diff --git a/src/devices/honeywell.c b/src/devices/honeywell.c index ef78caa0..f464f2e2 100644 --- a/src/devices/honeywell.c +++ b/src/devices/honeywell.c @@ -38,52 +38,82 @@ Data layout: - E: 8bit Event, where 0x80 = Open/Close, 0x04 = Heartbeat / or id - S: 16bit CRC +Demodulated as raw PCM (half-bit width ~136 us) with the preamble and +Manchester decoding done explicitly in decode_fn, rather than relying on +OOK_PULSE_MANCHESTER_ZEROBIT's own pulse-level auto-decode. That demod has +no preamble-alignment step of its own -- any noise before the real signal +starts (seen on some 5816/5820L/2GIG units at close range, where receiver +AGC overload makes the pre-message "gap" noisy) throws off its bit count +from the very first edge, corrupting the whole message even though the +underlying pulse train is intact. Searching for the preamble explicitly at +the raw level, as done here, recovers those messages: confirmed against +real captures in https://github.com/merbanan/rtl_433/issues/2015 that +decoded 0 of 6 repeats with the old demod and 6 of 6 with this one. */ static int honeywell_decode(r_device *decoder, bitbuffer_t *bitbuffer) { - // full preamble is 0xFFFE - uint8_t const preamble_pattern[2] = {0xff, 0xe0}; // 12 bits - + // full preamble is 0xFFFE decoded, i.e. 0x555556 (24 bits) raw Manchester + // before decoding -- searched for at the raw level (see file header) so + // that noise before the real signal starts can't misalign the decode. + // The preamble is a repeating 01 pattern until its final 10, so a naive + // single bitbuffer_search() can latch onto an earlier, spurious 24-bit + // match within that run at the wrong (off-by-one-bit) alignment -- loop + // over every match and validate by CRC instead of trusting the first. + uint8_t const preamble_pattern[3] = {0x55, 0x55, 0x56}; int row = 0; // we expect a single row only. reduce collisions - if (bitbuffer->num_rows != 1 || bitbuffer->bits_per_row[row] < 60) { + if (bitbuffer->num_rows != 1 || bitbuffer->bits_per_row[row] < 120) { return DECODE_ABORT_LENGTH; } - bitbuffer_invert(bitbuffer); + int raw_len = bitbuffer->bits_per_row[row]; + uint8_t b[10] = {0}; + int channel = 0; + int device_id = 0; + int crc = 0; + int len = 0; + unsigned raw_pos = 0; + int found = 0; - int pos = bitbuffer_search(bitbuffer, row, 0, preamble_pattern, 12) + 12; - int len = bitbuffer->bits_per_row[row] - pos; - if (len < 48) { - return DECODE_ABORT_LENGTH; + while ((raw_pos = bitbuffer_search(bitbuffer, row, raw_pos, preamble_pattern, 24)) + 24 < (unsigned)raw_len) { + bitbuffer_t decoded = {0}; + bitbuffer_manchester_decode(bitbuffer, row, raw_pos + 24, &decoded, 96); + raw_pos += 1; // try the next possible (possibly off-by-one) match too + + len = decoded.bits_per_row[0]; + if (len < 48) { + continue; + } + memcpy(b, decoded.bb[0], 10); + + channel = b[0] >> 4; + device_id = ((b[0] & 0xf) << 16) | (b[1] << 8) | b[2]; + crc = (b[4] << 8) | b[5]; + + if (device_id == 0 && crc == 0) { + continue; // Reduce collisions + } + + uint16_t crc_calculated; + if (channel == 0x2 || channel == 0x4 || channel == 0x9 || channel == 0xA || channel == 0xC) { + // 2GIG brand, also Type 0xC for Tilt Sensor + crc_calculated = crc16(b, 4, 0x8050, 0); + } else { // channel == 0x8 + crc_calculated = crc16(b, 4, 0x8005, 0); + } + if (crc == crc_calculated) { + found = 1; + break; + } } - uint8_t b[10] = {0}; - uint16_t crc_calculated = 0; - bitbuffer_extract_bytes(bitbuffer, row, pos, b, 80); - - int channel = b[0] >> 4; - int device_id = ((b[0] & 0xf) << 16) | (b[1] << 8) | b[2]; - int crc = (b[4] << 8) | b[5]; - - if (device_id == 0 && crc == 0) { - return DECODE_ABORT_EARLY; // Reduce collisions + if (!found) { + return DECODE_FAIL_MIC; // Not a valid packet } if (len > 50) { // DW11 decoder_log_bitrow(decoder, 1, __func__, b, (len > 80 ? 80 : len), ""); } - if (channel == 0x2 || channel == 0x4 || channel == 0x9 || channel == 0xA || channel == 0xC) { - // 2GIG brand, also Type 0xC for Tilt Sensor - - crc_calculated = crc16(b, 4, 0x8050, 0); - } else { // channel == 0x8 - crc_calculated = crc16(b, 4, 0x8005, 0); - } - if (crc != crc_calculated) { - return DECODE_FAIL_MIC; // Not a valid packet - } - int event = b[3]; // decoded event bits: CTRABHUU // NOTE: not sure if these apply to all device types @@ -133,10 +163,10 @@ static char const *const output_fields[] = { r_device const honeywell = { .name = "Honeywell Door/Window Sensor, 2Gig DW10/DW11, RE208 repeater", - .modulation = OOK_PULSE_MANCHESTER_ZEROBIT, - .short_width = 156, - .long_width = 0, - .reset_limit = 292, + .modulation = OOK_PULSE_PCM, + .short_width = 136, + .long_width = 136, + .reset_limit = 408, .decode_fn = &honeywell_decode, .fields = output_fields, };