Skip to content

Commit

Permalink
Merge pull request stm32duino#2204 from fpistm/spi_fixup
Browse files Browse the repository at this point in the history
[spi]: Keep constexpr constructor
  • Loading branch information
fpistm committed Nov 24, 2023
2 parents a46472a + e781dc7 commit cd3043f
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 167 deletions.
14 changes: 8 additions & 6 deletions libraries/SPI/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)`
Expand All @@ -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++
Expand Down
108 changes: 43 additions & 65 deletions libraries/SPI/src/SPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

/**
Expand All @@ -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);
}
}

Expand All @@ -89,23 +89,23 @@ void SPIClass::endTransaction(void)
/**
* @brief Deinitialize the SPI instance and stop it.
*/
void SPIClass::end()
void SPIClass::end(void)
{
spi_deinit(&_spi);
}

/**
* @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);
}

/**
Expand All @@ -119,71 +119,75 @@ void SPIClass::setBitOrder(BitOrder bitOrder)
* SPI_MODE2 1 0
* SPI_MODE3 1 1
*/

void SPIClass::setDataMode(uint8_t mode)
{
setDataMode((SPIMode)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;
}

/**
* @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;
}
Expand All @@ -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);
}
}

Expand Down Expand Up @@ -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 */
Expand Down
Loading

0 comments on commit cd3043f

Please sign in to comment.