diff options
author | Dasky <[email protected]> | 2024-09-09 23:44:35 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2024-09-10 08:44:35 +1000 |
commit | 2c7bf34d09247c2f306f0068e34a2a3a4f3f58e1 (patch) | |
tree | 63052adc2c43f2e676bed9dc4957f961f3cb4eff /platforms/avr | |
parent | 3aaa086ac8a50ed7fc501c2dc93c1d195b63dcc3 (diff) | |
download | qmk_firmware-2c7bf34d09247c2f306f0068e34a2a3a4f3f58e1.tar.gz qmk_firmware-2c7bf34d09247c2f306f0068e34a2a3a4f3f58e1.zip |
Allow for inverted SPI CS logic (#23699)
Diffstat (limited to 'platforms/avr')
-rw-r--r-- | platforms/avr/drivers/spi_master.c | 84 | ||||
-rw-r--r-- | platforms/avr/drivers/spi_master.h | 9 |
2 files changed, 61 insertions, 32 deletions
diff --git a/platforms/avr/drivers/spi_master.c b/platforms/avr/drivers/spi_master.c index 74b847c71a..ba7d782ab0 100644 --- a/platforms/avr/drivers/spi_master.c +++ b/platforms/avr/drivers/spi_master.c @@ -36,9 +36,18 @@ # define SPI_TIMEOUT 100 #endif -static pin_t currentSlavePin = NO_PIN; -static uint8_t currentSlaveConfig = 0; -static bool currentSlave2X = false; +static pin_t current_slave_pin = NO_PIN; +static bool current_cs_active_low = true; +static uint8_t current_slave_config = 0; +static bool current_slave_2x = false; + +static inline void spi_select(void) { + gpio_write_pin(current_slave_pin, current_cs_active_low ? 0 : 1); +} + +static inline void spi_unselect(void) { + gpio_write_pin(current_slave_pin, current_cs_active_low ? 1 : 0); +} void spi_init(void) { gpio_write_pin_high(SPI_SS_PIN); @@ -50,63 +59,74 @@ void spi_init(void) { } bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { - if (currentSlavePin != NO_PIN || slavePin == NO_PIN) { + spi_start_config_t start_config = {0}; + start_config.slave_pin = slavePin; + start_config.lsb_first = lsbFirst; + start_config.mode = mode; + start_config.divisor = divisor; + start_config.cs_active_low = true; + return spi_start_extended(&start_config); +} + +bool spi_start_extended(spi_start_config_t *start_config) { + if (current_slave_pin != NO_PIN || start_config->slave_pin == NO_PIN) { return false; } - currentSlaveConfig = 0; + current_slave_config = 0; - if (lsbFirst) { - currentSlaveConfig |= _BV(DORD); + if (start_config->lsb_first) { + current_slave_config |= _BV(DORD); } - switch (mode) { + switch (start_config->mode) { case 1: - currentSlaveConfig |= _BV(CPHA); + current_slave_config |= _BV(CPHA); break; case 2: - currentSlaveConfig |= _BV(CPOL); + current_slave_config |= _BV(CPOL); break; case 3: - currentSlaveConfig |= (_BV(CPOL) | _BV(CPHA)); + current_slave_config |= (_BV(CPOL) | _BV(CPHA)); break; } uint16_t roundedDivisor = 1; - while (roundedDivisor < divisor) { + while (roundedDivisor < start_config->divisor) { roundedDivisor <<= 1; } switch (roundedDivisor) { case 16: - currentSlaveConfig |= _BV(SPR0); + current_slave_config |= _BV(SPR0); break; case 64: - currentSlaveConfig |= _BV(SPR1); + current_slave_config |= _BV(SPR1); break; case 128: - currentSlaveConfig |= (_BV(SPR1) | _BV(SPR0)); + current_slave_config |= (_BV(SPR1) | _BV(SPR0)); break; case 2: - currentSlave2X = true; + current_slave_2x = true; break; case 8: - currentSlave2X = true; - currentSlaveConfig |= _BV(SPR0); + current_slave_2x = true; + current_slave_config |= _BV(SPR0); break; case 32: - currentSlave2X = true; - currentSlaveConfig |= _BV(SPR1); + current_slave_2x = true; + current_slave_config |= _BV(SPR1); break; } - SPCR |= currentSlaveConfig; - if (currentSlave2X) { + SPCR |= current_slave_config; + if (current_slave_2x) { SPSR |= _BV(SPI2X); } - currentSlavePin = slavePin; - gpio_set_pin_output(currentSlavePin); - gpio_write_pin_low(currentSlavePin); + current_slave_pin = start_config->slave_pin; + current_cs_active_low = start_config->cs_active_low; + gpio_set_pin_output(current_slave_pin); + spi_select(); return true; } @@ -168,13 +188,13 @@ spi_status_t spi_receive(uint8_t *data, uint16_t length) { } void spi_stop(void) { - if (currentSlavePin != NO_PIN) { - gpio_set_pin_output(currentSlavePin); - gpio_write_pin_high(currentSlavePin); - currentSlavePin = NO_PIN; + if (current_slave_pin != NO_PIN) { + gpio_set_pin_output(current_slave_pin); + spi_unselect(); + current_slave_pin = NO_PIN; SPSR &= ~(_BV(SPI2X)); - SPCR &= ~(currentSlaveConfig); - currentSlaveConfig = 0; - currentSlave2X = false; + SPCR &= ~(current_slave_config); + current_slave_config = 0; + current_slave_2x = false; } } diff --git a/platforms/avr/drivers/spi_master.h b/platforms/avr/drivers/spi_master.h index 8a30f47ae4..ebbf7ddeab 100644 --- a/platforms/avr/drivers/spi_master.h +++ b/platforms/avr/drivers/spi_master.h @@ -41,9 +41,18 @@ typedef int16_t spi_status_t; #ifdef __cplusplus extern "C" { #endif +typedef struct spi_start_config_t { + pin_t slave_pin; + bool lsb_first; + uint8_t mode; + uint16_t divisor; + bool cs_active_low; +} spi_start_config_t; + void spi_init(void); bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor); +bool spi_start_extended(spi_start_config_t *start_config); spi_status_t spi_write(uint8_t data); |