Skip to content

Commit c30c7e1

Browse files
committed
Merge pull request #4763 from wled/fix-parallel-i2s-selection
Prevent parallel I2S use if different LED types are used.
1 parent b7bfd6f commit c30c7e1

File tree

2 files changed

+33
-22
lines changed

2 files changed

+33
-22
lines changed

wled00/FX_fcn.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1139,21 +1139,27 @@ void WS2812FX::finalizeInit() {
11391139
#if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3)
11401140
// determine if it is sensible to use parallel I2S outputs on ESP32 (i.e. more than 5 outputs = 1 I2S + 4 RMT)
11411141
unsigned maxLedsOnBus = 0;
1142+
unsigned busType = 0;
11421143
for (const auto &bus : busConfigs) {
11431144
if (Bus::isDigital(bus.type) && !Bus::is2Pin(bus.type)) {
11441145
digitalCount++;
1146+
if (busType == 0) busType = bus.type; // remember first bus type
1147+
if (busType != bus.type) {
1148+
DEBUG_PRINTF_P(PSTR("Mixed digital bus types detected! Forcing single I2S output.\n"));
1149+
useParallelI2S = false; // mixed bus types, no parallel I2S
1150+
}
11451151
if (bus.count > maxLedsOnBus) maxLedsOnBus = bus.count;
11461152
}
11471153
}
11481154
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
1155+
// we may remove 600 LEDs per bus limit when NeoPixelBus is updated beyond 2.8.3
1156+
if (maxLedsOnBus <= 600 && useParallelI2S) BusManager::useParallelOutput(); // must call before creating buses
11511157
else useParallelI2S = false; // enforce single I2S
1158+
digitalCount = 0;
11521159
#endif
11531160

11541161
// create buses/outputs
11551162
unsigned mem = 0;
1156-
digitalCount = 0;
11571163
for (const auto &bus : busConfigs) {
11581164
mem += bus.memUsage(Bus::isDigital(bus.type) && !Bus::is2Pin(bus.type) ? digitalCount++ : 0); // includes global buffer
11591165
if (mem <= MAX_LED_MEMORY) {

wled00/data/settings_leds.htm

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
<script src="common.js" async type="text/javascript"></script>
88
<script>
99
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
10-
var oMaxB=1;
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,15 +42,20 @@
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): 20 - ESP32, 14 - S3/S2, 6 - C3, 4 - 8266
47-
maxD = d; // maxD - max digital channels (can be changed if using ESP32 parallel I2S): 17 - ESP32, 12 - S3/S2, 2 - C3, 3 - 8266
45+
maxB = b; // maxB - max physical (analog + digital) buses: 32 - ESP32, 14 - S3/S2, 6 - C3, 4 - 8266
46+
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: 6 - ESP32/S3, 4 - S2/C3, 3 - ESP8266 (only used to distinguish S2/S3)
5049
maxPB = p; // maxPB - max LEDs per bus
5150
maxM = m; // maxM - max LED memory
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]");
@@ -212,7 +216,6 @@
212216
let busMA = 0;
213217
let sLC = 0, sPC = 0, sDI = 0, maxLC = 0;
214218
const abl = d.Sf.ABL.checked;
215-
maxB = oMaxB; // TODO make sure we start with all possible buses
216219
let setPinConfig = (n,t) => {
217220
let p0d = "GPIO:";
218221
let p1d = "";
@@ -271,7 +274,7 @@
271274
gRGBW |= hasW(t); // RGBW checkbox
272275
gId("co"+n).style.display = (isVir(t) || isAna(t)) ? "none":"inline"; // hide color order for PWM
273276
gId("dig"+n+"w").style.display = (isDig(t) && hasW(t)) ? "inline":"none"; // show swap channels dropdown
274-
gId("dig"+n+"w").querySelector("[data-opt=CCT]").disabled = !hasCCT(t); // disable WW/CW swapping
277+
gId("dig"+n+"w").querySelector("[data-opt=CCT]").disabled = !hasCCT(t); // disable WW/CW swapping
275278
if (!(isDig(t) && hasW(t))) d.Sf["WO"+n].value = 0; // reset swapping
276279
gId("dig"+n+"c").style.display = (isAna(t)) ? "none":"inline"; // hide count for analog
277280
gId("dig"+n+"r").style.display = (isVir(t)) ? "none":"inline"; // hide reversed for virtual
@@ -289,11 +292,16 @@
289292
d.Sf.CR.checked = false;
290293
}
291294
// update start indexes, max values, calculate current, etc
295+
let sameType = 0;
292296
var nList = d.Sf.querySelectorAll("#mLC input[name^=L]");
293297
nList.forEach((LC,i)=>{
294298
let nm = LC.name.substring(0,2); // field name
295299
let n = LC.name.substring(2); // bus number
296300
let t = parseInt(d.Sf["LT"+n].value); // LED type SELECT
301+
if (isDig(t)) {
302+
if (sameType == 0) sameType = t; // first bus type
303+
else if (sameType != t) sameType = -1; // different bus type
304+
}
297305
// do we have a led count field
298306
if (nm=="LC") {
299307
let c = parseInt(LC.value,10); //get LED count
@@ -351,18 +359,13 @@
351359
else LC.style.color = d.ro_gpio.some((e)=>e==parseInt(LC.value)) ? "orange" : "#fff";
352360
}
353361
});
354-
const S2 = (oMaxB == 14) && (maxV == 4);
355-
const S3 = (oMaxB == 14) && (maxV == 6);
356-
if (oMaxB == 32 || S2 || S3) { // TODO: crude ESP32 & S2/S3 detection
357-
if (maxLC > 300 || dC <= 2) {
362+
if (is32() || isS2() || isS3()) {
363+
if (maxLC > 600 || dC < 2 || sameType <= 0) {
358364
d.Sf["PR"].checked = false;
359365
gId("prl").classList.add("hide");
360366
} else
361367
gId("prl").classList.remove("hide");
362-
// S2 supports mono I2S as well as parallel so we need to take that into account; S3 only supports parallel
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==4) does support mono I2S
365-
}
368+
} else d.Sf["PR"].checked = false;
366369
// distribute ABL current if not using PPL
367370
enPPL(sDI);
368371

@@ -479,15 +482,17 @@
479482
if (type.t != undefined && type.t != "") {
480483
opt.setAttribute('data-type', type.t);
481484
}
482-
sel.appendChild(opt);
485+
sel.appendChild(opt);
483486
}
484487
}
485488
});
486489
enLA(d.Sf["LAsel"+s],s); // update LED mA
487490
// 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()
491+
let sel = d.getElementsByName("LT"+s)[0];
492+
// 32 & S2 supports mono I2S as well as parallel so we need to take that into account; S3 only supports parallel
493+
let maxDB = maxD - (is32() || isS2() || isS3() ? (!d.Sf["PR"].checked)*8 - (!isS3()) : 0); // adjust max digital buses if parallel I2S is not used
494+
if (digitalB >= maxDB) disable(sel,'option[data-type="D"]'); // NOTE: see isDig()
495+
if (twopinB >= 2) disable(sel,'option[data-type="2P"]'); // NOTE: see isD2P() (we will only allow 2 2pin buses)
491496
disable(sel,`option[data-type^="${'A'.repeat(maxA-analogB+1)}"]`); // NOTE: see isPWM()
492497
sel.selectedIndex = sel.querySelector('option:not(:disabled)').index;
493498
}
@@ -586,7 +591,7 @@
586591
var cs = false;
587592
for (var i=1; i < gEBCN("iST").length; i++) {
588593
var s = chrID(i);
589-
var p = chrID(i-1); // cover edge case 'A' previous char being '9'
594+
var p = chrID(i-1); // cover edge case 'A' previous char being '9'
590595
var v = parseInt(gId("ls"+p).value) + parseInt(gN("LC"+p).value);
591596
if (v != parseInt(gId("ls"+s).value)) {cs = true; startsDirty[i] = true;}
592597
}
@@ -617,7 +622,7 @@
617622

618623
function receivedText(e) {
619624
let lines = e.target.result;
620-
let c = JSON.parse(lines);
625+
let c = JSON.parse(lines);
621626
if (c.hw) {
622627
if (c.hw.led) {
623628
// remove all existing outputs

0 commit comments

Comments
 (0)