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>
This commit is contained in:
Ryan 2024-10-06 19:01:07 +11:00 committed by GitHub
parent 43e82ed5c7
commit 208ebf54a9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
61 changed files with 649 additions and 672 deletions

View file

@ -932,7 +932,7 @@ ifeq ($(strip $(WS2812_DRIVER_REQUIRED)), yes)
OPT_DEFS += -DWS2812_$(strip $(shell echo $(WS2812_DRIVER) | tr '[:lower:]' '[:upper:]')) 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 $(PLATFORM)), CHIBIOS)
ifeq ($(strip $(WS2812_DRIVER)), pwm) ifeq ($(strip $(WS2812_DRIVER)), pwm)

View file

@ -241,13 +241,44 @@ Using a complementary timer output (`TIMx_CHyN`) is possible only for advanced-c
## API {#api} ## 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` ### `void ws2812_set_color(int index, uint8_t red, uint8_t green, uint8_t blue)` {#api-ws2812-set-color}
A pointer to the LED array.
- `uint16_t number_of_leds` Set the color of a single LED. This function does not immediately update the LEDs; call `ws2812_flush()` after you are finished.
The length of the LED array.
#### 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
drivers/ws2812.c Normal file
View file

@ -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

View file

@ -15,7 +15,7 @@
#pragma once #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 * 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 # define WS2812_LED_COUNT RGB_MATRIX_LED_COUNT
#endif #endif
void ws2812_init(void); #define WS2812_BYTE_ORDER_RGB 0
#define WS2812_BYTE_ORDER_GRB 1
#define WS2812_BYTE_ORDER_BGR 2
/* User Interface #ifndef WS2812_BYTE_ORDER
* # define WS2812_BYTE_ORDER WS2812_BYTE_ORDER_GRB
* Input: #endif
* ledarray: An array of GRB data describing the LED colors
* number_of_leds: The number of LEDs to write typedef struct PACKED ws2812_led_t {
* #if (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_GRB)
* The functions will perform the following actions: uint8_t g;
* - Set the data-out pin as output uint8_t r;
* - Send out the LED data uint8_t b;
* - Wait 50us to reset the LEDs #elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_RGB)
*/ uint8_t r;
void ws2812_setleds(rgb_led_t *ledarray, uint16_t number_of_leds); 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);
void ws2812_rgb_to_rgbw(ws2812_led_t *led);

View file

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

View file

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

View file

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

View file

@ -21,47 +21,55 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "ergodox_ez.h" #include "ergodox_ez.h"
#include "ws2812.h" #include "ws2812.h"
void setleds_custom(rgb_led_t *led, uint16_t led_num) { #define WS2812_I2C_ADDRESS_LEFT 0x84
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];
#endif
}
i2c_transmit(0x84, data, sizeof(data), ERGODOX_EZ_I2C_TIMEOUT);
ws2812_setleds(led, led_num); #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);
}
}
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 = { const rgblight_driver_t rgblight_driver = {
.init = ws2812_init, .init = ws2812_init,
.setleds = setleds_custom, .set_color = set_color_custom,
.set_color_all = set_color_all_custom,
.flush = flush_custom,
}; };

View file

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

View file

