RS-11.5 legs D–F: TX digital path proven clean in-firmware; corruption follows the receiver; overload refuted - #94
Merged
Merged
Conversation
…are space closed New diagnostic gate LIFETRAC_RXCONT_ARM (daemon env + harness -RxcontArm, production default 1): 0 disables all RXCONT arming so the firmware's RS-4.12 re-arm chain never starts and the radio sits in STANDBY between fragments. NEVER ship 0 — in-stream command delivery (99.8%) lives in those listening gaps and inter-train-only delivery would blow the 700 ms control latency budget. Leg C result (300 s @ 3000 B, probe-bracketed, archive committed): the slot-(total-2) spike is UNCHANGED with no turnaround cycling (idx11 22/66 attributed, CRC delta +62 vs +75/+80 in legs A/B). With this, every software-layer candidate is eliminated; the corruption is physical/silicon in the TX chain or deterministic self-EMI. Next discriminators need a flash session (post-TX FIFO readback CRC, measured TX duration in RFCO, IRQ-flag capture) or an SDR capture. Also recorded: idle-bench ambient false-demod CRC floor ~4/h (negligible vs 62-80 per 300 s run). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…TX_DONE Instruments the L072 TX path to discriminate the slot-(total-2) on-air CRC corruption (all software layers exonerated by legs A-C): - Load-time DJB checksum over the FIFO content (hop header + payload); after TX_DONE the FIFO is re-read in 32-byte chunks (SX1276 retains it in STANDBY) and compared. Mismatch = the radiated bits were corrupt at the source. - TX_DONE arriving >5 ms before the expected ToA = truncated radiation (poll latency only ever lengthens the measurement — no false positives). Reporting: three additive STATS counters (payload 132->144; host parse_stats label lists are offset-guarded and updated) plus FAULT URCs 0x0D/0x0E whose sub byte carries the fragment tx_id (== index), so the tx daemon log shows WHICH slot misbehaved. The readback costs ~1-2 ms inside the ~17 ms inter-fragment gap; if the corruption vanishes under instrumentation, that timing sensitivity is itself a finding. Bench stubs extended for check-tx-len-guard. All 27 check targets PASS; size budget PASS (23,388 B / 184 KB). Note: check_mh_wire_sync remains red as on main (pre-existing H7/L072 schema drift, 68 vs now 144). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… on air Leg D (instrumented firmware, flashed): 2468/2468 FIFO readbacks intact, zero early TX_DONEs, zero FAULTs — while the base still took +110 CRC errors. The transmitter's digital path (host feed -> mailbox -> FIFO -> duration) is exonerated by direct measurement; corruption enters between modulator and demodulator. Leg E (role swap) aborted with no data: the harness TX image exists only on the tractor and lifetrac-v25 lacks numpy for the synth publisher. Learned in passing: the SWD reset path works on the base board (its L072 counters now zeroed — substitute for the dead gpio163), and the proper swap recipe is -TxFeed host with the tx daemon in lifetrac-v25. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…; overload refuted Leg E' (manual role swap, base TX via PC-broker host feed): both boards corrupt as receivers, both clean as transmitters — unit hardware defect eliminated. Shape is board-specific: tractor-as-RX 6.6% UNIFORM across the train; base-as-RX 3-4.5% locked at slot total-2. Leg F (new LIFETRAC_TX_POWER_DBM host knob, CFG_SET at startup, can only lower below the ERP ceiling): 2 dBm vs 14 dBm leaves the CRC rate unchanged (3.9%) — front-end overload refuted. The overnight idle floor (~4 CRC/h vs 75-170 per 300 s active) refutes ambient interference. Final diagnosis state: ~4% of our own fragments arrive payload-corrupt at the receiver, both directions, power-independent, TX digital path proven intact in-firmware. Remaining: receiver-side host/board coupling or board EMI. Next: physical separation test (needs hands) or RX-side firmware capture increment. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR continues the RS-11.5 on-air corruption investigation by adding firmware-level TX-path discriminators (FIFO post-TX readback + early-TX_DONE detection), extending host-visible stats/fault reporting, and adding host-side harness knobs to run discriminating bench legs (RXCONT disable and TX power override). The accompanying bench-evidence updates document legs C and D–F and the resulting narrowed hypothesis space (corruption follows the receiver; TX digital path and overload refuted).
Changes:
- Add Murata L072 firmware instrumentation to detect TX FIFO mutation and truncated transmissions, reporting via new STATS counters and FAULT URCs.
- Extend host STATS payload/parsing to include the new discriminator counters.
- Add host/harness controls for RS-11.5 diagnostics (
LIFETRAC_RXCONT_ARM,LIFETRAC_TX_POWER_DBM) and update bench evidence/TODO narrative.
Reviewed changes
Copilot reviewed 14 out of 26 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| LifeTrac-v25/DESIGN-CONTROLLER/TODO.md | Updates the running RS-11.5 investigation notes with legs C and D–F conclusions and next steps. |
| LifeTrac-v25/DESIGN-CONTROLLER/firmware/x8_lora_bootloader_helper/run_live_radio_monitor.ps1 | Adds -RxcontArm harness parameter and plumbs it into the TX daemon container env. |
| LifeTrac-v25/DESIGN-CONTROLLER/firmware/x8_lora_bootloader_helper/rs115_stats_probe.py | Updates stats probe to print the newly added discriminator counters. |
| LifeTrac-v25/DESIGN-CONTROLLER/firmware/x8_lora_bootloader_helper/method_g_stage1_probe.py | Extends STATS label list to parse the new additive counters with length guards. |
| LifeTrac-v25/DESIGN-CONTROLLER/firmware/tractor_x8/image_tx_daemon.py | Adds LIFETRAC_RXCONT_ARM gate and LIFETRAC_TX_POWER_DBM CFG_SET diagnostic override. |
| LifeTrac-v25/DESIGN-CONTROLLER/firmware/murata_l072/radio/sx1276_tx.c | Implements TX discriminators: FIFO checksum at load, post-TX FIFO readback compare, and early-TX_DONE timing check with fault emission. |
| LifeTrac-v25/DESIGN-CONTROLLER/firmware/murata_l072/include/host_types.h | Extends STATS wire payload length/offsets and adds new fault codes 0x0D/0x0E. |
| LifeTrac-v25/DESIGN-CONTROLLER/firmware/murata_l072/include/host_stats.h | Declares new host_stats increment functions for the discriminator counters. |
| LifeTrac-v25/DESIGN-CONTROLLER/firmware/murata_l072/host/host_stats.c | Adds storage/serialization for the new discriminator counters at the STATS tail. |
| LifeTrac-v25/DESIGN-CONTROLLER/firmware/murata_l072/bench/host_proto/tx_len_guard.c | Adds stubs needed for the new TX discriminator hooks in host-compiled bench tests. |
| LifeTrac-v25/DESIGN-CONTROLLER/bench-evidence/RS_11_4_train_length_sweep_2026-08-02/RESULTS.md | Documents leg C and legs D–F results and the updated diagnosis. |
| LifeTrac-v25/DESIGN-CONTROLLER/bench-evidence/RS_11_4_train_length_sweep_2026-08-02/leg_f_rx_extract.log | Evidence artifact referenced by RESULTS updates. |
| LifeTrac-v25/DESIGN-CONTROLLER/bench-evidence/RS_11_4_train_length_sweep_2026-08-02/leg_f_power_drop.log | Evidence log for the TX power drop discriminator run (leg F). |
| LifeTrac-v25/DESIGN-CONTROLLER/bench-evidence/RS_11_4_train_length_sweep_2026-08-02/leg_e_swap_rx_extract.log | Evidence log for the manual role-swap discriminator run (leg E′). |
| LifeTrac-v25/DESIGN-CONTROLLER/bench-evidence/radio_monitor_20260802_110209_87821c90/tx_daemon.log | Archived harness output for an aborted run attempt. |
| LifeTrac-v25/DESIGN-CONTROLLER/bench-evidence/radio_monitor_20260802_110209_87821c90/synth_pub.log | Archived harness output for an aborted run attempt. |
| LifeTrac-v25/DESIGN-CONTROLLER/bench-evidence/radio_monitor_20260802_110209_87821c90/rx_daemon.log | Archived harness output for an aborted run attempt. |
| LifeTrac-v25/DESIGN-CONTROLLER/bench-evidence/radio_monitor_20260802_110209_87821c90/params.txt | Archived parameter capture for an aborted run attempt. |
| LifeTrac-v25/DESIGN-CONTROLLER/bench-evidence/radio_monitor_20260802_105435_87821c90/tx_daemon.log | Archived TX daemon log for the instrumented-firmware run (leg D context). |
| LifeTrac-v25/DESIGN-CONTROLLER/bench-evidence/radio_monitor_20260802_105435_87821c90/synth_pub.log | Archived synthetic publisher log for the instrumented-firmware run. |
| LifeTrac-v25/DESIGN-CONTROLLER/bench-evidence/radio_monitor_20260802_105435_87821c90/rx_daemon.log | Archived RX daemon log for the instrumented-firmware run. |
| LifeTrac-v25/DESIGN-CONTROLLER/bench-evidence/radio_monitor_20260802_105435_87821c90/params.txt | Archived parameter capture for the instrumented-firmware run. |
| LifeTrac-v25/DESIGN-CONTROLLER/bench-evidence/radio_monitor_20260802_094053_86bf5d7f/tx_daemon.log | Archived TX daemon log for the RXCONT-disabled run (leg C context). |
| LifeTrac-v25/DESIGN-CONTROLLER/bench-evidence/radio_monitor_20260802_094053_86bf5d7f/synth_pub.log | Archived synthetic publisher log for the RXCONT-disabled run. |
| LifeTrac-v25/DESIGN-CONTROLLER/bench-evidence/radio_monitor_20260802_094053_86bf5d7f/rx_daemon.log | Archived RX daemon log for the RXCONT-disabled run. |
| LifeTrac-v25/DESIGN-CONTROLLER/bench-evidence/radio_monitor_20260802_094053_86bf5d7f/params.txt | Archived parameter capture for the RXCONT-disabled run. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+133
to
+134
| # corruption mechanism). Production default 1. | ||
| [int]$RxcontArm = 1, |
Comment on lines
+608
to
+622
| # RS-11.5 diagnostic (2026-08-02): optional TX power override for the | ||
| # front-end-overload discriminator (bench antennas sit inches apart | ||
| # at the default 14 dBm). Empty = leave the firmware default alone. | ||
| # Regulatory: the firmware's ERP clamp still applies — this can only | ||
| # LOWER power below the configured ceiling on the bench. | ||
| tx_dbm = _os.environ.get("LIFETRAC_TX_POWER_DBM", "").strip() | ||
| if tx_dbm: | ||
| try: | ||
| dbm = int(tx_dbm) | ||
| link.request(HOST_TYPE_CFG_SET_REQ, HOST_TYPE_CFG_OK_URC, | ||
| bytes([CFG_KEY_TX_POWER_DBM, 0x01, dbm & 0xFF]), | ||
| timeout=1.0) | ||
| LOG.warning("RS-11.5 diagnostic: TX_POWER_DBM=%d", dbm) | ||
| except Exception as exc: # pragma: no cover | ||
| LOG.warning("CFG_SET(TX_POWER_DBM=%s) failed: %s", tx_dbm, exc) |
New RX_CRC_DUMP_URC (0xC5): on every payload-CRC failure the L072 ships
IRQ flags, packet RSSI/SNR, length, and the corrupt bytes (reuses the
caller's frame buffer; ~0.3/s at the observed rate). Both boards
flashed; rx daemon logs each dump; 126 captured in one 300 s run.
The dumps answer everything: our fragments arrive at -97 dBm mean /
~0-6 dB SNR — the bench deliberately runs ANTENNA-LESS (HIL_RUNBOOK:
"no antennas attached") on leakage coupling, and the ~4% loss is
ordinary noise-floor single-bit corruption ("WEBP"->"WMBP"-class
flips), uniform across positions, no truncation or fill patterns.
Reassessed per the corrections discipline: the penultimate "position
lock" was an attribution-observability artifact (dump-level truth is
uniform — trust the instrument as a counter, not its per-index shape);
leg F softens to "the corrupt fraction is set by the floor-adjacent
regime" (the 2 dBm CFG did reach the PA; overload still refuted).
RS-11.5 closed: fix = the pending antenna installation; RS-11.6 queued
for the post-antenna re-baseline. Also adds LIFETRAC_TX_POWER_DBM
(diagnostic, ERP-clamped) from leg F. Suite 1103/2446; 27 fw checks +
size budget PASS.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ough the TX-RFO arm Operator input corrected the RS-11.5 closure: the bench has antennas (Wurth Hermippe-III 868 MHz 2.5 dBi SMA on both Max Carriers) — the "antenna-less by design" reading mis-generalized a HIL_RUNBOOK line about the H7 rig. With antennas present, -97 dBm at bench range was ~60 dB of missing budget, and the firmware audit found it: the ABZ switch truth table is PA1=CRF1 (RX), PC1=CRF2 (TX-RFO), PC2=CRF3 (PA_BOOST), exactly one high per mode — but both switch drivers treated PA1 as a TX/RX direction pin and drove the TX-RFO arm high in RX. Fixed in sx1276.c and sx1276_modes.c. Leg H verification (both boards reflashed, archive committed): corrupt-dump RSSI mean -96.8 -> -64.3 dBm (+33 dB recovered). SNR stayed at ~+1.7 mean — the noise floor rose WITH the signal, i.e. the remaining limiter is broadband interference entering the same antenna path (bench-local EMI; USB3/DDR at ~900 MHz is the prime suspect, and it also explains leg F's null on the broken switch: signal and interference were attenuated together). Legs I/J (2 vs 17 dBm on the fixed switch) run the SIR discriminator; harness gains -TxPowerDbm. Also records the 868-vs-915 MHz antenna detuning (few dB, secondary; US-band swap worth queuing). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…lf-interference Power sweep on the fixed switch (new -TxPowerDbm): 2 dBm -> 6.3% loss, 14 -> 5.4%, 17 -> 4.0% — mildly power-responsive, and the corrupt population sits at ~+2 dB SNR at every power and both switch configs (noise tracks our own signal across ~48 dB of combined change). A fixed external interferer cannot do that: the residual floor is signal-proportional self-interference at bench geometry (close-range multipath / near-field coupling, detuned 868 MHz antennas). Final closure: (1) the ABZ switch-mapping bug is fixed, +33 dB verified — ships regardless of bench; (2) the residual ~4% floor at 17 dBm awaits the antenna-position experiment (RS-11.6, user's hands-on task) on a rig that now reads corrupt packets directly; (3) bench runs get a free ~1.4x loss cut at -TxPowerDbm 17. Caveat recorded: healthy-frame SNR logging is the missing instrument. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…H31) Operator decision 2026-08-02: field antennas will be Taoglas TD.95.6H31 Blade (868/915 MHz dual-band omnidirectional dipole, terminal mount) — properly tuned for the 902-928 MHz operating band, unlike the bench's 868-only Hermippe-III units. ~2 dBi-class gain sits under the FCC §15.247 6 dBi threshold, so no ERP power reduction; the datasheet gain goes into the field profile's antenna_gain CFG at provisioning. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…dation, power clamp Copilot findings, all valid: - Archived params.txt now records rxcont_arm and tx_power_dbm (the two new run-affecting knobs were invisible in evidence bundles — the PR #93 catch, applied here on the stacked branch). - -RxcontArm gets [ValidateSet(0,1)] — any non-1 int silently disabled RXCONT (the daemon checks == "1"). - LIFETRAC_TX_POWER_DBM is range-checked host-side to 2..17 before the wire: a negative value wrapped via & 0xFF to 255, which the firmware normalizes DOWN to 17 dBm — junk input could silently RAISE power. Out-of-range now warns and leaves the profile default. Suite 1103/2446 green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Continues the RS-11.5 investigation from PR #93 with experimental firmware and three on-air discriminating legs. Full record in
bench-evidence/RS_11_4_train_length_sweep_2026-08-02/RESULTS.md§9–§14.New firmware instrumentation (flashed to the tractor, SWD/AN3155, RC=0)
LIFETRAC_TX_POWER_DBM(CFG_SET at startup; can only lower below the ERP-clamped ceiling) and the leg-CLIFETRAC_RXCONT_ARMfrom PR RS-11.5 leg C: RXCONT turnaround exonerated — software discriminator space closed #93.The three legs
Plus the §8 idle-floor argument: ~4 false-demod CRC events/hour when idle vs 75–170 per 300 s active — ambient interference refuted three orders of magnitude over.
Where the diagnosis now stands
~4% of our own fragments arrive payload-corrupt at the receiver (header demodulates, payload CRC fails), in both directions, at both power levels, with the transmit chain proven intact. Everything software, everything digital-TX, overload, ambient RF, and unit-specific hardware are eliminated by measurement. Remaining hypothesis space: receiver-side host/board coupling into demodulation (the base's train-position lock hints at something periodic on the receiving host) or board-level EMI with per-board signatures.
Recommended next steps (in the TODO): a physical separation/orientation change at the bench (requires hands — no RF gear available), or an RX-side firmware capture increment (IRQ flags + RSSI + corrupt-payload dump) as the next flash session.
Bench state: daemons stopped, radios idle; the tractor L072 runs the instrumented build (production-equivalent + additive diagnostics); TX power reverts to the profile default at next daemon startup without the env.
Suite: 1103/2446 green. The known-red
check_mh_wire_syncremains red as on main (pre-existing H7/L072 schema drift; the additive STATS growth is noted there).🤖 Generated with Claude Code