PulseDecoder.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "PulseDecoder.h" | ||
| 2 | #if defined(ESP32) | ||
| 3 | #include <esp_attr.h> | ||
| 4 | #define PULSE_DECODER_ATTR IRAM_ATTR | ||
| 5 | #else | ||
| 6 | #define PULSE_DECODER_ATTR | ||
| 7 | #endif | ||
| 8 | |||
| 9 | // Each timing is accepted within 30%. | ||
| 10 | #define TOLERANCE_MIN 0.7 | ||
| 11 | #define TOLERANCE_MAX 1.3 | ||
| 12 | static const uint32_t tempo_wakeup_pulse = 9415; | ||
| 13 | static const uint32_t tempo_wakeup_min = 9415 * TOLERANCE_MIN; | ||
| 14 | static const uint32_t tempo_wakeup_max = 9415 * TOLERANCE_MAX; | ||
| 15 | static const uint32_t tempo_wakeup_silence = 89565; | ||
| 16 | static const uint32_t tempo_wakeup_silence_min = 89565 * TOLERANCE_MIN; | ||
| 17 | static const uint32_t tempo_wakeup_silence_max = 89565 * TOLERANCE_MAX; | ||
| 18 | static const uint32_t tempo_synchro_hw_min = SYMBOL * 4 * TOLERANCE_MIN; | ||
| 19 | static const uint32_t tempo_synchro_hw_max = SYMBOL * 4 * TOLERANCE_MAX; | ||
| 20 | static const uint32_t tempo_synchro_sw_min = 4850 * TOLERANCE_MIN; | ||
| 21 | static const uint32_t tempo_synchro_sw_max = 4850 * TOLERANCE_MAX; | ||
| 22 | static const uint32_t tempo_half_symbol_min = SYMBOL * TOLERANCE_MIN; | ||
| 23 | static const uint32_t tempo_half_symbol_max = SYMBOL * TOLERANCE_MAX; | ||
| 24 | static const uint32_t tempo_symbol_min = SYMBOL * 2 * TOLERANCE_MIN; | ||
| 25 | static const uint32_t tempo_symbol_max = SYMBOL * 2 * TOLERANCE_MAX; | ||
| 26 | static const uint32_t tempo_if_gap = 30415; // Gap between frames | ||
| 27 | static int16_t bitMin = SYMBOL * TOLERANCE_MIN; | ||
| 28 | 1021 | PULSE_DECODER_ATTR PulseResult decodePulse(somfy_rx_t &rx, uint32_t durationUs) { | |
| 29 | 1021 | const unsigned int duration = durationUs; | |
| 30 | 1021 | if (duration < bitMin) { | |
| 31 | // The incoming bit is < 448us so it is probably a glitch so blow it off. | ||
| 32 | // We need to ignore this bit. | ||
| 33 | // REMOVE THIS AFTER WE DETERMINE THAT THE out-of-bounds stuff isn't a problem. If there are bits | ||
| 34 | // from the previous frame then we will capture this data here. | ||
| 35 | 1 | if(rx.pulseCount < MAX_TIMINGS && rx.cpt_synchro_hw > 0) rx.pulses[rx.pulseCount++] = duration; | |
| 36 | 1 | return PulseResult::glitch; | |
| 37 | } | ||
| 38 | 1020 | switch (rx.status) { | |
| 39 | 311 | case waiting_synchro: | |
| 40 | 311 | if(rx.pulseCount < MAX_TIMINGS) rx.pulses[rx.pulseCount++] = duration; | |
| 41 | 311 | if (duration > tempo_synchro_hw_min && duration < tempo_synchro_hw_max) { | |
| 42 | // We have found a hardware sync bit. There should be at least 4 of these. | ||
| 43 | 112 | ++rx.cpt_synchro_hw; | |
| 44 | } | ||
| 45 | 199 | else if (duration > tempo_synchro_sw_min && duration < tempo_synchro_sw_max && rx.cpt_synchro_hw >= 4) { | |
| 46 | // If we have a full hardware sync then we should look for the software sync. If we have a software sync | ||
| 47 | // bit and enough hardware sync bits then we should start receiving data. It turns out that a 56 bit packet | ||
| 48 | // with give 4 or 14 bits of hardware sync. An 80 bit packet gives 12, 13 or 24 bits of hw sync. Early on | ||
| 49 | // I had some shorter and longer hw syncs but I can no longer repeat this. | ||
| 50 | 8 | memset(rx.payload, 0x00, sizeof(rx.payload)); | |
| 51 | 8 | rx.previous_bit = 0x00; | |
| 52 | 8 | rx.waiting_half_symbol = false; | |
| 53 | 8 | rx.cpt_bits = 0; | |
| 54 | // Keep an eye on this as it is possible that we might get fewer or more synchro bits. | ||
| 55 | 8 | if (rx.cpt_synchro_hw <= 7) rx.bit_length = 56; | |
| 56 | 7 | else if (rx.cpt_synchro_hw == 14) rx.bit_length = 56; | |
| 57 | 2 | else if (rx.cpt_synchro_hw == 13) rx.bit_length = 80; // The RS485 device sends this sync. | |
| 58 | 2 | else if (rx.cpt_synchro_hw == 12) rx.bit_length = 80; | |
| 59 | 1 | else if (rx.cpt_synchro_hw > 17) rx.bit_length = 80; | |
| 60 | ✗ | else rx.bit_length = 56; | |
| 61 | //rx.bit_length = 80; | ||
| 62 | 8 | rx.status = receiving_data; | |
| 63 | } | ||
| 64 | else { | ||
| 65 | // Reset and start looking for hardware sync again. | ||
| 66 | 191 | rx.cpt_synchro_hw = 0; | |
| 67 | // Try to capture the wakeup pulse. | ||
| 68 | 191 | if(duration > tempo_wakeup_min && duration < tempo_wakeup_max) | |
| 69 | { | ||
| 70 | 4 | memset(&rx.payload, 0x00, sizeof(rx.payload)); | |
| 71 | 4 | rx.previous_bit = 0x00; | |
| 72 | 4 | rx.waiting_half_symbol = false; | |
| 73 | 4 | rx.cpt_bits = 0; | |
| 74 | 4 | rx.bit_length = 56; | |
| 75 | } | ||
| 76 | 187 | else if((rx.pulseCount > 20 && rx.cpt_synchro_hw == 0) || duration > 250000) { | |
| 77 | 8 | rx.pulseCount = 0; | |
| 78 | } | ||
| 79 | } | ||
| 80 | 311 | break; | |
| 81 | 709 | case receiving_data: | |
| 82 | 709 | if(rx.pulseCount < MAX_TIMINGS) rx.pulses[rx.pulseCount++] = duration; | |
| 83 | // We should be receiving data at this point. | ||
| 84 | 709 | if (duration > tempo_symbol_min && duration < tempo_symbol_max && !rx.waiting_half_symbol) { | |
| 85 | 180 | rx.previous_bit = 1 - rx.previous_bit; | |
| 86 | // Bits come in high order bit first. | ||
| 87 | 180 | rx.payload[rx.cpt_bits / 8] += rx.previous_bit << (7 - rx.cpt_bits % 8); | |
| 88 | 180 | ++rx.cpt_bits; | |
| 89 | } | ||
| 90 | 529 | else if (duration > tempo_half_symbol_min && duration < tempo_half_symbol_max) { | |
| 91 | 528 | if (rx.waiting_half_symbol) { | |
| 92 | 264 | rx.waiting_half_symbol = false; | |
| 93 | 264 | rx.payload[rx.cpt_bits / 8] += rx.previous_bit << (7 - rx.cpt_bits % 8); | |
| 94 | 264 | ++rx.cpt_bits; | |
| 95 | } | ||
| 96 | else { | ||
| 97 | 264 | rx.waiting_half_symbol = true; | |
| 98 | } | ||
| 99 | } | ||
| 100 | else { | ||
| 101 | //++rx.cpt_bits; | ||
| 102 | // Start over we are not within our parameters for bit timing. | ||
| 103 | 1 | memset(&rx.payload, 0x00, sizeof(rx.payload)); | |
| 104 | 1 | rx.pulseCount = 1; | |
| 105 | 1 | rx.cpt_synchro_hw = 0; | |
| 106 | 1 | rx.previous_bit = 0x00; | |
| 107 | 1 | rx.waiting_half_symbol = false; | |
| 108 | 1 | rx.cpt_bits = 0; | |
| 109 | 1 | rx.bit_length = 56; | |
| 110 | 1 | rx.status = waiting_synchro; | |
| 111 | 1 | rx.pulses[0] = duration; | |
| 112 | } | ||
| 113 | 709 | break; | |
| 114 | ✗ | default: | |
| 115 | ✗ | break; | |
| 116 | } | ||
| 117 | 1020 | return rx.status == receiving_data && rx.cpt_bits >= rx.bit_length ? PulseResult::frame : PulseResult::more; | |
| 118 | } | ||
| 119 | |||
| 120 |