Added segment names.

This commit is contained in:
Blaz Kristan 2021-04-04 21:10:44 +02:00
parent 89543e927a
commit 31ea032054
8 changed files with 1876 additions and 1851 deletions

View File

@ -244,7 +244,7 @@ class WS2812FX {
// segment parameters // segment parameters
public: public:
typedef struct Segment { // 24 bytes typedef struct Segment { // 28 bytes
uint16_t start; uint16_t start;
uint16_t stop; //segment invalid if stop == 0 uint16_t stop; //segment invalid if stop == 0
uint8_t speed; uint8_t speed;
@ -255,6 +255,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];
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;
if (c == colors[slot]) return false; if (c == colors[slot]) return false;
@ -849,9 +850,9 @@ class WS2812FX {
uint8_t _segment_index = 0; uint8_t _segment_index = 0;
uint8_t _segment_index_palette_last = 99; uint8_t _segment_index_palette_last = 99;
segment _segments[MAX_NUM_SEGMENTS] = { // SRAM footprint: 24 bytes per element segment _segments[MAX_NUM_SEGMENTS] = { // SRAM footprint: 28 bytes per element
// start, stop, speed, intensity, palette, mode, options, grouping, spacing, opacity (unused), color[] // start, stop, speed, intensity, palette, mode, options, grouping, spacing, opacity (unused), color[]
{ 0, 7, DEFAULT_SPEED, 128, 0, DEFAULT_MODE, NO_OPTIONS, 1, 0, 255, {DEFAULT_COLOR}} { 0, 7, DEFAULT_SPEED, 128, 0, DEFAULT_MODE, NO_OPTIONS, 1, 0, 255, {DEFAULT_COLOR}, nullptr }
}; };
segment_runtime _segment_runtimes[MAX_NUM_SEGMENTS]; // SRAM footprint: 28 bytes per element segment_runtime _segment_runtimes[MAX_NUM_SEGMENTS]; // SRAM footprint: 28 bytes per element
friend class Segment_runtime; friend class Segment_runtime;

View File

@ -560,6 +560,7 @@ void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping,
} }
void WS2812FX::resetSegments() { void WS2812FX::resetSegments() {
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) if (_segments[i].name) delete _segments[i].name;
mainSegment = 0; mainSegment = 0;
memset(_segments, 0, sizeof(_segments)); memset(_segments, 0, sizeof(_segments));
//memset(_segment_runtimes, 0, sizeof(_segment_runtimes)); //memset(_segment_runtimes, 0, sizeof(_segment_runtimes));
@ -996,9 +997,9 @@ bool WS2812FX::segmentsAreIdentical(Segment* a, Segment* b)
//load custom mapping table from JSON file //load custom mapping table from JSON file
void WS2812FX::deserializeMap(uint8_t n) { void WS2812FX::deserializeMap(uint8_t n) {
String fileName = String("/ledmap"); String fileName = String(F("/ledmap"));
if (n) fileName += String(n); if (n) fileName += String(n);
fileName += String(".json"); fileName += String(F(".json"));
bool isFile = WLED_FS.exists(fileName); bool isFile = WLED_FS.exists(fileName);
if (!isFile) { if (!isFile) {

View File

@ -132,13 +132,14 @@ button {
.segt { .segt {
table-layout: fixed; table-layout: fixed;
width: 76%; width: 100%;
} }
.segtd { .segt TD {
text-align: center; text-align: center;
text-transform: uppercase; text-transform: uppercase;
font-size: 14px; font-size: 14px;
vertical-align: middle;
} }
.keytd { .keytd {
@ -740,13 +741,12 @@ input[type=number]::-webkit-outer-spin-button {
cursor: pointer; cursor: pointer;
background: var(--c-3); background: var(--c-3);
border-radius: 5px; border-radius: 5px;
padding: 42px 8px;
margin: -8px 0 0;
} }
.cnf-s { .cnf-s {
position: absolute; padding: 8px;
top: 66px;
right: 28px;
padding: 43px 6px;
} }
.pwr { .pwr {
@ -759,11 +759,6 @@ input[type=number]::-webkit-outer-spin-button {
color: var(--c-f); color: var(--c-f);
} }
.half {
padding: 7.5px;
top: 64px;
}
.del { .del {
position: absolute; position: absolute;
bottom: 8px; bottom: 8px;

View File

@ -297,9 +297,8 @@ function checkUsed(i)
function pName(i) function pName(i)
{ {
if (!pJson || !pJson[i]) return "";
var n = "Preset " + i; var n = "Preset " + i;
if (pJson[i].n) n = pJson[i].n; if (pJson && pJson[i] && pJson[i].n) n = pJson[i].n;
return n; return n;
} }
@ -593,37 +592,36 @@ function populateSegments(s)
<span class="checkmark schk"></span> <span class="checkmark schk"></span>
</label> </label>
<div class="segname" onclick="selSegEx(${i})"> <div class="segname" onclick="selSegEx(${i})">
Segment ${i} ${inst.n ? inst.n : "Segment "+i}
</div> </div>
<i class="icons e-icon flr ${expanded[i] ? "exp":""}" id="sege${i}" onclick="expand(${i})">&#xe395;</i> <i class="icons e-icon flr ${expanded[i] ? "exp":""}" id="sege${i}" onclick="expand(${i})">&#xe395;</i>
<div class="segin ${expanded[i] ? "expanded":""}" id="seg${i}"> <div class="segin ${expanded[i] ? "expanded":""}" id="seg${i}">
<table class="segt"> <input type="text" class="ptxt noslide" id="seg${i}t" autocomplete="off" maxlength=32 value="${inst.n?inst.n:""}" placeholder="Enter name..."/><br>
<tr> <table class="segt">
<td class="segtd">Start LED</td> <tr>
<td class="segtd">${cfg.comp.seglen?"LED count":"Stop LED"}</td> <td width="38%">Start LED</td>
</tr> <td width="38%">${cfg.comp.seglen?"LED count":"Stop LED"}</td>
<tr> </tr>
<td class="segtd"><input class="noslide segn" id="seg${i}s" type="number" min="0" max="${ledCount-1}" value="${inst.start}" oninput="updateLen(${i})"></td> <tr>
<td class="segtd"><input class="noslide segn" id="seg${i}e" type="number" min="0" max="${ledCount-(cfg.comp.seglen?inst.start:0)}" value="${inst.stop-(cfg.comp.seglen?inst.start:0)}" oninput="updateLen(${i})"></td> <td><input class="noslide segn" id="seg${i}s" type="number" min="0" max="${ledCount-1}" value="${inst.start}" oninput="updateLen(${i})"></td>
</tr> <td><input class="noslide segn" id="seg${i}e" type="number" min="0" max="${ledCount-(cfg.comp.seglen?inst.start:0)}" value="${inst.stop-(cfg.comp.seglen?inst.start:0)}" oninput="updateLen(${i})"></td>
</table> <td rowspan="3"><i class="icons e-icon cnf" id="segc${i}" onclick="setSeg(${i})">&#xe390;</i></td>
<table class="segt"> </tr>
<tr> <tr>
<td class="segtd">Grouping</td> <td>Grouping</td>
<td class="segtd">Spacing</td> <td>Spacing</td>
</tr> </tr>
<tr> <tr>
<td class="segtd"><input class="noslide segn" id="seg${i}grp" type="number" min="1" max="255" value="${inst.grp}" oninput="updateLen(${i})"></td> <td><input class="noslide segn" id="seg${i}grp" type="number" min="1" max="255" value="${inst.grp}" oninput="updateLen(${i})"></td>
<td class="segtd"><input class="noslide segn" id="seg${i}spc" type="number" min="0" max="255" value="${inst.spc}" oninput="updateLen(${i})"></td> <td><input class="noslide segn" id="seg${i}spc" type="number" min="0" max="255" value="${inst.spc}" oninput="updateLen(${i})"></td>
</tr> </tr>
</table> </table>
<div class="h bp" id="seg${i}len"></div> <div class="h bp" id="seg${i}len"></div>
<i class="icons e-icon pwr ${powered[i] ? "act":""}" id="seg${i}pwr" onclick="setSegPwr(${i})">&#xe08f;</i> <i class="icons e-icon pwr ${powered[i] ? "act":""}" id="seg${i}pwr" onclick="setSegPwr(${i})">&#xe08f;</i>
<div class="sliderwrap il sws"> <div class="sliderwrap il sws">
<input id="seg${i}bri" class="noslide sis" onchange="setSegBri(${i})" oninput="updateTrail(this)" max="255" min="1" type="range" value="${inst.bri}" /> <input id="seg${i}bri" class="noslide sis" onchange="setSegBri(${i})" oninput="updateTrail(this)" max="255" min="1" type="range" value="${inst.bri}" />
<div class="sliderdisplay"></div> <div class="sliderdisplay"></div>
</div> </div>
<i class="icons e-icon cnf cnf-s" id="segc${i}" onclick="setSeg(${i})">&#xe390;</i>
<i class="icons e-icon del" id="segd${i}" onclick="delSeg(${i})">&#xe037;</i> <i class="icons e-icon del" id="segd${i}" onclick="delSeg(${i})">&#xe037;</i>
<label class="check revchkl"> <label class="check revchkl">
Reverse direction Reverse direction
@ -1244,18 +1242,19 @@ function makeSeg()
New segment ${lowestUnused} New segment ${lowestUnused}
</div> </div>
<div class="segin expanded"> <div class="segin expanded">
<input type="text" class="ptxt noslide" id="seg${lowestUnused}t" autocomplete="off" maxlength=32 value="" placeholder="Enter name..."/><br>
<table class="segt"> <table class="segt">
<tr> <tr>
<td class="segtd">Start LED</td> <td width="38%">Start LED</td>
<td class="segtd">${cfg.comp.seglen?"LED count":"Stop LED"}</td> <td width="38%">${cfg.comp.seglen?"LED count":"Stop LED"}</td>
</tr> </tr>
<tr> <tr>
<td class="segtd"><input class="noslide segn" id="seg${lowestUnused}s" type="number" min="0" max="${ledCount-1}" value="${ns}" oninput="updateLen(${lowestUnused})"></td> <td><input class="noslide segn" id="seg${lowestUnused}s" type="number" min="0" max="${ledCount-1}" value="${ns}" oninput="updateLen(${lowestUnused})"></td>
<td class="segtd"><input class="noslide segn" id="seg${lowestUnused}e" type="number" min="0" max="${ledCount-(cfg.comp.seglen?ns:0)}" value="${ledCount-(cfg.comp.seglen?ns:0)}" oninput="updateLen(${lowestUnused})"></td> <td><input class="noslide segn" id="seg${lowestUnused}e" type="number" min="0" max="${ledCount-(cfg.comp.seglen?ns:0)}" value="${ledCount-(cfg.comp.seglen?ns:0)}" oninput="updateLen(${lowestUnused})"></td>
<td><i class="icons e-icon cnf cnf-s" id="segc${lowestUnused}" onclick="setSeg(${lowestUnused});resetUtil();">&#xe390;</i></td>
</tr> </tr>
</table> </table>
<div class="h" id="seg${lowestUnused}len">${ledCount - ns} LEDs</div> <div class="h" id="seg${lowestUnused}len">${ledCount - ns} LEDs</div>
<i class="icons e-icon cnf cnf-s half" id="segc${lowestUnused}" onclick="setSeg(${lowestUnused});resetUtil();">&#xe390;</i>
<div class="c"><button class="btn btn-p" onclick="resetUtil()">Cancel</button></div> <div class="c"><button class="btn btn-p" onclick="resetUtil()">Cancel</button></div>
</div> </div>
</div>`; </div>`;
@ -1342,10 +1341,11 @@ function selSeg(s)
function setSeg(s) function setSeg(s)
{ {
var name = gId(`seg${s}t`).value;
var start = parseInt(gId(`seg${s}s`).value); var start = parseInt(gId(`seg${s}s`).value);
var stop = parseInt(gId(`seg${s}e`).value); var stop = parseInt(gId(`seg${s}e`).value);
if (stop == 0) {delSeg(s); return;} if (stop == 0) {delSeg(s); return;}
var obj = {"seg": {"id": s, "start": start, "stop": (cfg.comp.seglen?start:0)+stop}}; var obj = {"seg": {"id": s, "n": name, "start": start, "stop": (cfg.comp.seglen?start:0)+stop}};
if (gId(`seg${s}grp`)) if (gId(`seg${s}grp`))
{ {
var grp = parseInt(gId(`seg${s}grp`).value); var grp = parseInt(gId(`seg${s}grp`).value);

File diff suppressed because it is too large Load Diff

View File

@ -15,6 +15,29 @@ void deserializeSegment(JsonObject elem, byte it)
uint16_t start = elem[F("start")] | seg.start; uint16_t start = elem[F("start")] | seg.start;
int stop = elem["stop"] | -1; int stop = elem["stop"] | -1;
if (elem["n"]) {
// name field exists
String name = elem["n"];
if (name.length()) {
if (seg.name) delete seg.name;
seg.name = new char[name.length()+1];
strcpy(seg.name, name.c_str());
} else {
// but is empty
elem.remove("n");
if (seg.name) {
delete seg.name;
seg.name = nullptr;
}
}
} else if (elem[F("start")] || elem["stop"]) {
// clearing or setting segment without name field
if (seg.name) {
delete seg.name;
seg.name = nullptr;
}
}
if (stop < 0) { if (stop < 0) {
uint16_t len = elem[F("len")]; uint16_t len = elem[F("len")];
stop = (len > 0) ? start + len : seg.stop; stop = (len > 0) ? start + len : seg.stop;
@ -319,6 +342,8 @@ void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id, bool fo
byte segbri = seg.opacity; byte segbri = seg.opacity;
root["bri"] = (segbri) ? segbri : 255; root["bri"] = (segbri) ? segbri : 255;
if (seg.name != nullptr) root["n"] = String(seg.name);
JsonArray colarr = root.createNestedArray("col"); JsonArray colarr = root.createNestedArray("col");
if (versionAPI>1) { if (versionAPI>1) {

View File

@ -55,6 +55,7 @@ void savePreset(byte index, bool persist, const char* pname, JsonObject saveobj)
DEBUGFS_PRINTLN(F("Reuse recv buffer")); DEBUGFS_PRINTLN(F("Reuse recv buffer"));
sObj.remove(F("psave")); sObj.remove(F("psave"));
sObj.remove(F("v")); sObj.remove(F("v"));
sObj.remove("rev"); // TODO: use rev:2 if more than 12 segments on ESP8266
if (!sObj["o"]) { if (!sObj["o"]) {
DEBUGFS_PRINTLN(F("Save current state")); DEBUGFS_PRINTLN(F("Save current state"));

View File

@ -8,7 +8,7 @@
*/ */
// version code in format yymmddb (b = daily build) // version code in format yymmddb (b = daily build)
#define VERSION 2104041 #define VERSION 2104042
//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