From f807eac26a49be684b4d9e1fc552f789790bb313 Mon Sep 17 00:00:00 2001 From: Paul Date: Tue, 26 May 2020 13:28:23 +0200 Subject: [PATCH] a9 - roll back uart changes for esp8266 --- lib/uuid-console/src/shell.cpp | 4 +- src/boiler.cpp | 2 +- src/console.h | 1 + src/emsesp.cpp | 10 +- src/mqtt.cpp | 17 ++- src/telegram.h | 3 +- src/uart/emsuart_esp8266.cpp | 197 ++++++++++++++++++++------------- src/version.h | 2 +- 8 files changed, 140 insertions(+), 96 deletions(-) diff --git a/lib/uuid-console/src/shell.cpp b/lib/uuid-console/src/shell.cpp index 9caaa9ed7..3090aaf8c 100644 --- a/lib/uuid-console/src/shell.cpp +++ b/lib/uuid-console/src/shell.cpp @@ -58,8 +58,8 @@ Shell::~Shell() { void Shell::start() { #ifdef EMSESP_DEBUG - // uuid::log::Logger::register_handler(this, uuid::log::Level::DEBUG); // added by proddy - uuid::log::Logger::register_handler(this, uuid::log::Level::INFO); // added by proddy + uuid::log::Logger::register_handler(this, uuid::log::Level::DEBUG); // added by proddy + //uuid::log::Logger::register_handler(this, uuid::log::Level::INFO); // added by proddy #else uuid::log::Logger::register_handler(this, uuid::log::Level::NOTICE); #endif diff --git a/src/boiler.cpp b/src/boiler.cpp index c9b6bca9e..283c3fc01 100644 --- a/src/boiler.cpp +++ b/src/boiler.cpp @@ -447,7 +447,7 @@ void Boiler::check_active() { // heating // using a quick hack for checking the heating by looking at the Selected Flow Temp, but doesn't work for all boilers apparently if (selFlowTemp_ != EMS_VALUE_UINT_NOTSET && burnGas_ != EMS_VALUE_UINT_NOTSET) { - heating_active_ = ((selFlowTemp_ >= EMS_BOILER_SELFLOWTEMP_HEATING) && (burnGas_ != EMS_VALUE_BOOL_OFF)); + heating_active_ = (!tap_water_active_ && ((selFlowTemp_ >= EMS_BOILER_SELFLOWTEMP_HEATING) && (burnGas_ != EMS_VALUE_BOOL_OFF))); } // see if the heating or hot tap water has changed, if so send diff --git a/src/console.h b/src/console.h index 3f4d8c12f..337133426 100644 --- a/src/console.h +++ b/src/console.h @@ -59,6 +59,7 @@ using uuid::log::Level; #ifdef EMSESP_DEBUG MAKE_PSTR_WORD(test) #endif + MAKE_PSTR_WORD(exit) MAKE_PSTR_WORD(help) MAKE_PSTR_WORD(settings) diff --git a/src/emsesp.cpp b/src/emsesp.cpp index 8f98e9b6e..825b8780b 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -425,7 +425,7 @@ bool EMSESP::process_telegram(std::shared_ptr telegram) { // check to see if we need to force an MQTT publish if (found) { if (emsdevice->updated_values()) { - emsdevice->publish_values(); + emsdevice->publish_values(); // publish to MQTT if we explicitly have too } } break; @@ -434,7 +434,7 @@ bool EMSESP::process_telegram(std::shared_ptr telegram) { } if (!found) { - LOG_DEBUG(F("No telegram type handler found for type ID 0x%02X (src 0x%02X, dest 0x%02X)"), telegram->type_id, telegram->src, telegram->dest); + LOG_DEBUG(F("No telegram type handler found for ID 0x%02X (src 0x%02X, dest 0x%02X)"), telegram->type_id, telegram->src, telegram->dest); } return found; @@ -586,7 +586,7 @@ void EMSESP::incoming_telegram(uint8_t * data, const uint8_t length) { txservice_.send_poll(); // close the bus txservice_.post_send_query(); // send type_id to last destination } else if (first_value == TxService::TX_WRITE_FAIL) { - LOG_DEBUG(F("Last Tx write rejected by host")); + LOG_ERROR(F("Last Tx write rejected by host")); txservice_.send_poll(); // close the bus } else { // ignore it, it's probably a poll and we can wait for the next one @@ -606,9 +606,9 @@ void EMSESP::incoming_telegram(uint8_t * data, const uint8_t length) { // So re-send the last Tx and increment retry count uint8_t retries = txservice_.retry_tx(); // returns 0 if exceeded count if (retries) { - LOG_DEBUG(F("Last Tx read failed. Retrying #%d..."), retries); + LOG_ERROR(F("Last Tx read failed. Retrying #%d..."), retries); } else { - LOG_DEBUG(F("Last Tx read failed. Giving up")); + LOG_ERROR(F("Last Tx read failed after %d retries"), txservice_.MAXIMUM_TX_RETRIES); } } } diff --git a/src/mqtt.cpp b/src/mqtt.cpp index 9b00788c2..c616eadd3 100644 --- a/src/mqtt.cpp +++ b/src/mqtt.cpp @@ -393,11 +393,7 @@ void Mqtt::on_publish(uint16_t packetId) { return; } - if (mqtt_message.packet_id_ == packetId) { -#ifdef EMSESP_DEBUG - LOG_DEBUG(F("Acknowledged PID %d. Removing from queue"), packetId); -#endif - } else { + if (mqtt_message.packet_id_ != packetId) { LOG_DEBUG(F("Mismatch, expecting PID %d, got %d"), mqtt_message.packet_id_, packetId); mqtt_publish_fails_++; // increment error count } @@ -422,9 +418,7 @@ char * Mqtt::make_topic(char * result, const std::string & topic) { } void Mqtt::start() { - publish("status", "online", true); // say we're alive to the Last Will topic, with retain on send_start_topic(); - send_heartbeat(); // send heartbeat if enabled } // send online appended with the version information as JSON @@ -440,6 +434,11 @@ void Mqtt::on_connect() { mqtt_reconnect_delay_ = Mqtt::MQTT_RECONNECT_DELAY_MIN; mqtt_last_connection_ = uuid::get_uptime(); mqtt_connecting_ = false; + + publish("status", "online", true); // say we're alive to the Last Will topic, with retain on + + send_heartbeat(); // send heartbeat if enabled + LOG_INFO(F("MQTT connected")); } @@ -602,9 +601,7 @@ void Mqtt::process_queue() { // but add the packet_id so we can check it later if (mqtt_qos_ != 0) { mqtt_messages_.front().packet_id_ = packet_id; -#ifdef EMSESP_DEBUG - LOG_DEBUG(F("Setting packetID for ACK to %d"), packet_id); -#endif + // LOG_DEBUG(F("Setting packetID for ACK to %d"), packet_id); return; } diff --git a/src/telegram.h b/src/telegram.h index 4bef66150..f351a9b8f 100644 --- a/src/telegram.h +++ b/src/telegram.h @@ -287,10 +287,9 @@ class TxService : public EMSbus { std::string last_tx_to_string() const; - - private: static constexpr uint8_t MAXIMUM_TX_RETRIES = 3; + private: uint8_t tx_telegram_id_ = 0; // queue counter static constexpr uint32_t TX_LOOP_WAIT = 10000; // when to check if Tx is up and running (10 sec) diff --git a/src/uart/emsuart_esp8266.cpp b/src/uart/emsuart_esp8266.cpp index 939c1f7d5..6247f54d5 100644 --- a/src/uart/emsuart_esp8266.cpp +++ b/src/uart/emsuart_esp8266.cpp @@ -24,35 +24,52 @@ namespace emsesp { -os_event_t recvTaskQueue[EMSUART_recvTaskQueueLen]; // our Rx queue +os_event_t recvTaskQueue[EMSUART_recvTaskQueueLen]; // our Rx queue + EMSuart::EMSRxBuf_t * pEMSRxBuf; EMSuart::EMSRxBuf_t * paEMSRxBuf[EMS_MAXBUFFERS]; -uint8_t emsRxBufIdx = 0; - -uint8_t phantomBreak = 0; -uint8_t tx_mode_ = EMS_TXMODE_DEFAULT; +uint8_t emsRxBufIdx = 0; +uint8_t phantomBreak = 0; +uint8_t tx_mode_ = EMS_TXMODE_DEFAULT; +// // Main interrupt handler // Important: must not use ICACHE_FLASH_ATTR +// void ICACHE_RAM_ATTR EMSuart::emsuart_rx_intr_handler(void * para) { - static uint8_t length = 0; - static uint8_t uart_buffer[128]; + static uint8_t length = 0; + static bool rx_idle_ = true; + static uint8_t uart_buffer[EMS_MAXBUFFERSIZE + 2]; + + // is a new buffer? if so init the thing for a new telegram + if (rx_idle_) { + rx_idle_ = false; // status set to busy + length = 0; + } + + // fill IRQ buffer, by emptying Rx FIFO + if (USIS(EMSUART_UART) & ((1 << UIFF) | (1 << UITO) | (1 << UIBD))) { + while ((USS(EMSUART_UART) >> USRXC) & 0xFF) { + uint8_t rx = USF(EMSUART_UART); + if (length < EMS_MAXBUFFERSIZE) + uart_buffer[length++] = rx; + } + + // clear Rx FIFO full and Rx FIFO timeout interrupts + USIC(EMSUART_UART) = (1 << UIFF) | (1 << UITO); + } // BREAK detection = End of EMS data block if (USIS(EMSUART_UART) & ((1 << UIBD))) { - uint8_t rxlen = (USS(EMSUART_UART) & 0xFF); // length of buffer - for (length = 0; length < rxlen; length++) { - uart_buffer[length] = USF(EMSUART_UART); - } - USIE(EMSUART_UART) = 0; // disable all interrupts and clear them - USC0(EMSUART_UART) &= ~(1 << UCBRK); // reset from sending - if (length < EMS_MAXBUFFERSIZE) { // only a valid telegram - 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 - } + ETS_UART_INTR_DISABLE(); // disable all interrupts and clear them USIC(EMSUART_UART) = (1 << UIBD); // INT clear the BREAK detect interrupt - USIE(EMSUART_UART) = (1 << UIBD); // enable only rx break + + 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 + rx_idle_ = true; // check 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 } } @@ -67,7 +84,6 @@ void ICACHE_FLASH_ATTR EMSuart::emsuart_recvTask(os_event_t * events) { uint8_t length = pCurrent->length; // number of bytes including the BRK at the end pCurrent->length = 0; - // LEGACY CODE if (phantomBreak) { phantomBreak = 0; length--; // remove phantom break from Rx buffer @@ -79,13 +95,23 @@ void ICACHE_FLASH_ATTR EMSuart::emsuart_recvTask(os_event_t * events) { return; } + // ignore double BRK at the end, possibly from the Tx loopback // also telegrams with no data value - // then transmit EMS buffer, excluding the BRK, length is checked by irq - if (length > 4) { + // then transmit EMS buffer, excluding the BRK + if ((length > 4) && (length <= EMS_MAXBUFFERSIZE + 1)) { EMSESP::incoming_telegram((uint8_t *)pCurrent->buffer, length - 1); } } +/* + * flush everything left over in buffer, this clears both rx and tx FIFOs + */ +void ICACHE_FLASH_ATTR EMSuart::emsuart_flush_fifos() { + uint32_t tmp = ((1 << UCRXRST) | (1 << UCTXRST)); // bit mask + USC0(EMSUART_UART) |= (tmp); // set bits + USC0(EMSUART_UART) &= ~(tmp); // clear bits +} + /* * init UART0 driver */ @@ -99,6 +125,9 @@ void ICACHE_FLASH_ATTR EMSuart::start(uint8_t tx_mode) { } pEMSRxBuf = paEMSRxBuf[0]; // reset EMS Rx Buffer + ETS_UART_INTR_DISABLE(); + ETS_UART_INTR_ATTACH(nullptr, nullptr); + // pin settings PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U); PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD); @@ -107,21 +136,43 @@ 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; + USC0(EMSUART_UART) = EMSUART_CONFIG; // 8N1 - USC0(EMSUART_UART) |= ((1 << UCRXRST) | (1 << UCTXRST)); // set bits - USC0(EMSUART_UART) &= ~((1 << UCRXRST) | (1 << UCTXRST)); // clear bits + emsuart_flush_fifos(); - // UCFFT = RX FIFO Full Threshold (7 bit) = want this to be more than 32) - USC1(EMSUART_UART) = (0x7F << UCFFT); // rx buffer full - USIE(EMSUART_UART) = 0; // disable all interrupts - USIC(EMSUART_UART) = 0xFFFF; // clear all interupts + // conf1 params + // UCTOE = RX TimeOut enable (default is 1) + // 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 traffic. + // Otherwise, we're only noticed by UCTOT or RxBRK! + USC1(EMSUART_UART) = 0; // reset config first + USC1(EMSUART_UART) = (0x01 << UCFFT) | (0x01 << UCTOT) | (0 << UCTOE); // enable interupts + + // set interrupts for triggers + USIC(EMSUART_UART) = 0xFFFF; // clear all interupts + USIE(EMSUART_UART) = 0; // disable all interrupts + + // 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 + // 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); + + // disable esp debug which will go to Tx and mess up the line - see https://github.com/espruino/Espruino/issues/655 + system_set_os_print(0); + + // swap Rx and Tx pins to use GPIO13 (D7) and GPIO15 (D8) respectively + system_uart_swap(); - system_os_task(emsuart_recvTask, EMSUART_recvTaskPrio, recvTaskQueue, EMSUART_recvTaskQueueLen); // set up interrupt callbacks for Rx - system_set_os_print(0); // disable esp debug which will go to Tx and mess up the line - see https://github.com/espruino/Espruino/issues/655 - system_uart_swap(); // swap Rx and Tx pins to use GPIO13 (D7) and GPIO15 (D8) respectively ETS_UART_INTR_ATTACH(emsuart_rx_intr_handler, nullptr); - USIE(EMSUART_UART) = (1 << UIBD); // enable only rx break interrupt + ETS_UART_INTR_ENABLE(); + + // LOG_INFO(F("UART service for Rx/Tx started")); } /* @@ -129,25 +180,59 @@ void ICACHE_FLASH_ATTR EMSuart::start(uint8_t tx_mode) { * This is called prior to an OTA upload and also before a save to the filesystem to prevent conflicts */ void ICACHE_FLASH_ATTR EMSuart::stop() { - USIE(EMSUART_UART) = 0; // disable interrup + ETS_UART_INTR_DISABLE(); } /* * re-start UART0 driver */ void ICACHE_FLASH_ATTR EMSuart::restart() { - USIE(EMSUART_UART) = (1 << UIBD); // enable only rx break + ETS_UART_INTR_ENABLE(); } +/* + * Send a BRK signal + * 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 + + // 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 + + if (tx_mode_ == EMS_TX_WTD_TIMEOUT) { // 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) + } + + USC0(EMSUART_UART) &= ~(tmp); // clear bit +} + +/* + * Sends a 1-byte poll, ending with a + * 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) { - USC0(EMSUART_UART) &= ~(1 << UCBRK); // clear bit USF(EMSUART_UART) = data; - USC0(EMSUART_UART) |= (1 << UCBRK); // send at the end + delayMicroseconds(EMSUART_TX_BRK_WAIT); + tx_brk(); // send } /* * Send data to Tx line, ending with a * 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) { @@ -270,44 +355,6 @@ EMSUART_STATUS ICACHE_FLASH_ATTR EMSuart::transmit(uint8_t * buf, uint8_t len) { return result; // send the Tx status back } -/* - * flush everything left over in buffer, this clears both rx and tx FIFOs - */ -void ICACHE_FLASH_ATTR EMSuart::emsuart_flush_fifos() { - uint32_t tmp = ((1 << UCRXRST) | (1 << UCTXRST)); // bit mask - USC0(EMSUART_UART) |= (tmp); // set bits - USC0(EMSUART_UART) &= ~(tmp); // clear bits -} - -/* - * Send a BRK signal - * 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 - - // 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 - - if (tx_mode_ == EMS_TX_WTD_TIMEOUT) { // 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) - } - - USC0(EMSUART_UART) &= ~(tmp); // clear bit -} - } // namespace emsesp #endif diff --git a/src/version.h b/src/version.h index 7a4641f7b..56a398129 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define EMSESP_APP_VERSION "2.0.0a8" +#define EMSESP_APP_VERSION "2.0.0a9"