mirror of https://github.com/arendst/Tasmota.git
Merge pull request #6757 from andrethomas/tasmota_slave
ArduinoSlave->TasmotaSlave
This commit is contained in:
commit
453c0f5394
|
@ -1,3 +0,0 @@
|
|||
# ArduinoHexParse
|
||||
|
||||
Parse hex files created by Arduino for Uno/Mini/Nano
|
|
@ -1,25 +0,0 @@
|
|||
#######################################
|
||||
# Syntax Coloring Map for ArduinoHexParse
|
||||
# (esp8266)
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
ArduinoHexParse KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
ArduinoHexParse KEYWORD2
|
||||
ParseLine KEYWORD2
|
||||
GetFlashPage KEYWORD2
|
||||
GetLoadAddress KEYWORD2
|
||||
IsFlashPageReady KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
{
|
||||
"name": "ArduinoHexParse",
|
||||
"version": "0.0.1",
|
||||
"description": "Parse hex files created by Arduino for Uno/Mini/Nano",
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/arendst/Sonoff-Tasmota/lib/ArduinoHexParse"
|
||||
},
|
||||
"frameworks": "arduino",
|
||||
"platforms": "espressif8266"
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
name=ArduinoHexParse
|
||||
version=0.0.1
|
||||
author=Andre Thomas
|
||||
maintainer=Andre Thomas <andre1024@gmail.com>
|
||||
sentence=Parse hex files created by Arduino for Uno/Mini/Nano
|
||||
paragraph=
|
||||
category=Signal Input/Output
|
||||
url=
|
||||
architectures=esp8266
|
|
@ -1,134 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2019 Andre Thomas and Theo Arends
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "ArduinoHexParse.h"
|
||||
|
||||
ArduinoHexParse::ArduinoHexParse(void)
|
||||
{
|
||||
loadAddress[0] = 0;
|
||||
loadAddress[1] = 0;
|
||||
}
|
||||
|
||||
void ArduinoHexParse::ParseLine(byte* hexline)
|
||||
{
|
||||
recordType = GetRecordType(hexline);
|
||||
if (0 == recordType) {
|
||||
address = GetAddress(hexline);
|
||||
len = GetLength(hexline);
|
||||
GetData(hexline, len);
|
||||
if (128 == PageMemIdx) {
|
||||
if (!firstRun) {
|
||||
loadAddress[1] += 0x40;
|
||||
if (0 == loadAddress[1]) {
|
||||
loadAddress[0] += 1;
|
||||
}
|
||||
}
|
||||
firstRun = false;
|
||||
FlashPageReady = true;
|
||||
PageMemIdx = 0;
|
||||
}
|
||||
nextAddress = address + len;
|
||||
}
|
||||
if (1 == recordType) {
|
||||
EndOfFile();
|
||||
FlashPageReady = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool ArduinoHexParse::IsFlashPageReady(void)
|
||||
{
|
||||
return FlashPageReady;
|
||||
}
|
||||
|
||||
byte* ArduinoHexParse::GetFlashPage(void)
|
||||
{
|
||||
FlashPageReady = false;
|
||||
return FlashPage;
|
||||
}
|
||||
|
||||
byte* ArduinoHexParse::GetLoadAddress(void)
|
||||
{
|
||||
return loadAddress;
|
||||
}
|
||||
|
||||
void ArduinoHexParse::GetLoadAddress(byte* hexline)
|
||||
{
|
||||
char buff[3];
|
||||
buff[2] = '\0';
|
||||
buff[0] = hexline[3];
|
||||
buff[1] = hexline[4];
|
||||
loadAddress[0] = strtol(buff, 0, 16);
|
||||
buff[0] = hexline[5];
|
||||
buff[1] = hexline[6];
|
||||
loadAddress[1] = strtol(buff, 0, 16);
|
||||
}
|
||||
|
||||
byte* ArduinoHexParse::GetData(byte* hexline, uint32_t len)
|
||||
{
|
||||
uint32_t start = 9;
|
||||
uint32_t end = (len * 2) + start;
|
||||
char buff[3];
|
||||
buff[2] = '\0';
|
||||
for (uint32_t x = start; x < end; x = x+2) {
|
||||
buff[0] = hexline[x];
|
||||
buff[1] = hexline[x+1];
|
||||
FlashPage[PageMemIdx] = strtol(buff, 0, 16);
|
||||
PageMemIdx++;
|
||||
}
|
||||
}
|
||||
|
||||
void ArduinoHexParse::EndOfFile(void)
|
||||
{
|
||||
loadAddress[1] += 0x40;
|
||||
if (0 == loadAddress[1]) {
|
||||
loadAddress[0] += 1;
|
||||
}
|
||||
while (128 > PageMemIdx) { // Fill the remaing space in the memory page with 0xFF
|
||||
FlashPage[PageMemIdx] = 0xFF;
|
||||
PageMemIdx++;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t ArduinoHexParse::GetAddress(byte* hexline)
|
||||
{
|
||||
char buff[5];
|
||||
buff[0] = hexline[3];
|
||||
buff[1] = hexline[4];
|
||||
buff[2] = hexline[5];
|
||||
buff[3] = hexline[6];
|
||||
buff[4] = '\0';
|
||||
return strtol(buff, 0, 16);
|
||||
}
|
||||
|
||||
uint16_t ArduinoHexParse::GetLength(byte* hexline)
|
||||
{
|
||||
char buff[3];
|
||||
buff[0] = hexline[1];
|
||||
buff[1] = hexline[2];
|
||||
buff[2] = '\0';
|
||||
return strtol(buff, 0, 16);
|
||||
}
|
||||
|
||||
uint16_t ArduinoHexParse::GetRecordType(byte* hexline)
|
||||
{
|
||||
char buff[3];
|
||||
buff[0] = hexline[7];
|
||||
buff[1] = hexline[8];
|
||||
buff[2] = '\0';
|
||||
return strtol(buff, 0, 16);
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2019 Andre Thomas and Theo Arends
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ARDUINOHEXPARSE_H__
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
class ArduinoHexParse {
|
||||
public:
|
||||
ArduinoHexParse(void);
|
||||
void ParseLine(byte* data);
|
||||
byte* GetFlashPage(void);
|
||||
byte* GetLoadAddress(void);
|
||||
bool IsFlashPageReady(void);
|
||||
private:
|
||||
uint32_t address = 0;
|
||||
uint32_t len = 0;
|
||||
uint32_t nextAddress = 0;
|
||||
uint32_t PageMemIdx = 0;
|
||||
uint32_t recordType = 0;
|
||||
byte FlashPage[128];
|
||||
byte loadAddress[2];
|
||||
bool FlashPageReady = false;
|
||||
bool firstRun = true;
|
||||
uint32_t GetAddress(byte* hexline);
|
||||
uint16_t GetLength(byte* hexline);
|
||||
uint16_t GetRecordType(byte* hexline);
|
||||
byte* GetData(byte* hexline, uint32_t len);
|
||||
void GetLoadAddress(byte* hexline);
|
||||
void EndOfFile(void);
|
||||
};
|
||||
|
||||
#endif // __ARDUINOHEXPARSE_H__
|
|
@ -3,6 +3,7 @@
|
|||
* Release
|
||||
* Fix on energy monitoring devices using PowerDelta Exception0 with epc1:0x4000dce5 = Divide by zero (#6750)
|
||||
* Fix Script array bug (#6751)
|
||||
* Move ArduinoSlave to TasmotaSlave (Experimental)
|
||||
*
|
||||
* 6.7.0 20191025
|
||||
* Release
|
||||
|
|
|
@ -627,9 +627,9 @@
|
|||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_ARDUINO_TX "Arduino TX"
|
||||
#define D_SENSOR_ARDUINO_RX "Arduino RX"
|
||||
#define D_SENSOR_ARDUINO_RESET "Arduino RST"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -627,9 +627,9 @@
|
|||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_ARDUINO_TX "Arduino TX"
|
||||
#define D_SENSOR_ARDUINO_RX "Arduino RX"
|
||||
#define D_SENSOR_ARDUINO_RESET "Arduino RST"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -627,9 +627,9 @@
|
|||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_ARDUINO_TX "Arduino TX"
|
||||
#define D_SENSOR_ARDUINO_RX "Arduino RX"
|
||||
#define D_SENSOR_ARDUINO_RESET "Arduino RST"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -627,9 +627,9 @@
|
|||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_ARDUINO_TX "Arduino TX"
|
||||
#define D_SENSOR_ARDUINO_RX "Arduino RX"
|
||||
#define D_SENSOR_ARDUINO_RESET "Arduino RST"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -627,9 +627,9 @@
|
|||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_ARDUINO_TX "Arduino TX"
|
||||
#define D_SENSOR_ARDUINO_RX "Arduino RX"
|
||||
#define D_SENSOR_ARDUINO_RESET "Arduino RST"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -627,9 +627,9 @@
|
|||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_ARDUINO_TX "Arduino TX"
|
||||
#define D_SENSOR_ARDUINO_RX "Arduino RX"
|
||||
#define D_SENSOR_ARDUINO_RESET "Arduino RST"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -627,9 +627,9 @@
|
|||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_ARDUINO_TX "Arduino TX"
|
||||
#define D_SENSOR_ARDUINO_RX "Arduino RX"
|
||||
#define D_SENSOR_ARDUINO_RESET "Arduino RST"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -627,9 +627,9 @@
|
|||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_ARDUINO_TX "Arduino TX"
|
||||
#define D_SENSOR_ARDUINO_RX "Arduino RX"
|
||||
#define D_SENSOR_ARDUINO_RESET "Arduino RST"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -627,9 +627,9 @@
|
|||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_ARDUINO_TX "Arduino TX"
|
||||
#define D_SENSOR_ARDUINO_RX "Arduino RX"
|
||||
#define D_SENSOR_ARDUINO_RESET "Arduino RST"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -627,9 +627,9 @@
|
|||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_ARDUINO_TX "Arduino TX"
|
||||
#define D_SENSOR_ARDUINO_RX "Arduino RX"
|
||||
#define D_SENSOR_ARDUINO_RESET "Arduino RST"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -627,9 +627,9 @@
|
|||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_ARDUINO_TX "Arduino TX"
|
||||
#define D_SENSOR_ARDUINO_RX "Arduino RX"
|
||||
#define D_SENSOR_ARDUINO_RESET "Arduino RST"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -627,9 +627,9 @@
|
|||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_ARDUINO_TX "Arduino TX"
|
||||
#define D_SENSOR_ARDUINO_RX "Arduino RX"
|
||||
#define D_SENSOR_ARDUINO_RESET "Arduino RST"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -627,9 +627,9 @@
|
|||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_ARDUINO_TX "Arduino TX"
|
||||
#define D_SENSOR_ARDUINO_RX "Arduino RX"
|
||||
#define D_SENSOR_ARDUINO_RESET "Arduino RST"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -627,9 +627,9 @@
|
|||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_ARDUINO_TX "Arduino TX"
|
||||
#define D_SENSOR_ARDUINO_RX "Arduino RX"
|
||||
#define D_SENSOR_ARDUINO_RESET "Arduino RST"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -627,9 +627,9 @@
|
|||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_ARDUINO_TX "Arduino TX"
|
||||
#define D_SENSOR_ARDUINO_RX "Arduino RX"
|
||||
#define D_SENSOR_ARDUINO_RESET "Arduino RST"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -627,9 +627,9 @@
|
|||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_ARDUINO_TX "Arduino TX"
|
||||
#define D_SENSOR_ARDUINO_RX "Arduino RX"
|
||||
#define D_SENSOR_ARDUINO_RESET "Arduino RST"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "А"
|
||||
|
|
|
@ -627,9 +627,9 @@
|
|||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_ARDUINO_TX "Arduino TX"
|
||||
#define D_SENSOR_ARDUINO_RX "Arduino RX"
|
||||
#define D_SENSOR_ARDUINO_RESET "Arduino RST"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -627,9 +627,9 @@
|
|||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_ARDUINO_TX "Arduino TX"
|
||||
#define D_SENSOR_ARDUINO_RX "Arduino RX"
|
||||
#define D_SENSOR_ARDUINO_RESET "Arduino RST"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -627,9 +627,9 @@
|
|||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_ARDUINO_TX "Arduino TX"
|
||||
#define D_SENSOR_ARDUINO_RX "Arduino RX"
|
||||
#define D_SENSOR_ARDUINO_RESET "Arduino RST"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -627,9 +627,9 @@
|
|||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_ARDUINO_TX "Arduino TX"
|
||||
#define D_SENSOR_ARDUINO_RX "Arduino RX"
|
||||
#define D_SENSOR_ARDUINO_RESET "Arduino RST"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "А"
|
||||
|
|
|
@ -627,9 +627,9 @@
|
|||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_ARDUINO_TX "Arduino TX"
|
||||
#define D_SENSOR_ARDUINO_RX "Arduino RX"
|
||||
#define D_SENSOR_ARDUINO_RESET "Arduino RST"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "安"
|
||||
|
|
|
@ -627,9 +627,9 @@
|
|||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_ARDUINO_TX "Arduino TX"
|
||||
#define D_SENSOR_ARDUINO_RX "Arduino RX"
|
||||
#define D_SENSOR_ARDUINO_RESET "Arduino RST"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "安"
|
||||
|
|
|
@ -534,9 +534,9 @@
|
|||
//#define USE_HRE // Add support for Badger HR-E Water Meter (+1k4 code)
|
||||
//#define USE_A4988_STEPPER // Add support for A4988/DRV8825 stepper-motor-driver-circuit (+10k5 code)
|
||||
|
||||
//#define USE_ARDUINO_SLAVE // Add support for Arduino Uno/Pro Mini via serial interface including flashing (+2k3 code, 44 mem)
|
||||
#define USE_ARDUINO_FLASH_SPEED 57600 // Usually 57600 for 3.3V variants and 115200 for 5V variants
|
||||
#define USE_ARDUINO_SERIAL_SPEED 57600 // Depends on the sketch that is running on the Uno/Pro Mini
|
||||
//#define USE_TASMOTA_SLAVE // Add support for Arduino Uno/Pro Mini via serial interface including flashing (+2k6 code, 64 mem)
|
||||
#define USE_TASMOTA_SLAVE_FLASH_SPEED 57600 // Usually 57600 for 3.3V variants and 115200 for 5V variants
|
||||
#define USE_TASMOTA_SLAVE_SERIAL_SPEED 57600 // Depends on the sketch that is running on the Uno/Pro Mini
|
||||
|
||||
// -- End of general directives -------------------
|
||||
|
||||
|
|
|
@ -208,10 +208,9 @@ enum UserSelectablePins {
|
|||
GPIO_SM2135_DAT, // SM2135 Dat
|
||||
GPIO_DEEPSLEEP, // Kill switch for deepsleep
|
||||
GPIO_EXS_ENABLE, // EXS MCU Enable
|
||||
GPIO_ARDUINO_TXD, // Arduino Slave TX
|
||||
GPIO_ARDUINO_RXD, // Arduino Slave RX
|
||||
GPIO_ARDUINO_RST, // Arduino Reset Pin
|
||||
GPIO_ARDUINO_RST_INV, // Arduino Reset Pin inverted
|
||||
GPIO_TASMOTASLAVE_TXD, // Arduino Slave TX
|
||||
GPIO_TASMOTASLAVE_RXD, // Arduino Slave RX
|
||||
GPIO_TASMOTASLAVE_RST, // Arduino Reset Pin
|
||||
GPIO_SENSOR_END };
|
||||
|
||||
// Programmer selectable GPIO functionality
|
||||
|
@ -290,7 +289,7 @@ const char kSensorNames[] PROGMEM =
|
|||
D_SENSOR_DDSU666_TX "|" D_SENSOR_DDSU666_RX "|"
|
||||
D_SENSOR_SM2135_CLK "|" D_SENSOR_SM2135_DAT "|"
|
||||
D_SENSOR_DEEPSLEEP "|" D_SENSOR_EXS_ENABLE "|"
|
||||
D_SENSOR_ARDUINO_TX "|" D_SENSOR_ARDUINO_RX "|" D_SENSOR_ARDUINO_RESET "|" D_SENSOR_ARDUINO_RESET "i|"
|
||||
D_SENSOR_SLAVE_TX "|" D_SENSOR_SLAVE_RX "|" D_SENSOR_SLAVE_RESET "|"
|
||||
;
|
||||
|
||||
const char kSensorNamesFixed[] PROGMEM =
|
||||
|
@ -703,11 +702,10 @@ const uint8_t kGpioNiceList[] PROGMEM = {
|
|||
GPIO_PN532_TXD, // PN532 HSU Tx
|
||||
GPIO_PN532_RXD, // PN532 HSU Rx
|
||||
#endif
|
||||
#ifdef USE_ARDUINO_SLAVE
|
||||
GPIO_ARDUINO_TXD, // Arduino Slave TX
|
||||
GPIO_ARDUINO_RXD, // Arduino Slave RX
|
||||
GPIO_ARDUINO_RST, // Arduino Reset Pin
|
||||
GPIO_ARDUINO_RST_INV, // Arduino Reset Pin inverted
|
||||
#ifdef USE_TASMOTA_SLAVE
|
||||
GPIO_TASMOTASLAVE_TXD, // Tasmota Slave TX
|
||||
GPIO_TASMOTASLAVE_RXD, // Tasmota Slave RX
|
||||
GPIO_TASMOTASLAVE_RST, // Tasmota Reset Pin
|
||||
#endif
|
||||
#ifdef USE_RDM6300
|
||||
GPIO_RDM6300_RX,
|
||||
|
|
|
@ -44,7 +44,7 @@ const uint16_t HTTP_REFRESH_TIME = 2345; // milliseconds
|
|||
uint8_t *efm8bb1_update = nullptr;
|
||||
#endif // USE_RF_FLASH
|
||||
|
||||
enum UploadTypes { UPL_TASMOTA, UPL_SETTINGS, UPL_EFM8BB1, UPL_ARDUINOSLAVE };
|
||||
enum UploadTypes { UPL_TASMOTA, UPL_SETTINGS, UPL_EFM8BB1, UPL_TASMOTASLAVE };
|
||||
|
||||
static const char * HEADER_KEYS[] = { "User-Agent", };
|
||||
|
||||
|
@ -2037,8 +2037,8 @@ void HandleUploadDone(void)
|
|||
WSContentSend_P(PSTR("%06x'>" D_SUCCESSFUL "</font></b><br>"), WebColor(COL_TEXT_SUCCESS));
|
||||
WSContentSend_P(HTTP_MSG_RSTRT);
|
||||
ShowWebSource(SRC_WEBGUI);
|
||||
#ifdef USE_ARDUINO_SLAVE
|
||||
if (ArduinoSlave_GetFlagFlashing()) {
|
||||
#ifdef USE_TASMOTA_SLAVE
|
||||
if (TasmotaSlave_GetFlagFlashing()) {
|
||||
restart_flag = 0;
|
||||
} else { // It was a normal firmware file, or we are ready to restart device
|
||||
restart_flag = 2;
|
||||
|
@ -2051,9 +2051,9 @@ void HandleUploadDone(void)
|
|||
WSContentSend_P(PSTR("</div><br>"));
|
||||
WSContentSpaceButton(BUTTON_MAIN);
|
||||
WSContentStop();
|
||||
#ifdef USE_ARDUINO_SLAVE
|
||||
if (ArduinoSlave_GetFlagFlashing()) {
|
||||
ArduinoSlave_Flash();
|
||||
#ifdef USE_TASMOTA_SLAVE
|
||||
if (TasmotaSlave_GetFlagFlashing()) {
|
||||
TasmotaSlave_Flash();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -2121,11 +2121,11 @@ void HandleUploadLoop(void)
|
|||
if (Web.upload_error != 0) { return; }
|
||||
} else
|
||||
#endif // USE_RF_FLASH
|
||||
#ifdef USE_ARDUINO_SLAVE
|
||||
#ifdef USE_TASMOTA_SLAVE
|
||||
if ((WEMOS == my_module_type) && (upload.buf[0] == ':')) { // Check if this is a ARDUINO SLAVE hex file
|
||||
Update.end(); // End esp8266 update session
|
||||
Web.upload_file_type = UPL_ARDUINOSLAVE;
|
||||
Web.upload_error = ArduinoSlave_UpdateInit();
|
||||
Web.upload_file_type = UPL_TASMOTASLAVE;
|
||||
Web.upload_error = TasmotaSlave_UpdateInit();
|
||||
if (Web.upload_error != 0) { return; }
|
||||
} else
|
||||
#endif
|
||||
|
@ -2187,9 +2187,9 @@ void HandleUploadLoop(void)
|
|||
}
|
||||
}
|
||||
#endif // USE_RF_FLASH
|
||||
#ifdef USE_ARDUINO_SLAVE
|
||||
else if (UPL_ARDUINOSLAVE == Web.upload_file_type) {
|
||||
ArduinoSlave_WriteBuffer(upload.buf, upload.currentSize);
|
||||
#ifdef USE_TASMOTA_SLAVE
|
||||
else if (UPL_TASMOTASLAVE == Web.upload_file_type) {
|
||||
TasmotaSlave_WriteBuffer(upload.buf, upload.currentSize);
|
||||
}
|
||||
#endif
|
||||
else { // firmware
|
||||
|
@ -2243,10 +2243,10 @@ void HandleUploadLoop(void)
|
|||
Web.upload_file_type = UPL_TASMOTA;
|
||||
}
|
||||
#endif // USE_RF_FLASH
|
||||
#ifdef USE_ARDUINO_SLAVE
|
||||
else if (UPL_ARDUINOSLAVE == Web.upload_file_type) {
|
||||
#ifdef USE_TASMOTA_SLAVE
|
||||
else if (UPL_TASMOTASLAVE == Web.upload_file_type) {
|
||||
// Done writing the hex to SPI flash
|
||||
ArduinoSlave_SetFlagFlashing(true); // So we know on upload success page if it needs to flash hex or do a normal restart
|
||||
TasmotaSlave_SetFlagFlashing(true); // So we know on upload success page if it needs to flash hex or do a normal restart
|
||||
Web.upload_file_type = UPL_TASMOTA;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,291 +0,0 @@
|
|||
/*
|
||||
xdrv_31_arduino_slave.ino - Support for Arduino Slave on Serial
|
||||
|
||||
Copyright (C) 2019 Andre Thomas and Theo Arends
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef USE_ARDUINO_SLAVE
|
||||
/*********************************************************************************************\
|
||||
* Arduino slave
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define XDRV_31 31
|
||||
|
||||
#define CONST_STK_CRC_EOP 0x20
|
||||
|
||||
#define CMND_STK_GET_SYNC 0x30
|
||||
#define CMND_STK_SET_DEVICE 0x42
|
||||
#define CMND_STK_SET_DEVICE_EXT 0x45
|
||||
#define CMND_STK_ENTER_PROGMODE 0x50
|
||||
#define CMND_STK_LEAVE_PROGMODE 0x51
|
||||
#define CMND_STK_LOAD_ADDRESS 0x55
|
||||
#define CMND_STK_PROG_PAGE 0x64
|
||||
|
||||
#include <TasmotaSerial.h>
|
||||
#include <ArduinoHexParse.h>
|
||||
|
||||
struct ASLAVE {
|
||||
uint32_t spi_hex_size = 0;
|
||||
uint32_t spi_sector_counter = 0;
|
||||
uint8_t spi_sector_cursor = 0;
|
||||
uint8_t inverted = LOW;
|
||||
bool type = false;
|
||||
bool flashing = false;
|
||||
} ASlave;
|
||||
|
||||
TasmotaSerial *ArduinoSlave_Serial;
|
||||
|
||||
uint32_t ArduinoSlaveFlashStart(void)
|
||||
{
|
||||
return (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 2; // Stay on the safe side
|
||||
}
|
||||
|
||||
uint8_t ArduinoSlave_UpdateInit(void)
|
||||
{
|
||||
ASlave.spi_hex_size = 0;
|
||||
ASlave.spi_sector_counter = ArduinoSlaveFlashStart(); // Reset the pre-defined write address where firmware will temporarily be stored
|
||||
ASlave.spi_sector_cursor = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ArduinoSlave_Reset(void)
|
||||
{
|
||||
if (ASlave.type) {
|
||||
digitalWrite(pin[GPIO_ARDUINO_RST], !ASlave.inverted);
|
||||
delay(1);
|
||||
digitalWrite(pin[GPIO_ARDUINO_RST], ASlave.inverted);
|
||||
delay(1);
|
||||
digitalWrite(pin[GPIO_ARDUINO_RST], !ASlave.inverted);
|
||||
delay(5);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t ArduinoSlave_waitForSerialData(int dataCount, int timeout)
|
||||
{
|
||||
int timer = 0;
|
||||
while (timer < timeout) {
|
||||
if (ArduinoSlave_Serial->available() >= dataCount) {
|
||||
return 1;
|
||||
}
|
||||
delay(1);
|
||||
timer++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t ArduinoSlave_sendBytes(uint8_t* bytes, int count)
|
||||
{
|
||||
ArduinoSlave_Serial->write(bytes, count);
|
||||
ArduinoSlave_waitForSerialData(2, 1000);
|
||||
uint8_t sync = ArduinoSlave_Serial->read();
|
||||
uint8_t ok = ArduinoSlave_Serial->read();
|
||||
if (sync == 0x14 && ok == 0x10) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t ArduinoSlave_execCmd(uint8_t cmd)
|
||||
{
|
||||
uint8_t bytes[] = { cmd, CONST_STK_CRC_EOP };
|
||||
return ArduinoSlave_sendBytes(bytes, 2);
|
||||
}
|
||||
|
||||
uint8_t ArduinoSlave_execParam(uint8_t cmd, uint8_t* params, int count)
|
||||
{
|
||||
uint8_t bytes[32];
|
||||
bytes[0] = cmd;
|
||||
int i = 0;
|
||||
while (i < count) {
|
||||
bytes[i + 1] = params[i];
|
||||
i++;
|
||||
}
|
||||
bytes[i + 1] = CONST_STK_CRC_EOP;
|
||||
return ArduinoSlave_sendBytes(bytes, i + 2);
|
||||
}
|
||||
|
||||
uint8_t ArduinoSlave_exitProgMode(void)
|
||||
{
|
||||
return ArduinoSlave_execCmd(CMND_STK_LEAVE_PROGMODE); // Exit programming mode
|
||||
}
|
||||
|
||||
void ArduinoSlave_SetupFlash(void)
|
||||
{
|
||||
uint8_t ProgParams[] = {0x86,0x00,0x00,0x01,0x01,0x01,0x01,0x03,0xff,0xff,0xff,0xff,0x00,0x80,0x04,0x00,0x00,0x00,0x80,0x00};
|
||||
uint8_t ExtProgParams[] = {0x05,0x04,0xd7,0xc2,0x00};
|
||||
ArduinoSlave_Serial->begin(USE_ARDUINO_FLASH_SPEED);
|
||||
if (ArduinoSlave_Serial->hardwareSerial()) {
|
||||
ClaimSerial();
|
||||
}
|
||||
ArduinoSlave_Reset();
|
||||
ArduinoSlave_execCmd(CMND_STK_GET_SYNC);
|
||||
ArduinoSlave_execParam(CMND_STK_SET_DEVICE, ProgParams, sizeof(ProgParams)); // Set programming parameters
|
||||
ArduinoSlave_execParam(CMND_STK_SET_DEVICE_EXT, ExtProgParams, sizeof(ExtProgParams)); // Set extended programming parameters
|
||||
ArduinoSlave_execCmd(CMND_STK_ENTER_PROGMODE); // Enter programming mode
|
||||
}
|
||||
|
||||
uint8_t ArduinoSlave_loadAddress(uint8_t adrHi, uint8_t adrLo)
|
||||
{
|
||||
uint8_t params[] = { adrHi, adrLo };
|
||||
return ArduinoSlave_execParam(CMND_STK_LOAD_ADDRESS, params, sizeof(params));
|
||||
}
|
||||
|
||||
void ArduinoSlave_FlashPage(uint8_t* address, uint8_t* data)
|
||||
{
|
||||
uint8_t Header[] = {CMND_STK_PROG_PAGE, 0x00, 0x80, 0x46};
|
||||
ArduinoSlave_loadAddress(address[1], address[0]);
|
||||
ArduinoSlave_Serial->write(Header, 4);
|
||||
for (int i = 0; i < 128; i++) {
|
||||
ArduinoSlave_Serial->write(data[i]);
|
||||
}
|
||||
ArduinoSlave_Serial->write(CONST_STK_CRC_EOP);
|
||||
ArduinoSlave_waitForSerialData(2, 1000);
|
||||
ArduinoSlave_Serial->read();
|
||||
ArduinoSlave_Serial->read();
|
||||
}
|
||||
|
||||
void ArduinoSlave_Flash(void)
|
||||
{
|
||||
bool reading = true;
|
||||
uint32_t read = 0;
|
||||
uint32_t processed = 0;
|
||||
char thishexline[50];
|
||||
uint8_t position = 0;
|
||||
char* flash_buffer;
|
||||
ArduinoHexParse hexParse = ArduinoHexParse();
|
||||
|
||||
ArduinoSlave_SetupFlash();
|
||||
|
||||
flash_buffer = new char[SPI_FLASH_SEC_SIZE];
|
||||
uint32_t flash_start = ArduinoSlaveFlashStart() * SPI_FLASH_SEC_SIZE;
|
||||
while (reading) {
|
||||
ESP.flashRead(flash_start + read, (uint32_t*)flash_buffer, SPI_FLASH_SEC_SIZE);
|
||||
read = read + SPI_FLASH_SEC_SIZE;
|
||||
if (read >= ASlave.spi_hex_size) {
|
||||
reading = false;
|
||||
}
|
||||
for (uint32_t ca = 0; ca < SPI_FLASH_SEC_SIZE; ca++) {
|
||||
processed++;
|
||||
if (processed <= ASlave.spi_hex_size) {
|
||||
if (':' == flash_buffer[ca]) {
|
||||
position = 0;
|
||||
}
|
||||
if (0x0D == flash_buffer[ca]) {
|
||||
thishexline[position] = 0;
|
||||
hexParse.ParseLine((uint8_t*)thishexline);
|
||||
if (hexParse.IsFlashPageReady()) {
|
||||
uint8_t* page = hexParse.GetFlashPage();
|
||||
uint8_t* address = hexParse.GetLoadAddress();
|
||||
ArduinoSlave_FlashPage(address, page);
|
||||
}
|
||||
} else {
|
||||
if (0x0A != flash_buffer[ca]) {
|
||||
thishexline[position] = flash_buffer[ca];
|
||||
position++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ASlave.flashing = false;
|
||||
ArduinoSlave_exitProgMode();
|
||||
restart_flag = 2;
|
||||
}
|
||||
|
||||
void ArduinoSlave_SetFlagFlashing(bool value)
|
||||
{
|
||||
ASlave.flashing = value;
|
||||
}
|
||||
|
||||
bool ArduinoSlave_GetFlagFlashing(void)
|
||||
{
|
||||
return ASlave.flashing ;
|
||||
}
|
||||
|
||||
void ArduinoSlave_WriteBuffer(uint8_t *buf, size_t size)
|
||||
{
|
||||
if (0 == ASlave.spi_sector_cursor) { // Starting a new sector write so we need to erase it first
|
||||
ESP.flashEraseSector(ASlave.spi_sector_counter);
|
||||
}
|
||||
ASlave.spi_sector_cursor++;
|
||||
ESP.flashWrite((ASlave.spi_sector_counter * SPI_FLASH_SEC_SIZE) + ((ASlave.spi_sector_cursor-1)*2048), (uint32_t*)buf, size);
|
||||
ASlave.spi_hex_size = ASlave.spi_hex_size + size;
|
||||
if (2 == ASlave.spi_sector_cursor) { // The web upload sends 2048 bytes at a time so keep track of the cursor position to reset it for the next flash sector erase
|
||||
ASlave.spi_sector_cursor = 0;
|
||||
ASlave.spi_sector_counter++;
|
||||
}
|
||||
}
|
||||
|
||||
void ArduinoSlave_Init(void)
|
||||
{
|
||||
if (ASlave.type) {
|
||||
return;
|
||||
}
|
||||
if ((pin[GPIO_ARDUINO_RXD] < 99) && (pin[GPIO_ARDUINO_TXD] < 99) &&
|
||||
((pin[GPIO_ARDUINO_RST] < 99) || (pin[GPIO_ARDUINO_RST_INV] < 99))) {
|
||||
ArduinoSlave_Serial = new TasmotaSerial(pin[GPIO_ARDUINO_RXD], pin[GPIO_ARDUINO_TXD], 1, 0, 200);
|
||||
if (ArduinoSlave_Serial->begin(USE_ARDUINO_SERIAL_SPEED)) {
|
||||
if (ArduinoSlave_Serial->hardwareSerial()) {
|
||||
ClaimSerial();
|
||||
}
|
||||
if (pin[GPIO_ARDUINO_RST_INV] < 99) {
|
||||
pin[GPIO_ARDUINO_RST] = pin[GPIO_ARDUINO_RST_INV];
|
||||
pin[GPIO_ARDUINO_RST_INV] = 99;
|
||||
ASlave.inverted = HIGH;
|
||||
}
|
||||
pinMode(pin[GPIO_ARDUINO_RST], OUTPUT);
|
||||
ASlave.type = true;
|
||||
ArduinoSlave_Reset();
|
||||
AddLog_P2(LOG_LEVEL_INFO, PSTR("Arduino Slave Enabled"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ArduinoSlave_Show(bool json)
|
||||
{
|
||||
if (ASlave.type) {
|
||||
ArduinoSlave_Serial->flush();
|
||||
ArduinoSlave_Serial->print("JSON");
|
||||
ArduinoSlave_Serial->find(char(0xFE));
|
||||
char buffer[100];
|
||||
uint16_t haveread = ArduinoSlave_Serial->readBytesUntil(char(0xFF), buffer, sizeof(buffer)-1);
|
||||
buffer[haveread] = '\0';
|
||||
if (json) {
|
||||
ResponseAppend_P(PSTR(",\"ArduinoSlave\":%s"), buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
bool Xdrv31(uint8_t function)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
switch (function) {
|
||||
case FUNC_EVERY_SECOND:
|
||||
ArduinoSlave_Init();
|
||||
break;
|
||||
case FUNC_JSON_APPEND:
|
||||
ArduinoSlave_Show(1);
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_ARDUINO_SLAVE
|
|
@ -0,0 +1,481 @@
|
|||
/*
|
||||
xdrv_31_tasmota_slave.ino - Support for external microcontroller slave on serial
|
||||
|
||||
Copyright (C) 2019 Andre Thomas and Theo Arends
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef USE_TASMOTA_SLAVE
|
||||
/*********************************************************************************************\
|
||||
* Tasmota slave
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define XDRV_31 31
|
||||
|
||||
#define CONST_STK_CRC_EOP 0x20
|
||||
|
||||
#define CMND_STK_GET_SYNC 0x30
|
||||
#define CMND_STK_SET_DEVICE 0x42
|
||||
#define CMND_STK_SET_DEVICE_EXT 0x45
|
||||
#define CMND_STK_ENTER_PROGMODE 0x50
|
||||
#define CMND_STK_LEAVE_PROGMODE 0x51
|
||||
#define CMND_STK_LOAD_ADDRESS 0x55
|
||||
#define CMND_STK_PROG_PAGE 0x64
|
||||
|
||||
/*************************************************\
|
||||
* Tasmota Slave Specific Commands
|
||||
\*************************************************/
|
||||
|
||||
#define CMND_START 0xFC
|
||||
#define CMND_END 0xFD
|
||||
|
||||
#define CMND_FEATURES 0x01
|
||||
#define CMND_JSON 0x02
|
||||
|
||||
#define PARAM_DATA_START 0xFE
|
||||
#define PARAM_DATA_END 0xFF
|
||||
|
||||
|
||||
#include <TasmotaSerial.h>
|
||||
|
||||
/*
|
||||
* Embedding class in here since its rather specific to Arduino bootloader
|
||||
*/
|
||||
|
||||
class SimpleHexParse {
|
||||
public:
|
||||
SimpleHexParse(void);
|
||||
uint8_t parseLine(char *hexline);
|
||||
uint8_t ptr_l = 0;
|
||||
uint8_t ptr_h = 0;
|
||||
bool PageIsReady = false;
|
||||
bool firstrun = true;
|
||||
bool EndOfFile = false;
|
||||
uint8_t FlashPage[128];
|
||||
uint8_t FlashPageIdx = 0;
|
||||
uint8_t layoverBuffer[16];
|
||||
uint8_t layoverIdx = 0;
|
||||
uint8_t getByte(char *hexline, uint8_t idx);
|
||||
};
|
||||
|
||||
SimpleHexParse::SimpleHexParse(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
uint8_t SimpleHexParse::parseLine(char *hexline)
|
||||
{
|
||||
if (layoverIdx) {
|
||||
memcpy(&FlashPage[0], &layoverBuffer[0], layoverIdx);
|
||||
FlashPageIdx = layoverIdx;
|
||||
layoverIdx = 0;
|
||||
}
|
||||
uint8_t len = getByte(hexline, 1);
|
||||
uint8_t addr_h = getByte(hexline, 2);
|
||||
uint8_t addr_l = getByte(hexline, 3);
|
||||
uint8_t rectype = getByte(hexline, 4);
|
||||
for (uint8_t idx = 0; idx < len; idx++) {
|
||||
if (FlashPageIdx < 128) {
|
||||
FlashPage[FlashPageIdx] = getByte(hexline, idx+5);
|
||||
FlashPageIdx++;
|
||||
} else { // We have layover bytes
|
||||
layoverBuffer[layoverIdx] = getByte(hexline, idx+5);
|
||||
layoverIdx++;
|
||||
}
|
||||
}
|
||||
if (1 == rectype) {
|
||||
EndOfFile = true;
|
||||
while (FlashPageIdx < 128) {
|
||||
FlashPage[FlashPageIdx] = 0xFF;
|
||||
FlashPageIdx++;
|
||||
}
|
||||
}
|
||||
if (FlashPageIdx == 128) {
|
||||
if (firstrun) {
|
||||
firstrun = false;
|
||||
} else {
|
||||
ptr_l += 0x40;
|
||||
if (ptr_l == 0) {
|
||||
ptr_l = 0;
|
||||
ptr_h++;
|
||||
}
|
||||
}
|
||||
firstrun = false;
|
||||
PageIsReady = true;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t SimpleHexParse::getByte(char* hexline, uint8_t idx)
|
||||
{
|
||||
char buff[3];
|
||||
buff[3] = '\0';
|
||||
memcpy(&buff, &hexline[(idx*2)-1], 2);
|
||||
return strtol(buff, 0, 16);
|
||||
}
|
||||
|
||||
/*
|
||||
* End of embedded class SimpleHexParse
|
||||
*/
|
||||
|
||||
struct TSLAVE {
|
||||
uint32_t spi_hex_size = 0;
|
||||
uint32_t spi_sector_counter = 0;
|
||||
uint8_t spi_sector_cursor = 0;
|
||||
bool type = false;
|
||||
bool flashing = false;
|
||||
bool SerialEnabled = false;
|
||||
uint8_t waitstate = 0; // We use this so that features detection does not slow down other stuff on startup
|
||||
} TSlave;
|
||||
|
||||
typedef union {
|
||||
uint16_t data;
|
||||
struct {
|
||||
uint16_t json : 1;
|
||||
uint16_t spare1 : 1;
|
||||
uint16_t spare2 : 1;
|
||||
uint16_t spare3 : 1;
|
||||
uint16_t spare4 : 1;
|
||||
uint16_t spare5 : 1;
|
||||
uint16_t spare6 : 1;
|
||||
uint16_t spare7 : 1;
|
||||
uint16_t spare8 : 1;
|
||||
uint16_t spare9 : 1;
|
||||
uint16_t spare10 : 1;
|
||||
uint16_t spare11 : 1;
|
||||
uint16_t spare12 : 1;
|
||||
uint16_t spare13 : 1;
|
||||
uint16_t spare14 : 1;
|
||||
uint16_t spare15 : 1;
|
||||
};
|
||||
} TSlaveFeatureCfg;
|
||||
|
||||
/*
|
||||
* The structure below must remain 4 byte aligned to be compatible with
|
||||
* Tasmota as master
|
||||
*/
|
||||
|
||||
struct FEATURES {
|
||||
uint32_t features_version;
|
||||
TSlaveFeatureCfg features;
|
||||
uint16_t spare4;
|
||||
} TSlaveSettings;
|
||||
|
||||
struct COMMAND {
|
||||
uint8_t command;
|
||||
uint8_t parameter;
|
||||
uint8_t unused2;
|
||||
uint8_t unused3;
|
||||
} Command;
|
||||
|
||||
TasmotaSerial *TasmotaSlave_Serial;
|
||||
|
||||
uint32_t TasmotaSlave_FlashStart(void)
|
||||
{
|
||||
return (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 2; // Stay on the safe side
|
||||
}
|
||||
|
||||
uint8_t TasmotaSlave_UpdateInit(void)
|
||||
{
|
||||
TSlave.spi_hex_size = 0;
|
||||
TSlave.spi_sector_counter = TasmotaSlave_FlashStart(); // Reset the pre-defined write address where firmware will temporarily be stored
|
||||
TSlave.spi_sector_cursor = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void TasmotaSlave_Reset(void)
|
||||
{
|
||||
if (TSlave.SerialEnabled) {
|
||||
digitalWrite(pin[GPIO_TASMOTASLAVE_RST], LOW);
|
||||
delay(1);
|
||||
digitalWrite(pin[GPIO_TASMOTASLAVE_RST], HIGH);
|
||||
delay(5);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t TasmotaSlave_waitForSerialData(int dataCount, int timeout)
|
||||
{
|
||||
int timer = 0;
|
||||
while (timer < timeout) {
|
||||
if (TasmotaSlave_Serial->available() >= dataCount) {
|
||||
return 1;
|
||||
}
|
||||
delay(1);
|
||||
timer++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t TasmotaSlave_sendBytes(uint8_t* bytes, int count)
|
||||
{
|
||||
TasmotaSlave_Serial->write(bytes, count);
|
||||
TasmotaSlave_waitForSerialData(2, 1000);
|
||||
uint8_t sync = TasmotaSlave_Serial->read();
|
||||
uint8_t ok = TasmotaSlave_Serial->read();
|
||||
if ((sync == 0x14) && (ok == 0x10)) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t TasmotaSlave_execCmd(uint8_t cmd)
|
||||
{
|
||||
uint8_t bytes[] = { cmd, CONST_STK_CRC_EOP };
|
||||
return TasmotaSlave_sendBytes(bytes, 2);
|
||||
}
|
||||
|
||||
uint8_t TasmotaSlave_execParam(uint8_t cmd, uint8_t* params, int count)
|
||||
{
|
||||
uint8_t bytes[32];
|
||||
bytes[0] = cmd;
|
||||
int i = 0;
|
||||
while (i < count) {
|
||||
bytes[i + 1] = params[i];
|
||||
i++;
|
||||
}
|
||||
bytes[i + 1] = CONST_STK_CRC_EOP;
|
||||
return TasmotaSlave_sendBytes(bytes, i + 2);
|
||||
}
|
||||
|
||||
uint8_t TasmotaSlave_exitProgMode(void)
|
||||
{
|
||||
return TasmotaSlave_execCmd(CMND_STK_LEAVE_PROGMODE); // Exit programming mode
|
||||
}
|
||||
|
||||
void TasmotaSlave_SetupFlash(void)
|
||||
{
|
||||
uint8_t ProgParams[] = {0x86, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x80, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00};
|
||||
uint8_t ExtProgParams[] = {0x05, 0x04, 0xd7, 0xc2, 0x00};
|
||||
TasmotaSlave_Serial->begin(USE_TASMOTA_SLAVE_FLASH_SPEED);
|
||||
if (TasmotaSlave_Serial->hardwareSerial()) {
|
||||
ClaimSerial();
|
||||
}
|
||||
TasmotaSlave_Reset();
|
||||
|
||||
uint8_t timer = 0;
|
||||
bool no_error = false;
|
||||
while (200 > timer) {
|
||||
if (TasmotaSlave_execCmd(CMND_STK_GET_SYNC)) {
|
||||
timer = 200;
|
||||
no_error = true;
|
||||
}
|
||||
delay(1);
|
||||
}
|
||||
|
||||
if (no_error) {
|
||||
AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Found bootloader"));
|
||||
} else {
|
||||
AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Bootloader could not be found"));
|
||||
}
|
||||
|
||||
if (no_error) {
|
||||
if (TasmotaSlave_execParam(CMND_STK_SET_DEVICE, ProgParams, sizeof(ProgParams))) {
|
||||
} else {
|
||||
no_error = true;
|
||||
AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Could not configure device for programming (1)"));
|
||||
}
|
||||
}
|
||||
|
||||
if (no_error) {
|
||||
if (TasmotaSlave_execParam(CMND_STK_SET_DEVICE_EXT, ExtProgParams, sizeof(ExtProgParams))) {
|
||||
} else {
|
||||
no_error = true;
|
||||
AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Could not configure device for programming (2)"));
|
||||
}
|
||||
}
|
||||
|
||||
if (no_error) {
|
||||
if (TasmotaSlave_execCmd(CMND_STK_ENTER_PROGMODE)) {
|
||||
} else {
|
||||
no_error = true;
|
||||
AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Failed to put bootloader into programming mode"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
uint8_t TasmotaSlave_loadAddress(uint8_t adrHi, uint8_t adrLo)
|
||||
{
|
||||
uint8_t params[] = { adrLo, adrHi };
|
||||
return TasmotaSlave_execParam(CMND_STK_LOAD_ADDRESS, params, sizeof(params));
|
||||
}
|
||||
|
||||
void TasmotaSlave_FlashPage(uint8_t addr_h, uint8_t addr_l, uint8_t* data)
|
||||
{
|
||||
uint8_t Header[] = {CMND_STK_PROG_PAGE, 0x00, 0x80, 0x46};
|
||||
TasmotaSlave_loadAddress(addr_h, addr_l);
|
||||
TasmotaSlave_Serial->write(Header, 4);
|
||||
for (int i = 0; i < 128; i++) {
|
||||
TasmotaSlave_Serial->write(data[i]);
|
||||
}
|
||||
TasmotaSlave_Serial->write(CONST_STK_CRC_EOP);
|
||||
TasmotaSlave_waitForSerialData(2, 1000);
|
||||
TasmotaSlave_Serial->read();
|
||||
TasmotaSlave_Serial->read();
|
||||
}
|
||||
|
||||
void TasmotaSlave_Flash(void)
|
||||
{
|
||||
bool reading = true;
|
||||
uint32_t read = 0;
|
||||
uint32_t processed = 0;
|
||||
char thishexline[50];
|
||||
uint8_t position = 0;
|
||||
char* flash_buffer;
|
||||
SimpleHexParse hexParse = SimpleHexParse();
|
||||
|
||||
TasmotaSlave_SetupFlash();
|
||||
|
||||
flash_buffer = new char[SPI_FLASH_SEC_SIZE];
|
||||
uint32_t flash_start = TasmotaSlave_FlashStart() * SPI_FLASH_SEC_SIZE;
|
||||
while (reading) {
|
||||
ESP.flashRead(flash_start + read, (uint32_t*)flash_buffer, SPI_FLASH_SEC_SIZE);
|
||||
read = read + SPI_FLASH_SEC_SIZE;
|
||||
if (read >= TSlave.spi_hex_size) {
|
||||
reading = false;
|
||||
}
|
||||
for (uint32_t ca = 0; ca < SPI_FLASH_SEC_SIZE; ca++) {
|
||||
processed++;
|
||||
if ((processed <= TSlave.spi_hex_size) && (!hexParse.EndOfFile)) {
|
||||
if (':' == flash_buffer[ca]) {
|
||||
position = 0;
|
||||
}
|
||||
if (0x0D == flash_buffer[ca]) {
|
||||
thishexline[position] = 0;
|
||||
hexParse.parseLine(thishexline);
|
||||
if (hexParse.PageIsReady) {
|
||||
TasmotaSlave_FlashPage(hexParse.ptr_h, hexParse.ptr_l, hexParse.FlashPage);
|
||||
hexParse.PageIsReady = false;
|
||||
hexParse.FlashPageIdx = 0;
|
||||
}
|
||||
} else {
|
||||
if (0x0A != flash_buffer[ca]) {
|
||||
thishexline[position] = flash_buffer[ca];
|
||||
position++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
TasmotaSlave_exitProgMode();
|
||||
TSlave.flashing = false;
|
||||
restart_flag = 2;
|
||||
}
|
||||
|
||||
void TasmotaSlave_SetFlagFlashing(bool value)
|
||||
{
|
||||
TSlave.flashing = value;
|
||||
}
|
||||
|
||||
bool TasmotaSlave_GetFlagFlashing(void)
|
||||
{
|
||||
return TSlave.flashing;
|
||||
}
|
||||
|
||||
void TasmotaSlave_WriteBuffer(uint8_t *buf, size_t size)
|
||||
{
|
||||
if (0 == TSlave.spi_sector_cursor) { // Starting a new sector write so we need to erase it first
|
||||
ESP.flashEraseSector(TSlave.spi_sector_counter);
|
||||
}
|
||||
TSlave.spi_sector_cursor++;
|
||||
ESP.flashWrite((TSlave.spi_sector_counter * SPI_FLASH_SEC_SIZE) + ((TSlave.spi_sector_cursor-1)*2048), (uint32_t*)buf, size);
|
||||
TSlave.spi_hex_size = TSlave.spi_hex_size + size;
|
||||
if (2 == TSlave.spi_sector_cursor) { // The web upload sends 2048 bytes at a time so keep track of the cursor position to reset it for the next flash sector erase
|
||||
TSlave.spi_sector_cursor = 0;
|
||||
TSlave.spi_sector_counter++;
|
||||
}
|
||||
}
|
||||
|
||||
void TasmotaSlave_Init(void)
|
||||
{
|
||||
if (TSlave.type) {
|
||||
return;
|
||||
}
|
||||
if (10 > TSlave.waitstate) {
|
||||
TSlave.waitstate++;
|
||||
return;
|
||||
}
|
||||
if (!TSlave.SerialEnabled) {
|
||||
if ((pin[GPIO_TASMOTASLAVE_RXD] < 99) && (pin[GPIO_TASMOTASLAVE_TXD] < 99) && (pin[GPIO_TASMOTASLAVE_RST] < 99)) {
|
||||
TasmotaSlave_Serial = new TasmotaSerial(pin[GPIO_TASMOTASLAVE_RXD], pin[GPIO_TASMOTASLAVE_TXD], 1, 0, 200);
|
||||
if (TasmotaSlave_Serial->begin(USE_TASMOTA_SLAVE_SERIAL_SPEED)) {
|
||||
if (TasmotaSlave_Serial->hardwareSerial()) {
|
||||
ClaimSerial();
|
||||
}
|
||||
pinMode(pin[GPIO_TASMOTASLAVE_RST], OUTPUT);
|
||||
TasmotaSlave_Reset();
|
||||
TSlave.SerialEnabled = true;
|
||||
AddLog_P2(LOG_LEVEL_INFO, PSTR("Tasmota Slave Enabled"));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (TSlave.SerialEnabled) { // All go for hardware now we need to detect features if there are any
|
||||
TasmotaSlave_sendCmnd(CMND_FEATURES, 0);
|
||||
char buffer[32];
|
||||
TasmotaSlave_Serial->readBytesUntil(char(PARAM_DATA_START), buffer, sizeof(buffer));
|
||||
uint8_t len = TasmotaSlave_Serial->readBytesUntil(char(PARAM_DATA_END), buffer, sizeof(buffer));
|
||||
memcpy(&TSlaveSettings, &buffer, sizeof(TSlaveSettings));
|
||||
if (20191026 <= TSlaveSettings.features_version) {
|
||||
TSlave.type = true;
|
||||
AddLog_P2(LOG_LEVEL_INFO, PSTR("Tasmota Slave Version %u"), TSlaveSettings.features_version);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TasmotaSlave_Show(void)
|
||||
{
|
||||
if ((TSlave.type) && (TSlaveSettings.features.json)) {
|
||||
char buffer[100];
|
||||
TasmotaSlave_sendCmnd(CMND_JSON, 0);
|
||||
TasmotaSlave_Serial->readBytesUntil(char(PARAM_DATA_START), buffer, sizeof(buffer)-1);
|
||||
uint8_t len = TasmotaSlave_Serial->readBytesUntil(char(PARAM_DATA_END), buffer, sizeof(buffer)-1);
|
||||
buffer[len] = '\0';
|
||||
ResponseAppend_P(PSTR(",\"TasmotaSlave\":%s"), buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void TasmotaSlave_sendCmnd(uint8_t cmnd, uint8_t param)
|
||||
{
|
||||
Command.command = cmnd;
|
||||
Command.parameter = param;
|
||||
char buffer[sizeof(Command)+2];
|
||||
buffer[0] = CMND_START;
|
||||
memcpy(&buffer[1], &Command, sizeof(Command));
|
||||
buffer[sizeof(Command)+1] = CMND_END;
|
||||
for (uint8_t ca = 0; ca < sizeof(buffer); ca++) {
|
||||
TasmotaSlave_Serial->write(buffer[ca]);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
bool Xdrv31(uint8_t function)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
switch (function) {
|
||||
case FUNC_EVERY_SECOND:
|
||||
TasmotaSlave_Init();
|
||||
break;
|
||||
case FUNC_JSON_APPEND:
|
||||
TasmotaSlave_Show();
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_TASMOTA_SLAVE
|
Loading…
Reference in New Issue