Merge branch 'segment-api' into dev
This commit is contained in:
commit
e9f6509cb0
17
.vscode/extensions.json
vendored
17
.vscode/extensions.json
vendored
@ -1,10 +1,7 @@
|
||||
{
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||
// for the documentation about the extensions.json format
|
||||
"recommendations": [
|
||||
"platformio.platformio-ide"
|
||||
],
|
||||
"unwantedRecommendations": [
|
||||
"ms-vscode.cpptools-extension-pack"
|
||||
]
|
||||
}
|
||||
{
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||
// for the documentation about the extensions.json format
|
||||
"recommendations": [
|
||||
"platformio.platformio-ide"
|
||||
]
|
||||
}
|
||||
|
2
package-lock.json
generated
2
package-lock.json
generated
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "wled",
|
||||
"version": "0.13.2-bl0",
|
||||
"version": "0.14.0-bl0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "wled",
|
||||
"version": "0.13.2-bl0",
|
||||
"version": "0.14.0-bl0",
|
||||
"description": "Tools for WLED project",
|
||||
"main": "tools/cdata.js",
|
||||
"directories": {
|
||||
|
@ -162,7 +162,7 @@ lib_compat_mode = strict
|
||||
lib_deps =
|
||||
fastled/FastLED @ 3.5.0
|
||||
IRremoteESP8266 @ 2.8.2
|
||||
https://github.com/Aircoookie/ESPAsyncWebServer.git @ ~2.0.4
|
||||
https://github.com/Aircoookie/ESPAsyncWebServer.git @ ~2.0.5
|
||||
#For use of the TTGO T-Display ESP32 Module with integrated TFT display uncomment the following line
|
||||
#TFT_eSPI
|
||||
#For use SSD1306 OLED display uncomment following
|
||||
|
@ -263,108 +263,60 @@ writeChunks(
|
||||
name: "PAGE_settings",
|
||||
method: "gzip",
|
||||
filter: "html-minify",
|
||||
mangle: (str) =>
|
||||
str
|
||||
.replace(
|
||||
/function GetV().*\<\/script\>/gms,
|
||||
"</script><script src=\"/settings/s.js?p=0\"></script>"
|
||||
)
|
||||
},
|
||||
{
|
||||
file: "settings_wifi.htm",
|
||||
name: "PAGE_settings_wifi",
|
||||
method: "gzip",
|
||||
filter: "html-minify",
|
||||
mangle: (str) =>
|
||||
str
|
||||
.replace(
|
||||
/function GetV().*\<\/script\>/gms,
|
||||
"</script><script src=\"/settings/s.js?p=1\"></script>"
|
||||
)
|
||||
},
|
||||
{
|
||||
file: "settings_leds.htm",
|
||||
name: "PAGE_settings_leds",
|
||||
method: "gzip",
|
||||
filter: "html-minify",
|
||||
mangle: (str) =>
|
||||
str
|
||||
.replace(
|
||||
/function GetV().*\<\/script\>/gms,
|
||||
"</script><script src=\"/settings/s.js?p=2\"></script>"
|
||||
)
|
||||
},
|
||||
{
|
||||
file: "settings_dmx.htm",
|
||||
name: "PAGE_settings_dmx",
|
||||
method: "gzip",
|
||||
filter: "html-minify",
|
||||
mangle: (str) =>
|
||||
str
|
||||
.replace(
|
||||
/function GetV().*\<\/script\>/gms,
|
||||
"</script><script src=\"/settings/s.js?p=7\"></script>"
|
||||
)
|
||||
},
|
||||
{
|
||||
file: "settings_ui.htm",
|
||||
name: "PAGE_settings_ui",
|
||||
method: "gzip",
|
||||
filter: "html-minify",
|
||||
mangle: (str) =>
|
||||
str
|
||||
.replace(
|
||||
/function GetV().*\<\/script\>/gms,
|
||||
"</script><script src=\"/settings/s.js?p=3\"></script>"
|
||||
)
|
||||
},
|
||||
{
|
||||
file: "settings_sync.htm",
|
||||
name: "PAGE_settings_sync",
|
||||
method: "gzip",
|
||||
filter: "html-minify",
|
||||
mangle: (str) =>
|
||||
str
|
||||
.replace(
|
||||
/function GetV().*\<\/script\>/gms,
|
||||
"</script><script src=\"/settings/s.js?p=4\"></script>"
|
||||
)
|
||||
},
|
||||
{
|
||||
file: "settings_time.htm",
|
||||
name: "PAGE_settings_time",
|
||||
method: "gzip",
|
||||
filter: "html-minify",
|
||||
mangle: (str) =>
|
||||
str
|
||||
.replace(
|
||||
/function GetV().*\<\/script\>/gms,
|
||||
"</script><script src=\"/settings/s.js?p=5\"></script>"
|
||||
)
|
||||
},
|
||||
{
|
||||
file: "settings_sec.htm",
|
||||
name: "PAGE_settings_sec",
|
||||
method: "gzip",
|
||||
filter: "html-minify",
|
||||
mangle: (str) =>
|
||||
str
|
||||
.replace(
|
||||
/function GetV().*\<\/script\>/gms,
|
||||
"</script><script src=\"/settings/s.js?p=6\"></script>"
|
||||
)
|
||||
},
|
||||
{
|
||||
file: "settings_um.htm",
|
||||
name: "PAGE_settings_um",
|
||||
method: "gzip",
|
||||
filter: "html-minify",
|
||||
mangle: (str) =>
|
||||
str
|
||||
.replace(
|
||||
/function GetV().*\<\/script\>/gms,
|
||||
"</script><script src=\"/settings/s.js?p=8\"></script>"
|
||||
)
|
||||
},
|
||||
{
|
||||
file: "settings_2D.htm",
|
||||
name: "PAGE_settings_2D",
|
||||
method: "gzip",
|
||||
filter: "html-minify",
|
||||
},
|
||||
{
|
||||
file: "settings_pin.htm",
|
||||
@ -441,6 +393,12 @@ const char PAGE_dmxmap[] PROGMEM = R"=====()=====";
|
||||
method: "gzip",
|
||||
filter: "html-minify",
|
||||
},
|
||||
{
|
||||
file: "liveviewws2D.htm",
|
||||
name: "PAGE_liveviewws2D",
|
||||
method: "gzip",
|
||||
filter: "html-minify",
|
||||
},
|
||||
{
|
||||
file: "404.htm",
|
||||
name: "PAGE_404",
|
||||
|
@ -103,25 +103,24 @@ class Animated_Staircase : public Usermod {
|
||||
|
||||
void updateSegments() {
|
||||
mainSegmentId = strip.getMainSegmentId();
|
||||
WS2812FX::Segment* segments = strip.getSegments();
|
||||
for (int i = 0; i < MAX_NUM_SEGMENTS; i++, segments++) {
|
||||
if (!segments->isActive()) {
|
||||
for (int i = 0; i < strip.getSegmentsNum(); i++) {
|
||||
Segment &seg = strip.getSegment(i);
|
||||
if (!seg.isActive()) {
|
||||
maxSegmentId = i - 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= onIndex && i < offIndex) {
|
||||
segments->setOption(SEG_OPTION_ON, 1, i);
|
||||
seg.setOption(SEG_OPTION_ON, true);
|
||||
|
||||
// We may need to copy mode and colors from segment 0 to make sure
|
||||
// changes are propagated even when the config is changed during a wipe
|
||||
// segments->mode = mainsegment.mode;
|
||||
// segments->colors[0] = mainsegment.colors[0];
|
||||
} else {
|
||||
segments->setOption(SEG_OPTION_ON, 0, i);
|
||||
seg.setOption(SEG_OPTION_ON, false);
|
||||
}
|
||||
// Always mark segments as "transitional", we are animating the staircase
|
||||
segments->setOption(SEG_OPTION_TRANSITIONAL, 1, i);
|
||||
seg.setOption(SEG_OPTION_TRANSITIONAL, true);
|
||||
}
|
||||
colorUpdated(CALL_MODE_DIRECT_CHANGE);
|
||||
}
|
||||
@ -290,13 +289,13 @@ class Animated_Staircase : public Usermod {
|
||||
}
|
||||
} else {
|
||||
// Restore segment options
|
||||
WS2812FX::Segment* segments = strip.getSegments();
|
||||
for (int i = 0; i < MAX_NUM_SEGMENTS; i++, segments++) {
|
||||
if (!segments->isActive()) {
|
||||
for (int i = 0; i < strip.getSegmentsNum(); i++) {
|
||||
Segment &seg = strip.getSegment(i);
|
||||
if (!seg.isActive()) {
|
||||
maxSegmentId = i - 1;
|
||||
break;
|
||||
}
|
||||
segments->setOption(SEG_OPTION_ON, 1, i);
|
||||
seg.setOption(SEG_OPTION_ON, true);
|
||||
}
|
||||
colorUpdated(CALL_MODE_DIRECT_CHANGE);
|
||||
DEBUG_PRINTLN(F("Animated Staircase disabled."));
|
||||
@ -406,6 +405,14 @@ class Animated_Staircase : public Usermod {
|
||||
}
|
||||
}
|
||||
|
||||
void appendConfigData() {
|
||||
//oappend(SET_F("dd=addDropdown('staircase','selectfield');"));
|
||||
//oappend(SET_F("addOption(dd,'1st value',0);"));
|
||||
//oappend(SET_F("addOption(dd,'2nd value',1);"));
|
||||
//oappend(SET_F("addInfo('staircase:selectfield',1,'additional info');")); // 0 is field type, 1 is actual field
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Writes the configuration to internal flash memory.
|
||||
*/
|
||||
@ -458,15 +465,11 @@ class Animated_Staircase : public Usermod {
|
||||
|
||||
useUSSensorTop = top[FPSTR(_useTopUltrasoundSensor)] | useUSSensorTop;
|
||||
topPIRorTriggerPin = top[FPSTR(_topPIRorTrigger_pin)] | topPIRorTriggerPin;
|
||||
// topPIRorTriggerPin = min(33,max(-1,(int)topPIRorTriggerPin)); // bounds check
|
||||
topEchoPin = top[FPSTR(_topEcho_pin)] | topEchoPin;
|
||||
// topEchoPin = min(39,max(-1,(int)topEchoPin)); // bounds check
|
||||
|
||||
useUSSensorBottom = top[FPSTR(_useBottomUltrasoundSensor)] | useUSSensorBottom;
|
||||
bottomPIRorTriggerPin = top[FPSTR(_bottomPIRorTrigger_pin)] | bottomPIRorTriggerPin;
|
||||
// bottomPIRorTriggerPin = min(33,max(-1,(int)bottomPIRorTriggerPin)); // bounds check
|
||||
bottomEchoPin = top[FPSTR(_bottomEcho_pin)] | bottomEchoPin;
|
||||
// bottomEchoPin = min(39,max(-1,(int)bottomEchoPin)); // bounds check
|
||||
|
||||
topMaxDist = top[FPSTR(_topEchoCm)] | topMaxDist;
|
||||
topMaxDist = min(150,max(30,(int)topMaxDist)); // max distnace ~1.5m (a lag of 9ms may be expected)
|
||||
@ -504,22 +507,22 @@ class Animated_Staircase : public Usermod {
|
||||
* tab of the web-UI.
|
||||
*/
|
||||
void addToJsonInfo(JsonObject& root) {
|
||||
JsonObject staircase = root["u"];
|
||||
if (staircase.isNull()) {
|
||||
staircase = root.createNestedObject("u");
|
||||
JsonObject user = root["u"];
|
||||
if (user.isNull()) {
|
||||
user = root.createNestedObject("u");
|
||||
}
|
||||
|
||||
JsonArray usermodEnabled = staircase.createNestedArray(F("Staircase")); // name
|
||||
String btn = F("<button class=\"btn infobtn\" onclick=\"requestJson({staircase:{enabled:");
|
||||
if (enabled) {
|
||||
btn += F("false}});\">");
|
||||
btn += F("enabled");
|
||||
} else {
|
||||
btn += F("true}});\">");
|
||||
btn += F("disabled");
|
||||
}
|
||||
btn += F("</button>");
|
||||
usermodEnabled.add(btn); // value
|
||||
JsonArray infoArr = user.createNestedArray(FPSTR(_name)); // name
|
||||
|
||||
String uiDomString = F("<button class=\"btn btn-xs\" onclick=\"requestJson({");
|
||||
uiDomString += FPSTR(_name);
|
||||
uiDomString += F(":{");
|
||||
uiDomString += FPSTR(_enabled);
|
||||
uiDomString += enabled ? F(":false}});\">") : F(":true}});\">");
|
||||
uiDomString += F("<i class=\"icons ");
|
||||
uiDomString += enabled ? "on" : "off";
|
||||
uiDomString += F("\"></i></button>");
|
||||
infoArr.add(uiDomString);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -26,15 +26,10 @@ private:
|
||||
bool HomeAssistantDiscovery = false; // Publish Home Assistant Device Information
|
||||
|
||||
// set the default pins based on the architecture, these get overridden by Usermod menu settings
|
||||
#ifdef ARDUINO_ARCH_ESP32 // ESP32 boards
|
||||
#define HW_PIN_SCL 22
|
||||
#define HW_PIN_SDA 21
|
||||
#else // ESP8266 boards
|
||||
#define HW_PIN_SCL 5
|
||||
#define HW_PIN_SDA 4
|
||||
#ifdef ESP8266
|
||||
//uint8_t RST_PIN = 16; // Uncoment for Heltec WiFi-Kit-8
|
||||
#endif
|
||||
int8_t ioPin[2] = {HW_PIN_SCL, HW_PIN_SDA}; // I2C pins: SCL, SDA...defaults to Arch hardware pins but overridden at setup()
|
||||
int8_t ioPin[2] = {i2c_scl, i2c_sda}; // I2C pins: SCL, SDA...defaults to Arch hardware pins but overridden at setup()
|
||||
bool initDone = false;
|
||||
|
||||
// BME280 sensor settings
|
||||
@ -177,7 +172,7 @@ private:
|
||||
public:
|
||||
void setup()
|
||||
{
|
||||
bool HW_Pins_Used = (ioPin[0]==HW_PIN_SCL && ioPin[1]==HW_PIN_SDA); // note whether architecture-based hardware SCL/SDA pins used
|
||||
bool HW_Pins_Used = (ioPin[0]==i2c_scl && ioPin[1]==i2c_sda); // note whether architecture-based hardware SCL/SDA pins used
|
||||
PinOwner po = PinOwner::UM_BME280; // defaults to being pinowner for SCL/SDA pins
|
||||
PinManagerPinType pins[2] = { { ioPin[0], true }, { ioPin[1], true } }; // allocate pins
|
||||
if (HW_Pins_Used) po = PinOwner::HW_I2C; // allow multiple allocations of HW I2C bus pins
|
||||
@ -444,7 +439,7 @@ public:
|
||||
for (byte i=0; i<2; i++) if (ioPin[i] != newPin[i]) { pinsChanged = true; break; } // check if any pins changed
|
||||
if (pinsChanged) { //if pins changed, deallocate old pins and allocate new ones
|
||||
PinOwner po = PinOwner::UM_BME280;
|
||||
if (ioPin[0]==HW_PIN_SCL && ioPin[1]==HW_PIN_SDA) po = PinOwner::HW_I2C; // allow multiple allocations of HW I2C bus pins
|
||||
if (ioPin[0]==i2c_scl && ioPin[1]==i2c_sda) po = PinOwner::HW_I2C; // allow multiple allocations of HW I2C bus pins
|
||||
pinManager.deallocateMultiplePins((const uint8_t *)ioPin, 2, po); // deallocate pins
|
||||
for (byte i=0; i<2; i++) ioPin[i] = newPin[i];
|
||||
setup();
|
||||
|
@ -249,7 +249,7 @@ class UsermodCronixie : public Usermod {
|
||||
|
||||
if (backlight && _digitOut[i] <11)
|
||||
{
|
||||
uint32_t col = strip.gamma32(strip.getSegment(0).colors[1]);
|
||||
uint32_t col = gamma32(strip.getSegment(0).colors[1]);
|
||||
for (uint16_t j=o; j< o+10; j++) {
|
||||
if (j != excl) strip.setPixelColor(j, col);
|
||||
}
|
||||
|
@ -355,7 +355,7 @@ public:
|
||||
// Color in grayscale bitmaps if Segment 1 exists
|
||||
// TODO If secondary and tertiary are black, color all in primary,
|
||||
// else color first three from Seg 1 color slots and last three from Seg 2 color slots
|
||||
WS2812FX::Segment& seg1 = strip.getSegment(tubeSegment);
|
||||
Segment& seg1 = strip.getSegment(tubeSegment);
|
||||
if (seg1.isActive()) {
|
||||
digitColor = strip.getPixelColor(seg1.start + digit);
|
||||
dimming = seg1.opacity;
|
||||
|
@ -63,7 +63,7 @@ class ElekstubeIPSUsermod : public Usermod {
|
||||
if (!toki.isTick()) return;
|
||||
updateLocalTime();
|
||||
|
||||
WS2812FX::Segment& seg1 = strip.getSegment(tfts.tubeSegment);
|
||||
Segment& seg1 = strip.getSegment(tfts.tubeSegment);
|
||||
if (seg1.isActive()) {
|
||||
bool update = false;
|
||||
if (seg1.opacity != lastBri) update = true;
|
||||
|
@ -143,15 +143,15 @@ private:
|
||||
}
|
||||
} else {
|
||||
if (m_offPreset) {
|
||||
applyPreset(m_offPreset, NotifyUpdateMode);
|
||||
if (currentPreset==m_onPreset || currentPlaylist==m_onPreset) applyPreset(m_offPreset, NotifyUpdateMode);
|
||||
return;
|
||||
} else if (prevPlaylist) {
|
||||
applyPreset(prevPlaylist, NotifyUpdateMode);
|
||||
if (currentPreset==m_onPreset || currentPlaylist==m_onPreset) applyPreset(prevPlaylist, NotifyUpdateMode);
|
||||
prevPlaylist = 0;
|
||||
return;
|
||||
} else if (prevPreset) {
|
||||
if (prevPreset<255) applyPreset(prevPreset, NotifyUpdateMode);
|
||||
else applyTemporaryPreset();
|
||||
if (prevPreset<255) { if (currentPreset==m_onPreset || currentPlaylist==m_onPreset) applyPreset(prevPreset, NotifyUpdateMode); }
|
||||
else { if (currentPreset==m_onPreset || currentPlaylist==m_onPreset) applyTemporaryPreset(); }
|
||||
prevPreset = 0;
|
||||
return;
|
||||
}
|
||||
@ -275,20 +275,9 @@ public:
|
||||
JsonObject user = root["u"];
|
||||
if (user.isNull()) user = root.createNestedObject("u");
|
||||
|
||||
String uiDomString = F("<button class=\"btn\" onclick=\"requestJson({");
|
||||
uiDomString += FPSTR(_name);
|
||||
uiDomString += F(":{");
|
||||
uiDomString += FPSTR(_enabled);
|
||||
if (enabled) {
|
||||
uiDomString += F(":false}});\">");
|
||||
uiDomString += F("PIR <i class=\"icons\"></i>");
|
||||
} else {
|
||||
uiDomString += F(":true}});\">");
|
||||
uiDomString += F("PIR <i class=\"icons\"></i>");
|
||||
}
|
||||
uiDomString += F("</button>");
|
||||
JsonArray infoArr = user.createNestedArray(uiDomString); // timer value
|
||||
JsonArray infoArr = user.createNestedArray(FPSTR(_name));
|
||||
|
||||
String uiDomString;
|
||||
if (enabled) {
|
||||
if (offTimerStart > 0)
|
||||
{
|
||||
@ -322,6 +311,20 @@ public:
|
||||
infoArr.add(F("disabled"));
|
||||
}
|
||||
|
||||
uiDomString = F(" <button class=\"btn btn-xs\" onclick=\"requestJson({");
|
||||
uiDomString += FPSTR(_name);
|
||||
uiDomString += F(":{");
|
||||
uiDomString += FPSTR(_enabled);
|
||||
if (enabled) {
|
||||
uiDomString += F(":false}});\">");
|
||||
uiDomString += F("<i class=\"icons on\"></i>");
|
||||
} else {
|
||||
uiDomString += F(":true}});\">");
|
||||
uiDomString += F("<i class=\"icons off\"></i>");
|
||||
}
|
||||
uiDomString += F("</button>");
|
||||
infoArr.add(uiDomString);
|
||||
|
||||
JsonObject sensor = root[F("sensor")];
|
||||
if (sensor.isNull()) sensor = root.createNestedObject(F("sensor"));
|
||||
sensor[F("motion")] = sensorPinState || offTimerStart>0 ? true : false;
|
||||
|
@ -51,6 +51,7 @@ class PWMFanUsermod : public Usermod {
|
||||
float targetTemperature = 25.0;
|
||||
uint8_t minPWMValuePct = 50;
|
||||
uint8_t numberOfInterrupsInOneSingleRotation = 2; // Number of interrupts ESP32 sees on tacho signal on a single fan rotation. All the fans I've seen trigger two interrups.
|
||||
uint8_t pwmValuePct = 0;
|
||||
|
||||
// strings to reduce flash memory usage (used more than twice)
|
||||
static const char _name[];
|
||||
@ -83,6 +84,8 @@ class PWMFanUsermod : public Usermod {
|
||||
}
|
||||
|
||||
void updateTacho(void) {
|
||||
// store milliseconds when tacho was measured the last time
|
||||
msLastTachoMeasurement = millis();
|
||||
if (tachoPin < 0) return;
|
||||
|
||||
// start of tacho measurement
|
||||
@ -93,8 +96,6 @@ class PWMFanUsermod : public Usermod {
|
||||
last_rpm /= tachoUpdateSec;
|
||||
// reset counter
|
||||
counter_rpm = 0;
|
||||
// store milliseconds when tacho was measured the last time
|
||||
msLastTachoMeasurement = millis();
|
||||
// attach interrupt again
|
||||
attachInterrupt(digitalPinToInterrupt(tachoPin), rpm_fan, FALLING);
|
||||
}
|
||||
@ -217,12 +218,30 @@ class PWMFanUsermod : public Usermod {
|
||||
* Below it is shown how this could be used for e.g. a light sensor
|
||||
*/
|
||||
void addToJsonInfo(JsonObject& root) {
|
||||
if (tachoPin < 0) return;
|
||||
JsonObject user = root["u"];
|
||||
if (user.isNull()) user = root.createNestedObject("u");
|
||||
JsonArray data = user.createNestedArray(FPSTR(_name));
|
||||
data.add(last_rpm);
|
||||
data.add(F("rpm"));
|
||||
if (enabled) {
|
||||
JsonObject user = root["u"];
|
||||
if (user.isNull()) user = root.createNestedObject("u");
|
||||
// if (!tempUM) {
|
||||
JsonArray infoArr = user.createNestedArray(F("Fan speed [%]"));
|
||||
String uiDomString = F("<div class=\"slider\"><div class=\"sliderwrap il\"><input class=\"noslide\" onchange=\"requestJson({'");
|
||||
uiDomString += FPSTR(_name);
|
||||
uiDomString += F("':{'");
|
||||
uiDomString += FPSTR(_speed);
|
||||
uiDomString += F("':parseInt(this.value)}});\" oninput=\"updateTrail(this);\" max=100 min=0 type=\"range\" value=");
|
||||
uiDomString += pwmValuePct;
|
||||
uiDomString += F(" /><div class=\"sliderdisplay\"></div></div></div>"); //<output class=\"sliderbubble\"></output>
|
||||
infoArr.add(uiDomString);
|
||||
// }
|
||||
if (tachoPin >= 0) {
|
||||
JsonArray data = user.createNestedArray(FPSTR(_name));
|
||||
data.add(last_rpm);
|
||||
data.add(F("rpm"));
|
||||
} else {
|
||||
JsonArray data = user.createNestedArray(FPSTR(_name));
|
||||
if (lockFan) data.add(F("locked"));
|
||||
else data.add(F("auto"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3,14 +3,6 @@
|
||||
#include "src/dependencies/time/DS1307RTC.h"
|
||||
#include "wled.h"
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#define HW_PIN_SCL 22
|
||||
#define HW_PIN_SDA 21
|
||||
#else
|
||||
#define HW_PIN_SCL 5
|
||||
#define HW_PIN_SDA 4
|
||||
#endif
|
||||
|
||||
//Connect DS1307 to standard I2C pins (ESP32: GPIO 21 (SDA)/GPIO 22 (SCL))
|
||||
|
||||
class RTCUsermod : public Usermod {
|
||||
@ -20,8 +12,9 @@ class RTCUsermod : public Usermod {
|
||||
public:
|
||||
|
||||
void setup() {
|
||||
PinManagerPinType pins[2] = { { HW_PIN_SCL, true }, { HW_PIN_SDA, true } };
|
||||
PinManagerPinType pins[2] = { { i2c_scl, true }, { i2c_sda, true } };
|
||||
if (!pinManager.allocateMultiplePins(pins, 2, PinOwner::HW_I2C)) { disabled = true; return; }
|
||||
RTC.begin();
|
||||
time_t rtcTime = RTC.get();
|
||||
if (rtcTime) {
|
||||
toki.setTime(rtcTime,TOKI_NO_MS_ACCURACY,TOKI_TS_RTC);
|
||||
@ -44,13 +37,13 @@ class RTCUsermod : public Usermod {
|
||||
* It will be called by WLED when settings are actually saved (for example, LED settings are saved)
|
||||
* I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings!
|
||||
*/
|
||||
void addToConfig(JsonObject& root)
|
||||
{
|
||||
JsonObject top = root.createNestedObject("RTC");
|
||||
JsonArray pins = top.createNestedArray("pin");
|
||||
pins.add(HW_PIN_SCL);
|
||||
pins.add(HW_PIN_SDA);
|
||||
}
|
||||
// void addToConfig(JsonObject& root)
|
||||
// {
|
||||
// JsonObject top = root.createNestedObject("RTC");
|
||||
// JsonArray pins = top.createNestedArray("pin");
|
||||
// pins.add(i2c_scl);
|
||||
// pins.add(i2c_sda);
|
||||
// }
|
||||
|
||||
uint16_t getId()
|
||||
{
|
||||
|
@ -21,14 +21,6 @@
|
||||
#include <Wire.h>
|
||||
#include <VL53L0X.h>
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#define HW_PIN_SCL 22
|
||||
#define HW_PIN_SDA 21
|
||||
#else
|
||||
#define HW_PIN_SCL 5
|
||||
#define HW_PIN_SDA 4
|
||||
#endif
|
||||
|
||||
#ifndef VL53L0X_MAX_RANGE_MM
|
||||
#define VL53L0X_MAX_RANGE_MM 230 // max height in millimiters to react for motions
|
||||
#endif
|
||||
@ -59,7 +51,7 @@ class UsermodVL53L0XGestures : public Usermod {
|
||||
public:
|
||||
|
||||
void setup() {
|
||||
PinManagerPinType pins[2] = { { HW_PIN_SCL, true }, { HW_PIN_SDA, true } };
|
||||
PinManagerPinType pins[2] = { { i2c_scl, true }, { i2c_sda, true } };
|
||||
if (!pinManager.allocateMultiplePins(pins, 2, PinOwner::HW_I2C)) { enabled = false; return; }
|
||||
Wire.begin();
|
||||
|
||||
@ -127,13 +119,13 @@ class UsermodVL53L0XGestures : public Usermod {
|
||||
* It will be called by WLED when settings are actually saved (for example, LED settings are saved)
|
||||
* I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings!
|
||||
*/
|
||||
void addToConfig(JsonObject& root)
|
||||
{
|
||||
JsonObject top = root.createNestedObject("VL53L0x");
|
||||
JsonArray pins = top.createNestedArray("pin");
|
||||
pins.add(HW_PIN_SCL);
|
||||
pins.add(HW_PIN_SDA);
|
||||
}
|
||||
// void addToConfig(JsonObject& root)
|
||||
// {
|
||||
// JsonObject top = root.createNestedObject("VL53L0x");
|
||||
// JsonArray pins = top.createNestedArray("pin");
|
||||
// pins.add(i2c_scl);
|
||||
// pins.add(i2c_sda);
|
||||
// }
|
||||
|
||||
/*
|
||||
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
|
||||
|
1494
usermods/audioreactive/audio_reactive.h
Normal file
1494
usermods/audioreactive/audio_reactive.h
Normal file
File diff suppressed because it is too large
Load Diff
508
usermods/audioreactive/audio_source.h
Normal file
508
usermods/audioreactive/audio_source.h
Normal file
@ -0,0 +1,508 @@
|
||||
#pragma once
|
||||
|
||||
#include <Wire.h>
|
||||
#include "wled.h"
|
||||
#include <driver/i2s.h>
|
||||
#include <driver/adc.h>
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0)
|
||||
#include <driver/adc_deprecated.h>
|
||||
#include <driver/adc_types_deprecated.h>
|
||||
#endif
|
||||
|
||||
//#include <driver/i2s_std.h>
|
||||
//#include <driver/i2s_pdm.h>
|
||||
//#include <driver/gpio.h>
|
||||
|
||||
|
||||
/* ToDo: remove. ES7243 is controlled via compiler defines
|
||||
Until this configuration is moved to the webinterface
|
||||
*/
|
||||
|
||||
// if you have problems to get your microphone work on the left channel, uncomment the following line
|
||||
//#define I2S_USE_RIGHT_CHANNEL // (experimental) define this to use right channel (digital mics only)
|
||||
#ifdef I2S_USE_RIGHT_CHANNEL
|
||||
#define I2S_MIC_CHANNEL I2S_CHANNEL_FMT_ONLY_RIGHT
|
||||
#define I2S_MIC_CHANNEL_TEXT "right channel only."
|
||||
#else
|
||||
#define I2S_MIC_CHANNEL I2S_CHANNEL_FMT_ONLY_LEFT
|
||||
#define I2S_MIC_CHANNEL_TEXT "left channel only."
|
||||
#endif
|
||||
|
||||
// Uncomment the line below to utilize ADC1 _exclusively_ for I2S sound input.
|
||||
// benefit: analog mic inputs will be sampled contiously -> better response times and less "glitches"
|
||||
// WARNING: this option WILL lock-up your device in case that any other analogRead() operation is performed;
|
||||
// for example if you want to read "analog buttons"
|
||||
//#define I2S_GRAB_ADC1_COMPLETELY // (experimental) continously sample analog ADC microphone. WARNING will cause analogRead() lock-up
|
||||
|
||||
// data type requested from the I2S driver - currently we always use 32bit
|
||||
//#define I2S_USE_16BIT_SAMPLES // (experimental) define this to request 16bit - more efficient but possibly less compatible
|
||||
#ifdef I2S_USE_16BIT_SAMPLES
|
||||
#define I2S_SAMPLE_RESOLUTION I2S_BITS_PER_SAMPLE_16BIT
|
||||
#define I2S_datatype int16_t
|
||||
#define I2S_unsigned_datatype uint16_t
|
||||
#undef I2S_SAMPLE_DOWNSCALE_TO_16BIT
|
||||
#else
|
||||
#define I2S_SAMPLE_RESOLUTION I2S_BITS_PER_SAMPLE_32BIT
|
||||
#define I2S_datatype int32_t
|
||||
#define I2S_unsigned_datatype uint32_t
|
||||
#define I2S_SAMPLE_DOWNSCALE_TO_16BIT
|
||||
#endif
|
||||
|
||||
/* Interface class
|
||||
AudioSource serves as base class for all microphone types
|
||||
This enables accessing all microphones with one single interface
|
||||
which simplifies the caller code
|
||||
*/
|
||||
class AudioSource {
|
||||
public:
|
||||
/* All public methods are virtual, so they can be overridden
|
||||
Everything but the destructor is also removed, to make sure each mic
|
||||
Implementation provides its version of this function
|
||||
*/
|
||||
virtual ~AudioSource() {};
|
||||
|
||||
/* Initialize
|
||||
This function needs to take care of anything that needs to be done
|
||||
before samples can be obtained from the microphone.
|
||||
*/
|
||||
virtual void initialize(int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE) = 0;
|
||||
|
||||
/* Deinitialize
|
||||
Release all resources and deactivate any functionality that is used
|
||||
by this microphone
|
||||
*/
|
||||
virtual void deinitialize() = 0;
|
||||
|
||||
/* getSamples
|
||||
Read num_samples from the microphone, and store them in the provided
|
||||
buffer
|
||||
*/
|
||||
virtual void getSamples(float *buffer, uint16_t num_samples) = 0;
|
||||
|
||||
/* check if the audio source driver was initialized successfully */
|
||||
virtual bool isInitialized(void) {return(_initialized);}
|
||||
|
||||
/* identify Audiosource type - I2S-ADC or I2S-digital */
|
||||
typedef enum{Type_unknown=0, Type_I2SAdc=1, Type_I2SDigital=2} AudioSourceType;
|
||||
virtual AudioSourceType getType(void) {return(Type_I2SDigital);} // default is "I2S digital source" - ADC type overrides this method
|
||||
|
||||
protected:
|
||||
/* Post-process audio sample - currently on needed for I2SAdcSource*/
|
||||
virtual I2S_datatype postProcessSample(I2S_datatype sample_in) {return(sample_in);} // default method can be overriden by instances (ADC) that need sample postprocessing
|
||||
|
||||
// Private constructor, to make sure it is not callable except from derived classes
|
||||
AudioSource(int sampleRate, int blockSize) :
|
||||
_sampleRate(sampleRate),
|
||||
_blockSize(blockSize),
|
||||
_initialized(false)
|
||||
{};
|
||||
|
||||
int _sampleRate; // Microphone sampling rate
|
||||
int _blockSize; // I2S block size
|
||||
bool _initialized; // Gets set to true if initialization is successful
|
||||
};
|
||||
|
||||
/* Basic I2S microphone source
|
||||
All functions are marked virtual, so derived classes can replace them
|
||||
*/
|
||||
class I2SSource : public AudioSource {
|
||||
public:
|
||||
I2SSource(int sampleRate, int blockSize) :
|
||||
AudioSource(sampleRate, blockSize) {
|
||||
_config = {
|
||||
.mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX),
|
||||
.sample_rate = _sampleRate,
|
||||
.bits_per_sample = I2S_SAMPLE_RESOLUTION,
|
||||
.channel_format = I2S_MIC_CHANNEL,
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0)
|
||||
.communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_STAND_I2S),
|
||||
#else
|
||||
.communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB),
|
||||
#endif
|
||||
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = _blockSize
|
||||
};
|
||||
}
|
||||
|
||||
virtual void initialize(int8_t i2swsPin = I2S_PIN_NO_CHANGE, int8_t i2ssdPin = I2S_PIN_NO_CHANGE, int8_t i2sckPin = I2S_PIN_NO_CHANGE, int8_t mclkPin = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE) {
|
||||
if (i2swsPin != I2S_PIN_NO_CHANGE && i2ssdPin != I2S_PIN_NO_CHANGE) {
|
||||
if (!pinManager.allocatePin(i2swsPin, true, PinOwner::UM_Audioreactive) ||
|
||||
!pinManager.allocatePin(i2ssdPin, false, PinOwner::UM_Audioreactive)) { // #206
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// i2ssckPin needs special treatment, since it might be unused on PDM mics
|
||||
if (i2sckPin != I2S_PIN_NO_CHANGE) {
|
||||
if (!pinManager.allocatePin(i2sckPin, true, PinOwner::UM_Audioreactive)) return;
|
||||
} else {
|
||||
// This is an I2S PDM microphone, these microphones only use a clock and
|
||||
// data line, to make it simpler to debug, use the WS pin as CLK and SD
|
||||
// pin as DATA
|
||||
_config.mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_PDM); // Change mode to pdm if clock pin not provided
|
||||
}
|
||||
|
||||
// Reserve the master clock pin if provided
|
||||
_mclkPin = mclkPin;
|
||||
if (mclkPin != I2S_PIN_NO_CHANGE) {
|
||||
if(!pinManager.allocatePin(mclkPin, true, PinOwner::UM_Audioreactive)) return;
|
||||
_routeMclk(mclkPin);
|
||||
}
|
||||
|
||||
_pinConfig = {
|
||||
.bck_io_num = i2sckPin,
|
||||
.ws_io_num = i2swsPin,
|
||||
.data_out_num = I2S_PIN_NO_CHANGE,
|
||||
.data_in_num = i2ssdPin
|
||||
};
|
||||
|
||||
esp_err_t err = i2s_driver_install(I2S_NUM_0, &_config, 0, nullptr);
|
||||
if (err != ESP_OK) {
|
||||
DEBUGSR_PRINTF("Failed to install i2s driver: %d\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
err = i2s_set_pin(I2S_NUM_0, &_pinConfig);
|
||||
if (err != ESP_OK) {
|
||||
DEBUGSR_PRINTF("Failed to set i2s pin config: %d\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
virtual void deinitialize() {
|
||||
_initialized = false;
|
||||
esp_err_t err = i2s_driver_uninstall(I2S_NUM_0);
|
||||
if (err != ESP_OK) {
|
||||
DEBUGSR_PRINTF("Failed to uninstall i2s driver: %d\n", err);
|
||||
return;
|
||||
}
|
||||
if (_pinConfig.ws_io_num != I2S_PIN_NO_CHANGE) pinManager.deallocatePin(_pinConfig.ws_io_num, PinOwner::UM_Audioreactive);
|
||||
if (_pinConfig.data_in_num != I2S_PIN_NO_CHANGE) pinManager.deallocatePin(_pinConfig.data_in_num, PinOwner::UM_Audioreactive);
|
||||
if (_pinConfig.bck_io_num != I2S_PIN_NO_CHANGE) pinManager.deallocatePin(_pinConfig.bck_io_num, PinOwner::UM_Audioreactive);
|
||||
// Release the master clock pin
|
||||
if (_mclkPin != I2S_PIN_NO_CHANGE) pinManager.deallocatePin(_mclkPin, PinOwner::UM_Audioreactive);
|
||||
}
|
||||
|
||||
virtual void getSamples(float *buffer, uint16_t num_samples) {
|
||||
if (_initialized) {
|
||||
esp_err_t err;
|
||||
size_t bytes_read = 0; /* Counter variable to check if we actually got enough data */
|
||||
I2S_datatype newSamples[num_samples]; /* Intermediary sample storage */
|
||||
|
||||
err = i2s_read(I2S_NUM_0, (void *)newSamples, sizeof(newSamples), &bytes_read, portMAX_DELAY);
|
||||
if (err != ESP_OK) {
|
||||
DEBUGSR_PRINTF("Failed to get samples: %d\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
// For correct operation, we need to read exactly sizeof(samples) bytes from i2s
|
||||
if (bytes_read != sizeof(newSamples)) {
|
||||
DEBUGSR_PRINTF("Failed to get enough samples: wanted: %d read: %d\n", sizeof(newSamples), bytes_read);
|
||||
return;
|
||||
}
|
||||
|
||||
// Store samples in sample buffer and update DC offset
|
||||
for (int i = 0; i < num_samples; i++) {
|
||||
|
||||
newSamples[i] = postProcessSample(newSamples[i]); // perform postprocessing (needed for ADC samples)
|
||||
|
||||
float currSample = 0.0f;
|
||||
#ifdef I2S_SAMPLE_DOWNSCALE_TO_16BIT
|
||||
currSample = (float) newSamples[i] / 65536.0f; // 32bit input -> 16bit; keeping lower 16bits as decimal places
|
||||
#else
|
||||
currSample = (float) newSamples[i]; // 16bit input -> use as-is
|
||||
#endif
|
||||
buffer[i] = currSample;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
void _routeMclk(int8_t mclkPin) {
|
||||
/* Enable the mclk routing depending on the selected mclk pin
|
||||
Only I2S_NUM_0 is supported
|
||||
*/
|
||||
if (mclkPin == GPIO_NUM_0) {
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1);
|
||||
WRITE_PERI_REG(PIN_CTRL,0xFFF0);
|
||||
} else if (mclkPin == GPIO_NUM_1) {
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_CLK_OUT3);
|
||||
WRITE_PERI_REG(PIN_CTRL, 0xF0F0);
|
||||
} else {
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_CLK_OUT2);
|
||||
WRITE_PERI_REG(PIN_CTRL, 0xFF00);
|
||||
}
|
||||
}
|
||||
|
||||
i2s_config_t _config;
|
||||
i2s_pin_config_t _pinConfig;
|
||||
int8_t _mclkPin;
|
||||
};
|
||||
|
||||
/* ES7243 Microphone
|
||||
This is an I2S microphone that requires ininitialization over
|
||||
I2C before I2S data can be received
|
||||
*/
|
||||
class ES7243 : public I2SSource {
|
||||
private:
|
||||
// I2C initialization functions for ES7243
|
||||
void _es7243I2cBegin() {
|
||||
Wire.begin(pin_ES7243_SDA, pin_ES7243_SCL, 100000U);
|
||||
}
|
||||
|
||||
void _es7243I2cWrite(uint8_t reg, uint8_t val) {
|
||||
#ifndef ES7243_ADDR
|
||||
Wire.beginTransmission(0x13);
|
||||
#else
|
||||
Wire.beginTransmission(ES7243_ADDR);
|
||||
#endif
|
||||
Wire.write((uint8_t)reg);
|
||||
Wire.write((uint8_t)val);
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
void _es7243InitAdc() {
|
||||
_es7243I2cBegin();
|
||||
_es7243I2cWrite(0x00, 0x01);
|
||||
_es7243I2cWrite(0x06, 0x00);
|
||||
_es7243I2cWrite(0x05, 0x1B);
|
||||
_es7243I2cWrite(0x01, 0x00); // 0x00 for 24 bit to match INMP441 - not sure if this needs adjustment to get 16bit samples from I2S
|
||||
_es7243I2cWrite(0x08, 0x43);
|
||||
_es7243I2cWrite(0x05, 0x13);
|
||||
}
|
||||
|
||||
public:
|
||||
ES7243(int sampleRate, int blockSize) :
|
||||
I2SSource(sampleRate, blockSize) {
|
||||
_config.channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT;
|
||||
};
|
||||
|
||||
void initialize(int8_t sdaPin, int8_t sclPin, int8_t i2swsPin, int8_t i2ssdPin, int8_t i2sckPin, int8_t mclkPin) {
|
||||
// Reserve SDA and SCL pins of the I2C interface
|
||||
if (!pinManager.allocatePin(sdaPin, true, PinOwner::HW_I2C) ||
|
||||
!pinManager.allocatePin(sclPin, true, PinOwner::HW_I2C)) {
|
||||
return;
|
||||
}
|
||||
|
||||
pin_ES7243_SDA = sdaPin;
|
||||
pin_ES7243_SCL = sclPin;
|
||||
|
||||
// First route mclk, then configure ADC over I2C, then configure I2S
|
||||
_es7243InitAdc();
|
||||
I2SSource::initialize(i2swsPin, i2ssdPin, i2sckPin, mclkPin);
|
||||
}
|
||||
|
||||
void deinitialize() {
|
||||
// Release SDA and SCL pins of the I2C interface
|
||||
pinManager.deallocatePin(pin_ES7243_SDA, PinOwner::HW_I2C);
|
||||
pinManager.deallocatePin(pin_ES7243_SCL, PinOwner::HW_I2C);
|
||||
I2SSource::deinitialize();
|
||||
}
|
||||
|
||||
private:
|
||||
int8_t pin_ES7243_SDA;
|
||||
int8_t pin_ES7243_SCL;
|
||||
};
|
||||
|
||||
/* ADC over I2S Microphone
|
||||
This microphone is an ADC pin sampled via the I2S interval
|
||||
This allows to use the I2S API to obtain ADC samples with high sample rates
|
||||
without the need of manual timing of the samples
|
||||
*/
|
||||
class I2SAdcSource : public I2SSource {
|
||||
public:
|
||||
I2SAdcSource(int sampleRate, int blockSize) :
|
||||
I2SSource(sampleRate, blockSize) {
|
||||
_config = {
|
||||
.mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN),
|
||||
.sample_rate = _sampleRate,
|
||||
.bits_per_sample = I2S_SAMPLE_RESOLUTION,
|
||||
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0)
|
||||
.communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_STAND_I2S),
|
||||
#else
|
||||
.communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB),
|
||||
#endif
|
||||
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = _blockSize,
|
||||
.use_apll = false,
|
||||
.tx_desc_auto_clear = false,
|
||||
.fixed_mclk = 0
|
||||
};
|
||||
}
|
||||
|
||||
/* identify Audiosource type - I2S-ADC*/
|
||||
AudioSourceType getType(void) {return(Type_I2SAdc);}
|
||||
|
||||
void initialize(int8_t audioPin, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE) {
|
||||
_myADCchannel = 0x0F;
|
||||
if(!pinManager.allocatePin(audioPin, false, PinOwner::UM_Audioreactive)) {
|
||||
DEBUGSR_PRINTF("failed to allocate GPIO for audio analog input: %d\n", audioPin);
|
||||
return;
|
||||
}
|
||||
_audioPin = audioPin;
|
||||
|
||||
// Determine Analog channel. Only Channels on ADC1 are supported
|
||||
int8_t channel = digitalPinToAnalogChannel(_audioPin);
|
||||
if (channel > 9) {
|
||||
DEBUGSR_PRINTF("Incompatible GPIO used for audio in: %d\n", _audioPin);
|
||||
return;
|
||||
} else {
|
||||
adc_gpio_init(ADC_UNIT_1, adc_channel_t(channel));
|
||||
_myADCchannel = channel;
|
||||
}
|
||||
|
||||
// Install Driver
|
||||
esp_err_t err = i2s_driver_install(I2S_NUM_0, &_config, 0, nullptr);
|
||||
if (err != ESP_OK) {
|
||||
DEBUGSR_PRINTF("Failed to install i2s driver: %d\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
// Enable I2S mode of ADC
|
||||
err = i2s_set_adc_mode(ADC_UNIT_1, adc1_channel_t(channel));
|
||||
if (err != ESP_OK) {
|
||||
DEBUGSR_PRINTF("Failed to set i2s adc mode: %d\n", err);
|
||||
return;
|
||||
}
|
||||
// adc1_config_channel_atten(adc1_channel_t(channel), ADC_ATTEN_DB_11)); //see https://github.com/espressif/arduino-esp32/blob/master/libraries/ESP32/examples/I2S/HiFreq_ADC/HiFreq_ADC.ino
|
||||
|
||||
#if defined(I2S_GRAB_ADC1_COMPLETELY)
|
||||
// according to docs from espressif, the ADC needs to be started explicitly
|
||||
// fingers crossed
|
||||
err = i2s_adc_enable(I2S_NUM_0);
|
||||
if (err != ESP_OK) {
|
||||
DEBUGSR_PRINTF("Failed to enable i2s adc: %d\n", err);
|
||||
//return;
|
||||
}
|
||||
#else
|
||||
err = i2s_adc_disable(I2S_NUM_0);
|
||||
//err = i2s_stop(I2S_NUM_0);
|
||||
if (err != ESP_OK) {
|
||||
DEBUGSR_PRINTF("Failed to initially disable i2s adc: %d\n", err);
|
||||
}
|
||||
#endif
|
||||
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
|
||||
I2S_datatype postProcessSample(I2S_datatype sample_in) {
|
||||
static I2S_datatype lastADCsample = 0; // last good sample
|
||||
static unsigned int broken_samples_counter = 0; // number of consecutive broken (and fixed) ADC samples
|
||||
I2S_datatype sample_out = 0;
|
||||
|
||||
// bring sample down down to 16bit unsigned
|
||||
I2S_unsigned_datatype rawData = * reinterpret_cast<I2S_unsigned_datatype *> (&sample_in); // C++ acrobatics to get sample as "unsigned"
|
||||
#ifndef I2S_USE_16BIT_SAMPLES
|
||||
rawData = (rawData >> 16) & 0xFFFF; // scale input down from 32bit -> 16bit
|
||||
I2S_datatype lastGoodSample = lastADCsample / 16384 ; // prepare "last good sample" accordingly (26bit-> 12bit with correct sign handling)
|
||||
#else
|
||||
rawData = rawData & 0xFFFF; // input is already in 16bit, just mask off possible junk
|
||||
I2S_datatype lastGoodSample = lastADCsample * 4; // prepare "last good sample" accordingly (10bit-> 12bit)
|
||||
#endif
|
||||
|
||||
// decode ADC sample data fields
|
||||
uint16_t the_channel = (rawData >> 12) & 0x000F; // upper 4 bit = ADC channel
|
||||
uint16_t the_sample = rawData & 0x0FFF; // lower 12bit -> ADC sample (unsigned)
|
||||
I2S_datatype finalSample = (int(the_sample) - 2048); // convert unsigned sample to signed (centered at 0);
|
||||
|
||||
if ((the_channel != _myADCchannel) && (_myADCchannel != 0x0F)) { // 0x0F means "don't know what my channel is"
|
||||
// fix bad sample
|
||||
finalSample = lastGoodSample; // replace with last good ADC sample
|
||||
broken_samples_counter ++;
|
||||
if (broken_samples_counter > 256) _myADCchannel = 0x0F; // too many bad samples in a row -> disable sample corrections
|
||||
//Serial.print("\n!ADC rogue sample 0x"); Serial.print(rawData, HEX); Serial.print("\tchannel:");Serial.println(the_channel);
|
||||
} else broken_samples_counter = 0; // good sample - reset counter
|
||||
|
||||
// back to original resolution
|
||||
#ifndef I2S_USE_16BIT_SAMPLES
|
||||
finalSample = finalSample << 16; // scale up from 16bit -> 32bit;
|
||||
#endif
|
||||
|
||||
finalSample = finalSample / 4; // mimic old analog driver behaviour (12bit -> 10bit)
|
||||
sample_out = (3 * finalSample + lastADCsample) / 4; // apply low-pass filter (2-tap FIR)
|
||||
//sample_out = (finalSample + lastADCsample) / 2; // apply stronger low-pass filter (2-tap FIR)
|
||||
|
||||
lastADCsample = sample_out; // update ADC last sample
|
||||
return(sample_out);
|
||||
}
|
||||
|
||||
|
||||
void getSamples(float *buffer, uint16_t num_samples) {
|
||||
/* Enable ADC. This has to be enabled and disabled directly before and
|
||||
* after sampling, otherwise Wifi dies
|
||||
*/
|
||||
if (_initialized) {
|
||||
#if !defined(I2S_GRAB_ADC1_COMPLETELY)
|
||||
// old code - works for me without enable/disable, at least on ESP32.
|
||||
//esp_err_t err = i2s_start(I2S_NUM_0);
|
||||
esp_err_t err = i2s_adc_enable(I2S_NUM_0);
|
||||
if (err != ESP_OK) {
|
||||
DEBUGSR_PRINTF("Failed to enable i2s adc: %d\n", err);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
I2SSource::getSamples(buffer, num_samples);
|
||||
|
||||
#if !defined(I2S_GRAB_ADC1_COMPLETELY)
|
||||
// old code - works for me without enable/disable, at least on ESP32.
|
||||
err = i2s_adc_disable(I2S_NUM_0); //i2s_adc_disable() may cause crash with IDF 4.4 (https://github.com/espressif/arduino-esp32/issues/6832)
|
||||
//err = i2s_stop(I2S_NUM_0);
|
||||
if (err != ESP_OK) {
|
||||
DEBUGSR_PRINTF("Failed to disable i2s adc: %d\n", err);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void deinitialize() {
|
||||
pinManager.deallocatePin(_audioPin, PinOwner::UM_Audioreactive);
|
||||
_initialized = false;
|
||||
_myADCchannel = 0x0F;
|
||||
|
||||
esp_err_t err;
|
||||
#if defined(I2S_GRAB_ADC1_COMPLETELY)
|
||||
// according to docs from espressif, the ADC needs to be stopped explicitly
|
||||
// fingers crossed
|
||||
err = i2s_adc_disable(I2S_NUM_0);
|
||||
if (err != ESP_OK) {
|
||||
DEBUGSR_PRINTF("Failed to disable i2s adc: %d\n", err);
|
||||
}
|
||||
#endif
|
||||
|
||||
i2s_stop(I2S_NUM_0);
|
||||
err = i2s_driver_uninstall(I2S_NUM_0);
|
||||
if (err != ESP_OK) {
|
||||
DEBUGSR_PRINTF("Failed to uninstall i2s driver: %d\n", err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
int8_t _audioPin;
|
||||
int8_t _myADCchannel = 0x0F; // current ADC channel for analog input. 0x0F means "undefined"
|
||||
};
|
||||
|
||||
/* SPH0645 Microphone
|
||||
This is an I2S microphone with some timing quirks that need
|
||||
special consideration.
|
||||
*/
|
||||
class SPH0654 : public I2SSource {
|
||||
public:
|
||||
SPH0654(int sampleRate, int blockSize) :
|
||||
I2SSource(sampleRate, blockSize)
|
||||
{}
|
||||
|
||||
void initialize(uint8_t i2swsPin, uint8_t i2ssdPin, uint8_t i2sckPin, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE) {
|
||||
I2SSource::initialize(i2swsPin, i2ssdPin, i2sckPin);
|
||||
REG_SET_BIT(I2S_TIMING_REG(I2S_NUM_0), BIT(9));
|
||||
REG_SET_BIT(I2S_CONF_REG(I2S_NUM_0), I2S_RX_MSB_SHIFT);
|
||||
}
|
||||
};
|
36
usermods/audioreactive/readme.md
Normal file
36
usermods/audioreactive/readme.md
Normal file
@ -0,0 +1,36 @@
|
||||
# Audioreactive usermod
|
||||
|
||||
This usermod allows controlling LEDs using audio input. Audio input can be either microphone or analog-in (AUX) using appropriate adapter.
|
||||
Supported microphones range from analog (MAX4466, MAX9814, ...) to digital (INMP441, ICS-43434, ...).
|
||||
|
||||
The usermod does audio processing and provides data structure that specially written effect can use.
|
||||
|
||||
The usermod **does not** provide effects or draws anything to LED strip/matrix.
|
||||
|
||||
## Installation
|
||||
|
||||
Add `-D USERMOD_AUDIOREACTIVE` to your PlatformIO environment as well as `arduinoFFT` to your `lib_deps`.
|
||||
If you are not using PlatformIO (which you should) try adding `#define USERMOD_AUDIOREACTIVE` to *my_config.h* and make sure you have _arduinoFFT_ library downloaded and installed.
|
||||
|
||||
Customised _arduinoFFT_ library for use with this usermod can be found at https://github.com/blazoncek/arduinoFFT.git
|
||||
|
||||
## Configuration
|
||||
|
||||
All parameters are runtime configurable though some may require hard boot after change (I2S microphone or selected GPIOs).
|
||||
|
||||
If you want to define default GPIOs during compile time use the following (default values in parentheses):
|
||||
|
||||
- `DMTYPE=x` : defines digital microphone type: 0=analog, 1=generic I2S, 2=ES7243 I2S, 3=SPH0645 I2S, 4=generic I2S with master clock, 5=PDM I2S
|
||||
- `AUDIOPIN=x` : GPIO for analog microphone/AUX-in (36)
|
||||
- `I2S_SDPIN=x` : GPIO for SD pin on digital mcrophone (32)
|
||||
- `I2S_WSPIN=x` : GPIO for WS pin on digital mcrophone (15)
|
||||
- `I2S_CKPIN=x` : GPIO for SCK pin on digital mcrophone (14)
|
||||
- `ES7243_SDAPIN` : GPIO for I2C SDA pin on ES7243 microphone (-1)
|
||||
- `ES7243_SCLPIN` : GPIO for I2C SCL pin on ES7243 microphone (-1)
|
||||
- `MCLK_PIN=x` : GPIO for master clock pin on digital mcrophone (-1)
|
||||
|
||||
**NOTE** Due to the fact that usermod uses I2S peripherial for analog audio sampling, use of analog *buttons* (i.e. potentiometers) is disabled while running this usermod with analog microphone.
|
||||
|
||||
## Release notes
|
||||
|
||||
2022-06 Ported from [soundreactive](https://github.com/atuline/WLED) by @blazoncek (AKA Blaz Kristan)
|
@ -42,14 +42,6 @@
|
||||
#include "Wire.h"
|
||||
#endif
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#define HW_PIN_SCL 22
|
||||
#define HW_PIN_SDA 21
|
||||
#else
|
||||
#define HW_PIN_SCL 5
|
||||
#define HW_PIN_SDA 4
|
||||
#endif
|
||||
|
||||
// ================================================================
|
||||
// === INTERRUPT DETECTION ROUTINE ===
|
||||
// ================================================================
|
||||
@ -93,7 +85,7 @@ class MPU6050Driver : public Usermod {
|
||||
* setup() is called once at boot. WiFi is not yet connected at this point.
|
||||
*/
|
||||
void setup() {
|
||||
PinManagerPinType pins[2] = { { HW_PIN_SCL, true }, { HW_PIN_SDA, true } };
|
||||
PinManagerPinType pins[2] = { { i2c_scl, true }, { i2c_sda, true } };
|
||||
if (!pinManager.allocateMultiplePins(pins, 2, PinOwner::HW_I2C)) { enabled = false; return; }
|
||||
// join I2C bus (I2Cdev library doesn't do this automatically)
|
||||
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
|
||||
@ -258,20 +250,20 @@ class MPU6050Driver : public Usermod {
|
||||
* addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
|
||||
* Values in the state object may be modified by connected clients
|
||||
*/
|
||||
void addToJsonState(JsonObject& root)
|
||||
{
|
||||
//void addToJsonState(JsonObject& root)
|
||||
//{
|
||||
//root["user0"] = userVar0;
|
||||
}
|
||||
//}
|
||||
|
||||
|
||||
/*
|
||||
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
|
||||
* Values in the state object may be modified by connected clients
|
||||
*/
|
||||
void readFromJsonState(JsonObject& root)
|
||||
{
|
||||
//void readFromJsonState(JsonObject& root)
|
||||
//{
|
||||
//if (root["bri"] == 255) DEBUG_PRINTLN(F("Don't burn down your garage!"));
|
||||
}
|
||||
//}
|
||||
|
||||
|
||||
/*
|
||||
@ -279,13 +271,13 @@ class MPU6050Driver : public Usermod {
|
||||
* It will be called by WLED when settings are actually saved (for example, LED settings are saved)
|
||||
* I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings!
|
||||
*/
|
||||
void addToConfig(JsonObject& root)
|
||||
{
|
||||
JsonObject top = root.createNestedObject("MPU6050_IMU");
|
||||
JsonArray pins = top.createNestedArray("pin");
|
||||
pins.add(HW_PIN_SCL);
|
||||
pins.add(HW_PIN_SDA);
|
||||
}
|
||||
// void addToConfig(JsonObject& root)
|
||||
// {
|
||||
// JsonObject top = root.createNestedObject("MPU6050_IMU");
|
||||
// JsonArray pins = top.createNestedArray("pin");
|
||||
// pins.add(HW_PIN_SCL);
|
||||
// pins.add(HW_PIN_SDA);
|
||||
// }
|
||||
|
||||
/*
|
||||
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
|
||||
|
@ -468,13 +468,17 @@ class MultiRelay : public Usermod {
|
||||
if (user.isNull())
|
||||
user = root.createNestedObject("u");
|
||||
|
||||
JsonArray infoArr = user.createNestedArray(F("Number of relays")); //name
|
||||
JsonArray infoArr = user.createNestedArray(FPSTR(_name)); //name
|
||||
infoArr.add(String(getActiveRelayCount()));
|
||||
infoArr.add(F(" relays"));
|
||||
|
||||
String uiDomString;
|
||||
for (uint8_t i=0; i<MULTI_RELAY_MAX_RELAYS; i++) {
|
||||
if (_relay[i].pin<0 || !_relay[i].external) continue;
|
||||
uiDomString = F("<button class=\"btn\" onclick=\"requestJson({");
|
||||
uiDomString = F("Relay "); uiDomString += i;
|
||||
JsonArray infoArr = user.createNestedArray(uiDomString); // timer value
|
||||
|
||||
uiDomString = F("<button class=\"btn btn-xs\" onclick=\"requestJson({");
|
||||
uiDomString += FPSTR(_name);
|
||||
uiDomString += F(":{");
|
||||
uiDomString += FPSTR(_relay_str);
|
||||
@ -483,12 +487,10 @@ class MultiRelay : public Usermod {
|
||||
uiDomString += F(",on:");
|
||||
uiDomString += _relay[i].state ? "false" : "true";
|
||||
uiDomString += F("}});\">");
|
||||
uiDomString += F("Relay ");
|
||||
uiDomString += i;
|
||||
uiDomString += F(" <i class=\"icons\"></i></button>");
|
||||
JsonArray infoArr = user.createNestedArray(uiDomString); // timer value
|
||||
|
||||
infoArr.add(_relay[i].state ? "on" : "off");
|
||||
uiDomString += F("<i class=\"icons");
|
||||
uiDomString += _relay[i].state ? F(" on") : F(" off");
|
||||
uiDomString += F("\"></i></button>");
|
||||
infoArr.add(uiDomString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ class StairwayWipeUsermod : public Usermod {
|
||||
resetTimebase(); //make sure wipe starts from beginning
|
||||
|
||||
//set wipe direction
|
||||
WS2812FX::Segment& seg = strip.getSegment(0);
|
||||
Segment& seg = strip.getSegment(0);
|
||||
bool doReverse = (userVar0 == 2);
|
||||
seg.setOption(1, doReverse);
|
||||
|
||||
|
@ -89,7 +89,7 @@ void startWipe()
|
||||
resetTimebase(); //make sure wipe starts from beginning
|
||||
|
||||
//set wipe direction
|
||||
WS2812FX::Segment& seg = strip.getSegment(0);
|
||||
Segment& seg = strip.getSegment(0);
|
||||
bool doReverse = (userVar0 == 2);
|
||||
seg.setOption(1, doReverse);
|
||||
|
||||
|
@ -24,54 +24,31 @@
|
||||
//
|
||||
|
||||
//The SCL and SDA pins are defined here.
|
||||
#ifndef FLD_PIN_SCL
|
||||
#define FLD_PIN_SCL i2c_scl
|
||||
#endif
|
||||
#ifndef FLD_PIN_SDA
|
||||
#define FLD_PIN_SDA i2c_sda
|
||||
#endif
|
||||
#ifndef FLD_PIN_CLOCKSPI
|
||||
#define FLD_PIN_CLOCKSPI spi_sclk
|
||||
#endif
|
||||
#ifndef FLD_PIN_DATASPI
|
||||
#define FLD_PIN_DATASPI spi_mosi
|
||||
#endif
|
||||
#ifndef FLD_PIN_CS
|
||||
#define FLD_PIN_CS spi_cs
|
||||
#endif
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#define HW_PIN_SCL 22
|
||||
#define HW_PIN_SDA 21
|
||||
#define HW_PIN_CLOCKSPI 18
|
||||
#define HW_PIN_DATASPI 23
|
||||
#ifndef FLD_PIN_SCL
|
||||
#define FLD_PIN_SCL 22
|
||||
#endif
|
||||
#ifndef FLD_PIN_SDA
|
||||
#define FLD_PIN_SDA 21
|
||||
#endif
|
||||
#ifndef FLD_PIN_CLOCKSPI
|
||||
#define FLD_PIN_CLOCKSPI 18
|
||||
#endif
|
||||
#ifndef FLD_PIN_DATASPI
|
||||
#define FLD_PIN_DATASPI 23
|
||||
#endif
|
||||
#ifndef FLD_PIN_DC
|
||||
#define FLD_PIN_DC 19
|
||||
#endif
|
||||
#ifndef FLD_PIN_CS
|
||||
#define FLD_PIN_CS 5
|
||||
#endif
|
||||
#ifndef FLD_PIN_RESET
|
||||
#define FLD_PIN_RESET 26
|
||||
#endif
|
||||
#else
|
||||
#define HW_PIN_SCL 5
|
||||
#define HW_PIN_SDA 4
|
||||
#define HW_PIN_CLOCKSPI 14
|
||||
#define HW_PIN_DATASPI 13
|
||||
#ifndef FLD_PIN_SCL
|
||||
#define FLD_PIN_SCL 5
|
||||
#endif
|
||||
#ifndef FLD_PIN_SDA
|
||||
#define FLD_PIN_SDA 4
|
||||
#endif
|
||||
#ifndef FLD_PIN_CLOCKSPI
|
||||
#define FLD_PIN_CLOCKSPI 14
|
||||
#endif
|
||||
#ifndef FLD_PIN_DATASPI
|
||||
#define FLD_PIN_DATASPI 13
|
||||
#endif
|
||||
#ifndef FLD_PIN_DC
|
||||
#define FLD_PIN_DC 12
|
||||
#endif
|
||||
#ifndef FLD_PIN_CS
|
||||
#define FLD_PIN_CS 15
|
||||
#endif
|
||||
#ifndef FLD_PIN_RESET
|
||||
#define FLD_PIN_RESET 16
|
||||
@ -192,13 +169,14 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
bool isHW;
|
||||
PinOwner po = PinOwner::UM_FourLineDisplay;
|
||||
if (type == SSD1306_SPI || type == SSD1306_SPI64) {
|
||||
isHW = (ioPin[0]==HW_PIN_CLOCKSPI && ioPin[1]==HW_PIN_DATASPI);
|
||||
isHW = (ioPin[0]==spi_sclk && ioPin[1]==spi_mosi);
|
||||
if (isHW) po = PinOwner::HW_SPI; // allow multiple allocations of HW I2C bus pins
|
||||
PinManagerPinType pins[5] = { { ioPin[0], true }, { ioPin[1], true }, { ioPin[2], true }, { ioPin[3], true }, { ioPin[4], true }};
|
||||
if (!pinManager.allocateMultiplePins(pins, 5, po)) { type=NONE; return; }
|
||||
} else {
|
||||
isHW = (ioPin[0]==HW_PIN_SCL && ioPin[1]==HW_PIN_SDA);
|
||||
isHW = (ioPin[0]==i2c_scl && ioPin[1]==i2c_sda);
|
||||
if (isHW) po = PinOwner::HW_I2C; // allow multiple allocations of HW I2C bus pins
|
||||
PinManagerPinType pins[2] = { { ioPin[0], true }, { ioPin[1], true } };
|
||||
if (ioPin[0]==HW_PIN_SCL && ioPin[1]==HW_PIN_SDA) po = PinOwner::HW_I2C; // allow multiple allocations of HW I2C bus pins
|
||||
if (!pinManager.allocateMultiplePins(pins, 2, po)) { type=NONE; return; }
|
||||
}
|
||||
|
||||
@ -718,8 +696,14 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
if (pinsChanged || type!=newType) {
|
||||
if (type != NONE) delete u8x8;
|
||||
PinOwner po = PinOwner::UM_FourLineDisplay;
|
||||
if (ioPin[0]==HW_PIN_SCL && ioPin[1]==HW_PIN_SDA) po = PinOwner::HW_I2C; // allow multiple allocations of HW I2C bus pins
|
||||
pinManager.deallocateMultiplePins((const uint8_t *)ioPin, (type == SSD1306_SPI || type == SSD1306_SPI64) ? 5 : 2, po);
|
||||
bool isSPI = (type == SSD1306_SPI || type == SSD1306_SPI64);
|
||||
if (isSPI) {
|
||||
if (ioPin[0]==spi_sclk && ioPin[1]==spi_mosi) po = PinOwner::HW_SPI; // allow multiple allocations of HW SPI bus pins
|
||||
pinManager.deallocateMultiplePins((const uint8_t *)ioPin, 5, po);
|
||||
} else {
|
||||
if (ioPin[0]==i2c_scl && ioPin[1]==i2c_sda) po = PinOwner::HW_I2C; // allow multiple allocations of HW I2C bus pins
|
||||
pinManager.deallocateMultiplePins((const uint8_t *)ioPin, 2, po);
|
||||
}
|
||||
for (byte i=0; i<5; i++) ioPin[i] = newPin[i];
|
||||
if (ioPin[0]<0 || ioPin[1]<0) { // data & clock must be > -1
|
||||
type = NONE;
|
||||
|
@ -25,54 +25,32 @@
|
||||
//
|
||||
|
||||
//The SCL and SDA pins are defined here.
|
||||
#ifndef FLD_PIN_SCL
|
||||
#define FLD_PIN_SCL i2c_scl
|
||||
#endif
|
||||
#ifndef FLD_PIN_SDA
|
||||
#define FLD_PIN_SDA i2c_sda
|
||||
#endif
|
||||
#ifndef FLD_PIN_CLOCKSPI
|
||||
#define FLD_PIN_CLOCKSPI spi_sclk
|
||||
#endif
|
||||
#ifndef FLD_PIN_DATASPI
|
||||
#define FLD_PIN_DATASPI spi_mosi
|
||||
#endif
|
||||
#ifndef FLD_PIN_CS
|
||||
#define FLD_PIN_CS spi_cs
|
||||
#endif
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#define HW_PIN_SCL 22
|
||||
#define HW_PIN_SDA 21
|
||||
#define HW_PIN_CLOCKSPI 18
|
||||
#define HW_PIN_DATASPI 23
|
||||
#ifndef FLD_PIN_SCL
|
||||
#define FLD_PIN_SCL 22
|
||||
#endif
|
||||
#ifndef FLD_PIN_SDA
|
||||
#define FLD_PIN_SDA 21
|
||||
#endif
|
||||
#ifndef FLD_PIN_CLOCKSPI
|
||||
#define FLD_PIN_CLOCKSPI 18
|
||||
#endif
|
||||
#ifndef FLD_PIN_DATASPI
|
||||
#define FLD_PIN_DATASPI 23
|
||||
#endif
|
||||
#ifndef FLD_PIN_DC
|
||||
#define FLD_PIN_DC 19
|
||||
#endif
|
||||
#ifndef FLD_PIN_CS
|
||||
#define FLD_PIN_CS 5
|
||||
#endif
|
||||
#ifndef FLD_PIN_RESET
|
||||
#define FLD_PIN_RESET 26
|
||||
#endif
|
||||
#else
|
||||
#define HW_PIN_SCL 5
|
||||
#define HW_PIN_SDA 4
|
||||
#define HW_PIN_CLOCKSPI 14
|
||||
#define HW_PIN_DATASPI 13
|
||||
#ifndef FLD_PIN_SCL
|
||||
#define FLD_PIN_SCL 5
|
||||
#endif
|
||||
#ifndef FLD_PIN_SDA
|
||||
#define FLD_PIN_SDA 4
|
||||
#endif
|
||||
#ifndef FLD_PIN_CLOCKSPI
|
||||
#define FLD_PIN_CLOCKSPI 14
|
||||
#endif
|
||||
#ifndef FLD_PIN_DATASPI
|
||||
#define FLD_PIN_DATASPI 13
|
||||
#endif
|
||||
#ifndef FLD_PIN_DC
|
||||
#define FLD_PIN_DC 12
|
||||
#endif
|
||||
#ifndef FLD_PIN_CS
|
||||
#define FLD_PIN_CS 15
|
||||
#endif
|
||||
#ifndef FLD_PIN_RESET
|
||||
#define FLD_PIN_RESET 16
|
||||
@ -92,13 +70,20 @@
|
||||
#define SCREEN_TIMEOUT_MS 60*1000 // 1 min
|
||||
|
||||
// Minimum time between redrawing screen in ms
|
||||
#define USER_LOOP_REFRESH_RATE_MS 1000
|
||||
#define REFRESH_RATE_MS 1000
|
||||
|
||||
// Extra char (+1) for null
|
||||
#define LINE_BUFFER_SIZE 16+1
|
||||
#define MAX_JSON_CHARS 19+1
|
||||
#define MAX_MODE_LINE_SPACE 13+1
|
||||
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
static TaskHandle_t Display_Task = nullptr;
|
||||
void DisplayTaskCode(void * parameter);
|
||||
#endif
|
||||
|
||||
|
||||
typedef enum {
|
||||
NONE = 0,
|
||||
SSD1306, // U8X8_SSD1306_128X32_UNIVISION_HW_I2C
|
||||
@ -112,10 +97,15 @@ typedef enum {
|
||||
|
||||
|
||||
class FourLineDisplayUsermod : public Usermod {
|
||||
public:
|
||||
FourLineDisplayUsermod() { if (!instance) instance = this; }
|
||||
static FourLineDisplayUsermod* getInstance(void) { return instance; }
|
||||
|
||||
private:
|
||||
|
||||
static FourLineDisplayUsermod *instance;
|
||||
bool initDone = false;
|
||||
volatile bool drawing = false;
|
||||
|
||||
// HW interface & configuration
|
||||
U8X8 *u8x8 = nullptr; // pointer to U8X8 display object
|
||||
@ -132,8 +122,8 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
bool flip = false; // flip display 180°
|
||||
uint8_t contrast = 10; // screen contrast
|
||||
uint8_t lineHeight = 1; // 1 row or 2 rows
|
||||
uint16_t refreshRate = USER_LOOP_REFRESH_RATE_MS; // in ms
|
||||
uint32_t screenTimeout = SCREEN_TIMEOUT_MS; // in ms
|
||||
uint16_t refreshRate = REFRESH_RATE_MS; // in ms
|
||||
uint32_t screenTimeout = SCREEN_TIMEOUT_MS; // in ms
|
||||
bool sleepMode = true; // allow screen sleep?
|
||||
bool clockMode = false; // display clock
|
||||
bool showSeconds = true; // display clock with seconds
|
||||
@ -195,6 +185,123 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
u8x8_cad_EndTransfer(u8x8_struct);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrappers for screen drawing
|
||||
*/
|
||||
void setFlipMode(uint8_t mode) {
|
||||
if (type == NONE || !enabled) return;
|
||||
u8x8->setFlipMode(mode);
|
||||
}
|
||||
void setContrast(uint8_t contrast) {
|
||||
if (type == NONE || !enabled) return;
|
||||
u8x8->setContrast(contrast);
|
||||
}
|
||||
void drawString(uint8_t col, uint8_t row, const char *string, bool ignoreLH=false) {
|
||||
if (type == NONE || !enabled) return;
|
||||
u8x8->setFont(u8x8_font_chroma48medium8_r);
|
||||
if (!ignoreLH && lineHeight==2) u8x8->draw1x2String(col, row, string);
|
||||
else u8x8->drawString(col, row, string);
|
||||
}
|
||||
void draw2x2String(uint8_t col, uint8_t row, const char *string) {
|
||||
if (type == NONE || !enabled) return;
|
||||
u8x8->setFont(u8x8_font_chroma48medium8_r);
|
||||
u8x8->draw2x2String(col, row, string);
|
||||
}
|
||||
void drawGlyph(uint8_t col, uint8_t row, char glyph, const uint8_t *font, bool ignoreLH=false) {
|
||||
if (type == NONE || !enabled) return;
|
||||
u8x8->setFont(font);
|
||||
if (!ignoreLH && lineHeight==2) u8x8->draw1x2Glyph(col, row, glyph);
|
||||
else u8x8->drawGlyph(col, row, glyph);
|
||||
}
|
||||
void draw2x2Glyph(uint8_t col, uint8_t row, char glyph, const uint8_t *font) {
|
||||
if (type == NONE || !enabled) return;
|
||||
u8x8->setFont(font);
|
||||
u8x8->draw2x2Glyph(col, row, glyph);
|
||||
}
|
||||
uint8_t getCols() {
|
||||
if (type==NONE || !enabled) return 0;
|
||||
return u8x8->getCols();
|
||||
}
|
||||
void clear() {
|
||||
if (type == NONE || !enabled) return;
|
||||
u8x8->clear();
|
||||
}
|
||||
void setPowerSave(uint8_t save) {
|
||||
if (type == NONE || !enabled) return;
|
||||
u8x8->setPowerSave(save);
|
||||
}
|
||||
|
||||
void center(String &line, uint8_t width) {
|
||||
int len = line.length();
|
||||
if (len<width) for (byte i=(width-len)/2; i>0; i--) line = ' ' + line;
|
||||
for (byte i=line.length(); i<width; i++) line += ' ';
|
||||
}
|
||||
|
||||
void draw2x2GlyphIcons() {
|
||||
if (lineHeight == 2) {
|
||||
drawGlyph( 1, 0, 1, u8x8_4LineDisplay_WLED_icons_2x2, true); //brightness icon
|
||||
drawGlyph( 5, 0, 2, u8x8_4LineDisplay_WLED_icons_2x2, true); //speed icon
|
||||
drawGlyph( 9, 0, 3, u8x8_4LineDisplay_WLED_icons_2x2, true); //intensity icon
|
||||
drawGlyph(14, 2*lineHeight, 4, u8x8_4LineDisplay_WLED_icons_2x2, true); //palette icon
|
||||
drawGlyph(14, 3*lineHeight, 5, u8x8_4LineDisplay_WLED_icons_2x2, true); //effect icon
|
||||
} else {
|
||||
drawGlyph( 1, 0, 1, u8x8_4LineDisplay_WLED_icons_2x1); //brightness icon
|
||||
drawGlyph( 5, 0, 2, u8x8_4LineDisplay_WLED_icons_2x1); //speed icon
|
||||
drawGlyph( 9, 0, 3, u8x8_4LineDisplay_WLED_icons_2x1); //intensity icon
|
||||
drawGlyph(15, 2, 4, u8x8_4LineDisplay_WLED_icons_1x1); //palette icon
|
||||
drawGlyph(15, 3, 5, u8x8_4LineDisplay_WLED_icons_1x1); //effect icon
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the current date and time in large characters
|
||||
* on the middle rows. Based 24 or 12 hour depending on
|
||||
* the useAMPM configuration.
|
||||
*/
|
||||
void showTime() {
|
||||
if (type == NONE || !enabled || !displayTurnedOff) return;
|
||||
|
||||
unsigned long now = millis();
|
||||
while (drawing && millis()-now < 250) delay(1); // wait if someone else is drawing
|
||||
drawing = true;
|
||||
|
||||
char lineBuffer[LINE_BUFFER_SIZE];
|
||||
static byte lastSecond;
|
||||
byte secondCurrent = second(localTime);
|
||||
byte minuteCurrent = minute(localTime);
|
||||
byte hourCurrent = hour(localTime);
|
||||
|
||||
if (knownMinute != minuteCurrent) { //only redraw clock if it has changed
|
||||
//updateLocalTime();
|
||||
byte AmPmHour = hourCurrent;
|
||||
boolean isitAM = true;
|
||||
if (useAMPM) {
|
||||
if (AmPmHour > 11) { AmPmHour -= 12; isitAM = false; }
|
||||
if (AmPmHour == 0) { AmPmHour = 12; }
|
||||
}
|
||||
if (knownHour != hourCurrent) {
|
||||
// only update date when hour changes
|
||||
sprintf_P(lineBuffer, PSTR("%s %2d "), monthShortStr(month(localTime)), day(localTime));
|
||||
draw2x2String(2, lineHeight==1 ? 0 : lineHeight, lineBuffer); // adjust for 8 line displays, draw month and day
|
||||
}
|
||||
sprintf_P(lineBuffer,PSTR("%2d:%02d"), (useAMPM ? AmPmHour : hourCurrent), minuteCurrent);
|
||||
draw2x2String(2, lineHeight*2, lineBuffer); //draw hour, min. blink ":" depending on odd/even seconds
|
||||
if (useAMPM) drawString(12, lineHeight*2, (isitAM ? "AM" : "PM"), true); //draw am/pm if using 12 time
|
||||
|
||||
drawStatusIcons(); //icons power, wifi, timer, etc
|
||||
|
||||
knownMinute = minuteCurrent;
|
||||
knownHour = hourCurrent;
|
||||
}
|
||||
if (showSeconds && secondCurrent != lastSecond) {
|
||||
lastSecond = secondCurrent;
|
||||
draw2x2String(6, lineHeight*2, secondCurrent%2 ? " " : ":");
|
||||
sprintf_P(lineBuffer, PSTR("%02d"), secondCurrent);
|
||||
drawString(12, lineHeight*2+1, lineBuffer, true); // even with double sized rows print seconds in 1 line
|
||||
}
|
||||
drawing = false;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// gets called once at boot. Do all initialization that doesn't depend on
|
||||
@ -205,13 +312,32 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
bool isHW, isSPI = (type == SSD1306_SPI || type == SSD1306_SPI64);
|
||||
PinOwner po = PinOwner::UM_FourLineDisplay;
|
||||
if (isSPI) {
|
||||
isHW = (ioPin[0]==HW_PIN_CLOCKSPI && ioPin[1]==HW_PIN_DATASPI);
|
||||
PinManagerPinType pins[5] = { { ioPin[0], true }, { ioPin[1], true }, { ioPin[2], true }, { ioPin[3], true }, { ioPin[4], true }};
|
||||
if (!pinManager.allocateMultiplePins(pins, 5, po)) { type=NONE; return; }
|
||||
} else {
|
||||
isHW = (ioPin[0]==HW_PIN_SCL && ioPin[1]==HW_PIN_SDA);
|
||||
uint8_t hw_sclk = spi_sclk<0 ? HW_PIN_CLOCKSPI : spi_sclk;
|
||||
uint8_t hw_mosi = spi_mosi<0 ? HW_PIN_DATASPI : spi_mosi;
|
||||
if (ioPin[0] < 0 || ioPin[1] < 0) {
|
||||
ioPin[0] = hw_sclk;
|
||||
ioPin[1] = hw_mosi;
|
||||
}
|
||||
isHW = (ioPin[0]==hw_sclk && ioPin[1]==hw_mosi);
|
||||
PinManagerPinType cspins[3] = { { ioPin[2], true }, { ioPin[3], true }, { ioPin[4], true } };
|
||||
if (!pinManager.allocateMultiplePins(cspins, 3, PinOwner::UM_FourLineDisplay)) { type=NONE; return; }
|
||||
if (isHW) po = PinOwner::HW_SPI; // allow multiple allocations of HW I2C bus pins
|
||||
PinManagerPinType pins[2] = { { ioPin[0], true }, { ioPin[1], true } };
|
||||
if (ioPin[0]==HW_PIN_SCL && ioPin[1]==HW_PIN_SDA) po = PinOwner::HW_I2C; // allow multiple allocations of HW I2C bus pins
|
||||
if (!pinManager.allocateMultiplePins(pins, 2, po)) {
|
||||
pinManager.deallocateMultiplePins(cspins, 3, PinOwner::UM_FourLineDisplay);
|
||||
type = NONE;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
uint8_t hw_scl = i2c_scl<0 ? HW_PIN_SCL : i2c_scl;
|
||||
uint8_t hw_sda = i2c_sda<0 ? HW_PIN_SDA : i2c_sda;
|
||||
if (ioPin[0] < 0 || ioPin[1] < 0) {
|
||||
ioPin[0] = hw_scl;
|
||||
ioPin[1] = hw_sda;
|
||||
}
|
||||
isHW = (ioPin[0]==hw_scl && ioPin[1]==hw_sda);
|
||||
if (isHW) po = PinOwner::HW_I2C; // allow multiple allocations of HW I2C bus pins
|
||||
PinManagerPinType pins[2] = { {ioPin[0], true }, { ioPin[1], true } };
|
||||
if (!pinManager.allocateMultiplePins(pins, 2, po)) { type=NONE; return; }
|
||||
}
|
||||
|
||||
@ -304,6 +430,7 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
setPowerSave(0);
|
||||
//drawString(0, 0, "Loading...");
|
||||
overlayLogo(3500);
|
||||
onUpdateBegin(false); // create Display task
|
||||
initDone = true;
|
||||
}
|
||||
|
||||
@ -319,63 +446,13 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
* Da loop.
|
||||
*/
|
||||
void loop() {
|
||||
#ifndef ARDUINO_ARCH_ESP32
|
||||
if (!enabled || strip.isUpdating()) return;
|
||||
unsigned long now = millis();
|
||||
if (now < nextUpdate) return;
|
||||
nextUpdate = now + ((displayTurnedOff && clockMode && showSeconds) ? 1000 : refreshRate);
|
||||
redraw(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrappers for screen drawing
|
||||
*/
|
||||
void setFlipMode(uint8_t mode) {
|
||||
if (type == NONE || !enabled) return;
|
||||
u8x8->setFlipMode(mode);
|
||||
}
|
||||
void setContrast(uint8_t contrast) {
|
||||
if (type == NONE || !enabled) return;
|
||||
u8x8->setContrast(contrast);
|
||||
}
|
||||
void drawString(uint8_t col, uint8_t row, const char *string, bool ignoreLH=false) {
|
||||
if (type == NONE || !enabled) return;
|
||||
u8x8->setFont(u8x8_font_chroma48medium8_r);
|
||||
if (!ignoreLH && lineHeight==2) u8x8->draw1x2String(col, row, string);
|
||||
else u8x8->drawString(col, row, string);
|
||||
}
|
||||
void draw2x2String(uint8_t col, uint8_t row, const char *string) {
|
||||
if (type == NONE || !enabled) return;
|
||||
u8x8->setFont(u8x8_font_chroma48medium8_r);
|
||||
u8x8->draw2x2String(col, row, string);
|
||||
}
|
||||
void drawGlyph(uint8_t col, uint8_t row, char glyph, const uint8_t *font, bool ignoreLH=false) {
|
||||
if (type == NONE || !enabled) return;
|
||||
u8x8->setFont(font);
|
||||
if (!ignoreLH && lineHeight==2) u8x8->draw1x2Glyph(col, row, glyph);
|
||||
else u8x8->drawGlyph(col, row, glyph);
|
||||
}
|
||||
void draw2x2Glyph(uint8_t col, uint8_t row, char glyph, const uint8_t *font) {
|
||||
if (type == NONE || !enabled) return;
|
||||
u8x8->setFont(font);
|
||||
u8x8->draw2x2Glyph(col, row, glyph);
|
||||
}
|
||||
uint8_t getCols() {
|
||||
if (type==NONE || !enabled) return 0;
|
||||
return u8x8->getCols();
|
||||
}
|
||||
void clear() {
|
||||
if (type == NONE || !enabled) return;
|
||||
u8x8->clear();
|
||||
}
|
||||
void setPowerSave(uint8_t save) {
|
||||
if (type == NONE || !enabled) return;
|
||||
u8x8->setPowerSave(save);
|
||||
}
|
||||
|
||||
void center(String &line, uint8_t width) {
|
||||
int len = line.length();
|
||||
if (len<width) for (byte i=(width-len)/2; i>0; i--) line = ' ' + line;
|
||||
for (byte i=line.length(); i<width; i++) line += ' ';
|
||||
#endif
|
||||
}
|
||||
|
||||
//function to update lastredraw
|
||||
@ -404,6 +481,8 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
}
|
||||
}
|
||||
|
||||
while (drawing && millis()-now < 250) delay(1); // wait if someone else is drawing
|
||||
|
||||
if (apActive && WLED_WIFI_CONFIGURED && now<15000) {
|
||||
knownSsid = apSSID;
|
||||
networkOverlay(PSTR("NETWORK INFO"),30000);
|
||||
@ -529,22 +608,6 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
}
|
||||
}
|
||||
|
||||
void draw2x2GlyphIcons() {
|
||||
if (lineHeight == 2) {
|
||||
drawGlyph( 1, 0, 1, u8x8_4LineDisplay_WLED_icons_2x2, true); //brightness icon
|
||||
drawGlyph( 5, 0, 2, u8x8_4LineDisplay_WLED_icons_2x2, true); //speed icon
|
||||
drawGlyph( 9, 0, 3, u8x8_4LineDisplay_WLED_icons_2x2, true); //intensity icon
|
||||
drawGlyph(14, 2*lineHeight, 4, u8x8_4LineDisplay_WLED_icons_2x2, true); //palette icon
|
||||
drawGlyph(14, 3*lineHeight, 5, u8x8_4LineDisplay_WLED_icons_2x2, true); //effect icon
|
||||
} else {
|
||||
drawGlyph( 1, 0, 1, u8x8_4LineDisplay_WLED_icons_2x1); //brightness icon
|
||||
drawGlyph( 5, 0, 2, u8x8_4LineDisplay_WLED_icons_2x1); //speed icon
|
||||
drawGlyph( 9, 0, 3, u8x8_4LineDisplay_WLED_icons_2x1); //intensity icon
|
||||
drawGlyph(15, 2, 4, u8x8_4LineDisplay_WLED_icons_1x1); //palette icon
|
||||
drawGlyph(15, 3, 5, u8x8_4LineDisplay_WLED_icons_1x1); //effect icon
|
||||
}
|
||||
}
|
||||
|
||||
void drawStatusIcons() {
|
||||
uint8_t col = 15;
|
||||
uint8_t row = 0;
|
||||
@ -570,8 +633,8 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
if (markColNum != 255 && markLineNum !=255) drawGlyph(markColNum, markLineNum*lineHeight, 21, u8x8_4LineDisplay_WLED_icons_1x1);
|
||||
}
|
||||
|
||||
//Display the current effect or palette (desiredEntry)
|
||||
// on the appropriate line (row).
|
||||
//Display the current effect or palette (desiredEntry)
|
||||
// on the appropriate line (row).
|
||||
void showCurrentEffectOrPalette(int inputEffPal, const char *qstring, uint8_t row) {
|
||||
char lineBuffer[MAX_JSON_CHARS];
|
||||
if (overlayUntil == 0) {
|
||||
@ -581,6 +644,10 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
// remove "* " from dynamic palettes
|
||||
for (byte i=2; i<=printedChars; i++) lineBuffer[i-2] = lineBuffer[i]; //include '\0'
|
||||
printedChars -= 2;
|
||||
} else if ((lineBuffer[0]==' ' && lineBuffer[1]>127)) {
|
||||
// remove note symbol from effect names
|
||||
for (byte i=5; i<=printedChars; i++) lineBuffer[i-5] = lineBuffer[i]; //include '\0'
|
||||
printedChars -= 5;
|
||||
}
|
||||
if (lineHeight == 2) { // use this code for 8 line display
|
||||
char smallBuffer1[MAX_MODE_LINE_SPACE];
|
||||
@ -635,10 +702,14 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
bool wakeDisplay() {
|
||||
if (type == NONE || !enabled) return false;
|
||||
if (displayTurnedOff) {
|
||||
unsigned long now = millis();
|
||||
while (drawing && millis()-now < 250) delay(1); // wait if someone else is drawing
|
||||
drawing = true;
|
||||
clear();
|
||||
// Turn the display back on
|
||||
sleepOrClock(false);
|
||||
//lastRedraw = millis();
|
||||
drawing = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -650,6 +721,9 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
* Used in Rotary Encoder usermod.
|
||||
*/
|
||||
void overlay(const char* line1, long showHowLong, byte glyphType) {
|
||||
unsigned long now = millis();
|
||||
while (drawing && millis()-now < 250) delay(1); // wait if someone else is drawing
|
||||
drawing = true;
|
||||
// Turn the display back on
|
||||
if (!wakeDisplay()) clear();
|
||||
// Print the overlay
|
||||
@ -663,6 +737,7 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
drawString(0, (glyphType<255?3:0)*lineHeight, buf.c_str());
|
||||
}
|
||||
overlayUntil = millis() + showHowLong;
|
||||
drawing = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -670,6 +745,9 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
* Clears the screen and prints.
|
||||
*/
|
||||
void overlayLogo(long showHowLong) {
|
||||
unsigned long now = millis();
|
||||
while (drawing && millis()-now < 250) delay(1); // wait if someone else is drawing
|
||||
drawing = true;
|
||||
// Turn the display back on
|
||||
if (!wakeDisplay()) clear();
|
||||
// Print the overlay
|
||||
@ -719,6 +797,7 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
}
|
||||
}
|
||||
overlayUntil = millis() + showHowLong;
|
||||
drawing = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -727,6 +806,9 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
* Used in Auto Save usermod
|
||||
*/
|
||||
void overlay(const char* line1, const char* line2, long showHowLong) {
|
||||
unsigned long now = millis();
|
||||
while (drawing && millis()-now < 250) delay(1); // wait if someone else is drawing
|
||||
drawing = true;
|
||||
// Turn the display back on
|
||||
if (!wakeDisplay()) clear();
|
||||
// Print the overlay
|
||||
@ -741,9 +823,14 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
drawString(0, 2*lineHeight, buf.c_str());
|
||||
}
|
||||
overlayUntil = millis() + showHowLong;
|
||||
drawing = false;
|
||||
}
|
||||
|
||||
void networkOverlay(const char* line1, long showHowLong) {
|
||||
unsigned long now = millis();
|
||||
while (drawing && millis()-now < 250) delay(1); // wait if someone else is drawing
|
||||
drawing = true;
|
||||
|
||||
String line;
|
||||
// Turn the display back on
|
||||
if (!wakeDisplay()) clear();
|
||||
@ -774,6 +861,7 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
center(line, getCols());
|
||||
drawString(0, lineHeight*3, line.c_str());
|
||||
overlayUntil = millis() + showHowLong;
|
||||
drawing = false;
|
||||
}
|
||||
|
||||
|
||||
@ -794,52 +882,6 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the current date and time in large characters
|
||||
* on the middle rows. Based 24 or 12 hour depending on
|
||||
* the useAMPM configuration.
|
||||
*/
|
||||
void showTime() {
|
||||
if (type == NONE || !enabled || !displayTurnedOff) return;
|
||||
|
||||
char lineBuffer[LINE_BUFFER_SIZE];
|
||||
static byte lastSecond;
|
||||
byte secondCurrent = second(localTime);
|
||||
byte minuteCurrent = minute(localTime);
|
||||
byte hourCurrent = hour(localTime);
|
||||
|
||||
if (knownMinute != minuteCurrent) { //only redraw clock if it has changed
|
||||
//updateLocalTime();
|
||||
byte AmPmHour = hourCurrent;
|
||||
boolean isitAM = true;
|
||||
if (useAMPM) {
|
||||
if (AmPmHour > 11) { AmPmHour -= 12; isitAM = false; }
|
||||
if (AmPmHour == 0) { AmPmHour = 12; }
|
||||
}
|
||||
if (knownHour != hourCurrent) {
|
||||
// only update date when hour changes
|
||||
sprintf_P(lineBuffer, PSTR("%s %2d "), monthShortStr(month(localTime)), day(localTime));
|
||||
draw2x2String(2, lineHeight==1 ? 0 : lineHeight, lineBuffer); // adjust for 8 line displays, draw month and day
|
||||
}
|
||||
sprintf_P(lineBuffer,PSTR("%2d:%02d"), (useAMPM ? AmPmHour : hourCurrent), minuteCurrent);
|
||||
draw2x2String(2, lineHeight*2, lineBuffer); //draw hour, min. blink ":" depending on odd/even seconds
|
||||
if (useAMPM) drawString(12, lineHeight*2, (isitAM ? "AM" : "PM"), true); //draw am/pm if using 12 time
|
||||
|
||||
drawStatusIcons(); //icons power, wifi, timer, etc
|
||||
|
||||
knownMinute = minuteCurrent;
|
||||
knownHour = hourCurrent;
|
||||
} else {
|
||||
if (secondCurrent == lastSecond) return;
|
||||
}
|
||||
if (showSeconds) {
|
||||
lastSecond = secondCurrent;
|
||||
draw2x2String(6, lineHeight*2, secondCurrent%2 ? " " : ":");
|
||||
sprintf_P(lineBuffer, PSTR("%02d"), secondCurrent);
|
||||
drawString(12, lineHeight*2+1, lineBuffer, true); // even with double sized rows print seconds in 1 line
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* handleButton() can be used to override default button behaviour. Returning true
|
||||
* will prevent button working in a default way.
|
||||
@ -913,7 +955,44 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
|
||||
|
||||
#if CONFIG_FREERTOS_UNICORE
|
||||
#define ARDUINO_RUNNING_CORE 0
|
||||
#else
|
||||
#define ARDUINO_RUNNING_CORE 1
|
||||
#endif
|
||||
void onUpdateBegin(bool init) {
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
if (init && Display_Task) {
|
||||
vTaskSuspend(Display_Task); // update is about to begin, disable task to prevent crash
|
||||
} else {
|
||||
// update has failed or create task requested
|
||||
if (Display_Task)
|
||||
vTaskResume(Display_Task);
|
||||
else
|
||||
xTaskCreatePinnedToCore(
|
||||
[](void * par) { // Function to implement the task
|
||||
// see https://www.freertos.org/vtaskdelayuntil.html
|
||||
const TickType_t xFrequency = REFRESH_RATE_MS * portTICK_PERIOD_MS / 2;
|
||||
TickType_t xLastWakeTime = xTaskGetTickCount();
|
||||
for(;;) {
|
||||
delay(1); // DO NOT DELETE THIS LINE! It is needed to give the IDLE(0) task enough time and to keep the watchdog happy.
|
||||
// taskYIELD(), yield(), vTaskDelay() and esp_task_wdt_feed() didn't seem to work.
|
||||
vTaskDelayUntil(&xLastWakeTime, xFrequency); // release CPU, by doing nothing for REFRESH_RATE_MS millis
|
||||
FourLineDisplayUsermod::getInstance()->redraw(false);
|
||||
}
|
||||
},
|
||||
"4LD", // Name of the task
|
||||
3072, // Stack size in words
|
||||
NULL, // Task input parameter
|
||||
1, // Priority of the task (not idle)
|
||||
&Display_Task, // Task handle
|
||||
ARDUINO_RUNNING_CORE
|
||||
);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API.
|
||||
* Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI.
|
||||
@ -951,8 +1030,8 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
oappend(SET_F("addOption(dd,'SSD1305 128x64',5);"));
|
||||
oappend(SET_F("addOption(dd,'SSD1306 SPI',6);"));
|
||||
oappend(SET_F("addOption(dd,'SSD1306 SPI 128x64',7);"));
|
||||
oappend(SET_F("addInfo('4LineDisplay:pin[]',0,'I2C/SPI CLK');"));
|
||||
oappend(SET_F("addInfo('4LineDisplay:pin[]',1,'I2C/SPI DTA');"));
|
||||
oappend(SET_F("addInfo('4LineDisplay:pin[]',0,'I2C/SPI CLK (-1 use global)');"));
|
||||
oappend(SET_F("addInfo('4LineDisplay:pin[]',1,'I2C/SPI DTA (-1 use global)');"));
|
||||
oappend(SET_F("addInfo('4LineDisplay:pin[]',2,'SPI CS');"));
|
||||
oappend(SET_F("addInfo('4LineDisplay:pin[]',3,'SPI DC');"));
|
||||
oappend(SET_F("addInfo('4LineDisplay:pin[]',4,'SPI RST');"));
|
||||
@ -981,7 +1060,9 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
top[FPSTR(_flip)] = (bool) flip;
|
||||
top[FPSTR(_contrast)] = contrast;
|
||||
top[FPSTR(_contrastFix)] = (bool) contrastFix;
|
||||
#ifndef ARDUINO_ARCH_ESP32
|
||||
top[FPSTR(_refreshRate)] = refreshRate;
|
||||
#endif
|
||||
top[FPSTR(_screenTimeOut)] = screenTimeout/1000;
|
||||
top[FPSTR(_sleepMode)] = (bool) sleepMode;
|
||||
top[FPSTR(_clockMode)] = (bool) clockMode;
|
||||
@ -1001,7 +1082,7 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
bool readFromConfig(JsonObject& root) {
|
||||
bool needsRedraw = false;
|
||||
DisplayType newType = type;
|
||||
int8_t newPin[5]; for (byte i=0; i<5; i++) newPin[i] = ioPin[i];
|
||||
int8_t oldPin[5]; for (byte i=0; i<5; i++) oldPin[i] = ioPin[i];
|
||||
|
||||
JsonObject top = root[FPSTR(_name)];
|
||||
if (top.isNull()) {
|
||||
@ -1012,11 +1093,13 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
|
||||
enabled = top[FPSTR(_enabled)] | enabled;
|
||||
newType = top["type"] | newType;
|
||||
for (byte i=0; i<5; i++) newPin[i] = top["pin"][i] | ioPin[i];
|
||||
for (byte i=0; i<5; i++) ioPin[i] = top["pin"][i] | ioPin[i];
|
||||
flip = top[FPSTR(_flip)] | flip;
|
||||
contrast = top[FPSTR(_contrast)] | contrast;
|
||||
#ifndef ARDUINO_ARCH_ESP32
|
||||
refreshRate = top[FPSTR(_refreshRate)] | refreshRate;
|
||||
refreshRate = min(5000, max(250, (int)refreshRate));
|
||||
#endif
|
||||
screenTimeout = (top[FPSTR(_screenTimeOut)] | screenTimeout/1000) * 1000;
|
||||
sleepMode = top[FPSTR(_sleepMode)] | sleepMode;
|
||||
clockMode = top[FPSTR(_clockMode)] | clockMode;
|
||||
@ -1030,24 +1113,31 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
DEBUG_PRINT(FPSTR(_name));
|
||||
if (!initDone) {
|
||||
// first run: reading from cfg.json
|
||||
for (byte i=0; i<5; i++) ioPin[i] = newPin[i];
|
||||
type = newType;
|
||||
DEBUG_PRINTLN(F(" config loaded."));
|
||||
} else {
|
||||
DEBUG_PRINTLN(F(" config (re)loaded."));
|
||||
// changing parameters from settings page
|
||||
bool pinsChanged = false;
|
||||
for (byte i=0; i<5; i++) if (ioPin[i] != newPin[i]) { pinsChanged = true; break; }
|
||||
for (byte i=0; i<5; i++) if (ioPin[i] != oldPin[i]) { pinsChanged = true; break; }
|
||||
if (pinsChanged || type!=newType) {
|
||||
if (type != NONE) delete u8x8;
|
||||
PinOwner po = PinOwner::UM_FourLineDisplay;
|
||||
if (ioPin[0]==HW_PIN_SCL && ioPin[1]==HW_PIN_SDA) po = PinOwner::HW_I2C; // allow multiple allocations of HW I2C bus pins
|
||||
pinManager.deallocateMultiplePins((const uint8_t *)ioPin, (type == SSD1306_SPI || type == SSD1306_SPI64) ? 5 : 2, po);
|
||||
for (byte i=0; i<5; i++) ioPin[i] = newPin[i];
|
||||
if (ioPin[0]<0 || ioPin[1]<0) { // data & clock must be > -1
|
||||
type = NONE;
|
||||
return true;
|
||||
} else type = newType;
|
||||
bool isSPI = (type == SSD1306_SPI || type == SSD1306_SPI64);
|
||||
if (isSPI) {
|
||||
pinManager.deallocateMultiplePins((const uint8_t *)(&oldPin[2]), 3, po);
|
||||
uint8_t hw_sclk = spi_sclk<0 ? HW_PIN_CLOCKSPI : spi_sclk;
|
||||
uint8_t hw_mosi = spi_mosi<0 ? HW_PIN_DATASPI : spi_mosi;
|
||||
bool isHW = (oldPin[0]==hw_sclk && oldPin[1]==hw_mosi);
|
||||
if (isHW) po = PinOwner::HW_SPI;
|
||||
} else {
|
||||
uint8_t hw_scl = i2c_scl<0 ? HW_PIN_SCL : i2c_scl;
|
||||
uint8_t hw_sda = i2c_sda<0 ? HW_PIN_SDA : i2c_sda;
|
||||
bool isHW = (oldPin[0]==hw_scl && oldPin[1]==hw_sda);
|
||||
if (isHW) po = PinOwner::HW_I2C;
|
||||
}
|
||||
pinManager.deallocateMultiplePins((const uint8_t *)oldPin, 2, po);
|
||||
type = newType;
|
||||
setup();
|
||||
needsRedraw |= true;
|
||||
} else {
|
||||
@ -1085,3 +1175,5 @@ const char FourLineDisplayUsermod::_clockMode[] PROGMEM = "clockMode";
|
||||
const char FourLineDisplayUsermod::_showSeconds[] PROGMEM = "showSeconds";
|
||||
const char FourLineDisplayUsermod::_busClkFrequency[] PROGMEM = "i2c-freq-kHz";
|
||||
const char FourLineDisplayUsermod::_contrastFix[] PROGMEM = "contrastFix";
|
||||
|
||||
FourLineDisplayUsermod *FourLineDisplayUsermod::instance = nullptr;
|
||||
|
@ -47,7 +47,7 @@
|
||||
|
||||
// The last UI state, remove color and saturation option if diplay not active(too many options)
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
#define LAST_UI_STATE 8
|
||||
#define LAST_UI_STATE 11
|
||||
#else
|
||||
#define LAST_UI_STATE 4
|
||||
#endif
|
||||
@ -56,7 +56,7 @@
|
||||
#define MODE_SORT_SKIP_COUNT 1
|
||||
|
||||
// Which list is being sorted
|
||||
static char **listBeingSorted;
|
||||
static const char **listBeingSorted;
|
||||
|
||||
/**
|
||||
* Modes and palettes are stored as strings that
|
||||
@ -65,8 +65,8 @@ static char **listBeingSorted;
|
||||
* JSON_mode_names or JSON_palette_names.
|
||||
*/
|
||||
static int re_qstringCmp(const void *ap, const void *bp) {
|
||||
char *a = listBeingSorted[*((byte *)ap)];
|
||||
char *b = listBeingSorted[*((byte *)bp)];
|
||||
const char *a = listBeingSorted[*((byte *)ap)];
|
||||
const char *b = listBeingSorted[*((byte *)bp)];
|
||||
int i = 0;
|
||||
do {
|
||||
char aVal = pgm_read_byte_near(a + i);
|
||||
@ -139,13 +139,13 @@ private:
|
||||
#endif
|
||||
|
||||
// Pointers the start of the mode names within JSON_mode_names
|
||||
char **modes_qstrings = nullptr;
|
||||
const char **modes_qstrings = nullptr;
|
||||
|
||||
// Array of mode indexes in alphabetical order.
|
||||
byte *modes_alpha_indexes = nullptr;
|
||||
|
||||
// Pointers the start of the palette names within JSON_palette_names
|
||||
char **palettes_qstrings = nullptr;
|
||||
const char **palettes_qstrings = nullptr;
|
||||
|
||||
// Array of palette indexes in alphabetical order.
|
||||
byte *palettes_alpha_indexes = nullptr;
|
||||
@ -185,7 +185,8 @@ private:
|
||||
* modes_alpha_indexes and palettes_alpha_indexes.
|
||||
*/
|
||||
void sortModesAndPalettes() {
|
||||
modes_qstrings = re_findModeStrings(JSON_mode_names, strip.getModeCount());
|
||||
//modes_qstrings = re_findModeStrings(JSON_mode_names, strip.getModeCount());
|
||||
modes_qstrings = strip.getModeDataSrc();
|
||||
modes_alpha_indexes = re_initIndexArray(strip.getModeCount());
|
||||
re_sortModes(modes_qstrings, modes_alpha_indexes, strip.getModeCount(), MODE_SORT_SKIP_COUNT);
|
||||
|
||||
@ -211,8 +212,8 @@ private:
|
||||
* Return an array of mode or palette names from the JSON string.
|
||||
* They don't end in '\0', they end in '"'.
|
||||
*/
|
||||
char **re_findModeStrings(const char json[], int numModes) {
|
||||
char **modeStrings = (char **)malloc(sizeof(char *) * numModes);
|
||||
const char **re_findModeStrings(const char json[], int numModes) {
|
||||
const char **modeStrings = (const char **)malloc(sizeof(const char *) * numModes);
|
||||
uint8_t modeIndex = 0;
|
||||
bool insideQuotes = false;
|
||||
// advance past the mark for markLineNum that may exist.
|
||||
@ -249,7 +250,8 @@ private:
|
||||
/**
|
||||
* Sort either the modes or the palettes using quicksort.
|
||||
*/
|
||||
void re_sortModes(char **modeNames, byte *indexes, int count, int numSkip) {
|
||||
void re_sortModes(const char **modeNames, byte *indexes, int count, int numSkip) {
|
||||
if (!modeNames) return;
|
||||
listBeingSorted = modeNames;
|
||||
qsort(indexes + numSkip, count - numSkip, sizeof(byte), re_qstringCmp);
|
||||
listBeingSorted = nullptr;
|
||||
@ -285,7 +287,7 @@ public:
|
||||
|
||||
if (!initDone) sortModesAndPalettes();
|
||||
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
// This Usermod uses FourLineDisplayUsermod for the best experience.
|
||||
// But it's optional. But you want it.
|
||||
display = (FourLineDisplayUsermod*) usermods.lookup(USERMOD_ID_FOUR_LINE_DISP);
|
||||
@ -365,19 +367,43 @@ public:
|
||||
if (buttonWaitTime && currentTime-buttonWaitTime>350 && !buttonPressedBefore) { //same speed as in button.cpp
|
||||
buttonWaitTime = 0;
|
||||
char newState = select_state + 1;
|
||||
bool changedState = true;
|
||||
if (newState > LAST_UI_STATE || (newState == 8 && presetHigh==0 && presetLow == 0)) newState = 0;
|
||||
bool changedState = false;
|
||||
char lineBuffer[64];
|
||||
do {
|
||||
// finde new state
|
||||
switch (newState) {
|
||||
case 0: strcpy_P(lineBuffer, PSTR("Brightness")); changedState = true; break;
|
||||
case 1: if (!extractModeSlider(effectCurrent, 0, lineBuffer, 63)) newState++; else changedState = true; break; // speed
|
||||
case 2: if (!extractModeSlider(effectCurrent, 1, lineBuffer, 63)) newState++; else changedState = true; break; // intensity
|
||||
case 3: strcpy_P(lineBuffer, PSTR("Color Palette")); changedState = true; break;
|
||||
case 4: strcpy_P(lineBuffer, PSTR("Effect")); changedState = true; break;
|
||||
case 5: strcpy_P(lineBuffer, PSTR("Main Color")); changedState = true; break;
|
||||
case 6: strcpy_P(lineBuffer, PSTR("Saturation")); changedState = true; break;
|
||||
case 7:
|
||||
if (!(strip.getSegment(applyToAll ? strip.getFirstSelectedSegId() : strip.getMainSegmentId()).getLightCapabilities() & 0x04)) newState++;
|
||||
else { strcpy_P(lineBuffer, PSTR("CCT")); changedState = true; }
|
||||
break;
|
||||
case 8: if (presetHigh==0 || presetLow == 0) newState++; else { strcpy_P(lineBuffer, PSTR("Preset")); changedState = true; } break;
|
||||
case 9:
|
||||
case 10:
|
||||
case 11: if (!extractModeSlider(effectCurrent, newState-7, lineBuffer, 63)) newState++; else changedState = true; break; // custom
|
||||
}
|
||||
if (newState > LAST_UI_STATE) newState = 0;
|
||||
} while (!changedState);
|
||||
if (display != nullptr) {
|
||||
switch (newState) {
|
||||
case 0: changedState = changeState(PSTR("Brightness"), 1, 0, 1); break; //1 = sun
|
||||
case 1: changedState = changeState(PSTR("Speed"), 1, 4, 2); break; //2 = skip forward
|
||||
case 2: changedState = changeState(PSTR("Intensity"), 1, 8, 3); break; //3 = fire
|
||||
case 3: changedState = changeState(PSTR("Color Palette"), 2, 0, 4); break; //4 = custom palette
|
||||
case 4: changedState = changeState(PSTR("Effect"), 3, 0, 5); break; //5 = puzzle piece
|
||||
case 5: changedState = changeState(PSTR("Main Color"), 255, 255, 7); break; //7 = brush
|
||||
case 6: changedState = changeState(PSTR("Saturation"), 255, 255, 8); break; //8 = contrast
|
||||
case 7: changedState = changeState(PSTR("CCT"), 255, 255, 10); break; //10 = star
|
||||
case 8: changedState = changeState(PSTR("Preset"), 255, 255, 11); break; //11 = heart
|
||||
case 0: changedState = changeState(lineBuffer, 1, 0, 1); break; //1 = sun
|
||||
case 1: changedState = changeState(lineBuffer, 1, 4, 2); break; //2 = skip forward
|
||||
case 2: changedState = changeState(lineBuffer, 1, 8, 3); break; //3 = fire
|
||||
case 3: changedState = changeState(lineBuffer, 2, 0, 4); break; //4 = custom palette
|
||||
case 4: changedState = changeState(lineBuffer, 3, 0, 5); break; //5 = puzzle piece
|
||||
case 5: changedState = changeState(lineBuffer, 255, 255, 7); break; //7 = brush
|
||||
case 6: changedState = changeState(lineBuffer, 255, 255, 8); break; //8 = contrast
|
||||
case 7: changedState = changeState(lineBuffer, 255, 255, 10); break; //10 = star
|
||||
case 8: changedState = changeState(lineBuffer, 255, 255, 11); break; //11 = heart
|
||||
case 9: changedState = changeState(lineBuffer, 255, 255, 10); break; //10 = star
|
||||
case 10: changedState = changeState(lineBuffer, 255, 255, 10); break; //10 = star
|
||||
case 11: changedState = changeState(lineBuffer, 255, 255, 10); break; //10 = star
|
||||
}
|
||||
}
|
||||
if (changedState) select_state = newState;
|
||||
@ -390,29 +416,35 @@ public:
|
||||
if (Enc_B == LOW) //changes to LOW so that then encoder registers a change at the very end of a pulse
|
||||
{ // B is high so clockwise
|
||||
switch(select_state) {
|
||||
case 0: changeBrightness(true); break;
|
||||
case 1: changeEffectSpeed(true); break;
|
||||
case 2: changeEffectIntensity(true); break;
|
||||
case 3: changePalette(true); break;
|
||||
case 4: changeEffect(true); break;
|
||||
case 5: changeHue(true); break;
|
||||
case 6: changeSat(true); break;
|
||||
case 7: changeCCT(true); break;
|
||||
case 8: changePreset(true); break;
|
||||
case 0: changeBrightness(true); break;
|
||||
case 1: changeEffectSpeed(true); break;
|
||||
case 2: changeEffectIntensity(true); break;
|
||||
case 3: changePalette(true); break;
|
||||
case 4: changeEffect(true); break;
|
||||
case 5: changeHue(true); break;
|
||||
case 6: changeSat(true); break;
|
||||
case 7: changeCCT(true); break;
|
||||
case 8: changePreset(true); break;
|
||||
case 9: changeCustom(1,true); break;
|
||||
case 10: changeCustom(2,true); break;
|
||||
case 11: changeCustom(3,true); break;
|
||||
}
|
||||
}
|
||||
else if (Enc_B == HIGH)
|
||||
{ // B is low so counter-clockwise
|
||||
switch(select_state) {
|
||||
case 0: changeBrightness(false); break;
|
||||
case 1: changeEffectSpeed(false); break;
|
||||
case 2: changeEffectIntensity(false); break;
|
||||
case 3: changePalette(false); break;
|
||||
case 4: changeEffect(false); break;
|
||||
case 5: changeHue(false); break;
|
||||
case 6: changeSat(false); break;
|
||||
case 7: changeCCT(false); break;
|
||||
case 8: changePreset(false); break;
|
||||
case 0: changeBrightness(false); break;
|
||||
case 1: changeEffectSpeed(false); break;
|
||||
case 2: changeEffectIntensity(false); break;
|
||||
case 3: changePalette(false); break;
|
||||
case 4: changeEffect(false); break;
|
||||
case 5: changeHue(false); break;
|
||||
case 6: changeSat(false); break;
|
||||
case 7: changeCCT(false); break;
|
||||
case 8: changePreset(false); break;
|
||||
case 9: changeCustom(1,false); break;
|
||||
case 10: changeCustom(2,false); break;
|
||||
case 11: changeCustom(3,false); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -496,13 +528,13 @@ public:
|
||||
effectCurrent = modes_alpha_indexes[effectCurrentIndex];
|
||||
stateChanged = true;
|
||||
if (applyToAll) {
|
||||
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
||||
for (byte i=0; i<strip.getSegmentsNum(); i++) {
|
||||
Segment& seg = strip.getSegment(i);
|
||||
if (!seg.isActive()) continue;
|
||||
strip.setMode(i, effectCurrent);
|
||||
}
|
||||
} else {
|
||||
//WS2812FX::Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||
//Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||
strip.setMode(strip.getMainSegmentId(), effectCurrent);
|
||||
}
|
||||
lampUdated();
|
||||
@ -524,13 +556,13 @@ public:
|
||||
effectSpeed = max(min((increase ? effectSpeed+fadeAmount : effectSpeed-fadeAmount), 255), 0);
|
||||
stateChanged = true;
|
||||
if (applyToAll) {
|
||||
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
||||
for (byte i=0; i<strip.getSegmentsNum(); i++) {
|
||||
Segment& seg = strip.getSegment(i);
|
||||
if (!seg.isActive()) continue;
|
||||
seg.speed = effectSpeed;
|
||||
}
|
||||
} else {
|
||||
WS2812FX::Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||
Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||
seg.speed = effectSpeed;
|
||||
}
|
||||
lampUdated();
|
||||
@ -552,13 +584,13 @@ public:
|
||||
effectIntensity = max(min((increase ? effectIntensity+fadeAmount : effectIntensity-fadeAmount), 255), 0);
|
||||
stateChanged = true;
|
||||
if (applyToAll) {
|
||||
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
||||
for (byte i=0; i<strip.getSegmentsNum(); i++) {
|
||||
Segment& seg = strip.getSegment(i);
|
||||
if (!seg.isActive()) continue;
|
||||
seg.intensity = effectIntensity;
|
||||
}
|
||||
} else {
|
||||
WS2812FX::Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||
Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||
seg.intensity = effectIntensity;
|
||||
}
|
||||
lampUdated();
|
||||
@ -568,6 +600,51 @@ public:
|
||||
}
|
||||
|
||||
|
||||
void changeCustom(uint8_t par, bool increase) {
|
||||
uint8_t val = 0;
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
if (display && display->wakeDisplay()) {
|
||||
display->redraw(true);
|
||||
// Throw away wake up input
|
||||
return;
|
||||
}
|
||||
display->updateRedrawTime();
|
||||
#endif
|
||||
stateChanged = true;
|
||||
if (applyToAll) {
|
||||
uint8_t id = strip.getFirstSelectedSegId();
|
||||
Segment& sid = strip.getSegment(id);
|
||||
switch (par) {
|
||||
case 3: val = sid.custom3 = max(min((increase ? sid.custom3+fadeAmount : sid.custom3-fadeAmount), 255), 0); break;
|
||||
case 2: val = sid.custom2 = max(min((increase ? sid.custom2+fadeAmount : sid.custom2-fadeAmount), 255), 0); break;
|
||||
default: val = sid.custom1 = max(min((increase ? sid.custom1+fadeAmount : sid.custom1-fadeAmount), 255), 0); break;
|
||||
}
|
||||
for (byte i=0; i<strip.getSegmentsNum(); i++) {
|
||||
Segment& seg = strip.getSegment(i);
|
||||
if (!seg.isActive() || i == id) continue;
|
||||
switch (par) {
|
||||
case 3: seg.custom3 = sid.custom3; break;
|
||||
case 2: seg.custom2 = sid.custom2; break;
|
||||
default: seg.custom1 = sid.custom1; break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Segment& seg = strip.getMainSegment();
|
||||
switch (par) {
|
||||
case 3: val = seg.custom3 = max(min((increase ? seg.custom3+fadeAmount : seg.custom3-fadeAmount), 255), 0); break;
|
||||
case 2: val = seg.custom2 = max(min((increase ? seg.custom2+fadeAmount : seg.custom2-fadeAmount), 255), 0); break;
|
||||
default: val = seg.custom1 = max(min((increase ? seg.custom1+fadeAmount : seg.custom1-fadeAmount), 255), 0); break;
|
||||
}
|
||||
}
|
||||
lampUdated();
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
char lineBuffer[64];
|
||||
sprintf(lineBuffer, "%d", val);
|
||||
display->overlay(lineBuffer, 500, 10); // use star
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void changePalette(bool increase) {
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
if (display && display->wakeDisplay()) {
|
||||
@ -581,13 +658,13 @@ public:
|
||||
effectPalette = palettes_alpha_indexes[effectPaletteIndex];
|
||||
stateChanged = true;
|
||||
if (applyToAll) {
|
||||
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
||||
for (byte i=0; i<strip.getSegmentsNum(); i++) {
|
||||
Segment& seg = strip.getSegment(i);
|
||||
if (!seg.isActive()) continue;
|
||||
seg.palette = effectPalette;
|
||||
}
|
||||
} else {
|
||||
WS2812FX::Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||
Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||
seg.palette = effectPalette;
|
||||
}
|
||||
lampUdated();
|
||||
@ -610,16 +687,21 @@ public:
|
||||
colorHStoRGB(currentHue1*256, currentSat1, col);
|
||||
stateChanged = true;
|
||||
if (applyToAll) {
|
||||
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
||||
for (byte i=0; i<strip.getSegmentsNum(); i++) {
|
||||
Segment& seg = strip.getSegment(i);
|
||||
if (!seg.isActive()) continue;
|
||||
seg.colors[0] = RGBW32(col[0], col[1], col[2], col[3]);
|
||||
}
|
||||
} else {
|
||||
WS2812FX::Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||
Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||
seg.colors[0] = RGBW32(col[0], col[1], col[2], col[3]);
|
||||
}
|
||||
lampUdated();
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
char lineBuffer[64];
|
||||
sprintf(lineBuffer, "%d", currentHue1);
|
||||
display->overlay(lineBuffer, 500, 7); // use brush
|
||||
#endif
|
||||
}
|
||||
|
||||
void changeSat(bool increase){
|
||||
@ -634,16 +716,21 @@ public:
|
||||
currentSat1 = max(min((increase ? currentSat1+fadeAmount : currentSat1-fadeAmount), 255), 0);
|
||||
colorHStoRGB(currentHue1*256, currentSat1, col);
|
||||
if (applyToAll) {
|
||||
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
||||
for (byte i=0; i<strip.getSegmentsNum(); i++) {
|
||||
Segment& seg = strip.getSegment(i);
|
||||
if (!seg.isActive()) continue;
|
||||
seg.colors[0] = RGBW32(col[0], col[1], col[2], col[3]);
|
||||
}
|
||||
} else {
|
||||
WS2812FX::Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||
Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||
seg.colors[0] = RGBW32(col[0], col[1], col[2], col[3]);
|
||||
}
|
||||
lampUdated();
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
char lineBuffer[64];
|
||||
sprintf(lineBuffer, "%d", currentSat1);
|
||||
display->overlay(lineBuffer, 500, 8); // use contrast
|
||||
#endif
|
||||
}
|
||||
|
||||
void changePreset(bool increase) {
|
||||
@ -656,6 +743,12 @@ public:
|
||||
display->updateRedrawTime();
|
||||
#endif
|
||||
if (presetHigh && presetLow && presetHigh > presetLow) {
|
||||
StaticJsonDocument<64> root;
|
||||
char str[64];
|
||||
sprintf_P(str, PSTR("%d~%d~%s"), presetLow, presetHigh, increase?"":"-");
|
||||
root[F("ps")] = str;
|
||||
deserializeState(root.as<JsonObject>(), CALL_MODE_BUTTON_PRESET);
|
||||
/*
|
||||
String apireq = F("win&PL=~");
|
||||
if (!increase) apireq += '-';
|
||||
apireq += F("&P1=");
|
||||
@ -663,7 +756,12 @@ public:
|
||||
apireq += F("&P2=");
|
||||
apireq += presetHigh;
|
||||
handleSet(nullptr, apireq, false);
|
||||
*/
|
||||
lampUdated();
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
sprintf(str, "%d", currentPreset);
|
||||
display->overlay(str, 500, 11); // use heart
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -678,16 +776,21 @@ public:
|
||||
#endif
|
||||
currentCCT = max(min((increase ? currentCCT+fadeAmount : currentCCT-fadeAmount), 255), 0);
|
||||
// if (applyToAll) {
|
||||
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
||||
for (byte i=0; i<strip.getSegmentsNum(); i++) {
|
||||
Segment& seg = strip.getSegment(i);
|
||||
if (!seg.isActive()) continue;
|
||||
seg.setCCT(currentCCT, i);
|
||||
seg.setCCT(currentCCT);
|
||||
}
|
||||
// } else {
|
||||
// WS2812FX::Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||
// Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||
// seg.setCCT(currentCCT, strip.getMainSegmentId());
|
||||
// }
|
||||
lampUdated();
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
char lineBuffer[64];
|
||||
sprintf(lineBuffer, "%d", currentCCT);
|
||||
display->overlay(lineBuffer, 500, 10); // use star
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -27,14 +27,14 @@ saveMacro(1, "&FX=0&R=255&G=255&B=255", false);
|
||||
//strip.getSegment(1).setOption(SEG_OPTION_SELECTED, true);
|
||||
|
||||
//select first two segments (background color + FX settable)
|
||||
WS2812FX::Segment &seg = strip.getSegment(0);
|
||||
Segment &seg = strip.getSegment(0);
|
||||
seg.colors[0] = ((0 << 24) | ((0 & 0xFF) << 16) | ((0 & 0xFF) << 8) | ((0 & 0xFF)));
|
||||
strip.getSegment(0).setOption(0, false);
|
||||
strip.getSegment(0).setOption(2, false);
|
||||
//other segments are text
|
||||
for (int i = 1; i < 10; i++)
|
||||
{
|
||||
WS2812FX::Segment &seg = strip.getSegment(i);
|
||||
Segment &seg = strip.getSegment(i);
|
||||
seg.colors[0] = ((0 << 24) | ((0 & 0xFF) << 16) | ((190 & 0xFF) << 8) | ((180 & 0xFF)));
|
||||
strip.getSegment(i).setOption(0, true);
|
||||
strip.setBrightness(128);
|
||||
@ -50,7 +50,7 @@ void selectWordSegments(bool state)
|
||||
{
|
||||
for (int i = 1; i < 10; i++)
|
||||
{
|
||||
//WS2812FX::Segment &seg = strip.getSegment(i);
|
||||
//Segment &seg = strip.getSegment(i);
|
||||
strip.getSegment(i).setOption(0, state);
|
||||
// strip.getSegment(1).setOption(SEG_OPTION_SELECTED, true);
|
||||
//seg.mode = 12;
|
||||
|
5093
wled00/FX.cpp
5093
wled00/FX.cpp
File diff suppressed because it is too large
Load Diff
1409
wled00/FX.h
1409
wled00/FX.h
File diff suppressed because it is too large
Load Diff
513
wled00/FX_2Dfcn.cpp
Normal file
513
wled00/FX_2Dfcn.cpp
Normal file
@ -0,0 +1,513 @@
|
||||
/*
|
||||
FX_2Dfcn.cpp contains all 2D utility functions
|
||||
|
||||
LICENSE
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2022 Blaz Kristan (https://blaz.at/home)
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
Parts of the code adapted from WLED Sound Reactive
|
||||
*/
|
||||
#include "wled.h"
|
||||
#include "FX.h"
|
||||
#include "palettes.h"
|
||||
|
||||
// setUpMatrix() - constructs ledmap array from matrix of panels with WxH pixels
|
||||
// this converts physical (possibly irregular) LED arrangement into well defined
|
||||
// array of logical pixels: fist entry corresponds to left-topmost logical pixel
|
||||
// followed by horizontal pixels, when matrixWidth logical pixels are added they
|
||||
// are followed by next row (down) of matrixWidth pixels (and so forth)
|
||||
// note: matrix may be comprised of multiple panels each with different orientation
|
||||
// but ledmap takes care of that. ledmap is constructed upon initialization
|
||||
// so matrix should disable regular ledmap processing
|
||||
void WS2812FX::setUpMatrix() {
|
||||
#ifndef WLED_DISABLE_2D
|
||||
// erase old ledmap, just in case.
|
||||
if (customMappingTable != nullptr) delete[] customMappingTable;
|
||||
customMappingTable = nullptr;
|
||||
customMappingSize = 0;
|
||||
|
||||
if (isMatrix) {
|
||||
matrixWidth = hPanels * panelW;
|
||||
matrixHeight = vPanels * panelH;
|
||||
|
||||
// safety check
|
||||
if (matrixWidth * matrixHeight > MAX_LEDS) {
|
||||
matrixWidth = _length;
|
||||
matrixHeight = 1;
|
||||
isMatrix = false;
|
||||
return;
|
||||
}
|
||||
|
||||
customMappingSize = matrixWidth * matrixHeight;
|
||||
customMappingTable = new uint16_t[customMappingSize];
|
||||
|
||||
if (customMappingTable != nullptr) {
|
||||
uint16_t startL; // index in custom mapping array (logical strip)
|
||||
uint16_t startP; // position of 1st pixel of panel on (virtual) strip
|
||||
uint16_t x, y, offset;
|
||||
uint8_t h = matrix.vertical ? vPanels : hPanels;
|
||||
uint8_t v = matrix.vertical ? hPanels : vPanels;
|
||||
|
||||
for (uint8_t j=0, p=0; j<v; j++) {
|
||||
for (uint8_t i=0; i<h; i++, p++) {
|
||||
y = (matrix.vertical ? matrix.rightStart : matrix.bottomStart) ? v - j - 1 : j;
|
||||
x = (matrix.vertical ? matrix.bottomStart : matrix.rightStart) ? h - i - 1 : i;
|
||||
x = matrix.serpentine && j%2 ? h - x - 1 : x;
|
||||
|
||||
startL = (matrix.vertical ? y : x) * panelW + (matrix.vertical ? x : y) * matrixWidth * panelH; // logical index (top-left corner)
|
||||
startP = p * panelW * panelH; // physical index (top-left corner)
|
||||
|
||||
uint8_t H = panel[h*j + i].vertical ? panelW : panelH;
|
||||
uint8_t W = panel[h*j + i].vertical ? panelH : panelW;
|
||||
for (uint16_t l=0, q=0; l<H; l++) {
|
||||
for (uint16_t k=0; k<W; k++, q++) {
|
||||
y = (panel[h*j + i].vertical ? panel[h*j + i].rightStart : panel[h*j + i].bottomStart) ? H - l - 1 : l;
|
||||
x = (panel[h*j + i].vertical ? panel[h*j + i].bottomStart : panel[h*j + i].rightStart) ? W - k - 1 : k;
|
||||
x = (panel[h*j + i].serpentine && l%2) ? (W - x - 1) : x;
|
||||
offset = (panel[h*j + i].vertical ? y : x) + (panel[h*j + i].vertical ? x : y) * matrixWidth;
|
||||
customMappingTable[startL + offset] = startP + q;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef WLED_DEBUG
|
||||
DEBUG_PRINT(F("Matrix ledmap:"));
|
||||
for (uint16_t i=0; i<customMappingSize; i++) {
|
||||
if (!(i%matrixWidth)) DEBUG_PRINTLN();
|
||||
DEBUG_PRINTF("%4d,", customMappingTable[i]);
|
||||
}
|
||||
DEBUG_PRINTLN();
|
||||
#endif
|
||||
} else {
|
||||
// memory allocation error
|
||||
matrixWidth = _length;
|
||||
matrixHeight = 1;
|
||||
isMatrix = false;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// not a matrix set up
|
||||
matrixWidth = _length;
|
||||
matrixHeight = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// absolute matrix version of setPixelColor()
|
||||
void IRAM_ATTR WS2812FX::setPixelColorXY(int x, int y, uint32_t col)
|
||||
{
|
||||
#ifndef WLED_DISABLE_2D
|
||||
if (!isMatrix) return; // not a matrix set-up
|
||||
uint16_t index = y * matrixWidth + x;
|
||||
#else
|
||||
uint16_t index = x;
|
||||
#endif
|
||||
if (index >= _length) return;
|
||||
if (index < customMappingSize) index = customMappingTable[index];
|
||||
busses.setPixelColor(index, col);
|
||||
}
|
||||
|
||||
// returns RGBW values of pixel
|
||||
uint32_t WS2812FX::getPixelColorXY(uint16_t x, uint16_t y) {
|
||||
#ifndef WLED_DISABLE_2D
|
||||
uint16_t index = (y * matrixWidth + x);
|
||||
#else
|
||||
uint16_t index = x;
|
||||
#endif
|
||||
if (index >= _length) return 0;
|
||||
if (index < customMappingSize) index = customMappingTable[index];
|
||||
return busses.getPixelColor(index);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// Segment:: routines
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef WLED_DISABLE_2D
|
||||
|
||||
// XY(x,y) - gets pixel index within current segment (often used to reference leds[] array element)
|
||||
uint16_t IRAM_ATTR Segment::XY(uint16_t x, uint16_t y) {
|
||||
uint16_t width = virtualWidth(); // segment width in logical pixels
|
||||
uint16_t height = virtualHeight(); // segment height in logical pixels
|
||||
return (x%width) + (y%height) * width;
|
||||
}
|
||||
|
||||
void IRAM_ATTR Segment::setPixelColorXY(int x, int y, uint32_t col)
|
||||
{
|
||||
if (!strip.isMatrix) return; // not a matrix set-up
|
||||
|
||||
if (leds) leds[XY(x,y)] = col;
|
||||
|
||||
uint8_t _bri_t = currentBri(on ? opacity : 0);
|
||||
if (_bri_t < 255) {
|
||||
byte r = scale8(R(col), _bri_t);
|
||||
byte g = scale8(G(col), _bri_t);
|
||||
byte b = scale8(B(col), _bri_t);
|
||||
byte w = scale8(W(col), _bri_t);
|
||||
col = RGBW32(r, g, b, w);
|
||||
}
|
||||
|
||||
if (reverse ) x = virtualWidth() - x - 1;
|
||||
if (reverse_y) y = virtualHeight() - y - 1;
|
||||
if (transpose) { uint16_t t = x; x = y; y = t; } // swap X & Y if segment transposed
|
||||
|
||||
x *= groupLength(); // expand to physical pixels
|
||||
y *= groupLength(); // expand to physical pixels
|
||||
if (x >= width() || y >= height()) return; // if pixel would fall out of segment just exit
|
||||
|
||||
for (int j = 0; j < grouping; j++) { // groupping vertically
|
||||
for (int g = 0; g < grouping; g++) { // groupping horizontally
|
||||
uint16_t xX = (x+g), yY = (y+j);
|
||||
if (xX >= width() || yY >= height()) continue; // we have reached one dimension's end
|
||||
|
||||
strip.setPixelColorXY(start + xX, startY + yY, col);
|
||||
|
||||
if (mirror) { //set the corresponding horizontally mirrored pixel
|
||||
if (transpose) strip.setPixelColorXY(start + xX, startY + height() - yY - 1, col);
|
||||
else strip.setPixelColorXY(start + width() - xX - 1, startY + yY, col);
|
||||
}
|
||||
if (mirror_y) { //set the corresponding vertically mirrored pixel
|
||||
if (transpose) strip.setPixelColorXY(start + width() - xX - 1, startY + yY, col);
|
||||
else strip.setPixelColorXY(start + xX, startY + height() - yY - 1, col);
|
||||
}
|
||||
if (mirror_y && mirror) { //set the corresponding vertically AND horizontally mirrored pixel
|
||||
strip.setPixelColorXY(width() - xX - 1, height() - yY - 1, col);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// anti-aliased version of setPixelColorXY()
|
||||
void Segment::setPixelColorXY(float x, float y, uint32_t col, bool aa)
|
||||
{
|
||||
if (!strip.isMatrix) return; // not a matrix set-up
|
||||
if (x<0.0f || x>1.0f || y<0.0f || y>1.0f) return; // not normalized
|
||||
|
||||
const uint16_t cols = virtualWidth();
|
||||
const uint16_t rows = virtualHeight();
|
||||
|
||||
float fX = x * (cols-1);
|
||||
float fY = y * (rows-1);
|
||||
if (aa) {
|
||||
uint16_t xL = roundf(fX-0.49f);
|
||||
uint16_t xR = roundf(fX+0.49f);
|
||||
uint16_t yT = roundf(fY-0.49f);
|
||||
uint16_t yB = roundf(fY+0.49f);
|
||||
float dL = fX - xL;
|
||||
float dR = xR - fX;
|
||||
float dT = fY - yT;
|
||||
float dB = yB - fY;
|
||||
uint32_t cXLYT = getPixelColorXY(xL, yT);
|
||||
uint32_t cXRYT = getPixelColorXY(xR, yT);
|
||||
uint32_t cXLYB = getPixelColorXY(xL, yB);
|
||||
uint32_t cXRYB = getPixelColorXY(xR, yB);
|
||||
|
||||
if (xL!=xR && yT!=yB) {
|
||||
setPixelColorXY(xL, yT, color_blend(col, cXLYT, uint8_t(sqrtf(dL*dT)*255.0f))); // blend TL pixel
|
||||
setPixelColorXY(xR, yT, color_blend(col, cXRYT, uint8_t(sqrtf(dR*dT)*255.0f))); // blend TR pixel
|
||||
setPixelColorXY(xL, yB, color_blend(col, cXLYB, uint8_t(sqrtf(dL*dB)*255.0f))); // blend BL pixel
|
||||
setPixelColorXY(xR, yB, color_blend(col, cXRYB, uint8_t(sqrtf(dR*dB)*255.0f))); // blend BR pixel
|
||||
} else if (xR!=xL && yT==yB) {
|
||||
setPixelColorXY(xR, yT, color_blend(col, cXLYT, uint8_t(dL*255.0f))); // blend L pixel
|
||||
setPixelColorXY(xR, yT, color_blend(col, cXRYT, uint8_t(dR*255.0f))); // blend R pixel
|
||||
} else if (xR==xL && yT!=yB) {
|
||||
setPixelColorXY(xR, yT, color_blend(col, cXLYT, uint8_t(dT*255.0f))); // blend T pixel
|
||||
setPixelColorXY(xL, yB, color_blend(col, cXLYB, uint8_t(dB*255.0f))); // blend B pixel
|
||||
} else {
|
||||
setPixelColorXY(xL, yT, col); // exact match (x & y land on a pixel)
|
||||
}
|
||||
} else {
|
||||
setPixelColorXY(uint16_t(roundf(fX)), uint16_t(roundf(fY)), col);
|
||||
}
|
||||
}
|
||||
|
||||
// returns RGBW values of pixel
|
||||
uint32_t Segment::getPixelColorXY(uint16_t x, uint16_t y) {
|
||||
int i = XY(x,y);
|
||||
if (leds) return RGBW32(leds[i].r, leds[i].g, leds[i].b, 0);
|
||||
if (reverse ) x = virtualWidth() - x - 1;
|
||||
if (reverse_y) y = virtualHeight() - y - 1;
|
||||
if (transpose) { uint16_t t = x; x = y; y = t; } // swap X & Y if segment transposed
|
||||
x *= groupLength(); // expand to physical pixels
|
||||
y *= groupLength(); // expand to physical pixels
|
||||
if (x >= width() || y >= height()) return 0;
|
||||
return strip.getPixelColorXY(start + x, startY + y);
|
||||
}
|
||||
|
||||
// Blends the specified color with the existing pixel color.
|
||||
void Segment::blendPixelColorXY(uint16_t x, uint16_t y, uint32_t color, uint8_t blend) {
|
||||
setPixelColorXY(x, y, color_blend(getPixelColorXY(x,y), color, blend));
|
||||
}
|
||||
|
||||
// Adds the specified color with the existing pixel color perserving color balance.
|
||||
void Segment::addPixelColorXY(int x, int y, uint32_t color) {
|
||||
setPixelColorXY(x, y, color_add(getPixelColorXY(x,y), color));
|
||||
}
|
||||
|
||||
void Segment::fadePixelColorXY(uint16_t x, uint16_t y, uint8_t fade) {
|
||||
CRGB pix = CRGB(getPixelColorXY(x,y)).nscale8_video(fade);
|
||||
setPixelColor(x, y, pix);
|
||||
}
|
||||
|
||||
// blurRow: perform a blur on a row of a rectangular matrix
|
||||
void Segment::blurRow(uint16_t row, fract8 blur_amount) {
|
||||
const uint16_t cols = virtualWidth();
|
||||
const uint16_t rows = virtualHeight();
|
||||
|
||||
if (row >= rows) return;
|
||||
// blur one row
|
||||
uint8_t keep = 255 - blur_amount;
|
||||
uint8_t seep = blur_amount >> 1;
|
||||
CRGB carryover = CRGB::Black;
|
||||
for (uint16_t x = 0; x < cols; x++) {
|
||||
CRGB cur = getPixelColorXY(x, row);
|
||||
CRGB part = cur;
|
||||
part.nscale8(seep);
|
||||
cur.nscale8(keep);
|
||||
cur += carryover;
|
||||
if (x) {
|
||||
CRGB prev = CRGB(getPixelColorXY(x-1, row)) + part;
|
||||
setPixelColorXY(x-1, row, prev);
|
||||
}
|
||||
setPixelColorXY(x, row, cur);
|
||||
carryover = part;
|
||||
}
|
||||
}
|
||||
|
||||
// blurCol: perform a blur on a column of a rectangular matrix
|
||||
void Segment::blurCol(uint16_t col, fract8 blur_amount) {
|
||||
const uint16_t cols = virtualWidth();
|
||||
const uint16_t rows = virtualHeight();
|
||||
|
||||
if (col >= cols) return;
|
||||
// blur one column
|
||||
uint8_t keep = 255 - blur_amount;
|
||||
uint8_t seep = blur_amount >> 1;
|
||||
CRGB carryover = CRGB::Black;
|
||||
for (uint16_t i = 0; i < rows; i++) {
|
||||
CRGB cur = getPixelColorXY(col, i);
|
||||
CRGB part = cur;
|
||||
part.nscale8(seep);
|
||||
cur.nscale8(keep);
|
||||
cur += carryover;
|
||||
if (i) {
|
||||
CRGB prev = CRGB(getPixelColorXY(col, i-1)) + part;
|
||||
setPixelColorXY(col, i-1, prev);
|
||||
}
|
||||
setPixelColorXY(col, i, cur);
|
||||
carryover = part;
|
||||
}
|
||||
}
|
||||
|
||||
// 1D Box blur (with added weight - blur_amount: [0=no blur, 255=max blur])
|
||||
void Segment::box_blur(uint16_t i, bool vertical, fract8 blur_amount) {
|
||||
const uint16_t cols = virtualWidth();
|
||||
const uint16_t rows = virtualHeight();
|
||||
const uint16_t dim1 = vertical ? rows : cols;
|
||||
const uint16_t dim2 = vertical ? cols : rows;
|
||||
if (i >= dim2) return;
|
||||
const float seep = blur_amount/255.f;
|
||||
const float keep = 3.f - 2.f*seep;
|
||||
// 1D box blur
|
||||
CRGB tmp[dim1];
|
||||
for (uint16_t j = 0; j < dim1; j++) {
|
||||
uint16_t x = vertical ? i : j;
|
||||
uint16_t y = vertical ? j : i;
|
||||
uint16_t xp = vertical ? x : x-1;
|
||||
uint16_t yp = vertical ? y-1 : y;
|
||||
uint16_t xn = vertical ? x : x+1;
|
||||
uint16_t yn = vertical ? y+1 : y;
|
||||
CRGB curr = getPixelColorXY(x,y);
|
||||
CRGB prev = (xp<0 || yp<0) ? CRGB::Black : getPixelColorXY(xp,yp);
|
||||
CRGB next = ((vertical && yn>=dim1) || (!vertical && xn>=dim1)) ? CRGB::Black : getPixelColorXY(xn,yn);
|
||||
uint16_t r, g, b;
|
||||
r = (curr.r*keep + (prev.r + next.r)*seep) / 3;
|
||||
g = (curr.g*keep + (prev.g + next.g)*seep) / 3;
|
||||
b = (curr.b*keep + (prev.b + next.b)*seep) / 3;
|
||||
tmp[j] = CRGB(r,g,b);
|
||||
}
|
||||
for (uint16_t j = 0; j < dim1; j++) {
|
||||
uint16_t x = vertical ? i : j;
|
||||
uint16_t y = vertical ? j : i;
|
||||
setPixelColorXY(x, y, tmp[j]);
|
||||
}
|
||||
}
|
||||
|
||||
// blur1d: one-dimensional blur filter. Spreads light to 2 line neighbors.
|
||||
// blur2d: two-dimensional blur filter. Spreads light to 8 XY neighbors.
|
||||
//
|
||||
// 0 = no spread at all
|
||||
// 64 = moderate spreading
|
||||
// 172 = maximum smooth, even spreading
|
||||
//
|
||||
// 173..255 = wider spreading, but increasing flicker
|
||||
//
|
||||
// Total light is NOT entirely conserved, so many repeated
|
||||
// calls to 'blur' will also result in the light fading,
|
||||
// eventually all the way to black; this is by design so that
|
||||
// it can be used to (slowly) clear the LEDs to black.
|
||||
|
||||
void Segment::blur1d(fract8 blur_amount) {
|
||||
const uint16_t rows = virtualHeight();
|
||||
for (uint16_t y = 0; y < rows; y++) blurRow(y, blur_amount);
|
||||
}
|
||||
|
||||
void Segment::moveX(int8_t delta) {
|
||||
const uint16_t cols = virtualWidth();
|
||||
const uint16_t rows = virtualHeight();
|
||||
if (!delta) return;
|
||||
if (delta > 0) {
|
||||
for (uint8_t y = 0; y < rows; y++) for (uint8_t x = 0; x < cols-1; x++) {
|
||||
if (x + delta >= cols) break;
|
||||
setPixelColorXY(x, y, getPixelColorXY((x + delta)%cols, y));
|
||||
}
|
||||
} else {
|
||||
for (uint8_t y = 0; y < rows; y++) for (int16_t x = cols-1; x >= 0; x--) {
|
||||
if (x + delta < 0) break;
|
||||
setPixelColorXY(x, y, getPixelColorXY(x + delta, y));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Segment::moveY(int8_t delta) {
|
||||
const uint16_t cols = virtualWidth();
|
||||
const uint16_t rows = virtualHeight();
|
||||
if (!delta) return;
|
||||
if (delta > 0) {
|
||||
for (uint8_t x = 0; x < cols; x++) for (uint8_t y = 0; y < rows-1; y++) {
|
||||
if (y + delta >= rows) break;
|
||||
setPixelColorXY(x, y, getPixelColorXY(x, (y + delta)));
|
||||
}
|
||||
} else {
|
||||
for (uint8_t x = 0; x < cols; x++) for (int16_t y = rows-1; y >= 0; y--) {
|
||||
if (y + delta < 0) break;
|
||||
setPixelColorXY(x, y, getPixelColorXY(x, y + delta));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// move() - move all pixels in desired direction delta number of pixels
|
||||
// @param dir direction: 0=left, 1=left-up, 2=up, 3=right-up, 4=right, 5=right-down, 6=down, 7=left-down
|
||||
// @param delta number of pixels to move
|
||||
void Segment::move(uint8_t dir, uint8_t delta) {
|
||||
if (delta==0) return;
|
||||
switch (dir) {
|
||||
case 0: moveX( delta); break;
|
||||
case 1: moveX( delta); moveY( delta); break;
|
||||
case 2: moveY( delta); break;
|
||||
case 3: moveX(-delta); moveY( delta); break;
|
||||
case 4: moveX(-delta); break;
|
||||
case 5: moveX(-delta); moveY(-delta); break;
|
||||
case 6: moveY(-delta); break;
|
||||
case 7: moveX( delta); moveY(-delta); break;
|
||||
}
|
||||
}
|
||||
|
||||
// by stepko, taken from https://editor.soulmatelights.com/gallery/573-blobs
|
||||
void Segment::fill_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB col) {
|
||||
const uint16_t cols = virtualWidth();
|
||||
const uint16_t rows = virtualHeight();
|
||||
for (int16_t y = -radius; y <= radius; y++) {
|
||||
for (int16_t x = -radius; x <= radius; x++) {
|
||||
if (x * x + y * y <= radius * radius &&
|
||||
int16_t(cx)+x>=0 && int16_t(cy)+y>=0 &&
|
||||
int16_t(cx)+x<cols && int16_t(cy)+y<rows)
|
||||
addPixelColorXY(cx + x, cy + y, col);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Segment::nscale8(uint8_t scale) {
|
||||
const uint16_t cols = virtualWidth();
|
||||
const uint16_t rows = virtualHeight();
|
||||
for(uint16_t y = 0; y < rows; y++) for (uint16_t x = 0; x < cols; x++) {
|
||||
if (leds) leds[XY(x,y)].nscale8(scale);
|
||||
else setPixelColorXY(x, y, CRGB(getPixelColorXY(x, y)).nscale8(scale));
|
||||
}
|
||||
}
|
||||
|
||||
//line function
|
||||
void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c) {
|
||||
const uint16_t cols = virtualWidth();
|
||||
const uint16_t rows = virtualHeight();
|
||||
if (x0 >= cols || x1 >= cols || y0 >= rows || y1 >= rows) return;
|
||||
const int16_t dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
|
||||
const int16_t dy = abs(y1-y0), sy = y0<y1 ? 1 : -1;
|
||||
int16_t err = (dx>dy ? dx : -dy)/2, e2;
|
||||
for (;;) {
|
||||
setPixelColorXY(x0,y0,c);
|
||||
if (x0==x1 && y0==y1) break;
|
||||
e2 = err;
|
||||
if (e2 >-dx) { err -= dy; x0 += sx; }
|
||||
if (e2 < dy) { err += dx; y0 += sy; }
|
||||
}
|
||||
}
|
||||
|
||||
#include "console_font_5x8.h"
|
||||
#include "console_font_5x12.h"
|
||||
#include "console_font_6x8.h"
|
||||
#include "console_font_7x9.h"
|
||||
|
||||
// draws a raster font character on canvas
|
||||
// only supports 5x8=40, 5x12=60, 6x8=48 and 7x9=63 fonts ATM
|
||||
void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color) {
|
||||
const uint16_t cols = virtualWidth();
|
||||
const uint16_t rows = virtualHeight();
|
||||
const int font = w*h;
|
||||
|
||||
//if (w<5 || w>6 || h!=8) return;
|
||||
for (int i = 0; i<h; i++) { // character height
|
||||
int16_t y0 = y + i;
|
||||
if (y0 < 0) continue; // drawing off-screen
|
||||
if (y0 >= rows) break; // drawing off-screen
|
||||
uint8_t bits = 0;
|
||||
switch (font) {
|
||||
case 40: bits = pgm_read_byte_near(&console_font_5x8[(chr * h) + i]); break; // 5x8 font
|
||||
case 48: bits = pgm_read_byte_near(&console_font_6x8[(chr * h) + i]); break; // 6x8 font
|
||||
case 63: bits = pgm_read_byte_near(&console_font_7x9[(chr * h) + i]); break; // 7x9 font
|
||||
case 60: bits = pgm_read_byte_near(&console_font_5x12[(chr * h) + i]); break; // 5x12 font
|
||||
default: return;
|
||||
}
|
||||
for (int j = 0; j<w; j++) { // character width
|
||||
int16_t x0 = x + (w-1) - j;
|
||||
if ((x0 >= 0 || x0 < cols) && ((bits>>(j+(8-w))) & 0x01)) { // bit set & drawing on-screen
|
||||
setPixelColorXY(x0, y0, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define WU_WEIGHT(a,b) ((uint8_t) (((a)*(b)+(a)+(b))>>8))
|
||||
void Segment::wu_pixel(uint32_t x, uint32_t y, CRGB c) { //awesome wu_pixel procedure by reddit u/sutaburosu
|
||||
// extract the fractional parts and derive their inverses
|
||||
uint8_t xx = x & 0xff, yy = y & 0xff, ix = 255 - xx, iy = 255 - yy;
|
||||
// calculate the intensities for each affected pixel
|
||||
uint8_t wu[4] = {WU_WEIGHT(ix, iy), WU_WEIGHT(xx, iy),
|
||||
WU_WEIGHT(ix, yy), WU_WEIGHT(xx, yy)};
|
||||
// multiply the intensities by the colour, and saturating-add them to the pixels
|
||||
for (int i = 0; i < 4; i++) {
|
||||
CRGB led = getPixelColorXY((x >> 8) + (i & 1), (y >> 8) + ((i >> 1) & 1));
|
||||
led.r = qadd8(led.r, c.r * wu[i] >> 8);
|
||||
led.g = qadd8(led.g, c.g * wu[i] >> 8);
|
||||
led.b = qadd8(led.b, c.b * wu[i] >> 8);
|
||||
setPixelColorXY(int((x >> 8) + (i & 1)), int((y >> 8) + ((i >> 1) & 1)), led);
|
||||
}
|
||||
}
|
||||
#undef WU_WEIGHT
|
||||
|
||||
#endif // WLED_DISABLE_2D
|
1821
wled00/FX_fcn.cpp
1821
wled00/FX_fcn.cpp
File diff suppressed because it is too large
Load Diff
@ -461,7 +461,7 @@ class BusPwm : public Bus {
|
||||
return numPins;
|
||||
}
|
||||
|
||||
inline void cleanup() {
|
||||
void cleanup() {
|
||||
deallocatePins();
|
||||
}
|
||||
|
||||
@ -494,6 +494,71 @@ class BusPwm : public Bus {
|
||||
};
|
||||
|
||||
|
||||
class BusOnOff : public Bus {
|
||||
public:
|
||||
BusOnOff(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) {
|
||||
_valid = false;
|
||||
if (bc.type != TYPE_ONOFF) return;
|
||||
|
||||
uint8_t currentPin = bc.pins[0];
|
||||
if (!pinManager.allocatePin(currentPin, true, PinOwner::BusOnOff)) {
|
||||
deallocatePins(); return;
|
||||
}
|
||||
_pin = currentPin; //store only after allocatePin() succeeds
|
||||
pinMode(_pin, OUTPUT);
|
||||
reversed = bc.reversed;
|
||||
_valid = true;
|
||||
};
|
||||
|
||||
void setPixelColor(uint16_t pix, uint32_t c) {
|
||||
if (pix != 0 || !_valid) return; //only react to first pixel
|
||||
c = autoWhiteCalc(c);
|
||||
uint8_t r = R(c);
|
||||
uint8_t g = G(c);
|
||||
uint8_t b = B(c);
|
||||
uint8_t w = W(c);
|
||||
|
||||
_data = bool((r+g+b+w) && _bri) ? 0xFF : 0;
|
||||
}
|
||||
|
||||
uint32_t getPixelColor(uint16_t pix) {
|
||||
if (!_valid) return 0;
|
||||
return RGBW32(_data, _data, _data, _data);
|
||||
}
|
||||
|
||||
void show() {
|
||||
if (!_valid) return;
|
||||
digitalWrite(_pin, reversed ? !(bool)_data : (bool)_data);
|
||||
}
|
||||
|
||||
inline void setBrightness(uint8_t b) {
|
||||
_bri = b;
|
||||
}
|
||||
|
||||
uint8_t getPins(uint8_t* pinArray) {
|
||||
if (!_valid) return 0;
|
||||
pinArray[0] = _pin;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void cleanup() {
|
||||
deallocatePins();
|
||||
}
|
||||
|
||||
~BusOnOff() {
|
||||
cleanup();
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t _pin = 255;
|
||||
uint8_t _data = 0;
|
||||
|
||||
void deallocatePins() {
|
||||
pinManager.deallocatePin(_pin, PinOwner::BusOnOff);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class BusNetwork : public Bus {
|
||||
public:
|
||||
BusNetwork(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) {
|
||||
|
@ -33,6 +33,11 @@
|
||||
#define I_8266_U1_TM1_4 14
|
||||
#define I_8266_DM_TM1_4 15
|
||||
#define I_8266_BB_TM1_4 16
|
||||
//TM1829 (RGB)
|
||||
#define I_8266_U0_TM2_3 39
|
||||
#define I_8266_U1_TM2_3 40
|
||||
#define I_8266_DM_TM2_3 41
|
||||
#define I_8266_BB_TM2_3 42
|
||||
|
||||
/*** ESP32 Neopixel methods ***/
|
||||
//RGB
|
||||
@ -52,6 +57,11 @@
|
||||
#define I_32_I0_TM1_4 27
|
||||
#define I_32_I1_TM1_4 28
|
||||
//Bit Bang theoratically possible, but very undesirable and not needed (no pin restrictions on RMT and I2S)
|
||||
//TM1829 (RGB)
|
||||
#define I_32_RN_TM2_3 43
|
||||
#define I_32_I0_TM2_3 44
|
||||
#define I_32_I1_TM2_3 45
|
||||
//Bit Bang theoratically possible, but very undesirable and not needed (no pin restrictions on RMT and I2S)
|
||||
|
||||
//APA102
|
||||
#define I_HS_DOT_3 29 //hardware SPI
|
||||
@ -96,6 +106,11 @@
|
||||
#define B_8266_U1_TM1_4 NeoPixelBrightnessBus<NeoWrgbTm1814Feature, NeoEsp8266Uart1Tm1814Method>
|
||||
#define B_8266_DM_TM1_4 NeoPixelBrightnessBus<NeoWrgbTm1814Feature, NeoEsp8266DmaTm1814Method>
|
||||
#define B_8266_BB_TM1_4 NeoPixelBrightnessBus<NeoWrgbTm1814Feature, NeoEsp8266BitBangTm1814Method>
|
||||
//TM1829 (RGB)
|
||||
#define B_8266_U0_TM2_4 NeoPixelBrightnessBus<NeoBrgFeature, NeoEsp8266Uart0Tm1829Method>
|
||||
#define B_8266_U1_TM2_4 NeoPixelBrightnessBus<NeoBrgFeature, NeoEsp8266Uart1Tm1829Method>
|
||||
#define B_8266_DM_TM2_4 NeoPixelBrightnessBus<NeoBrgFeature, NeoEsp8266DmaTm1829Method>
|
||||
#define B_8266_BB_TM2_4 NeoPixelBrightnessBus<NeoBrgFeature, NeoEsp8266BitBangTm1829Method>
|
||||
#endif
|
||||
|
||||
/*** ESP32 Neopixel methods ***/
|
||||
@ -133,6 +148,15 @@
|
||||
#define B_32_I1_TM1_4 NeoPixelBrightnessBus<NeoWrgbTm1814Feature, NeoEsp32I2s1Tm1814Method>
|
||||
#endif
|
||||
//Bit Bang theoratically possible, but very undesirable and not needed (no pin restrictions on RMT and I2S)
|
||||
//TM1829 (RGB)
|
||||
#define B_32_RN_TM2_3 NeoPixelBrightnessBus<NeoBrgFeature, NeoEsp32RmtNTm1829Method>
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#define B_32_I0_TM2_3 NeoPixelBrightnessBus<NeoBrgFeature, NeoEsp32I2s0Tm1829Method>
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#define B_32_I1_TM2_3 NeoPixelBrightnessBus<NeoBrgFeature, NeoEsp32I2s1Tm1829Method>
|
||||
#endif
|
||||
//Bit Bang theoratically possible, but very undesirable and not needed (no pin restrictions on RMT and I2S)
|
||||
|
||||
#endif
|
||||
|
||||
@ -201,6 +225,10 @@ class PolyBus {
|
||||
case I_8266_U1_TM1_4: beginTM1814<B_8266_U1_TM1_4*>(busPtr); break;
|
||||
case I_8266_DM_TM1_4: beginTM1814<B_8266_DM_TM1_4*>(busPtr); break;
|
||||
case I_8266_BB_TM1_4: beginTM1814<B_8266_BB_TM1_4*>(busPtr); break;
|
||||
case I_8266_U0_TM2_3: (static_cast<B_8266_U0_TM2_4*>(busPtr))->Begin(); break;
|
||||
case I_8266_U1_TM2_3: (static_cast<B_8266_U1_TM2_4*>(busPtr))->Begin(); break;
|
||||
case I_8266_DM_TM2_3: (static_cast<B_8266_DM_TM2_4*>(busPtr))->Begin(); break;
|
||||
case I_8266_BB_TM2_3: (static_cast<B_8266_BB_TM2_4*>(busPtr))->Begin(); break;
|
||||
case I_HS_DOT_3: (static_cast<B_HS_DOT_3*>(busPtr))->Begin(); break;
|
||||
case I_HS_LPD_3: (static_cast<B_HS_LPD_3*>(busPtr))->Begin(); break;
|
||||
case I_HS_LPO_3: (static_cast<B_HS_LPO_3*>(busPtr))->Begin(); break;
|
||||
@ -230,11 +258,14 @@ class PolyBus {
|
||||
case I_32_I1_400_3: (static_cast<B_32_I1_400_3*>(busPtr))->Begin(); break;
|
||||
#endif
|
||||
case I_32_RN_TM1_4: beginTM1814<B_32_RN_TM1_4*>(busPtr); break;
|
||||
case I_32_RN_TM2_3: (static_cast<B_32_RN_TM2_3*>(busPtr))->Begin(); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
case I_32_I0_TM1_4: beginTM1814<B_32_I0_TM1_4*>(busPtr); break;
|
||||
case I_32_I0_TM2_3: (static_cast<B_32_I0_TM2_3*>(busPtr))->Begin(); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
case I_32_I1_TM1_4: beginTM1814<B_32_I1_TM1_4*>(busPtr); break;
|
||||
case I_32_I1_TM2_3: (static_cast<B_32_I1_TM2_3*>(busPtr))->Begin(); break;
|
||||
#endif
|
||||
// ESP32 can (and should, to avoid inadvertantly driving the chip select signal) specify the pins used for SPI, but only in begin()
|
||||
case I_HS_DOT_3: (static_cast<B_HS_DOT_3*>(busPtr))->Begin(pins[1], -1, pins[0], -1); break;
|
||||
@ -271,6 +302,10 @@ class PolyBus {
|
||||
case I_8266_U1_TM1_4: busPtr = new B_8266_U1_TM1_4(len, pins[0]); break;
|
||||
case I_8266_DM_TM1_4: busPtr = new B_8266_DM_TM1_4(len, pins[0]); break;
|
||||
case I_8266_BB_TM1_4: busPtr = new B_8266_BB_TM1_4(len, pins[0]); break;
|
||||
case I_8266_U0_TM2_3: busPtr = new B_8266_U0_TM2_4(len, pins[0]); break;
|
||||
case I_8266_U1_TM2_3: busPtr = new B_8266_U1_TM2_4(len, pins[0]); break;
|
||||
case I_8266_DM_TM2_3: busPtr = new B_8266_DM_TM2_4(len, pins[0]); break;
|
||||
case I_8266_BB_TM2_3: busPtr = new B_8266_BB_TM2_4(len, pins[0]); break;
|
||||
#endif
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
case I_32_RN_NEO_3: busPtr = new B_32_RN_NEO_3(len, pins[0], (NeoBusChannel)channel); break;
|
||||
@ -295,11 +330,14 @@ class PolyBus {
|
||||
case I_32_I1_400_3: busPtr = new B_32_I1_400_3(len, pins[0]); break;
|
||||
#endif
|
||||
case I_32_RN_TM1_4: busPtr = new B_32_RN_TM1_4(len, pins[0], (NeoBusChannel)channel); break;
|
||||
case I_32_RN_TM2_3: busPtr = new B_32_RN_TM2_3(len, pins[0], (NeoBusChannel)channel); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
case I_32_I0_TM1_4: busPtr = new B_32_I0_TM1_4(len, pins[0]); break;
|
||||
case I_32_I0_TM2_3: busPtr = new B_32_I0_TM2_3(len, pins[0]); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
case I_32_I1_TM1_4: busPtr = new B_32_I1_TM1_4(len, pins[0]); break;
|
||||
case I_32_I1_TM2_3: busPtr = new B_32_I1_TM2_3(len, pins[0]); break;
|
||||
#endif
|
||||
#endif
|
||||
// for 2-wire: pins[1] is clk, pins[0] is dat. begin expects (len, clk, dat)
|
||||
@ -337,6 +375,10 @@ class PolyBus {
|
||||
case I_8266_U1_TM1_4: (static_cast<B_8266_U1_TM1_4*>(busPtr))->Show(); break;
|
||||
case I_8266_DM_TM1_4: (static_cast<B_8266_DM_TM1_4*>(busPtr))->Show(); break;
|
||||
case I_8266_BB_TM1_4: (static_cast<B_8266_BB_TM1_4*>(busPtr))->Show(); break;
|
||||
case I_8266_U0_TM2_3: (static_cast<B_8266_U0_TM2_4*>(busPtr))->Show(); break;
|
||||
case I_8266_U1_TM2_3: (static_cast<B_8266_U1_TM2_4*>(busPtr))->Show(); break;
|
||||
case I_8266_DM_TM2_3: (static_cast<B_8266_DM_TM2_4*>(busPtr))->Show(); break;
|
||||
case I_8266_BB_TM2_3: (static_cast<B_8266_BB_TM2_4*>(busPtr))->Show(); break;
|
||||
#endif
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->Show(); break;
|
||||
@ -361,11 +403,14 @@ class PolyBus {
|
||||
case I_32_I1_400_3: (static_cast<B_32_I1_400_3*>(busPtr))->Show(); break;
|
||||
#endif
|
||||
case I_32_RN_TM1_4: (static_cast<B_32_RN_TM1_4*>(busPtr))->Show(); break;
|
||||
case I_32_RN_TM2_3: (static_cast<B_32_RN_TM2_3*>(busPtr))->Show(); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
case I_32_I0_TM1_4: (static_cast<B_32_I0_TM1_4*>(busPtr))->Show(); break;
|
||||
case I_32_I0_TM2_3: (static_cast<B_32_I0_TM2_3*>(busPtr))->Show(); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
case I_32_I1_TM1_4: (static_cast<B_32_I1_TM1_4*>(busPtr))->Show(); break;
|
||||
case I_32_I1_TM2_3: (static_cast<B_32_I1_TM2_3*>(busPtr))->Show(); break;
|
||||
#endif
|
||||
#endif
|
||||
case I_HS_DOT_3: (static_cast<B_HS_DOT_3*>(busPtr))->Show(); break;
|
||||
@ -400,6 +445,10 @@ class PolyBus {
|
||||
case I_8266_U1_TM1_4: return (static_cast<B_8266_U1_TM1_4*>(busPtr))->CanShow(); break;
|
||||
case I_8266_DM_TM1_4: return (static_cast<B_8266_DM_TM1_4*>(busPtr))->CanShow(); break;
|
||||
case I_8266_BB_TM1_4: return (static_cast<B_8266_BB_TM1_4*>(busPtr))->CanShow(); break;
|
||||
case I_8266_U0_TM2_3: return (static_cast<B_8266_U0_TM2_4*>(busPtr))->CanShow(); break;
|
||||
case I_8266_U1_TM2_3: return (static_cast<B_8266_U1_TM2_4*>(busPtr))->CanShow(); break;
|
||||
case I_8266_DM_TM2_3: return (static_cast<B_8266_DM_TM2_4*>(busPtr))->CanShow(); break;
|
||||
case I_8266_BB_TM2_3: return (static_cast<B_8266_BB_TM2_4*>(busPtr))->CanShow(); break;
|
||||
#endif
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
case I_32_RN_NEO_3: return (static_cast<B_32_RN_NEO_3*>(busPtr))->CanShow(); break;
|
||||
@ -424,11 +473,14 @@ class PolyBus {
|
||||
case I_32_I1_400_3: return (static_cast<B_32_I1_400_3*>(busPtr))->CanShow(); break;
|
||||
#endif
|
||||
case I_32_RN_TM1_4: return (static_cast<B_32_RN_TM1_4*>(busPtr))->CanShow(); break;
|
||||
case I_32_RN_TM2_3: return (static_cast<B_32_RN_TM2_3*>(busPtr))->CanShow(); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
case I_32_I0_TM1_4: return (static_cast<B_32_I0_TM1_4*>(busPtr))->CanShow(); break;
|
||||
case I_32_I0_TM2_3: return (static_cast<B_32_I0_TM2_3*>(busPtr))->CanShow(); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
case I_32_I1_TM1_4: return (static_cast<B_32_I1_TM1_4*>(busPtr))->CanShow(); break;
|
||||
case I_32_I1_TM2_3: return (static_cast<B_32_I1_TM2_3*>(busPtr))->CanShow(); break;
|
||||
#endif
|
||||
#endif
|
||||
case I_HS_DOT_3: return (static_cast<B_HS_DOT_3*>(busPtr))->CanShow(); break;
|
||||
@ -487,6 +539,10 @@ class PolyBus {
|
||||
case I_8266_U1_TM1_4: (static_cast<B_8266_U1_TM1_4*>(busPtr))->SetPixelColor(pix, col); break;
|
||||
case I_8266_DM_TM1_4: (static_cast<B_8266_DM_TM1_4*>(busPtr))->SetPixelColor(pix, col); break;
|
||||
case I_8266_BB_TM1_4: (static_cast<B_8266_BB_TM1_4*>(busPtr))->SetPixelColor(pix, col); break;
|
||||
case I_8266_U0_TM2_3: (static_cast<B_8266_U0_TM2_4*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
|
||||
case I_8266_U1_TM2_3: (static_cast<B_8266_U1_TM2_4*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
|
||||
case I_8266_DM_TM2_3: (static_cast<B_8266_DM_TM2_4*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
|
||||
case I_8266_BB_TM2_3: (static_cast<B_8266_BB_TM2_4*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
|
||||
#endif
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
|
||||
@ -511,11 +567,14 @@ class PolyBus {
|
||||
case I_32_I1_400_3: (static_cast<B_32_I1_400_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
|
||||
#endif
|
||||
case I_32_RN_TM1_4: (static_cast<B_32_RN_TM1_4*>(busPtr))->SetPixelColor(pix, col); break;
|
||||
case I_32_RN_TM2_3: (static_cast<B_32_RN_TM2_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
case I_32_I0_TM1_4: (static_cast<B_32_I0_TM1_4*>(busPtr))->SetPixelColor(pix, col); break;
|
||||
case I_32_I0_TM2_3: (static_cast<B_32_I0_TM2_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
case I_32_I1_TM1_4: (static_cast<B_32_I1_TM1_4*>(busPtr))->SetPixelColor(pix, col); break;
|
||||
case I_32_I1_TM2_3: (static_cast<B_32_I1_TM2_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
|
||||
#endif
|
||||
#endif
|
||||
case I_HS_DOT_3: (static_cast<B_HS_DOT_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
|
||||
@ -550,6 +609,10 @@ class PolyBus {
|
||||
case I_8266_U1_TM1_4: (static_cast<B_8266_U1_TM1_4*>(busPtr))->SetBrightness(b); break;
|
||||
case I_8266_DM_TM1_4: (static_cast<B_8266_DM_TM1_4*>(busPtr))->SetBrightness(b); break;
|
||||
case I_8266_BB_TM1_4: (static_cast<B_8266_BB_TM1_4*>(busPtr))->SetBrightness(b); break;
|
||||
case I_8266_U0_TM2_3: (static_cast<B_8266_U0_TM2_4*>(busPtr))->SetBrightness(b); break;
|
||||
case I_8266_U1_TM2_3: (static_cast<B_8266_U1_TM2_4*>(busPtr))->SetBrightness(b); break;
|
||||
case I_8266_DM_TM2_3: (static_cast<B_8266_DM_TM2_4*>(busPtr))->SetBrightness(b); break;
|
||||
case I_8266_BB_TM2_3: (static_cast<B_8266_BB_TM2_4*>(busPtr))->SetBrightness(b); break;
|
||||
#endif
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->SetBrightness(b); break;
|
||||
@ -574,11 +637,14 @@ class PolyBus {
|
||||
case I_32_I1_400_3: (static_cast<B_32_I1_400_3*>(busPtr))->SetBrightness(b); break;
|
||||
#endif
|
||||
case I_32_RN_TM1_4: (static_cast<B_32_RN_TM1_4*>(busPtr))->SetBrightness(b); break;
|
||||
case I_32_RN_TM2_3: (static_cast<B_32_RN_TM2_3*>(busPtr))->SetBrightness(b); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
case I_32_I0_TM1_4: (static_cast<B_32_I0_TM1_4*>(busPtr))->SetBrightness(b); break;
|
||||
case I_32_I0_TM2_3: (static_cast<B_32_I0_TM2_3*>(busPtr))->SetBrightness(b); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
case I_32_I1_TM1_4: (static_cast<B_32_I1_TM1_4*>(busPtr))->SetBrightness(b); break;
|
||||
case I_32_I1_TM2_3: (static_cast<B_32_I1_TM2_3*>(busPtr))->SetBrightness(b); break;
|
||||
#endif
|
||||
#endif
|
||||
case I_HS_DOT_3: (static_cast<B_HS_DOT_3*>(busPtr))->SetBrightness(b); break;
|
||||
@ -614,6 +680,10 @@ class PolyBus {
|
||||
case I_8266_U1_TM1_4: col = (static_cast<B_8266_U1_TM1_4*>(busPtr))->GetPixelColor(pix); break;
|
||||
case I_8266_DM_TM1_4: col = (static_cast<B_8266_DM_TM1_4*>(busPtr))->GetPixelColor(pix); break;
|
||||
case I_8266_BB_TM1_4: col = (static_cast<B_8266_BB_TM1_4*>(busPtr))->GetPixelColor(pix); break;
|
||||
case I_8266_U0_TM2_3: col = (static_cast<B_8266_U0_TM2_4*>(busPtr))->GetPixelColor(pix); break;
|
||||
case I_8266_U1_TM2_3: col = (static_cast<B_8266_U1_TM2_4*>(busPtr))->GetPixelColor(pix); break;
|
||||
case I_8266_DM_TM2_3: col = (static_cast<B_8266_DM_TM2_4*>(busPtr))->GetPixelColor(pix); break;
|
||||
case I_8266_BB_TM2_3: col = (static_cast<B_8266_BB_TM2_4*>(busPtr))->GetPixelColor(pix); break;
|
||||
#endif
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
case I_32_RN_NEO_3: col = (static_cast<B_32_RN_NEO_3*>(busPtr))->GetPixelColor(pix); break;
|
||||
@ -638,11 +708,14 @@ class PolyBus {
|
||||
case I_32_I1_400_3: col = (static_cast<B_32_I1_400_3*>(busPtr))->GetPixelColor(pix); break;
|
||||
#endif
|
||||
case I_32_RN_TM1_4: col = (static_cast<B_32_RN_TM1_4*>(busPtr))->GetPixelColor(pix); break;
|
||||
case I_32_RN_TM2_3: col = (static_cast<B_32_RN_TM2_3*>(busPtr))->GetPixelColor(pix); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
case I_32_I0_TM1_4: col = (static_cast<B_32_I0_TM1_4*>(busPtr))->GetPixelColor(pix); break;
|
||||
case I_32_I0_TM2_3: col = (static_cast<B_32_I0_TM2_3*>(busPtr))->GetPixelColor(pix); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
case I_32_I1_TM1_4: col = (static_cast<B_32_I1_TM1_4*>(busPtr))->GetPixelColor(pix); break;
|
||||
case I_32_I1_TM2_3: col = (static_cast<B_32_I1_TM2_3*>(busPtr))->GetPixelColor(pix); break;
|
||||
#endif
|
||||
#endif
|
||||
case I_HS_DOT_3: col = (static_cast<B_HS_DOT_3*>(busPtr))->GetPixelColor(pix); break;
|
||||
@ -697,6 +770,10 @@ class PolyBus {
|
||||
case I_8266_U1_TM1_4: delete (static_cast<B_8266_U1_TM1_4*>(busPtr)); break;
|
||||
case I_8266_DM_TM1_4: delete (static_cast<B_8266_DM_TM1_4*>(busPtr)); break;
|
||||
case I_8266_BB_TM1_4: delete (static_cast<B_8266_BB_TM1_4*>(busPtr)); break;
|
||||
case I_8266_U0_TM2_3: delete (static_cast<B_8266_U0_TM2_4*>(busPtr)); break;
|
||||
case I_8266_U1_TM2_3: delete (static_cast<B_8266_U1_TM2_4*>(busPtr)); break;
|
||||
case I_8266_DM_TM2_3: delete (static_cast<B_8266_DM_TM2_4*>(busPtr)); break;
|
||||
case I_8266_BB_TM2_3: delete (static_cast<B_8266_BB_TM2_4*>(busPtr)); break;
|
||||
#endif
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
case I_32_RN_NEO_3: delete (static_cast<B_32_RN_NEO_3*>(busPtr)); break;
|
||||
@ -721,11 +798,14 @@ class PolyBus {
|
||||
case I_32_I1_400_3: delete (static_cast<B_32_I1_400_3*>(busPtr)); break;
|
||||
#endif
|
||||
case I_32_RN_TM1_4: delete (static_cast<B_32_RN_TM1_4*>(busPtr)); break;
|
||||
case I_32_RN_TM2_3: delete (static_cast<B_32_RN_TM2_3*>(busPtr)); break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
case I_32_I0_TM1_4: delete (static_cast<B_32_I0_TM1_4*>(busPtr)); break;
|
||||
case I_32_I0_TM2_3: delete (static_cast<B_32_I0_TM2_3*>(busPtr)); break;
|
||||
#endif
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
case I_32_I1_TM1_4: delete (static_cast<B_32_I1_TM1_4*>(busPtr)); break;
|
||||
case I_32_I1_TM2_3: delete (static_cast<B_32_I1_TM2_3*>(busPtr)); break;
|
||||
#endif
|
||||
#endif
|
||||
case I_HS_DOT_3: delete (static_cast<B_HS_DOT_3*>(busPtr)); break;
|
||||
@ -779,6 +859,8 @@ class PolyBus {
|
||||
return I_8266_U0_400_3 + offset;
|
||||
case TYPE_TM1814:
|
||||
return I_8266_U0_TM1_4 + offset;
|
||||
case TYPE_TM1829:
|
||||
return I_8266_U0_TM2_3 + offset;
|
||||
}
|
||||
#else //ESP32
|
||||
uint8_t offset = 0; //0 = RMT (num 0-7) 8 = I2S0 9 = I2S1
|
||||
@ -799,6 +881,8 @@ class PolyBus {
|
||||
return I_32_RN_400_3 + offset;
|
||||
case TYPE_TM1814:
|
||||
return I_32_RN_TM1_4 + offset;
|
||||
case TYPE_TM1829:
|
||||
return I_32_RN_TM2_3 + offset;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -195,11 +195,11 @@ void handleAnalog(uint8_t b)
|
||||
colorHStoRGB(aRead*256,255,col);
|
||||
} else {
|
||||
// otherwise use "double press" for segment selection
|
||||
WS2812FX::Segment& seg = strip.getSegment(macroDoublePress[b]);
|
||||
Segment& seg = strip.getSegment(macroDoublePress[b]);
|
||||
if (aRead == 0) {
|
||||
seg.setOption(SEG_OPTION_ON, 0); // off
|
||||
} else {
|
||||
seg.setOpacity(aRead, macroDoublePress[b]);
|
||||
seg.setOpacity(aRead);
|
||||
seg.setOption(SEG_OPTION_ON, 1);
|
||||
}
|
||||
// this will notify clients of update (websockets,mqtt,etc)
|
||||
@ -216,10 +216,13 @@ void handleAnalog(uint8_t b)
|
||||
void handleButton()
|
||||
{
|
||||
static unsigned long lastRead = 0UL;
|
||||
static unsigned long lastRun = 0UL;
|
||||
bool analog = false;
|
||||
unsigned long now = millis();
|
||||
|
||||
if (strip.isUpdating()) return; // don't interfere with strip updates. Our button will still be there in 1ms (next cycle)
|
||||
//if (strip.isUpdating()) return; // don't interfere with strip updates. Our button will still be there in 1ms (next cycle)
|
||||
if (strip.isUpdating() && (millis() - lastRun < 400)) return; // be niced, but avoid button starvation
|
||||
lastRun = millis();
|
||||
|
||||
for (uint8_t b=0; b<WLED_MAX_BUTTONS; b++) {
|
||||
#ifdef ESP8266
|
||||
@ -265,7 +268,9 @@ void handleButton()
|
||||
if (b == 0 && dur > WLED_LONG_AP) { // long press on button 0 (when released)
|
||||
if (dur > WLED_LONG_FACTORY_RESET) { // factory reset if pressed > 10 seconds
|
||||
WLED_FS.format();
|
||||
#ifdef WLED_ADD_EEPROM_SUPPORT
|
||||
clearEEPROM();
|
||||
#endif
|
||||
doReboot = true;
|
||||
} else {
|
||||
WLED::instance().initAP(true);
|
||||
|
@ -90,6 +90,44 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
CJSON(strip.cctBlending, hw_led[F("cb")]);
|
||||
Bus::setCCTBlend(strip.cctBlending);
|
||||
strip.setTargetFps(hw_led["fps"]); //NOP if 0, default 42 FPS
|
||||
CJSON(strip.useLedsArray, hw_led[F("ld")]);
|
||||
|
||||
#ifndef WLED_DISABLE_2D
|
||||
// 2D Matrix Settings
|
||||
JsonObject matrix = hw_led[F("matrix")];
|
||||
if (!matrix.isNull()) {
|
||||
strip.isMatrix = true;
|
||||
CJSON(strip.panelH, matrix[F("ph")]);
|
||||
CJSON(strip.panelW, matrix[F("pw")]);
|
||||
CJSON(strip.hPanels, matrix[F("mph")]);
|
||||
CJSON(strip.vPanels, matrix[F("mpv")]);
|
||||
CJSON(strip.matrix.bottomStart, matrix[F("pb")]);
|
||||
CJSON(strip.matrix.rightStart, matrix[F("pr")]);
|
||||
CJSON(strip.matrix.vertical, matrix[F("pv")]);
|
||||
CJSON(strip.matrix.serpentine, matrix[F("ps")]);
|
||||
|
||||
JsonArray panels = matrix[F("panels")];
|
||||
uint8_t s = 0;
|
||||
if (!panels.isNull()) {
|
||||
for (JsonObject pnl : panels) {
|
||||
CJSON(strip.panel[s].bottomStart, pnl["b"]);
|
||||
CJSON(strip.panel[s].rightStart, pnl["r"]);
|
||||
CJSON(strip.panel[s].vertical, pnl["v"]);
|
||||
CJSON(strip.panel[s].serpentine, pnl["s"]);
|
||||
if (++s >= WLED_MAX_PANELS) break; // max panels reached
|
||||
}
|
||||
}
|
||||
// clear remaining panels
|
||||
for (; s<WLED_MAX_PANELS; s++) {
|
||||
strip.panel[s].bottomStart = 0;
|
||||
strip.panel[s].rightStart = 0;
|
||||
strip.panel[s].vertical = 0;
|
||||
strip.panel[s].serpentine = 0;
|
||||
}
|
||||
|
||||
strip.setUpMatrix();
|
||||
}
|
||||
#endif
|
||||
|
||||
JsonArray ins = hw_led["ins"];
|
||||
|
||||
@ -229,6 +267,30 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
if (serialBaud < 96 || serialBaud > 15000) serialBaud = 1152;
|
||||
updateBaudRate(serialBaud *100);
|
||||
|
||||
JsonArray hw_if_i2c = hw[F("if")][F("i2c-pin")];
|
||||
CJSON(i2c_sda, hw_if_i2c[0]);
|
||||
CJSON(i2c_scl, hw_if_i2c[1]);
|
||||
PinManagerPinType i2c[2] = { { i2c_sda, true }, { i2c_scl, true } };
|
||||
if (i2c_scl >= 0 && i2c_sda >= 0 && pinManager.allocateMultiplePins(i2c, 2, PinOwner::HW_I2C)) {
|
||||
#ifdef ESP32
|
||||
Wire.setPins(i2c_sda, i2c_scl); // this will fail if Wire is initilised (Wire.begin() called prior)
|
||||
#endif
|
||||
Wire.begin();
|
||||
} else {
|
||||
i2c_sda = -1;
|
||||
i2c_scl = -1;
|
||||
}
|
||||
JsonArray hw_if_spi = hw[F("if")][F("spi-pin")];
|
||||
CJSON(spi_mosi, hw_if_spi[0]);
|
||||
CJSON(spi_sclk, hw_if_spi[1]);
|
||||
PinManagerPinType spi[3] = { { spi_mosi, true }, { spi_sclk, true } };
|
||||
if (spi_mosi >= 0 && spi_sclk >= 0 && pinManager.allocateMultiplePins(spi, 2, PinOwner::HW_SPI)) {
|
||||
// do not initialise bus here
|
||||
} else {
|
||||
spi_mosi = -1;
|
||||
spi_sclk = -1;
|
||||
}
|
||||
|
||||
//int hw_status_pin = hw[F("status")]["pin"]; // -1
|
||||
|
||||
JsonObject light = doc[F("light")];
|
||||
@ -470,7 +532,9 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
void deserializeConfigFromFS() {
|
||||
bool success = deserializeConfigSec();
|
||||
if (!success) { //if file does not exist, try reading from EEPROM
|
||||
#ifdef WLED_ADD_EEPROM_SUPPORT
|
||||
deEEPSettings();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
@ -480,7 +544,9 @@ void deserializeConfigFromFS() {
|
||||
|
||||
success = readObjectFromFile("/cfg.json", nullptr, &doc);
|
||||
if (!success) { //if file does not exist, try reading from EEPROM
|
||||
#ifdef WLED_ADD_EEPROM_SUPPORT
|
||||
deEEPSettings();
|
||||
#endif
|
||||
releaseJSONBufferLock();
|
||||
return;
|
||||
}
|
||||
@ -584,6 +650,31 @@ void serializeConfig() {
|
||||
hw_led[F("cb")] = strip.cctBlending;
|
||||
hw_led["fps"] = strip.getTargetFps();
|
||||
hw_led[F("rgbwm")] = Bus::getAutoWhiteMode(); // global override
|
||||
hw_led[F("ld")] = strip.useLedsArray;
|
||||
|
||||
#ifndef WLED_DISABLE_2D
|
||||
// 2D Matrix Settings
|
||||
if (strip.isMatrix) {
|
||||
JsonObject matrix = hw_led.createNestedObject(F("matrix"));
|
||||
matrix[F("ph")] = strip.panelH;
|
||||
matrix[F("pw")] = strip.panelW;
|
||||
matrix[F("mph")] = strip.hPanels;
|
||||
matrix[F("mpv")] = strip.vPanels;
|
||||
matrix[F("pb")] = strip.matrix.bottomStart;
|
||||
matrix[F("pr")] = strip.matrix.rightStart;
|
||||
matrix[F("pv")] = strip.matrix.vertical;
|
||||
matrix[F("ps")] = strip.matrix.serpentine;
|
||||
|
||||
JsonArray panels = matrix.createNestedArray(F("panels"));
|
||||
for (uint8_t i=0; i<strip.hPanels*strip.vPanels; i++) {
|
||||
JsonObject pnl = panels.createNestedObject();
|
||||
pnl["b"] = strip.panel[i].bottomStart;
|
||||
pnl["r"] = strip.panel[i].rightStart;
|
||||
pnl["v"] = strip.panel[i].vertical;
|
||||
pnl["s"] = strip.panel[i].serpentine;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
JsonArray hw_led_ins = hw_led.createNestedArray("ins");
|
||||
|
||||
@ -648,6 +739,14 @@ void serializeConfig() {
|
||||
|
||||
hw[F("baud")] = serialBaud;
|
||||
|
||||
JsonObject hw_if = hw.createNestedObject(F("if"));
|
||||
JsonArray hw_if_i2c = hw_if.createNestedArray("i2c-pin");
|
||||
hw_if_i2c.add(i2c_sda);
|
||||
hw_if_i2c.add(i2c_scl);
|
||||
JsonArray hw_if_spi = hw_if.createNestedArray("spi-pin");
|
||||
hw_if_spi.add(spi_mosi);
|
||||
hw_if_spi.add(spi_sclk);
|
||||
|
||||
//JsonObject hw_status = hw.createNestedObject("status");
|
||||
//hw_status["pin"] = -1;
|
||||
|
||||
|
@ -1,12 +1,57 @@
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* Color conversion methods
|
||||
* Color conversion & utility methods
|
||||
*/
|
||||
|
||||
/*
|
||||
* color blend function
|
||||
*/
|
||||
uint32_t color_blend(uint32_t color1, uint32_t color2, uint16_t blend, bool b16) {
|
||||
if(blend == 0) return color1;
|
||||
uint16_t blendmax = b16 ? 0xFFFF : 0xFF;
|
||||
if(blend == blendmax) return color2;
|
||||
uint8_t shift = b16 ? 16 : 8;
|
||||
|
||||
uint32_t w1 = W(color1);
|
||||
uint32_t r1 = R(color1);
|
||||
uint32_t g1 = G(color1);
|
||||
uint32_t b1 = B(color1);
|
||||
|
||||
uint32_t w2 = W(color2);
|
||||
uint32_t r2 = R(color2);
|
||||
uint32_t g2 = G(color2);
|
||||
uint32_t b2 = B(color2);
|
||||
|
||||
uint32_t w3 = ((w2 * blend) + (w1 * (blendmax - blend))) >> shift;
|
||||
uint32_t r3 = ((r2 * blend) + (r1 * (blendmax - blend))) >> shift;
|
||||
uint32_t g3 = ((g2 * blend) + (g1 * (blendmax - blend))) >> shift;
|
||||
uint32_t b3 = ((b2 * blend) + (b1 * (blendmax - blend))) >> shift;
|
||||
|
||||
return RGBW32(r3, g3, b3, w3);
|
||||
}
|
||||
|
||||
/*
|
||||
* color add function that preserves ratio
|
||||
* idea: https://github.com/Aircoookie/WLED/pull/2465 by https://github.com/Proto-molecule
|
||||
*/
|
||||
uint32_t color_add(uint32_t c1, uint32_t c2)
|
||||
{
|
||||
uint32_t r = R(c1) + R(c2);
|
||||
uint32_t g = G(c1) + G(c2);
|
||||
uint32_t b = B(c1) + B(c2);
|
||||
uint32_t w = W(c1) + W(c2);
|
||||
uint16_t max = r;
|
||||
if (g > max) max = g;
|
||||
if (b > max) max = b;
|
||||
if (w > max) max = w;
|
||||
if (max < 256) return RGBW32(r, g, b, w);
|
||||
else return RGBW32(r * 255 / max, g * 255 / max, b * 255 / max, w * 255 / max);
|
||||
}
|
||||
|
||||
void setRandomColor(byte* rgb)
|
||||
{
|
||||
lastRandomIndex = strip.get_random_wheel_index(lastRandomIndex);
|
||||
lastRandomIndex = strip.getMainSegment().get_random_wheel_index(lastRandomIndex);
|
||||
colorHStoRGB(lastRandomIndex*256,255,rgb);
|
||||
}
|
||||
|
||||
@ -274,3 +319,53 @@ uint16_t approximateKelvinFromRGB(uint32_t rgb) {
|
||||
return (k > 10091) ? 10091 : k;
|
||||
}
|
||||
}
|
||||
|
||||
//gamma 2.8 lookup table used for color correction
|
||||
static byte gammaT[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5,
|
||||
5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10,
|
||||
10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16,
|
||||
17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25,
|
||||
25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36,
|
||||
37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50,
|
||||
51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68,
|
||||
69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89,
|
||||
90, 92, 93, 95, 96, 98, 99,101,102,104,105,107,109,110,112,114,
|
||||
115,117,119,120,122,124,126,127,129,131,133,135,137,138,140,142,
|
||||
144,146,148,150,152,154,156,158,160,162,164,167,169,171,173,175,
|
||||
177,180,182,184,186,189,191,193,196,198,200,203,205,208,210,213,
|
||||
215,218,220,223,225,228,231,233,236,239,241,244,247,249,252,255 };
|
||||
|
||||
uint8_t gamma8_cal(uint8_t b, float gamma)
|
||||
{
|
||||
return (int)(powf((float)b / 255.0f, gamma) * 255.0f + 0.5f);
|
||||
}
|
||||
|
||||
void calcGammaTable(float gamma)
|
||||
{
|
||||
for (uint16_t i = 0; i < 256; i++) {
|
||||
gammaT[i] = gamma8_cal(i, gamma);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t gamma8(uint8_t b)
|
||||
{
|
||||
return gammaT[b];
|
||||
}
|
||||
|
||||
uint32_t gamma32(uint32_t color)
|
||||
{
|
||||
//if (!strip.gammaCorrectCol) return color;
|
||||
uint8_t w = W(color);
|
||||
uint8_t r = R(color);
|
||||
uint8_t g = G(color);
|
||||
uint8_t b = B(color);
|
||||
w = gammaT[w];
|
||||
r = gammaT[r];
|
||||
g = gammaT[g];
|
||||
b = gammaT[b];
|
||||
return RGBW32(r, g, b, w);
|
||||
}
|
||||
|
4099
wled00/console_font_5x12.h
Normal file
4099
wled00/console_font_5x12.h
Normal file
File diff suppressed because it is too large
Load Diff
3075
wled00/console_font_5x8.h
Normal file
3075
wled00/console_font_5x8.h
Normal file
File diff suppressed because it is too large
Load Diff
3075
wled00/console_font_6x8.h
Normal file
3075
wled00/console_font_6x8.h
Normal file
File diff suppressed because it is too large
Load Diff
3331
wled00/console_font_7x9.h
Normal file
3331
wled00/console_font_7x9.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -5,6 +5,8 @@
|
||||
* Readability defines and their associated numerical values + compile-time constants
|
||||
*/
|
||||
|
||||
#define GRADIENT_PALETTE_COUNT 58
|
||||
|
||||
//Defaults
|
||||
#define DEFAULT_CLIENT_SSID "Your_Network"
|
||||
#define DEFAULT_AP_PASS "wled1234"
|
||||
@ -77,6 +79,7 @@
|
||||
#define USERMOD_ID_MY9291 28 //Usermod "usermod_MY9291.h"
|
||||
#define USERMOD_ID_SI7021_MQTT_HA 29 //Usermod "usermod_si7021_mqtt_ha.h"
|
||||
#define USERMOD_ID_BME280 30 //Usermod "usermod_bme280.h
|
||||
#define USERMOD_ID_AUDIOREACTIVE 31 //Usermod "audioreactive.h"
|
||||
|
||||
//Access point behavior
|
||||
#define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot
|
||||
@ -151,6 +154,7 @@
|
||||
#define TYPE_WS2812_RGB 22
|
||||
#define TYPE_GS8608 23 //same driver as WS2812, but will require signal 2x per second (else displays test pattern)
|
||||
#define TYPE_WS2811_400KHZ 24 //half-speed WS2812 protocol, used by very old WS2811 units
|
||||
#define TYPE_TM1829 25
|
||||
#define TYPE_SK6812_RGBW 30
|
||||
#define TYPE_TM1814 31
|
||||
//"Analog" types (PWM) (32-47)
|
||||
@ -224,7 +228,11 @@
|
||||
#define SEG_OPTION_MIRROR 3 //Indicates that the effect will be mirrored within the segment
|
||||
#define SEG_OPTION_NONUNITY 4 //Indicates that the effect does not use FRAMETIME or needs getPixelColor
|
||||
#define SEG_OPTION_FREEZE 5 //Segment contents will not be refreshed
|
||||
#define SEG_OPTION_RESET 6 //Segment runtime requires reset
|
||||
#define SEG_OPTION_TRANSITIONAL 7
|
||||
#define SEG_OPTION_REVERSED_Y 8
|
||||
#define SEG_OPTION_MIRROR_Y 9
|
||||
#define SEG_OPTION_TRANSPOSED 10
|
||||
|
||||
//Segment differs return byte
|
||||
#define SEG_DIFFERS_BRI 0x01
|
||||
@ -241,6 +249,7 @@
|
||||
// WLED Error modes
|
||||
#define ERR_NONE 0 // All good :)
|
||||
#define ERR_EEP_COMMIT 2 // Could not commit to EEPROM (wrong flash layout?)
|
||||
#define ERR_NOBUF 3 // JSON buffer was not released in time, request cannot be handled at this time
|
||||
#define ERR_JSON 9 // JSON parsing failed (input too large?)
|
||||
#define ERR_FS_BEGIN 10 // Could not init filesystem (no partition?)
|
||||
#define ERR_FS_QUOTA 11 // The FS is full or the maximum file size is reached
|
||||
@ -356,4 +365,37 @@
|
||||
|
||||
#define INTERFACE_UPDATE_COOLDOWN 2000 //time in ms to wait between websockets, alexa, and MQTT updates
|
||||
|
||||
#if defined(ESP8266) && defined(HW_PIN_SCL)
|
||||
#undef HW_PIN_SCL
|
||||
#endif
|
||||
#if defined(ESP8266) && defined(HW_PIN_SDA)
|
||||
#undef HW_PIN_SDA
|
||||
#endif
|
||||
#ifndef HW_PIN_SCL
|
||||
#define HW_PIN_SCL SCL
|
||||
#endif
|
||||
#ifndef HW_PIN_SDA
|
||||
#define HW_PIN_SDA SDA
|
||||
#endif
|
||||
|
||||
#if defined(ESP8266) && defined(HW_PIN_CLOCKSPI)
|
||||
#undef HW_PIN_CLOCKSPI
|
||||
#endif
|
||||
#if defined(ESP8266) && defined(HW_PIN_DATASPI)
|
||||
#undef HW_PIN_DATASPI
|
||||
#endif
|
||||
#if defined(ESP8266) && defined(HW_PIN_CSSPI)
|
||||
#undef HW_PIN_CSSPI
|
||||
#endif
|
||||
// defaults for VSPI
|
||||
#ifndef HW_PIN_CLOCKSPI
|
||||
#define HW_PIN_CLOCKSPI SCK
|
||||
#endif
|
||||
#ifndef HW_PIN_DATASPI
|
||||
#define HW_PIN_DATASPI MOSI
|
||||
#endif
|
||||
#ifndef HW_PIN_CSSPI
|
||||
#define HW_PIN_CSSPI SS
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -123,11 +123,19 @@ button {
|
||||
.icons {
|
||||
font-family: 'WIcons';
|
||||
font-style: normal;
|
||||
font-size: 24px;
|
||||
line-height: 1;
|
||||
font-size: 24px !important;
|
||||
line-height: 1 !important;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.icons.on {
|
||||
color: var(--c-g);
|
||||
}
|
||||
|
||||
.icons.off {
|
||||
color: var(--c-6);
|
||||
}
|
||||
|
||||
.top .icons, .bot .icons {
|
||||
margin: -2px 0 4px 0;
|
||||
}
|
||||
@ -185,7 +193,7 @@ button {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
left: 12px;
|
||||
pointer-events: none;
|
||||
/*pointer-events: none;*/
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
@ -225,6 +233,17 @@ button {
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
#liveview2D {
|
||||
height: 90%;
|
||||
display: none;
|
||||
width: 90%;
|
||||
border: 0px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%,-50%);
|
||||
}
|
||||
|
||||
.tab {
|
||||
background-color: transparent;
|
||||
color: var(--c-d);
|
||||
@ -359,27 +378,85 @@ button {
|
||||
bottom: 5px;
|
||||
}
|
||||
|
||||
#fx {
|
||||
height: calc(100% - 121px);
|
||||
overflow-y: scroll;
|
||||
padding-left: 6px; /* compensate scroll bar */
|
||||
}
|
||||
|
||||
#sliders {
|
||||
width: 310px;
|
||||
width: 300px;
|
||||
margin: 0 auto;
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
#sliders .labels {
|
||||
padding-top: 3px;
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
#slider0, #slider1, #slider2, #slider3, #slider4 {
|
||||
background: var(--c-2);
|
||||
max-width: 310px;
|
||||
.slider {
|
||||
background-color: var(--c-2);
|
||||
max-width: 300px;
|
||||
min-width: 280px;
|
||||
margin: 0 auto 5px;
|
||||
border-radius: 15px;
|
||||
margin: 0 auto; /* add 5px; if you want some vertical space but looks ugly */
|
||||
border-radius: 24px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.filter, .option {
|
||||
background-color: var(--c-4);
|
||||
border-radius: 26px;
|
||||
height: 26px;
|
||||
margin: 0 auto; /* add 4-8px if you want space at the bottom */
|
||||
padding: 4px 2px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
opacity: 1;
|
||||
transition: opacity 0.5s linear, height 0.5s, transform 0.5s;
|
||||
transform: scaleY(1);
|
||||
}
|
||||
|
||||
.option {
|
||||
z-index: unset;
|
||||
}
|
||||
|
||||
/* Tooltip text */
|
||||
.slider .tooltiptext, .option .tooltiptext {
|
||||
visibility: hidden;
|
||||
background-color: var(--c-5);
|
||||
/*border: 2px solid var(--c-2);*/
|
||||
box-shadow: 4px 4px 10px 4px var(--c-1);
|
||||
color: var(--c-f);
|
||||
text-align: center;
|
||||
padding: 5px 10px;
|
||||
border-radius: 6px;
|
||||
|
||||
/* Position the tooltip text */
|
||||
width: 160px;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
bottom: 100%;
|
||||
left: 50%;
|
||||
margin-left: -92px;
|
||||
|
||||
/* Fade in tooltip */
|
||||
opacity: 0;
|
||||
transition: opacity 0.75s;
|
||||
}
|
||||
.option .tooltiptext {
|
||||
bottom: 120%;
|
||||
}
|
||||
/* Tooltip arrow */
|
||||
.slider .tooltiptext::after, .option .tooltiptext::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 50%;
|
||||
margin-left: -5px;
|
||||
border-width: 5px;
|
||||
border-style: solid;
|
||||
border-color: var(--c-5) transparent transparent transparent;
|
||||
}
|
||||
/* Show the tooltip text when you mouse over the tooltip container */
|
||||
.slider:hover .tooltiptext, .option .check:hover .tooltiptext {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
#pql, .edit-icon {
|
||||
@ -389,6 +466,13 @@ button {
|
||||
.hide {
|
||||
display: none !important;
|
||||
}
|
||||
.fade {
|
||||
visibility: hidden; /* hide it */
|
||||
opacity: 0; /* make it transparent */
|
||||
transform: scaleY(0); /* shrink content */
|
||||
height: 0px; /* force other elements to move */
|
||||
padding: 0; /* remove empty space */
|
||||
}
|
||||
|
||||
.first {
|
||||
margin-top: 10px;
|
||||
@ -473,13 +557,14 @@ button {
|
||||
z-index: -2;
|
||||
}
|
||||
|
||||
#imgw {
|
||||
display: inline-block;
|
||||
margin: 8px;
|
||||
#info .slider {
|
||||
max-width: 200px;
|
||||
min-width: 145px;
|
||||
float: right;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#kv, #kn {
|
||||
display: inline-block;
|
||||
#info .sliderwrap {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
#info table, #nodes table {
|
||||
@ -502,6 +587,15 @@ button {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
#imgw {
|
||||
/*display: inline-block;*/
|
||||
margin: 8px auto;
|
||||
}
|
||||
/*
|
||||
#kv, #kn {
|
||||
display: inline-block;
|
||||
}
|
||||
*/
|
||||
#lv {
|
||||
max-width: 600px;
|
||||
display: inline-block;
|
||||
@ -708,6 +802,9 @@ input[type=range]::-moz-range-thumb {
|
||||
#putil .btn-xs {
|
||||
margin: 0;
|
||||
}
|
||||
#info .btn-xs {
|
||||
border: 1px solid var(--c-4);
|
||||
}
|
||||
|
||||
#putil .btn-s {
|
||||
width: 135px;
|
||||
@ -756,19 +853,22 @@ input[type=range]::-moz-range-thumb {
|
||||
}
|
||||
|
||||
select {
|
||||
padding: 4px;
|
||||
padding: 4px 8px;
|
||||
margin: 0;
|
||||
font-size: 19px;
|
||||
background-color: var(--c-3);
|
||||
color: var(--c-d);
|
||||
cursor: pointer;
|
||||
border: 1px solid var(--c-2);
|
||||
border-radius: 5px;
|
||||
border: 0 solid var(--c-2);
|
||||
border-radius: 20px;
|
||||
transition-duration: 0.5s;
|
||||
-webkit-backface-visibility: hidden;
|
||||
-webkit-transform:translate3d(0,0,0);
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
backface-visibility: hidden;
|
||||
transform:translate3d(0,0,0);
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
#tt {
|
||||
text-align: center;
|
||||
@ -776,16 +876,26 @@ select {
|
||||
.cl {
|
||||
background-color: #000;
|
||||
}
|
||||
.sel-p {
|
||||
margin: 5px 0 10px;
|
||||
width: 5em;
|
||||
}
|
||||
.sel-pl {
|
||||
select.sel-p, select.sel-pl, select.sel-ple {
|
||||
margin: 5px 0;
|
||||
width: 100%;
|
||||
background-position: 141px 16px;
|
||||
height: 40px;
|
||||
}
|
||||
.sel-ple {
|
||||
width: 100%;
|
||||
div.sel-p {
|
||||
position: relative;
|
||||
}
|
||||
div.sel-p:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 22px;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 8px solid transparent;
|
||||
border-right: 8px solid transparent;
|
||||
border-top: 8px solid var(--c-f);
|
||||
}
|
||||
select.sel-ple {
|
||||
text-align: center;
|
||||
}
|
||||
option {
|
||||
@ -869,10 +979,18 @@ textarea {
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
text-overflow: clip;
|
||||
overflow: clip;
|
||||
text-overflow: ellipsis;
|
||||
line-height: 24px;
|
||||
padding: 8px 0;
|
||||
padding: 8px 24px;
|
||||
max-width: 170px;
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.segname .flr, .pname .flr {
|
||||
transform: rotate(0deg);
|
||||
right: -6px;
|
||||
}
|
||||
|
||||
/* segment power wrapper */
|
||||
@ -907,19 +1025,24 @@ textarea {
|
||||
}
|
||||
|
||||
.xxs {
|
||||
border: 2px solid var(--c-e) !important;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
margin: 5px;
|
||||
/*box-shadow: 0 0 0 2px #fff;*/
|
||||
}
|
||||
|
||||
.xxs-w {
|
||||
border-width: 5px !important;
|
||||
margin: 2px;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
/*box-shadow: 0 0 0 5px #fff;*/
|
||||
}
|
||||
|
||||
#csl .xxs {
|
||||
border: 2px solid var(--c-d) !important;
|
||||
/*box-shadow: 0 0 0 2px var(--c-d);*/
|
||||
}
|
||||
#csl .xxs-w {
|
||||
border-width: 5px !important;
|
||||
/*box-shadow: 0 0 0 5px var(--c-d);*/
|
||||
}
|
||||
|
||||
.qcs, #namelabel {
|
||||
@ -948,11 +1071,12 @@ textarea {
|
||||
}
|
||||
|
||||
.frz {
|
||||
left: 36px;
|
||||
left: 32px;
|
||||
position: absolute;
|
||||
top: -3px;
|
||||
cursor: pointer;
|
||||
padding: 8px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.expanded .frz {
|
||||
@ -972,6 +1096,11 @@ textarea {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
TD .revchkl {
|
||||
padding: 0 0 0 32px;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.check input, .radio input {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
@ -1041,6 +1170,10 @@ textarea {
|
||||
background: var(--c-f);
|
||||
}
|
||||
|
||||
TD .checkmark, TD .radiomark {
|
||||
top: -6px;
|
||||
}
|
||||
|
||||
.h {
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
@ -1068,16 +1201,32 @@ textarea {
|
||||
top: auto !important; /* prevent sticky */
|
||||
bottom: auto !important;
|
||||
}
|
||||
/*
|
||||
.seg:last-child {
|
||||
margin: 0;
|
||||
}
|
||||
*/
|
||||
/* checkmark labels */
|
||||
.seg .schkl {
|
||||
position: absolute;
|
||||
top: 7px;
|
||||
left: 9px;
|
||||
}
|
||||
/* checkmark labels */
|
||||
.filter .fchkl, .option .ochkl {
|
||||
display: inline-block;
|
||||
min-width: 0.7em;
|
||||
padding: 1px 4px 4px 32px;
|
||||
text-align: left;
|
||||
line-height: 24px;
|
||||
vertical-align: middle;
|
||||
-webkit-filter: grayscale(100%); /* Safari 6.0 - 9.0 */
|
||||
filter: grayscale(100%);
|
||||
}
|
||||
|
||||
.lbl-s {
|
||||
display: inline-block;
|
||||
/* margin: 10px 4px 0 0; */
|
||||
margin-top: 6px;
|
||||
font-size: 13px;
|
||||
width: 48%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* list wrapper */
|
||||
.list {
|
||||
@ -1132,6 +1281,7 @@ textarea {
|
||||
.lstI.sticky,
|
||||
.lstI.selected {
|
||||
z-index: 1;
|
||||
box-shadow: 0px 0px 10px 4px var(--c-1);
|
||||
}
|
||||
|
||||
#pcont .selected:not([class*="expanded"]) {
|
||||
@ -1164,6 +1314,9 @@ textarea {
|
||||
/* list item name (for sorting) */
|
||||
.lstIname {
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
-webkit-filter: grayscale(100%); /* Safari 6.0 - 9.0 */
|
||||
filter: grayscale(100%);
|
||||
}
|
||||
|
||||
/* list item palette preview */
|
||||
@ -1193,6 +1346,8 @@ textarea {
|
||||
border-radius: 21px;
|
||||
background: var(--c-2);
|
||||
border: 1px solid var(--c-3);
|
||||
-webkit-filter: grayscale(100%); /* Safari 6.0 - 9.0 */
|
||||
filter: grayscale(100%);
|
||||
}
|
||||
|
||||
.fnd input[type="text"]:focus {
|
||||
@ -1293,7 +1448,7 @@ textarea {
|
||||
width: 145px;
|
||||
}
|
||||
#info div, #nodes div {
|
||||
width: 320px;
|
||||
max-width: 320px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,9 +46,9 @@
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
setTimeout(()=>{h.appendChild(l)},50);
|
||||
setTimeout(()=>{h.appendChild(l)},100);
|
||||
});
|
||||
setTimeout(()=>{h.appendChild(l)},50);
|
||||
setTimeout(()=>{h.appendChild(l)},100);
|
||||
</script>
|
||||
<link rel="stylesheet" href="index.css">
|
||||
</head>
|
||||
@ -200,9 +200,9 @@
|
||||
<div id="fx">
|
||||
<p class="labels hd" id="modeLabel">Effect mode</p>
|
||||
<div class="staytop fnd" id="fxFind">
|
||||
<input type="text" placeholder="Search" oninput="search(this,'fxlist')" onfocus="search(this,'fxlist')" />
|
||||
<input type="text" placeholder="Search" oninput="search(this,'fxlist')" onfocus="search(this,'fxlist');gId('filters').classList.add('fade');" onblur="gId('filters').classList.remove('fade')"/>
|
||||
<i class="icons clear-icon" onclick="clean(this);"></i>
|
||||
<i class="icons search-icon"></i>
|
||||
<i class="icons search-icon" onclick="gId('filters').classList.toggle('hide');" style="cursor:pointer;"></i>
|
||||
</div>
|
||||
<div id="fxlist" class="list">
|
||||
<div class="lstI">
|
||||
@ -217,50 +217,86 @@
|
||||
</div>
|
||||
</div>
|
||||
<div id="sliders">
|
||||
<p class="labels hd" id="sliderLabel0">Effect speed</p>
|
||||
<div id="slider0">
|
||||
<div id="filters" class="filter">
|
||||
<label id="filterPal" class="check fchkl">🎨
|
||||
<input type="checkbox" data-flt="🎨" onchange="filterFx(this)">
|
||||
<span class="checkmark"></span>
|
||||
</label>
|
||||
<label id="filter1D" class="check fchkl">⋮
|
||||
<input type="checkbox" data-flt="⋮" onchange="filterFx(this)">
|
||||
<span class="checkmark"></span>
|
||||
</label>
|
||||
<label id="filter2D" class="check fchkl">▦
|
||||
<input type="checkbox" data-flt="▦" onchange="filterFx(this)">
|
||||
<span class="checkmark"></span>
|
||||
</label>
|
||||
<label id="filterVol" class="check fchkl">♪
|
||||
<input type="checkbox" data-flt="♪" onchange="filterFx(this)">
|
||||
<span class="checkmark"></span>
|
||||
</label>
|
||||
<label id="filterFreq" class="check fchkl">♫
|
||||
<input type="checkbox" data-flt="♫" onchange="filterFx(this)">
|
||||
<span class="checkmark"></span>
|
||||
</label>
|
||||
</div>
|
||||
<div id="slider0" class="slider">
|
||||
<i class="icons slider-icon" style="cursor: pointer;" onclick="tglFreeze()"></i>
|
||||
<div class="sliderwrap il">
|
||||
<input id="sliderSpeed" class="noslide" onchange="setSpeed()" oninput="updateTrail(this)" max="255" min="0" type="range" value="128" />
|
||||
<div class="sliderdisplay"></div>
|
||||
</div>
|
||||
<output class="sliderbubble"></output>
|
||||
<span id="sliderLabel0" class="tooltiptext">Effect speed</span>
|
||||
</div>
|
||||
<p class="labels hd" id="sliderLabel1">Effect intensity</p>
|
||||
<div id="slider1">
|
||||
<div id="slider1" class="slider">
|
||||
<i class="icons slider-icon" style="cursor: pointer;" onclick="tglLabels()"></i>
|
||||
<div class="sliderwrap il">
|
||||
<input id="sliderIntensity" class="noslide" onchange="setIntensity()" oninput="updateTrail(this)" max="255" min="0" type="range" value="128" />
|
||||
<div class="sliderdisplay"></div>
|
||||
</div>
|
||||
<output class="sliderbubble"></output>
|
||||
<span class="tooltiptext" id="sliderLabel1">Effect intensity</span>
|
||||
</div>
|
||||
<p class="labels hd" id="sliderLabel2">Custom 1</p>
|
||||
<div id="slider2" class="hide">
|
||||
<div id="slider2" class="slider hide">
|
||||
<i class="icons slider-icon"></i>
|
||||
<div class="sliderwrap il">
|
||||
<input id="sliderC1" class="noslide" onchange="setCustom(1)" oninput="updateTrail(this)" max="255" min="0" type="range" value="6" />
|
||||
<input id="sliderC1" class="noslide" onchange="setCustom(1)" oninput="updateTrail(this)" max="255" min="0" type="range" value="0" />
|
||||
<div class="sliderdisplay"></div>
|
||||
</div>
|
||||
<output class="sliderbubble"></output>
|
||||
<span class="tooltiptext" id="sliderLabel2">Custom 1</span>
|
||||
</div>
|
||||
<p class="labels hd" id="sliderLabel3">Custom 2</p>
|
||||
<div id="slider3" class="hide">
|
||||
<div id="slider3" class="slider hide">
|
||||
<i class="icons slider-icon"></i>
|
||||
<div class="sliderwrap il">
|
||||
<input id="sliderC2" class="noslide" onchange="setCustom(2)" oninput="updateTrail(this)" max="255" min="0" type="range" value="6" />
|
||||
<input id="sliderC2" class="noslide" onchange="setCustom(2)" oninput="updateTrail(this)" max="255" min="0" type="range" value="0" />
|
||||
<div class="sliderdisplay"></div>
|
||||
</div>
|
||||
<output class="sliderbubble"></output>
|
||||
<span class="tooltiptext" id="sliderLabel3">Custom 2</span>
|
||||
</div>
|
||||
<p class="labels hd" id="sliderLabel4">Custom 3</p>
|
||||
<div id="slider4" class="hide">
|
||||
<div id="slider4" class="slider hide">
|
||||
<i class="icons slider-icon"></i>
|
||||
<div class="sliderwrap il">
|
||||
<input id="sliderC3" class="noslide" onchange="setCustom(3)" oninput="updateTrail(this)" max="255" min="0" type="range" value="6" />
|
||||
<input id="sliderC3" class="noslide" onchange="setCustom(3)" oninput="updateTrail(this)" max="31" min="0" type="range" value="0" />
|
||||
<div class="sliderdisplay"></div>
|
||||
</div>
|
||||
<output class="sliderbubble"></output>
|
||||
<span class="tooltiptext" id="sliderLabel4">Custom 3</span>
|
||||
</div>
|
||||
<div id="fxopt" class="option fade">
|
||||
<label id="opt0" class="check ochkl hide"><i class="icons"></i><span class="tooltiptext" id="optLabel0">Check 1</span>
|
||||
<input type="checkbox" onchange="setOption(1, this.checked)">
|
||||
<span class="checkmark"></span>
|
||||
</label>
|
||||
<label id="opt1" class="check ochkl hide"><i class="icons"></i><span class="tooltiptext" id="optLabel1">Check 2</span>
|
||||
<input type="checkbox" onchange="setOption(2, this.checked)">
|
||||
<span class="checkmark"></span>
|
||||
</label>
|
||||
<label id="opt2" class="check ochkl hide"><i class="icons"></i><span class="tooltiptext" id="optLabel2">Check 3</span>
|
||||
<input type="checkbox" onchange="setOption(3, this.checked)">
|
||||
<span class="checkmark"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -308,7 +344,7 @@
|
||||
<button class="btn btn-xs close" onclick="toggleInfo()"><i class="icons rot45"></i></button>
|
||||
<div id="imgw">
|
||||
<img class="wi" alt="" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB0AAAAFCAYAAAC5Fuf5AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABbSURBVChTlY9bDoAwDMNW7n9nwCipytQN4Z8tbrTHmDmF4oPzyldwRqp1SSdnV/NuZuzqerAByxXznBw3igkeFEfXyUuhK/yFM0CxJfyqXZEOc6/Sr9/bf7uIC5Nwd7orMvAPAAAAAElFTkSuQmCC" />
|
||||
</div><br>
|
||||
</div>
|
||||
<div id="kv">Loading...</div><br>
|
||||
<div>
|
||||
<button class="btn infobtn" onclick="requestJson()">Refresh</button>
|
||||
@ -329,6 +365,10 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="mliveview2D" class="modal">
|
||||
<div id="kliveview2D" style="width:100%; height:100%">Loading...</div><br>
|
||||
</div>
|
||||
|
||||
<div id="rover" class="modal">
|
||||
<i class="icons huge"></i><br>
|
||||
<div id="lv">?</div><br><br>
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -19,49 +19,43 @@
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="canv" />
|
||||
<div id="canv"></div>
|
||||
<script>
|
||||
function updatePreview(leds) {
|
||||
var str = "linear-gradient(90deg,";
|
||||
var len = leds.length;
|
||||
for (i = 2; i < len; i+=3) {
|
||||
str += `rgb(${leds[i]},${leds[i+1]},${leds[i+2]})`;
|
||||
if (i < len -3) str += ","
|
||||
}
|
||||
str += ")";
|
||||
document.getElementById("canv").style.background = str;
|
||||
}
|
||||
|
||||
function getLiveJson(e) {
|
||||
try {
|
||||
if (toString.call(e.data) === '[object ArrayBuffer]') {
|
||||
let leds = new Uint8Array(event.data);
|
||||
if (leds[0] != 76) return; //'L'
|
||||
updatePreview(leds);
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
console.error("Peek WS error:",err);
|
||||
}
|
||||
}
|
||||
|
||||
var ws;
|
||||
try {
|
||||
ws = top.window.ws;
|
||||
} catch (e) {}
|
||||
if (ws && ws.readyState === WebSocket.OPEN) {
|
||||
console.info("Peek uses top WS");
|
||||
//console.info("Peek uses top WS");
|
||||
ws.send("{'lv':true}");
|
||||
} else {
|
||||
console.info("Peek WS opening");
|
||||
ws = new WebSocket((window.location.protocol == "https:"?"wss":"ws")+"://"+document.location.host+"/ws");
|
||||
ws.onopen = function () {
|
||||
console.info("Peek WS open");
|
||||
//console.info("Peek WS open");
|
||||
ws.send("{'lv':true}");
|
||||
}
|
||||
}
|
||||
ws.binaryType = "arraybuffer";
|
||||
ws.addEventListener('message',getLiveJson);
|
||||
ws.addEventListener('message', (e) => {
|
||||
try {
|
||||
if (toString.call(e.data) === '[object ArrayBuffer]') {
|
||||
let leds = new Uint8Array(event.data);
|
||||
if (leds[0] != 76) return; //'L'
|
||||
let str = "linear-gradient(90deg,";
|
||||
let len = leds.length;
|
||||
let start = leds[1]==2 ? 4 : 2; // 1 = 1D, 2 = 1D/2D (leds[2]=w, leds[3]=h)
|
||||
for (i = start; i < len; i+=3) {
|
||||
str += `rgb(${leds[i]},${leds[i+1]},${leds[i+2]})`;
|
||||
if (i < len -3) str += ","
|
||||
}
|
||||
str += ")";
|
||||
document.getElementById("canv").style.background = str;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Peek WS error:",err);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
77
wled00/data/liveviewws2D.htm
Normal file
77
wled00/data/liveviewws2D.htm
Normal file
@ -0,0 +1,77 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
|
||||
<meta charset="utf-8">
|
||||
<meta name="theme-color" content="#222222">
|
||||
<title>WLED Live Preview</title>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="canv"></canvas>
|
||||
<script>
|
||||
var c = document.getElementById('canv');
|
||||
var leds = "";
|
||||
var throttled = false;
|
||||
function setCanvas() {
|
||||
c.width = window.innerWidth * 0.98; //remove scroll bars
|
||||
c.height = window.innerHeight * 0.98; //remove scroll bars
|
||||
}
|
||||
setCanvas();
|
||||
// Check for canvas support
|
||||
var ctx = c.getContext('2d');
|
||||
if (ctx) { // Access the rendering context
|
||||
// use parent WS or open new
|
||||
var ws;
|
||||
try {
|
||||
ws = top.window.ws;
|
||||
} catch (e) {}
|
||||
if (ws && ws.readyState === WebSocket.OPEN) {
|
||||
ws.send("{'lv':true}");
|
||||
} else {
|
||||
ws = new WebSocket((window.location.protocol == "https:"?"wss":"ws")+"://"+document.location.host+"/ws");
|
||||
ws.onopen = ()=>{
|
||||
ws.send("{'lv':true}");
|
||||
}
|
||||
}
|
||||
ws.binaryType = "arraybuffer";
|
||||
ws.addEventListener('message',(e)=>{
|
||||
try {
|
||||
if (toString.call(e.data) === '[object ArrayBuffer]') {
|
||||
let leds = new Uint8Array(event.data);
|
||||
if (leds[0] != 76 || leds[1] != 2 || !ctx) return; //'L', set in ws.cpp
|
||||
let mW = leds[2]; // matrix width
|
||||
let mH = leds[3]; // matrix height
|
||||
let pPL = Math.min(c.width / mW, c.height / mH); // pixels per LED (width of circle)
|
||||
let lOf = Math.floor((c.width - pPL*mW)/2); //left offeset (to center matrix)
|
||||
var i = 4;
|
||||
for (y=0.5;y<mH;y++) for (x=0.5; x<mW; x++) {
|
||||
ctx.fillStyle = `rgb(${leds[i]},${leds[i+1]},${leds[i+2]})`;
|
||||
ctx.beginPath();
|
||||
ctx.arc(x*pPL+lOf, y*pPL, pPL*0.4, 0, 2 * Math.PI);
|
||||
ctx.fill();
|
||||
i+=3;
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Peek WS error:",err);
|
||||
}
|
||||
});
|
||||
}
|
||||
// window.resize event listener
|
||||
window.addEventListener('resize', (e)=>{
|
||||
if (!throttled) { // only run if we're not throttled
|
||||
setCanvas(); // actual callback action
|
||||
throttled = true; // we're throttled!
|
||||
setTimeout(()=>{ // set a timeout to un-throttle
|
||||
throttled = false;
|
||||
}, 250);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -6,9 +6,38 @@
|
||||
<title>WLED Settings</title>
|
||||
<script>
|
||||
var d=document;
|
||||
var loc = false, locip;
|
||||
function gId(n){return d.getElementById(n);}
|
||||
function S(){GetV();}
|
||||
function GetV(){}
|
||||
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||
function loadJS(FILE_URL, async = true) {
|
||||
let scE = d.createElement("script");
|
||||
scE.setAttribute("src", FILE_URL);
|
||||
scE.setAttribute("type", "text/javascript");
|
||||
scE.setAttribute("async", async);
|
||||
d.body.appendChild(scE);
|
||||
// success event
|
||||
scE.addEventListener("load", () => {
|
||||
//console.log("File loaded");
|
||||
GetV();
|
||||
});
|
||||
// error event
|
||||
scE.addEventListener("error", (ev) => {
|
||||
console.log("Error on loading file", ev);
|
||||
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||
});
|
||||
}
|
||||
function S(){
|
||||
if (window.location.protocol == "file:") {
|
||||
loc = true;
|
||||
locip = localStorage.getItem('locIp');
|
||||
if (!locip) {
|
||||
locip = prompt("File Mode. Please enter WLED IP!");
|
||||
localStorage.setItem('locIp', locip);
|
||||
}
|
||||
}
|
||||
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=0';
|
||||
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
body {
|
||||
@ -18,31 +47,33 @@
|
||||
margin: 0;
|
||||
}
|
||||
html {
|
||||
--h: 10.2vh;
|
||||
--h: 9vh;
|
||||
}
|
||||
button {
|
||||
background: #333;
|
||||
color: #fff;
|
||||
font-family: Verdana, Helvetica, sans-serif;
|
||||
display: inline-block;
|
||||
display: block;
|
||||
border: 1px solid #333;
|
||||
border-radius: var(--h);
|
||||
font-size: 6vmin;
|
||||
height: var(--h);
|
||||
width: calc(100% - 40px);
|
||||
margin-top: 2vh;
|
||||
margin: 2vh auto 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body onload="S()">
|
||||
<form action="/"><button type=submit id="b">Back</button></form>
|
||||
<form action="/settings/wifi"><button type="submit">WiFi Setup</button></form>
|
||||
<form action="/settings/leds"><button type="submit">LED Preferences</button></form>
|
||||
<form action="/settings/ui"><button type="submit">User Interface</button></form>
|
||||
<form action="/settings/dmx"><button id="dmxbtn" style="display: none;" type="submit">DMX Output</button></form>
|
||||
<form action="/settings/sync"><button type="submit">Sync Interfaces</button></form>
|
||||
<form action="/settings/time"><button type="submit">Time & Macros</button></form>
|
||||
<form action="/settings/um"><button type="submit">Usermods</button></form>
|
||||
<form action="/settings/sec"><button type="submit">Security & Updates</button></form>
|
||||
<button type=submit id="b" onclick="window.location='/'">Back</button>
|
||||
<button type="submit" onclick="window.location='./settings/wifi'">WiFi Setup</button>
|
||||
<button type="submit" onclick="window.location='./settings/leds'">LED Preferences</button>
|
||||
<button type="submit" onclick="window.location='./settings/2D'">2D Configuration</button>
|
||||
<button type="submit" onclick="window.location='./settings/ui'">User Interface</button>
|
||||
<button id="dmxbtn" style="display: none;" type="submit" onclick="window.location='./settings/dmx'">DMX Output</button>
|
||||
<button type="submit" onclick="window.location='./settings/sync'">Sync Interfaces</button>
|
||||
<button type="submit" onclick="window.location='./settings/time'">Time & Macros</button>
|
||||
<button type="submit" onclick="window.location='./settings/um'">Usermods</button>
|
||||
<button type="submit" onclick="window.location='./settings/sec'">Security & Updates</button>
|
||||
</body>
|
||||
</html>
|
150
wled00/data/settings_2D.htm
Normal file
150
wled00/data/settings_2D.htm
Normal file
@ -0,0 +1,150 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=500">
|
||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
|
||||
<title>2D Set-up</title>
|
||||
<script>
|
||||
var d=document;
|
||||
var loc = false, locip;
|
||||
function H(){window.open("https://kno.wled.ge/features/2D");}
|
||||
function B(){window.open("/settings","_self");}
|
||||
function gId(n){return d.getElementById(n);}
|
||||
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||
function loadJS(FILE_URL, async = true) {
|
||||
let scE = d.createElement("script");
|
||||
scE.setAttribute("src", FILE_URL);
|
||||
scE.setAttribute("type", "text/javascript");
|
||||
scE.setAttribute("async", async);
|
||||
d.body.appendChild(scE);
|
||||
// success event
|
||||
scE.addEventListener("load", () => {
|
||||
//console.log("File loaded");
|
||||
GetV();
|
||||
UI();
|
||||
});
|
||||
// error event
|
||||
scE.addEventListener("error", (ev) => {
|
||||
console.log("Error on loading file", ev);
|
||||
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||
});
|
||||
}
|
||||
function S() {
|
||||
if (window.location.protocol == "file:") {
|
||||
loc = true;
|
||||
locip = localStorage.getItem('locIp');
|
||||
if (!locip) {
|
||||
locip = prompt("File Mode. Please enter WLED IP!");
|
||||
localStorage.setItem('locIp', locip);
|
||||
}
|
||||
}
|
||||
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=10';
|
||||
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
}
|
||||
|
||||
var maxPanels=64;
|
||||
function UI(change=false)
|
||||
{
|
||||
if (gId("somp").value === "0") {
|
||||
gId("mpdiv").style.display = "none";
|
||||
resetPanels();
|
||||
return;
|
||||
}
|
||||
|
||||
gId("mpdiv").style.display = "block";
|
||||
maxPanels = parseInt(d.Sf.MPH.value) * parseInt(d.Sf.MPV.value);
|
||||
|
||||
let i = gId("panels").children.length;
|
||||
if (i<maxPanels) for (let j=i; j<maxPanels; j++) addPanel(j);
|
||||
if (i>maxPanels) for (let j=i; j>maxPanels; j--) remPanel();
|
||||
//btnPanel(gId("panels").children.length);
|
||||
}
|
||||
|
||||
function addPanels() {
|
||||
let h = parseInt(d.Sf.MPH.value);
|
||||
let v = parseInt(d.Sf.MPV.value);
|
||||
for (let i=0; i<h*v; i++) addPanel(i);
|
||||
}
|
||||
|
||||
function addPanel(i=0) {
|
||||
let p = gId("panels");
|
||||
if (p.children.length >= maxPanels) return;
|
||||
let b = `<div id="pnl${i}">${i===0?"":'<hr style="width:260px">'}Panel ${i}<br>1<sup>st</sup> LED: <select name="P${i}B">
|
||||
<option value="0">Top</option>
|
||||
<option value="1">Bottom</option>
|
||||
</select><select name="P${i}R">
|
||||
<option value="0">Left</option>
|
||||
<option value="1">Right</option>
|
||||
</select><br>
|
||||
Orientation: <select name="P${i}V">
|
||||
<option value="0">Horizontal</option>
|
||||
<option value="1">Vertical</option>
|
||||
</select><br>
|
||||
Serpentine: <input type="checkbox" name="P${i}S"></div>`;
|
||||
p.insertAdjacentHTML("beforeend", b);
|
||||
}
|
||||
|
||||
function remPanel() {
|
||||
let p = gId("panels").children;
|
||||
var i = p.length;
|
||||
if (i <= 1) return;
|
||||
p[i-1].remove();
|
||||
}
|
||||
|
||||
function resetPanels() {
|
||||
d.Sf.MPH.value = 1;
|
||||
d.Sf.MPV.value = 1;
|
||||
for (let e of gId("panels").children) e.remove();
|
||||
}
|
||||
|
||||
function btnPanel(i) {
|
||||
gId("pnl_add").style.display = (i<maxPanels) ? "inline":"none";
|
||||
gId("pnl_rem").style.display = (i>1) ? "inline":"none";
|
||||
}
|
||||
</script>
|
||||
<style>@import url("style.css");</style>
|
||||
</head>
|
||||
<body onload="S()">
|
||||
<form id="form_s" name="Sf" method="post">
|
||||
<div class="toprow">
|
||||
<div class="helpB"><button type="button" onclick="H()">?</button></div>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr>
|
||||
</div>
|
||||
<h2>2D setup</h2>
|
||||
Strip or panel:
|
||||
<select id="somp" name="SOMP" onchange="resetPanels();addPanels();UI();" >
|
||||
<option value="0">1D Strip</option>
|
||||
<option value="1">2D Matrix</option>
|
||||
</select><br>
|
||||
<div id="mpdiv" style="display:none;">
|
||||
<h3>Panel set-up</h3>
|
||||
Panel dimensions (WxH): <input name="PW" type="number" min="1" max="128" value="8"> x <input name="PH" type="number" min="1" max="128" value="8"><br>
|
||||
Horizontal panels: <input name="MPH" type="number" min="1" max="8" value="1" oninput="UI()">
|
||||
Vertical panels: <input name="MPV" type="number" min="1" max="8" value="1" oninput="UI()"><br>
|
||||
1<sup>st</sup> panel: <select name="PB">
|
||||
<option value="0">Top</option>
|
||||
<option value="1">Bottom</option>
|
||||
</select><select name="PR">
|
||||
<option value="0">Left</option>
|
||||
<option value="1">Right</option>
|
||||
</select><br>
|
||||
Orientation: <select name="PV">
|
||||
<option value="0">Horizontal</option>
|
||||
<option value="1">Vertical</option>
|
||||
</select><br>
|
||||
Serpentine: <input type="checkbox" name="PS">
|
||||
<hr style="width:260px">
|
||||
<i>A matrix is made of 1 or more physical LED panels of the same dimensions.<br>
|
||||
Panels should be arranged from top-left to bottom-right order, starting with lower panel number on the left (or top if transposed).<br>
|
||||
Each panel can have different LED orientation and/or starting point and/or layout.</i><br>
|
||||
<hr style="width:260px">
|
||||
<h3>LED panel layout</h3>
|
||||
<div id="panels">
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
@ -6,35 +6,65 @@
|
||||
<meta charset="utf-8">
|
||||
<title>DMX Settings</title>
|
||||
<script>
|
||||
function GCH(num) {
|
||||
d=document;
|
||||
d.getElementById('dmxchannels').innerHTML += "";
|
||||
for (i=0;i<num;i++) {
|
||||
d.getElementById('dmxchannels').innerHTML += "<span id=CH" + (i+1) + "s >Channel " + (i+1) + ": <select name=CH" + (i+1) + " id=\"CH" + (i+1) + "\"><option value=0>Set to 0</option><option value=1>Red</option><option value=2>Green</option><option value=3>Blue</option><option value=4>White</option><option value=5>Shutter (Brightness)</option><option value=6>Set to 255</option></select></span><br />\n";
|
||||
}
|
||||
}
|
||||
function mMap(){
|
||||
d=document;
|
||||
numCh=document.Sf.CN.value;
|
||||
numGap=document.Sf.CG.value;
|
||||
if (parseInt(numCh)>parseInt(numGap)) {
|
||||
d.getElementById("gapwarning").style.display="block";
|
||||
} else {
|
||||
d.getElementById("gapwarning").style.display="none";
|
||||
}
|
||||
for (i=0;i<15;i++) {
|
||||
if (i>=numCh) {
|
||||
d.getElementById("CH"+(i+1) + "s").style.opacity = "0.5";
|
||||
d.getElementById("CH"+(i+1)).disabled = true;
|
||||
|
||||
} else {
|
||||
d.getElementById("CH"+(i+1) + "s").style.opacity = "1";
|
||||
d.getElementById("CH"+(i+1)).disabled = false;
|
||||
var d=document;
|
||||
var loc = false, locip;
|
||||
function H(){window.open("https://github.com/Aircoookie/WLED/wiki/DMX");}
|
||||
function B(){window.history.back();}
|
||||
function GCH(num) {
|
||||
d.getElementById('dmxchannels').innerHTML += "";
|
||||
for (i=0;i<num;i++) {
|
||||
d.getElementById('dmxchannels').innerHTML += "<span id=CH" + (i+1) + "s >Channel " + (i+1) + ": <select name=CH" + (i+1) + " id=\"CH" + (i+1) + "\"><option value=0>Set to 0</option><option value=1>Red</option><option value=2>Green</option><option value=3>Blue</option><option value=4>White</option><option value=5>Shutter (Brightness)</option><option value=6>Set to 255</option></select></span><br />\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
function S(){GCH(15);GetV();mMap();}function H(){window.open("https://github.com/Aircoookie/WLED/wiki/DMX");}function B(){window.history.back();}
|
||||
function GetV(){}
|
||||
function mMap(){
|
||||
numCh=document.Sf.CN.value;
|
||||
numGap=document.Sf.CG.value;
|
||||
if (parseInt(numCh)>parseInt(numGap)) {
|
||||
d.getElementById("gapwarning").style.display="block";
|
||||
} else {
|
||||
d.getElementById("gapwarning").style.display="none";
|
||||
}
|
||||
for (i=0;i<15;i++) {
|
||||
if (i>=numCh) {
|
||||
d.getElementById("CH"+(i+1) + "s").style.opacity = "0.5";
|
||||
d.getElementById("CH"+(i+1)).disabled = true;
|
||||
|
||||
} else {
|
||||
d.getElementById("CH"+(i+1) + "s").style.opacity = "1";
|
||||
d.getElementById("CH"+(i+1)).disabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||
function loadJS(FILE_URL, async = true) {
|
||||
let scE = d.createElement("script");
|
||||
scE.setAttribute("src", FILE_URL);
|
||||
scE.setAttribute("type", "text/javascript");
|
||||
scE.setAttribute("async", async);
|
||||
d.body.appendChild(scE);
|
||||
// success event
|
||||
scE.addEventListener("load", () => {
|
||||
//console.log("File loaded");
|
||||
GCH(15);GetV();mMap();
|
||||
});
|
||||
// error event
|
||||
scE.addEventListener("error", (ev) => {
|
||||
console.log("Error on loading file", ev);
|
||||
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||
});
|
||||
}
|
||||
function S(){
|
||||
if (window.location.protocol == "file:") {
|
||||
loc = true;
|
||||
locip = localStorage.getItem('locIp');
|
||||
if (!locip) {
|
||||
locip = prompt("File Mode. Please enter WLED IP!");
|
||||
localStorage.setItem('locIp', locip);
|
||||
}
|
||||
}
|
||||
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=7';
|
||||
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
}
|
||||
</script>
|
||||
<style>@import url("style.css");</style>
|
||||
</head>
|
||||
|
@ -8,10 +8,29 @@
|
||||
<script>
|
||||
var d=document,laprev=55,maxB=1,maxM=4000,maxPB=4096,maxL=1333,maxLbquot=0; //maximum bytes for LED allocation: 4kB for 8266, 32kB for 32
|
||||
var customStarts=false,startsDirty=[],maxCOOverrides=5;
|
||||
var loc = false, locip;
|
||||
function H(){window.open("https://kno.wled.ge/features/settings/#led-settings");}
|
||||
function B(){window.open("/settings","_self");}
|
||||
function gId(n){return d.getElementById(n);}
|
||||
function off(n){d.getElementsByName(n)[0].value = -1;}
|
||||
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||
function loadJS(FILE_URL, async = true) {
|
||||
let scE = d.createElement("script");
|
||||
scE.setAttribute("src", FILE_URL);
|
||||
scE.setAttribute("type", "text/javascript");
|
||||
scE.setAttribute("async", async);
|
||||
d.body.appendChild(scE);
|
||||
// success event
|
||||
scE.addEventListener("load", () => {
|
||||
//console.log("File loaded");
|
||||
GetV();checkSi();setABL();
|
||||
});
|
||||
// error event
|
||||
scE.addEventListener("error", (ev) => {
|
||||
console.log("Error on loading file", ev);
|
||||
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||
});
|
||||
}
|
||||
var timeout;
|
||||
function showToast(text, error = false)
|
||||
{
|
||||
@ -131,7 +150,7 @@
|
||||
if (s[i].name.substring(0,2)=="LT") {
|
||||
var n = s[i].name.substring(2);
|
||||
var t = parseInt(s[i].value,10);
|
||||
gId("p0d"+n).innerHTML = (t>=80 && t<96) ? "IP address:" : (t > 49) ? "Data GPIO:" : (t >41) ? "GPIOs:" : "GPIO:";
|
||||
gId("p0d"+n).innerHTML = (t>=80 && t<96) ? "IP address:" : (t > 49) ? "Data GPIO:" : (t > 41) ? "GPIOs:" : "GPIO:";
|
||||
gId("p1d"+n).innerHTML = (t> 49 && t<64) ? "Clk GPIO:" : "";
|
||||
var LK = d.getElementsByName("L1"+n)[0]; // clock pin
|
||||
|
||||
@ -157,18 +176,18 @@
|
||||
gId("rf"+n).checked = (gId("rf"+n).checked || t == 31); // LEDs require data in off state
|
||||
if (t > 31 && t < 48) d.getElementsByName("LC"+n)[0].value = 1; // for sanity change analog count just to 1 LED
|
||||
}
|
||||
gId("rf"+n).onclick = (t == 31) ? (function(){return false}) : (function(){}); // prevent change for TM1814
|
||||
gId("rf"+n).onclick = (t == 31) ? (()=>{return false}) : (()=>{}); // prevent change for TM1814
|
||||
isRGBW |= (t == 30 || t == 31 || (t > 40 && t < 46 && t != 43)); // RGBW checkbox, TYPE_xxxx values from const.h
|
||||
gId("co"+n).style.display = ((t>=80 && t<96) || (t > 40 && t < 48)) ? "none":"inline"; // hide color order for PWM
|
||||
gId("co"+n).style.display = ((t >= 80 && t < 96) || (t >= 40 && t < 48)) ? "none":"inline"; // hide color order for PWM
|
||||
gId("dig"+n+"w").style.display = (t == 30 || t == 31) ? "inline":"none"; // show swap channels dropdown
|
||||
if (!(t == 30 || t == 31)) d.getElementsByName("WO"+n)[0].value = 0; // reset swapping
|
||||
gId("dig"+n+"c").style.display = (t > 40 && t < 48) ? "none":"inline"; // hide count for analog
|
||||
gId("dig"+n+"r").style.display = (t>=80 && t<96) ? "none":"inline"; // hide reversed for virtual
|
||||
gId("dig"+n+"s").style.display = ((t>=80 && t<96) || (t > 40 && t < 48)) ? "none":"inline"; // hide skip 1st for virtual & analog
|
||||
gId("dig"+n+"f").style.display = (t>=16 && t<32 || t>=50 && t<64) ? "inline":"none"; // hide refresh
|
||||
gId("dig"+n+"a").style.display = (isRGBW) ? "inline":"none"; // auto calculate white
|
||||
gId("rev"+n).innerHTML = (t > 40 && t < 48) ? "Inverted output":"Reversed (rotated 180°)"; // change reverse text for analog
|
||||
gId("psd"+n).innerHTML = (t > 40 && t < 48) ? "Index:":"Start:"; // change analog start description
|
||||
gId("dig"+n+"c").style.display = (t >= 40 && t < 48) ? "none":"inline"; // hide count for analog
|
||||
gId("dig"+n+"r").style.display = (t >= 80 && t < 96) ? "none":"inline"; // hide reversed for virtual
|
||||
gId("dig"+n+"s").style.display = ((t >= 80 && t < 96) || (t >= 40 && t < 48)) ? "none":"inline"; // hide skip 1st for virtual & analog
|
||||
gId("dig"+n+"f").style.display = ((t >= 16 && t < 32) || (t >= 50 && t < 64)) ? "inline":"none"; // hide refresh
|
||||
gId("dig"+n+"a").style.display = (isRGBW && t != 40) ? "inline":"none"; // auto calculate white
|
||||
gId("rev"+n).innerHTML = (t >= 40 && t < 48) ? "Inverted output":"Reversed (rotated 180°)"; // change reverse text for analog
|
||||
gId("psd"+n).innerHTML = (t >= 40 && t < 48) ? "Index:":"Start:"; // change analog start description
|
||||
}
|
||||
}
|
||||
// display white channel calculation method
|
||||
@ -297,11 +316,13 @@ ${i+1}:
|
||||
<option value="30">SK6812 RGBW</option>
|
||||
<option value="31">TM1814</option>
|
||||
<option value="24">400kHz</option>
|
||||
<option value="25">TM1829</option>
|
||||
<option value="50">WS2801</option>
|
||||
<option value="51">APA102</option>
|
||||
<option value="52">LPD8806</option>
|
||||
<option value="54">LPD6803</option>
|
||||
<option value="53">P9813</option>
|
||||
<option value="40">On/Off</option>
|
||||
<option value="41">PWM White</option>
|
||||
<option value="42">PWM CCT</option>
|
||||
<option value="43">PWM RGB</option>
|
||||
@ -506,12 +527,17 @@ Length: <input type="number" name="XC${i}" id="xc${i}" class="l" min="1" max="65
|
||||
}
|
||||
}
|
||||
}
|
||||
function S(){GetV();checkSi();setABL();}
|
||||
function GetV()
|
||||
{
|
||||
//values injected by server while sending HTML
|
||||
//d.um_p=[6,7,8,9,10,11,1];bLimits(3,4096,4000,1664);d.Sf.MS.checked=1;addLEDs(1);d.Sf.L00.value=2;d.Sf.LC0.value=30;d.Sf.LT0.value=22;d.Sf.CO0.value=0;d.Sf.LS0.value=15;d.Sf.CV0.checked=1;d.Sf.SL0.checked=0;addLEDs(1);d.Sf.L01.value=10;d.Sf.L11.value=10;d.Sf.L21.value=1;d.Sf.L31.value=10;d.Sf.LC1.value=60;d.Sf.LT1.value=80;d.Sf.CO1.value=1;d.Sf.LS1.value=0;d.Sf.CV1.checked=0;d.Sf.SL1.checked=0;d.Sf.MA.value=850;d.Sf.LA.value=0;d.Sf.CA.value=56;d.Sf.AW.value=3;d.Sf.BO.checked=1;d.Sf.BP.value=80;d.Sf.GB.checked=0;d.Sf.GC.checked=1;d.Sf.TF.checked=1;d.Sf.TD.value=700;d.Sf.PF.checked=0;d.Sf.BF.value=100;d.Sf.TB.value=0;d.Sf.TL.value=60;d.Sf.TW.value=0;d.Sf.PB.selectedIndex=0;d.Sf.RL.value=12;d.Sf.RM.checked=1;addBtn(0,0,0);addBtn(1,-1,0);d.Sf.TT.value=32;d.Sf.IR.value=-1;d.Sf.IT.value=0;
|
||||
//d.um_p=[6,7,8,9,10,11,14,15,13,1,21,19,22,25,26,27,5,23,18,17];bLimits(10,2048,64000,8192);d.Sf.MS.checked=1;d.Sf.CCT.checked=0;addLEDs(1);d.Sf.L00.value=192;d.Sf.L10.value=168;d.Sf.L20.value=0;d.Sf.L30.value=61;d.Sf.LC0.value=421;d.Sf.LT0.value=80;d.Sf.CO0.value=1;d.Sf.LS0.value=0;d.Sf.CV0.checked=0;d.Sf.SL0.checked=0;d.Sf.RF0.checked=0;d.Sf.MA.value=850;d.Sf.LA.value=0;d.Sf.CA.value=127;d.Sf.AW.value=3;d.Sf.BO.checked=0;d.Sf.BP.value=0;d.Sf.GB.checked=0;d.Sf.GC.checked=1;d.Sf.TF.checked=1;d.Sf.TD.value=700;d.Sf.PF.checked=1;d.Sf.BF.value=100;d.Sf.TB.value=0;d.Sf.TL.value=60;d.Sf.TW.value=1;d.Sf.PB.selectedIndex=0;d.Sf.RL.value=-1;d.Sf.RM.checked=1;addBtn(0,-1,0);addBtn(1,-1,0);addBtn(2,-1,0);addBtn(3,-1,0);d.Sf.TT.value=32;d.Sf.IR.value=-1;d.Sf.IT.value=8;
|
||||
function S(){
|
||||
if (window.location.protocol == "file:") {
|
||||
loc = true;
|
||||
locip = localStorage.getItem('locIp');
|
||||
if (!locip) {
|
||||
locip = prompt("File Mode. Please enter WLED IP!");
|
||||
localStorage.setItem('locIp', locip);
|
||||
}
|
||||
}
|
||||
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=2';
|
||||
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
}
|
||||
</script>
|
||||
<style>@import url("style.css");</style>
|
||||
@ -564,8 +590,9 @@ Length: <input type="number" name="XC${i}" id="xc${i}" class="l" min="1" max="65
|
||||
Use less than <span id="wreason">800 LEDs per output</span> for the best experience!<br>
|
||||
</div>
|
||||
<hr style="width:260px">
|
||||
Make a segment for each output: <input type="checkbox" name="MS"> <br>
|
||||
Custom bus start indices: <input type="checkbox" onchange="tglSi(this.checked)" id="si"> <br>
|
||||
Make a segment for each output: <input type="checkbox" name="MS"><br>
|
||||
Custom bus start indices: <input type="checkbox" onchange="tglSi(this.checked)" id="si"><br>
|
||||
Use global LED buffer: <input type="checkbox" name="LD"><br>
|
||||
<hr style="width:260px">
|
||||
<div id="color_order_mapping">
|
||||
Color Order Override:
|
||||
|
@ -7,11 +7,32 @@
|
||||
<title>Misc Settings</title>
|
||||
<script>
|
||||
var d = document;
|
||||
var loc = false, locip;
|
||||
function H() { window.open("https://kno.wled.ge/features/settings/#security-settings"); }
|
||||
function B() { window.open("/settings","_self"); }
|
||||
function U() { window.open("/update","_self"); }
|
||||
function gId(s) { return d.getElementById(s); }
|
||||
function isObj(o) { return (o && typeof o === 'object' && !Array.isArray(o)); }
|
||||
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||
function loadJS(FILE_URL, async = true) {
|
||||
let scE = d.createElement("script");
|
||||
scE.setAttribute("src", FILE_URL);
|
||||
scE.setAttribute("type", "text/javascript");
|
||||
scE.setAttribute("async", async);
|
||||
d.body.appendChild(scE);
|
||||
// success event
|
||||
scE.addEventListener("load", () => {
|
||||
//console.log("File loaded");
|
||||
GetV();
|
||||
setBckFilename(gId("bckcfg"));
|
||||
setBckFilename(gId("bckpresets"));
|
||||
});
|
||||
// error event
|
||||
scE.addEventListener("error", (ev) => {
|
||||
console.log("Error on loading file", ev);
|
||||
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||
});
|
||||
}
|
||||
var timeout;
|
||||
function showToast(text, error = false)
|
||||
{
|
||||
@ -40,16 +61,27 @@
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
function GetV()
|
||||
{
|
||||
//values injected by server while sending HTML
|
||||
function setBckFilename(x) {
|
||||
x.setAttribute("download","wled_" + x.getAttribute("download") + (sd=="WLED"?"":("_" +sd)));
|
||||
}
|
||||
function S() {
|
||||
if (window.location.protocol == "file:") {
|
||||
loc = true;
|
||||
locip = localStorage.getItem('locIp');
|
||||
if (!locip) {
|
||||
locip = prompt("File Mode. Please enter WLED IP!");
|
||||
localStorage.setItem('locIp', locip);
|
||||
}
|
||||
}
|
||||
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=6';
|
||||
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
@import url("style.css");
|
||||
</style>
|
||||
</head>
|
||||
<body onload="GetV()">
|
||||
<body onload="S()">
|
||||
<form id="form_s" name="Sf" method="post">
|
||||
<div class="toprow">
|
||||
<div class="helpB"><button type="button" onclick="H()">?</button></div>
|
||||
@ -74,9 +106,9 @@
|
||||
Enable ArduinoOTA: <input type="checkbox" name="AO">
|
||||
<hr>
|
||||
<h3>Backup & Restore</h3>
|
||||
<a class="btn lnk" href="/presets.json?download" target="download-frame">Backup presets</a><br>
|
||||
<a class="btn lnk" id="bckcfg" href="/presets.json" download="presets">Backup presets</a><br>
|
||||
<div>Restore presets<br><input type="file" name="data" accept=".json"> <button type="button" onclick="uploadFile(d.Sf.data,'/presets.json');">Upload</button><br></div><br>
|
||||
<a class="btn lnk" href="/cfg.json?download" target="download-frame">Backup configuration</a><br>
|
||||
<a class="btn lnk" id="bckpresets" href="/cfg.json" download="cfg">Backup configuration</a><br>
|
||||
<div>Restore configuration<br><input type="file" name="data2" accept=".json"> <button type="button" onclick="uploadFile(d.Sf.data2,'/cfg.json');">Upload</button><br></div>
|
||||
<div style="color: #fa0;">⚠ Restoring presets/configuration will OVERWRITE your current presets/configuration.<br>
|
||||
Incorrect configuration may require a factory reset or re-flashing of your ESP.</div>
|
||||
@ -92,6 +124,5 @@
|
||||
<div id="toast"></div>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button>
|
||||
</form>
|
||||
<iframe name=download-frame style='display:none;'></iframe>
|
||||
</body>
|
||||
</html>
|
@ -5,42 +5,71 @@
|
||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
|
||||
<meta charset="utf-8">
|
||||
<title>Sync Settings</title>
|
||||
<script>var d=document;
|
||||
function gId(s)
|
||||
{
|
||||
return d.getElementById(s);
|
||||
}
|
||||
function H(){window.open("https://kno.wled.ge/interfaces/udp-notifier/");}
|
||||
function B(){window.open("/settings","_self");}
|
||||
function adj(){if (d.Sf.DI.value == 6454) {if (d.Sf.DA.value == 1) d.Sf.DA.value = 0; if (d.Sf.EU.value == 1) d.Sf.EU.value = 0;}
|
||||
else if (d.Sf.DI.value == 5568) {if (d.Sf.DA.value == 0) d.Sf.DA.value = 1; if (d.Sf.EU.value == 0) d.Sf.EU.value = 1;} }
|
||||
function FC()
|
||||
{
|
||||
for(j=0;j<8;j++)
|
||||
<script>var d=document;
|
||||
var loc = false, locip;
|
||||
function gId(s)
|
||||
{
|
||||
gId("G"+(j+1)).checked=gId("GS").value>>j&1;
|
||||
gId("R"+(j+1)).checked=gId("GR").value>>j&1;
|
||||
return d.getElementById(s);
|
||||
}
|
||||
}
|
||||
function GC()
|
||||
{
|
||||
var a=0, b=0;
|
||||
function H(){window.open("https://kno.wled.ge/interfaces/udp-notifier/");}
|
||||
function B(){window.open("/settings","_self");}
|
||||
function adj(){if (d.Sf.DI.value == 6454) {if (d.Sf.DA.value == 1) d.Sf.DA.value = 0; if (d.Sf.EU.value == 1) d.Sf.EU.value = 0;}
|
||||
else if (d.Sf.DI.value == 5568) {if (d.Sf.DA.value == 0) d.Sf.DA.value = 1; if (d.Sf.EU.value == 0) d.Sf.EU.value = 1;} }
|
||||
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||
function loadJS(FILE_URL, async = true) {
|
||||
let scE = d.createElement("script");
|
||||
scE.setAttribute("src", FILE_URL);
|
||||
scE.setAttribute("type", "text/javascript");
|
||||
scE.setAttribute("async", async);
|
||||
d.body.appendChild(scE);
|
||||
// success event
|
||||
scE.addEventListener("load", () => {
|
||||
//console.log("File loaded");
|
||||
GetV();SetVal();
|
||||
});
|
||||
// error event
|
||||
scE.addEventListener("error", (ev) => {
|
||||
console.log("Error on loading file", ev);
|
||||
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||
});
|
||||
}
|
||||
function FC()
|
||||
{
|
||||
for(j=0;j<8;j++)
|
||||
{
|
||||
gId("G"+(j+1)).checked=gId("GS").value>>j&1;
|
||||
gId("R"+(j+1)).checked=gId("GR").value>>j&1;
|
||||
}
|
||||
}
|
||||
function GC()
|
||||
{
|
||||
var a=0, b=0;
|
||||
|
||||
var m=1;
|
||||
for(j=0;j<8;j++)
|
||||
{
|
||||
a+=gId("G"+(j+1)).checked*m;
|
||||
b+=gId("R"+(j+1)).checked*m;
|
||||
m*=2;
|
||||
var m=1;
|
||||
for(j=0;j<8;j++)
|
||||
{
|
||||
a+=gId("G"+(j+1)).checked*m;
|
||||
b+=gId("R"+(j+1)).checked*m;
|
||||
m*=2;
|
||||
}
|
||||
gId("GS").value=a;
|
||||
gId("GR").value=b;
|
||||
}
|
||||
gId("GS").value=a;
|
||||
gId("GR").value=b;
|
||||
}
|
||||
function SP(){var p = d.Sf.DI.value; gId("xp").style.display = (p > 0)?"none":"block"; if (p > 0) d.Sf.EP.value = p;}
|
||||
function SetVal(){switch(parseInt(d.Sf.EP.value)){case 5568: d.Sf.DI.value = 5568; break; case 6454: d.Sf.DI.value = 6454; break; case 4048: d.Sf.DI.value = 4048; break; }; SP();FC();}
|
||||
function S(){GetV();SetVal();}
|
||||
function GetV(){var d=document;}
|
||||
</script>
|
||||
function SP(){var p = d.Sf.DI.value; gId("xp").style.display = (p > 0)?"none":"block"; if (p > 0) d.Sf.EP.value = p;}
|
||||
function SetVal(){switch(parseInt(d.Sf.EP.value)){case 5568: d.Sf.DI.value = 5568; break; case 6454: d.Sf.DI.value = 6454; break; case 4048: d.Sf.DI.value = 4048; break; }; SP();FC();}
|
||||
function S(){
|
||||
if (window.location.protocol == "file:") {
|
||||
loc = true;
|
||||
locip = localStorage.getItem('locIp');
|
||||
if (!locip) {
|
||||
locip = prompt("File Mode. Please enter WLED IP!");
|
||||
localStorage.setItem('locIp', locip);
|
||||
}
|
||||
}
|
||||
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=4';
|
||||
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
}
|
||||
</script>
|
||||
<style>@import url("style.css");</style>
|
||||
</head>
|
||||
<body onload="S()">
|
||||
|
@ -7,26 +7,42 @@
|
||||
<title>Time Settings</title>
|
||||
<script>
|
||||
var d=document;
|
||||
var loc = false, locip;
|
||||
var el=false;
|
||||
var ms=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
|
||||
function H()
|
||||
{
|
||||
window.open("https://kno.wled.ge/features/settings/#time-settings");
|
||||
function H() { window.open("https://kno.wled.ge/features/settings/#time-settings"); }
|
||||
function B() { window.open("/settings","_self"); }
|
||||
function gId(s) { return d.getElementById(s); }
|
||||
function gN(s) { return d.getElementsByName(s)[0]; }
|
||||
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||
function loadJS(FILE_URL, async = true) {
|
||||
let scE = d.createElement("script");
|
||||
scE.setAttribute("src", FILE_URL);
|
||||
scE.setAttribute("type", "text/javascript");
|
||||
scE.setAttribute("async", async);
|
||||
d.body.appendChild(scE);
|
||||
// success event
|
||||
scE.addEventListener("load", () => {
|
||||
//console.log("File loaded");
|
||||
BTa();GetV();updLoc();Cs();FC();
|
||||
});
|
||||
// error event
|
||||
scE.addEventListener("error", (ev) => {
|
||||
console.log("Error on loading file", ev);
|
||||
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||
});
|
||||
}
|
||||
function B()
|
||||
{
|
||||
window.open("/settings","_self");
|
||||
}
|
||||
function S()
|
||||
{
|
||||
BTa();GetV();updLoc();Cs();FC();
|
||||
}
|
||||
function gId(s)
|
||||
{
|
||||
return d.getElementById(s);
|
||||
}
|
||||
function gN(s) {
|
||||
return d.getElementsByName(s)[0];
|
||||
function S() {
|
||||
if (window.location.protocol == "file:") {
|
||||
loc = true;
|
||||
locip = localStorage.getItem('locIp');
|
||||
if (!locip) {
|
||||
locip = prompt("File Mode. Please enter WLED IP!");
|
||||
localStorage.setItem('locIp', locip);
|
||||
}
|
||||
}
|
||||
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=5';
|
||||
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
}
|
||||
function expand(o,i)
|
||||
{
|
||||
@ -34,10 +50,7 @@
|
||||
t.style.display = t.style.display!=="none" ? "none" : "";
|
||||
o.innerHTML = t.style.display==="none" ? "📅" : "✕";
|
||||
}
|
||||
function Cs()
|
||||
{
|
||||
gId("cac").style.display=(gN("OL").checked)?"block":"none";
|
||||
}
|
||||
function Cs() { gId("cac").style.display=(gN("OL").checked)?"block":"none"; }
|
||||
function BTa()
|
||||
{
|
||||
var ih="<thead><tr><th>En.</th><th>Hour</th><th>Minute</th><th>Preset</th><th></th></tr></thead>";
|
||||
@ -132,10 +145,6 @@
|
||||
if (parseFloat(d.Sf.LT.value)<0) { d.Sf.LTR.value = "S"; d.Sf.LT.value = -1*parseFloat(d.Sf.LT.value); } else d.Sf.LTR.value = "N";
|
||||
if (parseFloat(d.Sf.LN.value)<0) { d.Sf.LNR.value = "W"; d.Sf.LN.value = -1*parseFloat(d.Sf.LN.value); } else d.Sf.LNR.value = "E";
|
||||
}
|
||||
function GetV()
|
||||
{
|
||||
//values injected by server while sending HTML
|
||||
}
|
||||
</script>
|
||||
<style>@import url("style.css");</style>
|
||||
</head>
|
||||
|
@ -7,6 +7,7 @@
|
||||
<title>UI Settings</title>
|
||||
<script>
|
||||
var d = document;
|
||||
var loc = false, locip;
|
||||
var initial_ds, initial_st, initial_su;
|
||||
var sett = null;
|
||||
var l = {
|
||||
@ -23,6 +24,7 @@
|
||||
"pid": "Show preset IDs",
|
||||
"seglen": "Set segment length instead of stop LED",
|
||||
"segpwr": "Hide segment power & brightness",
|
||||
"segexp" : "Always expand first segment",
|
||||
"css": "Enable custom CSS",
|
||||
"hdays": "Enable custom Holidays list"
|
||||
},
|
||||
@ -40,10 +42,7 @@
|
||||
}
|
||||
}
|
||||
};
|
||||
function gId(s)
|
||||
{
|
||||
return d.getElementById(s);
|
||||
}
|
||||
function gId(s) { return d.getElementById(s); }
|
||||
function isObject(item) {
|
||||
return (item && typeof item === 'object' && !Array.isArray(item));
|
||||
}
|
||||
@ -163,22 +162,43 @@
|
||||
if (d.Sf.DS.value != initial_ds || d.Sf.ST.checked != initial_st || d.Sf.SU.checked != initial_su) d.Sf.submit();
|
||||
}
|
||||
|
||||
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||
function loadJS(FILE_URL, async = true) {
|
||||
let scE = d.createElement("script");
|
||||
scE.setAttribute("src", FILE_URL);
|
||||
scE.setAttribute("type", "text/javascript");
|
||||
scE.setAttribute("async", async);
|
||||
d.body.appendChild(scE);
|
||||
// success event
|
||||
scE.addEventListener("load", () => {
|
||||
//console.log("File loaded");
|
||||
GetV();
|
||||
initial_ds = d.Sf.DS.value;
|
||||
initial_st = d.Sf.ST.checked;
|
||||
initial_su = d.Sf.SU.checked;
|
||||
GetLS();
|
||||
});
|
||||
// error event
|
||||
scE.addEventListener("error", (ev) => {
|
||||
console.log("Error on loading file", ev);
|
||||
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||
});
|
||||
}
|
||||
function S()
|
||||
{
|
||||
GetV();
|
||||
initial_ds = d.Sf.DS.value;
|
||||
initial_st = d.Sf.ST.checked;
|
||||
initial_su = d.Sf.SU.checked;
|
||||
GetLS();
|
||||
}
|
||||
function H()
|
||||
{
|
||||
window.open("https://kno.wled.ge/features/settings/#user-interface-settings");
|
||||
}
|
||||
function B()
|
||||
{
|
||||
window.open("/settings","_self");
|
||||
if (window.location.protocol == "file:") {
|
||||
loc = true;
|
||||
locip = localStorage.getItem('locIp');
|
||||
if (!locip) {
|
||||
locip = prompt("File Mode. Please enter WLED IP!");
|
||||
localStorage.setItem('locIp', locip);
|
||||
}
|
||||
}
|
||||
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=3';
|
||||
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
}
|
||||
function H() { window.open("https://kno.wled.ge/features/settings/#user-interface-settings"); }
|
||||
function B() { window.open("/settings","_self"); }
|
||||
function UI()
|
||||
{
|
||||
gId('idonthateyou').style.display = (gId('dm').checked) ? 'inline':'none';
|
||||
@ -213,7 +233,6 @@
|
||||
fO.value = '';
|
||||
return false;
|
||||
}
|
||||
function GetV(){var d=document;}
|
||||
</script>
|
||||
<style>@import url("style.css");</style>
|
||||
</head>
|
||||
@ -241,6 +260,7 @@
|
||||
<span class="l"></span>: <input type="checkbox" id="comp_pid" class="agi cb"><br>
|
||||
<span class="l"></span>: <input type="checkbox" id="comp_seglen" class="agi cb"><br>
|
||||
<span class="l"></span>: <input type="checkbox" id="comp_segpwr" class="agi cb"><br>
|
||||
<span class="l"></span>: <input type="checkbox" id="comp_segexp" class="agi cb"><br>
|
||||
I hate dark mode: <input type="checkbox" id="dm" onchange="UI()"><br>
|
||||
<span id="idonthateyou" style="display:none"><i>Why would you? </i>🥺<br></span>
|
||||
<span class="l"></span>: <input type="number" min=0.0 max=1.0 step=0.01 id="theme_alpha_tab" class="agi"><br>
|
||||
|
@ -17,6 +17,24 @@
|
||||
function isO(i) { return (i && typeof i === 'object' && !Array.isArray(i)); }
|
||||
function H() { window.open("https://github.com/Aircoookie/WLED/wiki/Settings#usermod-settings"); }
|
||||
function B() { window.open("/settings","_self"); }
|
||||
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||
function loadJS(FILE_URL, async = true) {
|
||||
let scE = d.createElement("script");
|
||||
scE.setAttribute("src", FILE_URL);
|
||||
scE.setAttribute("type", "text/javascript");
|
||||
scE.setAttribute("async", async);
|
||||
d.body.appendChild(scE);
|
||||
// success event
|
||||
scE.addEventListener("load", () => {
|
||||
//console.log("File loaded");
|
||||
GetV();
|
||||
});
|
||||
// error event
|
||||
scE.addEventListener("error", (ev) => {
|
||||
console.log("Error on loading file", ev);
|
||||
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||
});
|
||||
}
|
||||
function S() {
|
||||
if (window.location.protocol == "file:") {
|
||||
loc = true;
|
||||
@ -37,6 +55,21 @@
|
||||
if (o.type=="number" && n.substr(0,3)=="pin") {
|
||||
for (var i=0; i<pins.length; i++) {
|
||||
if (k==pinO[i]) continue;
|
||||
if (o.value==pins[i] && pinO[i]==="if") { o.style.color="lime"; break; }
|
||||
if (o.value==pins[i] || o.value<-1 || o.value>39) { o.style.color="red"; break; } else o.style.color=o.value>33?"orange":"#fff";
|
||||
}
|
||||
} else {
|
||||
switch (o.name) {
|
||||
case "SDA": break;
|
||||
case "SCL": break;
|
||||
case "MOSI": break;
|
||||
case "SCLK": break;
|
||||
case "CS": break;
|
||||
default: return;
|
||||
}
|
||||
for (var i=0; i<pins.length; i++) {
|
||||
if (k==pinO[i]) continue;
|
||||
if (o.value==pins[i] && pinO[i]==="if") { o.style.color="lime"; break; }
|
||||
if (o.value==pins[i] || o.value<-1 || o.value>39) { o.style.color="red"; break; } else o.style.color=o.value>33?"orange":"#fff";
|
||||
}
|
||||
}
|
||||
@ -63,6 +96,7 @@
|
||||
}
|
||||
function addField(k,f,o,a=false) { //key, field, (sub)object, isArray
|
||||
if (isO(o)) {
|
||||
urows += '<hr style="width:260px">';
|
||||
for (const [s,v] of Object.entries(o)) {
|
||||
// possibility to nest objects (only 1 level)
|
||||
if (f!=='unknown' && !k.includes(":")) addField(k+":"+f,s,v);
|
||||
@ -137,7 +171,9 @@
|
||||
// https://stackoverflow.com/questions/26440494/insert-text-after-this-input-element-with-javascript
|
||||
function addInfo(name,el,txt) {
|
||||
let obj = d.getElementsByName(name);
|
||||
if (obj[el]) obj[el].insertAdjacentHTML('afterend', ' '+txt);
|
||||
if (!obj.length) return;
|
||||
if (typeof el === "string" && obj[0]) obj[0].placeholder = el;
|
||||
else if (obj[el]) obj[el].insertAdjacentHTML('afterend', ' '+txt);
|
||||
}
|
||||
// load settings and insert values into DOM
|
||||
function ldS() {
|
||||
@ -161,7 +197,8 @@
|
||||
}
|
||||
if (urows==="") urows = "Usermods configuration not found.<br>Press <i>Save</i> to initialize defaults.";
|
||||
gId("um").innerHTML = urows;
|
||||
GetV();
|
||||
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=8';
|
||||
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
})
|
||||
.catch((error)=>{
|
||||
gId('lserr').style.display = "inline";
|
||||
@ -172,7 +209,6 @@
|
||||
e.preventDefault();
|
||||
if (d.Sf.checkValidity()) d.Sf.submit(); //https://stackoverflow.com/q/37323914
|
||||
}
|
||||
function GetV() {} // replaced during 'npm run build'
|
||||
</script>
|
||||
<style>@import url("style.css");</style>
|
||||
</head>
|
||||
@ -186,6 +222,15 @@
|
||||
<span id="lserr" style="color:red; display:none">⚠ Could not load configuration.</span><hr>
|
||||
</div>
|
||||
<h2>Usermod Setup</h2>
|
||||
Global I<sup>2</sup>C GPIOs (HW)<br>
|
||||
<i style="color: orange;">(only changable on ESP32, change requires reboot!)</i><br>
|
||||
SDA:<input type="number" min="-1" max="33" name="SDA" onchange="check(this,'if')" class="s" placeholder="SDA">
|
||||
SCL:<input type="number" min="-1" max="33" name="SCL" onchange="check(this,'if')" class="s" placeholder="SCL">
|
||||
<hr style="width:260px">
|
||||
Global SPI GPIOs (HW)<br>
|
||||
<i style="color: orange;">(only changable on ESP32, change requires reboot!)</i><br>
|
||||
MOSI:<input type="number" min="-1" max="33" name="MOSI" onchange="check(this,'if')" class="s" placeholder="MOSI">
|
||||
SCLK:<input type="number" min="-1" max="33" name="SCLK" onchange="check(this,'if')" class="s" placeholder="SCLK">
|
||||
<div id="um">Loading settings...</div>
|
||||
<hr><button type="button" onclick="B()">Back</button><button type="submit">Save</button>
|
||||
</form>
|
||||
|
@ -6,16 +6,44 @@
|
||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
|
||||
<title>WiFi Settings</title>
|
||||
<script>
|
||||
var d=document;
|
||||
var loc = false, locip;
|
||||
function H(){window.open("https://kno.wled.ge/features/settings/#wifi-settings");}
|
||||
function B(){window.open("/settings","_self");}
|
||||
function GetV()
|
||||
{
|
||||
//values injected by server while sending HTML
|
||||
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||
function loadJS(FILE_URL, async = true) {
|
||||
let scE = d.createElement("script");
|
||||
scE.setAttribute("src", FILE_URL);
|
||||
scE.setAttribute("type", "text/javascript");
|
||||
scE.setAttribute("async", async);
|
||||
d.body.appendChild(scE);
|
||||
// success event
|
||||
scE.addEventListener("load", () => {
|
||||
//console.log("File loaded");
|
||||
GetV();
|
||||
});
|
||||
// error event
|
||||
scE.addEventListener("error", (ev) => {
|
||||
console.log("Error on loading file", ev);
|
||||
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||
});
|
||||
}
|
||||
function S() {
|
||||
if (window.location.protocol == "file:") {
|
||||
loc = true;
|
||||
locip = localStorage.getItem('locIp');
|
||||
if (!locip) {
|
||||
locip = prompt("File Mode. Please enter WLED IP!");
|
||||
localStorage.setItem('locIp', locip);
|
||||
}
|
||||
}
|
||||
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=1';
|
||||
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
}
|
||||
</script>
|
||||
<style>@import url("style.css");</style>
|
||||
</head>
|
||||
<body onload="GetV()">
|
||||
<body onload="S()">
|
||||
<form id="form_s" name="Sf" method="post">
|
||||
<div class="toprow">
|
||||
<div class="helpB"><button type="button" onclick="H()">?</button></div>
|
||||
|
@ -644,7 +644,7 @@ function populateEffects()
|
||||
|
||||
for (let i = 0; i < effects.length; i++) {
|
||||
// WLEDSR: add slider and color control to setEffect (used by requestjson)
|
||||
if (effects[i].name.indexOf("Reserved") < 0) {
|
||||
if (effects[i].name.indexOf("RSVD") < 0) {
|
||||
var posAt = effects[i].name.indexOf("@");
|
||||
var extra = '';
|
||||
if (posAt > 0)
|
||||
|
@ -154,7 +154,7 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, byte protocol){
|
||||
DMXOldDimmer = e131_data[dataOffset+0];
|
||||
bri = e131_data[dataOffset+0];
|
||||
}
|
||||
if (e131_data[dataOffset+1] < MODE_COUNT)
|
||||
if (e131_data[dataOffset+1] < strip.getModeCount())
|
||||
effectCurrent = e131_data[dataOffset+ 1];
|
||||
effectSpeed = e131_data[dataOffset+ 2]; // flickers
|
||||
effectIntensity = e131_data[dataOffset+ 3];
|
||||
|
@ -58,21 +58,23 @@ bool getJsonValue(const JsonVariant& element, DestType& destination, const Defau
|
||||
|
||||
|
||||
//colors.cpp
|
||||
uint32_t color_blend(uint32_t,uint32_t,uint16_t,bool b16=false);
|
||||
uint32_t color_add(uint32_t,uint32_t);
|
||||
inline uint32_t colorFromRgbw(byte* rgbw) { return uint32_t((byte(rgbw[3]) << 24) | (byte(rgbw[0]) << 16) | (byte(rgbw[1]) << 8) | (byte(rgbw[2]))); }
|
||||
void colorHStoRGB(uint16_t hue, byte sat, byte* rgb); //hue, sat to rgb
|
||||
void colorKtoRGB(uint16_t kelvin, byte* rgb);
|
||||
void colorCTtoRGB(uint16_t mired, byte* rgb); //white spectrum to rgb
|
||||
|
||||
void colorXYtoRGB(float x, float y, byte* rgb); // only defined if huesync disabled TODO
|
||||
void colorRGBtoXY(byte* rgb, float* xy); // only defined if huesync disabled TODO
|
||||
|
||||
void colorFromDecOrHexString(byte* rgb, char* in);
|
||||
bool colorFromHexString(byte* rgb, const char* in);
|
||||
|
||||
uint32_t colorBalanceFromKelvin(uint16_t kelvin, uint32_t rgb);
|
||||
uint16_t approximateKelvinFromRGB(uint32_t rgb);
|
||||
|
||||
void setRandomColor(byte* rgb);
|
||||
uint8_t gamma8_cal(uint8_t b, float gamma);
|
||||
void calcGammaTable(float gamma);
|
||||
uint8_t gamma8(uint8_t b);
|
||||
uint32_t gamma32(uint32_t);
|
||||
|
||||
//dmx.cpp
|
||||
void initDMX();
|
||||
@ -129,7 +131,7 @@ void handleIR();
|
||||
|
||||
void deserializeSegment(JsonObject elem, byte it, byte presetId = 0);
|
||||
bool deserializeState(JsonObject root, byte callMode = CALL_MODE_DIRECT_CHANGE, byte presetId = 0);
|
||||
void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id, bool forPreset = false, bool segmentBounds = true);
|
||||
void serializeSegment(JsonObject& root, Segment& seg, byte id, bool forPreset = false, bool segmentBounds = true);
|
||||
void serializeState(JsonObject root, bool forPreset = false, bool includeBri = true, bool segmentBounds = true);
|
||||
void serializeInfo(JsonObject root);
|
||||
void serializeModeNames(JsonArray arr, const char *qstring);
|
||||
@ -296,7 +298,7 @@ class UsermodManager {
|
||||
void onUpdateBegin(bool);
|
||||
bool add(Usermod* um);
|
||||
Usermod* lookup(uint16_t mod_id);
|
||||
byte getModCount();
|
||||
byte getModCount() {return numMods;};
|
||||
};
|
||||
|
||||
//usermods_list.cpp
|
||||
@ -311,7 +313,7 @@ void userLoop();
|
||||
int getNumVal(const String* req, uint16_t pos);
|
||||
void parseNumber(const char* str, byte* val, byte minv=0, byte maxv=255);
|
||||
bool getVal(JsonVariant elem, byte* val, byte minv=0, byte maxv=255);
|
||||
bool updateVal(const String* req, const char* key, byte* val, byte minv=0, byte maxv=255);
|
||||
bool updateVal(const char* req, const char* key, byte* val, byte minv=0, byte maxv=255);
|
||||
bool oappend(const char* txt); // append new c string to temp buffer efficiently
|
||||
bool oappendi(int i); // append new number to temp buffer efficiently
|
||||
void sappend(char stype, const char* key, int val);
|
||||
@ -321,12 +323,19 @@ bool isAsterisksOnly(const char* str, byte maxLen);
|
||||
bool requestJSONBufferLock(uint8_t module=255);
|
||||
void releaseJSONBufferLock();
|
||||
uint8_t extractModeName(uint8_t mode, const char *src, char *dest, uint8_t maxLen);
|
||||
uint8_t extractModeSlider(uint8_t mode, uint8_t slider, char *dest, uint8_t maxLen, uint8_t *var = nullptr);
|
||||
int16_t extractModeDefaults(uint8_t mode, const char *segVar);
|
||||
uint16_t crc16(const unsigned char* data_p, size_t length);
|
||||
um_data_t* simulateSound(uint8_t simulationId);
|
||||
void enumerateLedmaps();
|
||||
|
||||
#ifdef WLED_ADD_EEPROM_SUPPORT
|
||||
//wled_eeprom.cpp
|
||||
void applyMacro(byte index);
|
||||
void deEEP();
|
||||
void deEEPSettings();
|
||||
void clearEEPROM();
|
||||
#endif
|
||||
|
||||
//wled_math.cpp
|
||||
#ifndef WLED_USE_REAL_MATH
|
||||
|
@ -41,47 +41,47 @@ const char PAGE_dmxmap[] PROGMEM = R"=====()=====";
|
||||
#endif
|
||||
|
||||
// Autogenerated from wled00/data/update.htm, do not edit!!
|
||||
const uint16_t PAGE_update_length = 615;
|
||||
const uint16_t PAGE_update_length = 616;
|
||||
const uint8_t PAGE_update[] PROGMEM = {
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0x75, 0x53, 0x5d, 0x6f, 0xd4, 0x30,
|
||||
0x10, 0x7c, 0xcf, 0xaf, 0x70, 0xfd, 0x74, 0x27, 0x71, 0x4e, 0x29, 0x4f, 0x94, 0x24, 0x85, 0xa3,
|
||||
0x15, 0xaa, 0x84, 0xd4, 0x4a, 0x6d, 0x41, 0x3c, 0x21, 0xc7, 0xde, 0x5c, 0xcc, 0x39, 0x76, 0x6a,
|
||||
0x6f, 0xee, 0x14, 0x55, 0xfd, 0xef, 0x6c, 0x9c, 0xbb, 0x82, 0xf8, 0x78, 0x89, 0xe2, 0xec, 0xec,
|
||||
0x78, 0x77, 0x66, 0x52, 0x9c, 0x5c, 0xde, 0x7c, 0xbc, 0xff, 0x76, 0x7b, 0xc5, 0x5a, 0xec, 0x6c,
|
||||
0x55, 0x1c, 0x9e, 0x20, 0x75, 0x55, 0x74, 0x80, 0x92, 0x29, 0xef, 0x10, 0x1c, 0x96, 0x7c, 0x6f,
|
||||
0x34, 0xb6, 0xa5, 0x86, 0x9d, 0x51, 0xb0, 0x4a, 0x07, 0xce, 0x9c, 0xec, 0xa0, 0xe4, 0x3b, 0x03,
|
||||
0xfb, 0xde, 0x07, 0xe4, 0x55, 0x56, 0xa0, 0x41, 0x0b, 0xd5, 0xd7, 0xcf, 0x57, 0x97, 0xec, 0xa1,
|
||||
0xd7, 0x12, 0xa1, 0xc8, 0xe7, 0x4f, 0x45, 0x54, 0xc1, 0xf4, 0x58, 0x65, 0xcd, 0xe0, 0x14, 0x1a,
|
||||
0xef, 0xd8, 0x7a, 0xb1, 0x7c, 0xda, 0x1b, 0xa7, 0xfd, 0x5e, 0xb4, 0x26, 0xa2, 0x0f, 0xa3, 0xa8,
|
||||
0xa5, 0xda, 0x2e, 0x96, 0xcf, 0x2f, 0x90, 0x07, 0x82, 0x68, 0xaf, 0x86, 0x8e, 0x26, 0x10, 0x1b,
|
||||
0xc0, 0x2b, 0x0b, 0xd3, 0xeb, 0x7a, 0xbc, 0xd6, 0x0b, 0x3e, 0x34, 0x7c, 0x29, 0x22, 0x8e, 0x16,
|
||||
0x84, 0x36, 0xb1, 0xb7, 0x72, 0x2c, 0xb9, 0xf3, 0x0e, 0xf8, 0xab, 0xff, 0xb6, 0x74, 0x71, 0xf3,
|
||||
0x77, 0x4f, 0x6d, 0xbd, 0xda, 0xf2, 0xe7, 0xac, 0xc8, 0x0f, 0x23, 0x1e, 0x46, 0x65, 0x31, 0xa8,
|
||||
0x92, 0xe7, 0x11, 0x10, 0x8d, 0xdb, 0xc4, 0x3c, 0x8a, 0x1f, 0xf1, 0xa2, 0x2f, 0xdf, 0xf2, 0xea,
|
||||
0x37, 0xe4, 0x44, 0x55, 0x65, 0xef, 0x4d, 0x37, 0x09, 0xc0, 0x86, 0x60, 0x17, 0x7c, 0xa6, 0x57,
|
||||
0x31, 0xf2, 0xe5, 0x3b, 0x42, 0x26, 0x44, 0x91, 0xcf, 0x92, 0xd6, 0x5e, 0x8f, 0xcc, 0x3b, 0xeb,
|
||||
0xa5, 0x2e, 0xf9, 0x27, 0xc0, 0x2f, 0x8b, 0x25, 0xd1, 0xb5, 0x67, 0x55, 0x96, 0x24, 0xbb, 0xf3,
|
||||
0x0d, 0xee, 0x65, 0x80, 0x17, 0xed, 0xa8, 0x52, 0x34, 0x3e, 0x74, 0x8c, 0xbc, 0x68, 0x3d, 0xf5,
|
||||
0xdc, 0xde, 0xdc, 0xdd, 0x73, 0x26, 0x93, 0x3c, 0x34, 0xdc, 0x90, 0x70, 0x9c, 0x19, 0x2a, 0x91,
|
||||
0x1e, 0x2c, 0x03, 0x52, 0x6e, 0xec, 0xc9, 0x94, 0x6e, 0xb0, 0x68, 0x7a, 0x19, 0x30, 0x9f, 0xfa,
|
||||
0x57, 0x04, 0x93, 0x9c, 0x6e, 0x8e, 0x43, 0xdd, 0x19, 0x72, 0xf3, 0x61, 0xba, 0xf8, 0xda, 0x45,
|
||||
0x94, 0xd6, 0x82, 0x66, 0x3b, 0x08, 0x91, 0x18, 0xcf, 0x59, 0x11, 0x7b, 0xe9, 0x58, 0xa6, 0xac,
|
||||
0x8c, 0xb1, 0xe4, 0xd1, 0xf4, 0xbc, 0x3a, 0x15, 0xaf, 0xdf, 0x88, 0xb3, 0x55, 0x6d, 0x4f, 0x69,
|
||||
0x1b, 0xaa, 0xd2, 0x16, 0xa1, 0xba, 0xf4, 0xfb, 0xb4, 0x05, 0xc3, 0x16, 0x98, 0xa5, 0x19, 0x22,
|
||||
0xb2, 0xda, 0x38, 0x19, 0x46, 0xe2, 0x90, 0x2c, 0x6b, 0x03, 0x34, 0x25, 0x6f, 0x11, 0xfb, 0x78,
|
||||
0x9e, 0xe7, 0x1b, 0x83, 0xed, 0x50, 0x0b, 0xe5, 0xbb, 0xfc, 0x83, 0x09, 0xca, 0x7b, 0xbf, 0x35,
|
||||
0x90, 0x4f, 0x2b, 0xe7, 0x01, 0x2c, 0xc8, 0x08, 0x91, 0x33, 0x94, 0x81, 0xfc, 0x2a, 0xf9, 0xf7,
|
||||
0xda, 0x4a, 0xb7, 0x25, 0x59, 0x4c, 0xb7, 0x61, 0x59, 0x32, 0xe1, 0xc8, 0x43, 0x5f, 0x44, 0x6c,
|
||||
0x0d, 0x58, 0x1d, 0x85, 0xf1, 0x07, 0xda, 0x23, 0xc5, 0x9f, 0xd4, 0x22, 0xee, 0x36, 0x17, 0x49,
|
||||
0xfe, 0xb2, 0xa1, 0x09, 0x57, 0xf1, 0x71, 0x20, 0x69, 0xa7, 0x90, 0xe6, 0x32, 0xed, 0x50, 0x18,
|
||||
0xd7, 0x0f, 0xc8, 0x66, 0xbd, 0x1a, 0x63, 0xe1, 0x18, 0xe8, 0xa3, 0xaa, 0x01, 0x1e, 0x07, 0x13,
|
||||
0x40, 0xcf, 0xe8, 0x7a, 0x40, 0xa4, 0x4c, 0xce, 0xf0, 0x59, 0x47, 0x22, 0x9b, 0x9d, 0x3a, 0x29,
|
||||
0xf2, 0xb9, 0xfc, 0x0f, 0xe8, 0x7c, 0x98, 0xc4, 0x57, 0xd6, 0xa8, 0x6d, 0xc9, 0xd7, 0x93, 0xf6,
|
||||
0x6b, 0x8a, 0xfa, 0xaf, 0xa6, 0x64, 0x52, 0x55, 0x68, 0xb3, 0xcb, 0x92, 0x97, 0x53, 0x50, 0x89,
|
||||
0xa6, 0x4a, 0xec, 0x94, 0x3e, 0x21, 0x04, 0x81, 0x13, 0xf9, 0x6d, 0x5a, 0x96, 0x69, 0xcf, 0x9c,
|
||||
0x47, 0xa6, 0xac, 0xa7, 0x83, 0x0f, 0x34, 0x6b, 0x13, 0x20, 0xb6, 0xc9, 0x8f, 0x5e, 0x6e, 0x80,
|
||||
0x9d, 0x2f, 0x8b, 0x9c, 0xf8, 0xa6, 0x75, 0xa7, 0xd4, 0x4d, 0x11, 0x9c, 0xfe, 0xed, 0x9f, 0x54,
|
||||
0x34, 0xf6, 0xf4, 0xf1, 0x03, 0x00, 0x00
|
||||
0x10, 0x7c, 0xcf, 0xaf, 0x70, 0xfd, 0x74, 0x27, 0x71, 0x4e, 0x41, 0xbc, 0x50, 0x92, 0x14, 0x8e,
|
||||
0x56, 0xa8, 0x12, 0x52, 0x4f, 0x6a, 0x0b, 0xe2, 0x09, 0x39, 0xf6, 0x26, 0x31, 0xe7, 0xd8, 0xa9,
|
||||
0xbd, 0xb9, 0xd3, 0x09, 0xf5, 0xbf, 0xb3, 0x71, 0xee, 0x0a, 0xe2, 0xe3, 0x25, 0x8a, 0xb3, 0xb3,
|
||||
0xe3, 0xdd, 0x99, 0x49, 0x71, 0x76, 0x75, 0xfb, 0xe1, 0xfe, 0xeb, 0xe6, 0x9a, 0x75, 0xd8, 0xdb,
|
||||
0xaa, 0x38, 0x3e, 0x41, 0xea, 0xaa, 0xe8, 0x01, 0x25, 0x53, 0xde, 0x21, 0x38, 0x2c, 0xf9, 0xde,
|
||||
0x68, 0xec, 0x4a, 0x0d, 0x3b, 0xa3, 0x60, 0x95, 0x0e, 0x9c, 0x39, 0xd9, 0x43, 0xc9, 0x77, 0x06,
|
||||
0xf6, 0x83, 0x0f, 0xc8, 0xab, 0xac, 0x40, 0x83, 0x16, 0xaa, 0x2f, 0x9f, 0xae, 0xaf, 0xd8, 0xc3,
|
||||
0xa0, 0x25, 0x42, 0x91, 0xcf, 0x9f, 0x8a, 0xa8, 0x82, 0x19, 0xb0, 0xca, 0x9a, 0xd1, 0x29, 0x34,
|
||||
0xde, 0xb1, 0xf5, 0x62, 0xf9, 0x63, 0x6f, 0x9c, 0xf6, 0x7b, 0xd1, 0x99, 0x88, 0x3e, 0x1c, 0x44,
|
||||
0x2d, 0xd5, 0x76, 0xb1, 0x7c, 0x7a, 0x86, 0x3c, 0x10, 0x44, 0x7b, 0x35, 0xf6, 0x34, 0x81, 0x68,
|
||||
0x01, 0xaf, 0x2d, 0x4c, 0xaf, 0xeb, 0xc3, 0x8d, 0x5e, 0xf0, 0xb1, 0xe1, 0x4b, 0x11, 0xf1, 0x60,
|
||||
0x41, 0x68, 0x13, 0x07, 0x2b, 0x0f, 0x25, 0x77, 0xde, 0x01, 0x7f, 0xf1, 0xdf, 0x96, 0x3e, 0xb6,
|
||||
0x7f, 0xf7, 0xd4, 0xd6, 0xab, 0x2d, 0x7f, 0xca, 0x8a, 0xfc, 0x38, 0xe2, 0x71, 0x54, 0x16, 0x83,
|
||||
0x2a, 0x79, 0x1e, 0x01, 0xd1, 0xb8, 0x36, 0xe6, 0x51, 0x7c, 0x8f, 0x97, 0x43, 0xf9, 0x86, 0x57,
|
||||
0xbf, 0x21, 0x27, 0xaa, 0x2a, 0x7b, 0x67, 0xfa, 0x49, 0x00, 0x36, 0x06, 0xbb, 0xe0, 0x33, 0xbd,
|
||||
0x8a, 0x91, 0x2f, 0xdf, 0x12, 0x32, 0x21, 0x8a, 0x7c, 0x96, 0xb4, 0xf6, 0xfa, 0xc0, 0xbc, 0xb3,
|
||||
0x5e, 0xea, 0x92, 0x7f, 0x04, 0xfc, 0xbc, 0x58, 0x12, 0x5d, 0xf7, 0xaa, 0xca, 0x92, 0x64, 0x77,
|
||||
0xbe, 0xc1, 0xbd, 0x0c, 0xf0, 0xac, 0x1d, 0x55, 0x8a, 0xc6, 0x87, 0x9e, 0x91, 0x17, 0x9d, 0xa7,
|
||||
0x9e, 0xcd, 0xed, 0xdd, 0x3d, 0x67, 0x32, 0xc9, 0x43, 0xc3, 0x8d, 0x09, 0xc7, 0x99, 0xa1, 0x12,
|
||||
0xe9, 0xc1, 0x32, 0x20, 0xe5, 0x0e, 0x03, 0x99, 0xd2, 0x8f, 0x16, 0xcd, 0x20, 0x03, 0xe6, 0x53,
|
||||
0xff, 0x8a, 0x60, 0x92, 0xd3, 0xcd, 0x71, 0xac, 0x7b, 0x43, 0x6e, 0x3e, 0x4c, 0x17, 0xdf, 0xb8,
|
||||
0x88, 0xd2, 0x5a, 0xd0, 0x6c, 0x07, 0x21, 0x12, 0xe3, 0x05, 0x2b, 0xe2, 0x20, 0x1d, 0xcb, 0x94,
|
||||
0x95, 0x31, 0x96, 0x3c, 0x9a, 0x81, 0x57, 0xe7, 0xe2, 0xe5, 0x6b, 0x71, 0xbe, 0xaa, 0xed, 0x39,
|
||||
0x6d, 0x43, 0x55, 0xda, 0x22, 0x54, 0x57, 0x7e, 0x9f, 0xb6, 0x60, 0xd8, 0x01, 0xb3, 0x34, 0x43,
|
||||
0x44, 0x56, 0x1b, 0x27, 0xc3, 0x81, 0x38, 0x24, 0xcb, 0xba, 0x00, 0x4d, 0xc9, 0x3b, 0xc4, 0x21,
|
||||
0x5e, 0xe4, 0x79, 0x6b, 0xb0, 0x1b, 0x6b, 0xa1, 0x7c, 0x9f, 0xbf, 0x37, 0x41, 0x79, 0xef, 0xb7,
|
||||
0x06, 0xf2, 0x69, 0xe5, 0x3c, 0x80, 0x05, 0x19, 0x21, 0x72, 0x86, 0x32, 0x90, 0x5f, 0x25, 0xff,
|
||||
0x56, 0x5b, 0xe9, 0xb6, 0x24, 0x8b, 0xe9, 0x5b, 0x96, 0x25, 0x13, 0x4e, 0x3c, 0xf4, 0x45, 0xc4,
|
||||
0xce, 0x80, 0xd5, 0x51, 0x18, 0x7f, 0xa4, 0x3d, 0x51, 0xfc, 0x49, 0x2d, 0xe2, 0xae, 0xbd, 0x4c,
|
||||
0xf2, 0x97, 0x0d, 0x4d, 0xb8, 0x8a, 0x8f, 0x23, 0x49, 0x3b, 0x85, 0x34, 0x97, 0x69, 0x87, 0xc2,
|
||||
0xb8, 0x61, 0x44, 0x36, 0xeb, 0xd5, 0x18, 0x0b, 0xa7, 0x40, 0x9f, 0x54, 0x0d, 0xf0, 0x38, 0x9a,
|
||||
0x00, 0x7a, 0x46, 0xd7, 0x23, 0x22, 0x65, 0x72, 0x86, 0xcf, 0x3a, 0x12, 0xd9, 0xec, 0xd4, 0x59,
|
||||
0x91, 0xcf, 0xe5, 0x7f, 0x40, 0xe7, 0xc3, 0x24, 0xbe, 0xb2, 0x46, 0x6d, 0x4b, 0xbe, 0x9e, 0xb4,
|
||||
0x5f, 0x53, 0xd4, 0x7f, 0x35, 0x25, 0x93, 0xaa, 0x42, 0x9b, 0x5d, 0x96, 0xbc, 0x9c, 0x82, 0x4a,
|
||||
0x34, 0x55, 0x62, 0xa7, 0xf4, 0x09, 0x21, 0x08, 0x9c, 0xc8, 0x37, 0x69, 0x59, 0xa6, 0x3d, 0x73,
|
||||
0x1e, 0x99, 0xb2, 0x9e, 0x0e, 0x3e, 0xd0, 0xac, 0x4d, 0x80, 0xd8, 0x25, 0x3f, 0x06, 0xd9, 0x02,
|
||||
0xbb, 0x58, 0x16, 0x39, 0xf1, 0x4d, 0xeb, 0x4e, 0xa9, 0x9b, 0x22, 0x38, 0xfd, 0xdb, 0x3f, 0x01,
|
||||
0xce, 0x0e, 0xa3, 0x73, 0xf1, 0x03, 0x00, 0x00
|
||||
};
|
||||
|
||||
|
||||
@ -229,55 +229,111 @@ const uint8_t PAGE_liveview[] PROGMEM = {
|
||||
|
||||
|
||||
// Autogenerated from wled00/data/liveviewws.htm, do not edit!!
|
||||
const uint16_t PAGE_liveviewws_length = 740;
|
||||
const uint16_t PAGE_liveviewws_length = 711;
|
||||
const uint8_t PAGE_liveviewws[] PROGMEM = {
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0x75, 0x54, 0x5d, 0x6f, 0xdb, 0x38,
|
||||
0x10, 0x7c, 0xf7, 0xaf, 0x50, 0x99, 0x4b, 0x2a, 0xc1, 0xb2, 0xec, 0xa4, 0x68, 0xd3, 0x93, 0x44,
|
||||
0x07, 0xfd, 0xf0, 0x43, 0x0f, 0xc1, 0x35, 0x40, 0x52, 0x04, 0x87, 0x20, 0x40, 0x29, 0x69, 0x2d,
|
||||
0xf1, 0x22, 0x91, 0x02, 0xb9, 0xb2, 0x60, 0x18, 0xfa, 0xef, 0xb7, 0x94, 0x1d, 0xe7, 0xee, 0xda,
|
||||
0xfa, 0x41, 0x22, 0xcd, 0xdd, 0x9d, 0xd9, 0x19, 0xae, 0xd2, 0x57, 0x9f, 0xbf, 0x7e, 0xba, 0xfb,
|
||||
0xeb, 0x66, 0xe5, 0x55, 0xd8, 0xd4, 0xcb, 0xf4, 0xf0, 0x04, 0x51, 0x2c, 0xd3, 0x06, 0x50, 0x78,
|
||||
0x4a, 0x34, 0xc0, 0xd9, 0x46, 0x42, 0xdf, 0x6a, 0x83, 0xcc, 0x9b, 0xe4, 0x5a, 0x21, 0x28, 0xe4,
|
||||
0xac, 0x97, 0x05, 0x56, 0xbc, 0x80, 0x8d, 0xcc, 0x61, 0x36, 0x6e, 0x42, 0xa9, 0x24, 0x4a, 0x51,
|
||||
0xcf, 0x6c, 0x2e, 0x6a, 0xe0, 0xe7, 0x61, 0x43, 0x7f, 0x34, 0x5d, 0xf3, 0xbc, 0x67, 0x87, 0x9a,
|
||||
0x93, 0xbc, 0x12, 0xc6, 0x02, 0xd5, 0xe8, 0x70, 0x3d, 0x7b, 0xcf, 0xfe, 0x03, 0x85, 0x15, 0x34,
|
||||
0x30, 0xcb, 0x75, 0xad, 0x0d, 0xf3, 0x8e, 0x60, 0x27, 0x17, 0xe3, 0x8f, 0x42, 0x51, 0x62, 0x0d,
|
||||
0xcb, 0xc9, 0xfd, 0xf5, 0xea, 0xb3, 0x77, 0x2d, 0x37, 0xe0, 0xdd, 0x18, 0x70, 0xf4, 0xd2, 0xf9,
|
||||
0xfe, 0x24, 0xb5, 0xb8, 0x75, 0x01, 0x99, 0x2e, 0xb6, 0xbb, 0x46, 0x98, 0x52, 0xaa, 0x78, 0x31,
|
||||
0x9c, 0xe4, 0x42, 0x6d, 0x76, 0x99, 0xc8, 0x9f, 0x4a, 0xa3, 0x3b, 0x55, 0xc4, 0x27, 0x8b, 0xc5,
|
||||
0x22, 0x59, 0xcb, 0x1a, 0xc1, 0xc4, 0x99, 0x91, 0x65, 0x85, 0x0a, 0xac, 0xf5, 0xcf, 0x2f, 0xdf,
|
||||
0x9e, 0x06, 0xc9, 0xd8, 0x4d, 0x7c, 0xbe, 0x58, 0x9c, 0x26, 0x15, 0xb8, 0xb3, 0xfd, 0xba, 0xd5,
|
||||
0x96, 0xfa, 0xd3, 0x2a, 0x16, 0x99, 0xd5, 0x75, 0x87, 0x30, 0x4c, 0xd2, 0xf9, 0x1e, 0x2e, 0x9d,
|
||||
0xef, 0x35, 0x73, 0xa8, 0xcb, 0xb4, 0x90, 0x1b, 0x4f, 0x16, 0x9c, 0x39, 0x50, 0xa2, 0x6c, 0x73,
|
||||
0x23, 0x5b, 0x5c, 0x4e, 0xd6, 0x9d, 0xca, 0x5d, 0xbe, 0xd7, 0xb5, 0x85, 0x40, 0x38, 0x10, 0xf7,
|
||||
0x21, 0xd8, 0x6d, 0x84, 0xf1, 0x14, 0x67, 0xb5, 0x54, 0x20, 0xcc, 0xac, 0x34, 0xa2, 0x90, 0xd4,
|
||||
0xb6, 0xff, 0xfb, 0xa2, 0x80, 0x32, 0x64, 0x21, 0x72, 0x88, 0x6a, 0x50, 0x25, 0x56, 0xc9, 0x5a,
|
||||
0x1b, 0x5f, 0xf2, 0x8b, 0x44, 0xa6, 0x98, 0xc8, 0x29, 0x7f, 0x13, 0xa8, 0x29, 0xff, 0x6e, 0xca,
|
||||
0xcc, 0xff, 0x6d, 0x07, 0x0f, 0xf2, 0x71, 0x08, 0xc7, 0xf7, 0xf4, 0xfc, 0xb8, 0xba, 0x78, 0x1c,
|
||||
0x82, 0xef, 0x21, 0x85, 0xcf, 0xde, 0x9c, 0x9d, 0xf9, 0x14, 0xcd, 0x42, 0x16, 0x24, 0xee, 0x1d,
|
||||
0xb0, 0xb0, 0xd0, 0x79, 0xd7, 0x10, 0x52, 0x54, 0x02, 0xae, 0x6a, 0x70, 0xcb, 0x8f, 0xdb, 0x2f,
|
||||
0x85, 0xbf, 0x67, 0x1e, 0x44, 0x63, 0x73, 0xd1, 0x8b, 0x6c, 0x5c, 0x0d, 0xc7, 0x26, 0x28, 0xc5,
|
||||
0xe9, 0xff, 0x87, 0xd5, 0xca, 0xb5, 0x80, 0x66, 0xbb, 0x93, 0x6b, 0x9f, 0x3d, 0xe8, 0xec, 0x6f,
|
||||
0xc8, 0xd1, 0xfb, 0x60, 0x8c, 0xd8, 0x7e, 0xec, 0xd6, 0x6b, 0x30, 0x8f, 0x8c, 0x73, 0x8e, 0xfa,
|
||||
0x16, 0x8d, 0x54, 0x65, 0x44, 0x77, 0xa1, 0xf6, 0x21, 0x22, 0x05, 0x44, 0x10, 0xec, 0x6a, 0x40,
|
||||
0x0f, 0xb8, 0x82, 0xde, 0xfb, 0x26, 0x15, 0xbe, 0x1f, 0xb3, 0x7c, 0xd8, 0x38, 0x4e, 0x63, 0x44,
|
||||
0x42, 0x35, 0x2f, 0xdf, 0xbd, 0xe2, 0xf0, 0xb0, 0x78, 0x0c, 0x0c, 0x60, 0x67, 0x54, 0xf2, 0x7f,
|
||||
0xf9, 0x86, 0x21, 0x17, 0x98, 0x57, 0x8e, 0x05, 0x5d, 0x18, 0xb2, 0x06, 0x22, 0x30, 0x86, 0x84,
|
||||
0x62, 0x37, 0x00, 0x4f, 0xde, 0xfd, 0xad, 0x37, 0x6e, 0x63, 0x16, 0xba, 0x58, 0xa7, 0x75, 0x6f,
|
||||
0x13, 0xc7, 0xb7, 0xb7, 0x44, 0xab, 0x8d, 0x7a, 0xa9, 0x0a, 0xdd, 0x47, 0xbd, 0x7d, 0xa9, 0x33,
|
||||
0xf4, 0xf6, 0xec, 0xac, 0xb7, 0x91, 0x21, 0x57, 0xb7, 0xb7, 0x48, 0x70, 0xd4, 0xc2, 0x3d, 0x64,
|
||||
0xb7, 0x3a, 0x7f, 0x02, 0x8c, 0xbe, 0xde, 0xac, 0xfe, 0xbc, 0xf2, 0x9f, 0xc1, 0xa4, 0x5a, 0xeb,
|
||||
0x03, 0x56, 0x67, 0xc1, 0x7a, 0x54, 0x93, 0x40, 0x59, 0x10, 0x52, 0x01, 0x0b, 0x8a, 0xe4, 0xdc,
|
||||
0xbd, 0xae, 0x37, 0xaf, 0x63, 0x34, 0x1d, 0x0c, 0x2c, 0x08, 0xe2, 0x9f, 0x65, 0x12, 0x4b, 0xdd,
|
||||
0x82, 0x22, 0x85, 0x28, 0xd1, 0x27, 0x66, 0x4e, 0x93, 0x23, 0xa2, 0xef, 0xb3, 0x0a, 0xb1, 0xb5,
|
||||
0x31, 0x49, 0x79, 0xa0, 0x5b, 0x6b, 0x62, 0x4b, 0x46, 0x44, 0xad, 0xd1, 0xa8, 0x69, 0x60, 0xae,
|
||||
0x58, 0x6f, 0x2d, 0x8b, 0xe9, 0xc9, 0x82, 0x29, 0x8b, 0xe7, 0x73, 0x36, 0x3d, 0xfa, 0x7b, 0x0c,
|
||||
0xae, 0xb4, 0xc5, 0x29, 0x9b, 0xbb, 0x98, 0x20, 0xd2, 0xca, 0x41, 0xf2, 0x67, 0x4b, 0xfd, 0x17,
|
||||
0xfd, 0x7e, 0x24, 0xf6, 0xcb, 0x76, 0x86, 0xf1, 0x20, 0x93, 0x4a, 0x98, 0xed, 0xdd, 0xb6, 0xa5,
|
||||
0x11, 0x16, 0xce, 0xc4, 0x6c, 0xb4, 0x9e, 0xb9, 0x33, 0x51, 0x14, 0x2b, 0xe7, 0xe8, 0xb5, 0xb4,
|
||||
0x34, 0xcd, 0x40, 0xbe, 0x34, 0x34, 0x6b, 0xa2, 0x04, 0x16, 0xfe, 0xeb, 0x12, 0x05, 0x6e, 0x98,
|
||||
0xf6, 0x93, 0x92, 0xce, 0xf7, 0x73, 0x34, 0x1f, 0x3f, 0x47, 0xff, 0x00, 0xeb, 0x0e, 0x42, 0x19,
|
||||
0xa4, 0x04, 0x00, 0x00
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0x6d, 0x54, 0x5d, 0x8f, 0x9b, 0x3a,
|
||||
0x10, 0x7d, 0xcf, 0xaf, 0xa0, 0xde, 0xdb, 0x2d, 0x56, 0x08, 0x24, 0xdb, 0xdb, 0x2f, 0xc0, 0x59,
|
||||
0xb5, 0xb7, 0x79, 0xa8, 0xb4, 0x6a, 0x57, 0xda, 0x5e, 0xad, 0xaa, 0x55, 0xa4, 0x1a, 0x98, 0x80,
|
||||
0xef, 0x82, 0x1d, 0xd9, 0x43, 0x50, 0x84, 0xf8, 0xef, 0x77, 0x20, 0xdb, 0xac, 0x2a, 0x95, 0x07,
|
||||
0xdb, 0xc3, 0x9c, 0x99, 0x33, 0x33, 0x3e, 0x90, 0xbe, 0xf8, 0xfc, 0xed, 0x9f, 0xef, 0x3f, 0x6e,
|
||||
0x37, 0x5e, 0x85, 0x4d, 0xbd, 0x4e, 0x9f, 0x56, 0x90, 0xc5, 0x3a, 0x6d, 0x00, 0xa5, 0xa7, 0x65,
|
||||
0x03, 0x82, 0x1d, 0x14, 0x74, 0x7b, 0x63, 0x91, 0x79, 0xb3, 0xdc, 0x68, 0x04, 0x8d, 0x82, 0x75,
|
||||
0xaa, 0xc0, 0x4a, 0x14, 0x70, 0x50, 0x39, 0x2c, 0x26, 0x23, 0x50, 0x5a, 0xa1, 0x92, 0xf5, 0xc2,
|
||||
0xe5, 0xb2, 0x06, 0xb1, 0x0a, 0x1a, 0x7a, 0xd1, 0xb4, 0xcd, 0x2f, 0x9b, 0x3d, 0xe5, 0x9c, 0xe5,
|
||||
0x95, 0xb4, 0x0e, 0x28, 0x47, 0x8b, 0xbb, 0xc5, 0x7b, 0xf6, 0x1b, 0x15, 0x56, 0xd0, 0xc0, 0x22,
|
||||
0x37, 0xb5, 0xb1, 0xcc, 0x3b, 0x93, 0x5d, 0x5c, 0x4d, 0x0f, 0x41, 0x51, 0x61, 0x0d, 0xeb, 0xd9,
|
||||
0xfd, 0xcd, 0xe6, 0xb3, 0x77, 0xa3, 0x0e, 0xe0, 0xdd, 0x5a, 0x18, 0xcb, 0x4b, 0xa3, 0x93, 0x27,
|
||||
0x75, 0x78, 0x1c, 0x01, 0x99, 0x29, 0x8e, 0x7d, 0x23, 0x6d, 0xa9, 0x74, 0xbc, 0x1c, 0x2e, 0x72,
|
||||
0xa9, 0x0f, 0x7d, 0x26, 0xf3, 0xc7, 0xd2, 0x9a, 0x56, 0x17, 0xf1, 0xc5, 0x72, 0xb9, 0x4c, 0x76,
|
||||
0xaa, 0x46, 0xb0, 0x71, 0x66, 0x55, 0x59, 0xa1, 0x06, 0xe7, 0xfc, 0xd5, 0xbb, 0x37, 0x2f, 0x79,
|
||||
0x32, 0x75, 0x13, 0xaf, 0x96, 0xcb, 0x97, 0x49, 0x05, 0xa3, 0xef, 0x74, 0xde, 0x1b, 0x47, 0xfd,
|
||||
0x19, 0x1d, 0xcb, 0xcc, 0x99, 0xba, 0x45, 0x18, 0x66, 0x69, 0x74, 0xa2, 0x4b, 0xa3, 0xd3, 0xcc,
|
||||
0x46, 0xd6, 0x75, 0x5a, 0xa8, 0x83, 0xa7, 0x0a, 0xc1, 0x46, 0x52, 0x2a, 0x39, 0x22, 0x9b, 0xea,
|
||||
0xca, 0xad, 0xda, 0xe3, 0x7a, 0x76, 0x90, 0xd6, 0xeb, 0x5c, 0x82, 0xf6, 0xd8, 0x77, 0x4e, 0xa0,
|
||||
0xd9, 0x87, 0x9d, 0xd2, 0x85, 0xe9, 0xc2, 0xce, 0x0d, 0xb9, 0xc4, 0xbc, 0xf2, 0x81, 0xf7, 0x43,
|
||||
0xe7, 0x2e, 0x2f, 0x3b, 0x17, 0x5a, 0xca, 0x7a, 0xbc, 0x43, 0x89, 0x20, 0x84, 0xb8, 0x87, 0xec,
|
||||
0xce, 0xe4, 0x8f, 0x80, 0xe1, 0xb7, 0xdb, 0xcd, 0xd7, 0x6b, 0x72, 0x3b, 0xd0, 0x85, 0xcf, 0xfa,
|
||||
0x57, 0xf5, 0xe1, 0x55, 0x8c, 0xb6, 0x85, 0x81, 0xf1, 0xd8, 0xa7, 0xa1, 0x51, 0x79, 0x10, 0x2a,
|
||||
0xbd, 0x33, 0x3e, 0xbb, 0x05, 0x78, 0xf4, 0xee, 0xef, 0x3c, 0xb3, 0x07, 0xad, 0x74, 0xc9, 0x78,
|
||||
0xe0, 0x13, 0xad, 0x86, 0xce, 0x3b, 0xa7, 0xf3, 0x7d, 0x56, 0x21, 0xee, 0x5d, 0xcc, 0x84, 0x78,
|
||||
0xaa, 0xa5, 0x36, 0x54, 0x0a, 0xb5, 0x1a, 0xee, 0xad, 0x41, 0x43, 0xb7, 0x71, 0xcd, 0x3a, 0xe7,
|
||||
0x58, 0x4c, 0x2b, 0xe3, 0x73, 0x16, 0x47, 0x11, 0x9b, 0x17, 0x26, 0x6f, 0x1b, 0xba, 0x9d, 0x67,
|
||||
0x70, 0x65, 0x1c, 0xce, 0x59, 0x34, 0x62, 0x78, 0x68, 0xf4, 0x48, 0x29, 0x76, 0xad, 0xce, 0x47,
|
||||
0xa7, 0xcf, 0xfb, 0x3f, 0x17, 0x3c, 0xf0, 0x80, 0x1c, 0x99, 0xd2, 0xd2, 0x1e, 0xbf, 0x1f, 0xf7,
|
||||
0x24, 0x01, 0x69, 0xad, 0x3c, 0x66, 0xed, 0x6e, 0x07, 0x96, 0x8d, 0x3e, 0x59, 0x14, 0x9b, 0x03,
|
||||
0x11, 0xdd, 0x28, 0x47, 0x6a, 0x00, 0xeb, 0xb3, 0x86, 0xee, 0x4a, 0x96, 0xc0, 0x02, 0x10, 0xeb,
|
||||
0x7e, 0x9c, 0xa4, 0xda, 0xf9, 0xec, 0xc1, 0x64, 0xff, 0x41, 0x8e, 0xde, 0xc7, 0x31, 0xfc, 0xd3,
|
||||
0x14, 0xbe, 0xa5, 0x8e, 0x68, 0xc4, 0x77, 0x68, 0xa9, 0xf5, 0x90, 0x54, 0x58, 0xfb, 0x10, 0x16,
|
||||
0x12, 0x25, 0xe7, 0x7d, 0x0d, 0xe8, 0xc1, 0x34, 0x88, 0x7f, 0x95, 0xc6, 0xf7, 0x53, 0x94, 0x0f,
|
||||
0x23, 0xcf, 0x09, 0x91, 0x50, 0xce, 0x77, 0x6f, 0x5f, 0x08, 0x78, 0x58, 0x6e, 0xb9, 0x05, 0x6c,
|
||||
0xad, 0x4e, 0xc6, 0x18, 0x52, 0x63, 0xad, 0x34, 0x48, 0xbb, 0x28, 0xad, 0x2c, 0x14, 0xe1, 0xfd,
|
||||
0x0f, 0xcb, 0x02, 0xca, 0x80, 0x05, 0x5a, 0x40, 0x58, 0x83, 0x2e, 0xe9, 0x53, 0xb0, 0xe2, 0x4a,
|
||||
0x50, 0xe8, 0x6a, 0x7b, 0xfd, 0x77, 0x7c, 0x95, 0xec, 0x8c, 0xf5, 0x95, 0xb0, 0x89, 0x4a, 0x75,
|
||||
0xa2, 0xe6, 0xe2, 0x35, 0xc7, 0xb9, 0xf8, 0x69, 0xcb, 0xcc, 0xff, 0xab, 0x87, 0x07, 0xb5, 0x1d,
|
||||
0x82, 0x69, 0x9f, 0xaf, 0xce, 0xa7, 0xab, 0xed, 0xc0, 0x7f, 0x06, 0x04, 0x5f, 0xbc, 0xbe, 0xbc,
|
||||
0xf4, 0x09, 0xcd, 0x02, 0xc6, 0x93, 0x71, 0xe7, 0x2c, 0x38, 0x0f, 0xbe, 0x04, 0xdc, 0xd4, 0x30,
|
||||
0x1e, 0x3f, 0x1d, 0xbf, 0xd0, 0x5c, 0x27, 0xbd, 0xf1, 0x70, 0x92, 0x64, 0xf8, 0x2c, 0x76, 0x81,
|
||||
0xc3, 0xb3, 0xb2, 0x7e, 0xa9, 0x03, 0xac, 0xa5, 0xa2, 0xce, 0xf2, 0x98, 0xcc, 0x98, 0x06, 0xca,
|
||||
0x87, 0x81, 0x8f, 0xb2, 0x3e, 0xa9, 0x35, 0x8d, 0x4e, 0x8a, 0x8e, 0xa6, 0x1f, 0xc3, 0xff, 0x16,
|
||||
0x7e, 0x9e, 0x8e, 0x2e, 0x04, 0x00, 0x00
|
||||
};
|
||||
|
||||
|
||||
// Autogenerated from wled00/data/liveviewws2D.htm, do not edit!!
|
||||
const uint16_t PAGE_liveviewws2D_length = 818;
|
||||
const uint8_t PAGE_liveviewws2D[] PROGMEM = {
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0x6d, 0x54, 0x6d, 0x6f, 0xdb, 0x36,
|
||||
0x10, 0xfe, 0xee, 0x5f, 0xa1, 0x70, 0x43, 0x2b, 0xda, 0xb2, 0xe4, 0xb8, 0xed, 0x96, 0xd9, 0xa2,
|
||||
0x8b, 0x36, 0x35, 0xb0, 0x02, 0xd9, 0x6a, 0xc0, 0x19, 0x82, 0x21, 0x30, 0x50, 0x5a, 0x3a, 0x5b,
|
||||
0x5c, 0x25, 0xd2, 0xa0, 0xce, 0x96, 0x35, 0x47, 0xff, 0x7d, 0x47, 0xc9, 0xf1, 0x32, 0x74, 0xfa,
|
||||
0x40, 0x91, 0xf7, 0xf2, 0xdc, 0xf1, 0xb9, 0x3b, 0xc6, 0x57, 0x9f, 0xbe, 0xdc, 0xde, 0xff, 0xb9,
|
||||
0x98, 0x7b, 0x19, 0x16, 0xf9, 0x2c, 0x3e, 0xaf, 0x20, 0xd3, 0x59, 0x5c, 0x00, 0x4a, 0x4f, 0xcb,
|
||||
0x02, 0x04, 0x3b, 0x28, 0xa8, 0x76, 0xc6, 0x22, 0xf3, 0x7a, 0x89, 0xd1, 0x08, 0x1a, 0x05, 0xab,
|
||||
0x54, 0x8a, 0x99, 0x48, 0xe1, 0xa0, 0x12, 0x18, 0xb6, 0x87, 0x40, 0x69, 0x85, 0x4a, 0xe6, 0xc3,
|
||||
0x32, 0x91, 0x39, 0x88, 0xeb, 0xa0, 0x20, 0x41, 0xb1, 0x2f, 0x9e, 0xcf, 0xec, 0x8c, 0xd9, 0x4b,
|
||||
0x32, 0x69, 0x4b, 0x20, 0x8c, 0x3d, 0x6e, 0x86, 0x37, 0xec, 0x3f, 0xa1, 0x30, 0x83, 0x02, 0x86,
|
||||
0x89, 0xc9, 0x8d, 0x65, 0xde, 0x25, 0xd8, 0x0f, 0xe3, 0xf6, 0x23, 0x53, 0x54, 0x98, 0xc3, 0xac,
|
||||
0xf7, 0x70, 0x37, 0xff, 0xe4, 0xdd, 0xa9, 0x03, 0x78, 0x0b, 0x0b, 0x2e, 0xbd, 0x38, 0xea, 0x34,
|
||||
0x71, 0x89, 0x35, 0xfd, 0xd6, 0x26, 0xad, 0x4f, 0x85, 0xb4, 0x5b, 0xa5, 0x27, 0xa3, 0x26, 0x8e,
|
||||
0x3a, 0x69, 0x1c, 0x75, 0x57, 0x73, 0xda, 0x59, 0x9c, 0x48, 0x7d, 0x90, 0xa5, 0xd7, 0x53, 0xa9,
|
||||
0x60, 0x6e, 0x4f, 0xe8, 0x51, 0x27, 0x23, 0x94, 0xc4, 0xaa, 0x1d, 0xce, 0x7a, 0x07, 0x69, 0xbd,
|
||||
0x44, 0xa4, 0x26, 0xd9, 0x17, 0x94, 0x48, 0xb8, 0x05, 0x9c, 0xe7, 0xe0, 0xb6, 0x1f, 0xeb, 0xcf,
|
||||
0xa9, 0xdf, 0xb9, 0xf1, 0x20, 0x87, 0xb4, 0x14, 0x8c, 0x05, 0x98, 0x59, 0x83, 0x94, 0x45, 0x2a,
|
||||
0xae, 0xae, 0xa7, 0x9b, 0xbd, 0x4e, 0x50, 0x19, 0xed, 0xd1, 0x55, 0x6f, 0x5b, 0x58, 0x9f, 0x9f,
|
||||
0x92, 0xb0, 0xe3, 0x2d, 0xfc, 0xe5, 0xa6, 0x5f, 0x29, 0x9d, 0x9a, 0x2a, 0x54, 0x5a, 0x83, 0x7d,
|
||||
0x68, 0x09, 0x4c, 0xc2, 0x0c, 0xd4, 0x36, 0xc3, 0xef, 0xd4, 0xbf, 0xb6, 0xe2, 0xe6, 0x05, 0xd2,
|
||||
0xb4, 0xcd, 0x0c, 0x8f, 0x22, 0x71, 0x49, 0xdd, 0x3a, 0xa2, 0x8e, 0xe8, 0xb3, 0x71, 0xca, 0xf8,
|
||||
0x54, 0x6d, 0x7c, 0xd2, 0xf0, 0x93, 0x33, 0xa9, 0xca, 0x29, 0xda, 0xfa, 0x54, 0x95, 0x02, 0xcd,
|
||||
0x2e, 0x3c, 0x63, 0x56, 0x65, 0x93, 0x48, 0x4c, 0x32, 0x1f, 0xf9, 0xa9, 0xa9, 0xca, 0x57, 0xaf,
|
||||
0xaa, 0x32, 0xb4, 0xc4, 0x4c, 0xbd, 0x44, 0x89, 0x20, 0x84, 0x78, 0x80, 0xf5, 0xd2, 0x24, 0xdf,
|
||||
0x00, 0xc3, 0x2f, 0x8b, 0xf9, 0xef, 0xef, 0x49, 0x5d, 0x82, 0xa6, 0xfb, 0x9e, 0x5e, 0xe7, 0x87,
|
||||
0xd7, 0x13, 0xb4, 0x7b, 0x68, 0x18, 0x9f, 0xf8, 0x84, 0xaa, 0xa1, 0xf2, 0x2e, 0xd6, 0xbe, 0xcf,
|
||||
0x32, 0xc4, 0x5d, 0x39, 0x61, 0x42, 0x9c, 0x43, 0xe5, 0x86, 0x22, 0x11, 0x0b, 0xe1, 0x8e, 0xa8,
|
||||
0x31, 0x54, 0xd7, 0xf7, 0xac, 0x2a, 0x4b, 0x36, 0xa1, 0x95, 0xf1, 0x01, 0x9b, 0x44, 0x11, 0x1b,
|
||||
0x5c, 0xe8, 0xbd, 0x18, 0x67, 0xa6, 0xc4, 0x01, 0x8b, 0x9c, 0x0d, 0x0f, 0x8d, 0x36, 0x3b, 0xd0,
|
||||
0xc2, 0xe7, 0x62, 0x76, 0xfa, 0xff, 0x4c, 0x9a, 0x80, 0xe4, 0x6b, 0xa5, 0xa5, 0xad, 0xef, 0xeb,
|
||||
0x1d, 0x75, 0x91, 0xb4, 0x56, 0xd6, 0xeb, 0xfd, 0x66, 0x03, 0x96, 0x39, 0x9d, 0x4c, 0xd3, 0xf9,
|
||||
0x81, 0x22, 0xdc, 0xa9, 0x92, 0x1a, 0x0a, 0xac, 0xcf, 0x0a, 0x28, 0x4b, 0xb9, 0x05, 0xaa, 0x19,
|
||||
0xa1, 0x3a, 0x86, 0x88, 0x34, 0xf6, 0x68, 0xd6, 0x7f, 0x41, 0x82, 0xde, 0x07, 0xe7, 0xfe, 0xb1,
|
||||
0x75, 0x5f, 0xd1, 0x55, 0x88, 0xba, 0x25, 0x5a, 0xa5, 0xb7, 0x21, 0x35, 0x72, 0xee, 0x63, 0x98,
|
||||
0x4a, 0x94, 0x9c, 0x9f, 0x72, 0x40, 0x0f, 0x5b, 0x06, 0xfe, 0x50, 0x1a, 0x6f, 0x5a, 0x2f, 0x1f,
|
||||
0x5c, 0x9c, 0xce, 0xc2, 0x15, 0xe2, 0xe7, 0x9f, 0xae, 0x04, 0x3e, 0x8e, 0x56, 0x4f, 0x4f, 0x63,
|
||||
0xb7, 0xb9, 0xa6, 0xcd, 0x95, 0x2b, 0x8e, 0x05, 0xdc, 0x5b, 0x3d, 0x75, 0x10, 0x96, 0xe4, 0xe3,
|
||||
0x55, 0xa0, 0xe9, 0xf7, 0x66, 0x15, 0x18, 0xf1, 0x9b, 0xc4, 0x2c, 0xa4, 0xd9, 0xf1, 0xcf, 0xcd,
|
||||
0x12, 0xd9, 0x4b, 0x63, 0x44, 0x9a, 0x07, 0xb2, 0x33, 0xd8, 0xe4, 0xc6, 0x58, 0xff, 0xd9, 0x66,
|
||||
0x68, 0xfa, 0x96, 0x47, 0xe3, 0xae, 0x2d, 0x40, 0xbc, 0x9d, 0x6e, 0x48, 0x59, 0x8b, 0xf0, 0xdd,
|
||||
0xb4, 0x8e, 0xf5, 0xb4, 0x1e, 0x0c, 0xb8, 0x13, 0x1c, 0x9d, 0xe0, 0x18, 0xdb, 0xe9, 0x91, 0x04,
|
||||
0x94, 0x45, 0xb8, 0x51, 0x79, 0xbe, 0x74, 0xa3, 0x21, 0xbe, 0xda, 0xed, 0xda, 0xff, 0xf1, 0x84,
|
||||
0x8f, 0xb0, 0x6a, 0x82, 0xf6, 0x3f, 0xb8, 0xbe, 0xec, 0xc6, 0xab, 0x86, 0x7f, 0x0d, 0x9c, 0xc3,
|
||||
0x1a, 0x68, 0xa2, 0x16, 0x14, 0xdf, 0xe7, 0xed, 0x59, 0xda, 0xc4, 0x3f, 0xf6, 0xcd, 0x40, 0x06,
|
||||
0x75, 0xdf, 0x04, 0xe1, 0x5b, 0x5a, 0x46, 0xc1, 0xb8, 0xdf, 0x66, 0xb8, 0xf8, 0xdc, 0xd9, 0xb8,
|
||||
0x20, 0x64, 0x0e, 0x03, 0xf1, 0xa6, 0xf9, 0xb7, 0xef, 0x68, 0xb6, 0x4b, 0x93, 0x43, 0x08, 0xd6,
|
||||
0x52, 0x66, 0x6c, 0x01, 0xf0, 0xcd, 0x7b, 0x58, 0x7a, 0xed, 0x71, 0x42, 0x65, 0xe1, 0x4d, 0xc3,
|
||||
0x9b, 0x73, 0x13, 0x7d, 0x5f, 0x3e, 0x0b, 0xa5, 0xfa, 0xfb, 0xb9, 0x7a, 0xcf, 0x53, 0xf7, 0xf4,
|
||||
0xe4, 0xbf, 0x98, 0x90, 0x97, 0xd3, 0x38, 0x0a, 0x48, 0x71, 0xaf, 0x0a, 0x30, 0x7b, 0x6a, 0x52,
|
||||
0xfe, 0xd2, 0x89, 0x46, 0xb5, 0x09, 0xc6, 0xef, 0x46, 0x9c, 0x37, 0xbc, 0x47, 0x0f, 0x45, 0x37,
|
||||
0xf8, 0x71, 0xd4, 0xbd, 0x11, 0x51, 0xfb, 0x22, 0xfe, 0x03, 0x69, 0xb3, 0xce, 0x95, 0x27, 0x05,
|
||||
0x00, 0x00
|
||||
};
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
// Autogenerated from wled00/data/simple.htm, do not edit!!
|
||||
const uint16_t PAGE_simple_L = 17882;
|
||||
const uint16_t PAGE_simple_L = 17880;
|
||||
const uint8_t PAGE_simple[] PROGMEM = {
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0xcd, 0x7d, 0xe9, 0x7a, 0xe2, 0xba,
|
||||
0xb2, 0xe8, 0xff, 0x3c, 0x05, 0xed, 0xde, 0x3b, 0x8d, 0x37, 0x0e, 0x98, 0x79, 0x6a, 0xd2, 0x9b,
|
||||
@ -871,260 +871,260 @@ const uint8_t PAGE_simple[] PROGMEM = {
|
||||
0xd3, 0xfd, 0xd5, 0x98, 0x6b, 0x6a, 0x0d, 0x1f, 0xe8, 0x36, 0x29, 0x4c, 0x06, 0xfb, 0x01, 0x56,
|
||||
0x2e, 0xc2, 0xf8, 0xec, 0x3a, 0x02, 0x94, 0xf8, 0x0e, 0x06, 0x84, 0x27, 0x32, 0x48, 0x1c, 0x3d,
|
||||
0x9a, 0x85, 0x0e, 0x07, 0x11, 0xf0, 0x1d, 0xf4, 0x84, 0xf1, 0x2a, 0x12, 0x8e, 0x54, 0x44, 0xc5,
|
||||
0x1c, 0x83, 0x15, 0x69, 0x13, 0xf4, 0x56, 0xcd, 0xcb, 0x5e, 0x92, 0xc3, 0x03, 0x0d, 0xf6, 0x18,
|
||||
0x64, 0x20, 0xff, 0x5d, 0xf4, 0x97, 0xfe, 0x9a, 0x62, 0xff, 0x46, 0xef, 0x2b, 0x0e, 0xda, 0xdc,
|
||||
0x15, 0x7f, 0x38, 0xa1, 0x12, 0xce, 0x48, 0x06, 0xbd, 0x36, 0x69, 0xf2, 0x35, 0xb3, 0x51, 0xad,
|
||||
0x56, 0x51, 0x1b, 0xe8, 0xe3, 0x96, 0x1a, 0xa0, 0x0e, 0x69, 0x1e, 0x5d, 0xa6, 0x47, 0xee, 0x50,
|
||||
0x4f, 0x72, 0xbd, 0x29, 0x90, 0x22, 0x56, 0xd3, 0x54, 0x61, 0xa5, 0xba, 0x08, 0x0a, 0xbe, 0x80,
|
||||
0xf2, 0x84, 0xa1, 0x1b, 0x77, 0x5b, 0xf0, 0x7f, 0x50, 0x12, 0x29, 0xa1, 0xfa, 0x47, 0xf0, 0xde,
|
||||
0xd7, 0xb3, 0x96, 0xae, 0x38, 0xdf, 0x32, 0xc4, 0xb9, 0xfa, 0xff, 0x64, 0x9a, 0xbc, 0x5d, 0x79,
|
||||
0x9c, 0xa3, 0x40, 0x07, 0xf4, 0xfb, 0xc3, 0x74, 0x38, 0x12, 0xde, 0x7a, 0xdf, 0x88, 0x46, 0xcf,
|
||||
0xdf, 0x89, 0xb8, 0x34, 0x3d, 0x5c, 0x9a, 0x0c, 0x97, 0x42, 0xe8, 0xf0, 0x17, 0x27, 0x7c, 0x7b,
|
||||
0xef, 0xbc, 0x17, 0x30, 0x3e, 0x66, 0x8f, 0xfb, 0x07, 0xe6, 0xd6, 0x23, 0x36, 0xb2, 0x89, 0x9c,
|
||||
0x64, 0x41, 0x47, 0x64, 0x6d, 0x94, 0xec, 0x57, 0x0f, 0x52, 0x82, 0xde, 0xf7, 0xcb, 0xbd, 0x8b,
|
||||
0xea, 0x39, 0x1b, 0x32, 0xe2, 0x36, 0x8d, 0xae, 0x30, 0xe8, 0x35, 0x8e, 0xc3, 0x61, 0x29, 0xf1,
|
||||
0x30, 0xd9, 0xa0, 0xeb, 0x7c, 0x1d, 0x37, 0xa8, 0x1c, 0xb6, 0xd3, 0x89, 0xc8, 0xf1, 0xfa, 0xd5,
|
||||
0x72, 0x1c, 0xa0, 0x3e, 0x7e, 0x11, 0xde, 0x9c, 0x0b, 0xe7, 0xb1, 0x5d, 0x96, 0xf0, 0xf1, 0x8b,
|
||||
0xe5, 0x6e, 0xdd, 0x32, 0xed, 0x27, 0xa1, 0x42, 0xe7, 0x8b, 0xeb, 0xef, 0xbe, 0xf8, 0x77, 0x14,
|
||||
0x24, 0x58, 0x08, 0x6f, 0xb6, 0x01, 0xe2, 0x89, 0x0d, 0x02, 0xbd, 0x04, 0x40, 0x14, 0x0d, 0xf4,
|
||||
0x58, 0x09, 0xd1, 0x88, 0x0e, 0x4c, 0xe7, 0xbd, 0x7c, 0xc8, 0x6d, 0x80, 0xba, 0xc3, 0xf3, 0x51,
|
||||
0xf7, 0x11, 0xc3, 0xa1, 0x58, 0x27, 0xdf, 0x7d, 0x78, 0x75, 0x82, 0x48, 0xa1, 0xb6, 0x32, 0x28,
|
||||
0xec, 0x2e, 0xf6, 0x84, 0xae, 0x60, 0x41, 0x17, 0x24, 0xc1, 0x6e, 0x7c, 0xc9, 0x62, 0xc7, 0xa2,
|
||||
0xed, 0x38, 0x3c, 0x6f, 0x37, 0xd0, 0x91, 0x94, 0x81, 0x16, 0xfe, 0x05, 0x86, 0x8e, 0xc0, 0x7c,
|
||||
0x49, 0x82, 0x0e, 0x5f, 0xb9, 0x5f, 0x82, 0x04, 0x5f, 0xf9, 0x5f, 0x75, 0xea, 0x42, 0x81, 0xca,
|
||||
0x9c, 0x0d, 0x4a, 0x80, 0xc3, 0x1b, 0xd8, 0x1f, 0xcf, 0x82, 0xa7, 0xb7, 0x1e, 0xa1, 0x7b, 0x7b,
|
||||
0x4d, 0x9a, 0xb4, 0x9a, 0x16, 0x80, 0x0a, 0x0e, 0xb4, 0xf8, 0xd4, 0x80, 0xcd, 0xee, 0x64, 0xeb,
|
||||
0xd0, 0xbe, 0x9f, 0x03, 0x03, 0x40, 0xcc, 0xe8, 0xd1, 0x94, 0x2c, 0xed, 0x55, 0x38, 0x25, 0xf7,
|
||||
0x6b, 0xf1, 0x05, 0xd0, 0xda, 0xb0, 0x01, 0x61, 0x76, 0x83, 0x64, 0x7c, 0x7c, 0xe0, 0x78, 0x02,
|
||||
0xb7, 0xd7, 0x6f, 0x8c, 0xaa, 0x40, 0x65, 0x4a, 0x40, 0x83, 0x5b, 0x40, 0x5b, 0x9c, 0x07, 0x79,
|
||||
0x67, 0x2f, 0xfe, 0xf9, 0x9b, 0xf7, 0x34, 0xa0, 0xdf, 0xa1, 0x2b, 0x9b, 0x12, 0x1b, 0xef, 0x6c,
|
||||
0xc2, 0x08, 0xb3, 0x67, 0x53, 0xa3, 0x41, 0x0d, 0xf5, 0xdf, 0x51, 0x6a, 0xa1, 0xcb, 0xec, 0x92,
|
||||
0xbe, 0xdf, 0x24, 0x58, 0x68, 0x54, 0x13, 0xf2, 0x77, 0x27, 0xd9, 0xbb, 0x4f, 0x96, 0x3a, 0x2a,
|
||||
0x59, 0xb0, 0x1d, 0x48, 0x50, 0x28, 0x69, 0x4e, 0x78, 0xf3, 0x71, 0xed, 0xb2, 0xa5, 0x1b, 0x9e,
|
||||
0x82, 0x83, 0xbe, 0x18, 0x4e, 0x40, 0x37, 0x09, 0x20, 0x23, 0xbc, 0xfd, 0x19, 0xf7, 0xea, 0xe1,
|
||||
0x60, 0x43, 0xe7, 0x40, 0xb1, 0x2d, 0xef, 0x27, 0x34, 0xd8, 0x60, 0x2e, 0x09, 0x50, 0x73, 0x5a,
|
||||
0x4c, 0xcd, 0x41, 0x35, 0xc0, 0xf7, 0xf0, 0xc5, 0x4c, 0x92, 0xd0, 0xed, 0xdf, 0xdc, 0xaa, 0x85,
|
||||
0xb3, 0xf4, 0xdf, 0x51, 0x5d, 0x1b, 0x37, 0x54, 0x99, 0x3a, 0xbd, 0x34, 0x74, 0x3c, 0xc5, 0x1a,
|
||||
0xa7, 0x60, 0xa9, 0x2c, 0x07, 0x83, 0x0d, 0xab, 0xbe, 0x6c, 0xa1, 0xa1, 0xaf, 0xfe, 0x4b, 0x23,
|
||||
0xb0, 0x74, 0x49, 0x7a, 0x20, 0x39, 0x4d, 0xd7, 0xb5, 0x35, 0x50, 0xad, 0x48, 0x92, 0x03, 0x2b,
|
||||
0x80, 0xe3, 0x41, 0x13, 0x95, 0xfc, 0x24, 0xea, 0x15, 0x63, 0xd7, 0x9c, 0xd4, 0x80, 0xec, 0x04,
|
||||
0xb3, 0xc1, 0xec, 0x76, 0x9a, 0x92, 0x71, 0xeb, 0x49, 0x73, 0x69, 0xb4, 0xc2, 0x32, 0xff, 0x5e,
|
||||
0x14, 0x99, 0xce, 0x94, 0xf3, 0x3d, 0x5d, 0xbf, 0xd7, 0xbf, 0x1c, 0x30, 0x74, 0x05, 0x3f, 0x1d,
|
||||
0xd7, 0x3f, 0x85, 0xd0, 0x0d, 0xcc, 0x2c, 0x85, 0xff, 0x0d, 0x7c, 0x9d, 0xbd, 0x8b, 0x0e, 0xf5,
|
||||
0x87, 0x4d, 0xc7, 0x35, 0x62, 0x66, 0x07, 0x06, 0x12, 0xae, 0x04, 0x7a, 0x34, 0x1c, 0xcf, 0xa3,
|
||||
0x1b, 0x01, 0xb8, 0x09, 0x76, 0x10, 0x99, 0xc8, 0xcc, 0x11, 0x0a, 0x12, 0x7d, 0xc0, 0x49, 0x23,
|
||||
0xec, 0x19, 0xf5, 0xee, 0x7e, 0x09, 0x91, 0x6a, 0x38, 0x34, 0x85, 0x06, 0xab, 0xa7, 0xd9, 0x31,
|
||||
0xbf, 0xbf, 0xdb, 0x66, 0x28, 0x08, 0x84, 0x81, 0x4e, 0x72, 0xf1, 0x77, 0x07, 0x86, 0xb7, 0x54,
|
||||
0x97, 0x9e, 0x5a, 0x7f, 0x63, 0x97, 0x9e, 0x78, 0xe1, 0xa8, 0x03, 0xfa, 0x43, 0xe9, 0xba, 0x2e,
|
||||
0xe2, 0xc4, 0x3b, 0x83, 0x86, 0x1b, 0xc3, 0x01, 0x30, 0xdc, 0x4b, 0xf8, 0x0f, 0x81, 0x01, 0x19,
|
||||
0x46, 0x4e, 0xb2, 0xed, 0x8a, 0x3e, 0x39, 0x52, 0xf3, 0xcc, 0xfa, 0xc7, 0x3c, 0x92, 0xbd, 0x30,
|
||||
0x7f, 0xf3, 0x75, 0xb0, 0xe7, 0xdc, 0x10, 0x54, 0x49, 0x55, 0xc3, 0x20, 0x85, 0xe4, 0xa6, 0xba,
|
||||
0xaf, 0xba, 0x0c, 0x46, 0xde, 0xbb, 0x95, 0x17, 0x71, 0x14, 0xe2, 0x5e, 0x0e, 0x8b, 0x46, 0x09,
|
||||
0xdf, 0x98, 0x1b, 0x8e, 0x49, 0xc1, 0x43, 0x7f, 0xd4, 0x33, 0xa0, 0x8d, 0x09, 0x0d, 0xe7, 0x60,
|
||||
0x08, 0xa7, 0x96, 0x98, 0xce, 0x76, 0xe4, 0xe9, 0x97, 0x87, 0x17, 0x3e, 0x08, 0xe9, 0x63, 0xf8,
|
||||
0x0a, 0xe7, 0x51, 0x9c, 0xf9, 0xd5, 0x10, 0x75, 0xc0, 0x50, 0x1a, 0xa1, 0xd3, 0x7f, 0x40, 0x46,
|
||||
0x60, 0xe3, 0xca, 0x36, 0x91, 0x5e, 0x16, 0xbe, 0x52, 0x80, 0x57, 0x35, 0x84, 0x75, 0x82, 0x6f,
|
||||
0x1b, 0xaf, 0x6d, 0xa0, 0x27, 0xdd, 0xbf, 0xa5, 0xf4, 0x20, 0x5e, 0x02, 0x8d, 0x4b, 0xd4, 0x34,
|
||||
0x1b, 0x22, 0xdb, 0x34, 0xdc, 0xde, 0x26, 0x2b, 0x1d, 0xf5, 0x26, 0x75, 0x4d, 0x27, 0xc9, 0xba,
|
||||
0x4e, 0xb6, 0xa7, 0xe1, 0x3e, 0x7a, 0x2a, 0x6a, 0xb8, 0xc1, 0x88, 0x9a, 0x0a, 0x9a, 0x54, 0x83,
|
||||
0xf2, 0x88, 0x06, 0x0d, 0x24, 0xf0, 0xf4, 0xc7, 0xcf, 0x8d, 0x28, 0xb8, 0xed, 0xe2, 0x5b, 0x2a,
|
||||
0xda, 0x40, 0x48, 0x4d, 0x5d, 0xc4, 0xcd, 0xfd, 0xd0, 0xa5, 0xaf, 0xbc, 0xbf, 0x5b, 0xb7, 0x92,
|
||||
0xcb, 0xee, 0x72, 0xd9, 0x9c, 0xbf, 0xbc, 0x9e, 0x84, 0xf7, 0xfa, 0xcc, 0x2e, 0xd7, 0x8a, 0x9f,
|
||||
0x10, 0x62, 0x3b, 0x11, 0xf1, 0x63, 0x42, 0xac, 0x02, 0x5e, 0x51, 0x15, 0x2f, 0xaf, 0x28, 0xee,
|
||||
0xda, 0xc2, 0x2f, 0x6b, 0xa1, 0xd3, 0xd2, 0xb4, 0x54, 0xcd, 0xab, 0x14, 0xde, 0x9e, 0x89, 0xa9,
|
||||
0x83, 0x7e, 0x56, 0x97, 0x0e, 0x00, 0xb4, 0x6e, 0x8f, 0x21, 0xc7, 0x0f, 0xdc, 0x18, 0x1f, 0x9f,
|
||||
0xab, 0x62, 0x04, 0x11, 0x21, 0x06, 0x4a, 0x05, 0xd1, 0xde, 0x39, 0xb1, 0x91, 0x84, 0xe2, 0x4d,
|
||||
0x86, 0x56, 0x27, 0x2c, 0xb1, 0x13, 0x04, 0x37, 0xd6, 0x8c, 0x1f, 0xa0, 0xb0, 0xe3, 0x83, 0x1f,
|
||||
0x85, 0xf3, 0x83, 0xfb, 0xbf, 0x50, 0x37, 0x01, 0x46, 0x2b, 0xcb, 0xe7, 0x63, 0x2a, 0x3c, 0xd5,
|
||||
0xdb, 0xd6, 0x94, 0xa6, 0xc9, 0x06, 0x8b, 0xe8, 0x10, 0x85, 0xb9, 0x31, 0x1a, 0x12, 0x5b, 0x53,
|
||||
0x6a, 0x5f, 0xc4, 0x05, 0x5f, 0x0b, 0x76, 0x4b, 0x97, 0xbd, 0xf1, 0x03, 0x97, 0xe7, 0x13, 0xe7,
|
||||
0xcf, 0x9f, 0x64, 0x12, 0xa3, 0xdd, 0xc8, 0x24, 0x11, 0x04, 0xc4, 0xc1, 0x4c, 0x39, 0xd4, 0x86,
|
||||
0xa6, 0x26, 0x35, 0x33, 0xa4, 0x57, 0x6e, 0x73, 0x36, 0x1d, 0x97, 0x9a, 0x13, 0x60, 0x5e, 0x4f,
|
||||
0x1c, 0x3c, 0x28, 0x86, 0x2e, 0x6a, 0xc7, 0xc1, 0x80, 0x79, 0x3f, 0x28, 0xdf, 0x0d, 0x87, 0xaa,
|
||||
0x10, 0xaa, 0x4a, 0xf3, 0x4c, 0x87, 0xa5, 0x3e, 0x76, 0x7e, 0x1e, 0x89, 0x15, 0x0c, 0x6d, 0x1a,
|
||||
0xf3, 0x42, 0xe8, 0xc7, 0x32, 0x12, 0xcf, 0x3b, 0xe7, 0x1b, 0x84, 0x04, 0xaf, 0x5a, 0xdb, 0x7f,
|
||||
0x2d, 0xda, 0x51, 0xe7, 0x39, 0x4f, 0xf5, 0x05, 0xfd, 0x1e, 0xac, 0xf2, 0xba, 0xf9, 0x23, 0xb0,
|
||||
0xd0, 0x1b, 0xa6, 0x10, 0xda, 0xc8, 0xf3, 0xce, 0x36, 0x6f, 0x6f, 0x47, 0x36, 0xbd, 0x40, 0xda,
|
||||
0x83, 0x4d, 0x19, 0xd8, 0xf4, 0x18, 0x5d, 0x48, 0x83, 0x0b, 0x93, 0x78, 0x92, 0x00, 0xbe, 0x7f,
|
||||
0x78, 0xdf, 0x35, 0x17, 0x38, 0xac, 0x30, 0x41, 0x07, 0x36, 0x0d, 0x30, 0xa4, 0x08, 0xfa, 0xcb,
|
||||
0x81, 0x99, 0x7f, 0x31, 0x28, 0xd1, 0x6b, 0xd0, 0xb4, 0x88, 0x41, 0xdb, 0x9b, 0xa0, 0x47, 0x19,
|
||||
0x23, 0x95, 0xe6, 0xdf, 0xc6, 0xdf, 0x6a, 0xae, 0x3d, 0x02, 0x15, 0x11, 0x57, 0xcc, 0xab, 0x73,
|
||||
0x46, 0xfa, 0x92, 0x8e, 0xf1, 0xf9, 0x2b, 0xf8, 0x0c, 0xc7, 0x3b, 0x2c, 0x47, 0xe7, 0x87, 0x97,
|
||||
0xe2, 0x4c, 0x12, 0xcf, 0x1a, 0x41, 0x1b, 0x00, 0x8f, 0x81, 0x13, 0x74, 0xd2, 0xc7, 0x79, 0x0e,
|
||||
0xd3, 0x13, 0x20, 0x4f, 0xb6, 0x35, 0xc1, 0xd0, 0x9b, 0xe8, 0xee, 0xd3, 0xa9, 0x37, 0x5f, 0xdf,
|
||||
0x1f, 0xd9, 0xec, 0x97, 0x3a, 0xb2, 0xe1, 0xe7, 0x8d, 0xe4, 0xfd, 0x74, 0x59, 0xd1, 0xb6, 0xa4,
|
||||
0x12, 0x96, 0x80, 0x2f, 0x1f, 0xa7, 0xdb, 0x97, 0x5d, 0x18, 0x04, 0x24, 0x8d, 0x54, 0xcb, 0xa0,
|
||||
0x03, 0x8a, 0x1d, 0x09, 0x07, 0xfd, 0x42, 0xff, 0x2e, 0xfe, 0xc0, 0x5d, 0xa2, 0x1a, 0x3e, 0xe3,
|
||||
0xf1, 0x6e, 0xd0, 0x42, 0x82, 0x57, 0xf7, 0x64, 0xb2, 0xa2, 0x37, 0xe7, 0x22, 0x0d, 0x9f, 0x5e,
|
||||
0xb3, 0x05, 0x12, 0x13, 0xed, 0xab, 0x7b, 0x1f, 0xcc, 0x48, 0xa4, 0xdb, 0x88, 0xb8, 0x77, 0x81,
|
||||
0x6c, 0x80, 0x80, 0x94, 0x32, 0x41, 0xc7, 0x62, 0x12, 0xc0, 0x49, 0xa5, 0x16, 0xbe, 0xb6, 0xe5,
|
||||
0xed, 0x6e, 0x20, 0xb2, 0x0c, 0x3f, 0x8e, 0x2b, 0xe4, 0x64, 0xba, 0x30, 0x13, 0x7e, 0xd3, 0x9e,
|
||||
0x5f, 0x89, 0x2e, 0xe2, 0xa5, 0x18, 0xae, 0x07, 0x26, 0x49, 0xc3, 0xc0, 0xe3, 0xaa, 0xde, 0x3e,
|
||||
0xe6, 0x9a, 0x70, 0xf0, 0x90, 0xf5, 0xe6, 0x07, 0xc9, 0x83, 0xdd, 0x43, 0x76, 0xd1, 0x96, 0xdb,
|
||||
0xd9, 0xf1, 0x7c, 0x98, 0x82, 0x2d, 0x68, 0x82, 0x52, 0x97, 0x18, 0x30, 0xcf, 0x12, 0xb2, 0x97,
|
||||
0xbf, 0xc0, 0x0a, 0xd2, 0x96, 0xbf, 0xc0, 0x52, 0x63, 0xfc, 0x1c, 0xcf, 0x43, 0x2c, 0x93, 0x31,
|
||||
0xf6, 0x1d, 0x1f, 0xde, 0x0b, 0x34, 0xe7, 0x52, 0x52, 0x8a, 0x13, 0xb8, 0x94, 0x4d, 0x3f, 0x35,
|
||||
0xdc, 0x9b, 0x5a, 0xc2, 0x62, 0x97, 0x00, 0x00, 0x84, 0xa5, 0xea, 0xac, 0x60, 0x18, 0xed, 0x32,
|
||||
0x24, 0x1d, 0xcf, 0xfb, 0xf3, 0x28, 0xa7, 0x43, 0xc4, 0x74, 0x1f, 0x90, 0x92, 0x57, 0x1f, 0x0b,
|
||||
0xfd, 0x12, 0x0c, 0xdc, 0x97, 0xde, 0xde, 0xa6, 0x5f, 0xbb, 0x54, 0xb2, 0x86, 0xea, 0x34, 0x83,
|
||||
0x3a, 0x34, 0x9f, 0x17, 0x56, 0x45, 0x5e, 0x90, 0xef, 0x4c, 0x85, 0xf5, 0x02, 0x2f, 0x28, 0xa1,
|
||||
0x4d, 0x05, 0x92, 0xa6, 0xe1, 0xb6, 0xdb, 0xdb, 0x22, 0x18, 0x11, 0xec, 0x99, 0xa1, 0x56, 0x45,
|
||||
0x87, 0x89, 0xef, 0x38, 0xf7, 0x33, 0x98, 0x87, 0x5c, 0xac, 0xd1, 0xcb, 0x70, 0x7d, 0x77, 0xe2,
|
||||
0x10, 0xbd, 0xf3, 0x89, 0x5e, 0xb0, 0x5d, 0xf8, 0x85, 0x63, 0x74, 0xe3, 0xf9, 0xd3, 0xb3, 0x58,
|
||||
0x1a, 0x37, 0xc4, 0x89, 0x61, 0x8e, 0xfa, 0x83, 0x04, 0x7d, 0x7b, 0x11, 0xc6, 0x11, 0x3a, 0xd2,
|
||||
0x98, 0x24, 0x58, 0xac, 0x5d, 0xac, 0x4a, 0xae, 0x16, 0x5c, 0xcb, 0x47, 0x5b, 0xf0, 0x7c, 0xb3,
|
||||
0x91, 0x32, 0x79, 0x2c, 0x73, 0xae, 0x39, 0x0e, 0xbe, 0xeb, 0xe1, 0xf8, 0x9a, 0x7a, 0x2f, 0x63,
|
||||
0x45, 0xaa, 0x58, 0xa4, 0x19, 0xea, 0x59, 0x82, 0x0e, 0x23, 0x01, 0x16, 0x52, 0xc2, 0x54, 0x60,
|
||||
0xa1, 0xa1, 0x5b, 0x78, 0x11, 0xa2, 0x5e, 0xca, 0x2c, 0xe8, 0x5e, 0x24, 0x2d, 0x98, 0xe2, 0x6a,
|
||||
0xf0, 0x43, 0xa5, 0xb1, 0x42, 0xe1, 0xeb, 0x1b, 0x0c, 0x90, 0x01, 0x7a, 0xf8, 0x76, 0x07, 0x23,
|
||||
0xdd, 0x9b, 0x86, 0xc3, 0x86, 0x10, 0x7f, 0x21, 0x56, 0x94, 0xad, 0x87, 0xd8, 0xce, 0x32, 0xda,
|
||||
0x3f, 0x14, 0x25, 0xf9, 0xd7, 0xb9, 0xe7, 0x17, 0xf2, 0xe7, 0x4f, 0xd0, 0x04, 0x3f, 0x0f, 0x09,
|
||||
0x18, 0x10, 0x81, 0x61, 0x71, 0x13, 0x62, 0xa7, 0xd1, 0x18, 0x2c, 0x21, 0x4f, 0xf2, 0xbc, 0xef,
|
||||
0x1c, 0xa3, 0x9c, 0xd8, 0x6c, 0x7c, 0xe4, 0x74, 0x76, 0x34, 0xdc, 0xa4, 0xf8, 0x38, 0xfc, 0x1c,
|
||||
0x74, 0x10, 0xf2, 0x83, 0xb3, 0x40, 0xa8, 0x72, 0xcc, 0x33, 0x8d, 0x67, 0xd7, 0x93, 0x5f, 0xa0,
|
||||
0x1e, 0x72, 0x32, 0xe8, 0x21, 0x18, 0x5b, 0x0d, 0xe6, 0x75, 0xc6, 0xad, 0xf4, 0x70, 0x10, 0x36,
|
||||
0x8a, 0xc2, 0xb4, 0x61, 0x4e, 0x92, 0x3c, 0x06, 0x5b, 0x50, 0x43, 0x20, 0x16, 0x3f, 0x4b, 0x78,
|
||||
0x9f, 0x73, 0x61, 0x54, 0x05, 0x3d, 0x01, 0x07, 0xfc, 0x1b, 0x96, 0xdb, 0x0f, 0x5f, 0x28, 0x00,
|
||||
0x0e, 0xbe, 0xcd, 0xb9, 0x31, 0xc7, 0xe4, 0xc2, 0x37, 0xbe, 0x86, 0x61, 0xa8, 0xd8, 0x72, 0x44,
|
||||
0xba, 0x84, 0xe6, 0x42, 0xc8, 0xa1, 0x0b, 0x84, 0x39, 0xde, 0xcd, 0xc0, 0xa7, 0x6e, 0x08, 0x78,
|
||||
0x92, 0x8d, 0xe0, 0xa5, 0x14, 0x18, 0x07, 0x8f, 0x36, 0xfd, 0x0e, 0x6e, 0x4e, 0xc0, 0x98, 0xf0,
|
||||
0x88, 0x94, 0xc6, 0x74, 0x07, 0x8a, 0x99, 0x3a, 0x5e, 0xb5, 0x6a, 0x23, 0xc7, 0xbe, 0xbd, 0x69,
|
||||
0xef, 0x54, 0xb8, 0x85, 0x80, 0x6f, 0x2a, 0xa9, 0xb9, 0x7f, 0x33, 0x10, 0x2e, 0xf9, 0xbf, 0xac,
|
||||
0x4a, 0xf4, 0x79, 0xbc, 0x5d, 0xe0, 0x07, 0xea, 0xe1, 0x8a, 0x02, 0x6a, 0x10, 0x9d, 0x31, 0x8d,
|
||||
0xaa, 0x0c, 0x4b, 0x95, 0x82, 0xa5, 0x7c, 0xac, 0x57, 0xf8, 0x15, 0x78, 0x3e, 0xa4, 0x53, 0x10,
|
||||
0x4f, 0xa7, 0xf0, 0xbe, 0x6b, 0x24, 0x2a, 0xbc, 0xf9, 0x5a, 0x78, 0x59, 0xe2, 0x8d, 0x0d, 0xb0,
|
||||
0x74, 0x1c, 0x0b, 0x0c, 0x07, 0xc2, 0x8e, 0x1d, 0xfc, 0xbd, 0xed, 0x86, 0x55, 0xe3, 0xde, 0x7b,
|
||||
0x4d, 0x4a, 0xe4, 0x18, 0xce, 0xdc, 0x34, 0x6a, 0xec, 0x16, 0x18, 0xfc, 0x0c, 0x6b, 0x0d, 0xe1,
|
||||
0x2b, 0x92, 0xe6, 0xde, 0xb5, 0x30, 0x60, 0x8a, 0x86, 0x2f, 0xc1, 0x11, 0x92, 0xfe, 0xc5, 0x31,
|
||||
0xec, 0x9b, 0x8f, 0x5d, 0x93, 0xe1, 0x1d, 0x3f, 0xc5, 0xbb, 0xb5, 0xfc, 0x69, 0x08, 0xee, 0x2e,
|
||||
0x6f, 0xb0, 0x2a, 0x3f, 0xb8, 0xd0, 0x1d, 0xe6, 0xf8, 0x0a, 0x20, 0x20, 0xb8, 0x50, 0x0a, 0xbe,
|
||||
0x6f, 0x8b, 0xf7, 0xcc, 0x0a, 0xff, 0x55, 0x2c, 0x51, 0x5b, 0x96, 0x01, 0x59, 0x5a, 0xb3, 0xf1,
|
||||
0x01, 0xf8, 0x3b, 0x4d, 0xfe, 0x74, 0x85, 0x87, 0x85, 0xfd, 0xf7, 0xae, 0xbb, 0xf1, 0x1e, 0x78,
|
||||
0x76, 0xf0, 0xcb, 0x1f, 0x1f, 0x0b, 0xf6, 0xa2, 0xbb, 0x4f, 0xeb, 0x06, 0x40, 0x8b, 0xfd, 0xe5,
|
||||
0x11, 0x5c, 0x78, 0xf0, 0xc2, 0xa3, 0xf0, 0x20, 0xad, 0x1d, 0x06, 0x7b, 0x09, 0x8a, 0x1f, 0x70,
|
||||
0xe9, 0x15, 0x01, 0x36, 0x14, 0x02, 0xd9, 0xea, 0x84, 0xe1, 0xd5, 0x37, 0xe6, 0x20, 0xa7, 0xc2,
|
||||
0x15, 0xcd, 0x60, 0xb0, 0x4e, 0x79, 0x17, 0xc2, 0xc7, 0xcd, 0x35, 0x12, 0x37, 0xd6, 0x68, 0xe1,
|
||||
0xf1, 0x5a, 0xd3, 0x6e, 0x7d, 0x59, 0xff, 0x66, 0xf1, 0x8f, 0x4a, 0xfb, 0x7b, 0x16, 0xec, 0x97,
|
||||
0x3f, 0x30, 0x76, 0x4d, 0x70, 0xac, 0x6e, 0x7d, 0x73, 0x56, 0x23, 0x6e, 0x5d, 0x46, 0x31, 0x18,
|
||||
0x0a, 0x90, 0xf1, 0x7d, 0x2d, 0x64, 0xa1, 0x38, 0x90, 0xf5, 0x9b, 0x4f, 0x7b, 0xa1, 0x1a, 0xf5,
|
||||
0x65, 0x8e, 0x99, 0xfd, 0xbd, 0x06, 0xfe, 0xaa, 0xad, 0xeb, 0x95, 0xce, 0xfd, 0xfe, 0x7c, 0x6f,
|
||||
0xbc, 0x70, 0x11, 0x12, 0x5b, 0x87, 0xa0, 0x6c, 0xd6, 0xe8, 0x1e, 0x11, 0x0a, 0xdb, 0xda, 0x72,
|
||||
0xab, 0x9f, 0xa0, 0x38, 0x5e, 0xf6, 0x71, 0xb1, 0x88, 0xde, 0x4d, 0x11, 0xb9, 0x1c, 0x33, 0x7c,
|
||||
0x26, 0x22, 0x7c, 0x5d, 0xa2, 0xd7, 0xb9, 0xfa, 0xb2, 0x7b, 0x4b, 0x64, 0x07, 0x69, 0x6b, 0xe7,
|
||||
0x30, 0x74, 0x3b, 0x66, 0x7c, 0x84, 0x1e, 0x16, 0xd6, 0x40, 0xda, 0xde, 0x5e, 0xd7, 0x03, 0xfa,
|
||||
0x16, 0x35, 0xd0, 0xcc, 0xcc, 0x3b, 0x8d, 0x4c, 0x92, 0x73, 0x99, 0x0c, 0xa4, 0xb1, 0x66, 0xda,
|
||||
0x35, 0xce, 0x19, 0x9a, 0x26, 0x06, 0xae, 0x51, 0x40, 0x35, 0xff, 0xd2, 0xdc, 0xd8, 0x38, 0xc3,
|
||||
0x17, 0x8d, 0x86, 0x87, 0xb9, 0xda, 0xc1, 0xbf, 0x31, 0xca, 0x35, 0xb8, 0xfa, 0xfc, 0x30, 0xa3,
|
||||
0x3d, 0xf8, 0x0f, 0x46, 0xb9, 0x0c, 0xc4, 0xd9, 0x4c, 0x1b, 0xc0, 0xad, 0xbf, 0xf8, 0xf1, 0x3d,
|
||||
0xe4, 0xd7, 0x62, 0xb5, 0x3a, 0x06, 0xcc, 0x6c, 0xae, 0x0e, 0xa6, 0x59, 0x2d, 0x50, 0xdb, 0xc3,
|
||||
0x34, 0x46, 0xc3, 0x49, 0x02, 0xa7, 0x70, 0x14, 0x2a, 0xdb, 0x36, 0x45, 0xaf, 0x1b, 0x3f, 0x8f,
|
||||
0xcd, 0x84, 0xb0, 0xda, 0x4e, 0x6f, 0x5a, 0x0b, 0x9d, 0x54, 0x8b, 0xc3, 0xf2, 0xef, 0x8f, 0xf4,
|
||||
0xf5, 0xc1, 0x38, 0x05, 0xaf, 0x01, 0x08, 0x93, 0x53, 0x23, 0x71, 0x38, 0xf4, 0x9d, 0x47, 0xd1,
|
||||
0x51, 0xae, 0x8c, 0x6d, 0xd5, 0x8e, 0xe5, 0xe3, 0xf8, 0x62, 0x17, 0x1e, 0xaf, 0xc1, 0x96, 0x33,
|
||||
0x5d, 0x0b, 0x2b, 0x62, 0x76, 0xac, 0x0c, 0x2e, 0x74, 0xdd, 0xef, 0xba, 0x09, 0x58, 0x0f, 0x72,
|
||||
0xc5, 0x56, 0x59, 0x01, 0x8b, 0x97, 0xc2, 0xc5, 0xa7, 0x14, 0xef, 0x14, 0x23, 0x71, 0xdc, 0xb2,
|
||||
0x68, 0xec, 0x80, 0xcf, 0xcd, 0xd1, 0x8e, 0x5e, 0xd4, 0x23, 0xe7, 0xca, 0x70, 0xff, 0x10, 0xcc,
|
||||
0x77, 0xaa, 0x8f, 0x86, 0xb4, 0x0e, 0xff, 0x3d, 0x72, 0x96, 0x7f, 0x98, 0xcd, 0x3f, 0xe5, 0xe6,
|
||||
0xc5, 0x28, 0xd2, 0xf0, 0xc4, 0xc8, 0xdc, 0xb8, 0x91, 0xb6, 0x03, 0xdb, 0x0f, 0xc3, 0x8e, 0xf0,
|
||||
0xba, 0x37, 0x52, 0x5f, 0xf2, 0xda, 0xcd, 0xb6, 0xee, 0xca, 0x4e, 0x25, 0x6e, 0x50, 0xae, 0x71,
|
||||
0xbf, 0xd3, 0xf7, 0xa2, 0x73, 0x7c, 0x3d, 0x96, 0x4d, 0x5d, 0xe1, 0x5e, 0x9e, 0x80, 0x08, 0xa0,
|
||||
0x92, 0x2c, 0xe9, 0x6e, 0x34, 0x6f, 0x23, 0x26, 0xe4, 0x8a, 0x49, 0x4a, 0x7e, 0x7d, 0xe8, 0x85,
|
||||
0xa4, 0xd6, 0x0e, 0xea, 0x78, 0x03, 0xe8, 0xfb, 0x32, 0x46, 0xa0, 0xe5, 0xed, 0x4f, 0xd1, 0xf7,
|
||||
0xbf, 0x34, 0x70, 0x83, 0x0a, 0x08, 0x7c, 0x3e, 0xa8, 0x89, 0x82, 0x03, 0x7f, 0x63, 0x7c, 0x6b,
|
||||
0x28, 0x28, 0x71, 0x91, 0xe3, 0x99, 0x41, 0xb8, 0xb3, 0xb7, 0x09, 0x9a, 0x2a, 0x8a, 0x7c, 0x5d,
|
||||
0x35, 0xe7, 0x24, 0x3d, 0x08, 0x17, 0xcb, 0x97, 0x62, 0xe5, 0xf8, 0x05, 0xf4, 0x56, 0x27, 0x49,
|
||||
0x9a, 0x28, 0xc9, 0x18, 0xeb, 0x3c, 0xa0, 0x77, 0x95, 0x0d, 0x70, 0xfb, 0x8a, 0xaf, 0xb3, 0xce,
|
||||
0x41, 0xe2, 0x62, 0x89, 0x10, 0x42, 0xb1, 0xe3, 0xbf, 0xd5, 0x60, 0x65, 0xcf, 0x25, 0x18, 0x9d,
|
||||
0xc7, 0x57, 0xd9, 0x79, 0x72, 0x76, 0x13, 0x17, 0xc8, 0xf0, 0x7a, 0x08, 0x67, 0xd7, 0x21, 0x8f,
|
||||
0x90, 0x1d, 0x46, 0xe6, 0x61, 0x28, 0xa3, 0x1f, 0xf1, 0x22, 0x85, 0x7d, 0x48, 0xf5, 0x30, 0xe8,
|
||||
0x01, 0x99, 0x76, 0xa9, 0x9d, 0xe3, 0x39, 0xc0, 0xe1, 0xc9, 0x0f, 0x31, 0x77, 0x23, 0x5e, 0x82,
|
||||
0xba, 0x8b, 0x51, 0xe2, 0xb8, 0x8d, 0xd4, 0xf5, 0x4a, 0x95, 0x22, 0x27, 0x9d, 0xfd, 0x17, 0xcb,
|
||||
0xe0, 0x59, 0x67, 0xd6, 0x54, 0xb8, 0x19, 0x9a, 0xe2, 0x79, 0x8f, 0x61, 0x4a, 0x22, 0x3d, 0x18,
|
||||
0x81, 0xb0, 0x8d, 0xa4, 0x38, 0x92, 0x3b, 0xb2, 0xa9, 0xa5, 0xe3, 0xcd, 0x1a, 0x18, 0x77, 0x9a,
|
||||
0x6d, 0xa6, 0x5b, 0xac, 0xbc, 0x33, 0xbe, 0x31, 0xf1, 0x7d, 0x18, 0x0e, 0xee, 0x6d, 0x7b, 0xae,
|
||||
0x12, 0x23, 0xcd, 0xdc, 0x24, 0x46, 0xba, 0xef, 0x7d, 0xcb, 0xb8, 0x5a, 0xa0, 0x2f, 0x06, 0x99,
|
||||
0xfa, 0x7b, 0x64, 0x5d, 0x4d, 0xd6, 0xe9, 0x48, 0xd7, 0xdf, 0x52, 0xb2, 0x61, 0x97, 0x11, 0x6f,
|
||||
0x28, 0x4a, 0x88, 0xff, 0x14, 0xe8, 0x8e, 0x2d, 0xff, 0x3b, 0x8c, 0xd6, 0xd3, 0x00, 0xad, 0xe1,
|
||||
0xee, 0xbf, 0x10, 0x7d, 0xac, 0x19, 0x51, 0xa6, 0xe0, 0x93, 0x80, 0xc7, 0x14, 0xd0, 0x6c, 0x0a,
|
||||
0x46, 0x84, 0x1e, 0x33, 0x97, 0xc1, 0xd9, 0x15, 0x7f, 0x44, 0x10, 0x41, 0xf0, 0xf0, 0x46, 0x2d,
|
||||
0x96, 0xd4, 0x62, 0xaf, 0xd8, 0x48, 0x72, 0x80, 0x09, 0x18, 0x2b, 0xfc, 0x85, 0xc9, 0xc9, 0x7b,
|
||||
0x7d, 0xcf, 0xfc, 0xc3, 0x4a, 0x2b, 0x37, 0xdd, 0x2d, 0xa7, 0xd0, 0x67, 0x81, 0x11, 0xa0, 0xa7,
|
||||
0xab, 0x40, 0x93, 0x73, 0x36, 0xd6, 0xda, 0x26, 0x58, 0x01, 0x82, 0x16, 0x31, 0x60, 0xf4, 0x7d,
|
||||
0x26, 0xf3, 0x25, 0x66, 0xbc, 0x20, 0x80, 0x75, 0x44, 0x8e, 0x21, 0x01, 0xeb, 0x68, 0x3c, 0x96,
|
||||
0xbe, 0xb7, 0x6c, 0xea, 0xf7, 0x86, 0x95, 0x16, 0x24, 0x46, 0x94, 0xd0, 0x38, 0x63, 0xcc, 0x02,
|
||||
0xeb, 0xd8, 0xde, 0x8e, 0xde, 0xf5, 0xd0, 0x68, 0xb8, 0x6c, 0x15, 0xac, 0xe7, 0x68, 0xdb, 0xdb,
|
||||
0x1f, 0x62, 0x9b, 0x46, 0x3c, 0xbc, 0x0b, 0x24, 0xbe, 0xe2, 0xd9, 0x32, 0x13, 0x72, 0x5f, 0xb0,
|
||||
0x3b, 0xc9, 0xf0, 0x52, 0x6c, 0xac, 0x93, 0x60, 0x01, 0x23, 0x0d, 0xc2, 0x51, 0x62, 0xf0, 0x04,
|
||||
0x58, 0x79, 0x54, 0x04, 0x42, 0x4a, 0xed, 0xe7, 0x4f, 0x13, 0x58, 0x87, 0x09, 0x5c, 0xc2, 0x4c,
|
||||
0xcb, 0x42, 0x18, 0xf8, 0x2f, 0xe1, 0x27, 0xfe, 0x0f, 0x5a, 0x4d, 0x3d, 0x4b, 0x9b, 0x8e, 0x59,
|
||||
0x04, 0xeb, 0x0d, 0x15, 0x30, 0xd7, 0xd1, 0x13, 0xd2, 0x4f, 0xf7, 0xa6, 0xa0, 0xa0, 0x08, 0x80,
|
||||
0x43, 0x04, 0xf6, 0x23, 0xda, 0x24, 0xc0, 0x7d, 0xaf, 0x55, 0x68, 0xb2, 0x96, 0x63, 0x15, 0xa9,
|
||||
0x8b, 0x25, 0x56, 0xf5, 0xbd, 0xda, 0xa8, 0x83, 0x45, 0x04, 0xa3, 0x13, 0x53, 0x54, 0xbc, 0x17,
|
||||
0xae, 0xac, 0xd5, 0xc9, 0x14, 0xc5, 0x8d, 0x2b, 0x4b, 0x88, 0xc0, 0x81, 0x12, 0x96, 0x2e, 0xb8,
|
||||
0x0d, 0x70, 0x78, 0x84, 0x3b, 0x3e, 0x6c, 0x1f, 0x07, 0x7f, 0x27, 0x83, 0x5b, 0x69, 0xbc, 0x4b,
|
||||
0x2f, 0xf1, 0x82, 0xce, 0xe5, 0x95, 0xbe, 0x19, 0x8c, 0xcd, 0xcd, 0x4c, 0x34, 0x3c, 0xa4, 0xb2,
|
||||
0xf0, 0x14, 0x13, 0x1b, 0xa6, 0x88, 0x1d, 0xfd, 0xf3, 0x2d, 0xe1, 0x64, 0x72, 0xa0, 0xa4, 0x1a,
|
||||
0xd9, 0x0a, 0xbf, 0x9b, 0xa7, 0xa7, 0xeb, 0xb1, 0x59, 0x5e, 0x18, 0x28, 0xbb, 0x39, 0xff, 0x67,
|
||||
0x5e, 0x2c, 0x01, 0x46, 0x0b, 0x85, 0x46, 0x63, 0xa0, 0xd0, 0x94, 0x54, 0x23, 0x8f, 0x29, 0x62,
|
||||
0x25, 0x94, 0x02, 0x00, 0x18, 0x67, 0x62, 0x97, 0x0e, 0xfb, 0xd3, 0x43, 0x67, 0xbf, 0xf1, 0x7b,
|
||||
0xe0, 0xe0, 0x05, 0x4c, 0x03, 0x65, 0x81, 0xb7, 0x59, 0x21, 0x2f, 0x2b, 0x82, 0x39, 0xfc, 0x9b,
|
||||
0x5f, 0x08, 0xd5, 0xac, 0xc8, 0xc8, 0x45, 0x31, 0x7a, 0x76, 0xc4, 0x6f, 0xb8, 0xbc, 0x09, 0x99,
|
||||
0xee, 0x53, 0x60, 0x7e, 0x44, 0xe5, 0x0f, 0x2e, 0x4f, 0x0e, 0xce, 0xa8, 0x93, 0x48, 0x9b, 0xdc,
|
||||
0x57, 0x7c, 0x61, 0x9b, 0x40, 0x42, 0x3b, 0xb2, 0x1c, 0x7d, 0xf9, 0xa8, 0x3d, 0x4c, 0xb0, 0x9b,
|
||||
0x95, 0x39, 0xea, 0xa9, 0x4f, 0xb2, 0x96, 0x61, 0x9d, 0x6e, 0x78, 0xdf, 0x29, 0x6d, 0x88, 0x5b,
|
||||
0x7f, 0x92, 0x38, 0x72, 0x7a, 0x34, 0x1e, 0x03, 0xc6, 0xba, 0xe5, 0x89, 0xb2, 0x77, 0x0e, 0x7a,
|
||||
0x4b, 0xfa, 0x94, 0x45, 0x14, 0xb8, 0xbc, 0x6b, 0xcf, 0x10, 0x4c, 0x32, 0xb2, 0xf1, 0xe6, 0xb2,
|
||||
0xcd, 0xff, 0x31, 0x6e, 0x58, 0x07, 0x5b, 0x47, 0x78, 0x04, 0xc8, 0x3f, 0x54, 0x1e, 0x6a, 0xb4,
|
||||
0x81, 0x27, 0xf1, 0xe9, 0xb0, 0xd8, 0xd1, 0x4e, 0x7e, 0xe1, 0x5d, 0xfa, 0xc3, 0xcf, 0x17, 0x91,
|
||||
0x72, 0xf3, 0x05, 0x1e, 0xf2, 0x89, 0x8c, 0x43, 0x14, 0xbc, 0xcb, 0x5b, 0x36, 0xdd, 0xbf, 0x48,
|
||||
0x7b, 0x1a, 0x3f, 0xdb, 0x3f, 0xb7, 0x6a, 0x91, 0x8b, 0x87, 0xa1, 0x63, 0xb5, 0x70, 0x2f, 0x17,
|
||||
0x18, 0xaf, 0xb8, 0xee, 0x70, 0x76, 0xe4, 0xaa, 0x8b, 0x28, 0x42, 0x71, 0x9b, 0xf5, 0xd3, 0x67,
|
||||
0xb3, 0xa7, 0x3f, 0x2c, 0x14, 0x9f, 0xa0, 0x9f, 0x46, 0x43, 0x83, 0xff, 0x03, 0x57, 0xe6, 0xdf,
|
||||
0xf0, 0x61, 0x9a, 0x80, 0xb9, 0x08, 0x82, 0x57, 0xef, 0x54, 0x08, 0x63, 0xc9, 0x4c, 0x5b, 0x00,
|
||||
0xe3, 0xbb, 0x99, 0x1e, 0xfe, 0x88, 0x5f, 0x9c, 0xb2, 0x82, 0x8d, 0x54, 0x16, 0xef, 0x8b, 0x15,
|
||||
0x40, 0xaf, 0xab, 0xb9, 0xc9, 0xe8, 0x3d, 0x4e, 0x2b, 0xe7, 0x7b, 0xc3, 0x5c, 0x87, 0xbe, 0x95,
|
||||
0x00, 0xf7, 0xfa, 0x96, 0x57, 0x13, 0x6c, 0xd6, 0x46, 0x02, 0x43, 0x17, 0x8f, 0xd2, 0x78, 0x81,
|
||||
0x41, 0x71, 0x57, 0x47, 0x10, 0xb8, 0x8f, 0x0b, 0xd0, 0xe5, 0xd7, 0x6e, 0xb9, 0x2f, 0x63, 0x33,
|
||||
0x35, 0x8c, 0x25, 0x59, 0xde, 0x6d, 0xa4, 0x2d, 0x4f, 0x0c, 0x99, 0x3f, 0x35, 0xbc, 0xcb, 0xc9,
|
||||
0x59, 0x1b, 0x89, 0x49, 0x83, 0xc5, 0xbc, 0x38, 0x8a, 0x1b, 0xe8, 0x2d, 0x28, 0x7c, 0xb7, 0xf8,
|
||||
0xfa, 0xe8, 0x96, 0x84, 0x17, 0xbb, 0xd4, 0x9d, 0x58, 0x7f, 0x8d, 0x20, 0x32, 0xc3, 0xeb, 0x74,
|
||||
0xb4, 0x3c, 0xbf, 0xbb, 0x93, 0xa5, 0xce, 0x2e, 0xb6, 0x9d, 0xbf, 0x88, 0x5e, 0xde, 0x62, 0xb0,
|
||||
0x10, 0xa7, 0x75, 0xa6, 0x7e, 0xdd, 0x0f, 0x2e, 0xc3, 0xc8, 0x50, 0xcd, 0x1c, 0x39, 0x51, 0xac,
|
||||
0xf9, 0x0a, 0x13, 0x3d, 0xe7, 0x9b, 0xa6, 0x2f, 0x82, 0x48, 0xe2, 0x95, 0x74, 0x08, 0x04, 0x67,
|
||||
0x87, 0xde, 0xfd, 0x93, 0x44, 0x35, 0x8b, 0x3d, 0xb1, 0x4b, 0x99, 0xb8, 0x70, 0xf8, 0xf7, 0x88,
|
||||
0xbd, 0x3f, 0x62, 0xa9, 0x77, 0xaf, 0x58, 0xab, 0xb2, 0x3e, 0xb2, 0x93, 0x6b, 0x37, 0xbc, 0x56,
|
||||
0x73, 0xc2, 0x06, 0x24, 0xcb, 0x5d, 0xb0, 0x78, 0xcf, 0xff, 0x6a, 0xad, 0xb9, 0x19, 0x76, 0xf9,
|
||||
0xa6, 0x5d, 0x5e, 0xb8, 0x68, 0x64, 0x69, 0x34, 0xe8, 0x44, 0xd0, 0x68, 0x5f, 0x1a, 0xa2, 0x30,
|
||||
0x15, 0x99, 0xa3, 0x9d, 0xf9, 0x31, 0xba, 0xf4, 0x0a, 0x6e, 0x74, 0x3b, 0x45, 0x18, 0xf4, 0xc8,
|
||||
0x60, 0x5b, 0x13, 0x41, 0x40, 0x44, 0x9a, 0x1d, 0xda, 0x51, 0x6f, 0xe8, 0x45, 0x47, 0xce, 0x8f,
|
||||
0x78, 0xc2, 0x4f, 0xf1, 0x57, 0x2d, 0x74, 0x2c, 0x64, 0x20, 0x39, 0xc7, 0xb6, 0x49, 0x83, 0xe0,
|
||||
0xe8, 0xa1, 0xf5, 0x48, 0x78, 0x11, 0x59, 0xd9, 0xa9, 0x65, 0xc1, 0x1a, 0xcb, 0x93, 0x98, 0x50,
|
||||
0x17, 0xd0, 0xe9, 0x6d, 0x5e, 0x8b, 0x0b, 0x7f, 0x17, 0x3b, 0xcc, 0xa7, 0x95, 0x97, 0x64, 0x28,
|
||||
0x4a, 0xd0, 0x0b, 0x64, 0x0b, 0x0c, 0x47, 0x7a, 0xcc, 0x35, 0x12, 0xdd, 0xe6, 0xdf, 0xd8, 0x1c,
|
||||
0x14, 0x81, 0x59, 0xf6, 0x30, 0xe5, 0x24, 0x83, 0xd3, 0x49, 0xfc, 0x9f, 0x3f, 0xe1, 0xae, 0xbb,
|
||||
0xb1, 0xdf, 0x26, 0x5e, 0x80, 0x07, 0x08, 0xf4, 0xd1, 0x03, 0xd0, 0x50, 0x9b, 0x7f, 0x08, 0x90,
|
||||
0xe9, 0x45, 0xa1, 0x85, 0x5e, 0x6a, 0xcc, 0xff, 0x64, 0x98, 0xff, 0xe5, 0x39, 0x8e, 0x6e, 0x4c,
|
||||
0x4b, 0xf8, 0xaf, 0xd6, 0xba, 0xd0, 0x39, 0xcf, 0x7b, 0xf4, 0x25, 0xe9, 0xcf, 0x87, 0xc8, 0x87,
|
||||
0x49, 0x8a, 0xda, 0xc9, 0xcc, 0x08, 0x65, 0x05, 0xfc, 0xd1, 0xaf, 0x74, 0xc6, 0x6c, 0xb8, 0x3b,
|
||||
0x53, 0xd1, 0xbf, 0x2b, 0x88, 0xb2, 0x28, 0x13, 0xef, 0x06, 0x4a, 0x25, 0x9d, 0x7f, 0x99, 0x99,
|
||||
0xc9, 0xf2, 0x5c, 0x66, 0x8e, 0xaf, 0x8b, 0x5f, 0xf0, 0x26, 0xb4, 0x24, 0xeb, 0xe3, 0xae, 0x08,
|
||||
0xcc, 0xf0, 0xbb, 0xc8, 0x07, 0x09, 0xdf, 0x31, 0x61, 0x17, 0x13, 0x8c, 0xdd, 0x74, 0x36, 0xb7,
|
||||
0xbd, 0xfd, 0xa9, 0xf1, 0x35, 0x1a, 0x1e, 0x3a, 0x00, 0x0e, 0x0c, 0x75, 0xf5, 0x8e, 0x6c, 0x6e,
|
||||
0x67, 0x47, 0xe3, 0x3c, 0x8a, 0xdc, 0x69, 0x38, 0xd8, 0xb7, 0xec, 0x8e, 0xe1, 0xc7, 0x36, 0x49,
|
||||
0xb8, 0x08, 0x5f, 0x1c, 0xaf, 0x0b, 0x20, 0x61, 0x36, 0xc1, 0xe8, 0xe1, 0x61, 0xd1, 0xcf, 0x22,
|
||||
0x13, 0xb7, 0xd4, 0x3c, 0xd2, 0x0f, 0x31, 0x0a, 0x76, 0xb3, 0x58, 0x58, 0xf5, 0xc0, 0xb7, 0xd5,
|
||||
0xfb, 0xa8, 0x3c, 0x22, 0x18, 0xfb, 0x5b, 0x0f, 0x6e, 0x37, 0xc6, 0xa3, 0xb7, 0x29, 0x2e, 0x7a,
|
||||
0xe3, 0xb1, 0x05, 0x69, 0x3b, 0xc9, 0x98, 0x1e, 0xeb, 0xbf, 0x74, 0x3c, 0xa6, 0xc8, 0xfe, 0x10,
|
||||
0x6b, 0xb1, 0x6c, 0xd6, 0x0e, 0xe0, 0x8c, 0x8f, 0xc1, 0xa5, 0x37, 0x7f, 0xe2, 0x15, 0xcb, 0x61,
|
||||
0x0a, 0x08, 0xee, 0x3b, 0x24, 0x42, 0x3a, 0x9d, 0x76, 0x99, 0xf2, 0xe4, 0x7b, 0x57, 0x7c, 0x8d,
|
||||
0x81, 0xd4, 0x19, 0x6f, 0xc0, 0xb8, 0x19, 0xff, 0xe4, 0x02, 0x94, 0xf3, 0x2f, 0xfd, 0xde, 0xde,
|
||||
0x66, 0x4f, 0x26, 0xbf, 0x3c, 0x63, 0x9d, 0xc0, 0x03, 0x3f, 0x09, 0x93, 0xf7, 0x72, 0x60, 0x35,
|
||||
0xf2, 0x3f, 0xe8, 0xa2, 0xfc, 0xf3, 0x27, 0x2a, 0xe9, 0x40, 0x0a, 0x43, 0x6a, 0x6d, 0x8e, 0x1a,
|
||||
0x71, 0xa8, 0x37, 0x90, 0x26, 0xd0, 0x5a, 0x7c, 0x6d, 0x6d, 0x79, 0xcc, 0x5b, 0x04, 0xaa, 0xdc,
|
||||
0xca, 0x30, 0x16, 0xde, 0xfd, 0x6e, 0x9e, 0x8e, 0xb6, 0x7a, 0xbb, 0x1a, 0x68, 0x69, 0x50, 0x82,
|
||||
0xa3, 0xf7, 0xc0, 0xd1, 0x0b, 0xe1, 0x60, 0xce, 0x57, 0x4b, 0x0d, 0x4d, 0x3c, 0x65, 0x8a, 0x4e,
|
||||
0x5a, 0xca, 0xd1, 0x36, 0x17, 0x0c, 0x5f, 0xed, 0xf6, 0x7e, 0x49, 0x0a, 0x12, 0x84, 0x37, 0x27,
|
||||
0xe0, 0xea, 0xfb, 0xa0, 0xdc, 0xc8, 0xfa, 0xa8, 0xd8, 0xf2, 0x96, 0x38, 0xbf, 0xdc, 0xd6, 0xf7,
|
||||
0x8c, 0xf7, 0xd6, 0x87, 0xc4, 0xf7, 0x0c, 0xee, 0xb1, 0xe2, 0xf7, 0xc0, 0x1d, 0xea, 0xbb, 0x89,
|
||||
0xff, 0x07, 0x67, 0xc7, 0x83, 0x20, 0xcd, 0xc3, 0x00, 0x00
|
||||
0x1c, 0x83, 0x15, 0x69, 0x13, 0xf4, 0x56, 0xcd, 0xcb, 0x5e, 0x92, 0xbb, 0xee, 0xde, 0xed, 0x73,
|
||||
0xfc, 0x77, 0xd1, 0x5f, 0xf6, 0x6b, 0x8a, 0xfc, 0x1b, 0x3d, 0xaf, 0x38, 0x60, 0x73, 0x57, 0xfc,
|
||||
0xe1, 0x84, 0x4a, 0x38, 0x23, 0x19, 0x74, 0xda, 0xa4, 0xc9, 0xd7, 0xcc, 0x46, 0xb5, 0x5a, 0x45,
|
||||
0x4d, 0xa0, 0x8f, 0xdb, 0x69, 0x80, 0x36, 0xa4, 0x77, 0x74, 0x97, 0x1e, 0xb9, 0x43, 0x3d, 0xc9,
|
||||
0xf5, 0xa6, 0x40, 0x86, 0x58, 0x4d, 0x53, 0x85, 0x95, 0xea, 0x22, 0x28, 0xf7, 0x02, 0xca, 0x12,
|
||||
0x86, 0x6a, 0xdc, 0x69, 0xc1, 0xff, 0x41, 0x41, 0xa4, 0x44, 0xea, 0x1f, 0xbf, 0x7b, 0x5f, 0xc7,
|
||||
0x5a, 0xba, 0xe1, 0x7c, 0xab, 0x10, 0xe7, 0xe9, 0xff, 0x93, 0x29, 0xf2, 0x76, 0xe4, 0x71, 0x7e,
|
||||
0x02, 0xfd, 0xcf, 0xef, 0x0f, 0xd3, 0xdf, 0x48, 0x78, 0xdb, 0x7d, 0x23, 0x1a, 0x3d, 0x5f, 0x27,
|
||||
0xe2, 0xd2, 0xf4, 0x70, 0x69, 0x32, 0x5c, 0x0a, 0xa1, 0x83, 0x5f, 0x9c, 0xf0, 0xed, 0xbd, 0xb3,
|
||||
0x5e, 0xc0, 0xf4, 0x98, 0x2d, 0xee, 0x1f, 0x96, 0x5b, 0x8f, 0xd8, 0xc8, 0x06, 0x72, 0x92, 0x05,
|
||||
0x1c, 0x91, 0xb5, 0x11, 0xb2, 0x5f, 0x3d, 0x48, 0x09, 0x7a, 0xd7, 0x2f, 0xf7, 0x2e, 0xaa, 0xe7,
|
||||
0x6c, 0xc8, 0x88, 0xdb, 0x34, 0xba, 0xc1, 0xa0, 0xd7, 0x38, 0x0e, 0x87, 0xa5, 0xc4, 0x43, 0x64,
|
||||
0x83, 0xae, 0xf3, 0x75, 0xdc, 0x9c, 0x72, 0xd8, 0x2e, 0x27, 0x22, 0xc7, 0xeb, 0x57, 0xcb, 0x71,
|
||||
0x80, 0xfa, 0xf8, 0x45, 0x78, 0x63, 0x2e, 0x9c, 0xc7, 0x76, 0x58, 0xc2, 0x47, 0x2f, 0x96, 0x3b,
|
||||
0x75, 0xcb, 0xb4, 0x9f, 0x84, 0x0a, 0x9c, 0x2f, 0xae, 0xbf, 0xf3, 0xe2, 0xdf, 0x4f, 0x90, 0x60,
|
||||
0xe1, 0xbb, 0xd9, 0x06, 0x88, 0x26, 0x36, 0x08, 0xf4, 0x10, 0x00, 0x51, 0x34, 0xd0, 0x5b, 0x25,
|
||||
0x44, 0xa3, 0x39, 0x30, 0x9d, 0xf7, 0xf2, 0x21, 0xb7, 0x01, 0xaa, 0x0e, 0xcf, 0x47, 0x5d, 0x47,
|
||||
0x0c, 0x87, 0x62, 0x9d, 0x7c, 0xf7, 0xe1, 0xd5, 0x09, 0x22, 0x85, 0xda, 0xc9, 0xa0, 0xac, 0xbb,
|
||||
0xd8, 0x13, 0xba, 0x7a, 0x05, 0x5d, 0x90, 0x04, 0xbb, 0xf1, 0x25, 0x8b, 0x1d, 0x8b, 0xb6, 0xe3,
|
||||
0xf0, 0xbc, 0xdd, 0x40, 0x27, 0x52, 0x06, 0x5a, 0xf8, 0x17, 0x18, 0x39, 0x02, 0xf3, 0x23, 0x09,
|
||||
0x3a, 0x7c, 0xe5, 0x7e, 0x09, 0x12, 0x7c, 0xe5, 0x7f, 0xd5, 0xa9, 0xfb, 0x04, 0x2a, 0x73, 0x36,
|
||||
0x28, 0x00, 0x0e, 0x6f, 0x60, 0x7f, 0x3c, 0xeb, 0x9d, 0xde, 0x78, 0x84, 0xae, 0xed, 0x35, 0x69,
|
||||
0xd2, 0x6a, 0x5a, 0x00, 0x2a, 0x38, 0xcc, 0xe2, 0x53, 0x03, 0x36, 0xbb, 0x93, 0xad, 0x43, 0xfb,
|
||||
0x7e, 0x0e, 0x0c, 0x00, 0x31, 0xa3, 0x47, 0x53, 0xb2, 0xb4, 0x57, 0xe1, 0x94, 0xdc, 0xaf, 0xc5,
|
||||
0x17, 0x40, 0x6b, 0xc3, 0x06, 0x84, 0xd9, 0x0d, 0x92, 0xf1, 0xf1, 0x81, 0xe3, 0x09, 0x5c, 0x5e,
|
||||
0xbf, 0x31, 0xa2, 0x02, 0x15, 0x29, 0x01, 0x8d, 0x6d, 0x01, 0xed, 0x70, 0x1e, 0x64, 0x9d, 0xbd,
|
||||
0xf8, 0xe7, 0x6f, 0xde, 0xd3, 0x7e, 0x7e, 0x87, 0xae, 0x6b, 0x4a, 0x6c, 0xbc, 0xaf, 0x09, 0xa3,
|
||||
0xcb, 0x9e, 0x4d, 0x8d, 0x06, 0x34, 0xd4, 0x7f, 0x47, 0xa9, 0x85, 0x2e, 0xb3, 0x4b, 0xfa, 0x6e,
|
||||
0x93, 0x60, 0xa1, 0x51, 0x2d, 0xc8, 0xdf, 0x99, 0x64, 0xef, 0x3d, 0x59, 0xea, 0xa7, 0x64, 0xc1,
|
||||
0x76, 0x1f, 0x41, 0x99, 0xa4, 0x39, 0xe1, 0x8d, 0xc7, 0xb5, 0xcb, 0x96, 0x6e, 0x76, 0x0a, 0x0e,
|
||||
0xfa, 0x61, 0x38, 0x01, 0x5d, 0x24, 0x80, 0x8c, 0xf0, 0xd6, 0x67, 0xdc, 0xa3, 0x87, 0x83, 0x0d,
|
||||
0x9d, 0x01, 0xc5, 0xb6, 0xbc, 0x9f, 0xd0, 0x60, 0x83, 0xb9, 0x23, 0x40, 0xc5, 0x69, 0x31, 0x15,
|
||||
0x07, 0x55, 0x00, 0xdf, 0xbb, 0x17, 0x33, 0x47, 0x42, 0x37, 0x7f, 0x73, 0xab, 0xd6, 0xcd, 0xd2,
|
||||
0x77, 0x47, 0xf5, 0x6c, 0xdc, 0x4c, 0x65, 0xaa, 0xf4, 0xd2, 0xc8, 0xf1, 0x94, 0x6a, 0x9c, 0x82,
|
||||
0xa5, 0xa2, 0x1c, 0x0c, 0x36, 0xac, 0xf6, 0xb2, 0x85, 0x86, 0x7e, 0xfa, 0x2f, 0x8d, 0xc0, 0xca,
|
||||
0x25, 0xe9, 0x81, 0xe4, 0x34, 0x5d, 0xd7, 0xd6, 0x40, 0xad, 0x22, 0x49, 0x0e, 0x2c, 0x00, 0x8e,
|
||||
0x07, 0x2d, 0x54, 0xf2, 0x93, 0xa8, 0x47, 0x8c, 0x5d, 0x71, 0x52, 0x03, 0xb2, 0x13, 0xcc, 0x06,
|
||||
0xb3, 0xd9, 0x69, 0x4a, 0xc6, 0xad, 0x27, 0xcd, 0xa5, 0xc1, 0x0a, 0xcb, 0xfc, 0x7b, 0x51, 0x64,
|
||||
0xfa, 0x52, 0xce, 0xf7, 0x72, 0xfd, 0x5e, 0xff, 0x62, 0xc0, 0xd0, 0xf5, 0xfb, 0x74, 0x5c, 0xff,
|
||||
0x14, 0x42, 0xb7, 0x2f, 0xb3, 0x14, 0xfe, 0x37, 0xf0, 0x75, 0xf6, 0x1e, 0x3a, 0xd4, 0x1d, 0x36,
|
||||
0x1d, 0xd5, 0x88, 0x99, 0x1c, 0x18, 0x44, 0xb8, 0x12, 0xe4, 0xd1, 0x70, 0x3c, 0x6f, 0x6e, 0x04,
|
||||
0xe0, 0x26, 0xd8, 0x41, 0x54, 0x22, 0x33, 0x45, 0x28, 0x48, 0xf4, 0xff, 0x26, 0x8d, 0xb0, 0x57,
|
||||
0xd4, 0xbb, 0xf7, 0x25, 0x44, 0xaa, 0xe1, 0xb0, 0x14, 0x1a, 0xa8, 0x9e, 0x66, 0x47, 0xfc, 0xfe,
|
||||
0x6e, 0x9b, 0xa1, 0x00, 0x10, 0x06, 0x3a, 0xc9, 0xc5, 0xdf, 0x1b, 0x18, 0xde, 0x4e, 0x5d, 0x7a,
|
||||
0x69, 0xfd, 0x4d, 0x5d, 0x7a, 0xda, 0x85, 0xa3, 0xce, 0xe7, 0x0f, 0xa5, 0xeb, 0xba, 0x68, 0x13,
|
||||
0xef, 0xfc, 0x19, 0x6e, 0x0a, 0x07, 0xc0, 0x70, 0x1f, 0xe1, 0x3f, 0x04, 0x06, 0x64, 0x18, 0x39,
|
||||
0xc5, 0xb6, 0x2b, 0xfa, 0xe4, 0x48, 0x4d, 0x33, 0xeb, 0x1f, 0xf3, 0x48, 0xf6, 0xc2, 0xfc, 0xcd,
|
||||
0xd7, 0xc1, 0x96, 0x73, 0x43, 0x50, 0x25, 0x55, 0x0d, 0x83, 0x14, 0x92, 0x9b, 0xea, 0xbe, 0xea,
|
||||
0x32, 0x18, 0x78, 0xef, 0x56, 0x5e, 0xc4, 0x51, 0x88, 0xfb, 0x38, 0x2c, 0x12, 0x25, 0x7c, 0x5b,
|
||||
0x6e, 0x38, 0x1e, 0x05, 0x0f, 0xfc, 0x51, 0xaf, 0x80, 0x36, 0x26, 0x34, 0x94, 0x83, 0x21, 0x9c,
|
||||
0x5a, 0x61, 0x3a, 0xdb, 0x8d, 0xa7, 0x5f, 0x1e, 0x5e, 0xf8, 0x20, 0x9c, 0x8f, 0xe1, 0x2b, 0x9c,
|
||||
0x47, 0x71, 0xe6, 0x57, 0x43, 0xd4, 0x01, 0x43, 0x69, 0x84, 0x4e, 0xfe, 0x01, 0x19, 0x81, 0x7d,
|
||||
0x2b, 0xdb, 0x44, 0x7a, 0x59, 0xf8, 0x4a, 0x01, 0x5e, 0xd3, 0x10, 0xd6, 0x09, 0xbe, 0x6d, 0xbc,
|
||||
0xb2, 0x81, 0x9e, 0x72, 0xff, 0x96, 0xd2, 0x83, 0x58, 0x09, 0x34, 0x2c, 0x51, 0xcb, 0x6c, 0x88,
|
||||
0x6c, 0xc3, 0x70, 0x7b, 0x9b, 0xac, 0x74, 0xd4, 0x9b, 0xd4, 0x35, 0x9d, 0x24, 0xeb, 0x3a, 0xd9,
|
||||
0x9e, 0x86, 0xfb, 0xe8, 0xa9, 0xa8, 0xe1, 0x06, 0x23, 0x6a, 0x2a, 0x68, 0x52, 0x0d, 0xca, 0x23,
|
||||
0x1a, 0x34, 0x88, 0xc0, 0xd3, 0x1f, 0x3f, 0x37, 0xa2, 0xe0, 0xa6, 0x8b, 0x6f, 0xa9, 0x68, 0x03,
|
||||
0x21, 0x35, 0x75, 0x11, 0x37, 0xf5, 0x43, 0x17, 0xbe, 0xf2, 0xfe, 0x4e, 0xdd, 0x4a, 0x2e, 0xbb,
|
||||
0xc7, 0x65, 0x73, 0xfe, 0xf2, 0x6a, 0x12, 0xde, 0xeb, 0x33, 0xbb, 0x58, 0x2b, 0x7e, 0x3a, 0x88,
|
||||
0xed, 0x42, 0xc4, 0x8f, 0x08, 0xb1, 0x0a, 0x78, 0x3d, 0x55, 0xbc, 0xbc, 0xa2, 0xb8, 0x6b, 0x0b,
|
||||
0xbf, 0xac, 0x85, 0x4e, 0x4b, 0xd3, 0x52, 0x35, 0xaf, 0x52, 0x78, 0x6b, 0x26, 0xa6, 0x0e, 0xfa,
|
||||
0x59, 0x5d, 0x3a, 0x00, 0xd0, 0xba, 0x3d, 0x86, 0x1c, 0x3f, 0x6c, 0x63, 0x7c, 0x7c, 0xa6, 0x8a,
|
||||
0x11, 0x44, 0x84, 0x18, 0x28, 0x15, 0x44, 0x7b, 0xe7, 0xc4, 0x46, 0x12, 0x8a, 0x35, 0x19, 0x5a,
|
||||
0x9d, 0xb0, 0xc4, 0x4e, 0x10, 0xdc, 0x54, 0x33, 0x7e, 0x80, 0xc2, 0x8e, 0x0f, 0x7e, 0x04, 0xce,
|
||||
0x0f, 0xee, 0xff, 0x42, 0xdd, 0x04, 0x18, 0xac, 0x2c, 0x9f, 0x8f, 0xa9, 0xf0, 0x54, 0x6f, 0x5b,
|
||||
0x53, 0x9a, 0x26, 0x1b, 0x2c, 0x9a, 0x43, 0x14, 0xe6, 0xc6, 0x68, 0x48, 0x6c, 0x4d, 0xa9, 0x7d,
|
||||
0x11, 0x17, 0x7c, 0x2d, 0xd8, 0x29, 0x5d, 0xf6, 0xc6, 0x0f, 0x5a, 0x9e, 0x4f, 0x9c, 0x3f, 0x7f,
|
||||
0x92, 0x49, 0x8c, 0x74, 0x23, 0x93, 0x44, 0x10, 0x0c, 0x07, 0x33, 0xe5, 0x50, 0xfb, 0x99, 0x9a,
|
||||
0xd3, 0xcc, 0x88, 0x5e, 0xb9, 0xc9, 0xd9, 0x74, 0x5c, 0x6a, 0x4e, 0x80, 0x69, 0x3d, 0x71, 0xf0,
|
||||
0x90, 0x18, 0xba, 0xa7, 0x1d, 0x07, 0x83, 0xe5, 0xfd, 0x80, 0x7c, 0x37, 0x1c, 0xa6, 0x42, 0xa8,
|
||||
0x2a, 0xcd, 0x33, 0x1d, 0x96, 0xfa, 0xd7, 0xf9, 0x79, 0x24, 0x4e, 0x30, 0xb4, 0x61, 0xcc, 0x0b,
|
||||
0xa1, 0x1f, 0xcb, 0x28, 0x3c, 0xef, 0x8c, 0x6f, 0x10, 0x0e, 0xbc, 0x6a, 0x69, 0xff, 0xb5, 0x48,
|
||||
0x47, 0x9d, 0xe7, 0x3c, 0xd5, 0x17, 0xf4, 0x7b, 0xb0, 0xc8, 0xeb, 0xe6, 0x8f, 0xc0, 0x3a, 0x6f,
|
||||
0x98, 0x42, 0x68, 0x13, 0xcf, 0x3b, 0xd7, 0xbc, 0xbd, 0x1d, 0xd9, 0xf0, 0x02, 0x69, 0x0f, 0x36,
|
||||
0x65, 0x60, 0xcf, 0x63, 0x64, 0x21, 0x0d, 0x2c, 0x4c, 0xe2, 0x29, 0x02, 0xf8, 0xfe, 0xe1, 0x7d,
|
||||
0xd7, 0x5c, 0xe0, 0xb0, 0xc2, 0x04, 0x9d, 0xd7, 0x34, 0xb8, 0x90, 0x22, 0xe8, 0x2f, 0x07, 0x65,
|
||||
0xfe, 0xc5, 0x80, 0x44, 0xaf, 0x41, 0xd3, 0x22, 0x06, 0x6d, 0x6f, 0x82, 0xde, 0x64, 0x8c, 0x52,
|
||||
0x9a, 0x7f, 0x1b, 0x7f, 0xab, 0xb9, 0xf6, 0x08, 0x54, 0x44, 0x5c, 0x31, 0xaf, 0xce, 0x19, 0xe9,
|
||||
0x4b, 0x3a, 0xc6, 0xe6, 0xaf, 0xe0, 0x33, 0x1c, 0xeb, 0xb0, 0x1c, 0x9d, 0x1f, 0x5a, 0x8a, 0x33,
|
||||
0x49, 0x3c, 0x6b, 0x04, 0x6d, 0x00, 0x3c, 0x02, 0x4e, 0xd0, 0x41, 0x1f, 0xe7, 0x39, 0x4c, 0x4f,
|
||||
0x80, 0x3c, 0xd9, 0xd6, 0x04, 0x43, 0x6f, 0xa2, 0xab, 0x4f, 0xa7, 0x9e, 0x7c, 0x7d, 0x7f, 0x64,
|
||||
0xb3, 0x5f, 0xea, 0xc8, 0x86, 0x9f, 0x37, 0x92, 0xf7, 0xd3, 0x65, 0x45, 0xdb, 0x92, 0x4a, 0x58,
|
||||
0x02, 0xbe, 0x78, 0x9c, 0x6e, 0x5d, 0x76, 0x61, 0x10, 0x90, 0x34, 0x52, 0x2d, 0x83, 0x0e, 0x28,
|
||||
0x76, 0x1c, 0x1c, 0xf4, 0x0b, 0xfd, 0xbb, 0xf8, 0x03, 0x77, 0x88, 0x6a, 0xf8, 0x8c, 0x47, 0xbb,
|
||||
0x41, 0x0b, 0x09, 0x5e, 0xdb, 0x93, 0xc9, 0x8a, 0xde, 0x9c, 0x8b, 0x34, 0x74, 0x7a, 0xcd, 0xf6,
|
||||
0x47, 0x4c, 0xb4, 0xaf, 0xee, 0x7b, 0x30, 0x23, 0x91, 0x6e, 0x21, 0xe2, 0xbe, 0x05, 0xb2, 0x01,
|
||||
0x02, 0x52, 0xca, 0x04, 0x1d, 0x8b, 0x49, 0x00, 0x27, 0x95, 0x5a, 0xf8, 0xda, 0x96, 0xb7, 0xb3,
|
||||
0x81, 0xc8, 0x32, 0xfc, 0x18, 0xae, 0x90, 0x83, 0xe9, 0xc2, 0x4c, 0xf8, 0x4d, 0x7b, 0x3e, 0x25,
|
||||
0xba, 0x88, 0x97, 0x62, 0xb8, 0x1e, 0x98, 0x24, 0x0d, 0x03, 0x8f, 0xaa, 0x7a, 0x7b, 0x98, 0x6b,
|
||||
0x42, 0xc1, 0x43, 0xd6, 0x9b, 0x1f, 0x20, 0x0f, 0x76, 0x0f, 0xd9, 0x45, 0x5b, 0x6e, 0x67, 0xc7,
|
||||
0xf3, 0x5f, 0x0a, 0xb6, 0xa0, 0x09, 0x4a, 0x5d, 0x62, 0xc0, 0x3c, 0x4b, 0xc8, 0x5e, 0xfe, 0x02,
|
||||
0x2b, 0x48, 0x5b, 0xfe, 0x02, 0x4b, 0x8d, 0xf1, 0x73, 0x3c, 0x0b, 0xb1, 0x4c, 0xc6, 0xb8, 0x77,
|
||||
0x7c, 0x78, 0x2f, 0xc8, 0x9c, 0x4b, 0x49, 0x29, 0x4e, 0xe0, 0x52, 0x36, 0xfd, 0xd4, 0x70, 0x5f,
|
||||
0x6a, 0x09, 0x8b, 0x5d, 0x00, 0x00, 0x10, 0x96, 0xaa, 0xb3, 0x82, 0x21, 0xb4, 0xcb, 0x70, 0x74,
|
||||
0x3c, 0xeb, 0xcf, 0xa3, 0x9c, 0x0e, 0x11, 0xd3, 0x7d, 0x40, 0x4a, 0x5e, 0x7d, 0x2c, 0xf4, 0x4b,
|
||||
0x30, 0x70, 0x4f, 0x7a, 0x7b, 0x9b, 0x7e, 0xed, 0x52, 0xc9, 0x1a, 0xaa, 0xd3, 0x0c, 0xea, 0xd0,
|
||||
0x7c, 0x5e, 0x58, 0x15, 0x79, 0x41, 0xbe, 0x33, 0x15, 0xd6, 0x0b, 0xbc, 0xa0, 0x84, 0x36, 0x15,
|
||||
0x48, 0x9a, 0x86, 0xda, 0x6e, 0x6f, 0x8b, 0x60, 0x44, 0xb0, 0x67, 0x86, 0x5a, 0x15, 0x1d, 0x26,
|
||||
0xbe, 0xd3, 0xdc, 0xcf, 0x60, 0xde, 0x71, 0xb1, 0x46, 0x2f, 0xc2, 0xf5, 0x5d, 0x89, 0x43, 0xf4,
|
||||
0xcc, 0x27, 0x7a, 0xc1, 0x56, 0xe1, 0x17, 0x8e, 0xd1, 0x8d, 0xe7, 0x4b, 0xcf, 0x62, 0x69, 0xdc,
|
||||
0x0c, 0x27, 0x86, 0x39, 0xea, 0x0f, 0x12, 0xf4, 0xcd, 0x45, 0x18, 0x43, 0xe8, 0x48, 0x63, 0x92,
|
||||
0x60, 0x71, 0x76, 0xb1, 0x2a, 0xb9, 0x5a, 0x70, 0x25, 0x1f, 0x6d, 0xc1, 0xf3, 0xcb, 0x46, 0xca,
|
||||
0xe4, 0xb1, 0xcc, 0xb9, 0xe6, 0x38, 0xf8, 0x9e, 0x87, 0xe3, 0x6b, 0xea, 0xb9, 0x8c, 0x15, 0xa9,
|
||||
0x62, 0x91, 0x66, 0xa8, 0x67, 0x09, 0x3a, 0x8c, 0x04, 0x58, 0x48, 0x09, 0x53, 0x81, 0x85, 0x86,
|
||||
0x2e, 0xe1, 0x45, 0x88, 0x7a, 0x29, 0xb3, 0xa0, 0xfb, 0x90, 0xb4, 0x60, 0x8a, 0xab, 0xc1, 0x0f,
|
||||
0x95, 0xc6, 0x09, 0x85, 0xaf, 0x6e, 0x30, 0x40, 0x06, 0xe8, 0xe1, 0x9b, 0x1d, 0x8c, 0x74, 0x6f,
|
||||
0x1a, 0x0e, 0x19, 0x42, 0xfc, 0x85, 0x58, 0x51, 0xb6, 0x1e, 0x62, 0x3b, 0xcb, 0x48, 0xff, 0x50,
|
||||
0x84, 0xe4, 0x5f, 0xe7, 0x9e, 0x5f, 0xc8, 0x9f, 0x3f, 0x41, 0x13, 0xfc, 0x3c, 0x24, 0x60, 0x40,
|
||||
0x04, 0x86, 0xc5, 0x4d, 0x88, 0x9d, 0x46, 0xe3, 0xaf, 0x84, 0x3c, 0xc9, 0xf3, 0xbe, 0x73, 0x8c,
|
||||
0x72, 0x62, 0xb3, 0xf1, 0x91, 0xc3, 0xd9, 0xd1, 0x70, 0x83, 0xe2, 0xe3, 0xd0, 0x73, 0xd0, 0x41,
|
||||
0xc8, 0x0f, 0xce, 0x02, 0xa1, 0xca, 0x31, 0xaf, 0x34, 0x9e, 0x5b, 0x4f, 0x7e, 0x81, 0x7a, 0xc8,
|
||||
0xc9, 0xa0, 0x87, 0x60, 0x6c, 0x35, 0x98, 0xc7, 0x19, 0xb7, 0xd1, 0xc3, 0x01, 0xd8, 0x28, 0x0a,
|
||||
0xd3, 0x86, 0x39, 0x49, 0xf2, 0x18, 0x68, 0x41, 0x0d, 0x81, 0x58, 0xec, 0x2c, 0xe1, 0x7d, 0xce,
|
||||
0x85, 0x11, 0x15, 0xf4, 0xf4, 0x1b, 0xf0, 0x6f, 0x58, 0x6e, 0x3f, 0x7c, 0xa1, 0x00, 0x38, 0xf8,
|
||||
0x36, 0xe7, 0xc6, 0x1c, 0x93, 0x0b, 0xdf, 0xf8, 0x1a, 0x86, 0xa0, 0x62, 0xcb, 0x11, 0xe9, 0x12,
|
||||
0x9a, 0x0b, 0x21, 0x87, 0x2e, 0x10, 0xe6, 0x74, 0x37, 0x03, 0x7f, 0xba, 0x21, 0xe0, 0x29, 0x36,
|
||||
0x82, 0x17, 0x52, 0x60, 0x0c, 0x3c, 0xda, 0xf4, 0x3b, 0xb8, 0x31, 0x01, 0x63, 0xc2, 0xe3, 0x51,
|
||||
0x1a, 0xd3, 0x1d, 0x28, 0x66, 0xea, 0x78, 0xcd, 0xaa, 0x8d, 0x1c, 0xfb, 0xf6, 0xa6, 0xbd, 0x53,
|
||||
0xe1, 0x16, 0x02, 0xbe, 0xa5, 0xa4, 0xe6, 0xfe, 0xcd, 0x20, 0xb8, 0xe4, 0xff, 0xb2, 0x2a, 0xd1,
|
||||
0xe7, 0xf1, 0x66, 0x81, 0x1f, 0xa8, 0x87, 0x2b, 0x0a, 0xa8, 0x41, 0x74, 0xc6, 0x34, 0xaa, 0x32,
|
||||
0x2c, 0x55, 0x0a, 0x96, 0xf2, 0xb1, 0x5e, 0xe1, 0x57, 0xe0, 0xf9, 0x90, 0x4e, 0x41, 0x3c, 0x9d,
|
||||
0xc2, 0xfb, 0xae, 0x91, 0xa8, 0xf0, 0xe6, 0x6b, 0xe1, 0x65, 0x89, 0xb7, 0x35, 0xc0, 0xd2, 0x71,
|
||||
0x2c, 0x30, 0x1c, 0x08, 0x3b, 0x72, 0xf0, 0xf7, 0xb6, 0x1a, 0x56, 0x8d, 0x7b, 0xef, 0x15, 0x29,
|
||||
0x91, 0x23, 0x38, 0x73, 0xd3, 0xa8, 0xb1, 0x1b, 0x60, 0xf0, 0x33, 0xac, 0x35, 0x84, 0xaf, 0x47,
|
||||
0x9a, 0x7b, 0x57, 0xc2, 0x80, 0x29, 0x1a, 0xbe, 0x00, 0x47, 0x48, 0xfa, 0x97, 0xc6, 0xb0, 0x6f,
|
||||
0x3e, 0x76, 0x45, 0x86, 0x77, 0xf4, 0x14, 0xef, 0xd5, 0xf2, 0xa7, 0x21, 0xb8, 0xb7, 0xbc, 0xc1,
|
||||
0xaa, 0xfc, 0xe0, 0x42, 0xf7, 0x97, 0xe3, 0xeb, 0x7f, 0x80, 0xe0, 0x42, 0x29, 0xf8, 0xae, 0x2d,
|
||||
0xde, 0x33, 0x2b, 0xfc, 0xd7, 0xb0, 0x44, 0x6d, 0x59, 0x06, 0x64, 0x69, 0xcd, 0xc6, 0x07, 0xe0,
|
||||
0xef, 0x32, 0xf9, 0xd3, 0x15, 0x1e, 0x16, 0xf6, 0xdf, 0xbb, 0xea, 0xc6, 0x7b, 0xe0, 0xd9, 0xa1,
|
||||
0x2f, 0x7f, 0x7c, 0x2c, 0xd0, 0x8b, 0xee, 0x3c, 0xad, 0x1b, 0x00, 0x2d, 0xf6, 0x97, 0x47, 0x70,
|
||||
0xe1, 0xc1, 0x0b, 0x8f, 0xc2, 0x83, 0xb4, 0x76, 0x18, 0xec, 0x05, 0x28, 0x7e, 0xb0, 0xa5, 0x57,
|
||||
0x04, 0xd8, 0x50, 0x08, 0x64, 0xab, 0x13, 0x86, 0x57, 0xdf, 0x98, 0x83, 0x9c, 0x0a, 0x57, 0x34,
|
||||
0x83, 0xc1, 0x3a, 0xe5, 0x5d, 0x06, 0x1f, 0x37, 0xd7, 0x48, 0xdc, 0x58, 0xa3, 0x85, 0xc7, 0x6b,
|
||||
0x4d, 0xbb, 0xf5, 0x65, 0xfd, 0x5b, 0xc5, 0x3f, 0x2a, 0xed, 0xef, 0x59, 0xb0, 0x5f, 0xfe, 0xc0,
|
||||
0xd8, 0x15, 0xc1, 0xb1, 0xba, 0xf5, 0xcd, 0x59, 0x8d, 0xb8, 0x75, 0x19, 0xc5, 0x60, 0x28, 0x38,
|
||||
0xc6, 0xf7, 0xb5, 0x90, 0x85, 0xe2, 0x40, 0xd6, 0x6f, 0x3e, 0xed, 0x85, 0x69, 0xd4, 0x97, 0x39,
|
||||
0x66, 0xf6, 0xf7, 0x1a, 0xf8, 0xab, 0xb6, 0xae, 0x57, 0x3a, 0xf7, 0xfb, 0xf3, 0xbd, 0xf1, 0x42,
|
||||
0x45, 0x48, 0x6c, 0x1d, 0x82, 0xb2, 0x59, 0xa3, 0x7b, 0x44, 0x28, 0x6c, 0x6b, 0xcb, 0x6d, 0x7e,
|
||||
0x82, 0xe2, 0x78, 0xd9, 0xc7, 0xc5, 0x22, 0x7a, 0x2f, 0x45, 0xe4, 0x62, 0xcc, 0xf0, 0x79, 0x88,
|
||||
0xf0, 0x55, 0x89, 0x5e, 0xe7, 0xea, 0xcb, 0xee, 0x2d, 0x91, 0x1d, 0xa4, 0xad, 0x9d, 0xc3, 0xd0,
|
||||
0xcd, 0x98, 0xf1, 0x11, 0x7a, 0x58, 0x58, 0x03, 0x69, 0x7b, 0x7b, 0x5d, 0x0f, 0xe8, 0x1b, 0xd4,
|
||||
0x40, 0x33, 0x33, 0xef, 0x34, 0x32, 0x49, 0xce, 0x65, 0x32, 0x90, 0xc6, 0x9a, 0x69, 0xd7, 0x38,
|
||||
0x67, 0x68, 0x9a, 0x18, 0xb4, 0x46, 0x01, 0xd5, 0xfc, 0x0b, 0x73, 0x63, 0xe3, 0x0c, 0x5f, 0x32,
|
||||
0x1a, 0x1e, 0xe6, 0x6a, 0x07, 0xff, 0xc6, 0x28, 0xd7, 0xe0, 0xea, 0xf3, 0xc3, 0x8c, 0xf6, 0xe0,
|
||||
0x3f, 0x18, 0xe5, 0x32, 0x08, 0x67, 0x33, 0x6d, 0x00, 0xb7, 0xfe, 0xe2, 0xc7, 0xf6, 0x90, 0x5f,
|
||||
0x8b, 0xd5, 0xea, 0x18, 0x2c, 0xb3, 0xb9, 0x3a, 0x98, 0x66, 0xb5, 0x40, 0x6d, 0x0f, 0xd3, 0x18,
|
||||
0x0d, 0x25, 0x09, 0x9c, 0xc2, 0x51, 0xa8, 0x6c, 0xdb, 0x14, 0xbd, 0x6e, 0xfc, 0x3c, 0x36, 0x13,
|
||||
0xc2, 0x6a, 0x3b, 0xbd, 0x69, 0x2d, 0x74, 0x4a, 0x2d, 0x0e, 0xcb, 0xbf, 0x3b, 0xd2, 0xd7, 0x07,
|
||||
0xe3, 0x14, 0xbc, 0x06, 0x20, 0x4c, 0x4e, 0x8d, 0xc4, 0xe1, 0xd0, 0xf7, 0x1d, 0x45, 0x47, 0xb9,
|
||||
0x32, 0xb6, 0x55, 0x3b, 0x96, 0x8f, 0xe3, 0x8b, 0x5d, 0x76, 0xbc, 0x06, 0x5b, 0xce, 0x74, 0x2d,
|
||||
0xac, 0x88, 0xd9, 0xb1, 0x32, 0xb8, 0xd0, 0x55, 0xbf, 0xeb, 0x26, 0x60, 0x3d, 0xc8, 0x15, 0x5b,
|
||||
0x65, 0x05, 0x2c, 0x5e, 0x08, 0x17, 0x9f, 0x52, 0xbc, 0x4f, 0x8c, 0xc4, 0x71, 0xcb, 0x22, 0xb1,
|
||||
0x03, 0x3e, 0x37, 0x47, 0x3b, 0x7a, 0x51, 0x8f, 0x9c, 0x29, 0xc3, 0xfd, 0x43, 0x30, 0xdf, 0xa9,
|
||||
0x3e, 0x1a, 0xd2, 0x3a, 0xfc, 0x77, 0xc8, 0x59, 0xfe, 0x41, 0x36, 0xff, 0x84, 0x9b, 0x17, 0x9f,
|
||||
0x48, 0x43, 0x13, 0x23, 0x73, 0xe3, 0x46, 0xda, 0x0e, 0x6c, 0x3f, 0x0c, 0x39, 0xc2, 0xab, 0xde,
|
||||
0x48, 0x7d, 0xc9, 0x6b, 0x37, 0xdb, 0xba, 0x2b, 0x3b, 0x95, 0xb8, 0x41, 0xb9, 0xc6, 0xfd, 0x4e,
|
||||
0xdf, 0x89, 0xce, 0xf1, 0xf5, 0x58, 0x36, 0x75, 0x85, 0x7b, 0x79, 0x02, 0x22, 0x80, 0x4a, 0xb2,
|
||||
0xa4, 0xbb, 0xd1, 0xbc, 0x8d, 0x98, 0x90, 0x2b, 0x26, 0x29, 0xf9, 0xf5, 0xa1, 0x17, 0x92, 0x5a,
|
||||
0x3b, 0xa8, 0xe3, 0x0d, 0xa0, 0xef, 0xcb, 0x18, 0x81, 0x96, 0xb7, 0x3f, 0x45, 0xdf, 0xfd, 0xd2,
|
||||
0xc0, 0x0d, 0x2a, 0x20, 0xf0, 0xf9, 0xa0, 0x26, 0x0a, 0x0e, 0xfc, 0x8d, 0xf1, 0x8d, 0xa1, 0xa0,
|
||||
0xc4, 0x45, 0x8e, 0x66, 0x06, 0xa1, 0xce, 0xde, 0x26, 0x68, 0xaa, 0x28, 0xf2, 0x75, 0xd5, 0x9c,
|
||||
0x93, 0xf4, 0x20, 0x5c, 0x2c, 0x5f, 0x8a, 0x95, 0xe3, 0x17, 0xd0, 0x5b, 0x9d, 0x24, 0x69, 0xa2,
|
||||
0x24, 0x63, 0x9c, 0xf3, 0x80, 0xde, 0x53, 0x36, 0xc0, 0xed, 0x2b, 0xbe, 0xce, 0x3a, 0x07, 0x89,
|
||||
0x8b, 0x25, 0x42, 0x08, 0xc5, 0x8e, 0xff, 0x46, 0x83, 0x95, 0x3d, 0x97, 0x60, 0x74, 0x1e, 0x5f,
|
||||
0x65, 0x67, 0xc9, 0xd9, 0x2d, 0x5c, 0x20, 0xc3, 0xeb, 0x21, 0x9c, 0x5d, 0x87, 0x3c, 0x42, 0x76,
|
||||
0x18, 0x99, 0x87, 0xa1, 0x8c, 0x7e, 0xc4, 0x8b, 0x14, 0xf6, 0x21, 0xd5, 0xc3, 0xa0, 0x07, 0x64,
|
||||
0xda, 0xa5, 0x76, 0x8e, 0xe7, 0x00, 0x87, 0x27, 0x3f, 0xbc, 0xdc, 0x8d, 0x78, 0x09, 0xea, 0x2e,
|
||||
0x46, 0x88, 0xe3, 0x36, 0x52, 0xd7, 0x2b, 0x55, 0x8a, 0x9c, 0x72, 0xf6, 0x5f, 0x2a, 0x83, 0xe7,
|
||||
0x9c, 0x59, 0x53, 0xe1, 0x66, 0x68, 0x8a, 0xe7, 0x3d, 0x86, 0x29, 0x89, 0xf4, 0x60, 0x04, 0xc2,
|
||||
0x36, 0x92, 0xe2, 0x48, 0xee, 0xc8, 0xa6, 0x96, 0x8e, 0x37, 0x6b, 0x60, 0xdc, 0x69, 0xb6, 0x99,
|
||||
0x6e, 0xb1, 0xf2, 0xce, 0xf8, 0xc6, 0xc4, 0x77, 0x61, 0x38, 0xb8, 0xb7, 0xed, 0xb9, 0x4a, 0x8c,
|
||||
0x34, 0x73, 0x93, 0x18, 0xe9, 0xbe, 0xf7, 0x2d, 0xe3, 0x6a, 0x81, 0xbe, 0x18, 0x64, 0xea, 0xef,
|
||||
0x91, 0x75, 0x35, 0x59, 0xa7, 0x23, 0x5d, 0x7f, 0x43, 0xc9, 0x86, 0x5d, 0x46, 0xbc, 0x9d, 0x28,
|
||||
0x21, 0xfe, 0x53, 0xa0, 0x3b, 0xb6, 0xfc, 0xef, 0x30, 0x5a, 0x4f, 0x03, 0xb4, 0x86, 0xbb, 0xff,
|
||||
0x42, 0xf4, 0xb1, 0x66, 0x44, 0x99, 0x82, 0x4f, 0x02, 0x1e, 0x53, 0x40, 0xb3, 0x29, 0x18, 0x11,
|
||||
0x7a, 0xcc, 0x5c, 0x06, 0x67, 0x57, 0xfc, 0x11, 0x41, 0x04, 0xc1, 0x83, 0x1b, 0xb5, 0x58, 0x52,
|
||||
0x8b, 0xbd, 0x5e, 0x23, 0xc9, 0x01, 0x26, 0x60, 0xac, 0xf0, 0x17, 0x26, 0x27, 0xef, 0xd5, 0x3d,
|
||||
0xf3, 0x0f, 0x2b, 0xad, 0xdc, 0x72, 0xb7, 0x9c, 0x42, 0x9f, 0x05, 0x46, 0x80, 0x9e, 0xae, 0x02,
|
||||
0x4d, 0xce, 0xd9, 0x58, 0x6b, 0x9b, 0x60, 0x05, 0x08, 0x5a, 0xc4, 0x80, 0xd1, 0x77, 0x99, 0xcc,
|
||||
0x97, 0x98, 0xf1, 0x82, 0x00, 0xd6, 0x11, 0x39, 0x86, 0x04, 0xac, 0xa3, 0xf1, 0x58, 0xfa, 0xde,
|
||||
0xb2, 0xa9, 0xdf, 0x1b, 0x56, 0x5a, 0x90, 0x18, 0x51, 0x42, 0xe3, 0x8c, 0x31, 0x0b, 0xac, 0x63,
|
||||
0x7b, 0x3b, 0x7a, 0xcf, 0x43, 0xa3, 0xe1, 0xb2, 0x55, 0xb0, 0x9e, 0xa3, 0x6d, 0x6f, 0x7f, 0x88,
|
||||
0x6d, 0x1a, 0xf1, 0xf0, 0x2e, 0x90, 0xf8, 0x8a, 0x67, 0xcb, 0x4c, 0xc8, 0x7d, 0xc1, 0xee, 0x24,
|
||||
0xc3, 0x4b, 0xb1, 0xb1, 0x4e, 0x82, 0x05, 0x8c, 0x34, 0x08, 0x47, 0x89, 0xc1, 0x13, 0x60, 0xe5,
|
||||
0x51, 0x11, 0x08, 0x29, 0xb5, 0x9f, 0x3f, 0x4d, 0x60, 0x1d, 0x26, 0x70, 0x09, 0x33, 0x2d, 0x0b,
|
||||
0x61, 0xe0, 0xbf, 0x84, 0x9f, 0xf8, 0x3f, 0x68, 0x35, 0xf5, 0x2c, 0x6d, 0x3a, 0x66, 0x11, 0xac,
|
||||
0x37, 0x54, 0xc0, 0x5c, 0x47, 0x4f, 0x48, 0x3f, 0xdd, 0x9b, 0x82, 0x82, 0x22, 0x00, 0x0e, 0x11,
|
||||
0xd8, 0x8f, 0x68, 0x93, 0x00, 0xf7, 0xbd, 0x56, 0xa1, 0xc9, 0x5a, 0x8e, 0x55, 0xa4, 0x2e, 0x96,
|
||||
0x58, 0xd5, 0xf7, 0x6a, 0xa3, 0x0e, 0x16, 0x11, 0x8c, 0x4e, 0x4c, 0x51, 0xf1, 0x5e, 0xb6, 0xb2,
|
||||
0x56, 0x27, 0x53, 0x14, 0x37, 0xae, 0x2c, 0x21, 0x02, 0x07, 0x4a, 0x58, 0xba, 0xe0, 0x36, 0xc0,
|
||||
0xe1, 0x11, 0xee, 0xf8, 0xb0, 0x7d, 0x1c, 0xfc, 0x9d, 0x0c, 0x6e, 0xa4, 0xf1, 0x2e, 0xbc, 0xc4,
|
||||
0xcb, 0x39, 0x97, 0xd7, 0xf9, 0x66, 0x30, 0x2e, 0x37, 0x33, 0xd1, 0xf0, 0x80, 0xca, 0xc2, 0x53,
|
||||
0x4c, 0x6c, 0x98, 0x22, 0x76, 0xec, 0xcf, 0xb7, 0x84, 0x93, 0xc9, 0x81, 0x92, 0x6a, 0x64, 0x2b,
|
||||
0xfc, 0x6e, 0x9e, 0x9e, 0xac, 0xc7, 0x66, 0x79, 0x61, 0xa0, 0xec, 0xe6, 0xfc, 0x9f, 0x79, 0xb1,
|
||||
0x04, 0x18, 0x2d, 0x14, 0x1a, 0x8d, 0x81, 0x42, 0x53, 0x52, 0x8d, 0x3c, 0xa6, 0x88, 0x95, 0x50,
|
||||
0x0a, 0x00, 0x60, 0x9c, 0x89, 0x5d, 0x38, 0xec, 0x4f, 0x0f, 0x9d, 0xfd, 0xc6, 0xef, 0x81, 0x83,
|
||||
0x97, 0x2f, 0x0d, 0x94, 0x05, 0xde, 0x64, 0x85, 0xbc, 0xac, 0x08, 0xe6, 0xf0, 0x6f, 0x7e, 0x21,
|
||||
0x54, 0xb3, 0x22, 0x23, 0x17, 0xc5, 0xe8, 0xd9, 0x11, 0xbf, 0xe1, 0xf2, 0x16, 0x64, 0xba, 0x4f,
|
||||
0x81, 0xf9, 0x11, 0x95, 0x3f, 0xb8, 0x38, 0x39, 0x38, 0x9f, 0x4e, 0x22, 0x6d, 0x72, 0x5f, 0xf1,
|
||||
0x65, 0x6d, 0x02, 0x09, 0xed, 0xc8, 0x72, 0xf4, 0xc5, 0xa3, 0xf6, 0x30, 0xc1, 0x6e, 0x55, 0xe6,
|
||||
0xa8, 0xa7, 0x3e, 0xc9, 0x5a, 0x86, 0x75, 0xba, 0xe1, 0x5d, 0xa7, 0xb4, 0x21, 0x6e, 0xfd, 0x29,
|
||||
0xe2, 0xc8, 0xc9, 0xd1, 0x78, 0x0c, 0x18, 0xeb, 0x96, 0x27, 0xca, 0xde, 0x39, 0xe4, 0x2d, 0xe9,
|
||||
0x53, 0x16, 0x51, 0xe0, 0xf2, 0xae, 0x3d, 0x43, 0x30, 0xc9, 0xc8, 0xc6, 0x9b, 0xcb, 0x36, 0xff,
|
||||
0xc7, 0xb8, 0x61, 0x1d, 0x6c, 0x1d, 0xe1, 0xf1, 0x1f, 0xff, 0x40, 0x79, 0xa8, 0xd1, 0x06, 0x9e,
|
||||
0xc2, 0xa7, 0xc3, 0x62, 0xc7, 0x3a, 0xf9, 0x85, 0x77, 0xe1, 0x0f, 0x3f, 0x5f, 0x44, 0xca, 0xcd,
|
||||
0x17, 0x78, 0xc0, 0x27, 0x32, 0x0e, 0x51, 0xf0, 0x2e, 0x6e, 0xd9, 0x74, 0xf7, 0x22, 0xed, 0x69,
|
||||
0xfc, 0x5c, 0xff, 0xdc, 0xaa, 0x45, 0x2e, 0x1d, 0x86, 0x8e, 0xd5, 0xc2, 0xbd, 0x5c, 0x60, 0xbc,
|
||||
0xe2, 0xba, 0x83, 0xd9, 0x91, 0x6b, 0x2e, 0xa2, 0x08, 0xc5, 0x6d, 0xd6, 0x4f, 0x9f, 0xcb, 0x9e,
|
||||
0xfe, 0xb0, 0x50, 0x7c, 0x82, 0x7e, 0x1a, 0x0d, 0x0b, 0xfe, 0x0f, 0x5c, 0x99, 0x7f, 0xc3, 0x87,
|
||||
0x69, 0x02, 0xe6, 0x22, 0x08, 0x5e, 0xbd, 0x4f, 0x21, 0x8c, 0x25, 0x33, 0x6d, 0x01, 0x8c, 0xef,
|
||||
0x66, 0x7a, 0xf8, 0x23, 0x7e, 0x69, 0xca, 0x0a, 0x36, 0x52, 0x59, 0xbc, 0x2b, 0x56, 0x00, 0xbd,
|
||||
0xae, 0xe6, 0x26, 0xa3, 0x77, 0x38, 0xad, 0x9c, 0xed, 0x0d, 0x73, 0x1d, 0xfa, 0x46, 0x02, 0xdc,
|
||||
0xeb, 0x5b, 0x5e, 0x4b, 0xb0, 0x59, 0x1b, 0x09, 0x0c, 0x5d, 0x3c, 0x46, 0xe3, 0x05, 0x06, 0xc5,
|
||||
0x5d, 0x1d, 0x41, 0xd0, 0x3e, 0x2e, 0x40, 0x97, 0x5f, 0xbb, 0xe5, 0xbe, 0x8c, 0xcd, 0xd4, 0x30,
|
||||
0x96, 0x64, 0x79, 0xaf, 0x91, 0xb6, 0x3c, 0x2d, 0x64, 0xfe, 0xd4, 0xf0, 0x1e, 0x27, 0x67, 0x6d,
|
||||
0x24, 0x26, 0x0d, 0x16, 0xf3, 0xe2, 0x28, 0x6e, 0xa0, 0xb7, 0xa0, 0xf0, 0xdd, 0xe2, 0xab, 0xa3,
|
||||
0x5b, 0x12, 0x5e, 0xea, 0x52, 0x77, 0x62, 0xfd, 0x35, 0x82, 0xc8, 0x0c, 0xaf, 0xd3, 0xd1, 0xf2,
|
||||
0xfc, 0xee, 0x4e, 0x96, 0x3a, 0xbb, 0xd8, 0x76, 0xfe, 0x22, 0x7a, 0x71, 0x8b, 0xc1, 0x42, 0x9c,
|
||||
0xd6, 0x99, 0xfa, 0x75, 0x3f, 0xb8, 0x0c, 0x23, 0x43, 0x35, 0x73, 0xe4, 0x44, 0xb1, 0xe6, 0x2b,
|
||||
0x4c, 0xf4, 0x8c, 0x6f, 0x9a, 0xbe, 0x04, 0x22, 0x89, 0xd7, 0xd1, 0x21, 0x10, 0x9c, 0x1d, 0x7a,
|
||||
0xef, 0x4f, 0x12, 0xd5, 0x2c, 0xf6, 0xc4, 0x2e, 0x64, 0xe2, 0xc2, 0xa1, 0xdf, 0x23, 0xf6, 0xee,
|
||||
0x88, 0xa5, 0xde, 0xbd, 0x62, 0xad, 0xca, 0xfa, 0xc8, 0x4e, 0xae, 0xdd, 0xf0, 0x5a, 0xcd, 0x09,
|
||||
0x1b, 0x90, 0x2c, 0x77, 0xc1, 0xe2, 0x3d, 0xff, 0xab, 0xb5, 0xe6, 0x56, 0xd8, 0xe5, 0x5b, 0x76,
|
||||
0x79, 0xe1, 0xa2, 0x91, 0xa5, 0xd1, 0xa0, 0x13, 0x41, 0xa3, 0x7d, 0x69, 0x88, 0xc2, 0x54, 0x64,
|
||||
0x8e, 0x76, 0xe6, 0xc7, 0xe8, 0xd2, 0xeb, 0xb7, 0xd1, 0xed, 0x14, 0x61, 0xd0, 0x23, 0x83, 0x6d,
|
||||
0x4d, 0x04, 0x01, 0x11, 0x69, 0x76, 0x60, 0x47, 0xbd, 0xa1, 0x97, 0x1c, 0x39, 0x3f, 0xe2, 0x09,
|
||||
0x3f, 0xc5, 0x5f, 0xb5, 0xd0, 0x91, 0x90, 0x81, 0xe4, 0x1c, 0xdb, 0x26, 0x0d, 0x82, 0xa3, 0x07,
|
||||
0xd6, 0x23, 0xe1, 0x45, 0x64, 0x65, 0xa7, 0x96, 0x05, 0x6b, 0x2c, 0x4f, 0x61, 0x42, 0x5d, 0x40,
|
||||
0xa7, 0xb7, 0x79, 0x2d, 0x2e, 0xfc, 0x5d, 0xec, 0x30, 0x9f, 0x56, 0x5e, 0x92, 0xa1, 0x28, 0x41,
|
||||
0x2f, 0x90, 0x2d, 0x30, 0x1c, 0xe9, 0x11, 0xd7, 0x48, 0x74, 0x9b, 0x7f, 0x5b, 0x73, 0x50, 0x04,
|
||||
0x66, 0xd9, 0xc3, 0x94, 0x93, 0x0c, 0x4e, 0x26, 0xf1, 0x7f, 0xfe, 0x84, 0xbb, 0xee, 0xc6, 0x7e,
|
||||
0x9b, 0x78, 0xf9, 0x1d, 0x20, 0xd0, 0x47, 0x0f, 0x40, 0x43, 0x6d, 0xfe, 0x21, 0x40, 0xa6, 0x17,
|
||||
0x85, 0x16, 0x7a, 0xa1, 0x31, 0xff, 0x93, 0x61, 0xfe, 0x97, 0xe7, 0x38, 0xba, 0x31, 0x2d, 0xe1,
|
||||
0xbf, 0x5a, 0xeb, 0x42, 0xe7, 0x3c, 0xef, 0xd1, 0x97, 0xa4, 0x3f, 0x1f, 0x22, 0x1f, 0x26, 0x29,
|
||||
0x6a, 0x27, 0x33, 0x23, 0x94, 0x15, 0xf0, 0x47, 0xbf, 0xd2, 0x19, 0xb3, 0xe1, 0xee, 0x4c, 0x45,
|
||||
0xff, 0x9e, 0x20, 0xca, 0xa2, 0x4c, 0xbc, 0x17, 0x28, 0x95, 0x74, 0xfe, 0x65, 0x66, 0x26, 0xcb,
|
||||
0x33, 0x99, 0x39, 0xbe, 0x2e, 0x7e, 0xc1, 0x5b, 0xd0, 0x92, 0xac, 0x8f, 0xbb, 0x22, 0x30, 0xc3,
|
||||
0xef, 0x22, 0x1f, 0x24, 0x7c, 0xc7, 0x84, 0x5d, 0x4c, 0x30, 0x76, 0xd3, 0xd9, 0xdc, 0xf6, 0xf6,
|
||||
0xa7, 0xc6, 0xd7, 0x68, 0x78, 0xe8, 0x00, 0x38, 0x30, 0xd4, 0xd5, 0xfb, 0xb1, 0xb9, 0x9d, 0x1d,
|
||||
0x8d, 0xf3, 0x28, 0x72, 0xa7, 0xe1, 0x60, 0xdf, 0xb2, 0x3b, 0x86, 0x1f, 0xdb, 0x24, 0xe1, 0x22,
|
||||
0x7c, 0x71, 0xbc, 0x2e, 0x80, 0x84, 0xd9, 0x04, 0xa3, 0x87, 0x07, 0x45, 0x3f, 0x8b, 0x4c, 0xdc,
|
||||
0x52, 0xf3, 0x48, 0x3f, 0xc4, 0x28, 0xd8, 0xad, 0x62, 0x61, 0xd5, 0x03, 0xdf, 0x54, 0xef, 0xa3,
|
||||
0xf2, 0x88, 0x60, 0xec, 0x6f, 0x3d, 0xb8, 0xd9, 0x18, 0x8f, 0xdd, 0xa6, 0xb8, 0xe8, 0x6d, 0xc7,
|
||||
0x16, 0xa4, 0xed, 0x24, 0x63, 0x7a, 0xac, 0xff, 0xc2, 0xf1, 0x98, 0x22, 0xfb, 0x43, 0xac, 0xc5,
|
||||
0xb2, 0x59, 0x3b, 0x80, 0x33, 0x3e, 0x06, 0x97, 0xde, 0xfa, 0x89, 0xd7, 0x2b, 0x87, 0x29, 0x20,
|
||||
0xb8, 0xeb, 0x90, 0x08, 0xe9, 0x74, 0xda, 0x65, 0xca, 0x93, 0xef, 0x5d, 0xf1, 0x35, 0x06, 0x52,
|
||||
0x67, 0xbc, 0x01, 0xe3, 0x66, 0xfc, 0x93, 0x0b, 0x50, 0xce, 0xbf, 0xf0, 0x7b, 0x7b, 0x9b, 0x3d,
|
||||
0x99, 0xfc, 0xf2, 0x7c, 0x75, 0x02, 0x0f, 0xfb, 0x24, 0x4c, 0xde, 0xcb, 0x81, 0xd5, 0xc8, 0xff,
|
||||
0xa0, 0x8b, 0xf2, 0xcf, 0x9f, 0xa8, 0xa4, 0x03, 0x29, 0x0c, 0xa9, 0xb5, 0x39, 0x6a, 0xc4, 0xa1,
|
||||
0xde, 0x40, 0x9a, 0x40, 0x6b, 0xf1, 0xb5, 0xb5, 0xe5, 0x31, 0x6f, 0x11, 0xa8, 0x72, 0x2b, 0xc3,
|
||||
0x58, 0x78, 0x77, 0xbb, 0x79, 0x3a, 0xda, 0xea, 0xcd, 0x6a, 0xa0, 0xa5, 0x41, 0x09, 0x8e, 0xde,
|
||||
0x01, 0x47, 0x2f, 0x83, 0x83, 0x39, 0x5f, 0x2d, 0x35, 0x34, 0xf1, 0x84, 0x29, 0x3a, 0x69, 0x29,
|
||||
0x47, 0xdb, 0x5c, 0x30, 0x7c, 0xad, 0xdb, 0xfb, 0x25, 0x29, 0x48, 0x10, 0xde, 0x9c, 0x80, 0xab,
|
||||
0xef, 0x83, 0x72, 0x23, 0xeb, 0xa3, 0x62, 0xcb, 0x1b, 0xe2, 0xfc, 0x72, 0x5b, 0xdf, 0x33, 0xde,
|
||||
0x1b, 0x1f, 0x12, 0xdf, 0x33, 0xb8, 0xc7, 0x8a, 0xdf, 0x03, 0x77, 0xa8, 0xef, 0x26, 0xfe, 0x1f,
|
||||
0x3d, 0xed, 0xd5, 0xb1, 0xc9, 0xc3, 0x00, 0x00
|
||||
};
|
||||
|
3580
wled00/html_ui.h
3580
wled00/html_ui.h
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,7 @@
|
||||
#include "wled.h"
|
||||
|
||||
#include "ir_codes.h"
|
||||
|
||||
/*
|
||||
* Infrared sensor support for generic 24/40/44 key RGB remotes
|
||||
*/
|
||||
@ -89,8 +91,8 @@ byte relativeChange(byte property, int8_t amount, byte lowerBoundary, byte highe
|
||||
void changeEffect(uint8_t fx)
|
||||
{
|
||||
if (irApplyToAllSelected) {
|
||||
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
||||
for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
|
||||
Segment& seg = strip.getSegment(i);
|
||||
if (!seg.isActive() || !seg.isSelected()) continue;
|
||||
strip.setMode(i, fx);
|
||||
}
|
||||
@ -105,8 +107,8 @@ void changeEffect(uint8_t fx)
|
||||
void changePalette(uint8_t pal)
|
||||
{
|
||||
if (irApplyToAllSelected) {
|
||||
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
||||
for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
|
||||
Segment& seg = strip.getSegment(i);
|
||||
if (!seg.isActive() || !seg.isSelected()) continue;
|
||||
seg.palette = pal;
|
||||
}
|
||||
@ -124,8 +126,8 @@ void changeEffectSpeed(int8_t amount)
|
||||
int16_t new_val = (int16_t) effectSpeed + amount;
|
||||
effectSpeed = (byte)constrain(new_val,0,255);
|
||||
if (irApplyToAllSelected) {
|
||||
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
||||
for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
|
||||
Segment& seg = strip.getSegment(i);
|
||||
if (!seg.isActive() || !seg.isSelected()) continue;
|
||||
seg.speed = effectSpeed;
|
||||
}
|
||||
@ -135,7 +137,7 @@ void changeEffectSpeed(int8_t amount)
|
||||
setValuesFromMainSeg();
|
||||
}
|
||||
} else { // if Effect == "solid Color", change the hue of the primary color
|
||||
WS2812FX::Segment& sseg = irApplyToAllSelected ? strip.getFirstSelectedSeg() : strip.getMainSegment();
|
||||
Segment& sseg = irApplyToAllSelected ? strip.getFirstSelectedSeg() : strip.getMainSegment();
|
||||
CRGB fastled_col;
|
||||
fastled_col.red = R(sseg.colors[0]);
|
||||
fastled_col.green = G(sseg.colors[0]);
|
||||
@ -147,8 +149,8 @@ void changeEffectSpeed(int8_t amount)
|
||||
prim_hsv.h = (byte)new_val;
|
||||
hsv2rgb_rainbow(prim_hsv, fastled_col);
|
||||
if (irApplyToAllSelected) {
|
||||
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
||||
for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
|
||||
Segment& seg = strip.getSegment(i);
|
||||
if (!seg.isActive() || !seg.isSelected()) continue;
|
||||
seg.colors[0] = RGBW32(fastled_col.red, fastled_col.green, fastled_col.blue, W(sseg.colors[0]));
|
||||
}
|
||||
@ -171,8 +173,8 @@ void changeEffectIntensity(int8_t amount)
|
||||
int16_t new_val = (int16_t) effectIntensity + amount;
|
||||
effectIntensity = (byte)constrain(new_val,0,255);
|
||||
if (irApplyToAllSelected) {
|
||||
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
||||
for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
|
||||
Segment& seg = strip.getSegment(i);
|
||||
if (!seg.isActive() || !seg.isSelected()) continue;
|
||||
seg.intensity = effectIntensity;
|
||||
}
|
||||
@ -182,7 +184,7 @@ void changeEffectIntensity(int8_t amount)
|
||||
setValuesFromMainSeg();
|
||||
}
|
||||
} else { // if Effect == "solid Color", change the saturation of the primary color
|
||||
WS2812FX::Segment& sseg = irApplyToAllSelected ? strip.getFirstSelectedSeg() : strip.getMainSegment();
|
||||
Segment& sseg = irApplyToAllSelected ? strip.getFirstSelectedSeg() : strip.getMainSegment();
|
||||
CRGB fastled_col;
|
||||
fastled_col.red = R(sseg.colors[0]);
|
||||
fastled_col.green = G(sseg.colors[0]);
|
||||
@ -192,8 +194,8 @@ void changeEffectIntensity(int8_t amount)
|
||||
prim_hsv.s = (byte)constrain(new_val,0,255); // constrain to 0-255
|
||||
hsv2rgb_rainbow(prim_hsv, fastled_col);
|
||||
if (irApplyToAllSelected) {
|
||||
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
||||
for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
|
||||
Segment& seg = strip.getSegment(i);
|
||||
if (!seg.isActive() || !seg.isSelected()) continue;
|
||||
seg.colors[0] = RGBW32(fastled_col.red, fastled_col.green, fastled_col.blue, W(sseg.colors[0]));
|
||||
}
|
||||
@ -214,8 +216,8 @@ void changeColor(uint32_t c, int16_t cct=-1)
|
||||
{
|
||||
if (irApplyToAllSelected) {
|
||||
// main segment may not be selected!
|
||||
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
||||
for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
|
||||
Segment& seg = strip.getSegment(i);
|
||||
if (!seg.isActive() || !seg.isSelected()) continue;
|
||||
byte capabilities = seg.getLightCapabilities();
|
||||
uint32_t mask = 0;
|
||||
@ -226,14 +228,14 @@ void changeColor(uint32_t c, int16_t cct=-1)
|
||||
if (isRGB) mask |= 0x00FFFFFF; // RGB
|
||||
if (hasW) mask |= 0xFF000000; // white
|
||||
if (hasW && !wSlider && (c & 0xFF000000)) { // segment has white channel & white channel is auto calculated & white specified
|
||||
seg.setColor(0, c | 0xFFFFFF, i); // for accurate/brighter mode we fake white (since button may not set white color to 0xFFFFFF)
|
||||
} else if (c & mask) seg.setColor(0, c & mask, i); // only apply if not black
|
||||
if (isCCT && cct >= 0) seg.setCCT(cct, i);
|
||||
seg.setColor(0, c | 0xFFFFFF); // for accurate/brighter mode we fake white (since button may not set white color to 0xFFFFFF)
|
||||
} else if (c & mask) seg.setColor(0, c & mask); // only apply if not black
|
||||
if (isCCT && cct >= 0) seg.setCCT(cct);
|
||||
}
|
||||
setValuesFromFirstSelectedSeg();
|
||||
} else {
|
||||
byte i = strip.getMainSegmentId();
|
||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
||||
Segment& seg = strip.getSegment(i);
|
||||
byte capabilities = seg.getLightCapabilities();
|
||||
uint32_t mask = 0;
|
||||
bool isRGB = GET_BIT(capabilities, 0); // is segment RGB capable
|
||||
@ -243,9 +245,9 @@ void changeColor(uint32_t c, int16_t cct=-1)
|
||||
if (isRGB) mask |= 0x00FFFFFF; // RGB
|
||||
if (hasW) mask |= 0xFF000000; // white
|
||||
if (hasW && !wSlider && (c & 0xFF000000)) { // segment has white channel & white channel is auto calculated & white specified
|
||||
seg.setColor(0, c | 0xFFFFFF, i); // for accurate/brighter mode we fake white (since button may not set white color to 0xFFFFFF)
|
||||
} else if (c & mask) seg.setColor(0, c & mask, i); // only apply if not black
|
||||
if (isCCT && cct >= 0) seg.setCCT(cct, i);
|
||||
seg.setColor(0, c | 0xFFFFFF); // for accurate/brighter mode we fake white (since button may not set white color to 0xFFFFFF)
|
||||
} else if (c & mask) seg.setColor(0, c & mask); // only apply if not black
|
||||
if (isCCT && cct >= 0) seg.setCCT(cct);
|
||||
setValuesFromMainSeg();
|
||||
}
|
||||
stateChanged = true;
|
||||
@ -253,7 +255,7 @@ void changeColor(uint32_t c, int16_t cct=-1)
|
||||
|
||||
void changeWhite(int8_t amount, int16_t cct=-1)
|
||||
{
|
||||
WS2812FX::Segment& seg = irApplyToAllSelected ? strip.getFirstSelectedSeg() : strip.getMainSegment();
|
||||
Segment& seg = irApplyToAllSelected ? strip.getFirstSelectedSeg() : strip.getMainSegment();
|
||||
byte r = R(seg.colors[0]);
|
||||
byte g = G(seg.colors[0]);
|
||||
byte b = B(seg.colors[0]);
|
||||
@ -424,7 +426,7 @@ void decodeIR24CT(uint32_t code)
|
||||
|
||||
void decodeIR40(uint32_t code)
|
||||
{
|
||||
WS2812FX::Segment& seg = irApplyToAllSelected ? strip.getFirstSelectedSeg() : strip.getMainSegment();
|
||||
Segment& seg = irApplyToAllSelected ? strip.getFirstSelectedSeg() : strip.getMainSegment();
|
||||
byte r = R(seg.colors[0]);
|
||||
byte g = G(seg.colors[0]);
|
||||
byte b = B(seg.colors[0]);
|
||||
@ -502,8 +504,8 @@ void decodeIR44(uint32_t code)
|
||||
case IR44_WARMWHITE : changeColor(COLOR_WARMWHITE, 63); changeEffect(FX_MODE_STATIC); break;
|
||||
case IR44_COLDWHITE : changeColor(COLOR_COLDWHITE, 191); changeEffect(FX_MODE_STATIC); break;
|
||||
case IR44_COLDWHITE2 : changeColor(COLOR_COLDWHITE2, 255); changeEffect(FX_MODE_STATIC); break;
|
||||
case IR44_REDPLUS : changeEffect(relativeChange(effectCurrent, 1, 0, MODE_COUNT -1)); break;
|
||||
case IR44_REDMINUS : changeEffect(relativeChange(effectCurrent, -1, 0, MODE_COUNT -1)); break;
|
||||
case IR44_REDPLUS : changeEffect(relativeChange(effectCurrent, 1, 0, strip.getModeCount() -1)); break;
|
||||
case IR44_REDMINUS : changeEffect(relativeChange(effectCurrent, -1, 0, strip.getModeCount() -1)); break;
|
||||
case IR44_GREENPLUS : changePalette(relativeChange(effectPalette, 1, 0, strip.getPaletteCount() -1)); break;
|
||||
case IR44_GREENMINUS : changePalette(relativeChange(effectPalette, -1, 0, strip.getPaletteCount() -1)); break;
|
||||
case IR44_BLUEPLUS : changeEffectIntensity( 16); break;
|
||||
@ -562,7 +564,7 @@ void decodeIR6(uint32_t code)
|
||||
case IR6_POWER: toggleOnOff(); break;
|
||||
case IR6_CHANNEL_UP: incBrightness(); break;
|
||||
case IR6_CHANNEL_DOWN: decBrightness(); break;
|
||||
case IR6_VOLUME_UP: changeEffect(relativeChange(effectCurrent, 1, 0, MODE_COUNT -1)); break;
|
||||
case IR6_VOLUME_UP: changeEffect(relativeChange(effectCurrent, 1, 0, strip.getModeCount() -1)); break;
|
||||
case IR6_VOLUME_DOWN: changePalette(relativeChange(effectPalette, 1, 0, strip.getPaletteCount() -1));
|
||||
switch(lastIR6ColourIdx) {
|
||||
case 0: changeColor(COLOR_RED); break;
|
||||
@ -600,7 +602,7 @@ void decodeIR9(uint32_t code)
|
||||
case IR9_DOWN : decBrightness(); break;
|
||||
case IR9_LEFT : changeEffectSpeed(-16); break;
|
||||
case IR9_RIGHT : changeEffectSpeed(16); break;
|
||||
case IR9_SELECT : changeEffect(relativeChange(effectCurrent, 1, 0, MODE_COUNT -1)); break;
|
||||
case IR9_SELECT : changeEffect(relativeChange(effectCurrent, 1, 0, strip.getModeCount() -1)); break;
|
||||
default: return;
|
||||
}
|
||||
lastValidCode = code;
|
||||
@ -670,7 +672,7 @@ void decodeIRJson(uint32_t code)
|
||||
decBrightness();
|
||||
} else if (cmdStr.startsWith(F("!presetF"))) { //!presetFallback
|
||||
uint8_t p1 = fdo["PL"] | 1;
|
||||
uint8_t p2 = fdo["FX"] | random8(MODE_COUNT -1);
|
||||
uint8_t p2 = fdo["FX"] | random8(strip.getModeCount() -1);
|
||||
uint8_t p3 = fdo["FP"] | 0;
|
||||
presetFallback(p1, p2, p3);
|
||||
}
|
||||
@ -712,7 +714,7 @@ void initIR()
|
||||
|
||||
void handleIR()
|
||||
{
|
||||
if (irEnabled > 0 && millis() - irCheckedTime > 120)
|
||||
if (irEnabled > 0 && millis() - irCheckedTime > 120 && !strip.isUpdating())
|
||||
{
|
||||
irCheckedTime = millis();
|
||||
if (irEnabled > 0)
|
||||
|
414
wled00/json.cpp
414
wled00/json.cpp
@ -11,15 +11,26 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
||||
byte id = elem["id"] | it;
|
||||
if (id >= strip.getMaxSegments()) return;
|
||||
|
||||
WS2812FX::Segment& seg = strip.getSegment(id);
|
||||
WS2812FX::Segment prev = seg; //make a backup so we can tell if something changed
|
||||
int stop = elem["stop"] | -1;
|
||||
|
||||
// if using vectors use this code to append segment
|
||||
if (id >= strip.getSegmentsNum()) {
|
||||
if (stop <= 0) return; // ignore empty/inactive segments
|
||||
strip.appendSegment(Segment(0, strip.getLengthTotal()));
|
||||
id = strip.getSegmentsNum()-1; // segments are added at the end of list
|
||||
}
|
||||
|
||||
Segment& seg = strip.getSegment(id);
|
||||
Segment prev = seg; //make a backup so we can tell if something changed
|
||||
|
||||
uint16_t start = elem["start"] | seg.start;
|
||||
int stop = elem["stop"] | -1;
|
||||
if (stop < 0) {
|
||||
uint16_t len = elem["len"];
|
||||
stop = (len > 0) ? start + len : seg.stop;
|
||||
}
|
||||
// 2D segments
|
||||
uint16_t startY = elem["startY"] | seg.startY;
|
||||
uint16_t stopY = elem["stopY"] | seg.stopY;
|
||||
|
||||
//repeat, multiplies segment until all LEDs are used, or max segments reached
|
||||
bool repeat = elem["rpt"] | false;
|
||||
@ -28,9 +39,10 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
||||
elem.remove("rpt"); // remove for recursive call
|
||||
elem.remove("n"); // remove for recursive call
|
||||
uint16_t len = stop - start;
|
||||
for (byte i=id+1; i<strip.getMaxSegments(); i++) {
|
||||
for (size_t i=id+1; i<strip.getMaxSegments(); i++) {
|
||||
start = start + len;
|
||||
if (start >= strip.getLengthTotal()) break;
|
||||
//TODO: add support for 2D
|
||||
elem["start"] = start;
|
||||
elem["stop"] = start + len;
|
||||
elem["rev"] = !elem["rev"]; // alternate reverse on even/odd segments
|
||||
@ -66,7 +78,14 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
||||
|
||||
uint16_t grp = elem["grp"] | seg.grouping;
|
||||
uint16_t spc = elem[F("spc")] | seg.spacing;
|
||||
uint16_t of = seg.offset;
|
||||
uint16_t of = seg.offset;
|
||||
uint8_t soundSim = elem[F("ssim")] | seg.soundSim;
|
||||
uint8_t map1D2D = elem[F("mp12")] | seg.map1D2D;
|
||||
|
||||
if ((spc>0 && spc!=seg.spacing) || seg.map1D2D!=map1D2D) seg.fill(BLACK); // clear spacing gaps
|
||||
|
||||
seg.map1D2D = map1D2D & 0x03;
|
||||
seg.soundSim = soundSim & 0x07;
|
||||
|
||||
uint16_t len = 1;
|
||||
if (stop > start) len = stop - start;
|
||||
@ -78,27 +97,27 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
||||
of = offsetAbs;
|
||||
}
|
||||
if (stop > start && of > len -1) of = len -1;
|
||||
strip.setSegment(id, start, stop, grp, spc, of);
|
||||
strip.setSegment(id, start, stop, grp, spc, of, startY, stopY);
|
||||
|
||||
byte segbri = seg.opacity;
|
||||
if (getVal(elem["bri"], &segbri)) {
|
||||
if (segbri > 0) seg.setOpacity(segbri, id);
|
||||
seg.setOption(SEG_OPTION_ON, segbri, id);
|
||||
if (segbri > 0) seg.setOpacity(segbri);
|
||||
seg.setOption(SEG_OPTION_ON, segbri);
|
||||
}
|
||||
|
||||
bool on = elem["on"] | seg.getOption(SEG_OPTION_ON);
|
||||
if (elem["on"].is<const char*>() && elem["on"].as<const char*>()[0] == 't') on = !on;
|
||||
seg.setOption(SEG_OPTION_ON, on, id);
|
||||
seg.setOption(SEG_OPTION_ON, on);
|
||||
bool frz = elem["frz"] | seg.getOption(SEG_OPTION_FREEZE);
|
||||
if (elem["frz"].is<const char*>() && elem["frz"].as<const char*>()[0] == 't') frz = !seg.getOption(SEG_OPTION_FREEZE);
|
||||
seg.setOption(SEG_OPTION_FREEZE, frz, id);
|
||||
seg.setOption(SEG_OPTION_FREEZE, frz);
|
||||
|
||||
seg.setCCT(elem["cct"] | seg.cct, id);
|
||||
seg.setCCT(elem["cct"] | seg.cct);
|
||||
|
||||
JsonArray colarr = elem["col"];
|
||||
if (!colarr.isNull())
|
||||
{
|
||||
for (uint8_t i = 0; i < 3; i++)
|
||||
for (size_t i = 0; i < 3; i++)
|
||||
{
|
||||
int rgbw[] = {0,0,0,0};
|
||||
bool colValid = false;
|
||||
@ -109,13 +128,13 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
||||
if (hexCol == nullptr) { //Kelvin color temperature (or invalid), e.g 2400
|
||||
int kelvin = colarr[i] | -1;
|
||||
if (kelvin < 0) continue;
|
||||
if (kelvin == 0) seg.setColor(i, 0, id);
|
||||
if (kelvin == 0) seg.setColor(i, 0);
|
||||
if (kelvin > 0) colorKtoRGB(kelvin, brgbw);
|
||||
colValid = true;
|
||||
} else { //HEX string, e.g. "FFAA00"
|
||||
colValid = colorFromHexString(brgbw, hexCol);
|
||||
}
|
||||
for (uint8_t c = 0; c < 4; c++) rgbw[c] = brgbw[c];
|
||||
for (size_t c = 0; c < 4; c++) rgbw[c] = brgbw[c];
|
||||
} else { //Array of ints (RGB or RGBW color), e.g. [255,160,0]
|
||||
byte sz = colX.size();
|
||||
if (sz == 0) continue; //do nothing on empty array
|
||||
@ -126,7 +145,7 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
||||
|
||||
if (!colValid) continue;
|
||||
|
||||
seg.setColor(i, RGBW32(rgbw[0],rgbw[1],rgbw[2],rgbw[3]), id);
|
||||
seg.setColor(i, RGBW32(rgbw[0],rgbw[1],rgbw[2],rgbw[3]));
|
||||
if (seg.mode == FX_MODE_STATIC) strip.trigger(); //instant refresh
|
||||
}
|
||||
}
|
||||
@ -143,28 +162,76 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
||||
}
|
||||
#endif
|
||||
|
||||
seg.setOption(SEG_OPTION_SELECTED, elem[F("sel")] | seg.getOption(SEG_OPTION_SELECTED));
|
||||
seg.setOption(SEG_OPTION_REVERSED, elem["rev"] | seg.getOption(SEG_OPTION_REVERSED));
|
||||
seg.setOption(SEG_OPTION_MIRROR , elem[F("mi")] | seg.getOption(SEG_OPTION_MIRROR ));
|
||||
seg.setOption(SEG_OPTION_SELECTED, elem["sel"] | seg.getOption(SEG_OPTION_SELECTED));
|
||||
seg.setOption(SEG_OPTION_REVERSED, elem["rev"] | seg.getOption(SEG_OPTION_REVERSED));
|
||||
seg.setOption(SEG_OPTION_MIRROR , elem[F("mi")] | seg.getOption(SEG_OPTION_MIRROR ));
|
||||
#ifndef WLED_DISABLE_2D
|
||||
seg.setOption(SEG_OPTION_REVERSED_Y, elem[F("rY")] | seg.getOption(SEG_OPTION_REVERSED_Y));
|
||||
seg.setOption(SEG_OPTION_MIRROR_Y , elem[F("mY")] | seg.getOption(SEG_OPTION_MIRROR_Y ));
|
||||
seg.setOption(SEG_OPTION_TRANSPOSED, elem[F("tp")] | seg.getOption(SEG_OPTION_TRANSPOSED));
|
||||
#endif
|
||||
|
||||
byte fx = seg.mode;
|
||||
if (getVal(elem["fx"], &fx, 1, strip.getModeCount())) { //load effect ('r' random, '~' inc/dec, 1-255 exact value)
|
||||
if (getVal(elem["fx"], &fx, 0, strip.getModeCount())) { //load effect ('r' random, '~' inc/dec, 0-255 exact value)
|
||||
if (!presetId && currentPlaylist>=0) unloadPlaylist();
|
||||
strip.setMode(id, fx);
|
||||
if (fx != seg.mode) {
|
||||
seg.startTransition(strip.getTransition()); // set effect transitions
|
||||
//seg.markForReset();
|
||||
seg.mode = fx;
|
||||
// load default values from effect string if effect is selected without
|
||||
// any other effect parameter (i.e. effect clicked in UI)
|
||||
if ( elem[F("sx")].isNull()
|
||||
&& elem[F("ix")].isNull()
|
||||
&& elem["pal"].isNull()
|
||||
&& elem[F("c1")].isNull()
|
||||
&& elem[F("c2")].isNull()
|
||||
&& elem[F("c3")].isNull() )
|
||||
{
|
||||
int16_t sOpt;
|
||||
sOpt = extractModeDefaults(fx, SET_F("sx")); if (sOpt >= 0) seg.speed = sOpt;
|
||||
sOpt = extractModeDefaults(fx, SET_F("ix")); if (sOpt >= 0) seg.intensity = sOpt;
|
||||
sOpt = extractModeDefaults(fx, SET_F("c1")); if (sOpt >= 0) seg.custom1 = sOpt;
|
||||
sOpt = extractModeDefaults(fx, SET_F("c2")); if (sOpt >= 0) seg.custom2 = sOpt;
|
||||
sOpt = extractModeDefaults(fx, SET_F("c3")); if (sOpt >= 0) seg.custom3 = sOpt;
|
||||
sOpt = extractModeDefaults(fx, SET_F("mp12")); if (sOpt >= 0) seg.map1D2D = sOpt & 0x03;
|
||||
sOpt = extractModeDefaults(fx, SET_F("ssim")); if (sOpt >= 0) seg.soundSim = sOpt & 0x07;
|
||||
sOpt = extractModeDefaults(fx, "rev"); if (sOpt >= 0) seg.reverse = (bool)sOpt;
|
||||
sOpt = extractModeDefaults(fx, SET_F("mi")); if (sOpt >= 0) seg.mirror = (bool)sOpt; // NOTE: setting this option is a risky business
|
||||
sOpt = extractModeDefaults(fx, SET_F("rY")); if (sOpt >= 0) seg.reverse_y = (bool)sOpt;
|
||||
sOpt = extractModeDefaults(fx, SET_F("mY")); if (sOpt >= 0) seg.mirror_y = (bool)sOpt; // NOTE: setting this option is a risky business
|
||||
sOpt = extractModeDefaults(fx, "pal");
|
||||
if (sOpt >= 0 && sOpt < strip.getPaletteCount() + strip.customPalettes.size()) {
|
||||
if (sOpt != seg.palette) {
|
||||
if (strip.paletteFade && !seg.transitional) seg.startTransition(strip.getTransition());
|
||||
seg.palette = sOpt;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//getVal also supports inc/decrementing and random
|
||||
getVal(elem[F("sx")], &seg.speed, 0, 255);
|
||||
getVal(elem[F("ix")], &seg.intensity, 0, 255);
|
||||
getVal(elem["pal"], &seg.palette, 1, strip.getPaletteCount());
|
||||
getVal(elem[F("c1x")], &seg.c1x, 0, 255);
|
||||
getVal(elem[F("c2x")], &seg.c2x, 0, 255);
|
||||
getVal(elem[F("c3x")], &seg.c3x, 0, 255);
|
||||
getVal(elem[F("sx")], &seg.speed);
|
||||
getVal(elem[F("ix")], &seg.intensity);
|
||||
uint8_t pal = seg.palette;
|
||||
if (getVal(elem["pal"], &pal, 1, strip.getPaletteCount())) {
|
||||
if (pal != seg.palette) {
|
||||
if (strip.paletteFade && !seg.transitional) seg.startTransition(strip.getTransition());
|
||||
seg.palette = pal;
|
||||
}
|
||||
}
|
||||
getVal(elem[F("c1")], &seg.custom1);
|
||||
getVal(elem[F("c2")], &seg.custom2);
|
||||
uint8_t cust3 = seg.custom3;
|
||||
getVal(elem[F("c3")], &cust3); // we can't pass reference to bifield
|
||||
seg.custom3 = cust3;
|
||||
|
||||
seg.check1 = elem[F("o1")] | seg.check1;
|
||||
seg.check2 = elem[F("o2")] | seg.check2;
|
||||
seg.check3 = elem[F("o3")] | seg.check3;
|
||||
|
||||
JsonArray iarr = elem[F("i")]; //set individual LEDs
|
||||
if (!iarr.isNull()) {
|
||||
uint8_t oldSegId = strip.setPixelSegment(id);
|
||||
|
||||
// set brightness immediately and disable transition
|
||||
transitionDelayTemp = 0;
|
||||
jsonTransitionOnce = true;
|
||||
@ -173,13 +240,13 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
||||
// freeze and init to black
|
||||
if (!seg.getOption(SEG_OPTION_FREEZE)) {
|
||||
seg.setOption(SEG_OPTION_FREEZE, true);
|
||||
strip.fill(0);
|
||||
seg.fill(BLACK);
|
||||
}
|
||||
|
||||
uint16_t start = 0, stop = 0;
|
||||
byte set = 0; //0 nothing set, 1 start set, 2 range set
|
||||
|
||||
for (uint16_t i = 0; i < iarr.size(); i++) {
|
||||
for (size_t i = 0; i < iarr.size(); i++) {
|
||||
if(iarr[i].is<JsonInteger>()) {
|
||||
if (!set) {
|
||||
start = iarr[i];
|
||||
@ -189,7 +256,7 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
||||
set = 2;
|
||||
}
|
||||
} else { //color
|
||||
int rgbw[] = {0,0,0,0};
|
||||
uint8_t rgbw[] = {0,0,0,0};
|
||||
JsonArray icol = iarr[i];
|
||||
if (!icol.isNull()) { //array, e.g. [255,0,0]
|
||||
byte sz = icol.size();
|
||||
@ -198,29 +265,27 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
||||
byte brgbw[] = {0,0,0,0};
|
||||
const char* hexCol = iarr[i];
|
||||
if (colorFromHexString(brgbw, hexCol)) {
|
||||
for (uint8_t c = 0; c < 4; c++) rgbw[c] = brgbw[c];
|
||||
for (size_t c = 0; c < 4; c++) rgbw[c] = brgbw[c];
|
||||
}
|
||||
}
|
||||
|
||||
if (set < 2) stop = start + 1;
|
||||
for (uint16_t i = start; i < stop; i++) {
|
||||
for (int i = start; i < stop; i++) {
|
||||
if (strip.gammaCorrectCol) {
|
||||
strip.setPixelColor(i, strip.gamma8(rgbw[0]), strip.gamma8(rgbw[1]), strip.gamma8(rgbw[2]), strip.gamma8(rgbw[3]));
|
||||
seg.setPixelColor(i, gamma8(rgbw[0]), gamma8(rgbw[1]), gamma8(rgbw[2]), gamma8(rgbw[3]));
|
||||
} else {
|
||||
strip.setPixelColor(i, rgbw[0], rgbw[1], rgbw[2], rgbw[3]);
|
||||
seg.setPixelColor(i, rgbw[0], rgbw[1], rgbw[2], rgbw[3]);
|
||||
}
|
||||
}
|
||||
if (!set) start++;
|
||||
set = 0;
|
||||
}
|
||||
}
|
||||
strip.setPixelSegment(oldSegId);
|
||||
strip.trigger();
|
||||
}
|
||||
// send UDP if not in preset and something changed that is not just selection
|
||||
// send UDP if something changed that is not just selection or segment power/opacity
|
||||
if ((seg.differs(prev) & 0x7E) && seg.getOption(SEG_OPTION_ON)==prev.getOption(SEG_OPTION_ON)) stateChanged = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// deserializes WLED state (fileDoc points to doc object if called from web server)
|
||||
@ -230,19 +295,30 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
|
||||
bool stateResponse = root[F("v")] | false;
|
||||
|
||||
bool onBefore = bri;
|
||||
getVal(root["bri"], &bri);
|
||||
uint8_t tmpBri = bri;
|
||||
getVal(root["bri"], &tmpBri);
|
||||
|
||||
bool on = root["on"] | (bri > 0);
|
||||
if (!on != !bri) toggleOnOff();
|
||||
|
||||
if (root["on"].is<const char*>() && root["on"].as<const char*>()[0] == 't') toggleOnOff();
|
||||
if (root["on"].isNull()) {
|
||||
if ((onBefore && tmpBri==0) || (!onBefore && tmpBri>0)) toggleOnOff();
|
||||
bri = tmpBri;
|
||||
} else {
|
||||
bool on = root["on"] | onBefore;
|
||||
if (on != onBefore || (root["on"].is<const char*>() && root["on"].as<const char*>()[0] == 't')) {
|
||||
toggleOnOff();
|
||||
// a hack is needed after toggleOnOf()
|
||||
if (!root["bri"].isNull()) {
|
||||
if (bri==0) briLast = tmpBri;
|
||||
else bri = tmpBri;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bri && !onBefore) { // unfreeze all segments when turning on
|
||||
for (uint8_t s=0; s < strip.getMaxSegments(); s++) {
|
||||
strip.getSegment(s).setOption(SEG_OPTION_FREEZE, false, s);
|
||||
for (size_t s=0; s < strip.getSegmentsNum(); s++) {
|
||||
strip.getSegment(s).setOption(SEG_OPTION_FREEZE, false);
|
||||
}
|
||||
if (realtimeMode && !realtimeOverride && useMainSegmentOnly) { // keep live segment frozen if live
|
||||
strip.getMainSegment().setOption(SEG_OPTION_FREEZE, true, strip.getMainSegmentId());
|
||||
strip.getMainSegment().setOption(SEG_OPTION_FREEZE, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -257,6 +333,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
|
||||
}
|
||||
}
|
||||
|
||||
// temporary transition (applies only once)
|
||||
tr = root[F("tt")] | -1;
|
||||
if (tr >= 0)
|
||||
{
|
||||
@ -294,7 +371,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
|
||||
realtimeOverride = root[F("lor")] | realtimeOverride;
|
||||
if (realtimeOverride > 2) realtimeOverride = REALTIME_OVERRIDE_ALWAYS;
|
||||
if (realtimeMode && useMainSegmentOnly) {
|
||||
strip.getMainSegment().setOption(SEG_OPTION_FREEZE, !realtimeOverride, strip.getMainSegmentId());
|
||||
strip.getMainSegment().setOption(SEG_OPTION_FREEZE, !realtimeOverride);
|
||||
}
|
||||
|
||||
if (root.containsKey("live")) {
|
||||
@ -316,13 +393,11 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
|
||||
if (id < 0) {
|
||||
//apply all selected segments
|
||||
//bool didSet = false;
|
||||
for (byte s = 0; s < strip.getMaxSegments(); s++) {
|
||||
WS2812FX::Segment &sg = strip.getSegment(s);
|
||||
if (sg.isActive()) {
|
||||
if (sg.isSelected()) {
|
||||
deserializeSegment(segVar, s, presetId);
|
||||
//didSet = true;
|
||||
}
|
||||
for (size_t s = 0; s < strip.getSegmentsNum(); s++) {
|
||||
Segment &sg = strip.getSegment(s);
|
||||
if (sg.isSelected()) {
|
||||
deserializeSegment(segVar, s, presetId);
|
||||
//didSet = true;
|
||||
}
|
||||
}
|
||||
//TODO: not sure if it is good idea to change first active but unselected segment
|
||||
@ -332,8 +407,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
|
||||
}
|
||||
} else {
|
||||
JsonArray segs = segVar.as<JsonArray>();
|
||||
for (JsonObject elem : segs)
|
||||
{
|
||||
for (JsonObject elem : segs) {
|
||||
deserializeSegment(elem, it, presetId);
|
||||
it++;
|
||||
}
|
||||
@ -344,28 +418,34 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
|
||||
loadLedmap = root[F("ledmap")] | loadLedmap;
|
||||
|
||||
byte ps = root[F("psave")];
|
||||
if (ps > 0) {
|
||||
savePreset(ps, nullptr, root);
|
||||
} else {
|
||||
ps = root[F("pdel")]; //deletion
|
||||
if (ps > 0) {
|
||||
deletePreset(ps);
|
||||
}
|
||||
if (ps > 0 && ps < 251) savePreset(ps, nullptr, root);
|
||||
|
||||
ps = root[F("pdel")]; //deletion
|
||||
if (ps > 0 && ps < 251) deletePreset(ps);
|
||||
|
||||
// HTTP API commands (must be handled before "ps")
|
||||
const char* httpwin = root["win"];
|
||||
if (httpwin) {
|
||||
String apireq = "win"; apireq += '&'; // reduce flash string usage
|
||||
apireq += httpwin;
|
||||
handleSet(nullptr, apireq, false); // may set stateChanged
|
||||
}
|
||||
|
||||
// applying preset (2 cases: a) API call includes all preset values, b) API only specifies preset ID)
|
||||
if (!root["ps"].isNull()) {
|
||||
ps = presetCycCurr;
|
||||
if (getVal(root["ps"], &ps, presetCycMin, presetCycMax)) { //load preset (clears state request!)
|
||||
if (ps >= presetCycMin && ps <= presetCycMax) presetCycCurr = ps;
|
||||
applyPreset(ps, callMode, !presetId); // may clear root object and replace it by preset content if presetId==0
|
||||
if (stateChanged) {
|
||||
// a) already applied preset content (requires "seg" or "win" but will ignore the rest)
|
||||
currentPreset = root["ps"] | currentPreset;
|
||||
// if preset contains HTTP API call do not change presetCycCurr
|
||||
if (root["win"].isNull()) presetCycCurr = currentPreset;
|
||||
stateChanged = false; // cancel state change update (preset was set directly by applying values stored in UI JSON array)
|
||||
} else if (root["win"].isNull() && getVal(root["ps"], &ps, 0, 0) && ps > 0 && ps < 251 && ps != currentPreset) {
|
||||
// b) preset ID only (use embedded cycling limits if they exist in getVal())
|
||||
presetCycCurr = ps;
|
||||
applyPreset(ps, callMode); // async load
|
||||
return stateResponse;
|
||||
}
|
||||
|
||||
//HTTP API commands
|
||||
const char* httpwin = root["win"];
|
||||
if (httpwin) {
|
||||
String apireq = "win"; apireq += '&'; // reduce flash string usage
|
||||
apireq += httpwin;
|
||||
handleSet(nullptr, apireq, false);
|
||||
}
|
||||
}
|
||||
|
||||
JsonObject playlist = root[F("playlist")];
|
||||
@ -380,12 +460,16 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
|
||||
return stateResponse;
|
||||
}
|
||||
|
||||
void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id, bool forPreset, bool segmentBounds)
|
||||
void serializeSegment(JsonObject& root, Segment& seg, byte id, bool forPreset, bool segmentBounds)
|
||||
{
|
||||
root["id"] = id;
|
||||
if (segmentBounds) {
|
||||
root["start"] = seg.start;
|
||||
root["stop"] = seg.stop;
|
||||
if (strip.isMatrix) {
|
||||
root[F("startY")] = seg.startY;
|
||||
root[F("stopY")] = seg.stopY;
|
||||
}
|
||||
}
|
||||
if (!forPreset) root["len"] = seg.stop - seg.start;
|
||||
root["grp"] = seg.grouping;
|
||||
@ -403,7 +487,7 @@ void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id, bool fo
|
||||
// this will reduce RAM footprint from ~300 bytes to 84 bytes per segment
|
||||
char colstr[70]; colstr[0] = '['; colstr[1] = '\0'; //max len 68 (5 chan, all 255)
|
||||
const char *format = strip.hasWhiteChannel() ? PSTR("[%u,%u,%u,%u]") : PSTR("[%u,%u,%u]");
|
||||
for (uint8_t i = 0; i < 3; i++)
|
||||
for (size_t i = 0; i < 3; i++)
|
||||
{
|
||||
byte segcol[4]; byte* c = segcol;
|
||||
segcol[0] = R(seg.colors[i]);
|
||||
@ -421,12 +505,22 @@ void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id, bool fo
|
||||
root[F("sx")] = seg.speed;
|
||||
root[F("ix")] = seg.intensity;
|
||||
root["pal"] = seg.palette;
|
||||
root[F("c1x")] = seg.c1x;
|
||||
root[F("c2x")] = seg.c2x;
|
||||
root[F("c3x")] = seg.c3x;
|
||||
root[F("c1")] = seg.custom1;
|
||||
root[F("c2")] = seg.custom2;
|
||||
root[F("c3")] = seg.custom3;
|
||||
root[F("sel")] = seg.isSelected();
|
||||
root["rev"] = seg.getOption(SEG_OPTION_REVERSED);
|
||||
root[F("mi")] = seg.getOption(SEG_OPTION_MIRROR);
|
||||
if (strip.isMatrix) {
|
||||
root[F("rY")] = seg.getOption(SEG_OPTION_REVERSED_Y);
|
||||
root[F("mY")] = seg.getOption(SEG_OPTION_MIRROR_Y);
|
||||
root[F("tp")] = seg.getOption(SEG_OPTION_TRANSPOSED);
|
||||
}
|
||||
root[F("o1")] = seg.check1;
|
||||
root[F("o2")] = seg.check2;
|
||||
root[F("o3")] = seg.check3;
|
||||
root[F("ssim")] = seg.soundSim;
|
||||
root[F("mp12")] = seg.map1D2D;
|
||||
}
|
||||
|
||||
void serializeState(JsonObject root, bool forPreset, bool includeBri, bool segmentBounds)
|
||||
@ -435,7 +529,6 @@ void serializeState(JsonObject root, bool forPreset, bool includeBri, bool segme
|
||||
root["on"] = (bri > 0);
|
||||
root["bri"] = briLast;
|
||||
root[F("transition")] = transitionDelay/100; //in 100ms
|
||||
root[F("tdd")] = transitionDelayDefault/100; //in 100ms
|
||||
}
|
||||
|
||||
if (!forPreset) {
|
||||
@ -468,9 +561,17 @@ void serializeState(JsonObject root, bool forPreset, bool includeBri, bool segme
|
||||
|
||||
bool selectedSegmentsOnly = root[F("sc")] | false;
|
||||
JsonArray seg = root.createNestedArray("seg");
|
||||
for (byte s = 0; s < strip.getMaxSegments(); s++) {
|
||||
WS2812FX::Segment &sg = strip.getSegment(s);
|
||||
if (selectedSegmentsOnly && !sg.isSelected()) continue;
|
||||
for (size_t s = 0; s < strip.getMaxSegments(); s++) {
|
||||
if (s >= strip.getSegmentsNum()) {
|
||||
if (forPreset && segmentBounds) { //disable segments not part of preset
|
||||
JsonObject seg0 = seg.createNestedObject();
|
||||
seg0["stop"] = 0;
|
||||
continue;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
Segment &sg = strip.getSegment(s);
|
||||
if (!forPreset && selectedSegmentsOnly && !sg.isSelected()) continue;
|
||||
if (sg.isActive()) {
|
||||
JsonObject seg0 = seg.createNestedObject();
|
||||
serializeSegment(seg0, sg, s, forPreset, segmentBounds);
|
||||
@ -493,12 +594,23 @@ void serializeInfo(JsonObject root)
|
||||
leds["fps"] = strip.getFps();
|
||||
leds[F("maxpwr")] = (strip.currentMilliamps)? strip.ablMilliampsMax : 0;
|
||||
leds[F("maxseg")] = strip.getMaxSegments();
|
||||
//leds[F("actseg")] = strip.getActiveSegmentsNum();
|
||||
//leds[F("seglock")] = false; //might be used in the future to prevent modifications to segment config
|
||||
|
||||
leds[F("cpal")] = strip.customPalettes.size(); //number of custom palettes
|
||||
|
||||
#ifndef WLED_DISABLE_2D
|
||||
if (strip.isMatrix) {
|
||||
JsonObject matrix = leds.createNestedObject("matrix");
|
||||
matrix["w"] = strip.matrixWidth;
|
||||
matrix["h"] = strip.matrixHeight;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t totalLC = 0;
|
||||
JsonArray lcarr = leds.createNestedArray(F("seglc"));
|
||||
uint8_t nSegs = strip.getLastActiveSegmentId();
|
||||
for (byte s = 0; s <= nSegs; s++) {
|
||||
size_t nSegs = strip.getSegmentsNum();
|
||||
for (size_t s = 0; s < nSegs; s++) {
|
||||
if (!strip.getSegment(s).isActive()) continue;
|
||||
uint8_t lc = strip.getSegment(s).getLightCapabilities();
|
||||
totalLC |= lc;
|
||||
lcarr.add(lc);
|
||||
@ -510,6 +622,19 @@ void serializeInfo(JsonObject root)
|
||||
leds[F("wv")] = totalLC & 0x02; // deprecated, true if white slider should be displayed for any segment
|
||||
leds["cct"] = totalLC & 0x04; // deprecated, use info.leds.lc
|
||||
|
||||
#ifdef WLED_DISABLE_AUDIO
|
||||
root[F("noaudio")] = true;
|
||||
#endif
|
||||
|
||||
#ifdef WLED_DEBUG
|
||||
JsonArray i2c = root.createNestedArray(F("i2c"));
|
||||
i2c.add(i2c_sda);
|
||||
i2c.add(i2c_scl);
|
||||
JsonArray spi = root.createNestedArray(F("spi"));
|
||||
spi.add(spi_mosi);
|
||||
spi.add(spi_sclk);
|
||||
#endif
|
||||
|
||||
root[F("str")] = syncToggleReceive;
|
||||
|
||||
root[F("name")] = serverDescription;
|
||||
@ -546,13 +671,8 @@ void serializeInfo(JsonObject root)
|
||||
root[F("palcount")] = strip.getPaletteCount();
|
||||
|
||||
JsonArray ledmaps = root.createNestedArray(F("maps"));
|
||||
for (uint8_t i=0; i<10; i++) {
|
||||
char fileName[16];
|
||||
strcpy_P(fileName, PSTR("/ledmap"));
|
||||
if (i) sprintf(fileName +7, "%d", i);
|
||||
strcat_P(fileName, PSTR(".json"));
|
||||
bool isFile = WLED_FS.exists(fileName);
|
||||
if (isFile || i==0) ledmaps.add(i);
|
||||
for (size_t i=0; i<10; i++) {
|
||||
if ((ledMaps>>i) & 0x0001) ledmaps.add(i);
|
||||
}
|
||||
|
||||
JsonObject wifi_info = root.createNestedObject("wifi");
|
||||
@ -681,6 +801,7 @@ void setPaletteColors(JsonArray json, byte* tcp)
|
||||
|
||||
void serializePalettes(JsonObject root, AsyncWebServerRequest* request)
|
||||
{
|
||||
byte tcp[72];
|
||||
#ifdef ESP8266
|
||||
int itemPerPage = 5;
|
||||
#else
|
||||
@ -693,19 +814,20 @@ void serializePalettes(JsonObject root, AsyncWebServerRequest* request)
|
||||
}
|
||||
|
||||
int palettesCount = strip.getPaletteCount();
|
||||
int customPalettes = strip.customPalettes.size();
|
||||
|
||||
int maxPage = (palettesCount -1) / itemPerPage;
|
||||
int maxPage = (palettesCount + customPalettes -1) / itemPerPage;
|
||||
if (page > maxPage) page = maxPage;
|
||||
|
||||
int start = itemPerPage * page;
|
||||
int end = start + itemPerPage;
|
||||
if (end >= palettesCount) end = palettesCount;
|
||||
if (end > palettesCount + customPalettes) end = palettesCount + customPalettes;
|
||||
|
||||
root[F("m")] = maxPage;
|
||||
root[F("m")] = maxPage; // inform caller how many pages there are
|
||||
JsonObject palettes = root.createNestedObject("p");
|
||||
|
||||
for (int i = start; i < end; i++) {
|
||||
JsonArray curPalette = palettes.createNestedArray(String(i));
|
||||
JsonArray curPalette = palettes.createNestedArray(String(i>=palettesCount ? 255 - i + palettesCount : i));
|
||||
switch (i) {
|
||||
case 0: //default palette
|
||||
setPaletteColors(curPalette, PartyColors_p);
|
||||
@ -771,9 +893,12 @@ void serializePalettes(JsonObject root, AsyncWebServerRequest* request)
|
||||
break;
|
||||
default:
|
||||
{
|
||||
byte tcp[72];
|
||||
memcpy_P(tcp, (byte*)pgm_read_dword(&(gGradientPalettes[i - 13])), 72);
|
||||
setPaletteColors(curPalette, tcp);
|
||||
if (i>=palettesCount) {
|
||||
setPaletteColors(curPalette, strip.customPalettes[i - palettesCount]);
|
||||
} else {
|
||||
memcpy_P(tcp, (byte*)pgm_read_dword(&(gGradientPalettes[i - 13])), 72);
|
||||
setPaletteColors(curPalette, tcp);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -800,72 +925,25 @@ void serializeNodes(JsonObject root)
|
||||
|
||||
void serializeModeData(JsonArray fxdata)
|
||||
{
|
||||
//JsonArray fxdata = root.createNestedArray("fxdata");
|
||||
String lineBuffer;
|
||||
bool insideQuotes = false;
|
||||
char singleJsonSymbol;
|
||||
size_t len = strlen_P(JSON_mode_names);
|
||||
|
||||
// Find the mode name in JSON
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(JSON_mode_names + i);
|
||||
if (singleJsonSymbol == '\0') break;
|
||||
switch (singleJsonSymbol) {
|
||||
case '"':
|
||||
insideQuotes = !insideQuotes;
|
||||
break;
|
||||
case '[':
|
||||
if (insideQuotes) lineBuffer += singleJsonSymbol;
|
||||
break;
|
||||
case ']':
|
||||
if (insideQuotes) {lineBuffer += singleJsonSymbol; break;}
|
||||
case ',':
|
||||
if (insideQuotes) {lineBuffer += singleJsonSymbol; break;}
|
||||
if (lineBuffer.length() > 0) {
|
||||
uint8_t endPos = lineBuffer.indexOf('@');
|
||||
if (endPos>0) fxdata.add(lineBuffer.substring(endPos));
|
||||
else fxdata.add("");
|
||||
lineBuffer.clear();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (!insideQuotes) break;
|
||||
lineBuffer += singleJsonSymbol;
|
||||
for (size_t i = 0; i < strip.getModeCount(); i++) {
|
||||
String lineBuffer = FPSTR(strip.getModeData(i));
|
||||
if (lineBuffer.length() > 0) {
|
||||
uint8_t endPos = lineBuffer.indexOf('@');
|
||||
if (endPos>0) fxdata.add(lineBuffer.substring(endPos));
|
||||
else fxdata.add("");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// deserializes mode names string into JsonArray
|
||||
// also removes WLED-SR extensions (@...) from deserialised names
|
||||
void serializeModeNames(JsonArray arr, const char *qstring) {
|
||||
String lineBuffer;
|
||||
bool insideQuotes = false;
|
||||
char singleJsonSymbol;
|
||||
size_t len = strlen_P(qstring);
|
||||
|
||||
// Find the mode name in JSON
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(qstring + i);
|
||||
if (singleJsonSymbol == '\0') break;
|
||||
switch (singleJsonSymbol) {
|
||||
case '"':
|
||||
insideQuotes = !insideQuotes;
|
||||
break;
|
||||
case '[':
|
||||
break;
|
||||
case ']':
|
||||
case ',':
|
||||
if (insideQuotes) break;
|
||||
if (lineBuffer.length() > 0) {
|
||||
uint8_t endPos = lineBuffer.indexOf('@');
|
||||
if (endPos>0) arr.add(lineBuffer.substring(0,endPos));
|
||||
else arr.add(lineBuffer);
|
||||
lineBuffer.clear();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (!insideQuotes) break;
|
||||
lineBuffer += singleJsonSymbol;
|
||||
void serializeModeNames(JsonArray arr) {
|
||||
for (size_t i = 0; i < strip.getModeCount(); i++) {
|
||||
String lineBuffer = FPSTR(strip.getModeData(i));
|
||||
if (lineBuffer.length() > 0) {
|
||||
uint8_t endPos = lineBuffer.indexOf('@');
|
||||
if (endPos>0) arr.add(lineBuffer.substring(0, endPos));
|
||||
else arr.add(lineBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -887,16 +965,17 @@ void serveJson(AsyncWebServerRequest* request)
|
||||
}
|
||||
#endif
|
||||
else if (url.indexOf(F("eff")) > 0) {
|
||||
// this is going to serve raw effect names which will include WLED-SR extensions in names
|
||||
// this serves just effect names without FX data extensions in names
|
||||
if (requestJSONBufferLock(19)) {
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse(&doc, true); // array document
|
||||
JsonArray lDoc = response->getRoot();
|
||||
serializeModeNames(lDoc, JSON_mode_names); // remove WLED-SR extensions from effect names
|
||||
serializeModeNames(lDoc); // remove WLED-SR extensions from effect names
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
releaseJSONBufferLock();
|
||||
} else {
|
||||
request->send_P(200, "application/json", JSON_mode_names);
|
||||
//request->send_P(200, "application/json", JSON_mode_names);
|
||||
request->send(503, "application/json", F("{\"error\":3}"));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -908,11 +987,14 @@ void serveJson(AsyncWebServerRequest* request)
|
||||
return;
|
||||
}
|
||||
else if (url.length() > 6) { //not just /json
|
||||
request->send( 501, "application/json", F("{\"error\":\"Not implemented\"}"));
|
||||
request->send(501, "application/json", F("{\"error\":\"Not implemented\"}"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!requestJSONBufferLock(17)) return;
|
||||
if (!requestJSONBufferLock(17)) {
|
||||
request->send(503, "application/json", F("{\"error\":3}"));
|
||||
return;
|
||||
}
|
||||
AsyncJsonResponse *response = new AsyncJsonResponse(&doc, subJson==6);
|
||||
|
||||
JsonVariant lDoc = response->getRoot();
|
||||
@ -938,7 +1020,7 @@ void serveJson(AsyncWebServerRequest* request)
|
||||
{
|
||||
//lDoc[F("effects")] = serialized((const __FlashStringHelper*)JSON_mode_names);
|
||||
JsonArray effects = lDoc.createNestedArray(F("effects"));
|
||||
serializeModeNames(effects, JSON_mode_names); // remove WLED-SR extensions from effect names
|
||||
serializeModeNames(effects); // remove WLED-SR extensions from effect names
|
||||
lDoc[F("palettes")] = serialized((const __FlashStringHelper*)JSON_palette_names);
|
||||
}
|
||||
}
|
||||
@ -970,7 +1052,7 @@ bool serveLiveLeds(AsyncWebServerRequest* request, uint32_t wsClient)
|
||||
obuf = buffer;
|
||||
olen = 9;
|
||||
|
||||
for (uint16_t i= 0; i < used; i += n)
|
||||
for (size_t i= 0; i < used; i += n)
|
||||
{
|
||||
uint32_t c = strip.getPixelColor(i);
|
||||
uint8_t r = qadd8(W(c), R(c)); //add white channel to RGB channels as a simple RGBW -> RGB map
|
||||
|
@ -8,7 +8,7 @@ void setValuesFromMainSeg() { setValuesFromSegment(strip.getMainSegment
|
||||
void setValuesFromFirstSelectedSeg() { setValuesFromSegment(strip.getFirstSelectedSegId()); }
|
||||
void setValuesFromSegment(uint8_t s)
|
||||
{
|
||||
WS2812FX::Segment& seg = strip.getSegment(s);
|
||||
Segment& seg = strip.getSegment(s);
|
||||
col[0] = R(seg.colors[0]);
|
||||
col[1] = G(seg.colors[0]);
|
||||
col[2] = B(seg.colors[0]);
|
||||
@ -30,9 +30,9 @@ void applyValuesToSelectedSegs()
|
||||
{
|
||||
// copy of first selected segment to tell if value was updated
|
||||
uint8_t firstSel = strip.getFirstSelectedSegId();
|
||||
WS2812FX::Segment selsegPrev = strip.getSegment(firstSel);
|
||||
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
||||
Segment selsegPrev = strip.getSegment(firstSel);
|
||||
for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
|
||||
Segment& seg = strip.getSegment(i);
|
||||
if (i != firstSel && (!seg.isActive() || !seg.isSelected())) continue;
|
||||
|
||||
if (effectSpeed != selsegPrev.speed) {seg.speed = effectSpeed; stateChanged = true;}
|
||||
@ -41,8 +41,8 @@ void applyValuesToSelectedSegs()
|
||||
if (effectCurrent != selsegPrev.mode) {strip.setMode(i, effectCurrent); stateChanged = true;}
|
||||
uint32_t col0 = RGBW32( col[0], col[1], col[2], col[3]);
|
||||
uint32_t col1 = RGBW32(colSec[0], colSec[1], colSec[2], colSec[3]);
|
||||
if (col0 != selsegPrev.colors[0]) {seg.setColor(0, col0, i); stateChanged = true;}
|
||||
if (col1 != selsegPrev.colors[1]) {seg.setColor(1, col1, i); stateChanged = true;}
|
||||
if (col0 != selsegPrev.colors[0]) {seg.setColor(0, col0); stateChanged = true;}
|
||||
if (col1 != selsegPrev.colors[1]) {seg.setColor(1, col1); stateChanged = true;}
|
||||
}
|
||||
}
|
||||
|
||||
@ -130,7 +130,7 @@ void stateUpdated(byte callMode) {
|
||||
|
||||
if (fadeTransition) {
|
||||
//set correct delay if not using notification delay
|
||||
if (callMode != CALL_MODE_NOTIFICATION && !jsonTransitionOnce) transitionDelayTemp = transitionDelay;
|
||||
if (callMode != CALL_MODE_NOTIFICATION && !jsonTransitionOnce) transitionDelayTemp = transitionDelay; // load actual transition duration
|
||||
jsonTransitionOnce = false;
|
||||
strip.setTransition(transitionDelayTemp);
|
||||
if (transitionDelayTemp == 0) {
|
||||
@ -143,7 +143,7 @@ void stateUpdated(byte callMode) {
|
||||
briOld = briT;
|
||||
tperLast = 0;
|
||||
}
|
||||
strip.setTransitionMode(true);
|
||||
strip.setTransitionMode(true); // force all segments to transition mode
|
||||
transitionActive = true;
|
||||
transitionStartTime = millis();
|
||||
} else {
|
||||
|
@ -69,7 +69,7 @@ void parseLxJson(int lxValue, byte segId, bool secondary)
|
||||
} else {
|
||||
DEBUG_PRINT(F("LX: segment "));
|
||||
DEBUG_PRINTLN(segId);
|
||||
strip.getSegment(segId).setColor(secondary, RGBW32(rgbw[0], rgbw[1], rgbw[2], rgbw[3]), segId);
|
||||
strip.getSegment(segId).setColor(secondary, RGBW32(rgbw[0], rgbw[1], rgbw[2], rgbw[3]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -90,7 +90,6 @@ void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties
|
||||
colorFromDecOrHexString(col, (char*)payloadStr);
|
||||
colorUpdated(CALL_MODE_DIRECT_CHANGE);
|
||||
} else if (strcmp_P(topic, PSTR("/api")) == 0) {
|
||||
DEBUG_PRINTLN(F("MQTT JSON buffer requested."));
|
||||
if (!requestJSONBufferLock(15)) { delete[] payloadStr; return; }
|
||||
if (payload[0] == '{') { //JSON API
|
||||
deserializeJson(doc, payloadStr);
|
||||
|
@ -13,8 +13,6 @@
|
||||
#ifndef PalettesWLED_h
|
||||
#define PalettesWLED_h
|
||||
|
||||
#define GRADIENT_PALETTE_COUNT 58
|
||||
|
||||
const byte ib_jul01_gp[] PROGMEM = {
|
||||
0, 194, 1, 1,
|
||||
94, 1, 29, 18,
|
||||
|
@ -75,12 +75,25 @@ bool PinManagerClass::deallocateMultiplePins(const uint8_t *pinArray, byte array
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (tag==PinOwner::HW_SPI) {
|
||||
if (spiAllocCount && --spiAllocCount>0) {
|
||||
// no deallocation done until last owner releases pins
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < arrayElementCount; i++) {
|
||||
deallocatePin(pinArray[i], tag);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PinManagerClass::deallocateMultiplePins(const managed_pin_type * mptArray, byte arrayElementCount, PinOwner tag)
|
||||
{
|
||||
uint8_t pins[arrayElementCount];
|
||||
for (int i=0; i<arrayElementCount; i++) pins[i] = mptArray[i].pin;
|
||||
return deallocateMultiplePins(pins, arrayElementCount, tag);
|
||||
}
|
||||
|
||||
bool PinManagerClass::allocateMultiplePins(const managed_pin_type * mptArray, byte arrayElementCount, PinOwner tag)
|
||||
{
|
||||
bool shouldFail = false;
|
||||
@ -100,8 +113,8 @@ bool PinManagerClass::allocateMultiplePins(const managed_pin_type * mptArray, by
|
||||
#endif
|
||||
shouldFail = true;
|
||||
}
|
||||
if (tag==PinOwner::HW_I2C && isPinAllocated(gpio, tag)) {
|
||||
// allow multiple "allocations" of HW I2C bus pins
|
||||
if ((tag==PinOwner::HW_I2C || tag==PinOwner::HW_SPI) && isPinAllocated(gpio, tag)) {
|
||||
// allow multiple "allocations" of HW I2C & SPI bus pins
|
||||
continue;
|
||||
} else if (isPinAllocated(gpio)) {
|
||||
#ifdef WLED_DEBUG
|
||||
@ -119,6 +132,7 @@ bool PinManagerClass::allocateMultiplePins(const managed_pin_type * mptArray, by
|
||||
}
|
||||
|
||||
if (tag==PinOwner::HW_I2C) i2cAllocCount++;
|
||||
if (tag==PinOwner::HW_SPI) spiAllocCount++;
|
||||
|
||||
// all pins are available .. track each one
|
||||
for (int i = 0; i < arrayElementCount; i++) {
|
||||
@ -145,8 +159,8 @@ bool PinManagerClass::allocateMultiplePins(const managed_pin_type * mptArray, by
|
||||
|
||||
bool PinManagerClass::allocatePin(byte gpio, bool output, PinOwner tag)
|
||||
{
|
||||
// HW I2C pins have to be allocated using allocateMultiplePins variant since there is always SCL/SDA pair
|
||||
if (!isPinOk(gpio, output) || tag==PinOwner::HW_I2C) return false;
|
||||
// HW I2C & SPI pins have to be allocated using allocateMultiplePins variant since there is always SCL/SDA pair
|
||||
if (!isPinOk(gpio, output) || tag==PinOwner::HW_I2C || tag==PinOwner::HW_SPI) return false;
|
||||
if (isPinAllocated(gpio)) {
|
||||
#ifdef WLED_DEBUG
|
||||
DEBUG_PRINT(F("PIN ALLOC: Pin "));
|
||||
|
@ -25,7 +25,7 @@ enum struct PinOwner : uint8_t {
|
||||
// High bit is set for all built-in pin owners
|
||||
Ethernet = 0x81,
|
||||
BusDigital = 0x82,
|
||||
BusDigital2 = 0x83,
|
||||
BusOnOff = 0x83,
|
||||
BusPwm = 0x84, // 'BusP' == PWM output using BusPwm
|
||||
Button = 0x85, // 'Butn' == button from configuration
|
||||
IR = 0x86, // 'IR' == IR receiver pin from configuration
|
||||
@ -34,6 +34,7 @@ enum struct PinOwner : uint8_t {
|
||||
DebugOut = 0x89, // 'Dbg' == debug output always IO1
|
||||
DMX = 0x8A, // 'DMX' == hard-coded to IO2
|
||||
HW_I2C = 0x8B, // 'I2C' == hardware I2C pins (4&5 on ESP8266, 21&22 on ESP32)
|
||||
HW_SPI = 0x8C, // 'SPI' == hardware (V)SPI pins (13,14&15 on ESP8266, 5,18&23 on ESP32)
|
||||
// Use UserMod IDs from const.h here
|
||||
UM_Unspecified = USERMOD_ID_UNSPECIFIED, // 0x01
|
||||
UM_Example = USERMOD_ID_EXAMPLE, // 0x02 // Usermod "usermod_v2_example.h"
|
||||
@ -54,7 +55,8 @@ enum struct PinOwner : uint8_t {
|
||||
// #define USERMOD_ID_SN_PHOTORESISTOR // 0x11 // Usermod "usermod_sn_photoresistor.h" -- Uses hard-coded pin (PHOTORESISTOR_PIN == A0), but could be easily updated to use pinManager
|
||||
UM_RGBRotaryEncoder = USERMOD_RGB_ROTARY_ENCODER, // 0x16 // Usermod "rgb-rotary-encoder.h"
|
||||
UM_QuinLEDAnPenta = USERMOD_ID_QUINLED_AN_PENTA, // 0x17 // Usermod "quinled-an-penta.h"
|
||||
UM_BME280 = USERMOD_ID_BME280 // 0x18 // Usermod "usermod_bme280.h -- Uses "standard" HW_I2C pins
|
||||
UM_BME280 = USERMOD_ID_BME280, // 0x18 // Usermod "usermod_bme280.h -- Uses "standard" HW_I2C pins
|
||||
UM_Audioreactive = USERMOD_ID_AUDIOREACTIVE // 0x1E // Usermod "audio_reactive.h"
|
||||
};
|
||||
static_assert(0u == static_cast<uint8_t>(PinOwner::None), "PinOwner::None must be zero, so default array initialization works as expected");
|
||||
|
||||
@ -68,13 +70,18 @@ class PinManagerClass {
|
||||
uint8_t ledcAlloc[2] = {0x00, 0x00}; //16 LEDC channels
|
||||
PinOwner ownerTag[40] = { PinOwner::None };
|
||||
#endif
|
||||
uint8_t i2cAllocCount = 0; // allow multiple allocation of I2C bus pins but keep track of allocations
|
||||
struct {
|
||||
uint8_t i2cAllocCount : 4; // allow multiple allocation of I2C bus pins but keep track of allocations
|
||||
uint8_t spiAllocCount : 4; // allow multiple allocation of SPI bus pins but keep track of allocations
|
||||
};
|
||||
|
||||
public:
|
||||
PinManagerClass() : i2cAllocCount(0), spiAllocCount(0) {}
|
||||
// De-allocates a single pin
|
||||
bool deallocatePin(byte gpio, PinOwner tag);
|
||||
// De-allocates multiple pins but only if all can be deallocated (PinOwner has to be specified)
|
||||
bool deallocateMultiplePins(const uint8_t *pinArray, byte arrayElementCount, PinOwner tag);
|
||||
bool deallocateMultiplePins(const managed_pin_type *pinArray, byte arrayElementCount, PinOwner tag);
|
||||
// Allocates a single pin, with an owner tag.
|
||||
// De-allocation requires the same owner tag (or override)
|
||||
bool allocatePin(byte gpio, bool output, PinOwner tag);
|
||||
|
@ -13,6 +13,8 @@ static volatile byte callModeToApply = 0;
|
||||
|
||||
bool applyPreset(byte index, byte callMode, bool fromJson)
|
||||
{
|
||||
DEBUG_PRINT(F("Request to apply preset: "));
|
||||
DEBUG_PRINTLN(index);
|
||||
presetToApply = index;
|
||||
callModeToApply = callMode;
|
||||
// the following is needed in case of HTTP JSON API call to return correct state to the caller
|
||||
@ -24,11 +26,13 @@ bool applyPreset(byte index, byte callMode, bool fromJson)
|
||||
void handlePresets(bool force)
|
||||
{
|
||||
bool changePreset = false;
|
||||
uint8_t tmpPreset = presetToApply; // store temporary since deserializeState() may call applyPreset()
|
||||
uint8_t tmpMode = callModeToApply;
|
||||
|
||||
if (presetToApply == 0 || (fileDoc && !force)) return; // JSON buffer already allocated and not force apply or no preset waiting
|
||||
if (tmpPreset == 0 || (fileDoc && !force)) return; // JSON buffer already allocated and not force apply or no preset waiting
|
||||
|
||||
JsonObject fdo;
|
||||
const char *filename = presetToApply < 255 ? "/presets.json" : "/tmp.json";
|
||||
const char *filename = tmpPreset < 255 ? "/presets.json" : "/tmp.json";
|
||||
|
||||
//crude way to determine if this was called by a network request
|
||||
uint8_t core = 1;
|
||||
@ -37,38 +41,60 @@ void handlePresets(bool force)
|
||||
#endif
|
||||
//only allow use of fileDoc from the core responsible for network requests (AKA HTTP JSON API)
|
||||
//do not use active network request doc from preset called by main loop (playlist, schedule, ...)
|
||||
if (fileDoc && core && force && presetToApply < 255) {
|
||||
if (fileDoc && core && force && tmpPreset < 255) {
|
||||
DEBUG_PRINT(F("Force applying preset: "));
|
||||
DEBUG_PRINTLN(presetToApply);
|
||||
|
||||
presetToApply = 0; //clear request for preset
|
||||
callModeToApply = 0;
|
||||
|
||||
// this will overwrite doc with preset content but applyPreset() is the last in such case and content of doc is no longer needed
|
||||
errorFlag = readObjectFromFileUsingId(filename, presetToApply, fileDoc) ? ERR_NONE : ERR_FS_PLOAD;
|
||||
errorFlag = readObjectFromFileUsingId(filename, tmpPreset, fileDoc) ? ERR_NONE : ERR_FS_PLOAD;
|
||||
|
||||
JsonObject fdo = fileDoc->as<JsonObject>();
|
||||
if (!fdo["seg"].isNull()) unloadPlaylist(); // if preset contains "seg" we must unload playlist
|
||||
if (!fdo["seg"].isNull() || !fdo["on"].isNull() || !fdo["bri"].isNull() || !fdo["ps"].isNull() || !fdo[F("playlist")].isNull() || !fdo["win"].isNull()) changePreset = true;
|
||||
fdo.remove("ps"); //remove load request for presets to prevent recursive crash
|
||||
deserializeState(fdo, callModeToApply, presetToApply);
|
||||
if (!errorFlag && changePreset) currentPreset = presetToApply;
|
||||
|
||||
colorUpdated(callModeToApply);
|
||||
//HTTP API commands
|
||||
const char* httpwin = fdo["win"];
|
||||
if (httpwin) {
|
||||
String apireq = "win"; // reduce flash string usage
|
||||
apireq += F("&IN&"); // internal call
|
||||
apireq += httpwin;
|
||||
handleSet(nullptr, apireq, false); // may call applyPreset() via PL=
|
||||
setValuesFromFirstSelectedSeg(); // fills legacy values
|
||||
changePreset = true;
|
||||
} else {
|
||||
if (!fdo["seg"].isNull()) unloadPlaylist(); // if preset contains "seg" we must unload playlist
|
||||
if (!fdo["seg"].isNull() || !fdo["on"].isNull() || !fdo["bri"].isNull() || !fdo["ps"].isNull() || !fdo[F("playlist")].isNull()) changePreset = true;
|
||||
fdo.remove("ps"); //remove load request for presets to prevent recursive crash
|
||||
|
||||
presetToApply = 0; //clear request for preset
|
||||
callModeToApply = 0;
|
||||
deserializeState(fdo, tmpMode, tmpPreset); // may call applyPreset() which will overwrite presetToApply
|
||||
}
|
||||
|
||||
if (!errorFlag && changePreset) presetCycCurr = currentPreset = tmpPreset;
|
||||
|
||||
colorUpdated(tmpMode);
|
||||
return;
|
||||
}
|
||||
|
||||
if (force) return; // something went wrong with force option (most likely WS request), quit and wait for async load
|
||||
|
||||
// allocate buffer
|
||||
DEBUG_PRINTLN(F("Apply preset JSON buffer requested."));
|
||||
if (!requestJSONBufferLock(9)) return; // will also assign fileDoc
|
||||
|
||||
presetToApply = 0; //clear request for preset
|
||||
callModeToApply = 0;
|
||||
|
||||
DEBUG_PRINT(F("Applying preset: "));
|
||||
DEBUG_PRINTLN(tmpPreset);
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
if (presetToApply==255 && tmpRAMbuffer!=nullptr) {
|
||||
if (tmpPreset==255 && tmpRAMbuffer!=nullptr) {
|
||||
deserializeJson(*fileDoc,tmpRAMbuffer);
|
||||
errorFlag = ERR_NONE;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
errorFlag = readObjectFromFileUsingId(filename, presetToApply, fileDoc) ? ERR_NONE : ERR_FS_PLOAD;
|
||||
errorFlag = readObjectFromFileUsingId(filename, tmpPreset, fileDoc) ? ERR_NONE : ERR_FS_PLOAD;
|
||||
}
|
||||
fdo = fileDoc->as<JsonObject>();
|
||||
|
||||
@ -78,30 +104,27 @@ void handlePresets(bool force)
|
||||
String apireq = "win"; // reduce flash string usage
|
||||
apireq += F("&IN&"); // internal call
|
||||
apireq += httpwin;
|
||||
handleSet(nullptr, apireq, false);
|
||||
handleSet(nullptr, apireq, false); // may call applyPreset() via PL=
|
||||
setValuesFromFirstSelectedSeg(); // fills legacy values
|
||||
changePreset = true;
|
||||
} else {
|
||||
if (!fdo["seg"].isNull() || !fdo["on"].isNull() || !fdo["bri"].isNull() || !fdo["nl"].isNull() || !fdo["ps"].isNull() || !fdo[F("playlist")].isNull() || !fdo["win"].isNull()) changePreset = true;
|
||||
if (!fdo["seg"].isNull() || !fdo["on"].isNull() || !fdo["bri"].isNull() || !fdo["nl"].isNull() || !fdo["ps"].isNull() || !fdo[F("playlist")].isNull()) changePreset = true;
|
||||
fdo.remove("ps"); //remove load request for presets to prevent recursive crash
|
||||
deserializeState(fdo, CALL_MODE_NO_NOTIFY, presetToApply);
|
||||
deserializeState(fdo, CALL_MODE_NO_NOTIFY, tmpPreset); // may change presetToApply by calling applyPreset()
|
||||
}
|
||||
if (!errorFlag && presetToApply < 255 && changePreset) currentPreset = presetToApply;
|
||||
if (!errorFlag && tmpPreset < 255 && changePreset) presetCycCurr = currentPreset = tmpPreset;
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP32)
|
||||
//Aircoookie recommended not to delete buffer
|
||||
if (presetToApply==255 && tmpRAMbuffer!=nullptr) {
|
||||
if (tmpPreset==255 && tmpRAMbuffer!=nullptr) {
|
||||
free(tmpRAMbuffer);
|
||||
tmpRAMbuffer = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
releaseJSONBufferLock(); // will also clear fileDoc
|
||||
colorUpdated(callModeToApply);
|
||||
updateInterfaces(callModeToApply);
|
||||
|
||||
presetToApply = 0; //clear request for preset
|
||||
callModeToApply = 0;
|
||||
colorUpdated(tmpMode);
|
||||
updateInterfaces(tmpMode);
|
||||
}
|
||||
|
||||
//called from handleSet(PS=) [network callback (fileDoc==nullptr), IR (irrational), deserializeState, UDP] and deserializeState() [network callback (filedoc!=nullptr)]
|
||||
@ -117,7 +140,6 @@ void savePreset(byte index, const char* pname, JsonObject saveobj)
|
||||
|
||||
if (!fileDoc) {
|
||||
// called from handleSet() HTTP API
|
||||
DEBUG_PRINTLN(F("Save preset JSON buffer requested."));
|
||||
if (!requestJSONBufferLock(10)) return;
|
||||
sObj = fileDoc->to<JsonObject>();
|
||||
bufferAllocated = true;
|
||||
|
153
wled00/set.cpp
153
wled00/set.cpp
@ -15,8 +15,8 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
return;
|
||||
}
|
||||
|
||||
//0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec 7: DMX 8: usermods
|
||||
if (subPage <1 || subPage >8 || !correctPIN) return;
|
||||
//0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec 7: DMX 8: usermods 9: N/A 10: 2D
|
||||
if (subPage <1 || subPage >10 || !correctPIN) return;
|
||||
|
||||
//WIFI SETTINGS
|
||||
if (subPage == 1)
|
||||
@ -85,6 +85,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
Bus::setCCTBlend(strip.cctBlending);
|
||||
Bus::setAutoWhiteMode(request->arg(F("AW")).toInt());
|
||||
strip.setTargetFps(request->arg(F("FR")).toInt());
|
||||
strip.useLedsArray = request->hasArg(F("LD"));
|
||||
|
||||
bool busesChanged = false;
|
||||
for (uint8_t s = 0; s < WLED_MAX_BUSSES; s++) {
|
||||
@ -99,7 +100,9 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
char aw[4] = "AW"; aw[2] = 48+s; aw[3] = 0; //auto white mode
|
||||
char wo[4] = "WO"; wo[2] = 48+s; wo[3] = 0; //channel swap
|
||||
if (!request->hasArg(lp)) {
|
||||
DEBUG_PRINTLN(F("No data.")); break;
|
||||
DEBUG_PRINT(F("No data for "));
|
||||
DEBUG_PRINTLN(s);
|
||||
break;
|
||||
}
|
||||
for (uint8_t i = 0; i < 5; i++) {
|
||||
lp[1] = 48+i;
|
||||
@ -119,6 +122,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
awmode = request->arg(aw).toInt();
|
||||
channelSwap = (type == TYPE_SK6812_RGBW || type == TYPE_TM1814) ? request->arg(wo).toInt() : 0;
|
||||
// actual finalization is done in WLED::loop() (removing old busses and adding new)
|
||||
// this may happen even before this loop is finished so we do "doInitBusses" after the loop
|
||||
if (busConfigs[s] != nullptr) delete busConfigs[s];
|
||||
busConfigs[s] = new BusConfig(type, pins, start, length, colorOrder | (channelSwap<<4), request->hasArg(cv), skip, awmode);
|
||||
busesChanged = true;
|
||||
@ -185,8 +189,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
|
||||
fadeTransition = request->hasArg(F("TF"));
|
||||
t = request->arg(F("TD")).toInt();
|
||||
if (t >= 0) transitionDelay = t;
|
||||
transitionDelayDefault = t;
|
||||
if (t >= 0) transitionDelayDefault = t;
|
||||
strip.paletteFade = request->hasArg(F("PF"));
|
||||
|
||||
nightlightTargetBri = request->arg(F("TB")).toInt();
|
||||
@ -396,7 +399,9 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
if (request->hasArg(F("RS"))) //complete factory reset
|
||||
{
|
||||
WLED_FS.format();
|
||||
#ifdef WLED_ADD_EEPROM_SUPPORT
|
||||
clearEEPROM();
|
||||
#endif
|
||||
serveMessage(request, 200, F("All Settings erased."), F("Connect to WLED-AP to setup again"),255);
|
||||
doReboot = true;
|
||||
}
|
||||
@ -472,6 +477,51 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
{
|
||||
if (!requestJSONBufferLock(5)) return;
|
||||
|
||||
// global I2C & SPI pins
|
||||
int8_t hw_sda_pin = !request->arg(F("SDA")).length() ? -1 : max(-1,min(33,(int)request->arg(F("SDA")).toInt()));
|
||||
int8_t hw_scl_pin = !request->arg(F("SCL")).length() ? -1 : max(-1,min(33,(int)request->arg(F("SCL")).toInt()));
|
||||
#ifdef ESP8266
|
||||
// cannot change pins on ESP8266
|
||||
if (hw_sda_pin >= 0 && hw_sda_pin != HW_PIN_SDA) hw_sda_pin = HW_PIN_SDA;
|
||||
if (hw_scl_pin >= 0 && hw_scl_pin != HW_PIN_SCL) hw_scl_pin = HW_PIN_SCL;
|
||||
#endif
|
||||
PinManagerPinType i2c[2] = { { hw_sda_pin, true }, { hw_scl_pin, true } };
|
||||
if (hw_sda_pin >= 0 && hw_scl_pin >= 0 && pinManager.allocateMultiplePins(i2c, 2, PinOwner::HW_I2C)) {
|
||||
i2c_sda = hw_sda_pin;
|
||||
i2c_scl = hw_scl_pin;
|
||||
#ifdef ESP32
|
||||
Wire.setPins(i2c_sda, i2c_scl); // this will fail if Wire is initilised (Wire.begin() called)
|
||||
#endif
|
||||
Wire.begin();
|
||||
} else {
|
||||
// there is no Wire.end()
|
||||
DEBUG_PRINTLN(F("Could not allocate I2C pins."));
|
||||
uint8_t i2c[2] = { i2c_scl, i2c_sda };
|
||||
pinManager.deallocateMultiplePins(i2c, 2, PinOwner::HW_I2C); // just in case deallocation of old pins
|
||||
i2c_sda = -1;
|
||||
i2c_scl = -1;
|
||||
}
|
||||
int8_t hw_mosi_pin = !request->arg(F("MOSI")).length() ? -1 : max(-1,min(33,(int)request->arg(F("MOSI")).toInt()));
|
||||
int8_t hw_sclk_pin = !request->arg(F("SCLK")).length() ? -1 : max(-1,min(33,(int)request->arg(F("SCLK")).toInt()));
|
||||
#ifdef ESP8266
|
||||
// cannot change pins on ESP8266
|
||||
if (hw_mosi_pin >= 0 && hw_mosi_pin != HW_PIN_DATASPI) hw_mosi_pin = HW_PIN_DATASPI;
|
||||
if (hw_sclk_pin >= 0 && hw_sclk_pin != HW_PIN_CLOCKSPI) hw_sclk_pin = HW_PIN_CLOCKSPI;
|
||||
#endif
|
||||
PinManagerPinType spi[2] = { { hw_mosi_pin, true }, { hw_sclk_pin, true } };
|
||||
if (hw_mosi_pin >= 0 && hw_sclk_pin >= 0 && pinManager.allocateMultiplePins(spi, 2, PinOwner::HW_SPI)) {
|
||||
spi_mosi = hw_mosi_pin;
|
||||
spi_sclk = hw_sclk_pin;
|
||||
// no bus initialisation
|
||||
} else {
|
||||
//SPI.end();
|
||||
DEBUG_PRINTLN(F("Could not allocate SPI pins."));
|
||||
uint8_t spi[2] = { spi_mosi, spi_sclk };
|
||||
pinManager.deallocateMultiplePins(spi, 2, PinOwner::HW_SPI); // just in case deallocation of old pins
|
||||
spi_mosi = -1;
|
||||
spi_sclk = -1;
|
||||
}
|
||||
|
||||
JsonObject um = doc.createNestedObject("um");
|
||||
|
||||
size_t args = request->args();
|
||||
@ -482,7 +532,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
|
||||
// POST request parameters are combined as <usermodname>_<usermodparameter>
|
||||
int umNameEnd = name.indexOf(":");
|
||||
if (umNameEnd<1) break; // parameter does not contain ":" or on 1st place -> wrong
|
||||
if (umNameEnd<1) continue; // parameter does not contain ":" or on 1st place -> wrong
|
||||
|
||||
JsonObject mod = um[name.substring(0,umNameEnd)]; // get a usermod JSON object
|
||||
if (mod.isNull()) {
|
||||
@ -551,6 +601,32 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
releaseJSONBufferLock();
|
||||
}
|
||||
|
||||
#ifndef WLED_DISABLE_2D
|
||||
//2D panels
|
||||
if (subPage == 10)
|
||||
{
|
||||
strip.isMatrix = request->arg(F("SOMP")).toInt();
|
||||
strip.panelH = MAX(1,MIN(128,request->arg(F("PH")).toInt()));
|
||||
strip.panelW = MAX(1,MIN(128,request->arg(F("PW")).toInt()));
|
||||
strip.hPanels = MAX(1,MIN(8,request->arg(F("MPH")).toInt()));
|
||||
strip.vPanels = MAX(1,MIN(8,request->arg(F("MPV")).toInt()));
|
||||
strip.matrix.bottomStart = request->arg(F("PB")).toInt();
|
||||
strip.matrix.rightStart = request->arg(F("PR")).toInt();
|
||||
strip.matrix.vertical = request->arg(F("PV")).toInt();
|
||||
strip.matrix.serpentine = request->hasArg(F("PS"));
|
||||
for (uint8_t i=0; i<WLED_MAX_PANELS; i++) {
|
||||
char pO[8]; sprintf_P(pO, PSTR("P%d"), i);
|
||||
uint8_t l = strlen(pO); pO[l+1] = 0;
|
||||
pO[l] = 'B'; if (!request->hasArg(pO)) break;
|
||||
pO[l] = 'B'; strip.panel[i].bottomStart = request->arg(pO).toInt();
|
||||
pO[l] = 'R'; strip.panel[i].rightStart = request->arg(pO).toInt();
|
||||
pO[l] = 'V'; strip.panel[i].vertical = request->arg(pO).toInt();
|
||||
pO[l] = 'S'; strip.panel[i].serpentine = request->hasArg(pO);
|
||||
}
|
||||
strip.setUpMatrix(); // will check limits
|
||||
}
|
||||
#endif
|
||||
|
||||
lastEditTime = millis();
|
||||
if (subPage != 2 && !doReboot) serializeConfig(); //do not save if factory reset or LED settings (which are saved after LED re-init)
|
||||
if (subPage == 4) alexaInit();
|
||||
@ -579,17 +655,17 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
|
||||
pos = req.indexOf(F("SS="));
|
||||
if (pos > 0) {
|
||||
byte t = getNumVal(&req, pos);
|
||||
if (t < strip.getMaxSegments()) {
|
||||
if (t < strip.getSegmentsNum()) {
|
||||
selectedSeg = t;
|
||||
singleSegment = true;
|
||||
}
|
||||
}
|
||||
|
||||
WS2812FX::Segment& selseg = strip.getSegment(selectedSeg);
|
||||
Segment& selseg = strip.getSegment(selectedSeg);
|
||||
pos = req.indexOf(F("SV=")); //segment selected
|
||||
if (pos > 0) {
|
||||
byte t = getNumVal(&req, pos);
|
||||
if (t == 2) for (uint8_t i = 0; i < strip.getMaxSegments(); i++) strip.getSegment(i).setOption(SEG_OPTION_SELECTED, 0); // unselect other segments
|
||||
if (t == 2) for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) strip.getSegment(i).setOption(SEG_OPTION_SELECTED, 0); // unselect other segments
|
||||
selseg.setOption(SEG_OPTION_SELECTED, t);
|
||||
}
|
||||
|
||||
@ -605,6 +681,8 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
|
||||
|
||||
uint16_t startI = selseg.start;
|
||||
uint16_t stopI = selseg.stop;
|
||||
uint16_t startY = selseg.startY;
|
||||
uint16_t stopY = selseg.stopY;
|
||||
uint8_t grpI = selseg.grouping;
|
||||
uint16_t spcI = selseg.spacing;
|
||||
pos = req.indexOf(F("&S=")); //segment start
|
||||
@ -624,7 +702,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
|
||||
if (pos > 0) {
|
||||
spcI = getNumVal(&req, pos);
|
||||
}
|
||||
strip.setSegment(selectedSeg, startI, stopI, grpI, spcI);
|
||||
strip.setSegment(selectedSeg, startI, stopI, grpI, spcI, UINT16_MAX, startY, stopY);
|
||||
|
||||
pos = req.indexOf(F("RV=")); //Segment reverse
|
||||
if (pos > 0) selseg.setOption(SEG_OPTION_REVERSED, req.charAt(pos+3) != '0');
|
||||
@ -635,9 +713,9 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
|
||||
pos = req.indexOf(F("SB=")); //Segment brightness/opacity
|
||||
if (pos > 0) {
|
||||
byte segbri = getNumVal(&req, pos);
|
||||
selseg.setOption(SEG_OPTION_ON, segbri, selectedSeg);
|
||||
selseg.setOption(SEG_OPTION_ON, segbri);
|
||||
if (segbri) {
|
||||
selseg.setOpacity(segbri, selectedSeg);
|
||||
selseg.setOpacity(segbri);
|
||||
}
|
||||
}
|
||||
|
||||
@ -660,25 +738,25 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
|
||||
if (pos > 0) presetCycMax = getNumVal(&req, pos);
|
||||
|
||||
//apply preset
|
||||
if (updateVal(&req, "PL=", &presetCycCurr, presetCycMin, presetCycMax)) {
|
||||
if (updateVal(req.c_str(), "PL=", &presetCycCurr, presetCycMin, presetCycMax)) {
|
||||
unloadPlaylist();
|
||||
applyPreset(presetCycCurr);
|
||||
}
|
||||
|
||||
//set brightness
|
||||
updateVal(&req, "&A=", &bri);
|
||||
updateVal(req.c_str(), "&A=", &bri);
|
||||
|
||||
bool col0Changed = false, col1Changed = false;
|
||||
//set colors
|
||||
col0Changed |= updateVal(&req, "&R=", &colIn[0]);
|
||||
col0Changed |= updateVal(&req, "&G=", &colIn[1]);
|
||||
col0Changed |= updateVal(&req, "&B=", &colIn[2]);
|
||||
col0Changed |= updateVal(&req, "&W=", &colIn[3]);
|
||||
col0Changed |= updateVal(req.c_str(), "&R=", &colIn[0]);
|
||||
col0Changed |= updateVal(req.c_str(), "&G=", &colIn[1]);
|
||||
col0Changed |= updateVal(req.c_str(), "&B=", &colIn[2]);
|
||||
col0Changed |= updateVal(req.c_str(), "&W=", &colIn[3]);
|
||||
|
||||
col1Changed |= updateVal(&req, "R2=", &colInSec[0]);
|
||||
col1Changed |= updateVal(&req, "G2=", &colInSec[1]);
|
||||
col1Changed |= updateVal(&req, "B2=", &colInSec[2]);
|
||||
col1Changed |= updateVal(&req, "W2=", &colInSec[3]);
|
||||
col1Changed |= updateVal(req.c_str(), "R2=", &colInSec[0]);
|
||||
col1Changed |= updateVal(req.c_str(), "G2=", &colInSec[1]);
|
||||
col1Changed |= updateVal(req.c_str(), "B2=", &colInSec[2]);
|
||||
col1Changed |= updateVal(req.c_str(), "W2=", &colInSec[3]);
|
||||
|
||||
#ifdef WLED_ENABLE_LOXONE
|
||||
//lox parser
|
||||
@ -740,7 +818,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
|
||||
if (pos > 0) {
|
||||
colorFromDecOrHexString(tmpCol, (char*)req.substring(pos + 3).c_str());
|
||||
uint32_t col2 = RGBW32(tmpCol[0], tmpCol[1], tmpCol[2], tmpCol[3]);
|
||||
selseg.setColor(2, col2, selectedSeg); // defined above (SS= or main)
|
||||
selseg.setColor(2, col2); // defined above (SS= or main)
|
||||
stateChanged = true;
|
||||
if (!singleSegment) strip.setColor(2, col2); // will set color to all active & selected segments
|
||||
}
|
||||
@ -769,37 +847,44 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
|
||||
if (col0Changed) {
|
||||
stateChanged = true;
|
||||
uint32_t colIn0 = RGBW32(colIn[0], colIn[1], colIn[2], colIn[3]);
|
||||
selseg.setColor(0, colIn0, selectedSeg);
|
||||
selseg.setColor(0, colIn0);
|
||||
if (!singleSegment) strip.setColor(0, colIn0); // will set color to all active & selected segments
|
||||
}
|
||||
|
||||
if (col1Changed) {
|
||||
stateChanged = true;
|
||||
uint32_t colIn1 = RGBW32(colInSec[0], colInSec[1], colInSec[2], colInSec[3]);
|
||||
selseg.setColor(1, colIn1, selectedSeg);
|
||||
selseg.setColor(1, colIn1);
|
||||
if (!singleSegment) strip.setColor(1, colIn1); // will set color to all active & selected segments
|
||||
}
|
||||
|
||||
bool fxModeChanged = false, speedChanged = false, intensityChanged = false, paletteChanged = false;
|
||||
// set effect parameters
|
||||
if (updateVal(&req, "FX=", &effectIn, 0, strip.getModeCount()-1)) {
|
||||
if (updateVal(req.c_str(), "FX=", &effectIn, 0, strip.getModeCount()-1)) {
|
||||
if (request != nullptr) unloadPlaylist(); // unload playlist if changing FX using web request
|
||||
fxModeChanged = true;
|
||||
}
|
||||
speedChanged = updateVal(&req, "SX=", &speedIn);
|
||||
intensityChanged = updateVal(&req, "IX=", &intensityIn);
|
||||
paletteChanged = updateVal(&req, "FP=", &paletteIn, 0, strip.getPaletteCount()-1);
|
||||
speedChanged = updateVal(req.c_str(), "SX=", &speedIn);
|
||||
intensityChanged = updateVal(req.c_str(), "IX=", &intensityIn);
|
||||
paletteChanged = updateVal(req.c_str(), "FP=", &paletteIn, 0, strip.getPaletteCount()-1);
|
||||
|
||||
stateChanged |= (fxModeChanged || speedChanged || intensityChanged || paletteChanged);
|
||||
|
||||
// apply to main and all selected segments to prevent #1618.
|
||||
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
||||
for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
|
||||
Segment& seg = strip.getSegment(i);
|
||||
if (i != selectedSeg && (singleSegment || !seg.isActive() || !seg.isSelected())) continue; // skip non main segments if not applying to all
|
||||
if (fxModeChanged) strip.setMode(i, effectIn);
|
||||
if (fxModeChanged) {
|
||||
seg.startTransition(strip.getTransition());
|
||||
seg.mode = effectIn;
|
||||
// TODO: we should load defaults here as well
|
||||
}
|
||||
if (speedChanged) seg.speed = speedIn;
|
||||
if (intensityChanged) seg.intensity = intensityIn;
|
||||
if (paletteChanged) seg.palette = paletteIn;
|
||||
if (paletteChanged) {
|
||||
if (strip.paletteBlend) seg.startTransition(strip.getTransition());
|
||||
seg.palette = paletteIn;
|
||||
}
|
||||
}
|
||||
|
||||
//set advanced overlay
|
||||
@ -896,7 +981,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
|
||||
realtimeOverride = getNumVal(&req, pos);
|
||||
if (realtimeOverride > 2) realtimeOverride = REALTIME_OVERRIDE_ALWAYS;
|
||||
if (realtimeMode && useMainSegmentOnly) {
|
||||
strip.getMainSegment().setOption(SEG_OPTION_FREEZE, !realtimeOverride, strip.getMainSegmentId());
|
||||
strip.getMainSegment().setOption(SEG_OPTION_FREEZE, !realtimeOverride);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,11 +33,6 @@
|
||||
|
||||
#define DS1307_CTRL_ID 0x68
|
||||
|
||||
DS1307RTC::DS1307RTC()
|
||||
{
|
||||
Wire.begin();
|
||||
}
|
||||
|
||||
// PUBLIC FUNCTIONS
|
||||
time_t DS1307RTC::get() // Aquire data from buffer and convert to time_t
|
||||
{
|
||||
|
@ -13,7 +13,8 @@ class DS1307RTC
|
||||
{
|
||||
// user-accessible "public" interface
|
||||
public:
|
||||
DS1307RTC();
|
||||
DS1307RTC() {}
|
||||
static void begin() { Wire.begin(); }
|
||||
static time_t get();
|
||||
static bool set(time_t t);
|
||||
static bool read(tmElements_t &tm);
|
||||
|
102
wled00/udp.cpp
102
wled00/udp.cpp
@ -28,7 +28,7 @@ void notify(byte callMode, bool followUp)
|
||||
default: return;
|
||||
}
|
||||
byte udpOut[WLEDPACKETSIZE];
|
||||
WS2812FX::Segment& mainseg = strip.getMainSegment();
|
||||
Segment& mainseg = strip.getMainSegment();
|
||||
udpOut[0] = 0; //0: wled notifier protocol 1: WARLS protocol
|
||||
udpOut[1] = callMode;
|
||||
udpOut[2] = bri;
|
||||
@ -89,12 +89,14 @@ void notify(byte callMode, bool followUp)
|
||||
udpOut[37] = strip.hasCCTBus() ? 0 : 255; //check this is 0 for the next value to be significant
|
||||
udpOut[38] = mainseg.cct;
|
||||
|
||||
udpOut[39] = strip.getMaxSegments();
|
||||
udpOut[39] = strip.getActiveSegmentsNum();
|
||||
udpOut[40] = UDP_SEG_SIZE; //size of each loop iteration (one segment)
|
||||
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
||||
WS2812FX::Segment &selseg = strip.getSegment(i);
|
||||
uint16_t ofs = 41 + i*UDP_SEG_SIZE; //start of segment offset byte
|
||||
udpOut[0 +ofs] = i;
|
||||
size_t s = 0, nsegs = strip.getSegmentsNum();
|
||||
for (size_t i = 0; i < nsegs; i++) {
|
||||
Segment &selseg = strip.getSegment(i);
|
||||
if (!selseg.isActive()) continue;
|
||||
uint16_t ofs = 41 + s*UDP_SEG_SIZE; //start of segment offset byte
|
||||
udpOut[0 +ofs] = s;
|
||||
udpOut[1 +ofs] = selseg.start >> 8;
|
||||
udpOut[2 +ofs] = selseg.start & 0xFF;
|
||||
udpOut[3 +ofs] = selseg.stop >> 8;
|
||||
@ -122,6 +124,7 @@ void notify(byte callMode, bool followUp)
|
||||
udpOut[25+ofs] = B(selseg.colors[2]);
|
||||
udpOut[26+ofs] = W(selseg.colors[2]);
|
||||
udpOut[27+ofs] = selseg.cct;
|
||||
++s;
|
||||
}
|
||||
|
||||
//uint16_t offs = SEG_OFFSET;
|
||||
@ -143,20 +146,20 @@ void realtimeLock(uint32_t timeoutMs, byte md)
|
||||
if (!realtimeMode && !realtimeOverride) {
|
||||
uint16_t stop, start;
|
||||
if (useMainSegmentOnly) {
|
||||
WS2812FX::Segment& mainseg = strip.getMainSegment();
|
||||
Segment& mainseg = strip.getMainSegment();
|
||||
start = mainseg.start;
|
||||
stop = mainseg.stop;
|
||||
mainseg.setOption(SEG_OPTION_FREEZE, true, strip.getMainSegmentId());
|
||||
mainseg.setOption(SEG_OPTION_FREEZE, true);
|
||||
} else {
|
||||
start = 0;
|
||||
stop = strip.getLengthTotal();
|
||||
}
|
||||
// clear strip/segment
|
||||
for (uint16_t i = start; i < stop; i++) strip.setPixelColor(i,0,0,0,0);
|
||||
for (size_t i = start; i < stop; i++) strip.setPixelColor(i,BLACK);
|
||||
// if WLED was off and using main segment only, freeze non-main segments so they stay off
|
||||
if (useMainSegmentOnly && bri == 0) {
|
||||
for (uint8_t s=0; s < strip.getMaxSegments(); s++) {
|
||||
strip.getSegment(s).setOption(SEG_OPTION_FREEZE, true, s);
|
||||
for (size_t s=0; s < strip.getSegmentsNum(); s++) {
|
||||
strip.getSegment(s).setOption(SEG_OPTION_FREEZE, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -183,7 +186,7 @@ void exitRealtime() {
|
||||
realtimeMode = REALTIME_MODE_INACTIVE; // inform UI immediately
|
||||
realtimeIP[0] = 0;
|
||||
if (useMainSegmentOnly) { // unfreeze live segment again
|
||||
strip.getMainSegment().setOption(SEG_OPTION_FREEZE, false, strip.getMainSegmentId());
|
||||
strip.getMainSegment().setOption(SEG_OPTION_FREEZE, false);
|
||||
}
|
||||
updateInterfaces(CALL_MODE_WS_SEND);
|
||||
}
|
||||
@ -221,7 +224,7 @@ void handleNotifications()
|
||||
if (!udpConnected) return;
|
||||
|
||||
bool isSupp = false;
|
||||
uint16_t packetSize = notifierUdp.parsePacket();
|
||||
size_t packetSize = notifierUdp.parsePacket();
|
||||
if (!packetSize && udp2Connected) {
|
||||
packetSize = notifier2Udp.parsePacket();
|
||||
isSupp = true;
|
||||
@ -241,7 +244,7 @@ void handleNotifications()
|
||||
if (realtimeOverride && !(realtimeMode && useMainSegmentOnly)) return;
|
||||
uint16_t id = 0;
|
||||
uint16_t totalLen = strip.getLengthTotal();
|
||||
for (uint16_t i = 0; i < packetSize -2; i += 3)
|
||||
for (size_t i = 0; i < packetSize -2; i += 3)
|
||||
{
|
||||
setRealtimePixel(id, lbuf[i], lbuf[i+1], lbuf[i+2], 0);
|
||||
id++; if (id >= totalLen) break;
|
||||
@ -275,7 +278,7 @@ void handleNotifications()
|
||||
}
|
||||
|
||||
if (it != Nodes.end()) {
|
||||
for (byte x = 0; x < 4; x++) {
|
||||
for (size_t x = 0; x < 4; x++) {
|
||||
it->second.ip[x] = udpIn[x + 2];
|
||||
}
|
||||
it->second.age = 0; // reset 'age counter'
|
||||
@ -287,7 +290,7 @@ void handleNotifications()
|
||||
it->second.nodeType = udpIn[38];
|
||||
uint32_t build = 0;
|
||||
if (len >= 44)
|
||||
for (byte i=0; i<sizeof(uint32_t); i++)
|
||||
for (size_t i=0; i<sizeof(uint32_t); i++)
|
||||
build |= udpIn[40+i]<<(8*i);
|
||||
it->second.build = build;
|
||||
}
|
||||
@ -339,11 +342,11 @@ void handleNotifications()
|
||||
if (applyEffects && currentPlaylist >= 0) unloadPlaylist();
|
||||
if (version > 10 && (receiveSegmentOptions || receiveSegmentBounds)) {
|
||||
uint8_t numSrcSegs = udpIn[39];
|
||||
for (uint8_t i = 0; i < numSrcSegs; i++) {
|
||||
for (size_t i = 0; i < numSrcSegs; i++) {
|
||||
uint16_t ofs = 41 + i*udpIn[40]; //start of segment offset byte
|
||||
uint8_t id = udpIn[0 +ofs];
|
||||
if (id > strip.getMaxSegments()) break;
|
||||
WS2812FX::Segment& selseg = strip.getSegment(id);
|
||||
if (id > strip.getSegmentsNum()) break;
|
||||
Segment& selseg = strip.getSegment(id);
|
||||
uint16_t start = (udpIn[1+ofs] << 8 | udpIn[2+ofs]);
|
||||
uint16_t stop = (udpIn[3+ofs] << 8 | udpIn[4+ofs]);
|
||||
uint16_t offset = (udpIn[7+ofs] << 8 | udpIn[8+ofs]);
|
||||
@ -351,8 +354,8 @@ void handleNotifications()
|
||||
strip.setSegment(id, start, stop, selseg.grouping, selseg.spacing, offset);
|
||||
continue;
|
||||
}
|
||||
for (uint8_t j = 0; j<4; j++) selseg.setOption(j, (udpIn[9 +ofs] >> j) & 0x01, id); //only take into account mirrored, selected, on, reversed
|
||||
selseg.setOpacity(udpIn[10+ofs], id);
|
||||
for (size_t j = 0; j<4; j++) selseg.setOption(j, (udpIn[9 +ofs] >> j) & 0x01); //only take into account mirrored, selected, on, reversed
|
||||
selseg.setOpacity(udpIn[10+ofs]);
|
||||
if (applyEffects) {
|
||||
strip.setMode(id, udpIn[11+ofs]);
|
||||
selseg.speed = udpIn[12+ofs];
|
||||
@ -360,10 +363,10 @@ void handleNotifications()
|
||||
selseg.palette = udpIn[14+ofs];
|
||||
}
|
||||
if (receiveNotificationColor || !someSel) {
|
||||
selseg.setColor(0, RGBW32(udpIn[15+ofs],udpIn[16+ofs],udpIn[17+ofs],udpIn[18+ofs]), id);
|
||||
selseg.setColor(1, RGBW32(udpIn[19+ofs],udpIn[20+ofs],udpIn[21+ofs],udpIn[22+ofs]), id);
|
||||
selseg.setColor(2, RGBW32(udpIn[23+ofs],udpIn[24+ofs],udpIn[25+ofs],udpIn[26+ofs]), id);
|
||||
selseg.setCCT(udpIn[27+ofs], id);
|
||||
selseg.setColor(0, RGBW32(udpIn[15+ofs],udpIn[16+ofs],udpIn[17+ofs],udpIn[18+ofs]));
|
||||
selseg.setColor(1, RGBW32(udpIn[19+ofs],udpIn[20+ofs],udpIn[21+ofs],udpIn[22+ofs]));
|
||||
selseg.setColor(2, RGBW32(udpIn[23+ofs],udpIn[24+ofs],udpIn[25+ofs],udpIn[26+ofs]));
|
||||
selseg.setCCT(udpIn[27+ofs]);
|
||||
}
|
||||
//setSegment() also properly resets segments
|
||||
if (receiveSegmentBounds) {
|
||||
@ -377,8 +380,8 @@ void handleNotifications()
|
||||
|
||||
// simple effect sync, applies to all selected segments
|
||||
if (applyEffects && (version < 11 || !receiveSegmentOptions)) {
|
||||
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
||||
for (size_t i = 0; i < strip.getSegmentsNum(); i++) {
|
||||
Segment& seg = strip.getSegment(i);
|
||||
if (!seg.isActive() || !seg.isSelected()) continue;
|
||||
if (udpIn[8] < strip.getModeCount()) strip.setMode(i, udpIn[8]);
|
||||
seg.speed = udpIn[9];
|
||||
@ -458,7 +461,7 @@ void handleNotifications()
|
||||
|
||||
uint16_t id = (tpmPayloadFrameSize/3)*(packetNum-1); //start LED
|
||||
uint16_t totalLen = strip.getLengthTotal();
|
||||
for (uint16_t i = 6; i < tpmPayloadFrameSize + 4; i += 3)
|
||||
for (size_t i = 6; i < tpmPayloadFrameSize + 4U; i += 3)
|
||||
{
|
||||
if (id < totalLen)
|
||||
{
|
||||
@ -494,14 +497,14 @@ void handleNotifications()
|
||||
uint16_t totalLen = strip.getLengthTotal();
|
||||
if (udpIn[0] == 1) //warls
|
||||
{
|
||||
for (uint16_t i = 2; i < packetSize -3; i += 4)
|
||||
for (size_t i = 2; i < packetSize -3; i += 4)
|
||||
{
|
||||
setRealtimePixel(udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3], 0);
|
||||
}
|
||||
} else if (udpIn[0] == 2) //drgb
|
||||
{
|
||||
uint16_t id = 0;
|
||||
for (uint16_t i = 2; i < packetSize -2; i += 3)
|
||||
for (size_t i = 2; i < packetSize -2; i += 3)
|
||||
{
|
||||
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], 0);
|
||||
|
||||
@ -510,7 +513,7 @@ void handleNotifications()
|
||||
} else if (udpIn[0] == 3) //drgbw
|
||||
{
|
||||
uint16_t id = 0;
|
||||
for (uint16_t i = 2; i < packetSize -3; i += 4)
|
||||
for (size_t i = 2; i < packetSize -3; i += 4)
|
||||
{
|
||||
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3]);
|
||||
|
||||
@ -519,7 +522,7 @@ void handleNotifications()
|
||||
} else if (udpIn[0] == 4) //dnrgb
|
||||
{
|
||||
uint16_t id = ((udpIn[3] << 0) & 0xFF) + ((udpIn[2] << 8) & 0xFF00);
|
||||
for (uint16_t i = 4; i < packetSize -2; i += 3)
|
||||
for (size_t i = 4; i < packetSize -2; i += 3)
|
||||
{
|
||||
if (id >= totalLen) break;
|
||||
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], 0);
|
||||
@ -528,7 +531,7 @@ void handleNotifications()
|
||||
} else if (udpIn[0] == 5) //dnrgbw
|
||||
{
|
||||
uint16_t id = ((udpIn[3] << 0) & 0xFF) + ((udpIn[2] << 8) & 0xFF00);
|
||||
for (uint16_t i = 4; i < packetSize -2; i += 4)
|
||||
for (size_t i = 4; i < packetSize -2; i += 4)
|
||||
{
|
||||
if (id >= totalLen) break;
|
||||
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3]);
|
||||
@ -560,11 +563,16 @@ void handleNotifications()
|
||||
void setRealtimePixel(uint16_t i, byte r, byte g, byte b, byte w)
|
||||
{
|
||||
uint16_t pix = i + arlsOffset;
|
||||
if (pix < strip.getLengthTotal())
|
||||
{
|
||||
if (!arlsDisableGammaCorrection && strip.gammaCorrectCol)
|
||||
{
|
||||
strip.setPixelColor(pix, strip.gamma8(r), strip.gamma8(g), strip.gamma8(b), strip.gamma8(w));
|
||||
if (pix < strip.getLengthTotal()) {
|
||||
if (!arlsDisableGammaCorrection && strip.gammaCorrectCol) {
|
||||
r = gamma8(r);
|
||||
g = gamma8(g);
|
||||
b = gamma8(b);
|
||||
w = gamma8(w);
|
||||
}
|
||||
if (useMainSegmentOnly) {
|
||||
Segment &seg = strip.getMainSegment();
|
||||
if (pix<seg.length()) seg.setPixelColor(pix, r, g, b, w);
|
||||
} else {
|
||||
strip.setPixelColor(pix, r, g, b, w);
|
||||
}
|
||||
@ -618,7 +626,7 @@ void sendSysInfoUDP()
|
||||
data[0] = 255;
|
||||
data[1] = 1;
|
||||
|
||||
for (byte x = 0; x < 4; x++) {
|
||||
for (size_t x = 0; x < 4; x++) {
|
||||
data[x + 2] = ip[x];
|
||||
}
|
||||
memcpy((byte *)data + 6, serverDescription, 32);
|
||||
@ -632,7 +640,7 @@ void sendSysInfoUDP()
|
||||
data[39] = ip[3]; // unit ID == last IP number
|
||||
|
||||
uint32_t build = VERSION;
|
||||
for (byte i=0; i<sizeof(uint32_t); i++)
|
||||
for (size_t i=0; i<sizeof(uint32_t); i++)
|
||||
data[40+i] = (build>>(8*i)) & 0xFF;
|
||||
|
||||
IPAddress broadcastIP(255, 255, 255, 255);
|
||||
@ -684,15 +692,15 @@ uint8_t realtimeBroadcast(uint8_t type, IPAddress client, uint16_t length, uint8
|
||||
case 0: // DDP
|
||||
{
|
||||
// calculate the number of UDP packets we need to send
|
||||
uint16_t channelCount = length * 3; // 1 channel for every R,G,B value
|
||||
uint16_t packetCount = ((channelCount-1) / DDP_CHANNELS_PER_PACKET) +1;
|
||||
size_t channelCount = length * 3; // 1 channel for every R,G,B value
|
||||
size_t packetCount = ((channelCount-1) / DDP_CHANNELS_PER_PACKET) +1;
|
||||
|
||||
// there are 3 channels per RGB pixel
|
||||
uint32_t channel = 0; // TODO: allow specifying the start channel
|
||||
// the current position in the buffer
|
||||
uint16_t bufferOffset = 0;
|
||||
size_t bufferOffset = 0;
|
||||
|
||||
for (uint16_t currentPacket = 0; currentPacket < packetCount; currentPacket++) {
|
||||
for (size_t currentPacket = 0; currentPacket < packetCount; currentPacket++) {
|
||||
if (sequenceNumber > 15) sequenceNumber = 0;
|
||||
|
||||
if (!ddpUdp.beginPacket(client, DDP_DEFAULT_PORT)) { // port defined in ESPAsyncE131.h
|
||||
@ -701,10 +709,10 @@ uint8_t realtimeBroadcast(uint8_t type, IPAddress client, uint16_t length, uint8
|
||||
}
|
||||
|
||||
// the amount of data is AFTER the header in the current packet
|
||||
uint16_t packetSize = DDP_CHANNELS_PER_PACKET;
|
||||
size_t packetSize = DDP_CHANNELS_PER_PACKET;
|
||||
|
||||
uint8_t flags = DDP_FLAGS1_VER1;
|
||||
if (currentPacket == (packetCount - 1)) {
|
||||
if (currentPacket == (packetCount - 1U)) {
|
||||
// last packet, set the push flag
|
||||
// TODO: determine if we want to send an empty push packet to each destination after sending the pixel data
|
||||
flags = DDP_FLAGS1_VER1 | DDP_FLAGS1_PUSH;
|
||||
@ -729,7 +737,7 @@ uint8_t realtimeBroadcast(uint8_t type, IPAddress client, uint16_t length, uint8
|
||||
|
||||
// write the colors, the write write(const uint8_t *buffer, size_t size)
|
||||
// function is just a loop internally too
|
||||
for (uint16_t i = 0; i < packetSize; i += 3) {
|
||||
for (size_t i = 0; i < packetSize; i += 3) {
|
||||
ddpUdp.write(scale8(buffer[bufferOffset++], bri)); // R
|
||||
ddpUdp.write(scale8(buffer[bufferOffset++], bri)); // G
|
||||
ddpUdp.write(scale8(buffer[bufferOffset++], bri)); // B
|
||||
|
@ -59,5 +59,3 @@ bool UsermodManager::add(Usermod* um)
|
||||
ums[numMods++] = um;
|
||||
return true;
|
||||
}
|
||||
|
||||
byte UsermodManager::getModCount() {return numMods;}
|
@ -132,6 +132,13 @@
|
||||
#include "../usermods/Si7021_MQTT_HA/usermod_si7021_mqtt_ha.h"
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_AUDIOREACTIVE
|
||||
#ifdef WLED_DISABLE_AUDIO
|
||||
#error Incompatible options: WLED_DISABLE_AUDIO and USERMOD_AUDIOREACTIVE
|
||||
#endif
|
||||
#include "../usermods/audioreactive/audio_reactive.h"
|
||||
#endif
|
||||
|
||||
void registerUsermods()
|
||||
{
|
||||
/*
|
||||
@ -251,4 +258,11 @@ void registerUsermods()
|
||||
#ifdef USERMOD_SI7021_MQTT_HA
|
||||
usermods.add(new Si7021_MQTT_HA());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_AUDIOREACTIVE
|
||||
#ifdef WLED_DISABLE_AUDIO
|
||||
#error Incompatible options: WLED_DISABLE_AUDIO and USERMOD_AUDIOREACTIVE
|
||||
#endif
|
||||
usermods.add(new AudioReactive());
|
||||
#endif
|
||||
}
|
||||
|
292
wled00/util.cpp
292
wled00/util.cpp
@ -14,16 +14,14 @@ int getNumVal(const String* req, uint16_t pos)
|
||||
void parseNumber(const char* str, byte* val, byte minv, byte maxv)
|
||||
{
|
||||
if (str == nullptr || str[0] == '\0') return;
|
||||
if (str[0] == 'r') {*val = random8(minv,maxv); return;}
|
||||
if (str[0] == 'r') {*val = random8(minv,maxv?maxv:255); return;} // maxv for random cannot be 0
|
||||
bool wrap = false;
|
||||
if (str[0] == 'w' && strlen(str) > 1) {str++; wrap = true;}
|
||||
if (str[0] == '~') {
|
||||
int out = atoi(str +1);
|
||||
if (out == 0)
|
||||
{
|
||||
if (out == 0) {
|
||||
if (str[1] == '0') return;
|
||||
if (str[1] == '-')
|
||||
{
|
||||
if (str[1] == '-') {
|
||||
*val = (int)(*val -1) < (int)minv ? maxv : min((int)maxv,(*val -1)); //-1, wrap around
|
||||
} else {
|
||||
*val = (int)(*val +1) > (int)maxv ? minv : max((int)minv,(*val +1)); //+1, wrap around
|
||||
@ -38,19 +36,20 @@ void parseNumber(const char* str, byte* val, byte minv, byte maxv)
|
||||
}
|
||||
*val = out;
|
||||
}
|
||||
} else
|
||||
{
|
||||
return;
|
||||
} else if (minv == maxv && minv == 0) { // limits "unset" i.e. both 0
|
||||
byte p1 = atoi(str);
|
||||
const char* str2 = strchr(str,'~'); //min/max range (for preset cycle, e.g. "1~5~")
|
||||
const char* str2 = strchr(str,'~'); // min/max range (for preset cycle, e.g. "1~5~")
|
||||
if (str2) {
|
||||
byte p2 = atoi(str2+1);
|
||||
presetCycMin = p1; presetCycMax = p2;
|
||||
while (isdigit((str2+1)[0])) str2++;
|
||||
parseNumber(str2+1, val, p1, p2);
|
||||
} else {
|
||||
*val = p1;
|
||||
byte p2 = atoi(++str2); // skip ~
|
||||
if (p2 > 0) {
|
||||
while (isdigit(*(++str2))); // skip digits
|
||||
parseNumber(str2, val, p1, p2);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
*val = atoi(str);
|
||||
}
|
||||
|
||||
|
||||
@ -70,12 +69,12 @@ bool getVal(JsonVariant elem, byte* val, byte vmin, byte vmax) {
|
||||
}
|
||||
|
||||
|
||||
bool updateVal(const String* req, const char* key, byte* val, byte minv, byte maxv)
|
||||
bool updateVal(const char* req, const char* key, byte* val, byte minv, byte maxv)
|
||||
{
|
||||
int pos = req->indexOf(key);
|
||||
if (pos < 1) return false;
|
||||
if (req->length() < (unsigned int)(pos + 4)) return false;
|
||||
parseNumber(req->c_str() + pos +3, val, minv, maxv);
|
||||
const char *v = strstr(req, key);
|
||||
if (v) v += strlen(key);
|
||||
else return false;
|
||||
parseNumber(v, val, minv, maxv);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -211,6 +210,9 @@ bool requestJSONBufferLock(uint8_t module)
|
||||
}
|
||||
|
||||
jsonBufferLock = module ? module : 255;
|
||||
DEBUG_PRINT(F("JSON buffer locked. ("));
|
||||
DEBUG_PRINT(jsonBufferLock);
|
||||
DEBUG_PRINTLN(")");
|
||||
fileDoc = &doc; // used for applying presets (presets.cpp)
|
||||
doc.clear();
|
||||
return true;
|
||||
@ -231,6 +233,22 @@ void releaseJSONBufferLock()
|
||||
// caller must provide large enough buffer for name (incluing SR extensions)!
|
||||
uint8_t extractModeName(uint8_t mode, const char *src, char *dest, uint8_t maxLen)
|
||||
{
|
||||
if (src == JSON_mode_names || src == nullptr) {
|
||||
if (mode < strip.getModeCount()) {
|
||||
char lineBuffer[256];
|
||||
//strcpy_P(lineBuffer, (const char*)pgm_read_dword(&(WS2812FX::_modeData[mode])));
|
||||
strcpy_P(lineBuffer, strip.getModeData(mode));
|
||||
size_t len = strlen(lineBuffer);
|
||||
size_t j = 0;
|
||||
for (; j < maxLen && j < len; j++) {
|
||||
if (lineBuffer[j] == '\0' || lineBuffer[j] == '@') break;
|
||||
dest[j] = lineBuffer[j];
|
||||
}
|
||||
dest[j] = 0; // terminate string
|
||||
return strlen(dest);
|
||||
} else return 0;
|
||||
}
|
||||
|
||||
uint8_t qComma = 0;
|
||||
bool insideQuotes = false;
|
||||
uint8_t printedChars = 0;
|
||||
@ -260,3 +278,239 @@ uint8_t extractModeName(uint8_t mode, const char *src, char *dest, uint8_t maxLe
|
||||
dest[printedChars] = '\0';
|
||||
return strlen(dest);
|
||||
}
|
||||
|
||||
|
||||
// extracts effect slider data (1st group after @)
|
||||
uint8_t extractModeSlider(uint8_t mode, uint8_t slider, char *dest, uint8_t maxLen, uint8_t *var)
|
||||
{
|
||||
dest[0] = '\0'; // start by clearing buffer
|
||||
|
||||
if (mode < strip.getModeCount()) {
|
||||
String lineBuffer = FPSTR(strip.getModeData(mode));
|
||||
if (lineBuffer.length() > 0) {
|
||||
int16_t start = lineBuffer.indexOf('@');
|
||||
int16_t stop = lineBuffer.indexOf(';', start);
|
||||
if (start>0 && stop>0) {
|
||||
String names = lineBuffer.substring(start, stop); // include @
|
||||
int16_t nameBegin = 1, nameEnd, nameDefault;
|
||||
if (slider < 10) {
|
||||
for (size_t i=0; i<=slider; i++) {
|
||||
const char *tmpstr;
|
||||
dest[0] = '\0'; //clear dest buffer
|
||||
if (nameBegin == 0) break; // there are no more names
|
||||
nameEnd = names.indexOf(',', nameBegin);
|
||||
if (i == slider) {
|
||||
nameDefault = names.indexOf('=', nameBegin); // find default value
|
||||
if (nameDefault > 0 && var && ((nameEnd>0 && nameDefault<nameEnd) || nameEnd<0)) {
|
||||
*var = (uint8_t)atoi(names.substring(nameDefault+1).c_str());
|
||||
}
|
||||
if (names.charAt(nameBegin) == '!') {
|
||||
switch (slider) {
|
||||
case 0: tmpstr = PSTR("FX Speed"); break;
|
||||
case 1: tmpstr = PSTR("FX Intensity"); break;
|
||||
case 2: tmpstr = PSTR("FX Custom 1"); break;
|
||||
case 3: tmpstr = PSTR("FX Custom 2"); break;
|
||||
case 4: tmpstr = PSTR("FX Custom 3"); break;
|
||||
default: tmpstr = PSTR("FX Custom"); break;
|
||||
}
|
||||
strncpy_P(dest, tmpstr, maxLen); // copy the name into buffer (replacing previous)
|
||||
dest[maxLen-1] = '\0';
|
||||
} else {
|
||||
if (nameEnd<0) tmpstr = names.substring(nameBegin).c_str(); // did not find ",", last name?
|
||||
else tmpstr = names.substring(nameBegin, nameEnd).c_str();
|
||||
strlcpy(dest, tmpstr, maxLen); // copy the name into buffer (replacing previous)
|
||||
}
|
||||
}
|
||||
nameBegin = nameEnd+1; // next name (if "," is not found it will be 0)
|
||||
} // next slider
|
||||
} else if (slider == 255) {
|
||||
// palette
|
||||
strlcpy(dest, "pal", maxLen);
|
||||
names = lineBuffer.substring(stop+1); // stop has index of color slot names
|
||||
nameBegin = names.indexOf(';'); // look for palette
|
||||
if (nameBegin >= 0) {
|
||||
nameEnd = names.indexOf(';', nameBegin+1);
|
||||
if (!isdigit(names[nameBegin+1])) nameBegin = names.indexOf('=', nameBegin+1); // look for default value
|
||||
if (nameEnd >= 0 && nameBegin > nameEnd) nameBegin = -1;
|
||||
if (nameBegin >= 0 && var) {
|
||||
*var = (uint8_t)atoi(names.substring(nameBegin+1).c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
// we have slider name (including default value) in the dest buffer
|
||||
for (size_t i=0; i<strlen(dest); i++) if (dest[i]=='=') { dest[i]='\0'; break; } // truncate default value
|
||||
|
||||
} else {
|
||||
// defaults to just speed and intensity since there is no slider data
|
||||
switch (slider) {
|
||||
case 0: strncpy_P(dest, PSTR("FX Speed"), maxLen); break;
|
||||
case 1: strncpy_P(dest, PSTR("FX Intensity"), maxLen); break;
|
||||
}
|
||||
dest[maxLen] = '\0'; // strncpy does not necessarily null terminate string
|
||||
}
|
||||
}
|
||||
return strlen(dest);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int16_t extractModeDefaults(uint8_t mode, const char *segVar)
|
||||
{
|
||||
if (mode < strip.getModeCount()) {
|
||||
String lineBuffer = FPSTR(strip.getModeData(mode));
|
||||
if (lineBuffer.length() > 0) {
|
||||
int16_t start = lineBuffer.lastIndexOf(';');
|
||||
if (start<0) return -1;
|
||||
|
||||
int16_t stop = lineBuffer.indexOf(segVar, start+1);
|
||||
if (stop<0) return -1;
|
||||
return atoi(lineBuffer.substring(stop+strlen(segVar)+1).c_str());
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
uint16_t crc16(const unsigned char* data_p, size_t length) {
|
||||
uint8_t x;
|
||||
uint16_t crc = 0xFFFF;
|
||||
if (!length) return 0x1D0F;
|
||||
while (length--) {
|
||||
x = crc >> 8 ^ *data_p++;
|
||||
x ^= x>>4;
|
||||
crc = (crc << 8) ^ ((uint16_t)(x << 12)) ^ ((uint16_t)(x <<5)) ^ ((uint16_t)x);
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
|
||||
#ifndef WLED_DISABLE_AUDIO
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Begin simulateSound (to enable audio enhanced effects to display something)
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Currently 4 types defined, to be fine tuned and new types added
|
||||
typedef enum UM_SoundSimulations {
|
||||
UMS_BeatSin = 0,
|
||||
UMS_WeWillRockYou,
|
||||
UMS_10_3,
|
||||
UMS_14_3
|
||||
} um_soundSimulations_t;
|
||||
|
||||
// this is still work in progress
|
||||
um_data_t* simulateSound(uint8_t simulationId)
|
||||
{
|
||||
static uint8_t samplePeak;
|
||||
static float FFT_MajorPeak;
|
||||
static uint8_t maxVol;
|
||||
static uint8_t binNum;
|
||||
|
||||
static float volumeSmth;
|
||||
static uint16_t volumeRaw;
|
||||
static float my_magnitude;
|
||||
|
||||
//arrays
|
||||
uint8_t *fftResult;
|
||||
|
||||
static um_data_t* um_data = nullptr;
|
||||
|
||||
if (!um_data) {
|
||||
//claim storage for arrays
|
||||
fftResult = (uint8_t *)malloc(sizeof(uint8_t) * 16);
|
||||
|
||||
// initialize um_data pointer structure
|
||||
// NOTE!!!
|
||||
// This may change as AudioReactive usermod may change
|
||||
um_data = new um_data_t;
|
||||
um_data->u_size = 8;
|
||||
um_data->u_type = new um_types_t[um_data->u_size];
|
||||
um_data->u_data = new void*[um_data->u_size];
|
||||
um_data->u_data[0] = &volumeSmth;
|
||||
um_data->u_data[1] = &volumeRaw;
|
||||
um_data->u_data[2] = fftResult;
|
||||
um_data->u_data[3] = &samplePeak;
|
||||
um_data->u_data[4] = &FFT_MajorPeak;
|
||||
um_data->u_data[5] = &my_magnitude;
|
||||
um_data->u_data[6] = &maxVol;
|
||||
um_data->u_data[7] = &binNum;
|
||||
} else {
|
||||
// get arrays from um_data
|
||||
fftResult = (uint8_t*)um_data->u_data[2];
|
||||
}
|
||||
|
||||
uint32_t ms = millis();
|
||||
|
||||
switch (simulationId) {
|
||||
default:
|
||||
case UMS_BeatSin:
|
||||
for (int i = 0; i<16; i++)
|
||||
fftResult[i] = beatsin8(120 / (i+1), 0, 255);
|
||||
// fftResult[i] = (beatsin8(120, 0, 255) + (256/16 * i)) % 256;
|
||||
volumeSmth = fftResult[8];
|
||||
break;
|
||||
case UMS_WeWillRockYou:
|
||||
if (ms%2000 < 200) {
|
||||
volumeSmth = random8(255);
|
||||
for (int i = 0; i<5; i++)
|
||||
fftResult[i] = random8(255);
|
||||
}
|
||||
else if (ms%2000 < 400) {
|
||||
volumeSmth = 0;
|
||||
for (int i = 0; i<16; i++)
|
||||
fftResult[i] = 0;
|
||||
}
|
||||
else if (ms%2000 < 600) {
|
||||
volumeSmth = random8(255);
|
||||
for (int i = 5; i<11; i++)
|
||||
fftResult[i] = random8(255);
|
||||
}
|
||||
else if (ms%2000 < 800) {
|
||||
volumeSmth = 0;
|
||||
for (int i = 0; i<16; i++)
|
||||
fftResult[i] = 0;
|
||||
}
|
||||
else if (ms%2000 < 1000) {
|
||||
volumeSmth = random8(255);
|
||||
for (int i = 11; i<16; i++)
|
||||
fftResult[i] = random8(255);
|
||||
}
|
||||
else {
|
||||
volumeSmth = 0;
|
||||
for (int i = 0; i<16; i++)
|
||||
fftResult[i] = 0;
|
||||
}
|
||||
break;
|
||||
case UMS_10_3:
|
||||
for (int i = 0; i<16; i++)
|
||||
fftResult[i] = inoise8(beatsin8(90 / (i+1), 0, 200)*15 + (ms>>10), ms>>3);
|
||||
volumeSmth = fftResult[8];
|
||||
break;
|
||||
case UMS_14_3:
|
||||
for (int i = 0; i<16; i++)
|
||||
fftResult[i] = inoise8(beatsin8(120 / (i+1), 10, 30)*10 + (ms>>14), ms>>3);
|
||||
volumeSmth = fftResult[8];
|
||||
break;
|
||||
}
|
||||
|
||||
samplePeak = random8() > 250;
|
||||
FFT_MajorPeak = volumeSmth;
|
||||
maxVol = 10; // this gets feedback fro UI
|
||||
binNum = 8; // this gets feedback fro UI
|
||||
volumeRaw = volumeSmth;
|
||||
my_magnitude = 10000.0 / 8.0f; //no idea if 10000 is a good value for FFT_Magnitude ???
|
||||
if (volumeSmth < 1 ) my_magnitude = 0.001f; // noise gate closed - mute
|
||||
|
||||
return um_data;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void enumerateLedmaps() {
|
||||
ledMaps = 1;
|
||||
for (size_t i=1; i<10; i++) {
|
||||
char fileName[16];
|
||||
sprintf_P(fileName, PSTR("/ledmap%d.json"), i);
|
||||
bool isFile = WLED_FS.exists(fileName);
|
||||
if (isFile) ledMaps |= 1 << i;
|
||||
}
|
||||
}
|
@ -118,6 +118,7 @@ void WLED::loop()
|
||||
if (stripMillis > maxStripMillis) maxStripMillis = stripMillis;
|
||||
#endif
|
||||
}
|
||||
|
||||
yield();
|
||||
#ifdef ESP8266
|
||||
MDNS.update();
|
||||
@ -204,6 +205,7 @@ void WLED::loop()
|
||||
DEBUG_PRINT(F("Loops/sec: ")); DEBUG_PRINTLN(loops / 30);
|
||||
DEBUG_PRINT(F("UM time[ms]: ")); DEBUG_PRINT(avgUsermodMillis/loops); DEBUG_PRINT("/");DEBUG_PRINTLN(maxUsermodMillis);
|
||||
DEBUG_PRINT(F("Strip time[ms]: ")); DEBUG_PRINT(avgStripMillis/loops); DEBUG_PRINT("/"); DEBUG_PRINTLN(maxStripMillis);
|
||||
strip.printSize();
|
||||
loops = 0;
|
||||
maxUsermodMillis = 0;
|
||||
maxStripMillis = 0;
|
||||
@ -313,7 +315,10 @@ void WLED::setup()
|
||||
if (!fsinit) {
|
||||
DEBUGFS_PRINTLN(F("FS failed!"));
|
||||
errorFlag = ERR_FS_BEGIN;
|
||||
} else deEEP();
|
||||
}
|
||||
#ifdef WLED_ADD_EEPROM_SUPPORT
|
||||
else deEEP();
|
||||
#endif
|
||||
updateFSInfo();
|
||||
|
||||
DEBUG_PRINTLN(F("Reading config"));
|
||||
@ -410,6 +415,7 @@ void WLED::beginStrip()
|
||||
{
|
||||
// Initialize NeoPixel Strip and button
|
||||
strip.finalizeInit(); // busses created during deserializeConfig()
|
||||
strip.loadCustomPalettes();
|
||||
strip.deserializeMap();
|
||||
strip.makeAutoSegments();
|
||||
strip.setBrightness(0);
|
||||
@ -692,6 +698,7 @@ void WLED::handleConnection()
|
||||
DEBUG_PRINT(F("Heap too low! "));
|
||||
DEBUG_PRINTLN(heap);
|
||||
forceReconnect = true;
|
||||
strip.purgeSegments(true); // remove all but one segments from memory
|
||||
}
|
||||
lastHeap = heap;
|
||||
heapTime = now;
|
||||
|
@ -8,7 +8,7 @@
|
||||
*/
|
||||
|
||||
// version code in format yymmddb (b = daily build)
|
||||
#define VERSION 2208140
|
||||
#define VERSION 2208191
|
||||
|
||||
//uncomment this if you have a "my_config.h" file you'd like to use
|
||||
//#define WLED_USE_MY_CONFIG
|
||||
@ -86,6 +86,8 @@
|
||||
#endif
|
||||
#include "esp_task_wdt.h"
|
||||
#endif
|
||||
#include <Wire.h>
|
||||
#include <SPI.h>
|
||||
|
||||
#include "src/dependencies/network/Network.h"
|
||||
|
||||
@ -94,7 +96,9 @@
|
||||
#endif
|
||||
|
||||
#include <ESPAsyncWebServer.h>
|
||||
#include <EEPROM.h>
|
||||
#ifdef WLED_ADD_EEPROM_SUPPORT
|
||||
#include <EEPROM.h>
|
||||
#endif
|
||||
#include <WiFiUdp.h>
|
||||
#include <DNSServer.h>
|
||||
#ifndef WLED_DISABLE_OTA
|
||||
@ -152,19 +156,12 @@ using PSRAMDynamicJsonDocument = BasicJsonDocument<PSRAM_Allocator>;
|
||||
#define PSRAMDynamicJsonDocument DynamicJsonDocument
|
||||
#endif
|
||||
|
||||
#include "fcn_declare.h"
|
||||
#include "html_ui.h"
|
||||
#ifdef WLED_ENABLE_SIMPLE_UI
|
||||
#include "html_simple.h"
|
||||
#endif
|
||||
#include "html_settings.h"
|
||||
#include "html_other.h"
|
||||
#include "FX.h"
|
||||
#include "ir_codes.h"
|
||||
#include "const.h"
|
||||
#include "fcn_declare.h"
|
||||
#include "NodeStruct.h"
|
||||
#include "pin_manager.h"
|
||||
#include "bus_manager.h"
|
||||
#include "FX.h"
|
||||
|
||||
#ifndef CLIENT_SSID
|
||||
#define CLIENT_SSID DEFAULT_CLIENT_SSID
|
||||
@ -458,12 +455,12 @@ WLED_GLOBAL bool wasConnected _INIT(false);
|
||||
WLED_GLOBAL byte lastRandomIndex _INIT(0); // used to save last random color so the new one is not the same
|
||||
|
||||
// transitions
|
||||
WLED_GLOBAL bool transitionActive _INIT(false);
|
||||
WLED_GLOBAL uint16_t transitionDelayDefault _INIT(transitionDelay);
|
||||
WLED_GLOBAL uint16_t transitionDelayTemp _INIT(transitionDelay);
|
||||
WLED_GLOBAL bool transitionActive _INIT(false);
|
||||
WLED_GLOBAL uint16_t transitionDelayDefault _INIT(transitionDelay); // default transition time (storec in cfg.json)
|
||||
WLED_GLOBAL uint16_t transitionDelayTemp _INIT(transitionDelay); // actual transition duration (overrides transitionDelay in certain cases)
|
||||
WLED_GLOBAL unsigned long transitionStartTime;
|
||||
WLED_GLOBAL float tperLast _INIT(0); // crossfade transition progress, 0.0f - 1.0f
|
||||
WLED_GLOBAL bool jsonTransitionOnce _INIT(false);
|
||||
WLED_GLOBAL float tperLast _INIT(0.0f); // crossfade transition progress, 0.0f - 1.0f
|
||||
WLED_GLOBAL bool jsonTransitionOnce _INIT(false); // flag to override transitionDelay (playlist, JSON API: "live" & "seg":{"i"} & "tt")
|
||||
|
||||
// nightlight
|
||||
WLED_GLOBAL bool nightlightActive _INIT(false);
|
||||
@ -642,10 +639,16 @@ WLED_GLOBAL WS2812FX strip _INIT(WS2812FX());
|
||||
WLED_GLOBAL BusConfig* busConfigs[WLED_MAX_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 uint16_t ledMaps _INIT(0); // bitfield representation of available ledmaps
|
||||
|
||||
// Usermod manager
|
||||
WLED_GLOBAL UsermodManager usermods _INIT(UsermodManager());
|
||||
|
||||
WLED_GLOBAL int8_t i2c_sda _INIT(-1); // global I2C SDA pin [HW_PIN_SDA] (used for usermods)
|
||||
WLED_GLOBAL int8_t i2c_scl _INIT(-1); // global I2C SCL pin [HW_PIN_SCL] (used for usermods)
|
||||
WLED_GLOBAL int8_t spi_mosi _INIT(-1); // global SPI DATA/MOSI pin [HW_PIN_DATASPI] (used for usermods)
|
||||
WLED_GLOBAL int8_t spi_sclk _INIT(-1); // global SPI CLOCK/SCLK pin [HW_PIN_CLOCKSPI] (used for usermods)
|
||||
|
||||
// global ArduinoJson buffer
|
||||
WLED_GLOBAL StaticJsonDocument<JSON_BUFFER_SIZE> doc;
|
||||
WLED_GLOBAL volatile uint8_t jsonBufferLock _INIT(0);
|
||||
|
@ -1,3 +1,4 @@
|
||||
#ifdef WLED_ADD_EEPROM_SUPPORT
|
||||
#include <EEPROM.h>
|
||||
#include "wled.h"
|
||||
|
||||
@ -418,7 +419,7 @@ void deEEP() {
|
||||
segObj[F("ix")] = EEPROM.read(i+16);
|
||||
segObj["pal"] = EEPROM.read(i+17);
|
||||
} else {
|
||||
WS2812FX::Segment* seg = strip.getSegments();
|
||||
Segment* seg = strip.getSegments();
|
||||
memcpy(seg, EEPROM.getDataPtr() +i+2, 240);
|
||||
if (ver == 2) { //versions before 2004230 did not have opacity
|
||||
for (byte j = 0; j < strip.getMaxSegments(); j++)
|
||||
@ -472,4 +473,5 @@ void deEEPSettings() {
|
||||
usermods.readFromConfig(empty);
|
||||
|
||||
serializeConfig();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -1,5 +1,12 @@
|
||||
#include "wled.h"
|
||||
|
||||
#include "html_ui.h"
|
||||
#ifdef WLED_ENABLE_SIMPLE_UI
|
||||
#include "html_simple.h"
|
||||
#endif
|
||||
#include "html_settings.h"
|
||||
#include "html_other.h"
|
||||
|
||||
/*
|
||||
* Integrated HTTP web server page declarations
|
||||
*/
|
||||
@ -103,6 +110,16 @@ void initServer()
|
||||
request->send(response);
|
||||
//request->send_P(200, "text/html", PAGE_liveviewws);
|
||||
});
|
||||
#ifndef WLED_DISABLE_2D
|
||||
server.on("/liveview2D", HTTP_GET, [](AsyncWebServerRequest *request){
|
||||
if (handleIfNoneMatchCacheHeader(request)) return;
|
||||
AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", PAGE_liveviewws2D, PAGE_liveviewws2D_length);
|
||||
response->addHeader(FPSTR(s_content_enc),"gzip");
|
||||
setStaticContentCacheHeaders(response);
|
||||
request->send(response);
|
||||
//request->send_P(200, "text/html", PAGE_liveviewws);
|
||||
});
|
||||
#endif
|
||||
#else
|
||||
server.on("/liveview", HTTP_GET, [](AsyncWebServerRequest *request){
|
||||
if (handleIfNoneMatchCacheHeader(request)) return;
|
||||
@ -482,7 +499,7 @@ void serveSettingsJS(AsyncWebServerRequest* request)
|
||||
char buf[SETTINGS_STACK_BUF_SIZE+37];
|
||||
buf[0] = 0;
|
||||
byte subPage = request->arg(F("p")).toInt();
|
||||
if (subPage > 9) {
|
||||
if (subPage > 10) {
|
||||
strcpy_P(buf, PSTR("alert('Settings for this request are not implemented.');"));
|
||||
request->send(501, "application/javascript", buf);
|
||||
return;
|
||||
@ -516,6 +533,7 @@ void serveSettings(AsyncWebServerRequest* request, bool post)
|
||||
else if (url.indexOf("sec") > 0) subPage = 6;
|
||||
else if (url.indexOf("dmx") > 0) subPage = 7;
|
||||
else if (url.indexOf("um") > 0) subPage = 8;
|
||||
else if (url.indexOf("2D") > 0) subPage = 10;
|
||||
else if (url.indexOf("lock") > 0) subPage = 251;
|
||||
}
|
||||
else if (url.indexOf("/update") >= 0) subPage = 9; // update page, for PIN check
|
||||
@ -548,6 +566,7 @@ void serveSettings(AsyncWebServerRequest* request, bool post)
|
||||
case 6: strcpy_P(s, PSTR("Security")); if (doReboot) strcpy_P(s2, PSTR("Rebooting, please wait ~10 seconds...")); break;
|
||||
case 7: strcpy_P(s, PSTR("DMX")); break;
|
||||
case 8: strcpy_P(s, PSTR("Usermods")); break;
|
||||
case 10: strcpy_P(s, PSTR("2D")); break;
|
||||
case 252: strcpy_P(s, correctPIN ? PSTR("PIN accepted") : PSTR("PIN rejected")); break;
|
||||
}
|
||||
|
||||
@ -578,6 +597,7 @@ void serveSettings(AsyncWebServerRequest* request, bool post)
|
||||
case 7: response = request->beginResponse_P(200, "text/html", PAGE_settings_dmx, PAGE_settings_dmx_length); break;
|
||||
case 8: response = request->beginResponse_P(200, "text/html", PAGE_settings_um, PAGE_settings_um_length); break;
|
||||
case 9: response = request->beginResponse_P(200, "text/html", PAGE_update, PAGE_update_length); break;
|
||||
case 10: response = request->beginResponse_P(200, "text/html", PAGE_settings_2D, PAGE_settings_2D_length); break;
|
||||
case 251: {
|
||||
correctPIN = !strlen(settingsPIN); // lock if a pin is set
|
||||
createEditHandler(correctPIN);
|
||||
|
@ -15,8 +15,8 @@ void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
|
||||
{
|
||||
if(type == WS_EVT_CONNECT){
|
||||
//client connected
|
||||
sendDataWs(client);
|
||||
DEBUG_PRINTLN(F("WS client connected."));
|
||||
sendDataWs(client);
|
||||
} else if(type == WS_EVT_DISCONNECT){
|
||||
//client disconnected
|
||||
if (client->id() == wsLiveClientId) wsLiveClientId = 0;
|
||||
@ -36,7 +36,6 @@ void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
|
||||
}
|
||||
|
||||
bool verboseResponse = false;
|
||||
DEBUG_PRINTLN(F("WS JSON receive buffer requested."));
|
||||
if (!requestJSONBufferLock(11)) return;
|
||||
|
||||
DeserializationError error = deserializeJson(doc, data, len);
|
||||
@ -59,6 +58,10 @@ void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
|
||||
if (verboseResponse) {
|
||||
sendDataWs(client);
|
||||
lastInterfaceUpdate = millis() - (INTERFACE_UPDATE_COOLDOWN -500);
|
||||
} else {
|
||||
// we have to send something back otherwise WS connection closes
|
||||
client->text(F("{\"success\":true}"));
|
||||
lastInterfaceUpdate = millis() - (INTERFACE_UPDATE_COOLDOWN -500);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -97,7 +100,6 @@ void sendDataWs(AsyncWebSocketClient * client)
|
||||
if (!ws.count()) return;
|
||||
AsyncWebSocketMessageBuffer * buffer;
|
||||
|
||||
DEBUG_PRINTLN(F("WS JSON send buffer requested."));
|
||||
if (!requestJSONBufferLock(12)) return;
|
||||
|
||||
JsonObject state = doc.createNestedObject("state");
|
||||
@ -105,21 +107,22 @@ void sendDataWs(AsyncWebSocketClient * client)
|
||||
JsonObject info = doc.createNestedObject("info");
|
||||
serializeInfo(info);
|
||||
|
||||
DEBUG_PRINTF("JSON buffer size: %u for WS request.\n", doc.memoryUsage());
|
||||
size_t len = measureJson(doc);
|
||||
DEBUG_PRINTF("JSON buffer size: %u for WS request (%u).\n", doc.memoryUsage(), len);
|
||||
|
||||
size_t heap1 = ESP.getFreeHeap();
|
||||
buffer = ws.makeBuffer(len); // will not allocate correct memory sometimes
|
||||
size_t heap2 = ESP.getFreeHeap();
|
||||
if (!buffer || heap1-heap2<len) {
|
||||
releaseJSONBufferLock();
|
||||
DEBUG_PRINTLN(F("WS buffer allocation failed."));
|
||||
ws.closeAll(1013); //code 1013 = temporary overload, try again later
|
||||
ws.cleanupClients(0); //disconnect all clients to release memory
|
||||
return; //out of memory
|
||||
}
|
||||
|
||||
serializeJson(doc, (char *)buffer->get(), len +1);
|
||||
releaseJSONBufferLock();
|
||||
buffer->lock();
|
||||
serializeJson(doc, (char *)buffer->get(), len);
|
||||
|
||||
DEBUG_PRINT(F("Sending WS data "));
|
||||
if (client) {
|
||||
@ -129,9 +132,11 @@ void sendDataWs(AsyncWebSocketClient * client)
|
||||
ws.textAll(buffer);
|
||||
DEBUG_PRINTLN(F("to multiple clients."));
|
||||
}
|
||||
}
|
||||
buffer->unlock();
|
||||
ws._cleanBuffers();
|
||||
|
||||
#define MAX_LIVE_LEDS_WS 256
|
||||
releaseJSONBufferLock();
|
||||
}
|
||||
|
||||
bool sendLiveLedsWs(uint32_t wsClient)
|
||||
{
|
||||
@ -139,16 +144,24 @@ bool sendLiveLedsWs(uint32_t wsClient)
|
||||
if (!wsc || wsc->queueLength() > 0) return false; //only send if queue free
|
||||
|
||||
uint16_t used = strip.getLengthTotal();
|
||||
const uint16_t MAX_LIVE_LEDS_WS = strip.isMatrix ? 1024 : 256;
|
||||
uint16_t n = ((used -1)/MAX_LIVE_LEDS_WS) +1; //only serve every n'th LED if count over MAX_LIVE_LEDS_WS
|
||||
uint16_t bufSize = 2 + (used/n)*3;
|
||||
uint16_t pos = (strip.isMatrix ? 4 : 2);
|
||||
uint16_t bufSize = pos + (used/n)*3;
|
||||
AsyncWebSocketMessageBuffer * wsBuf = ws.makeBuffer(bufSize);
|
||||
if (!wsBuf) return false; //out of memory
|
||||
uint8_t* buffer = wsBuf->get();
|
||||
buffer[0] = 'L';
|
||||
buffer[1] = 1; //version
|
||||
#ifndef WLED_DISABLE_2D
|
||||
if (strip.isMatrix) {
|
||||
buffer[1] = 2; //version
|
||||
buffer[2] = strip.matrixWidth;
|
||||
buffer[3] = strip.matrixHeight;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint16_t pos = 2;
|
||||
for (uint16_t i= 0; pos < bufSize -2; i += n)
|
||||
for (uint16_t i = 0; pos < bufSize -2; i += n)
|
||||
{
|
||||
uint32_t c = strip.getPixelColor(i);
|
||||
buffer[pos++] = qadd8(W(c), R(c)); //R, add white channel to RGB channels as a simple RGBW -> RGB map
|
||||
|
@ -177,7 +177,7 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
obuf = dest;
|
||||
olen = 0;
|
||||
|
||||
if (subPage <0 || subPage >9) return;
|
||||
if (subPage <0 || subPage >10) return;
|
||||
|
||||
if (subPage == 0)
|
||||
{
|
||||
@ -261,6 +261,15 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
// add reserved and usermod pins as d.um_p array
|
||||
oappend(SET_F("d.um_p=[6,7,8,9,10,11"));
|
||||
|
||||
if (i2c_sda > -1 && i2c_scl > -1) {
|
||||
oappend(","); oappend(itoa(i2c_sda,nS,10));
|
||||
oappend(","); oappend(itoa(i2c_scl,nS,10));
|
||||
}
|
||||
if (spi_mosi > -1 && spi_sclk > -1) {
|
||||
oappend(","); oappend(itoa(spi_mosi,nS,10));
|
||||
oappend(","); oappend(itoa(spi_sclk,nS,10));
|
||||
}
|
||||
|
||||
if (requestJSONBufferLock(6)) {
|
||||
// if we can't allocate JSON buffer ignore usermod pins
|
||||
JsonObject mods = doc.createNestedObject(F("um"));
|
||||
@ -308,9 +317,14 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
|
||||
// set limits
|
||||
oappend(SET_F("bLimits("));
|
||||
#if defined(ESP32) && defined(USERMOD_AUDIOREACTIVE)
|
||||
// requested by @softhack007 https://github.com/blazoncek/WLED/issues/33
|
||||
oappend(itoa(WLED_MAX_BUSSES-2,nS,10)); oappend(","); // prevent use of I2S buses if audio installed
|
||||
#else
|
||||
oappend(itoa(WLED_MAX_BUSSES,nS,10)); oappend(",");
|
||||
#endif
|
||||
oappend(itoa(MAX_LEDS_PER_BUS,nS,10)); oappend(",");
|
||||
oappend(itoa(MAX_LED_MEMORY,nS,10)); oappend(",");
|
||||
oappend(itoa(MAX_LED_MEMORY,nS,10)); oappend(",");
|
||||
oappend(itoa(MAX_LEDS,nS,10));
|
||||
oappend(SET_F(");"));
|
||||
|
||||
@ -320,6 +334,7 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
sappend('v',SET_F("CB"),strip.cctBlending);
|
||||
sappend('v',SET_F("FR"),strip.getTargetFps());
|
||||
sappend('v',SET_F("AW"),Bus::getAutoWhiteMode());
|
||||
sappend('v',SET_F("LD"),strip.useLedsArray);
|
||||
|
||||
for (uint8_t s=0; s < busses.getNumBusses(); s++) {
|
||||
Bus* bus = busses.getBus(s);
|
||||
@ -580,6 +595,9 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
oappend(SET_F(" (build "));
|
||||
oappendi(VERSION);
|
||||
oappend(SET_F(")\";"));
|
||||
oappend(SET_F("sd=\""));
|
||||
oappend(serverDescription);
|
||||
oappend(SET_F("\";"));
|
||||
}
|
||||
|
||||
#ifdef WLED_ENABLE_DMX // include only if DMX is enabled
|
||||
@ -615,6 +633,14 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
oappend(SET_F("numM="));
|
||||
oappendi(usermods.getModCount());
|
||||
oappend(";");
|
||||
sappend('v',SET_F("SDA"),i2c_sda);
|
||||
sappend('v',SET_F("SCL"),i2c_scl);
|
||||
sappend('v',SET_F("MOSI"),spi_mosi);
|
||||
sappend('v',SET_F("SCLK"),spi_sclk);
|
||||
oappend(SET_F("addInfo('SDA','")); oappendi(HW_PIN_SDA); oappend(SET_F("');"));
|
||||
oappend(SET_F("addInfo('SCL','")); oappendi(HW_PIN_SCL); oappend(SET_F("');"));
|
||||
oappend(SET_F("addInfo('MOSI','")); oappendi(HW_PIN_DATASPI); oappend(SET_F("');"));
|
||||
oappend(SET_F("addInfo('SCLK','")); oappendi(HW_PIN_CLOCKSPI); oappend(SET_F("');"));
|
||||
usermods.appendConfigData();
|
||||
}
|
||||
|
||||
@ -632,4 +658,37 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
oappendi(VERSION);
|
||||
oappend(SET_F(")\";"));
|
||||
}
|
||||
|
||||
if (subPage == 10) // 2D matrices
|
||||
{
|
||||
sappend('v',SET_F("SOMP"),strip.isMatrix);
|
||||
#ifndef WLED_DISABLE_2D
|
||||
oappend(SET_F("resetPanels();"));
|
||||
if (strip.isMatrix) {
|
||||
sappend('v',SET_F("PH"),strip.panelH);
|
||||
sappend('v',SET_F("PW"),strip.panelW);
|
||||
sappend('v',SET_F("MPH"),strip.hPanels);
|
||||
sappend('v',SET_F("MPV"),strip.vPanels);
|
||||
sappend('v',SET_F("PB"),strip.matrix.bottomStart);
|
||||
sappend('v',SET_F("PR"),strip.matrix.rightStart);
|
||||
sappend('v',SET_F("PV"),strip.matrix.vertical);
|
||||
sappend('c',SET_F("PS"),strip.matrix.serpentine);
|
||||
// panels
|
||||
for (uint8_t i=0; i<strip.hPanels*strip.vPanels; i++) {
|
||||
char n[5];
|
||||
oappend(SET_F("addPanel("));
|
||||
oappend(itoa(i,n,10));
|
||||
oappend(SET_F(");"));
|
||||
char pO[8]; sprintf_P(pO, PSTR("P%d"), i);
|
||||
uint8_t l = strlen(pO); pO[l+1] = 0;
|
||||
pO[l] = 'B'; sappend('v',pO,strip.panel[i].bottomStart);
|
||||
pO[l] = 'R'; sappend('v',pO,strip.panel[i].rightStart);
|
||||
pO[l] = 'V'; sappend('v',pO,strip.panel[i].vertical);
|
||||
pO[l] = 'S'; sappend('c',pO,strip.panel[i].serpentine);
|
||||
}
|
||||
}
|
||||
#else
|
||||
oappend(SET_F("gId(\"somp\").remove(1);")); // remove 2D option from dropdown
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user