diff --git a/mos.yml b/mos.yml index 13ab6138..c267f247 100644 --- a/mos.yml +++ b/mos.yml @@ -122,6 +122,17 @@ config_schema: - ["ssw.name", "s", "", {}] - ["ssw.in_mode", "i", 0, {}] + #abstract for calibration type + - ["gains", "o", {title: "", abstract: true}] + - ["gains.avgain", "f", 4194304, {title: ""}] #default register values are 0x40000 + - ["gains.aigain", "f", 4194304, {title: ""}] + - ["gains.awgain", "f", 4194304, {title: ""}] + - ["gains.phcala", "f", 0, {title: "Sign magnitude 10bit value. register is 16 bit, value coming from cal seems to have sign in 22 bit (1 << 22)"}] + - ["gains.bvgain", "f", 4194304, {title: ""}] + - ["gains.bigain", "f", 4194304, {title: ""}] + - ["gains.bwgain", "f", 4194304, {title: ""}] + - ["gains.phcalb", "f", 0, {title: ""}] + build_vars: # BLE disabled for most models. MGOS_HAP_BLE: 0 @@ -697,7 +708,7 @@ conds: MGOS_ROOT_FS_TYPE: LFS MGOS_ROOT_FS_SIZE: 458752 ESP_IDF_EXTRA_PARTITION: "aux,0x55,0x00,0x3f0000,48K" - ESP_IDF_EXTRA_PARTITION_2: "shelly,data,0x88,0x3fc000,16K" + ESP_IDF_EXTRA_PARTITION_2: "shelly,data,0x88,0x3fc000,16K,encrypted" ESP_IDF_SDKCONFIG_OPTS: > ${build_vars.ESP_IDF_SDKCONFIG_OPTS} CONFIG_FREERTOS_UNICORE=y @@ -738,6 +749,15 @@ conds: - ["ssw2", "ssw", {title: "SSW2 settings"}] - ["ssw2.name", "Input 2"] + #factory config saved at 0x1000 in shelly partition + - ["factory", "o", {title: ""}] + - ["factory.batch", "s", "", {title: ""}] + - ["factory.model", "s", "", {title: ""}] + - ["factory.version", "i", 0, {title: ""}] + - ["factory.calib", "o", {title: "Factory calib settings"}] + - ["factory.calib.done", "b", false, {title: ""}] + - ["factory.calib.gains0", "gains", {title: ""}] + - when: build_vars.MODEL == "ShellyPlusI4" apply: name: PlusI4 diff --git a/src/ShellyPlus2PM/shelly_init.cpp b/src/ShellyPlus2PM/shelly_init.cpp index c46b8056..6f64557f 100644 --- a/src/ShellyPlus2PM/shelly_init.cpp +++ b/src/ShellyPlus2PM/shelly_init.cpp @@ -26,6 +26,8 @@ #include "shelly_temp_sensor_ntc.hpp" #include "shelly_temp_sensor_ow.hpp" +#include "esp_partition.h" + #include #include "shelly_hap_garage_door_opener.hpp" @@ -40,6 +42,58 @@ static std::vector> sensors; static struct mgos_ade7953 *s_ade7953 = NULL; +#define MGOS_ADE7953_REG_AIGAIN 0x380 +#define MGOS_ADE7953_REG_AVGAIN 0x381 +#define MGOS_ADE7953_REG_AWGAIN 0x382 +#define MGOS_ADE7953_REG_BVGAIN 0x38D +#define MGOS_ADE7953_REG_BWGAIN 0x38E +#define MGOS_ADE7953_REG_BIGAIN 0x38C + +static void ReadFactoryData(mgos_config *c) { + const char *label = "shelly"; + esp_partition_subtype_t subtype = ESP_PARTITION_SUBTYPE_ANY; + esp_partition_type_t type = ESP_PARTITION_TYPE_ANY; + + const esp_partition_t *part = esp_partition_find_first(type, subtype, label); + if (part == NULL) { + LOG(LL_INFO, ("Partition %s not found", label)); + return; + } + + size_t part_offset = 0x0; + size_t size = 0x2000; // map both "partitions" + spi_flash_mmap_handle_t out_handle; + const void *out_ptr; + + esp_err_t err = esp_partition_mmap( + part, part_offset, size, SPI_FLASH_MMAP_DATA, &out_ptr, &out_handle); + if (err) { + LOG(LL_INFO, ("Partition %s not mapped", label)); + return; + } + + // read first partition at 0x0 + const struct mg_str str = mg_mk_str_n((const char *) out_ptr, size); + bool succ = mgos_conf_parse_sub(str, mgos_config_get_schema(), + c); // TODO: merge into main cfg + if (!succ) { + LOG(LL_INFO, ("Partition %s not parsed", "factory data")); + return; + } + + // read escond partition at 0x1000 + void *ptr2 = (uint8_t *) out_ptr + 0x1000; + const struct mg_str str2 = mg_mk_str_n((const char *) ptr2, size); + succ = mgos_conf_parse_sub(str2, mgos_config_get_schema(), + c); // TODO: merge into main cfg + if (!succ) { + LOG(LL_INFO, ("Partition %s not parsed", "factory calib")); + return; + } + + spi_flash_munmap(out_handle); +} + static Status PowerMeterInit(std::vector> *pms) { const struct mgos_config_ade7953 ade7953_cfg = { .voltage_scale = .0000382602, @@ -52,21 +106,60 @@ static Status PowerMeterInit(std::vector> *pms) { .apower_scale_1 = (1 / 164.0), .aenergy_scale_0 = (1 / 25240.0), .aenergy_scale_1 = (1 / 25240.0), - .voltage_pga_gain = 0, - .current_pga_gain_0 = 0, - .current_pga_gain_1 = 0, + .voltage_pga_gain = 0, //MGOS_ADE7953_PGA_GAIN_2, + .current_pga_gain_0 = 0, //MGOS_ADE7953_PGA_GAIN_8, + .current_pga_gain_1 = 0, //MGOS_ADE7953_PGA_GAIN_8, }; - int reset_pin = 33; + mgos_config_factory *c = &(mgos_sys_config.factory); + + int reset_pin = -1; + if (c->model != NULL && strcmp(c->model, "SNSW-102P16EU") == 0) { + LOG(LL_INFO, ("model %s", c->model)); + LOG(LL_INFO, ("Newer revision detected")); + if (mgos_sys_config_get_i2c_sda_gpio() != 26) { + mgos_sys_config_set_i2c_sda_gpio(26); + } + reset_pin = 33; + } else { + if (mgos_sys_config_get_i2c_sda_gpio() != 33) { + mgos_sys_config_set_i2c_sda_gpio(33); + } + reset_pin = 0; // unknown? + } + // we need to reboot if we changed because i2c_global was already called; this + // messes up the downgrading process in original firmware + // + mgos_gpio_setup_output(reset_pin, 0); + mgos_usleep(10); mgos_gpio_setup_output(reset_pin, 1); + mgos_msleep(10); s_ade7953 = mgos_ade7953_create(mgos_i2c_get_global(), &ade7953_cfg); if (s_ade7953 == nullptr) { LOG(LL_INFO, ("Failed to init ADE7953")); + return mgos::Errorf(STATUS_UNAVAILABLE, "Failed to init ADE7953"); } + if (c->calib.done && false) { //do not use for now + LOG(LL_INFO, ("gains: av %f ai %f aw %f", c->calib.gains0.avgain, + c->calib.gains0.aigain, c->calib.gains0.awgain)); + mgos_ade7953_write_reg(s_ade7953, MGOS_ADE7953_REG_AVGAIN, + c->calib.gains0.avgain); + mgos_ade7953_write_reg(s_ade7953, MGOS_ADE7953_REG_AIGAIN, + c->calib.gains0.aigain); + mgos_ade7953_write_reg(s_ade7953, MGOS_ADE7953_REG_AWGAIN, + c->calib.gains0.awgain); + mgos_ade7953_write_reg(s_ade7953, MGOS_ADE7953_REG_BVGAIN, + c->calib.gains0.bvgain); + mgos_ade7953_write_reg(s_ade7953, MGOS_ADE7953_REG_BIGAIN, + c->calib.gains0.bigain); + mgos_ade7953_write_reg(s_ade7953, MGOS_ADE7953_REG_BWGAIN, + c->calib.gains0.bwgain); + } + Status st; std::unique_ptr pm1(new ADE7953PowerMeter(1, s_ade7953, 0)); if (!(st = pm1->Init()).ok()) return st; @@ -83,9 +176,20 @@ void CreatePeripherals(std::vector> *inputs, std::vector> *outputs, std::vector> *pms, std::unique_ptr *sys_temp) { + ReadFactoryData(&mgos_sys_config); + outputs->emplace_back(new OutputPin(1, 13, 1)); outputs->emplace_back(new OutputPin(2, 12, 1)); - auto *in1 = new InputPin(1, 5, 1, MGOS_GPIO_PULL_NONE, true); + + bool new_rev = false; + mgos_config_factory *c = &(mgos_sys_config.factory); + if (c->model != NULL && strcmp(c->model, "SNSW-102P16EU") == 0) { + new_rev = true; + } + + int pin1 = new_rev ? 5 : 2; + + auto *in1 = new InputPin(1, pin1, 1, MGOS_GPIO_PULL_NONE, true); in1->AddHandler(std::bind(&HandleInputResetSequence, in1, 4, _1, _2)); in1->Init(); inputs->emplace_back(in1); @@ -99,26 +203,33 @@ void CreatePeripherals(std::vector> *inputs, LOG(LL_INFO, ("Failed to init ADE7953: %s", s.c_str())); } - sys_temp->reset(new TempSensorSDNT1608X103F3950(35, 3.3f, 10000.0f)); + int adc_pin = new_rev ? 35 : 37; + sys_temp->reset(new TempSensorSDNT1608X103F3950(adc_pin, 3.3f, 10000.0f)); - int pin_out = 0; - int pin_in = 1; + // do not block uart when ESP_DBG_UART = 1 + // this should be gpio19? - if (DetectAddon(pin_in, pin_out)) { - s_onewire.reset(new Onewire(pin_in, pin_out)); - sensors = s_onewire->DiscoverAll(); - if (sensors.empty()) { - s_onewire.reset(); - sensors = DiscoverDHTSensors(pin_in, pin_out); - } - if (sensors.empty()) { - // No sensors detected, we assume to use addon as input for switch or - // closed/open sensor - auto *in2 = new InputPin(2, pin_in, 0, MGOS_GPIO_PULL_NONE, false); - in2->Init(); - inputs->emplace_back(in2); - } - } + // int pin_out = 0; + // int pin_in = 1; + + // if (DetectAddon(pin_in, pin_out)) { + // s_onewire.reset(new Onewire(pin_in, pin_out)); + // sensors = s_onewire->DiscoverAll(); + // if (sensors.empty()) { + // s_onewire.reset(); + // sensors = DiscoverDHTSensors(pin_in, pin_out); + // } + // if (sensors.empty()) { + // // No sensors detected, we assume to use addon as input for switch or + // // closed/open sensor + // auto *in2 = new InputPin(2, pin_in, 0, MGOS_GPIO_PULL_NONE, false); + // in2->Init(); + // inputs->emplace_back(in2); + // } + // } + // + + // InitSysBtn(new_rev ? BTN_GPIO : 27, BTN_DOWN); } void CreateComponents(std::vector> *comps,