Skip to content

Commit 6a5b82f

Browse files
committed
[sam] Implementation of SPI multibyte transfer
1 parent 5f88564 commit 6a5b82f

File tree

2 files changed

+57
-1
lines changed

2 files changed

+57
-1
lines changed

hardware/arduino/sam/libraries/SPI/SPI.cpp

+52
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,58 @@ byte SPIClass::transfer(byte _pin, uint8_t _data, SPITransferMode _mode) {
196196
return d & 0xFF;
197197
}
198198

199+
void SPIClass::transfer(byte _pin, void *_buf, size_t _count, SPITransferMode _mode) {
200+
if (_count == 0)
201+
return;
202+
203+
uint8_t *buffer = (uint8_t *)_buf;
204+
if (_count == 1) {
205+
*buffer = transfer(_pin, *buffer, _mode);
206+
return;
207+
}
208+
209+
uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL(_pin);
210+
bool reverse = (bitOrder[ch] == LSBFIRST);
211+
212+
// Send the first byte
213+
uint32_t d = *buffer;
214+
if (reverse)
215+
d = __REV(__RBIT(d));
216+
while ((spi->SPI_SR & SPI_SR_TDRE) == 0)
217+
;
218+
spi->SPI_TDR = d | SPI_PCS(ch);
219+
220+
while (_count > 1) {
221+
// Prepare next byte
222+
d = *(buffer+1);
223+
if (reverse)
224+
d = __REV(__RBIT(d));
225+
if (_count == 2 && _mode == SPI_LAST)
226+
d |= SPI_TDR_LASTXFER;
227+
228+
// Read transferred byte and send next one straight away
229+
while ((spi->SPI_SR & SPI_SR_RDRF) == 0)
230+
;
231+
uint8_t r = spi->SPI_RDR;
232+
spi->SPI_TDR = d | SPI_PCS(ch);
233+
234+
// Save read byte
235+
if (reverse)
236+
r = __REV(__RBIT(r));
237+
*buffer = r;
238+
buffer++;
239+
_count--;
240+
}
241+
242+
// Receive the last transferred byte
243+
while ((spi->SPI_SR & SPI_SR_RDRF) == 0)
244+
;
245+
uint8_t r = spi->SPI_RDR;
246+
if (reverse)
247+
r = __REV(__RBIT(r));
248+
*buffer = r;
249+
}
250+
199251
void SPIClass::attachInterrupt(void) {
200252
// Should be enableInterrupt()
201253
}

hardware/arduino/sam/libraries/SPI/SPI.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,12 @@ class SPIClass {
8080
public:
8181
SPIClass(Spi *_spi, uint32_t _id, void(*_initCb)(void));
8282

83+
// Transfer functions
84+
byte transfer(byte _pin, uint8_t _data, SPITransferMode _mode = SPI_LAST);
85+
void transfer(byte _pin, void *_buf, size_t _count, SPITransferMode _mode = SPI_LAST);
86+
// Transfer functions on default pin BOARD_SPI_DEFAULT_SS
8387
byte transfer(uint8_t _data, SPITransferMode _mode = SPI_LAST) { return transfer(BOARD_SPI_DEFAULT_SS, _data, _mode); }
84-
byte transfer(byte _channel, uint8_t _data, SPITransferMode _mode = SPI_LAST);
88+
void transfer(void *_buf, size_t _count, SPITransferMode _mode = SPI_LAST) { transfer(BOARD_SPI_DEFAULT_SS, _buf, _count, _mode); }
8589

8690
// Transaction Functions
8791
void usingInterrupt(uint8_t interruptNumber);

0 commit comments

Comments
 (0)