Double buffering at bus level.
This commit is contained in:
parent
fa9b151c36
commit
272f96b405
19
wled00/FX.h
19
wled00/FX.h
@ -379,7 +379,6 @@ typedef struct Segment {
|
||||
uint16_t aux0; // custom var
|
||||
uint16_t aux1; // custom var
|
||||
byte* data; // effect data pointer
|
||||
CRGB* leds; // local leds[] array (may be a pointer to global)
|
||||
static uint16_t maxWidth, maxHeight; // these define matrix width & height (max. segment dimensions)
|
||||
|
||||
private:
|
||||
@ -462,7 +461,6 @@ typedef struct Segment {
|
||||
aux0(0),
|
||||
aux1(0),
|
||||
data(nullptr),
|
||||
leds(nullptr),
|
||||
_capabilities(0),
|
||||
_dataLen(0),
|
||||
_t(nullptr)
|
||||
@ -483,10 +481,8 @@ typedef struct Segment {
|
||||
//Serial.print(F("Destroying segment:"));
|
||||
//if (name) Serial.printf(" %s (%p)", name, name);
|
||||
//if (data) Serial.printf(" %d (%p)", (int)_dataLen, data);
|
||||
//if (leds) Serial.printf(" [%u]", length()*sizeof(CRGB));
|
||||
//Serial.println();
|
||||
//#endif
|
||||
if (leds) free(leds);
|
||||
if (name) delete[] name;
|
||||
if (_t) delete _t;
|
||||
deallocateData();
|
||||
@ -496,7 +492,7 @@ typedef struct Segment {
|
||||
Segment& operator= (Segment &&orig) noexcept; // move assignment
|
||||
|
||||
#ifdef WLED_DEBUG
|
||||
size_t getSize() const { return sizeof(Segment) + (data?_dataLen:0) + (name?strlen(name):0) + (_t?sizeof(Transition):0) + (leds?sizeof(CRGB)*length():0); }
|
||||
size_t getSize() const { return sizeof(Segment) + (data?_dataLen:0) + (name?strlen(name):0) + (_t?sizeof(Transition):0); }
|
||||
#endif
|
||||
|
||||
inline bool getOption(uint8_t n) const { return ((options >> n) & 0x01); }
|
||||
@ -537,7 +533,7 @@ typedef struct Segment {
|
||||
* Safe to call from interrupts and network requests.
|
||||
*/
|
||||
inline void markForReset(void) { reset = true; } // setOption(SEG_OPTION_RESET, true)
|
||||
void setUpLeds(void); // set up leds[] array for loseless getPixelColor()
|
||||
inline void setUpLeds(void) {} // legacy filler (should be removed)
|
||||
|
||||
// transition functions
|
||||
void startTransition(uint16_t dur); // transition has to start before actual segment values change
|
||||
@ -578,7 +574,7 @@ typedef struct Segment {
|
||||
uint16_t virtualHeight(void) const;
|
||||
uint16_t nrOfVStrips(void) const;
|
||||
#ifndef WLED_DISABLE_2D
|
||||
uint16_t XY(uint16_t x, uint16_t y); // support function to get relative index within segment (for leds[])
|
||||
uint16_t XY(uint16_t x, uint16_t y); // support function to get relative index within segment
|
||||
void setPixelColorXY(int x, int y, uint32_t c); // set relative pixel within segment with color
|
||||
void setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0) { setPixelColorXY(x, y, RGBW32(r,g,b,w)); } // automatically inline
|
||||
void setPixelColorXY(int x, int y, CRGB c) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0)); } // automatically inline
|
||||
@ -677,7 +673,6 @@ class WS2812FX { // 96 bytes
|
||||
// true private variables
|
||||
_length(DEFAULT_LED_COUNT),
|
||||
_brightness(DEFAULT_BRIGHTNESS),
|
||||
_renderBrightness(0),
|
||||
_transitionDur(750),
|
||||
_targetFps(WLED_FPS),
|
||||
_frametime(FRAMETIME_FIXED),
|
||||
@ -710,7 +705,6 @@ class WS2812FX { // 96 bytes
|
||||
panel.clear();
|
||||
#endif
|
||||
customPalettes.clear();
|
||||
if (_globalLedBuffer) free(_globalLedBuffer);
|
||||
}
|
||||
|
||||
static WS2812FX* getInstance(void) { return instance; }
|
||||
@ -757,8 +751,7 @@ class WS2812FX { // 96 bytes
|
||||
hasCCTBus(void),
|
||||
// return true if the strip is being sent pixel updates
|
||||
isUpdating(void),
|
||||
deserializeMap(uint8_t n=0),
|
||||
useGlobalLedBuffer = false;
|
||||
deserializeMap(uint8_t n=0);
|
||||
|
||||
inline bool isServicing(void) { return _isServicing; }
|
||||
inline bool hasWhiteChannel(void) {return _hasWhiteChannel;}
|
||||
@ -876,7 +869,7 @@ class WS2812FX { // 96 bytes
|
||||
|
||||
private:
|
||||
uint16_t _length;
|
||||
uint8_t _brightness, _renderBrightness;
|
||||
uint8_t _brightness;
|
||||
uint16_t _transitionDur;
|
||||
|
||||
uint8_t _targetFps;
|
||||
@ -905,8 +898,6 @@ class WS2812FX { // 96 bytes
|
||||
uint8_t _segment_index;
|
||||
uint8_t _mainSegment;
|
||||
|
||||
static uint32_t *_globalLedBuffer; // global leds[] array
|
||||
|
||||
uint8_t
|
||||
estimateCurrentAndLimitBri(void);
|
||||
};
|
||||
|
@ -199,8 +199,6 @@ void /*IRAM_ATTR*/ Segment::setPixelColorXY(int x, int y, uint32_t col)
|
||||
if (Segment::maxHeight==1) return; // not a matrix set-up
|
||||
if (x >= virtualWidth() || y >= virtualHeight() || x<0 || y<0) return; // if pixel would fall out of virtual segment just exit
|
||||
|
||||
if (leds) leds[XY(x,y)] = col;
|
||||
|
||||
uint8_t _bri_t = currentBri(on ? opacity : 0);
|
||||
if (_bri_t < 255) {
|
||||
byte r = scale8(R(col), _bri_t);
|
||||
@ -286,8 +284,6 @@ void Segment::setPixelColorXY(float x, float y, uint32_t col, bool aa)
|
||||
|
||||
// returns RGBW values of pixel
|
||||
uint32_t Segment::getPixelColorXY(uint16_t x, uint16_t y) {
|
||||
int i = XY(x,y);
|
||||
if (leds) return RGBW32(leds[i].r, leds[i].g, leds[i].b, 0);
|
||||
if (reverse ) x = virtualWidth() - x - 1;
|
||||
if (reverse_y) y = virtualHeight() - y - 1;
|
||||
if (transpose) { uint16_t t = x; x = y; y = t; } // swap X & Y if segment transposed
|
||||
|
@ -85,11 +85,9 @@ Segment::Segment(const Segment &orig) {
|
||||
data = nullptr;
|
||||
_dataLen = 0;
|
||||
_t = nullptr;
|
||||
leds = nullptr;
|
||||
if (orig.name) { name = new char[strlen(orig.name)+1]; if (name) strcpy(name, orig.name); }
|
||||
if (orig.data) { if (allocateData(orig._dataLen)) memcpy(data, orig.data, orig._dataLen); }
|
||||
if (orig._t) { _t = new Transition(orig._t->_dur, orig._t->_briT, orig._t->_cctT, orig._t->_colorT); }
|
||||
if (orig.leds) { leds = (CRGB*)malloc(sizeof(CRGB)*length()); if (leds) memcpy(leds, orig.leds, sizeof(CRGB)*length()); }
|
||||
}
|
||||
|
||||
// move constructor
|
||||
@ -100,7 +98,6 @@ Segment::Segment(Segment &&orig) noexcept {
|
||||
orig.data = nullptr;
|
||||
orig._dataLen = 0;
|
||||
orig._t = nullptr;
|
||||
orig.leds = nullptr;
|
||||
}
|
||||
|
||||
// copy assignment
|
||||
@ -110,7 +107,6 @@ Segment& Segment::operator= (const Segment &orig) {
|
||||
// clean destination
|
||||
if (name) delete[] name;
|
||||
if (_t) delete _t;
|
||||
if (leds) free(leds);
|
||||
deallocateData();
|
||||
// copy source
|
||||
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
||||
@ -119,12 +115,10 @@ Segment& Segment::operator= (const Segment &orig) {
|
||||
data = nullptr;
|
||||
_dataLen = 0;
|
||||
_t = nullptr;
|
||||
leds = nullptr;
|
||||
// copy source data
|
||||
if (orig.name) { name = new char[strlen(orig.name)+1]; if (name) strcpy(name, orig.name); }
|
||||
if (orig.data) { if (allocateData(orig._dataLen)) memcpy(data, orig.data, orig._dataLen); }
|
||||
if (orig._t) { _t = new Transition(orig._t->_dur, orig._t->_briT, orig._t->_cctT, orig._t->_colorT); }
|
||||
if (orig.leds) { leds = (CRGB*)malloc(sizeof(CRGB)*length()); if (leds) memcpy(leds, orig.leds, sizeof(CRGB)*length()); }
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@ -136,13 +130,11 @@ Segment& Segment::operator= (Segment &&orig) noexcept {
|
||||
if (name) delete[] name; // free old name
|
||||
deallocateData(); // free old runtime data
|
||||
if (_t) delete _t;
|
||||
if (leds) free(leds);
|
||||
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
||||
orig.name = nullptr;
|
||||
orig.data = nullptr;
|
||||
orig._dataLen = 0;
|
||||
orig._t = nullptr;
|
||||
orig.leds = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@ -182,29 +174,12 @@ void Segment::deallocateData() {
|
||||
*/
|
||||
void Segment::resetIfRequired() {
|
||||
if (reset) {
|
||||
if (leds) { free(leds); leds = nullptr; }
|
||||
//if (transitional && _t) { transitional = false; delete _t; _t = nullptr; }
|
||||
deallocateData();
|
||||
next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0;
|
||||
reset = false; // setOption(SEG_OPTION_RESET, false);
|
||||
}
|
||||
}
|
||||
|
||||
void Segment::setUpLeds() {
|
||||
// deallocation happens in resetIfRequired() as it is called when segment changes or in destructor
|
||||
if (WS2812FX::_globalLedBuffer) return; // TODO optional seg buffer for FX without lossy restore due to opacity
|
||||
|
||||
// no global buffer
|
||||
if (leds == nullptr && length() > 0) { //softhack007 quickfix - avoid malloc(0) which is undefined behaviour (should not happen, but i've seen it)
|
||||
//#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)
|
||||
//if (psramFound())
|
||||
// leds = (CRGB*)ps_malloc(sizeof(CRGB)*length()); // softhack007 disabled; putting leds into psram leads to horrible slowdown on WROVER boards
|
||||
//else
|
||||
//#endif
|
||||
leds = (CRGB*)malloc(sizeof(CRGB)*length());
|
||||
}
|
||||
}
|
||||
|
||||
CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
|
||||
static unsigned long _lastPaletteChange = 0; // perhaps it should be per segment
|
||||
static CRGBPalette16 randomPalette = CRGBPalette16(DEFAULT_COLOR);
|
||||
@ -617,8 +592,6 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (leds) leds[i] = col;
|
||||
|
||||
uint16_t len = length();
|
||||
uint8_t _bri_t = currentBri(on ? opacity : 0);
|
||||
if (_bri_t < 255) {
|
||||
@ -718,8 +691,6 @@ uint32_t Segment::getPixelColor(int i)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (leds) return RGBW32(leds[i].r, leds[i].g, leds[i].b, 0);
|
||||
|
||||
if (reverse) i = virtualLength() - i - 1;
|
||||
i *= groupLength();
|
||||
i += start;
|
||||
@ -1058,24 +1029,6 @@ void WS2812FX::finalizeInit(void)
|
||||
Segment::maxHeight = 1;
|
||||
}
|
||||
|
||||
// initialize leds array
|
||||
if (_globalLedBuffer) {
|
||||
//purgeSegments(true);
|
||||
free(_globalLedBuffer);
|
||||
_globalLedBuffer = nullptr;
|
||||
}
|
||||
if (useGlobalLedBuffer) {
|
||||
size_t arrSize = sizeof(uint32_t) * getLengthTotal();
|
||||
// softhack007 disabled; putting leds into psram leads to horrible slowdown on WROVER boards (see setUpLeds())
|
||||
//#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)
|
||||
//if (psramFound())
|
||||
// Segment::_globalLedBuffer = (CRGB*) ps_malloc(arrSize);
|
||||
//else
|
||||
//#endif
|
||||
_globalLedBuffer = (uint32_t*) malloc(arrSize);
|
||||
memset(_globalLedBuffer, 0, arrSize);
|
||||
}
|
||||
|
||||
//segments are created in makeAutoSegments();
|
||||
DEBUG_PRINTLN(F("Loading custom palettes"));
|
||||
loadCustomPalettes(); // (re)load all custom palettes
|
||||
@ -1103,11 +1056,10 @@ void WS2812FX::service() {
|
||||
if(nowUp > seg.next_time || _triggered || (doShow && seg.mode == FX_MODE_STATIC))
|
||||
{
|
||||
if (seg.grouping == 0) seg.grouping = 1; // sanity check
|
||||
if (!doShow) {
|
||||
busses.setBrightness(_brightness); // bus luminance must be set before FX using setPixelColor()
|
||||
_renderBrightness = _brightness; // save in case brightness gets changed while FX is calculated
|
||||
// if (!doShow) {
|
||||
// busses.setBrightness(_brightness); // bus luminance must be set before FX using setPixelColor()
|
||||
doShow = true;
|
||||
}
|
||||
// }
|
||||
uint16_t delay = FRAMETIME;
|
||||
|
||||
if (!seg.freeze) { //only run effect function if not frozen
|
||||
@ -1146,18 +1098,13 @@ void IRAM_ATTR WS2812FX::setPixelColor(int i, uint32_t col)
|
||||
{
|
||||
if (i < customMappingSize) i = customMappingTable[i];
|
||||
if (i >= _length) return;
|
||||
if (_globalLedBuffer) {
|
||||
_globalLedBuffer[i] = col;
|
||||
} else {
|
||||
busses.setPixelColor(i, col);
|
||||
}
|
||||
busses.setPixelColor(i, col);
|
||||
}
|
||||
|
||||
uint32_t WS2812FX::getPixelColor(uint16_t i)
|
||||
{
|
||||
if (i < customMappingSize) i = customMappingTable[i];
|
||||
if (i >= _length) return 0;
|
||||
if (_globalLedBuffer) return _globalLedBuffer[i];
|
||||
return busses.getPixelColor(i);
|
||||
}
|
||||
|
||||
@ -1188,7 +1135,6 @@ uint8_t WS2812FX::estimateCurrentAndLimitBri() {
|
||||
|
||||
if (ablMilliampsMax < 150 || actualMilliampsPerLed == 0) { //0 mA per LED and too low numbers turn off calculation
|
||||
currentMilliamps = 0;
|
||||
busses.setBrightness(_brightness);
|
||||
return _brightness;
|
||||
}
|
||||
|
||||
@ -1209,15 +1155,14 @@ uint8_t WS2812FX::estimateCurrentAndLimitBri() {
|
||||
uint16_t len = bus->getLength();
|
||||
uint32_t busPowerSum = 0;
|
||||
for (uint_fast16_t i = 0; i < len; i++) { //sum up the usage of each LED
|
||||
uint32_t c = 0;
|
||||
if (_globalLedBuffer)
|
||||
{
|
||||
c = _globalLedBuffer[bus->getStart() + i];
|
||||
} else {
|
||||
c = bus->getPixelColor(i);
|
||||
}
|
||||
uint32_t c = bus->getPixelColor(i);
|
||||
byte r = R(c), g = G(c), b = B(c), w = W(c);
|
||||
|
||||
if (useGlobalLedBuffer) {
|
||||
r = scale8(r, _brightness);
|
||||
g = scale8(g, _brightness);
|
||||
b = scale8(b, _brightness);
|
||||
w = scale8(w, _brightness);
|
||||
}
|
||||
if(useWackyWS2815PowerModel) { //ignore white component on WS2815 power calculation
|
||||
busPowerSum += (MAX(MAX(r,g),b)) * 3;
|
||||
} else {
|
||||
@ -1232,22 +1177,14 @@ uint8_t WS2812FX::estimateCurrentAndLimitBri() {
|
||||
powerSum += busPowerSum;
|
||||
}
|
||||
|
||||
uint32_t powerSum0 = powerSum;
|
||||
powerSum *= _brightness;
|
||||
uint8_t newBri = _brightness;
|
||||
|
||||
if (powerSum > powerBudget) //scale brightness down to stay in current limit
|
||||
{
|
||||
if (powerSum > powerBudget) {//scale brightness down to stay in current limit
|
||||
float scale = (float)powerBudget / (float)powerSum;
|
||||
uint16_t scaleI = scale * 255;
|
||||
uint8_t scaleB = (scaleI > 255) ? 255 : scaleI;
|
||||
newBri = scale8(_brightness, scaleB);
|
||||
busses.setBrightness(newBri); //to keep brightness uniform, sets virtual busses too
|
||||
currentMilliamps = (powerSum0 * newBri) / puPerMilliamp;
|
||||
} else {
|
||||
currentMilliamps = powerSum / puPerMilliamp;
|
||||
busses.setBrightness(_brightness);
|
||||
}
|
||||
currentMilliamps = (powerSum * newBri) / puPerMilliamp;
|
||||
currentMilliamps += MA_FOR_ESP; //add power of ESP back to estimate
|
||||
currentMilliamps += pLen; //add standby power back to estimate
|
||||
return newBri;
|
||||
@ -1259,19 +1196,8 @@ void WS2812FX::show(void) {
|
||||
show_callback callback = _callback;
|
||||
if (callback) callback();
|
||||
|
||||
Bus::setRestoreBri(_renderBrightness);
|
||||
uint8_t busBrightness = estimateCurrentAndLimitBri();
|
||||
|
||||
if (_globalLedBuffer) { // copy data from buffer to bus
|
||||
//for (uint16_t i = 0; i < _length; i++) busses.setPixelColor(i, _globalLedBuffer[i]);
|
||||
busses.setColorsFromBuffer(_globalLedBuffer);
|
||||
} else {
|
||||
// if brightness changed since last show, must set everything again to update to new luminance
|
||||
if (_renderBrightness != busBrightness) {
|
||||
for (uint16_t i = 0; i < _length; i++) busses.setPixelColor(i, busses.getPixelColor(i)); // LOSSLESS due to trick (but still slow!)
|
||||
Bus::setRestoreBri(busBrightness);
|
||||
}
|
||||
}
|
||||
busses.setBrightness(busBrightness);
|
||||
|
||||
// some buses send asynchronously and this method will return before
|
||||
// all of the data has been sent.
|
||||
@ -1283,7 +1209,6 @@ void WS2812FX::show(void) {
|
||||
if (diff > 0) fpsCurr = 1000 / diff;
|
||||
_cumulativeFps = (3 * _cumulativeFps + fpsCurr) >> 2;
|
||||
_lastShow = now;
|
||||
_renderBrightness = _brightness;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1351,8 +1276,6 @@ void WS2812FX::setBrightness(uint8_t b, bool direct) {
|
||||
if (direct) {
|
||||
// would be dangerous if applied immediately (could exceed ABL), but will not output until the next show()
|
||||
busses.setBrightness(b);
|
||||
_renderBrightness = b;
|
||||
Bus::setRestoreBri(b);
|
||||
} else {
|
||||
unsigned long t = millis();
|
||||
if (_segments[0].next_time > t + 22 && t - _lastShow > MIN_SHOW_DELAY) show(); //apply brightness change immediately if no refresh soon
|
||||
@ -1735,7 +1658,6 @@ bool WS2812FX::deserializeMap(uint8_t n) {
|
||||
|
||||
|
||||
WS2812FX* WS2812FX::instance = nullptr;
|
||||
uint32_t* WS2812FX::_globalLedBuffer = nullptr;
|
||||
|
||||
const char JSON_mode_names[] PROGMEM = R"=====(["FX names moved"])=====";
|
||||
const char JSON_palette_names[] PROGMEM = R"=====([
|
||||
|
@ -91,6 +91,11 @@ uint32_t Bus::autoWhiteCalc(uint32_t c) {
|
||||
return RGBW32(r, g, b, w);
|
||||
}
|
||||
|
||||
uint8_t *Bus::allocData(size_t size) {
|
||||
if (_data) free(_data); // should not happen, but for safety
|
||||
return _data = (uint8_t *)(size>0 ? calloc(size, sizeof(uint8_t)) : nullptr);
|
||||
}
|
||||
|
||||
|
||||
BusDigital::BusDigital(BusConfig &bc, uint8_t nr, const ColorOrderMap &com) : Bus(bc.type, bc.start, bc.autoWhite), _colorOrderMap(com) {
|
||||
if (!IS_DIGITAL(bc.type) || !bc.count) return;
|
||||
@ -107,22 +112,57 @@ BusDigital::BusDigital(BusConfig &bc, uint8_t nr, const ColorOrderMap &com) : Bu
|
||||
reversed = bc.reversed;
|
||||
_needsRefresh = bc.refreshReq || bc.type == TYPE_TM1814;
|
||||
_skip = bc.skipAmount; //sacrificial pixels
|
||||
_len = bc.count + _skip;
|
||||
_len = bc.count;
|
||||
_colorOrder = bc.colorOrder;
|
||||
_iType = PolyBus::getI(bc.type, _pins, nr);
|
||||
if (_iType == I_NONE) return;
|
||||
if (useGlobalLedBuffer && !allocData(_len * (hasWhite() + 3*hasRGB()))) return; //warning: hardcoded channel count
|
||||
uint16_t lenToCreate = _len;
|
||||
if (bc.type == TYPE_WS2812_1CH_X3) lenToCreate = NUM_ICS_WS2812_1CH_3X(_len); // only needs a third of "RGB" LEDs for NeoPixelBus
|
||||
_busPtr = PolyBus::create(_iType, _pins, lenToCreate, nr, _frequencykHz);
|
||||
if (bc.type == TYPE_WS2812_1CH_X3) lenToCreate = NUM_ICS_WS2812_1CH_3X(_len); // only needs a third of "RGB" LEDs for NeoPixelBus
|
||||
_busPtr = PolyBus::create(_iType, _pins, lenToCreate + _skip, nr, _frequencykHz);
|
||||
_valid = (_busPtr != nullptr);
|
||||
_colorOrder = bc.colorOrder;
|
||||
DEBUG_PRINTF("%successfully inited strip %u (len %u) with type %u and pins %u,%u (itype %u)\n", _valid?"S":"Uns", nr, _len, bc.type, _pins[0],_pins[1],_iType);
|
||||
}
|
||||
|
||||
void BusDigital::show() {
|
||||
PolyBus::show(_busPtr, _iType);
|
||||
if (!_valid) return;
|
||||
PolyBus::setBrightness(_busPtr, _iType, _bri);
|
||||
if (useGlobalLedBuffer) {
|
||||
size_t channels = hasWhite() + 3*hasRGB();
|
||||
for (size_t i=0; i<_len; i++) {
|
||||
size_t offset = i*channels;
|
||||
uint8_t co = _colorOrderMap.getPixelColorOrder(i+_start, _colorOrder);
|
||||
uint32_t c;
|
||||
if (_type == TYPE_WS2812_1CH_X3) { // map to correct IC, each controls 3 LEDs (_len is always a multiple of 3)
|
||||
switch (i%3) {
|
||||
case 0: c = RGBW32(_data[offset] , _data[offset+1], _data[offset+2], 0); break;
|
||||
case 1: c = RGBW32(_data[offset-1], _data[offset] , _data[offset+1], 0); break;
|
||||
case 2: c = RGBW32(_data[offset-2], _data[offset-1], _data[offset] , 0); break;
|
||||
}
|
||||
} else {
|
||||
c = RGBW32(_data[offset],_data[offset+1],_data[offset+2],(hasWhite()?_data[offset+3]:0));
|
||||
}
|
||||
uint16_t pix = i;
|
||||
if (reversed) pix = _len - pix -1;
|
||||
else pix += _skip;
|
||||
PolyBus::setPixelColor(_busPtr, _iType, pix, c, co);
|
||||
}
|
||||
PolyBus::show(_busPtr, _iType);
|
||||
} else {
|
||||
PolyBus::applyPostAdjustments(_busPtr, _iType);
|
||||
PolyBus::show(_busPtr, _iType);
|
||||
// now restore (as close as possible) previous colors
|
||||
// warning: this may not be the best idea as the buffer may still be in use
|
||||
for (size_t i=0; i<_len; i++) {
|
||||
uint8_t co = _colorOrderMap.getPixelColorOrder(i+_start, _colorOrder);
|
||||
setPixelColor(i, restoreColorLossy(PolyBus::getPixelColor(_busPtr, _iType, i, co), _bri));
|
||||
}
|
||||
}
|
||||
PolyBus::setBrightness(_busPtr, _iType, 255); // restore full brightness
|
||||
}
|
||||
|
||||
bool BusDigital::canShow() {
|
||||
if (!_valid) return true;
|
||||
return PolyBus::canShow(_busPtr, _iType);
|
||||
}
|
||||
|
||||
@ -130,57 +170,81 @@ void BusDigital::setBrightness(uint8_t b) {
|
||||
//Fix for turning off onboard LED breaking bus
|
||||
#ifdef LED_BUILTIN
|
||||
if (_bri == 0 && b > 0) {
|
||||
if (_pins[0] == LED_BUILTIN || _pins[1] == LED_BUILTIN) PolyBus::begin(_busPtr, _iType, _pins);
|
||||
if (_pins[0] == LED_BUILTIN || _pins[1] == LED_BUILTIN) reinit();
|
||||
}
|
||||
#endif
|
||||
Bus::setBrightness(b);
|
||||
PolyBus::setBrightness(_busPtr, _iType, b);
|
||||
}
|
||||
|
||||
//If LEDs are skipped, it is possible to use the first as a status LED.
|
||||
//TODO only show if no new show due in the next 50ms
|
||||
void BusDigital::setStatusPixel(uint32_t c) {
|
||||
if (_skip && canShow()) {
|
||||
if (_valid && _skip && canShow()) {
|
||||
PolyBus::setPixelColor(_busPtr, _iType, 0, c, _colorOrderMap.getPixelColorOrder(_start, _colorOrder));
|
||||
PolyBus::show(_busPtr, _iType);
|
||||
}
|
||||
}
|
||||
|
||||
void IRAM_ATTR BusDigital::setPixelColor(uint16_t pix, uint32_t c) {
|
||||
if (_type == TYPE_SK6812_RGBW || _type == TYPE_TM1814 || _type == TYPE_WS2812_1CH_X3) c = autoWhiteCalc(c);
|
||||
if (!_valid) return;
|
||||
if (hasWhite()) c = autoWhiteCalc(c);
|
||||
if (_cct >= 1900) c = colorBalanceFromKelvin(_cct, c); //color correction from CCT
|
||||
if (reversed) pix = _len - pix -1;
|
||||
else pix += _skip;
|
||||
uint8_t co = _colorOrderMap.getPixelColorOrder(pix+_start, _colorOrder);
|
||||
if (_type == TYPE_WS2812_1CH_X3) { // map to correct IC, each controls 3 LEDs
|
||||
uint16_t pOld = pix;
|
||||
pix = IC_INDEX_WS2812_1CH_3X(pix);
|
||||
uint32_t cOld = PolyBus::getPixelColor(_busPtr, _iType, pix, co);
|
||||
switch (pOld % 3) { // change only the single channel (TODO: this can cause loss because of get/set)
|
||||
case 0: c = RGBW32(R(cOld), W(c) , B(cOld), 0); break;
|
||||
case 1: c = RGBW32(W(c) , G(cOld), B(cOld), 0); break;
|
||||
case 2: c = RGBW32(R(cOld), G(cOld), W(c) , 0); break;
|
||||
if (useGlobalLedBuffer) {
|
||||
size_t channels = hasWhite() + 3*hasRGB();
|
||||
size_t offset = pix*channels;
|
||||
if (hasRGB()) {
|
||||
_data[offset++] = R(c);
|
||||
_data[offset++] = G(c);
|
||||
_data[offset++] = B(c);
|
||||
}
|
||||
if (hasWhite()) _data[offset] = W(c);
|
||||
} else {
|
||||
if (reversed) pix = _len - pix -1;
|
||||
else pix += _skip;
|
||||
uint8_t co = _colorOrderMap.getPixelColorOrder(pix+_start, _colorOrder);
|
||||
if (_type == TYPE_WS2812_1CH_X3) { // map to correct IC, each controls 3 LEDs
|
||||
uint16_t pOld = pix;
|
||||
pix = IC_INDEX_WS2812_1CH_3X(pix);
|
||||
uint32_t cOld = PolyBus::getPixelColor(_busPtr, _iType, pix, co);
|
||||
switch (pOld % 3) { // change only the single channel (TODO: this can cause loss because of get/set)
|
||||
case 0: c = RGBW32(R(cOld), W(c) , B(cOld), 0); break;
|
||||
case 1: c = RGBW32(W(c) , G(cOld), B(cOld), 0); break;
|
||||
case 2: c = RGBW32(R(cOld), G(cOld), W(c) , 0); break;
|
||||
}
|
||||
}
|
||||
PolyBus::setPixelColor(_busPtr, _iType, pix, c, co);
|
||||
}
|
||||
PolyBus::setPixelColor(_busPtr, _iType, pix, c, co);
|
||||
}
|
||||
|
||||
uint32_t BusDigital::getPixelColor(uint16_t pix) {
|
||||
if (reversed) pix = _len - pix -1;
|
||||
else pix += _skip;
|
||||
uint8_t co = _colorOrderMap.getPixelColorOrder(pix+_start, _colorOrder);
|
||||
if (_type == TYPE_WS2812_1CH_X3) { // map to correct IC, each controls 3 LEDs
|
||||
uint16_t pOld = pix;
|
||||
pix = IC_INDEX_WS2812_1CH_3X(pix);
|
||||
uint32_t c = restoreColorLossy(PolyBus::getPixelColor(_busPtr, _iType, pix, co));
|
||||
switch (pOld % 3) { // get only the single channel
|
||||
case 0: c = RGBW32(G(c), G(c), G(c), G(c)); break;
|
||||
case 1: c = RGBW32(R(c), R(c), R(c), R(c)); break;
|
||||
case 2: c = RGBW32(B(c), B(c), B(c), B(c)); break;
|
||||
if (!_valid) return 0;
|
||||
if (useGlobalLedBuffer) {
|
||||
size_t channels = hasWhite() + 3*hasRGB();
|
||||
size_t offset = pix*channels;
|
||||
uint32_t c;
|
||||
if (!hasRGB()) {
|
||||
c = RGBW32(_data[offset], _data[offset], _data[offset], _data[offset]);
|
||||
} else {
|
||||
c = RGBW32(_data[offset], _data[offset+1], _data[offset+2], hasWhite() ? _data[offset+3] : 0);
|
||||
}
|
||||
return c;
|
||||
} else {
|
||||
if (reversed) pix = _len - pix -1;
|
||||
else pix += _skip;
|
||||
uint8_t co = _colorOrderMap.getPixelColorOrder(pix+_start, _colorOrder);
|
||||
if (_type == TYPE_WS2812_1CH_X3) { // map to correct IC, each controls 3 LEDs
|
||||
uint16_t pOld = pix;
|
||||
pix = IC_INDEX_WS2812_1CH_3X(pix);
|
||||
uint32_t c = PolyBus::getPixelColor(_busPtr, _iType, pix, co);
|
||||
switch (pOld % 3) { // get only the single channel
|
||||
case 0: c = RGBW32(G(c), G(c), G(c), G(c)); break;
|
||||
case 1: c = RGBW32(R(c), R(c), R(c), R(c)); break;
|
||||
case 2: c = RGBW32(B(c), B(c), B(c), B(c)); break;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
return PolyBus::getPixelColor(_busPtr, _iType, pix, co);
|
||||
}
|
||||
return restoreColorLossy(PolyBus::getPixelColor(_busPtr, _iType, pix, co));
|
||||
}
|
||||
|
||||
uint8_t BusDigital::getPins(uint8_t* pinArray) {
|
||||
@ -196,6 +260,7 @@ void BusDigital::setColorOrder(uint8_t colorOrder) {
|
||||
}
|
||||
|
||||
void BusDigital::reinit() {
|
||||
if (!_valid) return;
|
||||
PolyBus::begin(_busPtr, _iType, _pins);
|
||||
}
|
||||
|
||||
@ -205,6 +270,7 @@ void BusDigital::cleanup() {
|
||||
_iType = I_NONE;
|
||||
_valid = false;
|
||||
_busPtr = nullptr;
|
||||
if (useGlobalLedBuffer) freeData();
|
||||
pinManager.deallocatePin(_pins[1], PinOwner::BusDigital);
|
||||
pinManager.deallocatePin(_pins[0], PinOwner::BusDigital);
|
||||
}
|
||||
@ -229,7 +295,7 @@ BusPwm::BusPwm(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) {
|
||||
for (uint8_t i = 0; i < numPins; i++) {
|
||||
uint8_t currentPin = bc.pins[i];
|
||||
if (!pinManager.allocatePin(currentPin, true, PinOwner::BusPwm)) {
|
||||
deallocatePins(); return;
|
||||
deallocatePins(); return;
|
||||
}
|
||||
_pins[i] = currentPin; //store only after allocatePin() succeeds
|
||||
#ifdef ESP8266
|
||||
@ -240,6 +306,7 @@ BusPwm::BusPwm(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) {
|
||||
#endif
|
||||
}
|
||||
reversed = bc.reversed;
|
||||
_data = _pwmdata; // avoid malloc() and use stack
|
||||
_valid = true;
|
||||
}
|
||||
|
||||
@ -353,6 +420,7 @@ BusOnOff::BusOnOff(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) {
|
||||
_pin = currentPin; //store only after allocatePin() succeeds
|
||||
pinMode(_pin, OUTPUT);
|
||||
reversed = bc.reversed;
|
||||
_data = &_onoffdata; // avoid malloc() and use stack
|
||||
_valid = true;
|
||||
}
|
||||
|
||||
@ -363,18 +431,17 @@ void BusOnOff::setPixelColor(uint16_t pix, uint32_t c) {
|
||||
uint8_t g = G(c);
|
||||
uint8_t b = B(c);
|
||||
uint8_t w = W(c);
|
||||
|
||||
_data = bool(r|g|b|w) && bool(_bri) ? 0xFF : 0;
|
||||
_data[0] = bool(r|g|b|w) && bool(_bri) ? 0xFF : 0;
|
||||
}
|
||||
|
||||
uint32_t BusOnOff::getPixelColor(uint16_t pix) {
|
||||
if (!_valid) return 0;
|
||||
return RGBW32(_data, _data, _data, _data);
|
||||
return RGBW32(_data[0], _data[0], _data[0], _data[0]);
|
||||
}
|
||||
|
||||
void BusOnOff::show() {
|
||||
if (!_valid) return;
|
||||
digitalWrite(_pin, reversed ? !(bool)_data : (bool)_data);
|
||||
digitalWrite(_pin, reversed ? !(bool)_data[0] : (bool)_data[0]);
|
||||
}
|
||||
|
||||
uint8_t BusOnOff::getPins(uint8_t* pinArray) {
|
||||
@ -401,13 +468,10 @@ BusNetwork::BusNetwork(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) {
|
||||
break;
|
||||
}
|
||||
_UDPchannels = _rgbw ? 4 : 3;
|
||||
_data = (byte *)malloc(bc.count * _UDPchannels);
|
||||
if (_data == nullptr) return;
|
||||
memset(_data, 0, bc.count * _UDPchannels);
|
||||
_len = bc.count;
|
||||
_client = IPAddress(bc.pins[0],bc.pins[1],bc.pins[2],bc.pins[3]);
|
||||
_broadcastLock = false;
|
||||
_valid = true;
|
||||
_valid = (allocData(_len * _UDPchannels) != nullptr);
|
||||
}
|
||||
|
||||
void BusNetwork::setPixelColor(uint16_t pix, uint32_t c) {
|
||||
@ -424,7 +488,7 @@ void BusNetwork::setPixelColor(uint16_t pix, uint32_t c) {
|
||||
uint32_t BusNetwork::getPixelColor(uint16_t pix) {
|
||||
if (!_valid || pix >= _len) return 0;
|
||||
uint16_t offset = pix * _UDPchannels;
|
||||
return RGBW32(_data[offset], _data[offset+1], _data[offset+2], _rgbw ? (_data[offset+3] << 24) : 0);
|
||||
return RGBW32(_data[offset], _data[offset+1], _data[offset+2], (_rgbw ? _data[offset+3] : 0));
|
||||
}
|
||||
|
||||
void BusNetwork::show() {
|
||||
@ -444,8 +508,7 @@ uint8_t BusNetwork::getPins(uint8_t* pinArray) {
|
||||
void BusNetwork::cleanup() {
|
||||
_type = I_NONE;
|
||||
_valid = false;
|
||||
if (_data != nullptr) free(_data);
|
||||
_data = nullptr;
|
||||
freeData();
|
||||
}
|
||||
|
||||
|
||||
@ -515,15 +578,6 @@ void IRAM_ATTR BusManager::setPixelColor(uint16_t pix, uint32_t c) {
|
||||
}
|
||||
}
|
||||
|
||||
void BusManager::setColorsFromBuffer(uint32_t* buf) {
|
||||
for (uint8_t i = 0; i < numBusses; i++) {
|
||||
Bus* b = busses[i];
|
||||
uint16_t bstart = b->getStart();
|
||||
for (uint16_t pix = 0; pix < b->getLength(); pix++)
|
||||
busses[i]->setPixelColor(pix, buf[bstart + pix]);
|
||||
}
|
||||
}
|
||||
|
||||
void BusManager::setBrightness(uint8_t b) {
|
||||
for (uint8_t i = 0; i < numBusses; i++) {
|
||||
busses[i]->setBrightness(b);
|
||||
@ -572,4 +626,3 @@ uint16_t BusManager::getTotalLength() {
|
||||
int16_t Bus::_cct = -1;
|
||||
uint8_t Bus::_cctBlend = 0;
|
||||
uint8_t Bus::_gAWM = 255;
|
||||
uint8_t Bus::_restaurationBri = 255;
|
||||
|
@ -18,6 +18,10 @@
|
||||
#define IC_INDEX_WS2812_2CH_3X(i) ((i)*2/3)
|
||||
#define WS2812_2CH_3X_SPANS_2_ICS(i) ((i)&0x01) // every other LED zone is on two different ICs
|
||||
|
||||
// flag for using double buffering in BusDigital
|
||||
extern bool useGlobalLedBuffer;
|
||||
|
||||
|
||||
//temporary struct for passing bus configuration to bus
|
||||
struct BusConfig {
|
||||
uint8_t type;
|
||||
@ -54,6 +58,7 @@ struct BusConfig {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Defines an LED Strip and its color ordering.
|
||||
struct ColorOrderMapEntry {
|
||||
uint16_t start;
|
||||
@ -87,12 +92,14 @@ struct ColorOrderMap {
|
||||
ColorOrderMapEntry _mappings[WLED_MAX_COLOR_ORDER_MAPPINGS];
|
||||
};
|
||||
|
||||
|
||||
//parent class of BusDigital, BusPwm, and BusNetwork
|
||||
class Bus {
|
||||
public:
|
||||
Bus(uint8_t type, uint16_t start, uint8_t aw)
|
||||
: _bri(255)
|
||||
, _len(1)
|
||||
, _data(nullptr) // keep data access consistent across all types of buses
|
||||
, _valid(false)
|
||||
, _needsRefresh(false)
|
||||
{
|
||||
@ -154,7 +161,6 @@ class Bus {
|
||||
inline uint8_t getAutoWhiteMode() { return _autoWhiteMode; }
|
||||
inline static void setGlobalAWMode(uint8_t m) { if (m < 5) _gAWM = m; else _gAWM = AW_GLOBAL_DISABLED; }
|
||||
inline static uint8_t getGlobalAWMode() { return _gAWM; }
|
||||
inline static void setRestoreBri(uint8_t b) { _restaurationBri = b; }
|
||||
|
||||
bool reversed = false;
|
||||
|
||||
@ -163,15 +169,17 @@ class Bus {
|
||||
uint8_t _bri;
|
||||
uint16_t _start;
|
||||
uint16_t _len;
|
||||
uint8_t *_data;
|
||||
bool _valid;
|
||||
bool _needsRefresh;
|
||||
uint8_t _autoWhiteMode;
|
||||
static uint8_t _gAWM;
|
||||
static int16_t _cct;
|
||||
static uint8_t _cctBlend;
|
||||
static uint8_t _restaurationBri; // previous brightness used as setPixelColor was called. Used for lossy restoration
|
||||
|
||||
uint32_t autoWhiteCalc(uint32_t c);
|
||||
uint8_t *allocData(size_t size = 1);
|
||||
void freeData() { if (_data) free(_data); _data = nullptr; }
|
||||
};
|
||||
|
||||
|
||||
@ -226,7 +234,7 @@ class BusDigital : public Bus {
|
||||
void * _busPtr = nullptr;
|
||||
const ColorOrderMap &_colorOrderMap;
|
||||
|
||||
inline uint32_t restoreColorLossy(uint32_t c) {
|
||||
inline uint32_t restoreColorLossy(uint32_t c, uint8_t _restaurationBri) {
|
||||
if (_bri == 255) return c;
|
||||
uint8_t* chan = (uint8_t*) &c;
|
||||
|
||||
@ -265,7 +273,7 @@ class BusPwm : public Bus {
|
||||
|
||||
private:
|
||||
uint8_t _pins[5] = {255, 255, 255, 255, 255};
|
||||
uint8_t _data[5] = {0};
|
||||
uint8_t _pwmdata[5] = {0};
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
uint8_t _ledcStart = 255;
|
||||
#endif
|
||||
@ -297,7 +305,7 @@ class BusOnOff : public Bus {
|
||||
|
||||
private:
|
||||
uint8_t _pin = 255;
|
||||
uint8_t _data = 0;
|
||||
uint8_t _onoffdata = 0;
|
||||
};
|
||||
|
||||
|
||||
@ -337,7 +345,6 @@ class BusNetwork : public Bus {
|
||||
uint8_t _UDPchannels;
|
||||
bool _rgbw;
|
||||
bool _broadcastLock;
|
||||
byte *_data;
|
||||
};
|
||||
|
||||
|
||||
@ -359,8 +366,6 @@ class BusManager {
|
||||
|
||||
void setPixelColor(uint16_t pix, uint32_t c);
|
||||
|
||||
void setColorsFromBuffer(uint32_t* buf);
|
||||
|
||||
void setBrightness(uint8_t b);
|
||||
|
||||
void setSegmentCCT(int16_t cct, bool allowWBCorrection = false);
|
||||
|
@ -280,6 +280,7 @@ class PolyBus {
|
||||
#endif
|
||||
if (clock_kHz) dotStar_strip->SetMethodSettings(NeoSpiSettings((uint32_t)clock_kHz*1000));
|
||||
}
|
||||
|
||||
// Begin & initialize the PixelSettings for TM1814 strips.
|
||||
template <class T>
|
||||
static void beginTM1814(void* busPtr) {
|
||||
@ -288,6 +289,7 @@ class PolyBus {
|
||||
// Max current for each LED (22.5 mA).
|
||||
tm1814_strip->SetPixelSettings(NeoTm1814Settings(/*R*/225, /*G*/225, /*B*/225, /*W*/225));
|
||||
}
|
||||
|
||||
static void begin(void* busPtr, uint8_t busType, uint8_t* pins, uint16_t clock_kHz = 0U) {
|
||||
switch (busType) {
|
||||
case I_NONE: break;
|
||||
@ -390,7 +392,8 @@ class PolyBus {
|
||||
case I_SS_WS1_3: (static_cast<B_SS_WS1_3*>(busPtr))->Begin(); break;
|
||||
case I_SS_P98_3: (static_cast<B_SS_P98_3*>(busPtr))->Begin(); break;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static void* create(uint8_t busType, uint8_t* pins, uint16_t len, uint8_t channel, uint16_t clock_kHz = 0U) {
|
||||
void* busPtr = nullptr;
|
||||
switch (busType) {
|
||||
@ -491,7 +494,8 @@ class PolyBus {
|
||||
}
|
||||
begin(busPtr, busType, pins, clock_kHz);
|
||||
return busPtr;
|
||||
};
|
||||
}
|
||||
|
||||
static void show(void* busPtr, uint8_t busType) {
|
||||
switch (busType) {
|
||||
case I_NONE: break;
|
||||
@ -588,7 +592,8 @@ class PolyBus {
|
||||
case I_HS_P98_3: (static_cast<B_HS_P98_3*>(busPtr))->Show(); break;
|
||||
case I_SS_P98_3: (static_cast<B_SS_P98_3*>(busPtr))->Show(); break;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static bool canShow(void* busPtr, uint8_t busType) {
|
||||
switch (busType) {
|
||||
case I_NONE: return true;
|
||||
@ -685,7 +690,8 @@ class PolyBus {
|
||||
case I_SS_P98_3: return (static_cast<B_SS_P98_3*>(busPtr))->CanShow(); break;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
static void setPixelColor(void* busPtr, uint8_t busType, uint16_t pix, uint32_t c, uint8_t co) {
|
||||
uint8_t r = c >> 16;
|
||||
uint8_t g = c >> 8;
|
||||
@ -805,7 +811,8 @@ class PolyBus {
|
||||
case I_HS_P98_3: (static_cast<B_HS_P98_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
||||
case I_SS_P98_3: (static_cast<B_SS_P98_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static void setBrightness(void* busPtr, uint8_t busType, uint8_t b) {
|
||||
switch (busType) {
|
||||
case I_NONE: break;
|
||||
@ -902,7 +909,106 @@ class PolyBus {
|
||||
case I_HS_P98_3: (static_cast<B_HS_P98_3*>(busPtr))->SetLuminance(b); break;
|
||||
case I_SS_P98_3: (static_cast<B_SS_P98_3*>(busPtr))->SetLuminance(b); break;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static void applyPostAdjustments(void* busPtr, uint8_t busType) {
|
||||
switch (busType) {
|
||||
case I_NONE: break;
|
||||
#ifdef ESP8266
|
||||
case I_8266_U0_NEO_3: (static_cast<B_8266_U0_NEO_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_8266_U1_NEO_3: (static_cast<B_8266_U1_NEO_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_8266_DM_NEO_3: (static_cast<B_8266_DM_NEO_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_8266_BB_NEO_3: (static_cast<B_8266_BB_NEO_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_8266_U0_NEO_4: (static_cast<B_8266_U0_NEO_4*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_8266_U1_NEO_4: (static_cast<B_8266_U1_NEO_4*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_8266_DM_NEO_4: (static_cast<B_8266_DM_NEO_4*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_8266_BB_NEO_4: (static_cast<B_8266_BB_NEO_4*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_8266_U0_400_3: (static_cast<B_8266_U0_400_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_8266_U1_400_3: (static_cast<B_8266_U1_400_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_8266_DM_400_3: (static_cast<B_8266_DM_400_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_8266_BB_400_3: (static_cast<B_8266_BB_400_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_8266_U0_TM1_4: (static_cast<B_8266_U0_TM1_4*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_8266_U1_TM1_4: (static_cast<B_8266_U1_TM1_4*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_8266_DM_TM1_4: (static_cast<B_8266_DM_TM1_4*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_8266_BB_TM1_4: (static_cast<B_8266_BB_TM1_4*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_8266_U0_TM2_3: (static_cast<B_8266_U0_TM2_4*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_8266_U1_TM2_3: (static_cast<B_8266_U1_TM2_4*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_8266_DM_TM2_3: (static_cast<B_8266_DM_TM2_4*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_8266_BB_TM2_3: (static_cast<B_8266_BB_TM2_4*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_8266_U0_UCS_3: (static_cast<B_8266_U0_UCS_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_8266_U1_UCS_3: (static_cast<B_8266_U1_UCS_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_8266_DM_UCS_3: (static_cast<B_8266_DM_UCS_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_8266_BB_UCS_3: (static_cast<B_8266_BB_UCS_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_8266_U0_UCS_4: (static_cast<B_8266_U0_UCS_4*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_8266_U1_UCS_4: (static_cast<B_8266_U1_UCS_4*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_8266_DM_UCS_4: (static_cast<B_8266_DM_UCS_4*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_8266_BB_UCS_4: (static_cast<B_8266_BB_UCS_4*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
#endif
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_NEO_3: (static_cast<B_32_I0_NEO_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
#endif
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_NEO_3: (static_cast<B_32_I1_NEO_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
#endif
|
||||
// case I_32_BB_NEO_3: (static_cast<B_32_BB_NEO_3*>(busPtr))->SetLuminance(b); (static_cast<B_32_BB_NEO_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_32_RN_NEO_4: (static_cast<B_32_RN_NEO_4*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_NEO_4: (static_cast<B_32_I0_NEO_4*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
#endif
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_NEO_4: (static_cast<B_32_I1_NEO_4*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
#endif
|
||||
// case I_32_BB_NEO_4: (static_cast<B_32_BB_NEO_4*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_32_RN_400_3: (static_cast<B_32_RN_400_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_400_3: (static_cast<B_32_I0_400_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
#endif
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_400_3: (static_cast<B_32_I1_400_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
#endif
|
||||
// case I_32_BB_400_3: (static_cast<B_32_BB_400_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_32_RN_TM1_4: (static_cast<B_32_RN_TM1_4*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_32_RN_TM2_3: (static_cast<B_32_RN_TM2_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_TM1_4: (static_cast<B_32_I0_TM1_4*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_32_I0_TM2_3: (static_cast<B_32_I0_TM2_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
#endif
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_TM1_4: (static_cast<B_32_I1_TM1_4*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_32_I1_TM2_3: (static_cast<B_32_I1_TM2_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
#endif
|
||||
case I_32_RN_UCS_3: (static_cast<B_32_RN_UCS_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_UCS_3: (static_cast<B_32_I0_UCS_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
#endif
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_UCS_3: (static_cast<B_32_I1_UCS_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
#endif
|
||||
// case I_32_BB_UCS_3: (static_cast<B_32_BB_UCS_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_32_RN_UCS_4: (static_cast<B_32_RN_UCS_4*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
case I_32_I0_UCS_4: (static_cast<B_32_I0_UCS_4*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
#endif
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
case I_32_I1_UCS_4: (static_cast<B_32_I1_UCS_4*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
#endif
|
||||
// case I_32_BB_UCS_4: (static_cast<B_32_BB_UCS_4*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
#endif
|
||||
case I_HS_DOT_3: (static_cast<B_HS_DOT_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_SS_DOT_3: (static_cast<B_SS_DOT_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_HS_LPD_3: (static_cast<B_HS_LPD_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_SS_LPD_3: (static_cast<B_SS_LPD_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_HS_LPO_3: (static_cast<B_HS_LPO_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_SS_LPO_3: (static_cast<B_SS_LPO_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_HS_WS1_3: (static_cast<B_HS_WS1_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_SS_WS1_3: (static_cast<B_SS_WS1_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_HS_P98_3: (static_cast<B_HS_P98_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
case I_SS_P98_3: (static_cast<B_SS_P98_3*>(busPtr))->ApplyPostAdjustments(); break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t getPixelColor(void* busPtr, uint8_t busType, uint16_t pix, uint8_t co) {
|
||||
RgbwColor col(0,0,0,0);
|
||||
switch (busType) {
|
||||
|
@ -90,7 +90,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
CJSON(strip.cctBlending, hw_led[F("cb")]);
|
||||
Bus::setCCTBlend(strip.cctBlending);
|
||||
strip.setTargetFps(hw_led["fps"]); //NOP if 0, default 42 FPS
|
||||
CJSON(strip.useGlobalLedBuffer, hw_led[F("ld")]);
|
||||
CJSON(useGlobalLedBuffer, hw_led[F("ld")]);
|
||||
|
||||
#ifndef WLED_DISABLE_2D
|
||||
// 2D Matrix Settings
|
||||
@ -163,7 +163,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
if (fromFS) {
|
||||
BusConfig bc = BusConfig(ledType, pins, start, length, colorOrder, reversed, skipFirst, AWmode, freqkHz);
|
||||
mem += BusManager::memUsage(bc);
|
||||
if (strip.useGlobalLedBuffer && start + length > maxlen) {
|
||||
if (useGlobalLedBuffer && start + length > maxlen) {
|
||||
maxlen = start + length;
|
||||
globalBufMem = maxlen * 4;
|
||||
}
|
||||
@ -711,7 +711,7 @@ void serializeConfig() {
|
||||
hw_led[F("cb")] = strip.cctBlending;
|
||||
hw_led["fps"] = strip.getTargetFps();
|
||||
hw_led[F("rgbwm")] = Bus::getGlobalAWMode(); // global auto white mode override
|
||||
hw_led[F("ld")] = strip.useGlobalLedBuffer;
|
||||
hw_led[F("ld")] = useGlobalLedBuffer;
|
||||
|
||||
#ifndef WLED_DISABLE_2D
|
||||
// 2D Matrix Settings
|
||||
|
@ -91,7 +91,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
Bus::setCCTBlend(strip.cctBlending);
|
||||
Bus::setGlobalAWMode(request->arg(F("AW")).toInt());
|
||||
strip.setTargetFps(request->arg(F("FR")).toInt());
|
||||
strip.useGlobalLedBuffer = request->hasArg(F("LD"));
|
||||
useGlobalLedBuffer = request->hasArg(F("LD"));
|
||||
|
||||
bool busesChanged = false;
|
||||
for (uint8_t s = 0; s < WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES; s++) {
|
||||
|
@ -156,7 +156,7 @@ void WLED::loop()
|
||||
for (uint8_t i = 0; i < WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES; i++) {
|
||||
if (busConfigs[i] == nullptr) break;
|
||||
mem += BusManager::memUsage(*busConfigs[i]);
|
||||
if (strip.useGlobalLedBuffer && busConfigs[i]->start + busConfigs[i]->count > maxlen) {
|
||||
if (useGlobalLedBuffer && busConfigs[i]->start + busConfigs[i]->count > maxlen) {
|
||||
maxlen = busConfigs[i]->start + busConfigs[i]->count;
|
||||
globalBufMem = maxlen * 4;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
*/
|
||||
|
||||
// version code in format yymmddb (b = daily build)
|
||||
#define VERSION 2306240
|
||||
#define VERSION 23062490
|
||||
|
||||
//uncomment this if you have a "my_config.h" file you'd like to use
|
||||
//#define WLED_USE_MY_CONFIG
|
||||
@ -331,12 +331,13 @@ WLED_GLOBAL byte bootPreset _INIT(0); // save preset to load
|
||||
//if true, a segment per bus will be created on boot and LED settings save
|
||||
//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
|
||||
WLED_GLOBAL bool autoSegments _INIT(false);
|
||||
WLED_GLOBAL bool correctWB _INIT(false); // CCT color correction of RGB color
|
||||
WLED_GLOBAL bool cctFromRgb _INIT(false); // CCT is calculated from RGB instead of using seg.cct
|
||||
WLED_GLOBAL bool gammaCorrectCol _INIT(true ); // use gamma correction on colors
|
||||
WLED_GLOBAL bool gammaCorrectBri _INIT(false); // use gamma correction on brightness
|
||||
WLED_GLOBAL float gammaCorrectVal _INIT(2.8f); // gamma correction value
|
||||
WLED_GLOBAL bool autoSegments _INIT(false);
|
||||
WLED_GLOBAL bool useGlobalLedBuffer _INIT(true);
|
||||
WLED_GLOBAL bool correctWB _INIT(false); // CCT color correction of RGB color
|
||||
WLED_GLOBAL bool cctFromRgb _INIT(false); // CCT is calculated from RGB instead of using seg.cct
|
||||
WLED_GLOBAL bool gammaCorrectCol _INIT(true); // use gamma correction on colors
|
||||
WLED_GLOBAL bool gammaCorrectBri _INIT(false); // use gamma correction on brightness
|
||||
WLED_GLOBAL float gammaCorrectVal _INIT(2.8f); // gamma correction value
|
||||
|
||||
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
|
||||
|
@ -404,7 +404,7 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
sappend('v',SET_F("CB"),strip.cctBlending);
|
||||
sappend('v',SET_F("FR"),strip.getTargetFps());
|
||||
sappend('v',SET_F("AW"),Bus::getGlobalAWMode());
|
||||
sappend('c',SET_F("LD"),strip.useGlobalLedBuffer);
|
||||
sappend('c',SET_F("LD"),useGlobalLedBuffer);
|
||||
|
||||
for (uint8_t s=0; s < busses.getNumBusses(); s++) {
|
||||
Bus* bus = busses.getBus(s);
|
||||
|
Loading…
Reference in New Issue
Block a user