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