code robustness improvements plus minor speedup

* make  XY() and _setPixelColorXY_raw() const (minor speedup)
* segment is a struct not a class: friend class Segment --> friend struct Segment
* fix missing braces around two macros
* use non-throwing "new" where possible
* improve robustness of transition code
This commit is contained in:
Frank 2025-01-07 15:09:29 +01:00 committed by Damian Schneider
parent 48f5099646
commit 703f84e5e1
6 changed files with 19 additions and 19 deletions

View File

@ -79,9 +79,9 @@ extern byte realtimeMode; // used in getMappedPixelIndex()
#define MAX_NUM_SEGMENTS 32 #define MAX_NUM_SEGMENTS 32
#endif #endif
#if defined(ARDUINO_ARCH_ESP32S2) #if defined(ARDUINO_ARCH_ESP32S2)
#define MAX_SEGMENT_DATA MAX_NUM_SEGMENTS*768 // 24k by default (S2 is short on free RAM) #define MAX_SEGMENT_DATA (MAX_NUM_SEGMENTS*768) // 24k by default (S2 is short on free RAM)
#else #else
#define MAX_SEGMENT_DATA MAX_NUM_SEGMENTS*1280 // 40k by default #define MAX_SEGMENT_DATA (MAX_NUM_SEGMENTS*1280) // 40k by default
#endif #endif
#endif #endif
@ -460,7 +460,7 @@ typedef struct Segment {
{} {}
} *_t; } *_t;
[[gnu::hot]] void _setPixelColorXY_raw(int& x, int& y, uint32_t& col); // set pixel without mapping (internal use only) [[gnu::hot]] void _setPixelColorXY_raw(int& x, int& y, uint32_t& col) const; // set pixel without mapping (internal use only)
public: public:
@ -642,7 +642,7 @@ typedef struct Segment {
#endif #endif
} }
#ifndef WLED_DISABLE_2D #ifndef WLED_DISABLE_2D
[[gnu::hot]] uint16_t XY(int x, int y); // support function to get relative index within segment [[gnu::hot]] uint16_t XY(int x, int y) const; // support function to get relative index within segment
[[gnu::hot]] void setPixelColorXY(int x, int y, uint32_t c); // set relative pixel within segment with color [[gnu::hot]] void setPixelColorXY(int x, int y, uint32_t c); // set relative pixel within segment with color
inline void setPixelColorXY(unsigned x, unsigned y, uint32_t c) { setPixelColorXY(int(x), int(y), c); } inline void setPixelColorXY(unsigned x, unsigned y, uint32_t c) { setPixelColorXY(int(x), int(y), c); }
inline void setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0) { setPixelColorXY(x, y, RGBW32(r,g,b,w)); } inline void setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0) { setPixelColorXY(x, y, RGBW32(r,g,b,w)); }
@ -936,7 +936,7 @@ class WS2812FX { // 96 bytes
}; };
std::vector<segment> _segments; std::vector<segment> _segments;
friend class Segment; friend struct Segment;
private: private:
volatile bool _suspend; volatile bool _suspend;

View File

