aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Diamond <josh@windowoffire.com>2020-05-09 04:56:16 -0400
committerGitHub <noreply@github.com>2020-05-09 01:56:16 -0700
commit2fe7e221ec9e412cc008aa5c03eaf27e35ff62c6 (patch)
tree79ae7e86cfb9048b3bd9795b596ec318581d801e
parente0f548085cc9c29e85122d393e74143eb5de1d4d (diff)
downloadqmk_firmware-2fe7e221ec9e412cc008aa5c03eaf27e35ff62c6.tar.gz
qmk_firmware-2fe7e221ec9e412cc008aa5c03eaf27e35ff62c6.zip
New RGB Lighting effect: Twinkle (#8887)
* Add twinkle RGB Lighting effect * 2nd twinkle algo - double-buffering * Further refinement: Per-LED twinkle * Add documentation for Twinkle RBG Lighting mode * Bias twinkle saturation closer to the set value * Fix whitespace
-rw-r--r--docs/feature_rgblight.md11
-rw-r--r--quantum/rgblight.c65
-rw-r--r--quantum/rgblight.h20
-rw-r--r--quantum/rgblight_modes.h8
4 files changed, 100 insertions, 4 deletions
diff --git a/docs/feature_rgblight.md b/docs/feature_rgblight.md
index de19b7419..045d97775 100644
--- a/docs/feature_rgblight.md
+++ b/docs/feature_rgblight.md
@@ -94,6 +94,7 @@ if `RGBLIGHT_EFFECT_xxxx` or `RGBLIGHT_ANIMATIONS` is defined, you also have a n
94|`RGBLIGHT_MODE_STATIC_GRADIENT`| 0,1,..,9 |Static gradient | 94|`RGBLIGHT_MODE_STATIC_GRADIENT`| 0,1,..,9 |Static gradient |
95|`RGBLIGHT_MODE_RGB_TEST` | *None* |RGB Test | 95|`RGBLIGHT_MODE_RGB_TEST` | *None* |RGB Test |
96|`RGBLIGHT_MODE_ALTERNATING` | *None* |Alternating | 96|`RGBLIGHT_MODE_ALTERNATING` | *None* |Alternating |
97|`RGBLIGHT_MODE_TWINKLE` | 0,1,2,3,4,5 |Twinkle |
97 98
98Check out [this video](https://youtube.com/watch?v=VKrpPAHlisY) for a demonstration. 99Check out [this video](https://youtube.com/watch?v=VKrpPAHlisY) for a demonstration.
99 100
@@ -103,8 +104,8 @@ Note: For versions older than 0.6.117, The mode numbers were written directly. I
103 104
104Use these defines to add or remove animations from the firmware. When you are running low on flash space, it can be helpful to disable animations you are not using. 105Use these defines to add or remove animations from the firmware. When you are running low on flash space, it can be helpful to disable animations you are not using.
105 106
106|Define |Default |Description | 107|Define |Default |Description |
107|------------------------------------|-------------|-------------------------------------------------------------------------------------| 108|------------------------------------|-------------|-------------------------------------------------------------------------|
108|`RGBLIGHT_ANIMATIONS` |*Not defined*|Enable all additional animation modes. | 109|`RGBLIGHT_ANIMATIONS` |*Not defined*|Enable all additional animation modes. |
109|`RGBLIGHT_EFFECT_ALTERNATING` |*Not defined*|Enable alternating animation mode. | 110|`RGBLIGHT_EFFECT_ALTERNATING` |*Not defined*|Enable alternating animation mode. |
110|`RGBLIGHT_EFFECT_BREATHING` |*Not defined*|Enable breathing animation mode. | 111|`RGBLIGHT_EFFECT_BREATHING` |*Not defined*|Enable breathing animation mode. |
@@ -115,6 +116,7 @@ Use these defines to add or remove animations from the firmware. When you are ru
115|`RGBLIGHT_EFFECT_RGB_TEST` |*Not defined*|Enable RGB test animation mode. | 116|`RGBLIGHT_EFFECT_RGB_TEST` |*Not defined*|Enable RGB test animation mode. |
116|`RGBLIGHT_EFFECT_SNAKE` |*Not defined*|Enable snake animation mode. | 117|`RGBLIGHT_EFFECT_SNAKE` |*Not defined*|Enable snake animation mode. |
117|`RGBLIGHT_EFFECT_STATIC_GRADIENT` |*Not defined*|Enable static gradient mode. | 118|`RGBLIGHT_EFFECT_STATIC_GRADIENT` |*Not defined*|Enable static gradient mode. |
119|`RGBLIGHT_EFFECT_TWINKLE` |*Not defined*|Enable twinkle animation mode. |
118 120
119### Effect and Animation Settings 121### Effect and Animation Settings
120 122
@@ -131,6 +133,8 @@ The following options are used to tweak the various animations:
131|`RGBLIGHT_EFFECT_KNIGHT_OFFSET` |`0` |The number of LEDs to start the "Knight" animation from the start of the strip by | 133|`RGBLIGHT_EFFECT_KNIGHT_OFFSET` |`0` |The number of LEDs to start the "Knight" animation from the start of the strip by |
132|`RGBLIGHT_RAINBOW_SWIRL_RANGE` |`255` |Range adjustment for the rainbow swirl effect to get different swirls | 134|`RGBLIGHT_RAINBOW_SWIRL_RANGE` |`255` |Range adjustment for the rainbow swirl effect to get different swirls |
133|`RGBLIGHT_EFFECT_SNAKE_LENGTH` |`4` |The number of LEDs to light up for the "Snake" animation | 135|`RGBLIGHT_EFFECT_SNAKE_LENGTH` |`4` |The number of LEDs to light up for the "Snake" animation |
136|`RGBLIGHT_EFFECT_TWINKLE_LIFE` |`75` |Adjusts how quickly each LED brightens and dims when twinkling (in animation steps) |
137|`RGBLIGHT_EFFECT_TWINKLE_PROBABILITY`|`1/127` |Adjusts how likely each LED is to twinkle (on each animation step) |
134 138
135### Example Usage to Reduce Memory Footprint 139### Example Usage to Reduce Memory Footprint
136 1. Remove `RGBLIGHT_ANIMATIONS` from `config.h`. 140 1. Remove `RGBLIGHT_ANIMATIONS` from `config.h`.
@@ -168,6 +172,9 @@ const uint8_t RGBLED_SNAKE_INTERVALS[] PROGMEM = {100, 50, 20};
168// How long (in milliseconds) to wait between animation steps for each of the "Knight" animations 172// How long (in milliseconds) to wait between animation steps for each of the "Knight" animations
169const uint8_t RGBLED_KNIGHT_INTERVALS[] PROGMEM = {127, 63, 31}; 173const uint8_t RGBLED_KNIGHT_INTERVALS[] PROGMEM = {127, 63, 31};
170 174
175// How long (in milliseconds) to wait between animation steps for each of the "Twinkle" animations
176const uint8_t RGBLED_TWINKLE_INTERVALS[] PROGMEM = {50, 25, 10};
177
171// These control which hues are selected for each of the "Static gradient" modes 178// These control which hues are selected for each of the "Static gradient" modes
172const uint8_t RGBLED_GRADIENT_RANGES[] PROGMEM = {255, 170, 127, 85, 64}; 179const uint8_t RGBLED_GRADIENT_RANGES[] PROGMEM = {255, 170, 127, 85, 64};
173``` 180```
diff --git a/quantum/rgblight.c b/quantum/rgblight.c
index 33326fa86..8d01bcf0e 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>
@@ -561,7 +562,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); 562 rgblight_setrgb_at(tmp_led.r, tmp_led.g, tmp_led.b, index);
562} 563}
563 564
564#if defined(RGBLIGHT_EFFECT_BREATHING) || defined(RGBLIGHT_EFFECT_RAINBOW_MOOD) || defined(RGBLIGHT_EFFECT_RAINBOW_SWIRL) || defined(RGBLIGHT_EFFECT_SNAKE) || defined(RGBLIGHT_EFFECT_KNIGHT) 565#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 566
566static uint8_t get_interval_time(const uint8_t *default_interval_address, uint8_t velocikey_min, uint8_t velocikey_max) { 567static uint8_t get_interval_time(const uint8_t *default_interval_address, uint8_t velocikey_min, uint8_t velocikey_max) {
567 return 568 return
@@ -905,6 +906,12 @@ void rgblight_task(void) {
905 effect_func = (effect_func_t)rgblight_effect_alternating; 906 effect_func = (effect_func_t)rgblight_effect_alternating;
906 } 907 }
907# endif 908# endif
909# ifdef RGBLIGHT_EFFECT_TWINKLE
910 else if (rgblight_status.base_mode == RGBLIGHT_MODE_TWINKLE) {
911 interval_time = get_interval_time(&RGBLED_TWINKLE_INTERVALS[delta % 3], 5, 50);
912 effect_func = (effect_func_t)rgblight_effect_twinkle;
913 }
914# endif
908 if (animation_status.restart) { 915 if (animation_status.restart) {
909 animation_status.restart = false; 916 animation_status.restart = false;
910 animation_status.last_timer = timer_read() - interval_time - 1; 917 animation_status.last_timer = timer_read() - interval_time - 1;
@@ -1189,3 +1196,59 @@ void rgblight_effect_alternating(animation_status_t *anim) {
1189 anim->pos = (anim->pos + 1) % 2; 1196 anim->pos = (anim->pos + 1) % 2;
1190} 1197}
1191#endif 1198#endif
1199
1200#ifdef RGBLIGHT_EFFECT_TWINKLE
1201__attribute__((weak)) const uint8_t RGBLED_TWINKLE_INTERVALS[] PROGMEM = {50, 25, 10};
1202
1203typedef struct PACKED {
1204 HSV hsv;
1205 uint8_t life;
1206 bool up;
1207} TwinkleState;
1208
1209static TwinkleState led_twinkle_state[RGBLED_NUM];
1210
1211void rgblight_effect_twinkle(animation_status_t *anim) {
1212
1213 bool random_color = anim->delta / 3;
1214 bool restart = anim->pos == 0;
1215 anim->pos = 1;
1216
1217 for (uint8_t i = 0; i < rgblight_ranges.effect_num_leds; i++) {
1218 TwinkleState *t = &(led_twinkle_state[i]);
1219 HSV *c = &(t->hsv);
1220 if (restart) {
1221 // Restart
1222 t->life = 0;
1223 t->hsv.v = 0;
1224 } else if (t->life) {
1225 // This LED is already on, either brightening or dimming
1226 t->life--;
1227 uint8_t on = t->up ? RGBLIGHT_EFFECT_TWINKLE_LIFE - t->life : t->life;
1228 c->v = (uint16_t) rgblight_config.val * on / RGBLIGHT_EFFECT_TWINKLE_LIFE;
1229 if (t->life == 0 && t->up) {
1230 t->up = false;
1231 t->life = RGBLIGHT_EFFECT_TWINKLE_LIFE;
1232 }
1233 if (!random_color) {
1234 c->h = rgblight_config.hue;
1235 c->s = rgblight_config.sat;
1236 }
1237 } else if (rand() < RAND_MAX * RGBLIGHT_EFFECT_TWINKLE_PROBABILITY) {
1238 // This LED is off, but was randomly selected to start brightening
1239 c->h = random_color ? rand() % 0xFF : rgblight_config.hue;
1240 c->s = random_color ? (rand() % (rgblight_config.sat / 2)) + (rgblight_config.sat / 2) : rgblight_config.sat;
1241 c->v = 0;
1242 t->life = RGBLIGHT_EFFECT_TWINKLE_LIFE;
1243 t->up = true;
1244 } else {
1245 // This LED is off, and was NOT selected to start brightening
1246 }
1247
1248 LED_TYPE *ledp = led + i + rgblight_ranges.effect_start_pos;
1249 sethsv(c->h, c->s, c->v, ledp);
1250 }
1251
1252 rgblight_set();
1253}
1254#endif
diff --git a/quantum/rgblight.h b/quantum/rgblight.h
index e06073728..7de9c3f3d 100644
--- a/quantum/rgblight.h
+++ b/quantum/rgblight.h
@@ -59,6 +59,12 @@
59| 34 | RGBLIGHT_MODE_STATIC_GRADIENT + 9 | 59| 34 | RGBLIGHT_MODE_STATIC_GRADIENT + 9 |
60| 35 | RGBLIGHT_MODE_RGB_TEST | 60| 35 | RGBLIGHT_MODE_RGB_TEST |
61| 36 | RGBLIGHT_MODE_ALTERNATING | 61| 36 | RGBLIGHT_MODE_ALTERNATING |
62| 37 | RGBLIGHT_MODE_TWINKLE |
63| 38 | RGBLIGHT_MODE_TWINKLE + 1 |
64| 39 | RGBLIGHT_MODE_TWINKLE + 2 |
65| 40 | RGBLIGHT_MODE_TWINKLE + 3 |
66| 41 | RGBLIGHT_MODE_TWINKLE + 4 |
67| 42 | RGBLIGHT_MODE_TWINKLE + 5 |
62|-----------------|-----------------------------------| 68|-----------------|-----------------------------------|
63 *****/ 69 *****/
64 70
@@ -73,6 +79,7 @@
73# define RGBLIGHT_EFFECT_STATIC_GRADIENT 79# define RGBLIGHT_EFFECT_STATIC_GRADIENT
74# define RGBLIGHT_EFFECT_RGB_TEST 80# define RGBLIGHT_EFFECT_RGB_TEST
75# define RGBLIGHT_EFFECT_ALTERNATING 81# define RGBLIGHT_EFFECT_ALTERNATING
82# define RGBLIGHT_EFFECT_TWINKLE
76#endif 83#endif
77 84
78#ifdef RGBLIGHT_STATIC_PATTERNS 85#ifdef RGBLIGHT_STATIC_PATTERNS
@@ -89,7 +96,8 @@
89 || defined(RGBLIGHT_EFFECT_KNIGHT) \ 96 || defined(RGBLIGHT_EFFECT_KNIGHT) \
90 || defined(RGBLIGHT_EFFECT_CHRISTMAS) \ 97 || defined(RGBLIGHT_EFFECT_CHRISTMAS) \
91 || defined(RGBLIGHT_EFFECT_RGB_TEST) \ 98 || defined(RGBLIGHT_EFFECT_RGB_TEST) \
92 || defined(RGBLIGHT_EFFECT_ALTERNATING) 99 || defined(RGBLIGHT_EFFECT_ALTERNATING) \
100 || defined(RGBLIGHT_EFFECT_TWINKLE)
93# define RGBLIGHT_USE_TIMER 101# define RGBLIGHT_USE_TIMER
94#endif 102#endif
95 103
@@ -141,6 +149,14 @@ enum RGBLIGHT_EFFECT_MODE {
141# define RGBLIGHT_EFFECT_CHRISTMAS_STEP 2 149# define RGBLIGHT_EFFECT_CHRISTMAS_STEP 2
142# endif 150# endif
143 151
152# ifndef RGBLIGHT_EFFECT_TWINKLE_LIFE
153# define RGBLIGHT_EFFECT_TWINKLE_LIFE 75
154# endif
155
156# ifndef RGBLIGHT_EFFECT_TWINKLE_PROBABILITY
157# define RGBLIGHT_EFFECT_TWINKLE_PROBABILITY 1/127
158# endif
159
144# ifndef RGBLIGHT_HUE_STEP 160# ifndef RGBLIGHT_HUE_STEP
145# define RGBLIGHT_HUE_STEP 8 161# define RGBLIGHT_HUE_STEP 8
146# endif 162# endif
@@ -208,6 +224,7 @@ extern const uint8_t RGBLED_RAINBOW_SWIRL_INTERVALS[3] PROGMEM;
208extern const uint8_t RGBLED_SNAKE_INTERVALS[3] PROGMEM; 224extern const uint8_t RGBLED_SNAKE_INTERVALS[3] PROGMEM;
209extern const uint8_t RGBLED_KNIGHT_INTERVALS[3] PROGMEM; 225extern const uint8_t RGBLED_KNIGHT_INTERVALS[3] PROGMEM;
210extern const uint16_t RGBLED_RGBTEST_INTERVALS[1] PROGMEM; 226extern const uint16_t RGBLED_RGBTEST_INTERVALS[1] PROGMEM;
227extern const uint8_t RGBLED_TWINKLE_INTERVALS[3] PROGMEM;
211extern bool is_rgblight_initialized; 228extern bool is_rgblight_initialized;
212 229
213// Should stay in sycn with rgb matrix config as we reuse eeprom storage for both (for now) 230// Should stay in sycn with rgb matrix config as we reuse eeprom storage for both (for now)
@@ -398,6 +415,7 @@ void rgblight_effect_knight(animation_status_t *anim);
398void rgblight_effect_christmas(animation_status_t *anim); 415void rgblight_effect_christmas(animation_status_t *anim);
399void rgblight_effect_rgbtest(animation_status_t *anim); 416void rgblight_effect_rgbtest(animation_status_t *anim);
400void rgblight_effect_alternating(animation_status_t *anim); 417void rgblight_effect_alternating(animation_status_t *anim);
418void rgblight_effect_twinkle(animation_status_t *anim);
401 419
402# endif 420# endif
403 421
diff --git a/quantum/rgblight_modes.h b/quantum/rgblight_modes.h
index 40c9ce498..7abdb87bc 100644
--- a/quantum/rgblight_modes.h
+++ b/quantum/rgblight_modes.h
@@ -53,6 +53,14 @@ _RGBM_SINGLE_DYNAMIC(RGB_TEST)
53# ifdef RGBLIGHT_EFFECT_ALTERNATING 53# ifdef RGBLIGHT_EFFECT_ALTERNATING
54_RGBM_SINGLE_DYNAMIC(ALTERNATING) 54_RGBM_SINGLE_DYNAMIC(ALTERNATING)
55# endif 55# endif
56# ifdef RGBLIGHT_EFFECT_TWINKLE
57_RGBM_MULTI_DYNAMIC(TWINKLE)
58_RGBM_TMP_DYNAMIC(twinkle_38, TWINKLE)
59_RGBM_TMP_DYNAMIC(twinkle_39, TWINKLE)
60_RGBM_TMP_DYNAMIC(twinkle_40, TWINKLE)
61_RGBM_TMP_DYNAMIC(twinkle_41, TWINKLE)
62_RGBM_TMP_DYNAMIC(TWINKLE_end, TWINKLE)
63# endif
56//// Add a new mode here. 64//// Add a new mode here.
57// #ifdef RGBLIGHT_EFFECT_<name> 65// #ifdef RGBLIGHT_EFFECT_<name>
58// _RGBM_<SINGLE|MULTI>_<STATIC|DYNAMIC>( <name> ) 66// _RGBM_<SINGLE|MULTI>_<STATIC|DYNAMIC>( <name> )