From c9bdecdb69454d377c38406261f74ca794fff419 Mon Sep 17 00:00:00 2001 From: Blaz Kristan Date: Tue, 10 May 2022 00:35:26 +0200 Subject: [PATCH] API change. New SR effects. Bugfixes. --- wled00/FX.cpp | 398 ++++++++++++++++++++++++++++++++++++++++---- wled00/FX.h | 60 +++++-- wled00/FX_2Dfcn.cpp | 229 ++++++++++++------------- wled00/FX_fcn.cpp | 49 ++++-- 4 files changed, 540 insertions(+), 196 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 2758c99a..5bc6f848 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -1102,6 +1102,7 @@ uint16_t WS2812FX::mode_comet(void) { */ uint16_t WS2812FX::mode_fireworks() { fade_out(0); + if (SEGENV.call == 0) { SEGENV.aux0 = UINT16_MAX; SEGENV.aux1 = UINT16_MAX; @@ -1112,11 +1113,11 @@ uint16_t WS2812FX::mode_fireworks() { if (valid1) sv1 = getPixelColor(SEGENV.aux0); if (valid2) sv2 = getPixelColor(SEGENV.aux1); blur(255-SEGMENT.speed); - if (valid1) setPixelColor(SEGENV.aux0 , sv1); + if (valid1) setPixelColor(SEGENV.aux0, sv1); if (valid2) setPixelColor(SEGENV.aux1, sv2); - for(uint16_t i=0; i> 1)) == 0) { + for (uint16_t i=0; i> 1)) == 0) { uint16_t index = random(SEGLEN); setPixelColor(index, color_from_palette(random8(), false, false, 0)); SEGENV.aux1 = SEGENV.aux0; @@ -1857,13 +1858,6 @@ uint16_t WS2812FX::mode_fire_2012() byte* heat = SEGENV.data; - if (SEGENV.call == 0) { - DEBUG_PRINTLN(nFlames); - DEBUG_PRINTLN(SEGLEN); - DEBUG_PRINTLN(nFlames*SEGLEN); - DEBUG_PRINTLN(q); - } - if (it != SEGENV.step) { SEGENV.step = it; uint8_t ignition = max(3,SEGLEN/10); // ignition area: 10% of segment length or minimum 3 pixels @@ -4248,8 +4242,8 @@ uint16_t WS2812FX::mode_aurora(void) { /////////////////////////////////////////////////////////////////////////////// //*************************** 2D routines *********************************** -// sample 2D routine -uint16_t WS2812FX::mode_2DBlackHole_A() { // By: Stepko https://editor.soulmatelights.com/gallery/1012 , Modified by: Andrew Tuline +// Black hole +uint16_t WS2812FX::mode_2DBlackHole(void) { // By: Stepko https://editor.soulmatelights.com/gallery/1012 , Modified by: Andrew Tuline uint16_t w = SEGMENT.virtualWidth(); uint16_t h = SEGMENT.virtualHeight(); uint16_t dataSize = sizeof(CRGB) * w * h; @@ -4262,24 +4256,24 @@ uint16_t WS2812FX::mode_2DBlackHole_A() { // By: Stepko https://edito // initialize on first call if (SEGENV.call == 0) { for (y = 0; y < h; y++) for (x = 0; x < w; x++) { - leds[x + y * w] = CRGB::Black; + leds[XY(x,y)] = CRGB::Black; } } - fadeToBlackBy(32, leds); // create fading trails + fadeToBlackBy(leds, 32); // create fading trails float t = (float)(millis())/128; for (byte i = 0; i < 8; i++) { x = beatsin8(SEGMENT.c1x>>3, 0, w - 1, 0, ((i % 2) ? 128 : 0) + t * i); y = beatsin8(10 , 0, h - 1, 0, ((i % 2) ? 192 : 64) + t * i); - leds[x + y * w] += CHSV(i*32, 255, 255); + leds[XY(x,y)] += CHSV(i*32, 255, 255); } for (byte i = 0; i < 8; i++) { x = beatsin8(SEGMENT.c2x>>3, w/4, w - 1 - w/4, 0, ((i % 2) ? 128 : 0) + t * i); y = beatsin8(SEGMENT.c3x>>3, h/4, h - 1 - h/4, 0, ((i % 2) ? 192 : 64) + t * i); - leds[x + y * w] += CHSV(i*32, 255, 255); + leds[XY(x,y)] += CHSV(i*32, 255, 255); } - leds[w/2 * (1 + h)] = CHSV(0,0,255); - blur2d(16, leds); + leds[XY(w/2,h/2)] = CHSV(0,0,255); + blur2d(leds, 16); for (y = 0; y < h; y++) for (x = 0; x < w; x++) { uint16_t o = x + y * w; @@ -4288,26 +4282,356 @@ uint16_t WS2812FX::mode_2DBlackHole_A() { // By: Stepko https://edito return FRAMETIME; } // mode_2DBlackHole() -// same as above not using leds[] -uint16_t WS2812FX::mode_2DBlackHole_B() { // By: Stepko https://editor.soulmatelights.com/gallery/1012 , Modified by: Andrew Tuline - uint16_t w = SEGMENT.virtualWidth(); - uint16_t h = SEGMENT.virtualHeight(); - uint16_t x, y; +///////////////////// +// 2D DNA // +///////////////////// +uint16_t WS2812FX::mode_2Ddna(void) { // dna originally by by ldirko at https://pastebin.com/pCkkkzcs. Updated by Preyy. WLED conversion by Andrew Tuline. + uint16_t width = SEGMENT.virtualWidth(); + uint16_t height = SEGMENT.virtualHeight(); + uint16_t dataSize = sizeof(CRGB) * width * height; - fade_out2D(32); // create fading trails - float t = (float)(millis())/128; - for (byte i = 0; i < 8; i++) { - x = beatsin8(SEGMENT.c1x>>3, 0, w - 1, 0, ((i % 2) ? 128 : 0) + t * i); - y = beatsin8(10 , 0, h - 1, 0, ((i % 2) ? 192 : 64) + t * i); - setPixelColorXY(x, y, col_to_crgb(getPixelColorXY(x,y)) + CHSV(i*32, 255, 255)); + if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed + CRGB *leds = reinterpret_cast(SEGENV.data); + + fadeToBlackBy(leds, 64); + + for(int i = 0; i < width; i++) { // change to height if you want to re-orient, and swap the 4 lines below. + leds[XY(i, beatsin8(SEGMENT.speed/8, 0, height-1, 0, i*4))] = ColorFromPalette(currentPalette, i*5+millis()/17, beatsin8(5, 55, 255, 0, i*10), LINEARBLEND); + leds[XY(i, beatsin8(SEGMENT.speed/8, 0, height-1, 0, i*4+128))] = ColorFromPalette(currentPalette,i*5+128+millis()/17, beatsin8(5, 55, 255, 0, i*10+128), LINEARBLEND); // 180 degrees (128) out of phase } - for (byte i = 0; i < 8; i++) { - x = beatsin8(SEGMENT.c2x>>3, w/4, w - 1 - w/4, 0, ((i % 2) ? 128 : 0) + t * i); - y = beatsin8(SEGMENT.c3x>>3, h/4, h - 1 - h/4, 0, ((i % 2) ? 192 : 64) + t * i); - setPixelColorXY(x, y, col_to_crgb(getPixelColorXY(x,y)) + CHSV(i*32, 255, 255)); - } - setPixelColorXY(w/2, h/2, WHITE); - //blur2d(16); + + blur2d(leds, SEGMENT.intensity/8); + + setPixels(leds); + return FRAMETIME; -} // mode_2DBlackHole() +} // mode_2Ddna() +///////////////////////// +// 2D DNA Spiral // +///////////////////////// +uint16_t WS2812FX::mode_2DDNASpiral() { // By: ldirko https://editor.soulmatelights.com/gallery/810 , modified by: Andrew Tuline + uint16_t width = SEGMENT.virtualWidth(); + uint16_t height = SEGMENT.virtualHeight(); + uint16_t dataSize = sizeof(CRGB) * width * height; + + if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed + CRGB *leds = reinterpret_cast(SEGENV.data); + + uint8_t speeds = SEGMENT.speed/2; + uint8_t freq = SEGMENT.intensity/8; + + static byte hue = 0; + uint32_t ms = millis() / 20; + nscale8(leds, 120); + + for (uint16_t i = 0; i < height; i++) { + uint16_t x = beatsin8(speeds, 0, width - 1, 0, i * freq) + beatsin8(speeds - 7, 0, width - 1, 0, i * freq + 128); + uint16_t x1 = beatsin8(speeds, 0, width - 1, 0, 128 + i * freq) + beatsin8(speeds - 7, 0, width - 1, 0, 128 + 64 + i * freq); + hue = i * 128 / width + ms; //ewowi20210629: not width - 1 to avoid crash if width = 1 + if ((i + ms / 8) & 3) { + x = x / 2; x1 = x1 / 2; + byte steps = abs8(x - x1) + 1; + for (byte k = 1; k <= steps; k++) { + byte dx = lerp8by8(x, x1, k * 255 / steps); + uint16_t index = XY(dx, i); + leds[index] += ColorFromPalette(currentPalette, hue, 255, LINEARBLEND); + leds[index] %= (k * 255 / steps); //for draw gradient line + } + leds[XY(x, i)] += CRGB::DarkSlateGray; + leds[XY(x1, i)] += CRGB::White; + } + } + + setPixels(leds); // Use this ONLY if we're going to display via leds[x] method. + return FRAMETIME; +} // mode_2DDNASpiral() + +///////////////////////// +// 2D Drift // +///////////////////////// +uint16_t WS2812FX::mode_2DDrift() { // By: Stepko https://editor.soulmatelights.com/gallery/884-drift , Modified by: Andrew Tuline + uint16_t width = SEGMENT.virtualWidth(); + uint16_t height = SEGMENT.virtualHeight(); + uint16_t dataSize = sizeof(CRGB) * width * height; + + if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed + CRGB *leds = reinterpret_cast(SEGENV.data); + + #define CenterX ((width / 2) - 0.5) + #define CenterY ((height / 2) - 0.5) + const byte maxDim = max(width, height); + fadeToBlackBy(leds, 128); + unsigned long t = millis() / (32 - SEGMENT.speed/8); + for (float i = 1; i < maxDim / 2; i += 0.25) { + float angle = radians(t * (maxDim / 2 - i)); + uint16_t myX = (uint16_t)(CenterX + sin_t(angle) * i); + uint16_t myY = (uint16_t)(CenterY + cos_t(angle) * i); + leds[XY( myX, myY)] += ColorFromPalette(currentPalette, (i * 20) + (t / 20), 255, LINEARBLEND); + } + blur2d(leds, SEGMENT.intensity/8); + + setPixels(leds); // Use this ONLY if we're going to display via leds[x] method. + return FRAMETIME; +} // mode_2DDrift() + +////////////////////////// +// 2D Firenoise // +////////////////////////// +uint16_t WS2812FX::mode_2Dfirenoise(void) { // firenoise2d. By Andrew Tuline. Yet another short routine. + uint16_t width = SEGMENT.virtualWidth(); + uint16_t height = SEGMENT.virtualHeight(); + uint16_t dataSize = sizeof(CRGB) * width * height; + + if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed + CRGB *leds = reinterpret_cast(SEGENV.data); + + uint16_t xscale = SEGMENT.intensity*4; + uint32_t yscale = SEGMENT.speed*8; + uint8_t indexx = 0; + + currentPalette = CRGBPalette16( CRGB(0,0,0), CRGB(0,0,0), CRGB(0,0,0), CRGB(0,0,0), + CRGB::Red, CRGB::Red, CRGB::Red, CRGB::DarkOrange, + CRGB::DarkOrange,CRGB::DarkOrange, CRGB::Orange, CRGB::Orange, + CRGB::Yellow, CRGB::Orange, CRGB::Yellow, CRGB::Yellow); + + for (uint16_t j=0; j < width; j++) { + for (uint16_t i=0; i < height; i++) { + indexx = inoise8(j*yscale*height/255, i*xscale+millis()/4); // We're moving along our Perlin map. + leds[XY(j,i)] = ColorFromPalette(currentPalette, min(i*(indexx)>>4, 255), i*255/width, LINEARBLEND); // With that value, look up the 8 bit colour palette value and assign it to the current LED. + } // for i + } // for j + + setPixels(leds); + return FRAMETIME; +} // mode_2Dfirenoise() + +////////////////////////////// +// 2D Frizzles // +////////////////////////////// +uint16_t WS2812FX::mode_2DFrizzles(void) { // By: Stepko https://editor.soulmatelights.com/gallery/640-color-frizzles , Modified by: Andrew Tuline + uint16_t width = SEGMENT.virtualWidth(); + uint16_t height = SEGMENT.virtualHeight(); + uint16_t dataSize = sizeof(CRGB) * width * height; + + if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed + CRGB *leds = reinterpret_cast(SEGENV.data); + + fadeToBlackBy(leds, 16); + for (byte i = 8; i > 0; i--) { + leds[XY(beatsin8(SEGMENT.speed/8 + i, 0, width - 1), beatsin8(SEGMENT.intensity/8 - i, 0, height - 1))] += ColorFromPalette(currentPalette, beatsin8(12, 0, 255), 255, LINEARBLEND); + } + blur2d(leds, 16); + + setPixels(leds); + return FRAMETIME; +} // mode_2DFrizzles() + +/////////////////////////////////////////// +// 2D Cellular Automata Game of life // +/////////////////////////////////////////// + +///////////////////////// +// 2D Hiphotic // +///////////////////////// +uint16_t WS2812FX::mode_2DHiphotic() { // By: ldirko https://editor.soulmatelights.com/gallery/810 , Modified by: Andrew Tuline + uint16_t width = SEGMENT.virtualWidth(); + uint16_t height = SEGMENT.virtualHeight(); + uint16_t dataSize = sizeof(CRGB) * width * height; + + if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed + CRGB *leds = reinterpret_cast(SEGENV.data); + + uint32_t a = millis() / 8; + + for (uint16_t x = 0; x < width; x++) { + for (uint16_t y = 0; y < height; y++) { + leds[XY(x,y)] = ColorFromPalette(currentPalette, sin8(cos8(x * SEGMENT.speed/16 + a / 3) + sin8(y * SEGMENT.intensity/16 + a / 4) + a), 255, LINEARBLEND); + } + } + + setPixels(leds); // Use this ONLY if we're going to display via leds[x] method. + return FRAMETIME; +} // mode_2DHiphotic() + +///////////////////////// +// 2D Julia // +///////////////////////// + +////////////////////////////// +// 2D Lissajous // +////////////////////////////// +uint16_t WS2812FX::mode_2DLissajous(void) { // By: Andrew Tuline + uint16_t width = SEGMENT.virtualWidth(); + uint16_t height = SEGMENT.virtualHeight(); + uint16_t dataSize = sizeof(CRGB) * width * height; + + if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed + CRGB *leds = reinterpret_cast(SEGENV.data); + + fadeToBlackBy(leds, SEGMENT.intensity); + + for (int i=0; i < 256; i ++) { + + uint8_t xlocn = sin8(millis()/2+i*SEGMENT.speed/64); + uint8_t ylocn = cos8(millis()/2+i*128/64); + + xlocn = map(xlocn,0,255,0,width-1); + ylocn = map(ylocn,0,255,0,height-1); + leds[XY(xlocn,ylocn)] = ColorFromPalette(currentPalette, millis()/100+i, 255, LINEARBLEND); + } + + setPixels(leds); + return FRAMETIME; +} // mode_2DLissajous() + + +/////////////////////// +// 2D Matrix // +/////////////////////// +uint16_t WS2812FX::mode_2Dmatrix(void) { // Matrix2D. By Jeremy Williams. Adapted by Andrew Tuline & improved by merkisoft and ewowi. + uint16_t width = SEGMENT.virtualWidth(); + uint16_t height = SEGMENT.virtualHeight(); + uint16_t dataSize = sizeof(CRGB) * width * height; + + if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed + CRGB *leds = reinterpret_cast(SEGENV.data); + + if (SEGENV.call == 0) fill_solid(leds, 0); + + uint8_t fade = map(SEGMENT.c1x, 0, 255, 50, 250); // equals trail size + uint8_t speed = (256-SEGMENT.speed) >> map(MIN(height, 150), 0, 150, 0, 3); // slower speeds for small displays + + CRGB spawnColor; + CRGB trailColor; + if (SEGMENT.c2x > 128) { + spawnColor = SEGCOLOR(0); + trailColor = SEGCOLOR(1); + } else { + spawnColor = CRGB(175,255,175); + trailColor = CRGB(27,130,39); + } + + if (millis() - SEGENV.step >= speed) { + SEGENV.step = millis(); + for (int16_t row=height-1; row>=0; row--) { + for (int16_t col=0; col> 2) +2)) & 0xFFFF; + counter = counter >> 8; + + //Akemi + uint8_t akemi[32][32]={ + {0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,2,2,3,3,3,3,3,3,2,2,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,2,3,3,0,0,0,0,0,0,3,3,2,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,2,3,0,0,0,6,5,5,4,0,0,0,3,2,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,2,3,0,0,6,6,5,5,5,5,4,4,0,0,3,2,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,2,3,0,6,5,5,5,5,5,5,5,5,4,0,3,2,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,2,3,0,6,5,5,5,5,5,5,5,5,5,5,4,0,3,2,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,3,2,0,6,5,5,5,5,5,5,5,5,5,5,4,0,2,3,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,3,2,3,6,5,5,7,7,5,5,5,5,7,7,5,5,4,3,2,3,0,0,0,0,0,0}, + {0,0,0,0,0,2,3,1,3,6,5,1,7,7,7,5,5,1,7,7,7,5,4,3,1,3,2,0,0,0,0,0}, + {0,0,0,0,0,8,3,1,3,6,5,1,7,7,7,5,5,1,7,7,7,5,4,3,1,3,8,9,0,0,0,0}, + {0,0,0,0,0,8,3,1,3,6,5,5,1,1,5,5,5,5,1,1,5,5,4,3,1,3,8,0,0,0,0,0}, + {0,0,0,0,0,2,3,1,3,6,5,5,5,5,5,5,5,5,5,5,5,5,4,3,1,3,2,0,0,0,0,0}, + {0,0,0,0,0,0,3,2,3,6,5,5,5,5,5,5,5,5,5,5,5,5,4,3,2,3,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,6,5,5,5,5,5,7,7,5,5,5,5,5,4,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,6,5,5,5,5,5,5,5,5,5,5,5,5,4,0,0,0,0,0,0,0,0,0}, + {1,0,0,0,0,0,0,0,0,6,5,5,5,5,5,5,5,5,5,5,5,5,4,0,0,0,0,0,0,0,0,2}, + {0,2,2,2,0,0,0,0,0,6,5,5,5,5,5,5,5,5,5,5,5,5,4,0,0,0,0,0,2,2,2,0}, + {0,0,0,3,2,0,0,0,6,5,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,0,2,2,0,0,0}, + {0,0,0,3,2,0,0,0,6,5,5,5,5,5,5,5,5,5,5,5,5,5,5,4,0,0,0,2,3,0,0,0}, + {0,0,0,0,3,2,0,0,0,0,3,3,0,3,3,0,0,3,3,0,3,3,0,0,0,0,2,2,0,0,0,0}, + {0,0,0,0,3,2,0,0,0,0,3,2,0,3,2,0,0,3,2,0,3,2,0,0,0,0,2,3,0,0,0,0}, + {0,0,0,0,0,3,2,0,0,3,2,0,0,3,2,0,0,3,2,0,0,3,2,0,0,2,3,0,0,0,0,0}, + {0,0,0,0,0,3,2,2,2,2,0,0,0,3,2,0,0,3,2,0,0,0,3,2,2,2,3,0,0,0,0,0}, + {0,0,0,0,0,0,3,3,3,0,0,0,0,3,2,0,0,3,2,0,0,0,0,3,3,3,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,3,2,0,0,3,2,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,3,2,0,0,3,2,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,3,2,0,0,3,2,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,3,2,0,0,3,2,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,3,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,3,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + }; + + //draw and color Akemi + for (uint16_t y=0; y < height; y++) for (uint16_t x=0; x < width; x++) { + CRGB color = BLACK; + CRGB faceColor = color_wheel(counter); + CRGB armsAndLegsColor = SEGCOLOR(1) > 0 ? SEGCOLOR(1) : 0xFFE0A0; //default warmish white 0xABA8FF; //0xFF52e5;// + CRGB soundColor = ORANGE; + float lightFactor = 0.15; + float normalFactor = 0.4; + float base = 0.0; //fftResult[0]/255.0; + switch (akemi[(y * 32)/height][(x * 32)/width]) { + case 0: color = BLACK; break; + case 3: armsAndLegsColor.r *= lightFactor; armsAndLegsColor.g *= lightFactor; armsAndLegsColor.b *= lightFactor; color = armsAndLegsColor; break; //light arms and legs 0x9B9B9B + case 2: armsAndLegsColor.r *= normalFactor; armsAndLegsColor.g *= normalFactor; armsAndLegsColor.b *= normalFactor; color = armsAndLegsColor; break; //normal arms and legs 0x888888 + case 1: color = armsAndLegsColor; break; //dark arms and legs 0x686868 + case 6: faceColor.r *= lightFactor; faceColor.g *= lightFactor; faceColor.b *= lightFactor; color=faceColor; break; //light face 0x31AAFF + case 5: faceColor.r *= normalFactor; faceColor.g *= normalFactor; faceColor.b *= normalFactor; color=faceColor; break; //normal face 0x0094FF + case 4: color = faceColor; break; //dark face 0x007DC6 + case 7: color = SEGCOLOR(2) > 0 ? SEGCOLOR(2) : 0xFFFFFF; break; //eyes and mouth default white + case 8: if (base > 0.4) {soundColor.r *= base; soundColor.g *= base; soundColor.b *= base; color=soundColor;} else color = armsAndLegsColor; break; + default: color = BLACK; + } + + if (SEGMENT.intensity > 128 /*&& fftResult[0] > 128*/) { //dance if base is high + setPixelColorXY(x, 0, BLACK); + setPixelColorXY(x, y+1, color); + } else + setPixelColorXY(x, y, color); + } + + //add geq left and right + /* + for (uint16_t x=0; x < width/8; x++) { + uint16_t band = x * width/8; + uint16_t barHeight = map(fftResult[band], 0, 255, 0, 17*height/32); + CRGB color = color_from_palette((band * 35), false, PALETTE_SOLID_WRAP, 0); + + for (uint16_t y=0; y < barHeight; y++) { + setPixelColorXY(x, height/2-y, color); + setPixelColorXY(width-1-x, height/2-y, color); + } + } + */ + return FRAMETIME; +} // mode_2DAkemi \ No newline at end of file diff --git a/wled00/FX.h b/wled00/FX.h index 0c557ba4..f8e042d6 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -120,8 +120,6 @@ #define REVERSE (uint8_t)0x002 #define SELECTED (uint8_t)0x001 -#define MODE_COUNT 120 - #define FX_MODE_STATIC 0 #define FX_MODE_BLINK 1 #define FX_MODE_BREATH 2 @@ -240,8 +238,18 @@ #define FX_MODE_BLENDS 115 #define FX_MODE_TV_SIMULATOR 116 #define FX_MODE_DYNAMIC_SMOOTH 117 -#define FX_MODE_BLACK_HOLE_A 118 -#define FX_MODE_BLACK_HOLE_B 119 +#define FX_MODE_BLACK_HOLE 118 +#define FX_MODE_DNA 119 +#define FX_MODE_DNA_SPIRAL 120 +#define FX_MODE_DRIFT 121 +#define FX_MODE_FIRENOISE 122 +#define FX_MODE_FRIZZLES 123 +#define FX_MODE_HIPNOTIC 124 +#define FX_MODE_LISSAJOUS 125 +#define FX_MODE_MATRIX 126 +#define FX_MODE_AKEMI 127 + +#define MODE_COUNT 128 class WS2812FX { @@ -606,8 +614,16 @@ class WS2812FX { _mode[FX_MODE_BLENDS] = &WS2812FX::mode_blends; _mode[FX_MODE_TV_SIMULATOR] = &WS2812FX::mode_tv_simulator; _mode[FX_MODE_DYNAMIC_SMOOTH] = &WS2812FX::mode_dynamic_smooth; - _mode[FX_MODE_BLACK_HOLE_A] = &WS2812FX::mode_2DBlackHole_A; - _mode[FX_MODE_BLACK_HOLE_B] = &WS2812FX::mode_2DBlackHole_B; + _mode[FX_MODE_BLACK_HOLE] = &WS2812FX::mode_2DBlackHole; + _mode[FX_MODE_DNA] = &WS2812FX::mode_2Ddna; + _mode[FX_MODE_DNA_SPIRAL] = &WS2812FX::mode_2DDNASpiral; + _mode[FX_MODE_DRIFT] = &WS2812FX::mode_2DDrift; + _mode[FX_MODE_FIRENOISE] = &WS2812FX::mode_2Dfirenoise; + _mode[FX_MODE_FRIZZLES] = &WS2812FX::mode_2DFrizzles; + _mode[FX_MODE_HIPNOTIC] = &WS2812FX::mode_2DHiphotic; + _mode[FX_MODE_LISSAJOUS] = &WS2812FX::mode_2DLissajous; + _mode[FX_MODE_MATRIX] = &WS2812FX::mode_2Dmatrix; + _mode[FX_MODE_AKEMI] = &WS2812FX::mode_2DAkemi; _brightness = DEFAULT_BRIGHTNESS; currentPalette = CRGBPalette16(CRGB::Black); @@ -863,30 +879,37 @@ class WS2812FX { void setUpMatrix(), setPixelColorXY(uint16_t x, uint16_t y, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0), - fill2D(uint32_t), - blur1d(fract8 blur_amount, CRGB* leds=nullptr), - blur2d(fract8 blur_amount, CRGB* leds=nullptr), - blurRows(fract8 blur_amount, CRGB* leds=nullptr), - blurColumns(fract8 blur_amount, CRGB* leds=nullptr), - fill_solid(const struct CRGB& color, CRGB* leds=nullptr), - fade_out2D(uint8_t r), - fadeToBlackBy(uint8_t fadeBy, CRGB* leds=nullptr), - nscale8(uint8_t scale, CRGB* leds=nullptr), + blur1d(CRGB* leds, fract8 blur_amount), + blur2d(CRGB* leds, fract8 blur_amount), + blurRow(uint16_t row, fract8 blur_amount, CRGB* leds=nullptr), + blurCol(uint16_t col, fract8 blur_amount, CRGB* leds=nullptr), + fill_solid(CRGB* leds, const struct CRGB& color), + fadeToBlackBy(CRGB* leds, uint8_t fadeBy), + nscale8(CRGB* leds, uint8_t scale), setPixels(CRGB* leds); inline void setPixelColorXY(uint16_t x, uint16_t y, uint32_t c) { setPixelColorXY(x, y, byte(c>>16), byte(c>>8), byte(c), byte(c>>24)); } inline void setPixelColorXY(uint16_t x, uint16_t y, CRGB &c) { setPixelColorXY(x, y, c.red, c.green, c.blue); } uint16_t - XY(uint16_t x, uint16_t y, uint8_t seg=255); + XY(uint16_t, uint16_t), + getPixelIndex(uint16_t x, uint16_t y, uint8_t seg=255); uint32_t getPixelColorXY(uint16_t, uint16_t); // 2D modes uint16_t - mode_2DBlackHole_A(), - mode_2DBlackHole_B(); + mode_2DBlackHole(void), + mode_2Ddna(void), + mode_2DDNASpiral(void), + mode_2DDrift(void), + mode_2Dfirenoise(void), + mode_2DFrizzles(void), + mode_2DHiphotic(void), + mode_2DLissajous(void), + mode_2Dmatrix(void), + mode_2DAkemi(void); // end 2D support @@ -922,6 +945,7 @@ class WS2812FX { color_wipe(bool, bool), dynamic(bool), scan(bool), + fireworks_base(CRGB*), running_base(bool,bool), larson_scanner(bool), sinelon_base(bool,bool), diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 7c9041d9..8865a3c8 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -106,13 +106,20 @@ void WS2812FX::setUpMatrix() { } } -// XY(x,y,seg) - returns an index of segment pixel in a matrix layout +// XY(x,y) - gets pixel index within current segment +uint16_t IRAM_ATTR WS2812FX::XY(uint16_t x, uint16_t y) { + uint16_t width = SEGMENT.virtualWidth(); // segment width in logical pixels + if (SEGMENT.getOption(SEG_OPTION_TRANSPOSED)) { uint16_t t = x; x = y; y = t; } // swap X & Y if segment transposed + return x + y * width; +} + +// getPixelIndex(x,y,seg) - returns an index of segment pixel in a matrix layout // index still needs to undergo ledmap processing to represent actual physical pixel // matrix is always organized by matrixHeight number of matrixWidth pixels from top to bottom, left to right -// so: pixel at XY(5,6) in a 2D segment with [start=10, stop=19, startY=20, stopY=29 : 10x10 pixels] +// so: pixel at getPixelIndex(5,6) in a 2D segment with [start=10, stop=19, startY=20, stopY=29 : 10x10 pixels] // corresponds to pixel with logical index of 847 (0 based) if a 2D segment belongs to a 32x32 matrix. // math: (matrixWidth * (startY + y)) + start + x => (32 * (20+6)) + 10 + 5 = 847 -uint16_t IRAM_ATTR WS2812FX::XY(uint16_t x, uint16_t y, uint8_t seg) { +uint16_t IRAM_ATTR WS2812FX::getPixelIndex(uint16_t x, uint16_t y, uint8_t seg) { if (seg == 255) seg = _segment_index; x %= _segments[seg].width(); // just in case constrain x (wrap around) y %= _segments[seg].height(); // just in case constrain y (wrap around) @@ -122,8 +129,8 @@ uint16_t IRAM_ATTR WS2812FX::XY(uint16_t x, uint16_t y, uint8_t seg) { void IRAM_ATTR WS2812FX::setPixelColorXY(uint16_t x, uint16_t y, byte r, byte g, byte b, byte w) { if (!isMatrix) return; // not a matrix set-up - uint8_t segIdx = SEGLEN ? _segment_index : _mainSegment; - if (SEGLEN && _bri_t < 255) { + + if (_bri_t < 255) { r = scale8(r, _bri_t); g = scale8(g, _bri_t); b = scale8(b, _bri_t); @@ -131,33 +138,33 @@ void IRAM_ATTR WS2812FX::setPixelColorXY(uint16_t x, uint16_t y, byte r, byte g, } uint32_t col = RGBW32(r, g, b, w); - uint16_t width = _segments[segIdx].virtualWidth(); // segment width in logical pixels (includes grouping, spacing, mirror & transposed) - uint16_t height = _segments[segIdx].virtualHeight(); // segment height in logical pixels (includes grouping, spacing, mirror & transposed) - if (_segments[segIdx].getOption(SEG_OPTION_TRANSPOSED)) { uint16_t t = x; x = y; y = t; } // swap X & Y if segment transposed + uint16_t width = SEGMENT.virtualWidth(); // segment width in logical pixels (includes grouping, spacing, mirror & transposed) + uint16_t height = SEGMENT.virtualHeight(); // segment height in logical pixels (includes grouping, spacing, mirror & transposed) + if (SEGMENT.getOption(SEG_OPTION_TRANSPOSED)) { uint16_t t = x; x = y; y = t; } // swap X & Y if segment transposed - x *= _segments[segIdx].groupLength(); - y *= _segments[segIdx].groupLength(); + x *= SEGMENT.groupLength(); + y *= SEGMENT.groupLength(); if (x >= width || y >= height) return; // if pixel would fall out of segment just exit - for (uint8_t j = 0; j < _segments[segIdx].grouping; j++) { // groupping vertically - for (uint8_t g = 0; g < _segments[segIdx].grouping; g++) { // groupping horizontally + for (uint8_t j = 0; j < SEGMENT.grouping; j++) { // groupping vertically + for (uint8_t g = 0; g < SEGMENT.grouping; g++) { // groupping horizontally uint16_t index, xX = (x+g), yY = (y+j); - if (xX >= width || yY >= height) continue; // we have reached one dimension's end + if (xX >= SEGMENT.width() || yY >= SEGMENT.height()) continue; // we have reached one dimension's end - if (_segments[segIdx].getOption(SEG_OPTION_REVERSED) ) xX = width - xX - 1; - if (_segments[segIdx].getOption(SEG_OPTION_REVERSED_Y)) yY = height - yY - 1; + if (SEGMENT.getOption(SEG_OPTION_REVERSED) ) xX = width - xX - 1; + if (SEGMENT.getOption(SEG_OPTION_REVERSED_Y)) yY = height - yY - 1; - index = XY(xX, yY, segIdx); + index = getPixelIndex(xX, yY); if (index < customMappingSize) index = customMappingTable[index]; busses.setPixelColor(index, col); - if (_segments[segIdx].getOption(SEG_OPTION_MIRROR)) { //set the corresponding horizontally mirrored pixel - index = XY(_segments[segIdx].width() - xX - 1, yY, segIdx); + if (SEGMENT.getOption(SEG_OPTION_MIRROR)) { //set the corresponding horizontally mirrored pixel + index = getPixelIndex(SEGMENT.width() - xX - 1, yY); if (index < customMappingSize) index = customMappingTable[index]; busses.setPixelColor(index, col); } - if (_segments[segIdx].getOption(SEG_OPTION_MIRROR_Y)) { //set the corresponding vertically mirrored pixel - index = XY(xX, _segments[segIdx].height() - yY - 1, segIdx); + if (SEGMENT.getOption(SEG_OPTION_MIRROR_Y)) { //set the corresponding vertically mirrored pixel + index = getPixelIndex(xX, SEGMENT.height() - yY - 1); if (index < customMappingSize) index = customMappingTable[index]; busses.setPixelColor(index, col); } @@ -168,72 +175,68 @@ void IRAM_ATTR WS2812FX::setPixelColorXY(uint16_t x, uint16_t y, byte r, byte g, uint32_t WS2812FX::getPixelColorXY(uint16_t x, uint16_t y) { - uint8_t segIdx = _segment_index; - uint16_t width = _segments[segIdx].virtualWidth(); // segment width in logical pixels - uint16_t height = _segments[segIdx].virtualHeight(); // segment height in logical pixels - if (_segments[segIdx].getOption(SEG_OPTION_TRANSPOSED)) { uint16_t t = x; x = y; y = t; } // swap X & Y if segment transposed + uint16_t width = SEGMENT.virtualWidth(); // segment width in logical pixels + uint16_t height = SEGMENT.virtualHeight(); // segment height in logical pixels + if (SEGMENT.getOption(SEG_OPTION_TRANSPOSED)) { uint16_t t = x; x = y; y = t; } // swap X & Y if segment transposed - x *= _segments[segIdx].groupLength(); - y *= _segments[segIdx].groupLength(); - if (x >= width || y >= height) return 0; + x *= SEGMENT.groupLength(); + y *= SEGMENT.groupLength(); + if (x >= SEGMENT.width() || y >= SEGMENT.height()) return 0; - if (_segments[segIdx].getOption(SEG_OPTION_REVERSED) ) x = width - x - 1; - if (_segments[segIdx].getOption(SEG_OPTION_REVERSED_Y)) y = height - y - 1; + if (SEGMENT.getOption(SEG_OPTION_REVERSED) ) x = width - x - 1; + if (SEGMENT.getOption(SEG_OPTION_REVERSED_Y)) y = height - y - 1; - uint16_t index = XY(x, y, segIdx); + uint16_t index = getPixelIndex(x, y); if (index < customMappingSize) index = customMappingTable[index]; return busses.getPixelColor(index); } + // blurRows: perform a blur1d on every row of a rectangular matrix -void WS2812FX::blurRows(fract8 blur_amount, CRGB* leds) +void WS2812FX::blurRow(uint16_t y, fract8 blur_amount, CRGB* leds) { uint16_t width = SEGMENT.virtualWidth(); - uint16_t height = SEGMENT.virtualHeight(); uint8_t keep = 255 - blur_amount; uint8_t seep = blur_amount >> 1; CRGB carryover = CRGB::Black; - for (uint16_t y = 0; y < height; y++) for (uint16_t x = 0; x < width; x++) { - CRGB cur = leds ? leds[x + y * width] : col_to_crgb(getPixelColorXY(x,y)); - CRGB part = cur; - part.nscale8(seep); - cur.nscale8(keep); - cur += carryover; - if (x) { - if (leds) leds[(x-1) + y * width] += part; - else setPixelColorXY(x-1, y, col_to_crgb(getPixelColorXY(x-1, y)) + part); - } - if (leds) leds[x + y * width] = cur; - else setPixelColorXY(x, y, cur); - carryover = part; + for (uint16_t x = 0; x < width; x++) { + CRGB cur = leds ? leds[XY(x,y)] : col_to_crgb(getPixelColorXY(x,y)); + CRGB part = cur; + part.nscale8(seep); + cur.nscale8(keep); + cur += carryover; + if (x) { + if (leds) leds[XY((x-1),y)] += part; + else setPixelColorXY(x-1, y, col_to_crgb(getPixelColorXY(x-1, y)) + part); } + if (leds) leds[XY(x,y)] = cur; + else setPixelColorXY(x, y, cur); + carryover = part; + } } // blurColumns: perform a blur1d on each column of a rectangular matrix -void WS2812FX::blurColumns(fract8 blur_amount, CRGB* leds) +void WS2812FX::blurCol(uint16_t x, fract8 blur_amount, CRGB* leds) { - uint16_t width = SEGMENT.virtualWidth(); uint16_t height = SEGMENT.virtualHeight(); // blur columns uint8_t keep = 255 - blur_amount; uint8_t seep = blur_amount >> 1; - for ( uint16_t x = 0; x < width; x++) { - CRGB carryover = CRGB::Black; - for ( uint16_t y = 0; y < height; y++) { - CRGB cur = leds ? leds[x + y * width] : col_to_crgb(getPixelColorXY(x,y)); - CRGB part = cur; - part.nscale8(seep); - cur.nscale8(keep); - cur += carryover; - if (y) { - if (leds) leds[x + (y-1) * width] += part; - else setPixelColorXY(x, y-1, col_to_crgb(getPixelColorXY(x,y-1)) + part); - } - if (leds) leds[x + y * width] = cur; - else setPixelColorXY(x, y, cur); - carryover = part; + CRGB carryover = CRGB::Black; + for ( uint16_t y = 0; y < height; y++) { + CRGB cur = leds ? leds[XY(x,y)] : col_to_crgb(getPixelColorXY(x,y)); + CRGB part = cur; + part.nscale8(seep); + cur.nscale8(keep); + cur += carryover; + if (y) { + if (leds) leds[XY(x,(y-1))] += part; + else setPixelColorXY(x, y-1, col_to_crgb(getPixelColorXY(x,y-1)) + part); } + if (leds) leds[XY(x,y)] = cur; + else setPixelColorXY(x, y, cur); + carryover = part; } } @@ -251,86 +254,66 @@ void WS2812FX::blurColumns(fract8 blur_amount, CRGB* leds) // eventually all the way to black; this is by design so that // it can be used to (slowly) clear the LEDs to black. -void WS2812FX::blur1d(fract8 blur_amount, CRGB* leds) +void WS2812FX::blur1d(CRGB* leds, fract8 blur_amount) { - blurRows(blur_amount, leds); + uint16_t height = SEGMENT.virtualHeight(); + for ( uint16_t y = 0; y < height; y++) + blurRow(y, blur_amount, leds); } -void WS2812FX::blur2d(fract8 blur_amount, CRGB* leds) +void WS2812FX::blur2d(CRGB* leds, fract8 blur_amount) { - blurRows(blur_amount, leds); - blurColumns(blur_amount, leds); + uint16_t w = SEGMENT.virtualWidth(); // same as SEGLEN + uint16_t h = SEGMENT.virtualHeight(); + uint8_t keep = 255 - blur_amount; + uint8_t seep = blur_amount >> 1; + for (uint16_t k = 0; k < h; k++) { + CRGB carryover = CRGB::Black; + for(uint16_t i = 0; i < w; i++) { + CRGB cur = leds ? leds[XY(i,k)] : col_to_crgb(getPixelColorXY(i, k)); + CRGB part = cur; + part.nscale8(seep); + cur.nscale8(keep); + cur += carryover; + if (i > 0) { + CRGB c = leds ? leds[XY(i,k)] : col_to_crgb(getPixelColorXY(i-1, k)); + c += part; + if (leds) leds[XY(i-1,k)] = c; + else setPixelColorXY(i-1, k, c.red, c.green, c.blue); + } + // seep from previous row + if (k > 0) { + CRGB c = col_to_crgb(getPixelColorXY(i, k-1)); + c.nscale8(seep); + cur += c; + } + if (leds) leds[XY(i,k)] = cur; + else setPixelColorXY(i, k, cur.red, cur.green, cur.blue); + carryover = part; + } + } } //ewowi20210628: new functions moved from colorutils: add segment awareness -/* - * Fills segment with color - */ -void WS2812FX::fill2D(uint32_t c) { +void WS2812FX::fill_solid(CRGB* leds, const struct CRGB& color) { uint16_t w = SEGMENT.virtualWidth(); uint16_t h = SEGMENT.virtualHeight(); for(uint16_t y = 0; y < h; y++) for (uint16_t x = 0; x < w; x++) { - setPixelColorXY(x, y, c); - } -} - -void WS2812FX::fill_solid(const struct CRGB& color, CRGB* leds) { - uint16_t w = SEGMENT.virtualWidth(); - uint16_t h = SEGMENT.virtualHeight(); - for(uint16_t y = 0; y < h; y++) for (uint16_t x = 0; x < w; x++) { - if (leds) leds[x + y * w] = color; + if (leds) leds[XY(x,y)] = color; else setPixelColorXY(x, y, color); } } -/* - * fade out function, higher rate = quicker fade - * TODO: may be better to use approach of nscale8() - */ -void WS2812FX::fade_out2D(uint8_t rate) { - uint16_t w = SEGMENT.virtualWidth(); - uint16_t h = SEGMENT.virtualHeight(); - rate = (255-rate) >> 1; - float mappedRate = float(rate) +1.1; - - uint32_t color = SEGCOLOR(1); // target color - int w2 = W(color); - int r2 = R(color); - int g2 = G(color); - int b2 = B(color); - - for(uint16_t y = 0; y < h; y++) for (uint16_t x = 0; x < w; x++) { - color = getPixelColorXY(x, y); - int w1 = W(color); - int r1 = R(color); - int g1 = G(color); - int b1 = B(color); - - int wdelta = (w2 - w1) / mappedRate; - int rdelta = (r2 - r1) / mappedRate; - int gdelta = (g2 - g1) / mappedRate; - int bdelta = (b2 - b1) / mappedRate; - - // if fade isn't complete, make sure delta is at least 1 (fixes rounding issues) - wdelta += (w2 == w1) ? 0 : (w2 > w1) ? 1 : -1; - rdelta += (r2 == r1) ? 0 : (r2 > r1) ? 1 : -1; - gdelta += (g2 == g1) ? 0 : (g2 > g1) ? 1 : -1; - bdelta += (b2 == b1) ? 0 : (b2 > b1) ? 1 : -1; - - setPixelColorXY(x, y, r1 + rdelta, g1 + gdelta, b1 + bdelta, w1 + wdelta); - } +void WS2812FX::fadeToBlackBy(CRGB* leds, uint8_t fadeBy) { + nscale8(leds, 255 - fadeBy); } -void WS2812FX::fadeToBlackBy(uint8_t fadeBy, CRGB* leds) { - nscale8(255 - fadeBy, leds); -} - -void WS2812FX::nscale8(uint8_t scale, CRGB* leds) { +void WS2812FX::nscale8(CRGB* leds, uint8_t scale) { uint16_t w = SEGMENT.virtualWidth(); uint16_t h = SEGMENT.virtualHeight(); for(uint16_t y = 0; y < h; y++) for (uint16_t x = 0; x < w; x++) { - if (leds) leds[x + y * w].nscale8(scale); + if (leds) leds[XY(x,y)].nscale8(scale); else setPixelColorXY(x, y, col_to_crgb(getPixelColorXY(x, y)).nscale8(scale)); } } @@ -338,5 +321,5 @@ void WS2812FX::nscale8(uint8_t scale, CRGB* leds) { void WS2812FX::setPixels(CRGB* leds) { uint16_t w = SEGMENT.virtualWidth(); uint16_t h = SEGMENT.virtualHeight(); - for (uint16_t y = 0; y < h; y++) for (uint16_t x = 0; x < w; x++) setPixelColorXY(x, y, leds[x + y*w]); + for (uint16_t y = 0; y < h; y++) for (uint16_t x = 0; x < w; x++) setPixelColorXY(x, y, leds[XY(x,y)]); } diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 2c58edba..ec4470ae 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -185,12 +185,11 @@ void WS2812FX::service() { void IRAM_ATTR WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w) { uint8_t segIdx = SEGLEN ? _segment_index : _mainSegment; - if (isMatrix) { + if (isMatrix && SEGLEN) { // map linear pixel into 2D segment area (even for 1D segments, expanding vertically) - uint16_t h = _segments[segIdx].height(); // segment height in logical pixels - uint8_t l = _segments[segIdx].groupLength(); - for (uint16_t y = 0; y < h; y += l) { // expand 1D effect vertically - setPixelColorXY(i, y, r, g, b, w); + uint16_t h = _segments[segIdx].virtualHeight(); // segment height in logical pixels + for (uint16_t y = 0; y < h; y++) { // expand 1D effect vertically + setPixelColorXY(i, y * _segments[segIdx].groupLength(), r, g, b, w); } return; } @@ -711,9 +710,9 @@ void WS2812FX::resetSegments() { _segments[0].setOption(SEG_OPTION_ON, 1); _segments[0].opacity = 255; _segments[0].cct = 127; - _segments[0].c1x = 0; - _segments[0].c2x = 0; - _segments[0].c3x = 0; + _segments[0].c1x = DEFAULT_C1; + _segments[0].c2x = DEFAULT_C2; + _segments[0].c3x = DEFAULT_C3; for (uint16_t i = 1; i < MAX_NUM_SEGMENTS; i++) { @@ -724,9 +723,9 @@ void WS2812FX::resetSegments() { _segments[i].cct = 127; _segments[i].speed = DEFAULT_SPEED; _segments[i].intensity = DEFAULT_INTENSITY; - _segments[i].c1x = 0; - _segments[i].c2x = 0; - _segments[i].c3x = 0; + _segments[i].c1x = DEFAULT_C1; + _segments[i].c2x = DEFAULT_C2; + _segments[i].c3x = DEFAULT_C3; _segment_runtimes[i].markForReset(); } _segment_runtimes[0].markForReset(); @@ -891,8 +890,11 @@ uint32_t IRAM_ATTR WS2812FX::color_blend(uint32_t color1, uint32_t color2, uint1 * Fills segment with color */ void WS2812FX::fill(uint32_t c) { - for(uint16_t i = 0; i < SEGLEN; i++) { - setPixelColor(i, c); + uint16_t w = SEGMENT.virtualWidth(); // same as SEGLEN + uint16_t h = SEGMENT.virtualHeight(); + for(uint16_t y = 0; y < h; y++) for (uint16_t x = 0; x < w; x++) { + if (isMatrix) setPixelColorXY(x, y, c); + else setPixelColor(x, c); } } @@ -908,6 +910,8 @@ void WS2812FX::blendPixelColor(uint16_t n, uint32_t color, uint8_t blend) * fade out function, higher rate = quicker fade */ void WS2812FX::fade_out(uint8_t rate) { + uint16_t w = SEGMENT.virtualWidth(); // same as SEGLEN + uint16_t h = SEGMENT.virtualHeight(); rate = (255-rate) >> 1; float mappedRate = float(rate) +1.1; @@ -917,8 +921,8 @@ void WS2812FX::fade_out(uint8_t rate) { int g2 = G(color); int b2 = B(color); - for(uint16_t i = 0; i < SEGLEN; i++) { - color = getPixelColor(i); + for(uint16_t y = 0; y < h; y++) for (uint16_t x = 0; x < w; x++) { + color = isMatrix ? getPixelColorXY(x, y) : getPixelColor(x); int w1 = W(color); int r1 = R(color); int g1 = G(color); @@ -935,7 +939,8 @@ void WS2812FX::fade_out(uint8_t rate) { gdelta += (g2 == g1) ? 0 : (g2 > g1) ? 1 : -1; bdelta += (b2 == b1) ? 0 : (b2 > b1) ? 1 : -1; - setPixelColor(i, r1 + rdelta, g1 + gdelta, b1 + bdelta, w1 + wdelta); + if (isMatrix) setPixelColorXY(x, y, r1 + rdelta, g1 + gdelta, b1 + bdelta, w1 + wdelta); + else setPixelColor(x, r1 + rdelta, g1 + gdelta, b1 + bdelta, w1 + wdelta); } } @@ -1427,8 +1432,16 @@ const char JSON_mode_names[] PROGMEM = R"=====([ "Blends@Shift speed,Blend speed;1,2,3,!", "TV Simulator", "Dynamic Smooth", -"2D Black Hole A@!,!,C1,C2,C3;!;!", -"2D Black Hole B@!,!,C1,C2,C3;!;!" +"2D Black Hole@!,!,Inner X,Outer X,Outer Y;!,!,!;!", +"2D DNA", +"2D DNA Spiral", +"2D Drift", +"2D Firenoise", +"2D Frizzles", +"2D Hipnotic", +"2D Lissajous", +"2D Matrix@!,!,Fade,Matrix?;!,!,!;!", +"2D Akemi@!,!;!,!;!" ])====="; const char JSON_palette_names[] PROGMEM = R"=====([