@ -2,8 +2,6 @@
#include "ws2812.h" #include "ws2812.h"
#include "rgbsps.h" #include "rgbsps.h"
rgb_led_t led[RGBSPS_NUM];
void keyboard_pre_init_kb(void) { void keyboard_pre_init_kb(void) {
ws2812_init(); 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) { void rgbsps_set(uint8_t index, uint8_t r, uint8_t g, uint8_t b) {
led[index].r = r; ws2812_set_color(index, r, g, b);
led[index].g = g;
led[index].b = b;
} }
void rgbsps_setall(uint8_t r, uint8_t g, uint8_t 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) { 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) { void rgbsps_sethsv(uint8_t index, uint16_t hue, uint8_t sat, uint8_t val) {

View file

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

View file

@ -39,27 +39,10 @@ static uint8_t isRecording = 0;
# if RGBLIGHT_LED_COUNT < 3 # if RGBLIGHT_LED_COUNT < 3
# error we need at least 3 RGB LEDs! # error we need at least 3 RGB LEDs!
# endif # endif
static rgb_led_t led[RGBLIGHT_LED_COUNT] = {{255, 255, 255}, {255, 255, 255}, {255, 255, 255}};
# define BRIGHT 32 # define BRIGHT 32
# define DIM 6 # 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 led_t led_state;
static uint8_t layer; static uint8_t layer;
static uint8_t default_layer; static uint8_t default_layer;
@ -81,17 +64,15 @@ void sleep_led_enable(void) {
suspend_active = true; suspend_active = true;
gpio_write_pin_low(MODELM_STATUS_LED); gpio_write_pin_low(MODELM_STATUS_LED);
#ifdef KEYBOARD_ibm_model_m_mschwingen_led_ws2812 #ifdef KEYBOARD_ibm_model_m_mschwingen_led_ws2812
led[0] = black; ws2812_set_color_all(0, 0, 0);
led[1] = black; ws2812_flush();
led[2] = black;
ws2812_setleds(led, RGBLIGHT_LED_COUNT);
#endif #endif
} }
void keyboard_pre_init_kb(void) { void keyboard_pre_init_kb(void) {
#ifdef KEYBOARD_ibm_model_m_mschwingen_led_ws2812 #ifdef KEYBOARD_ibm_model_m_mschwingen_led_ws2812
ws2812_init(); ws2812_init();
ws2812_setleds(led, RGBLIGHT_LED_COUNT); ws2812_flush();
#else #else
/* Set status LEDs pins to output and Low (on) */ /* Set status LEDs pins to output and Low (on) */
gpio_set_pin_output(MODELM_LED_CAPSLOCK); 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 #ifdef KEYBOARD_ibm_model_m_mschwingen_led_ws2812
static void led_update_rgb(void) { static void led_update_rgb(void) {
if (isRecording && blink_state) { if (isRecording && blink_state) {
led[0] = white; ws2812_set_color(0, BRIGHT, BRIGHT, BRIGHT);
} else { } else {
switch (default_layer) { switch (default_layer) {
case 0: 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; break;
case 1: 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; 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) { switch (layer) {
case 0: case 0:
case 1: case 1:
default: 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; break;
case 2: 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; break;
case 3: 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; break;
} }
if (!suspend_active) { if (!suspend_active) {
ws2812_setleds(led, RGBLIGHT_LED_COUNT); ws2812_flush();
} }
} }

View file

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

View file

@ -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_CA1, CB9_CA1, CB8_CA1}, // Down
{0, CB7_CA7, CB9_CA7, CB8_CA7}, // Right {0, CB7_CA7, CB9_CA7, CB8_CA7}, // Right
}; };
int rgb_matrix_led_index(int index) {
return index;
}
#endif #endif

View file

@ -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_CA1, CB9_CA1, CB8_CA1}, // Down
{0, CB7_CA7, CB9_CA7, CB8_CA7}, // Right {0, CB7_CA7, CB9_CA7, CB8_CA7}, // Right
}; };
int rgb_matrix_led_index(int index) {
return index;
}
#endif #endif

View file

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

View file

@ -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 }, { 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 // 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 } { 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} ,{ 28, 40}, { 62, 40}, { 96, 40}, {130, 40}, {164, 40}, {198, 40}
# endif # endif
}, { }, {
@ -124,7 +124,7 @@ led_config_t g_led_config = {
1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 4,
// Ctrl, GUI, Alt, Space, RAlt, FN, Left, Down, Right // Ctrl, GUI, Alt, Space, RAlt, FN, Left, Down, Right
1, 1, 1, 4, 1, 1, 1, 1, 1 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 ,2, 2, 2, 2, 2, 2
# endif # endif
} }
@ -147,10 +147,6 @@ bool rgb_matrix_indicators_kb(void) {
// Custom RGB Matrix driver that combines IS31FL3733 and WS2812 // 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) { static void rgb_matrix_driver_init(void) {
i2c_init(); i2c_init();
is31fl3733_init(0); is31fl3733_init(0);
@ -164,31 +160,25 @@ static void rgb_matrix_driver_init(void) {
static void rgb_matrix_driver_flush(void) { static void rgb_matrix_driver_flush(void) {
is31fl3733_update_pwm_buffers(0); is31fl3733_update_pwm_buffers(0);
# if WS2812_LED_TOTAL > 0 # if WS2812_LED_COUNT > 0
ws2812_setleds(rgb_matrix_ws2812_array, WS2812_LED_TOTAL); ws2812_flush();
# endif # endif
} }
static void rgb_matrix_driver_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) { static void rgb_matrix_driver_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
if (index < IS31FL3733_LED_COUNT) { if (index < IS31FL3733_LED_COUNT) {
is31fl3733_set_color(index, red, green, blue); is31fl3733_set_color(index, red, green, blue);
# if WS2812_LED_COUNT > 0
} else { } else {
# if WS2812_LED_TOTAL > 0 ws2812_set_color(index - IS31FL3733_LED_COUNT, red, green, blue);
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;
# endif # endif
} }
} }
static void rgb_matrix_driver_set_color_all(uint8_t red, uint8_t green, uint8_t blue) { static void rgb_matrix_driver_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
is31fl3733_set_color_all(red, green, blue); is31fl3733_set_color_all(red, green, blue);
# if WS2812_LED_TOTAL > 0 # if WS2812_LED_COUNT > 0
for (uint8_t i = 0; i < WS2812_LED_TOTAL; i++) { ws2812_set_color_all(red, green, blue);
rgb_matrix_ws2812_array[i].r = red;
rgb_matrix_ws2812_array[i].g = green;
rgb_matrix_ws2812_array[i].b = blue;
}
# endif # endif
} }

