Add rtl_433 decoder (100 kbps Manchester) and firmware field analysis#59
Conversation
Add the rtl_433 decoder for the Uponor Clean 1 868 MHz inner/outer link, built from real RTL-SDR captures: 100 kbps line rate carrying software-Manchester data (raw 01->1, 10->0), ~40 bytes/packet, constant fd7a bababa 83 header, near-static telemetry sent as a two-packet exchange every ~62 s. The decoder demods at 100 kbps, Manchester-decodes both bit phases and keeps the cleaner one, anchors on fd7a, and emits header + raw payload hex until the fields and CRC are pinned down. It ships disabled. docs/rtl433.md records the capture procedure and empirical results, plus a firmware section: Ghidra analysis of the MC9S08 flash shows the on-air byte layout is not in the CPU (it is only an SPI slave on a custom MC9S08<->8051 message bus; the nRF9E5's 8051 owns framing/Manchester). Firmware does give the decode targets (alarm-code and setpoint tables), so field mapping [U6] needs a display-correlated capture. Add the Ghidra helper scripts used (DumpBytes, FindRefsInRange, ForceDecompile). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
| the display. It ships disabled until the fields and CRC are pinned down. | ||
|
|
||
| Flex-decoder equivalent for a first capture pass (100 kbps, then Manchester by | ||
| eye): rtl_433 -X 'n=uclean1,m=FSK_PCM,s=10,l=10,r=100' |
There was a problem hiding this comment.
this if missing the -f parameter
…pass - The flex-decoder example in the header was missing the tuner frequency; add -f 868.20M (tune low so the carrier sits off the RTL-SDR DC spike). - Document why we don't use rtl_433's native bitbuffer_manchester_decode(): it aborts at the first Manchester violation and does a single phase, whereas real captures need violation tolerance + best-of-two-phase selection. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
Addressed both review comments in 6748389:
(Note: there's a stray empty pending review on this PR from a failed reply attempt — you may want to discard it in the UI; I wasn't permitted to delete it.) |
Live capture showed the old command produced ~24 noise rows alongside the real ~650-bit packets, and the default detector fragments the weaker far-unit packet. -Y minmax selects the FSK peak detector (recovers 8 clean ~650-bit packets from a 4-event replay) and bits>=400 drops the sub-100-bit noise rows. Also document why decode_mc is unusable here. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
Improved the flex The old
New command: Also documented (both in |
The C decoder anchors on the Manchester-decoded fd 7a header. Map that same
sync into the flex command's raw (Manchester-encoded) domain: decoded fd 7a
encodes to raw 0x5559 0x9566, so preamble={32}55599566 aligns every packet to
the header. Verified against uclean_offset.cu8: all 8 packets anchor at fd7a
and line up byte-for-byte. (decode_mc still confirmed unusable - collapses to
0-4 bit rows - so it stays out of the flex command.)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The exact 32-bit preamble match runs in the raw (Manchester-encoded) domain, so one noise-flipped bit in the fd7a sync drops the whole packet. On a live capture this loses the weaker far-unit packet of an exchange, showing one message instead of two. Restore the no-preamble bits>=400 command as the primary capture-pass recommendation (catches every message); keep preamble only as an optional alignment aid for clean signals, with the tradeoff spelled out. The C decoder does not have this problem: it Manchester-decodes with tolerance first, then bit-searches fd7a. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The demodulator-level FSK_MC_ZEROBIT slicer decodes Manchester straight from pulse timing, unlike the decode_mc post-filter (which aborts on the first violation and is unusable here). With s=10 (half-bit) and invert to match the 01->1/10->0 convention, it prints the decoded bytes directly - the fd 7a ba ba ba 83 header comes out verbatim - with full recall (all 8 packets of a 4-event replay), and none of the exact-match preamble fragility. Make it the primary flex first-pass command; keep FSK_PCM raw + optional preamble as the inspect-raw-bits alternative. Verified against uclean_offset.cu8. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add section 0c with the two on-air frames actually recovered (poll + response), byte-identical across ~35 min of capture. Documents the framing structure found without display correlation: no counter/rolling code, a constant 0x1b type byte, and a swapped pair of 3-byte node-ID fields (03 5b / 08 d2) between poll and response. Gives future display-correlated captures a fixed diff target for [U6]. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Now that the link is confirmed Manchester (validated against the FSK_MC_ZEROBIT flex demod), switch the r_device from FSK_PULSE_PCM with a hand-rolled two-phase Manchester pass to FSK_PULSE_MANCHESTER_ZEROBIT. The framework hands back already-decoded data bits, so drop the custom uclean1_manchester()/uclean1_bit()/uclean1_bitsearch() helpers and the illegal-pair quality gate. The decode fn now just anchors on fd7a with bitbuffer_search (retrying inverted for polarity) and extracts header + payload. Removes the mc_illegal output field. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Match the product's retail name "Uponor Clean 1", mapping spaces to hyphens per the rtl_433 model-string convention (Brand-Model, no spaces). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Summary
01->1,10->0), ~40 bytes/packet, constantfd7a bababa 83header, near-static telemetry sent as a two-packet exchange every ~62 s. Demods at 100 kbps, Manchester-decodes both bit phases and keeps the cleaner one, anchors onfd7a, emits header + raw payload hex. Shipsdisabled=1until fields/CRC are pinned down.docs/rtl433.md: capture procedure, empirical results, and a firmware section. Ghidra analysis of the MC9S08 flash shows the on-air byte layout is not in the CPU — it is only an SPI slave on a custom MC9S08<->8051 message bus; the nRF9E5's 8051 owns framing/Manchester. Firmware does give the decode targets (alarm-code and setpoint tables), so field mapping ([U6]) needs a display-correlated capture.DumpBytes,FindRefsInRange,ForceDecompile..gitignoreignores*.cu8(large IQ captures stay local).Test plan
tools/rtl433/uponor_clean1.cintosrc/devices/, register ininclude/rtl_433_devices.h+src/CMakeLists.txt,cmake && make).-R <num>(decoder is disabled by default) and confirm it emits thefd7a bababa 83header + payload hex.[U6]) still require a display-correlated capture before enabling.🤖 Generated with Claude Code