1 /* Copyright 2016-2017 Yang Liu
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.
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.
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/>.
19 #include <avr/eeprom.h>
20 #include <avr/interrupt.h>
22 #ifdef STM32_EEPROM_ENABLE
25 #include "eeprom_stm32.h"
32 #include "led_tables.h"
34 #ifndef RGBLIGHT_LIMIT_VAL
35 #define RGBLIGHT_LIMIT_VAL 255
38 #define _RGBM_SINGLE_STATIC(sym) RGBLIGHT_MODE_ ## sym,
39 #define _RGBM_SINGLE_DYNAMIC(sym)
40 #define _RGBM_MULTI_STATIC(sym) RGBLIGHT_MODE_ ## sym,
41 #define _RGBM_MULTI_DYNAMIC(sym)
42 #define _RGBM_TMP_STATIC(sym) RGBLIGHT_MODE_ ## sym,
43 #define _RGBM_TMP_DYNAMIC(sym)
44 static uint8_t static_effect_table [] = {
48 static inline int is_static_effect(uint8_t mode) {
49 return memchr(static_effect_table, mode, sizeof(static_effect_table)) != NULL;
52 #define MIN(a,b) (((a)<(b))?(a):(b))
53 #define MAX(a,b) (((a)>(b))?(a):(b))
55 #ifdef RGBLIGHT_EFFECT_STATIC_GRADIENT
56 __attribute__ ((weak))
57 const uint16_t RGBLED_GRADIENT_RANGES[] PROGMEM = {360, 240, 180, 120, 90};
60 rgblight_config_t rgblight_config;
61 bool is_rgblight_initialized = false;
63 LED_TYPE led[RGBLED_NUM];
64 bool rgblight_timer_enabled = false;
66 void sethsv(uint16_t hue, uint8_t sat, uint8_t val, LED_TYPE *led1) {
67 uint8_t r = 0, g = 0, b = 0, base, color;
69 if (val > RGBLIGHT_LIMIT_VAL) {
70 val=RGBLIGHT_LIMIT_VAL; // limit the val
73 if (sat == 0) { // Acromatic color (gray). Hue doesn't mind.
78 base = ((255 - sat) * val) >> 8;
79 color = (val - base) * (hue % 60) / 60;
114 r = pgm_read_byte(&CIE1931_CURVE[r]);
115 g = pgm_read_byte(&CIE1931_CURVE[g]);
116 b = pgm_read_byte(&CIE1931_CURVE[b]);
118 setrgb(r, g, b, led1);
121 void setrgb(uint8_t r, uint8_t g, uint8_t b, LED_TYPE *led1) {
127 void rgblight_check_config(void) {
128 /* Add some out of bound checks for RGB light config */
130 if (rgblight_config.mode < RGBLIGHT_MODE_STATIC_LIGHT) {
131 rgblight_config.mode = RGBLIGHT_MODE_STATIC_LIGHT;
133 else if (rgblight_config.mode > RGBLIGHT_MODES) {
134 rgblight_config.mode = RGBLIGHT_MODES;
137 if (rgblight_config.hue < 0) {
138 rgblight_config.hue = 0;
139 } else if (rgblight_config.hue > 360) {
140 rgblight_config.hue %= 360;
143 if (rgblight_config.sat < 0) {
144 rgblight_config.sat = 0;
145 } else if (rgblight_config.sat > 255) {
146 rgblight_config.sat = 255;
149 if (rgblight_config.val < 0) {
150 rgblight_config.val = 0;
151 } else if (rgblight_config.val > RGBLIGHT_LIMIT_VAL) {
152 rgblight_config.val = RGBLIGHT_LIMIT_VAL;
157 uint32_t eeconfig_read_rgblight(void) {
158 #if defined(__AVR__) || defined(STM32_EEPROM_ENABLE) || defined(PROTOCOL_ARM_ATSAM) || defined(EEPROM_SIZE)
159 return eeprom_read_dword(EECONFIG_RGBLIGHT);
165 void eeconfig_update_rgblight(uint32_t val) {
166 #if defined(__AVR__) || defined(STM32_EEPROM_ENABLE) || defined(PROTOCOL_ARM_ATSAM) || defined(EEPROM_SIZE)
167 rgblight_check_config();
168 eeprom_update_dword(EECONFIG_RGBLIGHT, val);
172 void eeconfig_update_rgblight_default(void) {
173 //dprintf("eeconfig_update_rgblight_default\n");
174 rgblight_config.enable = 1;
175 rgblight_config.mode = RGBLIGHT_MODE_STATIC_LIGHT;
176 rgblight_config.hue = 0;
177 rgblight_config.sat = 255;
178 rgblight_config.val = RGBLIGHT_LIMIT_VAL;
179 rgblight_config.speed = 0;
180 eeconfig_update_rgblight(rgblight_config.raw);
183 void eeconfig_debug_rgblight(void) {
184 dprintf("rgblight_config eprom\n");
185 dprintf("rgblight_config.enable = %d\n", rgblight_config.enable);
186 dprintf("rghlight_config.mode = %d\n", rgblight_config.mode);
187 dprintf("rgblight_config.hue = %d\n", rgblight_config.hue);
188 dprintf("rgblight_config.sat = %d\n", rgblight_config.sat);
189 dprintf("rgblight_config.val = %d\n", rgblight_config.val);
190 dprintf("rgblight_config.speed = %d\n", rgblight_config.speed);
193 void rgblight_init(void) {
194 /* if already initialized, don't do it again.
195 If you must do it again, extern this and set to false, first.
196 This is a dirty, dirty hack until proper hooks can be added for keyboard startup. */
197 if (is_rgblight_initialized) { return; }
199 debug_enable = 1; // Debug ON!
200 dprintf("rgblight_init called.\n");
201 dprintf("rgblight_init start!\n");
202 if (!eeconfig_is_enabled()) {
203 dprintf("rgblight_init eeconfig is not enabled.\n");
205 eeconfig_update_rgblight_default();
207 rgblight_config.raw = eeconfig_read_rgblight();
208 if (!rgblight_config.mode) {
209 dprintf("rgblight_init rgblight_config.mode = 0. Write default values to EEPROM.\n");
210 eeconfig_update_rgblight_default();
211 rgblight_config.raw = eeconfig_read_rgblight();
213 rgblight_check_config();
215 eeconfig_debug_rgblight(); // display current eeprom values
217 #ifdef RGBLIGHT_USE_TIMER
218 rgblight_timer_init(); // setup the timer
221 if (rgblight_config.enable) {
222 rgblight_mode_noeeprom(rgblight_config.mode);
225 is_rgblight_initialized = true;
229 void rgblight_update_dword(uint32_t dword) {
230 rgblight_config.raw = dword;
231 eeconfig_update_rgblight(rgblight_config.raw);
232 if (rgblight_config.enable)
233 rgblight_mode(rgblight_config.mode);
235 #ifdef RGBLIGHT_USE_TIMER
236 rgblight_timer_disable();
242 void rgblight_increase(void) {
244 if (rgblight_config.mode < RGBLIGHT_MODES) {
245 mode = rgblight_config.mode + 1;
249 void rgblight_decrease(void) {
251 // Mode will never be < 1. If it ever is, eeprom needs to be initialized.
252 if (rgblight_config.mode > RGBLIGHT_MODE_STATIC_LIGHT) {
253 mode = rgblight_config.mode - 1;
257 void rgblight_step_helper(bool write_to_eeprom) {
259 mode = rgblight_config.mode + 1;
260 if (mode > RGBLIGHT_MODES) {
263 rgblight_mode_eeprom_helper(mode, write_to_eeprom);
265 void rgblight_step_noeeprom(void) {
266 rgblight_step_helper(false);
268 void rgblight_step(void) {
269 rgblight_step_helper(true);
271 void rgblight_step_reverse_helper(bool write_to_eeprom) {
273 mode = rgblight_config.mode - 1;
275 mode = RGBLIGHT_MODES;
277 rgblight_mode_eeprom_helper(mode, write_to_eeprom);
279 void rgblight_step_reverse_noeeprom(void) {
280 rgblight_step_reverse_helper(false);
282 void rgblight_step_reverse(void) {
283 rgblight_step_reverse_helper(true);
286 uint8_t rgblight_get_mode(void) {
287 if (!rgblight_config.enable) {
291 return rgblight_config.mode;
294 void rgblight_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) {
295 if (!rgblight_config.enable) {
298 if (mode < RGBLIGHT_MODE_STATIC_LIGHT) {
299 rgblight_config.mode = RGBLIGHT_MODE_STATIC_LIGHT;
300 } else if (mode > RGBLIGHT_MODES) {
301 rgblight_config.mode = RGBLIGHT_MODES;
303 rgblight_config.mode = mode;
305 if (write_to_eeprom) {
306 eeconfig_update_rgblight(rgblight_config.raw);
307 xprintf("rgblight mode [EEPROM]: %u\n", rgblight_config.mode);
309 xprintf("rgblight mode [NOEEPROM]: %u\n", rgblight_config.mode);
311 if( is_static_effect(rgblight_config.mode) ) {
312 #ifdef RGBLIGHT_USE_TIMER
313 rgblight_timer_disable();
316 #ifdef RGBLIGHT_USE_TIMER
317 rgblight_timer_enable();
320 rgblight_sethsv_noeeprom(rgblight_config.hue, rgblight_config.sat, rgblight_config.val);
323 void rgblight_mode(uint8_t mode) {
324 rgblight_mode_eeprom_helper(mode, true);
327 void rgblight_mode_noeeprom(uint8_t mode) {
328 rgblight_mode_eeprom_helper(mode, false);
332 void rgblight_toggle(void) {
333 xprintf("rgblight toggle [EEPROM]: rgblight_config.enable = %u\n", !rgblight_config.enable);
334 if (rgblight_config.enable) {
342 void rgblight_toggle_noeeprom(void) {
343 xprintf("rgblight toggle [NOEEPROM]: rgblight_config.enable = %u\n", !rgblight_config.enable);
344 if (rgblight_config.enable) {
345 rgblight_disable_noeeprom();
348 rgblight_enable_noeeprom();
352 void rgblight_enable(void) {
353 rgblight_config.enable = 1;
354 // No need to update EEPROM here. rgblight_mode() will do that, actually
355 //eeconfig_update_rgblight(rgblight_config.raw);
356 xprintf("rgblight enable [EEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable);
357 rgblight_mode(rgblight_config.mode);
360 void rgblight_enable_noeeprom(void) {
361 rgblight_config.enable = 1;
362 xprintf("rgblight enable [NOEEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable);
363 rgblight_mode_noeeprom(rgblight_config.mode);
366 void rgblight_disable(void) {
367 rgblight_config.enable = 0;
368 eeconfig_update_rgblight(rgblight_config.raw);
369 xprintf("rgblight disable [EEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable);
370 #ifdef RGBLIGHT_USE_TIMER
371 rgblight_timer_disable();
377 void rgblight_disable_noeeprom(void) {
378 rgblight_config.enable = 0;
379 xprintf("rgblight disable [noEEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable);
380 #ifdef RGBLIGHT_USE_TIMER
381 rgblight_timer_disable();
388 // Deals with the messy details of incrementing an integer
389 static uint8_t increment( uint8_t value, uint8_t step, uint8_t min, uint8_t max ) {
390 int16_t new_value = value;
392 return MIN( MAX( new_value, min ), max );
395 static uint8_t decrement( uint8_t value, uint8_t step, uint8_t min, uint8_t max ) {
396 int16_t new_value = value;
398 return MIN( MAX( new_value, min ), max );
401 void rgblight_increase_hue_helper(bool write_to_eeprom) {
403 hue = (rgblight_config.hue+RGBLIGHT_HUE_STEP) % 360;
404 rgblight_sethsv_eeprom_helper(hue, rgblight_config.sat, rgblight_config.val, write_to_eeprom);
406 void rgblight_increase_hue_noeeprom(void) {
407 rgblight_increase_hue_helper(false);
409 void rgblight_increase_hue(void) {
410 rgblight_increase_hue_helper(true);
412 void rgblight_decrease_hue_helper(bool write_to_eeprom) {
414 if (rgblight_config.hue-RGBLIGHT_HUE_STEP < 0) {
415 hue = (rgblight_config.hue + 360 - RGBLIGHT_HUE_STEP) % 360;
417 hue = (rgblight_config.hue - RGBLIGHT_HUE_STEP) % 360;
419 rgblight_sethsv_eeprom_helper(hue, rgblight_config.sat, rgblight_config.val, write_to_eeprom);
421 void rgblight_decrease_hue_noeeprom(void) {
422 rgblight_decrease_hue_helper(false);
424 void rgblight_decrease_hue(void) {
425 rgblight_decrease_hue_helper(true);
427 void rgblight_increase_sat_helper(bool write_to_eeprom) {
429 if (rgblight_config.sat + RGBLIGHT_SAT_STEP > 255) {
432 sat = rgblight_config.sat + RGBLIGHT_SAT_STEP;
434 rgblight_sethsv_eeprom_helper(rgblight_config.hue, sat, rgblight_config.val, write_to_eeprom);
436 void rgblight_increase_sat_noeeprom(void) {
437 rgblight_increase_sat_helper(false);
439 void rgblight_increase_sat(void) {
440 rgblight_increase_sat_helper(true);
442 void rgblight_decrease_sat_helper(bool write_to_eeprom) {
444 if (rgblight_config.sat - RGBLIGHT_SAT_STEP < 0) {
447 sat = rgblight_config.sat - RGBLIGHT_SAT_STEP;
449 rgblight_sethsv_eeprom_helper(rgblight_config.hue, sat, rgblight_config.val, write_to_eeprom);
451 void rgblight_decrease_sat_noeeprom(void) {
452 rgblight_decrease_sat_helper(false);
454 void rgblight_decrease_sat(void) {
455 rgblight_decrease_sat_helper(true);
457 void rgblight_increase_val_helper(bool write_to_eeprom) {
459 if (rgblight_config.val + RGBLIGHT_VAL_STEP > RGBLIGHT_LIMIT_VAL) {
460 val = RGBLIGHT_LIMIT_VAL;
462 val = rgblight_config.val + RGBLIGHT_VAL_STEP;
464 rgblight_sethsv_eeprom_helper(rgblight_config.hue, rgblight_config.sat, val, write_to_eeprom);
466 void rgblight_increase_val_noeeprom(void) {
467 rgblight_increase_val_helper(false);
469 void rgblight_increase_val(void) {
470 rgblight_increase_val_helper(true);
472 void rgblight_decrease_val_helper(bool write_to_eeprom) {
474 if (rgblight_config.val - RGBLIGHT_VAL_STEP < 0) {
477 val = rgblight_config.val - RGBLIGHT_VAL_STEP;
479 rgblight_sethsv_eeprom_helper(rgblight_config.hue, rgblight_config.sat, val, write_to_eeprom);
481 void rgblight_decrease_val_noeeprom(void) {
482 rgblight_decrease_val_helper(false);
484 void rgblight_decrease_val(void) {
485 rgblight_decrease_val_helper(true);
487 void rgblight_increase_speed(void) {
488 rgblight_config.speed = increment( rgblight_config.speed, 1, 0, 3 );
489 eeconfig_update_rgblight(rgblight_config.raw);//EECONFIG needs to be increased to support this
492 void rgblight_decrease_speed(void) {
493 rgblight_config.speed = decrement( rgblight_config.speed, 1, 0, 3 );
494 eeconfig_update_rgblight(rgblight_config.raw);//EECONFIG needs to be increased to support this
497 void rgblight_sethsv_noeeprom_old(uint16_t hue, uint8_t sat, uint8_t val) {
498 if (rgblight_config.enable) {
500 sethsv(hue, sat, val, &tmp_led);
501 // dprintf("rgblight set hue [MEMORY]: %u,%u,%u\n", inmem_config.hue, inmem_config.sat, inmem_config.val);
502 rgblight_setrgb(tmp_led.r, tmp_led.g, tmp_led.b);
506 void rgblight_sethsv_eeprom_helper(uint16_t hue, uint8_t sat, uint8_t val, bool write_to_eeprom) {
507 if (rgblight_config.enable) {
508 if (rgblight_config.mode == RGBLIGHT_MODE_STATIC_LIGHT) {
511 sethsv(hue, sat, val, &tmp_led);
512 rgblight_setrgb(tmp_led.r, tmp_led.g, tmp_led.b);
514 // all LEDs in same color
515 if ( 1 == 0 ) { //dummy
517 #ifdef RGBLIGHT_EFFECT_BREATHING
518 else if (rgblight_config.mode >= RGBLIGHT_MODE_BREATHING &&
519 rgblight_config.mode <= RGBLIGHT_MODE_BREATHING_end) {
520 // breathing mode, ignore the change of val, use in memory value instead
521 val = rgblight_config.val;
524 #ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD
525 else if (rgblight_config.mode >= RGBLIGHT_MODE_RAINBOW_MOOD &&
526 rgblight_config.mode <= RGBLIGHT_MODE_RAINBOW_MOOD_end) {
527 // rainbow mood, ignore the change of hue
528 hue = rgblight_config.hue;
531 #ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL
532 else if (rgblight_config.mode >= RGBLIGHT_MODE_RAINBOW_SWIRL &&
533 rgblight_config.mode <= RGBLIGHT_MODE_RAINBOW_SWIRL_end) {
534 // rainbow swirl, ignore the change of hue
535 hue = rgblight_config.hue;
538 #ifdef RGBLIGHT_EFFECT_STATIC_GRADIENT
539 else if (rgblight_config.mode >= RGBLIGHT_MODE_STATIC_GRADIENT &&
540 rgblight_config.mode <= RGBLIGHT_MODE_STATIC_GRADIENT_end) {
543 int8_t direction = ((rgblight_config.mode - RGBLIGHT_MODE_STATIC_GRADIENT) % 2) ? -1 : 1;
544 uint16_t range = pgm_read_word(&RGBLED_GRADIENT_RANGES[(rgblight_config.mode - RGBLIGHT_MODE_STATIC_GRADIENT) / 2]);
545 for (uint8_t i = 0; i < RGBLED_NUM; i++) {
546 _hue = (range / RGBLED_NUM * i * direction + hue + 360) % 360;
547 dprintf("rgblight rainbow set hsv: %u,%u,%d,%u\n", i, _hue, direction, range);
548 sethsv(_hue, sat, val, (LED_TYPE *)&led[i]);
554 rgblight_config.hue = hue;
555 rgblight_config.sat = sat;
556 rgblight_config.val = val;
557 if (write_to_eeprom) {
558 eeconfig_update_rgblight(rgblight_config.raw);
559 xprintf("rgblight set hsv [EEPROM]: %u,%u,%u\n", rgblight_config.hue, rgblight_config.sat, rgblight_config.val);
561 xprintf("rgblight set hsv [NOEEPROM]: %u,%u,%u\n", rgblight_config.hue, rgblight_config.sat, rgblight_config.val);
566 void rgblight_sethsv(uint16_t hue, uint8_t sat, uint8_t val) {
567 rgblight_sethsv_eeprom_helper(hue, sat, val, true);
570 void rgblight_sethsv_noeeprom(uint16_t hue, uint8_t sat, uint8_t val) {
571 rgblight_sethsv_eeprom_helper(hue, sat, val, false);
574 uint16_t rgblight_get_hue(void) {
575 return rgblight_config.hue;
578 uint8_t rgblight_get_sat(void) {
579 return rgblight_config.sat;
582 uint8_t rgblight_get_val(void) {
583 return rgblight_config.val;
586 void rgblight_setrgb(uint8_t r, uint8_t g, uint8_t b) {
587 if (!rgblight_config.enable) { return; }
589 for (uint8_t i = 0; i < RGBLED_NUM; i++) {
597 void rgblight_setrgb_at(uint8_t r, uint8_t g, uint8_t b, uint8_t index) {
598 if (!rgblight_config.enable || index >= RGBLED_NUM) { return; }
606 void rgblight_sethsv_at(uint16_t hue, uint8_t sat, uint8_t val, uint8_t index) {
607 if (!rgblight_config.enable) { return; }
610 sethsv(hue, sat, val, &tmp_led);
611 rgblight_setrgb_at(tmp_led.r, tmp_led.g, tmp_led.b, index);
614 void rgblight_setrgb_range(uint8_t r, uint8_t g, uint8_t b, uint8_t start, uint8_t end) {
615 if (!rgblight_config.enable || start < 0 || start >= end || end > RGBLED_NUM) { return; }
617 for (uint8_t i = start; i < end; i++) {
626 void rgblight_sethsv_range(uint16_t hue, uint8_t sat, uint8_t val, uint8_t start, uint8_t end) {
627 if (!rgblight_config.enable) { return; }
630 sethsv(hue, sat, val, &tmp_led);
631 rgblight_setrgb_range(tmp_led.r, tmp_led.g, tmp_led.b, start, end);
634 void rgblight_setrgb_master(uint8_t r, uint8_t g, uint8_t b) {
635 rgblight_setrgb_range(r, g, b, 0 , (uint8_t) RGBLED_NUM/2);
638 void rgblight_setrgb_slave(uint8_t r, uint8_t g, uint8_t b) {
639 rgblight_setrgb_range(r, g, b, (uint8_t) RGBLED_NUM/2, (uint8_t) RGBLED_NUM);
642 void rgblight_sethsv_master(uint16_t hue, uint8_t sat, uint8_t val) {
643 rgblight_sethsv_range(hue, sat, val, 0, (uint8_t) RGBLED_NUM/2);
646 void rgblight_sethsv_slave(uint16_t hue, uint8_t sat, uint8_t val) {
647 rgblight_sethsv_range(hue, sat, val, (uint8_t) RGBLED_NUM/2, (uint8_t) RGBLED_NUM);
650 #ifndef RGBLIGHT_CUSTOM_DRIVER
651 void rgblight_set(void) {
652 if (rgblight_config.enable) {
654 ws2812_setleds_rgbw(led, RGBLED_NUM);
656 ws2812_setleds(led, RGBLED_NUM);
659 for (uint8_t i = 0; i < RGBLED_NUM; i++) {
665 ws2812_setleds_rgbw(led, RGBLED_NUM);
667 ws2812_setleds(led, RGBLED_NUM);
673 #ifdef RGBLIGHT_USE_TIMER
675 // Animation timer -- AVR Timer3
676 void rgblight_timer_init(void) {
677 // static uint8_t rgblight_timer_is_init = 0;
678 // if (rgblight_timer_is_init) {
681 // rgblight_timer_is_init = 1;
682 // /* Timer 3 setup */
683 // TCCR3B = _BV(WGM32) // CTC mode OCR3A as TOP
684 // | _BV(CS30); // Clock selelct: clk/1
685 // /* Set TOP value */
686 // uint8_t sreg = SREG;
688 // OCR3AH = (RGBLED_TIMER_TOP >> 8) & 0xff;
689 // OCR3AL = RGBLED_TIMER_TOP & 0xff;
692 rgblight_timer_enabled = true;
694 void rgblight_timer_enable(void) {
695 rgblight_timer_enabled = true;
696 dprintf("TIMER3 enabled.\n");
698 void rgblight_timer_disable(void) {
699 rgblight_timer_enabled = false;
700 dprintf("TIMER3 disabled.\n");
702 void rgblight_timer_toggle(void) {
703 rgblight_timer_enabled ^= rgblight_timer_enabled;
704 dprintf("TIMER3 toggled.\n");
707 void rgblight_show_solid_color(uint8_t r, uint8_t g, uint8_t b) {
709 rgblight_mode(RGBLIGHT_MODE_STATIC_LIGHT);
710 rgblight_setrgb(r, g, b);
713 void rgblight_task(void) {
714 if (rgblight_timer_enabled) {
715 // static light mode, do nothing here
716 if ( 1 == 0 ) { //dummy
718 #ifdef RGBLIGHT_EFFECT_BREATHING
719 else if (rgblight_config.mode >= RGBLIGHT_MODE_BREATHING &&
720 rgblight_config.mode <= RGBLIGHT_MODE_BREATHING_end) {
722 rgblight_effect_breathing(rgblight_config.mode - RGBLIGHT_MODE_BREATHING );
725 #ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD
726 else if (rgblight_config.mode >= RGBLIGHT_MODE_RAINBOW_MOOD &&
727 rgblight_config.mode <= RGBLIGHT_MODE_RAINBOW_MOOD_end) {
729 rgblight_effect_rainbow_mood(rgblight_config.mode - RGBLIGHT_MODE_RAINBOW_MOOD);
732 #ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL
733 else if (rgblight_config.mode >= RGBLIGHT_MODE_RAINBOW_SWIRL &&
734 rgblight_config.mode <= RGBLIGHT_MODE_RAINBOW_SWIRL_end) {
735 // rainbow swirl mode
736 rgblight_effect_rainbow_swirl(rgblight_config.mode - RGBLIGHT_MODE_RAINBOW_SWIRL);
739 #ifdef RGBLIGHT_EFFECT_SNAKE
740 else if (rgblight_config.mode >= RGBLIGHT_MODE_SNAKE &&
741 rgblight_config.mode <= RGBLIGHT_MODE_SNAKE_end) {
743 rgblight_effect_snake(rgblight_config.mode - RGBLIGHT_MODE_SNAKE);
746 #ifdef RGBLIGHT_EFFECT_KNIGHT
747 else if (rgblight_config.mode >= RGBLIGHT_MODE_KNIGHT &&
748 rgblight_config.mode <= RGBLIGHT_MODE_KNIGHT_end) {
750 rgblight_effect_knight(rgblight_config.mode - RGBLIGHT_MODE_KNIGHT);
753 #ifdef RGBLIGHT_EFFECT_CHRISTMAS
754 else if (rgblight_config.mode == RGBLIGHT_MODE_CHRISTMAS) {
756 rgblight_effect_christmas();
759 #ifdef RGBLIGHT_EFFECT_RGB_TEST
760 else if (rgblight_config.mode == RGBLIGHT_MODE_RGB_TEST) {
762 rgblight_effect_rgbtest();
765 #ifdef RGBLIGHT_EFFECT_ALTERNATING
766 else if (rgblight_config.mode == RGBLIGHT_MODE_ALTERNATING){
767 rgblight_effect_alternating();
773 #endif /* RGBLIGHT_USE_TIMER */
776 #ifdef RGBLIGHT_EFFECT_BREATHING
777 __attribute__ ((weak))
778 const uint8_t RGBLED_BREATHING_INTERVALS[] PROGMEM = {30, 20, 10, 5};
780 void rgblight_effect_breathing(uint8_t interval) {
781 static uint8_t pos = 0;
782 static uint16_t last_timer = 0;
785 if (timer_elapsed(last_timer) < pgm_read_byte(&RGBLED_BREATHING_INTERVALS[interval])) {
788 last_timer = timer_read();
790 // http://sean.voisen.org/blog/2011/10/breathing-led-with-arduino/
791 val = (exp(sin((pos/255.0)*M_PI)) - RGBLIGHT_EFFECT_BREATHE_CENTER/M_E)*(RGBLIGHT_EFFECT_BREATHE_MAX/(M_E-1/M_E));
792 rgblight_sethsv_noeeprom_old(rgblight_config.hue, rgblight_config.sat, val);
793 pos = (pos + 1) % 256;
797 #ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD
798 __attribute__ ((weak))
799 const uint8_t RGBLED_RAINBOW_MOOD_INTERVALS[] PROGMEM = {120, 60, 30};
801 void rgblight_effect_rainbow_mood(uint8_t interval) {
802 static uint16_t current_hue = 0;
803 static uint16_t last_timer = 0;
805 if (timer_elapsed(last_timer) < pgm_read_byte(&RGBLED_RAINBOW_MOOD_INTERVALS[interval])) {
808 last_timer = timer_read();
809 rgblight_sethsv_noeeprom_old(current_hue, rgblight_config.sat, rgblight_config.val);
810 current_hue = (current_hue + 1) % 360;
814 #ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL
815 #ifndef RGBLIGHT_RAINBOW_SWIRL_RANGE
816 #define RGBLIGHT_RAINBOW_SWIRL_RANGE 360
819 __attribute__ ((weak))
820 const uint8_t RGBLED_RAINBOW_SWIRL_INTERVALS[] PROGMEM = {100, 50, 20};
822 void rgblight_effect_rainbow_swirl(uint8_t interval) {
823 static uint16_t current_hue = 0;
824 static uint16_t last_timer = 0;
827 if (timer_elapsed(last_timer) < pgm_read_byte(&RGBLED_RAINBOW_SWIRL_INTERVALS[interval / 2])) {
830 last_timer = timer_read();
831 for (i = 0; i < RGBLED_NUM; i++) {
832 hue = (RGBLIGHT_RAINBOW_SWIRL_RANGE / RGBLED_NUM * i + current_hue) % 360;
833 sethsv(hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i]);
838 current_hue = (current_hue + 1) % 360;
840 if (current_hue - 1 < 0) {
843 current_hue = current_hue - 1;
849 #ifdef RGBLIGHT_EFFECT_SNAKE
850 __attribute__ ((weak))
851 const uint8_t RGBLED_SNAKE_INTERVALS[] PROGMEM = {100, 50, 20};
853 void rgblight_effect_snake(uint8_t interval) {
854 static uint8_t pos = 0;
855 static uint16_t last_timer = 0;
858 int8_t increment = 1;
862 if (timer_elapsed(last_timer) < pgm_read_byte(&RGBLED_SNAKE_INTERVALS[interval / 2])) {
865 last_timer = timer_read();
866 for (i = 0; i < RGBLED_NUM; i++) {
870 for (j = 0; j < RGBLIGHT_EFFECT_SNAKE_LENGTH; j++) {
871 k = pos + j * increment;
876 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]);
881 if (increment == 1) {
883 pos = RGBLED_NUM - 1;
888 pos = (pos + 1) % RGBLED_NUM;
893 #ifdef RGBLIGHT_EFFECT_KNIGHT
894 __attribute__ ((weak))
895 const uint8_t RGBLED_KNIGHT_INTERVALS[] PROGMEM = {127, 63, 31};
897 void rgblight_effect_knight(uint8_t interval) {
898 static uint16_t last_timer = 0;
899 if (timer_elapsed(last_timer) < pgm_read_byte(&RGBLED_KNIGHT_INTERVALS[interval])) {
902 last_timer = timer_read();
904 static int8_t low_bound = 0;
905 static int8_t high_bound = RGBLIGHT_EFFECT_KNIGHT_LENGTH - 1;
906 static int8_t increment = 1;
909 // Set all the LEDs to 0
910 for (i = 0; i < RGBLED_NUM; i++) {
915 // Determine which LEDs should be lit up
916 for (i = 0; i < RGBLIGHT_EFFECT_KNIGHT_LED_NUM; i++) {
917 cur = (i + RGBLIGHT_EFFECT_KNIGHT_OFFSET) % RGBLED_NUM;
919 if (i >= low_bound && i <= high_bound) {
920 sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[cur]);
929 // Move from low_bound to high_bound changing the direction we increment each
930 // time a boundary is hit.
931 low_bound += increment;
932 high_bound += increment;
934 if (high_bound <= 0 || low_bound >= RGBLIGHT_EFFECT_KNIGHT_LED_NUM - 1) {
935 increment = -increment;
940 #ifdef RGBLIGHT_EFFECT_CHRISTMAS
941 void rgblight_effect_christmas(void) {
942 static uint16_t current_offset = 0;
943 static uint16_t last_timer = 0;
946 if (timer_elapsed(last_timer) < RGBLIGHT_EFFECT_CHRISTMAS_INTERVAL) {
949 last_timer = timer_read();
950 current_offset = (current_offset + 1) % 2;
951 for (i = 0; i < RGBLED_NUM; i++) {
952 hue = 0 + ((i/RGBLIGHT_EFFECT_CHRISTMAS_STEP + current_offset) % 2) * 120;
953 sethsv(hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i]);
959 #ifdef RGBLIGHT_EFFECT_RGB_TEST
960 __attribute__ ((weak))
961 const uint16_t RGBLED_RGBTEST_INTERVALS[] PROGMEM = {1024};
963 void rgblight_effect_rgbtest(void) {
964 static uint8_t pos = 0;
965 static uint16_t last_timer = 0;
966 static uint8_t maxval = 0;
967 uint8_t g; uint8_t r; uint8_t b;
969 if (timer_elapsed(last_timer) < pgm_read_word(&RGBLED_RGBTEST_INTERVALS[0])) {
975 sethsv(0, 255, RGBLIGHT_LIMIT_VAL, &tmp_led);
978 last_timer = timer_read();
981 case 0: r = maxval; break;
982 case 1: g = maxval; break;
983 case 2: b = maxval; break;
985 rgblight_setrgb(r, g, b);
990 #ifdef RGBLIGHT_EFFECT_ALTERNATING
991 void rgblight_effect_alternating(void){
992 static uint16_t last_timer = 0;
993 static uint16_t pos = 0;
994 if (timer_elapsed(last_timer) < 500) {
997 last_timer = timer_read();
999 for(int i = 0; i<RGBLED_NUM; i++){
1000 if(i<RGBLED_NUM/2 && pos){
1001 sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i]);
1002 }else if (i>=RGBLED_NUM/2 && !pos){
1003 sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i]);
1005 sethsv(rgblight_config.hue, rgblight_config.sat, 0, (LED_TYPE *)&led[i]);
1009 pos = (pos + 1) % 2;