From 7d361061c6550745dc74542b527b5840f9cd72f7 Mon Sep 17 00:00:00 2001 From: Susis Strolch Date: Wed, 17 Jul 2019 14:25:54 +0200 Subject: [PATCH 1/4] add marker pins (GPIO12, GPIO14) for logic analyser MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ° use faster macros for LA markers --- lib/MyESP/MyESP.cpp | 5 ----- src/ems-esp.cpp | 4 ++++ src/ems.h | 45 ++++++++++++++++++++++++++++++++++++++++++++- src/emsuart.cpp | 7 +++++++ 4 files changed, 55 insertions(+), 6 deletions(-) diff --git a/lib/MyESP/MyESP.cpp b/lib/MyESP/MyESP.cpp index 9fd14b039..bd50785ab 100644 --- a/lib/MyESP/MyESP.cpp +++ b/lib/MyESP/MyESP.cpp @@ -2195,16 +2195,11 @@ void MyESP::begin(const char * app_hostname, const char * app_name, const char * } _eeprom_setup(); // set up EEPROM for storing crash data, if compiled with -DCRASH - _fs_setup(); // SPIFFS setup, do this first to get values _wifi_setup(); // WIFI setup _ota_setup(); // init OTA _webserver_setup(); // init web server - - // print a welcome message - myDebug_P(PSTR("\n* %s version %s"), _app_name, _app_version); SerialAndTelnet.flush(); - _setSystemCheck(false); // reset system check _heartbeatCheck(true); // force heartbeat } diff --git a/src/ems-esp.cpp b/src/ems-esp.cpp index b4c7da1f5..9e8593317 100644 --- a/src/ems-esp.cpp +++ b/src/ems-esp.cpp @@ -1799,6 +1799,10 @@ void showerCheck() { // SETUP // void setup() { + // LA trigger create a small puls to show setup is starting... + INIT_MARKERS(0); + LA_PULSE(50); + // init our own parameters initEMSESP(); diff --git a/src/ems.h b/src/ems.h index 34a0662ba..4c05d12fb 100644 --- a/src/ems.h +++ b/src/ems.h @@ -12,6 +12,47 @@ #include +/* debug helper for logic analyzer + * create marker puls on GPIOx + * ° for Rx, we use GPIO14 + * ° for Tx, we use GPIO12 + */ +#define LOGICANALYZER +#ifdef LOGICANALYZER + #define RX_MARK_PIN 14 + #define TX_MARK_PIN 12 + + #define RX_MARK_MASK (1<> USTXC) & 0xFF) != 0) ; + TX_PULSE(EMSUART_BIT_TIME/2); tmp = ((1 << UCRXRST) | (1 << UCTXRST)); // bit mask USC0(EMSUART_UART) |= (tmp); // set bits USC0(EMSUART_UART) &= ~(tmp); // clear bits @@ -199,17 +201,20 @@ void ICACHE_FLASH_ATTR emsuart_tx_buffer(uint8_t * buf, uint8_t len) { if (EMS_Sys_Status.emsTxMode == 0) { // classic mode logic for (uint8_t i = 0; i < len; i++) { + TX_PULSE(EMSUART_BIT_TIME/4); USF(EMSUART_UART) = buf[i]; } emsuart_tx_brk(); // send } else if (EMS_Sys_Status.emsTxMode == 1) { // With extra tx delay for EMS+ for (uint8_t i = 0; i < len; i++) { + TX_PULSE(EMSUART_BIT_TIME/4); 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.emsTxMode == 3) { // Junkers logic by @philrich for (uint8_t i = 0; i < len; i++) { + TX_PULSE(EMSUART_BIT_TIME/4); USF(EMSUART_UART) = buf[i]; // just to be safe wait for tx fifo empty (needed?) @@ -237,6 +242,7 @@ void ICACHE_FLASH_ATTR emsuart_tx_buffer(uint8_t * buf, uint8_t len) { // throw out the telegram... for (uint8_t i = 0; i < len;) { + TX_PULSE(EMSUART_BIT_TIME/4); USF(EMSUART_UART) = buf[i++]; // send each Tx byte // wait for echo from busmaster while ((((USS(EMSUART_UART) >> USRXC) & 0xFF) < i || (USIS(EMSUART_UART) & (1 << UIBD)))) { @@ -249,6 +255,7 @@ void ICACHE_FLASH_ATTR emsuart_tx_buffer(uint8_t * buf, uint8_t len) { // otherwise we send the final Tx-BRK in the loopback and re=enable Rx-INT. // worst case, we'll see an additional Rx-BRK... if (!(USIS(EMSUART_UART) & (1 << UIBD))) { + TX_PULSE(EMSUART_BIT_TIME/2); // no bus collision - send terminating BRK signal USC0(EMSUART_UART) |= (1 << UCLBE); // enable loopback USC0(EMSUART_UART) |= (1 << UCBRK); // set From 7743ff5d56dbc57051c61749969cef71282fd4dd Mon Sep 17 00:00:00 2001 From: Susis Strolch Date: Thu, 18 Jul 2019 16:26:42 +0200 Subject: [PATCH 2/4] add burnStarts, burnWorkMin, heatWorkMin to boiler data set --- src/ems-esp.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/ems-esp.cpp b/src/ems-esp.cpp index 9e8593317..06e39a463 100644 --- a/src/ems-esp.cpp +++ b/src/ems-esp.cpp @@ -754,6 +754,14 @@ void publishValues(bool force) { if (EMS_Boiler.wWHeat != EMS_VALUE_INT_NOTSET) rootBoiler["wWHeat"] = _bool_to_char(s, EMS_Boiler.wWHeat); + // **** also add burnStarts, burnWorkMin, heatWorkMin + if (abs(EMS_Boiler.burnStarts) != EMS_VALUE_LONG_NOTSET) + rootBoiler["burnStarts"] = (double)EMS_Boiler.burnStarts; + if (abs(EMS_Boiler.burnWorkMin) != EMS_VALUE_LONG_NOTSET) + rootBoiler["burnWorkMin"] = (double)EMS_Boiler.burnWorkMin; + if (abs(EMS_Boiler.heatWorkMin) != EMS_VALUE_LONG_NOTSET) + rootBoiler["heatWorkMin"] = (double)EMS_Boiler.heatWorkMin; + rootBoiler["ServiceCode"] = EMS_Boiler.serviceCodeChar; rootBoiler["ServiceCodeNumber"] = EMS_Boiler.serviceCode; From 5587b9d267711418c93926bc110e9718bff65fd5 Mon Sep 17 00:00:00 2001 From: Susis Strolch Date: Fri, 19 Jul 2019 13:16:23 +0200 Subject: [PATCH 3/4] reworks because of 'tx_mode 2' and protocol issues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ° added markers (GIO12, GPIO14) for logic analyzer debugging ° change UART initialisation - set RxFIFO full to 1 char, so we can detect active telegram on EMS-Bus - set RxTOT to 1 char for the same reason ° in ems_parseTelegram: ignore telegram if emsRxStatus != EMS_RX_STATUS_IDLE because we missed to respond in a timely manner ° ems_tx_buffer is not void anymore, instead we return the Tx status ° extended the emsTxStatus - EMS_TX_WTD_TIMEOUT: timeout while waiting for echo of last Tx byte out telegram was ignored by the bus master, so the byte wasn't echoed - EMS_TX_BRK_DETECT: BRK detected while sending the telegram bus master send us a break because of protocol violation ° add burnStarts, burnWorkMin and heatWorkMin to MQTT boiler message TODO: + take care of ems_tx_buffer return code + accept direct telegram in ems_parse_telegram and do a proper acknowledge + split the heartbeat in static (version, IP-address) and dynamic (RSS etc) + change the hearbeat to a JSON structure so we can easier pick the uptime --- src/ems.cpp | 21 ++++- src/ems.h | 10 +-- src/emsuart.cpp | 203 +++++++++++++++++++++++++++++------------------- src/emsuart.h | 2 +- src/my_config.h | 5 ++ 5 files changed, 151 insertions(+), 90 deletions(-) diff --git a/src/ems.cpp b/src/ems.cpp index fd492b5b6..cbf2a6c2a 100644 --- a/src/ems.cpp +++ b/src/ems.cpp @@ -724,9 +724,23 @@ void ems_parseTelegram(uint8_t * telegram, uint8_t length) { 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) - // or either a return code like 0x01 or 0x04 from the last Write command + /* + * 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) + * or either a return code like 0x01 or 0x04 from the last Write command + * Roger Wilco: we have different types here: + * EMS_ID_ME && length == 1 && EMS_TX_STATUS_IDLE && EMS_RX_STATUS_IDLE: polling request + * EMS_ID_ME && length > 1 && EMS_TX_STATUS_IDLE && EMS_RX_STATUS_IDLE: direct telegram + * (EMS_TX_SUCCESS || EMS_TX_ERROR) && EMS_TX_STATUS_WAIT: response, free the EMS bus + * + * In addition, it may happen that we where interrupted (f.e. by WIFI activity) and the + * buffer isn't valid anymore, so we must not answer at all... + */ + if (EMS_Sys_Status.emsRxStatus != EMS_RX_STATUS_IDLE) { + myDebug_P(PSTR("** We missed the bus - Rx non-idle!")); + return; + } + if (length == 1) { uint8_t value = telegram[0]; // 1st byte of data package @@ -816,6 +830,7 @@ void ems_parseTelegram(uint8_t * telegram, uint8_t length) { // Assume at this point we have something that vaguely resembles a telegram in the format [src] [dest] [type] [offset] [data] [crc] // validate the CRC, if it's bad ignore it if (telegram[length - 1] != _crcCalculator(telegram, length)) { + LA_PULSE(200); EMS_Sys_Status.emxCrcErr++; if (EMS_Sys_Status.emsLogging == EMS_SYS_LOGGING_VERBOSE) { _debugPrintTelegram("Corrupt telegram: ", &EMS_RxTelegram, COLOR_RED, true); diff --git a/src/ems.h b/src/ems.h index 4c05d12fb..5d406bef7 100644 --- a/src/ems.h +++ b/src/ems.h @@ -17,7 +17,6 @@ * ° for Rx, we use GPIO14 * ° for Tx, we use GPIO12 */ -#define LOGICANALYZER #ifdef LOGICANALYZER #define RX_MARK_PIN 14 #define TX_MARK_PIN 12 @@ -47,10 +46,10 @@ GPIO_L(MARKERS_MASK); \ } while (0) #else - #define RX_PULSE(pulse) - #define TX_PULSE(pulse) - #define LA_PULSE(pulse) - #define INIT_MARKERS(void) + #define RX_PULSE(pulse) {} + #define TX_PULSE(pulse) {} + #define LA_PULSE(pulse) {} + #define INIT_MARKERS(void) {} #endif #define EMS_ID_NONE 0x00 // used as a dest in broadcast messages and empty device IDs @@ -104,6 +103,7 @@ typedef enum { } _EMS_RX_STATUS; typedef enum { + EMS_TX_STATUS_OK, EMS_TX_STATUS_IDLE, // ready EMS_TX_STATUS_WAIT, // waiting for response from last Tx EMS_TX_WTD_TIMEOUT, // watchdog timeout during send diff --git a/src/emsuart.cpp b/src/emsuart.cpp index 30eb88295..5c19b0296 100644 --- a/src/emsuart.cpp +++ b/src/emsuart.cpp @@ -5,10 +5,10 @@ * Paul Derbyshire - https://github.com/proddy/EMS-ESP */ -#include "emsuart.h" -#include "ems.h" #include #include +#include "ems.h" +#include "emsuart.h" _EMSRxBuf * pEMSRxBuf; _EMSRxBuf * paEMSRxBuf[EMS_MAXBUFFERS]; @@ -29,7 +29,7 @@ static void emsuart_rx_intr_handler(void * para) { EMS_Sys_Status.emsRxStatus = EMS_RX_STATUS_BUSY; // status set to busy length = 0; } - + GPIO_H(RX_MARK_MASK); // fill IRQ buffer, by emptying Rx FIFO if (USIS(EMSUART_UART) & ((1 << UIFF) | (1 << UITO) | (1 << UIBD))) { while ((USS(EMSUART_UART) >> USRXC) & 0xFF) { @@ -39,21 +39,20 @@ static void emsuart_rx_intr_handler(void * para) { // clear Rx FIFO full and Rx FIFO timeout interrupts USIC(EMSUART_UART) = (1 << UIFF) | (1 << UITO); } + GPIO_L(RX_MARK_MASK); // BREAK detection = End of EMS data block if (USIS(EMSUART_UART) & ((1 << UIBD))) { ETS_UART_INTR_DISABLE(); // disable all interrupts and clear them - RX_PULSE(EMSUART_BIT_TIME/2); - USIC(EMSUART_UART) = (1 << UIBD); // INT clear the BREAK detect interrupt pEMSRxBuf->length = length; os_memcpy((void *)pEMSRxBuf->buffer, (void *)&uart_buffer, length); // copy data into transfer buffer, including the BRK 0x00 at the end EMS_Sys_Status.emsRxStatus = EMS_RX_STATUS_IDLE; // set the status flag stating BRK has been received and we can start a new package + ETS_UART_INTR_ENABLE(); // re-enable UART interrupts system_os_post(EMSUART_recvTaskPrio, 0, 0); // call emsuart_recvTask() at next opportunity - - ETS_UART_INTR_ENABLE(); // re-enable UART interrupts + RX_PULSE(EMSUART_BIT_TIME/2); } } @@ -64,21 +63,22 @@ static void emsuart_rx_intr_handler(void * para) { */ static void ICACHE_FLASH_ATTR emsuart_recvTask(os_event_t * events) { _EMSRxBuf * pCurrent = pEMSRxBuf; + pEMSRxBuf = paEMSRxBuf[++emsRxBufIdx % EMS_MAXBUFFERS]; // next free EMS Receive buffer uint8_t length = pCurrent->length; // number of bytes including the BRK at the end + pCurrent->length = 0; // validate and transmit the EMS buffer, excluding the BRK if (length == 2) { + RX_PULSE(20); // it's a poll or status code, single byte and ok to send on ems_parseTelegram((uint8_t *)pCurrent->buffer, 1); } else if ((length > 4) && (length <= EMS_MAXBUFFERSIZE + 1) && (pCurrent->buffer[length - 2] != 0x00)) { // ignore double BRK at the end, possibly from the Tx loopback // also telegrams with no data value + RX_PULSE(40); ems_parseTelegram((uint8_t *)pCurrent->buffer, length - 1); // transmit EMS buffer, excluding the BRK } - - memset(pCurrent->buffer, 0x00, EMS_MAXBUFFERSIZE); // wipe memory just to be safe - - pEMSRxBuf = paEMSRxBuf[++emsRxBufIdx % EMS_MAXBUFFERS]; // next free EMS Receive buffer + // memset(pCurrent->buffer, 0x00, EMS_MAXBUFFERSIZE); // wipe memory just to be safe } /* @@ -118,11 +118,14 @@ void ICACHE_FLASH_ATTR emsuart_init() { // conf1 params // UCTOE = RX TimeOut enable (default is 1) - // UCTOT = RX TimeOut Threshold (7 bit) = want this when no more data after 2 characters (default is 2) + // UCTOT = RX TimeOut Threshold (7 bit) = want this when no more data after 1 characters (default is 2) // UCFFT = RX FIFO Full Threshold (7 bit) = want this to be 31 for 32 bytes of buffer (default was 127) // see https://www.espressif.com/sites/default/files/documentation/esp8266-technical_reference_en.pdf + // + // change: we set UCFFT to 1 to get an immediate indicator about incoming trafffic. + // Otherwise, we're only noticed by UCTOT or RxBRK! USC1(EMSUART_UART) = 0; // reset config first - USC1(EMSUART_UART) = (EMS_MAX_TELEGRAM_LENGTH << UCFFT) | (0x02 << UCTOT) | (1 << UCTOE); // enable interupts + USC1(EMSUART_UART) = (0x01 << UCFFT) | (0x01 << UCTOT) | (1 << UCTOE); // enable interupts // set interrupts for triggers USIC(EMSUART_UART) = 0xFFFF; // clear all interupts @@ -171,7 +174,6 @@ void ICACHE_FLASH_ATTR emsuart_tx_brk() { while (((USS(EMSUART_UART) >> USTXC) & 0xFF) != 0) ; - TX_PULSE(EMSUART_BIT_TIME/2); tmp = ((1 << UCRXRST) | (1 << UCTXRST)); // bit mask USC0(EMSUART_UART) |= (tmp); // set bits USC0(EMSUART_UART) &= ~(tmp); // clear bits @@ -179,6 +181,7 @@ void ICACHE_FLASH_ATTR emsuart_tx_brk() { // To create a 11-bit we set TXD_BRK bit so the break signal will // automatically be sent when the tx fifo is empty tmp = (1 << UCBRK); + GPIO_H(TX_MARK_MASK); USC0(EMSUART_UART) |= (tmp); // set bit if (EMS_Sys_Status.emsTxMode <= 1) { // classic mode and ems+ (0, 1) @@ -188,91 +191,129 @@ void ICACHE_FLASH_ATTR emsuart_tx_brk() { } USC0(EMSUART_UART) &= ~(tmp); // clear bit + GPIO_L(TX_MARK_MASK); } /* * Send to Tx, ending with a */ -void ICACHE_FLASH_ATTR emsuart_tx_buffer(uint8_t * buf, uint8_t len) { - if (len == 0) - return; +_EMS_TX_STATUS ICACHE_FLASH_ATTR emsuart_tx_buffer(uint8_t * buf, uint8_t len) { + _EMS_TX_STATUS result = EMS_TX_STATUS_OK; + if (len) { + LA_PULSE(50); + // temp code until we get mode 2 working without resets + if (EMS_Sys_Status.emsTxMode == 0) { // classic mode logic + for (uint8_t i = 0; i < len; i++) { + TX_PULSE(EMSUART_BIT_TIME/4); + USF(EMSUART_UART) = buf[i]; + } + emsuart_tx_brk(); // send + } else if (EMS_Sys_Status.emsTxMode == 1) { // With extra tx delay for EMS+ + for (uint8_t i = 0; i < len; i++) { + TX_PULSE(EMSUART_BIT_TIME/4); + 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.emsTxMode == 3) { // Junkers logic by @philrich + for (uint8_t i = 0; i < len; i++) { + TX_PULSE(EMSUART_BIT_TIME/4); + USF(EMSUART_UART) = buf[i]; - // temp code until we get mode 2 working without resets + // just to be safe wait for tx fifo empty (needed?) + while (((USS(EMSUART_UART) >> USTXC) & 0xff) != 0) + ; - if (EMS_Sys_Status.emsTxMode == 0) { // classic mode logic - for (uint8_t i = 0; i < len; i++) { - TX_PULSE(EMSUART_BIT_TIME/4); - USF(EMSUART_UART) = buf[i]; - } - emsuart_tx_brk(); // send - } else if (EMS_Sys_Status.emsTxMode == 1) { // With extra tx delay for EMS+ - for (uint8_t i = 0; i < len; i++) { - TX_PULSE(EMSUART_BIT_TIME/4); - 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.emsTxMode == 3) { // Junkers logic by @philrich - for (uint8_t i = 0; i < len; i++) { - TX_PULSE(EMSUART_BIT_TIME/4); - USF(EMSUART_UART) = buf[i]; + // wait until bits are sent on wire + delayMicroseconds(EMSUART_TX_WAIT_BYTE - EMSUART_TX_LAG + EMSUART_TX_WAIT_GAP); + } + emsuart_tx_brk(); // send + } else if (EMS_Sys_Status.emsTxMode == 2) { + /* + * based on code from 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) + * - is detected + * At end of receive we re-enable Rx-INT and send a Tx-BRK in loopback mode. + */ - // 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 if (EMS_Sys_Status.emsTxMode == 2) { /* - * based on code from 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) - * - is detected - * At end of receive we re-enable Rx-INT and send a Tx-BRK in loopback mode. - */ - ETS_UART_INTR_DISABLE(); // disable rx interrupt + * EMS-Bus error handling + * 1. Busmaster stops echoing on Tx w/o permission + * 2. Busmaster cancel telegram by sending a BRK + * + * Case 1. is handled by a watchdog counter which is reset on each + * Tx attempt. The timeout should be 20x EMSUART_BIT_TIME plus + * some smart guess for processing time on targeted EMS device. + * We set EMS_Sys_Status.emsTxStatus to EMS_TX_WTD_TIMEOUT and return + * + * Case 2. is handled via a BRK chk during transmission. + * We set EMS_Sys_Status.emsTxStatus to EMS_TX_BRK_DETECT and return + * + */ + // shorter busy poll... + #define EMSUART_BUSY_WAIT (EMSUART_BIT_TIME / 8) + #define EMS_TX_TO_COUNT ((20 + 10000 / EMSUART_BIT_TIME) * 8) + uint16_t wdc = EMS_TX_TO_COUNT; - // clear Rx status register - USC0(EMSUART_UART) |= (1 << UCRXRST); // reset uart rx fifo - emsuart_flush_fifos(); + ETS_UART_INTR_DISABLE(); // disable rx interrupt - // throw out the telegram... - for (uint8_t i = 0; i < len;) { - TX_PULSE(EMSUART_BIT_TIME/4); - USF(EMSUART_UART) = buf[i++]; // send each Tx byte - // wait for echo from busmaster - while ((((USS(EMSUART_UART) >> USRXC) & 0xFF) < i || (USIS(EMSUART_UART) & (1 << UIBD)))) { - delayMicroseconds(EMSUART_BIT_TIME); // burn CPU cycles... - } - } + // clear Rx status register + USC0(EMSUART_UART) |= (1 << UCRXRST); // reset uart rx fifo + emsuart_flush_fifos(); - // we got the whole telegram in the Rx buffer - // on Rx-BRK (bus collision), we simply enable Rx and leave it - // otherwise we send the final Tx-BRK in the loopback and re=enable Rx-INT. - // worst case, we'll see an additional Rx-BRK... - if (!(USIS(EMSUART_UART) & (1 << UIBD))) { - TX_PULSE(EMSUART_BIT_TIME/2); - // no bus collision - send terminating BRK signal - USC0(EMSUART_UART) |= (1 << UCLBE); // enable loopback - USC0(EMSUART_UART) |= (1 << UCBRK); // set + // throw out the telegram... + for (uint8_t i = 0; i < len && result == EMS_TX_STATUS_OK;) { + GPIO_H(TX_MARK_MASK); - // wait until BRK detected... - while (!(USIS(EMSUART_UART) & (1 << UIBD))) { - delayMicroseconds(EMSUART_BIT_TIME); + wdc = EMS_TX_TO_COUNT; + volatile uint8_t _usrxc = (USS(EMSUART_UART) >> USRXC) & 0xFF; + USF(EMSUART_UART) = buf[i++]; // send each Tx byte + // wait for echo from busmaster + GPIO_L(TX_MARK_MASK); + + while (((USS(EMSUART_UART) >> USRXC) & 0xFF) == _usrxc) { + delayMicroseconds(EMSUART_BUSY_WAIT); // burn CPU cycles... + if (--wdc == 0) { + EMS_Sys_Status.emsTxStatus = result = EMS_TX_WTD_TIMEOUT; + break; + } + if (USIR(EMSUART_UART) & (1 << UIBD)) { + USIC(EMSUART_UART) = (1 << UIBD); // clear BRK detect IRQ + EMS_Sys_Status.emsTxStatus = result = EMS_TX_BRK_DETECT; + } + } } - USC0(EMSUART_UART) &= ~(1 << UCBRK); // clear + // we got the whole telegram in the Rx buffer + // on Rx-BRK (bus collision), we simply enable Rx and leave it + // otherwise we send the final Tx-BRK in the loopback and re=enable Rx-INT. + // worst case, we'll see an additional Rx-BRK... + if (result != EMS_TX_STATUS_OK) { + LA_PULSE(200); // mark Tx error + } else { + // neither bus collision nor timeout - send terminating BRK signal + GPIO_H(TX_MARK_MASK); + if (!(USIS(EMSUART_UART) & (1 << UIBD))) { - USIC(EMSUART_UART) = (1 << UIBD); // clear BRK detect IRQ - USC0(EMSUART_UART) &= ~(1 << UCLBE); // disable loopback + // no bus collision - send terminating BRK signal + USC0(EMSUART_UART) |= (1 << UCLBE)|(1 << UCBRK); // enable loopback & set + + // wait until BRK detected... + while (!(USIR(EMSUART_UART) & (1 << UIBD))) { + delayMicroseconds(EMSUART_BUSY_WAIT); + } + + USC0(EMSUART_UART) &= ~((1 << UCBRK)|(1 << UCLBE)); // disable loopback & clear + USIC(EMSUART_UART) = (1 << UIBD); // clear BRK detect IRQ + } + GPIO_L(TX_MARK_MASK); + } + ETS_UART_INTR_ENABLE(); // receive anything from FIFO... } - - ETS_UART_INTR_ENABLE(); // receive anything from FIFO... } + return result; } /* diff --git a/src/emsuart.h b/src/emsuart.h index c49e2f6a8..9424ac7cf 100644 --- a/src/emsuart.h +++ b/src/emsuart.h @@ -35,5 +35,5 @@ typedef struct { void ICACHE_FLASH_ATTR emsuart_init(); void ICACHE_FLASH_ATTR emsuart_stop(); void ICACHE_FLASH_ATTR emsuart_start(); -void ICACHE_FLASH_ATTR emsuart_tx_buffer(uint8_t * buf, uint8_t len); +_EMS_TX_STATUS ICACHE_FLASH_ATTR emsuart_tx_buffer(uint8_t * buf, uint8_t len); void ICACHE_FLASH_ATTR emsuart_tx_poll(); diff --git a/src/my_config.h b/src/my_config.h index 20575b25d..f83ff92b9 100644 --- a/src/my_config.h +++ b/src/my_config.h @@ -84,10 +84,15 @@ // can be enabled and disabled via the 'set led' command and pin set by 'set led_gpio' #define EMSESP_LED_GPIO LED_BUILTIN +#ifdef LOGICANALYZER +#define EMSESP_DALLAS_GPIO D1 +#define EMSESP_DALLAS_PARASITE false +#else // set this if using an external temperature sensor like a DS18B20 // D5 is the default on a bbqkees board #define EMSESP_DALLAS_GPIO D5 #define EMSESP_DALLAS_PARASITE false +#endif // By default the EMS bus will be scanned for known devices based on the product ids in ems_devices.h // You can override the Thermostat and Boiler types here From 0a700b945171d929e5d74b1797ee28469330ab54 Mon Sep 17 00:00:00 2001 From: Susis Strolch Date: Fri, 19 Jul 2019 15:46:18 +0200 Subject: [PATCH 4/4] in ems-esp:setup: set GPIO15 to HIGH so we don't disturb the EMS-Bus during boot --- src/ems-esp.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ems-esp.cpp b/src/ems-esp.cpp index 06e39a463..9af65f956 100644 --- a/src/ems-esp.cpp +++ b/src/ems-esp.cpp @@ -1811,6 +1811,10 @@ void setup() { INIT_MARKERS(0); LA_PULSE(50); + // GPIO15 has a pull down, so we must set it to HIGH + pinMode(15, OUTPUT); + digitalWrite(15,1); + // init our own parameters initEMSESP();