diff --git a/src/emsesp.cpp b/src/emsesp.cpp index f86b4dddc..d7a278e55 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -577,7 +577,6 @@ 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 // get_uptime is only updated once per loop, does not give the right time LOG_DEBUG(F("[DEBUG] Echo after %d ms: %s"), ::millis() - tx_time_, Helpers::data_to_hex(data, length).c_str()); diff --git a/src/helpers.cpp b/src/helpers.cpp index 4b46acb89..ed495cc2f 100644 --- a/src/helpers.cpp +++ b/src/helpers.cpp @@ -359,11 +359,11 @@ bool Helpers::hasValue(const int8_t v) { } bool Helpers::hasValue(const int16_t v) { - return (v != EMS_VALUE_SHORT_NOTSET); + return (v != EMS_VALUE_SHORT_NOTSET && v != EMS_VALUE_USHORT_NOTSET && v != EMS_VALUE_SHORT_INVALID && v != EMS_VALUE_USHORT_INVALID); } bool Helpers::hasValue(const uint16_t v) { - return (v != EMS_VALUE_USHORT_NOTSET); + return (v != EMS_VALUE_SHORT_NOTSET && v != EMS_VALUE_USHORT_NOTSET && v != EMS_VALUE_SHORT_INVALID && v != EMS_VALUE_USHORT_INVALID); } bool Helpers::hasValue(const uint32_t v) { diff --git a/src/telegram.cpp b/src/telegram.cpp index 8e9273585..0b305903d 100644 --- a/src/telegram.cpp +++ b/src/telegram.cpp @@ -270,7 +270,10 @@ void RxService::add(uint8_t * data, uint8_t length) { uint8_t message_length; // length of the message block, excluding CRC // work out depending on the type, where the data message block starts and the message length - if (data[2] < 0xF0) { + // EMS 1 has type_id always in data[2], if it gets a ems+ inquiery it will reply with FF but short length + // i.e. sending 0B A1 FF 00 01 D8 20 CRC to a MM10 Mixer (ems1.0), the reply is 21 0B FF 00 CRC + // see: https://github.com/proddy/EMS-ESP/issues/380#issuecomment-633663007 + if (data[2] < 0xF0 || length < 6) { // EMS 1.0 type_id = data[2]; message_data = data + 4; diff --git a/src/uart/emsuart_esp32.cpp b/src/uart/emsuart_esp32.cpp index 668ba2504..b083dbfdd 100644 --- a/src/uart/emsuart_esp32.cpp +++ b/src/uart/emsuart_esp32.cpp @@ -61,13 +61,25 @@ void IRAM_ATTR EMSuart::emsuart_rx_intr_handler(void * para) { static uint8_t rxbuf[EMS_MAXBUFFERSIZE]; static uint8_t length; + if (EMS_UART.int_st.rxfifo_full) { + EMS_UART.int_clr.rxfifo_full = 1; + emsTxBufIdx++; + if (emsTxBufIdx < emsTxBufLen) { + EMS_UART.conf1.rxfifo_full_thrhd = emsTxBufIdx + 1; + EMS_UART.fifo.rw_byte = emsTxBuf[emsTxBufIdx]; + } else if (emsTxBufIdx == emsTxBufLen) { + EMS_UART.conf0.txd_brk = 1; // after send + EMS_UART.int_ena.rxfifo_full = 0; + EMS_UART.conf1.rxfifo_full_thrhd = 0x7F; + } + } if (EMS_UART.int_st.brk_det) { EMS_UART.int_clr.brk_det = 1; // clear flag if (emsTxBufIdx < emsTxBufLen) { // timer tx_mode is interrupted by emsTxBufIdx = emsTxBufLen; // stop timer mode drop_next_rx = true; // we have trash in buffer } - length = 0; + length = 0; while (EMS_UART.status.rxfifo_cnt) { uint8_t rx = EMS_UART.fifo.rw_byte; // read all bytes from fifo if (length < EMS_MAXBUFFERSIZE) { @@ -172,6 +184,12 @@ void EMSuart::send_poll(uint8_t data) { emsTxBufLen = 1; timerAlarmWrite(timer, emsTxWait, false); timerAlarmEnable(timer); + } else if (tx_mode_ == 5) { + EMS_UART.fifo.rw_byte = data; + emsTxBufIdx = 0; + emsTxBufLen = 1; + EMS_UART.conf1.rxfifo_full_thrhd = 1; + EMS_UART.int_ena.rxfifo_full = 1; } else if (tx_mode_ == EMS_TXMODE_NEW) { EMS_UART.fifo.rw_byte = data; EMS_UART.conf0.txd_brk = 1; // after send @@ -190,7 +208,7 @@ void EMSuart::send_poll(uint8_t data) { } else { volatile uint8_t _usrxc = EMS_UART.status.rxfifo_cnt; EMS_UART.fifo.rw_byte = data; - uint8_t timeoutcnt = EMSUART_TX_TIMEOUT; + uint16_t timeoutcnt = EMSUART_TX_TIMEOUT; while ((EMS_UART.status.rxfifo_cnt == _usrxc) && (--timeoutcnt > 0)) { delayMicroseconds(EMSUART_TX_BUSY_WAIT); // burn CPU cycles... } @@ -219,6 +237,17 @@ uint16_t EMSuart::transmit(uint8_t * buf, uint8_t len) { timerAlarmEnable(timer); return EMS_TX_STATUS_OK; } + if (tx_mode_ == 5) { + for (uint8_t i = 0; i < len; i++) { + emsTxBuf[i] = buf[i]; + } + EMS_UART.fifo.rw_byte = buf[0]; + emsTxBufIdx = 0; + emsTxBufLen = len; + EMS_UART.conf1.rxfifo_full_thrhd = 1; + EMS_UART.int_ena.rxfifo_full = 1; + return EMS_TX_STATUS_OK; + } if (tx_mode_ == EMS_TXMODE_NEW) { // hardware controlled modes for (uint8_t i = 0; i < len; i++) { EMS_UART.fifo.rw_byte = buf[i]; @@ -253,7 +282,7 @@ uint16_t EMSuart::transmit(uint8_t * buf, uint8_t len) { for (uint8_t i = 0; i < len; i++) { volatile uint8_t _usrxc = EMS_UART.status.rxfifo_cnt; EMS_UART.fifo.rw_byte = buf[i]; // send each Tx byte - uint8_t timeoutcnt = EMSUART_TX_TIMEOUT; + uint16_t timeoutcnt = EMSUART_TX_TIMEOUT; while ((EMS_UART.status.rxfifo_cnt == _usrxc) && (--timeoutcnt > 0)) { delayMicroseconds(EMSUART_TX_BUSY_WAIT); // burn CPU cycles... } diff --git a/src/uart/emsuart_esp32.h b/src/uart/emsuart_esp32.h index 5e332ea07..b1528ef3c 100644 --- a/src/uart/emsuart_esp32.h +++ b/src/uart/emsuart_esp32.h @@ -50,7 +50,7 @@ // EMS 1.0 #define EMSUART_TX_BUSY_WAIT (EMSUART_TX_BIT_TIME / 8) // 13 -#define EMSUART_TX_TIMEOUT (22 * EMSUART_TX_BIT_TIME / EMSUART_TX_BUSY_WAIT) // 176 +#define EMSUART_TX_TIMEOUT (32 * EMSUART_TX_BIT_TIME / EMSUART_TX_BUSY_WAIT) // 256 // HT3/Junkers - Time to send one Byte (8 Bits, 1 Start Bit, 1 Stop Bit) plus 7 bit delay. The -8 is for lag compensation. // since we use a faster processor the lag is negligible diff --git a/src/uart/emsuart_esp8266.cpp b/src/uart/emsuart_esp8266.cpp index 894360219..f86e05ae6 100644 --- a/src/uart/emsuart_esp8266.cpp +++ b/src/uart/emsuart_esp8266.cpp @@ -43,13 +43,26 @@ void ICACHE_RAM_ATTR EMSuart::emsuart_rx_intr_handler(void * para) { static uint8_t length = 0; static uint8_t uart_buffer[EMS_MAXBUFFERSIZE + 2]; + if (USIS(EMSUART_UART) & ((1 << UIFF))) { // Fifo full, sending in Mode 5 + USIC(EMSUART_UART) |= (1 << UIFF); // clear fifo interrupt + emsTxBufIdx++; + if (emsTxBufIdx < emsTxBufLen) { + USF(EMSUART_UART) = emsTxBuf[emsTxBufIdx]; // send next byte + USC1(EMSUART_UART) = ((emsTxBufIdx + 1) << UCFFT); // increase fifo full + } else if (emsTxBufIdx == emsTxBufLen) { + USC0(EMSUART_UART) |= (1 << UCBRK); // set + USIE(EMSUART_UART) &= ~(1 << UIFF); // disable fifo-full irq + USC1(EMSUART_UART) = (0x7F << UCFFT); // fifo full to max + } + } if (USIS(EMSUART_UART) & ((1 << UIBD))) { // BREAK detection = End of EMS data block USC0(EMSUART_UART) &= ~(1 << UCBRK); // reset tx-brk if (emsTxBufIdx < emsTxBufLen) { // timer tx_mode is interrupted by emsTxBufIdx = emsTxBufLen; // stop timer mode drop_next_rx = true; // we have trash in buffer } - USIC(EMSUART_UART) = (1 << UIBD); // INT clear the BREAK detect interrupt + USIC(EMSUART_UART) = (1 << UIBD); // INT clear the BREAK detect interrupt + USIE(EMSUART_UART) &= ~(1 << UIFF); // disable fifo-full irq length = 0; while ((USS(EMSUART_UART) >> USRXC) & 0x0FF) { // read fifo into buffer uint8_t rx = USF(EMSUART_UART); @@ -62,9 +75,9 @@ void ICACHE_RAM_ATTR EMSuart::emsuart_rx_intr_handler(void * para) { if (!drop_next_rx) { pEMSRxBuf->length = length; os_memcpy((void *)pEMSRxBuf->buffer, (void *)&uart_buffer, pEMSRxBuf->length); // copy data into transfer buffer, including the BRK 0x00 at the end + system_os_post(EMSUART_recvTaskPrio, 0, 0); // call emsuart_recvTask() at next opportunity } drop_next_rx = false; - system_os_post(EMSUART_recvTaskPrio, 0, 0); // call emsuart_recvTask() at next opportunity } } @@ -235,11 +248,18 @@ void EMSuart::send_poll(uint8_t data) { // reset tx-brk, just in case it is accidentally set USC0(EMSUART_UART) &= ~(1 << UCBRK); - if (tx_mode_ >= 5) { // timer controlled modes + if (tx_mode_ > 5) { // timer controlled modes USF(EMSUART_UART) = data; emsTxBufIdx = 0; emsTxBufLen = 1; timer1_write(emsTxWait); + } else if (tx_mode_ == 5) { // reload sendbuffer in irq + USIC(EMSUART_UART) |= (1 << UIFF); // clear fifo-full irq + USC1(EMSUART_UART) = (0x01 << UCFFT); // fifo full to 1 + USF(EMSUART_UART) = data; + emsTxBufIdx = 0; + emsTxBufLen = 1; + USIE(EMSUART_UART) |= (1 << UIFF); // enable fifo-full irq } else if (tx_mode_ == EMS_TXMODE_NEW) { // hardware controlled modes USF(EMSUART_UART) = data; USC0(EMSUART_UART) |= (1 << UCBRK); // brk after sendout @@ -285,7 +305,7 @@ uint16_t ICACHE_FLASH_ATTR EMSuart::transmit(uint8_t * buf, uint8_t len) { USC0(EMSUART_UART) &= ~(1 << UCBRK); // timer controlled modes with extra delay - if (tx_mode_ >= 5) { + if (tx_mode_ > 5) { for (uint8_t i = 0; i < len; i++) { emsTxBuf[i] = buf[i]; } @@ -295,6 +315,19 @@ uint16_t ICACHE_FLASH_ATTR EMSuart::transmit(uint8_t * buf, uint8_t len) { timer1_write(emsTxWait); return EMS_TX_STATUS_OK; } + // interrupt controlled mode: readback in rx-irq and send next byte + if (tx_mode_ == 5) { + for (uint8_t i = 0; i < len; i++) { + emsTxBuf[i] = buf[i]; + } + USIC(EMSUART_UART) |= (1 << UIFF); // clear fifo-full irq + emsTxBufIdx = 0; + emsTxBufLen = len; + USF(EMSUART_UART) = buf[0]; + USC1(EMSUART_UART) = (0x01 << UCFFT); // fifo full to 1 + USIE(EMSUART_UART) |= (1 << UIFF); // enable fifo-full irq + return EMS_TX_STATUS_OK; + } // new code from Michael. See https://github.com/proddy/EMS-ESP/issues/380 if (tx_mode_ == EMS_TXMODE_NEW) { // tx_mode 4