Effect buffer optimisations

setMode() fix for selecting gap
UI error messages
This commit is contained in:
Blaz Kristan 2023-12-27 19:36:25 +01:00
parent 08d9f7d967
commit 6332ee6edb
8 changed files with 1437 additions and 1442 deletions

View File

@ -5292,7 +5292,6 @@ uint16_t mode_2Dmatrix(void) { // Matrix2D. By Jeremy Williams.
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
if (SEGENV.call == 0) { if (SEGENV.call == 0) {
memset(SEGMENT.data, 0, dataSize); // no falling spawns
SEGMENT.fill(BLACK); SEGMENT.fill(BLACK);
SEGENV.step = 0; SEGENV.step = 0;
} }

View File

@ -543,9 +543,9 @@ typedef struct Segment {
// runtime data functions // runtime data functions
inline uint16_t dataSize(void) const { return _dataLen; } inline uint16_t dataSize(void) const { return _dataLen; }
bool allocateData(size_t len); bool allocateData(size_t len); // allocates effect data buffer in heap and clears it
void deallocateData(void); void deallocateData(void); // deallocates (frees) effect data buffer from heap
void resetIfRequired(void); void resetIfRequired(void); // sets all SEGENV variables to 0 and clears data buffer
/** /**
* Flags that before the next effect is calculated, * Flags that before the next effect is calculated,
* the internal segment state should be reset. * the internal segment state should be reset.
@ -559,8 +559,8 @@ typedef struct Segment {
void stopTransition(void); void stopTransition(void);
void handleTransition(void); void handleTransition(void);
#ifndef WLED_DISABLE_MODE_BLEND #ifndef WLED_DISABLE_MODE_BLEND
void swapSegenv(tmpsegd_t &tmpSegD); void swapSegenv(tmpsegd_t &tmpSegD); // copies segment data into specifed buffer, if buffer is not a transition buffer, segment data is overwritten from transition buffer
void restoreSegenv(tmpsegd_t &tmpSegD); void restoreSegenv(tmpsegd_t &tmpSegD); // restores segment data from buffer, if buffer is not transition buffer, changed values are copied to transition buffer
#endif #endif
uint16_t progress(void); // transition progression between 0-65535 uint16_t progress(void); // transition progression between 0-65535
uint8_t currentBri(bool useCct = false); uint8_t currentBri(bool useCct = false);

View File

@ -143,27 +143,28 @@ Segment& Segment::operator= (Segment &&orig) noexcept {
return *this; return *this;
} }
// allocates effect data buffer on heap and initialises (erases) it
bool IRAM_ATTR Segment::allocateData(size_t len) { bool IRAM_ATTR Segment::allocateData(size_t len) {
if (len == 0) return false; // nothing to do
if (data && _dataLen >= len) { // already allocated enough (reduce fragmentation) if (data && _dataLen >= len) { // already allocated enough (reduce fragmentation)
if (call == 0) memset(data, 0, len); // erase buffer if called during effect initialisation if (call == 0) memset(data, 0, len); // erase buffer if called during effect initialisation
return true; return true;
} }
//DEBUG_PRINTF("-- Allocating data (%d): %p\n", len, this); //DEBUG_PRINTF("-- Allocating data (%d): %p\n", len, this);
deallocateData(); deallocateData(); // if the old buffer was smaller release it first
if (len == 0) return false; // nothing to do
if (Segment::getUsedSegmentData() + len > MAX_SEGMENT_DATA) { if (Segment::getUsedSegmentData() + len > MAX_SEGMENT_DATA) {
// not enough memory // not enough memory
DEBUG_PRINT(F("!!! Effect RAM depleted: ")); DEBUG_PRINT(F("!!! Effect RAM depleted: "));
DEBUG_PRINTF("%d/%d !!!\n", len, Segment::getUsedSegmentData()); DEBUG_PRINTF("%d/%d !!!\n", len, Segment::getUsedSegmentData());
errorFlag = ERR_NORAM;
return false; return false;
} }
// do not use SPI RAM on ESP32 since it is slow // do not use SPI RAM on ESP32 since it is slow
data = (byte*) malloc(len); data = (byte*)calloc(len, sizeof(byte));
if (!data) { DEBUG_PRINTLN(F("!!! Allocation failed. !!!")); return false; } // allocation failed if (!data) { DEBUG_PRINTLN(F("!!! Allocation failed. !!!")); return false; } // allocation failed
Segment::addUsedSegmentData(len); Segment::addUsedSegmentData(len);
//DEBUG_PRINTF("--- Allocated data (%p): %d/%d -> %p\n", this, len, Segment::getUsedSegmentData(), data); //DEBUG_PRINTF("--- Allocated data (%p): %d/%d -> %p\n", this, len, Segment::getUsedSegmentData(), data);
_dataLen = len; _dataLen = len;
memset(data, 0, len);
return true; return true;
} }
@ -194,7 +195,7 @@ void IRAM_ATTR Segment::deallocateData() {
void Segment::resetIfRequired() { void Segment::resetIfRequired() {
if (!reset) return; if (!reset) return;
//DEBUG_PRINTF("-- Segment reset: %p\n", this); //DEBUG_PRINTF("-- Segment reset: %p\n", this);
deallocateData(); if (data && _dataLen > 0) memset(data, 0, _dataLen); // prevent heap fragmentation (just erase buffer instead of deallocateData())
next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0; next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0;
reset = false; reset = false;
} }
@ -561,8 +562,10 @@ void Segment::setOption(uint8_t n, bool val) {
} }
void Segment::setMode(uint8_t fx, bool loadDefaults) { void Segment::setMode(uint8_t fx, bool loadDefaults) {
// skip reserved
while (fx < strip.getModeCount() && strncmp_P("RSVD", strip.getModeData(fx), 4) == 0) fx++;
if (fx >= strip.getModeCount()) fx = 0; // set solid mode
// if we have a valid mode & is not reserved // if we have a valid mode & is not reserved
if (fx < strip.getModeCount() && strncmp_P("RSVD", strip.getModeData(fx), 4)) {
if (fx != mode) { if (fx != mode) {
#ifndef WLED_DISABLE_MODE_BLEND #ifndef WLED_DISABLE_MODE_BLEND
if (modeBlending) startTransition(strip.getTransition()); // set effect transitions if (modeBlending) startTransition(strip.getTransition()); // set effect transitions
@ -591,7 +594,6 @@ void Segment::setMode(uint8_t fx, bool loadDefaults) {
stateChanged = true; // send UDP/WS broadcast stateChanged = true; // send UDP/WS broadcast
} }
} }
}
void Segment::setPalette(uint8_t pal) { void Segment::setPalette(uint8_t pal) {
if (pal < 245 && pal > GRADIENT_PALETTE_COUNT+13) pal = 0; // built in palettes if (pal < 245 && pal > GRADIENT_PALETTE_COUNT+13) pal = 0; // built in palettes

View File

@ -258,23 +258,8 @@ void BusDigital::setBrightness(uint8_t b) {
if (_pins[0] == LED_BUILTIN || _pins[1] == LED_BUILTIN) reinit(); if (_pins[0] == LED_BUILTIN || _pins[1] == LED_BUILTIN) reinit();
} }
#endif #endif
uint8_t prevBri = _bri;
Bus::setBrightness(b); Bus::setBrightness(b);
PolyBus::setBrightness(_busPtr, _iType, b); PolyBus::setBrightness(_busPtr, _iType, b);
/*
if (_data) return; // use _buffering this causes ~20% FPS drop
// must update/repaint every LED in the NeoPixelBus buffer to the new brightness
// the only case where repainting is unnecessary is when all pixels are set after the brightness change but before the next show
// (which we can't rely on)
uint16_t hwLen = _len;
if (_type == TYPE_WS2812_1CH_X3) hwLen = NUM_ICS_WS2812_1CH_3X(_len); // only needs a third of "RGB" LEDs for NeoPixelBus
for (unsigned i = 0; i < hwLen; i++) {
// use 0 as color order, actual order does not matter here as we just update the channel values as-is
uint32_t c = restoreColorLossy(PolyBus::getPixelColor(_busPtr, _iType, i, 0), prevBri);
PolyBus::setPixelColor(_busPtr, _iType, i, c, 0);
}
*/
} }
//If LEDs are skipped, it is possible to use the first as a status LED. //If LEDs are skipped, it is possible to use the first as a status LED.

