-
-
Notifications
You must be signed in to change notification settings - Fork 4.4k
Move gamma correction down to bus level #5722
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -266,33 +266,44 @@ void BusDigital::setStatusPixel(uint32_t c) { | |
| } | ||
| } | ||
|
|
||
| void BusDigital::setBrightness(uint8_t b) { | ||
| _bri = b; | ||
| if (_bri > 0 && _bri < 255 && applyGamma) | ||
| _bri = gamma8inv(_bri + 1); // limit min brightness so gamma does not dim to black | ||
| } | ||
|
|
||
| // note: using WLED_O2_ATTR makes this function ~7% faster at the expense of 600 bytes of flash | ||
| void IRAM_ATTR BusDigital::setPixelColor(unsigned pix, uint32_t c) { | ||
| if (!_valid) return; | ||
| if (Bus::_cct >= 1900) c = colorBalanceFromKelvin(Bus::_cct, c); //color correction from CCT | ||
| if (_reversed) pix = _len - pix - 1; | ||
| pix += _skip; | ||
| uint8_t cctWW = 0, cctCW = 0; | ||
| uint16_t wwcw = 0; | ||
| if (hasWhite()) c = autoWhiteCalc(c, cctWW, cctCW); | ||
| c = color_fade(c, _bri, true); // apply brightness | ||
|
|
||
| if (hasCCT()) { | ||
| wwcw = ((cctCW + 1) * _bri) & 0xFF00; // apply brightness to CCT (store CW in upper byte) | ||
| wwcw |= ((cctWW + 1) * _bri) >> 8; | ||
| if (_type == TYPE_WS2812_WWA) c = RGBW32(wwcw, wwcw >> 8, 0, W(c)); // ww,cw, 0, w | ||
| } | ||
| // apply brightness, color correction and white calculation, if black, we can skip all of it as they are no-ops | ||
| if (c > 0) { | ||
| c = color_fade(c, _bri, false); // apply brightness | ||
| c = gamma32(c); // apply gamma correction if (currently) used | ||
| if (Bus::_cct >= 1900) c = colorBalanceFromKelvin(Bus::_cct, c); //color correction from CCT | ||
|
|
||
| if (hasWhite()) c = autoWhiteCalc(c, cctWW, cctCW); | ||
|
|
||
| if (hasCCT()) { | ||
| wwcw = uint16_t(cctCW) << 8; // store CW in upper byte | ||
| wwcw |= cctWW; | ||
| if (_type == TYPE_WS2812_WWA) c = RGBW32(wwcw, wwcw >> 8, 0, W(c)); // ww,cw, 0, w | ||
|
DedeHai marked this conversation as resolved.
DedeHai marked this conversation as resolved.
|
||
| } | ||
|
|
||
| if (BusManager::_useABL) { | ||
| // if using ABL, sum all color channels to estimate current and limit brightness in show() | ||
| uint8_t r = R(c), g = G(c), b = B(c); | ||
| if (_milliAmpsPerLed < 255) { // normal ABL | ||
| _colorSum += r + g + b + W(c); | ||
| } else { // wacky WS2815 power model, ignore white channel, use max of RGB (issue #549) | ||
| _colorSum += ((r > g) ? ((r > b) ? r : b) : ((g > b) ? g : b)); | ||
| if (BusManager::_useABL) { | ||
| // if using ABL, sum all color channels to estimate current and limit brightness in show() | ||
| uint8_t r = R(c), g = G(c), b = B(c); | ||
| if (_milliAmpsPerLed < 255) { // normal ABL | ||
| _colorSum += r + g + b + W(c); | ||
| } else { // wacky WS2815 power model, ignore white channel, use max of RGB (issue #549) | ||
| _colorSum += ((r > g) ? ((r > b) ? r : b) : ((g > b) ? g : b)); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if (_reversed) pix = _len - pix -1; | ||
| pix += _skip; | ||
| const uint8_t co = _colorOrderMap.getPixelColorOrder(pix+_start, _colorOrder); | ||
| if (_type == TYPE_WS2812_1CH_X3) { // map to correct IC, each controls 3 LEDs | ||
| unsigned pOld = pix; | ||
|
|
@@ -560,8 +571,14 @@ void BusPwm::show() { | |
| // for all other cases it will just try to "spread" the load on PSU | ||
| // Phase shifting requires that LEDC timers are synchronised (see setup()). For PWM CCT (and H-bridge) it is | ||
| // also mandatory that both channels use the same timer (pinManager takes care of that). | ||
| unsigned duty; | ||
| for (unsigned i = 0; i < numPins; i++) { | ||
| unsigned duty = (_data[i] * pwmBri) / 255; | ||
| unsigned duty; | ||
| if (applyGamma) { | ||
| duty = (unsigned)(powf((float)_data[i] / 255.0f, gammaCorrectVal) * pwmBri); // apply full resolution gamma correction: way more accurate than using gamma8(_data[i]) | ||
| } else { | ||
| duty = (_data[i] * pwmBri) / 255; | ||
| } | ||
| unsigned deadTime = 0; | ||
|
|
||
| if (_type == TYPE_ANALOG_2CH && Bus::_cctBlend <= 0) { | ||
|
|
@@ -714,6 +731,7 @@ BusNetwork::BusNetwork(const BusConfig &bc) | |
| void BusNetwork::setPixelColor(unsigned pix, uint32_t c) { | ||
| if (!_valid || pix >= _len) return; | ||
| uint8_t ww, cw; // dummy, unused | ||
| // TODO: should gamma be applied here or better leave it to the receiver? | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It should be left to the receiver. |
||
| if (_hasWhite) c = autoWhiteCalc(c, ww, cw); | ||
| if (Bus::_cct >= 1900) c = colorBalanceFromKelvin(Bus::_cct, c); //color correction from CCT | ||
| unsigned offset = pix * _UDPchannels; | ||
|
|
@@ -1109,8 +1127,8 @@ BusHub75Matrix::BusHub75Matrix(const BusConfig &bc) : Bus(bc.type, bc.start, bc. | |
|
|
||
| void IRAM_ATTR BusHub75Matrix::setPixelColor(unsigned pix, uint32_t c) { | ||
| if (!_valid) return; // note: no need to check pix >= _len as that is checked in containsPixel() | ||
| c = gamma32(c); // apply gamma correction if (currently) used | ||
| // if (_cct >= 1900) c = colorBalanceFromKelvin(_cct, c); //color correction from CCT | ||
|
|
||
| if (_ledBuffer) { | ||
| CRGB fastled_col = CRGB(c); | ||
| if (_ledBuffer[pix] != fastled_col) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -382,6 +382,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) | |
| gammaCorrectBri = false; | ||
| gammaCorrectCol = false; | ||
| } | ||
| applyGamma = gammaCorrectCol && !(realtimeMode && arlsDisableGammaCorrection && !realtimeOverride); // update gamma use (disable if needed) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should calculate this every frame in |
||
| NeoGammaWLEDMethod::calcGammaTable(gammaCorrectVal); // fill look-up tables | ||
|
|
||
| t = request->arg(F("TD")).toInt(); | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.