From de7a8426c9af7602b95ac9a04baf1d1a601dce84 Mon Sep 17 00:00:00 2001 From: Xelus22 Date: Sat, 13 Mar 2021 16:22:34 +1100 Subject: [PATCH 1/7] initial commit --- drivers/chibios/ws2812_spi.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/chibios/ws2812_spi.c b/drivers/chibios/ws2812_spi.c index 89df2987b548..09e01e1f3902 100644 --- a/drivers/chibios/ws2812_spi.c +++ b/drivers/chibios/ws2812_spi.c @@ -32,6 +32,14 @@ # endif #endif +// Define SPI config speed +#ifndef WS2812_SPI_DIVISOR +# if defined(STM32L4XX) +# define WS2812_SPI_DIVISOR (SPI_CR1_BR_2) // fpclk/32 +# else +# define WS2812_SPI_DIVISOR (SPI_CR1_BR_1 | SPI_CR1_BR_0) // fpclk/16 +#endif + #define BYTES_FOR_LED_BYTE 4 #define NB_COLORS 3 #define BYTES_FOR_LED (BYTES_FOR_LED_BYTE * NB_COLORS) @@ -83,7 +91,7 @@ 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_DIVISOR // baudrate : fpclk / 8 => 1tick is 0.32us (2.25 MHz) }; spiAcquireBus(&WS2812_SPI); /* Acquire ownership of the bus. */ From b129ed036255a4fb18547f0529aa6e80bf798225 Mon Sep 17 00:00:00 2001 From: Xelus22 Date: Sat, 13 Mar 2021 16:34:39 +1100 Subject: [PATCH 2/7] include circular buffer command --- drivers/chibios/ws2812_spi.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/chibios/ws2812_spi.c b/drivers/chibios/ws2812_spi.c index 09e01e1f3902..e89362b2ad55 100644 --- a/drivers/chibios/ws2812_spi.c +++ b/drivers/chibios/ws2812_spi.c @@ -40,6 +40,14 @@ # define WS2812_SPI_DIVISOR (SPI_CR1_BR_1 | SPI_CR1_BR_0) // fpclk/16 #endif +// Define SPI circular buffer +#ifndef WS2812_SPI_CIRCULAR_BUFFER +# if defined(STM32L4XX) +# define WS2812_SPI_CIRCULAR_BUFFER 1 +# else +# define WS2812_SPI_CIRCULAR_BUFFER 0 +#endif + #define BYTES_FOR_LED_BYTE 4 #define NB_COLORS 3 #define BYTES_FOR_LED (BYTES_FOR_LED_BYTE * NB_COLORS) @@ -90,7 +98,7 @@ void ws2812_init(void) { // TODO: more dynamic baudrate static const SPIConfig spicfg = { - 0, NULL, PAL_PORT(RGB_DI_PIN), PAL_PAD(RGB_DI_PIN), + WS2812_SPI_CIRCULAR_BUFFER, NULL, PAL_PORT(RGB_DI_PIN), PAL_PAD(RGB_DI_PIN), WS2812_SPI_DIVISOR // baudrate : fpclk / 8 => 1tick is 0.32us (2.25 MHz) }; From ef3ea89eb7fea0f2d0385be6bcd1a5ac2151f55a Mon Sep 17 00:00:00 2001 From: Xelus22 Date: Sat, 13 Mar 2021 17:05:25 +1100 Subject: [PATCH 3/7] add endif --- drivers/chibios/ws2812_spi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/chibios/ws2812_spi.c b/drivers/chibios/ws2812_spi.c index e89362b2ad55..294ca5fbf328 100644 --- a/drivers/chibios/ws2812_spi.c +++ b/drivers/chibios/ws2812_spi.c @@ -38,6 +38,7 @@ # define WS2812_SPI_DIVISOR (SPI_CR1_BR_2) // fpclk/32 # else # define WS2812_SPI_DIVISOR (SPI_CR1_BR_1 | SPI_CR1_BR_0) // fpclk/16 +# endif #endif // Define SPI circular buffer @@ -46,6 +47,7 @@ # define WS2812_SPI_CIRCULAR_BUFFER 1 # else # define WS2812_SPI_CIRCULAR_BUFFER 0 +# endif #endif #define BYTES_FOR_LED_BYTE 4 From bc3f7b5365d6187af4770a56e3eb7f339f8db123 Mon Sep 17 00:00:00 2001 From: Xelus22 Date: Sat, 13 Mar 2021 18:50:31 +1100 Subject: [PATCH 4/7] circular buffer mode --- drivers/chibios/ws2812_spi.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/chibios/ws2812_spi.c b/drivers/chibios/ws2812_spi.c index 294ca5fbf328..45012fd17dc8 100644 --- a/drivers/chibios/ws2812_spi.c +++ b/drivers/chibios/ws2812_spi.c @@ -107,6 +107,9 @@ void ws2812_init(void) { spiAcquireBus(&WS2812_SPI); /* Acquire ownership of the bus. */ spiStart(&WS2812_SPI, &spicfg); /* Setup transfer parameters. */ spiSelect(&WS2812_SPI); /* Slave Select assertion. */ +#if WS2812_SPI_CIRCULAR_BUFFER == 1 + spiStartSend(&WS2812_SPI, sizeof(txbuf) / sizeof(txbuf[0]), txbuf); +#endif } void ws2812_setleds(LED_TYPE* ledarray, uint16_t leds) { @@ -125,6 +128,8 @@ void ws2812_setleds(LED_TYPE* ledarray, uint16_t leds) { #ifdef WS2812_SPI_SYNC spiSend(&WS2812_SPI, sizeof(txbuf) / sizeof(txbuf[0]), txbuf); #else +# if WS2812_SPI_CIRCULAR_BUFFER == 0 spiStartSend(&WS2812_SPI, sizeof(txbuf) / sizeof(txbuf[0]), txbuf); +# endif #endif } From 13c0392bad785a180fcff7a0aae4cdf301224fee Mon Sep 17 00:00:00 2001 From: Xelus22 Date: Sat, 13 Mar 2021 22:35:05 +1100 Subject: [PATCH 5/7] remove untrue comment --- drivers/chibios/ws2812_spi.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/chibios/ws2812_spi.c b/drivers/chibios/ws2812_spi.c index 45012fd17dc8..95200d300110 100644 --- a/drivers/chibios/ws2812_spi.c +++ b/drivers/chibios/ws2812_spi.c @@ -33,6 +33,9 @@ #endif // Define SPI config speed +// baudrate should target 3.2MHz +// F072 fpclk = 48MHz +// 48/16 = 3Mhz #ifndef WS2812_SPI_DIVISOR # if defined(STM32L4XX) # define WS2812_SPI_DIVISOR (SPI_CR1_BR_2) // fpclk/32 @@ -101,7 +104,7 @@ void ws2812_init(void) { // TODO: more dynamic baudrate static const SPIConfig spicfg = { WS2812_SPI_CIRCULAR_BUFFER, NULL, PAL_PORT(RGB_DI_PIN), PAL_PAD(RGB_DI_PIN), - WS2812_SPI_DIVISOR // baudrate : fpclk / 8 => 1tick is 0.32us (2.25 MHz) + WS2812_SPI_DIVISOR }; spiAcquireBus(&WS2812_SPI); /* Acquire ownership of the bus. */ From 03f1eea5e2765d36d0d7963c6e37698a9467bc8c Mon Sep 17 00:00:00 2001 From: Xelus22 Date: Wed, 17 Mar 2021 23:32:06 +1100 Subject: [PATCH 6/7] revamp and add documentation --- docs/ws2812_driver.md | 19 ++++++++++++++++ drivers/chibios/ws2812_spi.c | 42 ++++++++++++++++++++++-------------- 2 files changed, 45 insertions(+), 16 deletions(-) diff --git a/docs/ws2812_driver.md b/docs/ws2812_driver.md index cca6827ec8d5..9dc1dd7d52ba 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 95200d300110..0eac167ea1a7 100644 --- a/drivers/chibios/ws2812_spi.c +++ b/drivers/chibios/ws2812_spi.c @@ -36,21 +36,31 @@ // baudrate should target 3.2MHz // F072 fpclk = 48MHz // 48/16 = 3Mhz -#ifndef WS2812_SPI_DIVISOR -# if defined(STM32L4XX) -# define WS2812_SPI_DIVISOR (SPI_CR1_BR_2) // fpclk/32 -# else -# define WS2812_SPI_DIVISOR (SPI_CR1_BR_1 | SPI_CR1_BR_0) // fpclk/16 -# endif +#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 -// Define SPI circular buffer -#ifndef WS2812_SPI_CIRCULAR_BUFFER -# if defined(STM32L4XX) -# define WS2812_SPI_CIRCULAR_BUFFER 1 -# else -# define WS2812_SPI_CIRCULAR_BUFFER 0 -# 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 @@ -103,14 +113,14 @@ void ws2812_init(void) { // TODO: more dynamic baudrate static const SPIConfig spicfg = { - WS2812_SPI_CIRCULAR_BUFFER, NULL, PAL_PORT(RGB_DI_PIN), PAL_PAD(RGB_DI_PIN), + 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. */ -#if WS2812_SPI_CIRCULAR_BUFFER == 1 +#ifdef WS2812_SPI_USE_CIRCULAR_BUFFER spiStartSend(&WS2812_SPI, sizeof(txbuf) / sizeof(txbuf[0]), txbuf); #endif } @@ -131,7 +141,7 @@ void ws2812_setleds(LED_TYPE* ledarray, uint16_t leds) { #ifdef WS2812_SPI_SYNC spiSend(&WS2812_SPI, sizeof(txbuf) / sizeof(txbuf[0]), txbuf); #else -# if WS2812_SPI_CIRCULAR_BUFFER == 0 +# ifndef WS2812_SPI_USE_CIRCULAR_BUFFER spiStartSend(&WS2812_SPI, sizeof(txbuf) / sizeof(txbuf[0]), txbuf); # endif #endif From f5c9216cd22e3aaf037f942b039827a4cba17425 Mon Sep 17 00:00:00 2001 From: Xelus22 <17491233+Xelus22@users.noreply.github.com> Date: Thu, 18 Mar 2021 02:24:15 +0000 Subject: [PATCH 7/7] do not allow WS2812_SPI_SYNC & CIRCULAR_BUFFER --- drivers/chibios/ws2812_spi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/chibios/ws2812_spi.c b/drivers/chibios/ws2812_spi.c index 0eac167ea1a7..bc0a54accedc 100644 --- a/drivers/chibios/ws2812_spi.c +++ b/drivers/chibios/ws2812_spi.c @@ -138,10 +138,10 @@ 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 -# ifndef WS2812_SPI_USE_CIRCULAR_BUFFER +# else spiStartSend(&WS2812_SPI, sizeof(txbuf) / sizeof(txbuf[0]), txbuf); # endif #endif