View File

@ -345,6 +345,7 @@
#define ERR_CONCURRENCY 2 // Conurrency (client active) #define ERR_CONCURRENCY 2 // Conurrency (client active)
#define ERR_NOBUF 3 // JSON buffer was not released in time, request cannot be handled at this time #define ERR_NOBUF 3 // JSON buffer was not released in time, request cannot be handled at this time
#define ERR_NOT_IMPL 4 // Not implemented #define ERR_NOT_IMPL 4 // Not implemented
#define ERR_NORAM 8 // effect RAM depleted
#define ERR_JSON 9 // JSON parsing failed (input too large?) #define ERR_JSON 9 // JSON parsing failed (input too large?)
#define ERR_FS_BEGIN 10 // Could not init filesystem (no partition?) #define ERR_FS_BEGIN 10 // Could not init filesystem (no partition?)
#define ERR_FS_QUOTA 11 // The FS is full or the maximum file size is reached #define ERR_FS_QUOTA 11 // The FS is full or the maximum file size is reached

View File

@ -329,7 +329,6 @@ function openTab(tabI, force = false)
var timeout; var timeout;
function showToast(text, error = false) function showToast(text, error = false)
{ {
if (error) gId('connind').style.backgroundColor = "var(--c-r)";
var x = gId('toast'); var x = gId('toast');
//if (error) text += '<i class="icons btn-icon" style="transform:rotate(45deg);position:absolute;top:10px;right:0px;" onclick="clearErrorToast(100);">&#xe18a;</i>'; //if (error) text += '<i class="icons btn-icon" style="transform:rotate(45deg);position:absolute;top:10px;right:0px;" onclick="clearErrorToast(100);">&#xe18a;</i>';
x.innerHTML = text; x.innerHTML = text;
@ -342,6 +341,7 @@ function showToast(text, error = false)
function showErrorToast() function showErrorToast()
{ {
gId('connind').style.backgroundColor = "var(--c-r)";
showToast('Connection to light failed!', true); showToast('Connection to light failed!', true);
} }
@ -1494,6 +1494,12 @@ function readState(s,command=false)
if (s.error && s.error != 0) { if (s.error && s.error != 0) {
var errstr = ""; var errstr = "";
switch (s.error) { switch (s.error) {
case 8:
errstr = "Effect RAM depleted!";
break;
case 9:
errstr = "JSON parsing error!";
break;
case 10: case 10:
errstr = "Could not mount filesystem!"; errstr = "Could not mount filesystem!";
break; break;

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,7 @@
*/ */
// version code in format yymmddb (b = daily build) // version code in format yymmddb (b = daily build)
#define VERSION 2312190 #define VERSION 2312270
//uncomment this if you have a "my_config.h" file you'd like to use //uncomment this if you have a "my_config.h" file you'd like to use
//#define WLED_USE_MY_CONFIG //#define WLED_USE_MY_CONFIG