From cae4d708e5a8066ce26b226126a3241f6278752b Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Fri, 24 Aug 2012 15:23:50 +0200 Subject: [PATCH] SPI: added setBitOrder support; added end(pin) method. --- .../sam/cores/arduino/wiring_constants.h | 6 ++- hardware/arduino/sam/libraries/SPI/SPI.cpp | 43 +++++++++++++------ hardware/arduino/sam/libraries/SPI/SPI.h | 18 +++++--- 3 files changed, 44 insertions(+), 23 deletions(-) diff --git a/hardware/arduino/sam/cores/arduino/wiring_constants.h b/hardware/arduino/sam/cores/arduino/wiring_constants.h index 868d46dbd..346b56454 100644 --- a/hardware/arduino/sam/cores/arduino/wiring_constants.h +++ b/hardware/arduino/sam/cores/arduino/wiring_constants.h @@ -42,8 +42,10 @@ extern "C"{ #define SERIAL 0x0 #define DISPLAY 0x1 -#define LSBFIRST 0 -#define MSBFIRST 1 +enum BitOrder { + LSBFIRST = 0, + MSBFIRST = 1 +}; #define CHANGE 1 #define FALLING 2 diff --git a/hardware/arduino/sam/libraries/SPI/SPI.cpp b/hardware/arduino/sam/libraries/SPI/SPI.cpp index a19ae1658..118dc4001 100644 --- a/hardware/arduino/sam/libraries/SPI/SPI.cpp +++ b/hardware/arduino/sam/libraries/SPI/SPI.cpp @@ -25,6 +25,7 @@ void SPIClass::begin() { // Default speed set to 4Mhz setClockDivider(BOARD_SPI_DEFAULT_SS, 21); setDataMode(BOARD_SPI_DEFAULT_SS, SPI_MODE0); + setBitOrder(BOARD_SPI_DEFAULT_SS, MSBFIRST); } void SPIClass::begin(uint8_t _pin) { @@ -34,39 +35,50 @@ void SPIClass::begin(uint8_t _pin) { g_APinDescription[spiPin].ulPinType, g_APinDescription[spiPin].ulPin, g_APinDescription[spiPin].ulPinConfiguration); - // Default speed set to 4Mhz - setClockDivider(_pin, 21); + + // Default speed set to 500Khz + setClockDivider(_pin, 168); setDataMode(_pin, SPI_MODE0); + setBitOrder(_pin, MSBFIRST); +} + +void SPIClass::end(uint8_t _pin) { + uint32_t spiPin = BOARD_PIN_TO_SPI_PIN(_pin); + // Setting the pin as INPUT will disconnect it from SPI peripheral + pinMode(spiPin, INPUT); } void SPIClass::end() { SPI_Disable(spi); } -//void SPIClass::setBitOrder(uint8_t _bitOrder, uint8_t _channel) { -// // Not supported -//} +void SPIClass::setBitOrder(uint8_t _pin, BitOrder _bitOrder) { + uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL(_pin); + bitOrder[ch] = _bitOrder; +} void SPIClass::setDataMode(uint8_t _pin, uint8_t _mode) { - uint32_t _channel = BOARD_PIN_TO_SPI_CHANNEL(_pin); - mode[_channel] = _mode | SPI_CSR_CSAAT; + uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL(_pin); + 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, _channel, mode[_channel] | SPI_CSR_SCBR(divider[_channel]) | SPI_CSR_DLYBCT(10) | (32<<16)); + SPI_ConfigureNPCS(spi, ch, mode[ch] | SPI_CSR_SCBR(divider[ch]) | SPI_CSR_DLYBCT(1)); } void SPIClass::setClockDivider(uint8_t _pin, uint8_t _divider) { - uint32_t _channel = BOARD_PIN_TO_SPI_CHANNEL(_pin); - divider[_channel] = _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, _channel, mode[_channel] | SPI_CSR_SCBR(divider[_channel]) | SPI_CSR_DLYBCT(1)); - SPI_ConfigureNPCS(spi, _channel, mode[_channel] | SPI_CSR_SCBR(divider[_channel]) | SPI_CSR_DLYBCT(10) | (32<<16)); + SPI_ConfigureNPCS(spi, ch, mode[ch] | SPI_CSR_SCBR(divider[ch]) | SPI_CSR_DLYBCT(1)); } byte SPIClass::transfer(byte _pin, uint8_t _data, SPITransferMode _mode) { - uint32_t _channel = BOARD_PIN_TO_SPI_CHANNEL(_pin); - uint32_t d = _data | SPI_PCS(_channel); + uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL(_pin); + // Reverse bit order + if (bitOrder[ch] == LSBFIRST) + _data = __REV(__RBIT(_data)); + uint32_t d = _data | SPI_PCS(ch); if (_mode == SPI_LAST) d |= SPI_TDR_LASTXFER; @@ -79,6 +91,9 @@ byte SPIClass::transfer(byte _pin, uint8_t _data, SPITransferMode _mode) { while ((spi->SPI_SR & SPI_SR_RDRF) == 0) ; d = spi->SPI_RDR; + // Reverse bit order + if (bitOrder[ch] == LSBFIRST) + d = __REV(__RBIT(d)); return d & 0xFF; } diff --git a/hardware/arduino/sam/libraries/SPI/SPI.h b/hardware/arduino/sam/libraries/SPI/SPI.h index 093d12de5..c11251df0 100644 --- a/hardware/arduino/sam/libraries/SPI/SPI.h +++ b/hardware/arduino/sam/libraries/SPI/SPI.h @@ -36,23 +36,27 @@ class SPIClass { void attachInterrupt(void); void detachInterrupt(void); - void begin(uint8_t _channel); void begin(void); void end(void); - // These methods sets a parameter on a single pin - //void setBitOrder(uint8_t _channel, uint8_t); - void setDataMode(uint8_t _channel, uint8_t); - void setClockDivider(uint8_t _channel, uint8_t); + // Attach/Detach pin to/from SPI controller + void begin(uint8_t _pin); + void end(uint8_t _pin); - // These methods sets the same parameters but on default pin PIN_SPI_SS_DEFAULT - //void setBitOrder(uint8_t _order) { setBitOrder(PIN_SPI_SS_DEFAULT, _order); }; + // These methods sets a parameter on a single pin + void setBitOrder(uint8_t _pin, BitOrder); + void setDataMode(uint8_t _pin, uint8_t); + 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); }; private: Spi *spi; uint32_t id; + BitOrder bitOrder[SPI_CHANNELS_NUM]; uint32_t divider[SPI_CHANNELS_NUM]; uint32_t mode[SPI_CHANNELS_NUM]; void (*initCb)(void);