From c858710aef435b6487b6a8cce7c53e9e78f1e692 Mon Sep 17 00:00:00 2001 From: Andreas Schultz Date: Tue, 15 Oct 2019 16:41:43 +0200 Subject: [PATCH] fix pwm multi channel (Option68) With Option68 enabled, the pwm channels are independent. The channel setting code was indirectly using setRGB and setCW. Those methods recalculate the channel values to adjust for brightness, thereby modifying the channel values. This change add raw channel set/get methods that do not modify the channels values and uses those when pwm_multichannel is in effect. --- sonoff/_changelog.ino | 1 + sonoff/xdrv_04_light.ino | 47 ++++++++++++++++++++++++++++------------ 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index e12f18640..7d3a871b6 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -7,6 +7,7 @@ * Add define USE_SONOFF_RF to enable/disable Sonoff Rf support (#6648) * Add incremental beeps to Ifan03 remote control fan speed buttons (#6636) * Add rule support after every command execution like Fanspeed#Data=2 (#6636) + * Fix handling of ligth channels when pwm_multichannel (Option68) is enabled * * 6.6.0.17 20191009 * Add command SetOption34 0..255 to set backlog delay. Default value is 200 (mSeconds) (#6562) diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 2fafd2e6c..603e95f30 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -420,6 +420,14 @@ class LightStateClass { getActualRGBCW(&channels[0], &channels[1], &channels[2], &channels[3], &channels[4]); } + void getChannelsRaw(uint8_t *channels) { + channels[0] = _r; + channels[1] = _g; + channels[2] = _b; + channels[3] = _wc; + channels[4] = _ww; + } + void getHSB(uint16_t *hue, uint8_t *sat, uint8_t *bri) { if (hue) { *hue = _hue; } if (sat) { *sat = _sat; } @@ -602,6 +610,16 @@ class LightStateClass { #endif } + // set all 5 channels at once, don't modify the values in ANY way + // Channels are: R G B CW WW + void setChannelsRaw(uint8_t *channels) { + _r = channels[0]; + _g = channels[1]; + _b = channels[2]; + _wc = channels[3]; + _ww = channels[4]; +} + // set all 5 channels at once. // Channels are: R G B CW WW // Brightness is automatically recalculated to adjust channels to the desired values @@ -838,10 +856,13 @@ public: AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::loadSettings light_type/sub (%d %d)", light_type, Light.subtype); #endif - // first try setting CW, if zero, it select RGB mode - _state->setCW(Settings.light_color[3], Settings.light_color[4], true); - _state->setRGB(Settings.light_color[0], Settings.light_color[1], Settings.light_color[2]); - if (!_pwm_multi_channels) { + if (_pwm_multi_channels) { + _state->setChannelsRaw(Settings.light_color); + } else { + // first try setting CW, if zero, it select RGB mode + _state->setCW(Settings.light_color[3], Settings.light_color[4], true); + _state->setRGB(Settings.light_color[0], Settings.light_color[1], Settings.light_color[2]); + // only if non-multi channel // We apply dimmer in priority to RGB uint8_t bri = _state->DimmerToBri(Settings.light_dimmer); @@ -893,16 +914,13 @@ public: // calculate the levels for each channel void calcLevels() { uint8_t r,g,b,c,w,briRGB,briCT; - _state->getActualRGBCW(&r,&g,&b,&c,&w); if (_pwm_multi_channels) { // if PWM multi channel, no more transformation required - Light.current_color[0] = r; - Light.current_color[1] = g; - Light.current_color[2] = b; - Light.current_color[3] = c; - Light.current_color[4] = w; + _state->getChannelsRaw(Light.current_color); return; } + + _state->getActualRGBCW(&r,&g,&b,&c,&w); briRGB = _state->getBriRGB(); briCT = _state->getBriCT(); @@ -948,9 +966,7 @@ public: void saveSettings() { if (Light.pwm_multi_channels) { // simply save each channel - _state->getActualRGBCW(&Settings.light_color[0], &Settings.light_color[1], - &Settings.light_color[2], &Settings.light_color[3], - &Settings.light_color[4]); + _state->getChannelsRaw(Settings.light_color); Settings.light_dimmer = 100; // arbitrary value, unused in this mode } else { uint8_t cm = _state->getColorMode(); @@ -980,13 +996,16 @@ public: // Channels are: R G B CW WW // Brightness is automatically recalculated to adjust channels to the desired values void changeChannels(uint8_t *channels) { - if (LST_COLDWARM == Light.subtype) { + if (Light.pwm_multi_channels) { + _state->setChannelsRaw(channels); + } else if (LST_COLDWARM == Light.subtype) { // remap channels 0-1 to 3-4 if cold/warm uint8_t remapped_channels[5] = {0,0,0,channels[0],channels[1]}; _state->setChannels(remapped_channels); } else { _state->setChannels(channels); } + saveSettings(); calcLevels(); }