From dab66ce9181888852817abe78e062e3923c75503 Mon Sep 17 00:00:00 2001 From: Susis Strolch Date: Mon, 22 Jul 2019 10:39:47 +0200 Subject: [PATCH] =?UTF-8?q?fixing=20tx=5Fmode=202=20=C2=B0=20stabilize=20e?= =?UTF-8?q?msuart=5Frx...=20=20=20We=20can=20get=20more=20than=2032=20byte?= =?UTF-8?q?s=20because=20of=20the=20trailing=20BRK.=20=20=20So=20the=20buf?= =?UTF-8?q?fersize=20for=20Rx=20interrupt=20is=20(for=20safety)=20increase?= =?UTF-8?q?d=20to=2036=20bytes.=20=20=20If=20length=20exceeds=2036=20bytes?= =?UTF-8?q?=20we=20dump=20them=20to=20/dev/null?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ° reintroduced the phantomBreak flag again We _must_ signal to Rx that we have a double break, otherwise we get problems in emsuart_recvTask... ° add ems_dumpBuffer which shows TxBuffer before send and RxBuffer after receive and applying phantomBreak. The dump is activated in "log j" mode and used to debug the protocol problems. ° change handling of ID bit 7 on system start we listen for telegram until we receive a valid one, larger than 5 byte. Depending on the bit7 of the source address we decide if we have a Buderus EMS or a Junkers EMS bus. This decision is used to set the variables emsIDMask (0x00 for Buderus, 0x80 for Junkers) and the emsPollAck buffer, used to send the propper acknowledge, depending on EMS type. ° move poll acknowledge function (emsuart_tx_poll) from emsuart.cpp to ems.cpp and rename to ems_pollAck ° add EMS_TX_REV_DETECT status for detecting the SourceID.7 bit and setting emsIDMask and emsPollAck buffer accordingly ° set initial emsTxStatus to EMS_TX_REV_DETECT ° add 'log j' - jabber - for more extensive debug logs --- src/ems-esp.cpp | 3 ++ src/ems.cpp | 139 +++++++++++++++++++++++++++++++++++++++--------- src/ems.h | 58 ++++++++++---------- src/emsuart.cpp | 49 +++++++++-------- src/emsuart.h | 1 - 5 files changed, 174 insertions(+), 76 deletions(-) diff --git a/src/ems-esp.cpp b/src/ems-esp.cpp index 5733a8367..3632f6644 100644 --- a/src/ems-esp.cpp +++ b/src/ems-esp.cpp @@ -1467,6 +1467,9 @@ void TelnetCommandCallback(uint8_t wc, const char * commandLine) { } else if (strcmp(second_cmd, "n") == 0) { ems_setLogging(EMS_SYS_LOGGING_NONE); ok = true; + } else if (strcmp(second_cmd, "j") == 0) { + ems_setLogging(EMS_SYS_LOGGING_NONE); + ok = true; } } diff --git a/src/ems.cpp b/src/ems.cpp index b33c6c597..6bc10ddf9 100644 --- a/src/ems.cpp +++ b/src/ems.cpp @@ -226,7 +226,7 @@ void ems_init() { EMS_Sys_Status.emsTxPkgs = 0; EMS_Sys_Status.emxCrcErr = 0; EMS_Sys_Status.emsRxStatus = EMS_RX_STATUS_IDLE; - EMS_Sys_Status.emsTxStatus = EMS_TX_STATUS_IDLE; + EMS_Sys_Status.emsTxStatus = EMS_TX_REV_DETECT; EMS_Sys_Status.emsRefreshed = false; EMS_Sys_Status.emsPollEnabled = false; // start up with Poll disabled EMS_Sys_Status.emsBusConnected = false; @@ -235,8 +235,9 @@ void ems_init() { EMS_Sys_Status.emsTxDisabled = false; EMS_Sys_Status.emsPollFrequency = 0; EMS_Sys_Status.txRetryCount = 0; - EMS_Sys_Status.emsReverse = false; EMS_Sys_Status.emsTxMode = 0; + EMS_Sys_Status.emsIDMask = 0x00; + EMS_Sys_Status.emsPollAck[0] = EMS_ID_ME; // thermostat EMS_Thermostat.setpoint_roomTemp = EMS_VALUE_SHORT_NOTSET; @@ -361,11 +362,12 @@ void ems_setTxMode(uint8_t mode) { // special case for Junkers. If tx_mode is 3 then set the reverse poll flag // https://github.com/proddy/EMS-ESP/issues/103#issuecomment-495945850 if (mode == 3) { - EMS_Sys_Status.emsReverse = true; + EMS_Sys_Status.emsIDMask = 0x80; myDebug_P(PSTR("Forcing emsReverse for Junkers")); } else { - EMS_Sys_Status.emsReverse = false; + EMS_Sys_Status.emsIDMask = 0x00; } + EMS_Sys_Status.emsPollAck[0] = EMS_ID_ME ^ EMS_Sys_Status.emsIDMask; } uint8_t ems_getTxMode() { @@ -453,10 +455,19 @@ void ems_setLogging(_EMS_SYS_LOGGING loglevel) { myDebug_P(PSTR("System Logging set to Solar Module only")); } else if (loglevel == EMS_SYS_LOGGING_RAW) { myDebug_P(PSTR("System Logging set to Raw mode")); + } else if (loglevel == EMS_SYS_LOGGING_JABBER) { + myDebug_P(PSTR("System Logging set to Jabber mode")); } } } +/** + * send a poll acknowledge + */ +void ems_tx_pollAck() { + emsuart_tx_buffer(&EMS_Sys_Status.emsPollAck[0], 1); +} + /** * Calculate CRC checksum using lookup table for speed * len is length of all the data in bytes (including the header & CRC byte at end) @@ -615,20 +626,26 @@ void _ems_sendTelegram() { } EMS_TxTelegram.data[EMS_TxTelegram.length - 1] = _crcCalculator(EMS_TxTelegram.data, EMS_TxTelegram.length); // add the CRC - emsuart_tx_buffer(EMS_TxTelegram.data, EMS_TxTelegram.length); // send the telegram to the UART Tx - EMS_TxQueue.shift(); // and remove from queue + _EMS_TX_STATUS _txStatus = emsuart_tx_buffer(EMS_TxTelegram.data, EMS_TxTelegram.length); // send the telegram to the UART Tx + if (EMS_TX_BRK_DETECT == _txStatus || EMS_TX_WTD_TIMEOUT == _txStatus) { + // Tx Error! + myDebug_P(PSTR("** error sending buffer: %s"),_txStatus == EMS_TX_BRK_DETECT ? + "BRK" : "WDTO"); + // EMS_Sys_Status.emsTxStatus = EMS_TX_STATUS_IDLE; + } + EMS_TxQueue.shift(); // and remove from queue return; } // create the header - EMS_TxTelegram.data[0] = (EMS_Sys_Status.emsReverse) ? EMS_ID_ME | 0x80 : EMS_ID_ME; // src + EMS_TxTelegram.data[0] = EMS_ID_ME ^ EMS_Sys_Status.emsIDMask; // src // dest if (EMS_TxTelegram.action == EMS_TX_TELEGRAM_WRITE) { EMS_TxTelegram.data[1] = EMS_TxTelegram.dest; } else { // for a READ or VALIDATE - EMS_TxTelegram.data[1] = EMS_TxTelegram.dest | 0x80; // read has 8th bit set + EMS_TxTelegram.data[1] = (EMS_TxTelegram.dest ^ 0x80 ^ EMS_Sys_Status.emsIDMask); // read has 8th bit set } // complete the rest of the header depending on EMS or EMS+ @@ -671,9 +688,17 @@ void _ems_sendTelegram() { } // send the telegram to the UART Tx - emsuart_tx_buffer(EMS_TxTelegram.data, EMS_TxTelegram.length); + _EMS_TX_STATUS _txStatus = emsuart_tx_buffer(EMS_TxTelegram.data, EMS_TxTelegram.length); // send the telegram to the UART Tx + if (EMS_TX_STATUS_OK == _txStatus || EMS_TX_STATUS_IDLE == _txStatus) + EMS_Sys_Status.emsTxStatus = EMS_TX_STATUS_WAIT; + else { + // Tx Error! + // Tx Error! + myDebug_P(PSTR("** error sending buffer: %s"),_txStatus == EMS_TX_BRK_DETECT ? + "BRK" : "WDTO"); + EMS_Sys_Status.emsTxStatus = EMS_TX_STATUS_IDLE; + } - EMS_Sys_Status.emsTxStatus = EMS_TX_STATUS_WAIT; } @@ -720,6 +745,57 @@ void _createValidate() { EMS_TxQueue.unshift(new_EMS_TxTelegram); // add back to queue making it first to be picked up next (FIFO) } +/** + * dump a UART Tx or Rx buffer to console... + */ +void ems_dumpBuffer(const char *prefix, uint8_t *telegram, uint8_t length) { + uint32_t timestamp = millis(); + static char output_str[200] = {0}; + static char buffer[16] = {0}; + + if (EMS_Sys_Status.emsLogging != EMS_SYS_LOGGING_JABBER) + return; + + // we only care about known devices + if (length) { + uint8_t dev = telegram[0] & 0x7F; + if (!((dev == 0x04)||(dev == 0x08)||(dev == 0x09)||(dev == 0x0a) + ||(dev == 0x01)||(dev == 0x0b)||(dev == 0x10))) + return; + } + + strlcpy(output_str, "(", sizeof(output_str)); + strlcat(output_str, COLOR_CYAN, sizeof(output_str)); + strlcat(output_str, _smallitoa((uint8_t)((timestamp / 3600000) % 24), buffer), sizeof(output_str)); + strlcat(output_str, ":", sizeof(output_str)); + strlcat(output_str, _smallitoa((uint8_t)((timestamp / 60000) % 60), buffer), sizeof(output_str)); + strlcat(output_str, ":", sizeof(output_str)); + strlcat(output_str, _smallitoa((uint8_t)((timestamp / 1000) % 60), buffer), sizeof(output_str)); + strlcat(output_str, ".", sizeof(output_str)); + strlcat(output_str, _smallitoa3(timestamp % 1000, buffer), sizeof(output_str)); + strlcat(output_str, COLOR_RESET, sizeof(output_str)); + strlcat(output_str, ") ", sizeof(output_str)); + + strlcat(output_str, COLOR_YELLOW, sizeof(output_str)); + strlcat(output_str, prefix, sizeof(output_str)); + + // show some EMS_Sys_Status entries + strlcat(output_str, _hextoa(EMS_Sys_Status.emsRxStatus, buffer), sizeof(output_str)); + strlcat(output_str, " ", sizeof(output_str)); + strlcat(output_str, _hextoa(EMS_Sys_Status.emsTxStatus, buffer), sizeof(output_str)); + strlcat(output_str, ": ", sizeof(output_str)); + + + // print whole buffer, don't interpret any data + for (int i = 0; i < (length); i++) { + strlcat(output_str, _hextoa(telegram[i], buffer), sizeof(output_str)); + strlcat(output_str, " ", sizeof(output_str)); + } + + strlcat(output_str, COLOR_RESET, sizeof(output_str)); + + myDebug(output_str); +} /** * Entry point triggered by an interrupt in emsuart.cpp * length is the number of all the telegram bytes up to and including the CRC at the end @@ -729,16 +805,28 @@ void _createValidate() { void ems_parseTelegram(uint8_t * telegram, uint8_t length) { static uint32_t _last_emsPollFrequency = 0; + ems_dumpBuffer("** [DEBUG MODE] ems_parseTelegram: ", telegram, 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 - * 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 + */ + + /* + * Detect the EMS bus type - Buderus or Junkers - and set emsIDMask accordingly. + * we wait for the first valid telegram and look at the SourceID. + * If Bit 7 is set we have a Buderus, otherwise a Junkers + */ + if (EMS_Sys_Status.emsTxStatus == EMS_TX_REV_DETECT) { + if ((length >= 5) && (telegram[length - 1] == _crcCalculator(telegram, length))) { + EMS_Sys_Status.emsTxStatus = EMS_TX_STATUS_IDLE; + EMS_Sys_Status.emsIDMask = telegram[0] & 0x80; + EMS_Sys_Status.emsPollAck[0] = EMS_ID_ME ^ EMS_Sys_Status.emsIDMask; + } else + return; // ignore the whole telegram Rx Telegram while in DETECT mode + } + + /* 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) { @@ -752,8 +840,7 @@ void ems_parseTelegram(uint8_t * telegram, uint8_t length) { uint8_t value = telegram[0]; // 1st byte of data package // check first for a Poll for us - // the poll has the MSB set - seems to work on both EMS and Junkers - if ((value & 0x7F) == EMS_ID_ME) { + if ((value ^ 0x80 ^ EMS_Sys_Status.emsIDMask) == EMS_ID_ME) { EMS_Sys_Status.emsTxCapable = true; uint32_t timenow_microsecs = micros(); EMS_Sys_Status.emsPollFrequency = (timenow_microsecs - _last_emsPollFrequency); @@ -766,7 +853,7 @@ void ems_parseTelegram(uint8_t * telegram, uint8_t length) { } else { // nothing to send so just send a poll acknowledgement back if (EMS_Sys_Status.emsPollEnabled) { - emsuart_tx_poll(); + ems_tx_pollAck(); } } } else if (EMS_Sys_Status.emsTxStatus == EMS_TX_STATUS_WAIT) { @@ -774,14 +861,14 @@ void ems_parseTelegram(uint8_t * telegram, uint8_t length) { if (value == EMS_TX_SUCCESS) { EMS_Sys_Status.emsTxPkgs++; // got a success 01. Send a validate to check the value of the last write - emsuart_tx_poll(); // send a poll to free the EMS bus + ems_tx_pollAck(); // send a poll to free the EMS bus _createValidate(); // create a validate Tx request (if needed) } else if (value == EMS_TX_ERROR) { // last write failed (04), delete it from queue and dont bother to retry if (EMS_Sys_Status.emsLogging == EMS_SYS_LOGGING_VERBOSE) { myDebug_P(PSTR("** Write command failed from host")); } - emsuart_tx_poll(); // send a poll to free the EMS bus + ems_tx_pollAck(); // send a poll to free the EMS bus _removeTxQueue(); // remove from queue } } @@ -792,7 +879,7 @@ void ems_parseTelegram(uint8_t * telegram, uint8_t length) { // ignore anything that doesn't resemble a proper telegram package // minimal is 5 bytes, excluding CRC at the end if (length <= 4) { - //_debugPrintTelegram("Noisy data:", &EMS_RxTelegram COLOR_RED); + _debugPrintTelegram("Noisy data:", &EMS_RxTelegram, COLOR_RED); return; } @@ -1035,7 +1122,7 @@ void _processType(_EMS_RxTelegram * EMS_RxTelegram) { // if its an echo of ourselves from the master UBA, ignore. This should never happen mind you if (EMS_RxTelegram->src == EMS_ID_ME) { - // _debugPrintTelegram("echo:", EMS_RxTelegram, COLOR_WHITE); + _debugPrintTelegram("echo:", EMS_RxTelegram, COLOR_WHITE); return; } @@ -1143,10 +1230,9 @@ void _processType(_EMS_RxTelegram * EMS_RxTelegram) { } } - emsuart_tx_poll(); // send Acknowledgement back to free the EMS bus since we have the telegram + ems_tx_pollAck(); // send Acknowledgement back to free the EMS bus since we have the telegram } - /** * Check if hot tap water or heating is active * using a quick hack for checking the heating. Selected Flow Temp >= 70 @@ -1684,7 +1770,8 @@ void _process_Version(_EMS_RxTelegram * EMS_RxTelegram) { // check to see if its a Junkers Heatronic3, which has a different poll'ing logic if (EMS_Boiler.product_id == EMS_PRODUCTID_HEATRONICS) { - EMS_Sys_Status.emsReverse = true; + EMS_Sys_Status.emsIDMask = 0x80; + EMS_Sys_Status.emsPollAck[0] = EMS_ID_ME ^ EMS_Sys_Status.emsIDMask; } myESP.fs_saveConfig(); // save config to SPIFFS diff --git a/src/ems.h b/src/ems.h index 800577200..d06ba7f19 100644 --- a/src/ems.h +++ b/src/ems.h @@ -29,39 +29,39 @@ #define GPIO_H(mask) (GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, (mask))) #define GPIO_L(mask) (GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, (mask))) -#define RX_PULSE(pulse) \ - do { \ - GPIO_H(RX_MARK_MASK); \ - delayMicroseconds(pulse); \ - GPIO_L(RX_MARK_MASK); \ +#define RX_PULSE(pulse) \ + do { \ + GPIO_H(RX_MARK_MASK); \ + delayMicroseconds(pulse); \ + GPIO_L(RX_MARK_MASK); \ } while (0) -#define TX_PULSE(pulse) \ - do { \ - GPIO_H(TX_MARK_MASK); \ - delayMicroseconds(pulse); \ - GPIO_L(TX_MARK_MASK); \ +#define TX_PULSE(pulse) \ + do { \ + GPIO_H(TX_MARK_MASK); \ + delayMicroseconds(pulse); \ + GPIO_L(TX_MARK_MASK); \ } while (0) -#define LA_PULSE(pulse) \ - do { \ - GPIO_H(MARKERS_MASK); \ - delayMicroseconds(pulse); \ - GPIO_L(MARKERS_MASK); \ +#define LA_PULSE(pulse) \ + do { \ + GPIO_H(MARKERS_MASK); \ + delayMicroseconds(pulse); \ + GPIO_L(MARKERS_MASK); \ } while (0) -#define INIT_MARKERS(void) \ - do { \ - pinMode(RX_MARK_PIN, OUTPUT); \ - pinMode(TX_MARK_PIN, OUTPUT); \ - GPIO_L(MARKERS_MASK); \ +#define INIT_MARKERS(void) \ + do { \ + pinMode(RX_MARK_PIN, OUTPUT); \ + pinMode(TX_MARK_PIN, OUTPUT); \ + GPIO_L(MARKERS_MASK); \ } while (0) #else -#define RX_PULSE(pulse) \ +#define RX_PULSE(pulse) \ {} -#define TX_PULSE(pulse) \ +#define TX_PULSE(pulse) \ {} -#define LA_PULSE(pulse) \ +#define LA_PULSE(pulse) \ {} -#define INIT_MARKERS(void) \ +#define INIT_MARKERS(void) \ {} #define RX_MARK_MASK #define TX_MARK_MASK @@ -124,7 +124,8 @@ typedef enum { EMS_TX_STATUS_IDLE, // ready EMS_TX_STATUS_WAIT, // waiting for response from last Tx EMS_TX_WTD_TIMEOUT, // watchdog timeout during send - EMS_TX_BRK_DETECT // incoming BRK during Tx + EMS_TX_BRK_DETECT, // incoming BRK during Tx + EMS_TX_REV_DETECT // waiting to detect reverse bit } _EMS_TX_STATUS; #define EMS_TX_SUCCESS 0x01 // EMS single byte after a Tx Write indicating a success @@ -145,7 +146,8 @@ typedef enum { EMS_SYS_LOGGING_BASIC, // only basic read/write messages EMS_SYS_LOGGING_THERMOSTAT, // only telegrams sent from thermostat EMS_SYS_LOGGING_SOLARMODULE, // only telegrams sent from thermostat - EMS_SYS_LOGGING_VERBOSE // everything + EMS_SYS_LOGGING_VERBOSE, // everything + EMS_SYS_LOGGING_JABBER // lots of debug output... } _EMS_SYS_LOGGING; // status/counters since last power on @@ -164,8 +166,9 @@ typedef struct { bool emsTxCapable; // able to send via Tx bool emsTxDisabled; // true to prevent all Tx uint8_t txRetryCount; // # times the last Tx was re-sent - bool emsReverse; // if true, poll logic is reversed uint8_t emsTxMode; // handles Tx logic + uint8_t emsIDMask; // Buderus: 0x00, Junkers: 0x80 + uint8_t emsPollAck[1]; // acknowledge buffer } _EMS_Sys_Status; // The Tx send package @@ -390,6 +393,7 @@ typedef struct { } _EMS_Type; // function definitions +extern void ems_dumpBuffer(const char *prefix, uint8_t *telegram, uint8_t length); extern void ems_parseTelegram(uint8_t * telegram, uint8_t len); void ems_init(); void ems_doReadCommand(uint16_t type, uint8_t dest, bool forceRefresh = false); diff --git a/src/emsuart.cpp b/src/emsuart.cpp index a701d25c3..a0bb11411 100644 --- a/src/emsuart.cpp +++ b/src/emsuart.cpp @@ -13,6 +13,7 @@ _EMSRxBuf * pEMSRxBuf; _EMSRxBuf * paEMSRxBuf[EMS_MAXBUFFERS]; uint8_t emsRxBufIdx = 0; +uint8_t phantomBreak= 0; os_event_t recvTaskQueue[EMSUART_recvTaskQueueLen]; // our Rx queue @@ -22,7 +23,7 @@ os_event_t recvTaskQueue[EMSUART_recvTaskQueueLen]; // our Rx queue // static void emsuart_rx_intr_handler(void * para) { static uint8_t length; - static uint8_t uart_buffer[EMS_MAXBUFFERSIZE]; + static uint8_t uart_buffer[EMS_MAXBUFFERSIZE + 2]; // is a new buffer? if so init the thing for a new telegram if (EMS_Sys_Status.emsRxStatus == EMS_RX_STATUS_IDLE) { @@ -33,7 +34,9 @@ static void emsuart_rx_intr_handler(void * para) { // fill IRQ buffer, by emptying Rx FIFO if (USIS(EMSUART_UART) & ((1 << UIFF) | (1 << UITO) | (1 << UIBD))) { while ((USS(EMSUART_UART) >> USRXC) & 0xFF) { - uart_buffer[length++] = USF(EMSUART_UART); + uint8_t rx = USF(EMSUART_UART); + if (length < EMS_MAXBUFFERSIZE) + uart_buffer[length++] = rx; } // clear Rx FIFO full and Rx FIFO timeout interrupts @@ -46,8 +49,9 @@ static void emsuart_rx_intr_handler(void * para) { ETS_UART_INTR_DISABLE(); // disable all interrupts and clear them 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 + pEMSRxBuf->length = (length > EMS_MAXBUFFERSIZE) ? EMS_MAXBUFFERSIZE : length; + os_memcpy((void *)pEMSRxBuf->buffer, (void *)&uart_buffer, pEMSRxBuf->length); // copy data into transfer buffer, including the BRK 0x00 at the end + length = 0; 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 @@ -67,18 +71,21 @@ static void ICACHE_FLASH_ATTR emsuart_recvTask(os_event_t * events) { 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 (phantomBreak) { + phantomBreak = 0; + length--; // remove phantom break from Rx buffer + } + 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)) { + } else if ((length > 4) && (length <= EMS_MAXBUFFERSIZE + 1)) { // 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 } /* @@ -122,10 +129,10 @@ void ICACHE_FLASH_ATTR emsuart_init() { // 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. + // change: we set UCFFT to 1 to get an immediate indicator about incoming traffic. // Otherwise, we're only noticed by UCTOT or RxBRK! USC1(EMSUART_UART) = 0; // reset config first - USC1(EMSUART_UART) = (0x01 << UCFFT) | (0x01 << UCTOT) | (1 << UCTOE); // enable interupts + USC1(EMSUART_UART) = (0x01 << UCFFT) | (0x01 << UCTOT) | (0 << UCTOE); // enable interupts // set interrupts for triggers USIC(EMSUART_UART) = 0xFFFF; // clear all interupts @@ -133,7 +140,8 @@ void ICACHE_FLASH_ATTR emsuart_init() { // enable rx break, fifo full and timeout. // but not frame error UIFR (because they are too frequent) or overflow UIOF because our buffer is only max 32 bytes - USIE(EMSUART_UART) = (1 << UIBD) | (1 << UIFF) | (1 << UITO); + // change: we don't care about Rx Timeout - it may lead to wrong readouts + USIE(EMSUART_UART) = (1 << UIBD) | (1 << UIFF) | (0 << UITO); // set up interrupt callbacks for Rx system_os_task(emsuart_recvTask, EMSUART_recvTaskPrio, recvTaskQueue, EMSUART_recvTaskQueueLen); @@ -199,6 +207,7 @@ void ICACHE_FLASH_ATTR emsuart_tx_brk() { */ _EMS_TX_STATUS ICACHE_FLASH_ATTR emsuart_tx_buffer(uint8_t * buf, uint8_t len) { _EMS_TX_STATUS result = EMS_TX_STATUS_OK; + ems_dumpBuffer("emsuart_tx_buffer: ", buf, len); // validate and transmit the EMS buffer, excluding the BRK if (len) { LA_PULSE(50); // temp code until we get mode 2 working without resets @@ -254,9 +263,9 @@ _EMS_TX_STATUS ICACHE_FLASH_ATTR emsuart_tx_buffer(uint8_t * buf, uint8_t len) { // shorter busy poll... #define EMSUART_BUSY_WAIT (EMSUART_BIT_TIME / 8) -#define EMS_TX_TO_COUNT ((20 + 10000 / EMSUART_BIT_TIME) * 8) +#define EMS_TX_TO_CHARS (2 + 20) +#define EMS_TX_TO_COUNT ( (EMS_TX_TO_CHARS) * 10 * 8) uint16_t wdc = EMS_TX_TO_COUNT; - ETS_UART_INTR_DISABLE(); // disable rx interrupt // clear Rx status register @@ -272,7 +281,6 @@ _EMS_TX_STATUS ICACHE_FLASH_ATTR emsuart_tx_buffer(uint8_t * buf, uint8_t len) { 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) { @@ -301,11 +309,13 @@ _EMS_TX_STATUS ICACHE_FLASH_ATTR emsuart_tx_buffer(uint8_t * buf, uint8_t len) { // wait until BRK detected... while (!(USIR(EMSUART_UART) & (1 << UIBD))) { - delayMicroseconds(EMSUART_BUSY_WAIT); + // delayMicroseconds(EMSUART_BUSY_WAIT); + delayMicroseconds(EMSUART_BIT_TIME); } USC0(EMSUART_UART) &= ~((1 << UCBRK) | (1 << UCLBE)); // disable loopback & clear USIC(EMSUART_UART) = (1 << UIBD); // clear BRK detect IRQ + phantomBreak = 1; } GPIO_L(TX_MARK_MASK); } @@ -317,13 +327,8 @@ _EMS_TX_STATUS 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 - */ + * *** moved to ems.cpp, renamed to ems_tx_pollAck void ICACHE_FLASH_ATTR emsuart_tx_poll() { - 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); + static uint8_t buf[1] = {EMS_ID_ME ^ EMS_Sys_Status.emsIDMask}; } + */ \ No newline at end of file diff --git a/src/emsuart.h b/src/emsuart.h index 0777dcfd5..3a4f9da7e 100644 --- a/src/emsuart.h +++ b/src/emsuart.h @@ -37,4 +37,3 @@ void ICACHE_FLASH_ATTR emsuart_init(); void ICACHE_FLASH_ATTR emsuart_stop(); void ICACHE_FLASH_ATTR emsuart_start(); _EMS_TX_STATUS ICACHE_FLASH_ATTR emsuart_tx_buffer(uint8_t * buf, uint8_t len); -void ICACHE_FLASH_ATTR emsuart_tx_poll();