From f21ab3588d797e0de38fce58e0670a00fdde9775 Mon Sep 17 00:00:00 2001 From: Blaz Kristan Date: Fri, 29 Mar 2024 16:43:37 +0100 Subject: [PATCH] Individual color channel control for JSON API - fixes #3860 - debug verbose - PSRAM detection --- wled00/FX_fcn.cpp | 26 +++----------------------- wled00/json.cpp | 40 +++++++++++++++++++++++++++------------- wled00/wled.cpp | 8 ++++++-- 3 files changed, 36 insertions(+), 38 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 766c71e597..f97268f9ba 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -1205,7 +1205,6 @@ void WS2812FX::service() { seg.next_time = nowUp + delay; } -// if (_segment_index == _queuedChangesSegId) setUpSegmentFromQueuedChanges(); _segment_index++; } _virtualSegmentLength = 0; @@ -1213,7 +1212,7 @@ void WS2812FX::service() { _triggered = false; #ifdef WLED_DEBUG - if (millis() - nowUp > _frametime) DEBUG_PRINTLN(F("Slow effects.")); + if (millis() - nowUp > _frametime) DEBUG_PRINTF_P(PSTR("Slow effects %u/%d.\n"), (unsigned)(millis()-nowUp), (int)_frametime); #endif if (doShow) { yield(); @@ -1221,7 +1220,7 @@ void WS2812FX::service() { show(); } #ifdef WLED_DEBUG - if (millis() - nowUp > _frametime) DEBUG_PRINTLN(F("Slow strip.")); + if (millis() - nowUp > _frametime) DEBUG_PRINTF_P(PSTR("Slow strip %u/%d.\n"), (unsigned)(millis()-nowUp), (int)_frametime); #endif } @@ -1431,31 +1430,12 @@ void WS2812FX::setSegment(uint8_t segId, uint16_t i1, uint16_t i2, uint8_t group appendSegment(Segment(0, strip.getLengthTotal())); segId = getSegmentsNum()-1; // segments are added at the end of list } -/* - if (_queuedChangesSegId == segId) _queuedChangesSegId = 255; // cancel queued change if already queued for this segment - - if (segId < getMaxSegments() && segId == getCurrSegmentId() && isServicing()) { // queue change to prevent concurrent access - // queuing a change for a second segment will lead to the loss of the first change if not yet applied - // however this is not a problem as the queued change is applied immediately after the effect function in that segment returns - _qStart = i1; _qStop = i2; _qStartY = startY; _qStopY = stopY; - _qGrouping = grouping; _qSpacing = spacing; _qOffset = offset; - _queuedChangesSegId = segId; - DEBUG_PRINT(F("Segment queued: ")); DEBUG_PRINTLN(segId); - return; // queued changes are applied immediately after effect function returns - } -*/ suspend(); _segments[segId].setUp(i1, i2, grouping, spacing, offset, startY, stopY); resume(); if (segId > 0 && segId == getSegmentsNum()-1 && i2 <= i1) _segments.pop_back(); // if last segment was deleted remove it from vector } -/* -void WS2812FX::setUpSegmentFromQueuedChanges() { - if (_queuedChangesSegId >= getSegmentsNum()) return; - _segments[_queuedChangesSegId].setUp(_qStart, _qStop, _qGrouping, _qSpacing, _qOffset, _qStartY, _qStopY); - _queuedChangesSegId = 255; -} -*/ + void WS2812FX::resetSegments() { _segments.clear(); // destructs all Segment as part of clearing #ifndef WLED_DISABLE_2D diff --git a/wled00/json.cpp b/wled00/json.cpp index 02eb22ba49..fd1527a219 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -142,28 +142,42 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId) { if (seg.getLightCapabilities() & 3) { // segment has RGB or White - for (size_t i = 0; i < 3; i++) - { + for (size_t i = 0; i < NUM_COLORS; i++) { + // JSON "col" array can contain the following values for each of segment's colors (primary, background, custom): + // "col":[int|string|object|array, int|string|object|array, int|string|object|array] + // int = Kelvin temperature or 0 for black + // string = hex representation of [WW]RRGGBB + // object = individual channel control {"r":0,"g":127,"b":255,"w":255}, each being optional (valid to send {}) + // array = direct channel values [r,g,b,w] (w element being optional) int rgbw[] = {0,0,0,0}; bool colValid = false; JsonArray colX = colarr[i]; if (colX.isNull()) { - byte brgbw[] = {0,0,0,0}; - const char* hexCol = colarr[i]; - if (hexCol == nullptr) { //Kelvin color temperature (or invalid), e.g 2400 - int kelvin = colarr[i] | -1; - if (kelvin < 0) continue; - if (kelvin == 0) seg.setColor(i, 0); - if (kelvin > 0) colorKtoRGB(kelvin, brgbw); + JsonObject oCol = colarr[i]; + if (!oCol.isNull()) { + // we have a JSON object for color {"w":123,"r":123,...}; allows individual channel control + rgbw[0] = oCol["r"] | R(seg.colors[i]); + rgbw[1] = oCol["g"] | G(seg.colors[i]); + rgbw[2] = oCol["b"] | B(seg.colors[i]); + rgbw[3] = oCol["w"] | W(seg.colors[i]); colValid = true; - } else { //HEX string, e.g. "FFAA00" - colValid = colorFromHexString(brgbw, hexCol); + } else { + byte brgbw[] = {0,0,0,0}; + const char* hexCol = colarr[i]; + if (hexCol == nullptr) { //Kelvin color temperature (or invalid), e.g 2400 + int kelvin = colarr[i] | -1; + if (kelvin < 0) continue; + if (kelvin == 0) seg.setColor(i, 0); + if (kelvin > 0) colorKtoRGB(kelvin, brgbw); + colValid = true; + } else { //HEX string, e.g. "FFAA00" + colValid = colorFromHexString(brgbw, hexCol); + } + for (size_t c = 0; c < 4; c++) rgbw[c] = brgbw[c]; } - for (size_t c = 0; c < 4; c++) rgbw[c] = brgbw[c]; } else { //Array of ints (RGB or RGBW color), e.g. [255,160,0] byte sz = colX.size(); if (sz == 0) continue; //do nothing on empty array - copyArray(colX, rgbw, 4); colValid = true; } diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 7b753da3b4..c64ea935c3 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -241,9 +241,10 @@ void WLED::loop() DEBUG_PRINT(F("Unix time: ")); toki.printTime(toki.getTime()); DEBUG_PRINT(F("Free heap: ")); DEBUG_PRINTLN(ESP.getFreeHeap()); #if defined(ARDUINO_ARCH_ESP32) - if (psramSafe && psramFound()) { + if (psramFound()) { DEBUG_PRINT(F("Total PSRAM: ")); DEBUG_PRINT(ESP.getPsramSize()/1024); DEBUG_PRINTLN("kB"); DEBUG_PRINT(F("Free PSRAM: ")); DEBUG_PRINT(ESP.getFreePsram()/1024); DEBUG_PRINTLN("kB"); + if (!psramSafe) DEBUG_PRINTLN(F("Not using PSRAM.")); } #endif DEBUG_PRINT(F("Wifi state: ")); DEBUG_PRINTLN(WiFi.status()); @@ -369,10 +370,12 @@ void WLED::setup() #if defined(ARDUINO_ARCH_ESP32) #ifndef BOARD_HAS_PSRAM if (psramFound() && ESP.getChipRevision() < 3) psramSafe = false; + if (!psramSafe) DEBUG_PRINTLN(F("Not using PSRAM.")); #endif pDoc = new PSRAMDynamicJsonDocument((psramSafe && psramFound() ? 2 : 1)*JSON_BUFFER_SIZE); + DEBUG_PRINT(F("JSON buffer allocated: ")); DEBUG_PRINTLN((psramSafe && psramFound() ? 2 : 1)*JSON_BUFFER_SIZE); // if the above fails requestJsonBufferLock() will always return false preventing crashes - if (psramSafe && psramFound()) { + if (psramFound()) { DEBUG_PRINT(F("Total PSRAM: ")); DEBUG_PRINT(ESP.getPsramSize()/1024); DEBUG_PRINTLN("kB"); DEBUG_PRINT(F("Free PSRAM : ")); DEBUG_PRINT(ESP.getFreePsram()/1024); DEBUG_PRINTLN("kB"); } @@ -423,6 +426,7 @@ void WLED::setup() DEBUG_PRINTLN(F("Reading config")); deserializeConfigFromFS(); + DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap()); #if defined(STATUSLED) && STATUSLED>=0 if (!pinManager.isPinAllocated(STATUSLED)) {