Skip to content

Commit d3be7a3

Browse files
committed
Merge branch '0_15' into psram-4-json
2 parents 7971f3c + 6cd0da8 commit d3be7a3

File tree

16 files changed

+1644
-1659
lines changed

16 files changed

+1644
-1659
lines changed

wled00/FX.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5292,7 +5292,6 @@ uint16_t mode_2Dmatrix(void) { // Matrix2D. By Jeremy Williams.
52925292
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
52935293

52945294
if (SEGENV.call == 0) {
5295-
memset(SEGMENT.data, 0, dataSize); // no falling spawns
52965295
SEGMENT.fill(BLACK);
52975296
SEGENV.step = 0;
52985297
}

wled00/FX.h

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -543,9 +543,9 @@ typedef struct Segment {
543543

544544
// runtime data functions
545545
inline uint16_t dataSize(void) const { return _dataLen; }
546-
bool allocateData(size_t len);
547-
void deallocateData(void);
548-
void resetIfRequired(void);
546+
bool allocateData(size_t len); // allocates effect data buffer in heap and clears it
547+
void deallocateData(void); // deallocates (frees) effect data buffer from heap
548+
void resetIfRequired(void); // sets all SEGENV variables to 0 and clears data buffer
549549
/**
550550
* Flags that before the next effect is calculated,
551551
* the internal segment state should be reset.
@@ -559,10 +559,10 @@ typedef struct Segment {
559559
void stopTransition(void);
560560
void handleTransition(void);
561561
#ifndef WLED_DISABLE_MODE_BLEND
562-
void swapSegenv(tmpsegd_t &tmpSegD);
563-
void restoreSegenv(tmpsegd_t &tmpSegD);
562+
void swapSegenv(tmpsegd_t &tmpSegD); // copies segment data into specifed buffer, if buffer is not a transition buffer, segment data is overwritten from transition buffer
563+
void restoreSegenv(tmpsegd_t &tmpSegD); // restores segment data from buffer, if buffer is not transition buffer, changed values are copied to transition buffer
564564
#endif
565-
uint16_t progress(void); //transition progression between 0-65535
565+
uint16_t progress(void); // transition progression between 0-65535
566566
uint8_t currentBri(bool useCct = false);
567567
uint8_t currentMode(void);
568568
uint32_t currentColor(uint8_t slot);
@@ -760,7 +760,7 @@ class WS2812FX { // 96 bytes
760760
resetSegments(),
761761
makeAutoSegments(bool forceReset = false),
762762
fixInvalidSegments(),
763-
setPixelColor(int n, uint32_t c),
763+
setPixelColor(unsigned n, uint32_t c),
764764
show(void),
765765
setTargetFps(uint8_t fps),
766766
addEffect(uint8_t id, mode_ptr mode_fn, const char *mode_name), // add effect to the list; defined in FX.cpp
@@ -769,10 +769,10 @@ class WS2812FX { // 96 bytes
769769
inline void restartRuntime() { for (Segment &seg : _segments) seg.markForReset(); }
770770
inline void setTransitionMode(bool t) { for (Segment &seg : _segments) seg.startTransition(t ? _transitionDur : 0); }
771771
inline void setColor(uint8_t slot, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0) { setColor(slot, RGBW32(r,g,b,w)); }
772-
inline void fill(uint32_t c) { for (int i = 0; i < getLengthTotal(); i++) setPixelColor(i, c); } // fill whole strip with color (inline)
772+
inline void fill(uint32_t c) { for (unsigned i = 0; i < getLengthTotal(); i++) setPixelColor(i, c); } // fill whole strip with color (inline)
773773
// outsmart the compiler :) by correctly overloading
774-
inline void setPixelColor(int n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0) { setPixelColor(n, RGBW32(r,g,b,w)); }
775-
inline void setPixelColor(int n, CRGB c) { setPixelColor(n, c.red, c.green, c.blue); }
774+
inline void setPixelColor(unsigned n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0) { setPixelColor(n, RGBW32(r,g,b,w)); }
775+
inline void setPixelColor(unsigned n, CRGB c) { setPixelColor(n, c.red, c.green, c.blue); }
776776
inline void trigger(void) { _triggered = true; } // Forces the next frame to be computed on all active segments.
777777
inline void setShowCallback(show_callback cb) { _callback = cb; }
778778
inline void setTransition(uint16_t t) { _transitionDur = t; }
@@ -878,7 +878,7 @@ class WS2812FX { // 96 bytes
878878
void setUpMatrix();
879879

880880
// outsmart the compiler :) by correctly overloading
881-
inline void setPixelColorXY(int x, int y, uint32_t c) { setPixelColor(y * Segment::maxWidth + x, c); }
881+
inline void setPixelColorXY(int x, int y, uint32_t c) { setPixelColor((unsigned)(y * Segment::maxWidth + x), c); }
882882
inline void setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0) { setPixelColorXY(x, y, RGBW32(r,g,b,w)); }
883883
inline void setPixelColorXY(int x, int y, CRGB c) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0)); }
884884

wled00/FX_2Dfcn.cpp

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,9 @@
3636
// so matrix should disable regular ledmap processing
3737
void WS2812FX::setUpMatrix() {
3838
#ifndef WLED_DISABLE_2D
39-
// erase old ledmap, just in case.
40-
if (customMappingTable != nullptr) delete[] customMappingTable;
41-
customMappingTable = nullptr;
42-
customMappingSize = 0;
43-
4439
// isMatrix is set in cfg.cpp or set.cpp
4540
if (isMatrix) {
46-
// calculate width dynamically because it will have gaps
41+
// calculate width dynamically because it may have gaps
4742
Segment::maxWidth = 1;
4843
Segment::maxHeight = 1;
4944
for (size_t i = 0; i < panel.size(); i++) {
@@ -68,15 +63,17 @@ void WS2812FX::setUpMatrix() {
6863
return;
6964
}
7065

71-
customMappingTable = new uint16_t[Segment::maxWidth * Segment::maxHeight];
66+
customMappingSize = 0; // prevent use of mapping if anything goes wrong
67+
68+
if (customMappingTable == nullptr) customMappingTable = new uint16_t[getLengthTotal()];
7269

7370
if (customMappingTable != nullptr) {
74-
customMappingSize = Segment::maxWidth * Segment::maxHeight;
71+
customMappingSize = getLengthTotal();
7572

7673
// fill with empty in case we don't fill the entire matrix
77-
for (size_t i = 0; i< customMappingSize; i++) {
78-
customMappingTable[i] = (uint16_t)-1;
79-
}
74+
unsigned matrixSize = Segment::maxWidth * Segment::maxHeight;
75+
for (unsigned i = 0; i<matrixSize; i++) customMappingTable[i] = 0xFFFFU;
76+
for (unsigned i = matrixSize; i<getLengthTotal(); i++) customMappingTable[i] = i; // trailing LEDs for ledmap (after matrix) if it exist
8077

8178
// we will try to load a "gap" array (a JSON file)
8279
// the array has to have the same amount of values as mapping array (or larger)
@@ -101,7 +98,7 @@ void WS2812FX::setUpMatrix() {
10198
// 1 ... active pixel (it will count and will be mapped)
10299
JsonArray map = pDoc->as<JsonArray>();
103100
gapSize = map.size();
104-
if (!map.isNull() && gapSize >= customMappingSize) { // not an empty map
101+
if (!map.isNull() && gapSize >= matrixSize) { // not an empty map
105102
gapTable = new int8_t[gapSize];
106103
if (gapTable) for (size_t i = 0; i < gapSize; i++) {
107104
gapTable[i] = constrain(map[i], -1, 1);

wled00/FX_fcn.cpp

Lines changed: 49 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -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
146147
bool 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() {
194195
void 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

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

11371136
void 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();

wled00/bus_manager.cpp

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -258,23 +258,8 @@ void BusDigital::setBrightness(uint8_t b) {
258258
if (_pins[0] == LED_BUILTIN || _pins[1] == LED_BUILTIN) reinit();
259259
}
260260
#endif
261-
uint8_t prevBri = _bri;
262261
Bus::setBrightness(b);
263262
PolyBus::setBrightness(_busPtr, _iType, b);
264-
/*
265-
if (_data) return; // use _buffering this causes ~20% FPS drop
266-
267-
// must update/repaint every LED in the NeoPixelBus buffer to the new brightness
268-
// the only case where repainting is unnecessary is when all pixels are set after the brightness change but before the next show
269-
// (which we can't rely on)
270-
uint16_t hwLen = _len;
271-
if (_type == TYPE_WS2812_1CH_X3) hwLen = NUM_ICS_WS2812_1CH_3X(_len); // only needs a third of "RGB" LEDs for NeoPixelBus
272-
for (unsigned i = 0; i < hwLen; i++) {
273-
// use 0 as color order, actual order does not matter here as we just update the channel values as-is
274-
uint32_t c = restoreColorLossy(PolyBus::getPixelColor(_busPtr, _iType, i, 0), prevBri);
275-
PolyBus::setPixelColor(_busPtr, _iType, i, c, 0);
276-
}
277-
*/
278263
}
279264

280265
//If LEDs are skipped, it is possible to use the first as a status LED.

wled00/cfg.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
7979

8080
noWifiSleep = doc[F("wifi")][F("sleep")] | !noWifiSleep; // inverted
8181
noWifiSleep = !noWifiSleep;
82-
//int wifi_phy = doc[F("wifi")][F("phy")]; //force phy mode n?
82+
force802_3g = doc[F("wifi")][F("phy")] | force802_3g; //force phy mode g?
8383

8484
JsonObject hw = doc[F("hw")];
8585

@@ -695,7 +695,7 @@ void serializeConfig() {
695695

696696
JsonObject wifi = root.createNestedObject("wifi");
697697
wifi[F("sleep")] = !noWifiSleep;
698-
//wifi[F("phy")] = 1;
698+
wifi[F("phy")] = (int)force802_3g;
699699

700700
#ifdef WLED_USE_ETHERNET
701701
JsonObject ethernet = root.createNestedObject("eth");

wled00/const.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,7 @@
345345
#define ERR_CONCURRENCY 2 // Conurrency (client active)
346346
#define ERR_NOBUF 3 // JSON buffer was not released in time, request cannot be handled at this time
347347
#define ERR_NOT_IMPL 4 // Not implemented
348+
#define ERR_NORAM 8 // effect RAM depleted
348349
#define ERR_JSON 9 // JSON parsing failed (input too large?)
349350
#define ERR_FS_BEGIN 10 // Could not init filesystem (no partition?)
350351
#define ERR_FS_QUOTA 11 // The FS is full or the maximum file size is reached

0 commit comments

Comments
 (0)