From 6cd0da821ab743fa1ac0d90b4c8243da476b954b Mon Sep 17 00:00:00 2001 From: Blaz Kristan Date: Thu, 28 Dec 2023 23:32:47 +0100 Subject: [PATCH] Reduce heap fragmentation when switching ledmaps --- wled00/FX.h | 10 +++++----- wled00/FX_2Dfcn.cpp | 21 +++++++++----------- wled00/FX_fcn.cpp | 48 ++++++++++++++++----------------------------- wled00/overlay.cpp | 8 ++++---- wled00/wled.cpp | 2 +- 5 files changed, 36 insertions(+), 53 deletions(-) diff --git a/wled00/FX.h b/wled00/FX.h index c60805968..3e1c7b238 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -760,7 +760,7 @@ class WS2812FX { // 96 bytes resetSegments(), makeAutoSegments(bool forceReset = false), fixInvalidSegments(), - setPixelColor(int n, uint32_t c), + setPixelColor(unsigned n, uint32_t c), show(void), setTargetFps(uint8_t fps), addEffect(uint8_t id, mode_ptr mode_fn, const char *mode_name), // add effect to the list; defined in FX.cpp @@ -769,10 +769,10 @@ class WS2812FX { // 96 bytes inline void restartRuntime() { for (Segment &seg : _segments) seg.markForReset(); } inline void setTransitionMode(bool t) { for (Segment &seg : _segments) seg.startTransition(t ? _transitionDur : 0); } inline void setColor(uint8_t slot, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0) { setColor(slot, RGBW32(r,g,b,w)); } - inline void fill(uint32_t c) { for (int i = 0; i < getLengthTotal(); i++) setPixelColor(i, c); } // fill whole strip with color (inline) + inline void fill(uint32_t c) { for (unsigned i = 0; i < getLengthTotal(); i++) setPixelColor(i, c); } // fill whole strip with color (inline) // outsmart the compiler :) by correctly overloading - inline void setPixelColor(int n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0) { setPixelColor(n, RGBW32(r,g,b,w)); } - inline void setPixelColor(int n, CRGB c) { setPixelColor(n, c.red, c.green, c.blue); } + inline void setPixelColor(unsigned n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0) { setPixelColor(n, RGBW32(r,g,b,w)); } + inline void setPixelColor(unsigned n, CRGB c) { setPixelColor(n, c.red, c.green, c.blue); } inline void trigger(void) { _triggered = true; } // Forces the next frame to be computed on all active segments. inline void setShowCallback(show_callback cb) { _callback = cb; } inline void setTransition(uint16_t t) { _transitionDur = t; } @@ -878,7 +878,7 @@ class WS2812FX { // 96 bytes void setUpMatrix(); // outsmart the compiler :) by correctly overloading - inline void setPixelColorXY(int x, int y, uint32_t c) { setPixelColor(y * Segment::maxWidth + x, c); } + inline void setPixelColorXY(int x, int y, uint32_t c) { setPixelColor((unsigned)(y * Segment::maxWidth + x), c); } inline void setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0) { setPixelColorXY(x, y, RGBW32(r,g,b,w)); } inline void setPixelColorXY(int x, int y, CRGB c) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0)); } diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index d2622f901..7a1453925 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -36,14 +36,9 @@ // so matrix should disable regular ledmap processing void WS2812FX::setUpMatrix() { #ifndef WLED_DISABLE_2D - // erase old ledmap, just in case. - if (customMappingTable != nullptr) delete[] customMappingTable; - customMappingTable = nullptr; - customMappingSize = 0; - // isMatrix is set in cfg.cpp or set.cpp if (isMatrix) { - // calculate width dynamically because it will have gaps + // calculate width dynamically because it may have gaps Segment::maxWidth = 1; Segment::maxHeight = 1; for (size_t i = 0; i < panel.size(); i++) { @@ -68,15 +63,17 @@ void WS2812FX::setUpMatrix() { return; } - customMappingTable = new uint16_t[Segment::maxWidth * Segment::maxHeight]; + customMappingSize = 0; // prevent use of mapping if anything goes wrong + + if (customMappingTable == nullptr) customMappingTable = new uint16_t[getLengthTotal()]; if (customMappingTable != nullptr) { - customMappingSize = Segment::maxWidth * Segment::maxHeight; + customMappingSize = getLengthTotal(); // fill with empty in case we don't fill the entire matrix - for (size_t i = 0; i< customMappingSize; i++) { - customMappingTable[i] = (uint16_t)-1; - } + unsigned matrixSize = Segment::maxWidth * Segment::maxHeight; + for (unsigned i = 0; i(); gapSize = map.size(); - if (!map.isNull() && gapSize >= customMappingSize) { // not an empty map + if (!map.isNull() && gapSize >= matrixSize) { // not an empty map gapTable = new int8_t[gapSize]; if (gapTable) for (size_t i = 0; i < gapSize; i++) { gapTable[i] = constrain(map[i], -1, 1); diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 501859f92..796392fac 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -753,10 +753,10 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col) uint32_t tmpCol = col; // set all the pixels in the group for (int j = 0; j < grouping; j++) { - uint16_t indexSet = i + ((reverse) ? -j : j); + unsigned indexSet = i + ((reverse) ? -j : j); if (indexSet >= start && indexSet < stop) { if (mirror) { //set the corresponding mirrored pixel - uint16_t indexMir = stop - indexSet + start - 1; + unsigned indexMir = stop - indexSet + start - 1; indexMir += offset; // offset/phase if (indexMir >= stop) indexMir -= len; // wrap #ifndef WLED_DISABLE_MODE_BLEND @@ -1123,17 +1123,14 @@ void WS2812FX::finalizeInit(void) { #endif } - if (isMatrix) setUpMatrix(); - else { - Segment::maxWidth = _length; - Segment::maxHeight = 1; - } + Segment::maxWidth = _length; + Segment::maxHeight = 1; //segments are created in makeAutoSegments(); DEBUG_PRINTLN(F("Loading custom palettes")); loadCustomPalettes(); // (re)load all custom palettes DEBUG_PRINTLN(F("Loading custom ledmaps")); - deserializeMap(); // (re)load default ledmap + deserializeMap(); // (re)load default ledmap (will also setUpMatrix() if ledmap does not exist) } void WS2812FX::service() { @@ -1212,7 +1209,7 @@ void WS2812FX::service() { #endif } -void IRAM_ATTR WS2812FX::setPixelColor(int i, uint32_t col) { +void IRAM_ATTR WS2812FX::setPixelColor(unsigned i, uint32_t col) { if (i < customMappingSize) i = customMappingTable[i]; if (i >= _length) return; busses.setPixelColor(i, col); @@ -1660,40 +1657,29 @@ bool WS2812FX::deserializeMap(uint8_t n) { strcat_P(fileName, PSTR(".json")); bool isFile = WLED_FS.exists(fileName); - if (!isFile) { - // erase custom mapping if selecting nonexistent ledmap.json (n==0) - if (!isMatrix && !n && customMappingTable != nullptr) { - customMappingSize = 0; - delete[] customMappingTable; - customMappingTable = nullptr; - } + customMappingSize = 0; // prevent use of mapping if anything goes wrong + + if (!isFile && n==0 && isMatrix) { + setUpMatrix(); return false; } - if (!requestJSONBufferLock(7)) return false; + if (!isFile || !requestJSONBufferLock(7)) return false; // this will trigger setUpMatrix() when called from wled.cpp if (!readObjectFromFile(fileName, nullptr, &doc)) { + DEBUG_PRINT(F("ERROR Invalid ledmap in ")); DEBUG_PRINTLN(fileName); releaseJSONBufferLock(); - return false; //if file does not exist just exit + return false; // if file does not load properly then exit } - DEBUG_PRINT(F("Reading LED map from ")); - DEBUG_PRINTLN(fileName); + DEBUG_PRINT(F("Reading LED map from ")); DEBUG_PRINTLN(fileName); - // erase old custom ledmap - if (customMappingTable != nullptr) { - customMappingSize = 0; - delete[] customMappingTable; - customMappingTable = nullptr; - } + if (customMappingTable == nullptr) customMappingTable = new uint16_t[getLengthTotal()]; JsonArray map = doc[F("map")]; if (!map.isNull() && map.size()) { // not an empty map - customMappingSize = map.size(); - customMappingTable = new uint16_t[customMappingSize]; - for (unsigned i=0; i overlayMax) hourPixel = overlayMin -1 + hourPixel - overlayMax; - int minutePixel = floorf(analogClock12pixel + overlaySize*minuteP); + unsigned minutePixel = floorf(analogClock12pixel + overlaySize*minuteP); if (minutePixel > overlayMax) minutePixel = overlayMin -1 + minutePixel - overlayMax; - int secondPixel = floorf(analogClock12pixel + overlaySize*secondP); + unsigned secondPixel = floorf(analogClock12pixel + overlaySize*secondP); if (secondPixel > overlayMax) secondPixel = overlayMin -1 + secondPixel - overlayMax; if (analogClockSecondsTrail) { @@ -36,7 +36,7 @@ void _overlayAnalogClock() { for (byte i = 0; i <= 12; i++) { - int pix = analogClock12pixel + roundf((overlaySize / 12.0f) *i); + unsigned pix = analogClock12pixel + roundf((overlaySize / 12.0f) *i); if (pix > overlayMax) pix -= overlaySize; strip.setPixelColor(pix, 0x00FFAA); } diff --git a/wled00/wled.cpp b/wled00/wled.cpp index ec623630f..7c2a93366 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -178,7 +178,7 @@ void WLED::loop() doSerializeConfig = true; } if (loadLedmap >= 0) { - if (!strip.deserializeMap(loadLedmap) && strip.isMatrix && loadLedmap == 0) strip.setUpMatrix(); + strip.deserializeMap(loadLedmap); loadLedmap = -1; } yield();