[sam] Implementation of SPI multibyte transfer

This commit is contained in:
Cristian Maglie 2014-09-10 22:03:00 +02:00
parent 5f88564b2b
commit 6a5b82f062
2 changed files with 57 additions and 1 deletions

View File

@ -196,6 +196,58 @@ byte SPIClass::transfer(byte _pin, uint8_t _data, SPITransferMode _mode) {
return d & 0xFF;
}
void SPIClass::transfer(byte _pin, void *_buf, size_t _count, SPITransferMode _mode) {
if (_count == 0)
return;
uint8_t *buffer = (uint8_t *)_buf;
if (_count == 1) {
*buffer = transfer(_pin, *buffer, _mode);
return;
}
uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL(_pin);
bool reverse = (bitOrder[ch] == LSBFIRST);
// Send the first byte
uint32_t d = *buffer;
if (reverse)
d = __REV(__RBIT(d));
while ((spi->SPI_SR & SPI_SR_TDRE) == 0)
;
spi->SPI_TDR = d | SPI_PCS(ch);
while (_count > 1) {
// Prepare next byte
d = *(buffer+1);
if (reverse)
d = __REV(__RBIT(d));
if (_count == 2 && _mode == SPI_LAST)
d |= SPI_TDR_LASTXFER;
// Read transferred byte and send next one straight away
while ((spi->SPI_SR & SPI_SR_RDRF) == 0)
;
uint8_t r = spi->SPI_RDR;
spi->SPI_TDR = d | SPI_PCS(ch);
// Save read byte
if (reverse)
r = __REV(__RBIT(r));
*buffer = r;
buffer++;
_count--;
}
// Receive the last transferred byte
while ((spi->SPI_SR & SPI_SR_RDRF) == 0)
;
uint8_t r = spi->SPI_RDR;
if (reverse)
r = __REV(__RBIT(r));
*buffer = r;
}
void SPIClass::attachInterrupt(void) {
// Should be enableInterrupt()
}

View File

@ -80,8 +80,12 @@ class SPIClass {
public:
SPIClass(Spi *_spi, uint32_t _id, void(*_initCb)(void));
// Transfer functions
byte transfer(byte _pin, uint8_t _data, SPITransferMode _mode = SPI_LAST);
void transfer(byte _pin, void *_buf, size_t _count, SPITransferMode _mode = SPI_LAST);
// Transfer functions on default pin BOARD_SPI_DEFAULT_SS
byte transfer(uint8_t _data, SPITransferMode _mode = SPI_LAST) { return transfer(BOARD_SPI_DEFAULT_SS, _data, _mode); }
byte transfer(byte _channel, uint8_t _data, SPITransferMode _mode = SPI_LAST);
void transfer(void *_buf, size_t _count, SPITransferMode _mode = SPI_LAST) { transfer(BOARD_SPI_DEFAULT_SS, _buf, _count, _mode); }
// Transaction Functions
void usingInterrupt(uint8_t interruptNumber);