@@ -143,27 +143,28 @@ Segment& Segment::operator= (Segment &&orig) noexcept {
143143 return *this ;
144144}
145145
146+ // allocates effect data buffer on heap and initialises (erases) it
146147bool IRAM_ATTR Segment::allocateData (size_t len) {
148+ if (len == 0 ) return false ; // nothing to do
147149 if (data && _dataLen >= len) { // already allocated enough (reduce fragmentation)
148150 if (call == 0 ) memset (data, 0 , len); // erase buffer if called during effect initialisation
149151 return true ;
150152 }
151153 // DEBUG_PRINTF("-- Allocating data (%d): %p\n", len, this);
152- deallocateData ();
153- if (len == 0 ) return false ; // nothing to do
154+ deallocateData (); // if the old buffer was smaller release it first
154155 if (Segment::getUsedSegmentData () + len > MAX_SEGMENT_DATA) {
155156 // not enough memory
156157 DEBUG_PRINT (F (" !!! Effect RAM depleted: " ));
157158 DEBUG_PRINTF (" %d/%d !!!\n " , len, Segment::getUsedSegmentData ());
159+ errorFlag = ERR_NORAM;
158160 return false ;
159161 }
160162 // do not use SPI RAM on ESP32 since it is slow
161- data = (byte*) malloc (len);
163+ data = (byte*)calloc (len, sizeof (byte) );
162164 if (!data) { DEBUG_PRINTLN (F (" !!! Allocation failed. !!!" )); return false ; } // allocation failed
163165 Segment::addUsedSegmentData (len);
164166 // DEBUG_PRINTF("--- Allocated data (%p): %d/%d -> %p\n", this, len, Segment::getUsedSegmentData(), data);
165167 _dataLen = len;
166- memset (data, 0 , len);
167168 return true ;
168169}
169170
@@ -194,7 +195,7 @@ void IRAM_ATTR Segment::deallocateData() {
194195void Segment::resetIfRequired () {
195196 if (!reset) return ;
196197 // DEBUG_PRINTF("-- Segment reset: %p\n", this);
197- deallocateData ();
198+ if (data && _dataLen > 0 ) memset (data, 0 , _dataLen); // prevent heap fragmentation (just erase buffer instead of deallocateData())
198199 next_time = 0 ; step = 0 ; call = 0 ; aux0 = 0 ; aux1 = 0 ;
199200 reset = false ;
200201}
@@ -561,35 +562,36 @@ void Segment::setOption(uint8_t n, bool val) {
561562}
562563
563564void Segment::setMode (uint8_t fx, bool loadDefaults) {
565+ // skip reserved
566+ while (fx < strip.getModeCount () && strncmp_P (" RSVD" , strip.getModeData (fx), 4 ) == 0 ) fx++;
567+ if (fx >= strip.getModeCount ()) fx = 0 ; // set solid mode
564568 // if we have a valid mode & is not reserved
565- if (fx < strip.getModeCount () && strncmp_P (" RSVD" , strip.getModeData (fx), 4 )) {
566- if (fx != mode) {
569+ if (fx != mode) {
567570#ifndef WLED_DISABLE_MODE_BLEND
568- if (modeBlending) startTransition (strip.getTransition ()); // set effect transitions
571+ if (modeBlending) startTransition (strip.getTransition ()); // set effect transitions
569572#endif
570- mode = fx;
571- // load default values from effect string
572- if (loadDefaults) {
573- int16_t sOpt ;
574- sOpt = extractModeDefaults (fx, " sx" ); speed = (sOpt >= 0 ) ? sOpt : DEFAULT_SPEED;
575- sOpt = extractModeDefaults (fx, " ix" ); intensity = (sOpt >= 0 ) ? sOpt : DEFAULT_INTENSITY;
576- sOpt = extractModeDefaults (fx, " c1" ); custom1 = (sOpt >= 0 ) ? sOpt : DEFAULT_C1;
577- sOpt = extractModeDefaults (fx, " c2" ); custom2 = (sOpt >= 0 ) ? sOpt : DEFAULT_C2;
578- sOpt = extractModeDefaults (fx, " c3" ); custom3 = (sOpt >= 0 ) ? sOpt : DEFAULT_C3;
579- sOpt = extractModeDefaults (fx, " o1" ); check1 = (sOpt >= 0 ) ? (bool )sOpt : false ;
580- sOpt = extractModeDefaults (fx, " o2" ); check2 = (sOpt >= 0 ) ? (bool )sOpt : false ;
581- sOpt = extractModeDefaults (fx, " o3" ); check3 = (sOpt >= 0 ) ? (bool )sOpt : false ;
582- sOpt = extractModeDefaults (fx, " m12" ); if (sOpt >= 0 ) map1D2D = constrain (sOpt , 0 , 7 ); else map1D2D = M12_Pixels; // reset mapping if not defined (2D FX may not work)
583- sOpt = extractModeDefaults (fx, " si" ); if (sOpt >= 0 ) soundSim = constrain (sOpt , 0 , 3 );
584- sOpt = extractModeDefaults (fx, " rev" ); if (sOpt >= 0 ) reverse = (bool )sOpt ;
585- sOpt = extractModeDefaults (fx, " mi" ); if (sOpt >= 0 ) mirror = (bool )sOpt ; // NOTE: setting this option is a risky business
586- sOpt = extractModeDefaults (fx, " rY" ); if (sOpt >= 0 ) reverse_y = (bool )sOpt ;
587- sOpt = extractModeDefaults (fx, " mY" ); if (sOpt >= 0 ) mirror_y = (bool )sOpt ; // NOTE: setting this option is a risky business
588- sOpt = extractModeDefaults (fx, " pal" ); if (sOpt >= 0 ) setPalette (sOpt ); // else setPalette(0);
589- }
590- markForReset ();
591- stateChanged = true ; // send UDP/WS broadcast
573+ mode = fx;
574+ // load default values from effect string
575+ if (loadDefaults) {
576+ int16_t sOpt ;
577+ sOpt = extractModeDefaults (fx, " sx" ); speed = (sOpt >= 0 ) ? sOpt : DEFAULT_SPEED;
578+ sOpt = extractModeDefaults (fx, " ix" ); intensity = (sOpt >= 0 ) ? sOpt : DEFAULT_INTENSITY;
579+ sOpt = extractModeDefaults (fx, " c1" ); custom1 = (sOpt >= 0 ) ? sOpt : DEFAULT_C1;
580+ sOpt = extractModeDefaults (fx, " c2" ); custom2 = (sOpt >= 0 ) ? sOpt : DEFAULT_C2;
581+ sOpt = extractModeDefaults (fx, " c3" ); custom3 = (sOpt >= 0 ) ? sOpt : DEFAULT_C3;
582+ sOpt = extractModeDefaults (fx, " o1" ); check1 = (sOpt >= 0 ) ? (bool )sOpt : false ;
583+ sOpt = extractModeDefaults (fx, " o2" ); check2 = (sOpt >= 0 ) ? (bool )sOpt : false ;
584+ sOpt = extractModeDefaults (fx, " o3" ); check3 = (sOpt >= 0 ) ? (bool )sOpt : false ;
585+ sOpt = extractModeDefaults (fx, " m12" ); if (sOpt >= 0 ) map1D2D = constrain (sOpt , 0 , 7 ); else map1D2D = M12_Pixels; // reset mapping if not defined (2D FX may not work)
586+ sOpt = extractModeDefaults (fx, " si" ); if (sOpt >= 0 ) soundSim = constrain (sOpt , 0 , 3 );
587+ sOpt = extractModeDefaults (fx, " rev" ); if (sOpt >= 0 ) reverse = (bool )sOpt ;
588+ sOpt = extractModeDefaults (fx, " mi" ); if (sOpt >= 0 ) mirror = (bool )sOpt ; // NOTE: setting this option is a risky business
589+ sOpt = extractModeDefaults (fx, " rY" ); if (sOpt >= 0 ) reverse_y = (bool )sOpt ;
590+ sOpt = extractModeDefaults (fx, " mY" ); if (sOpt >= 0 ) mirror_y = (bool )sOpt ; // NOTE: setting this option is a risky business
591+ sOpt = extractModeDefaults (fx, " pal" ); if (sOpt >= 0 ) setPalette (sOpt ); // else setPalette(0);
592592 }
593+ markForReset ();
594+ stateChanged = true ; // send UDP/WS broadcast
593595 }
594596}
595597
@@ -751,10 +753,10 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
751753 uint32_t tmpCol = col;
752754 // set all the pixels in the group
753755 for (int j = 0 ; j < grouping; j++) {
754- uint16_t indexSet = i + ((reverse) ? -j : j);
756+ unsigned indexSet = i + ((reverse) ? -j : j);
755757 if (indexSet >= start && indexSet < stop) {
756758 if (mirror) { // set the corresponding mirrored pixel
757- uint16_t indexMir = stop - indexSet + start - 1 ;
759+ unsigned indexMir = stop - indexSet + start - 1 ;
758760 indexMir += offset; // offset/phase
759761 if (indexMir >= stop) indexMir -= len; // wrap
760762#ifndef WLED_DISABLE_MODE_BLEND
@@ -1121,17 +1123,14 @@ void WS2812FX::finalizeInit(void) {
11211123 #endif
11221124 }
11231125
1124- if (isMatrix) setUpMatrix ();
1125- else {
1126- Segment::maxWidth = _length;
1127- Segment::maxHeight = 1 ;
1128- }
1126+ Segment::maxWidth = _length;
1127+ Segment::maxHeight = 1 ;
11291128
11301129 // segments are created in makeAutoSegments();
11311130 DEBUG_PRINTLN (F (" Loading custom palettes" ));
11321131 loadCustomPalettes (); // (re)load all custom palettes
11331132 DEBUG_PRINTLN (F (" Loading custom ledmaps" ));
1134- deserializeMap (); // (re)load default ledmap
1133+ deserializeMap (); // (re)load default ledmap (will also setUpMatrix() if ledmap does not exist)
11351134}
11361135
11371136void WS2812FX::service () {
@@ -1210,7 +1209,7 @@ void WS2812FX::service() {
12101209 #endif
12111210}
12121211
1213- void IRAM_ATTR WS2812FX::setPixelColor (int i, uint32_t col) {
1212+ void IRAM_ATTR WS2812FX::setPixelColor (unsigned i, uint32_t col) {
12141213 if (i < customMappingSize) i = customMappingTable[i];
12151214 if (i >= _length) return ;
12161215 busses.setPixelColor (i, col);
@@ -1658,41 +1657,30 @@ bool WS2812FX::deserializeMap(uint8_t n) {
16581657 strcat_P (fileName, PSTR (" .json" ));
16591658 bool isFile = WLED_FS.exists (fileName);
16601659
1661- if (!isFile) {
1662- // erase custom mapping if selecting nonexistent ledmap.json (n==0)
1663- if (!isMatrix && !n && customMappingTable != nullptr ) {
1664- customMappingSize = 0 ;
1665- delete[] customMappingTable;
1666- customMappingTable = nullptr ;
1667- }
1660+ customMappingSize = 0 ; // prevent use of mapping if anything goes wrong
1661+
1662+ if (!isFile && n==0 && isMatrix) {
1663+ setUpMatrix ();
16681664 return false ;
16691665 }
16701666
1671- if (!requestJSONBufferLock (7 )) return false ;
1667+ if (!isFile || ! requestJSONBufferLock (7 )) return false ; // this will trigger setUpMatrix() when called from wled.cpp
16721668
16731669 if (!readObjectFromFile (fileName, nullptr , pDoc)) {
1670+ DEBUG_PRINT (F (" ERROR Invalid ledmap in " )); DEBUG_PRINTLN (fileName);
16741671 releaseJSONBufferLock ();
1675- return false ; // if file does not exist just exit
1672+ return false ; // if file does not load properly then exit
16761673 }
16771674
1678- DEBUG_PRINT (F (" Reading LED map from " ));
1679- DEBUG_PRINTLN (fileName);
1675+ DEBUG_PRINT (F (" Reading LED map from " )); DEBUG_PRINTLN (fileName);
16801676
1681- // erase old custom ledmap
1682- if (customMappingTable != nullptr ) {
1683- customMappingSize = 0 ;
1684- delete[] customMappingTable;
1685- customMappingTable = nullptr ;
1686- }
1677+ if (customMappingTable == nullptr ) customMappingTable = new uint16_t [getLengthTotal ()];
16871678
16881679 JsonObject root = pDoc->as <JsonObject>();
16891680 JsonArray map = root[F (" map" )];
16901681 if (!map.isNull () && map.size ()) { // not an empty map
1691- customMappingSize = map.size ();
1692- customMappingTable = new uint16_t [customMappingSize];
1693- for (unsigned i=0 ; i<customMappingSize; i++) {
1694- customMappingTable[i] = (uint16_t ) (map[i]<0 ? 0xFFFFU : map[i]);
1695- }
1682+ customMappingSize = min ((unsigned )map.size (), (unsigned )getLengthTotal ());
1683+ for (unsigned i=0 ; i<customMappingSize; i++) customMappingTable[i] = (uint16_t ) (map[i]<0 ? 0xFFFFU : map[i]);
16961684 }
16971685
16981686 releaseJSONBufferLock ();
0 commit comments