Per strip skip first LED implementation (#1871)

* Per strip "skip first LED".
Moved skip first led into bus manager.

* Update cfg.cpp

* Do not display Skip 1st on analog types

Rename skipFirstLed() to clarify what it does
Remove RGBW override

Co-authored-by: Aircoookie <dev.aircoookie@gmail.com>
Co-authored-by: Aircoookie <cschwinne@gmail.com>
This commit is contained in:
Blaž Kristan 2021-05-17 16:23:46 +02:00 committed by GitHub
parent 4bcfff780a
commit 1617658bfe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 764 additions and 744 deletions

View File

@ -581,7 +581,7 @@ class WS2812FX {
}
void
finalizeInit(uint16_t countPixels, bool skipFirst),
finalizeInit(uint16_t countPixels),
service(void),
blur(uint8_t),
fill(uint32_t),
@ -813,7 +813,6 @@ class WS2812FX {
void handle_palette(void);
bool
_skipFirstMode,
_triggered;
mode_ptr _mode[MODE_COUNT]; // SRAM footprint: 4 bytes per element

View File

@ -61,16 +61,11 @@
#endif
//do not call this method from system context (network callback)
void WS2812FX::finalizeInit(uint16_t countPixels, bool skipFirst)
void WS2812FX::finalizeInit(uint16_t countPixels)
{
RESET_RUNTIME;
_length = countPixels;
_skipFirstMode = skipFirst;
_lengthRaw = _length;
if (_skipFirstMode) {
_lengthRaw += LED_SKIP_AMOUNT;
}
//if busses failed to load, add default (FS issue...)
if (busses.getNumBusses() == 0) {
@ -204,7 +199,6 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w)
}
}
uint16_t skip = _skipFirstMode ? LED_SKIP_AMOUNT : 0;
if (SEGLEN) {//from segment
//color_blend(getpixel, col, _bri_t); (pseudocode for future blending of segments)
@ -216,7 +210,6 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w)
}
uint32_t col = ((w << 24) | (r << 16) | (g << 8) | (b));
/* Set all the pixels in the group, ensuring _skipFirstMode is honored */
bool reversed = IS_REVERSE;
uint16_t realIndex = realPixelIndex(i);
@ -226,22 +219,17 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w)
if (IS_MIRROR) { //set the corresponding mirrored pixel
uint16_t indexMir = SEGMENT.stop - indexSet + SEGMENT.start - 1;
if (indexMir < customMappingSize) indexMir = customMappingTable[indexMir];
busses.setPixelColor(indexMir + skip, col);
busses.setPixelColor(indexMir, col);
}
if (indexSet < customMappingSize) indexSet = customMappingTable[indexSet];
busses.setPixelColor(indexSet + skip, col);
busses.setPixelColor(indexSet, col);
}
}
} else { //live data, etc.
if (i < customMappingSize) i = customMappingTable[i];
uint32_t col = ((w << 24) | (r << 16) | (g << 8) | (b));
busses.setPixelColor(i + skip, col);
}
if (skip && i == 0) {
for (uint16_t j = 0; j < skip; j++) {
busses.setPixelColor(j, BLACK);
}
busses.setPixelColor(i, col);
}
}
@ -514,8 +502,6 @@ uint32_t WS2812FX::getPixelColor(uint16_t i)
i = realPixelIndex(i);
if (i < customMappingSize) i = customMappingTable[i];
if (_skipFirstMode) i += LED_SKIP_AMOUNT;
if (i >= _lengthRaw) return 0;

View File

