Skip to content

Commit 66869f8

Browse files
authored
Merge pull request #4744 from wled/CCT-fix
CCT fix May require some additional optimisations in the future to reduce unnecessary memory allocations (i.e. mixed CCT and non CCT buses).
2 parents a041fd1 + 10d1098 commit 66869f8

File tree

2 files changed

+36
-9
lines changed

2 files changed

+36
-9
lines changed

wled00/FX.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -802,7 +802,7 @@ class Segment {
802802
friend class WS2812FX;
803803
};
804804

805-
// main "strip" class (104 bytes)
805+
// main "strip" class (108 bytes)
806806
class WS2812FX {
807807
typedef uint16_t (*mode_ptr)(); // pointer to mode function
808808
typedef void (*show_callback)(); // pre show callback
@@ -829,6 +829,7 @@ class WS2812FX {
829829
cctFromRgb(false),
830830
// true private variables
831831
_pixels(nullptr),
832+
_pixelCCT(nullptr),
832833
_suspend(false),
833834
_brightness(DEFAULT_BRIGHTNESS),
834835
_length(DEFAULT_LED_COUNT),
@@ -857,6 +858,7 @@ class WS2812FX {
857858

858859
~WS2812FX() {
859860
d_free(_pixels);
861+
d_free(_pixelCCT); // just in case
860862
d_free(customMappingTable);
861863
_mode.clear();
862864
_modeData.clear();
@@ -1004,6 +1006,7 @@ class WS2812FX {
10041006

10051007
private:
10061008
uint32_t *_pixels;
1009+
uint8_t *_pixelCCT;
10071010
std::vector<Segment> _segments;
10081011

10091012
volatile bool _suspend;

wled00/FX_fcn.cpp

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1224,11 +1224,6 @@ void WS2812FX::service() {
12241224
unsigned frameDelay = FRAMETIME;
12251225

12261226
if (!seg.freeze) { //only run effect function if not frozen
1227-
int oldCCT = BusManager::getSegmentCCT(); // store original CCT value (actually it is not Segment based)
1228-
// when correctWB is true we need to correct/adjust RGB value according to desired CCT value, but it will also affect actual WW/CW ratio
1229-
// when cctFromRgb is true we implicitly calculate WW and CW from RGB values
1230-
if (cctFromRgb) BusManager::setSegmentCCT(-1);
1231-
else BusManager::setSegmentCCT(seg.currentCCT(), correctWB);
12321227
// Effect blending
12331228
uint16_t prog = seg.progress();
12341229
seg.beginDraw(prog); // set up parameters for get/setPixelColor() (will also blend colors and palette if blend style is FADE)
@@ -1249,7 +1244,6 @@ void WS2812FX::service() {
12491244
Segment::modeBlend(false); // unset semaphore
12501245
}
12511246
if (seg.isInTransition() && frameDelay > FRAMETIME) frameDelay = FRAMETIME; // force faster updates during transition
1252-
BusManager::setSegmentCCT(oldCCT); // restore old CCT for ABL adjustments
12531247
}
12541248

12551249
seg.next_time = nowUp + frameDelay;
@@ -1324,6 +1318,7 @@ void WS2812FX::blendSegment(const Segment &topSegment) const {
13241318
const unsigned progress = topSegment.progress();
13251319
const unsigned progInv = 0xFFFFU - progress;
13261320
uint8_t opacity = topSegment.currentBri(); // returns transitioned opacity for style FADE
1321+
uint8_t cct = topSegment.currentCCT();
13271322

13281323
Segment::setClippingRect(0, 0); // disable clipping by default
13291324

@@ -1396,6 +1391,7 @@ void WS2812FX::blendSegment(const Segment &topSegment) const {
13961391
const int baseY = topSegment.startY + y;
13971392
size_t indx = XY(baseX, baseY); // absolute address on strip
13981393
_pixels[indx] = color_blend(_pixels[indx], blend(c, _pixels[indx]), o);
1394+
if (_pixelCCT) _pixelCCT[indx] = cct;
13991395
// Apply mirroring
14001396
if (topSegment.mirror || topSegment.mirror_y) {
14011397
const int mirrorX = topSegment.start + width - x - 1;
@@ -1406,6 +1402,11 @@ void WS2812FX::blendSegment(const Segment &topSegment) const {
14061402
if (topSegment.mirror) _pixels[idxMX] = color_blend(_pixels[idxMX], blend(c, _pixels[idxMX]), o);
14071403
if (topSegment.mirror_y) _pixels[idxMY] = color_blend(_pixels[idxMY], blend(c, _pixels[idxMY]), o);
14081404
if (topSegment.mirror && topSegment.mirror_y) _pixels[idxMM] = color_blend(_pixels[idxMM], blend(c, _pixels[idxMM]), o);
1405+
if (_pixelCCT) {
1406+
if (topSegment.mirror) _pixelCCT[idxMX] = cct;
1407+
if (topSegment.mirror_y) _pixelCCT[idxMY] = cct;
1408+
if (topSegment.mirror && topSegment.mirror_y) _pixelCCT[idxMM] = cct;
1409+
}
14091410
}
14101411
};
14111412

@@ -1477,10 +1478,12 @@ void WS2812FX::blendSegment(const Segment &topSegment) const {
14771478
indxM += topSegment.offset; // offset/phase
14781479
if (indxM >= topSegment.stop) indxM -= length; // wrap
14791480
_pixels[indxM] = color_blend(_pixels[indxM], blend(c, _pixels[indxM]), o);
1481+
if (_pixelCCT) _pixelCCT[indxM] = cct;
14801482
}
14811483
indx += topSegment.offset; // offset/phase
14821484
if (indx >= topSegment.stop) indx -= length; // wrap
14831485
_pixels[indx] = color_blend(_pixels[indx], blend(c, _pixels[indx]), o);
1486+
if (_pixelCCT) _pixelCCT[indx] = cct;
14841487
};
14851488

14861489
// if we blend using "push" style we need to "shift" canvas to left/right/
@@ -1588,6 +1591,13 @@ void WS2812FX::show() {
15881591
size_t diff = showNow - _lastShow;
15891592

15901593
size_t totalLen = getLengthTotal();
1594+
// WARNING: as WLED doesn't handle CCT on pixel level but on Segment level instead
1595+
// we need to keep track of each pixel's CCT when blending segments (if CCT is present)
1596+
// and then set appropriate CCT from that pixel during paint (see below).
1597+
if ((hasCCTBus() || correctWB) && !cctFromRgb)
1598+
_pixelCCT = static_cast<uint8_t*>(d_malloc(totalLen * sizeof(uint8_t))); // allocate CCT buffer if necessary
1599+
if (_pixelCCT) memset(_pixelCCT, 127, totalLen); // set neutral (50:50) CCT
1600+
15911601
if (realtimeMode == REALTIME_MODE_INACTIVE || useMainSegmentOnly || realtimeOverride > REALTIME_OVERRIDE_NONE) {
15921602
// clear frame buffer
15931603
for (size_t i = 0; i < totalLen; i++) _pixels[i] = BLACK; // memset(_pixels, 0, sizeof(uint32_t) * getLengthTotal());
@@ -1605,8 +1615,22 @@ void WS2812FX::show() {
16051615
uint8_t newBri = estimateCurrentAndLimitBri(_brightness, _pixels);
16061616
if (newBri != _brightness) BusManager::setBrightness(newBri);
16071617

1608-
// paint actuall pixels
1609-
for (size_t i = 0; i < totalLen; i++) BusManager::setPixelColor(getMappedPixelIndex(i), realtimeMode && arlsDisableGammaCorrection ? _pixels[i] : gamma32(_pixels[i]));
1618+
// paint actual pixels
1619+
int oldCCT = Bus::getCCT(); // store original CCT value (since it is global)
1620+
// when cctFromRgb is true we implicitly calculate WW and CW from RGB values (cct==-1)
1621+
if (cctFromRgb) BusManager::setSegmentCCT(-1);
1622+
for (size_t i = 0; i < totalLen; i++) {
1623+
// when correctWB is true setSegmentCCT() will convert CCT into K with which we can then
1624+
// correct/adjust RGB value according to desired CCT value, it will still affect actual WW/CW ratio
1625+
if (_pixelCCT) { // cctFromRgb already exluded at allocation
1626+
if (i == 0 || _pixelCCT[i-1] != _pixelCCT[i]) BusManager::setSegmentCCT(_pixelCCT[i], correctWB);
1627+
}
1628+
BusManager::setPixelColor(getMappedPixelIndex(i), realtimeMode && arlsDisableGammaCorrection ? _pixels[i] : gamma32(_pixels[i]));
1629+
}
1630+
Bus::setCCT(oldCCT); // restore old CCT for ABL adjustments
1631+
1632+
d_free(_pixelCCT);
1633+
_pixelCCT = nullptr;
16101634

16111635
// some buses send asynchronously and this method will return before
16121636
// all of the data has been sent.

0 commit comments

Comments
 (0)