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:]'))
SRC += ws2812_$(strip $(WS2812_DRIVER)).c
SRC += ws2812.c ws2812_$(strip $(WS2812_DRIVER)).c
ifeq ($(strip $(PLATFORM)), CHIBIOS)
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}
### `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
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
#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
void ws2812_init(void);
#define WS2812_BYTE_ORDER_RGB 0
#define WS2812_BYTE_ORDER_GRB 1
#define WS2812_BYTE_ORDER_BGR 2
/* 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);
#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);
void ws2812_rgb_to_rgbw(ws2812_led_t *led);

View file

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

View file

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

View file

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

View file

@ -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];
#endif
}
i2c_transmit(0x84, data, sizeof(data), ERGODOX_EZ_I2C_TIMEOUT);
#define WS2812_I2C_ADDRESS_LEFT 0x84
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 = {
.init = ws2812_init,
.setleds = setleds_custom,
.init = ws2812_init,
.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 WS2812_LED_COUNT RGBSPS_NUM
#endif
/* PS/2 mouse */

View file

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

View file

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

View file

@ -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();
}
}

View file

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

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_CA7, CB9_CA7, CB8_CA7}, // Right
};
int rgb_matrix_led_index(int index) {
return index;
}
#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_CA7, CB9_CA7, CB8_CA7}, // Right
};
int rgb_matrix_led_index(int index) {
return index;
}
#endif

View file

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

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 },
// 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
}

View file

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

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 },
// 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
}

View file

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

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 },
// 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
}

View file

@ -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);
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_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);
}
}
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

View file

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

View file

@ -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();

View file

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

View file

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

View file

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

View file

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

View file

@ -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)
{
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;
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);
}
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);
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)

View file

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

View file

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

View file

@ -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)
{
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;
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);
}
ws2812_setleds(start_led+IS31FL3731_LED_COUNT, 1);
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)

View file

@ -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);
}

View file

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

View file

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

View file

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

View file

@ -1,35 +1,20 @@
// 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) {
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));
}
}
rgb_led_t prime_leds[RGBLIGHT_LED_COUNT];
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_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);
@ -39,7 +24,42 @@ void prime_initleds(void) {
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 = {
.init = prime_initleds,
.setleds = prime_setleds,
.init = init_custom,
.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)
#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);

View file

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

View file

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

View file

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

View file

@ -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 );
}

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();
}
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) {

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);
}

View file

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

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

View file

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

View file

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

View file

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

View file

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

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(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);

View file

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

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(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);

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."
# 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

View file

@ -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) {
HSV hsv = {hue, sat, val};
RGB rgb = rgblight_hsv_to_rgb(hsv);
setrgb(rgb.r, rgb.g, rgb.b, 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(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_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, 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) {
@ -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();

View file

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

View file

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

View file

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