This commit is contained in:
Aiden
2026-05-13 16:36:43 +10:00
parent 0824f46feb
commit 4e8be74dd9
7 changed files with 181 additions and 1 deletions

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:32:20.568 RX 006 bytes 00 00 00 00 80 DA
16:32:20.568 DETECT heartbeat x1
16:32:21.270 RX 006 bytes 00 00 00 00 80 DA
16:32:21.270 DETECT heartbeat x1
16:32:21.879 RX 006 bytes 00 00 15 80 00 CF
16:32:21.879 DETECT call-on x1
16:32:21.999 TX button response frame 006 00 00 15 80 00 CF
16:32:22.000 TX button response frame 006 00 00 15 00 00 4F
16:32:23.980 RX 006 bytes 00 00 00 00 80 DA
16:32:23.980 DETECT heartbeat x1
16:32:24.654 RX 006 bytes 00 00 15 00 00 4F
16:32:24.654 DETECT call-off x1
16:32:25.264 RX 001 bytes 00
16:32:25.294 RX 005 bytes 00 00 00 80 DA
16:32:25.966 RX 001 bytes 00
16:32:25.996 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:31:27.712 RX 006 bytes 00 00 15 80 00 CF
16:31:27.712 DETECT call-on x1
16:31:27.733 TX button response frame 006 00 00 15 80 00 CF
16:31:27.733 TX button response frame 006 00 00 15 00 00 4F
16:31:29.683 RX 001 bytes 00
16:31:29.714 RX 005 bytes 00 00 00 80 DA
16:31:30.383 RX 001 bytes 00
16:31:30.414 RX 005 bytes 00 00 00 80 DA
16:31:31.087 RX 006 bytes 00 00 00 00 80 DA
16:31:31.087 DETECT heartbeat x1
16:31:31.788 RX 006 bytes 00 00 00 00 80 DA
16:31:31.788 DETECT heartbeat x1
16:31:32.490 RX 006 bytes 00 00 00 00 80 DA
16:31:32.490 DETECT heartbeat x1
16:31:33.193 RX 006 bytes 00 00 00 00 80 DA
16:31:33.193 DETECT heartbeat x1
Stopped.

View File

@@ -0,0 +1,23 @@
Button test on COM5 at 38400 8N1
Listening for 15.0s; respond_to_cam_power=False, respond_to_call=True, mirror_call=False
16:31:45.587 RX 006 bytes 00 00 00 00 80 DA
16:31:45.587 DETECT heartbeat x1
16:31:46.285 RX 006 bytes 00 00 00 00 80 DA
16:31:46.285 DETECT heartbeat x1
16:31:46.895 RX 006 bytes 00 00 15 80 00 CF
16:31:46.895 DETECT call-on x1
16:31:46.946 TX button response frame 006 00 00 15 80 00 CF
16:31:46.946 TX button response frame 006 00 00 15 00 00 4F
16:31:48.895 RX 006 bytes 00 00 00 00 80 DA
16:31:48.895 DETECT heartbeat x1
16:31:49.049 RX 006 bytes 00 00 15 00 00 4F
16:31:49.049 DETECT call-off x1
16:31:49.688 RX 006 bytes 00 00 00 00 80 DA
16:31:49.688 DETECT heartbeat x1
16:31:50.389 RX 006 bytes 00 00 00 00 80 DA
16:31:50.389 DETECT heartbeat x1
16:31:51.088 RX 006 bytes 00 00 00 00 80 DA
16:31:51.088 DETECT heartbeat x1
16:31:51.788 RX 006 bytes 00 00 00 00 80 DA
16:31:51.788 DETECT heartbeat x1
Stopped.

View File

@@ -0,0 +1,22 @@
Button test on COM5 at 38400 8N1
Listening for 15.0s; respond_to_cam_power=False, respond_to_call=True, mirror_call=False
16:32:03.872 RX 006 bytes 00 00 00 00 80 DA
16:32:03.872 DETECT heartbeat x1
16:32:04.542 RX 001 bytes 00
16:32:04.572 RX 005 bytes 00 00 00 80 DA
16:32:04.908 RX 006 bytes 00 00 15 80 00 CF
16:32:04.908 DETECT call-on x1
16:32:04.990 TX button response frame 006 00 00 15 80 00 CF
16:32:04.990 TX button response frame 006 00 00 15 00 00 4F
16:32:05.021 RX 006 bytes 07 80 45 30 D0 78
16:32:06.967 RX 006 bytes 00 00 00 00 80 DA
16:32:06.967 DETECT heartbeat x1
16:32:07.457 RX 006 bytes 00 00 15 00 00 4F
16:32:07.457 DETECT call-off x1
16:32:08.068 RX 006 bytes 00 00 00 00 80 DA
16:32:08.068 DETECT heartbeat x1
16:32:08.769 RX 006 bytes 00 00 00 00 80 DA
16:32:08.769 DETECT heartbeat x1
16:32:09.470 RX 006 bytes 00 00 00 00 80 DA
16:32:09.470 DETECT heartbeat x1
Stopped.

