6565#endif
6666
6767// do not call this method from system context (network callback)
68- void WS2812FX::finalizeInit (uint16_t countPixels )
68+ void WS2812FX::finalizeInit (void )
6969{
7070 RESET_RUNTIME;
71- _length = countPixels ;
71+ isRgbw = isOffRefreshRequred = false ;
7272
73- // if busses failed to load, add default (FS issue...)
73+ // if busses failed to load, add default (fresh install, FS issue, ...)
7474 if (busses.getNumBusses () == 0 ) {
7575 const uint8_t defDataPins[] = {DATA_PINS};
7676 const uint16_t defCounts[] = {PIXEL_COUNTS};
7777 const uint8_t defNumBusses = ((sizeof defDataPins) / (sizeof defDataPins[0 ]));
7878 const uint8_t defNumCounts = ((sizeof defCounts) / (sizeof defCounts[0 ]));
7979 uint16_t prevLen = 0 ;
80- for (uint8_t i = 0 ; i < defNumBusses; i++) {
80+ for (uint8_t i = 0 ; i < defNumBusses && i < WLED_MAX_BUSSES ; i++) {
8181 uint8_t defPin[] = {defDataPins[i]};
8282 uint16_t start = prevLen;
83- uint16_t count = _length;
84- if (defNumBusses > 1 && defNumCounts) {
85- count = defCounts[(i < defNumCounts) ? i : defNumCounts -1 ];
86- }
83+ uint16_t count = defCounts[(i < defNumCounts) ? i : defNumCounts -1 ];
8784 prevLen += count;
8885 BusConfig defCfg = BusConfig (DEFAULT_LED_TYPE, defPin, start, count, COL_ORDER_GRB);
8986 busses.add (defCfg);
@@ -92,60 +89,30 @@ void WS2812FX::finalizeInit(uint16_t countPixels)
9289
9390 deserializeMap ();
9491
95- uint16_t segStarts[MAX_NUM_SEGMENTS] = {0 };
96- uint16_t segStops [MAX_NUM_SEGMENTS] = {0 };
97-
98- setBrightness (_brightness);
99-
100- // TODO make sure segments are only refreshed when bus config actually changed (new settings page)
101- uint8_t s = 0 ;
102- for (uint8_t i = 0 ; i < busses.getNumBusses (); i++) {
103- Bus* b = busses.getBus (i);
104-
105- if (autoSegments) { // make one segment per bus
106- segStarts[s] = b->getStart ();
107- segStops[s] = segStarts[s] + b->getLength ();
108-
109- // check for overlap with previous segments
110- for (uint8_t j = 0 ; j < s; j++) {
111- if (segStops[j] > segStarts[s] && segStarts[j] < segStops[s]) {
112- // segments overlap, merge
113- segStarts[j] = min (segStarts[s],segStarts[j]);
114- segStops [j] = max (segStops [s],segStops [j]); segStops[s] = 0 ;
115- s--;
116- }
117- }
118- s++;
119- }
120-
92+ _length = 0 ;
93+ for (uint8_t i=0 ; i<busses.getNumBusses (); i++) {
94+ Bus *bus = busses.getBus (i);
95+ if (bus == nullptr ) continue ;
96+ if (bus->getStart () + bus->getLength () > MAX_LEDS) break ;
97+ // RGBW mode is enabled if at least one of the strips is RGBW
98+ isRgbw |= bus->isRgbw ();
99+ // refresh is required to remain off if at least one of the strips requires the refresh.
100+ isOffRefreshRequred |= bus->isOffRefreshRequired ();
101+ uint16_t busEnd = bus->getStart () + bus->getLength ();
102+ if (busEnd > _length) _length = busEnd;
121103 #ifdef ESP8266
122- if ((!IS_DIGITAL (b ->getType ()) || IS_2PIN (b ->getType ()))) continue ;
104+ if ((!IS_DIGITAL (bus ->getType ()) || IS_2PIN (bus ->getType ()))) continue ;
123105 uint8_t pins[5 ];
124- b ->getPins (pins);
125- BusDigital* bd = static_cast <BusDigital*>(b );
106+ if (!bus ->getPins (pins)) continue ;
107+ BusDigital* bd = static_cast <BusDigital*>(bus );
126108 if (pins[0 ] == 3 ) bd->reinit ();
127109 #endif
128110 }
111+ ledCount = _length;
129112
130- if (autoSegments) {
131- for (uint8_t i = 0 ; i < MAX_NUM_SEGMENTS; i++) {
132- setSegment (i, segStarts[i], segStops[i]);
133- }
134- } else {
135- // expand the main seg to the entire length, but only if there are no other segments
136- uint8_t mainSeg = getMainSegmentId ();
137-
138- if (getActiveSegmentsNum () < 2 ) {
139- setSegment (mainSeg, 0 , _length);
140- } else {
141- // there are multiple segments, leave them, but prune length to total
142- for (uint8_t i = 0 ; i < MAX_NUM_SEGMENTS; i++)
143- {
144- if (_segments[i].start >= _length) setSegment (i, 0 , 0 );
145- if (_segments[i].stop > _length) setSegment (i, _segments[i].start , _length);
146- }
147- }
148- }
113+ // segments are created in makeAutoSegments();
114+
115+ setBrightness (_brightness);
149116}
150117
151118void WS2812FX::service () {
@@ -654,23 +621,67 @@ void WS2812FX::resetSegments() {
654621 _segment_runtimes[0 ].reset ();
655622}
656623
657- void WS2812FX::populateDefaultSegments () {
658- uint16_t length = 0 ;
659- for (uint8_t i=0 ; i<busses.getNumBusses (); i++) {
660- Bus *bus = busses.getBus (i);
661- if (bus == nullptr ) continue ;
662- _segments[i].start = bus->getStart ();
663- length += bus->getLength ();
664- _segments[i].stop = _segments[i].start + bus->getLength ();
665- _segments[i].mode = DEFAULT_MODE;
666- _segments[i].colors [0 ] = DEFAULT_COLOR;
667- _segments[i].speed = DEFAULT_SPEED;
668- _segments[i].intensity = DEFAULT_INTENSITY;
669- _segments[i].grouping = 1 ;
670- _segments[i].setOption (SEG_OPTION_SELECTED, 1 );
671- _segments[i].setOption (SEG_OPTION_ON, 1 );
672- _segments[i].opacity = 255 ;
624+ void WS2812FX::makeAutoSegments () {
625+ uint16_t segStarts[MAX_NUM_SEGMENTS] = {0 };
626+ uint16_t segStops [MAX_NUM_SEGMENTS] = {0 };
627+
628+ if (autoSegments) { // make one segment per bus
629+ uint8_t s = 0 ;
630+ for (uint8_t i = 0 ; i < busses.getNumBusses (); i++) {
631+ Bus* b = busses.getBus (i);
632+
633+ segStarts[s] = b->getStart ();
634+ segStops[s] = segStarts[s] + b->getLength ();
635+
636+ // check for overlap with previous segments
637+ for (uint8_t j = 0 ; j < s; j++) {
638+ if (segStops[j] > segStarts[s] && segStarts[j] < segStops[s]) {
639+ // segments overlap, merge
640+ segStarts[j] = min (segStarts[s],segStarts[j]);
641+ segStops [j] = max (segStops [s],segStops [j]); segStops[s] = 0 ;
642+ s--;
643+ }
644+ }
645+ s++;
646+ }
647+ for (uint8_t i = 0 ; i < MAX_NUM_SEGMENTS; i++) {
648+ setSegment (i, segStarts[i], segStops[i]);
649+ }
650+ } else {
651+ // expand the main seg to the entire length, but only if there are no other segments
652+ uint8_t mainSeg = getMainSegmentId ();
653+
654+ if (getActiveSegmentsNum () < 2 ) {
655+ setSegment (mainSeg, 0 , _length);
656+ }
657+ }
658+
659+ fixInvalidSegments ();
660+ }
661+
662+ void WS2812FX::fixInvalidSegments () {
663+ // make sure no segment is longer than total (sanity check)
664+ for (uint8_t i = 0 ; i < MAX_NUM_SEGMENTS; i++)
665+ {
666+ if (_segments[i].start >= _length) setSegment (i, 0 , 0 );
667+ if (_segments[i].stop > _length) setSegment (i, _segments[i].start , _length);
668+ }
669+ }
670+
671+ // true if all segments align with a bus, or if a segment covers the total length
672+ bool WS2812FX::checkSegmentAlignment () {
673+ for (uint8_t i = 0 ; i < MAX_NUM_SEGMENTS; i++)
674+ {
675+ if (_segments[i].start >= _segments[i].stop ) continue ; // inactive segment
676+ bool aligned = false ;
677+ for (uint8_t b = 0 ; b<busses.getNumBusses (); b++) {
678+ Bus *bus = busses.getBus (b);
679+ if (_segments[i].start == bus->getStart () && _segments[i].stop == bus->getStart () + bus->getLength ()) aligned = true ;
680+ }
681+ if (_segments[i].start == 0 && _segments[i].stop == _length) aligned = true ;
682+ if (!aligned) return false ;
673683 }
684+ return true ;
674685}
675686
676687// After this function is called, setPixelColor() will use that segment (offsets, grouping, ... will apply)
0 commit comments