integrated OTGWSerial Class by Schelte Bron

This commit is contained in:
Robert van den Breemen 2021-02-08 00:13:52 +01:00
parent de769d4f8d
commit c3e469c243
21 changed files with 1959 additions and 161 deletions

View File

@ -1,7 +1,7 @@
{
"board": "esp8266:esp8266:nodemcuv2",
"output": "D://Users//Robert//Documents//GitHub//build",
"configuration": "xtal=160,vt=flash,exception=legacy,ssl=all,eesz=4M2M,led=2,ip=lm2f,dbg=Disabled,lvl=None____,wipe=sdk,baud=115200",
"configuration": "xtal=160,vt=flash,exception=legacy,ssl=all,eesz=4M2M,led=2,ip=lm2f,dbg=Disabled,lvl=None____,wipe=none,baud=921600",
"port": "COM4",
"prebuild": "D://Users//Robert//Documents//GitHub//Rvdb//autoinc-semver//semver-incr-build.bat ./version.h",
"sketch": "OTGW-firmware.ino"

View File

@ -14,6 +14,13 @@
"string": "cpp",
"fstream": "cpp",
"cstring": "cpp",
"regex": "cpp"
"regex": "cpp",
"array": "cpp",
"deque": "cpp",
"list": "cpp",
"unordered_map": "cpp",
"unordered_set": "cpp",
"initializer_list": "cpp",
"sstream": "cpp"
}
}

View File

@ -12,9 +12,9 @@
/*---- start macro's ------------------------------------------------------------------*/
#define Debug(...) ({ TelnetStream.print(__VA_ARGS__); })
#define Debugln(...) ({ TelnetStream.println(__VA_ARGS__); })
#define Debugf(...) ({ TelnetStream.printf(__VA_ARGS__); })
#define Debug(...) ({ TelnetStream.print(__VA_ARGS__); })
#define Debugln(...) ({ TelnetStream.println(__VA_ARGS__); })
#define Debugf(...) ({ TelnetStream.printf(__VA_ARGS__); })
#define DebugFlush() ({ TelnetStream.flush(); })

View File

@ -274,7 +274,7 @@ void upgradePIC()
{
DebugTln(F("Redirect to upgrade PIC .."));
doRedirect("Upgrade OTGW PIC ", 120, "/FSexplorer", false);
upgradenow();
// upgradenow();
} // upgradePIC()

View File

