Просмотр исходного кода

WS2812 API rework (#24364)

* Begin WS2812 API rework

* Move RGBW conversion, clean up color.h, fix RGBW for AVR bitbang

* Formatting & update PS2AVRGB I2C driver (untested)

* Tested ARM bitbang RGB+RGBW

* Tested ARM SPI RGB - RGBW not working

* Tested ARM PWM RGB+RGBW

* Tested RP2040 PIO driver RGB+RGBW

* Update RGBLight

* Formatting

* Fix BM60HSRGB rev2

* Fix oddforge/vea

* Fix 1k and XD002 RGBLite

* Fix model_m/mschwingen

* Fix handwired/promethium

* Rename `WS2812_LED_TOTAL` for BM60HSRGB

* Fix work_louder boards

* Fix dawn60

* Fix rgbkb/pan

* Fix neson_design/700e and n6

* Fix ergodox_ez/shine

* ergodox_ez/shine: invert indices for left half

* Fix matrix/abelx

* Fix matrix/m20add

* Remove custom rgblight driver for matrix/noah - should be done with lighting layers

* Fix LED indexes for RGBLight split

* Rename `convert_rgb_to_rgbw()` to `ws2812_rgb_to_rgbw()`

* Update WS2812 API docs

* `ergodox_ez/shine`: simplify LED index calculation

* LED/RGB Matrix: Add weak function for LED index resolution

* Bandaid fix for RGB Matrix splits not using WS2812

* `steelseries/prime_plus`: redo custom RGBLight driver

* Update keyboards/steelseries/prime_plus/rgblight_custom.c

Co-authored-by: Dasky <32983009+daskygit@users.noreply.github.com>

---------

Co-authored-by: Dasky <32983009+daskygit@users.noreply.github.com>
Ryan 1 год назад
Родитель
Сommit
208ebf54a9
61 измененных файлов с 638 добавлено и 661 удалено
  1. 1 1
      builddefs/common_features.mk
  2. 38 7
      docs/drivers/ws2812.md
  3. 15 0
      drivers/ws2812.c
  4. 32 13
      drivers/ws2812.h
  5. 2 0
      keyboards/1k/config.h
  6. 2 2
      keyboards/1k/keymaps/default/rgblite.h
  7. 2 0
      keyboards/ergodox_ez/post_config.h
  8. 45 37
      keyboards/ergodox_ez/shine/rgblight_custom.c
  9. 1 0
      keyboards/handwired/promethium/config.h
  10. 2 6
      keyboards/handwired/promethium/rgbsps.c
  11. 1 0
      keyboards/ibm/model_m/mschwingen/config.h
  12. 35 30
      keyboards/ibm/model_m/mschwingen/mschwingen.c
  13. 4 0
      keyboards/input_club/ergodox_infinity/ergodox_infinity.c
  14. 4 0
      keyboards/keychron/q11/ansi_encoder/ansi_encoder.c
  15. 4 0
      keyboards/keychron/q11/iso_encoder/iso_encoder.c
  16. 3 3
      keyboards/kprepublic/bm60hsrgb/rev2/config.h
  17. 8 18
      keyboards/kprepublic/bm60hsrgb/rev2/rev2.c
  18. 3 3
      keyboards/kprepublic/bm60hsrgb_iso/rev2/config.h
  19. 8 18
      keyboards/kprepublic/bm60hsrgb_iso/rev2/rev2.c
  20. 3 3
      keyboards/kprepublic/bm60hsrgb_poker/rev2/config.h
  21. 8 18
      keyboards/kprepublic/bm60hsrgb_poker/rev2/rev2.c
  22. 23 22
      keyboards/matrix/abelx/abelx.c
  23. 1 0
      keyboards/matrix/abelx/config.h
  24. 0 7
      keyboards/matrix/m20add/m20add.c
  25. 6 13
      keyboards/matrix/m20add/rgb_ring.c
  26. 0 1
      keyboards/matrix/m20add/rgb_ring.h
  27. 1 1
      keyboards/matrix/noah/keyboard.json
  28. 0 57
      keyboards/matrix/noah/noah.c
  29. 33 28
      keyboards/neson_design/700e/700e.c
  30. 1 0
      keyboards/neson_design/700e/config.h
  31. 1 0
      keyboards/neson_design/n6/config.h
  32. 34 27
      keyboards/neson_design/n6/n6.c
  33. 17 4
      keyboards/oddforge/vea/ws2812_custom.c
  34. 3 0
      keyboards/orthograph/orthograph.c
  35. 1 0
      keyboards/rgbkb/pan/config.h
  36. 4 24
      keyboards/rgbkb/pan/pan.c
  37. 40 20
      keyboards/steelseries/prime_plus/rgblight_custom.c
  38. 6 12
      keyboards/wilba_tech/wt_rgb_backlight.c
  39. 7 3
      keyboards/work_louder/rgb_functions.c
  40. 1 1
      keyboards/xelus/dawn60/rev1/config.h
  41. 2 2
      keyboards/xelus/dawn60/rev1_qmk/config.h
  42. 3 11
      keyboards/xelus/dawn60/rev1_qmk/rev1_qmk.c
  43. 3 0
      keyboards/xiudi/xd002/keymaps/rgb_lite/config.h
  44. 3 3
      keyboards/xiudi/xd002/keymaps/rgb_lite/rgblite.h
  45. 30 22
      platforms/avr/drivers/ws2812_bitbang.c
  46. 19 3
      platforms/avr/drivers/ws2812_i2c.c
  47. 22 5
      platforms/chibios/drivers/vendor/RP/RP2040/ws2812_vendor.c
  48. 29 13
      platforms/chibios/drivers/ws2812_bitbang.c
  49. 22 6
      platforms/chibios/drivers/ws2812_pwm.c
  50. 21 4
      platforms/chibios/drivers/ws2812_spi.c
  51. 0 11
      quantum/color.c
  52. 0 24
      quantum/color.h
  53. 10 1
      quantum/led_matrix/led_matrix.c
  54. 2 0
      quantum/led_matrix/led_matrix.h
  55. 10 1
      quantum/rgb_matrix/rgb_matrix.c
  56. 2 0
      quantum/rgb_matrix/rgb_matrix.h
  57. 4 54
      quantum/rgb_matrix/rgb_matrix_drivers.c
  58. 45 107
      quantum/rgblight/rgblight.c
  59. 0 1
      quantum/rgblight/rgblight.h
  60. 8 12
      quantum/rgblight/rgblight_drivers.c
  61. 3 2
      quantum/rgblight/rgblight_drivers.h

+ 1 - 1
builddefs/common_features.mk

@@ -932,7 +932,7 @@ ifeq ($(strip $(WS2812_DRIVER_REQUIRED)), yes)
 
     OPT_DEFS += -DWS2812_$(strip $(shell echo $(WS2812_DRIVER) | tr '[:lower:]' '[:upper:]'))
 
-    SRC += ws2812_$(strip $(WS2812_DRIVER)).c
+    SRC += ws2812.c ws2812_$(strip $(WS2812_DRIVER)).c
 
     ifeq ($(strip $(PLATFORM)), CHIBIOS)
         ifeq ($(strip $(WS2812_DRIVER)), pwm)

+ 38 - 7
docs/drivers/ws2812.md

@@ -241,13 +241,44 @@ Using a complementary timer output (`TIMx_CHyN`) is possible only for advanced-c
 
 ## API {#api}
 
-### `void ws2812_setleds(rgb_led_t *ledarray, uint16_t number_of_leds)` {#api-ws2812-setleds}
+### `void ws2812_init(void)` {#api-ws2812-init}
 
-Send RGB data to the WS2812 LED chain.
+Initialize the LED driver. This function should be called first.
 
-#### Arguments {#api-ws2812-setleds-arguments}
+---
 
- - `rgb_led_t *ledarray`  
-   A pointer to the LED array.
- - `uint16_t number_of_leds`  
-   The length of the LED array.
+### `void ws2812_set_color(int index, uint8_t red, uint8_t green, uint8_t blue)` {#api-ws2812-set-color}
+
+Set the color of a single LED. This function does not immediately update the LEDs; call `ws2812_flush()` after you are finished.
+
+#### Arguments {#api-ws2812-set-color-arguments}
+
+ - `int index`  
+   The LED index in the WS2812 chain.
+ - `uint8_t red`  
+   The red value to set.
+ - `uint8_t green`  
+   The green value to set.
+ - `uint8_t blue`  
+   The blue value to set.
+
+---
+
+### `void ws812_set_color_all(uint8_t red, uint8_t green, uint8_t blue)` {#api-ws2812-set-color-all}
+
+Set the color of all LEDs.
+
+#### Arguments {#api-ws2812-set-color-all-arguments}
+
+ - `uint8_t red`  
+   The red value to set.
+ - `uint8_t green`  
+   The green value to set.
+ - `uint8_t blue`  
+   The blue value to set.
+
+---
+
+### `void ws2812_flush(void)` {#api-ws2812-flush}
+
+Flush the PWM values to the LED chain.

+ 15 - 0
drivers/ws2812.c

@@ -0,0 +1,15 @@
+// Copyright 2024 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "ws2812.h"
+
+#if defined(WS2812_RGBW)
+void ws2812_rgb_to_rgbw(ws2812_led_t *led) {
+    // Determine lowest value in all three colors, put that into
+    // the white channel and then shift all colors by that amount
+    led->w = MIN(led->r, MIN(led->g, led->b));
+    led->r -= led->w;
+    led->g -= led->w;
+    led->b -= led->w;
+}
+#endif

+ 32 - 13
drivers/ws2812.h

@@ -15,7 +15,7 @@
 
 #pragma once
 
-#include "quantum/color.h"
+#include "util.h"
 
 /*
  * The WS2812 datasheets define T1H 900ns, T0H 350ns, T1L 350ns, T0L 900ns. Hence, by default, these
@@ -62,17 +62,36 @@
 #    define WS2812_LED_COUNT RGB_MATRIX_LED_COUNT
 #endif
 
+#define WS2812_BYTE_ORDER_RGB 0
+#define WS2812_BYTE_ORDER_GRB 1
+#define WS2812_BYTE_ORDER_BGR 2
+
+#ifndef WS2812_BYTE_ORDER
+#    define WS2812_BYTE_ORDER WS2812_BYTE_ORDER_GRB
+#endif
+
+typedef struct PACKED ws2812_led_t {
+#if (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_GRB)
+    uint8_t g;
+    uint8_t r;
+    uint8_t b;
+#elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_RGB)
+    uint8_t r;
+    uint8_t g;
+    uint8_t b;
+#elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_BGR)
+    uint8_t b;
+    uint8_t g;
+    uint8_t r;
+#endif
+#ifdef WS2812_RGBW
+    uint8_t w;
+#endif
+} ws2812_led_t;
+
 void ws2812_init(void);
+void ws2812_set_color(int index, uint8_t red, uint8_t green, uint8_t blue);
+void ws2812_set_color_all(uint8_t red, uint8_t green, uint8_t blue);
+void ws2812_flush(void);
 
-/* User Interface
- *
- * Input:
- *         ledarray:           An array of GRB data describing the LED colors
- *         number_of_leds:     The number of LEDs to write
- *
- * The functions will perform the following actions:
- *         - Set the data-out pin as output
- *         - Send out the LED data
- *         - Wait 50us to reset the LEDs
- */
-void ws2812_setleds(rgb_led_t *ledarray, uint16_t number_of_leds);
+void ws2812_rgb_to_rgbw(ws2812_led_t *led);

+ 2 - 0
keyboards/1k/config.h

@@ -32,3 +32,5 @@
 #define USB_INTR_ENABLE_BIT PCIE
 #define USB_INTR_PENDING_BIT PCIF
 #define USB_INTR_VECTOR SIG_PIN_CHANGE
+
+#define WS2812_LED_COUNT 1

+ 2 - 2
keyboards/1k/keymaps/default/rgblite.h

@@ -11,8 +11,8 @@ static inline void rgblite_init(void) {
 }
 
 static inline void rgblite_setrgb(RGB rgb) {
-    rgb_led_t leds[RGBLIGHT_LED_COUNT] = {{.r = rgb.r, .g = rgb.g, .b = rgb.b}};
-    ws2812_setleds(leds, RGBLIGHT_LED_COUNT);
+    ws2812_set_color_all(rgb.r, rgb.g, rgb.b);
+    ws2812_flush();
 }
 
 static void rgblite_increase_hue(void) {

+ 2 - 0
keyboards/ergodox_ez/post_config.h

@@ -33,8 +33,10 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 #ifdef ERGODOX_LED_30
 // If using 30 LEDs, then define that many
+#    define WS2812_LED_COUNT 30
 #    define RGBLIGHT_LED_COUNT 30  // Number of LEDs
 #else
 // If not, then only define 15
+#    define WS2812_LED_COUNT 15
 #    define RGBLIGHT_LED_COUNT 15  // Number of LEDs
 #endif

+ 45 - 37
keyboards/ergodox_ez/shine/rgblight_custom.c

@@ -21,47 +21,55 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include "ergodox_ez.h"
 #include "ws2812.h"
 
-void setleds_custom(rgb_led_t *led, uint16_t led_num) {
-    uint16_t length = 0;
-    int i = 0;
-    int j = 0;
-#    ifdef WS2812_RGBW
-    int bytes_per_led = 4;
-#    else
-    int bytes_per_led = 3;
-#    endif
-#    if defined(ERGODOX_LED_30)
-    // prevent right-half code from trying to bitbang all 30
-    // so with 30 LEDs, we count from 29 to 15 here, and the
-    // other half does 0 to 14.
-    uint8_t half_led_num = RGBLIGHT_LED_COUNT / 2;
-    length = half_led_num * bytes_per_led;
-    uint8_t data[length];
-    for (i = half_led_num + half_led_num - 1; i >= half_led_num; --i)
-#    elif defined(ERGODOX_LED_15_MIRROR)
-    length = led_num * bytes_per_led;
-    uint8_t data[length];
-    for (i = 0; i < led_num; ++i)
-#    else  // ERGDOX_LED_15 non-mirrored
-    length = led_num * bytes_per_led;
-    uint8_t data[length];
-    for (i = led_num - 1; i >= 0; --i)
-#    endif
-    {
-        uint8_t *data_byte = (uint8_t *)(led + i);
-        data[j++] = data_byte[0];
-        data[j++] = data_byte[1];
-        data[j++] = data_byte[2];
-#ifdef WS2812_RGBW
-        data[j++] = data_byte[3];
+#define WS2812_I2C_ADDRESS_LEFT 0x84
+
+#if defined(ERGODOX_LED_30)
+#    define WS2812_LED_COUNT_LEFT (RGBLIGHT_LED_COUNT / 2)
+ws2812_led_t ws2812_leds_left[WS2812_LED_COUNT_LEFT];
+#else
+#    define WS2812_LED_COUNT_LEFT RGBLIGHT_LED_COUNT
+ws2812_led_t ws2812_leds_left[WS2812_LED_COUNT_LEFT];
+#endif
+
+void set_color_left(int index, uint8_t red, uint8_t green, uint8_t blue) {
+    ws2812_leds_left[index].r = red;
+    ws2812_leds_left[index].g = green;
+    ws2812_leds_left[index].b = blue;
+#if defined(WS2812_RGBW)
+    ws2812_rgb_to_rgbw(&ws2812_leds_left[index]);
+#endif
+}
+
+void set_color_custom(int index, uint8_t red, uint8_t green, uint8_t blue) {
+#if defined(ERGODOX_LED_30)
+    if (index < WS2812_LED_COUNT_LEFT) {
+        ws2812_set_color(index, red, green, blue);
+    } else {
+        set_color_left(RGBLIGHT_LED_COUNT - index - 1, red, green, blue);
+    }
+#elif defined(ERGODOX_LED_15_MIRROR)
+    ws2812_set_color(index, red, green, blue);
+    set_color_left(index, red, green, blue);
+#else
+    ws2812_set_color(index, red, green, blue);
+    set_color_left(WS2812_LED_COUNT_LEFT - index - 1, red, green, blue);
 #endif
+}
+
+void set_color_all_custom(uint8_t red, uint8_t green, uint8_t blue) {
+    for (int i = 0; i < RGBLIGHT_LED_COUNT; i++) {
+        set_color_custom(i, red, green, blue);
     }
-    i2c_transmit(0x84, data, sizeof(data), ERGODOX_EZ_I2C_TIMEOUT);
+}
 
-    ws2812_setleds(led, led_num);
+void flush_custom(void) {
+    i2c_transmit(WS2812_I2C_ADDRESS_LEFT, (uint8_t *)ws2812_leds_left, sizeof(ws2812_leds_left), ERGODOX_EZ_I2C_TIMEOUT);
+    ws2812_flush();
 }
 
 const rgblight_driver_t rgblight_driver = {
-    .init    = ws2812_init,
-    .setleds = setleds_custom,
+    .init          = ws2812_init,
+    .set_color     = set_color_custom,
+    .set_color_all = set_color_all_custom,
+    .flush         = flush_custom,
 };

+ 1 - 0
keyboards/handwired/promethium/config.h

@@ -155,6 +155,7 @@ enum led_sequence {
 };
 
 #    define RGBSPS_NUM LED_TOTAL
+#    define WS2812_LED_COUNT RGBSPS_NUM
 #endif
 
 /* PS/2 mouse */

+ 2 - 6
keyboards/handwired/promethium/rgbsps.c

@@ -2,8 +2,6 @@
 #include "ws2812.h"
 #include "rgbsps.h"
 
-rgb_led_t led[RGBSPS_NUM];
-
 void keyboard_pre_init_kb(void) {
   ws2812_init();
 
@@ -11,9 +9,7 @@ void keyboard_pre_init_kb(void) {
 }
 
 void rgbsps_set(uint8_t index, uint8_t r, uint8_t g, uint8_t b) {
-  led[index].r = r;
-  led[index].g = g;
-  led[index].b = b;
+  ws2812_set_color(index, r, g, b);
 }
 
 void rgbsps_setall(uint8_t r, uint8_t g, uint8_t b) {
@@ -27,7 +23,7 @@ void rgbsps_turnoff(void) {
 }
 
 void rgbsps_send(void) {
-  ws2812_setleds(led, RGBSPS_NUM);
+  ws2812_flush();
 }
 
 void rgbsps_sethsv(uint8_t index, uint16_t hue, uint8_t sat, uint8_t val) {

+ 1 - 0
keyboards/ibm/model_m/mschwingen/config.h

@@ -65,6 +65,7 @@
 # define MODELM_LED_SCROLLOCK MODELM_LED3
 # define MODELM_LED_NUMLOCK   MODELM_LED1
 #elif defined(KEYBOARD_ibm_model_m_mschwingen_led_ws2812)
+# define WS2812_LED_COUNT 3
 #else
 # error one of MODELM_LEDS_FFC, MODELM_LEDS_WIRED or MODELM_LEDS_WS2812 must be set!
 #endif

+ 35 - 30
keyboards/ibm/model_m/mschwingen/mschwingen.c

@@ -39,27 +39,10 @@ static uint8_t  isRecording = 0;
 #    if RGBLIGHT_LED_COUNT < 3
 #        error we need at least 3 RGB LEDs!
 #    endif
-static rgb_led_t led[RGBLIGHT_LED_COUNT] = {{255, 255, 255}, {255, 255, 255}, {255, 255, 255}};
 
 #    define BRIGHT 32
 #    define DIM 6
 
-static const rgb_led_t black = {.r = 0, .g = 0, .b = 0};
-
-static const __attribute__((unused)) rgb_led_t green  = {.r = 0, .g = BRIGHT, .b = 0};
-static const __attribute__((unused)) rgb_led_t lgreen = {.r = 0, .g = DIM, .b = 0};
-
-static const __attribute__((unused)) rgb_led_t red  = {.r = BRIGHT, .g = 0, .b = 0};
-static const __attribute__((unused)) rgb_led_t lred = {.r = DIM, .g = 0, .b = 0};
-
-static const __attribute__((unused)) rgb_led_t blue  = {.r = 0, .g = 0, .b = BRIGHT};
-static const __attribute__((unused)) rgb_led_t lblue = {.r = 0, .g = 0, .b = DIM};
-
-static const __attribute__((unused)) rgb_led_t turq  = {.r = 0, .g = BRIGHT, .b = BRIGHT};
-static const __attribute__((unused)) rgb_led_t lturq = {.r = 0, .g = DIM, .b = DIM};
-
-static const __attribute__((unused)) rgb_led_t white = {.r = BRIGHT, .g = BRIGHT, .b = BRIGHT};
-
 static led_t   led_state;
 static uint8_t layer;
 static uint8_t default_layer;
@@ -81,17 +64,15 @@ void sleep_led_enable(void) {
     suspend_active = true;
     gpio_write_pin_low(MODELM_STATUS_LED);
 #ifdef KEYBOARD_ibm_model_m_mschwingen_led_ws2812
-    led[0] = black;
-    led[1] = black;
-    led[2] = black;
-    ws2812_setleds(led, RGBLIGHT_LED_COUNT);
+    ws2812_set_color_all(0, 0, 0);
+    ws2812_flush();
 #endif
 }
 
 void keyboard_pre_init_kb(void) {
 #ifdef KEYBOARD_ibm_model_m_mschwingen_led_ws2812
     ws2812_init();
-    ws2812_setleds(led, RGBLIGHT_LED_COUNT);
+    ws2812_flush();
 #else
     /* Set status LEDs pins to output and Low (on) */
     gpio_set_pin_output(MODELM_LED_CAPSLOCK);
@@ -121,35 +102,59 @@ void keyboard_pre_init_kb(void) {
 #ifdef KEYBOARD_ibm_model_m_mschwingen_led_ws2812
 static void led_update_rgb(void) {
     if (isRecording && blink_state) {
-        led[0] = white;
+        ws2812_set_color(0, BRIGHT, BRIGHT, BRIGHT);
     } else {
         switch (default_layer) {
             case 0:
-                led[0] = led_state.num_lock ? blue : lblue;
+                if (led_state.num_lock) {
+                    ws2812_set_color(0, 0, 0, BRIGHT);
+                } else {
+                    ws2812_set_color(0, 0, 0, DIM);
+                }
                 break;
             case 1:
-                led[0] = led_state.num_lock ? green : black;
+                if (led_state.num_lock) {
+                    ws2812_set_color(0, 0, BRIGHT, 0);
+                } else {
+                    ws2812_set_color(0, 0, 0, 0);
+                }
                 break;
         }
     }
 
-    led[1] = led_state.caps_lock ? green : black;
+    if (led_state.caps_lock) {
+        ws2812_set_color(1, 0, BRIGHT, 0);
+    } else {
+        ws2812_set_color(1, 0, 0, 0);
+    }
 
     switch (layer) {
         case 0:
         case 1:
         default:
-            led[2] = led_state.scroll_lock ? green : black;
+            if (led_state.scroll_lock) {
+                ws2812_set_color(2, 0, BRIGHT, 0);
+            } else {
+                ws2812_set_color(2, 0, 0, 0);
+            }
             break;
         case 2:
-            led[2] = led_state.scroll_lock ? red : lred;
+            if (led_state.scroll_lock) {
+                ws2812_set_color(2, BRIGHT, 0, 0);
+            } else {
+                ws2812_set_color(2, DIM, 0, 0);
+            }
             break;
         case 3:
-            led[2] = led_state.scroll_lock ? turq : lturq;
+            if (led_state.scroll_lock) {
+                ws2812_set_color(2, 0, BRIGHT, BRIGHT);
+            } else {
+                ws2812_set_color(2, 0, DIM, DIM);
+            }
             break;
     }
     if (!suspend_active) {
-	ws2812_setleds(led, RGBLIGHT_LED_COUNT);
+        ws2812_flush();
     }
 }
 

+ 4 - 0
keyboards/input_club/ergodox_infinity/ergodox_infinity.c

@@ -209,6 +209,10 @@ const is31fl3731_led_t PROGMEM g_is31fl3731_leds[IS31FL3731_LED_COUNT] = {
 //                                                                       71           70           69
                                                                     { 0, C3_7 }, { 0, C2_7 }, { 0, C1_7 },
 };
+
+int led_matrix_led_index(int index) {
+    return index;
+}
 #endif
 
 #ifdef ST7565_ENABLE

+ 4 - 0
keyboards/keychron/q11/ansi_encoder/ansi_encoder.c

@@ -125,4 +125,8 @@ const snled27351_led_t PROGMEM g_snled27351_leds[SNLED27351_LED_COUNT] = {
     {0, CB7_CA1,  CB9_CA1,  CB8_CA1},  // Down
     {0, CB7_CA7,  CB9_CA7,  CB8_CA7},  // Right
 };
+
+int rgb_matrix_led_index(int index) {
+    return index;
+}
 #endif

+ 4 - 0
keyboards/keychron/q11/iso_encoder/iso_encoder.c

@@ -126,4 +126,8 @@ const snled27351_led_t PROGMEM g_snled27351_leds[SNLED27351_LED_COUNT] = {
     {0, CB7_CA1,  CB9_CA1,  CB8_CA1},  // Down
     {0, CB7_CA7,  CB9_CA7,  CB8_CA7},  // Right
 };
+
+int rgb_matrix_led_index(int index) {
+    return index;
+}
 #endif

+ 3 - 3
keyboards/kprepublic/bm60hsrgb/rev2/config.h

@@ -25,9 +25,9 @@
 // Underglow LEDs are WS2812, but someone might want to use RGBLIGHT for them;
 // don't use those LEDs in RGB Matrix in that case.
 #ifdef RGBLIGHT_ENABLE
-#    define WS2812_LED_TOTAL 0
+#    define WS2812_LED_COUNT 0
 #else
-#    define WS2812_LED_TOTAL 6
+#    define WS2812_LED_COUNT 6
 #endif
 
-#define RGB_MATRIX_LED_COUNT (IS31FL3733_LED_COUNT + WS2812_LED_TOTAL)
+#define RGB_MATRIX_LED_COUNT (IS31FL3733_LED_COUNT + WS2812_LED_COUNT)

+ 8 - 18
keyboards/kprepublic/bm60hsrgb/rev2/rev2.c

@@ -110,7 +110,7 @@ led_config_t g_led_config = {
     {  18,  48 }, {  30,  48 }, {  45,  48 }, {  60,  48 }, {  75,  48 }, {  90,  48 }, { 105,  48 }, { 120,  48 }, { 135,  48 }, { 150,  48 }, { 165,  48 }, { 191,  48 }, { 210,  48 },
     // Ctrl, GUI, Alt, Space, RAlt, FN, Left, Down, Right
     {   3,  64 }, {  22,  64 }, {  33,  64 }, { 101,  64 }, { 135,  64 }, { 153,  64 }, { 195,  64 }, { 210,  64 }, { 225,  64 }
-#    if WS2812_LED_TOTAL > 0
+#    if WS2812_LED_COUNT > 0
         ,{ 28, 40}, { 62, 40}, { 96, 40}, {130, 40}, {164, 40}, {198, 40}
 #    endif
 }, {
@@ -124,7 +124,7 @@ led_config_t g_led_config = {
     1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 4,
     // Ctrl, GUI, Alt, Space, RAlt, FN, Left, Down, Right
     1, 1, 1, 4, 1, 1, 1, 1, 1
-#    if WS2812_LED_TOTAL > 0
+#    if WS2812_LED_COUNT > 0
         ,2, 2, 2, 2, 2, 2
 #    endif
     }
@@ -147,10 +147,6 @@ bool rgb_matrix_indicators_kb(void) {
 // Custom RGB Matrix driver that combines IS31FL3733 and WS2812
 // ==========================================================================
 
-#    if WS2812_LED_TOTAL > 0
-rgb_led_t rgb_matrix_ws2812_array[WS2812_LED_TOTAL];
-#    endif
-
 static void rgb_matrix_driver_init(void) {
     i2c_init();
     is31fl3733_init(0);
@@ -164,31 +160,25 @@ static void rgb_matrix_driver_init(void) {
 
 static void rgb_matrix_driver_flush(void) {
     is31fl3733_update_pwm_buffers(0);
-#    if WS2812_LED_TOTAL > 0
-    ws2812_setleds(rgb_matrix_ws2812_array, WS2812_LED_TOTAL);
+#    if WS2812_LED_COUNT > 0
+    ws2812_flush();
 #    endif
 }
 
 static void rgb_matrix_driver_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
     if (index < IS31FL3733_LED_COUNT) {
         is31fl3733_set_color(index, red, green, blue);
+#    if WS2812_LED_COUNT > 0
     } else {
-#    if WS2812_LED_TOTAL > 0
-        rgb_matrix_ws2812_array[index - IS31FL3733_LED_COUNT].r = red;
-        rgb_matrix_ws2812_array[index - IS31FL3733_LED_COUNT].g = green;
-        rgb_matrix_ws2812_array[index - IS31FL3733_LED_COUNT].b = blue;
+        ws2812_set_color(index - IS31FL3733_LED_COUNT, red, green, blue);
 #    endif
     }
 }
 
 static void rgb_matrix_driver_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
     is31fl3733_set_color_all(red, green, blue);
-#    if WS2812_LED_TOTAL > 0
-    for (uint8_t i = 0; i < WS2812_LED_TOTAL; i++) {
-        rgb_matrix_ws2812_array[i].r = red;
-        rgb_matrix_ws2812_array[i].g = green;
-        rgb_matrix_ws2812_array[i].b = blue;
-    }
+#    if WS2812_LED_COUNT > 0
+        ws2812_set_color_all(red, green, blue);
 #    endif
 }
 

+ 3 - 3
keyboards/kprepublic/bm60hsrgb_iso/rev2/config.h

@@ -23,9 +23,9 @@
 // Underglow LEDs are WS2812, but someone might want to use RGBLIGHT for them;
 // don't use those LEDs in RGB Matrix in that case.
 #ifdef RGBLIGHT_ENABLE
-#    define WS2812_LED_TOTAL 0
+#    define WS2812_LED_COUNT 0
 #else
-#    define WS2812_LED_TOTAL 6
+#    define WS2812_LED_COUNT 6
 #endif
 
-#define RGB_MATRIX_LED_COUNT (IS31FL3733_LED_COUNT + WS2812_LED_TOTAL)
+#define RGB_MATRIX_LED_COUNT (IS31FL3733_LED_COUNT + WS2812_LED_COUNT)

+ 8 - 18
keyboards/kprepublic/bm60hsrgb_iso/rev2/rev2.c

@@ -112,7 +112,7 @@ led_config_t g_led_config = { {
     {   3,  48 }, {  22,  48 }, {  33,  48 }, {  48,  48 }, {  63,  48 }, {  78,  48 }, {  93,  48 }, { 108,  48 }, { 123,  48 }, { 138,  48 }, { 153,  48 }, { 168,  48 }, { 194,  48 }, { 213,  48 },
     // Ctrl, GUI, Alt, Space, RAlt, FN, Left, Down, Right
     {   3,  64 }, {  22,  64 }, {  33,  64 }, { 101,  64 }, { 135,  64 }, { 153,  64 }, { 195,  64 }, { 210,  64 }, { 225,  64 }
-#    if WS2812_LED_TOTAL > 0
+#    if WS2812_LED_COUNT > 0
         ,{ 28, 40}, { 62, 40}, { 96, 40}, {130, 40}, {164, 40}, {198, 40}
 #    endif
 }, {
@@ -126,7 +126,7 @@ led_config_t g_led_config = { {
     1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 4,
     // Ctrl, GUI, Alt, Space, RAlt, FN, Left, Down, Right
     1, 1, 1, 4, 1, 1, 1, 1, 1
-#    if WS2812_LED_TOTAL > 0
+#    if WS2812_LED_COUNT > 0
         ,2, 2, 2, 2, 2, 2
 #    endif
 } };
@@ -147,10 +147,6 @@ bool rgb_matrix_indicators_kb(void) {
 // Custom RGB Matrix driver that combines IS31FL3733 and WS2812
 // ==========================================================================
 
-#    if WS2812_LED_TOTAL > 0
-rgb_led_t rgb_matrix_ws2812_array[WS2812_LED_TOTAL];
-#    endif
-
 static void rgb_matrix_driver_init(void) {
     i2c_init();
     is31fl3733_init(0);
@@ -164,31 +160,25 @@ static void rgb_matrix_driver_init(void) {
 
 static void rgb_matrix_driver_flush(void) {
     is31fl3733_update_pwm_buffers(0);
-#    if WS2812_LED_TOTAL > 0
-    ws2812_setleds(rgb_matrix_ws2812_array, WS2812_LED_TOTAL);
+#    if WS2812_LED_COUNT > 0
+    ws2812_flush();
 #    endif
 }
 
 static void rgb_matrix_driver_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
     if (index < IS31FL3733_LED_COUNT) {
         is31fl3733_set_color(index, red, green, blue);
+#    if WS2812_LED_COUNT > 0
     } else {
-#    if WS2812_LED_TOTAL > 0
-        rgb_matrix_ws2812_array[index - IS31FL3733_LED_COUNT].r = red;
-        rgb_matrix_ws2812_array[index - IS31FL3733_LED_COUNT].g = green;
-        rgb_matrix_ws2812_array[index - IS31FL3733_LED_COUNT].b = blue;
+        ws2812_set_color(index - IS31FL3733_LED_COUNT, red, green, blue);
 #    endif
     }
 }
 
 static void rgb_matrix_driver_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
     is31fl3733_set_color_all(red, green, blue);
-#    if WS2812_LED_TOTAL > 0
-    for (uint8_t i = 0; i < WS2812_LED_TOTAL; i++) {
-        rgb_matrix_ws2812_array[i].r = red;
-        rgb_matrix_ws2812_array[i].g = green;
-        rgb_matrix_ws2812_array[i].b = blue;
-    }
+#    if WS2812_LED_COUNT > 0
+    ws2812_set_color_all(red, green, blue);
 #    endif
 }
 

+ 3 - 3
keyboards/kprepublic/bm60hsrgb_poker/rev2/config.h

@@ -21,9 +21,9 @@
 // Underglow LEDs are WS2812, but someone might want to use RGBLIGHT for them;
 // don't use those LEDs in RGB Matrix in that case.
 #ifdef RGBLIGHT_ENABLE
-#    define WS2812_LED_TOTAL 0
+#    define WS2812_LED_COUNT 0
 #else
-#    define WS2812_LED_TOTAL 6
+#    define WS2812_LED_COUNT 6
 #endif
 
-#define RGB_MATRIX_LED_COUNT (IS31FL3733_LED_COUNT + WS2812_LED_TOTAL)
+#define RGB_MATRIX_LED_COUNT (IS31FL3733_LED_COUNT + WS2812_LED_COUNT)

+ 8 - 18
keyboards/kprepublic/bm60hsrgb_poker/rev2/rev2.c

@@ -107,7 +107,7 @@ led_config_t g_led_config = {
     {  18,  48 }, {  30,  48 }, {  45,  48 }, {  60,  48 }, {  75,  48 }, {  90,  48 }, { 105,  48 }, { 120,  48 }, { 135,  48 }, { 150,  48 }, { 165,  48 }, { 191,  48 },
     // Ctrl, GUI, Alt, Space, RAlt, FN, Left, Down, Right
     {   3,  64 }, {  22,  64 }, {  33,  64 }, { 101,  64 }, { 135,  64 }, { 153,  64 }, { 210,  64 }, { 225,  64 }
-#    if WS2812_LED_TOTAL > 0
+#    if WS2812_LED_COUNT > 0
         ,{ 28, 40}, { 62, 40}, { 96, 40}, {130, 40}, {164, 40}, {198, 40}
 #    endif
 }, {
@@ -121,7 +121,7 @@ led_config_t g_led_config = {
     1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1,
     // Ctrl, GUI, Alt, Space, RAlt, FN, Left, Down, Right
     1, 1, 1, 4, 1, 1, 1, 1
-#    if WS2812_LED_TOTAL > 0
+#    if WS2812_LED_COUNT > 0
         ,2, 2, 2, 2, 2, 2
 #    endif
     }
@@ -143,10 +143,6 @@ bool rgb_matrix_indicators_kb(void) {
 // Custom RGB Matrix driver that combines IS31FL3733 and WS2812
 // ==========================================================================
 
-#    if WS2812_LED_TOTAL > 0
-rgb_led_t rgb_matrix_ws2812_array[WS2812_LED_TOTAL];
-#    endif
-
 static void rgb_matrix_driver_init(void) {
     i2c_init();
     is31fl3733_init(0);
@@ -160,31 +156,25 @@ static void rgb_matrix_driver_init(void) {
 
 static void rgb_matrix_driver_flush(void) {
     is31fl3733_update_pwm_buffers(0);
-#    if WS2812_LED_TOTAL > 0
-    ws2812_setleds(rgb_matrix_ws2812_array, WS2812_LED_TOTAL);
+#    if WS2812_LED_COUNT > 0
+    ws2812_flush();
 #    endif
 }
 
 static void rgb_matrix_driver_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
     if (index < IS31FL3733_LED_COUNT) {
         is31fl3733_set_color(index, red, green, blue);
+#    if WS2812_LED_COUNT > 0
     } else {
-#    if WS2812_LED_TOTAL > 0
-        rgb_matrix_ws2812_array[index - IS31FL3733_LED_COUNT].r = red;
-        rgb_matrix_ws2812_array[index - IS31FL3733_LED_COUNT].g = green;
-        rgb_matrix_ws2812_array[index - IS31FL3733_LED_COUNT].b = blue;
+        ws2812_set_color(index - IS31FL3733_LED_COUNT, red, green, blue);
 #    endif
     }
 }
 
 static void rgb_matrix_driver_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
     is31fl3733_set_color_all(red, green, blue);
-#    if WS2812_LED_TOTAL > 0
-    for (uint8_t i = 0; i < WS2812_LED_TOTAL; i++) {
-        rgb_matrix_ws2812_array[i].r = red;
-        rgb_matrix_ws2812_array[i].g = green;
-        rgb_matrix_ws2812_array[i].b = blue;
-    }
+#    if WS2812_LED_COUNT > 0
+    ws2812_set_color_all(red, green, blue);
 #    endif
 }
 

+ 23 - 22
keyboards/matrix/abelx/abelx.c

@@ -41,20 +41,6 @@ uint8_t read_pin(uint16_t pin)
     return (data & (1<<GET_PIN(pin))) ? 1 : 0;
 }
 
-void matrix_init_kb(void) {
-#ifdef RGBLIGHT_ENABLE
-    aw9523b_init(AW9523B_ADDR);
-#endif
-    matrix_init_user();
-}
-
-
-void housekeeping_task_kb(void) {
-#ifdef RGBLIGHT_ENABLE
-    aw9523b_update_pwm_buffers(AW9523B_ADDR);
-#endif
-}
-
 #ifdef RGBLIGHT_ENABLE
 #include "rgblight.h"
 #include "ws2812.h"
@@ -67,20 +53,35 @@ const aw9523b_led g_aw9523b_leds[AW9523B_RGB_NUM] = {
     {AW9523B_P07_PWM, AW9523B_P06_PWM, AW9523B_P05_PWM},
 };
 
-void setleds_custom(rgb_led_t *start_led, uint16_t num_leds)
-{
-    uint8_t num = num_leds < AW9523B_RGB_NUM ? num_leds : AW9523B_RGB_NUM;
+void init_custom(void) {
+    aw9523b_init(AW9523B_ADDR);
+    ws2812_init();
+}
 
-    ws2812_setleds(start_led, num);
+void set_color_custom(int index, uint8_t red, uint8_t green, uint8_t blue) {
+    if (index < AW9523B_RGB_NUM) {
+        aw9523b_set_color(index, red, green, blue);
+    } else {
+        ws2812_set_color(index - AW9523B_RGB_NUM, red, green, blue);
+    }
+}
 
-    for (int i = 0; i < num; i++) {
-        aw9523b_set_color(i, start_led[i].r, start_led[i].g, start_led[i].b);
+void set_color_all_custom(uint8_t red, uint8_t green, uint8_t blue) {
+    for (int i = 0; i < RGBLIGHT_LED_COUNT; i++) {
+        set_color_custom(i, red, green, blue);
     }
 }
 
+void flush_custom(void) {
+    aw9523b_update_pwm_buffers(AW9523B_ADDR);
+    ws2812_flush();
+}
+
 const rgblight_driver_t rgblight_driver = {
-    .init    = ws2812_init,
-    .setleds = setleds_custom,
+    .init          = init_custom,
+    .set_color     = set_color_custom,
+    .set_color_all = set_color_all_custom,
+    .flush         = flush_custom,
 };
 
 #endif

+ 1 - 0
keyboards/matrix/abelx/config.h

@@ -89,5 +89,6 @@
 #define I2C1_DUTY_CYCLE FAST_DUTY_CYCLE_2
 
 #define AW9523B_RGB_NUM 4
+#define WS2812_LED_COUNT 5
 
 #define EARLY_INIT_PERFORM_BOOTLOADER_JUMP FALSE

+ 0 - 7
keyboards/matrix/m20add/m20add.c

@@ -27,13 +27,6 @@ uint8_t read_pin(uint16_t pin)
     return (data & (1<<GET_PIN(pin))) ? 1 : 0;
 }
 
-void matrix_init_kb(void) {
-#ifdef RGBLIGHT_ENABLE
-    rgb_ring_init();
-#endif
-    matrix_init_user();
-}
-
 void housekeeping_task_kb(void) {
 #ifdef RGBLIGHT_ENABLE
     rgb_ring_task();

+ 6 - 13
keyboards/matrix/m20add/rgb_ring.c

@@ -361,27 +361,22 @@ static void custom_effects(void)
     effect_funcs[rgb_ring.effect]();
 }
 
-void setleds_custom(rgb_led_t *start_led, uint16_t num_leds)
-{
+void flush_custom(void) {
     if (rgb_ring.state != RING_STATE_QMK) {
         return;
     }
 
-    for (uint8_t i = 0; i < num_leds; i++) {
-        is31fl3731_set_color(i, start_led[i].r, start_led[i].g, start_led[i].b);
-    }
+    is31fl3731_flush();
 }
 
 const rgblight_driver_t rgblight_driver = {
-    .setleds = setleds_custom,
+    .init          = is31fl3731_init_drivers,
+    .set_color     = is31fl3731_set_color,
+    .set_color_all = is31fl3731_set_color_all,
+    .flush         = flush_custom,
 };
 
 
-void rgb_ring_init(void)
-{
-    is31fl3731_init_drivers();
-}
-
 void rgb_ring_task(void)
 {
     switch (rgb_ring.state) {
@@ -397,8 +392,6 @@ void rgb_ring_task(void)
         default:
             break;
     };
-
-    is31fl3731_flush();
 }
 
 bool process_record_kb(uint16_t keycode, keyrecord_t *record)

+ 0 - 1
keyboards/matrix/m20add/rgb_ring.h

@@ -19,5 +19,4 @@
 
 #pragma once
 
-void rgb_ring_init(void);
 void rgb_ring_task(void);

+ 1 - 1
keyboards/matrix/noah/keyboard.json

@@ -10,7 +10,7 @@
     "no_startup_check": true
   },
   "rgblight": {
-    "driver": "custom",
+    "driver": "ws2812",
     "led_count": 7,
     "animations": {
       "breathing": true,

+ 0 - 57
keyboards/matrix/noah/noah.c

@@ -9,57 +9,6 @@ void bootloader_jump(void) {
     NVIC_SystemReset();
 }
 
-#ifdef RGBLIGHT_ENABLE
-#include <string.h>
-#include "rgblight.h"
-#include "ws2812.h"
-extern rgblight_config_t rgblight_config;
-
-// led 0 for caps lock, led 1 for scroll lock, led 3 for num lock
-// led 4 for layer 1, led 5 for layer 2, led 6 for layer 3, led 7 for layer 4
-#if RGBLIGHT_LED_COUNT < 7
-#error "MUST set the RGBLIGHT_LED_COUNT bigger than 7"
-#endif
-rgb_led_t noah_leds[RGBLIGHT_LED_COUNT];
-static bool noah_led_mode = false;
-void setleds_custom(rgb_led_t *ledarray, uint16_t num_leds) {
-    memset(&noah_leds[0], 0, sizeof(noah_leds));
-    if (!rgblight_config.enable) {
-        for (uint8_t i = 0; i < RGBLIGHT_LED_COUNT; i++) {
-            ledarray[i].r = 0;
-            ledarray[i].g = 0;
-            ledarray[i].b = 0;
-        }
-    }
-    if (noah_led_mode) {
-      led_t led_state = host_keyboard_led_state();
-      if (led_state.caps_lock) {
-        noah_leds[0] = ledarray[0];
-      }
-      if (led_state.scroll_lock) {
-        noah_leds[1] = ledarray[1];
-      }
-      if (led_state.num_lock) {
-        noah_leds[2] = ledarray[2];
-      }
-      for (int32_t i = 0; i < 4; i++) {
-        if(layer_state_is(i+1)) {
-          noah_leds[i + 3] = ledarray[i + 3];
-        }
-      }
-    } else {
-      memcpy(&noah_leds[0], &ledarray[0], sizeof(noah_leds));
-    }
-
-  ws2812_setleds(noah_leds, RGBLIGHT_LED_COUNT);
-}
-
-const rgblight_driver_t rgblight_driver = {
-    .init    = ws2812_init,
-    .setleds = setleds_custom,
-};
-#endif
-
 #ifdef RGB_MATRIX_ENABLE
 const is31fl3731_led_t PROGMEM g_is31fl3731_leds[IS31FL3731_LED_COUNT] = {
 /* Refer to IS31 manual for these locations
@@ -150,11 +99,6 @@ const is31fl3731_led_t PROGMEM g_is31fl3731_leds[IS31FL3731_LED_COUNT] = {
 bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
   if (record->event.pressed) {
     switch(keycode) {
-    #ifdef RGBLIGHT_ENABLE
-        case KC_F24: // switch the led mode on or off
-        noah_led_mode = !noah_led_mode;
-        return false;
-
     #ifdef RGB_MATRIX_ENABLE
         case KC_F13: // toggle rgb matrix
         rgb_matrix_toggle();
@@ -162,7 +106,6 @@ bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
         case KC_F14:
         rgb_matrix_step();
         return false;
-    #endif
     #endif
         default:
         break;

+ 33 - 28
keyboards/neson_design/700e/700e.c

@@ -18,9 +18,11 @@
  */
 
 #include "quantum.h"
-#include "i2c_master.h"
-#include "drivers/led/issi/is31fl3731.h"
-#include "ws2812.h"
+
+#ifdef RGBLIGHT_ENABLE
+#    include "i2c_master.h"
+#    include "drivers/led/issi/is31fl3731.h"
+#    include "ws2812.h"
 
 enum {
     SELF_TESTING,
@@ -67,7 +69,6 @@ enum {
 #endif
 #define ST_RIGHT_END        (ST_RIGHT_BEGIN+ST_RIGHT_SIZE-1)
 
-#ifdef RGBLIGHT_ENABLE
 
 typedef struct {
     uint8_t state;
@@ -295,7 +296,6 @@ void matrix_init_kb(void)
     gpio_set_pin_output(LED_CAPS_LOCK_PIN);
     gpio_write_pin_low(LED_CAPS_LOCK_PIN);
 
-    is31fl3731_init_drivers();
 
     update_ticks();
     matrix_init_user();
@@ -313,17 +313,10 @@ void housekeeping_task_kb(void)
     } else if (rgb_state.state == CAPS_ALERT) {
         if (rgb_state.alert) {
             is31fl3731_set_color_all(ALERM_LED_R, ALERM_LED_G, ALERM_LED_B);
-            rgb_led_t leds[4];
-            for (int i = 0; i < 4; i++) {
-                leds[i].r = ALERM_LED_G;
-                leds[i].g = ALERM_LED_R;
-                leds[i].b = ALERM_LED_B;
-            }
-            ws2812_setleds(leds, 4);
+            ws2812_set_color_all(ALERM_LED_G, ALERM_LED_R, ALERM_LED_B);
         } else {
             is31fl3731_set_color_all(0, 0, 0);
-            rgb_led_t leds[4] = {0};
-            ws2812_setleds(leds, 4);
+            ws2812_set_color_all(0, 0, 0);
         }
 
         if (timer_elapsed(rgb_state.ticks) > ALERT_INTERVAL) {
@@ -333,28 +326,40 @@ void housekeeping_task_kb(void)
     }
 
     is31fl3731_flush();
+    ws2812_flush();
 }
 
-void setleds_custom(rgb_led_t *start_led, uint16_t num_leds)
-{
-    if (rgb_state.state != NORMAL) return;
+void init_custom(void) {
+    is31fl3731_init_drivers();
+    ws2812_init();
+}
 
-    for (uint8_t i = 0; i < IS31FL3731_LED_COUNT; i++) {
-        is31fl3731_set_color(i, start_led[i].r, start_led[i].g, start_led[i].b);
+void set_color_custom(int index, uint8_t red, uint8_t green, uint8_t blue) {
+    if (index < IS31FL3731_LED_COUNT) {
+        is31fl3731_set_color(index, red, green, blue);
+    } else if (index < IS31FL3731_LED_COUNT + WS2812_LED_COUNT) {
+        ws2812_set_color(index - IS31FL3731_LED_COUNT, green, red, blue);
     }
-    rgb_led_t leds[4];
-    for (int i = 0; i < 4; i++) {
-        leds[i].r = start_led[IS31FL3731_LED_COUNT+i].g;
-        leds[i].g = start_led[IS31FL3731_LED_COUNT+i].r;
-        leds[i].b = start_led[IS31FL3731_LED_COUNT+i].b;
+}
+
+void set_color_all_custom(uint8_t red, uint8_t green, uint8_t blue) {
+    for (int i = 0; i < RGBLIGHT_LED_COUNT; i++) {
+        set_color_custom(i, red, green, blue);
     }
-    //ws2812_setleds(start_led+IS31FL3731_LED_COUNT, 4);
-    ws2812_setleds(leds, 4);
+}
+
+void flush_custom(void) {
+    if (rgb_state.state != NORMAL) return;
+
+    is31fl3731_flush();
+    ws2812_flush();
 }
 
 const rgblight_driver_t rgblight_driver = {
-    .init    = ws2812_init,
-    .setleds = setleds_custom,
+    .init          = init_custom,
+    .set_color     = set_color_custom,
+    .set_color_all = set_color_all_custom,
+    .flush         = flush_custom,
 };
 
 bool led_update_kb(led_t led_state)

+ 1 - 0
keyboards/neson_design/700e/config.h

@@ -21,5 +21,6 @@
 #define IS31FL3731_I2C_ADDRESS_1 IS31FL3731_I2C_ADDRESS_GND
 #define IS31FL3731_I2C_ADDRESS_2 IS31FL3731_I2C_ADDRESS_VCC
 #define IS31FL3731_LED_COUNT 64
+#define WS2812_LED_COUNT 4
 
 #define USB_SUSPEND_WAKEUP_DELAY 1000

+ 1 - 0
keyboards/neson_design/n6/config.h

@@ -21,3 +21,4 @@
 #define IS31FL3731_I2C_ADDRESS_1 IS31FL3731_I2C_ADDRESS_GND
 #define IS31FL3731_I2C_ADDRESS_2 IS31FL3731_I2C_ADDRESS_VCC
 #define IS31FL3731_LED_COUNT 64
+#define WS2812_LED_COUNT 1

+ 34 - 27
keyboards/neson_design/n6/n6.c

@@ -18,9 +18,11 @@
  */
 
 #include "quantum.h"
-#include "i2c_master.h"
-#include "drivers/led/issi/is31fl3731.h"
-#include "ws2812.h"
+
+#ifdef RGBLIGHT_ENABLE
+#    include "i2c_master.h"
+#    include "drivers/led/issi/is31fl3731.h"
+#    include "ws2812.h"
 
 enum {
     SELF_TESTING,
@@ -67,7 +69,6 @@ enum {
 #endif
 #define ST_RIGHT_END        (ST_RIGHT_BEGIN+ST_RIGHT_SIZE-1)
 
-#ifdef RGBLIGHT_ENABLE
 extern rgblight_config_t rgblight_config;
 
 typedef struct {
@@ -299,8 +300,6 @@ void matrix_init_kb(void)
     gpio_set_pin_output(LED_CAPS_LOCK_PIN);
     gpio_write_pin_low(LED_CAPS_LOCK_PIN);
 
-    is31fl3731_init_drivers();
-
     update_ticks();
     matrix_init_user();
 }
@@ -310,22 +309,12 @@ void housekeeping_task_kb(void)
     if (rgb_state.state == SELF_TESTING) {
         self_testing();
     } else if (rgb_state.state == CAPS_ALERT) {
-        //gold 0xFF, 0xD9, 0x00
-        rgb_led_t led = {
-            .r = 0xFF,
-            //.g = 0xD9,
-            .g = 0xA5,
-            .b = 0x00,
-        };
         if (rgb_state.alert) {
-            is31fl3731_set_color_all(led.r, led.g, led.b);
-            ws2812_setleds(&led, 1);
+            is31fl3731_set_color_all(0xFF, 0xA5, 0x00);
+            ws2812_set_color_all(0xFF, 0xA5, 0x00);
         } else {
-            led.r = 0;
-            led.g = 0;
-            led.b = 0;
             is31fl3731_set_color_all(0, 0, 0);
-            ws2812_setleds(&led, 1);
+            ws2812_set_color_all(0, 0, 0);
         }
 
         if (timer_elapsed(rgb_state.ticks) > ALERT_INTERVAL) {
@@ -337,19 +326,37 @@ void housekeeping_task_kb(void)
     is31fl3731_flush();
 }
 
-void setleds_custom(rgb_led_t *start_led, uint16_t num_leds)
-{
-    if (rgb_state.state != NORMAL) return;
+void init_custom(void) {
+    is31fl3731_init_drivers();
+    ws2812_init();
+}
 
-    for (uint8_t i = 0; i < IS31FL3731_LED_COUNT; i++) {
-        is31fl3731_set_color(i, start_led[i].r, start_led[i].g, start_led[i].b);
+void set_color_custom(int index, uint8_t red, uint8_t green, uint8_t blue) {
+    if (index < IS31FL3731_LED_COUNT) {
+        is31fl3731_set_color(index, red, green, blue);
+    } else if (index < IS31FL3731_LED_COUNT + WS2812_LED_COUNT) {
+        ws2812_set_color(index - IS31FL3731_LED_COUNT, red, green, blue);
     }
-    ws2812_setleds(start_led+IS31FL3731_LED_COUNT, 1);
+}
+
+void set_color_all_custom(uint8_t red, uint8_t green, uint8_t blue) {
+    for (int i = 0; i < RGBLIGHT_LED_COUNT; i++) {
+        set_color_custom(i, red, green, blue);
+    }
+}
+
+void flush_custom(void) {
+    if (rgb_state.state != NORMAL) return;
+
+    is31fl3731_flush();
+    ws2812_flush();
 }
 
 const rgblight_driver_t rgblight_driver = {
-    .init    = ws2812_init,
-    .setleds = setleds_custom,
+    .init          = init_custom,
+    .set_color     = set_color_custom,
+    .set_color_all = set_color_all_custom,
+    .flush         = flush_custom,
 };
 
 bool led_update_kb(led_t led_state)

+ 17 - 4
keyboards/oddforge/vea/ws2812_custom.c

@@ -17,12 +17,25 @@
 #    define WS2812_I2C_TIMEOUT 100
 #endif
 
+ws2812_led_t ws2812_leds[WS2812_LED_COUNT];
+
 void ws2812_init(void) {
     i2c_init();
 }
 
-// Setleds for standard RGB
-void ws2812_setleds(rgb_led_t *ledarray, uint16_t leds) {
-    i2c_transmit(WS2812_I2C_ADDRESS, (uint8_t *)ledarray, sizeof(rgb_led_t) * (leds >> 1), WS2812_I2C_TIMEOUT);
-    i2c_transmit(WS2812_I2C_ADDRESS_RIGHT, (uint8_t *)ledarray+(sizeof(rgb_led_t) * (leds >> 1)), sizeof(rgb_led_t) * (leds - (leds >> 1)), WS2812_I2C_TIMEOUT);
+void ws2812_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
+    ws2812_leds[index].r = red;
+    ws2812_leds[index].g = green;
+    ws2812_leds[index].b = blue;
+}
+
+void ws2812_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
+    for (int i = 0; i < WS2812_LED_COUNT; i++) {
+        ws2812_set_color(i, red, green, blue);
+    }
+}
+
+void ws2812_flush(void) {
+    i2c_transmit(WS2812_I2C_ADDRESS, (uint8_t *)ws2812_leds, sizeof(ws2812_led_t) * (WS2812_LED_COUNT >> 1), WS2812_I2C_TIMEOUT);
+    i2c_transmit(WS2812_I2C_ADDRESS_RIGHT, (uint8_t *)ws2812_leds + (sizeof(ws2812_led_t) * (WS2812_LED_COUNT >> 1)), sizeof(ws2812_led_t) * (WS2812_LED_COUNT - (WS2812_LED_COUNT >> 1)), WS2812_I2C_TIMEOUT);
 }

+ 3 - 0
keyboards/orthograph/orthograph.c

@@ -125,4 +125,7 @@ const is31fl3733_led_t PROGMEM g_is31fl3733_leds[IS31FL3733_LED_COUNT] = {
 {0, SW7_CS7, SW8_CS7, SW9_CS7}
 };
 
+int rgb_matrix_led_index(int index) {
+    return index;
+}
 #endif

+ 1 - 0
keyboards/rgbkb/pan/config.h

@@ -17,3 +17,4 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #pragma once
 
 #define RGB_MATRIX_LED_COUNT 64
+#define WS2812_LED_COUNT 64

+ 4 - 24
keyboards/rgbkb/pan/pan.c

@@ -21,43 +21,23 @@
 #    if defined(KEYBOARD_rgbkb_pan_rev1)
 #        include "ws2812.h"
 
-// LED color buffer
-rgb_led_t rgb_matrix_ws2812_array[RGB_MATRIX_LED_COUNT];
-
-static void flush(void) {
-    ws2812_setleds(rgb_matrix_ws2812_array, RGB_MATRIX_LED_COUNT);
-}
-
 // Set an led in the buffer to a color
 static inline void setled(int i, uint8_t r, uint8_t g, uint8_t b) {
 #        if defined(RGB_ENCODERS) || defined(STAGGERED_RGB_ENCODERS)
     if (i == 0 || i == 1) {  // if encoder LEDs, change LEDs
-        rgb_matrix_ws2812_array[i].r = g;
-        rgb_matrix_ws2812_array[i].g = b;
-        rgb_matrix_ws2812_array[i].b = r;
+        ws2812_set_color(i, g, b, r);
     } else
 #        endif
     {
-        rgb_matrix_ws2812_array[i].r = r;
-        rgb_matrix_ws2812_array[i].g = g;
-        rgb_matrix_ws2812_array[i].b = b;
-    }
-#        ifdef WS2812_RGBW
-    convert_rgb_to_rgbw(&rgb_matrix_ws2812_array[i]);
-#        endif
-}
-
-static void setled_all(uint8_t r, uint8_t g, uint8_t b) {
-    for (int i = 0; i < ARRAY_SIZE(rgb_matrix_ws2812_array); i++) {
-        setled(i, r, g, b);
+        ws2812_set_color(i, r, g, b);
     }
 }
 
 const rgb_matrix_driver_t rgb_matrix_driver = {
     .init          = ws2812_init,
-    .flush         = flush,
+    .flush         = ws2812_flush,
     .set_color     = setled,
-    .set_color_all = setled_all,
+    .set_color_all = ws2812_set_color_all,
 };
 #    endif
 

+ 40 - 20
keyboards/steelseries/prime_plus/rgblight_custom.c

@@ -1,45 +1,65 @@
 // Copyright 2024 Dasky (@daskygit)
 // SPDX-License-Identifier: GPL-2.0-or-later
 
-#include "quantum.h"
+#include <hal.h>
+#include "chibios_config.h"
+#include "gpio.h"
+#include "color.h"
+#include "rgblight_drivers.h"
 
 static PWMConfig pwmCFG = {
     .frequency = 0xFFFF,
     .period    = 256,
 };
 
-void prime_setleds(rgb_led_t *start_led, uint16_t num_leds) {
-    if (start_led[0].r == 0) {
+rgb_led_t prime_leds[RGBLIGHT_LED_COUNT];
+
+void init_custom(void) {
+    palSetPadMode(PAL_PORT(RGB_RED_PIN), PAL_PAD(RGB_RED_PIN), PAL_MODE_ALTERNATE_PUSHPULL);
+    palSetPadMode(PAL_PORT(RGB_GREEN_PIN), PAL_PAD(RGB_GREEN_PIN), PAL_MODE_ALTERNATE_PUSHPULL);
+    palSetPadMode(PAL_PORT(RGB_BLUE_PIN), PAL_PAD(RGB_BLUE_PIN), PAL_MODE_ALTERNATE_PUSHPULL);
+    pwmCFG.channels[RGB_RED_PWM_CHANNEL - 1].mode   = PWM_OUTPUT_ACTIVE_HIGH;
+    pwmCFG.channels[RGB_GREEN_PWM_CHANNEL - 1].mode = PWM_OUTPUT_ACTIVE_HIGH;
+    pwmCFG.channels[RGB_BLUE_PWM_CHANNEL - 1].mode  = PWM_OUTPUT_ACTIVE_HIGH;
+    pwmStart(&RGB_PWM_DRIVER, &pwmCFG);
+}
+
+void set_color_custom(int index, uint8_t red, uint8_t green, uint8_t blue) {
+    prime_leds[index].r = red;
+    prime_leds[index].g = green;
+    prime_leds[index].b = blue;
+}
+
+void set_color_all_custom(uint8_t red, uint8_t green, uint8_t blue) {
+    for (int i = 0; i < RGBLIGHT_LED_COUNT; i++) {
+        set_color_custom(i, red, green, blue);
+    }
+}
+
+void flush_custom(void) {
+    if (prime_leds[0].r == 0) {
         pwmDisableChannel(&RGB_PWM_DRIVER, RGB_RED_PWM_CHANNEL - 1);
     } else {
-        uint32_t duty = ((uint32_t)0xFFFF * start_led[0].r) / 0xFF;
+        uint32_t duty = ((uint32_t)0xFFFF * prime_leds[0].r) / 0xFF;
         pwmEnableChannel(&RGB_PWM_DRIVER, RGB_RED_PWM_CHANNEL - 1, PWM_FRACTION_TO_WIDTH(&RGB_PWM_DRIVER, 0xFFFF, duty));
     }
-    if (start_led[0].g == 0) {
+    if (prime_leds[0].g == 0) {
         pwmDisableChannel(&RGB_PWM_DRIVER, RGB_GREEN_PWM_CHANNEL - 1);
     } else {
-        uint32_t duty = ((uint32_t)0xFFFF * start_led[0].g) / 0xFF;
+        uint32_t duty = ((uint32_t)0xFFFF * prime_leds[0].g) / 0xFF;
         pwmEnableChannel(&RGB_PWM_DRIVER, RGB_GREEN_PWM_CHANNEL - 1, PWM_FRACTION_TO_WIDTH(&RGB_PWM_DRIVER, 0xFFFF, duty));
     }
-    if (start_led[0].b == 0) {
+    if (prime_leds[0].b == 0) {
         pwmDisableChannel(&RGB_PWM_DRIVER, RGB_BLUE_PWM_CHANNEL - 1);
     } else {
-        uint32_t duty = ((uint32_t)0xFFFF * start_led[0].b) / 0xFF;
+        uint32_t duty = ((uint32_t)0xFFFF * prime_leds[0].b) / 0xFF;
         pwmEnableChannel(&RGB_PWM_DRIVER, RGB_BLUE_PWM_CHANNEL - 1, PWM_FRACTION_TO_WIDTH(&RGB_PWM_DRIVER, 0xFFFF, duty));
     }
 }
 
-void prime_initleds(void) {
-    palSetPadMode(PAL_PORT(RGB_RED_PIN), PAL_PAD(RGB_RED_PIN), PAL_MODE_ALTERNATE_PUSHPULL);
-    palSetPadMode(PAL_PORT(RGB_GREEN_PIN), PAL_PAD(RGB_GREEN_PIN), PAL_MODE_ALTERNATE_PUSHPULL);
-    palSetPadMode(PAL_PORT(RGB_BLUE_PIN), PAL_PAD(RGB_BLUE_PIN), PAL_MODE_ALTERNATE_PUSHPULL);
-    pwmCFG.channels[RGB_RED_PWM_CHANNEL - 1].mode   = PWM_OUTPUT_ACTIVE_HIGH;
-    pwmCFG.channels[RGB_GREEN_PWM_CHANNEL - 1].mode = PWM_OUTPUT_ACTIVE_HIGH;
-    pwmCFG.channels[RGB_BLUE_PWM_CHANNEL - 1].mode  = PWM_OUTPUT_ACTIVE_HIGH;
-    pwmStart(&RGB_PWM_DRIVER, &pwmCFG);
-}
-
 const rgblight_driver_t rgblight_driver = {
-    .init    = prime_initleds,
-    .setleds = prime_setleds,
+    .init          = init_custom,
+    .set_color     = set_color_custom,
+    .set_color_all = set_color_all_custom,
+    .flush         = flush_custom,
 };

+ 6 - 12
keyboards/wilba_tech/wt_rgb_backlight.c

@@ -60,7 +60,6 @@
 
 #if defined(RGB_BACKLIGHT_DAWN60)
 #include "ws2812.h"
-rgb_led_t g_ws2812_leds[WS2812_LED_TOTAL];
 #endif
 
 #include "progmem.h"
@@ -1011,6 +1010,9 @@ void backlight_update_pwm_buffers(void)
         driver = 0;
     }
 #else
+#if defined(RGB_BACKLIGHT_DAWN60)
+    ws2812_flush();
+#endif
     is31fl3731_update_pwm_buffers( 0 );
     is31fl3731_update_pwm_buffers( 1 );
     is31fl3731_update_led_control_registers( 0 );
@@ -1037,10 +1039,7 @@ void backlight_set_color( int index, uint8_t red, uint8_t green, uint8_t blue )
     if( index < IS31FL3731_LED_COUNT ) {
         is31fl3731_set_color( index, red, green, blue );
     } else {
-        g_ws2812_leds[index - IS31FL3731_LED_COUNT].r = red;
-        g_ws2812_leds[index - IS31FL3731_LED_COUNT].g = green;
-        g_ws2812_leds[index - IS31FL3731_LED_COUNT].b = blue;
-        ws2812_setleds(g_ws2812_leds, WS2812_LED_TOTAL);
+        ws2812_set_color( index - IS31FL3731_LED_COUNT, red, green, blue );
     }
 #else
     is31fl3731_set_color( index, red, green, blue );
@@ -1075,12 +1074,7 @@ void backlight_set_color_all( uint8_t red, uint8_t green, uint8_t blue )
     }
 #elif defined(RGB_BACKLIGHT_DAWN60)
     is31fl3731_set_color_all( red, green, blue );
-    for (uint8_t i = 0; i < WS2812_LED_TOTAL; i++) {
-        g_ws2812_leds[i].r = red;
-        g_ws2812_leds[i].g = green;
-        g_ws2812_leds[i].b = blue;
-    }
-    ws2812_setleds(g_ws2812_leds, WS2812_LED_TOTAL);
+    ws2812_set_color_all( red, green, blue );
 #else
     is31fl3731_set_color_all( red, green, blue );
 #endif
@@ -1325,7 +1319,7 @@ void backlight_effect_alphas_mods(void)
         }
     }
 #if defined(RGB_BACKLIGHT_DAWN60)
-    for (int i = 0; i < WS2812_LED_TOTAL; i++) {
+    for (int i = 0; i < WS2812_LED_COUNT; i++) {
         if ((RGB_UNDERGLOW_ALPHA_TOP_START <= i && i <= RGB_UNDERGLOW_ALPHA_TOP_END) ||
             (RGB_UNDERGLOW_ALPHA_BOT_START <= i && i <= RGB_UNDERGLOW_ALPHA_BOT_END)) {
             backlight_set_color(i + IS31FL3731_LED_COUNT, rgb1.r, rgb1.g, rgb1.b);

+ 7 - 3
keyboards/work_louder/rgb_functions.c

@@ -26,13 +26,17 @@
 #define WS2812_DI_PIN RGBLIGHT_DI_PIN
 
 #define ws2812_init ws2812_rgb_init
-#define ws2812_setleds ws2812_rgb_setleds
+#define ws2812_set_color ws2812_rgb_set_color
+#define ws2812_set_color_all ws2812_rgb_set_color_all
+#define ws2812_flush ws2812_rgb_flush
 
 #include "ws2812_bitbang.c"
 
 const rgblight_driver_t rgblight_driver = {
-    .init    = ws2812_init,
-    .setleds = ws2812_setleds,
+    .init          = ws2812_init,
+    .set_color     = ws2812_set_color,
+    .set_color_all = ws2812_set_color_all,
+    .flush         = ws2812_flush,
 };
 #endif
 

+ 1 - 1
keyboards/xelus/dawn60/rev1/config.h

@@ -42,7 +42,7 @@
 #define RGB_BACKLIGHT_DAWN60
 
 //RGB Underglow defines
-#define WS2812_LED_TOTAL 20
+#define WS2812_LED_COUNT 20
 
 #define RGB_UNDERGLOW_ALPHA_TOP_START 0
 #define RGB_UNDERGLOW_ALPHA_TOP_END   6   

+ 2 - 2
keyboards/xelus/dawn60/rev1_qmk/config.h

@@ -16,14 +16,14 @@
 #pragma once
 
 //RGB Underglow defines
-#define WS2812_LED_TOTAL 20
+#define WS2812_LED_COUNT 20
 
 //RGB Matrix defines
 #define IS31FL3731_I2C_ADDRESS_1 IS31FL3731_I2C_ADDRESS_GND
 #define IS31FL3731_I2C_ADDRESS_2 IS31FL3731_I2C_ADDRESS_SDA
 #define IS31FL3731_LED_COUNT 64
 
-#define RGB_MATRIX_LED_COUNT (IS31FL3731_LED_COUNT + WS2812_LED_TOTAL)
+#define RGB_MATRIX_LED_COUNT (IS31FL3731_LED_COUNT + WS2812_LED_COUNT)
 
 // enable/disable LEDs based on layout
 // switch between split backspace (1) or normal backspace(0)

+ 3 - 11
keyboards/xelus/dawn60/rev1_qmk/rev1_qmk.c

@@ -23,8 +23,6 @@
 #include "ws2812.h"
 
 #ifdef RGB_MATRIX_ENABLE
-rgb_led_t rgb_matrix_ws2812_array[WS2812_LED_TOTAL];
-
 const is31fl3731_led_t PROGMEM g_is31fl3731_leds[IS31FL3731_LED_COUNT] = {
 /* Refer to IS31 manual for these locations
  *   driver
@@ -161,26 +159,20 @@ static void init(void) {
 static void flush(void) {
     is31fl3731_update_pwm_buffers(0);
     is31fl3731_update_pwm_buffers(1);
-    ws2812_setleds(rgb_matrix_ws2812_array, WS2812_LED_TOTAL);
+    ws2812_flush();
 }
 
 static void set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
     if (index < IS31FL3731_LED_COUNT) {
         is31fl3731_set_color(index, red, green, blue);
     } else {
-        rgb_matrix_ws2812_array[index - IS31FL3731_LED_COUNT].r = red;
-        rgb_matrix_ws2812_array[index - IS31FL3731_LED_COUNT].g = green;
-        rgb_matrix_ws2812_array[index - IS31FL3731_LED_COUNT].b = blue;
+        ws2812_set_color(index - IS31FL3731_LED_COUNT, red, green, blue);
     }
 }
 
 static void set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
     is31fl3731_set_color_all( red, green, blue );
-    for (uint8_t i = 0; i < WS2812_LED_TOTAL; i++) {
-        rgb_matrix_ws2812_array[i].r = red;
-        rgb_matrix_ws2812_array[i].g = green;
-        rgb_matrix_ws2812_array[i].b = blue;
-    }
+    ws2812_set_color_all( red, green, blue );
 }
 
 

+ 3 - 0
keyboards/xiudi/xd002/keymaps/rgb_lite/config.h

@@ -0,0 +1,3 @@
+#pragma once
+
+#define WS2812_LED_COUNT 2

+ 3 - 3
keyboards/xiudi/xd002/keymaps/rgb_lite/rgblite.h

@@ -7,9 +7,9 @@ static inline void rgblite_init(void) {
     ws2812_init();
 }
 
-static inline void rgblite_setrgb(uint8_t _r, uint8_t _g, uint8_t _b) {
-    rgb_led_t leds[RGBLIGHT_LED_COUNT] = {{.r = _r, .g = _g, .b = _b}, {.r = _r, .g = _g, .b = _b}};
-    ws2812_setleds(leds, RGBLIGHT_LED_COUNT);
+static inline void rgblite_setrgb(uint8_t r, uint8_t g, uint8_t b) {
+    ws2812_set_color_all(r, g, b);
+    ws2812_flush();
 }
 
 static void rgblite_increase_hue(void) {

+ 30 - 22
platforms/avr/drivers/ws2812_bitbang.c

@@ -28,28 +28,6 @@
 
 #define pinmask(pin) (_BV((pin)&0xF))
 
-/*
- * Forward declare internal functions
- *
- * The functions take a byte-array and send to the data output as WS2812 bitstream.
- * The length is the number of bytes to send - three per LED.
- */
-
-static inline void ws2812_sendarray_mask(uint8_t *data, uint16_t datlen, uint8_t masklo, uint8_t maskhi);
-
-void ws2812_init(void) {
-    DDRx_ADDRESS(WS2812_DI_PIN) |= pinmask(WS2812_DI_PIN);
-}
-
-void ws2812_setleds(rgb_led_t *ledarray, uint16_t number_of_leds) {
-    uint8_t masklo = ~(pinmask(WS2812_DI_PIN)) & PORTx_ADDRESS(WS2812_DI_PIN);
-    uint8_t maskhi = pinmask(WS2812_DI_PIN) | PORTx_ADDRESS(WS2812_DI_PIN);
-
-    ws2812_sendarray_mask((uint8_t *)ledarray, number_of_leds * sizeof(rgb_led_t), masklo, maskhi);
-
-    _delay_us(WS2812_TRST_US);
-}
-
 /*
   This routine writes an array of bytes with RGB values to the Dataout pin
   using the fast 800kHz clockless WS2811/2812 protocol.
@@ -172,3 +150,33 @@ static inline void ws2812_sendarray_mask(uint8_t *data, uint16_t datlen, uint8_t
 
     SREG = sreg_prev;
 }
+
+ws2812_led_t ws2812_leds[WS2812_LED_COUNT];
+
+void ws2812_init(void) {
+    DDRx_ADDRESS(WS2812_DI_PIN) |= pinmask(WS2812_DI_PIN);
+}
+
+void ws2812_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
+    ws2812_leds[index].r = red;
+    ws2812_leds[index].g = green;
+    ws2812_leds[index].b = blue;
+#if defined(WS2812_RGBW)
+    ws2812_rgb_to_rgbw(&ws2812_leds[index]);
+#endif
+}
+
+void ws2812_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
+    for (int i = 0; i < WS2812_LED_COUNT; i++) {
+        ws2812_set_color(i, red, green, blue);
+    }
+}
+
+void ws2812_flush(void) {
+    uint8_t masklo = ~(pinmask(WS2812_DI_PIN)) & PORTx_ADDRESS(WS2812_DI_PIN);
+    uint8_t maskhi = pinmask(WS2812_DI_PIN) | PORTx_ADDRESS(WS2812_DI_PIN);
+
+    ws2812_sendarray_mask((uint8_t *)ws2812_leds, WS2812_LED_COUNT * sizeof(ws2812_led_t), masklo, maskhi);
+
+    _delay_us(WS2812_TRST_US);
+}

+ 19 - 3
platforms/avr/drivers/ws2812_i2c.c

@@ -1,3 +1,6 @@
+// Copyright 2024 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+
 #include "ws2812.h"
 #include "i2c_master.h"
 
@@ -13,11 +16,24 @@
 #    define WS2812_I2C_TIMEOUT 100
 #endif
 
+ws2812_led_t ws2812_leds[WS2812_LED_COUNT];
+
 void ws2812_init(void) {
     i2c_init();
 }
 
-// Setleds for standard RGB
-void ws2812_setleds(rgb_led_t *ledarray, uint16_t leds) {
-    i2c_transmit(WS2812_I2C_ADDRESS, (uint8_t *)ledarray, sizeof(rgb_led_t) * leds, WS2812_I2C_TIMEOUT);
+void ws2812_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
+    ws2812_leds[index].r = red;
+    ws2812_leds[index].g = green;
+    ws2812_leds[index].b = blue;
+}
+
+void ws2812_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
+    for (int i = 0; i < WS2812_LED_COUNT; i++) {
+        ws2812_set_color(i, red, green, blue);
+    }
+}
+
+void ws2812_flush(void) {
+    i2c_transmit(WS2812_I2C_ADDRESS, (uint8_t *)ws2812_leds, WS2812_LED_COUNT * sizeof(ws2812_led_t), WS2812_I2C_TIMEOUT);
 }

+ 22 - 5
platforms/chibios/drivers/vendor/RP/RP2040/ws2812_vendor.c

@@ -266,19 +266,36 @@ static inline void sync_ws2812_transfer(void) {
     busy_wait_until(LAST_TRANSFER);
 }
 
-void ws2812_setleds(rgb_led_t* ledarray, uint16_t leds) {
+ws2812_led_t ws2812_leds[WS2812_LED_COUNT];
+
+void ws2812_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
+    ws2812_leds[index].r = red;
+    ws2812_leds[index].g = green;
+    ws2812_leds[index].b = blue;
+#if defined(WS2812_RGBW)
+    ws2812_rgb_to_rgbw(&ws2812_leds[index]);
+#endif
+}
+
+void ws2812_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
+    for (int i = 0; i < WS2812_LED_COUNT; i++) {
+        ws2812_set_color(i, red, green, blue);
+    }
+}
+
+void ws2812_flush(void) {
     sync_ws2812_transfer();
 
-    for (int i = 0; i < leds; i++) {
+    for (int i = 0; i < WS2812_LED_COUNT; i++) {
 #if defined(WS2812_RGBW)
-        WS2812_BUFFER[i] = rgbw8888_to_u32(ledarray[i].r, ledarray[i].g, ledarray[i].b, ledarray[i].w);
+        WS2812_BUFFER[i] = rgbw8888_to_u32(ws2812_leds[i].r, ws2812_leds[i].g, ws2812_leds[i].b, ws2812_leds[i].w);
 #else
-        WS2812_BUFFER[i] = rgbw8888_to_u32(ledarray[i].r, ledarray[i].g, ledarray[i].b, 0);
+        WS2812_BUFFER[i] = rgbw8888_to_u32(ws2812_leds[i].r, ws2812_leds[i].g, ws2812_leds[i].b, 0);
 #endif
     }
 
     dmaChannelSetSourceX(dma_channel, (uint32_t)WS2812_BUFFER);
-    dmaChannelSetCounterX(dma_channel, leds);
+    dmaChannelSetCounterX(dma_channel, WS2812_LED_COUNT);
     dmaChannelSetModeX(dma_channel, RP_DMA_MODE_WS2812);
     dmaChannelEnableX(dma_channel);
 }

+ 29 - 13
platforms/chibios/drivers/ws2812_bitbang.c

@@ -76,33 +76,49 @@ void sendByte(uint8_t byte) {
     }
 }
 
+ws2812_led_t ws2812_leds[WS2812_LED_COUNT];
+
 void ws2812_init(void) {
     palSetLineMode(WS2812_DI_PIN, WS2812_OUTPUT_MODE);
 }
 
-// Setleds for standard RGB
-void ws2812_setleds(rgb_led_t *ledarray, uint16_t leds) {
+void ws2812_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
+    ws2812_leds[index].r = red;
+    ws2812_leds[index].g = green;
+    ws2812_leds[index].b = blue;
+#if defined(WS2812_RGBW)
+    ws2812_rgb_to_rgbw(&ws2812_leds[index]);
+#endif
+}
+
+void ws2812_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
+    for (int i = 0; i < WS2812_LED_COUNT; i++) {
+        ws2812_set_color(i, red, green, blue);
+    }
+}
+
+void ws2812_flush(void) {
     // this code is very time dependent, so we need to disable interrupts
     chSysLock();
 
-    for (uint8_t i = 0; i < leds; i++) {
+    for (int i = 0; i < WS2812_LED_COUNT; i++) {
         // WS2812 protocol dictates grb order
 #if (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_GRB)
-        sendByte(ledarray[i].g);
-        sendByte(ledarray[i].r);
-        sendByte(ledarray[i].b);
+        sendByte(ws2812_leds[i].g);
+        sendByte(ws2812_leds[i].r);
+        sendByte(ws2812_leds[i].b);
 #elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_RGB)
-        sendByte(ledarray[i].r);
-        sendByte(ledarray[i].g);
-        sendByte(ledarray[i].b);
+        sendByte(ws2812_leds[i].r);
+        sendByte(ws2812_leds[i].g);
+        sendByte(ws2812_leds[i].b);
 #elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_BGR)
-        sendByte(ledarray[i].b);
-        sendByte(ledarray[i].g);
-        sendByte(ledarray[i].r);
+        sendByte(ws2812_leds[i].b);
+        sendByte(ws2812_leds[i].g);
+        sendByte(ws2812_leds[i].r);
 #endif
 
 #ifdef WS2812_RGBW
-        sendByte(ledarray[i].w);
+        sendByte(ws2812_leds[i].w);
 #endif
     }
 

+ 22 - 6
platforms/chibios/drivers/ws2812_pwm.c

@@ -387,13 +387,29 @@ void ws2812_write_led_rgbw(uint16_t led_number, uint8_t r, uint8_t g, uint8_t b,
     }
 }
 
-// Setleds for standard RGB
-void ws2812_setleds(rgb_led_t* ledarray, uint16_t leds) {
-    for (uint16_t i = 0; i < leds; i++) {
-#ifdef WS2812_RGBW
-        ws2812_write_led_rgbw(i, ledarray[i].r, ledarray[i].g, ledarray[i].b, ledarray[i].w);
+ws2812_led_t ws2812_leds[WS2812_LED_COUNT];
+
+void ws2812_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
+    ws2812_leds[index].r = red;
+    ws2812_leds[index].g = green;
+    ws2812_leds[index].b = blue;
+#if defined(WS2812_RGBW)
+    ws2812_rgb_to_rgbw(&ws2812_leds[index]);
+#endif
+}
+
+void ws2812_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
+    for (int i = 0; i < WS2812_LED_COUNT; i++) {
+        ws2812_set_color(i, red, green, blue);
+    }
+}
+
+void ws2812_flush(void) {
+    for (int i = 0; i < WS2812_LED_COUNT; i++) {
+#if defined(WS2812_RGBW)
+        ws2812_write_led_rgbw(i, ws2812_leds[i].r, ws2812_leds[i].g, ws2812_leds[i].b, ws2812_leds[i].w);
 #else
-        ws2812_write_led(i, ledarray[i].r, ledarray[i].g, ledarray[i].b);
+        ws2812_write_led(i, ws2812_leds[i].r, ws2812_leds[i].g, ws2812_leds[i].b);
 #endif
     }
 }

+ 21 - 4
platforms/chibios/drivers/ws2812_spi.c

@@ -106,7 +106,7 @@ static uint8_t get_protocol_eq(uint8_t data, int pos) {
     return eq;
 }
 
-static void set_led_color_rgb(rgb_led_t color, int pos) {
+static void set_led_color_rgb(ws2812_led_t color, int pos) {
     uint8_t* tx_start = &txbuf[PREAMBLE_SIZE];
 
 #if (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_GRB)
@@ -137,6 +137,8 @@ static void set_led_color_rgb(rgb_led_t color, int pos) {
 #endif
 }
 
+ws2812_led_t ws2812_leds[WS2812_LED_COUNT];
+
 void ws2812_init(void) {
     palSetLineMode(WS2812_DI_PIN, WS2812_MOSI_OUTPUT_MODE);
 
@@ -187,9 +189,24 @@ void ws2812_init(void) {
 #endif
 }
 
-void ws2812_setleds(rgb_led_t* ledarray, uint16_t leds) {
-    for (uint8_t i = 0; i < leds; i++) {
-        set_led_color_rgb(ledarray[i], i);
+void ws2812_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
+    ws2812_leds[index].r = red;
+    ws2812_leds[index].g = green;
+    ws2812_leds[index].b = blue;
+#if defined(WS2812_RGBW)
+    ws2812_rgb_to_rgbw(&ws2812_leds[index]);
+#endif
+}
+
+void ws2812_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
+    for (int i = 0; i < WS2812_LED_COUNT; i++) {
+        ws2812_set_color(i, red, green, blue);
+    }
+}
+
+void ws2812_flush(void) {
+    for (int i = 0; i < WS2812_LED_COUNT; i++) {
+        set_led_color_rgb(ws2812_leds[i], i);
     }
 
     // Send async - each led takes ~0.03ms, 50 leds ~1.5ms, animations flushing faster than send will cause issues.

+ 0 - 11
quantum/color.c

@@ -108,14 +108,3 @@ RGB hsv_to_rgb(HSV hsv) {
 RGB hsv_to_rgb_nocie(HSV hsv) {
     return hsv_to_rgb_impl(hsv, false);
 }
-
-#ifdef WS2812_RGBW
-void convert_rgb_to_rgbw(rgb_led_t *led) {
-    // Determine lowest value in all three colors, put that into
-    // the white channel and then shift all colors by that amount
-    led->w = MIN(led->r, MIN(led->g, led->b));
-    led->r -= led->w;
-    led->g -= led->w;
-    led->b -= led->w;
-}
-#endif

+ 0 - 24
quantum/color.h

@@ -74,31 +74,10 @@
 
 // clang-format on
 
-#define WS2812_BYTE_ORDER_RGB 0
-#define WS2812_BYTE_ORDER_GRB 1
-#define WS2812_BYTE_ORDER_BGR 2
-
-#ifndef WS2812_BYTE_ORDER
-#    define WS2812_BYTE_ORDER WS2812_BYTE_ORDER_GRB
-#endif
-
 typedef struct PACKED rgb_led_t {
-#if (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_GRB)
-    uint8_t g;
-    uint8_t r;
-    uint8_t b;
-#elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_RGB)
     uint8_t r;
     uint8_t g;
     uint8_t b;
-#elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_BGR)
-    uint8_t b;
-    uint8_t g;
-    uint8_t r;
-#endif
-#ifdef WS2812_RGBW
-    uint8_t w;
-#endif
 } rgb_led_t;
 
 typedef rgb_led_t RGB;
@@ -111,6 +90,3 @@ typedef struct PACKED HSV {
 
 RGB hsv_to_rgb(HSV hsv);
 RGB hsv_to_rgb_nocie(HSV hsv);
-#ifdef WS2812_RGBW
-void convert_rgb_to_rgbw(rgb_led_t *led);
-#endif

+ 10 - 1
quantum/led_matrix/led_matrix.c

@@ -139,11 +139,20 @@ void led_matrix_update_pwm_buffers(void) {
     led_matrix_driver.flush();
 }
 
+__attribute__((weak)) int led_matrix_led_index(int index) {
+#if defined(LED_MATRIX_SPLIT)
+    if (!is_keyboard_left() && index >= k_led_matrix_split[0]) {
+        return index - k_led_matrix_split[0];
+    }
+#endif
+    return index;
+}
+
 void led_matrix_set_value(int index, uint8_t value) {
 #ifdef USE_CIE1931_CURVE
     value = pgm_read_byte(&CIE1931_CURVE[value]);
 #endif
-    led_matrix_driver.set_value(index, value);
+    led_matrix_driver.set_value(led_matrix_led_index(index), value);
 }
 
 void led_matrix_set_value_all(uint8_t value) {

+ 2 - 0
quantum/led_matrix/led_matrix.h

@@ -121,6 +121,8 @@ void eeconfig_debug_led_matrix(void);
 uint8_t led_matrix_map_row_column_to_led_kb(uint8_t row, uint8_t column, uint8_t *led_i);
 uint8_t led_matrix_map_row_column_to_led(uint8_t row, uint8_t column, uint8_t *led_i);
 
+int led_matrix_led_index(int index);
+
 void led_matrix_set_value(int index, uint8_t value);
 void led_matrix_set_value_all(uint8_t value);
 

+ 10 - 1
quantum/rgb_matrix/rgb_matrix.c

@@ -143,8 +143,17 @@ void rgb_matrix_update_pwm_buffers(void) {
     rgb_matrix_driver.flush();
 }
 
+__attribute__((weak)) int rgb_matrix_led_index(int index) {
+#if defined(RGB_MATRIX_SPLIT)
+    if (!is_keyboard_left() && index >= k_rgb_matrix_split[0]) {
+        return index - k_rgb_matrix_split[0];
+    }
+#endif
+    return index;
+}
+
 void rgb_matrix_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
-    rgb_matrix_driver.set_color(index, red, green, blue);
+    rgb_matrix_driver.set_color(rgb_matrix_led_index(index), red, green, blue);
 }
 
 void rgb_matrix_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {

+ 2 - 0
quantum/rgb_matrix/rgb_matrix.h

@@ -145,6 +145,8 @@ void eeconfig_update_rgb_matrix(void);
 uint8_t rgb_matrix_map_row_column_to_led_kb(uint8_t row, uint8_t column, uint8_t *led_i);
 uint8_t rgb_matrix_map_row_column_to_led(uint8_t row, uint8_t column, uint8_t *led_i);
 
+int rgb_matrix_led_index(int index);
+
 void rgb_matrix_set_color(int index, uint8_t red, uint8_t green, uint8_t blue);
 void rgb_matrix_set_color_all(uint8_t red, uint8_t green, uint8_t blue);
 

+ 4 - 54
quantum/rgb_matrix/rgb_matrix_drivers.c

@@ -146,61 +146,11 @@ const rgb_matrix_driver_t rgb_matrix_driver = {
 #        pragma message "You need to use a custom driver, or re-implement the WS2812 driver to use a different configuration."
 #    endif
 
-// LED color buffer
-rgb_led_t rgb_matrix_ws2812_array[WS2812_LED_COUNT];
-bool      ws2812_dirty = false;
-
-static void init(void) {
-    ws2812_init();
-    ws2812_dirty = false;
-}
-
-static void flush(void) {
-    if (ws2812_dirty) {
-        ws2812_setleds(rgb_matrix_ws2812_array, WS2812_LED_COUNT);
-        ws2812_dirty = false;
-    }
-}
-
-// Set an led in the buffer to a color
-static inline void setled(int i, uint8_t r, uint8_t g, uint8_t b) {
-#    if defined(RGB_MATRIX_SPLIT)
-    const uint8_t k_rgb_matrix_split[2] = RGB_MATRIX_SPLIT;
-    if (!is_keyboard_left()) {
-        if (i >= k_rgb_matrix_split[0]) {
-            i -= k_rgb_matrix_split[0];
-        } else {
-            return;
-        }
-    } else if (i >= k_rgb_matrix_split[0]) {
-        return;
-    }
-#    endif
-
-    if (rgb_matrix_ws2812_array[i].r == r && rgb_matrix_ws2812_array[i].g == g && rgb_matrix_ws2812_array[i].b == b) {
-        return;
-    }
-
-    ws2812_dirty                 = true;
-    rgb_matrix_ws2812_array[i].r = r;
-    rgb_matrix_ws2812_array[i].g = g;
-    rgb_matrix_ws2812_array[i].b = b;
-#    ifdef WS2812_RGBW
-    convert_rgb_to_rgbw(&rgb_matrix_ws2812_array[i]);
-#    endif
-}
-
-static void setled_all(uint8_t r, uint8_t g, uint8_t b) {
-    for (int i = 0; i < ARRAY_SIZE(rgb_matrix_ws2812_array); i++) {
-        setled(i, r, g, b);
-    }
-}
-
 const rgb_matrix_driver_t rgb_matrix_driver = {
-    .init          = init,
-    .flush         = flush,
-    .set_color     = setled,
-    .set_color_all = setled_all,
+    .init          = ws2812_init,
+    .flush         = ws2812_flush,
+    .set_color     = ws2812_set_color,
+    .set_color_all = ws2812_set_color_all,
 };
 
 #endif

+ 45 - 107
quantum/rgblight/rgblight.c

@@ -115,11 +115,6 @@ static bool pre_suspend_enabled;
 animation_status_t animation_status = {};
 #endif
 
-#ifndef LED_ARRAY
-rgb_led_t led[RGBLIGHT_LED_COUNT];
-#    define LED_ARRAY led
-#endif
-
 #ifdef RGBLIGHT_LAYERS
 rgblight_segment_t const *const *rgblight_layers = NULL;
 
@@ -145,23 +140,26 @@ __attribute__((weak)) RGB rgblight_hsv_to_rgb(HSV hsv) {
     return hsv_to_rgb(hsv);
 }
 
-void setrgb(uint8_t r, uint8_t g, uint8_t b, rgb_led_t *led1) {
-    led1->r = r;
-    led1->g = g;
-    led1->b = b;
-#ifdef WS2812_RGBW
-    led1->w = 0;
+uint8_t rgblight_led_index(uint8_t index) {
+#if defined(RGBLIGHT_LED_MAP)
+    return pgm_read_byte(&led_map[index]) - rgblight_ranges.clipping_start_pos;
+#else
+    return index - rgblight_ranges.clipping_start_pos;
 #endif
 }
 
-void sethsv_raw(uint8_t hue, uint8_t sat, uint8_t val, rgb_led_t *led1) {
+void setrgb(uint8_t r, uint8_t g, uint8_t b, int index) {
+    rgblight_driver.set_color(rgblight_led_index(index), r, g, b);
+}
+
+void sethsv_raw(uint8_t hue, uint8_t sat, uint8_t val, int index) {
     HSV hsv = {hue, sat, val};
     RGB rgb = rgblight_hsv_to_rgb(hsv);
-    setrgb(rgb.r, rgb.g, rgb.b, led1);
+    setrgb(rgb.r, rgb.g, rgb.b, index);
 }
 
-void sethsv(uint8_t hue, uint8_t sat, uint8_t val, rgb_led_t *led1) {
-    sethsv_raw(hue, sat, val > RGBLIGHT_LIMIT_VAL ? RGBLIGHT_LIMIT_VAL : val, led1);
+void sethsv(uint8_t hue, uint8_t sat, uint8_t val, int index) {
+    sethsv_raw(hue, sat, val > RGBLIGHT_LIMIT_VAL ? RGBLIGHT_LIMIT_VAL : val, index);
 }
 
 void rgblight_check_config(void) {
@@ -515,9 +513,8 @@ void rgblight_decrease_speed_noeeprom(void) {
 
 void rgblight_sethsv_noeeprom_old(uint8_t hue, uint8_t sat, uint8_t val) {
     if (rgblight_config.enable) {
-        rgb_led_t tmp_led;
-        sethsv(hue, sat, val, &tmp_led);
-        rgblight_setrgb(tmp_led.r, tmp_led.g, tmp_led.b);
+        RGB rgb = hsv_to_rgb((HSV){hue, sat, val > RGBLIGHT_LIMIT_VAL ? RGBLIGHT_LIMIT_VAL : val});
+        rgblight_setrgb(rgb.r, rgb.g, rgb.b);
     }
 }
 
@@ -531,13 +528,12 @@ void rgblight_sethsv_eeprom_helper(uint8_t hue, uint8_t sat, uint8_t val, bool w
         rgblight_status.base_mode = mode_base_table[rgblight_config.mode];
         if (rgblight_config.mode == RGBLIGHT_MODE_STATIC_LIGHT) {
             // same static color
-            rgb_led_t tmp_led;
 #ifdef RGBLIGHT_LAYERS_RETAIN_VAL
             // needed for rgblight_layers_write() to get the new val, since it reads rgblight_config.val
             rgblight_config.val = val;
 #endif
-            sethsv(hue, sat, val, &tmp_led);
-            rgblight_setrgb(tmp_led.r, tmp_led.g, tmp_led.b);
+            RGB rgb = hsv_to_rgb((HSV){hue, sat, val > RGBLIGHT_LIMIT_VAL ? RGBLIGHT_LIMIT_VAL : val});
+            rgblight_setrgb(rgb.r, rgb.g, rgb.b);
         } else {
             // all LEDs in same color
             if (1 == 0) { // dummy
@@ -575,7 +571,7 @@ void rgblight_sethsv_eeprom_helper(uint8_t hue, uint8_t sat, uint8_t val, bool w
                         _hue = hue - _hue;
                     }
                     dprintf("rgblight rainbow set hsv: %d,%d,%d,%u\n", i, _hue, direction, range);
-                    sethsv(_hue, sat, val, (rgb_led_t *)&led[i + rgblight_ranges.effect_start_pos]);
+                    sethsv(_hue, sat, val, i + rgblight_ranges.effect_start_pos);
                 }
 #    ifdef RGBLIGHT_LAYERS_RETAIN_VAL
                 // needed for rgblight_layers_write() to get the new val, since it reads rgblight_config.val
@@ -649,12 +645,7 @@ void rgblight_setrgb(uint8_t r, uint8_t g, uint8_t b) {
     }
 
     for (uint8_t i = rgblight_ranges.effect_start_pos; i < rgblight_ranges.effect_end_pos; i++) {
-        led[i].r = r;
-        led[i].g = g;
-        led[i].b = b;
-#ifdef WS2812_RGBW
-        led[i].w = 0;
-#endif
+        rgblight_driver.set_color(rgblight_led_index(i), r, g, b);
     }
     rgblight_set();
 }
@@ -664,12 +655,7 @@ void rgblight_setrgb_at(uint8_t r, uint8_t g, uint8_t b, uint8_t index) {
         return;
     }
 
-    led[index].r = r;
-    led[index].g = g;
-    led[index].b = b;
-#ifdef WS2812_RGBW
-    led[index].w = 0;
-#endif
+    rgblight_driver.set_color(rgblight_led_index(index), r, g, b);
     rgblight_set();
 }
 
@@ -678,9 +664,8 @@ void rgblight_sethsv_at(uint8_t hue, uint8_t sat, uint8_t val, uint8_t index) {
         return;
     }
 
-    rgb_led_t tmp_led;
-    sethsv(hue, sat, val, &tmp_led);
-    rgblight_setrgb_at(tmp_led.r, tmp_led.g, tmp_led.b, index);
+    RGB rgb = hsv_to_rgb((HSV){hue, sat, val > RGBLIGHT_LIMIT_VAL ? RGBLIGHT_LIMIT_VAL : val});
+    rgblight_setrgb_at(rgb.r, rgb.g, rgb.b, index);
 }
 
 #if defined(RGBLIGHT_EFFECT_BREATHING) || defined(RGBLIGHT_EFFECT_RAINBOW_MOOD) || defined(RGBLIGHT_EFFECT_RAINBOW_SWIRL) || defined(RGBLIGHT_EFFECT_SNAKE) || defined(RGBLIGHT_EFFECT_KNIGHT) || defined(RGBLIGHT_EFFECT_TWINKLE)
@@ -701,12 +686,7 @@ void rgblight_setrgb_range(uint8_t r, uint8_t g, uint8_t b, uint8_t start, uint8
     }
 
     for (uint8_t i = start; i < end; i++) {
-        led[i].r = r;
-        led[i].g = g;
-        led[i].b = b;
-#ifdef WS2812_RGBW
-        led[i].w = 0;
-#endif
+        rgblight_driver.set_color(rgblight_led_index(i), r, g, b);
     }
     rgblight_set();
 }
@@ -716,9 +696,8 @@ void rgblight_sethsv_range(uint8_t hue, uint8_t sat, uint8_t val, uint8_t start,
         return;
     }
 
-    rgb_led_t tmp_led;
-    sethsv(hue, sat, val, &tmp_led);
-    rgblight_setrgb_range(tmp_led.r, tmp_led.g, tmp_led.b, start, end);
+    RGB rgb = hsv_to_rgb((HSV){hue, sat, val > RGBLIGHT_LIMIT_VAL ? RGBLIGHT_LIMIT_VAL : val});
+    rgblight_setrgb_range(rgb.r, rgb.g, rgb.b, start, end);
 }
 
 #ifndef RGBLIGHT_SPLIT
@@ -785,12 +764,12 @@ static void rgblight_layers_write(void) {
                 break; // No more segments
             }
             // Write segment.count LEDs
-            rgb_led_t *const limit = &led[MIN(segment.index + segment.count, RGBLIGHT_LED_COUNT)];
-            for (rgb_led_t *led_ptr = &led[segment.index]; led_ptr < limit; led_ptr++) {
+            int limit = MIN(segment.index + segment.count, RGBLIGHT_LED_COUNT);
+            for (int i = segment.index; i < limit; i++) {
 #    ifdef RGBLIGHT_LAYERS_RETAIN_VAL
-                sethsv(segment.hue, segment.sat, current_val, led_ptr);
+                sethsv(segment.hue, segment.sat, current_val, i);
 #    else
-                sethsv(segment.hue, segment.sat, segment.val, led_ptr);
+                sethsv(segment.hue, segment.sat, segment.val, i);
 #    endif
             }
             segment_ptr++;
@@ -897,17 +876,9 @@ void rgblight_wakeup(void) {
 #endif
 
 void rgblight_set(void) {
-    rgb_led_t *start_led;
-    uint8_t    num_leds = rgblight_ranges.clipping_num_leds;
-
     if (!rgblight_config.enable) {
         for (uint8_t i = rgblight_ranges.effect_start_pos; i < rgblight_ranges.effect_end_pos; i++) {
-            led[i].r = 0;
-            led[i].g = 0;
-            led[i].b = 0;
-#ifdef WS2812_RGBW
-            led[i].w = 0;
-#endif
+            rgblight_driver.set_color(rgblight_led_index(i), 0, 0, 0);
         }
     }
 
@@ -923,22 +894,7 @@ void rgblight_set(void) {
     }
 #endif
 
-#ifdef RGBLIGHT_LED_MAP
-    rgb_led_t led0[RGBLIGHT_LED_COUNT];
-    for (uint8_t i = 0; i < RGBLIGHT_LED_COUNT; i++) {
-        led0[i] = led[pgm_read_byte(&led_map[i])];
-    }
-    start_led = led0 + rgblight_ranges.clipping_start_pos;
-#else
-    start_led = led + rgblight_ranges.clipping_start_pos;
-#endif
-
-#ifdef WS2812_RGBW
-    for (uint8_t i = 0; i < num_leds; i++) {
-        convert_rgb_to_rgbw(&start_led[i]);
-    }
-#endif
-    rgblight_driver.setleds(start_led, num_leds);
+    rgblight_driver.flush();
 }
 
 #ifdef RGBLIGHT_SPLIT
@@ -1222,7 +1178,7 @@ void rgblight_effect_rainbow_swirl(animation_status_t *anim) {
 
     for (i = 0; i < rgblight_ranges.effect_num_leds; i++) {
         hue = (RGBLIGHT_RAINBOW_SWIRL_RANGE / rgblight_ranges.effect_num_leds * i + anim->current_hue);
-        sethsv(hue, rgblight_config.sat, rgblight_config.val, (rgb_led_t *)&led[i + rgblight_ranges.effect_start_pos]);
+        sethsv(hue, rgblight_config.sat, rgblight_config.val, i + rgblight_ranges.effect_start_pos);
     }
     rgblight_set();
 
@@ -1259,13 +1215,8 @@ void rgblight_effect_snake(animation_status_t *anim) {
 #    endif
 
     for (i = 0; i < rgblight_ranges.effect_num_leds; i++) {
-        rgb_led_t *ledp = led + i + rgblight_ranges.effect_start_pos;
-        ledp->r         = 0;
-        ledp->g         = 0;
-        ledp->b         = 0;
-#    ifdef WS2812_RGBW
-        ledp->w = 0;
-#    endif
+        rgblight_driver.set_color(rgblight_led_index(i + rgblight_ranges.effect_start_pos), 0, 0, 0);
+
         for (j = 0; j < RGBLIGHT_EFFECT_SNAKE_LENGTH; j++) {
             k = pos + j * increment;
             if (k > RGBLIGHT_LED_COUNT) {
@@ -1275,7 +1226,7 @@ void rgblight_effect_snake(animation_status_t *anim) {
                 k = k + rgblight_ranges.effect_num_leds;
             }
             if (i == k) {
-                sethsv(rgblight_config.hue, rgblight_config.sat, (uint8_t)(rgblight_config.val * (RGBLIGHT_EFFECT_SNAKE_LENGTH - j) / RGBLIGHT_EFFECT_SNAKE_LENGTH), ledp);
+                sethsv(rgblight_config.hue, rgblight_config.sat, (uint8_t)(rgblight_config.val * (RGBLIGHT_EFFECT_SNAKE_LENGTH - j) / RGBLIGHT_EFFECT_SNAKE_LENGTH), i + rgblight_ranges.effect_start_pos);
             }
         }
     }
@@ -1320,26 +1271,16 @@ void rgblight_effect_knight(animation_status_t *anim) {
 #    endif
     // Set all the LEDs to 0
     for (i = rgblight_ranges.effect_start_pos; i < rgblight_ranges.effect_end_pos; i++) {
-        led[i].r = 0;
-        led[i].g = 0;
-        led[i].b = 0;
-#    ifdef WS2812_RGBW
-        led[i].w = 0;
-#    endif
+        rgblight_driver.set_color(rgblight_led_index(i), 0, 0, 0);
     }
     // Determine which LEDs should be lit up
     for (i = 0; i < RGBLIGHT_EFFECT_KNIGHT_LED_NUM; i++) {
         cur = (i + RGBLIGHT_EFFECT_KNIGHT_OFFSET) % rgblight_ranges.effect_num_leds + rgblight_ranges.effect_start_pos;
 
         if (i >= low_bound && i <= high_bound) {
-            sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, (rgb_led_t *)&led[cur]);
+            sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, cur);
         } else {
-            led[cur].r = 0;
-            led[cur].g = 0;
-            led[cur].b = 0;
-#    ifdef WS2812_RGBW
-            led[cur].w = 0;
-#    endif
+            rgblight_driver.set_color(rgblight_led_index(cur), 0, 0, 0);
         }
     }
     rgblight_set();
@@ -1384,7 +1325,7 @@ void rgblight_effect_christmas(animation_status_t *anim) {
 
     for (i = 0; i < rgblight_ranges.effect_num_leds; i++) {
         uint8_t local_hue = (i / RGBLIGHT_EFFECT_CHRISTMAS_STEP) % 2 ? hue : hue_green - hue;
-        sethsv(local_hue, rgblight_config.sat, val, (rgb_led_t *)&led[i + rgblight_ranges.effect_start_pos]);
+        sethsv(local_hue, rgblight_config.sat, val, i + rgblight_ranges.effect_start_pos);
     }
     rgblight_set();
 
@@ -1407,9 +1348,8 @@ void rgblight_effect_rgbtest(animation_status_t *anim) {
     uint8_t        b;
 
     if (maxval == 0) {
-        rgb_led_t tmp_led;
-        sethsv(0, 255, RGBLIGHT_LIMIT_VAL, &tmp_led);
-        maxval = tmp_led.r;
+        RGB rgb = hsv_to_rgb((HSV){0, 255, RGBLIGHT_LIMIT_VAL});
+        maxval  = rgb.r;
     }
     g = r = b = 0;
     switch (anim->pos) {
@@ -1431,13 +1371,12 @@ void rgblight_effect_rgbtest(animation_status_t *anim) {
 #ifdef RGBLIGHT_EFFECT_ALTERNATING
 void rgblight_effect_alternating(animation_status_t *anim) {
     for (int i = 0; i < rgblight_ranges.effect_num_leds; i++) {
-        rgb_led_t *ledp = led + i + rgblight_ranges.effect_start_pos;
         if (i < rgblight_ranges.effect_num_leds / 2 && anim->pos) {
-            sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, ledp);
+            sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, i + rgblight_ranges.effect_start_pos);
         } else if (i >= rgblight_ranges.effect_num_leds / 2 && !anim->pos) {
-            sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, ledp);
+            sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, i + rgblight_ranges.effect_start_pos);
         } else {
-            sethsv(rgblight_config.hue, rgblight_config.sat, 0, ledp);
+            sethsv(rgblight_config.hue, rgblight_config.sat, 0, i + rgblight_ranges.effect_start_pos);
         }
     }
     rgblight_set();
@@ -1504,8 +1443,7 @@ void rgblight_effect_twinkle(animation_status_t *anim) {
             // This LED is off, and was NOT selected to start brightening
         }
 
-        rgb_led_t *ledp = led + i + rgblight_ranges.effect_start_pos;
-        sethsv(c->h, c->s, c->v, ledp);
+        sethsv(c->h, c->s, c->v, i + rgblight_ranges.effect_start_pos);
     }
 
     rgblight_set();

+ 0 - 1
quantum/rgblight/rgblight.h

@@ -169,7 +169,6 @@ enum RGBLIGHT_EFFECT_MODE {
 #include "rgblight_drivers.h"
 #include "progmem.h"
 #include "eeconfig.h"
-#include "ws2812.h"
 #include "color.h"
 
 #ifdef RGBLIGHT_LAYERS

+ 8 - 12
quantum/rgblight/rgblight_drivers.c

@@ -7,24 +7,20 @@
 #    include "ws2812.h"
 
 const rgblight_driver_t rgblight_driver = {
-    .init    = ws2812_init,
-    .setleds = ws2812_setleds,
+    .init          = ws2812_init,
+    .set_color     = ws2812_set_color,
+    .set_color_all = ws2812_set_color_all,
+    .flush         = ws2812_flush,
 };
 
 #elif defined(RGBLIGHT_APA102)
 #    include "apa102.h"
 
-// Temporary shim
-static void apa102_setleds(rgb_led_t *ledarray, uint16_t number_of_leds) {
-    for (uint16_t i = 0; i < number_of_leds; i++) {
-        apa102_set_color(i, ledarray[i].r, ledarray[i].g, ledarray[i].b);
-    }
-    apa102_flush();
-}
-
 const rgblight_driver_t rgblight_driver = {
-    .init    = apa102_init,
-    .setleds = apa102_setleds,
+    .init          = apa102_init,
+    .set_color     = apa102_set_color,
+    .set_color_all = apa102_set_color_all,
+    .flush         = apa102_flush,
 };
 
 #endif

+ 3 - 2
quantum/rgblight/rgblight_drivers.h

@@ -4,11 +4,12 @@
 #pragma once
 
 #include <stdint.h>
-#include "color.h"
 
 typedef struct {
     void (*init)(void);
-    void (*setleds)(rgb_led_t *ledarray, uint16_t number_of_leds);
+    void (*set_color)(int index, uint8_t red, uint8_t green, uint8_t blue);
+    void (*set_color_all)(uint8_t red, uint8_t green, uint8_t blue);
+    void (*flush)(void);
 } rgblight_driver_t;
 
 extern const rgblight_driver_t rgblight_driver;