From 7138e891bea322262593b1736f2cc652eb418374 Mon Sep 17 00:00:00 2001 From: Christian Schwinne Date: Sun, 20 Feb 2022 00:20:22 +0100 Subject: [PATCH] Add per-segment light capability info (#2552) * Add per-segment light capability info * Fix duplication * Change to more lightweight seglc array * Added segment capabilities. * Differs and capabilities refactoring * Add back selection differs option Co-authored-by: Blaz Kristan --- wled00/FX.h | 32 ++++------------- wled00/FX_fcn.cpp | 88 +++++++++++++++++++++++++++++++++++++++++++++-- wled00/const.h | 2 +- wled00/json.cpp | 17 +++++++-- 4 files changed, 108 insertions(+), 31 deletions(-) diff --git a/wled00/FX.h b/wled00/FX.h index 657d79ee..d92967f3 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -334,28 +334,8 @@ class WS2812FX { vLength = (vLength + 1) /2; // divide by 2 if mirror, leave at least a single LED return vLength; } - uint8_t differs(Segment& b) { - uint8_t d = 0; - if (start != b.start) d |= SEG_DIFFERS_BOUNDS; - if (stop != b.stop) d |= SEG_DIFFERS_BOUNDS; - if (offset != b.offset) d |= SEG_DIFFERS_GSO; - if (grouping != b.grouping) d |= SEG_DIFFERS_GSO; - if (spacing != b.spacing) d |= SEG_DIFFERS_GSO; - if (opacity != b.opacity) d |= SEG_DIFFERS_BRI; - if (mode != b.mode) d |= SEG_DIFFERS_FX; - if (speed != b.speed) d |= SEG_DIFFERS_FX; - if (intensity != b.intensity) d |= SEG_DIFFERS_FX; - if (palette != b.palette) d |= SEG_DIFFERS_FX; - - if ((options & 0b00101110) != (b.options & 0b00101110)) d |= SEG_DIFFERS_OPT; - if ((options & 0x01) != (b.options & 0x01)) d |= SEG_DIFFERS_SEL; - for (uint8_t i = 0; i < NUM_COLORS; i++) - { - if (colors[i] != b.colors[i]) d |= SEG_DIFFERS_COL; - } - - return d; - } + uint8_t differs(Segment& b); + uint8_t getLightCapabilities(); } segment; // segment runtime parameters @@ -653,7 +633,7 @@ class WS2812FX { setMainSegmentId(uint8_t n), restartRuntime(), resetSegments(), - makeAutoSegments(), + makeAutoSegments(bool forceReset = false), fixInvalidSegments(), setPixelColor(uint16_t n, uint32_t c), setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0), @@ -665,7 +645,8 @@ class WS2812FX { gammaCorrectBri = false, gammaCorrectCol = true, checkSegmentAlignment(void), - hasCCTBus(void), + hasRGBWBus(void), + hasCCTBus(void), // return true if the strip is being sent pixel updates isUpdating(void); @@ -680,7 +661,8 @@ class WS2812FX { getMaxSegments(void), getActiveSegmentsNum(void), getMainSegmentId(void), - getTargetFps(void), + getLastActiveSegmentId(void), + getTargetFps(void), setPixelSegment(uint8_t n), gamma8(uint8_t), gamma8_cal(uint8_t, float), diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index a59da9ad..ccc0f6e7 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -460,6 +460,13 @@ uint8_t WS2812FX::getMainSegmentId(void) { return _mainSegment; } +uint8_t WS2812FX::getLastActiveSegmentId(void) { + for (uint8_t i = MAX_NUM_SEGMENTS -1; i > 0; i--) { + if (_segments[i].isActive()) return i; + } + return 0; +} + uint8_t WS2812FX::getActiveSegmentsNum(void) { uint8_t c = 0; for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) @@ -520,6 +527,77 @@ uint16_t WS2812FX::getLengthPhysical(void) { return len; } +uint8_t WS2812FX::Segment::differs(Segment& b) { + uint8_t d = 0; + if (start != b.start) d |= SEG_DIFFERS_BOUNDS; + if (stop != b.stop) d |= SEG_DIFFERS_BOUNDS; + if (offset != b.offset) d |= SEG_DIFFERS_GSO; + if (grouping != b.grouping) d |= SEG_DIFFERS_GSO; + if (spacing != b.spacing) d |= SEG_DIFFERS_GSO; + if (opacity != b.opacity) d |= SEG_DIFFERS_BRI; + if (mode != b.mode) d |= SEG_DIFFERS_FX; + if (speed != b.speed) d |= SEG_DIFFERS_FX; + if (intensity != b.intensity) d |= SEG_DIFFERS_FX; + if (palette != b.palette) d |= SEG_DIFFERS_FX; + + if ((options & 0b00101110) != (b.options & 0b00101110)) d |= SEG_DIFFERS_OPT; + if ((options & 0x01) != (b.options & 0x01)) d |= SEG_DIFFERS_SEL; + + for (uint8_t i = 0; i < NUM_COLORS; i++) + { + if (colors[i] != b.colors[i]) d |= SEG_DIFFERS_COL; + } + + return d; +} + +uint8_t WS2812FX::Segment::getLightCapabilities() { + if (!isActive()) return 0; + uint8_t capabilities = 0; + uint8_t awm = Bus::getAutoWhiteMode(); + bool whiteSlider = (awm == RGBW_MODE_DUAL || awm == RGBW_MODE_MANUAL_ONLY); + + for (uint8_t b = 0; b < busses.getNumBusses(); b++) { + Bus *bus = busses.getBus(b); + if (bus == nullptr || bus->getLength()==0) break; + if (bus->getStart() >= stop) continue; + if (bus->getStart() + bus->getLength() <= start) continue; + + uint8_t type = bus->getType(); + if (!whiteSlider || (type != TYPE_ANALOG_1CH && (cctFromRgb || type != TYPE_ANALOG_2CH))) + { + capabilities |= 0x01; //segment supports RGB (full color) + } + if (bus->isRgbw() && whiteSlider) capabilities |= 0x02; //segment supports white channel + if (!cctFromRgb) { + switch (type) { + case TYPE_ANALOG_5CH: + case TYPE_ANALOG_2CH: + capabilities |= 0x04; //segment supports white CCT + } + } + if (correctWB && type != TYPE_ANALOG_1CH) capabilities |= 0x04; //white balance correction (uses CCT slider) + } + return capabilities; +} + +//used for JSON API info.leds.rgbw. Little practical use, deprecate with info.leds.rgbw. +//returns if there is an RGBW bus (supports RGB and White, not only white) +//not influenced by auto-white mode, also true if white slider does not affect output white channel +bool WS2812FX::hasRGBWBus(void) { + for (uint8_t b = 0; b < busses.getNumBusses(); b++) { + Bus *bus = busses.getBus(b); + if (bus == nullptr || bus->getLength()==0) break; + switch (bus->getType()) { + case TYPE_SK6812_RGBW: + case TYPE_TM1814: + case TYPE_ANALOG_4CH: + return true; + } + } + return false; +} + bool WS2812FX::hasCCTBus(void) { if (cctFromRgb && !correctWB) return false; for (uint8_t b = 0; b < busses.getNumBusses(); b++) { @@ -604,7 +682,7 @@ void WS2812FX::resetSegments() { _segment_runtimes[0].markForReset(); } -void WS2812FX::makeAutoSegments() { +void WS2812FX::makeAutoSegments(bool forceReset) { if (autoSegments) { //make one segment per bus uint16_t segStarts[MAX_NUM_SEGMENTS] = {0}; uint16_t segStops [MAX_NUM_SEGMENTS] = {0}; @@ -630,8 +708,14 @@ void WS2812FX::makeAutoSegments() { setSegment(i, segStarts[i], segStops[i]); } } else { - //expand the main seg to the entire length, but only if there are no other segments + //expand the main seg to the entire length, but only if there are no other segments, or reset is forced uint8_t mainSeg = getMainSegmentId(); + + if (forceReset) { + for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) { + setSegment(i, 0, 0); + } + } if (getActiveSegmentsNum() < 2) { setSegment(mainSeg, 0, _length); diff --git a/wled00/const.h b/wled00/const.h index 6e411abd..d1e021e7 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -306,7 +306,7 @@ // Size of buffer for API JSON object (increase for more segments) #ifdef ESP8266 - #define JSON_BUFFER_SIZE 9216 + #define JSON_BUFFER_SIZE 10240 #else #define JSON_BUFFER_SIZE 20480 #endif diff --git a/wled00/json.cpp b/wled00/json.cpp index 4b1bfb7c..ef6ca513 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -508,9 +508,9 @@ void serializeInfo(JsonObject root) JsonObject leds = root.createNestedObject("leds"); leds[F("count")] = strip.getLengthTotal(); - leds[F("rgbw")] = strip.hasWhiteChannel(); - leds[F("wv")] = false; - leds["cct"] = correctWB || strip.hasCCTBus(); + leds[F("rgbw")] = strip.hasRGBWBus(); //deprecated, use info.leds.lc + leds[F("wv")] = false; //deprecated, use info.leds.lc + leds["cct"] = correctWB || strip.hasCCTBus(); //deprecated, use info.leds.lc switch (Bus::getAutoWhiteMode()) { case RGBW_MODE_MANUAL_ONLY: case RGBW_MODE_DUAL: @@ -523,6 +523,17 @@ void serializeInfo(JsonObject root) leds[F("maxpwr")] = (strip.currentMilliamps)? strip.ablMilliampsMax : 0; leds[F("maxseg")] = strip.getMaxSegments(); //leds[F("seglock")] = false; //might be used in the future to prevent modifications to segment config + + uint8_t totalLC = 0; + JsonArray lcarr = leds.createNestedArray(F("seglc")); + uint8_t nSegs = strip.getLastActiveSegmentId(); + for (byte s = 0; s <= nSegs; s++) { + uint8_t lc = strip.getSegment(s).getLightCapabilities(); + totalLC |= lc; + lcarr.add(lc); + } + + leds["lc"] = totalLC; root[F("str")] = syncToggleReceive;