mirror of
https://github.com/wled/WLED.git
synced 2025-07-17 07:46:32 +00:00
Prevent parallel I2S use if different LED types are used.
- helps with #4315 - add-on to #4762 - increases parallel I2S LED limit to 600 per bus
This commit is contained in:
parent
232dc044e7
commit
1808fa776b
@ -1203,21 +1203,27 @@ void WS2812FX::finalizeInit() {
|
|||||||
#if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
#if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||||
// determine if it is sensible to use parallel I2S outputs on ESP32 (i.e. more than 5 outputs = 1 I2S + 4 RMT)
|
// determine if it is sensible to use parallel I2S outputs on ESP32 (i.e. more than 5 outputs = 1 I2S + 4 RMT)
|
||||||
unsigned maxLedsOnBus = 0;
|
unsigned maxLedsOnBus = 0;
|
||||||
|
unsigned busType = 0;
|
||||||
for (const auto &bus : busConfigs) {
|
for (const auto &bus : busConfigs) {
|
||||||
if (Bus::isDigital(bus.type) && !Bus::is2Pin(bus.type)) {
|
if (Bus::isDigital(bus.type) && !Bus::is2Pin(bus.type)) {
|
||||||
digitalCount++;
|
digitalCount++;
|
||||||
|
if (busType == 0) busType = bus.type; // remember first bus type
|
||||||
|
if (busType != bus.type) {
|
||||||
|
DEBUG_PRINTF_P(PSTR("Mixed digital bus types detected! Forcing single I2S output.\n"));
|
||||||
|
useParallelI2S = false; // mixed bus types, no parallel I2S
|
||||||
|
}
|
||||||
if (bus.count > maxLedsOnBus) maxLedsOnBus = bus.count;
|
if (bus.count > maxLedsOnBus) maxLedsOnBus = bus.count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DEBUG_PRINTF_P(PSTR("Maximum LEDs on a bus: %u\nDigital buses: %u\n"), maxLedsOnBus, digitalCount);
|
DEBUG_PRINTF_P(PSTR("Maximum LEDs on a bus: %u\nDigital buses: %u\n"), maxLedsOnBus, digitalCount);
|
||||||
// we may remove 300 LEDs per bus limit when NeoPixelBus is updated beyond 2.9.0
|
// we may remove 600 LEDs per bus limit when NeoPixelBus is updated beyond 2.8.3
|
||||||
if (maxLedsOnBus <= 300 && useParallelI2S) BusManager::useParallelOutput(); // must call before creating buses
|
if (maxLedsOnBus <= 600 && useParallelI2S) BusManager::useParallelOutput(); // must call before creating buses
|
||||||
else useParallelI2S = false; // enforce single I2S
|
else useParallelI2S = false; // enforce single I2S
|
||||||
|
digitalCount = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// create buses/outputs
|
// create buses/outputs
|
||||||
unsigned mem = 0;
|
unsigned mem = 0;
|
||||||
digitalCount = 0;
|
|
||||||
for (const auto &bus : busConfigs) {
|
for (const auto &bus : busConfigs) {
|
||||||
mem += bus.memUsage(Bus::isDigital(bus.type) && !Bus::is2Pin(bus.type) ? digitalCount++ : 0); // includes global buffer
|
mem += bus.memUsage(Bus::isDigital(bus.type) && !Bus::is2Pin(bus.type) ? digitalCount++ : 0); // includes global buffer
|
||||||
if (mem <= MAX_LED_MEMORY) {
|
if (mem <= MAX_LED_MEMORY) {
|
||||||
|
@ -6,8 +6,7 @@
|
|||||||
<title>LED Settings</title>
|
<title>LED Settings</title>
|
||||||
<script src="common.js" async type="text/javascript"></script>
|
<script src="common.js" async type="text/javascript"></script>
|
||||||
<script>
|
<script>
|
||||||
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
|
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
|
||||||
var oMaxB=1;
|
|
||||||
var customStarts=false,startsDirty=[];
|
var customStarts=false,startsDirty=[];
|
||||||
function off(n) { gN(n).value = -1;}
|
function off(n) { gN(n).value = -1;}
|
||||||
// these functions correspond to C macros found in const.h
|
// these functions correspond to C macros found in const.h
|
||||||
@ -43,7 +42,7 @@
|
|||||||
if (loc) d.Sf.action = getURL('/settings/leds');
|
if (loc) d.Sf.action = getURL('/settings/leds');
|
||||||
}
|
}
|
||||||
function bLimits(b,v,p,m,l,o=5,d=2,a=6) {
|
function bLimits(b,v,p,m,l,o=5,d=2,a=6) {
|
||||||
oMaxB = maxB = b; // maxB - max buses (can be changed if using ESP32 parallel I2S): 19 - ESP32, 14 - S3/S2, 6 - C3, 4 - 8266
|
maxB = b; // maxB - max physical (analog + digital) buses: 32 - ESP32, 14 - S3/S2, 6 - C3, 4 - 8266
|
||||||
maxD = d; // maxD - max digital channels (can be changed if using ESP32 parallel I2S): 16 - ESP32, 12 - S3/S2, 2 - C3, 3 - 8266
|
maxD = d; // maxD - max digital channels (can be changed if using ESP32 parallel I2S): 16 - ESP32, 12 - S3/S2, 2 - C3, 3 - 8266
|
||||||
maxA = a; // maxA - max analog channels: 16 - ESP32, 8 - S3/S2, 6 - C3, 5 - 8266
|
maxA = a; // maxA - max analog channels: 16 - ESP32, 8 - S3/S2, 6 - C3, 5 - 8266
|
||||||
maxV = v; // maxV - min virtual buses: 4 - ESP32/S3, 3 - S2/C3, 2 - ESP8266
|
maxV = v; // maxV - min virtual buses: 4 - ESP32/S3, 3 - S2/C3, 2 - ESP8266
|
||||||
@ -52,6 +51,11 @@
|
|||||||
maxL = l; // maxL - max LEDs (will serve to determine ESP >1664 == ESP32)
|
maxL = l; // maxL - max LEDs (will serve to determine ESP >1664 == ESP32)
|
||||||
maxCO = o; // maxCO - max Color Order mappings
|
maxCO = o; // maxCO - max Color Order mappings
|
||||||
}
|
}
|
||||||
|
function is8266() { return maxA == 5 && maxD == 3; } // NOTE: see const.h
|
||||||
|
function is32() { return maxA == 16 && maxD == 16; } // NOTE: see const.h
|
||||||
|
function isC3() { return maxA == 6 && maxD == 2; } // NOTE: see const.h
|
||||||
|
function isS2() { return maxA == 8 && maxD == 12 && maxV == 4; } // NOTE: see const.h
|
||||||
|
function isS3() { return maxA == 8 && maxD == 12 && maxV == 6; } // NOTE: see const.h
|
||||||
function pinsOK() {
|
function pinsOK() {
|
||||||
var ok = true;
|
var ok = true;
|
||||||
var nList = d.Sf.querySelectorAll("#mLC input[name^=L]");
|
var nList = d.Sf.querySelectorAll("#mLC input[name^=L]");
|
||||||
@ -213,7 +217,6 @@
|
|||||||
let busMA = 0;
|
let busMA = 0;
|
||||||
let sLC = 0, sPC = 0, sDI = 0, maxLC = 0;
|
let sLC = 0, sPC = 0, sDI = 0, maxLC = 0;
|
||||||
const abl = d.Sf.ABL.checked;
|
const abl = d.Sf.ABL.checked;
|
||||||
maxB = oMaxB; // TODO make sure we start with all possible buses
|
|
||||||
let setPinConfig = (n,t) => {
|
let setPinConfig = (n,t) => {
|
||||||
let p0d = "GPIO:";
|
let p0d = "GPIO:";
|
||||||
let p1d = "";
|
let p1d = "";
|
||||||
@ -290,11 +293,16 @@
|
|||||||
d.Sf.CR.checked = false;
|
d.Sf.CR.checked = false;
|
||||||
}
|
}
|
||||||
// update start indexes, max values, calculate current, etc
|
// update start indexes, max values, calculate current, etc
|
||||||
|
let sameType = 0;
|
||||||
var nList = d.Sf.querySelectorAll("#mLC input[name^=L]");
|
var nList = d.Sf.querySelectorAll("#mLC input[name^=L]");
|
||||||
nList.forEach((LC,i)=>{
|
nList.forEach((LC,i)=>{
|
||||||
let nm = LC.name.substring(0,2); // field name
|
let nm = LC.name.substring(0,2); // field name
|
||||||
let n = LC.name.substring(2); // bus number
|
let n = LC.name.substring(2); // bus number
|
||||||
let t = parseInt(d.Sf["LT"+n].value); // LED type SELECT
|
let t = parseInt(d.Sf["LT"+n].value); // LED type SELECT
|
||||||
|
if (isDig(t)) {
|
||||||
|
if (sameType == 0) sameType = t; // first bus type
|
||||||
|
else if (sameType != t) sameType = -1; // different bus type
|
||||||
|
}
|
||||||
// do we have a led count field
|
// do we have a led count field
|
||||||
if (nm=="LC") {
|
if (nm=="LC") {
|
||||||
let c = parseInt(LC.value,10); //get LED count
|
let c = parseInt(LC.value,10); //get LED count
|
||||||
@ -352,17 +360,13 @@
|
|||||||
else LC.style.color = d.ro_gpio.some((e)=>e==parseInt(LC.value)) ? "orange" : "#fff";
|
else LC.style.color = d.ro_gpio.some((e)=>e==parseInt(LC.value)) ? "orange" : "#fff";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const S2 = (oMaxB == 14) && (maxV == 4);
|
if (is32() || isS2() || isS3()) {
|
||||||
const S3 = (oMaxB == 14) && (maxV == 6);
|
if (maxLC > 600 || dC < 2 || sameType <= 0) {
|
||||||
if (oMaxB == 19 || S2 || S3) { // TODO: crude ESP32 & S2/S3 detection
|
|
||||||
if (maxLC > 300 || dC <= 2) {
|
|
||||||
d.Sf["PR"].checked = false;
|
d.Sf["PR"].checked = false;
|
||||||
gId("prl").classList.add("hide");
|
gId("prl").classList.add("hide");
|
||||||
} else
|
} else
|
||||||
gId("prl").classList.remove("hide");
|
gId("prl").classList.remove("hide");
|
||||||
maxD = (S2 || S3 ? 4 : 8) + (d.Sf["PR"].checked ? 8 : S2); // TODO: use bLimits() : 4/8RMT + (x1/x8 parallel) I2S1
|
} else d.Sf["PR"].checked = false;
|
||||||
maxB = oMaxB - (d.Sf["PR"].checked ? 0 : 7 + S3); // S2 (maxV==3) does support single I2S
|
|
||||||
}
|
|
||||||
// distribute ABL current if not using PPL
|
// distribute ABL current if not using PPL
|
||||||
enPPL(sDI);
|
enPPL(sDI);
|
||||||
|
|
||||||
@ -485,9 +489,11 @@ mA/LED: <select name="LAsel${s}" onchange="enLA(this,'${s}');UI();">
|
|||||||
});
|
});
|
||||||
enLA(d.Sf["LAsel"+s],s); // update LED mA
|
enLA(d.Sf["LAsel"+s],s); // update LED mA
|
||||||
// disable inappropriate LED types
|
// disable inappropriate LED types
|
||||||
let sel = d.getElementsByName("LT"+s)[0]
|
let sel = d.getElementsByName("LT"+s)[0];
|
||||||
if (i >= maxB || digitalB >= maxD) disable(sel,'option[data-type="D"]'); // NOTE: see isDig()
|
// 32 & S2 supports mono I2S as well as parallel so we need to take that into account; S3 only supports parallel
|
||||||
if (i >= maxB || twopinB >= 1) disable(sel,'option[data-type="2P"]'); // NOTE: see isD2P()
|
let maxDB = maxD - (is32() || isS2() || isS3() ? (!d.Sf["PR"].checked)*8 - (!isS3()) : 0); // adjust max digital buses if parallel I2S is not used
|
||||||
|
if (digitalB >= maxDB) disable(sel,'option[data-type="D"]'); // NOTE: see isDig()
|
||||||
|
if (twopinB >= 2) disable(sel,'option[data-type="2P"]'); // NOTE: see isD2P() (we will only allow 2 2pin buses)
|
||||||
disable(sel,`option[data-type^="${'A'.repeat(maxA-analogB+1)}"]`); // NOTE: see isPWM()
|
disable(sel,`option[data-type^="${'A'.repeat(maxA-analogB+1)}"]`); // NOTE: see isPWM()
|
||||||
sel.selectedIndex = sel.querySelector('option:not(:disabled)').index;
|
sel.selectedIndex = sel.querySelector('option:not(:disabled)').index;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user