diff --git a/libraries/SPI/README.md b/libraries/SPI/README.md index 5bf0889c59..59564fd7e5 100644 --- a/libraries/SPI/README.md +++ b/libraries/SPI/README.md @@ -7,10 +7,6 @@ User have 2 possibilities about the management of the CS pin: * the CS pin is managed directly by the user code before to transfer the data (like the Arduino SPI library) * the user uses a hardware CS pin linked to the SPI peripheral -### New SPISetting parameter - -* `noReceive`: value can be `SPI_TRANSMITRECEIVE` or `SPI_TRANSMITONLY`. It allows to skip receive data after transmitting. Default `SPI_TRANSMITRECEIVE`. - ### New API functions * `SPIClass::SPIClass(uint8_t mosi, uint8_t miso, uint8_t sclk, uint8_t ssel)`: alternative class constructor @@ -39,10 +35,15 @@ void setup() { } ``` +### Extended API + +* All `transfer()` API's have a new bool argument `skipReceive`. It allows to skip receive data after transmitting. Value can be `SPI_TRANSMITRECEIVE` or `SPI_TRANSMITONLY`. Default `SPI_TRANSMITRECEIVE`. + #### Change default `SPI` instance pins It is also possible to change the default pins used by the `SPI` instance using above API: -[[/img/Warning-icon.png|alt="Warning"]] **Have to be called before `begin()`.** +> [!WARNING] +> **Have to be called before `begin()`.** * `void setMISO(uint32_t miso)` * `void setMOSI(uint32_t mosi)` @@ -53,7 +54,8 @@ It is also possible to change the default pins used by the `SPI` instance using * `void setSCLK(PinName sclk)` * `void setSSEL(PinName ssel)` -**_Note 1_** Using `setSSEL()` allows to enable hardware CS pin management linked to the SPI peripheral. +> [!NOTE] +> Using `setSSEL()` allows to enable hardware CS pin management linked to the SPI peripheral. ##### Example: ```C++ diff --git a/libraries/SPI/src/SPI.cpp b/libraries/SPI/src/SPI.cpp index b3266d348a..f42f2e88d7 100644 --- a/libraries/SPI/src/SPI.cpp +++ b/libraries/SPI/src/SPI.cpp @@ -57,10 +57,10 @@ SPIClass::SPIClass(uint32_t mosi, uint32_t miso, uint32_t sclk, uint32_t ssel) void SPIClass::begin(void) { _spi.handle.State = HAL_SPI_STATE_RESET; - _spiSettings = DEFAULT_SPI_SETTINGS; - spi_init(&_spi, _spiSettings.getClockFreq(), - _spiSettings.getDataMode(), - _spiSettings.getBitOrder()); + _spiSettings = SPISettings(); + spi_init(&_spi, _spiSettings.clockFreq, + _spiSettings.dataMode, + _spiSettings.bitOrder); } /** @@ -72,9 +72,9 @@ void SPIClass::beginTransaction(SPISettings settings) { if (_spiSettings != settings) { _spiSettings = settings; - spi_init(&_spi, _spiSettings.getClockFreq(), - _spiSettings.getDataMode(), - _spiSettings.getBitOrder()); + spi_init(&_spi, _spiSettings.clockFreq, + _spiSettings.dataMode, + _spiSettings.bitOrder); } } @@ -89,7 +89,7 @@ void SPIClass::endTransaction(void) /** * @brief Deinitialize the SPI instance and stop it. */ -void SPIClass::end() +void SPIClass::end(void) { spi_deinit(&_spi); } @@ -97,15 +97,15 @@ void SPIClass::end() /** * @brief Deprecated function. * Configure the bit order: MSB first or LSB first. - * @param _bitOrder: MSBFIRST or LSBFIRST + * @param bitOrder: MSBFIRST or LSBFIRST */ void SPIClass::setBitOrder(BitOrder bitOrder) { - _spiSettings.setBitOrder(bitOrder); + _spiSettings.bitOrder = bitOrder; - spi_init(&_spi, _spiSettings.getClockFreq(), - _spiSettings.getDataMode(), - _spiSettings.getBitOrder()); + spi_init(&_spi, _spiSettings.clockFreq, + _spiSettings.dataMode, + _spiSettings.bitOrder); } /** @@ -119,7 +119,6 @@ void SPIClass::setBitOrder(BitOrder bitOrder) * SPI_MODE2 1 0 * SPI_MODE3 1 1 */ - void SPIClass::setDataMode(uint8_t mode) { setDataMode((SPIMode)mode); @@ -127,42 +126,44 @@ void SPIClass::setDataMode(uint8_t mode) void SPIClass::setDataMode(SPIMode mode) { - _spiSettings.setDataMode(mode); - - spi_init(&_spi, _spiSettings.getClockFreq(), - _spiSettings.getDataMode(), - _spiSettings.getBitOrder()); + _spiSettings.dataMode = mode; + spi_init(&_spi, _spiSettings.clockFreq, + _spiSettings.dataMode, + _spiSettings.bitOrder); } /** * @brief Deprecated function. * Configure the clock speed - * @param _divider: the SPI clock can be divided by values from 1 to 255. + * @param divider: the SPI clock can be divided by values from 1 to 255. * If 0, default SPI speed is used. */ -void SPIClass::setClockDivider(uint8_t _divider) +void SPIClass::setClockDivider(uint8_t divider) { - if (_divider == 0) { - _spiSettings.setClockFreq(SPI_SPEED_CLOCK_DEFAULT); + if (divider == 0) { + _spiSettings.clockFreq = SPI_SPEED_CLOCK_DEFAULT; } else { - /* Get clock freq of the SPI instance and compute it */ - _spiSettings.setClockFreq(spi_getClkFreq(&_spi) / _divider); + /* Get clk freq of the SPI instance and compute it */ + _spiSettings.clockFreq = spi_getClkFreq(&_spi) / divider; } - spi_init(&_spi, _spiSettings.getClockFreq(), - _spiSettings.getDataMode(), - _spiSettings.getBitOrder()); + spi_init(&_spi, _spiSettings.clockFreq, + _spiSettings.dataMode, + _spiSettings.bitOrder); } /** * @brief Transfer one byte on the SPI bus. * begin() or beginTransaction() must be called at least once before. * @param data: byte to send. + * @param skipReceive: skip receiving data after transmit or not. + * SPI_TRANSMITRECEIVE or SPI_TRANSMITONLY. + * Optional, default: SPI_TRANSMITRECEIVE. * @return byte received from the slave. */ -uint8_t SPIClass::transfer(uint8_t data) +uint8_t SPIClass::transfer(uint8_t data, bool skipReceive) { - spi_transfer(&_spi, &data, sizeof(uint8_t), SPI_TRANSFER_TIMEOUT, _spiSettings.getSkipRecv()); + spi_transfer(&_spi, &data, sizeof(uint8_t), SPI_TRANSFER_TIMEOUT, skipReceive); return data; } @@ -170,20 +171,23 @@ uint8_t SPIClass::transfer(uint8_t data) * @brief Transfer two bytes on the SPI bus in 16 bits format. * begin() or beginTransaction() must be called at least once before. * @param data: bytes to send. + * @param skipReceive: skip receiving data after transmit or not. + * SPI_TRANSMITRECEIVE or SPI_TRANSMITONLY. + * Optional, default: SPI_TRANSMITRECEIVE. * @return bytes received from the slave in 16 bits format. */ -uint16_t SPIClass::transfer16(uint16_t data) +uint16_t SPIClass::transfer16(uint16_t data, bool skipReceive) { uint16_t tmp; - if (_spiSettings.getBitOrder()) { + if (_spiSettings.bitOrder) { tmp = ((data & 0xff00) >> 8) | ((data & 0xff) << 8); data = tmp; } spi_transfer(&_spi, (uint8_t *)&data, sizeof(uint16_t), - SPI_TRANSFER_TIMEOUT, _spiSettings.getSkipRecv()); + SPI_TRANSFER_TIMEOUT, skipReceive); - if (_spiSettings.getBitOrder()) { + if (_spiSettings.bitOrder) { tmp = ((data & 0xff00) >> 8) | ((data & 0xff) << 8); data = tmp; } @@ -197,12 +201,15 @@ uint16_t SPIClass::transfer16(uint16_t data) * @param buf: pointer to the bytes to send. The bytes received are copy in * this buffer. * @param count: number of bytes to send/receive. + * @param skipReceive: skip receiving data after transmit or not. + * SPI_TRANSMITRECEIVE or SPI_TRANSMITONLY. + * Optional, default: SPI_TRANSMITRECEIVE. */ -void SPIClass::transfer(void *buf, size_t count) +void SPIClass::transfer(void *buf, size_t count, bool skipReceive) { if ((count != 0) && (buf != NULL)) { spi_transfer(&_spi, ((uint8_t *)buf), count, - SPI_TRANSFER_TIMEOUT, _spiSettings.getSkipRecv()); + SPI_TRANSFER_TIMEOUT, skipReceive); } } @@ -239,35 +246,6 @@ void SPIClass::detachInterrupt(void) } #if defined(SUBGHZSPI_BASE) -void SUBGHZSPIClass::begin() -{ - SPIClass::begin(); -} - -void SUBGHZSPIClass::beginTransaction(SPISettings settings) -{ - SPIClass::beginTransaction(settings); -} - -byte SUBGHZSPIClass::transfer(uint8_t _data) -{ - byte res; - res = SPIClass::transfer(_data); - return res; -} - -uint16_t SUBGHZSPIClass::transfer16(uint16_t _data) -{ - uint16_t rx_buffer = 0; - rx_buffer = SPIClass::transfer16(_data); - return rx_buffer; -} - -void SUBGHZSPIClass::transfer(void *_buf, size_t _count) -{ - SPIClass::transfer(_buf, _count); -} - void SUBGHZSPIClass::enableDebugPins(uint32_t mosi, uint32_t miso, uint32_t sclk, uint32_t ssel) { /* Configure SPI GPIO pins */ diff --git a/libraries/SPI/src/SPI.h b/libraries/SPI/src/SPI.h index 9509c871eb..1c8bbc11cd 100644 --- a/libraries/SPI/src/SPI.h +++ b/libraries/SPI/src/SPI.h @@ -38,8 +38,8 @@ extern "C" { #define SPI_CLOCK_DIV64 64 #define SPI_CLOCK_DIV128 128 -#define SPI_TRANSMITRECEIVE 0x0 -#define SPI_TRANSMITONLY 0x1 +#define SPI_TRANSMITRECEIVE false +#define SPI_TRANSMITONLY true // Defines a default timeout delay in milliseconds for the SPI transfer #ifndef SPI_TRANSFER_TIMEOUT @@ -48,36 +48,27 @@ extern "C" { class SPISettings { public: - SPISettings(uint32_t clock, BitOrder bitOrder, SPIMode dataMode, bool skipRecv = SPI_TRANSMITRECEIVE) - { - if (__builtin_constant_p(clock)) { - init_AlwaysInline(clock, bitOrder, dataMode, skipRecv); - } else { - init_MightInline(clock, bitOrder, dataMode, skipRecv); - } - } - - SPISettings(uint32_t clock, BitOrder bitOrder, int dataMode, bool skipRecv = SPI_TRANSMITRECEIVE) - { - if (__builtin_constant_p(clock)) { - init_AlwaysInline(clock, bitOrder, (SPIMode)dataMode, skipRecv); - } else { - init_MightInline(clock, bitOrder, (SPIMode)dataMode, skipRecv); - } - } - - // Default speed set to 4MHz, SPI mode set to MODE 0 and Bit order set to MSB first. - SPISettings() - { - init_AlwaysInline(SPI_SPEED_CLOCK_DEFAULT, MSBFIRST, SPI_MODE0, SPI_TRANSMITRECEIVE); - } + constexpr SPISettings(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) + : clockFreq(clock), + bitOrder(bitOrder), + dataMode((SPIMode)dataMode) + { } + constexpr SPISettings(uint32_t clock, BitOrder bitOrder, SPIMode dataMode) + : clockFreq(clock), + bitOrder(bitOrder), + dataMode(dataMode) + { } + constexpr SPISettings() + : clockFreq(SPI_SPEED_CLOCK_DEFAULT), + bitOrder(MSBFIRST), + dataMode(SPI_MODE0) + { } bool operator==(const SPISettings &rhs) const { if ((this->clockFreq == rhs.clockFreq) && (this->bitOrder == rhs.bitOrder) && - (this->dataMode == rhs.dataMode) && - (this->skipRecv == rhs.skipRecv)) { + (this->dataMode == rhs.dataMode)) { return true; } return false; @@ -88,65 +79,14 @@ class SPISettings { return !(*this == rhs); } - uint32_t getClockFreq() const - { - return clockFreq; - } - SPIMode getDataMode() const - { - return dataMode; - } - BitOrder getBitOrder() const - { - return (bitOrder); - } - bool getSkipRecv() const - { - return skipRecv; - } - - void setClockFreq(uint32_t clkFreq) - { - clockFreq = clkFreq; - } - void setDataMode(SPIMode mode) - { - dataMode = mode; - } - void setBitOrder(BitOrder order) - { - bitOrder = order; - } - void setSkipRecv(bool skip) - { - skipRecv = skip; - } - private: - void init_MightInline(uint32_t clock, BitOrder bitOrder, SPIMode dataMode, bool skipRecv) - { - init_AlwaysInline(clock, bitOrder, dataMode, skipRecv); - } - - // Core developer MUST use an helper function in beginTransaction() to use this data - void init_AlwaysInline(uint32_t clock, BitOrder bitOrder, SPIMode dataMode, bool skipRecv) __attribute__((__always_inline__)) - { - this->clockFreq = clock; - this->dataMode = dataMode; - this->bitOrder = bitOrder; - this->skipRecv = skipRecv; - } + uint32_t clockFreq; //specifies the spi bus maximum clock speed + BitOrder bitOrder; //bit order (MSBFirst or LSBFirst) + SPIMode dataMode; //one of the data mode - uint32_t clockFreq; - SPIMode dataMode; - BitOrder bitOrder; - bool skipRecv; - - friend class HardwareSPI; + friend class SPIClass; }; -const SPISettings DEFAULT_SPI_SETTINGS = SPISettings(); - class SPIClass { public: SPIClass(); @@ -199,9 +139,9 @@ class SPIClass { /* Transfer functions: must be called after initialization of the SPI * instance with begin() or beginTransaction(). */ - virtual uint8_t transfer(uint8_t _data); - virtual uint16_t transfer16(uint16_t _data); - virtual void transfer(void *buf, size_t count); + virtual uint8_t transfer(uint8_t data, bool skipReceive = SPI_TRANSMITRECEIVE); + virtual uint16_t transfer16(uint16_t data, bool skipReceive = SPI_TRANSMITRECEIVE); + virtual void transfer(void *buf, size_t count, bool skipReceive = SPI_TRANSMITRECEIVE); /* These methods are deprecated and kept for compatibility. * Use SPISettings with SPI.beginTransaction() to configure SPI parameters. @@ -229,7 +169,7 @@ class SPIClass { private: /* Current SPISettings */ - SPISettings _spiSettings = DEFAULT_SPI_SETTINGS; + SPISettings _spiSettings = SPISettings(); }; extern SPIClass SPI; @@ -242,16 +182,7 @@ class SUBGHZSPIClass : public SPIClass { _spi.spi = SUBGHZSPI; } - void begin(); - void beginTransaction(SPISettings settings); - byte transfer(uint8_t _data); - uint16_t transfer16(uint16_t _data); - void transfer(void *_buf, size_t _count); void enableDebugPins(uint32_t mosi = DEBUG_SUBGHZSPI_MOSI, uint32_t miso = DEBUG_SUBGHZSPI_MISO, uint32_t sclk = DEBUG_SUBGHZSPI_SCLK, uint32_t ssel = DEBUG_SUBGHZSPI_SS); - - using SPIClass::beginTransaction; - using SPIClass::transfer; - using SPIClass::transfer16; }; #endif diff --git a/libraries/SubGhz/src/SubGhz.cpp b/libraries/SubGhz/src/SubGhz.cpp index a175c0c551..b5394fd55f 100644 --- a/libraries/SubGhz/src/SubGhz.cpp +++ b/libraries/SubGhz/src/SubGhz.cpp @@ -21,6 +21,8 @@ extern "C" void SUBGHZ_Radio_IRQHandler(void) SubGhz.handleIrq(); } +constexpr SPISettings SubGhzClass::spi_settings; + void SubGhzClass::handleIrq() { if (callback) { diff --git a/libraries/SubGhz/src/SubGhz.h b/libraries/SubGhz/src/SubGhz.h index dd8683f279..60bb621fad 100644 --- a/libraries/SubGhz/src/SubGhz.h +++ b/libraries/SubGhz/src/SubGhz.h @@ -101,7 +101,7 @@ class SubGhzClass { // supported by the radio, which should always work (no chance of // bad wiring that requires reducing the speed). // This value should be passed to `SubGhz.SPI.beginTransaction()`. - const SPISettings spi_settings = {16000000, MSBFIRST, SPI_MODE0}; + static constexpr SPISettings spi_settings = {16000000, MSBFIRST, SPI_MODE0}; protected: // To access handleIrq()