diff --git a/wled00/FX.h b/wled00/FX.h index 60b1473c..882f4c9e 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -504,6 +504,7 @@ typedef struct Segment { static uint16_t getUsedSegmentData(void) { return _usedSegmentData; } static void addUsedSegmentData(int len) { _usedSegmentData += len; } + void set(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 setColor(uint8_t slot, uint32_t c); //returns true if changed void setCCT(uint16_t k); void setOpacity(uint8_t o); diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 42d2dde0..0ac09998 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -43,21 +43,22 @@ void WS2812FX::setUpMatrix() { // isMatrix is set in cfg.cpp or set.cpp if (isMatrix) { - Segment::maxWidth = hPanels * panelW; - Segment::maxHeight = vPanels * panelH; + uint16_t maxWidth = hPanels * panelW; + uint16_t maxHeight = vPanels * panelH; // safety check - if (Segment::maxWidth * Segment::maxHeight > MAX_LEDS || Segment::maxWidth == 1 || Segment::maxHeight == 1) { - Segment::maxWidth = _length; - Segment::maxHeight = 1; + if (maxWidth * maxHeight > MAX_LEDS || maxWidth == 1 || maxHeight == 1) { isMatrix = false; return; } - customMappingSize = Segment::maxWidth * Segment::maxHeight; - customMappingTable = new uint16_t[customMappingSize]; + customMappingTable = new uint16_t[maxWidth * maxHeight]; if (customMappingTable != nullptr) { + Segment::maxWidth = maxWidth; + Segment::maxHeight = maxHeight; + customMappingSize = maxWidth * maxHeight; + uint16_t startL; // index in custom mapping array (logical strip) uint16_t startP; // position of 1st pixel of panel on (virtual) strip uint16_t x, y, offset; @@ -94,18 +95,12 @@ void WS2812FX::setUpMatrix() { } DEBUG_PRINTLN(); #endif - } else { - // memory allocation error - Segment::maxWidth = _length; - Segment::maxHeight = 1; + } else { // memory allocation error isMatrix = false; - return; } - } else { - // not a matrix set up - Segment::maxWidth = _length; - Segment::maxHeight = 1; } +#else + isMatrix = false; // no matter what config says #endif } diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index cc3b122e..d2a8182e 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -376,6 +376,45 @@ void Segment::handleTransition() { } } +void Segment::set(uint16_t i1, uint16_t i2, uint8_t grp, uint8_t spc, uint16_t ofs, uint16_t i1Y, uint16_t i2Y) { + //return if neither bounds nor grouping have changed + bool boundsUnchanged = (start == i1 && stop == i2); + if (Segment::maxHeight>1) { //2D + boundsUnchanged &= (startY == i1Y && stopY == i2Y); + } + if (boundsUnchanged + && (!grp || (grouping == grp && spacing == spc)) + && (ofs == UINT16_MAX || ofs == offset)) return; + + if (stop) fill(BLACK); //turn old segment range off + if (i2 <= i1) { //disable segment + stop = 0; + markForReset(); + return; + } + if (Segment::maxHeight>1) { // 2D + #ifndef WLED_DISABLE_2D + if (i1 < Segment::maxWidth) start = i1; + stop = i2 > Segment::maxWidth ? Segment::maxWidth : i2; + if (i1Y < Segment::maxHeight) startY = i1Y; + stopY = i2Y > Segment::maxHeight ? Segment::maxHeight : MAX(1,i2Y); + #endif + } else { + if (i1 < strip.getLengthTotal()) start = i1; + stop = i2 > strip.getLengthTotal() ? strip.getLengthTotal() : i2; + startY = 0; + stopY = 1; + } + if (grp) { + grouping = grp; + spacing = spc; + } + if (ofs < UINT16_MAX) offset = ofs; + markForReset(); + if (!boundsUnchanged) refreshLightCapabilities(); +} + + bool Segment::setColor(uint8_t slot, uint32_t c) { //returns true if changed if (slot >= NUM_COLORS || c == colors[slot]) return false; if (fadeTransition) startTransition(strip.getTransition()); // start transition prior to change @@ -957,6 +996,11 @@ void WS2812FX::finalizeInit(void) #endif } + if (!isMatrix) { // if 2D then max values defined in setUpMatrix() using panel set-up + Segment::maxWidth = _length; + Segment::maxHeight = 1; + } + //initialize leds array. TBD: realloc if nr of leds change if (Segment::_globalLeds) { purgeSegments(true); @@ -1319,54 +1363,7 @@ Segment& WS2812FX::getSegment(uint8_t id) { void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping, uint8_t spacing, uint16_t offset, uint16_t startY, uint16_t stopY) { if (n >= _segments.size()) return; - Segment& seg = _segments[n]; - - //return if neither bounds nor grouping have changed - bool boundsUnchanged = (seg.start == i1 && seg.stop == i2); - if (isMatrix) { - boundsUnchanged &= (seg.startY == startY && seg.stopY == stopY); - } - if (boundsUnchanged - && (!grouping || (seg.grouping == grouping && seg.spacing == spacing)) - && (offset == UINT16_MAX || offset == seg.offset)) return; - - //if (seg.stop) setRange(seg.start, seg.stop -1, BLACK); //turn old segment range off - if (seg.stop) seg.fill(BLACK); //turn old segment range off - if (i2 <= i1) //disable segment - { - // disabled segments should get removed using purgeSegments() - DEBUG_PRINT(F("-- Segment ")); DEBUG_PRINT(n); DEBUG_PRINTLN(F(" marked inactive.")); - seg.stop = 0; - seg.options = 0b0000000000000101; // on & selected - //if (seg.name) { - // delete[] seg.name; - // seg.name = nullptr; - //} - // if main segment is deleted, set first active as main segment - if (n == _mainSegment) setMainSegmentId(0); - seg.markForReset(); - return; - } - if (isMatrix) { - #ifndef WLED_DISABLE_2D - if (i1 < Segment::maxWidth) seg.start = i1; - seg.stop = i2 > Segment::maxWidth ? Segment::maxWidth : i2; - if (startY < Segment::maxHeight) seg.startY = startY; - seg.stopY = stopY > Segment::maxHeight ? Segment::maxHeight : MAX(1,stopY); - #endif - } else { - if (i1 < _length) seg.start = i1; - seg.stop = i2 > _length ? _length : i2; - seg.startY = 0; - seg.stopY = 1; - } - if (grouping) { - seg.grouping = grouping; - seg.spacing = spacing; - } - if (offset < UINT16_MAX) seg.offset = offset; - seg.markForReset(); - if (!boundsUnchanged) seg.refreshLightCapabilities(); + _segments[n].set(i1, i2, grouping, spacing, offset, startY, stopY); } void WS2812FX::restartRuntime() { diff --git a/wled00/json.cpp b/wled00/json.cpp index 192afd4b..fe87e4f6 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -105,7 +105,7 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId) of = offsetAbs; } if (stop > start && of > len -1) of = len -1; - strip.setSegment(id, start, stop, grp, spc, of, startY, stopY); + seg.set(start, stop, grp, spc, of, startY, stopY); byte segbri = seg.opacity; if (getVal(elem["bri"], &segbri)) { diff --git a/wled00/set.cpp b/wled00/set.cpp index 0369e2e3..cb66937d 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -744,7 +744,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply) if (pos > 0) { spcI = getNumVal(&req, pos); } - strip.setSegment(selectedSeg, startI, stopI, grpI, spcI, UINT16_MAX, startY, stopY); + selseg.set(startI, stopI, grpI, spcI, UINT16_MAX, startY, stopY); pos = req.indexOf(F("RV=")); //Segment reverse if (pos > 0) selseg.reverse = req.charAt(pos+3) != '0'; diff --git a/wled00/udp.cpp b/wled00/udp.cpp index 2d1388f8..06172f6e 100644 --- a/wled00/udp.cpp +++ b/wled00/udp.cpp @@ -363,7 +363,7 @@ void handleNotifications() uint16_t stopY = 1, stop = (udpIn[3+ofs] << 8 | udpIn[4+ofs]); uint16_t offset = (udpIn[7+ofs] << 8 | udpIn[8+ofs]); if (!receiveSegmentOptions) { - strip.setSegment(id, start, stop, selseg.grouping, selseg.spacing, offset, startY, stopY); + selseg.set(start, stop, selseg.grouping, selseg.spacing, offset, startY, stopY); continue; } //for (size_t j = 1; j<4; j++) selseg.setOption(j, (udpIn[9 +ofs] >> j) & 0x01); //only take into account mirrored, on, reversed; ignore selected @@ -396,11 +396,10 @@ void handleNotifications() startY = (udpIn[32+ofs] << 8 | udpIn[33+ofs]); stopY = (udpIn[34+ofs] << 8 | udpIn[35+ofs]); } - //setSegment() also properly resets segments if (receiveSegmentBounds) { - strip.setSegment(id, start, stop, udpIn[5+ofs], udpIn[6+ofs], offset, startY, stopY); + selseg.set(start, stop, udpIn[5+ofs], udpIn[6+ofs], offset, startY, stopY); } else { - strip.setSegment(id, selseg.start, selseg.stop, udpIn[5+ofs], udpIn[6+ofs], selseg.offset, selseg.startY, selseg.stopY); + selseg.set(selseg.start, selseg.stop, udpIn[5+ofs], udpIn[6+ofs], selseg.offset, selseg.startY, selseg.stopY); } } stateChanged = true;