Skip to content

Commit abf6e95

Browse files
committed
Fix for low RAM: reduce number of particles dynamically
If PS memory allocation fails, try several times, reducing the number of particles rather than just quitting. This helps with larger setups that may not have enough memory in a contiguous block. Now chances of a PS running are much higher.
1 parent 936e8a0 commit abf6e95

1 file changed

Lines changed: 32 additions & 13 deletions

File tree

wled00/FXparticleSystem.cpp

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -965,17 +965,17 @@ __attribute__((optimize("O2"))) void ParticleSystem2D::collideParticles(PSpartic
965965
// update size and pointers (memory location and size can change dynamically)
966966
// note: do not access the PS class in FX befor running this function (or it messes up SEGENV.data)
967967
void ParticleSystem2D::updateSystem(void) {
968-
PSPRINTLN("updateSystem2D");
968+
//PSPRINTLN("updateSystem2D");
969969
setMatrixSize(SEGMENT.vWidth(), SEGMENT.vHeight());
970970
updatePSpointers(advPartProps != nullptr, advPartSize != nullptr); // update pointers to PS data, also updates availableParticles
971-
PSPRINTLN("\n END update System2D, running FX...");
971+
//PSPRINTLN("\n END update System2D, running FX...");
972972
}
973973

974974
// set the pointers for the class (this only has to be done once and not on every FX call, only the class pointer needs to be reassigned to SEGENV.data every time)
975975
// function returns the pointer to the next byte available for the FX (if it assigned more memory for other stuff using the above allocate function)
976976
// FX handles the PSsources, need to tell this function how many there are
977977
void ParticleSystem2D::updatePSpointers(bool isadvanced, bool sizecontrol) {
978-
PSPRINTLN("updatePSpointers");
978+
//PSPRINTLN("updatePSpointers");
979979
// Note on memory alignment:
980980
// a pointer MUST be 4 byte aligned. sizeof() in a struct/class is always aligned to the largest element. if it contains a 32bit, it will be padded to 4 bytes, 16bit is padded to 2byte alignment.
981981
// The PS is aligned to 4 bytes, a PSparticle is aligned to 2 and a struct containing only byte sized variables is not aligned at all and may need to be padded when dividing the memoryblock.
@@ -1107,17 +1107,26 @@ bool initParticleSystem2D(ParticleSystem2D *&PartSys, uint32_t requestedsources,
11071107

11081108
uint32_t numparticles = calculateNumberOfParticles2D(pixels, advanced, sizecontrol);
11091109
PSPRINT(" segmentsize:" + String(cols) + " x " + String(rows));
1110-
PSPRINT(" request numparticles:" + String(numparticles));
1110+
PSPRINTLN(" request numparticles:" + String(numparticles));
11111111
uint32_t numsources = calculateNumberOfSources2D(pixels, requestedsources);
1112-
if (!allocateParticleSystemMemory2D(numparticles, numsources, advanced, sizecontrol, additionalbytes))
1113-
{
1114-
DEBUG_PRINT(F("PS init failed: memory depleted"));
1115-
return false;
1112+
bool allocsuccess = false;
1113+
while(numparticles >= 4) { // make sure we have at least 4 particles or quit
1114+
if (allocateParticleSystemMemory2D(numparticles, numsources, advanced, sizecontrol, additionalbytes)) {
1115+
PSPRINTLN(F("PS 2D alloc succeeded"));
1116+
allocsuccess = true;
1117+
break; // allocation succeeded
1118+
}
1119+
numparticles /= 2; // cut number of particles in half and try again
1120+
PSPRINTLN(F("PS 2D alloc failed, trying with less particles..."));
1121+
}
1122+
if (!allocsuccess) {
1123+
PSPRINTLN(F("PS 2D alloc failed, not enough memory!"));
1124+
return false; // allocation failed
11161125
}
11171126

11181127
PartSys = new (SEGENV.data) ParticleSystem2D(cols, rows, numparticles, numsources, advanced, sizecontrol); // particle system constructor
11191128

1120-
PSPRINTLN("2D PS init done");
1129+
PSPRINTLN(F("2D PS init done"));
11211130
return true;
11221131
}
11231132

@@ -1760,7 +1769,7 @@ uint32_t calculateNumberOfParticles1D(const uint32_t fraction, const bool isadva
17601769
if (isadvanced) // advanced property array needs ram, reduce number of particles to use the same amount
17611770
numberofParticles = (numberofParticles * sizeof(PSparticle1D)) / (sizeof(PSparticle1D) + sizeof(PSadvancedParticle1D));
17621771
numberofParticles = (numberofParticles * (fraction + 1)) >> 8; // calculate fraction of particles
1763-
numberofParticles = numberofParticles < 20 ? 20 : numberofParticles; // 20 minimum
1772+
numberofParticles = numberofParticles < 10 ? 10 : numberofParticles; // 10 minimum
17641773
//make sure it is a multiple of 4 for proper memory alignment (easier than using padding bytes)
17651774
numberofParticles = (numberofParticles+3) & ~0x03; // note: with a separate particle buffer, this is probably unnecessary
17661775
PSPRINTLN(" calc numparticles:" + String(numberofParticles));
@@ -1797,9 +1806,19 @@ bool initParticleSystem1D(ParticleSystem1D *&PartSys, const uint32_t requestedso
17971806
if (SEGLEN == 1) return false; // single pixel not supported
17981807
uint32_t numparticles = calculateNumberOfParticles1D(fractionofparticles, advanced);
17991808
uint32_t numsources = calculateNumberOfSources1D(requestedsources);
1800-
if (!allocateParticleSystemMemory1D(numparticles, numsources, advanced, additionalbytes)) {
1801-
DEBUG_PRINT(F("PS init failed: memory depleted"));
1802-
return false;
1809+
bool allocsuccess = false;
1810+
while(numparticles >= 10) { // make sure we have at least 10 particles or quit
1811+
if (allocateParticleSystemMemory1D(numparticles, numsources, advanced, additionalbytes)) {
1812+
PSPRINT(F("PS 1D alloc succeeded"));
1813+
allocsuccess = true;
1814+
break; // allocation succeeded
1815+
}
1816+
numparticles /= 2; // cut number of particles in half and try again
1817+
PSPRINTLN(F("PS 1D alloc failed, trying with less particles..."));
1818+
}
1819+
if (!allocsuccess) {
1820+
PSPRINTLN(F("PS init failed: memory depleted"));
1821+
return false; // allocation failed
18031822
}
18041823
PartSys = new (SEGENV.data) ParticleSystem1D(SEGMENT.virtualLength(), numparticles, numsources, advanced); // particle system constructor
18051824
return true;

0 commit comments

Comments
 (0)