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