aboutsummaryrefslogtreecommitdiff
path: root/quantum/rgblight.c
diff options
context:
space:
mode:
Diffstat (limited to 'quantum/rgblight.c')
-rw-r--r--quantum/rgblight.c125
1 files changed, 116 insertions, 9 deletions
diff --git a/quantum/rgblight.c b/quantum/rgblight.c
index 26cb41a96..d33484ccf 100644
--- a/quantum/rgblight.c
+++ b/quantum/rgblight.c
@@ -15,6 +15,7 @@
15 */ 15 */
16#include <math.h> 16#include <math.h>
17#include <string.h> 17#include <string.h>
18#include <stdlib.h>
18#ifdef __AVR__ 19#ifdef __AVR__
19# include <avr/eeprom.h> 20# include <avr/eeprom.h>
20# include <avr/interrupt.h> 21# include <avr/interrupt.h>
@@ -367,6 +368,8 @@ void rgblight_disable_noeeprom(void) {
367 rgblight_set(); 368 rgblight_set();
368} 369}
369 370
371bool rgblight_is_enabled(void) { return rgblight_config.enable; }
372
370void rgblight_increase_hue_helper(bool write_to_eeprom) { 373void rgblight_increase_hue_helper(bool write_to_eeprom) {
371 uint8_t hue = rgblight_config.hue + RGBLIGHT_HUE_STEP; 374 uint8_t hue = rgblight_config.hue + RGBLIGHT_HUE_STEP;
372 rgblight_sethsv_eeprom_helper(hue, rgblight_config.sat, rgblight_config.val, write_to_eeprom); 375 rgblight_sethsv_eeprom_helper(hue, rgblight_config.sat, rgblight_config.val, write_to_eeprom);
@@ -521,6 +524,8 @@ uint8_t rgblight_get_sat(void) { return rgblight_config.sat; }
521 524
522uint8_t rgblight_get_val(void) { return rgblight_config.val; } 525uint8_t rgblight_get_val(void) { return rgblight_config.val; }
523 526
527HSV rgblight_get_hsv(void) { return (HSV){rgblight_config.hue, rgblight_config.sat, rgblight_config.val}; }
528
524void rgblight_setrgb(uint8_t r, uint8_t g, uint8_t b) { 529void rgblight_setrgb(uint8_t r, uint8_t g, uint8_t b) {
525 if (!rgblight_config.enable) { 530 if (!rgblight_config.enable) {
526 return; 531 return;
@@ -561,7 +566,7 @@ void rgblight_sethsv_at(uint8_t hue, uint8_t sat, uint8_t val, uint8_t index) {
561 rgblight_setrgb_at(tmp_led.r, tmp_led.g, tmp_led.b, index); 566 rgblight_setrgb_at(tmp_led.r, tmp_led.g, tmp_led.b, index);
562} 567}
563 568
564#if defined(RGBLIGHT_EFFECT_BREATHING) || defined(RGBLIGHT_EFFECT_RAINBOW_MOOD) || defined(RGBLIGHT_EFFECT_RAINBOW_SWIRL) || defined(RGBLIGHT_EFFECT_SNAKE) || defined(RGBLIGHT_EFFECT_KNIGHT) 569#if defined(RGBLIGHT_EFFECT_BREATHING) || defined(RGBLIGHT_EFFECT_RAINBOW_MOOD) || defined(RGBLIGHT_EFFECT_RAINBOW_SWIRL) || defined(RGBLIGHT_EFFECT_SNAKE) || defined(RGBLIGHT_EFFECT_KNIGHT) || defined(RGBLIGHT_EFFECT_TWINKLE)
565 570
566static uint8_t get_interval_time(const uint8_t *default_interval_address, uint8_t velocikey_min, uint8_t velocikey_max) { 571static uint8_t get_interval_time(const uint8_t *default_interval_address, uint8_t velocikey_min, uint8_t velocikey_max) {
567 return 572 return
@@ -612,7 +617,7 @@ void rgblight_sethsv_slave(uint8_t hue, uint8_t sat, uint8_t val) { rgblight_set
612 617
613#ifdef RGBLIGHT_LAYERS 618#ifdef RGBLIGHT_LAYERS
614void rgblight_set_layer_state(uint8_t layer, bool enabled) { 619void rgblight_set_layer_state(uint8_t layer, bool enabled) {
615 uint8_t mask = 1 << layer; 620 rgblight_layer_mask_t mask = 1 << layer;
616 if (enabled) { 621 if (enabled) {
617 rgblight_status.enabled_layer_mask |= mask; 622 rgblight_status.enabled_layer_mask |= mask;
618 } else { 623 } else {
@@ -623,10 +628,17 @@ void rgblight_set_layer_state(uint8_t layer, bool enabled) {
623 if (rgblight_status.timer_enabled == false) { 628 if (rgblight_status.timer_enabled == false) {
624 rgblight_mode_noeeprom(rgblight_config.mode); 629 rgblight_mode_noeeprom(rgblight_config.mode);
625 } 630 }
631
632# ifdef RGBLIGHT_LAYERS_OVERRIDE_RGB_OFF
633 // If not enabled, then nothing else will actually set the LEDs...
634 if (!rgblight_config.enable) {
635 rgblight_set();
636 }
637# endif
626} 638}
627 639
628bool rgblight_get_layer_state(uint8_t layer) { 640bool rgblight_get_layer_state(uint8_t layer) {
629 uint8_t mask = 1 << layer; 641 rgblight_layer_mask_t mask = 1 << layer;
630 return (rgblight_status.enabled_layer_mask & mask) != 0; 642 return (rgblight_status.enabled_layer_mask & mask) != 0;
631} 643}
632 644
@@ -658,21 +670,41 @@ static void rgblight_layers_write(void) {
658 } 670 }
659 } 671 }
660} 672}
673
674# ifdef RGBLIGHT_LAYER_BLINK
675rgblight_layer_mask_t _blinked_layer_mask = 0;
676uint16_t _blink_duration = 0;
677static uint16_t _blink_timer;
678
679void rgblight_blink_layer(uint8_t layer, uint16_t duration_ms) {
680 rgblight_set_layer_state(layer, true);
681 _blinked_layer_mask |= 1 << layer;
682 _blink_timer = timer_read();
683 _blink_duration = duration_ms;
684}
685
686void rgblight_unblink_layers(void) {
687 if (_blinked_layer_mask != 0 && timer_elapsed(_blink_timer) > _blink_duration) {
688 for (uint8_t layer = 0; layer < RGBLIGHT_MAX_LAYERS; layer++) {
689 if ((_blinked_layer_mask & 1 << layer) != 0) {
690 rgblight_set_layer_state(layer, false);
691 }
692 }
693 _blinked_layer_mask = 0;
694 }
695}
696# endif
697
661#endif 698#endif
662 699
663__attribute__((weak)) void rgblight_call_driver(LED_TYPE *start_led, uint8_t num_leds) { ws2812_setleds(start_led, num_leds); } 700__attribute__((weak)) void rgblight_call_driver(LED_TYPE *start_led, uint8_t num_leds) { ws2812_setleds(start_led, num_leds); }
664 701
665#ifndef RGBLIGHT_CUSTOM_DRIVER 702#ifndef RGBLIGHT_CUSTOM_DRIVER
703
666void rgblight_set(void) { 704void rgblight_set(void) {
667 LED_TYPE *start_led; 705 LED_TYPE *start_led;
668 uint8_t num_leds = rgblight_ranges.clipping_num_leds; 706 uint8_t num_leds = rgblight_ranges.clipping_num_leds;
669 707
670# ifdef RGBLIGHT_LAYERS
671 if (rgblight_layers != NULL) {
672 rgblight_layers_write();
673 }
674# endif
675
676 if (!rgblight_config.enable) { 708 if (!rgblight_config.enable) {
677 for (uint8_t i = rgblight_ranges.effect_start_pos; i < rgblight_ranges.effect_end_pos; i++) { 709 for (uint8_t i = rgblight_ranges.effect_start_pos; i < rgblight_ranges.effect_end_pos; i++) {
678 led[i].r = 0; 710 led[i].r = 0;
@@ -684,6 +716,16 @@ void rgblight_set(void) {
684 } 716 }
685 } 717 }
686 718
719# ifdef RGBLIGHT_LAYERS
720 if (rgblight_layers != NULL
721# ifndef RGBLIGHT_LAYERS_OVERRIDE_RGB_OFF
722 && rgblight_config.enable
723# endif
724 ) {
725 rgblight_layers_write();
726 }
727# endif
728
687# ifdef RGBLIGHT_LED_MAP 729# ifdef RGBLIGHT_LED_MAP
688 LED_TYPE led0[RGBLED_NUM]; 730 LED_TYPE led0[RGBLED_NUM];
689 for (uint8_t i = 0; i < RGBLED_NUM; i++) { 731 for (uint8_t i = 0; i < RGBLED_NUM; i++) {
@@ -880,6 +922,12 @@ void rgblight_task(void) {
880 effect_func = (effect_func_t)rgblight_effect_alternating; 922 effect_func = (effect_func_t)rgblight_effect_alternating;
881 } 923 }
882# endif 924# endif
925# ifdef RGBLIGHT_EFFECT_TWINKLE
926 else if (rgblight_status.base_mode == RGBLIGHT_MODE_TWINKLE) {
927 interval_time = get_interval_time(&RGBLED_TWINKLE_INTERVALS[delta % 3], 5, 50);
928 effect_func = (effect_func_t)rgblight_effect_twinkle;
929 }
930# endif
883 if (animation_status.restart) { 931 if (animation_status.restart) {
884 animation_status.restart = false; 932 animation_status.restart = false;
885 animation_status.last_timer = timer_read() - interval_time - 1; 933 animation_status.last_timer = timer_read() - interval_time - 1;
@@ -909,6 +957,10 @@ void rgblight_task(void) {
909# endif 957# endif
910 } 958 }
911 } 959 }
960
961# ifdef RGBLIGHT_LAYER_BLINK
962 rgblight_unblink_layers();
963# endif
912} 964}
913 965
914#endif /* RGBLIGHT_USE_TIMER */ 966#endif /* RGBLIGHT_USE_TIMER */
@@ -1160,3 +1212,58 @@ void rgblight_effect_alternating(animation_status_t *anim) {
1160 anim->pos = (anim->pos + 1) % 2; 1212 anim->pos = (anim->pos + 1) % 2;
1161} 1213}
1162#endif 1214#endif
1215
1216#ifdef RGBLIGHT_EFFECT_TWINKLE
1217__attribute__((weak)) const uint8_t RGBLED_TWINKLE_INTERVALS[] PROGMEM = {50, 25, 10};
1218
1219typedef struct PACKED {
1220 HSV hsv;
1221 uint8_t life;
1222 bool up;
1223} TwinkleState;
1224
1225static TwinkleState led_twinkle_state[RGBLED_NUM];
1226
1227void rgblight_effect_twinkle(animation_status_t *anim) {
1228 bool random_color = anim->delta / 3;
1229 bool restart = anim->pos == 0;
1230 anim->pos = 1;
1231
1232 for (uint8_t i = 0; i < rgblight_ranges.effect_num_leds; i++) {
1233 TwinkleState *t = &(led_twinkle_state[i]);
1234 HSV * c = &(t->hsv);
1235 if (restart) {
1236 // Restart
1237 t->life = 0;
1238 t->hsv.v = 0;
1239 } else if (t->life) {
1240 // This LED is already on, either brightening or dimming
1241 t->life--;
1242 uint8_t on = t->up ? RGBLIGHT_EFFECT_TWINKLE_LIFE - t->life : t->life;
1243 c->v = (uint16_t)rgblight_config.val * on / RGBLIGHT_EFFECT_TWINKLE_LIFE;
1244 if (t->life == 0 && t->up) {
1245 t->up = false;
1246 t->life = RGBLIGHT_EFFECT_TWINKLE_LIFE;
1247 }
1248 if (!random_color) {
1249 c->h = rgblight_config.hue;
1250 c->s = rgblight_config.sat;
1251 }
1252 } else if (rand() < RAND_MAX * RGBLIGHT_EFFECT_TWINKLE_PROBABILITY) {
1253 // This LED is off, but was randomly selected to start brightening
1254 c->h = random_color ? rand() % 0xFF : rgblight_config.hue;
1255 c->s = random_color ? (rand() % (rgblight_config.sat / 2)) + (rgblight_config.sat / 2) : rgblight_config.sat;
1256 c->v = 0;
1257 t->life = RGBLIGHT_EFFECT_TWINKLE_LIFE;
1258 t->up = true;
1259 } else {
1260 // This LED is off, and was NOT selected to start brightening
1261 }
1262
1263 LED_TYPE *ledp = led + i + rgblight_ranges.effect_start_pos;
1264 sethsv(c->h, c->s, c->v, ledp);
1265 }
1266
1267 rgblight_set();
1268}
1269#endif