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