Squashed commit of the white-balance branch.

Updated simple UI.
Minor change in ST7789 display.
This commit is contained in:
Blaz Kristan 2021-10-16 15:13:30 +02:00
parent 5a658b7080
commit c2e6d1c6bf
22 changed files with 4445 additions and 4206 deletions

View File

@ -92,7 +92,7 @@ class St7789DisplayUsermod : public Usermod {
updateLocalTime(); updateLocalTime();
byte minuteCurrent = minute(localTime); byte minuteCurrent = minute(localTime);
byte hourCurrent = hour(localTime); byte hourCurrent = hour(localTime);
byte secondCurrent = second(localTime); //byte secondCurrent = second(localTime);
knownMinute = minuteCurrent; knownMinute = minuteCurrent;
knownHour = hourCurrent; knownHour = hourCurrent;
@ -140,7 +140,7 @@ class St7789DisplayUsermod : public Usermod {
void setup() void setup()
{ {
PinManagerPinType pins[] = { { TFT_MOSI, true }, { TFT_MISO, false}, { TFT_SCLK, true }, { TFT_CS, true}, { TFT_DC, true}, { TFT_RST, true }, { TFT_BL, true } }; PinManagerPinType pins[] = { { TFT_MOSI, true }, { TFT_MISO, false}, { TFT_SCLK, true }, { TFT_CS, true}, { TFT_DC, true}, { TFT_RST, true }, { TFT_BL, true } };
if (!pinManager.allocateMultiplePins(pins, 5, PinOwner::UM_FourLineDisplay)) { return; } if (!pinManager.allocateMultiplePins(pins, 7, PinOwner::UM_FourLineDisplay)) { return; }
tft.init(); tft.init();
tft.setRotation(0); //Rotation here is set up for the text to be readable with the port on the left. Use 1 to flip. tft.setRotation(0); //Rotation here is set up for the text to be readable with the port on the left. Use 1 to flip.
@ -364,19 +364,14 @@ class St7789DisplayUsermod : public Usermod {
* Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI. * Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI.
* Below it is shown how this could be used for e.g. a light sensor * Below it is shown how this could be used for e.g. a light sensor
*/ */
/*
void addToJsonInfo(JsonObject& root) void addToJsonInfo(JsonObject& root)
{ {
int reading = 20;
//this code adds "u":{"Light":[20," lux"]} to the info object
JsonObject user = root["u"]; JsonObject user = root["u"];
if (user.isNull()) user = root.createNestedObject("u"); if (user.isNull()) user = root.createNestedObject("u");
JsonArray lightArr = user.createNestedArray("Light"); //name JsonArray lightArr = user.createNestedArray("ST7789"); //name
lightArr.add(reading); //value lightArr.add(F("installed")); //unit
lightArr.add(" lux"); //unit
} }
*/
/* /*

View File

@ -166,7 +166,7 @@
#define FX_MODE_GRADIENT 46 #define FX_MODE_GRADIENT 46
#define FX_MODE_LOADING 47 #define FX_MODE_LOADING 47
#define FX_MODE_POLICE 48 #define FX_MODE_POLICE 48
#define FX_MODE_POLICE_ALL 49 #define FX_MODE_POLICE_ALL 49 // candidate for removal
#define FX_MODE_TWO_DOTS 50 #define FX_MODE_TWO_DOTS 50
#define FX_MODE_TWO_AREAS 51 #define FX_MODE_TWO_AREAS 51
#define FX_MODE_RUNNING_DUAL 52 #define FX_MODE_RUNNING_DUAL 52
@ -247,7 +247,7 @@ class WS2812FX {
// segment parameters // segment parameters
public: public:
typedef struct Segment { // 29 (32 in memory?) bytes typedef struct Segment { // 30 (33 in memory?) bytes
uint16_t start; uint16_t start;
uint16_t stop; //segment invalid if stop == 0 uint16_t stop; //segment invalid if stop == 0
uint16_t offset; uint16_t offset;
@ -259,6 +259,7 @@ class WS2812FX {
uint8_t grouping, spacing; uint8_t grouping, spacing;
uint8_t opacity; uint8_t opacity;
uint32_t colors[NUM_COLORS]; uint32_t colors[NUM_COLORS];
uint8_t cct; //0==2000K, 255==10160K
char *name; char *name;
bool setColor(uint8_t slot, uint32_t c, uint8_t segn) { //returns true if changed bool setColor(uint8_t slot, uint32_t c, uint8_t segn) { //returns true if changed
if (slot >= NUM_COLORS || segn >= MAX_NUM_SEGMENTS) return false; if (slot >= NUM_COLORS || segn >= MAX_NUM_SEGMENTS) return false;

View File

@ -220,6 +220,17 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w)
uint16_t realIndex = realPixelIndex(i); uint16_t realIndex = realPixelIndex(i);
uint16_t len = SEGMENT.length(); uint16_t len = SEGMENT.length();
// determine if we can do white balance
int16_t cct = -1;
for (uint8_t b = 0; b < busses.getNumBusses(); b++) {
Bus *bus = busses.getBus(b);
if (bus == nullptr || !bus->containsPixel(realIndex)) continue;
if (allowCCT || bus->getType() == TYPE_ANALOG_2CH || bus->getType() == TYPE_ANALOG_5CH) {
cct = SEGMENT.cct;
break;
}
}
for (uint16_t j = 0; j < SEGMENT.grouping; j++) { for (uint16_t j = 0; j < SEGMENT.grouping; j++) {
uint16_t indexSet = realIndex + (IS_REVERSE ? -j : j); uint16_t indexSet = realIndex + (IS_REVERSE ? -j : j);
if (indexSet >= SEGMENT.start && indexSet < SEGMENT.stop) { if (indexSet >= SEGMENT.start && indexSet < SEGMENT.stop) {
@ -230,14 +241,14 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w)
if (indexMir >= SEGMENT.stop) indexMir -= len; if (indexMir >= SEGMENT.stop) indexMir -= len;
if (indexMir < customMappingSize) indexMir = customMappingTable[indexMir]; if (indexMir < customMappingSize) indexMir = customMappingTable[indexMir];
busses.setPixelColor(indexMir, col); busses.setPixelColor(indexMir, col, cct);
} }
/* offset/phase */ /* offset/phase */
indexSet += SEGMENT.offset; indexSet += SEGMENT.offset;
if (indexSet >= SEGMENT.stop) indexSet -= len; if (indexSet >= SEGMENT.stop) indexSet -= len;
if (indexSet < customMappingSize) indexSet = customMappingTable[indexSet]; if (indexSet < customMappingSize) indexSet = customMappingTable[indexSet];
busses.setPixelColor(indexSet, col); busses.setPixelColor(indexSet, col, cct);
} }
} }
} else { //live data, etc. } else { //live data, etc.
@ -624,6 +635,7 @@ void WS2812FX::resetSegments() {
_segments[0].setOption(SEG_OPTION_SELECTED, 1); _segments[0].setOption(SEG_OPTION_SELECTED, 1);
_segments[0].setOption(SEG_OPTION_ON, 1); _segments[0].setOption(SEG_OPTION_ON, 1);
_segments[0].opacity = 255; _segments[0].opacity = 255;
_segments[0].cct = 128;
for (uint16_t i = 1; i < MAX_NUM_SEGMENTS; i++) for (uint16_t i = 1; i < MAX_NUM_SEGMENTS; i++)
{ {
@ -631,6 +643,7 @@ void WS2812FX::resetSegments() {
_segments[i].grouping = 1; _segments[i].grouping = 1;
_segments[i].setOption(SEG_OPTION_ON, 1); _segments[i].setOption(SEG_OPTION_ON, 1);
_segments[i].opacity = 255; _segments[i].opacity = 255;
_segments[i].cct = 128;
_segments[i].speed = DEFAULT_SPEED; _segments[i].speed = DEFAULT_SPEED;
_segments[i].intensity = DEFAULT_INTENSITY; _segments[i].intensity = DEFAULT_INTENSITY;
_segment_runtimes[i].reset(); _segment_runtimes[i].reset();

View File

@ -10,6 +10,9 @@
#include "bus_wrapper.h" #include "bus_wrapper.h"
#include <Arduino.h> #include <Arduino.h>
//color.cpp
uint32_t colorBalanceFromKelvin(uint16_t kelvin, uint32_t rgb);
// enable additional debug output // enable additional debug output
#ifdef WLED_DEBUG #ifdef WLED_DEBUG
#ifndef ESP8266 #ifndef ESP8266
@ -70,66 +73,35 @@ class Bus {
_start = start; _start = start;
}; };
virtual ~Bus() {} //throw the bus under the bus
virtual void show() {} virtual void show() {}
virtual bool canShow() { return true; } virtual bool canShow() { return true; }
virtual void setPixelColor(uint16_t pix, uint32_t c) {}; virtual void setPixelColor(uint16_t pix, uint32_t c) {};
virtual void setPixelColor(uint16_t pix, uint32_t c, uint8_t cct) {};
virtual void setBrightness(uint8_t b) {};
virtual uint32_t getPixelColor(uint16_t pix) { return 0; }; virtual uint32_t getPixelColor(uint16_t pix) { return 0; };
virtual void setBrightness(uint8_t b) {};
virtual void cleanup() {}; virtual void cleanup() {};
virtual ~Bus() { //throw the bus under the bus
}
virtual uint8_t getPins(uint8_t* pinArray) { return 0; } virtual uint8_t getPins(uint8_t* pinArray) { return 0; }
virtual uint16_t getLength() { return 1; }
inline uint16_t getStart() {
return _start;
}
inline void setStart(uint16_t start) {
_start = start;
}
virtual uint16_t getLength() {
return 1; // is this ok? shouldn't it be 0 in virtual function?
}
virtual void setColorOrder() {} virtual void setColorOrder() {}
virtual uint8_t getColorOrder() { return COL_ORDER_RGB; }
virtual uint8_t skippedLeds() { return 0; }
virtual uint8_t getColorOrder() { inline uint16_t getStart() { return _start; }
return COL_ORDER_RGB; inline void setStart(uint16_t start) { _start = start; }
} inline uint8_t getType() { return _type; }
inline bool isOk() { return _valid; }
virtual bool isRgbw() { inline bool isOffRefreshRequired() { return _needsRefresh; }
return false; inline bool containsPixel(uint16_t pix) { return pix >= _start; }
}
virtual uint8_t skippedLeds() {
return 0;
}
inline uint8_t getType() {
return _type;
}
inline bool isOk() {
return _valid;
}
virtual bool isRgbw() { return false; }
static bool isRgbw(uint8_t type) { static bool isRgbw(uint8_t type) {
if (type == TYPE_SK6812_RGBW || type == TYPE_TM1814) return true; 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_ONOFF && type <= TYPE_ANALOG_5CH && type != TYPE_ANALOG_3CH) return true;
return false; return false;
} }
inline bool isOffRefreshRequired() {
return _needsRefresh;
}
bool reversed = false; bool reversed = false;
protected: protected:
@ -190,6 +162,11 @@ class BusDigital : public Bus {
PolyBus::setPixelColor(_busPtr, _iType, pix, c, _colorOrder); PolyBus::setPixelColor(_busPtr, _iType, pix, c, _colorOrder);
} }
void setPixelColor(uint16_t pix, uint32_t c, uint8_t cct) {
c = colorBalanceFromKelvin(2000+(cct<<5), c); // color correction from CCT
setPixelColor(pix, c);
}
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;
@ -285,6 +262,34 @@ class BusPwm : public Bus {
_valid = true; _valid = true;
}; };
void setPixelColor(uint16_t pix, uint32_t c, uint8_t cct) {
if (pix != 0 || !_valid) return; //only react to first pixel
c = colorBalanceFromKelvin(2000+(cct<<5), c); // color correction from CCT (w remains unchanged)
uint8_t r = c >> 16;
uint8_t g = c >> 8;
uint8_t b = c ;
uint8_t w = c >> 24;
switch (_type) {
case TYPE_ANALOG_1CH: //one channel (white), use highest RGBW value
_data[0] = max(r, max(g, max(b, w)));
break;
case TYPE_ANALOG_2CH: //warm white + cold white
// perhaps a non-linear adjustment would be in order. need to test
_data[1] = (w * cct) / 255;
_data[0] = 255 - _data[1]; // or (w * (255-cct)) / 255;
break;
case TYPE_ANALOG_5CH: //RGB + warm white + cold white
// perhaps a non-linear adjustment would be in order. need to test
_data[4] = (w * cct) / 255; w = 255 - w; // or (w * (255-cct)) / 255;
case TYPE_ANALOG_4CH: //RGBW
_data[3] = w;
case TYPE_ANALOG_3CH: //standard dumb RGB
_data[0] = r; _data[1] = g; _data[2] = b;
break;
}
}
void setPixelColor(uint16_t pix, uint32_t c) { void setPixelColor(uint16_t pix, uint32_t c) {
if (pix != 0 || !_valid) return; //only react to first pixel if (pix != 0 || !_valid) return; //only react to first pixel
uint8_t r = c >> 16; uint8_t r = c >> 16;
@ -295,14 +300,11 @@ class BusPwm : public Bus {
switch (_type) { switch (_type) {
case TYPE_ANALOG_1CH: //one channel (white), use highest RGBW value case TYPE_ANALOG_1CH: //one channel (white), use highest RGBW value
_data[0] = max(r, max(g, max(b, w))); break; _data[0] = max(r, max(g, max(b, w))); break;
case TYPE_ANALOG_2CH: //warm white + cold white
case TYPE_ANALOG_2CH: //warm white + cold white, we'll need some nice handling here, for now just R+G channels
case TYPE_ANALOG_3CH: //standard dumb RGB case TYPE_ANALOG_3CH: //standard dumb RGB
case TYPE_ANALOG_4CH: //RGBW case TYPE_ANALOG_4CH: //standard dumb RGBW
case TYPE_ANALOG_5CH: //we'll want the white handling from 2CH here + RGB case TYPE_ANALOG_5CH: //we'll want the white handling from 2CH here + RGB
_data[0] = r; _data[1] = g; _data[2] = b; _data[3] = w; _data[4] = 0; break; _data[0] = r; _data[1] = g; _data[2] = b; _data[3] = w; _data[4] = 0; break;
default: return;
} }
} }
@ -419,6 +421,11 @@ class BusNetwork : public Bus {
if (_rgbw) _data[offset+3] = 0xFF & (c >> 24); if (_rgbw) _data[offset+3] = 0xFF & (c >> 24);
} }
void setPixelColor(uint16_t pix, uint32_t c, uint8_t cct) {
c = colorBalanceFromKelvin(2000+(cct<<5), c); // color correction from CCT
setPixelColor(pix, c);
}
uint32_t getPixelColor(uint16_t pix) { uint32_t getPixelColor(uint16_t pix) {
if (!_valid || pix >= _len) return 0; if (!_valid || pix >= _len) return 0;
uint16_t offset = pix * _UDPchannels; uint16_t offset = pix * _UDPchannels;
@ -540,12 +547,13 @@ class BusManager {
} }
} }
void setPixelColor(uint16_t pix, uint32_t c) { void setPixelColor(uint16_t pix, uint32_t c, int16_t cct=-1) {
for (uint8_t i = 0; i < numBusses; i++) { for (uint8_t i = 0; i < numBusses; i++) {
Bus* b = busses[i]; Bus* b = busses[i];
uint16_t bstart = b->getStart(); uint16_t bstart = b->getStart();
if (pix < bstart || pix >= bstart + b->getLength()) continue; if (pix < bstart || pix >= bstart + b->getLength()) continue;
busses[i]->setPixelColor(pix - bstart, c); if (cct<0) busses[i]->setPixelColor(pix - bstart, c); // no white balance
else busses[i]->setPixelColor(pix - bstart, c, cct); // do white balance
} }
} }

