diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h
index f85543cd0..51cd2d0fd 100644
--- a/sonoff/sonoff_template.h
+++ b/sonoff/sonoff_template.h
@@ -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,
diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino
index 40b3bab83..17622e920 100644
--- a/sonoff/xdrv_01_webserver.ino
+++ b/sonoff/xdrv_01_webserver.ino
@@ -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 "
"), 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("
"));
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
diff --git a/sonoff/xdrv_31_arduino_slave.ino b/sonoff/xdrv_31_arduino_slave.ino
index 497ab28dd..dff94182b 100644
--- a/sonoff/xdrv_31_arduino_slave.ino
+++ b/sonoff/xdrv_31_arduino_slave.ino
@@ -1,5 +1,5 @@
/*
- xdrv_31_arduino_slave.ino - Support for Arduino Slave on Serial
+ xdrv_31_tasmota_slave.ino - Support for external microcontroller slave on serial
Copyright (C) 2019 Andre Thomas and Theo Arends
@@ -17,9 +17,9 @@
along with this program. If not, see .
*/
-#ifdef USE_ARDUINO_SLAVE
+#ifdef USE_TASMOTA_SLAVE
/*********************************************************************************************\
- * Arduino slave
+ * Tasmota slave
\*********************************************************************************************/
#define XDRV_31 31
@@ -34,50 +34,182 @@
#define CMND_STK_LOAD_ADDRESS 0x55
#define CMND_STK_PROG_PAGE 0x64
-#include
-#include
+/*************************************************\
+ * Tasmota Slave Specific Commands
+\*************************************************/
-struct ASLAVE {
+#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
+
+/*
+ * 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;
- uint8_t inverted = LOW;
bool type = false;
bool flashing = false;
-} ASlave;
+ bool SerialEnabled = false;
+ uint8_t waitstate = 0; // We use this so that features detection does not slow down other stuff on startup
+} TSlave;
-TasmotaSerial *ArduinoSlave_Serial;
+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;
-uint32_t ArduinoSlaveFlashStart(void)
+/*
+ * 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 ArduinoSlave_UpdateInit(void)
+uint8_t TasmotaSlave_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;
+ 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 ArduinoSlave_Reset(void)
+void TasmotaSlave_Reset(void)
{
- if (ASlave.type) {
- digitalWrite(pin[GPIO_ARDUINO_RST], !ASlave.inverted);
+ if (TSlave.SerialEnabled) {
+ digitalWrite(pin[GPIO_TASMOTASLAVE_RST], LOW);
delay(1);
- digitalWrite(pin[GPIO_ARDUINO_RST], ASlave.inverted);
- delay(1);
- digitalWrite(pin[GPIO_ARDUINO_RST], !ASlave.inverted);
+ digitalWrite(pin[GPIO_TASMOTASLAVE_RST], HIGH);
delay(5);
}
}
-uint8_t ArduinoSlave_waitForSerialData(int dataCount, int timeout)
+uint8_t TasmotaSlave_waitForSerialData(int dataCount, int timeout)
{
int timer = 0;
while (timer < timeout) {
- if (ArduinoSlave_Serial->available() >= dataCount) {
+ if (TasmotaSlave_Serial->available() >= dataCount) {
return 1;
}
delay(1);
@@ -86,25 +218,25 @@ uint8_t ArduinoSlave_waitForSerialData(int dataCount, int timeout)
return 0;
}
-uint8_t ArduinoSlave_sendBytes(uint8_t* bytes, int count)
+uint8_t TasmotaSlave_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) {
+ 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 ArduinoSlave_execCmd(uint8_t cmd)
+uint8_t TasmotaSlave_execCmd(uint8_t cmd)
{
uint8_t bytes[] = { cmd, CONST_STK_CRC_EOP };
- return ArduinoSlave_sendBytes(bytes, 2);
+ return TasmotaSlave_sendBytes(bytes, 2);
}
-uint8_t ArduinoSlave_execParam(uint8_t cmd, uint8_t* params, int count)
+uint8_t TasmotaSlave_execParam(uint8_t cmd, uint8_t* params, int count)
{
uint8_t bytes[32];
bytes[0] = cmd;
@@ -114,50 +246,87 @@ uint8_t ArduinoSlave_execParam(uint8_t cmd, uint8_t* params, int count)
i++;
}
bytes[i + 1] = CONST_STK_CRC_EOP;
- return ArduinoSlave_sendBytes(bytes, i + 2);
+ return TasmotaSlave_sendBytes(bytes, i + 2);
}
-uint8_t ArduinoSlave_exitProgMode(void)
+uint8_t TasmotaSlave_exitProgMode(void)
{
- return ArduinoSlave_execCmd(CMND_STK_LEAVE_PROGMODE); // Exit programming mode
+ return TasmotaSlave_execCmd(CMND_STK_LEAVE_PROGMODE); // Exit programming mode
}
-void ArduinoSlave_SetupFlash(void)
+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};
- ArduinoSlave_Serial->begin(USE_ARDUINO_FLASH_SPEED);
- if (ArduinoSlave_Serial->hardwareSerial()) {
+ 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();
}
- 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
+ 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 ArduinoSlave_loadAddress(uint8_t adrHi, uint8_t adrLo)
+uint8_t TasmotaSlave_loadAddress(uint8_t adrHi, uint8_t adrLo)
{
- uint8_t params[] = { adrHi, adrLo };
- return ArduinoSlave_execParam(CMND_STK_LOAD_ADDRESS, params, sizeof(params));
+ uint8_t params[] = { adrLo, adrHi };
+ return TasmotaSlave_execParam(CMND_STK_LOAD_ADDRESS, params, sizeof(params));
}
-void ArduinoSlave_FlashPage(uint8_t* address, uint8_t* data)
+void TasmotaSlave_FlashPage(uint8_t addr_h, uint8_t addr_l, uint8_t* data)
{
uint8_t Header[] = {CMND_STK_PROG_PAGE, 0x00, 0x80, 0x46};
- ArduinoSlave_loadAddress(address[1], address[0]);
- ArduinoSlave_Serial->write(Header, 4);
+ TasmotaSlave_loadAddress(addr_h, addr_l);
+ TasmotaSlave_Serial->write(Header, 4);
for (int i = 0; i < 128; i++) {
- ArduinoSlave_Serial->write(data[i]);
+ TasmotaSlave_Serial->write(data[i]);
}
- ArduinoSlave_Serial->write(CONST_STK_CRC_EOP);
- ArduinoSlave_waitForSerialData(2, 1000);
- ArduinoSlave_Serial->read();
- ArduinoSlave_Serial->read();
+ TasmotaSlave_Serial->write(CONST_STK_CRC_EOP);
+ TasmotaSlave_waitForSerialData(2, 1000);
+ TasmotaSlave_Serial->read();
+ TasmotaSlave_Serial->read();
}
-void ArduinoSlave_Flash(void)
+void TasmotaSlave_Flash(void)
{
bool reading = true;
uint32_t read = 0;
@@ -165,31 +334,31 @@ void ArduinoSlave_Flash(void)
char thishexline[50];
uint8_t position = 0;
char* flash_buffer;
- ArduinoHexParse hexParse = ArduinoHexParse();
+ SimpleHexParse hexParse = SimpleHexParse();
- ArduinoSlave_SetupFlash();
+ TasmotaSlave_SetupFlash();
flash_buffer = new char[SPI_FLASH_SEC_SIZE];
- uint32_t flash_start = ArduinoSlaveFlashStart() * 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 >= ASlave.spi_hex_size) {
+ if (read >= TSlave.spi_hex_size) {
reading = false;
}
for (uint32_t ca = 0; ca < SPI_FLASH_SEC_SIZE; ca++) {
processed++;
- if (processed <= ASlave.spi_hex_size) {
+ if ((processed <= TSlave.spi_hex_size) && (!hexParse.EndOfFile)) {
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);
+ 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]) {
@@ -200,72 +369,93 @@ void ArduinoSlave_Flash(void)
}
}
}
- ASlave.flashing = false;
- ArduinoSlave_exitProgMode();
+ TasmotaSlave_exitProgMode();
+ TSlave.flashing = false;
restart_flag = 2;
}
-void ArduinoSlave_SetFlagFlashing(bool value)
+void TasmotaSlave_SetFlagFlashing(bool value)
{
- ASlave.flashing = value;
+ TSlave.flashing = value;
}
-bool ArduinoSlave_GetFlagFlashing(void)
+bool TasmotaSlave_GetFlagFlashing(void)
{
- return ASlave.flashing ;
+ return TSlave.flashing;
}
-void ArduinoSlave_WriteBuffer(uint8_t *buf, size_t size)
+void TasmotaSlave_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);
+ if (0 == TSlave.spi_sector_cursor) { // Starting a new sector write so we need to erase it first
+ ESP.flashEraseSector(TSlave.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++;
+ 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 ArduinoSlave_Init(void)
+void TasmotaSlave_Init(void)
{
- if (ASlave.type) {
+ if (TSlave.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 (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 (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"));
+ }
+ }
+ 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 ArduinoSlave_Show(bool json)
+void TasmotaSlave_Show(void)
{
- if (ASlave.type) {
- ArduinoSlave_Serial->flush();
- ArduinoSlave_Serial->print("JSON");
- ArduinoSlave_Serial->find(char(0xFE));
+ if ((TSlave.type) && (TSlaveSettings.features.json)) {
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);
- }
+ 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]);
}
}
@@ -279,13 +469,13 @@ bool Xdrv31(uint8_t function)
switch (function) {
case FUNC_EVERY_SECOND:
- ArduinoSlave_Init();
+ TasmotaSlave_Init();
break;
case FUNC_JSON_APPEND:
- ArduinoSlave_Show(1);
+ TasmotaSlave_Show();
break;
}
return result;
}
-#endif // USE_ARDUINO_SLAVE
\ No newline at end of file
+#endif // USE_TASMOTA_SLAVE
\ No newline at end of file