From 24383d36801221224cf353caf7036de95a5f4ec2 Mon Sep 17 00:00:00 2001 From: MadVikingGod Date: Fri, 9 May 2014 07:56:36 -0700 Subject: [PATCH 1/2] Added functions to the Due SPI library to enable 16bit SPI transfers. The LSBFIRST setting only works for 8 bits. TODO: twiddle 9-16 bit words to be reversed for LSB transfers. This is made more difficult because of the right-justified contents of the transfer data format. -MVG --- hardware/arduino/sam/libraries/SPI/SPI.cpp | 20 ++++++++++++++++---- hardware/arduino/sam/libraries/SPI/SPI.h | 19 +++++++++++++++++-- 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/hardware/arduino/sam/libraries/SPI/SPI.cpp b/hardware/arduino/sam/libraries/SPI/SPI.cpp index 9517e22263a..7ad241145a9 100644 --- a/hardware/arduino/sam/libraries/SPI/SPI.cpp +++ b/hardware/arduino/sam/libraries/SPI/SPI.cpp @@ -25,6 +25,7 @@ void SPIClass::begin() { setClockDivider(BOARD_SPI_DEFAULT_SS, 21); setDataMode(BOARD_SPI_DEFAULT_SS, SPI_MODE0); setBitOrder(BOARD_SPI_DEFAULT_SS, MSBFIRST); + setTransferWidth(BOARD_SPI_DEFAULT_SS, SPI_WDITH_8); } void SPIClass::begin(uint8_t _pin) { @@ -41,6 +42,7 @@ void SPIClass::begin(uint8_t _pin) { setClockDivider(_pin, 21); setDataMode(_pin, SPI_MODE0); setBitOrder(_pin, MSBFIRST); + setTransferWidth(_pin, SPI_WIDTH_8); } void SPIClass::init() { @@ -73,18 +75,28 @@ void SPIClass::setDataMode(uint8_t _pin, uint8_t _mode) { mode[ch] = _mode | SPI_CSR_CSAAT; // SPI_CSR_DLYBCT(1) keeps CS enabled for 32 MCLK after a completed // transfer. Some device needs that for working properly. - SPI_ConfigureNPCS(spi, ch, mode[ch] | SPI_CSR_SCBR(divider[ch]) | SPI_CSR_DLYBCT(1)); + SPI_ConfigureNPCS(spi, ch, mode[ch] | width[ch] | SPI_CSR_SCBR(divider[ch]) | SPI_CSR_DLYBCT(1)); } +void SPIClass::setTransferWidth(uint8_t _pin, uint8_t _width) { + uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL(_pin); + width[ch] = _width<<8; + // SPI_CSR_DLYBCT(1) keeps CS enabled for 32 MCLK after a completed + // transfer. Some device needs that for working properly. + SPI_ConfigureNPCS(spi, ch, mode[ch] | width[ch] | SPI_CSR_SCBR(divider[ch]) | SPI_CSR_DLYBCT(1)); +} + + void SPIClass::setClockDivider(uint8_t _pin, uint8_t _divider) { uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL(_pin); divider[ch] = _divider; // SPI_CSR_DLYBCT(1) keeps CS enabled for 32 MCLK after a completed // transfer. Some device needs that for working properly. - SPI_ConfigureNPCS(spi, ch, mode[ch] | SPI_CSR_SCBR(divider[ch]) | SPI_CSR_DLYBCT(1)); + SPI_ConfigureNPCS(spi, ch, mode[ch] | width[ch] | SPI_CSR_SCBR(divider[ch]) | SPI_CSR_DLYBCT(1)); } -byte SPIClass::transfer(byte _pin, uint8_t _data, SPITransferMode _mode) { + +byte SPIClass::transfer(byte _pin, uint16_t _data, SPITransferMode _mode) { uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL(_pin); // Reverse bit order if (bitOrder[ch] == LSBFIRST) @@ -105,7 +117,7 @@ byte SPIClass::transfer(byte _pin, uint8_t _data, SPITransferMode _mode) { // Reverse bit order if (bitOrder[ch] == LSBFIRST) d = __REV(__RBIT(d)); - return d & 0xFF; + return d & (1<<(8+width[ch])-1); } void SPIClass::attachInterrupt(void) { diff --git a/hardware/arduino/sam/libraries/SPI/SPI.h b/hardware/arduino/sam/libraries/SPI/SPI.h index 735bd4bf9a5..e4d81b9d789 100644 --- a/hardware/arduino/sam/libraries/SPI/SPI.h +++ b/hardware/arduino/sam/libraries/SPI/SPI.h @@ -23,13 +23,25 @@ enum SPITransferMode { SPI_CONTINUE, SPI_LAST }; +enum SPITransferWidth { + SPI_WIDTH_8, + SPI_WIDTH_9, + SPI_WIDTH_10, + SPI_WIDTH_11, + SPI_WIDTH_12, + SPI_WIDTH_13, + SPI_WIDTH_14, + SPI_WIDTH_15, + SPI_WIDTH_16 +}; class SPIClass { public: SPIClass(Spi *_spi, uint32_t _id, void(*_initCb)(void)); - 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); + byte transfer(uint16_t _data, SPITransferMode _mode = SPI_LAST) { return transfer(BOARD_SPI_DEFAULT_SS, _data, _mode); } + byte transfer(byte _channel, uint16_t _data, SPITransferMode _mode = SPI_LAST); + // SPI Configuration methods @@ -46,12 +58,14 @@ class SPIClass { // These methods sets a parameter on a single pin void setBitOrder(uint8_t _pin, BitOrder); void setDataMode(uint8_t _pin, uint8_t); + void setTransferWidth(uint8_t _pin, uint8_t _width); void setClockDivider(uint8_t _pin, uint8_t); // These methods sets the same parameters but on default pin BOARD_SPI_DEFAULT_SS void setBitOrder(BitOrder _order) { setBitOrder(BOARD_SPI_DEFAULT_SS, _order); }; void setDataMode(uint8_t _mode) { setDataMode(BOARD_SPI_DEFAULT_SS, _mode); }; void setClockDivider(uint8_t _div) { setClockDivider(BOARD_SPI_DEFAULT_SS, _div); }; + void setTransferWidth(uint8_t _width) { setTransferWidth(BOARD_SPI_DEFAULT_SS, _width); }; private: void init(); @@ -61,6 +75,7 @@ class SPIClass { BitOrder bitOrder[SPI_CHANNELS_NUM]; uint32_t divider[SPI_CHANNELS_NUM]; uint32_t mode[SPI_CHANNELS_NUM]; + uint32_t width[SPI_CHANNELS_NUM]; void (*initCb)(void); bool initialized; }; From 02e9f18007e41e1a30104a94e7de6856c1f45e15 Mon Sep 17 00:00:00 2001 From: MadVikingGod Date: Fri, 9 May 2014 08:04:30 -0700 Subject: [PATCH 2/2] Corrected a spelling mistake. --- hardware/arduino/sam/libraries/SPI/SPI.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hardware/arduino/sam/libraries/SPI/SPI.cpp b/hardware/arduino/sam/libraries/SPI/SPI.cpp index 7ad241145a9..4307d2ca2a7 100644 --- a/hardware/arduino/sam/libraries/SPI/SPI.cpp +++ b/hardware/arduino/sam/libraries/SPI/SPI.cpp @@ -25,7 +25,7 @@ void SPIClass::begin() { setClockDivider(BOARD_SPI_DEFAULT_SS, 21); setDataMode(BOARD_SPI_DEFAULT_SS, SPI_MODE0); setBitOrder(BOARD_SPI_DEFAULT_SS, MSBFIRST); - setTransferWidth(BOARD_SPI_DEFAULT_SS, SPI_WDITH_8); + setTransferWidth(BOARD_SPI_DEFAULT_SS, SPI_WIDTH_8); } void SPIClass::begin(uint8_t _pin) {