@ -11,20 +11,16 @@
***************************************************************************
*/
//define Nodoshop OTGW hardware
// #define OTGW_BUTTON D3
#define OTGW_RESET 14
// #define OTGW_LED1 D4
// #define OTGW_LED2 D0
#define OTGW_BUTTON 0 //D3
#define OTGW_RESET 14 //D5
#define OTGW_LED1 2 //D4
#define OTGW_LED2 16 //D0
//external watchdog
// #define OTGW_I2C_SCL 5
// #define OTGW_I2C_SDA 4
// #define OTGW_EXT_WD_I2C_ADDRESS 0x26
#define EXT_WD_I2C_ADDRESS 0x26
#define PIN_I2C_SDA 4
#define PIN_I2C_SCL 5
#define PIN_I2C_SDA 4 //D2
#define PIN_I2C_SCL 5 //D1
//Macro to Feed the Watchdog
#define FEEDWATCHDOGNOW Wire.beginTransmission(EXT_WD_I2C_ADDRESS); Wire.write(0xA5); Wire.endTransmission();
@ -52,27 +48,47 @@
//some variable's
OpenthermData OTdata;
#define OTGW_BANNER "OpenTherm Gateway "
//===================[ Reset OTGW ]===============================
void resetOTGW() {
//lower the right pin for just 100ms and the OTGW is reset
DebugTln("OTGW PIC reset");
pinMode(OTGW_RESET, OUTPUT);
digitalWrite(OTGW_RESET, LOW);
OTGWSerial.print("GW=R\r\n");
delay(100);
digitalWrite(OTGW_RESET, HIGH);
pinMode(OTGW_RESET, INPUT_PULLUP);
//wait for response
OTGWSerial.setTimeout(250);
String line = OTGWSerial.readStringUntil('\n');
line.trim();
DebugTf("Received after reset: %s (%d)\r\n", CSTR(line), line.length());
bOTGWonline = (line.length()>0);
if (bOTGWonline){
//find version
int p = line.indexOf(OTGW_BANNER);
if (p >= 0) {
p += sizeof(OTGW_BANNER);
sPICfwversion = line.substring(p);
} else sPICfwversion ="No version found";
} else sPICfwversion = "No OTWG connected!";
DebugTf("Current firmware version: %s\r\n", CSTR(sPICfwversion));
OTGWSerial.setTimeout(1000);
}
//===================[ getpicfwversion ]===========================
String getpicfwversion(){
String _ret="";
#define BANNER "OpenTherm Gateway"
String line = executeCommand("PR=A");
int p = line.indexOf(BANNER);
int p = line.indexOf(OTGW_BANNER);
if (p >= 0) {
p += sizeof(BANNER);
p += sizeof(OTGW_BANNER);
_ret = line.substring(p);
} else _ret ="No version found";
DebugTf("Current firmware version: %s\n", CSTR(_ret));
DebugTf("Current firmware version: %s\r\n", CSTR(_ret));
_ret.trim();
return _ret;
}
@ -80,23 +96,23 @@ String getpicfwversion(){
String executeCommand(const String sCmd){
//send command to OTGW
DebugTf("OTGW Send Cmd [%s]\r\n", CSTR(sCmd));
Serial.setTimeout(1000);
OTGWSerial.setTimeout(1000);
DECLARE_TIMER_MS(tmrWaitForIt, 1000);
while((Serial.availableForWrite() < sCmd.length()+2) && !DUE(tmrWaitForIt)){
while((OTGWSerial.availableForWrite() < sCmd.length()+2) && !DUE(tmrWaitForIt)){
feedWatchDog();
}
Serial.write(CSTR(sCmd));
Serial.write("\r\n");
Serial.flush();
OTGWSerial.write(CSTR(sCmd));
OTGWSerial.write("\r\n");
OTGWSerial.flush();
//wait for response
RESTART_TIMER(tmrWaitForIt);
while(!Serial.available() && !DUE(tmrWaitForIt)) {
while(!OTGWSerial.available() && !DUE(tmrWaitForIt)) {
feedWatchDog();
}
String _cmd = sCmd.substring(0,2);
DebugTf("Send command: [%s]\r\n", CSTR(_cmd));
//fetch a line
String line = Serial.readStringUntil('\n');
String line = OTGWSerial.readStringUntil('\n');
line.trim();
String _ret ="";
if (line.startsWith(_cmd)){
@ -129,81 +145,81 @@ String executeCommand(const String sCmd){
return _ret;
}
String executeCommandCstyle(const String sCmd){
return executeCommandCstyle(CSTR(sCmd), sCmd.length());
}
// String executeCommandCstyle(const String sCmd){
// return executeCommandCstyle(CSTR(sCmd), sCmd.length());
// }
String executeCommandCstyle(const char* sCmd, size_t len){
char _cmd[2];
char line[80];
char _ret[80];
//send command to OTGW
DebugTf("OTGW Send Cmd [%s]=[%s]\r\n", sCmd);
while(Serial.availableForWrite() < len+2){
feedWatchDog();
}
Serial.write(sCmd, len);
Serial.write("\r\n");
Serial.flush();
//wait for response
Serial.setTimeout(3000);
while(!Serial.available()) {
feedWatchDog();
}
// DebugTf("Send command: [%s]\r\n", _cmd);
//fetch a line
size_t l = Serial.readBytesUntil('\n', line, sizeof(line)-1);
line[l]='\0';
_cmd[0]='\0';
if (l > 0) {
strcpy(_cmd,strtok(line,":"));
}
if (prefix(_cmd, sCmd)){
// Responses: When a serial command is accepted by the gateway, it responds with the two letters of the command code, a colon, and the interpreted data value.
// Command: "TT=19.125"
// Response: "TT: 19.13"
// [XX:response string]
strcpy(_ret,strtok(NULL,":"));
} else if (prefix("NG", _cmd)){
strlcpy(_ret, "NG - No Good. The command code is unknown.", sizeof(_ret));
} else if (prefix("SE", _cmd)){
strlcpy(_ret, "SE - Syntax Error. The command contained an unexpected character or was incomplete.", sizeof(_ret));
} else if (prefix("BV", _cmd)){
strlcpy(_ret, "BV - Bad Value. The command contained a data value that is not allowed.", sizeof(_ret));
} else if (prefix("OR", _cmd)){
strlcpy(_ret, "OR - Out of Range. A number was specified outside of the allowed range.", sizeof(_ret));
} else if (prefix("NS", _cmd)){
strlcpy(_ret, "NS - No Space. The alternative Data-ID could not be added because the table is full.", sizeof(_ret));
} else if (prefix("NF", _cmd)){
strlcpy(_ret, "NF - Not Found. The specified alternative Data-ID could not be removed because it does not exist in the table.", sizeof(_ret));
} else if (prefix("OE", _cmd)){
strlcpy(_ret, "OE - Overrun Error. The processor was busy and failed to process all received characters.", sizeof(_ret));
} else {
strlcpy(_ret, "Error: Different command response [", sizeof(_ret));
strlcat(_ret, _cmd, sizeof(_ret));
strlcat(_ret, "] Cmd send [", sizeof(_ret));
strlcat(_ret, sCmd, sizeof(_ret));
strlcat(_ret, "]", sizeof(_ret));
}
DebugTf("Command send - Response returned: [%s]:[%s] - line: [%s]\r\n", _cmd, _ret, line);
return _ret;
}
// String executeCommandCstyle(const char* sCmd, size_t len){
// char _cmd[2];
// char line[80];
// char _ret[80];
// //send command to OTGW
// DebugTf("OTGW Send Cmd [%s]=[%s]\r\n", sCmd);
// while(OTGWSerial.availableForWrite() < len+2){
// feedWatchDog();
// }
// OTGWSerial.write(sCmd, len);
// OTGWSerial.write("\r\n");
// OTGWSerial.flush();
// //wait for response
// OTGWSerial.setTimeout(3000);
// while(!OTGWSerial.available()) {
// feedWatchDog();
// }
// // DebugTf("Send command: [%s]\r\n", _cmd);
// //fetch a line
// size_t l = OTGWSerial.readBytesUntil('\n', line, sizeof(line)-1);
// line[l]='\0';
// _cmd[0]='\0';
// if (l > 0) {
// strcpy(_cmd,strtok(line,":"));
// }
// if (prefix(_cmd, sCmd)){
// // Responses: When a serial command is accepted by the gateway, it responds with the two letters of the command code, a colon, and the interpreted data value.
// // Command: "TT=19.125"
// // Response: "TT: 19.13"
// // [XX:response string]
// strcpy(_ret,strtok(NULL,":"));
// } else if (prefix("NG", _cmd)){
// strlcpy(_ret, "NG - No Good. The command code is unknown.", sizeof(_ret));
// } else if (prefix("SE", _cmd)){
// strlcpy(_ret, "SE - Syntax Error. The command contained an unexpected character or was incomplete.", sizeof(_ret));
// } else if (prefix("BV", _cmd)){
// strlcpy(_ret, "BV - Bad Value. The command contained a data value that is not allowed.", sizeof(_ret));
// } else if (prefix("OR", _cmd)){
// strlcpy(_ret, "OR - Out of Range. A number was specified outside of the allowed range.", sizeof(_ret));
// } else if (prefix("NS", _cmd)){
// strlcpy(_ret, "NS - No Space. The alternative Data-ID could not be added because the table is full.", sizeof(_ret));
// } else if (prefix("NF", _cmd)){
// strlcpy(_ret, "NF - Not Found. The specified alternative Data-ID could not be removed because it does not exist in the table.", sizeof(_ret));
// } else if (prefix("OE", _cmd)){
// strlcpy(_ret, "OE - Overrun Error. The processor was busy and failed to process all received characters.", sizeof(_ret));
// } else {
// strlcpy(_ret, "Error: Different command response [", sizeof(_ret));
// strlcat(_ret, _cmd, sizeof(_ret));
// strlcat(_ret, "] Cmd send [", sizeof(_ret));
// strlcat(_ret, sCmd, sizeof(_ret));
// strlcat(_ret, "]", sizeof(_ret));
// }
// DebugTf("Command send - Response returned: [%s]:[%s] - line: [%s]\r\n", _cmd, _ret, line);
// return _ret;
// }
//===================[ OTGW PS=1 Command ]===============================
void getOTGW_PS_1(){
DebugTln("PS=1");
Serial.write("PS=1\r\n");
Serial.flush();
OTGWSerial.write("PS=1\r\n");
OTGWSerial.flush();
while(!Serial.available()) {
while(!OTGWSerial.available()) {
feedWatchDog();
}
String line = Serial.readStringUntil('\n');
String line = OTGWSerial.readStringUntil('\n');
line.trim(); //remove LF and CR (and whitespaces)
DebugTln(line);
DebugTln("PS=0");
Serial.write("PS=0\r\n");
Serial.flush();
OTGWSerial.write("PS=0\r\n");
OTGWSerial.flush();
}
//===================[ OTGW PS=1 Command ]===============================
//===================[ Watchdog OTGW ]===============================
@ -720,25 +736,25 @@ int sendOTGW(const char* buf, int len)
//Send the buffer to OTGW when the Serial interface is available
if (Serial) {
//check the write buffer
Debugf("Serial Write Buffer space = [%d] - needed [%d]\r\n",Serial.availableForWrite(), (len+2));
Debugf("Serial Write Buffer space = [%d] - needed [%d]\r\n",OTGWSerial.availableForWrite(), (len+2));
DebugT("Sending to Serial [");
for (int i = 0; i < len; i++) {
Debug((char)buf[i]);
}
Debug("] ("); Debug(len); Debug(")"); Debugln();
while (Serial.availableForWrite()==(len+2)) {
while (OTGWSerial.availableForWrite()==(len+2)) {
//cannot write, buffer full, wait for some space in serial out buffer
feedWatchDog(); //this yields for other processes
}
if (Serial.availableForWrite()>= (len+2)) {
if (OTGWSerial.availableForWrite()>= (len+2)) {
//write buffer to serial
Serial.write(buf, len);
// Serial.write("PS=0\r\n");
Serial.write('\r');
Serial.write('\n');
Serial.flush();
OTGWSerial.write(buf, len);
// OTGWSerial.write("PS=0\r\n");
OTGWSerial.write('\r');
OTGWSerial.write('\n');
OTGWSerial.flush();
} else Debugln("Error: Write buffer not big enough!");
} else Debugln("Error: Serial device not found!");
}
@ -929,14 +945,14 @@ void handleOTGW()
//handle incoming data from network (port 25238) sent to serial port OTGW (WRITE BUFFER)
while (OTGWstream.available()){
//Serial.write(OTGWstream.read()); //just forward it directly to Serial
//OTGWSerial.write(OTGWstream.read()); //just forward it directly to Serial
outByte = OTGWstream.read(); // read from port 25238
while (Serial.availableForWrite()==0) {
while (OTGWSerial.availableForWrite()==0) {
//cannot write, buffer full, wait for some space in serial out buffer
feedWatchDog(); //this yields for other processes
}
Serial.write(outByte); // write to serial port
Serial.flush(); // wait for write to serial
OTGWSerial.write(outByte); // write to serial port
OTGWSerial.flush(); // wait for write to serial
if (outByte == '\n')
{ //on newline, do something...
sWrite[bytes_write] = 0;
@ -960,9 +976,9 @@ void handleOTGW()
}
//Handle incoming data from OTGW through serial port (READ BUFFER)
while(Serial.available())
while(OTGWSerial.available())
{
inByte = Serial.read(); // read from serial port
inByte = OTGWSerial.read(); // read from serial port
OTGWstream.write(inByte); // write to port 25238
if (inByte== '\n')
{ //line terminator, continue to process incoming message
@ -1085,6 +1101,17 @@ void startOTGWstream()
OTGWstream.begin();
}
void upgradenow() {
if (OTGWSerial.busy()) return; // if already in programming mode, never call it twice
DebugTln("Start PIC upgrade now.");
fwupgradestart(FIRMWARE);
while (OTGWSerial.busy()){
feedWatchDog();
}
// When you are done, then reset the PIC one more time, to capture the actual fwversion of the OTGW
resetOTGW();
}
/***************************************************************************
*
* Permission is hereby granted, free of charge, to any person obtaining a

View File

@ -30,9 +30,9 @@
#ifndef Debug
//#warning Debug() was not defined!
#define Debug(...) ({ Serial.print(__VA_ARGS__); })
#define Debugln(...) ({ Serial.println(__VA_ARGS__); })
#define Debugf(...) ({ Serial.printf(__VA_ARGS__); })
#define Debug(...) ({ OTGWSerial.print(__VA_ARGS__); })
#define Debugln(...) ({ OTGWSerial.println(__VA_ARGS__); })
#define Debugf(...) ({ OTGWSerial.printf(__VA_ARGS__); })
//#else
// #warning Seems Debug() is already defined!
#endif
@ -105,8 +105,8 @@ void ESP8266HTTPUpdateServerTemplate<ServerType>::setup(ESP8266WebServerTemplate
if(upload.status == UPLOAD_FILE_START){
_updaterError.clear();
if (_serial_output)
Serial.setDebugOutput(true);
// if (_serial_output)
// OTGWSerial.setDebugOutput(true);
_authenticated = (_username == emptyString || _password == emptyString || _server->authenticate(_username.c_str(), _password.c_str()));
if(!_authenticated){
@ -144,7 +144,8 @@ void ESP8266HTTPUpdateServerTemplate<ServerType>::setup(ESP8266WebServerTemplate
} else {
_setUpdaterError();
}
if (_serial_output) Serial.setDebugOutput(false);
// if (_serial_output)
// OTGWSerial.setDebugOutput(false);
} else if(_authenticated && upload.status == UPLOAD_FILE_ABORTED){
Update.end();
if (_serial_output) Debugln("Update was aborted");

View File

@ -9,15 +9,36 @@
***************************************************************************
*/
#include <Arduino.h>
#include <ezTime.h> // https://github.com/ropg/ezTime
#include <TelnetStream.h> // https://github.com/jandrassy/TelnetStream/commit/1294a9ee5cc9b1f7e51005091e351d60c8cddecf
#include <ArduinoJson.h> // https://arduinojson.org/
#include "Wire.h"
#include "Debug.h"
#include "safeTimers.h"
#include "networkStuff.h"
#include "OTGWSerial.h" // Bron Schelte's Serial class - it upgrades and more
#include "OTGW-Core.h" // Core code for this firmware
#include "OTGW-upgrade.h" // Schelte Bron's upgrade PIC code
//OTGW Nodoshop hardware definitions
#define I2CSCL D1
#define I2CSDA D2
#define BUTTON D3
#define PICRST D5
#define LED1 D4
#define LED2 D0
#define FIRMWARE "/gateway.hex"
extern OTGWSerial OTGWSerial(PICRST, LED2);
void fwupgradestart(const char *hexfile);
void blinkLEDnow();
void blinkLEDnow(uint8_t);
void setLed(int8_t, uint8_t);
//Now load network suff
#include "networkStuff.h"
//Defaults and macro definitions
#define _HOSTNAME "OTGW"
@ -45,6 +66,7 @@ const char *flashMode[] { "QIO", "QOUT", "DIO", "DOUT", "Unknown" };
//Information on OTGW
String sPICfwversion = "";
bool bOTGWonline = true;
//All things that are settings
String settingHostname = _HOSTNAME;

View File

@ -30,14 +30,18 @@
#include "OTGW-firmware.h"
#define ON LOW
#define OFF HIGH
//=====================================================================
void setup()
{
Serial.begin(9600, SERIAL_8N1);
while (!Serial) {} //Wait for OK
Serial.println(F("\r\n[OTGW firmware - Nodoshop version]\r\n"));
Serial.printf("Booting....[%s]\r\n\r\n", String(_FW_VERSION).c_str());
// Serial is initialized by OTGWSerial. It resets the pic and opens serialdevice.
// OTGWSerial.begin();//OTGW Serial device that knows about OTGW PIC
// while (!Serial) {} //Wait for OK
OTGWSerial.println(F("\r\n[OTGW firmware - Nodoshop version]\r\n"));
OTGWSerial.printf("Booting....[%s]\r\n\r\n", String(_FW_VERSION).c_str());
rebootCount = updateRebootCount();
@ -45,42 +49,46 @@ void setup()
randomSeed(RANDOM_REG32); //This is 8266 HWRNG used to seed the Random PRNG: Read more: https://config9.com/arduino/getting-a-truly-random-number-in-arduino/
lastReset = ESP.getResetReason();
Serial.printf("Last reset reason: [%s]\r\n", CSTR(ESP.getResetReason()));
OTGWSerial.printf("Last reset reason: [%s]\r\n", CSTR(ESP.getResetReason()));
//setup the status LED
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH); //OFF
pinMode(16,OUTPUT);
digitalWrite(16,LOW);
setLed(LED1, ON);
setLed(LED2, ON);
//start the debug port 23
startTelnet();
Serial.print("Use 'telnet ");
Serial.print(WiFi.localIP());
Serial.println("' for debugging");
OTGWSerial.print("Use 'telnet ");
OTGWSerial.print(WiFi.localIP());
OTGWSerial.println("' for debugging");
DebugT("Waiting");
Debugln();
//================ LittleFS ===========================================
if (LittleFS.begin())
{
Serial.println(F("LittleFS Mount succesfull\r"));
OTGWSerial.println(F("LittleFS Mount succesfull\r"));
LittleFSmounted = true;
} else {
Serial.println(F("LittleFS Mount failed\r")); // Serious problem with LittleFS
OTGWSerial.println(F("LittleFS Mount failed\r")); // Serious problem with LittleFS
LittleFSmounted = false;
}
readSettings(true);
// Connect to and initialise WiFi network
Serial.println(F("Attempting to connect to WiFi network\r"));
digitalWrite(LED_BUILTIN, HIGH);
OTGWSerial.println(F("Attempting to connect to WiFi network\r"));
setLed(LED1, ON);
startWiFi(_HOSTNAME, 240); // timeout 240 seconds
digitalWrite(LED_BUILTIN, LOW);
for (int i=0; i<=3;i++) {
blinkLEDnow(LED1);
delay(250);
blinkLEDnow(LED1);
delay(250);
}
setLed(LED1, OFF);
startMDNS(CSTR(settingHostname));
delay(1000);
// Start MQTT connection
startMQTT();
@ -129,20 +137,15 @@ void setup()
httpServer.on("/api", HTTP_ANY, processAPI); //was only HTTP_GET (20210110)
httpServer.begin();
Serial.println("\nHTTP Server started\r");
OTGWSerial.println("\nHTTP Server started\r");
// Set up first message as the IP address
sprintf(cMsg, "%03d.%03d.%d.%d", WiFi.localIP()[0], WiFi.localIP()[1], WiFi.localIP()[2], WiFi.localIP()[3]);
Serial.printf("\nAssigned IP[%s]\r\n", cMsg);
for (int i=0; i<50; i++){
blinkLEDnow();
delay(200);
}// 50* 200 = 10.0000 msec = 10 seconds of blinking
OTGWSerial.printf("\nAssigned IP=%s\r\n", cMsg);
DebugTln("Setup Watchdog");
initWatchDog(); // setup the WatchDog
Serial.println(F("Setup finished!\r\n"));
OTGWSerial.println(F("Setup finished!\r\n"));
// After resetting the OTGW PIC never send anything to Serial for debug
// and switch to telnet port 23 for debug purposed.
// Setup the OTGW PIC
@ -150,29 +153,44 @@ void setup()
resetOTGW(); // reset the OTGW pic
DebugTln("Start OTGW Stream");
startOTGWstream(); // start port 25238
DebugTln("Fetch PIC firmware");
sPICfwversion = getpicfwversion(); // fetch the firmware version
DebugTf("OTGW PIC firmware version = [%s]\r\n", CSTR(sPICfwversion));
DebugTf("Reboot count = [%d]\r\n", rebootCount);
pinMode(16,OUTPUT);
digitalWrite(16,HIGH);
setLed(LED1, OFF);
//Blink LED2 to signal setup done
for (int i=0; i<=3;i++) {
blinkLEDnow(LED2);
delay(250);
blinkLEDnow(LED2);
delay(250);
}
setLed(LED2, OFF);
}
//=====================================================================
//===[ blink status led ]===
void blinkLEDms(uint32_t iDelay){
void setLed(uint8_t led, uint8_t status){
pinMode(led, OUTPUT);
digitalWrite(led, status);
}
void blinkLEDms(uint32_t delay){
//blink the statusled, when time passed
DECLARE_TIMER_MS(timerBlink, iDelay);
DECLARE_TIMER_MS(timerBlink, delay);
if (DUE(timerBlink)) {
blinkLEDnow();
}
}
void blinkLEDnow(){
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
blinkLEDnow(LED1);
}
void blinkLEDnow(uint8_t led = LED1){
pinMode(led, OUTPUT);
digitalWrite(led, !digitalRead(led));
}
//===[ no-blocking delay with running background tasks in ms ]===

169
data/diagnose.hex Normal file
View File

@ -0,0 +1,169 @@
:020000040000FA
:080000008A1500278A150A2861
:08000800F000030E8301A000CB
:100010000408A1000A08A2008A01230882073728E1
:1000200037284028402832283728162883161C1BDA
:100030009C1F2228831281019101B201B3018C100F
:100040000D1337281C0D83121211B11F803E0318A7
:100050003028010831060339B10631170B13202867
:1000600012152028101083161C0883120D13220865
:100070008A0021088400200E8300F00E700E090013
:100080008A1583161C0883123106B1063205031D3A
:0800900097230D138A11372894
:041000000034003484
:0C1004006400061D022898011A088A15D5
:1010100000278A1583018316E73085002730860074
:1010200007309B00E6309D00193099001815181202
:101030009816831298171816900183018B13831644
:10104000D730810006309C000D17831203170A3039
:101050008F00D8308D00482203170A308F00F130FE
:101060008D004822831710308400981C3A281A08F3
:101070001812181664008C1E3A28181902281A082B
:101080008000E03903194C286F30040203183A2815
:1010900000088D22840A3A2808308A000008533E4E
:1010A00003188A0A82003A283A283A283A283A2825
:1010B0003A283A283A2872283A283A283A283A28E8
:1010C0007D283A283A283A283A283A283A283A28CD
:1010D0003A283A283A283A283A283A283A283A2800
:1010E0003A283A281030040203193A2884030830B9
:1010F0008D228D2208308D223A2880011030840004
:10110000A301800803199D281A302302031896288A
:101110002308A307A30DA307A30D0008840A393CE5
:10112000093C031C9628A307031C812803170B30D6
:101130008F0036308D0048221D2807302302031807
:101140009628442208308A00A930230703188A0A07
:101150008200B028B928DA28DA28F1285A29DB29B0
:101160001030040203191D288610831686108A1178
:101170000028B2010130B1008316D73081008312FC
:10118000640019220319D7280B1DC0280B11B10BBD
:10119000C0280130B1000310B20DB2080319B21516
:1011A000B21AB20DD830860432098605C028D8306C
:1011B00086041D2883161C088312B10040302318B2
:1011C0008030B200A501A030B300B4000D130B179E
:1011D0008B1710146400192203191D2825181F22CB
:1011E000EA28831603309C008312851105129001B2
:1011F0008E018F010C10101464000C18282983161E
:101200001C088312C039031DFC280B178B1703170A
:101210000B308F006C308D00482208302F210317CF
:101220000B308F0076308D00482208302F210317B5
:101230000B308F0080308D00482210302F21031793
:101240000B308F008A308D00482210302F211D284E
:1012500003170B308F003E308D0048221D2890016F
:101260008E018F010C101014850664000C18522991
:1012700010183529EE300E07AC000F08031C0F03C1
:10128000AB0083161C0E8312A700050C27060C3931
:10129000031D5329A62203170B308F0094308D00B5
:1012A00048220800101003170B308F0056308D00B5
:1012B00048220800831600309F00D030810083123E
:1012C00003170B308F005C308D00482200308A21DC
:1012D00003170B308F0062308D00482208308A21BE
:1012E00050309F00392283161E088312AB002B0D4D
:1012F0001E08AC00AC0DAB0DAC0DAB0DAC0703186C
:10130000AB0A03170B308F0066308D00482269222C
:1013100044221D28403A9F001030A600333084003C
:101320008313FF308000840AA60B92294030B2005C
:10133000A701392264001E08B10039221E083102BB
:10134000031C003C023C031CA701A70AA71DB329EC
:101350001E0E0F39333E84001E0EF03980008316B6
:101360001E0E80048312A60B9A29B20B9A293A30DA
:10137000A700333084000018D42927088D228D223D
:1013800033300402A700AB000310AB0C000CAC0020
:10139000AB0CAC0C000E0F39A70E2707AC070318D7
:1013A000AB0A69222C30A700840A43300402031CD4
:1013B000BB2944220800B10164008316D8308100A3
:1013C000F93092009C088312053092000D130B1720
:1013D0008B176400192203191D28311BF6298C1C58
:1013E000E929B30A0319B20A8C10E929B11E122A9D
:1013F0003208AB003308AC005430B11B42308D22B0
:101400003A308D228D22A622AB010310110DAC00C3
:10141000AB0DAC0DAB0D31080339AC042E308D2271
:10142000B22244228030B1063113B11612150B17C7
:10143000E92903118C1E08001A080D3C0800340825
:10144000840083170008AB0083130008AC00B40AC3
:10145000A622340833020319302A2C308D220800CA
:10146000A510A030B300B40025102E308D224422E8
:1014700008001F14FA3081000B110B1D3D2A1F15A7
:101480001F19402A1F1008000D308D220A308D2AA6
:1014900083168C018C170C140000000083120C0DB5
:1014A0000E0D031360220319080003170C08031321
:1014B00060220319080003178D0A03198F0A482AAE
:1014C0007F391A3A031908001A3A031D8D2A0311AD
:1014D00008002B0875226430A7002C08C722AC1B1B
:1014E000AB0A2B08A7002E307C2A2511A7009C3EB2
:1014F000031C7E2AA70031308D222515A60127085E
:10150000A700F63E031C862AA60A802A260803198D
:1015100025198B2227082515303E64000C1E8D2AC4
:10152000990020341030A600A801A901AA019E2A22
:101530002A08C022AA002908C022A900AC0DAB0DC0
:10154000AA0DA90DA80DA60B982A08009222251114
:101550002808B7222908B7222A08B7222519080027
:1015600030308D2A922225152908BB222A08A7008F
:10157000270EBB2227080F39031925198B2A0800CB
:10158000333EA700A71DFD3EA71FD03E0800AB01BC
:10159000AC01083AA600083AA6060310AC0DAB0D44
:1015A000A70D0318AC070318AB0AA60BCD2A080039
:1015B0008A06F027EE32683AF232A036E133653A15
:1015C000E13BA03C6932E7306F37F439E334A039AE
:1015D000A016652B7339EF342037AE1800198A0630
:1015E0001A05AE184C10C4227410F3320D3A0005DF
:1015F0002E194210F4347410ED34EE34A033683AEE
:10160000F232EF36F439F4308A06AE194210F4346F
:101610007410ED34EE34A0336F31EC34F2328A06BC
:101620002E1A4410EC32F9307310ED3CE536723A64
:101630008D3C0005AE1A5610EC37613AE5336C105C
:10164000F632EC328D3900052E1B49106C32A03277
:10165000693AE5368D390A05EE22653A2039653A50
:10166000F4396E10ED3A65313A391A108A06EE24D3
:10167000613B69362032653AF439000DA311A0119F
:10168000F2226F393A3949107437F2326133E53159
:10169000A0396F322737203AF0306538F2307410B5
:1016A000A03765316C10EF3765381A32A311A011DD
:1016B000F2226F390D391A05682AF232EF36F43901
:1016C000F430000D6F21EC34F232000D65296533E2
:1016D00065396337BA321A10CB27C1186810E7345E
:1016E0002D346F3AEC16F737201D000DCB27C118AB
:1016F0006C10F737F416AD376934E833201D000D50
:10170000CB27C2186810E7342D346F3AEC16F73740
:10171000201D000DCB27C2186C10F737F416AD371B
:0E1720006934E833201D000DF33A8A06000DEF
:02172E000F08A2
:10173000AF000E08B0000F082F060319A62BAF0646
:101740000E08B000F930B007031CAF03A51CB92B7D
:101750003309F03903190800330884002E083002D9
:10176000800083172D08031C013E2F028000B30A5E
:0E17700025143008AE002F08AD00A5140800A7
:101E0000031E08008B138316031360308F002730E6
:101E10008600E730850007309B00E6309D000630E5
:101E20009C00D73081001930990026309800831229
:101E300098171816FF30860081010130E327C2276A
:101E40001030E3278C1E0800C827031D08008317E5
:101E500010308400F001C8270319282F0B3A03190A
:101E6000392F013A0319C82772088000F007840A45
:101E70002B2FF008031D822F031712088D00130863
:101E80008F00143084001108F1000F308A00100810
:101E9000083C083C031C822F8207592F5F2F872F95
:101EA000992FA12FAC2F822F822FED2F0101000F30
:101EB000FF0F56308D000F308F00123084008316D4
:101EC0008C170C140000000083120C088000840A98
:101ED0000E088000840A8D0A03198F0AF10B5F2F08
:101EE00010300402F1000F30C227F00110308400DE
:101EF0000008F007840AB527F10B782F7009013E1E
:101F0000B527C2270313C8270319282F822F84302F
:101F1000D127FC308D050430F40000088C00840AC1
:101F200000088E00840AD527F40B8D2FF10B872F24
:101F3000722F9430D1271F308D04D527F10B992FA4
:101F4000722F83168C010C1483120C088000840AF3
:101F50008D0AF10BA12F702F0430D12700088C00BF
:101F6000840AD527F10BAC2F722FF3000F3A031917
:101F7000BF2F0B3A0319BF2F013A031DC12F0530A4
:101F8000C2277308640003130C1EC42F9900043485
:101F90009818ED2F64008C1ECA2F1A08F2000F3A11
:101FA000080083168C0083120800640083165530E5
:101FB0008D00AA308D008C148C18DC2F83128D0AB2
:101FC00003198F0A013464008C1A08000B1DE32FDB
:101FD0000B11FF3E031DE32F0434031386108316F9
:101FE0008610FF308500860081009B0007309C0032
:101FF00098019901830198018B018A0164000028EE
:02400E007C3FF5
:02401000FF3F70
:00000001FF

1
data/diagnose.ver Normal file
View File

@ -0,0 +1 @@
1.2

532
data/gateway-4.3.hex Normal file
View File

@ -0,0 +1,532 @@
:020000040000FA
:080000008A1500278A15872CE0
:08000800F000030E8301F1007A
:100010000408F2000A08B0008A111108E4008C18E4
:10002000D3250D1B4B2530088A0072088400710E01
:080030008300F00E700E0900C0
:08003800751B3C28751A082312
:100040007508F90076087A06031DE701FA067708B5
:10005000FB007808FC00DB125B178820ED01F3221F
:1000600003193528DB1E08006728DB165B13A62260
:10007000DB1E0800F6006728DA1576084E0603191D
:10008000E013751E0823F322F51A751E5128031973
:100090004C2855398007542876088A1596228A11EB
:1000A0005428FF3A601F80056013DB17DB187D289A
:1000B000DB1A5F288820DB1A61190800672888206E
:1000C00040305B1F7030DA22DB135B1F882078081A
:1000D00077067606F5137506F300F30E7306F30044
:1000E000F30CF30CF3060130F318F3067318F5174D
:1000F0005230751B41308A11D22B88205030F500C8
:100100000430F600AA30F7003908F800DB10672841
:10011000F61B5D2B00308A007608913E03188A0A90
:100120008200292959296F29672B84298D29932930
:100130005D2B5D2BA629892A972A892A972AB62919
:10014000682BBE29672B682B682BEE29682B682B40
:100150005D2B682B672B682BF729682B682B682B86
:10016000682B682B682B682B682B5D2B5D2B5D2B18
:100170005D2B5D2B5D2B5D2B5D2B5D2B5D2B5D2B3F
:100180005D2B012A0B2A682B682B682B682B682BA8
:10019000682B152A352A682B682B682B682B682B4F
:1001A000682B5D2B5D2B5D2B5D2B5D2B5D2B622BFF
:1001B000552A682B682B682B682B682B682B682BBB
:1001C000682B682B682B682B682B682B682B682B97
:1001D000682B892A972A892A972A5D2B5D2B5D2B0C
:1001E0005D2B5D2B5D2B5D2B5D2B5C2A622B682BC1
:1001F000682B682B892A972A892A972A5D2B5D2BE1
:100200005D2B5D2B682B682B682B682B682B682B6C
:10021000682B682B682B682B682B5D2B782A7E2A2D
:10022000682B603017297908C038F51F7F397506AB
:10023000031DDB16F50600347706031DDB16F706F3
:1002400000347B081C217C087806031DDB16F806A9
:100250000034751B3929A0227708C40803193329F3
:100260000138E11BFE396E1E1C29FD39EE1A0238D9
:100270001C29F51A08007808FC00413903195A12A4
:10028000031D5A1A47295A160530CE00E0174D3083
:100290007E237808083946307E23780804395730A1
:1002A0007E237808023948307E23770802394330AC
:1002B0007E2B751B6529A02244084506031D751E6B
:1002C000080044081C2145082429F51E0800751A59
:1002D0000800C40803190800C401C5010800751FFF
:1002E000772901307B051C217C08242113297718EC
:1002F000DE17631A080078080B3C0319E31B08009B
:10030000E317DE1B63170800751F0800AA30770289
:10031000031D0800132139082429751B682B5F1A57
:100320005F1B0800DC29751F080060100301F51E23
:10033000751A9B29780861060339E1061321611CAF
:10034000E010E11C6011770803381C29751F0800B4
:1003500013215F1E3A081C215F1E3B0824215F13F6
:10036000E31ADF1D08005F1DDB140800751B080081
:10037000A022611F080058081C212429751B13297D
:10038000DF195F1B08005F1ADC293B087802F300C5
:100390003A08031C013E7702031CFF3A031DE329C0
:1003A000031CF309E0307305031DE3295F190800FE
:1003B0005F15DF134F30802B5F123A083B0403199F
:1003C000EB295F1708005F1DDF0A5F1D0800631B34
:1003D000EB29BA01BB01DF014F308C2B751F0800E0
:1003E0001321D31F21293E081C213F082429751BF6
:1003F0005A1C0800DA18112913213C081C213D0859
:100400002429751F0800E010F51A682B7708D00022
:100410007808CF00682B751F08006011F51A682B4B
:100420007708D2007808D100682B751B232AC008F2
:10043000751EE019031908001030172140081C210F
:10044000410824213834E011F51E0800751E2F2ABA
:1004500013214008031950081C2141082429C00811
:1004600003190800C001C1010800751B432AC20816
:10047000751E601A031908001030172142081C214C
:100480004308242139346012F51E0800751E4F2AD6
:1004900013214208031952081C2143082429C208C9
:1004A00003190800C201C30108000310460C031819
:1004B000751B080024211C29751F0800DF1AD60EA1
:1004C000DB126823DB1A6B2A1321560E0339242111
:1004D0006B1B78081C21631BDF1E762A560E5606FE
:1004E000031D5F1B762A5F16DF155F17DF120800FA
:1004F000751F0800132103301C212429751FE31FD9
:10050000080063137708143C0319E316031C6317F0
:100510000800751F0800DB1ADB1F682B7708F51E23
:1005200003190800E800760ACE00E0170800751BE2
:10053000DB1E622BE90A68086902031CE017080049
:10054000751B0800F322FF3A800508000030F50013
:10055000F701F801E0080319BF2A60176018063494
:10056000E018303460193134E0191C2A601A3C2A32
:10057000E01FBE2A6908F7004E080800E0014D0898
:10058000031DE32A5B1AD92A2030FD004A0A1F39CD
:10059000CA00E03E8A152F268A1183128D00831629
:1005A0000C1483120C080313031D0800FD0BC62A4C
:1005B0005B16DB127904F5007B08F7007C08F80075
:1005C0007A08F60008001030F5007430FD00F301E1
:1005D0000314EB2AFD0AF30D73084D050319EA2AEB
:1005E000CD067D0808007608F400740CF300730C47
:1005F0001F39BA3E8400F41B0034033074180C30E9
:10060000F300F418F30E00097305F30E730E0800DF
:10061000760D031CF51A0800F300730E0F39F30072
:1006200076080739FD00FD0A2E237306F3067306CC
:10063000B10103100318B10AF30CFD0B1A2B031CB4
:1006400008004523B107310D103E84008317770859
:100650008000840A780880008313080003308A0031
:100660007308353E03188A0A82004334C0340734C5
:100670001F340034003403340334003400340034B5
:10068000003400340034F0340F34F30003308A00B7
:1006900073084D3E03188A0A82000034033405347F
:1006A00008340D340D340D340F3411341134113439
:1006B00011341134113411341534DB1BDB1E751F5A
:1006C00008006E2BDB1BDB1E751F08006D2BA022A4
:1006D000DB1BDB1E751F0800FB01FC0176088A1579
:1006E00045238A11031D08001321831700087C0489
:1006F00024218413000883137B041C2903198C2BE9
:100700005F3E84000014FE30000503190800FF3A24
:100710008605F938E20500345F3E840000100008C9
:0C0720000319080086040639E2040034C6
:04072C008A152F26D5
:100730008A1183128D009F2BB72303178D0A83160E
:100740000C1483120C080313031D9C2B0800962322
:100750000D30B7230A30B72BF400740EB0237408A1
:100760000F39F63E0318073E0A3EDA17303ECC0832
:1007700003190C1EBD2B99000034840037084C0768
:10078000B03E031C503E903E0406840604068317C8
:10079000800083134C08503A031DCC0A00345430B7
:1007A000751B42305B190800B7237508AC23760827
:1007B000AC237708AC237808AC23A82B5E1908007B
:1007C0008A3096236508AC23A8234530651CD223C4
:1007D000E50147080319080084000008F3004708F2
:1007E000AC233D30B7237308AC23A82B4B084B0731
:1007F000103E840083170008B400840A0008B50086
:10080000831304308A004B08CB0A093E03188A0A76
:100810008200222C3A2C222C3A2C4A2C3A2C3A2CAC
:100820003A2C3A2C3A2C3A2C312C3A2C4A2C4A2C81
:100830003A2C3A2C6D2C6D2C6D2C6D2C6D2C6D2C56
:100840006D2C6D2C340827242F30B7233508F30086
:100850000830FD00F30D2F24FD0B2A2C0800070D96
:10086000B52BB41F3A2CB409B509B50A0319B40A5B
:100870002D30B723350F3E2CB40AB50134084F2470
:100880006430F30035083A25B51BB40A3408F30088
:100890002E305C2C34084F242F30B7233508DA1360
:1008A000F3009C3E031C5E2CF3009C3E031C5B2C5F
:1008B000F30032305C2C3130B723DA17FD017308B6
:1008C000F300F63E031C662CFD0A602C7D0803191C
:1008D000DA1B6B247308DA17B52B1030FD00B10159
:1008E000B201B301792C33088A24B30032088A2478
:1008F000B200B50DB40DB30DB20DB10DFD0B732CDF
:10090000DA13310891243208912433089124DA1B38
:100910000800B52B333EF300F31DFD3EF31FD03E20
:100920000800F300730E952473080F390319DA1BBE
:10093000B52B08003608043C031D623404308A00DD
:1009400023085A3C193C031C6834A93E03188A0A40
:1009500082000F349134A434683468346834182D1C
:100960006834122D683468340434E52C6834CB2C98
:10097000F92CEA2C012D1B2D0A2D6834C72CF22CE2
:100980006834683468342308B7233D30B72BC32458
:100990006B08FD3EB02BC324DF084E300319B72B84
:1009A0003A083B066E300319B72B560E56060F3920
:1009B000DF1ED6065430D61C43305F1D2038B723C7
:1009C0003A08B4003B08B5003A2CC32447307E18DF
:1009D0004D30B72BC3247E0E0739AC3E8A153B261B
:1009E0008A11B72BC3243030EE1A31306E1E4130DD
:1009F000B72BC3245E1C80347430DE187B30962302
:100A00008334C3244430E31B5230E31A4330631B66
:100A10004930B72BC3246B0EF300F30CF30C2F24D7
:100A2000F30C2F2CC324050D803E2F24050D2F2CF5
:100A3000C324590EAC2BC32402308A153B268A11DD
:100A4000B40003308A153B268A11B5003A2C3608CB
:100A5000043C031D62342308313C013C031C683410
:100A60000319362DCB015A155B15382D5A115B1120
:100A70008A11B52BB401B501083AFD00083AFD060C
:100A80000310B50DB40DF30D0318B5070318B40A20
:060A9000FD0B402D0800E3
:0A0A960083161C0E83120D135C067C
:100AA0000C3903190800DC0604390319DE1D5B2D1F
:100AB000FF30E5000800031DDE19632DDE15B808C0
:100AC00003195C1A812DB8080319A22D03305D02A9
:100AD000031C462E83161C0D8312DE19803EB80BB4
:100AE000902D031C4B2EDC1B4F2E5B148A115230B1
:100AF0008C2354308C2342308C238A11DE11121146
:100B00009F2DB8015C1218305E18083005061839A0
:100B100085068A1158308C2342308C238A11982DF7
:100B200080300318DC06F80DF70DF60DF50D5C139B
:100B3000DD01640891020630031C91028C106430C0
:100B4000810008001219AF2DE508031D9F2D2A30E2
:100B500091001215DD0183168C1483129F2D0A302B
:100B60005D020318982D83161C0D8312DE19803E3A
:100B7000031C9F2D83161C1E031083120318DE18FE
:100B8000C32DDE145E15DD0803197F2D8A11523046
:100B900080234230DE19543080238A112130B8007E
:100BA000DC135C13982D8C10DD0A5C1AF12DB8084B
:100BB0000319DE1DEE2D5D08143C03191B2E503069
:100BC0005D02031C08001211DE1183161C1E0310A7
:100BD0008312031C0800DE145E150800DD194D2E7B
:100BE00008005D180800B80803190B2E03015C1CEF
:100BF00018305E18103A050648058506DD18182ECF
:100C00005C100314F80DF70DF60DF50D03185C14C8
:100C1000DD01B803080012115C12481ADC168A11B3
:100C200058308C2354308C2342308C238A11080096
:100C30000130DC0608005C190800DE1F372E831621
:100C400010309C061C1E03101C0E83120D135C0634
:100C50000C39DC060318392E5E15DE1C08005E1008
:100C6000DE10051650308A118C238A110800DE161A
:100C700008005E18422E5E14051250308A1180233F
:100C80008A110800DE1408005C179F2D5C1BEB1A0C
:100C9000442E0130502E0230502E0330502E04309E
:100CA000E5080319E5001211B801DD015C128A1193
:100CB00058308C2352308C2342308C2354308C2378
:100CC00065090319672E453080237A30E6008A11C2
:020CD0009F2D56
:0E0CD200031DC02E5A1BDA0106308A005A0894
:100CE0001F39763E03188A0ADA0A8200832EE92E1B
:100CF000912E0034832EE72E942E832EE92E9F2EE4
:100D0000A12EA52EC02E851383168513C226831609
:100D100085178312C526851B8F2EC3260134DA144E
:100D2000C02E4430EA260034D6267308103C03193E
:100D300001347308283C031D8F2EDA170134BE30AE
:100D4000EA2ED6267308DB000134D626DA1BAE2E37
:100D5000730C5B0CB400B501B50CB82E5B0EF0390A
:100D6000B500730EF039F3005B0E0F397304B40055
:100D70005A14DA14553A0319C02E8A15C9210134C0
:100D80005A170034C326E830C62E363083168C102E
:100D9000120283120A3E910012158C1CCD2E1211E4
:100DA0008C100800D426D42600000800D726DA26A6
:100DB000DA26DA2685138316851303108517831226
:100DC000D326851B0314F30C2D30C62608003330C0
:100DD000EA2ECC30F300EC26EF26EF26EF26F30CBC
:100DE000851383168513031885173230C62683169C
:060DF00085178312013497
:0A0DF6006217E21300276213E217F0
:100E000007308A005908E21B590E07390A3E0318B9
:100E10008A0A8200152F212F242F242F242F152FEB
:100E2000152F122FF030E21FD9056208C039831642
:100E300085048312080062093F38831685058312F2
:100E400008001B27850508001B27FF3A85040800BA
:100E50006217E2132D276213E21707308A00590840
:100E6000E21B590E0739373E03188A0A8200080030
:100E7000080008003F2F462F572F592F4D2F0508E8
:100E8000E21805096205C0398506080005086219DF
:100E900005096205C03985060800DC1E0800B8088F
:100EA0008A1169268A1100380319DC120800050925
:100EB0005A2F05086205C039031D642F621C080003
:100EC0006210B401B5016F2F62180800621402307D
:100ED0008A153B26B40003303B26B50001308A1545
:060EE00035218A11080013
:041000000034003484
:0C1004007E19442804303602031C6234BC
:1010100022083D3C031D623408308A002008210666
:10102000F300E039031D5F3420088A11B72321083B
:10103000B7233A30B7232030B72308308A0073082B
:10104000243E03188A0A820046285128592861281C
:1010500066286E28F3287628BC28BC28BC287B2864
:101060005F34BC28BC28BC2880288B2893285F3498
:1010700098285F345F349D285F345F345F34A22842
:10108000AA28AF285F34B7287E1171342008543A5B
:1010900003192D29153A03196B2A0C3A0319EA2A68
:1010A0005F342008523A0319A42B013A0319002B8C
:1010B0005F342008503A0319FC2A1B3A03196A2BA3
:1010C0005F342008503A0319FE2A5F342008563A4C
:1010D0000319332A053A031971295F342008443A69
:1010E0000319892A123A0319AC29F32820084F3A28
:1010F00003199F2B5F342008433A03192B2A5F34CE
:101100002008533A0319E029143A0319BF2A043A74
:101110000319A3295F342008433A0319362B103AE8
:10112000031963295F342008463A0319AA2A5F3459
:101130002008443A0319D6295F342008543A031989
:1011400028295F3420084F3A0319BC291C3A031997
:101150008A295F342008553A0319512B5F3420083F
:10116000493A0319912B193A0319CE2B5F34200801
:10117000483A03191B2A5F3420084C3A031D5F3498
:101180003608043C031D62342308F3005A3C193C22
:10119000031C683441302102063E4F2223088A1185
:1011A000B7238A1541302102F3002308B400083028
:1011B000F318403073190230B10003107318B10DE9
:1011C000A03084001A30FD0031098005840AFD0B2F
:1011D000E52834085F3E8400310880043408001C90
:1011E00003158A117E2B2008473C031D5F34360807
:1011F000043C031D623430302302F300F839031D30
:101200006234F03021180A295905703C03195A102C
:10121000F30E0F3059057304D900F30001304F224B
:101220006217E213C030211CE2068A110027590818
:10123000211C590E07398A11B52B03103608043AC0
:10124000031D62342308313C013C03180800683454
:101250001624031808000130312916240318080049
:1012600003305A1B62343521C72956060F39D6067A
:101270000030631F40293A083B04031D5F161030FD
:10128000DF053508BB003408BA00DF155F17DF162D
:10129000B901E31ADB143B0403195F29E31E0800BC
:1012A0003A0856243508B9003B0856243408B907D3
:1012B000B51BB90A3A08B4003B08B50008005F1630
:1012C0005610D61008001624031808003504031D14
:1012D0005A1B623402304F223508F30003304F228C
:1012E000C7291624031808003504031981294F085B
:1012F0007824031C683450087824031D031C8329B8
:101300006834E01185296118E0153508C1003408FA
:10131000C000C729162403180800350403199A29A8
:1013200051087824031C683452087824031D031CD8
:101330009C29683460129E29E11860163508C300A4
:101340003408C200C7291624031808005A1B623447
:10135000C4003508C500C729DD230318BA29800851
:10136000031D6234643C031C6E34730DC6007308A5
:101370008A114F2CC601C329162403180800B41F74
:10138000341FC6295A102D308A11B72BC9218A1152
:10139000312C3408BC000317A60003133508BD0028
:1013A0000317A70003135A14DA1008003608053C87
:1013B000031D6234F92303180800C7008A11AC2BFF
:1013C000DD2303180800BE00173C031C6E34000820
:1013D0003A3C031D6234840ADE2303186234BF00E2
:1013E0003B3C031C6E3400082F3C031D6234840A0E
:1013F00030300002031D031C6834F300F839031D6C
:101400006834840A8008031D6234F30E0310730DE0
:10141000BE04F830D3003E081F39F3008A115D2462
:101420003F08F3003A305C242F30B7233E0EF30020
:10143000730C0739B52B3608043C031D62346E1259
:10144000EE122308313C0319EE16FE3903196E160D
:1014500049228A11F32C1D21031C0800031DE113EE
:101460000319E1171B293608043C031D62342308C5
:10147000393C093C031C6834033EF300E038831612
:101480009D008312E0306B057304EB004D228A113E
:10149000C82C6E08F3000E304F2AF30000308A1576
:1014A0002F268A1583128D007308031783160C14D8
:1014B00083120C060319682A8C0683160C158B13ED
:1014C00055308D00AA308D008C148B170C118312AF
:1014D000031373080800DD230318080003196E3492
:1014E0008008031D62345B128A152F268A15831229
:1014F000E0308D00730883160C1483128C080319D6
:10150000862A8D0A031D7B2A0313653455228A110E
:101510004F2CDD230318080003196E348008031DC7
:1015200062349622031808008A114F2CF3008A15A2
:101530002F268A158312E0308D0083160C14831237
:1015400073080C060319552A8D0A031D9D2A0313DF
:1015500003146B343608043C031D6234E301230892
:10156000433A0319E3160A3A03196317E308031D04
:1015700063166308F3000D304F228A11022D3608DE
:10158000043C031D62341D21031CE02A6E14EE0688
:101590007E060139031DD02AFE14D222FE18A300B4
:1015A00049229C2B121950347E106E1CFE197E1499
:1015B00003307E18063083169C008312FE1008004C
:1015C0002308523C031D68346C1486108316861061
:1015D0008A110028DD230318F82A8008031D6234CD
:1015E000643C031C6E346117643CD8008A114F2C94
:1015F00061136430D800C3298A119A2C8A11272DCF
:10160000DD230318080003196834F4003A3000029F
:10161000031D6234840AB401DE2303180800800825
:1016200003191E2BB4002C300002031D6234840AFF
:10163000DE23031808008008031D6234B500740817
:1016400045230319272B03014523031D6534831705
:1016500035088000841334088000831384177408CD
:1016600080008A114F243A30B7234A2CDD23031817
:101670000800031968348008031D62344523031DE4
:101680006B34800173088A114F2CF300E030840022
:10169000000873060319080001308407831C482BD7
:1016A0000034DD2303180800031DB400B41B6834A4
:1016B0008008031D62348A11F4228A1580043408DC
:1016C0008223D03E8A153B268A157304552234089E
:1016D0008A114F2CDD2303180800031DB400B41B2E
:1016E00068348008031D62348A11F4228A15FF3A97
:1016F000800534088223D03E8A153B268A15F309DB
:101700007305662B0310F4000130F4180430F30065
:101710007418F30D7419F30EF40E740D740D1F3953
:1017200008001D21031C080020302318EB04FF3A99
:10173000231CEB056B084D2223088A11B72B1D21B2
:10174000031C08004030952B3608063C031D62340C
:101750000130F3002308483A0319B42B1F3A031D44
:1017600062340430F30012302406423A0319BD2BD0
:10177000123A031D62340310F30D2508533A03197E
:10178000C52B1B3A031D6234F30E7308CD042308E6
:101790008A11B7232408B7232508B72BDD230318A4
:1017A00008008008031D6234CE00E017E801E9015B
:1017B0008A114F2C233084000800DA230008393CBA
:1017C000093C031CF72BF300840A0008393C093C50
:1017D000031CF52BB1001A30730203186E34730822
:1017E00062243107031CE32B6E34730808000314D2
:1017F0006234DA23032403180800F300F30E0324F1
:10180000031C7304080030300002031CF72BF63E63
:10181000031C122CDF39F93E031CF72BFA3E031888
:101820006234063E0A3E840A03100800DA235A177F
:1018300000082D3C03191F2C5A13023C0319840A7B
:10184000DE2303180800B40100080319422C2E3CC3
:10185000031DF72B0730FD00840A00080319422CF2
:10186000393C093C031CF72B7D196224FD18B40791
:101870000310FD0CFD080319031C2C2CFB3E031860
:10188000B40A2C2C5A1F4B2CF309B4080319542CFE
:101890003408643CB400B5016824B208031D013E5D
:1018A000B5007308B4000800F30A4B2CB401B5006E
:1018B0005E245E24B5070318B40A08000310B50DB2
:1018C000B40D0800B200B207B20DB207320D080025
:1018D0001030FD00B101B201B50DB40DB20D643090
:1018E00032020318B200B10DFD0B6C2C3108080058
:0A18F0003402031D0800B5080800CB
:0618FA009A08EA1A832C93
:10190000EA01462D6C14EC148A1500278A1503137E
:1019100083128601831660308F0007309B00E7300A
:1019200085002730860003300E0640308E18503078
:10193000831203196C0EFE00031EFE15831603307E
:101940008E00D5308100F930920083120030920071
:101950008E018F013130900020306325A030632547
:1019600083171030632581010B1164000B1DB52C0A
:1019700083161930990018151812981683129817A3
:10198000FE1D181641309F0000303B26EB00E0386A
:1019900083169D000E303B26EE008A15D4228A1550
:1019A00083160D178C141C0E83010D130C39DC00EB
:1019B0005C0DE7388500FF3086000B17FE1D8B1786
:1019C000CA090730E0001430CF005030D0000A3090
:1019D000D1005A30D2006430D8003D30D4000D30F0
:1019E0003B26E3001030FD00B401D030B1003108D7
:1019F0003B26B5003408B5080319092DB4000310BF
:101A0000B50C031C072D8A11F4228A158004340AB0
:101A1000FB2C0730B404B40AB10AFD0BF72C1130CB
:101A20008A11A7238A15F30106303B268A15D62092
:101A30008A15F30A07303B268A15D6208A15F30A41
:101A400008303B268A15D6208A15F30A09303B2632
:101A50008A15D6208A15F30A0A303B268A15D62025
:101A60008A15F30A0B303B268A15D6208A150130D9
:101A70003B26D9008A11FB268A15FE1D462D4D30C6
:101A80008A11802327308A11A7238A156400CC0885
:101A9000031D1F26FE19462D5B1896255E19C525C8
:101AA0000B19D8250C18FE250C1B45268A11282752
:101AB0008A155A190C26671B822C8C1E462D181964
:101AC0007D2C8325462D84008001840A0409703909
:101AD000031D642D08003608203E84001A08DB1917
:101AE000080080000A3A03190800073A03197D2DFF
:101AF0003608013E831CB6000800B608031908002A
:101B00008001DB150800981C882D181218167E1508
:101B10006B25DB1D08008A150220B601DB118A1136
:101B20000038031D9623A8238A15C12D8A11CF23BF
:101B30008A155B107E18A82D8A111C208A15611D3C
:101B4000AA2DDC1676087A06031DC12DD50A55127A
:101B5000E701C12D0130DD005C145C1658308A119C
:101B600080234230751B543080230830751B1030A1
:101B7000C8002230B80083168C148312F93091000B
:101B800012158A11E9238A1508005E1180305E1C47
:101B9000D42D7430DE1CD12D57087A3C031C08006C
:101BA0007B308A11962383308A11A7238A15080077
:101BB0000B11D40BE62DDA19E70A5E163D30D4007E
:101BC0006D0FED0005306D0203188511EA1EEA0A5B
:101BD000121D1F158A15FE18D2228A1165090319D4
:101BE000E501E508031DDE238A15E608031DE60B63
:101BF000080045308A118C238A1508000C10D31B6D
:101C0000D303DF195F1908008030DF065F054F300E
:101C10008A117E238A1508004C1B08008A11F623BE
:101C20008A1519304B0203181A2E2C308A11B7234B
:101C30008A1508005A118A11A8238A1508000C1E5B
:101C400008003708903E840083170008831399002A
:101C5000B70A503037060319B701CC030800031741
:101C600083168C1C0800831203138C1E2F2EF40085
:101C70006B2574082F2E2F268C0183128D0083165E
:101C80000C1483120C08031308000C131E085706CB
:101C9000D70657065702031C003CFC39031D832E50
:101CA00057087A3C0318DE1A652E743C031C632E19
:101CB000611D0800343C031C852E61114A308A11D5
:101CC000A7238A150800E115662EE1116119852EFA
:101CD000611532308A11A7238A1512110B1383164E
:101CE0001C121C0E83120D130B175C060C39DC063C
:101CF000DE01631EE301DF01BA01BB0150308A112E
:101D00008C238A150800611D08007E1C5E1E0800D9
:101D10000030F500F701F8019F26F600FA008A115D
:101D2000F3228A15031D972EB626F600FA008A11B3
:101D300067208A15DB12AA25DE01ED0108000E30AE
:101D40008A005508A63E03188A0A8200BE2E19345E
:101D5000CA2EB62E11341B341C34DC2EB62EBE2EE9
:101D60001934CA2E38343934B62E12348A11A622C8
:101D70008A155B1E0800F501F701F801C408031D70
:101D8000E11BC32E77140319E11DC72E7714EE1A39
:101D9000F714003475164508F8004408031DDA2EC0
:101DA0000A30E11DD92E4308F8004208031DDA2E3F
:101DB0005208F801F700013475165808F7000E3480
:101E0000031E08008B138316031360308F002730E6
:101E10008600E730850007309B00E6309D000630E5
:101E20009C00D73081001930990026309800831229
:101E300098171816FF30860081010130E327C2276A
:101E40001030E3278C1E0800C827031D08008317E5
:101E500010308400F001C8270319282F0B3A03190A
:101E6000392F013A0319C82772088000F007840A45
:101E70002B2FF008031D822F031712088D00130863
:101E80008F00143084001108F1000F308A00100810
:101E9000083C083C031C822F8207592F5F2F872F95
:101EA000992FA12FAC2F822F822FED2F0101000F30
:101EB000FF0F56308D000F308F00123084008316D4
:101EC0008C170C140000000083120C088000840A98
:101ED0000E088000840A8D0A03198F0AF10B5F2F08
:101EE00010300402F1000F30C227F00110308400DE
:101EF0000008F007840AB527F10B782F7009013E1E
:101F0000B527C2270313C8270319282F822F84302F
:101F1000D127FC308D050430F40000088C00840AC1
:101F200000088E00840AD527F40B8D2FF10B872F24
:101F3000722F9430D1271F308D04D527F10B992FA4
:101F4000722F83168C010C1483120C088000840AF3
:101F50008D0AF10BA12F702F0430D12700088C00BF
:101F6000840AD527F10BAC2F722FF3000F3A031917
:101F7000BF2F0B3A0319BF2F013A031DC12F0530A4
:101F8000C2277308640003130C1EC42F9900043485
:101F90009818ED2F64008C1ECA2F1A08F2000F3A11
:101FA000080083168C0083120800640083165530E5
:101FB0008D00AA308D008C148C18DC2F83128D0AB2
:101FC00003198F0A013464008C1A08000B1DE32FDB
:101FD0000B11FF3E031DE32F0434031386108316F9
:101FE0008610FF308500860081009B0007309C0032
:101FF00098019901830198018B018A0164000028EE
:02400E00742F0D
:02401000FF3F70
:1042000066000000100000004C003D004600580011
:104210004F004D005000430000000000000041002E
:104220003D004F00700065006E005400680065009E
:1042300072006D0020004700610074006500770087
:1042400061007900200034002E0033000000570088
:104250004400540020007200650073006500740083
:104260002100000054006800650072006D006F00BE
:104270007300740061007400200064006900730022
:1042800063006F006E006E006500630074006500DF
:104290006400000054006800650072006D006F004B
:1042A0007300740061007400200063006F006E00F2
:1042B0006E006500630074006500640000004E003D
:1042C000470000005300450000004E00530000006E
:1042D0004200560000004E00460000004F00520011
:1042E00000004F00450000004D00650064006900BB
:1042F00075006D000000480069006700680000005C
:104300004C006F007700200070006F0077006500A0
:10431000720000004500720072006F007200200001
:10432000000042003D00310034003A00330030000C
:104330002000300037002D00300031002D00320009
:10434000300032003100000043003D003400200006
:104350004D0048007A0000004500430053004C0027
:0443600050004200C7
:1043A000000000000000000000000000000000000D
:1043B00000000000000000000000000000000000FD
:1043C0007400750076007700780079007A007B0031
:1043D00000000000000000000000000000000000DD
:1043E00000000000000000000000000000000000CD
:1043F00000000000000000000000000000000000BD
:00000001FF

1
data/gateway-4.3.ver Normal file
View File

@ -0,0 +1 @@
4.3

1
data/gateway.ver Normal file
View File

@ -0,0 +1 @@
5.0

190
data/interface.hex Normal file
View File

@ -0,0 +1,190 @@
:020000040000FA
:080000008A1500278A157729F3
:08000800F000030E8301F1007A
:100010000408F2000A08B0008A151108C8008C18FC
:10002000FC220D1B8A2230088A0072088400710E9F
:080030008300F00E700E0900C0
:041000000034003484
:0C1004007E1A442804303B02031C4C34CC
:1010100022083D3C031D032908308A0020082106D0
:10102000F300E039031D493420088A159A2321086A
:101030009A233A309A2320309A2308308A00730882
:10104000243E03188A0A8200493449344628493428
:101050004B284934493449346428493449344934A3
:101060004934642864286428502849344934493470
:1010700055285A2849344934493449344934493483
:1010800049345F28493449347E1255342008503C95
:1010900003198A2849342008563C031997284934F3
:1010A0002008473C0319F52849342008443C03191B
:1010B0008C2849342008453C0319EB284934200882
:1010C000493C0319DD28493420084C3C031D4934B0
:1010D0007F20031C080023088A159A238A154130B3
:1010E0002102F3000830F3184030B40003107318E5
:1010F000B40D0608231C06093405860608000310F3
:101100003B08043A031D4C342308313C013C0318CE
:1011100008004F348A15D72B3B08053C031D4C347F
:101120004C2103180800840000088A15902B3B0806
:10113000043C031D4C342308393C093C031C4F3448
:10114000033EF300E03883169D008312E0304B0528
:101150007304CB00AD208A15F12BF30000308A1503
:1011600041228A15831203178D0073088316031713
:101170000C14831203170C060319CA288C06831655
:1011800003170C158B1355308D00AA308D008C146D
:101190008B170C1183120313730808000310F4005B
:1011A0000130F4180430F3007418F30D7419F30EC1
:1011B000F40E740D740D1F3908007F20031C080005
:1011C00020302318CB04FF3A231CCB054B08AD205D
:1011D00023088A159A2B7F20031C0800031DC717BC
:1011E0000319C71323088A159A2B3B08043C031DD7
:1011F0004C342308523C031D4F34031386108316CE
:1012000086108A1100283B08083A031D4C34203010
:1012100084004D2103180800F9004D21031808002F
:10122000FA004D2103180800FB004D2103180800A7
:10123000FC000130C600451445160830791B1030FB
:10124000BE002230BD0083168C148312F930910049
:1012500012150530791FC2008A15BD2B233084007A
:1012600008000008393C093C031C4A29F300840AA1
:101270000008393C093C031C4829B2001A307302AB
:1012800003185234730869213207031C362952347B
:101290007308080003144C342E215621031808004B
:1012A000F300F30E5621031C7304080030300002D3
:1012B000031C4A29F63E031C6529DF39F93E031C4D
:1012C0004A29FA3E03184C34063E0A3E840A0310AB
:0E12D0000800B300B307B30DB307330D0800D9
:0212DE006400AA
:1012E000061D6F2998011A088A1500278A1503130D
:1012F000831286010516831660308F00E730850063
:1013000027308600FE01031EFE15D5308100F9301E
:1013100092008312003092003130900081010B1155
:1013200064000B1D9029033083169C0007309B003E
:101330001930990018151812981683129817181654
:1013400041309F00203084005030FD00803080010B
:1013500084068001840AFD0BA72900304D22CB00B2
:10136000E03883169D000D178C14830183161C0E24
:1013700083120D130C39C500450DE7388500FF3089
:1013800086000B178B173D30C00004308A158B2365
:101390008A156400BF08031D30224418052247192E
:1013A0000A220B191D220C1B5B2218196F298C1A9B
:1013B000F221C9293B08203E84001A08C4190800FC
:1013C00080000A3A03190800073A0319EC293B0880
:1013D000013E831CBB000800BB0803190800800104
:1013E000C4150800981CF729181218167E16DA2161
:1013F000C41D08008A150220BB01C4118A150038DB
:10140000031D75238C238A1508008A15B0238A15BD
:101410004410080047116430471C192A5830C71C73
:10142000162A41087A3C031C08005F308A15752390
:1014300067308A158B238A1508000B11C00B252AEB
:101440003D30C000C20B08008511121D1F158A1502
:1014500049090319C901C908031DC9238A150800D0
:101460000C1E08003C08A03E8400000899000408F7
:1014700080008013BC0A50303C060319BC01BF0336
:101480000800831603178C1C0800831203138C1E9C
:10149000412AF400DA217408412A41228C01831286
:1014A00003178D00831603170C14831203170C08FF
:1014B0008312031308000C131E084106C1064106DF
:1014C0004102031C003CFC39031D080041087A3C22
:1014D000031C762A4108733C683C0318C41C0800AE
:1014E000C41034308A158B238A150800C4180800EC
:1014F000C4141C308A158B238A1512110B13831602
:101500001C121C0E83120D130B1745060C39C50651
:04151000C701080007
:0C15140083161C0E83120D1345060C39C3
:1015200003190800C50604390319C71D9A2AFF309C
:10153000C9000800031DC719A22AC715BD08031951
:10154000451AB82ABD080319D32A03304602031CE2
:101550005D2B83161C0D8312C719803EBD0BC12A5B
:10156000031C622BC51B662B4414C7111211D02A11
:10157000BD01451218304718083005061839850690
:10158000C92A80300318C506F80DF70DF60DF50DC4
:101590004513C601480891020630031C91028C10C5
:1015A0006430810008001219E02AC908031DD02AFE
:1015B0002A3091001215C60183168C148312D02A8A
:1015C0000A3046020318C92A83161C0D8312C71954
:1015D000803E031CD02A83161C1E0310831203189E
:1015E000C718F42AC7144715C6080319B62A2130AC
:1015F000BD00C5134513C92A8C10C60A451A062B0F
:10160000BD080319282BC619642B080046180800CA
:10161000BD080319202B0301451C18304718103A48
:1016200005063E058506C618252B45100314FC0D3E
:10163000FB0DFA0DF90D03184514C601BD03080092
:10164000121145123E1AC51608000130C5060800E1
:10165000C71D08004608143C03193D2B50304602B4
:10166000031C08001211C71183161C1E03108312DD
:10167000031C0800C71447150800451DC71F0800B4
:10168000831610309C061C1E03101C0E83120D13B3
:1016900045060C39C5060318542B4715C71C08000E
:1016A0004710C710051608004718592B4714051294
:1016B0000800C71408004517D02A451BCB1A5B2B1E
:1016C0000130672B0230672B0330672B0430C908C9
:1016D0000319C9001211BD01C601451249090319B8
:0A16E000732B7A30CA008A15D02A55
:0616EA008A1541228A1559
:1016F000831203178D00802B9A23831203178D0A00
:10170000831603170C14831203170C088312031398
:10171000031D7C2B080075230D309A230A309A2B69
:10172000F400740E942374080F39F63E0318073E34
:101730000A3E303EBF0803190C1EA02B990000344E
:1017400084003C083F07B03E031C503EA03E040608
:101750008406040680003F08503A031DBF0A003487
:101760005430751B42309A237508902376089023D5
:1017700077089023780890238C2B5230791B4130C6
:101780009A23790890237A0890237B0890237C0879
:10179000902B471908006E307523490890238C233D
:1017A0004530491CB323C9010800070D992B3B089C
:1017B000043A031D4C342308413A03190234153A04
:1017C0000319EA2B023A0319F02B4F3423089A230A
:1017D0003D309A2BE6234B0EF300F30CF30CD52B84
:0817E000E6234B08FD3E942BAB
:101E0000031E08008B138316031360308F002730E6
:101E10008600E730850007309B00E6309D000630E5
:101E20009C00D73081001930990026309800831229
:101E300098171816FF30860081010130E327C2276A
:101E40001030E3278C1E0800C827031D08008317E5
:101E500010308400F001C8270319282F0B3A03190A
:101E6000392F013A0319C82772088000F007840A45
:101E70002B2FF008031D822F031712088D00130863
:101E80008F00143084001108F1000F308A00100810
:101E9000083C083C031C822F8207592F5F2F872F95
:101EA000992FA12FAC2F822F822FED2F0101000F30
:101EB000FF0F56308D000F308F00123084008316D4
:101EC0008C170C140000000083120C088000840A98
:101ED0000E088000840A8D0A03198F0AF10B5F2F08
:101EE00010300402F1000F30C227F00110308400DE
:101EF0000008F007840AB527F10B782F7009013E1E
:101F0000B527C2270313C8270319282F822F84302F
:101F1000D127FC308D050430F40000088C00840AC1
:101F200000088E00840AD527F40B8D2FF10B872F24
:101F3000722F9430D1271F308D04D527F10B992FA4
:101F4000722F83168C010C1483120C088000840AF3
:101F50008D0AF10BA12F702F0430D12700088C00BF
:101F6000840AD527F10BAC2F722FF3000F3A031917
:101F7000BF2F0B3A0319BF2F013A031DC12F0530A4
:101F8000C2277308640003130C1EC42F9900043485
:101F90009818ED2F64008C1ECA2F1A08F2000F3A11
:101FA000080083168C0083120800640083165530E5
:101FB0008D00AA308D008C148C18DC2F83128D0AB2
:101FC00003198F0A013464008C1A08000B1DE32FDB
:101FD0000B11FF3E031DE32F0434031386108316F9
:101FE0008610FF308500860081009B0007309C0032
:101FF00098019901830198018B018A0164000028EE
:02400E00742F0D
:02401000FF3F70
:104200002600000041003D004F00700065006E0078
:1042100054006800650072006D00200049006E00C7
:104220007400650072006600610063006500200094
:1042300031002E003100000054006800650072005B
:104240006D006F0073007400610074002000640052
:104250006900730063006F006E006E00650063000C
:10426000740065006400000054006800650072007E
:104270006D006F0073007400610074002000630023
:104280006F006E006E0065006300740065006400DE
:1042900000004E00470000005300450000004200AF
:1042A000560000004F00520000004F004500000083
:1042B0004D0065006400690075006D000000480055
:1042C00069006700680000004C006F007700200064
:1042D00070006F00770065007200000045007200FA
:1042E00072006F00720020000000310037003A00B9
:1042F000350039002000320030002D003100300040
:104300002D00320030003100350000003400200064
:084310004D0048007A00000096
:00000001FF

1
data/interface.ver Normal file
View File

@ -0,0 +1 @@
1.1

View File

@ -0,0 +1,697 @@
/*
OTGWSerial.cpp - Library for OTGW PIC communication
Copyright (c) 2021 - Schelte Bron
MIT License
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include <Arduino.h>
#include <LittleFS.h>
#include "OTGWSerial.h"
#define STX ((uint8_t)0x0F)
#define ETX ((uint8_t)0x04)
#define DLE ((uint8_t)0x05)
#define XFER_MAX_ID 16
// Relative duration of each programming operation (each unit is actually about 21ms)
#define WEIGHT_RESET 8
#define WEIGHT_VERSION 1
#define WEIGHT_DATAREAD 4
#define WEIGHT_CODEPROG 10
#define WEIGHT_DATAPROG 20
#define byteswap(val) ((val << 8) | (val >> 8))
enum {
FWSTATE_IDLE,
FWSTATE_RSET,
FWSTATE_VERSION,
FWSTATE_DUMP,
FWSTATE_PREP,
FWSTATE_CODE,
FWSTATE_DATA
};
enum {
CMD_VERSION,
CMD_READPROG,
CMD_WRITEPROG,
CMD_ERASEPROG,
CMD_READDATA,
CMD_WRITEDATA,
CMD_READCFG,
CMD_WRITECFG,
CMD_RESET
};
static const char banner[] = "OpenTherm Gateway ";
OTGWSerial::OTGWSerial(int resetPin, int progressLed)
: HardwareSerial(UART0), _reset(resetPin), _led(progressLed) {
HardwareSerial::begin(9600, SERIAL_8N1);
// The PIC may have been confused by garbage on the
// serial interface when the NodeMCU resets.
resetPic();
_upgrade_stage = FWSTATE_IDLE;
_version[0] = '\0';
_version_pos = 0;
}
int OTGWSerial::available() {
if (upgradeEvent()) return 0;
return HardwareSerial::available();
}
int OTGWSerial::read() {
if (upgradeEvent()) return -1;
return HardwareSerial::read();
}
// // Reimplement the read function. Other read functions call this to implement their functionality.
// int OTGWSerial::read() {
// int retval;
// char ch;
// if (upgradeEvent()) return -1;
// retval = HardwareSerial::read();
// if (retval >= 0) {
// ch = retval;
// matchBanner(&ch);
// }
// return retval;
// }
int OTGWSerial::availableForWrite() {
if (upgradeEvent()) return 0;
return HardwareSerial::availableForWrite();
}
size_t OTGWSerial::write(uint8_t c) {
if (upgradeEvent()) return 0;
return HardwareSerial::write(c);
}
size_t OTGWSerial::write(const uint8_t *buffer, size_t len) {
if (upgradeEvent()) return 0;
return HardwareSerial::write(buffer, len);
}
bool OTGWSerial::busy() {
return upgradeEvent();
}
void OTGWSerial::resetPic() {
if (_reset >= 0) {
pinMode(_reset, OUTPUT);
digitalWrite(_reset, LOW);
}
HardwareSerial::print("GW=R\r");
if (_reset >= 0) {
delay(100);
digitalWrite(_reset, HIGH);
pinMode(_reset, INPUT);
}
_banner_matched = 0;
}
const char *OTGWSerial::firmwareVersion() {
return _version;
}
void OTGWSerial::registerFinishedCallback(OTGWUpgradeFinished *func) {
_finishedFunc = func;
}
void OTGWSerial::registerProgressCallback(OTGWUpgradeProgress *func) {
_progressFunc = func;
}
void OTGWSerial::SetLED(int state) {
if (_led >= 0) {
digitalWrite(_led, state ? LOW : HIGH);
}
}
void OTGWSerial::progress(int weight) {
if (_progressFunc) {
_upgrade_data->progress += weight;
_progressFunc(_upgrade_data->progress * 100 / _upgrade_data->total);
}
}
// Look for the banner in the incoming data and extract the version number
void OTGWSerial::matchBanner(const char *str, int len) {
for (int i = 0; i < len; i++) {
if (banner[_banner_matched] == '\0') {
if (isspace(str[i])) {
_version[_version_pos] = '\0';
_banner_matched = 0;
_version_pos = 0;
} else {
_version[_version_pos++] = str[i];
}
} else if (str[i] != banner[_banner_matched++]) {
_banner_matched = 0;
}
}
}
unsigned char OTGWSerial::hexChecksum(char *hex, int len) {
unsigned char sum = 0;
int val;
while (len-- > 0) {
sscanf(hex, "%02x", &val);
sum -= val;
hex += 2;
}
return sum;
}
OTGWError OTGWSerial::readHexFile(const char *hexfile, int *total) {
char hexbuf[48];
int len, addr, tag, data, offs, linecnt = 0, weight;
uint32_t codemap[4] = {};
byte datamap = 0;
OTGWError rc = OTGW_ERROR_HEX_FORMAT;
File f;
f = LittleFS.open(hexfile, "r");
if (!f) return OTGW_ERROR_HEX_ACCESS;
memset(_upgrade_data->codemem, -1, 4096 * sizeof(short));
memset(_upgrade_data->datamem, -1, 256 * sizeof(char));
weight = WEIGHT_RESET + WEIGHT_VERSION;
f.setTimeout(0);
while (f.readBytesUntil('\n', hexbuf, sizeof(hexbuf)) != 0) {
linecnt++;
if (sscanf(hexbuf, ":%2x%4x%2x", &len, &addr, &tag) != 3) {
// Parse error
rc = OTGW_ERROR_HEX_FORMAT;
break;
}
if (len & 1) {
// Invalid data size
rc = OTGW_ERROR_HEX_DATASIZE;
break;
}
if (hexChecksum(hexbuf + 1, len + 5) != 0) {
// Checksum error
rc = OTGW_ERROR_HEX_CHECKSUM;
break;
}
offs = 9;
len >>= 1;
if (tag == 0) {
if (addr >= 0x4400) {
// Bogus addresses
continue;
} else if (addr >= 0x4200) {
// Data memory
addr = (addr - 0x4200) >> 1;
while (len > 0) {
if (sscanf(hexbuf + offs, "%04x", &data) != 1) break;
if (!bitRead(datamap, addr / 64)) weight += WEIGHT_DATAPROG;
bitSet(datamap, addr / 64);
_upgrade_data->datamem[addr++] = byteswap(data);
offs += 4;
len--;
}
} else if (addr >= 0x4000) {
// Configuration bits
continue;
} else {
// Program memory
addr >>= 1;
while (len > 0) {
if (sscanf(hexbuf + offs, "%04x", &data) != 1) {
// Didn't find hex data
break;
}
if (!bitRead(codemap[addr / (32 * 32)], (addr / 32) & 31)) weight += WEIGHT_CODEPROG;
bitSet(codemap[addr / (32 * 32)], (addr / 32) & 31);
_upgrade_data->codemem[addr++] = byteswap(data);
offs += 4;
len--;
}
}
if (len) break;
} else if (tag == 1) {
rc = OTGW_ERROR_NONE;
break;
}
}
f.close();
if (total) *total = weight;
return rc;
}
int OTGWSerial::versionCompare(const char *version1, const char* version2) {
const char *s1 = version1, *s2 = version2;
int v1, v2, n;
while (*s1 && *s2) {
if (!sscanf(s1, "%d%n", &v1, &n)) return 0;
s1 += n;
if (!sscanf(s2, "%d%n", &v2, &n)) return 0;
s2 += n;
if (v1 < v2) return -1;
if (v1 > v2) return 1;
if (*s1 != *s2) {
// Alpha versions
if (*s1 == 'a') return -1;
if (*s2 == 'a') return 1;
// Beta versions
if (*s1 == 'b') return -1;
if (*s2 == 'b') return 1;
// Subversions
if (*s1 == 0) return -1;
if (*s2 == 0) return 1;
}
s1++;
s2++;
}
}
int OTGWSerial::eepromSettings(const char *version, OTGWTransferData *xfer) {
char buffer[64];
int last = 0, len, id, p1, p2, addr, size, mask, n;
File f;
f = LittleFS.open("/transfer.dat", "r");
if (!f) return last;
while (f.available()) {
len = f.readBytesUntil('\n', buffer, sizeof(buffer) - 1);
buffer[len] = '\0';
if ((n = sscanf(buffer, "%d %n%*s%n %x %d %x", &id, &p1, &p2, &addr, &size, &mask)) == 4) {
if (id >= XFER_MAX_ID);
buffer[p2] = '\0';
if (versionCompare(version, buffer + p1) < 0) continue;
xfer[id].addr = addr;
xfer[id].size = size;
xfer[id].mask = mask;
if (id > last) last = id;
}
}
f.close();
return last;
}
void OTGWSerial::transferSettings(const char *ver1, const char *ver2) {
OTGWTransferData xfer1[XFER_MAX_ID] = {}, xfer2[XFER_MAX_ID] = {};
int last, i, j, mask;
byte value;
last = min(eepromSettings(ver1, xfer1), eepromSettings(ver2, xfer2));
for (i = 0; i <= last; i++) {
if (xfer1[i].size) {
for (j = 0; j < xfer1[i].size; j++) {
if (xfer1[i].addr < 0x100) {
value = _upgrade_data->eedata[xfer1[i].addr + j];
} else {
value = xfer1[i].addr & 0xff;
}
if (j < xfer2[i].size && xfer2[i].addr < 0x100) {
// Combine the masks
mask = xfer1[i].mask | xfer2[i].mask;
// Insert the old data into the data array
_upgrade_data->datamem[xfer2[i].addr + j] = _upgrade_data->datamem[xfer2[i].addr + j] & mask | value & ~mask;
}
}
}
}
}
void OTGWSerial::fwCommand(const unsigned char *cmd, int len) {
uint8_t i, ch, sum = 0;
HardwareSerial::write(STX);
for (i = 0; i <= len; i++) {
ch = i < len ? cmd[i] : sum;
if (ch == STX || ch == ETX || ch == DLE) {
HardwareSerial::write(DLE);
}
HardwareSerial::write(ch);
sum -= ch;
}
HardwareSerial::write(ETX);
}
bool OTGWSerial::eraseCode(short addr, bool rc) {
byte fwcommand[] = {CMD_ERASEPROG, 1, 0, 0};
short i;
for (i = 0; i < 32; i++) {
if (_upgrade_data->codemem[addr + i] != 0xffff) {
rc = true;
break;
}
}
if (rc) {
fwcommand[2] = addr & 0xff;
fwcommand[3] = addr >> 8;
fwCommand(fwcommand, sizeof(fwcommand));
}
return rc;
}
void OTGWSerial::loadCode(short addr, const unsigned short *code, short len) {
byte i, fwcommand[4 + 2 * len];
unsigned short *data = (unsigned short *)fwcommand + 2;
fwcommand[0] = CMD_WRITEPROG;
fwcommand[1] = len >> 2;
fwcommand[2] = addr & 0xff;
fwcommand[3] = addr >> 8;
for (i = 0; i < len; i++) {
data[i] = code[i] & 0x3fff;
}
fwCommand(fwcommand, sizeof(fwcommand));
}
void OTGWSerial::readCode(short addr, short len) {
byte fwcommand[] = {CMD_READPROG, 32, 0, 0};
fwcommand[1] = len;
fwcommand[2] = addr & 0xff;
fwcommand[3] = addr >> 8;
fwCommand(fwcommand, sizeof(fwcommand));
}
bool OTGWSerial::verifyCode(const unsigned short *code, const unsigned short *data, short len) {
short i;
bool rc = true;
for (i = 0; i < len; i++) {
if (data[i] != (code[i] & 0x3fff)) {
_upgrade_data->errcnt++;
rc = false;
}
}
return rc;
}
void OTGWSerial::loadData(short addr) {
byte i;
byte fwcommand[68] = {CMD_WRITEDATA, 64};
fwcommand[2] = addr & 0xff;
fwcommand[3] = addr >> 8;
for (i = 0; i < 64; i++) {
fwcommand[i + 4] = _upgrade_data->datamem[addr + i];
}
fwCommand(fwcommand, sizeof(fwcommand));
}
void OTGWSerial::readData(short addr) {
byte fwcommand[] = {CMD_READDATA, 64, 0, 0};
fwcommand[2] = addr & 0xff;
fwCommand(fwcommand, sizeof(fwcommand));
}
bool OTGWSerial::verifyData(short pc, const byte *data, short len) {
short i;
bool rc = true;
for (i = 0; i < len; i++) {
if (data[i] != _upgrade_data->datamem[pc + i]) {
_upgrade_data->errcnt++;
rc = false;
}
}
return rc;
}
OTGWError OTGWSerial::startUpgrade(const char *hexfile) {
int weight;
unsigned short ptr;
char *s;
OTGWError result;
if (_upgrade_data != nullptr) {
return OTGW_ERROR_INPROG;
}
_upgrade_data = (OTGWUpgradeData *)malloc(sizeof(OTGWUpgradeData));
if (_upgrade_data == nullptr) {
return OTGW_ERROR_MEMORY;
}
result = readHexFile(hexfile, &weight);
if (result != OTGW_ERROR_NONE) {
return finishUpgrade(result);
}
if (_upgrade_data->codemem[0] != 0x158a || (_upgrade_data->codemem[1] & 0x3e00) != 0x2600) {
// Bad magic
return finishUpgrade(OTGW_ERROR_MAGIC);
}
// The self-programming code will be skipped (assume 256 program words)
weight -= 8 * WEIGHT_CODEPROG;
// Look for the new firmware version
_upgrade_data->version = nullptr;
ptr = 0;
while (ptr < 256) {
s = strstr((char *)_upgrade_data->datamem + ptr, banner);
if (s == nullptr) {
ptr += strnlen((char *)_upgrade_data->datamem + ptr, 256 - ptr) + 1;
} else {
s += sizeof(banner) - 1; // Drop the terminating '\0'
_upgrade_data->version = s;
if (*_version) {
// Reading out the EEPROM settings takes 4 reads of 64 bytes
weight += 4 * WEIGHT_DATAREAD;
}
break;
}
}
_upgrade_data->total = weight;
stateMachine();
return OTGW_ERROR_NONE;
}
void OTGWSerial::stateMachine(const unsigned char *packet, int len) {
const unsigned short *data = (const unsigned short *)packet;
byte cmd = 0;
if (packet == nullptr || len == 0) {
cmd = _upgrade_data->lastcmd;
} else {
cmd = packet[0];
_upgrade_data->lastcmd = cmd;
}
if (_upgrade_stage != FWSTATE_IDLE && packet == nullptr) {
int maxtries = (_upgrade_stage == FWSTATE_CODE || _upgrade_stage == FWSTATE_DATA ? 100 : 10);
if (++_upgrade_data->retries >= maxtries) {
finishUpgrade(OTGW_ERROR_RETRIES);
return;
}
}
switch (_upgrade_stage) {
case FWSTATE_IDLE:
_upgrade_data->errcnt = 0;
_upgrade_data->retries = 0;
_upgrade_data->progress = 0;
resetPic();
_upgrade_stage = FWSTATE_RSET;
break;
case FWSTATE_RSET:
if (packet != nullptr) {
byte fwcommand[] = {CMD_VERSION, 3};
progress(WEIGHT_RESET);
fwCommand(fwcommand, sizeof(fwcommand));
_upgrade_stage = FWSTATE_VERSION;
} else {
resetPic();
}
break;
case FWSTATE_VERSION:
if (data != nullptr) {
_upgrade_data->protectstart = data[2];
_upgrade_data->protectend = data[3];
_upgrade_data->failsafe[0] = 0x158a; // BSF PCLATH,3
if ((_upgrade_data->protectstart & 0x800) == 0) {
_upgrade_data->failsafe[0] = 0x118a; // BCF PCLATH,3
}
_upgrade_data->failsafe[1] = 0x2000 | _upgrade_data->protectstart & 0x7ff; // CALL SelfProg
_upgrade_data->failsafe[2] = 0x118a; // BCF PCLATH,3
_upgrade_data->failsafe[3] = 0x2820; // GOTO 0x20
progress(WEIGHT_VERSION);
if (*_version && _upgrade_data->version) {
// Both old and new versions are known
// Dump the current eeprom data to be able to transfer the settings
_upgrade_data->pc = 0;
readData(_upgrade_data->pc);
_upgrade_stage = FWSTATE_DUMP;
} else {
_upgrade_data->pc = 0x20;
eraseCode(_upgrade_data->pc, true);
_upgrade_stage = FWSTATE_PREP;
}
} else {
byte fwcommand[] = {CMD_VERSION, 3};
fwCommand(fwcommand, sizeof(fwcommand));
_upgrade_stage = FWSTATE_VERSION;
}
break;
case FWSTATE_DUMP:
if (packet != nullptr) {
progress(WEIGHT_DATAREAD);
memcpy(_upgrade_data->eedata + _upgrade_data->pc, packet + 4, 64);
_upgrade_data->pc += 64;
}
if (_upgrade_data->pc < 0x100) {
readData(_upgrade_data->pc);
} else {
// Transfer the EEPROM settings
transferSettings(_version, _upgrade_data->version);
_upgrade_data->pc = 0x20;
eraseCode(_upgrade_data->pc);
_upgrade_stage = FWSTATE_PREP;
}
break;
case FWSTATE_PREP:
// Programming has started; invalidate the firmware version
*_version = '\0';
if (cmd == CMD_ERASEPROG) {
loadCode(_upgrade_data->pc, _upgrade_data->failsafe, 4);
} else if (cmd == CMD_WRITEPROG) {
readCode(_upgrade_data->pc, 4);
} else {
if (packet != nullptr && packet[1] == 4 && data[1] == _upgrade_data->pc && verifyCode(_upgrade_data->failsafe, data + 2, 4)) {
progress(WEIGHT_CODEPROG);
_upgrade_data->pc = 0;
eraseCode(_upgrade_data->pc);
_upgrade_stage = FWSTATE_CODE;
} else {
// Failed. Try again.
eraseCode(_upgrade_data->pc, true);
}
}
break;
case FWSTATE_CODE:
if (cmd == CMD_ERASEPROG) {
// digitalWrite(LED2, LOW);
loadCode(_upgrade_data->pc, _upgrade_data->codemem + _upgrade_data->pc);
} else if (cmd == CMD_WRITEPROG) {
// digitalWrite(LED2, HIGH);
readCode(_upgrade_data->pc);
} else if (cmd == CMD_READPROG) {
if (packet != nullptr && packet[1] == 32 && data[1] == _upgrade_data->pc && verifyCode(_upgrade_data->codemem + _upgrade_data->pc, data + 2)) {
do {
do {
_upgrade_data->pc += 32;
} while (_upgrade_data->pc + 31 >= _upgrade_data->protectstart && _upgrade_data->pc <= _upgrade_data->protectend);
if (_upgrade_data->pc >= 0x1000) {
_upgrade_data->pc = 0;
loadData(_upgrade_data->pc);
_upgrade_stage = FWSTATE_DATA;
break;
} else if (eraseCode(_upgrade_data->pc)) {
progress(WEIGHT_CODEPROG);
break;
}
} while (_upgrade_data->pc < 0x1000);
} else {
eraseCode(_upgrade_data->pc);
}
}
break;
case FWSTATE_DATA:
if (cmd == CMD_WRITEDATA) {
// digitalWrite(LED2, HIGH);
readData(_upgrade_data->pc);
} else if (cmd == CMD_READDATA) {
if (packet != nullptr && verifyData(_upgrade_data->pc, packet + 4)) {
progress(WEIGHT_DATAPROG);
_upgrade_data->pc += 64;
if (_upgrade_data->pc < 0x100) {
// digitalWrite(LED2, LOW);
loadData(_upgrade_data->pc);
} else {
byte fwcommand[] = {CMD_RESET, 0};
fwCommand(fwcommand, sizeof(fwcommand));
finishUpgrade(OTGW_ERROR_NONE);
}
} else {
// digitalWrite(LED2, LOW);
loadData(_upgrade_data->pc);
}
}
break;
}
if (_upgrade_stage != FWSTATE_IDLE) {
_upgrade_data->lastaction = millis();
}
}
OTGWError OTGWSerial::finishUpgrade(OTGWError result) {
short errors = _upgrade_data->errcnt, retries = _upgrade_data->retries;
free((void *)_upgrade_data);
_upgrade_data = nullptr;
_upgrade_stage = FWSTATE_IDLE;
if (_finishedFunc) {
_finishedFunc(result, errors, retries);
}
return result;
}
// Proceed with the upgrade, if applicable
bool OTGWSerial::upgradeEvent() {
int ch;
bool dle;
if (_upgrade_stage == FWSTATE_IDLE) return false;
while (HardwareSerial::available()) {
ch = HardwareSerial::read();
dle = _upgrade_data->bufpos < sizeof(_upgrade_data->buffer) && _upgrade_data->buffer[_upgrade_data->bufpos] == DLE;
if (!dle && ch == STX) {
SetLED(1);
_upgrade_data->bufpos = 0;
_upgrade_data->checksum = 0;
_upgrade_data->buffer[0] = '\0';
} else if ((!dle || _upgrade_stage == FWSTATE_RSET) && ch == ETX) {
SetLED(0);
if (_upgrade_data->checksum == 0 || _upgrade_stage == FWSTATE_RSET) {
stateMachine(_upgrade_data->buffer, _upgrade_data->bufpos);
} else {
// Checksum mismatch
stateMachine();
}
} else if (_upgrade_data->bufpos >= sizeof(_upgrade_data->buffer)) {
// Prevent overwriting the program data
} else if (!dle && ch == DLE) {
_upgrade_data->buffer[_upgrade_data->bufpos] = ch;
} else {
_upgrade_data->buffer[_upgrade_data->bufpos++] = ch;
_upgrade_data->checksum -= ch;
_upgrade_data->buffer[_upgrade_data->bufpos] = '\0';
}
}
if (_upgrade_stage != FWSTATE_IDLE && millis() - _upgrade_data->lastaction > 1000) {
// Too much time has passed since the last action
// Send a non-DLE byte in case the PIC is waiting for a byte following a DLE
HardwareSerial::write(STX);
stateMachine();
}
return true;
}

View File

@ -0,0 +1,132 @@
/*
OTGWSerial.h - Library for OTGW PIC communication
Copyright (c) 2021 - Schelte Bron
MIT License
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef OTGWSerial_h
#define OTGWSerial_h
#include <HardwareSerial.h>
typedef enum {
OTGW_ERROR_NONE, // No error
OTGW_ERROR_MEMORY, // Not enough space
OTGW_ERROR_HEX_ACCESS, // Could not open hex file
OTGW_ERROR_HEX_FORMAT, // Invalid format of hex file
OTGW_ERROR_HEX_DATASIZE,// Wrong data size in hex file
OTGW_ERROR_HEX_CHECKSUM,// Bad checksum in hex file
OTGW_ERROR_INPROG, // Firmware upgrade in progress
OTGW_ERROR_MAGIC, // Hex file does not contain expected data
OTGW_ERROR_RESET, // PIC reset failed
OTGW_ERROR_RETRIES, // Too many retries
OTGW_ERROR_MISMATCHES // Too many mismatches
} OTGWError;
typedef struct {
unsigned char buffer[80];
unsigned char datamem[256];
unsigned char eedata[256];
unsigned short codemem[4096];
unsigned short failsafe[4];
unsigned short protectstart, protectend;
unsigned short pc, errcnt, retries, progress, total;
byte bufpos, checksum, lastcmd;
unsigned long lastaction;
char *version;
} OTGWUpgradeData;
typedef struct {
unsigned short addr;
byte size, mask;
} OTGWTransferData;
typedef void OTGWUpgradeFinished(OTGWError result, short errors, short retries);
typedef void OTGWUpgradeProgress(int pct);
class OTGWSerial: public HardwareSerial {
public:
OTGWSerial(int resetPin = -1, int progressLed = -1);
int available();
int read();
int availableForWrite();
size_t write(uint8_t c);
size_t write(const uint8_t *buffer, size_t len);
size_t write(const char *buffer, size_t len) {
return write((const uint8_t *)buffer, len);
}
// These handle ambiguity for write(0) case, because (0) can be a pointer or an integer
inline size_t write(short t) { return write((uint8_t)t); }
inline size_t write(unsigned short t) { return write((uint8_t)t); }
inline size_t write(int t) { return write((uint8_t)t); }
inline size_t write(unsigned int t) { return write((uint8_t)t); }
inline size_t write(long t) { return write((uint8_t)t); }
inline size_t write(unsigned long t) { return write((uint8_t)t); }
// Enable write(char) to fall through to write(uint8_t)
inline size_t write(char c) { return write((uint8_t) c); }
inline size_t write(int8_t c) { return write((uint8_t) c); }
size_t write(const char *buffer) {
if(buffer == NULL)
return 0;
return write((const uint8_t *)buffer, strlen(buffer));
}
const char *firmwareVersion();
bool busy();
void resetPic();
OTGWError startUpgrade(const char *hexfile);
void registerFinishedCallback(OTGWUpgradeFinished *func);
void registerProgressCallback(OTGWUpgradeProgress *func);
protected:
OTGWUpgradeData *_upgrade_data = nullptr;
OTGWUpgradeFinished *_finishedFunc = nullptr;
OTGWUpgradeProgress *_progressFunc = nullptr;
char _version[16];
int _reset, _led;
byte _banner_matched, _version_pos, _upgrade_stage;
void SetLED(int state);
void progress(int weight);
void matchBanner(const char *str, int len = 1);
unsigned char hexChecksum(char *hex, int len);
OTGWError readHexFile(const char *hexfile, int *total = nullptr);
int versionCompare(const char *version1, const char* version2);
int eepromSettings(const char *version, OTGWTransferData *xfer);
void transferSettings(const char *ver1, const char *ver2);
void fwCommand(const unsigned char *cmd, int len);
bool eraseCode(short addr, bool rc = false);
void loadCode(short addr, const unsigned short *code, short len = 32);
void readCode(short addr, short len = 32);
bool verifyCode(const unsigned short *code, const unsigned short *data, short len = 32);
void loadData(short addr);
void readData(short addr);
bool verifyData(short pc, const byte *data, short len = 64);
void stateMachine(const unsigned char *packet = nullptr, int len = 0);
OTGWError finishUpgrade(OTGWError result);
bool upgradeEvent();
};
#endif

View File

@ -50,7 +50,6 @@
ESP8266WebServer httpServer (80);
ESP8266HTTPUpdateServer httpUpdater(true);
static FSInfo LittleFSinfo;
bool LittleFSmounted;
bool isConnected = false;
@ -76,7 +75,7 @@ void startWiFi(const char* hostname, int timeOut)
uint32_t lTime = millis();
String thisAP = String(hostname) + "-" + WiFi.macAddress();
Serial.println("Start Wifi ...");
OTGWSerial.println("Start Wifi ...");
manageWiFi.setDebugOutput(true);
//--- next line in release needs to be commented out!
@ -94,7 +93,7 @@ void startWiFi(const char* hostname, int timeOut)
//--- if it does not connect it starts an access point with the specified name
//--- here "<HOSTNAME>-<MAC>"
//--- and goes into a blocking loop awaiting configuration
Serial.printf("AutoConnect to: %s", thisAP.c_str());
OTGWSerial.printf("AutoConnect to: %s", thisAP.c_str());
if (!manageWiFi.autoConnect(thisAP.c_str()))
{
//-- fail to connect? Have you tried turning it off and on again?

View File

@ -2,13 +2,13 @@
#define _VERSION_MAJOR 0
#define _VERSION_MINOR 7
#define _VERSION_PATCH 3
#define _VERSION_BUILD 506
#define _VERSION_BUILD 561
//#define _VERSION_PRERELEASE beta //uncomment to define prerelease labels: alpha - beta - rc
#define _VERSION_DATE "04-02-2021"
#define _VERSION_TIME "00:01:47"
#define _VERSION_DATE "08-02-2021"
#define _VERSION_TIME "00:13:21"
#define _SEMVER_CORE "0.7.3"
#define _SEMVER_BUILD "0.7.3+506"
#define _SEMVER_FULL "0.7.3+506"
#define _SEMVER_NOBUILD "0.7.3 (04-02-2021)"
#define _VERSION "0.7.3+506 (04-02-2021)"
#define _SEMVER_BUILD "0.7.3+561"
#define _SEMVER_FULL "0.7.3+561"
#define _SEMVER_NOBUILD "0.7.3 (08-02-2021)"
#define _VERSION "0.7.3+561 (08-02-2021)"
//The version information is created automatically, more information here: https://github.com/rvdbreemen/autoinc-semver