View File

@ -86,6 +86,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
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")]);
CJSON(strip.rgbwMode, hw_led[F("rgbwm")]); CJSON(strip.rgbwMode, hw_led[F("rgbwm")]);
CJSON(allowCCT, hw_led["cct"]);
JsonArray ins = hw_led["ins"]; JsonArray ins = hw_led["ins"];
@ -534,6 +535,7 @@ void serializeConfig() {
hw_led[F("maxpwr")] = strip.ablMilliampsMax; hw_led[F("maxpwr")] = strip.ablMilliampsMax;
hw_led[F("ledma")] = strip.milliampsPerLed; hw_led[F("ledma")] = strip.milliampsPerLed;
hw_led[F("rgbwm")] = strip.rgbwMode; hw_led[F("rgbwm")] = strip.rgbwMode;
hw_led["cct"] = allowCCT;
JsonArray hw_led_ins = hw_led.createNestedArray("ins"); JsonArray hw_led_ins = hw_led.createNestedArray("ins");
@ -550,7 +552,7 @@ void serializeConfig() {
ins[F("order")] = bus->getColorOrder(); ins[F("order")] = bus->getColorOrder();
ins["rev"] = bus->reversed; ins["rev"] = bus->reversed;
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("rgbw")] = bus->isRgbw(); ins[F("rgbw")] = bus->isRgbw();
} }

