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
				
			
		| 
						 | 
				
			
			@ -15,6 +15,7 @@
 | 
			
		|||
 */
 | 
			
		||||
#include <math.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#ifdef __AVR__
 | 
			
		||||
#    include <avr/eeprom.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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#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) {
 | 
			
		||||
    return
 | 
			
		||||
| 
						 | 
				
			
			@ -904,6 +905,12 @@ void rgblight_task(void) {
 | 
			
		|||
            interval_time = 500;
 | 
			
		||||
            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
 | 
			
		||||
        if (animation_status.restart) {
 | 
			
		||||
            animation_status.restart    = false;
 | 
			
		||||
| 
						 | 
				
			
			@ -1189,3 +1196,59 @@ void rgblight_effect_alternating(animation_status_t *anim) {
 | 
			
		|||
    anim->pos = (anim->pos + 1) % 2;
 | 
			
		||||
}
 | 
			
		||||
#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 |
 | 
			
		||||
|       35        | RGBLIGHT_MODE_RGB_TEST            |
 | 
			
		||||
|       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_RGB_TEST
 | 
			
		||||
#    define RGBLIGHT_EFFECT_ALTERNATING
 | 
			
		||||
#    define RGBLIGHT_EFFECT_TWINKLE
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef RGBLIGHT_STATIC_PATTERNS
 | 
			
		||||
| 
						 | 
				
			
			@ -89,7 +96,8 @@
 | 
			
		|||
  || defined(RGBLIGHT_EFFECT_KNIGHT)        \
 | 
			
		||||
  || defined(RGBLIGHT_EFFECT_CHRISTMAS)     \
 | 
			
		||||
  || defined(RGBLIGHT_EFFECT_RGB_TEST)      \
 | 
			
		||||
  || defined(RGBLIGHT_EFFECT_ALTERNATING)
 | 
			
		||||
  || defined(RGBLIGHT_EFFECT_ALTERNATING)   \
 | 
			
		||||
  || defined(RGBLIGHT_EFFECT_TWINKLE)
 | 
			
		||||
#    define RGBLIGHT_USE_TIMER
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -141,6 +149,14 @@ enum RGBLIGHT_EFFECT_MODE {
 | 
			
		|||
#        define RGBLIGHT_EFFECT_CHRISTMAS_STEP 2
 | 
			
		||||
#    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
 | 
			
		||||
#        define RGBLIGHT_HUE_STEP 8
 | 
			
		||||
#    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_KNIGHT_INTERVALS[3] PROGMEM;
 | 
			
		||||
extern const uint16_t RGBLED_RGBTEST_INTERVALS[1] PROGMEM;
 | 
			
		||||
extern const uint8_t  RGBLED_TWINKLE_INTERVALS[3] PROGMEM;
 | 
			
		||||
extern bool           is_rgblight_initialized;
 | 
			
		||||
 | 
			
		||||
// 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_rgbtest(animation_status_t *anim);
 | 
			
		||||
void rgblight_effect_alternating(animation_status_t *anim);
 | 
			
		||||
void rgblight_effect_twinkle(animation_status_t *anim);
 | 
			
		||||
 | 
			
		||||
#    endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -53,6 +53,14 @@ _RGBM_SINGLE_DYNAMIC(RGB_TEST)
 | 
			
		|||
#    ifdef RGBLIGHT_EFFECT_ALTERNATING
 | 
			
		||||
_RGBM_SINGLE_DYNAMIC(ALTERNATING)
 | 
			
		||||
#    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.
 | 
			
		||||
// #ifdef RGBLIGHT_EFFECT_<name>
 | 
			
		||||
//    _RGBM_<SINGLE|MULTI>_<STATIC|DYNAMIC>( <name> )
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue