SPI: added setBitOrder support; added end(pin) method.

This commit is contained in:
Cristian Maglie 2012-08-24 15:23:50 +02:00
parent bdf3f19c34
commit cae4d708e5
3 changed files with 44 additions and 23 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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);