diff options
author | Drashna Jaelre <drashna@live.com> | 2021-09-18 00:28:57 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-18 17:28:57 +1000 |
commit | 7c10d00ca6ec07f169d6f5e3c83bd7449a578ac0 (patch) | |
tree | 6761699b048ced82e5ccf8a09129bb26e493746b /platforms | |
parent | 07600939786186277e2db53dd42e0e35ce1a04f6 (diff) | |
download | qmk_firmware-7c10d00ca6ec07f169d6f5e3c83bd7449a578ac0.tar.gz qmk_firmware-7c10d00ca6ec07f169d6f5e3c83bd7449a578ac0.zip |
Add RGBW support to PWM and SPI drivers for ChibiOS (#14327)
* Add RGBW support to PWM and SPI drivers for ChibiOS
* Apply suggestions from code review
Co-authored-by: Ryan <fauxpark@gmail.com>
Co-authored-by: Ryan <fauxpark@gmail.com>
Diffstat (limited to 'platforms')
-rw-r--r-- | platforms/chibios/drivers/ws2812_pwm.c | 38 | ||||
-rw-r--r-- | platforms/chibios/drivers/ws2812_spi.c | 15 |
2 files changed, 44 insertions, 9 deletions
diff --git a/platforms/chibios/drivers/ws2812_pwm.c b/platforms/chibios/drivers/ws2812_pwm.c index 48d81cc87..c17b9cd4e 100644 --- a/platforms/chibios/drivers/ws2812_pwm.c +++ b/platforms/chibios/drivers/ws2812_pwm.c | |||
@@ -5,7 +5,9 @@ | |||
5 | /* Adapted from https://github.com/joewa/WS2812-LED-Driver_ChibiOS/ */ | 5 | /* Adapted from https://github.com/joewa/WS2812-LED-Driver_ChibiOS/ */ |
6 | 6 | ||
7 | #ifdef RGBW | 7 | #ifdef RGBW |
8 | # error "RGBW not supported" | 8 | # define WS2812_CHANNELS 4 |
9 | #else | ||
10 | # define WS2812_CHANNELS 3 | ||
9 | #endif | 11 | #endif |
10 | 12 | ||
11 | #ifndef WS2812_PWM_DRIVER | 13 | #ifndef WS2812_PWM_DRIVER |
@@ -68,8 +70,9 @@ | |||
68 | * The reset period for each frame is defined in WS2812_TRST_US. | 70 | * The reset period for each frame is defined in WS2812_TRST_US. |
69 | * Calculate the number of zeroes to add at the end assuming 1.25 uS/bit: | 71 | * Calculate the number of zeroes to add at the end assuming 1.25 uS/bit: |
70 | */ | 72 | */ |
73 | #define WS2812_COLOR_BITS (WS2812_CHANNELS * 8) | ||
71 | #define WS2812_RESET_BIT_N (1000 * WS2812_TRST_US / 1250) | 74 | #define WS2812_RESET_BIT_N (1000 * WS2812_TRST_US / 1250) |
72 | #define WS2812_COLOR_BIT_N (RGBLED_NUM * 24) /**< Number of data bits */ | 75 | #define WS2812_COLOR_BIT_N (RGBLED_NUM * WS2812_COLOR_BITS) /**< Number of data bits */ |
73 | #define WS2812_BIT_N (WS2812_COLOR_BIT_N + WS2812_RESET_BIT_N) /**< Total number of bits in a frame */ | 76 | #define WS2812_BIT_N (WS2812_COLOR_BIT_N + WS2812_RESET_BIT_N) /**< Total number of bits in a frame */ |
74 | 77 | ||
75 | /** | 78 | /** |
@@ -114,7 +117,7 @@ | |||
114 | * | 117 | * |
115 | * @return The bit index | 118 | * @return The bit index |
116 | */ | 119 | */ |
117 | #define WS2812_BIT(led, byte, bit) (24 * (led) + 8 * (byte) + (7 - (bit))) | 120 | #define WS2812_BIT(led, byte, bit) (WS2812_COLOR_BITS * (led) + 8 * (byte) + (7 - (bit))) |
118 | 121 | ||
119 | #if (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_GRB) | 122 | #if (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_GRB) |
120 | /** | 123 | /** |
@@ -228,6 +231,20 @@ | |||
228 | # define WS2812_BLUE_BIT(led, bit) WS2812_BIT((led), 0, (bit)) | 231 | # define WS2812_BLUE_BIT(led, bit) WS2812_BIT((led), 0, (bit)) |
229 | #endif | 232 | #endif |
230 | 233 | ||
234 | #ifdef RGBW | ||
235 | /** | ||
236 | * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given white bit | ||
237 | * | ||
238 | * @note The white byte is the last byte in the color packet | ||
239 | * | ||
240 | * @param[in] led: The led index [0, @ref WS2812_LED_N) | ||
241 | * @param[in] bit: The bit index [0, 7] | ||
242 | * | ||
243 | * @return The bit index | ||
244 | */ | ||
245 | # define WS2812_WHITE_BIT(led, bit) WS2812_BIT((led), 3, (bit)) | ||
246 | #endif | ||
247 | |||
231 | /* --- PRIVATE VARIABLES ---------------------------------------------------- */ | 248 | /* --- PRIVATE VARIABLES ---------------------------------------------------- */ |
232 | 249 | ||
233 | static uint32_t ws2812_frame_buffer[WS2812_BIT_N + 1]; /**< Buffer for a frame */ | 250 | 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) { | |||
296 | ws2812_frame_buffer[WS2812_BLUE_BIT(led_number, bit)] = ((b >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0; | 313 | ws2812_frame_buffer[WS2812_BLUE_BIT(led_number, bit)] = ((b >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0; |
297 | } | 314 | } |
298 | } | 315 | } |
316 | void ws2812_write_led_rgbw(uint16_t led_number, uint8_t r, uint8_t g, uint8_t b, uint8_t w) { | ||
317 | // Write color to frame buffer | ||
318 | for (uint8_t bit = 0; bit < 8; bit++) { | ||
319 | ws2812_frame_buffer[WS2812_RED_BIT(led_number, bit)] = ((r >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0; | ||
320 | ws2812_frame_buffer[WS2812_GREEN_BIT(led_number, bit)] = ((g >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0; | ||
321 | ws2812_frame_buffer[WS2812_BLUE_BIT(led_number, bit)] = ((b >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0; | ||
322 | #ifdef RGBW | ||
323 | ws2812_frame_buffer[WS2812_WHITE_BIT(led_number, bit)] = ((w >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0; | ||
324 | #endif | ||
325 | } | ||
326 | } | ||
299 | 327 | ||
300 | // Setleds for standard RGB | 328 | // Setleds for standard RGB |
301 | void ws2812_setleds(LED_TYPE* ledarray, uint16_t leds) { | 329 | void ws2812_setleds(LED_TYPE* ledarray, uint16_t leds) { |
@@ -306,6 +334,10 @@ void ws2812_setleds(LED_TYPE* ledarray, uint16_t leds) { | |||
306 | } | 334 | } |
307 | 335 | ||
308 | for (uint16_t i = 0; i < leds; i++) { | 336 | for (uint16_t i = 0; i < leds; i++) { |
337 | #ifdef RGBW | ||
338 | ws2812_write_led_rgbw(i, ledarray[i].r, ledarray[i].g, ledarray[i].b, ledarray[i].w); | ||
339 | #else | ||
309 | ws2812_write_led(i, ledarray[i].r, ledarray[i].g, ledarray[i].b); | 340 | ws2812_write_led(i, ledarray[i].r, ledarray[i].g, ledarray[i].b); |
341 | #endif | ||
310 | } | 342 | } |
311 | } | 343 | } |
diff --git a/platforms/chibios/drivers/ws2812_spi.c b/platforms/chibios/drivers/ws2812_spi.c index 589bf85c3..62722f466 100644 --- a/platforms/chibios/drivers/ws2812_spi.c +++ b/platforms/chibios/drivers/ws2812_spi.c | |||
@@ -3,10 +3,6 @@ | |||
3 | 3 | ||
4 | /* Adapted from https://github.com/gamazeps/ws2812b-chibios-SPIDMA/ */ | 4 | /* Adapted from https://github.com/gamazeps/ws2812b-chibios-SPIDMA/ */ |
5 | 5 | ||
6 | #ifdef RGBW | ||
7 | # error "RGBW not supported" | ||
8 | #endif | ||
9 | |||
10 | // Define the spi your LEDs are plugged to here | 6 | // Define the spi your LEDs are plugged to here |
11 | #ifndef WS2812_SPI | 7 | #ifndef WS2812_SPI |
12 | # define WS2812_SPI SPID1 | 8 | # define WS2812_SPI SPID1 |
@@ -74,8 +70,12 @@ | |||
74 | #endif | 70 | #endif |
75 | 71 | ||
76 | #define BYTES_FOR_LED_BYTE 4 | 72 | #define BYTES_FOR_LED_BYTE 4 |
77 | #define NB_COLORS 3 | 73 | #ifdef RGBW |
78 | #define BYTES_FOR_LED (BYTES_FOR_LED_BYTE * NB_COLORS) | 74 | # define WS2812_CHANNELS 4 |
75 | #else | ||
76 | # define WS2812_CHANNELS 3 | ||
77 | #endif | ||
78 | #define BYTES_FOR_LED (BYTES_FOR_LED_BYTE * WS2812_CHANNELS) | ||
79 | #define DATA_SIZE (BYTES_FOR_LED * RGBLED_NUM) | 79 | #define DATA_SIZE (BYTES_FOR_LED * RGBLED_NUM) |
80 | #define RESET_SIZE (1000 * WS2812_TRST_US / (2 * 1250)) | 80 | #define RESET_SIZE (1000 * WS2812_TRST_US / (2 * 1250)) |
81 | #define PREAMBLE_SIZE 4 | 81 | #define PREAMBLE_SIZE 4 |
@@ -116,6 +116,9 @@ static void set_led_color_rgb(LED_TYPE color, int pos) { | |||
116 | for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE + j] = get_protocol_eq(color.g, j); | 116 | for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE + j] = get_protocol_eq(color.g, j); |
117 | 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); | 117 | 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); |
118 | #endif | 118 | #endif |
119 | #ifdef RGBW | ||
120 | 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); | ||
121 | #endif | ||
119 | } | 122 | } |
120 | 123 | ||
121 | void ws2812_init(void) { | 124 | void ws2812_init(void) { |