diff --git a/wled00/NpbWrapper.h b/wled00/NpbWrapper.h index a773b721..632d4cc3 100644 --- a/wled00/NpbWrapper.h +++ b/wled00/NpbWrapper.h @@ -6,7 +6,7 @@ //see https://github.com/Aircoookie/WLED/issues/2 for flicker free ESP32 support //PIN CONFIGURATION -#define LEDPIN 2 //strip pin. Any for ESP32, gpio2 is recommended for ESP8266 +#define LEDPIN 5 //strip pin. Any for ESP32, gpio2 is recommended for ESP8266 #define BTNPIN 0 //button pin. Needs to have pullup (gpio0 recommended) #define IR_PIN 4 //infrared pin. #define AUXPIN 15 //unused auxiliary output pin diff --git a/wled00/WS2812FX.cpp b/wled00/WS2812FX.cpp index 7e42df59..48f6ff19 100644 --- a/wled00/WS2812FX.cpp +++ b/wled00/WS2812FX.cpp @@ -43,7 +43,7 @@ #include "palettes.h" -#define LED_SKIP_AMOUNT 1 +#define LED_SKIP_AMOUNT 24 void WS2812FX::init(bool supportWhite, uint16_t countPixels, bool skipFirst) { @@ -100,7 +100,8 @@ void WS2812FX::clear() 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) return true; + if (m < FX_MODE_FIRE_2012) return false; + if (m == FX_MODE_FIRE_2012 || m == FX_MODE_COLORTWINKLE || m == FX_MODE_METEOR || m == FX_MODE_METEOR_SMOOTH || m == FX_MODE_RIPPLE) return true; return false; } @@ -736,7 +737,7 @@ uint16_t WS2812FX::mode_dynamic(void) { setPixelColor(i, color_wheel(random8())); } } - setPixelColor(SEGMENT.start + random(SEGMENT_LENGTH), color_wheel(random8())); + setPixelColor(SEGMENT.start + random16(SEGMENT_LENGTH), color_wheel(random8())); return 50 + (15 * (uint32_t)(255 - SEGMENT.speed)); } @@ -917,22 +918,14 @@ uint16_t WS2812FX::mode_theater_chase_rainbow(void) { * Running lights effect with smooth sine transition. */ uint16_t WS2812FX::mode_running_lights(void) { - uint8_t w = ((SEGMENT.colors[0] >> 24) & 0xFF); - uint8_t r = ((SEGMENT.colors[0] >> 16) & 0xFF); - uint8_t g = ((SEGMENT.colors[0] >> 8) & 0xFF); - uint8_t b = (SEGMENT.colors[0] & 0xFF); + uint8_t x_scale = (SEGMENT.intensity >> 3) + (SEGMENT.intensity >> 4); for(uint16_t i=0; i < SEGMENT_LENGTH; i++) { - int s = (sin(i+SEGMENT_RUNTIME.counter_mode_call) * 127) + 128; - if (SEGMENT.palette == 0) - { - setPixelColor(SEGMENT.start + i, (((uint32_t)(r * s)) / 255), (((uint32_t)(g * s)) / 255), (((uint32_t)(b * s)) / 255), (((uint32_t)(w * s)) / 255)); - } else { - setPixelColor(SEGMENT.start + i, color_from_palette(SEGMENT.start + i, true, PALETTE_SOLID_WRAP, 0, s)); - } + uint8_t s = sin8(i*x_scale +(SEGMENT_RUNTIME.counter_mode_step >> 3)); + setPixelColor(SEGMENT.start + i, color_blend(SEGMENT.colors[1], color_from_palette(SEGMENT.start + i, true, PALETTE_SOLID_WRAP, 0), s)); } - - return 10 + (uint16_t)(255 - SEGMENT.speed); + SEGMENT_RUNTIME.counter_mode_step += SEGMENT.speed; + return 20; } @@ -944,12 +937,10 @@ uint16_t WS2812FX::twinkle(uint32_t color) { for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { setPixelColor(i, SEGMENT.colors[1]); } - uint16_t min_leds = max(1, SEGMENT_LENGTH / 5); // make sure, at least one LED is on - uint16_t max_leds = max(1, SEGMENT_LENGTH / 2); // make sure, at least one LED is on - SEGMENT_RUNTIME.counter_mode_step = random(min_leds, max_leds); + SEGMENT_RUNTIME.counter_mode_step = map(SEGMENT.intensity, 0, 255, 1, SEGMENT_LENGTH); // make sure, at least one LED is on } - uint16_t i = SEGMENT.start + random(SEGMENT_LENGTH); + uint16_t i = SEGMENT.start + random16(SEGMENT_LENGTH); if (color == SEGMENT.colors[0]) { setPixelColor(i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 0)); @@ -958,7 +949,7 @@ uint16_t WS2812FX::twinkle(uint32_t color) { } SEGMENT_RUNTIME.counter_mode_step--; - return 50 + (8 * (uint16_t)(255 - SEGMENT.speed)); + return 20 + (5 * (uint16_t)(255 - SEGMENT.speed)); } /* @@ -1021,38 +1012,55 @@ void WS2812FX::fade_out(uint8_t rate) { /* - * twinkle_fade function + * Dissolve function */ -uint16_t WS2812FX::twinkle_fade(uint32_t color) { - fade_out((255-SEGMENT.intensity) / 32); - - if(random8(3) == 0) { - uint16_t i = SEGMENT.start + random(SEGMENT_LENGTH); - if (color == SEGMENT.colors[0]) - { - setPixelColor(i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 0)); - } else { - setPixelColor(i, color); +uint16_t WS2812FX::dissolve(uint32_t color) { + bool wa = (SEGMENT.colors[1] != 0 && _brightness < 255); //workaround, can't compare getPixel to color if not full brightness + + for (uint16_t j = 0; j <= SEGMENT_LENGTH / 15; j++) + { + if (random8() <= SEGMENT.intensity) { + for (uint8_t times = 0; times < 10; times++) //attempt to spawn a new pixel 5 times + { + uint16_t i = SEGMENT.start + random16(SEGMENT_LENGTH); + if (SEGMENT_RUNTIME.aux_param) { //dissolve to primary/palette + if (getPixelColor(i) == SEGMENT.colors[1] || wa) { + if (color == SEGMENT.colors[0]) + { + setPixelColor(i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 0)); + } else { setPixelColor(i, color); } + break; //only spawn 1 new pixel per frame per 50 LEDs + } + } else { //dissolve to secondary + if (getPixelColor(i) != SEGMENT.colors[1]) { setPixelColor(i, SEGMENT.colors[1]); break; } + } + } } } + + if (SEGMENT_RUNTIME.counter_mode_call > (255 - SEGMENT.speed) + 15) + { + SEGMENT_RUNTIME.aux_param = !SEGMENT_RUNTIME.aux_param; + SEGMENT_RUNTIME.counter_mode_call = 0; + } - return 100 + ((uint32_t)(255 - SEGMENT.speed)) / 3; + return 20; } /* - * Blink several LEDs on, fading out. + * Blink several LEDs on and then off */ -uint16_t WS2812FX::mode_twinkle_fade(void) { - return twinkle_fade(SEGMENT.colors[0]); +uint16_t WS2812FX::mode_dissolve(void) { + return dissolve(SEGMENT.colors[0]); } /* - * Blink several LEDs in random colors on, fading out. + * Blink several LEDs on and then off in random colors */ -uint16_t WS2812FX::mode_twinkle_fade_random(void) { - return twinkle_fade(color_wheel(random8())); +uint16_t WS2812FX::mode_dissolve_random(void) { + return dissolve(color_wheel(random8())); } @@ -1064,7 +1072,7 @@ uint16_t WS2812FX::mode_sparkle(void) { for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { setPixelColor(i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 1)); } - SEGMENT_RUNTIME.aux_param = random(SEGMENT_LENGTH); // aux_param stores the random led index + SEGMENT_RUNTIME.aux_param = random16(SEGMENT_LENGTH); // aux_param stores the random led index setPixelColor(SEGMENT.start + SEGMENT_RUNTIME.aux_param, SEGMENT.colors[0]); return 10 + (uint16_t)(255 - SEGMENT.speed); } @@ -1085,7 +1093,7 @@ uint16_t WS2812FX::mode_flash_sparkle(void) { setPixelColor(i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 0)); if(random8(5) == 0) { - SEGMENT_RUNTIME.aux_param = random(SEGMENT_LENGTH); // aux_param stores the random led index + SEGMENT_RUNTIME.aux_param = random16(SEGMENT_LENGTH); // aux_param stores the random led index setPixelColor(SEGMENT.start + SEGMENT_RUNTIME.aux_param, SEGMENT.colors[1]); return 20; } @@ -1104,7 +1112,7 @@ uint16_t WS2812FX::mode_hyper_sparkle(void) { if(random8(5) < 2) { for(uint16_t i=0; i < max(1, SEGMENT_LENGTH/3); i++) { - setPixelColor(SEGMENT.start + random(SEGMENT_LENGTH), SEGMENT.colors[1]); + setPixelColor(SEGMENT.start + random16(SEGMENT_LENGTH), SEGMENT.colors[1]); } return 20; } @@ -1515,7 +1523,7 @@ uint16_t WS2812FX::fireworks(uint32_t color) { for(uint16_t i=0; i SEGMENT_RUNTIME.counter_mode_step) { @@ -2046,9 +2054,9 @@ uint16_t WS2812FX::mode_random_chase(void) setPixelColor(i, getPixelColor(i-1)); } uint32_t color = getPixelColor(SEGMENT.start + 1); - int r = random(6) != 0 ? (color >> 16 & 0xFF) : random(256); - int g = random(6) != 0 ? (color >> 8 & 0xFF) : random(256); - int b = random(6) != 0 ? (color & 0xFF) : random(256); + int r = random8(6) != 0 ? (color >> 16 & 0xFF) : random8(); + int g = random8(6) != 0 ? (color >> 8 & 0xFF) : random8(); + int b = random8(6) != 0 ? (color & 0xFF) : random8(); setPixelColor(SEGMENT.start, r, g, b); return 10 + (uint16_t)(255 - SEGMENT.speed); @@ -2063,10 +2071,10 @@ typedef struct Oscillator { uint16_t WS2812FX::mode_oscillate(void) { - static oscillator oscillators[NUM_COLORS] = { + static oscillator oscillators[2] = { {SEGMENT_LENGTH/4, SEGMENT_LENGTH/8, 1, 1}, - {SEGMENT_LENGTH/4*2, SEGMENT_LENGTH/8, -1, 1}, - {SEGMENT_LENGTH/4*3, SEGMENT_LENGTH/8, 1, 2} + {SEGMENT_LENGTH/4*2, SEGMENT_LENGTH/8, -1, 1} + //{SEGMENT_LENGTH/4*3, SEGMENT_LENGTH/8, 1, 2} }; for(int8_t i=0; i < sizeof(oscillators)/sizeof(oscillators[0]); i++) { @@ -2074,12 +2082,12 @@ uint16_t WS2812FX::mode_oscillate(void) if((oscillators[i].dir == -1) && (oscillators[i].pos <= 0)) { oscillators[i].pos = 0; oscillators[i].dir = 1; - oscillators[i].speed = random(1, 3); + oscillators[i].speed = random8(1, 3); } if((oscillators[i].dir == 1) && (oscillators[i].pos >= (SEGMENT_LENGTH - 1))) { oscillators[i].pos = SEGMENT_LENGTH - 1; oscillators[i].dir = -1; - oscillators[i].speed = random(1, 3); + oscillators[i].speed = random8(1, 3); } } @@ -2462,7 +2470,7 @@ uint16_t WS2812FX::mode_bpm(void) uint16_t WS2812FX::mode_fillnoise8(void) { - if (SEGMENT_RUNTIME.counter_mode_call == 0) SEGMENT_RUNTIME.counter_mode_step = random(12345); + if (SEGMENT_RUNTIME.counter_mode_call == 0) SEGMENT_RUNTIME.counter_mode_step = random16(12345); CRGB fastled_col; for (uint16_t i = SEGMENT.start; i <= SEGMENT.stop; i++) { uint8_t index = inoise8(i * SEGMENT_LENGTH, SEGMENT_RUNTIME.counter_mode_step + i * SEGMENT_LENGTH) % 255; @@ -2670,14 +2678,6 @@ uint16_t WS2812FX::mode_meteor() { } -//smooth -//front ramping (maybe from get color -//50fps -//fade each led by a certain range (even ramp possible for sparkling) -//maybe dim to color[1] at end? -//_locked 0-15 bg-last 15-240 last-first 240-255 first-bg - -#define IS_PART_OF_METEOR 245 // smooth meteor effect // 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 @@ -2743,3 +2743,56 @@ uint16_t WS2812FX::mode_railway() SEGMENT_RUNTIME.counter_mode_step += 20; return 20; } + + +//Water ripple +//fade duration is random 2-5sec +//propagation velocity from speed +//drop rate from intensity +uint16_t WS2812FX::mode_ripple() +{ + uint16_t maxripples = SEGMENT_LENGTH / 5; + if (maxripples == 0) return mode_static(); + + //set background + for (uint16_t i = SEGMENT.start; i <= SEGMENT.stop; i++) + { + setPixelColor(i, SEGMENT.colors[1]); + } + + //draw wave + for (uint16_t rippleI = 0; rippleI < maxripples; rippleI++) + { + uint16_t storeI = SEGMENT.start + 5*rippleI; + uint8_t ripplestate = _locked[storeI]; + if (ripplestate) + { + uint16_t rippleorigin = ((_locked[storeI+2] << 8) & 0xFF00) + _locked[storeI+3]; + uint8_t rippledur = _locked[storeI+1]; + uint8_t ripplecolor = _locked[storeI+4]; + int16_t progress = ripplestate - rippledur -1; + int16_t propagation = (progress * (SEGMENT.speed >> 1)) >> 8; + int16_t left = rippleorigin - propagation; + int16_t right = rippleorigin +1 + propagation; + uint8_t mix = (ripplestate > 127) ? (ripplestate-128)*2 : 0; + uint32_t col = color_blend(color_from_palette(ripplecolor, false, false, 255), SEGMENT.colors[1], mix); + if (left >= SEGMENT.start) setPixelColor(left, col); + if (right <= SEGMENT.stop) setPixelColor(right, col); + + _locked[storeI]++; + } else //randomly create new ripple + { + if (random16(4096) <= SEGMENT.intensity) + { + _locked[storeI] = random8(120); //vary ripple strenght + _locked[storeI+1] = _locked[storeI]; + uint16_t origin = SEGMENT.start + random16(SEGMENT_LENGTH); + _locked[storeI+2] = origin >> 8; + _locked[storeI+3] = origin & 0xFF; + _locked[storeI+4] = random8(); + } + } + } + + return 20; +} diff --git a/wled00/WS2812FX.h b/wled00/WS2812FX.h index 679ee731..47f89e96 100644 --- a/wled00/WS2812FX.h +++ b/wled00/WS2812FX.h @@ -85,7 +85,7 @@ #define REVERSE (uint8_t)0x80 #define IS_REVERSE ((SEGMENT.options & REVERSE) == REVERSE) -#define MODE_COUNT 79 +#define MODE_COUNT 80 #define FX_MODE_STATIC 0 #define FX_MODE_BLINK 1 @@ -105,8 +105,8 @@ #define FX_MODE_RUNNING_LIGHTS 15 #define FX_MODE_TWINKLE 16 #define FX_MODE_TWINKLE_RANDOM 17 -#define FX_MODE_TWINKLE_FADE 18 -#define FX_MODE_TWINKLE_FADE_RANDOM 19 +#define FX_MODE_DISSOLVE 18 +#define FX_MODE_DISSOLVE_RANDOM 19 #define FX_MODE_SPARKLE 20 #define FX_MODE_FLASH_SPARKLE 21 #define FX_MODE_HYPER_SPARKLE 22 @@ -167,6 +167,7 @@ #define FX_MODE_METEOR 76 #define FX_MODE_METEOR_SMOOTH 77 #define FX_MODE_RAILWAY 78 +#define FX_MODE_RIPPLE 79 class WS2812FX { @@ -212,8 +213,8 @@ class WS2812FX { _mode[FX_MODE_THEATER_CHASE_RAINBOW] = &WS2812FX::mode_theater_chase_rainbow; _mode[FX_MODE_TWINKLE] = &WS2812FX::mode_twinkle; _mode[FX_MODE_TWINKLE_RANDOM] = &WS2812FX::mode_twinkle_random; - _mode[FX_MODE_TWINKLE_FADE] = &WS2812FX::mode_twinkle_fade; - _mode[FX_MODE_TWINKLE_FADE_RANDOM] = &WS2812FX::mode_twinkle_fade_random; + _mode[FX_MODE_DISSOLVE] = &WS2812FX::mode_dissolve; + _mode[FX_MODE_DISSOLVE_RANDOM] = &WS2812FX::mode_dissolve_random; _mode[FX_MODE_SPARKLE] = &WS2812FX::mode_sparkle; _mode[FX_MODE_FLASH_SPARKLE] = &WS2812FX::mode_flash_sparkle; _mode[FX_MODE_HYPER_SPARKLE] = &WS2812FX::mode_hyper_sparkle; @@ -275,7 +276,7 @@ class WS2812FX { _mode[FX_MODE_METEOR] = &WS2812FX::mode_meteor; _mode[FX_MODE_METEOR_SMOOTH] = &WS2812FX::mode_meteor_smooth; _mode[FX_MODE_RAILWAY] = &WS2812FX::mode_railway; - + _mode[FX_MODE_RIPPLE] = &WS2812FX::mode_ripple; _brightness = DEFAULT_BRIGHTNESS; _running = false; @@ -372,7 +373,7 @@ class WS2812FX { scan(bool), theater_chase(uint32_t, uint32_t, bool), twinkle(uint32_t), - twinkle_fade(uint32_t), + dissolve(uint32_t), chase(uint32_t, uint32_t, uint32_t, uint8_t), running(uint32_t, uint32_t), fireworks(uint32_t), @@ -402,8 +403,8 @@ class WS2812FX { mode_running_lights(void), mode_twinkle(void), mode_twinkle_random(void), - mode_twinkle_fade(void), - mode_twinkle_fade_random(void), + mode_dissolve(void), + mode_dissolve_random(void), mode_sparkle(void), mode_flash_sparkle(void), mode_hyper_sparkle(void), @@ -438,6 +439,7 @@ class WS2812FX { mode_tricolor_chase(void), mode_tricolor_wipe(void), mode_tricolor_fade(void), + mode_lightning(void), mode_icu(void), mode_multi_comet(void), mode_dual_larson_scanner(void), @@ -459,7 +461,7 @@ class WS2812FX { mode_meteor(void), mode_meteor_smooth(void), mode_railway(void), - mode_lightning(void); + mode_ripple(void); private: NeoPixelWrapper *bus; diff --git a/wled00/data/index.htm b/wled00/data/index.htm index 68ecbee7..0cb366fb 100644 --- a/wled00/data/index.htm +++ b/wled00/data/index.htm @@ -2,7 +2,7 @@ - WLED 0.8.2 + WLED 0.8.3