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