View File

@ -67,6 +67,7 @@ void colorHStoRGB(uint16_t hue, byte sat, byte* rgb) //hue, sat to rgb
if (strip.isRgbw && strip.rgbwMode == RGBW_MODE_LEGACY) colorRGBtoRGBW(col); if (strip.isRgbw && strip.rgbwMode == RGBW_MODE_LEGACY) colorRGBtoRGBW(col);
} }
//get RGB values from color temperature in K (https://tannerhelland.com/2012/09/18/convert-temperature-rgb-algorithm-code.html)
void colorKtoRGB(uint16_t kelvin, byte* rgb) //white spectrum to rgb, calc void colorKtoRGB(uint16_t kelvin, byte* rgb) //white spectrum to rgb, calc
{ {
float r = 0, g = 0, b = 0; float r = 0, g = 0, b = 0;
@ -84,7 +85,7 @@ void colorKtoRGB(uint16_t kelvin, byte* rgb) //white spectrum to rgb, calc
g = round(288.1221695283 * pow((temp - 60), -0.0755148492)); g = round(288.1221695283 * pow((temp - 60), -0.0755148492));
b = 255; b = 255;
} }
g += 15; //mod by Aircoookie, a bit less accurate but visibly less pinkish //g += 15; //mod by Aircoookie, a bit less accurate but visibly less pinkish
rgb[0] = (uint8_t) constrain(r, 0, 255); rgb[0] = (uint8_t) constrain(r, 0, 255);
rgb[1] = (uint8_t) constrain(g, 0, 255); rgb[1] = (uint8_t) constrain(g, 0, 255);
rgb[2] = (uint8_t) constrain(b, 0, 255); rgb[2] = (uint8_t) constrain(b, 0, 255);
@ -244,3 +245,24 @@ void colorRGBtoRGBW(byte* rgb) //rgb to rgbw (http://codewelt.com/rgbw). (RGBW_M
float sat = 100.0f * ((high - low) / high);; // maximum saturation is 100 (corrected from 255) float sat = 100.0f * ((high - low) / high);; // maximum saturation is 100 (corrected from 255)
rgb[3] = (byte)((255.0f - sat) / 255.0f * (rgb[0] + rgb[1] + rgb[2]) / 3); rgb[3] = (byte)((255.0f - sat) / 255.0f * (rgb[0] + rgb[1] + rgb[2]) / 3);
} }
// adjust RGB values based on color temperature in K (range [2800-10200]) (https://en.wikipedia.org/wiki/Color_balance)
void colorBalanceFromKelvin(uint16_t kelvin, byte *rgb)
{
byte rgbw[4] = {0,0,0,0};
colorKtoRGB(kelvin, rgbw); // convert Kelvin to RGB
rgb[0] = ((uint16_t) rgbw[0] * rgb[0]) / 255; // correct R
rgb[1] = ((uint16_t) rgbw[1] * rgb[1]) / 255; // correct G
rgb[2] = ((uint16_t) rgbw[2] * rgb[2]) / 255; // correct B
}
uint32_t colorBalanceFromKelvin(uint16_t kelvin, uint32_t rgb)
{
byte rgbw[4] = {0,0,0,0};
colorKtoRGB(kelvin, rgbw); // convert Kelvin to RGB
rgbw[0] = ((uint16_t) rgbw[0] * ((rgb>>16) & 0xFF)) / 255; // correct R
rgbw[1] = ((uint16_t) rgbw[1] * ((rgb>> 8) & 0xFF)) / 255; // correct G
rgbw[2] = ((uint16_t) rgbw[2] * ((rgb ) & 0xFF)) / 255; // correct B
rgbw[3] = ((rgb>>24) & 0xFF);
return colorFromRgbw(rgbw);
}

View File

@ -456,17 +456,23 @@ button {
#info table, #nodes table { #info table, #nodes table {
table-layout: fixed; table-layout: fixed;
width: 490px; width: 100%;
margin: auto;
} }
#info td, #nodes td { #info td, #nodes td {
padding-bottom: 8px; padding-bottom: 8px;
} }
#info .btn, #nodes .btn { #info .btn {
margin: 5px;
}
#info table .btn, #nodes table .btn {
margin: 0; margin: 0;
} }
#info div, #nodes div {
width: 490px;
margin: 0 auto;
}
#lv { #lv {
max-width: 600px; max-width: 600px;
@ -498,13 +504,28 @@ img {
.sliderdisplay { .sliderdisplay {
content:''; content:'';
position: absolute; position: absolute;
top: 13px; bottom: 13px; top: 13px; left: 8px; right: 8px;
left: 10px; right: 10px; height: 4px;
background: var(--c-4); background: var(--c-4);
border-radius: 17px; border-radius: 16px;
pointer-events: none; pointer-events: none;
z-index: -1; z-index: -1;
} }
#rwrap .sliderdisplay,
#gwrap .sliderdisplay,
#bwrap .sliderdisplay,
#wwrap .sliderdisplay,
#wbal .sliderdisplay {
height: 28px;
top: 0; bottom: 0;
left: 0; right: 0;
/*border: 1px solid var(--c-b);*/
}
#rwrap .sliderdisplay { background: linear-gradient(90deg, #000 0%, #f00); }
#gwrap .sliderdisplay { background: linear-gradient(90deg, #000 0%, #0f0); }
#bwrap .sliderdisplay { background: linear-gradient(90deg, #000 0%, #00f); }
#wwrap .sliderdisplay { background: linear-gradient(90deg, #000 0%, #fff); }
#wbal .sliderdisplay { background: linear-gradient(90deg, #ff8f1f 0%, #fff 50%, #d4e0ff); }
.sliderbubble { .sliderbubble {
width: 24px; width: 24px;
@ -515,7 +536,7 @@ img {
color: var(--c-f); color: var(--c-f);
padding: 4px 4px 2px; padding: 4px 4px 2px;
font-size: 14px; font-size: 14px;
right: 5px; right: 3px;
transition: visibility 0.25s ease, opacity 0.25s ease; transition: visibility 0.25s ease, opacity 0.25s ease;
opacity: 0; opacity: 0;
visibility: hidden; visibility: hidden;
@ -532,12 +553,20 @@ output.sliderbubbleshow {
input[type=range] { input[type=range] {
-webkit-appearance: none; -webkit-appearance: none;
width: 220px; width: 100%;
padding: 0px; padding: 0;
margin: 0px 10px 0px 10px; margin: 0;
background-color: transparent; background-color: transparent;
cursor: pointer; cursor: pointer;
} }
#rwrap input[type=range],
#gwrap input[type=range],
#bwrap input[type=range],
#wwrap input[type=range],
#wbal input[type=range] {
width: 252px;
margin: 0;
}
input[type=range]:focus { input[type=range]:focus {
outline: none; outline: none;
} }
@ -550,7 +579,7 @@ input[type=range]::-webkit-slider-runnable-track {
input[type=range]::-webkit-slider-thumb { input[type=range]::-webkit-slider-thumb {
height: 16px; height: 16px;
width: 16px; width: 16px;
border-radius: 17px; border-radius: 50%;
background: var(--c-f); background: var(--c-f);
cursor: pointer; cursor: pointer;
-webkit-appearance: none; -webkit-appearance: none;
@ -565,19 +594,44 @@ input[type=range]::-moz-range-thumb {
border: 0px solid rgba(0, 0, 0, 0); border: 0px solid rgba(0, 0, 0, 0);
height: 16px; height: 16px;
width: 16px; width: 16px;
border-radius: 17px; border-radius: 50%;
background: var(--c-f); background: var(--c-f);
transform: translateY(7px); transform: translateY(5px);
} }
#wwrap { #rwrap input[type=range]::-webkit-slider-thumb,
display: none; #gwrap input[type=range]::-webkit-slider-thumb,
#bwrap input[type=range]::-webkit-slider-thumb,
#wwrap input[type=range]::-webkit-slider-thumb,
#wbal input[type=range]::-webkit-slider-thumb {
height: 18px;
width: 18px;
border: 2px solid #000;
margin-top: 5px;
}
#rwrap input[type=range]::-moz-range-thumb,
#gwrap input[type=range]::-moz-range-thumb,
#bwrap input[type=range]::-moz-range-thumb,
#wwrap input[type=range]::-moz-range-thumb,
#wbal input[type=range]::-moz-range-thumb {
border: 2px solid var(--c-1);
}
#wwrap, #wbal {
display: block;
} }
.sliderwrap { .sliderwrap {
height: 30px; height: 30px;
width: 240px; width: 230px;
position: relative; position: relative;
} }
#rwrap .sliderwrap,
#gwrap .sliderwrap,
#bwrap .sliderwrap,
#wwrap .sliderwrap,
#wbal .sliderwrap {
width: 260px;
margin: 10px 0 0;
}
.hd { .hd {
display: var(--bhd); display: var(--bhd);
@ -589,7 +643,7 @@ input[type=range]::-moz-range-thumb {
} }
#picker { #picker {
margin: 10px auto; margin: 10px auto 0;
width: 260px; width: 260px;
} }
@ -1141,9 +1195,9 @@ input[type="text"].fnd:hover {
@media all and (max-width: 550px) and (min-width: 374px) { @media all and (max-width: 550px) and (min-width: 374px) {
#info .btn, #nodes .btn { #info .btn, #nodes .btn {
width: 155px; width: 150px;
} }
#info table, #nodes table { #info div, #nodes div {
width: 320px; width: 320px;
} }
} }

