diff options
| -rw-r--r-- | docs/ws2812_driver.md | 19 | ||||
| -rw-r--r-- | drivers/chibios/ws2812_spi.c | 44 | 
2 files changed, 59 insertions, 4 deletions
| diff --git a/docs/ws2812_driver.md b/docs/ws2812_driver.md index fa14f02fdb..e69400364c 100644 --- a/docs/ws2812_driver.md +++ b/docs/ws2812_driver.md @@ -77,6 +77,25 @@ Configure the hardware via your config.h:  You must also turn on the SPI feature in your halconf.h and mcuconf.h +#### Circular Buffer Mode +Some boards may flicker while in the normal buffer mode. To fix this issue, circular buffer mode may be used to rectify the issue.  + +By default, the circular buffer mode is disabled. + +To enable this alternative buffer mode, place this into your `config.h` file: +```c +#define WS2812_SPI_USE_CIRCULAR_BUFFER +``` + +#### Setting baudrate with divisor +To adjust the baudrate at which the SPI peripheral is configured, users will need to derive the target baudrate from the clock tree provided by STM32CubeMX. + +Only divisors of 2, 4, 8, 16, 32, 64, 128 and 256 are supported by hardware. + +|Define              |Default|Description                          | +|--------------------|-------|-------------------------------------| +|`WS2812_SPI_DIVISOR`|`16`   |SPI source clock peripheral divisor  | +  #### Testing Notes  While not an exhaustive list, the following table provides the scenarios that have been partially validated: diff --git a/drivers/chibios/ws2812_spi.c b/drivers/chibios/ws2812_spi.c index 89df2987b5..bc0a54acce 100644 --- a/drivers/chibios/ws2812_spi.c +++ b/drivers/chibios/ws2812_spi.c @@ -32,6 +32,37 @@  #    endif  #endif +// Define SPI config speed +// baudrate should target 3.2MHz +// F072 fpclk = 48MHz  +// 48/16 = 3Mhz +#if WS2812_SPI_DIVISOR == 2 +#    define WS2812_SPI_DIVISOR (0) +#elif WS2812_SPI_DIVISOR == 4 +#    define WS2812_SPI_DIVISOR (SPI_CR1_BR_0) +#elif WS2812_SPI_DIVISOR == 8 +#    define WS2812_SPI_DIVISOR (SPI_CR1_BR_1) +#elif WS2812_SPI_DIVISOR == 16                                  //same as default +#    define WS2812_SPI_DIVISOR (SPI_CR1_BR_1 | SPI_CR1_BR_0) +#elif WS2812_SPI_DIVISOR == 32 +#    define WS2812_SPI_DIVISOR (SPI_CR1_BR_2) +#elif WS2812_SPI_DIVISOR == 64 +#    define WS2812_SPI_DIVISOR (SPI_CR1_BR_2 | SPI_CR1_BR_0) +#elif WS2812_SPI_DIVISOR == 128 +#    define WS2812_SPI_DIVISOR (SPI_CR1_BR_2 | SPI_CR1_BR_1) +#elif WS2812_SPI_DIVISOR == 256 +#    define WS2812_SPI_DIVISOR (SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_BR_0) +#else +#    define WS2812_SPI_DIVISOR (SPI_CR1_BR_1 | SPI_CR1_BR_0)    //default +#endif + +// Use SPI circular buffer +#ifdef WS2812_SPI_USE_CIRCULAR_BUFFER +#    define WS2812_SPI_BUFFER_MODE 1    //circular buffer +#else +#    define WS2812_SPI_BUFFER_MODE 0    //normal buffer +#endif +  #define BYTES_FOR_LED_BYTE 4  #define NB_COLORS 3  #define BYTES_FOR_LED (BYTES_FOR_LED_BYTE * NB_COLORS) @@ -82,13 +113,16 @@ void ws2812_init(void) {      // TODO: more dynamic baudrate      static const SPIConfig spicfg = { -        0, NULL, PAL_PORT(RGB_DI_PIN), PAL_PAD(RGB_DI_PIN), -        SPI_CR1_BR_1 | SPI_CR1_BR_0  // baudrate : fpclk / 8 => 1tick is 0.32us (2.25 MHz) +        WS2812_SPI_BUFFER_MODE, NULL, PAL_PORT(RGB_DI_PIN), PAL_PAD(RGB_DI_PIN), +        WS2812_SPI_DIVISOR      };      spiAcquireBus(&WS2812_SPI);     /* Acquire ownership of the bus.    */      spiStart(&WS2812_SPI, &spicfg); /* Setup transfer parameters.       */      spiSelect(&WS2812_SPI);         /* Slave Select assertion.          */ +#ifdef WS2812_SPI_USE_CIRCULAR_BUFFER +    spiStartSend(&WS2812_SPI, sizeof(txbuf) / sizeof(txbuf[0]), txbuf); +#endif  }  void ws2812_setleds(LED_TYPE* ledarray, uint16_t leds) { @@ -104,9 +138,11 @@ void ws2812_setleds(LED_TYPE* ledarray, uint16_t leds) {      // Send async - each led takes ~0.03ms, 50 leds ~1.5ms, animations flushing faster than send will cause issues.      // Instead spiSend can be used to send synchronously (or the thread logic can be added back). -#ifdef WS2812_SPI_SYNC +#ifndef WS2812_SPI_USE_CIRCULAR_BUFFER +#    ifdef WS2812_SPI_SYNC      spiSend(&WS2812_SPI, sizeof(txbuf) / sizeof(txbuf[0]), txbuf); -#else +#    else      spiStartSend(&WS2812_SPI, sizeof(txbuf) / sizeof(txbuf[0]), txbuf); +#    endif  #endif  } | 