View file

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

View file

@ -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 }, { 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 // 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 } { 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} ,{ 28, 40}, { 62, 40}, { 96, 40}, {130, 40}, {164, 40}, {198, 40}
# endif # 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, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 4,
// Ctrl, GUI, Alt, Space, RAlt, FN, Left, Down, Right // Ctrl, GUI, Alt, Space, RAlt, FN, Left, Down, Right
1, 1, 1, 4, 1, 1, 1, 1, 1 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 ,2, 2, 2, 2, 2, 2
# endif # endif
} }; } };
@ -147,10 +147,6 @@ bool rgb_matrix_indicators_kb(void) {
// Custom RGB Matrix driver that combines IS31FL3733 and WS2812 // 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) { static void rgb_matrix_driver_init(void) {
i2c_init(); i2c_init();
is31fl3733_init(0); is31fl3733_init(0);
@ -164,31 +160,25 @@ static void rgb_matrix_driver_init(void) {
static void rgb_matrix_driver_flush(void) { static void rgb_matrix_driver_flush(void) {
is31fl3733_update_pwm_buffers(0); is31fl3733_update_pwm_buffers(0);
# if WS2812_LED_TOTAL > 0 # if WS2812_LED_COUNT > 0
ws2812_setleds(rgb_matrix_ws2812_array, WS2812_LED_TOTAL); ws2812_flush();
# endif # endif
} }
static void rgb_matrix_driver_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) { static void rgb_matrix_driver_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
if (index < IS31FL3733_LED_COUNT) { if (index < IS31FL3733_LED_COUNT) {
is31fl3733_set_color(index, red, green, blue); is31fl3733_set_color(index, red, green, blue);
# if WS2812_LED_COUNT > 0
} else { } else {
# if WS2812_LED_TOTAL > 0 ws2812_set_color(index - IS31FL3733_LED_COUNT, red, green, blue);
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;
# endif # endif
} }
} }
static void rgb_matrix_driver_set_color_all(uint8_t red, uint8_t green, uint8_t blue) { static void rgb_matrix_driver_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
is31fl3733_set_color_all(red, green, blue); is31fl3733_set_color_all(red, green, blue);
# if WS2812_LED_TOTAL > 0 # if WS2812_LED_COUNT > 0
for (uint8_t i = 0; i < WS2812_LED_TOTAL; i++) { ws2812_set_color_all(red, green, blue);
rgb_matrix_ws2812_array[i].r = red;
rgb_matrix_ws2812_array[i].g = green;
rgb_matrix_ws2812_array[i].b = blue;
}
# endif # endif
} }

View file

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

View file

