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
This commit is contained in:
parent
e0f548085c
commit
2fe7e221ec
4 changed files with 100 additions and 4 deletions
|
@ -94,6 +94,7 @@ if `RGBLIGHT_EFFECT_xxxx` or `RGBLIGHT_ANIMATIONS` is defined, you also have a n
|
||||||
|`RGBLIGHT_MODE_STATIC_GRADIENT`| 0,1,..,9 |Static gradient |
|
|`RGBLIGHT_MODE_STATIC_GRADIENT`| 0,1,..,9 |Static gradient |
|
||||||
|`RGBLIGHT_MODE_RGB_TEST` | *None* |RGB Test |
|
|`RGBLIGHT_MODE_RGB_TEST` | *None* |RGB Test |
|
||||||
|`RGBLIGHT_MODE_ALTERNATING` | *None* |Alternating |
|
|`RGBLIGHT_MODE_ALTERNATING` | *None* |Alternating |
|
||||||
|
|`RGBLIGHT_MODE_TWINKLE` | 0,1,2,3,4,5 |Twinkle |
|
||||||
|
|
||||||
Check out [this video](https://youtube.com/watch?v=VKrpPAHlisY) for a demonstration.
|
Check out [this video](https://youtube.com/watch?v=VKrpPAHlisY) for a demonstration.
|
||||||
|
|
||||||
|
@ -103,8 +104,8 @@ Note: For versions older than 0.6.117, The mode numbers were written directly. I
|
||||||
|
|
||||||
Use 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.
|
Use 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.
|
||||||
|
|
||||||
|Define |Default |Description |
|
|Define |Default |Description |
|
||||||
|------------------------------------|-------------|-------------------------------------------------------------------------------------|
|
|------------------------------------|-------------|-------------------------------------------------------------------------|
|
||||||
|`RGBLIGHT_ANIMATIONS` |*Not defined*|Enable all additional animation modes. |
|
|`RGBLIGHT_ANIMATIONS` |*Not defined*|Enable all additional animation modes. |
|
||||||
|`RGBLIGHT_EFFECT_ALTERNATING` |*Not defined*|Enable alternating animation mode. |
|
|`RGBLIGHT_EFFECT_ALTERNATING` |*Not defined*|Enable alternating animation mode. |
|
||||||
|`RGBLIGHT_EFFECT_BREATHING` |*Not defined*|Enable breathing animation mode. |
|
|`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
|
||||||
|`RGBLIGHT_EFFECT_RGB_TEST` |*Not defined*|Enable RGB test animation mode. |
|
|`RGBLIGHT_EFFECT_RGB_TEST` |*Not defined*|Enable RGB test animation mode. |
|
||||||
|`RGBLIGHT_EFFECT_SNAKE` |*Not defined*|Enable snake animation mode. |
|
|`RGBLIGHT_EFFECT_SNAKE` |*Not defined*|Enable snake animation mode. |
|
||||||
|`RGBLIGHT_EFFECT_STATIC_GRADIENT` |*Not defined*|Enable static gradient mode. |
|
|`RGBLIGHT_EFFECT_STATIC_GRADIENT` |*Not defined*|Enable static gradient mode. |
|
||||||
|
|`RGBLIGHT_EFFECT_TWINKLE` |*Not defined*|Enable twinkle animation mode. |
|
||||||
|
|
||||||
### Effect and Animation Settings
|
### Effect and Animation Settings
|
||||||
|
|
||||||
|
@ -131,6 +133,8 @@ The following options are used to tweak the various animations:
|
||||||
|`RGBLIGHT_EFFECT_KNIGHT_OFFSET` |`0` |The number of LEDs to start the "Knight" animation from the start of the strip by |
|
|`RGBLIGHT_EFFECT_KNIGHT_OFFSET` |`0` |The number of LEDs to start the "Knight" animation from the start of the strip by |
|
||||||
|`RGBLIGHT_RAINBOW_SWIRL_RANGE` |`255` |Range adjustment for the rainbow swirl effect to get different swirls |
|
|`RGBLIGHT_RAINBOW_SWIRL_RANGE` |`255` |Range adjustment for the rainbow swirl effect to get different swirls |
|
||||||
|`RGBLIGHT_EFFECT_SNAKE_LENGTH` |`4` |The number of LEDs to light up for the "Snake" animation |
|
|`RGBLIGHT_EFFECT_SNAKE_LENGTH` |`4` |The number of LEDs to light up for the "Snake" animation |
|
||||||
|
|`RGBLIGHT_EFFECT_TWINKLE_LIFE` |`75` |Adjusts how quickly each LED brightens and dims when twinkling (in animation steps) |
|
||||||
|
|`RGBLIGHT_EFFECT_TWINKLE_PROBABILITY`|`1/127` |Adjusts how likely each LED is to twinkle (on each animation step) |
|
||||||
|
|
||||||
### Example Usage to Reduce Memory Footprint
|
### Example Usage to Reduce Memory Footprint
|
||||||
1. Remove `RGBLIGHT_ANIMATIONS` from `config.h`.
|
1. Remove `RGBLIGHT_ANIMATIONS` from `config.h`.
|
||||||
|
@ -168,6 +172,9 @@ const uint8_t RGBLED_SNAKE_INTERVALS[] PROGMEM = {100, 50, 20};
|
||||||
// How long (in milliseconds) to wait between animation steps for each of the "Knight" animations
|
// How long (in milliseconds) to wait between animation steps for each of the "Knight" animations
|
||||||
const uint8_t RGBLED_KNIGHT_INTERVALS[] PROGMEM = {127, 63, 31};
|
const uint8_t RGBLED_KNIGHT_INTERVALS[] PROGMEM = {127, 63, 31};
|
||||||
|
|
||||||
|
// How long (in milliseconds) to wait between animation steps for each of the "Twinkle" animations
|
||||||
|
const uint8_t RGBLED_TWINKLE_INTERVALS[] PROGMEM = {50, 25, 10};
|
||||||
|
|
||||||
// These control which hues are selected for each of the "Static gradient" modes
|
// These control which hues are selected for each of the "Static gradient" modes
|
||||||
const uint8_t RGBLED_GRADIENT_RANGES[] PROGMEM = {255, 170, 127, 85, 64};
|
const uint8_t RGBLED_GRADIENT_RANGES[] PROGMEM = {255, 170, 127, 85, 64};
|
||||||
```
|
```
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#ifdef __AVR__
|
#ifdef __AVR__
|
||||||
# include <avr/eeprom.h>
|
# include <avr/eeprom.h>
|
||||||
# include <avr/interrupt.h>
|
# include <avr/interrupt.h>
|
||||||
|
@ -561,7 +562,7 @@ void rgblight_sethsv_at(uint8_t hue, uint8_t sat, uint8_t val, uint8_t index) {
|
||||||
rgblight_setrgb_at(tmp_led.r, tmp_led.g, tmp_led.b, index);
|
rgblight_setrgb_at(tmp_led.r, tmp_led.g, tmp_led.b, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(RGBLIGHT_EFFECT_BREATHING) || defined(RGBLIGHT_EFFECT_RAINBOW_MOOD) || defined(RGBLIGHT_EFFECT_RAINBOW_SWIRL) || defined(RGBLIGHT_EFFECT_SNAKE) || defined(RGBLIGHT_EFFECT_KNIGHT)
|
#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)
|
||||||
|
|
||||||
static uint8_t get_interval_time(const uint8_t *default_interval_address, uint8_t velocikey_min, uint8_t velocikey_max) {
|
static uint8_t get_interval_time(const uint8_t *default_interval_address, uint8_t velocikey_min, uint8_t velocikey_max) {
|
||||||
return
|
return
|
||||||
|
@ -904,6 +905,12 @@ void rgblight_task(void) {
|
||||||
interval_time = 500;
|
interval_time = 500;
|
||||||
effect_func = (effect_func_t)rgblight_effect_alternating;
|
effect_func = (effect_func_t)rgblight_effect_alternating;
|
||||||
}
|
}
|
||||||
|
# endif
|
||||||
|
# ifdef RGBLIGHT_EFFECT_TWINKLE
|
||||||
|
else if (rgblight_status.base_mode == RGBLIGHT_MODE_TWINKLE) {
|
||||||
|
interval_time = get_interval_time(&RGBLED_TWINKLE_INTERVALS[delta % 3], 5, 50);
|
||||||
|
effect_func = (effect_func_t)rgblight_effect_twinkle;
|
||||||
|
}
|
||||||
# endif
|
# endif
|
||||||
if (animation_status.restart) {
|
if (animation_status.restart) {
|
||||||
animation_status.restart = false;
|
animation_status.restart = false;
|
||||||
|
@ -1189,3 +1196,59 @@ void rgblight_effect_alternating(animation_status_t *anim) {
|
||||||
anim->pos = (anim->pos + 1) % 2;
|
anim->pos = (anim->pos + 1) % 2;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef RGBLIGHT_EFFECT_TWINKLE
|
||||||
|
__attribute__((weak)) const uint8_t RGBLED_TWINKLE_INTERVALS[] PROGMEM = {50, 25, 10};
|
||||||
|
|
||||||
|
typedef struct PACKED {
|
||||||
|
HSV hsv;
|
||||||
|
uint8_t life;
|
||||||
|
bool up;
|
||||||
|
} TwinkleState;
|
||||||
|
|
||||||
|
static TwinkleState led_twinkle_state[RGBLED_NUM];
|
||||||
|
|
||||||
|
void rgblight_effect_twinkle(animation_status_t *anim) {
|
||||||
|
|
||||||
|
bool random_color = anim->delta / 3;
|
||||||
|
bool restart = anim->pos == 0;
|
||||||
|
anim->pos = 1;
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < rgblight_ranges.effect_num_leds; i++) {
|
||||||
|
TwinkleState *t = &(led_twinkle_state[i]);
|
||||||
|
HSV *c = &(t->hsv);
|
||||||
|
if (restart) {
|
||||||
|
// Restart
|
||||||
|
t->life = 0;
|
||||||
|
t->hsv.v = 0;
|
||||||
|
} else if (t->life) {
|
||||||
|
// This LED is already on, either brightening or dimming
|
||||||
|
t->life--;
|
||||||
|
uint8_t on = t->up ? RGBLIGHT_EFFECT_TWINKLE_LIFE - t->life : t->life;
|
||||||
|
c->v = (uint16_t) rgblight_config.val * on / RGBLIGHT_EFFECT_TWINKLE_LIFE;
|
||||||
|
if (t->life == 0 && t->up) {
|
||||||
|
t->up = false;
|
||||||
|
t->life = RGBLIGHT_EFFECT_TWINKLE_LIFE;
|
||||||
|
}
|
||||||
|
if (!random_color) {
|
||||||
|
c->h = rgblight_config.hue;
|
||||||
|
c->s = rgblight_config.sat;
|
||||||
|
}
|
||||||
|
} else if (rand() < RAND_MAX * RGBLIGHT_EFFECT_TWINKLE_PROBABILITY) {
|
||||||
|
// This LED is off, but was randomly selected to start brightening
|
||||||
|
c->h = random_color ? rand() % 0xFF : rgblight_config.hue;
|
||||||
|
c->s = random_color ? (rand() % (rgblight_config.sat / 2)) + (rgblight_config.sat / 2) : rgblight_config.sat;
|
||||||
|
c->v = 0;
|
||||||
|
t->life = RGBLIGHT_EFFECT_TWINKLE_LIFE;
|
||||||
|
t->up = true;
|
||||||
|
} else {
|
||||||
|
// This LED is off, and was NOT selected to start brightening
|
||||||
|
}
|
||||||
|
|
||||||
|
LED_TYPE *ledp = led + i + rgblight_ranges.effect_start_pos;
|
||||||
|
sethsv(c->h, c->s, c->v, ledp);
|
||||||
|
}
|
||||||
|
|
||||||
|
rgblight_set();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -59,6 +59,12 @@
|
||||||
| 34 | RGBLIGHT_MODE_STATIC_GRADIENT + 9 |
|
| 34 | RGBLIGHT_MODE_STATIC_GRADIENT + 9 |
|
||||||
| 35 | RGBLIGHT_MODE_RGB_TEST |
|
| 35 | RGBLIGHT_MODE_RGB_TEST |
|
||||||
| 36 | RGBLIGHT_MODE_ALTERNATING |
|
| 36 | RGBLIGHT_MODE_ALTERNATING |
|
||||||
|
| 37 | RGBLIGHT_MODE_TWINKLE |
|
||||||
|
| 38 | RGBLIGHT_MODE_TWINKLE + 1 |
|
||||||
|
| 39 | RGBLIGHT_MODE_TWINKLE + 2 |
|
||||||
|
| 40 | RGBLIGHT_MODE_TWINKLE + 3 |
|
||||||
|
| 41 | RGBLIGHT_MODE_TWINKLE + 4 |
|
||||||
|
| 42 | RGBLIGHT_MODE_TWINKLE + 5 |
|
||||||
|-----------------|-----------------------------------|
|
|-----------------|-----------------------------------|
|
||||||
*****/
|
*****/
|
||||||
|
|
||||||
|
@ -73,6 +79,7 @@
|
||||||
# define RGBLIGHT_EFFECT_STATIC_GRADIENT
|
# define RGBLIGHT_EFFECT_STATIC_GRADIENT
|
||||||
# define RGBLIGHT_EFFECT_RGB_TEST
|
# define RGBLIGHT_EFFECT_RGB_TEST
|
||||||
# define RGBLIGHT_EFFECT_ALTERNATING
|
# define RGBLIGHT_EFFECT_ALTERNATING
|
||||||
|
# define RGBLIGHT_EFFECT_TWINKLE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef RGBLIGHT_STATIC_PATTERNS
|
#ifdef RGBLIGHT_STATIC_PATTERNS
|
||||||
|
@ -89,7 +96,8 @@
|
||||||
|| defined(RGBLIGHT_EFFECT_KNIGHT) \
|
|| defined(RGBLIGHT_EFFECT_KNIGHT) \
|
||||||
|| defined(RGBLIGHT_EFFECT_CHRISTMAS) \
|
|| defined(RGBLIGHT_EFFECT_CHRISTMAS) \
|
||||||
|| defined(RGBLIGHT_EFFECT_RGB_TEST) \
|
|| defined(RGBLIGHT_EFFECT_RGB_TEST) \
|
||||||
|| defined(RGBLIGHT_EFFECT_ALTERNATING)
|
|| defined(RGBLIGHT_EFFECT_ALTERNATING) \
|
||||||
|
|| defined(RGBLIGHT_EFFECT_TWINKLE)
|
||||||
# define RGBLIGHT_USE_TIMER
|
# define RGBLIGHT_USE_TIMER
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -141,6 +149,14 @@ enum RGBLIGHT_EFFECT_MODE {
|
||||||
# define RGBLIGHT_EFFECT_CHRISTMAS_STEP 2
|
# define RGBLIGHT_EFFECT_CHRISTMAS_STEP 2
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
# ifndef RGBLIGHT_EFFECT_TWINKLE_LIFE
|
||||||
|
# define RGBLIGHT_EFFECT_TWINKLE_LIFE 75
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# ifndef RGBLIGHT_EFFECT_TWINKLE_PROBABILITY
|
||||||
|
# define RGBLIGHT_EFFECT_TWINKLE_PROBABILITY 1/127
|
||||||
|
# endif
|
||||||
|
|
||||||
# ifndef RGBLIGHT_HUE_STEP
|
# ifndef RGBLIGHT_HUE_STEP
|
||||||
# define RGBLIGHT_HUE_STEP 8
|
# define RGBLIGHT_HUE_STEP 8
|
||||||
# endif
|
# endif
|
||||||
|
@ -208,6 +224,7 @@ extern const uint8_t RGBLED_RAINBOW_SWIRL_INTERVALS[3] PROGMEM;
|
||||||
extern const uint8_t RGBLED_SNAKE_INTERVALS[3] PROGMEM;
|
extern const uint8_t RGBLED_SNAKE_INTERVALS[3] PROGMEM;
|
||||||
extern const uint8_t RGBLED_KNIGHT_INTERVALS[3] PROGMEM;
|
extern const uint8_t RGBLED_KNIGHT_INTERVALS[3] PROGMEM;
|
||||||
extern const uint16_t RGBLED_RGBTEST_INTERVALS[1] PROGMEM;
|
extern const uint16_t RGBLED_RGBTEST_INTERVALS[1] PROGMEM;
|
||||||
|
extern const uint8_t RGBLED_TWINKLE_INTERVALS[3] PROGMEM;
|
||||||
extern bool is_rgblight_initialized;
|
extern bool is_rgblight_initialized;
|
||||||
|
|
||||||
// Should stay in sycn with rgb matrix config as we reuse eeprom storage for both (for now)
|
// 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);
|
||||||
void rgblight_effect_christmas(animation_status_t *anim);
|
void rgblight_effect_christmas(animation_status_t *anim);
|
||||||
void rgblight_effect_rgbtest(animation_status_t *anim);
|
void rgblight_effect_rgbtest(animation_status_t *anim);
|
||||||
void rgblight_effect_alternating(animation_status_t *anim);
|
void rgblight_effect_alternating(animation_status_t *anim);
|
||||||
|
void rgblight_effect_twinkle(animation_status_t *anim);
|
||||||
|
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,14 @@ _RGBM_SINGLE_DYNAMIC(RGB_TEST)
|
||||||
# ifdef RGBLIGHT_EFFECT_ALTERNATING
|
# ifdef RGBLIGHT_EFFECT_ALTERNATING
|
||||||
_RGBM_SINGLE_DYNAMIC(ALTERNATING)
|
_RGBM_SINGLE_DYNAMIC(ALTERNATING)
|
||||||
# endif
|
# endif
|
||||||
|
# ifdef RGBLIGHT_EFFECT_TWINKLE
|
||||||
|
_RGBM_MULTI_DYNAMIC(TWINKLE)
|
||||||
|
_RGBM_TMP_DYNAMIC(twinkle_38, TWINKLE)
|
||||||
|
_RGBM_TMP_DYNAMIC(twinkle_39, TWINKLE)
|
||||||
|
_RGBM_TMP_DYNAMIC(twinkle_40, TWINKLE)
|
||||||
|
_RGBM_TMP_DYNAMIC(twinkle_41, TWINKLE)
|
||||||
|
_RGBM_TMP_DYNAMIC(TWINKLE_end, TWINKLE)
|
||||||
|
# endif
|
||||||
//// Add a new mode here.
|
//// Add a new mode here.
|
||||||
// #ifdef RGBLIGHT_EFFECT_<name>
|
// #ifdef RGBLIGHT_EFFECT_<name>
|
||||||
// _RGBM_<SINGLE|MULTI>_<STATIC|DYNAMIC>( <name> )
|
// _RGBM_<SINGLE|MULTI>_<STATIC|DYNAMIC>( <name> )
|
||||||
|
|
Loading…
Reference in a new issue