diff --git a/code/espurna/light.ino b/code/espurna/light.ino index b8108b7f..4fbcf94c 100644 --- a/code/espurna/light.ino +++ b/code/espurna/light.ino @@ -34,7 +34,7 @@ typedef struct { bool state; unsigned char inputValue; // value that has been inputted unsigned char value; // normalized value including brightness - unsigned char shadow; // represented value + unsigned char target; // target value double current; // transition value } channel_t; std::vector _light_channel; @@ -314,25 +314,29 @@ void _fromMireds(unsigned long mireds) { // Output Values // ----------------------------------------------------------------------------- -void _toRGB(char * rgb, size_t len) { +void _toRGB(char * rgb, size_t len, bool target) { unsigned long value = 0; - value += _light_channel[0].inputValue; + value += target ? _light_channel[0].target : _light_channel[0].inputValue; value <<= 8; - value += _light_channel[1].inputValue; + value += target ? _light_channel[1].target : _light_channel[1].inputValue; value <<= 8; - value += _light_channel[2].inputValue; + value += target ? _light_channel[2].target : _light_channel[2].inputValue; snprintf_P(rgb, len, PSTR("#%06X"), value); } -void _toHSV(char * hsv, size_t len) { +void _toRGB(char * rgb, size_t len) { + _toRGB(rgb, len, false); +} + +void _toHSV(char * hsv, size_t len, bool target) { double h, s, v; double brightness = (double) _light_brightness / LIGHT_MAX_BRIGHTNESS; - double r = (double) (_light_channel[0].inputValue * brightness) / 255.0; - double g = (double) (_light_channel[1].inputValue * brightness) / 255.0; - double b = (double) (_light_channel[2].inputValue * brightness) / 255.0; + double r = (double) ((target ? _light_channel[0].target : _light_channel[0].inputValue) * brightness) / 255.0; + double g = (double) ((target ? _light_channel[1].target : _light_channel[1].inputValue) * brightness) / 255.0; + double b = (double) ((target ? _light_channel[2].target : _light_channel[2].inputValue) * brightness) / 255.0; double min = std::min(r, std::min(g, b)); double max = std::max(r, std::max(g, b)); @@ -363,27 +367,41 @@ void _toHSV(char * hsv, size_t len) { snprintf_P(hsv, len, PSTR("%d,%d,%d"), round(h), round(s), round(v)); } -void _toLong(char * color, size_t len) { +void _toHSV(char * hsv, size_t len) { + _toHSV(hsv, len, false); +} + +void _toLong(char * color, size_t len, bool target) { + if (!_light_has_color) return; snprintf_P(color, len, PSTR("%d,%d,%d"), - (int) _light_channel[0].inputValue, - (int) _light_channel[1].inputValue, - (int) _light_channel[2].inputValue + (int) (target ? _light_channel[0].target : _light_channel[0].inputValue), + (int) (target ? _light_channel[1].target : _light_channel[1].inputValue), + (int) (target ? _light_channel[2].target : _light_channel[2].inputValue) ); + } -void _toCSV(char * buffer, size_t len, bool applyBrightness) { +void _toLong(char * color, size_t len) { + _toLong(color, len, false); +} + +void _toCSV(char * buffer, size_t len, bool applyBrightness, bool target) { char num[10]; float b = applyBrightness ? (float) _light_brightness / LIGHT_MAX_BRIGHTNESS : 1; for (unsigned char i=0; i<_light_channel.size(); i++) { - itoa(_light_channel[i].inputValue * b, num, 10); + itoa((target ? _light_channel[i].target : _light_channel[i].inputValue) * b, num, 10); if (i>0) strncat(buffer, ",", len--); strncat(buffer, num, len); len = len - strlen(num); } } +void _toCSV(char * buffer, size_t len, bool applyBrightness) { + _toCSV(buffer, len, applyBrightness, false); +} + // ----------------------------------------------------------------------------- // PROVIDER // ----------------------------------------------------------------------------- @@ -399,37 +417,32 @@ unsigned int _toPWM(unsigned long value, bool gamma, bool reverse) { // Returns a PWM value for the given channel ID unsigned int _toPWM(unsigned char id) { bool useGamma = _light_use_gamma && _light_has_color && (id < 3); - return _toPWM(_light_channel[id].shadow, useGamma, _light_channel[id].reverse); + return _toPWM(_light_channel[id].current, useGamma, _light_channel[id].reverse); } -void _shadow() { +void _transition() { // Update transition ticker _light_steps_left--; if (_light_steps_left == 0) _light_transition_ticker.detach(); // Transitions - unsigned char target; for (unsigned int i=0; i < _light_channel.size(); i++) { - target = _light_state && _light_channel[i].state ? _light_channel[i].value : 0; - if (_light_steps_left == 0) { - _light_channel[i].current = target; + _light_channel[i].current = _light_channel[i].target; } else { - double difference = (double) (target - _light_channel[i].current) / (_light_steps_left + 1); + double difference = (double) (_light_channel[i].target - _light_channel[i].current) / (_light_steps_left + 1); _light_channel[i].current = _light_channel[i].current + difference; } - _light_channel[i].shadow = _light_channel[i].current; - } } void _lightProviderUpdate() { - _shadow(); + _transition(); #if LIGHT_PROVIDER == LIGHT_PROVIDER_MY92XX @@ -572,13 +585,13 @@ void lightMQTT() { // Color if (getSetting("useCSS", LIGHT_USE_CSS).toInt() == 1) { - _toRGB(buffer, sizeof(buffer)); + _toRGB(buffer, sizeof(buffer), true); } else { - _toLong(buffer, sizeof(buffer)); + _toLong(buffer, sizeof(buffer), true); } mqttSend(MQTT_TOPIC_COLOR_RGB, buffer); - _toHSV(buffer, sizeof(buffer)); + _toHSV(buffer, sizeof(buffer), true); mqttSend(MQTT_TOPIC_COLOR_HSV, buffer); // Mireds @@ -589,7 +602,7 @@ void lightMQTT() { // Channels for (unsigned int i=0; i < _light_channel.size(); i++) { - itoa(_light_channel[i].inputValue, buffer, 10); + itoa(_light_channel[i].target, buffer, 10); mqttSend(MQTT_TOPIC_CHANNEL, i, buffer); } @@ -642,6 +655,12 @@ void lightUpdate(bool save, bool forward, bool group_forward) { _generateBrightness(); + // Update channels + for (unsigned int i=0; i < _light_channel.size(); i++) { + _light_channel[i].target = _light_state && _light_channel[i].state ? _light_channel[i].value : 0; + DEBUG_MSG_P("[LIGHT] Channel #%u target value: %u\n", i, _light_channel[i].target); + } + // Configure color transition _light_steps_left = _light_use_transitions ? _light_transition_time / LIGHT_TRANSITION_STEP : 1; _light_transition_ticker.attach_ms(LIGHT_TRANSITION_STEP, _lightProviderUpdate); @@ -844,9 +863,9 @@ void _lightAPISetup() { apiRegister(MQTT_TOPIC_COLOR_RGB, [](char * buffer, size_t len) { if (getSetting("useCSS", LIGHT_USE_CSS).toInt() == 1) { - _toRGB(buffer, len); + _toRGB(buffer, len, true); } else { - _toLong(buffer, len); + _toLong(buffer, len, true); } }, [](const char * payload) { @@ -857,7 +876,7 @@ void _lightAPISetup() { apiRegister(MQTT_TOPIC_COLOR_HSV, [](char * buffer, size_t len) { - _toHSV(buffer, len); + _toHSV(buffer, len, true); }, [](const char * payload) { lightColor(payload, false); @@ -889,7 +908,7 @@ void _lightAPISetup() { snprintf_P(key, sizeof(key), PSTR("%s/%d"), MQTT_TOPIC_CHANNEL, id); apiRegister(key, [id](char * buffer, size_t len) { - snprintf_P(buffer, len, PSTR("%d"), lightChannel(id)); + snprintf_P(buffer, len, PSTR("%d"), _light_channel[id].target); }, [id](const char * payload) { lightChannel(id, atoi(payload));