From 62b62d4b500733a7d1c7982211141426061f36ae Mon Sep 17 00:00:00 2001 From: Your Name Date: Tue, 2 Sep 2025 21:04:19 -0400 Subject: [PATCH 1/3] add Rainbow Shimmer effect. Just like Rainbow Cycle but with a white flash that runs across the segment --- wled00/FX.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ wled00/FX.h | 3 ++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index f3163dc18e..811ecf423e 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -544,6 +544,45 @@ uint16_t mode_rainbow_cycle(void) { } static const char _data_FX_MODE_RAINBOW_CYCLE[] PROGMEM = "Rainbow@!,Size;;!"; +/* + * Cycles a rainbow over the entire string of LEDs, with a white flash that goes across it. + */ +uint16_t mode_rainbow_shimmer() { + + unsigned counter = (strip.now * ((SEGMENT.speed >> 2) + 2)) & 0xFFFF; + counter = counter >> 8; + + uint32_t shimmerSpeed = 100 + (255 - SEGMENT.custom2) * 40; //ranges from 100-10260ms + uint32_t shimmerSize = (SEGMENT.custom3 * SEGLEN / 2 >> 5) + 1; + uint32_t cycleTime = (255 - SEGMENT.custom1) * 150 + shimmerSpeed; + + uint32_t percCycle = strip.now % cycleTime; + float shimmerIndex = (float)percCycle / (float)shimmerSpeed * (SEGLEN + 2*shimmerSize); + + shimmerIndex -= shimmerSize; + + // reverse direction of shimmer + if(!SEGMENT.check1) { + shimmerIndex = (float)SEGLEN - shimmerIndex; + } + + + for (unsigned i = 0; i < SEGLEN; i++) { + // Standard rainbow effect. + uint8_t index = (i * (16 << (SEGMENT.intensity / 29)) / SEGLEN) + counter; + SEGMENT.setPixelColor(i, SEGMENT.color_wheel(index)); + + //shimmer logic + float distFromShimmerCenter = fabsf(shimmerIndex - i); + // Only process pixels that are within the shimmer's range. + if (distFromShimmerCenter < shimmerSize) { + SEGMENT.setPixelColor(i, color_blend(SEGMENT.getPixelColor(i), 0xFFFFFF, (uint8_t)(255 * (1.0f - (distFromShimmerCenter / shimmerSize))))); + } + } + + return FRAMETIME; +} +static const char _data_FX_MODE_RAINBOW_SHIMMER[] PROGMEM = "Rainbow Shimmer@!,Size,Shimmer Frq,Shimmer Speed,Shimmer Length,Reverse;;c1=231,c2=221"; /* * Alternating pixels running function. @@ -10665,6 +10704,7 @@ void WS2812FX::setupEffectData() { addEffect(FX_MODE_DYNAMIC, &mode_dynamic, _data_FX_MODE_DYNAMIC); addEffect(FX_MODE_RAINBOW, &mode_rainbow, _data_FX_MODE_RAINBOW); addEffect(FX_MODE_RAINBOW_CYCLE, &mode_rainbow_cycle, _data_FX_MODE_RAINBOW_CYCLE); + addEffect(FX_MODE_RAINBOW_SHIMMER, &mode_rainbow_shimmer, _data_FX_MODE_RAINBOW_SHIMMER); addEffect(FX_MODE_SCAN, &mode_scan, _data_FX_MODE_SCAN); addEffect(FX_MODE_DUAL_SCAN, &mode_dual_scan, _data_FX_MODE_DUAL_SCAN); addEffect(FX_MODE_FADE, &mode_fade, _data_FX_MODE_FADE); diff --git a/wled00/FX.h b/wled00/FX.h index 097c857caf..bdd1154855 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -374,7 +374,8 @@ extern byte realtimeMode; // used in getMappedPixelIndex() #define FX_MODE_PS1DSONICBOOM 215 #define FX_MODE_PS1DSPRINGY 216 #define FX_MODE_PARTICLEGALAXY 217 -#define MODE_COUNT 218 +#define FX_MODE_RAINBOW_SHIMMER 218 +#define MODE_COUNT 219 #define BLEND_STYLE_FADE 0x00 // universal From 4f55dc3f2821fdea1e3e8c3edcb50b8dc092f6ee Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 3 Sep 2025 21:47:23 -0400 Subject: [PATCH 2/3] changed effect to be used as an overlay, removed float. --- wled00/FX.cpp | 40 ++++++++++++++++++---------------------- wled00/FX.h | 2 +- 2 files changed, 19 insertions(+), 23 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 811ecf423e..e570e426e2 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -547,42 +547,38 @@ static const char _data_FX_MODE_RAINBOW_CYCLE[] PROGMEM = "Rainbow@!,Size;;!"; /* * Cycles a rainbow over the entire string of LEDs, with a white flash that goes across it. */ -uint16_t mode_rainbow_shimmer() { +uint16_t mode_shimmer() { - unsigned counter = (strip.now * ((SEGMENT.speed >> 2) + 2)) & 0xFFFF; - counter = counter >> 8; - - uint32_t shimmerSpeed = 100 + (255 - SEGMENT.custom2) * 40; //ranges from 100-10260ms - uint32_t shimmerSize = (SEGMENT.custom3 * SEGLEN / 2 >> 5) + 1; - uint32_t cycleTime = (255 - SEGMENT.custom1) * 150 + shimmerSpeed; + uint32_t shimmerSpeed = 100 + (255 - SEGMENT.speed) * 40; // [100,10260ms] + uint32_t shimmerSize = (SEGMENT.custom1 * SEGLEN >> 9) + 1; // [1,SEGLEN/2+1] + uint32_t cycleTime = (255 - SEGMENT.intensity) * 150 + shimmerSpeed; // [100, 48510] uint32_t percCycle = strip.now % cycleTime; - float shimmerIndex = (float)percCycle / (float)shimmerSpeed * (SEGLEN + 2*shimmerSize); + uint64_t shimmerIndex = ((uint64_t)percCycle<<8) / shimmerSpeed * (SEGLEN + 2*shimmerSize); - shimmerIndex -= shimmerSize; + shimmerIndex -= shimmerSize << 8; - // reverse direction of shimmer + //change direction unless reverse is checked if(!SEGMENT.check1) { - shimmerIndex = (float)SEGLEN - shimmerIndex; + shimmerIndex = (((uint64_t) SEGLEN) << 8) - shimmerIndex; } - for (unsigned i = 0; i < SEGLEN; i++) { - // Standard rainbow effect. - uint8_t index = (i * (16 << (SEGMENT.intensity / 29)) / SEGLEN) + counter; - SEGMENT.setPixelColor(i, SEGMENT.color_wheel(index)); - - //shimmer logic - float distFromShimmerCenter = fabsf(shimmerIndex - i); + //shimmer logic + uint64_t distFromShimmerCenter = abs((int32_t)shimmerIndex - ((int64_t)i << 8)); + // Only process pixels that are within the shimmer's range. - if (distFromShimmerCenter < shimmerSize) { - SEGMENT.setPixelColor(i, color_blend(SEGMENT.getPixelColor(i), 0xFFFFFF, (uint8_t)(255 * (1.0f - (distFromShimmerCenter / shimmerSize))))); + if (distFromShimmerCenter < (shimmerSize<<8)) { + SEGMENT.setPixelColor(i, color_blend(SEGCOLOR(1), SEGCOLOR(0), 255-(distFromShimmerCenter / shimmerSize))); + } + else { + SEGMENT.setPixelColor(i,SEGCOLOR(1)); } } return FRAMETIME; } -static const char _data_FX_MODE_RAINBOW_SHIMMER[] PROGMEM = "Rainbow Shimmer@!,Size,Shimmer Frq,Shimmer Speed,Shimmer Length,Reverse;;c1=231,c2=221"; +static const char _data_FX_MODE_SHIMMER[] PROGMEM = "Shimmer@Speed,Frequancy,Size,,,Reverse;!!;sx=231,ix=221"; /* * Alternating pixels running function. @@ -10704,7 +10700,7 @@ void WS2812FX::setupEffectData() { addEffect(FX_MODE_DYNAMIC, &mode_dynamic, _data_FX_MODE_DYNAMIC); addEffect(FX_MODE_RAINBOW, &mode_rainbow, _data_FX_MODE_RAINBOW); addEffect(FX_MODE_RAINBOW_CYCLE, &mode_rainbow_cycle, _data_FX_MODE_RAINBOW_CYCLE); - addEffect(FX_MODE_RAINBOW_SHIMMER, &mode_rainbow_shimmer, _data_FX_MODE_RAINBOW_SHIMMER); + addEffect(FX_MODE_SHIMMER, &mode_shimmer, _data_FX_MODE_SHIMMER); addEffect(FX_MODE_SCAN, &mode_scan, _data_FX_MODE_SCAN); addEffect(FX_MODE_DUAL_SCAN, &mode_dual_scan, _data_FX_MODE_DUAL_SCAN); addEffect(FX_MODE_FADE, &mode_fade, _data_FX_MODE_FADE); diff --git a/wled00/FX.h b/wled00/FX.h index bdd1154855..a0cd9219ab 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -374,7 +374,7 @@ extern byte realtimeMode; // used in getMappedPixelIndex() #define FX_MODE_PS1DSONICBOOM 215 #define FX_MODE_PS1DSPRINGY 216 #define FX_MODE_PARTICLEGALAXY 217 -#define FX_MODE_RAINBOW_SHIMMER 218 +#define FX_MODE_SHIMMER 218 #define MODE_COUNT 219 From c619a4e9f71f4cca93660dcf339e35bd9c409e4e Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 4 Sep 2025 09:58:30 -0400 Subject: [PATCH 3/3] removed 64bit ints and added color pallete support --- wled00/FX.cpp | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index e570e426e2..f23d4a28d9 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -545,40 +545,45 @@ uint16_t mode_rainbow_cycle(void) { static const char _data_FX_MODE_RAINBOW_CYCLE[] PROGMEM = "Rainbow@!,Size;;!"; /* - * Cycles a rainbow over the entire string of LEDs, with a white flash that goes across it. + * adds a predictable white flash across the segment */ uint16_t mode_shimmer() { - - uint32_t shimmerSpeed = 100 + (255 - SEGMENT.speed) * 40; // [100,10260ms] - uint32_t shimmerSize = (SEGMENT.custom1 * SEGLEN >> 9) + 1; // [1,SEGLEN/2+1] - uint32_t cycleTime = (255 - SEGMENT.intensity) * 150 + shimmerSpeed; // [100, 48510] - + uint32_t segmentSize; + //gaurd against buffer overflow, should never exceed this based + //on 1000 pixles per GPIO and 10 strips + if(SEGLEN>10000) { + segmentSize = 10000; + } else { + segmentSize=SEGLEN; + } + + uint32_t shimmerSpeed = 100 + (255 - SEGMENT.speed) * 40; // [100,10300] + uint32_t shimmerSize = (SEGMENT.custom1 * segmentSize >> 9) + 1; // [1,(SEGLEN/2)+1] capped at 5001. + uint32_t cycleTime = (255 - SEGMENT.intensity) * 150 + shimmerSpeed; // [100, 48550] uint32_t percCycle = strip.now % cycleTime; - uint64_t shimmerIndex = ((uint64_t)percCycle<<8) / shimmerSpeed * (SEGLEN + 2*shimmerSize); + int32_t shimmerIndex = (percCycle<<8) / shimmerSpeed * (segmentSize + 2*shimmerSize); // maxamum >124285 shimmerIndex -= shimmerSize << 8; //change direction unless reverse is checked if(!SEGMENT.check1) { - shimmerIndex = (((uint64_t) SEGLEN) << 8) - shimmerIndex; + shimmerIndex = ((segmentSize) << 8) - shimmerIndex; } - for (unsigned i = 0; i < SEGLEN; i++) { - //shimmer logic - uint64_t distFromShimmerCenter = abs((int32_t)shimmerIndex - ((int64_t)i << 8)); - - // Only process pixels that are within the shimmer's range. + for (uint32_t i = 0; i < segmentSize; i++) { + + // slightly dangerous, but shimmer index is bounded to be safe + uint32_t distFromShimmerCenter = abs((int32_t)shimmerIndex - ((int32_t)i << 8)); if (distFromShimmerCenter < (shimmerSize<<8)) { - SEGMENT.setPixelColor(i, color_blend(SEGCOLOR(1), SEGCOLOR(0), 255-(distFromShimmerCenter / shimmerSize))); + SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(255-(distFromShimmerCenter / shimmerSize),false,PALETTE_SOLID_WRAP,0)); } else { SEGMENT.setPixelColor(i,SEGCOLOR(1)); } } - return FRAMETIME; } -static const char _data_FX_MODE_SHIMMER[] PROGMEM = "Shimmer@Speed,Frequancy,Size,,,Reverse;!!;sx=231,ix=221"; +static const char _data_FX_MODE_SHIMMER[] PROGMEM = "Shimmer@Speed,Frequency,Size,,,Reverse;Fx,Bg,Cx;!;m12;sx=231,ix=221,pal=4"; /* * Alternating pixels running function.