]> git.donarmstrong.com Git - qmk_firmware.git/blob - quantum/rgblight.c
[Keyboard] fixed pins for numpad_5x4 layout (#6311)
[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 "color.h"
32 #include "debug.h"
33 #include "led_tables.h"
34 #include "lib/lib8tion/lib8tion.h"
35 #ifdef VELOCIKEY_ENABLE
36   #include "velocikey.h"
37 #endif
38
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
43   #define RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS     rgblight_status.change_flags |= (RGBLIGHT_STATUS_CHANGE_MODE|RGBLIGHT_STATUS_CHANGE_HSVS)
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
49   #define RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS
50   #define RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE
51   #define RGBLIGHT_SPLIT_ANIMATION_TICK
52 #endif
53
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)
58 #define _RGBM_TMP_STATIC(sym, msym)      RGBLIGHT_MODE_ ## sym,
59 #define _RGBM_TMP_DYNAMIC(sym, msym)
60 static uint8_t static_effect_table [] = {
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,
70 static uint8_t mode_base_table [] = {
71     0, // RGBLIGHT_MODE_zero
72 #include "rgblight_modes.h"
73 };
74
75 static inline int is_static_effect(uint8_t mode) {
76     return memchr(static_effect_table, mode, sizeof(static_effect_table)) != NULL;
77 }
78
79 #ifdef RGBLIGHT_LED_MAP
80 const uint8_t led_map[] PROGMEM = RGBLIGHT_LED_MAP;
81 #endif
82
83 #ifdef RGBLIGHT_EFFECT_STATIC_GRADIENT
84 __attribute__ ((weak))
85 const uint8_t RGBLED_GRADIENT_RANGES[] PROGMEM = {255, 170, 127, 85, 64};
86 #endif
87
88 rgblight_config_t rgblight_config;
89 rgblight_status_t rgblight_status = { .timer_enabled = false };
90 bool is_rgblight_initialized = false;
91
92 #ifdef RGBLIGHT_USE_TIMER
93 animation_status_t animation_status = {};
94 #endif
95
96 #ifndef LED_ARRAY
97 LED_TYPE led[RGBLED_NUM];
98   #define LED_ARRAY led
99 #endif
100
101
102 static uint8_t clipping_start_pos = 0;
103 static uint8_t clipping_num_leds = RGBLED_NUM;
104 static uint8_t effect_start_pos = 0;
105 static uint8_t effect_end_pos = RGBLED_NUM;
106 static uint8_t effect_num_leds = RGBLED_NUM;
107
108 void 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
113 void 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 }
120
121 void sethsv_raw(uint8_t hue, uint8_t sat, uint8_t val, LED_TYPE *led1) {
122   HSV hsv = { hue, sat, val };
123   RGB rgb = hsv_to_rgb(hsv);
124   setrgb(rgb.r, rgb.g, rgb.b, led1);
125 }
126
127 void 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
133 void setrgb(uint8_t r, uint8_t g, uint8_t b, LED_TYPE *led1) {
134   (*led1).r = r;
135   (*led1).g = g;
136   (*led1).b = b;
137 }
138
139 void 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
149   if (rgblight_config.val > RGBLIGHT_LIMIT_VAL) {
150     rgblight_config.val = RGBLIGHT_LIMIT_VAL;
151   }
152 }
153
154 uint32_t eeconfig_read_rgblight(void) {
155   #if defined(__AVR__) || defined(STM32_EEPROM_ENABLE) || defined(PROTOCOL_ARM_ATSAM) || defined(EEPROM_SIZE)
156     return eeprom_read_dword(EECONFIG_RGBLIGHT);
157   #else
158     return 0;
159   #endif
160 }
161
162 void eeconfig_update_rgblight(uint32_t val) {
163   #if defined(__AVR__) || defined(STM32_EEPROM_ENABLE) || defined(PROTOCOL_ARM_ATSAM) || defined(EEPROM_SIZE)
164     rgblight_check_config();
165     eeprom_update_dword(EECONFIG_RGBLIGHT, val);
166   #endif
167 }
168
169 void eeconfig_update_rgblight_default(void) {
170   //dprintf("eeconfig_update_rgblight_default\n");
171   rgblight_config.enable = 1;
172   rgblight_config.mode = RGBLIGHT_MODE_STATIC_LIGHT;
173   rgblight_config.hue = 0;
174   rgblight_config.sat = UINT8_MAX;
175   rgblight_config.val = RGBLIGHT_LIMIT_VAL;
176   rgblight_config.speed = 0;
177   RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS;
178   eeconfig_update_rgblight(rgblight_config.raw);
179 }
180
181 void eeconfig_debug_rgblight(void) {
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);
188   dprintf("rgblight_config.speed = %d\n", rgblight_config.speed);
189 }
190
191 void rgblight_init(void) {
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
197   debug_enable = 1; // Debug ON!
198   dprintf("rgblight_init called.\n");
199   dprintf("rgblight_init start!\n");
200   if (!eeconfig_is_enabled()) {
201     dprintf("rgblight_init eeconfig is not enabled.\n");
202     eeconfig_init();
203     eeconfig_update_rgblight_default();
204   }
205   rgblight_config.raw = eeconfig_read_rgblight();
206   RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS;
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   }
212   rgblight_check_config();
213
214   eeconfig_debug_rgblight(); // display current eeprom values
215
216 #ifdef RGBLIGHT_USE_TIMER
217     rgblight_timer_init(); // setup the timer
218 #endif
219
220   if (rgblight_config.enable) {
221     rgblight_mode_noeeprom(rgblight_config.mode);
222   }
223
224   is_rgblight_initialized = true;
225
226 }
227
228 uint32_t rgblight_read_dword(void) {
229   return rgblight_config.raw;
230 }
231
232 void rgblight_update_dword(uint32_t dword) {
233   RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS;
234   rgblight_config.raw = dword;
235   if (rgblight_config.enable)
236     rgblight_mode_noeeprom(rgblight_config.mode);
237   else {
238 #ifdef RGBLIGHT_USE_TIMER
239       rgblight_timer_disable();
240 #endif
241       rgblight_set();
242   }
243 }
244
245 void rgblight_increase(void) {
246   uint8_t mode = 0;
247   if (rgblight_config.mode < RGBLIGHT_MODES) {
248     mode = rgblight_config.mode + 1;
249   }
250   rgblight_mode(mode);
251 }
252 void rgblight_decrease(void) {
253   uint8_t mode = 0;
254   // Mode will never be < 1. If it ever is, eeprom needs to be initialized.
255   if (rgblight_config.mode > RGBLIGHT_MODE_STATIC_LIGHT) {
256     mode = rgblight_config.mode - 1;
257   }
258   rgblight_mode(mode);
259 }
260 void rgblight_step_helper(bool write_to_eeprom) {
261   uint8_t mode = 0;
262   mode = rgblight_config.mode + 1;
263   if (mode > RGBLIGHT_MODES) {
264     mode = 1;
265   }
266   rgblight_mode_eeprom_helper(mode, write_to_eeprom);
267 }
268 void rgblight_step_noeeprom(void) {
269   rgblight_step_helper(false);
270 }
271 void rgblight_step(void) {
272   rgblight_step_helper(true);
273 }
274 void rgblight_step_reverse_helper(bool write_to_eeprom) {
275   uint8_t mode = 0;
276   mode = rgblight_config.mode - 1;
277   if (mode < 1) {
278     mode = RGBLIGHT_MODES;
279   }
280   rgblight_mode_eeprom_helper(mode, write_to_eeprom);
281 }
282 void rgblight_step_reverse_noeeprom(void) {
283   rgblight_step_reverse_helper(false);
284 }
285 void rgblight_step_reverse(void) {
286   rgblight_step_reverse_helper(true);
287 }
288
289 uint8_t rgblight_get_mode(void) {
290   if (!rgblight_config.enable) {
291     return false;
292   }
293
294   return rgblight_config.mode;
295 }
296
297 void rgblight_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) {
298   if (!rgblight_config.enable) {
299     return;
300   }
301   if (mode < RGBLIGHT_MODE_STATIC_LIGHT) {
302     rgblight_config.mode = RGBLIGHT_MODE_STATIC_LIGHT;
303   } else if (mode > RGBLIGHT_MODES) {
304     rgblight_config.mode = RGBLIGHT_MODES;
305   } else {
306     rgblight_config.mode = mode;
307   }
308   RGBLIGHT_SPLIT_SET_CHANGE_MODE;
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   }
315   if( is_static_effect(rgblight_config.mode) ) {
316 #ifdef RGBLIGHT_USE_TIMER
317       rgblight_timer_disable();
318 #endif
319   } else {
320 #ifdef RGBLIGHT_USE_TIMER
321       rgblight_timer_enable();
322 #endif
323   }
324 #ifdef RGBLIGHT_USE_TIMER
325     animation_status.restart = true;
326 #endif
327   rgblight_sethsv_noeeprom(rgblight_config.hue, rgblight_config.sat, rgblight_config.val);
328 }
329
330 void rgblight_mode(uint8_t mode) {
331   rgblight_mode_eeprom_helper(mode, true);
332 }
333
334 void rgblight_mode_noeeprom(uint8_t mode) {
335   rgblight_mode_eeprom_helper(mode, false);
336 }
337
338
339 void rgblight_toggle(void) {
340   xprintf("rgblight toggle [EEPROM]: rgblight_config.enable = %u\n", !rgblight_config.enable);
341   if (rgblight_config.enable) {
342     rgblight_disable();
343   }
344   else {
345     rgblight_enable();
346   }
347 }
348
349 void 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
359 void rgblight_enable(void) {
360   rgblight_config.enable = 1;
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);
364   rgblight_mode(rgblight_config.mode);
365 }
366
367 void 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
373 void rgblight_disable(void) {
374   rgblight_config.enable = 0;
375   eeconfig_update_rgblight(rgblight_config.raw);
376   xprintf("rgblight disable [EEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable);
377 #ifdef RGBLIGHT_USE_TIMER
378       rgblight_timer_disable();
379 #endif
380   RGBLIGHT_SPLIT_SET_CHANGE_MODE;
381   wait_ms(50);
382   rgblight_set();
383 }
384
385 void rgblight_disable_noeeprom(void) {
386   rgblight_config.enable = 0;
387   xprintf("rgblight disable [noEEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable);
388 #ifdef RGBLIGHT_USE_TIMER
389     rgblight_timer_disable();
390 #endif
391   RGBLIGHT_SPLIT_SET_CHANGE_MODE;
392   wait_ms(50);
393   rgblight_set();
394 }
395
396 void rgblight_increase_hue_helper(bool write_to_eeprom) {
397   uint8_t hue = rgblight_config.hue + RGBLIGHT_HUE_STEP;
398   rgblight_sethsv_eeprom_helper(hue, rgblight_config.sat, rgblight_config.val, write_to_eeprom);
399 }
400 void rgblight_increase_hue_noeeprom(void) {
401   rgblight_increase_hue_helper(false);
402 }
403 void rgblight_increase_hue(void) {
404   rgblight_increase_hue_helper(true);
405 }
406 void rgblight_decrease_hue_helper(bool write_to_eeprom) {
407   uint8_t hue = rgblight_config.hue - RGBLIGHT_HUE_STEP;
408   rgblight_sethsv_eeprom_helper(hue, rgblight_config.sat, rgblight_config.val, write_to_eeprom);
409 }
410 void rgblight_decrease_hue_noeeprom(void) {
411   rgblight_decrease_hue_helper(false);
412 }
413 void rgblight_decrease_hue(void) {
414   rgblight_decrease_hue_helper(true);
415 }
416 void rgblight_increase_sat_helper(bool write_to_eeprom) {
417   uint8_t sat = qadd8(rgblight_config.sat, RGBLIGHT_SAT_STEP);
418   rgblight_sethsv_eeprom_helper(rgblight_config.hue, sat, rgblight_config.val, write_to_eeprom);
419 }
420 void rgblight_increase_sat_noeeprom(void) {
421   rgblight_increase_sat_helper(false);
422 }
423 void rgblight_increase_sat(void) {
424   rgblight_increase_sat_helper(true);
425 }
426 void rgblight_decrease_sat_helper(bool write_to_eeprom) {
427   uint8_t sat = qsub8(rgblight_config.sat, RGBLIGHT_SAT_STEP);
428   rgblight_sethsv_eeprom_helper(rgblight_config.hue, sat, rgblight_config.val, write_to_eeprom);
429 }
430 void rgblight_decrease_sat_noeeprom(void) {
431   rgblight_decrease_sat_helper(false);
432 }
433 void rgblight_decrease_sat(void) {
434   rgblight_decrease_sat_helper(true);
435 }
436 void rgblight_increase_val_helper(bool write_to_eeprom) {
437   uint8_t val = qadd8(rgblight_config.val, RGBLIGHT_VAL_STEP);
438   rgblight_sethsv_eeprom_helper(rgblight_config.hue, rgblight_config.sat, val, write_to_eeprom);
439 }
440 void rgblight_increase_val_noeeprom(void) {
441   rgblight_increase_val_helper(false);
442 }
443 void rgblight_increase_val(void) {
444   rgblight_increase_val_helper(true);
445 }
446 void rgblight_decrease_val_helper(bool write_to_eeprom) {
447   uint8_t val = qsub8(rgblight_config.val, RGBLIGHT_VAL_STEP);
448   rgblight_sethsv_eeprom_helper(rgblight_config.hue, rgblight_config.sat, val, write_to_eeprom);
449 }
450 void rgblight_decrease_val_noeeprom(void) {
451   rgblight_decrease_val_helper(false);
452 }
453 void rgblight_decrease_val(void) {
454   rgblight_decrease_val_helper(true);
455 }
456 void rgblight_increase_speed(void) {
457     if (rgblight_config.speed < 3)
458         rgblight_config.speed++;
459     //RGBLIGHT_SPLIT_SET_CHANGE_HSVS; // NEED?
460     eeconfig_update_rgblight(rgblight_config.raw);//EECONFIG needs to be increased to support this
461 }
462
463 void rgblight_decrease_speed(void) {
464     if (rgblight_config.speed > 0)
465         rgblight_config.speed--;
466     //RGBLIGHT_SPLIT_SET_CHANGE_HSVS; // NEED??
467     eeconfig_update_rgblight(rgblight_config.raw);//EECONFIG needs to be increased to support this
468 }
469
470 void rgblight_sethsv_noeeprom_old(uint8_t hue, uint8_t sat, uint8_t val) {
471   if (rgblight_config.enable) {
472     LED_TYPE tmp_led;
473     sethsv(hue, sat, val, &tmp_led);
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 }
478
479 void rgblight_sethsv_eeprom_helper(uint8_t hue, uint8_t sat, uint8_t val, bool write_to_eeprom) {
480   if (rgblight_config.enable) {
481     rgblight_status.base_mode = mode_base_table[rgblight_config.mode];
482     if (rgblight_config.mode == RGBLIGHT_MODE_STATIC_LIGHT) {
483       // same static color
484       LED_TYPE tmp_led;
485       sethsv(hue, sat, val, &tmp_led);
486       rgblight_setrgb(tmp_led.r, tmp_led.g, tmp_led.b);
487     } else {
488       // all LEDs in same color
489       if ( 1 == 0 ) { //dummy
490       }
491 #ifdef RGBLIGHT_EFFECT_BREATHING
492       else if (rgblight_status.base_mode == RGBLIGHT_MODE_BREATHING ) {
493         // breathing mode, ignore the change of val, use in memory value instead
494         val = rgblight_config.val;
495       }
496 #endif
497 #ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD
498       else if (rgblight_status.base_mode == RGBLIGHT_MODE_RAINBOW_MOOD) {
499         // rainbow mood, ignore the change of hue
500         hue = rgblight_config.hue;
501       }
502 #endif
503 #ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL
504       else if (rgblight_status.base_mode == RGBLIGHT_MODE_RAINBOW_SWIRL) {
505         // rainbow swirl, ignore the change of hue
506         hue = rgblight_config.hue;
507       }
508 #endif
509 #ifdef RGBLIGHT_EFFECT_STATIC_GRADIENT
510       else if (rgblight_status.base_mode == RGBLIGHT_MODE_STATIC_GRADIENT) {
511         // static gradient
512         uint8_t delta = rgblight_config.mode - rgblight_status.base_mode;
513         bool direction = (delta % 2) == 0;
514 #ifdef __AVR__
515         // probably due to how pgm_read_word is defined for ARM, but the ARM compiler really hates this line
516         uint8_t range = pgm_read_word(&RGBLED_GRADIENT_RANGES[delta / 2]);
517 #else
518         uint8_t range = RGBLED_GRADIENT_RANGES[delta / 2];
519 #endif
520         for (uint8_t i = 0; i < effect_num_leds; i++) {
521           uint8_t _hue = ((uint16_t)i * (uint16_t)range) / effect_num_leds;
522           if (direction) {
523             _hue = hue + _hue;
524           } else {
525             _hue = hue - _hue;
526           }
527           dprintf("rgblight rainbow set hsv: %d,%d,%d,%u\n", i, _hue, direction, range);
528           sethsv(_hue, sat, val, (LED_TYPE *)&led[i + effect_start_pos]);
529         }
530         rgblight_set();
531       }
532 #endif
533     }
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
541     rgblight_config.hue = hue;
542     rgblight_config.sat = sat;
543     rgblight_config.val = val;
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     }
550   }
551 }
552
553 void rgblight_sethsv(uint8_t hue, uint8_t sat, uint8_t val) {
554   rgblight_sethsv_eeprom_helper(hue, sat, val, true);
555 }
556
557 void rgblight_sethsv_noeeprom(uint8_t hue, uint8_t sat, uint8_t val) {
558   rgblight_sethsv_eeprom_helper(hue, sat, val, false);
559 }
560
561 uint8_t rgblight_get_hue(void) {
562   return rgblight_config.hue;
563 }
564
565 uint8_t rgblight_get_sat(void) {
566   return rgblight_config.sat;
567 }
568
569 uint8_t rgblight_get_val(void) {
570   return rgblight_config.val;
571 }
572
573 void rgblight_setrgb(uint8_t r, uint8_t g, uint8_t b) {
574   if (!rgblight_config.enable) { return; }
575
576   for (uint8_t i = effect_start_pos; i < effect_end_pos; i++) {
577     led[i].r = r;
578     led[i].g = g;
579     led[i].b = b;
580   }
581   rgblight_set();
582 }
583
584 void 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
593 void rgblight_sethsv_at(uint8_t hue, uint8_t sat, uint8_t val, uint8_t index) {
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
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
604 static uint8_t get_interval_time(const uint8_t* default_interval_address, uint8_t velocikey_min, uint8_t velocikey_max) {
605   return
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
614 void 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
626 void rgblight_sethsv_range(uint8_t hue, uint8_t sat, uint8_t val, uint8_t start, uint8_t end) {
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
634 #ifndef RGBLIGHT_SPLIT
635 void 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
639 void 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
643 void rgblight_sethsv_master(uint8_t hue, uint8_t sat, uint8_t val) {
644   rgblight_sethsv_range(hue, sat, val, 0, (uint8_t) RGBLED_NUM/2);
645 }
646
647 void rgblight_sethsv_slave(uint8_t hue, uint8_t sat, uint8_t val) {
648   rgblight_sethsv_range(hue, sat, val, (uint8_t) RGBLED_NUM/2, (uint8_t) RGBLED_NUM);
649 }
650 #endif // ifndef RGBLIGHT_SPLIT
651
652 #ifndef RGBLIGHT_CUSTOM_DRIVER
653 void rgblight_set(void) {
654   LED_TYPE *start_led;
655   uint16_t num_leds = clipping_num_leds;
656
657   if (!rgblight_config.enable) {
658     for (uint8_t i = effect_start_pos; i < effect_end_pos; i++) {
659       led[i].r = 0;
660       led[i].g = 0;
661       led[i].b = 0;
662     }
663   }
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
678 }
679 #endif
680
681 #ifdef RGBLIGHT_SPLIT
682 /* for split keyboard master side */
683 uint8_t rgblight_get_change_flags(void) {
684     return rgblight_status.change_flags;
685 }
686
687 void rgblight_clear_change_flags(void) {
688     rgblight_status.change_flags = 0;
689 }
690
691 void 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 */
697 void 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
727 #ifdef RGBLIGHT_USE_TIMER
728
729 typedef void (*effect_func_t)(animation_status_t *anim);
730
731 // Animation timer -- use system timer (AVR Timer0)
732 void rgblight_timer_init(void) {
733   // OLD!!!! Animation timer -- AVR Timer3
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
749   rgblight_status.timer_enabled = false;
750   RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE;
751 }
752 void rgblight_timer_enable(void) {
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");
759 }
760 void rgblight_timer_disable(void) {
761   rgblight_status.timer_enabled = false;
762   RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE;
763   dprintf("rgblight timer disable.\n");
764 }
765 void rgblight_timer_toggle(void) {
766   dprintf("rgblight timer toggle.\n");
767   if(rgblight_status.timer_enabled) {
768       rgblight_timer_disable();
769   } else {
770       rgblight_timer_enable();
771   }
772 }
773
774 void rgblight_show_solid_color(uint8_t r, uint8_t g, uint8_t b) {
775   rgblight_enable();
776   rgblight_mode(RGBLIGHT_MODE_STATIC_LIGHT);
777   rgblight_setrgb(r, g, b);
778 }
779
780 static 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
792 void rgblight_task(void) {
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;
798
799     // static light mode, do nothing here
800     if ( 1 == 0 ) { //dummy
801     }
802 #ifdef RGBLIGHT_EFFECT_BREATHING
803     else if (rgblight_status.base_mode == RGBLIGHT_MODE_BREATHING) {
804       // breathing mode
805       interval_time = get_interval_time(&RGBLED_BREATHING_INTERVALS[delta], 1, 100);
806       effect_func = rgblight_effect_breathing;
807     }
808 #endif
809 #ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD
810     else if (rgblight_status.base_mode == RGBLIGHT_MODE_RAINBOW_MOOD) {
811       // rainbow mood mode
812       interval_time = get_interval_time(&RGBLED_RAINBOW_MOOD_INTERVALS[delta], 5, 100);
813       effect_func = rgblight_effect_rainbow_mood;
814     }
815 #endif
816 #ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL
817     else if (rgblight_status.base_mode == RGBLIGHT_MODE_RAINBOW_SWIRL) {
818       // rainbow swirl mode
819       interval_time = get_interval_time(&RGBLED_RAINBOW_SWIRL_INTERVALS[delta / 2], 1, 100);
820       effect_func = rgblight_effect_rainbow_swirl;
821     }
822 #endif
823 #ifdef RGBLIGHT_EFFECT_SNAKE
824     else if (rgblight_status.base_mode == RGBLIGHT_MODE_SNAKE) {
825       // snake mode
826       interval_time = get_interval_time(&RGBLED_SNAKE_INTERVALS[delta / 2], 1, 200);
827       effect_func = rgblight_effect_snake;
828     }
829 #endif
830 #ifdef RGBLIGHT_EFFECT_KNIGHT
831     else if (rgblight_status.base_mode == RGBLIGHT_MODE_KNIGHT) {
832       // knight mode
833       interval_time = get_interval_time(&RGBLED_KNIGHT_INTERVALS[delta], 5, 100);
834       effect_func = rgblight_effect_knight;
835     }
836 #endif
837 #ifdef RGBLIGHT_EFFECT_CHRISTMAS
838     else if (rgblight_status.base_mode == RGBLIGHT_MODE_CHRISTMAS) {
839       // christmas mode
840       interval_time = RGBLIGHT_EFFECT_CHRISTMAS_INTERVAL;
841       effect_func = (effect_func_t)rgblight_effect_christmas;
842     }
843 #endif
844 #ifdef RGBLIGHT_EFFECT_RGB_TEST
845     else if (rgblight_status.base_mode == RGBLIGHT_MODE_RGB_TEST) {
846       // RGB test mode
847       interval_time = pgm_read_word(&RGBLED_RGBTEST_INTERVALS[0]);
848       effect_func = (effect_func_t)rgblight_effect_rgbtest;
849     }
850 #endif
851 #ifdef RGBLIGHT_EFFECT_ALTERNATING
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
861     }
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       }
888 #endif
889     }
890   }
891 }
892
893 #endif /* RGBLIGHT_USE_TIMER */
894
895 // Effects
896 #ifdef RGBLIGHT_EFFECT_BREATHING
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
905 __attribute__ ((weak))
906 const uint8_t RGBLED_BREATHING_INTERVALS[] PROGMEM = {30, 20, 10, 5};
907
908 void rgblight_effect_breathing(animation_status_t *anim) {
909   float val;
910
911   // http://sean.voisen.org/blog/2011/10/breathing-led-with-arduino/
912 #ifdef RGBLIGHT_EFFECT_BREATHE_TABLE
913   val = pgm_read_byte(&rgblight_effect_breathe_table[anim->pos / table_scale]);
914 #else
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));
916 #endif
917   rgblight_sethsv_noeeprom_old(rgblight_config.hue, rgblight_config.sat, val);
918   anim->pos = (anim->pos + 1);
919 }
920 #endif
921
922 #ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD
923 __attribute__ ((weak))
924 const uint8_t RGBLED_RAINBOW_MOOD_INTERVALS[] PROGMEM = {120, 60, 30};
925
926 void rgblight_effect_rainbow_mood(animation_status_t *anim) {
927   rgblight_sethsv_noeeprom_old(anim->current_hue, rgblight_config.sat, rgblight_config.val);
928   anim->current_hue++;
929 }
930 #endif
931
932 #ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL
933 #ifndef RGBLIGHT_RAINBOW_SWIRL_RANGE
934   #define RGBLIGHT_RAINBOW_SWIRL_RANGE 255
935 #endif
936
937 __attribute__ ((weak))
938 const uint8_t RGBLED_RAINBOW_SWIRL_INTERVALS[] PROGMEM = {100, 50, 20};
939
940 void rgblight_effect_rainbow_swirl(animation_status_t *anim) {
941   uint8_t hue;
942   uint8_t i;
943
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]);
947   }
948   rgblight_set();
949
950   if (anim->delta % 2) {
951     anim->current_hue++;
952   } else {
953     anim->current_hue--;
954   }
955 }
956 #endif
957
958 #ifdef RGBLIGHT_EFFECT_SNAKE
959 __attribute__ ((weak))
960 const uint8_t RGBLED_SNAKE_INTERVALS[] PROGMEM = {100, 50, 20};
961
962 void rgblight_effect_snake(animation_status_t *anim) {
963   static uint8_t pos = 0;
964   uint8_t i, j;
965   int8_t k;
966   int8_t increment = 1;
967
968   if (anim->delta % 2) {
969     increment = -1;
970   }
971
972 #if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
973   if (anim->pos == 0) { // restart signal
974     if (increment == 1) {
975       pos = effect_num_leds - 1;
976     } else {
977       pos = 0;
978     }
979     anim->pos = 1;
980   }
981 #endif
982
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;
988     for (j = 0; j < RGBLIGHT_EFFECT_SNAKE_LENGTH; j++) {
989       k = pos + j * increment;
990       if (k < 0) {
991         k = k + effect_num_leds;
992       }
993       if (i == k) {
994         sethsv(rgblight_config.hue, rgblight_config.sat,
995                (uint8_t)(rgblight_config.val*(RGBLIGHT_EFFECT_SNAKE_LENGTH-j)/RGBLIGHT_EFFECT_SNAKE_LENGTH),
996                ledp);
997       }
998     }
999   }
1000   rgblight_set();
1001   if (increment == 1) {
1002     if (pos - 1 < 0) {
1003       pos = effect_num_leds - 1;
1004 #if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
1005       anim->pos = 0;
1006 #endif
1007     } else {
1008       pos -= 1;
1009 #if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
1010       anim->pos = 1;
1011 #endif
1012     }
1013   } else {
1014     pos = (pos + 1) % effect_num_leds;
1015 #if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
1016     anim->pos = pos;
1017 #endif
1018   }
1019 }
1020 #endif
1021
1022 #ifdef RGBLIGHT_EFFECT_KNIGHT
1023 __attribute__ ((weak))
1024 const uint8_t RGBLED_KNIGHT_INTERVALS[] PROGMEM = {127, 63, 31};
1025
1026 void rgblight_effect_knight(animation_status_t *anim) {
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
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
1041   // Set all the LEDs to 0
1042   for (i = effect_start_pos; i < effect_end_pos; i++) {
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++) {
1049     cur = (i + RGBLIGHT_EFFECT_KNIGHT_OFFSET) % effect_num_leds + effect_start_pos;
1050
1051     if (i >= low_bound && i <= high_bound) {
1052       sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[cur]);
1053     } else {
1054       led[cur].r = 0;
1055       led[cur].g = 0;
1056       led[cur].b = 0;
1057     }
1058   }
1059   rgblight_set();
1060
1061   // Move from low_bound to high_bound changing the direction we increment each
1062   // time a boundary is hit.
1063   low_bound += increment;
1064   high_bound += increment;
1065
1066   if (high_bound <= 0 || low_bound >= RGBLIGHT_EFFECT_KNIGHT_LED_NUM - 1) {
1067     increment = -increment;
1068 #if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
1069     if (increment == 1) {
1070         anim->pos = 0;
1071     }
1072 #endif
1073   }
1074 }
1075 #endif
1076
1077 #ifdef RGBLIGHT_EFFECT_CHRISTMAS
1078 void rgblight_effect_christmas(animation_status_t *anim) {
1079   uint8_t hue;
1080   uint8_t i;
1081
1082   anim->current_offset = (anim->current_offset + 1) % 2;
1083   for (i = 0; i < effect_num_leds; i++) {
1084     hue = 0 + ((i/RGBLIGHT_EFFECT_CHRISTMAS_STEP + anim->current_offset) % 2) * 85;
1085     sethsv(hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i + effect_start_pos]);
1086   }
1087   rgblight_set();
1088 }
1089 #endif
1090
1091 #ifdef RGBLIGHT_EFFECT_RGB_TEST
1092 __attribute__ ((weak))
1093 const uint16_t RGBLED_RGBTEST_INTERVALS[] PROGMEM = {1024};
1094
1095 void rgblight_effect_rgbtest(animation_status_t *anim) {
1096   static uint8_t maxval = 0;
1097   uint8_t g; uint8_t r; uint8_t b;
1098
1099   if( maxval == 0 ) {
1100       LED_TYPE tmp_led;
1101       sethsv(0, 255, RGBLIGHT_LIMIT_VAL, &tmp_led);
1102       maxval = tmp_led.r;
1103   }
1104   g = r = b = 0;
1105   switch( anim->pos ) {
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);
1111   anim->pos = (anim->pos + 1) % 3;
1112 }
1113 #endif
1114
1115 #ifdef RGBLIGHT_EFFECT_ALTERNATING
1116 void rgblight_effect_alternating(animation_status_t *anim) {
1117
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);
1126       }
1127   }
1128   rgblight_set();
1129   anim->pos = (anim->pos + 1) % 2;
1130 }
1131 #endif