From 6f7466b6dd72e161b61683e26b7720421d8cc9bd Mon Sep 17 00:00:00 2001 From: Xelus22 <17491233+Xelus22@users.noreply.github.com> Date: Fri, 19 Mar 2021 08:29:18 +0000 Subject: ARM WS2812 SPI config (baudrate and circular buffer) (#12216) * initial commit * include circular buffer command * add endif * circular buffer mode * remove untrue comment * revamp and add documentation * do not allow WS2812_SPI_SYNC & CIRCULAR_BUFFER --- drivers/chibios/ws2812_spi.c | 44 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) (limited to 'drivers/chibios/ws2812_spi.c') 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 } -- cgit v1.2.3 From 32f0567ca5e0d7db78ce316df6b5a18546c525b7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 19 Mar 2021 16:24:36 +0000 Subject: Format code according to conventions (#12292) Co-authored-by: QMK Bot --- drivers/chibios/ws2812_spi.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'drivers/chibios/ws2812_spi.c') diff --git a/drivers/chibios/ws2812_spi.c b/drivers/chibios/ws2812_spi.c index bc0a54acce..e02cbabc02 100644 --- a/drivers/chibios/ws2812_spi.c +++ b/drivers/chibios/ws2812_spi.c @@ -34,7 +34,7 @@ // Define SPI config speed // baudrate should target 3.2MHz -// F072 fpclk = 48MHz +// F072 fpclk = 48MHz // 48/16 = 3Mhz #if WS2812_SPI_DIVISOR == 2 # define WS2812_SPI_DIVISOR (0) @@ -42,7 +42,7 @@ # 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 +#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) @@ -53,14 +53,14 @@ #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 +# 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 +# define WS2812_SPI_BUFFER_MODE 1 // circular buffer #else -# define WS2812_SPI_BUFFER_MODE 0 //normal buffer +# define WS2812_SPI_BUFFER_MODE 0 // normal buffer #endif #define BYTES_FOR_LED_BYTE 4 @@ -112,10 +112,7 @@ void ws2812_init(void) { palSetLineMode(RGB_DI_PIN, WS2812_OUTPUT_MODE); // TODO: more dynamic baudrate - static const SPIConfig spicfg = { - WS2812_SPI_BUFFER_MODE, NULL, PAL_PORT(RGB_DI_PIN), PAL_PAD(RGB_DI_PIN), - WS2812_SPI_DIVISOR - }; + static const SPIConfig spicfg = {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. */ -- cgit v1.2.3 From 1bb7af4d446174b7181c9bb22dbd14c93642ea10 Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Tue, 17 Aug 2021 23:43:09 +0100 Subject: Relocate platform specific drivers (#13894) * Relocate platform specific drivers * Move stm eeprom * Tidy up slightly --- drivers/chibios/ws2812_spi.c | 159 ------------------------------------------- 1 file changed, 159 deletions(-) delete mode 100644 drivers/chibios/ws2812_spi.c (limited to 'drivers/chibios/ws2812_spi.c') diff --git a/drivers/chibios/ws2812_spi.c b/drivers/chibios/ws2812_spi.c deleted file mode 100644 index 377a929b94..0000000000 --- a/drivers/chibios/ws2812_spi.c +++ /dev/null @@ -1,159 +0,0 @@ -#include "quantum.h" -#include "ws2812.h" - -/* Adapted from https://github.com/gamazeps/ws2812b-chibios-SPIDMA/ */ - -#ifdef RGBW -# error "RGBW not supported" -#endif - -// Define the spi your LEDs are plugged to here -#ifndef WS2812_SPI -# define WS2812_SPI SPID1 -#endif - -#ifndef WS2812_SPI_MOSI_PAL_MODE -# define WS2812_SPI_MOSI_PAL_MODE 5 -#endif - -#ifndef WS2812_SPI_SCK_PAL_MODE -# define WS2812_SPI_SCK_PAL_MODE 5 -#endif - -// Push Pull or Open Drain Configuration -// Default Push Pull -#ifndef WS2812_EXTERNAL_PULLUP -# if defined(USE_GPIOV1) -# define WS2812_MOSI_OUTPUT_MODE PAL_MODE_STM32_ALTERNATE_PUSHPULL -# else -# define WS2812_MOSI_OUTPUT_MODE PAL_MODE_ALTERNATE(WS2812_SPI_MOSI_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL -# endif -#else -# if defined(USE_GPIOV1) -# define WS2812_MOSI_OUTPUT_MODE PAL_MODE_STM32_ALTERNATE_OPENDRAIN -# else -# define WS2812_MOSI_OUTPUT_MODE PAL_MODE_ALTERNATE(WS2812_SPI_MOSI_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN -# 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 - -#if defined(USE_GPIOV1) -# define WS2812_SCK_OUTPUT_MODE PAL_MODE_STM32_ALTERNATE_PUSHPULL -#else -# define WS2812_SCK_OUTPUT_MODE PAL_MODE_ALTERNATE(WS2812_SPI_SCK_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL -#endif - -#define BYTES_FOR_LED_BYTE 4 -#define NB_COLORS 3 -#define BYTES_FOR_LED (BYTES_FOR_LED_BYTE * NB_COLORS) -#define DATA_SIZE (BYTES_FOR_LED * RGBLED_NUM) -#define RESET_SIZE (1000 * WS2812_TRST_US / (2 * 1250)) -#define PREAMBLE_SIZE 4 - -static uint8_t txbuf[PREAMBLE_SIZE + DATA_SIZE + RESET_SIZE] = {0}; - -/* - * As the trick here is to use the SPI to send a huge pattern of 0 and 1 to - * the ws2812b protocol, we use this helper function to translate bytes into - * 0s and 1s for the LED (with the appropriate timing). - */ -static uint8_t get_protocol_eq(uint8_t data, int pos) { - uint8_t eq = 0; - if (data & (1 << (2 * (3 - pos)))) - eq = 0b1110; - else - eq = 0b1000; - if (data & (2 << (2 * (3 - pos)))) - eq += 0b11100000; - else - eq += 0b10000000; - return eq; -} - -static void set_led_color_rgb(LED_TYPE color, int pos) { - uint8_t* tx_start = &txbuf[PREAMBLE_SIZE]; - -#if (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_GRB) - for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + j] = get_protocol_eq(color.g, j); - for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE + j] = get_protocol_eq(color.r, j); - for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE * 2 + j] = get_protocol_eq(color.b, j); -#elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_RGB) - for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + j] = get_protocol_eq(color.r, j); - for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE + j] = get_protocol_eq(color.g, j); - for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE * 2 + j] = get_protocol_eq(color.b, j); -#elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_BGR) - for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + j] = get_protocol_eq(color.b, j); - for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE + j] = get_protocol_eq(color.g, j); - for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE * 2 + j] = get_protocol_eq(color.r, j); -#endif -} - -void ws2812_init(void) { - palSetLineMode(RGB_DI_PIN, WS2812_MOSI_OUTPUT_MODE); - -#ifdef WS2812_SPI_SCK_PIN - palSetLineMode(WS2812_SPI_SCK_PIN, WS2812_SCK_OUTPUT_MODE); -#endif // WS2812_SPI_SCK_PIN - - // TODO: more dynamic baudrate - static const SPIConfig spicfg = {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) { - static bool s_init = false; - if (!s_init) { - ws2812_init(); - s_init = true; - } - - for (uint8_t i = 0; i < leds; i++) { - set_led_color_rgb(ledarray[i], i); - } - - // 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). -#ifndef WS2812_SPI_USE_CIRCULAR_BUFFER -# ifdef WS2812_SPI_SYNC - spiSend(&WS2812_SPI, sizeof(txbuf) / sizeof(txbuf[0]), txbuf); -# else - spiStartSend(&WS2812_SPI, sizeof(txbuf) / sizeof(txbuf[0]), txbuf); -# endif -#endif -} -- cgit v1.2.3