Skip to content

Commit 8e321de

Browse files
authored
Merge branch 'wled:main' into clean-scheduling
2 parents de9630e + e2f5bec commit 8e321de

File tree

11 files changed

+294
-252
lines changed

11 files changed

+294
-252
lines changed

wled00/FX.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8837,7 +8837,7 @@ uint16_t mode_particleGEQ(void) {
88378837
//set particle properties TODO: could also use the spray...
88388838
PartSys->particles[i].ttl = 20 + map(SEGMENT.intensity, 0,255, emitspeed>>1, emitspeed + hw_random16(emitspeed)) ; // set particle alive, particle lifespan is in number of frames
88398839
PartSys->particles[i].x = xposition + hw_random16(binwidth) - (binwidth>>1); // position randomly, deviating half a bin width
8840-
PartSys->particles[i].y = PS_P_RADIUS; // start at the bottom (PS_P_RADIUS is minimum position a particle is fully in frame)
8840+
PartSys->particles[i].y = 0; // start at the bottom
88418841
PartSys->particles[i].vx = hw_random16(SEGMENT.custom1>>1)-(SEGMENT.custom1>>2) ; //x-speed variation: +/- custom1/4
88428842
PartSys->particles[i].vy = emitspeed;
88438843
PartSys->particles[i].hue = (bin<<4) + hw_random16(17) - 8; // color from palette according to bin

wled00/FX.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,7 @@ class Segment {
686686

687687
// 1D strip
688688
uint16_t virtualLength() const;
689+
uint16_t maxMappingLength() const;
689690
[[gnu::hot]] void setPixelColor(int n, uint32_t c) const; // set relative pixel within segment with color
690691
inline void setPixelColor(unsigned n, uint32_t c) const { setPixelColor(int(n), c); }
691692
inline void setPixelColor(int n, byte r, byte g, byte b, byte w = 0) const { setPixelColor(n, RGBW32(r,g,b,w)); }
@@ -808,6 +809,8 @@ class Segment {
808809
inline void wu_pixel(uint32_t x, uint32_t y, CRGB c) {}
809810
#endif
810811
friend class WS2812FX;
812+
friend class ParticleSystem2D;
813+
friend class ParticleSystem1D;
811814
};
812815

813816
// main "strip" class (108 bytes)

wled00/FX_fcn.cpp

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,16 @@ bool Segment::allocateData(size_t len) {
159159
return false;
160160
}
161161
// prefer DRAM over SPI RAM on ESP32 since it is slow
162-
if (data) data = (byte*)d_realloc(data, len);
163-
else data = (byte*)d_malloc(len);
162+
if (data) {
163+
data = (byte*)d_realloc_malloc(data, len); // realloc with malloc fallback
164+
if (!data) {
165+
data = nullptr;
166+
Segment::addUsedSegmentData(-_dataLen); // subtract original buffer size
167+
_dataLen = 0; // reset data length
168+
}
169+
}
170+
else data = (byte*)d_malloc(len);
171+
164172
if (data) {
165173
memset(data, 0, len); // erase buffer
166174
Segment::addUsedSegmentData(len - _dataLen);
@@ -170,7 +178,6 @@ bool Segment::allocateData(size_t len) {
170178
}
171179
// allocation failed
172180
DEBUG_PRINTLN(F("!!! Allocation failed. !!!"));
173-
Segment::addUsedSegmentData(-_dataLen); // subtract original buffer size
174181
errorFlag = ERR_NORAM;
175182
return false;
176183
}
@@ -449,8 +456,8 @@ void Segment::setGeometry(uint16_t i1, uint16_t i2, uint8_t grp, uint8_t spc, ui
449456
}
450457
// re-allocate FX render buffer
451458
if (length() != oldLength) {
452-
if (pixels) pixels = static_cast<uint32_t*>(d_realloc(pixels, sizeof(uint32_t) * length()));
453-
else pixels = static_cast<uint32_t*>(d_malloc(sizeof(uint32_t) * length()));
459+
if (pixels) d_free(pixels); // using realloc on large buffers can cause additional fragmentation instead of reducing it
460+
pixels = static_cast<uint32_t*>(d_malloc(sizeof(uint32_t) * length()));
454461
if (!pixels) {
455462
DEBUG_PRINTLN(F("!!! Not enough RAM for pixel buffer !!!"));
456463
errorFlag = ERR_NORAM_PX;
@@ -563,8 +570,8 @@ Segment &Segment::setName(const char *newName) {
563570
if (newName) {
564571
const int newLen = min(strlen(newName), (size_t)WLED_MAX_SEGNAME_LEN);
565572
if (newLen) {
566-
if (name) name = static_cast<char*>(d_realloc(name, newLen+1));
567-
else name = static_cast<char*>(d_malloc(newLen+1));
573+
if (name) d_free(name); // free old name
574+
name = static_cast<char*>(d_malloc(newLen+1));
568575
if (name) strlcpy(name, newName, newLen+1);
569576
name[newLen] = 0;
570577
return *this;
@@ -645,6 +652,14 @@ uint16_t Segment::virtualLength() const {
645652
return vLength;
646653
}
647654

655+
#ifndef WLED_DISABLE_2D
656+
// maximum length of a mapped 1D segment, used in PS for buffer allocation
657+
uint16_t Segment::maxMappingLength() const {
658+
uint32_t vW = virtualWidth();
659+
uint32_t vH = virtualHeight();
660+
return max(sqrt32_bw(vH*vH + vW*vW), (uint32_t)getPinwheelLength(vW, vH)); // use diagonal
661+
}
662+
#endif
648663
// pixel is clipped if it falls outside clipping range
649664
// if clipping start > stop the clipping range is inverted
650665
bool IRAM_ATTR_YN Segment::isPixelClipped(int i) const {
@@ -729,8 +744,8 @@ void IRAM_ATTR_YN Segment::setPixelColor(int i, uint32_t col) const
729744
}
730745
break;
731746
case M12_pCorner:
732-
for (int x = 0; x <= i; x++) setPixelColorRaw(XY(x, i), col);
733-
for (int y = 0; y < i; y++) setPixelColorRaw(XY(i, y), col);
747+
for (int x = 0; x <= i; x++) setPixelColorXY(x, i, col); // note: <= to include i=0. Relies on overflow check in sPC()
748+
for (int y = 0; y < i; y++) setPixelColorXY(i, y, col);
734749
break;
735750
case M12_sPinwheel: {
736751
// Uses Bresenham's algorithm to place coordinates of two lines in arrays then draws between them
@@ -1139,21 +1154,27 @@ void WS2812FX::finalizeInit() {
11391154
#if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3)
11401155
// determine if it is sensible to use parallel I2S outputs on ESP32 (i.e. more than 5 outputs = 1 I2S + 4 RMT)
11411156
unsigned maxLedsOnBus = 0;
1157+
unsigned busType = 0;
11421158
for (const auto &bus : busConfigs) {
11431159
if (Bus::isDigital(bus.type) && !Bus::is2Pin(bus.type)) {
11441160
digitalCount++;
1161+
if (busType == 0) busType = bus.type; // remember first bus type
1162+
if (busType != bus.type) {
1163+
DEBUG_PRINTF_P(PSTR("Mixed digital bus types detected! Forcing single I2S output.\n"));
1164+
useParallelI2S = false; // mixed bus types, no parallel I2S
1165+
}
11451166
if (bus.count > maxLedsOnBus) maxLedsOnBus = bus.count;
11461167
}
11471168
}
11481169
DEBUG_PRINTF_P(PSTR("Maximum LEDs on a bus: %u\nDigital buses: %u\n"), maxLedsOnBus, digitalCount);
1149-
// we may remove 300 LEDs per bus limit when NeoPixelBus is updated beyond 2.9.0
1150-
if (maxLedsOnBus <= 300 && useParallelI2S) BusManager::useParallelOutput(); // must call before creating buses
1170+
// we may remove 600 LEDs per bus limit when NeoPixelBus is updated beyond 2.8.3
1171+
if (maxLedsOnBus <= 600 && useParallelI2S) BusManager::useParallelOutput(); // must call before creating buses
11511172
else useParallelI2S = false; // enforce single I2S
1173+
digitalCount = 0;
11521174
#endif
11531175

11541176
// create buses/outputs
11551177
unsigned mem = 0;
1156-
digitalCount = 0;
11571178
for (const auto &bus : busConfigs) {
11581179
mem += bus.memUsage(Bus::isDigital(bus.type) && !Bus::is2Pin(bus.type) ? digitalCount++ : 0); // includes global buffer
11591180
if (mem <= MAX_LED_MEMORY) {
@@ -1189,8 +1210,8 @@ void WS2812FX::finalizeInit() {
11891210
deserializeMap(); // (re)load default ledmap (will also setUpMatrix() if ledmap does not exist)
11901211

11911212
// allocate frame buffer after matrix has been set up (gaps!)
1192-
if (_pixels) _pixels = static_cast<uint32_t*>(d_realloc(_pixels, getLengthTotal() * sizeof(uint32_t)));
1193-
else _pixels = static_cast<uint32_t*>(d_malloc(getLengthTotal() * sizeof(uint32_t)));
1213+
if (_pixels) d_free(_pixels); // using realloc on large buffers can cause additional fragmentation instead of reducing it
1214+
_pixels = static_cast<uint32_t*>(d_malloc(getLengthTotal() * sizeof(uint32_t)));
11941215
DEBUG_PRINTF_P(PSTR("strip buffer size: %uB\n"), getLengthTotal() * sizeof(uint32_t));
11951216

11961217
DEBUG_PRINTF_P(PSTR("Heap after strip init: %uB\n"), ESP.getFreeHeap());
@@ -1677,7 +1698,7 @@ void WS2812FX::setTransitionMode(bool t) {
16771698

16781699
// wait until frame is over (service() has finished or time for 1 frame has passed; yield() crashes on 8266)
16791700
void WS2812FX::waitForIt() {
1680-
unsigned long maxWait = millis() + getFrameTime();
1701+
unsigned long maxWait = millis() + getFrameTime() + 100; // TODO: this needs a proper fix for timeout!
16811702
while (isServicing() && maxWait > millis()) delay(1);
16821703
#ifdef WLED_DEBUG
16831704
if (millis() >= maxWait) DEBUG_PRINTLN(F("Waited for strip to finish servicing."));

0 commit comments

Comments
 (0)