mirror of
https://github.com/wled/WLED.git
synced 2025-04-24 14:57:18 +00:00
Merge branch '0_15' into blending-styles
This commit is contained in:
commit
a4ac444bda
@ -889,7 +889,7 @@ class WS2812FX { // 96 bytes
|
||||
isMatrix;
|
||||
|
||||
#ifndef WLED_DISABLE_2D
|
||||
#define WLED_MAX_PANELS 64
|
||||
#define WLED_MAX_PANELS 18
|
||||
uint8_t
|
||||
panels;
|
||||
|
||||
|
@ -1265,6 +1265,7 @@ void WS2812FX::finalizeInit(void) {
|
||||
// for the lack of better place enumerate ledmaps here
|
||||
// if we do it in json.cpp (serializeInfo()) we are getting flashes on LEDs
|
||||
// unfortunately this means we do not get updates after uploads
|
||||
// the other option is saving UI settings which will cause enumeration
|
||||
enumerateLedmaps();
|
||||
|
||||
_hasWhiteChannel = _isOffRefreshRequired = false;
|
||||
@ -1308,11 +1309,12 @@ void WS2812FX::finalizeInit(void) {
|
||||
unsigned busEnd = bus->getStart() + bus->getLength();
|
||||
if (busEnd > _length) _length = busEnd;
|
||||
#ifdef ESP8266
|
||||
if ((!IS_DIGITAL(bus->getType()) || IS_2PIN(bus->getType()))) continue;
|
||||
uint8_t pins[5];
|
||||
if (!bus->getPins(pins)) continue;
|
||||
BusDigital* bd = static_cast<BusDigital*>(bus);
|
||||
if (pins[0] == 3) bd->reinit();
|
||||
// why do we need to reinitialise GPIO3???
|
||||
//if ((!IS_DIGITAL(bus->getType()) || IS_2PIN(bus->getType()))) continue;
|
||||
//uint8_t pins[5];
|
||||
//if (!bus->getPins(pins)) continue;
|
||||
//BusDigital* bd = static_cast<BusDigital*>(bus);
|
||||
//if (pins[0] == 3) bd->reinit();
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1885,13 +1887,15 @@ bool WS2812FX::deserializeMap(uint8_t n) {
|
||||
bool isFile = WLED_FS.exists(fileName);
|
||||
|
||||
customMappingSize = 0; // prevent use of mapping if anything goes wrong
|
||||
currentLedmap = 0;
|
||||
if (n == 0 || isFile) interfaceUpdateCallMode = CALL_MODE_WS_SEND; // schedule WS update (to inform UI)
|
||||
|
||||
if (!isFile && n==0 && isMatrix) {
|
||||
setUpMatrix();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isFile || !requestJSONBufferLock(7)) return false; // this will trigger setUpMatrix() when called from wled.cpp
|
||||
if (!isFile || !requestJSONBufferLock(7)) return false;
|
||||
|
||||
if (!readObjectFromFile(fileName, nullptr, pDoc)) {
|
||||
DEBUG_PRINT(F("ERROR Invalid ledmap in ")); DEBUG_PRINTLN(fileName);
|
||||
@ -1915,6 +1919,7 @@ bool WS2812FX::deserializeMap(uint8_t n) {
|
||||
if (!map.isNull() && map.size()) { // not an empty map
|
||||
customMappingSize = min((unsigned)map.size(), (unsigned)getLengthTotal());
|
||||
for (unsigned i=0; i<customMappingSize; i++) customMappingTable[i] = (uint16_t) (map[i]<0 ? 0xFFFFU : map[i]);
|
||||
currentLedmap = n;
|
||||
}
|
||||
} else {
|
||||
DEBUG_PRINTLN(F("ERROR LED map allocation error."));
|
||||
|
@ -270,12 +270,6 @@ bool BusDigital::canShow() {
|
||||
|
||||
void BusDigital::setBrightness(uint8_t b) {
|
||||
if (_bri == b) return;
|
||||
//Fix for turning off onboard LED breaking bus
|
||||
#ifdef LED_BUILTIN
|
||||
if (_bri == 0) { // && b > 0, covered by guard if above
|
||||
if (_pins[0] == LED_BUILTIN || _pins[1] == LED_BUILTIN) reinit();
|
||||
}
|
||||
#endif
|
||||
Bus::setBrightness(b);
|
||||
PolyBus::setBrightness(_busPtr, _iType, b);
|
||||
}
|
||||
@ -707,6 +701,7 @@ int BusManager::add(BusConfig &bc) {
|
||||
}
|
||||
|
||||
void BusManager::useParallelOutput(void) {
|
||||
_parallelOutputs = 8; // hardcoded since we use NPB I2S x8 methods
|
||||
PolyBus::setParallelI2S1Output();
|
||||
}
|
||||
|
||||
@ -717,9 +712,81 @@ void BusManager::removeAll() {
|
||||
while (!canAllShow()) yield();
|
||||
for (unsigned i = 0; i < numBusses; i++) delete busses[i];
|
||||
numBusses = 0;
|
||||
_parallelOutputs = 1;
|
||||
PolyBus::setParallelI2S1Output(false);
|
||||
}
|
||||
|
||||
#ifdef ESP32_DATA_IDLE_HIGH
|
||||
// #2478
|
||||
// If enabled, RMT idle level is set to HIGH when off
|
||||
// to prevent leakage current when using an N-channel MOSFET to toggle LED power
|
||||
void BusManager::esp32RMTInvertIdle() {
|
||||
bool idle_out;
|
||||
unsigned rmt = 0;
|
||||
for (unsigned u = 0; u < numBusses(); u++) {
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32C3) // 2 RMT, only has 1 I2S but NPB does not support it ATM
|
||||
if (u > 1) return;
|
||||
rmt = u;
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32S2) // 4 RMT, only has 1 I2S bus, supported in NPB
|
||||
if (u > 3) return;
|
||||
rmt = u;
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32S3) // 4 RMT, has 2 I2S but NPB does not support them ATM
|
||||
if (u > 3) return;
|
||||
rmt = u;
|
||||
#else
|
||||
if (u < _parallelOutputs) continue;
|
||||
if (u >= _parallelOutputs + 8) return; // only 8 RMT channels
|
||||
rmt = u - _parallelOutputs;
|
||||
#endif
|
||||
if (busses[u]->getLength()==0 || !IS_DIGITAL(busses[u]->getType()) || IS_2PIN(busses[u]->getType())) continue;
|
||||
//assumes that bus number to rmt channel mapping stays 1:1
|
||||
rmt_channel_t ch = static_cast<rmt_channel_t>(rmt);
|
||||
rmt_idle_level_t lvl;
|
||||
rmt_get_idle_level(ch, &idle_out, &lvl);
|
||||
if (lvl == RMT_IDLE_LEVEL_HIGH) lvl = RMT_IDLE_LEVEL_LOW;
|
||||
else if (lvl == RMT_IDLE_LEVEL_LOW) lvl = RMT_IDLE_LEVEL_HIGH;
|
||||
else continue;
|
||||
rmt_set_idle_level(ch, idle_out, lvl);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void BusManager::on() {
|
||||
#ifdef ESP8266
|
||||
//Fix for turning off onboard LED breaking bus
|
||||
if (pinManager.getPinOwner(LED_BUILTIN) == PinOwner::BusDigital) {
|
||||
for (unsigned i = 0; i < numBusses; i++) {
|
||||
uint8_t pins[2] = {255,255};
|
||||
if (IS_DIGITAL(busses[i]->getType()) && busses[i]->getPins(pins)) {
|
||||
if (pins[0] == LED_BUILTIN || pins[1] == LED_BUILTIN) {
|
||||
BusDigital *bus = static_cast<BusDigital*>(busses[i]);
|
||||
bus->reinit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef ESP32_DATA_IDLE_HIGH
|
||||
esp32RMTInvertIdle();
|
||||
#endif
|
||||
}
|
||||
|
||||
void BusManager::off() {
|
||||
#ifdef ESP8266
|
||||
// turn off built-in LED if strip is turned off
|
||||
// this will break digital bus so will need to be re-initialised on On
|
||||
if (pinManager.getPinOwner(LED_BUILTIN) == PinOwner::BusDigital) {
|
||||
for (unsigned i = 0; i < numBusses; i++) if (busses[i]->isOffRefreshRequired()) return;
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
digitalWrite(LED_BUILTIN, HIGH);
|
||||
}
|
||||
#endif
|
||||
#ifdef ESP32_DATA_IDLE_HIGH
|
||||
esp32RMTInvertIdle();
|
||||
#endif
|
||||
}
|
||||
|
||||
void BusManager::show() {
|
||||
_milliAmpsUsed = 0;
|
||||
for (unsigned i = 0; i < numBusses; i++) {
|
||||
@ -799,4 +866,5 @@ uint8_t BusManager::numBusses = 0;
|
||||
Bus* BusManager::busses[WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES];
|
||||
ColorOrderMap BusManager::colorOrderMap = {};
|
||||
uint16_t BusManager::_milliAmpsUsed = 0;
|
||||
uint16_t BusManager::_milliAmpsMax = ABL_MILLIAMPS_DEFAULT;
|
||||
uint16_t BusManager::_milliAmpsMax = ABL_MILLIAMPS_DEFAULT;
|
||||
uint8_t BusManager::_parallelOutputs = 1;
|
||||
|
@ -365,6 +365,9 @@ class BusManager {
|
||||
//do not call this method from system context (network callback)
|
||||
static void removeAll();
|
||||
|
||||
static void on(void);
|
||||
static void off(void);
|
||||
|
||||
static void show();
|
||||
static bool canAllShow();
|
||||
static void setStatusPixel(uint32_t c);
|
||||
@ -392,7 +395,11 @@ class BusManager {
|
||||
static ColorOrderMap colorOrderMap;
|
||||
static uint16_t _milliAmpsUsed;
|
||||
static uint16_t _milliAmpsMax;
|
||||
static uint8_t _parallelOutputs;
|
||||
|
||||
#ifdef ESP32_DATA_IDLE_HIGH
|
||||
static void esp32RMTInvertIdle();
|
||||
#endif
|
||||
static uint8_t getNumVirtualBusses() {
|
||||
int j = 0;
|
||||
for (int i=0; i<numBusses; i++) if (busses[i]->getType() >= TYPE_NET_DDP_RGB && busses[i]->getType() < 96) j++;
|
||||
|
@ -358,69 +358,35 @@ void handleButton()
|
||||
}
|
||||
}
|
||||
|
||||
// If enabled, RMT idle level is set to HIGH when off
|
||||
// to prevent leakage current when using an N-channel MOSFET to toggle LED power
|
||||
#ifdef ESP32_DATA_IDLE_HIGH
|
||||
void esp32RMTInvertIdle()
|
||||
{
|
||||
bool idle_out;
|
||||
for (uint8_t u = 0; u < BusManager::getNumBusses(); u++)
|
||||
{
|
||||
if (u > 7) return; // only 8 RMT channels, TODO: ESP32 variants have less RMT channels
|
||||
Bus *bus = BusManager::getBus(u);
|
||||
if (!bus || bus->getLength()==0 || !IS_DIGITAL(bus->getType()) || IS_2PIN(bus->getType())) continue;
|
||||
//assumes that bus number to rmt channel mapping stays 1:1
|
||||
rmt_channel_t ch = static_cast<rmt_channel_t>(u);
|
||||
rmt_idle_level_t lvl;
|
||||
rmt_get_idle_level(ch, &idle_out, &lvl);
|
||||
if (lvl == RMT_IDLE_LEVEL_HIGH) lvl = RMT_IDLE_LEVEL_LOW;
|
||||
else if (lvl == RMT_IDLE_LEVEL_LOW) lvl = RMT_IDLE_LEVEL_HIGH;
|
||||
else continue;
|
||||
rmt_set_idle_level(ch, idle_out, lvl);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// handleIO() happens *after* handleTransitions() (see wled.cpp) which may change bri/briT but *before* strip.service()
|
||||
// where actual LED painting occurrs
|
||||
// this is important for relay control and in the event of turning off on-board LED
|
||||
void handleIO()
|
||||
{
|
||||
handleButton();
|
||||
|
||||
//set relay when LEDs turn on
|
||||
if (strip.getBrightness())
|
||||
{
|
||||
// if we want to control on-board LED (ESP8266) or relay we have to do it here as the final show() may not happen until
|
||||
// next loop() cycle
|
||||
if (strip.getBrightness()) {
|
||||
lastOnTime = millis();
|
||||
if (offMode)
|
||||
{
|
||||
#ifdef ESP32_DATA_IDLE_HIGH
|
||||
esp32RMTInvertIdle();
|
||||
#endif
|
||||
if (offMode) {
|
||||
BusManager::on();
|
||||
if (rlyPin>=0) {
|
||||
pinMode(rlyPin, rlyOpenDrain ? OUTPUT_OPEN_DRAIN : OUTPUT);
|
||||
digitalWrite(rlyPin, rlyMde);
|
||||
}
|
||||
offMode = false;
|
||||
}
|
||||
} else if (millis() - lastOnTime > 600)
|
||||
{
|
||||
} else if (millis() - lastOnTime > 600 && !strip.needsUpdate()) {
|
||||
// for turning LED or relay off we need to wait until strip no longer needs updates (strip.trigger())
|
||||
if (!offMode) {
|
||||
#ifdef ESP8266
|
||||
// turn off built-in LED if strip is turned off
|
||||
// this will break digital bus so will need to be re-initialised on On
|
||||
PinOwner ledPinOwner = pinManager.getPinOwner(LED_BUILTIN);
|
||||
if (!strip.isOffRefreshRequired() && (ledPinOwner == PinOwner::None || ledPinOwner == PinOwner::BusDigital)) {
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
digitalWrite(LED_BUILTIN, HIGH);
|
||||
}
|
||||
#endif
|
||||
#ifdef ESP32_DATA_IDLE_HIGH
|
||||
esp32RMTInvertIdle();
|
||||
#endif
|
||||
BusManager::off();
|
||||
if (rlyPin>=0) {
|
||||
pinMode(rlyPin, rlyOpenDrain ? OUTPUT_OPEN_DRAIN : OUTPUT);
|
||||
digitalWrite(rlyPin, !rlyMde);
|
||||
}
|
||||
offMode = true;
|
||||
}
|
||||
offMode = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,15 +79,11 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
getStringFromJson(apSSID, ap[F("ssid")], 33);
|
||||
getStringFromJson(apPass, ap["psk"] , 65); //normally not present due to security
|
||||
//int ap_pskl = ap[F("pskl")];
|
||||
|
||||
CJSON(apChannel, ap[F("chan")]);
|
||||
if (apChannel > 13 || apChannel < 1) apChannel = 1;
|
||||
|
||||
CJSON(apHide, ap[F("hide")]);
|
||||
if (apHide > 1) apHide = 1;
|
||||
|
||||
CJSON(apBehavior, ap[F("behav")]);
|
||||
|
||||
/*
|
||||
JsonArray ap_ip = ap["ip"];
|
||||
for (byte i = 0; i < 4; i++) {
|
||||
@ -95,9 +91,14 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
}
|
||||
*/
|
||||
|
||||
noWifiSleep = doc[F("wifi")][F("sleep")] | !noWifiSleep; // inverted
|
||||
noWifiSleep = !noWifiSleep;
|
||||
force802_3g = doc[F("wifi")][F("phy")] | force802_3g; //force phy mode g?
|
||||
JsonObject wifi = doc[F("wifi")];
|
||||
noWifiSleep = !(wifi[F("sleep")] | !noWifiSleep); // inverted
|
||||
//noWifiSleep = !noWifiSleep;
|
||||
CJSON(force802_3g, wifi[F("phy")]); //force phy mode g?
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
CJSON(txPower, wifi[F("txpwr")]);
|
||||
txPower = min(max((int)txPower, (int)WIFI_POWER_2dBm), (int)WIFI_POWER_19_5dBm);
|
||||
#endif
|
||||
|
||||
JsonObject hw = doc[F("hw")];
|
||||
|
||||
@ -771,8 +772,11 @@ void serializeConfig() {
|
||||
JsonObject wifi = root.createNestedObject(F("wifi"));
|
||||
wifi[F("sleep")] = !noWifiSleep;
|
||||
wifi[F("phy")] = force802_3g;
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
wifi[F("txpwr")] = txPower;
|
||||
#endif
|
||||
|
||||
#ifdef WLED_USE_ETHERNET
|
||||
#ifdef WLED_USE_ETHERNET
|
||||
JsonObject ethernet = root.createNestedObject("eth");
|
||||
ethernet["type"] = ethernetType;
|
||||
if (ethernetType != WLED_ETH_NONE && ethernetType < WLED_NUM_ETH_TYPES) {
|
||||
@ -794,7 +798,7 @@ void serializeConfig() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
JsonObject hw = root.createNestedObject(F("hw"));
|
||||
|
||||
|
@ -192,9 +192,9 @@
|
||||
#define CALL_MODE_INIT 0 //no updates on init, can be used to disable updates
|
||||
#define CALL_MODE_DIRECT_CHANGE 1
|
||||
#define CALL_MODE_BUTTON 2 //default button actions applied to selected segments
|
||||
#define CALL_MODE_NOTIFICATION 3
|
||||
#define CALL_MODE_NIGHTLIGHT 4
|
||||
#define CALL_MODE_NO_NOTIFY 5
|
||||
#define CALL_MODE_NOTIFICATION 3 //caused by incoming notification (UDP or DMX preset)
|
||||
#define CALL_MODE_NIGHTLIGHT 4 //nightlight progress
|
||||
#define CALL_MODE_NO_NOTIFY 5 //change state but do not send notifications (UDP)
|
||||
#define CALL_MODE_FX_CHANGED 6 //no longer used
|
||||
#define CALL_MODE_HUE 7
|
||||
#define CALL_MODE_PRESET_CYCLE 8 //no longer used
|
||||
|
@ -126,9 +126,10 @@
|
||||
<button id="hexcnf" class="btn btn-xs" onclick="fromHex();"><i class="icons btn-icon"></i></button>
|
||||
</div>
|
||||
<div style="padding: 8px 0;" id="btns">
|
||||
<button class="btn btn-xs" title="File editor" type="button" id="edit" onclick="window.location.href=getURL('/edit')"><i class="icons btn-icon"></i></button>
|
||||
<button class="btn btn-xs" title="Pixel Magic Tool" type="button" id="pxmb" onclick="window.location.href=getURL('/pxmagic.htm')"><i class="icons btn-icon"></i></button>
|
||||
<button class="btn btn-xs" title="Add custom palette" type="button" onclick="window.location.href=getURL('/cpal.htm')"><i class="icons btn-icon"></i></button>
|
||||
<button class="btn btn-xs" title="Remove custom palette" type="button" id="rmPal" onclick="palettesData=null;localStorage.removeItem('wledPalx');requestJson({rmcpal:true});setTimeout(loadPalettes,250,loadPalettesData);"><i class="icons btn-icon"></i></button>
|
||||
<button class="btn btn-xs" title="Remove last custom palette" type="button" id="rmPal" onclick="palettesData=null;localStorage.removeItem('wledPalx');requestJson({rmcpal:true});setTimeout(loadPalettes,250,loadPalettesData);"><i class="icons btn-icon"></i></button>
|
||||
</div>
|
||||
<p class="labels hd" id="pall"><i class="icons sel-icon" onclick="tglHex()"></i> Color palette</p>
|
||||
<div id="palw" class="il">
|
||||
|
@ -669,18 +669,15 @@ function parseInfo(i) {
|
||||
//syncTglRecv = i.str;
|
||||
maxSeg = i.leds.maxseg;
|
||||
pmt = i.fs.pmt;
|
||||
if (pcMode && !i.wifi.ap) gId('edit').classList.remove("hide"); else gId('edit').classList.add("hide");
|
||||
gId('buttonNodes').style.display = lastinfo.ndc > 0 ? null:"none";
|
||||
// do we have a matrix set-up
|
||||
mw = i.leds.matrix ? i.leds.matrix.w : 0;
|
||||
mh = i.leds.matrix ? i.leds.matrix.h : 0;
|
||||
isM = mw>0 && mh>0;
|
||||
if (!isM) {
|
||||
//gId("filter0D").classList.remove('hide');
|
||||
//gId("filter1D").classList.add('hide');
|
||||
gId("filter2D").classList.add('hide');
|
||||
} else {
|
||||
//gId("filter0D").classList.add('hide');
|
||||
//gId("filter1D").classList.remove('hide');
|
||||
gId("filter2D").classList.remove('hide');
|
||||
}
|
||||
// if (i.noaudio) {
|
||||
@ -745,10 +742,10 @@ ${inforow("Environment",i.arch + " " + i.core + " (" + i.lwip + ")")}
|
||||
</table>`;
|
||||
gId('kv').innerHTML = cn;
|
||||
// update all sliders in Info
|
||||
for (let sd of (d.querySelectorAll('#kv .sliderdisplay')||[])) {
|
||||
d.querySelectorAll('#kv .sliderdisplay').forEach((sd,i) => {
|
||||
let s = sd.previousElementSibling;
|
||||
if (s) updateTrail(s);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function populateSegments(s)
|
||||
@ -895,8 +892,8 @@ function populateSegments(s)
|
||||
gId('segutil2').style.display = (segCount > 1) ? "block":"none"; // rsbtn parent
|
||||
|
||||
if (Array.isArray(li.maps) && li.maps.length>1) {
|
||||
let cont = `Ledmap: <select class="sel-sg" onchange="requestJson({'ledmap':parseInt(this.value)})"><option value="" selected>Unchanged</option>`;
|
||||
for (const k of (li.maps||[])) cont += `<option value="${k.id}">${k.id==0?'Default':(k.n?k.n:'ledmap'+k.id+'.json')}</option>`;
|
||||
let cont = `Ledmap: <select class="sel-sg" onchange="requestJson({'ledmap':parseInt(this.value)})">`;
|
||||
for (const k of li.maps) cont += `<option ${s.ledmap===k.id?"selected":""} value="${k.id}">${k.id==0?'Default':(k.n?k.n:'ledmap'+k.id+'.json')}</option>`;
|
||||
cont += "</select></div>";
|
||||
gId("ledmap").innerHTML = cont;
|
||||
gId("ledmap").classList.remove('hide');
|
||||
@ -991,13 +988,12 @@ function populatePalettes()
|
||||
|
||||
function redrawPalPrev()
|
||||
{
|
||||
let palettes = d.querySelectorAll('#pallist .lstI');
|
||||
for (var pal of (palettes||[])) {
|
||||
d.querySelectorAll('#pallist .lstI').forEach((pal,i) =>{
|
||||
let lP = pal.querySelector('.lstIprev');
|
||||
if (lP) {
|
||||
lP.style = genPalPrevCss(pal.dataset.id);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function genPalPrevCss(id)
|
||||
@ -1358,10 +1354,12 @@ function updateSelectedFx()
|
||||
}
|
||||
|
||||
// hide 2D mapping and/or sound simulation options
|
||||
var segs = gId("segcont").querySelectorAll(`div[data-map="map2D"]`);
|
||||
for (const seg of segs) if (selectedName.indexOf("\u25A6")<0) seg.classList.remove('hide'); else seg.classList.add('hide');
|
||||
var segs = gId("segcont").querySelectorAll(`div[data-snd="si"]`);
|
||||
for (const seg of segs) if (selectedName.indexOf("\u266A")<0 && selectedName.indexOf("\u266B")<0) seg.classList.add('hide'); else seg.classList.remove('hide'); // also "♫ "?
|
||||
gId("segcont").querySelectorAll(`div[data-map="map2D"]`).forEach((seg)=>{
|
||||
if (selectedName.indexOf("\u25A6")<0) seg.classList.remove('hide'); else seg.classList.add('hide');
|
||||
});
|
||||
gId("segcont").querySelectorAll(`div[data-snd="si"]`).forEach((seg)=>{
|
||||
if (selectedName.indexOf("\u266A")<0 && selectedName.indexOf("\u266B")<0) seg.classList.add('hide'); else seg.classList.remove('hide'); // also "♫ "?
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -1571,8 +1569,7 @@ function setEffectParameters(idx)
|
||||
var paOnOff = (effectPars.length<3 || effectPars[2]=='')?[]:effectPars[2].split(",");
|
||||
|
||||
// set html slider items on/off
|
||||
let sliders = d.querySelectorAll("#sliders .sliderwrap");
|
||||
sliders.forEach((slider, i)=>{
|
||||
d.querySelectorAll("#sliders .sliderwrap").forEach((slider, i)=>{
|
||||
let text = slider.getAttribute("title");
|
||||
if ((!controlDefined && i<((idx<128)?2:nSliders)) || (slOnOff.length>i && slOnOff[i]!="")) {
|
||||
if (slOnOff.length>i && slOnOff[i]!="!") text = slOnOff[i];
|
||||
@ -1586,8 +1583,7 @@ function setEffectParameters(idx)
|
||||
|
||||
if (slOnOff.length > 5) { // up to 3 checkboxes
|
||||
gId('fxopt').classList.remove('fade');
|
||||
let checks = d.querySelectorAll("#sliders .ochkl");
|
||||
checks.forEach((check, i)=>{
|
||||
d.querySelectorAll("#sliders .ochkl").forEach((check, i)=>{
|
||||
let text = check.getAttribute("title");
|
||||
if (5+i<slOnOff.length && slOnOff[5+i]!=='') {
|
||||
if (slOnOff.length>5+i && slOnOff[5+i]!="!") text = slOnOff[5+i];
|
||||
@ -2035,7 +2031,7 @@ ${makePlSel(plJson[i].end?plJson[i].end:0, true)}
|
||||
</label>`;
|
||||
if (Array.isArray(lastinfo.maps) && lastinfo.maps.length>1) {
|
||||
content += `<div class="lbl-l">Ledmap: <div class="sel-p"><select class="sel-p" id="p${i}lmp"><option value="">Unchanged</option>`;
|
||||
for (const k of (lastinfo.maps||[])) content += `<option value="${k.id}"${(i>0 && pJson[i].ledmap==k.id)?" selected":""}>${k.id==0?'Default':(k.n?k.n:'ledmap'+k.id+'.json')}</option>`;
|
||||
for (const k of lastinfo.maps) content += `<option value="${k.id}"${(i>0 && pJson[i].ledmap==k.id)?" selected":""}>${k.id==0?'Default':(k.n?k.n:'ledmap'+k.id+'.json')}</option>`;
|
||||
content += "</select></div></div>";
|
||||
}
|
||||
}
|
||||
@ -2183,13 +2179,12 @@ function selGrp(g)
|
||||
{
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
var sel = gId(`segcont`).querySelectorAll(`div[data-set="${g}"]`);
|
||||
var obj = {"seg":[]};
|
||||
for (let i=0; i<=lSeg; i++) if (gId(`seg${i}`)) obj.seg.push({"id":i,"sel":false});
|
||||
for (let s of (sel||[])) {
|
||||
gId(`segcont`).querySelectorAll(`div[data-set="${g}"]`).forEach((s)=>{
|
||||
let i = parseInt(s.id.substring(3));
|
||||
obj.seg[i] = {"id":i,"sel":true};
|
||||
}
|
||||
});
|
||||
if (obj.seg.length) requestJson(obj);
|
||||
}
|
||||
|
||||
@ -2843,15 +2838,14 @@ function search(field, listId = null) {
|
||||
// do not search if filter is active
|
||||
if (gId("filters").querySelectorAll("input[type=checkbox]:checked").length) return;
|
||||
|
||||
const listItems = gId(listId).querySelectorAll('.lstI');
|
||||
// filter list items but leave (Default & Solid) always visible
|
||||
for (i = (listId === 'pcont' ? 0 : 1); i < listItems.length; i++) {
|
||||
const listItem = listItems[i];
|
||||
gId(listId).querySelectorAll('.lstI').forEach((listItem,i)=>{
|
||||
if (listId!=='pcont' && i===0) return;
|
||||
const listItemName = listItem.querySelector('.lstIname').innerText.toUpperCase();
|
||||
const searchIndex = listItemName.indexOf(field.value.toUpperCase());
|
||||
listItem.style.display = (searchIndex < 0) ? 'none' : '';
|
||||
listItem.dataset.searchIndex = searchIndex;
|
||||
}
|
||||
});
|
||||
|
||||
// sort list items by search index and name
|
||||
const sortedListItems = Array.from(listItems).sort((a, b) => {
|
||||
@ -2912,14 +2906,12 @@ function filterFx() {
|
||||
inputField.value = '';
|
||||
inputField.focus();
|
||||
clean(inputField.nextElementSibling);
|
||||
const listItems = gId("fxlist").querySelectorAll('.lstI');
|
||||
for (let i = 1; i < listItems.length; i++) {
|
||||
const listItem = listItems[i];
|
||||
gId("fxlist").querySelectorAll('.lstI').forEach((listItem,i) => {
|
||||
const listItemName = listItem.querySelector('.lstIname').innerText;
|
||||
let hide = false;
|
||||
gId("filters").querySelectorAll("input[type=checkbox]").forEach((e) => { if (e.checked && !listItemName.includes(e.dataset.flt)) hide = true; });
|
||||
listItem.style.display = hide ? 'none' : '';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function preventBlur(e) {
|
||||
@ -3070,6 +3062,7 @@ function size()
|
||||
|
||||
function togglePcMode(fromB = false)
|
||||
{
|
||||
let ap = (fromB && !lastinfo) || (lastinfo && lastinfo.wifi && lastinfo.witi.ap);
|
||||
if (fromB) {
|
||||
pcModeA = !pcModeA;
|
||||
localStorage.setItem('pcm', pcModeA);
|
||||
@ -3079,6 +3072,7 @@ function togglePcMode(fromB = false)
|
||||
if (!fromB && ((wW < 1024 && lastw < 1024) || (wW >= 1024 && lastw >= 1024))) return; // no change in size and called from size()
|
||||
if (pcMode) openTab(0, true);
|
||||
gId('buttonPcm').className = (pcMode) ? "active":"";
|
||||
if (pcMode && !ap) gId('edit').classList.remove("hide"); else gId('edit').classList.add("hide");
|
||||
gId('bot').style.height = (pcMode && !cfg.comp.pcmbot) ? "0":"auto";
|
||||
sCol('--bh', gId('bot').clientHeight + "px");
|
||||
_C.style.width = (pcMode || simplifiedUI)?'100%':'400%';
|
||||
@ -3104,8 +3098,7 @@ function mergeDeep(target, ...sources)
|
||||
|
||||
function tooltip(cont=null)
|
||||
{
|
||||
const elements = d.querySelectorAll((cont?cont+" ":"")+"[title]");
|
||||
elements.forEach((element)=>{
|
||||
d.querySelectorAll((cont?cont+" ":"")+"[title]").forEach((element)=>{
|
||||
element.addEventListener("mouseover", ()=>{
|
||||
// save title
|
||||
element.setAttribute("data-title", element.getAttribute("title"));
|
||||
@ -3132,8 +3125,7 @@ function tooltip(cont=null)
|
||||
});
|
||||
|
||||
element.addEventListener("mouseout", ()=>{
|
||||
const tooltips = d.querySelectorAll('.tooltip');
|
||||
tooltips.forEach((tooltip)=>{
|
||||
d.querySelectorAll('.tooltip').forEach((tooltip)=>{
|
||||
tooltip.classList.remove("visible");
|
||||
d.body.removeChild(tooltip);
|
||||
});
|
||||
|
@ -6,6 +6,7 @@
|
||||
<title>LED Settings</title>
|
||||
<script>
|
||||
var d=document,laprev=55,maxB=1,maxV=0,maxM=4000,maxPB=4096,maxL=1333,maxCO=10,maxLbquot=0; //maximum bytes for LED allocation: 4kB for 8266, 32kB for 32
|
||||
var oMaxB=1;
|
||||
d.um_p = [];
|
||||
d.rsvd = [];
|
||||
d.ro_gpio = [];
|
||||
@ -58,7 +59,13 @@
|
||||
timeout = setTimeout(function(){ x.className = x.className.replace("show", ""); }, 2900);
|
||||
}
|
||||
function bLimits(b,v,p,m,l,o) {
|
||||
maxB = b; maxV = v; maxM = m; maxPB = p; maxL = l; maxCO = o;
|
||||
// maxB - max buses (can be changed if using ESP32 parallel I2S)
|
||||
// maxV - min virtual buses
|
||||
// maxPB - max LEDs per bus
|
||||
// maxM - max LED memory
|
||||
// maxL - max LEDs
|
||||
// maxCO - max Color Order mappings
|
||||
oMaxB = maxB = b; maxV = v; maxM = m; maxPB = p; maxL = l; maxCO = o;
|
||||
}
|
||||
function pinsOK() {
|
||||
var ok = true;
|
||||
@ -211,6 +218,7 @@
|
||||
let busMA = 0;
|
||||
let sLC = 0, sPC = 0, sDI = 0, maxLC = 0;
|
||||
const ablEN = d.Sf.ABL.checked;
|
||||
maxB = oMaxB; // TODO make sure we start with all possible buses
|
||||
|
||||
// enable/disable LED fields
|
||||
d.Sf.querySelectorAll("#mLC select[name^=LT]").forEach((s)=>{
|
||||
@ -275,6 +283,7 @@
|
||||
// do we have a led count field
|
||||
if (nm=="LC") {
|
||||
let c = parseInt(LC.value,10); //get LED count
|
||||
if (c > 300 && i < 8) maxB = min(oMaxB,10); //TODO: hard limit for buses when using ESP32 parallel I2S
|
||||
if (!customStarts || !startsDirty[n]) gId("ls"+n).value=sLC; //update start value
|
||||
gId("ls"+n).disabled = !customStarts; //enable/disable field editing
|
||||
if (c) {
|
||||
@ -827,7 +836,8 @@ Swap: <select id="xw${s}" name="XW${s}">
|
||||
Apply IR change to main segment only: <input type="checkbox" name="MSO"><br>
|
||||
<div id="json" style="display:none;">JSON file: <input type="file" name="data" accept=".json"><button type="button" class="sml" onclick="uploadFile('/ir.json')">Upload</button><br></div>
|
||||
<a href="https://kno.wled.ge/interfaces/infrared/" target="_blank">IR info</a><br>
|
||||
Relay GPIO: <input type="number" min="-1" max="48" name="RL" onchange="UI()" class="xs"><span style="cursor: pointer;" onclick="off('RL')"> ✕</span> Invert <input type="checkbox" name="RM"> Open drain <input type="checkbox" name="RO"><br>
|
||||
Relay GPIO: <input type="number" min="-1" max="48" name="RL" onchange="UI()" class="xs"><span style="cursor: pointer;" onclick="off('RL')"> ✕</span><br>
|
||||
Invert <input type="checkbox" name="RM"> Open drain <input type="checkbox" name="RO"><br>
|
||||
<hr class="sml">
|
||||
<h3>Defaults</h3>
|
||||
Turn LEDs on after power up/reset: <input type="checkbox" name="BO"><br>
|
||||
|
@ -224,8 +224,23 @@ Static subnet mask:<br>
|
||||
<h3>Experimental</h3>
|
||||
Force 802.11g mode (ESP8266 only): <input type="checkbox" name="FG"><br>
|
||||
Disable WiFi sleep: <input type="checkbox" name="WS"><br>
|
||||
<i>Can help with connectivity issues.<br>
|
||||
Do not enable if WiFi is working correctly, increases power consumption.</i>
|
||||
<i>Can help with connectivity issues and Audioreactive sync.<br>
|
||||
Disabling WiFi sleep increases power consumption.</i><br>
|
||||
<div id="tx">TX power: <select name="TX">
|
||||
<option value="78">19.5 dBm</option>
|
||||
<option value="76">19 dBm</option>
|
||||
<option value="74">18.5 dBm</option>
|
||||
<option value="68">17 dBm</option>
|
||||
<option value="60">15 dBm</option>
|
||||
<option value="52">13 dBm</option>
|
||||
<option value="44">11 dBm</option>
|
||||
<option value="34">8.5 dBm</option>
|
||||
<option value="28">7 dBm</option>
|
||||
<option value="20">5 dBm</option>
|
||||
<option value="8">2 dBm</option>
|
||||
</select><br>
|
||||
<i class="warn">WARNING: Modifying TX power may render device unreachable.</i>
|
||||
</div>
|
||||
|
||||
<h3>ESP-NOW Wireless</h3>
|
||||
<div id="NoESPNOW" class="hide">
|
||||
|
@ -598,6 +598,7 @@ void serializeState(JsonObject root, bool forPreset, bool includeBri, bool segme
|
||||
|
||||
root["ps"] = (currentPreset > 0) ? currentPreset : -1;
|
||||
root[F("pl")] = currentPlaylist;
|
||||
root[F("ledmap")] = currentLedmap;
|
||||
|
||||
usermods.addToJsonState(root);
|
||||
|
||||
@ -741,6 +742,7 @@ void serializeInfo(JsonObject root)
|
||||
wifi_info[F("rssi")] = qrssi;
|
||||
wifi_info[F("signal")] = getSignalQuality(qrssi);
|
||||
wifi_info[F("channel")] = WiFi.channel();
|
||||
wifi_info[F("ap")] = apActive;
|
||||
|
||||
JsonObject fs_info = root.createNestedObject("fs");
|
||||
fs_info["u"] = fsBytesUsed / 1000;
|
||||
|
@ -182,7 +182,7 @@ void handleTransitions() {
|
||||
applyFinalBri();
|
||||
return;
|
||||
}
|
||||
if (tper - tperLast < 0.004f) return;
|
||||
if (tper - tperLast < 0.004f) return; // less than 1 bit change (1/255)
|
||||
tperLast = tper;
|
||||
briT = briOld + ((bri - briOld) * tper);
|
||||
applyBri();
|
||||
|
@ -77,6 +77,11 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
if (t != apChannel) forceReconnect = true;
|
||||
if (t > 0 && t < 14) apChannel = t;
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
int tx = request->arg(F("TX")).toInt();
|
||||
txPower = min(max(tx, (int)WIFI_POWER_2dBm), (int)WIFI_POWER_19_5dBm);
|
||||
#endif
|
||||
|
||||
force802_3g = request->hasArg(F("FG"));
|
||||
noWifiSleep = request->hasArg(F("WS"));
|
||||
|
||||
|
@ -267,12 +267,12 @@ void WLED::loop()
|
||||
DEBUG_PRINT(F("Free heap: ")); DEBUG_PRINTLN(ESP.getFreeHeap());
|
||||
#if defined(ARDUINO_ARCH_ESP32)
|
||||
if (psramFound()) {
|
||||
DEBUG_PRINT(F("Total PSRAM: ")); DEBUG_PRINT(ESP.getPsramSize()/1024); DEBUG_PRINTLN("kB");
|
||||
DEBUG_PRINT(F("Free PSRAM: ")); DEBUG_PRINT(ESP.getFreePsram()/1024); DEBUG_PRINTLN("kB");
|
||||
DEBUG_PRINTF_P(PSTR("PSRAM: %dkB/%dkB\n"), ESP.getFreePsram()/1024, ESP.getPsramSize()/1024);
|
||||
if (!psramSafe) DEBUG_PRINTLN(F("Not using PSRAM."));
|
||||
}
|
||||
DEBUG_PRINTF_P(PSTR("TX power: %d/%d\n"), WiFi.getTxPower(), txPower);
|
||||
#endif
|
||||
DEBUG_PRINT(F("Wifi state: ")); DEBUG_PRINTLN(WiFi.status());
|
||||
DEBUG_PRINTF_P(PSTR("Wifi state: %d\n"), WiFi.status());
|
||||
#ifndef WLED_DISABLE_ESPNOW
|
||||
DEBUG_PRINT(F("ESP-NOW state: ")); DEBUG_PRINTLN(statusESPNow);
|
||||
#endif
|
||||
@ -403,9 +403,9 @@ void WLED::setup()
|
||||
DEBUG_PRINT(F("JSON buffer allocated: ")); DEBUG_PRINTLN((psramSafe && psramFound() ? 2 : 1)*JSON_BUFFER_SIZE);
|
||||
// if the above fails requestJsonBufferLock() will always return false preventing crashes
|
||||
if (psramFound()) {
|
||||
DEBUG_PRINT(F("Total PSRAM: ")); DEBUG_PRINT(ESP.getPsramSize()/1024); DEBUG_PRINTLN("kB");
|
||||
DEBUG_PRINT(F("Free PSRAM : ")); DEBUG_PRINT(ESP.getFreePsram()/1024); DEBUG_PRINTLN("kB");
|
||||
DEBUG_PRINTF_P(PSTR("PSRAM: %dkB/%dkB\n"), ESP.getFreePsram()/1024, ESP.getPsramSize()/1024);
|
||||
}
|
||||
DEBUG_PRINTF_P(PSTR("TX power: %d/%d\n"), WiFi.getTxPower(), txPower);
|
||||
#endif
|
||||
|
||||
#if defined(WLED_DEBUG) && !defined(WLED_DEBUG_HOST)
|
||||
@ -583,11 +583,13 @@ void WLED::beginStrip()
|
||||
if (bootPreset > 0) {
|
||||
applyPreset(bootPreset, CALL_MODE_INIT);
|
||||
}
|
||||
colorUpdated(CALL_MODE_INIT);
|
||||
colorUpdated(CALL_MODE_INIT); // will not send notification
|
||||
|
||||
// init relay pin
|
||||
if (rlyPin>=0)
|
||||
if (rlyPin >= 0) {
|
||||
pinMode(rlyPin, rlyOpenDrain ? OUTPUT_OPEN_DRAIN : OUTPUT);
|
||||
digitalWrite(rlyPin, (rlyMde ? bri : !bri));
|
||||
}
|
||||
}
|
||||
|
||||
void WLED::initAP(bool resetAP)
|
||||
@ -603,8 +605,8 @@ void WLED::initAP(bool resetAP)
|
||||
DEBUG_PRINTLN(apSSID);
|
||||
WiFi.softAPConfig(IPAddress(4, 3, 2, 1), IPAddress(4, 3, 2, 1), IPAddress(255, 255, 255, 0));
|
||||
WiFi.softAP(apSSID, apPass, apChannel, apHide);
|
||||
#if defined(LOLIN_WIFI_FIX) && (defined(ARDUINO_ARCH_ESP32C3) || defined(ARDUINO_ARCH_ESP32S2) || defined(ARDUINO_ARCH_ESP32S3))
|
||||
WiFi.setTxPower(WIFI_POWER_8_5dBm);
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
WiFi.setTxPower(wifi_power_t(txPower));
|
||||
#endif
|
||||
|
||||
if (!apActive) // start captive portal if AP active
|
||||
@ -827,9 +829,7 @@ void WLED::initConnection()
|
||||
WiFi.begin(multiWiFi[selectedWiFi].clientSSID, multiWiFi[selectedWiFi].clientPass); // no harm if called multiple times
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#if defined(LOLIN_WIFI_FIX) && (defined(ARDUINO_ARCH_ESP32C3) || defined(ARDUINO_ARCH_ESP32S2) || defined(ARDUINO_ARCH_ESP32S3))
|
||||
WiFi.setTxPower(WIFI_POWER_8_5dBm);
|
||||
#endif
|
||||
WiFi.setTxPower(wifi_power_t(txPower));
|
||||
WiFi.setSleep(!noWifiSleep);
|
||||
WiFi.setHostname(hostname);
|
||||
#else
|
||||
|
@ -8,7 +8,7 @@
|
||||
*/
|
||||
|
||||
// version code in format yymmddb (b = daily build)
|
||||
#define VERSION 2406121
|
||||
#define VERSION 2406190
|
||||
|
||||
//uncomment this if you have a "my_config.h" file you'd like to use
|
||||
//#define WLED_USE_MY_CONFIG
|
||||
@ -334,6 +334,13 @@ WLED_GLOBAL bool noWifiSleep _INIT(true); // disabling m
|
||||
#else
|
||||
WLED_GLOBAL bool noWifiSleep _INIT(false);
|
||||
#endif
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#if defined(LOLIN_WIFI_FIX) && (defined(ARDUINO_ARCH_ESP32C3) || defined(ARDUINO_ARCH_ESP32S2) || defined(ARDUINO_ARCH_ESP32S3))
|
||||
WLED_GLOBAL uint8_t txPower _INIT(WIFI_POWER_8_5dBm);
|
||||
#else
|
||||
WLED_GLOBAL uint8_t txPower _INIT(WIFI_POWER_19_5dBm);
|
||||
#endif
|
||||
#endif
|
||||
WLED_GLOBAL bool force802_3g _INIT(false);
|
||||
#define WLED_WIFI_CONFIGURED (strlen(multiWiFi[0].clientSSID) >= 1 && strcmp(multiWiFi[0].clientSSID, DEFAULT_CLIENT_SSID) != 0)
|
||||
|
||||
@ -754,6 +761,7 @@ WLED_GLOBAL WS2812FX strip _INIT(WS2812FX());
|
||||
WLED_GLOBAL BusConfig* busConfigs[WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES] _INIT({nullptr}); //temporary, to remember values from network callback until after
|
||||
WLED_GLOBAL bool doInitBusses _INIT(false);
|
||||
WLED_GLOBAL int8_t loadLedmap _INIT(-1);
|
||||
WLED_GLOBAL uint8_t currentLedmap _INIT(0);
|
||||
#ifndef ESP8266
|
||||
WLED_GLOBAL char *ledmapNames[WLED_MAX_LEDMAPS-1] _INIT_N(({nullptr}));
|
||||
#endif
|
||||
|
@ -283,6 +283,11 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
sappends('s',SET_F("AP"),fapass);
|
||||
|
||||
sappend('v',SET_F("AC"),apChannel);
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
sappend('v',SET_F("TX"),txPower);
|
||||
#else
|
||||
oappend(SET_F("gId('tx').style.display='none';"));
|
||||
#endif
|
||||
sappend('c',SET_F("FG"),force802_3g);
|
||||
sappend('c',SET_F("WS"),noWifiSleep);
|
||||
|
||||
@ -298,7 +303,7 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
sappend('v',SET_F("ETH"),ethernetType);
|
||||
#else
|
||||
//hide ethernet setting if not compiled in
|
||||
oappend(SET_F("document.getElementById('ethd').style.display='none';"));
|
||||
oappend(SET_F("gId('ethd').style.display='none';"));
|
||||
#endif
|
||||
|
||||
if (Network.isConnected()) //is connected
|
||||
|
Loading…
x
Reference in New Issue
Block a user