diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 90a28554..206e626f 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -1209,7 +1209,13 @@ uint8_t WS2812FX::estimateCurrentAndLimitBri() { uint16_t len = bus->getLength(); uint32_t busPowerSum = 0; for (uint_fast16_t i = 0; i < len; i++) { //sum up the usage of each LED - uint32_t c = bus->getPixelColor(i); + uint32_t c = 0; + if (_globalLedBuffer) + { + c = _globalLedBuffer[bus->getStart() + i]; + } else { + c = bus->getPixelColor(i); + } byte r = R(c), g = G(c), b = B(c), w = W(c); if(useWackyWS2815PowerModel) { //ignore white component on WS2815 power calculation @@ -1253,6 +1259,7 @@ void WS2812FX::show(void) { show_callback callback = _callback; if (callback) callback(); + Bus::setRestoreBri(_renderBrightness); uint8_t busBrightness = estimateCurrentAndLimitBri(); if (_globalLedBuffer) { // copy data from buffer to bus @@ -1260,7 +1267,8 @@ void WS2812FX::show(void) { } else { // if brightness changed since last show, must set everything again to update to new luminance if (_renderBrightness != busBrightness) { - for (uint16_t i = 0; i < _length; i++) busses.setPixelColor(i, busses.getPixelColor(i)); // LOSSY and slow! + for (uint16_t i = 0; i < _length; i++) busses.setPixelColor(i, busses.getPixelColor(i)); // LOSSLESS due to trick (but still slow!) + Bus::setRestoreBri(busBrightness); } } @@ -1343,6 +1351,7 @@ void WS2812FX::setBrightness(uint8_t b, bool direct) { // would be dangerous if applied immediately (could exceed ABL), but will not output until the next show() busses.setBrightness(b); _renderBrightness = b; + Bus::setRestoreBri(b); } else { unsigned long t = millis(); if (_segments[0].next_time > t + 22 && t - _lastShow > MIN_SHOW_DELAY) show(); //apply brightness change immediately if no refresh soon diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 729393cb..4b75baad 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -563,3 +563,4 @@ uint16_t BusManager::getTotalLength() { int16_t Bus::_cct = -1; uint8_t Bus::_cctBlend = 0; uint8_t Bus::_gAWM = 255; +uint8_t Bus::_restaurationBri = 255; diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index fd5d8651..8740a9a2 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -154,6 +154,7 @@ class Bus { inline uint8_t getAutoWhiteMode() { return _autoWhiteMode; } inline static void setGlobalAWMode(uint8_t m) { if (m < 5) _gAWM = m; else _gAWM = AW_GLOBAL_DISABLED; } inline static uint8_t getGlobalAWMode() { return _gAWM; } + inline static void setRestoreBri(uint8_t b) { _restaurationBri = b; } bool reversed = false; @@ -168,6 +169,7 @@ class Bus { static uint8_t _gAWM; static int16_t _cct; static uint8_t _cctBlend; + static uint8_t _restaurationBri; // previous brightness used as setPixelColor was called. Used for lossy restoration uint32_t autoWhiteCalc(uint32_t c); }; @@ -231,7 +233,7 @@ class BusDigital : public Bus { for (uint8_t i=0; i<4; i++) { uint16_t val = chan[i]; - chan[i] = (val << 8) / (_bri + 1); + chan[i] = ((val << 8) + _restaurationBri) / (_restaurationBri + 1); //adding _bri slighly improves recovery / stops degradation on re-scale } return c; } diff --git a/wled00/cfg.cpp b/wled00/cfg.cpp index 5b0fbd5f..bc63f811 100644 --- a/wled00/cfg.cpp +++ b/wled00/cfg.cpp @@ -134,7 +134,8 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { if (fromFS || !ins.isNull()) { uint8_t s = 0; // bus iterator if (fromFS) busses.removeAll(); // can't safely manipulate busses directly in network callback - uint32_t mem = 0; + uint32_t mem = 0, globalBufMem = 0; + uint16_t maxlen = 0; bool busesChanged = false; for (JsonObject elm : ins) { if (s >= WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES) break; @@ -162,7 +163,11 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { if (fromFS) { BusConfig bc = BusConfig(ledType, pins, start, length, colorOrder, reversed, skipFirst, AWmode, freqkHz); mem += BusManager::memUsage(bc); - if (mem <= MAX_LED_MEMORY) if (busses.add(bc) == -1) break; // finalization will be done in WLED::beginStrip() + if (strip.useGlobalLedBuffer && start + length > maxlen) { + maxlen = start + length; + globalBufMem = maxlen * 4; + } + if (mem + globalBufMem <= MAX_LED_MEMORY) if (busses.add(bc) == -1) break; // finalization will be done in WLED::beginStrip() } else { if (busConfigs[s] != nullptr) delete busConfigs[s]; busConfigs[s] = new BusConfig(ledType, pins, start, length, colorOrder, reversed, skipFirst, AWmode); diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm index 9f822294..11a34493 100644 --- a/wled00/data/settings_leds.htm +++ b/wled00/data/settings_leds.htm @@ -141,7 +141,7 @@ let len = parseInt(d.getElementsByName("LC"+n)[0].value); len += parseInt(d.getElementsByName("SL"+n)[0].value); // skipped LEDs are allocated too let dbl = 0; - if (d.Sf.LD.checked) dbl = len * 3; // double buffering + if (d.Sf.LD.checked) dbl = len * 4; // double buffering if (t < 32) { if (t==26 || t==29) len *= 2; // 16 bit LEDs if (maxM < 10000 && d.getElementsByName("L0"+n)[0].value == 3) { //8266 DMA uses 5x the mem diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 6866a692..cd027c06 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -151,11 +151,16 @@ void WLED::loop() DEBUG_PRINTLN(F("Re-init busses.")); bool aligned = strip.checkSegmentAlignment(); //see if old segments match old bus(ses) busses.removeAll(); - uint32_t mem = 0; + uint32_t mem = 0, globalBufMem = 0; + uint16_t maxlen = 0; for (uint8_t i = 0; i < WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES; i++) { if (busConfigs[i] == nullptr) break; mem += BusManager::memUsage(*busConfigs[i]); - if (mem <= MAX_LED_MEMORY) { + if (strip.useGlobalLedBuffer && busConfigs[i]->start + busConfigs[i]->count > maxlen) { + maxlen = busConfigs[i]->start + busConfigs[i]->count; + globalBufMem = maxlen * 4; + } + if (mem + globalBufMem <= MAX_LED_MEMORY) { busses.add(*busConfigs[i]); } delete busConfigs[i]; busConfigs[i] = nullptr;