View File

@ -49,33 +49,41 @@
<div id="rgbwrap"> <div id="rgbwrap">
<div id="rwrap" class="il"> <div id="rwrap" class="il">
<div class="sliderwrap il"> <div class="sliderwrap il">
<input id="sliderR" class="noslide" onchange="fromRgb()" oninput="updateTrail(this,1)" max="255" min="0" type="range" value="128" /> <input id="sliderR" class="noslide" onchange="fromRgb()" xoninput="updateTrail(this,1)" max="255" min="0" type="range" value="128" />
<div class="sliderdisplay"></div> <div class="sliderdisplay"></div>
</div> </div>
<output class="sliderbubble"></output> <!--output class="sliderbubble"></output-->
</div><br> </div><br>
<div id="gwrap" class="il"> <div id="gwrap" class="il">
<div class="sliderwrap il"> <div class="sliderwrap il">
<input id="sliderG" class="noslide" onchange="fromRgb()" oninput="updateTrail(this,2)" max="255" min="0" type="range" value="128" /> <input id="sliderG" class="noslide" onchange="fromRgb()" xoninput="updateTrail(this,2)" max="255" min="0" type="range" value="128" />
<div class="sliderdisplay"></div> <div class="sliderdisplay"></div>
</div> </div>
<output class="sliderbubble"></output> <!--output class="sliderbubble"></output-->
</div><br> </div><br>
<div id="bwrap" class="il"> <div id="bwrap" class="il">
<div class="sliderwrap il"> <div class="sliderwrap il">
<input id="sliderB" class="noslide" onchange="fromRgb()" oninput="updateTrail(this,3)" max="255" min="0" type="range" value="128" /> <input id="sliderB" class="noslide" onchange="fromRgb()" xoninput="updateTrail(this,3)" max="255" min="0" type="range" value="128" />
<div class="sliderdisplay"></div> <div class="sliderdisplay"></div>
</div> </div>
<output class="sliderbubble"></output> <!--output class="sliderbubble"></output-->
</div><br> </div><br>
</div> </div>
<div id="wwrap"> <div id="wwrap">
<p class="labels">White channel</p> <p class="labels hd">White channel</p>
<div class="sliderwrap il"> <div id="whibri" class="sliderwrap il">
<input id="sliderW" class="noslide" onchange="setColor(0)" oninput="updateTrail(this)" max="255" min="0" type="range" value="128" /> <input id="sliderW" class="noslide" onchange="setColor(0)" xoninput="updateTrail(this,4)" max="255" min="0" type="range" value="128" />
<div class="sliderdisplay"></div> <div class="sliderdisplay"></div>
<output class="sliderbubble"></output>
</div> </div>
<!--output class="sliderbubble"></output-->
</div>
<div id="wbal">
<p class="labels hd">White balance</p>
<div class="sliderwrap il">
<input id="sliderA" class="noslide" onchange="setBalance(this.value)" xoninput="updateTrail(this,5)" max="255" min="0" type="range" value="128" />
<div class="sliderdisplay"></div>
</div>
<!--output class="sliderbubble"></output-->
</div> </div>
<div id="qcs-w"> <div id="qcs-w">
<div class="qcs" onclick="pC('#ff0000');" title="Red" style="background-color:#ff0000;"></div> <div class="qcs" onclick="pC('#ff0000');" title="Red" style="background-color:#ff0000;"></div>
@ -201,28 +209,32 @@
<img class="wi" alt="" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB0AAAAFCAYAAAC5Fuf5AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABbSURBVChTlY9bDoAwDMNW7n9nwCipytQN4Z8tbrTHmDmF4oPzyldwRqp1SSdnV/NuZuzqerAByxXznBw3igkeFEfXyUuhK/yFM0CxJfyqXZEOc6/Sr9/bf7uIC5Nwd7orMvAPAAAAAElFTkSuQmCC" /> <img class="wi" alt="" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB0AAAAFCAYAAAC5Fuf5AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABbSURBVChTlY9bDoAwDMNW7n9nwCipytQN4Z8tbrTHmDmF4oPzyldwRqp1SSdnV/NuZuzqerAByxXznBw3igkeFEfXyUuhK/yFM0CxJfyqXZEOc6/Sr9/bf7uIC5Nwd7orMvAPAAAAAElFTkSuQmCC" />
</div><br> </div><br>
<div id="kv">Loading...</div><br> <div id="kv">Loading...</div><br>
<table> <div>
<!--table>
<tr> <tr>
<td class="keytd"><button class="btn" onclick="loadInfo()">Refresh</button></td> <td class="keytd"--><button class="btn" onclick="loadInfo()">Refresh</button><!--/td>
<td class="valtd"><button class="btn" onclick="toggleInfo()">Close Info</button></td> <td class="valtd"--><button class="btn" onclick="toggleInfo()">Close Info</button><!--/td>
</tr> </tr>
<tr> <tr>
<td class="keytd"><button class="btn" onclick="toggleNodes()">Instance List</button></td> <td class="keytd"--><button class="btn" onclick="toggleNodes()">Instance List</button><!--/td>
<td class="valtd"><button class="btn" id="resetbtn" onclick="cnfReset()">Reboot WLED</button></td> <td class="valtd"--><button class="btn" id="resetbtn" onclick="cnfReset()">Reboot WLED</button><!--/td>
</tr> </tr>
</table><br> </table-->
</div><br>
<span class="h">Made with <span id="heart">&#10084;&#xFE0E;</span> by Aircoookie and the WLED community</span> <span class="h">Made with <span id="heart">&#10084;&#xFE0E;</span> by Aircoookie and the WLED community</span>
</div> </div>
<div id="nodes" class="modal"> <div id="nodes" class="modal">
<div id="ndlt">WLED instances</div> <div id="ndlt">WLED instances</div>
<div id="kn">Loading...</div><br> <div id="kn">Loading...</div><br>
<table> <div>
<!--table>
<tr> <tr>
<td class="keytd"><button class="btn infobtn" onclick="loadNodes()">Refresh</button></td> <td class="keytd"--><button class="btn infobtn" onclick="loadNodes()">Refresh</button><!--/td>
<td class="valtd"><button class="btn infobtn" onclick="toggleNodes()">Close list</button></td> <td class="valtd"--><button class="btn infobtn" onclick="toggleNodes()">Close list</button><!--/td>
</tr> </tr>
</table><br> </table-->
</div><br>
</div> </div>
<div id="rover" class="modal"> <div id="rover" class="modal">

View File

