From a06846fa74617fcd366383abd4824303a3fd4c01 Mon Sep 17 00:00:00 2001 From: Mike Ryan Date: Fri, 31 Dec 2021 14:35:27 -0600 Subject: [PATCH 1/3] Overridable color order - Use `ColorOrderMap` to hold optional color order overrides for ranges of LEDs. - Serialization of config to/from filesystem is complete. - Back-end configuration is complete. - TODO: front-end changes to the LED settings page. --- wled00/bus_manager.h | 70 ++++++++++++++++++++++++++++++++++++++++---- wled00/cfg.cpp | 28 ++++++++++++++++++ wled00/const.h | 2 ++ wled00/set.cpp | 12 ++++++++ 4 files changed, 107 insertions(+), 5 deletions(-) diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index 72118383..74497cae 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -73,6 +73,56 @@ struct BusConfig { } }; +// Defines an LED Strip and its color ordering. +struct ColorOrderMapEntry { + uint16_t start; + uint16_t len; + uint8_t colorOrder; +}; + +struct ColorOrderMap { + void add(uint16_t start, uint16_t len, uint8_t colorOrder) { + if (_count >= WLED_MAX_COLOR_ORDER_MAPPINGS) { + return; + } + _mappings[_count].start = start; + _mappings[_count].len = len; + _mappings[_count].colorOrder = colorOrder; + _count++; + } + + uint8_t count() const { + return _count; + } + + void reset() { + _count = 0; + memset(_mappings, 0, sizeof(_mappings)); + } + + const ColorOrderMapEntry* get(uint8_t n) const { + if (n > _count) { + return nullptr; + } + return &(_mappings[n]); + } + + inline uint8_t getPixelColorOrder(uint16_t pix, uint8_t defaultColorOrder) const { + if (_count == 0) return defaultColorOrder; + + for (uint8_t i = 0; i < _count; i++) { + if (pix >= _mappings[i].start && pix < (_mappings[i].start + _mappings[i].len)) { + return _mappings[i].colorOrder; + } + } + return defaultColorOrder; + } + + private: + uint8_t _count; + ColorOrderMapEntry _mappings[WLED_MAX_COLOR_ORDER_MAPPINGS]; +}; + //parent class of BusDigital, BusPwm, and BusNetwork class Bus { public: @@ -152,7 +202,7 @@ class Bus { class BusDigital : public Bus { public: - BusDigital(BusConfig &bc, uint8_t nr) : Bus(bc.type, bc.start) { + BusDigital(BusConfig &bc, uint8_t nr, const ColorOrderMap &com) : Bus(bc.type, bc.start), _colorOrderMap(com) { if (!IS_DIGITAL(bc.type) || !bc.count) return; if (!pinManager.allocatePin(bc.pins[0], true, PinOwner::BusDigital)) return; _pins[0] = bc.pins[0]; @@ -197,7 +247,7 @@ class BusDigital : public Bus { //TODO only show if no new show due in the next 50ms void setStatusPixel(uint32_t c) { if (_skip && canShow()) { - PolyBus::setPixelColor(_busPtr, _iType, 0, c, _colorOrder); + PolyBus::setPixelColor(_busPtr, _iType, 0, c, _colorOrderMap.getPixelColorOrder(_start, _colorOrder)); PolyBus::show(_busPtr, _iType); } } @@ -207,13 +257,13 @@ class BusDigital : public Bus { if (_cct >= 1900) c = colorBalanceFromKelvin(_cct, c); //color correction from CCT if (reversed) pix = _len - pix -1; else pix += _skip; - PolyBus::setPixelColor(_busPtr, _iType, pix, c, _colorOrder); + PolyBus::setPixelColor(_busPtr, _iType, pix, c, _colorOrderMap.getPixelColorOrder(pix+_start, _colorOrder)); } uint32_t getPixelColor(uint16_t pix) { if (reversed) pix = _len - pix -1; else pix += _skip; - return PolyBus::getPixelColor(_busPtr, _iType, pix, _colorOrder); + return PolyBus::getPixelColor(_busPtr, _iType, pix, _colorOrderMap.getPixelColorOrder(pix+_start, _colorOrder)); } inline uint8_t getColorOrder() { @@ -263,6 +313,7 @@ class BusDigital : public Bus { uint8_t _iType = I_NONE; uint8_t _skip = 0; void * _busPtr = nullptr; + const ColorOrderMap &_colorOrderMap; }; @@ -555,7 +606,7 @@ class BusManager { if (bc.type >= TYPE_NET_DDP_RGB && bc.type < 96) { busses[numBusses] = new BusNetwork(bc); } else if (IS_DIGITAL(bc.type)) { - busses[numBusses] = new BusDigital(bc, numBusses); + busses[numBusses] = new BusDigital(bc, numBusses, colorOrderMap); } else { busses[numBusses] = new BusPwm(bc); } @@ -640,8 +691,17 @@ class BusManager { return len; } + void updateColorOrderMap(const ColorOrderMap &com) { + memcpy(&colorOrderMap, &com, sizeof(ColorOrderMap)); + } + + const ColorOrderMap& getColorOrderMap() const { + return colorOrderMap; + } + private: uint8_t numBusses = 0; Bus* busses[WLED_MAX_BUSSES]; + ColorOrderMap colorOrderMap; }; #endif diff --git a/wled00/cfg.cpp b/wled00/cfg.cpp index 86c8c687..46c55982 100644 --- a/wled00/cfg.cpp +++ b/wled00/cfg.cpp @@ -123,6 +123,22 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { } if (hw_led["rev"]) busses.getBus(0)->reversed = true; //set 0.11 global reversed setting for first bus + // read color order map configuration + JsonArray hw_com = hw[F("com")]; + if (!hw_com.isNull()) { + ColorOrderMap com = {}; + uint8_t s = 0; + for (JsonObject entry : hw_com) { + if (s > WLED_MAX_COLOR_ORDER_MAPPINGS) break; + uint16_t start = entry[F("start")] | 0; + uint16_t len = entry[F("len")] | 0; + uint8_t colorOrder = (int)entry[F("order")]; + com.add(start, len, colorOrder); + s++; + } + busses.updateColorOrderMap(com); + } + // read multiple button configuration JsonObject btn_obj = hw["btn"]; JsonArray hw_btn_ins = btn_obj[F("ins")]; @@ -573,6 +589,18 @@ void serializeConfig() { ins[F("rgbw")] = bus->isRgbw(); } + JsonArray hw_com = hw.createNestedArray(F("com")); + const ColorOrderMap& com = busses.getColorOrderMap(); + for (uint8_t s = 0; s < com.count(); s++) { + const ColorOrderMapEntry *entry = com.get(s); + if (!entry) break; + + JsonObject co = hw_com.createNestedObject(); + co[F("start")] = entry->start; + co[F("len")] = entry->len; + co[F("order")] = entry->colorOrder; + } + // button(s) JsonObject hw_btn = hw.createNestedObject("btn"); hw_btn["max"] = WLED_MAX_BUTTONS; // just information about max number of buttons (not actually used) diff --git a/wled00/const.h b/wled00/const.h index 3d3cf1cb..209adcb1 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -39,6 +39,8 @@ #endif #endif +#define WLED_MAX_COLOR_ORDER_MAPPINGS 10 + //Usermod IDs #define USERMOD_ID_RESERVED 0 //Unused. Might indicate no usermod present #define USERMOD_ID_UNSPECIFIED 1 //Default value for a general user mod that does not specify a custom ID diff --git a/wled00/set.cpp b/wled00/set.cpp index 1eb1b431..17dadcff 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -136,6 +136,18 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) doInitBusses = true; } + ColorOrderMap com = {}; + for (uint8_t s = 0; s < WLED_MAX_COLOR_ORDER_MAPPINGS; s++) { + char xs[4] = "XS"; xs[2] = 48+s; xs[3] = 0; //start LED + char xc[4] = "XC"; xc[2] = 48+s; xc[3] = 0; //strip length + char xo[4] = "XO"; xo[2] = 48+s; xo[3] = 0; //color order + start = request->arg(xs).toInt(); + length = request->arg(xc).toInt(); + colorOrder = request->arg(xo).toInt(); + com.add(start, length, colorOrder); + } + busses.updateColorOrderMap(com); + // upate other pins int hw_ir_pin = request->arg(F("IR")).toInt(); if (pinManager.allocatePin(hw_ir_pin,false, PinOwner::IR)) { From b8e23b2d7ea0b71b49b8f188e0148fa8a15d9fc1 Mon Sep 17 00:00:00 2001 From: Mike Ryan Date: Sat, 1 Jan 2022 15:08:07 -0600 Subject: [PATCH 2/3] Add Color order override settings - Adds color order override section to settings page. --- wled00/bus_manager.h | 6 ++++ wled00/const.h | 1 + wled00/data/settings_leds.htm | 58 +++++++++++++++++++++++++++++++++++ wled00/html_settings.h | 36 +++++++++++++--------- wled00/xml.cpp | 11 +++++++ 5 files changed, 97 insertions(+), 15 deletions(-) diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index 74497cae..da5467b5 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -85,6 +85,12 @@ struct ColorOrderMap { if (_count >= WLED_MAX_COLOR_ORDER_MAPPINGS) { return; } + if (len == 0) { + return; + } + if (colorOrder > COL_ORDER_MAX) { + return; + } _mappings[_count].start = start; _mappings[_count].len = len; _mappings[_count].colorOrder = colorOrder; diff --git a/wled00/const.h b/wled00/const.h index 209adcb1..a303f46e 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -172,6 +172,7 @@ #define COL_ORDER_RBG 3 #define COL_ORDER_BGR 4 #define COL_ORDER_GBR 5 +#define COL_ORDER_MAX 5 //Button type diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm index 8dd81e44..bbac7eeb 100644 --- a/wled00/data/settings_leds.htm +++ b/wled00/data/settings_leds.htm @@ -347,6 +347,50 @@ ${i+1}: if (!init) UI(); } + + function addCOM(start=0,len=1,co=0) { + var i = d.getElementsByClassName("com_entry").length; + if (i >= 10) return; + + var b = `
+
+${i+1}: Start:   +Length: +
Color Order: + +

`; + gId("com_entries").insertAdjacentHTML("beforeend", b); + gId("xo"+i).value = co; + btnCOM(i+1); + } + + function remCOM() { + var entries = d.getElementsByClassName("com_entry"); + var i = entries.length; + if (i === 0) return; + entries[i-1].remove(); + btnCOM(i-1); + } + + function resetCOM() { + for (let e of d.getElementsByClassName("com_entry")) { + e.remove(); + } + btnCOM(0); + } + + function btnCOM(i) { + gId("com_add").style.display = (i<10) ? "inline":"none"; + gId("com_rem").style.display = (i>0) ? "inline":"none"; + } + function addBtn(i,p,t) { var c = gId("btns").innerHTML; var bt = "BT" + String.fromCharCode((i<10?48:55)+i);; @@ -431,6 +475,12 @@ ${i+1}: d.getElementsByName("CV"+i)[0].checked = v.rev; }); } + if(c.hw.com) { + resetCOM(); + c.hw.com.forEach(e => { + addCOM(e.start, e.len, e.order); + }); + } if (c.hw.btn) { var b = c.hw.btn; if (Array.isArray(b.ins)) gId("btns").innerHTML = ""; @@ -510,6 +560,14 @@ ${i+1}: Make a segment for each output:
Custom bus start indices:

+
+ Color Order Override: +
+
+ +
+
+
Touch threshold:
IR GPIO: