From fae127c2b9a986e1d827d352f615cef5b1d3cbdb Mon Sep 17 00:00:00 2001 From: acheronfail Date: Fri, 16 Aug 2024 21:51:27 +0930 Subject: [PATCH 1/2] Improve color_wheel so it blends more between colors Fix: improved accuracy of generated rainbow colors for LEDs --- src/leds.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/leds.c b/src/leds.c index a7dae68..92b880b 100644 --- a/src/leds.c +++ b/src/leds.c @@ -40,6 +40,7 @@ #define W(c) ((uint8_t) ((c) >> 24)) #define RGB(r, g, b) ((r) << 16 | (g) << 8 | (b)) #define RGBW(r, g, b, w) ((w) << 24 | (r) << 16 | (g) << 8 | (b)) +#define TAU (2.0 * M_PI) static const uint32_t colors[] = { 0x00000000, // BLACK @@ -99,18 +100,21 @@ static uint32_t color_blend(uint32_t color1, uint32_t color2, float blend) { return RGBW(r, g, b, w); } -// Borrowed from WLED +// This function is an approximation of `sqrtf(sinf(x) * 0.5 + 0.5)` +inline static float taylor_series(float zero_to_tau) { + float x = (-0.5 * zero_to_tau) + 2.4; + float x3 = x * x * x; + float x5 = x3 * x * x; + float r = fabs(x - (x3 / 6.0) + (x5 / 120.0)); + return fminf(r, 1.0f); +} + static uint32_t color_wheel(uint8_t pos) { - pos = 255 - pos; - if (pos < 85) { - return ((uint32_t) (255 - pos * 3) << 16) | ((uint32_t) 0 << 8) | (pos * 3); - } else if (pos < 170) { - pos -= 85; - return ((uint32_t) 0 << 16) | ((uint32_t) (pos * 3) << 8) | (255 - pos * 3); - } else { - pos -= 170; - return ((uint32_t) (pos * 3) << 16) | ((uint32_t) (255 - pos * 3) << 8) | 0; - } + float norm = (float) pos / 255.0; + float r = taylor_series((norm + 0.0 / 3.0) * TAU); + float b = taylor_series((norm + 1.0 / 3.0) * TAU); + float g = taylor_series((norm + 2.0 / 3.0) * TAU); + return ((uint8_t) (r * 255) << 16) | ((uint8_t) (g * 255) << 8) | (uint8_t) (b * 255); } static void sattolo_shuffle(uint32_t seed, uint8_t *array, uint8_t length) { From fae191d297843dd37a8dfef07e049fe406e76c7c Mon Sep 17 00:00:00 2001 From: acheronfail Date: Fri, 16 Aug 2024 21:31:34 +0930 Subject: [PATCH 2/2] LEDs: add Rainbow Fade and Rainbow Cycle effects Using "Solid" on the headlights and "Rainbow Cycle" on the taillights can replicate the "Mullet" setting on the Float package. Using "Rainbow Cycle" on both replicates the "Rave" effect from the Float package. Feature: add Rainbow Fade and Rainbow Cycle effects --- src/conf/datatypes.h | 2 ++ src/conf/settings.xml | 10 ++++++++++ src/leds.c | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+) diff --git a/src/conf/datatypes.h b/src/conf/datatypes.h index 14a39bf..3db3f4c 100644 --- a/src/conf/datatypes.h +++ b/src/conf/datatypes.h @@ -86,6 +86,8 @@ typedef enum { LED_MODE_STROBE, LED_MODE_KNIGHT_RIDER, LED_MODE_FELONY, + LED_MODE_RAINBOW_CYCLE, + LED_MODE_RAINBOW_FADE, } LedMode; typedef enum { diff --git a/src/conf/settings.xml b/src/conf/settings.xml index 5ea47bb..1ca3939 100644 --- a/src/conf/settings.xml +++ b/src/conf/settings.xml @@ -2255,6 +2255,8 @@ p, li { white-space: pre-wrap; } Strobe Knight Rider Felony + Rainbow Cycle + Rainbow Fade Front Brightness @@ -2417,6 +2419,8 @@ p, li { white-space: pre-wrap; } Strobe Knight Rider Felony + Rainbow Cycle + Rainbow Fade Rear Brightness @@ -2579,6 +2583,8 @@ p, li { white-space: pre-wrap; } Strobe Knight Rider Felony + Rainbow Cycle + Rainbow Fade Headlights Brightness @@ -2743,6 +2749,8 @@ p, li { white-space: pre-wrap; } Strobe Knight Rider Felony + Rainbow Cycle + Rainbow Fade Taillights Brightness @@ -3035,6 +3043,8 @@ p, li { white-space: pre-wrap; } Strobe Knight Rider Felony + Rainbow Cycle + Rainbow Fade Status Idle Brightness diff --git a/src/leds.c b/src/leds.c index 92b880b..6c72b28 100644 --- a/src/leds.c +++ b/src/leds.c @@ -312,6 +312,32 @@ static void anim_felony(Leds *leds, const LedStrip *strip, const LedBar *bar, fl } } +static const uint32_t rainbow_cycle_colors[] = { + 0x00FFFF00, + 0x0000FF00, + 0x0000FFFF, + 0x000000FF, + 0x00FF00FF, + 0x00FF0000, +}; +static const uint8_t rainbow_cycle_colors_len = + sizeof(rainbow_cycle_colors) / sizeof(rainbow_cycle_colors[0]); + +static void anim_rainbow_cycle(Leds *leds, const LedStrip *strip, float time) { + uint8_t color_idx = (uint8_t) (time / 0.1f) % rainbow_cycle_colors_len; + strip_set_color(leds, strip, rainbow_cycle_colors[color_idx], strip->brightness, 1.0f); +} + +static void anim_rgb_fade(Leds *leds, const LedStrip *strip, float time) { + strip_set_color( + leds, + strip, + color_wheel((uint8_t) floorf(fmodf(time, 4.0f) * 255.0f)), + strip->brightness, + 1.0f + ); +} + static void led_strip_animate(Leds *leds, const LedStrip *strip, const LedBar *bar, float time) { time *= bar->speed; @@ -334,6 +360,12 @@ static void led_strip_animate(Leds *leds, const LedStrip *strip, const LedBar *b case LED_MODE_FELONY: anim_felony(leds, strip, bar, time); break; + case LED_MODE_RAINBOW_CYCLE: + anim_rainbow_cycle(leds, strip, time); + break; + case LED_MODE_RAINBOW_FADE: + anim_rgb_fade(leds, strip, time); + break; } }