Skip to content

Commit 39f3c99

Browse files
authored
Merge pull request #4763 from wled/fix-parallel-i2s-selection
Prevent parallel I2S use if different LED types are used.
2 parents 232dc04 + 1808fa7 commit 39f3c99

File tree

2 files changed

+33
-21
lines changed

2 files changed

+33
-21
lines changed

wled00/FX_fcn.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1203,21 +1203,27 @@ void WS2812FX::finalizeInit() {
12031203
#if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3)
12041204
// determine if it is sensible to use parallel I2S outputs on ESP32 (i.e. more than 5 outputs = 1 I2S + 4 RMT)
12051205
unsigned maxLedsOnBus = 0;
1206+
unsigned busType = 0;
12061207
for (const auto &bus : busConfigs) {
12071208
if (Bus::isDigital(bus.type) && !Bus::is2Pin(bus.type)) {
12081209
digitalCount++;
1210+
if (busType == 0) busType = bus.type; // remember first bus type
1211+
if (busType != bus.type) {
1212+
DEBUG_PRINTF_P(PSTR("Mixed digital bus types detected! Forcing single I2S output.\n"));
1213+
useParallelI2S = false; // mixed bus types, no parallel I2S
1214+
}
12091215
if (bus.count > maxLedsOnBus) maxLedsOnBus = bus.count;
12101216
}
12111217
}
12121218
DEBUG_PRINTF_P(PSTR("Maximum LEDs on a bus: %u\nDigital buses: %u\n"), maxLedsOnBus, digitalCount);
1213-
// we may remove 300 LEDs per bus limit when NeoPixelBus is updated beyond 2.9.0
1214-
if (maxLedsOnBus <= 300 && useParallelI2S) BusManager::useParallelOutput(); // must call before creating buses
1219+
// we may remove 600 LEDs per bus limit when NeoPixelBus is updated beyond 2.8.3
1220+
if (maxLedsOnBus <= 600 && useParallelI2S) BusManager::useParallelOutput(); // must call before creating buses
12151221
else useParallelI2S = false; // enforce single I2S
1222+
digitalCount = 0;
12161223
#endif
12171224

12181225
// create buses/outputs
12191226
unsigned mem = 0;
1220-
digitalCount = 0;
12211227
for (const auto &bus : busConfigs) {
12221228
mem += bus.memUsage(Bus::isDigital(bus.type) && !Bus::is2Pin(bus.type) ? digitalCount++ : 0); // includes global buffer
12231229
if (mem <= MAX_LED_MEMORY) {

wled00/data/settings_leds.htm

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66
<title>LED Settings</title>
77
<script src="common.js" async type="text/javascript"></script>
88
<script>
9-
var laprev=55,maxB=1,maxD=1,maxA=1,maxV=0,maxM=4000,maxPB=2048,maxL=1664,maxCO=5,maxLbquot=0; //maximum bytes for LED allocation: 4kB for 8266, 32kB for 32
10-
var oMaxB=1;
9+
var maxB=1,maxD=1,maxA=1,maxV=0,maxM=4000,maxPB=2048,maxL=1664,maxCO=5; //maximum bytes for LED allocation: 4kB for 8266, 32kB for 32
1110
var customStarts=false,startsDirty=[];
1211
function off(n) { gN(n).value = -1;}
1312
// these functions correspond to C macros found in const.h
@@ -43,7 +42,7 @@
4342
if (loc) d.Sf.action = getURL('/settings/leds');
4443
}
4544
function bLimits(b,v,p,m,l,o=5,d=2,a=6) {
46-
oMaxB = maxB = b; // maxB - max buses (can be changed if using ESP32 parallel I2S): 19 - ESP32, 14 - S3/S2, 6 - C3, 4 - 8266
45+
maxB = b; // maxB - max physical (analog + digital) buses: 32 - ESP32, 14 - S3/S2, 6 - C3, 4 - 8266
4746
maxD = d; // maxD - max digital channels (can be changed if using ESP32 parallel I2S): 16 - ESP32, 12 - S3/S2, 2 - C3, 3 - 8266
4847
maxA = a; // maxA - max analog channels: 16 - ESP32, 8 - S3/S2, 6 - C3, 5 - 8266
4948
maxV = v; // maxV - min virtual buses: 4 - ESP32/S3, 3 - S2/C3, 2 - ESP8266
@@ -52,6 +51,11 @@
5251
maxL = l; // maxL - max LEDs (will serve to determine ESP >1664 == ESP32)
5352
maxCO = o; // maxCO - max Color Order mappings
5453
}
54+
function is8266() { return maxA == 5 && maxD == 3; } // NOTE: see const.h
55+
function is32() { return maxA == 16 && maxD == 16; } // NOTE: see const.h
56+
function isC3() { return maxA == 6 && maxD == 2; } // NOTE: see const.h
57+
function isS2() { return maxA == 8 && maxD == 12 && maxV == 4; } // NOTE: see const.h
58+
function isS3() { return maxA == 8 && maxD == 12 && maxV == 6; } // NOTE: see const.h
5559
function pinsOK() {
5660
var ok = true;
5761
var nList = d.Sf.querySelectorAll("#mLC input[name^=L]");
@@ -213,7 +217,6 @@
213217
let busMA = 0;
214218
let sLC = 0, sPC = 0, sDI = 0, maxLC = 0;
215219
const abl = d.Sf.ABL.checked;
216-
maxB = oMaxB; // TODO make sure we start with all possible buses
217220
let setPinConfig = (n,t) => {
218221
let p0d = "GPIO:";
219222
let p1d = "";
@@ -272,7 +275,7 @@
272275
gRGBW |= hasW(t); // RGBW checkbox
273276
gId("co"+n).style.display = (isVir(t) || isAna(t)) ? "none":"inline"; // hide color order for PWM
274277
gId("dig"+n+"w").style.display = (isDig(t) && hasW(t)) ? "inline":"none"; // show swap channels dropdown
275-
gId("dig"+n+"w").querySelector("[data-opt=CCT]").disabled = !hasCCT(t); // disable WW/CW swapping
278+
gId("dig"+n+"w").querySelector("[data-opt=CCT]").disabled = !hasCCT(t); // disable WW/CW swapping
276279
if (!(isDig(t) && hasW(t))) d.Sf["WO"+n].value = 0; // reset swapping
277280
gId("dig"+n+"c").style.display = (isAna(t)) ? "none":"inline"; // hide count for analog
278281
gId("dig"+n+"r").style.display = (isVir(t)) ? "none":"inline"; // hide reversed for virtual
@@ -290,11 +293,16 @@
290293
d.Sf.CR.checked = false;
291294
}
292295
// update start indexes, max values, calculate current, etc
296+
let sameType = 0;
293297
var nList = d.Sf.querySelectorAll("#mLC input[name^=L]");
294298
nList.forEach((LC,i)=>{
295299
let nm = LC.name.substring(0,2); // field name
296300
let n = LC.name.substring(2); // bus number
297301
let t = parseInt(d.Sf["LT"+n].value); // LED type SELECT
302+
if (isDig(t)) {
303+
if (sameType == 0) sameType = t; // first bus type
304+
else if (sameType != t) sameType = -1; // different bus type
305+
}
298306
// do we have a led count field
299307
if (nm=="LC") {
300308
let c = parseInt(LC.value,10); //get LED count
@@ -352,17 +360,13 @@
352360
else LC.style.color = d.ro_gpio.some((e)=>e==parseInt(LC.value)) ? "orange" : "#fff";
353361
}
354362
});
355-
const S2 = (oMaxB == 14) && (maxV == 4);
356-
const S3 = (oMaxB == 14) && (maxV == 6);
357-
if (oMaxB == 19 || S2 || S3) { // TODO: crude ESP32 & S2/S3 detection
358-
if (maxLC > 300 || dC <= 2) {
363+
if (is32() || isS2() || isS3()) {
364+
if (maxLC > 600 || dC < 2 || sameType <= 0) {
359365
d.Sf["PR"].checked = false;
360366
gId("prl").classList.add("hide");
361367
} else
362368
gId("prl").classList.remove("hide");
363-
maxD = (S2 || S3 ? 4 : 8) + (d.Sf["PR"].checked ? 8 : S2); // TODO: use bLimits() : 4/8RMT + (x1/x8 parallel) I2S1
364-
maxB = oMaxB - (d.Sf["PR"].checked ? 0 : 7 + S3); // S2 (maxV==3) does support single I2S
365-
}
369+
} else d.Sf["PR"].checked = false;
366370
// distribute ABL current if not using PPL
367371
enPPL(sDI);
368372

@@ -479,15 +483,17 @@
479483
if (type.t != undefined && type.t != "") {
480484
opt.setAttribute('data-type', type.t);
481485
}
482-
sel.appendChild(opt);
486+
sel.appendChild(opt);
483487
}
484488
}
485489
});
486490
enLA(d.Sf["LAsel"+s],s); // update LED mA
487491
// disable inappropriate LED types
488-
let sel = d.getElementsByName("LT"+s)[0]
489-
if (i >= maxB || digitalB >= maxD) disable(sel,'option[data-type="D"]'); // NOTE: see isDig()
490-
if (i >= maxB || twopinB >= 1) disable(sel,'option[data-type="2P"]'); // NOTE: see isD2P()
492+
let sel = d.getElementsByName("LT"+s)[0];
493+
// 32 & S2 supports mono I2S as well as parallel so we need to take that into account; S3 only supports parallel
494+
let maxDB = maxD - (is32() || isS2() || isS3() ? (!d.Sf["PR"].checked)*8 - (!isS3()) : 0); // adjust max digital buses if parallel I2S is not used
495+
if (digitalB >= maxDB) disable(sel,'option[data-type="D"]'); // NOTE: see isDig()
496+
if (twopinB >= 2) disable(sel,'option[data-type="2P"]'); // NOTE: see isD2P() (we will only allow 2 2pin buses)
491497
disable(sel,`option[data-type^="${'A'.repeat(maxA-analogB+1)}"]`); // NOTE: see isPWM()
492498
sel.selectedIndex = sel.querySelector('option:not(:disabled)').index;
493499
}
@@ -586,7 +592,7 @@
586592
var cs = false;
587593
for (var i=1; i < gEBCN("iST").length; i++) {
588594
var s = chrID(i);
589-
var p = chrID(i-1); // cover edge case 'A' previous char being '9'
595+
var p = chrID(i-1); // cover edge case 'A' previous char being '9'
590596
var v = parseInt(gId("ls"+p).value) + parseInt(gN("LC"+p).value);
591597
if (v != parseInt(gId("ls"+s).value)) {cs = true; startsDirty[i] = true;}
592598
}
@@ -617,7 +623,7 @@
617623

618624
function receivedText(e) {
619625
let lines = e.target.result;
620-
var c = JSON.parse(lines);
626+
var c = JSON.parse(lines);
621627
if (c.hw) {
622628
if (c.hw.led) {
623629
for (var i=0; i<oMaxB+maxV; i++) addLEDs(-1);

0 commit comments

Comments
 (0)