Support white addressable LED strips (#3073)
* Support white addressable LED strips * Various white handling tweaks Allow RGB controls for white-only busses depending on AWM (makes palette-only FX work on non-RGB addressable busses) Fixed RGB controls hidden if segment contained any non-RGB bus (even though there is also an RGB bus in that segment) New Max auto white mode Added hasCCT() bus method Rename methods to be clearer WS2811 White getPixelColor fix() * Fix merge conflict (bus manager cpp)
This commit is contained in:
parent
f2459ea904
commit
74156b7ed8
@ -749,7 +749,7 @@ uint8_t Segment::differs(Segment& b) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Segment::refreshLightCapabilities() {
|
void Segment::refreshLightCapabilities() {
|
||||||
uint8_t capabilities = 0x01;
|
uint8_t capabilities = 0;
|
||||||
|
|
||||||
for (uint8_t b = 0; b < busses.getNumBusses(); b++) {
|
for (uint8_t b = 0; b < busses.getNumBusses(); b++) {
|
||||||
Bus *bus = busses.getBus(b);
|
Bus *bus = busses.getBus(b);
|
||||||
@ -759,19 +759,17 @@ void Segment::refreshLightCapabilities() {
|
|||||||
if (bus->getStart() + bus->getLength() <= start) continue;
|
if (bus->getStart() + bus->getLength() <= start) continue;
|
||||||
|
|
||||||
uint8_t type = bus->getType();
|
uint8_t type = bus->getType();
|
||||||
if (type == TYPE_ONOFF || type == TYPE_ANALOG_1CH || (!cctFromRgb && type == TYPE_ANALOG_2CH)) capabilities &= 0xFE; // does not support RGB
|
if (bus->hasRGB() || (cctFromRgb && bus->hasCCT())) capabilities |= SEG_CAPABILITY_RGB;
|
||||||
if (bus->isRgbw()) capabilities |= 0x02; // segment supports white channel
|
if (!cctFromRgb && bus->hasCCT()) capabilities |= SEG_CAPABILITY_CCT;
|
||||||
if (!cctFromRgb) {
|
if (correctWB && (bus->hasRGB() || bus->hasCCT())) capabilities |= SEG_CAPABILITY_CCT; //white balance correction (CCT slider)
|
||||||
switch (type) {
|
if (bus->hasWhite()) {
|
||||||
case TYPE_ANALOG_5CH:
|
uint8_t aWM = Bus::getGlobalAWMode() == AW_GLOBAL_DISABLED ? bus->getAutoWhiteMode() : Bus::getGlobalAWMode();
|
||||||
case TYPE_ANALOG_2CH:
|
bool whiteSlider = (aWM == RGBW_MODE_DUAL || aWM == RGBW_MODE_MANUAL_ONLY); // white slider allowed
|
||||||
capabilities |= 0x04; //segment supports white CCT
|
// if auto white calculation from RGB is active (Accurate/Brighter), force RGB controls even if there are no RGB busses
|
||||||
}
|
if (!whiteSlider) capabilities |= SEG_CAPABILITY_RGB;
|
||||||
|
// if auto white calculation from RGB is disabled/optional (None/Dual), allow white channel adjustments
|
||||||
|
if ( whiteSlider) capabilities |= SEG_CAPABILITY_W;
|
||||||
}
|
}
|
||||||
if (correctWB && !(type == TYPE_ANALOG_1CH || type == TYPE_ONOFF)) capabilities |= 0x04; //white balance correction (uses CCT slider)
|
|
||||||
uint8_t aWM = Bus::getAutoWhiteMode()<255 ? Bus::getAutoWhiteMode() : bus->getAWMode();
|
|
||||||
bool whiteSlider = (aWM == RGBW_MODE_DUAL || aWM == RGBW_MODE_MANUAL_ONLY); // white slider allowed
|
|
||||||
if (bus->isRgbw() && (whiteSlider || !(capabilities & 0x01))) capabilities |= 0x08; // allow white channel adjustments (AWM allows or is not RGB)
|
|
||||||
}
|
}
|
||||||
_capabilities = capabilities;
|
_capabilities = capabilities;
|
||||||
}
|
}
|
||||||
@ -1000,7 +998,7 @@ void WS2812FX::finalizeInit(void)
|
|||||||
if (bus == nullptr) continue;
|
if (bus == nullptr) continue;
|
||||||
if (bus->getStart() + bus->getLength() > MAX_LEDS) break;
|
if (bus->getStart() + bus->getLength() > MAX_LEDS) break;
|
||||||
//RGBW mode is enabled if at least one of the strips is RGBW
|
//RGBW mode is enabled if at least one of the strips is RGBW
|
||||||
_hasWhiteChannel |= bus->isRgbw();
|
_hasWhiteChannel |= bus->hasWhite();
|
||||||
//refresh is required to remain off if at least one of the strips requires the refresh.
|
//refresh is required to remain off if at least one of the strips requires the refresh.
|
||||||
_isOffRefreshRequired |= bus->isOffRefreshRequired();
|
_isOffRefreshRequired |= bus->isOffRefreshRequired();
|
||||||
uint16_t busEnd = bus->getStart() + bus->getLength();
|
uint16_t busEnd = bus->getStart() + bus->getLength();
|
||||||
@ -1167,7 +1165,7 @@ void WS2812FX::estimateCurrentAndLimitBri() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bus->isRgbw()) { //RGBW led total output with white LEDs enabled is still 50mA, so each channel uses less
|
if (bus->hasWhite()) { //RGBW led total output with white LEDs enabled is still 50mA, so each channel uses less
|
||||||
busPowerSum *= 3;
|
busPowerSum *= 3;
|
||||||
busPowerSum = busPowerSum >> 2; //same as /= 4
|
busPowerSum = busPowerSum >> 2; //same as /= 4
|
||||||
}
|
}
|
||||||
@ -1335,12 +1333,7 @@ bool WS2812FX::hasRGBWBus(void) {
|
|||||||
for (size_t b = 0; b < busses.getNumBusses(); b++) {
|
for (size_t b = 0; b < busses.getNumBusses(); b++) {
|
||||||
Bus *bus = busses.getBus(b);
|
Bus *bus = busses.getBus(b);
|
||||||
if (bus == nullptr || bus->getLength()==0) break;
|
if (bus == nullptr || bus->getLength()==0) break;
|
||||||
switch (bus->getType()) {
|
if (bus->hasRGB() && bus->hasWhite()) return true;
|
||||||
case TYPE_SK6812_RGBW:
|
|
||||||
case TYPE_TM1814:
|
|
||||||
case TYPE_ANALOG_4CH:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -85,6 +85,7 @@ uint32_t Bus::autoWhiteCalc(uint32_t c) {
|
|||||||
uint8_t r = R(c);
|
uint8_t r = R(c);
|
||||||
uint8_t g = G(c);
|
uint8_t g = G(c);
|
||||||
uint8_t b = B(c);
|
uint8_t b = B(c);
|
||||||
|
if (aWM == RGBW_MODE_MAX) return RGBW32(r, g, b, r > g ? (r > b ? r : b) : (g > b ? g : b)); // brightest RGB channel
|
||||||
w = r < g ? (r < b ? r : b) : (g < b ? g : b);
|
w = r < g ? (r < b ? r : b) : (g < b ? g : b);
|
||||||
if (aWM == RGBW_MODE_AUTO_ACCURATE) { r -= w; g -= w; b -= w; } //subtract w in ACCURATE mode
|
if (aWM == RGBW_MODE_AUTO_ACCURATE) { r -= w; g -= w; b -= w; } //subtract w in ACCURATE mode
|
||||||
return RGBW32(r, g, b, w);
|
return RGBW32(r, g, b, w);
|
||||||
@ -107,7 +108,9 @@ BusDigital::BusDigital(BusConfig &bc, uint8_t nr, const ColorOrderMap &com) : Bu
|
|||||||
_len = bc.count + _skip;
|
_len = bc.count + _skip;
|
||||||
_iType = PolyBus::getI(bc.type, _pins, nr);
|
_iType = PolyBus::getI(bc.type, _pins, nr);
|
||||||
if (_iType == I_NONE) return;
|
if (_iType == I_NONE) return;
|
||||||
_busPtr = PolyBus::create(_iType, _pins, _len, nr);
|
uint16_t lenToCreate = _len;
|
||||||
|
if (bc.type == TYPE_WS2812_1CH_X3) lenToCreate = NUM_ICS_WS2812_1CH_3X(_len); // only needs a third of "RGB" LEDs for NeoPixelBus
|
||||||
|
_busPtr = PolyBus::create(_iType, _pins, lenToCreate, nr);
|
||||||
_valid = (_busPtr != nullptr);
|
_valid = (_busPtr != nullptr);
|
||||||
_colorOrder = bc.colorOrder;
|
_colorOrder = bc.colorOrder;
|
||||||
DEBUG_PRINTF("%successfully inited strip %u (len %u) with type %u and pins %u,%u (itype %u)\n", _valid?"S":"Uns", nr, _len, bc.type, _pins[0],_pins[1],_iType);
|
DEBUG_PRINTF("%successfully inited strip %u (len %u) with type %u and pins %u,%u (itype %u)\n", _valid?"S":"Uns", nr, _len, bc.type, _pins[0],_pins[1],_iType);
|
||||||
@ -142,17 +145,40 @@ void BusDigital::setStatusPixel(uint32_t c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR BusDigital::setPixelColor(uint16_t pix, uint32_t c) {
|
void IRAM_ATTR BusDigital::setPixelColor(uint16_t pix, uint32_t c) {
|
||||||
if (_type == TYPE_SK6812_RGBW || _type == TYPE_TM1814) c = autoWhiteCalc(c);
|
if (_type == TYPE_SK6812_RGBW || _type == TYPE_TM1814 || _type == TYPE_WS2812_1CH_X3) c = autoWhiteCalc(c);
|
||||||
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, _colorOrderMap.getPixelColorOrder(pix+_start, _colorOrder));
|
uint8_t co = _colorOrderMap.getPixelColorOrder(pix+_start, _colorOrder);
|
||||||
|
if (_type == TYPE_WS2812_1CH_X3) { // map to correct IC, each controls 3 LEDs
|
||||||
|
uint16_t pOld = pix;
|
||||||
|
pix = IC_INDEX_WS2812_1CH_3X(pix);
|
||||||
|
uint32_t cOld = PolyBus::getPixelColor(_busPtr, _iType, pix, co);
|
||||||
|
switch (pOld % 3) { // change only the single channel (TODO: this can cause loss because of get/set)
|
||||||
|
case 0: c = RGBW32(R(cOld), W(c) , B(cOld), 0); break;
|
||||||
|
case 1: c = RGBW32(W(c) , G(cOld), B(cOld), 0); break;
|
||||||
|
case 2: c = RGBW32(R(cOld), G(cOld), W(c) , 0); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PolyBus::setPixelColor(_busPtr, _iType, pix, c, co);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t BusDigital::getPixelColor(uint16_t pix) {
|
uint32_t BusDigital::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, _colorOrderMap.getPixelColorOrder(pix+_start, _colorOrder));
|
uint8_t co = _colorOrderMap.getPixelColorOrder(pix+_start, _colorOrder);
|
||||||
|
if (_type == TYPE_WS2812_1CH_X3) { // map to correct IC, each controls 3 LEDs
|
||||||
|
uint16_t pOld = pix;
|
||||||
|
pix = IC_INDEX_WS2812_1CH_3X(pix);
|
||||||
|
uint32_t c = PolyBus::getPixelColor(_busPtr, _iType, pix, co);
|
||||||
|
switch (pOld % 3) { // get only the single channel
|
||||||
|
case 0: c = RGBW32(G(c), G(c), G(c), G(c)); break;
|
||||||
|
case 1: c = RGBW32(R(c), R(c), R(c), R(c)); break;
|
||||||
|
case 2: c = RGBW32(B(c), B(c), B(c), B(c)); break;
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
return PolyBus::getPixelColor(_busPtr, _iType, pix, co);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t BusDigital::getPins(uint8_t* pinArray) {
|
uint8_t BusDigital::getPins(uint8_t* pinArray) {
|
||||||
@ -387,7 +413,7 @@ BusNetwork::BusNetwork(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) {
|
|||||||
|
|
||||||
void BusNetwork::setPixelColor(uint16_t pix, uint32_t c) {
|
void BusNetwork::setPixelColor(uint16_t pix, uint32_t c) {
|
||||||
if (!_valid || pix >= _len) return;
|
if (!_valid || pix >= _len) return;
|
||||||
if (isRgbw()) c = autoWhiteCalc(c);
|
if (hasWhite()) c = autoWhiteCalc(c);
|
||||||
if (_cct >= 1900) c = colorBalanceFromKelvin(_cct, c); //color correction from CCT
|
if (_cct >= 1900) c = colorBalanceFromKelvin(_cct, c); //color correction from CCT
|
||||||
uint16_t offset = pix * _UDPchannels;
|
uint16_t offset = pix * _UDPchannels;
|
||||||
_data[offset] = R(c);
|
_data[offset] = R(c);
|
||||||
|
@ -11,6 +11,13 @@
|
|||||||
#define SET_BIT(var,bit) ((var)|=(uint16_t)(0x0001<<(bit)))
|
#define SET_BIT(var,bit) ((var)|=(uint16_t)(0x0001<<(bit)))
|
||||||
#define UNSET_BIT(var,bit) ((var)&=(~(uint16_t)(0x0001<<(bit))))
|
#define UNSET_BIT(var,bit) ((var)&=(~(uint16_t)(0x0001<<(bit))))
|
||||||
|
|
||||||
|
#define NUM_ICS_WS2812_1CH_3X(len) (((len)+2)/3) // 1 WS2811 IC controls 3 zones (each zone has 1 LED, W)
|
||||||
|
#define IC_INDEX_WS2812_1CH_3X(i) ((i)/3)
|
||||||
|
|
||||||
|
#define NUM_ICS_WS2812_2CH_3X(len) (((len)+1)*2/3) // 2 WS2811 ICs control 3 zones (each zone has 2 LEDs, CW and WW)
|
||||||
|
#define IC_INDEX_WS2812_2CH_3X(i) ((i)*2/3)
|
||||||
|
#define WS2812_2CH_3X_SPANS_2_ICS(i) ((i)&0x01) // every other LED zone is on two different ICs
|
||||||
|
|
||||||
//temporary struct for passing bus configuration to bus
|
//temporary struct for passing bus configuration to bus
|
||||||
struct BusConfig {
|
struct BusConfig {
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
@ -90,7 +97,7 @@ class Bus {
|
|||||||
{
|
{
|
||||||
_type = type;
|
_type = type;
|
||||||
_start = start;
|
_start = start;
|
||||||
_autoWhiteMode = Bus::isRgbw(_type) ? aw : RGBW_MODE_MANUAL_ONLY;
|
_autoWhiteMode = Bus::hasWhite(_type) ? aw : RGBW_MODE_MANUAL_ONLY;
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual ~Bus() {} //throw the bus under the bus
|
virtual ~Bus() {} //throw the bus under the bus
|
||||||
@ -114,20 +121,20 @@ class Bus {
|
|||||||
inline bool isOffRefreshRequired() { return _needsRefresh; }
|
inline bool isOffRefreshRequired() { return _needsRefresh; }
|
||||||
bool containsPixel(uint16_t pix) { return pix >= _start && pix < _start+_len; }
|
bool containsPixel(uint16_t pix) { return pix >= _start && pix < _start+_len; }
|
||||||
|
|
||||||
virtual bool isRgbw() { return Bus::isRgbw(_type); }
|
|
||||||
static bool isRgbw(uint8_t type) {
|
|
||||||
if (type == TYPE_SK6812_RGBW || type == TYPE_TM1814) return true;
|
|
||||||
if (type > TYPE_ONOFF && type <= TYPE_ANALOG_5CH && type != TYPE_ANALOG_3CH) return true;
|
|
||||||
if (type == TYPE_NET_DDP_RGBW) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
virtual bool hasRGB() {
|
virtual bool hasRGB() {
|
||||||
if (_type == TYPE_WS2812_1CH || _type == TYPE_WS2812_WWA || _type == TYPE_ANALOG_1CH || _type == TYPE_ANALOG_2CH || _type == TYPE_ONOFF) return false;
|
if ((_type >= TYPE_WS2812_1CH && _type <= TYPE_WS2812_WWA) || _type == TYPE_ANALOG_1CH || _type == TYPE_ANALOG_2CH || _type == TYPE_ONOFF) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
virtual bool hasWhite() {
|
virtual bool hasWhite() { return Bus::hasWhite(_type); }
|
||||||
if (_type == TYPE_SK6812_RGBW || _type == TYPE_TM1814 || _type == TYPE_WS2812_1CH || _type == TYPE_WS2812_WWA ||
|
static bool hasWhite(uint8_t type) {
|
||||||
_type == TYPE_ANALOG_1CH || _type == TYPE_ANALOG_2CH || _type == TYPE_ANALOG_4CH || _type == TYPE_ANALOG_5CH || _type == TYPE_NET_DDP_RGBW) return true;
|
if ((type >= TYPE_WS2812_1CH && type <= TYPE_WS2812_WWA) || type == TYPE_SK6812_RGBW || type == TYPE_TM1814) return true; // digital types with white channel
|
||||||
|
if (type > TYPE_ONOFF && type <= TYPE_ANALOG_5CH && type != TYPE_ANALOG_3CH) return true; // analog types with white channel
|
||||||
|
if (type == TYPE_NET_DDP_RGBW) return true; // network types with white channel
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
virtual bool hasCCT() {
|
||||||
|
if (_type == TYPE_WS2812_2CH_X3 || _type == TYPE_WS2812_WWA ||
|
||||||
|
_type == TYPE_ANALOG_2CH || _type == TYPE_ANALOG_5CH) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
static void setCCT(uint16_t cct) {
|
static void setCCT(uint16_t cct) {
|
||||||
@ -141,10 +148,10 @@ class Bus {
|
|||||||
if (_cctBlend > WLED_MAX_CCT_BLEND) _cctBlend = WLED_MAX_CCT_BLEND;
|
if (_cctBlend > WLED_MAX_CCT_BLEND) _cctBlend = WLED_MAX_CCT_BLEND;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
inline void setAWMode(uint8_t m) { if (m < 4) _autoWhiteMode = m; }
|
inline void setAutoWhiteMode(uint8_t m) { if (m < 5) _autoWhiteMode = m; }
|
||||||
inline uint8_t getAWMode() { return _autoWhiteMode; }
|
inline uint8_t getAutoWhiteMode() { return _autoWhiteMode; }
|
||||||
inline static void setAutoWhiteMode(uint8_t m) { if (m < 4) _gAWM = m; else _gAWM = 255; }
|
inline static void setGlobalAWMode(uint8_t m) { if (m < 5) _gAWM = m; else _gAWM = AW_GLOBAL_DISABLED; }
|
||||||
inline static uint8_t getAutoWhiteMode() { return _gAWM; }
|
inline static uint8_t getGlobalAWMode() { return _gAWM; }
|
||||||
|
|
||||||
bool reversed = false;
|
bool reversed = false;
|
||||||
|
|
||||||
@ -292,10 +299,6 @@ class BusNetwork : public Bus {
|
|||||||
|
|
||||||
uint8_t getPins(uint8_t* pinArray);
|
uint8_t getPins(uint8_t* pinArray);
|
||||||
|
|
||||||
bool isRgbw() {
|
|
||||||
return _rgbw;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t getLength() {
|
uint16_t getLength() {
|
||||||
return _len;
|
return _len;
|
||||||
}
|
}
|
||||||
@ -370,4 +373,4 @@ class BusManager {
|
|||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
@ -894,6 +894,8 @@ class PolyBus {
|
|||||||
uint8_t offset = pins[0] -1; //for driver: 0 = uart0, 1 = uart1, 2 = dma, 3 = bitbang
|
uint8_t offset = pins[0] -1; //for driver: 0 = uart0, 1 = uart1, 2 = dma, 3 = bitbang
|
||||||
if (offset > 3) offset = 3;
|
if (offset > 3) offset = 3;
|
||||||
switch (busType) {
|
switch (busType) {
|
||||||
|
case TYPE_WS2812_1CH_X3:
|
||||||
|
case TYPE_WS2812_2CH_X3:
|
||||||
case TYPE_WS2812_RGB:
|
case TYPE_WS2812_RGB:
|
||||||
case TYPE_WS2812_WWA:
|
case TYPE_WS2812_WWA:
|
||||||
return I_8266_U0_NEO_3 + offset;
|
return I_8266_U0_NEO_3 + offset;
|
||||||
@ -926,6 +928,8 @@ class PolyBus {
|
|||||||
if (num > 7) offset = num -7;
|
if (num > 7) offset = num -7;
|
||||||
#endif
|
#endif
|
||||||
switch (busType) {
|
switch (busType) {
|
||||||
|
case TYPE_WS2812_1CH_X3:
|
||||||
|
case TYPE_WS2812_2CH_X3:
|
||||||
case TYPE_WS2812_RGB:
|
case TYPE_WS2812_RGB:
|
||||||
case TYPE_WS2812_WWA:
|
case TYPE_WS2812_WWA:
|
||||||
return I_32_RN_NEO_3 + offset;
|
return I_32_RN_NEO_3 + offset;
|
||||||
|
@ -84,7 +84,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
uint8_t autoWhiteMode = RGBW_MODE_MANUAL_ONLY;
|
uint8_t autoWhiteMode = RGBW_MODE_MANUAL_ONLY;
|
||||||
CJSON(strip.ablMilliampsMax, hw_led[F("maxpwr")]);
|
CJSON(strip.ablMilliampsMax, hw_led[F("maxpwr")]);
|
||||||
CJSON(strip.milliampsPerLed, hw_led[F("ledma")]);
|
CJSON(strip.milliampsPerLed, hw_led[F("ledma")]);
|
||||||
Bus::setAutoWhiteMode(hw_led[F("rgbwm")] | 255);
|
Bus::setGlobalAWMode(hw_led[F("rgbwm")] | 255);
|
||||||
CJSON(correctWB, hw_led["cct"]);
|
CJSON(correctWB, hw_led["cct"]);
|
||||||
CJSON(cctFromRgb, hw_led[F("cr")]);
|
CJSON(cctFromRgb, hw_led[F("cr")]);
|
||||||
CJSON(strip.cctBlending, hw_led[F("cb")]);
|
CJSON(strip.cctBlending, hw_led[F("cb")]);
|
||||||
@ -700,7 +700,7 @@ void serializeConfig() {
|
|||||||
hw_led[F("cr")] = cctFromRgb;
|
hw_led[F("cr")] = cctFromRgb;
|
||||||
hw_led[F("cb")] = strip.cctBlending;
|
hw_led[F("cb")] = strip.cctBlending;
|
||||||
hw_led["fps"] = strip.getTargetFps();
|
hw_led["fps"] = strip.getTargetFps();
|
||||||
hw_led[F("rgbwm")] = Bus::getAutoWhiteMode(); // global override
|
hw_led[F("rgbwm")] = Bus::getGlobalAWMode(); // global auto white mode override
|
||||||
hw_led[F("ld")] = strip.useLedsArray;
|
hw_led[F("ld")] = strip.useLedsArray;
|
||||||
|
|
||||||
#ifndef WLED_DISABLE_2D
|
#ifndef WLED_DISABLE_2D
|
||||||
@ -745,7 +745,7 @@ void serializeConfig() {
|
|||||||
ins[F("skip")] = bus->skippedLeds();
|
ins[F("skip")] = bus->skippedLeds();
|
||||||
ins["type"] = bus->getType() & 0x7F;
|
ins["type"] = bus->getType() & 0x7F;
|
||||||
ins["ref"] = bus->isOffRefreshRequired();
|
ins["ref"] = bus->isOffRefreshRequired();
|
||||||
ins[F("rgbwm")] = bus->getAWMode();
|
ins[F("rgbwm")] = bus->getAutoWhiteMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonArray hw_com = hw.createNestedArray(F("com"));
|
JsonArray hw_com = hw.createNestedArray(F("com"));
|
||||||
|
@ -143,11 +143,13 @@
|
|||||||
#define CALL_MODE_BUTTON_PRESET 12 //button/IR JSON preset/macro
|
#define CALL_MODE_BUTTON_PRESET 12 //button/IR JSON preset/macro
|
||||||
|
|
||||||
//RGB to RGBW conversion mode
|
//RGB to RGBW conversion mode
|
||||||
#define RGBW_MODE_MANUAL_ONLY 0 //No automatic white channel calculation. Manual white channel slider
|
#define RGBW_MODE_MANUAL_ONLY 0 // No automatic white channel calculation. Manual white channel slider
|
||||||
#define RGBW_MODE_AUTO_BRIGHTER 1 //New algorithm. Adds as much white as the darkest RGBW channel
|
#define RGBW_MODE_AUTO_BRIGHTER 1 // New algorithm. Adds as much white as the darkest RGBW channel
|
||||||
#define RGBW_MODE_AUTO_ACCURATE 2 //New algorithm. Adds as much white as the darkest RGBW channel and subtracts this amount from each RGB channel
|
#define RGBW_MODE_AUTO_ACCURATE 2 // New algorithm. Adds as much white as the darkest RGBW channel and subtracts this amount from each RGB channel
|
||||||
#define RGBW_MODE_DUAL 3 //Manual slider + auto calculation. Automatically calculates only if manual slider is set to off (0)
|
#define RGBW_MODE_DUAL 3 // Manual slider + auto calculation. Automatically calculates only if manual slider is set to off (0)
|
||||||
#define RGBW_MODE_LEGACY 4 //Old floating algorithm. Too slow for realtime and palette support
|
#define RGBW_MODE_MAX 4 // Sets white to the value of the brightest RGB channel (good for white-only LEDs without any RGB)
|
||||||
|
//#define RGBW_MODE_LEGACY 4 // Old floating algorithm. Too slow for realtime and palette support (unused)
|
||||||
|
#define AW_GLOBAL_DISABLED 255 // Global auto white mode override disabled. Per-bus setting is used
|
||||||
|
|
||||||
//realtime modes
|
//realtime modes
|
||||||
#define REALTIME_MODE_INACTIVE 0
|
#define REALTIME_MODE_INACTIVE 0
|
||||||
@ -193,7 +195,9 @@
|
|||||||
#define TYPE_NONE 0 //light is not configured
|
#define TYPE_NONE 0 //light is not configured
|
||||||
#define TYPE_RESERVED 1 //unused. Might indicate a "virtual" light
|
#define TYPE_RESERVED 1 //unused. Might indicate a "virtual" light
|
||||||
//Digital types (data pin only) (16-31)
|
//Digital types (data pin only) (16-31)
|
||||||
#define TYPE_WS2812_1CH 20 //white-only chips
|
#define TYPE_WS2812_1CH 18 //white-only chips (1 channel per IC) (unused)
|
||||||
|
#define TYPE_WS2812_1CH_X3 19 //white-only chips (3 channels per IC)
|
||||||
|
#define TYPE_WS2812_2CH_X3 20 //CCT chips (1st IC controls WW + CW of 1st zone and CW of 2nd zone, 2nd IC controls WW of 2nd zone and WW + CW of 3rd zone)
|
||||||
#define TYPE_WS2812_WWA 21 //amber + warm + cold white
|
#define TYPE_WS2812_WWA 21 //amber + warm + cold white
|
||||||
#define TYPE_WS2812_RGB 22
|
#define TYPE_WS2812_RGB 22
|
||||||
#define TYPE_GS8608 23 //same driver as WS2812, but will require signal 2x per second (else displays test pattern)
|
#define TYPE_GS8608 23 //same driver as WS2812, but will require signal 2x per second (else displays test pattern)
|
||||||
@ -290,6 +294,11 @@
|
|||||||
//Playlist option byte
|
//Playlist option byte
|
||||||
#define PL_OPTION_SHUFFLE 0x01
|
#define PL_OPTION_SHUFFLE 0x01
|
||||||
|
|
||||||
|
// Segment capability byte
|
||||||
|
#define SEG_CAPABILITY_RGB 0x01
|
||||||
|
#define SEG_CAPABILITY_W 0x02
|
||||||
|
#define SEG_CAPABILITY_CCT 0x04
|
||||||
|
|
||||||
// WLED Error modes
|
// WLED Error modes
|
||||||
#define ERR_NONE 0 // All good :)
|
#define ERR_NONE 0 // All good :)
|
||||||
#define ERR_EEP_COMMIT 2 // Could not commit to EEPROM (wrong flash layout?)
|
#define ERR_EEP_COMMIT 2 // Could not commit to EEPROM (wrong flash layout?)
|
||||||
|
@ -1319,7 +1319,7 @@ function readState(s,command=false)
|
|||||||
sellvl = 2;
|
sellvl = 2;
|
||||||
var lc = lastinfo.leds.seglc[s.seg[i].id];
|
var lc = lastinfo.leds.seglc[s.seg[i].id];
|
||||||
hasRGB |= !!(lc & 0x01);
|
hasRGB |= !!(lc & 0x01);
|
||||||
hasWhite |= !!(lc & 0x08); // & 0x02 contains W channel
|
hasWhite |= !!(lc & 0x02);
|
||||||
hasCCT |= !!(lc & 0x04);
|
hasCCT |= !!(lc & 0x04);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1327,7 +1327,7 @@ function readState(s,command=false)
|
|||||||
if (sellvl == 1) {
|
if (sellvl == 1) {
|
||||||
var lc = lastinfo.leds.seglc[i.id];
|
var lc = lastinfo.leds.seglc[i.id];
|
||||||
hasRGB = !!(lc & 0x01);
|
hasRGB = !!(lc & 0x01);
|
||||||
hasWhite = !!(lc & 0x08); // & 0x02 contains W channel
|
hasWhite = !!(lc & 0x02);
|
||||||
hasCCT = !!(lc & 0x04);
|
hasCCT = !!(lc & 0x04);
|
||||||
}
|
}
|
||||||
if (!i) {
|
if (!i) {
|
||||||
|
@ -184,7 +184,7 @@
|
|||||||
if (t > 31 && t < 48) d.getElementsByName("LC"+n)[0].value = 1; // for sanity change analog count just to 1 LED
|
if (t > 31 && t < 48) d.getElementsByName("LC"+n)[0].value = 1; // for sanity change analog count just to 1 LED
|
||||||
}
|
}
|
||||||
gId("rf"+n).onclick = (t == 31) ? (()=>{return false}) : (()=>{}); // prevent change for TM1814
|
gId("rf"+n).onclick = (t == 31) ? (()=>{return false}) : (()=>{}); // prevent change for TM1814
|
||||||
isRGBW = (t == 30 || t == 31 || (t > 40 && t < 46 && t != 43) || t == 88); // RGBW checkbox, TYPE_xxxx values from const.h
|
isRGBW = ((t > 17 && t < 22) || t == 30 || t == 31 || (t > 40 && t < 46 && t != 43) || t == 88); // RGBW checkbox, TYPE_xxxx values from const.h
|
||||||
gId("co"+n).style.display = ((t >= 80 && t < 96) || (t >= 40 && t < 48)) ? "none":"inline"; // hide color order for PWM
|
gId("co"+n).style.display = ((t >= 80 && t < 96) || (t >= 40 && t < 48)) ? "none":"inline"; // hide color order for PWM
|
||||||
gId("dig"+n+"w").style.display = (t == 30 || t == 31) ? "inline":"none"; // show swap channels dropdown
|
gId("dig"+n+"w").style.display = (t == 30 || t == 31) ? "inline":"none"; // show swap channels dropdown
|
||||||
if (!(t == 30 || t == 31)) d.getElementsByName("WO"+n)[0].value = 0; // reset swapping
|
if (!(t == 30 || t == 31)) d.getElementsByName("WO"+n)[0].value = 0; // reset swapping
|
||||||
@ -335,6 +335,7 @@ ${i+1}:
|
|||||||
<option value="52">LPD8806</option>\
|
<option value="52">LPD8806</option>\
|
||||||
<option value="54">LPD6803</option>\
|
<option value="54">LPD6803</option>\
|
||||||
<option value="53">P9813</option>\
|
<option value="53">P9813</option>\
|
||||||
|
<option value="19">WS2811 White</option>\
|
||||||
<option value="40">On/Off</option>\
|
<option value="40">On/Off</option>\
|
||||||
<option value="41">PWM White</option>\
|
<option value="41">PWM White</option>\
|
||||||
<option value="42">PWM CCT</option>\
|
<option value="42">PWM CCT</option>\
|
||||||
@ -369,7 +370,7 @@ ${i+1}:
|
|||||||
<div id="dig${i}r" style="display:inline"><br><span id="rev${i}">Reversed</span>: <input type="checkbox" name="CV${i}"></div>
|
<div id="dig${i}r" style="display:inline"><br><span id="rev${i}">Reversed</span>: <input type="checkbox" name="CV${i}"></div>
|
||||||
<div id="dig${i}s" style="display:inline"><br>Skip first LEDs: <input type="number" name="SL${i}" min="0" max="255" value="0" oninput="UI()"></div>
|
<div id="dig${i}s" style="display:inline"><br>Skip first LEDs: <input type="number" name="SL${i}" min="0" max="255" value="0" oninput="UI()"></div>
|
||||||
<div id="dig${i}f" style="display:inline"><br>Off Refresh: <input id="rf${i}" type="checkbox" name="RF${i}"></div>
|
<div id="dig${i}f" style="display:inline"><br>Off Refresh: <input id="rf${i}" type="checkbox" name="RF${i}"></div>
|
||||||
<div id="dig${i}a" style="display:inline"><br>Auto-calculate white channel from RGB:<br><select name="AW${i}"><option value=0>None</option><option value=1>Brighter</option><option value=2>Accurate</option><option value=3>Dual</option></select> </div>
|
<div id="dig${i}a" style="display:inline"><br>Auto-calculate white channel from RGB:<br><select name="AW${i}"><option value=0>None</option><option value=1>Brighter</option><option value=2>Accurate</option><option value=3>Dual</option><option value=4>Max</option></select> </div>
|
||||||
</div>`;
|
</div>`;
|
||||||
f.insertAdjacentHTML("beforeend", cn);
|
f.insertAdjacentHTML("beforeend", cn);
|
||||||
}
|
}
|
||||||
@ -667,6 +668,7 @@ Length: <input type="number" name="XC${i}" id="xc${i}" class="l" min="1" max="65
|
|||||||
<option value=1>Brighter</option>
|
<option value=1>Brighter</option>
|
||||||
<option value=2>Accurate</option>
|
<option value=2>Accurate</option>
|
||||||
<option value=3>Dual</option>
|
<option value=3>Dual</option>
|
||||||
|
<option value=4>Max</option>
|
||||||
</select>
|
</select>
|
||||||
<br>
|
<br>
|
||||||
Calculate CCT from RGB: <input type="checkbox" name="CR"> <br>
|
Calculate CCT from RGB: <input type="checkbox" name="CR"> <br>
|
||||||
|
1498
wled00/html_other.h
1498
wled00/html_other.h
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
2241
wled00/html_simple.h
2241
wled00/html_simple.h
File diff suppressed because it is too large
Load Diff
1906
wled00/html_ui.h
1906
wled00/html_ui.h
File diff suppressed because it is too large
Load Diff
@ -83,7 +83,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
|||||||
cctFromRgb = request->hasArg(F("CR"));
|
cctFromRgb = request->hasArg(F("CR"));
|
||||||
strip.cctBlending = request->arg(F("CB")).toInt();
|
strip.cctBlending = request->arg(F("CB")).toInt();
|
||||||
Bus::setCCTBlend(strip.cctBlending);
|
Bus::setCCTBlend(strip.cctBlending);
|
||||||
Bus::setAutoWhiteMode(request->arg(F("AW")).toInt());
|
Bus::setGlobalAWMode(request->arg(F("AW")).toInt());
|
||||||
strip.setTargetFps(request->arg(F("FR")).toInt());
|
strip.setTargetFps(request->arg(F("FR")).toInt());
|
||||||
strip.useLedsArray = request->hasArg(F("LD"));
|
strip.useLedsArray = request->hasArg(F("LD"));
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// version code in format yymmddb (b = daily build)
|
// version code in format yymmddb (b = daily build)
|
||||||
#define VERSION 2302080
|
#define VERSION 2302120
|
||||||
|
|
||||||
//uncomment this if you have a "my_config.h" file you'd like to use
|
//uncomment this if you have a "my_config.h" file you'd like to use
|
||||||
//#define WLED_USE_MY_CONFIG
|
//#define WLED_USE_MY_CONFIG
|
||||||
|
@ -382,7 +382,7 @@ void getSettingsJS(byte subPage, char* dest)
|
|||||||
sappend('c',SET_F("CR"),cctFromRgb);
|
sappend('c',SET_F("CR"),cctFromRgb);
|
||||||
sappend('v',SET_F("CB"),strip.cctBlending);
|
sappend('v',SET_F("CB"),strip.cctBlending);
|
||||||
sappend('v',SET_F("FR"),strip.getTargetFps());
|
sappend('v',SET_F("FR"),strip.getTargetFps());
|
||||||
sappend('v',SET_F("AW"),Bus::getAutoWhiteMode());
|
sappend('v',SET_F("AW"),Bus::getGlobalAWMode());
|
||||||
sappend('v',SET_F("LD"),strip.useLedsArray);
|
sappend('v',SET_F("LD"),strip.useLedsArray);
|
||||||
|
|
||||||
for (uint8_t s=0; s < busses.getNumBusses(); s++) {
|
for (uint8_t s=0; s < busses.getNumBusses(); s++) {
|
||||||
@ -412,7 +412,7 @@ void getSettingsJS(byte subPage, char* dest)
|
|||||||
sappend('c',cv,bus->reversed);
|
sappend('c',cv,bus->reversed);
|
||||||
sappend('v',sl,bus->skippedLeds());
|
sappend('v',sl,bus->skippedLeds());
|
||||||
sappend('c',rf,bus->isOffRefreshRequired());
|
sappend('c',rf,bus->isOffRefreshRequired());
|
||||||
sappend('v',aw,bus->getAWMode());
|
sappend('v',aw,bus->getAutoWhiteMode());
|
||||||
sappend('v',wo,bus->getColorOrder() >> 4);
|
sappend('v',wo,bus->getColorOrder() >> 4);
|
||||||
}
|
}
|
||||||
sappend('v',SET_F("MA"),strip.ablMilliampsMax);
|
sappend('v',SET_F("MA"),strip.ablMilliampsMax);
|
||||||
|
Loading…
Reference in New Issue
Block a user