add RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS; to rgblight_update_dword()
[jackhill/qmk/firmware.git] / quantum / rgblight.c
CommitLineData
23839b8c 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 */
ad49db8c 16#include <math.h>
6d6d91c8 17#include <string.h>
ade22f8e
JH
18#ifdef __AVR__
19 #include <avr/eeprom.h>
20 #include <avr/interrupt.h>
21#endif
0f507f01
AK
22#ifdef STM32_EEPROM_ENABLE
23 #include "hal.h"
24 #include "eeprom.h"
25 #include "eeprom_stm32.h"
26#endif
ade22f8e 27#include "wait.h"
0a40654b
YL
28#include "progmem.h"
29#include "timer.h"
30#include "rgblight.h"
31#include "debug.h"
f113f954 32#include "led_tables.h"
c1c5922a
CL
33#ifdef VELOCIKEY_ENABLE
34 #include "velocikey.h"
35#endif
0a40654b 36
dfab177f
TI
37#ifdef RGBLIGHT_SPLIT
38 /* for split keyboard */
39 #define RGBLIGHT_SPLIT_SET_CHANGE_MODE rgblight_status.change_flags |= RGBLIGHT_STATUS_CHANGE_MODE
40 #define RGBLIGHT_SPLIT_SET_CHANGE_HSVS rgblight_status.change_flags |= RGBLIGHT_STATUS_CHANGE_HSVS
5312131d 41 #define RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS rgblight_status.change_flags |= (RGBLIGHT_STATUS_CHANGE_MODE|RGBLIGHT_STATUS_CHANGE_HSVS)
dfab177f
TI
42 #define RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE rgblight_status.change_flags |= RGBLIGHT_STATUS_CHANGE_TIMER
43 #define RGBLIGHT_SPLIT_ANIMATION_TICK rgblight_status.change_flags |= RGBLIGHT_STATUS_ANIMATION_TICK
44#else
45 #define RGBLIGHT_SPLIT_SET_CHANGE_MODE
46 #define RGBLIGHT_SPLIT_SET_CHANGE_HSVS
5312131d 47 #define RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS
dfab177f
TI
48 #define RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE
49 #define RGBLIGHT_SPLIT_ANIMATION_TICK
50#endif
51
6d6d91c8
TI
52#define _RGBM_SINGLE_STATIC(sym) RGBLIGHT_MODE_ ## sym,
53#define _RGBM_SINGLE_DYNAMIC(sym)
54#define _RGBM_MULTI_STATIC(sym) RGBLIGHT_MODE_ ## sym,
55#define _RGBM_MULTI_DYNAMIC(sym)
dfab177f
TI
56#define _RGBM_TMP_STATIC(sym, msym) RGBLIGHT_MODE_ ## sym,
57#define _RGBM_TMP_DYNAMIC(sym, msym)
6d6d91c8 58static uint8_t static_effect_table [] = {
dfab177f
TI
59#include "rgblight_modes.h"
60};
61
62#define _RGBM_SINGLE_STATIC(sym) RGBLIGHT_MODE_ ## sym,
63#define _RGBM_SINGLE_DYNAMIC(sym) RGBLIGHT_MODE_ ## sym,
64#define _RGBM_MULTI_STATIC(sym) RGBLIGHT_MODE_ ## sym,
65#define _RGBM_MULTI_DYNAMIC(sym) RGBLIGHT_MODE_ ## sym,
66#define _RGBM_TMP_STATIC(sym, msym) RGBLIGHT_MODE_ ## msym,
67#define _RGBM_TMP_DYNAMIC(sym, msym) RGBLIGHT_MODE_ ## msym,
68static uint8_t mode_base_table [] = {
69 0, // RGBLIGHT_MODE_zero
70#include "rgblight_modes.h"
6d6d91c8
TI
71};
72
73static inline int is_static_effect(uint8_t mode) {
74 return memchr(static_effect_table, mode, sizeof(static_effect_table)) != NULL;
75}
76
afacd423 77#define MIN(a,b) (((a)<(b))?(a):(b))
78#define MAX(a,b) (((a)>(b))?(a):(b))
79
f7fd7f67
TI
80#ifdef RGBLIGHT_LED_MAP
81const uint8_t led_map[] PROGMEM = RGBLIGHT_LED_MAP;
82#endif
83
6d6d91c8 84#ifdef RGBLIGHT_EFFECT_STATIC_GRADIENT
a7882b1f 85__attribute__ ((weak))
86const uint16_t RGBLED_GRADIENT_RANGES[] PROGMEM = {360, 240, 180, 120, 90};
6d6d91c8 87#endif
0a40654b
YL
88
89rgblight_config_t rgblight_config;
dfab177f 90rgblight_status_t rgblight_status = { .timer_enabled = false };
cc146e32 91bool is_rgblight_initialized = false;
0a40654b 92
dfab177f
TI
93#ifdef RGBLIGHT_USE_TIMER
94animation_status_t animation_status = {};
95#endif
96
5fcd744d 97#ifndef LED_ARRAY
e9f74875 98LED_TYPE led[RGBLED_NUM];
5fcd744d
X
99 #define LED_ARRAY led
100#endif
101
0a40654b 102
f077204f
D
103static uint8_t clipping_start_pos = 0;
104static uint8_t clipping_num_leds = RGBLED_NUM;
105
106void rgblight_set_clipping_range(uint8_t start_pos, uint8_t num_leds) {
107 clipping_start_pos = start_pos;
108 clipping_num_leds = num_leds;
109}
110
111
e9f74875 112void sethsv(uint16_t hue, uint8_t sat, uint8_t val, LED_TYPE *led1) {
ea2d2f5d 113 uint8_t r = 0, g = 0, b = 0, base, color;
0a40654b 114
2038a515 115 if (val > RGBLIGHT_LIMIT_VAL) {
6c24e28b 116 val=RGBLIGHT_LIMIT_VAL; // limit the val
2038a515 117 }
6c24e28b 118
3a860c4b
JO
119 if (sat == 0) { // Acromatic color (gray). Hue doesn't mind.
120 r = val;
121 g = val;
122 b = val;
123 } else {
124 base = ((255 - sat) * val) >> 8;
ea2d2f5d 125 color = (val - base) * (hue % 60) / 60;
3a860c4b
JO
126
127 switch (hue / 60) {
128 case 0:
129 r = val;
ea2d2f5d 130 g = base + color;
3a860c4b
JO
131 b = base;
132 break;
133 case 1:
ea2d2f5d 134 r = val - color;
3a860c4b
JO
135 g = val;
136 b = base;
137 break;
138 case 2:
139 r = base;
140 g = val;
ea2d2f5d 141 b = base + color;
3a860c4b
JO
142 break;
143 case 3:
144 r = base;
ea2d2f5d 145 g = val - color;
3a860c4b
JO
146 b = val;
147 break;
148 case 4:
ea2d2f5d 149 r = base + color;
3a860c4b
JO
150 g = base;
151 b = val;
152 break;
153 case 5:
154 r = val;
155 g = base;
ea2d2f5d 156 b = val - color;
3a860c4b
JO
157 break;
158 }
159 }
f113f954
FS
160 r = pgm_read_byte(&CIE1931_CURVE[r]);
161 g = pgm_read_byte(&CIE1931_CURVE[g]);
162 b = pgm_read_byte(&CIE1931_CURVE[b]);
ea2d2f5d
JO
163
164 setrgb(r, g, b, led1);
0a40654b
YL
165}
166
e9f74875 167void setrgb(uint8_t r, uint8_t g, uint8_t b, LED_TYPE *led1) {
0a40654b
YL
168 (*led1).r = r;
169 (*led1).g = g;
170 (*led1).b = b;
171}
172
cc146e32
DJ
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 }
179 else if (rgblight_config.mode > RGBLIGHT_MODES) {
180 rgblight_config.mode = RGBLIGHT_MODES;
181 }
182
183 if (rgblight_config.hue < 0) {
184 rgblight_config.hue = 0;
185 } else if (rgblight_config.hue > 360) {
186 rgblight_config.hue %= 360;
187 }
188
189 if (rgblight_config.sat < 0) {
190 rgblight_config.sat = 0;
191 } else if (rgblight_config.sat > 255) {
192 rgblight_config.sat = 255;
193 }
194
195 if (rgblight_config.val < 0) {
196 rgblight_config.val = 0;
197 } else if (rgblight_config.val > RGBLIGHT_LIMIT_VAL) {
198 rgblight_config.val = RGBLIGHT_LIMIT_VAL;
199 }
200
201}
0a40654b
YL
202
203uint32_t eeconfig_read_rgblight(void) {
0f507f01 204 #if defined(__AVR__) || defined(STM32_EEPROM_ENABLE) || defined(PROTOCOL_ARM_ATSAM) || defined(EEPROM_SIZE)
ade22f8e
JH
205 return eeprom_read_dword(EECONFIG_RGBLIGHT);
206 #else
207 return 0;
208 #endif
0a40654b 209}
cc146e32 210
620ac4b2 211void eeconfig_update_rgblight(uint32_t val) {
0f507f01 212 #if defined(__AVR__) || defined(STM32_EEPROM_ENABLE) || defined(PROTOCOL_ARM_ATSAM) || defined(EEPROM_SIZE)
cc146e32 213 rgblight_check_config();
ade22f8e
JH
214 eeprom_update_dword(EECONFIG_RGBLIGHT, val);
215 #endif
0a40654b 216}
cc146e32 217
620ac4b2 218void eeconfig_update_rgblight_default(void) {
0fab3bbd 219 //dprintf("eeconfig_update_rgblight_default\n");
3a860c4b 220 rgblight_config.enable = 1;
6d6d91c8 221 rgblight_config.mode = RGBLIGHT_MODE_STATIC_LIGHT;
e9f74875
JH
222 rgblight_config.hue = 0;
223 rgblight_config.sat = 255;
2038a515 224 rgblight_config.val = RGBLIGHT_LIMIT_VAL;
afacd423 225 rgblight_config.speed = 0;
5312131d 226 RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS;
3a860c4b 227 eeconfig_update_rgblight(rgblight_config.raw);
0a40654b 228}
cc146e32 229
0a40654b 230void eeconfig_debug_rgblight(void) {
3a860c4b
JO
231 dprintf("rgblight_config eprom\n");
232 dprintf("rgblight_config.enable = %d\n", rgblight_config.enable);
233 dprintf("rghlight_config.mode = %d\n", rgblight_config.mode);
234 dprintf("rgblight_config.hue = %d\n", rgblight_config.hue);
235 dprintf("rgblight_config.sat = %d\n", rgblight_config.sat);
236 dprintf("rgblight_config.val = %d\n", rgblight_config.val);
afacd423 237 dprintf("rgblight_config.speed = %d\n", rgblight_config.speed);
0a40654b
YL
238}
239
240void rgblight_init(void) {
cc146e32
DJ
241 /* if already initialized, don't do it again.
242 If you must do it again, extern this and set to false, first.
243 This is a dirty, dirty hack until proper hooks can be added for keyboard startup. */
244 if (is_rgblight_initialized) { return; }
245
0a40654b 246 debug_enable = 1; // Debug ON!
3a860c4b 247 dprintf("rgblight_init called.\n");
3a860c4b 248 dprintf("rgblight_init start!\n");
0a40654b 249 if (!eeconfig_is_enabled()) {
3a860c4b 250 dprintf("rgblight_init eeconfig is not enabled.\n");
0a40654b 251 eeconfig_init();
3a860c4b 252 eeconfig_update_rgblight_default();
0a40654b
YL
253 }
254 rgblight_config.raw = eeconfig_read_rgblight();
5312131d 255 RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS;
3a860c4b
JO
256 if (!rgblight_config.mode) {
257 dprintf("rgblight_init rgblight_config.mode = 0. Write default values to EEPROM.\n");
258 eeconfig_update_rgblight_default();
259 rgblight_config.raw = eeconfig_read_rgblight();
260 }
cc146e32
DJ
261 rgblight_check_config();
262
3a860c4b 263 eeconfig_debug_rgblight(); // display current eeprom values
0a40654b 264
6d6d91c8 265#ifdef RGBLIGHT_USE_TIMER
3a860c4b 266 rgblight_timer_init(); // setup the timer
6d6d91c8 267#endif
0a40654b
YL
268
269 if (rgblight_config.enable) {
751719e6 270 rgblight_mode_noeeprom(rgblight_config.mode);
0a40654b 271 }
cc146e32
DJ
272
273 is_rgblight_initialized = true;
274
0a40654b
YL
275}
276
9c4424ae
LT
277uint32_t rgblight_read_dword(void) {
278 return rgblight_config.raw;
279}
280
2e23689b 281void rgblight_update_dword(uint32_t dword) {
9f8c8c53 282 RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS;
2e23689b 283 rgblight_config.raw = dword;
2e23689b 284 if (rgblight_config.enable)
9c4424ae 285 rgblight_mode_noeeprom(rgblight_config.mode);
2e23689b 286 else {
6d6d91c8 287#ifdef RGBLIGHT_USE_TIMER
2e23689b 288 rgblight_timer_disable();
6d6d91c8 289#endif
2e23689b
JH
290 rgblight_set();
291 }
292}
293
0a40654b 294void rgblight_increase(void) {
3a860c4b 295 uint8_t mode = 0;
0a40654b
YL
296 if (rgblight_config.mode < RGBLIGHT_MODES) {
297 mode = rgblight_config.mode + 1;
298 }
3a860c4b 299 rgblight_mode(mode);
0a40654b 300}
0a40654b 301void rgblight_decrease(void) {
3a860c4b
JO
302 uint8_t mode = 0;
303 // Mode will never be < 1. If it ever is, eeprom needs to be initialized.
6d6d91c8 304 if (rgblight_config.mode > RGBLIGHT_MODE_STATIC_LIGHT) {
3a860c4b 305 mode = rgblight_config.mode - 1;
0a40654b 306 }
3a860c4b 307 rgblight_mode(mode);
0a40654b 308}
9e6ee477 309void rgblight_step_helper(bool write_to_eeprom) {
3a860c4b 310 uint8_t mode = 0;
0a40654b
YL
311 mode = rgblight_config.mode + 1;
312 if (mode > RGBLIGHT_MODES) {
313 mode = 1;
314 }
9e6ee477 315 rgblight_mode_eeprom_helper(mode, write_to_eeprom);
0a40654b 316}
9e6ee477
FS
317void rgblight_step_noeeprom(void) {
318 rgblight_step_helper(false);
319}
320void rgblight_step(void) {
321 rgblight_step_helper(true);
322}
323void rgblight_step_reverse_helper(bool write_to_eeprom) {
5a1b68d5 324 uint8_t mode = 0;
325 mode = rgblight_config.mode - 1;
326 if (mode < 1) {
327 mode = RGBLIGHT_MODES;
328 }
9e6ee477
FS
329 rgblight_mode_eeprom_helper(mode, write_to_eeprom);
330}
331void rgblight_step_reverse_noeeprom(void) {
332 rgblight_step_reverse_helper(false);
333}
334void rgblight_step_reverse(void) {
335 rgblight_step_reverse_helper(true);
5a1b68d5 336}
0a40654b 337
b7688590 338uint8_t rgblight_get_mode(void) {
4580d3a7 339 if (!rgblight_config.enable) {
340 return false;
341 }
342
343 return rgblight_config.mode;
344}
345
751719e6 346void rgblight_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) {
3a860c4b
JO
347 if (!rgblight_config.enable) {
348 return;
349 }
6d6d91c8
TI
350 if (mode < RGBLIGHT_MODE_STATIC_LIGHT) {
351 rgblight_config.mode = RGBLIGHT_MODE_STATIC_LIGHT;
3a860c4b
JO
352 } else if (mode > RGBLIGHT_MODES) {
353 rgblight_config.mode = RGBLIGHT_MODES;
354 } else {
355 rgblight_config.mode = mode;
356 }
dfab177f 357 RGBLIGHT_SPLIT_SET_CHANGE_MODE;
751719e6
DJ
358 if (write_to_eeprom) {
359 eeconfig_update_rgblight(rgblight_config.raw);
360 xprintf("rgblight mode [EEPROM]: %u\n", rgblight_config.mode);
361 } else {
362 xprintf("rgblight mode [NOEEPROM]: %u\n", rgblight_config.mode);
363 }
6d6d91c8
TI
364 if( is_static_effect(rgblight_config.mode) ) {
365#ifdef RGBLIGHT_USE_TIMER
3a860c4b 366 rgblight_timer_disable();
6d6d91c8
TI
367#endif
368 } else {
369#ifdef RGBLIGHT_USE_TIMER
3a860c4b 370 rgblight_timer_enable();
6d6d91c8 371#endif
3a860c4b 372 }
dfab177f
TI
373#ifdef RGBLIGHT_USE_TIMER
374 animation_status.restart = true;
375#endif
751719e6
DJ
376 rgblight_sethsv_noeeprom(rgblight_config.hue, rgblight_config.sat, rgblight_config.val);
377}
378
379void rgblight_mode(uint8_t mode) {
380 rgblight_mode_eeprom_helper(mode, true);
381}
382
383void rgblight_mode_noeeprom(uint8_t mode) {
384 rgblight_mode_eeprom_helper(mode, false);
0a40654b
YL
385}
386
751719e6 387
0a40654b 388void rgblight_toggle(void) {
751719e6 389 xprintf("rgblight toggle [EEPROM]: rgblight_config.enable = %u\n", !rgblight_config.enable);
3a860c4b 390 if (rgblight_config.enable) {
16546ee0
CG
391 rgblight_disable();
392 }
393 else {
394 rgblight_enable();
3a860c4b 395 }
0a40654b
YL
396}
397
751719e6
DJ
398void rgblight_toggle_noeeprom(void) {
399 xprintf("rgblight toggle [NOEEPROM]: rgblight_config.enable = %u\n", !rgblight_config.enable);
400 if (rgblight_config.enable) {
401 rgblight_disable_noeeprom();
402 }
403 else {
404 rgblight_enable_noeeprom();
405 }
406}
407
285c5a91
EZ
408void rgblight_enable(void) {
409 rgblight_config.enable = 1;
751719e6
DJ
410 // No need to update EEPROM here. rgblight_mode() will do that, actually
411 //eeconfig_update_rgblight(rgblight_config.raw);
412 xprintf("rgblight enable [EEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable);
285c5a91
EZ
413 rgblight_mode(rgblight_config.mode);
414}
415
751719e6
DJ
416void rgblight_enable_noeeprom(void) {
417 rgblight_config.enable = 1;
418 xprintf("rgblight enable [NOEEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable);
419 rgblight_mode_noeeprom(rgblight_config.mode);
420}
421
16546ee0
CG
422void rgblight_disable(void) {
423 rgblight_config.enable = 0;
424 eeconfig_update_rgblight(rgblight_config.raw);
751719e6 425 xprintf("rgblight disable [EEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable);
6d6d91c8
TI
426#ifdef RGBLIGHT_USE_TIMER
427 rgblight_timer_disable();
428#endif
dfab177f 429 RGBLIGHT_SPLIT_SET_CHANGE_MODE;
ade22f8e 430 wait_ms(50);
16546ee0
CG
431 rgblight_set();
432}
433
751719e6
DJ
434void rgblight_disable_noeeprom(void) {
435 rgblight_config.enable = 0;
436 xprintf("rgblight disable [noEEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable);
6d6d91c8 437#ifdef RGBLIGHT_USE_TIMER
751719e6 438 rgblight_timer_disable();
6d6d91c8 439#endif
dfab177f 440 RGBLIGHT_SPLIT_SET_CHANGE_MODE;
0f507f01 441 wait_ms(50);
751719e6
DJ
442 rgblight_set();
443}
444
445
afacd423 446// Deals with the messy details of incrementing an integer
da1afe15 447static uint8_t increment( uint8_t value, uint8_t step, uint8_t min, uint8_t max ) {
afacd423 448 int16_t new_value = value;
449 new_value += step;
450 return MIN( MAX( new_value, min ), max );
451}
452
da1afe15 453static uint8_t decrement( uint8_t value, uint8_t step, uint8_t min, uint8_t max ) {
afacd423 454 int16_t new_value = value;
455 new_value -= step;
456 return MIN( MAX( new_value, min ), max );
457}
0a40654b 458
9e6ee477 459void rgblight_increase_hue_helper(bool write_to_eeprom) {
3a860c4b 460 uint16_t hue;
0a40654b 461 hue = (rgblight_config.hue+RGBLIGHT_HUE_STEP) % 360;
9e6ee477 462 rgblight_sethsv_eeprom_helper(hue, rgblight_config.sat, rgblight_config.val, write_to_eeprom);
0a40654b 463}
9e6ee477
FS
464void rgblight_increase_hue_noeeprom(void) {
465 rgblight_increase_hue_helper(false);
466}
467void rgblight_increase_hue(void) {
468 rgblight_increase_hue_helper(true);
469}
470void rgblight_decrease_hue_helper(bool write_to_eeprom) {
3a860c4b
JO
471 uint16_t hue;
472 if (rgblight_config.hue-RGBLIGHT_HUE_STEP < 0) {
473 hue = (rgblight_config.hue + 360 - RGBLIGHT_HUE_STEP) % 360;
474 } else {
475 hue = (rgblight_config.hue - RGBLIGHT_HUE_STEP) % 360;
476 }
9e6ee477 477 rgblight_sethsv_eeprom_helper(hue, rgblight_config.sat, rgblight_config.val, write_to_eeprom);
0a40654b 478}
9e6ee477
FS
479void rgblight_decrease_hue_noeeprom(void) {
480 rgblight_decrease_hue_helper(false);
481}
482void rgblight_decrease_hue(void) {
483 rgblight_decrease_hue_helper(true);
484}
485void rgblight_increase_sat_helper(bool write_to_eeprom) {
3a860c4b 486 uint8_t sat;
0a40654b
YL
487 if (rgblight_config.sat + RGBLIGHT_SAT_STEP > 255) {
488 sat = 255;
489 } else {
3a860c4b 490 sat = rgblight_config.sat + RGBLIGHT_SAT_STEP;
0a40654b 491 }
9e6ee477 492 rgblight_sethsv_eeprom_helper(rgblight_config.hue, sat, rgblight_config.val, write_to_eeprom);
0a40654b 493}
9e6ee477
FS
494void rgblight_increase_sat_noeeprom(void) {
495 rgblight_increase_sat_helper(false);
496}
497void rgblight_increase_sat(void) {
498 rgblight_increase_sat_helper(true);
499}
500void rgblight_decrease_sat_helper(bool write_to_eeprom) {
3a860c4b 501 uint8_t sat;
0a40654b
YL
502 if (rgblight_config.sat - RGBLIGHT_SAT_STEP < 0) {
503 sat = 0;
504 } else {
3a860c4b 505 sat = rgblight_config.sat - RGBLIGHT_SAT_STEP;
0a40654b 506 }
9e6ee477 507 rgblight_sethsv_eeprom_helper(rgblight_config.hue, sat, rgblight_config.val, write_to_eeprom);
0a40654b 508}
9e6ee477
FS
509void rgblight_decrease_sat_noeeprom(void) {
510 rgblight_decrease_sat_helper(false);
511}
512void rgblight_decrease_sat(void) {
513 rgblight_decrease_sat_helper(true);
514}
515void rgblight_increase_val_helper(bool write_to_eeprom) {
3a860c4b 516 uint8_t val;
2038a515 517 if (rgblight_config.val + RGBLIGHT_VAL_STEP > RGBLIGHT_LIMIT_VAL) {
518 val = RGBLIGHT_LIMIT_VAL;
0a40654b 519 } else {
3a860c4b 520 val = rgblight_config.val + RGBLIGHT_VAL_STEP;
0a40654b 521 }
9e6ee477 522 rgblight_sethsv_eeprom_helper(rgblight_config.hue, rgblight_config.sat, val, write_to_eeprom);
0a40654b 523}
9e6ee477
FS
524void rgblight_increase_val_noeeprom(void) {
525 rgblight_increase_val_helper(false);
526}
527void rgblight_increase_val(void) {
528 rgblight_increase_val_helper(true);
529}
530void rgblight_decrease_val_helper(bool write_to_eeprom) {
3a860c4b 531 uint8_t val;
0a40654b
YL
532 if (rgblight_config.val - RGBLIGHT_VAL_STEP < 0) {
533 val = 0;
534 } else {
3a860c4b 535 val = rgblight_config.val - RGBLIGHT_VAL_STEP;
0a40654b 536 }
9e6ee477
FS
537 rgblight_sethsv_eeprom_helper(rgblight_config.hue, rgblight_config.sat, val, write_to_eeprom);
538}
539void rgblight_decrease_val_noeeprom(void) {
540 rgblight_decrease_val_helper(false);
541}
542void rgblight_decrease_val(void) {
543 rgblight_decrease_val_helper(true);
0a40654b 544}
afacd423 545void rgblight_increase_speed(void) {
546 rgblight_config.speed = increment( rgblight_config.speed, 1, 0, 3 );
dfab177f 547 //RGBLIGHT_SPLIT_SET_CHANGE_HSVS; // NEED?
afacd423 548 eeconfig_update_rgblight(rgblight_config.raw);//EECONFIG needs to be increased to support this
549}
550
551void rgblight_decrease_speed(void) {
552 rgblight_config.speed = decrement( rgblight_config.speed, 1, 0, 3 );
dfab177f 553 //RGBLIGHT_SPLIT_SET_CHANGE_HSVS; // NEED??
afacd423 554 eeconfig_update_rgblight(rgblight_config.raw);//EECONFIG needs to be increased to support this
555}
0a40654b 556
751719e6 557void rgblight_sethsv_noeeprom_old(uint16_t hue, uint8_t sat, uint8_t val) {
0a40654b 558 if (rgblight_config.enable) {
e9f74875 559 LED_TYPE tmp_led;
0a40654b 560 sethsv(hue, sat, val, &tmp_led);
0a40654b
YL
561 // dprintf("rgblight set hue [MEMORY]: %u,%u,%u\n", inmem_config.hue, inmem_config.sat, inmem_config.val);
562 rgblight_setrgb(tmp_led.r, tmp_led.g, tmp_led.b);
563 }
564}
751719e6
DJ
565
566void rgblight_sethsv_eeprom_helper(uint16_t hue, uint8_t sat, uint8_t val, bool write_to_eeprom) {
0a40654b 567 if (rgblight_config.enable) {
dfab177f 568 rgblight_status.base_mode = mode_base_table[rgblight_config.mode];
6d6d91c8 569 if (rgblight_config.mode == RGBLIGHT_MODE_STATIC_LIGHT) {
3a860c4b 570 // same static color
751719e6
DJ
571 LED_TYPE tmp_led;
572 sethsv(hue, sat, val, &tmp_led);
573 rgblight_setrgb(tmp_led.r, tmp_led.g, tmp_led.b);
3a860c4b
JO
574 } else {
575 // all LEDs in same color
6d6d91c8
TI
576 if ( 1 == 0 ) { //dummy
577 }
578#ifdef RGBLIGHT_EFFECT_BREATHING
dfab177f 579 else if (rgblight_status.base_mode == RGBLIGHT_MODE_BREATHING ) {
3a860c4b
JO
580 // breathing mode, ignore the change of val, use in memory value instead
581 val = rgblight_config.val;
6d6d91c8
TI
582 }
583#endif
584#ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD
dfab177f 585 else if (rgblight_status.base_mode == RGBLIGHT_MODE_RAINBOW_MOOD) {
6d6d91c8
TI
586 // rainbow mood, ignore the change of hue
587 hue = rgblight_config.hue;
588 }
589#endif
590#ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL
dfab177f 591 else if (rgblight_status.base_mode == RGBLIGHT_MODE_RAINBOW_SWIRL) {
6d6d91c8 592 // rainbow swirl, ignore the change of hue
3a860c4b 593 hue = rgblight_config.hue;
6d6d91c8
TI
594 }
595#endif
596#ifdef RGBLIGHT_EFFECT_STATIC_GRADIENT
dfab177f 597 else if (rgblight_status.base_mode == RGBLIGHT_MODE_STATIC_GRADIENT) {
a7882b1f 598 // static gradient
599 uint16_t _hue;
dfab177f
TI
600 uint8_t delta = rgblight_config.mode - rgblight_status.base_mode;
601 int8_t direction = (delta % 2) ? -1 : 1;
602 uint16_t range = pgm_read_word(&RGBLED_GRADIENT_RANGES[delta / 2]);
a7882b1f 603 for (uint8_t i = 0; i < RGBLED_NUM; i++) {
604 _hue = (range / RGBLED_NUM * i * direction + hue + 360) % 360;
605 dprintf("rgblight rainbow set hsv: %u,%u,%d,%u\n", i, _hue, direction, range);
606 sethsv(_hue, sat, val, (LED_TYPE *)&led[i]);
607 }
608 rgblight_set();
3a860c4b 609 }
6d6d91c8 610#endif
3a860c4b 611 }
dfab177f
TI
612#ifdef RGBLIGHT_SPLIT
613 if( rgblight_config.hue != hue ||
614 rgblight_config.sat != sat ||
615 rgblight_config.val != val ) {
616 RGBLIGHT_SPLIT_SET_CHANGE_HSVS;
617 }
618#endif
3a860c4b
JO
619 rgblight_config.hue = hue;
620 rgblight_config.sat = sat;
621 rgblight_config.val = val;
751719e6
DJ
622 if (write_to_eeprom) {
623 eeconfig_update_rgblight(rgblight_config.raw);
624 xprintf("rgblight set hsv [EEPROM]: %u,%u,%u\n", rgblight_config.hue, rgblight_config.sat, rgblight_config.val);
625 } else {
626 xprintf("rgblight set hsv [NOEEPROM]: %u,%u,%u\n", rgblight_config.hue, rgblight_config.sat, rgblight_config.val);
627 }
3a860c4b
JO
628 }
629}
630
751719e6
DJ
631void rgblight_sethsv(uint16_t hue, uint8_t sat, uint8_t val) {
632 rgblight_sethsv_eeprom_helper(hue, sat, val, true);
633}
634
635void rgblight_sethsv_noeeprom(uint16_t hue, uint8_t sat, uint8_t val) {
636 rgblight_sethsv_eeprom_helper(hue, sat, val, false);
637}
638
12e66330 639uint16_t rgblight_get_hue(void) {
640 return rgblight_config.hue;
641}
642
643uint8_t rgblight_get_sat(void) {
644 return rgblight_config.sat;
645}
646
647uint8_t rgblight_get_val(void) {
648 return rgblight_config.val;
649}
650
3a860c4b 651void rgblight_setrgb(uint8_t r, uint8_t g, uint8_t b) {
16546ee0
CG
652 if (!rgblight_config.enable) { return; }
653
3a860c4b 654 for (uint8_t i = 0; i < RGBLED_NUM; i++) {
0a40654b
YL
655 led[i].r = r;
656 led[i].g = g;
657 led[i].b = b;
658 }
659 rgblight_set();
0a40654b
YL
660}
661
16546ee0
CG
662void rgblight_setrgb_at(uint8_t r, uint8_t g, uint8_t b, uint8_t index) {
663 if (!rgblight_config.enable || index >= RGBLED_NUM) { return; }
664
665 led[index].r = r;
666 led[index].g = g;
667 led[index].b = b;
668 rgblight_set();
669}
670
671void rgblight_sethsv_at(uint16_t hue, uint8_t sat, uint8_t val, uint8_t index) {
672 if (!rgblight_config.enable) { return; }
673
674 LED_TYPE tmp_led;
675 sethsv(hue, sat, val, &tmp_led);
676 rgblight_setrgb_at(tmp_led.r, tmp_led.g, tmp_led.b, index);
677}
678
c1c5922a
CL
679#if defined(RGBLIGHT_EFFECT_BREATHING) || defined(RGBLIGHT_EFFECT_RAINBOW_MOOD) || defined(RGBLIGHT_EFFECT_RAINBOW_SWIRL) \
680 || defined(RGBLIGHT_EFFECT_SNAKE) || defined(RGBLIGHT_EFFECT_KNIGHT)
681
682static uint8_t get_interval_time(const uint8_t* default_interval_address, uint8_t velocikey_min, uint8_t velocikey_max) {
f077204f 683 return
c1c5922a
CL
684#ifdef VELOCIKEY_ENABLE
685 velocikey_enabled() ? velocikey_match_speed(velocikey_min, velocikey_max) :
686#endif
687 pgm_read_byte(default_interval_address);
688}
689
690#endif
691
642f6cf1
E
692void rgblight_setrgb_range(uint8_t r, uint8_t g, uint8_t b, uint8_t start, uint8_t end) {
693 if (!rgblight_config.enable || start < 0 || start >= end || end > RGBLED_NUM) { return; }
694
695 for (uint8_t i = start; i < end; i++) {
696 led[i].r = r;
697 led[i].g = g;
698 led[i].b = b;
699 }
700 rgblight_set();
701 wait_ms(1);
702}
703
704void rgblight_sethsv_range(uint16_t hue, uint8_t sat, uint8_t val, uint8_t start, uint8_t end) {
705 if (!rgblight_config.enable) { return; }
706
707 LED_TYPE tmp_led;
708 sethsv(hue, sat, val, &tmp_led);
709 rgblight_setrgb_range(tmp_led.r, tmp_led.g, tmp_led.b, start, end);
710}
711
712void rgblight_setrgb_master(uint8_t r, uint8_t g, uint8_t b) {
713 rgblight_setrgb_range(r, g, b, 0 , (uint8_t) RGBLED_NUM/2);
714}
715
716void rgblight_setrgb_slave(uint8_t r, uint8_t g, uint8_t b) {
717 rgblight_setrgb_range(r, g, b, (uint8_t) RGBLED_NUM/2, (uint8_t) RGBLED_NUM);
718}
719
720void rgblight_sethsv_master(uint16_t hue, uint8_t sat, uint8_t val) {
721 rgblight_sethsv_range(hue, sat, val, 0, (uint8_t) RGBLED_NUM/2);
722}
723
724void rgblight_sethsv_slave(uint16_t hue, uint8_t sat, uint8_t val) {
725 rgblight_sethsv_range(hue, sat, val, (uint8_t) RGBLED_NUM/2, (uint8_t) RGBLED_NUM);
726}
727
d4cd5dda 728#ifndef RGBLIGHT_CUSTOM_DRIVER
0a40654b 729void rgblight_set(void) {
f077204f
D
730 LED_TYPE *start_led = led + clipping_start_pos;
731 uint16_t num_leds = clipping_num_leds;
3a860c4b 732 if (rgblight_config.enable) {
f7fd7f67
TI
733 #ifdef RGBLIGHT_LED_MAP
734 LED_TYPE led0[RGBLED_NUM];
735 for(uint8_t i = 0; i < RGBLED_NUM; i++) {
736 led0[i] = led[pgm_read_byte(&led_map[i])];
737 }
f077204f 738 start_led = led0 + clipping_start_pos;
f7fd7f67 739 #endif
b8679bbe 740 #ifdef RGBW
f077204f 741 ws2812_setleds_rgbw(start_led, num_leds);
b8679bbe 742 #else
f077204f 743 ws2812_setleds(start_led, num_leds);
b8679bbe 744 #endif
3a860c4b
JO
745 } else {
746 for (uint8_t i = 0; i < RGBLED_NUM; i++) {
747 led[i].r = 0;
748 led[i].g = 0;
749 led[i].b = 0;
750 }
b8679bbe 751 #ifdef RGBW
f077204f 752 ws2812_setleds_rgbw(start_led, num_leds);
b8679bbe 753 #else
f077204f 754 ws2812_setleds(start_led, num_leds);
b8679bbe 755 #endif
3a860c4b 756 }
0a40654b 757}
d4cd5dda 758#endif
0a40654b 759
dfab177f
TI
760#ifdef RGBLIGHT_SPLIT
761/* for split keyboard master side */
762uint8_t rgblight_get_change_flags(void) {
763 return rgblight_status.change_flags;
764}
765
766void rgblight_clear_change_flags(void) {
767 rgblight_status.change_flags = 0;
768}
769
770void rgblight_get_syncinfo(rgblight_syncinfo_t *syncinfo) {
771 syncinfo->config = rgblight_config;
772 syncinfo->status = rgblight_status;
773}
774
775/* for split keyboard slave side */
776void rgblight_update_sync(rgblight_syncinfo_t *syncinfo, bool write_to_eeprom) {
777 if (syncinfo->status.change_flags & RGBLIGHT_STATUS_CHANGE_MODE) {
778 if (syncinfo->config.enable) {
779 rgblight_config.enable = 1; // == rgblight_enable_noeeprom();
780 rgblight_mode_eeprom_helper(syncinfo->config.mode, write_to_eeprom);
781 } else {
782 rgblight_disable_noeeprom();
783 }
784 }
785 if (syncinfo->status.change_flags & RGBLIGHT_STATUS_CHANGE_HSVS) {
786 rgblight_sethsv_eeprom_helper(syncinfo->config.hue, syncinfo->config.sat, syncinfo->config.val, write_to_eeprom);
787 // rgblight_config.speed = config->speed; // NEED???
788 }
789 #ifdef RGBLIGHT_USE_TIMER
790 if (syncinfo->status.change_flags & RGBLIGHT_STATUS_CHANGE_TIMER) {
791 if (syncinfo->status.timer_enabled) {
792 rgblight_timer_enable();
793 } else {
794 rgblight_timer_disable();
795 }
796 }
797 #ifndef RGBLIGHT_SPLIT_NO_ANIMATION_SYNC
798 if (syncinfo->status.change_flags & RGBLIGHT_STATUS_ANIMATION_TICK) {
799 animation_status.restart = true;
800 }
801 #endif /* RGBLIGHT_SPLIT_NO_ANIMATION_SYNC */
802 #endif /* RGBLIGHT_USE_TIMER */
803}
804#endif /* RGBLIGHT_SPLIT */
805
6d6d91c8 806#ifdef RGBLIGHT_USE_TIMER
57e08eb8 807
dfab177f
TI
808typedef void (*effect_func_t)(animation_status_t *anim);
809
810// Animation timer -- use system timer (AVR Timer0)
0a40654b 811void rgblight_timer_init(void) {
dfab177f 812 // OLD!!!! Animation timer -- AVR Timer3
e9f74875
JH
813 // static uint8_t rgblight_timer_is_init = 0;
814 // if (rgblight_timer_is_init) {
815 // return;
816 // }
817 // rgblight_timer_is_init = 1;
818 // /* Timer 3 setup */
819 // TCCR3B = _BV(WGM32) // CTC mode OCR3A as TOP
820 // | _BV(CS30); // Clock selelct: clk/1
821 // /* Set TOP value */
822 // uint8_t sreg = SREG;
823 // cli();
824 // OCR3AH = (RGBLED_TIMER_TOP >> 8) & 0xff;
825 // OCR3AL = RGBLED_TIMER_TOP & 0xff;
826 // SREG = sreg;
827
dfab177f
TI
828 rgblight_status.timer_enabled = false;
829 RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE;
0a40654b
YL
830}
831void rgblight_timer_enable(void) {
dfab177f
TI
832 if( !is_static_effect(rgblight_config.mode) ) {
833 rgblight_status.timer_enabled = true;
834 }
835 animation_status.last_timer = timer_read();
836 RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE;
837 dprintf("rgblight timer enabled.\n");
0a40654b
YL
838}
839void rgblight_timer_disable(void) {
dfab177f
TI
840 rgblight_status.timer_enabled = false;
841 RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE;
842 dprintf("rgblight timer disable.\n");
0a40654b
YL
843}
844void rgblight_timer_toggle(void) {
dfab177f
TI
845 dprintf("rgblight timer toggle.\n");
846 if(rgblight_status.timer_enabled) {
847 rgblight_timer_disable();
848 } else {
849 rgblight_timer_enable();
850 }
0a40654b
YL
851}
852
4094544d
EZ
853void rgblight_show_solid_color(uint8_t r, uint8_t g, uint8_t b) {
854 rgblight_enable();
6d6d91c8 855 rgblight_mode(RGBLIGHT_MODE_STATIC_LIGHT);
4094544d
EZ
856 rgblight_setrgb(r, g, b);
857}
858
dfab177f
TI
859static void rgblight_effect_dummy(animation_status_t *anim) {
860 // do nothing
861 /********
862 dprintf("rgblight_task() what happened?\n");
863 dprintf("is_static_effect %d\n", is_static_effect(rgblight_config.mode));
864 dprintf("mode = %d, base_mode = %d, timer_enabled %d, ",
865 rgblight_config.mode, rgblight_status.base_mode,
866 rgblight_status.timer_enabled);
867 dprintf("last_timer = %d\n",anim->last_timer);
868 **/
869}
870
e9f74875 871void rgblight_task(void) {
dfab177f
TI
872 if (rgblight_status.timer_enabled) {
873 effect_func_t effect_func = rgblight_effect_dummy;
874 uint16_t interval_time = 2000; // dummy interval
875 uint8_t delta = rgblight_config.mode - rgblight_status.base_mode;
876 animation_status.delta = delta;
c1c5922a 877
6d6d91c8
TI
878 // static light mode, do nothing here
879 if ( 1 == 0 ) { //dummy
880 }
881#ifdef RGBLIGHT_EFFECT_BREATHING
dfab177f 882 else if (rgblight_status.base_mode == RGBLIGHT_MODE_BREATHING) {
6d6d91c8 883 // breathing mode
dfab177f
TI
884 interval_time = get_interval_time(&RGBLED_BREATHING_INTERVALS[delta], 1, 100);
885 effect_func = rgblight_effect_breathing;
6d6d91c8
TI
886 }
887#endif
888#ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD
dfab177f 889 else if (rgblight_status.base_mode == RGBLIGHT_MODE_RAINBOW_MOOD) {
6d6d91c8 890 // rainbow mood mode
dfab177f
TI
891 interval_time = get_interval_time(&RGBLED_RAINBOW_MOOD_INTERVALS[delta], 5, 100);
892 effect_func = rgblight_effect_rainbow_mood;
6d6d91c8
TI
893 }
894#endif
895#ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL
dfab177f 896 else if (rgblight_status.base_mode == RGBLIGHT_MODE_RAINBOW_SWIRL) {
6d6d91c8 897 // rainbow swirl mode
dfab177f
TI
898 interval_time = get_interval_time(&RGBLED_RAINBOW_SWIRL_INTERVALS[delta / 2], 1, 100);
899 effect_func = rgblight_effect_rainbow_swirl;
6d6d91c8
TI
900 }
901#endif
902#ifdef RGBLIGHT_EFFECT_SNAKE
dfab177f 903 else if (rgblight_status.base_mode == RGBLIGHT_MODE_SNAKE) {
6d6d91c8 904 // snake mode
dfab177f
TI
905 interval_time = get_interval_time(&RGBLED_SNAKE_INTERVALS[delta / 2], 1, 200);
906 effect_func = rgblight_effect_snake;
6d6d91c8
TI
907 }
908#endif
909#ifdef RGBLIGHT_EFFECT_KNIGHT
dfab177f 910 else if (rgblight_status.base_mode == RGBLIGHT_MODE_KNIGHT) {
6d6d91c8 911 // knight mode
dfab177f
TI
912 interval_time = get_interval_time(&RGBLED_KNIGHT_INTERVALS[delta], 5, 100);
913 effect_func = rgblight_effect_knight;
6d6d91c8
TI
914 }
915#endif
916#ifdef RGBLIGHT_EFFECT_CHRISTMAS
dfab177f 917 else if (rgblight_status.base_mode == RGBLIGHT_MODE_CHRISTMAS) {
6d6d91c8 918 // christmas mode
dfab177f
TI
919 interval_time = RGBLIGHT_EFFECT_CHRISTMAS_INTERVAL;
920 effect_func = (effect_func_t)rgblight_effect_christmas;
6d6d91c8
TI
921 }
922#endif
923#ifdef RGBLIGHT_EFFECT_RGB_TEST
dfab177f 924 else if (rgblight_status.base_mode == RGBLIGHT_MODE_RGB_TEST) {
6d6d91c8 925 // RGB test mode
dfab177f
TI
926 interval_time = pgm_read_word(&RGBLED_RGBTEST_INTERVALS[0]);
927 effect_func = (effect_func_t)rgblight_effect_rgbtest;
6d6d91c8
TI
928 }
929#endif
930#ifdef RGBLIGHT_EFFECT_ALTERNATING
dfab177f
TI
931 else if (rgblight_status.base_mode == RGBLIGHT_MODE_ALTERNATING){
932 interval_time = 500;
933 effect_func = (effect_func_t)rgblight_effect_alternating;
934 }
935#endif
936 if (animation_status.restart) {
937 animation_status.restart = false;
938 animation_status.last_timer = timer_read() - interval_time - 1;
939 animation_status.pos16 = 0; // restart signal to local each effect
e9f74875 940 }
dfab177f
TI
941 if (timer_elapsed(animation_status.last_timer) >= interval_time) {
942#if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
943 static uint16_t report_last_timer = 0;
944 static bool tick_flag = false;
945 uint16_t oldpos16;
946 if (tick_flag) {
947 tick_flag = false;
948 //dprintf("rgblight animation tick\n");
949 if (timer_elapsed(report_last_timer) >= 30000) {
950 report_last_timer = timer_read();
951 dprintf("rgblight animation tick report to slave\n");
952 RGBLIGHT_SPLIT_ANIMATION_TICK;
953 }
954 }
955 oldpos16 = animation_status.pos16;
956 //dprintf("call effect function\n");
957#endif
958 animation_status.last_timer += interval_time;
959 effect_func(&animation_status);
960#if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
961 //dprintf("pos16, oldpos16 = %d %d\n",
962 // animation_status.pos16,oldpos16);
963 if (animation_status.pos16 == 0 && oldpos16 != 0) {
964 //dprintf("flag on\n");
965 tick_flag = true;
966 }
6d6d91c8 967#endif
dfab177f 968 }
3a860c4b
JO
969 }
970}
971
6d6d91c8
TI
972#endif /* RGBLIGHT_USE_TIMER */
973
3a860c4b 974// Effects
6d6d91c8
TI
975#ifdef RGBLIGHT_EFFECT_BREATHING
976__attribute__ ((weak))
977const uint8_t RGBLED_BREATHING_INTERVALS[] PROGMEM = {30, 20, 10, 5};
978
dfab177f 979void rgblight_effect_breathing(animation_status_t *anim) {
ad49db8c 980 float val;
0a40654b 981
ad49db8c 982 // http://sean.voisen.org/blog/2011/10/breathing-led-with-arduino/
dfab177f 983 val = (exp(sin((anim->pos/255.0)*M_PI)) - RGBLIGHT_EFFECT_BREATHE_CENTER/M_E)*(RGBLIGHT_EFFECT_BREATHE_MAX/(M_E-1/M_E));
751719e6 984 rgblight_sethsv_noeeprom_old(rgblight_config.hue, rgblight_config.sat, val);
dfab177f 985 anim->pos = (anim->pos + 1) % 256;
0a40654b 986}
6d6d91c8
TI
987#endif
988
989#ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD
990__attribute__ ((weak))
991const uint8_t RGBLED_RAINBOW_MOOD_INTERVALS[] PROGMEM = {120, 60, 30};
992
dfab177f
TI
993void rgblight_effect_rainbow_mood(animation_status_t *anim) {
994 rgblight_sethsv_noeeprom_old(anim->current_hue, rgblight_config.sat, rgblight_config.val);
995 anim->current_hue = (anim->current_hue + 1) % 360;
0a40654b 996}
6d6d91c8
TI
997#endif
998
999#ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL
94f58322
FT
1000#ifndef RGBLIGHT_RAINBOW_SWIRL_RANGE
1001 #define RGBLIGHT_RAINBOW_SWIRL_RANGE 360
1002#endif
1003
6d6d91c8
TI
1004__attribute__ ((weak))
1005const uint8_t RGBLED_RAINBOW_SWIRL_INTERVALS[] PROGMEM = {100, 50, 20};
1006
dfab177f 1007void rgblight_effect_rainbow_swirl(animation_status_t *anim) {
3a860c4b
JO
1008 uint16_t hue;
1009 uint8_t i;
c1c5922a 1010
3a860c4b 1011 for (i = 0; i < RGBLED_NUM; i++) {
dfab177f 1012 hue = (RGBLIGHT_RAINBOW_SWIRL_RANGE / RGBLED_NUM * i + anim->current_hue) % 360;
e9f74875 1013 sethsv(hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i]);
3a860c4b
JO
1014 }
1015 rgblight_set();
1016
dfab177f
TI
1017 if (anim->delta % 2) {
1018 anim->current_hue = (anim->current_hue + 1) % 360;
3a860c4b 1019 } else {
dfab177f
TI
1020 if (anim->current_hue - 1 < 0) {
1021 anim->current_hue = 359;
3a860c4b 1022 } else {
dfab177f 1023 anim->current_hue = anim->current_hue - 1;
3a860c4b
JO
1024 }
1025 }
0a40654b 1026}
6d6d91c8
TI
1027#endif
1028
1029#ifdef RGBLIGHT_EFFECT_SNAKE
1030__attribute__ ((weak))
1031const uint8_t RGBLED_SNAKE_INTERVALS[] PROGMEM = {100, 50, 20};
1032
dfab177f 1033void rgblight_effect_snake(animation_status_t *anim) {
3a860c4b 1034 static uint8_t pos = 0;
3a860c4b
JO
1035 uint8_t i, j;
1036 int8_t k;
899c88cd 1037 int8_t increment = 1;
dfab177f
TI
1038
1039 if (anim->delta % 2) {
899c88cd 1040 increment = -1;
3a860c4b 1041 }
c1c5922a 1042
dfab177f
TI
1043#if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
1044 if (anim->pos == 0) { // restart signal
1045 if (increment == 1) {
1046 pos = RGBLED_NUM - 1;
1047 } else {
1048 pos = 0;
1049 }
1050 anim->pos = 1;
3a860c4b 1051 }
dfab177f
TI
1052#endif
1053
3a860c4b
JO
1054 for (i = 0; i < RGBLED_NUM; i++) {
1055 led[i].r = 0;
1056 led[i].g = 0;
1057 led[i].b = 0;
1058 for (j = 0; j < RGBLIGHT_EFFECT_SNAKE_LENGTH; j++) {
899c88cd 1059 k = pos + j * increment;
3a860c4b
JO
1060 if (k < 0) {
1061 k = k + RGBLED_NUM;
1062 }
1063 if (i == k) {
dfab177f
TI
1064 sethsv(rgblight_config.hue, rgblight_config.sat,
1065 (uint8_t)(rgblight_config.val*(RGBLIGHT_EFFECT_SNAKE_LENGTH-j)/RGBLIGHT_EFFECT_SNAKE_LENGTH),
1066 (LED_TYPE *)&led[i]);
3a860c4b
JO
1067 }
1068 }
1069 }
1070 rgblight_set();
899c88cd 1071 if (increment == 1) {
3a860c4b
JO
1072 if (pos - 1 < 0) {
1073 pos = RGBLED_NUM - 1;
dfab177f
TI
1074#if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
1075 anim->pos = 0;
1076#endif
3a860c4b
JO
1077 } else {
1078 pos -= 1;
dfab177f
TI
1079#if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
1080 anim->pos = 1;
1081#endif
3a860c4b
JO
1082 }
1083 } else {
1084 pos = (pos + 1) % RGBLED_NUM;
dfab177f
TI
1085#if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
1086 anim->pos = pos;
1087#endif
3a860c4b 1088 }
0a40654b 1089}
6d6d91c8
TI
1090#endif
1091
1092#ifdef RGBLIGHT_EFFECT_KNIGHT
1093__attribute__ ((weak))
1094const uint8_t RGBLED_KNIGHT_INTERVALS[] PROGMEM = {127, 63, 31};
1095
dfab177f 1096void rgblight_effect_knight(animation_status_t *anim) {
4edfa97e
DS
1097
1098 static int8_t low_bound = 0;
1099 static int8_t high_bound = RGBLIGHT_EFFECT_KNIGHT_LENGTH - 1;
1100 static int8_t increment = 1;
1101 uint8_t i, cur;
1102
dfab177f
TI
1103#if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
1104 if (anim->pos == 0) { // restart signal
1105 anim->pos = 1;
1106 low_bound = 0;
1107 high_bound = RGBLIGHT_EFFECT_KNIGHT_LENGTH - 1;
1108 increment = 1;
1109 }
1110#endif
4580d3a7 1111 // Set all the LEDs to 0
94f8b758 1112 for (i = 0; i < RGBLED_NUM; i++) {
4580d3a7 1113 led[i].r = 0;
1114 led[i].g = 0;
1115 led[i].b = 0;
1116 }
1117 // Determine which LEDs should be lit up
1118 for (i = 0; i < RGBLIGHT_EFFECT_KNIGHT_LED_NUM; i++) {
94f8b758 1119 cur = (i + RGBLIGHT_EFFECT_KNIGHT_OFFSET) % RGBLED_NUM;
4edfa97e
DS
1120
1121 if (i >= low_bound && i <= high_bound) {
1122 sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[cur]);
3a860c4b 1123 } else {
4edfa97e
DS
1124 led[cur].r = 0;
1125 led[cur].g = 0;
1126 led[cur].b = 0;
3a860c4b
JO
1127 }
1128 }
4edfa97e
DS
1129 rgblight_set();
1130
4580d3a7 1131 // Move from low_bound to high_bound changing the direction we increment each
1132 // time a boundary is hit.
4edfa97e
DS
1133 low_bound += increment;
1134 high_bound += increment;
1135
4580d3a7 1136 if (high_bound <= 0 || low_bound >= RGBLIGHT_EFFECT_KNIGHT_LED_NUM - 1) {
4edfa97e 1137 increment = -increment;
dfab177f
TI
1138#if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
1139 if (increment == 1) {
1140 anim->pos = 0;
1141 }
1142#endif
4edfa97e 1143 }
3a860c4b 1144}
6d6d91c8 1145#endif
3a860c4b 1146
6d6d91c8 1147#ifdef RGBLIGHT_EFFECT_CHRISTMAS
dfab177f 1148void rgblight_effect_christmas(animation_status_t *anim) {
cae269b0
JH
1149 uint16_t hue;
1150 uint8_t i;
dfab177f
TI
1151
1152 anim->current_offset = (anim->current_offset + 1) % 2;
cae269b0 1153 for (i = 0; i < RGBLED_NUM; i++) {
dfab177f 1154 hue = 0 + ((i/RGBLIGHT_EFFECT_CHRISTMAS_STEP + anim->current_offset) % 2) * 120;
cae269b0
JH
1155 sethsv(hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i]);
1156 }
1157 rgblight_set();
1158}
6d6d91c8
TI
1159#endif
1160
1161#ifdef RGBLIGHT_EFFECT_RGB_TEST
1162__attribute__ ((weak))
1163const uint16_t RGBLED_RGBTEST_INTERVALS[] PROGMEM = {1024};
cae269b0 1164
dfab177f 1165void rgblight_effect_rgbtest(animation_status_t *anim) {
52297346
TI
1166 static uint8_t maxval = 0;
1167 uint8_t g; uint8_t r; uint8_t b;
1168
52297346
TI
1169 if( maxval == 0 ) {
1170 LED_TYPE tmp_led;
1171 sethsv(0, 255, RGBLIGHT_LIMIT_VAL, &tmp_led);
1172 maxval = tmp_led.r;
1173 }
52297346 1174 g = r = b = 0;
dfab177f 1175 switch( anim->pos ) {
52297346
TI
1176 case 0: r = maxval; break;
1177 case 1: g = maxval; break;
1178 case 2: b = maxval; break;
1179 }
1180 rgblight_setrgb(r, g, b);
dfab177f 1181 anim->pos = (anim->pos + 1) % 3;
52297346 1182}
6d6d91c8 1183#endif
52297346 1184
6d6d91c8 1185#ifdef RGBLIGHT_EFFECT_ALTERNATING
dfab177f 1186void rgblight_effect_alternating(animation_status_t *anim) {
595f3cbe
B
1187
1188 for(int i = 0; i<RGBLED_NUM; i++){
dfab177f 1189 if(i<RGBLED_NUM/2 && anim->pos){
db03b769 1190 sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i]);
dfab177f 1191 }else if (i>=RGBLED_NUM/2 && !anim->pos){
db03b769 1192 sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i]);
1193 }else{
1194 sethsv(rgblight_config.hue, rgblight_config.sat, 0, (LED_TYPE *)&led[i]);
1195 }
595f3cbe
B
1196 }
1197 rgblight_set();
dfab177f 1198 anim->pos = (anim->pos + 1) % 2;
595f3cbe 1199}
6d6d91c8 1200#endif