From 528b36c68beed443cf3df2a2f4cb666e8c99671c Mon Sep 17 00:00:00 2001 From: Drashna Jael're Date: Sun, 5 Sep 2021 23:02:22 -0700 Subject: [PATCH 1/2] Add RGBW support to PWM and SPI drivers for ChibiOS --- platforms/chibios/drivers/ws2812_pwm.c | 38 ++++++++++++++++++++++++-- platforms/chibios/drivers/ws2812_spi.c | 13 +++++---- 2 files changed, 43 insertions(+), 8 deletions(-) diff --git a/platforms/chibios/drivers/ws2812_pwm.c b/platforms/chibios/drivers/ws2812_pwm.c index e6af55b6b361..cf7c5f55fe76 100644 --- a/platforms/chibios/drivers/ws2812_pwm.c +++ b/platforms/chibios/drivers/ws2812_pwm.c @@ -5,7 +5,9 @@ /* Adapted from https://github.com/joewa/WS2812-LED-Driver_ChibiOS/ */ #ifdef RGBW -# error "RGBW not supported" +# define WS2812_COLOR_N 4 +#else +# define WS2812_COLOR_N 3 #endif #ifndef WS2812_PWM_DRIVER @@ -68,8 +70,9 @@ * The reset period for each frame is defined in WS2812_TRST_US. * Calculate the number of zeroes to add at the end assuming 1.25 uS/bit: */ +#define WS2812_COLOR_BITS (WS2812_COLOR_N * 8) #define WS2812_RESET_BIT_N (1000 * WS2812_TRST_US / 1250) -#define WS2812_COLOR_BIT_N (RGBLED_NUM * 24) /**< Number of data bits */ +#define WS2812_COLOR_BIT_N (RGBLED_NUM * WS2812_COLOR_BITS) /**< Number of data bits */ #define WS2812_BIT_N (WS2812_COLOR_BIT_N + WS2812_RESET_BIT_N) /**< Total number of bits in a frame */ /** @@ -114,7 +117,7 @@ * * @return The bit index */ -#define WS2812_BIT(led, byte, bit) (24 * (led) + 8 * (byte) + (7 - (bit))) +#define WS2812_BIT(led, byte, bit) (WS2812_COLOR_BITS * (led) + 8 * (byte) + (7 - (bit))) #if (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_GRB) /** @@ -228,6 +231,20 @@ # define WS2812_BLUE_BIT(led, bit) WS2812_BIT((led), 0, (bit)) #endif +#ifdef RGBW +/** + * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given white bit + * + * @note The white byte is the last byte in the color packet + * + * @param[in] led: The led index [0, @ref WS2812_LED_N) + * @param[in] bit: The bit index [0, 7] + * + * @return The bit index + */ +# define WS2812_WHITE_BIT(led, bit) WS2812_BIT((led), 3, (bit)) +#endif + /* --- PRIVATE VARIABLES ---------------------------------------------------- */ static uint32_t ws2812_frame_buffer[WS2812_BIT_N + 1]; /**< Buffer for a frame */ @@ -296,6 +313,17 @@ void ws2812_write_led(uint16_t led_number, uint8_t r, uint8_t g, uint8_t b) { ws2812_frame_buffer[WS2812_BLUE_BIT(led_number, bit)] = ((b >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0; } } +void ws2812_write_led_rgbw(uint16_t led_number, uint8_t r, uint8_t g, uint8_t b, uint8_t w) { + // Write color to frame buffer + for (uint8_t bit = 0; bit < 8; bit++) { + ws2812_frame_buffer[WS2812_RED_BIT(led_number, bit)] = ((r >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0; + ws2812_frame_buffer[WS2812_GREEN_BIT(led_number, bit)] = ((g >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0; + ws2812_frame_buffer[WS2812_BLUE_BIT(led_number, bit)] = ((b >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0; +#ifdef RGBW + ws2812_frame_buffer[WS2812_WHITE_BIT(led_number, bit)] = ((w >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0; +#endif + } +} // Setleds for standard RGB void ws2812_setleds(LED_TYPE* ledarray, uint16_t leds) { @@ -306,6 +334,10 @@ void ws2812_setleds(LED_TYPE* ledarray, uint16_t leds) { } for (uint16_t i = 0; i < leds; i++) { +#ifdef RGBW + ws2812_write_led_rgbw(i, ledarray[i].r, ledarray[i].g, ledarray[i].b, ledarray[i].w); +#else ws2812_write_led(i, ledarray[i].r, ledarray[i].g, ledarray[i].b); +#endif } } diff --git a/platforms/chibios/drivers/ws2812_spi.c b/platforms/chibios/drivers/ws2812_spi.c index fe14b478ab6e..01269b67a80f 100644 --- a/platforms/chibios/drivers/ws2812_spi.c +++ b/platforms/chibios/drivers/ws2812_spi.c @@ -3,10 +3,6 @@ /* 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 @@ -74,7 +70,11 @@ #endif #define BYTES_FOR_LED_BYTE 4 -#define NB_COLORS 3 +#ifdef RGBW +# define NB_COLORS4 +#else +# define NB_COLORS 3 +#endif #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)) @@ -116,6 +116,9 @@ static void set_led_color_rgb(LED_TYPE color, int pos) { 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 +#ifdef RGBW + for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE * 4 + j] = get_protocol_eq(color.w, j); +#endif } void ws2812_init(void) { From 6ca4f69a46e3e1d48d5610139a1f2845daeb2704 Mon Sep 17 00:00:00 2001 From: Drashna Jaelre Date: Mon, 6 Sep 2021 00:01:06 -0700 Subject: [PATCH 2/2] Apply suggestions from code review Co-authored-by: Ryan --- platforms/chibios/drivers/ws2812_pwm.c | 6 +++--- platforms/chibios/drivers/ws2812_spi.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/platforms/chibios/drivers/ws2812_pwm.c b/platforms/chibios/drivers/ws2812_pwm.c index cf7c5f55fe76..41ad93794216 100644 --- a/platforms/chibios/drivers/ws2812_pwm.c +++ b/platforms/chibios/drivers/ws2812_pwm.c @@ -5,9 +5,9 @@ /* Adapted from https://github.com/joewa/WS2812-LED-Driver_ChibiOS/ */ #ifdef RGBW -# define WS2812_COLOR_N 4 +# define WS2812_CHANNELS 4 #else -# define WS2812_COLOR_N 3 +# define WS2812_CHANNELS 3 #endif #ifndef WS2812_PWM_DRIVER @@ -70,7 +70,7 @@ * The reset period for each frame is defined in WS2812_TRST_US. * Calculate the number of zeroes to add at the end assuming 1.25 uS/bit: */ -#define WS2812_COLOR_BITS (WS2812_COLOR_N * 8) +#define WS2812_COLOR_BITS (WS2812_CHANNELS * 8) #define WS2812_RESET_BIT_N (1000 * WS2812_TRST_US / 1250) #define WS2812_COLOR_BIT_N (RGBLED_NUM * WS2812_COLOR_BITS) /**< Number of data bits */ #define WS2812_BIT_N (WS2812_COLOR_BIT_N + WS2812_RESET_BIT_N) /**< Total number of bits in a frame */ diff --git a/platforms/chibios/drivers/ws2812_spi.c b/platforms/chibios/drivers/ws2812_spi.c index 01269b67a80f..82c9586e27ea 100644 --- a/platforms/chibios/drivers/ws2812_spi.c +++ b/platforms/chibios/drivers/ws2812_spi.c @@ -71,11 +71,11 @@ #define BYTES_FOR_LED_BYTE 4 #ifdef RGBW -# define NB_COLORS4 +# define WS2812_CHANNELS 4 #else -# define NB_COLORS 3 +# define WS2812_CHANNELS 3 #endif -#define BYTES_FOR_LED (BYTES_FOR_LED_BYTE * NB_COLORS) +#define BYTES_FOR_LED (BYTES_FOR_LED_BYTE * WS2812_CHANNELS) #define DATA_SIZE (BYTES_FOR_LED * RGBLED_NUM) #define RESET_SIZE (1000 * WS2812_TRST_US / (2 * 1250)) #define PREAMBLE_SIZE 4