@ -49,15 +49,15 @@ var cpick = new iro.ColorPicker("#picker", {
{ {
component: iro.ui.Slider, component: iro.ui.Slider,
options: { sliderType: 'value' } options: { sliderType: 'value' }
}, }/*,
{ {
component: iro.ui.Slider, component: iro.ui.Slider,
options: { options: {
sliderType: 'kelvin', sliderType: 'kelvin',
minTemperature: 2100, minTemperature: 2000,
maxTemperature: 10000 maxTemperature: 10160
}
} }
}*/
] ]
}); });
@ -253,7 +253,6 @@ function onLoad()
}); });
}); });
resetUtil(); resetUtil();
updateUI(true);
d.addEventListener("visibilitychange", handleVisibilityChange, false); d.addEventListener("visibilitychange", handleVisibilityChange, false);
size(); size();
@ -392,7 +391,7 @@ function presetError(empty)
if (bckstr.length > 10) hasBackup = true; if (bckstr.length > 10) hasBackup = true;
} catch (e) {} } catch (e) {}
var cn = `<div class="seg c">`; var cn = `<div class="seg c" style="padding:8px;">`;
if (empty) if (empty)
cn += `You have no presets yet!`; cn += `You have no presets yet!`;
else else
@ -593,6 +592,7 @@ function loadInfo(callback=null)
parseInfo(); parseInfo();
showNodes(); showNodes();
if (isInfo) populateInfo(json); if (isInfo) populateInfo(json);
updateUI();
reqsLegal = true; reqsLegal = true;
if (!ws && lastinfo.ws > -1) setTimeout(makeWS,500); if (!ws && lastinfo.ws > -1) setTimeout(makeWS,500);
}) })
@ -949,7 +949,10 @@ function updateTrail(e, slidercol)
case 3: scol = "#00f"; break; case 3: scol = "#00f"; break;
default: scol = "var(--c-f)"; default: scol = "var(--c-f)";
} }
var val = `linear-gradient(90deg, ${scol} ${perc}%, var(--c-4) ${perc}%)`; var g = `${scol} ${perc}%, var(--c-4) ${perc}%`;
if (slidercol==4) g = `#000 0%, #fff`;
if (slidercol==5) g = `#ff8f1f 0%, #fff 50%, #d4e0ff`;
var val = `linear-gradient(90deg, ${g})`;
e.parentNode.getElementsByClassName('sliderdisplay')[0].style.background = val; e.parentNode.getElementsByClassName('sliderdisplay')[0].style.background = val;
var bubble = e.parentNode.parentNode.getElementsByTagName('output')[0]; var bubble = e.parentNode.parentNode.getElementsByTagName('output')[0];
if (bubble) bubble.innerHTML = e.value; if (bubble) bubble.innerHTML = e.value;
@ -1013,28 +1016,30 @@ function updatePA(scrollto=false)
} }
} }
function updateUI(scrollto=false) function updateUI()
{ {
gId('buttonPower').className = (isOn) ? "active":""; gId('buttonPower').className = (isOn) ? "active":"";
gId('buttonNl').className = (nlA) ? "active":""; gId('buttonNl').className = (nlA) ? "active":"";
gId('buttonSync').className = (syncSend) ? "active":""; gId('buttonSync').className = (syncSend) ? "active":"";
showNodes(); showNodes();
updateSelectedPalette(scrollto); updateSelectedPalette();
updateSelectedFx(scrollto); updateSelectedFx();
updateTrail(gId('sliderBri')); updateTrail(gId('sliderBri'));
updateTrail(gId('sliderSpeed')); updateTrail(gId('sliderSpeed'));
updateTrail(gId('sliderIntensity')); updateTrail(gId('sliderIntensity'));
updateTrail(gId('sliderW')); //updateTrail(gId('sliderW'),4);
//updateTrail(gId('sliderA'),5);
if (isRgbw) gId('wwrap').style.display = "block"; if (isRgbw) gId('wwrap').style.display = "block";
gId("wbal").style.display = (lastinfo.leds.cct) ? "block":"none";
updatePA(scrollto); updatePA(true);
updateHex(); updateHex();
updateRgb(); updateRgb();
} }
function updateSelectedPalette(scrollto=false) function updateSelectedPalette()
{ {
var parent = gId('pallist'); var parent = gId('pallist');
var selPaletteInput = parent.querySelector(`input[name="palette"][value="${selectedPal}"]`); var selPaletteInput = parent.querySelector(`input[name="palette"][value="${selectedPal}"]`);
@ -1047,7 +1052,7 @@ function updateSelectedPalette(scrollto=false)
if (selectedPalette) parent.querySelector(`.lstI[data-id="${selectedPal}"]`).classList.add('selected'); if (selectedPalette) parent.querySelector(`.lstI[data-id="${selectedPal}"]`).classList.add('selected');
} }
function updateSelectedFx(scrollto=false) function updateSelectedFx()
{ {
var parent = gId('fxlist'); var parent = gId('fxlist');
var selEffectInput = parent.querySelector(`input[name="fx"][value="${selectedFx}"]`); var selEffectInput = parent.querySelector(`input[name="fx"][value="${selectedFx}"]`);
@ -1160,6 +1165,7 @@ function readState(s,command=false)
} }
selectSlot(csel); selectSlot(csel);
gId('sliderW').value = whites[csel]; gId('sliderW').value = whites[csel];
if (i.cct && i.cct>=0) gId("sliderA").value = i.cct;
gId('sliderSpeed').value = i.sx; gId('sliderSpeed').value = i.sx;
gId('sliderIntensity').value = i.ix; gId('sliderIntensity').value = i.ix;
@ -1189,7 +1195,7 @@ function readState(s,command=false)
selectedPal = i.pal; selectedPal = i.pal;
selectedFx = i.fx; selectedFx = i.fx;
redrawPalPrev(); // if any color changed (random palette did at least) redrawPalPrev(); // if any color changed (random palette did at least)
updateUI(true); updateUI();
} }
var jsonTimeout; var jsonTimeout;
@ -1804,7 +1810,7 @@ function selectSlot(b)
cd[csel].classList.add('xxs-w'); cd[csel].classList.add('xxs-w');
cpick.color.set(cd[csel].style.backgroundColor); cpick.color.set(cd[csel].style.backgroundColor);
gId('sliderW').value = whites[csel]; gId('sliderW').value = whites[csel];
updateTrail(gId('sliderW')); //updateTrail(gId('sliderW'),4);
updateHex(); updateHex();
updateRgb(); updateRgb();
} }
@ -1826,13 +1832,10 @@ function pC(col)
function updateRgb() function updateRgb()
{ {
var col = cpick.color.rgb; var s,col = cpick.color.rgb;
var s = gId('sliderR'); s = gId('sliderR').value = col.r; //updateTrail(s,1);
s.value = col.r; updateTrail(s,1); s = gId('sliderG').value = col.g; //updateTrail(s,2);
s = gId('sliderG'); s = gId('sliderB').value = col.b; //updateTrail(s,3);
s.value = col.g; updateTrail(s,2);
s = gId('sliderB');
s.value = col.b; updateTrail(s,3);
} }
function updateHex() function updateHex()
@ -1889,6 +1892,12 @@ function setColor(sr)
requestJson(obj); requestJson(obj);
} }
function setBalance(b)
{
var obj = {"seg": {"cct": parseInt(b)}};
requestJson(obj);
}
var hc = 0; var hc = 0;
setInterval(function(){if (!isInfo) return; hc+=18; if (hc>300) hc=0; if (hc>200)hc=306; if (hc==144) hc+=36; if (hc==108) hc+=18; setInterval(function(){if (!isInfo) return; hc+=18; if (hc>300) hc=0; if (hc>200)hc=306; if (hc==144) hc+=36; if (hc==108) hc+=18;
gId('heart').style.color = `hsl(${hc}, 100%, 50%)`;}, 910); gId('heart').style.color = `hsl(${hc}, 100%, 50%)`;}, 910);

View File

