Decouple segment led buffer from global led buffer

This commit is contained in:
Christian Schwinne 2023-06-26 18:16:38 +02:00
parent ebd909dfe7
commit 498dd76730
5 changed files with 34 additions and 36 deletions

View File

@ -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);
};

View File

@ -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"=====([

View File

@ -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

View File

@ -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++) {

View File

@ -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);