Static queued segment bounds

(saves 180 bytes of RAM)
Fixed segment index not increasing on inactive segments
This commit is contained in:
cschwinne 2023-07-13 03:09:42 +02:00
parent fa6070c680
commit 4766666913
3 changed files with 58 additions and 44 deletions

View File

@ -395,8 +395,8 @@ typedef struct Segment {
uint16_t _dataLen; uint16_t _dataLen;
static uint16_t _usedSegmentData; static uint16_t _usedSegmentData;
uint16_t _qStart, _qStop, _qStartY, _qStopY; static uint16_t _qStart, _qStop, _qStartY, _qStopY;
bool _queuedChanges; static uint8_t _queuedChangesSegId;
// transition data, valid only if transitional==true, holds values during transition (72 bytes) // transition data, valid only if transitional==true, holds values during transition (72 bytes)
struct Transition { struct Transition {
@ -466,7 +466,6 @@ typedef struct Segment {
data(nullptr), data(nullptr),
_capabilities(0), _capabilities(0),
_dataLen(0), _dataLen(0),
_queuedChanges(false),
_t(nullptr) _t(nullptr)
{ {
//refreshLightCapabilities(); //refreshLightCapabilities();
@ -515,7 +514,7 @@ typedef struct Segment {
static uint16_t getUsedSegmentData(void) { return _usedSegmentData; } static uint16_t getUsedSegmentData(void) { return _usedSegmentData; }
static void addUsedSegmentData(int len) { _usedSegmentData += len; } static void addUsedSegmentData(int len) { _usedSegmentData += len; }
void setUp(uint16_t i1, uint16_t i2, uint8_t grp=1, uint8_t spc=0, uint16_t ofs=UINT16_MAX, uint16_t i1Y=0, uint16_t i2Y=1, bool immediate=false); void setUp(uint16_t i1, uint16_t i2, uint8_t grp=1, uint8_t spc=0, uint16_t ofs=UINT16_MAX, uint16_t i1Y=0, uint16_t i2Y=1, uint8_t segId = 255);
bool setColor(uint8_t slot, uint32_t c); //returns true if changed bool setColor(uint8_t slot, uint32_t c); //returns true if changed
void setCCT(uint16_t k); void setCCT(uint16_t k);
void setOpacity(uint8_t o); void setOpacity(uint8_t o);

View File

@ -76,6 +76,9 @@
uint16_t Segment::_usedSegmentData = 0U; // amount of RAM all segments use for their data[] uint16_t Segment::_usedSegmentData = 0U; // amount of RAM all segments use for their data[]
uint16_t Segment::maxWidth = DEFAULT_LED_COUNT; uint16_t Segment::maxWidth = DEFAULT_LED_COUNT;
uint16_t Segment::maxHeight = 1; uint16_t Segment::maxHeight = 1;
uint8_t Segment::_queuedChangesSegId = 255U;
uint16_t Segment::_qStart = 0, Segment::_qStop = 0;
uint16_t Segment::_qStartY = 0, Segment::_qStopY = 0;
// copy constructor // copy constructor
Segment::Segment(const Segment &orig) { Segment::Segment(const Segment &orig) {
@ -174,12 +177,15 @@ void Segment::deallocateData() {
* may free that data buffer. * may free that data buffer.
*/ */
void Segment::resetIfRequired() { void Segment::resetIfRequired() {
if (reset) { if (!reset) return;
deallocateData(); deallocateData();
next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0; next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0;
if (_queuedChanges) setUp(_qStart, _qStop, grouping, spacing, offset, _qStartY, _qStopY, true); if (_queuedChangesSegId == strip.getCurrSegmentId()) { // apply queued changes
reset = false; // setOption(SEG_OPTION_RESET, false); setUp(_qStart, _qStop, grouping, spacing, offset, _qStartY, _qStopY);
_queuedChangesSegId = 255;
} }
reset = false;
} }
CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) { CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
@ -354,8 +360,10 @@ void Segment::handleTransition() {
} }
} }
void Segment::setUp(uint16_t i1, uint16_t i2, uint8_t grp, uint8_t spc, uint16_t ofs, uint16_t i1Y, uint16_t i2Y, bool immediate) { // segId is given when called from network callback, changes are queued if that segment is currently in its effect function
_queuedChanges = false; // cancel anything queued void Segment::setUp(uint16_t i1, uint16_t i2, uint8_t grp, uint8_t spc, uint16_t ofs, uint16_t i1Y, uint16_t i2Y, uint8_t segId) {
if (_queuedChangesSegId == segId) _queuedChangesSegId = 255; // cancel queued change if already queued for this segment
// return if neither bounds nor grouping have changed // return if neither bounds nor grouping have changed
bool boundsUnchanged = (start == i1 && stop == i2); bool boundsUnchanged = (start == i1 && stop == i2);
#ifndef WLED_DISABLE_2D #ifndef WLED_DISABLE_2D
@ -376,8 +384,19 @@ void Segment::setUp(uint16_t i1, uint16_t i2, uint8_t grp, uint8_t spc, uint16_t
if (ofs < UINT16_MAX) offset = ofs; if (ofs < UINT16_MAX) offset = ofs;
markForReset(); markForReset();
if (!boundsUnchanged) { if (boundsUnchanged) return; // TODO test if it is save to change grp/spc/ofs without queueing
if (immediate) { // queuing a change for a second segment will lead to the loss of the first change if not yet applied
// however this is not a problem as the queued change is applied immediately after the effect function in that segment returns
if (segId < MAX_NUM_SEGMENTS && segId == strip.getCurrSegmentId() && strip.isServicing()) { // queue change to prevent concurrent access
_qStart = i1;
_qStop = i2;
_qStartY = i1Y;
_qStopY = i2Y;
_queuedChangesSegId = segId;
return; // queued changes are applied immediately after effect function returns
}
// apply change immediately
if (i2 <= i1) { //disable segment if (i2 <= i1) { //disable segment
stop = 0; stop = 0;
return; return;
@ -397,15 +416,7 @@ void Segment::setUp(uint16_t i1, uint16_t i2, uint8_t grp, uint8_t spc, uint16_t
stop = 0; stop = 0;
return; return;
} }
if (!boundsUnchanged) refreshLightCapabilities(); refreshLightCapabilities();
} else {
_qStart = i1;
_qStop = i2;
_qStartY = i1Y;
_qStopY = i2Y;
_queuedChanges = true;
}
}
} }
@ -1087,7 +1098,7 @@ void WS2812FX::service() {
// reset the segment runtime data if needed // reset the segment runtime data if needed
seg.resetIfRequired(); seg.resetIfRequired();
if (!seg.isActive()) continue; if (!seg.isActive()) { _segment_index++; continue; }
// last condition ensures all solid segments are updated at the same time // last condition ensures all solid segments are updated at the same time
if(nowUp > seg.next_time || _triggered || (doShow && seg.mode == FX_MODE_STATIC)) if(nowUp > seg.next_time || _triggered || (doShow && seg.mode == FX_MODE_STATIC))
@ -1115,6 +1126,7 @@ void WS2812FX::service() {
seg.next_time = nowUp + delay; seg.next_time = nowUp + delay;
} }
seg.resetIfRequired(); // another reset chance, mainly to apply new segment bounds if queued
_segment_index++; _segment_index++;
} }
_virtualSegmentLength = 0; _virtualSegmentLength = 0;

View File

@ -112,8 +112,8 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId)
if (stop > start && of > len -1) of = len -1; if (stop > start && of > len -1) of = len -1;
// update segment (delete if necessary) // update segment (delete if necessary)
// we must not change segment dimensions during drawing of effects as that may produce undesired behaviour (crash) // we must not change segment dimensions during drawing of effects in that segment as concurrent access may cause a crash
seg.setUp(start, stop, grp, spc, of, startY, stopY, !strip.isServicing()); seg.setUp(start, stop, grp, spc, of, startY, stopY, id);
if (seg.reset && seg.stop == 0) return true; // segment was deleted & is marked for reset, no need to change anything else if (seg.reset && seg.stop == 0) return true; // segment was deleted & is marked for reset, no need to change anything else
@ -1065,7 +1065,10 @@ void serveJson(AsyncWebServerRequest* request)
DEBUG_PRINTF("JSON buffer size: %u for request: %d\n", lDoc.memoryUsage(), subJson); DEBUG_PRINTF("JSON buffer size: %u for request: %d\n", lDoc.memoryUsage(), subJson);
size_t len = response->setLength(); #ifdef WLED_DEBUG
size_t len =
#endif
response->setLength();
DEBUG_PRINT(F("JSON content length: ")); DEBUG_PRINTLN(len); DEBUG_PRINT(F("JSON content length: ")); DEBUG_PRINTLN(len);
request->send(response); request->send(response);