Skip to content

Commit 4d39dd0

Browse files
DedeHaiblazoncek
andauthored
Fix LED buffer size calculation (wled#4928)
* Attempt at better bus memory calculation and estimation * Remov double buffer count for ESP8266 (thanks @DedeHai) * improve UI calculation * adding mendatory LED buffers to UI memory calculation * adding buffer for transitions to memory calculation, change "error" to "warning" * bugfixes in settings_leds.htm * fix getDataSize() forESP8266, ESP8266 does not use double buffering. * update led settings: fix parsing by @blazoncek * new warnings for LED buffer use, deny adding a bus if it exceeds limits * adds recommendations for users (reboot, disable transitions) Co-authored-by: Blaž Kristan <[email protected]>
1 parent 15ba01a commit 4d39dd0

File tree

5 files changed

+203
-183
lines changed

5 files changed

+203
-183
lines changed

wled00/FX_fcn.cpp

100755100644
Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1178,17 +1178,42 @@ void WS2812FX::finalizeInit() {
11781178
digitalCount = 0;
11791179
#endif
11801180

1181+
DEBUG_PRINTF_P(PSTR("Heap before buses: %d\n"), getFreeHeapSize());
11811182
// create buses/outputs
11821183
unsigned mem = 0;
1184+
unsigned maxI2S = 0;
11831185
for (const auto &bus : busConfigs) {
1184-
mem += bus.memUsage(Bus::isDigital(bus.type) && !Bus::is2Pin(bus.type) ? digitalCount++ : 0); // includes global buffer
1185-
if (mem <= MAX_LED_MEMORY) {
1186-
if (BusManager::add(bus) == -1) break;
1186+
unsigned memB = bus.memUsage(Bus::isDigital(bus.type) && !Bus::is2Pin(bus.type) ? digitalCount++ : 0); // does not include DMA/RMT buffer
1187+
mem += memB;
1188+
// estimate maximum I2S memory usage (only relevant for digital non-2pin busses)
1189+
#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(ESP8266)
1190+
#if defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S3)
1191+
const bool usesI2S = ((useParallelI2S && digitalCount <= 8) || (!useParallelI2S && digitalCount == 1));
1192+
#elif defined(CONFIG_IDF_TARGET_ESP32S2)
1193+
const bool usesI2S = (useParallelI2S && digitalCount <= 8);
1194+
#else
1195+
const bool usesI2S = false;
1196+
#endif
1197+
if (Bus::isDigital(bus.type) && !Bus::is2Pin(bus.type) && usesI2S) {
1198+
#ifdef NPB_CONF_4STEP_CADENCE
1199+
constexpr unsigned stepFactor = 4; // 4 step cadence (4 bits per pixel bit)
1200+
#else
1201+
constexpr unsigned stepFactor = 3; // 3 step cadence (3 bits per pixel bit)
1202+
#endif
1203+
unsigned i2sCommonSize = stepFactor * bus.count * (3*Bus::hasRGB(bus.type)+Bus::hasWhite(bus.type)+Bus::hasCCT(bus.type)) * (Bus::is16bit(bus.type)+1);
1204+
if (i2sCommonSize > maxI2S) maxI2S = i2sCommonSize;
1205+
}
1206+
#endif
1207+
if (mem + maxI2S <= MAX_LED_MEMORY) {
1208+
BusManager::add(bus);
1209+
DEBUG_PRINTF_P(PSTR("Bus memory: %uB\n"), memB);
11871210
} else {
11881211
errorFlag = ERR_NORAM_PX; // alert UI
11891212
DEBUG_PRINTF_P(PSTR("Out of LED memory! Bus %d (%d) #%u not created."), (int)bus.type, (int)bus.count, digitalCount);
1213+
break;
11901214
}
11911215
}
1216+
DEBUG_PRINTF_P(PSTR("LED buffer size: %uB/%uB\n"), mem + maxI2S, BusManager::memUsage());
11921217
busConfigs.clear();
11931218
busConfigs.shrink_to_fit();
11941219

wled00/bus_manager.cpp

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ size_t BusDigital::getPins(uint8_t* pinArray) const {
354354
}
355355

356356
size_t BusDigital::getBusSize() const {
357-
return sizeof(BusDigital) + (isOk() ? PolyBus::getDataSize(_busPtr, _iType) : 0);
357+
return sizeof(BusDigital) + (isOk() ? PolyBus::getDataSize(_busPtr, _iType) : 0); // does not include common I2S DMA buffer
358358
}
359359

360360
void BusDigital::setColorOrder(uint8_t colorOrder) {
@@ -1123,7 +1123,8 @@ size_t BusConfig::memUsage(unsigned nr) const {
11231123
if (Bus::isVirtual(type)) {
11241124
return sizeof(BusNetwork) + (count * Bus::getNumberOfChannels(type));
11251125
} else if (Bus::isDigital(type)) {
1126-
return sizeof(BusDigital) + PolyBus::memUsage(count + skipAmount, PolyBus::getI(type, pins, nr)) /*+ doubleBuffer * (count + skipAmount) * Bus::getNumberOfChannels(type)*/;
1126+
// if any of digital buses uses I2S, there is additional common I2S DMA buffer not accounted for here
1127+
return sizeof(BusDigital) + PolyBus::memUsage(count + skipAmount, PolyBus::getI(type, pins, nr));
11271128
} else if (Bus::isOnOff(type)) {
11281129
return sizeof(BusOnOff);
11291130
} else {
@@ -1139,23 +1140,23 @@ size_t BusManager::memUsage() {
11391140
unsigned maxI2S = 0;
11401141
#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(ESP8266)
11411142
unsigned digitalCount = 0;
1142-
#if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)
1143-
#define MAX_RMT 4
1144-
#else
1145-
#define MAX_RMT 8
1146-
#endif
11471143
#endif
11481144
for (const auto &bus : busses) {
1149-
unsigned busSize = bus->getBusSize();
1145+
size += bus->getBusSize();
11501146
#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(ESP8266)
1151-
if (bus->isDigital() && !bus->is2Pin()) digitalCount++;
1152-
if (PolyBus::isParallelI2S1Output() && digitalCount > MAX_RMT) {
1153-
unsigned i2sCommonSize = 3 * bus->getLength() * bus->getNumberOfChannels() * (bus->is16bit()+1);
1154-
if (i2sCommonSize > maxI2S) maxI2S = i2sCommonSize;
1155-
busSize -= i2sCommonSize;
1147+
if (bus->isDigital() && !bus->is2Pin()) {
1148+
digitalCount++;
1149+
if ((PolyBus::isParallelI2S1Output() && digitalCount <= 8) || (!PolyBus::isParallelI2S1Output() && digitalCount == 1)) {
1150+
#ifdef NPB_CONF_4STEP_CADENCE
1151+
constexpr unsigned stepFactor = 4; // 4 step cadence (4 bits per pixel bit)
1152+
#else
1153+
constexpr unsigned stepFactor = 3; // 3 step cadence (3 bits per pixel bit)
1154+
#endif
1155+
unsigned i2sCommonSize = stepFactor * bus->getLength() * bus->getNumberOfChannels() * (bus->is16bit()+1);
1156+
if (i2sCommonSize > maxI2S) maxI2S = i2sCommonSize;
1157+
}
11561158
}
11571159
#endif
1158-
size += busSize;
11591160
}
11601161
return size + maxI2S;
11611162
}

0 commit comments

Comments
 (0)