@ -51,7 +51,7 @@ void WS2812FX::setUpMatrix() {
customMappingSize = 0; // prevent use of mapping if anything goes wrong customMappingSize = 0; // prevent use of mapping if anything goes wrong
if (customMappingTable) delete[] customMappingTable; if (customMappingTable) delete[] customMappingTable;
customMappingTable = new uint16_t[getLengthTotal()]; customMappingTable = new(std::nothrow) uint16_t[getLengthTotal()];
if (customMappingTable) { if (customMappingTable) {
customMappingSize = getLengthTotal(); customMappingSize = getLengthTotal();
@ -85,7 +85,7 @@ void WS2812FX::setUpMatrix() {
JsonArray map = pDoc->as<JsonArray>(); JsonArray map = pDoc->as<JsonArray>();
gapSize = map.size(); gapSize = map.size();
if (!map.isNull() && gapSize >= matrixSize) { // not an empty map if (!map.isNull() && gapSize >= matrixSize) { // not an empty map
gapTable = new int8_t[gapSize]; gapTable = new(std::nothrow) int8_t[gapSize];
if (gapTable) for (size_t i = 0; i < gapSize; i++) { if (gapTable) for (size_t i = 0; i < gapSize; i++) {
gapTable[i] = constrain(map[i], -1, 1); gapTable[i] = constrain(map[i], -1, 1);
} }
@ -146,7 +146,7 @@ void WS2812FX::setUpMatrix() {
#ifndef WLED_DISABLE_2D #ifndef WLED_DISABLE_2D
// XY(x,y) - gets pixel index within current segment (often used to reference leds[] array element) // XY(x,y) - gets pixel index within current segment (often used to reference leds[] array element)
uint16_t IRAM_ATTR_YN Segment::XY(int x, int y) uint16_t IRAM_ATTR_YN Segment::XY(int x, int y) const
{ {
const int vW = vWidth(); // segment width in logical pixels (can be 0 if segment is inactive) const int vW = vWidth(); // segment width in logical pixels (can be 0 if segment is inactive)
const int vH = vHeight(); // segment height in logical pixels (is always >= 1) const int vH = vHeight(); // segment height in logical pixels (is always >= 1)
@ -154,7 +154,7 @@ uint16_t IRAM_ATTR_YN Segment::XY(int x, int y)
} }
// raw setColor function without checks (checks are done in setPixelColorXY()) // raw setColor function without checks (checks are done in setPixelColorXY())
void IRAM_ATTR_YN Segment::_setPixelColorXY_raw(int& x, int& y, uint32_t& col) void IRAM_ATTR_YN Segment::_setPixelColorXY_raw(int& x, int& y, uint32_t& col) const
{ {
const int baseX = start + x; const int baseX = start + x;
const int baseY = startY + y; const int baseY = startY + y;

View File

@ -94,7 +94,7 @@ Segment::Segment(const Segment &orig) {
name = nullptr; name = nullptr;
data = nullptr; data = nullptr;
_dataLen = 0; _dataLen = 0;
if (orig.name) { name = new char[strlen(orig.name)+1]; if (name) strcpy(name, orig.name); } if (orig.name) { name = new(std::nothrow) 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.data) { if (allocateData(orig._dataLen)) memcpy(data, orig.data, orig._dataLen); }
} }
@ -122,7 +122,7 @@ Segment& Segment::operator= (const Segment &orig) {
data = nullptr; data = nullptr;
_dataLen = 0; _dataLen = 0;
// copy source data // copy source data
if (orig.name) { name = new char[strlen(orig.name)+1]; if (name) strcpy(name, orig.name); } if (orig.name) { name = new(std::nothrow) 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.data) { if (allocateData(orig._dataLen)) memcpy(data, orig.data, orig._dataLen); }
} }
return *this; return *this;
@ -253,7 +253,7 @@ void Segment::startTransition(uint16_t dur) {
if (isInTransition()) return; // already in transition no need to store anything if (isInTransition()) return; // already in transition no need to store anything
// starting a transition has to occur before change so we get current values 1st // starting a transition has to occur before change so we get current values 1st
_t = new Transition(dur); // no previous transition running _t = new(std::nothrow) Transition(dur); // no previous transition running
if (!_t) return; // failed to allocate data if (!_t) return; // failed to allocate data
//DEBUG_PRINTF_P(PSTR("-- Started transition: %p (%p)\n"), this, _t); //DEBUG_PRINTF_P(PSTR("-- Started transition: %p (%p)\n"), this, _t);
@ -380,7 +380,7 @@ void Segment::restoreSegenv(tmpsegd_t &tmpSeg) {
uint8_t Segment::currentBri(bool useCct) const { uint8_t Segment::currentBri(bool useCct) const {
unsigned prog = progress(); unsigned prog = progress();
if (prog < 0xFFFFU) { if (prog < 0xFFFFU && _t) {
unsigned curBri = (useCct ? cct : (on ? opacity : 0)) * prog; unsigned curBri = (useCct ? cct : (on ? opacity : 0)) * prog;
curBri += (useCct ? _t->_cctT : _t->_briT) * (0xFFFFU - prog); curBri += (useCct ? _t->_cctT : _t->_briT) * (0xFFFFU - prog);
return curBri / 0xFFFFU; return curBri / 0xFFFFU;
@ -391,7 +391,7 @@ uint8_t Segment::currentBri(bool useCct) const {
uint8_t Segment::currentMode() const { uint8_t Segment::currentMode() const {
#ifndef WLED_DISABLE_MODE_BLEND #ifndef WLED_DISABLE_MODE_BLEND
unsigned prog = progress(); unsigned prog = progress();
if (modeBlending && prog < 0xFFFFU) return _t->_modeT; if (modeBlending && prog < 0xFFFFU && _t) return _t->_modeT;
#endif #endif
return mode; return mode;
} }
@ -1809,7 +1809,7 @@ bool WS2812FX::deserializeMap(unsigned n) {
} }
if (customMappingTable) delete[] customMappingTable; if (customMappingTable) delete[] customMappingTable;
customMappingTable = new uint16_t[getLengthTotal()]; customMappingTable = new(std::nothrow) uint16_t[getLengthTotal()];
if (customMappingTable) { if (customMappingTable) {
DEBUG_PRINT(F("Reading LED map from ")); DEBUG_PRINTLN(fileName); DEBUG_PRINT(F("Reading LED map from ")); DEBUG_PRINTLN(fileName);

View File

@ -77,7 +77,7 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId)
if (name != nullptr) len = strlen(name); if (name != nullptr) len = strlen(name);
if (len > 0) { if (len > 0) {
if (len > WLED_MAX_SEGNAME_LEN) len = WLED_MAX_SEGNAME_LEN; if (len > WLED_MAX_SEGNAME_LEN) len = WLED_MAX_SEGNAME_LEN;
seg.name = new char[len+1]; seg.name = new(std::nothrow) char[len+1];
if (seg.name) strlcpy(seg.name, name, WLED_MAX_SEGNAME_LEN+1); if (seg.name) strlcpy(seg.name, name, WLED_MAX_SEGNAME_LEN+1);
} else { } else {
// but is empty (already deleted above) // but is empty (already deleted above)

View File

@ -61,7 +61,7 @@ int16_t loadPlaylist(JsonObject playlistObj, byte presetId) {
if (playlistLen == 0) return -1; if (playlistLen == 0) return -1;
if (playlistLen > 100) playlistLen = 100; if (playlistLen > 100) playlistLen = 100;
playlistEntries = new PlaylistEntry[playlistLen]; playlistEntries = new(std::nothrow) PlaylistEntry[playlistLen];
if (playlistEntries == nullptr) return -1; if (playlistEntries == nullptr) return -1;
byte it = 0; byte it = 0;

View File

@ -216,8 +216,8 @@ void handlePresets()
//called from handleSet(PS=) [network callback (sObj is empty), IR (irrational), deserializeState, UDP] and deserializeState() [network callback (filedoc!=nullptr)] //called from handleSet(PS=) [network callback (sObj is empty), IR (irrational), deserializeState, UDP] and deserializeState() [network callback (filedoc!=nullptr)]
void savePreset(byte index, const char* pname, JsonObject sObj) void savePreset(byte index, const char* pname, JsonObject sObj)
{ {
if (!saveName) saveName = new char[33]; if (!saveName) saveName = new(std::nothrow) char[33];
if (!quickLoad) quickLoad = new char[9]; if (!quickLoad) quickLoad = new(std::nothrow) char[9];
if (!saveName || !quickLoad) return; if (!saveName || !quickLoad) return;
if (index == 0 || (index > 250 && index < 255)) return; if (index == 0 || (index > 250 && index < 255)) return;