From 9d76820ef6edfe25202fa3daf5436fb799328a5d Mon Sep 17 00:00:00 2001 From: Aiden <68633820+awils27@users.noreply.github.com> Date: Wed, 13 May 2026 16:24:13 +1000 Subject: [PATCH] run 6 --- .../rcp-buttons-call-exact-echo-repro-1.txt | 29 +++++ .../rcp-buttons-call-exact-echo-repro-2.txt | 33 +++++ .../rcp-buttons-call-exact-echo-repro-3.txt | 19 +++ ...ttons-latched-call-mirror-hold-release.txt | 116 ++++++++++++++++++ docs/discovery-notes.md | 113 +++++++++++++++++ scripts/serial_button_response_test.py | 56 ++++++++- 6 files changed, 365 insertions(+), 1 deletion(-) create mode 100644 captures/rcp-buttons-call-exact-echo-repro-1.txt create mode 100644 captures/rcp-buttons-call-exact-echo-repro-2.txt create mode 100644 captures/rcp-buttons-call-exact-echo-repro-3.txt create mode 100644 captures/rcp-buttons-latched-call-mirror-hold-release.txt diff --git a/captures/rcp-buttons-call-exact-echo-repro-1.txt b/captures/rcp-buttons-call-exact-echo-repro-1.txt new file mode 100644 index 0000000..054fd56 --- /dev/null +++ b/captures/rcp-buttons-call-exact-echo-repro-1.txt @@ -0,0 +1,29 @@ +Button test on COM5 at 38400 8N1 +Listening for 15.0s; respond_to_cam_power=False, respond_to_call=True, mirror_call=False +16:23:12.184 RX 006 bytes 00 00 00 00 80 DA +16:23:12.184 DETECT heartbeat x1 +16:23:12.794 RX 006 bytes 00 00 15 80 00 CF +16:23:12.794 DETECT call-on x1 +16:23:12.846 TX button response frame 006 00 00 15 80 00 CF +16:23:12.846 TX button response frame 006 00 00 15 00 00 4F +16:23:14.794 RX 006 bytes 00 00 00 00 80 DA +16:23:14.794 DETECT heartbeat x1 +16:23:15.465 RX 001 bytes 00 +16:23:15.496 RX 005 bytes 00 00 00 80 DA +16:23:16.164 RX 001 bytes 00 +16:23:16.194 RX 005 bytes 00 00 00 80 DA +16:23:16.866 RX 001 bytes 00 +16:23:16.897 RX 005 bytes 00 00 00 80 DA +16:23:17.263 RX 006 bytes 00 00 15 80 00 CF +16:23:17.263 DETECT call-on x1 +16:23:17.813 RX 001 bytes 00 +16:23:17.861 RX 005 bytes 00 15 00 00 4F +16:23:18.472 RX 001 bytes 00 +16:23:18.523 RX 005 bytes 00 00 00 80 DA +16:23:19.163 RX 001 bytes 00 +16:23:19.194 RX 005 bytes 00 00 00 80 DA +16:23:19.866 RX 001 bytes 00 +16:23:19.898 RX 005 bytes 00 00 00 80 DA +16:23:20.566 RX 001 bytes 00 +16:23:20.596 RX 005 bytes 00 00 00 80 DA +Stopped. diff --git a/captures/rcp-buttons-call-exact-echo-repro-2.txt b/captures/rcp-buttons-call-exact-echo-repro-2.txt new file mode 100644 index 0000000..bc62878 --- /dev/null +++ b/captures/rcp-buttons-call-exact-echo-repro-2.txt @@ -0,0 +1,33 @@ +Button test on COM5 at 38400 8N1 +Listening for 15.0s; respond_to_cam_power=False, respond_to_call=True, mirror_call=False +16:23:34.651 RX 001 bytes 00 +16:23:34.681 RX 005 bytes 00 00 00 80 DA +16:23:35.352 RX 001 bytes 00 +16:23:35.382 RX 005 bytes 00 00 00 80 DA +16:23:36.048 RX 001 bytes 00 +16:23:36.080 RX 005 bytes 00 00 00 80 DA +16:23:36.630 RX 006 bytes 00 00 15 80 00 CF +16:23:36.630 DETECT call-on x1 +16:23:36.681 TX button response frame 006 00 00 15 80 00 CF +16:23:36.681 TX button response frame 006 00 00 15 00 00 4F +16:23:36.714 RX 006 bytes 07 80 45 20 D0 68 +16:23:36.714 DETECT watch-frame 07 80 45 20 D0 68 x1 +16:23:37.355 RX 001 bytes 00 +16:23:37.386 RX 005 bytes 00 00 00 80 DA +16:23:37.629 RX 006 bytes 00 00 00 00 80 DA +16:23:37.629 DETECT heartbeat x1 +16:23:37.872 RX 006 bytes 00 00 00 00 80 DA +16:23:37.872 DETECT heartbeat x1 +16:23:38.118 RX 006 bytes 00 00 00 00 80 DA +16:23:38.118 DETECT heartbeat x1 +16:23:38.361 RX 001 bytes 00 +16:23:38.393 RX 005 bytes 00 00 00 80 DA +16:23:38.606 RX 001 bytes 00 +16:23:38.636 RX 005 bytes 00 00 00 80 DA +16:23:39.277 RX 006 bytes 00 00 00 00 80 DA +16:23:39.277 DETECT heartbeat x1 +16:23:39.978 RX 006 bytes 00 00 00 00 80 DA +16:23:39.978 DETECT heartbeat x1 +16:23:40.649 RX 001 bytes 00 +16:23:40.679 RX 005 bytes 00 00 00 80 DA +Stopped. diff --git a/captures/rcp-buttons-call-exact-echo-repro-3.txt b/captures/rcp-buttons-call-exact-echo-repro-3.txt new file mode 100644 index 0000000..d215788 --- /dev/null +++ b/captures/rcp-buttons-call-exact-echo-repro-3.txt @@ -0,0 +1,19 @@ +Button test on COM5 at 38400 8N1 +Listening for 15.0s; respond_to_cam_power=False, respond_to_call=True, mirror_call=False +16:23:53.557 RX 006 bytes 00 00 00 00 80 DA +16:23:53.557 DETECT heartbeat x1 +16:23:54.257 RX 006 bytes 00 00 00 00 80 DA +16:23:54.257 DETECT heartbeat x1 +16:23:54.840 RX 006 bytes 00 00 15 80 00 CF +16:23:54.840 DETECT call-on x1 +16:23:54.891 TX button response frame 006 00 00 15 80 00 CF +16:23:54.891 TX button response frame 006 00 00 15 00 00 4F +16:23:56.878 RX 006 bytes 00 00 00 00 80 DA +16:23:56.878 DETECT heartbeat x1 +16:23:57.550 RX 001 bytes 00 +16:23:57.580 RX 005 bytes 00 00 00 80 DA +16:23:58.251 RX 001 bytes 00 +16:23:58.282 RX 005 bytes 00 00 00 80 DA +16:23:58.953 RX 001 bytes 00 +16:23:58.983 RX 005 bytes 00 00 00 80 DA +Stopped. diff --git a/captures/rcp-buttons-latched-call-mirror-hold-release.txt b/captures/rcp-buttons-latched-call-mirror-hold-release.txt new file mode 100644 index 0000000..ee7a0b3 --- /dev/null +++ b/captures/rcp-buttons-latched-call-mirror-hold-release.txt @@ -0,0 +1,116 @@ +Button test on COM5 at 38400 8N1 +16:18:46.109 TX latch primer frame 006 00 00 00 00 80 DA +LATCH PRIMER RX 24 bytes; heartbeat=4 +16:18:47.118 TX latch query frame 006 00 00 B5 00 80 6F +LATCH QUERY RX 30 bytes; no known complete frames +Listening for 30.0s; respond_to_cam_power=False, respond_to_call=False, mirror_call=True +16:18:52.018 RX 048 bytes 07 80 6D 20 D8 48 07 80 6D 20 D8 48 07 80 6D 20 D8 48 00 00 00 00 80 DA 00 00 15 00 00 4F 00 00 00 00 80 DA 00 00 00 00 80 DA 00 00 00 00 80 DA +16:18:52.018 DETECT heartbeat x4 +16:18:52.018 DETECT call-off x1 +16:18:52.020 TX CALL low mirror frame 006 00 00 15 00 00 4F +16:18:52.324 RX 006 bytes 00 00 15 80 00 CF +16:18:52.324 DETECT call-on x1 +16:18:52.324 TX CALL high mirror frame 006 00 00 15 80 00 CF +16:18:52.355 RX 006 bytes 00 00 15 80 00 CF +16:18:52.355 DETECT call-on x1 +16:18:52.600 RX 006 bytes 00 00 15 80 00 CF +16:18:52.600 DETECT call-on x1 +16:18:52.873 RX 006 bytes 00 00 15 80 00 CF +16:18:52.873 DETECT call-on x1 +16:18:53.117 RX 006 bytes 00 00 15 80 00 CF +16:18:53.117 DETECT call-on x1 +16:18:53.360 RX 006 bytes 00 00 15 80 00 CF +16:18:53.360 DETECT call-on x1 +16:18:53.603 RX 006 bytes 00 00 15 80 00 CF +16:18:53.603 DETECT call-on x1 +16:18:53.879 RX 006 bytes 00 00 15 80 00 CF +16:18:53.879 DETECT call-on x1 +16:18:54.122 RX 006 bytes 00 00 15 80 00 CF +16:18:54.122 DETECT call-on x1 +16:18:54.761 RX 012 bytes 00 00 00 00 80 DA 00 00 15 00 00 4F +16:18:54.761 DETECT heartbeat x1 +16:18:54.761 DETECT call-off x1 +16:18:55.465 RX 006 bytes 00 00 00 00 80 DA +16:18:55.465 DETECT heartbeat x1 +16:18:56.164 RX 006 bytes 00 00 00 00 80 DA +16:18:56.164 DETECT heartbeat x1 +16:18:56.864 RX 006 bytes 00 00 00 00 80 DA +16:18:56.864 DETECT heartbeat x1 +16:18:57.563 RX 006 bytes 00 00 00 00 80 DA +16:18:57.563 DETECT heartbeat x1 +16:18:58.264 RX 006 bytes 00 00 00 00 80 DA +16:18:58.264 DETECT heartbeat x1 +Stopped. +Button test on COM5 at 38400 8N1 +16:19:14.306 TX latch primer frame 006 00 00 00 00 80 DA +LATCH PRIMER RX 24 bytes; heartbeat=4 +16:19:15.313 TX latch query frame 006 00 00 B5 00 80 6F +LATCH QUERY RX 24 bytes; heartbeat=4 +Listening for 30.0s; respond_to_cam_power=False, respond_to_call=False, mirror_call=True +16:19:18.525 RX 036 bytes 00 00 00 00 80 DA 00 00 00 00 80 DA 00 00 00 00 80 DA 00 00 00 00 80 DA 00 00 00 00 80 DA 00 00 00 00 80 DA +16:19:18.525 DETECT heartbeat x6 +16:19:18.985 RX 006 bytes 00 00 15 80 00 CF +16:19:18.985 DETECT call-on x1 +16:19:18.985 TX CALL high mirror frame 006 00 00 15 80 00 CF +16:19:19.658 RX 006 bytes 00 00 00 00 80 DA +16:19:19.658 DETECT heartbeat x1 +16:19:19.904 RX 001 bytes 00 +16:19:19.935 RX 005 bytes 00 00 00 80 DA +16:19:20.147 RX 001 bytes 00 +16:19:20.178 RX 005 bytes 00 00 00 80 DA +16:19:20.422 RX 006 bytes 00 00 00 00 80 DA +16:19:20.422 DETECT heartbeat x1 +16:19:20.666 RX 006 bytes 00 00 00 00 80 DA +16:19:20.666 DETECT heartbeat x1 +16:19:20.910 RX 001 bytes 00 +16:19:20.941 RX 005 bytes 00 00 00 80 DA +16:19:21.551 RX 001 bytes 00 +16:19:21.581 RX 005 bytes 00 00 00 80 DA +16:19:22.253 RX 001 bytes 00 +16:19:22.284 RX 005 bytes 00 00 00 80 DA +16:19:22.528 RX 006 bytes 00 00 15 80 00 CF +16:19:22.528 DETECT call-on x1 +16:19:23.168 RX 007 bytes 00 00 00 00 80 DA 00 +16:19:23.168 DETECT heartbeat x1 +16:19:23.199 RX 005 bytes 00 15 00 00 4F +16:19:23.199 TX CALL low mirror frame 006 00 00 15 00 00 4F +16:19:23.870 RX 006 bytes 00 00 00 00 80 DA +16:19:23.870 DETECT heartbeat x1 +16:19:24.113 RX 006 bytes 00 00 00 00 80 DA +16:19:24.113 DETECT heartbeat x1 +16:19:24.357 RX 001 bytes 00 +16:19:24.388 RX 005 bytes 00 00 00 80 DA +16:19:24.602 RX 001 bytes 00 +16:19:24.633 RX 005 bytes 00 00 00 80 DA +Stopped. +Button test on COM5 at 38400 8N1 +16:19:31.700 TX latch primer frame 006 00 00 00 00 80 DA +LATCH PRIMER RX 24 bytes; heartbeat=4 +16:19:32.707 TX latch query frame 006 00 00 B5 00 80 6F +LATCH QUERY RX 30 bytes; no known complete frames +Listening for 30.0s; respond_to_cam_power=False, respond_to_call=False, mirror_call=True +16:19:36.283 RX 042 bytes 07 80 6D 20 D8 48 07 80 6D 20 D8 48 07 80 6D 20 D8 48 07 80 6D 20 D8 48 00 00 00 00 80 DA 00 00 15 00 00 4F 00 00 00 00 80 DA +16:19:36.283 DETECT heartbeat x2 +16:19:36.283 DETECT call-off x1 +16:19:36.283 TX CALL low mirror frame 006 00 00 15 00 00 4F +16:19:36.833 RX 006 bytes 00 00 00 00 80 DA +16:19:36.833 DETECT heartbeat x1 +16:19:37.077 RX 001 bytes 00 +16:19:37.107 RX 005 bytes 00 00 00 80 DA +16:19:37.321 RX 001 bytes 00 +16:19:37.352 RX 005 bytes 00 00 00 80 DA +16:19:37.595 RX 006 bytes 00 00 00 00 80 DA +16:19:37.595 DETECT heartbeat x1 +16:19:37.842 RX 006 bytes 00 00 00 00 80 DA +16:19:37.842 DETECT heartbeat x1 +16:19:38.085 RX 001 bytes 00 +16:19:38.116 RX 005 bytes 00 00 00 80 DA +16:19:38.725 RX 001 bytes 00 +16:19:38.756 RX 005 bytes 00 00 00 80 DA +16:19:38.878 RX 006 bytes 00 00 15 00 00 4F +16:19:38.878 DETECT call-off x1 +16:19:39.546 RX 006 bytes 00 00 00 00 80 DA +16:19:39.546 DETECT heartbeat x1 +16:19:40.248 RX 006 bytes 00 00 00 00 80 DA +16:19:40.248 DETECT heartbeat x1 +Stopped. diff --git a/docs/discovery-notes.md b/docs/discovery-notes.md index 73029a5..e66d311 100644 --- a/docs/discovery-notes.md +++ b/docs/discovery-notes.md @@ -2731,3 +2731,116 @@ Next CALL-focused checks: which of the two echoed frames causes `07 80 45 20 D0 68`. 3. Try using `07 80 45 20 D0 68` as a follow-up host frame after CALL exact echo, only after confirming repeatability. + +### Real-World CALL Hold/Release Test + +Goal: mimic how CALL would likely work in use: + +```text +User holds CALL -> RCP sends CALL high/on +Host responds high -> host echoes/acknowledges CALL high/on +User releases CALL -> RCP sends CALL low/off +Host responds low -> host echoes/acknowledges CALL low/off +``` + +Test BTN8: mirror CALL high and low once per state. + +```powershell +python scripts/serial_button_response_test.py --port COM5 --duration 30 --prompt --mirror-call --mirror-call-once-per-state --log captures/rcp-buttons-call-mirror-hold-release.txt +``` + +Procedure: + +1. Power-cycle the RCP. +2. Start the command and press Enter at the prompt. +3. Hold `CALL` for about 2 seconds. +4. Release `CALL`. +5. Watch whether the screen changes and note the final screen text. + +Interpretation: + +- If the RCP again sends `07 80 45 20 D0 68`, the frame is likely part of the + CALL response path. +- If the screen still ends at `CONNECT NOT ACT`, this mirrors CALL signaling but + still does not satisfy the active-session handshake. + +Optional latched version: + +```powershell +python scripts/serial_button_response_test.py --port COM5 --latch --latch-query-command 0xB5 --duration 30 --prompt --mirror-call --mirror-call-once-per-state --log captures/rcp-buttons-latched-call-mirror-hold-release.txt +``` + +### 2026-05-13 Latched CALL Mirror Result + +Capture: + +- `captures/rcp-buttons-latched-call-mirror-hold-release.txt` + +The capture contains three appended latched runs. Each run sent the `00 -> B5` +latch setup, then mirrored observed CALL high/low events with the matching CALL +frame. + +Observed result: + +- The RCP still emitted CALL high/low frames while latched. +- The mirror script sent `CALL high mirror` and/or `CALL low mirror` responses + as expected. +- No run reproduced the earlier exact-echo response + `07 80 45 20 D0 68`. +- Serial output returned to heartbeat/CALL event traffic. + +Interpretation: + +- The earlier `07 80 45 20 D0 68` response appears tied to sending both CALL + echo frames immediately after CALL high, not to a realistic held/released CALL + mirror sequence. +- Mirroring CALL state while latched does not appear to activate or unlatch the + RCP. +- The latched state continues to allow front-panel CALL events to be transmitted. + +Tooling note: + +- `scripts/serial_button_response_test.py` now clears the serial input buffer + immediately after the manual prompt. This avoids stale frames collected while + waiting at the prompt contaminating button timing in future hold/release + tests. + +Clean non-latched repeat, if needed: + +```powershell +python scripts/serial_button_response_test.py --port COM5 --duration 30 --prompt --mirror-call --mirror-call-once-per-state --log captures/rcp-buttons-call-mirror-hold-release.txt +``` + +### CALL Exact-Echo Reproducibility Test + +Goal: determine whether the new frame `07 80 45 20 D0 68` is reproducible when +using the artificial exact-CALL echo that originally produced it. + +Test BTN9: repeat exact CALL echo and explicitly watch for `07 80 45 20 D0 68`. + +```powershell +python scripts/serial_button_response_test.py --port COM5 --duration 15 --prompt --respond-to-call --respond-once --response-frame "00 00 15 80 00 CF" --response-frame "00 00 15 00 00 4F" --watch-frame "07 80 45 20 D0 68" --log captures/rcp-buttons-call-exact-echo-repro-1.txt +``` + +Run the same command three times, changing only the log filename: + +```powershell +python scripts/serial_button_response_test.py --port COM5 --duration 15 --prompt --respond-to-call --respond-once --response-frame "00 00 15 80 00 CF" --response-frame "00 00 15 00 00 4F" --watch-frame "07 80 45 20 D0 68" --log captures/rcp-buttons-call-exact-echo-repro-2.txt +python scripts/serial_button_response_test.py --port COM5 --duration 15 --prompt --respond-to-call --respond-once --response-frame "00 00 15 80 00 CF" --response-frame "00 00 15 00 00 4F" --watch-frame "07 80 45 20 D0 68" --log captures/rcp-buttons-call-exact-echo-repro-3.txt +``` + +Procedure for each run: + +1. Power-cycle the RCP. +2. Start the command and press Enter at the prompt. +3. Press `CALL` once. +4. Stop after the script exits, then power-cycle before the next run. + +Interpretation: + +- If `Watch totals: 07 80 45 20 D0 68=1` appears consistently, the frame is a + reproducible response to artificial exact CALL echo. +- If it appears intermittently, timing or current panel state is probably part + of the trigger. +- If it does not appear, the original hit may have depended on a very specific + press/release timing or buffered frame ordering. diff --git a/scripts/serial_button_response_test.py b/scripts/serial_button_response_test.py index e883021..8edb7e8 100644 --- a/scripts/serial_button_response_test.py +++ b/scripts/serial_button_response_test.py @@ -6,6 +6,7 @@ This helper can: 1. Optionally put the RCP into a latched state with a known primer/query. 2. Listen for the button frames that are known to appear while disconnected. 3. Optionally transmit response frames when CAM POWER or CALL is observed. +4. Optionally mirror CALL high/low events with matching host responses. Known RCP-origin button frames: @@ -144,12 +145,23 @@ def parse_args() -> argparse.Namespace: parser.add_argument("--after-latch", type=float, default=1.0) parser.add_argument("--respond-to-cam-power", action="store_true") parser.add_argument("--respond-to-call", action="store_true") + parser.add_argument( + "--mirror-call", + action="store_true", + help="respond to CALL high with CALL high and CALL low with CALL low", + ) parser.add_argument( "--response-frame", type=parse_hex_bytes, action="append", help="hex frame to send when CAM POWER is seen; can be repeated", ) + parser.add_argument( + "--watch-frame", + type=parse_hex_bytes, + action="append", + help="hex frame to count when it appears in RX; can be repeated", + ) parser.add_argument("--response-delay", type=float, default=0.05) parser.add_argument("--response-repeat", type=int, default=1) parser.add_argument("--response-interval", type=float, default=0.2) @@ -158,6 +170,11 @@ def parse_args() -> argparse.Namespace: action="store_true", help="only transmit the response on the first matched button frame", ) + parser.add_argument( + "--mirror-call-once-per-state", + action="store_true", + help="with --mirror-call, respond once to CALL high and once to CALL low", + ) parser.add_argument("--prompt", action="store_true", help="pause before listen so you can prepare button presses") return parser.parse_args() @@ -166,10 +183,14 @@ def main() -> int: args = parse_args() emit, log_file = make_logger(args.log) response_frames = args.response_frame or [CAM_POWER] + watch_frames = args.watch_frame or [] primer = build_frame(0x00, 0x00, args.latch_primer_command, args.state, args.value) query = build_frame(0x00, 0x00, args.latch_query_command, args.state, args.value) responded = False + mirrored_call_on = False + mirrored_call_off = False totals = {name: 0 for name in KNOWN_PATTERNS} + watch_totals = {hex_preview(frame): 0 for frame in watch_frames} try: with serial.Serial( @@ -195,11 +216,13 @@ def main() -> int: if args.prompt: input("Ready to listen. Press Enter, then press CAM POWER/CALL on the RCP: ") + ser.reset_input_buffer() emit( f"Listening for {args.duration:.1f}s; " f"respond_to_cam_power={args.respond_to_cam_power}, " - f"respond_to_call={args.respond_to_call}" + f"respond_to_call={args.respond_to_call}, " + f"mirror_call={args.mirror_call}" ) stop_at = time.monotonic() + args.duration buffer = bytearray() @@ -219,6 +242,32 @@ def main() -> int: if count: totals[name] += count emit(f"{stamp} DETECT {name} x{count}") + for frame in watch_frames: + count = data.count(frame) + if count: + key = hex_preview(frame) + watch_totals[key] += count + emit(f"{stamp} DETECT watch-frame {key} x{count}") + + if args.mirror_call: + mirrored = False + if CALL_ON in buffer and not ( + args.mirror_call_once_per_state and mirrored_call_on + ): + send_frame(ser, emit, "CALL high mirror", CALL_ON) + mirrored_call_on = True + responded = True + mirrored = True + if CALL_OFF in buffer and not ( + args.mirror_call_once_per_state and mirrored_call_off + ): + send_frame(ser, emit, "CALL low mirror", CALL_OFF) + mirrored_call_off = True + responded = True + mirrored = True + if mirrored: + buffer.clear() + continue should_respond = ( ( @@ -243,6 +292,11 @@ def main() -> int: "Totals: " + ", ".join(f"{name}={count}" for name, count in totals.items()) ) + if watch_totals: + emit( + "Watch totals: " + + ", ".join(f"{frame}={count}" for frame, count in watch_totals.items()) + ) except KeyboardInterrupt: emit("Stopped.") return 0