Lets split eh (#3120)
[jackhill/qmk/firmware.git] / quantum / rgblight.c
CommitLineData
23839b8c 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 */
ad49db8c 16#include <math.h>
ade22f8e
JH
17#ifdef __AVR__
18 #include <avr/eeprom.h>
19 #include <avr/interrupt.h>
20#endif
21#include "wait.h"
0a40654b
YL
22#include "progmem.h"
23#include "timer.h"
24#include "rgblight.h"
25#include "debug.h"
f113f954 26#include "led_tables.h"
0a40654b 27
2038a515 28#ifndef RGBLIGHT_LIMIT_VAL
29#define RGBLIGHT_LIMIT_VAL 255
30#endif
31
afacd423 32#define MIN(a,b) (((a)<(b))?(a):(b))
33#define MAX(a,b) (((a)>(b))?(a):(b))
34
9b0e21f8 35__attribute__ ((weak))
0a40654b 36const uint8_t RGBLED_BREATHING_INTERVALS[] PROGMEM = {30, 20, 10, 5};
9b0e21f8 37__attribute__ ((weak))
0a40654b 38const uint8_t RGBLED_RAINBOW_MOOD_INTERVALS[] PROGMEM = {120, 60, 30};
9b0e21f8 39__attribute__ ((weak))
0a40654b 40const uint8_t RGBLED_RAINBOW_SWIRL_INTERVALS[] PROGMEM = {100, 50, 20};
9b0e21f8 41__attribute__ ((weak))
0a40654b 42const uint8_t RGBLED_SNAKE_INTERVALS[] PROGMEM = {100, 50, 20};
9b0e21f8 43__attribute__ ((weak))
4580d3a7 44const uint8_t RGBLED_KNIGHT_INTERVALS[] PROGMEM = {127, 63, 31};
a7882b1f 45__attribute__ ((weak))
46const uint16_t RGBLED_GRADIENT_RANGES[] PROGMEM = {360, 240, 180, 120, 90};
52297346
TI
47__attribute__ ((weak))
48const uint16_t RGBLED_RGBTEST_INTERVALS[] PROGMEM = {1024};
0a40654b
YL
49
50rgblight_config_t rgblight_config;
0a40654b 51
e9f74875 52LED_TYPE led[RGBLED_NUM];
e9f74875 53bool rgblight_timer_enabled = false;
0a40654b 54
e9f74875 55void sethsv(uint16_t hue, uint8_t sat, uint8_t val, LED_TYPE *led1) {
ea2d2f5d 56 uint8_t r = 0, g = 0, b = 0, base, color;
0a40654b 57
2038a515 58 if (val > RGBLIGHT_LIMIT_VAL) {
6c24e28b 59 val=RGBLIGHT_LIMIT_VAL; // limit the val
2038a515 60 }
6c24e28b 61
3a860c4b
JO
62 if (sat == 0) { // Acromatic color (gray). Hue doesn't mind.
63 r = val;
64 g = val;
65 b = val;
66 } else {
67 base = ((255 - sat) * val) >> 8;
ea2d2f5d 68 color = (val - base) * (hue % 60) / 60;
3a860c4b
JO
69
70 switch (hue / 60) {
71 case 0:
72 r = val;
ea2d2f5d 73 g = base + color;
3a860c4b
JO
74 b = base;
75 break;
76 case 1:
ea2d2f5d 77 r = val - color;
3a860c4b
JO
78 g = val;
79 b = base;
80 break;
81 case 2:
82 r = base;
83 g = val;
ea2d2f5d 84 b = base + color;
3a860c4b
JO
85 break;
86 case 3:
87 r = base;
ea2d2f5d 88 g = val - color;
3a860c4b
JO
89 b = val;
90 break;
91 case 4:
ea2d2f5d 92 r = base + color;
3a860c4b
JO
93 g = base;
94 b = val;
95 break;
96 case 5:
97 r = val;
98 g = base;
ea2d2f5d 99 b = val - color;
3a860c4b
JO
100 break;
101 }
102 }
f113f954
FS
103 r = pgm_read_byte(&CIE1931_CURVE[r]);
104 g = pgm_read_byte(&CIE1931_CURVE[g]);
105 b = pgm_read_byte(&CIE1931_CURVE[b]);
ea2d2f5d
JO
106
107 setrgb(r, g, b, led1);
0a40654b
YL
108}
109
e9f74875 110void setrgb(uint8_t r, uint8_t g, uint8_t b, LED_TYPE *led1) {
0a40654b
YL
111 (*led1).r = r;
112 (*led1).g = g;
113 (*led1).b = b;
114}
115
116
117uint32_t eeconfig_read_rgblight(void) {
ade22f8e
JH
118 #ifdef __AVR__
119 return eeprom_read_dword(EECONFIG_RGBLIGHT);
120 #else
121 return 0;
122 #endif
0a40654b 123}
620ac4b2 124void eeconfig_update_rgblight(uint32_t val) {
ade22f8e
JH
125 #ifdef __AVR__
126 eeprom_update_dword(EECONFIG_RGBLIGHT, val);
127 #endif
0a40654b 128}
620ac4b2 129void eeconfig_update_rgblight_default(void) {
0fab3bbd 130 //dprintf("eeconfig_update_rgblight_default\n");
3a860c4b
JO
131 rgblight_config.enable = 1;
132 rgblight_config.mode = 1;
e9f74875
JH
133 rgblight_config.hue = 0;
134 rgblight_config.sat = 255;
2038a515 135 rgblight_config.val = RGBLIGHT_LIMIT_VAL;
afacd423 136 rgblight_config.speed = 0;
3a860c4b 137 eeconfig_update_rgblight(rgblight_config.raw);
0a40654b
YL
138}
139void eeconfig_debug_rgblight(void) {
3a860c4b
JO
140 dprintf("rgblight_config eprom\n");
141 dprintf("rgblight_config.enable = %d\n", rgblight_config.enable);
142 dprintf("rghlight_config.mode = %d\n", rgblight_config.mode);
143 dprintf("rgblight_config.hue = %d\n", rgblight_config.hue);
144 dprintf("rgblight_config.sat = %d\n", rgblight_config.sat);
145 dprintf("rgblight_config.val = %d\n", rgblight_config.val);
afacd423 146 dprintf("rgblight_config.speed = %d\n", rgblight_config.speed);
0a40654b
YL
147}
148
149void rgblight_init(void) {
150 debug_enable = 1; // Debug ON!
3a860c4b 151 dprintf("rgblight_init called.\n");
3a860c4b 152 dprintf("rgblight_init start!\n");
0a40654b 153 if (!eeconfig_is_enabled()) {
3a860c4b 154 dprintf("rgblight_init eeconfig is not enabled.\n");
0a40654b 155 eeconfig_init();
3a860c4b 156 eeconfig_update_rgblight_default();
0a40654b
YL
157 }
158 rgblight_config.raw = eeconfig_read_rgblight();
3a860c4b
JO
159 if (!rgblight_config.mode) {
160 dprintf("rgblight_init rgblight_config.mode = 0. Write default values to EEPROM.\n");
161 eeconfig_update_rgblight_default();
162 rgblight_config.raw = eeconfig_read_rgblight();
163 }
164 eeconfig_debug_rgblight(); // display current eeprom values
0a40654b 165
3774a7fc 166 #ifdef RGBLIGHT_ANIMATIONS
3a860c4b
JO
167 rgblight_timer_init(); // setup the timer
168 #endif
0a40654b
YL
169
170 if (rgblight_config.enable) {
751719e6 171 rgblight_mode_noeeprom(rgblight_config.mode);
0a40654b
YL
172 }
173}
174
2e23689b
JH
175void rgblight_update_dword(uint32_t dword) {
176 rgblight_config.raw = dword;
177 eeconfig_update_rgblight(rgblight_config.raw);
178 if (rgblight_config.enable)
179 rgblight_mode(rgblight_config.mode);
180 else {
181 #ifdef RGBLIGHT_ANIMATIONS
182 rgblight_timer_disable();
183 #endif
184 rgblight_set();
185 }
186}
187
0a40654b 188void rgblight_increase(void) {
3a860c4b 189 uint8_t mode = 0;
0a40654b
YL
190 if (rgblight_config.mode < RGBLIGHT_MODES) {
191 mode = rgblight_config.mode + 1;
192 }
3a860c4b 193 rgblight_mode(mode);
0a40654b 194}
0a40654b 195void rgblight_decrease(void) {
3a860c4b
JO
196 uint8_t mode = 0;
197 // Mode will never be < 1. If it ever is, eeprom needs to be initialized.
198 if (rgblight_config.mode > 1) {
199 mode = rgblight_config.mode - 1;
0a40654b 200 }
3a860c4b 201 rgblight_mode(mode);
0a40654b 202}
0a40654b 203void rgblight_step(void) {
3a860c4b 204 uint8_t mode = 0;
0a40654b
YL
205 mode = rgblight_config.mode + 1;
206 if (mode > RGBLIGHT_MODES) {
207 mode = 1;
208 }
3a860c4b 209 rgblight_mode(mode);
0a40654b 210}
5a1b68d5 211void rgblight_step_reverse(void) {
212 uint8_t mode = 0;
213 mode = rgblight_config.mode - 1;
214 if (mode < 1) {
215 mode = RGBLIGHT_MODES;
216 }
217 rgblight_mode(mode);
218}
0a40654b 219
4580d3a7 220uint32_t rgblight_get_mode(void) {
221 if (!rgblight_config.enable) {
222 return false;
223 }
224
225 return rgblight_config.mode;
226}
227
751719e6 228void rgblight_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) {
3a860c4b
JO
229 if (!rgblight_config.enable) {
230 return;
231 }
232 if (mode < 1) {
233 rgblight_config.mode = 1;
234 } else if (mode > RGBLIGHT_MODES) {
235 rgblight_config.mode = RGBLIGHT_MODES;
236 } else {
237 rgblight_config.mode = mode;
238 }
751719e6
DJ
239 if (write_to_eeprom) {
240 eeconfig_update_rgblight(rgblight_config.raw);
241 xprintf("rgblight mode [EEPROM]: %u\n", rgblight_config.mode);
242 } else {
243 xprintf("rgblight mode [NOEEPROM]: %u\n", rgblight_config.mode);
244 }
3a860c4b 245 if (rgblight_config.mode == 1) {
3774a7fc 246 #ifdef RGBLIGHT_ANIMATIONS
3a860c4b
JO
247 rgblight_timer_disable();
248 #endif
52297346
TI
249 } else if ((rgblight_config.mode >= 2 && rgblight_config.mode <= 24) ||
250 rgblight_config.mode == 35 ) {
3a860c4b
JO
251 // MODE 2-5, breathing
252 // MODE 6-8, rainbow mood
253 // MODE 9-14, rainbow swirl
254 // MODE 15-20, snake
255 // MODE 21-23, knight
4580d3a7 256 // MODE 24, xmas
52297346 257 // MODE 35 RGB test
3a860c4b 258
3774a7fc 259 #ifdef RGBLIGHT_ANIMATIONS
3a860c4b
JO
260 rgblight_timer_enable();
261 #endif
a7882b1f 262 } else if (rgblight_config.mode >= 25 && rgblight_config.mode <= 34) {
263 // MODE 25-34, static gradient
264
265 #ifdef RGBLIGHT_ANIMATIONS
266 rgblight_timer_disable();
267 #endif
3a860c4b 268 }
751719e6
DJ
269 rgblight_sethsv_noeeprom(rgblight_config.hue, rgblight_config.sat, rgblight_config.val);
270}
271
272void rgblight_mode(uint8_t mode) {
273 rgblight_mode_eeprom_helper(mode, true);
274}
275
276void rgblight_mode_noeeprom(uint8_t mode) {
277 rgblight_mode_eeprom_helper(mode, false);
0a40654b
YL
278}
279
751719e6 280
0a40654b 281void rgblight_toggle(void) {
751719e6 282 xprintf("rgblight toggle [EEPROM]: rgblight_config.enable = %u\n", !rgblight_config.enable);
3a860c4b 283 if (rgblight_config.enable) {
16546ee0
CG
284 rgblight_disable();
285 }
286 else {
287 rgblight_enable();
3a860c4b 288 }
0a40654b
YL
289}
290
751719e6
DJ
291void rgblight_toggle_noeeprom(void) {
292 xprintf("rgblight toggle [NOEEPROM]: rgblight_config.enable = %u\n", !rgblight_config.enable);
293 if (rgblight_config.enable) {
294 rgblight_disable_noeeprom();
295 }
296 else {
297 rgblight_enable_noeeprom();
298 }
299}
300
285c5a91
EZ
301void rgblight_enable(void) {
302 rgblight_config.enable = 1;
751719e6
DJ
303 // No need to update EEPROM here. rgblight_mode() will do that, actually
304 //eeconfig_update_rgblight(rgblight_config.raw);
305 xprintf("rgblight enable [EEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable);
285c5a91
EZ
306 rgblight_mode(rgblight_config.mode);
307}
308
751719e6
DJ
309void rgblight_enable_noeeprom(void) {
310 rgblight_config.enable = 1;
311 xprintf("rgblight enable [NOEEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable);
312 rgblight_mode_noeeprom(rgblight_config.mode);
313}
314
16546ee0
CG
315void rgblight_disable(void) {
316 rgblight_config.enable = 0;
317 eeconfig_update_rgblight(rgblight_config.raw);
751719e6 318 xprintf("rgblight disable [EEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable);
16546ee0
CG
319 #ifdef RGBLIGHT_ANIMATIONS
320 rgblight_timer_disable();
321 #endif
ade22f8e 322 wait_ms(50);
16546ee0
CG
323 rgblight_set();
324}
325
751719e6
DJ
326void rgblight_disable_noeeprom(void) {
327 rgblight_config.enable = 0;
328 xprintf("rgblight disable [noEEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable);
329 #ifdef RGBLIGHT_ANIMATIONS
330 rgblight_timer_disable();
331 #endif
332 _delay_ms(50);
333 rgblight_set();
334}
335
336
afacd423 337// Deals with the messy details of incrementing an integer
338uint8_t increment( uint8_t value, uint8_t step, uint8_t min, uint8_t max ) {
339 int16_t new_value = value;
340 new_value += step;
341 return MIN( MAX( new_value, min ), max );
342}
343
344uint8_t decrement( uint8_t value, uint8_t step, uint8_t min, uint8_t max ) {
345 int16_t new_value = value;
346 new_value -= step;
347 return MIN( MAX( new_value, min ), max );
348}
0a40654b 349
3a860c4b
JO
350void rgblight_increase_hue(void) {
351 uint16_t hue;
0a40654b
YL
352 hue = (rgblight_config.hue+RGBLIGHT_HUE_STEP) % 360;
353 rgblight_sethsv(hue, rgblight_config.sat, rgblight_config.val);
354}
3a860c4b
JO
355void rgblight_decrease_hue(void) {
356 uint16_t hue;
357 if (rgblight_config.hue-RGBLIGHT_HUE_STEP < 0) {
358 hue = (rgblight_config.hue + 360 - RGBLIGHT_HUE_STEP) % 360;
359 } else {
360 hue = (rgblight_config.hue - RGBLIGHT_HUE_STEP) % 360;
361 }
0a40654b
YL
362 rgblight_sethsv(hue, rgblight_config.sat, rgblight_config.val);
363}
364void rgblight_increase_sat(void) {
3a860c4b 365 uint8_t sat;
0a40654b
YL
366 if (rgblight_config.sat + RGBLIGHT_SAT_STEP > 255) {
367 sat = 255;
368 } else {
3a860c4b 369 sat = rgblight_config.sat + RGBLIGHT_SAT_STEP;
0a40654b
YL
370 }
371 rgblight_sethsv(rgblight_config.hue, sat, rgblight_config.val);
372}
3a860c4b
JO
373void rgblight_decrease_sat(void) {
374 uint8_t sat;
0a40654b
YL
375 if (rgblight_config.sat - RGBLIGHT_SAT_STEP < 0) {
376 sat = 0;
377 } else {
3a860c4b 378 sat = rgblight_config.sat - RGBLIGHT_SAT_STEP;
0a40654b
YL
379 }
380 rgblight_sethsv(rgblight_config.hue, sat, rgblight_config.val);
381}
3a860c4b
JO
382void rgblight_increase_val(void) {
383 uint8_t val;
2038a515 384 if (rgblight_config.val + RGBLIGHT_VAL_STEP > RGBLIGHT_LIMIT_VAL) {
385 val = RGBLIGHT_LIMIT_VAL;
0a40654b 386 } else {
3a860c4b 387 val = rgblight_config.val + RGBLIGHT_VAL_STEP;
0a40654b
YL
388 }
389 rgblight_sethsv(rgblight_config.hue, rgblight_config.sat, val);
390}
391void rgblight_decrease_val(void) {
3a860c4b 392 uint8_t val;
0a40654b
YL
393 if (rgblight_config.val - RGBLIGHT_VAL_STEP < 0) {
394 val = 0;
395 } else {
3a860c4b 396 val = rgblight_config.val - RGBLIGHT_VAL_STEP;
0a40654b
YL
397 }
398 rgblight_sethsv(rgblight_config.hue, rgblight_config.sat, val);
399}
afacd423 400void rgblight_increase_speed(void) {
401 rgblight_config.speed = increment( rgblight_config.speed, 1, 0, 3 );
402 eeconfig_update_rgblight(rgblight_config.raw);//EECONFIG needs to be increased to support this
403}
404
405void rgblight_decrease_speed(void) {
406 rgblight_config.speed = decrement( rgblight_config.speed, 1, 0, 3 );
407 eeconfig_update_rgblight(rgblight_config.raw);//EECONFIG needs to be increased to support this
408}
0a40654b 409
751719e6 410void rgblight_sethsv_noeeprom_old(uint16_t hue, uint8_t sat, uint8_t val) {
0a40654b 411 if (rgblight_config.enable) {
e9f74875 412 LED_TYPE tmp_led;
0a40654b 413 sethsv(hue, sat, val, &tmp_led);
0a40654b
YL
414 // dprintf("rgblight set hue [MEMORY]: %u,%u,%u\n", inmem_config.hue, inmem_config.sat, inmem_config.val);
415 rgblight_setrgb(tmp_led.r, tmp_led.g, tmp_led.b);
416 }
417}
751719e6
DJ
418
419void rgblight_sethsv_eeprom_helper(uint16_t hue, uint8_t sat, uint8_t val, bool write_to_eeprom) {
0a40654b 420 if (rgblight_config.enable) {
3a860c4b
JO
421 if (rgblight_config.mode == 1) {
422 // same static color
751719e6
DJ
423 LED_TYPE tmp_led;
424 sethsv(hue, sat, val, &tmp_led);
425 rgblight_setrgb(tmp_led.r, tmp_led.g, tmp_led.b);
3a860c4b
JO
426 } else {
427 // all LEDs in same color
428 if (rgblight_config.mode >= 2 && rgblight_config.mode <= 5) {
429 // breathing mode, ignore the change of val, use in memory value instead
430 val = rgblight_config.val;
431 } else if (rgblight_config.mode >= 6 && rgblight_config.mode <= 14) {
432 // rainbow mood and rainbow swirl, ignore the change of hue
433 hue = rgblight_config.hue;
a7882b1f 434 } else if (rgblight_config.mode >= 25 && rgblight_config.mode <= 34) {
435 // static gradient
436 uint16_t _hue;
437 int8_t direction = ((rgblight_config.mode - 25) % 2) ? -1 : 1;
438 uint16_t range = pgm_read_word(&RGBLED_GRADIENT_RANGES[(rgblight_config.mode - 25) / 2]);
439 for (uint8_t i = 0; i < RGBLED_NUM; i++) {
440 _hue = (range / RGBLED_NUM * i * direction + hue + 360) % 360;
441 dprintf("rgblight rainbow set hsv: %u,%u,%d,%u\n", i, _hue, direction, range);
442 sethsv(_hue, sat, val, (LED_TYPE *)&led[i]);
443 }
444 rgblight_set();
3a860c4b
JO
445 }
446 }
447 rgblight_config.hue = hue;
448 rgblight_config.sat = sat;
449 rgblight_config.val = val;
751719e6
DJ
450 if (write_to_eeprom) {
451 eeconfig_update_rgblight(rgblight_config.raw);
452 xprintf("rgblight set hsv [EEPROM]: %u,%u,%u\n", rgblight_config.hue, rgblight_config.sat, rgblight_config.val);
453 } else {
454 xprintf("rgblight set hsv [NOEEPROM]: %u,%u,%u\n", rgblight_config.hue, rgblight_config.sat, rgblight_config.val);
455 }
3a860c4b
JO
456 }
457}
458
751719e6
DJ
459void rgblight_sethsv(uint16_t hue, uint8_t sat, uint8_t val) {
460 rgblight_sethsv_eeprom_helper(hue, sat, val, true);
461}
462
463void rgblight_sethsv_noeeprom(uint16_t hue, uint8_t sat, uint8_t val) {
464 rgblight_sethsv_eeprom_helper(hue, sat, val, false);
465}
466
12e66330 467uint16_t rgblight_get_hue(void) {
468 return rgblight_config.hue;
469}
470
471uint8_t rgblight_get_sat(void) {
472 return rgblight_config.sat;
473}
474
475uint8_t rgblight_get_val(void) {
476 return rgblight_config.val;
477}
478
3a860c4b 479void rgblight_setrgb(uint8_t r, uint8_t g, uint8_t b) {
16546ee0
CG
480 if (!rgblight_config.enable) { return; }
481
3a860c4b 482 for (uint8_t i = 0; i < RGBLED_NUM; i++) {
0a40654b
YL
483 led[i].r = r;
484 led[i].g = g;
485 led[i].b = b;
486 }
487 rgblight_set();
0a40654b
YL
488}
489
16546ee0
CG
490void rgblight_setrgb_at(uint8_t r, uint8_t g, uint8_t b, uint8_t index) {
491 if (!rgblight_config.enable || index >= RGBLED_NUM) { return; }
492
493 led[index].r = r;
494 led[index].g = g;
495 led[index].b = b;
496 rgblight_set();
497}
498
499void rgblight_sethsv_at(uint16_t hue, uint8_t sat, uint8_t val, uint8_t index) {
500 if (!rgblight_config.enable) { return; }
501
502 LED_TYPE tmp_led;
503 sethsv(hue, sat, val, &tmp_led);
504 rgblight_setrgb_at(tmp_led.r, tmp_led.g, tmp_led.b, index);
505}
506
d4cd5dda 507#ifndef RGBLIGHT_CUSTOM_DRIVER
0a40654b 508void rgblight_set(void) {
3a860c4b 509 if (rgblight_config.enable) {
b8679bbe
JH
510 #ifdef RGBW
511 ws2812_setleds_rgbw(led, RGBLED_NUM);
512 #else
513 ws2812_setleds(led, RGBLED_NUM);
514 #endif
3a860c4b
JO
515 } else {
516 for (uint8_t i = 0; i < RGBLED_NUM; i++) {
517 led[i].r = 0;
518 led[i].g = 0;
519 led[i].b = 0;
520 }
b8679bbe
JH
521 #ifdef RGBW
522 ws2812_setleds_rgbw(led, RGBLED_NUM);
523 #else
524 ws2812_setleds(led, RGBLED_NUM);
525 #endif
3a860c4b 526 }
0a40654b 527}
d4cd5dda 528#endif
0a40654b 529
3774a7fc 530#ifdef RGBLIGHT_ANIMATIONS
57e08eb8 531
0a40654b
YL
532// Animation timer -- AVR Timer3
533void rgblight_timer_init(void) {
e9f74875
JH
534 // static uint8_t rgblight_timer_is_init = 0;
535 // if (rgblight_timer_is_init) {
536 // return;
537 // }
538 // rgblight_timer_is_init = 1;
539 // /* Timer 3 setup */
540 // TCCR3B = _BV(WGM32) // CTC mode OCR3A as TOP
541 // | _BV(CS30); // Clock selelct: clk/1
542 // /* Set TOP value */
543 // uint8_t sreg = SREG;
544 // cli();
545 // OCR3AH = (RGBLED_TIMER_TOP >> 8) & 0xff;
546 // OCR3AL = RGBLED_TIMER_TOP & 0xff;
547 // SREG = sreg;
548
549 rgblight_timer_enabled = true;
0a40654b
YL
550}
551void rgblight_timer_enable(void) {
e9f74875 552 rgblight_timer_enabled = true;
3a860c4b 553 dprintf("TIMER3 enabled.\n");
0a40654b
YL
554}
555void rgblight_timer_disable(void) {
e9f74875 556 rgblight_timer_enabled = false;
3a860c4b 557 dprintf("TIMER3 disabled.\n");
0a40654b
YL
558}
559void rgblight_timer_toggle(void) {
e9f74875 560 rgblight_timer_enabled ^= rgblight_timer_enabled;
3a860c4b 561 dprintf("TIMER3 toggled.\n");
0a40654b
YL
562}
563
4094544d
EZ
564void rgblight_show_solid_color(uint8_t r, uint8_t g, uint8_t b) {
565 rgblight_enable();
566 rgblight_mode(1);
567 rgblight_setrgb(r, g, b);
568}
569
e9f74875
JH
570void rgblight_task(void) {
571 if (rgblight_timer_enabled) {
572 // mode = 1, static light, do nothing here
573 if (rgblight_config.mode >= 2 && rgblight_config.mode <= 5) {
574 // mode = 2 to 5, breathing mode
575 rgblight_effect_breathing(rgblight_config.mode - 2);
576 } else if (rgblight_config.mode >= 6 && rgblight_config.mode <= 8) {
577 // mode = 6 to 8, rainbow mood mod
578 rgblight_effect_rainbow_mood(rgblight_config.mode - 6);
579 } else if (rgblight_config.mode >= 9 && rgblight_config.mode <= 14) {
580 // mode = 9 to 14, rainbow swirl mode
581 rgblight_effect_rainbow_swirl(rgblight_config.mode - 9);
582 } else if (rgblight_config.mode >= 15 && rgblight_config.mode <= 20) {
583 // mode = 15 to 20, snake mode
584 rgblight_effect_snake(rgblight_config.mode - 15);
585 } else if (rgblight_config.mode >= 21 && rgblight_config.mode <= 23) {
586 // mode = 21 to 23, knight mode
587 rgblight_effect_knight(rgblight_config.mode - 21);
0e548f8b 588 } else if (rgblight_config.mode == 24) {
cae269b0
JH
589 // mode = 24, christmas mode
590 rgblight_effect_christmas();
52297346
TI
591 } else if (rgblight_config.mode == 35) {
592 // mode = 35, RGB test
593 rgblight_effect_rgbtest();
e9f74875 594 }
3a860c4b
JO
595 }
596}
597
598// Effects
0a40654b 599void rgblight_effect_breathing(uint8_t interval) {
3a860c4b
JO
600 static uint8_t pos = 0;
601 static uint16_t last_timer = 0;
ad49db8c 602 float val;
0a40654b 603
3a860c4b
JO
604 if (timer_elapsed(last_timer) < pgm_read_byte(&RGBLED_BREATHING_INTERVALS[interval])) {
605 return;
606 }
607 last_timer = timer_read();
0a40654b 608
ad49db8c 609
610 // http://sean.voisen.org/blog/2011/10/breathing-led-with-arduino/
611 val = (exp(sin((pos/255.0)*M_PI)) - RGBLIGHT_EFFECT_BREATHE_CENTER/M_E)*(RGBLIGHT_EFFECT_BREATHE_MAX/(M_E-1/M_E));
751719e6 612 rgblight_sethsv_noeeprom_old(rgblight_config.hue, rgblight_config.sat, val);
3a860c4b 613 pos = (pos + 1) % 256;
0a40654b 614}
0a40654b 615void rgblight_effect_rainbow_mood(uint8_t interval) {
3a860c4b
JO
616 static uint16_t current_hue = 0;
617 static uint16_t last_timer = 0;
0a40654b 618
3a860c4b
JO
619 if (timer_elapsed(last_timer) < pgm_read_byte(&RGBLED_RAINBOW_MOOD_INTERVALS[interval])) {
620 return;
621 }
622 last_timer = timer_read();
751719e6 623 rgblight_sethsv_noeeprom_old(current_hue, rgblight_config.sat, rgblight_config.val);
3a860c4b 624 current_hue = (current_hue + 1) % 360;
0a40654b 625}
0a40654b 626void rgblight_effect_rainbow_swirl(uint8_t interval) {
3a860c4b
JO
627 static uint16_t current_hue = 0;
628 static uint16_t last_timer = 0;
629 uint16_t hue;
630 uint8_t i;
da887ea4 631 if (timer_elapsed(last_timer) < pgm_read_byte(&RGBLED_RAINBOW_SWIRL_INTERVALS[interval / 2])) {
3a860c4b
JO
632 return;
633 }
634 last_timer = timer_read();
635 for (i = 0; i < RGBLED_NUM; i++) {
636 hue = (360 / RGBLED_NUM * i + current_hue) % 360;
e9f74875 637 sethsv(hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i]);
3a860c4b
JO
638 }
639 rgblight_set();
640
641 if (interval % 2) {
642 current_hue = (current_hue + 1) % 360;
643 } else {
644 if (current_hue - 1 < 0) {
645 current_hue = 359;
646 } else {
647 current_hue = current_hue - 1;
648 }
649 }
0a40654b
YL
650}
651void rgblight_effect_snake(uint8_t interval) {
3a860c4b
JO
652 static uint8_t pos = 0;
653 static uint16_t last_timer = 0;
654 uint8_t i, j;
655 int8_t k;
899c88cd 656 int8_t increment = 1;
3a860c4b 657 if (interval % 2) {
899c88cd 658 increment = -1;
3a860c4b
JO
659 }
660 if (timer_elapsed(last_timer) < pgm_read_byte(&RGBLED_SNAKE_INTERVALS[interval / 2])) {
661 return;
662 }
663 last_timer = timer_read();
664 for (i = 0; i < RGBLED_NUM; i++) {
665 led[i].r = 0;
666 led[i].g = 0;
667 led[i].b = 0;
668 for (j = 0; j < RGBLIGHT_EFFECT_SNAKE_LENGTH; j++) {
899c88cd 669 k = pos + j * increment;
3a860c4b
JO
670 if (k < 0) {
671 k = k + RGBLED_NUM;
672 }
673 if (i == k) {
e9f74875 674 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]);
3a860c4b
JO
675 }
676 }
677 }
678 rgblight_set();
899c88cd 679 if (increment == 1) {
3a860c4b
JO
680 if (pos - 1 < 0) {
681 pos = RGBLED_NUM - 1;
682 } else {
683 pos -= 1;
684 }
685 } else {
686 pos = (pos + 1) % RGBLED_NUM;
687 }
0a40654b 688}
0a40654b 689void rgblight_effect_knight(uint8_t interval) {
3a860c4b 690 static uint16_t last_timer = 0;
3a860c4b
JO
691 if (timer_elapsed(last_timer) < pgm_read_byte(&RGBLED_KNIGHT_INTERVALS[interval])) {
692 return;
693 }
694 last_timer = timer_read();
4edfa97e
DS
695
696 static int8_t low_bound = 0;
697 static int8_t high_bound = RGBLIGHT_EFFECT_KNIGHT_LENGTH - 1;
698 static int8_t increment = 1;
699 uint8_t i, cur;
700
4580d3a7 701 // Set all the LEDs to 0
94f8b758 702 for (i = 0; i < RGBLED_NUM; i++) {
4580d3a7 703 led[i].r = 0;
704 led[i].g = 0;
705 led[i].b = 0;
706 }
707 // Determine which LEDs should be lit up
708 for (i = 0; i < RGBLIGHT_EFFECT_KNIGHT_LED_NUM; i++) {
94f8b758 709 cur = (i + RGBLIGHT_EFFECT_KNIGHT_OFFSET) % RGBLED_NUM;
4edfa97e
DS
710
711 if (i >= low_bound && i <= high_bound) {
712 sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[cur]);
3a860c4b 713 } else {
4edfa97e
DS
714 led[cur].r = 0;
715 led[cur].g = 0;
716 led[cur].b = 0;
3a860c4b
JO
717 }
718 }
4edfa97e
DS
719 rgblight_set();
720
4580d3a7 721 // Move from low_bound to high_bound changing the direction we increment each
722 // time a boundary is hit.
4edfa97e
DS
723 low_bound += increment;
724 high_bound += increment;
725
4580d3a7 726 if (high_bound <= 0 || low_bound >= RGBLIGHT_EFFECT_KNIGHT_LED_NUM - 1) {
4edfa97e
DS
727 increment = -increment;
728 }
3a860c4b
JO
729}
730
cae269b0
JH
731
732void rgblight_effect_christmas(void) {
733 static uint16_t current_offset = 0;
734 static uint16_t last_timer = 0;
735 uint16_t hue;
736 uint8_t i;
0e548f8b 737 if (timer_elapsed(last_timer) < RGBLIGHT_EFFECT_CHRISTMAS_INTERVAL) {
cae269b0
JH
738 return;
739 }
740 last_timer = timer_read();
741 current_offset = (current_offset + 1) % 2;
742 for (i = 0; i < RGBLED_NUM; i++) {
0e548f8b 743 hue = 0 + ((i/RGBLIGHT_EFFECT_CHRISTMAS_STEP + current_offset) % 2) * 120;
cae269b0
JH
744 sethsv(hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i]);
745 }
746 rgblight_set();
747}
748
52297346
TI
749void rgblight_effect_rgbtest(void) {
750 static uint8_t pos = 0;
751 static uint16_t last_timer = 0;
752 static uint8_t maxval = 0;
753 uint8_t g; uint8_t r; uint8_t b;
754
755 if (timer_elapsed(last_timer) < pgm_read_word(&RGBLED_RGBTEST_INTERVALS[0])) {
756 return;
757 }
758
759 if( maxval == 0 ) {
760 LED_TYPE tmp_led;
761 sethsv(0, 255, RGBLIGHT_LIMIT_VAL, &tmp_led);
762 maxval = tmp_led.r;
763 }
764 last_timer = timer_read();
765 g = r = b = 0;
766 switch( pos ) {
767 case 0: r = maxval; break;
768 case 1: g = maxval; break;
769 case 2: b = maxval; break;
770 }
771 rgblight_setrgb(r, g, b);
772 pos = (pos + 1) % 3;
773}
774
775#endif /* RGBLIGHT_ANIMATIONS */