From 3a43050d93fdf1afce468cd7f0c3c8bb15d374a0 Mon Sep 17 00:00:00 2001 From: Colin Kuebler Date: Wed, 30 Jan 2019 17:19:40 -0500 Subject: [PATCH 1/8] Integrated Gabor's SM16716 code into the light driver code Removed redundant processing and variables Added new light type to distinguish SM16716 devices --- sonoff/sonoff.ino | 6 + sonoff/xdrv_04_light.ino | 106 ++++++++++ sonoff/xdrv_20_sm16717.ino | 400 ------------------------------------- 3 files changed, 112 insertions(+), 400 deletions(-) delete mode 100644 sonoff/xdrv_20_sm16717.ino diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 936f7930e..fbf256134 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2422,6 +2422,12 @@ void GpioInit(void) light_type = LT_WS2812; } #endif // USE_WS2812 +#ifdef USE_SM16716 + if (SM16716_ModuleSelected()) { + light_type += 3; + light_type |= 16; + } +#endif // ifdef USE_SM16716 if (!light_type) { for (uint8_t i = 0; i < MAX_PWMS; i++) { // Basic PWM control only if (pin[GPIO_PWM1 +i] < 99) { diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 9d8740ccb..2dc098c80 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -32,6 +32,9 @@ * 11 +WS2812 RGB(W) no (One WS2812 RGB or RGBW ledstrip) * 12 AiLight RGBW no * 13 Sonoff B1 RGBCW yes + * 19 SM16716 RGB no + * 20 SM16716+W RGBW no + * 21 SM16716+CW RGBCW yes * * light_scheme WS2812 3+ Colors 1+2 Colors Effect * ------------ ------ --------- ---------- ----------------- @@ -354,6 +357,99 @@ void LightMy92x1Duty(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b, uint8_t dut os_delay_us(12); // TStop > 12us. } +#ifdef USE_SM16716 +/*********************************************************************************************\ + * SM16716 - Controlling RGB over a synchronous serial line + * Copyright (C) 2019 Gabor Simon + * + * Source: https://community.home-assistant.io/t/cheap-uk-wifi-bulbs-with-tasmota-teardown-help-tywe3s/40508/27 + * +\*********************************************************************************************/ + +// Enable this for debug logging +//#define D_LOG_SM16716 "SM16716: " + +uint8_t sm16716_pin_clk = 100; +uint8_t sm16716_pin_dat = 100; + +void SM16716_SendBit(uint8_t v) +{ + /* NOTE: + * According to the spec sheet, max freq is 30 MHz, that is 16.6 ns per high/low half of the + * clk square wave. That is less than the overhead of 'digitalWrite' at this clock rate, + * so no additional delays are needed yet. */ + + digitalWrite(sm16716_pin_dat, (v != 0) ? HIGH : LOW); + //delayMicroseconds(1); + digitalWrite(sm16716_pin_clk, HIGH); + //delayMicroseconds(1); + digitalWrite(sm16716_pin_clk, LOW); +} + +void SM16716_SendByte(uint8_t v) +{ + uint8_t mask; + + for (mask = 0x80; mask; mask >>= 1) { + SM16716_SendBit(v & mask); + } +} + +void SM16716_Update(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b) +{ +#ifdef D_LOG_SM16716 + snprintf_P(log_data, sizeof(log_data), + PSTR(D_LOG_SM16716 "Update; rgb=%02x%02x%02x"), + duty_r, duty_g, duty_b); + AddLog(LOG_LEVEL_DEBUG); +#endif // D_LOG_SM16716 + + // send start bit + SM16716_SendBit(1); + // send 24-bit rgb data + SM16716_SendByte(duty_r); + SM16716_SendByte(duty_g); + SM16716_SendByte(duty_g); + // send a 'do it' pulse + // (if multiple chips are chained, each one processes the 1st '1rgb' 25-bit block and + // passes on the rest, right until the one starting with 0) + SM16716_SendBit(0); + SM16716_SendByte(0); + SM16716_SendByte(0); + SM16716_SendByte(0); + SM16716_Show_State(); +} + +bool SM16716_ModuleSelected(void) +{ + sm16716_pin_clk = pin[GPIO_SM16716_CLK]; + sm16716_pin_dat = pin[GPIO_SM16716_DAT]; +#ifdef D_LOG_SM16716 + snprintf_P(log_data, sizeof(log_data), + PSTR(D_LOG_SM16716 "ModuleSelected; clk_pin=%d, dat_pin=%d)"), + sm16716_pin_clk, sm16716_pin_dat); + AddLog(LOG_LEVEL_DEBUG); +#endif // D_LOG_SM16716 + return (sm16716_pin_clk < 99) && (sm16716_pin_dat < 99); +} + +bool SM16716_Init(void) +{ + uint8_t t_init; + + pinMode(sm16716_pin_clk, OUTPUT); + digitalWrite(sm16716_pin_clk, LOW); + + pinMode(sm16716_pin_dat, OUTPUT); + digitalWrite(sm16716_pin_dat, LOW); + + for (t_init = 0; t_init < 50; ++t_init) { + SM16716_SendBit(0); + } + + return true; +} + /********************************************************************************************/ void LightInit(void) @@ -402,6 +498,11 @@ void LightInit(void) max_scheme = LS_MAX + WS2812_SCHEMES; } #endif // USE_WS2812 ************************************************************************ +#ifdef USE_SM16716 + else if (16 & light_type) { + SM16716_Init(); + } +#endif // ifdef USE_SM16716 else { light_pdi_pin = pin[GPIO_DI]; light_pdcki_pin = pin[GPIO_DCKI]; @@ -844,6 +945,11 @@ void LightAnimate(void) Ws2812SetColor(0, cur_col[0], cur_col[1], cur_col[2], cur_col[3]); } #endif // USE_ES2812 ************************************************************************ +#ifdef USE_SM16716 + else if (16 & light_type) { + SM16716_Update(cur_col[0], cur_col[1], cur_col[2]); + } +#endif // ifdef USE_SM16716 else if (light_type > LT_WS2812) { LightMy92x1Duty(cur_col[0], cur_col[1], cur_col[2], cur_col[3], cur_col[4]); } diff --git a/sonoff/xdrv_20_sm16717.ino b/sonoff/xdrv_20_sm16717.ino deleted file mode 100644 index 1dada4c9c..000000000 --- a/sonoff/xdrv_20_sm16717.ino +++ /dev/null @@ -1,400 +0,0 @@ -/* - xdrv_20_sm16716.ino - SM16716 RGB led controller support for Sonoff-Tasmota - - Copyright (C) 2019 Gabor Simon - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifdef USE_SM16716 - -/*********************************************************************************************\ - * SM16716 - Controlling RGB over a synchronous serial line - * - * Source: https://community.home-assistant.io/t/cheap-uk-wifi-bulbs-with-tasmota-teardown-help-tywe3s/40508/27 - * -\*********************************************************************************************/ - -#define XDRV_20 20 - -// Enable this for debug logging -//#define D_LOG_SM16716 "SM16716: " - -enum SM16716_Commands { - CMND_SM16716_COLOR }; - -const char k_SM16716_Commands[] PROGMEM = - D_CMND_COLOR ; - -uint8_t sm16716_pin_clk = 100; -uint8_t sm16716_pin_dat = 100; - -bool sm16716_is_selected = false; -bool sm16716_is_on = false; -uint8_t sm16716_color[3] = {0, 0, 0}; -int8_t sm16716_color_preset = 0; - - -/*********************************************************************************************/ -void SM16716_SendBit(uint8_t v) -{ - /* NOTE: - * According to the spec sheet, max freq is 30 MHz, that is 16.6 ns per high/low half of the - * clk square wave. That is less than the overhead of 'digitalWrite' at this clock rate, - * so no additional delays are needed yet. */ - - digitalWrite(sm16716_pin_dat, (v != 0) ? HIGH : LOW); - //delayMicroseconds(1); - digitalWrite(sm16716_pin_clk, HIGH); - //delayMicroseconds(1); - digitalWrite(sm16716_pin_clk, LOW); -} - - -/*********************************************************************************************/ -void SM16716_SendByte(uint8_t v) -{ - uint8_t mask; - - for (mask = 0x80; mask; mask >>= 1) { - SM16716_SendBit(v & mask); - } -} - - -/*********************************************************************************************/ -void SM16716_Append_JSON(void) -{ - snprintf_P(mqtt_data, sizeof(mqtt_data), - PSTR("%s,\"SM16716\":{\"Red\":%d,\"Green\":%d,\"Blue\":%d}"), - mqtt_data, sm16716_color[0], sm16716_color[1], sm16716_color[2]); -} - - -/*********************************************************************************************/ -bool SM16716_Show_State(void) -{ - snprintf_P(mqtt_data, sizeof(mqtt_data), - PSTR("{\"" D_CMND_COLOR "\":\"%02x%02x%02x\"}"), - sm16716_color[0], sm16716_color[1], sm16716_color[2]); - return true; -} - - -/*********************************************************************************************/ -void SM16716_Update() -{ -#ifdef D_LOG_SM16716 - snprintf_P(log_data, sizeof(log_data), - PSTR(D_LOG_SM16716 "Update; pwr=%02x, rgb=%02x%02x%02x"), - sm16716_is_on, sm16716_color[0], sm16716_color[1], sm16716_color[2]); - AddLog(LOG_LEVEL_DEBUG); -#endif // D_LOG_SM16716 - - // send start bit - SM16716_SendBit(1); - // send 24-bit rgb data - if (sm16716_is_on) { - SM16716_SendByte(sm16716_color[0]); - SM16716_SendByte(sm16716_color[1]); - SM16716_SendByte(sm16716_color[2]); - } - else { - SM16716_SendByte(0); - SM16716_SendByte(0); - SM16716_SendByte(0); - } - // send a 'do it' pulse - // (if multiple chips are chained, each one processes the 1st '1rgb' 25-bit block and - // passes on the rest, right until the one starting with 0) - SM16716_SendBit(0); - SM16716_SendByte(0); - SM16716_SendByte(0); - SM16716_SendByte(0); - SM16716_Show_State(); -} - - -/*********************************************************************************************/ -bool SM16716_ModuleSelected(void) -{ - sm16716_pin_clk = pin[GPIO_SM16716_CLK]; - sm16716_pin_dat = pin[GPIO_SM16716_DAT]; -#ifdef D_LOG_SM16716 - snprintf_P(log_data, sizeof(log_data), - PSTR(D_LOG_SM16716 "ModuleSelected; clk_pin=%d, dat_pin=%d)"), - sm16716_pin_clk, sm16716_pin_dat); - AddLog(LOG_LEVEL_DEBUG); -#endif // D_LOG_SM16716 - sm16716_is_selected = (sm16716_pin_clk < 99) && (sm16716_pin_dat < 99); - return sm16716_is_selected; -} - - -/*********************************************************************************************/ -bool SM16716_Init(void) -{ - uint8_t t_init; - - if (!SM16716_ModuleSelected()) { - return false; - } - - pinMode(sm16716_pin_clk, OUTPUT); - digitalWrite(sm16716_pin_clk, LOW); - - pinMode(sm16716_pin_dat, OUTPUT); - digitalWrite(sm16716_pin_dat, LOW); - - for (t_init = 0; t_init < 50; ++t_init) { - SM16716_SendBit(0); - } - - return true; -} - - -/*********************************************************************************************/ -/* Try to parse a string as 'RRGGBB' hex-encoded color value - * Accept only exact match (i.e. there can be no leftover chars) - */ -bool SM16716_Parse_RRGGBB(const char *data, int data_len) { - char component[3]; - char *endptr = NULL; - uint8_t candidate[3]; - int i; - -#ifdef D_LOG_SM16716 - snprintf_P(log_data, sizeof(log_data), - PSTR(D_LOG_SM16716 "Parse_RRGGBB; data='%s', data_len=%d"), - data, data_len); - AddLog(LOG_LEVEL_DEBUG); -#endif // D_LOG_SM16716 - - if (data_len != 6) { - // too long or too short - return false; - } - - // a component is exactly 3 chars, so terminate the string now - component[2] = '\0'; - - // try to parse 3 components - for (i = 0; i < 3; ++i) { - // copy the value to the temp string - component[0] = data[0]; - component[1] = data[1]; - // try to interpret it as a hex number - candidate[i] = (uint8_t)strtoul(component, &endptr, 16); - if (!endptr || *endptr) { - // not a valid hex number - return false; - } - // advance to the next 2 characters - data += 2; - } - - // now that we have all 3, we may change sm16716_color[] - sm16716_color[0] = candidate[0]; - sm16716_color[1] = candidate[1]; - sm16716_color[2] = candidate[2]; - return true; -} - - -/*********************************************************************************************/ -bool SM16716_Parse_Color(char *data, int data_len) { - /* NOTE: Very similar to 'LightColorEntry', but can't reuse it here, because - * 'light_type' must be PWM, and then it won't parse the color components. */ - -#ifdef D_LOG_SM16716 - snprintf_P(log_data, sizeof(log_data), - PSTR(D_LOG_SM16716 "Parse_Color; data='%s', data_len=%d"), - data, data_len); - AddLog(LOG_LEVEL_DEBUG); -#endif // D_LOG_SM16716 - - if (data_len < 3) { // too short for color literal: try to interpret as a color preset - // check for '+' and '-' commands first - switch (data[0]) { - case '+': // advance to the next preset, handle wrap-around - ++sm16716_color_preset; - if (sm16716_color_preset >= MAX_FIXED_COLOR) { - sm16716_color_preset = 0; - } - break; - - case '-': // return to the previous preset, handle wrap-around - --sm16716_color_preset; - if (sm16716_color_preset < 0) { - sm16716_color_preset = MAX_FIXED_COLOR - 1; - } - break; - - default: - // try to interpret it as a decimal integer - { - char *endptr = NULL; - uint8_t candidate = (uint8_t)strtoul(data, &endptr, 10); - if (!endptr || *endptr || (candidate < 0) || (MAX_FIXED_COLOR <= candidate)) { - // it's not a valid integer (and nothing else), or the number is not a valid preset index - return false; - } - // we have the requested preset index - sm16716_color_preset = candidate; - } - break; - } - -#ifdef D_LOG_SM16716 - snprintf_P(log_data, sizeof(log_data), - PSTR(D_LOG_SM16716 "Parse_Color; preset=%d"), - sm16716_color_preset); - AddLog(LOG_LEVEL_DEBUG); -#endif // D_LOG_SM16716 - - // copy the requested preset values - memcpy_P(sm16716_color, &kFixedColor[sm16716_color_preset], 3); - } - else if (data[0] == '#') { // starts with #, so try to interpret as #RRGGBB - if (!SM16716_Parse_RRGGBB(data + 1, data_len - 1)) { - // not a valid RRGGBB after the # - return false; - } - } - // two more formats left: RRGGBB (without #) and comma separated color components - else if (SM16716_Parse_RRGGBB(data, data_len)) { // try to interpret as RRGGBB - // parsed successfully as RRGGBB, nothing more to do - } - else { // try to interpret as rrr,g,bb - uint8_t candidate[3]; - char *tok, *last, *endptr = NULL; - int i; - - // try to parse the first 3 comma-separated tokens - for (i = 0; i < 3; ++i) { - // try to isolate the next token - tok = strtok_r(data, ",", &last); - if (!tok) { - // we're beyond the end of string: there were too few tokens - return false; - } - // try to interpret the token as integer - candidate[i] = (uint8_t)strtoul(tok, &endptr, 0); - if (!endptr || *endptr) { - // not a valid integer - return false; - } - // in the next cycle just continue this token-processing session - data = NULL; - } - // there shouldn't be any leftover characters (i.e. we need exactly 3 components) - tok = strtok_r(NULL, ",", &last); - if (tok) { - // too many components - return false; - } - // now that we have all 3 components, we may change sm16716_color - sm16716_color[0] = candidate[0]; - sm16716_color[1] = candidate[1]; - sm16716_color[2] = candidate[2]; - } - return true; -} - - -/*********************************************************************************************/ -bool SM16716_Command(void) -{ - char command [CMDSZ]; - int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, k_SM16716_Commands); - -#ifdef D_LOG_SM16716 - snprintf_P(log_data, sizeof(log_data), - PSTR(D_LOG_SM16716 "Command; topic='%s', data_len=%d, data='%s', code=%d"), - XdrvMailbox.topic, XdrvMailbox.data_len, XdrvMailbox.data, command_code); - AddLog(LOG_LEVEL_DEBUG); -#endif // D_LOG_SM16716 - - switch (command_code) { - case CMND_SM16716_COLOR: - if (XdrvMailbox.data_len == 0) { - return SM16716_Show_State(); - } - if (!SM16716_Parse_Color(XdrvMailbox.data, XdrvMailbox.data_len)) { - return false; - } - SM16716_Update(); - return true; - } - return false; // Unknown command -} - - -/*********************************************************************************************\ - * Interface -\*********************************************************************************************/ -bool Xdrv20(uint8_t function) -{ - if (function == FUNC_MODULE_INIT) { - return SM16716_ModuleSelected(); - } - - if (!sm16716_is_selected) { - return false; - } - - switch (function) { - case FUNC_INIT: -#ifdef D_LOG_SM16716 - snprintf_P(log_data, sizeof(log_data), - PSTR(D_LOG_SM16716 "Entry; function=FUNC_INIT")); - AddLog(LOG_LEVEL_DEBUG); -#endif - return SM16716_Init(); - - case FUNC_COMMAND: -#ifdef D_LOG_SM16716 - snprintf_P(log_data, sizeof(log_data), - PSTR(D_LOG_SM16716 "Entry; function=FUNC_COMMAND")); - AddLog(LOG_LEVEL_DEBUG); -#endif - return SM16716_Command(); - - //case FUNC_SET_POWER: - case FUNC_SET_DEVICE_POWER: -#ifdef D_LOG_SM16716 - snprintf_P(log_data, sizeof(log_data), - PSTR(D_LOG_SM16716 "Entry; function=FUNC_SET_DEVICE_POWER, index=%02x, payload=%02x"), - XdrvMailbox.index, XdrvMailbox.payload); - AddLog(LOG_LEVEL_DEBUG); -#endif - sm16716_is_on = (XdrvMailbox.index != 0); - SM16716_Update(); - return false; // don't catch the event - - case FUNC_JSON_APPEND: -#ifdef D_LOG_SM16716 - snprintf_P(log_data, sizeof(log_data), - PSTR(D_LOG_SM16716 "Entry; function=FUNC_JSON_APPEND")); - AddLog(LOG_LEVEL_DEBUG); -#endif - SM16716_Append_JSON(); - break; - } - return false; -} - -#endif // USE_SM16716 -// vim: set ft=c sw=2 ts=2 et: From fa7440fb9afca4baa2db8fb6d83d622e8ebc90ef Mon Sep 17 00:00:00 2001 From: Colin Kuebler Date: Wed, 30 Jan 2019 17:28:25 -0500 Subject: [PATCH 2/8] Allow PWM while SM16716 is enabled, for mixed control devices --- sonoff/xdrv_04_light.ino | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 2dc098c80..90ef446ae 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -500,6 +500,13 @@ void LightInit(void) #endif // USE_WS2812 ************************************************************************ #ifdef USE_SM16716 else if (16 & light_type) { + // init PWM + for (uint8_t i = 0; i < light_subtype; i++) { + Settings.pwm_value[i] = 0; // Disable direct PWM control + if (pin[GPIO_PWM1 +i] < 99) { + pinMode(pin[GPIO_PWM1 +i], OUTPUT); + } + } SM16716_Init(); } #endif // ifdef USE_SM16716 @@ -919,7 +926,7 @@ void LightAnimate(void) light_last_color[i] = light_new_color[i]; cur_col[i] = light_last_color[i]*Settings.rgbwwTable[i]/255; cur_col[i] = (Settings.light_correction) ? ledTable[cur_col[i]] : cur_col[i]; - if (light_type < LT_PWM6) { + if (light_type < LT_PWM6 || light_type & 16) { if (pin[GPIO_PWM1 +i] < 99) { if (cur_col[i] > 0xFC) { cur_col[i] = 0xFC; // Fix unwanted blinking and PWM watchdog errors for values close to pwm_range (H801, Arilux and BN-SZ01) From ec984ab841d605225d33c723682da5de6f715d53 Mon Sep 17 00:00:00 2001 From: Colin Kuebler Date: Wed, 30 Jan 2019 17:32:17 -0500 Subject: [PATCH 3/8] Fixed compiler errors Missing #endif oops Vestigial function call --- sonoff/xdrv_04_light.ino | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 90ef446ae..b60d0e64b 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -417,7 +417,6 @@ void SM16716_Update(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b) SM16716_SendByte(0); SM16716_SendByte(0); SM16716_SendByte(0); - SM16716_Show_State(); } bool SM16716_ModuleSelected(void) @@ -450,6 +449,8 @@ bool SM16716_Init(void) return true; } +#endif // ifdef USE_SM16716 + /********************************************************************************************/ void LightInit(void) From adcfeeaed5923307c857a5d7b87f5df9a1d6f0b1 Mon Sep 17 00:00:00 2001 From: Colin Kuebler Date: Wed, 30 Jan 2019 17:57:47 -0500 Subject: [PATCH 4/8] Fixed bug in web config page caused by merge from dev --- sonoff/sonoff_template.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index e050dc882..809b0e390 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -221,7 +221,7 @@ const char kSensorNames[] PROGMEM = D_SENSOR_AZ_TX "|" D_SENSOR_AZ_RX "|" D_SENSOR_MAX31855_CS "|" D_SENSOR_MAX31855_CLK "|" D_SENSOR_MAX31855_DO "|" D_SENSOR_BUTTON "1i|" D_SENSOR_BUTTON "2i|" D_SENSOR_BUTTON "3i|" D_SENSOR_BUTTON "4i|" - D_SENSOR_BUTTON "1in|" D_SENSOR_BUTTON "2in|" D_SENSOR_BUTTON "3in|" D_SENSOR_BUTTON "4in" + D_SENSOR_BUTTON "1in|" D_SENSOR_BUTTON "2in|" D_SENSOR_BUTTON "3in|" D_SENSOR_BUTTON "4in|" D_SENSOR_SM16716_CLK "|" D_SENSOR_SM16716_DAT ; From 4b6ddfb76f3a188a12618ecf95e0a95a66bfa939 Mon Sep 17 00:00:00 2001 From: Colin Kuebler Date: Wed, 30 Jan 2019 18:15:25 -0500 Subject: [PATCH 5/8] Moved PWM control to its own block while using SM16716 to skip RGB values --- sonoff/xdrv_04_light.ino | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index b60d0e64b..d58207331 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -367,7 +367,7 @@ void LightMy92x1Duty(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b, uint8_t dut \*********************************************************************************************/ // Enable this for debug logging -//#define D_LOG_SM16716 "SM16716: " +#define D_LOG_SM16716 "SM16716: " uint8_t sm16716_pin_clk = 100; uint8_t sm16716_pin_dat = 100; @@ -927,7 +927,7 @@ void LightAnimate(void) light_last_color[i] = light_new_color[i]; cur_col[i] = light_last_color[i]*Settings.rgbwwTable[i]/255; cur_col[i] = (Settings.light_correction) ? ledTable[cur_col[i]] : cur_col[i]; - if (light_type < LT_PWM6 || light_type & 16) { + if (light_type < LT_PWM6) { if (pin[GPIO_PWM1 +i] < 99) { if (cur_col[i] > 0xFC) { cur_col[i] = 0xFC; // Fix unwanted blinking and PWM watchdog errors for values close to pwm_range (H801, Arilux and BN-SZ01) @@ -956,6 +956,17 @@ void LightAnimate(void) #ifdef USE_SM16716 else if (16 & light_type) { SM16716_Update(cur_col[0], cur_col[1], cur_col[2]); + for (uint8_t i = 3; i < light_subtype; i++) { + if (pin[GPIO_PWM1 +i-3] < 99) { + if (cur_col[i] > 0xFC) { + cur_col[i] = 0xFC; // Fix unwanted blinking and PWM watchdog errors for values close to pwm_range (H801, Arilux and BN-SZ01) + } + uint16_t curcol = cur_col[i] * (Settings.pwm_range / 255); +// snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION "Cur_Col%d %d, CurCol %d"), i, cur_col[i], curcol); +// AddLog(LOG_LEVEL_DEBUG); + analogWrite(pin[GPIO_PWM1 +i-3], bitRead(pwm_inverted, i-3) ? Settings.pwm_range - curcol : curcol); + } + } } #endif // ifdef USE_SM16716 else if (light_type > LT_WS2812) { From f60dd3c06aff4612f0fd663e4717d5af77ddcf0a Mon Sep 17 00:00:00 2001 From: Colin Kuebler Date: Wed, 30 Jan 2019 18:32:37 -0500 Subject: [PATCH 6/8] Moved pin mode selection for sm16716 out of init function Made void Call SM16716_Init before setting the color --- sonoff/xdrv_04_light.ino | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index d58207331..0591da5bb 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -432,21 +432,11 @@ bool SM16716_ModuleSelected(void) return (sm16716_pin_clk < 99) && (sm16716_pin_dat < 99); } -bool SM16716_Init(void) +void SM16716_Init(void) { - uint8_t t_init; - - pinMode(sm16716_pin_clk, OUTPUT); - digitalWrite(sm16716_pin_clk, LOW); - - pinMode(sm16716_pin_dat, OUTPUT); - digitalWrite(sm16716_pin_dat, LOW); - - for (t_init = 0; t_init < 50; ++t_init) { + for (uint8_t t_init = 0; t_init < 50; ++t_init) { SM16716_SendBit(0); } - - return true; } #endif // ifdef USE_SM16716 @@ -508,6 +498,13 @@ void LightInit(void) pinMode(pin[GPIO_PWM1 +i], OUTPUT); } } + // init sm16716 + pinMode(sm16716_pin_clk, OUTPUT); + digitalWrite(sm16716_pin_clk, LOW); + + pinMode(sm16716_pin_dat, OUTPUT); + digitalWrite(sm16716_pin_dat, LOW); + SM16716_Init(); } #endif // ifdef USE_SM16716 @@ -955,7 +952,6 @@ void LightAnimate(void) #endif // USE_ES2812 ************************************************************************ #ifdef USE_SM16716 else if (16 & light_type) { - SM16716_Update(cur_col[0], cur_col[1], cur_col[2]); for (uint8_t i = 3; i < light_subtype; i++) { if (pin[GPIO_PWM1 +i-3] < 99) { if (cur_col[i] > 0xFC) { @@ -967,6 +963,10 @@ void LightAnimate(void) analogWrite(pin[GPIO_PWM1 +i-3], bitRead(pwm_inverted, i-3) ? Settings.pwm_range - curcol : curcol); } } + if(cur_col[0] | cur_col[1] | cur_col[2]){ + SM16716_Init(); + } + SM16716_Update(cur_col[0], cur_col[1], cur_col[2]); } #endif // ifdef USE_SM16716 else if (light_type > LT_WS2812) { From 1c76991c7fb3c89d7ca5b1dd4349bd47a0e54e68 Mon Sep 17 00:00:00 2001 From: Colin Kuebler Date: Thu, 31 Jan 2019 13:28:38 -0500 Subject: [PATCH 7/8] Added sm16716 select to the pin definitions --- sonoff/language/bg-BG.h | 1 + sonoff/language/cs-CZ.h | 1 + sonoff/language/de-DE.h | 1 + sonoff/language/el-GR.h | 1 + sonoff/language/en-GB.h | 1 + sonoff/language/es-AR.h | 1 + sonoff/language/fr-FR.h | 1 + sonoff/language/he-HE.h | 1 + sonoff/language/hu-HU.h | 1 + sonoff/language/it-IT.h | 1 + sonoff/language/nl-NL.h | 1 + sonoff/language/pl-PL.h | 1 + sonoff/language/pt-BR.h | 1 + sonoff/language/pt-PT.h | 1 + sonoff/language/ru-RU.h | 1 + sonoff/language/sk-SK.h | 1 + sonoff/language/sv-SE.h | 1 + sonoff/language/tr-TR.h | 1 + sonoff/language/uk-UK.h | 1 + sonoff/language/zh-CN.h | 1 + sonoff/language/zh-TW.h | 1 + sonoff/sonoff_template.h | 12 +++++++----- 22 files changed, 28 insertions(+), 5 deletions(-) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 03c1b9f32..6c3f4556a 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index c87260f71..38c80d158 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 692c74e17..607c781da 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 81a017a0b..0a385a966 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 9644e8b4d..34dc71c4a 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index a2f8bcf8a..597be23db 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index b9fa0d423..41da8c895 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index 22f9677b5..96c14b0e5 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index b6dd5b55a..628a12770 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index fa3c0b533..90a967057 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index 684545acf..cb3c9913c 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index 8e677b554..1e50d2f6b 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index 1d708f072..f86addf8e 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index baa0e28a5..8d8f1bb8d 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index 19c09a7fc..9064b1407 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/sk-SK.h b/sonoff/language/sk-SK.h index e2551f9bc..b778d45a5 100644 --- a/sonoff/language/sk-SK.h +++ b/sonoff/language/sk-SK.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index 2b7b672a4..495564051 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index bdab28afb..d55b02899 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 4e3c255d5..8c6d82a10 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index d4ff8eba8..0d8a4012d 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "安" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 186c5bae3..cd1e503ec 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -546,6 +546,7 @@ #define D_SENSOR_MAX31855_DO "MAX31855 DO" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_SEL "SM16716 SEL" // Units #define D_UNIT_AMPERE "安" diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 809b0e390..0ad920b27 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -154,8 +154,9 @@ enum UserSelectablePins { GPIO_KEY2_INV_NP, GPIO_KEY3_INV_NP, GPIO_KEY4_INV_NP, - GPIO_SM16716_CLK, // SM16716 CLK - GPIO_SM16716_DAT, // SM16716 DAT + GPIO_SM16716_CLK, // SM16716 CLOCK + GPIO_SM16716_DAT, // SM16716 DATA + GPIO_SM16716_SEL, // SM16716 SELECT GPIO_SENSOR_END }; // Programmer selectable GPIO functionality offset by user selectable GPIOs @@ -222,7 +223,7 @@ const char kSensorNames[] PROGMEM = D_SENSOR_MAX31855_CS "|" D_SENSOR_MAX31855_CLK "|" D_SENSOR_MAX31855_DO "|" D_SENSOR_BUTTON "1i|" D_SENSOR_BUTTON "2i|" D_SENSOR_BUTTON "3i|" D_SENSOR_BUTTON "4i|" D_SENSOR_BUTTON "1in|" D_SENSOR_BUTTON "2in|" D_SENSOR_BUTTON "3in|" D_SENSOR_BUTTON "4in|" - D_SENSOR_SM16716_CLK "|" D_SENSOR_SM16716_DAT + D_SENSOR_SM16716_CLK "|" D_SENSOR_SM16716_DAT "|" D_SENSOR_SM16716_SEL ; /********************************************************************************************/ @@ -530,8 +531,9 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_MAX31855DO, // MAX31855 Serial interface #endif #ifdef USE_SM16716 - GPIO_SM16716_CLK, // SM16716 CLK - GPIO_SM16716_DAT, // SM16716 DAT + GPIO_SM16716_CLK, // SM16716 CLOCK + GPIO_SM16716_DAT, // SM16716 DATA + GPIO_SM16716_SEL, // SM16716 SELECT #endif // USE_SM16716 }; From 04f1ed1659240092e1cfc987d0f5e811c5310884 Mon Sep 17 00:00:00 2001 From: Colin Kuebler Date: Thu, 31 Jan 2019 17:17:01 -0500 Subject: [PATCH 8/8] Implemented sm16716 select If SM16716_SEL is specified, it will toggle it on/off depending on whether or not there is color data --- sonoff/xdrv_04_light.ino | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 0591da5bb..9cb22d698 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -371,6 +371,7 @@ void LightMy92x1Duty(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b, uint8_t dut uint8_t sm16716_pin_clk = 100; uint8_t sm16716_pin_dat = 100; +uint8_t sm16716_pin_sel = 100; void SM16716_SendBit(uint8_t v) { @@ -397,6 +398,23 @@ void SM16716_SendByte(uint8_t v) void SM16716_Update(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b) { + if (sm16716_pin_sel < 99) { + if (duty_r | duty_g | duty_b) { +#ifdef D_LOG_SM16716 + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "turning color on")); + AddLog(LOG_LEVEL_DEBUG); +#endif // D_LOG_SM16716 + digitalWrite(sm16716_pin_sel, HIGH); + delayMicroseconds(20); + SM16716_Init(); + } else { +#ifdef D_LOG_SM16716 + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "turning color off")); + AddLog(LOG_LEVEL_DEBUG); +#endif // D_LOG_SM16716 + digitalWrite(sm16716_pin_sel, LOW); + } + } #ifdef D_LOG_SM16716 snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Update; rgb=%02x%02x%02x"), @@ -409,10 +427,11 @@ void SM16716_Update(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b) // send 24-bit rgb data SM16716_SendByte(duty_r); SM16716_SendByte(duty_g); - SM16716_SendByte(duty_g); + SM16716_SendByte(duty_b); // send a 'do it' pulse // (if multiple chips are chained, each one processes the 1st '1rgb' 25-bit block and // passes on the rest, right until the one starting with 0) + //SM16716_Init(); SM16716_SendBit(0); SM16716_SendByte(0); SM16716_SendByte(0); @@ -423,6 +442,7 @@ bool SM16716_ModuleSelected(void) { sm16716_pin_clk = pin[GPIO_SM16716_CLK]; sm16716_pin_dat = pin[GPIO_SM16716_DAT]; + sm16716_pin_sel = pin[GPIO_SM16716_SEL]; #ifdef D_LOG_SM16716 snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "ModuleSelected; clk_pin=%d, dat_pin=%d)"), @@ -505,6 +525,11 @@ void LightInit(void) pinMode(sm16716_pin_dat, OUTPUT); digitalWrite(sm16716_pin_dat, LOW); + if (sm16716_pin_sel < 99) { + pinMode(sm16716_pin_sel, OUTPUT); + digitalWrite(sm16716_pin_sel, LOW); + } + SM16716_Init(); } #endif // ifdef USE_SM16716 @@ -963,9 +988,6 @@ void LightAnimate(void) analogWrite(pin[GPIO_PWM1 +i-3], bitRead(pwm_inverted, i-3) ? Settings.pwm_range - curcol : curcol); } } - if(cur_col[0] | cur_col[1] | cur_col[2]){ - SM16716_Init(); - } SM16716_Update(cur_col[0], cur_col[1], cur_col[2]); } #endif // ifdef USE_SM16716