diff --git a/platform/drivers/SPI/spi_bitbang.c b/platform/drivers/SPI/spi_bitbang.c index 4ca6b5d9..6590c2ea 100644 --- a/platform/drivers/SPI/spi_bitbang.c +++ b/platform/drivers/SPI/spi_bitbang.c @@ -21,44 +21,18 @@ #include #include "spi_bitbang.h" -typedef uint8_t (*sendRecv_impl)(struct spiConfig *cfg, uint8_t data); - -static uint8_t sendRecv_clkRising(struct spiConfig *cfg, uint8_t data) +uint8_t spiBitbang_sendRecv(const void *priv, uint8_t data) { + const struct spiConfig *cfg = (const struct spiConfig *) priv; uint8_t incoming = 0; for(uint8_t cnt = 0; cnt < 8; cnt++) { - // Setup new output towards the peripheral - if((data & 0x80) != 0) - gpio_setPin(cfg->mosi.port, cfg->mosi.pin); + // Clock inactive edge + if((cfg->flags & SPI_FLAG_CPHA) != 0) + gpio_setPin(cfg->clk.port, cfg->clk.pin); else - gpio_clearPin(cfg->mosi.port, cfg->mosi.pin); - - // Sample the current incoming bit from the peripheral - data <<= 1; - incoming <<= 1; - incoming |= gpio_readPin(cfg->miso.port, cfg->miso.pin); - - // One clock cycle, peripheral reads the new bit and updates its output - // bit - delayUs(cfg->clkPeriod); - gpio_setPin(cfg->clk.port, cfg->clk.pin); - delayUs(cfg->clkPeriod); - gpio_clearPin(cfg->clk.port, cfg->clk.pin); - } - - return incoming; -} - -static uint8_t sendRecv_clkFalling(struct spiConfig *cfg, uint8_t data) -{ - uint8_t incoming = 0; - - for(uint8_t cnt = 0; cnt < 8; cnt++) - { - // Clock rising edge (inactive edge) - gpio_setPin(cfg->clk.port, cfg->clk.pin); + gpio_clearPin(cfg->clk.port, cfg->clk.pin); // Setup data output if((data & 0x80) != 0) @@ -71,10 +45,14 @@ static uint8_t sendRecv_clkFalling(struct spiConfig *cfg, uint8_t data) incoming <<= 1; incoming |= gpio_readPin(cfg->miso.port, cfg->miso.pin); - // Clock falling edge, peripheral reads new data and updates its output - // line delayUs(cfg->clkPeriod); - gpio_clearPin(cfg->clk.port, cfg->clk.pin); + + // Clock active edge + if((cfg->flags & SPI_FLAG_CPHA) != 0) + gpio_clearPin(cfg->clk.port, cfg->clk.pin); + else + gpio_setPin(cfg->clk.port, cfg->clk.pin); + delayUs(cfg->clkPeriod); } @@ -82,9 +60,12 @@ static uint8_t sendRecv_clkFalling(struct spiConfig *cfg, uint8_t data) } -int spiBitbang_init(const struct spiDevice* dev) +int spiBitbang_init(const struct spiCustomDevice *dev) { - struct spiConfig *cfg = (struct spiConfig *) dev->priv; + const struct spiConfig *cfg = (const struct spiConfig *) dev->priv; + + // Basic driver init + spi_init((const struct spiDevice *) dev); // Setup MOSI and clock lines as output, low level gpio_setMode(cfg->clk.port, cfg->clk.pin, OUTPUT); @@ -96,84 +77,17 @@ int spiBitbang_init(const struct spiDevice* dev) if((cfg->flags & SPI_HALF_DUPLEX) == 0) gpio_setMode(cfg->miso.port, cfg->miso.pin, INPUT); - // Set initial state of clock line to high if requested - if((cfg->flags & SPI_FLAG_CPOL) != 0) - gpio_clearPin(cfg->clk.port, cfg->clk.pin); - - if(dev->mutex != NULL) - pthread_mutex_init((pthread_mutex_t *) dev->mutex, NULL); - return 0; - } -void spiBitbang_terminate(const struct spiDevice* dev) +void spiBitbang_terminate(const struct spiCustomDevice* dev) { - struct spiConfig *cfg = (struct spiConfig *) dev->priv; + const struct spiConfig *cfg = (const struct spiConfig *) dev->priv; // Set clock and MOSI back to Hi-Z state gpio_setMode(cfg->clk.port, cfg->clk.pin, INPUT); gpio_setMode(cfg->mosi.port, cfg->mosi.pin, INPUT); - if(dev->mutex != NULL) - pthread_mutex_destroy((pthread_mutex_t *) dev->mutex); -} - -int spiBitbang_impl(const struct spiDevice *dev, const void *txBuf, - const size_t txSize, void *rxBuf, const size_t rxSize) -{ - struct spiConfig *cfg = (struct spiConfig *) dev->priv; - const uint8_t *txData = (const uint8_t *) txBuf; - uint8_t *rxData = (uint8_t *) rxBuf; - sendRecv_impl spi_sendRecv; - - if((cfg->flags & SPI_FLAG_CPHA) != 0) - spi_sendRecv = &sendRecv_clkFalling; - else - spi_sendRecv = &sendRecv_clkRising; - - // Send only - if((rxBuf == NULL) || (rxSize == 0)) - { - for(size_t i = 0; i < txSize; i++) - spi_sendRecv(cfg, txData[i]); - - return 0; - } - - // Receive only - if((txBuf == NULL) || (txSize == 0)) - { - for(size_t i = 0; i < rxSize; i++) - rxData[i] = spi_sendRecv(cfg, 0x00); - - return 0; - } - - // Transmit and receive - size_t txRxSize = (txSize < rxSize) ? txSize : rxSize; - for(size_t i = 0; i < txRxSize; i++) - rxData[i] = spi_sendRecv(cfg, txData[i]); - - // Still something to send? - if(txSize > txRxSize) - { - for(size_t i = 0; i < (txSize - txRxSize); i++) - { - size_t pos = txRxSize + i; - spi_sendRecv(cfg, txData[pos]); - } - } - - // Still something to receive? - if(rxSize > txRxSize) - { - for(size_t i = 0; i < (rxSize - txRxSize); i++) - { - size_t pos = txRxSize + i; - rxData[pos] = spi_sendRecv(cfg, 0x00); - } - } - - return 0; + // Final driver cleanup + spi_terminate((const struct spiDevice *) dev); } diff --git a/platform/drivers/SPI/spi_bitbang.h b/platform/drivers/SPI/spi_bitbang.h index b1df4260..08e1b976 100644 --- a/platform/drivers/SPI/spi_bitbang.h +++ b/platform/drivers/SPI/spi_bitbang.h @@ -23,6 +23,7 @@ #include #include +#include "spi_custom.h" #ifdef __cplusplus extern "C" { @@ -50,38 +51,33 @@ struct spiConfig * Instantiate an SPI bitbang device. * * @param name: device name. - * @param mutx: pointer to mutex, or NULL. * @param cfg: driver configuration data. + * @param mutx: pointer to mutex, or NULL. */ -#define SPI_BITBANG_DEVICE_DEFINE(name, mutx, cfg) \ -int spiBitbang_impl(const struct spiDevice *dev, const void *txBuf, \ - const size_t txSize, void *rxBuf, const size_t rxSize); \ -const struct spiDevice name = \ -{ \ - .transfer = spiBitbang_impl, \ - .priv = &cfg, \ - .mutex = mutx, \ +#define SPI_BITBANG_DEVICE_DEFINE(name, cfg, mutx) \ +uint8_t spiBitbang_sendRecv(const void *priv, uint8_t data); \ +const struct spiCustomDevice name = \ +{ \ + .transfer = spiCustom_transfer, \ + .priv = &cfg, \ + .mutex = mutx, \ + .spiFunc = spiBitbang_sendRecv \ }; /** * Initialise a bitbang SPI driver. - * Is left to application code to change the operating mode and alternate function - * mapping of the corresponding gpio lines. * * @param dev: SPI bitbang device descriptor. - * @param speed: SPI clock speed. - * @param flags: SPI configuration flags. * @return zero on success, a negative error code otherwise. */ -int spiBitbang_init(const struct spiDevice *dev); +int spiBitbang_init(const struct spiCustomDevice *dev); /** * Shut down a bitbang SPI driver. * * @param dev: SPI bitbang device descriptor. */ -void spiBitbang_terminate(const struct spiDevice *dev); - +void spiBitbang_terminate(const struct spiCustomDevice *dev); #ifdef __cplusplus }