Global buffer and ABL fixes

This commit is contained in:
Christian Schwinne 2023-06-27 00:38:30 +02:00
parent f6e86bfcf8
commit 61ba16b779
6 changed files with 30 additions and 8 deletions

View File

@ -1209,7 +1209,13 @@ uint8_t WS2812FX::estimateCurrentAndLimitBri() {
uint16_t len = bus->getLength(); uint16_t len = bus->getLength();
uint32_t busPowerSum = 0; uint32_t busPowerSum = 0;
for (uint_fast16_t i = 0; i < len; i++) { //sum up the usage of each LED 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); byte r = R(c), g = G(c), b = B(c), w = W(c);
if(useWackyWS2815PowerModel) { //ignore white component on WS2815 power calculation if(useWackyWS2815PowerModel) { //ignore white component on WS2815 power calculation
@ -1253,6 +1259,7 @@ void WS2812FX::show(void) {
show_callback callback = _callback; show_callback callback = _callback;
if (callback) callback(); if (callback) callback();
Bus::setRestoreBri(_renderBrightness);
uint8_t busBrightness = estimateCurrentAndLimitBri(); uint8_t busBrightness = estimateCurrentAndLimitBri();
if (_globalLedBuffer) { // copy data from buffer to bus if (_globalLedBuffer) { // copy data from buffer to bus
@ -1260,7 +1267,8 @@ void WS2812FX::show(void) {
} else { } else {
// if brightness changed since last show, must set everything again to update to new luminance // if brightness changed since last show, must set everything again to update to new luminance
if (_renderBrightness != busBrightness) { 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() // would be dangerous if applied immediately (could exceed ABL), but will not output until the next show()
busses.setBrightness(b); busses.setBrightness(b);
_renderBrightness = b; _renderBrightness = b;
Bus::setRestoreBri(b);
} else { } else {
unsigned long t = millis(); 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 if (_segments[0].next_time > t + 22 && t - _lastShow > MIN_SHOW_DELAY) show(); //apply brightness change immediately if no refresh soon

View File

@ -563,3 +563,4 @@ uint16_t BusManager::getTotalLength() {
int16_t Bus::_cct = -1; int16_t Bus::_cct = -1;
uint8_t Bus::_cctBlend = 0; uint8_t Bus::_cctBlend = 0;
uint8_t Bus::_gAWM = 255; uint8_t Bus::_gAWM = 255;
uint8_t Bus::_restaurationBri = 255;

View File

@ -154,6 +154,7 @@ class Bus {
inline uint8_t getAutoWhiteMode() { return _autoWhiteMode; } 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 void setGlobalAWMode(uint8_t m) { if (m < 5) _gAWM = m; else _gAWM = AW_GLOBAL_DISABLED; }
inline static uint8_t getGlobalAWMode() { return _gAWM; } inline static uint8_t getGlobalAWMode() { return _gAWM; }
inline static void setRestoreBri(uint8_t b) { _restaurationBri = b; }
bool reversed = false; bool reversed = false;
@ -168,6 +169,7 @@ class Bus {
static uint8_t _gAWM; static uint8_t _gAWM;
static int16_t _cct; static int16_t _cct;
static uint8_t _cctBlend; 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); uint32_t autoWhiteCalc(uint32_t c);
}; };
@ -231,7 +233,7 @@ class BusDigital : public Bus {
for (uint8_t i=0; i<4; i++) for (uint8_t i=0; i<4; i++)
{ {
uint16_t val = chan[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; return c;
} }

View File

@ -134,7 +134,8 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
if (fromFS || !ins.isNull()) { if (fromFS || !ins.isNull()) {
uint8_t s = 0; // bus iterator uint8_t s = 0; // bus iterator
if (fromFS) busses.removeAll(); // can't safely manipulate busses directly in network callback 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; bool busesChanged = false;
for (JsonObject elm : ins) { for (JsonObject elm : ins) {
if (s >= WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES) break; if (s >= WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES) break;
@ -162,7 +163,11 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
if (fromFS) { if (fromFS) {
BusConfig bc = BusConfig(ledType, pins, start, length, colorOrder, reversed, skipFirst, AWmode, freqkHz); BusConfig bc = BusConfig(ledType, pins, start, length, colorOrder, reversed, skipFirst, AWmode, freqkHz);
mem += BusManager::memUsage(bc); 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 { } else {
if (busConfigs[s] != nullptr) delete busConfigs[s]; if (busConfigs[s] != nullptr) delete busConfigs[s];
busConfigs[s] = new BusConfig(ledType, pins, start, length, colorOrder, reversed, skipFirst, AWmode); busConfigs[s] = new BusConfig(ledType, pins, start, length, colorOrder, reversed, skipFirst, AWmode);

View File

@ -141,7 +141,7 @@
let len = parseInt(d.getElementsByName("LC"+n)[0].value); let len = parseInt(d.getElementsByName("LC"+n)[0].value);
len += parseInt(d.getElementsByName("SL"+n)[0].value); // skipped LEDs are allocated too len += parseInt(d.getElementsByName("SL"+n)[0].value); // skipped LEDs are allocated too
let dbl = 0; 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 < 32) {
if (t==26 || t==29) len *= 2; // 16 bit LEDs 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 if (maxM < 10000 && d.getElementsByName("L0"+n)[0].value == 3) { //8266 DMA uses 5x the mem

View File

@ -151,11 +151,16 @@ void WLED::loop()
DEBUG_PRINTLN(F("Re-init busses.")); DEBUG_PRINTLN(F("Re-init busses."));
bool aligned = strip.checkSegmentAlignment(); //see if old segments match old bus(ses) bool aligned = strip.checkSegmentAlignment(); //see if old segments match old bus(ses)
busses.removeAll(); 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++) { for (uint8_t i = 0; i < WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES; i++) {
if (busConfigs[i] == nullptr) break; if (busConfigs[i] == nullptr) break;
mem += BusManager::memUsage(*busConfigs[i]); 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]); busses.add(*busConfigs[i]);
} }
delete busConfigs[i]; busConfigs[i] = nullptr; delete busConfigs[i]; busConfigs[i] = nullptr;