diff --git a/libraries/SPI/src/SPI.cpp b/libraries/SPI/src/SPI.cpp index 1670372..1050ef6 100644 --- a/libraries/SPI/src/SPI.cpp +++ b/libraries/SPI/src/SPI.cpp @@ -1,22 +1,16 @@ #include "SPI.h" -#include "mik32_hal_spi.h" -SPI_HandleTypeDef hspi; +SPIClass SPI(1); +#if SPI_COMMON_QTY > 1 +SPIClass SPI1(0); +#endif -bool newConfig = false; -bool isInited = false; -uint32_t currentSpeed = 0; -int8_t currentDataOrder = MSBFIRST; -int8_t currentDataMode = -1; static uint8_t reverse_bits(uint8_t byte); -// ------------------------------------------------------------------ // - -void SPISettings::spiUpdateSettings(uint32_t speedMaximum, uint8_t dataOrder, uint8_t dataMode) +void SPIClass::updateSettings(uint32_t speedMaximum, uint8_t dataOrder, uint8_t dataMode) { // update config only if something has changed - if ((currentSpeed != speedMaximum) || (currentDataOrder != dataOrder) || - (currentDataMode != dataMode)) + if ((_speed != speedMaximum) || (_dataOrder != dataOrder) || (_dataMode != dataMode)) { // Find the fastest clock that is less than or equal to the // given clock rate. If nothing is slow enough - use the slowest. @@ -33,63 +27,64 @@ void SPISettings::spiUpdateSettings(uint32_t speedMaximum, uint8_t dataOrder, ui // if break didn't call in cycle, it will be the greatest divRegVal (and divider) // update params in struct - hspi.Init.CLKPhase = dataMode & 0b00000001; - hspi.Init.CLKPolarity = (dataMode & 0b00000010)>>1; - hspi.Init.BaudRateDiv = divRegVal; + _hspi.Init.CLKPhase = dataMode & 0b00000001; + _hspi.Init.CLKPolarity = (dataMode & 0b00000010)>>1; + _hspi.Init.BaudRateDiv = divRegVal; - currentSpeed = speedMaximum; - currentDataOrder = dataOrder; - currentDataMode = dataMode; - newConfig = true; + _speed = speedMaximum; + _dataOrder = dataOrder; + _dataMode = dataMode; + _newConfig = true; } } -// ------------------------------------------------------------------ // - -SPIClass SPI; -bool SPIClass::spiInUse = false; -uint8_t SPIClass::interruptMode = 0; -uint8_t SPIClass::interruptMask = 0; - void SPIClass::begin() { - spi_onBegin(); + spi_onBegin(_spiNum); // set constant parameters in spi struct - hspi.Instance = SPI_1; - hspi.Init.SPI_Mode = HAL_SPI_MODE_MASTER; // only master mode used - hspi.Init.ThresholdTX = 4; - hspi.Init.Decoder = SPI_DECODER_NONE; - hspi.Init.ManualCS = SPI_MANUALCS_ON; - hspi.Init.ChipSelect = SPI_CS_NONE; + if (_spiNum == 0) + _hspi.Instance = SPI_0; + else + _hspi.Instance = SPI_1; + _hspi.Init.SPI_Mode = HAL_SPI_MODE_MASTER; // only master mode used + _hspi.Init.ThresholdTX = 4; + _hspi.Init.Decoder = SPI_DECODER_NONE; + _hspi.Init.ManualCS = SPI_MANUALCS_ON; + _hspi.Init.ChipSelect = SPI_CS_NONE; // adjustable parameters default values as in SPISettings() - hspi.Init.BaudRateDiv = SPI_CLOCK_DIV8; - hspi.Init.CLKPhase = SPI_MODE0 & 0b00000001; - hspi.Init.CLKPolarity = (SPI_MODE0 & 0b00000010)>>1; + _hspi.Init.BaudRateDiv = SPI_CLOCK_DIV8; + _hspi.Init.CLKPhase = SPI_MODE0 & 0b00000001; + _hspi.Init.CLKPolarity = (SPI_MODE0 & 0b00000010)>>1; - spiInUse = true; + _spiInUse = true; } void SPIClass::end() { - if (spiInUse && isInited) + if (_spiInUse && _isInited) { // turn off spi - HAL_SPI_Disable(&hspi); + HAL_SPI_Disable(&_hspi); // deinit spi gpio pins - if (hspi.Instance == SPI_1) // only spi1 is using in currunt version + if (_hspi.Instance == SPI_0) + { + HAL_GPIO_PinConfig(GPIO_0, (HAL_PinsTypeDef)(GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2), + HAL_GPIO_MODE_GPIO_INPUT, HAL_GPIO_PULL_NONE, HAL_GPIO_DS_2MA); + } + else if (_hspi.Instance == SPI_1) { HAL_GPIO_PinConfig(GPIO_1, (HAL_PinsTypeDef)(GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2), HAL_GPIO_MODE_GPIO_INPUT, HAL_GPIO_PULL_NONE, HAL_GPIO_DS_2MA); } - spi_onEnd(); + spi_onEnd(_spiNum); - spiInUse = false; - isInited = false; - interruptMode = 0; - interruptMask = 0; + _spiInUse = false; + _isInited = false; + _interruptMode = 0; + _interruptMask = 0; } } @@ -98,9 +93,9 @@ void SPIClass::usingInterrupt(uint8_t interruptNumber) if(interruptNumber < EXTERNAL_INTERRUPTS_QTY) { noInterrupts(); // prevent transactionBegin - interruptMask |= (1 << interruptNumber); // add new interrupt to mask - if (!interruptMode) - interruptMode = 1; + _interruptMask |= (1 << interruptNumber); // add new interrupt to mask + if (!_interruptMode) + _interruptMode = 1; interrupts(); } } @@ -110,34 +105,40 @@ void SPIClass::notUsingInterrupt(uint8_t interruptNumber) if(interruptNumber < EXTERNAL_INTERRUPTS_QTY) { noInterrupts(); // prevent transactionBegin - interruptMask &= ~(1< 0)) + if (_spiInUse && (_interruptMode > 0)) { for (uint8_t i = 0; i < EXTERNAL_INTERRUPTS_QTY; i++) { - if (interruptMask & (1 << i)) + if (_interruptMask & (1 << i)) // disable every interrupt by it's number disableInterrupt(i); } } - // initialize spi bus or update config - if(spiInUse && ((!isInited) || newConfig)) + // initialize spi bus or update config if needed + if(_spiInUse && ((!_isInited) || _newConfig)) { // initialize spi with given settings - if (HAL_SPI_Init(&hspi) != HAL_OK) + if (HAL_SPI_Init(&_hspi) != HAL_OK) ErrorMsgHandler("SPI.beginTransaction(): initialization error"); else - isInited = true; + { + _isInited = true; + _newConfig = false; + } } } @@ -145,19 +146,19 @@ uint8_t SPIClass::transfer(uint8_t data) { uint8_t rxByte = 0; - if (isInited) + if (_isInited) { // reverse bits if LSB mode needed - if (currentDataOrder == LSBFIRST) + if (_dataOrder == LSBFIRST) data = reverse_bits(data); // send and recieve data - HAL_StatusTypeDef SPI_Status = HAL_SPI_Exchange(&hspi, &data, &rxByte, 1, SPI_TIMEOUT_DEFAULT*2); + HAL_StatusTypeDef SPI_Status = HAL_SPI_Exchange(&_hspi, &data, &rxByte, 1, SPI_TIMEOUT_DEFAULT*2); if (SPI_Status != HAL_OK) - HAL_SPI_ClearError(&hspi); + HAL_SPI_ClearError(&_hspi); // reverse bits again if LSB mode needed - if (currentDataOrder == LSBFIRST) + if (_dataOrder == LSBFIRST) rxByte = reverse_bits(rxByte); } return rxByte; @@ -167,10 +168,10 @@ uint16_t SPIClass::transfer16(uint16_t data) { uint8_t buf[2]; uint16_t rxVal = 0; - if (isInited) + if (_isInited) { // prepare data for send - if (currentDataOrder == LSBFIRST) + if (_dataOrder == LSBFIRST) { // least significant byte is forward and reverse bits inside each byte buf[0] = reverse_bits(data&0xFF); @@ -184,12 +185,12 @@ uint16_t SPIClass::transfer16(uint16_t data) } // send and recieve data - HAL_StatusTypeDef SPI_Status = HAL_SPI_Exchange(&hspi, buf, buf, 2, SPI_TIMEOUT_DEFAULT*2); + HAL_StatusTypeDef SPI_Status = HAL_SPI_Exchange(&_hspi, buf, buf, 2, SPI_TIMEOUT_DEFAULT*2); if (SPI_Status != HAL_OK) - HAL_SPI_ClearError(&hspi); + HAL_SPI_ClearError(&_hspi); // process the received data - if (currentDataOrder == LSBFIRST) + if (_dataOrder == LSBFIRST) // reverse bits for LSB mode rxVal = ( ((uint16_t)reverse_bits(buf[1]) ) << 8) | reverse_bits(buf[0]); else @@ -203,24 +204,24 @@ void SPIClass::transfer(void *buf, size_t count) if (count == 0) return; - if (isInited) + if (_isInited) { uint8_t *p = (uint8_t *)buf; // reverse bits in buffer if LSB mode needed - if (currentDataOrder == LSBFIRST) + if (_dataOrder == LSBFIRST) { for (uint32_t i = 0; i < count; i++) *(p+i) = reverse_bits(*(p+i)); } // send and recieve data using the same buffer - HAL_StatusTypeDef SPI_Status = HAL_SPI_Exchange(&hspi, (uint8_t*)buf, (uint8_t*)buf, count, SPI_TIMEOUT_DEFAULT*2); + HAL_StatusTypeDef SPI_Status = HAL_SPI_Exchange(&_hspi, (uint8_t*)buf, (uint8_t*)buf, count, SPI_TIMEOUT_DEFAULT*2); if (SPI_Status != HAL_OK) - HAL_SPI_ClearError(&hspi); + HAL_SPI_ClearError(&_hspi); // reverse bits if LSB mode needed - if (currentDataOrder == LSBFIRST) + if (_dataOrder == LSBFIRST) { p = (uint8_t *)buf; // return to buf beginning for (uint32_t i = 0; i < count; i++) @@ -232,11 +233,11 @@ void SPIClass::transfer(void *buf, size_t count) void SPIClass::endTransaction(void) { // enable interrupts in use - if (spiInUse && (interruptMode > 0)) + if (_spiInUse && (_interruptMode > 0)) { for (uint8_t i = 0; i < EXTERNAL_INTERRUPTS_QTY; i++) { - if (interruptMask & (1 << i)) + if (_interruptMask & (1 << i)) // enable every interrupt in use by it's number enableInterrupt(i); } @@ -246,20 +247,20 @@ void SPIClass::endTransaction(void) // ------------------------------------ // void SPIClass::setBitOrder(uint8_t bitOrder) { - if (spiInUse) - currentDataOrder = bitOrder; + if (_spiInUse) + _dataOrder = bitOrder; else ErrorMsgHandler("SPI.setBitOrder():SPI.begin() need to be called first"); } void SPIClass::setDataMode(uint8_t dataMode) { - if (spiInUse) + if (_spiInUse) { - hspi.Init.CLKPhase = (dataMode&0b00000001); - hspi.Init.CLKPolarity = (dataMode&0b00000010)>>1; - HAL_SPI_Set_Clock_Mode(&hspi); - currentDataMode = dataMode; + _hspi.Init.CLKPhase = (dataMode&0b00000001); + _hspi.Init.CLKPolarity = (dataMode&0b00000010)>>1; + HAL_SPI_Set_Clock_Mode(&_hspi); + _dataMode = dataMode; } else ErrorMsgHandler("SPI.setDataMode():SPI.begin() need to be called first"); @@ -267,7 +268,7 @@ void SPIClass::setDataMode(uint8_t dataMode) void SPIClass::setClockDivider(uint8_t clockDiv) { - if (spiInUse) + if (_spiInUse) { // if divider is valid if ((clockDiv == SPI_CLOCK_DIV2) || (clockDiv == SPI_CLOCK_DIV4) || @@ -275,9 +276,9 @@ void SPIClass::setClockDivider(uint8_t clockDiv) (clockDiv == SPI_CLOCK_DIV32) || (clockDiv == SPI_CLOCK_DIV64) || (clockDiv == SPI_CLOCK_DIV128) || (clockDiv == SPI_CLOCK_DIV256)) { - hspi.Init.BaudRateDiv = clockDiv; - currentSpeed = F_CPU >> (clockDiv+1); - HAL_SPI_Set_Clock_Divider(&hspi); + _hspi.Init.BaudRateDiv = clockDiv; + _speed = F_CPU >> (clockDiv+1); + HAL_SPI_Set_Clock_Divider(&_hspi); } else ErrorMsgHandler("SPI.setClockDivider(): Invalid clock devider"); diff --git a/libraries/SPI/src/SPI.h b/libraries/SPI/src/SPI.h index b54e6b2..cee0433 100644 --- a/libraries/SPI/src/SPI.h +++ b/libraries/SPI/src/SPI.h @@ -15,6 +15,7 @@ #define _SPI_H_INCLUDED #include +#include "mik32_hal_spi.h" // SPI_HAS_TRANSACTION means SPI has beginTransaction(), endTransaction(), // usingInterrupt(), and SPISetting(clock, bitOrder, dataMode) @@ -32,7 +33,6 @@ #define SPI_DEFAULT_SPEED 4000000 - // dividers for setClockDivider() #define SPI_CLOCK_DIV2 0x00 // 16 MHz #define SPI_CLOCK_DIV4 0x01 // 8 MHz @@ -49,45 +49,49 @@ #define SPI_MODE2 0b10 #define SPI_MODE3 0b11 - -class SPISettings -{ +class SPISettings { public: - SPISettings(uint32_t speedMaximum, uint8_t dataOrder, uint8_t dataMode) - { - spiUpdateSettings(speedMaximum, dataOrder, dataMode); - } - - SPISettings() - { - spiUpdateSettings(SPI_DEFAULT_SPEED, MSBFIRST, SPI_MODE0); - } - -private: - void spiUpdateSettings(uint32_t speedMaximum, uint8_t dataOrder, uint8_t dataMode); - - friend class SPIClass; + uint32_t speedMaximum; + uint8_t newDataOrder; + uint8_t newDataMode; + // save values from arguments + SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t mode) + : speedMaximum(clock), newDataOrder(bitOrder), newDataMode(mode) {} }; class SPIClass { private: - static bool spiInUse; - static uint8_t interruptMode; // 0=none, 1=mask - static uint8_t interruptMask; // which interrupts to mask + uint8_t _spiNum; + SPI_HandleTypeDef _hspi = {0}; + uint32_t _speed = 0; + uint8_t _dataOrder = MSBFIRST; + uint8_t _dataMode = -1; + bool _isInited = false; + bool _newConfig = false; + bool _spiInUse = false; + uint8_t _interruptMode = 0; // 0=none, 1=mask + uint8_t _interruptMask = 0; // which interrupts to mask + + void updateSettings(uint32_t speedMaximum, uint8_t dataOrder, uint8_t dataMode); public: + inline SPIClass(uint8_t num) + { + // Set the SPI to be used + _spiNum = (num < SPI_COMMON_QTY) ? num : 1; // SPI1 by default + } // Initialize the SPI library - static void begin(); + void begin(); // If SPI is used from within an interrupt, this function registers // that interrupt with the SPI library, so beginTransaction() can // prevent conflicts. The input interruptNumber is the number used // with attachInterrupt. - static void usingInterrupt(uint8_t interruptNumber); + void usingInterrupt(uint8_t interruptNumber); // And this does the opposite. - static void notUsingInterrupt(uint8_t interruptNumber); + void notUsingInterrupt(uint8_t interruptNumber); // Note: the usingInterrupt and notUsingInterrupt functions should // not to be called from ISR context or inside a transaction. // For details see: @@ -109,7 +113,7 @@ public: void endTransaction(void); // Disable the SPI bus - static void end(); + void end(); // This function is deprecated. New applications should use // beginTransaction() to configure SPI settings. @@ -124,5 +128,8 @@ public: }; extern SPIClass SPI; +#if SPI_COMMON_QTY > 1 +extern SPIClass SPI1; +#endif #endif