This commit is contained in:
Aiden
2026-05-13 16:24:13 +10:00
parent 7f0ec19798
commit 9d76820ef6
6 changed files with 365 additions and 1 deletions

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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