Skip to content

Commit 887254f

Browse files
committed
Bugfixes
- LED memory calculation (not UI) - potential fix for wled#4040 - compiler warning in FX
1 parent 5874b78 commit 887254f

File tree

8 files changed

+87
-67
lines changed

8 files changed

+87
-67
lines changed

wled00/FX.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2367,7 +2367,7 @@ uint16_t mode_meteor() {
23672367
}
23682368

23692369
// draw meteor
2370-
for (int j = 0; j < meteorSize; j++) {
2370+
for (unsigned j = 0; j < meteorSize; j++) {
23712371
int index = (in + j) % SEGLEN;
23722372
int idx = 255;
23732373
int i = trail[index] = max;

wled00/bus_manager.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -670,9 +670,9 @@ void BusNetwork::cleanup() {
670670
uint32_t BusManager::memUsage(BusConfig &bc) {
671671
if (bc.type == TYPE_ONOFF || IS_PWM(bc.type)) return 5;
672672

673-
uint16_t len = bc.count + bc.skipAmount;
674-
uint16_t channels = Bus::getNumberOfChannels(bc.type);
675-
uint16_t multiplier = 1;
673+
unsigned len = bc.count + bc.skipAmount;
674+
unsigned channels = Bus::getNumberOfChannels(bc.type);
675+
unsigned multiplier = 1;
676676
if (IS_DIGITAL(bc.type)) { // digital types
677677
if (IS_16BIT(bc.type)) len *= 2; // 16-bit LEDs
678678
#ifdef ESP8266
@@ -686,6 +686,12 @@ uint32_t BusManager::memUsage(BusConfig &bc) {
686686
return (len * multiplier + bc.doubleBuffer * (bc.count + bc.skipAmount)) * channels;
687687
}
688688

689+
uint32_t BusManager::memUsage(unsigned maxChannels, unsigned maxCount, unsigned minBuses) {
690+
//ESP32 RMT uses double buffer, parallel I2S uses 8x buffer (3 times)
691+
unsigned multiplier = PolyBus::isParallelI2S1Output() ? 3 : 2;
692+
return (maxChannels * maxCount * minBuses * multiplier);
693+
}
694+
689695
int BusManager::add(BusConfig &bc) {
690696
if (getNumBusses() - getNumVirtualBusses() >= WLED_MAX_BUSSES) return -1;
691697
if (IS_VIRTUAL(bc.type)) {

wled00/bus_manager.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,7 @@ class BusManager {
356356

357357
//utility to get the approx. memory usage of a given BusConfig
358358
static uint32_t memUsage(BusConfig &bc);
359+
static uint32_t memUsage(unsigned channels, unsigned count, unsigned buses = 1);
359360
static uint16_t currentMilliamps(void) { return _milliAmpsUsed; }
360361
static uint16_t ablMilliampsMax(void) { return _milliAmpsMax; }
361362

wled00/button.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ void handleAnalog(uint8_t b)
178178
#ifdef ESP8266
179179
rawReading = analogRead(A0) << 2; // convert 10bit read to 12bit
180180
#else
181-
if ((btnPin[b] < 0) || (digitalPinToAnalogChannel(btnPin[b]) < 0)) return; // pin must support analog ADC - newer esp32 frameworks throw lots of warnings otherwise
181+
if ((btnPin[b] < 0) /*|| (digitalPinToAnalogChannel(btnPin[b]) < 0)*/) return; // pin must support analog ADC - newer esp32 frameworks throw lots of warnings otherwise
182182
rawReading = analogRead(btnPin[b]); // collect at full 12bit resolution
183183
#endif
184184
yield(); // keep WiFi task running - analog read may take several millis on ESP8266

wled00/cfg.cpp

Lines changed: 48 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -160,44 +160,46 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
160160
DEBUG_PRINTF_P(PSTR("Heap before buses: %d\n"), ESP.getFreeHeap());
161161
int s = 0; // bus iterator
162162
if (fromFS) BusManager::removeAll(); // can't safely manipulate busses directly in network callback
163-
uint32_t mem = 0;
164-
bool busesChanged = false;
163+
unsigned mem = 0;
164+
165165
// determine if it is sensible to use parallel I2S outputs on ESP32 (i.e. more than 5 outputs = 1 I2S + 4 RMT)
166166
bool useParallel = false;
167167
#if defined(ARDUINO_ARCH_ESP32) && !defined(ARDUINO_ARCH_ESP32S2) && !defined(ARDUINO_ARCH_ESP32S3) && !defined(ARDUINO_ARCH_ESP32C3)
168168
unsigned digitalCount = 0;
169-
unsigned maxLeds = 0;
170-
int oldType = 0;
171-
int j = 0;
169+
unsigned maxLedsOnBus = 0;
170+
unsigned maxChannels = 0;
172171
for (JsonObject elm : ins) {
173172
unsigned type = elm["type"] | TYPE_WS2812_RGB;
174-
unsigned len = elm["len"] | 30;
175-
if (IS_DIGITAL(type) && !IS_2PIN(type)) digitalCount++;
176-
if (len > maxLeds) maxLeds = len;
177-
// we need to have all LEDs of the same type for parallel
178-
if (j++ < 8 && oldType > 0 && oldType != type) oldType = -1;
179-
else if (oldType == 0) oldType = type;
173+
unsigned len = elm["len"] | DEFAULT_LED_COUNT;
174+
if (!IS_DIGITAL(type)) continue;
175+
if (!IS_2PIN(type)) {
176+
digitalCount++;
177+
unsigned channels = Bus::getNumberOfChannels(type);
178+
if (len > maxLedsOnBus) maxLedsOnBus = len;
179+
if (channels > maxChannels) maxChannels = channels;
180+
}
180181
}
181-
DEBUG_PRINTF_P(PSTR("Maximum LEDs on a bus: %u\nDigital buses: %u\nDifferent types: %d\n"), maxLeds, digitalCount, (int)(oldType == -1));
182+
DEBUG_PRINTF_P(PSTR("Maximum LEDs on a bus: %u\nDigital buses: %u\n"), maxLedsOnBus, digitalCount);
182183
// we may remove 300 LEDs per bus limit when NeoPixelBus is updated beyond 2.9.0
183-
if (/*oldType != -1 && */maxLeds <= 300 && digitalCount > 5) {
184+
if (maxLedsOnBus <= 300 && digitalCount > 5) {
185+
DEBUG_PRINTLN(F("Switching to parallel I2S."));
184186
useParallel = true;
185187
BusManager::useParallelOutput();
186-
DEBUG_PRINTF_P(PSTR("Switching to parallel I2S with max. %d LEDs per ouptut.\n"), maxLeds);
188+
mem = BusManager::memUsage(maxChannels, maxLedsOnBus, 8); // use alternate memory calculation
187189
}
188190
#endif
191+
189192
for (JsonObject elm : ins) {
190193
if (s >= WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES) break;
191194
uint8_t pins[5] = {255, 255, 255, 255, 255};
192195
JsonArray pinArr = elm["pin"];
193196
if (pinArr.size() == 0) continue;
194-
pins[0] = pinArr[0];
197+
//pins[0] = pinArr[0];
195198
unsigned i = 0;
196199
for (int p : pinArr) {
197200
pins[i++] = p;
198201
if (i>4) break;
199202
}
200-
201203
uint16_t length = elm["len"] | 1;
202204
uint8_t colorOrder = (int)elm[F("order")]; // contains white channel swap option in upper nibble
203205
uint8_t skipFirst = elm[F("skip")];
@@ -208,7 +210,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
208210
bool refresh = elm["ref"] | false;
209211
uint16_t freqkHz = elm[F("freq")] | 0; // will be in kHz for DotStar and Hz for PWM
210212
uint8_t AWmode = elm[F("rgbwm")] | RGBW_MODE_MANUAL_ONLY;
211-
uint8_t maPerLed = elm[F("ledma")] | 55;
213+
uint8_t maPerLed = elm[F("ledma")] | LED_MILLIAMPS_DEFAULT;
212214
uint16_t maMax = elm[F("maxpwr")] | (ablMilliampsMax * length) / total; // rough (incorrect?) per strip ABL calculation when no config exists
213215
// To disable brightness limiter we either set output max current to 0 or single LED current to 0 (we choose output max current)
214216
if (IS_PWM(ledType) || IS_ONOFF(ledType) || IS_VIRTUAL(ledType)) { // analog and virtual
@@ -219,26 +221,21 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
219221
if (fromFS) {
220222
BusConfig bc = BusConfig(ledType, pins, start, length, colorOrder, reversed, skipFirst, AWmode, freqkHz, useGlobalLedBuffer, maPerLed, maMax);
221223
if (useParallel && s < 8) {
222-
// we are using parallel I2S and memUsage() will include x8 allocation into account
223-
if (s == 0)
224-
mem = BusManager::memUsage(bc); // includes x8 memory allocation for parallel I2S
225-
else
226-
if (BusManager::memUsage(bc) > mem)
227-
mem = BusManager::memUsage(bc); // if we have unequal LED count use the largest
224+
// if for some unexplained reason the above pre-calculation was wrong, update
225+
unsigned memT = BusManager::memUsage(bc); // includes x8 memory allocation for parallel I2S
226+
if (memT > mem) mem = memT; // if we have unequal LED count use the largest
228227
} else
229228
mem += BusManager::memUsage(bc); // includes global buffer
230229
if (mem <= MAX_LED_MEMORY) if (BusManager::add(bc) == -1) break; // finalization will be done in WLED::beginStrip()
231230
} else {
232231
if (busConfigs[s] != nullptr) delete busConfigs[s];
233232
busConfigs[s] = new BusConfig(ledType, pins, start, length, colorOrder, reversed, skipFirst, AWmode, freqkHz, useGlobalLedBuffer, maPerLed, maMax);
234-
busesChanged = true;
233+
doInitBusses = true; // finalization done in beginStrip()
235234
}
236235
s++;
237236
}
238237
DEBUG_PRINTF_P(PSTR("LED buffer size: %uB\n"), mem);
239238
DEBUG_PRINTF_P(PSTR("Heap after buses: %d\n"), ESP.getFreeHeap());
240-
doInitBusses = busesChanged;
241-
// finalization done in beginStrip()
242239
}
243240
if (hw_led["rev"]) BusManager::getBus(0)->setReversed(true); //set 0.11 global reversed setting for first bus
244241

@@ -275,22 +272,34 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
275272
btnPin[s] = pin;
276273
#ifdef ARDUINO_ARCH_ESP32
277274
// ESP32 only: check that analog button pin is a valid ADC gpio
278-
if (((buttonType[s] == BTN_TYPE_ANALOG) || (buttonType[s] == BTN_TYPE_ANALOG_INVERTED)) && (digitalPinToAnalogChannel(btnPin[s]) < 0))
279-
{
280-
// not an ADC analog pin
281-
DEBUG_PRINT(F("PIN ALLOC error: GPIO")); DEBUG_PRINT(btnPin[s]);
282-
DEBUG_PRINT(F("for analog button #")); DEBUG_PRINT(s);
283-
DEBUG_PRINTLN(F(" is not an analog pin!"));
284-
btnPin[s] = -1;
285-
pinManager.deallocatePin(pin,PinOwner::Button);
275+
if ((buttonType[s] == BTN_TYPE_ANALOG) || (buttonType[s] == BTN_TYPE_ANALOG_INVERTED)) {
276+
if (digitalPinToAnalogChannel(btnPin[s]) < 0) {
277+
// not an ADC analog pin
278+
DEBUG_PRINT(F("PIN ALLOC error: GPIO")); DEBUG_PRINT(btnPin[s]);
279+
DEBUG_PRINT(F("for analog button #")); DEBUG_PRINT(s);
280+
DEBUG_PRINTLN(F(" is not an analog pin!"));
281+
btnPin[s] = -1;
282+
pinManager.deallocatePin(pin,PinOwner::Button);
283+
} else {
284+
analogReadResolution(12); // see #4040
285+
}
286286
}
287-
//if touch pin, enable the touch interrupt on ESP32 S2 & S3
288-
#ifdef SOC_TOUCH_VERSION_2 // ESP32 S2 and S3 have a fucntion to check touch state but need to attach an interrupt to do so
289-
if ((buttonType[s] == BTN_TYPE_TOUCH || buttonType[s] == BTN_TYPE_TOUCH_SWITCH))
287+
else if ((buttonType[s] == BTN_TYPE_TOUCH || buttonType[s] == BTN_TYPE_TOUCH_SWITCH))
290288
{
291-
touchAttachInterrupt(btnPin[s], touchButtonISR, 256 + (touchThreshold << 4)); // threshold on Touch V2 is much higher (1500 is a value given by Espressif example, I measured changes of over 5000)
289+
if (digitalPinToTouchChannel(btnPin[s]) < 0) {
290+
// not a touch pin
291+
DEBUG_PRINTF_P(PSTR("PIN ALLOC error: GPIO%d for touch button #%d is not an touch pin!\n"), btnPin[s], s);
292+
btnPin[s] = -1;
293+
pinManager.deallocatePin(pin,PinOwner::Button);
294+
}
295+
//if touch pin, enable the touch interrupt on ESP32 S2 & S3
296+
#ifdef SOC_TOUCH_VERSION_2 // ESP32 S2 and S3 have a function to check touch state but need to attach an interrupt to do so
297+
else
298+
{
299+
touchAttachInterrupt(btnPin[s], touchButtonISR, 256 + (touchThreshold << 4)); // threshold on Touch V2 is much higher (1500 is a value given by Espressif example, I measured changes of over 5000)
300+
}
301+
#endif
292302
}
293-
#endif
294303
else
295304
#endif
296305
{

wled00/set.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -266,12 +266,16 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
266266
buttonType[i] = request->arg(be).toInt();
267267
#ifdef ARDUINO_ARCH_ESP32
268268
// ESP32 only: check that button pin is a valid gpio
269-
if (((buttonType[i] == BTN_TYPE_ANALOG) || (buttonType[i] == BTN_TYPE_ANALOG_INVERTED)) && (digitalPinToAnalogChannel(btnPin[i]) < 0))
269+
if ((buttonType[i] == BTN_TYPE_ANALOG) || (buttonType[i] == BTN_TYPE_ANALOG_INVERTED))
270270
{
271-
// not an ADC analog pin
272-
DEBUG_PRINTF_P(PSTR("PIN ALLOC error: GPIO%d for analog button #%d is not an analog pin!\n"), btnPin[i], i);
273-
btnPin[i] = -1;
274-
pinManager.deallocatePin(hw_btn_pin,PinOwner::Button);
271+
if (digitalPinToAnalogChannel(btnPin[i]) < 0) {
272+
// not an ADC analog pin
273+
DEBUG_PRINTF_P(PSTR("PIN ALLOC error: GPIO%d for analog button #%d is not an analog pin!\n"), btnPin[i], i);
274+
btnPin[i] = -1;
275+
pinManager.deallocatePin(hw_btn_pin,PinOwner::Button);
276+
} else {
277+
analogReadResolution(12); // see #4040
278+
}
275279
}
276280
else if ((buttonType[i] == BTN_TYPE_TOUCH || buttonType[i] == BTN_TYPE_TOUCH_SWITCH))
277281
{

wled00/wled.cpp

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -175,39 +175,39 @@ void WLED::loop()
175175
DEBUG_PRINTLN(F("Re-init busses."));
176176
bool aligned = strip.checkSegmentAlignment(); //see if old segments match old bus(ses)
177177
BusManager::removeAll();
178+
unsigned mem = 0;
178179
// determine if it is sensible to use parallel I2S outputs on ESP32 (i.e. more than 5 outputs = 1 I2S + 4 RMT)
179180
bool useParallel = false;
180181
#if defined(ARDUINO_ARCH_ESP32) && !defined(ARDUINO_ARCH_ESP32S2) && !defined(ARDUINO_ARCH_ESP32S3) && !defined(ARDUINO_ARCH_ESP32C3)
181182
unsigned digitalCount = 0;
182-
unsigned maxLeds = 0;
183-
int oldType = 0;
183+
unsigned maxLedsOnBus = 0;
184+
unsigned maxChannels = 0;
184185
for (unsigned i = 0; i < WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES; i++) {
185186
if (busConfigs[i] == nullptr) break;
186-
if (IS_DIGITAL(busConfigs[i]->type) && !IS_2PIN(busConfigs[i]->type)) digitalCount++;
187-
if (busConfigs[i]->count > maxLeds) maxLeds = busConfigs[i]->count;
188-
// we need to have all LEDs of the same type for parallel
189-
if (i < 8 && oldType > 0 && oldType != busConfigs[i]->type) oldType = -1;
190-
else if (oldType == 0) oldType = busConfigs[i]->type;
187+
if (!IS_DIGITAL(busConfigs[i]->type)) continue;
188+
if (!IS_2PIN(busConfigs[i]->type)) {
189+
digitalCount++;
190+
unsigned channels = Bus::getNumberOfChannels(busConfigs[i]->type);
191+
if (busConfigs[i]->count > maxLedsOnBus) maxLedsOnBus = busConfigs[i]->count;
192+
if (channels > maxChannels) maxChannels = channels;
193+
}
191194
}
192-
DEBUG_PRINTF_P(PSTR("Maximum LEDs on a bus: %u\nDigital buses: %u\nDifferent types: %d\n"), maxLeds, digitalCount, (int)(oldType == -1));
195+
DEBUG_PRINTF_P(PSTR("Maximum LEDs on a bus: %u\nDigital buses: %u\n"), maxLedsOnBus, digitalCount);
193196
// we may remove 300 LEDs per bus limit when NeoPixelBus is updated beyond 2.9.0
194-
if (/*oldType != -1 && */maxLeds <= 300 && digitalCount > 5) {
197+
if (maxLedsOnBus <= 300 && digitalCount > 5) {
198+
DEBUG_PRINTF_P(PSTR("Switching to parallel I2S."));
195199
useParallel = true;
196200
BusManager::useParallelOutput();
197-
DEBUG_PRINTF_P(PSTR("Switching to parallel I2S with max. %d LEDs per ouptut.\n"), maxLeds);
201+
mem = BusManager::memUsage(maxChannels, maxLedsOnBus, 8); // use alternate memory calculation (hse to be used *after* useParallelOutput())
198202
}
199203
#endif
200204
// create buses/outputs
201-
unsigned mem = 0;
202205
for (unsigned i = 0; i < WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES; i++) {
203206
if (busConfigs[i] == nullptr || (!useParallel && i > 10)) break;
204207
if (useParallel && i < 8) {
205-
// we are using parallel I2S and memUsage() will include x8 allocation into account
206-
if (i == 0)
207-
mem = BusManager::memUsage(*busConfigs[i]); // includes x8 memory allocation for parallel I2S
208-
else
209-
if (BusManager::memUsage(*busConfigs[i]) > mem)
210-
mem = BusManager::memUsage(*busConfigs[i]); // if we have unequal LED count use the largest
208+
// if for some unexplained reason the above pre-calculation was wrong, update
209+
unsigned memT = BusManager::memUsage(*busConfigs[i]); // includes x8 memory allocation for parallel I2S
210+
if (memT > mem) mem = memT; // if we have unequal LED count use the largest
211211
} else
212212
mem += BusManager::memUsage(*busConfigs[i]); // includes global buffer
213213
if (mem <= MAX_LED_MEMORY) BusManager::add(*busConfigs[i]);

wled00/wled.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*/
99

1010
// version code in format yymmddb (b = daily build)
11-
#define VERSION 2406290
11+
#define VERSION 2407070
1212

1313
//uncomment this if you have a "my_config.h" file you'd like to use
1414
//#define WLED_USE_MY_CONFIG

0 commit comments

Comments
 (0)