@ -188,13 +188,13 @@
var n = LCs[i].name.substring(2); // bus number var n = LCs[i].name.substring(2); // bus number
// do we have a led count field // do we have a led count field
if (nm=="LC") { if (nm=="LC") {
var c=parseInt(LCs[i].value,10); var c=parseInt(LCs[i].value,10); //get LED gount
if (!customStarts || !startsDirty[n]) gId("ls"+n).value=sLC; if (!customStarts || !startsDirty[n]) gId("ls"+n).value=sLC; //update start value
gId("ls"+n).disabled = !customStarts; gId("ls"+n).disabled = !customStarts; //enable/disable field editing
if(c){ if(c){
var s = parseInt(gId("ls"+n).value); var s = parseInt(gId("ls"+n).value); //start value
if (s+c > sLC) sLC = s+c; if (s+c > sLC) sLC = s+c; //update total count
if(c>maxLC)maxLC=c; if(c>maxLC)maxLC=c; //max per output
var t = parseInt(d.getElementsByName("LT"+n)[0].value); // LED type SELECT var t = parseInt(d.getElementsByName("LT"+n)[0].value); // LED type SELECT
if (t<80) sPC+=c; //virtual out busses do not count towards physical LEDs if (t<80) sPC+=c; //virtual out busses do not count towards physical LEDs
} // increase led count } // increase led count
@ -247,8 +247,8 @@
gId('m0').innerHTML = memu; gId('m0').innerHTML = memu;
bquot = memu / maxM * 100; bquot = memu / maxM * 100;
gId('dbar').style.background = `linear-gradient(90deg, ${bquot > 60 ? (bquot > 90 ? "red":"orange"):"#ccc"} 0 ${bquot}%%, #444 ${bquot}%% 100%%)`; gId('dbar').style.background = `linear-gradient(90deg, ${bquot > 60 ? (bquot > 90 ? "red":"orange"):"#ccc"} 0 ${bquot}%%, #444 ${bquot}%% 100%%)`;
gId('ledwarning').style.display = (sLC > maxPB || maxLC > 800 || bquot > 80) ? 'inline':'none'; gId('ledwarning').style.display = (maxLC > Math.min(maxPB,800) || bquot > 80) ? 'inline':'none';
gId('ledwarning').style.color = (sLC > maxPB || maxLC > maxPB || bquot > 100) ? 'red':'orange'; gId('ledwarning').style.color = (maxLC > Math.max(maxPB,800) || bquot > 100) ? 'red':'orange';
gId('wreason').innerHTML = (bquot > 80) ? "80% of max. LED memory" +(bquot>100 ? ` (<b>ERROR: Using over ${maxM}B!</b>)` : "") : "800 LEDs per output"; gId('wreason').innerHTML = (bquot > 80) ? "80% of max. LED memory" +(bquot>100 ? ` (<b>ERROR: Using over ${maxM}B!</b>)` : "") : "800 LEDs per output";
// calculate power // calculate power
var val = Math.ceil((100 + sPC * laprev)/500)/2; var val = Math.ceil((100 + sPC * laprev)/500)/2;
@ -448,6 +448,7 @@ ${i+1}:
<hr style="width:260px"> <hr style="width:260px">
Make a segment for each output: <input type="checkbox" name="MS"> <br> Make a segment for each output: <input type="checkbox" name="MS"> <br>
Custom bus start indices: <input type="checkbox" onchange="tglSi(this.checked)" id="si"> <br> Custom bus start indices: <input type="checkbox" onchange="tglSi(this.checked)" id="si"> <br>
Allow WB correction: <input type="checkbox" name="CCT"> <br>
<hr style="width:260px"> <hr style="width:260px">
<div id="btns"></div> <div id="btns"></div>
Touch threshold: <input type="number" class="s" min="0" max="100" name="TT" required><br> Touch threshold: <input type="number" class="s" min="0" max="100" name="TT" required><br>

File diff suppressed because one or more lines are too long

View File

@ -42,8 +42,6 @@
<div class ="container"> <div class ="container">
<div class="tabcontent"> <div class="tabcontent">
<div id="picker" class="center"></div>
<div id="qcs-w" class="center"> <div id="qcs-w" class="center">
<div class="qcs" onclick="pC('#ff0000');" title="Red" style="background-color:#ff0000;"></div> <div class="qcs" onclick="pC('#ff0000');" title="Red" style="background-color:#ff0000;"></div>
<div class="qcs" onclick="pC('#ffa000');" title="Orange" style="background-color:#ffa000;"></div> <div class="qcs" onclick="pC('#ffa000');" title="Orange" style="background-color:#ffa000;"></div>
@ -63,14 +61,48 @@
<button class="xxs btn" onclick="selectSlot(2);">3</button> <button class="xxs btn" onclick="selectSlot(2);">3</button>
</div> </div>
<div id="wwrap" class="center"> <div id="picker" class="center"></div>
<p class="label h">White channel</p>
<i class="icons slider-icon" id="wht" title="White channel">&#xe333;</i> <div id="rgbwrap" class="center">
<div id="rwrap" class="il">
<div class="sliderwrap il"> <div class="sliderwrap il">
<input id="sliderW" onchange="setColor(0)" oninput="updateTrail(this)" max="255" min="0" type="range" value="128" /> <input id="sliderR" onchange="fromRgb()" max="255" min="0" type="range" value="128" />
<div class="sliderdisplay"></div> <div class="sliderdisplay"></div>
</div> </div>
<output class="sliderbubble"></output> <!--output class="sliderbubble"></output-->
</div><br>
<div id="gwrap" class="il">
<div class="sliderwrap il">
<input id="sliderG" onchange="fromRgb()" max="255" min="0" type="range" value="128" />
<div class="sliderdisplay"></div>
</div>
<!--output class="sliderbubble"></output-->
</div><br>
<div id="bwrap" class="il">
<div class="sliderwrap il">
<input id="sliderB" onchange="fromRgb()" max="255" min="0" type="range" value="128" />
<div class="sliderdisplay"></div>
</div>
<!--output class="sliderbubble"></output-->
</div><br>
</div>
<div id="wwrap" class="center">
<p class="label hd">White channel</p>
<!--i class="icons slider-icon" id="wht" title="White channel">&#xe333;</i-->
<div class="sliderwrap il">
<input id="sliderW" onchange="setColor(0)" max="255" min="0" type="range" value="128" />
<div class="sliderdisplay"></div>
</div>
<!--output class="sliderbubble"></output-->
</div>
<div id="wbal">
<p class="labels hd">White balance</p>
<div class="sliderwrap il">
<input id="sliderA" onchange="setBalance(this.value)" max="255" min="0" type="range" value="128" />
<div class="sliderdisplay"></div>
</div>
<!--output class="sliderbubble"></output-->
</div> </div>
<div id="Segments" class="center"> <div id="Segments" class="center">

View File

@ -45,7 +45,7 @@ var cpick = new iro.ColorPicker("#picker", {
{ {
component: iro.ui.Slider, component: iro.ui.Slider,
options: { sliderType: 'value' } options: { sliderType: 'value' }
}, }/*,
{ {
component: iro.ui.Slider, component: iro.ui.Slider,
options: { options: {
@ -53,7 +53,7 @@ var cpick = new iro.ColorPicker("#picker", {
minTemperature: 2100, minTemperature: 2100,
maxTemperature: 10000 maxTemperature: 10000
} }
} }*/
] ]
}); });
@ -70,7 +70,7 @@ function applyCfg()
if (bg) sCol('--c-1', bg); if (bg) sCol('--c-1', bg);
var ccfg = cfg.comp.colors; var ccfg = cfg.comp.colors;
//gId('picker').style.display = "none"; // ccfg.picker ? "block":"none"; //gId('picker').style.display = "none"; // ccfg.picker ? "block":"none";
//gId('rgbwrap').style.display = ccfg.rgb ? "block":"none"; gId('rgbwrap').style.display = ccfg.rgb ? "block":"none";
gId('qcs-w').style.display = ccfg.quick ? "block":"none"; gId('qcs-w').style.display = ccfg.quick ? "block":"none";
var l = cfg.comp.labels; //l = false; var l = cfg.comp.labels; //l = false;
var e = d.querySelectorAll('.tab-label'); var e = d.querySelectorAll('.tab-label');
@ -239,7 +239,7 @@ async function onLoad()
}); });
}); });
}); });
updateUI(true); //updateUI(true);
d.addEventListener("visibilitychange", handleVisibilityChange, false); d.addEventListener("visibilitychange", handleVisibilityChange, false);
size(); size();
@ -458,7 +458,7 @@ function populatePresets()
pNum++; pNum++;
} }
gId('pcont').innerHTML = cn; gId('pcont').innerHTML = cn;
updatePA(true); updatePA();
populateQL(); populateQL();
} }
@ -768,22 +768,14 @@ function generateListItemHtml(id, name, clickAction, extraHtml = '')
return `<div class="lstI c" data-id="${id}" onClick="${clickAction}(${id})"><span class="lstIname">${name}</span>${extraHtml}</div>`; return `<div class="lstI c" data-id="${id}" onClick="${clickAction}(${id})"><span class="lstIname">${name}</span>${extraHtml}</div>`;
} }
function updateTrail(e, slidercol) function updateTrail(e)
{ {
if (e==null) return; if (e==null) return;
var max = e.hasAttribute('max') ? e.attributes.max.value : 255; var max = e.hasAttribute('max') ? e.attributes.max.value : 255;
var perc = e.value * 100 / max; var perc = e.value * 100 / max;
perc = parseInt(perc); perc = parseInt(perc);
if (perc < 50) perc += 2; if (perc < 50) perc += 2;
var scol; e.parentNode.getElementsByClassName('sliderdisplay')[0].style.background = `linear-gradient(90deg, var(--c-f) ${perc}%, var(--c-4) ${perc}%)`;
switch (slidercol) {
case 1: scol = "#f00"; break;
case 2: scol = "#0f0"; break;
case 3: scol = "#00f"; break;
default: scol = "var(--c-f)";
}
var val = `linear-gradient(90deg, ${scol} ${perc}%, var(--c-4) ${perc}%)`;
e.parentNode.getElementsByClassName('sliderdisplay')[0].style.background = val;
var bubble = e.parentNode.parentNode.getElementsByTagName('output')[0]; var bubble = e.parentNode.parentNode.getElementsByTagName('output')[0];
if (bubble) bubble.innerHTML = e.value; if (bubble) bubble.innerHTML = e.value;
} }
@ -794,7 +786,7 @@ function toggleBubble(e)
bubble.classList.toggle('sliderbubbleshow'); bubble.classList.toggle('sliderbubbleshow');
} }
function updatePA(scrollto=false) function updatePA()
{ {
var ps = gEBCN("pres"); var ps = gEBCN("pres");
for (let i = 0; i < ps.length; i++) { for (let i = 0; i < ps.length; i++) {
@ -812,7 +804,7 @@ function updatePA(scrollto=false)
} }
} }
function updateUI(scrollto=false) function updateUI()
{ {
gId('buttonPower').className = (isOn) ? "active":""; gId('buttonPower').className = (isOn) ? "active":"";
@ -830,11 +822,12 @@ function updateUI(scrollto=false)
updateTrail(gId('sliderBri')); updateTrail(gId('sliderBri'));
updateTrail(gId('sliderSpeed')); updateTrail(gId('sliderSpeed'));
updateTrail(gId('sliderIntensity')); updateTrail(gId('sliderIntensity'));
updateTrail(gId('sliderW'));
if (isRgbw) gId('wwrap').style.display = "block"; if (isRgbw) gId('wwrap').style.display = "block";
gId("wbal").style.display = (lastinfo.leds.cct) ? "block":"none";
updatePA(scrollto); updatePA(true);
redrawPalPrev(); redrawPalPrev();
updateRgb();
var l = cfg.comp.labels; //l = false; var l = cfg.comp.labels; //l = false;
var e = d.querySelectorAll('.label'); var e = d.querySelectorAll('.label');
@ -942,6 +935,7 @@ function readState(s,command=false)
selectSlot(csel); selectSlot(csel);
} }
gId('sliderW').value = whites[csel]; gId('sliderW').value = whites[csel];
if (i.cct && i.cct>=0) gId("sliderA").value = i.cct;
gId('sliderSpeed').value = i.sx; gId('sliderSpeed').value = i.sx;
gId('sliderIntensity').value = i.ix; gId('sliderIntensity').value = i.ix;
@ -970,7 +964,7 @@ function readState(s,command=false)
selectedPal = i.pal; selectedPal = i.pal;
selectedFx = i.fx; selectedFx = i.fx;
updateUI(true); updateUI();
} }
var jsonTimeout; var jsonTimeout;
@ -1060,10 +1054,10 @@ function tglBri(b=null)
function tglCP() function tglCP()
{ {
// var p = gId(`picker`).style.display === "block";
var p = gId('buttonCP').className === "active"; var p = gId('buttonCP').className === "active";
gId('buttonCP').className = !p ? "active":""; gId('buttonCP').className = !p ? "active":"";
gId('picker').style.display = !p ? "block":"none"; gId('picker').style.display = !p ? "block":"none";
gId('rgbwrap').style.display = !p ? "block":"none";
var csl = gId(`csl`).style.display === "block"; var csl = gId(`csl`).style.display === "block";
gId('csl').style.display = !csl ? "block":"none"; gId('csl').style.display = !csl ? "block":"none";
var ps = gId(`Presets`).style.display === "block"; var ps = gId(`Presets`).style.display === "block";
@ -1176,7 +1170,6 @@ function selectSlot(b)
cd[csel].classList.add('xxs-w'); cd[csel].classList.add('xxs-w');
cpick.color.set(cd[csel].style.backgroundColor); cpick.color.set(cd[csel].style.backgroundColor);
gId('sliderW').value = whites[csel]; gId('sliderW').value = whites[csel];
updateTrail(gId('sliderW'));
redrawPalPrev(); redrawPalPrev();
} }
@ -1195,6 +1188,23 @@ function pC(col)
setColor(0); setColor(0);
} }
function updateRgb()
{
var s,col = cpick.color.rgb;
s = gId('sliderR').value = col.r;
s = gId('sliderG').value = col.g;
s = gId('sliderB').value = col.b;
}
function fromRgb()
{
var r = gId('sliderR').value;
var g = gId('sliderG').value;
var b = gId('sliderB').value;
cpick.color.set(`rgb(${r},${g},${b})`);
setColor(0);
}
function setColor(sr) function setColor(sr)
{ {
var cd = gId('csl').children; var cd = gId('csl').children;
@ -1212,6 +1222,12 @@ function setColor(sr)
requestJson(obj); requestJson(obj);
} }
function setBalance(b)
{
var obj = {"seg": {"cct": parseInt(b)}};
requestJson(obj);
}
var hc = 0; var hc = 0;
setInterval(function(){if (!isInfo) return; hc+=18; if (hc>300) hc=0; if (hc>200)hc=306; if (hc==144) hc+=36; if (hc==108) hc+=18; setInterval(function(){if (!isInfo) return; hc+=18; if (hc>300) hc=0; if (hc>200)hc=306; if (hc==144) hc+=36; if (hc==108) hc+=18;
gId('heart').style.color = `hsl(${hc}, 100%, 50%)`;}, 910); gId('heart').style.color = `hsl(${hc}, 100%, 50%)`;}, 910);

