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) { |
