From 8e8feb0c58c1ac17008c5dd082226d746232a4ea Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Thu, 23 Nov 2023 15:28:26 +0100 Subject: [PATCH 1/8] Revert "chore(SPI): align with ArduinoCoreAPI" This reverts commit 392469a1dc66448dea543119b7258128b5596a03. --- libraries/SPI/src/SPI.cpp | 95 +++++++++--------- libraries/SPI/src/SPI.h | 144 ++++++++-------------------- libraries/SPI/src/utility/spi_com.c | 6 +- libraries/SPI/src/utility/spi_com.h | 13 ++- 4 files changed, 94 insertions(+), 164 deletions(-) diff --git a/libraries/SPI/src/SPI.cpp b/libraries/SPI/src/SPI.cpp index b3266d348a..b8f282ffe5 100644 --- a/libraries/SPI/src/SPI.cpp +++ b/libraries/SPI/src/SPI.cpp @@ -57,10 +57,9 @@ 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()); + spi_init(&_spi, _spiSettings.clk, + _spiSettings.dMode, + _spiSettings.bOrder); } /** @@ -70,12 +69,14 @@ void SPIClass::begin(void) */ void SPIClass::beginTransaction(SPISettings settings) { - if (_spiSettings != settings) { - _spiSettings = settings; - spi_init(&_spi, _spiSettings.getClockFreq(), - _spiSettings.getDataMode(), - _spiSettings.getBitOrder()); - } + _spiSettings.clk = settings.clk; + _spiSettings.dMode = settings.dMode; + _spiSettings.bOrder = settings.bOrder; + _spiSettings.noReceive = settings.noReceive; + + spi_init(&_spi, _spiSettings.clk, + _spiSettings.dMode, + _spiSettings.bOrder); } /** @@ -101,17 +102,17 @@ void SPIClass::end() */ void SPIClass::setBitOrder(BitOrder bitOrder) { - _spiSettings.setBitOrder(bitOrder); + _spiSettings.bOrder = bitOrder; - spi_init(&_spi, _spiSettings.getClockFreq(), - _spiSettings.getDataMode(), - _spiSettings.getBitOrder()); + spi_init(&_spi, _spiSettings.clk, + _spiSettings.dMode, + _spiSettings.bOrder); } /** * @brief Deprecated function. * Configure the data mode (clock polarity and clock phase) - * @param mode: SPI_MODE0, SPI_MODE1, SPI_MODE2 or SPI_MODE3 + * @param _mode: SPI_MODE0, SPI_MODE1, SPI_MODE2 or SPI_MODE3 * @note * Mode Clock Polarity (CPOL) Clock Phase (CPHA) * SPI_MODE0 0 0 @@ -119,19 +120,21 @@ void SPIClass::setBitOrder(BitOrder bitOrder) * SPI_MODE2 1 0 * SPI_MODE3 1 1 */ - -void SPIClass::setDataMode(uint8_t mode) +void SPIClass::setDataMode(uint8_t _mode) { - setDataMode((SPIMode)mode); -} - -void SPIClass::setDataMode(SPIMode mode) -{ - _spiSettings.setDataMode(mode); + if (SPI_MODE0 == _mode) { + _spiSettings.dMode = SPI_MODE_0; + } else if (SPI_MODE1 == _mode) { + _spiSettings.dMode = SPI_MODE_1; + } else if (SPI_MODE2 == _mode) { + _spiSettings.dMode = SPI_MODE_2; + } else if (SPI_MODE3 == _mode) { + _spiSettings.dMode = SPI_MODE_3; + } - spi_init(&_spi, _spiSettings.getClockFreq(), - _spiSettings.getDataMode(), - _spiSettings.getBitOrder()); + spi_init(&_spi, _spiSettings.clk, + _spiSettings.dMode, + _spiSettings.bOrder); } /** @@ -143,15 +146,15 @@ void SPIClass::setDataMode(SPIMode mode) void SPIClass::setClockDivider(uint8_t _divider) { if (_divider == 0) { - _spiSettings.setClockFreq(SPI_SPEED_CLOCK_DEFAULT); + _spiSettings.clk = 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.clk = spi_getClkFreq(&_spi) / _divider; } - spi_init(&_spi, _spiSettings.getClockFreq(), - _spiSettings.getDataMode(), - _spiSettings.getBitOrder()); + spi_init(&_spi, _spiSettings.clk, + _spiSettings.dMode, + _spiSettings.bOrder); } /** @@ -160,9 +163,9 @@ void SPIClass::setClockDivider(uint8_t _divider) * @param data: byte to send. * @return byte received from the slave. */ -uint8_t SPIClass::transfer(uint8_t data) +byte SPIClass::transfer(uint8_t data) { - spi_transfer(&_spi, &data, sizeof(uint8_t), SPI_TRANSFER_TIMEOUT, _spiSettings.getSkipRecv()); + spi_transfer(&_spi, &data, sizeof(uint8_t), SPI_TRANSFER_TIMEOUT, _spiSettings.noReceive); return data; } @@ -176,14 +179,14 @@ uint16_t SPIClass::transfer16(uint16_t data) { uint16_t tmp; - if (_spiSettings.getBitOrder()) { + if (_spiSettings.bOrder) { 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, _spiSettings.noReceive); - if (_spiSettings.getBitOrder()) { + if (_spiSettings.bOrder) { tmp = ((data & 0xff00) >> 8) | ((data & 0xff) << 8); data = tmp; } @@ -194,30 +197,22 @@ uint16_t SPIClass::transfer16(uint16_t data) /** * @brief Transfer several bytes. Only one buffer used to send and receive data. * begin() or beginTransaction() must be called at least once before. - * @param buf: pointer to the bytes to send. The bytes received are copy in + * @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 _count: number of bytes to send/receive. */ -void SPIClass::transfer(void *buf, size_t count) +void SPIClass::transfer(void *_buf, size_t _count) { if ((count != 0) && (buf != NULL)) { spi_transfer(&_spi, ((uint8_t *)buf), count, - SPI_TRANSFER_TIMEOUT, _spiSettings.getSkipRecv()); + SPI_TRANSFER_TIMEOUT, _spiSettings.noReceive); } } /** * @brief Not implemented. */ -void SPIClass::usingInterrupt(int interruptNumber) -{ - UNUSED(interruptNumber); -} - -/** - * @brief Not implemented. - */ -void SPIClass::notUsingInterrupt(int interruptNumber) +void SPIClass::usingInterrupt(uint8_t interruptNumber) { UNUSED(interruptNumber); } diff --git a/libraries/SPI/src/SPI.h b/libraries/SPI/src/SPI.h index 9509c871eb..f8e41bea5c 100644 --- a/libraries/SPI/src/SPI.h +++ b/libraries/SPI/src/SPI.h @@ -38,6 +38,12 @@ extern "C" { #define SPI_CLOCK_DIV64 64 #define SPI_CLOCK_DIV128 128 +// SPI mode parameters for SPISettings +#define SPI_MODE0 0x00 +#define SPI_MODE1 0x01 +#define SPI_MODE2 0x02 +#define SPI_MODE3 0x03 + #define SPI_TRANSMITRECEIVE 0x0 #define SPI_TRANSMITONLY 0x1 @@ -48,105 +54,37 @@ 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); - } - - bool operator==(const SPISettings &rhs) const - { - if ((this->clockFreq == rhs.clockFreq) && - (this->bitOrder == rhs.bitOrder) && - (this->dataMode == rhs.dataMode) && - (this->skipRecv == rhs.skipRecv)) { - return true; - } - return false; - } - - bool operator!=(const SPISettings &rhs) const - { - 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; - } - + constexpr SPISettings(uint32_t clock, BitOrder bitOrder, uint8_t dataMode, bool noRecv = SPI_TRANSMITRECEIVE) + : clk(clock), + bOrder(bitOrder), + dMode((spi_mode_e)( + (SPI_MODE0 == dataMode) ? SPI_MODE_0 : + (SPI_MODE1 == dataMode) ? SPI_MODE_1 : + (SPI_MODE2 == dataMode) ? SPI_MODE_2 : + (SPI_MODE3 == dataMode) ? SPI_MODE_3 : + SPI_MODE0 + )), + noReceive(noRecv) + { } + constexpr SPISettings() + : clk(SPI_SPEED_CLOCK_DEFAULT), + bOrder(MSBFIRST), + dMode(SPI_MODE_0), + noReceive(SPI_TRANSMITRECEIVE) + { } 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; - SPIMode dataMode; - BitOrder bitOrder; - bool skipRecv; - - friend class HardwareSPI; + uint32_t clk; //specifies the spi bus maximum clock speed + BitOrder bOrder; //bit order (MSBFirst or LSBFirst) + spi_mode_e dMode; //one of the data mode + //Mode Clock Polarity (CPOL) Clock Phase (CPHA) + //SPI_MODE0 0 0 + //SPI_MODE1 0 1 + //SPI_MODE2 1 0 + //SPI_MODE3 1 1 + friend class SPIClass; + bool noReceive; }; -const SPISettings DEFAULT_SPI_SETTINGS = SPISettings(); - class SPIClass { public: SPIClass(); @@ -187,7 +125,7 @@ class SPIClass { _spi.pin_ssel = (ssel); }; - virtual void begin(void); + virtual void begin(); void end(void); /* This function should be used to configure the SPI instance in case you @@ -199,21 +137,19 @@ 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 byte transfer(uint8_t _data); virtual uint16_t transfer16(uint16_t _data); - virtual void transfer(void *buf, size_t count); + virtual void transfer(void *_buf, size_t _count); /* These methods are deprecated and kept for compatibility. * Use SPISettings with SPI.beginTransaction() to configure SPI parameters. */ void setBitOrder(BitOrder); void setDataMode(uint8_t); - void setDataMode(SPIMode); void setClockDivider(uint8_t); - // Not implemented functions. Kept for compatibility. - void usingInterrupt(int interruptNumber); - void notUsingInterrupt(int interruptNumber); + // Not implemented functions. Kept for backward compatibility. + void usingInterrupt(uint8_t interruptNumber); void attachInterrupt(void); void detachInterrupt(void); @@ -229,7 +165,7 @@ class SPIClass { private: /* Current SPISettings */ - SPISettings _spiSettings = DEFAULT_SPI_SETTINGS; + SPISettings _spiSettings = SPISettings(); }; extern SPIClass SPI; diff --git a/libraries/SPI/src/utility/spi_com.c b/libraries/SPI/src/utility/spi_com.c index bd582681bd..cfc2c2cc45 100644 --- a/libraries/SPI/src/utility/spi_com.c +++ b/libraries/SPI/src/utility/spi_com.c @@ -227,7 +227,7 @@ static uint32_t compute_disable_delay(spi_t *obj) * @param msb : set to 1 in msb first * @retval None */ -void spi_init(spi_t *obj, uint32_t speed, SPIMode mode, uint8_t msb) +void spi_init(spi_t *obj, uint32_t speed, spi_mode_e mode, uint8_t msb) { if (obj == NULL) { return; @@ -313,13 +313,13 @@ void spi_init(spi_t *obj, uint32_t speed, SPIMode mode, uint8_t msb) handle->Init.Direction = SPI_DIRECTION_2LINES; - if ((mode == SPI_MODE0) || (mode == SPI_MODE2)) { + if ((mode == SPI_MODE_0) || (mode == SPI_MODE_2)) { handle->Init.CLKPhase = SPI_PHASE_1EDGE; } else { handle->Init.CLKPhase = SPI_PHASE_2EDGE; } - if ((mode == SPI_MODE0) || (mode == SPI_MODE1)) { + if ((mode == SPI_MODE_0) || (mode == SPI_MODE_1)) { handle->Init.CLKPolarity = SPI_POLARITY_LOW; } else { handle->Init.CLKPolarity = SPI_POLARITY_HIGH; diff --git a/libraries/SPI/src/utility/spi_com.h b/libraries/SPI/src/utility/spi_com.h index 7562c08118..ee322e6982 100644 --- a/libraries/SPI/src/utility/spi_com.h +++ b/libraries/SPI/src/utility/spi_com.h @@ -85,13 +85,12 @@ typedef struct spi_s spi_t; //SPI_MODE2 1 0 //SPI_MODE3 1 1 //enum definitions coming from SPI.h of SAM -// SPI mode parameters for SPISettings typedef enum { - SPI_MODE0 = 0, - SPI_MODE1 = 1, - SPI_MODE2 = 2, - SPI_MODE3 = 3, -} SPIMode; + SPI_MODE_0 = 0x00, + SPI_MODE_1 = 0x01, + SPI_MODE_2 = 0x02, + SPI_MODE_3 = 0x03 +} spi_mode_e; ///@brief SPI errors typedef enum { @@ -101,7 +100,7 @@ typedef enum { } spi_status_e; /* Exported functions ------------------------------------------------------- */ -void spi_init(spi_t *obj, uint32_t speed, SPIMode mode, uint8_t msb); +void spi_init(spi_t *obj, uint32_t speed, spi_mode_e mode, uint8_t msb); void spi_deinit(spi_t *obj); spi_status_e spi_transfer(spi_t *obj, uint8_t *buffer, uint16_t len, uint32_t Timeout, bool skipReceive); From c9a89f1b611df1c1bdb5694c2069071201860991 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Thu, 23 Nov 2023 16:14:31 +0100 Subject: [PATCH 2/8] Revert "fix(SubGhz): SPISettings not properly defined" This reverts commit d61ad831a72241657fcd2dfd1d3e6d704dd601e6. --- libraries/SubGhz/src/SubGhz.cpp | 2 ++ libraries/SubGhz/src/SubGhz.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) 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() From ea70e88cfa393c2f2683a75de6c2d9d06b0d4ed0 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Thu, 23 Nov 2023 16:13:57 +0100 Subject: [PATCH 3/8] chore(spi): partially align with ArduinoCoreAPI Keep constexpr constructor to ensures that constructing an SPISettings object can be done at compiletime. Fixes #2201. Signed-off-by: Frederic Pillon --- libraries/SPI/src/SPI.cpp | 95 +++++++++++++++-------------- libraries/SPI/src/SPI.h | 71 ++++++++++----------- libraries/SPI/src/utility/spi_com.c | 6 +- libraries/SPI/src/utility/spi_com.h | 13 ++-- 4 files changed, 96 insertions(+), 89 deletions(-) diff --git a/libraries/SPI/src/SPI.cpp b/libraries/SPI/src/SPI.cpp index b8f282ffe5..15dbb79f18 100644 --- a/libraries/SPI/src/SPI.cpp +++ b/libraries/SPI/src/SPI.cpp @@ -57,9 +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; - spi_init(&_spi, _spiSettings.clk, - _spiSettings.dMode, - _spiSettings.bOrder); + _spiSettings = SPISettings(); + spi_init(&_spi, _spiSettings.clockFreq, + _spiSettings.dataMode, + _spiSettings.bitOrder); } /** @@ -69,14 +70,12 @@ void SPIClass::begin(void) */ void SPIClass::beginTransaction(SPISettings settings) { - _spiSettings.clk = settings.clk; - _spiSettings.dMode = settings.dMode; - _spiSettings.bOrder = settings.bOrder; - _spiSettings.noReceive = settings.noReceive; - - spi_init(&_spi, _spiSettings.clk, - _spiSettings.dMode, - _spiSettings.bOrder); + if (_spiSettings != settings) { + _spiSettings = settings; + spi_init(&_spi, _spiSettings.clockFreq, + _spiSettings.dataMode, + _spiSettings.bitOrder); + } } /** @@ -90,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); } @@ -98,21 +97,21 @@ 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.bOrder = bitOrder; + _spiSettings.bitOrder = bitOrder; - spi_init(&_spi, _spiSettings.clk, - _spiSettings.dMode, - _spiSettings.bOrder); + spi_init(&_spi, _spiSettings.clockFreq, + _spiSettings.dataMode, + _spiSettings.bitOrder); } /** * @brief Deprecated function. * Configure the data mode (clock polarity and clock phase) - * @param _mode: SPI_MODE0, SPI_MODE1, SPI_MODE2 or SPI_MODE3 + * @param mode: SPI_MODE0, SPI_MODE1, SPI_MODE2 or SPI_MODE3 * @note * Mode Clock Polarity (CPOL) Clock Phase (CPHA) * SPI_MODE0 0 0 @@ -120,41 +119,37 @@ void SPIClass::setBitOrder(BitOrder bitOrder) * SPI_MODE2 1 0 * SPI_MODE3 1 1 */ -void SPIClass::setDataMode(uint8_t _mode) +void SPIClass::setDataMode(uint8_t mode) { - if (SPI_MODE0 == _mode) { - _spiSettings.dMode = SPI_MODE_0; - } else if (SPI_MODE1 == _mode) { - _spiSettings.dMode = SPI_MODE_1; - } else if (SPI_MODE2 == _mode) { - _spiSettings.dMode = SPI_MODE_2; - } else if (SPI_MODE3 == _mode) { - _spiSettings.dMode = SPI_MODE_3; - } + setDataMode((SPIMode)mode); +} - spi_init(&_spi, _spiSettings.clk, - _spiSettings.dMode, - _spiSettings.bOrder); +void SPIClass::setDataMode(SPIMode mode) +{ + _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.clk = SPI_SPEED_CLOCK_DEFAULT; + if (divider == 0) { + _spiSettings.clockFreq = SPI_SPEED_CLOCK_DEFAULT; } else { /* Get clk freq of the SPI instance and compute it */ - _spiSettings.clk = spi_getClkFreq(&_spi) / _divider; + _spiSettings.clockFreq = spi_getClkFreq(&_spi) / divider; } - spi_init(&_spi, _spiSettings.clk, - _spiSettings.dMode, - _spiSettings.bOrder); + spi_init(&_spi, _spiSettings.clockFreq, + _spiSettings.dataMode, + _spiSettings.bitOrder); } /** @@ -163,7 +158,7 @@ void SPIClass::setClockDivider(uint8_t _divider) * @param data: byte to send. * @return byte received from the slave. */ -byte SPIClass::transfer(uint8_t data) +uint8_t SPIClass::transfer(uint8_t data) { spi_transfer(&_spi, &data, sizeof(uint8_t), SPI_TRANSFER_TIMEOUT, _spiSettings.noReceive); return data; @@ -179,14 +174,14 @@ uint16_t SPIClass::transfer16(uint16_t data) { uint16_t tmp; - if (_spiSettings.bOrder) { + 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.noReceive); - if (_spiSettings.bOrder) { + if (_spiSettings.bitOrder) { tmp = ((data & 0xff00) >> 8) | ((data & 0xff) << 8); data = tmp; } @@ -197,11 +192,11 @@ uint16_t SPIClass::transfer16(uint16_t data) /** * @brief Transfer several bytes. Only one buffer used to send and receive data. * begin() or beginTransaction() must be called at least once before. - * @param _buf: pointer to the bytes to send. The bytes received are copy in + * @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 count: number of bytes to send/receive. */ -void SPIClass::transfer(void *_buf, size_t _count) +void SPIClass::transfer(void *buf, size_t count) { if ((count != 0) && (buf != NULL)) { spi_transfer(&_spi, ((uint8_t *)buf), count, @@ -212,7 +207,15 @@ void SPIClass::transfer(void *_buf, size_t _count) /** * @brief Not implemented. */ -void SPIClass::usingInterrupt(uint8_t interruptNumber) +void SPIClass::usingInterrupt(int interruptNumber) +{ + UNUSED(interruptNumber); +} + +/** + * @brief Not implemented. + */ +void SPIClass::notUsingInterrupt(int interruptNumber) { UNUSED(interruptNumber); } diff --git a/libraries/SPI/src/SPI.h b/libraries/SPI/src/SPI.h index f8e41bea5c..af19d4e38e 100644 --- a/libraries/SPI/src/SPI.h +++ b/libraries/SPI/src/SPI.h @@ -38,12 +38,6 @@ extern "C" { #define SPI_CLOCK_DIV64 64 #define SPI_CLOCK_DIV128 128 -// SPI mode parameters for SPISettings -#define SPI_MODE0 0x00 -#define SPI_MODE1 0x01 -#define SPI_MODE2 0x02 -#define SPI_MODE3 0x03 - #define SPI_TRANSMITRECEIVE 0x0 #define SPI_TRANSMITONLY 0x1 @@ -54,35 +48,42 @@ extern "C" { class SPISettings { public: - constexpr SPISettings(uint32_t clock, BitOrder bitOrder, uint8_t dataMode, bool noRecv = SPI_TRANSMITRECEIVE) - : clk(clock), - bOrder(bitOrder), - dMode((spi_mode_e)( - (SPI_MODE0 == dataMode) ? SPI_MODE_0 : - (SPI_MODE1 == dataMode) ? SPI_MODE_1 : - (SPI_MODE2 == dataMode) ? SPI_MODE_2 : - (SPI_MODE3 == dataMode) ? SPI_MODE_3 : - SPI_MODE0 - )), + constexpr SPISettings(uint32_t clock, BitOrder bitOrder, SPIMode dataMode, bool noRecv = SPI_TRANSMITRECEIVE) + : clockFreq(clock), + bitOrder(bitOrder), + dataMode(dataMode), noReceive(noRecv) { } constexpr SPISettings() - : clk(SPI_SPEED_CLOCK_DEFAULT), - bOrder(MSBFIRST), - dMode(SPI_MODE_0), + : clockFreq(SPI_SPEED_CLOCK_DEFAULT), + bitOrder(MSBFIRST), + dataMode(SPI_MODE0), noReceive(SPI_TRANSMITRECEIVE) { } + + bool operator==(const SPISettings &rhs) const + { + if ((this->clockFreq == rhs.clockFreq) && + (this->bitOrder == rhs.bitOrder) && + (this->dataMode == rhs.dataMode) && + (this->noReceive == rhs.noReceive)) { + return true; + } + return false; + } + + bool operator!=(const SPISettings &rhs) const + { + return !(*this == rhs); + } + private: - uint32_t clk; //specifies the spi bus maximum clock speed - BitOrder bOrder; //bit order (MSBFirst or LSBFirst) - spi_mode_e dMode; //one of the data mode - //Mode Clock Polarity (CPOL) Clock Phase (CPHA) - //SPI_MODE0 0 0 - //SPI_MODE1 0 1 - //SPI_MODE2 1 0 - //SPI_MODE3 1 1 - friend class SPIClass; + uint32_t clockFreq; //specifies the spi bus maximum clock speed + BitOrder bitOrder; //bit order (MSBFirst or LSBFirst) + SPIMode dataMode; //one of the data mode bool noReceive; + + friend class SPIClass; }; class SPIClass { @@ -125,7 +126,7 @@ class SPIClass { _spi.pin_ssel = (ssel); }; - virtual void begin(); + virtual void begin(void); void end(void); /* This function should be used to configure the SPI instance in case you @@ -137,19 +138,21 @@ class SPIClass { /* Transfer functions: must be called after initialization of the SPI * instance with begin() or beginTransaction(). */ - virtual byte 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); + virtual uint16_t transfer16(uint16_t data); + virtual void transfer(void *buf, size_t count); /* These methods are deprecated and kept for compatibility. * Use SPISettings with SPI.beginTransaction() to configure SPI parameters. */ void setBitOrder(BitOrder); void setDataMode(uint8_t); + void setDataMode(SPIMode); void setClockDivider(uint8_t); - // Not implemented functions. Kept for backward compatibility. - void usingInterrupt(uint8_t interruptNumber); + // Not implemented functions. Kept for compatibility. + void usingInterrupt(int interruptNumber); + void notUsingInterrupt(int interruptNumber); void attachInterrupt(void); void detachInterrupt(void); diff --git a/libraries/SPI/src/utility/spi_com.c b/libraries/SPI/src/utility/spi_com.c index cfc2c2cc45..bd582681bd 100644 --- a/libraries/SPI/src/utility/spi_com.c +++ b/libraries/SPI/src/utility/spi_com.c @@ -227,7 +227,7 @@ static uint32_t compute_disable_delay(spi_t *obj) * @param msb : set to 1 in msb first * @retval None */ -void spi_init(spi_t *obj, uint32_t speed, spi_mode_e mode, uint8_t msb) +void spi_init(spi_t *obj, uint32_t speed, SPIMode mode, uint8_t msb) { if (obj == NULL) { return; @@ -313,13 +313,13 @@ void spi_init(spi_t *obj, uint32_t speed, spi_mode_e mode, uint8_t msb) handle->Init.Direction = SPI_DIRECTION_2LINES; - if ((mode == SPI_MODE_0) || (mode == SPI_MODE_2)) { + if ((mode == SPI_MODE0) || (mode == SPI_MODE2)) { handle->Init.CLKPhase = SPI_PHASE_1EDGE; } else { handle->Init.CLKPhase = SPI_PHASE_2EDGE; } - if ((mode == SPI_MODE_0) || (mode == SPI_MODE_1)) { + if ((mode == SPI_MODE0) || (mode == SPI_MODE1)) { handle->Init.CLKPolarity = SPI_POLARITY_LOW; } else { handle->Init.CLKPolarity = SPI_POLARITY_HIGH; diff --git a/libraries/SPI/src/utility/spi_com.h b/libraries/SPI/src/utility/spi_com.h index ee322e6982..7562c08118 100644 --- a/libraries/SPI/src/utility/spi_com.h +++ b/libraries/SPI/src/utility/spi_com.h @@ -85,12 +85,13 @@ typedef struct spi_s spi_t; //SPI_MODE2 1 0 //SPI_MODE3 1 1 //enum definitions coming from SPI.h of SAM +// SPI mode parameters for SPISettings typedef enum { - SPI_MODE_0 = 0x00, - SPI_MODE_1 = 0x01, - SPI_MODE_2 = 0x02, - SPI_MODE_3 = 0x03 -} spi_mode_e; + SPI_MODE0 = 0, + SPI_MODE1 = 1, + SPI_MODE2 = 2, + SPI_MODE3 = 3, +} SPIMode; ///@brief SPI errors typedef enum { @@ -100,7 +101,7 @@ typedef enum { } spi_status_e; /* Exported functions ------------------------------------------------------- */ -void spi_init(spi_t *obj, uint32_t speed, spi_mode_e mode, uint8_t msb); +void spi_init(spi_t *obj, uint32_t speed, SPIMode mode, uint8_t msb); void spi_deinit(spi_t *obj); spi_status_e spi_transfer(spi_t *obj, uint8_t *buffer, uint16_t len, uint32_t Timeout, bool skipReceive); From c1b1d61ac158f3c571ad4044f8a97fd59c3bbaf8 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Mon, 20 Nov 2023 17:02:50 +0100 Subject: [PATCH 4/8] feat(spi): remove skip receive from SPISettings This parameter should not be part of SPISettings. Signed-off-by: Frederic Pillon --- libraries/SPI/README.md | 4 ---- libraries/SPI/src/SPI.cpp | 6 +++--- libraries/SPI/src/SPI.h | 15 ++++----------- 3 files changed, 7 insertions(+), 18 deletions(-) diff --git a/libraries/SPI/README.md b/libraries/SPI/README.md index 5bf0889c59..2849c787ac 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 diff --git a/libraries/SPI/src/SPI.cpp b/libraries/SPI/src/SPI.cpp index 15dbb79f18..01d74b2852 100644 --- a/libraries/SPI/src/SPI.cpp +++ b/libraries/SPI/src/SPI.cpp @@ -160,7 +160,7 @@ void SPIClass::setClockDivider(uint8_t divider) */ uint8_t SPIClass::transfer(uint8_t data) { - spi_transfer(&_spi, &data, sizeof(uint8_t), SPI_TRANSFER_TIMEOUT, _spiSettings.noReceive); + spi_transfer(&_spi, &data, sizeof(uint8_t), SPI_TRANSFER_TIMEOUT, false); return data; } @@ -179,7 +179,7 @@ uint16_t SPIClass::transfer16(uint16_t data) data = tmp; } spi_transfer(&_spi, (uint8_t *)&data, sizeof(uint16_t), - SPI_TRANSFER_TIMEOUT, _spiSettings.noReceive); + SPI_TRANSFER_TIMEOUT, false); if (_spiSettings.bitOrder) { tmp = ((data & 0xff00) >> 8) | ((data & 0xff) << 8); @@ -200,7 +200,7 @@ void SPIClass::transfer(void *buf, size_t count) { if ((count != 0) && (buf != NULL)) { spi_transfer(&_spi, ((uint8_t *)buf), count, - SPI_TRANSFER_TIMEOUT, _spiSettings.noReceive); + SPI_TRANSFER_TIMEOUT, false); } } diff --git a/libraries/SPI/src/SPI.h b/libraries/SPI/src/SPI.h index af19d4e38e..fc673ca882 100644 --- a/libraries/SPI/src/SPI.h +++ b/libraries/SPI/src/SPI.h @@ -38,9 +38,6 @@ extern "C" { #define SPI_CLOCK_DIV64 64 #define SPI_CLOCK_DIV128 128 -#define SPI_TRANSMITRECEIVE 0x0 -#define SPI_TRANSMITONLY 0x1 - // Defines a default timeout delay in milliseconds for the SPI transfer #ifndef SPI_TRANSFER_TIMEOUT #define SPI_TRANSFER_TIMEOUT 1000 @@ -48,25 +45,22 @@ extern "C" { class SPISettings { public: - constexpr SPISettings(uint32_t clock, BitOrder bitOrder, SPIMode dataMode, bool noRecv = SPI_TRANSMITRECEIVE) + constexpr SPISettings(uint32_t clock, BitOrder bitOrder, SPIMode dataMode) : clockFreq(clock), bitOrder(bitOrder), - dataMode(dataMode), - noReceive(noRecv) + dataMode(dataMode) { } constexpr SPISettings() : clockFreq(SPI_SPEED_CLOCK_DEFAULT), bitOrder(MSBFIRST), - dataMode(SPI_MODE0), - noReceive(SPI_TRANSMITRECEIVE) + dataMode(SPI_MODE0) { } bool operator==(const SPISettings &rhs) const { if ((this->clockFreq == rhs.clockFreq) && (this->bitOrder == rhs.bitOrder) && - (this->dataMode == rhs.dataMode) && - (this->noReceive == rhs.noReceive)) { + (this->dataMode == rhs.dataMode)) { return true; } return false; @@ -81,7 +75,6 @@ class SPISettings { uint32_t clockFreq; //specifies the spi bus maximum clock speed BitOrder bitOrder; //bit order (MSBFirst or LSBFirst) SPIMode dataMode; //one of the data mode - bool noReceive; friend class SPIClass; }; From 98fca7dc081def1ac072196cf91ffbf82833af89 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Wed, 22 Nov 2023 14:30:24 +0100 Subject: [PATCH 5/8] chore(subghzspi): clean up useless declaration Since internal CS pin removed. Signed-off-by: Frederic Pillon --- libraries/SPI/src/SPI.cpp | 29 ----------------------------- libraries/SPI/src/SPI.h | 9 --------- 2 files changed, 38 deletions(-) diff --git a/libraries/SPI/src/SPI.cpp b/libraries/SPI/src/SPI.cpp index 01d74b2852..4bd483a5da 100644 --- a/libraries/SPI/src/SPI.cpp +++ b/libraries/SPI/src/SPI.cpp @@ -237,35 +237,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 fc673ca882..49dcdbcd6e 100644 --- a/libraries/SPI/src/SPI.h +++ b/libraries/SPI/src/SPI.h @@ -174,16 +174,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 From aa5abaad419792c61dbab5101d78fe8496da0539 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Tue, 21 Nov 2023 10:04:26 +0100 Subject: [PATCH 6/8] feat(spi): allow to skip receive during transfer Linked to #912. Signed-off-by: Frederic Pillon --- libraries/SPI/README.md | 4 ++++ libraries/SPI/src/SPI.cpp | 21 +++++++++++++++------ libraries/SPI/src/SPI.h | 9 ++++++--- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/libraries/SPI/README.md b/libraries/SPI/README.md index 2849c787ac..a74b2fc272 100644 --- a/libraries/SPI/README.md +++ b/libraries/SPI/README.md @@ -35,6 +35,10 @@ 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: diff --git a/libraries/SPI/src/SPI.cpp b/libraries/SPI/src/SPI.cpp index 4bd483a5da..f42f2e88d7 100644 --- a/libraries/SPI/src/SPI.cpp +++ b/libraries/SPI/src/SPI.cpp @@ -156,11 +156,14 @@ void SPIClass::setClockDivider(uint8_t divider) * @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, false); + spi_transfer(&_spi, &data, sizeof(uint8_t), SPI_TRANSFER_TIMEOUT, skipReceive); return data; } @@ -168,9 +171,12 @@ 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; @@ -179,7 +185,7 @@ uint16_t SPIClass::transfer16(uint16_t data) data = tmp; } spi_transfer(&_spi, (uint8_t *)&data, sizeof(uint16_t), - SPI_TRANSFER_TIMEOUT, false); + SPI_TRANSFER_TIMEOUT, skipReceive); if (_spiSettings.bitOrder) { tmp = ((data & 0xff00) >> 8) | ((data & 0xff) << 8); @@ -195,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, false); + SPI_TRANSFER_TIMEOUT, skipReceive); } } diff --git a/libraries/SPI/src/SPI.h b/libraries/SPI/src/SPI.h index 49dcdbcd6e..d293d3ac46 100644 --- a/libraries/SPI/src/SPI.h +++ b/libraries/SPI/src/SPI.h @@ -38,6 +38,9 @@ extern "C" { #define SPI_CLOCK_DIV64 64 #define SPI_CLOCK_DIV128 128 +#define SPI_TRANSMITRECEIVE false +#define SPI_TRANSMITONLY true + // Defines a default timeout delay in milliseconds for the SPI transfer #ifndef SPI_TRANSFER_TIMEOUT #define SPI_TRANSFER_TIMEOUT 1000 @@ -131,9 +134,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. From 8a01b92bb15db6ec5a056d8cdad034a8134051a0 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Tue, 21 Nov 2023 09:48:56 +0100 Subject: [PATCH 7/8] doc(spi): update README.md Signed-off-by: Frederic Pillon --- libraries/SPI/README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libraries/SPI/README.md b/libraries/SPI/README.md index a74b2fc272..59564fd7e5 100644 --- a/libraries/SPI/README.md +++ b/libraries/SPI/README.md @@ -42,7 +42,8 @@ void setup() { #### 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++ From e781dc78a81b3f3fe92d4c49a86e9d59c375a850 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Thu, 23 Nov 2023 17:14:04 +0100 Subject: [PATCH 8/8] feat(spi): add SPISettings constructor with uint8_t for backward compatibility. Example with Adafruit GFX Library library. Signed-off-by: Frederic Pillon --- libraries/SPI/src/SPI.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libraries/SPI/src/SPI.h b/libraries/SPI/src/SPI.h index d293d3ac46..1c8bbc11cd 100644 --- a/libraries/SPI/src/SPI.h +++ b/libraries/SPI/src/SPI.h @@ -48,6 +48,11 @@ extern "C" { class SPISettings { public: + 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),