diff --git a/wled00/FX.h b/wled00/FX.h index 6e0b46435..a3e1547cf 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -316,9 +316,31 @@ class WS2812FX { WS2812FX::_usedSegmentData -= _dataLen; _dataLen = 0; } - void reset(){next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0; deallocateData();} + + /** + * If reset of this segment was request, clears runtime + * settings of this segment. + * Must not be called while an effect mode function is running + * because it could access the data buffer and this method + * may free that data buffer. + */ + void resetIfRequired() { + if (_requiresReset) { + next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0; + deallocateData(); + _requiresReset = false; + } + } + + /** + * Flags that before the next effect is calculated, + * the internal segment state should be reset. + * Call resetIfRequired before calling the next effect function. + */ + void reset() { _requiresReset = true; } private: uint16_t _dataLen = 0; + bool _requiresReset = false; } segment_runtime; WS2812FX() { diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index ddb49f6f0..340b047ff 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -76,6 +76,11 @@ void WS2812FX::service() { for(uint8_t i=0; i < MAX_NUM_SEGMENTS; i++) { _segment_index = i; + + // reset the segment runtime data if needed, called before isActive to ensure deleted + // segment's buffers are cleared + SEGENV.resetIfRequired(); + if (SEGMENT.isActive()) { if(nowUp > SEGENV.next_time || _triggered || (doShow && SEGMENT.mode == 0)) //last is temporary