diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index 6cb686971..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]); @@ -1257,6 +1275,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.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 = bri_rgb > bri_ct ? bri_rgb : bri_ct; + if (max_bri == 0) { + bri_rgb = bri; + bri_ct = bri; + } else { + 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); +#endif + light_controller.changeBriRGB(bri_rgb); + light_controller.changeBriCT(bri_ct); +} + void LightColorOffset(int32_t offset) { uint16_t hue; uint8_t sat; @@ -2461,7 +2501,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 +2753,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 +2780,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) {