diff --git a/src/emsesp.cpp b/src/emsesp.cpp index 9d0814a27..a9f00bc9b 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -571,10 +571,10 @@ 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 // 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()); -#endif +// #endif return; // it's an echo } 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 d6d91cb34..eae81b6c4 100644 --- a/src/telegram.cpp +++ b/src/telegram.cpp @@ -270,7 +270,9 @@ 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 to a MM10 Mixer (ems1.0) he replys with 21 0B FF 00 + 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 c93e4b2ad..56717e4c8 100644 --- a/src/uart/emsuart_esp32.cpp +++ b/src/uart/emsuart_esp32.cpp @@ -60,13 +60,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 = emsTxBufId + 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) { @@ -169,6 +181,13 @@ 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; + return EMS_TX_STATUS_OK; } else if (tx_mode_ == EMS_TXMODE_NEW) { EMS_UART.fifo.rw_byte = data; EMS_UART.conf0.txd_brk = 1; // after send @@ -216,6 +235,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]; diff --git a/src/uart/emsuart_esp8266.cpp b/src/uart/emsuart_esp8266.cpp index faedc23d8..b4706a54d 100644 --- a/src/uart/emsuart_esp8266.cpp +++ b/src/uart/emsuart_esp8266.cpp @@ -44,13 +44,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); // INT 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 + 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 + 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 + 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); @@ -63,9 +76,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 } } @@ -237,11 +250,17 @@ 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 + 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 @@ -257,7 +276,7 @@ void EMSuart::send_poll(uint8_t data) { ETS_UART_INTR_DISABLE(); volatile uint8_t _usrxc = (USS(EMSUART_UART) >> USRXC) & 0xFF; USF(EMSUART_UART) = data; - uint8_t timeoutcnt = EMSUART_TX_TIMEOUT; + uint16_t timeoutcnt = EMSUART_TX_TIMEOUT; while ((((USS(EMSUART_UART) >> USRXC) & 0xFF) == _usrxc) && (--timeoutcnt > 0)) { delayMicroseconds(EMSUART_TX_BUSY_WAIT); // burn CPU cycles... } @@ -285,7 +304,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 +314,17 @@ uint16_t ICACHE_FLASH_ATTR EMSuart::transmit(uint8_t * buf, uint8_t len) { timer1_write(emsTxWait); return EMS_TX_STATUS_OK; } + 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]; + 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 @@ -362,7 +392,7 @@ uint16_t 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++) { volatile uint8_t _usrxc = (USS(EMSUART_UART) >> USRXC) & 0xFF; - uint8_t timeoutcnt = EMSUART_TX_TIMEOUT; + uint16_t timeoutcnt = EMSUART_TX_TIMEOUT; USF(EMSUART_UART) = buf[i]; // send each Tx byte // wait for echo while ((((USS(EMSUART_UART) >> USRXC) & 0xFF) == _usrxc) && (--timeoutcnt > 0)) { @@ -378,7 +408,7 @@ uint16_t ICACHE_FLASH_ATTR EMSuart::transmit(uint8_t * buf, uint8_t len) { if (!(USIS(EMSUART_UART) & (1 << UIBD))) { // no bus collision - send terminating BRK signal USC0(EMSUART_UART) |= (1 << UCBRK); // set - uint8_t timeoutcnt = EMSUART_TX_TIMEOUT; + uint16_t timeoutcnt = EMSUART_TX_TIMEOUT; // wait until BRK detected... while (!(USIR(EMSUART_UART) & (1 << UIBD)) && (--timeoutcnt > 0)) { delayMicroseconds(EMSUART_TX_BUSY_WAIT); diff --git a/src/uart/emsuart_esp8266.h b/src/uart/emsuart_esp8266.h index 0f6d7d1e7..3463dcf91 100644 --- a/src/uart/emsuart_esp8266.h +++ b/src/uart/emsuart_esp8266.h @@ -46,7 +46,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) // equivaltent to 32 bittimes // 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