Skip to content

Commit

Permalink
Fix interaction of SO92, VirtualCT, and RGBWWTable (#18768)
Browse files Browse the repository at this point in the history
* remove unused variable

* Relocate SO92 implementation
This way, SO92 does not ignore SO106

* Relocate RGBWWTable implementation
This fixes a bug related to RGBWWTable and SO92.
Also, the code is tidier this way

* Cleanup: Reduce code duplication

* more consistent behaviour for SO92 and free_cw

---------

Co-authored-by: jonschz <[email protected]>
  • Loading branch information
jonschz and jonschz authored Jun 1, 2023
1 parent b9d855e commit 9d57a19
Showing 1 changed file with 25 additions and 29 deletions.
54 changes: 25 additions & 29 deletions tasmota/tasmota_xdrv_driver/xdrv_04_light.ino
Original file line number Diff line number Diff line change
Expand Up @@ -1911,21 +1911,14 @@ void LightAnimate(void)
cur_col_10[i] = change8to10(Light.new_color[i]);
}

bool rgbwwtable_applied_white = false; // did we already applied RGBWWTable to white channels (ex: in white_blend_mode or virtual_ct)
if (Light.pwm_multi_channels) {
calcGammaMultiChannels(cur_col_10);
} else {
// AddLog(LOG_LEVEL_INFO, PSTR(">>> calcGammaBulbs In %03X,%03X,%03X,%03X,%03X"), cur_col_10[0], cur_col_10[1], cur_col_10[2], cur_col_10[3], cur_col_10[4]);
rgbwwtable_applied_white = calcGammaBulbs(cur_col_10); // true means that one PWM channel is used for CT
calcGammaBulbs(cur_col_10);
// AddLog(LOG_LEVEL_INFO, PSTR(">>> calcGammaBulbs Out %03X,%03X,%03X,%03X,%03X"), cur_col_10[0], cur_col_10[1], cur_col_10[2], cur_col_10[3], cur_col_10[4]);
}

// Apply RGBWWTable only if not Settings->flag4.white_blend_mode
for (uint32_t i = 0; i < (rgbwwtable_applied_white ? 3 : Light.subtype); i++) {
uint32_t adjust = change8to10(Settings->rgbwwTable[i]);
cur_col_10[i] = changeUIntScale(cur_col_10[i], 0, 1023, 0, adjust);
}

// final adjusments for PMW ranges, post-gamma correction
for (uint32_t i = 0; i < LST_MAX; i++) {
// scale from 0..1023 to 0..pwm_range, but keep any non-zero value to at least 1
Expand Down Expand Up @@ -2320,9 +2313,8 @@ void calcGammaBulb5Channels_8(uint8_t in8[LST_MAX], uint16_t col10[LST_MAX]) {
calcGammaBulb5Channels(col10, nullptr, nullptr);
}

bool calcGammaBulbs(uint16_t cur_col_10[5]) {
void calcGammaBulbs(uint16_t cur_col_10[5]) {
bool rgbwwtable_applied_white = false;
bool pwm_ct = false;
bool white_free_cw = false; // true if White channels are uncorrelated. Happens when CW+WW>255, i.e. manually setting white channels to exceed to total power of a single channel (may harm the power supply)
// Various values needed for accurate White calculation
// CT value streteched to 0..1023 (from within CT range, so not necessarily from 153 to 500). 0=Cold, 1023=Warm
Expand All @@ -2340,24 +2332,7 @@ bool calcGammaBulbs(uint16_t cur_col_10[5]) {
calcGammaBulbCW(cur_col_10, &white_bri10, &white_free_cw);
}

// Now we know ct_10 and white_bri10 (gamma corrected if needed)

if ((LST_COLDWARM == Light.subtype) || (LST_RGBCW == Light.subtype)) {
#ifdef ESP8266
if ((PHILIPS == TasmotaGlobal.module_type) || (Settings->flag4.pwm_ct_mode)) { // channel 1 is the color tone, mapped to cold channel (0..255)
#else
if (Settings->flag4.pwm_ct_mode) { // channel 1 is the color tone, mapped to cold channel (0..255)
#endif // ESP8266
pwm_ct = true;
// Xiaomi Philips bulbs follow a different scheme:
// channel 0=intensity, channel1=temperature
cur_col_10[cw0] = white_bri10;
cur_col_10[cw0+1] = ct_10;
return false; // avoid any interference
}
}

// Now see if we need to mix RGB and White
// Now see if we need to mix RGB and White
// Valid only for LST_RGBW, LST_RGBCW, SetOption105 1, and white is zero (see doc)
if ((LST_RGBW <= Light.subtype) && (Settings->flag4.white_blend_mode) && (0 == cur_col_10[3]+cur_col_10[4])) {
uint32_t min_rgb_10 = min3(cur_col_10[0], cur_col_10[1], cur_col_10[2]);
Expand Down Expand Up @@ -2421,7 +2396,28 @@ bool calcGammaBulbs(uint16_t cur_col_10[5]) {
cur_col_10[cw0] = white_bri10 - cur_col_10[cw0+1];
}
}
return rgbwwtable_applied_white;

// Apply RGBWWTable (RGB: always, CW: only if white_blend_mode is not engaged)
for (uint32_t i = 0; i < (rgbwwtable_applied_white ? 3 : Light.subtype); i++) {
uint32_t adjust = change8to10(Settings->rgbwwTable[i]);
cur_col_10[i] = changeUIntScale(cur_col_10[i], 0, 1023, 0, adjust);
}

// Implement SO92: Some lights like Xiaomi Philips bulbs follow the scheme
// cw0=intensity, cw0+1=temperature
if (ChannelCT() >= 0) {
// Need to compute white_bri10 and ct_10 from cur_col_10[] for compatibility with VirtualCT
white_bri10 = cur_col_10[cw0] + cur_col_10[cw0+1];
ct_10 = changeUIntScale(cur_col_10[cw0+1], 0, white_bri10, 0, 1023);
if (white_bri10 > 1023) {
// In white_free_cw mode, the combined brightness of cw and ww may be larger than 1023.
// This cannot be represented in pwm_ct_mode, so we set the maximum brightness instead.
white_bri10 = 1023;
}

cur_col_10[cw0] = white_bri10;
cur_col_10[cw0+1] = ct_10;
}
}

#ifdef USE_DEVICE_GROUPS
Expand Down

0 comments on commit 9d57a19

Please sign in to comment.