From c6ddba8fd71dc849a3d3049820ec0c8a338bb81a Mon Sep 17 00:00:00 2001 From: Gabor Simon Date: Sat, 19 Jan 2019 14:37:22 +0000 Subject: [PATCH 01/89] Started SM16716 support --- sonoff/language/bg-BG.h | 2 + sonoff/language/cs-CZ.h | 2 + sonoff/language/de-DE.h | 2 + sonoff/language/en-GB.h | 2 + sonoff/language/es-AR.h | 2 + sonoff/language/fr-FR.h | 2 + sonoff/language/he-HE.h | 2 + sonoff/language/hu-HU.h | 2 + sonoff/language/it-IT.h | 2 + sonoff/language/nl-NL.h | 2 + sonoff/language/pl-PL.h | 2 + sonoff/language/pt-BR.h | 2 + sonoff/language/pt-PT.h | 2 + sonoff/language/ru-RU.h | 2 + sonoff/language/sk-SK.h | 2 + sonoff/language/sv-SE.h | 2 + sonoff/language/tr-TR.h | 2 + sonoff/language/uk-UK.h | 2 + sonoff/language/zh-CN.h | 2 + sonoff/language/zh-TW.h | 2 + sonoff/xdrv_20_sm16717.ino | 325 +++++++++++++++++++++++++++++++++++++ 21 files changed, 365 insertions(+) create mode 100644 sonoff/xdrv_20_sm16717.ino diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index d7d812385855..03c1b9f32737 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index e10ec2c4ff33..c87260f7105a 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index bea56f0f6140..692c74e1761e 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 4ac9186e512d..9644e8b4d29f 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index 8add1a3ba6b5..a2f8bcf8aaf9 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index aca69fac6ca5..b9fa0d423461 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index d4b41f0b56c8..22f9677b5fe2 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index ee071da54924..b6dd5b55ab2e 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 5ebef743d225..fa3c0b533ebf 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index 1235ab26d03c..684545acf5f6 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index 6327f87d0138..bc4dad5cad23 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index 8f1364771750..1d708f0726e0 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index f863a214823c..baa0e28a5f7e 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index 20f9a2d9fd07..19c09a7fc48d 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/sk-SK.h b/sonoff/language/sk-SK.h index 0edd9bea0823..e2551f9bc72f 100644 --- a/sonoff/language/sk-SK.h +++ b/sonoff/language/sk-SK.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index 21246a8f3a0e..2b7b672a45dd 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index 3ef7dd3f5242..bdab28afbcdb 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 59d9ab8b4ce3..4e3c255d5163 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "А" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index c64c1b5c3e4f..d4ff8eba8041 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "安" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 3560ddf34690..186c5bae3126 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "安" diff --git a/sonoff/xdrv_20_sm16717.ino b/sonoff/xdrv_20_sm16717.ino new file mode 100644 index 000000000000..98416019c3c8 --- /dev/null +++ b/sonoff/xdrv_20_sm16717.ino @@ -0,0 +1,325 @@ +/* + 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 D_LOG_SM16716 "SM16716: " +#define XDRV_20 20 + +#define CLK_USEC 10 // Clock interval in microseconds + +enum SM16716_Commands { + CMND_SM16716_POWER, CMND_SM16716_DIMMER, CMND_SM16716_COLOR }; + +const char k_SM16716_Commands[] PROGMEM = + D_CMND_POWER "|" D_CMND_DIMMER "|" D_CMND_COLOR ; + +uint8_t sm61716_pin_clk = 100; +uint8_t sm61716_pin_dat = 100; + +uint8_t sm61716_colour[3] = {0, 0, 0}; + +uint8_t sm61716_eff_red = 0; +uint8_t sm61716_eff_green = 0; +uint8_t sm61716_eff_blue = 0; + +int8_t sm61716_colour_preset = 0; + +/*********************************************************************************************/ + +void SM16716_SendBit(uint8_t v) +{ + digitalWrite(sm61716_pin_dat, v ? HIGH : LOW); + digitalWrite(sm61716_pin_clk, HIGH); + delayMicroseconds(CLK_USEC); + digitalWrite(sm61716_pin_clk, LOW); + delayMicroseconds(CLK_USEC); +} + +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(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Append_JSON;")); + AddLog(LOG_LEVEL_DEBUG); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"SM16716\":{\"Red\":%d,\"Green\":%d,\"Blue\":%d}"), mqtt_data, sm61716_colour[0], sm61716_colour[1], sm61716_colour[2]); +} + +/*********************************************************************************************/ +boolean SM16716_Show_State(void) +{ + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_COLOR "\":\"%02x%02x%02x\"}"), + sm61716_colour[0], sm61716_colour[1], sm61716_colour[2]); + return true; +} + +/*********************************************************************************************/ +void SM16716_Update() +{ + uint8_t eff_red, eff_green, eff_blue; + + if (Settings.power) { // any bit is ok for us + eff_red = (uint16_t)sm61716_colour[0] * Settings.light_dimmer / 100; + eff_green = (uint16_t)sm61716_colour[1] * Settings.light_dimmer / 100; + eff_blue = (uint16_t)sm61716_colour[2] * Settings.light_dimmer / 100; + } + else { + eff_red = eff_green = eff_blue = 0; + } + + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Update; pwr=%02x, rgb=%02x%02x%02x, dimmer=%d, eff=%02x%02x%02x"), + Settings.power, sm61716_colour[0], sm61716_colour[1], sm61716_colour[2], Settings.light_dimmer, eff_red, eff_green, eff_blue); + AddLog(LOG_LEVEL_DEBUG); + + if ((eff_red != sm61716_eff_red) || (eff_green != sm61716_eff_green) || (eff_blue != sm61716_eff_blue)) { + sm61716_eff_red = eff_red; + sm61716_eff_green = eff_green; + sm61716_eff_blue = eff_blue; + + SM16716_SendBit(1); + SM16716_SendByte(eff_red); + SM16716_SendByte(eff_green); + SM16716_SendByte(eff_blue); + } + SM16716_Show_State(); +} + +/*********************************************************************************************/ +boolean SM16716_ModuleSelected(void) +{ + sm61716_pin_clk = pin[GPIO_SM16716_CLK]; + sm61716_pin_dat = pin[GPIO_SM16716_DAT]; + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "ModuleSelected; clk_pin=%d, dat_pin=%d)"), sm61716_pin_clk, sm61716_pin_dat); + AddLog(LOG_LEVEL_DEBUG); + return (sm61716_pin_clk < 99) && (sm61716_pin_dat < 99); +} + +/*********************************************************************************************/ +boolean SM16716_Init(void) +{ + uint8_t t_init; + if (!SM16716_ModuleSelected()) + return false; + + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Init;")); + + pinMode(sm61716_pin_clk, OUTPUT); + digitalWrite(sm61716_pin_clk, LOW); + + pinMode(sm61716_pin_dat, OUTPUT); + digitalWrite(sm61716_pin_dat, LOW); + + AddLog(LOG_LEVEL_DEBUG); + for (t_init = 0; t_init < 50; ++t_init) + SM16716_SendBit(0); + + return true; +} + +boolean SM16716_Parse_RRGGBB(const char *data, int data_len) { + char component[3]; + char *endptr = NULL; + uint8_t candidate[3]; + int i; + + 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); + + if (data_len != 6) + return false; + + component[2] = '\0'; + + for (i = 0; i < 3; ++i) { + component[0] = data[0]; + component[1] = data[1]; + candidate[i] = (uint8_t)strtoul(component, &endptr, 16); + if (!endptr || *endptr) + return false; + data += 2; + } + + sm61716_colour[0] = candidate[0]; + sm61716_colour[1] = candidate[1]; + sm61716_colour[2] = candidate[2]; + return true; +} + +boolean SM16716_Parse_Colour(char *data, int data_len) { + /* NOTE: Very similar to 'LightColorEntry', but it's not reusable, because + * 'light_type' must be PWM, but then it won't parse the colour components. + * It's indeed more effective to not do the parsing when the current light + * type couldn't handle it, but enum LightTypes is not to be changed, so + * I can't implement new light types. + * + * If the parsing/handling of light attributes were separated from the + * technical details of actually sending it to the device, then only the + * device-specific parts should've been adapted, but unfortunately this is + * not the case here, so, here we go */ + + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Parse_Colour; data='%s', data_len=%d"), data, data_len); + AddLog(LOG_LEVEL_DEBUG); + + if (data_len < 3) { // Colour preset + switch (data[0]) { + case '+': + ++sm61716_colour_preset; + if (sm61716_colour_preset >= MAX_FIXED_COLOR) + sm61716_colour_preset = 0; + break; + + case '-': + --sm61716_colour_preset; + if (sm61716_colour_preset < 0) + sm61716_colour_preset = MAX_FIXED_COLOR - 1; + break; + + default: + { + char *endptr = NULL; + uint8_t candidate = (uint8_t)strtoul(data, &endptr, 10); + if (!endptr || *endptr || (candidate < 0) || (MAX_FIXED_COLOR <= candidate)) + return false; + sm61716_colour_preset = candidate; + } + break; + } + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Parse_Colour; preset=%d"), sm61716_colour_preset); + AddLog(LOG_LEVEL_DEBUG); + memcpy_P(sm61716_colour, &kFixedColor[sm61716_colour_preset], 3); + } + else if (data[0] == '#') { // #RRGGBB + if (!SM16716_Parse_RRGGBB(data + 1, data_len - 1)) + return false; + } + else if (SM16716_Parse_RRGGBB(data, data_len)) { // RRGGBB + } + else { // rrr,g,bb + uint8_t candidate[3]; + char *tok, *last, *endptr = NULL; + int i; + + for (i = 0; i < 3; ++i) { + tok = strtok_r(data, ",", &last); + if (!tok) + return false; + candidate[i] = (uint8_t)strtoul(tok, &endptr, 0); + if (!endptr || *endptr) + return false; + data = NULL; + } + tok = strtok_r(NULL, ",", &last); + if (tok) + return false; // junk at the end + sm61716_colour[0] = candidate[0]; + sm61716_colour[1] = candidate[1]; + sm61716_colour[2] = candidate[2]; + } + return true; +} + +/*********************************************************************************************/ +bool SM16716_Command(void) +{ + char command [CMDSZ]; + int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, k_SM16716_Commands); + + 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); + + switch (command_code) { + case CMND_SM16716_POWER: + SM16716_Update(); + return false; // Don't catch the event, only handle the change + + case CMND_SM16716_DIMMER: + SM16716_Update(); + return false; // Don't catch the event, only handle the change + + case CMND_SM16716_COLOR: + if (XdrvMailbox.data_len == 0) + return SM16716_Show_State(); + if (!SM16716_Parse_Colour(XdrvMailbox.data, XdrvMailbox.data_len)) + return false; + SM16716_Update(); + return true; + } + return false; // Unknown command +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ +boolean Xdrv20(byte function) +{ + //snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Xdrv20; function=%d, index=%d"), function, XdrvMailbox.index); + //AddLog(LOG_LEVEL_DEBUG); + + switch (function) { + case FUNC_MODULE_INIT: + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Entry; function=FUNC_MODULE_INIT")); + AddLog(LOG_LEVEL_DEBUG); + return SM16716_ModuleSelected(); + + case FUNC_INIT: + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Entry; function=FUNC_INIT")); + AddLog(LOG_LEVEL_DEBUG); + return SM16716_Init(); + + case FUNC_COMMAND: + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Entry; function=FUNC_COMMAND")); + AddLog(LOG_LEVEL_DEBUG); + return SM16716_Command(); + + case FUNC_SET_POWER: + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Entry; function=FUNC_SET_POWER, index=%02x, payload=%02x"), XdrvMailbox.index, XdrvMailbox.payload); + AddLog(LOG_LEVEL_DEBUG); + return false; + + case FUNC_SET_DEVICE_POWER: + 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); + return false; + + case FUNC_JSON_APPEND: + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Entry; function=FUNC_JSON_APPEND")); + AddLog(LOG_LEVEL_DEBUG); + SM16716_Append_JSON(); + break; + } + return false; +} + +#endif // USE_SM16716 + +// vim: set ft=c sw=2 ts=2 et: From 553738335278c8ef12446ae40b1e2237b65c562e Mon Sep 17 00:00:00 2001 From: Gabor Simon Date: Sat, 19 Jan 2019 22:28:58 +0000 Subject: [PATCH 02/89] sm16716 works via mqtt --- sonoff/sonoff_template.h | 37 +++++- sonoff/xdrv_20_sm16717.ino | 261 +++++++++++++++++++++---------------- 2 files changed, 181 insertions(+), 117 deletions(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 39eb8737d9b9..250bd9f46271 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -146,6 +146,8 @@ enum UserSelectablePins { GPIO_MAX31855CS, // MAX31855 Serial interface GPIO_MAX31855CLK, // MAX31855 Serial interface GPIO_MAX31855DO, // MAX31855 Serial interface + GPIO_SM16716_CLK, // SM16716 CLK + GPIO_SM16716_DAT, // SM16716 DAT GPIO_SENSOR_END }; // Programmer selectable GPIO functionality offset by user selectable GPIOs @@ -209,7 +211,8 @@ const char kSensorNames[] PROGMEM = D_SENSOR_SSPI_MISO "|" D_SENSOR_SSPI_MOSI "|" D_SENSOR_SSPI_SCLK "|" D_SENSOR_SSPI_CS "|" D_SENSOR_SSPI_DC "|" D_SENSOR_RF_SENSOR "|" D_SENSOR_AZ_TX "|" D_SENSOR_AZ_RX "|" - D_SENSOR_MAX31855_CS "|" D_SENSOR_MAX31855_CLK "|" D_SENSOR_MAX31855_DO; + D_SENSOR_MAX31855_CS "|" D_SENSOR_MAX31855_CLK "|" D_SENSOR_MAX31855_DO "|" + D_SENSOR_SM16716_CLK "|" D_SENSOR_SM16716_DAT; /********************************************************************************************/ @@ -281,6 +284,7 @@ enum SupportedModules { KA10, ZX2820, MI_DESK_LAMP, + SYF05, MAXMODULE }; /********************************************************************************************/ @@ -506,6 +510,10 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_MAX31855CLK, // MAX31855 Serial interface GPIO_MAX31855DO, // MAX31855 Serial interface #endif +#ifdef USE_SM16716 + GPIO_SM16716_CLK, // SM16716 CLK + GPIO_SM16716_DAT, // SM16716 DAT +#endif // USE_SM16716 }; const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { @@ -574,7 +582,8 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { PHILIPS, YTF_IR_BRIDGE, WITTY, // Development Devices - WEMOS + WEMOS, + SYF05 }; // Default module settings @@ -1774,6 +1783,30 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_ROT_A, // GPIO12 Rotary switch A pin GPIO_ROT_B, // GPIO13 Rotary switch B pin 0, 0, 0, 0 + }, + { "SYF05", // Sunyesmart SYF05 (a.k.a. Fcmila) = TYWE3S + SM16726 + // https://www.flipkart.com/fc-mila-bxav-xs-ad-smart-bulb/p/itmf85zgs45fzr7n + // https://docs.tuya.com/en/hardware/WiFi-module/wifi-e3s-module.html + // http://www.datasheet-pdf.com/PDF/SM16716-Datasheet-Sunmoon-932771 + GPIO_USER, // GPIO00 N.C. + 0, + GPIO_USER, // GPIO02 N.C. + 0, + GPIO_SM16716_CLK, // GPIO04 + GPIO_PWM1, // GPIO05 Cold White + // GPIO06 + // GPIO07 + // GPIO08 + 0, // GPIO09 + 0, // GPIO10 + // GPIO11 + GPIO_USER, // GPIO12 Warm White, not used on the LED panel + GPIO_USER, // GPIO13 N.C. (used as LED if you add it) + GPIO_SM16716_DAT, // GPIO14 + 0, // GPIO15 + GPIO_USER, // GPIO16 N.C. + GPIO_FLAG_ADC0 // ADC0 A0 Analog input +// + GPIO_FLAG_PULLUP // Allow input pull-up control } }; diff --git a/sonoff/xdrv_20_sm16717.ino b/sonoff/xdrv_20_sm16717.ino index 98416019c3c8..1779d1e7484b 100644 --- a/sonoff/xdrv_20_sm16717.ino +++ b/sonoff/xdrv_20_sm16717.ino @@ -18,6 +18,7 @@ */ #ifdef USE_SM16716 + /*********************************************************************************************\ * SM16716 - Controlling RGB over a synchronous serial line * @@ -25,134 +26,156 @@ * \*********************************************************************************************/ -#define D_LOG_SM16716 "SM16716: " #define XDRV_20 20 -#define CLK_USEC 10 // Clock interval in microseconds +// Enable this for debug logging +//#define D_LOG_SM16716 "SM16716: " enum SM16716_Commands { - CMND_SM16716_POWER, CMND_SM16716_DIMMER, CMND_SM16716_COLOR }; + CMND_SM16716_COLOR }; const char k_SM16716_Commands[] PROGMEM = - D_CMND_POWER "|" D_CMND_DIMMER "|" D_CMND_COLOR ; - -uint8_t sm61716_pin_clk = 100; -uint8_t sm61716_pin_dat = 100; + D_CMND_COLOR ; -uint8_t sm61716_colour[3] = {0, 0, 0}; +uint8_t sm16716_pin_clk = 100; +uint8_t sm16716_pin_dat = 100; -uint8_t sm61716_eff_red = 0; -uint8_t sm61716_eff_green = 0; -uint8_t sm61716_eff_blue = 0; +boolean sm16716_is_selected = false; +boolean sm16716_is_on = false; +uint8_t sm16716_color[3] = {0, 0, 0}; +int8_t sm16716_color_preset = 0; -int8_t sm61716_colour_preset = 0; /*********************************************************************************************/ - void SM16716_SendBit(uint8_t v) { - digitalWrite(sm61716_pin_dat, v ? HIGH : LOW); - digitalWrite(sm61716_pin_clk, HIGH); - delayMicroseconds(CLK_USEC); - digitalWrite(sm61716_pin_clk, LOW); - delayMicroseconds(CLK_USEC); + /* 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) + for (mask = 0x80; mask; mask >>= 1) { SM16716_SendBit(v & mask); + } } + /*********************************************************************************************/ void SM16716_Append_JSON(void) { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Append_JSON;")); - AddLog(LOG_LEVEL_DEBUG); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"SM16716\":{\"Red\":%d,\"Green\":%d,\"Blue\":%d}"), mqtt_data, sm61716_colour[0], sm61716_colour[1], sm61716_colour[2]); + 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]); } + /*********************************************************************************************/ boolean SM16716_Show_State(void) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_COLOR "\":\"%02x%02x%02x\"}"), - sm61716_colour[0], sm61716_colour[1], sm61716_colour[2]); + 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() { - uint8_t eff_red, eff_green, eff_blue; - - if (Settings.power) { // any bit is ok for us - eff_red = (uint16_t)sm61716_colour[0] * Settings.light_dimmer / 100; - eff_green = (uint16_t)sm61716_colour[1] * Settings.light_dimmer / 100; - eff_blue = (uint16_t)sm61716_colour[2] * Settings.light_dimmer / 100; +#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 { - eff_red = eff_green = eff_blue = 0; - } - - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Update; pwr=%02x, rgb=%02x%02x%02x, dimmer=%d, eff=%02x%02x%02x"), - Settings.power, sm61716_colour[0], sm61716_colour[1], sm61716_colour[2], Settings.light_dimmer, eff_red, eff_green, eff_blue); - AddLog(LOG_LEVEL_DEBUG); - - if ((eff_red != sm61716_eff_red) || (eff_green != sm61716_eff_green) || (eff_blue != sm61716_eff_blue)) { - sm61716_eff_red = eff_red; - sm61716_eff_green = eff_green; - sm61716_eff_blue = eff_blue; - - SM16716_SendBit(1); - SM16716_SendByte(eff_red); - SM16716_SendByte(eff_green); - SM16716_SendByte(eff_blue); + 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(); } + /*********************************************************************************************/ boolean SM16716_ModuleSelected(void) { - sm61716_pin_clk = pin[GPIO_SM16716_CLK]; - sm61716_pin_dat = pin[GPIO_SM16716_DAT]; - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "ModuleSelected; clk_pin=%d, dat_pin=%d)"), sm61716_pin_clk, sm61716_pin_dat); + 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); - return (sm61716_pin_clk < 99) && (sm61716_pin_dat < 99); +#endif // D_LOG_SM16716 + sm16716_is_selected = (sm16716_pin_clk < 99) && (sm16716_pin_dat < 99); + return sm16716_is_selected; } + /*********************************************************************************************/ boolean SM16716_Init(void) { uint8_t t_init; + if (!SM16716_ModuleSelected()) return false; - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Init;")); - - pinMode(sm61716_pin_clk, OUTPUT); - digitalWrite(sm61716_pin_clk, LOW); + pinMode(sm16716_pin_clk, OUTPUT); + digitalWrite(sm16716_pin_clk, LOW); - pinMode(sm61716_pin_dat, OUTPUT); - digitalWrite(sm61716_pin_dat, LOW); + pinMode(sm16716_pin_dat, OUTPUT); + digitalWrite(sm16716_pin_dat, LOW); - AddLog(LOG_LEVEL_DEBUG); for (t_init = 0; t_init < 50; ++t_init) SM16716_SendBit(0); return true; } + +/*********************************************************************************************/ boolean SM16716_Parse_RRGGBB(const char *data, int data_len) { char component[3]; char *endptr = NULL; uint8_t candidate[3]; int i; - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Parse_RRGGBB; data='%s', data_len=%d"), data, data_len); +#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) return false; @@ -168,39 +191,37 @@ boolean SM16716_Parse_RRGGBB(const char *data, int data_len) { data += 2; } - sm61716_colour[0] = candidate[0]; - sm61716_colour[1] = candidate[1]; - sm61716_colour[2] = candidate[2]; + sm16716_color[0] = candidate[0]; + sm16716_color[1] = candidate[1]; + sm16716_color[2] = candidate[2]; return true; } -boolean SM16716_Parse_Colour(char *data, int data_len) { - /* NOTE: Very similar to 'LightColorEntry', but it's not reusable, because - * 'light_type' must be PWM, but then it won't parse the colour components. - * It's indeed more effective to not do the parsing when the current light - * type couldn't handle it, but enum LightTypes is not to be changed, so - * I can't implement new light types. - * - * If the parsing/handling of light attributes were separated from the - * technical details of actually sending it to the device, then only the - * device-specific parts should've been adapted, but unfortunately this is - * not the case here, so, here we go */ - - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Parse_Colour; data='%s', data_len=%d"), data, data_len); + +/*********************************************************************************************/ +boolean 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) { // Colour preset + if (data_len < 3) { // a color preset switch (data[0]) { case '+': - ++sm61716_colour_preset; - if (sm61716_colour_preset >= MAX_FIXED_COLOR) - sm61716_colour_preset = 0; + ++sm16716_color_preset; + if (sm16716_color_preset >= MAX_FIXED_COLOR) + sm16716_color_preset = 0; break; case '-': - --sm61716_colour_preset; - if (sm61716_colour_preset < 0) - sm61716_colour_preset = MAX_FIXED_COLOR - 1; + --sm16716_color_preset; + if (sm16716_color_preset < 0) + sm16716_color_preset = MAX_FIXED_COLOR - 1; break; default: @@ -209,13 +230,17 @@ boolean SM16716_Parse_Colour(char *data, int data_len) { uint8_t candidate = (uint8_t)strtoul(data, &endptr, 10); if (!endptr || *endptr || (candidate < 0) || (MAX_FIXED_COLOR <= candidate)) return false; - sm61716_colour_preset = candidate; + sm16716_color_preset = candidate; } break; } - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Parse_Colour; preset=%d"), sm61716_colour_preset); +#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); - memcpy_P(sm61716_colour, &kFixedColor[sm61716_colour_preset], 3); +#endif // D_LOG_SM16716 + memcpy_P(sm16716_color, &kFixedColor[sm16716_color_preset], 3); } else if (data[0] == '#') { // #RRGGBB if (!SM16716_Parse_RRGGBB(data + 1, data_len - 1)) @@ -240,36 +265,32 @@ boolean SM16716_Parse_Colour(char *data, int data_len) { tok = strtok_r(NULL, ",", &last); if (tok) return false; // junk at the end - sm61716_colour[0] = candidate[0]; - sm61716_colour[1] = candidate[1]; - sm61716_colour[2] = candidate[2]; + 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); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Command; topic='%s', data_len=%d, data='%s', code=%d"), +#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_POWER: - SM16716_Update(); - return false; // Don't catch the event, only handle the change - - case CMND_SM16716_DIMMER: - SM16716_Update(); - return false; // Don't catch the event, only handle the change - case CMND_SM16716_COLOR: if (XdrvMailbox.data_len == 0) return SM16716_Show_State(); - if (!SM16716_Parse_Colour(XdrvMailbox.data, XdrvMailbox.data_len)) + if (!SM16716_Parse_Color(XdrvMailbox.data, XdrvMailbox.data_len)) return false; SM16716_Update(); return true; @@ -277,43 +298,54 @@ bool SM16716_Command(void) return false; // Unknown command } + /*********************************************************************************************\ * Interface \*********************************************************************************************/ boolean Xdrv20(byte function) { - //snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Xdrv20; function=%d, index=%d"), function, XdrvMailbox.index); - //AddLog(LOG_LEVEL_DEBUG); - - switch (function) { - case FUNC_MODULE_INIT: - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Entry; function=FUNC_MODULE_INIT")); - AddLog(LOG_LEVEL_DEBUG); + if (function == FUNC_MODULE_INIT) { return SM16716_ModuleSelected(); + } + + if (!sm16716_is_selected) + return false; + switch (function) { case FUNC_INIT: - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Entry; function=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: - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Entry; function=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); return SM16716_Command(); +#endif - case FUNC_SET_POWER: - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Entry; function=FUNC_SET_POWER, index=%02x, payload=%02x"), XdrvMailbox.index, XdrvMailbox.payload); - AddLog(LOG_LEVEL_DEBUG); - return false; - + //case FUNC_SET_POWER: case FUNC_SET_DEVICE_POWER: - 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); +#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); - return false; +#endif + sm16716_is_on = (XdrvMailbox.index != 0); + SM16716_Update(); + return false; // don't catch the event case FUNC_JSON_APPEND: - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Entry; function=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; } @@ -321,5 +353,4 @@ boolean Xdrv20(byte function) } #endif // USE_SM16716 - // vim: set ft=c sw=2 ts=2 et: From d9e0e9f89e0d913e5a158cad569485b0d4af796c Mon Sep 17 00:00:00 2001 From: Gabor Simon Date: Sun, 20 Jan 2019 21:18:28 +0000 Subject: [PATCH 03/89] Added missing definitions to Greek localisation header --- sonoff/language/el-GR.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 8a440253830c..81a017a0bcd6 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -544,6 +544,8 @@ #define D_SENSOR_MAX31855_CS "MAX31855 CS" #define D_SENSOR_MAX31855_CLK "MAX31855 CLK" #define D_SENSOR_MAX31855_DO "MAX31855 DO" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" // Units #define D_UNIT_AMPERE "A" From f833dd07ad02b2fd2c39d37cb95b864f0337c672 Mon Sep 17 00:00:00 2001 From: Gabor Simon Date: Mon, 21 Jan 2019 06:44:07 +0000 Subject: [PATCH 04/89] Enabled 'warm white' pwm in the module config, code comments added, coding style improved --- sonoff/sonoff_template.h | 4 +- sonoff/xdrv_20_sm16717.ino | 86 ++++++++++++++++++++++++++++---------- 2 files changed, 67 insertions(+), 23 deletions(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 250bd9f46271..ceca9685efb0 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -1800,10 +1800,10 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, // GPIO09 0, // GPIO10 // GPIO11 - GPIO_USER, // GPIO12 Warm White, not used on the LED panel + GPIO_PWM2, // GPIO12 Warm White GPIO_USER, // GPIO13 N.C. (used as LED if you add it) GPIO_SM16716_DAT, // GPIO14 - 0, // GPIO15 + 0, // GPIO15 wired to GND GPIO_USER, // GPIO16 N.C. GPIO_FLAG_ADC0 // ADC0 A0 Analog input // + GPIO_FLAG_PULLUP // Allow input pull-up control diff --git a/sonoff/xdrv_20_sm16717.ino b/sonoff/xdrv_20_sm16717.ino index 1779d1e7484b..7b367fc2f3bf 100644 --- a/sonoff/xdrv_20_sm16717.ino +++ b/sonoff/xdrv_20_sm16717.ino @@ -147,8 +147,9 @@ boolean SM16716_Init(void) { uint8_t t_init; - if (!SM16716_ModuleSelected()) + if (!SM16716_ModuleSelected()) { return false; + } pinMode(sm16716_pin_clk, OUTPUT); digitalWrite(sm16716_pin_clk, LOW); @@ -156,14 +157,18 @@ boolean SM16716_Init(void) pinMode(sm16716_pin_dat, OUTPUT); digitalWrite(sm16716_pin_dat, LOW); - for (t_init = 0; t_init < 50; ++t_init) + 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) + */ boolean SM16716_Parse_RRGGBB(const char *data, int data_len) { char component[3]; char *endptr = NULL; @@ -177,20 +182,30 @@ boolean SM16716_Parse_RRGGBB(const char *data, int data_len) { AddLog(LOG_LEVEL_DEBUG); #endif // D_LOG_SM16716 - if (data_len != 6) + 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) + 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]; @@ -210,61 +225,87 @@ boolean SM16716_Parse_Color(char *data, int data_len) { AddLog(LOG_LEVEL_DEBUG); #endif // D_LOG_SM16716 - if (data_len < 3) { // a color preset + 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 '+': + case '+': // advance to the next preset, handle wrap-around ++sm16716_color_preset; - if (sm16716_color_preset >= MAX_FIXED_COLOR) + if (sm16716_color_preset >= MAX_FIXED_COLOR) { sm16716_color_preset = 0; + } break; - case '-': + case '-': // return to the previous preset, handle wrap-around --sm16716_color_preset; - if (sm16716_color_preset < 0) + 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)) + 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] == '#') { // #RRGGBB - if (!SM16716_Parse_RRGGBB(data + 1, data_len - 1)) + 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; + } } - else if (SM16716_Parse_RRGGBB(data, data_len)) { // RRGGBB + // 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 { // rrr,g,bb + 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) + 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) + 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) - return false; // junk at the end + 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]; @@ -288,10 +329,12 @@ bool SM16716_Command(void) switch (command_code) { case CMND_SM16716_COLOR: - if (XdrvMailbox.data_len == 0) + if (XdrvMailbox.data_len == 0) { return SM16716_Show_State(); - if (!SM16716_Parse_Color(XdrvMailbox.data, XdrvMailbox.data_len)) + } + if (!SM16716_Parse_Color(XdrvMailbox.data, XdrvMailbox.data_len)) { return false; + } SM16716_Update(); return true; } @@ -308,8 +351,9 @@ boolean Xdrv20(byte function) return SM16716_ModuleSelected(); } - if (!sm16716_is_selected) + if (!sm16716_is_selected) { return false; + } switch (function) { case FUNC_INIT: From 4509019d646325a323fc6f3c5d1439da48a029de Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 28 Jan 2019 18:04:33 +0100 Subject: [PATCH 05/89] Fix valid button range check Fix valid button range check --- sonoff/support.ino | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sonoff/support.ino b/sonoff/support.ino index 91d1f76335b1..b2e74addc466 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -713,6 +713,12 @@ bool GetUsedInModule(uint8_t val, uint8_t *arr) if ((val >= GPIO_KEY1_NP) && (val < GPIO_KEY1_NP + MAX_KEYS)) { offset = -(GPIO_KEY1_NP - GPIO_KEY1); } + if ((val >= GPIO_KEY1_INV) && (val < GPIO_KEY1_INV + MAX_KEYS)) { + offset = -(GPIO_KEY1_INV - GPIO_KEY1); + } + if ((val >= GPIO_KEY1_INV_NP) && (val < GPIO_KEY1_INV_NP + MAX_KEYS)) { + offset = -(GPIO_KEY1_INV_NP - GPIO_KEY1); + } if ((val >= GPIO_SWT1) && (val < GPIO_SWT1 + MAX_SWITCHES)) { offset = (GPIO_SWT1_NP - GPIO_SWT1); From a770f54e9022a45b6a3b538f375ed4a23b293550 Mon Sep 17 00:00:00 2001 From: Gabor Simon Date: Tue, 29 Jan 2019 06:58:52 +0000 Subject: [PATCH 06/89] misplaced #endif fixed --- sonoff/xdrv_20_sm16717.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_20_sm16717.ino b/sonoff/xdrv_20_sm16717.ino index 7b367fc2f3bf..0016efc2ef05 100644 --- a/sonoff/xdrv_20_sm16717.ino +++ b/sonoff/xdrv_20_sm16717.ino @@ -369,8 +369,8 @@ boolean Xdrv20(byte function) snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SM16716 "Entry; function=FUNC_COMMAND")); AddLog(LOG_LEVEL_DEBUG); - return SM16716_Command(); #endif + return SM16716_Command(); //case FUNC_SET_POWER: case FUNC_SET_DEVICE_POWER: From c1012e32b51dab109e7dee68f689c9bd75bec195 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Tue, 29 Jan 2019 11:52:18 +0100 Subject: [PATCH 07/89] Add Note Not all devices can be supported. Focus sonoff --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 1d2ad635b53e..be308c54d0a2 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,9 @@ A Sonoff device is not a toy. It uses Mains AC so there is a danger of electrocu We don't take any responsibility nor liability for using this software nor for the installation or any tips, advice, videos, etc. given by any member of this site or any related site. +### Note +Please dont ask too add devices where you cant provide a basic working configuration (other than sonoff). Since there are thousands of them.. + ### Quick Install Download one of the released binaries from https://github.com/arendst/Sonoff-Tasmota/releases and flash it to your hardware as documented in the wiki. From a370f85a8bb5ed057deb14a446284024f0365dca Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 29 Jan 2019 13:37:59 +0100 Subject: [PATCH 08/89] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index be308c54d0a2..0184e7cc52d2 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ A Sonoff device is not a toy. It uses Mains AC so there is a danger of electrocu We don't take any responsibility nor liability for using this software nor for the installation or any tips, advice, videos, etc. given by any member of this site or any related site. ### Note -Please dont ask too add devices where you cant provide a basic working configuration (other than sonoff). Since there are thousands of them.. +Please do not ask to add devices where you can't provide a basic working configuration (other than sonoff). Since there are thousands of them.. ### Quick Install Download one of the released binaries from https://github.com/arendst/Sonoff-Tasmota/releases and flash it to your hardware as documented in the wiki. From e2d80403382c08d6ff06e104ddc7512dd8f9781a Mon Sep 17 00:00:00 2001 From: Gabor Simon Date: Wed, 30 Jan 2019 07:05:38 +0000 Subject: [PATCH 09/89] Type changed from boolean to bool applied to xdrv_20_sm16716.ino as well The upstream commit that changed the types in the interface: commit 304ac6fe44c9ba9aca4478036555e9eaa442dc9b Author: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon Jan 28 14:08:33 2019 +0100 6.4.1.12 code changes (byte/boolean) --- sonoff/xdrv_20_sm16717.ino | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sonoff/xdrv_20_sm16717.ino b/sonoff/xdrv_20_sm16717.ino index 0016efc2ef05..1dada4c9ca89 100644 --- a/sonoff/xdrv_20_sm16717.ino +++ b/sonoff/xdrv_20_sm16717.ino @@ -40,8 +40,8 @@ const char k_SM16716_Commands[] PROGMEM = uint8_t sm16716_pin_clk = 100; uint8_t sm16716_pin_dat = 100; -boolean sm16716_is_selected = false; -boolean sm16716_is_on = false; +bool sm16716_is_selected = false; +bool sm16716_is_on = false; uint8_t sm16716_color[3] = {0, 0, 0}; int8_t sm16716_color_preset = 0; @@ -83,7 +83,7 @@ void SM16716_Append_JSON(void) /*********************************************************************************************/ -boolean SM16716_Show_State(void) +bool SM16716_Show_State(void) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_COLOR "\":\"%02x%02x%02x\"}"), @@ -127,7 +127,7 @@ void SM16716_Update() /*********************************************************************************************/ -boolean SM16716_ModuleSelected(void) +bool SM16716_ModuleSelected(void) { sm16716_pin_clk = pin[GPIO_SM16716_CLK]; sm16716_pin_dat = pin[GPIO_SM16716_DAT]; @@ -143,7 +143,7 @@ boolean SM16716_ModuleSelected(void) /*********************************************************************************************/ -boolean SM16716_Init(void) +bool SM16716_Init(void) { uint8_t t_init; @@ -169,7 +169,7 @@ boolean SM16716_Init(void) /* Try to parse a string as 'RRGGBB' hex-encoded color value * Accept only exact match (i.e. there can be no leftover chars) */ -boolean SM16716_Parse_RRGGBB(const char *data, int data_len) { +bool SM16716_Parse_RRGGBB(const char *data, int data_len) { char component[3]; char *endptr = NULL; uint8_t candidate[3]; @@ -214,7 +214,7 @@ boolean SM16716_Parse_RRGGBB(const char *data, int data_len) { /*********************************************************************************************/ -boolean SM16716_Parse_Color(char *data, int data_len) { +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. */ @@ -345,7 +345,7 @@ bool SM16716_Command(void) /*********************************************************************************************\ * Interface \*********************************************************************************************/ -boolean Xdrv20(byte function) +bool Xdrv20(uint8_t function) { if (function == FUNC_MODULE_INIT) { return SM16716_ModuleSelected(); From cb13e8b05e6a486285e07d3490f44d8ba674361d Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 30 Jan 2019 14:33:20 +0100 Subject: [PATCH 10/89] Update xdrv_12_home_assistant.ino Minor gain in string length --- sonoff/xdrv_12_home_assistant.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index 80c5b4ebe1fd..6b6d1bff3885 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -67,7 +67,7 @@ const char HASS_DISCOVER_LIGHT_WHITE[] PROGMEM = "%s,\"whit_val_cmd_t\":\"%s\"," // cmnd/led2/White "\"whit_val_stat_t\":\"%s\"," // stat/led2/RESULT "\"white_value_scale\":100," // (No abbreviation defined) - "\"whit_val_tpl\":\"{{ value_json.Channel[3] }}\""; + "\"whit_val_tpl\":\"{{value_json.Channel[3]}}\""; const char HASS_DISCOVER_LIGHT_CT[] PROGMEM = "%s,\"clr_temp_cmd_t\":\"%s\"," // cmnd/led2/CT From 2c164a8b4b80d4c4d355bdfcbb84831f2c009011 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 30 Jan 2019 14:34:31 +0100 Subject: [PATCH 11/89] 6.4.1.13 Add boot loop offset 6.4.1.13 20190130 * Add command SetOption36 to control boot loop default restoration (#4645, #5063) --- sonoff/_changelog.ino | 5 ++++- sonoff/my_user_config.h | 1 + sonoff/settings.ino | 3 +++ sonoff/sonoff.h | 2 +- sonoff/sonoff.ino | 42 +++++++++++++++++++++-------------------- sonoff/sonoff_version.h | 2 +- 6 files changed, 32 insertions(+), 23 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 78200f2d8081..d35493110da3 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.4.1.12 20190128 +/* 6.4.1.13 20190130 + * Add command SetOption36 to control boot loop default restoration (#4645, #5063) + * + * 6.4.1.12 20190128 * Change code use of boolean to bool and byte to uint8_t * Change code uint8_t flags to bool flags * diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 83bbb7b6514b..c9c6505d5d03 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -54,6 +54,7 @@ #define SAVE_DATA 1 // [SaveData] Save changed parameters to Flash (0 = disable, 1 - 3600 seconds) #define SAVE_STATE 1 // [SetOption0] Save changed power state to Flash (0 = disable, 1 = enable) +#define BOOT_LOOP_OFFSET 1 // [SetOption36] Number of boot loops before starting restoring defaults (0 = disable, 1..200 = boot loops offset) // -- Wifi ---------------------------------------- #define WIFI_IP_ADDRESS "0.0.0.0" // [IpAddress1] Set to 0.0.0.0 for using DHCP or enter a static IP address diff --git a/sonoff/settings.ino b/sonoff/settings.ino index c1b84cafa595..8f510785862e 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -1027,6 +1027,9 @@ void SettingsDelta(void) Settings.interlock[0] = 0xFF; // Legacy support using all relays in one interlock group for (uint8_t i = 1; i < MAX_INTERLOCKS; i++) { Settings.interlock[i] = 0; } } + if (Settings.version < 0x0604010D) { + Settings.param[P_BOOT_LOOP_OFFSET] = BOOT_LOOP_OFFSET; + } Settings.version = VERSION; SettingsSave(1); diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 699d8c8196ed..9ba91f09185c 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -227,7 +227,7 @@ enum ButtonStates { PRESSED, NOT_PRESSED }; enum Shortcuts { SC_CLEAR, SC_DEFAULT, SC_USER }; -enum SettingsParmaIndex {P_HOLD_TIME, P_MAX_POWER_RETRY, P_TUYA_DIMMER_ID, P_MDNS_DELAYED_START, P_MAX_PARAM8}; // Max is PARAM8_SIZE (18) - SetOption32 until SetOption49 +enum SettingsParmaIndex {P_HOLD_TIME, P_MAX_POWER_RETRY, P_TUYA_DIMMER_ID, P_MDNS_DELAYED_START, P_BOOT_LOOP_OFFSET, P_MAX_PARAM8}; // Max is PARAM8_SIZE (18) - SetOption32 until SetOption49 enum DomoticzSensors {DZ_TEMP, DZ_TEMP_HUM, DZ_TEMP_HUM_BARO, DZ_POWER_ENERGY, DZ_ILLUMINANCE, DZ_COUNT, DZ_VOLTAGE, DZ_CURRENT, DZ_AIRQUALITY, DZ_MAX_SENSORS}; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 936f7930e78a..88e0ee3ce897 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2484,30 +2484,32 @@ void setup(void) Settings.flag2.emulation = 0; #endif // USE_EMULATION - // Disable functionality as possible cause of fast restart within BOOT_LOOP_TIME seconds (Exception, WDT or restarts) - if (RtcReboot.fast_reboot_count > 1) { // Restart twice - Settings.flag3.user_esp8285_enable = 0; // Disable ESP8285 Generic GPIOs interfering with flash SPI - if (RtcReboot.fast_reboot_count > 2) { // Restart 3 times - for (uint8_t i = 0; i < MAX_RULE_SETS; i++) { - if (bitRead(Settings.rule_stop, i)) { - bitWrite(Settings.rule_enabled, i, 0); // Disable rules causing boot loop + if (Settings.param[P_BOOT_LOOP_OFFSET]) { + // Disable functionality as possible cause of fast restart within BOOT_LOOP_TIME seconds (Exception, WDT or restarts) + if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET]) { // Restart twice + Settings.flag3.user_esp8285_enable = 0; // Disable ESP8285 Generic GPIOs interfering with flash SPI + if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +1) { // Restart 3 times + for (uint8_t i = 0; i < MAX_RULE_SETS; i++) { + if (bitRead(Settings.rule_stop, i)) { + bitWrite(Settings.rule_enabled, i, 0); // Disable rules causing boot loop + } } } - } - if (RtcReboot.fast_reboot_count > 3) { // Restarted 4 times - Settings.rule_enabled = 0; // Disable all rules - } - if (RtcReboot.fast_reboot_count > 4) { // Restarted 5 times - for (uint8_t i = 0; i < sizeof(Settings.my_gp); i++) { - Settings.my_gp.io[i] = GPIO_NONE; // Reset user defined GPIO disabling sensors + if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +2) { // Restarted 4 times + Settings.rule_enabled = 0; // Disable all rules } + if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +3) { // Restarted 5 times + for (uint8_t i = 0; i < sizeof(Settings.my_gp); i++) { + Settings.my_gp.io[i] = GPIO_NONE; // Reset user defined GPIO disabling sensors + } + } + if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +4) { // Restarted 6 times + Settings.module = SONOFF_BASIC; // Reset module to Sonoff Basic + // Settings.last_module = SONOFF_BASIC; + } + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_LOG_SOME_SETTINGS_RESET " (%d)"), RtcReboot.fast_reboot_count); + AddLog(LOG_LEVEL_DEBUG); } - if (RtcReboot.fast_reboot_count > 5) { // Restarted 6 times - Settings.module = SONOFF_BASIC; // Reset module to Sonoff Basic -// Settings.last_module = SONOFF_BASIC; - } - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_LOG_SOME_SETTINGS_RESET " (%d)"), RtcReboot.fast_reboot_count); - AddLog(LOG_LEVEL_DEBUG); } Format(mqtt_client, Settings.mqtt_client, sizeof(mqtt_client)); diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 83db36b91eab..099c8955ff13 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x0604010C +#define VERSION 0x0604010D #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" From 0007df121aeedcfcb59708fb4660fe448c2d96a2 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 30 Jan 2019 15:14:24 +0100 Subject: [PATCH 12/89] Update settings.ino Fix for new installs --- sonoff/settings.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 8f510785862e..03003d5c3d62 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -567,6 +567,7 @@ void SettingsDefaultSet2(void) // Settings.flag.value_units = 0; // Settings.flag.stop_flash_rotate = 0; Settings.save_data = SAVE_DATA; + Settings.param[P_BOOT_LOOP_OFFSET] = BOOT_LOOP_OFFSET; Settings.sleep = APP_SLEEP; if (Settings.sleep < 50) { Settings.sleep = 50; // Default to 50 for sleep, for now From 9825d6ffb6ff9e516e1b9c9dcd4c91a29088bde3 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 30 Jan 2019 16:27:17 +0100 Subject: [PATCH 13/89] Add resiliency to saved Settings Add resiliency to saved Settings (#5065) --- sonoff/_changelog.ino | 1 + sonoff/settings.ino | 45 ++++++++++++++++++++++++++++++------------- 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index d35493110da3..ab986d52251e 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,5 +1,6 @@ /* 6.4.1.13 20190130 * Add command SetOption36 to control boot loop default restoration (#4645, #5063) + * Add resiliency to saved Settings (#5065) * * 6.4.1.12 20190128 * Change code use of boolean to bool and byte to uint8_t diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 03003d5c3d62..13634d5417cb 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -447,31 +447,50 @@ void SettingsSave(uint8_t rotate) void SettingsLoad(void) { -/* Load configuration from eeprom or one of 7 slots below if first load does not stop_flash_rotate - */ + // Load configuration from eeprom or one of 7 slots below if first valid load does not stop_flash_rotate struct SYSCFGH { uint16_t cfg_holder; // 000 uint16_t cfg_size; // 002 unsigned long save_flag; // 004 } _SettingsH; + unsigned long save_flag = 0; - bool bad_crc = false; - settings_location = SETTINGS_LOCATION +1; + settings_location = 0; + uint32_t flash_location = SETTINGS_LOCATION +1; for (uint8_t i = 0; i < CFG_ROTATES; i++) { - settings_location--; - ESP.flashRead(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); - ESP.flashRead((settings_location -1) * SPI_FLASH_SEC_SIZE, (uint32*)&_SettingsH, sizeof(SYSCFGH)); - if (Settings.version > 0x06000000) { bad_crc = (Settings.cfg_crc != GetSettingsCrc()); } - if (Settings.flag.stop_flash_rotate || bad_crc || (Settings.cfg_holder != _SettingsH.cfg_holder) || (Settings.save_flag > _SettingsH.save_flag)) { - break; + flash_location--; + ESP.flashRead(flash_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); + + bool valid = false; + if (Settings.version > 0x06000000) { + valid = (Settings.cfg_crc == GetSettingsCrc()); + } else { + ESP.flashRead((flash_location -1) * SPI_FLASH_SEC_SIZE, (uint32*)&_SettingsH, sizeof(SYSCFGH)); + valid = (Settings.cfg_holder == _SettingsH.cfg_holder); + } + if (valid) { + if (Settings.save_flag > save_flag) { + save_flag = Settings.save_flag; + settings_location = flash_location; + if (Settings.flag.stop_flash_rotate) { + break; + } + } } + delay(1); } - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_CONFIG D_LOADED_FROM_FLASH_AT " %X, " D_COUNT " %d"), settings_location, Settings.save_flag); - AddLog(LOG_LEVEL_DEBUG); + if (settings_location > 0) { + ESP.flashRead(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_CONFIG D_LOADED_FROM_FLASH_AT " %X, " D_COUNT " %d"), + settings_location, Settings.save_flag); + AddLog(LOG_LEVEL_DEBUG); + } #ifndef BE_MINIMAL - if (bad_crc || (Settings.cfg_holder != (uint16_t)CFG_HOLDER)) { SettingsDefault(); } + if (!settings_location || (Settings.cfg_holder != (uint16_t)CFG_HOLDER)) { // Init defaults if cfg_holder differs from user settings in my_user_config.h + SettingsDefault(); + } settings_crc = GetSettingsCrc(); #endif // BE_MINIMAL From ed41370d24d9c94fa8bf1a820e6fb5495e1ca630 Mon Sep 17 00:00:00 2001 From: netpok Date: Wed, 30 Jan 2019 19:44:48 +0100 Subject: [PATCH 14/89] Add Tuya SP10 --- sonoff/sonoff_template.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 3385930f4eab..99f4d14580c3 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -292,6 +292,7 @@ enum SupportedModules { KA10, ZX2820, MI_DESK_LAMP, + SP10, MAXMODULE }; /********************************************************************************************/ @@ -572,6 +573,7 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { SK03_TUYA, DIGOO, KA10, + SP10, NEO_COOLCAM, // Socket Relay Devices OBI, OBI2, @@ -1793,6 +1795,25 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_ROT_A, // GPIO12 Rotary switch A pin GPIO_ROT_B, // GPIO13 Rotary switch B pin 0, 0, 0, 0 + }, + { "SP10", // Tuya SP10 (ESP8285 - BL0937 Energy Monitoring) + // https://www.aliexpress.com/item/Smart-Mini-WiFi-Plug-Outlet-Switch-Work-With-ForEcho-Alexa-Google-Home-Remote-EU-Smart-Socket/32963670423.html + 0, // GPIO00 + GPIO_PWM1, // GPIO01 Nightlight + 0, // GPIO02 + GPIO_KEY1, // GPIO03 Button + GPIO_HJL_CF, // GPIO04 BL0937 CF power + GPIO_NRG_CF1, // GPIO05 BL0937 CF1 voltage / current + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_NRG_SEL_INV, // GPIO12 BL0937 Sel output (1 = Voltage) + GPIO_LED1, // GPIO13 Blue LED - Link status + GPIO_REL1, // GPIO14 Relay 1 and red LED + 0, 0, 0 } }; From 3a43050d93fdf1afce468cd7f0c3c8bb15d374a0 Mon Sep 17 00:00:00 2001 From: Colin Kuebler Date: Wed, 30 Jan 2019 17:19:40 -0500 Subject: [PATCH 15/89] 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 936f7930e78a..fbf256134d76 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 9d8740ccb089..2dc098c80f5b 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 1dada4c9ca89..000000000000 --- 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 16/89] 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 2dc098c80f5b..90ef446ae16e 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 17/89] 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 90ef446ae16e..b60d0e64bb3a 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 18/89] 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 e050dc882354..809b0e390682 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 19/89] 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 b60d0e64bb3a..d58207331c85 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 20/89] 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 d58207331c85..0591da5bbb81 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 21/89] 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 03c1b9f32737..6c3f4556a768 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 c87260f7105a..38c80d158b64 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 692c74e1761e..607c781da581 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 81a017a0bcd6..0a385a96664d 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 9644e8b4d29f..34dc71c4a4e6 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 a2f8bcf8aaf9..597be23dbd77 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 b9fa0d423461..41da8c8956af 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 22f9677b5fe2..96c14b0e50ad 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 b6dd5b55ab2e..628a1277025e 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 fa3c0b533ebf..90a9670571fb 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 684545acf5f6..cb3c9913cc2e 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 8e677b5546d8..1e50d2f6b101 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 1d708f0726e0..f86addf8eb6e 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 baa0e28a5f7e..8d8f1bb8d54a 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 19c09a7fc48d..9064b14074c3 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 e2551f9bc72f..b778d45a5066 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 2b7b672a45dd..4955640514a0 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 bdab28afbcdb..d55b02899689 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 4e3c255d5163..8c6d82a10aba 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 d4ff8eba8041..0d8a4012dde9 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 186c5bae3126..cd1e503ec942 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 809b0e390682..0ad920b27227 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 12361df7053008242f325f43e8cd9c89e6fbe3f5 Mon Sep 17 00:00:00 2001 From: andrethomas Date: Thu, 31 Jan 2019 22:03:47 +0200 Subject: [PATCH 22/89] PN532: Fix regression --- sonoff/xsns_40_pn532_i2c.ino | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sonoff/xsns_40_pn532_i2c.ino b/sonoff/xsns_40_pn532_i2c.ino index 6718ffc4ec28..640e21c6ef6e 100644 --- a/sonoff/xsns_40_pn532_i2c.ino +++ b/sonoff/xsns_40_pn532_i2c.ino @@ -432,6 +432,7 @@ void PN532_ScanForTag(void) } if (pn532_i2c_function == 2) { #ifdef USE_PN532_DATA_RAW + memcpy(&card_data,&pn532_i2c_newdata,sizeof(card_data)); if (mifareclassic_WriteDataBlock(1, card_data)) { set_success = true; snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Data write successful"); @@ -441,13 +442,14 @@ void PN532_ScanForTag(void) #else bool IsAlphaNumeric = true; for (uint8_t i = 0;i < pn532_i2c_newdata_len;i++) { - if ((!isalpha(pn532_i2c_newdata[i])) || (!isdigit(pn532_i2c_newdata[i]))) { + if ((!isalpha(pn532_i2c_newdata[i])) && (!isdigit(pn532_i2c_newdata[i]))) { IsAlphaNumeric = false; } } if (IsAlphaNumeric) { + memcpy(&card_data,&pn532_i2c_newdata,pn532_i2c_newdata_len); + card_data[pn532_i2c_newdata_len] = '\0'; // Enforce null termination if (mifareclassic_WriteDataBlock(1, card_data)) { - memcpy(&card_data,&pn532_i2c_newdata,sizeof(card_data)); set_success = true; snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Data write successful"); AddLog(LOG_LEVEL_INFO); From 04f1ed1659240092e1cfc987d0f5e811c5310884 Mon Sep 17 00:00:00 2001 From: Colin Kuebler Date: Thu, 31 Jan 2019 17:17:01 -0500 Subject: [PATCH 23/89] 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 0591da5bbb81..9cb22d698fcf 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 From 8be3da63e1ba7bf58eec5481887e9a5abfc1e459 Mon Sep 17 00:00:00 2001 From: Kevin Baluha Date: Thu, 31 Jan 2019 20:13:23 -0700 Subject: [PATCH 24/89] add functionality to use multiple ads1115's on one i2cbus --- sonoff/xsns_12_ads1115.ino | 77 +++++++++++++++++++++++++++----------- 1 file changed, 55 insertions(+), 22 deletions(-) diff --git a/sonoff/xsns_12_ads1115.ino b/sonoff/xsns_12_ads1115.ino index f75baa3e8681..f2cfda028f07 100644 --- a/sonoff/xsns_12_ads1115.ino +++ b/sonoff/xsns_12_ads1115.ino @@ -119,7 +119,8 @@ CONFIG REGISTER uint8_t ads1115_type = 0; uint8_t ads1115_address; uint8_t ads1115_addresses[] = { ADS1115_ADDRESS_ADDR_GND, ADS1115_ADDRESS_ADDR_VDD, ADS1115_ADDRESS_ADDR_SDA, ADS1115_ADDRESS_ADDR_SCL }; - +uint8_t ads1115_found[] = {false,false,false,false}; +int16_t ads1115_values[4]; //Ads1115StartComparator(channel, ADS1115_REG_CONFIG_MODE_SINGLE); //Ads1115StartComparator(channel, ADS1115_REG_CONFIG_MODE_CONTIN); void Ads1115StartComparator(uint8_t channel, uint16_t mode) @@ -161,51 +162,83 @@ void Ads1115Detect(void) { uint16_t buffer; - if (ads1115_type) { - return; - } + //if (ads1115_type) { + //return; + //} for (uint8_t i = 0; i < sizeof(ads1115_addresses); i++) { ads1115_address = ads1115_addresses[i]; if (I2cValidRead16(&buffer, ads1115_address, ADS1115_REG_POINTER_CONVERT)) { Ads1115StartComparator(i, ADS1115_REG_CONFIG_MODE_CONTIN); ads1115_type = 1; + ads1115_found[i] = 1; snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "ADS1115", ads1115_address); AddLog(LOG_LEVEL_DEBUG); - break; + //break; } } } +void Ads1115GetValues(uint8_t address) { + uint8_t old_address = ads1115_address; + ads1115_address = address; + for (uint8_t i = 0; i < 4; i++) { + ads1115_values[i] = Ads1115GetConversion(i); + snprintf_P(log_data, sizeof(log_data), "Logging ADS1115 %02x (%i) = %i", address, i, ads1115_values[i] ); + AddLog(LOG_LEVEL_INFO); + } + ads1115_address = old_address; +} + +void Ads1115toJSON(char *comma_j) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s{"), mqtt_data,comma_j); + char *comma = (char*)""; + for (uint8_t i = 0; i < 4; i++) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"A%d\":%d"), mqtt_data, comma, i, ads1115_values[i]); + comma = (char*)","; + } + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); +} + +void Ads1115toString(uint8_t address) { + char label[15]; + snprintf_P(label, sizeof(label), "ADS1115(%02x)", address); + + for (uint8_t i = 0; i < 4; i++) { + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ANALOG, mqtt_data, label, i, ads1115_values[i]); + } +} + void Ads1115Show(bool json) { - if (ads1115_type) { - char stemp[10]; + if (!ads1115_type) + return; - uint8_t dsxflg = 0; - for (uint8_t i = 0; i < 4; i++) { - int16_t adc_value = Ads1115GetConversion(i); + if (json) + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"ADS1115\":["), mqtt_data); + char *comma = (char*)""; + + for (uint8_t t = 0; t < sizeof(ads1115_addresses); t++) { + snprintf_P(log_data, sizeof(log_data), "Logging ADS1115 %02x", ads1115_addresses[t]); + AddLog(LOG_LEVEL_INFO); + if (ads1115_found[t]) { + Ads1115GetValues(ads1115_addresses[t]); if (json) { - if (!dsxflg ) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"ADS1115\":{"), mqtt_data); - stemp[0] = '\0'; + Ads1115toJSON(comma); + comma = (char*)","; } - dsxflg++; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"A%d\":%d"), mqtt_data, stemp, i, adc_value); - strlcpy(stemp, ",", sizeof(stemp)); #ifdef USE_WEBSERVER - } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ANALOG, mqtt_data, "ADS1115", i, adc_value); + else { + Ads1115toString(ads1115_addresses[t]); + } #endif // USE_WEBSERVER } } + if (json) { - if (dsxflg) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s]"), mqtt_data); } - } - } } /*********************************************************************************************\ From ef40aff62a25f86a32888abe485743b6ba1779e9 Mon Sep 17 00:00:00 2001 From: Gabor Simon Date: Fri, 1 Feb 2019 04:37:22 +0000 Subject: [PATCH 25/89] Added SM16716_SEL pin to SYF05 template, enabled SM16716 support --- sonoff/my_user_config.h | 2 ++ sonoff/sonoff_template.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 83bbb7b6514b..92f2a6d86987 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -416,6 +416,8 @@ // #define USE_THEO_V2 // Add support for decoding Theo V2 sensors as documented on https://sidweb.nl using 434MHz RF sensor receiver (+1k4 code) // #define USE_ALECTO_V2 // Add support for decoding Alecto V2 sensors like ACH2010, WS3000 and DKW2012 weather stations using 868MHz RF sensor receiver (+1k7 code) +#define USE_SM16716 // Add support for SM16716 RGB LED controller + /*********************************************************************************************\ * Debug features are only supported in development branch \*********************************************************************************************/ diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 0ad920b27227..115e999cf588 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -1822,7 +1822,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, // GPIO10 // GPIO11 GPIO_PWM2, // GPIO12 Warm White - GPIO_USER, // GPIO13 N.C. (used as LED if you add it) + GPIO_SM16716_SEL, // GPIO13 GPIO_SM16716_DAT, // GPIO14 0, // GPIO15 wired to GND GPIO_USER, // GPIO16 N.C. From 25856c323a834cead4d412402ed77563adfc236f Mon Sep 17 00:00:00 2001 From: Colin Kuebler Date: Fri, 1 Feb 2019 00:59:53 -0500 Subject: [PATCH 26/89] Track sm16716 select pin state so we don't waste cycles continuously enabling/disabling color Added some comments; disabled sm16716 debug messages by default Removed delay after setting select pin; didn't seem to help anyway --- sonoff/xdrv_04_light.ino | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 9cb22d698fcf..4a6c21389222 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -367,11 +367,12 @@ 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; uint8_t sm16716_pin_sel = 100; +uint8_t sm16716_enabled = 0; void SM16716_SendBit(uint8_t v) { @@ -399,19 +400,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) { + uint8_t sm16716_should_enable = (duty_r | duty_g | duty_b); + if (!sm16716_enabled && sm16716_should_enable) { #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 + sm16716_enabled = 1; digitalWrite(sm16716_pin_sel, HIGH); - delayMicroseconds(20); + //delayMicroseconds(20); SM16716_Init(); - } else { + } + else if (sm16716_enabled && !sm16716_should_enable) { #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 + sm16716_enabled = 0; digitalWrite(sm16716_pin_sel, LOW); } } @@ -977,6 +982,7 @@ void LightAnimate(void) #endif // USE_ES2812 ************************************************************************ #ifdef USE_SM16716 else if (16 & light_type) { + // handle any PWM pins, skipping the first 3 values for sm16716 for (uint8_t i = 3; i < light_subtype; i++) { if (pin[GPIO_PWM1 +i-3] < 99) { if (cur_col[i] > 0xFC) { @@ -988,6 +994,7 @@ void LightAnimate(void) analogWrite(pin[GPIO_PWM1 +i-3], bitRead(pwm_inverted, i-3) ? Settings.pwm_range - curcol : curcol); } } + // handle sm16716 update SM16716_Update(cur_col[0], cur_col[1], cur_col[2]); } #endif // ifdef USE_SM16716 From de41a88becf7485e563ef3ea07a14a6cb9ba2a89 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 1 Feb 2019 14:05:55 +0100 Subject: [PATCH 27/89] Fix stop flash rotate functionality Fix stop flash rotate functionality --- sonoff/settings.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 13634d5417cb..55a73fc56a35 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -472,7 +472,7 @@ void SettingsLoad(void) if (Settings.save_flag > save_flag) { save_flag = Settings.save_flag; settings_location = flash_location; - if (Settings.flag.stop_flash_rotate) { + if (Settings.flag.stop_flash_rotate && (0 == i)) { // Stop only if eeprom area should be used and it is valid break; } } From edb0cf8f699c6e2a9f07cb2020ee0fac042ec8d7 Mon Sep 17 00:00:00 2001 From: netpok Date: Fri, 1 Feb 2019 14:54:35 +0100 Subject: [PATCH 28/89] Add WAGA life CHCZ02MB device --- sonoff/sonoff_template.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 99f4d14580c3..08d731b5eef7 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -293,6 +293,7 @@ enum SupportedModules { ZX2820, MI_DESK_LAMP, SP10, + WAGA, MAXMODULE }; /********************************************************************************************/ @@ -574,6 +575,7 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { DIGOO, KA10, SP10, + WAGA, NEO_COOLCAM, // Socket Relay Devices OBI, OBI2, @@ -1814,6 +1816,26 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_LED1, // GPIO13 Blue LED - Link status GPIO_REL1, // GPIO14 Relay 1 and red LED 0, 0, 0 + }, + { "WAGA CHCZ02MB", // WAGA life CHCZ02MB (HJL-01 Energy Monitoring) + // https://www.ebay.com/itm/332595697006 + GPIO_LED1, // GPIO00 Red LED + 0, // GPIO01 Serial TX + 0, // GPIO02 + GPIO_NRG_SEL_INV, // GPIO03 HJL-01 Sel output (1 = Voltage) + 0, // GPIO04 + GPIO_HJL_CF, // GPIO05 HJL-01 CF power + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_REL1, // GPIO12 Relay + GPIO_KEY1, // GPIO13 Button + GPIO_NRG_CF1, // GPIO14 HJL-01 CF1 voltage / current + GPIO_LED2, // GPIO15 Blue LED - Link status + 0, 0 } }; From 1bb22c06a6c15198a6f3ff6fa442e1eef2b8f107 Mon Sep 17 00:00:00 2001 From: netpok Date: Fri, 1 Feb 2019 14:55:33 +0100 Subject: [PATCH 29/89] Update SP10 descriptions --- sonoff/sonoff_template.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 08d731b5eef7..598d03e80475 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -1798,7 +1798,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_ROT_B, // GPIO13 Rotary switch B pin 0, 0, 0, 0 }, - { "SP10", // Tuya SP10 (ESP8285 - BL0937 Energy Monitoring) + { "SP10", // Tuya SP10 (BL0937 Energy Monitoring) // https://www.aliexpress.com/item/Smart-Mini-WiFi-Plug-Outlet-Switch-Work-With-ForEcho-Alexa-Google-Home-Remote-EU-Smart-Socket/32963670423.html 0, // GPIO00 GPIO_PWM1, // GPIO01 Nightlight @@ -1814,7 +1814,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { // GPIO11 (SD_CMD Flash) GPIO_NRG_SEL_INV, // GPIO12 BL0937 Sel output (1 = Voltage) GPIO_LED1, // GPIO13 Blue LED - Link status - GPIO_REL1, // GPIO14 Relay 1 and red LED + GPIO_REL1, // GPIO14 Relay and red LED 0, 0, 0 }, { "WAGA CHCZ02MB", // WAGA life CHCZ02MB (HJL-01 Energy Monitoring) From b927237aad9e6a828f77f934b7dc18d7c93a3451 Mon Sep 17 00:00:00 2001 From: netpok Date: Fri, 1 Feb 2019 15:01:45 +0100 Subject: [PATCH 30/89] Fix LED numbering --- sonoff/sonoff_template.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 598d03e80475..fa7d7d54656e 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -1819,7 +1819,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { }, { "WAGA CHCZ02MB", // WAGA life CHCZ02MB (HJL-01 Energy Monitoring) // https://www.ebay.com/itm/332595697006 - GPIO_LED1, // GPIO00 Red LED + GPIO_LED2, // GPIO00 Red LED 0, // GPIO01 Serial TX 0, // GPIO02 GPIO_NRG_SEL_INV, // GPIO03 HJL-01 Sel output (1 = Voltage) @@ -1834,7 +1834,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_REL1, // GPIO12 Relay GPIO_KEY1, // GPIO13 Button GPIO_NRG_CF1, // GPIO14 HJL-01 CF1 voltage / current - GPIO_LED2, // GPIO15 Blue LED - Link status + GPIO_LED1, // GPIO15 Blue LED - Link status 0, 0 } }; From 7e56dc538dda9eb2ea08a72ce265ed79e92dd6ed Mon Sep 17 00:00:00 2001 From: andrethomas Date: Fri, 1 Feb 2019 18:46:37 +0200 Subject: [PATCH 31/89] MHZ19: Allow enable and disable of ABC --- sonoff/settings.h | 17 +++++++++++++++-- sonoff/xsns_15_mhz19.ino | 37 ++++++++++++++++++++++++++----------- 2 files changed, 41 insertions(+), 13 deletions(-) diff --git a/sonoff/settings.h b/sonoff/settings.h index 83a26e311c7d..22f6d940d4d2 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -163,6 +163,20 @@ typedef union { }; } Mcp230xxCfg; +typedef union { + uint8_t data; + struct { + uint8_t spare0 : 1; + uint8_t spare1 : 1; + uint8_t spare2 : 1; + uint8_t spare3 : 1; + uint8_t spare4 : 1; + uint8_t spare5 : 1; + uint8_t spare6 : 1; + uint8_t mhz19b_abc_disable : 1; // Disable ABC (Automatic Baseline Correction for MHZ19(B) (0 = Enabled (default), 1 = Disabled with Sensor15 command) + }; +} SensorCfg1; + /* struct SYSCFG { unsigned long cfg_holder; // 000 Pre v6 header @@ -311,8 +325,7 @@ struct SYSCFG { uint8_t knx_CB_param[MAX_KNX_CB]; // 6EC Type of Output (set relay, toggle relay, reply sensor value) Mcp230xxCfg mcp230xx_config[16]; // 6F6 uint8_t mcp230xx_int_prio; // 716 - - uint8_t free_717[1]; // 717 + SensorCfg1 SensorBits1; // 717 On/Off settings used by Sensor Commands uint16_t mcp230xx_int_timer; // 718 uint8_t rgbwwTable[5]; // 71A diff --git a/sonoff/xsns_15_mhz19.ino b/sonoff/xsns_15_mhz19.ino index 509f9e0bc10b..747a8125f326 100644 --- a/sonoff/xsns_15_mhz19.ino +++ b/sonoff/xsns_15_mhz19.ino @@ -39,7 +39,10 @@ enum MhzFilterOptions {MHZ19_FILTER_OFF, MHZ19_FILTER_OFF_ALLSAMPLES, MHZ19_FILT /*********************************************************************************************\ * Source: http://www.winsen-sensor.com/d/files/infrared-gas-sensor/mh-z19b-co2-ver1_0.pdf * - * Automatic Baseline Correction (ABC logic function) + * Automatic Baseline Correction (ABC logic function) is enabled by default but may be disabled with command + * Sensor15 0 + * and enabled again with command + * Sensor15 1 * * ABC logic function refers to that sensor itself do zero point judgment and automatic calibration procedure * intelligently after a continuous operation period. The automatic calibration cycle is every 24 hours after powered on. @@ -52,10 +55,6 @@ enum MhzFilterOptions {MHZ19_FILTER_OFF, MHZ19_FILTER_OFF_ALLSAMPLES, MHZ19_FILT * Please do zero calibration timely, such as manual or commend calibration. \*********************************************************************************************/ -#define MHZ19_ABC_ENABLE 1 // Automatic Baseline Correction (0 = off, 1 = on (default)) - -/*********************************************************************************************/ - #include #ifndef CO2_LOW @@ -72,6 +71,9 @@ TasmotaSerial *MhzSerial; const char kMhzModels[] PROGMEM = "|B"; +const char ABC_ENABLED[] PROGMEM = "ABC is Enabled"; +const char ABC_DISABLED[] PROGMEM = "ABC is Enabled"; + enum MhzCommands { MHZ_CMND_READPPM, MHZ_CMND_ABCENABLE, MHZ_CMND_ABCDISABLE, MHZ_CMND_ZEROPOINT, MHZ_CMND_RESET, MHZ_CMND_RANGE_1000, MHZ_CMND_RANGE_2000, MHZ_CMND_RANGE_3000, MHZ_CMND_RANGE_5000 }; const uint8_t kMhzCommands[][4] PROGMEM = { // 2 3 6 7 @@ -88,7 +90,6 @@ const uint8_t kMhzCommands[][4] PROGMEM = { uint8_t mhz_type = 1; uint16_t mhz_last_ppm = 0; uint8_t mhz_filter = MHZ19_FILTER_OPTION; -bool mhz_abc_enable = MHZ19_ABC_ENABLE; bool mhz_abc_must_apply = false; float mhz_temperature = 0; @@ -218,7 +219,7 @@ void MhzEverySecond(void) uint16_t u = (mhz_response[6] << 8) | mhz_response[7]; if (15000 == u) { // During (and only ever at) sensor boot, 'u' is reported as 15000 - if (!mhz_abc_enable) { + if (Settings.SensorBits1.mhz19b_abc_disable) { // After bootup of the sensor the ABC will be enabled. // Thus only actively disable after bootup. mhz_abc_must_apply = true; @@ -235,7 +236,7 @@ void MhzEverySecond(void) if (0 == s || 64 == s) { // Reading is stable. if (mhz_abc_must_apply) { mhz_abc_must_apply = false; - if (mhz_abc_enable) { + if (!Settings.SensorBits1.mhz19b_abc_disable) { MhzSendCmd(MHZ_CMND_ABCENABLE); } else { MhzSendCmd(MHZ_CMND_ABCDISABLE); @@ -252,8 +253,8 @@ void MhzEverySecond(void) /*********************************************************************************************\ * Command Sensor15 * - * 0 - (Not implemented) ABC Off - * 1 - (Not implemented) ABC On + * 0 - ABC Off + * 1 - ABC On (Default) * 2 - Manual start = ABC Off * 3 - (Not implemented) Optional filter settings * 9 - Reset @@ -273,6 +274,16 @@ bool MhzCommandSensor(void) bool serviced = true; switch (XdrvMailbox.payload) { + case 0: + Settings.SensorBits1.mhz19b_abc_disable = true; + MhzSendCmd(MHZ_CMND_ABCDISABLE); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_DISABLED); + break; + case 1: + Settings.SensorBits1.mhz19b_abc_disable = false; + MhzSendCmd(MHZ_CMND_ABCENABLE); + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_ENABLED); + break; case 2: MhzSendCmd(MHZ_CMND_ZEROPOINT); snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_ZERO_POINT_CALIBRATION); @@ -298,7 +309,11 @@ bool MhzCommandSensor(void) snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_5000); break; default: - serviced = false; + if (!Settings.SensorBits1.mhz19b_abc_disable) { + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_ENABLED); + } else { + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_DISABLED); + } } return serviced; From 99b027852b145e27b93a7f7fdd3f933d95d01c22 Mon Sep 17 00:00:00 2001 From: Colin Kuebler Date: Fri, 1 Feb 2019 17:33:21 -0500 Subject: [PATCH 32/89] Fixed first color command failing; need to wait for chip to power up --- sonoff/xdrv_04_light.ino | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 4a6c21389222..ba12ac3db64d 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -408,7 +408,9 @@ void SM16716_Update(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b) #endif // D_LOG_SM16716 sm16716_enabled = 1; digitalWrite(sm16716_pin_sel, HIGH); - //delayMicroseconds(20); + // in testing I found it takes a minimum of ~380us to wake up the chip + // tested on a Merkury RGBW with an SM726EB + delayMicroseconds(400); SM16716_Init(); } else if (sm16716_enabled && !sm16716_should_enable) { From 817d0af598d887c7105e7d023f840d4f23762d87 Mon Sep 17 00:00:00 2001 From: Colin Kuebler Date: Fri, 1 Feb 2019 17:37:37 -0500 Subject: [PATCH 33/89] No need (and pointless) to call SM16716_Init until color updates, iff using sel pin --- sonoff/xdrv_04_light.ino | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index ba12ac3db64d..f65dd43da82b 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -535,9 +535,11 @@ void LightInit(void) if (sm16716_pin_sel < 99) { pinMode(sm16716_pin_sel, OUTPUT); digitalWrite(sm16716_pin_sel, LOW); + // no need to call SM16716_Init here, it will be called after sel goes HIGH + } else { + // no sel pin means you have an 'always on' chip, so init right away + SM16716_Init(); } - - SM16716_Init(); } #endif // ifdef USE_SM16716 else { From 4dc1d2f26004554a94df60b72f4a5b0aaa394b6f Mon Sep 17 00:00:00 2001 From: netpok Date: Sat, 2 Feb 2019 01:10:35 +0100 Subject: [PATCH 34/89] Fix led polarity --- sonoff/sonoff_template.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index fa7d7d54656e..1fbf50bf1b9a 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -1819,7 +1819,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { }, { "WAGA CHCZ02MB", // WAGA life CHCZ02MB (HJL-01 Energy Monitoring) // https://www.ebay.com/itm/332595697006 - GPIO_LED2, // GPIO00 Red LED + GPIO_LED2_INV, // GPIO00 Red LED 0, // GPIO01 Serial TX 0, // GPIO02 GPIO_NRG_SEL_INV, // GPIO03 HJL-01 Sel output (1 = Voltage) @@ -1834,7 +1834,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_REL1, // GPIO12 Relay GPIO_KEY1, // GPIO13 Button GPIO_NRG_CF1, // GPIO14 HJL-01 CF1 voltage / current - GPIO_LED1, // GPIO15 Blue LED - Link status + GPIO_LED1_INV, // GPIO15 Blue LED - Link status 0, 0 } }; From 6d19a9c998eb6a4da0692836d420628b96d6ccfc Mon Sep 17 00:00:00 2001 From: Colin Kuebler Date: Fri, 1 Feb 2019 19:28:16 -0500 Subject: [PATCH 35/89] Generalize the SYF05 a tiny bit so it can be easily adapted to similar bulbs --- sonoff/sonoff_template.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 80155a7c125d..e57cd54cfd68 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -1827,6 +1827,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, 0, 0 }, { "SYF05", // Sunyesmart SYF05 (a.k.a. Fcmila) = TYWE3S + SM16726 + // Also works with Merkury 904 RGBW Bulbs with 13 set to GPIO_SM16716_SEL // https://www.flipkart.com/fc-mila-bxav-xs-ad-smart-bulb/p/itmf85zgs45fzr7n // https://docs.tuya.com/en/hardware/WiFi-module/wifi-e3s-module.html // http://www.datasheet-pdf.com/PDF/SM16716-Datasheet-Sunmoon-932771 @@ -1834,17 +1835,17 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, GPIO_USER, // GPIO02 N.C. 0, - GPIO_SM16716_CLK, // GPIO04 - GPIO_PWM1, // GPIO05 Cold White + GPIO_SM16716_CLK, // GPIO04 SM16716 Clock + GPIO_PWM1, // GPIO05 White // GPIO06 // GPIO07 // GPIO08 0, // GPIO09 0, // GPIO10 // GPIO11 - GPIO_PWM2, // GPIO12 Warm White - GPIO_SM16716_SEL, // GPIO13 - GPIO_SM16716_DAT, // GPIO14 + GPIO_USER, // GPIO12 Alt. White on some devices + GPIO_USER, // GPIO13 SM16716 Select on some devices + GPIO_SM16716_DAT, // GPIO14 SM16716 Data 0, // GPIO15 wired to GND GPIO_USER, // GPIO16 N.C. GPIO_FLAG_ADC0 // ADC0 A0 Analog input From d7b8a6453dbea52a6006d1e2c62593365dd39376 Mon Sep 17 00:00:00 2001 From: Colin Kuebler Date: Fri, 1 Feb 2019 19:41:12 -0500 Subject: [PATCH 36/89] Added preprocessor constant for LT_SM16716 for improved code readability Note that this differs from other LT_* in that it's not an enum Ensure the SM16716 codepath is only taken when the top half of light_type is LT_SM16716 --- sonoff/sonoff.h | 2 ++ sonoff/sonoff.ino | 2 +- sonoff/xdrv_04_light.ino | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 9ba91f09185c..b54a32f3c0b8 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -168,6 +168,8 @@ typedef unsigned long power_t; // Power (Relay) type #define NEO_RGBW 5 // Neopixel RGBW leds #define NEO_GRBW 6 // Neopixel GRBW leds +#define LT_SM16716 16 // Lights that use SM16716 will have this bit set in light_type + #define MQTT_PUBSUBCLIENT 1 // Mqtt PubSubClient library #define MQTT_TASMOTAMQTT 2 // Mqtt TasmotaMqtt library based on esp-mqtt-arduino - soon obsolete #define MQTT_ESPMQTTARDUINO 3 // Mqtt esp-mqtt-arduino library by Ingo Randolf - obsolete but define is present for debugging purposes diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 694f7d4c9eac..7be59f746e9b 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2425,7 +2425,7 @@ void GpioInit(void) #ifdef USE_SM16716 if (SM16716_ModuleSelected()) { light_type += 3; - light_type |= 16; + light_type |= LT_SM16716; } #endif // ifdef USE_SM16716 if (!light_type) { diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index f65dd43da82b..bc4a9b91cb26 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -517,7 +517,7 @@ void LightInit(void) } #endif // USE_WS2812 ************************************************************************ #ifdef USE_SM16716 - else if (16 & light_type) { + else if (LT_SM16716 == light_type - light_subtype) { // init PWM for (uint8_t i = 0; i < light_subtype; i++) { Settings.pwm_value[i] = 0; // Disable direct PWM control @@ -985,7 +985,7 @@ void LightAnimate(void) } #endif // USE_ES2812 ************************************************************************ #ifdef USE_SM16716 - else if (16 & light_type) { + else if (LT_SM16716 == light_type - light_subtype) { // handle any PWM pins, skipping the first 3 values for sm16716 for (uint8_t i = 3; i < light_subtype; i++) { if (pin[GPIO_PWM1 +i-3] < 99) { From 35060dfa45cb84c248c1930f522dc51f0f23b41e Mon Sep 17 00:00:00 2001 From: Colin Kuebler Date: Fri, 1 Feb 2019 20:12:13 -0500 Subject: [PATCH 37/89] Measured impact of USE_SM16716 on binary filesize --- sonoff/my_user_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index c914e55679f9..d06b0c85454f 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -417,7 +417,7 @@ // #define USE_THEO_V2 // Add support for decoding Theo V2 sensors as documented on https://sidweb.nl using 434MHz RF sensor receiver (+1k4 code) // #define USE_ALECTO_V2 // Add support for decoding Alecto V2 sensors like ACH2010, WS3000 and DKW2012 weather stations using 868MHz RF sensor receiver (+1k7 code) -#define USE_SM16716 // Add support for SM16716 RGB LED controller +#define USE_SM16716 // Add support for SM16716 RGB LED controller (+0k7 code) /*********************************************************************************************\ * Debug features are only supported in development branch From 0c747a74991ed0c257c97809909673c6f55109ae Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 2 Feb 2019 15:16:35 +0100 Subject: [PATCH 38/89] Split module and GPIO ajax list Split module and GPIO ajax list --- sonoff/xdrv_01_webserver.ino | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 1974e9128238..daf45be9f782 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -145,28 +145,31 @@ const char HTTP_SCRIPT_CONSOL[] PROGMEM = "return false;" "}" ""; - const char HTTP_SCRIPT_MODULE1[] PROGMEM = "var os;" "function sk(s,g){" // s = value, g = id and name - "var o=os.replace(\"value='\"+s+\"'\",\"selected value='\"+s+\"'\");" + "var o=os.replace(/}1/g,\"