diff --git a/wled00/FX.cpp b/wled00/FX.cpp index b1e348849..5461347e3 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2346,9 +2346,8 @@ uint16_t WS2812FX::mode_spots_fade() * 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 + // number of balls based on intensity setting to max of 7 (cycles colors) + // non-chosen color is a random color int balls = int(((SEGMENT.intensity * 6.2) / 255) + 1); // ideally use speed for gravity effect on the bounce @@ -2375,7 +2374,7 @@ uint16_t WS2812FX::mode_BouncingBalls(void) { } for (int i = 0 ; i < balls ; i++) { - TimeSinceLastBounce[i] = millis() - ClockTimeSinceLastBounce[i]; + TimeSinceLastBounce[i] = (millis() - ClockTimeSinceLastBounce[i])/((255-SEGMENT.speed)*8/256 +1); Height[i] = 0.5 * Gravity * pow( TimeSinceLastBounce[i]/1000 , 2.0 ) + ImpactVelocity[i] * TimeSinceLastBounce[i]/1000; if ( Height[i] < 0 ) { @@ -2398,37 +2397,75 @@ uint16_t WS2812FX::mode_BouncingBalls(void) { color = color_wheel(random8()); } - setPixelColor(Position[i],color); + setPixelColor(SEGMENT.start+Position[i],color); } - return 20; + return FRAMETIME; } /* * Sinelon stolen from FASTLED examples */ -uint16_t WS2812FX::mode_sinelon(void) { +uint16_t WS2812FX::sinelon_base(bool dual, bool rainbow=false) { fade_out(SEGMENT.intensity); int pos = beatsin16(SEGMENT.speed/10,0,SEGLEN-1); static int prevpos = 0; + + uint32_t color1 = color_from_palette(pos, true, false, 0); + if (rainbow) { + color1 = color_wheel((pos % 8) * 32); + } - // 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)); + setPixelColor(i, color1); } } else { for (uint16_t i = prevpos; i < pos; i++) { - setPixelColor(i, color_from_palette(pos, false, false, 0)); + setPixelColor(SEGMENT.start + i, color1); + } + } + + if (dual) { + uint32_t color2 = SEGCOLOR(2); + + if (color2 == 0) { + color2 = color_from_palette(pos, true, false, 0); + } + if (rainbow) { + color2 = color_wheel((pos % 8) * 32); + } + if( pos < prevpos ) { + for (uint16_t i = pos; i < prevpos; i++) + { + setPixelColor(SEGMENT.start + SEGLEN-1-i, color2); + } + } else { + for (uint16_t i = prevpos; i < pos; i++) + { + setPixelColor(SEGMENT.start + SEGLEN-1-i, color2); + } } } prevpos = pos; return FRAMETIME; } +uint16_t WS2812FX::mode_sinelon(void) { + return sinelon_base(false); +} + +uint16_t WS2812FX::mode_sinelon_dual(void) { + return sinelon_base(true); +} + +uint16_t WS2812FX::mode_sinelon_rainbow(void) { + return sinelon_base(true, true); +} + //Rainbow with glitter, inspired by https://gist.github.com/kriegsman/062e10f7f07ba8518af6 uint16_t WS2812FX::mode_glitter() @@ -2470,12 +2507,12 @@ uint16_t WS2812FX::mode_popcorn(void) { fill(SEGCOLOR(1)); uint16_t ledIndex; - for(int8_t i=0; i < MAX_NUM_POPCORN; i++) { + for(int8_t i=0; i < SEGMENT.intensity*MAX_NUM_POPCORN/255; 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); + popcorn[i].velocity -= (GRAVITY * ((255-SEGMENT.speed)*8/256 + 1)); 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 @@ -2489,7 +2526,7 @@ uint16_t WS2812FX::mode_popcorn(void) { } } - return SPEED_FORMULA_L; + return FRAMETIME; } diff --git a/wled00/FX.h b/wled00/FX.h index 92f3cf78d..29a667939 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 94 #define FX_MODE_STATIC 0 #define FX_MODE_BLINK 1 @@ -177,7 +177,9 @@ #define FX_MODE_CANDLE 88 #define FX_MODE_BOUNCINGBALLS 89 #define FX_MODE_SINELON 90 -#define FX_MODE_POPCORN 91 +#define FX_MODE_SINELON_DUAL 91 +#define FX_MODE_SINELON_RAINBOW 92 +#define FX_MODE_POPCORN 93 class WS2812FX { @@ -324,6 +326,8 @@ class WS2812FX { _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_SINELON_DUAL] = &WS2812FX::mode_sinelon_dual; + _mode[FX_MODE_SINELON_RAINBOW] = &WS2812FX::mode_sinelon_rainbow; _mode[FX_MODE_POPCORN] = &WS2812FX::mode_popcorn; _mode[FX_MODE_GLITTER] = &WS2812FX::mode_glitter; _mode[FX_MODE_CANDLE] = &WS2812FX::mode_candle; @@ -510,6 +514,8 @@ class WS2812FX { mode_spots_fade(void), mode_BouncingBalls(void), mode_sinelon(void), + mode_sinelon_dual(void), + mode_sinelon_rainbow(void), mode_popcorn(void), mode_glitter(void), mode_candle(void); @@ -553,6 +559,7 @@ class WS2812FX { theater_chase(uint32_t, uint32_t, bool), running_base(bool), larson_scanner(bool), + sinelon_base(bool,bool), dissolve(uint32_t), chase(uint32_t, uint32_t, uint32_t, bool), gradient_base(bool), @@ -587,8 +594,8 @@ 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","Bouncing Balls", +"Sinelon","Sinelon Dual","Sinelon Rainbow","Popcorn" ])=====";