@@ -1681,9 +1681,13 @@ void WS2812FX::setTransitionMode(bool t) {
16811681 resume ();
16821682}
16831683
1684- // wait until frame is over (service() has finished or time for 1 frame has passed; yield() crashes on 8266)
1684+ // wait until frame is over (service() has finished or time for 2 frames have passed; yield() crashes on 8266)
1685+ // the latter may, in rare circumstances, lead to incorrectly assuming strip is done servicing but will not block
1686+ // other processing "indefinitely"
1687+ // rare circumstances are: setting FPS to high number (i.e. 120) and have very slow effect that will need more
1688+ // time than 2 * _frametime (1000/FPS) to draw content
16851689void WS2812FX::waitForIt () {
1686- unsigned long maxWait = millis () + getFrameTime () + 100 ; // TODO: this needs a proper fix for timeout!
1690+ unsigned long maxWait = millis () + 2 * getFrameTime () + 100 ; // TODO: this needs a proper fix for timeout! see #4779
16871691 while (isServicing () && maxWait > millis ()) delay (1 );
16881692 #ifdef WLED_DEBUG
16891693 if (millis () >= maxWait) DEBUG_PRINTLN (F (" Waited for strip to finish servicing." ));
@@ -1810,14 +1814,19 @@ Segment& WS2812FX::getSegment(unsigned id) {
18101814 return _segments[id >= _segments.size () ? getMainSegmentId () : id]; // vectors
18111815}
18121816
1817+ // WARNING: resetSegments(), makeAutoSegments() and fixInvalidSegments() must not be called while
1818+ // strip is being serviced (strip.service()), you must call suspend prior if changing segments outside
1819+ // loop() context
18131820void WS2812FX::resetSegments () {
1821+ if (isServicing ()) return ;
18141822 _segments.clear (); // destructs all Segment as part of clearing
18151823 _segments.emplace_back (0 , isMatrix ? Segment::maxWidth : _length, 0 , isMatrix ? Segment::maxHeight : 1 );
18161824 _segments.shrink_to_fit (); // just in case ...
18171825 _mainSegment = 0 ;
18181826}
18191827
18201828void WS2812FX::makeAutoSegments (bool forceReset) {
1829+ if (isServicing ()) return ;
18211830 if (autoSegments) { // make one segment per bus
18221831 unsigned segStarts[MAX_NUM_SEGMENTS] = {0 };
18231832 unsigned segStops [MAX_NUM_SEGMENTS] = {0 };
@@ -1889,6 +1898,7 @@ void WS2812FX::makeAutoSegments(bool forceReset) {
18891898}
18901899
18911900void WS2812FX::fixInvalidSegments () {
1901+ if (isServicing ()) return ;
18921902 // make sure no segment is longer than total (sanity check)
18931903 for (size_t i = getSegmentsNum ()-1 ; i > 0 ; i--) {
18941904 if (isMatrix) {
@@ -1951,6 +1961,7 @@ void WS2812FX::printSize() {
19511961
19521962// load custom mapping table from JSON file (called from finalizeInit() or deserializeState())
19531963// if this is a matrix set-up and default ledmap.json file does not exist, create mapping table using setUpMatrix() from panel information
1964+ // WARNING: effect drawing has to be suspended (strip.suspend()) or must be called from loop() context
19541965bool WS2812FX::deserializeMap (unsigned n) {
19551966 char fileName[32 ];
19561967 strcpy_P (fileName, PSTR (" /ledmap" ));
@@ -1980,9 +1991,6 @@ bool WS2812FX::deserializeMap(unsigned n) {
19801991 } else
19811992 DEBUG_PRINTF_P (PSTR (" Reading LED map from %s\n " ), fileName);
19821993
1983- suspend ();
1984- waitForIt ();
1985-
19861994 JsonObject root = pDoc->as <JsonObject>();
19871995 // if we are loading default ledmap (at boot) set matrix width and height from the ledmap (compatible with WLED MM ledmaps)
19881996 if (n == 0 && (!root[F (" width" )].isNull () || !root[F (" height" )].isNull ())) {
@@ -2040,8 +2048,6 @@ bool WS2812FX::deserializeMap(unsigned n) {
20402048 DEBUG_PRINTLN (F (" ERROR LED map allocation error." ));
20412049 }
20422050
2043- resume ();
2044-
20452051 releaseJSONBufferLock ();
20462052 return (customMappingSize > 0 );
20472053}
0 commit comments