From 816fd78fbb545ccddc85763e0837e67fafc4f989 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 1 Dec 2022 16:18:38 +0100 Subject: [PATCH] Fix LD2410 using HardwareSerial on ESP8266 --- .../TasmotaSerial-3.5.0/src/TasmotaSerial.cpp | 21 ++++--- .../TasmotaSerial-3.5.0/src/TasmotaSerial.h | 6 +- .../tasmota_xsns_sensor/xsns_102_ld2410.ino | 57 ++++++++++++++++++- 3 files changed, 69 insertions(+), 15 deletions(-) diff --git a/lib/default/TasmotaSerial-3.5.0/src/TasmotaSerial.cpp b/lib/default/TasmotaSerial-3.5.0/src/TasmotaSerial.cpp index 99241a44f..ce8958169 100644 --- a/lib/default/TasmotaSerial-3.5.0/src/TasmotaSerial.cpp +++ b/lib/default/TasmotaSerial-3.5.0/src/TasmotaSerial.cpp @@ -54,7 +54,8 @@ TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin, int hardware_fal serial_buffer_size = buffer_size; m_rx_pin = receive_pin; m_tx_pin = transmit_pin; - m_in_pos = m_out_pos = 0; + m_in_pos = 0; + m_out_pos = 0; #ifdef ESP8266 if (!((isValidGPIOpin(receive_pin)) && (isValidGPIOpin(transmit_pin) || transmit_pin == 16))) { return; @@ -293,7 +294,8 @@ void TasmotaSerial::flush(void) { while (TSerial->available()) { TSerial->read(); } #endif // ESP32 } else { - m_in_pos = m_out_pos = 0; + m_in_pos = 0; + m_out_pos = 0; } } @@ -428,13 +430,14 @@ size_t TasmotaSerial::write(uint8_t b) { } void IRAM_ATTR TasmotaSerial::rxRead(void) { + uint32_t m_out_pos_fixed = m_out_pos; if (!m_nwmode) { int32_t loop_read = m_very_high_speed ? serial_buffer_size : 1; // Advance the starting point for the samples but compensate for the // initial delay which occurs before the interrupt is delivered uint32_t wait = m_bit_start_time; uint32_t start = ESP.getCycleCount(); - while (loop_read-- > 0) { // try to receveive all consecutive bytes in a raw + while (loop_read-- > 0) { // try to receveive all consecutive bytes in a row uint32_t rec = 0; for (uint32_t i = 0; i < 8; i++) { TM_SERIAL_WAIT_RCV; @@ -442,14 +445,14 @@ void IRAM_ATTR TasmotaSerial::rxRead(void) { if (digitalRead(m_rx_pin)) rec |= 0x80; } // Store the received value in the buffer unless we have an overflow - uint32_t next = (m_in_pos+1) % serial_buffer_size; - if (next != (int)m_out_pos) { + uint32_t next = (m_in_pos + 1) % serial_buffer_size; + if (next != m_out_pos_fixed) { m_buffer[m_in_pos] = rec; m_in_pos = next; } else { - // Buffer overrun - exit and fix Hardware Watchdog in case of high speed flooding + // Buffer overrun - exit m_overflow = true; - break; + loop_read = 0; } TM_SERIAL_WAIT_RCV_LOOP; // wait for stop bit @@ -511,7 +514,7 @@ void IRAM_ATTR TasmotaSerial::rxRead(void) { } //stobyte(0,ssp->ss_byte>>1); uint32_t next = (m_in_pos + 1) % serial_buffer_size; - if (next != (uint32_t)m_out_pos) { + if (next != m_out_pos_fixed) { m_buffer[m_in_pos] = ss_byte >> 1; m_in_pos = next; } @@ -525,7 +528,7 @@ void IRAM_ATTR TasmotaSerial::rxRead(void) { // bit zero was 0, //stobyte(0,ssp->ss_byte>>1); uint32_t next = (m_in_pos + 1) % serial_buffer_size; - if (next != (uint32_t)m_out_pos) { + if (next != m_out_pos_fixed) { m_buffer[m_in_pos] = ss_byte >> 1; m_in_pos = next; } diff --git a/lib/default/TasmotaSerial-3.5.0/src/TasmotaSerial.h b/lib/default/TasmotaSerial-3.5.0/src/TasmotaSerial.h index b9542699e..3e4f9a315 100644 --- a/lib/default/TasmotaSerial-3.5.0/src/TasmotaSerial.h +++ b/lib/default/TasmotaSerial-3.5.0/src/TasmotaSerial.h @@ -70,11 +70,12 @@ class TasmotaSerial : public Stream { private: bool isValidGPIOpin(int pin); + size_t txWrite(uint8_t byte); + void _fast_write(uint8_t b); // IRAM minimized version #ifdef ESP32 bool freeUart(void); void Esp32Begin(void); #endif - size_t txWrite(uint8_t byte); // Member variables int m_rx_pin; @@ -97,9 +98,6 @@ class TasmotaSerial : public Stream { bool m_high_speed = false; bool m_very_high_speed = false; // above 100000 bauds uint8_t *m_buffer = nullptr; - - void _fast_write(uint8_t b); // IRAM minimized version - #ifdef ESP32 uint32_t m_speed; uint32_t m_config; diff --git a/tasmota/tasmota_xsns_sensor/xsns_102_ld2410.ino b/tasmota/tasmota_xsns_sensor/xsns_102_ld2410.ino index 474e4e825..ad4457492 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_102_ld2410.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_102_ld2410.ino @@ -67,6 +67,7 @@ struct { uint8_t step; uint8_t retry; uint8_t settings; + uint8_t byte_counter; bool valid_response; } LD2410; @@ -93,13 +94,13 @@ void Ld1410HandleTargetData(void) { LD2410.static_distance = LD2410.buffer[13] << 8 | LD2410.buffer[12]; LD2410.static_energy = LD2410.buffer[14]; LD2410.detect_distance = LD2410.buffer[16] << 8 | LD2410.buffer[15]; - +/* AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("LD2: Type %d, State %d, Moving %d/%d%%, Static %d/%d%%, Detect %d"), LD2410.buffer[6], LD2410.buffer[8], LD2410.moving_distance, LD2410.moving_energy, LD2410.static_distance, LD2410.static_energy, LD2410.detect_distance); - +*/ if (0x01 == LD2410.buffer[6]) { // Engineering mode data // Adds 22 extra bytes of data @@ -153,6 +154,8 @@ bool Ld2410Match(const uint8_t *header, uint32_t offset) { } void Ld2410Input(void) { +/* + // Works with TasmotaSerial as SoftwareSerial but fails with HardwareSerial uint32_t size = LD2410Serial->read(LD2410.buffer, LD2410_BUFFER_SIZE); if (size) { AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("LD2: Rcvd %*_H"), size, LD2410.buffer); @@ -175,6 +178,56 @@ void Ld2410Input(void) { } } } +*/ + // Works with TasmotaSerial and HardwareSerial + while (LD2410Serial->available()) { + yield(); // Fix watchdogs + + LD2410.buffer[LD2410.byte_counter++] = LD2410Serial->read(); + if (LD2410.byte_counter < 4) { continue; } // Need first four header bytes + + uint32_t header_start = LD2410.byte_counter -4; // Fix interrupted header transmits + bool target_header = (Ld2410Match(LD2410_target_header, header_start)); // F4F3F2F1 + bool config_header = (Ld2410Match(LD2410_config_header, header_start)); // FDFCFBFA + if ((target_header || config_header) && (header_start != 0)) { + memmove(LD2410.buffer, LD2410.buffer + header_start, 4); // Sync buffer with header + LD2410.byte_counter = 4; + } + if (LD2410.byte_counter < 6) { continue; } // Need packet size bytes + + target_header = (Ld2410Match(LD2410_target_header, 0)); // F4F3F2F1 + config_header = (Ld2410Match(LD2410_config_header, 0)); // FDFCFBFA + if (target_header || config_header) { + uint32_t len = LD2410.buffer[4] +10; // Total packet size + if (len > LD2410_BUFFER_SIZE) { + LD2410.byte_counter = 0; // Invalid data + break; // Exit loop to satisfy yields + } + if (LD2410.byte_counter < len) { continue; } // Need complete packet + +// AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("LD2: Rcvd %*_H"), len, LD2410.buffer); + + if (target_header) { // F4F3F2F1 + +// AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("LD2: Rcvd %*_H"), len, LD2410.buffer); + + if (Ld2410Match(LD2410_target_footer, len -4)) { // F8F7F6F5 + Ld1410HandleTargetData(); + } + } + else if (config_header) { // FDFCFBFA + + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("LD2: Rcvd %*_H"), len, LD2410.buffer); + + if (Ld2410Match(LD2410_config_footer, len -4)) { // 04030201 + Ld1410HandleConfigData(); + } + } + } + LD2410.byte_counter = 0; // Finished or bad received footer + break; // Exit loop to satisfy yields + } + // If here then LD2410.byte_counter could still be partial correct for next loop } void Ld2410SendCommand(uint32_t command, uint8_t *val = nullptr, uint32_t val_len = 0);