aboutsummaryrefslogtreecommitdiff
path: root/quantum/rgblight.c
diff options
context:
space:
mode:
Diffstat (limited to 'quantum/rgblight.c')
-rw-r--r--quantum/rgblight.c211
1 files changed, 157 insertions, 54 deletions
diff --git a/quantum/rgblight.c b/quantum/rgblight.c
index d550c5866..eff70aae1 100644
--- a/quantum/rgblight.c
+++ b/quantum/rgblight.c
@@ -1,3 +1,18 @@
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 */
1#include <avr/eeprom.h> 16#include <avr/eeprom.h>
2#include <avr/interrupt.h> 17#include <avr/interrupt.h>
3#include <util/delay.h> 18#include <util/delay.h>
@@ -66,14 +81,17 @@ __attribute__ ((weak))
66const uint8_t RGBLED_SNAKE_INTERVALS[] PROGMEM = {100, 50, 20}; 81const uint8_t RGBLED_SNAKE_INTERVALS[] PROGMEM = {100, 50, 20};
67__attribute__ ((weak)) 82__attribute__ ((weak))
68const uint8_t RGBLED_KNIGHT_INTERVALS[] PROGMEM = {100, 50, 20}; 83const uint8_t RGBLED_KNIGHT_INTERVALS[] PROGMEM = {100, 50, 20};
84__attribute__ ((weak))
85const uint16_t RGBLED_GRADIENT_RANGES[] PROGMEM = {360, 240, 180, 120, 90};
69 86
70rgblight_config_t rgblight_config; 87rgblight_config_t rgblight_config;
71rgblight_config_t inmem_config; 88rgblight_config_t inmem_config;
72struct cRGB led[RGBLED_NUM];
73uint8_t rgblight_inited = 0;
74 89
90LED_TYPE led[RGBLED_NUM];
91uint8_t rgblight_inited = 0;
92bool rgblight_timer_enabled = false;
75 93
76void sethsv(uint16_t hue, uint8_t sat, uint8_t val, struct cRGB *led1) { 94void sethsv(uint16_t hue, uint8_t sat, uint8_t val, LED_TYPE *led1) {
77 uint8_t r = 0, g = 0, b = 0, base, color; 95 uint8_t r = 0, g = 0, b = 0, base, color;
78 96
79 if (sat == 0) { // Acromatic color (gray). Hue doesn't mind. 97 if (sat == 0) { // Acromatic color (gray). Hue doesn't mind.
@@ -124,7 +142,7 @@ void sethsv(uint16_t hue, uint8_t sat, uint8_t val, struct cRGB *led1) {
124 setrgb(r, g, b, led1); 142 setrgb(r, g, b, led1);
125} 143}
126 144
127void setrgb(uint8_t r, uint8_t g, uint8_t b, struct cRGB *led1) { 145void setrgb(uint8_t r, uint8_t g, uint8_t b, LED_TYPE *led1) {
128 (*led1).r = r; 146 (*led1).r = r;
129 (*led1).g = g; 147 (*led1).g = g;
130 (*led1).b = b; 148 (*led1).b = b;
@@ -141,9 +159,9 @@ void eeconfig_update_rgblight_default(void) {
141 dprintf("eeconfig_update_rgblight_default\n"); 159 dprintf("eeconfig_update_rgblight_default\n");
142 rgblight_config.enable = 1; 160 rgblight_config.enable = 1;
143 rgblight_config.mode = 1; 161 rgblight_config.mode = 1;
144 rgblight_config.hue = 200; 162 rgblight_config.hue = 0;
145 rgblight_config.sat = 204; 163 rgblight_config.sat = 255;
146 rgblight_config.val = 204; 164 rgblight_config.val = 255;
147 eeconfig_update_rgblight(rgblight_config.raw); 165 eeconfig_update_rgblight(rgblight_config.raw);
148} 166}
149void eeconfig_debug_rgblight(void) { 167void eeconfig_debug_rgblight(void) {
@@ -173,7 +191,7 @@ void rgblight_init(void) {
173 } 191 }
174 eeconfig_debug_rgblight(); // display current eeprom values 192 eeconfig_debug_rgblight(); // display current eeprom values
175 193
176 #if !defined(AUDIO_ENABLE) && defined(RGBLIGHT_TIMER) 194 #ifdef RGBLIGHT_ANIMATIONS
177 rgblight_timer_init(); // setup the timer 195 rgblight_timer_init(); // setup the timer
178 #endif 196 #endif
179 197
@@ -182,6 +200,19 @@ void rgblight_init(void) {
182 } 200 }
183} 201}
184 202
203void rgblight_update_dword(uint32_t dword) {
204 rgblight_config.raw = dword;
205 eeconfig_update_rgblight(rgblight_config.raw);
206 if (rgblight_config.enable)
207 rgblight_mode(rgblight_config.mode);
208 else {
209 #ifdef RGBLIGHT_ANIMATIONS
210 rgblight_timer_disable();
211 #endif
212 rgblight_set();
213 }
214}
215
185void rgblight_increase(void) { 216void rgblight_increase(void) {
186 uint8_t mode = 0; 217 uint8_t mode = 0;
187 if (rgblight_config.mode < RGBLIGHT_MODES) { 218 if (rgblight_config.mode < RGBLIGHT_MODES) {
@@ -205,6 +236,14 @@ void rgblight_step(void) {
205 } 236 }
206 rgblight_mode(mode); 237 rgblight_mode(mode);
207} 238}
239void rgblight_step_reverse(void) {
240 uint8_t mode = 0;
241 mode = rgblight_config.mode - 1;
242 if (mode < 1) {
243 mode = RGBLIGHT_MODES;
244 }
245 rgblight_mode(mode);
246}
208 247
209void rgblight_mode(uint8_t mode) { 248void rgblight_mode(uint8_t mode) {
210 if (!rgblight_config.enable) { 249 if (!rgblight_config.enable) {
@@ -220,19 +259,25 @@ void rgblight_mode(uint8_t mode) {
220 eeconfig_update_rgblight(rgblight_config.raw); 259 eeconfig_update_rgblight(rgblight_config.raw);
221 xprintf("rgblight mode: %u\n", rgblight_config.mode); 260 xprintf("rgblight mode: %u\n", rgblight_config.mode);
222 if (rgblight_config.mode == 1) { 261 if (rgblight_config.mode == 1) {
223 #if !defined(AUDIO_ENABLE) && defined(RGBLIGHT_TIMER) 262 #ifdef RGBLIGHT_ANIMATIONS
224 rgblight_timer_disable(); 263 rgblight_timer_disable();
225 #endif 264 #endif
226 } else if (rgblight_config.mode >= 2 && rgblight_config.mode <= 23) { 265 } else if (rgblight_config.mode >= 2 && rgblight_config.mode <= 24) {
227 // MODE 2-5, breathing 266 // MODE 2-5, breathing
228 // MODE 6-8, rainbow mood 267 // MODE 6-8, rainbow mood
229 // MODE 9-14, rainbow swirl 268 // MODE 9-14, rainbow swirl
230 // MODE 15-20, snake 269 // MODE 15-20, snake
231 // MODE 21-23, knight 270 // MODE 21-23, knight
232 271
233 #if !defined(AUDIO_ENABLE) && defined(RGBLIGHT_TIMER) 272 #ifdef RGBLIGHT_ANIMATIONS
234 rgblight_timer_enable(); 273 rgblight_timer_enable();
235 #endif 274 #endif
275 } else if (rgblight_config.mode >= 25 && rgblight_config.mode <= 34) {
276 // MODE 25-34, static gradient
277
278 #ifdef RGBLIGHT_ANIMATIONS
279 rgblight_timer_disable();
280 #endif
236 } 281 }
237 rgblight_sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val); 282 rgblight_sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val);
238} 283}
@@ -244,7 +289,7 @@ void rgblight_toggle(void) {
244 if (rgblight_config.enable) { 289 if (rgblight_config.enable) {
245 rgblight_mode(rgblight_config.mode); 290 rgblight_mode(rgblight_config.mode);
246 } else { 291 } else {
247 #if !defined(AUDIO_ENABLE) && defined(RGBLIGHT_TIMER) 292 #ifdef RGBLIGHT_ANIMATIONS
248 rgblight_timer_disable(); 293 rgblight_timer_disable();
249 #endif 294 #endif
250 _delay_ms(50); 295 _delay_ms(50);
@@ -252,6 +297,13 @@ void rgblight_toggle(void) {
252 } 297 }
253} 298}
254 299
300void rgblight_enable(void) {
301 rgblight_config.enable = 1;
302 eeconfig_update_rgblight(rgblight_config.raw);
303 xprintf("rgblight enable: rgblight_config.enable = %u\n", rgblight_config.enable);
304 rgblight_mode(rgblight_config.mode);
305}
306
255 307
256void rgblight_increase_hue(void) { 308void rgblight_increase_hue(void) {
257 uint16_t hue; 309 uint16_t hue;
@@ -307,7 +359,7 @@ void rgblight_decrease_val(void) {
307void rgblight_sethsv_noeeprom(uint16_t hue, uint8_t sat, uint8_t val) { 359void rgblight_sethsv_noeeprom(uint16_t hue, uint8_t sat, uint8_t val) {
308 inmem_config.raw = rgblight_config.raw; 360 inmem_config.raw = rgblight_config.raw;
309 if (rgblight_config.enable) { 361 if (rgblight_config.enable) {
310 struct cRGB tmp_led; 362 LED_TYPE tmp_led;
311 sethsv(hue, sat, val, &tmp_led); 363 sethsv(hue, sat, val, &tmp_led);
312 inmem_config.hue = hue; 364 inmem_config.hue = hue;
313 inmem_config.sat = sat; 365 inmem_config.sat = sat;
@@ -329,6 +381,17 @@ void rgblight_sethsv(uint16_t hue, uint8_t sat, uint8_t val) {
329 } else if (rgblight_config.mode >= 6 && rgblight_config.mode <= 14) { 381 } else if (rgblight_config.mode >= 6 && rgblight_config.mode <= 14) {
330 // rainbow mood and rainbow swirl, ignore the change of hue 382 // rainbow mood and rainbow swirl, ignore the change of hue
331 hue = rgblight_config.hue; 383 hue = rgblight_config.hue;
384 } else if (rgblight_config.mode >= 25 && rgblight_config.mode <= 34) {
385 // static gradient
386 uint16_t _hue;
387 int8_t direction = ((rgblight_config.mode - 25) % 2) ? -1 : 1;
388 uint16_t range = pgm_read_word(&RGBLED_GRADIENT_RANGES[(rgblight_config.mode - 25) / 2]);
389 for (uint8_t i = 0; i < RGBLED_NUM; i++) {
390 _hue = (range / RGBLED_NUM * i * direction + hue + 360) % 360;
391 dprintf("rgblight rainbow set hsv: %u,%u,%d,%u\n", i, _hue, direction, range);
392 sethsv(_hue, sat, val, (LED_TYPE *)&led[i]);
393 }
394 rgblight_set();
332 } 395 }
333 } 396 }
334 rgblight_config.hue = hue; 397 rgblight_config.hue = hue;
@@ -349,68 +412,90 @@ void rgblight_setrgb(uint8_t r, uint8_t g, uint8_t b) {
349 rgblight_set(); 412 rgblight_set();
350} 413}
351 414
415__attribute__ ((weak))
352void rgblight_set(void) { 416void rgblight_set(void) {
353 if (rgblight_config.enable) { 417 if (rgblight_config.enable) {
354 ws2812_setleds(led, RGBLED_NUM); 418 #ifdef RGBW
419 ws2812_setleds_rgbw(led, RGBLED_NUM);
420 #else
421 ws2812_setleds(led, RGBLED_NUM);
422 #endif
355 } else { 423 } else {
356 for (uint8_t i = 0; i < RGBLED_NUM; i++) { 424 for (uint8_t i = 0; i < RGBLED_NUM; i++) {
357 led[i].r = 0; 425 led[i].r = 0;
358 led[i].g = 0; 426 led[i].g = 0;
359 led[i].b = 0; 427 led[i].b = 0;
360 } 428 }
361 ws2812_setleds(led, RGBLED_NUM); 429 #ifdef RGBW
430 ws2812_setleds_rgbw(led, RGBLED_NUM);
431 #else
432 ws2812_setleds(led, RGBLED_NUM);
433 #endif
362 } 434 }
363} 435}
364 436
365#if !defined(AUDIO_ENABLE) && defined(RGBLIGHT_TIMER) 437#ifdef RGBLIGHT_ANIMATIONS
366 438
367// Animation timer -- AVR Timer3 439// Animation timer -- AVR Timer3
368void rgblight_timer_init(void) { 440void rgblight_timer_init(void) {
369 static uint8_t rgblight_timer_is_init = 0; 441 // static uint8_t rgblight_timer_is_init = 0;
370 if (rgblight_timer_is_init) { 442 // if (rgblight_timer_is_init) {
371 return; 443 // return;
372 } 444 // }
373 rgblight_timer_is_init = 1; 445 // rgblight_timer_is_init = 1;
374 /* Timer 3 setup */ 446 // /* Timer 3 setup */
375 TCCR3B = _BV(WGM32) //CTC mode OCR3A as TOP 447 // TCCR3B = _BV(WGM32) // CTC mode OCR3A as TOP
376 | _BV(CS30); //Clock selelct: clk/1 448 // | _BV(CS30); // Clock selelct: clk/1
377 /* Set TOP value */ 449 // /* Set TOP value */
378 uint8_t sreg = SREG; 450 // uint8_t sreg = SREG;
379 cli(); 451 // cli();
380 OCR3AH = (RGBLED_TIMER_TOP >> 8) & 0xff; 452 // OCR3AH = (RGBLED_TIMER_TOP >> 8) & 0xff;
381 OCR3AL = RGBLED_TIMER_TOP & 0xff; 453 // OCR3AL = RGBLED_TIMER_TOP & 0xff;
382 SREG = sreg; 454 // SREG = sreg;
455
456 rgblight_timer_enabled = true;
383} 457}
384void rgblight_timer_enable(void) { 458void rgblight_timer_enable(void) {
385 TIMSK3 |= _BV(OCIE3A); 459 rgblight_timer_enabled = true;
386 dprintf("TIMER3 enabled.\n"); 460 dprintf("TIMER3 enabled.\n");
387} 461}
388void rgblight_timer_disable(void) { 462void rgblight_timer_disable(void) {
389 TIMSK3 &= ~_BV(OCIE3A); 463 rgblight_timer_enabled = false;
390 dprintf("TIMER3 disabled.\n"); 464 dprintf("TIMER3 disabled.\n");
391} 465}
392void rgblight_timer_toggle(void) { 466void rgblight_timer_toggle(void) {
393 TIMSK3 ^= _BV(OCIE3A); 467 rgblight_timer_enabled ^= rgblight_timer_enabled;
394 dprintf("TIMER3 toggled.\n"); 468 dprintf("TIMER3 toggled.\n");
395} 469}
396 470
397ISR(TIMER3_COMPA_vect) { 471void rgblight_show_solid_color(uint8_t r, uint8_t g, uint8_t b) {
398 // mode = 1, static light, do nothing here 472 rgblight_enable();
399 if (rgblight_config.mode >= 2 && rgblight_config.mode <= 5) { 473 rgblight_mode(1);
400 // mode = 2 to 5, breathing mode 474 rgblight_setrgb(r, g, b);
401 rgblight_effect_breathing(rgblight_config.mode - 2); 475}
402 } else if (rgblight_config.mode >= 6 && rgblight_config.mode <= 8) { 476
403 // mode = 6 to 8, rainbow mood mod 477void rgblight_task(void) {
404 rgblight_effect_rainbow_mood(rgblight_config.mode - 6); 478 if (rgblight_timer_enabled) {
405 } else if (rgblight_config.mode >= 9 && rgblight_config.mode <= 14) { 479 // mode = 1, static light, do nothing here
406 // mode = 9 to 14, rainbow swirl mode 480 if (rgblight_config.mode >= 2 && rgblight_config.mode <= 5) {
407 rgblight_effect_rainbow_swirl(rgblight_config.mode - 9); 481 // mode = 2 to 5, breathing mode
408 } else if (rgblight_config.mode >= 15 && rgblight_config.mode <= 20) { 482 rgblight_effect_breathing(rgblight_config.mode - 2);
409 // mode = 15 to 20, snake mode 483 } else if (rgblight_config.mode >= 6 && rgblight_config.mode <= 8) {
410 rgblight_effect_snake(rgblight_config.mode - 15); 484 // mode = 6 to 8, rainbow mood mod
411 } else if (rgblight_config.mode >= 21 && rgblight_config.mode <= 23) { 485 rgblight_effect_rainbow_mood(rgblight_config.mode - 6);
412 // mode = 21 to 23, knight mode 486 } else if (rgblight_config.mode >= 9 && rgblight_config.mode <= 14) {
413 rgblight_effect_knight(rgblight_config.mode - 21); 487 // mode = 9 to 14, rainbow swirl mode
488 rgblight_effect_rainbow_swirl(rgblight_config.mode - 9);
489 } else if (rgblight_config.mode >= 15 && rgblight_config.mode <= 20) {
490 // mode = 15 to 20, snake mode
491 rgblight_effect_snake(rgblight_config.mode - 15);
492 } else if (rgblight_config.mode >= 21 && rgblight_config.mode <= 23) {
493 // mode = 21 to 23, knight mode
494 rgblight_effect_knight(rgblight_config.mode - 21);
495 } else if (rgblight_config.mode == 24) {
496 // mode = 24, christmas mode
497 rgblight_effect_christmas();
498 }
414 } 499 }
415} 500}
416 501
@@ -449,7 +534,7 @@ void rgblight_effect_rainbow_swirl(uint8_t interval) {
449 last_timer = timer_read(); 534 last_timer = timer_read();
450 for (i = 0; i < RGBLED_NUM; i++) { 535 for (i = 0; i < RGBLED_NUM; i++) {
451 hue = (360 / RGBLED_NUM * i + current_hue) % 360; 536 hue = (360 / RGBLED_NUM * i + current_hue) % 360;
452 sethsv(hue, rgblight_config.sat, rgblight_config.val, &led[i]); 537 sethsv(hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i]);
453 } 538 }
454 rgblight_set(); 539 rgblight_set();
455 540
@@ -486,7 +571,7 @@ void rgblight_effect_snake(uint8_t interval) {
486 k = k + RGBLED_NUM; 571 k = k + RGBLED_NUM;
487 } 572 }
488 if (i == k) { 573 if (i == k) {
489 sethsv(rgblight_config.hue, rgblight_config.sat, (uint8_t)(rgblight_config.val*(RGBLIGHT_EFFECT_SNAKE_LENGTH-j)/RGBLIGHT_EFFECT_SNAKE_LENGTH), &led[i]); 574 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]);
490 } 575 }
491 } 576 }
492 } 577 }
@@ -506,7 +591,7 @@ void rgblight_effect_knight(uint8_t interval) {
506 static uint16_t last_timer = 0; 591 static uint16_t last_timer = 0;
507 uint8_t i, j, cur; 592 uint8_t i, j, cur;
508 int8_t k; 593 int8_t k;
509 struct cRGB preled[RGBLED_NUM]; 594 LED_TYPE preled[RGBLED_NUM];
510 static int8_t increment = -1; 595 static int8_t increment = -1;
511 if (timer_elapsed(last_timer) < pgm_read_byte(&RGBLED_KNIGHT_INTERVALS[interval])) { 596 if (timer_elapsed(last_timer) < pgm_read_byte(&RGBLED_KNIGHT_INTERVALS[interval])) {
512 return; 597 return;
@@ -525,7 +610,7 @@ void rgblight_effect_knight(uint8_t interval) {
525 k = RGBLED_NUM - 1; 610 k = RGBLED_NUM - 1;
526 } 611 }
527 if (i == k) { 612 if (i == k) {
528 sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, &preled[i]); 613 sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&preled[i]);
529 } 614 }
530 } 615 }
531 } 616 }
@@ -555,4 +640,22 @@ void rgblight_effect_knight(uint8_t interval) {
555 } 640 }
556} 641}
557 642
643
644void rgblight_effect_christmas(void) {
645 static uint16_t current_offset = 0;
646 static uint16_t last_timer = 0;
647 uint16_t hue;
648 uint8_t i;
649 if (timer_elapsed(last_timer) < RGBLIGHT_EFFECT_CHRISTMAS_INTERVAL) {
650 return;
651 }
652 last_timer = timer_read();
653 current_offset = (current_offset + 1) % 2;
654 for (i = 0; i < RGBLED_NUM; i++) {
655 hue = 0 + ((i/RGBLIGHT_EFFECT_CHRISTMAS_STEP + current_offset) % 2) * 120;
656 sethsv(hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i]);
657 }
658 rgblight_set();
659}
660
558#endif 661#endif