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