View File

@@ -2959,3 +2959,78 @@ python scripts/serial_button_response_test.py --port COM5 --duration 15 --prompt
For each run, power-cycle first, press and hold `CALL` for about 2 seconds, then For each run, power-cycle first, press and hold `CALL` for about 2 seconds, then
release after either the watch frame appears or the next heartbeat appears. release after either the watch frame appears or the next heartbeat appears.
### 2026-05-13 CALL Timing-Bracket Result
Captures:
- `captures/rcp-buttons-call-exact-echo-delay-20ms.txt`
- `captures/rcp-buttons-call-exact-echo-delay-50ms.txt`
- `captures/rcp-buttons-call-exact-echo-delay-80ms.txt`
- `captures/rcp-buttons-call-exact-echo-delay-120ms.txt`
User procedure:
- Each run used the same two-frame exact CALL echo pair.
- Button hold timing was kept as accurate and consistent as possible.
Observed result:
| Delay | Result |
| --- | --- |
| 20 ms | heartbeat only; no `0x45` response |
| 50 ms | heartbeat/CALL traffic only; no `0x45` response |
| 80 ms | new response `07 80 45 30 D0 78` |
| 120 ms | heartbeat/CALL traffic only; no `0x45` response |
Comparison of known CALL-response-family frames:
```text
07 80 45 20 D0 68
07 80 45 30 D0 78
```
Both frames are checksum-valid under the current XOR-with-`0x5A` hypothesis.
They share prefix `07 80`, command/status byte `45`, and value byte `D0`. The
state/status byte changed from `20` to `30`, with the checksum changing from
`68` to `78` as expected.
Interpretation:
- The RCP appears to have a CALL-related `0x45` response family.
- The observed `0x45` response is timing-sensitive but not locked only to the
original 50 ms response delay.
- The `0x20` vs `0x30` byte may represent a CALL/button substate, link/session
substate, or timing/window state.
- This is stronger evidence that the panel is responding meaningfully to host
traffic, even though the LCD state still has not been driven active.
Next CALL timing tests should watch both known `0x45` family frames:
```powershell
python scripts/serial_button_response_test.py --port COM5 --duration 15 --prompt --respond-to-call --respond-once --response-delay 0.06 --response-frame "00 00 15 80 00 CF" --response-frame "00 00 15 00 00 4F" --watch-frame "07 80 45 20 D0 68" --watch-frame "07 80 45 30 D0 78" --log captures/rcp-buttons-call-exact-echo-delay-60ms.txt
python scripts/serial_button_response_test.py --port COM5 --duration 15 --prompt --respond-to-call --respond-once --response-delay 0.07 --response-frame "00 00 15 80 00 CF" --response-frame "00 00 15 00 00 4F" --watch-frame "07 80 45 20 D0 68" --watch-frame "07 80 45 30 D0 78" --log captures/rcp-buttons-call-exact-echo-delay-70ms.txt
python scripts/serial_button_response_test.py --port COM5 --duration 15 --prompt --respond-to-call --respond-once --response-delay 0.08 --response-frame "00 00 15 80 00 CF" --response-frame "00 00 15 00 00 4F" --watch-frame "07 80 45 20 D0 68" --watch-frame "07 80 45 30 D0 78" --log captures/rcp-buttons-call-exact-echo-delay-80ms-v2.txt
python scripts/serial_button_response_test.py --port COM5 --duration 15 --prompt --respond-to-call --respond-once --response-delay 0.09 --response-frame "00 00 15 80 00 CF" --response-frame "00 00 15 00 00 4F" --watch-frame "07 80 45 20 D0 68" --watch-frame "07 80 45 30 D0 78" --log captures/rcp-buttons-call-exact-echo-delay-90ms.txt
python scripts/serial_button_response_test.py --port COM5 --duration 15 --prompt --respond-to-call --respond-once --response-delay 0.10 --response-frame "00 00 15 80 00 CF" --response-frame "00 00 15 00 00 4F" --watch-frame "07 80 45 20 D0 68" --watch-frame "07 80 45 30 D0 78" --log captures/rcp-buttons-call-exact-echo-delay-100ms.txt
```
If the `0x45` family repeats in the 60-100 ms window, the next step is to test
whether the host can answer the RCP's `0x45` response with a checksum-valid
host-shaped frame using command byte `0x45`.
Tooling note:
- `scripts/serial_button_response_test.py` now supports
`--followup-on-watch-frame` with one or more `--followup-frame` values. This
lets the host answer a reproduced RCP response immediately in the same run.
Possible follow-up test after reproducing a `0x45` response:
```powershell
python scripts/serial_button_response_test.py --port COM5 --duration 15 --prompt --respond-to-call --respond-once --response-delay 0.08 --response-frame "00 00 15 80 00 CF" --response-frame "00 00 15 00 00 4F" --watch-frame "07 80 45 20 D0 68" --watch-frame "07 80 45 30 D0 78" --followup-on-watch-frame --followup-frame "00 00 45 00 80 9F" --log captures/rcp-buttons-call-45-followup-host-shaped.txt
```
This test is deliberately secondary. Run it only after the `0x45` family
repeats, so any change can be attributed to the follow-up rather than to the
initial CALL echo timing.

