From 0cf891b9d9c4b3b103c2487ff954373bd8f5aa9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Kristan?= Date: Thu, 14 Jul 2022 13:22:34 +0200 Subject: [PATCH] Optimisations --- wled00/FX.h | 17 +++++------ wled00/FX_2Dfcn.cpp | 18 ------------ wled00/FX_fcn.cpp | 70 +++++++++++++++++++++++++++++++-------------- 3 files changed, 55 insertions(+), 50 deletions(-) diff --git a/wled00/FX.h b/wled00/FX.h index 12ad57cc7..198e9c978 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -361,6 +361,13 @@ uint32_t color_add(uint32_t,uint32_t); #define MODE_COUNT 185 #endif +typedef enum mapping1D2D { + M12_Pixels = 0, + M12_VerticalBar = 1, + M12_Circle = 2, + M12_Block = 3 +} mapping1D2D_t; + struct Segment; // color transitions @@ -501,13 +508,6 @@ typedef struct Segment { // 40 (44 in memory) bytes } segment; -typedef enum mapping1D2D { - M12_Pixels = 0, - M12_VerticalBar = 1, - M12_Circle = 2, - M12_Block = 3 -} mapping1D2D_t; - // main "strip" class class WS2812FX { // 96 bytes typedef uint16_t (*mode_ptr)(void); // pointer to mode function @@ -674,9 +674,6 @@ class WS2812FX { // 96 bytes inline void setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0) { setPixelColorXY(x, y, RGBW32(r,g,b,w)); } // automatically inline inline void setPixelColorXY(int x, int y, CRGB c) { setPixelColorXY(x, y, c.red, c.green, c.blue); } - uint16_t - getMappingLength(); - uint32_t getPixelColorXY(uint16_t, uint16_t); diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 9e8647337..bb6c07a92 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -238,24 +238,6 @@ void Segment::setPixelColorXY(float x, float y, uint32_t col, bool aa) #endif } -uint16_t IRAM_ATTR WS2812FX::getMappingLength() { - switch (SEGMENT.mapping12) { - case M12_Pixels: - return SEGMENT.virtualWidth() * SEGMENT.virtualHeight(); - break; - case M12_VerticalBar: - return SEGMENT.virtualWidth(); - break; - case M12_Circle: - return (SEGMENT.virtualWidth() + SEGMENT.virtualHeight()) / 4; // take half of the average width - break; - case M12_Block: - return (SEGMENT.virtualWidth() + SEGMENT.virtualHeight()) / 4; // take half of the average width - break; - } - return SEGMENT.virtualWidth() * SEGMENT.virtualHeight(); -} - // returns RGBW values of pixel uint32_t Segment::getPixelColorXY(uint16_t x, uint16_t y) { #ifndef WLED_DISABLE_2D diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 749b5e04e..fd60cdd59 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -166,6 +166,21 @@ uint16_t Segment::virtualHeight() { // 1D strip uint16_t Segment::virtualLength() { +#ifndef WLED_DISABLE_2D + if (height() > 1) { + uint16_t vW = virtualWidth(); + uint16_t vH = virtualHeight(); + uint32_t vLen = vW * vH; // use all pixels from segment + switch (mapping12) { + case M12_VerticalBar: vLen = vW; + break; + case M12_Circle: + case M12_Block: vLen = (vW + vH) / 4; // take half of the average width + break; + } + return vLen; + } +#endif uint16_t groupLen = groupLength(); uint16_t vLength = (length() + groupLen - 1) / groupLen; if (getOption(SEG_OPTION_MIRROR)) vLength = (vLength + 1) /2; // divide by 2 if mirror, leave at least a single LED @@ -174,38 +189,45 @@ uint16_t Segment::virtualLength() { void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col) { - if (strip.isMatrix) { - uint16_t h = virtualHeight(); // segment height in logical pixels - switch (SEGMENT.mapping12) { +#ifndef WLED_DISABLE_2D + if (height() > 1) { // if this does not work use strip.isMatrix + uint16_t vH = virtualHeight(); // segment height in logical pixels + uint16_t vW = virtualWidth(); + switch (mapping12) { case M12_Pixels: - setPixelColorXY(i%SEGMENT.virtualWidth(), i/SEGMENT.virtualWidth(), col); + // use all available pixels as a long strip + setPixelColorXY(i % vW, i / vW, col); break; case M12_VerticalBar: - // map linear pixel into 2D segment area (even for 1D segments, expanding vertically) - for (int y = 0; y < h; y++) { // expand 1D effect vertically + // expand 1D effect vertically + for (int y = 0; y < vH; y++) { setPixelColorXY(i, y * groupLength(), col); } break; case M12_Circle: - for (int degrees = 0; degrees <= 360; degrees += 180 / (i+1)) { - int x = roundf(roundf((sinf(degrees*DEG_TO_RAD) * i + SEGMENT.virtualWidth() / 2) * 10)/10); - int y = roundf(roundf((cosf(degrees*DEG_TO_RAD) * i + SEGMENT.virtualHeight() / 2) * 10)/10); + // expand in circular fashion from center + for (int degrees = 0; degrees <= 360; degrees += 180 / (i+1)) { // this may prove too many iterations on larger matrices + // may want to try float version as well (with or without antialiasing) + unsigned int x = roundf(roundf((sin_t(degrees*DEG_TO_RAD) * i + vW / 2.0f) * 10)/10); // sin_t is Aircoookie's implementation that uses less RAM + unsigned int y = roundf(roundf((cos_t(degrees*DEG_TO_RAD) * i + vH / 2.0f) * 10)/10); // cos_t is Aircoookie's implementation that uses less RAM setPixelColorXY(x, y, col); } break; case M12_Block: - for (int x = SEGMENT.virtualWidth() / 2 - i - 1; x <= SEGMENT.virtualWidth() / 2 + i; x++) { - setPixelColorXY(x, SEGMENT.virtualHeight() / 2 - i - 1, col); - setPixelColorXY(x, SEGMENT.virtualHeight() / 2 + i , col); + // expand in rectangular fashion from center + for (int x = vW / 2 - i - 1; x <= vW / 2 + i; x++) { + setPixelColorXY(x, vH / 2 - i - 1, col); + setPixelColorXY(x, vH / 2 + i , col); } - for (int y = SEGMENT.virtualHeight() / 2 - i - 1 + 1; y <= SEGMENT.virtualHeight() / 2 + i - 1; y++) { - setPixelColorXY(SEGMENT.virtualWidth() / 2 - i - 1, y, col); - setPixelColorXY(SEGMENT.virtualWidth() / 2 + i , y, col); + for (int y = vH / 2 - i - 1 + 1; y <= vH / 2 + i - 1; y++) { + setPixelColorXY(vW / 2 - i - 1, y, col); + setPixelColorXY(vW / 2 + i , y, col); } break; } return; } +#endif uint16_t len = length(); uint8_t _bri_t = strip._bri_t; @@ -276,10 +298,13 @@ void Segment::setPixelColor(float i, uint32_t col, bool aa) uint32_t Segment::getPixelColor(uint16_t i) { - if (strip.isMatrix) { - switch (SEGMENT.mapping12) { +#ifndef WLED_DISABLE_2D + if (height() > 1) { // if this does not work use strip.isMatrix + uint16_t vH = virtualHeight(); // segment height in logical pixels + uint16_t vW = virtualWidth(); + switch (mapping12) { case M12_Pixels: - return getPixelColorXY(i%SEGMENT.virtualWidth(), i/SEGMENT.virtualWidth()); + return getPixelColorXY(i % vW, i / vW); break; case M12_VerticalBar: // map linear pixel into 2D segment area (even for 1D segments, expanding vertically) @@ -287,19 +312,20 @@ uint32_t Segment::getPixelColor(uint16_t i) break; case M12_Circle: { - int x = roundf(roundf((SEGMENT.virtualWidth() / 2) * 10)/10); - int y = roundf(roundf((i + SEGMENT.virtualHeight() / 2) * 10)/10); + int x = roundf(roundf((vW / 2) * 10)/10); + int y = roundf(roundf((i + vH / 2) * 10)/10); return getPixelColorXY(x,y); } break; case M12_Block: - return getPixelColorXY(SEGMENT.virtualWidth() / 2, SEGMENT.virtualHeight() / 2 - i - 1); + return getPixelColorXY(vW / 2, vH / 2 - i - 1); break; } return 0; } +#endif - if (getOption(SEG_OPTION_REVERSED)) i = strip.getMappingLength() - i - 1; + if (getOption(SEG_OPTION_REVERSED)) i = strip.virtualLength() - i - 1; i *= groupLength(); i += start; /* offset/phase */