mirror of
https://github.com/wled/WLED.git
synced 2025-07-24 19:26:40 +00:00
Full per-port ABL implementation and bugfix.
Update of BusManager class (static)
This commit is contained in:
parent
6cd0da821a
commit
1c1b67e000
@ -84,11 +84,11 @@ class QuinLEDAnPentaUsermod : public Usermod
|
|||||||
void getCurrentUsedLedPins()
|
void getCurrentUsedLedPins()
|
||||||
{
|
{
|
||||||
for (int8_t lp = 0; lp <= 4; lp++) currentLedPins[lp] = 0;
|
for (int8_t lp = 0; lp <= 4; lp++) currentLedPins[lp] = 0;
|
||||||
byte numBusses = busses.getNumBusses();
|
byte numBusses = BusManager::getNumBusses();
|
||||||
byte numUsedPins = 0;
|
byte numUsedPins = 0;
|
||||||
|
|
||||||
for (int8_t b = 0; b < numBusses; b++) {
|
for (int8_t b = 0; b < numBusses; b++) {
|
||||||
Bus* curBus = busses.getBus(b);
|
Bus* curBus = BusManager::getBus(b);
|
||||||
if (curBus != nullptr) {
|
if (curBus != nullptr) {
|
||||||
uint8_t pins[5] = {0, 0, 0, 0, 0};
|
uint8_t pins[5] = {0, 0, 0, 0, 0};
|
||||||
currentBussesNumPins[b] = curBus->getPins(pins);
|
currentBussesNumPins[b] = curBus->getPins(pins);
|
||||||
@ -104,11 +104,11 @@ class QuinLEDAnPentaUsermod : public Usermod
|
|||||||
|
|
||||||
void getCurrentLedcValues()
|
void getCurrentLedcValues()
|
||||||
{
|
{
|
||||||
byte numBusses = busses.getNumBusses();
|
byte numBusses = BusManager::getNumBusses();
|
||||||
byte numLedc = 0;
|
byte numLedc = 0;
|
||||||
|
|
||||||
for (int8_t b = 0; b < numBusses; b++) {
|
for (int8_t b = 0; b < numBusses; b++) {
|
||||||
Bus* curBus = busses.getBus(b);
|
Bus* curBus = BusManager::getBus(b);
|
||||||
if (curBus != nullptr) {
|
if (curBus != nullptr) {
|
||||||
uint32_t curPixColor = curBus->getPixelColor(0);
|
uint32_t curPixColor = curBus->getPixelColor(0);
|
||||||
uint8_t _data[5] = {255, 255, 255, 255, 255};
|
uint8_t _data[5] = {255, 255, 255, 255, 255};
|
||||||
|
@ -682,10 +682,7 @@ class WS2812FX { // 96 bytes
|
|||||||
WS2812FX() :
|
WS2812FX() :
|
||||||
paletteFade(0),
|
paletteFade(0),
|
||||||
paletteBlend(0),
|
paletteBlend(0),
|
||||||
milliampsPerLed(55),
|
|
||||||
cctBlending(0),
|
cctBlending(0),
|
||||||
ablMilliampsMax(ABL_MILLIAMPS_DEFAULT),
|
|
||||||
currentMilliamps(0),
|
|
||||||
now(millis()),
|
now(millis()),
|
||||||
timebase(0),
|
timebase(0),
|
||||||
isMatrix(false),
|
isMatrix(false),
|
||||||
@ -793,7 +790,6 @@ class WS2812FX { // 96 bytes
|
|||||||
|
|
||||||
uint8_t
|
uint8_t
|
||||||
paletteBlend,
|
paletteBlend,
|
||||||
milliampsPerLed,
|
|
||||||
cctBlending,
|
cctBlending,
|
||||||
getActiveSegmentsNum(void),
|
getActiveSegmentsNum(void),
|
||||||
getFirstSelectedSegId(void),
|
getFirstSelectedSegId(void),
|
||||||
@ -811,8 +807,6 @@ class WS2812FX { // 96 bytes
|
|||||||
inline uint8_t getModeCount() { return _modeCount; }
|
inline uint8_t getModeCount() { return _modeCount; }
|
||||||
|
|
||||||
uint16_t
|
uint16_t
|
||||||
ablMilliampsMax,
|
|
||||||
currentMilliamps,
|
|
||||||
getLengthPhysical(void),
|
getLengthPhysical(void),
|
||||||
getLengthTotal(void), // will include virtual/nonexistent pixels in matrix
|
getLengthTotal(void), // will include virtual/nonexistent pixels in matrix
|
||||||
getFps();
|
getFps();
|
||||||
|
@ -900,8 +900,8 @@ void Segment::refreshLightCapabilities() {
|
|||||||
segStopIdx = stop;
|
segStopIdx = stop;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned b = 0; b < busses.getNumBusses(); b++) {
|
for (unsigned b = 0; b < BusManager::getNumBusses(); b++) {
|
||||||
Bus *bus = busses.getBus(b);
|
Bus *bus = BusManager::getBus(b);
|
||||||
if (bus == nullptr || bus->getLength()==0) break;
|
if (bus == nullptr || bus->getLength()==0) break;
|
||||||
if (!bus->isOk()) continue;
|
if (!bus->isOk()) continue;
|
||||||
if (bus->getStart() >= segStopIdx) continue;
|
if (bus->getStart() >= segStopIdx) continue;
|
||||||
@ -1086,7 +1086,7 @@ void WS2812FX::finalizeInit(void) {
|
|||||||
_hasWhiteChannel = _isOffRefreshRequired = false;
|
_hasWhiteChannel = _isOffRefreshRequired = false;
|
||||||
|
|
||||||
//if busses failed to load, add default (fresh install, FS issue, ...)
|
//if busses failed to load, add default (fresh install, FS issue, ...)
|
||||||
if (busses.getNumBusses() == 0) {
|
if (BusManager::getNumBusses() == 0) {
|
||||||
DEBUG_PRINTLN(F("No busses, init default"));
|
DEBUG_PRINTLN(F("No busses, init default"));
|
||||||
const uint8_t defDataPins[] = {DATA_PINS};
|
const uint8_t defDataPins[] = {DATA_PINS};
|
||||||
const uint16_t defCounts[] = {PIXEL_COUNTS};
|
const uint16_t defCounts[] = {PIXEL_COUNTS};
|
||||||
@ -1099,13 +1099,13 @@ void WS2812FX::finalizeInit(void) {
|
|||||||
uint16_t count = defCounts[(i < defNumCounts) ? i : defNumCounts -1];
|
uint16_t count = defCounts[(i < defNumCounts) ? i : defNumCounts -1];
|
||||||
prevLen += count;
|
prevLen += count;
|
||||||
BusConfig defCfg = BusConfig(DEFAULT_LED_TYPE, defPin, start, count, DEFAULT_LED_COLOR_ORDER, false, 0, RGBW_MODE_MANUAL_ONLY);
|
BusConfig defCfg = BusConfig(DEFAULT_LED_TYPE, defPin, start, count, DEFAULT_LED_COLOR_ORDER, false, 0, RGBW_MODE_MANUAL_ONLY);
|
||||||
if (busses.add(defCfg) == -1) break;
|
if (BusManager::add(defCfg) == -1) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_length = 0;
|
_length = 0;
|
||||||
for (int i=0; i<busses.getNumBusses(); i++) {
|
for (int i=0; i<BusManager::getNumBusses(); i++) {
|
||||||
Bus *bus = busses.getBus(i);
|
Bus *bus = BusManager::getBus(i);
|
||||||
if (bus == nullptr) continue;
|
if (bus == nullptr) continue;
|
||||||
if (bus->getStart() + bus->getLength() > MAX_LEDS) break;
|
if (bus->getStart() + bus->getLength() > MAX_LEDS) break;
|
||||||
//RGBW mode is enabled if at least one of the strips is RGBW
|
//RGBW mode is enabled if at least one of the strips is RGBW
|
||||||
@ -1162,7 +1162,7 @@ void WS2812FX::service() {
|
|||||||
_colors_t[1] = gamma32(seg.currentColor(1));
|
_colors_t[1] = gamma32(seg.currentColor(1));
|
||||||
_colors_t[2] = gamma32(seg.currentColor(2));
|
_colors_t[2] = gamma32(seg.currentColor(2));
|
||||||
seg.currentPalette(_currentPalette, seg.palette); // we need to pass reference
|
seg.currentPalette(_currentPalette, seg.palette); // we need to pass reference
|
||||||
if (!cctFromRgb || correctWB) busses.setSegmentCCT(seg.currentBri(true), correctWB);
|
if (!cctFromRgb || correctWB) BusManager::setSegmentCCT(seg.currentBri(true), correctWB);
|
||||||
// Effect blending
|
// Effect blending
|
||||||
// When two effects are being blended, each may have different segment data, this
|
// When two effects are being blended, each may have different segment data, this
|
||||||
// data needs to be saved first and then restored before running previous mode.
|
// data needs to be saved first and then restored before running previous mode.
|
||||||
@ -1193,7 +1193,7 @@ void WS2812FX::service() {
|
|||||||
_segment_index++;
|
_segment_index++;
|
||||||
}
|
}
|
||||||
_virtualSegmentLength = 0;
|
_virtualSegmentLength = 0;
|
||||||
busses.setSegmentCCT(-1);
|
BusManager::setSegmentCCT(-1);
|
||||||
_isServicing = false;
|
_isServicing = false;
|
||||||
_triggered = false;
|
_triggered = false;
|
||||||
|
|
||||||
@ -1212,13 +1212,13 @@ void WS2812FX::service() {
|
|||||||
void IRAM_ATTR WS2812FX::setPixelColor(unsigned i, uint32_t col) {
|
void IRAM_ATTR WS2812FX::setPixelColor(unsigned i, uint32_t col) {
|
||||||
if (i < customMappingSize) i = customMappingTable[i];
|
if (i < customMappingSize) i = customMappingTable[i];
|
||||||
if (i >= _length) return;
|
if (i >= _length) return;
|
||||||
busses.setPixelColor(i, col);
|
BusManager::setPixelColor(i, col);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t IRAM_ATTR WS2812FX::getPixelColor(uint16_t i) {
|
uint32_t IRAM_ATTR WS2812FX::getPixelColor(uint16_t i) {
|
||||||
if (i < customMappingSize) i = customMappingTable[i];
|
if (i < customMappingSize) i = customMappingTable[i];
|
||||||
if (i >= _length) return 0;
|
if (i >= _length) return 0;
|
||||||
return busses.getPixelColor(i);
|
return BusManager::getPixelColor(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WS2812FX::show(void) {
|
void WS2812FX::show(void) {
|
||||||
@ -1229,7 +1229,7 @@ void WS2812FX::show(void) {
|
|||||||
// some buses send asynchronously and this method will return before
|
// some buses send asynchronously and this method will return before
|
||||||
// all of the data has been sent.
|
// all of the data has been sent.
|
||||||
// See https://github.com/Makuna/NeoPixelBus/wiki/ESP32-NeoMethods#neoesp32rmt-methods
|
// See https://github.com/Makuna/NeoPixelBus/wiki/ESP32-NeoMethods#neoesp32rmt-methods
|
||||||
busses.show();
|
BusManager::show();
|
||||||
|
|
||||||
unsigned long showNow = millis();
|
unsigned long showNow = millis();
|
||||||
size_t diff = showNow - _lastShow;
|
size_t diff = showNow - _lastShow;
|
||||||
@ -1244,7 +1244,7 @@ void WS2812FX::show(void) {
|
|||||||
* On some hardware (ESP32), strip updates are done asynchronously.
|
* On some hardware (ESP32), strip updates are done asynchronously.
|
||||||
*/
|
*/
|
||||||
bool WS2812FX::isUpdating() {
|
bool WS2812FX::isUpdating() {
|
||||||
return !busses.canAllShow();
|
return !BusManager::canAllShow();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1303,7 +1303,7 @@ void WS2812FX::setBrightness(uint8_t b, bool direct) {
|
|||||||
}
|
}
|
||||||
// setting brightness with NeoPixelBusLg has no effect on already painted pixels,
|
// setting brightness with NeoPixelBusLg has no effect on already painted pixels,
|
||||||
// so we need to force an update to existing buffer
|
// so we need to force an update to existing buffer
|
||||||
busses.setBrightness(b);
|
BusManager::setBrightness(b);
|
||||||
if (!direct) {
|
if (!direct) {
|
||||||
unsigned long t = millis();
|
unsigned long t = millis();
|
||||||
if (_segments[0].next_time > t + 22 && t - _lastShow > MIN_SHOW_DELAY) trigger(); //apply brightness change immediately if no refresh soon
|
if (_segments[0].next_time > t + 22 && t - _lastShow > MIN_SHOW_DELAY) trigger(); //apply brightness change immediately if no refresh soon
|
||||||
@ -1359,8 +1359,8 @@ uint16_t WS2812FX::getLengthTotal(void) {
|
|||||||
|
|
||||||
uint16_t WS2812FX::getLengthPhysical(void) {
|
uint16_t WS2812FX::getLengthPhysical(void) {
|
||||||
uint16_t len = 0;
|
uint16_t len = 0;
|
||||||
for (size_t b = 0; b < busses.getNumBusses(); b++) {
|
for (size_t b = 0; b < BusManager::getNumBusses(); b++) {
|
||||||
Bus *bus = busses.getBus(b);
|
Bus *bus = BusManager::getBus(b);
|
||||||
if (bus->getType() >= TYPE_NET_DDP_RGB) continue; //exclude non-physical network busses
|
if (bus->getType() >= TYPE_NET_DDP_RGB) continue; //exclude non-physical network busses
|
||||||
len += bus->getLength();
|
len += bus->getLength();
|
||||||
}
|
}
|
||||||
@ -1371,8 +1371,8 @@ uint16_t WS2812FX::getLengthPhysical(void) {
|
|||||||
//returns if there is an RGBW bus (supports RGB and White, not only white)
|
//returns if there is an RGBW bus (supports RGB and White, not only white)
|
||||||
//not influenced by auto-white mode, also true if white slider does not affect output white channel
|
//not influenced by auto-white mode, also true if white slider does not affect output white channel
|
||||||
bool WS2812FX::hasRGBWBus(void) {
|
bool WS2812FX::hasRGBWBus(void) {
|
||||||
for (size_t b = 0; b < busses.getNumBusses(); b++) {
|
for (size_t b = 0; b < BusManager::getNumBusses(); b++) {
|
||||||
Bus *bus = busses.getBus(b);
|
Bus *bus = BusManager::getBus(b);
|
||||||
if (bus == nullptr || bus->getLength()==0) break;
|
if (bus == nullptr || bus->getLength()==0) break;
|
||||||
if (bus->hasRGB() && bus->hasWhite()) return true;
|
if (bus->hasRGB() && bus->hasWhite()) return true;
|
||||||
}
|
}
|
||||||
@ -1381,8 +1381,8 @@ bool WS2812FX::hasRGBWBus(void) {
|
|||||||
|
|
||||||
bool WS2812FX::hasCCTBus(void) {
|
bool WS2812FX::hasCCTBus(void) {
|
||||||
if (cctFromRgb && !correctWB) return false;
|
if (cctFromRgb && !correctWB) return false;
|
||||||
for (size_t b = 0; b < busses.getNumBusses(); b++) {
|
for (size_t b = 0; b < BusManager::getNumBusses(); b++) {
|
||||||
Bus *bus = busses.getBus(b);
|
Bus *bus = BusManager::getBus(b);
|
||||||
if (bus == nullptr || bus->getLength()==0) break;
|
if (bus == nullptr || bus->getLength()==0) break;
|
||||||
switch (bus->getType()) {
|
switch (bus->getType()) {
|
||||||
case TYPE_ANALOG_5CH:
|
case TYPE_ANALOG_5CH:
|
||||||
@ -1468,8 +1468,8 @@ void WS2812FX::makeAutoSegments(bool forceReset) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (size_t i = s; i < busses.getNumBusses(); i++) {
|
for (size_t i = s; i < BusManager::getNumBusses(); i++) {
|
||||||
Bus* b = busses.getBus(i);
|
Bus* b = BusManager::getBus(i);
|
||||||
|
|
||||||
segStarts[s] = b->getStart();
|
segStarts[s] = b->getStart();
|
||||||
segStops[s] = segStarts[s] + b->getLength();
|
segStops[s] = segStarts[s] + b->getLength();
|
||||||
@ -1558,8 +1558,8 @@ void WS2812FX::fixInvalidSegments() {
|
|||||||
bool WS2812FX::checkSegmentAlignment() {
|
bool WS2812FX::checkSegmentAlignment() {
|
||||||
bool aligned = false;
|
bool aligned = false;
|
||||||
for (segment &seg : _segments) {
|
for (segment &seg : _segments) {
|
||||||
for (unsigned b = 0; b<busses.getNumBusses(); b++) {
|
for (unsigned b = 0; b<BusManager::getNumBusses(); b++) {
|
||||||
Bus *bus = busses.getBus(b);
|
Bus *bus = BusManager::getBus(b);
|
||||||
if (seg.start == bus->getStart() && seg.stop == bus->getStart() + bus->getLength()) aligned = true;
|
if (seg.start == bus->getStart() && seg.stop == bus->getStart() + bus->getLength()) aligned = true;
|
||||||
}
|
}
|
||||||
if (seg.start == 0 && seg.stop == _length) aligned = true;
|
if (seg.start == 0 && seg.stop == _length) aligned = true;
|
||||||
|
@ -125,7 +125,7 @@ BusDigital::BusDigital(BusConfig &bc, uint8_t nr, const ColorOrderMap &com)
|
|||||||
if (bc.type == TYPE_WS2812_1CH_X3) lenToCreate = NUM_ICS_WS2812_1CH_3X(bc.count); // only needs a third of "RGB" LEDs for NeoPixelBus
|
if (bc.type == TYPE_WS2812_1CH_X3) lenToCreate = NUM_ICS_WS2812_1CH_3X(bc.count); // only needs a third of "RGB" LEDs for NeoPixelBus
|
||||||
_busPtr = PolyBus::create(_iType, _pins, lenToCreate + _skip, nr, _frequencykHz);
|
_busPtr = PolyBus::create(_iType, _pins, lenToCreate + _skip, nr, _frequencykHz);
|
||||||
_valid = (_busPtr != nullptr);
|
_valid = (_busPtr != nullptr);
|
||||||
DEBUG_PRINTF("%successfully inited strip %u (len %u) with type %u and pins %u,%u (itype %u)\n", _valid?"S":"Uns", nr, bc.count, bc.type, _pins[0], _pins[1], _iType);
|
DEBUG_PRINTF("%successfully inited strip %u (len %u) with type %u and pins %u,%u (itype %u). mA=%d/%d\n", _valid?"S":"Uns", nr, bc.count, bc.type, _pins[0], _pins[1], _iType, _milliAmpsPerLed, _milliAmpsMax);
|
||||||
}
|
}
|
||||||
|
|
||||||
//fine tune power estimation constants for your setup
|
//fine tune power estimation constants for your setup
|
||||||
@ -150,7 +150,7 @@ uint8_t BusDigital::estimateCurrentAndLimitBri() {
|
|||||||
bool useWackyWS2815PowerModel = false;
|
bool useWackyWS2815PowerModel = false;
|
||||||
byte actualMilliampsPerLed = _milliAmpsPerLed;
|
byte actualMilliampsPerLed = _milliAmpsPerLed;
|
||||||
|
|
||||||
if (_milliAmpsMax < MA_FOR_ESP || actualMilliampsPerLed == 0) { //0 mA per LED and too low numbers turn off calculation
|
if (_milliAmpsMax < MA_FOR_ESP/BusManager::getNumBusses() || actualMilliampsPerLed == 0) { //0 mA per LED and too low numbers turn off calculation
|
||||||
return _bri;
|
return _bri;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,7 +159,12 @@ uint8_t BusDigital::estimateCurrentAndLimitBri() {
|
|||||||
actualMilliampsPerLed = 12; // from testing an actual strip
|
actualMilliampsPerLed = 12; // from testing an actual strip
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t powerBudget = (_milliAmpsMax - MA_FOR_ESP); //100mA for ESP power
|
size_t powerBudget = (_milliAmpsMax - MA_FOR_ESP/BusManager::getNumBusses()); //80/120mA for ESP power
|
||||||
|
if (powerBudget > getLength()) { //each LED uses about 1mA in standby, exclude that from power budget
|
||||||
|
powerBudget -= getLength();
|
||||||
|
} else {
|
||||||
|
powerBudget = 0;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t busPowerSum = 0;
|
uint32_t busPowerSum = 0;
|
||||||
for (unsigned i = 0; i < getLength(); i++) { //sum up the usage of each LED
|
for (unsigned i = 0; i < getLength(); i++) { //sum up the usage of each LED
|
||||||
@ -178,29 +183,26 @@ uint8_t BusDigital::estimateCurrentAndLimitBri() {
|
|||||||
busPowerSum >>= 2; //same as /= 4
|
busPowerSum >>= 2; //same as /= 4
|
||||||
}
|
}
|
||||||
|
|
||||||
if (powerBudget > getLength()) { //each LED uses about 1mA in standby, exclude that from power budget
|
|
||||||
powerBudget -= getLength();
|
|
||||||
} else {
|
|
||||||
powerBudget = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// powerSum has all the values of channels summed (max would be getLength()*765 as white is excluded) so convert to milliAmps
|
// powerSum has all the values of channels summed (max would be getLength()*765 as white is excluded) so convert to milliAmps
|
||||||
busPowerSum = (busPowerSum * actualMilliampsPerLed) / 765;
|
busPowerSum = (busPowerSum * actualMilliampsPerLed) / 765;
|
||||||
|
_milliAmpsTotal = busPowerSum * _bri / 255;
|
||||||
|
|
||||||
uint8_t newBri = _bri;
|
uint8_t newBri = _bri;
|
||||||
if (busPowerSum * _bri / 255 > powerBudget) { //scale brightness down to stay in current limit
|
if (busPowerSum * _bri / 255 > powerBudget) { //scale brightness down to stay in current limit
|
||||||
float scale = (float)(powerBudget * 255) / (float)(busPowerSum * _bri);
|
float scale = (float)(powerBudget * 255) / (float)(busPowerSum * _bri);
|
||||||
uint16_t scaleI = scale * 255;
|
if (scale >= 1.0f) return _bri;
|
||||||
uint8_t scaleB = (scaleI > 255) ? 255 : scaleI;
|
_milliAmpsTotal = ceilf((float)_milliAmpsTotal * scale);
|
||||||
|
uint8_t scaleB = min((int)(scale * 255), 255);
|
||||||
newBri = unsigned(_bri * scaleB) / 256 + 1;
|
newBri = unsigned(_bri * scaleB) / 256 + 1;
|
||||||
}
|
}
|
||||||
return newBri;
|
return newBri;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BusDigital::show() {
|
void BusDigital::show() {
|
||||||
|
_milliAmpsTotal = 0;
|
||||||
if (!_valid) return;
|
if (!_valid) return;
|
||||||
|
|
||||||
uint8_t newBri = estimateCurrentAndLimitBri();
|
uint8_t newBri = estimateCurrentAndLimitBri(); // will fill _milliAmpsTotal
|
||||||
if (newBri < _bri) PolyBus::setBrightness(_busPtr, _iType, newBri); // limit brightness to stay within current limits
|
if (newBri < _bri) PolyBus::setBrightness(_busPtr, _iType, newBri); // limit brightness to stay within current limits
|
||||||
|
|
||||||
if (_data) { // use _buffering this causes ~20% FPS drop
|
if (_data) { // use _buffering this causes ~20% FPS drop
|
||||||
@ -646,9 +648,12 @@ void BusManager::removeAll() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BusManager::show() {
|
void BusManager::show() {
|
||||||
|
_milliAmpsUsed = 0;
|
||||||
for (unsigned i = 0; i < numBusses; i++) {
|
for (unsigned i = 0; i < numBusses; i++) {
|
||||||
busses[i]->show();
|
busses[i]->show();
|
||||||
|
_milliAmpsUsed += busses[i]->getUsedCurrent();
|
||||||
}
|
}
|
||||||
|
if (_milliAmpsUsed) _milliAmpsUsed += MA_FOR_ESP;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BusManager::setStatusPixel(uint32_t c) {
|
void BusManager::setStatusPixel(uint32_t c) {
|
||||||
@ -714,3 +719,11 @@ uint16_t BusManager::getTotalLength() {
|
|||||||
int16_t Bus::_cct = -1;
|
int16_t Bus::_cct = -1;
|
||||||
uint8_t Bus::_cctBlend = 0;
|
uint8_t Bus::_cctBlend = 0;
|
||||||
uint8_t Bus::_gAWM = 255;
|
uint8_t Bus::_gAWM = 255;
|
||||||
|
|
||||||
|
uint16_t BusDigital::_milliAmpsTotal = 0;
|
||||||
|
|
||||||
|
uint8_t BusManager::numBusses = 0;
|
||||||
|
Bus* BusManager::busses[WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES];
|
||||||
|
ColorOrderMap BusManager::colorOrderMap = {};
|
||||||
|
uint16_t BusManager::_milliAmpsUsed = 0;
|
||||||
|
uint16_t BusManager::_milliAmpsMax = ABL_MILLIAMPS_DEFAULT;
|
@ -137,6 +137,7 @@ class Bus {
|
|||||||
virtual uint8_t skippedLeds() { return 0; }
|
virtual uint8_t skippedLeds() { return 0; }
|
||||||
virtual uint16_t getFrequency() { return 0U; }
|
virtual uint16_t getFrequency() { return 0U; }
|
||||||
virtual uint16_t getLEDCurrent() { return 0; }
|
virtual uint16_t getLEDCurrent() { return 0; }
|
||||||
|
virtual uint16_t getUsedCurrent() { return 0; }
|
||||||
virtual uint16_t getMaxCurrent() { return 0; }
|
virtual uint16_t getMaxCurrent() { return 0; }
|
||||||
inline void setReversed(bool reversed) { _reversed = reversed; }
|
inline void setReversed(bool reversed) { _reversed = reversed; }
|
||||||
inline uint16_t getStart() { return _start; }
|
inline uint16_t getStart() { return _start; }
|
||||||
@ -219,6 +220,7 @@ class BusDigital : public Bus {
|
|||||||
uint16_t getFrequency() { return _frequencykHz; }
|
uint16_t getFrequency() { return _frequencykHz; }
|
||||||
uint8_t estimateCurrentAndLimitBri();
|
uint8_t estimateCurrentAndLimitBri();
|
||||||
uint16_t getLEDCurrent() { return _milliAmpsPerLed; }
|
uint16_t getLEDCurrent() { return _milliAmpsPerLed; }
|
||||||
|
uint16_t getUsedCurrent() { return _milliAmpsTotal; }
|
||||||
uint16_t getMaxCurrent() { return _milliAmpsMax; }
|
uint16_t getMaxCurrent() { return _milliAmpsMax; }
|
||||||
void reinit();
|
void reinit();
|
||||||
void cleanup();
|
void cleanup();
|
||||||
@ -233,7 +235,8 @@ class BusDigital : public Bus {
|
|||||||
uint16_t _milliAmpsMax;
|
uint16_t _milliAmpsMax;
|
||||||
void * _busPtr;
|
void * _busPtr;
|
||||||
const ColorOrderMap &_colorOrderMap;
|
const ColorOrderMap &_colorOrderMap;
|
||||||
//bool _buffering; // temporary until we figure out why comparison "_data" causes severe FPS drop
|
|
||||||
|
static uint16_t _milliAmpsTotal; // is overwitten/recalculated on each show()
|
||||||
|
|
||||||
inline uint32_t restoreColorLossy(uint32_t c, uint8_t restoreBri) {
|
inline uint32_t restoreColorLossy(uint32_t c, uint8_t restoreBri) {
|
||||||
if (restoreBri < 255) {
|
if (restoreBri < 255) {
|
||||||
@ -314,39 +317,44 @@ class BusNetwork : public Bus {
|
|||||||
|
|
||||||
class BusManager {
|
class BusManager {
|
||||||
public:
|
public:
|
||||||
BusManager() : numBusses(0) {};
|
BusManager() {};
|
||||||
|
|
||||||
//utility to get the approx. memory usage of a given BusConfig
|
//utility to get the approx. memory usage of a given BusConfig
|
||||||
static uint32_t memUsage(BusConfig &bc);
|
static uint32_t memUsage(BusConfig &bc);
|
||||||
|
static uint16_t currentMilliamps(void) { return _milliAmpsUsed; }
|
||||||
|
static uint16_t ablMilliampsMax(void) { return _milliAmpsMax; }
|
||||||
|
|
||||||
int add(BusConfig &bc);
|
static int add(BusConfig &bc);
|
||||||
|
|
||||||
//do not call this method from system context (network callback)
|
//do not call this method from system context (network callback)
|
||||||
void removeAll();
|
static void removeAll();
|
||||||
|
|
||||||
void show();
|
static void show();
|
||||||
bool canAllShow();
|
static bool canAllShow();
|
||||||
void setStatusPixel(uint32_t c);
|
static void setStatusPixel(uint32_t c);
|
||||||
void setPixelColor(uint16_t pix, uint32_t c);
|
static void setPixelColor(uint16_t pix, uint32_t c);
|
||||||
void setBrightness(uint8_t b);
|
static void setBrightness(uint8_t b);
|
||||||
void setSegmentCCT(int16_t cct, bool allowWBCorrection = false);
|
static void setSegmentCCT(int16_t cct, bool allowWBCorrection = false);
|
||||||
uint32_t getPixelColor(uint16_t pix);
|
static void setMilliampsMax(uint16_t max) { _milliAmpsMax = max;}
|
||||||
|
static uint32_t getPixelColor(uint16_t pix);
|
||||||
|
|
||||||
Bus* getBus(uint8_t busNr);
|
static Bus* getBus(uint8_t busNr);
|
||||||
|
|
||||||
//semi-duplicate of strip.getLengthTotal() (though that just returns strip._length, calculated in finalizeInit())
|
//semi-duplicate of strip.getLengthTotal() (though that just returns strip._length, calculated in finalizeInit())
|
||||||
uint16_t getTotalLength();
|
static uint16_t getTotalLength();
|
||||||
inline uint8_t getNumBusses() const { return numBusses; }
|
static uint8_t getNumBusses() { return numBusses; }
|
||||||
|
|
||||||
inline void updateColorOrderMap(const ColorOrderMap &com) { memcpy(&colorOrderMap, &com, sizeof(ColorOrderMap)); }
|
static void updateColorOrderMap(const ColorOrderMap &com) { memcpy(&colorOrderMap, &com, sizeof(ColorOrderMap)); }
|
||||||
inline const ColorOrderMap& getColorOrderMap() const { return colorOrderMap; }
|
static const ColorOrderMap& getColorOrderMap() { return colorOrderMap; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t numBusses;
|
static uint8_t numBusses;
|
||||||
Bus* busses[WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES];
|
static Bus* busses[WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES];
|
||||||
ColorOrderMap colorOrderMap;
|
static ColorOrderMap colorOrderMap;
|
||||||
|
static uint16_t _milliAmpsUsed;
|
||||||
|
static uint16_t _milliAmpsMax;
|
||||||
|
|
||||||
inline uint8_t getNumVirtualBusses() {
|
static uint8_t getNumVirtualBusses() {
|
||||||
int j = 0;
|
int j = 0;
|
||||||
for (int i=0; i<numBusses; i++) if (busses[i]->getType() >= TYPE_NET_DDP_RGB && busses[i]->getType() < 96) j++;
|
for (int i=0; i<numBusses; i++) if (busses[i]->getType() >= TYPE_NET_DDP_RGB && busses[i]->getType() < 96) j++;
|
||||||
return j;
|
return j;
|
||||||
|
@ -347,10 +347,10 @@ void handleButton()
|
|||||||
void esp32RMTInvertIdle()
|
void esp32RMTInvertIdle()
|
||||||
{
|
{
|
||||||
bool idle_out;
|
bool idle_out;
|
||||||
for (uint8_t u = 0; u < busses.getNumBusses(); u++)
|
for (uint8_t u = 0; u < BusManager::getNumBusses(); u++)
|
||||||
{
|
{
|
||||||
if (u > 7) return; // only 8 RMT channels, TODO: ESP32 variants have less RMT channels
|
if (u > 7) return; // only 8 RMT channels, TODO: ESP32 variants have less RMT channels
|
||||||
Bus *bus = busses.getBus(u);
|
Bus *bus = BusManager::getBus(u);
|
||||||
if (!bus || bus->getLength()==0 || !IS_DIGITAL(bus->getType()) || IS_2PIN(bus->getType())) continue;
|
if (!bus || bus->getLength()==0 || !IS_DIGITAL(bus->getType()) || IS_2PIN(bus->getType())) continue;
|
||||||
//assumes that bus number to rmt channel mapping stays 1:1
|
//assumes that bus number to rmt channel mapping stays 1:1
|
||||||
rmt_channel_t ch = static_cast<rmt_channel_t>(u);
|
rmt_channel_t ch = static_cast<rmt_channel_t>(u);
|
||||||
|
@ -87,8 +87,8 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
JsonObject hw_led = hw["led"];
|
JsonObject hw_led = hw["led"];
|
||||||
|
|
||||||
uint16_t total = hw_led[F("total")] | strip.getLengthTotal();
|
uint16_t total = hw_led[F("total")] | strip.getLengthTotal();
|
||||||
CJSON(strip.ablMilliampsMax, hw_led[F("maxpwr")]);
|
uint16_t ablMilliampsMax = hw_led[F("maxpwr")] | BusManager::ablMilliampsMax();
|
||||||
CJSON(strip.milliampsPerLed, hw_led[F("ledma")]); // no longer used
|
BusManager::setMilliampsMax(ablMilliampsMax);
|
||||||
Bus::setGlobalAWMode(hw_led[F("rgbwm")] | AW_GLOBAL_DISABLED);
|
Bus::setGlobalAWMode(hw_led[F("rgbwm")] | AW_GLOBAL_DISABLED);
|
||||||
CJSON(correctWB, hw_led["cct"]);
|
CJSON(correctWB, hw_led["cct"]);
|
||||||
CJSON(cctFromRgb, hw_led[F("cr")]);
|
CJSON(cctFromRgb, hw_led[F("cr")]);
|
||||||
@ -138,7 +138,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
|
|
||||||
if (fromFS || !ins.isNull()) {
|
if (fromFS || !ins.isNull()) {
|
||||||
uint8_t s = 0; // bus iterator
|
uint8_t s = 0; // bus iterator
|
||||||
if (fromFS) busses.removeAll(); // can't safely manipulate busses directly in network callback
|
if (fromFS) BusManager::removeAll(); // can't safely manipulate busses directly in network callback
|
||||||
uint32_t mem = 0, globalBufMem = 0;
|
uint32_t mem = 0, globalBufMem = 0;
|
||||||
uint16_t maxlen = 0;
|
uint16_t maxlen = 0;
|
||||||
bool busesChanged = false;
|
bool busesChanged = false;
|
||||||
@ -164,8 +164,8 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
bool refresh = elm["ref"] | false;
|
bool refresh = elm["ref"] | false;
|
||||||
uint16_t freqkHz = elm[F("freq")] | 0; // will be in kHz for DotStar and Hz for PWM (not yet implemented fully)
|
uint16_t freqkHz = elm[F("freq")] | 0; // will be in kHz for DotStar and Hz for PWM (not yet implemented fully)
|
||||||
uint8_t AWmode = elm[F("rgbwm")] | RGBW_MODE_MANUAL_ONLY;
|
uint8_t AWmode = elm[F("rgbwm")] | RGBW_MODE_MANUAL_ONLY;
|
||||||
uint8_t maPerLed = elm[F("ledma")] | strip.milliampsPerLed; // replace with 55 when removing strip.milliampsPerLed
|
uint8_t maPerLed = elm[F("ledma")] | 55;
|
||||||
uint16_t maMax = elm[F("maxpwr")] | (strip.ablMilliampsMax * length) / total; // rough (incorrect?) per strip ABL calculation when no config exists
|
uint16_t maMax = elm[F("maxpwr")] | (ablMilliampsMax * length) / total; // rough (incorrect?) per strip ABL calculation when no config exists
|
||||||
// To disable brightness limiter we either set output max current to 0 or single LED current to 0 (we choose output max current)
|
// To disable brightness limiter we either set output max current to 0 or single LED current to 0 (we choose output max current)
|
||||||
if ((ledType > TYPE_TM1814 && ledType < TYPE_WS2801) || ledType >= TYPE_NET_DDP_RGB) { // analog and virtual
|
if ((ledType > TYPE_TM1814 && ledType < TYPE_WS2801) || ledType >= TYPE_NET_DDP_RGB) { // analog and virtual
|
||||||
maPerLed = 0;
|
maPerLed = 0;
|
||||||
@ -179,7 +179,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
maxlen = start + length;
|
maxlen = start + length;
|
||||||
globalBufMem = maxlen * 4;
|
globalBufMem = maxlen * 4;
|
||||||
}
|
}
|
||||||
if (mem + globalBufMem <= MAX_LED_MEMORY) if (busses.add(bc) == -1) break; // finalization will be done in WLED::beginStrip()
|
if (mem + globalBufMem <= MAX_LED_MEMORY) if (BusManager::add(bc) == -1) break; // finalization will be done in WLED::beginStrip()
|
||||||
} else {
|
} else {
|
||||||
if (busConfigs[s] != nullptr) delete busConfigs[s];
|
if (busConfigs[s] != nullptr) delete busConfigs[s];
|
||||||
busConfigs[s] = new BusConfig(ledType, pins, start, length, colorOrder, reversed, skipFirst, AWmode, freqkHz, useGlobalLedBuffer, maPerLed, maMax);
|
busConfigs[s] = new BusConfig(ledType, pins, start, length, colorOrder, reversed, skipFirst, AWmode, freqkHz, useGlobalLedBuffer, maPerLed, maMax);
|
||||||
@ -190,7 +190,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
doInitBusses = busesChanged;
|
doInitBusses = busesChanged;
|
||||||
// finalization done in beginStrip()
|
// finalization done in beginStrip()
|
||||||
}
|
}
|
||||||
if (hw_led["rev"]) busses.getBus(0)->setReversed(true); //set 0.11 global reversed setting for first bus
|
if (hw_led["rev"]) BusManager::getBus(0)->setReversed(true); //set 0.11 global reversed setting for first bus
|
||||||
|
|
||||||
// read color order map configuration
|
// read color order map configuration
|
||||||
JsonArray hw_com = hw[F("com")];
|
JsonArray hw_com = hw[F("com")];
|
||||||
@ -205,7 +205,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
com.add(start, len, colorOrder);
|
com.add(start, len, colorOrder);
|
||||||
s++;
|
s++;
|
||||||
}
|
}
|
||||||
busses.updateColorOrderMap(com);
|
BusManager::updateColorOrderMap(com);
|
||||||
}
|
}
|
||||||
|
|
||||||
// read multiple button configuration
|
// read multiple button configuration
|
||||||
@ -722,8 +722,8 @@ void serializeConfig() {
|
|||||||
|
|
||||||
JsonObject hw_led = hw.createNestedObject("led");
|
JsonObject hw_led = hw.createNestedObject("led");
|
||||||
hw_led[F("total")] = strip.getLengthTotal(); //provided for compatibility on downgrade and per-output ABL
|
hw_led[F("total")] = strip.getLengthTotal(); //provided for compatibility on downgrade and per-output ABL
|
||||||
hw_led[F("maxpwr")] = strip.ablMilliampsMax;
|
hw_led[F("maxpwr")] = BusManager::ablMilliampsMax();
|
||||||
hw_led[F("ledma")] = strip.milliampsPerLed; // no longer used
|
hw_led[F("ledma")] = 0; // no longer used
|
||||||
hw_led["cct"] = correctWB;
|
hw_led["cct"] = correctWB;
|
||||||
hw_led[F("cr")] = cctFromRgb;
|
hw_led[F("cr")] = cctFromRgb;
|
||||||
hw_led[F("cb")] = strip.cctBlending;
|
hw_led[F("cb")] = strip.cctBlending;
|
||||||
@ -753,8 +753,8 @@ void serializeConfig() {
|
|||||||
|
|
||||||
JsonArray hw_led_ins = hw_led.createNestedArray("ins");
|
JsonArray hw_led_ins = hw_led.createNestedArray("ins");
|
||||||
|
|
||||||
for (uint8_t s = 0; s < busses.getNumBusses(); s++) {
|
for (uint8_t s = 0; s < BusManager::getNumBusses(); s++) {
|
||||||
Bus *bus = busses.getBus(s);
|
Bus *bus = BusManager::getBus(s);
|
||||||
if (!bus || bus->getLength()==0) break;
|
if (!bus || bus->getLength()==0) break;
|
||||||
JsonObject ins = hw_led_ins.createNestedObject();
|
JsonObject ins = hw_led_ins.createNestedObject();
|
||||||
ins["start"] = bus->getStart();
|
ins["start"] = bus->getStart();
|
||||||
@ -775,7 +775,7 @@ void serializeConfig() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
JsonArray hw_com = hw.createNestedArray(F("com"));
|
JsonArray hw_com = hw.createNestedArray(F("com"));
|
||||||
const ColorOrderMap& com = busses.getColorOrderMap();
|
const ColorOrderMap& com = BusManager::getColorOrderMap();
|
||||||
for (uint8_t s = 0; s < com.count(); s++) {
|
for (uint8_t s = 0; s < com.count(); s++) {
|
||||||
const ColorOrderMapEntry *entry = com.get(s);
|
const ColorOrderMapEntry *entry = com.get(s);
|
||||||
if (!entry) break;
|
if (!entry) break;
|
||||||
|
@ -107,30 +107,36 @@
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (!pinsOK()) {e.stopPropagation();return false;} // Prevent form submission and contact with server
|
if (!pinsOK()) {e.stopPropagation();return false;} // Prevent form submission and contact with server
|
||||||
if (bquot > 100) {var msg = "Too many LEDs for me to handle!"; if (maxM < 10000) msg += "\n\rConsider using an ESP32."; alert(msg);}
|
if (bquot > 100) {var msg = "Too many LEDs for me to handle!"; if (maxM < 10000) msg += "\n\rConsider using an ESP32."; alert(msg);}
|
||||||
|
if (d.Sf.PPL.checked) d.Sf.MA.value = 0; // submit 0 as ABL (PPL will handle it)
|
||||||
if (d.Sf.checkValidity()) d.Sf.submit(); //https://stackoverflow.com/q/37323914
|
if (d.Sf.checkValidity()) d.Sf.submit(); //https://stackoverflow.com/q/37323914
|
||||||
}
|
}
|
||||||
function enABL()
|
function enABL()
|
||||||
{
|
{
|
||||||
var en = d.Sf["ABL"].checked;
|
var en = d.Sf.ABL.checked;
|
||||||
d.Sf["MA"].min = en ? 250 : 0;
|
|
||||||
gId('abl').style.display = (en) ? 'inline':'none';
|
gId('abl').style.display = (en) ? 'inline':'none';
|
||||||
gId('psu2').style.display = (en) ? 'inline':'none';
|
gId('psu2').style.display = (en) ? 'inline':'none';
|
||||||
if (!en) d.Sf["PPL"].checked = false;
|
if (!en) d.Sf.PPL.checked = false;
|
||||||
enPPL();
|
enPPL();
|
||||||
UI();
|
UI();
|
||||||
}
|
}
|
||||||
function enPPL()
|
function enPPL()
|
||||||
{
|
{
|
||||||
const abl = d.Sf["ABL"].checked;
|
const abl = d.Sf.ABL.checked;
|
||||||
const en = d.Sf["PPL"].checked;
|
const ppl = d.Sf.PPL.checked;
|
||||||
d.Sf["MA"].readonly = en;
|
let sumMA = 0;
|
||||||
gId("ppldis").style.display = en ? 'inline' : 'none';
|
d.Sf.MA.readonly = ppl;
|
||||||
|
d.Sf.MA.min = abl && !ppl ? 250 : 0;
|
||||||
|
gId("psuMA").style.display = ppl ? 'none' : 'inline';
|
||||||
|
gId("ppldis").style.display = ppl ? 'inline' : 'none';
|
||||||
|
// set PPL minimum value and clear actual PPL limit if ABL disabled
|
||||||
d.Sf.querySelectorAll("#mLC input[name^=MA]").forEach((i,n)=>{
|
d.Sf.querySelectorAll("#mLC input[name^=MA]").forEach((i,n)=>{
|
||||||
gId("PSU"+n).style.display = en ? "inline" : "none";
|
gId("PSU"+n).style.display = ppl ? "inline" : "none";
|
||||||
const t = parseInt(d.Sf["LT"+n].value); // LED type SELECT
|
const t = parseInt(d.Sf["LT"+n].value); // LED type SELECT
|
||||||
i.min = en && !((t >= 80 && t < 96) || (t >= 40 && t < 48)) ? 250 : 0;
|
i.min = ppl && !((t >= 80 && t < 96) || (t >= 40 && t < 48)) ? 250 : 0;
|
||||||
if (!abl) i.value = 0;
|
if (!abl) i.value = 0;
|
||||||
|
else if (ppl) sumMA += parseInt(i.value,10);
|
||||||
});
|
});
|
||||||
|
if (ppl) d.Sf.MA.value = sumMA; // populate UI ABL value if PPL used
|
||||||
}
|
}
|
||||||
function enLA(s,n)
|
function enLA(s,n)
|
||||||
{
|
{
|
||||||
@ -141,10 +147,11 @@
|
|||||||
}
|
}
|
||||||
function setABL()
|
function setABL()
|
||||||
{
|
{
|
||||||
d.Sf["ABL"].checked = false;
|
console.log(d.Sf.MA.value);
|
||||||
|
d.Sf.ABL.checked = parseInt(d.Sf.MA.value) > 0;
|
||||||
// check if ABL is enabled (max mA entered per output)
|
// check if ABL is enabled (max mA entered per output)
|
||||||
d.Sf.querySelectorAll("#mLC input[name^=MA]").forEach((i,n)=>{
|
d.Sf.querySelectorAll("#mLC input[name^=MA]").forEach((i,n)=>{
|
||||||
if (parseInt(i.value) > 0) d.Sf["ABL"].checked = true;
|
if (parseInt(i.value) > 0) d.Sf.ABL.checked = true;
|
||||||
});
|
});
|
||||||
// select appropriate LED current
|
// select appropriate LED current
|
||||||
d.Sf.querySelectorAll("#mLC select[name^=LAsel]").forEach((sel,n)=>{
|
d.Sf.querySelectorAll("#mLC select[name^=LAsel]").forEach((sel,n)=>{
|
||||||
@ -190,8 +197,8 @@
|
|||||||
let isRGBW = false, gRGBW = false, memu = 0;
|
let isRGBW = false, gRGBW = false, memu = 0;
|
||||||
let sumMA = 0, busMA = 0;
|
let sumMA = 0, busMA = 0;
|
||||||
let sLC = 0, sPC = 0, sDI = 0, maxLC = 0;
|
let sLC = 0, sPC = 0, sDI = 0, maxLC = 0;
|
||||||
const ablEN = d.Sf["ABL"].checked;
|
const ablEN = d.Sf.ABL.checked;
|
||||||
const pplEN = d.Sf["PPL"].checked;
|
const pplEN = d.Sf.PPL.checked;
|
||||||
|
|
||||||
// enable/disable LED fields
|
// enable/disable LED fields
|
||||||
d.Sf.querySelectorAll("#mLC select[name^=LT]").forEach((s)=>{
|
d.Sf.querySelectorAll("#mLC select[name^=LT]").forEach((s)=>{
|
||||||
@ -244,7 +251,7 @@
|
|||||||
gId("rev"+n).innerHTML = (t >= 40 && t < 48) ? "Inverted output":"Reversed (rotated 180°)"; // change reverse text for analog
|
gId("rev"+n).innerHTML = (t >= 40 && t < 48) ? "Inverted output":"Reversed (rotated 180°)"; // change reverse text for analog
|
||||||
gId("psd"+n).innerHTML = (t >= 40 && t < 48) ? "Index:":"Start:"; // change analog start description
|
gId("psd"+n).innerHTML = (t >= 40 && t < 48) ? "Index:":"Start:"; // change analog start description
|
||||||
if (ablEN && pplEN && !((t >= 80 && t < 96) || (t >= 40 && t < 48))) {
|
if (ablEN && pplEN && !((t >= 80 && t < 96) || (t >= 40 && t < 48))) {
|
||||||
sumMA += parseInt(d.Sf["MA"+n].value);
|
sumMA += parseInt(d.Sf["MA"+n].value); // summarize PPL ABL limit (fields)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// display global white channel overrides
|
// display global white channel overrides
|
||||||
@ -269,11 +276,12 @@
|
|||||||
if (s+c > sLC) sLC = s+c; //update total count
|
if (s+c > sLC) sLC = s+c; //update total count
|
||||||
if (c > maxLC) maxLC = c; //max per output
|
if (c > maxLC) maxLC = c; //max per output
|
||||||
if (t < 80) sPC += c; //virtual out busses do not count towards physical LEDs
|
if (t < 80) sPC += c; //virtual out busses do not count towards physical LEDs
|
||||||
if (!((t >= 80 && t < 96) || (t >= 40 && t < 48))) sDI += c;
|
//if (!((t >= 80 && t < 96) || (t >= 40 && t < 48))) sDI += c;
|
||||||
if (!((t >= 80 && t < 96) || (t >= 40 && t < 48))) {
|
if (!((t >= 80 && t < 96) || (t >= 40 && t < 48))) {
|
||||||
|
sDI += c; // summarize digital LED count
|
||||||
let maPL = parseInt(d.Sf["LA"+n].value);
|
let maPL = parseInt(d.Sf["LA"+n].value);
|
||||||
if (maPL == 255) maPL = 12;
|
if (maPL == 255) maPL = 12;
|
||||||
busMA += maPL*c;
|
busMA += maPL*c; // summarize maximum bus current (calculated)
|
||||||
}
|
}
|
||||||
} // increase led count
|
} // increase led count
|
||||||
return;
|
return;
|
||||||
@ -316,14 +324,18 @@
|
|||||||
else LC.style.color = d.ro_gpio.some((e)=>e==parseInt(LC.value)) ? "orange" : "#fff";
|
else LC.style.color = d.ro_gpio.some((e)=>e==parseInt(LC.value)) ? "orange" : "#fff";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// distribute ABL current if not using PPL, otherwise sumMA contains summarized ABL limit
|
||||||
d.Sf.querySelectorAll("#mLC input[name^=LC]").forEach((s,n)=>{
|
d.Sf.querySelectorAll("#mLC input[name^=LC]").forEach((s,n)=>{
|
||||||
let c = parseInt(s.value,10); //get LED count
|
let c = parseInt(s.value,10); //get LED count
|
||||||
let t = parseInt(d.Sf["LT"+n].value);
|
let t = parseInt(d.Sf["LT"+n].value); //get LED type
|
||||||
if (ablEN) {
|
if (!ablEN || (t >= 80 && t < 96) || (t >= 40 && t < 48)) {
|
||||||
let v = Math.round(parseInt(d.Sf["MA"].value,10)*c/sDI);
|
// virtual and analog LEDs have no limiter
|
||||||
if (!pplEN && !((t >= 80 && t < 96) || (t >= 40 && t < 48))) d.Sf["MA"+n].value = v;
|
d.Sf["MA"+n].value = 0;
|
||||||
} else d.Sf["MA"+n].value = 0;
|
return;
|
||||||
|
}
|
||||||
|
if (!pplEN) d.Sf["MA"+n].value = Math.round(parseInt(d.Sf.MA.value,10)*c/sDI);
|
||||||
});
|
});
|
||||||
|
if (pplEN) d.Sf.MA.value = sumMA; // update global ABL if using PPL
|
||||||
// update total led count
|
// update total led count
|
||||||
gId("lc").textContent = sLC;
|
gId("lc").textContent = sLC;
|
||||||
gId("pc").textContent = (sLC == sPC) ? "":"(" + sPC + " physical)";
|
gId("pc").textContent = (sLC == sPC) ? "":"(" + sPC + " physical)";
|
||||||
@ -336,7 +348,6 @@
|
|||||||
gId('ledwarning').style.color = (maxLC > Math.max(maxPB,800) || bquot > 100) ? 'red':'orange';
|
gId('ledwarning').style.color = (maxLC > Math.max(maxPB,800) || bquot > 100) ? 'red':'orange';
|
||||||
gId('wreason').innerHTML = (bquot > 80) ? "80% of max. LED memory" +(bquot>100 ? ` (<b>ERROR: Using over ${maxM}B!</b>)` : "") : "800 LEDs per output";
|
gId('wreason').innerHTML = (bquot > 80) ? "80% of max. LED memory" +(bquot>100 ? ` (<b>ERROR: Using over ${maxM}B!</b>)` : "") : "800 LEDs per output";
|
||||||
// calculate power
|
// calculate power
|
||||||
if (pplEN) d.Sf.MA.value = sumMA;
|
|
||||||
gId('ampwarning').style.display = (parseInt(d.Sf.MA.value,10) > 7200) ? 'inline':'none';
|
gId('ampwarning').style.display = (parseInt(d.Sf.MA.value,10) > 7200) ? 'inline':'none';
|
||||||
var val = Math.ceil((100 + busMA)/500)/2;
|
var val = Math.ceil((100 + busMA)/500)/2;
|
||||||
val = (val > 5) ? Math.ceil(val) : val;
|
val = (val > 5) ? Math.ceil(val) : val;
|
||||||
@ -409,7 +420,7 @@ mA/LED: <select name="LAsel${i}" onchange="enLA(this,${i});UI();">
|
|||||||
<option value="0">Custom</option>
|
<option value="0">Custom</option>
|
||||||
</select><br>
|
</select><br>
|
||||||
<div id="LAdis${i}" style="display: none;">max. mA/LED: <input name="LA${i}" type="number" min="1" max="254" oninput="UI()"> mA<br></div>
|
<div id="LAdis${i}" style="display: none;">max. mA/LED: <input name="LA${i}" type="number" min="1" max="254" oninput="UI()"> mA<br></div>
|
||||||
<div id="PSU${i}">PSU: <input name="MA${i}" type="number" class="xl" min="250" max="65000" oninput="UI()"> mA<br></div>
|
<div id="PSU${i}">PSU: <input name="MA${i}" type="number" class="xl" min="250" max="65000" oninput="UI()" value="250"> mA<br></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="co${i}" style="display:inline">Color Order:
|
<div id="co${i}" style="display:inline">Color Order:
|
||||||
<select name="CO${i}">
|
<select name="CO${i}">
|
||||||
@ -445,7 +456,10 @@ mA/LED: <select name="LAsel${i}" onchange="enLA(this,${i});UI();">
|
|||||||
gId("+").style.display = (i<maxB+maxV-1) ? "inline":"none";
|
gId("+").style.display = (i<maxB+maxV-1) ? "inline":"none";
|
||||||
gId("-").style.display = (i>0) ? "inline":"none";
|
gId("-").style.display = (i>0) ? "inline":"none";
|
||||||
|
|
||||||
if (!init) UI();
|
if (!init) {
|
||||||
|
enPPL();
|
||||||
|
UI();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addCOM(start=0,len=1,co=0) {
|
function addCOM(start=0,len=1,co=0) {
|
||||||
@ -750,7 +764,7 @@ Length: <input type="number" name="XC${i}" id="xc${i}" class="l" min="1" max="65
|
|||||||
<i>Automatically limits brightness to stay close to the limit.<br>
|
<i>Automatically limits brightness to stay close to the limit.<br>
|
||||||
Keep at <1A if poweing LEDs directly from the ESP 5V pin!<br>
|
Keep at <1A if poweing LEDs directly from the ESP 5V pin!<br>
|
||||||
Analog (PWM) and virtual LEDs cannot use automatic brightness limiter.<br></i>
|
Analog (PWM) and virtual LEDs cannot use automatic brightness limiter.<br></i>
|
||||||
Maximum PSU Current: <input name="MA" type="number" class="xl" min="250" max="65000" oninput="UI()" required> mA<br>
|
<div id="psuMA">Maximum PSU Current: <input name="MA" type="number" class="xl" min="250" max="65000" oninput="UI()" required> mA<br></div>
|
||||||
Use per-output limiter: <input type="checkbox" name="PPL" onchange="enPPL()"><br>
|
Use per-output limiter: <input type="checkbox" name="PPL" onchange="enPPL()"><br>
|
||||||
<div id="ppldis" style="display:none;">
|
<div id="ppldis" style="display:none;">
|
||||||
<i>Make sure you enter correct values in each LED output.<br>
|
<i>Make sure you enter correct values in each LED output.<br>
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -605,9 +605,9 @@ void serializeInfo(JsonObject root)
|
|||||||
|
|
||||||
JsonObject leds = root.createNestedObject("leds");
|
JsonObject leds = root.createNestedObject("leds");
|
||||||
leds[F("count")] = strip.getLengthTotal();
|
leds[F("count")] = strip.getLengthTotal();
|
||||||
leds[F("pwr")] = strip.currentMilliamps;
|
leds[F("pwr")] = BusManager::currentMilliamps();
|
||||||
leds["fps"] = strip.getFps();
|
leds["fps"] = strip.getFps();
|
||||||
leds[F("maxpwr")] = (strip.currentMilliamps)? strip.ablMilliampsMax : 0;
|
leds[F("maxpwr")] = BusManager::currentMilliamps()>0 ? BusManager::ablMilliampsMax() : 0;
|
||||||
leds[F("maxseg")] = strip.getMaxSegments();
|
leds[F("maxseg")] = strip.getMaxSegments();
|
||||||
//leds[F("actseg")] = strip.getActiveSegmentsNum();
|
//leds[F("actseg")] = strip.getActiveSegmentsNum();
|
||||||
//leds[F("seglock")] = false; //might be used in the future to prevent modifications to segment config
|
//leds[F("seglock")] = false; //might be used in the future to prevent modifications to segment config
|
||||||
|
@ -99,8 +99,8 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
|||||||
uint16_t length, start, maMax;
|
uint16_t length, start, maMax;
|
||||||
uint8_t pins[5] = {255, 255, 255, 255, 255};
|
uint8_t pins[5] = {255, 255, 255, 255, 255};
|
||||||
|
|
||||||
strip.ablMilliampsMax = request->arg(F("MA")).toInt();
|
uint16_t ablMilliampsMax = request->arg(F("MA")).toInt();
|
||||||
//strip.milliampsPerLed = request->arg(F("LA")).toInt();
|
BusManager::setMilliampsMax(ablMilliampsMax);
|
||||||
|
|
||||||
autoSegments = request->hasArg(F("MS"));
|
autoSegments = request->hasArg(F("MS"));
|
||||||
correctWB = request->hasArg(F("CCT"));
|
correctWB = request->hasArg(F("CCT"));
|
||||||
@ -197,7 +197,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
|||||||
com.add(start, length, colorOrder);
|
com.add(start, length, colorOrder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
busses.updateColorOrderMap(com);
|
BusManager::updateColorOrderMap(com);
|
||||||
|
|
||||||
// upate other pins
|
// upate other pins
|
||||||
int hw_ir_pin = request->arg(F("IR")).toInt();
|
int hw_ir_pin = request->arg(F("IR")).toInt();
|
||||||
|
@ -157,7 +157,7 @@ void WLED::loop()
|
|||||||
doInitBusses = false;
|
doInitBusses = false;
|
||||||
DEBUG_PRINTLN(F("Re-init busses."));
|
DEBUG_PRINTLN(F("Re-init busses."));
|
||||||
bool aligned = strip.checkSegmentAlignment(); //see if old segments match old bus(ses)
|
bool aligned = strip.checkSegmentAlignment(); //see if old segments match old bus(ses)
|
||||||
busses.removeAll();
|
BusManager::removeAll();
|
||||||
uint32_t mem = 0, globalBufMem = 0;
|
uint32_t mem = 0, globalBufMem = 0;
|
||||||
uint16_t maxlen = 0;
|
uint16_t maxlen = 0;
|
||||||
for (uint8_t i = 0; i < WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES; i++) {
|
for (uint8_t i = 0; i < WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES; i++) {
|
||||||
@ -168,7 +168,7 @@ void WLED::loop()
|
|||||||
globalBufMem = maxlen * 4;
|
globalBufMem = maxlen * 4;
|
||||||
}
|
}
|
||||||
if (mem + globalBufMem <= MAX_LED_MEMORY) {
|
if (mem + globalBufMem <= MAX_LED_MEMORY) {
|
||||||
busses.add(*busConfigs[i]);
|
BusManager::add(*busConfigs[i]);
|
||||||
}
|
}
|
||||||
delete busConfigs[i]; busConfigs[i] = nullptr;
|
delete busConfigs[i]; busConfigs[i] = nullptr;
|
||||||
}
|
}
|
||||||
@ -960,7 +960,7 @@ void WLED::handleStatusLED()
|
|||||||
#if STATUSLED>=0
|
#if STATUSLED>=0
|
||||||
digitalWrite(STATUSLED, ledStatusState);
|
digitalWrite(STATUSLED, ledStatusState);
|
||||||
#else
|
#else
|
||||||
busses.setStatusPixel(ledStatusState ? c : 0);
|
BusManager::setStatusPixel(ledStatusState ? c : 0);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -971,7 +971,7 @@ void WLED::handleStatusLED()
|
|||||||
digitalWrite(STATUSLED, LOW);
|
digitalWrite(STATUSLED, LOW);
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
busses.setStatusPixel(0);
|
BusManager::setStatusPixel(0);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// version code in format yymmddb (b = daily build)
|
// version code in format yymmddb (b = daily build)
|
||||||
#define VERSION 2312270
|
#define VERSION 2312290
|
||||||
|
|
||||||
//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
|
||||||
|
@ -99,7 +99,7 @@ void loadSettingsFromEEPROM()
|
|||||||
bool skipFirst = EEPROM.read(2204);
|
bool skipFirst = EEPROM.read(2204);
|
||||||
bool reversed = EEPROM.read(252);
|
bool reversed = EEPROM.read(252);
|
||||||
BusConfig bc = BusConfig(EEPROM.read(372) ? TYPE_SK6812_RGBW : TYPE_WS2812_RGB, pins, 0, length, colorOrder, reversed, skipFirst);
|
BusConfig bc = BusConfig(EEPROM.read(372) ? TYPE_SK6812_RGBW : TYPE_WS2812_RGB, pins, 0, length, colorOrder, reversed, skipFirst);
|
||||||
busses.add(bc);
|
BusManager::add(bc);
|
||||||
|
|
||||||
notifyButton = EEPROM.read(230);
|
notifyButton = EEPROM.read(230);
|
||||||
if (EEPROM.read(231)) udpNumRetries = 1;
|
if (EEPROM.read(231)) udpNumRetries = 1;
|
||||||
|
@ -356,8 +356,8 @@ void getSettingsJS(byte subPage, char* dest)
|
|||||||
sappend('c',SET_F("LD"),useGlobalLedBuffer);
|
sappend('c',SET_F("LD"),useGlobalLedBuffer);
|
||||||
|
|
||||||
uint16_t sumMa = 0;
|
uint16_t sumMa = 0;
|
||||||
for (uint8_t s=0; s < busses.getNumBusses(); s++) {
|
for (uint8_t s=0; s < BusManager::getNumBusses(); s++) {
|
||||||
Bus* bus = busses.getBus(s);
|
Bus* bus = BusManager::getBus(s);
|
||||||
if (bus == nullptr) continue;
|
if (bus == nullptr) continue;
|
||||||
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
|
||||||
char lc[4] = "LC"; lc[2] = 48+s; lc[3] = 0; //strip length
|
char lc[4] = "LC"; lc[2] = 48+s; lc[3] = 0; //strip length
|
||||||
@ -413,22 +413,13 @@ void getSettingsJS(byte subPage, char* dest)
|
|||||||
sappend('v',ma,bus->getMaxCurrent());
|
sappend('v',ma,bus->getMaxCurrent());
|
||||||
sumMa += bus->getMaxCurrent();
|
sumMa += bus->getMaxCurrent();
|
||||||
}
|
}
|
||||||
sappend('c',SET_F("PPL"),(sumMa>0 && abs(sumMa - strip.ablMilliampsMax)>2)); // approxiamte detection if per-output limiter is enabled
|
sappend('v',SET_F("MA"),BusManager::ablMilliampsMax() ? BusManager::ablMilliampsMax() : sumMa);
|
||||||
sappend('v',SET_F("MA"),strip.ablMilliampsMax);
|
sappend('c',SET_F("PPL"),!BusManager::ablMilliampsMax() && sumMa > 0);
|
||||||
/*
|
|
||||||
sappend('v',SET_F("LA"),strip.milliampsPerLed);
|
|
||||||
if (strip.currentMilliamps)
|
|
||||||
{
|
|
||||||
sappends('m',SET_F("(\"pow\")[0]"),(char*)"");
|
|
||||||
olen -= 2; //delete ";
|
|
||||||
oappendi(strip.currentMilliamps);
|
|
||||||
oappend(SET_F("mA\";"));
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
oappend(SET_F("resetCOM("));
|
oappend(SET_F("resetCOM("));
|
||||||
oappend(itoa(WLED_MAX_COLOR_ORDER_MAPPINGS,nS,10));
|
oappend(itoa(WLED_MAX_COLOR_ORDER_MAPPINGS,nS,10));
|
||||||
oappend(SET_F(");"));
|
oappend(SET_F(");"));
|
||||||
const ColorOrderMap& com = busses.getColorOrderMap();
|
const ColorOrderMap& com = BusManager::getColorOrderMap();
|
||||||
for (uint8_t s=0; s < com.count(); s++) {
|
for (uint8_t s=0; s < com.count(); s++) {
|
||||||
const ColorOrderMapEntry* entry = com.get(s);
|
const ColorOrderMapEntry* entry = com.get(s);
|
||||||
if (entry == nullptr) break;
|
if (entry == nullptr) break;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user