cctFromRgb option

This commit is contained in:
cschwinne 2021-11-26 20:18:38 +01:00
parent 3dec4a6651
commit ba8a00764a
13 changed files with 2230 additions and 2210 deletions

View File

@ -259,7 +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];
int16_t cct; //-1==auto (no RGB balance correction), 0==1900K, 255==10091K uint16_t cct; //0==1900K, 255==10091K, or Kelvin value >=1900
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

@ -138,7 +138,7 @@ void WS2812FX::service() {
if (!SEGMENT.getOption(SEG_OPTION_FREEZE)) { //only run effect function if not frozen if (!SEGMENT.getOption(SEG_OPTION_FREEZE)) { //only run effect function if not frozen
_virtualSegmentLength = SEGMENT.virtualLength(); _virtualSegmentLength = SEGMENT.virtualLength();
busses.setSegmentCCT(SEGMENT.cct, correctWB); if (!cctFromRgb || correctWB) busses.setSegmentCCT(SEGMENT.cct, correctWB);
_bri_t = SEGMENT.opacity; _colors_t[0] = SEGMENT.colors[0]; _colors_t[1] = SEGMENT.colors[1]; _colors_t[2] = SEGMENT.colors[2]; _bri_t = SEGMENT.opacity; _colors_t[0] = SEGMENT.colors[0]; _colors_t[1] = SEGMENT.colors[1]; _colors_t[2] = SEGMENT.colors[2];
if (!IS_SEGMENT_ON) _bri_t = 0; if (!IS_SEGMENT_ON) _bri_t = 0;
for (uint8_t t = 0; t < MAX_NUM_TRANSITIONS; t++) { for (uint8_t t = 0; t < MAX_NUM_TRANSITIONS; t++) {
@ -605,7 +605,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 = -1; _segments[0].cct = 127;
for (uint16_t i = 1; i < MAX_NUM_SEGMENTS; i++) for (uint16_t i = 1; i < MAX_NUM_SEGMENTS; i++)
{ {
@ -613,7 +613,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 = -1; _segments[i].cct = 127;
_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

@ -81,6 +81,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
CJSON(strip.milliampsPerLed, hw_led[F("ledma")]); CJSON(strip.milliampsPerLed, hw_led[F("ledma")]);
uint8_t rgbwMode = hw_led[F("rgbwm")] | RGBW_MODE_DUAL; // use global setting (legacy) uint8_t rgbwMode = hw_led[F("rgbwm")] | RGBW_MODE_DUAL; // use global setting (legacy)
CJSON(correctWB, hw_led["cct"]); CJSON(correctWB, hw_led["cct"]);
CJSON(cctFromRgb, hw_led[F("cr")]);
JsonArray ins = hw_led["ins"]; JsonArray ins = hw_led["ins"];
@ -521,6 +522,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["cct"] = correctWB; hw_led["cct"] = correctWB;
hw_led[F("cr")] = cctFromRgb;
JsonArray hw_led_ins = hw_led.createNestedArray("ins"); JsonArray hw_led_ins = hw_led.createNestedArray("ins");

View File

@ -471,7 +471,9 @@ img {
#rwrap .sliderdisplay { --bg: #f00; } #rwrap .sliderdisplay { --bg: #f00; }
#gwrap .sliderdisplay { --bg: #0f0; } #gwrap .sliderdisplay { --bg: #0f0; }
#bwrap .sliderdisplay { --bg: #00f; } #bwrap .sliderdisplay { --bg: #00f; }
#wbal .sliderdisplay { background: linear-gradient(90deg, #ff8f1f 0%, #fff 50%, #cbdbff); } #wbal .sliderdisplay, #kwrap .sliderdisplay {
background: linear-gradient(90deg, #ff8f1f 0%, #fff 50%, #cbdbff);
}
.sliderbubble { .sliderbubble {
width: 36px; width: 36px;
@ -534,7 +536,7 @@ input[type=range]:active + .sliderbubble {
display: inline; display: inline;
transform: translateX(-50%); transform: translateX(-50%);
} }
#wwrap { #wwrap, #wbal {
display: none; display: none;
} }

View File

@ -47,13 +47,13 @@
<div id="picker" class="noslide"></div> <div id="picker" class="noslide"></div>
<div id="vwrap"> <div id="vwrap">
<div class="sliderwrap il" id="vwrap"> <div class="sliderwrap il" id="vwrap">
<input id="sliderV" class="noslide" onchange="setColor(0)" oninput="fromV()" max="100" min="0" type="range" value="128" step="any" /> <input id="sliderV" class="noslide" oninput="fromV()" onchange="setColor(0)" max="100" min="0" type="range" value="128" step="any" />
<div class="sliderdisplay"></div> <div class="sliderdisplay"></div>
</div><br> </div><br>
</div> </div>
<div id="wbal"> <div id="kwrap">
<div class="sliderwrap il"> <div class="sliderwrap il">
<input id="sliderA" class="noslide" oninput="fromA()" onchange="setBalance(this.value)" max="10091" min="1900" type="range" value="6550" /> <input id="sliderK" class="noslide" oninput="fromK()" onchange="setColor(0)" max="10091" min="1900" type="range" value="6550" />
<div class="sliderdisplay"></div> <div class="sliderdisplay"></div>
</div> </div>
</div> </div>
@ -79,6 +79,13 @@
<div class="sliderdisplay"></div> <div class="sliderdisplay"></div>
</div> </div>
</div> </div>
<div id="wbal">
<p class="labels">White balance</p>
<div class="sliderwrap il">
<input id="sliderA" class="noslide" onchange="setBalance(this.value)" max="255" min="0" type="range" value="128" />
<div class="sliderdisplay"></div>
</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>
<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>

View File

@ -4,7 +4,6 @@ var noNewSegs = false;
var isOn = false, nlA = false, isLv = false, isInfo = false, isNodes = false, syncSend = false, syncTglRecv = true, isRgbw = false; var isOn = false, nlA = false, isLv = false, isInfo = false, isNodes = false, syncSend = false, syncTglRecv = true, isRgbw = false;
var whites = [0,0,0]; var whites = [0,0,0];
var selColors; var selColors;
var mcct = false; //manual CCT (if false, CCT from RGB)
var expanded = [false]; var expanded = [false];
var powered = [true]; var powered = [true];
var nlDur = 60, nlTar = 0; var nlDur = 60, nlTar = 0;
@ -70,6 +69,7 @@ function applyCfg()
d.getElementById('hexw').style.display = ccfg.hex ? "block":"none"; d.getElementById('hexw').style.display = ccfg.hex ? "block":"none";
d.getElementById('picker').style.display = ccfg.picker ? "block":"none"; d.getElementById('picker').style.display = ccfg.picker ? "block":"none";
d.getElementById('vwrap').style.display = ccfg.picker ? "block":"none"; d.getElementById('vwrap').style.display = ccfg.picker ? "block":"none";
d.getElementById('kwrap').style.display = ccfg.picker ? "block":"none";
d.getElementById('rgbwrap').style.display = ccfg.rgb ? "block":"none"; d.getElementById('rgbwrap').style.display = ccfg.rgb ? "block":"none";
d.getElementById('qcs-w').style.display = ccfg.quick ? "block":"none"; d.getElementById('qcs-w').style.display = ccfg.quick ? "block":"none";
var l = cfg.comp.labels; var l = cfg.comp.labels;
@ -922,8 +922,9 @@ function updateUI()
updateTrail(d.getElementById('sliderBri')); updateTrail(d.getElementById('sliderBri'));
updateTrail(d.getElementById('sliderSpeed')); updateTrail(d.getElementById('sliderSpeed'));
updateTrail(d.getElementById('sliderIntensity')); updateTrail(d.getElementById('sliderIntensity'));
//updateTrail(d.getElementById('sliderW'));
d.getElementById('wwrap').style.display = (isRgbw) ? "block":"none"; d.getElementById('wwrap').style.display = (isRgbw) ? "block":"none";
d.getElementById('wbal').style.display = (lastinfo.leds.cct) ? "block":"none";
d.getElementById('kwrap').style.display = (lastinfo.leds.cct) ? "none":"block";
updatePA(); updatePA();
//updateHex(); //updateHex();
@ -1006,7 +1007,7 @@ function readState(s,command=false) {
selectSlot(csel); selectSlot(csel);
} }
//d.getElementById('sliderW').value = whites[csel]; //d.getElementById('sliderW').value = whites[csel];
if (mcct & i.cct && i.cct>=0) d.getElementById("sliderA").value = i.cct; if (i.cct != null && i.cct>=0) d.getElementById("sliderA").value = i.cct;
d.getElementById('sliderSpeed').value = i.sx; d.getElementById('sliderSpeed').value = i.sx;
d.getElementById('sliderIntensity').value = i.ix; d.getElementById('sliderIntensity').value = i.ix;
@ -1154,9 +1155,6 @@ function requestJson(command, rinfo = true) {
} }
d.title = name; d.title = name;
isRgbw = info.leds.wv; isRgbw = info.leds.wv;
mcct = info.leds.cct;
let wsld = d.getElementById("wbal");
if (mcct) wsld.parentNode.insertBefore(wsld,d.getElementById('qcs-w'));
ledCount = info.leds.count; ledCount = info.leds.count;
syncTglRecv = info.str; syncTglRecv = info.str;
maxSeg = info.leds.maxseg; maxSeg = info.leds.maxseg;
@ -1742,7 +1740,7 @@ function updatePSliders() {
var cs = 'rgb('+c.r+','+c.g+','+c.b+')'; var cs = 'rgb('+c.r+','+c.g+','+c.b+')';
v.parentNode.getElementsByClassName('sliderdisplay')[0].style.setProperty('--bg',cs); v.parentNode.getElementsByClassName('sliderdisplay')[0].style.setProperty('--bg',cs);
updateTrail(v); updateTrail(v);
if (!mcct) d.getElementById('sliderA').value = cpick.color.kelvin; d.getElementById('sliderK').value = cpick.color.kelvin;
} }
function updateRgb() function updateRgb()
@ -1789,9 +1787,9 @@ function fromV()
cpick.color.setChannel('hsv', 'v', d.getElementById('sliderV').value); cpick.color.setChannel('hsv', 'v', d.getElementById('sliderV').value);
} }
function fromA() function fromK()
{ {
if (!mcct) cpick.color.set({ kelvin: d.getElementById('sliderA').value }); cpick.color.set({ kelvin: d.getElementById('sliderK').value });
} }
function fromRgb() function fromRgb()
@ -1822,7 +1820,6 @@ function setColor(sr) {
function setBalance(b) function setBalance(b)
{ {
if (!mcct) {setColor(0); return;}
var obj = {"seg": {"cct": parseInt(b)}}; var obj = {"seg": {"cct": parseInt(b)}};
requestJson(obj); requestJson(obj);
} }

View File

@ -511,7 +511,7 @@ ${i+1}:
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>
White Balance correction: <input type="checkbox" name="CCT"> <br> White Balance correction: <input type="checkbox" name="CCT"> <br>
Calculate CCT from RGB: TODO<br> Calculate CCT from RGB: <input type="checkbox" name="CR"> <br>
CCT blending mode: TODO<br> CCT blending mode: TODO<br>
<hr style="width:260px"> <hr style="width:260px">
<div id="btns"></div> <div id="btns"></div>

View File

@ -118,22 +118,22 @@ id="wreason">800 LEDs per output</span> for the best experience!<br></div><hr
style="width:260px">Make a segment for each output: <input type="checkbox" style="width:260px">Make a segment for each output: <input type="checkbox"
name="MS"><br>Custom bus start indices: <input type="checkbox" name="MS"><br>Custom bus start indices: <input type="checkbox"
onchange="tglSi(this.checked)" id="si"><br>White Balance correction: <input onchange="tglSi(this.checked)" id="si"><br>White Balance correction: <input
type="checkbox" name="CCT"><br>Calculate CCT from RGB: TODO<br> type="checkbox" name="CCT"><br>Calculate CCT from RGB: <input type="checkbox"
CCT blending mode: TODO<br><hr style="width:260px"><div id="btns"></div> name="CR"><br>CCT blending mode: TODO<br><hr style="width:260px"><div id="btns">
Touch threshold: <input type="number" class="s" min="0" max="100" name="TT" </div>Touch threshold: <input type="number" class="s" min="0" max="100"
required><br>IR GPIO: <input type="number" min="-1" max="40" name="IR" name="TT" required><br>IR GPIO: <input type="number" min="-1" max="40"
onchange="UI()" class="xs"><select name="IT" onchange="UI()"><option value="0"> name="IR" onchange="UI()" class="xs"><select name="IT" onchange="UI()"><option
Remote disabled</option><option value="1">24-key RGB</option><option value="2"> value="0">Remote disabled</option><option value="1">24-key RGB</option><option
24-key with CT</option><option value="3">40-key blue</option><option value="4"> value="2">24-key with CT</option><option value="3">40-key blue</option><option
44-key RGB</option><option value="5">21-key RGB</option><option value="6"> value="4">44-key RGB</option><option value="5">21-key RGB</option><option
6-key black</option><option value="7">9-key red</option><option value="8"> value="6">6-key black</option><option value="7">9-key red</option><option
JSON remote</option></select><span style="cursor:pointer" onclick='off("IR")'> value="8">JSON remote</option></select><span style="cursor:pointer"
&nbsp;&#215;</span><br><div id="json" style="display:none">JSON file: <input onclick='off("IR")'>&nbsp;&#215;</span><br><div id="json" style="display:none">
type="file" name="data" accept=".json"> <input type="button" value="Upload" JSON file: <input type="file" name="data" accept=".json"> <input type="button"
onclick='uploadFile("/ir.json")'><br></div><div id="toast"></div><a value="Upload" onclick='uploadFile("/ir.json")'><br></div><div id="toast"></div>
href="https://kno.wled.ge/interfaces/infrared/" target="_blank">IR info</a><br> <a href="https://kno.wled.ge/interfaces/infrared/" target="_blank">IR info</a>
Relay GPIO: <input type="number" min="-1" max="33" name="RL" onchange="UI()" <br>Relay GPIO: <input type="number" min="-1" max="33" name="RL"
class="xs"> Invert <input type="checkbox" name="RM"><span onchange="UI()" class="xs"> Invert <input type="checkbox" name="RM"><span
style="cursor:pointer" onclick='off("RL")'>&nbsp;&#215;</span><br><hr style="cursor:pointer" onclick='off("RL")'>&nbsp;&#215;</span><br><hr
style="width:260px"><h3>Defaults</h3>Turn LEDs on after power up/reset: <input style="width:260px"><h3>Defaults</h3>Turn LEDs on after power up/reset: <input
type="checkbox" name="BO"><br>Default brightness: <input name="CA" type="checkbox" name="BO"><br>Default brightness: <input name="CA"

File diff suppressed because it is too large Load Diff

View File

@ -388,7 +388,10 @@ 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; uint16_t cct = seg.cct;
if (cct >= 1900) cct = (cct - 1900) >> 5; //convert K to 0-255
if (cct > 255) cct = 255;
root["cct"] = cct;
if (segmentBounds && seg.name != nullptr) root["n"] = reinterpret_cast<const char *>(seg.name); //not good practice, but decreases required JSON buffer if (segmentBounds && seg.name != nullptr) root["n"] = reinterpret_cast<const char *>(seg.name); //not good practice, but decreases required JSON buffer
@ -512,7 +515,7 @@ void serializeInfo(JsonObject root)
switch (bus->getType()) { switch (bus->getType()) {
case TYPE_ANALOG_5CH: case TYPE_ANALOG_5CH:
case TYPE_ANALOG_2CH: case TYPE_ANALOG_2CH:
leds["cct"] = true; if (!cctFromRgb) leds["cct"] = true;
break; break;
} }
switch (bus->getAutoWhiteMode()) { switch (bus->getAutoWhiteMode()) {

View File

@ -96,6 +96,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
autoSegments = request->hasArg(F("MS")); autoSegments = request->hasArg(F("MS"));
correctWB = request->hasArg(F("CCT")); correctWB = request->hasArg(F("CCT"));
cctFromRgb = request->hasArg(F("CR"));
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

@ -269,7 +269,8 @@ WLED_GLOBAL byte bootPreset _INIT(0); // save preset to load
//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 correctWB _INIT(false); //CCT color correction WLED_GLOBAL bool correctWB _INIT(false); //CCT color correction of RGB color
WLED_GLOBAL bool cctFromRgb _INIT(true); //CCT is calculated from RGB instead of using seg.cct
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

@ -371,6 +371,7 @@ void getSettingsJS(byte subPage, char* dest)
sappend('c',SET_F("MS"),autoSegments); sappend('c',SET_F("MS"),autoSegments);
sappend('c',SET_F("CCT"),correctWB); sappend('c',SET_F("CCT"),correctWB);
sappend('c',SET_F("CR"),cctFromRgb);
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);