Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions wled00/FX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7528,9 +7528,9 @@ uint16_t mode_2Ddistortionwaves() {
byte valueG = gdistort + ((a2-( ((xoffs - cx1) * (xoffs - cx1) + (yoffs - cy1) * (yoffs - cy1))>>7 ))<<1);
byte valueB = bdistort + ((a3-( ((xoffs - cx2) * (xoffs - cx2) + (yoffs - cy2) * (yoffs - cy2))>>7 ))<<1);

valueR = gamma8(cos8_t(valueR));
valueG = gamma8(cos8_t(valueG));
valueB = gamma8(cos8_t(valueB));
valueR = cos8_t(valueR);
valueG = cos8_t(valueG);
valueB = cos8_t(valueB);

if(SEGMENT.palette == 0) {
// use RGB values (original color mode)
Expand Down
86 changes: 12 additions & 74 deletions wled00/FX_fcn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1196,8 +1196,9 @@ void WS2812FX::finalizeInit() {
if (busEnd > _length) _length = busEnd;
// This must be done after all buses have been created, as some kinds (parallel I2S) interact
bus->begin();
bus->setBrightness(bri);
bus->setBrightness(scaledBri(bri));
}
BusManager::initializeABL(); // init brightness limiter
DEBUG_PRINTF_P(PSTR("Heap after buses: %d\n"), ESP.getFreeHeap());

Segment::maxWidth = _length;
Expand Down Expand Up @@ -1299,7 +1300,7 @@ static uint8_t _add (uint8_t a, uint8_t b) { unsigned t = a + b; return t
static uint8_t _subtract (uint8_t a, uint8_t b) { return b > a ? (b - a) : 0; }
static uint8_t _difference(uint8_t a, uint8_t b) { return b > a ? (b - a) : (a - b); }
static uint8_t _average (uint8_t a, uint8_t b) { return (a + b) >> 1; }
#ifdef CONFIG_IDF_TARGET_ESP32C3
#if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3)
static uint8_t _multiply (uint8_t a, uint8_t b) { return ((a * b) + 255) >> 8; } // faster than division on C3 but slightly less accurate
#else
static uint8_t _multiply (uint8_t a, uint8_t b) { return (a * b) / 255; } // origianl uses a & b in range [0,1]
Expand All @@ -1310,10 +1311,10 @@ static uint8_t _darken (uint8_t a, uint8_t b) { return a < b ? a : b; }
static uint8_t _screen (uint8_t a, uint8_t b) { return 255 - _multiply(~a,~b); } // 255 - (255-a)*(255-b)/255
static uint8_t _overlay (uint8_t a, uint8_t b) { return b < 128 ? 2 * _multiply(a,b) : (255 - 2 * _multiply(~a,~b)); }
static uint8_t _hardlight (uint8_t a, uint8_t b) { return a < 128 ? 2 * _multiply(a,b) : (255 - 2 * _multiply(~a,~b)); }
#ifdef CONFIG_IDF_TARGET_ESP32C3
static uint8_t _softlight (uint8_t a, uint8_t b) { return (((b * b * (255 - 2 * a) + 255) >> 8) + 2 * a * b + 255) >> 8; } // Pegtop's formula (1 - 2a)b^2 + 2ab
#if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3)
static uint8_t _softlight (uint8_t a, uint8_t b) { return (((b * b * (255 - 2 * a))) + ((2 * a * b + 256) << 8)) >> 16; } // Pegtop's formula (1 - 2a)b^2
#else
static uint8_t _softlight (uint8_t a, uint8_t b) { return (b * b * (255 - 2 * a) / 255 + 2 * a * b) / 255; } // Pegtop's formula (1 - 2a)b^2 + 2ab
static uint8_t _softlight (uint8_t a, uint8_t b) { return (b * b * (255 - 2 * a) + 255 * 2 * a * b) / (255 * 255); } // Pegtop's formula (1 - 2a)b^2 + 2ab
#endif
static uint8_t _dodge (uint8_t a, uint8_t b) { return _divide(~a,b); }
static uint8_t _burn (uint8_t a, uint8_t b) { return ~_divide(a,~b); }
Expand Down Expand Up @@ -1555,66 +1556,6 @@ void WS2812FX::blendSegment(const Segment &topSegment) const {
Segment::setClippingRect(0, 0); // disable clipping for overlays
}

// To disable brightness limiter we either set output max current to 0 or single LED current to 0
static uint8_t estimateCurrentAndLimitBri(uint8_t brightness, uint32_t *pixels) {
unsigned milliAmpsMax = BusManager::ablMilliampsMax();
if (milliAmpsMax > 0) {
unsigned milliAmpsTotal = 0;
unsigned avgMilliAmpsPerLED = 0;
unsigned lengthDigital = 0;
bool useWackyWS2815PowerModel = false;

for (size_t i = 0; i < BusManager::getNumBusses(); i++) {
const Bus *bus = BusManager::getBus(i);
if (!(bus && bus->isDigital() && bus->isOk())) continue;
unsigned maPL = bus->getLEDCurrent();
if (maPL == 0 || bus->getMaxCurrent() > 0) continue; // skip buses with 0 mA per LED or max current per bus defined (PP-ABL)
if (maPL == 255) {
useWackyWS2815PowerModel = true;
maPL = 12; // WS2815 uses 12mA per channel
}
avgMilliAmpsPerLED += maPL * bus->getLength();
lengthDigital += bus->getLength();
// sum up the usage of each LED on digital bus
uint32_t busPowerSum = 0;
for (unsigned j = 0; j < bus->getLength(); j++) {
uint32_t c = pixels[j + bus->getStart()];
byte r = R(c), g = G(c), b = B(c), w = W(c);
if (useWackyWS2815PowerModel) { //ignore white component on WS2815 power calculation
busPowerSum += (max(max(r,g),b)) * 3;
} else {
busPowerSum += (r + g + b + w);
}
}
// RGBW led total output with white LEDs enabled is still 50mA, so each channel uses less
if (bus->hasWhite()) {
busPowerSum *= 3;
busPowerSum >>= 2; //same as /= 4
}
// powerSum has all the values of channels summed (max would be getLength()*765 as white is excluded) so convert to milliAmps
milliAmpsTotal += (busPowerSum * maPL * brightness) / (765*255);
}
if (lengthDigital > 0) {
avgMilliAmpsPerLED /= lengthDigital;

if (milliAmpsMax > MA_FOR_ESP && avgMilliAmpsPerLED > 0) { //0 mA per LED and too low numbers turn off calculation
unsigned powerBudget = (milliAmpsMax - MA_FOR_ESP); //80/120mA for ESP power
if (powerBudget > lengthDigital) { //each LED uses about 1mA in standby, exclude that from power budget
powerBudget -= lengthDigital;
} else {
powerBudget = 0;
}
if (milliAmpsTotal > powerBudget) {
//scale brightness down to stay in current limit
unsigned scaleB = powerBudget * 255 / milliAmpsTotal;
brightness = ((brightness * scaleB) >> 8) + 1;
}
}
}
}
return brightness;
}

void WS2812FX::show() {
unsigned long showNow = millis();
size_t diff = showNow - _lastShow;
Expand All @@ -1640,10 +1581,6 @@ void WS2812FX::show() {
show_callback callback = _callback;
if (callback) callback(); // will call setPixelColor or setRealtimePixelColor

// determine ABL brightness
uint8_t newBri = estimateCurrentAndLimitBri(_brightness, _pixels);
if (newBri != _brightness) BusManager::setBrightness(newBri);

// paint actual pixels
int oldCCT = Bus::getCCT(); // store original CCT value (since it is global)
// when cctFromRgb is true we implicitly calculate WW and CW from RGB values (cct==-1)
Expand All @@ -1654,7 +1591,11 @@ void WS2812FX::show() {
if (_pixelCCT) { // cctFromRgb already exluded at allocation
if (i == 0 || _pixelCCT[i-1] != _pixelCCT[i]) BusManager::setSegmentCCT(_pixelCCT[i], correctWB);
}
BusManager::setPixelColor(getMappedPixelIndex(i), realtimeMode && arlsDisableGammaCorrection ? _pixels[i] : gamma32(_pixels[i]));

uint32_t c = _pixels[i]; // need a copy, do not modify _pixels directly (no byte access allowed on ESP32)
if(c > 0 && !(realtimeMode && arlsDisableGammaCorrection))
c = gamma32(c); // apply gamma correction if enabled note: applying gamma after brightness has too much color loss
BusManager::setPixelColor(getMappedPixelIndex(i), c);
}
Bus::setCCT(oldCCT); // restore old CCT for ABL adjustments

Expand All @@ -1666,9 +1607,6 @@ void WS2812FX::show() {
// See https://github.com/Makuna/NeoPixelBus/wiki/ESP32-NeoMethods#neoesp32rmt-methods
BusManager::show();

// restore brightness for next frame
if (newBri != _brightness) BusManager::setBrightness(_brightness);

if (diff > 0) { // skip calculation if no time has passed
size_t fpsCurr = (1000 << FPS_CALC_SHIFT) / diff; // fixed point math
_cumulativeFps = (FPS_CALC_AVG * _cumulativeFps + fpsCurr + FPS_CALC_AVG / 2) / (FPS_CALC_AVG + 1); // "+FPS_CALC_AVG/2" for proper rounding
Expand Down Expand Up @@ -1733,7 +1671,7 @@ void WS2812FX::setBrightness(uint8_t b, bool direct) {
if (_brightness == 0) { //unfreeze all segments on power off
for (const Segment &seg : _segments) seg.freeze = false; // freeze is mutable
}
BusManager::setBrightness(b);
BusManager::setBrightness(scaledBri(b));
if (!direct) {
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
Expand Down
Loading