Skip to content

Commit 8cb61b4

Browse files
authored
True 16 bit transfer, and new loop friendly 16 bit transfer
This replaces the transfer16() with a true 16 bit transfer, adds a new loop friendly 16 bit transfer, and rename the old transfer16() as two bytes to transfer16_asbytes()
1 parent 731b943 commit 8cb61b4

File tree

2 files changed

+102
-0
lines changed

2 files changed

+102
-0
lines changed

libraries/SPI/SPI.cpp

+98
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@
33
* Copyright (c) 2014 by Paul Stoffregen <[email protected]> (Transaction API)
44
* Copyright (c) 2014 by Matthijs Kooijman <[email protected]> (SPISettings AVR)
55
* Copyright (c) 2014 by Andrew J. Kroll <[email protected]> (atomicity fixes)
6+
* Copyright (c) 2024 by Mitchell C. Nelson, PhD <[email protected]>
67
* SPI Master library for arduino.
78
*
89
* This file is free software; you can redistribute it and/or modify
910
* it under the terms of either the GNU General Public License version 2
1011
* or the GNU Lesser General Public License version 2.1, both as
1112
* published by the Free Software Foundation.
13+
*
14+
*
1215
*/
1316

1417
/**************************************************************************************
@@ -203,7 +206,102 @@ uint8_t ArduinoSPI::transfer(uint8_t data)
203206
return rxbuf;
204207
}
205208

209+
/* This provides true 16 bit transfers
210+
*/
206211
uint16_t ArduinoSPI::transfer16(uint16_t data)
212+
{
213+
uint16_t rxbuf;
214+
215+
if (_is_sci) {
216+
_spi_cb_event[_cb_event_idx] = SPI_EVENT_TRANSFER_ABORTED;
217+
218+
_write_then_read(&_spi_sci_ctrl, &data, &rxbuf, 1, SPI_BIT_WIDTH_16_BITS);
219+
220+
for (auto const start = millis();
221+
(SPI_EVENT_TRANSFER_COMPLETE != _spi_cb_event[_cb_event_idx]) && (millis() - start < 1000); )
222+
{
223+
__NOP();
224+
}
225+
if (SPI_EVENT_TRANSFER_ABORTED == _spi_cb_event[_cb_event_idx])
226+
{
227+
end();
228+
return 0;
229+
}
230+
}
231+
else
232+
{
233+
_spi_ctrl.p_regs->SPCR_b.SPE = 0; /* disable SPI unit */
234+
_spi_ctrl.p_regs->SPDCR = R_SPI0_SPDCR_SPLW_Msk; /* SPI word access */
235+
_spi_ctrl.p_regs->SPCMD_b[0].SPB = 0x0F; /* spi bit width = 16 */
236+
_spi_ctrl.p_regs->SPCR_b.SPE = 1; /* enable SPI unit */
237+
238+
while (!_spi_ctrl.p_regs->SPSR_b.SPTEF){}
239+
240+
_spi_ctrl.p_regs->SPDR = data;
241+
242+
while (!_spi_ctrl.p_regs->SPSR_b.SPRF){}
243+
244+
rxbuf = _spi_ctrl.p_regs->SPDR;
245+
246+
247+
_spi_ctrl.p_regs->SPCR_b.SPE = 0; /* disable SPI unit */
248+
_spi_ctrl.p_regs->SPDCR = R_SPI0_SPDCR_SPBYT_Msk; /* SPI byte access */
249+
_spi_ctrl.p_regs->SPCMD_b[0].SPB = 7; /* spi bit width = 8 */
250+
_spi_ctrl.p_regs->SPCR_b.SPE = 1; /* enable SPI unit */
251+
}
252+
253+
return rxbuf;
254+
}
255+
256+
/* Use these three functions when you need to loop over a device
257+
such as an ADC or DAC where you need to pulse a pin between
258+
each access. Call transfer16_setup() before the loop, then
259+
call tansfer16_transfer() inside the loop, and then when you
260+
are done you may choose to call transfer16_cleanup() to restore
261+
the default 8 bit setup.
262+
*/
263+
264+
uint16_t ArduinoSPI::transfer16_setup()
265+
{
266+
if (!_is_sci) {
267+
_spi_ctrl.p_regs->SPCR_b.SPE = 0; /* disable SPI unit */
268+
_spi_ctrl.p_regs->SPDCR = R_SPI0_SPDCR_SPLW_Msk; /* SPI word access */
269+
_spi_ctrl.p_regs->SPCMD_b[0].SPB = 0x0F; /* spi bit width = 16 */
270+
_spi_ctrl.p_regs->SPCR_b.SPE = 1; /* enable SPI unit */
271+
}
272+
}
273+
274+
uint16_t ArduinoSPI::transfer16_transfer(uint16_t data)
275+
{
276+
uint16_t rxbuf;
277+
if (_is_sci) {
278+
return transfer16(data);
279+
}
280+
else {
281+
while (!_spi_ctrl.p_regs->SPSR_b.SPTEF){}
282+
283+
_spi_ctrl.p_regs->SPDR = data;
284+
285+
while (!_spi_ctrl.p_regs->SPSR_b.SPRF){}
286+
287+
rxbuf = _spi_ctrl.p_regs->SPDR;
288+
}
289+
}
290+
291+
uint16_t ArduinoSPI::transfer16_cleanup()
292+
{
293+
_spi_ctrl.p_regs->SPCR_b.SPE = 0; /* disable SPI unit */
294+
_spi_ctrl.p_regs->SPDCR = R_SPI0_SPDCR_SPBYT_Msk; /* SPI byte access */
295+
_spi_ctrl.p_regs->SPCMD_b[0].SPB = 7; /* spi bit width = 8 */
296+
_spi_ctrl.p_regs->SPCR_b.SPE = 1; /* enable SPI unit */
297+
}
298+
299+
300+
/* This is the original 16 bit transfer as two bytes, with an
301+
extra 1.4 usecs between the two bytes.
302+
*/
303+
304+
uint16_t ArduinoSPI::transfer16_asbytes(uint16_t data)
207305
{
208306
union { uint16_t val; struct { uint8_t lsb; uint8_t msb; }; } t;
209307
t.val = data;

libraries/SPI/SPI.h

+4
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ class ArduinoSPI : public SPIClass
6969

7070
virtual uint8_t transfer(uint8_t data);
7171
virtual uint16_t transfer16(uint16_t data);
72+
virtual uint16_t transfer16_setup();
73+
virtual uint16_t transfer16_transfer(uint16_t data);
74+
virtual uint16_t transfer16_cleanup();
75+
virtual uint16_t transfer16_asbytes(uint16_t data);
7276
virtual void transfer(void *buf, size_t count);
7377

7478
// Transaction Functions

0 commit comments

Comments
 (0)