diff --git a/wled00/FX.cpp b/wled00/FX.cpp index e7c7c820..27bd730d 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -30,7 +30,6 @@ #define IBN 5100 #define PALETTE_SOLID_WRAP (paletteBlend == 1 || paletteBlend == 3) - /* * No blinking. Just plain old static light. */ @@ -1003,14 +1002,6 @@ uint16_t WS2812FX::mode_running_color(void) { } -/* - * Alternating red/blue pixels running. - */ -uint16_t WS2812FX::mode_running_red_blue(void) { - return running(RED, BLUE); -} - - /* * Alternating red/green pixels running. */ @@ -3880,3 +3871,153 @@ uint16_t WS2812FX::mode_tv_simulator(void) { return FRAMETIME; #endif } + +/* + Aurora effect +*/ + +//CONFIG +#define BACKLIGHT 5 +#define W_MAX_COUNT 20 //Number of simultaneous waves +#define W_MAX_SPEED 6 //Higher number, higher speed +#define W_WIDTH_FACTOR 6 //Higher number, smaller waves + +class AuroraWave { + private: + uint16_t ttl; + CRGB basecolor; + float basealpha; + uint16_t age; + uint16_t width; + float center; + bool goingleft; + float speed_factor; + bool alive = true; + + public: + void init(uint32_t segment_length, CRGB color) { + ttl = random(500, 1501); + basecolor = color; + basealpha = random(60, 101) / (float)100; + age = 0; + width = random(segment_length / 20, segment_length / W_WIDTH_FACTOR); //half of width to make math easier + if (!width) width = 1; + center = random(101) / (float)100 * segment_length; + goingleft = random(0, 2) == 0; + speed_factor = (random(10, 31) / (float)100 * W_MAX_SPEED / 255); + alive = true; + } + + CRGB getColorForLED(int ledIndex) { + if(ledIndex < center - width || ledIndex > center + width) return 0; //Position out of range of this wave + + CRGB rgb; + + //Offset of this led from center of wave + //The further away from the center, the dimmer the LED + float offset = ledIndex - center; + if (offset < 0) offset = -offset; + float offsetFactor = offset / width; + + //The age of the wave determines it brightness. + //At half its maximum age it will be the brightest. + float ageFactor = 0.1; + if((float)age / ttl < 0.5) { + ageFactor = (float)age / (ttl / 2); + } else { + ageFactor = (float)(ttl - age) / ((float)ttl * 0.5); + } + + //Calculate color based on above factors and basealpha value + float factor = (1 - offsetFactor) * ageFactor * basealpha; + rgb.r = basecolor.r * factor; + rgb.g = basecolor.g * factor; + rgb.b = basecolor.b * factor; + + return rgb; + }; + + //Change position and age of wave + //Determine if its sill "alive" + void update(uint32_t segment_length, uint32_t speed) { + if(goingleft) { + center -= speed_factor * speed; + } else { + center += speed_factor * speed; + } + + age++; + + if(age > ttl) { + alive = false; + } else { + if(goingleft) { + if(center + width < 0) { + alive = false; + } + } else { + if(center - width > segment_length) { + alive = false; + } + } + } + }; + + bool stillAlive() { + return alive; + }; +}; + +uint16_t WS2812FX::mode_aurora(void) { + //aux1 = Wavecount + //aux2 = Intensity in last loop + + AuroraWave* waves; + + if(SEGENV.aux0 != SEGMENT.intensity || SEGENV.call == 0) { + //Intensity slider changed or first call + SEGENV.aux1 = ((float)SEGMENT.intensity / 255) * W_MAX_COUNT; + SEGENV.aux0 = SEGMENT.intensity; + + if(!SEGENV.allocateData(sizeof(AuroraWave) * SEGENV.aux1)) { + return mode_static(); //allocation failed + } + + waves = reinterpret_cast(SEGENV.data); + + for(int i = 0; i < SEGENV.aux1; i++) { + waves[i].init(SEGLEN, col_to_crgb(color_from_palette(random8(), false, false, random(0, 3)))); + } + } else { + waves = reinterpret_cast(SEGENV.data); + } + + for(int i = 0; i < SEGENV.aux1; i++) { + //Update values of wave + waves[i].update(SEGLEN, SEGMENT.speed); + + if(!(waves[i].stillAlive())) { + //If a wave dies, reinitialize it starts over. + waves[i].init(SEGLEN, col_to_crgb(color_from_palette(random8(), false, false, random(0, 3)))); + } + } + + //Loop through LEDs to determine color + for(int i = 0; i < SEGLEN; i++) { + CRGB mixedRgb = CRGB(BACKLIGHT, BACKLIGHT, BACKLIGHT); + + //For each LED we must check each wave if it is "active" at this position. + //If there are multiple waves active on a LED we multiply their values. + for(int j = 0; j < SEGENV.aux1; j++) { + CRGB rgb = waves[j].getColorForLED(i); + + if(rgb != CRGB(0)) { + mixedRgb += rgb; + } + } + + setPixelColor(i, mixedRgb[0], mixedRgb[1], mixedRgb[2], BACKLIGHT); + } + + return FRAMETIME; +} \ No newline at end of file diff --git a/wled00/FX.h b/wled00/FX.h index f368e567..b50902bb 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -119,7 +119,6 @@ #define IS_REVERSE ((SEGMENT.options & REVERSE ) == REVERSE ) #define IS_SELECTED ((SEGMENT.options & SELECTED ) == SELECTED ) - #define MODE_COUNT 118 #define FX_MODE_STATIC 0 @@ -160,7 +159,7 @@ #define FX_MODE_TRAFFIC_LIGHT 35 #define FX_MODE_COLOR_SWEEP_RANDOM 36 #define FX_MODE_RUNNING_COLOR 37 -#define FX_MODE_RUNNING_RED_BLUE 38 +#define FX_MODE_AURORA 38 #define FX_MODE_RUNNING_RANDOM 39 #define FX_MODE_LARSON_SCANNER 40 #define FX_MODE_COMET 41 @@ -389,7 +388,7 @@ class WS2812FX { _mode[FX_MODE_TRAFFIC_LIGHT] = &WS2812FX::mode_traffic_light; _mode[FX_MODE_COLOR_SWEEP_RANDOM] = &WS2812FX::mode_color_sweep_random; _mode[FX_MODE_RUNNING_COLOR] = &WS2812FX::mode_running_color; - _mode[FX_MODE_RUNNING_RED_BLUE] = &WS2812FX::mode_running_red_blue; + _mode[FX_MODE_AURORA] = &WS2812FX::mode_aurora; _mode[FX_MODE_RUNNING_RANDOM] = &WS2812FX::mode_running_random; _mode[FX_MODE_LARSON_SCANNER] = &WS2812FX::mode_larson_scanner; _mode[FX_MODE_COMET] = &WS2812FX::mode_comet; @@ -603,7 +602,7 @@ class WS2812FX { mode_colorful(void), mode_traffic_light(void), mode_running_color(void), - mode_running_red_blue(void), + mode_aurora(void), mode_running_random(void), mode_larson_scanner(void), mode_comet(void), @@ -764,7 +763,7 @@ const char JSON_mode_names[] PROGMEM = R"=====([ "Solid","Blink","Breathe","Wipe","Wipe Random","Random Colors","Sweep","Dynamic","Colorloop","Rainbow", "Scan","Scan Dual","Fade","Theater","Theater Rainbow","Running","Saw","Twinkle","Dissolve","Dissolve Rnd", "Sparkle","Sparkle Dark","Sparkle+","Strobe","Strobe Rainbow","Strobe Mega","Blink Rainbow","Android","Chase","Chase Random", -"Chase Rainbow","Chase Flash","Chase Flash Rnd","Rainbow Runner","Colorful","Traffic Light","Sweep Random","Running 2","Red & Blue","Stream", +"Chase Rainbow","Chase Flash","Chase Flash Rnd","Rainbow Runner","Colorful","Traffic Light","Sweep Random","Running 2","Aurora","Stream", "Scanner","Lighthouse","Fireworks","Rain","Merry Christmas","Fire Flicker","Gradient","Loading","Police","Police All", "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", @@ -782,7 +781,7 @@ const char JSON_palette_names[] PROGMEM = R"=====([ "Pastel","Sunset 2","Beech","Vintage","Departure","Landscape","Beach","Sherbet","Hult","Hult 64", "Drywet","Jul","Grintage","Rewhi","Tertiary","Fire","Icefire","Cyane","Light Pink","Autumn", "Magenta","Magred","Yelmag","Yelblu","Orange & Teal","Tiamat","April Night","Orangery","C9","Sakura", -"Aurora","Atlantica","C9 2","C9 New","Temperature" +"Aurora","Atlantica","C9 2","C9 New","Temperature","Aurora 2" ])====="; #endif diff --git a/wled00/palettes.h b/wled00/palettes.h index 1753ea79..80b0ea53 100644 --- a/wled00/palettes.h +++ b/wled00/palettes.h @@ -13,7 +13,7 @@ #ifndef PalettesWLED_h #define PalettesWLED_h -#define GRADIENT_PALETTE_COUNT 42 +#define GRADIENT_PALETTE_COUNT 43 const byte ib_jul01_gp[] PROGMEM = { 0, 194, 1, 1, @@ -631,6 +631,14 @@ const byte temperature_gp[] PROGMEM = { 240, 80, 3, 3, 255, 80, 3, 3}; + const byte Aurora2[] PROGMEM = { + 0, 17, 177, 13, //Greenish + 64, 121, 242, 5, //Greenish + 128, 25, 173, 121, //Turquoise + 192, 250, 77, 127, //Pink + 255, 171, 101, 221 //Purple + }; + // Single array of defined cpt-city color palettes. // This will let us programmatically choose one based on // a number, rather than having to activate each explicitly @@ -677,7 +685,8 @@ const byte* const gGradientPalettes[] PROGMEM = { Atlantica_gp, //51-38 Atlantica C9_2_gp, //52-39 C9 2 C9_new_gp, //53-40 C9 New - temperature_gp //54-41 Temperature + temperature_gp, //54-41 Temperature + Aurora2 //55-42 Aurora 2 }; #endif