mirror of
https://github.com/rstrouse/ESPSomfy-RTS.git
synced 2026-10-31 13:52:15 +01:00
refactor: move the RX pulse decoder into PulseDecoder
The decoding of the time between received edges into frame bits moves out of Transceiver::handleReceive unchanged into decodePulse(), with the RTS timings and the receive buffer type. It stays in IRAM on the ESP32 and is now covered by native tests that feed it the edges sendFrame() produces for 56 and 80-bit first frames and repeats, a glitch and a broken pulse. handleReceive keeps the noise guard, the edge timing and the RX queue. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
c75b715b3b
commit
a176017960
6 changed files with 306 additions and 138 deletions
119
src/PulseDecoder.cpp
Normal file
119
src/PulseDecoder.cpp
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
#include "PulseDecoder.h"
|
||||
#if defined(ESP32)
|
||||
#include <esp_attr.h>
|
||||
#define PULSE_DECODER_ATTR IRAM_ATTR
|
||||
#else
|
||||
#define PULSE_DECODER_ATTR
|
||||
#endif
|
||||
|
||||
// Each timing is accepted within 30%.
|
||||
#define TOLERANCE_MIN 0.7
|
||||
#define TOLERANCE_MAX 1.3
|
||||
static const uint32_t tempo_wakeup_pulse = 9415;
|
||||
static const uint32_t tempo_wakeup_min = 9415 * TOLERANCE_MIN;
|
||||
static const uint32_t tempo_wakeup_max = 9415 * TOLERANCE_MAX;
|
||||
static const uint32_t tempo_wakeup_silence = 89565;
|
||||
static const uint32_t tempo_wakeup_silence_min = 89565 * TOLERANCE_MIN;
|
||||
static const uint32_t tempo_wakeup_silence_max = 89565 * TOLERANCE_MAX;
|
||||
static const uint32_t tempo_synchro_hw_min = SYMBOL * 4 * TOLERANCE_MIN;
|
||||
static const uint32_t tempo_synchro_hw_max = SYMBOL * 4 * TOLERANCE_MAX;
|
||||
static const uint32_t tempo_synchro_sw_min = 4850 * TOLERANCE_MIN;
|
||||
static const uint32_t tempo_synchro_sw_max = 4850 * TOLERANCE_MAX;
|
||||
static const uint32_t tempo_half_symbol_min = SYMBOL * TOLERANCE_MIN;
|
||||
static const uint32_t tempo_half_symbol_max = SYMBOL * TOLERANCE_MAX;
|
||||
static const uint32_t tempo_symbol_min = SYMBOL * 2 * TOLERANCE_MIN;
|
||||
static const uint32_t tempo_symbol_max = SYMBOL * 2 * TOLERANCE_MAX;
|
||||
static const uint32_t tempo_if_gap = 30415; // Gap between frames
|
||||
static int16_t bitMin = SYMBOL * TOLERANCE_MIN;
|
||||
PULSE_DECODER_ATTR PulseResult decodePulse(somfy_rx_t &rx, uint32_t durationUs) {
|
||||
const unsigned int duration = durationUs;
|
||||
if (duration < bitMin) {
|
||||
// The incoming bit is < 448us so it is probably a glitch so blow it off.
|
||||
// We need to ignore this bit.
|
||||
// REMOVE THIS AFTER WE DETERMINE THAT THE out-of-bounds stuff isn't a problem. If there are bits
|
||||
// from the previous frame then we will capture this data here.
|
||||
if(rx.pulseCount < MAX_TIMINGS && rx.cpt_synchro_hw > 0) rx.pulses[rx.pulseCount++] = duration;
|
||||
return PulseResult::glitch;
|
||||
}
|
||||
switch (rx.status) {
|
||||
case waiting_synchro:
|
||||
if(rx.pulseCount < MAX_TIMINGS) rx.pulses[rx.pulseCount++] = duration;
|
||||
if (duration > tempo_synchro_hw_min && duration < tempo_synchro_hw_max) {
|
||||
// We have found a hardware sync bit. There should be at least 4 of these.
|
||||
++rx.cpt_synchro_hw;
|
||||
}
|
||||
else if (duration > tempo_synchro_sw_min && duration < tempo_synchro_sw_max && rx.cpt_synchro_hw >= 4) {
|
||||
// If we have a full hardware sync then we should look for the software sync. If we have a software sync
|
||||
// bit and enough hardware sync bits then we should start receiving data. It turns out that a 56 bit packet
|
||||
// with give 4 or 14 bits of hardware sync. An 80 bit packet gives 12, 13 or 24 bits of hw sync. Early on
|
||||
// I had some shorter and longer hw syncs but I can no longer repeat this.
|
||||
memset(rx.payload, 0x00, sizeof(rx.payload));
|
||||
rx.previous_bit = 0x00;
|
||||
rx.waiting_half_symbol = false;
|
||||
rx.cpt_bits = 0;
|
||||
// Keep an eye on this as it is possible that we might get fewer or more synchro bits.
|
||||
if (rx.cpt_synchro_hw <= 7) rx.bit_length = 56;
|
||||
else if (rx.cpt_synchro_hw == 14) rx.bit_length = 56;
|
||||
else if (rx.cpt_synchro_hw == 13) rx.bit_length = 80; // The RS485 device sends this sync.
|
||||
else if (rx.cpt_synchro_hw == 12) rx.bit_length = 80;
|
||||
else if (rx.cpt_synchro_hw > 17) rx.bit_length = 80;
|
||||
else rx.bit_length = 56;
|
||||
//rx.bit_length = 80;
|
||||
rx.status = receiving_data;
|
||||
}
|
||||
else {
|
||||
// Reset and start looking for hardware sync again.
|
||||
rx.cpt_synchro_hw = 0;
|
||||
// Try to capture the wakeup pulse.
|
||||
if(duration > tempo_wakeup_min && duration < tempo_wakeup_max)
|
||||
{
|
||||
memset(&rx.payload, 0x00, sizeof(rx.payload));
|
||||
rx.previous_bit = 0x00;
|
||||
rx.waiting_half_symbol = false;
|
||||
rx.cpt_bits = 0;
|
||||
rx.bit_length = 56;
|
||||
}
|
||||
else if((rx.pulseCount > 20 && rx.cpt_synchro_hw == 0) || duration > 250000) {
|
||||
rx.pulseCount = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case receiving_data:
|
||||
if(rx.pulseCount < MAX_TIMINGS) rx.pulses[rx.pulseCount++] = duration;
|
||||
// We should be receiving data at this point.
|
||||
if (duration > tempo_symbol_min && duration < tempo_symbol_max && !rx.waiting_half_symbol) {
|
||||
rx.previous_bit = 1 - rx.previous_bit;
|
||||
// Bits come in high order bit first.
|
||||
rx.payload[rx.cpt_bits / 8] += rx.previous_bit << (7 - rx.cpt_bits % 8);
|
||||
++rx.cpt_bits;
|
||||
}
|
||||
else if (duration > tempo_half_symbol_min && duration < tempo_half_symbol_max) {
|
||||
if (rx.waiting_half_symbol) {
|
||||
rx.waiting_half_symbol = false;
|
||||
rx.payload[rx.cpt_bits / 8] += rx.previous_bit << (7 - rx.cpt_bits % 8);
|
||||
++rx.cpt_bits;
|
||||
}
|
||||
else {
|
||||
rx.waiting_half_symbol = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
//++rx.cpt_bits;
|
||||
// Start over we are not within our parameters for bit timing.
|
||||
memset(&rx.payload, 0x00, sizeof(rx.payload));
|
||||
rx.pulseCount = 1;
|
||||
rx.cpt_synchro_hw = 0;
|
||||
rx.previous_bit = 0x00;
|
||||
rx.waiting_half_symbol = false;
|
||||
rx.cpt_bits = 0;
|
||||
rx.bit_length = 56;
|
||||
rx.status = waiting_synchro;
|
||||
rx.pulses[0] = duration;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return rx.status == receiving_data && rx.cpt_bits >= rx.bit_length ? PulseResult::frame : PulseResult::more;
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue