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.
This commit is contained in:
parent
33f72e40da
commit
a06846fa74
@ -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
|
//parent class of BusDigital, BusPwm, and BusNetwork
|
||||||
class Bus {
|
class Bus {
|
||||||
public:
|
public:
|
||||||
@ -152,7 +202,7 @@ class Bus {
|
|||||||
|
|
||||||
class BusDigital : public Bus {
|
class BusDigital : public Bus {
|
||||||
public:
|
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 (!IS_DIGITAL(bc.type) || !bc.count) return;
|
||||||
if (!pinManager.allocatePin(bc.pins[0], true, PinOwner::BusDigital)) return;
|
if (!pinManager.allocatePin(bc.pins[0], true, PinOwner::BusDigital)) return;
|
||||||
_pins[0] = bc.pins[0];
|
_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
|
//TODO only show if no new show due in the next 50ms
|
||||||
void setStatusPixel(uint32_t c) {
|
void setStatusPixel(uint32_t c) {
|
||||||
if (_skip && canShow()) {
|
if (_skip && canShow()) {
|
||||||
PolyBus::setPixelColor(_busPtr, _iType, 0, c, _colorOrder);
|
PolyBus::setPixelColor(_busPtr, _iType, 0, c, _colorOrderMap.getPixelColorOrder(_start, _colorOrder));
|
||||||
PolyBus::show(_busPtr, _iType);
|
PolyBus::show(_busPtr, _iType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -207,13 +257,13 @@ class BusDigital : public Bus {
|
|||||||
if (_cct >= 1900) c = colorBalanceFromKelvin(_cct, c); //color correction from CCT
|
if (_cct >= 1900) c = colorBalanceFromKelvin(_cct, c); //color correction from CCT
|
||||||
if (reversed) pix = _len - pix -1;
|
if (reversed) pix = _len - pix -1;
|
||||||
else pix += _skip;
|
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) {
|
uint32_t getPixelColor(uint16_t pix) {
|
||||||
if (reversed) pix = _len - pix -1;
|
if (reversed) pix = _len - pix -1;
|
||||||
else pix += _skip;
|
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() {
|
inline uint8_t getColorOrder() {
|
||||||
@ -263,6 +313,7 @@ class BusDigital : public Bus {
|
|||||||
uint8_t _iType = I_NONE;
|
uint8_t _iType = I_NONE;
|
||||||
uint8_t _skip = 0;
|
uint8_t _skip = 0;
|
||||||
void * _busPtr = nullptr;
|
void * _busPtr = nullptr;
|
||||||
|
const ColorOrderMap &_colorOrderMap;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -555,7 +606,7 @@ class BusManager {
|
|||||||
if (bc.type >= TYPE_NET_DDP_RGB && bc.type < 96) {
|
if (bc.type >= TYPE_NET_DDP_RGB && bc.type < 96) {
|
||||||
busses[numBusses] = new BusNetwork(bc);
|
busses[numBusses] = new BusNetwork(bc);
|
||||||
} else if (IS_DIGITAL(bc.type)) {
|
} else if (IS_DIGITAL(bc.type)) {
|
||||||
busses[numBusses] = new BusDigital(bc, numBusses);
|
busses[numBusses] = new BusDigital(bc, numBusses, colorOrderMap);
|
||||||
} else {
|
} else {
|
||||||
busses[numBusses] = new BusPwm(bc);
|
busses[numBusses] = new BusPwm(bc);
|
||||||
}
|
}
|
||||||
@ -640,8 +691,17 @@ class BusManager {
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateColorOrderMap(const ColorOrderMap &com) {
|
||||||
|
memcpy(&colorOrderMap, &com, sizeof(ColorOrderMap));
|
||||||
|
}
|
||||||
|
|
||||||
|
const ColorOrderMap& getColorOrderMap() const {
|
||||||
|
return colorOrderMap;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t numBusses = 0;
|
uint8_t numBusses = 0;
|
||||||
Bus* busses[WLED_MAX_BUSSES];
|
Bus* busses[WLED_MAX_BUSSES];
|
||||||
|
ColorOrderMap colorOrderMap;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
@ -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
|
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
|
// read multiple button configuration
|
||||||
JsonObject btn_obj = hw["btn"];
|
JsonObject btn_obj = hw["btn"];
|
||||||
JsonArray hw_btn_ins = btn_obj[F("ins")];
|
JsonArray hw_btn_ins = btn_obj[F("ins")];
|
||||||
@ -573,6 +589,18 @@ void serializeConfig() {
|
|||||||
ins[F("rgbw")] = bus->isRgbw();
|
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)
|
// button(s)
|
||||||
JsonObject hw_btn = hw.createNestedObject("btn");
|
JsonObject hw_btn = hw.createNestedObject("btn");
|
||||||
hw_btn["max"] = WLED_MAX_BUTTONS; // just information about max number of buttons (not actually used)
|
hw_btn["max"] = WLED_MAX_BUTTONS; // just information about max number of buttons (not actually used)
|
||||||
|
@ -39,6 +39,8 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define WLED_MAX_COLOR_ORDER_MAPPINGS 10
|
||||||
|
|
||||||
//Usermod IDs
|
//Usermod IDs
|
||||||
#define USERMOD_ID_RESERVED 0 //Unused. Might indicate no usermod present
|
#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
|
#define USERMOD_ID_UNSPECIFIED 1 //Default value for a general user mod that does not specify a custom ID
|
||||||
|
@ -136,6 +136,18 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
|||||||
doInitBusses = true;
|
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
|
// upate other pins
|
||||||
int hw_ir_pin = request->arg(F("IR")).toInt();
|
int hw_ir_pin = request->arg(F("IR")).toInt();
|
||||||
if (pinManager.allocatePin(hw_ir_pin,false, PinOwner::IR)) {
|
if (pinManager.allocatePin(hw_ir_pin,false, PinOwner::IR)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user