diff --git a/wled00/FX.h b/wled00/FX.h index 19b1fc4ac..059bf820c 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -380,7 +380,6 @@ typedef struct Segment { uint16_t aux1; // custom var byte* data; // effect data pointer CRGB* leds; // local leds[] array (may be a pointer to global) - static CRGB *_globalLeds; // global leds[] array static uint16_t maxWidth, maxHeight; // these define matrix width & height (max. segment dimensions) private: @@ -487,7 +486,7 @@ typedef struct Segment { //if (leds) Serial.printf(" [%u]", length()*sizeof(CRGB)); //Serial.println(); //#endif - if (!Segment::_globalLeds && leds) free(leds); + if (leds) free(leds); if (name) delete[] name; if (_t) delete _t; deallocateData(); @@ -497,7 +496,7 @@ typedef struct Segment { Segment& operator= (Segment &&orig) noexcept; // move assignment #ifdef WLED_DEBUG - size_t getSize() const { return sizeof(Segment) + (data?_dataLen:0) + (name?strlen(name):0) + (_t?sizeof(Transition):0) + (!Segment::_globalLeds && leds?sizeof(CRGB)*length():0); } + size_t getSize() const { return sizeof(Segment) + (data?_dataLen:0) + (name?strlen(name):0) + (_t?sizeof(Transition):0) + (leds?sizeof(CRGB)*length():0); } #endif inline bool getOption(uint8_t n) const { return ((options >> n) & 0x01); } @@ -710,7 +709,7 @@ class WS2812FX { // 96 bytes panel.clear(); #endif customPalettes.clear(); - if (useLedsArray && Segment::_globalLeds) free(Segment::_globalLeds); + if (_globalLedBuffer) free(_globalLedBuffer); } static WS2812FX* getInstance(void) { return instance; } @@ -758,7 +757,7 @@ class WS2812FX { // 96 bytes // return true if the strip is being sent pixel updates isUpdating(void), deserializeMap(uint8_t n=0), - useLedsArray = false; + useGlobalLedBuffer = false; inline bool isServicing(void) { return _isServicing; } inline bool hasWhiteChannel(void) {return _hasWhiteChannel;} @@ -905,6 +904,8 @@ class WS2812FX { // 96 bytes uint8_t _segment_index; uint8_t _mainSegment; + static uint32_t *_globalLedBuffer; // global leds[] array + void estimateCurrentAndLimitBri(void); }; diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 50d3f2f40..181819e60 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -74,7 +74,6 @@ // Segment class implementation /////////////////////////////////////////////////////////////////////////////// uint16_t Segment::_usedSegmentData = 0U; // amount of RAM all segments use for their data[] -CRGB *Segment::_globalLeds = nullptr; uint16_t Segment::maxWidth = DEFAULT_LED_COUNT; uint16_t Segment::maxHeight = 1; @@ -86,11 +85,11 @@ Segment::Segment(const Segment &orig) { data = nullptr; _dataLen = 0; _t = nullptr; - if (leds && !Segment::_globalLeds) leds = nullptr; + leds = nullptr; if (orig.name) { name = new char[strlen(orig.name)+1]; if (name) strcpy(name, orig.name); } if (orig.data) { if (allocateData(orig._dataLen)) memcpy(data, orig.data, orig._dataLen); } if (orig._t) { _t = new Transition(orig._t->_dur, orig._t->_briT, orig._t->_cctT, orig._t->_colorT); } - if (orig.leds && !Segment::_globalLeds) { leds = (CRGB*)malloc(sizeof(CRGB)*length()); if (leds) memcpy(leds, orig.leds, sizeof(CRGB)*length()); } + if (orig.leds) { leds = (CRGB*)malloc(sizeof(CRGB)*length()); if (leds) memcpy(leds, orig.leds, sizeof(CRGB)*length()); } } // move constructor @@ -111,7 +110,7 @@ Segment& Segment::operator= (const Segment &orig) { // clean destination if (name) delete[] name; if (_t) delete _t; - if (leds && !Segment::_globalLeds) free(leds); + if (leds) free(leds); deallocateData(); // copy source memcpy((void*)this, (void*)&orig, sizeof(Segment)); @@ -120,12 +119,12 @@ Segment& Segment::operator= (const Segment &orig) { data = nullptr; _dataLen = 0; _t = nullptr; - if (!Segment::_globalLeds) leds = nullptr; + leds = nullptr; // copy source data if (orig.name) { name = new char[strlen(orig.name)+1]; if (name) strcpy(name, orig.name); } if (orig.data) { if (allocateData(orig._dataLen)) memcpy(data, orig.data, orig._dataLen); } if (orig._t) { _t = new Transition(orig._t->_dur, orig._t->_briT, orig._t->_cctT, orig._t->_colorT); } - if (orig.leds && !Segment::_globalLeds) { leds = (CRGB*)malloc(sizeof(CRGB)*length()); if (leds) memcpy(leds, orig.leds, sizeof(CRGB)*length()); } + if (orig.leds) { leds = (CRGB*)malloc(sizeof(CRGB)*length()); if (leds) memcpy(leds, orig.leds, sizeof(CRGB)*length()); } } return *this; } @@ -137,7 +136,7 @@ Segment& Segment::operator= (Segment &&orig) noexcept { if (name) delete[] name; // free old name deallocateData(); // free old runtime data if (_t) delete _t; - if (leds && !Segment::_globalLeds) free(leds); + if (leds) free(leds); memcpy((void*)this, (void*)&orig, sizeof(Segment)); orig.name = nullptr; orig.data = nullptr; @@ -183,7 +182,7 @@ void Segment::deallocateData() { */ void Segment::resetIfRequired() { if (reset) { - if (leds && !Segment::_globalLeds) { free(leds); leds = nullptr; } + if (leds) { free(leds); leds = nullptr; } //if (transitional && _t) { transitional = false; delete _t; _t = nullptr; } deallocateData(); next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0; @@ -193,19 +192,16 @@ void Segment::resetIfRequired() { void Segment::setUpLeds() { // deallocation happens in resetIfRequired() as it is called when segment changes or in destructor - if (Segment::_globalLeds) - #ifndef WLED_DISABLE_2D - leds = &Segment::_globalLeds[start + startY*Segment::maxWidth]; - #else - leds = &Segment::_globalLeds[start]; - #endif - else if (leds == nullptr && length() > 0) { //softhack007 quickfix - avoid malloc(0) which is undefined behaviour (should not happen, but i've seen it) + if (WS2812FX::_globalLedBuffer) return; // TODO optional seg buffer for FX without lossy restore due to opacity + + // no global buffer + if (leds == nullptr && length() > 0) { //softhack007 quickfix - avoid malloc(0) which is undefined behaviour (should not happen, but i've seen it) //#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM) //if (psramFound()) // leds = (CRGB*)ps_malloc(sizeof(CRGB)*length()); // softhack007 disabled; putting leds into psram leads to horrible slowdown on WROVER boards //else //#endif - leds = (CRGB*)malloc(sizeof(CRGB)*length()); + leds = (CRGB*)malloc(sizeof(CRGB)*length()); } } @@ -1062,22 +1058,22 @@ void WS2812FX::finalizeInit(void) Segment::maxHeight = 1; } - //initialize leds array. TBD: realloc if nr of leds change - if (Segment::_globalLeds) { - purgeSegments(true); - free(Segment::_globalLeds); - Segment::_globalLeds = nullptr; + // initialize leds array + if (_globalLedBuffer) { + //purgeSegments(true); + free(_globalLedBuffer); + _globalLedBuffer = nullptr; } - if (useLedsArray) { - size_t arrSize = sizeof(CRGB) * getLengthTotal(); + if (useGlobalLedBuffer) { + size_t arrSize = sizeof(uint32_t) * getLengthTotal(); // softhack007 disabled; putting leds into psram leads to horrible slowdown on WROVER boards (see setUpLeds()) //#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM) //if (psramFound()) - // Segment::_globalLeds = (CRGB*) ps_malloc(arrSize); + // Segment::_globalLedBuffer = (CRGB*) ps_malloc(arrSize); //else //#endif - Segment::_globalLeds = (CRGB*) malloc(arrSize); - memset(Segment::_globalLeds, 0, arrSize); + _globalLedBuffer = (uint32_t*) malloc(arrSize); + memset(_globalLedBuffer, 0, arrSize); } //segments are created in makeAutoSegments(); @@ -1604,7 +1600,7 @@ void WS2812FX::printSize() { DEBUG_PRINTF("Data: %d*%d=%uB\n", sizeof(const char *), _modeData.size(), (_modeData.capacity()*sizeof(const char *))); DEBUG_PRINTF("Map: %d*%d=%uB\n", sizeof(uint16_t), (int)customMappingSize, customMappingSize*sizeof(uint16_t)); size = getLengthTotal(); - if (useLedsArray) DEBUG_PRINTF("Buffer: %d*%u=%uB\n", sizeof(CRGB), size, size*sizeof(CRGB)); + if (useGlobalLedBuffer) DEBUG_PRINTF("Buffer: %d*%u=%uB\n", sizeof(CRGB), size, size*sizeof(CRGB)); } #endif @@ -1707,6 +1703,7 @@ bool WS2812FX::deserializeMap(uint8_t n) { WS2812FX* WS2812FX::instance = nullptr; +uint32_t* WS2812FX::_globalLedBuffer = nullptr; const char JSON_mode_names[] PROGMEM = R"=====(["FX names moved"])====="; const char JSON_palette_names[] PROGMEM = R"=====([ diff --git a/wled00/cfg.cpp b/wled00/cfg.cpp index 15ef0e1f0..5b0fbd5fb 100644 --- a/wled00/cfg.cpp +++ b/wled00/cfg.cpp @@ -90,7 +90,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { CJSON(strip.cctBlending, hw_led[F("cb")]); Bus::setCCTBlend(strip.cctBlending); strip.setTargetFps(hw_led["fps"]); //NOP if 0, default 42 FPS - CJSON(strip.useLedsArray, hw_led[F("ld")]); + CJSON(strip.useGlobalLedBuffer, hw_led[F("ld")]); #ifndef WLED_DISABLE_2D // 2D Matrix Settings @@ -706,7 +706,7 @@ void serializeConfig() { hw_led[F("cb")] = strip.cctBlending; hw_led["fps"] = strip.getTargetFps(); hw_led[F("rgbwm")] = Bus::getGlobalAWMode(); // global auto white mode override - hw_led[F("ld")] = strip.useLedsArray; + hw_led[F("ld")] = strip.useGlobalLedBuffer; #ifndef WLED_DISABLE_2D // 2D Matrix Settings diff --git a/wled00/set.cpp b/wled00/set.cpp index 588ae0cd7..30d499d60 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -91,7 +91,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) Bus::setCCTBlend(strip.cctBlending); Bus::setGlobalAWMode(request->arg(F("AW")).toInt()); strip.setTargetFps(request->arg(F("FR")).toInt()); - strip.useLedsArray = request->hasArg(F("LD")); + strip.useGlobalLedBuffer = request->hasArg(F("LD")); bool busesChanged = false; for (uint8_t s = 0; s < WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES; s++) { diff --git a/wled00/xml.cpp b/wled00/xml.cpp index e9eb8dd0f..8057aac73 100644 --- a/wled00/xml.cpp +++ b/wled00/xml.cpp @@ -404,7 +404,7 @@ void getSettingsJS(byte subPage, char* dest) sappend('v',SET_F("CB"),strip.cctBlending); sappend('v',SET_F("FR"),strip.getTargetFps()); sappend('v',SET_F("AW"),Bus::getGlobalAWMode()); - sappend('c',SET_F("LD"),strip.useLedsArray); + sappend('c',SET_F("LD"),strip.useGlobalLedBuffer); for (uint8_t s=0; s < busses.getNumBusses(); s++) { Bus* bus = busses.getBus(s);