diff --git a/src/emsesp.cpp b/src/emsesp.cpp index f79667c17..571c2388e 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -568,9 +568,9 @@ void EMSESP::incoming_telegram(uint8_t * data, const uint8_t length) { if (((first_value & 0x7F) == txservice_.ems_bus_id()) && (length > 1)) { // if we ask ourself at roomcontrol for version e.g. 0B 98 02 00 20 Roomctrl::check((data[1] ^ 0x80 ^ rxservice_.ems_mask()), data); -#ifdef EMSESP_DEBUG +//#ifdef EMSESP_DEBUG LOG_DEBUG(F("Echo: %s"), Helpers::data_to_hex(data, length).c_str()); -#endif +//#endif return; // it's an echo } @@ -725,8 +725,9 @@ void EMSESP::console_commands(Shell & shell, unsigned int context) { flash_string_vector{F_(set), F_(tx_mode)}, flash_string_vector{F_(n_mandatory)}, [](Shell & shell, const std::vector & arguments) { - uint8_t tx_mode = (arguments[0]).at(0) - '0'; - if ((tx_mode > 0) && (tx_mode <= 4)) { + // uint8_t tx_mode = (arguments[0]).at(0) - '0'; + uint8_t tx_mode = std::strtol(arguments[0].c_str(), nullptr, 10); + if ((tx_mode > 0) && (tx_mode <= 30)) { Settings settings; settings.ems_tx_mode(tx_mode); settings.commit(); diff --git a/src/telegram.cpp b/src/telegram.cpp index db58ca5bb..6ae4907a0 100644 --- a/src/telegram.cpp +++ b/src/telegram.cpp @@ -487,13 +487,13 @@ void TxService::send_telegram(const QueuedTxTelegram & tx_telegram) { } // send the telegram to the UART Tx - EMSUART_STATUS status = EMSuart::transmit(telegram_raw, length); + uint16_t status = EMSuart::transmit(telegram_raw, length); #ifdef EMSESP_DEBUG LOG_TRACE(F("Tx: %s"), Helpers::data_to_hex(telegram_raw, length).c_str()); #endif if (status != EMS_TX_STATUS_OK) { - LOG_ERROR(F("Failed to transmit Tx via UART. Error: %s"), status == EMS_TX_WTD_TIMEOUT ? F("Timeout") : F("BRK")); + LOG_ERROR(F("Failed to transmit Tx via UART.")); tx_waiting(false); // nothing send, tx not in wait state return; } @@ -515,10 +515,10 @@ void TxService::send_telegram(const uint8_t * data, const uint8_t length) { LOG_DEBUG(F("Sending Raw telegram: %s (length=%d)"), Helpers::data_to_hex(telegram_raw, length).c_str(), length); // send the telegram to the UART Tx - EMSUART_STATUS status = EMSuart::transmit(telegram_raw, length); + uint16_t status = EMSuart::transmit(telegram_raw, length); //LOG_TRACE(F("Tx: %s"), Helpers::data_to_hex(telegram_raw, length).c_str()); if (status != EMS_TX_STATUS_OK) { - LOG_ERROR(F("Failed to transmit Tx via UART. Error: %s"), status == EMS_TX_WTD_TIMEOUT ? F("Timeout") : F("BRK")); + LOG_ERROR(F("Failed to transmit Tx via UART")); } } diff --git a/src/uart/emsuart_esp32.cpp b/src/uart/emsuart_esp32.cpp index c2369217a..091363cec 100644 --- a/src/uart/emsuart_esp32.cpp +++ b/src/uart/emsuart_esp32.cpp @@ -30,8 +30,14 @@ namespace emsesp { static intr_handle_t uart_handle; static RingbufHandle_t buf_handle = NULL; -static bool drop_next_rx = true; -static uint8_t tx_mode_ = 0xFF; +static hw_timer_t * timer = NULL; +bool drop_next_rx = true; +uint8_t tx_mode_ = 0xFF; +//portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED; +uint8_t emsTxBuf[EMS_MAXBUFFERSIZE]; +uint8_t emsTxBufIdx; +uint8_t emsTxBufLen; +uint32_t emsTxWait; /* * Task to handle the incoming data @@ -73,11 +79,39 @@ void IRAM_ATTR EMSuart::emsuart_rx_intr_handler(void * para) { drop_next_rx = false; } } + + +void IRAM_ATTR EMSuart::emsuart_tx_timer_intr_handler() { + if (emsTxBufIdx > 32) { + return; + } + emsTxBufIdx++; + if (emsTxBufIdx < emsTxBufLen) { + EMS_UART.fifo.rw_byte = emsTxBuf[emsTxBufIdx]; + timerAlarmWrite(timer, emsTxWait, false); + timerAlarmEnable(timer); + } else if (emsTxBufIdx == emsTxBufLen) { + EMS_UART.conf0.txd_brk = 1; // after send + } +} + /* * init UART driver */ void EMSuart::start(uint8_t tx_mode) { + if (tx_mode == EMS_TXMODE_DEFAULT) { + emsTxWait = EMSUART_BIT_TIME * 11; + } else if (tx_mode == EMS_TXMODE_EMSPLUS) { + emsTxWait = EMSUART_BIT_TIME * 20; + } else if (tx_mode == EMS_TXMODE_HT3) { + emsTxWait = EMSUART_BIT_TIME * 17; + } else if(tx_mode > 10 ) { + emsTxWait = EMSUART_BIT_TIME * tx_mode; + } else if(tx_mode > 5 ) { + emsTxWait = EMSUART_BIT_TIME * tx_mode * 2; + } if (tx_mode_ != 0xFF) { // uart already initialized + tx_mode_ = tx_mode; restart(); return; } @@ -101,6 +135,11 @@ void EMSuart::start(uint8_t tx_mode) { ESP_ERROR_CHECK(uart_isr_register(EMSUART_UART, emsuart_rx_intr_handler, NULL, ESP_INTR_FLAG_IRAM, &uart_handle)); xTaskCreate(emsuart_recvTask, "emsuart_recvTask", 2048, NULL, configMAX_PRIORITIES - 1, NULL); EMS_UART.int_ena.brk_det = 1; // activate only break + + emsTxBufIdx = 0; + emsTxBufLen = 0; + timer = timerBegin(1, 80, true); // timer prescale to 1 µs, countup + timerAttachInterrupt(timer, &emsuart_tx_timer_intr_handler, true); // Timer with edge interrupt } /* @@ -108,6 +147,7 @@ void EMSuart::start(uint8_t tx_mode) { */ void EMSuart::stop() { EMS_UART.int_ena.val = 0; // disable all intr. + // timerAlarmDisable(timer); }; /* @@ -119,14 +159,24 @@ void EMSuart::restart() { drop_next_rx = true; // and drop first frame } EMS_UART.int_ena.brk_det = 1; // activate only break + emsTxBufIdx = 0; + emsTxBufLen = 0; }; /* * Sends a 1-byte poll, ending with a */ void EMSuart::send_poll(uint8_t data) { - EMS_UART.fifo.rw_byte = data; - EMS_UART.conf0.txd_brk = 1; // after send + if (tx_mode_ == EMS_TXMODE_NEW || tx_mode_ == 5) { + EMS_UART.fifo.rw_byte = data; + EMS_UART.conf0.txd_brk = 1; // after send + } else { + EMS_UART.fifo.rw_byte = data; + emsTxBufIdx = 0; + emsTxBufLen = 1; + timerAlarmWrite(timer, emsTxWait, false); + timerAlarmEnable(timer); + } } /* @@ -134,12 +184,24 @@ void EMSuart::send_poll(uint8_t data) { * buf contains the CRC and len is #bytes including the CRC * returns code, 1=success */ -EMSUART_STATUS EMSuart::transmit(uint8_t * buf, uint8_t len) { - if (len > 0) { +uint16_t EMSuart::transmit(uint8_t * buf, uint8_t len) { + if (len == 0 || len > 32) { + return EMS_TX_STATUS_ERROR; + } + if (tx_mode_ == EMS_TXMODE_NEW || tx_mode_ == 5) { for (uint8_t i = 0; i < len; i++) { EMS_UART.fifo.rw_byte = buf[i]; } EMS_UART.conf0.txd_brk = 1; // after send + } else { + for (uint8_t i = 0; i < len; i++) { + emsTxBuf[i] = buf[i]; + } + EMS_UART.fifo.rw_byte = buf[0]; + emsTxBufIdx = 0; + emsTxBufLen = len; + timerAlarmWrite(timer, emsTxWait, false); + timerAlarmEnable(timer); } return EMS_TX_STATUS_OK; } diff --git a/src/uart/emsuart_esp32.h b/src/uart/emsuart_esp32.h index 7a1871e0f..4e958469e 100644 --- a/src/uart/emsuart_esp32.h +++ b/src/uart/emsuart_esp32.h @@ -38,6 +38,13 @@ #define EMSUART_UART UART_NUM_2 // on the ESP32 we're using UART2 #define EMS_UART UART2 // for intr setting #define EMSUART_BAUD 9600 // uart baud rate for the EMS circuit +#define EMSUART_BIT_TIME 104 // bit time @9600 baud + +#define EMS_TXMODE_DEFAULT 1 +#define EMS_TXMODE_EMSPLUS 2 +#define EMS_TXMODE_HT3 3 +#define EMS_TXMODE_NEW 4 // for michael's testing + // customize the GPIO pins for RX and TX here #ifdef WEMOS_D1_32 @@ -50,11 +57,8 @@ namespace emsesp { -typedef enum { - EMS_TX_STATUS_OK = 1, - EMS_TX_WTD_TIMEOUT, // watchdog timeout during send - EMS_TX_BRK_DETECT, // incoming BRK during Tx -} EMSUART_STATUS; +#define EMS_TX_STATUS_OK 1 +#define EMS_TX_STATUS_ERROR 0 class EMSuart { public: @@ -65,11 +69,13 @@ class EMSuart { static void send_poll(uint8_t data); static void stop(); static void restart(); - static EMSUART_STATUS transmit(uint8_t * buf, uint8_t len); + static uint16_t transmit(uint8_t * buf, uint8_t len); private: static void emsuart_recvTask(void * para); static void IRAM_ATTR emsuart_rx_intr_handler(void * para); + static void IRAM_ATTR emsuart_tx_timer_intr_handler(); + }; } // namespace emsesp diff --git a/src/uart/emsuart_esp8266.cpp b/src/uart/emsuart_esp8266.cpp index f01030a36..d77a77de3 100644 --- a/src/uart/emsuart_esp8266.cpp +++ b/src/uart/emsuart_esp8266.cpp @@ -50,13 +50,11 @@ void ICACHE_RAM_ATTR EMSuart::emsuart_rx_intr_handler(void * para) { static uint8_t uart_buffer[EMS_MAXBUFFERSIZE + 2]; if (USIS(EMSUART_UART) & ((1 << UIBD))) { // BREAK detection = End of EMS data block - USC0(EMSUART_UART) &= ~(1 << UCBRK); // reset tx-brk + USC0(EMSUART_UART) &= ~(1 << UCBRK); // reset tx-brk + // just for testing if break isn't finished yet // while((USS(EMSUART_UART) >> USRXD) == 0); // wait for idle state of pin - // if((USS(EMSUART_UART) >> USRXD) == 0) { // if rx is not idle wait one bittime - // delayMicroseconds(EMSUART_BIT_TIME); - // } - USIC(EMSUART_UART) = (1 << UIBD); // INT clear the BREAK detect interrupt - length = 0; + USIC(EMSUART_UART) = (1 << UIBD); // INT clear the BREAK detect interrupt + length = 0; while ((USS(EMSUART_UART) >> USRXC) & 0x0FF) { // read fifo into buffer uint8_t rx = USF(EMSUART_UART); if (length < EMS_MAXBUFFERSIZE) { @@ -116,22 +114,40 @@ void ICACHE_FLASH_ATTR EMSuart::emsuart_flush_fifos() { // ISR to Fire when Timer is triggered void ICACHE_RAM_ATTR EMSuart::emsuart_tx_timer_intr_handler() { + if (emsTxBufIdx > 32) { + return; + } emsTxBufIdx++; if (emsTxBufIdx < emsTxBufLen) { USF(EMSUART_UART) = emsTxBuf[emsTxBufIdx]; - timer1_write(emsTxWait); - } else if (emsTxBufIdx == emsTxBufLen) { + timer1_write(emsTxWait); + } else if (emsTxBufIdx == emsTxBufLen) { USC0(EMSUART_UART) |= (1 << UCBRK); // set -// timer1_write(emsTxWait); -// } else { -// USC0(EMSUART_UART) &= ~(1 << UCBRK); // clear + if (tx_mode_ > 5 || tx_mode_ < 11) { + timer1_write(5 * EMSUART_TX_BIT_TIME * 11); + USIE(EMSUART_UART) &= ~(1 << UIBD); // disable break interrupt + } + } else if (USC0(EMSUART_UART) & (1 << UCBRK)) { + USC0(EMSUART_UART) &= ~(1 << UCBRK); // clear + USIE(EMSUART_UART) |= (1 << UIBD); // enable break interrupt } } /* * init UART0 driver */ void ICACHE_FLASH_ATTR EMSuart::start(uint8_t tx_mode) { - if (tx_mode_ != 0xFF) { // it's a restart no need to configure rx + if (tx_mode > 10) { + emsTxWait = 5 * EMSUART_TX_BIT_TIME * tx_mode; // bittimes for tx_mode + } else if (tx_mode > 5) { + emsTxWait = 10 * EMSUART_TX_BIT_TIME * tx_mode; // bittimes for tx_mode + } + if (tx_mode == 5) { + USC0(EMSUART_UART) = 0x2C; // 8N1,5 + } else { + USC0(EMSUART_UART) = EMSUART_CONFIG; // 8N1 + } + + if (tx_mode_ != 0xFF) { // it's a restart no need to configure uart tx_mode_ = tx_mode; restart(); return; @@ -140,6 +156,7 @@ void ICACHE_FLASH_ATTR EMSuart::start(uint8_t tx_mode) { // allocate and preset EMS Receive buffers for (int i = 0; i < EMS_MAXBUFFERS; i++) { EMSRxBuf_t * p = (EMSRxBuf_t *)malloc(sizeof(EMSRxBuf_t)); + p->length = 0; paEMSRxBuf[i] = p; } pEMSRxBuf = paEMSRxBuf[0]; // reset EMS Rx Buffer @@ -155,7 +172,6 @@ void ICACHE_FLASH_ATTR EMSuart::start(uint8_t tx_mode) { // set 9600, 8 bits, no parity check, 1 stop bit USD(EMSUART_UART) = (UART_CLK_FREQ / EMSUART_BAUD); - USC0(EMSUART_UART) = EMSUART_CONFIG; // 8N1 emsuart_flush_fifos(); @@ -168,9 +184,9 @@ void ICACHE_FLASH_ATTR EMSuart::start(uint8_t tx_mode) { // change: we set UCFFT to 1 to get an immediate indicator about incoming traffic. // Otherwise, we're only noticed by UCTOT or RxBRK! // change: don't care, we do not use these interrupts - // USC1(EMSUART_UART) = 0; // reset config first + USC1(EMSUART_UART) = 0; // reset config first // USC1(EMSUART_UART) = (0x7F << UCFFT) | (0x04 << UCTOT) | (1 << UCTOE); // enable interupts - + // set interrupts for triggers USIC(EMSUART_UART) = 0xFFFF; // clear all interupts USIE(EMSUART_UART) = 0; // disable all interrupts @@ -194,11 +210,10 @@ void ICACHE_FLASH_ATTR EMSuart::start(uint8_t tx_mode) { ETS_UART_INTR_ENABLE(); drop_next_rx = true; // LOG_INFO(F("UART service for Rx/Tx started")); - + // for sending with large delay in EMS+ mode we use a timer interrupt - timer1_attachInterrupt(emsuart_tx_timer_intr_handler); // Add ISR Function - timer1_enable(TIM_DIV16, TIM_EDGE, TIM_SINGLE); // 5 MHz timer - emsTxWait = 5 * EMSUART_BIT_TIME * 20; // 20 bittimes for tx_mode 2 + timer1_attachInterrupt(emsuart_tx_timer_intr_handler); // Add ISR Function + timer1_enable(TIM_DIV16, TIM_EDGE, TIM_SINGLE); // 5 MHz timer } /* @@ -229,28 +244,28 @@ void ICACHE_FLASH_ATTR EMSuart::restart() { * Which is a 11-bit set of zero's (11 cycles) */ void ICACHE_FLASH_ATTR EMSuart::tx_brk() { - uint32_t tmp; // must make sure Tx FIFO is empty while (((USS(EMSUART_UART) >> USTXC) & 0xFF)) ; - - tmp = ((1 << UCRXRST) | (1 << UCTXRST)); // bit mask - USC0(EMSUART_UART) |= (tmp); // set bits - USC0(EMSUART_UART) &= ~(tmp); // clear bits + // do not clear buffers to get a echo back + // tmp = ((1 << UCRXRST) | (1 << UCTXRST)); // bit mask + // USC0(EMSUART_UART) |= (tmp); // set bits + // USC0(EMSUART_UART) &= ~(tmp); // clear bits // 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); - USC0(EMSUART_UART) |= (tmp); // set bit + ETS_UART_INTR_DISABLE(); + USC0(EMSUART_UART) |= (1 << UCBRK); // set bit - if (tx_mode_ == EMS_TXMODE_EMSPLUS) { // EMS+ mode - delayMicroseconds(EMSUART_TX_BRK_WAIT); - } else if (tx_mode_ == EMS_TXMODE_HT3) { // junkers mode - delayMicroseconds(EMSUART_TX_WAIT_BRK - EMSUART_TX_LAG); // 1144 (11 Bits) + if (tx_mode_ == EMS_TXMODE_EMSPLUS) { // EMS+ mode + delayMicroseconds(EMSUART_TX_BRK_WAIT); // 2070 + } else if (tx_mode_ == EMS_TXMODE_HT3) { // junkers mode + delayMicroseconds(EMSUART_TX_BRK_WAIT_HT3); // 1144 } - USC0(EMSUART_UART) &= ~(tmp); // clear bit + USC0(EMSUART_UART) &= ~(1 << UCBRK); // clear BRK bit + ETS_UART_INTR_ENABLE(); } /* @@ -258,16 +273,18 @@ void ICACHE_FLASH_ATTR EMSuart::tx_brk() { * It's a bit dirty. there is no special wait logic per tx_mode type, fifo flushes or error checking */ void EMSuart::send_poll(uint8_t data) { - if (tx_mode_ == EMS_TXMODE_NEW) { - USC0(EMSUART_UART) &= ~(1 << UCBRK); // reset tx-brk - USF(EMSUART_UART) = data; - USC0(EMSUART_UART) |= (1 << UCBRK); // send at the end - } else if (tx_mode_ == EMS_TXMODE_EMSPLUS) { + // reset tx-brk, just in case it is accidently set + USC0(EMSUART_UART) &= ~(1 << UCBRK); + if (tx_mode_ > 5) { // timer controlled modes USF(EMSUART_UART) = data; emsTxBufIdx = 0; emsTxBufLen = 1; timer1_write(emsTxWait); - } else { + } else if (tx_mode_ >= EMS_TXMODE_NEW) { // hardware controlled modes + USF(EMSUART_UART) = data; + USC0(EMSUART_UART) |= (1 << UCBRK); // send at the end + } else { // software controlled modes + // EMS1.0, EMS+ and HT3 USF(EMSUART_UART) = data; delayMicroseconds(EMSUART_TX_BRK_WAIT); tx_brk(); // send @@ -279,20 +296,33 @@ void EMSuart::send_poll(uint8_t data) { * buf contains the CRC and len is #bytes including the CRC * returns code, 0=success, 1=brk error, 2=watchdog timeout */ -EMSUART_STATUS ICACHE_FLASH_ATTR EMSuart::transmit(uint8_t * buf, uint8_t len) { - if (len == 0) { - return EMS_TX_STATUS_OK; // nothing to send +uint16_t ICACHE_FLASH_ATTR EMSuart::transmit(uint8_t * buf, uint8_t len) { + if (len == 0 || len > 32) { + return EMS_TX_STATUS_ERR; // nothing or to much to send } #ifdef EMSESP_DEBUG - LOG_INFO(F("(debug) UART Response time: %d ms"), uuid::get_uptime() - emsRxTime); + // LOG_INFO(F("[DEBUG] UART Response time: %d ms"), uuid::get_uptime() - emsRxTime); #endif // if ((uuid::get_uptime() - emsRxTime) > EMS_RX_TO_TX_TIMEOUT)) { // send allowed within 20 ms - // return EMS_TX_WTD_TIMEOUT; + // return EMS_TX_STATUS_ERR; // } + // reset tx-brk, just in case it is accidently set + USC0(EMSUART_UART) &= ~(1 << UCBRK); + + // timer controlled modes with extra delay + if (tx_mode_ > 5) { + for (uint8_t i = 0; i < len; i++) { + emsTxBuf[i] = buf[i]; + } + emsTxBufIdx = 0; + emsTxBufLen = len; + USF(EMSUART_UART) = buf[0]; + timer1_write(emsTxWait); + return EMS_TX_STATUS_OK; + } // new code from Michael. See https://github.com/proddy/EMS-ESP/issues/380 - if (tx_mode_ == EMS_TXMODE_NEW) { - USC0(EMSUART_UART) &= ~(1 << UCBRK); // reset tx-brk + if (tx_mode_ >= EMS_TXMODE_NEW) { for (uint8_t i = 0; i < len; i++) { USF(EMSUART_UART) = buf[i]; } @@ -303,15 +333,10 @@ EMSUART_STATUS ICACHE_FLASH_ATTR EMSuart::transmit(uint8_t * buf, uint8_t len) { // EMS+ https://github.com/proddy/EMS-ESP/issues/23# if (tx_mode_ == EMS_TXMODE_EMSPLUS) { // With extra tx delay for EMS+ for (uint8_t i = 0; i < len; i++) { - emsTxBuf[i] = buf[i]; -// USF(EMSUART_UART) = buf[i]; -// delayMicroseconds(EMSUART_TX_BRK_WAIT); // 2070 + USF(EMSUART_UART) = buf[i]; + delayMicroseconds(EMSUART_TX_BRK_WAIT); // 2070 } - emsTxBufIdx = 0; - emsTxBufLen = len; - USF(EMSUART_UART) = buf[0]; - timer1_write(emsTxWait); -// tx_brk(); // send + tx_brk(); // send return EMS_TX_STATUS_OK; } @@ -325,14 +350,14 @@ EMSUART_STATUS ICACHE_FLASH_ATTR EMSuart::transmit(uint8_t * buf, uint8_t len) { ; // wait until bits are sent on wire - delayMicroseconds(EMSUART_TX_WAIT_BYTE - EMSUART_TX_LAG + EMSUART_TX_WAIT_GAP); // 1760 + delayMicroseconds(EMSUART_TX_BRK_WAIT_HT3); } tx_brk(); // send return EMS_TX_STATUS_OK; } /* - * Logic for tx_mode of 0 (EMS_TXMODE_DEFAULT) + * Logic for tx_mode of 1 * based on code from https://github.com/proddy/EMS-ESP/issues/103 by @susisstrolch * * Logic: @@ -347,7 +372,7 @@ EMSUART_STATUS ICACHE_FLASH_ATTR EMSuart::transmit(uint8_t * buf, uint8_t len) { * 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 + * Tx attempt. The timeout should be 20x EMSUART_TX_BIT_TIME plus * some smart guess for processing time on targeted EMS device. * We set Status to EMS_TX_WTD_TIMEOUT and return * @@ -365,23 +390,11 @@ EMSUART_STATUS ICACHE_FLASH_ATTR EMSuart::transmit(uint8_t * buf, uint8_t len) { // send the bytes along the serial line for (uint8_t i = 0; i < len; i++) { - uint16_t wdc = EMS_TX_TO_COUNT; // 1760 volatile uint8_t _usrxc = (USS(EMSUART_UART) >> USRXC) & 0xFF; USF(EMSUART_UART) = buf[i]; // send each Tx byte // wait for echo from the busmaster while (((USS(EMSUART_UART) >> USRXC) & 0xFF) == _usrxc) { - delayMicroseconds(EMSUART_BUSY_WAIT); // burn CPU cycles... - if (--wdc == 0) { - // interrupts(); - ETS_UART_INTR_ENABLE(); - return EMS_TX_WTD_TIMEOUT; - } - if (USIR(EMSUART_UART) & (1 << UIBD)) { - USIC(EMSUART_UART) = (1 << UIBD); // clear BRK detect IRQ - // interrupts(); - ETS_UART_INTR_ENABLE(); - return EMS_TX_BRK_DETECT; - } + delayMicroseconds(EMSUART_TX_BUSY_WAIT); // burn CPU cycles... } } @@ -392,16 +405,18 @@ EMSUART_STATUS ICACHE_FLASH_ATTR EMSuart::transmit(uint8_t * buf, uint8_t len) { // neither bus collision nor timeout - send terminating BRK signal if (!(USIS(EMSUART_UART) & (1 << UIBD))) { // no bus collision - send terminating BRK signal - USC0(EMSUART_UART) |= (1 << UCLBE) | (1 << UCBRK); // enable loopback & set + // USC0(EMSUART_UART) |= (1 << UCLBE) | (1 << UCBRK); // enable loopback & set + USC0(EMSUART_UART) |= (1 << UCBRK); // set // wait until BRK detected... while (!(USIR(EMSUART_UART) & (1 << UIBD))) { - delayMicroseconds(EMSUART_BIT_TIME); + delayMicroseconds(EMSUART_TX_BIT_TIME); } - USC0(EMSUART_UART) &= ~((1 << UCBRK) | (1 << UCLBE)); // disable loopback & clear - USIC(EMSUART_UART) = (1 << UIBD); // clear BRK detect IRQ - phantomBreak = 1; + USC0(EMSUART_UART) &= ~(1 << UCBRK); // clear + // USC0(EMSUART_UART) &= ~((1 << UCBRK) | (1 << UCLBE)); // disable loopback & clear + // USIC(EMSUART_UART) = (1 << UIBD); // clear BRK detect IRQ + // phantomBreak = 1; } // interrupts(); diff --git a/src/uart/emsuart_esp8266.h b/src/uart/emsuart_esp8266.h index 5db541b21..26ca2478c 100644 --- a/src/uart/emsuart_esp8266.h +++ b/src/uart/emsuart_esp8266.h @@ -26,7 +26,7 @@ #include #define EMSUART_UART 0 // UART 0 -#define EMSUART_CONFIG 0x1C // 8N1 (8 bits, no stop bits, 1 parity) +#define EMSUART_CONFIG 0x1C // 8N1 (8 bits, no parity, 1 stop bit) #define EMSUART_BAUD 9600 // uart baud rate for the EMS circuit #define EMS_MAXBUFFERS 3 // buffers for circular filling to avoid collisions @@ -41,34 +41,30 @@ #define EMS_TXMODE_NEW 4 // for michael's testing // LEGACY -#define EMSUART_BIT_TIME 104 // bit time @9600 baud +#define EMSUART_TX_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_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 -#define EMSUART_BUSY_WAIT (EMSUART_BIT_TIME / 8) -#define EMS_TX_TO_CHARS (2 + 20) -#define EMS_TX_TO_COUNT ((EMS_TX_TO_CHARS)*8) + +// EMS 1.0 +#define EMSUART_TX_BUSY_WAIT (EMSUART_TX_BIT_TIME / 8) // 13 + +// HT3/Junkers - Time to send one Byte (8 Bits, 1 Start Bit, 1 Stop Bit). The -8 is for lag compensation. +#define EMSUART_TX_BRK_WAIT_HT3 (EMSUART_TX_BIT_TIME * 11) - 8 // 1136 namespace emsesp { -typedef enum { - EMS_TX_STATUS_OK = 1, - EMS_TX_WTD_TIMEOUT, // watchdog timeout during send - EMS_TX_BRK_DETECT, // incoming BRK during Tx -} EMSUART_STATUS; +#define EMS_TX_STATUS_ERR 0 +#define EMS_TX_STATUS_OK 1 class EMSuart { public: EMSuart() = default; ~EMSuart() = default; - static void ICACHE_FLASH_ATTR start(uint8_t tx_mode); - static void ICACHE_FLASH_ATTR stop(); - static void ICACHE_FLASH_ATTR restart(); - static void ICACHE_FLASH_ATTR send_poll(uint8_t data); - static EMSUART_STATUS ICACHE_FLASH_ATTR transmit(uint8_t * buf, uint8_t len); + static void ICACHE_FLASH_ATTR start(uint8_t tx_mode); + static void ICACHE_FLASH_ATTR stop(); + static void ICACHE_FLASH_ATTR restart(); + static void ICACHE_FLASH_ATTR send_poll(uint8_t data); + static uint16_t ICACHE_FLASH_ATTR transmit(uint8_t * buf, uint8_t len); typedef struct { uint8_t length; @@ -83,7 +79,6 @@ class EMSuart { static void ICACHE_FLASH_ATTR emsuart_flush_fifos(); static void ICACHE_FLASH_ATTR tx_brk(); static void ICACHE_RAM_ATTR emsuart_tx_timer_intr_handler(); - }; } // namespace emsesp