diff --git a/wled00/FX.cpp b/wled00/FX.cpp index b1e348849..1791b710c 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; } @@ -2341,95 +2365,6 @@ uint16_t WS2812FX::mode_spots_fade() } -/* -* Bouncing Balls Effect -* Adapted from: https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/ -*/ -uint16_t WS2812FX::mode_BouncingBalls(void) { - // number of balls based on intensity setting, - // only has 4 for a few of the higher settings as there is no colour selection - // fourth ball is a random colour - int balls = int(((SEGMENT.intensity * 6.2) / 255) + 1); - - // ideally use speed for gravity effect on the bounce - float Gravity = -9.81; - - const int maxBallCount = 7; - static float Height[maxBallCount]; - static float ImpactVelocity[maxBallCount]; - static int Position[maxBallCount]; - static float TimeSinceLastBounce[maxBallCount]; - static long ClockTimeSinceLastBounce[maxBallCount]; - static int StartHeight = 1; // height in metres (strip length) - static float Dampening[maxBallCount] = {0}; // Coefficient of Restitution (bounce damping) - static float ImpactVelocityStart=sqrt( -2 * Gravity * StartHeight); - - // Different from the examples, to allow for initialisation of the first bounce - if (Dampening[0] == 0) { - for (int i = 0 ; i < maxBallCount ; i++) { - ClockTimeSinceLastBounce[i] = millis(); - ImpactVelocity[i] = ImpactVelocityStart; - TimeSinceLastBounce[i] = 0; - Dampening[i] = 0.90 - float(i)/pow(maxBallCount,2); - } - } - - for (int i = 0 ; i < balls ; i++) { - TimeSinceLastBounce[i] = millis() - ClockTimeSinceLastBounce[i]; - Height[i] = 0.5 * Gravity * pow( TimeSinceLastBounce[i]/1000 , 2.0 ) + ImpactVelocity[i] * TimeSinceLastBounce[i]/1000; - - if ( Height[i] < 0 ) { - Height[i] = 0; - ImpactVelocity[i] = Dampening[i] * ImpactVelocity[i]; - ClockTimeSinceLastBounce[i] = millis(); - - if ( ImpactVelocity[i] < 0.01 ) { - ImpactVelocity[i] = ImpactVelocityStart; - } - } - Position[i] = round( Height[i] * (SEGLEN - 1) / StartHeight); - } - - fill(BLACK); - - for (int i = 0 ; i < balls ; i++) { - uint32_t color = SEGCOLOR(i % NUM_COLORS); - if (!color) { - color = color_wheel(random8()); - } - - setPixelColor(Position[i],color); - } - - return 20; -} - -/* -* Sinelon stolen from FASTLED examples -*/ -uint16_t WS2812FX::mode_sinelon(void) { - - fade_out(SEGMENT.intensity); - int pos = beatsin16(SEGMENT.speed/10,0,SEGLEN-1); - static int prevpos = 0; - - // setRange seems great to use, but doesn't work here for some reason - if( pos < prevpos ) { - for (uint16_t i = pos; i < prevpos; i++) - { - setPixelColor(i, color_from_palette(pos, false, false, 0)); - } - } else { - for (uint16_t i = prevpos; i < pos; i++) - { - setPixelColor(i, color_from_palette(pos, false, false, 0)); - } - } - prevpos = pos; - return FRAMETIME; -} - - //Rainbow with glitter, inspired by https://gist.github.com/kriegsman/062e10f7f07ba8518af6 uint16_t WS2812FX::mode_glitter() { @@ -2444,55 +2379,6 @@ uint16_t WS2812FX::mode_glitter() } -/* -* POPCORN -*/ -typedef struct Kernel { - float position; - float velocity; - int32_t color; -} kernel; - -#define MAX_NUM_POPCORN 12 -#define GRAVITY 0.06 - -uint16_t WS2812FX::mode_popcorn(void) { - uint32_t popcornColor = SEGCOLOR(0); - uint32_t bgColor = SEGCOLOR(1); - if(popcornColor == bgColor) popcornColor = color_wheel(random8()); - - static kernel popcorn[MAX_NUM_POPCORN]; - static float coeff = 0.0f; - if(coeff == 0.0f) { // calculate the velocity coeff once (the secret sauce) - coeff = pow((float)SEGLEN, 0.5223324f) * 0.3944296f; - } - - fill(SEGCOLOR(1)); - - uint16_t ledIndex; - for(int8_t i=0; i < MAX_NUM_POPCORN; i++) { - bool isActive = popcorn[i].position >= 0.0f; - - if(isActive) { // if kernel is active, update its position - popcorn[i].position += popcorn[i].velocity; - popcorn[i].velocity -= (GRAVITY * SEGMENT.intensity/25); - ledIndex = SEGMENT.start + popcorn[i].position; - if(ledIndex >= SEGMENT.start && ledIndex <= SEGMENT.stop) setPixelColor(ledIndex, popcorn[i].color); - } else { // if kernel is inactive, randomly pop it - if(random8() < 2) { // POP!!! - popcorn[i].position = 0.0f; - popcorn[i].velocity = coeff * (random(66, 100) / 100.0f); - popcorn[i].color = popcornColor; - ledIndex = SEGMENT.start; - setPixelColor(ledIndex, popcorn[i].color); - } - } - } - - return SPEED_FORMULA_L; -} - - //values close to 100 produce 5Hz flicker, which looks very candle-y //Inspired by https://github.com/avanhanegem/ArduinoCandleEffectNeoPixel //and https://cpldcpu.wordpress.com/2016/01/05/reverse-engineering-a-real-candle/