aboutsummaryrefslogtreecommitdiff
path: root/quantum/rgblight
diff options
context:
space:
mode:
authorRyan <fauxpark@gmail.com>2021-06-28 15:15:24 +1000
committerGitHub <noreply@github.com>2021-06-28 15:15:24 +1000
commitcb23fe9fc1fa6e2219380228ae589f3d733ea4e6 (patch)
tree8383c0cbf24389a4bfad04880f13d1a7e0098366 /quantum/rgblight
parent5a5015594f44f8b7f7d3c5bc43479c3e670656d6 (diff)
downloadqmk_firmware-cb23fe9fc1fa6e2219380228ae589f3d733ea4e6.tar.gz
qmk_firmware-cb23fe9fc1fa6e2219380228ae589f3d733ea4e6.zip
Move RGBLight code into its own folder (#13312)
Diffstat (limited to 'quantum/rgblight')
-rw-r--r--quantum/rgblight/rgblight.c1391
-rw-r--r--quantum/rgblight/rgblight.h442
-rw-r--r--quantum/rgblight/rgblight_breathe_table.h117
-rw-r--r--quantum/rgblight/rgblight_modes.h75
-rw-r--r--quantum/rgblight/rgblight_post_config.h5
5 files changed, 2030 insertions, 0 deletions
diff --git a/quantum/rgblight/rgblight.c b/quantum/rgblight/rgblight.c
new file mode 100644
index 000000000..54face173
--- /dev/null
+++ b/quantum/rgblight/rgblight.c
@@ -0,0 +1,1391 @@
1/* Copyright 2016-2017 Yang Liu
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16#include <math.h>
17#include <string.h>
18#include <stdlib.h>
19#ifdef __AVR__
20# include <avr/eeprom.h>
21# include <avr/interrupt.h>
22#endif
23#ifdef EEPROM_ENABLE
24# include "eeprom.h"
25#endif
26#ifdef STM32_EEPROM_ENABLE
27# include <hal.h>
28# include "eeprom_stm32.h"
29#endif
30#include "wait.h"
31#include "progmem.h"
32#include "sync_timer.h"
33#include "rgblight.h"
34#include "color.h"
35#include "debug.h"
36#include "led_tables.h"
37#include <lib/lib8tion/lib8tion.h>
38#ifdef VELOCIKEY_ENABLE
39# include "velocikey.h"
40#endif
41
42#ifndef MIN
43# define MIN(a, b) (((a) < (b)) ? (a) : (b))
44#endif
45#ifndef MAX
46# define MAX(a, b) (((a) > (b)) ? (a) : (b))
47#endif
48
49#ifdef RGBLIGHT_SPLIT
50/* for split keyboard */
51# define RGBLIGHT_SPLIT_SET_CHANGE_MODE rgblight_status.change_flags |= RGBLIGHT_STATUS_CHANGE_MODE
52# define RGBLIGHT_SPLIT_SET_CHANGE_HSVS rgblight_status.change_flags |= RGBLIGHT_STATUS_CHANGE_HSVS
53# define RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS rgblight_status.change_flags |= (RGBLIGHT_STATUS_CHANGE_MODE | RGBLIGHT_STATUS_CHANGE_HSVS)
54# define RGBLIGHT_SPLIT_SET_CHANGE_LAYERS rgblight_status.change_flags |= RGBLIGHT_STATUS_CHANGE_LAYERS
55# define RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE rgblight_status.change_flags |= RGBLIGHT_STATUS_CHANGE_TIMER
56# define RGBLIGHT_SPLIT_ANIMATION_TICK rgblight_status.change_flags |= RGBLIGHT_STATUS_ANIMATION_TICK
57#else
58# define RGBLIGHT_SPLIT_SET_CHANGE_MODE
59# define RGBLIGHT_SPLIT_SET_CHANGE_HSVS
60# define RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS
61# define RGBLIGHT_SPLIT_SET_CHANGE_LAYERS
62# define RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE
63# define RGBLIGHT_SPLIT_ANIMATION_TICK
64#endif
65
66#define _RGBM_SINGLE_STATIC(sym) RGBLIGHT_MODE_##sym,
67#define _RGBM_SINGLE_DYNAMIC(sym)
68#define _RGBM_MULTI_STATIC(sym) RGBLIGHT_MODE_##sym,
69#define _RGBM_MULTI_DYNAMIC(sym)
70#define _RGBM_TMP_STATIC(sym, msym) RGBLIGHT_MODE_##sym,
71#define _RGBM_TMP_DYNAMIC(sym, msym)
72static uint8_t static_effect_table[] = {
73#include "rgblight_modes.h"
74};
75
76#define _RGBM_SINGLE_STATIC(sym) RGBLIGHT_MODE_##sym,
77#define _RGBM_SINGLE_DYNAMIC(sym) RGBLIGHT_MODE_##sym,
78#define _RGBM_MULTI_STATIC(sym) RGBLIGHT_MODE_##sym,
79#define _RGBM_MULTI_DYNAMIC(sym) RGBLIGHT_MODE_##sym,
80#define _RGBM_TMP_STATIC(sym, msym) RGBLIGHT_MODE_##msym,
81#define _RGBM_TMP_DYNAMIC(sym, msym) RGBLIGHT_MODE_##msym,
82static uint8_t mode_base_table[] = {
83 0, // RGBLIGHT_MODE_zero
84#include "rgblight_modes.h"
85};
86
87#if !defined(RGBLIGHT_DEFAULT_MODE)
88# define RGBLIGHT_DEFAULT_MODE RGBLIGHT_MODE_STATIC_LIGHT
89#endif
90
91#if !defined(RGBLIGHT_DEFAULT_HUE)
92# define RGBLIGHT_DEFAULT_HUE 0
93#endif
94
95#if !defined(RGBLIGHT_DEFAULT_SAT)
96# define RGBLIGHT_DEFAULT_SAT UINT8_MAX
97#endif
98
99#if !defined(RGBLIGHT_DEFAULT_VAL)
100# define RGBLIGHT_DEFAULT_VAL RGBLIGHT_LIMIT_VAL
101#endif
102
103#if !defined(RGBLIGHT_DEFAULT_SPD)
104# define RGBLIGHT_DEFAULT_SPD 0
105#endif
106
107static inline int is_static_effect(uint8_t mode) { return memchr(static_effect_table, mode, sizeof(static_effect_table)) != NULL; }
108
109#ifdef RGBLIGHT_LED_MAP
110const uint8_t led_map[] PROGMEM = RGBLIGHT_LED_MAP;
111#endif
112
113#ifdef RGBLIGHT_EFFECT_STATIC_GRADIENT
114__attribute__((weak)) const uint8_t RGBLED_GRADIENT_RANGES[] PROGMEM = {255, 170, 127, 85, 64};
115#endif
116
117rgblight_config_t rgblight_config;
118rgblight_status_t rgblight_status = {.timer_enabled = false};
119bool is_rgblight_initialized = false;
120
121#ifdef RGBLIGHT_SLEEP
122static bool is_suspended;
123static bool pre_suspend_enabled;
124#endif
125
126#ifdef RGBLIGHT_USE_TIMER
127animation_status_t animation_status = {};
128#endif
129
130#ifndef LED_ARRAY
131LED_TYPE led[RGBLED_NUM];
132# define LED_ARRAY led
133#endif
134
135#ifdef RGBLIGHT_LAYERS
136rgblight_segment_t const *const *rgblight_layers = NULL;
137#endif
138
139rgblight_ranges_t rgblight_ranges = {0, RGBLED_NUM, 0, RGBLED_NUM, RGBLED_NUM};
140
141void rgblight_set_clipping_range(uint8_t start_pos, uint8_t num_leds) {
142 rgblight_ranges.clipping_start_pos = start_pos;
143 rgblight_ranges.clipping_num_leds = num_leds;
144}
145
146void rgblight_set_effect_range(uint8_t start_pos, uint8_t num_leds) {
147 if (start_pos >= RGBLED_NUM) return;
148 if (start_pos + num_leds > RGBLED_NUM) return;
149 rgblight_ranges.effect_start_pos = start_pos;
150 rgblight_ranges.effect_end_pos = start_pos + num_leds;
151 rgblight_ranges.effect_num_leds = num_leds;
152}
153
154__attribute__((weak)) RGB rgblight_hsv_to_rgb(HSV hsv) { return hsv_to_rgb(hsv); }
155
156void sethsv_raw(uint8_t hue, uint8_t sat, uint8_t val, LED_TYPE *led1) {
157 HSV hsv = {hue, sat, val};
158 RGB rgb = rgblight_hsv_to_rgb(hsv);
159 setrgb(rgb.r, rgb.g, rgb.b, led1);
160}
161
162void sethsv(uint8_t hue, uint8_t sat, uint8_t val, LED_TYPE *led1) { sethsv_raw(hue, sat, val > RGBLIGHT_LIMIT_VAL ? RGBLIGHT_LIMIT_VAL : val, led1); }
163
164void setrgb(uint8_t r, uint8_t g, uint8_t b, LED_TYPE *led1) {
165 led1->r = r;
166 led1->g = g;
167 led1->b = b;
168#ifdef RGBW
169 led1->w = 0;
170#endif
171}
172
173void rgblight_check_config(void) {
174 /* Add some out of bound checks for RGB light config */
175
176 if (rgblight_config.mode < RGBLIGHT_MODE_STATIC_LIGHT) {
177 rgblight_config.mode = RGBLIGHT_MODE_STATIC_LIGHT;
178 } else if (rgblight_config.mode > RGBLIGHT_MODES) {
179 rgblight_config.mode = RGBLIGHT_MODES;
180 }
181
182 if (rgblight_config.val > RGBLIGHT_LIMIT_VAL) {
183 rgblight_config.val = RGBLIGHT_LIMIT_VAL;
184 }
185}
186
187uint32_t eeconfig_read_rgblight(void) {
188#ifdef EEPROM_ENABLE
189 return eeprom_read_dword(EECONFIG_RGBLIGHT);
190#else
191 return 0;
192#endif
193}
194
195void eeconfig_update_rgblight(uint32_t val) {
196#ifdef EEPROM_ENABLE
197 rgblight_check_config();
198 eeprom_update_dword(EECONFIG_RGBLIGHT, val);
199#endif
200}
201
202void eeconfig_update_rgblight_current(void) { eeconfig_update_rgblight(rgblight_config.raw); }
203
204void eeconfig_update_rgblight_default(void) {
205 rgblight_config.enable = 1;
206 rgblight_config.mode = RGBLIGHT_DEFAULT_MODE;
207 rgblight_config.hue = RGBLIGHT_DEFAULT_HUE;
208 rgblight_config.sat = RGBLIGHT_DEFAULT_SAT;
209 rgblight_config.val = RGBLIGHT_DEFAULT_VAL;
210 rgblight_config.speed = RGBLIGHT_DEFAULT_SPD;
211 RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS;
212 eeconfig_update_rgblight(rgblight_config.raw);
213}
214
215void eeconfig_debug_rgblight(void) {
216 dprintf("rgblight_config EEPROM:\n");
217 dprintf("rgblight_config.enable = %d\n", rgblight_config.enable);
218 dprintf("rghlight_config.mode = %d\n", rgblight_config.mode);
219 dprintf("rgblight_config.hue = %d\n", rgblight_config.hue);
220 dprintf("rgblight_config.sat = %d\n", rgblight_config.sat);
221 dprintf("rgblight_config.val = %d\n", rgblight_config.val);
222 dprintf("rgblight_config.speed = %d\n", rgblight_config.speed);
223}
224
225void rgblight_init(void) {
226 /* if already initialized, don't do it again.
227 If you must do it again, extern this and set to false, first.
228 This is a dirty, dirty hack until proper hooks can be added for keyboard startup. */
229 if (is_rgblight_initialized) {
230 return;
231 }
232
233 dprintf("rgblight_init called.\n");
234 dprintf("rgblight_init start!\n");
235 if (!eeconfig_is_enabled()) {
236 dprintf("rgblight_init eeconfig is not enabled.\n");
237 eeconfig_init();
238 eeconfig_update_rgblight_default();
239 }
240 rgblight_config.raw = eeconfig_read_rgblight();
241 RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS;
242 if (!rgblight_config.mode) {
243 dprintf("rgblight_init rgblight_config.mode = 0. Write default values to EEPROM.\n");
244 eeconfig_update_rgblight_default();
245 rgblight_config.raw = eeconfig_read_rgblight();
246 }
247 rgblight_check_config();
248
249 eeconfig_debug_rgblight(); // display current eeprom values
250
251 rgblight_timer_init(); // setup the timer
252
253 if (rgblight_config.enable) {
254 rgblight_mode_noeeprom(rgblight_config.mode);
255 }
256
257 is_rgblight_initialized = true;
258}
259
260void rgblight_reload_from_eeprom(void) {
261 /* Reset back to what we have in eeprom */
262 rgblight_config.raw = eeconfig_read_rgblight();
263 RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS;
264 rgblight_check_config();
265 eeconfig_debug_rgblight(); // display current eeprom values
266 if (rgblight_config.enable) {
267 rgblight_mode_noeeprom(rgblight_config.mode);
268 }
269}
270
271uint32_t rgblight_read_dword(void) { return rgblight_config.raw; }
272
273void rgblight_update_dword(uint32_t dword) {
274 RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS;
275 rgblight_config.raw = dword;
276 if (rgblight_config.enable)
277 rgblight_mode_noeeprom(rgblight_config.mode);
278 else {
279 rgblight_timer_disable();
280 rgblight_set();
281 }
282}
283
284void rgblight_increase(void) {
285 uint8_t mode = 0;
286 if (rgblight_config.mode < RGBLIGHT_MODES) {
287 mode = rgblight_config.mode + 1;
288 }
289 rgblight_mode(mode);
290}
291void rgblight_decrease(void) {
292 uint8_t mode = 0;
293 // Mode will never be < 1. If it ever is, eeprom needs to be initialized.
294 if (rgblight_config.mode > RGBLIGHT_MODE_STATIC_LIGHT) {
295 mode = rgblight_config.mode - 1;
296 }
297 rgblight_mode(mode);
298}
299void rgblight_step_helper(bool write_to_eeprom) {
300 uint8_t mode = 0;
301 mode = rgblight_config.mode + 1;
302 if (mode > RGBLIGHT_MODES) {
303 mode = 1;
304 }
305 rgblight_mode_eeprom_helper(mode, write_to_eeprom);
306}
307void rgblight_step_noeeprom(void) { rgblight_step_helper(false); }
308void rgblight_step(void) { rgblight_step_helper(true); }
309void rgblight_step_reverse_helper(bool write_to_eeprom) {
310 uint8_t mode = 0;
311 mode = rgblight_config.mode - 1;
312 if (mode < 1) {
313 mode = RGBLIGHT_MODES;
314 }
315 rgblight_mode_eeprom_helper(mode, write_to_eeprom);
316}
317void rgblight_step_reverse_noeeprom(void) { rgblight_step_reverse_helper(false); }
318void rgblight_step_reverse(void) { rgblight_step_reverse_helper(true); }
319
320uint8_t rgblight_get_mode(void) {
321 if (!rgblight_config.enable) {
322 return false;
323 }
324
325 return rgblight_config.mode;
326}
327
328void rgblight_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) {
329 if (!rgblight_config.enable) {
330 return;
331 }
332 if (mode < RGBLIGHT_MODE_STATIC_LIGHT) {
333 rgblight_config.mode = RGBLIGHT_MODE_STATIC_LIGHT;
334 } else if (mode > RGBLIGHT_MODES) {
335 rgblight_config.mode = RGBLIGHT_MODES;
336 } else {
337 rgblight_config.mode = mode;
338 }
339 RGBLIGHT_SPLIT_SET_CHANGE_MODE;
340 if (write_to_eeprom) {
341 eeconfig_update_rgblight(rgblight_config.raw);
342 dprintf("rgblight mode [EEPROM]: %u\n", rgblight_config.mode);
343 } else {
344 dprintf("rgblight mode [NOEEPROM]: %u\n", rgblight_config.mode);
345 }
346 if (is_static_effect(rgblight_config.mode)) {
347 rgblight_timer_disable();
348 } else {
349 rgblight_timer_enable();
350 }
351#ifdef RGBLIGHT_USE_TIMER
352 animation_status.restart = true;
353#endif
354 rgblight_sethsv_noeeprom(rgblight_config.hue, rgblight_config.sat, rgblight_config.val);
355}
356
357void rgblight_mode(uint8_t mode) { rgblight_mode_eeprom_helper(mode, true); }
358
359void rgblight_mode_noeeprom(uint8_t mode) { rgblight_mode_eeprom_helper(mode, false); }
360
361void rgblight_toggle(void) {
362 dprintf("rgblight toggle [EEPROM]: rgblight_config.enable = %u\n", !rgblight_config.enable);
363 if (rgblight_config.enable) {
364 rgblight_disable();
365 } else {
366 rgblight_enable();
367 }
368}
369
370void rgblight_toggle_noeeprom(void) {
371 dprintf("rgblight toggle [NOEEPROM]: rgblight_config.enable = %u\n", !rgblight_config.enable);
372 if (rgblight_config.enable) {
373 rgblight_disable_noeeprom();
374 } else {
375 rgblight_enable_noeeprom();
376 }
377}
378
379void rgblight_enable(void) {
380 rgblight_config.enable = 1;
381 // No need to update EEPROM here. rgblight_mode() will do that, actually
382 // eeconfig_update_rgblight(rgblight_config.raw);
383 dprintf("rgblight enable [EEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable);
384 rgblight_mode(rgblight_config.mode);
385}
386
387void rgblight_enable_noeeprom(void) {
388 rgblight_config.enable = 1;
389 dprintf("rgblight enable [NOEEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable);
390 rgblight_mode_noeeprom(rgblight_config.mode);
391}
392
393void rgblight_disable(void) {
394 rgblight_config.enable = 0;
395 eeconfig_update_rgblight(rgblight_config.raw);
396 dprintf("rgblight disable [EEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable);
397 rgblight_timer_disable();
398 RGBLIGHT_SPLIT_SET_CHANGE_MODE;
399 wait_ms(50);
400 rgblight_set();
401}
402
403void rgblight_disable_noeeprom(void) {
404 rgblight_config.enable = 0;
405 dprintf("rgblight disable [NOEEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable);
406 rgblight_timer_disable();
407 RGBLIGHT_SPLIT_SET_CHANGE_MODE;
408 wait_ms(50);
409 rgblight_set();
410}
411
412bool rgblight_is_enabled(void) { return rgblight_config.enable; }
413
414void rgblight_increase_hue_helper(bool write_to_eeprom) {
415 uint8_t hue = rgblight_config.hue + RGBLIGHT_HUE_STEP;
416 rgblight_sethsv_eeprom_helper(hue, rgblight_config.sat, rgblight_config.val, write_to_eeprom);
417}
418void rgblight_increase_hue_noeeprom(void) { rgblight_increase_hue_helper(false); }
419void rgblight_increase_hue(void) { rgblight_increase_hue_helper(true); }
420void rgblight_decrease_hue_helper(bool write_to_eeprom) {
421 uint8_t hue = rgblight_config.hue - RGBLIGHT_HUE_STEP;
422 rgblight_sethsv_eeprom_helper(hue, rgblight_config.sat, rgblight_config.val, write_to_eeprom);
423}
424void rgblight_decrease_hue_noeeprom(void) { rgblight_decrease_hue_helper(false); }
425void rgblight_decrease_hue(void) { rgblight_decrease_hue_helper(true); }
426void rgblight_increase_sat_helper(bool write_to_eeprom) {
427 uint8_t sat = qadd8(rgblight_config.sat, RGBLIGHT_SAT_STEP);
428 rgblight_sethsv_eeprom_helper(rgblight_config.hue, sat, rgblight_config.val, write_to_eeprom);
429}
430void rgblight_increase_sat_noeeprom(void) { rgblight_increase_sat_helper(false); }
431void rgblight_increase_sat(void) { rgblight_increase_sat_helper(true); }
432void rgblight_decrease_sat_helper(bool write_to_eeprom) {
433 uint8_t sat = qsub8(rgblight_config.sat, RGBLIGHT_SAT_STEP);
434 rgblight_sethsv_eeprom_helper(rgblight_config.hue, sat, rgblight_config.val, write_to_eeprom);
435}
436void rgblight_decrease_sat_noeeprom(void) { rgblight_decrease_sat_helper(false); }
437void rgblight_decrease_sat(void) { rgblight_decrease_sat_helper(true); }
438void rgblight_increase_val_helper(bool write_to_eeprom) {
439 uint8_t val = qadd8(rgblight_config.val, RGBLIGHT_VAL_STEP);
440 rgblight_sethsv_eeprom_helper(rgblight_config.hue, rgblight_config.sat, val, write_to_eeprom);
441}
442void rgblight_increase_val_noeeprom(void) { rgblight_increase_val_helper(false); }
443void rgblight_increase_val(void) { rgblight_increase_val_helper(true); }
444void rgblight_decrease_val_helper(bool write_to_eeprom) {
445 uint8_t val = qsub8(rgblight_config.val, RGBLIGHT_VAL_STEP);
446 rgblight_sethsv_eeprom_helper(rgblight_config.hue, rgblight_config.sat, val, write_to_eeprom);
447}
448void rgblight_decrease_val_noeeprom(void) { rgblight_decrease_val_helper(false); }
449void rgblight_decrease_val(void) { rgblight_decrease_val_helper(true); }
450
451void rgblight_increase_speed_helper(bool write_to_eeprom) {
452 if (rgblight_config.speed < 3) rgblight_config.speed++;
453 // RGBLIGHT_SPLIT_SET_CHANGE_HSVS; // NEED?
454 if (write_to_eeprom) {
455 eeconfig_update_rgblight(rgblight_config.raw); // EECONFIG needs to be increased to support this
456 }
457}
458void rgblight_increase_speed(void) { rgblight_increase_speed_helper(true); }
459void rgblight_increase_speed_noeeprom(void) { rgblight_increase_speed_helper(false); }
460
461void rgblight_decrease_speed_helper(bool write_to_eeprom) {
462 if (rgblight_config.speed > 0) rgblight_config.speed--;
463 // RGBLIGHT_SPLIT_SET_CHANGE_HSVS; // NEED??
464 if (write_to_eeprom) {
465 eeconfig_update_rgblight(rgblight_config.raw); // EECONFIG needs to be increased to support this
466 }
467}
468void rgblight_decrease_speed(void) { rgblight_decrease_speed_helper(true); }
469void rgblight_decrease_speed_noeeprom(void) { rgblight_decrease_speed_helper(false); }
470
471void rgblight_sethsv_noeeprom_old(uint8_t hue, uint8_t sat, uint8_t val) {
472 if (rgblight_config.enable) {
473 LED_TYPE tmp_led;
474 sethsv(hue, sat, val, &tmp_led);
475 rgblight_setrgb(tmp_led.r, tmp_led.g, tmp_led.b);
476 }
477}
478
479void rgblight_sethsv_eeprom_helper(uint8_t hue, uint8_t sat, uint8_t val, bool write_to_eeprom) {
480 if (rgblight_config.enable) {
481 rgblight_status.base_mode = mode_base_table[rgblight_config.mode];
482 if (rgblight_config.mode == RGBLIGHT_MODE_STATIC_LIGHT) {
483 // same static color
484 LED_TYPE tmp_led;
485 sethsv(hue, sat, val, &tmp_led);
486 rgblight_setrgb(tmp_led.r, tmp_led.g, tmp_led.b);
487 } else {
488 // all LEDs in same color
489 if (1 == 0) { // dummy
490 }
491#ifdef RGBLIGHT_EFFECT_BREATHING
492 else if (rgblight_status.base_mode == RGBLIGHT_MODE_BREATHING) {
493 // breathing mode, ignore the change of val, use in memory value instead
494 val = rgblight_config.val;
495 }
496#endif
497#ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD
498 else if (rgblight_status.base_mode == RGBLIGHT_MODE_RAINBOW_MOOD) {
499 // rainbow mood, ignore the change of hue
500 hue = rgblight_config.hue;
501 }
502#endif
503#ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL
504 else if (rgblight_status.base_mode == RGBLIGHT_MODE_RAINBOW_SWIRL) {
505 // rainbow swirl, ignore the change of hue
506 hue = rgblight_config.hue;
507 }
508#endif
509#ifdef RGBLIGHT_EFFECT_STATIC_GRADIENT
510 else if (rgblight_status.base_mode == RGBLIGHT_MODE_STATIC_GRADIENT) {
511 // static gradient
512 uint8_t delta = rgblight_config.mode - rgblight_status.base_mode;
513 bool direction = (delta % 2) == 0;
514# ifdef __AVR__
515 // probably due to how pgm_read_word is defined for ARM, but the ARM compiler really hates this line
516 uint8_t range = pgm_read_word(&RGBLED_GRADIENT_RANGES[delta / 2]);
517# else
518 uint8_t range = RGBLED_GRADIENT_RANGES[delta / 2];
519# endif
520 for (uint8_t i = 0; i < rgblight_ranges.effect_num_leds; i++) {
521 uint8_t _hue = ((uint16_t)i * (uint16_t)range) / rgblight_ranges.effect_num_leds;
522 if (direction) {
523 _hue = hue + _hue;
524 } else {
525 _hue = hue - _hue;
526 }
527 dprintf("rgblight rainbow set hsv: %d,%d,%d,%u\n", i, _hue, direction, range);
528 sethsv(_hue, sat, val, (LED_TYPE *)&led[i + rgblight_ranges.effect_start_pos]);
529 }
530 rgblight_set();
531 }
532#endif
533 }
534#ifdef RGBLIGHT_SPLIT
535 if (rgblight_config.hue != hue || rgblight_config.sat != sat || rgblight_config.val != val) {
536 RGBLIGHT_SPLIT_SET_CHANGE_HSVS;
537 }
538#endif
539 rgblight_config.hue = hue;
540 rgblight_config.sat = sat;
541 rgblight_config.val = val;
542 if (write_to_eeprom) {
543 eeconfig_update_rgblight(rgblight_config.raw);
544 dprintf("rgblight set hsv [EEPROM]: %u,%u,%u\n", rgblight_config.hue, rgblight_config.sat, rgblight_config.val);
545 } else {
546 dprintf("rgblight set hsv [NOEEPROM]: %u,%u,%u\n", rgblight_config.hue, rgblight_config.sat, rgblight_config.val);
547 }
548 }
549}
550
551void rgblight_sethsv(uint8_t hue, uint8_t sat, uint8_t val) { rgblight_sethsv_eeprom_helper(hue, sat, val, true); }
552
553void rgblight_sethsv_noeeprom(uint8_t hue, uint8_t sat, uint8_t val) { rgblight_sethsv_eeprom_helper(hue, sat, val, false); }
554
555uint8_t rgblight_get_speed(void) { return rgblight_config.speed; }
556
557void rgblight_set_speed_eeprom_helper(uint8_t speed, bool write_to_eeprom) {
558 rgblight_config.speed = speed;
559 if (write_to_eeprom) {
560 eeconfig_update_rgblight(rgblight_config.raw); // EECONFIG needs to be increased to support this
561 dprintf("rgblight set speed [EEPROM]: %u\n", rgblight_config.speed);
562 } else {
563 dprintf("rgblight set speed [NOEEPROM]: %u\n", rgblight_config.speed);
564 }
565}
566
567void rgblight_set_speed(uint8_t speed) { rgblight_set_speed_eeprom_helper(speed, true); }
568
569void rgblight_set_speed_noeeprom(uint8_t speed) { rgblight_set_speed_eeprom_helper(speed, false); }
570
571uint8_t rgblight_get_hue(void) { return rgblight_config.hue; }
572
573uint8_t rgblight_get_sat(void) { return rgblight_config.sat; }
574
575uint8_t rgblight_get_val(void) { return rgblight_config.val; }
576
577HSV rgblight_get_hsv(void) { return (HSV){rgblight_config.hue, rgblight_config.sat, rgblight_config.val}; }
578
579void rgblight_setrgb(uint8_t r, uint8_t g, uint8_t b) {
580 if (!rgblight_config.enable) {
581 return;
582 }
583
584 for (uint8_t i = rgblight_ranges.effect_start_pos; i < rgblight_ranges.effect_end_pos; i++) {
585 led[i].r = r;
586 led[i].g = g;
587 led[i].b = b;
588#ifdef RGBW
589 led[i].w = 0;
590#endif
591 }
592 rgblight_set();
593}
594
595void rgblight_setrgb_at(uint8_t r, uint8_t g, uint8_t b, uint8_t index) {
596 if (!rgblight_config.enable || index >= RGBLED_NUM) {
597 return;
598 }
599
600 led[index].r = r;
601 led[index].g = g;
602 led[index].b = b;
603#ifdef RGBW
604 led[index].w = 0;
605#endif
606 rgblight_set();
607}
608
609void rgblight_sethsv_at(uint8_t hue, uint8_t sat, uint8_t val, uint8_t index) {
610 if (!rgblight_config.enable) {
611 return;
612 }
613
614 LED_TYPE tmp_led;
615 sethsv(hue, sat, val, &tmp_led);
616 rgblight_setrgb_at(tmp_led.r, tmp_led.g, tmp_led.b, index);
617}
618
619#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)
620
621static uint8_t get_interval_time(const uint8_t *default_interval_address, uint8_t velocikey_min, uint8_t velocikey_max) {
622 return
623# ifdef VELOCIKEY_ENABLE
624 velocikey_enabled() ? velocikey_match_speed(velocikey_min, velocikey_max) :
625# endif
626 pgm_read_byte(default_interval_address);
627}
628
629#endif
630
631void rgblight_setrgb_range(uint8_t r, uint8_t g, uint8_t b, uint8_t start, uint8_t end) {
632 if (!rgblight_config.enable || start < 0 || start >= end || end > RGBLED_NUM) {
633 return;
634 }
635
636 for (uint8_t i = start; i < end; i++) {
637 led[i].r = r;
638 led[i].g = g;
639 led[i].b = b;
640#ifdef RGBW
641 led[i].w = 0;
642#endif
643 }
644 rgblight_set();
645 wait_ms(1);
646}
647
648void rgblight_sethsv_range(uint8_t hue, uint8_t sat, uint8_t val, uint8_t start, uint8_t end) {
649 if (!rgblight_config.enable) {
650 return;
651 }
652
653 LED_TYPE tmp_led;
654 sethsv(hue, sat, val, &tmp_led);
655 rgblight_setrgb_range(tmp_led.r, tmp_led.g, tmp_led.b, start, end);
656}
657
658#ifndef RGBLIGHT_SPLIT
659void rgblight_setrgb_master(uint8_t r, uint8_t g, uint8_t b) { rgblight_setrgb_range(r, g, b, 0, (uint8_t)RGBLED_NUM / 2); }
660
661void rgblight_setrgb_slave(uint8_t r, uint8_t g, uint8_t b) { rgblight_setrgb_range(r, g, b, (uint8_t)RGBLED_NUM / 2, (uint8_t)RGBLED_NUM); }
662
663void rgblight_sethsv_master(uint8_t hue, uint8_t sat, uint8_t val) { rgblight_sethsv_range(hue, sat, val, 0, (uint8_t)RGBLED_NUM / 2); }
664
665void rgblight_sethsv_slave(uint8_t hue, uint8_t sat, uint8_t val) { rgblight_sethsv_range(hue, sat, val, (uint8_t)RGBLED_NUM / 2, (uint8_t)RGBLED_NUM); }
666#endif // ifndef RGBLIGHT_SPLIT
667
668#ifdef RGBLIGHT_LAYERS
669void rgblight_set_layer_state(uint8_t layer, bool enabled) {
670 rgblight_layer_mask_t mask = (rgblight_layer_mask_t)1 << layer;
671 if (enabled) {
672 rgblight_status.enabled_layer_mask |= mask;
673 } else {
674 rgblight_status.enabled_layer_mask &= ~mask;
675 }
676 RGBLIGHT_SPLIT_SET_CHANGE_LAYERS;
677 // Static modes don't have a ticker running to update the LEDs
678 if (rgblight_status.timer_enabled == false) {
679 rgblight_mode_noeeprom(rgblight_config.mode);
680 }
681
682# ifdef RGBLIGHT_LAYERS_OVERRIDE_RGB_OFF
683 // If not enabled, then nothing else will actually set the LEDs...
684 if (!rgblight_config.enable) {
685 rgblight_set();
686 }
687# endif
688}
689
690bool rgblight_get_layer_state(uint8_t layer) {
691 rgblight_layer_mask_t mask = (rgblight_layer_mask_t)1 << layer;
692 return (rgblight_status.enabled_layer_mask & mask) != 0;
693}
694
695// Write any enabled LED layers into the buffer
696static void rgblight_layers_write(void) {
697 uint8_t i = 0;
698 // For each layer
699 for (const rgblight_segment_t *const *layer_ptr = rgblight_layers; i < RGBLIGHT_MAX_LAYERS; layer_ptr++, i++) {
700 if (!rgblight_get_layer_state(i)) {
701 continue; // Layer is disabled
702 }
703 const rgblight_segment_t *segment_ptr = pgm_read_ptr(layer_ptr);
704 if (segment_ptr == NULL) {
705 break; // No more layers
706 }
707 // For each segment
708 while (1) {
709 rgblight_segment_t segment;
710 memcpy_P(&segment, segment_ptr, sizeof(rgblight_segment_t));
711 if (segment.index == RGBLIGHT_END_SEGMENT_INDEX) {
712 break; // No more segments
713 }
714 // Write segment.count LEDs
715 LED_TYPE *const limit = &led[MIN(segment.index + segment.count, RGBLED_NUM)];
716 for (LED_TYPE *led_ptr = &led[segment.index]; led_ptr < limit; led_ptr++) {
717 sethsv(segment.hue, segment.sat, segment.val, led_ptr);
718 }
719 segment_ptr++;
720 }
721 }
722}
723
724# ifdef RGBLIGHT_LAYER_BLINK
725rgblight_layer_mask_t _blinking_layer_mask = 0;
726static uint16_t _repeat_timer;
727static uint8_t _times_remaining;
728static uint16_t _dur;
729
730void rgblight_blink_layer(uint8_t layer, uint16_t duration_ms) { rgblight_blink_layer_repeat(layer, duration_ms, 1); }
731
732void rgblight_blink_layer_repeat(uint8_t layer, uint16_t duration_ms, uint8_t times) {
733 _times_remaining = times * 2;
734 _dur = duration_ms;
735
736 rgblight_set_layer_state(layer, true);
737 _times_remaining--;
738 _blinking_layer_mask |= (rgblight_layer_mask_t)1 << layer;
739 _repeat_timer = sync_timer_read() + duration_ms;
740}
741
742void rgblight_blink_layer_repeat_helper(void) {
743 if (_blinking_layer_mask != 0 && timer_expired(sync_timer_read(), _repeat_timer)) {
744 for (uint8_t layer = 0; layer < RGBLIGHT_MAX_LAYERS; layer++) {
745 if ((_blinking_layer_mask & (rgblight_layer_mask_t)1 << layer) != 0 && _times_remaining > 0) {
746 if (_times_remaining % 2 == 1) {
747 rgblight_set_layer_state(layer, false);
748 } else {
749 rgblight_set_layer_state(layer, true);
750 }
751 _times_remaining--;
752 _repeat_timer = sync_timer_read() + _dur;
753 }
754 }
755 if (_times_remaining <= 0) {
756 _blinking_layer_mask = 0;
757 }
758 }
759}
760# endif
761
762#endif
763
764#ifdef RGBLIGHT_SLEEP
765
766void rgblight_suspend(void) {
767 rgblight_timer_disable();
768 if (!is_suspended) {
769 is_suspended = true;
770 pre_suspend_enabled = rgblight_config.enable;
771
772# ifdef RGBLIGHT_LAYER_BLINK
773 // make sure any layer blinks don't come back after suspend
774 rgblight_status.enabled_layer_mask &= ~_blinking_layer_mask;
775 _blinking_layer_mask = 0;
776# endif
777
778 rgblight_disable_noeeprom();
779 }
780}
781
782void rgblight_wakeup(void) {
783 is_suspended = false;
784
785 if (pre_suspend_enabled) {
786 rgblight_enable_noeeprom();
787 }
788# ifdef RGBLIGHT_LAYERS_OVERRIDE_RGB_OFF
789 // Need this or else the LEDs won't be set
790 else if (rgblight_status.enabled_layer_mask != 0) {
791 rgblight_set();
792 }
793# endif
794
795 rgblight_timer_enable();
796}
797
798#endif
799
800__attribute__((weak)) void rgblight_call_driver(LED_TYPE *start_led, uint8_t num_leds) { ws2812_setleds(start_led, num_leds); }
801
802#ifndef RGBLIGHT_CUSTOM_DRIVER
803
804void rgblight_set(void) {
805 LED_TYPE *start_led;
806 uint8_t num_leds = rgblight_ranges.clipping_num_leds;
807
808 if (!rgblight_config.enable) {
809 for (uint8_t i = rgblight_ranges.effect_start_pos; i < rgblight_ranges.effect_end_pos; i++) {
810 led[i].r = 0;
811 led[i].g = 0;
812 led[i].b = 0;
813# ifdef RGBW
814 led[i].w = 0;
815# endif
816 }
817 }
818
819# ifdef RGBLIGHT_LAYERS
820 if (rgblight_layers != NULL
821# if !defined(RGBLIGHT_LAYERS_OVERRIDE_RGB_OFF)
822 && rgblight_config.enable
823# elif defined(RGBLIGHT_SLEEP)
824 && !is_suspended
825# endif
826 ) {
827 rgblight_layers_write();
828 }
829# endif
830
831# ifdef RGBLIGHT_LED_MAP
832 LED_TYPE led0[RGBLED_NUM];
833 for (uint8_t i = 0; i < RGBLED_NUM; i++) {
834 led0[i] = led[pgm_read_byte(&led_map[i])];
835 }
836 start_led = led0 + rgblight_ranges.clipping_start_pos;
837# else
838 start_led = led + rgblight_ranges.clipping_start_pos;
839# endif
840
841# ifdef RGBW
842 for (uint8_t i = 0; i < num_leds; i++) {
843 convert_rgb_to_rgbw(&start_led[i]);
844 }
845# endif
846 rgblight_call_driver(start_led, num_leds);
847}
848#endif
849
850#ifdef RGBLIGHT_SPLIT
851/* for split keyboard master side */
852uint8_t rgblight_get_change_flags(void) { return rgblight_status.change_flags; }
853
854void rgblight_clear_change_flags(void) { rgblight_status.change_flags = 0; }
855
856void rgblight_get_syncinfo(rgblight_syncinfo_t *syncinfo) {
857 syncinfo->config = rgblight_config;
858 syncinfo->status = rgblight_status;
859}
860
861/* for split keyboard slave side */
862void rgblight_update_sync(rgblight_syncinfo_t *syncinfo, bool write_to_eeprom) {
863# ifdef RGBLIGHT_LAYERS
864 if (syncinfo->status.change_flags & RGBLIGHT_STATUS_CHANGE_LAYERS) {
865 rgblight_status.enabled_layer_mask = syncinfo->status.enabled_layer_mask;
866 }
867# endif
868 if (syncinfo->status.change_flags & RGBLIGHT_STATUS_CHANGE_MODE) {
869 if (syncinfo->config.enable) {
870 rgblight_config.enable = 1; // == rgblight_enable_noeeprom();
871 rgblight_mode_eeprom_helper(syncinfo->config.mode, write_to_eeprom);
872 } else {
873 rgblight_disable_noeeprom();
874 }
875 }
876 if (syncinfo->status.change_flags & RGBLIGHT_STATUS_CHANGE_HSVS) {
877 rgblight_sethsv_eeprom_helper(syncinfo->config.hue, syncinfo->config.sat, syncinfo->config.val, write_to_eeprom);
878 // rgblight_config.speed = config->speed; // NEED???
879 }
880# ifdef RGBLIGHT_USE_TIMER
881 if (syncinfo->status.change_flags & RGBLIGHT_STATUS_CHANGE_TIMER) {
882 if (syncinfo->status.timer_enabled) {
883 rgblight_timer_enable();
884 } else {
885 rgblight_timer_disable();
886 }
887 }
888# ifndef RGBLIGHT_SPLIT_NO_ANIMATION_SYNC
889 if (syncinfo->status.change_flags & RGBLIGHT_STATUS_ANIMATION_TICK) {
890 animation_status.restart = true;
891 }
892# endif /* RGBLIGHT_SPLIT_NO_ANIMATION_SYNC */
893# endif /* RGBLIGHT_USE_TIMER */
894}
895#endif /* RGBLIGHT_SPLIT */
896
897#ifdef RGBLIGHT_USE_TIMER
898
899typedef void (*effect_func_t)(animation_status_t *anim);
900
901// Animation timer -- use system timer (AVR Timer0)
902void rgblight_timer_init(void) {
903 rgblight_status.timer_enabled = false;
904 RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE;
905}
906void rgblight_timer_enable(void) {
907 if (!is_static_effect(rgblight_config.mode)) {
908 rgblight_status.timer_enabled = true;
909 }
910 animation_status.last_timer = sync_timer_read();
911 RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE;
912 dprintf("rgblight timer enabled.\n");
913}
914void rgblight_timer_disable(void) {
915 rgblight_status.timer_enabled = false;
916 RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE;
917 dprintf("rgblight timer disable.\n");
918}
919void rgblight_timer_toggle(void) {
920 dprintf("rgblight timer toggle.\n");
921 if (rgblight_status.timer_enabled) {
922 rgblight_timer_disable();
923 } else {
924 rgblight_timer_enable();
925 }
926}
927
928void rgblight_show_solid_color(uint8_t r, uint8_t g, uint8_t b) {
929 rgblight_enable();
930 rgblight_mode(RGBLIGHT_MODE_STATIC_LIGHT);
931 rgblight_setrgb(r, g, b);
932}
933
934static void rgblight_effect_dummy(animation_status_t *anim) {
935 // do nothing
936 /********
937 dprintf("rgblight_task() what happened?\n");
938 dprintf("is_static_effect %d\n", is_static_effect(rgblight_config.mode));
939 dprintf("mode = %d, base_mode = %d, timer_enabled %d, ",
940 rgblight_config.mode, rgblight_status.base_mode,
941 rgblight_status.timer_enabled);
942 dprintf("last_timer = %d\n",anim->last_timer);
943 **/
944}
945
946void rgblight_task(void) {
947 if (rgblight_status.timer_enabled) {
948 effect_func_t effect_func = rgblight_effect_dummy;
949 uint16_t interval_time = 2000; // dummy interval
950 uint8_t delta = rgblight_config.mode - rgblight_status.base_mode;
951 animation_status.delta = delta;
952
953 // static light mode, do nothing here
954 if (1 == 0) { // dummy
955 }
956# ifdef RGBLIGHT_EFFECT_BREATHING
957 else if (rgblight_status.base_mode == RGBLIGHT_MODE_BREATHING) {
958 // breathing mode
959 interval_time = get_interval_time(&RGBLED_BREATHING_INTERVALS[delta], 1, 100);
960 effect_func = rgblight_effect_breathing;
961 }
962# endif
963# ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD
964 else if (rgblight_status.base_mode == RGBLIGHT_MODE_RAINBOW_MOOD) {
965 // rainbow mood mode
966 interval_time = get_interval_time(&RGBLED_RAINBOW_MOOD_INTERVALS[delta], 5, 100);
967 effect_func = rgblight_effect_rainbow_mood;
968 }
969# endif
970# ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL
971 else if (rgblight_status.base_mode == RGBLIGHT_MODE_RAINBOW_SWIRL) {
972 // rainbow swirl mode
973 interval_time = get_interval_time(&RGBLED_RAINBOW_SWIRL_INTERVALS[delta / 2], 1, 100);
974 effect_func = rgblight_effect_rainbow_swirl;
975 }
976# endif
977# ifdef RGBLIGHT_EFFECT_SNAKE
978 else if (rgblight_status.base_mode == RGBLIGHT_MODE_SNAKE) {
979 // snake mode
980 interval_time = get_interval_time(&RGBLED_SNAKE_INTERVALS[delta / 2], 1, 200);
981 effect_func = rgblight_effect_snake;
982 }
983# endif
984# ifdef RGBLIGHT_EFFECT_KNIGHT
985 else if (rgblight_status.base_mode == RGBLIGHT_MODE_KNIGHT) {
986 // knight mode
987 interval_time = get_interval_time(&RGBLED_KNIGHT_INTERVALS[delta], 5, 100);
988 effect_func = rgblight_effect_knight;
989 }
990# endif
991# ifdef RGBLIGHT_EFFECT_CHRISTMAS
992 else if (rgblight_status.base_mode == RGBLIGHT_MODE_CHRISTMAS) {
993 // christmas mode
994 interval_time = RGBLIGHT_EFFECT_CHRISTMAS_INTERVAL;
995 effect_func = (effect_func_t)rgblight_effect_christmas;
996 }
997# endif
998# ifdef RGBLIGHT_EFFECT_RGB_TEST
999 else if (rgblight_status.base_mode == RGBLIGHT_MODE_RGB_TEST) {
1000 // RGB test mode
1001 interval_time = pgm_read_word(&RGBLED_RGBTEST_INTERVALS[0]);
1002 effect_func = (effect_func_t)rgblight_effect_rgbtest;
1003 }
1004# endif
1005# ifdef RGBLIGHT_EFFECT_ALTERNATING
1006 else if (rgblight_status.base_mode == RGBLIGHT_MODE_ALTERNATING) {
1007 interval_time = 500;
1008 effect_func = (effect_func_t)rgblight_effect_alternating;
1009 }
1010# endif
1011# ifdef RGBLIGHT_EFFECT_TWINKLE
1012 else if (rgblight_status.base_mode == RGBLIGHT_MODE_TWINKLE) {
1013 interval_time = get_interval_time(&RGBLED_TWINKLE_INTERVALS[delta % 3], 5, 30);
1014 effect_func = (effect_func_t)rgblight_effect_twinkle;
1015 }
1016# endif
1017 if (animation_status.restart) {
1018 animation_status.restart = false;
1019 animation_status.last_timer = sync_timer_read();
1020 animation_status.pos16 = 0; // restart signal to local each effect
1021 }
1022 uint16_t now = sync_timer_read();
1023 if (timer_expired(now, animation_status.last_timer)) {
1024# if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
1025 static uint16_t report_last_timer = 0;
1026 static bool tick_flag = false;
1027 uint16_t oldpos16;
1028 if (tick_flag) {
1029 tick_flag = false;
1030 if (timer_expired(now, report_last_timer)) {
1031 report_last_timer += 30000;
1032 dprintf("rgblight animation tick report to slave\n");
1033 RGBLIGHT_SPLIT_ANIMATION_TICK;
1034 }
1035 }
1036 oldpos16 = animation_status.pos16;
1037# endif
1038 animation_status.last_timer += interval_time;
1039 effect_func(&animation_status);
1040# if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
1041 if (animation_status.pos16 == 0 && oldpos16 != 0) {
1042 tick_flag = true;
1043 }
1044# endif
1045 }
1046 }
1047
1048# ifdef RGBLIGHT_LAYER_BLINK
1049 rgblight_blink_layer_repeat_helper();
1050# endif
1051}
1052
1053#endif /* RGBLIGHT_USE_TIMER */
1054
1055#if defined(RGBLIGHT_EFFECT_BREATHING) || defined(RGBLIGHT_EFFECT_TWINKLE)
1056
1057# ifndef RGBLIGHT_EFFECT_BREATHE_CENTER
1058# ifndef RGBLIGHT_BREATHE_TABLE_SIZE
1059# define RGBLIGHT_BREATHE_TABLE_SIZE 256 // 256 or 128 or 64
1060# endif
1061# include <rgblight_breathe_table.h>
1062# endif
1063
1064static uint8_t breathe_calc(uint8_t pos) {
1065 // http://sean.voisen.org/blog/2011/10/breathing-led-with-arduino/
1066# ifdef RGBLIGHT_EFFECT_BREATHE_TABLE
1067 return pgm_read_byte(&rgblight_effect_breathe_table[pos / table_scale]);
1068# else
1069 return (exp(sin((pos / 255.0) * M_PI)) - RGBLIGHT_EFFECT_BREATHE_CENTER / M_E) * (RGBLIGHT_EFFECT_BREATHE_MAX / (M_E - 1 / M_E));
1070# endif
1071}
1072
1073#endif
1074
1075// Effects
1076#ifdef RGBLIGHT_EFFECT_BREATHING
1077
1078__attribute__((weak)) const uint8_t RGBLED_BREATHING_INTERVALS[] PROGMEM = {30, 20, 10, 5};
1079
1080void rgblight_effect_breathing(animation_status_t *anim) {
1081 uint8_t val = breathe_calc(anim->pos);
1082 rgblight_sethsv_noeeprom_old(rgblight_config.hue, rgblight_config.sat, val);
1083 anim->pos = (anim->pos + 1);
1084}
1085#endif
1086
1087#ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD
1088__attribute__((weak)) const uint8_t RGBLED_RAINBOW_MOOD_INTERVALS[] PROGMEM = {120, 60, 30};
1089
1090void rgblight_effect_rainbow_mood(animation_status_t *anim) {
1091 rgblight_sethsv_noeeprom_old(anim->current_hue, rgblight_config.sat, rgblight_config.val);
1092 anim->current_hue++;
1093}
1094#endif
1095
1096#ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL
1097# ifndef RGBLIGHT_RAINBOW_SWIRL_RANGE
1098# define RGBLIGHT_RAINBOW_SWIRL_RANGE 255
1099# endif
1100
1101__attribute__((weak)) const uint8_t RGBLED_RAINBOW_SWIRL_INTERVALS[] PROGMEM = {100, 50, 20};
1102
1103void rgblight_effect_rainbow_swirl(animation_status_t *anim) {
1104 uint8_t hue;
1105 uint8_t i;
1106
1107 for (i = 0; i < rgblight_ranges.effect_num_leds; i++) {
1108 hue = (RGBLIGHT_RAINBOW_SWIRL_RANGE / rgblight_ranges.effect_num_leds * i + anim->current_hue);
1109 sethsv(hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i + rgblight_ranges.effect_start_pos]);
1110 }
1111 rgblight_set();
1112
1113 if (anim->delta % 2) {
1114 anim->current_hue++;
1115 } else {
1116 anim->current_hue--;
1117 }
1118}
1119#endif
1120
1121#ifdef RGBLIGHT_EFFECT_SNAKE
1122__attribute__((weak)) const uint8_t RGBLED_SNAKE_INTERVALS[] PROGMEM = {100, 50, 20};
1123
1124void rgblight_effect_snake(animation_status_t *anim) {
1125 static uint8_t pos = 0;
1126 uint8_t i, j;
1127 int8_t k;
1128 int8_t increment = 1;
1129
1130 if (anim->delta % 2) {
1131 increment = -1;
1132 }
1133
1134# if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
1135 if (anim->pos == 0) { // restart signal
1136 if (increment == 1) {
1137 pos = rgblight_ranges.effect_num_leds - 1;
1138 } else {
1139 pos = 0;
1140 }
1141 anim->pos = 1;
1142 }
1143# endif
1144
1145 for (i = 0; i < rgblight_ranges.effect_num_leds; i++) {
1146 LED_TYPE *ledp = led + i + rgblight_ranges.effect_start_pos;
1147 ledp->r = 0;
1148 ledp->g = 0;
1149 ledp->b = 0;
1150# ifdef RGBW
1151 ledp->w = 0;
1152# endif
1153 for (j = 0; j < RGBLIGHT_EFFECT_SNAKE_LENGTH; j++) {
1154 k = pos + j * increment;
1155 if (k > RGBLED_NUM) {
1156 k = k % RGBLED_NUM;
1157 }
1158 if (k < 0) {
1159 k = k + rgblight_ranges.effect_num_leds;
1160 }
1161 if (i == k) {
1162 sethsv(rgblight_config.hue, rgblight_config.sat, (uint8_t)(rgblight_config.val * (RGBLIGHT_EFFECT_SNAKE_LENGTH - j) / RGBLIGHT_EFFECT_SNAKE_LENGTH), ledp);
1163 }
1164 }
1165 }
1166 rgblight_set();
1167 if (increment == 1) {
1168 if (pos - 1 < 0) {
1169 pos = rgblight_ranges.effect_num_leds - 1;
1170# if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
1171 anim->pos = 0;
1172# endif
1173 } else {
1174 pos -= 1;
1175# if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
1176 anim->pos = 1;
1177# endif
1178 }
1179 } else {
1180 pos = (pos + 1) % rgblight_ranges.effect_num_leds;
1181# if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
1182 anim->pos = pos;
1183# endif
1184 }
1185}
1186#endif
1187
1188#ifdef RGBLIGHT_EFFECT_KNIGHT
1189__attribute__((weak)) const uint8_t RGBLED_KNIGHT_INTERVALS[] PROGMEM = {127, 63, 31};
1190
1191void rgblight_effect_knight(animation_status_t *anim) {
1192 static int8_t low_bound = 0;
1193 static int8_t high_bound = RGBLIGHT_EFFECT_KNIGHT_LENGTH - 1;
1194 static int8_t increment = 1;
1195 uint8_t i, cur;
1196
1197# if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
1198 if (anim->pos == 0) { // restart signal
1199 anim->pos = 1;
1200 low_bound = 0;
1201 high_bound = RGBLIGHT_EFFECT_KNIGHT_LENGTH - 1;
1202 increment = 1;
1203 }
1204# endif
1205 // Set all the LEDs to 0
1206 for (i = rgblight_ranges.effect_start_pos; i < rgblight_ranges.effect_end_pos; i++) {
1207 led[i].r = 0;
1208 led[i].g = 0;
1209 led[i].b = 0;
1210# ifdef RGBW
1211 led[i].w = 0;
1212# endif
1213 }
1214 // Determine which LEDs should be lit up
1215 for (i = 0; i < RGBLIGHT_EFFECT_KNIGHT_LED_NUM; i++) {
1216 cur = (i + RGBLIGHT_EFFECT_KNIGHT_OFFSET) % rgblight_ranges.effect_num_leds + rgblight_ranges.effect_start_pos;
1217
1218 if (i >= low_bound && i <= high_bound) {
1219 sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[cur]);
1220 } else {
1221 led[cur].r = 0;
1222 led[cur].g = 0;
1223 led[cur].b = 0;
1224# ifdef RGBW
1225 led[cur].w = 0;
1226# endif
1227 }
1228 }
1229 rgblight_set();
1230
1231 // Move from low_bound to high_bound changing the direction we increment each
1232 // time a boundary is hit.
1233 low_bound += increment;
1234 high_bound += increment;
1235
1236 if (high_bound <= 0 || low_bound >= RGBLIGHT_EFFECT_KNIGHT_LED_NUM - 1) {
1237 increment = -increment;
1238# if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
1239 if (increment == 1) {
1240 anim->pos = 0;
1241 }
1242# endif
1243 }
1244}
1245#endif
1246
1247#ifdef RGBLIGHT_EFFECT_CHRISTMAS
1248# define CUBED(x) ((x) * (x) * (x))
1249
1250/**
1251 * Christmas lights effect, with a smooth animation between red & green.
1252 */
1253void rgblight_effect_christmas(animation_status_t *anim) {
1254 static int8_t increment = 1;
1255 const uint8_t max_pos = 32;
1256 const uint8_t hue_green = 85;
1257
1258 uint32_t xa;
1259 uint8_t hue, val;
1260 uint8_t i;
1261
1262 // The effect works by animating anim->pos from 0 to 32 and back to 0.
1263 // The pos is used in a cubic bezier formula to ease-in-out between red and green, leaving the interpolated colors visible as short as possible.
1264 xa = CUBED((uint32_t)anim->pos);
1265 hue = ((uint32_t)hue_green) * xa / (xa + CUBED((uint32_t)(max_pos - anim->pos)));
1266 // Additionally, these interpolated colors get shown with a slightly darker value, to make them less prominent than the main colors.
1267 val = 255 - (3 * (hue < hue_green / 2 ? hue : hue_green - hue) / 2);
1268
1269 for (i = 0; i < rgblight_ranges.effect_num_leds; i++) {
1270 uint8_t local_hue = (i / RGBLIGHT_EFFECT_CHRISTMAS_STEP) % 2 ? hue : hue_green - hue;
1271 sethsv(local_hue, rgblight_config.sat, val, (LED_TYPE *)&led[i + rgblight_ranges.effect_start_pos]);
1272 }
1273 rgblight_set();
1274
1275 if (anim->pos == 0) {
1276 increment = 1;
1277 } else if (anim->pos == max_pos) {
1278 increment = -1;
1279 }
1280 anim->pos += increment;
1281}
1282#endif
1283
1284#ifdef RGBLIGHT_EFFECT_RGB_TEST
1285__attribute__((weak)) const uint16_t RGBLED_RGBTEST_INTERVALS[] PROGMEM = {1024};
1286
1287void rgblight_effect_rgbtest(animation_status_t *anim) {
1288 static uint8_t maxval = 0;
1289 uint8_t g;
1290 uint8_t r;
1291 uint8_t b;
1292
1293 if (maxval == 0) {
1294 LED_TYPE tmp_led;
1295 sethsv(0, 255, RGBLIGHT_LIMIT_VAL, &tmp_led);
1296 maxval = tmp_led.r;
1297 }
1298 g = r = b = 0;
1299 switch (anim->pos) {
1300 case 0:
1301 r = maxval;
1302 break;
1303 case 1:
1304 g = maxval;
1305 break;
1306 case 2:
1307 b = maxval;
1308 break;
1309 }
1310 rgblight_setrgb(r, g, b);
1311 anim->pos = (anim->pos + 1) % 3;
1312}
1313#endif
1314
1315#ifdef RGBLIGHT_EFFECT_ALTERNATING
1316void rgblight_effect_alternating(animation_status_t *anim) {
1317 for (int i = 0; i < rgblight_ranges.effect_num_leds; i++) {
1318 LED_TYPE *ledp = led + i + rgblight_ranges.effect_start_pos;
1319 if (i < rgblight_ranges.effect_num_leds / 2 && anim->pos) {
1320 sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, ledp);
1321 } else if (i >= rgblight_ranges.effect_num_leds / 2 && !anim->pos) {
1322 sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, ledp);
1323 } else {
1324 sethsv(rgblight_config.hue, rgblight_config.sat, 0, ledp);
1325 }
1326 }
1327 rgblight_set();
1328 anim->pos = (anim->pos + 1) % 2;
1329}
1330#endif
1331
1332#ifdef RGBLIGHT_EFFECT_TWINKLE
1333__attribute__((weak)) const uint8_t RGBLED_TWINKLE_INTERVALS[] PROGMEM = {30, 15, 5};
1334
1335typedef struct PACKED {
1336 HSV hsv;
1337 uint8_t life;
1338 uint8_t max_life;
1339} TwinkleState;
1340
1341static TwinkleState led_twinkle_state[RGBLED_NUM];
1342
1343void rgblight_effect_twinkle(animation_status_t *anim) {
1344 const bool random_color = anim->delta / 3;
1345 const bool restart = anim->pos == 0;
1346 anim->pos = 1;
1347
1348 const uint8_t bottom = breathe_calc(0);
1349 const uint8_t top = breathe_calc(127);
1350
1351 uint8_t frac(uint8_t n, uint8_t d) { return (uint16_t)255 * n / d; }
1352 uint8_t scale(uint16_t v, uint8_t scale) { return (v * scale) >> 8; }
1353
1354 for (uint8_t i = 0; i < rgblight_ranges.effect_num_leds; i++) {
1355 TwinkleState *t = &(led_twinkle_state[i]);
1356 HSV * c = &(t->hsv);
1357
1358 if (!random_color) {
1359 c->h = rgblight_config.hue;
1360 c->s = rgblight_config.sat;
1361 }
1362
1363 if (restart) {
1364 // Restart
1365 t->life = 0;
1366 c->v = 0;
1367 } else if (t->life) {
1368 // This LED is already on, either brightening or dimming
1369 t->life--;
1370 uint8_t unscaled = frac(breathe_calc(frac(t->life, t->max_life)) - bottom, top - bottom);
1371 c->v = scale(rgblight_config.val, unscaled);
1372 } else if (rand() < scale((uint16_t)RAND_MAX * RGBLIGHT_EFFECT_TWINKLE_PROBABILITY, 127 + rgblight_config.val / 2)) {
1373 // This LED is off, but was randomly selected to start brightening
1374 if (random_color) {
1375 c->h = rand() % 0xFF;
1376 c->s = (rand() % (rgblight_config.sat / 2)) + (rgblight_config.sat / 2);
1377 }
1378 c->v = 0;
1379 t->max_life = MAX(20, MIN(RGBLIGHT_EFFECT_TWINKLE_LIFE, rgblight_config.val));
1380 t->life = t->max_life;
1381 } else {
1382 // This LED is off, and was NOT selected to start brightening
1383 }
1384
1385 LED_TYPE *ledp = led + i + rgblight_ranges.effect_start_pos;
1386 sethsv(c->h, c->s, c->v, ledp);
1387 }
1388
1389 rgblight_set();
1390}
1391#endif
diff --git a/quantum/rgblight/rgblight.h b/quantum/rgblight/rgblight.h
new file mode 100644
index 000000000..bec2c6695
--- /dev/null
+++ b/quantum/rgblight/rgblight.h
@@ -0,0 +1,442 @@
1/* Copyright 2017 Yang Liu
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#pragma once
18
19/***** rgblight_mode(mode)/rgblight_mode_noeeprom(mode) ****
20
21 old mode number (before 0.6.117) to new mode name table
22
23|-----------------|-----------------------------------|
24| old mode number | new mode name |
25|-----------------|-----------------------------------|
26| 1 | RGBLIGHT_MODE_STATIC_LIGHT |
27| 2 | RGBLIGHT_MODE_BREATHING |
28| 3 | RGBLIGHT_MODE_BREATHING + 1 |
29| 4 | RGBLIGHT_MODE_BREATHING + 2 |
30| 5 | RGBLIGHT_MODE_BREATHING + 3 |
31| 6 | RGBLIGHT_MODE_RAINBOW_MOOD |
32| 7 | RGBLIGHT_MODE_RAINBOW_MOOD + 1 |
33| 8 | RGBLIGHT_MODE_RAINBOW_MOOD + 2 |
34| 9 | RGBLIGHT_MODE_RAINBOW_SWIRL |
35| 10 | RGBLIGHT_MODE_RAINBOW_SWIRL + 1 |
36| 11 | RGBLIGHT_MODE_RAINBOW_SWIRL + 2 |
37| 12 | RGBLIGHT_MODE_RAINBOW_SWIRL + 3 |
38| 13 | RGBLIGHT_MODE_RAINBOW_SWIRL + 4 |
39| 14 | RGBLIGHT_MODE_RAINBOW_SWIRL + 5 |
40| 15 | RGBLIGHT_MODE_SNAKE |
41| 16 | RGBLIGHT_MODE_SNAKE + 1 |
42| 17 | RGBLIGHT_MODE_SNAKE + 2 |
43| 18 | RGBLIGHT_MODE_SNAKE + 3 |
44| 19 | RGBLIGHT_MODE_SNAKE + 4 |
45| 20 | RGBLIGHT_MODE_SNAKE + 5 |
46| 21 | RGBLIGHT_MODE_KNIGHT |
47| 22 | RGBLIGHT_MODE_KNIGHT + 1 |
48| 23 | RGBLIGHT_MODE_KNIGHT + 2 |
49| 24 | RGBLIGHT_MODE_CHRISTMAS |
50| 25 | RGBLIGHT_MODE_STATIC_GRADIENT |
51| 26 | RGBLIGHT_MODE_STATIC_GRADIENT + 1 |
52| 27 | RGBLIGHT_MODE_STATIC_GRADIENT + 2 |
53| 28 | RGBLIGHT_MODE_STATIC_GRADIENT + 3 |
54| 29 | RGBLIGHT_MODE_STATIC_GRADIENT + 4 |
55| 30 | RGBLIGHT_MODE_STATIC_GRADIENT + 5 |
56| 31 | RGBLIGHT_MODE_STATIC_GRADIENT + 6 |
57| 32 | RGBLIGHT_MODE_STATIC_GRADIENT + 7 |
58| 33 | RGBLIGHT_MODE_STATIC_GRADIENT + 8 |
59| 34 | RGBLIGHT_MODE_STATIC_GRADIENT + 9 |
60| 35 | RGBLIGHT_MODE_RGB_TEST |
61| 36 | RGBLIGHT_MODE_ALTERNATING |
62| 37 | RGBLIGHT_MODE_TWINKLE |
63| 38 | RGBLIGHT_MODE_TWINKLE + 1 |
64| 39 | RGBLIGHT_MODE_TWINKLE + 2 |
65| 40 | RGBLIGHT_MODE_TWINKLE + 3 |
66| 41 | RGBLIGHT_MODE_TWINKLE + 4 |
67| 42 | RGBLIGHT_MODE_TWINKLE + 5 |
68|-----------------|-----------------------------------|
69 *****/
70
71#ifdef RGBLIGHT_ANIMATIONS
72// for backward compatibility
73# define RGBLIGHT_EFFECT_BREATHING
74# define RGBLIGHT_EFFECT_RAINBOW_MOOD
75# define RGBLIGHT_EFFECT_RAINBOW_SWIRL
76# define RGBLIGHT_EFFECT_SNAKE
77# define RGBLIGHT_EFFECT_KNIGHT
78# define RGBLIGHT_EFFECT_CHRISTMAS
79# define RGBLIGHT_EFFECT_STATIC_GRADIENT
80# define RGBLIGHT_EFFECT_RGB_TEST
81# define RGBLIGHT_EFFECT_ALTERNATING
82# define RGBLIGHT_EFFECT_TWINKLE
83#endif
84
85#ifdef RGBLIGHT_STATIC_PATTERNS
86# define RGBLIGHT_EFFECT_STATIC_GRADIENT
87#endif
88
89// clang-format off
90
91// check dynamic animation effects chose ?
92#if defined(RGBLIGHT_EFFECT_BREATHING) \
93 || defined(RGBLIGHT_EFFECT_RAINBOW_MOOD) \
94 || defined(RGBLIGHT_EFFECT_RAINBOW_SWIRL) \
95 || defined(RGBLIGHT_EFFECT_SNAKE) \
96 || defined(RGBLIGHT_EFFECT_KNIGHT) \
97 || defined(RGBLIGHT_EFFECT_CHRISTMAS) \
98 || defined(RGBLIGHT_EFFECT_RGB_TEST) \
99 || defined(RGBLIGHT_EFFECT_ALTERNATING) \
100 || defined(RGBLIGHT_EFFECT_TWINKLE)
101# define RGBLIGHT_USE_TIMER
102#endif
103
104// clang-format on
105
106#define _RGBM_SINGLE_STATIC(sym) RGBLIGHT_MODE_##sym,
107#define _RGBM_SINGLE_DYNAMIC(sym) RGBLIGHT_MODE_##sym,
108#define _RGBM_MULTI_STATIC(sym) RGBLIGHT_MODE_##sym,
109#define _RGBM_MULTI_DYNAMIC(sym) RGBLIGHT_MODE_##sym,
110#define _RGBM_TMP_STATIC(sym, msym) RGBLIGHT_MODE_##sym,
111#define _RGBM_TMP_DYNAMIC(sym, msym) RGBLIGHT_MODE_##sym,
112enum RGBLIGHT_EFFECT_MODE {
113 RGBLIGHT_MODE_zero = 0,
114#include "rgblight_modes.h"
115 RGBLIGHT_MODE_last
116};
117
118#ifndef RGBLIGHT_H_DUMMY_DEFINE
119
120# define RGBLIGHT_MODES (RGBLIGHT_MODE_last - 1)
121
122// sample: #define RGBLIGHT_EFFECT_BREATHE_CENTER 1.85
123
124# ifndef RGBLIGHT_EFFECT_BREATHE_MAX
125# define RGBLIGHT_EFFECT_BREATHE_MAX 255 // 0-255
126# endif
127
128# ifndef RGBLIGHT_EFFECT_SNAKE_LENGTH
129# define RGBLIGHT_EFFECT_SNAKE_LENGTH 4
130# endif
131
132# ifndef RGBLIGHT_EFFECT_KNIGHT_LENGTH
133# define RGBLIGHT_EFFECT_KNIGHT_LENGTH 3
134# endif
135
136# ifndef RGBLIGHT_EFFECT_KNIGHT_OFFSET
137# define RGBLIGHT_EFFECT_KNIGHT_OFFSET 0
138# endif
139
140# ifndef RGBLIGHT_EFFECT_KNIGHT_LED_NUM
141# define RGBLIGHT_EFFECT_KNIGHT_LED_NUM (rgblight_ranges.effect_num_leds)
142# endif
143
144# ifndef RGBLIGHT_EFFECT_CHRISTMAS_INTERVAL
145# define RGBLIGHT_EFFECT_CHRISTMAS_INTERVAL 40
146# endif
147
148# ifndef RGBLIGHT_EFFECT_CHRISTMAS_STEP
149# define RGBLIGHT_EFFECT_CHRISTMAS_STEP 2
150# endif
151
152# ifndef RGBLIGHT_EFFECT_TWINKLE_LIFE
153# define RGBLIGHT_EFFECT_TWINKLE_LIFE 200
154# endif
155
156# ifndef RGBLIGHT_EFFECT_TWINKLE_PROBABILITY
157# define RGBLIGHT_EFFECT_TWINKLE_PROBABILITY 1 / 127
158# endif
159
160# ifndef RGBLIGHT_HUE_STEP
161# define RGBLIGHT_HUE_STEP 8
162# endif
163# ifndef RGBLIGHT_SAT_STEP
164# define RGBLIGHT_SAT_STEP 17
165# endif
166# ifndef RGBLIGHT_VAL_STEP
167# define RGBLIGHT_VAL_STEP 17
168# endif
169# ifndef RGBLIGHT_LIMIT_VAL
170# define RGBLIGHT_LIMIT_VAL 255
171# endif
172
173# include <stdint.h>
174# include <stdbool.h>
175# include "eeconfig.h"
176# include "ws2812.h"
177# include "color.h"
178# include "rgblight_list.h"
179
180# if defined(__AVR__)
181# include <avr/pgmspace.h>
182# endif
183
184# ifdef RGBLIGHT_LAYERS
185typedef struct {
186 uint8_t index; // The first LED to light
187 uint8_t count; // The number of LEDs to light
188 uint8_t hue;
189 uint8_t sat;
190 uint8_t val;
191} rgblight_segment_t;
192
193# define RGBLIGHT_END_SEGMENT_INDEX (255)
194# define RGBLIGHT_END_SEGMENTS \
195 { RGBLIGHT_END_SEGMENT_INDEX, 0, 0, 0 }
196# ifndef RGBLIGHT_MAX_LAYERS
197# define RGBLIGHT_MAX_LAYERS 8
198# endif
199# if RGBLIGHT_MAX_LAYERS <= 0
200# error invalid RGBLIGHT_MAX_LAYERS value (must be >= 1)
201# elif RGBLIGHT_MAX_LAYERS <= 8
202typedef uint8_t rgblight_layer_mask_t;
203# elif RGBLIGHT_MAX_LAYERS <= 16
204typedef uint16_t rgblight_layer_mask_t;
205# elif RGBLIGHT_MAX_LAYERS <= 32
206typedef uint32_t rgblight_layer_mask_t;
207# else
208# error invalid RGBLIGHT_MAX_LAYERS value (must be <= 32)
209# endif
210# define RGBLIGHT_LAYER_SEGMENTS(...) \
211 { __VA_ARGS__, RGBLIGHT_END_SEGMENTS }
212# define RGBLIGHT_LAYERS_LIST(...) \
213 { __VA_ARGS__, NULL }
214
215// Get/set enabled rgblight layers
216void rgblight_set_layer_state(uint8_t layer, bool enabled);
217bool rgblight_get_layer_state(uint8_t layer);
218
219// Point this to an array of rgblight_segment_t arrays in keyboard_post_init_user to use rgblight layers
220extern const rgblight_segment_t *const *rgblight_layers;
221
222# ifdef RGBLIGHT_LAYER_BLINK
223# define RGBLIGHT_USE_TIMER
224void rgblight_blink_layer(uint8_t layer, uint16_t duration_ms);
225void rgblight_blink_layer_repeat(uint8_t layer, uint16_t duration_ms, uint8_t times);
226# endif
227
228# endif
229
230extern LED_TYPE led[RGBLED_NUM];
231
232extern const uint8_t RGBLED_BREATHING_INTERVALS[4] PROGMEM;
233extern const uint8_t RGBLED_RAINBOW_MOOD_INTERVALS[3] PROGMEM;
234extern const uint8_t RGBLED_RAINBOW_SWIRL_INTERVALS[3] PROGMEM;
235extern const uint8_t RGBLED_SNAKE_INTERVALS[3] PROGMEM;
236extern const uint8_t RGBLED_KNIGHT_INTERVALS[3] PROGMEM;
237extern const uint16_t RGBLED_RGBTEST_INTERVALS[1] PROGMEM;
238extern const uint8_t RGBLED_TWINKLE_INTERVALS[3] PROGMEM;
239extern bool is_rgblight_initialized;
240
241// Should stay in sycn with rgb matrix config as we reuse eeprom storage for both (for now)
242typedef union {
243 uint32_t raw;
244 struct {
245 bool enable : 1;
246 uint8_t mode : 7;
247 uint8_t hue : 8;
248 uint8_t sat : 8;
249 uint8_t val : 8;
250 uint8_t speed : 8; // EECONFIG needs to be increased to support this
251 };
252} rgblight_config_t;
253
254typedef struct _rgblight_status_t {
255 uint8_t base_mode;
256 bool timer_enabled;
257# ifdef RGBLIGHT_SPLIT
258 uint8_t change_flags;
259# endif
260# ifdef RGBLIGHT_LAYERS
261 rgblight_layer_mask_t enabled_layer_mask;
262# endif
263} rgblight_status_t;
264
265/*
266 * Structure for RGB Light clipping ranges
267 */
268typedef struct _rgblight_ranges_t {
269 uint8_t clipping_start_pos;
270 uint8_t clipping_num_leds;
271 uint8_t effect_start_pos;
272 uint8_t effect_end_pos;
273 uint8_t effect_num_leds;
274} rgblight_ranges_t;
275
276extern rgblight_ranges_t rgblight_ranges;
277
278/* === Utility Functions ===*/
279void sethsv(uint8_t hue, uint8_t sat, uint8_t val, LED_TYPE *led1);
280void sethsv_raw(uint8_t hue, uint8_t sat, uint8_t val, LED_TYPE *led1); // without RGBLIGHT_LIMIT_VAL check
281void setrgb(uint8_t r, uint8_t g, uint8_t b, LED_TYPE *led1);
282
283/* === Low level Functions === */
284void rgblight_set(void);
285void rgblight_set_clipping_range(uint8_t start_pos, uint8_t num_leds);
286
287/* === Effects and Animations Functions === */
288/* effect range setting */
289void rgblight_set_effect_range(uint8_t start_pos, uint8_t num_leds);
290
291/* direct operation */
292void rgblight_setrgb_at(uint8_t r, uint8_t g, uint8_t b, uint8_t index);
293void rgblight_sethsv_at(uint8_t hue, uint8_t sat, uint8_t val, uint8_t index);
294void rgblight_setrgb_range(uint8_t r, uint8_t g, uint8_t b, uint8_t start, uint8_t end);
295void rgblight_sethsv_range(uint8_t hue, uint8_t sat, uint8_t val, uint8_t start, uint8_t end);
296void rgblight_setrgb(uint8_t r, uint8_t g, uint8_t b);
297
298# ifndef RGBLIGHT_SPLIT
299void rgblight_setrgb_master(uint8_t r, uint8_t g, uint8_t b);
300void rgblight_setrgb_slave(uint8_t r, uint8_t g, uint8_t b);
301void rgblight_sethsv_master(uint8_t hue, uint8_t sat, uint8_t val);
302void rgblight_sethsv_slave(uint8_t hue, uint8_t sat, uint8_t val);
303# endif
304
305/* effect mode change */
306void rgblight_mode(uint8_t mode);
307void rgblight_mode_noeeprom(uint8_t mode);
308void rgblight_increase(void);
309void rgblight_decrease(void);
310void rgblight_step(void);
311void rgblight_step_noeeprom(void);
312void rgblight_step_reverse(void);
313void rgblight_step_reverse_noeeprom(void);
314
315/* effects mode disable/enable */
316void rgblight_toggle(void);
317void rgblight_toggle_noeeprom(void);
318void rgblight_enable(void);
319void rgblight_enable_noeeprom(void);
320void rgblight_disable(void);
321void rgblight_disable_noeeprom(void);
322
323/* hue, sat, val change */
324void rgblight_increase_hue(void);
325void rgblight_increase_hue_noeeprom(void);
326void rgblight_decrease_hue(void);
327void rgblight_decrease_hue_noeeprom(void);
328void rgblight_increase_sat(void);
329void rgblight_increase_sat_noeeprom(void);
330void rgblight_decrease_sat(void);
331void rgblight_decrease_sat_noeeprom(void);
332void rgblight_increase_val(void);
333void rgblight_increase_val_noeeprom(void);
334void rgblight_decrease_val(void);
335void rgblight_decrease_val_noeeprom(void);
336void rgblight_increase_speed(void);
337void rgblight_increase_speed_noeeprom(void);
338void rgblight_decrease_speed(void);
339void rgblight_decrease_speed_noeeprom(void);
340void rgblight_sethsv(uint8_t hue, uint8_t sat, uint8_t val);
341void rgblight_sethsv_noeeprom(uint8_t hue, uint8_t sat, uint8_t val);
342
343/* effect speed */
344uint8_t rgblight_get_speed(void);
345void rgblight_set_speed(uint8_t speed);
346void rgblight_set_speed_noeeprom(uint8_t speed);
347
348/* reset */
349void rgblight_reload_from_eeprom(void);
350
351/* query */
352uint8_t rgblight_get_mode(void);
353uint8_t rgblight_get_hue(void);
354uint8_t rgblight_get_sat(void);
355uint8_t rgblight_get_val(void);
356bool rgblight_is_enabled(void);
357HSV rgblight_get_hsv(void);
358
359/* === qmk_firmware (core)internal Functions === */
360void rgblight_init(void);
361void rgblight_suspend(void);
362void rgblight_wakeup(void);
363uint32_t rgblight_read_dword(void);
364void rgblight_update_dword(uint32_t dword);
365uint32_t eeconfig_read_rgblight(void);
366void eeconfig_update_rgblight(uint32_t val);
367void eeconfig_update_rgblight_current(void);
368void eeconfig_update_rgblight_default(void);
369void eeconfig_debug_rgblight(void);
370
371void rgb_matrix_increase(void);
372void rgb_matrix_decrease(void);
373
374void rgblight_sethsv_eeprom_helper(uint8_t hue, uint8_t sat, uint8_t val, bool write_to_eeprom);
375void rgblight_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom);
376
377# define EZ_RGB(val) rgblight_show_solid_color((val >> 16) & 0xFF, (val >> 8) & 0xFF, val & 0xFF)
378void rgblight_show_solid_color(uint8_t r, uint8_t g, uint8_t b);
379
380# ifdef RGBLIGHT_USE_TIMER
381void rgblight_task(void);
382void rgblight_timer_init(void);
383void rgblight_timer_enable(void);
384void rgblight_timer_disable(void);
385void rgblight_timer_toggle(void);
386# else
387# define rgblight_task()
388# define rgblight_timer_init()
389# define rgblight_timer_enable()
390# define rgblight_timer_disable()
391# define rgblight_timer_toggle()
392# endif
393
394# ifdef RGBLIGHT_SPLIT
395# define RGBLIGHT_STATUS_CHANGE_MODE (1 << 0)
396# define RGBLIGHT_STATUS_CHANGE_HSVS (1 << 1)
397# define RGBLIGHT_STATUS_CHANGE_TIMER (1 << 2)
398# define RGBLIGHT_STATUS_ANIMATION_TICK (1 << 3)
399# define RGBLIGHT_STATUS_CHANGE_LAYERS (1 << 4)
400
401typedef struct _rgblight_syncinfo_t {
402 rgblight_config_t config;
403 rgblight_status_t status;
404} rgblight_syncinfo_t;
405
406/* for split keyboard master side */
407uint8_t rgblight_get_change_flags(void);
408void rgblight_clear_change_flags(void);
409void rgblight_get_syncinfo(rgblight_syncinfo_t *syncinfo);
410/* for split keyboard slave side */
411void rgblight_update_sync(rgblight_syncinfo_t *syncinfo, bool write_to_eeprom);
412# endif
413
414# ifdef RGBLIGHT_USE_TIMER
415
416typedef struct _animation_status_t {
417 uint16_t last_timer;
418 uint8_t delta; /* mode - base_mode */
419 bool restart;
420 union {
421 uint16_t pos16;
422 uint8_t pos;
423 int8_t current_hue;
424 uint16_t current_offset;
425 };
426} animation_status_t;
427
428extern animation_status_t animation_status;
429
430void rgblight_effect_breathing(animation_status_t *anim);
431void rgblight_effect_rainbow_mood(animation_status_t *anim);
432void rgblight_effect_rainbow_swirl(animation_status_t *anim);
433void rgblight_effect_snake(animation_status_t *anim);
434void rgblight_effect_knight(animation_status_t *anim);
435void rgblight_effect_christmas(animation_status_t *anim);
436void rgblight_effect_rgbtest(animation_status_t *anim);
437void rgblight_effect_alternating(animation_status_t *anim);
438void rgblight_effect_twinkle(animation_status_t *anim);
439
440# endif
441
442#endif // #ifndef RGBLIGHT_H_DUMMY_DEFINE
diff --git a/quantum/rgblight/rgblight_breathe_table.h b/quantum/rgblight/rgblight_breathe_table.h
new file mode 100644
index 000000000..30245318b
--- /dev/null
+++ b/quantum/rgblight/rgblight_breathe_table.h
@@ -0,0 +1,117 @@
1#pragma once
2
3#define RGBLIGHT_EFFECT_BREATHE_TABLE
4
5// clang-format off
6
7// Breathing center: 1.85
8// Breathing max: 255
9
10const uint8_t PROGMEM rgblight_effect_breathe_table[] = {
11#if RGBLIGHT_BREATHE_TABLE_SIZE == 256
12 0x22, 0x23, 0x25, 0x26, 0x28, 0x29, 0x2A, 0x2C,
13 0x2D, 0x2F, 0x30, 0x32, 0x33, 0x35, 0x36, 0x38,
14 0x3A, 0x3B, 0x3D, 0x3E, 0x40, 0x42, 0x43, 0x45,
15 0x47, 0x49, 0x4A, 0x4C, 0x4E, 0x50, 0x51, 0x53,
16 0x55, 0x57, 0x59, 0x5A, 0x5C, 0x5E, 0x60, 0x62,
17 0x64, 0x66, 0x68, 0x69, 0x6B, 0x6D, 0x6F, 0x71,
18 0x73, 0x75, 0x77, 0x79, 0x7B, 0x7D, 0x7F, 0x81,
19 0x83, 0x85, 0x87, 0x89, 0x8A, 0x8C, 0x8E, 0x90,
20 0x92, 0x94, 0x96, 0x98, 0x9A, 0x9C, 0x9E, 0x9F,
21 0xA1, 0xA3, 0xA5, 0xA7, 0xA8, 0xAA, 0xAC, 0xAE,
22 0xAF, 0xB1, 0xB3, 0xB4, 0xB6, 0xB8, 0xB9, 0xBB,
23 0xBC, 0xBE, 0xBF, 0xC1, 0xC2, 0xC3, 0xC5, 0xC6,
24 0xC7, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xD0,
25 0xD1, 0xD2, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7,
26 0xD7, 0xD8, 0xD9, 0xD9, 0xDA, 0xDA, 0xDB, 0xDB,
27 0xDB, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDD, 0xDD,
28 0xDD, 0xDD, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDB,
29 0xDB, 0xDB, 0xDA, 0xDA, 0xD9, 0xD9, 0xD8, 0xD7,
30 0xD7, 0xD6, 0xD5, 0xD4, 0xD3, 0xD2, 0xD2, 0xD1,
31 0xD0, 0xCE, 0xCD, 0xCC, 0xCB, 0xCA, 0xC9, 0xC7,
32 0xC6, 0xC5, 0xC3, 0xC2, 0xC1, 0xBF, 0xBE, 0xBC,
33 0xBB, 0xB9, 0xB8, 0xB6, 0xB4, 0xB3, 0xB1, 0xAF,
34 0xAE, 0xAC, 0xAA, 0xA8, 0xA7, 0xA5, 0xA3, 0xA1,
35 0x9F, 0x9E, 0x9C, 0x9A, 0x98, 0x96, 0x94, 0x92,
36 0x90, 0x8E, 0x8C, 0x8A, 0x89, 0x87, 0x85, 0x83,
37 0x81, 0x7F, 0x7D, 0x7B, 0x79, 0x77, 0x75, 0x73,
38 0x71, 0x6F, 0x6D, 0x6B, 0x69, 0x68, 0x66, 0x64,
39 0x62, 0x60, 0x5E, 0x5C, 0x5A, 0x59, 0x57, 0x55,
40 0x53, 0x51, 0x50, 0x4E, 0x4C, 0x4A, 0x49, 0x47,
41 0x45, 0x43, 0x42, 0x40, 0x3E, 0x3D, 0x3B, 0x3A,
42 0x38, 0x36, 0x35, 0x33, 0x32, 0x30, 0x2F, 0x2D,
43 0x2C, 0x2A, 0x29, 0x28, 0x26, 0x25, 0x23, 0x22
44#endif
45
46#if RGBLIGHT_BREATHE_TABLE_SIZE == 128
47 0x22, 0x25, 0x28, 0x2A,
48 0x2D, 0x30, 0x33, 0x36,
49 0x3A, 0x3D, 0x40, 0x43,
50 0x47, 0x4A, 0x4E, 0x51,
51 0x55, 0x59, 0x5C, 0x60,
52 0x64, 0x68, 0x6B, 0x6F,
53 0x73, 0x77, 0x7B, 0x7F,
54 0x83, 0x87, 0x8A, 0x8E,
55 0x92, 0x96, 0x9A, 0x9E,
56 0xA1, 0xA5, 0xA8, 0xAC,
57 0xAF, 0xB3, 0xB6, 0xB9,
58 0xBC, 0xBF, 0xC2, 0xC5,
59 0xC7, 0xCA, 0xCC, 0xCE,
60 0xD1, 0xD2, 0xD4, 0xD6,
61 0xD7, 0xD9, 0xDA, 0xDB,
62 0xDB, 0xDC, 0xDC, 0xDD,
63 0xDD, 0xDC, 0xDC, 0xDC,
64 0xDB, 0xDA, 0xD9, 0xD8,
65 0xD7, 0xD5, 0xD3, 0xD2,
66 0xD0, 0xCD, 0xCB, 0xC9,
67 0xC6, 0xC3, 0xC1, 0xBE,
68 0xBB, 0xB8, 0xB4, 0xB1,
69 0xAE, 0xAA, 0xA7, 0xA3,
70 0x9F, 0x9C, 0x98, 0x94,
71 0x90, 0x8C, 0x89, 0x85,
72 0x81, 0x7D, 0x79, 0x75,
73 0x71, 0x6D, 0x69, 0x66,
74 0x62, 0x5E, 0x5A, 0x57,
75 0x53, 0x50, 0x4C, 0x49,
76 0x45, 0x42, 0x3E, 0x3B,
77 0x38, 0x35, 0x32, 0x2F,
78 0x2C, 0x29, 0x26, 0x23
79#endif
80
81#if RGBLIGHT_BREATHE_TABLE_SIZE == 64
82 0x22, 0x28,
83 0x2D, 0x33,
84 0x3A, 0x40,
85 0x47, 0x4E,
86 0x55, 0x5C,
87 0x64, 0x6B,
88 0x73, 0x7B,
89 0x83, 0x8A,
90 0x92, 0x9A,
91 0xA1, 0xA8,
92 0xAF, 0xB6,
93 0xBC, 0xC2,
94 0xC7, 0xCC,
95 0xD1, 0xD4,
96 0xD7, 0xDA,
97 0xDB, 0xDC,
98 0xDD, 0xDC,
99 0xDB, 0xD9,
100 0xD7, 0xD3,
101 0xD0, 0xCB,
102 0xC6, 0xC1,
103 0xBB, 0xB4,
104 0xAE, 0xA7,
105 0x9F, 0x98,
106 0x90, 0x89,
107 0x81, 0x79,
108 0x71, 0x69,
109 0x62, 0x5A,
110 0x53, 0x4C,
111 0x45, 0x3E,
112 0x38, 0x32,
113 0x2C, 0x26
114#endif
115};
116
117static const int table_scale = 256 / sizeof(rgblight_effect_breathe_table);
diff --git a/quantum/rgblight/rgblight_modes.h b/quantum/rgblight/rgblight_modes.h
new file mode 100644
index 000000000..7abdb87bc
--- /dev/null
+++ b/quantum/rgblight/rgblight_modes.h
@@ -0,0 +1,75 @@
1#ifdef _RGBM_SINGLE_STATIC
2_RGBM_SINGLE_STATIC(STATIC_LIGHT)
3# ifdef RGBLIGHT_EFFECT_BREATHING
4_RGBM_MULTI_DYNAMIC(BREATHING)
5_RGBM_TMP_DYNAMIC(breathing_3, BREATHING)
6_RGBM_TMP_DYNAMIC(breathing_4, BREATHING)
7_RGBM_TMP_DYNAMIC(BREATHING_end, BREATHING)
8# endif
9# ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD
10_RGBM_MULTI_DYNAMIC(RAINBOW_MOOD)
11_RGBM_TMP_DYNAMIC(rainbow_mood_7, RAINBOW_MOOD)
12_RGBM_TMP_DYNAMIC(RAINBOW_MOOD_end, RAINBOW_MOOD)
13# endif
14# ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL
15_RGBM_MULTI_DYNAMIC(RAINBOW_SWIRL)
16_RGBM_TMP_DYNAMIC(rainbow_swirl_10, RAINBOW_SWIRL)
17_RGBM_TMP_DYNAMIC(rainbow_swirl_11, RAINBOW_SWIRL)
18_RGBM_TMP_DYNAMIC(rainbow_swirl_12, RAINBOW_SWIRL)
19_RGBM_TMP_DYNAMIC(rainbow_swirl_13, RAINBOW_SWIRL)
20_RGBM_TMP_DYNAMIC(RAINBOW_SWIRL_end, RAINBOW_SWIRL)
21# endif
22# ifdef RGBLIGHT_EFFECT_SNAKE
23_RGBM_MULTI_DYNAMIC(SNAKE)
24_RGBM_TMP_DYNAMIC(snake_16, SNAKE)
25_RGBM_TMP_DYNAMIC(snake_17, SNAKE)
26_RGBM_TMP_DYNAMIC(snake_18, SNAKE)
27_RGBM_TMP_DYNAMIC(snake_19, SNAKE)
28_RGBM_TMP_DYNAMIC(SNAKE_end, SNAKE)
29# endif
30# ifdef RGBLIGHT_EFFECT_KNIGHT
31_RGBM_MULTI_DYNAMIC(KNIGHT)
32_RGBM_TMP_DYNAMIC(knight_22, KNIGHT)
33_RGBM_TMP_DYNAMIC(KNIGHT_end, KNIGHT)
34# endif
35# ifdef RGBLIGHT_EFFECT_CHRISTMAS
36_RGBM_SINGLE_DYNAMIC(CHRISTMAS)
37# endif
38# ifdef RGBLIGHT_EFFECT_STATIC_GRADIENT
39_RGBM_MULTI_STATIC(STATIC_GRADIENT)
40_RGBM_TMP_STATIC(static_gradient_26, STATIC_GRADIENT)
41_RGBM_TMP_STATIC(static_gradient_27, STATIC_GRADIENT)
42_RGBM_TMP_STATIC(static_gradient_28, STATIC_GRADIENT)
43_RGBM_TMP_STATIC(static_gradient_29, STATIC_GRADIENT)
44_RGBM_TMP_STATIC(static_gradient_30, STATIC_GRADIENT)
45_RGBM_TMP_STATIC(static_gradient_31, STATIC_GRADIENT)
46_RGBM_TMP_STATIC(static_gradient_32, STATIC_GRADIENT)
47_RGBM_TMP_STATIC(static_gradient_33, STATIC_GRADIENT)
48_RGBM_TMP_STATIC(STATIC_GRADIENT_end, STATIC_GRADIENT)
49# endif
50# ifdef RGBLIGHT_EFFECT_RGB_TEST
51_RGBM_SINGLE_DYNAMIC(RGB_TEST)
52# endif
53# ifdef RGBLIGHT_EFFECT_ALTERNATING
54_RGBM_SINGLE_DYNAMIC(ALTERNATING)
55# endif
56# ifdef RGBLIGHT_EFFECT_TWINKLE
57_RGBM_MULTI_DYNAMIC(TWINKLE)
58_RGBM_TMP_DYNAMIC(twinkle_38, TWINKLE)
59_RGBM_TMP_DYNAMIC(twinkle_39, TWINKLE)
60_RGBM_TMP_DYNAMIC(twinkle_40, TWINKLE)
61_RGBM_TMP_DYNAMIC(twinkle_41, TWINKLE)
62_RGBM_TMP_DYNAMIC(TWINKLE_end, TWINKLE)
63# endif
64//// Add a new mode here.
65// #ifdef RGBLIGHT_EFFECT_<name>
66// _RGBM_<SINGLE|MULTI>_<STATIC|DYNAMIC>( <name> )
67// #endif
68#endif
69
70#undef _RGBM_SINGLE_STATIC
71#undef _RGBM_SINGLE_DYNAMIC
72#undef _RGBM_MULTI_STATIC
73#undef _RGBM_MULTI_DYNAMIC
74#undef _RGBM_TMP_STATIC
75#undef _RGBM_TMP_DYNAMIC
diff --git a/quantum/rgblight/rgblight_post_config.h b/quantum/rgblight/rgblight_post_config.h
new file mode 100644
index 000000000..3c14cb610
--- /dev/null
+++ b/quantum/rgblight/rgblight_post_config.h
@@ -0,0 +1,5 @@
1#if defined(RGBLED_SPLIT) && !defined(RGBLIGHT_SPLIT)
2// When RGBLED_SPLIT is defined,
3// it is considered that RGBLIGHT_SPLIT is defined implicitly.
4# define RGBLIGHT_SPLIT
5#endif