@ -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 }, { 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 // 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 } { 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} ,{ 28, 40}, { 62, 40}, { 96, 40}, {130, 40}, {164, 40}, {198, 40}
# endif # endif
}, { }, {
@ -121,7 +121,7 @@ led_config_t g_led_config = {
1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1,
// Ctrl, GUI, Alt, Space, RAlt, FN, Left, Down, Right // Ctrl, GUI, Alt, Space, RAlt, FN, Left, Down, Right
1, 1, 1, 4, 1, 1, 1, 1 1, 1, 1, 4, 1, 1, 1, 1
# if WS2812_LED_TOTAL > 0 # if WS2812_LED_COUNT > 0
,2, 2, 2, 2, 2, 2 ,2, 2, 2, 2, 2, 2
# endif # endif
} }
@ -143,10 +143,6 @@ bool rgb_matrix_indicators_kb(void) {
// Custom RGB Matrix driver that combines IS31FL3733 and WS2812 // 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) { static void rgb_matrix_driver_init(void) {
i2c_init(); i2c_init();
is31fl3733_init(0); is31fl3733_init(0);
@ -160,31 +156,25 @@ static void rgb_matrix_driver_init(void) {
static void rgb_matrix_driver_flush(void) { static void rgb_matrix_driver_flush(void) {
is31fl3733_update_pwm_buffers(0); is31fl3733_update_pwm_buffers(0);
# if WS2812_LED_TOTAL > 0 # if WS2812_LED_COUNT > 0
ws2812_setleds(rgb_matrix_ws2812_array, WS2812_LED_TOTAL); ws2812_flush();
# endif # endif
} }
static void rgb_matrix_driver_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) { static void rgb_matrix_driver_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
if (index < IS31FL3733_LED_COUNT) { if (index < IS31FL3733_LED_COUNT) {
is31fl3733_set_color(index, red, green, blue); is31fl3733_set_color(index, red, green, blue);
# if WS2812_LED_COUNT > 0
} else { } else {
# if WS2812_LED_TOTAL > 0 ws2812_set_color(index - IS31FL3733_LED_COUNT, red, green, blue);
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;
# endif # endif
} }
} }
static void rgb_matrix_driver_set_color_all(uint8_t red, uint8_t green, uint8_t blue) { static void rgb_matrix_driver_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
is31fl3733_set_color_all(red, green, blue); is31fl3733_set_color_all(red, green, blue);
# if WS2812_LED_TOTAL > 0 # if WS2812_LED_COUNT > 0
for (uint8_t i = 0; i < WS2812_LED_TOTAL; i++) { ws2812_set_color_all(red, green, blue);
rgb_matrix_ws2812_array[i].r = red;
rgb_matrix_ws2812_array[i].g = green;
rgb_matrix_ws2812_array[i].b = blue;
}
# endif # endif
} }

View file

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

View file

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

View file

@ -27,13 +27,6 @@ uint8_t read_pin(uint16_t pin)
return (data & (1<<GET_PIN(pin))) ? 1 : 0; 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) { void housekeeping_task_kb(void) {
#ifdef RGBLIGHT_ENABLE #ifdef RGBLIGHT_ENABLE
rgb_ring_task(); rgb_ring_task();

View file

@ -361,27 +361,22 @@ static void custom_effects(void)
effect_funcs[rgb_ring.effect](); 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) { if (rgb_ring.state != RING_STATE_QMK) {
return; return;
} }
for (uint8_t i = 0; i < num_leds; i++) { is31fl3731_flush();
is31fl3731_set_color(i, start_led[i].r, start_led[i].g, start_led[i].b);
}
} }
const rgblight_driver_t rgblight_driver = { 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) void rgb_ring_task(void)
{ {
switch (rgb_ring.state) { switch (rgb_ring.state) {
@ -397,8 +392,6 @@ void rgb_ring_task(void)
default: default:
break; break;
}; };
is31fl3731_flush();
} }
bool process_record_kb(uint16_t keycode, keyrecord_t *record) bool process_record_kb(uint16_t keycode, keyrecord_t *record)

View file

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

View file

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

View file