View File

@@ -7,6 +7,7 @@ This helper can:
2. Listen for the button frames that are known to appear while disconnected. 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. 3. Optionally transmit response frames when CAM POWER or CALL is observed.
4. Optionally mirror CALL high/low events with matching host responses. 4. Optionally mirror CALL high/low events with matching host responses.
5. Optionally transmit follow-up frames when a watched response frame appears.
Known RCP-origin button frames: Known RCP-origin button frames:
@@ -162,6 +163,18 @@ def parse_args() -> argparse.Namespace:
action="append", action="append",
help="hex frame to count when it appears in RX; can be repeated", help="hex frame to count when it appears in RX; can be repeated",
) )
parser.add_argument(
"--followup-on-watch-frame",
action="store_true",
help="send follow-up frame(s) when any watched frame is observed",
)
parser.add_argument(
"--followup-frame",
type=parse_hex_bytes,
action="append",
help="hex frame to send after a watched frame appears; can be repeated",
)
parser.add_argument("--followup-delay", type=float, default=0.05)
parser.add_argument("--response-delay", type=float, default=0.05) parser.add_argument("--response-delay", type=float, default=0.05)
parser.add_argument("--response-repeat", type=int, default=1) parser.add_argument("--response-repeat", type=int, default=1)
parser.add_argument("--response-interval", type=float, default=0.2) parser.add_argument("--response-interval", type=float, default=0.2)
@@ -176,7 +189,10 @@ def parse_args() -> argparse.Namespace:
help="with --mirror-call, respond once to CALL high and once to CALL low", 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") parser.add_argument("--prompt", action="store_true", help="pause before listen so you can prepare button presses")
return parser.parse_args() args = parser.parse_args()
if args.followup_on_watch_frame and not args.followup_frame:
parser.error("--followup-on-watch-frame requires at least one --followup-frame")
return args
def main() -> int: def main() -> int:
@@ -187,6 +203,7 @@ def main() -> int:
primer = build_frame(0x00, 0x00, args.latch_primer_command, args.state, args.value) 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) query = build_frame(0x00, 0x00, args.latch_query_command, args.state, args.value)
responded = False responded = False
followup_sent = False
mirrored_call_on = False mirrored_call_on = False
mirrored_call_off = False mirrored_call_off = False
totals = {name: 0 for name in KNOWN_PATTERNS} totals = {name: 0 for name in KNOWN_PATTERNS}
@@ -248,6 +265,11 @@ def main() -> int:
key = hex_preview(frame) key = hex_preview(frame)
watch_totals[key] += count watch_totals[key] += count
emit(f"{stamp} DETECT watch-frame {key} x{count}") emit(f"{stamp} DETECT watch-frame {key} x{count}")
if args.followup_on_watch_frame and not followup_sent:
followup_sent = True
time.sleep(args.followup_delay)
for followup in args.followup_frame or []:
send_frame(ser, emit, "watch follow-up", followup)
if args.mirror_call: if args.mirror_call:
mirrored = False mirrored = False