@ -17,9 +17,11 @@ struct BusConfig {
uint16_t start = 0;
uint8_t colorOrder = COL_ORDER_GRB;
bool reversed = false;
uint8_t skipAmount;
uint8_t pins[5] = {LEDPIN, 255, 255, 255, 255};
BusConfig(uint8_t busType, uint8_t* ppins, uint16_t pstart, uint16_t len = 1, uint8_t pcolorOrder = COL_ORDER_GRB, bool rev = false) {
type = busType; count = len; start = pstart; colorOrder = pcolorOrder; reversed = rev;
BusConfig(uint8_t busType, uint8_t* ppins, uint16_t pstart, uint16_t len = 1, uint8_t pcolorOrder = COL_ORDER_GRB, bool rev = false, uint8_t skip=0) {
type = busType; count = len; start = pstart;
colorOrder = pcolorOrder; reversed = rev; skipAmount = skip;
uint8_t nPins = 1;
if (type > 47) nPins = 2;
else if (type > 41 && type < 46) nPins = NUM_PWM_PINS(type);
@ -51,11 +53,11 @@ class Bus {
virtual uint8_t getPins(uint8_t* pinArray) { return 0; }
uint16_t getStart() {
inline uint16_t getStart() {
return _start;
}
void setStart(uint16_t start) {
inline void setStart(uint16_t start) {
_start = start;
}
@ -69,14 +71,28 @@ class Bus {
return COL_ORDER_RGB;
}
uint8_t getType() {
virtual bool isRgbw() {
return false;
}
virtual uint8_t skippedLeds() {
return 0;
}
inline uint8_t getType() {
return _type;
}
bool isOk() {
inline bool isOk() {
return _valid;
}
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;
return false;
}
bool reversed = false;
protected:
@ -99,8 +115,9 @@ class BusDigital : public Bus {
cleanup(); return;
}
}
_len = bc.count;
reversed = bc.reversed;
_skip = bc.skipAmount; //sacrificial pixels
_len = bc.count + _skip;
_iType = PolyBus::getI(bc.type, _pins, nr);
if (_iType == I_NONE) return;
_busPtr = PolyBus::create(_iType, _pins, _len);
@ -109,11 +126,11 @@ class BusDigital : public Bus {
//Serial.printf("Successfully inited strip %u (len %u) with type %u and pins %u,%u (itype %u)\n",nr, len, type, pins[0],pins[1],_iType);
};
void show() {
inline void show() {
PolyBus::show(_busPtr, _iType);
}
bool canShow() {
inline bool canShow() {
return PolyBus::canShow(_busPtr, _iType);
}
@ -130,20 +147,22 @@ class BusDigital : public Bus {
void setPixelColor(uint16_t pix, uint32_t c) {
if (reversed) pix = _len - pix -1;
else pix += _skip;
PolyBus::setPixelColor(_busPtr, _iType, pix, c, _colorOrder);
}
uint32_t getPixelColor(uint16_t pix) {
if (reversed) pix = _len - pix -1;
else pix += _skip;
return PolyBus::getPixelColor(_busPtr, _iType, pix, _colorOrder);
}
uint8_t getColorOrder() {
inline uint8_t getColorOrder() {
return _colorOrder;
}
uint16_t getLength() {
return _len;
inline uint16_t getLength() {
return _len - _skip;
}
uint8_t getPins(uint8_t* pinArray) {
@ -157,7 +176,15 @@ class BusDigital : public Bus {
_colorOrder = colorOrder;
}
void reinit() {
inline bool isRgbw() {
return (_type == TYPE_SK6812_RGBW || _type == TYPE_TM1814);
}
inline uint8_t skippedLeds() {
return _skip;
}
inline void reinit() {
PolyBus::begin(_busPtr, _iType, _pins);
}
@ -180,6 +207,7 @@ class BusDigital : public Bus {
uint8_t _pins[2] = {255, 255};
uint8_t _iType = I_NONE;
uint16_t _len = 0;
uint8_t _skip = 0;
void * _busPtr = nullptr;
};
@ -255,7 +283,7 @@ class BusPwm : public Bus {
}
}
void setBrightness(uint8_t b) {
inline void setBrightness(uint8_t b) {
_bri = b;
}
@ -265,7 +293,11 @@ class BusPwm : public Bus {
return numPins;
}
void cleanup() {
bool isRgbw() {
return (_type > TYPE_ONOFF && _type <= TYPE_ANALOG_5CH && _type != TYPE_ANALOG_3CH);
}
inline void cleanup() {
deallocatePins();
}
@ -304,7 +336,7 @@ class BusManager {
};
//utility to get the approx. memory usage of a given BusConfig
uint32_t memUsage(BusConfig &bc) {
static uint32_t memUsage(BusConfig &bc) {
uint8_t type = bc.type;
uint16_t len = bc.count;
if (type < 32) {
@ -333,8 +365,7 @@ class BusManager {
} else {
busses[numBusses] = new BusPwm(bc);
}
numBusses++;
return numBusses -1;
return numBusses++;
}
//do not call this method from system context (network callback)
@ -358,6 +389,7 @@ class BusManager {
uint16_t bstart = b->getStart();
if (pix < bstart || pix >= bstart + b->getLength()) continue;
busses[i]->setPixelColor(pix - bstart, c);
break;
}
}
@ -389,14 +421,18 @@ class BusManager {
return busses[busNr];
}
uint8_t getNumBusses() {
inline uint8_t getNumBusses() {
return numBusses;
}
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;
return false;
uint16_t getTotalLength() {
uint16_t len = 0;
for (uint8_t i=0; i<numBusses; i++ ) len += busses[i]->getLength();
return len;
}
static inline bool isRgbw(uint8_t type) {
return Bus::isRgbw(type);
}
//Return true if the strip requires a refresh to stay off.

View File

@ -837,7 +837,7 @@ class PolyBus {
}
//gives back the internal type index (I_XX_XXX_X above) for the input
static uint8_t getI(uint8_t busType, uint8_t* pins, uint8_t num = 0) {
static uint8_t getI(uint8_t busType, uint8_t* pins, uint8_t num = 0, bool rgbwOverride = false) {
if (!IS_DIGITAL(busType)) return I_NONE;
if (IS_2PIN(busType)) { //SPI LED chips
bool isHSPI = false;
@ -863,7 +863,7 @@ class PolyBus {
switch (busType) {
case TYPE_WS2812_RGB:
case TYPE_WS2812_WWA:
return I_8266_U0_NEO_3 + offset;
return (rgbwOverride ? I_8266_U0_NEO_4 : I_8266_U0_NEO_3) + offset;
case TYPE_SK6812_RGBW:
return I_8266_U0_NEO_4 + offset;
case TYPE_WS2811_400KHZ:
@ -877,7 +877,7 @@ class PolyBus {
switch (busType) {
case TYPE_WS2812_RGB:
case TYPE_WS2812_WWA:
return I_32_R0_NEO_3 + offset;
return (rgbwOverride ? I_32_R0_NEO_3 : I_32_R0_NEO_4) + offset;
case TYPE_SK6812_RGBW:
return I_32_R0_NEO_4 + offset;
case TYPE_WS2811_400KHZ:

View File

@ -103,7 +103,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
if (length==0) continue;
uint8_t colorOrder = (int)elm[F("order")];
//only use skip from the first strip (this shouldn't have been in ins obj. but remains here for compatibility)
if (s==0) skipFirstLed = elm[F("skip")];
uint8_t skipFirst = elm[F("skip")];
uint16_t start = elm[F("start")] | 0;
if (start >= ledCount) continue;
//limit length of strip if it would exceed total configured LEDs
@ -115,11 +115,11 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
//refresh is required to remain off if at least one of the strips requires the refresh.
strip.isOffRefreshRequred |= BusManager::isOffRefreshRequred(ledType);
s++;
BusConfig bc = BusConfig(ledType, pins, start, length, colorOrder, reversed);
BusConfig bc = BusConfig(ledType, pins, start, length, colorOrder, reversed, skipFirst);
mem += busses.memUsage(bc);
if (mem <= MAX_LED_MEMORY) busses.add(bc);
}
strip.finalizeInit(ledCount, skipFirstLed);
strip.finalizeInit(ledCount);
}
if (hw_led["rev"]) busses.getBus(0)->reversed = true; //set 0.11 global reversed setting for first bus
@ -488,7 +488,7 @@ void serializeConfig() {
for (uint8_t i = 0; i < nPins; i++) ins_pin.add(pins[i]);
ins[F("order")] = bus->getColorOrder();
ins["rev"] = bus->reversed;
ins[F("skip")] = (skipFirstLed && s == 0) ? 1 : 0;
ins[F("skip")] = bus->skippedLeds();
ins["type"] = bus->getType();
}

View File

@ -235,7 +235,9 @@
<br>
<span id="psd${i}">Start:</span> <input type="number" name="LS${i}" min="0" max="8191" value="${lastEnd(i)}" required />&nbsp;
<div id="dig${i}" style="display:inline">
Count: <input type="number" name="LC${i}" min="0" max="${maxPB}" value="1" required oninput="UI()" /><br></div>
Count: <input type="number" name="LC${i}" min="0" max="${maxPB}" value="1" required oninput="UI()" /><br>
Skip 1<sup>st</sup> LED: <input id="sl${i}" type="checkbox" name="SL${i}">&nbsp;
</div>
Reverse: <input type="checkbox" name="CV${i}"><br>
</div>`;
f.insertAdjacentHTML("beforeend", cn);
@ -338,7 +340,6 @@
<option value="2">Linear (never wrap)</option>
<option value="3">None (not recommended)</option>
</select><br>
Skip first LED: <input type="checkbox" name="SL"><br>
<span class="wc">
Auto-calculate white channel from RGB:<br>
<select name="AW">

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -85,7 +85,8 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
//TODO remove all busses, but not in this system call
//busses->removeAll();
uint8_t colorOrder, type;
strip.isRgbw = false;
uint8_t colorOrder, type, skip;
uint16_t length, start;
uint8_t pins[5] = {255, 255, 255, 255, 255};
@ -96,6 +97,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
char lt[4] = "LT"; lt[2] = 48+s; lt[3] = 0; //strip type
char ls[4] = "LS"; ls[2] = 48+s; ls[3] = 0; //strip start LED
char cv[4] = "CV"; cv[2] = 48+s; cv[3] = 0; //strip reverse
char sl[4] = "SL"; sl[2] = 48+s; sl[3] = 0; //skip 1st LED
if (!request->hasArg(lp)) {
DEBUG_PRINTLN("No data."); break;
}
@ -105,8 +107,8 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
pins[i] = (request->arg(lp).length() > 0) ? request->arg(lp).toInt() : 255;
}
type = request->arg(lt).toInt();
//if (isRgbw(type)) strip.isRgbw = true; //30fps
//strip.isRgbw = true;
strip.isRgbw = strip.isRgbw || BusManager::isRgbw(type);
skip = request->hasArg(sl) ? LED_SKIP_AMOUNT : 0;
if (request->hasArg(lc) && request->arg(lc).toInt() > 0) {
length = request->arg(lc).toInt();
@ -118,9 +120,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
start = (request->hasArg(ls)) ? request->arg(ls).toInt() : 0;
if (busConfigs[s] != nullptr) delete busConfigs[s];
busConfigs[s] = new BusConfig(type, pins, start, length, colorOrder, request->hasArg(cv));
//if (BusManager::isRgbw(type)) strip.isRgbw = true; //20fps
//strip.isRgbw = true;
busConfigs[s] = new BusConfig(type, pins, start, length, colorOrder, request->hasArg(cv), skip);
doInitBusses = true;
}
@ -181,7 +181,6 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
t = request->arg(F("PB")).toInt();
if (t >= 0 && t < 4) strip.paletteBlend = t;
skipFirstLed = request->hasArg(F("SL"));
t = request->arg(F("BF")).toInt();
if (t > 0) briMultiplier = t;
}

View File

@ -256,7 +256,7 @@ void WLED::loop()
strip.isRgbw = (strip.isRgbw || BusManager::isRgbw(busConfigs[i]->type));
delete busConfigs[i]; busConfigs[i] = nullptr;
}
strip.finalizeInit(ledCount, skipFirstLed);
strip.finalizeInit(ledCount);
yield();
serializeConfig();
}
@ -405,7 +405,7 @@ void WLED::beginStrip()
if (ledCount > MAX_LEDS || ledCount == 0)
ledCount = 30;
strip.finalizeInit(ledCount, skipFirstLed);
strip.finalizeInit(ledCount);
strip.setBrightness(0);
strip.setShowCallback(handleOverlayDraw);

View File

@ -248,7 +248,6 @@ WLED_GLOBAL byte nightlightMode _INIT(NL_MODE_FADE); // See const.h for ava
WLED_GLOBAL bool fadeTransition _INIT(true); // enable crossfading color transition
WLED_GLOBAL uint16_t transitionDelay _INIT(750); // default crossfade duration in ms
WLED_GLOBAL bool skipFirstLed _INIT(false); // ignore first LED in strip (useful if you need the LED as signal repeater)
WLED_GLOBAL byte briMultiplier _INIT(100); // % of brightness to set (to limit power, if you set it to 50 and set bri to 255, actual brightness will be 127)
// User Interface CONFIG

View File

@ -317,7 +317,7 @@ void loadSettingsFromEEPROM()
notifyMacro = EEPROM.read(2201);
strip.rgbwMode = EEPROM.read(2203);
skipFirstLed = EEPROM.read(2204);
//skipFirstLed = EEPROM.read(2204);
if (EEPROM.read(2210) || EEPROM.read(2211) || EEPROM.read(2212))
{

View File

@ -294,6 +294,7 @@ void getSettingsJS(byte subPage, char* dest)
char lt[4] = "LT"; lt[2] = 48+s; lt[3] = 0; //strip type
char ls[4] = "LS"; ls[2] = 48+s; ls[3] = 0; //strip start LED
char cv[4] = "CV"; cv[2] = 48+s; cv[3] = 0; //strip reverse
char sl[4] = "SL"; sl[2] = 48+s; sl[3] = 0; //skip 1st LED
oappend(SET_F("addLEDs(1);"));
uint8_t pins[5];
uint8_t nPins = bus->getPins(pins);
@ -306,6 +307,7 @@ void getSettingsJS(byte subPage, char* dest)
sappend('v',co,bus->getColorOrder());
sappend('v',ls,bus->getStart());
sappend('c',cv,bus->reversed);
sappend('c',sl,bus->skippedLeds());
}
sappend('v',SET_F("MA"),strip.ablMilliampsMax);
sappend('v',SET_F("LA"),strip.milliampsPerLed);
@ -334,7 +336,6 @@ void getSettingsJS(byte subPage, char* dest)
sappend('v',SET_F("TL"),nightlightDelayMinsDefault);
sappend('v',SET_F("TW"),nightlightMode);
sappend('i',SET_F("PB"),strip.paletteBlend);
sappend('c',SET_F("SL"),skipFirstLed);
sappend('v',SET_F("RL"),rlyPin);
sappend('c',SET_F("RM"),rlyMde);
sappend('v',SET_F("BT"),btnPin);