From 8600360173083d379f1437a32af580d498c1ccbf Mon Sep 17 00:00:00 2001 From: fishbone-git Date: Tue, 24 Dec 2019 14:46:07 +0100 Subject: [PATCH 01/30] more effects to FRAMETIME --- wled00/FX.cpp | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 8349f0f6..4410a43b 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -961,6 +961,10 @@ uint16_t WS2812FX::mode_halloween(void) { * Random colored pixels running. */ uint16_t WS2812FX::mode_running_random(void) { + uint32_t cycleTime = 25 + (3 * (uint32_t)(255 - SEGMENT.speed)); + uint32_t it = now / cycleTime; + if (SEGENV.aux1 == it) return FRAMETIME; + for(uint16_t i=SEGLEN-1; i > 0; i--) { setPixelColor(SEGMENT.start + i, getPixelColor(SEGMENT.start + i - 1)); } @@ -975,7 +979,9 @@ uint16_t WS2812FX::mode_running_random(void) { { SEGENV.step = 0; } - return SPEED_FORMULA_L; + + SEGENV.aux1 = it; + return FRAMETIME; } @@ -1091,6 +1097,10 @@ uint16_t WS2812FX::mode_rain() * Fire flicker function */ uint16_t WS2812FX::mode_fire_flicker(void) { + uint32_t cycleTime = 40 + (255 - SEGMENT.speed); + uint32_t it = now / cycleTime; + if (SEGENV.step == it) return FRAMETIME; + byte w = (SEGCOLOR(0) >> 24) & 0xFF; byte r = (SEGCOLOR(0) >> 16) & 0xFF; byte g = (SEGCOLOR(0) >> 8) & 0xFF; @@ -1105,7 +1115,9 @@ uint16_t WS2812FX::mode_fire_flicker(void) { setPixelColor(i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 0, 255 - flicker)); } } - return 20 + random((255 - SEGMENT.speed),(2 * (uint16_t)(255 - SEGMENT.speed))); + + SEGENV.step = it; + return FRAMETIME; } @@ -1285,6 +1297,7 @@ uint16_t WS2812FX::mode_icu(void) { setPixelColor(SEGMENT.start + dest, col); setPixelColor(SEGMENT.start + dest + SEGLEN/2, col); + if (SEGMENT.intensity > 127) return FRAMETIME; return SPEED_FORMULA_L; } @@ -1294,6 +1307,11 @@ uint16_t WS2812FX::mode_icu(void) { */ uint16_t WS2812FX::mode_tricolor_wipe(void) { + uint32_t cycleTime = 40 + (3 * (uint32_t)(255 - SEGMENT.speed)); + uint32_t it = now / cycleTime; + if (SEGENV.step == it) return FRAMETIME; + uint8_t incr = it-SEGENV.step; + if(SEGENV.step < SEGLEN) { uint32_t led_offset = SEGENV.step; setPixelColor(SEGMENT.start + led_offset, SEGCOLOR(0)); @@ -1307,7 +1325,7 @@ uint16_t WS2812FX::mode_tricolor_wipe(void) } SEGENV.step = (SEGENV.step + 1) % (SEGLEN * 3); - return SPEED_FORMULA_L; + return FRAMETIME; } @@ -1318,6 +1336,9 @@ uint16_t WS2812FX::mode_tricolor_wipe(void) */ uint16_t WS2812FX::mode_tricolor_fade(void) { + uint16_t counter = now * ((SEGMENT.speed >> 3) +1); + SEGENV.step = (counter * 768) >> 16; + uint32_t color1 = 0, color2 = 0; byte stage = 0; @@ -1348,10 +1369,7 @@ uint16_t WS2812FX::mode_tricolor_fade(void) setPixelColor(i, color); } - SEGENV.step += 4; - if(SEGENV.step >= 768) SEGENV.step = 0; - - return 5 + ((uint32_t)(255 - SEGMENT.speed) / 10); + return FRAMETIME; } @@ -1361,6 +1379,10 @@ uint16_t WS2812FX::mode_tricolor_fade(void) */ uint16_t WS2812FX::mode_multi_comet(void) { + uint32_t cycleTime = 20 + (2 * (uint32_t)(255 - SEGMENT.speed)); + uint32_t it = now / cycleTime; + if (SEGENV.step == it) return FRAMETIME; + fade_out(SEGMENT.intensity); static uint16_t comets[] = {UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX}; @@ -1382,7 +1404,9 @@ uint16_t WS2812FX::mode_multi_comet(void) } } } - return SPEED_FORMULA_L; + + SEGENV.step = it; + return FRAMETIME; } From 0d4d1eff94ccbf43a8f047968fd8cd9611139070 Mon Sep 17 00:00:00 2001 From: fishbone-git Date: Tue, 24 Dec 2019 14:58:22 +0100 Subject: [PATCH 02/30] Revert "Merge branch 'master' into framerate" This reverts commit 38cc4603580249cf317353b97941a8b0a1b0080f, reversing changes made to 8600360173083d379f1437a32af580d498c1ccbf. --- wled00/FX.cpp | 28 ++++++++++++++-------------- wled00/FX.h | 14 ++------------ wled00/wled00.ino | 2 +- wled00/wled01_eeprom.ino | 7 ------- 4 files changed, 17 insertions(+), 34 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 1791b710..4410a43b 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -301,24 +301,24 @@ uint16_t WS2812FX::scan(bool dual) uint32_t cycleTime = 750 + (255 - SEGMENT.speed)*150; uint32_t perc = now % cycleTime; uint16_t prog = (perc * 65535) / cycleTime; - uint16_t size = 1 + ((SEGMENT.intensity * SEGLEN) >>9); - uint16_t ledIndex = (prog * ((SEGLEN *2) - size *2)) >> 16; + uint16_t ledIndex = (prog * ((SEGLEN * 2) - 2)) >> 16; + uint16_t size = 1 + SEGMENT.intensity >> 3; fill(SEGCOLOR(1)); - int led_offset = ledIndex - (SEGLEN - size); + int led_offset = ledIndex - (SEGLEN - 1); led_offset = abs(led_offset); - if (dual) { - for (uint16_t j = led_offset; j < led_offset + size; j++) { - uint16_t i2 = SEGMENT.stop -1 -j; - setPixelColor(i2, color_from_palette(i2, true, PALETTE_SOLID_WRAP, (SEGCOLOR(2))? 2:0)); - } + uint16_t i = SEGMENT.start + led_offset; + for (int16_t j=i-size/2; j<=i+size/2; j++) { + if (j>=0) setPixelColor(j, color_from_palette(i, true, PALETTE_SOLID_WRAP, 0)); } - for (uint16_t j = led_offset; j < led_offset + size; j++) { - uint16_t i = SEGMENT.start + j; - setPixelColor(i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 0)); + if (dual) { + uint16_t i2 = SEGMENT.start + SEGLEN - led_offset - 1; + for (int16_t j=i2-size/2; j<=i2+size/2; j++) { + if (j>=0) setPixelColor(j, color_from_palette(i2, true, PALETTE_SOLID_WRAP, 0)); + } } return FRAMETIME; @@ -1004,7 +1004,7 @@ uint16_t WS2812FX::larson_scanner(bool dual) { for (uint16_t i = SEGENV.step; i < index; i++) { uint16_t j = (SEGENV.aux0)?i:SEGLEN-1-i; - setPixelColor(SEGMENT.start + j, color_from_palette(j, true, PALETTE_SOLID_WRAP, 0)); + setPixelColor(j, color_from_palette(j, true, PALETTE_SOLID_WRAP, 0)); } if (dual) { uint32_t c; @@ -1016,7 +1016,7 @@ uint16_t WS2812FX::larson_scanner(bool dual) { for (uint16_t i = SEGENV.step; i < index; i++) { uint16_t j = (SEGENV.aux0)?SEGLEN-1-i:i; - setPixelColor(SEGMENT.start + j, c); + setPixelColor(j, c); } } @@ -1034,7 +1034,7 @@ uint16_t WS2812FX::mode_comet(void) { fade_out(SEGMENT.intensity); - setPixelColor(SEGMENT.start + index, color_from_palette(index, true, PALETTE_SOLID_WRAP, 0)); + setPixelColor(index, color_from_palette(index, true, PALETTE_SOLID_WRAP, 0)); return FRAMETIME; } diff --git a/wled00/FX.h b/wled00/FX.h index 92f3cf78..53096b7e 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -84,7 +84,7 @@ #define IS_REVERSE ((SEGMENT.options & REVERSE ) == REVERSE ) #define IS_SELECTED ((SEGMENT.options & SELECTED) == SELECTED ) -#define MODE_COUNT 92 +#define MODE_COUNT 89 #define FX_MODE_STATIC 0 #define FX_MODE_BLINK 1 @@ -175,9 +175,6 @@ #define FX_MODE_SPOTS_FADE 86 #define FX_MODE_GLITTER 87 #define FX_MODE_CANDLE 88 -#define FX_MODE_BOUNCINGBALLS 89 -#define FX_MODE_SINELON 90 -#define FX_MODE_POPCORN 91 class WS2812FX { @@ -322,9 +319,6 @@ class WS2812FX { _mode[FX_MODE_TRI_STATIC_PATTERN] = &WS2812FX::mode_tri_static_pattern; _mode[FX_MODE_SPOTS] = &WS2812FX::mode_spots; _mode[FX_MODE_SPOTS_FADE] = &WS2812FX::mode_spots_fade; - _mode[FX_MODE_BOUNCINGBALLS] = &WS2812FX::mode_BouncingBalls; - _mode[FX_MODE_SINELON] = &WS2812FX::mode_sinelon; - _mode[FX_MODE_POPCORN] = &WS2812FX::mode_popcorn; _mode[FX_MODE_GLITTER] = &WS2812FX::mode_glitter; _mode[FX_MODE_CANDLE] = &WS2812FX::mode_candle; @@ -508,9 +502,6 @@ class WS2812FX { mode_tri_static_pattern(void), mode_spots(void), mode_spots_fade(void), - mode_BouncingBalls(void), - mode_sinelon(void), - mode_popcorn(void), mode_glitter(void), mode_candle(void); @@ -587,8 +578,7 @@ const char JSON_mode_names[] PROGMEM = R"=====([ "Two Dots","Two Areas","Circus","Halloween","Tri Chase","Tri Wipe","Tri Fade","Lightning","ICU","Multi Comet", "Scanner Dual ","Stream 2","Oscillate","Pride 2015","Juggle","Palette","Fire 2012","Colorwaves","Bpm","Fill Noise", "Noise 1","Noise 2","Noise 3","Noise 4","Colortwinkles","Lake","Meteor","Meteor Smooth","Railway","Ripple", -"Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade","Glitter","Candle", -"Bouncing Balls", "Sinelon","Popcorn" +"Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade","Glitter","Candle" ])====="; diff --git a/wled00/wled00.ino b/wled00/wled00.ino index a577c95d..90bf0ac8 100644 --- a/wled00/wled00.ino +++ b/wled00/wled00.ino @@ -98,7 +98,7 @@ //version code in format yymmddb (b = daily build) -#define VERSION 1912232 +#define VERSION 1912231 char versionString[] = "0.9.0-b2"; diff --git a/wled00/wled01_eeprom.ino b/wled00/wled01_eeprom.ino index 8a43a79d..2f68703e 100644 --- a/wled00/wled01_eeprom.ino +++ b/wled00/wled01_eeprom.ino @@ -561,7 +561,6 @@ bool applyPreset(byte index, bool loadBri = true, bool loadCol = true, bool load col[j] = EEPROM.read(i+j+2); colSec[j] = EEPROM.read(i+j+6); } - strip.setColor(2, EEPROM.read(i+12), EEPROM.read(i+13), EEPROM.read(i+14), EEPROM.read(i+15)); //tertiary color } if (loadFX) { @@ -599,12 +598,6 @@ void savePreset(byte index) } EEPROM.write(i+10, effectCurrent); EEPROM.write(i+11, effectSpeed); - - uint32_t colTer = strip.getSegment(strip.getMainSegmentId()).colors[2]; - EEPROM.write(i+12, (colTer >> 16) & 0xFF); - EEPROM.write(i+13, (colTer >> 8) & 0xFF); - EEPROM.write(i+14, (colTer >> 0) & 0xFF); - EEPROM.write(i+15, (colTer >> 24) & 0xFF); EEPROM.write(i+16, effectIntensity); EEPROM.write(i+17, effectPalette); From 7712faca0a2bad60ba40ee49056349e392c85619 Mon Sep 17 00:00:00 2001 From: fishbone-git Date: Tue, 24 Dec 2019 15:11:04 +0100 Subject: [PATCH 03/30] manual merge --- wled00/wled00.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/wled00.ino b/wled00/wled00.ino index 90bf0ac8..a577c95d 100644 --- a/wled00/wled00.ino +++ b/wled00/wled00.ino @@ -98,7 +98,7 @@ //version code in format yymmddb (b = daily build) -#define VERSION 1912231 +#define VERSION 1912232 char versionString[] = "0.9.0-b2"; From 58f41a1f9b7946489cc5a4d50c3198d5c239e3f7 Mon Sep 17 00:00:00 2001 From: fishbone-git Date: Tue, 24 Dec 2019 15:12:54 +0100 Subject: [PATCH 04/30] manual merge #2 --- wled00/FX.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 4410a43b..1791b710 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -301,24 +301,24 @@ uint16_t WS2812FX::scan(bool dual) uint32_t cycleTime = 750 + (255 - SEGMENT.speed)*150; uint32_t perc = now % cycleTime; uint16_t prog = (perc * 65535) / cycleTime; - uint16_t ledIndex = (prog * ((SEGLEN * 2) - 2)) >> 16; - uint16_t size = 1 + SEGMENT.intensity >> 3; + uint16_t size = 1 + ((SEGMENT.intensity * SEGLEN) >>9); + uint16_t ledIndex = (prog * ((SEGLEN *2) - size *2)) >> 16; fill(SEGCOLOR(1)); - int led_offset = ledIndex - (SEGLEN - 1); + int led_offset = ledIndex - (SEGLEN - size); led_offset = abs(led_offset); - uint16_t i = SEGMENT.start + led_offset; - for (int16_t j=i-size/2; j<=i+size/2; j++) { - if (j>=0) setPixelColor(j, color_from_palette(i, true, PALETTE_SOLID_WRAP, 0)); + if (dual) { + for (uint16_t j = led_offset; j < led_offset + size; j++) { + uint16_t i2 = SEGMENT.stop -1 -j; + setPixelColor(i2, color_from_palette(i2, true, PALETTE_SOLID_WRAP, (SEGCOLOR(2))? 2:0)); + } } - if (dual) { - uint16_t i2 = SEGMENT.start + SEGLEN - led_offset - 1; - for (int16_t j=i2-size/2; j<=i2+size/2; j++) { - if (j>=0) setPixelColor(j, color_from_palette(i2, true, PALETTE_SOLID_WRAP, 0)); - } + for (uint16_t j = led_offset; j < led_offset + size; j++) { + uint16_t i = SEGMENT.start + j; + setPixelColor(i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 0)); } return FRAMETIME; @@ -1004,7 +1004,7 @@ uint16_t WS2812FX::larson_scanner(bool dual) { for (uint16_t i = SEGENV.step; i < index; i++) { uint16_t j = (SEGENV.aux0)?i:SEGLEN-1-i; - setPixelColor(j, color_from_palette(j, true, PALETTE_SOLID_WRAP, 0)); + setPixelColor(SEGMENT.start + j, color_from_palette(j, true, PALETTE_SOLID_WRAP, 0)); } if (dual) { uint32_t c; @@ -1016,7 +1016,7 @@ uint16_t WS2812FX::larson_scanner(bool dual) { for (uint16_t i = SEGENV.step; i < index; i++) { uint16_t j = (SEGENV.aux0)?SEGLEN-1-i:i; - setPixelColor(j, c); + setPixelColor(SEGMENT.start + j, c); } } @@ -1034,7 +1034,7 @@ uint16_t WS2812FX::mode_comet(void) { fade_out(SEGMENT.intensity); - setPixelColor(index, color_from_palette(index, true, PALETTE_SOLID_WRAP, 0)); + setPixelColor(SEGMENT.start + index, color_from_palette(index, true, PALETTE_SOLID_WRAP, 0)); return FRAMETIME; } From 37827cdd6c95f83659c2f69f288580e822277d4e Mon Sep 17 00:00:00 2001 From: fishbone-git Date: Tue, 24 Dec 2019 15:20:38 +0100 Subject: [PATCH 05/30] another manual merge --- wled00/wled01_eeprom.ino | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/wled00/wled01_eeprom.ino b/wled00/wled01_eeprom.ino index 2f68703e..8a43a79d 100644 --- a/wled00/wled01_eeprom.ino +++ b/wled00/wled01_eeprom.ino @@ -561,6 +561,7 @@ bool applyPreset(byte index, bool loadBri = true, bool loadCol = true, bool load col[j] = EEPROM.read(i+j+2); colSec[j] = EEPROM.read(i+j+6); } + strip.setColor(2, EEPROM.read(i+12), EEPROM.read(i+13), EEPROM.read(i+14), EEPROM.read(i+15)); //tertiary color } if (loadFX) { @@ -598,6 +599,12 @@ void savePreset(byte index) } EEPROM.write(i+10, effectCurrent); EEPROM.write(i+11, effectSpeed); + + uint32_t colTer = strip.getSegment(strip.getMainSegmentId()).colors[2]; + EEPROM.write(i+12, (colTer >> 16) & 0xFF); + EEPROM.write(i+13, (colTer >> 8) & 0xFF); + EEPROM.write(i+14, (colTer >> 0) & 0xFF); + EEPROM.write(i+15, (colTer >> 24) & 0xFF); EEPROM.write(i+16, effectIntensity); EEPROM.write(i+17, effectPalette); From f39b9041a032beb5c81c289b51d6c7bc4a5c9189 Mon Sep 17 00:00:00 2001 From: fishbone-git Date: Tue, 24 Dec 2019 15:22:40 +0100 Subject: [PATCH 06/30] remove test --- wled00/FX.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 1791b710..cfd204ef 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -1297,8 +1297,7 @@ uint16_t WS2812FX::mode_icu(void) { setPixelColor(SEGMENT.start + dest, col); setPixelColor(SEGMENT.start + dest + SEGLEN/2, col); - if (SEGMENT.intensity > 127) return FRAMETIME; - return SPEED_FORMULA_L; + return FRAMETIME; } From 012045878d68a6e22c3c9b97b5e1dc2ada741926 Mon Sep 17 00:00:00 2001 From: fishbone-git Date: Tue, 24 Dec 2019 21:05:20 +0100 Subject: [PATCH 07/30] theatre rainbow too fast with a double-step --- wled00/FX.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index cfd204ef..7ea1fe79 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -414,7 +414,6 @@ uint16_t WS2812FX::mode_theater_chase(void) { * Inspired by the Adafruit examples. */ uint16_t WS2812FX::mode_theater_chase_rainbow(void) { - SEGENV.step = (SEGENV.step + 1) & 0xFF; return theater_chase(color_wheel(SEGENV.step), SEGCOLOR(1), false); } From 50082043ef4c3870446df7ce0ead46c6532201c1 Mon Sep 17 00:00:00 2001 From: fishbone-git Date: Fri, 27 Dec 2019 20:58:06 +0100 Subject: [PATCH 08/30] add exploding fireworks --- wled00/FX.cpp | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++ wled00/FX.h | 12 +++-- 2 files changed, 131 insertions(+), 3 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index c862a085..207ce1ff 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2348,3 +2348,125 @@ uint16_t WS2812FX::mode_candle() return FRAMETIME; } + + +/* + * Exploding fireworks effect + * adapted from: http://www.anirama.com/1000leds/1d-fireworks/ + */ +#define NUM_SPARKS 60 // max number (could be NUM_LEDS / 2); +uint16_t WS2812FX::mode_exploding_fireworks(void) +{ + if (SEGENV.aux1==0) { // manage states using params + flare(); + } else { + explode(); + } + + return FRAMETIME; +} + +static float sparkPos[NUM_SPARKS]; +static float sparkVel[NUM_SPARKS]; +static float sparkCol[NUM_SPARKS]; +static float flarePos; +static float flareVel; +static float brightness; + +void WS2812FX::flare() { + float gravity = -0.02 - (SEGMENT.speed/10000.0); // m/s/s + + if (SEGENV.aux0 == 0) { //use aux0 for initialization flag + flarePos = 0; + flareVel = float(random16(150, 190)) / (75+SEGMENT.intensity/4); // trial and error to get reasonable range + brightness = 1; +Serial.printf("%3.1f %3.3f %3d",flareVel,gravity,SEGMENT.intensity); +Serial.println(""); + // initialize launch sparks + for (int i = 0; i < 5; i++) { + sparkPos[i] = 0; + sparkVel[i] = (float(random8(100,255)) / 255.0) * (flareVel/ 3.0); // random around 20% of flare velocity + sparkCol[i] = sparkVel[i] * 1000.0; + sparkCol[i] = constrain(sparkCol[i], 0, 255); + } + SEGENV.aux0=1; + } + + // launch + if (flareVel >= -.3) { + // sparks + for (int i = 0; i < 5; i++) { + sparkPos[i] += sparkVel[i]; + sparkPos[i] = constrain(sparkPos[i], 0, SEGLEN-1); + sparkVel[i] += gravity; + sparkCol[i] += -.8; + sparkCol[i] = constrain(sparkCol[i], 0, 255); + + CRGB color = HeatColor(sparkCol[i]); + setPixelColor(SEGMENT.stop - int(sparkPos[i]),color.red,color.green,color.blue); + } + // flare + fade_out(255); + setPixelColor(SEGMENT.stop - int(flarePos),brightness*255,brightness*255,brightness*255); + + flarePos += flareVel; + flarePos = constrain(flarePos, 0, SEGLEN-1); + flareVel += gravity; + brightness *= .975; + } else { + SEGENV.aux0=0; // allow next state to init + SEGENV.aux1=1; // ready to explode + } +} + +/* + * Explode! + * + * Explosion happens where the flare ended. + * Size is proportional to the height. + */ +void WS2812FX::explode() { + int nSparks = flarePos / 2; // works out to look about right + nSparks = constrain(nSparks,0,NUM_SPARKS); + static float dying_gravity; + float gravity = -0.02 - (SEGMENT.speed/10000.0); + float c1=120; + float c2=50; + + // initialize sparks + if (SEGENV.aux0==0) { + for (int i = 0; i < nSparks; i++) { + sparkPos[i] = flarePos; + sparkVel[i] = (float(random16(0, 20000)) / 10000.0) - 1.0; // from -1 to 1 + sparkCol[i] = abs(sparkVel[i] * 500.0); // set colors before scaling velocity to keep them bright + sparkCol[i] = constrain(sparkCol[i], 0, 255); + sparkVel[i] *= flarePos / SEGLEN; // proportional to height + } + sparkCol[0] = 255; // this will be our known spark + dying_gravity = gravity; + SEGENV.aux0=1; + } + + if (sparkCol[0] > c2/10 ) {//&& sparkPos[0] > 0) { // as long as our known spark is lit, work with all the sparks + fade_out(255); + for (int i = 0; i < nSparks; i++) { + sparkPos[i] += sparkVel[i]; + sparkPos[i] = constrain(sparkPos[i], 0, SEGLEN-1); + sparkVel[i] += dying_gravity; + sparkCol[i] *= .97; + sparkCol[i] = constrain(sparkCol[i], 0, 255); // red cross dissolve + + if(sparkCol[i] > c1) { // fade white to yellow + setPixelColor(SEGMENT.stop - sparkPos[i],255, 255, (255 * (sparkCol[i] - c1)) / (255 - c1)); + } else if (sparkCol[i] < c2) { // fade from red to black + setPixelColor(SEGMENT.stop - sparkPos[i],(255 * sparkCol[i]) / c2, 0, 0); + } else { // fade from yellow to red + setPixelColor(SEGMENT.stop - sparkPos[i],255, (255 * (sparkCol[i] - c2)) / (c1 - c2), 0); + } + } + dying_gravity *= .995; // as sparks burn out they fall slower + } else { + SEGENV.aux0=0; + SEGENV.aux1=0; + } +} \ No newline at end of file diff --git a/wled00/FX.h b/wled00/FX.h index 9ba70357..7fa1a848 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -84,7 +84,7 @@ #define IS_REVERSE ((SEGMENT.options & REVERSE ) == REVERSE ) #define IS_SELECTED ((SEGMENT.options & SELECTED) == SELECTED ) -#define MODE_COUNT 89 +#define MODE_COUNT 90 #define FX_MODE_STATIC 0 #define FX_MODE_BLINK 1 @@ -175,6 +175,7 @@ #define FX_MODE_SPOTS_FADE 86 #define FX_MODE_GLITTER 87 #define FX_MODE_CANDLE 88 +#define FX_MODE_EXPLODING_FIREWORKS 89 class WS2812FX { @@ -321,6 +322,8 @@ class WS2812FX { _mode[FX_MODE_SPOTS_FADE] = &WS2812FX::mode_spots_fade; _mode[FX_MODE_GLITTER] = &WS2812FX::mode_glitter; _mode[FX_MODE_CANDLE] = &WS2812FX::mode_candle; + _mode[FX_MODE_EXPLODING_FIREWORKS] = &WS2812FX::mode_exploding_fireworks; + _brightness = DEFAULT_BRIGHTNESS; currentPalette = CRGBPalette16(CRGB::Black); @@ -359,6 +362,8 @@ class WS2812FX { resetSegments(), setPixelColor(uint16_t n, uint32_t c), setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0), + flare(void), + explode(void), show(void); bool @@ -503,7 +508,8 @@ class WS2812FX { mode_spots(void), mode_spots_fade(void), mode_glitter(void), - mode_candle(void); + mode_candle(void), + mode_exploding_fireworks(void); private: @@ -577,7 +583,7 @@ const char JSON_mode_names[] PROGMEM = R"=====([ "Two Dots","Two Areas","Circus","Halloween","Tri Chase","Tri Wipe","Tri Fade","Lightning","ICU","Multi Comet", "Dual Scanner","Stream 2","Oscillate","Pride 2015","Juggle","Palette","Fire 2012","Colorwaves","Bpm","Fill Noise", "Noise 1","Noise 2","Noise 3","Noise 4","Colortwinkles","Lake","Meteor","Smooth Meteor","Railway","Ripple", -"Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade","Glitter","Candle" +"Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade","Glitter","Candle","Fireworks 1D" ])====="; From ce5839ce27d5e7a6cd5deaeeb8e0dd5ad888fc60 Mon Sep 17 00:00:00 2001 From: fishbone-git Date: Fri, 27 Dec 2019 22:20:34 +0100 Subject: [PATCH 09/30] remove debug message --- wled00/FX.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 207ce1ff..af0974b0 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2380,8 +2380,7 @@ void WS2812FX::flare() { flarePos = 0; flareVel = float(random16(150, 190)) / (75+SEGMENT.intensity/4); // trial and error to get reasonable range brightness = 1; -Serial.printf("%3.1f %3.3f %3d",flareVel,gravity,SEGMENT.intensity); -Serial.println(""); + // initialize launch sparks for (int i = 0; i < 5; i++) { sparkPos[i] = 0; From e3def22b07f7bd0547ded1c00d2026bdd4d7bbaf Mon Sep 17 00:00:00 2001 From: fishbone-git Date: Sat, 28 Dec 2019 15:43:55 +0100 Subject: [PATCH 10/30] add multi fireworks starburst effect --- wled00/FX.cpp | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++ wled00/FX.h | 9 ++-- 2 files changed, 122 insertions(+), 3 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index c862a085..a9fc1f03 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2348,3 +2348,119 @@ uint16_t WS2812FX::mode_candle() return FRAMETIME; } + +typedef struct Particle { + CRGB color; + uint32_t birth =0; + uint32_t last =0; + double vel =0; + uint16_t pos =0; + float fragment[40]; +} star; + +uint16_t WS2812FX::mode_starburst(void) { + uint32_t it = millis(); + + boolean Blend = true; + const uint8_t numStars = 10; + const uint8_t maxFrag = 15; + static star stars[numStars]; + float MaxSpeed = 375.0f; // Max velocity + int NewParticleProbability = 2; // Odds of new particle (out of 255) + float ParticlePreignitonTime = 0.0f; // How long to "wink" + float ParticleIgnition = 0.15f; // How long to "flash" + float ParticleHoldTime = 0.0f; // Main lifecycle time + float ParticleFadeTime = 1.4f; // Fade out time + float ParticleSize = 0.00f; // Size of the particle + + for (int j = 0; j < numStars; j++) + { + if (random8((265-SEGMENT.speed)/2) < NewParticleProbability && stars[j].birth==0) + { + // Pick a random color and location. + uint16_t startPos = random8(SEGLEN-1); + CRGB color = col_to_crgb(color_wheel(random8())); + double multiplier = (double)(random8())/255.0 * 0.5; + + stars[j].color = color; + stars[j].pos = startPos; + stars[j].vel = MaxSpeed * (double)(random16())/65535.0 * multiplier; + stars[j].birth = it; + stars[j].last = it; + int num = 10+SEGMENT.intensity * random8(5,maxFrag)/255; + + for (int i=0; i<=maxFrag; i++) { + if (i < num) stars[j].fragment[i] = startPos; + else stars[j].fragment[i] = -1; + } + } + } + + fill(BLACK); + + for (int j=0; j 0) { + float dt = (it-stars[j].last)/1000.0; + + for (int i=0; i<=maxFrag; i++) { + int var = i/2; + if (stars[j].fragment[i] > 0) { + if (i % 2) { + stars[j].fragment[i] -= stars[j].vel * dt * (float)var/6.0; + } else { + stars[j].fragment[i] += stars[j].vel * dt * (float)var/6.0; + } + } + } + stars[j].last = it; + stars[j].vel -= 2*stars[j].vel*dt; + stars[j].color = stars[j].color.nscale8_video(235); + } + + CRGB c = stars[j].color; + + // If the star is brand new, it flashes white briefly. + // Otherwise it just fades over time. + float fade = 0.0f; + float age = (it-stars[j].birth)/1000.0; + + if (age > ParticlePreignitonTime && age < ParticleIgnition + ParticlePreignitonTime) { + c = CRGB(WHITE); + } else { + // Figure out how much to fade and shrink the star based on + // its age relative to its lifetime + if (age < ParticlePreignitonTime) { + fade = 1.0 - (age / ParticlePreignitonTime); + } else { + age -= ParticlePreignitonTime; + if (age < ParticleHoldTime + ParticleIgnition) { + fade = 0.0f; // Just born + } else if (age > ParticleHoldTime + ParticleIgnition + ParticleFadeTime) { + fade = 1.0f; // Black hole, all faded out + stars[j].birth = 0; + } else { + age -= (ParticleHoldTime + ParticleIgnition); + fade = (age / ParticleFadeTime); // Fading star + } + } + c = c.nscale8_video(255-int(255.0*fade)); + } + ParticleSize = (1 - fade) * 5; + + for (int i=0; i<=maxFrag; i++) { + if (stars[j].fragment[i] > 0) { + int start = stars[j].fragment[i] - int(ParticleSize/2); + if (start<0) start = 0; + int end = stars[j].fragment[i] + int(ParticleSize/2); + if (end>SEGLEN-1) end = SEGLEN-1; + for (int p=start; p<=end; p++) { + setPixelColor(SEGMENT.start+p, c.r, c.g, c.b); + } + } + } + + } + + return FRAMETIME; +} \ No newline at end of file diff --git a/wled00/FX.h b/wled00/FX.h index 9ba70357..f61cb400 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -84,7 +84,7 @@ #define IS_REVERSE ((SEGMENT.options & REVERSE ) == REVERSE ) #define IS_SELECTED ((SEGMENT.options & SELECTED) == SELECTED ) -#define MODE_COUNT 89 +#define MODE_COUNT 90 #define FX_MODE_STATIC 0 #define FX_MODE_BLINK 1 @@ -175,6 +175,7 @@ #define FX_MODE_SPOTS_FADE 86 #define FX_MODE_GLITTER 87 #define FX_MODE_CANDLE 88 +#define FX_MODE_STARBURST 89 class WS2812FX { @@ -321,6 +322,7 @@ class WS2812FX { _mode[FX_MODE_SPOTS_FADE] = &WS2812FX::mode_spots_fade; _mode[FX_MODE_GLITTER] = &WS2812FX::mode_glitter; _mode[FX_MODE_CANDLE] = &WS2812FX::mode_candle; + _mode[FX_MODE_STARBURST] = &WS2812FX::mode_starburst; _brightness = DEFAULT_BRIGHTNESS; currentPalette = CRGBPalette16(CRGB::Black); @@ -503,7 +505,8 @@ class WS2812FX { mode_spots(void), mode_spots_fade(void), mode_glitter(void), - mode_candle(void); + mode_candle(void), + mode_starburst(void); private: @@ -577,7 +580,7 @@ const char JSON_mode_names[] PROGMEM = R"=====([ "Two Dots","Two Areas","Circus","Halloween","Tri Chase","Tri Wipe","Tri Fade","Lightning","ICU","Multi Comet", "Dual Scanner","Stream 2","Oscillate","Pride 2015","Juggle","Palette","Fire 2012","Colorwaves","Bpm","Fill Noise", "Noise 1","Noise 2","Noise 3","Noise 4","Colortwinkles","Lake","Meteor","Smooth Meteor","Railway","Ripple", -"Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade","Glitter","Candle" +"Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade","Glitter","Candle","Fireworks Starburst" ])====="; From 5efd1f3a918d1e90678ada1eb826fba268727ee9 Mon Sep 17 00:00:00 2001 From: fishbone-git Date: Mon, 30 Dec 2019 00:04:56 +0100 Subject: [PATCH 11/30] add comment for source and description --- wled00/FX.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index a9fc1f03..48048339 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2349,6 +2349,12 @@ uint16_t WS2812FX::mode_candle() return FRAMETIME; } + +/* +/ Fireworks in starburst effect +/ based on the video: https://www.reddit.com/r/arduino/comments/c3sd46/i_made_this_fireworks_effect_for_my_led_strips/ +/ Speed sets frequency of new starbursts, intensity is the intensity of the burst +*/ typedef struct Particle { CRGB color; uint32_t birth =0; From f187d7258b73013ae8605b7379eabe80c4c7114b Mon Sep 17 00:00:00 2001 From: fishbone-git Date: Mon, 30 Dec 2019 00:08:49 +0100 Subject: [PATCH 12/30] rework for slightly better visuals --- wled00/FX.cpp | 63 +++++++++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 48048339..501995ff 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2360,7 +2360,7 @@ typedef struct Particle { uint32_t birth =0; uint32_t last =0; double vel =0; - uint16_t pos =0; + uint16_t pos =-1; float fragment[40]; } star; @@ -2368,34 +2368,36 @@ uint16_t WS2812FX::mode_starburst(void) { uint32_t it = millis(); boolean Blend = true; - const uint8_t numStars = 10; - const uint8_t maxFrag = 15; + const uint8_t numStars = 12; + const uint8_t maxFrag = 20; static star stars[numStars]; float MaxSpeed = 375.0f; // Max velocity int NewParticleProbability = 2; // Odds of new particle (out of 255) float ParticlePreignitonTime = 0.0f; // How long to "wink" - float ParticleIgnition = 0.15f; // How long to "flash" + float ParticleIgnition = 0.06f; // How long to "flash" float ParticleHoldTime = 0.0f; // Main lifecycle time - float ParticleFadeTime = 1.4f; // Fade out time + float ParticleFadeTime = 2.6f; // Fade out time float ParticleSize = 0.00f; // Size of the particle for (int j = 0; j < numStars; j++) { - if (random8((265-SEGMENT.speed)/2) < NewParticleProbability && stars[j].birth==0) + // speed to adjust chance of a burst, max is nearly always. + if (random8((263-SEGMENT.speed)/2) < NewParticleProbability && stars[j].birth==0) { // Pick a random color and location. uint16_t startPos = random8(SEGLEN-1); CRGB color = col_to_crgb(color_wheel(random8())); - double multiplier = (double)(random8())/255.0 * 0.5; + double multiplier = (float)(random8())/255.0 * 1.0; stars[j].color = color; stars[j].pos = startPos; - stars[j].vel = MaxSpeed * (double)(random16())/65535.0 * multiplier; + stars[j].vel = MaxSpeed * (float)(random8())/255.0 * multiplier; stars[j].birth = it; stars[j].last = it; - int num = 10+SEGMENT.intensity * random8(5,maxFrag)/255; + // more fragments means larger burst effect + int num = random8(5,10 + (SEGMENT.intensity * maxFrag/255)); - for (int i=0; i<=maxFrag; i++) { + for (int i=0; i<40; i++) { if (i < num) stars[j].fragment[i] = startPos; else stars[j].fragment[i] = -1; } @@ -2406,12 +2408,14 @@ uint16_t WS2812FX::mode_starburst(void) { for (int j=0; j 0) { + if (stars[j].birth != 0) { float dt = (it-stars[j].last)/1000.0; for (int i=0; i<=maxFrag; i++) { int var = i/2; + if (stars[j].fragment[i] > 0) { + // spplit fragments half to each side with some travelling further if (i % 2) { stars[j].fragment[i] -= stars[j].vel * dt * (float)var/6.0; } else { @@ -2420,8 +2424,8 @@ uint16_t WS2812FX::mode_starburst(void) { } } stars[j].last = it; - stars[j].vel -= 2*stars[j].vel*dt; - stars[j].color = stars[j].color.nscale8_video(235); + stars[j].vel -= 3*stars[j].vel*dt; + stars[j].color = stars[j].color.nscale8(235); } CRGB c = stars[j].color; @@ -2430,7 +2434,7 @@ uint16_t WS2812FX::mode_starburst(void) { // Otherwise it just fades over time. float fade = 0.0f; float age = (it-stars[j].birth)/1000.0; - + if (age > ParticlePreignitonTime && age < ParticleIgnition + ParticlePreignitonTime) { c = CRGB(WHITE); } else { @@ -2439,34 +2443,33 @@ uint16_t WS2812FX::mode_starburst(void) { if (age < ParticlePreignitonTime) { fade = 1.0 - (age / ParticlePreignitonTime); } else { - age -= ParticlePreignitonTime; - if (age < ParticleHoldTime + ParticleIgnition) { - fade = 0.0f; // Just born - } else if (age > ParticleHoldTime + ParticleIgnition + ParticleFadeTime) { - fade = 1.0f; // Black hole, all faded out - stars[j].birth = 0; - } else { - age -= (ParticleHoldTime + ParticleIgnition); - fade = (age / ParticleFadeTime); // Fading star - } + age -= ParticlePreignitonTime; + if (age < ParticleHoldTime + ParticleIgnition) { + fade = 0.0f; // Just born + } else if (age > ParticleHoldTime + ParticleIgnition + ParticleFadeTime) { + fade = 1.0f; // Black hole, all faded out + stars[j].birth = 0; + } else { + age -= (ParticleHoldTime + ParticleIgnition); + fade = (age / ParticleFadeTime); // Fading star + } } - c = c.nscale8_video(255-int(255.0*fade)); + + c = c.nscale8(255-int(255.0*fade)/2); } - ParticleSize = (1 - fade) * 5; + ParticleSize = (1 - fade) * 4; for (int i=0; i<=maxFrag; i++) { if (stars[j].fragment[i] > 0) { - int start = stars[j].fragment[i] - int(ParticleSize/2); + int start = int(stars[j].fragment[i]) - int(ParticleSize/2); if (start<0) start = 0; - int end = stars[j].fragment[i] + int(ParticleSize/2); + int end = int(stars[j].fragment[i]) + int(ParticleSize/2); if (end>SEGLEN-1) end = SEGLEN-1; for (int p=start; p<=end; p++) { setPixelColor(SEGMENT.start+p, c.r, c.g, c.b); } } } - } - return FRAMETIME; } \ No newline at end of file From eb251050a526b00cde387fdbe9696fbd8f747a7f Mon Sep 17 00:00:00 2001 From: fishbone-git Date: Mon, 30 Dec 2019 00:22:28 +0100 Subject: [PATCH 13/30] fix exploding firworks controls to match the slider direction to the effect --- wled00/FX.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index af0974b0..7e920352 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2378,7 +2378,7 @@ void WS2812FX::flare() { if (SEGENV.aux0 == 0) { //use aux0 for initialization flag flarePos = 0; - flareVel = float(random16(150, 190)) / (75+SEGMENT.intensity/4); // trial and error to get reasonable range + flareVel = float(random16(150, 190)) / (75+(255-SEGMENT.intensity)/4); // trial and error to get reasonable range brightness = 1; // initialize launch sparks @@ -2428,10 +2428,10 @@ void WS2812FX::explode() { int nSparks = flarePos / 2; // works out to look about right nSparks = constrain(nSparks,0,NUM_SPARKS); static float dying_gravity; - float gravity = -0.02 - (SEGMENT.speed/10000.0); + float gravity = -0.02 - ((255-SEGMENT.speed)/10000.0); float c1=120; float c2=50; - + // initialize sparks if (SEGENV.aux0==0) { for (int i = 0; i < nSparks; i++) { From 508804d0d5548a47ba2f39ec5b81bd7bb6ae2739 Mon Sep 17 00:00:00 2001 From: cschwinne Date: Mon, 30 Dec 2019 01:18:19 +0100 Subject: [PATCH 14/30] Few fixes for tricolor wipe --- wled00/FX.cpp | 49 ++++++++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 7ea1fe79..6eab3195 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -1296,7 +1296,7 @@ uint16_t WS2812FX::mode_icu(void) { setPixelColor(SEGMENT.start + dest, col); setPixelColor(SEGMENT.start + dest + SEGLEN/2, col); - return FRAMETIME; + return SPEED_FORMULA_L; } @@ -1305,24 +1305,35 @@ uint16_t WS2812FX::mode_icu(void) { */ uint16_t WS2812FX::mode_tricolor_wipe(void) { - uint32_t cycleTime = 40 + (3 * (uint32_t)(255 - SEGMENT.speed)); - uint32_t it = now / cycleTime; - if (SEGENV.step == it) return FRAMETIME; - uint8_t incr = it-SEGENV.step; + uint32_t counter = now / (40 + (3 * (uint32_t)(255 - SEGMENT.speed))); + uint32_t prog = counter % (SEGLEN * 3); + uint16_t led_offset = prog; - if(SEGENV.step < SEGLEN) { - uint32_t led_offset = SEGENV.step; - setPixelColor(SEGMENT.start + led_offset, SEGCOLOR(0)); - } else if (SEGENV.step < SEGLEN*2) { - uint32_t led_offset = SEGENV.step - SEGLEN; - setPixelColor(SEGMENT.start + led_offset, SEGCOLOR(1)); - } else + for (uint16_t i = SEGMENT.start; i < SEGMENT.stop; i++) { - uint32_t led_offset = SEGENV.step - SEGLEN*2; - setPixelColor(SEGMENT.start + led_offset, color_from_palette(SEGMENT.start + led_offset, true, PALETTE_SOLID_WRAP, 2)); + setPixelColor(i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 2)); + } + + if(prog < SEGLEN) { //wipe from 0 to 1 + for (uint16_t i = SEGMENT.start; i < SEGMENT.stop; i++) + { + setPixelColor(i, (i - SEGMENT.start > led_offset)? SEGCOLOR(0) : SEGCOLOR(1)); + } + } else if (prog < SEGLEN*2) { //wipe from 1 to 2 + led_offset = prog - SEGLEN; + for (uint16_t i = SEGMENT.start +led_offset +1; i < SEGMENT.stop; i++) + { + setPixelColor(i, SEGCOLOR(1)); + } + } else //wipe from 2 to 0 + { + led_offset = prog - SEGLEN*2; + for (uint16_t i = SEGMENT.start; i <= SEGMENT.start +led_offset; i++) + { + setPixelColor(i, SEGCOLOR(0)); + } } - SEGENV.step = (SEGENV.step + 1) % (SEGLEN * 3); return FRAMETIME; } @@ -1335,16 +1346,16 @@ uint16_t WS2812FX::mode_tricolor_wipe(void) uint16_t WS2812FX::mode_tricolor_fade(void) { uint16_t counter = now * ((SEGMENT.speed >> 3) +1); - SEGENV.step = (counter * 768) >> 16; + uint32_t prog = (counter * 768) >> 16; uint32_t color1 = 0, color2 = 0; byte stage = 0; - if(SEGENV.step < 256) { + if(prog < 256) { color1 = SEGCOLOR(0); color2 = SEGCOLOR(1); stage = 0; - } else if(SEGENV.step < 512) { + } else if(prog < 512) { color1 = SEGCOLOR(1); color2 = SEGCOLOR(2); stage = 1; @@ -1354,7 +1365,7 @@ uint16_t WS2812FX::mode_tricolor_fade(void) stage = 2; } - byte stp = SEGENV.step % 256; + byte stp = prog; // % 256 uint32_t color = 0; for(uint16_t i=SEGMENT.start; i < SEGMENT.stop; i++) { if (stage == 2) { From 8ca6ca2c88e02b934444122c1423053b983604b0 Mon Sep 17 00:00:00 2001 From: cschwinne Date: Mon, 30 Dec 2019 01:40:38 +0100 Subject: [PATCH 15/30] TriWipe synced --- wled00/FX.cpp | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 6eab3195..76aee7bf 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -1305,30 +1305,32 @@ uint16_t WS2812FX::mode_icu(void) { */ uint16_t WS2812FX::mode_tricolor_wipe(void) { - uint32_t counter = now / (40 + (3 * (uint32_t)(255 - SEGMENT.speed))); - uint32_t prog = counter % (SEGLEN * 3); - uint16_t led_offset = prog; + uint32_t cycleTime = 1000 + (255 - SEGMENT.speed)*200; + uint32_t perc = now % cycleTime; + uint16_t prog = (perc * 65535) / cycleTime; + uint16_t ledIndex = (prog * SEGLEN * 3) >> 16; + uint16_t ledOffset = ledIndex; for (uint16_t i = SEGMENT.start; i < SEGMENT.stop; i++) { setPixelColor(i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 2)); } - if(prog < SEGLEN) { //wipe from 0 to 1 + if(ledIndex < SEGLEN) { //wipe from 0 to 1 for (uint16_t i = SEGMENT.start; i < SEGMENT.stop; i++) { - setPixelColor(i, (i - SEGMENT.start > led_offset)? SEGCOLOR(0) : SEGCOLOR(1)); + setPixelColor(i, (i - SEGMENT.start > ledOffset)? SEGCOLOR(0) : SEGCOLOR(1)); } - } else if (prog < SEGLEN*2) { //wipe from 1 to 2 - led_offset = prog - SEGLEN; - for (uint16_t i = SEGMENT.start +led_offset +1; i < SEGMENT.stop; i++) + } else if (ledIndex < SEGLEN*2) { //wipe from 1 to 2 + ledOffset = ledIndex - SEGLEN; + for (uint16_t i = SEGMENT.start +ledOffset +1; i < SEGMENT.stop; i++) { setPixelColor(i, SEGCOLOR(1)); } } else //wipe from 2 to 0 { - led_offset = prog - SEGLEN*2; - for (uint16_t i = SEGMENT.start; i <= SEGMENT.start +led_offset; i++) + ledOffset = ledIndex - SEGLEN*2; + for (uint16_t i = SEGMENT.start; i <= SEGMENT.start +ledOffset; i++) { setPixelColor(i, SEGCOLOR(0)); } From 6e35b5ba8b6a39658836d761a3acfb688df6d1b0 Mon Sep 17 00:00:00 2001 From: cschwinne Date: Mon, 30 Dec 2019 17:34:15 +0100 Subject: [PATCH 16/30] Fix analog write range --- wled00/FX.cpp | 2 +- wled00/NpbWrapper.h | 35 +++++++++++++++++------------------ wled00/wled00.ino | 2 +- wled00/wled19_json.ino | 2 +- 4 files changed, 20 insertions(+), 21 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index aeba1485..552b0f55 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -242,7 +242,7 @@ uint16_t WS2812FX::mode_dynamic(void) { uint32_t cycleTime = 50 + (255 - SEGMENT.speed)*15; uint32_t it = now / cycleTime; - if (it != SEGENV.step) //new color + if (it != SEGENV.step && SEGMENT.speed != 0) //new color { for(uint16_t i=SEGMENT.start; i < SEGMENT.stop; i++) { if (random8() <= SEGMENT.intensity) _locked[i] = random8(); diff --git a/wled00/NpbWrapper.h b/wled00/NpbWrapper.h index a704e426..05d73868 100644 --- a/wled00/NpbWrapper.h +++ b/wled00/NpbWrapper.h @@ -130,26 +130,25 @@ public: _pGrbw = new NeoPixelBrightnessBus(countPixels, LEDPIN); #endif _pGrbw->Begin(); - break; - - #ifdef WLED_USE_ANALOG_LEDS - //init PWM pins - PINs 5,12,13,15 are used with Magic Home LED Controller - pinMode(RPIN, OUTPUT); - pinMode(GPIN, OUTPUT); - pinMode(BPIN, OUTPUT); - switch (_type) { - case NeoPixelType_Grb: break; - #ifdef WLED_USE_5CH_LEDS - case NeoPixelType_Grbw: pinMode(WPIN, OUTPUT); pinMode(W2PIN, OUTPUT); break; - #else - case NeoPixelType_Grbw: pinMode(WPIN, OUTPUT); break; - #endif - } - analogWriteRange(255); //same range as one RGB channel - analogWriteFreq(880); //PWM frequency proven as good for LEDs + + #ifdef WLED_USE_ANALOG_LEDS + pinMode(WPIN, OUTPUT); + #ifdef WLED_USE_5CH_LEDS + pinMode(W2PIN, OUTPUT); #endif - + #endif + + break; } + + #ifdef WLED_USE_ANALOG_LEDS + //init PWM pins - PINs 5,12,13,15 are used with Magic Home LED Controller + pinMode(RPIN, OUTPUT); + pinMode(GPIN, OUTPUT); + pinMode(BPIN, OUTPUT); + analogWriteRange(255); //same range as one RGB channel + analogWriteFreq(880); //PWM frequency proven as good for LEDs + #endif } #ifdef WLED_USE_ANALOG_LEDS diff --git a/wled00/wled00.ino b/wled00/wled00.ino index a577c95d..0d120292 100644 --- a/wled00/wled00.ino +++ b/wled00/wled00.ino @@ -98,7 +98,7 @@ //version code in format yymmddb (b = daily build) -#define VERSION 1912232 +#define VERSION 1912291 char versionString[] = "0.9.0-b2"; diff --git a/wled00/wled19_json.ino b/wled00/wled19_json.ino index 3e135d40..802941a6 100644 --- a/wled00/wled19_json.ino +++ b/wled00/wled19_json.ino @@ -243,7 +243,7 @@ void serializeInfo(JsonObject root) leds_pin.add(LEDPIN); leds["pwr"] = strip.currentMilliamps; - leds["maxpwr"] = strip.ablMilliampsMax; + leds["maxpwr"] = (strip.currentMilliamps)? strip.ablMilliampsMax : 0; leds["maxseg"] = strip.getMaxSegments(); leds["seglock"] = false; //will be used in the future to prevent modifications to segment config From 51fb981d24e75300ad0833688c513a9041ab5c9e Mon Sep 17 00:00:00 2001 From: cschwinne Date: Tue, 31 Dec 2019 11:11:05 +0100 Subject: [PATCH 17/30] Add possiblilty for segments to dynamically allocate memory --- wled00/FX.h | 39 +++++++++++++++++++++++++++++++++++---- wled00/FX_fcn.cpp | 6 +++++- wled00/wled00.ino | 2 +- 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/wled00/FX.h b/wled00/FX.h index 53096b7e..8f2ba95b 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -44,10 +44,17 @@ #define WLED_FPS 42 #define FRAMETIME (1000/WLED_FPS) -/* each segment uses 37 bytes of SRAM memory, so if you're application fails because of +/* each segment uses 52 bytes of SRAM memory, so if you're application fails because of insufficient memory, decreasing MAX_NUM_SEGMENTS may help */ #define MAX_NUM_SEGMENTS 10 +/* How much data bytes all segments combined may allocate */ +#ifdef ESP8266 +#define MAX_SEGMENT_DATA 2048 +#else +#define MAX_SEGMENT_DATA 8192 +#endif + #define NUM_COLORS 3 /* number of colors per segment */ #define SEGMENT _segments[_segment_index] #define SEGCOLOR(x) gamma32(_segments[_segment_index].colors[x]) @@ -221,13 +228,35 @@ class WS2812FX { } segment; // segment runtime parameters - typedef struct Segment_runtime { // 16 bytes + typedef struct Segment_runtime { // 28 bytes unsigned long next_time; uint32_t step; uint32_t call; uint16_t aux0; uint16_t aux1; - void reset(){next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0;}; + byte* data = nullptr; + bool allocateData(uint16_t len){ + if (data && _dataLen == len) return true; //already allocated + deallocateData(); + if (WS2812FX::_usedSegmentData + len > MAX_SEGMENT_DATA) return false; //not enough memory + data = new (std::nothrow) byte[len]; + if (!data) return false; //allocation failed + WS2812FX::_usedSegmentData += len; + _dataLen = len; + memset(data, 0, len); + return true; + } + void deallocateData(){ + if (data) { + delete[] data; + } + data = nullptr; + WS2812FX::_usedSegmentData -= _dataLen; + _dataLen = 0; + } + void reset(){next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0; deallocateData();} + private: + uint16_t _dataLen = 0; } segment_runtime; WS2812FX() { @@ -518,6 +547,7 @@ class WS2812FX { uint16_t _length, _lengthRaw, _usableCount; uint16_t _rand16seed; uint8_t _brightness; + static uint16_t _usedSegmentData; void handle_palette(void); void fill(uint32_t); @@ -564,7 +594,8 @@ class WS2812FX { // start, stop, speed, intensity, palette, mode, options, 3 unused bytes (group, spacing, opacity), color[] { 0, 7, DEFAULT_SPEED, 128, 0, DEFAULT_MODE, NO_OPTIONS, 1, 0, 255, {DEFAULT_COLOR}} }; - segment_runtime _segment_runtimes[MAX_NUM_SEGMENTS]; // SRAM footprint: 16 bytes per element + segment_runtime _segment_runtimes[MAX_NUM_SEGMENTS]; // SRAM footprint: 28 bytes per element + friend class Segment_runtime; }; diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 2b7d6ec1..7fa6eae8 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -473,7 +473,7 @@ void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2) { void WS2812FX::resetSegments() { memset(_segments, 0, sizeof(_segments)); - memset(_segment_runtimes, 0, sizeof(_segment_runtimes)); + //memset(_segment_runtimes, 0, sizeof(_segment_runtimes)); _segment_index = 0; _segments[0].mode = DEFAULT_MODE; _segments[0].colors[0] = DEFAULT_COLOR; @@ -484,7 +484,9 @@ void WS2812FX::resetSegments() { for (uint16_t i = 1; i < MAX_NUM_SEGMENTS; i++) { _segments[i].colors[0] = color_wheel(i*51); + _segment_runtimes[i].reset(); } + _segment_runtimes[0].reset(); } void WS2812FX::setIndividual(uint16_t i, uint32_t col) @@ -862,3 +864,5 @@ uint32_t WS2812FX::gamma32(uint32_t color) b = gammaT[b]; return ((w << 24) | (r << 16) | (g << 8) | (b)); } + +uint16_t WS2812FX::_usedSegmentData = 0; diff --git a/wled00/wled00.ino b/wled00/wled00.ino index 0d120292..6a1a7b07 100644 --- a/wled00/wled00.ino +++ b/wled00/wled00.ino @@ -98,7 +98,7 @@ //version code in format yymmddb (b = daily build) -#define VERSION 1912291 +#define VERSION 1912311 char versionString[] = "0.9.0-b2"; From 1671c782609257ef9c84b630913c3c1010577ab3 Mon Sep 17 00:00:00 2001 From: cschwinne Date: Tue, 31 Dec 2019 12:35:18 +0100 Subject: [PATCH 18/30] First working state --- wled00/FX.cpp | 29 ++++++++++++++--------------- wled00/wled00.ino | 2 +- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 193adfac..a5a20733 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2444,21 +2444,21 @@ uint16_t WS2812FX::mode_candle() / based on the video: https://www.reddit.com/r/arduino/comments/c3sd46/i_made_this_fireworks_effect_for_my_led_strips/ / Speed sets frequency of new starbursts, intensity is the intensity of the burst */ +#define STARBURST_MAX_FRAG 20 + typedef struct Particle { CRGB color; uint32_t birth =0; uint32_t last =0; double vel =0; uint16_t pos =-1; - float fragment[40]; + float fragment[STARBURST_MAX_FRAG]; } star; uint16_t WS2812FX::mode_starburst(void) { uint32_t it = millis(); - boolean Blend = true; const uint8_t numStars = 12; - const uint8_t maxFrag = 20; static star stars[numStars]; float MaxSpeed = 375.0f; // Max velocity int NewParticleProbability = 2; // Odds of new particle (out of 255) @@ -2466,15 +2466,14 @@ uint16_t WS2812FX::mode_starburst(void) { float ParticleIgnition = 0.06f; // How long to "flash" float ParticleHoldTime = 0.0f; // Main lifecycle time float ParticleFadeTime = 2.6f; // Fade out time - float ParticleSize = 0.00f; // Size of the particle for (int j = 0; j < numStars; j++) { // speed to adjust chance of a burst, max is nearly always. - if (random8((263-SEGMENT.speed)/2) < NewParticleProbability && stars[j].birth==0) + if (random8((263-SEGMENT.speed)>>1) < NewParticleProbability && stars[j].birth==0) { // Pick a random color and location. - uint16_t startPos = random8(SEGLEN-1); + uint16_t startPos = random16(SEGLEN-1); CRGB color = col_to_crgb(color_wheel(random8())); double multiplier = (float)(random8())/255.0 * 1.0; @@ -2484,9 +2483,9 @@ uint16_t WS2812FX::mode_starburst(void) { stars[j].birth = it; stars[j].last = it; // more fragments means larger burst effect - int num = random8(5,10 + (SEGMENT.intensity * maxFrag/255)); + int num = random8(5,10 + (SEGMENT.intensity * STARBURST_MAX_FRAG/255)); - for (int i=0; i<40; i++) { + for (int i=0; i < STARBURST_MAX_FRAG; i++) { if (i < num) stars[j].fragment[i] = startPos; else stars[j].fragment[i] = -1; } @@ -2500,7 +2499,7 @@ uint16_t WS2812FX::mode_starburst(void) { if (stars[j].birth != 0) { float dt = (it-stars[j].last)/1000.0; - for (int i=0; i<=maxFrag; i++) { + for (int i=0; i < STARBURST_MAX_FRAG; i++) { int var = i/2; if (stars[j].fragment[i] > 0) { @@ -2525,7 +2524,7 @@ uint16_t WS2812FX::mode_starburst(void) { float age = (it-stars[j].birth)/1000.0; if (age > ParticlePreignitonTime && age < ParticleIgnition + ParticlePreignitonTime) { - c = CRGB(WHITE); + c = CRGB(ULTRAWHITE); } else { // Figure out how much to fade and shrink the star based on // its age relative to its lifetime @@ -2546,19 +2545,19 @@ uint16_t WS2812FX::mode_starburst(void) { c = c.nscale8(255-int(255.0*fade)/2); } - ParticleSize = (1 - fade) * 4; + float ParticleSize = (1 - fade) * 4; - for (int i=0; i<=maxFrag; i++) { + for (int i=0; i < STARBURST_MAX_FRAG; i++) { if (stars[j].fragment[i] > 0) { int start = int(stars[j].fragment[i]) - int(ParticleSize/2); if (start<0) start = 0; int end = int(stars[j].fragment[i]) + int(ParticleSize/2); - if (end>SEGLEN-1) end = SEGLEN-1; - for (int p=start; p<=end; p++) { + if (end > SEGLEN) end = SEGLEN; + for (int p = start; p < end; p++) { setPixelColor(SEGMENT.start+p, c.r, c.g, c.b); } } } } return FRAMETIME; -} \ No newline at end of file +} diff --git a/wled00/wled00.ino b/wled00/wled00.ino index 6a1a7b07..c77eae7a 100644 --- a/wled00/wled00.ino +++ b/wled00/wled00.ino @@ -98,7 +98,7 @@ //version code in format yymmddb (b = daily build) -#define VERSION 1912311 +#define VERSION 1912312 char versionString[] = "0.9.0-b2"; From 8b6366688a37151b9e7ba1b75dd359eb50f2d180 Mon Sep 17 00:00:00 2001 From: fishbone-git Date: Tue, 31 Dec 2019 13:47:17 +0100 Subject: [PATCH 19/30] minor updates for cleanup --- wled00/FX.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 501995ff..fa4bbef0 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2359,25 +2359,23 @@ typedef struct Particle { CRGB color; uint32_t birth =0; uint32_t last =0; - double vel =0; + float vel =0; uint16_t pos =-1; - float fragment[40]; + float fragment[30]; } star; uint16_t WS2812FX::mode_starburst(void) { uint32_t it = millis(); - boolean Blend = true; - const uint8_t numStars = 12; - const uint8_t maxFrag = 20; + const uint8_t numStars = 12; // max starburtsts at one time + const uint8_t maxFrag = 20; // max fragments from each burst static star stars[numStars]; - float MaxSpeed = 375.0f; // Max velocity + int MaxSpeed = 375; // Max velocity int NewParticleProbability = 2; // Odds of new particle (out of 255) float ParticlePreignitonTime = 0.0f; // How long to "wink" - float ParticleIgnition = 0.06f; // How long to "flash" + float ParticleIgnition = 0.06f; // How long to "flash" float ParticleHoldTime = 0.0f; // Main lifecycle time float ParticleFadeTime = 2.6f; // Fade out time - float ParticleSize = 0.00f; // Size of the particle for (int j = 0; j < numStars; j++) { @@ -2387,7 +2385,7 @@ uint16_t WS2812FX::mode_starburst(void) { // Pick a random color and location. uint16_t startPos = random8(SEGLEN-1); CRGB color = col_to_crgb(color_wheel(random8())); - double multiplier = (float)(random8())/255.0 * 1.0; + float multiplier = (float)(random8())/255.0 * 1.0; stars[j].color = color; stars[j].pos = startPos; @@ -2397,7 +2395,7 @@ uint16_t WS2812FX::mode_starburst(void) { // more fragments means larger burst effect int num = random8(5,10 + (SEGMENT.intensity * maxFrag/255)); - for (int i=0; i<40; i++) { + for (int i=0; i<30; i++) { if (i < num) stars[j].fragment[i] = startPos; else stars[j].fragment[i] = -1; } @@ -2457,7 +2455,7 @@ uint16_t WS2812FX::mode_starburst(void) { c = c.nscale8(255-int(255.0*fade)/2); } - ParticleSize = (1 - fade) * 4; + float ParticleSize = (1 - fade) * 4; for (int i=0; i<=maxFrag; i++) { if (stars[j].fragment[i] > 0) { From 446e2c123f9ad0235ad37974bc12feb414467d5f Mon Sep 17 00:00:00 2001 From: cschwinne Date: Tue, 31 Dec 2019 16:37:44 +0100 Subject: [PATCH 20/30] More improvements --- wled00/FX.cpp | 61 ++++++++++++++++++++++----------------------------- 1 file changed, 26 insertions(+), 35 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index a5a20733..ebd22f67 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2458,28 +2458,24 @@ typedef struct Particle { uint16_t WS2812FX::mode_starburst(void) { uint32_t it = millis(); - const uint8_t numStars = 12; + const uint8_t numStars = 4; static star stars[numStars]; - float MaxSpeed = 375.0f; // Max velocity - int NewParticleProbability = 2; // Odds of new particle (out of 255) - float ParticlePreignitonTime = 0.0f; // How long to "wink" - float ParticleIgnition = 0.06f; // How long to "flash" - float ParticleHoldTime = 0.0f; // Main lifecycle time - float ParticleFadeTime = 2.6f; // Fade out time + float maxSpeed = 375.0f; // Max velocity + float ParticleIgnition = 250.0f; // How long to "flash" + float ParticleFadeTime = 1500.0f; // Fade out time for (int j = 0; j < numStars; j++) { // speed to adjust chance of a burst, max is nearly always. - if (random8((263-SEGMENT.speed)>>1) < NewParticleProbability && stars[j].birth==0) + if (random8((144-(SEGMENT.speed >> 1))) == 0 && stars[j].birth == 0) { // Pick a random color and location. uint16_t startPos = random16(SEGLEN-1); - CRGB color = col_to_crgb(color_wheel(random8())); double multiplier = (float)(random8())/255.0 * 1.0; - stars[j].color = color; + stars[j].color = col_to_crgb(color_wheel(random8())); stars[j].pos = startPos; - stars[j].vel = MaxSpeed * (float)(random8())/255.0 * multiplier; + stars[j].vel = maxSpeed * (float)(random8())/255.0 * multiplier; stars[j].birth = it; stars[j].last = it; // more fragments means larger burst effect @@ -2492,7 +2488,7 @@ uint16_t WS2812FX::mode_starburst(void) { } } - fill(BLACK); + fill(SEGCOLOR(1)); for (int j=0; j> 1; if (stars[j].fragment[i] > 0) { // spplit fragments half to each side with some travelling further @@ -2513,7 +2509,6 @@ uint16_t WS2812FX::mode_starburst(void) { } stars[j].last = it; stars[j].vel -= 3*stars[j].vel*dt; - stars[j].color = stars[j].color.nscale8(235); } CRGB c = stars[j].color; @@ -2521,37 +2516,33 @@ uint16_t WS2812FX::mode_starburst(void) { // If the star is brand new, it flashes white briefly. // Otherwise it just fades over time. float fade = 0.0f; - float age = (it-stars[j].birth)/1000.0; + float age = it-stars[j].birth; - if (age > ParticlePreignitonTime && age < ParticleIgnition + ParticlePreignitonTime) { - c = CRGB(ULTRAWHITE); + if (age < ParticleIgnition) { + c = col_to_crgb(color_blend(ULTRAWHITE, crgb_to_col(c), 254.5f*((age / ParticleIgnition)))); } else { // Figure out how much to fade and shrink the star based on // its age relative to its lifetime - if (age < ParticlePreignitonTime) { - fade = 1.0 - (age / ParticlePreignitonTime); + if (age > ParticleIgnition + ParticleFadeTime) { + fade = 1.0f; // Black hole, all faded out + stars[j].birth = 0; + c = col_to_crgb(SEGCOLOR(1)); } else { - age -= ParticlePreignitonTime; - if (age < ParticleHoldTime + ParticleIgnition) { - fade = 0.0f; // Just born - } else if (age > ParticleHoldTime + ParticleIgnition + ParticleFadeTime) { - fade = 1.0f; // Black hole, all faded out - stars[j].birth = 0; - } else { - age -= (ParticleHoldTime + ParticleIgnition); - fade = (age / ParticleFadeTime); // Fading star - } + age -= ParticleIgnition; + fade = (age / ParticleFadeTime); // Fading star + byte f = 254.5f*fade; + c = col_to_crgb(color_blend(crgb_to_col(c), SEGCOLOR(1), f)); } - - c = c.nscale8(255-int(255.0*fade)/2); } - float ParticleSize = (1 - fade) * 4; + + float ParticleSize = (1.0 - fade) * 2; for (int i=0; i < STARBURST_MAX_FRAG; i++) { if (stars[j].fragment[i] > 0) { - int start = int(stars[j].fragment[i]) - int(ParticleSize/2); - if (start<0) start = 0; - int end = int(stars[j].fragment[i]) + int(ParticleSize/2); + int start = int(stars[j].fragment[i]) - int(ParticleSize); + if (start < 0) start = 0; + int end = int(stars[j].fragment[i]) + int(ParticleSize); + if (start == end) end++; if (end > SEGLEN) end = SEGLEN; for (int p = start; p < end; p++) { setPixelColor(SEGMENT.start+p, c.r, c.g, c.b); From 21b498fecec35a7fc5389a84f78106c3881b1629 Mon Sep 17 00:00:00 2001 From: cschwinne Date: Tue, 31 Dec 2019 19:01:37 +0100 Subject: [PATCH 21/30] Memory optimizations --- wled00/FX.cpp | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index ebd22f67..3d839995 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2444,9 +2444,9 @@ uint16_t WS2812FX::mode_candle() / based on the video: https://www.reddit.com/r/arduino/comments/c3sd46/i_made_this_fireworks_effect_for_my_led_strips/ / Speed sets frequency of new starbursts, intensity is the intensity of the burst */ -#define STARBURST_MAX_FRAG 20 +#define STARBURST_MAX_FRAG 12 -typedef struct Particle { +typedef struct particle { CRGB color; uint32_t birth =0; uint32_t last =0; @@ -2458,11 +2458,11 @@ typedef struct Particle { uint16_t WS2812FX::mode_starburst(void) { uint32_t it = millis(); - const uint8_t numStars = 4; + const uint8_t numStars = 15; static star stars[numStars]; float maxSpeed = 375.0f; // Max velocity - float ParticleIgnition = 250.0f; // How long to "flash" - float ParticleFadeTime = 1500.0f; // Fade out time + float particleIgnition = 250.0f; // How long to "flash" + float particleFadeTime = 1500.0f; // Fade out time for (int j = 0; j < numStars; j++) { @@ -2471,7 +2471,7 @@ uint16_t WS2812FX::mode_starburst(void) { { // Pick a random color and location. uint16_t startPos = random16(SEGLEN-1); - double multiplier = (float)(random8())/255.0 * 1.0; + float multiplier = (float)(random8())/255.0 * 1.0; stars[j].color = col_to_crgb(color_wheel(random8())); stars[j].pos = startPos; @@ -2479,7 +2479,7 @@ uint16_t WS2812FX::mode_starburst(void) { stars[j].birth = it; stars[j].last = it; // more fragments means larger burst effect - int num = random8(5,10 + (SEGMENT.intensity * STARBURST_MAX_FRAG/255)); + int num = random8(3,6 + (SEGMENT.intensity >> 5)); for (int i=0; i < STARBURST_MAX_FRAG; i++) { if (i < num) stars[j].fragment[i] = startPos; @@ -2499,12 +2499,8 @@ uint16_t WS2812FX::mode_starburst(void) { int var = i >> 1; if (stars[j].fragment[i] > 0) { - // spplit fragments half to each side with some travelling further - if (i % 2) { - stars[j].fragment[i] -= stars[j].vel * dt * (float)var/6.0; - } else { - stars[j].fragment[i] += stars[j].vel * dt * (float)var/6.0; - } + //all fragments travel right, will be mirrored on other side + stars[j].fragment[i] += stars[j].vel * dt * (float)var/3.0; } } stars[j].last = it; @@ -2518,30 +2514,34 @@ uint16_t WS2812FX::mode_starburst(void) { float fade = 0.0f; float age = it-stars[j].birth; - if (age < ParticleIgnition) { - c = col_to_crgb(color_blend(ULTRAWHITE, crgb_to_col(c), 254.5f*((age / ParticleIgnition)))); + if (age < particleIgnition) { + c = col_to_crgb(color_blend(WHITE, crgb_to_col(c), 254.5f*((age / particleIgnition)))); } else { // Figure out how much to fade and shrink the star based on // its age relative to its lifetime - if (age > ParticleIgnition + ParticleFadeTime) { + if (age > particleIgnition + particleFadeTime) { fade = 1.0f; // Black hole, all faded out stars[j].birth = 0; c = col_to_crgb(SEGCOLOR(1)); } else { - age -= ParticleIgnition; - fade = (age / ParticleFadeTime); // Fading star + age -= particleIgnition; + fade = (age / particleFadeTime); // Fading star byte f = 254.5f*fade; c = col_to_crgb(color_blend(crgb_to_col(c), SEGCOLOR(1), f)); } } - float ParticleSize = (1.0 - fade) * 2; + float particleSize = (1.0 - fade) * 2; - for (int i=0; i < STARBURST_MAX_FRAG; i++) { + for (uint8_t index=0; index < STARBURST_MAX_FRAG*2; index++) { + bool mirrored = index & 0x1; + uint8_t i = index >> 1; if (stars[j].fragment[i] > 0) { - int start = int(stars[j].fragment[i]) - int(ParticleSize); + float loc = stars[j].fragment[i]; + if (mirrored) loc -= (loc-stars[j].pos)*2; + int start = loc - particleSize; + int end = loc + particleSize; if (start < 0) start = 0; - int end = int(stars[j].fragment[i]) + int(ParticleSize); if (start == end) end++; if (end > SEGLEN) end = SEGLEN; for (int p = start; p < end; p++) { From 1c6b1c530f1c97c882398ed073d3501e77c6d766 Mon Sep 17 00:00:00 2001 From: srg74 <28492985+srg74@users.noreply.github.com> Date: Tue, 31 Dec 2019 17:52:59 -0500 Subject: [PATCH 22/30] Update wled06_usermod.ino Corrected pin numbering --- usermods/ssd1306_i2c_oled_u8g2/wled06_usermod.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usermods/ssd1306_i2c_oled_u8g2/wled06_usermod.ino b/usermods/ssd1306_i2c_oled_u8g2/wled06_usermod.ino index c7317064..593625b9 100644 --- a/usermods/ssd1306_i2c_oled_u8g2/wled06_usermod.ino +++ b/usermods/ssd1306_i2c_oled_u8g2/wled06_usermod.ino @@ -1,7 +1,7 @@ #include // from https://github.com/olikraus/u8g2/ //The SCL and SDA pins are defined here. -//Lolin32 boards use SCL=4 SDA=5 +//Lolin32 boards use SCL=5 SDA=4 #define U8X8_PIN_SCL 5 #define U8X8_PIN_SDA 4 From 58861fa524e38c46a93ef964662719f1dd0a6d42 Mon Sep 17 00:00:00 2001 From: srg74 <28492985+srg74@users.noreply.github.com> Date: Tue, 31 Dec 2019 17:57:15 -0500 Subject: [PATCH 23/30] Update platformio.ini Added commented library reference for OLED display --- platformio.ini | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index c4cac76d..45f2148f 100644 --- a/platformio.ini +++ b/platformio.ini @@ -41,6 +41,8 @@ lib_deps_external = IRremoteESP8266@2.5.5 #Time@1.5 #Timezone@1.2.1 + #For use SSD1306 0.91" OLED display uncomment following + #U8g2@~2.27.2 [common:esp8266] # ------------------------------------------------------------------------------ @@ -214,4 +216,4 @@ build_flags = -D WLED_ENABLE_5CH_LEDS lib_deps = ${common.lib_deps_external} - \ No newline at end of file + From 4dfc1631af08bc26b6c4ff92b31a15cb57a20019 Mon Sep 17 00:00:00 2001 From: cschwinne Date: Wed, 1 Jan 2020 01:04:54 +0100 Subject: [PATCH 24/30] Few Cronixie fixes --- wled00/wled03_set.ino | 7 ++++--- wled00/wled10_ntp.ino | 17 ++++++++++------- wled00/wled13_cronixie.ino | 1 - 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/wled00/wled03_set.ino b/wled00/wled03_set.ino index 3f08d280..9c753fec 100644 --- a/wled00/wled03_set.ino +++ b/wled00/wled03_set.ino @@ -622,6 +622,10 @@ bool handleSet(AsyncWebServerRequest *request, const String& req) //cronixie #ifndef WLED_DISABLE_CRONIXIE + //mode, 1 countdown + pos = req.indexOf("NM="); + if (pos > 0) countdownMode = (req.charAt(pos+3) != '0'); + pos = req.indexOf("NX="); //sets digits to code if (pos > 0) { strlcpy(cronixieDisplay, req.substring(pos + 3, pos + 9).c_str(), 6); @@ -636,9 +640,6 @@ bool handleSet(AsyncWebServerRequest *request, const String& req) overlayRefreshedTime = 0; } #endif - //mode, 1 countdown - pos = req.indexOf("NM="); - if (pos > 0) countdownMode = (req.charAt(pos+3) != '0'); pos = req.indexOf("U0="); //user var 0 if (pos > 0) { diff --git a/wled00/wled10_ntp.ino b/wled00/wled10_ntp.ino index 57a810f1..bf8df064 100644 --- a/wled00/wled10_ntp.ino +++ b/wled00/wled10_ntp.ino @@ -163,13 +163,16 @@ void setCountdown() //returns true if countdown just over bool checkCountdown() { - long diff = countdownTime - now(); - local = abs(diff); - if (diff <0 && !countdownOverTriggered) - { - if (macroCountdown != 0) applyMacro(macroCountdown); - countdownOverTriggered = true; - return true; + unsigned long n = now(); + local = countdownTime - n; + if (n > countdownTime) { + local = n - countdownTime; + if (!countdownOverTriggered) + { + if (macroCountdown != 0) applyMacro(macroCountdown); + countdownOverTriggered = true; + return true; + } } return false; } diff --git a/wled00/wled13_cronixie.ino b/wled00/wled13_cronixie.ino index dac32475..4c5a7496 100644 --- a/wled00/wled13_cronixie.ino +++ b/wled00/wled13_cronixie.ino @@ -147,7 +147,6 @@ void _overlayCronixie() { if (countdownMode) checkCountdown(); #ifndef WLED_DISABLE_CRONIXIE - byte h = hour(local); byte h0 = h; byte m = minute(local); From 22c1f4bb4e3aa6d963547489fcf5bc236226e28d Mon Sep 17 00:00:00 2001 From: srg74 <28492985+srg74@users.noreply.github.com> Date: Tue, 31 Dec 2019 19:53:25 -0500 Subject: [PATCH 25/30] Update readme.txt Minor editing --- usermods/QuinLED_Dig_Uno_Temp_MQTT/readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usermods/QuinLED_Dig_Uno_Temp_MQTT/readme.txt b/usermods/QuinLED_Dig_Uno_Temp_MQTT/readme.txt index 62401f8e..61287336 100644 --- a/usermods/QuinLED_Dig_Uno_Temp_MQTT/readme.txt +++ b/usermods/QuinLED_Dig_Uno_Temp_MQTT/readme.txt @@ -4,5 +4,5 @@ This code uses Aircookie's WLED software. It has a premade file for user modific To install: -Add the enties in the WLED00 file to the top of the same file from Aircoookies WLED. +Add the entries in the WLED00 file to the top of the same file from Aircoookies WLED. Replace the WLED06_usermod.ino file in Aircoookies WLED folder. From 8013f8d5b35cff4947ef36f48c91b173037fdb88 Mon Sep 17 00:00:00 2001 From: cschwinne Date: Thu, 2 Jan 2020 02:12:10 +0100 Subject: [PATCH 26/30] Update year --- wled00/FX.cpp | 11 +++++++++-- wled00/FX.h | 4 +--- wled00/html_settings.h | 4 ++-- wled00/wled00.ino | 2 +- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index dac4aade..291703b6 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2446,6 +2446,7 @@ uint16_t WS2812FX::mode_candle() */ #define STARBURST_MAX_FRAG 12 +//each needs 64 byte typedef struct particle { CRGB color; uint32_t birth =0; @@ -2456,10 +2457,16 @@ typedef struct particle { } star; uint16_t WS2812FX::mode_starburst(void) { + uint8_t numStars = 1 + (SEGLEN >> 3); + if (numStars > 15) numStars = 15; + uint16_t dataSize = sizeof(star) * numStars; + + if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed + uint32_t it = millis(); - const uint8_t numStars = 15; - static star stars[numStars]; + star* stars = reinterpret_cast(SEGENV.data); + float maxSpeed = 375.0f; // Max velocity float particleIgnition = 250.0f; // How long to "flash" float particleFadeTime = 1500.0f; // Fade out time diff --git a/wled00/FX.h b/wled00/FX.h index bb33741d..5bf896cb 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -248,9 +248,7 @@ class WS2812FX { return true; } void deallocateData(){ - if (data) { - delete[] data; - } + delete[] data; data = nullptr; WS2812FX::_usedSegmentData -= _dataLen; _dataLen = 0; diff --git a/wled00/html_settings.h b/wled00/html_settings.h index 678aa281..a15e62eb 100644 --- a/wled00/html_settings.h +++ b/wled00/html_settings.h @@ -368,10 +368,10 @@ HTTP traffic is unencrypted. An attacker in the same network can intercept form
Enable ArduinoOTA:

About

-WLED version 0.9.0-b1

+WLED version 0.9.0-b2

Contributors, dependencies and special thanks
A huge thank you to everyone who helped me create WLED!

-(c) 2016-2019 Christian Schwinne
+(c) 2016-2020 Christian Schwinne
Licensed under the MIT license

Server message: Response error!
diff --git a/wled00/wled00.ino b/wled00/wled00.ino index c77eae7a..7860c20b 100644 --- a/wled00/wled00.ino +++ b/wled00/wled00.ino @@ -98,7 +98,7 @@ //version code in format yymmddb (b = daily build) -#define VERSION 1912312 +#define VERSION 2001011 char versionString[] = "0.9.0-b2"; From 3d359229cfb0de997b8315e34dfb09ccbdda5cb6 Mon Sep 17 00:00:00 2001 From: cschwinne Date: Thu, 2 Jan 2020 20:41:15 +0100 Subject: [PATCH 27/30] Reworked effects to use data instead of locked --- wled00/FX.cpp | 164 ++++++++++++++++++++++++++++------------------ wled00/FX.h | 3 - wled00/FX_fcn.cpp | 30 +-------- wled00/wled00.ino | 2 +- 4 files changed, 105 insertions(+), 94 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 291703b6..ca4b3d43 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -236,22 +236,24 @@ uint16_t WS2812FX::mode_random_color(void) { // * to new random colors. */ uint16_t WS2812FX::mode_dynamic(void) { + if (!SEGENV.allocateData(SEGLEN)) return mode_static(); //allocation failed + if(SEGENV.call == 0) { - for(uint16_t i=SEGMENT.start; i < SEGMENT.stop; i++) _locked[i] = random8(); + for (uint16_t i = 0; i < SEGLEN; i++) SEGENV.data[i] = random8(); } uint32_t cycleTime = 50 + (255 - SEGMENT.speed)*15; uint32_t it = now / cycleTime; if (it != SEGENV.step && SEGMENT.speed != 0) //new color { - for(uint16_t i=SEGMENT.start; i < SEGMENT.stop; i++) { - if (random8() <= SEGMENT.intensity) _locked[i] = random8(); + for (uint16_t i = 0; i < SEGLEN; i++) { + if (random8() <= SEGMENT.intensity) SEGENV.data[i] = random8(); } SEGENV.step = it; } - for(uint16_t i=SEGMENT.start; i < SEGMENT.stop; i++) { - setPixelColor(i, color_wheel(_locked[i])); + for (uint16_t i = 0; i < SEGLEN; i++) { + setPixelColor(SEGMENT.start + i, color_wheel(SEGENV.data[i])); } return FRAMETIME; } @@ -1467,17 +1469,24 @@ typedef struct Oscillator { */ uint16_t WS2812FX::mode_oscillate(void) { - static oscillator oscillators[NUM_COLORS] = { - {SEGLEN/4, SEGLEN/8, 1, 1}, - {SEGLEN/4*3, SEGLEN/8, 1, 2}, - {SEGLEN/4*2, SEGLEN/8, -1, 1} - - }; + uint8_t numOscillators = 3; + uint16_t dataSize = sizeof(oscillator) * numOscillators; + + if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed + + Oscillator* oscillators = reinterpret_cast(SEGENV.data); + + if (SEGENV.call == 0) + { + oscillators[0] = {SEGLEN/4, SEGLEN/8, 1, 1}; + oscillators[1] = {SEGLEN/4*3, SEGLEN/8, 1, 2}; + oscillators[2] = {SEGLEN/4*2, SEGLEN/8, -1, 1}; + } uint32_t cycleTime = 20 + (2 * (uint32_t)(255 - SEGMENT.speed)); uint32_t it = now / cycleTime; - for(int8_t i=0; i < sizeof(oscillators)/sizeof(oscillators[0]); i++) { + for(uint8_t i=0; i < numOscillators; i++) { // if the counter has increased, move the oscillator by the random step if (it != SEGENV.step) oscillators[i].pos += oscillators[i].dir * oscillators[i].speed; oscillators[i].size = SEGLEN/(3+SEGMENT.intensity/8); @@ -1494,9 +1503,9 @@ uint16_t WS2812FX::mode_oscillate(void) } } - for(int16_t i=0; i < SEGLEN; i++) { + for(uint16_t i=0; i < SEGLEN; i++) { uint32_t color = BLACK; - for(int8_t j=0; j < sizeof(oscillators)/sizeof(oscillators[0]); j++) { + for(uint8_t j=0; j < numOscillators; j++) { if(i >= oscillators[j].pos - oscillators[j].size && i <= oscillators[j].pos + oscillators[j].size) { color = (color == BLACK) ? SEGMENT.colors[j] : color_blend(color, SEGMENT.colors[j], 128); } @@ -1666,30 +1675,34 @@ uint16_t WS2812FX::mode_fire_2012() { uint32_t it = now >> 5; //div 32 + if (!SEGENV.allocateData(SEGLEN)) return mode_static(); //allocation failed + + byte* heat = SEGENV.data; + if (it != SEGENV.step) { // Step 1. Cool down every cell a little - for( int i = SEGMENT.start; i < SEGMENT.stop; i++) { - _locked[i] = qsub8(_locked[i], random8(0, (((20 + SEGMENT.speed /3) * 10) / SEGLEN) + 2)); + for (uint16_t i = 0; i < SEGLEN; i++) { + SEGENV.data[i] = qsub8(heat[i], random8(0, (((20 + SEGMENT.speed /3) * 10) / SEGLEN) + 2)); } // Step 2. Heat from each cell drifts 'up' and diffuses a little - for( int k= SEGMENT.stop -1; k >= SEGMENT.start + 2; k--) { - _locked[k] = (_locked[k - 1] + _locked[k - 2] + _locked[k - 2] ) / 3; + for (uint16_t k= SEGLEN -1; k > 1; k--) { + heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3; } // Step 3. Randomly ignite new 'sparks' of heat near the bottom - if( random8() <= SEGMENT.intensity ) { - int y = SEGMENT.start + random8(7); - if (y < SEGMENT.stop) _locked[y] = qadd8(_locked[y], random8(160,255) ); + if (random8() <= SEGMENT.intensity) { + uint8_t y = random8(7); + if (y < SEGLEN) heat[y] = qadd8(heat[y], random8(160,255)); } SEGENV.step = it; } // Step 4. Map from heat cells to LED colors - for( int j = SEGMENT.start; j < SEGMENT.stop; j++) { - CRGB color = ColorFromPalette( currentPalette, min(_locked[j],240), 255, LINEARBLEND); - setPixelColor(j, color.red, color.green, color.blue); + for (uint16_t j = 0; j < SEGLEN; j++) { + CRGB color = ColorFromPalette(currentPalette, min(heat[j],240), 255, LINEARBLEND); + setPixelColor(SEGMENT.start + j, color.red, color.green, color.blue); } return FRAMETIME; } @@ -1870,18 +1883,25 @@ uint16_t WS2812FX::mode_noise16_4() //based on https://gist.github.com/kriegsman/5408ecd397744ba0393e uint16_t WS2812FX::mode_colortwinkle() { + uint16_t dataSize = (SEGLEN+7) >> 3; //1 bit per LED + if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed + CRGB fastled_col, prev; fract8 fadeUpAmount = 8 + (SEGMENT.speed/4), fadeDownAmount = 5 + (SEGMENT.speed/7); - for( uint16_t i = SEGMENT.start; i < SEGMENT.stop; i++) { + for (uint16_t i = SEGMENT.start; i < SEGMENT.stop; i++) { fastled_col = col_to_crgb(getPixelColor(i)); prev = fastled_col; - if(_locked[i]) { + uint16_t index = (i - SEGMENT.start) >> 3; + uint8_t bitNum = (i - SEGMENT.start) & 0x07; + bool fadeUp = bitRead(SEGENV.data[index], bitNum); + + if (fadeUp) { CRGB incrementalColor = fastled_col; incrementalColor.nscale8_video( fadeUpAmount); fastled_col += incrementalColor; - if( fastled_col.red == 255 || fastled_col.green == 255 || fastled_col.blue == 255) { - _locked[i] = false; + if (fastled_col.red == 255 || fastled_col.green == 255 || fastled_col.blue == 255) { + bitWrite(SEGENV.data[index], bitNum, false); } setPixelColor(i, fastled_col.red, fastled_col.green, fastled_col.blue); @@ -1898,13 +1918,15 @@ uint16_t WS2812FX::mode_colortwinkle() for (uint16_t j = 0; j <= SEGLEN / 50; j++) { - if ( random8() <= SEGMENT.intensity ) { + if (random8() <= SEGMENT.intensity) { for (uint8_t times = 0; times < 5; times++) //attempt to spawn a new pixel 5 times { int i = SEGMENT.start + random16(SEGLEN); if(getPixelColor(i) == 0) { fastled_col = ColorFromPalette(currentPalette, random8(), 64, NOBLEND); - _locked[i] = true; + uint16_t index = (i - SEGMENT.start) >> 3; + uint8_t bitNum = (i - SEGMENT.start) & 0x07; + bitWrite(SEGENV.data[index], bitNum, true); setPixelColor(i, fastled_col.red, fastled_col.green, fastled_col.blue); break; //only spawn 1 new pixel per frame per 50 LEDs } @@ -1938,29 +1960,33 @@ uint16_t WS2812FX::mode_lake() { // send a meteor from begining to to the end of the strip with a trail that randomly decays. // adapted from https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/#LEDStripEffectMeteorRain uint16_t WS2812FX::mode_meteor() { + if (!SEGENV.allocateData(SEGLEN)) return mode_static(); //allocation failed + + byte* trail = SEGENV.data; + byte meteorSize= 1+ SEGLEN / 10; uint16_t counter = now * ((SEGMENT.speed >> 2) +8); uint16_t in = counter * SEGLEN >> 16; // fade all leds to colors[1] in LEDs one step - for (uint16_t i = SEGMENT.start; i < SEGMENT.stop; i++) { + for (uint16_t i = 0; i < SEGLEN; i++) { if (random8() <= 255 - SEGMENT.intensity) { byte meteorTrailDecay = 128 + random8(127); - _locked[i] = scale8(_locked[i], meteorTrailDecay); - setPixelColor(i, color_from_palette(_locked[i], false, true, 255)); + trail[i] = scale8(trail[i], meteorTrailDecay); + setPixelColor(SEGMENT.start + i, color_from_palette(trail[i], false, true, 255)); } } // draw meteor for(int j = 0; j < meteorSize; j++) { uint16_t index = in + j; - if(in + j >= SEGMENT.stop) { - index = SEGMENT.start + (in + j - SEGMENT.stop); + if(index >= SEGLEN) { + index = (in + j - SEGLEN); } - _locked[index] = 240; - setPixelColor(index, color_from_palette(_locked[index], false, true, 255)); + trail[index] = 240; + setPixelColor(SEGMENT.start + index, color_from_palette(trail[index], false, true, 255)); } return FRAMETIME; @@ -1971,29 +1997,33 @@ uint16_t WS2812FX::mode_meteor() { // send a meteor from begining to to the end of the strip with a trail that randomly decays. // adapted from https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/#LEDStripEffectMeteorRain uint16_t WS2812FX::mode_meteor_smooth() { + if (!SEGENV.allocateData(SEGLEN)) return mode_static(); //allocation failed + + byte* trail = SEGENV.data; + byte meteorSize= 1+ SEGLEN / 10; - uint16_t in = map((SEGENV.step >> 6 & 0xFF), 0, 255, SEGMENT.start, SEGMENT.stop -1); + uint16_t in = map((SEGENV.step >> 6 & 0xFF), 0, 255, 0, SEGLEN -1); // fade all leds to colors[1] in LEDs one step - for (uint16_t i = SEGMENT.start; i < SEGMENT.stop; i++) { - if (_locked[i] != 0 && random8() <= 255 - SEGMENT.intensity) + for (uint16_t i = 0; i < SEGLEN; i++) { + if (trail[i] != 0 && random8() <= 255 - SEGMENT.intensity) { int change = 3 - random8(12); //change each time between -8 and +3 - _locked[i] += change; - if (_locked[i] > 245) _locked[i] = 0; - if (_locked[i] > 240) _locked[i] = 240; - setPixelColor(i, color_from_palette(_locked[i], false, true, 255)); + trail[i] += change; + if (trail[i] > 245) trail[i] = 0; + if (trail[i] > 240) trail[i] = 240; + setPixelColor(SEGMENT.start + i, color_from_palette(trail[i], false, true, 255)); } } // draw meteor for(int j = 0; j < meteorSize; j++) { uint16_t index = in + j; - if(in + j >= SEGMENT.stop) { - index = SEGMENT.start + (in + j - SEGMENT.stop); + if(in + j >= SEGLEN) { + index = (in + j - SEGLEN); } - setPixelColor(index, color_blend(getPixelColor(index), color_from_palette(240, false, true, 255), 48)); - _locked[index] = 240; + setPixelColor(SEGMENT.start + index, color_blend(getPixelColor(SEGMENT.start + index), color_from_palette(240, false, true, 255), 48)); + trail[index] = 240; } SEGENV.step += SEGMENT.speed +1; @@ -2035,23 +2065,35 @@ uint16_t WS2812FX::mode_railway() //Water ripple //propagation velocity from speed //drop rate from intensity + +//4 bytes +typedef struct Ripple { + uint8_t state; + uint8_t color; + uint16_t pos; +} ripple; + uint16_t WS2812FX::mode_ripple() { - uint16_t maxripples = SEGLEN / 4; - if (maxripples == 0) return mode_static(); + uint16_t maxRipples = 1 + (SEGLEN >> 2); + if (maxRipples > 100) maxRipples = 100; + uint16_t dataSize = sizeof(ripple) * maxRipples; + + if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed + + Ripple* ripples = reinterpret_cast(SEGENV.data); fill(SEGCOLOR(1)); //draw wave - for (uint16_t rippleI = 0; rippleI < maxripples; rippleI++) + for (uint16_t i = 0; i < maxRipples; i++) { - uint16_t storeI = SEGMENT.start + 4*rippleI; - uint16_t ripplestate = _locked[storeI]; + uint16_t ripplestate = ripples[i].state; if (ripplestate) { uint8_t rippledecay = (SEGMENT.speed >> 4) +1; //faster decay if faster propagation - uint16_t rippleorigin = (_locked[storeI+1] << 8) + _locked[storeI+2]; - uint32_t col = color_from_palette(_locked[storeI+3], false, false, 255); + uint16_t rippleorigin = ripples[i].pos; + uint32_t col = color_from_palette(ripples[i].color, false, false, 255); uint16_t propagation = ((ripplestate/rippledecay -1) * SEGMENT.speed); int16_t propI = propagation >> 8; uint8_t propF = propagation & 0xFF; @@ -2061,7 +2103,7 @@ uint16_t WS2812FX::mode_ripple() for (int16_t v = left; v < left +4; v++) { uint8_t mag = scale8(cubicwave8((propF>>2)+(v-left)*64), amp); - if (v >= SEGMENT.start) + if (v < SEGMENT.stop && v >= SEGMENT.start) { setPixelColor(v, color_blend(getPixelColor(v), col, mag)); } @@ -2072,16 +2114,14 @@ uint16_t WS2812FX::mode_ripple() } } ripplestate += rippledecay; - _locked[storeI] = (ripplestate > 254) ? 0 : ripplestate; + ripples[i].state = (ripplestate > 254) ? 0 : ripplestate; } else //randomly create new wave { if (random16(IBN + 10000) <= SEGMENT.intensity) { - _locked[storeI] = 1; - uint16_t origin = SEGMENT.start + random16(SEGLEN); - _locked[storeI+1] = origin >> 8; - _locked[storeI+2] = origin & 0xFF; - _locked[storeI+3] = random8(); //color + ripples[i].state = 1; + ripples[i].pos = SEGMENT.start + random16(SEGLEN); + ripples[i].color = random8(); //color } } } diff --git a/wled00/FX.h b/wled00/FX.h index 5bf896cb..8c51f142 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -358,7 +358,6 @@ class WS2812FX { currentMilliamps = 0; timebase = 0; _locked = nullptr; - _modeUsesLock = false; bus = new NeoPixelWrapper(); resetSegments(); } @@ -552,10 +551,8 @@ class WS2812FX { void handle_palette(void); void fill(uint32_t); - bool modeUsesLock(uint8_t); bool - _modeUsesLock, _rgbwMode, _cronixieMode, _cronixieBacklightEnabled, diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 7fa6eae8..25f40a88 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -96,14 +96,6 @@ void WS2812FX::service() { _triggered = false; } -bool WS2812FX::modeUsesLock(uint8_t m) -{ - if (m == FX_MODE_FIRE_2012 || m == FX_MODE_COLORTWINKLE || - m == FX_MODE_METEOR || m == FX_MODE_METEOR_SMOOTH || - m == FX_MODE_RIPPLE || m == FX_MODE_DYNAMIC ) return true; - return false; -} - void WS2812FX::setPixelColor(uint16_t n, uint32_t c) { uint8_t w = (c >> 24); uint8_t r = (c >> 16); @@ -115,7 +107,7 @@ void WS2812FX::setPixelColor(uint16_t n, uint32_t c) { void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w) { i = i * (_disableNLeds+1); - if (_locked[i] && !_modeUsesLock) return; + if (_locked[i]) return; if (IS_REVERSE) i = SEGMENT.stop -1 -i + SEGMENT.start; //reverse just individual segment byte tmpg = g; switch (colorOrder) //0 = Grb, default @@ -273,7 +265,6 @@ void WS2812FX::trigger() { void WS2812FX::setMode(uint8_t segid, uint8_t m) { if (segid >= MAX_NUM_SEGMENTS) return; - bool anyUsedLock = _modeUsesLock, anyUseLock = false; if (m >= MODE_COUNT) m = MODE_COUNT - 1; if (_segments[segid].mode != m) @@ -281,13 +272,6 @@ void WS2812FX::setMode(uint8_t segid, uint8_t m) { _segment_runtimes[segid].reset(); _segments[segid].mode = m; } - - for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) - { - if (modeUsesLock(_segments[i].mode)) anyUseLock = true; - } - if (anyUsedLock && !anyUseLock) unlockAll(); - _modeUsesLock = anyUseLock; } uint8_t WS2812FX::getModeCount() @@ -454,12 +438,7 @@ void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2) { if (n >= MAX_NUM_SEGMENTS) return; Segment& seg = _segments[n]; if (seg.start == i1 && seg.stop == i2) return; - if (seg.isActive() && modeUsesLock(seg.mode)) - { - _modeUsesLock = false; - unlockRange(seg.start, seg.stop); - _modeUsesLock = true; - } + _segment_index = n; fill(0); //turn old segment range off if (i2 <= i1) //disable segment { @@ -491,7 +470,6 @@ void WS2812FX::resetSegments() { void WS2812FX::setIndividual(uint16_t i, uint32_t col) { - if (modeUsesLock(SEGMENT.mode)) return; if (i >= 0 && i < _length) { _locked[i] = false; @@ -513,13 +491,11 @@ void WS2812FX::setRange(uint16_t i, uint16_t i2, uint32_t col) void WS2812FX::lock(uint16_t i) { - if (_modeUsesLock) return; if (i < _length) _locked[i] = true; } void WS2812FX::lockRange(uint16_t i, uint16_t i2) { - if (_modeUsesLock) return; for (uint16_t x = i; x < i2; x++) { if (x < _length) _locked[i] = true; @@ -528,13 +504,11 @@ void WS2812FX::lockRange(uint16_t i, uint16_t i2) void WS2812FX::unlock(uint16_t i) { - if (_modeUsesLock) return; if (i < _length) _locked[i] = false; } void WS2812FX::unlockRange(uint16_t i, uint16_t i2) { - if (_modeUsesLock) return; for (uint16_t x = i; x < i2; x++) { if (x < _length) _locked[x] = false; diff --git a/wled00/wled00.ino b/wled00/wled00.ino index 7860c20b..3144b56c 100644 --- a/wled00/wled00.ino +++ b/wled00/wled00.ino @@ -98,7 +98,7 @@ //version code in format yymmddb (b = daily build) -#define VERSION 2001011 +#define VERSION 2001021 char versionString[] = "0.9.0-b2"; From 9bf534288ca860a86e856e27c84370e68a75419c Mon Sep 17 00:00:00 2001 From: cschwinne Date: Thu, 2 Jan 2020 22:10:59 +0100 Subject: [PATCH 28/30] Removed pixel locking --- wled00/FX.h | 14 +++++----- wled00/FX_fcn.cpp | 55 ++++++-------------------------------- wled00/wled00.ino | 3 ++- wled00/wled03_set.ino | 24 ----------------- wled00/wled05_init.ino | 1 + wled00/wled07_notify.ino | 2 -- wled00/wled11_ol.ino | 32 ++++++++++------------ wled00/wled13_cronixie.ino | 1 - 8 files changed, 31 insertions(+), 101 deletions(-) diff --git a/wled00/FX.h b/wled00/FX.h index 8c51f142..c6d458d8 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -187,6 +187,9 @@ class WS2812FX { typedef uint16_t (WS2812FX::*mode_ptr)(void); + + // pre show callback + typedef void (*show_callback) (void); // segment parameters public: @@ -357,7 +360,6 @@ class WS2812FX { ablMilliampsMax = 850; currentMilliamps = 0; timebase = 0; - _locked = nullptr; bus = new NeoPixelWrapper(); resetSegments(); } @@ -374,13 +376,8 @@ class WS2812FX { driverModeCronixie(bool b), setCronixieDigits(byte* d), setCronixieBacklight(bool b), - setIndividual(uint16_t i, uint32_t col), setRange(uint16_t i, uint16_t i2, uint32_t col), - lock(uint16_t i), - lockRange(uint16_t i, uint16_t i2), - unlock(uint16_t i), - unlockRange(uint16_t i, uint16_t i2), - unlockAll(void), + setShowCallback(show_callback cb), setTransitionMode(bool t), trigger(void), setSegment(uint8_t n, uint16_t start, uint16_t stop), @@ -559,11 +556,12 @@ class WS2812FX { _skipFirstMode, _triggered; - byte* _locked; byte _cronixieDigits[6]; mode_ptr _mode[MODE_COUNT]; // SRAM footprint: 4 bytes per element + show_callback _callback = nullptr; + // mode helper functions uint16_t blink(uint32_t, uint32_t, bool strobe, bool), diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 25f40a88..3081c2be 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -32,7 +32,7 @@ void WS2812FX::init(bool supportWhite, uint16_t countPixels, bool skipFirst, uint8_t disableNLeds) { - if (supportWhite == _rgbwMode && countPixels == _length && _locked != NULL && disableNLeds == _disableNLeds) return; + if (supportWhite == _rgbwMode && countPixels == _length && disableNLeds == _disableNLeds) return; RESET_RUNTIME; _rgbwMode = supportWhite; _skipFirstMode = skipFirst; @@ -59,13 +59,9 @@ void WS2812FX::init(bool supportWhite, uint16_t countPixels, bool skipFirst, uin bus->Begin((NeoPixelType)ty, _lengthRaw); - delete[] _locked; - _locked = new byte[_length]; - _segments[0].start = 0; _segments[0].stop = _usableCount; - - unlockAll(); + setBrightness(_brightness); } @@ -107,7 +103,6 @@ void WS2812FX::setPixelColor(uint16_t n, uint32_t c) { void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w) { i = i * (_disableNLeds+1); - if (_locked[i]) return; if (IS_REVERSE) i = SEGMENT.stop -1 -i + SEGMENT.start; //reverse just individual segment byte tmpg = g; switch (colorOrder) //0 = Grb, default @@ -200,6 +195,8 @@ void WS2812FX::setCronixieDigits(byte d[]) //you can set it to 0 if the ESP is powered by USB and the LEDs by external void WS2812FX::show(void) { + if (_callback) _callback(); + //power limit calculation //each LED can draw up 195075 "power units" (approx. 53mA) //one PU is the power it takes to have 1 channel 1 step brighter per brightness step @@ -468,56 +465,20 @@ void WS2812FX::resetSegments() { _segment_runtimes[0].reset(); } -void WS2812FX::setIndividual(uint16_t i, uint32_t col) -{ - if (i >= 0 && i < _length) - { - _locked[i] = false; - setPixelColor(i, col); - _locked[i] = true; - } -} - void WS2812FX::setRange(uint16_t i, uint16_t i2, uint32_t col) { if (i2 >= i) { - for (uint16_t x = i; x <= i2; x++) setIndividual(x,col); + for (uint16_t x = i; x <= i2; x++) setPixelColor(x, col); } else { - for (uint16_t x = i2; x <= i; x++) setIndividual(x,col); + for (uint16_t x = i2; x <= i; x++) setPixelColor(x, col); } } -void WS2812FX::lock(uint16_t i) +void WS2812FX::setShowCallback(show_callback cb) { - if (i < _length) _locked[i] = true; -} - -void WS2812FX::lockRange(uint16_t i, uint16_t i2) -{ - for (uint16_t x = i; x < i2; x++) - { - if (x < _length) _locked[i] = true; - } -} - -void WS2812FX::unlock(uint16_t i) -{ - if (i < _length) _locked[i] = false; -} - -void WS2812FX::unlockRange(uint16_t i, uint16_t i2) -{ - for (uint16_t x = i; x < i2; x++) - { - if (x < _length) _locked[x] = false; - } -} - -void WS2812FX::unlockAll() -{ - for (int i=0; i < _length; i++) _locked[i] = false; + _callback = cb; } void WS2812FX::setTransitionMode(bool t) diff --git a/wled00/wled00.ino b/wled00/wled00.ino index 3144b56c..5fc1092f 100644 --- a/wled00/wled00.ino +++ b/wled00/wled00.ino @@ -98,7 +98,7 @@ //version code in format yymmddb (b = daily build) -#define VERSION 2001021 +#define VERSION 2001022 char versionString[] = "0.9.0-b2"; @@ -424,6 +424,7 @@ AsyncMqttClient* mqtt = NULL; void colorFromUint32(uint32_t,bool=false); void serveMessage(AsyncWebServerRequest*,uint16_t,String,String,byte); void handleE131Packet(e131_packet_t*, IPAddress); +void handleOverlayDraw(); #define E131_MAX_UNIVERSE_COUNT 9 diff --git a/wled00/wled03_set.ino b/wled00/wled03_set.ino index 9c753fec..b20103ce 100644 --- a/wled00/wled03_set.ino +++ b/wled00/wled03_set.ino @@ -200,7 +200,6 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) if (request->hasArg("OL")){ overlayDefault = request->arg("OL").toInt(); - if (overlayCurrent != overlayDefault) strip.unlockAll(); overlayCurrent = overlayDefault; } @@ -459,29 +458,6 @@ bool handleSet(AsyncWebServerRequest *request, const String& req) pos = req.indexOf("OL="); if (pos > 0) { overlayCurrent = getNumVal(&req, pos); - strip.unlockAll(); - } - - //(un)lock pixel (ranges) - pos = req.indexOf("&L="); - if (pos > 0) { - uint16_t index = getNumVal(&req, pos); - pos = req.indexOf("L2="); - bool unlock = req.indexOf("UL") > 0; - if (pos > 0) { - uint16_t index2 = getNumVal(&req, pos); - if (unlock) { - strip.unlockRange(index, index2); - } else { - strip.lockRange(index, index2); - } - } else { - if (unlock) { - strip.unlock(index); - } else { - strip.lock(index); - } - } } //apply macro diff --git a/wled00/wled05_init.ino b/wled00/wled05_init.ino index 684893f1..a347eb4d 100644 --- a/wled00/wled05_init.ino +++ b/wled00/wled05_init.ino @@ -96,6 +96,7 @@ void wledInit() void beginStrip() { // Initialize NeoPixel Strip and button + strip.setShowCallback(handleOverlayDraw); #ifdef BTNPIN pinMode(BTNPIN, INPUT_PULLUP); diff --git a/wled00/wled07_notify.ino b/wled00/wled07_notify.ino index 22370072..8bb739e0 100644 --- a/wled00/wled07_notify.ino +++ b/wled00/wled07_notify.ino @@ -79,7 +79,6 @@ void arlsLock(uint32_t timeoutMs) { strip.setPixelColor(i,0,0,0,0); } - strip.unlockAll(); realtimeActive = true; } realtimeTimeout = millis() + timeoutMs; @@ -127,7 +126,6 @@ void handleNotifications() //unlock strip when realtime UDP times out if (realtimeActive && millis() > realtimeTimeout) { - //strip.unlockAll(); strip.setBrightness(bri); realtimeActive = false; //strip.setMode(effectCurrent); diff --git a/wled00/wled11_ol.ino b/wled00/wled11_ol.ino index fc3a47d8..cfe8a1f9 100644 --- a/wled00/wled11_ol.ino +++ b/wled00/wled11_ol.ino @@ -1,6 +1,7 @@ /* * Used to draw clock overlays over the strip */ + void initCronixie() { if (overlayCurrent == 3 && !cronixieInit) @@ -24,14 +25,8 @@ void handleOverlays() initCronixie(); updateLocalTime(); checkTimers(); - switch (overlayCurrent) - { - case 0: break;//no overlay - case 1: _overlayAnalogClock(); break;//2 analog clock - case 2: break;//nixie 1-digit, removed - case 3: _overlayCronixie();//Diamex cronixie clock kit - } - if (!countdownMode || overlayCurrent < 3) checkCountdown(); //countdown macro activation must work + checkCountdown(); + if (overlayCurrent == 3) _overlayCronixie();//Diamex cronixie clock kit overlayRefreshedTime = millis(); } } @@ -40,7 +35,6 @@ void handleOverlays() void _overlayAnalogClock() { int overlaySize = overlayMax - overlayMin +1; - strip.unlockAll(); if (countdownMode) { _overlayAnalogCountdown(); return; @@ -73,23 +67,19 @@ void _overlayAnalogClock() { pix = analogClock12pixel + round((overlaySize / 12.0) *i); if (pix > overlayMax) pix -= overlaySize; - strip.setIndividual(pix, 0x00FFAA); + strip.setPixelColor(pix, 0x00FFAA); } } - if (!analogClockSecondsTrail) strip.setIndividual(secondPixel, 0xFF0000); - strip.setIndividual(minutePixel, 0x00FF00); - strip.setIndividual(hourPixel, 0x0000FF); + if (!analogClockSecondsTrail) strip.setPixelColor(secondPixel, 0xFF0000); + strip.setPixelColor(minutePixel, 0x00FF00); + strip.setPixelColor(hourPixel, 0x0000FF); overlayRefreshMs = 998; } void _overlayAnalogCountdown() { - strip.unlockAll(); - if (now() >= countdownTime) - { - checkCountdown(); - } else + if (now() < countdownTime) { long diff = countdownTime - now(); double pval = 60; @@ -127,3 +117,9 @@ void _overlayAnalogCountdown() } overlayRefreshMs = 998; } + + +void handleOverlayDraw() { + if (overlayCurrent != 1) return; //only analog clock + _overlayAnalogClock(); +} diff --git a/wled00/wled13_cronixie.ino b/wled00/wled13_cronixie.ino index 4c5a7496..de89aede 100644 --- a/wled00/wled13_cronixie.ino +++ b/wled00/wled13_cronixie.ino @@ -145,7 +145,6 @@ void setCronixie() void _overlayCronixie() { - if (countdownMode) checkCountdown(); #ifndef WLED_DISABLE_CRONIXIE byte h = hour(local); byte h0 = h; From cdef7a53a43c5c223539f85de010dc01a4e26407 Mon Sep 17 00:00:00 2001 From: cschwinne Date: Fri, 3 Jan 2020 17:47:06 +0100 Subject: [PATCH 29/30] Fireworks 1D working --- wled00/FX.cpp | 224 +++++++++++++++++++++++++------------------------- wled00/FX.h | 2 - 2 files changed, 114 insertions(+), 112 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index c93f8305..6051a155 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2605,118 +2605,122 @@ uint16_t WS2812FX::mode_starburst(void) { * Exploding fireworks effect * adapted from: http://www.anirama.com/1000leds/1d-fireworks/ */ -#define NUM_SPARKS 60 // max number (could be NUM_LEDS / 2); + +//each needs 12 byte +typedef struct Spark { + float pos; + float vel; + float col; +} spark; + uint16_t WS2812FX::mode_exploding_fireworks(void) { - if (SEGENV.aux1==0) { // manage states using params - flare(); - } else { - explode(); - } + //allocate segment data + uint16_t numSparks = 2 + (SEGLEN >> 1); + if (numSparks > 80) numSparks = 80; + uint16_t dataSize = sizeof(spark) * numSparks; + if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed + fill(BLACK); + + Spark* sparks = reinterpret_cast(SEGENV.data); + Spark* flare = sparks; //first spark is flare data + + float gravity = -0.02 - (SEGMENT.speed/10000.0); // m/s/s + + if (SEGENV.aux1 == 0) { //FLARE + if (SEGENV.aux0 == 0) { //init flare + flare->pos = 0; + flare->vel = float(random16(150, 190)) / (75+(255-SEGMENT.intensity)/4); // trial and error to get reasonable range + //flare->vel = 2; + flare->col = 1; //brightness + + // initialize launch sparks + for (int i = 1; i < min(6, numSparks); i++) { + sparks[i].pos = 0; + sparks[i].vel = (float(random8(100,255)) / 255.0) * (flare->vel/ 3.0); // random around 20% of flare velocity + sparks[i].col = sparks[i].vel * 1000.0; + sparks[i].col = constrain(sparks[i].col, 0, 255); + } + SEGENV.aux0 = 1; + } + + // launch + if (flare->vel > -.3) { + // sparks + for (int i = 1; i < min(6, numSparks); i++) { + sparks[i].pos += sparks[i].vel; + sparks[i].pos = constrain(sparks[i].pos, 0, SEGLEN-1); + sparks[i].vel += gravity; + sparks[i].col -= 0.8; + sparks[i].col = constrain(sparks[i].col, 0, 255); + + CRGB color = HeatColor(sparks[i].col); + setPixelColor(SEGMENT.start + int(sparks[i].pos),color.red,color.green,color.blue); + } + // flare + //fade_out(255); + setPixelColor(SEGMENT.start + int(flare->pos),flare->col*255,flare->col*255,flare->col*255); + + flare->pos += flare->vel; + flare->pos = constrain(flare->pos, 0, SEGLEN-1); + flare->vel += gravity; + flare->col *= .975; + } else { + SEGENV.aux0 = 0; // allow next state to init + SEGENV.aux1 = 1; // ready to explode + } + } else { + /* + * Explode! + * + * Explosion happens where the flare ended. + * Size is proportional to the height. + */ + int nSparks = flare->pos / 2; // works out to look about right + nSparks = constrain(nSparks, 0, numSparks); + static float dying_gravity; + //gravity = -0.02 - ((255-SEGMENT.speed)/10000.0); + + // initialize sparks + if (SEGENV.aux0==0) { + for (int i = 1; i < nSparks; i++) { + sparks[i].pos = flare->pos; + sparks[i].vel = (float(random16(0, 20000)) / 10000.0) - 1.0; // from -1 to 1 + sparks[i].col = abs(sparks[i].vel * 500.0); // set colors before scaling velocity to keep them bright + sparks[i].col = constrain(sparks[i].col, 0, 255); + sparks[i].vel *= flare->pos / SEGLEN; // proportional to height + } + sparks[1].col = 255; // this will be our known spark + dying_gravity = gravity; + SEGENV.aux0 = 1; + } + + float c1 = 120; + float c2 = 50; + + if (sparks[1].col > 5) {//&& sparks[1].pos > 0) { // as long as our known spark is lit, work with all the sparks + //fade_out(255); + for (int i = 1; i < nSparks; i++) { + sparks[i].pos += sparks[i].vel; + sparks[i].pos = constrain(sparks[i].pos, 0, SEGLEN-1); + sparks[i].vel += dying_gravity; + sparks[i].col *= .97; + sparks[i].col = constrain(sparks[i].col, 0, 255); // red cross dissolve + + if(sparks[i].pos > c1) { // fade white to yellow + setPixelColor(SEGMENT.start + sparks[i].pos,255, 255, (255 * (sparks[i].col - c1)) / (255 - c1)); + } else if (sparks[i].col < c2) { // fade from red to black + setPixelColor(SEGMENT.start + sparks[i].pos,(255 * sparks[i].col) / c2, 0, 0); + } else { // fade from yellow to red + setPixelColor(SEGMENT.start + sparks[i].pos,255, (255 * (sparks[i].col - c2)) / (c1 - c2), 0); + } + } + dying_gravity *= .995; // as sparks burn out they fall slower + } else { + SEGENV.aux0 = 0; //init again + SEGENV.aux1 = 0; //back to flare + } + } return FRAMETIME; } - -static float sparkPos[NUM_SPARKS]; -static float sparkVel[NUM_SPARKS]; -static float sparkCol[NUM_SPARKS]; -static float flarePos; -static float flareVel; -static float brightness; - -void WS2812FX::flare() { - float gravity = -0.02 - (SEGMENT.speed/10000.0); // m/s/s - - if (SEGENV.aux0 == 0) { //use aux0 for initialization flag - flarePos = 0; - flareVel = float(random16(150, 190)) / (75+(255-SEGMENT.intensity)/4); // trial and error to get reasonable range - brightness = 1; - - // initialize launch sparks - for (int i = 0; i < 5; i++) { - sparkPos[i] = 0; - sparkVel[i] = (float(random8(100,255)) / 255.0) * (flareVel/ 3.0); // random around 20% of flare velocity - sparkCol[i] = sparkVel[i] * 1000.0; - sparkCol[i] = constrain(sparkCol[i], 0, 255); - } - SEGENV.aux0=1; - } - - // launch - if (flareVel >= -.3) { - // sparks - for (int i = 0; i < 5; i++) { - sparkPos[i] += sparkVel[i]; - sparkPos[i] = constrain(sparkPos[i], 0, SEGLEN-1); - sparkVel[i] += gravity; - sparkCol[i] += -.8; - sparkCol[i] = constrain(sparkCol[i], 0, 255); - - CRGB color = HeatColor(sparkCol[i]); - setPixelColor(SEGMENT.stop - int(sparkPos[i]),color.red,color.green,color.blue); - } - // flare - fade_out(255); - setPixelColor(SEGMENT.stop - int(flarePos),brightness*255,brightness*255,brightness*255); - - flarePos += flareVel; - flarePos = constrain(flarePos, 0, SEGLEN-1); - flareVel += gravity; - brightness *= .975; - } else { - SEGENV.aux0=0; // allow next state to init - SEGENV.aux1=1; // ready to explode - } -} - -/* - * Explode! - * - * Explosion happens where the flare ended. - * Size is proportional to the height. - */ -void WS2812FX::explode() { - int nSparks = flarePos / 2; // works out to look about right - nSparks = constrain(nSparks,0,NUM_SPARKS); - static float dying_gravity; - float gravity = -0.02 - ((255-SEGMENT.speed)/10000.0); - float c1=120; - float c2=50; - - // initialize sparks - if (SEGENV.aux0==0) { - for (int i = 0; i < nSparks; i++) { - sparkPos[i] = flarePos; - sparkVel[i] = (float(random16(0, 20000)) / 10000.0) - 1.0; // from -1 to 1 - sparkCol[i] = abs(sparkVel[i] * 500.0); // set colors before scaling velocity to keep them bright - sparkCol[i] = constrain(sparkCol[i], 0, 255); - sparkVel[i] *= flarePos / SEGLEN; // proportional to height - } - sparkCol[0] = 255; // this will be our known spark - dying_gravity = gravity; - SEGENV.aux0=1; - } - - if (sparkCol[0] > c2/10 ) {//&& sparkPos[0] > 0) { // as long as our known spark is lit, work with all the sparks - fade_out(255); - for (int i = 0; i < nSparks; i++) { - sparkPos[i] += sparkVel[i]; - sparkPos[i] = constrain(sparkPos[i], 0, SEGLEN-1); - sparkVel[i] += dying_gravity; - sparkCol[i] *= .97; - sparkCol[i] = constrain(sparkCol[i], 0, 255); // red cross dissolve - - if(sparkCol[i] > c1) { // fade white to yellow - setPixelColor(SEGMENT.stop - sparkPos[i],255, 255, (255 * (sparkCol[i] - c1)) / (255 - c1)); - } else if (sparkCol[i] < c2) { // fade from red to black - setPixelColor(SEGMENT.stop - sparkPos[i],(255 * sparkCol[i]) / c2, 0, 0); - } else { // fade from yellow to red - setPixelColor(SEGMENT.stop - sparkPos[i],255, (255 * (sparkCol[i] - c2)) / (c1 - c2), 0); - } - } - dying_gravity *= .995; // as sparks burn out they fall slower - } else { - SEGENV.aux0=0; - SEGENV.aux1=0; - } -} diff --git a/wled00/FX.h b/wled00/FX.h index 824e0bef..0b2d21af 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -386,8 +386,6 @@ class WS2812FX { resetSegments(), setPixelColor(uint16_t n, uint32_t c), setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0), - flare(void), - explode(void), show(void); bool From 5c7d993dbea2c532f08eebf50d88d23edea29bb8 Mon Sep 17 00:00:00 2001 From: cschwinne Date: Fri, 3 Jan 2020 22:56:56 +0100 Subject: [PATCH 30/30] Numerous improvements to 1D FW --- wled00/FX.cpp | 117 ++++++++++++++++++++++------------------------ wled00/wled00.ino | 2 +- 2 files changed, 58 insertions(+), 61 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 6051a155..e1af8338 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2610,7 +2610,8 @@ uint16_t WS2812FX::mode_starburst(void) { typedef struct Spark { float pos; float vel; - float col; + uint16_t col; + uint8_t colIndex; } spark; uint16_t WS2812FX::mode_exploding_fireworks(void) @@ -2623,104 +2624,100 @@ uint16_t WS2812FX::mode_exploding_fireworks(void) fill(BLACK); + bool actuallyReverse = SEGMENT.getOption(1); + //have fireworks start in either direction based on intensity + SEGMENT.setOption(1, SEGENV.step); + Spark* sparks = reinterpret_cast(SEGENV.data); Spark* flare = sparks; //first spark is flare data - float gravity = -0.02 - (SEGMENT.speed/10000.0); // m/s/s + float gravity = -0.0004 - (SEGMENT.speed/800000.0); // m/s/s + gravity *= SEGLEN; - if (SEGENV.aux1 == 0) { //FLARE + if (SEGENV.aux0 < 2) { //FLARE if (SEGENV.aux0 == 0) { //init flare flare->pos = 0; - flare->vel = float(random16(150, 190)) / (75+(255-SEGMENT.intensity)/4); // trial and error to get reasonable range - //flare->vel = 2; - flare->col = 1; //brightness - - // initialize launch sparks - for (int i = 1; i < min(6, numSparks); i++) { - sparks[i].pos = 0; - sparks[i].vel = (float(random8(100,255)) / 255.0) * (flare->vel/ 3.0); // random around 20% of flare velocity - sparks[i].col = sparks[i].vel * 1000.0; - sparks[i].col = constrain(sparks[i].col, 0, 255); - } + uint16_t peakHeight = 75 + random8(180); //0-255 + peakHeight = (peakHeight * (SEGLEN -1)) >> 8; + flare->vel = sqrt(-2.0 * gravity * peakHeight); + flare->col = 255; //brightness + SEGENV.aux0 = 1; } // launch - if (flare->vel > -.3) { - // sparks - for (int i = 1; i < min(6, numSparks); i++) { - sparks[i].pos += sparks[i].vel; - sparks[i].pos = constrain(sparks[i].pos, 0, SEGLEN-1); - sparks[i].vel += gravity; - sparks[i].col -= 0.8; - sparks[i].col = constrain(sparks[i].col, 0, 255); - - CRGB color = HeatColor(sparks[i].col); - setPixelColor(SEGMENT.start + int(sparks[i].pos),color.red,color.green,color.blue); - } + if (flare->vel > 12 * gravity) { // flare - //fade_out(255); - setPixelColor(SEGMENT.start + int(flare->pos),flare->col*255,flare->col*255,flare->col*255); + setPixelColor(SEGMENT.start + int(flare->pos),flare->col,flare->col,flare->col); flare->pos += flare->vel; flare->pos = constrain(flare->pos, 0, SEGLEN-1); flare->vel += gravity; - flare->col *= .975; + flare->col -= 2; } else { - SEGENV.aux0 = 0; // allow next state to init - SEGENV.aux1 = 1; // ready to explode + SEGENV.aux0 = 2; // ready to explode } - } else { + } else if (SEGENV.aux0 < 4) { /* * Explode! * * Explosion happens where the flare ended. * Size is proportional to the height. */ - int nSparks = flare->pos / 2; // works out to look about right + int nSparks = flare->pos; nSparks = constrain(nSparks, 0, numSparks); static float dying_gravity; - //gravity = -0.02 - ((255-SEGMENT.speed)/10000.0); // initialize sparks - if (SEGENV.aux0==0) { + if (SEGENV.aux0 == 2) { for (int i = 1; i < nSparks; i++) { sparks[i].pos = flare->pos; - sparks[i].vel = (float(random16(0, 20000)) / 10000.0) - 1.0; // from -1 to 1 - sparks[i].col = abs(sparks[i].vel * 500.0); // set colors before scaling velocity to keep them bright - sparks[i].col = constrain(sparks[i].col, 0, 255); - sparks[i].vel *= flare->pos / SEGLEN; // proportional to height + sparks[i].vel = (float(random16(0, 20000)) / 10000.0) - 0.9; // from -0.9 to 1.1 + sparks[i].col = 345;//abs(sparks[i].vel * 750.0); // set colors before scaling velocity to keep them bright + //sparks[i].col = constrain(sparks[i].col, 0, 345); + sparks[i].colIndex = random8(); + sparks[i].vel *= flare->pos/SEGLEN; // proportional to height + sparks[i].vel *= -gravity *50; } - sparks[1].col = 255; // this will be our known spark - dying_gravity = gravity; - SEGENV.aux0 = 1; + //sparks[1].col = 345; // this will be our known spark + dying_gravity = gravity/2; + SEGENV.aux0 = 3; } - - float c1 = 120; - float c2 = 50; - if (sparks[1].col > 5) {//&& sparks[1].pos > 0) { // as long as our known spark is lit, work with all the sparks - //fade_out(255); + if (sparks[1].col > 4) {//&& sparks[1].pos > 0) { // as long as our known spark is lit, work with all the sparks for (int i = 1; i < nSparks; i++) { sparks[i].pos += sparks[i].vel; - sparks[i].pos = constrain(sparks[i].pos, 0, SEGLEN-1); sparks[i].vel += dying_gravity; - sparks[i].col *= .97; - sparks[i].col = constrain(sparks[i].col, 0, 255); // red cross dissolve - - if(sparks[i].pos > c1) { // fade white to yellow - setPixelColor(SEGMENT.start + sparks[i].pos,255, 255, (255 * (sparks[i].col - c1)) / (255 - c1)); - } else if (sparks[i].col < c2) { // fade from red to black - setPixelColor(SEGMENT.start + sparks[i].pos,(255 * sparks[i].col) / c2, 0, 0); - } else { // fade from yellow to red - setPixelColor(SEGMENT.start + sparks[i].pos,255, (255 * (sparks[i].col - c2)) / (c1 - c2), 0); + if (sparks[i].col > 3) sparks[i].col -= 4; + + if (sparks[i].pos > 0 && sparks[i].pos < SEGLEN) { + uint16_t prog = sparks[i].col; + uint32_t spColor = (SEGMENT.palette) ? color_wheel(sparks[i].colIndex) : SEGCOLOR(0); + CRGB c = CRGB::Black; //HeatColor(sparks[i].col); + if (prog > 300) { //fade from white to spark color + c = col_to_crgb(color_blend(spColor, WHITE, (prog - 300)*5)); + } else if (prog > 45) { //fade from spark color to black + c = col_to_crgb(color_blend(BLACK, spColor, prog - 45)); + uint8_t cooling = (300 - prog) >> 5; + c.g = qsub8(c.g, cooling); + c.b = qsub8(c.b, cooling * 2); + } + setPixelColor(SEGMENT.start + int(sparks[i].pos), c.red, c.green, c.blue); } } - dying_gravity *= .995; // as sparks burn out they fall slower + dying_gravity *= .99; // as sparks burn out they fall slower } else { - SEGENV.aux0 = 0; //init again - SEGENV.aux1 = 0; //back to flare + SEGENV.aux0 = 6 + random8(10); //wait for this many frames + } + } else { + SEGENV.aux0--; + if (SEGENV.aux0 < 4) { + SEGENV.aux0 = 0; //back to flare + SEGENV.step = (SEGMENT.intensity > random8()); //decide firing side } } + + SEGMENT.setOption(1, actuallyReverse); + return FRAMETIME; } diff --git a/wled00/wled00.ino b/wled00/wled00.ino index 5fc1092f..52951f61 100644 --- a/wled00/wled00.ino +++ b/wled00/wled00.ino @@ -98,7 +98,7 @@ //version code in format yymmddb (b = daily build) -#define VERSION 2001022 +#define VERSION 2001031 char versionString[] = "0.9.0-b2";