From 6a5b82f062f1c28472cfe2015416246808f77264 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Wed, 10 Sep 2014 22:03:00 +0200 Subject: [PATCH] [sam] Implementation of SPI multibyte transfer --- hardware/arduino/sam/libraries/SPI/SPI.cpp | 52 ++++++++++++++++++++++ hardware/arduino/sam/libraries/SPI/SPI.h | 6 ++- 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/hardware/arduino/sam/libraries/SPI/SPI.cpp b/hardware/arduino/sam/libraries/SPI/SPI.cpp index 8aa01c5d9..377918cec 100644 --- a/hardware/arduino/sam/libraries/SPI/SPI.cpp +++ b/hardware/arduino/sam/libraries/SPI/SPI.cpp @@ -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() } diff --git a/hardware/arduino/sam/libraries/SPI/SPI.h b/hardware/arduino/sam/libraries/SPI/SPI.h index 60a9f61ec..c68784a2e 100644 --- a/hardware/arduino/sam/libraries/SPI/SPI.h +++ b/hardware/arduino/sam/libraries/SPI/SPI.h @@ -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);