@ -9,57 +9,6 @@ void bootloader_jump(void) {
NVIC_SystemReset(); 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 #ifdef RGB_MATRIX_ENABLE
const is31fl3731_led_t PROGMEM g_is31fl3731_leds[IS31FL3731_LED_COUNT] = { const is31fl3731_led_t PROGMEM g_is31fl3731_leds[IS31FL3731_LED_COUNT] = {
/* Refer to IS31 manual for these locations /* 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) { bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
if (record->event.pressed) { if (record->event.pressed) {
switch(keycode) { 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 #ifdef RGB_MATRIX_ENABLE
case KC_F13: // toggle rgb matrix case KC_F13: // toggle rgb matrix
rgb_matrix_toggle(); rgb_matrix_toggle();
@ -162,7 +106,6 @@ bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
case KC_F14: case KC_F14:
rgb_matrix_step(); rgb_matrix_step();
return false; return false;
#endif
#endif #endif
default: default:
break; break;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,35 +1,20 @@
// Copyright 2024 Dasky (@daskygit) // Copyright 2024 Dasky (@daskygit)
// SPDX-License-Identifier: GPL-2.0-or-later // 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 = { static PWMConfig pwmCFG = {
.frequency = 0xFFFF, .frequency = 0xFFFF,
.period = 256, .period = 256,
}; };
void prime_setleds(rgb_led_t *start_led, uint16_t num_leds) { rgb_led_t prime_leds[RGBLIGHT_LED_COUNT];
if (start_led[0].r == 0) {
pwmDisableChannel(&RGB_PWM_DRIVER, RGB_RED_PWM_CHANNEL - 1);
} else {
uint32_t duty = ((uint32_t)0xFFFF * start_led[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) {
pwmDisableChannel(&RGB_PWM_DRIVER, RGB_GREEN_PWM_CHANNEL - 1);
} else {
uint32_t duty = ((uint32_t)0xFFFF * start_led[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) {
pwmDisableChannel(&RGB_PWM_DRIVER, RGB_BLUE_PWM_CHANNEL - 1);
} else {
uint32_t duty = ((uint32_t)0xFFFF * start_led[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) { void init_custom(void) {
palSetPadMode(PAL_PORT(RGB_RED_PIN), PAL_PAD(RGB_RED_PIN), PAL_MODE_ALTERNATE_PUSHPULL); 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_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); palSetPadMode(PAL_PORT(RGB_BLUE_PIN), PAL_PAD(RGB_BLUE_PIN), PAL_MODE_ALTERNATE_PUSHPULL);
@ -39,7 +24,42 @@ void prime_initleds(void) {
pwmStart(&RGB_PWM_DRIVER, &pwmCFG); 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 * prime_leds[0].r) / 0xFF;
pwmEnableChannel(&RGB_PWM_DRIVER, RGB_RED_PWM_CHANNEL - 1, PWM_FRACTION_TO_WIDTH(&RGB_PWM_DRIVER, 0xFFFF, duty));
}
if (prime_leds[0].g == 0) {
pwmDisableChannel(&RGB_PWM_DRIVER, RGB_GREEN_PWM_CHANNEL - 1);
} else {
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 (prime_leds[0].b == 0) {
pwmDisableChannel(&RGB_PWM_DRIVER, RGB_BLUE_PWM_CHANNEL - 1);
} else {
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));
}
}
const rgblight_driver_t rgblight_driver = { const rgblight_driver_t rgblight_driver = {
.init = prime_initleds, .init = init_custom,
.setleds = prime_setleds, .set_color = set_color_custom,
.set_color_all = set_color_all_custom,
.flush = flush_custom,
}; };

View file

@ -60,7 +60,6 @@
#if defined(RGB_BACKLIGHT_DAWN60) #if defined(RGB_BACKLIGHT_DAWN60)
#include "ws2812.h" #include "ws2812.h"
rgb_led_t g_ws2812_leds[WS2812_LED_TOTAL];
#endif #endif
#include "progmem.h" #include "progmem.h"
@ -1011,6 +1010,9 @@ void backlight_update_pwm_buffers(void)
driver = 0; driver = 0;
} }
#else #else
#if defined(RGB_BACKLIGHT_DAWN60)
ws2812_flush();
#endif
is31fl3731_update_pwm_buffers( 0 ); is31fl3731_update_pwm_buffers( 0 );
is31fl3731_update_pwm_buffers( 1 ); is31fl3731_update_pwm_buffers( 1 );
is31fl3731_update_led_control_registers( 0 ); 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 ) { if( index < IS31FL3731_LED_COUNT ) {
is31fl3731_set_color( index, red, green, blue ); is31fl3731_set_color( index, red, green, blue );
} else { } else {
g_ws2812_leds[index - IS31FL3731_LED_COUNT].r = red; ws2812_set_color( index - IS31FL3731_LED_COUNT, red, green, blue );
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);
} }
#else #else
is31fl3731_set_color( index, red, green, blue ); 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) #elif defined(RGB_BACKLIGHT_DAWN60)
is31fl3731_set_color_all( red, green, blue ); is31fl3731_set_color_all( red, green, blue );
for (uint8_t i = 0; i < WS2812_LED_TOTAL; i++) { ws2812_set_color_all( red, green, blue );
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);
#else #else
is31fl3731_set_color_all( red, green, blue ); is31fl3731_set_color_all( red, green, blue );
#endif #endif
@ -1325,7 +1319,7 @@ void backlight_effect_alphas_mods(void)
} }
} }
#if defined(RGB_BACKLIGHT_DAWN60) #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) || 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)) { (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); backlight_set_color(i + IS31FL3731_LED_COUNT, rgb1.r, rgb1.g, rgb1.b);

View file

@ -26,13 +26,17 @@
#define WS2812_DI_PIN RGBLIGHT_DI_PIN #define WS2812_DI_PIN RGBLIGHT_DI_PIN
#define ws2812_init ws2812_rgb_init #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" #include "ws2812_bitbang.c"
const rgblight_driver_t rgblight_driver = { const rgblight_driver_t rgblight_driver = {
.init = ws2812_init, .init = ws2812_init,
.setleds = ws2812_setleds, .set_color = ws2812_set_color,
.set_color_all = ws2812_set_color_all,
.flush = ws2812_flush,
}; };
#endif #endif

View file

@ -42,7 +42,7 @@
#define RGB_BACKLIGHT_DAWN60 #define RGB_BACKLIGHT_DAWN60
//RGB Underglow defines //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_START 0
#define RGB_UNDERGLOW_ALPHA_TOP_END 6 #define RGB_UNDERGLOW_ALPHA_TOP_END 6

View file

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

View file

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

View file

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

View file

@ -7,9 +7,9 @@ static inline void rgblite_init(void) {
ws2812_init(); ws2812_init();
} }
static inline void rgblite_setrgb(uint8_t _r, uint8_t _g, uint8_t _b) { 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_set_color_all(r, g, b);
ws2812_setleds(leds, RGBLIGHT_LED_COUNT); ws2812_flush();
} }
static void rgblite_increase_hue(void) { static void rgblite_increase_hue(void) {

View file

@ -28,28 +28,6 @@
#define pinmask(pin) (_BV((pin)&0xF)) #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 This routine writes an array of bytes with RGB values to the Dataout pin
using the fast 800kHz clockless WS2811/2812 protocol. 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; 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);
}

View file

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

View file

@ -266,19 +266,36 @@ static inline void sync_ws2812_transfer(void) {
busy_wait_until(LAST_TRANSFER); 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(); sync_ws2812_transfer();
for (int i = 0; i < leds; i++) { for (int i = 0; i < WS2812_LED_COUNT; i++) {
#if defined(WS2812_RGBW) #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 #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 #endif
} }
dmaChannelSetSourceX(dma_channel, (uint32_t)WS2812_BUFFER); dmaChannelSetSourceX(dma_channel, (uint32_t)WS2812_BUFFER);
dmaChannelSetCounterX(dma_channel, leds); dmaChannelSetCounterX(dma_channel, WS2812_LED_COUNT);
dmaChannelSetModeX(dma_channel, RP_DMA_MODE_WS2812); dmaChannelSetModeX(dma_channel, RP_DMA_MODE_WS2812);
dmaChannelEnableX(dma_channel); dmaChannelEnableX(dma_channel);
} }

View file

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

View file

@ -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 ws2812_led_t ws2812_leds[WS2812_LED_COUNT];
void ws2812_setleds(rgb_led_t* ledarray, uint16_t leds) {
for (uint16_t i = 0; i < leds; i++) { void ws2812_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
#ifdef WS2812_RGBW ws2812_leds[index].r = red;
ws2812_write_led_rgbw(i, ledarray[i].r, ledarray[i].g, ledarray[i].b, ledarray[i].w); 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 #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 #endif
} }
} }

View file

@ -106,7 +106,7 @@ static uint8_t get_protocol_eq(uint8_t data, int pos) {
return eq; 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]; uint8_t* tx_start = &txbuf[PREAMBLE_SIZE];
#if (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_GRB) #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 #endif
} }
ws2812_led_t ws2812_leds[WS2812_LED_COUNT];
void ws2812_init(void) { void ws2812_init(void) {
palSetLineMode(WS2812_DI_PIN, WS2812_MOSI_OUTPUT_MODE); palSetLineMode(WS2812_DI_PIN, WS2812_MOSI_OUTPUT_MODE);
@ -187,9 +189,24 @@ void ws2812_init(void) {
#endif #endif
} }
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) {
for (uint8_t i = 0; i < leds; i++) { ws2812_leds[index].r = red;
set_led_color_rgb(ledarray[i], i); 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. // Send async - each led takes ~0.03ms, 50 leds ~1.5ms, animations flushing faster than send will cause issues.

View file

@ -108,14 +108,3 @@ RGB hsv_to_rgb(HSV hsv) {
RGB hsv_to_rgb_nocie(HSV hsv) { RGB hsv_to_rgb_nocie(HSV hsv) {
return hsv_to_rgb_impl(hsv, false); 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

View file

@ -74,31 +74,10 @@
// clang-format on // 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 { 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 r;
uint8_t g; uint8_t g;
uint8_t b; 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; } rgb_led_t;
typedef rgb_led_t RGB; typedef rgb_led_t RGB;
@ -111,6 +90,3 @@ typedef struct PACKED HSV {
RGB hsv_to_rgb(HSV hsv); RGB hsv_to_rgb(HSV hsv);
RGB hsv_to_rgb_nocie(HSV hsv); RGB hsv_to_rgb_nocie(HSV hsv);
#ifdef WS2812_RGBW
void convert_rgb_to_rgbw(rgb_led_t *led);
#endif

View file

@ -139,11 +139,20 @@ void led_matrix_update_pwm_buffers(void) {
led_matrix_driver.flush(); 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) { void led_matrix_set_value(int index, uint8_t value) {
#ifdef USE_CIE1931_CURVE #ifdef USE_CIE1931_CURVE
value = pgm_read_byte(&CIE1931_CURVE[value]); value = pgm_read_byte(&CIE1931_CURVE[value]);
#endif #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) { void led_matrix_set_value_all(uint8_t value) {

View file

@ -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_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); 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(int index, uint8_t value);
void led_matrix_set_value_all(uint8_t value); void led_matrix_set_value_all(uint8_t value);

View file

@ -143,8 +143,17 @@ void rgb_matrix_update_pwm_buffers(void) {
rgb_matrix_driver.flush(); 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) { 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) { void rgb_matrix_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {

View file

@ -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_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); 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(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); void rgb_matrix_set_color_all(uint8_t red, uint8_t green, uint8_t blue);

View file

@ -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." # pragma message "You need to use a custom driver, or re-implement the WS2812 driver to use a different configuration."
# endif # 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 = { const rgb_matrix_driver_t rgb_matrix_driver = {
.init = init, .init = ws2812_init,
.flush = flush, .flush = ws2812_flush,
.set_color = setled, .set_color = ws2812_set_color,
.set_color_all = setled_all, .set_color_all = ws2812_set_color_all,
}; };
#endif #endif

View file

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

View file

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

View file

@ -7,24 +7,20 @@
# include "ws2812.h" # include "ws2812.h"
const rgblight_driver_t rgblight_driver = { const rgblight_driver_t rgblight_driver = {
.init = ws2812_init, .init = ws2812_init,
.setleds = ws2812_setleds, .set_color = ws2812_set_color,
.set_color_all = ws2812_set_color_all,
.flush = ws2812_flush,
}; };
#elif defined(RGBLIGHT_APA102) #elif defined(RGBLIGHT_APA102)
# include "apa102.h" # 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 = { const rgblight_driver_t rgblight_driver = {
.init = apa102_init, .init = apa102_init,
.setleds = apa102_setleds, .set_color = apa102_set_color,
.set_color_all = apa102_set_color_all,
.flush = apa102_flush,
}; };
#endif #endif

View file

@ -4,11 +4,12 @@
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
#include "color.h"
typedef struct { typedef struct {
void (*init)(void); 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; } rgblight_driver_t;
extern const rgblight_driver_t rgblight_driver; extern const rgblight_driver_t rgblight_driver;