diff options
Diffstat (limited to 'platforms/chibios/drivers')
-rw-r--r-- | platforms/chibios/drivers/backlight_pwm.c | 2 | ||||
-rw-r--r-- | platforms/chibios/drivers/spi_master.c | 96 | ||||
-rw-r--r-- | platforms/chibios/drivers/spi_master.h | 9 | ||||
-rw-r--r-- | platforms/chibios/drivers/vendor/RP/RP2040/ws2812_vendor.c | 27 | ||||
-rw-r--r-- | platforms/chibios/drivers/ws2812_bitbang.c | 42 | ||||
-rw-r--r-- | platforms/chibios/drivers/ws2812_pwm.c | 28 | ||||
-rw-r--r-- | platforms/chibios/drivers/ws2812_spi.c | 25 |
7 files changed, 162 insertions, 67 deletions
diff --git a/platforms/chibios/drivers/backlight_pwm.c b/platforms/chibios/drivers/backlight_pwm.c index 01e6f71307..25fe7962b0 100644 --- a/platforms/chibios/drivers/backlight_pwm.c +++ b/platforms/chibios/drivers/backlight_pwm.c @@ -25,7 +25,7 @@ # define BACKLIGHT_PWM_CHANNEL 3 #endif -// Support for pins which are on TIM1_CH1N - requires STM32_PWM_USE_ADVANCED +// Support for pins which are on TIM1_CH1N #ifdef BACKLIGHT_PWM_COMPLEMENTARY_OUTPUT # if BACKLIGHT_ON_STATE == 1 # define PWM_OUTPUT_MODE PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW; diff --git a/platforms/chibios/drivers/spi_master.c b/platforms/chibios/drivers/spi_master.c index fcdbc9ecf0..cbe765e233 100644 --- a/platforms/chibios/drivers/spi_master.c +++ b/platforms/chibios/drivers/spi_master.c @@ -19,13 +19,33 @@ #include "timer.h" static bool spiStarted = false; - #if SPI_SELECT_MODE == SPI_SELECT_MODE_NONE -static pin_t currentSlavePin; +static pin_t current_slave_pin = NO_PIN; +static bool current_cs_active_low = true; #endif static SPIConfig spiConfig; +static inline void spi_select(void) { + spiSelect(&SPI_DRIVER); + +#if SPI_SELECT_MODE == SPI_SELECT_MODE_NONE + if (current_slave_pin != NO_PIN) { + gpio_write_pin(current_slave_pin, current_cs_active_low ? 0 : 1); + } +#endif +} + +static inline void spi_unselect(void) { +#if SPI_SELECT_MODE == SPI_SELECT_MODE_NONE + if (current_slave_pin != NO_PIN) { + gpio_write_pin(current_slave_pin, current_cs_active_low ? 1 : 0); + } +#endif + + spiUnselect(&SPI_DRIVER); +} + __attribute__((weak)) void spi_init(void) { static bool is_initialised = false; if (!is_initialised) { @@ -63,7 +83,7 @@ __attribute__((weak)) 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) { #if (SPI_USE_MUTUAL_EXCLUSION == TRUE) spiAcquireBus(&SPI_DRIVER); #endif // (SPI_USE_MUTUAL_EXCLUSION == TRUE) @@ -71,16 +91,15 @@ bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { if (spiStarted) { return false; } - #if SPI_SELECT_MODE != SPI_SELECT_MODE_NONE - if (slavePin == NO_PIN) { + if (start_config->slave_pin == NO_PIN) { return false; } #endif #if !(defined(WB32F3G71xx) || defined(WB32FQ95xx)) uint16_t roundedDivisor = 2; - while (roundedDivisor < divisor) { + while (roundedDivisor < start_config->divisor) { roundedDivisor <<= 1; } @@ -92,11 +111,11 @@ bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { #if defined(K20x) || defined(KL2x) spiConfig.tar0 = SPIx_CTARn_FMSZ(7) | SPIx_CTARn_ASC(1); - if (lsbFirst) { + if (start_config->lsb_first) { spiConfig.tar0 |= SPIx_CTARn_LSBFE; } - switch (mode) { + switch (start_config->mode) { case 0: break; case 1: @@ -141,11 +160,11 @@ bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { spiConfig.cr0 = SPI_CR0_SELOEN; spiConfig.cr1 = SPI_CR1_MODE | 8; // 8 bits and in master mode - if (lsbFirst) { + if (start_config->lsb_first) { spiConfig.cr1 |= SPI_CR1_FIRSTBIT; } - switch (mode) { + switch (start_config->mode) { case 0: spiConfig.cr1 |= SPI_CR1_FORMAT_MODE0; break; @@ -163,17 +182,17 @@ bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { spiConfig.cpr = (roundedDivisor - 1) >> 1; #elif defined(WB32F3G71xx) || defined(WB32FQ95xx) - if (!lsbFirst) { - osalDbgAssert(lsbFirst != FALSE, "unsupported lsbFirst"); + if (!start_config->lsb_first) { + osalDbgAssert(start_config->lsb_first != FALSE, "unsupported lsb_first"); } - if (divisor < 1) { + if (start_config->divisor < 1) { return false; } - spiConfig.SPI_BaudRatePrescaler = (divisor << 2); + spiConfig.SPI_BaudRatePrescaler = (start_config->divisor << 2); - switch (mode) { + switch (start_config->mode) { case 0: spiConfig.SPI_CPHA = SPI_CPHA_1Edge; spiConfig.SPI_CPOL = SPI_CPOL_Low; @@ -192,8 +211,8 @@ bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { break; } #elif defined(MCU_RP) - if (lsbFirst) { - osalDbgAssert(lsbFirst == false, "RP2040s PrimeCell SPI implementation does not support sending LSB first."); + if (start_config->lsb_first) { + osalDbgAssert(start_config->lsb_first == false, "RP2040s PrimeCell SPI implementation does not support sending LSB first."); } // Motorola frame format and 8bit transfer data size. @@ -203,7 +222,7 @@ bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { // passed divisor to be the only value to divide the input clock by. spiConfig.SSPCPSR = roundedDivisor; // Even number from 2 to 254 - switch (mode) { + switch (start_config->mode) { case 0: spiConfig.SSPCR0 &= ~SPI_SSPCR0_SPO; // Clock polarity: low spiConfig.SSPCR0 &= ~SPI_SSPCR0_SPH; // Clock phase: sample on first edge @@ -224,11 +243,11 @@ bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { #else spiConfig.cr1 = 0; - if (lsbFirst) { + if (start_config->lsb_first) { spiConfig.cr1 |= SPI_CR1_LSBFIRST; } - switch (mode) { + switch (start_config->mode) { case 0: break; case 1: @@ -271,31 +290,37 @@ bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { spiStarted = true; #if SPI_SELECT_MODE == SPI_SELECT_MODE_NONE - currentSlavePin = slavePin; + current_slave_pin = start_config->slave_pin; + current_cs_active_low = start_config->cs_active_low; #endif #if SPI_SELECT_MODE == SPI_SELECT_MODE_PAD - spiConfig.ssport = PAL_PORT(slavePin); - spiConfig.sspad = PAL_PAD(slavePin); - gpio_set_pin_output(slavePin); + spiConfig.ssport = PAL_PORT(start_config->slave_pin); + spiConfig.sspad = PAL_PAD(start_config->slave_pin); + gpio_set_pin_output(start_config->slave_pin); #elif SPI_SELECT_MODE == SPI_SELECT_MODE_NONE - if (slavePin != NO_PIN) { - gpio_set_pin_output(slavePin); + if (start_config->slave_pin != NO_PIN) { + gpio_set_pin_output(start_config->slave_pin); } #else # error "Unsupported SPI_SELECT_MODE" #endif spiStart(&SPI_DRIVER, &spiConfig); - spiSelect(&SPI_DRIVER); -#if SPI_SELECT_MODE == SPI_SELECT_MODE_NONE - if (slavePin != NO_PIN) { - gpio_write_pin_low(slavePin); - } -#endif + spi_select(); return true; } +bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { + 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); +} + spi_status_t spi_write(uint8_t data) { uint8_t rxData; spiExchange(&SPI_DRIVER, 1, &data, &rxData); @@ -322,12 +347,7 @@ spi_status_t spi_receive(uint8_t *data, uint16_t length) { void spi_stop(void) { if (spiStarted) { -#if SPI_SELECT_MODE == SPI_SELECT_MODE_NONE - if (currentSlavePin != NO_PIN) { - gpio_write_pin_high(currentSlavePin); - } -#endif - spiUnselect(&SPI_DRIVER); + spi_unselect(); spiStop(&SPI_DRIVER); spiStarted = false; } diff --git a/platforms/chibios/drivers/spi_master.h b/platforms/chibios/drivers/spi_master.h index 6a3ce481f1..4ad6144091 100644 --- a/platforms/chibios/drivers/spi_master.h +++ b/platforms/chibios/drivers/spi_master.h @@ -75,9 +75,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); diff --git a/platforms/chibios/drivers/vendor/RP/RP2040/ws2812_vendor.c b/platforms/chibios/drivers/vendor/RP/RP2040/ws2812_vendor.c index 41a5311719..6cf035e1f2 100644 --- a/platforms/chibios/drivers/vendor/RP/RP2040/ws2812_vendor.c +++ b/platforms/chibios/drivers/vendor/RP/RP2040/ws2812_vendor.c @@ -266,19 +266,36 @@ static inline void sync_ws2812_transfer(void) { busy_wait_until(LAST_TRANSFER); } -void ws2812_setleds(rgb_led_t* ledarray, uint16_t leds) { +ws2812_led_t ws2812_leds[WS2812_LED_COUNT]; + +void ws2812_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) { + ws2812_leds[index].r = red; + ws2812_leds[index].g = green; + ws2812_leds[index].b = blue; +#if defined(WS2812_RGBW) + ws2812_rgb_to_rgbw(&ws2812_leds[index]); +#endif +} + +void ws2812_set_color_all(uint8_t red, uint8_t green, uint8_t blue) { + for (int i = 0; i < WS2812_LED_COUNT; i++) { + ws2812_set_color(i, red, green, blue); + } +} + +void ws2812_flush(void) { sync_ws2812_transfer(); - for (int i = 0; i < leds; i++) { + for (int i = 0; i < WS2812_LED_COUNT; i++) { #if defined(WS2812_RGBW) - WS2812_BUFFER[i] = rgbw8888_to_u32(ledarray[i].r, ledarray[i].g, ledarray[i].b, ledarray[i].w); + WS2812_BUFFER[i] = rgbw8888_to_u32(ws2812_leds[i].r, ws2812_leds[i].g, ws2812_leds[i].b, ws2812_leds[i].w); #else - WS2812_BUFFER[i] = rgbw8888_to_u32(ledarray[i].r, ledarray[i].g, ledarray[i].b, 0); + WS2812_BUFFER[i] = rgbw8888_to_u32(ws2812_leds[i].r, ws2812_leds[i].g, ws2812_leds[i].b, 0); #endif } dmaChannelSetSourceX(dma_channel, (uint32_t)WS2812_BUFFER); - dmaChannelSetCounterX(dma_channel, leds); + dmaChannelSetCounterX(dma_channel, WS2812_LED_COUNT); dmaChannelSetModeX(dma_channel, RP_DMA_MODE_WS2812); dmaChannelEnableX(dma_channel); } diff --git a/platforms/chibios/drivers/ws2812_bitbang.c b/platforms/chibios/drivers/ws2812_bitbang.c index 96378ec0ac..fce1963d0a 100644 --- a/platforms/chibios/drivers/ws2812_bitbang.c +++ b/platforms/chibios/drivers/ws2812_bitbang.c @@ -76,33 +76,49 @@ void sendByte(uint8_t byte) { } } +ws2812_led_t ws2812_leds[WS2812_LED_COUNT]; + void ws2812_init(void) { palSetLineMode(WS2812_DI_PIN, WS2812_OUTPUT_MODE); } -// Setleds for standard RGB -void ws2812_setleds(rgb_led_t *ledarray, uint16_t leds) { +void ws2812_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) { + ws2812_leds[index].r = red; + ws2812_leds[index].g = green; + ws2812_leds[index].b = blue; +#if defined(WS2812_RGBW) + ws2812_rgb_to_rgbw(&ws2812_leds[index]); +#endif +} + +void ws2812_set_color_all(uint8_t red, uint8_t green, uint8_t blue) { + for (int i = 0; i < WS2812_LED_COUNT; i++) { + ws2812_set_color(i, red, green, blue); + } +} + +void ws2812_flush(void) { // this code is very time dependent, so we need to disable interrupts chSysLock(); - for (uint8_t i = 0; i < leds; i++) { + for (int i = 0; i < WS2812_LED_COUNT; i++) { // WS2812 protocol dictates grb order #if (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_GRB) - sendByte(ledarray[i].g); - sendByte(ledarray[i].r); - sendByte(ledarray[i].b); + sendByte(ws2812_leds[i].g); + sendByte(ws2812_leds[i].r); + sendByte(ws2812_leds[i].b); #elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_RGB) - sendByte(ledarray[i].r); - sendByte(ledarray[i].g); - sendByte(ledarray[i].b); + sendByte(ws2812_leds[i].r); + sendByte(ws2812_leds[i].g); + sendByte(ws2812_leds[i].b); #elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_BGR) - sendByte(ledarray[i].b); - sendByte(ledarray[i].g); - sendByte(ledarray[i].r); + sendByte(ws2812_leds[i].b); + sendByte(ws2812_leds[i].g); + sendByte(ws2812_leds[i].r); #endif #ifdef WS2812_RGBW - sendByte(ledarray[i].w); + sendByte(ws2812_leds[i].w); #endif } diff --git a/platforms/chibios/drivers/ws2812_pwm.c b/platforms/chibios/drivers/ws2812_pwm.c index 1e9d2ebb41..dc0e309163 100644 --- a/platforms/chibios/drivers/ws2812_pwm.c +++ b/platforms/chibios/drivers/ws2812_pwm.c @@ -387,13 +387,29 @@ void ws2812_write_led_rgbw(uint16_t led_number, uint8_t r, uint8_t g, uint8_t b, } } -// Setleds for standard RGB -void ws2812_setleds(rgb_led_t* ledarray, uint16_t leds) { - for (uint16_t i = 0; i < leds; i++) { -#ifdef WS2812_RGBW - ws2812_write_led_rgbw(i, ledarray[i].r, ledarray[i].g, ledarray[i].b, ledarray[i].w); +ws2812_led_t ws2812_leds[WS2812_LED_COUNT]; + +void ws2812_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) { + ws2812_leds[index].r = red; + ws2812_leds[index].g = green; + ws2812_leds[index].b = blue; +#if defined(WS2812_RGBW) + ws2812_rgb_to_rgbw(&ws2812_leds[index]); +#endif +} + +void ws2812_set_color_all(uint8_t red, uint8_t green, uint8_t blue) { + for (int i = 0; i < WS2812_LED_COUNT; i++) { + ws2812_set_color(i, red, green, blue); + } +} + +void ws2812_flush(void) { + for (int i = 0; i < WS2812_LED_COUNT; i++) { +#if defined(WS2812_RGBW) + ws2812_write_led_rgbw(i, ws2812_leds[i].r, ws2812_leds[i].g, ws2812_leds[i].b, ws2812_leds[i].w); #else - ws2812_write_led(i, ledarray[i].r, ledarray[i].g, ledarray[i].b); + ws2812_write_led(i, ws2812_leds[i].r, ws2812_leds[i].g, ws2812_leds[i].b); #endif } } diff --git a/platforms/chibios/drivers/ws2812_spi.c b/platforms/chibios/drivers/ws2812_spi.c index 9896f9e69d..a1357edec5 100644 --- a/platforms/chibios/drivers/ws2812_spi.c +++ b/platforms/chibios/drivers/ws2812_spi.c @@ -106,7 +106,7 @@ static uint8_t get_protocol_eq(uint8_t data, int pos) { return eq; } -static void set_led_color_rgb(rgb_led_t color, int pos) { +static void set_led_color_rgb(ws2812_led_t color, int pos) { uint8_t* tx_start = &txbuf[PREAMBLE_SIZE]; #if (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_GRB) @@ -137,6 +137,8 @@ static void set_led_color_rgb(rgb_led_t color, int pos) { #endif } +ws2812_led_t ws2812_leds[WS2812_LED_COUNT]; + void ws2812_init(void) { palSetLineMode(WS2812_DI_PIN, WS2812_MOSI_OUTPUT_MODE); @@ -187,9 +189,24 @@ void ws2812_init(void) { #endif } -void ws2812_setleds(rgb_led_t* ledarray, uint16_t leds) { - for (uint8_t i = 0; i < leds; i++) { - set_led_color_rgb(ledarray[i], i); +void ws2812_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) { + ws2812_leds[index].r = red; + ws2812_leds[index].g = green; + ws2812_leds[index].b = blue; +#if defined(WS2812_RGBW) + ws2812_rgb_to_rgbw(&ws2812_leds[index]); +#endif +} + +void ws2812_set_color_all(uint8_t red, uint8_t green, uint8_t blue) { + for (int i = 0; i < WS2812_LED_COUNT; i++) { + ws2812_set_color(i, red, green, blue); + } +} + +void ws2812_flush(void) { + for (int i = 0; i < WS2812_LED_COUNT; i++) { + set_led_color_rgb(ws2812_leds[i], i); } // Send async - each led takes ~0.03ms, 50 leds ~1.5ms, animations flushing faster than send will cause issues. |