From d4119fe54d46debbf494726a28228bb5ec537473 Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Mon, 4 Jun 2018 18:10:38 +0200 Subject: [PATCH] Add SnfBrdg EFM8BB1 fw tools 6.0.0a * Add support for uploading Sonoff Bridge firmware found in tools/fw_efm8bb1 folder build by Portisch using Web Gui File Upload (#2886) * Add command RfRaw to control Portisch firmware features --- lib/C2Programmer-1.0.0/README.md | 10 + lib/C2Programmer-1.0.0/keywords.txt | 19 + lib/C2Programmer-1.0.0/library.json | 15 + lib/C2Programmer-1.0.0/library.properties | 9 + lib/C2Programmer-1.0.0/src/c2.cpp | 649 ++++++++++++++++++ lib/C2Programmer-1.0.0/src/c2.h | 141 ++++ lib/C2Programmer-1.0.0/src/ihx.cpp | 71 ++ lib/C2Programmer-1.0.0/src/ihx.h | 39 ++ sonoff/_releasenotes.ino | 2 + sonoff/i18n.h | 3 +- sonoff/language/bg-BG.h | 4 + sonoff/language/cs-CZ.h | 4 + sonoff/language/de-DE.h | 4 + sonoff/language/el-GR.h | 4 + sonoff/language/en-GB.h | 4 + sonoff/language/es-AR.h | 4 + sonoff/language/fr-FR.h | 4 + sonoff/language/hu-HU.h | 4 + sonoff/language/it-IT.h | 4 + sonoff/language/nl-NL.h | 6 +- sonoff/language/pl-PL.h | 4 + sonoff/language/pt-BR.h | 4 + sonoff/language/pt-PT.h | 4 + sonoff/language/ru-RU.h | 4 + sonoff/language/uk-UK.h | 4 + sonoff/language/zh-CN.h | 4 + sonoff/language/zh-TW.h | 4 + sonoff/sonoff.h | 2 +- sonoff/sonoff.ino | 3 +- sonoff/user_config.h | 2 + sonoff/xdrv_02_webserver.ino | 115 +++- sonoff/xdrv_03_energy.ino | 2 +- sonoff/xdrv_04_light.ino | 2 +- sonoff/xdrv_05_irremote.ino | 2 +- sonoff/xdrv_06_snfbridge.ino | 272 +++++++- sonoff/xdrv_08_serial_bridge.ino | 2 +- sonoff/xdrv_09_timers.ino | 2 +- sonoff/xdrv_10_rules.ino | 2 +- sonoff/xdrv_11_knx.ino | 2 +- sonoff/xdrv_interface.ino | 1 + tools/fw_efm8bb1/RF_Bridge_00.hex | 406 +++++++++++ tools/fw_efm8bb1/RF_Bridge_iTead_Original.hex | 207 ++++++ 42 files changed, 2013 insertions(+), 37 deletions(-) create mode 100644 lib/C2Programmer-1.0.0/README.md create mode 100644 lib/C2Programmer-1.0.0/keywords.txt create mode 100644 lib/C2Programmer-1.0.0/library.json create mode 100644 lib/C2Programmer-1.0.0/library.properties create mode 100644 lib/C2Programmer-1.0.0/src/c2.cpp create mode 100644 lib/C2Programmer-1.0.0/src/c2.h create mode 100644 lib/C2Programmer-1.0.0/src/ihx.cpp create mode 100644 lib/C2Programmer-1.0.0/src/ihx.h create mode 100644 tools/fw_efm8bb1/RF_Bridge_00.hex create mode 100644 tools/fw_efm8bb1/RF_Bridge_iTead_Original.hex diff --git a/lib/C2Programmer-1.0.0/README.md b/lib/C2Programmer-1.0.0/README.md new file mode 100644 index 000000000..ff7295c8d --- /dev/null +++ b/lib/C2Programmer-1.0.0/README.md @@ -0,0 +1,10 @@ +# c2_prog_wifi +WiFi-enabled programmer for Silicon Labs microcontrollers using the C2 programmer protocol, and to act as a serial-wifi bridge. + +Designed to run in the Arduino environment for ESP8266 module: https://github.com/esp8266/Arduino + +New programs can be loaded sending .hex files through the web-interface. + +Everything is still alpha. Currently tested with EFM8BB10F2G-A-QFN20 and ESP-01 module: http://app.cear.ufpb.br/~lucas.hartmann/tag/efm8bb1/ + +LICENSE: GPLv3 or newer. \ No newline at end of file diff --git a/lib/C2Programmer-1.0.0/keywords.txt b/lib/C2Programmer-1.0.0/keywords.txt new file mode 100644 index 000000000..80066aed8 --- /dev/null +++ b/lib/C2Programmer-1.0.0/keywords.txt @@ -0,0 +1,19 @@ +####################################### +# Syntax Coloring Map for C2Programmer +# (esp8266) +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + + +####################################### +# Constants (LITERAL1) +####################################### + diff --git a/lib/C2Programmer-1.0.0/library.json b/lib/C2Programmer-1.0.0/library.json new file mode 100644 index 000000000..be074b8ed --- /dev/null +++ b/lib/C2Programmer-1.0.0/library.json @@ -0,0 +1,15 @@ +{ + "name": "C2Programmer", + "version": "1.0.0", + "keywords": [ + "C2", "io", "Programmer" + ], + "description": "Implementation of C2 programmer allowing update of Sonoff Bridge RF chip.", + "repository": + { + "type": "git", + "url": "https://github.com/lhartmann/c2_prog_wifi" + }, + "frameworks": "arduino", + "platforms": "espressif8266" +} diff --git a/lib/C2Programmer-1.0.0/library.properties b/lib/C2Programmer-1.0.0/library.properties new file mode 100644 index 000000000..affc5e809 --- /dev/null +++ b/lib/C2Programmer-1.0.0/library.properties @@ -0,0 +1,9 @@ +name=C2Programmer +version=1.0.0 +author=Lucas Hartmann +maintainer=Theo Arends +sentence=Implementation of C2 programmer allowing update of Sonoff Bridge RF chip. +paragraph= +category=Signal Input/Output +url= +architectures=esp8266 diff --git a/lib/C2Programmer-1.0.0/src/c2.cpp b/lib/C2Programmer-1.0.0/src/c2.cpp new file mode 100644 index 000000000..22bfbaedd --- /dev/null +++ b/lib/C2Programmer-1.0.0/src/c2.cpp @@ -0,0 +1,649 @@ +#include "c2.h" + +///////////////////////////////////////////// +// Nothing should need change on this file // +///////////////////////////////////////////// + +// Times in microseconds +#define T_RD (20+5) +#define T_SD ( 2+5) + +// Layer 0: Bit shifter +static bool c2_bit(bool b) { + C2D(b); + // C2_DELAY_US(1); + C2CK(0); + // C2_DELAY_US(1); + b = C2D(); + C2CK(1); + return b; +} + +// Layer 1: C2D Register read/write +void c2_address_write(uint8_t address) { +#ifdef C2_DEBUG + Serial.print("AW"); + Serial.println(address, HEX); +#endif + // start + c2_bit(true); + C2D_enable(true); + + // instruction + c2_bit(1); + c2_bit(1); + + // Address + for (int i = 0; i < 8; ++i) { + c2_bit(address & 1); + address >>= 1; + } + + // Stop + C2D_enable(false); + c2_bit(1); +} + +uint8_t c2_address_read() { + // start + c2_bit(true); + C2D_enable(true); + + // instruction + c2_bit(0); + c2_bit(1); + + // Change C2D direction + C2D_enable(false); + c2_bit(0); + + // Address + uint8_t a = 0, m = 1; + for (int i = 0; i < 8; ++i) { + if (c2_bit(a & 1)) { + a |= m; + } + m <<= 1; + } + + // Stop is implied +#ifdef C2_DEBUG + Serial.print("AR"); + Serial.println(a, HEX); +#endif + return a; +} + +uint8_t c2_data_write(uint32_t d, uint8_t bytes) { +#ifdef C2_DEBUG + Serial.print("DW"); + Serial.println(d, HEX); +#endif + + // start + c2_bit(true); + C2D_enable(true); + + // instruction + c2_bit(1); + c2_bit(0); + + // Length + bytes--; + c2_bit(bytes & 1); + c2_bit(bytes & 2); + bytes++; + + // Data + for (int i = 0; i < 8 * bytes; ++i) { + c2_bit(d & 1); + d >>= 1; + } + + // Reverse C2D direction + C2D_enable(false); + c2_bit(0); + + // Wait + uint8_t to = 128; + while (!c2_bit(0)) if (!--to) return C2_SHIFT_TIMEOUT; + + // Stop + //c2_bit(0); implied + + return C2_SUCCESS; +} + +uint8_t c2_data_read(uint32_t &d, uint8_t bytes) { + // start + c2_bit(true); + C2D_enable(true); + + // instruction + c2_bit(0); + c2_bit(0); + + // Length + bytes--; + c2_bit(bytes & 1); + c2_bit(bytes & 2); + bytes++; + + // Reverse C2D direction + C2D_enable(false); + c2_bit(0); + + // Wait + uint8_t to = 128; + while (!c2_bit(0)) if (!--to) return C2_SHIFT_TIMEOUT; + + // Data + d = 0; + uint32_t m = 1; + for (int i = 0; i < 8 * bytes; ++i) { + if (c2_bit(d & 1)) { + d |= m; + } + m <<= 1; + } + + // Stop is implied +#ifdef C2D_DEBUG + Serial.print("DR"); + Serial.println(d, HEX); +#endif + return C2_SUCCESS; +} + +// Layer 2: Operations +#define C2_POLL_INBUSY() { \ + uint16_t to = 1000; \ + uint8_t a; \ + while (1) { \ + a = c2_address_read(); \ + if (a == 0xFF) return C2_BROKEN_LINK; \ + if (~a & C2_INBUSY) break; \ + if (--to == 0) return C2_POLL_TIMEOUT; \ + C2_DELAY_MS(1); \ + }; \ + } + +#define C2_POLL_OUTREADY() { \ + uint16_t to = 10000; \ + uint8_t a; \ + while (1) { \ + a = c2_address_read(); \ + if (a == 0xFF) return C2_BROKEN_LINK; \ + if (a & C2_OUTREADY) break; \ + if (--to == 0) return C2_POLL_TIMEOUT; \ + C2_DELAY_MS(1); \ + }; \ + } + +#define C2_DATA_WRITE_AND_CHECK(v, s) { \ + uint8_t r = c2_data_write(v, s); \ + if (r != C2_SUCCESS) return r; \ + } + +#define C2_DATA_READ_AND_CHECK(v, s) { \ + uint8_t r = c2_data_read(v, s); \ + if (r != C2_SUCCESS) return r; \ + } + +#define C2_EXPECT_DATA(value) { \ + uint8_t d; \ + C2_DATA_READ_AND_CHECK(d, 1); \ + if (d != (value)) return C2_CMD_ERROR; \ + } + +uint8_t c2_reset() { + C2CK(false); + C2_DELAY_US(T_RD); + C2CK(true); + C2_DELAY_US(T_SD); + return C2_SUCCESS; +} + +uint8_t c2_programming_init() { + c2_reset(); + c2_address_write(C2FPCTL); + C2_DATA_WRITE_AND_CHECK(C2FPCTL_ENABLE0, 1); + C2_DATA_WRITE_AND_CHECK(C2FPCTL_CORE_HALT, 1); + C2_DATA_WRITE_AND_CHECK(C2FPCTL_ENABLE1, 1) + C2_DELAY_MS(21); + return C2_SUCCESS; +} + +uint8_t c2_block_write(uint32_t address, uint8_t *data, uint8_t len) { + // 1. Perform an Address Write with a value of FPDAT + c2_address_write(C2FPDAT); + + // 2. Perform a Data Write with the Block Write command. + C2_DATA_WRITE_AND_CHECK(C2FPDAT_BLOCK_WRITE, 1); + + // 3. Poll on InBusy using Address Read until the bit clears. + C2_POLL_INBUSY(); + + // 4. Poll on OutReady using Address Read until the bit set. + C2_POLL_OUTREADY(); + + // 5. Perform a Data Read instruction. A value of 0x0D is okay. + C2_EXPECT_DATA(0x0D); + + // 6. Perform a Data Write with the high byte of the address. + C2_DATA_WRITE_AND_CHECK(address >> 8, 1); + + // 7. Poll on InBusy using Address Read until the bit clears. + C2_POLL_INBUSY(); + + // 8. Perform a Data Write with the low byte of the address. + C2_DATA_WRITE_AND_CHECK(address & 255, 1); + + // 9. Poll on InBusy using Address Read until the bit clears. + C2_POLL_INBUSY(); + + // 10. Perform a Data Write with the length. + C2_DATA_WRITE_AND_CHECK(len, 1); + + // 12a. Repeat steps 11 and 12 for each byte specified by the length field. + uint8_t i = 0; + do { + // 11. Poll on InBusy using Address Read until the bit clears. + C2_POLL_INBUSY(); + + // 12. Perform a Data Write with the data. This will write the data to the flash. + C2_DATA_WRITE_AND_CHECK(data[i], 1); + } while (++i != len); + + // 13. Poll on OutReady using Address Read until the bit set. + C2_POLL_OUTREADY(); + + // 14. Perform a Data Read instruction. A value of 0x0D is okay. write to an EPROM block: + C2_EXPECT_DATA(0x0D); + + return C2_SUCCESS; +} + +uint8_t c2_eeprom_write(uint32_t address, uint8_t *data, uint8_t len) { + // 1. Write 0x04 to the FPCTL register. + c2_address_write(C2FPCTL); + C2_DATA_WRITE_AND_CHECK(0x04, 1); + + // 2. Write 0x40 to EPCTL. + c2_address_write(C2EPCTL); + C2_DATA_WRITE_AND_CHECK(0x40, 1); + + // 3. Write 0x58 to EPCTL. + C2_DATA_WRITE_AND_CHECK(0x58, 1); + + // 4. Write the high byte of the address to EPADDRH. + c2_address_write(C2EPADDRH); + C2_DATA_WRITE_AND_CHECK(address >> 8, 1); + + // 5. Write the low byte of the address to address EPADDRL. + c2_address_write(C2EPADDRL); + C2_DATA_WRITE_AND_CHECK(address, 1); + + // 6. Perform an Address Write with a value of EPDAT. + c2_address_write(C2EPDAT); + + // 7. Turn on VPP. + + // 8. Wait for the VPP settling time. + + // 10a. Repeat steps 9 and 10 until all bytes are written. + uint8_t i = 0; + do { + // 9. Write the data to the device using a Data Write. + C2_DATA_WRITE_AND_CHECK(data[i], 1); + + // 10. Perform Address Read instructions until the value returned is not 0x80 and the EPROM is no longer busy. + C2_POLL_INBUSY(); + } while (++i != len); + + // 12. Turn off VPP. Note that VPP can only be applied for a maximum lifetime amount, and this value is specified in the device data sheet. + + // 13. Write 0x40 to EPCTL. + c2_address_write(C2EPCTL); + C2_DATA_WRITE_AND_CHECK(0x40, 1); + + // 14. Write 0x00 to EPCTL. + C2_DATA_WRITE_AND_CHECK(0x00, 1); + + // 15. Write 0x02 to FPCTL. + c2_address_write(C2FPCTL); + C2_DATA_WRITE_AND_CHECK(0x02, 1); + + // 16. Write 0x04 to FPCTL. + C2_DATA_WRITE_AND_CHECK(0x04, 1); + + // 17. Write 0x01 to FPCTL. + C2_DATA_WRITE_AND_CHECK(0x01, 1); + + return C2_SUCCESS; +} + +uint8_t c2_block_read(uint32_t address, uint8_t *data, uint8_t len) { + // 1. Perform an Address Write with a value of FPDAT. + c2_address_write(C2FPDAT); + + // 2. Perform a Data Write with the Block Read command. + C2_DATA_WRITE_AND_CHECK(C2FPDAT_BLOCK_READ, 1); + + // 3. Poll on InBusy using Address Read until the bit clears. + C2_POLL_INBUSY(); + + // 4. Poll on OutReady using Address Read until the bit set. + C2_POLL_OUTREADY(); + + // 5. Perform a Data Read instruction. A value of 0x0D is okay. + C2_EXPECT_DATA(0x0D); + + // 6. Perform a Data Write with the high byte of the address. + C2_DATA_WRITE_AND_CHECK(address >> 8, 1); + + // 7. Poll on InBusy using Address Read until the bit clears. + C2_POLL_INBUSY(); + + // 8. Perform a Data Write with the low byte of the address. + C2_DATA_WRITE_AND_CHECK(address, 1); + + // 9. Poll on InBusy using Address Read until the bit clears. + C2_POLL_INBUSY(); + + // 10. Perform a Data Write with the length. + C2_DATA_WRITE_AND_CHECK(len, 1); + + // 11. Poll on InBusy using Address Read until the bit clears. + C2_POLL_INBUSY(); + + // 12. Poll on OutReady using Address Read until the bit set. + C2_POLL_OUTREADY(); + + // 13. Read FPI Command Status. Abort if Status != 0x0D. + C2_EXPECT_DATA(0x0D); + + // 15a. Repeat step 14 and 15 for each byte specified by the length field. + uint8_t i = 0; + do { + // 14. Poll on OutReady using Address Read until the bit set. + C2_POLL_OUTREADY(); + + // 15. Perform a Data Read instruction. This will read the data from the flash. + C2_DATA_READ_AND_CHECK(data[i], 1); + } while (++i != len); + + return C2_SUCCESS; +} + +uint8_t c2_eeprom_read(uint32_t address, uint8_t *data, uint8_t len) { + // 1. Write 0x04 to the FPCTL register. + c2_address_write(C2FPCTL); + C2_DATA_WRITE_AND_CHECK(0x04, 1); + + // 2. Write 0x00 to EPCTL. + c2_address_write(C2EPCTL); + C2_DATA_WRITE_AND_CHECK(0x00, 1); + + // 3. Write 0x58 to EPCTL. + C2_DATA_WRITE_AND_CHECK(0x58, 1); + + // 4. Write the high byte of the address to EPADDRH. + c2_address_write(C2EPADDRH); + C2_DATA_WRITE_AND_CHECK(address >> 8, 1); + + // 5. Write the low byte of the address to address EPADDRL. + c2_address_write(C2EPADDRL); + C2_DATA_WRITE_AND_CHECK(address, 1); + + // 6. Perform an Address Write with a value of EPDAT. + c2_address_write(C2EPDAT); + + // 9. Repeat steps 7 and 8 until all bytes are read. + uint8_t i = 0; + do { + // 7.1. Perform an Address Write operation with a value of EPSTAT. + c2_address_write(C2EPSTAT); + + // 7.2. Perform a Data Read operation and check the bits of the EPSTAT register. + uint8_t err; + C2_DATA_READ_AND_CHECK(err, 1); + if (err & C2EPSTAT_ERROR) return C2_CMD_ERROR; + + // 7.3. Perform an Address Write operation with a value of EPDAT. + c2_address_write(C2EPDAT); + + // 7. Perform Address Read instructions until the value returned is not 0x80 and the EPROM is no longer busy. + C2_POLL_INBUSY(); + + // 8.1. Perform an Address Write operation with a value of EPSTAT. + c2_address_write(C2EPSTAT); + + // 8.2. Perform a Data Read operation and check the ERROR bit in the EPSTAT register. + C2_DATA_READ_AND_CHECK(err, 1); + if (err & C2EPSTAT_ERROR) return C2_CMD_ERROR; + + // 8.3. Perform an Address Write operation with a value of EPDAT. + C2_DATA_WRITE_AND_CHECK(C2EPDAT, 1); + + // 8. Read the byte using the Data Read instruction. + C2_DATA_READ_AND_CHECK(data[i], 1); + } while (++i != len); + + // 10. Write 0x40 to EPCTL. + c2_address_write(C2EPCTL); + C2_DATA_WRITE_AND_CHECK(0x40, 1); + + // 11. Write 0x00 to EPCTL. + C2_DATA_WRITE_AND_CHECK(0x00, 1); + + // 12. Write 0x02 to FPCTL. + c2_address_write(C2FPCTL); + C2_DATA_WRITE_AND_CHECK(0x02, 1); + + // 13. Write 0x04 to FPCTL. + C2_DATA_WRITE_AND_CHECK(0x04, 1); + + // 14. Write 0x01 to FPCTL. + C2_DATA_WRITE_AND_CHECK(0x01, 1); + + return C2_SUCCESS; +} + +uint8_t c2_page_erase(uint8_t page) { + // 1. Perform an Address Write with a value of FPDAT. + c2_address_write(C2FPDAT); + + // 2. Perform a Data Write with the Page Erase command. + c2_data_write(C2FPDAT_FLASH_PAGE_ERASE, 1); + + // 3. Poll on InBusy using Address Read until the bit clears. + C2_POLL_INBUSY(); + + // 4. Poll on OutReady using Address Read until the bit set. + C2_POLL_OUTREADY(); + + // 5. Perform a Data Read instruction. A value of 0x0D is okay. + C2_EXPECT_DATA(0x0D); + + // 6. Perform a Data Write with the page number. + c2_data_write(page, 1); + + // 7. Poll on InBusy using Address Read until the bit clears. + C2_POLL_INBUSY(); + + // 8. Poll on OutReady using Address Read until the bit clears. + C2_POLL_OUTREADY(); + + // 9. Perform a Data Read instruction. A value of 0x0D is okay. + C2_EXPECT_DATA(0x0D); + + // 10. Perform a Data Write with the a value of 0x00. + c2_data_write(0x00, 1); + + // 11. Poll on InBusy using Address Read until the bit clears. + C2_POLL_INBUSY(); + + // 12. Poll on OutReady using Address Read until the bit set. + C2_POLL_OUTREADY(); + + // 13. Perform a Data Read instruction. A value of 0x0D is okay. + C2_EXPECT_DATA(0x0D); + + return C2_SUCCESS; +} + +uint8_t c2_device_erase() { + // 1. Perform an Address Write with a value of FPDAT. + c2_address_write(C2FPDAT); + + // 2. Perform a Data Write with the Device Erase command. + C2_DATA_WRITE_AND_CHECK(C2FPDAT_DEVICE_ERASE, 1); + + // 3. Poll on InBusy using Address Read until the bit clears. + C2_POLL_INBUSY(); + + // 4. Poll on OutReady using Address Read until the bit set. + C2_POLL_OUTREADY(); + + // 5. Perform a Data Read instruction. A value of 0x0D is okay. + C2_EXPECT_DATA(0x0D); + + // 6. Perform a Data Write with a value of 0xDE. + C2_DATA_WRITE_AND_CHECK(0xDE, 1); + + // 7. Poll on InBusy using Address Read until the bit clears. + C2_POLL_INBUSY(); + + // 8. Perform a Data Write with a value of 0xAD. + C2_DATA_WRITE_AND_CHECK(0xAD, 1); + + // 9. Poll on InBusy using Address Read until the bit clears. + C2_POLL_INBUSY(); + + // 10. Perform a Data Write with a value of 0xA5. + C2_DATA_WRITE_AND_CHECK(0xA5, 1); + + // 11. Poll on InBusy using Address Read until the bit clears. + C2_POLL_INBUSY(); + + // 12. Poll on OutReady using Address Read until the bit set. + C2_POLL_OUTREADY(); + + // 13. Perform a Data Read instruction. A value of 0x0D is okay. + C2_EXPECT_DATA(0x0D); + + return C2_SUCCESS; +} + +uint8_t c2_sfr_write_non_paged(uint8_t address, uint8_t data) { + // 1. Write the SFR address to the device using the Address Write instruction. + c2_address_write(address); + + // 2. Write the SFR value to the device using the Data Write instruction. + C2_DATA_WRITE_AND_CHECK(data, 1); + + return C2_SUCCESS; +} + +uint8_t c2_sfr_write_paged(uint8_t address, uint8_t data) { + // 1. Perform an Address Write with a value of FPDAT. + c2_address_write(C2FPDAT); + + // 2. Write the Direct Write command (0x0A) using a Data Write + C2_DATA_WRITE_AND_CHECK(C2FPDAT_DIRECT_WRITE, 1); + + // 3. Poll InBusy until the data is processed by the PI. + C2_POLL_INBUSY(); + + // 4. Poll OutReady it sets to 1. + C2_POLL_OUTREADY(); + + // 5. Perform a Data Read to ensure a return value of 0x0D (no errors). + C2_EXPECT_DATA(0x0D); + + // 6. Perform a Data Write with a value of the SFR address. + C2_DATA_WRITE_AND_CHECK(address, 1); + + // 7. Poll InBusy until the data is processed by the PI. + C2_POLL_INBUSY(); + + // 8. Perform a Data Write with a value of 0x01. + C2_DATA_WRITE_AND_CHECK(0x01, 1); + + // 9. Poll InBusy until the data is processed by the PI. + C2_POLL_INBUSY(); + + // 10. Perform a Data Write with the new SFR value. + C2_DATA_WRITE_AND_CHECK(data, 1); + + // 11. Poll InBusy until the data is processed by the PI. + C2_POLL_INBUSY(); + + return C2_SUCCESS; +} + +// 4.6. Reading from an SFR +// To read from an SFR on a device that does not have SFR paging: +uint8_t c2_sfr_read_non_paged(uint8_t address, uint8_t &v) { + // 1. Write the SFR address to the device using the Address Write instruction. + c2_address_write(address); + + // 2. Read the SFR value from the device using the Data Read instruction. + C2_DATA_READ_AND_CHECK(v, 1); + + return C2_SUCCESS; +} + +// For devices with SFR paging, direct reads through the PI using the Direct Read command are recommended to ensure the SFR Page is managed properly. +// To read an SFR from a device with SFR paging: +uint8_t c2_sfr_read_paged(uint8_t address, uint8_t &v) { + // 1. Perform an Address Write with a value of FPDAT. + c2_address_write(C2FPDAT); + + // 2. Write the Direct Read command (0x09) using a Data Write. + C2_DATA_WRITE_AND_CHECK(C2FPDAT_DIRECT_READ, 1); + + // 3. Poll InBusy until the data is processed by the PI. + C2_POLL_INBUSY(); + + // 4. Poll OutReady until it sets to 1. + C2_POLL_OUTREADY(); + + // 5. Perform a Data Read to ensure a return value of 0x0D (no errors). + C2_EXPECT_DATA(0x0D); + + // 6. Perform a Data Write with a value of the SFR address. + C2_DATA_WRITE_AND_CHECK(address, 1); + + // 7. Poll InBusy until the data is processed by the PI. + C2_POLL_INBUSY(); + + // 8. Perform a Data Write with a value of 0x01. + C2_DATA_WRITE_AND_CHECK(0x01, 1); + + // 9. Poll InBusy until the data is processed by the PI. + C2_POLL_INBUSY(); + + // 10. Poll OutReady until it sets to 0. + C2_POLL_OUTREADY(); + + // 11. Read the SFR value from the device using the Data Read instruction. + C2_DATA_READ_AND_CHECK(v, 1); + + return C2_SUCCESS; +} + +const char *c2_print_status_by_name(uint8_t ch) { + switch (ch) { + case C2_SUCCESS: return "Success"; + case C2_SHIFT_TIMEOUT: return "Shift wait timeout error"; + case C2_POLL_TIMEOUT: return "Register poll timeout error"; + case C2_CMD_ERROR: return "In-command error"; + case C2_BROKEN_LINK: return "Broken link, address read failed"; + default: return "unknownl error"; + } +} + +// This is to enforce arduino-like formatting in kate +// kate: space-indent on; indent-width 2; mixed-indent off; indent-mode cstyle; diff --git a/lib/C2Programmer-1.0.0/src/c2.h b/lib/C2Programmer-1.0.0/src/c2.h new file mode 100644 index 000000000..bc744d02f --- /dev/null +++ b/lib/C2Programmer-1.0.0/src/c2.h @@ -0,0 +1,141 @@ +#ifndef C2_H +#define C2_H + +#include +#include + +//////////////////////////////// +// Hardware Abstraction Layer // +//////////////////////////////// + +// Rewrite these for your hardware + +#define PIN_C2CK 4 +#define PIN_C2D 5 + +// Set C2CK state +inline void C2CK(bool ck) { + digitalWrite(PIN_C2CK, ck); +} + +// get C2CK state +inline bool C2CK() { + return digitalRead(PIN_C2CK); +} + +// Set C2D state +inline void C2D(bool d) { + digitalWrite(PIN_C2D, d); +} + +// Get C2D state +inline bool C2D() { + return digitalRead(PIN_C2D); +} + +// Enable/disable C2D output butter +inline void C2D_enable(bool oe) { + if (oe) pinMode(PIN_C2D, OUTPUT); + else pinMode(PIN_C2D, INPUT); +} + +// Delay functions +#define C2_DELAY_US(n) delayMicroseconds(n) +#define C2_DELAY_MS(n) delay(n) + +//////////////////////////////////////////// +// Nothing should need change from now on // +//////////////////////////////////////////// + +// Exceptions: +#define C2_SUCCESS 0x00 // Compare for success +#define C2_ERROR 0xFF // Mask for all errors +#define C2_TIMEOUT 0x03 // Mask for timeouts +#define C2_SHIFT_TIMEOUT 0x01 // Shift wait +#define C2_POLL_TIMEOUT 0x02 // Register poll +#define C2_CMD_ERROR 0x04 // In-command Error +#define C2_BROKEN_LINK 0x08 // Address read returned 0xFF, comms disabled + +// Register Addresses +#define C2DEVID 0x00 +#define C2REVID 0x01 +#define C2FPCTL 0x02 +#define C2FPDAT 0xB4 + +#define C2EPCTL 0x00 +#define C2EPDAT 0x00 +#define C2EPDAT 0x00 +#define C2EPADDRH 0x00 +#define C2EPADDRL 0x00 +#define C2EPSTAT 0x00 + +// Commands for FPCTL register +#define C2FPCTL_ENABLE0 0x02 +#define C2FPCTL_CORE_HALT 0x04 +#define C2FPCTL_ENABLE1 0x01 + +// Commands for FPDAT register +#define C2FPDAT_DEVICE_ERASE 0x03 +#define C2FPDAT_FLASH_BLOCK_READ 0x06 +#define C2FPDAT_BLOCK_WRITE 0x07 +#define C2FPDAT_FLASH_PAGE_ERASE 0x08 +#define C2FPDAT_BLOCK_READ 0x06 +#define C2FPDAT_GET_VERSION 0x01 +#define C2FPDAT_GET_DERIVATIVE 0x02 +#define C2FPDAT_DIRECT_READ 0x09 +#define C2FPDAT_DIRECT_WRITE 0x0A +#define C2FPDAT_INDIRECT_READ 0x0B +#define C2FPDAT_INDIRECT_WRITE 0x0C + +// Commands for EPCTL register +#define C2EPCTL_ENABLE0 0x40 +#define C2EPCTL_ENABLE1 0x58 + +// EPSTAT status bits +#define C2EPSTAT_WLOCK 0x80 +#define C2EPSTAT_RLOCK 0x40 +#define C2EPSTAT_ERROR 0x01 + +// 'Address read' status bits +#define C2_FLBUSY 0x08 +#define C2_EEBUSY C2_FLBUSY +#define C2_EEERROR 0x04 +#define C2_INBUSY 0x02 +#define C2_OUTREADY 0x01 + +// Layer 1: C2 Programmig Interface (PI) Register access +void c2_address_write(uint8_t address); +uint8_t c2_address_read(); +uint8_t c2_data_write(uint32_t d, uint8_t bytes); +uint8_t c2_data_read(uint32_t &d, uint8_t bytes=4); + +// Shorcuts for smaller words +inline uint8_t c2_data_read(uint16_t &d, uint8_t bytes=2) { + uint32_t dd; + uint8_t r = c2_data_read(dd, 2); + d = dd; + return r; +} +inline uint8_t c2_data_read(uint8_t &d, uint8_t bytes=1) { + uint32_t dd; + uint8_t r = c2_data_read(dd, 1); + d = dd; + return r; +} + +// Layer 2: Operations +uint8_t c2_reset(); +uint8_t c2_programming_init(); +uint8_t c2_block_write(uint32_t address, uint8_t *data, uint8_t len); +uint8_t c2_block_read(uint32_t address, uint8_t *data, uint8_t len); +uint8_t c2_eeprom_read(uint32_t address, uint8_t *data, uint8_t len); +uint8_t c2_page_erase(uint8_t page); +uint8_t c2_device_erase(); +uint8_t c2_sfr_write_non_paged(uint8_t address, uint8_t data); +uint8_t c2_sfr_write_paged(uint8_t address, uint8_t data); +uint8_t c2_sfr_read_non_paged(uint8_t address, uint8_t &data); +uint8_t c2_sfr_read_paged(uint8_t address, uint8_t &data); + +const char *c2_print_status_by_name(uint8_t ch); + +#endif // C2_H diff --git a/lib/C2Programmer-1.0.0/src/ihx.cpp b/lib/C2Programmer-1.0.0/src/ihx.cpp new file mode 100644 index 000000000..9a0ad6fcd --- /dev/null +++ b/lib/C2Programmer-1.0.0/src/ihx.cpp @@ -0,0 +1,71 @@ +#include "ihx.h" +#include + +static const char *conv = "0123456789ABCDEFabcdef"; +static uint8_t value_of_hex(uint8_t ch) { + uint8_t i = 0; + //Loop through list + while (conv[i] && ch != conv[i]) i++; + + if (!conv[i]) return 0; + //Convert to upper case + if (i >= 16) return i - 6; // lowercase + return i; +} + +uint8_t ihx_decode(uint8_t *buff, uint16_t slen) { + // Make sure the line looks like intel + if (buff[0] != ':') { +#ifdef IHX_DEBUG + Serial.println("IHX: Bad start:" + buff[0]); +#endif + return IHX_ERROR; + } + + // Remove strayline terminators at the end of the file + while (buff[slen - 1] == '\n' || buff[slen - 1] == '\r') slen--; + + // Length must be odd: start followed by hex pairs + if (slen < 11) { +#ifdef IHX_DEBUG + Serial.printf("IHX: Short read: %u\n", slen); +#endif + return IHX_ERROR; + } + + if (slen % 2 != 1) { +#ifdef IHX_DEBUG + Serial.printf("IHX: Length not odd (%u)\n", slen); +#endif + return IHX_ERROR; + } + + // Decode + uint8_t cs = 0; + for (int i = 0; i < (slen - 1) / 2; ++i) { + buff[i] = (value_of_hex(buff[2 * i + 1]) << 4) | value_of_hex(buff[2 * i + 2]); + cs += buff[i]; + } + + // Validate checksum + if (cs) { +#ifdef IHX_DEBUG + Serial.print("IHX: Bad checksum: "); + Serial.println(cs, HEX); +#endif + + return IHX_ERROR; + } + + // Check if lengths match + if (buff[0] * 2 + 11 != slen) { +#ifdef IHX_DEBUG + Serial.println("IHX: Length mismatch"); +#endif + return IHX_ERROR; + } + + return IHX_SUCCESS; +} + + diff --git a/lib/C2Programmer-1.0.0/src/ihx.h b/lib/C2Programmer-1.0.0/src/ihx.h new file mode 100644 index 000000000..b9fe8bec8 --- /dev/null +++ b/lib/C2Programmer-1.0.0/src/ihx.h @@ -0,0 +1,39 @@ +#ifndef IHX_H +#define IHX_H + +#include + +// Decoded +// Intel HEX file format: +// 1B - Start ':' +// 2B - data bytes +// 4B - address +// 2B - record type +// ?B - data +// 2B - checksum + +// 01234567890123 +// :NNAAAATTDDSS +struct ihx_t { + uint8_t len; + uint8_t address_high; + uint8_t address_low; + uint8_t record_type; // See IHX_RT_* below + uint8_t data[]; +}; +#define IHX_RT_DATA 0x00 +#define IHX_RT_END_OF_FILE 0x01 +#define IHX_RT_EXTENDED_SEGMENT_ADDRESS 0x02 +#define IHX_RT_START_SEGMENT_ADDRESS 0x03 +#define IHX_RT_EXTENDED_LINEAR_ADDRESS 0x04 +#define IHX_RT_START_LINEAR_ADDRESS 0x05 + +#define IHX_SUCCESS 0x00 +#define IHX_ERROR 0xFF + +extern uint8_t ihx_decode(uint8_t *buff, uint16_t slen); + +#endif // IHX_H + +// This is to enforce arduino-like formatting in kate +// kate: space-indent on; indent-width 2; mixed-indent off; indent-mode cstyle; diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index e32a7c7ef..5f28ffcc7 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,5 +1,7 @@ /* 6.0.0a * Add CRC to Settings making future upgrades more fail-safe + * Add support for uploading Sonoff Bridge firmware found in tools/fw_efm8bb1 folder build by Portisch using Web Gui File Upload (#2886) + * Add command RfRaw to control Portisch firmware features * Remove version 3, 4 and pre 5.2 settings auto-upgrade. See https://github.com/arendst/Sonoff-Tasmota/wiki/Upgrade#migration-path * Change default CFG_HOLDER from 0x20161209 to 4617 (=0x1209) - no impact on default upgrades * Fix Pzem004T checksum error diff --git a/sonoff/i18n.h b/sonoff/i18n.h index c6346a748..e0f1c2439 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -345,6 +345,7 @@ #define D_CMND_RFLOW "RfLow" #define D_CMND_RFSYNC "RfSync" #define D_JSON_RFRECEIVED "RfReceived" +#define D_CMND_RFRAW "RfRaw" // Commands xdrv_07_domoticz.ino #define D_CMND_DOMOTICZ "Domoticz" @@ -511,7 +512,7 @@ const char kOptionToggle[] PROGMEM = "TOGGLE|" D_TOGGLE "|" D_ADMIN ; const char kOptionBlink[] PROGMEM = "BLINK|" D_BLINK ; const char kOptionBlinkOff[] PROGMEM = "BLINKOFF|" D_BLINKOFF ; -// webserver.ino +// xdrv_02_webserver.ino #ifdef USE_WEBSERVER const char HTTP_SNS_TEMP[] PROGMEM = "%s{s}%s " D_TEMPERATURE "{m}%s°%c{e}"; // {s} = , {m} = , {e} = const char HTTP_SNS_HUM[] PROGMEM = "%s{s}%s " D_HUMIDITY "{m}%s%%{e}"; // {s} = , {m} = , {e} = diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 37a252909..13911e083 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -321,6 +321,10 @@ #define D_UPLOAD_ERR_7 "Зареждането е прекъснато" #define D_UPLOAD_ERR_8 "Файлът е невалиден" #define D_UPLOAD_ERR_9 "Файлът е прекалено голям" +#define D_UPLOAD_ERR_10 "Failed to init RF chip" +#define D_UPLOAD_ERR_11 "Failed to erase RF chip" +#define D_UPLOAD_ERR_12 "Failed to write to RF chip" +#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" #define D_UPLOAD_ERROR_CODE "Код на грешка при зареждането" #define D_ENTER_COMMAND "Въвеждане на команда" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index 96883e1fb..eec72fc31 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -321,6 +321,10 @@ #define D_UPLOAD_ERR_7 "Nahrávání přerušeno" #define D_UPLOAD_ERR_8 "Špatný soubor" #define D_UPLOAD_ERR_9 "Soubor je příliš velký" +#define D_UPLOAD_ERR_10 "Failed to init RF chip" +#define D_UPLOAD_ERR_11 "Failed to erase RF chip" +#define D_UPLOAD_ERR_12 "Failed to write to RF chip" +#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" #define D_UPLOAD_ERROR_CODE "Chyba nahrávání" #define D_ENTER_COMMAND "Vlož příkaz" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 4670b6999..91a2bcfef 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -321,6 +321,10 @@ #define D_UPLOAD_ERR_7 "Upload abgebrochen" #define D_UPLOAD_ERR_8 "Datei ungültig" #define D_UPLOAD_ERR_9 "Datei zu groß" +#define D_UPLOAD_ERR_10 "Failed to init RF chip" +#define D_UPLOAD_ERR_11 "Failed to erase RF chip" +#define D_UPLOAD_ERR_12 "Failed to write to RF chip" +#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" #define D_UPLOAD_ERROR_CODE "Upload Fehler Nummer" #define D_ENTER_COMMAND "Befehl eingeben" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 5abbf2b22..2281e2faf 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -321,6 +321,10 @@ #define D_UPLOAD_ERR_7 "Το ανεβάσμα διακόπηκε" #define D_UPLOAD_ERR_8 "Μη έγκυρο αρχείο" #define D_UPLOAD_ERR_9 "Το αρχείο είναι πολύ μεγάλο" +#define D_UPLOAD_ERR_10 "Failed to init RF chip" +#define D_UPLOAD_ERR_11 "Failed to erase RF chip" +#define D_UPLOAD_ERR_12 "Failed to write to RF chip" +#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" #define D_UPLOAD_ERROR_CODE "Κωδικός λάθους ανεβάσματος" #define D_ENTER_COMMAND "Εισαγωγή εντολής" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 2d0ffb38a..f5f0d6e22 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -321,6 +321,10 @@ #define D_UPLOAD_ERR_7 "Upload aborted" #define D_UPLOAD_ERR_8 "File invalid" #define D_UPLOAD_ERR_9 "File too large" +#define D_UPLOAD_ERR_10 "Failed to init RF chip" +#define D_UPLOAD_ERR_11 "Failed to erase RF chip" +#define D_UPLOAD_ERR_12 "Failed to write to RF chip" +#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" #define D_UPLOAD_ERROR_CODE "Upload error code" #define D_ENTER_COMMAND "Enter command" diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index 4b08fff62..68fbb1750 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -321,6 +321,10 @@ #define D_UPLOAD_ERR_7 "Carga cancelada" #define D_UPLOAD_ERR_8 "Archivo no válido" #define D_UPLOAD_ERR_9 "Archivo muy grande" +#define D_UPLOAD_ERR_10 "Failed to init RF chip" +#define D_UPLOAD_ERR_11 "Failed to erase RF chip" +#define D_UPLOAD_ERR_12 "Failed to write to RF chip" +#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" #define D_UPLOAD_ERROR_CODE "Código de error de carga" #define D_ENTER_COMMAND "Ingresar comando" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 4a980e174..09f9ffe0f 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -321,6 +321,10 @@ #define D_UPLOAD_ERR_7 "Téléchargement annulé" #define D_UPLOAD_ERR_8 "Fichier invalide" #define D_UPLOAD_ERR_9 "Fichier trop grand" +#define D_UPLOAD_ERR_10 "Failed to init RF chip" +#define D_UPLOAD_ERR_11 "Failed to erase RF chip" +#define D_UPLOAD_ERR_12 "Failed to write to RF chip" +#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" #define D_UPLOAD_ERROR_CODE "Code d'erreur téléchargement" #define D_ENTER_COMMAND "Saisir une commande" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index f6c1aac8d..986b18fdf 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -321,6 +321,10 @@ #define D_UPLOAD_ERR_7 "Feltöltés megszakítva" #define D_UPLOAD_ERR_8 "Érvénytelen file" #define D_UPLOAD_ERR_9 "File túl nagy" +#define D_UPLOAD_ERR_10 "Failed to init RF chip" +#define D_UPLOAD_ERR_11 "Failed to erase RF chip" +#define D_UPLOAD_ERR_12 "Failed to write to RF chip" +#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" #define D_UPLOAD_ERROR_CODE "Feltöltés hiba kód" #define D_ENTER_COMMAND "Parancsolj" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 5ce673196..eeac61384 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -321,6 +321,10 @@ #define D_UPLOAD_ERR_7 "Invio annullato" #define D_UPLOAD_ERR_8 "File non valido" #define D_UPLOAD_ERR_9 "File troppo grande" +#define D_UPLOAD_ERR_10 "Failed to init RF chip" +#define D_UPLOAD_ERR_11 "Failed to erase RF chip" +#define D_UPLOAD_ERR_12 "Failed to write to RF chip" +#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" #define D_UPLOAD_ERROR_CODE "Codice errore invio" #define D_ENTER_COMMAND "Inserire comando" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index 6e088bdb1..a764cb667 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -28,7 +28,7 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v5.14.0a + * Updated until v6.0.0a \*********************************************************************/ //#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) @@ -321,6 +321,10 @@ #define D_UPLOAD_ERR_7 "Opwaarderen afgebroken" #define D_UPLOAD_ERR_8 "Ongeldig bestand" #define D_UPLOAD_ERR_9 "Bestand is te groot" +#define D_UPLOAD_ERR_10 "Init RF chip mislukt" +#define D_UPLOAD_ERR_11 "Wissen RF chip mislukt" +#define D_UPLOAD_ERR_12 "Opwaarderen RF chip mislukt" +#define D_UPLOAD_ERR_13 "Decoderen RF bestand mislukt" #define D_UPLOAD_ERROR_CODE "Opwaardeer foutcode" #define D_ENTER_COMMAND "Geef opdracht" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index 62b112698..a039cf333 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -321,6 +321,10 @@ #define D_UPLOAD_ERR_7 "Wgrywanie przerwane" #define D_UPLOAD_ERR_8 "Błędny plik" #define D_UPLOAD_ERR_9 "Plik jest za duży" +#define D_UPLOAD_ERR_10 "Failed to init RF chip" +#define D_UPLOAD_ERR_11 "Failed to erase RF chip" +#define D_UPLOAD_ERR_12 "Failed to write to RF chip" +#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" #define D_UPLOAD_ERROR_CODE "Błąd wgrywania" #define D_ENTER_COMMAND "Wprowadź polecenie" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index 01ff2e48c..4bcf8efa2 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -321,6 +321,10 @@ #define D_UPLOAD_ERR_7 "Envio cancelado" #define D_UPLOAD_ERR_8 "Arquivo inválido" #define D_UPLOAD_ERR_9 "Arquivo muito grande" +#define D_UPLOAD_ERR_10 "Failed to init RF chip" +#define D_UPLOAD_ERR_11 "Failed to erase RF chip" +#define D_UPLOAD_ERR_12 "Failed to write to RF chip" +#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" #define D_UPLOAD_ERROR_CODE "Código de erro do envio" #define D_ENTER_COMMAND "Inserir comando" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index a7da5a4ac..4eeeb3965 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -321,6 +321,10 @@ #define D_UPLOAD_ERR_7 "Envio cancelado" #define D_UPLOAD_ERR_8 "Ficheiro inválido" #define D_UPLOAD_ERR_9 "Ficheiro demasiado grande" +#define D_UPLOAD_ERR_10 "Failed to init RF chip" +#define D_UPLOAD_ERR_11 "Failed to erase RF chip" +#define D_UPLOAD_ERR_12 "Failed to write to RF chip" +#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" #define D_UPLOAD_ERROR_CODE "Código de erro do envio" #define D_ENTER_COMMAND "Inserir comando" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index b54f2d7f1..cda108cdc 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -321,6 +321,10 @@ #define D_UPLOAD_ERR_7 "Загрузка прервана" #define D_UPLOAD_ERR_8 "Файл неверный" #define D_UPLOAD_ERR_9 "Слишком большой файл" +#define D_UPLOAD_ERR_10 "Failed to init RF chip" +#define D_UPLOAD_ERR_11 "Failed to erase RF chip" +#define D_UPLOAD_ERR_12 "Failed to write to RF chip" +#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" #define D_UPLOAD_ERROR_CODE "Код ошибки загрузки" #define D_ENTER_COMMAND "Введите команду" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 481291ee8..c0339b9e8 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -321,6 +321,10 @@ #define D_UPLOAD_ERR_7 "Завантаження перервано" #define D_UPLOAD_ERR_8 "Файл невірний" #define D_UPLOAD_ERR_9 "Занадто великий файл" +#define D_UPLOAD_ERR_10 "Failed to init RF chip" +#define D_UPLOAD_ERR_11 "Failed to erase RF chip" +#define D_UPLOAD_ERR_12 "Failed to write to RF chip" +#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" #define D_UPLOAD_ERROR_CODE "Код помилки завантаження" #define D_ENTER_COMMAND "Уведіть команду" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index 5b036a557..7a485feb0 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -321,6 +321,10 @@ #define D_UPLOAD_ERR_7 "上传取消" #define D_UPLOAD_ERR_8 "错误的固件" #define D_UPLOAD_ERR_9 "固件太大" +#define D_UPLOAD_ERR_10 "Failed to init RF chip" +#define D_UPLOAD_ERR_11 "Failed to erase RF chip" +#define D_UPLOAD_ERR_12 "Failed to write to RF chip" +#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" #define D_UPLOAD_ERROR_CODE "上传错误代码" #define D_ENTER_COMMAND "输入命令" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index baecc8318..e6adb4b0e 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -321,6 +321,10 @@ #define D_UPLOAD_ERR_7 "上傳取消" #define D_UPLOAD_ERR_8 "錯誤的固件" #define D_UPLOAD_ERR_9 "固件太大" +#define D_UPLOAD_ERR_10 "Failed to init RF chip" +#define D_UPLOAD_ERR_11 "Failed to erase RF chip" +#define D_UPLOAD_ERR_12 "Failed to write to RF chip" +#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" #define D_UPLOAD_ERROR_CODE "上傳錯誤代碼" #define D_ENTER_COMMAND "輸入命令" diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 5dd01a632..5d641f5fb 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -193,7 +193,7 @@ enum LightTypes {LT_BASIC, LT_PWM1, LT_PWM2, LT_PWM3, LT_PWM4, LT_PWM5, LT_PWM6, enum LichtSubtypes {LST_NONE, LST_SINGLE, LST_COLDWARM, LST_RGB, LST_RGBW, LST_RGBWC}; enum LichtSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MAX}; -enum XsnsFunctions {FUNC_INIT, FUNC_LOOP, FUNC_EVERY_50_MSECOND, FUNC_EVERY_SECOND, FUNC_PREP_BEFORE_TELEPERIOD, FUNC_JSON_APPEND, FUNC_WEB_APPEND, FUNC_SAVE_BEFORE_RESTART, +enum XsnsFunctions {FUNC_PRE_INIT, FUNC_INIT, FUNC_LOOP, FUNC_EVERY_50_MSECOND, FUNC_EVERY_SECOND, FUNC_PREP_BEFORE_TELEPERIOD, FUNC_JSON_APPEND, FUNC_WEB_APPEND, FUNC_SAVE_BEFORE_RESTART, FUNC_COMMAND, FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_INIT, FUNC_MQTT_DATA, FUNC_SET_POWER, FUNC_SHOW_SENSOR, FUNC_RULES_PROCESS}; const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 }; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 0d0fc91da..de3935c07 100644 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2324,7 +2324,7 @@ void GpioInit() } SetLedPower(Settings.ledstate &8); - XdrvCall(FUNC_INIT); + XdrvCall(FUNC_PRE_INIT); } extern "C" { @@ -2449,6 +2449,7 @@ void setup() ArduinoOTAInit(); #endif // USE_ARDUINO_OTA + XdrvCall(FUNC_INIT); XsnsCall(FUNC_INIT); } diff --git a/sonoff/user_config.h b/sonoff/user_config.h index a9f7cfab4..17b09bbe0 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -310,6 +310,8 @@ #define USE_SR04 // Add support for HC-SR04 ultrasonic devices (+1k code) +#define USE_RF_FLASH // Add support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB + /*********************************************************************************************\ * Select features and sensors enabled in previous version saving space \*********************************************************************************************/ diff --git a/sonoff/xdrv_02_webserver.ino b/sonoff/xdrv_02_webserver.ino index c290bcd90..1f699cfb0 100644 --- a/sonoff/xdrv_02_webserver.ino +++ b/sonoff/xdrv_02_webserver.ino @@ -25,6 +25,12 @@ * Based on source by AlexT (https://github.com/tzapu) \*********************************************************************************************/ +#ifdef USE_RF_FLASH +uint8_t *efm8bb1_update = NULL; +#endif // USE_RF_FLASH + +enum UploadTypes { UPL_TASMOTA, UPL_SETTINGS, UPL_EFM8BB1 }; + const char HTTP_HEAD[] PROGMEM = "" "" @@ -1162,7 +1168,7 @@ void HandleRestoreConfiguration() ShowPage(page); upload_error = 0; - upload_file_type = 1; + upload_file_type = UPL_SETTINGS; } void HandleUpgradeFirmware() @@ -1181,7 +1187,7 @@ void HandleUpgradeFirmware() ShowPage(page); upload_error = 0; - upload_file_type = 0; + upload_file_type = UPL_TASMOTA; } void HandleUpgradeFirmwareStart() @@ -1238,6 +1244,12 @@ void HandleUploadDone() case 7: strncpy_P(error, PSTR(D_UPLOAD_ERR_7), sizeof(error)); break; case 8: strncpy_P(error, PSTR(D_UPLOAD_ERR_8), sizeof(error)); break; case 9: strncpy_P(error, PSTR(D_UPLOAD_ERR_9), sizeof(error)); break; +#ifdef USE_RF_FLASH + case 10: strncpy_P(error, PSTR(D_UPLOAD_ERR_10), sizeof(error)); break; + case 11: strncpy_P(error, PSTR(D_UPLOAD_ERR_11), sizeof(error)); break; + case 12: strncpy_P(error, PSTR(D_UPLOAD_ERR_12), sizeof(error)); break; + case 13: strncpy_P(error, PSTR(D_UPLOAD_ERR_13), sizeof(error)); break; +#endif default: snprintf_P(error, sizeof(error), PSTR(D_UPLOAD_ERROR_CODE " %d"), upload_error); } @@ -1248,9 +1260,8 @@ void HandleUploadDone() } else { page += F("green'>" D_SUCCESSFUL "
"); page += FPSTR(HTTP_MSG_RSTRT); - ShowWebSource(SRC_WEBGUI); - restart_flag = 2; + restart_flag = 2; // Always restart to re-enable disabled features during update } SettingsBufferFree(); page += F("
"); @@ -1265,7 +1276,7 @@ void HandleUploadLoop() if (HTTP_USER == webserver_state) { return; } if (upload_error) { - if (!upload_file_type) { Update.end(); } + if (UPL_TASMOTA == upload_file_type) { Update.end(); } return; } @@ -1280,7 +1291,7 @@ void HandleUploadLoop() SettingsSave(1); // Free flash for upload snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_UPLOAD D_FILE " %s ..."), upload.filename.c_str()); AddLog(LOG_LEVEL_INFO); - if (upload_file_type) { + if (UPL_SETTINGS == upload_file_type) { if (!SettingsBufferAlloc()) { upload_error = 2; // Not enough space return; @@ -1296,6 +1307,12 @@ void HandleUploadLoop() if (Settings.flag.mqtt_enabled) MqttDisconnect(); uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000; if (!Update.begin(maxSketchSpace)) { //start with max available size + +// if (_serialoutput) Update.printError(Serial); +// if (Update.getError() == UPDATE_ERROR_BOOTSTRAP) { +// if (_serialoutput) Serial.println("Device still in UART update mode, perform powercycle"); +// } + upload_error = 2; // Not enough space return; } @@ -1303,22 +1320,34 @@ void HandleUploadLoop() upload_progress_dot_count = 0; } else if (!upload_error && (UPLOAD_FILE_WRITE == upload.status)) { if (0 == upload.totalSize) { - if (upload_file_type) { + if (UPL_SETTINGS == upload_file_type) { config_block_count = 0; - } else { - if (upload.buf[0] != 0xE9) { - upload_error = 3; // Magic byte is not 0xE9 - return; + } + else { +#ifdef USE_RF_FLASH + if ((SONOFF_BRIDGE == Settings.module) && (upload.buf[0] == ':')) { // Check if this is a RF bridge FW file + Update.end(); // End esp8266 update session + upload_file_type = UPL_EFM8BB1; + + upload_error = SnfBrUpdateInit(); + if (upload_error != 0) { return; } + } else +#endif // USE_RF_FLASH + { + if (upload.buf[0] != 0xE9) { + upload_error = 3; // Magic byte is not 0xE9 + return; + } + uint32_t bin_flash_size = ESP.magicFlashChipSize((upload.buf[3] & 0xf0) >> 4); + if(bin_flash_size > ESP.getFlashChipRealSize()) { + upload_error = 4; // Program flash size is larger than real flash size + return; + } + upload.buf[2] = 3; // Force DOUT - ESP8285 } - uint32_t bin_flash_size = ESP.magicFlashChipSize((upload.buf[3] & 0xf0) >> 4); - if(bin_flash_size > ESP.getFlashChipRealSize()) { - upload_error = 4; // Program flash size is larger than real flash size - return; - } - upload.buf[2] = 3; // Force DOUT - ESP8285 } } - if (upload_file_type) { // config + if (UPL_SETTINGS == upload_file_type) { if (!upload_error) { if (upload.currentSize > (sizeof(Settings) - (config_block_count * HTTP_UPLOAD_BUFLEN))) { upload_error = 9; // File too large @@ -1327,7 +1356,42 @@ void HandleUploadLoop() memcpy(settings_buffer + (config_block_count * HTTP_UPLOAD_BUFLEN), upload.buf, upload.currentSize); config_block_count++; } - } else { // firmware + } +#ifdef USE_RF_FLASH + else if (UPL_EFM8BB1 == upload_file_type) { + if (efm8bb1_update != NULL) { // We have carry over data since last write, i. e. a start but not an end + ssize_t result = rf_glue_remnant_with_new_data_and_write(efm8bb1_update, upload.buf, upload.currentSize); + free(efm8bb1_update); + efm8bb1_update = NULL; + if (result != 0) { + upload_error = abs(result); // 2 = Not enough space, 8 = File invalid + return; + } + } + ssize_t result = rf_search_and_write(upload.buf, upload.currentSize); + if (result < 0) { + upload_error = abs(result); + return; + } else if (result > 0) { + if (result > upload.currentSize) { + // Offset is larger than the buffer supplied, this should not happen + upload_error = 9; // File too large - Failed to decode RF firmware + return; + } + // A remnant has been detected, allocate data for it plus a null termination byte + size_t remnant_sz = upload.currentSize - result; + efm8bb1_update = (uint8_t *) malloc(remnant_sz + 1); + if (efm8bb1_update == NULL) { + upload_error = 2; // Not enough space - Unable to allocate memory to store new RF firmware + return; + } + memcpy(efm8bb1_update, upload.buf + result, remnant_sz); + // Add null termination at the end of of remnant buffer + efm8bb1_update[remnant_sz] = '\0'; + } + } +#endif // USE_RF_FLASH + else { // firmware if (!upload_error && (Update.write(upload.buf, upload.currentSize) != upload.currentSize)) { upload_error = 5; // Upload buffer miscompare return; @@ -1342,7 +1406,7 @@ void HandleUploadLoop() if (_serialoutput && (upload_progress_dot_count % 80)) { Serial.println(); } - if (upload_file_type) { + if (UPL_SETTINGS == upload_file_type) { if (config_xor_on_set) { for (uint16_t i = 2; i < sizeof(Settings); i++) { settings_buffer[i] ^= (config_xor_on_set +i); @@ -1370,7 +1434,14 @@ void HandleUploadLoop() upload_error = 8; // File invalid return; } - } else { + } +#ifdef USE_RF_FLASH + else if (UPL_EFM8BB1 == upload_file_type) { + // RF FW flash done + upload_file_type = UPL_TASMOTA; + } +#endif // USE_RF_FLASH + else { if (!Update.end(true)) { // true to set the size to the current progress if (_serialoutput) { Update.printError(Serial); } upload_error = 6; // Upload failed. Enable logging 3 @@ -1385,7 +1456,7 @@ void HandleUploadLoop() restart_flag = 0; MqttRetryCounter(0); upload_error = 7; // Upload aborted - if (!upload_file_type) { Update.end(); } + if (UPL_TASMOTA == upload_file_type) { Update.end(); } } delay(0); } diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index e38dc537b..180e9b858 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -1165,7 +1165,7 @@ boolean Xdrv03(byte function) if (energy_flg) { switch (function) { - case FUNC_INIT: + case FUNC_PRE_INIT: EnergyDrvInit(); break; case FUNC_COMMAND: diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 34a1a9861..7843192f7 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -1295,7 +1295,7 @@ boolean Xdrv04(byte function) if (light_type) { switch (function) { - case FUNC_INIT: + case FUNC_PRE_INIT: LightInit(); break; case FUNC_EVERY_50_MSECOND: diff --git a/sonoff/xdrv_05_irremote.ino b/sonoff/xdrv_05_irremote.ino index df2828fb9..2688d6c2f 100644 --- a/sonoff/xdrv_05_irremote.ino +++ b/sonoff/xdrv_05_irremote.ino @@ -401,7 +401,7 @@ boolean Xdrv05(byte function) if ((pin[GPIO_IRSEND] < 99) || (pin[GPIO_IRRECV] < 99)) { switch (function) { - case FUNC_INIT: + case FUNC_PRE_INIT: if (pin[GPIO_IRSEND] < 99) { IrSendInit(); } diff --git a/sonoff/xdrv_06_snfbridge.ino b/sonoff/xdrv_06_snfbridge.ino index 4149ae2a9..e146ea1ea 100644 --- a/sonoff/xdrv_06_snfbridge.ino +++ b/sonoff/xdrv_06_snfbridge.ino @@ -1,7 +1,7 @@ /* xdrv_06_snfbridge.ino - sonoff RF bridge 433 support for Sonoff-Tasmota - Copyright (C) 2018 Theo Arends + Copyright (C) 2018 Theo Arends and Erik Andrén Zachrisson (fw update) 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 @@ -24,11 +24,12 @@ #define SFB_TIME_AVOID_DUPLICATE 2000 // Milliseconds enum SonoffBridgeCommands { - CMND_RFSYNC, CMND_RFLOW, CMND_RFHIGH, CMND_RFHOST, CMND_RFCODE, CMND_RFKEY }; + CMND_RFSYNC, CMND_RFLOW, CMND_RFHIGH, CMND_RFHOST, CMND_RFCODE, CMND_RFKEY, CMND_RFRAW }; const char kSonoffBridgeCommands[] PROGMEM = - D_CMND_RFSYNC "|" D_CMND_RFLOW "|" D_CMND_RFHIGH "|" D_CMND_RFHOST "|" D_CMND_RFCODE "|" D_CMND_RFKEY ; + D_CMND_RFSYNC "|" D_CMND_RFLOW "|" D_CMND_RFHIGH "|" D_CMND_RFHOST "|" D_CMND_RFCODE "|" D_CMND_RFKEY "|" D_CMND_RFRAW; uint8_t sonoff_bridge_receive_flag = 0; +uint8_t sonoff_bridge_receive_raw_flag = 0; uint8_t sonoff_bridge_learn_key = 1; uint8_t sonoff_bridge_learn_active = 0; uint8_t sonoff_bridge_expected_bytes = 0; @@ -37,6 +38,206 @@ uint32_t sonoff_bridge_last_send_code = 0; unsigned long sonoff_bridge_last_time = 0; unsigned long sonoff_bridge_last_learn_time = 0; +#ifdef USE_RF_FLASH +/*********************************************************************************************\ + * EFM8BB1 RF microcontroller in-situ firmware update + * + * Enables upload of EFM8BB1 firmware provided by https://github.com/Portisch/RF-Bridge-EFM8BB1 using the web gui. + * Based on source by Erik Andrén Zachrisson (https://github.com/arendst/Sonoff-Tasmota/pull/2886) +\*********************************************************************************************/ + +#include "ihx.h" +#include "c2.h" + +#define RF_RECORD_NO_START_FOUND -1 +#define RF_RECORD_NO_END_FOUND -2 + +ssize_t rf_find_hex_record_start(uint8_t *buf, size_t size) +{ + for (int i = 0; i < size; i++) { + if (buf[i] == ':') { + return i; + } + } + return RF_RECORD_NO_START_FOUND; +} + +ssize_t rf_find_hex_record_end(uint8_t *buf, size_t size) +{ + for (ssize_t i = 0; i < size; i++) { + if (buf[i] == '\n') { + return i; + } + } + return RF_RECORD_NO_END_FOUND; +} + +ssize_t rf_glue_remnant_with_new_data_and_write(const uint8_t *remnant_data, uint8_t *new_data, size_t new_data_len) +{ + ssize_t record_start; + ssize_t record_end; + ssize_t glue_record_sz; + uint8_t *glue_buf; + ssize_t result; + + if (remnant_data[0] != ':') { return -8; } // File invalid - RF Remnant data did not start with a start token + + // Find end token in new data + record_end = rf_find_hex_record_end(new_data, new_data_len); + record_start = rf_find_hex_record_start(new_data, new_data_len); + + // Be paranoid and check that there is no start marker before the end record + // If so this implies that there was something wrong with the last start marker saved + // in the last upload part + if ((record_start != RF_RECORD_NO_START_FOUND) && (record_start < record_end)) { + return -8; // File invalid - Unexpected RF start marker found before RF end marker + } + + glue_record_sz = strlen((const char *) remnant_data) + record_end; + + glue_buf = (uint8_t *) malloc(glue_record_sz); + if (glue_buf == NULL) { return -2; } // Not enough space + + // Assemble new glue buffer + memcpy(glue_buf, remnant_data, strlen((const char *) remnant_data)); + memcpy(glue_buf + strlen((const char *) remnant_data), new_data, record_end); + + result = rf_decode_and_write(glue_buf, glue_record_sz); + free(glue_buf); + return result; +} + +ssize_t rf_decode_and_write(uint8_t *record, size_t size) +{ + uint8_t err = ihx_decode(record, size); + if (err != IHX_SUCCESS) { return -13; } // Failed to decode RF firmware + + ihx_t *h = (ihx_t *) record; + if (h->record_type == IHX_RT_DATA) { + int retries = 5; + uint16_t address = h->address_high * 0x100 + h->address_low; + + do { + err = c2_programming_init(); + err = c2_block_write(address, h->data, h->len); + } while (err != C2_SUCCESS && retries--); + } else if (h->record_type == IHX_RT_END_OF_FILE) { + // RF firmware upgrade done, restarting RF chip + err = c2_reset(); + } + + if (err != C2_SUCCESS) { return -12; } // Failed to write to RF chip + + return 0; +} + +ssize_t rf_search_and_write(uint8_t *buf, size_t size) +{ + // Binary contains a set of commands, decode and program each one + ssize_t rec_end; + ssize_t rec_start; + ssize_t err; + + for (size_t i = 0; i < size; i++) { + // Find starts and ends of commands + rec_start = rf_find_hex_record_start(buf + i, size - i); + if (rec_start == RF_RECORD_NO_START_FOUND) { + // There is nothing left to save in this buffer + return -8; // File invalid + } + + // Translate rec_start from local buffer position to chunk position + rec_start += i; + rec_end = rf_find_hex_record_end(buf + rec_start, size - rec_start); + if (rec_end == RF_RECORD_NO_END_FOUND) { + // We have found a start but not an end, save remnant + return rec_start; + } + + // Translate rec_end from local buffer position to chunk position + rec_end += rec_start; + + err = rf_decode_and_write(buf + rec_start, rec_end - rec_start); + if (err < 0) { return err; } + i = rec_end; + } + // Buffer was perfectly aligned, start and end found without any remaining trailing characters + return 0; +} + +uint8_t rf_erase_flash() +{ + uint8_t err; + + for (int i = 0; i < 4; i++) { // HACK: Try multiple times as the command sometimes fails (unclear why) + err = c2_programming_init(); + if (err != C2_SUCCESS) { + return 10; // Failed to init RF chip + } + err = c2_device_erase(); + if (err != C2_SUCCESS) { + if (i < 3) { + c2_reset(); // Reset RF chip and try again + } else { + return 11; // Failed to erase RF chip + } + } else { + break; + } + } + return 0; +} + +uint8_t SnfBrUpdateInit() +{ + pinMode(PIN_C2CK, OUTPUT); + pinMode(PIN_C2D, INPUT); + + return rf_erase_flash(); // 10, 11 +} +#endif // USE_RF_FLASH + +/********************************************************************************************/ + +void SonoffBridgeSendRaw(char *codes, int size) +{ + char *p; + char stemp[3]; + uint8_t code; + + while (size > 0) { + snprintf(stemp, sizeof(stemp), codes); + code = strtol(stemp, &p, 16); + Serial.write(code); + size -= 2; + codes += 2; + } +} + +void SonoffBridgeReceivedRaw() +{ + // Decoding according to https://github.com/Portisch/RF-Bridge-EFM8BB1 + uint8_t buckets = 0; + + if (0xB1 == serial_in_buffer[1]) { buckets = serial_in_buffer[2] << 1; } // Bucket sniffing + + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RFRAW "\":{\"" D_JSON_DATA "\":\"")); + for (int i = 0; i < serial_in_byte_counter; i++) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%02X"), mqtt_data, serial_in_buffer[i]); + if (0xB1 == serial_in_buffer[1]) { + if ((i > 3) && buckets) { buckets--; } + if ((i < 3) || (buckets % 2) || (i == serial_in_byte_counter -2)) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s "), mqtt_data); + } + } + } + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"}}"), mqtt_data); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_CMND_RFRAW)); + XdrvRulesProcess(); +} + +/********************************************************************************************/ + void SonoffBridgeLearnFailed() { sonoff_bridge_learn_active = 0; @@ -110,12 +311,28 @@ boolean SonoffBridgeSerialInput() { // iTead Rf Universal Transceiver Module Serial Protocol Version 1.0 (20170420) if (sonoff_bridge_receive_flag) { - if (!((0 == serial_in_byte_counter) && (0 == serial_in_byte))) { // Skip leading 0 + if (sonoff_bridge_receive_raw_flag) { + if (!serial_in_byte_counter) { + serial_in_buffer[serial_in_byte_counter++] = 0xAA; + } + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + if (0x55 == serial_in_byte) { // 0x55 - End of text + SonoffBridgeReceivedRaw(); + sonoff_bridge_receive_flag = 0; + return 1; + } + } + else if (!((0 == serial_in_byte_counter) && (0 == serial_in_byte))) { // Skip leading 0 if (0 == serial_in_byte_counter) { sonoff_bridge_expected_bytes = 2; // 0xA0, 0xA1, 0xA2 if (serial_in_byte >= 0xA3) { sonoff_bridge_expected_bytes = 11; // 0xA3, 0xA4, 0xA5 } + if (serial_in_byte == 0xA6) { + sonoff_bridge_expected_bytes = 0; // 0xA6 and up supported by Portisch firmware only + serial_in_buffer[serial_in_byte_counter++] = 0xAA; + sonoff_bridge_receive_raw_flag = 1; + } } serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; if ((sonoff_bridge_expected_bytes == serial_in_byte_counter) && (0x55 == serial_in_byte)) { // 0x55 - End of text @@ -134,6 +351,13 @@ boolean SonoffBridgeSerialInput() return 0; } +void SonoffBridgeSendCommand(byte code) +{ + Serial.write(0xAA); // Start of Text + Serial.write(code); // Command or Acknowledge + Serial.write(0x55); // End of Text +} + void SonoffBridgeSendAck() { Serial.write(0xAA); // Start of Text @@ -294,11 +518,48 @@ boolean SonoffBridgeCommand() } else { snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, sonoff_bridge_learn_key, D_JSON_LEARNING_ACTIVE); } + } + else if (CMND_RFRAW == command_code) { + if (XdrvMailbox.data_len) { + if (XdrvMailbox.data_len < 6) { // On, Off + switch (XdrvMailbox.payload) { + case 0: // Receive Raw Off + SonoffBridgeSendCommand(0xA7); // Stop reading RF signals enabling iTead default RF handling + case 1: // Receive Raw On + sonoff_bridge_receive_raw_flag = XdrvMailbox.payload; + break; + case 166: // 0xA6 - Start reading RF signals disabling iTead default RF handling + case 167: // 0xA7 - Stop reading RF signals enabling iTead default RF handling + case 169: // 0xA9 - Start learning predefined protocols + case 176: // 0xB0 - Stop sniffing + case 177: // 0xB1 - Start sniffing + SonoffBridgeSendCommand(XdrvMailbox.payload); + sonoff_bridge_receive_raw_flag = 1; + break; + case 192: // 0xC0 - Beep + char beep[] = "AAC000C055"; + SonoffBridgeSendRaw(beep, sizeof(beep)); + break; + } + } else { + SonoffBridgeSendRaw(XdrvMailbox.data, XdrvMailbox.data_len); + sonoff_bridge_receive_raw_flag = 1; + } + } + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(sonoff_bridge_receive_raw_flag)); } else serviced = false; // Unknown command return serviced; } +/*********************************************************************************************/ + +void SonoffBridgeInit() +{ + sonoff_bridge_receive_raw_flag = 0; + SonoffBridgeSendCommand(0xA7); // Stop reading RF signals enabling iTead default RF handling +} + /*********************************************************************************************\ * Interface \*********************************************************************************************/ @@ -311,6 +572,9 @@ boolean Xdrv06(byte function) if (SONOFF_BRIDGE == Settings.module) { switch (function) { + case FUNC_INIT: + SonoffBridgeInit(); + break; case FUNC_COMMAND: result = SonoffBridgeCommand(); break; diff --git a/sonoff/xdrv_08_serial_bridge.ino b/sonoff/xdrv_08_serial_bridge.ino index 653649b91..5d04c8059 100644 --- a/sonoff/xdrv_08_serial_bridge.ino +++ b/sonoff/xdrv_08_serial_bridge.ino @@ -135,7 +135,7 @@ boolean Xdrv08(byte function) if (serial_bridge_active) { switch (function) { - case FUNC_INIT: + case FUNC_PRE_INIT: SerialBridgeInit(); break; case FUNC_LOOP: diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index e19be6fff..337846efc 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -726,7 +726,7 @@ boolean Xdrv09(byte function) boolean result = false; switch (function) { - case FUNC_INIT: + case FUNC_PRE_INIT: TimerSetRandomWindows(); break; case FUNC_EVERY_SECOND: diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index b33872b7e..65e8df730 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -516,7 +516,7 @@ boolean Xdrv10(byte function) boolean result = false; switch (function) { - case FUNC_INIT: + case FUNC_PRE_INIT: RulesInit(); break; case FUNC_EVERY_50_MSECOND: diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index 1dc9fcd44..eef88e001 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -1078,7 +1078,7 @@ boolean Xdrv11(byte function) { boolean result = false; switch (function) { - case FUNC_INIT: + case FUNC_PRE_INIT: KNX_INIT(); break; case FUNC_LOOP: diff --git a/sonoff/xdrv_interface.ino b/sonoff/xdrv_interface.ino index 1897cec5f..6080b103b 100644 --- a/sonoff/xdrv_interface.ino +++ b/sonoff/xdrv_interface.ino @@ -179,6 +179,7 @@ boolean XdrvRulesProcess() /*********************************************************************************************\ * Function call to all xdrv * + * FUNC_PRE_INIT * FUNC_INIT * FUNC_LOOP * FUNC_MQTT_SUBSCRIBE diff --git a/tools/fw_efm8bb1/RF_Bridge_00.hex b/tools/fw_efm8bb1/RF_Bridge_00.hex new file mode 100644 index 000000000..4fbda3662 --- /dev/null +++ b/tools/fw_efm8bb1/RF_Bridge_00.hex @@ -0,0 +1,406 @@ +:020000040000FA +:10000000020FEFED24F8FEEFD39E4015ED2408FD1E +:10001000E433FCC3EF9DEC6480F874809850028058 +:1000200001C322020ED0E4F5A922220213637EFF4F +:10003000EFD394004022EF9480501DE4FDED75F065 +:100040000EA424A5F582E43418F583E493B50704DF +:10005000AE0580040DBD05E5AF062202110612189B +:100060004E53D87853DBFE12180FE4900085F0222F +:10007000D2DE220213B6D2011215F6C290C296D277 +:1000800080E4FBFD7F101217F612064374A4F0D231 +:10009000AFE4F52FF530D2960530E5307002052F2C +:1000A000B410F3E52FB427EEC29630010912150DF6 +:1000B0008E328F338006753201753300E53370045C +:1000C000E532640170409000CCE07007F52FF53008 +:1000D0000202870530E5307002052FD39410E52F1A +:1000E00094274002D296D3E5309430E52F94755092 +:1000F00003020287E4F52FF5309000CCF09000CB9E +:10010000F0C296020287E4F52FF5309000CCE0149F +:10011000602A14700302025914700302021E147044 +:100120000302023424046003020287E53364AA60F8 +:10013000030202879000CC04F0020287E5339000AE +:10014000CBF0A37402F0E5331208B30206A00170ED +:10015000A10182A501A6A601BAA701C3A801DFA932 +:1001600001C6B001CFB10197C00287FF00000215A0 +:100170001205E69000A87401F0E4900075F07FA1EC +:10018000806E12005E9000CC7404F0753108E4F5C6 +:10019000357534090202879000CC7404F0E4F5351B +:1001A000753402020287E49000A8F0900075F07F99 +:1001B000A612067474A6F002028712064374A4F015 +:1001C0000202877531089000CC7403F00202879018 +:1001D00000757401F07FB1120674EFF0020287120D +:1001E00005E69000A8E0F52EE4F0900075F07FA9F8 +:1001F0001214D090007CEFF07D307C757F017E0082 +:1002000012164902028712065790007CEFF0E49024 +:1002100000CCF08072E49000CBF0A3F08069E4F5AC +:1002200035E533F534E534D394009000CC402574A3 +:1002300004F0805374042535F582E43400F583E539 +:1002400033F00535E53565346007E535C394704016 +:10025000369000CC7402F0802EE5336455702890FF +:1002600000CCF0C2019000CBE02460601824FC6058 +:100270000F24FE600B14600824F66004241070073D +:100280007FA01217C3D2019000CBE01208B302B0D6 +:10029000A102DAA402ECA503C5A603E1A8051FA9E3 +:1002A000055CB005CFB1038DC003B3FF000000AA09 +:1002B000900084E030E70F7DC87C001206167FA313 +:1002C00012140902053912180740030200AA7DE83A +:1002D0007C031206167FA2020554900084E020E7FA +:1002E000030200AA7FA41214090203D99000CCE0F3 +:1002F00060030200AA900085E024FC606D24046085 +:10030000030200AA1531900008E0FEA3E0FF7C0084 +:100310007D641208D9C006C0071215A0D007D00608 +:100320001208218F3E900006E0FEA3E0FF8E3FF50D +:10033000407C007D641208D9C006C0071215A0D009 +:1003400007D0061208218F41754218900008E0FA84 +:10035000A3E0FB900004E0FCA3E0FDA3E0FEA3E02B +:10036000FF12067B7406F00204EBE53160171206FB +:100370002DD39400500302051012062D12066012B0 +:1003800018400205101206577FA00205549000CCB9 +:10039000E060030200AA900004E0FCA3E0FD7F01FE +:1003A0007E00121649D296121840C2967FA01217EC +:1003B000C3800AE4FF1217C3E49000CCF0D201120C +:1003C000066B0200AA900084E020E7030200AA5412 +:1003D0007FF537FD7FA612130CE4900084F0020035 +:1003E000AA9000CCE060030200AA900085E024FC03 +:1003F00070030204F1240460030200AA1531120004 +:100400005E900004E0647F702FA3E0FEA3E0FFA3F2 +:10041000E0FCA3E0FDA3E0FAA3E0FBA3E0F53EA32C +:10042000E0F53FA3E0F540A3E0F541A3E0F542127B +:10043000067B740CF00204E2900004E0FF12002E30 +:100440008F36E536F470030204DDEF75F00EA42458 +:1004500060F582E43418F583E493FE740193FFC0E1 +:1004600006C0071215BA2462F582E434181215C1C9 +:10047000C004C0051215BA2465F582E43418F5836A +:10048000E493FA740193FB1215BA2469F582E434FB +:1004900018F583E493FF1215BA2467F582E4341843 +:1004A0001215C11215BA246AF582E43418F583E4F2 +:1004B00093FE1215BA246BF582E43418F583E493A5 +:1004C000F5428E418C3F8D408F3ED005D004D00741 +:1004D000D0061212929000747401F08005E490002E +:1004E000CBF09000CBE070030200AA121749020083 +:1004F000AAE53160231215BA246CF582E43418F5AC +:1005000083E493FFD394004007EF12066012184073 +:10051000E4900085F00200AA12066B7FA08035905F +:100520000084E0FF30E71C547FF5377DC87C001263 +:1005300005F9AD377FAB12130CE4900084F0D201C3 +:100540000200AA12180740030200AA7DE87C0312E9 +:1005500005F97FAA1217C3D2010200AA900004E095 +:1005600025E0F5379000CCE060030200AA900085FA +:10057000E0700512005E800B900085E0640460036B +:100580000200AAE5376007E534C394045008E490FC +:1005900000CBF00200AA74062537F9E43400753B5D +:1005A00001F53C893DC3E534953724FEF53E9000C6 +:1005B00005E0F53F7B017A00790612118B7FA012CE +:1005C00017C390007CE0FF1214D0D2010200AA9061 +:1005D0000084E020E7030200AA7FB1121210E49029 +:1005E0000084F00200AA7D327C007F017E0012169A +:1005F00049D296121840C296227F017E00121649F7 +:10060000D296121840C2969000A8E52EF090007C79 +:10061000E0FF1214D0227F017E00121649D29612FA +:100620001840C29690007CE0FF1214D0227F011285 +:10063000002EEF75F00EA4246CF582E43418F583D7 +:10064000E493229000A87401F0E4900075F07FA478 +:100650001214D090007C2290007CE0FF1214D02273 +:10066000FD7C007F017E001216492290007CE0FF95 +:100670001214D0221214D090007C221212929000F8 +:100680007422BB010CE58229F582E5833AF583E00B +:10069000225006E92582F8E622BBFE06E92582F80B +:1006A000E222E58229F582E5833AF583E49322BBD1 +:1006B000010689828A83F0225002F722BBFE01F3F1 +:1006C00022EF8DF0A4A8F0CF8CF0A428CE8DF0A45A +:1006D0002EFE22BC000BBE0029EF8DF084FFADF092 +:1006E00022E4CCF875F008EF2FFFEE33FEEC33FC7C +:1006F000EE9DEC984005FCEE9DFE0FD5F0E9E4CEB2 +:10070000FD22EDF8F5F0EE8420D21CFEADF075F080 +:1007100008EF2FFFED33FD4007985006D5F0F22289 +:10072000C398FD0FD5F0EA22C2D5EC30E709B2D567 +:10073000E4C39DFDE49CFCEE30E715B2D5E4C39F15 +:10074000FFE49EFE1206D3C3E49DFDE49CFC8003FF +:100750001206D330D507C3E49FFFE49EFE22BB01FF +:1007600010E58229F582E5833AF583E0F5F0A3E010 +:10077000225009E92582F886F008E622BBFE0AE944 +:100780002582F8E2F5F008E222E5832AF583E99371 +:10079000F5F0A3E99322E88FF0A4CC8BF0A42CFC15 +:1007A000E98EF0A42CFC8AF0EDA42CFCEA8EF0A4D7 +:1007B000CDA8F08BF0A42DCC3825F0FDE98FF0A466 +:1007C0002CCD35F0FCEB8EF0A4FEA9F0EB8FF0A45D +:1007D000CFC5F02ECD39FEE43CFCEAA42DCE35F099 +:1007E000FDE43CFC2275F008758200EF2FFFEE332C +:1007F000FECD33CDCC33CCC58233C5829BED9AEC94 +:1008000099E58298400CF582EE9BFEED9AFDEC99FD +:10081000FC0FD5F0D6E4CEFBE4CDFAE4CCF9A88207 +:1008200022B800C1B90059BA002DEC8BF084CFCEAC +:10083000CDFCE5F0CBF97818EF2FFFEE33FEED336A +:10084000FDEC33FCEB33FB10D703994004EB99FB31 +:100850000FD8E5E4F9FA227818EF2FFFEE33FEED1A +:1008600033FDEC33FCC933C910D7059BE99A400727 +:10087000EC9BFCE99AF90FD8E0E4C9FAE4CCFB223E +:1008800075F010EF2FFFEE33FEED33FDCC33CCC807 +:1008900033C810D7079BEC9AE899400AED9BFDEC12 +:1008A0009AFCE899F80FD5F0DAE4CDFBE4CCFAE451 +:1008B000C8F922D083D082F8E49370127401937047 +:1008C0000DA3A393F8740193F5828883E4737402F3 +:1008D000936860EFA3A3A380DFEC8EF0A4CCC5F0F7 +:1008E000CCCDF8EFA4CEC5F02DFDE43CFCE8A42E61 +:1008F000C8C5F03DFDE43CFCEFA4FFE5F028FEE4B4 +:100900003DFDE43CFC22EF4E6012EF60010EEDBBBA +:10091000010B89828A83F0A3DFFCDEFA2289F05082 +:1009200007F709DFFCA9F022BBFEFCF309DFFCA9F5 +:10093000F022AFE9AEEA7C007D0A1206C18E088F74 +:1009400009209303020B2185080A85090BC3E509D9 +:10095000950DF511E508950CF510900075E01470F3 +:1009600003020B1B046003020B42900085E014603D +:1009700065046003020B42900084E06003020B42B6 +:100980009000A8E0FFAB11AA10AD0FAC0E120E1331 +:100990008F12E51264807003020B4290007F120CEC +:1009A000A3900002E510F0A3E511120C5FE49000A3 +:1009B00074F0900077F090007EF0F513F514FE7F50 +:1009C00070FD7B017A007904120906E490007DF045 +:1009D00090008504F022E51275F00EA424AAF58299 +:1009E000E43418F583E493FFD39400400B90007E29 +:1009F000E09F5004E004F022900088E014F09000A2 +:100A000077E004F0AE10AF11AB07AA06E50F2BFF9D +:100A1000E50E3AFEE433FDE433FCC004A905AA0662 +:100A2000AB07AE0EAF0F120CABD0001208218F2215 +:100A3000120C231200034029E51275F00EA424B015 +:100A4000F582E43418F583E493FDAF2212000340ED +:100A500010120B436F600AE4900084F0C290A3F080 +:100A600022120C23AF221200035007120B43C39F24 +:100A70004011D3E50F9514E50E9513402B120B434F +:100A80006F7025900086120CA3D290120BF6C083D3 +:100A9000C082120C9B7401A806088002C333D8FCE4 +:100AA0004FD082D083F0801790007A120CA3C290AE +:100AB000D39514E50E95134006850E13850F1490FB +:100AC0000088E07015120BF6E0FF90007DE06FFFEC +:100AD00012176490007DEF120C5F120B436F70626F +:100AE0001217FF5005E4900083F0900083E0FF9020 +:100AF000007DE06F601D12180F7DF47C017F017E88 +:100B00000012162090007DE0900083F0A3E512F023 +:100B10004480F0C290E4900085F022AF11AE1080C6 +:100B20001E85080C85090DC3E509950BF50FE50831 +:100B3000950AF50E900075E0147007AF0FAE0E1217 +:100B40000CC822E51275F00EA424B1F582E4341825 +:100B5000F583E493FF900077E022120821AB07AA07 +:100B600006E4F9F87F407E427D0FFC120821E47B09 +:100B7000FFFAF9F8120796A804A905AA06AB077FA1 +:100B8000207ED77D757C01120821EFF40422AE2669 +:100B9000AF277C007D1F1206D38E2A8F2B7C007D11 +:100BA000051206D3C3E52B9FFDE52A9EFCD3E52560 +:100BB0009DE5249C22E52975F00EA424A8F582E485 +:100BC0003418F583E493FE740193FF2438FDEE346A +:100BD000FFFCD3E5279DE5269C22900074E02404C9 +:100BE000F582E43400F58322E52525E0248AF582A8 +:100BF000E43400F58322900077E024FFFFE434FF23 +:100C0000FE7C007D0812072874042FF58274003ED4 +:100C1000F58322E52B2FFFE52A3EC3FEE5259FE560 +:100C2000249E22E51275F00EA424AFF582E4341858 +:100C3000F583E493FD22E52975F00EA424A6F58240 +:100C4000E43418F5832253DAFE53F7DF53F7BF225B +:100C5000AB3BAA3CA93D854082758300020682F029 +:100C60009000887408F022EF24C8FFE43EFEC3E53C +:100C7000279FE5269E2275F0FFA4FFAEF07C007D45 +:100C8000640206D3900078E523F0A3E524F02290D7 +:100C90000081E0FF900077E0D39F22E0FF90008882 +:100CA000E0FE22E50EF0A3E50FF0227C007D640259 +:100CB00008D9540F75F002A4F58285F08322D3E59C +:100CC000279470E5269417228E238F24900085E0C8 +:100CD000146035147003020D9D24026003020E049B +:100CE000C290900084E06003020E04AF24AE231291 +:100CF00017914003020E04E4900001F0120C84905E +:100D000000857401F0D29022900078E0FCA3E0FD11 +:100D1000AE047802CEC313CE13D8F92DFFEC3EFEFD +:100D2000D3E5249FE5239E4009120C84E490000142 +:100D3000F022AF24AE23121492501A900001E094D6 +:100D4000004012E4900074F09000887404F0900069 +:100D5000857402F022C3E5249464E5239400403AAC +:100D6000120E05501C120BE8E0FEA3E02524FFE55F +:100D7000233EC313FEEF13FF120BE8EEF0A3EFF0D8 +:100D800022900001E0120BEA120C87900001E004AF +:100D9000F0E0D3941E406DE4805EE48063B290AFD7 +:100DA00024AE23121492500D900084E04480F0C2CF +:100DB00090E4A3F022120E055041900088E0B404A4 +:100DC00011E525C454F0FF120BDAEFF0E49000882F +:100DD000F022120BDAE0FFE525540FFEEF4EF09003 +:100DE0000074E004F09000887404F0900074E0D384 +:100DF00094704010E4900001F08005E4900001F050 +:100E0000900085F0227B007A007925AF24AE231272 +:100E1000107E228F238C248D258A268B277528808F +:100E2000E523707CE4F5297F0112002EEF6529701F +:100E30001B120CBE405FE5279450E52694465055A2 +:100E4000120B8E4050120C13504B807E120C36E465 +:100E500093FE740193FFD39400EE9400402BEF2493 +:100E600038FFEE34FFD3120C1B402A120C367401EB +:100E70009324C8FFE4933400120C1A5018120BB5D7 +:100E80004013120C67500E8041120BB54007120C34 +:100E900067500280350529E529C394054089802DD6 +:100EA000AF2312002E8F297F0112002EEF652970CB +:100EB0001C120CBE4017E5279450E5269446500DB1 +:100EC000120B8E4008120C135003852928AF2822DC +:100ED000C0E0C0F0C083C082C0D075D000C000C0E8 +:100EE00001C002C003C004C005C006C007E5985495 +:100EF00003F547F45298E54730E017121857900071 +:100F0000C0121690EFF09000C0E004F0E0B41402BC +:100F1000E4F0E54730E12E9000C2E0D39400401A9F +:100F20009000BFE02448F8E6FF1218549000BFE09C +:100F300004F09000C2E014F08002D2029000BFE002 +:100F4000B42002E4F0D007D006D005D004D003D0FE +:100F500002D001D000D0D0D082D083D0F0D0E03207 +:100F60004200C700004200C300004200C900004226 +:100F700000C500004100CC004100CB0041008400CE +:100F8000410085004100A8004100750041007C003F +:100F900041007656410089AB4100000041008200CB +:100FA00042007F0000420002000042008600004232 +:100FB000007A000041008100410088004100770074 +:100FC00041007E00410074004100830041007D002B +:100FD000410001004100C0004100C1004100BE00CD +:100FE0004100BF004100C2004100BD00C10200122B +:100FF000002A787FE4F6D8FD758167021039020077 +:1010000076E493A3F8E493A34003F68001F208DFAB +:10101000F48029E493A3F85407240CC8C333C454C0 +:101020000F4420C8834004F456800146F6DFE48074 +:101030000B0102040810204080900F60E47E0193B1 +:1010400060BCA3FF543F30E509541FFEE493A36046 +:10105000010ECF54C025E060A840B8E493A3FAE4A1 +:1010600093A3F8E493A3C8C582C8CAC583CAF0A3F2 +:10107000C8C582C8CAC583CADFE9DEE780BE8E263E +:101080008F278B288A29892AC200E4F52B9000013A +:10109000E0FFE52BC39F506BE527AE267803CEC358 +:1010A00013CE13D8F9FDAC06E527AE267802CEC3E1 +:1010B00013CE13D8F92DF52DEE3CF52CE52B120BA4 +:1010C000EAE0FEA3E0FFC3952DFDEE952CFCC3EDF9 +:1010D0009527EC95265028E52D2FFFE52C3EFEC3E5 +:1010E000E5279FE5269E5017E52A45294528600BF0 +:1010F000AB28AA29A92AE52B1206AFD20080040545 +:101100002B808AA20022C0E0C0F0C083C082C0D081 +:1011100075D000C000C001C002C003C004C005C03B +:1011200006C007E5D85487F521F452D8E5F730E535 +:1011300008E5F730E60312154353F7DFE52130E702 +:1011400008E5D930E00312185DE52130E008E5DA62 +:1011500030E00312169BE52130E108E5DB30E003C7 +:10116000120932E52130E208E5DC30E00312185EB6 +:10117000D007D006D005D004D003D002D001D000D3 +:10118000D0D0D082D083D0F0D0E0328B388A398969 +:101190003A53DBFE120C4653E2FDE4F540E540C352 +:1011A000953E504FAB38AA39A93AC003C002C001DE +:1011B000120C50C4120CB2D001D002D00312075E40 +:1011C000F54285F041D280121202AB38AA39A93A11 +:1011D000C003C002C001120C50120CB2D001D002E8 +:1011E000D00312075EF54285F041C280121202055B +:1011F0004080AAB290AF3F153FEF709E43E202C21B +:101200009022FDAC417F0A7E001215741218402214 +:10121000AE07E4F5381216EA900001E004FF12165A +:10122000F112128B900001E0FFE538C39F501212BB +:101230001684121677121684F58312167E053880EE +:10124000E3900078E0FF1216F190007812167E12FB +:10125000128B900088E07006900074E004F0E4F5D2 +:1012600038900074E0FFE538C39F501774042538A8 +:101270001216720538E538541F70E612185112180C +:101280004A80DE7F551216F10218511218511218B9 +:101290004A228E388F398C3A8D3BAE02AF03120C46 +:1012A000ABC007AF3EAB07E4FAF9F8D007120B5A10 +:1012B000900000F0AE3FAF40120CABC007AF41ABA7 +:1012C00007E4FAF9F8D007120B5A900082F0E53ED5 +:1012D000120C76900076EFF0E541120C76900089C2 +:1012E000EFF090007FE538F0A3E539F0900002E5DB +:1012F0003AF0A3E53BF0900081E542F043DA015378 +:10130000F7DF43F74053DBFE75F9FF22AE07E4FC3D +:10131000FB1216EAED75F00EA424F7F582E43418FA +:10132000F583E493FFECC39F500774082CFC0B80FB +:10133000E3EB04FF1216F1ED75F00EA424EBF58239 +:10134000E43418F583E493FF1216F1E4FCECC39B3C +:10135000500974042C1216720C80F27F551216F18B +:10136000021851C0E0C083C082C0D075D000C00454 +:10137000C005C006C00753C87F9000C7E0FEA3E0C9 +:10138000FF4E700353C8FB9000C31214875009909E +:1013900000C7E4F0A3F0800DC39000C8E09DF0907A +:1013A00000C7E09CF0D007D006D005D004D0D0D044 +:1013B00082D083D0E032C0E0C083C082C0D075D07C +:1013C00000C004C005C006C00753917F9000C9E06B +:1013D000FEA3E0FF4E70035391FB9000C5121487EB +:1013E00050099000C9E4F0A3F0800DC39000CAE05A +:1013F0009DF09000C9E09CF0D007D006D005D00445 +:10140000D0D0D082D083D0E032AE07E4FDF53812E0 +:1014100016EA900002E0FF1216F190000212167E0A +:1014200090007AE0FF1216F190007A12167E90007A +:1014300086E0FF1216F190008612167E74042D12BB +:1014400016720DBD03F67F551216F1021851AB0747 +:10145000AA06E4F9F87F407E427D0FFC120821A81D +:1014600004A905AA06AB077F207ED77D757C0112F3 +:101470000821C3E49FFFE49EFE22AB07AA06E4F91D +:10148000F87FE87E03FD22E0FCA3E0FDC3EF9DEEC4 +:101490009C22AD07AC06900078E0FEA3E07802CE77 +:1014A000C313CE13D8F9FFC3900079E09FFB9000DF +:1014B00078E09EFAC3EB9DEA9C5013A3E02FFF90C7 +:1014C0000078E03EFEC3ED9FEC9E50028001C322F7 +:1014D0008F3890007CE0F5397F0B12185A43DB01FE +:1014E000120C461200707D0A7C007F017E001216ED +:1014F0004912184043E202E4900085F0900084F025 +:101500009000CBE538F090007CF0AF39229000C01D +:10151000E0FF9000BEE0B507057E017F002290004D +:10152000BE121690E0FD7C009000BEE004F0E0B436 +:101530001402E4F09000BDE0FEEE4204E4F0AE04DC +:10154000AF0522120C8F400302172B120BDA120C7C +:101550009BEFA806088002C313D8FC30E00B900074 +:1015600000E0FF12185AD29022900082E0FF121879 +:101570005AC290228E438F448C458D4612144E12CF +:1015800017ABE54624BF9000CAF0E54534FF900054 +:10159000C9F09000C5E543F0A3E544F0439104226F +:1015A000900006E0FEA3E0FF900009E02FFF90000E +:1015B00008E03EAB07FAE4F9F822E53675F00EA430 +:1015C00022F583E493FC740193FD22D29053E2FD53 +:1015D000D28090007F1215E6C290C2809000021265 +:1015E00015E643E20222E0FCA3E0FD7F0A7E001242 +:1015F00015741218402212181612181D12182412EF +:1016000017CE12002612177B1217EC1217D81217DA +:10161000E21217B712182B12183212184602183994 +:101620008E238F248C258D2612147A12145B1217A8 +:101630009F9000C7E525F0A3E526F09000C3E523C1 +:10164000F0A3E524F043C804228E3A8F3B8C3C8DF6 +:101650003D12147A12145B1217AB9000C9E53CF0EE +:10166000A3E53DF09000C5E53AF0A3E53BF04391DA +:101670000422F582E43400F583E0FF0216F1A3E0D2 +:10168000FF0216F1E53825E0248AF582E4340022D1 +:10169000E024A9F582E43400F58322900088E0700C +:1016A00008900074E004120C5F900077E004F09062 +:1016B0000088E014F0120C8F50030216C353E2FDB1 +:1016C000C28022120BDA120C9BEFA806088002C31C +:1016D00013D8FC30E0059000768003900089E07D0F +:1016E00000FCE4FF12170D22AE077FAA1216F1AF1D +:1016F00006C2029000C1E0B42002E4F09000C1E014 +:101700002448F8A607E004F0A3E004F022AB07AFFA +:1017100004EB14600C14600E2402700E8DFB8FFC21 +:10172000228DE98FEA228DEB8FEC22E4FDFCFF1283 +:10173000170D120C4612184E53D87853E2FDC28092 +:10174000C2909000857404F022120C60E014F090B6 +:1017500000777401F09000857403F01216C312151F +:10176000CB0200707E1DE4FDEF30E70625E06EFF42 +:101770008004EF25E0FF0DBD08EE22AF885388AF4F +:10178000758CA0758DCBEF5440FEEF54104E4288FF +:1017900022C3EF94ACEE940D4003D38001C322AD7D +:1017A00007AC06ECF5CBAF058FCA22AD07AC06EC53 +:1017B000F593AF058F9222C2DE75D90575F9FF75D5 +:1017C0009601221216E87F551216F102185175E3A0 +:1017D0004075E10175E20222E59154045391FB4208 +:1017E0009122758E5475892243885022E5C854048D +:1017F00053C8FB42C82253984FEB4F4DF59822E552 +:10180000C8C320E201D322E591C320E201D32253D1 +:10181000C8FB53C87F227597DE7597AD2275A4115A +:1018200075D4CE2275A54175D5772253F77F75DA29 +:101830004A2253F77F75DB302275E69075A8B022F7 +:10184000E59120E2FB22439810223002FD22C2DE05 +:1018500022D299228F9922AF99228F8C22222201A3 +:101860000190307000064001904B1918000212C020 +:1018700005DC0002BC012C461E2808030BB82328F7 +:1018800000044C01904B19180004251C0BB80003F0 +:10189000840140461E180005000072D80702BC01F2 +:1018A0002C26404000010190307000064001904B12 +:1018B0001918000212C005DC0002BC012C461E28CB +:1018C00008030BB8232800044C01904B191800049E +:1018D000251C0BB80003840140461E1800050000BB +:1018E00072D80702BC012C264040000101903070E4 +:1018F00000064001904B1918000212C005DC0002DE +:10190000BC012C461E2808030BB8232800044C01F8 +:10191000904B19180004251C0BB8000384014046A5 +:101920001E180005000072D80702BC012C2640409A +:0119300000B6 +:00000001FF diff --git a/tools/fw_efm8bb1/RF_Bridge_iTead_Original.hex b/tools/fw_efm8bb1/RF_Bridge_iTead_Original.hex new file mode 100644 index 000000000..ee0e95356 --- /dev/null +++ b/tools/fw_efm8bb1/RF_Bridge_iTead_Original.hex @@ -0,0 +1,207 @@ +:020000040000FA +:10000000020779AB07AA06EB2401FEE43A900080D0 +:10001000F0A3CEF0ED1490007DF08B828A83E0F5A2 +:100020009922220204D0C204C29022020B03120CB5 +:100030009C120CA3120CAA120C8012006E120B91CF +:10004000120BAA120BC3120C8A120C75120B5D0252 +:100050000C5C53984FEB4F4DF598220208CC1200E0 +:100060002E120C30D2AF120B77120C0A80F8E4F586 +:10007000A922FF020A37020218E86480F8E933E88F +:100080003360110460F0ED33EC337009E8FCE9FDF6 +:10009000EAFEEBFF220460DED3EB9FEA9EE99DE8D7 +:1000A000C2E78CF0C2F795F0400CE8CCF8E9CDF946 +:1000B000EACEFAEBCFFB1201E385D0F058047003CF +:1000C00020D5B3E80470075002B2D502022292D5BF +:1000D000EC0460F7E4CCC0E0C398F8603B9418608F +:1000E00008400DD0E0FB0201FAE4FBFAC9FC8028CD +:1000F000E830E406E4C9FBE4CAFCE830E305E4C9FF +:10010000CACBFCE854076010F8C3E913F9EA13FA04 +:10011000EB13FBEC13FCD8F130F52FC3E49CFCEFA0 +:100120009BFFEE9AFEED99FDD0E0FBEF4E4D4C703B +:100130001222DB0302021FEC2CFCEF33FFEE33FE36 +:10014000ED33FDED30E7EB0201FAEF2BFFEE3AFE67 +:10015000ED39FDD0E0FB50130BBB0003020222ED92 +:1001600013FDEE13FEEF13FFEC13FC0201FA75F022 +:1001700020800E75F010800575F0087D007E007FF0 +:10018000003392D530D5031202E3EC334010EF3345 +:10019000FFEE33FEED33FDEC33FCD5F0ED22E5F060 +:1001A000247EA2D513CC92E7CDCEFF22EDD2E7CDAF +:1001B00033EC3392D524814006E4FFFEFDFC22FCA3 +:1001C000E4CFCECDCC24E0501174FF80EDC3CC132E +:1001D000CCCD13CDCE13CECF13CF0470F030D5DEFF +:1001E0000202E3E9D2E7C933E833F892D5EDD2E76A +:1001F000CD33EC33FC5002B2D522EC30E7100FBF08 +:10020000000C0EBE00080DBD00040BEB6014A2D55F +:10021000EB13FCED92E7FD2274FFFCFDFEFF22E4F0 +:1002200080F8A2D574FF13FC7D80E480EFEF8DF0A1 +:10023000A4A8F0CF8CF0A428CE8DF0A42EFE22BC72 +:10024000000BBE0029EF8DF084FFADF022E4CCF866 +:1002500075F008EF2FFFEE33FEEC33FCEE9DEC98CB +:100260004005FCEE9DFE0FD5F0E9E4CEFD22EDF851 +:10027000F5F0EE8420D21CFEADF075F008EF2FFFF4 +:10028000ED33FD4007985006D5F0F222C398FD0FDC +:10029000D5F0EA22E88FF0A4CC8BF0A42CFCE98EF8 +:1002A000F0A42CFC8AF0EDA42CFCEA8EF0A4CDA8DE +:1002B000F08BF0A42DCC3825F0FDE98FF0A42CCDE7 +:1002C00035F0FCEB8EF0A4FEA9F0EB8FF0A4CFC5C7 +:1002D000F02ECD39FEE43CFCEAA42DCE35F0FDE451 +:1002E0003CFC22C3E49FFFE49EFEE49DFDE49CFCF5 +:1002F00022EB9FF5F0EA9E42F0E99D42F0E89C4532 +:10030000F022E8600FECC313FCED13FDEE13FEEFDB +:1003100013FFD8F122E8600FEFC333FFEE33FEED99 +:1003200033FDEC33FCD8F122E4F50BF50AF509F5C1 +:1003300008F50CF50DF50EF50FF510F511F512F5A4 +:1003400013F514F515F516F517900000E06401603B +:10035000030204C7F0E52C7015900004E0F524A317 +:10036000E0F525A3E0F526A3E0F5271208ADE52585 +:100370002527F50DE5243526F50CFEAF0D7C007D17 +:100380000512023F8E108F11AE22AF237C007D0537 +:1003900012023F8E128F13E4FBEBC3943040030232 +:1003A000044F12086A12087BF583E0FCA3E0FD2FDE +:1003B000F50FEC3EF50EE50D2511FFE50C3510FEB1 +:1003C000D3E50F9FE50E9E5014C3E50D9511FFE593 +:1003D0000C9510FEC3E50F9FE50E9E5009052EE516 +:1003E0002E7002052D2212086AFFD3ED9FEC9E406D +:1003F000221208A0EF4401F50BEEF50AEDF509EC29 +:10040000F50812086A1208B812087C12087412085B +:10041000C2803712086A12087BF583E0FCA3E0C3B0 +:100420009FEC9E501C1208A08F0B8E0A8D098C0821 +:1004300012086A1208C212087C1208741208B880E6 +:1004400009052EE52E7002052D220B0B0203999053 +:100450000002E0FEA3E0FF2511FDE5103EFCC3E530 +:10046000239DE5229C5027C3EF9511FFEE9510FECA +:10047000D3E5239FE5229E4015AF2BAE2AAD29ACD4 +:1004800028AB0BAA0AA909A8081202F160311208C8 +:10049000AD850B2B850A2A850929850828752C012D +:1004A000E4F52DF52EAE14AF15FC1208878E268FBD +:1004B00027AE16AF177C001208878E248F252205E1 +:1004C0002CE4F52DF52E22052EE52E7002052D22A9 +:1004D000C0E0C0F0C083C082C0D075D000C000C0F2 +:1004E00001C002C003C004C005C006C007E598549F +:1004F00003F51EF4529890007CE0700302058AE533 +:100500001E20E00302058A90007EE0FEA3E0FFF5D6 +:10051000828E83E599F08F828E83E0FF20000B644A +:10052000AA60030205BCD200803A200137300034B3 +:10053000EF64A0601EEF64A16019EF64A26014EF85 +:1005400064A3600FEF64A4600AEF64A56005120C59 +:10055000698069D201EF64A06008EF64A16003BF05 +:10056000A202D20290007FE004F0700690007EE0CC +:1005700004F090007CE014F0E0FE6008BF550B3002 +:1005800002086006120C691209E3E51E30E12D90A5 +:10059000007DE06024900080E0FEA3E0F5828E8381 +:1005A000E0F599900081E004F07006900080E0048E +:1005B000F090007DE014F08003120022D007D006F6 +:1005C000D005D004D003D002D001D000D0D0D0824A +:1005D000D083D0F0D0E032E4F518F519F51DF51C04 +:1005E000F51BF51A30AF6890006612096BF522ED25 +:1005F000F52312096AF526EDF52712096AF524EDAF +:10060000F525A3E0FFE4FCFDFEFBFA7901F81202F8 +:1006100094A804A905AA06AB0790006DE0FEE4FCCF +:10062000FD2BFBEA3EFAED39F9EC38F8A3E0FFE4E4 +:10063000FEEB2FFFEE3AFEED39FDEC388F2B8E2AC4 +:100640008D29F5287F0A7E00120BDCC291C2AFE42F +:10065000F51812095EAF23AE22120BF4852B1D850F +:100660002A1C85291B85281AE4F519E4FFFEE51BE1 +:100670005480FDE4FCFBFAF9F8C31202F16011D2D8 +:1006800080AF25AE24120BF4C280AF27AE268007C0 +:1006900012095EAF25AE24120BF4AF1DAE1CAD1BCC +:1006A000AC1A78011203158F1D8E1C8D1B8C1A0538 +:1006B00019E519C3941840B30518E518C394084008 +:1006C00091D291D2AF7F0A7E00120BDC12092D125B +:1006D0000003120CC3E4F537220233000001370097 +:1006E0000235000041007D0041007C00C100C101D5 +:1006F000C102C105C104C1030139000138006064B1 +:1007000000000000000000000000000000000000E9 +:1007100000000000000000000000000000000000D9 +:1007200000000000000000000000000000000000C9 +:1007300000000000000000000000000000000000B9 +:1007400000000000000000000000000000000000A9 +:100750000000000000000000000000000000000099 +:100760000000000000000D2200000000000000005A +:10077000000000000001210000787FE4F6D8FD753C +:1007800081390207C002005EE493A3F8E493A3401A +:1007900003F68001F208DFF48029E493A3F85407FC +:1007A000240CC8C333C4540F4420C8834004F456F7 +:1007B000800146F6DFE4800B01020408102040802F +:1007C0009006D9E47E019360BCA3FF543F30E50955 +:1007D000541FFEE493A360010ECF54C025E060A82F +:1007E00040B8E493A3FAE493A3F8E493A3C8C582C2 +:1007F000C8CAC583CAF0A3C8C582C8CAC583CADF30 +:10080000E9DEE780BEAB07AA06900001E07019C3DD +:10081000EB94C8EA9400405130934EA3EAF0A3EB66 +:10082000F09000017401F0227C007D05AF03AE0260 +:1008300012022DD3900003E09F900002E09E401032 +:10084000E52112087DF583EAF0A3EBF0052180078E +:10085000E4900001F0F521E521C39430400BE4F56C +:100860002190000004F0E4A3F022EB25E02406F53B +:1008700082E43400F583E0FEA3E022FFEB25E024D0 +:1008800004F582E43400227D1812023FAC06AD0765 +:10089000E4120173E4FBFAF9783F12007D0201AC27 +:1008A000AF0BAE0AAD09AC08780102031590000247 +:1008B000E0F522A3E0F523222515F515EE3514F514 +:1008C00014222517F517EE3516F51622C0E0C0F0F4 +:1008D000C083C082C0D075D000C000C001C002C0BB +:1008E00003C004C005C006C00730D823C2D885FCA9 +:1008F0002F85FB30C3E5309532F534E52F9531F582 +:1009000033852F31853032AF34FE12080580035312 +:10091000D879D007D006D005D004D003D002D001BA +:10092000D000D0D0D082D083D0F0D0E03290007010 +:1009300074AAF074A0A3F0A37455F07E007F707DBC +:100940000322AF2BAE2AAD29AC28120302A3EFF08D +:1009500022120A7D120C207E007F707D0C22D28034 +:10096000AF27AE26120BF4C28022A3E0FEA3E0FD67 +:10097000EE2212022DEEA3F02275F00AA4A3F022BB +:10098000C3E52E9496E52D940022053930052AE51D +:1009900039C39414404C0538E538D394045002B25E +:1009A00096E4F539B290E538C394084035E4F5385B +:1009B000C296C290C205C20422300412E539C39423 +:1009C0000A401F309602C296E4F539B290223003F5 +:1009D00011E539D3940A400AE4F539B29020900227 +:1009E000C20322900064E0FFB4AA0BA3E0B4A00607 +:1009F000A3E064556040EF64AA7022900065E06453 +:100A0000A1701AA3E0B45515120C2012092D120082 +:100A100003E4F535F536120C947537012290006425 +:100A2000E0B4AA12A3E0B4A50D90006FE0B455069F +:100A3000753702120C2022C0E0C0F0C083C082C013 +:100A4000D075D000C000C001C002C003C004C00502 +:100A5000C006C00712098A0536E53670020535530F +:100A6000917FD007D006D005D004D003D002D001AA +:100A7000D000D0D0D082D083D0F0D0E032900070BF +:100A800074AAF0A3EFF0AE22AF237C007D0A120916 +:100A900072E523120979AE26AF27120972E52712F3 +:100AA0000979AE24AF25120972E52512097978106B +:100AB0001209427808120942A3E52BF0A37455F0FD +:100AC00022E52CB40A03120CBD1209804015E52C56 +:100AD000940A400FE4F52DF52E7FA3120951120060 +:100AE00003801CC3E5369470E535941740149000DC +:100AF0007074AAF074A2120935120003120026E4E1 +:100B0000F53722C0E0C0F0C083C082C0D075D000ED +:100B1000C000C001C002C003C004C005C006C007B9 +:100B2000120328C2CFD007D006D005D004D003D0FE +:100B300002D001D000D0D0D082D083D0F0D0E0322B +:100B40001209804017E52CD394004010E4F52DF5F0 +:100B50002E7FA4120951120003120CC322E5D854AF +:100B600040FFE5F75480FE53D8BF53F77F75DA3165 +:100B7000EF42D8EE42F722E5377015120CB7EF704E +:100B80000F120CB1EF70097E007F647D0C120C4EC9 +:100B900022AF885388AF758C0B758AD7758DCBEFD4 +:100BA0005440FEEF54104E428822E5C8540453C806 +:100BB000FB75CD4075CC9875CB4075CA9843C80479 +:100BC00042C822E59154045391FB7595FF75940B2F +:100BD0007593B075923F439104429122AD07AC06E4 +:100BE000D3ED9400EC9400400A120C40ED1D70F01F +:100BF0001C80ED22EF1FAC0670011E4C600B000044 +:100C00000000000000000080EB22E53714600A14A9 +:100C1000600A24027009020B40020AC11205D722A1 +:100C2000E4F52CF52BF52AF529F528F522F52322F4 +:100C3000C280D291C290C296E4FBFD7F10020052A6 +:100C40007F927E09EF1F70011EEF4E70F722900019 +:100C50007EEEF0A3EFF090007CEDF02275E690754B +:100C6000F31075A8B075B8102290007CE4F0C200B3 +:100C7000C201C20222C2DE75D904759E01D2DE22F3 +:100C800075E34075E10175E20122758E14758922C4 +:100C900043885022D204E4F539D296227597DE7546 +:100CA00097AD2275A41375D4CF2275A54375D507CA +:100CB0002290007DE0FF2290007CE0FF22D205E43C +:090CC000F53922D203E4F53922D2 +:00000001FF