View File

@ -71,6 +71,9 @@ void colorFromDecOrHexString(byte* rgb, char* in);
bool colorFromHexString(byte* rgb, const char* in); bool colorFromHexString(byte* rgb, const char* in);
void colorRGBtoRGBW(byte* rgb); //rgb to rgbw (http://codewelt.com/rgbw). (RGBW_MODE_LEGACY) void colorRGBtoRGBW(byte* rgb); //rgb to rgbw (http://codewelt.com/rgbw). (RGBW_MODE_LEGACY)
void colorBalanceFromKelvin(uint16_t kelvin, byte *rgb);
uint32_t colorBalanceFromKelvin(uint16_t kelvin, uint32_t rgb);
//dmx.cpp //dmx.cpp
void initDMX(); void initDMX();
void handleDMX(); void handleDMX();

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -74,6 +74,8 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
if (elem["on"].is<const char*>() && elem["on"].as<const char*>()[0] == 't') on = !on; if (elem["on"].is<const char*>() && elem["on"].as<const char*>()[0] == 't') on = !on;
seg.setOption(SEG_OPTION_ON, on, id); seg.setOption(SEG_OPTION_ON, on, id);
seg.cct = elem["cct"] | seg.cct;
JsonArray colarr = elem["col"]; JsonArray colarr = elem["col"];
if (!colarr.isNull()) if (!colarr.isNull())
{ {
@ -96,6 +98,7 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
const char* hexCol = colarr[i]; const char* hexCol = colarr[i];
if (hexCol == nullptr) { //Kelvin color temperature (or invalid), e.g 2400 if (hexCol == nullptr) { //Kelvin color temperature (or invalid), e.g 2400
int kelvin = colarr[i] | -1; int kelvin = colarr[i] | -1;
//kelvin = map(seg.cct, 0, 255, 2800, 10200)
if (kelvin < 0) continue; if (kelvin < 0) continue;
if (kelvin == 0) seg.setColor(i, 0, id); if (kelvin == 0) seg.setColor(i, 0, id);
if (kelvin > 0) colorKtoRGB(kelvin, brgbw); if (kelvin > 0) colorKtoRGB(kelvin, brgbw);
@ -370,6 +373,7 @@ void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id, bool fo
root["on"] = seg.getOption(SEG_OPTION_ON); root["on"] = seg.getOption(SEG_OPTION_ON);
byte segbri = seg.opacity; byte segbri = seg.opacity;
root["bri"] = (segbri) ? segbri : 255; root["bri"] = (segbri) ? segbri : 255;
root["cct"] = seg.cct;
if (segmentBounds && seg.name != nullptr) root["n"] = reinterpret_cast<const char *>(seg.name); if (segmentBounds && seg.name != nullptr) root["n"] = reinterpret_cast<const char *>(seg.name);
@ -466,6 +470,17 @@ void serializeInfo(JsonObject root)
leds[F("count")] = ledCount; leds[F("count")] = ledCount;
leds[F("rgbw")] = strip.isRgbw; leds[F("rgbw")] = strip.isRgbw;
leds[F("wv")] = strip.isRgbw && (strip.rgbwMode == RGBW_MODE_MANUAL_ONLY || strip.rgbwMode == RGBW_MODE_DUAL); //should a white channel slider be displayed? leds[F("wv")] = strip.isRgbw && (strip.rgbwMode == RGBW_MODE_MANUAL_ONLY || strip.rgbwMode == RGBW_MODE_DUAL); //should a white channel slider be displayed?
leds["cct"] = allowCCT;
for (uint8_t s = 0; s < busses.getNumBusses(); s++) {
Bus *bus = busses.getBus(s);
if (!bus || bus->getLength()==0) break;
switch (bus->getType() & 0x7F) {
case TYPE_ANALOG_5CH:
case TYPE_ANALOG_2CH:
leds["cct"] = true;
break;
}
}
JsonArray leds_pin = leds.createNestedArray("pin"); JsonArray leds_pin = leds.createNestedArray("pin");
for (uint8_t s=0; s<busses.getNumBusses(); s++) { for (uint8_t s=0; s<busses.getNumBusses(); s++) {

View File

@ -72,6 +72,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
uint8_t pins[5] = {255, 255, 255, 255, 255}; uint8_t pins[5] = {255, 255, 255, 255, 255};
autoSegments = request->hasArg(F("MS")); autoSegments = request->hasArg(F("MS"));
allowCCT = request->hasArg(F("CCT"));
for (uint8_t s = 0; s < WLED_MAX_BUSSES; s++) { for (uint8_t s = 0; s < WLED_MAX_BUSSES; s++) {
char lp[4] = "L0"; lp[2] = 48+s; lp[3] = 0; //ascii 0-9 //strip data pin char lp[4] = "L0"; lp[2] = 48+s; lp[3] = 0; //ascii 0-9 //strip data pin

View File

@ -36,6 +36,9 @@ void WLED::loop()
{ {
#ifdef WLED_DEBUG #ifdef WLED_DEBUG
static unsigned long maxUsermodMillis = 0; static unsigned long maxUsermodMillis = 0;
static uint16_t avgUsermodMillis = 0;
static unsigned long maxStripMillis = 0;
static uint16_t avgStripMillis = 0;
#endif #endif
handleTime(); handleTime();
@ -55,6 +58,7 @@ void WLED::loop()
usermods.loop(); usermods.loop();
#ifdef WLED_DEBUG #ifdef WLED_DEBUG
usermodMillis = millis() - usermodMillis; usermodMillis = millis() - usermodMillis;
avgUsermodMillis += usermodMillis;
if (usermodMillis > maxUsermodMillis) maxUsermodMillis = usermodMillis; if (usermodMillis > maxUsermodMillis) maxUsermodMillis = usermodMillis;
#endif #endif
@ -91,12 +95,20 @@ void WLED::loop()
yield(); yield();
#ifdef WLED_DEBUG
unsigned long stripMillis = millis();
#endif
if (!offMode || strip.isOffRefreshRequred) if (!offMode || strip.isOffRefreshRequred)
strip.service(); strip.service();
#ifdef ESP8266 #ifdef ESP8266
else if (!noWifiSleep) else if (!noWifiSleep)
delay(1); //required to make sure ESP enters modem sleep (see #1184) delay(1); //required to make sure ESP enters modem sleep (see #1184)
#endif #endif
#ifdef WLED_DEBUG
stripMillis = millis() - stripMillis;
avgStripMillis += stripMillis;
if (stripMillis > maxStripMillis) maxStripMillis = stripMillis;
#endif
} }
yield(); yield();
#ifdef ESP8266 #ifdef ESP8266
@ -171,9 +183,13 @@ void WLED::loop()
DEBUG_PRINT(F("NTP last sync: ")); DEBUG_PRINTLN(ntpLastSyncTime); DEBUG_PRINT(F("NTP last sync: ")); DEBUG_PRINTLN(ntpLastSyncTime);
DEBUG_PRINT(F("Client IP: ")); DEBUG_PRINTLN(Network.localIP()); DEBUG_PRINT(F("Client IP: ")); DEBUG_PRINTLN(Network.localIP());
DEBUG_PRINT(F("Loops/sec: ")); DEBUG_PRINTLN(loops / 30); DEBUG_PRINT(F("Loops/sec: ")); DEBUG_PRINTLN(loops / 30);
DEBUG_PRINT(F("Max UM time[ms]: ")); DEBUG_PRINTLN(maxUsermodMillis); DEBUG_PRINT(F("UM time[ms]: ")); DEBUG_PRINT(avgUsermodMillis/loops); DEBUG_PRINT("/");DEBUG_PRINTLN(maxUsermodMillis);
DEBUG_PRINT(F("Strip time[ms]: ")); DEBUG_PRINT(avgStripMillis/loops); DEBUG_PRINT("/"); DEBUG_PRINTLN(maxStripMillis);
loops = 0; loops = 0;
maxUsermodMillis = 0; maxUsermodMillis = 0;
maxStripMillis = 0;
avgUsermodMillis = 0;
avgStripMillis = 0;
debugTime = millis(); debugTime = millis();
} }
loops++; loops++;

View File

@ -8,7 +8,7 @@
*/ */
// version code in format yymmddb (b = daily build) // version code in format yymmddb (b = daily build)
#define VERSION 2110111 #define VERSION 2110151
//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
@ -273,6 +273,7 @@ WLED_GLOBAL byte bootPreset _INIT(0); // save preset to load after p
//if false, only one segment spanning the total LEDs is created, //if false, only one segment spanning the total LEDs is created,
//but not on LED settings save if there is more than one segment currently //but not on LED settings save if there is more than one segment currently
WLED_GLOBAL bool autoSegments _INIT(false); WLED_GLOBAL bool autoSegments _INIT(false);
WLED_GLOBAL bool allowCCT _INIT(false); //CCT color correction
WLED_GLOBAL byte col[] _INIT_N(({ 255, 160, 0, 0 })); // current RGB(W) primary color. col[] should be updated if you want to change the color. WLED_GLOBAL byte col[] _INIT_N(({ 255, 160, 0, 0 })); // current RGB(W) primary color. col[] should be updated if you want to change the color.
WLED_GLOBAL byte colSec[] _INIT_N(({ 0, 0, 0, 0 })); // current RGB(W) secondary color WLED_GLOBAL byte colSec[] _INIT_N(({ 0, 0, 0, 0 })); // current RGB(W) secondary color

View File

@ -322,6 +322,7 @@ void getSettingsJS(byte subPage, char* dest)
oappend(SET_F(");")); oappend(SET_F(");"));
sappend('c',SET_F("MS"),autoSegments); sappend('c',SET_F("MS"),autoSegments);
sappend('c',SET_F("CCT"),allowCCT);
for (uint8_t s=0; s < busses.getNumBusses(); s++) { for (uint8_t s=0; s < busses.getNumBusses(); s++) {
Bus* bus = busses.getBus(s); Bus* bus = busses.getBus(s);