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