From f148221d193f8b70a54b6724d08c378bd6030448 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 10 May 2021 15:01:41 +0200 Subject: [PATCH 1/3] Allow retaining ratio between white and color channels --- tasmota/xdrv_04_light.ino | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index 6cb686971..91775d70c 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -1257,6 +1257,28 @@ void LightSetBri(uint8_t device, uint8_t bri) { } } +void LightSetBriScaled(uint8_t bri) { + // change both dimmers, retain ratio between white and color channels + uint32_t bri_rgb = light_state.getBriRGB(); + uint32_t bri_ct = light_state.getBriCT(); +#ifdef DEBUG_LIGHT + AddLog(LOG_LEVEL_DEBUG, "LightSetBri bri:%d, bri_rgb:%d, bri_ct: %d", bri, bri_rgb, bri_ct); +#endif + uint32_t max_bri = light_state.getBri(); + if (max_bri == 0) { + bri_rgb = bri; + bri_ct = bri; + } else { + bri_rgb = bri * bri_rgb / max_bri; + bri_ct = bri * bri_ct / max_bri; + } +#ifdef DEBUG_LIGHT + AddLog(LOG_LEVEL_DEBUG, "LightSetBri new bri_rgb:%d, new bri_ct: %d", bri_rgb, bri_ct); +#endif + light_controller.changeBriRGB(bri_rgb); + light_controller.changeBriCT(bri_ct); +} + void LightColorOffset(int32_t offset) { uint16_t hue; uint8_t sat; @@ -2461,7 +2483,7 @@ void CmndSupportColor(void) light_controller.changeChannels(Light.entry_color); if (2 == XdrvMailbox.index) { // If Color2, set back old brightness - light_controller.changeBri(old_bri); + LightSetBriScaled(old_bri); } #ifdef USE_LIGHT_PALETTE } @@ -2713,7 +2735,7 @@ void CmndDimmer(void) TasmotaGlobal.skip_light_fade = true; XdrvMailbox.index = 0; } - else if (XdrvMailbox.index > 2) { + else if (XdrvMailbox.index > 4) { XdrvMailbox.index = 1; } @@ -2740,7 +2762,14 @@ void CmndDimmer(void) if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { if (light_controller.isCTRGBLinked()) { // normal state, linked RGB and CW - light_controller.changeDimmer(XdrvMailbox.payload); + if (4 == XdrvMailbox.index) { + // change both dimmers, retain ratio between white and color channels + uint32_t new_bri = changeUIntScale(XdrvMailbox.payload, 0, 100, 0, 255); + LightSetBriScaled(new_bri); + } else { + // change both dimmers + light_controller.changeDimmer(XdrvMailbox.payload); + } LightPreparePower(); } else { if (0 != XdrvMailbox.index) { From 47d1e6f78bf9bc85bb560d51085a1284ddae3c64 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 10 May 2021 20:35:04 +0200 Subject: [PATCH 2/3] Use changeUIntScale when scaling brightness --- tasmota/xdrv_04_light.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index 91775d70c..e22b4706f 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -1269,8 +1269,8 @@ void LightSetBriScaled(uint8_t bri) { bri_rgb = bri; bri_ct = bri; } else { - bri_rgb = bri * bri_rgb / max_bri; - bri_ct = bri * bri_ct / max_bri; + bri_rgb = changeUIntScale(bri_rgb, 0, max_bri, 0, bri); + bri_ct = changeUIntScale(bri_ct, 0, max_bri, 0, bri); } #ifdef DEBUG_LIGHT AddLog(LOG_LEVEL_DEBUG, "LightSetBri new bri_rgb:%d, new bri_ct: %d", bri_rgb, bri_ct); From ee2f3f4737cc91c31890a8cecb0bdc9ad811ada2 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 10 May 2021 20:36:22 +0200 Subject: [PATCH 3/3] Save rgb/ct ratio when setting color --- tasmota/xdrv_04_light.ino | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index e22b4706f..27051e00e 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -171,7 +171,8 @@ void (* const LightCommand[])(void) PROGMEM = { // Light color mode, either RGB alone, or white-CT alone, or both only available if ct_rgb_linked is false enum LightColorModes { - LCM_RGB = 1, LCM_CT = 2, LCM_BOTH = 3 }; + LCM_RGB = 1, LCM_CT = 2, LCM_BOTH = 3 +}; struct LRgbColor { uint8_t R, G, B; @@ -321,6 +322,7 @@ class LightStateClass { uint16_t _hue = 0; // 0..359 uint8_t _sat = 255; // 0..255 uint8_t _briRGB = 255; // 0..255 + uint8_t _briRGB_orig = 255; // 0..255 // dimmer is same as _bri but with a range of 0%-100% uint8_t _r = 255; // 0..255 uint8_t _g = 255; // 0..255 @@ -331,6 +333,7 @@ class LightStateClass { uint8_t _wc = 255; // white cold channel uint8_t _ww = 0; // white warm channel uint8_t _briCT = 255; + uint8_t _briCT_orig = 255; uint8_t _color_mode = LCM_RGB; // RGB by default @@ -343,7 +346,7 @@ class LightStateClass { _subtype = sub_type; // set sub_type at initialization, shoudln't be changed afterwards } - // This function is a bit hairy, it will try to match the rerquired + // This function is a bit hairy, it will try to match the required // colormode with the features of the device: // LST_NONE: LCM_RGB // LST_SINGLE: LCM_RGB @@ -455,6 +458,10 @@ class LightStateClass { return _briCT; } + inline uint8_t getBriCTOrig() { + return _briCT_orig; + } + static inline uint8_t DimmerToBri(uint8_t dimmer) { return changeUIntScale(dimmer, 0, 100, 0, 255); // 0..255 } @@ -520,6 +527,10 @@ class LightStateClass { return _briRGB; } + inline uint8_t getBriRGBOrig() { + return _briRGB_orig; + } + void setDimmer(uint8_t dimmer) { setBri(DimmerToBri(dimmer)); } @@ -649,6 +660,13 @@ class LightStateClass { void setChannels(uint8_t *channels) { setRGB(channels[0], channels[1], channels[2]); setCW(channels[3], channels[4], true); // free range for WC and WW + uint8_t r = channels[0]; + uint8_t g = channels[1]; + uint8_t b = channels[2]; + uint8_t cw = channels[3]; + uint8_t ww = channels[4]; + _briRGB_orig = (r > g && r > b) ? r : (g > b) ? g : b; + _briCT_orig = (cw > ww) ? cw : ww; #ifdef DEBUG_LIGHT AddLog(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setChannels (%d %d %d %d %d)", channels[0], channels[1], channels[2], channels[3], channels[4]); @@ -1259,12 +1277,12 @@ void LightSetBri(uint8_t device, uint8_t bri) { void LightSetBriScaled(uint8_t bri) { // change both dimmers, retain ratio between white and color channels - uint32_t bri_rgb = light_state.getBriRGB(); - uint32_t bri_ct = light_state.getBriCT(); + uint32_t bri_rgb = light_state.getBriRGBOrig(); + uint32_t bri_ct = light_state.getBriCTOrig(); #ifdef DEBUG_LIGHT AddLog(LOG_LEVEL_DEBUG, "LightSetBri bri:%d, bri_rgb:%d, bri_ct: %d", bri, bri_rgb, bri_ct); #endif - uint32_t max_bri = light_state.getBri(); + uint32_t max_bri = bri_rgb > bri_ct ? bri_rgb : bri_ct; if (max_bri == 0) { bri_rgb = bri; bri_ct = bri;