diff --git a/wled00/FX.h b/wled00/FX.h index 7ea54fe9..a8ae9e66 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -657,7 +657,6 @@ class WS2812FX { setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0), show(void), setTargetFps(uint8_t fps), - setPixelSegment(uint8_t n), deserializeMap(uint8_t n=0); bool @@ -688,6 +687,7 @@ class WS2812FX { //getFirstSelectedSegment(void), getMainSegmentId(void), getTargetFps(void), + setPixelSegment(uint8_t n), gamma8(uint8_t), gamma8_cal(uint8_t, float), sin_gap(uint16_t), diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index d7b39645..765e4915 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -135,7 +135,7 @@ void WS2812FX::service() { uint16_t delay = FRAMETIME; if (!SEGMENT.getOption(SEG_OPTION_FREEZE)) { //only run effect function if not frozen - _virtualSegmentLength = SEGMENT.virtualLength(); + SEGLEN = SEGMENT.virtualLength(); _bri_t = SEGMENT.opacity; _colors_t[0] = SEGMENT.colors[0]; _colors_t[1] = SEGMENT.colors[1]; _colors_t[2] = SEGMENT.colors[2]; uint8_t _cct_t = SEGMENT.cct; if (!IS_SEGMENT_ON) _bri_t = 0; @@ -156,7 +156,7 @@ void WS2812FX::service() { SEGENV.next_time = nowUp + delay; } } - _virtualSegmentLength = 0; + SEGLEN = 0; busses.setSegmentCCT(-1); if(doShow) { yield(); @@ -716,36 +716,16 @@ bool WS2812FX::checkSegmentAlignment() { } //After this function is called, setPixelColor() will use that segment (offsets, grouping, ... will apply) -//Note: If called in an interrupt (e.g. JSON API), it must be reset with "setPixelColor(255)", +//Note: If called in an interrupt (e.g. JSON API), original segment must be restored, //otherwise it can lead to a crash on ESP32 because _segment_index is modified while in use by the main thread -#ifdef ARDUINO_ARCH_ESP32 -uint8_t _segment_index_prev = 0; -uint16_t _virtualSegmentLength_prev = 0; -bool _ps_set = false; -#endif - -void WS2812FX::setPixelSegment(uint8_t n) +uint8_t WS2812FX::setPixelSegment(uint8_t n) { + uint8_t prevSegId = _segment_index; if (n < MAX_NUM_SEGMENTS) { - #ifdef ARDUINO_ARCH_ESP32 - if (!_ps_set) { - _segment_index_prev = _segment_index; - _virtualSegmentLength_prev = _virtualSegmentLength; - _ps_set = true; - } - #endif _segment_index = n; - _virtualSegmentLength = SEGMENT.virtualLength(); - } else { - _virtualSegmentLength = 0; - #ifdef ARDUINO_ARCH_ESP32 - if (_ps_set) { - _segment_index = _segment_index_prev; - _virtualSegmentLength = _virtualSegmentLength_prev; - _ps_set = false; - } - #endif + SEGLEN = SEGMENT.virtualLength(); } + return prevSegId; } void WS2812FX::setRange(uint16_t i, uint16_t i2, uint32_t col) diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index ca3215c8..709aefc8 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -138,7 +138,6 @@ void serializeState(JsonObject root, bool forPreset = false, bool includeBri = t void serializeInfo(JsonObject root); void serializeModeNames(JsonArray arr, const char *qstring); void serializeModeData(JsonObject root); -uint8_t extractModeName(uint8_t mode, const char *src, char *dest, uint8_t maxLen); void serveJson(AsyncWebServerRequest* request); bool serveLiveLeds(AsyncWebServerRequest* request, uint32_t wsClient = 0); @@ -283,6 +282,7 @@ void _setRandomColor(bool _sec,bool fromButton=false); bool isAsterisksOnly(const char* str, byte maxLen); bool requestJSONBufferLock(uint8_t module=255); void releaseJSONBufferLock(); +uint8_t extractModeName(uint8_t mode, const char *src, char *dest, uint8_t maxLen); //wled_eeprom.cpp void applyMacro(byte index); diff --git a/wled00/json.cpp b/wled00/json.cpp index 8dcdd902..d96796f9 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -174,7 +174,7 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId) JsonArray iarr = elem[F("i")]; //set individual LEDs if (!iarr.isNull()) { - strip.setPixelSegment(id); + uint8_t oldSegId = strip.setPixelSegment(id); //freeze and init to black if (!seg.getOption(SEG_OPTION_FREEZE)) { @@ -220,7 +220,7 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId) set = 0; } } - strip.setPixelSegment(255); + strip.setPixelSegment(oldSegId); strip.trigger(); } else if (!elem["frz"] && iarr.isNull()) { //return to regular effect seg.setOption(SEG_OPTION_FREEZE, false); @@ -874,41 +874,6 @@ void serializeModeNames(JsonArray arr, const char *qstring) { } } -// extracts effect mode (or palette) name from names serialized string -// caller must provide large enough buffer! -uint8_t extractModeName(uint8_t mode, const char *src, char *dest, uint8_t maxLen) -{ - uint8_t qComma = 0; - bool insideQuotes = false; - uint8_t printedChars = 0; - char singleJsonSymbol; - size_t len = strlen_P(src); - - // Find the mode name in JSON - for (size_t i = 0; i < len; i++) { - singleJsonSymbol = pgm_read_byte_near(src + i); - if (singleJsonSymbol == '\0') break; - switch (singleJsonSymbol) { - case '"': - insideQuotes = !insideQuotes; - break; - case '[': - case ']': - break; - case ',': - if (!insideQuotes) qComma++; - default: - if (!insideQuotes || (qComma != mode)) break; - dest[printedChars++] = singleJsonSymbol; - } - if ((qComma > mode) || (printedChars >= maxLen)) break; - } - dest[printedChars] = '\0'; - char *pos = strchr(dest,'@'); - if (pos) *pos = '\0'; - return strlen(dest); -} - void serveJson(AsyncWebServerRequest* request) { byte subJson = 0; @@ -925,14 +890,16 @@ void serveJson(AsyncWebServerRequest* request) } else if (url.indexOf(F("eff")) > 0) { // this is going to serve raw effect names which will include WLED-SR extensions in names - request->send_P(200, "application/json", JSON_mode_names); - // if we want parsed effect names use this (warning, this will prevent UI from receiving this extension making it useless) - //AsyncJsonResponse* response = new AsyncJsonResponse(JSON_BUFFER_SIZE, true); // array document - //JsonArray doc = response->getRoot(); - //deserializeModeNames(doc, JSON_mode_names); // remove WLED-SR extensions from effect names - //response->setLength(); - //request->send(response); - //delete response; + if (requestJSONBufferLock(19)) { + AsyncJsonResponse* response = new AsyncJsonResponse(&doc, true); // array document + JsonArray lDoc = response->getRoot(); + serializeModeNames(lDoc, JSON_mode_names); // remove WLED-SR extensions from effect names + response->setLength(); + request->send(response); + releaseJSONBufferLock(); + } else { + request->send_P(200, "application/json", JSON_mode_names); + } return; } else if (url.indexOf("pal") > 0) { diff --git a/wled00/util.cpp b/wled00/util.cpp index d18902af..ce9d16ac 100644 --- a/wled00/util.cpp +++ b/wled00/util.cpp @@ -231,3 +231,41 @@ void releaseJSONBufferLock() fileDoc = nullptr; jsonBufferLock = 0; } + + +// extracts effect mode (or palette) name from names serialized string +// caller must provide large enough buffer! +uint8_t extractModeName(uint8_t mode, const char *src, char *dest, uint8_t maxLen) +{ + uint8_t qComma = 0; + bool insideQuotes = false; + uint8_t printedChars = 0; + char singleJsonSymbol; + size_t len = strlen_P(src); + + // Find the mode name in JSON + for (size_t i = 0; i < len; i++) { + singleJsonSymbol = pgm_read_byte_near(src + i); + if (singleJsonSymbol == '\0') break; + if (singleJsonSymbol == '@' && insideQuotes && qComma == mode) break; //stop when SR extension encountered + switch (singleJsonSymbol) { + case '"': + insideQuotes = !insideQuotes; + break; + case '[': + case ']': + break; + case ',': + if (!insideQuotes) qComma++; + default: + if (!insideQuotes || (qComma != mode)) break; + dest[printedChars++] = singleJsonSymbol; + break; + } + if ((qComma > mode) || (printedChars >= maxLen)) break; + } + dest[printedChars] = '\0'; + //char *pos = strchr(dest,'@'); + //if (pos) *pos = '\0'; + return strlen(dest); +} diff --git a/wled00/wled.h b/wled00/wled.h index e9d2ef1d..5930afeb 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -8,7 +8,7 @@ */ // version code in format yymmddb (b = daily build) -#define VERSION 2201281 +#define VERSION 2201311 //uncomment this if you have a "my_config.h" file you'd like to use //#define WLED_USE_MY_CONFIG