diff options
Diffstat (limited to 'platforms/chibios/drivers/ws2812_pwm.c')
| -rw-r--r-- | platforms/chibios/drivers/ws2812_pwm.c | 38 |
1 files changed, 35 insertions, 3 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 | } |
