Skip to content

Commit 25d5295

Browse files
authored
Merge pull request #5023 from DedeHai/matrix_save_fix
fix timing issue when changing 1D <-> 2D credits to @blazoncek
2 parents 474a995 + 50c0f41 commit 25d5295

File tree

3 files changed

+22
-11
lines changed

3 files changed

+22
-11
lines changed

wled00/FX_2Dfcn.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
// note: matrix may be comprised of multiple panels each with different orientation
1818
// but ledmap takes care of that. ledmap is constructed upon initialization
1919
// so matrix should disable regular ledmap processing
20+
// WARNING: effect drawing has to be suspended (strip.suspend()) or must be called from loop() context
2021
void WS2812FX::setUpMatrix() {
2122
#ifndef WLED_DISABLE_2D
2223
// isMatrix is set in cfg.cpp or set.cpp
@@ -45,12 +46,12 @@ void WS2812FX::setUpMatrix() {
4546
return;
4647
}
4748

48-
suspend();
49-
waitForIt();
50-
5149
customMappingSize = 0; // prevent use of mapping if anything goes wrong
5250

5351
d_free(customMappingTable);
52+
// Segment::maxWidth and Segment::maxHeight are set according to panel layout
53+
// and the product will include at least all leds in matrix
54+
// if actual LEDs are more, getLengthTotal() will return correct number of LEDs
5455
customMappingTable = static_cast<uint16_t*>(d_malloc(sizeof(uint16_t)*getLengthTotal())); // prefer to not use SPI RAM
5556

5657
if (customMappingTable) {
@@ -113,7 +114,6 @@ void WS2812FX::setUpMatrix() {
113114

114115
// delete gap array as we no longer need it
115116
p_free(gapTable);
116-
resume();
117117

118118
#ifdef WLED_DEBUG
119119
DEBUG_PRINT(F("Matrix ledmap:"));

wled00/FX_fcn.cpp

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -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
16851689
void 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
18131820
void 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

18201828
void 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

18911900
void 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
19541965
bool 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
}

wled00/set.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -814,8 +814,13 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
814814
}
815815
}
816816
strip.panel.shrink_to_fit(); // release unused memory
817+
// we are changing matrix/ledmap geometry which *will* affect existing segments
818+
// since we are not in loop() context we must make sure that effects are not running. credit @blazonchek for properly fixing #4911
819+
strip.suspend();
820+
strip.waitForIt();
817821
strip.deserializeMap(); // (re)load default ledmap (will also setUpMatrix() if ledmap does not exist)
818822
strip.makeAutoSegments(true); // force re-creation of segments
823+
strip.resume();
819824
}
820825
#endif
821826

0 commit comments

Comments
 (0)