From 1d7310411f232691f0d6bebfddb499e52649f700 Mon Sep 17 00:00:00 2001 From: proddy Date: Sun, 26 May 2019 12:23:50 +0200 Subject: [PATCH] merge Junkers Tx logic --- CHANGELOG.md | 15 ++++++++----- lib/MyESP/MyESP.cpp | 2 +- src/ems-esp.cpp | 6 ++--- src/ems.cpp | 27 +++++++++++++++-------- src/ems.h | 1 + src/emsuart.cpp | 53 ++++++++++++++++++++++++++++++--------------- src/emsuart.h | 11 +++++----- src/version.h | 2 +- 8 files changed, 76 insertions(+), 41 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 39e4e9b83..169574802 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,20 +5,25 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [1.8.0dev] 2019- +## [1.8.0dev] 2019-05-26 ### Added - MM50 Mixer +- tx_delay takes a value from 0 to 3 for the different Tx logic + + 0 = original classic ems logic + + 1 = @kwertie01 ems+ logic (https://github.com/proddy/EMS-ESP/issues/23#issuecomment-476872291) + + 2 = @susisstrolch logic [(pull request 113)](https://github.com/proddy/EMS-ESP/pull/113) + + 3 = @philrich logic for Junkers (https://github.com/proddy/EMS-ESP/files/3190563/ems-delay-rev-poll.patch.txt) ### Fixed - runtime exceptions with latest 2.5.1 arduino core -### Changed - -- Improved Tx code, by @Susis Strolch [(pull request 113)](https://github.com/proddy/EMS-ESP/pull/113). Use `set_txdelay 2` - ## [1.7.0] 2019-05-11 ### Added diff --git a/lib/MyESP/MyESP.cpp b/lib/MyESP/MyESP.cpp index 5163c72f5..2cdd138f9 100644 --- a/lib/MyESP/MyESP.cpp +++ b/lib/MyESP/MyESP.cpp @@ -496,7 +496,7 @@ void MyESP::_consoleShowHelp() { } else { myDebug_P(PSTR("* Hostname: %s (%s)"), _getESPhostname().c_str(), WiFi.localIP().toString().c_str()); myDebug_P(PSTR("* WiFi SSID: %s (signal %d%%)"), WiFi.SSID().c_str(), getWifiQuality()); - myDebug_P(PSTR("* MQTT is %s"), mqttClient.connected() ? "connected" : "disconnected"); + myDebug_P(PSTR("* MQTT %s"), mqttClient.connected() ? "connected" : "disconnected"); } myDebug_P(PSTR("*")); diff --git a/src/ems-esp.cpp b/src/ems-esp.cpp index f8e21cf31..548747178 100644 --- a/src/ems-esp.cpp +++ b/src/ems-esp.cpp @@ -106,7 +106,7 @@ command_t project_cmds[] = { {true, "shower_alert ", "send a warning of cold water after shower time is exceeded"}, {true, "publish_wait ", "set frequency for publishing to MQTT"}, {true, "heating_circuit <1 | 2>", "set the thermostat HC to work with if using multiple heating circuits"}, - {true, "tx_delay ", "0=normal, 1=ems+, 2=new logic"}, + {true, "tx_delay ", "0=classic ems logic, 1=@kwertie01 ems+ logic, 2=@susisstrolch logic, 3=@philrich logic for Junkers"}, {false, "info", "show data captured on the EMS bus"}, {false, "log ", "set logging mode to none, basic, thermostat only, raw or verbose"}, @@ -339,10 +339,10 @@ void showInfo() { if (ems_getBusConnected()) { myDebug_P(PSTR(" Bus is connected")); - myDebug_P(PSTR(" Rx: Poll=%d microsecs, # Rx telegrams read=%d, # CRC errors=%d"), ems_getPollFrequency(), EMS_Sys_Status.emsRxPgks, EMS_Sys_Status.emxCrcErr); + myDebug_P(PSTR(" Rx: Poll=%d microseconds, # Rx telegrams read=%d, # CRC errors=%d"), ems_getPollFrequency(), EMS_Sys_Status.emsRxPgks, EMS_Sys_Status.emxCrcErr); if (ems_getTxCapable()) { - myDebug_P(PSTR(" Tx: available, Tx delay is %d, # Tx telegrams sent=%d"), ems_getTxDelay(), EMS_Sys_Status.emsTxPkgs); + myDebug_P(PSTR(" Tx: available, Tx delay is %d, # successful write commands=%d"), ems_getTxDelay(), EMS_Sys_Status.emsTxPkgs); } else { myDebug_P(PSTR(" Tx: no signal")); } diff --git a/src/ems.cpp b/src/ems.cpp index 7242fdea7..08d097588 100644 --- a/src/ems.cpp +++ b/src/ems.cpp @@ -221,6 +221,7 @@ void ems_init() { EMS_Sys_Status.emsPollFrequency = 0; EMS_Sys_Status.txRetryCount = 0; EMS_Sys_Status.emsTxDelay = 0; + EMS_Sys_Status.emsReverse = false; // thermostat EMS_Thermostat.setpoint_roomTemp = EMS_VALUE_SHORT_NOTSET; @@ -331,6 +332,13 @@ bool ems_getPoll() { void ems_setTxDelay(uint8_t delay) { EMS_Sys_Status.emsTxDelay = delay; + + // special case for Junkers. If tx_delay is 3 then set the reverse poll flag + // https://github.com/proddy/EMS-ESP/issues/103#issuecomment-495945850 + if (delay == 3) { + EMS_Sys_Status.emsReverse = true; + myDebug_P(PSTR("Setting for Tx Junkers logic and enabled the poll reverse flag")); + } } uint8_t ems_getTxDelay() { @@ -557,8 +565,9 @@ void _ems_sendTelegram() { return; } - // create header - EMS_TxTelegram.data[0] = EMS_ID_ME; // src + // create the header + EMS_TxTelegram.data[0] = (EMS_Sys_Status.emsReverse) ? EMS_ID_ME | 0x80 : EMS_ID_ME; // src + // dest if (EMS_TxTelegram.action == EMS_TX_TELEGRAM_WRITE) { EMS_TxTelegram.data[1] = EMS_TxTelegram.dest; @@ -672,9 +681,10 @@ void _ems_readTelegram(uint8_t * telegram, uint8_t length) { // create the Rx package static _EMS_RxTelegram EMS_RxTelegram; static uint32_t _last_emsPollFrequency = 0; - EMS_RxTelegram.telegram = telegram; - EMS_RxTelegram.timestamp = millis(); - EMS_RxTelegram.length = length; + + EMS_RxTelegram.telegram = telegram; + EMS_RxTelegram.timestamp = millis(); + EMS_RxTelegram.length = length; // check if we just received a single byte // it could well be a Poll request from the boiler for us, which will have a value of 0x8B (0x0B | 0x80) @@ -684,12 +694,11 @@ void _ems_readTelegram(uint8_t * telegram, uint8_t length) { EMS_Sys_Status.emsPollFrequency = (timenow_microsecs - _last_emsPollFrequency); _last_emsPollFrequency = timenow_microsecs; - // check first for a Poll for us uint8_t value = telegram[0]; // 1st byte of data package - if ((value & 0x7F) == EMS_ID_ME) { - EMS_Sys_Status.emsTxCapable = true; - + // check first for a Poll for us + // the poll has the MSB set - seems to work on both EMS and Junkers + if (value == (EMS_ID_ME | 0x80)) { // do we have something to send thats waiting in the Tx queue? // if so send it if the Queue is not in a wait state if ((!EMS_TxQueue.isEmpty()) && (EMS_Sys_Status.emsTxStatus == EMS_TX_STATUS_IDLE)) { diff --git a/src/ems.h b/src/ems.h index edb8fbd1e..34925146e 100644 --- a/src/ems.h +++ b/src/ems.h @@ -95,6 +95,7 @@ typedef struct { bool emsTxDisabled; // true to prevent all Tx uint8_t txRetryCount; // # times the last Tx was re-sent uint8_t emsTxDelay; // handles Tx logic + bool emsReverse; // if true, poll logic is reversed } _EMS_Sys_Status; // The Tx send package diff --git a/src/emsuart.cpp b/src/emsuart.cpp index 536572155..01b84cb75 100644 --- a/src/emsuart.cpp +++ b/src/emsuart.cpp @@ -175,7 +175,11 @@ void ICACHE_FLASH_ATTR emsuart_tx_brk() { // automatically be sent when the tx fifo is empty tmp = (1 << UCBRK); USC0(EMSUART_UART) |= (tmp); // set bit - delayMicroseconds(EMSUART_TX_BRK_WAIT); + if (EMS_Sys_Status.emsTxDelay <= 2) { + delayMicroseconds(EMSUART_TX_BRK_WAIT); // classic mode + } else if (EMS_Sys_Status.emsTxDelay == 3) { + delayMicroseconds(EMSUART_TX_WAIT_BRK - EMSUART_TX_LAG); // 1144 (11 Bits) + } USC0(EMSUART_UART) &= ~(tmp); // clear bit } @@ -193,21 +197,32 @@ static inline void ICACHE_FLASH_ATTR emsuart_loopback(bool enable) { * Send to Tx, ending with a */ void ICACHE_FLASH_ATTR emsuart_tx_buffer(uint8_t * buf, uint8_t len) { - // backwards compatibility - if (EMS_Sys_Status.emsTxDelay < 2) { + if (EMS_Sys_Status.emsTxDelay == 0) { // Classic logic + for (uint8_t i = 0; i < len; i++) { + USF(EMSUART_UART) = buf[i]; + } + emsuart_tx_brk(); // send + } else if (EMS_Sys_Status.emsTxDelay == 1) { // With extra tx delay for EMS+ + for (uint8_t i = 0; i < len; i++) { + USF(EMSUART_UART) = buf[i]; + delayMicroseconds(EMSUART_TX_BRK_WAIT); // https://github.com/proddy/EMS-ESP/issues/23# + } + emsuart_tx_brk(); // send + } else if (EMS_Sys_Status.emsTxDelay == 3) { // Junkers logic by @philrich for (uint8_t i = 0; i < len; i++) { USF(EMSUART_UART) = buf[i]; - // check if we need to force a delay to slow down Tx - // https://github.com/proddy/EMS-ESP/issues/23# - if (EMS_Sys_Status.emsTxDelay == 1) { - delayMicroseconds(EMSUART_TX_BRK_WAIT); - } + // just to be safe wait for tx fifo empty (needed?) + while (((USS(EMSUART_UART) >> USTXC) & 0xff) != 0) + ; + + // wait until bits are sent on wire + delayMicroseconds(EMSUART_TX_WAIT_BYTE - EMSUART_TX_LAG + EMSUART_TX_WAIT_GAP); } - emsuart_tx_brk(); // send - } else { - /* smart Tx - take two - https://github.com/proddy/EMS-ESP/issues/103 by @susisstrolch - * changed logic... + emsuart_tx_brk(); // send + } else if (EMS_Sys_Status.emsTxDelay == 2) { // smart Tx - take two - https://github.com/proddy/EMS-ESP/issues/103 by @susisstrolch + + /* * we emit the whole telegram, with Rx interrupt disabled, collecting busmaster response in FIFO. * after sending the last char we poll the Rx status until either * - size(Rx FIFO) == size(Tx-Telegram) @@ -227,8 +242,7 @@ void ICACHE_FLASH_ATTR emsuart_tx_buffer(uint8_t * buf, uint8_t len) { } // wait until we received sizeof(telegram) or RxBRK (== collision detect) - // while ((((USS(EMSUART_UART) >> USRXC) & 0xFF) < len) || !(USIS(EMSUART_UART) & (1 << UIBD))) - while ((((USS(EMSUART_UART) >> USRXC) & 0xFF) < len) || (U0IS & (1 << UIBD))) { + while ((((USS(EMSUART_UART) >> USRXC) & 0xFF) < len) || (USIS(EMSUART_UART) & (1 << UIBD))) { delayMicroseconds(11 * EMSUART_BIT_TIME); // burn CPU cycles... } @@ -236,7 +250,7 @@ void ICACHE_FLASH_ATTR emsuart_tx_buffer(uint8_t * buf, uint8_t len) { // on Rx-BRK (bus collision), we simply enable Rx and leave // otherwise, we send the final Tx-BRK in loopback and enable Rx-INT. // worst case, we'll see an additional Rx-BRK... - if (!(U0IS & (1 << UIBD))) { + if (!(USIS(EMSUART_UART) & (1 << UIBD))) { // no bus collision - send terminating BRK signal emsuart_loopback(true); USC0(EMSUART_UART) |= (1 << UCBRK); // set @@ -260,6 +274,11 @@ void ICACHE_FLASH_ATTR emsuart_tx_buffer(uint8_t * buf, uint8_t len) { * Send the Poll (our own ID) to Tx as a single byte and end with a */ void ICACHE_FLASH_ATTR emsuart_tx_poll() { - static uint8_t buf[] = {EMS_ID_ME}; + static uint8_t buf[1]; + if (EMS_Sys_Status.emsReverse) { + buf[0] = {EMS_ID_ME | 0x80}; + } else { + buf[0] = {EMS_ID_ME}; + } emsuart_tx_buffer(buf, 1); -} \ No newline at end of file +} diff --git a/src/emsuart.h b/src/emsuart.h index c01803cda..dce0bf761 100644 --- a/src/emsuart.h +++ b/src/emsuart.h @@ -16,11 +16,12 @@ #define EMS_MAXBUFFERS 10 // 4 buffers for circular filling to avoid collisions #define EMS_MAXBUFFERSIZE 32 // max size of the buffer. packets are max 32 bytes -// this is how long we drop the Tx signal to create a 11-bit Break of zeros (BRK) -// At 9600 baud, 11 bits will be 1144 microseconds -// the BRK from Boiler master is roughly 1.039ms, so accounting for hardware lag using around 2078 (for half-duplex) - 8 (lag) -#define EMSUART_TX_BRK_WAIT 2070 -#define EMSUART_BIT_TIME 104 // bit time @9600 baud +#define EMSUART_TX_BRK_WAIT 2070 // the BRK from Boiler master is roughly 1.039ms, so accounting for hardware lag using around 2078 (for half-duplex) - 8 (lag) +#define EMSUART_BIT_TIME 104 // bit time @9600 baud +#define EMSUART_TX_WAIT_BYTE EMSUART_BIT_TIME * 10 // Time to send one Byte (8 Bits, 1 Start Bit, 1 Stop Bit) +#define EMSUART_TX_WAIT_BRK EMSUART_BIT_TIME * 11 // Time to send a BRK Signal (11 Bit) +#define EMSUART_TX_WAIT_GAP EMSUART_BIT_TIME * 7 // Gap between to Bytes +#define EMSUART_TX_LAG 8 // Assumed Lag #define EMSUART_recvTaskPrio 1 #define EMSUART_recvTaskQueueLen 64 diff --git a/src/version.h b/src/version.h index b71406fcb..607408915 100644 --- a/src/version.h +++ b/src/version.h @@ -6,5 +6,5 @@ #pragma once #define APP_NAME "EMS-ESP" -#define APP_VERSION "1.8.0b3" +#define APP_VERSION "1.8.0b4" #define APP_HOSTNAME "ems-esp"