diff --git a/wled00/e131.cpp b/wled00/e131.cpp
index c16ed9332..98cfe28fb 100644
--- a/wled00/e131.cpp
+++ b/wled00/e131.cpp
@@ -38,8 +38,7 @@ void handleDDPPacket(e131_packet_t* p) {
if (realtimeMode != REALTIME_MODE_DDP) ddpSeenPush = false; // just starting, no push yet
realtimeLock(realtimeTimeoutMs, REALTIME_MODE_DDP);
- if (!realtimeOverride || (realtimeMode && useMainSegmentOnly)) {
- if (useMainSegmentOnly) strip.getMainSegment().beginDraw();
+ if (!realtimeOverride) {
for (unsigned i = start; i < stop; i++, c += ddpChannelsPerLed) {
setRealtimePixel(i, data[c], data[c+1], data[c+2], ddpChannelsPerLed >3 ? data[c+3] : 0);
}
@@ -150,10 +149,9 @@ void handleDMXData(uint16_t uni, uint16_t dmxChannels, uint8_t* e131_data, uint8
realtimeLock(realtimeTimeoutMs, mde);
- if (realtimeOverride && !(realtimeMode && useMainSegmentOnly)) return;
+ if (realtimeOverride) return;
wChannel = (availDMXLen > 3) ? e131_data[dataOffset+3] : 0;
- if (useMainSegmentOnly) strip.getMainSegment().beginDraw();
for (unsigned i = 0; i < totalLen; i++)
setRealtimePixel(i, e131_data[dataOffset+0], e131_data[dataOffset+1], e131_data[dataOffset+2], wChannel);
break;
@@ -163,7 +161,7 @@ void handleDMXData(uint16_t uni, uint16_t dmxChannels, uint8_t* e131_data, uint8
if (availDMXLen < 4) return;
realtimeLock(realtimeTimeoutMs, mde);
- if (realtimeOverride && !(realtimeMode && useMainSegmentOnly)) return;
+ if (realtimeOverride) return;
wChannel = (availDMXLen > 4) ? e131_data[dataOffset+4] : 0;
if (bri != e131_data[dataOffset+0]) {
@@ -171,7 +169,6 @@ void handleDMXData(uint16_t uni, uint16_t dmxChannels, uint8_t* e131_data, uint8
strip.setBrightness(bri, true);
}
- if (useMainSegmentOnly) strip.getMainSegment().beginDraw();
for (unsigned i = 0; i < totalLen; i++)
setRealtimePixel(i, e131_data[dataOffset+1], e131_data[dataOffset+2], e131_data[dataOffset+3], wChannel);
break;
@@ -228,16 +225,16 @@ void handleDMXData(uint16_t uni, uint16_t dmxChannels, uint8_t* e131_data, uint8
if (e131_data[dataOffset+3] != seg.intensity) seg.intensity = e131_data[dataOffset+3];
if (e131_data[dataOffset+4] != seg.palette) seg.setPalette(e131_data[dataOffset+4]);
- if ((e131_data[dataOffset+5] & 0b00000010) != seg.reverse_y) { seg.setOption(SEG_OPTION_REVERSED_Y, e131_data[dataOffset+5] & 0b00000010); }
- if ((e131_data[dataOffset+5] & 0b00000100) != seg.mirror_y) { seg.setOption(SEG_OPTION_MIRROR_Y, e131_data[dataOffset+5] & 0b00000100); }
- if ((e131_data[dataOffset+5] & 0b00001000) != seg.transpose) { seg.setOption(SEG_OPTION_TRANSPOSED, e131_data[dataOffset+5] & 0b00001000); }
- if ((e131_data[dataOffset+5] & 0b00110000) / 8 != seg.map1D2D) {
- seg.map1D2D = (e131_data[dataOffset+5] & 0b00110000) / 8;
+ if (bool(e131_data[dataOffset+5] & 0b00000010) != seg.reverse_y) { seg.reverse_y = bool(e131_data[dataOffset+5] & 0b00000010); }
+ if (bool(e131_data[dataOffset+5] & 0b00000100) != seg.mirror_y) { seg.mirror_y = bool(e131_data[dataOffset+5] & 0b00000100); }
+ if (bool(e131_data[dataOffset+5] & 0b00001000) != seg.transpose) { seg.transpose = bool(e131_data[dataOffset+5] & 0b00001000); }
+ if ((e131_data[dataOffset+5] & 0b00110000) >> 4 != seg.map1D2D) {
+ seg.map1D2D = (e131_data[dataOffset+5] & 0b00110000) >> 4;
}
// To maintain backwards compatibility with prior e1.31 values, reverse is fixed to mask 0x01000000
- if ((e131_data[dataOffset+5] & 0b01000000) != seg.reverse) { seg.setOption(SEG_OPTION_REVERSED, e131_data[dataOffset+5] & 0b01000000); }
+ if ((e131_data[dataOffset+5] & 0b01000000) != seg.reverse) { seg.reverse = bool(e131_data[dataOffset+5] & 0b01000000); }
// To maintain backwards compatibility with prior e1.31 values, mirror is fixed to mask 0x10000000
- if ((e131_data[dataOffset+5] & 0b10000000) != seg.mirror) { seg.setOption(SEG_OPTION_MIRROR, e131_data[dataOffset+5] & 0b10000000); }
+ if ((e131_data[dataOffset+5] & 0b10000000) != seg.mirror) { seg.mirror = bool(e131_data[dataOffset+5] & 0b10000000); }
uint32_t colors[3];
byte whites[3] = {0,0,0};
@@ -271,7 +268,7 @@ void handleDMXData(uint16_t uni, uint16_t dmxChannels, uint8_t* e131_data, uint8
case DMX_MODE_MULTIPLE_RGB:
case DMX_MODE_MULTIPLE_RGBW:
{
- bool is4Chan = (DMXMode == DMX_MODE_MULTIPLE_RGBW);
+ const bool is4Chan = (DMXMode == DMX_MODE_MULTIPLE_RGBW);
const unsigned dmxChannelsPerLed = is4Chan ? 4 : 3;
const unsigned ledsPerUniverse = is4Chan ? MAX_4_CH_LEDS_PER_UNIVERSE : MAX_3_CH_LEDS_PER_UNIVERSE;
uint8_t stripBrightness = bri;
@@ -303,7 +300,7 @@ void handleDMXData(uint16_t uni, uint16_t dmxChannels, uint8_t* e131_data, uint8
}
realtimeLock(realtimeTimeoutMs, mde);
- if (realtimeOverride && !(realtimeMode && useMainSegmentOnly)) return;
+ if (realtimeOverride) return;
if (ledsTotal > totalLen) {
ledsTotal = totalLen;
@@ -316,17 +313,9 @@ void handleDMXData(uint16_t uni, uint16_t dmxChannels, uint8_t* e131_data, uint8
}
}
- if (useMainSegmentOnly) strip.getMainSegment().beginDraw();
- if (!is4Chan) {
- for (unsigned i = previousLeds; i < ledsTotal; i++) {
- setRealtimePixel(i, e131_data[dmxOffset], e131_data[dmxOffset+1], e131_data[dmxOffset+2], 0);
- dmxOffset+=3;
- }
- } else {
- for (unsigned i = previousLeds; i < ledsTotal; i++) {
- setRealtimePixel(i, e131_data[dmxOffset], e131_data[dmxOffset+1], e131_data[dmxOffset+2], e131_data[dmxOffset+3]);
- dmxOffset+=4;
- }
+ for (unsigned i = previousLeds; i < ledsTotal; i++) {
+ setRealtimePixel(i, e131_data[dmxOffset], e131_data[dmxOffset+1], e131_data[dmxOffset+2], is4Chan ? e131_data[dmxOffset+3] : 0);
+ dmxOffset += dmxChannelsPerLed;
}
break;
}
@@ -529,7 +518,7 @@ void sendArtnetPollReply(ArtPollReply *reply, IPAddress ipAddress, uint16_t port
reply->reply_sub_sw = (uint8_t)((portAddress >> 4) & 0x000F);
reply->reply_sw_out[0] = (uint8_t)(portAddress & 0x000F);
- snprintf_P((char *)reply->reply_node_report, sizeof(reply->reply_node_report)-1, PSTR("#0001 [%04u] OK - WLED v" TOSTRING(WLED_VERSION)), pollReplyCount);
+ snprintf_P((char *)reply->reply_node_report, sizeof(reply->reply_node_report)-1, PSTR("#0001 [%04u] OK - WLED v%s"), pollReplyCount, versionString);
if (pollReplyCount < 9999) {
pollReplyCount++;
diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h
index ff2443648..d2f62870d 100644
--- a/wled00/fcn_declare.h
+++ b/wled00/fcn_declare.h
@@ -158,13 +158,18 @@ class NeoGammaWLEDMethod {
public:
[[gnu::hot]] static uint8_t Correct(uint8_t value); // apply Gamma to single channel
[[gnu::hot]] static uint32_t Correct32(uint32_t color); // apply Gamma to RGBW32 color (WLED specific, not used by NPB)
- static void calcGammaTable(float gamma); // re-calculates & fills gamma table
+ [[gnu::hot]] static uint32_t inverseGamma32(uint32_t color); // apply inverse Gamma to RGBW32 color
+ static void calcGammaTable(float gamma); // re-calculates & fills gamma tables
static inline uint8_t rawGamma8(uint8_t val) { return gammaT[val]; } // get value from Gamma table (WLED specific, not used by NPB)
+ static inline uint8_t rawInverseGamma8(uint8_t val) { return gammaT_inv[val]; } // get value from inverse Gamma table (WLED specific, not used by NPB)
private:
static uint8_t gammaT[];
+ static uint8_t gammaT_inv[];
};
#define gamma32(c) NeoGammaWLEDMethod::Correct32(c)
#define gamma8(c) NeoGammaWLEDMethod::rawGamma8(c)
+#define gamma32inv(c) NeoGammaWLEDMethod::inverseGamma32(c)
+#define gamma8inv(c) NeoGammaWLEDMethod::rawInverseGamma8(c)
[[gnu::hot, gnu::pure]] uint32_t color_blend(uint32_t c1, uint32_t c2 , uint8_t blend);
inline uint32_t color_blend16(uint32_t c1, uint32_t c2, uint16_t b) { return color_blend(c1, c2, b >> 8); };
[[gnu::hot, gnu::pure]] uint32_t color_add(uint32_t, uint32_t, bool preserveCR = false);
@@ -172,6 +177,9 @@ inline uint32_t color_blend16(uint32_t c1, uint32_t c2, uint16_t b) { return col
[[gnu::hot, gnu::pure]] uint32_t ColorFromPaletteWLED(const CRGBPalette16 &pal, unsigned index, uint8_t brightness = (uint8_t)255U, TBlendType blendType = LINEARBLEND);
CRGBPalette16 generateHarmonicRandomPalette(const CRGBPalette16 &basepalette);
CRGBPalette16 generateRandomPalette();
+void loadCustomPalettes();
+extern std::vector
customPalettes;
+inline size_t getPaletteCount() { return 13 + GRADIENT_PALETTE_COUNT + customPalettes.size(); }
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 hsv2rgb(const CHSV32& hsv, uint32_t& rgb);
void colorHStoRGB(uint16_t hue, byte sat, byte* rgb);
@@ -223,9 +231,8 @@ void onHueConnect(void* arg, AsyncClient* client);
void sendHuePoll();
void onHueData(void* arg, AsyncClient* client, void *data, size_t len);
-#include "FX.h" // must be below colors.cpp declarations (potentially due to duplicate declarations of e.g. color_blend)
-
//image_loader.cpp
+class Segment;
#ifdef WLED_ENABLE_GIF
bool fileSeekCallback(unsigned long position);
unsigned long filePositionCallback(void);
@@ -261,9 +268,7 @@ void handleIR();
#include "ESPAsyncWebServer.h"
#include "src/dependencies/json/ArduinoJson-v6.h"
#include "src/dependencies/json/AsyncJson-v6.h"
-#include "FX.h"
-bool deserializeSegment(JsonObject elem, byte it, byte presetId = 0);
bool deserializeState(JsonObject root, byte callMode = CALL_MODE_DIRECT_CHANGE, byte presetId = 0);
void serializeSegment(const JsonObject& root, const Segment& seg, byte id, bool forPreset = false, bool segmentBounds = true);
void serializeState(JsonObject root, bool forPreset = false, bool includeBri = true, bool segmentBounds = true, bool selectedSegmentsOnly = false);
@@ -277,8 +282,8 @@ bool serveLiveLeds(AsyncWebServerRequest* request, uint32_t wsClient = 0);
//led.cpp
void setValuesFromSegment(uint8_t s);
-void setValuesFromMainSeg();
-void setValuesFromFirstSelectedSeg();
+#define setValuesFromMainSeg() setValuesFromSegment(strip.getMainSegmentId())
+#define setValuesFromFirstSelectedSeg() setValuesFromSegment(strip.getFirstSelectedSegId())
void toggleOnOff();
void applyBri();
void applyFinalBri();
@@ -490,11 +495,11 @@ void userLoop();
#define inoise8 perlin8 // fastled legacy alias
#define inoise16 perlin16 // fastled legacy alias
#define hex2int(a) (((a)>='0' && (a)<='9') ? (a)-'0' : ((a)>='A' && (a)<='F') ? (a)-'A'+10 : ((a)>='a' && (a)<='f') ? (a)-'a'+10 : 0)
-[[gnu::pure]] 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 vmin=0, byte vmax=255); // getVal supports inc/decrementing and random ("X~Y(r|[w]~[-][Z])" form)
+[[gnu::pure]] 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 vmin=0, byte vmax=255); // getVal supports inc/decrementing and random ("X~Y(r|[w]~[-][Z])" form)
[[gnu::pure]] bool getBoolVal(const JsonVariant &elem, bool dflt);
-bool updateVal(const char* 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);
size_t printSetFormCheckbox(Print& settingsScript, const char* key, int val);
size_t printSetFormValue(Print& settingsScript, const char* key, int val);
size_t printSetFormValue(Print& settingsScript, const char* key, const char* val);
@@ -544,6 +549,29 @@ inline uint8_t hw_random8() { return HW_RND_REGISTER; };
inline uint8_t hw_random8(uint32_t upperlimit) { return (hw_random8() * upperlimit) >> 8; }; // input range 0-255
inline uint8_t hw_random8(uint32_t lowerlimit, uint32_t upperlimit) { uint32_t range = upperlimit - lowerlimit; return lowerlimit + hw_random8(range); }; // input range 0-255
+// PSRAM allocation wrappers
+#ifndef ESP8266
+extern "C" {
+ void *p_malloc(size_t); // prefer PSRAM over DRAM
+ void *p_calloc(size_t, size_t); // prefer PSRAM over DRAM
+ void *p_realloc(void *, size_t); // prefer PSRAM over DRAM
+ inline void p_free(void *ptr) { heap_caps_free(ptr); }
+ void *d_malloc(size_t); // prefer DRAM over PSRAM
+ void *d_calloc(size_t, size_t); // prefer DRAM over PSRAM
+ void *d_realloc(void *, size_t); // prefer DRAM over PSRAM
+ inline void d_free(void *ptr) { heap_caps_free(ptr); }
+}
+#else
+#define p_malloc malloc
+#define p_calloc calloc
+#define p_realloc realloc
+#define p_free free
+#define d_malloc malloc
+#define d_calloc calloc
+#define d_realloc realloc
+#define d_free free
+#endif
+
// RAII guard class for the JSON Buffer lock
// Modeled after std::lock_guard
class JSONBufferGuard {
diff --git a/wled00/file.cpp b/wled00/file.cpp
index d390207d4..c1960e616 100644
--- a/wled00/file.cpp
+++ b/wled00/file.cpp
@@ -39,7 +39,7 @@ void closeFile() {
uint32_t s = millis();
#endif
f.close();
- DEBUGFS_PRINTF("took %d ms\n", millis() - s);
+ DEBUGFS_PRINTF("took %lu ms\n", millis() - s);
doCloseFile = false;
}
@@ -69,14 +69,14 @@ static bool bufferedFind(const char *target, bool fromStart = true) {
if(buf[count] == target[index]) {
if(++index >= targetLen) { // return true if all chars in the target match
f.seek((f.position() - bufsize) + count +1);
- DEBUGFS_PRINTF("Found at pos %d, took %d ms", f.position(), millis() - s);
+ DEBUGFS_PRINTF("Found at pos %d, took %lu ms", f.position(), millis() - s);
return true;
}
}
count++;
}
}
- DEBUGFS_PRINTF("No match, took %d ms\n", millis() - s);
+ DEBUGFS_PRINTF("No match, took %lu ms\n", millis() - s);
return false;
}
@@ -111,7 +111,7 @@ static bool bufferedFindSpace(size_t targetLen, bool fromStart = true) {
f.seek((f.position() - bufsize) + count +1 - targetLen);
knownLargestSpace = MAX_SPACE; //there may be larger spaces after, so we don't know
}
- DEBUGFS_PRINTF("Found at pos %d, took %d ms", f.position(), millis() - s);
+ DEBUGFS_PRINTF("Found at pos %d, took %lu ms", f.position(), millis() - s);
return true;
}
} else {
@@ -125,7 +125,7 @@ static bool bufferedFindSpace(size_t targetLen, bool fromStart = true) {
count++;
}
}
- DEBUGFS_PRINTF("No match, took %d ms\n", millis() - s);
+ DEBUGFS_PRINTF("No match, took %lu ms\n", millis() - s);
return false;
}
@@ -151,13 +151,13 @@ static bool bufferedFindObjectEnd() {
if (buf[count] == '}') objDepth--;
if (objDepth == 0) {
f.seek((f.position() - bufsize) + count +1);
- DEBUGFS_PRINTF("} at pos %d, took %d ms", f.position(), millis() - s);
+ DEBUGFS_PRINTF("} at pos %d, took %lu ms", f.position(), millis() - s);
return true;
}
count++;
}
}
- DEBUGFS_PRINTF("No match, took %d ms\n", millis() - s);
+ DEBUGFS_PRINTF("No match, took %lu ms\n", millis() - s);
return false;
}
@@ -203,7 +203,7 @@ static bool appendObjectToFile(const char* key, const JsonDocument* content, uin
if (f.position() > 2) f.write(','); //add comma if not first object
f.print(key);
serializeJson(*content, f);
- DEBUGFS_PRINTF("Inserted, took %d ms (total %d)", millis() - s1, millis() - s);
+ DEBUGFS_PRINTF("Inserted, took %lu ms (total %lu)", millis() - s1, millis() - s);
doCloseFile = true;
return true;
}
@@ -251,7 +251,7 @@ static bool appendObjectToFile(const char* key, const JsonDocument* content, uin
f.write('}');
doCloseFile = true;
- DEBUGFS_PRINTF("Appended, took %d ms (total %d)", millis() - s1, millis() - s);
+ DEBUGFS_PRINTF("Appended, took %lu ms (total %lu)", millis() - s1, millis() - s);
return true;
}
@@ -321,7 +321,7 @@ bool writeObjectToFile(const char* file, const char* key, const JsonDocument* co
}
doCloseFile = true;
- DEBUGFS_PRINTF("Replaced/deleted, took %d ms\n", millis() - s);
+ DEBUGFS_PRINTF("Replaced/deleted, took %lu ms\n", millis() - s);
return true;
}
@@ -356,7 +356,7 @@ bool readObjectFromFile(const char* file, const char* key, JsonDocument* dest, c
else deserializeJson(*dest, f);
f.close();
- DEBUGFS_PRINTF("Read, took %d ms\n", millis() - s);
+ DEBUGFS_PRINTF("Read, took %lu ms\n", millis() - s);
return true;
}
@@ -392,7 +392,7 @@ static const uint8_t *getPresetCache(size_t &size) {
if ((presetsModifiedTime != presetsCachedTime) || (presetsCachedValidate != cacheInvalidate)) {
if (presetsCached) {
- free(presetsCached);
+ p_free(presetsCached);
presetsCached = nullptr;
}
}
@@ -403,7 +403,7 @@ static const uint8_t *getPresetCache(size_t &size) {
presetsCachedTime = presetsModifiedTime;
presetsCachedValidate = cacheInvalidate;
presetsCachedSize = 0;
- presetsCached = (uint8_t*)ps_malloc(file.size() + 1);
+ presetsCached = (uint8_t*)p_malloc(file.size() + 1);
if (presetsCached) {
presetsCachedSize = file.size();
file.read(presetsCached, presetsCachedSize);
@@ -419,7 +419,7 @@ static const uint8_t *getPresetCache(size_t &size) {
#endif
bool handleFileRead(AsyncWebServerRequest* request, String path){
- DEBUG_PRINT(F("WS FileRead: ")); DEBUG_PRINTLN(path);
+ DEBUGFS_PRINT(F("WS FileRead: ")); DEBUGFS_PRINTLN(path);
if(path.endsWith("/")) path += "index.htm";
if(path.indexOf(F("sec")) > -1) return false;
#ifdef ARDUINO_ARCH_ESP32
diff --git a/wled00/image_loader.cpp b/wled00/image_loader.cpp
index 966505794..aa4ae2e16 100644
--- a/wled00/image_loader.cpp
+++ b/wled00/image_loader.cpp
@@ -78,7 +78,7 @@ void drawPixelCallback(int16_t x, int16_t y, uint8_t red, uint8_t green, uint8_t
byte renderImageToSegment(Segment &seg) {
if (!seg.name) return IMAGE_ERROR_NO_NAME;
// disable during effect transition, causes flickering, multiple allocations and depending on image, part of old FX remaining
- if (seg.mode != seg.currentMode()) return IMAGE_ERROR_WAITING;
+ //if (seg.mode != seg.currentMode()) return IMAGE_ERROR_WAITING;
if (activeSeg && activeSeg != &seg) return IMAGE_ERROR_SEG_LIMIT; // only one segment at a time
activeSeg = &seg;
diff --git a/wled00/ir.cpp b/wled00/ir.cpp
index 9f7950a2f..b2fec76f1 100644
--- a/wled00/ir.cpp
+++ b/wled00/ir.cpp
@@ -425,8 +425,8 @@ static void decodeIR44(uint32_t code)
case IR44_COLDWHITE2 : changeColor(COLOR_COLDWHITE2, 255); changeEffect(FX_MODE_STATIC); 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_GREENPLUS : changePalette(relativeChange(effectPalette, 1, 0, getPaletteCount() -1)); break;
+ case IR44_GREENMINUS : changePalette(relativeChange(effectPalette, -1, 0, getPaletteCount() -1)); break;
case IR44_BLUEPLUS : changeEffectIntensity( 16); break;
case IR44_BLUEMINUS : changeEffectIntensity(-16); break;
case IR44_QUICK : changeEffectSpeed( 16); break;
@@ -435,7 +435,7 @@ static void decodeIR44(uint32_t code)
case IR44_DIY2 : presetFallback(2, FX_MODE_BREATH, 0); break;
case IR44_DIY3 : presetFallback(3, FX_MODE_FIRE_FLICKER, 0); break;
case IR44_DIY4 : presetFallback(4, FX_MODE_RAINBOW, 0); break;
- case IR44_DIY5 : presetFallback(5, FX_MODE_METEOR, 0); break;
+ case IR44_DIY5 : presetFallback(5, FX_MODE_METEOR, 0); break;
case IR44_DIY6 : presetFallback(6, FX_MODE_RAIN, 0); break;
case IR44_AUTO : changeEffect(FX_MODE_STATIC); break;
case IR44_FLASH : changeEffect(FX_MODE_PALETTE); break;
@@ -484,7 +484,7 @@ static void decodeIR6(uint32_t code)
case IR6_CHANNEL_UP: incBrightness(); break;
case IR6_CHANNEL_DOWN: decBrightness(); 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));
+ case IR6_VOLUME_DOWN: changePalette(relativeChange(effectPalette, 1, 0, getPaletteCount() -1));
switch(lastIR6ColourIdx) {
case 0: changeColor(COLOR_RED); break;
case 1: changeColor(COLOR_REDDISH); break;
@@ -530,7 +530,7 @@ static void decodeIR9(uint32_t code)
/*
This allows users to customize IR actions without the need to edit C code and compile.
-From the https://github.com/wled-dev/WLED/wiki/Infrared-Control page, download the starter
+From the https://github.com/wled/WLED/wiki/Infrared-Control page, download the starter
ir.json file that corresponds to the number of buttons on your remote.
Many of the remotes with the same number of buttons emit the same codes, but will have
different labels or colors. Once you edit the ir.json file, upload it to your controller
diff --git a/wled00/json.cpp b/wled00/json.cpp
index c09b543f1..441468102 100644
--- a/wled00/json.cpp
+++ b/wled00/json.cpp
@@ -2,14 +2,74 @@
#include "palettes.h"
+#define JSON_PATH_STATE 1
+#define JSON_PATH_INFO 2
+#define JSON_PATH_STATE_INFO 3
+#define JSON_PATH_NODES 4
+#define JSON_PATH_PALETTES 5
+#define JSON_PATH_FXDATA 6
+#define JSON_PATH_NETWORKS 7
+#define JSON_PATH_EFFECTS 8
+
/*
* JSON API (De)serialization
*/
+namespace {
+ typedef struct {
+ uint32_t colors[NUM_COLORS];
+ uint16_t start;
+ uint16_t stop;
+ uint16_t offset;
+ uint16_t grouping;
+ uint16_t spacing;
+ uint16_t startY;
+ uint16_t stopY;
+ uint16_t options;
+ uint8_t mode;
+ uint8_t palette;
+ uint8_t opacity;
+ uint8_t speed;
+ uint8_t intensity;
+ uint8_t custom1;
+ uint8_t custom2;
+ uint8_t custom3;
+ bool check1;
+ bool check2;
+ bool check3;
+ } SegmentCopy;
-bool deserializeSegment(JsonObject elem, byte it, byte presetId)
+ uint8_t differs(const Segment& b, const SegmentCopy& a) {
+ uint8_t d = 0;
+ if (a.start != b.start) d |= SEG_DIFFERS_BOUNDS;
+ if (a.stop != b.stop) d |= SEG_DIFFERS_BOUNDS;
+ if (a.offset != b.offset) d |= SEG_DIFFERS_GSO;
+ if (a.grouping != b.grouping) d |= SEG_DIFFERS_GSO;
+ if (a.spacing != b.spacing) d |= SEG_DIFFERS_GSO;
+ if (a.opacity != b.opacity) d |= SEG_DIFFERS_BRI;
+ if (a.mode != b.mode) d |= SEG_DIFFERS_FX;
+ if (a.speed != b.speed) d |= SEG_DIFFERS_FX;
+ if (a.intensity != b.intensity) d |= SEG_DIFFERS_FX;
+ if (a.palette != b.palette) d |= SEG_DIFFERS_FX;
+ if (a.custom1 != b.custom1) d |= SEG_DIFFERS_FX;
+ if (a.custom2 != b.custom2) d |= SEG_DIFFERS_FX;
+ if (a.custom3 != b.custom3) d |= SEG_DIFFERS_FX;
+ if (a.startY != b.startY) d |= SEG_DIFFERS_BOUNDS;
+ if (a.stopY != b.stopY) d |= SEG_DIFFERS_BOUNDS;
+
+ //bit pattern: (msb first)
+ // set:2, sound:2, mapping:3, transposed, mirrorY, reverseY, [reset,] paused, mirrored, on, reverse, [selected]
+ if ((a.options & 0b1111111111011110U) != (b.options & 0b1111111111011110U)) d |= SEG_DIFFERS_OPT;
+ if ((a.options & 0x0001U) != (b.options & 0x0001U)) d |= SEG_DIFFERS_SEL;
+ for (unsigned i = 0; i < NUM_COLORS; i++) if (a.colors[i] != b.colors[i]) d |= SEG_DIFFERS_COL;
+
+ return d;
+ }
+}
+
+static bool deserializeSegment(JsonObject elem, byte it, byte presetId = 0)
{
byte id = elem["id"] | it;
- if (id >= strip.getMaxSegments()) return false;
+ if (id >= WS2812FX::getMaxSegments()) return false;
bool newSeg = false;
int stop = elem["stop"] | -1;
@@ -17,16 +77,37 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId)
// append segment
if (id >= strip.getSegmentsNum()) {
if (stop <= 0) return false; // ignore empty/inactive segments
- strip.appendSegment(Segment(0, strip.getLengthTotal()));
+ strip.appendSegment(0, strip.getLengthTotal());
id = strip.getSegmentsNum()-1; // segments are added at the end of list
newSeg = true;
}
//DEBUG_PRINTLN(F("-- JSON deserialize segment."));
Segment& seg = strip.getSegment(id);
- //DEBUG_PRINTF_P(PSTR("-- Original segment: %p (%p)\n"), &seg, seg.data);
- const Segment prev = seg; //make a backup so we can tell if something changed (calling copy constructor)
- //DEBUG_PRINTF_P(PSTR("-- Duplicate segment: %p (%p)\n"), &prev, prev.data);
+ // we do not want to make segment copy as it may use a lot of RAM (effect data and pixel buffer)
+ // so we will create a copy of segment options and compare it with original segment when done processing
+ SegmentCopy prev = {
+ {seg.colors[0], seg.colors[1], seg.colors[2]},
+ seg.start,
+ seg.stop,
+ seg.offset,
+ seg.grouping,
+ seg.spacing,
+ seg.startY,
+ seg.stopY,
+ seg.options,
+ seg.mode,
+ seg.palette,
+ seg.opacity,
+ seg.speed,
+ seg.intensity,
+ seg.custom1,
+ seg.custom2,
+ seg.custom3,
+ seg.check1,
+ seg.check2,
+ seg.check3
+ };
int start = elem["start"] | seg.start;
if (stop < 0) {
@@ -44,7 +125,7 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId)
elem.remove("rpt"); // remove for recursive call
elem.remove("n"); // remove for recursive call
unsigned len = stop - start;
- for (size_t i=id+1; i= strip.getLengthTotal()) break;
//TODO: add support for 2D
@@ -58,28 +139,11 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId)
if (elem["n"]) {
// name field exists
- if (seg.name) { //clear old name
- free(seg.name);
- seg.name = nullptr;
- }
-
const char * name = elem["n"].as();
- size_t len = 0;
- if (name != nullptr) len = strlen(name);
- if (len > 0) {
- if (len > WLED_MAX_SEGNAME_LEN) len = WLED_MAX_SEGNAME_LEN;
- seg.name = static_cast(malloc(len+1));
- if (seg.name) strlcpy(seg.name, name, WLED_MAX_SEGNAME_LEN+1);
- } else {
- // but is empty (already deleted above)
- elem.remove("n");
- }
+ seg.setName(name); // will resolve empty and null correctly
} else if (start != seg.start || stop != seg.stop) {
// clearing or setting segment without name field
- if (seg.name) {
- free(seg.name);
- seg.name = nullptr;
- }
+ seg.clearName();
}
uint16_t grp = elem["grp"] | seg.grouping;
@@ -97,6 +161,12 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId)
bool transpose = getBoolVal(elem[F("tp")], seg.transpose);
#endif
+ // if segment's virtual dimensions change we need to restart effect (segment blending and PS rely on dimensions)
+ if (seg.mirror != mirror) seg.markForReset();
+ #ifndef WLED_DISABLE_2D
+ if (seg.mirror_y != mirror_y || seg.transpose != transpose) seg.markForReset();
+ #endif
+
int len = (stop > start) ? stop - start : 1;
int offset = elem[F("of")] | INT32_MAX;
if (offset != INT32_MAX) {
@@ -118,8 +188,8 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId)
}
byte segbri = seg.opacity;
- if (getVal(elem["bri"], &segbri)) {
- if (segbri > 0) seg.setOpacity(segbri);
+ if (getVal(elem["bri"], segbri)) {
+ if (segbri > 0) seg.setOpacity(segbri); // use transition
seg.setOption(SEG_OPTION_ON, segbri); // use transition
}
@@ -175,13 +245,13 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId)
if (!colValid) continue;
- seg.setColor(i, RGBW32(rgbw[0],rgbw[1],rgbw[2],rgbw[3]));
+ seg.setColor(i, RGBW32(rgbw[0],rgbw[1],rgbw[2],rgbw[3])); // use transition
if (seg.mode == FX_MODE_STATIC) strip.trigger(); //instant refresh
}
} else {
// non RGB & non White segment (usually On/Off bus)
- seg.setColor(0, ULTRAWHITE);
- seg.setColor(1, BLACK);
+ seg.setColor(0, ULTRAWHITE); // use transition
+ seg.setColor(1, BLACK); // use transition
}
}
@@ -197,7 +267,6 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId)
}
#endif
- //seg.map1D2D = constrain(map1D2D, 0, 7); // done in setGeometry()
seg.set = constrain(set, 0, 3);
seg.soundSim = constrain(soundSim, 0, 3);
seg.selected = selected;
@@ -210,57 +279,58 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId)
#endif
byte fx = seg.mode;
- if (getVal(elem["fx"], &fx, 0, strip.getModeCount())) {
+ if (getVal(elem["fx"], fx, 0, strip.getModeCount())) {
if (!presetId && currentPlaylist>=0) unloadPlaylist();
- if (fx != seg.mode) seg.setMode(fx, elem[F("fxdef")]);
+ if (fx != seg.mode) seg.setMode(fx, elem[F("fxdef")]); // use transition (WARNING: may change map1D2D causing geometry change)
}
- getVal(elem["sx"], &seg.speed);
- getVal(elem["ix"], &seg.intensity);
+ getVal(elem["sx"], seg.speed);
+ getVal(elem["ix"], seg.intensity);
uint8_t pal = seg.palette;
if (seg.getLightCapabilities() & 1) { // ignore palette for White and On/Off segments
- if (getVal(elem["pal"], &pal, 0, strip.getPaletteCount())) seg.setPalette(pal);
+ if (getVal(elem["pal"], pal, 0, getPaletteCount())) seg.setPalette(pal);
}
- getVal(elem["c1"], &seg.custom1);
- getVal(elem["c2"], &seg.custom2);
+ getVal(elem["c1"], seg.custom1);
+ getVal(elem["c2"], seg.custom2);
uint8_t cust3 = seg.custom3;
- getVal(elem["c3"], &cust3, 0, 31); // we can't pass reference to bitfield
+ getVal(elem["c3"], cust3, 0, 31); // we can't pass reference to bitfield
seg.custom3 = constrain(cust3, 0, 31);
seg.check1 = getBoolVal(elem["o1"], seg.check1);
seg.check2 = getBoolVal(elem["o2"], seg.check2);
seg.check3 = getBoolVal(elem["o3"], seg.check3);
+ uint8_t blend = seg.blendMode;
+ getVal(elem["bm"], blend, 0, 15); // we can't pass reference to bitfield
+ seg.blendMode = constrain(blend, 0, 15);
+
JsonArray iarr = elem[F("i")]; //set individual LEDs
if (!iarr.isNull()) {
- uint8_t oldMap1D2D = seg.map1D2D;
- seg.map1D2D = M12_Pixels; // no mapping
-
// set brightness immediately and disable transition
jsonTransitionOnce = true;
- seg.stopTransition();
+ if (seg.isInTransition()) seg.startTransition(0); // setting transition time to 0 will stop transition in next frame
strip.setTransition(0);
strip.setBrightness(scaledBri(bri), true);
// freeze and init to black
if (!seg.freeze) {
seg.freeze = true;
- seg.fill(BLACK);
+ seg.clear();
}
- start = 0, stop = 0;
- set = 0; //0 nothing set, 1 start set, 2 range set
+ unsigned iStart = 0, iStop = 0;
+ unsigned iSet = 0; //0 nothing set, 1 start set, 2 range set
for (size_t i = 0; i < iarr.size(); i++) {
- if(iarr[i].is()) {
- if (!set) {
- start = abs(iarr[i].as());
- set++;
+ if (iarr[i].is()) {
+ if (!iSet) {
+ iStart = abs(iarr[i].as());
+ iSet++;
} else {
- stop = abs(iarr[i].as());
- set++;
+ iStop = abs(iarr[i].as());
+ iSet++;
}
} else { //color
uint8_t rgbw[] = {0,0,0,0};
@@ -276,17 +346,16 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId)
}
}
- if (set < 2 || stop <= start) stop = start + 1;
- uint32_t c = gamma32(RGBW32(rgbw[0], rgbw[1], rgbw[2], rgbw[3]));
- while (start < stop) seg.setPixelColor(start++, c);
- set = 0;
+ if (iSet < 2 || iStop <= iStart) iStop = iStart + 1;
+ uint32_t c = RGBW32(rgbw[0], rgbw[1], rgbw[2], rgbw[3]);
+ while (iStart < iStop) seg.setRawPixelColor(iStart++, c); // sets pixel color without 1D->2D expansion, grouping or spacing
+ iSet = 0;
}
}
- seg.map1D2D = oldMap1D2D; // restore mapping
strip.trigger(); // force segment update
}
// send UDP/WS if segment options changed (except selection; will also deselect current preset)
- if (seg.differs(prev) & 0x7F) stateChanged = true;
+ if (differs(seg, prev) & ~SEG_DIFFERS_SEL) stateChanged = true;
return true;
}
@@ -302,7 +371,8 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
#endif
bool onBefore = bri;
- getVal(root["bri"], &bri);
+ getVal(root["bri"], bri);
+ if (bri != briOld) stateChanged = true;
bool on = root["on"] | (bri > 0);
if (!on != !bri) toggleOnOff();
@@ -329,10 +399,8 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
}
}
-#ifndef WLED_DISABLE_MODE_BLEND
blendingStyle = root[F("bs")] | blendingStyle;
blendingStyle &= 0x1F;
-#endif
// temporary transition (applies only once)
tr = root[F("tt")] | -1;
@@ -345,6 +413,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
if (tr >= 0) strip.timebase = (unsigned long)tr - millis();
JsonObject nl = root["nl"];
+ if (!nl.isNull()) stateChanged = true;
nightlightActive = getBoolVal(nl["on"], nightlightActive);
nightlightDelayMins = nl["dur"] | nightlightDelayMins;
nightlightMode = nl["mode"] | nightlightMode;
@@ -371,6 +440,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
if (realtimeOverride > 2) realtimeOverride = REALTIME_OVERRIDE_ALWAYS;
if (realtimeMode && useMainSegmentOnly) {
strip.getMainSegment().freeze = !realtimeOverride;
+ realtimeOverride = REALTIME_OVERRIDE_NONE; // ignore request for override if using main segment only
}
if (root.containsKey("live")) {
@@ -388,18 +458,14 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
if (!segVar.isNull()) {
// we may be called during strip.service() so we must not modify segments while effects are executing
strip.suspend();
- const unsigned long start = millis();
- while (strip.isServicing() && millis() - start < strip.getFrameTime()) yield(); // wait until frame is over
- #ifdef WLED_DEBUG
- if (millis() - start > 0) DEBUG_PRINTLN(F("JSON: Waited for strip to finish servicing."));
- #endif
+ strip.waitForIt();
if (segVar.is()) {
int id = segVar["id"] | -1;
//if "seg" is not an array and ID not specified, apply to all selected/checked segments
if (id < 0) {
//apply all selected segments
for (size_t s = 0; s < strip.getSegmentsNum(); s++) {
- Segment &sg = strip.getSegment(s);
+ const Segment &sg = strip.getSegment(s);
if (sg.isActive() && sg.isSelected()) {
deserializeSegment(segVar, s, presetId);
}
@@ -449,7 +515,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
DEBUG_PRINTF_P(PSTR("Preset direct: %d\n"), currentPreset);
} else if (!root["ps"].isNull()) {
// we have "ps" call (i.e. from button or external API call) or "pd" that includes "ps" (i.e. from UI call)
- if (root["win"].isNull() && getVal(root["ps"], &presetCycCurr, 1, 250) && presetCycCurr > 0 && presetCycCurr < 251 && presetCycCurr != currentPreset) {
+ if (root["win"].isNull() && getVal(root["ps"], presetCycCurr, 1, 250) && presetCycCurr > 0 && presetCycCurr < 251 && presetCycCurr != currentPreset) {
DEBUG_PRINTF_P(PSTR("Preset select: %d\n"), presetCycCurr);
// b) preset ID only or preset that does not change state (use embedded cycling limits if they exist in getVal())
applyPreset(presetCycCurr, callMode); // async load from file system (only preset ID was specified)
@@ -465,11 +531,11 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
}
if (root.containsKey(F("rmcpal")) && root[F("rmcpal")].as()) {
- if (strip.customPalettes.size()) {
+ if (customPalettes.size()) {
char fileName[32];
- sprintf_P(fileName, PSTR("/palette%d.json"), strip.customPalettes.size()-1);
+ sprintf_P(fileName, PSTR("/palette%d.json"), customPalettes.size()-1);
if (WLED_FS.exists(fileName)) WLED_FS.remove(fileName);
- strip.loadCustomPalettes();
+ loadCustomPalettes();
}
}
@@ -488,13 +554,13 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
//if (restart) forceReconnect = true;
}
- stateUpdated(callMode);
+ if (stateChanged) stateUpdated(callMode);
if (presetToRestore) currentPreset = presetToRestore;
return stateResponse;
}
-void serializeSegment(const JsonObject& root, const Segment& seg, byte id, bool forPreset, bool segmentBounds)
+static void serializeSegment(JsonObject& root, const Segment& seg, byte id, bool forPreset, bool segmentBounds)
{
root["id"] = id;
if (segmentBounds) {
@@ -517,6 +583,7 @@ void serializeSegment(const JsonObject& root, const Segment& seg, byte id, bool
root["bri"] = (segbri) ? segbri : 255;
root["cct"] = seg.cct;
root[F("set")] = seg.set;
+ root["lc"] = seg.getLightCapabilities();
if (seg.name != nullptr) root["n"] = reinterpret_cast(seg.name); //not good practice, but decreases required JSON buffer
else if (forPreset) root["n"] = "";
@@ -561,6 +628,7 @@ void serializeSegment(const JsonObject& root, const Segment& seg, byte id, bool
root["o3"] = seg.check3;
root["si"] = seg.soundSim;
root["m12"] = seg.map1D2D;
+ root["bm"] = seg.blendMode;
}
void serializeState(JsonObject root, bool forPreset, bool includeBri, bool segmentBounds, bool selectedSegmentsOnly)
@@ -569,9 +637,7 @@ void serializeState(JsonObject root, bool forPreset, bool includeBri, bool segme
root["on"] = (bri > 0);
root["bri"] = briLast;
root[F("transition")] = transitionDelay/100; //in 100ms
-#ifndef WLED_DISABLE_MODE_BLEND
root[F("bs")] = blendingStyle;
-#endif
}
if (!forPreset) {
@@ -602,7 +668,7 @@ void serializeState(JsonObject root, bool forPreset, bool includeBri, bool segme
root[F("mainseg")] = strip.getMainSegmentId();
JsonArray seg = root.createNestedArray("seg");
- for (size_t s = 0; s < strip.getMaxSegments(); s++) {
+ for (size_t s = 0; s < WS2812FX::getMaxSegments(); s++) {
if (s >= strip.getSegmentsNum()) {
if (forPreset && segmentBounds && !selectedSegmentsOnly) { //disable segments not part of preset
JsonObject seg0 = seg.createNestedObject();
@@ -611,7 +677,7 @@ void serializeState(JsonObject root, bool forPreset, bool includeBri, bool segme
} else
break;
}
- Segment &sg = strip.getSegment(s);
+ const Segment &sg = strip.getSegment(s);
if (forPreset && selectedSegmentsOnly && !sg.isSelected()) continue;
if (sg.isActive()) {
JsonObject seg0 = seg.createNestedObject();
@@ -635,7 +701,7 @@ void serializeInfo(JsonObject root)
leds[F("pwr")] = BusManager::currentMilliamps();
leds["fps"] = strip.getFps();
leds[F("maxpwr")] = BusManager::currentMilliamps()>0 ? BusManager::ablMilliampsMax() : 0;
- leds[F("maxseg")] = strip.getMaxSegments();
+ leds[F("maxseg")] = WS2812FX::getMaxSegments();
//leds[F("actseg")] = strip.getActiveSegmentsNum();
//leds[F("seglock")] = false; //might be used in the future to prevent modifications to segment config
leds[F("bootps")] = bootPreset;
@@ -649,13 +715,13 @@ void serializeInfo(JsonObject root)
#endif
unsigned totalLC = 0;
- JsonArray lcarr = leds.createNestedArray(F("seglc"));
+ JsonArray lcarr = leds.createNestedArray(F("seglc")); // deprecated, use state.seg[].lc
size_t nSegs = strip.getSegmentsNum();
for (size_t s = 0; s < nSegs; s++) {
if (!strip.getSegment(s).isActive()) continue;
unsigned lc = strip.getSegment(s).getLightCapabilities();
totalLC |= lc;
- lcarr.add(lc);
+ lcarr.add(lc); // deprecated, use state.seg[].lc
}
leds["lc"] = totalLC;
@@ -703,8 +769,8 @@ void serializeInfo(JsonObject root)
#endif
root[F("fxcount")] = strip.getModeCount();
- root[F("palcount")] = strip.getPaletteCount();
- root[F("cpalcount")] = strip.customPalettes.size(); //number of custom palettes
+ root[F("palcount")] = getPaletteCount();
+ root[F("cpalcount")] = customPalettes.size(); //number of custom palettes
JsonArray ledmaps = root.createNestedArray(F("maps"));
for (size_t i=0; i maxPage) page = maxPage;
int start = itemPerPage * page;
int end = start + itemPerPage;
- if (end > palettesCount + customPalettes) end = palettesCount + customPalettes;
+ if (end > palettesCount + customPalettesCount) end = palettesCount + customPalettesCount;
root[F("m")] = maxPage; // inform caller how many pages there are
JsonObject palettes = root.createNestedObject("p");
@@ -911,7 +977,7 @@ void serializePalettes(JsonObject root, int page)
break;
default:
if (i >= palettesCount)
- setPaletteColors(curPalette, strip.customPalettes[i - palettesCount]);
+ setPaletteColors(curPalette, customPalettes[i - palettesCount]);
else if (i < 13) // palette 6 - 12, fastled palettes
setPaletteColors(curPalette, *fastledPalettes[i-6]);
else {
diff --git a/wled00/led.cpp b/wled00/led.cpp
index 2d2f5b6f2..43771f9d5 100644
--- a/wled00/led.cpp
+++ b/wled00/led.cpp
@@ -4,11 +4,9 @@
* LED methods
*/
-void setValuesFromMainSeg() { setValuesFromSegment(strip.getMainSegmentId()); }
-void setValuesFromFirstSelectedSeg() { setValuesFromSegment(strip.getFirstSelectedSegId()); }
-void setValuesFromSegment(uint8_t s)
-{
- Segment& seg = strip.getSegment(s);
+ // applies chosen setment properties to legacy values
+void setValuesFromSegment(uint8_t s) {
+ const Segment& seg = strip.getSegment(s);
colPri[0] = R(seg.colors[0]);
colPri[1] = G(seg.colors[0]);
colPri[2] = B(seg.colors[0]);
@@ -24,25 +22,19 @@ void setValuesFromSegment(uint8_t s)
}
-// applies global legacy values (col, colSec, effectCurrent...)
-// problem: if the first selected segment already has the value to be set, other selected segments are not updated
-void applyValuesToSelectedSegs()
-{
- // copy of first selected segment to tell if value was updated
- unsigned firstSel = strip.getFirstSelectedSegId();
- Segment selsegPrev = strip.getSegment(firstSel);
+// applies global legacy values (colPri, colSec, effectCurrent...) to each selected segment
+void applyValuesToSelectedSegs() {
for (unsigned 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;}
- if (effectIntensity != selsegPrev.intensity) {seg.intensity = effectIntensity; stateChanged = true;}
- if (effectPalette != selsegPrev.palette) {seg.setPalette(effectPalette);}
- if (effectCurrent != selsegPrev.mode) {seg.setMode(effectCurrent);}
+ if (!(seg.isActive() && seg.isSelected())) continue;
+ if (effectSpeed != seg.speed) {seg.speed = effectSpeed; stateChanged = true;}
+ if (effectIntensity != seg.intensity) {seg.intensity = effectIntensity; stateChanged = true;}
+ if (effectPalette != seg.palette) {seg.setPalette(effectPalette);}
+ if (effectCurrent != seg.mode) {seg.setMode(effectCurrent);}
uint32_t col0 = RGBW32(colPri[0], colPri[1], colPri[2], colPri[3]);
uint32_t col1 = RGBW32(colSec[0], colSec[1], colSec[2], colSec[3]);
- if (col0 != selsegPrev.colors[0]) {seg.setColor(0, col0);}
- if (col1 != selsegPrev.colors[1]) {seg.setColor(1, col1);}
+ if (col0 != seg.colors[0]) {seg.setColor(0, col0);}
+ if (col1 != seg.colors[1]) {seg.setColor(1, col1);}
}
}
@@ -73,7 +65,8 @@ byte scaledBri(byte in)
//applies global temporary brightness (briT) to strip
void applyBri() {
- if (!(realtimeMode && arlsForceMaxBri)) {
+ if (realtimeOverride || !(realtimeMode && arlsForceMaxBri))
+ {
//DEBUG_PRINTF_P(PSTR("Applying strip brightness: %d (%d,%d)\n"), (int)briT, (int)bri, (int)briOld);
strip.setBrightness(scaledBri(briT));
}
@@ -94,7 +87,7 @@ void applyFinalBri() {
void stateUpdated(byte callMode) {
//call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification)
// 6: fx changed 7: hue 8: preset cycle 9: blynk 10: alexa 11: ws send only 12: button preset
- setValuesFromFirstSelectedSeg();
+ setValuesFromFirstSelectedSeg(); // a much better approach would be to use main segment: setValuesFromMainSeg()
if (bri != briOld || stateChanged) {
if (stateChanged) currentPreset = 0; //something changed, so we are no longer in the preset
@@ -104,7 +97,6 @@ void stateUpdated(byte callMode) {
//set flag to update ws and mqtt
interfaceUpdateCallMode = callMode;
- stateChanged = false;
} else {
if (nightlightActive && !nightlightActiveOld && callMode != CALL_MODE_NOTIFICATION && callMode != CALL_MODE_NO_NOTIFY) {
notify(CALL_MODE_NIGHTLIGHT);
@@ -134,15 +126,16 @@ void stateUpdated(byte callMode) {
jsonTransitionOnce = false;
transitionActive = false;
applyFinalBri();
- return;
+ strip.trigger();
+ } else {
+ if (transitionActive) {
+ briOld = briT;
+ } else if (bri != briOld || stateChanged)
+ strip.setTransitionMode(true); // force all segments to transition mode
+ transitionActive = true;
+ transitionStartTime = now;
}
-
- if (transitionActive) {
- briOld = briT;
- } else
- strip.setTransitionMode(true); // force all segments to transition mode
- transitionActive = true;
- transitionStartTime = now;
+ stateChanged = false;
}
diff --git a/wled00/mqtt.cpp b/wled00/mqtt.cpp
index a462881ec..62f296104 100644
--- a/wled00/mqtt.cpp
+++ b/wled00/mqtt.cpp
@@ -27,7 +27,7 @@ static void parseMQTTBriPayload(char* payload)
static void onMqttConnect(bool sessionPresent)
{
//(re)subscribe to required topics
- char subuf[MQTT_MAX_TOPIC_LEN + 6];
+ char subuf[MQTT_MAX_TOPIC_LEN + 9];
if (mqttDeviceTopic[0] != 0) {
strlcpy(subuf, mqttDeviceTopic, MQTT_MAX_TOPIC_LEN + 1);
@@ -52,6 +52,13 @@ static void onMqttConnect(bool sessionPresent)
UsermodManager::onMqttConnect(sessionPresent);
DEBUG_PRINTLN(F("MQTT ready"));
+
+#ifndef USERMOD_SMARTNEST
+ strlcpy(subuf, mqttDeviceTopic, MQTT_MAX_TOPIC_LEN + 1);
+ strcat_P(subuf, PSTR("/status"));
+ mqtt->publish(subuf, 0, true, "online"); // retain message for a LWT
+#endif
+
publishMqtt();
}
@@ -68,8 +75,8 @@ static void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProp
}
if (index == 0) { // start (1st partial packet or the only packet)
- if (payloadStr) free(payloadStr); // fail-safe: release buffer
- payloadStr = static_cast(malloc(total+1)); // allocate new buffer
+ p_free(payloadStr); // release buffer if it exists
+ payloadStr = static_cast(p_malloc(total+1)); // allocate new buffer
}
if (payloadStr == nullptr) return; // buffer not allocated
@@ -94,7 +101,7 @@ static void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProp
} else {
// Non-Wled Topic used here. Probably a usermod subscribed to this topic.
UsermodManager::onMqttMessage(topic, payloadStr);
- free(payloadStr);
+ p_free(payloadStr);
payloadStr = nullptr;
return;
}
@@ -124,7 +131,7 @@ static void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProp
// topmost topic (just wled/MAC)
parseMQTTBriPayload(payloadStr);
}
- free(payloadStr);
+ p_free(payloadStr);
payloadStr = nullptr;
}
@@ -174,10 +181,6 @@ void publishMqtt()
strcat_P(subuf, PSTR("/c"));
mqtt->publish(subuf, 0, retainMqttMsg, s); // optionally retain message (#2263)
- strlcpy(subuf, mqttDeviceTopic, MQTT_MAX_TOPIC_LEN + 1);
- strcat_P(subuf, PSTR("/status"));
- mqtt->publish(subuf, 0, true, "online"); // retain message for a LWT
-
// TODO: use a DynamicBufferList. Requires a list-read-capable MQTT client API.
DynamicBuffer buf(1024);
bufferPrint pbuf(buf.data(), buf.size());
@@ -196,7 +199,8 @@ bool initMqtt()
if (!mqttEnabled || mqttServer[0] == 0 || !WLED_CONNECTED) return false;
if (mqtt == nullptr) {
- mqtt = new AsyncMqttClient();
+ void *ptr = p_malloc(sizeof(AsyncMqttClient));
+ mqtt = new (ptr) AsyncMqttClient(); // use placement new (into PSRAM), client will never be deleted
if (!mqtt) return false;
mqtt->onMessage(onMqttMessage);
mqtt->onConnect(onMqttConnect);
diff --git a/wled00/overlay.cpp b/wled00/overlay.cpp
index fcd0a40c2..3f6e63121 100644
--- a/wled00/overlay.cpp
+++ b/wled00/overlay.cpp
@@ -90,9 +90,8 @@ void _overlayAnalogCountdown()
void handleOverlayDraw() {
UsermodManager::handleOverlayDraw();
if (analogClockSolidBlack) {
- const Segment* segments = strip.getSegments();
for (unsigned i = 0; i < strip.getSegmentsNum(); i++) {
- const Segment& segment = segments[i];
+ const Segment& segment = strip.getSegment(i);
if (!segment.isActive()) continue;
if (segment.mode > 0 || segment.colors[0] > 0) {
return;
diff --git a/wled00/palettes.h b/wled00/palettes.h
old mode 100644
new mode 100755
index c84c1fb97..a77540fd1
--- a/wled00/palettes.h
+++ b/wled00/palettes.h
@@ -1,500 +1,374 @@
-/*
- * Color palettes for FastLED effects (65-73).
- * 4 bytes per color: index, red, green, blue
- */
-
-// From ColorWavesWithPalettes by Mark Kriegsman: https://gist.github.com/kriegsman/8281905786e8b2632aeb
-// Unfortunately, these are stored in RAM!
-
-// Gradient palette "ib_jul01_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/ing/xmas/tn/ib_jul01.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 16 bytes of program space.
-
#ifndef PalettesWLED_h
#define PalettesWLED_h
-const byte ib_jul01_gp[] PROGMEM = {
- 0, 194, 1, 1,
- 94, 1, 29, 18,
- 132, 57,131, 28,
- 255, 113, 1, 1};
+/*
+ * WLED Color palettes
+ *
+ * Note: palettes imported from http://seaviewsensing.com/pub/cpt-city are gamma corrected using gammas (1.182, 1.0, 1.136)
+ * this is done to match colors of the palettes after applying the (default) global gamma of 2.2 to versions
+ * prior to WLED 0.16 which used pre-applied gammas of (2.6,2.2,2.5) for these palettes.
+ * Palettes from FastLED are intended to be used without gamma correction, an inverse gamma of 2.2 is applied to original colors
+ */
+
+// Gradient palette "ib_jul01_gp", originally from
+// http://seaviewsensing.com/pub/cpt-city/ing/xmas/ib_jul01.c3g
+const uint8_t ib_jul01_gp[] PROGMEM = {
+ 0, 226, 6, 12,
+ 94, 26, 96, 78,
+ 132, 130, 189, 94,
+ 255, 177, 3, 9};
// Gradient palette "es_vintage_57_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/vintage/tn/es_vintage_57.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 20 bytes of program space.
-
-const byte es_vintage_57_gp[] PROGMEM = {
- 0, 2, 1, 1,
- 53, 18, 1, 0,
- 104, 69, 29, 1,
- 153, 167,135, 10,
- 255, 46, 56, 4};
-
+// http://seaviewsensing.com/pub/cpt-city/es/vintage/es_vintage_57.c3g
+const uint8_t es_vintage_57_gp[] PROGMEM = {
+ 0, 29, 8, 3,
+ 53, 76, 1, 0,
+ 104, 142, 96, 28,
+ 153, 211, 191, 61,
+ 255, 117, 129, 42};
// Gradient palette "es_vintage_01_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/vintage/tn/es_vintage_01.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 32 bytes of program space.
-
-const byte es_vintage_01_gp[] PROGMEM = {
- 0, 4, 1, 1,
- 51, 16, 0, 1,
- 76, 97,104, 3,
- 101, 255,131, 19,
- 127, 67, 9, 4,
- 153, 16, 0, 1,
- 229, 4, 1, 1,
- 255, 4, 1, 1};
-
+// http://seaviewsensing.com/pub/cpt-city/es/vintage/es_vintage_01.c3g
+const uint8_t es_vintage_01_gp[] PROGMEM = {
+ 0, 41, 18, 24,
+ 51, 73, 0, 22,
+ 76, 165, 170, 38,
+ 101, 255, 189, 80,
+ 127, 139, 56, 40,
+ 153, 73, 0, 22,
+ 229, 41, 18, 24,
+ 255, 41, 18, 24};
// Gradient palette "es_rivendell_15_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/rivendell/tn/es_rivendell_15.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 20 bytes of program space.
-
-const byte es_rivendell_15_gp[] PROGMEM = {
- 0, 1, 14, 5,
- 101, 16, 36, 14,
- 165, 56, 68, 30,
- 242, 150,156, 99,
- 255, 150,156, 99};
-
+// http://seaviewsensing.com/pub/cpt-city/es/rivendell/es_rivendell_15.c3g
+const uint8_t es_rivendell_15_gp[] PROGMEM = {
+ 0, 24, 69, 44,
+ 101, 73, 105, 70,
+ 165, 129, 140, 97,
+ 242, 200, 204, 166,
+ 255, 200, 204, 166};
// Gradient palette "rgi_15_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/ds/rgi/tn/rgi_15.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 36 bytes of program space.
-// Edited to be brighter
-
-const byte rgi_15_gp[] PROGMEM = {
- 0, 4, 1, 70,
- 31, 55, 1, 30,
- 63, 255, 4, 7,
- 95, 59, 2, 29,
- 127, 11, 3, 50,
- 159, 39, 8, 60,
- 191, 112, 19, 40,
- 223, 78, 11, 39,
- 255, 29, 8, 59};
-
+// http://seaviewsensing.com/pub/cpt-city/ds/rgi/rgi_15.c3g
+const uint8_t rgi_15_gp[] PROGMEM = {
+ 0, 41, 14, 99,
+ 31, 128, 24, 74,
+ 63, 227, 34, 50,
+ 95, 132, 31, 76,
+ 127, 47, 29, 102,
+ 159, 109, 47, 101,
+ 191, 176, 66, 100,
+ 223, 129, 57, 104,
+ 255, 84, 48, 108};
// Gradient palette "retro2_16_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/ma/retro2/tn/retro2_16.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 8 bytes of program space.
-
-const byte retro2_16_gp[] PROGMEM = {
- 0, 188,135, 1,
- 255, 46, 7, 1};
-
+// http://seaviewsensing.com/pub/cpt-city/ma/retro2/retro2_16.c3g
+const uint8_t retro2_16_gp[] PROGMEM = {
+ 0, 222, 191, 8,
+ 255, 117, 52, 1};
// Gradient palette "Analogous_1_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/red/tn/Analogous_1.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 20 bytes of program space.
-
-const byte Analogous_1_gp[] PROGMEM = {
- 0, 3, 0,255,
- 63, 23, 0,255,
- 127, 67, 0,255,
- 191, 142, 0, 45,
- 255, 255, 0, 0};
-
+// http://seaviewsensing.com/pub/cpt-city/nd/red/Analogous_1.c3g
+const uint8_t Analogous_1_gp[] PROGMEM = {
+ 0, 38, 0, 255,
+ 63, 86, 0, 255,
+ 127, 139, 0, 255,
+ 191, 196, 0, 117,
+ 255, 255, 0, 0};
// Gradient palette "es_pinksplash_08_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/pink_splash/tn/es_pinksplash_08.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 20 bytes of program space.
-
-const byte es_pinksplash_08_gp[] PROGMEM = {
- 0, 126, 11,255,
- 127, 197, 1, 22,
- 175, 210,157,172,
- 221, 157, 3,112,
- 255, 157, 3,112};
-
+// http://seaviewsensing.com/pub/cpt-city/es/pink_splash/es_pinksplash_08.c3g
+const uint8_t es_pinksplash_08_gp[] PROGMEM = {
+ 0, 186, 63, 255,
+ 127, 227, 9, 85,
+ 175, 234, 205, 213,
+ 221, 205, 38, 176,
+ 255, 205, 38, 176,
+};
// Gradient palette "es_ocean_breeze_036_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/ocean_breeze/tn/es_ocean_breeze_036.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 16 bytes of program space.
-
-const byte es_ocean_breeze_036_gp[] PROGMEM = {
- 0, 1, 6, 7,
- 89, 1, 99,111,
- 153, 144,209,255,
- 255, 0, 73, 82};
-
+// http://seaviewsensing.com/pub/cpt-city/es/ocean_breeze/es_ocean_breeze_036.c3g
+const uint8_t es_ocean_breeze_036_gp[] PROGMEM = {
+ 0, 16, 48, 51,
+ 89, 27, 166, 175,
+ 153, 197, 233, 255,
+ 255, 0, 145, 152};
// Gradient palette "departure_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/mjf/tn/departure.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 88 bytes of program space.
-
-const byte departure_gp[] PROGMEM = {
- 0, 8, 3, 0,
- 42, 23, 7, 0,
- 63, 75, 38, 6,
- 84, 169, 99, 38,
- 106, 213,169,119,
- 116, 255,255,255,
- 138, 135,255,138,
- 148, 22,255, 24,
- 170, 0,255, 0,
- 191, 0,136, 0,
- 212, 0, 55, 0,
- 255, 0, 55, 0};
-
+// http://seaviewsensing.com/pub/cpt-city/mjf/departure.c3g
+const uint8_t departure_gp[] PROGMEM = {
+ 0, 53, 34, 0,
+ 42, 86, 51, 0,
+ 63, 147, 108, 49,
+ 84, 212, 166, 108,
+ 106, 235, 212, 180,
+ 116, 255, 255, 255,
+ 138, 191, 255, 193,
+ 148, 84, 255, 88,
+ 170, 0, 255, 0,
+ 191, 0, 192, 0,
+ 212, 0, 128, 0,
+ 255, 0, 128, 0};
// Gradient palette "es_landscape_64_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/landscape/tn/es_landscape_64.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 36 bytes of program space.
-
-const byte es_landscape_64_gp[] PROGMEM = {
- 0, 0, 0, 0,
- 37, 2, 25, 1,
- 76, 15,115, 5,
- 127, 79,213, 1,
- 128, 126,211, 47,
- 130, 188,209,247,
- 153, 144,182,205,
- 204, 59,117,250,
- 255, 1, 37,192};
-
+// http://seaviewsensing.com/pub/cpt-city/es/landscape/es_landscape_64.c3g
+const uint8_t es_landscape_64_gp[] PROGMEM = {
+ 0, 0, 0, 0,
+ 37, 31, 89, 19,
+ 76, 72, 178, 43,
+ 127, 150, 235, 5,
+ 128, 186, 234, 119,
+ 130, 222, 233, 252,
+ 153, 197, 219, 231,
+ 204, 132, 179, 253,
+ 255, 28, 107, 225};
// Gradient palette "es_landscape_33_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/landscape/tn/es_landscape_33.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 24 bytes of program space.
-
-const byte es_landscape_33_gp[] PROGMEM = {
- 0, 1, 5, 0,
- 19, 32, 23, 1,
- 38, 161, 55, 1,
- 63, 229,144, 1,
- 66, 39,142, 74,
- 255, 1, 4, 1};
-
+// http://seaviewsensing.com/pub/cpt-city/es/landscape/es_landscape_33.c3g
+const uint8_t es_landscape_33_gp[] PROGMEM = {
+ 0, 12, 45, 0,
+ 19, 101, 86, 2,
+ 38, 207, 128, 4,
+ 63, 243, 197, 18,
+ 66, 109, 196, 146,
+ 255, 5, 39, 7};
// Gradient palette "rainbowsherbet_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/ma/icecream/tn/rainbowsherbet.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 28 bytes of program space.
-
-const byte rainbowsherbet_gp[] PROGMEM = {
- 0, 255, 33, 4,
- 43, 255, 68, 25,
- 86, 255, 7, 25,
- 127, 255, 82,103,
- 170, 255,255,242,
- 209, 42,255, 22,
- 255, 87,255, 65};
-
+// http://seaviewsensing.com/pub/cpt-city/ma/icecream/rainbowsherbet.c3g
+const uint8_t rainbowsherbet_gp[] PROGMEM = {
+ 0, 255, 102, 41,
+ 43, 255, 140, 90,
+ 86, 255, 51, 90,
+ 127, 255, 153, 169,
+ 170, 255, 255, 249,
+ 209, 113, 255, 85,
+ 255, 157, 255, 137};
// Gradient palette "gr65_hult_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/hult/tn/gr65_hult.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 24 bytes of program space.
-
-const byte gr65_hult_gp[] PROGMEM = {
- 0, 247,176,247,
- 48, 255,136,255,
- 89, 220, 29,226,
- 160, 7, 82,178,
- 216, 1,124,109,
- 255, 1,124,109};
-
+// http://seaviewsensing.com/pub/cpt-city/hult/gr65_hult.c3g
+const uint8_t gr65_hult_gp[] PROGMEM = {
+ 0, 251, 216, 252,
+ 48, 255, 192, 255,
+ 89, 239, 95, 241,
+ 160, 51, 153, 217,
+ 216, 24, 184, 174,
+ 255, 24, 184, 174};
// Gradient palette "gr64_hult_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/hult/tn/gr64_hult.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 32 bytes of program space.
-
-const byte gr64_hult_gp[] PROGMEM = {
- 0, 1,124,109,
- 66, 1, 93, 79,
- 104, 52, 65, 1,
- 130, 115,127, 1,
- 150, 52, 65, 1,
- 201, 1, 86, 72,
- 239, 0, 55, 45,
- 255, 0, 55, 45};
-
+// http://seaviewsensing.com/pub/cpt-city/hult/gr64_hult.c3g
+const uint8_t gr64_hult_gp[] PROGMEM = {
+ 0, 24, 184, 174,
+ 66, 8, 162, 150,
+ 104, 124, 137, 7,
+ 130, 178, 186, 22,
+ 150, 124, 137, 7,
+ 201, 6, 156, 144,
+ 239, 0, 128, 117,
+ 255, 0, 128, 117};
// Gradient palette "GMT_drywet_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/gmt/tn/GMT_drywet.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 28 bytes of program space.
-
-const byte GMT_drywet_gp[] PROGMEM = {
- 0, 47, 30, 2,
- 42, 213,147, 24,
- 84, 103,219, 52,
- 127, 3,219,207,
- 170, 1, 48,214,
- 212, 1, 1,111,
- 255, 1, 7, 33};
-
+// http://seaviewsensing.com/pub/cpt-city/gmt/GMT_drywet.c3g
+const uint8_t GMT_drywet_gp[] PROGMEM = {
+ 0, 119, 97, 33,
+ 42, 235, 199, 88,
+ 84, 169, 238, 124,
+ 127, 37, 238, 232,
+ 170, 7, 120, 236,
+ 212, 27, 1, 175,
+ 255, 4, 51, 101};
// Gradient palette "ib15_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/ing/general/tn/ib15.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 24 bytes of program space.
-
-const byte ib15_gp[] PROGMEM = {
- 0, 113, 91,147,
- 72, 157, 88, 78,
- 89, 208, 85, 33,
- 107, 255, 29, 11,
- 141, 137, 31, 39,
- 255, 59, 33, 89};
-
+// http://seaviewsensing.com/pub/cpt-city/ing/general/ib15.c3g
+const uint8_t ib15_gp[] PROGMEM = {
+ 0, 177, 160, 199,
+ 72, 205, 158, 149,
+ 89, 233, 155, 101,
+ 107, 255, 95, 63,
+ 141, 192, 98, 109,
+ 255, 132, 101, 159};
// Gradient palette "Tertiary_01_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/vermillion/tn/Tertiary_01.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 20 bytes of program space.
-
-const byte Tertiary_01_gp[] PROGMEM = {
- 0, 0, 1,255,
- 63, 3, 68, 45,
- 127, 23,255, 0,
- 191, 100, 68, 1,
- 255, 255, 1, 4};
-
+// http://seaviewsensing.com/pub/cpt-city/nd/vermillion/Tertiary_01.c3g
+const uint8_t Tertiary_01_gp[] PROGMEM = {
+ 0, 0, 25, 255,
+ 63, 38, 140, 117,
+ 127, 86, 255, 0,
+ 191, 167, 140, 19,
+ 255, 255, 25, 41};
// Gradient palette "lava_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/neota/elem/tn/lava.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 52 bytes of program space.
-
-const byte lava_gp[] PROGMEM = {
- 0, 0, 0, 0,
- 46, 18, 0, 0,
- 96, 113, 0, 0,
- 108, 142, 3, 1,
- 119, 175, 17, 1,
- 146, 213, 44, 2,
- 174, 255, 82, 4,
- 188, 255,115, 4,
- 202, 255,156, 4,
- 218, 255,203, 4,
- 234, 255,255, 4,
- 244, 255,255, 71,
- 255, 255,255,255};
-
-
-// Gradient palette "fierce_ice_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/neota/elem/tn/fierce-ice.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 28 bytes of program space.
-
-const byte fierce_ice_gp[] PROGMEM = {
- 0, 0, 0, 0,
- 59, 0, 9, 45,
- 119, 0, 38,255,
- 149, 3,100,255,
- 180, 23,199,255,
- 217, 100,235,255,
- 255, 255,255,255};
+// http://seaviewsensing.com/pub/cpt-city/neota/elem/lava.c3g
+const uint8_t lava_gp[] PROGMEM = {
+ 0, 0, 0, 0,
+ 46, 77, 0, 0,
+ 96, 177, 0, 0,
+ 108, 196, 38, 9,
+ 119, 215, 76, 19,
+ 146, 235, 115, 29,
+ 174, 255, 153, 41,
+ 188, 255, 178, 41,
+ 202, 255, 204, 41,
+ 218, 255, 230, 41,
+ 234, 255, 255, 41,
+ 244, 255, 255, 143,
+ 255, 255, 255, 255};
+// Gradient palette "fierce-ice_gp", originally from
+// http://seaviewsensing.com/pub/cpt-city/neota/elem/fierce-ice.c3g
+const uint8_t fierce_ice_gp[] PROGMEM = {
+ 0, 0, 0, 0,
+ 59, 0, 51, 117,
+ 119, 0, 102, 255,
+ 149, 38, 153, 255,
+ 180, 86, 204, 255,
+ 217, 167, 230, 255,
+ 255, 255, 255, 255};
// Gradient palette "Colorfull_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/atmospheric/tn/Colorfull.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 44 bytes of program space.
-
-const byte Colorfull_gp[] PROGMEM = {
- 0, 10, 85, 5,
- 25, 29,109, 18,
- 60, 59,138, 42,
- 93, 83, 99, 52,
- 106, 110, 66, 64,
- 109, 123, 49, 65,
- 113, 139, 35, 66,
- 116, 192,117, 98,
- 124, 255,255,137,
- 168, 100,180,155,
- 255, 22,121,174};
-
+// http://seaviewsensing.com/pub/cpt-city/nd/atmospheric/Colorfull.c3g
+const uint8_t Colorfull_gp[] PROGMEM = {
+ 0, 61, 155, 44,
+ 25, 95, 174, 77,
+ 60, 132, 193, 113,
+ 93, 154, 166, 125,
+ 106, 175, 138, 136,
+ 109, 183, 121, 137,
+ 113, 194, 104, 138,
+ 116, 225, 179, 165,
+ 124, 255, 255, 192,
+ 168, 167, 218, 203,
+ 255, 84, 182, 215};
// Gradient palette "Pink_Purple_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/atmospheric/tn/Pink_Purple.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 44 bytes of program space.
-
-const byte Pink_Purple_gp[] PROGMEM = {
- 0, 19, 2, 39,
- 25, 26, 4, 45,
- 51, 33, 6, 52,
- 76, 68, 62,125,
- 102, 118,187,240,
- 109, 163,215,247,
- 114, 217,244,255,
- 122, 159,149,221,
- 149, 113, 78,188,
- 183, 128, 57,155,
- 255, 146, 40,123};
-
+// http://seaviewsensing.com/pub/cpt-city/nd/atmospheric/Pink_Purple.c3g
+const uint8_t Pink_Purple_gp[] PROGMEM = {
+ 0, 79, 32, 109,
+ 25, 90, 40, 117,
+ 51, 102, 48, 124,
+ 76, 141, 135, 185,
+ 102, 180, 222, 248,
+ 109, 208, 236, 252,
+ 114, 237, 250, 255,
+ 122, 206, 200, 239,
+ 149, 177, 149, 222,
+ 183, 187, 130, 203,
+ 255, 198, 111, 184};
// Gradient palette "Sunset_Real_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/atmospheric/tn/Sunset_Real.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 28 bytes of program space.
-
-const byte Sunset_Real_gp[] PROGMEM = {
- 0, 120, 0, 0,
- 22, 179, 22, 0,
- 51, 255,104, 0,
- 85, 167, 22, 18,
- 135, 100, 0,103,
- 198, 16, 0,130,
- 255, 0, 0,160};
-
+// http://seaviewsensing.com/pub/cpt-city/nd/atmospheric/Sunset_Real.c3g
+const uint8_t Sunset_Real_gp[] PROGMEM = {
+ 0, 181, 0, 0,
+ 22, 218, 85, 0,
+ 51, 255, 170, 0,
+ 85, 211, 85, 77,
+ 135, 167, 0, 169,
+ 198, 73, 0, 188,
+ 255, 0, 0, 207};
// Gradient palette "Sunset_Yellow_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/atmospheric/tn/Sunset_Yellow.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 44 bytes of program space.
-
-const byte Sunset_Yellow_gp[] PROGMEM = {
- 0, 10, 62,123,
- 36, 56,130,103,
- 87, 153,225, 85,
- 100, 199,217, 68,
- 107, 255,207, 54,
- 115, 247,152, 57,
- 120, 239,107, 61,
- 128, 247,152, 57,
- 180, 255,207, 54,
- 223, 255,227, 48,
- 255, 255,248, 42};
-
+// http://seaviewsensing.com/pub/cpt-city/nd/atmospheric/Sunset_Yellow.c3g
+const uint8_t Sunset_Yellow_gp[] PROGMEM = {
+ 0, 61, 135, 184,
+ 36, 129, 188, 169,
+ 87, 203, 241, 155,
+ 100, 228, 237, 141,
+ 107, 255, 232, 127,
+ 115, 251, 202, 130,
+ 120, 248, 172, 133,
+ 128, 251, 202, 130,
+ 180, 255, 232, 127,
+ 223, 255, 242, 120,
+ 255, 255, 252, 113};
// Gradient palette "Beech_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/atmospheric/tn/Beech.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 60 bytes of program space.
-
-const byte Beech_gp[] PROGMEM = {
- 0, 255,252,214,
- 12, 255,252,214,
- 22, 255,252,214,
- 26, 190,191,115,
- 28, 137,141, 52,
- 28, 112,255,205,
- 50, 51,246,214,
- 71, 17,235,226,
- 93, 2,193,199,
- 120, 0,156,174,
- 133, 1,101,115,
- 136, 1, 59, 71,
- 136, 7,131,170,
- 208, 1, 90,151,
- 255, 0, 56,133};
-
+// http://seaviewsensing.com/pub/cpt-city/nd/atmospheric/Beech.c3g
+const uint8_t Beech_gp[] PROGMEM = {
+ 0, 255, 254, 236,
+ 12, 255, 254, 236,
+ 22, 255, 254, 236,
+ 26, 223, 224, 178,
+ 28, 192, 195, 124,
+ 28, 176, 255, 231,
+ 50, 123, 251, 236,
+ 71, 74, 246, 241,
+ 93, 33, 225, 228,
+ 120, 0, 204, 215,
+ 133, 4, 168, 178,
+ 136, 10, 132, 143,
+ 136, 51, 189, 212,
+ 208, 23, 159, 201,
+ 255, 0, 129, 190};
// Gradient palette "Another_Sunset_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/atmospheric/tn/Another_Sunset.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 32 bytes of program space.
-
-const byte Another_Sunset_gp[] PROGMEM = {
- 0, 110, 49, 11,
- 29, 55, 34, 10,
- 68, 22, 22, 9,
- 68, 239,124, 8,
- 97, 220,156, 27,
- 124, 203,193, 61,
- 178, 33, 53, 56,
- 255, 0, 1, 52};
-
-
-
-
+// http://seaviewsensing.com/pub/cpt-city/nd/atmospheric/Another_Sunset.c3g
+const uint8_t Another_Sunset_gp[] PROGMEM = {
+ 0, 175, 121, 62,
+ 29, 128, 103, 60,
+ 68, 84, 84, 58,
+ 68, 248, 184, 55,
+ 97, 239, 204, 93,
+ 124, 230, 225, 133,
+ 178, 102, 125, 129,
+ 255, 0, 26, 125};
// Gradient palette "es_autumn_19_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/autumn/tn/es_autumn_19.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 52 bytes of program space.
-
-const byte es_autumn_19_gp[] PROGMEM = {
- 0, 26, 1, 1,
- 51, 67, 4, 1,
- 84, 118, 14, 1,
- 104, 137,152, 52,
- 112, 113, 65, 1,
- 122, 133,149, 59,
- 124, 137,152, 52,
- 135, 113, 65, 1,
- 142, 139,154, 46,
- 163, 113, 13, 1,
- 204, 55, 3, 1,
- 249, 17, 1, 1,
- 255, 17, 1, 1};
-
+// http://seaviewsensing.com/pub/cpt-city/es/autumn/es_autumn_19.c3g
+const uint8_t es_autumn_19_gp[] PROGMEM = {
+ 0, 90, 14, 5,
+ 51, 139, 41, 13,
+ 84, 180, 70, 17,
+ 104, 192, 202, 125,
+ 112, 177, 137, 3,
+ 122, 190, 200, 131,
+ 124, 192, 202, 124,
+ 135, 177, 137, 3,
+ 142, 194, 203, 118,
+ 163, 177, 68, 17,
+ 204, 128, 35, 12,
+ 249, 74, 5, 2,
+ 255, 74, 5, 2};
// Gradient palette "BlacK_Blue_Magenta_White_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/basic/tn/BlacK_Blue_Magenta_White.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 28 bytes of program space.
-
-const byte BlacK_Blue_Magenta_White_gp[] PROGMEM = {
- 0, 0, 0, 0,
- 42, 0, 0, 45,
- 84, 0, 0,255,
- 127, 42, 0,255,
- 170, 255, 0,255,
- 212, 255, 55,255,
- 255, 255,255,255};
-
+// http://seaviewsensing.com/pub/cpt-city/nd/basic/BlacK_Blue_Magenta_White.c3g
+const uint8_t BlacK_Blue_Magenta_White_gp[] PROGMEM = {
+ 0, 0, 0, 0,
+ 42, 0, 0, 117,
+ 84, 0, 0, 255,
+ 127, 113, 0, 255,
+ 170, 255, 0, 255,
+ 212, 255, 128, 255,
+ 255, 255, 255, 255};
// Gradient palette "BlacK_Magenta_Red_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/basic/tn/BlacK_Magenta_Red.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 20 bytes of program space.
-
-const byte BlacK_Magenta_Red_gp[] PROGMEM = {
- 0, 0, 0, 0,
- 63, 42, 0, 45,
- 127, 255, 0,255,
- 191, 255, 0, 45,
- 255, 255, 0, 0};
-
+// http://seaviewsensing.com/pub/cpt-city/nd/basic/BlacK_Magenta_Red.c3g
+const uint8_t BlacK_Magenta_Red_gp[] PROGMEM = {
+ 0, 0, 0, 0,
+ 63, 113, 0, 117,
+ 127, 255, 0, 255,
+ 191, 255, 0, 117,
+ 255, 255, 0, 0};
// Gradient palette "BlacK_Red_Magenta_Yellow_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/basic/tn/BlacK_Red_Magenta_Yellow.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 28 bytes of program space.
-
-const byte BlacK_Red_Magenta_Yellow_gp[] PROGMEM = {
- 0, 0, 0, 0,
- 42, 42, 0, 0,
- 84, 255, 0, 0,
- 127, 255, 0, 45,
- 170, 255, 0,255,
- 212, 255, 55, 45,
- 255, 255,255, 0};
-
+// http://seaviewsensing.com/pub/cpt-city/nd/basic/BlacK_Red_Magenta_Yellow.c3g
+const uint8_t BlacK_Red_Magenta_Yellow_gp[] PROGMEM = {
+ 0, 0, 0, 0,
+ 42, 113, 0, 0,
+ 84, 255, 0, 0,
+ 127, 255, 0, 117,
+ 170, 255, 0, 255,
+ 212, 255, 128, 117,
+ 255, 255, 255, 0};
// Gradient palette "Blue_Cyan_Yellow_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/basic/tn/Blue_Cyan_Yellow.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 20 bytes of program space.
-
-const byte Blue_Cyan_Yellow_gp[] PROGMEM = {
- 0, 0, 0,255,
- 63, 0, 55,255,
- 127, 0,255,255,
- 191, 42,255, 45,
- 255, 255,255, 0};
-
+// http://seaviewsensing.com/pub/cpt-city/nd/basic/Blue_Cyan_Yellow.c3g
+const uint8_t Blue_Cyan_Yellow_gp[] PROGMEM = {
+ 0, 0, 0, 255,
+ 63, 0, 128, 255,
+ 127, 0, 255, 255,
+ 191, 113, 255, 117,
+ 255, 255, 255, 0};
//Custom palette by Aircoookie
-
const byte Orange_Teal_gp[] PROGMEM = {
0, 0,150, 92,
55, 0,150, 92,
@@ -502,7 +376,6 @@ const byte Orange_Teal_gp[] PROGMEM = {
255, 255, 72, 0};
//Custom palette by Aircoookie
-
const byte Tiamat_gp[] PROGMEM = {
0, 1, 2, 14, //gc
33, 2, 5, 35, //gc from 47, 61,126
@@ -517,7 +390,6 @@ const byte Tiamat_gp[] PROGMEM = {
255, 255,249,255};
//Custom palette by Aircoookie
-
const byte April_Night_gp[] PROGMEM = {
0, 1, 5, 45, //deep blue
10, 1, 5, 45,
@@ -585,288 +457,257 @@ const byte Atlantica_gp[] PROGMEM = {
const byte C9_2_gp[] PROGMEM = {
0, 6, 126, 2, //green
45, 6, 126, 2,
- 45, 4, 30, 114, //blue
+ 46, 4, 30, 114, //blue
90, 4, 30, 114,
- 90, 255, 5, 0, //red
+ 91, 255, 5, 0, //red
135, 255, 5, 0,
- 135, 196, 57, 2, //amber
+ 136, 196, 57, 2, //amber
180, 196, 57, 2,
- 180, 137, 85, 2, //yellow
+ 181, 137, 85, 2, //yellow
255, 137, 85, 2};
//C9, but brighter and with a less purple blue
const byte C9_new_gp[] PROGMEM = {
0, 255, 5, 0, //red
60, 255, 5, 0,
- 60, 196, 57, 2, //amber (start 61?)
+ 61, 196, 57, 2, //amber (start 61?)
120, 196, 57, 2,
- 120, 6, 126, 2, //green (start 126?)
+ 121, 6, 126, 2, //green (start 126?)
180, 6, 126, 2,
- 180, 4, 30, 114, //blue (start 191?)
+ 181, 4, 30, 114, //blue (start 191?)
255, 4, 30, 114};
// Gradient palette "temperature_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/arendal/tn/temperature.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 144 bytes of program space.
+// http://seaviewsensing.com/pub/cpt-city/arendal/temperature.c3g
+const uint8_t temperature_gp[] PROGMEM = {
+ 0, 20, 92, 171,
+ 14, 15, 111, 186,
+ 28, 6, 142, 211,
+ 42, 2, 161, 227,
+ 56, 16, 181, 239,
+ 70, 38, 188, 201,
+ 84, 86, 204, 200,
+ 99, 139, 219, 176,
+ 113, 182, 229, 125,
+ 127, 196, 230, 63,
+ 141, 241, 240, 22,
+ 155, 254, 222, 30,
+ 170, 251, 199, 4,
+ 184, 247, 157, 9,
+ 198, 243, 114, 15,
+ 226, 213, 30, 29,
+ 240, 151, 38, 35,
+ 255, 151, 38, 35};
-const byte temperature_gp[] PROGMEM = {
- 0, 1, 27,105,
- 14, 1, 40,127,
- 28, 1, 70,168,
- 42, 1, 92,197,
- 56, 1,119,221,
- 70, 3,130,151,
- 84, 23,156,149,
- 99, 67,182,112,
- 113, 121,201, 52,
- 127, 142,203, 11,
- 141, 224,223, 1,
- 155, 252,187, 2,
- 170, 247,147, 1,
- 184, 237, 87, 1,
- 198, 229, 43, 1,
- 226, 171, 2, 2,
- 240, 80, 3, 3,
- 255, 80, 3, 3};
-
- const byte Aurora2_gp[] PROGMEM = {
- 0, 17, 177, 13, //Greenish
- 64, 121, 242, 5, //Greenish
- 128, 25, 173, 121, //Turquoise
- 192, 250, 77, 127, //Pink
- 255, 171, 101, 221 //Purple
- };
-
- // Gradient palette "bhw1_01_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw1/tn/bhw1_01.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 12 bytes of program space.
-
-const byte retro_clown_gp[] PROGMEM = {
- 0, 227,101, 3,
- 117, 194, 18, 19,
- 255, 92, 8,192};
+// Gradient palette "bhw1_01_gp", originally from
+// http://seaviewsensing.com/pub/cpt-city/bhw/bhw1/bhw1_01.c3g
+const uint8_t retro_clown_gp[] PROGMEM = {
+ 0, 242, 168, 38,
+ 117, 226, 78, 80,
+ 255, 161, 54, 225,
+};
// Gradient palette "bhw1_04_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw1/tn/bhw1_04.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 20 bytes of program space.
-
-const byte candy_gp[] PROGMEM = {
- 0, 229,227, 1,
- 15, 227,101, 3,
- 142, 40, 1, 80,
- 198, 17, 1, 79,
- 255, 0, 0, 45};
+// http://seaviewsensing.com/pub/cpt-city/bhw/bhw1/bhw1_04.c3g
+const uint8_t candy_gp[] PROGMEM = {
+ 0, 243, 242, 23,
+ 15, 242, 168, 38,
+ 142, 111, 21, 151,
+ 198, 74, 22, 150,
+ 255, 0, 0, 117};
// Gradient palette "bhw1_05_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw1/tn/bhw1_05.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 8 bytes of program space.
-
-const byte toxy_reaf_gp[] PROGMEM = {
- 0, 1,221, 53,
- 255, 73, 3,178};
+// http://seaviewsensing.com/pub/cpt-city/bhw/bhw1/bhw1_05.c3g
+const uint8_t toxy_reaf_gp[] PROGMEM = {
+ 0, 2, 239, 126,
+ 255, 145, 35, 217};
// Gradient palette "bhw1_06_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw1/tn/bhw1_06.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 16 bytes of program space.
-
-const byte fairy_reaf_gp[] PROGMEM = {
- 0, 184, 1,128,
- 160, 1,193,182,
- 219, 153,227,190,
- 255, 255,255,255};
+// http://seaviewsensing.com/pub/cpt-city/bhw/bhw1/bhw1_06.c3g
+const uint8_t fairy_reaf_gp[] PROGMEM = {
+ 0, 220, 19, 187,
+ 160, 12, 225, 219,
+ 219, 203, 242, 223,
+ 255, 255, 255, 255};
// Gradient palette "bhw1_14_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw1/tn/bhw1_14.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 36 bytes of program space.
-
-const byte semi_blue_gp[] PROGMEM = {
- 0, 0, 0, 0,
- 12, 1, 1, 3,
- 53, 8, 1, 22,
- 80, 4, 6, 89,
- 119, 2, 25,216,
- 145, 7, 10, 99,
- 186, 15, 2, 31,
- 233, 2, 1, 5,
- 255, 0, 0, 0};
+// http://seaviewsensing.com/pub/cpt-city/bhw/bhw1/bhw1_14.c3g
+const uint8_t semi_blue_gp[] PROGMEM = {
+ 0, 0, 0, 0,
+ 12, 24, 4, 38,
+ 53, 55, 8, 84,
+ 80, 43, 48, 159,
+ 119, 31, 89, 237,
+ 145, 50, 59, 166,
+ 186, 71, 30, 98,
+ 233, 31, 15, 45,
+ 255, 0, 0, 0};
// Gradient palette "bhw1_three_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw1/tn/bhw1_three.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 32 bytes of program space.
-
-const byte pink_candy_gp[] PROGMEM = {
- 0, 255,255,255,
- 45, 7, 12,255,
- 112, 227, 1,127,
- 112, 227, 1,127,
- 140, 255,255,255,
- 155, 227, 1,127,
- 196, 45, 1, 99,
- 255, 255,255,255};
+// http://seaviewsensing.com/pub/cpt-city/bhw/bhw1/bhw1_three.c3g
+const uint8_t pink_candy_gp[] PROGMEM = {
+ 0, 255, 255, 255,
+ 45, 50, 64, 255,
+ 112, 242, 16, 186,
+ 140, 255, 255, 255,
+ 155, 242, 16, 186,
+ 196, 116, 13, 166,
+ 255, 255, 255, 255};
// Gradient palette "bhw1_w00t_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw1/tn/bhw1_w00t.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 16 bytes of program space.
-
-const byte red_reaf_gp[] PROGMEM = {
- 0, 3, 13, 43,
- 104, 78,141,240,
- 188, 255, 0, 0,
- 255, 28, 1, 1};
-
+// http://seaviewsensing.com/pub/cpt-city/bhw/bhw1/bhw1_w00t.c3g
+const uint8_t red_reaf_gp[] PROGMEM = {
+ 0, 36, 68, 114,
+ 104, 149, 195, 248,
+ 188, 255, 0, 0,
+ 255, 94, 14, 9};
// Gradient palette "bhw2_23_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw2/tn/bhw2_23.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Red & Flash in SR
-// Size: 28 bytes of program space.
-
-const byte aqua_flash_gp[] PROGMEM = {
- 0, 0, 0, 0,
- 66, 57,227,233,
- 96, 255,255, 8,
- 124, 255,255,255,
- 153, 255,255, 8,
- 188, 57,227,233,
- 255, 0, 0, 0};
+// http://seaviewsensing.com/pub/cpt-city/bhw/bhw2/bhw2_23.c3g
+const uint8_t aqua_flash_gp[] PROGMEM = {
+ 0, 0, 0, 0,
+ 66, 130, 242, 245,
+ 96, 255, 255, 53,
+ 124, 255, 255, 255,
+ 153, 255, 255, 53,
+ 188, 130, 242, 245,
+ 255, 0, 0, 0};
// Gradient palette "bhw2_xc_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw2/tn/bhw2_xc.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// YBlue in SR
-// Size: 28 bytes of program space.
+// http://seaviewsensing.com/pub/cpt-city/bhw/bhw2/bhw2_xc.c3g
+const uint8_t yelblu_hot_gp[] PROGMEM = {
+ 0, 43, 30, 57,
+ 58, 73, 0, 119,
+ 122, 87, 0, 74,
+ 158, 197, 57, 22,
+ 183, 218, 117, 27,
+ 219, 239, 177, 32,
+ 255, 246, 247, 27,
+};
-const byte yelblu_hot_gp[] PROGMEM = {
- 0, 4, 2, 9,
- 58, 16, 0, 47,
- 122, 24, 0, 16,
- 158, 144, 9, 1,
- 183, 179, 45, 1,
- 219, 220,114, 2,
- 255, 234,237, 1};
-
- // Gradient palette "bhw2_45_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw2/tn/bhw2_45.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 24 bytes of program space.
-
-const byte lite_light_gp[] PROGMEM = {
- 0, 0, 0, 0,
- 9, 1, 1, 1,
- 40, 5, 5, 6,
- 66, 5, 5, 6,
- 101, 10, 1, 12,
- 255, 0, 0, 0};
+// Gradient palette "bhw2_45_gp", originally from
+// http://seaviewsensing.com/pub/cpt-city/bhw/bhw2/bhw2_45.c3g
+const uint8_t lite_light_gp[] PROGMEM = {
+ 0, 0, 0, 0,
+ 9, 20, 21, 22,
+ 40, 46, 43, 49,
+ 66, 46, 43, 49,
+ 101, 61, 16, 65,
+ 255, 0, 0, 0};
// Gradient palette "bhw2_22_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw2/tn/bhw2_22.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Pink Plasma in SR
-// Size: 20 bytes of program space.
-
-const byte red_flash_gp[] PROGMEM = {
- 0, 0, 0, 0,
- 99, 227, 1, 1,
- 130, 249,199, 95,
- 155, 227, 1, 1,
- 255, 0, 0, 0};
+// http://seaviewsensing.com/pub/cpt-city/bhw/bhw2/bhw2_22.c3g
+const uint8_t red_flash_gp[] PROGMEM = {
+ 0, 0, 0, 0,
+ 99, 242, 12, 8,
+ 130, 253, 228, 163,
+ 155, 242, 12, 8,
+ 255, 0, 0, 0};
// Gradient palette "bhw3_40_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw3/tn/bhw3_40.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 32 bytes of program space.
-
-const byte blink_red_gp[] PROGMEM = {
- 0, 1, 1, 1,
- 43, 4, 1, 11,
- 76, 10, 1, 3,
- 109, 161, 4, 29,
- 127, 255, 86,123,
- 165, 125, 16,160,
- 204, 35, 13,223,
- 255, 18, 2, 18};
+// http://seaviewsensing.com/pub/cpt-city/bhw/bhw3/bhw3_40.c3g
+const uint8_t blink_red_gp[] PROGMEM = {
+ 0, 4, 7, 4,
+ 43, 40, 25, 62,
+ 76, 61, 15, 36,
+ 109, 207, 39, 96,
+ 127, 255, 156, 184,
+ 165, 185, 73, 207,
+ 204, 105, 66, 240,
+ 255, 77, 29, 78};
// Gradient palette "bhw3_52_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw3/tn/bhw3_52.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Yellow2Blue in SR
-// Size: 28 bytes of program space.
-
-const byte red_shift_gp[] PROGMEM = {
- 0, 31, 1, 27,
- 45, 34, 1, 16,
- 99, 137, 5, 9,
- 132, 213,128, 10,
- 175, 199, 22, 1,
- 201, 199, 9, 6,
- 255, 1, 0, 1};
+// http://seaviewsensing.com/pub/cpt-city/bhw/bhw3/bhw3_52.c3g
+const uint8_t red_shift_gp[] PROGMEM = {
+ 0, 98, 22, 93,
+ 45, 103, 22, 73,
+ 99, 192, 45, 56,
+ 132, 235, 187, 59,
+ 175, 228, 85, 26,
+ 201, 228, 56, 48,
+ 255, 2, 0, 2};
// Gradient palette "bhw4_097_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw4/tn/bhw4_097.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Yellow2Red in SR
-// Size: 44 bytes of program space.
-
-const byte red_tide_gp[] PROGMEM = {
- 0, 247, 5, 0,
- 28, 255, 67, 1,
- 43, 234, 88, 11,
- 58, 234,176, 51,
- 84, 229, 28, 1,
- 114, 113, 12, 1,
- 140, 255,225, 44,
- 168, 113, 12, 1,
- 196, 244,209, 88,
- 216, 255, 28, 1,
- 255, 53, 1, 1};
+// http://seaviewsensing.com/pub/cpt-city/bhw/bhw4/bhw4_097.c3g
+const uint8_t red_tide_gp[] PROGMEM = {
+ 0, 251, 46, 0,
+ 28, 255, 139, 25,
+ 43, 246, 158, 63,
+ 58, 246, 216, 123,
+ 84, 243, 94, 10,
+ 114, 177, 65, 11,
+ 140, 255, 241, 115,
+ 168, 177, 65, 11,
+ 196, 250, 233, 158,
+ 216, 255, 94, 6,
+ 255, 126, 8, 4};
// Gradient palette "bhw4_017_gp", originally from
-// http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw4/tn/bhw4_017.png.index.html
-// converted for FastLED with gammas (2.6, 2.2, 2.5)
-// Size: 40 bytes of program space.
-
-const byte candy2_gp[] PROGMEM = {
- 0, 39, 33, 34,
- 25, 4, 6, 15,
- 48, 49, 29, 22,
- 73, 224,173, 1,
- 89, 177, 35, 5,
- 130, 4, 6, 15,
- 163, 255,114, 6,
- 186, 224,173, 1,
- 211, 39, 33, 34,
- 255, 1, 1, 1};
+// http://seaviewsensing.com/pub/cpt-city/bhw/bhw4/bhw4_017.c3g
+const uint8_t candy2_gp[] PROGMEM = {
+ 0, 109, 102, 102,
+ 25, 42, 49, 71,
+ 48, 121, 96, 84,
+ 73, 241, 214, 26,
+ 89, 216, 104, 44,
+ 130, 42, 49, 71,
+ 163, 255, 177, 47,
+ 186, 241, 214, 26,
+ 211, 109, 102, 102,
+ 255, 20, 19, 13};
const byte trafficlight_gp[] PROGMEM = {
- 0, 0, 0, 0, //black
- 85, 0, 255, 0, //green
- 170, 255, 255, 0, //yellow
- 255, 255, 0, 0}; //red
+ 0, 0, 0, 0, //black
+ 85, 0, 255, 0, //green
+ 170, 255, 255, 0, //yellow
+ 255, 255, 0, 0}; //red
+
+const byte Aurora2_gp[] PROGMEM = {
+ 0, 17, 177, 13, //Greenish
+ 64, 121, 242, 5, //Greenish
+ 128, 25, 173, 121, //Turquoise
+ 192, 250, 77, 127, //Pink
+ 255, 171, 101, 221}; //Purple
+
+// FastLed palettes, corrected with inverse gamma of 2.2 to match original looks
+
+// Party colors
+const TProgmemRGBPalette16 PartyColors_gc22 FL_PROGMEM = {
+ 0x9B00D5, 0xBD00B8, 0xDA0092, 0xF3005C,
+ 0xF45500, 0xDC8F00, 0xD5B400, 0xD5D500,
+ 0xD59B00, 0xEF6600, 0xF90044, 0xE10086,
+ 0xC400B0, 0xA300CF, 0x7600E8, 0x0032FC};
+
+// Rainbow colors
+const TProgmemRGBPalette16 RainbowColors_gc22 FL_PROGMEM = {
+ 0xFF0000, 0xEB7000, 0xD59B00, 0xD5BA00,
+ 0xD5D500, 0x9CEB00, 0x00FF00, 0x00EB70,
+ 0x00D59B, 0x009CD4, 0x0000FF, 0x7000EB,
+ 0x9B00D5, 0xBA00BB, 0xD5009B, 0xEB0072};
+
+// Rainbow colors with alternatating stripes of black
+const TProgmemRGBPalette16 RainbowStripeColors_gc22 FL_PROGMEM = {
+ 0xFF0000, 0x000000, 0xD59B00, 0x000000,
+ 0xD5D500, 0x000000, 0x00FF00, 0x000000,
+ 0x00D59B, 0x000000, 0x0000FF, 0x000000,
+ 0x9B00D5, 0x000000, 0xD5009B, 0x000000};
// array of fastled palettes (palette 6 - 12)
const TProgmemRGBPalette16 *const fastledPalettes[] PROGMEM = {
- &PartyColors_p, //06-00 Party
+ &PartyColors_gc22, //06-00 Party
&CloudColors_p, //07-01 Cloud
&LavaColors_p, //08-02 Lava
&OceanColors_p, //09-03 Ocean
&ForestColors_p, //10-04 Forest
- &RainbowColors_p, //11-05 Rainbow
- &RainbowStripeColors_p //12-06 Rainbow Bands
+ &RainbowColors_gc22, //11-05 Rainbow
+ &RainbowStripeColors_gc22 //12-06 Rainbow Bands
};
// Single array of defined cpt-city color palettes.
// This will let us programmatically choose one based on
// a number, rather than having to activate each explicitly
// by name every time.
-const byte* const gGradientPalettes[] PROGMEM = {
+const uint8_t* const gGradientPalettes[] PROGMEM = {
Sunset_Real_gp, //13-00 Sunset
es_rivendell_15_gp, //14-01 Rivendell
es_ocean_breeze_036_gp, //15-02 Breeze
diff --git a/wled00/pin_manager.cpp b/wled00/pin_manager.cpp
index 6f1652301..cdbb85267 100644
--- a/wled00/pin_manager.cpp
+++ b/wled00/pin_manager.cpp
@@ -1,5 +1,5 @@
-#include "pin_manager.h"
#include "wled.h"
+#include "pin_manager.h"
#ifdef ARDUINO_ARCH_ESP32
#ifdef bitRead
diff --git a/wled00/pin_manager.h b/wled00/pin_manager.h
index b285b6ee5..662e499b2 100644
--- a/wled00/pin_manager.h
+++ b/wled00/pin_manager.h
@@ -3,11 +3,6 @@
/*
* Registers pins so there is no attempt for two interfaces to use the same pin
*/
-#include
-#ifdef ARDUINO_ARCH_ESP32
-#include "driver/ledc.h" // needed for analog/LEDC channel counts
-#endif
-#include "const.h" // for USERMOD_* values
#ifdef ESP8266
#define WLED_NUM_PINS (GPIO_PIN_COUNT+1) // somehow they forgot GPIO 16 (0-16==17)
diff --git a/wled00/presets.cpp b/wled00/presets.cpp
index b749289bd..fed2c1ed9 100644
--- a/wled00/presets.cpp
+++ b/wled00/presets.cpp
@@ -29,8 +29,9 @@ bool presetNeedsSaving() {
static void doSaveState() {
bool persist = (presetToSave < 251);
- unsigned long start = millis();
- while (strip.isUpdating() && millis()-start < (2*FRAMETIME_FIXED)+1) yield(); // wait 2 frames
+ unsigned long maxWait = millis() + strip.getFrameTime();
+ while (strip.isUpdating() && millis() < maxWait) delay(1); // wait for strip to finish updating, accessing FS during sendout causes glitches
+
if (!requestJSONBufferLock(10)) return;
initPresetsFile(); // just in case if someone deleted presets.json using /edit
@@ -56,14 +57,10 @@ static void doSaveState() {
*/
#if defined(ARDUINO_ARCH_ESP32)
if (!persist) {
- if (tmpRAMbuffer!=nullptr) free(tmpRAMbuffer);
+ p_free(tmpRAMbuffer);
size_t len = measureJson(*pDoc) + 1;
- DEBUG_PRINTLN(len);
// if possible use SPI RAM on ESP32
- if (psramSafe && psramFound())
- tmpRAMbuffer = (char*) ps_malloc(len);
- else
- tmpRAMbuffer = (char*) malloc(len);
+ tmpRAMbuffer = (char*)p_malloc(len);
if (tmpRAMbuffer!=nullptr) {
serializeJson(*pDoc, tmpRAMbuffer, len);
} else {
@@ -80,8 +77,8 @@ static void doSaveState() {
// clean up
saveLedmap = -1;
presetToSave = 0;
- free(saveName);
- free(quickLoad);
+ p_free(saveName);
+ p_free(quickLoad);
saveName = nullptr;
quickLoad = nullptr;
playlistSave = false;
@@ -168,9 +165,9 @@ void handlePresets()
DEBUG_PRINTF_P(PSTR("Applying preset: %u\n"), (unsigned)tmpPreset);
- #if defined(ARDUINO_ARCH_ESP32S3) || defined(ARDUINO_ARCH_ESP32S2) || defined(ARDUINO_ARCH_ESP32C3)
- unsigned long start = millis();
- while (strip.isUpdating() && millis() - start < FRAMETIME_FIXED) yield(); // wait for strip to finish updating, accessing FS during sendout causes glitches
+ #if defined(ARDUINO_ARCH_ESP32S2) || defined(ARDUINO_ARCH_ESP32C3)
+ unsigned long maxWait = millis() + strip.getFrameTime();
+ while (strip.isUpdating() && millis() < maxWait) delay(1); // wait for strip to finish updating, accessing FS during sendout causes glitches
#endif
#ifdef ARDUINO_ARCH_ESP32
@@ -206,7 +203,7 @@ void handlePresets()
#if defined(ARDUINO_ARCH_ESP32)
//Aircoookie recommended not to delete buffer
if (tmpPreset==255 && tmpRAMbuffer!=nullptr) {
- free(tmpRAMbuffer);
+ p_free(tmpRAMbuffer);
tmpRAMbuffer = nullptr;
}
#endif
@@ -220,8 +217,8 @@ void handlePresets()
//called from handleSet(PS=) [network callback (sObj is empty), IR (irrational), deserializeState, UDP] and deserializeState() [network callback (filedoc!=nullptr)]
void savePreset(byte index, const char* pname, JsonObject sObj)
{
- if (!saveName) saveName = static_cast(malloc(33));
- if (!quickLoad) quickLoad = static_cast(malloc(9));
+ if (!saveName) saveName = static_cast(p_malloc(33));
+ if (!quickLoad) quickLoad = static_cast(p_malloc(9));
if (!saveName || !quickLoad) return;
if (index == 0 || (index > 250 && index < 255)) return;
@@ -267,8 +264,8 @@ void savePreset(byte index, const char* pname, JsonObject sObj)
presetsModifiedTime = toki.second(); //unix time
updateFSInfo();
}
- free(saveName);
- free(quickLoad);
+ p_free(saveName);
+ p_free(quickLoad);
saveName = nullptr;
quickLoad = nullptr;
} else {
diff --git a/wled00/remote.cpp b/wled00/remote.cpp
index 8c060a70c..14c3c0d01 100644
--- a/wled00/remote.cpp
+++ b/wled00/remote.cpp
@@ -181,16 +181,10 @@ static bool remoteJson(int button)
return parsed;
}
-// Callback function that will be executed when data is received
+// Callback function that will be executed when data is received from a linked remote
void handleWiZdata(uint8_t *incomingData, size_t len) {
message_structure_t *incoming = reinterpret_cast(incomingData);
- if (strcmp(last_signal_src, linked_remote) != 0) {
- DEBUG_PRINT(F("ESP Now Message Received from Unlinked Sender: "));
- DEBUG_PRINTLN(last_signal_src);
- return;
- }
-
if (len != sizeof(message_structure_t)) {
DEBUG_PRINTF_P(PSTR("Unknown incoming ESP Now message received of length %u\n"), len);
return;
diff --git a/wled00/set.cpp b/wled00/set.cpp
index 725875023..6229ba28e 100644
--- a/wled00/set.cpp
+++ b/wled00/set.cpp
@@ -28,7 +28,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
char gw[5] = "GW"; gw[2] = 48+n; gw[4] = 0; //GW address
char sn[5] = "SN"; sn[2] = 48+n; sn[4] = 0; //subnet mask
if (request->hasArg(cs)) {
- if (n >= multiWiFi.size()) multiWiFi.push_back(WiFiConfig()); // expand vector by one
+ if (n >= multiWiFi.size()) multiWiFi.emplace_back(); // expand vector by one
char oldSSID[33]; strcpy(oldSSID, multiWiFi[n].clientSSID);
char oldPass[65]; strcpy(oldPass, multiWiFi[n].clientPass);
@@ -91,8 +91,21 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
bool oldESPNow = enableESPNow;
enableESPNow = request->hasArg(F("RE"));
if (oldESPNow != enableESPNow) forceReconnect = true;
- strlcpy(linked_remote, request->arg(F("RMAC")).c_str(), 13);
- strlwr(linked_remote); //Normalize MAC format to lowercase
+ linked_remotes.clear(); // clear old remotes
+ for (size_t n = 0; n < 10; n++) {
+ char rm[4];
+ snprintf(rm, sizeof(rm), "RM%d", n); // "RM0" to "RM9"
+ if (request->hasArg(rm)) {
+ const String& arg = request->arg(rm);
+ if (arg.isEmpty()) continue;
+ std::array mac{};
+ strlcpy(mac.data(), request->arg(rm).c_str(), 13);
+ strlwr(mac.data());
+ if (mac[0] != '\0') {
+ linked_remotes.emplace_back(mac);
+ }
+ }
+ }
#endif
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_ETHERNET)
@@ -129,6 +142,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
unsigned length, start, maMax;
uint8_t pins[5] = {255, 255, 255, 255, 255};
+ // this will set global ABL max current used when per-port ABL is not used
unsigned ablMilliampsMax = request->arg(F("MA")).toInt();
BusManager::setMilliampsMax(ablMilliampsMax);
@@ -136,10 +150,10 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
strip.correctWB = request->hasArg(F("CCT"));
strip.cctFromRgb = request->hasArg(F("CR"));
cctICused = request->hasArg(F("IC"));
- Bus::setCCTBlend(request->arg(F("CB")).toInt());
+ uint8_t cctBlending = request->arg(F("CB")).toInt();
+ Bus::setCCTBlend(cctBlending);
Bus::setGlobalAWMode(request->arg(F("AW")).toInt());
strip.setTargetFps(request->arg(F("FR")).toInt());
- useGlobalLedBuffer = request->hasArg(F("LD"));
#if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3)
useParallelI2S = request->hasArg(F("PR"));
#endif
@@ -207,12 +221,12 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
maMax = 0;
} else {
maPerLed = request->arg(la).toInt();
- maMax = request->arg(ma).toInt(); // if ABL is disabled this will be 0
+ maMax = request->arg(ma).toInt() * request->hasArg(F("PPL")); // if PP-ABL is disabled maMax (per bus) must be 0
}
type |= request->hasArg(rf) << 7; // off refresh override
// 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
- busConfigs.emplace_back(type, pins, start, length, colorOrder | (channelSwap<<4), request->hasArg(cv), skip, awmode, freq, useGlobalLedBuffer, maPerLed, maMax);
+ busConfigs.emplace_back(type, pins, start, length, colorOrder | (channelSwap<<4), request->hasArg(cv), skip, awmode, freq, maPerLed, maMax);
busesChanged = true;
}
//doInitBusses = busesChanged; // we will do that below to ensure all input data is processed
@@ -327,13 +341,14 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
gammaCorrectBri = false;
gammaCorrectCol = false;
}
- NeoGammaWLEDMethod::calcGammaTable(gammaCorrectVal); // fill look-up table
+ NeoGammaWLEDMethod::calcGammaTable(gammaCorrectVal); // fill look-up tables
t = request->arg(F("TD")).toInt();
if (t >= 0) transitionDelayDefault = t;
t = request->arg(F("TP")).toInt();
randomPaletteChangeTime = MIN(255,MAX(1,t));
useHarmonicRandomPalette = request->hasArg(F("TH"));
+ useRainbowWheel = request->hasArg(F("RW"));
nightlightTargetBri = request->arg(F("TB")).toInt();
t = request->arg(F("TL")).toInt();
@@ -342,7 +357,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
nightlightMode = request->arg(F("TW")).toInt();
t = request->arg(F("PB")).toInt();
- if (t >= 0 && t < 4) strip.paletteBlend = t;
+ if (t >= 0 && t < 4) paletteBlend = t;
t = request->arg(F("BF")).toInt();
if (t > 0) briMultiplier = t;
@@ -358,7 +373,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
DEBUG_PRINTLN(F("Enumerating ledmaps"));
enumerateLedmaps();
DEBUG_PRINTLN(F("Loading custom palettes"));
- strip.loadCustomPalettes(); // (re)load all custom palettes
+ loadCustomPalettes(); // (re)load all custom palettes
}
//SYNC
@@ -593,7 +608,9 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
{
otaLock = request->hasArg(F("NO"));
wifiLock = request->hasArg(F("OW"));
+ #ifndef WLED_DISABLE_OTA
aOtaEnabled = request->hasArg(F("AO"));
+ #endif
//createEditHandler(correctPIN && !otaLock);
}
}
@@ -771,14 +788,14 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
if (subPage == SUBPAGE_2D)
{
strip.isMatrix = request->arg(F("SOMP")).toInt();
- strip.panel.clear(); // release memory if allocated
+ strip.panel.clear();
if (strip.isMatrix) {
- strip.panels = MAX(1,MIN(WLED_MAX_PANELS,request->arg(F("MPC")).toInt()));
- strip.panel.reserve(strip.panels); // pre-allocate memory
- for (unsigned i=0; iarg(F("MPC")).toInt(), 1, WLED_MAX_PANELS);
+ strip.panel.reserve(panels); // pre-allocate memory
+ for (unsigned i=0; iarg(pO).toInt();
strip.panel.push_back(p);
}
- strip.setUpMatrix(); // will check limits
- strip.makeAutoSegments(true);
- strip.deserializeMap();
- } else {
- Segment::maxWidth = strip.getLengthTotal();
- Segment::maxHeight = 1;
}
+ strip.panel.shrink_to_fit(); // release unused memory
+ strip.deserializeMap(); // (re)load default ledmap (will also setUpMatrix() if ledmap does not exist)
+ strip.makeAutoSegments(true); // force re-creation of segments
}
#endif
@@ -824,7 +838,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
//segment select (sets main segment)
pos = req.indexOf(F("SM="));
if (pos > 0 && !realtimeMode) {
- strip.setMainSegmentId(getNumVal(&req, pos));
+ strip.setMainSegmentId(getNumVal(req, pos));
}
byte selectedSeg = strip.getFirstSelectedSegId();
@@ -833,7 +847,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
pos = req.indexOf(F("SS="));
if (pos > 0) {
- unsigned t = getNumVal(&req, pos);
+ unsigned t = getNumVal(req, pos);
if (t < strip.getSegmentsNum()) {
selectedSeg = t;
singleSegment = true;
@@ -843,7 +857,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
Segment& selseg = strip.getSegment(selectedSeg);
pos = req.indexOf(F("SV=")); //segment selected
if (pos > 0) {
- unsigned t = getNumVal(&req, pos);
+ unsigned t = getNumVal(req, pos);
if (t == 2) for (unsigned i = 0; i < strip.getSegmentsNum(); i++) strip.getSegment(i).selected = false; // unselect other segments
selseg.selected = t;
}
@@ -872,19 +886,19 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
uint16_t spcI = selseg.spacing;
pos = req.indexOf(F("&S=")); //segment start
if (pos > 0) {
- startI = std::abs(getNumVal(&req, pos));
+ startI = std::abs(getNumVal(req, pos));
}
pos = req.indexOf(F("S2=")); //segment stop
if (pos > 0) {
- stopI = std::abs(getNumVal(&req, pos));
+ stopI = std::abs(getNumVal(req, pos));
}
pos = req.indexOf(F("GP=")); //segment grouping
if (pos > 0) {
- grpI = std::max(1,getNumVal(&req, pos));
+ grpI = std::max(1,getNumVal(req, pos));
}
pos = req.indexOf(F("SP=")); //segment spacing
if (pos > 0) {
- spcI = std::max(0,getNumVal(&req, pos));
+ spcI = std::max(0,getNumVal(req, pos));
}
strip.suspend(); // must suspend strip operations before changing geometry
selseg.setGeometry(startI, stopI, grpI, spcI, UINT16_MAX, startY, stopY, selseg.map1D2D);
@@ -898,7 +912,7 @@ 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);
+ byte segbri = getNumVal(req, pos);
selseg.setOption(SEG_OPTION_ON, segbri); // use transition
if (segbri) {
selseg.setOpacity(segbri);
@@ -907,7 +921,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
pos = req.indexOf(F("SW=")); //segment power
if (pos > 0) {
- switch (getNumVal(&req, pos)) {
+ switch (getNumVal(req, pos)) {
case 0: selseg.setOption(SEG_OPTION_ON, false); break; // use transition
case 1: selseg.setOption(SEG_OPTION_ON, true); break; // use transition
default: selseg.setOption(SEG_OPTION_ON, !selseg.on); break; // use transition
@@ -915,16 +929,16 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
}
pos = req.indexOf(F("PS=")); //saves current in preset
- if (pos > 0) savePreset(getNumVal(&req, pos));
+ if (pos > 0) savePreset(getNumVal(req, pos));
pos = req.indexOf(F("P1=")); //sets first preset for cycle
- if (pos > 0) presetCycMin = getNumVal(&req, pos);
+ if (pos > 0) presetCycMin = getNumVal(req, pos);
pos = req.indexOf(F("P2=")); //sets last preset for cycle
- if (pos > 0) presetCycMax = getNumVal(&req, pos);
+ if (pos > 0) presetCycMax = getNumVal(req, pos);
//apply preset
- if (updateVal(req.c_str(), "PL=", &presetCycCurr, presetCycMin, presetCycMax)) {
+ if (updateVal(req.c_str(), "PL=", presetCycCurr, presetCycMin, presetCycMax)) {
applyPreset(presetCycCurr);
}
@@ -932,25 +946,25 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
if (pos > 0) doAdvancePlaylist = true;
//set brightness
- updateVal(req.c_str(), "&A=", &bri);
+ updateVal(req.c_str(), "&A=", bri);
bool col0Changed = false, col1Changed = false, col2Changed = false;
//set colors
- 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]);
+ 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.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]);
+ 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
pos = req.indexOf(F("LX=")); // Lox primary color
if (pos > 0) {
- int lxValue = getNumVal(&req, pos);
+ int lxValue = getNumVal(req, pos);
if (parseLx(lxValue, colIn)) {
bri = 255;
nightlightActive = false; //always disable nightlight when toggling
@@ -959,7 +973,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
}
pos = req.indexOf(F("LY=")); // Lox secondary color
if (pos > 0) {
- int lxValue = getNumVal(&req, pos);
+ int lxValue = getNumVal(req, pos);
if(parseLx(lxValue, colInSec)) {
bri = 255;
nightlightActive = false; //always disable nightlight when toggling
@@ -971,11 +985,11 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
//set hue
pos = req.indexOf(F("HU="));
if (pos > 0) {
- uint16_t temphue = getNumVal(&req, pos);
+ uint16_t temphue = getNumVal(req, pos);
byte tempsat = 255;
pos = req.indexOf(F("SA="));
if (pos > 0) {
- tempsat = getNumVal(&req, pos);
+ tempsat = getNumVal(req, pos);
}
byte sec = req.indexOf(F("H2"));
colorHStoRGB(temphue, tempsat, (sec>0) ? colInSec : colIn);
@@ -986,25 +1000,25 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
pos = req.indexOf(F("&K="));
if (pos > 0) {
byte sec = req.indexOf(F("K2"));
- colorKtoRGB(getNumVal(&req, pos), (sec>0) ? colInSec : colIn);
+ colorKtoRGB(getNumVal(req, pos), (sec>0) ? colInSec : colIn);
col0Changed |= (!sec); col1Changed |= sec;
}
//set color from HEX or 32bit DEC
pos = req.indexOf(F("CL="));
if (pos > 0) {
- colorFromDecOrHexString(colIn, req.substring(pos + 3).c_str());
+ colorFromDecOrHexString(colIn, (char*)req.substring(pos + 3).c_str());
col0Changed = true;
}
pos = req.indexOf(F("C2="));
if (pos > 0) {
- colorFromDecOrHexString(colInSec, req.substring(pos + 3).c_str());
+ colorFromDecOrHexString(colInSec, (char*)req.substring(pos + 3).c_str());
col1Changed = true;
}
pos = req.indexOf(F("C3="));
if (pos > 0) {
byte tmpCol[4];
- colorFromDecOrHexString(tmpCol, req.substring(pos + 3).c_str());
+ colorFromDecOrHexString(tmpCol, (char*)req.substring(pos + 3).c_str());
col2 = RGBW32(tmpCol[0], tmpCol[1], tmpCol[2], tmpCol[3]);
selseg.setColor(2, col2); // defined above (SS= or main)
col2Changed = true;
@@ -1013,7 +1027,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
//set to random hue SR=0->1st SR=1->2nd
pos = req.indexOf(F("SR"));
if (pos > 0) {
- byte sec = getNumVal(&req, pos);
+ byte sec = getNumVal(req, pos);
setRandomColor(sec? colInSec : colIn);
col0Changed |= (!sec); col1Changed |= sec;
}
@@ -1039,19 +1053,19 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
bool fxModeChanged = false, speedChanged = false, intensityChanged = false, paletteChanged = false;
bool custom1Changed = false, custom2Changed = false, custom3Changed = false, check1Changed = false, check2Changed = false, check3Changed = false;
// set effect parameters
- if (updateVal(req.c_str(), "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.c_str(), "SX=", &speedIn);
- intensityChanged = updateVal(req.c_str(), "IX=", &intensityIn);
- paletteChanged = updateVal(req.c_str(), "FP=", &paletteIn, 0, strip.getPaletteCount()-1);
- custom1Changed = updateVal(req.c_str(), "X1=", &custom1In);
- custom2Changed = updateVal(req.c_str(), "X2=", &custom2In);
- custom3Changed = updateVal(req.c_str(), "X3=", &custom3In);
- check1Changed = updateVal(req.c_str(), "M1=", &check1In);
- check2Changed = updateVal(req.c_str(), "M2=", &check2In);
- check3Changed = updateVal(req.c_str(), "M3=", &check3In);
+ speedChanged = updateVal(req.c_str(), "SX=", speedIn);
+ intensityChanged = updateVal(req.c_str(), "IX=", intensityIn);
+ paletteChanged = updateVal(req.c_str(), "FP=", paletteIn, 0, getPaletteCount()-1);
+ custom1Changed = updateVal(req.c_str(), "X1=", custom1In);
+ custom2Changed = updateVal(req.c_str(), "X2=", custom2In);
+ custom3Changed = updateVal(req.c_str(), "X3=", custom3In);
+ check1Changed = updateVal(req.c_str(), "M1=", check1In);
+ check2Changed = updateVal(req.c_str(), "M2=", check2In);
+ check3Changed = updateVal(req.c_str(), "M3=", check3In);
stateChanged |= (fxModeChanged || speedChanged || intensityChanged || paletteChanged || custom1Changed || custom2Changed || custom3Changed || check1Changed || check2Changed || check3Changed);
@@ -1077,13 +1091,13 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
//set advanced overlay
pos = req.indexOf(F("OL="));
if (pos > 0) {
- overlayCurrent = getNumVal(&req, pos);
+ overlayCurrent = getNumVal(req, pos);
}
//apply macro (deprecated, added for compatibility with pre-0.11 automations)
pos = req.indexOf(F("&M="));
if (pos > 0) {
- applyPreset(getNumVal(&req, pos) + 16);
+ applyPreset(getNumVal(req, pos) + 16);
}
//toggle send UDP direct notifications
@@ -1102,7 +1116,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
pos = req.indexOf(F("&T="));
if (pos > 0) {
nightlightActive = false; //always disable nightlight when toggling
- switch (getNumVal(&req, pos))
+ switch (getNumVal(req, pos))
{
case 0: if (bri != 0){briLast = bri; bri = 0;} break; //off, only if it was previously on
case 1: if (bri == 0) bri = briLast; break; //on, only if it was previously off
@@ -1121,7 +1135,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
nightlightActive = false;
} else {
nightlightActive = true;
- if (!aNlDef) nightlightDelayMins = getNumVal(&req, pos);
+ if (!aNlDef) nightlightDelayMins = getNumVal(req, pos);
else nightlightDelayMins = nightlightDelayMinsDefault;
nightlightStartTime = millis();
}
@@ -1135,7 +1149,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
//set nightlight target brightness
pos = req.indexOf(F("NT="));
if (pos > 0) {
- nightlightTargetBri = getNumVal(&req, pos);
+ nightlightTargetBri = getNumVal(req, pos);
nightlightActiveOld = false; //re-init
}
@@ -1143,35 +1157,36 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
pos = req.indexOf(F("NF="));
if (pos > 0)
{
- nightlightMode = getNumVal(&req, pos);
+ nightlightMode = getNumVal(req, pos);
nightlightActiveOld = false; //re-init
}
if (nightlightMode > NL_MODE_SUN) nightlightMode = NL_MODE_SUN;
pos = req.indexOf(F("TT="));
- if (pos > 0) transitionDelay = getNumVal(&req, pos);
+ if (pos > 0) transitionDelay = getNumVal(req, pos);
strip.setTransition(transitionDelay);
//set time (unix timestamp)
pos = req.indexOf(F("ST="));
if (pos > 0) {
- setTimeFromAPI(getNumVal(&req, pos));
+ setTimeFromAPI(getNumVal(req, pos));
}
//set countdown goal (unix timestamp)
pos = req.indexOf(F("CT="));
if (pos > 0) {
- countdownTime = getNumVal(&req, pos);
+ countdownTime = getNumVal(req, pos);
if (countdownTime - toki.second() > 0) countdownOverTriggered = false;
}
pos = req.indexOf(F("LO="));
if (pos > 0) {
- realtimeOverride = getNumVal(&req, pos);
+ realtimeOverride = getNumVal(req, pos);
if (realtimeOverride > 2) realtimeOverride = REALTIME_OVERRIDE_ALWAYS;
if (realtimeMode && useMainSegmentOnly) {
strip.getMainSegment().freeze = !realtimeOverride;
+ realtimeOverride = REALTIME_OVERRIDE_NONE; // ignore request for override if using main segment only
}
}
@@ -1184,12 +1199,12 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
pos = req.indexOf(F("U0=")); //user var 0
if (pos > 0) {
- userVar0 = getNumVal(&req, pos);
+ userVar0 = getNumVal(req, pos);
}
pos = req.indexOf(F("U1=")); //user var 1
if (pos > 0) {
- userVar1 = getNumVal(&req, pos);
+ userVar1 = getNumVal(req, pos);
}
// you can add more if you need
diff --git a/wled00/udp.cpp b/wled00/udp.cpp
index 4395b285d..f2fee5354 100644
--- a/wled00/udp.cpp
+++ b/wled00/udp.cpp
@@ -6,7 +6,7 @@
#define UDP_SEG_SIZE 36
#define SEG_OFFSET (41)
-#define WLEDPACKETSIZE (41+(MAX_NUM_SEGMENTS*UDP_SEG_SIZE)+0)
+#define WLEDPACKETSIZE (41+(WS2812FX::getMaxSegments()*UDP_SEG_SIZE)+0)
#define UDP_IN_MAXSIZE 1472
#define PRESUMED_NETWORK_DELAY 3 //how many ms could it take on avg to reach the receiver? This will be added to transmitted times
@@ -55,7 +55,7 @@ void notify(byte callMode, bool followUp)
//0: old 1: supports white 2: supports secondary color
//3: supports FX intensity, 24 byte packet 4: supports transitionDelay 5: sup palette
//6: supports timebase syncing, 29 byte packet 7: supports tertiary color 8: supports sys time sync, 36 byte packet
- //9: supports sync groups, 37 byte packet 10: supports CCT, 39 byte packet 11: per segment options, variable packet length (40+MAX_NUM_SEGMENTS*3)
+ //9: supports sync groups, 37 byte packet 10: supports CCT, 39 byte packet 11: per segment options, variable packet length (40+WS2812FX::getMaxSegments()*3)
//12: enhanced effect sliders, 2D & mapping options
udpOut[11] = 12;
col = mainseg.colors[1];
@@ -104,7 +104,7 @@ void notify(byte callMode, bool followUp)
udpOut[40] = UDP_SEG_SIZE; //size of each loop iteration (one segment)
size_t s = 0, nsegs = strip.getSegmentsNum();
for (size_t i = 0; i < nsegs; i++) {
- Segment &selseg = strip.getSegment(i);
+ const Segment &selseg = strip.getSegment(i);
if (!selseg.isActive()) continue;
unsigned ofs = 41 + s*UDP_SEG_SIZE; //start of segment offset byte
udpOut[0 +ofs] = s;
@@ -177,7 +177,7 @@ void notify(byte callMode, bool followUp)
memcpy(buffer.data + packetSize, &udpOut[41+i*UDP_SEG_SIZE], UDP_SEG_SIZE);
packetSize += UDP_SEG_SIZE;
if (packetSize + UDP_SEG_SIZE < bufferSize) continue;
- DEBUG_PRINTF_P(PSTR("ESP-NOW sending packet: %d (%d)\n"), (int)buffer.packet, packetSize+3);
+ DEBUG_PRINTF_P(PSTR("ESP-NOW sending packet: %d (%u)\n"), (int)buffer.packet, packetSize+3);
err = quickEspNow.send(ESPNOW_BROADCAST_ADDRESS, reinterpret_cast(&buffer), packetSize+3);
buffer.packet++;
packetSize = 0;
@@ -266,13 +266,13 @@ static void parseNotifyPacket(const uint8_t *udpIn) {
strip.resume();
}
size_t inactiveSegs = 0;
- for (size_t i = 0; i < numSrcSegs && i < strip.getMaxSegments(); i++) {
+ for (size_t i = 0; i < numSrcSegs && i < WS2812FX::getMaxSegments(); i++) {
unsigned ofs = 41 + i*udpIn[40]; //start of segment offset byte
unsigned id = udpIn[0 +ofs];
DEBUG_PRINTF_P(PSTR("UDP segment received: %u\n"), id);
if (id > strip.getSegmentsNum()) break;
else if (id == strip.getSegmentsNum()) {
- if (receiveSegmentBounds && id < strip.getMaxSegments()) strip.appendSegment();
+ if (receiveSegmentBounds && id < WS2812FX::getMaxSegments()) strip.appendSegment();
else break;
}
DEBUG_PRINTF_P(PSTR("UDP segment check: %u\n"), id);
@@ -327,7 +327,7 @@ static void parseNotifyPacket(const uint8_t *udpIn) {
// freeze, reset should never be synced
// LSB to MSB: select, reverse, on, mirror, freeze, reset, reverse_y, mirror_y, transpose, map1d2d (3), ssim (2), set (2)
DEBUG_PRINTF_P(PSTR("Apply options: %u\n"), id);
- selseg.options = (selseg.options & 0b0000000000110001U) | (udpIn[28+ofs]<<8) | (udpIn[9 +ofs] & 0b11001110U); // ignore selected, freeze, reset
+ selseg.options = (selseg.options & 0b0000000000110001U) | ((uint16_t)udpIn[28+ofs]<<8) | (udpIn[9 +ofs] & 0b11001110U); // ignore selected, freeze, reset
if (applyEffects) {
DEBUG_PRINTF_P(PSTR("Apply sliders: %u\n"), id);
selseg.custom1 = udpIn[29+ofs];
@@ -406,31 +406,26 @@ static void parseNotifyPacket(const uint8_t *udpIn) {
stateUpdated(CALL_MODE_NOTIFICATION);
}
+// realtimeLock() is called from UDP notifications, JSON API or serial Ada
void realtimeLock(uint32_t timeoutMs, byte md)
{
if (!realtimeMode && !realtimeOverride) {
- unsigned stop, start;
if (useMainSegmentOnly) {
Segment& mainseg = strip.getMainSegment();
- start = mainseg.start;
- stop = mainseg.stop;
+ mainseg.clear(); // clear entire segment (in case sender transmits less pixels)
mainseg.freeze = true;
// if WLED was off and using main segment only, freeze non-main segments so they stay off
if (bri == 0) {
- for (size_t s = 0; s < strip.getSegmentsNum(); s++) {
- strip.getSegment(s).freeze = true;
- }
+ for (size_t s = 0; s < strip.getSegmentsNum(); s++) strip.getSegment(s).freeze = true;
}
} else {
- start = 0;
- stop = strip.getLengthTotal();
+ // clear entire strip
+ strip.fill(BLACK);
+ }
+ // if strip is off (bri==0) and not already in RTM
+ if (briT == 0) {
+ strip.setBrightness(scaledBri(briLast), true);
}
- // clear strip/segment
- for (size_t i = start; i < stop; i++) strip.setPixelColor(i,BLACK);
- }
- // if strip is off (bri==0) and not already in RTM
- if (briT == 0 && !realtimeMode && !realtimeOverride) {
- strip.setBrightness(scaledBri(briLast), true);
}
if (realtimeTimeout != UINT32_MAX) {
@@ -452,6 +447,7 @@ void exitRealtime() {
realtimeIP[0] = 0;
if (useMainSegmentOnly) { // unfreeze live segment again
strip.getMainSegment().freeze = false;
+ strip.trigger();
} else {
strip.show(); // possible fix for #3589
}
@@ -481,7 +477,8 @@ void handleNotifications()
if (e131NewData && millis() - strip.getLastShow() > 15)
{
e131NewData = false;
- strip.show();
+ if (useMainSegmentOnly) strip.trigger();
+ else strip.show();
}
//unlock strip when realtime UDP times out
@@ -508,13 +505,13 @@ void handleNotifications()
uint8_t lbuf[packetSize];
rgbUdp.read(lbuf, packetSize);
realtimeLock(realtimeTimeoutMs, REALTIME_MODE_HYPERION);
- if (realtimeOverride && !(realtimeMode && useMainSegmentOnly)) return;
+ if (realtimeOverride) return;
unsigned totalLen = strip.getLengthTotal();
- if (useMainSegmentOnly) strip.getMainSegment().beginDraw(); // set up parameters for get/setPixelColor()
for (size_t i = 0, id = 0; i < packetSize -2 && id < totalLen; i += 3, id++) {
setRealtimePixel(id, lbuf[i], lbuf[i+1], lbuf[i+2], 0);
}
- if (!(realtimeMode && useMainSegmentOnly)) strip.show();
+ if (useMainSegmentOnly) strip.trigger();
+ else strip.show();
return;
}
}
@@ -583,7 +580,7 @@ void handleNotifications()
realtimeIP = (isSupp) ? notifier2Udp.remoteIP() : notifierUdp.remoteIP();
realtimeLock(realtimeTimeoutMs, REALTIME_MODE_TPM2NET);
- if (realtimeOverride && !(realtimeMode && useMainSegmentOnly)) return;
+ if (realtimeOverride) return;
tpmPacketCount++; //increment the packet count
if (tpmPacketCount == 1) tpmPayloadFrameSize = (udpIn[2] << 8) + udpIn[3]; //save frame size for the whole payload if this is the first packet
@@ -592,13 +589,13 @@ void handleNotifications()
unsigned id = (tpmPayloadFrameSize/3)*(packetNum-1); //start LED
unsigned totalLen = strip.getLengthTotal();
- if (useMainSegmentOnly) strip.getMainSegment().beginDraw(); // set up parameters for get/setPixelColor()
for (size_t i = 6; i < tpmPayloadFrameSize + 4U && id < totalLen; i += 3, id++) {
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], 0);
}
if (tpmPacketCount == numPackets) { //reset packet count and show if all packets were received
tpmPacketCount = 0;
- strip.show();
+ if (useMainSegmentOnly) strip.trigger();
+ else strip.show();
}
return;
}
@@ -610,17 +607,15 @@ void handleNotifications()
DEBUG_PRINTLN(realtimeIP);
if (packetSize < 2) return;
- if (udpIn[1] == 0)
- {
- realtimeTimeout = 0;
+ if (udpIn[1] == 0) {
+ realtimeTimeout = 0; // cancel realtime mode immediately
return;
} else {
realtimeLock(udpIn[1]*1000 +1, REALTIME_MODE_UDP);
}
- if (realtimeOverride && !(realtimeMode && useMainSegmentOnly)) return;
+ if (realtimeOverride) return;
unsigned totalLen = strip.getLengthTotal();
- if (useMainSegmentOnly) strip.getMainSegment().beginDraw(); // set up parameters for get/setPixelColor()
if (udpIn[0] == 1 && packetSize > 5) //warls
{
for (size_t i = 2; i < packetSize -3; i += 4)
@@ -654,7 +649,8 @@ void handleNotifications()
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3]);
}
}
- strip.show();
+ if (useMainSegmentOnly) strip.trigger();
+ else strip.show();
return;
}
@@ -679,20 +675,7 @@ void handleNotifications()
void setRealtimePixel(uint16_t i, byte r, byte g, byte b, byte w)
{
unsigned pix = i + arlsOffset;
- if (pix < strip.getLengthTotal()) {
- if (!arlsDisableGammaCorrection && gammaCorrectCol) {
- r = gamma8(r);
- g = gamma8(g);
- b = gamma8(b);
- w = gamma8(w);
- }
- uint32_t col = RGBW32(r,g,b,w);
- if (useMainSegmentOnly) {
- strip.getMainSegment().setPixelColor(pix, col); // this expects that strip.getMainSegment().beginDraw() has been called in handleNotification()
- } else {
- strip.setPixelColor(pix, col);
- }
- }
+ strip.setRealtimePixelColor(pix, RGBW32(r,g,b,w));
}
/*********************************************************************************************\
@@ -808,7 +791,7 @@ static size_t sequenceNumber = 0; // this needs to be shared across all ou
static const size_t ART_NET_HEADER_SIZE = 12;
static const byte ART_NET_HEADER[] PROGMEM = {0x41,0x72,0x74,0x2d,0x4e,0x65,0x74,0x00,0x00,0x50,0x00,0x0e};
-uint8_t realtimeBroadcast(uint8_t type, IPAddress client, uint16_t length, const uint8_t* buffer, uint8_t bri, bool isRGBW) {
+uint8_t realtimeBroadcast(uint8_t type, IPAddress client, uint16_t length, const uint8_t *buffer, uint8_t bri, bool isRGBW) {
if (!(apActive || interfacesInited) || !client[0] || !length) return 1; // network not initialised or dummy/unset IP address 031522 ajn added check for ap
WiFiUDP ddpUdp;
@@ -959,14 +942,22 @@ void espNowReceiveCB(uint8_t* address, uint8_t* data, uint8_t len, signed int rs
// usermods hook can override processing
if (UsermodManager::onEspNowMessage(address, data, len)) return;
- // handle WiZ Mote data
- if (data[0] == 0x91 || data[0] == 0x81 || data[0] == 0x80) {
- handleWiZdata(data, len);
+ bool knownRemote = false;
+ for (const auto& mac : linked_remotes) {
+ if (strlen(mac.data()) == 12 && strcmp(last_signal_src, mac.data()) == 0) {
+ knownRemote = true;
+ break;
+ }
+ }
+ if (!knownRemote) {
+ DEBUG_PRINT(F("ESP Now Message Received from Unlinked Sender: "));
+ DEBUG_PRINTLN(last_signal_src);
return;
}
- if (strlen(linked_remote) == 12 && strcmp(last_signal_src, linked_remote) != 0) {
- DEBUG_PRINTLN(F("ESP-NOW unpaired remote sender."));
+ // handle WiZ Mote data
+ if (data[0] == 0x91 || data[0] == 0x81 || data[0] == 0x80) {
+ handleWiZdata(data, len);
return;
}
diff --git a/wled00/um_manager.cpp b/wled00/um_manager.cpp
index 9bfb7e737..1a7cc2269 100644
--- a/wled00/um_manager.cpp
+++ b/wled00/um_manager.cpp
@@ -39,7 +39,13 @@ bool UsermodManager::getUMData(um_data_t **data, uint8_t mod_id) {
return false;
}
void UsermodManager::addToJsonState(JsonObject& obj) { for (auto mod = _usermod_table_begin; mod < _usermod_table_end; ++mod) (*mod)->addToJsonState(obj); }
-void UsermodManager::addToJsonInfo(JsonObject& obj) { for (auto mod = _usermod_table_begin; mod < _usermod_table_end; ++mod) (*mod)->addToJsonInfo(obj); }
+void UsermodManager::addToJsonInfo(JsonObject& obj) {
+ auto um_id_list = obj.createNestedArray("um");
+ for (auto mod = _usermod_table_begin; mod < _usermod_table_end; ++mod) {
+ um_id_list.add((*mod)->getId());
+ (*mod)->addToJsonInfo(obj);
+ }
+}
void UsermodManager::readFromJsonState(JsonObject& obj) { for (auto mod = _usermod_table_begin; mod < _usermod_table_end; ++mod) (*mod)->readFromJsonState(obj); }
void UsermodManager::addToConfig(JsonObject& obj) { for (auto mod = _usermod_table_begin; mod < _usermod_table_end; ++mod) (*mod)->addToConfig(obj); }
bool UsermodManager::readFromConfig(JsonObject& obj) {
diff --git a/wled00/util.cpp b/wled00/util.cpp
index ac8a16207..97e1e3b03 100644
--- a/wled00/util.cpp
+++ b/wled00/util.cpp
@@ -4,17 +4,17 @@
//helper to get int value at a position in string
-int getNumVal(const String* req, uint16_t pos)
+int getNumVal(const String &req, uint16_t pos)
{
- return req->substring(pos+3).toInt();
+ return req.substring(pos+3).toInt();
}
//helper to get int value with in/decrementing support via ~ syntax
-void parseNumber(const char* str, byte* val, byte minv, byte maxv)
+void parseNumber(const char* str, byte &val, byte minv, byte maxv)
{
if (str == nullptr || str[0] == '\0') return;
- if (str[0] == 'r') {*val = hw_random8(minv,maxv?maxv:255); return;} // maxv for random cannot be 0
+ if (str[0] == 'r') {val = hw_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] == '~') {
@@ -22,19 +22,19 @@ void parseNumber(const char* str, byte* val, byte minv, byte maxv)
if (out == 0) {
if (str[1] == '0') return;
if (str[1] == '-') {
- *val = (int)(*val -1) < (int)minv ? maxv : min((int)maxv,(*val -1)); //-1, wrap around
+ 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
+ val = (int)(val +1) > (int)maxv ? minv : max((int)minv,(val +1)); //+1, wrap around
}
} else {
- if (wrap && *val == maxv && out > 0) out = minv;
- else if (wrap && *val == minv && out < 0) out = maxv;
+ if (wrap && val == maxv && out > 0) out = minv;
+ else if (wrap && val == minv && out < 0) out = maxv;
else {
- out += *val;
+ out += val;
if (out > maxv) out = maxv;
if (out < minv) out = minv;
}
- *val = out;
+ val = out;
}
return;
} else if (minv == maxv && minv == 0) { // limits "unset" i.e. both 0
@@ -49,14 +49,14 @@ void parseNumber(const char* str, byte* val, byte minv, byte maxv)
}
}
}
- *val = atoi(str);
+ val = atoi(str);
}
//getVal supports inc/decrementing and random ("X~Y(r|~[w][-][Z])" form)
-bool getVal(JsonVariant elem, byte* val, byte vmin, byte vmax) {
+bool getVal(JsonVariant elem, byte &val, byte vmin, byte vmax) {
if (elem.is()) {
if (elem < 0) return false; //ignore e.g. {"ps":-1}
- *val = elem;
+ val = elem;
return true;
} else if (elem.is()) {
const char* str = elem;
@@ -82,7 +82,7 @@ bool getBoolVal(const JsonVariant &elem, bool dflt) {
}
-bool updateVal(const char* req, const char* key, byte* val, byte minv, byte maxv)
+bool updateVal(const char* req, const char* key, byte &val, byte minv, byte maxv)
{
const char *v = strstr(req, key);
if (v) v += strlen(key);
@@ -619,6 +619,68 @@ int32_t hw_random(int32_t lowerlimit, int32_t upperlimit) {
return hw_random(diff) + lowerlimit;
}
+#ifndef ESP8266
+void *p_malloc(size_t size) {
+ int caps1 = MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT;
+ int caps2 = MALLOC_CAP_DEFAULT | MALLOC_CAP_8BIT;
+ if (psramSafe) {
+ if (heap_caps_get_free_size(caps2) > 3*MIN_HEAP_SIZE && size < 512) std::swap(caps1, caps2); // use DRAM for small alloactions & when heap is plenty
+ return heap_caps_malloc_prefer(size, 2, caps1, caps2); // otherwise prefer PSRAM if it exists
+ }
+ return heap_caps_malloc(size, caps2);
+}
+
+void *p_realloc(void *ptr, size_t size) {
+ int caps1 = MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT;
+ int caps2 = MALLOC_CAP_DEFAULT | MALLOC_CAP_8BIT;
+ if (psramSafe) {
+ if (heap_caps_get_free_size(caps2) > 3*MIN_HEAP_SIZE && size < 512) std::swap(caps1, caps2); // use DRAM for small alloactions & when heap is plenty
+ return heap_caps_realloc_prefer(ptr, size, 2, caps1, caps2); // otherwise prefer PSRAM if it exists
+ }
+ return heap_caps_realloc(ptr, size, caps2);
+}
+
+void *p_calloc(size_t count, size_t size) {
+ int caps1 = MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT;
+ int caps2 = MALLOC_CAP_DEFAULT | MALLOC_CAP_8BIT;
+ if (psramSafe) {
+ if (heap_caps_get_free_size(caps2) > 3*MIN_HEAP_SIZE && size < 512) std::swap(caps1, caps2); // use DRAM for small alloactions & when heap is plenty
+ return heap_caps_calloc_prefer(count, size, 2, caps1, caps2); // otherwise prefer PSRAM if it exists
+ }
+ return heap_caps_calloc(count, size, caps2);
+}
+
+void *d_malloc(size_t size) {
+ int caps1 = MALLOC_CAP_DEFAULT | MALLOC_CAP_8BIT;
+ int caps2 = MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT;
+ if (psramSafe) {
+ if (size > MIN_HEAP_SIZE) std::swap(caps1, caps2); // prefer PSRAM for large alloactions
+ return heap_caps_malloc_prefer(size, 2, caps1, caps2); // otherwise prefer DRAM
+ }
+ return heap_caps_malloc(size, caps1);
+}
+
+void *d_realloc(void *ptr, size_t size) {
+ int caps1 = MALLOC_CAP_DEFAULT | MALLOC_CAP_8BIT;
+ int caps2 = MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT;
+ if (psramSafe) {
+ if (size > MIN_HEAP_SIZE) std::swap(caps1, caps2); // prefer PSRAM for large alloactions
+ return heap_caps_realloc_prefer(ptr, size, 2, caps1, caps2); // otherwise prefer DRAM
+ }
+ return heap_caps_realloc(ptr, size, caps1);
+}
+
+void *d_calloc(size_t count, size_t size) {
+ int caps1 = MALLOC_CAP_DEFAULT | MALLOC_CAP_8BIT;
+ int caps2 = MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT;
+ if (psramSafe) {
+ if (size > MIN_HEAP_SIZE) std::swap(caps1, caps2); // prefer PSRAM for large alloactions
+ return heap_caps_calloc_prefer(count, size, 2, caps1, caps2); // otherwise prefer DRAM
+ }
+ return heap_caps_calloc(count, size, caps1);
+}
+#endif
+
/*
* Fixed point integer based Perlin noise functions by @dedehai
* Note: optimized for speed and to mimic fastled inoise functions, not for accuracy or best randomness
diff --git a/wled00/wled.cpp b/wled00/wled.cpp
index cc338d23f..63af7c2b8 100644
--- a/wled00/wled.cpp
+++ b/wled00/wled.cpp
@@ -529,6 +529,7 @@ void WLED::setup()
void WLED::beginStrip()
{
// Initialize NeoPixel Strip and button
+ strip.setTransition(0); // temporarily prevent transitions to reduce segment copies
strip.finalizeInit(); // busses created during deserializeConfig() if config existed
strip.makeAutoSegments();
strip.setBrightness(0);
@@ -557,6 +558,8 @@ void WLED::beginStrip()
applyPreset(bootPreset, CALL_MODE_INIT);
}
+ strip.setTransition(transitionDelayDefault); // restore transitions
+
// init relay pin
if (rlyPin >= 0) {
pinMode(rlyPin, rlyOpenDrain ? OUTPUT_OPEN_DRAIN : OUTPUT);
@@ -738,9 +741,6 @@ void WLED::initInterfaces()
e131.begin(e131Multicast, e131Port, e131Universe, E131_MAX_UNIVERSE_COUNT);
ddp.begin(false, DDP_DEFAULT_PORT);
reconnectHue();
-#ifndef WLED_DISABLE_MQTT
- initMqtt();
-#endif
interfacesInited = true;
wasConnected = true;
}
@@ -750,7 +750,9 @@ void WLED::handleConnection()
static bool scanDone = true;
static byte stacO = 0;
const unsigned long now = millis();
+ #ifdef WLED_DEBUG
const unsigned long nowS = now/1000;
+ #endif
const bool wifiConfigured = WLED_WIFI_CONFIGURED;
// ignore connection handling if WiFi is configured and scan still running
diff --git a/wled00/wled.h b/wled00/wled.h
index f8dc1252a..e4cab539a 100644
--- a/wled00/wled.h
+++ b/wled00/wled.h
@@ -64,6 +64,9 @@
//This is generally a terrible idea, but improves boot success on boards with a 3.3v regulator + cap setup that can't provide 400mA peaks
//#define WLED_DISABLE_BROWNOUT_DET
+#include
+#include
+
// Library inclusions.
#include
#ifdef ESP8266
@@ -417,7 +420,7 @@ WLED_GLOBAL bool cctICused _INIT(false); // CCT IC used (Athom 15W bulb
#endif
WLED_GLOBAL bool gammaCorrectCol _INIT(true); // use gamma correction on colors
WLED_GLOBAL bool gammaCorrectBri _INIT(false); // use gamma correction on brightness
-WLED_GLOBAL float gammaCorrectVal _INIT(2.8f); // gamma correction value
+WLED_GLOBAL float gammaCorrectVal _INIT(2.2f); // gamma correction value
WLED_GLOBAL byte colPri[] _INIT_N(({ 255, 160, 0, 0 })); // current RGB(W) primary color. colPri[] should be updated if you want to change the color.
WLED_GLOBAL byte colSec[] _INIT_N(({ 0, 0, 0, 0 })); // current RGB(W) secondary color
@@ -538,7 +541,8 @@ WLED_GLOBAL bool serialCanTX _INIT(false);
WLED_GLOBAL bool enableESPNow _INIT(false); // global on/off for ESP-NOW
WLED_GLOBAL byte statusESPNow _INIT(ESP_NOW_STATE_UNINIT); // state of ESP-NOW stack (0 uninitialised, 1 initialised, 2 error)
WLED_GLOBAL bool useESPNowSync _INIT(false); // use ESP-NOW wireless technology for sync
-WLED_GLOBAL char linked_remote[13] _INIT(""); // MAC of ESP-NOW remote (Wiz Mote)
+//WLED_GLOBAL char linked_remote[13] _INIT(""); // MAC of ESP-NOW remote (Wiz Mote)
+WLED_GLOBAL std::vector> linked_remotes; // MAC of ESP-NOW remotes (Wiz Mote)
WLED_GLOBAL char last_signal_src[13] _INIT(""); // last seen ESP-NOW sender
#endif
@@ -584,7 +588,11 @@ WLED_GLOBAL bool otaLock _INIT(true); // prevents OTA firmware update
WLED_GLOBAL bool otaLock _INIT(false); // prevents OTA firmware updates without password. ALWAYS enable if system exposed to any public networks
#endif
WLED_GLOBAL bool wifiLock _INIT(false); // prevents access to WiFi settings when OTA lock is enabled
+#ifndef WLED_DISABLE_OTA
WLED_GLOBAL bool aOtaEnabled _INIT(true); // ArduinoOTA allows easy updates directly from the IDE. Careful, it does not auto-disable when OTA lock is on
+#else
+WLED_GLOBAL bool aOtaEnabled _INIT(false); // ArduinoOTA allows easy updates directly from the IDE. Careful, it does not auto-disable when OTA lock is on
+#endif
WLED_GLOBAL char settingsPIN[5] _INIT(WLED_PIN); // PIN for settings pages
WLED_GLOBAL bool correctPIN _INIT(!strlen(settingsPIN));
WLED_GLOBAL unsigned long lastEditTime _INIT(0);
@@ -602,6 +610,8 @@ WLED_GLOBAL bool wasConnected _INIT(false);
// color
WLED_GLOBAL byte lastRandomIndex _INIT(0); // used to save last random color so the new one is not the same
+WLED_GLOBAL std::vector customPalettes; // custom palettes
+WLED_GLOBAL uint8_t paletteBlend _INIT(0); // determines blending and wrapping of palette: 0: blend, wrap if moving (SEGMENT.speed>0); 1: blend, always wrap; 2: blend, never wrap; 3: don't blend or wrap
// transitions
WLED_GLOBAL uint8_t blendingStyle _INIT(0); // effect blending/transitionig style
@@ -612,6 +622,7 @@ WLED_GLOBAL unsigned long transitionStartTime;
WLED_GLOBAL bool jsonTransitionOnce _INIT(false); // flag to override transitionDelay (playlist, JSON API: "live" & "seg":{"i"} & "tt")
WLED_GLOBAL uint8_t randomPaletteChangeTime _INIT(5); // amount of time [s] between random palette changes (min: 1s, max: 255s)
WLED_GLOBAL bool useHarmonicRandomPalette _INIT(true); // use *harmonic* random palette generation (nicer looking) or truly random
+WLED_GLOBAL bool useRainbowWheel _INIT(false); // use "rainbow" color wheel instead of "spectrum" color wheel
// nightlight
WLED_GLOBAL bool nightlightActive _INIT(false);
diff --git a/wled00/wled_eeprom.cpp b/wled00/wled_eeprom.cpp
index d0451d9a9..fb63bc646 100644
--- a/wled00/wled_eeprom.cpp
+++ b/wled00/wled_eeprom.cpp
@@ -225,7 +225,7 @@ void loadSettingsFromEEPROM()
if (lastEEPROMversion > 7)
{
//strip.paletteFade = EEPROM.read(374);
- strip.paletteBlend = EEPROM.read(382);
+ paletteBlend = EEPROM.read(382);
for (int i = 0; i < 8; ++i)
{
diff --git a/wled00/wled_server.cpp b/wled00/wled_server.cpp
index 06750838f..c7a4cc003 100644
--- a/wled00/wled_server.cpp
+++ b/wled00/wled_server.cpp
@@ -176,7 +176,7 @@ static void handleUpload(AsyncWebServerRequest *request, const String& filename,
doReboot = true;
request->send(200, FPSTR(CONTENT_TYPE_PLAIN), F("Configuration restore successful.\nRebooting..."));
} else {
- if (filename.indexOf(F("palette")) >= 0 && filename.indexOf(F(".json")) >= 0) strip.loadCustomPalettes();
+ if (filename.indexOf(F("palette")) >= 0 && filename.indexOf(F(".json")) >= 0) loadCustomPalettes();
request->send(200, FPSTR(CONTENT_TYPE_PLAIN), F("File Uploaded!"));
}
cacheInvalidate++;
@@ -365,7 +365,6 @@ void initServer()
createEditHandler(correctPIN);
static const char _update[] PROGMEM = "/update";
-#ifndef WLED_DISABLE_OTA
//init ota page
server.on(_update, HTTP_GET, [](AsyncWebServerRequest *request){
if (otaLock) {
@@ -419,12 +418,6 @@ void initServer()
}
}
});
-#else
- server.on(_update, HTTP_GET, [](AsyncWebServerRequest *request){
- serveMessage(request, 501, FPSTR(s_notimplemented), F("OTA updating is disabled in this build."), 254);
- });
-#endif
-
#ifdef WLED_ENABLE_DMX
server.on(F("/dmxmap"), HTTP_GET, [](AsyncWebServerRequest *request){
diff --git a/wled00/xml.cpp b/wled00/xml.cpp
index de2f5590d..a3cf6fe42 100644
--- a/wled00/xml.cpp
+++ b/wled00/xml.cpp
@@ -216,7 +216,11 @@ void getSettingsJS(byte subPage, Print& settingsScript)
#ifndef WLED_DISABLE_ESPNOW
printSetFormCheckbox(settingsScript,PSTR("RE"),enableESPNow);
- printSetFormValue(settingsScript,PSTR("RMAC"),linked_remote);
+ settingsScript.printf_P(PSTR("rstR();")); // reset remote list
+ for (size_t i = 0; i < linked_remotes.size(); i++) {
+ settingsScript.printf_P(PSTR("aR(\"RM%u\",\"%s\");"), i, linked_remotes[i].data()); // add remote to list
+ }
+ settingsScript.print(F("tE();")); // fill fields
#else
//hide remote settings if not compiled
settingsScript.print(F("toggle('ESPNOW');")); // hide ESP-NOW setting
@@ -258,10 +262,6 @@ void getSettingsJS(byte subPage, Print& settingsScript)
#ifndef WLED_DISABLE_ESPNOW
if (strlen(last_signal_src) > 0) { //Have seen an ESP-NOW Remote
printSetClassElementHTML(settingsScript,PSTR("rlid"),0,last_signal_src);
- } else if (!enableESPNow) {
- printSetClassElementHTML(settingsScript,PSTR("rlid"),0,(char*)F("(Enable ESP-NOW to listen)"));
- } else {
- printSetClassElementHTML(settingsScript,PSTR("rlid"),0,(char*)F("None"));
}
#endif
}
@@ -291,12 +291,11 @@ void getSettingsJS(byte subPage, Print& settingsScript)
printSetFormValue(settingsScript,PSTR("CB"),Bus::getCCTBlend());
printSetFormValue(settingsScript,PSTR("FR"),strip.getTargetFps());
printSetFormValue(settingsScript,PSTR("AW"),Bus::getGlobalAWMode());
- printSetFormCheckbox(settingsScript,PSTR("LD"),useGlobalLedBuffer);
printSetFormCheckbox(settingsScript,PSTR("PR"),BusManager::hasParallelOutput()); // get it from bus manager not global variable
unsigned sumMa = 0;
- for (int s = 0; s < BusManager::getNumBusses(); s++) {
- const Bus* bus = BusManager::getBus(s);
+ for (size_t s = 0; s < BusManager::getNumBusses(); s++) {
+ const Bus *bus = BusManager::getBus(s);
if (!bus || !bus->isOk()) break; // should not happen but for safety
int offset = s < 10 ? '0' : 'A' - 10;
char lp[4] = "L0"; lp[2] = offset+s; lp[3] = 0; //ascii 0-9 //strip data pin
@@ -380,7 +379,8 @@ void getSettingsJS(byte subPage, Print& settingsScript)
printSetFormValue(settingsScript,PSTR("TB"),nightlightTargetBri);
printSetFormValue(settingsScript,PSTR("TL"),nightlightDelayMinsDefault);
printSetFormValue(settingsScript,PSTR("TW"),nightlightMode);
- printSetFormIndex(settingsScript,PSTR("PB"),strip.paletteBlend);
+ printSetFormIndex(settingsScript,PSTR("PB"),paletteBlend);
+ printSetFormCheckbox(settingsScript,PSTR("RW"),useRainbowWheel);
printSetFormValue(settingsScript,PSTR("RL"),rlyPin);
printSetFormCheckbox(settingsScript,PSTR("RM"),rlyMde);
printSetFormCheckbox(settingsScript,PSTR("RO"),rlyOpenDrain);
@@ -595,6 +595,10 @@ void getSettingsJS(byte subPage, Print& settingsScript)
snprintf_P(tmp_buf,sizeof(tmp_buf),PSTR("WLED %s (build %d)"),versionString,VERSION);
printSetClassElementHTML(settingsScript,PSTR("sip"),0,tmp_buf);
settingsScript.printf_P(PSTR("sd=\"%s\";"), serverDescription);
+ #ifdef WLED_DISABLE_OTA
+ //hide settings if not compiled
+ settingsScript.print(F("toggle('aOTA');")); // hide ArduinoOTA checkbox
+ #endif
}
#ifdef WLED_ENABLE_DMX // include only if DMX is enabled
@@ -666,16 +670,14 @@ void getSettingsJS(byte subPage, Print& settingsScript)
#ifndef WLED_DISABLE_2D
settingsScript.printf_P(PSTR("maxPanels=%d;resetPanels();"),WLED_MAX_PANELS);
if (strip.isMatrix) {
- if(strip.panels>0){
- printSetFormValue(settingsScript,PSTR("PW"),strip.panel[0].width); //Set generator Width and Height to first panel size for convenience
- printSetFormValue(settingsScript,PSTR("PH"),strip.panel[0].height);
- }
- printSetFormValue(settingsScript,PSTR("MPC"),strip.panels);
+ printSetFormValue(settingsScript,PSTR("PW"),strip.panel.size()>0?strip.panel[0].width:8); //Set generator Width and Height to first panel size for convenience
+ printSetFormValue(settingsScript,PSTR("PH"),strip.panel.size()>0?strip.panel[0].height:8);
+ printSetFormValue(settingsScript,PSTR("MPC"),strip.panel.size());
// panels
- for (unsigned i=0; i