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