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