3880 lines
161 KiB
Markdown
3880 lines
161 KiB
Markdown
# Discovery Notes
|
|
|
|
This file records hands-on observations separately from manual-derived facts.
|
|
Treat these as bench notes: useful and current, but still worth rechecking with
|
|
photos, continuity tests, and instrument captures.
|
|
|
|
## 2026-05-13 - RCP-TX7 10-Pin Power and Cable
|
|
|
|
Observed on the RCP-TX7 10-pin remote connector/cable during restoration work:
|
|
|
|
- Pin 9 confirmed as ground / DC return.
|
|
- Pin 10 confirmed as power input.
|
|
- Cable color for pin 9 / ground: brown.
|
|
- Cable color for pin 10 / +12 V power: brown-white.
|
|
- Cable colors for pins 1-8 have been continuity-mapped; see the working cable
|
|
map below.
|
|
- Yellow and yellow-white conductors are present in the cable but did not map to
|
|
connector pins during continuity testing.
|
|
- Multimeter reading from pin 9 ground to pin 4 serial data: about -9 V.
|
|
- Multimeter reading from pin 9 ground to pin 7 serial data: about +0.037 V.
|
|
- Pins 4 and 7 were the only serial-related combinations that produced a
|
|
meaningful multimeter result during this check.
|
|
- With power present on pins 9 and 10, the panel shows a green `PANEL ACTIVE`
|
|
light.
|
|
- The inside of the 10-pin cable contains 12 wires total.
|
|
- Three of those wire groups are twisted pairs.
|
|
|
|
Immediate implications:
|
|
|
|
- The bench result agrees with the RCP-TX7 and CCU-TX7 manual pinout for pins 9
|
|
and 10.
|
|
- The 12-conductor cable construction suggests not every conductor maps
|
|
one-to-one to the 10 connector pins; shielding/drain, duplicated grounds, or
|
|
paired signal returns may be present.
|
|
- The three twisted pairs are likely important candidates for serial data,
|
|
composite video, and/or power/ground pairing, but this should be confirmed by
|
|
continuity testing rather than color or twist assumptions.
|
|
- Pin 4 measuring around -9 V relative to pin 9 strongly suggests true RS-232
|
|
level idle on at least the RCP-to-CCU/camera data line.
|
|
- Pin 7 near 0 V may be inactive/floating until a CCU or camera drives the
|
|
return data line.
|
|
|
|
### Working Cable Map
|
|
|
|
This table combines the manual-derived pin purpose with hands-on color mapping.
|
|
Rows marked `confirmed` have been checked on the current cable/panel under test.
|
|
|
|
| Pin | Purpose | Cable color | Status | Notes |
|
|
| ---: | --- | --- | --- | --- |
|
|
| 1 | Spare / unused | red | confirmed | No function shown in service manual. |
|
|
| 2 | VBS / composite video X | black | confirmed | 1.0 Vp-p composite video input to RCP. |
|
|
| 3 | VBS / composite video ground | green | confirmed | Video reference/ground. |
|
|
| 4 | Serial data, RCP to CCU/camera | orange | confirmed | RS-232C-based data direction. |
|
|
| 5 | Serial/data ground | blue | confirmed | One of two serial/data grounds. |
|
|
| 6 | Serial/data ground | grey | confirmed | One of two serial/data grounds. |
|
|
| 7 | Serial data, CCU/camera to RCP | purple | confirmed | RS-232C-based data direction. |
|
|
| 8 | Spare / unused | purple-white | confirmed | No function shown in service manual. |
|
|
| 9 | DC return / ground | brown | confirmed | Confirmed as ground on current cable. |
|
|
| 10 | +12 V remote power input | brown-white | confirmed | Confirmed as power input on current cable. |
|
|
|
|
### Unmapped Cable Conductors
|
|
|
|
The cable contains two additional conductors that did not show continuity to
|
|
the 10 connector pins during the current test:
|
|
|
|
| Conductor color | Current status | Notes |
|
|
| --- | --- | --- |
|
|
| yellow | unmapped | May be shield/drain-related, spare, broken, or connected only at one end. |
|
|
| yellow-white | unmapped | May be shield/drain-related, spare, broken, or connected only at one end. |
|
|
|
|
Recheck these against connector shells, shield braid/drain, cable strain relief
|
|
hardware, and both ends of the cable if accessible.
|
|
|
|
Suggested next observations to capture:
|
|
|
|
1. Connector orientation photo showing pin numbering reference.
|
|
2. Wire color list, including which colors form each twisted pair.
|
|
3. Confirm whether yellow and yellow-white connect to shield, shell, or one end
|
|
only.
|
|
4. Resistance between pins 5, 6, and 9 with the cable disconnected.
|
|
5. Scope idle voltage and activity on pins 4 and 7 relative to pins 5/6 and
|
|
pin 9 while pressing panel controls and, later, while connected to a CCU or
|
|
camera.
|
|
|
|
## Serial Capture Setup
|
|
|
|
Initial USB serial adapter wiring for passive listening:
|
|
|
|
| Adapter terminal | RCP-TX7 cable pin | Cable color | Purpose |
|
|
| --- | ---: | --- | --- |
|
|
| `GND` | 9 | brown | Shared reference / DC return |
|
|
| `RXD` | 4 | orange | Listen to RCP-to-CCU/camera serial data |
|
|
|
|
Do not connect adapter `TXD` during the first capture pass. Pin 4 measured about
|
|
-9 V relative to pin 9, so use the adapter's RS-232 side, not TTL UART mode.
|
|
|
|
Capture helper:
|
|
|
|
```powershell
|
|
python -m pip install pyserial
|
|
python scripts/serial_sniff.py --list
|
|
python scripts/serial_sniff.py --port COM3 --baud 38400 --ascii
|
|
python scripts/serial_sniff.py --port COM3 --baud 38400 --frame-size 6 --log captures/rcp-pin4.txt
|
|
```
|
|
|
|
Replace `COM3` with the adapter port shown by `--list` or Windows Device
|
|
Manager. While the script is running, press simple RCP controls and watch for
|
|
new hex bytes.
|
|
|
|
### 2026-05-13 Initial Pin 4 Capture
|
|
|
|
With the adapter in RS-232 mode, adapter `RXD` connected to RCP pin 4, and
|
|
adapter `GND` connected to pin 9, the stream produced repeating 6-byte patterns:
|
|
|
|
```text
|
|
00 00 00 00 80 DA
|
|
00 00 07 80 00 DD
|
|
```
|
|
|
|
Observed behavior:
|
|
|
|
- Frames repeat roughly every 200 ms during the sample.
|
|
- The stream sometimes appeared split as `00` followed by five bytes, which is
|
|
likely a read-timeout/chunking artifact rather than a protocol feature.
|
|
- Button presses did not obviously correlate with a visible byte change in the
|
|
first capture.
|
|
|
|
Current interpretation:
|
|
|
|
- This looks like a regular RCP-origin heartbeat/status transmission on pin 4,
|
|
not random noise.
|
|
- Because only pin 4 is connected, this may be the panel repeatedly trying to
|
|
announce itself or poll a missing CCU/camera.
|
|
- Pin 7 measured near 0 V and is probably quiet until a CCU/camera drives the
|
|
return channel.
|
|
|
|
Next capture passes:
|
|
|
|
1. Use `--frame-size 6` to avoid misleading `1 + 5` packet splits.
|
|
2. Capture a quiet baseline for 30 seconds.
|
|
3. Capture separate files while pressing one control repeatedly, naming the
|
|
action in the filename.
|
|
4. Later, capture pin 7 when connected to a real CCU/camera or a controlled
|
|
test transmitter.
|
|
|
|
### 2026-05-13 Baseline vs CAM POWER Capture
|
|
|
|
Capture files:
|
|
|
|
- `captures/rcp-pin4-baseline.txt`
|
|
- `captures/rcp-pin4-cam-power.txt`
|
|
- `captures/rcp-pin4-call.txt`
|
|
|
|
Frame counts from the available logs:
|
|
|
|
| Capture | Frame | Count | Current label |
|
|
| --- | --- | ---: | --- |
|
|
| baseline | `00 00 00 00 80 DA` | 67 | idle heartbeat |
|
|
| CAM POWER | `00 00 00 00 80 DA` | 23 | idle heartbeat |
|
|
| CAM POWER | `00 00 07 80 00 DD` | 4 | CAM POWER candidate |
|
|
| CALL | `00 00 00 00 80 DA` | 17 | idle heartbeat |
|
|
| CALL | `00 00 15 80 00 CF` | 4 | CALL candidate, state/high bit set |
|
|
| CALL | `00 00 15 00 00 4F` | 4 | CALL candidate, state/high bit clear |
|
|
|
|
Current interpretation:
|
|
|
|
- The baseline capture contains only `00 00 00 00 80 DA`.
|
|
- Pressing `CAM POWER` introduces `00 00 07 80 00 DD`.
|
|
- Pressing `CALL` introduces `00 00 15 80 00 CF` and `00 00 15 00 00 4F`.
|
|
- Other tested buttons did not obviously produce unique frames while the panel
|
|
was not connected to a CCU/camera.
|
|
- `CAM POWER` and `CALL` may be among the few controls the panel transmits even
|
|
without a completed host/CCU session.
|
|
- The CALL frames differ by byte 4 (`80` vs `00`) and final byte (`CF` vs `4F`),
|
|
suggesting a state bit plus checksum or complement-style trailing byte.
|
|
- Current checksum hypothesis: byte 6 is XOR checksum with seed `0x5A` over the
|
|
first five bytes. Examples:
|
|
- `5A xor 00 xor 00 xor 00 xor 00 xor 80 = DA`
|
|
- `5A xor 00 xor 00 xor 07 xor 80 xor 00 = DD`
|
|
- `5A xor 00 xor 00 xor 15 xor 80 xor 00 = CF`
|
|
- `5A xor 00 xor 00 xor 15 xor 00 xor 00 = 4F`
|
|
|
|
Helper for future captures:
|
|
|
|
```powershell
|
|
python scripts/analyze_capture.py captures/rcp-pin4-baseline.txt captures/rcp-pin4-cam-power.txt captures/rcp-pin4-call.txt
|
|
```
|
|
|
|
## Host Response Experiments
|
|
|
|
The RCP currently appears to be in an offline heartbeat state. With no CCU/camera
|
|
response present, only `CAM POWER` and `CALL` have been observed to send unique
|
|
frames beyond the heartbeat. The next protocol step is to learn what the RCP
|
|
expects on pin 7 (`CCU/camera -> RCP`).
|
|
|
|
Important wiring for host-response tests:
|
|
|
|
| Adapter terminal | RCP-TX7 cable pin | Cable color | Purpose |
|
|
| --- | ---: | --- | --- |
|
|
| `GND` | 9 | brown | Shared reference / DC return |
|
|
| `TXD` | 7 | purple | Candidate host-to-RCP transmit line |
|
|
|
|
Suggested safety precautions:
|
|
|
|
- Use the adapter's RS-232 side, not TTL UART.
|
|
- Keep adapter `RXD` on pin 4 if possible so the RCP output is still logged.
|
|
- Add a series resistor, for example 1 k to 4.7 k, between adapter `TXD` and pin
|
|
7 for early experiments.
|
|
- Send one candidate frame at a time or repeat at a slow cadence. Avoid brute
|
|
forcing unknown byte ranges.
|
|
- Watch for changes in heartbeat, LCD state, panel lock state, or new frames on
|
|
pin 4.
|
|
|
|
Frame sender:
|
|
|
|
```powershell
|
|
python scripts/serial_send_frame.py --port COM3 --dry-run
|
|
python scripts/serial_send_frame.py --port COM3 --frame "00 00 00 00 80 DA" --repeat 5 --interval 0.2
|
|
```
|
|
|
|
On Windows, a COM port is usually exclusive, so the sniffer and sender cannot
|
|
open the same adapter at the same time. Use the combined probe script when RXD
|
|
is connected to pin 4 and TXD is connected to pin 7:
|
|
|
|
```powershell
|
|
python scripts/serial_probe_response.py --port COM3 --tx-frame "00 00 00 00 80 DA" --repeat 5 --interval 0.2 --log captures/rcp-response-test.txt
|
|
```
|
|
|
|
This listens first, sends the candidate response from the same serial session,
|
|
then keeps listening for changes on pin 4.
|
|
|
|
Candidate first response:
|
|
|
|
- `00 00 00 00 80 DA` - mirror the observed heartbeat as a possible no-op/ack.
|
|
|
|
If mirroring the heartbeat changes nothing, the next low-risk approach is to
|
|
capture a real CCU/camera response rather than guessing. If no host is available,
|
|
try only checksum-valid, documented-frame-shape candidates and record every
|
|
attempt in a separate capture log.
|
|
|
|
### 2026-05-13 Heartbeat Mirror Response Result
|
|
|
|
Experiment:
|
|
|
|
- Adapter `TXD` connected to RCP pin 7.
|
|
- Sent `00 00 00 00 80 DA` on the host-to-RCP line as a mirrored heartbeat /
|
|
possible no-op acknowledgement.
|
|
- Capture file: `captures/rcp-response-heartbeat-mirror.txt`.
|
|
|
|
Observed result:
|
|
|
|
- The RCP screen changed to `CONNECT: NOT ACT`.
|
|
- During this capture, pin 4 still transmitted only `00 00 00 00 80 DA`.
|
|
- Frame count: 59 received heartbeat frames, 10 transmitted mirrored heartbeat
|
|
frames.
|
|
- Pin 4 heartbeat timing became more frequent during the response window, then
|
|
returned to the slower baseline cadence afterward.
|
|
|
|
Current interpretation:
|
|
|
|
- The RCP is detecting return-channel traffic on pin 7.
|
|
- Mirroring the heartbeat is enough to move the panel out of the simple offline
|
|
state, but it does not complete active host/CCU negotiation.
|
|
- `NOT ACT` likely means connected/not active, connected/not activated, or a
|
|
similar state where the link is electrically/protocol-visible but no valid
|
|
control session has been established.
|
|
- The RCP did not emit a new command/status frame on pin 4 in response to the
|
|
mirrored heartbeat, so the next handshake step is probably not simply an echo
|
|
of its heartbeat.
|
|
|
|
Additional checksum-valid response tests:
|
|
|
|
| Capture | TX frame | RX result on pin 4 | Screen result |
|
|
| --- | --- | --- | --- |
|
|
| `captures/rcp-response-zero-state.txt` | `00 00 00 00 00 5A` | heartbeat only | `CONNECT: NOT ACT` |
|
|
| `captures/rcp-response-state-byte4.txt` | `00 00 00 80 00 DA` | heartbeat only | `CONNECT: NOT ACT` |
|
|
| `captures/rcp-response-invalid-checksum.txt` | `00 00 00 00 80 00` | heartbeat only | `CONNECT: NOT ACT` |
|
|
| TXD connected, no transmitted bytes | RS-232 idle only | heartbeat only | no `CONNECT: NOT ACT` |
|
|
| Single-byte test | `00` | heartbeat only | no `CONNECT: NOT ACT` |
|
|
| Single-byte test | `FF` | heartbeat only | no `CONNECT: NOT ACT` |
|
|
| Short-frame test | `00 00 00` | heartbeat only | no `CONNECT: NOT ACT` |
|
|
| Frame-length test | `00 00 00 00` | heartbeat only | no `CONNECT: NOT ACT` |
|
|
| Frame-length test | `00 00 00 00 80` | heartbeat only | no `CONNECT: NOT ACT` |
|
|
| Frame-length test | `00 00 00 00 80 DA 00` | heartbeat only | `CONNECT: NOT ACT` |
|
|
|
|
Updated interpretation:
|
|
|
|
- `CONNECT: NOT ACT` is probably a link-present state, not proof of a correct
|
|
CCU handshake.
|
|
- The RCP reacts to several checksum-valid 6-byte frames on pin 7, but continues
|
|
sending only the pin 4 heartbeat.
|
|
- An intentionally invalid checksum frame also produced `CONNECT: NOT ACT`, so
|
|
that display state does not prove checksum acceptance.
|
|
- The response needed to enter an active control session likely needs a specific
|
|
status/identity/activation frame, not just a valid no-op frame shape.
|
|
- TXD connected at idle without transmitted bytes did not produce
|
|
`CONNECT: NOT ACT`, so the display state appears to require received byte
|
|
activity on pin 7, not merely a driven RS-232 idle level.
|
|
- Single-byte and three-byte transmissions did not produce `CONNECT: NOT ACT`,
|
|
so the RCP is likely recognizing a minimum frame length or parser shape rather
|
|
than arbitrary serial bytes.
|
|
- Four-byte and five-byte transmissions did not produce `CONNECT: NOT ACT`, but
|
|
a seven-byte transmission beginning with the known six-byte heartbeat did.
|
|
This suggests the first six bytes are enough to trigger the parser/link state,
|
|
and the seventh byte may be ignored, buffered for a later frame, or treated as
|
|
extra data after the recognized packet.
|
|
- None of the tested host frames have caused the RCP to emit anything on pin 4
|
|
except the heartbeat.
|
|
|
|
Command-field response tests, using frame shape `00 00 CMD 00 80 CHECKSUM`:
|
|
|
|
| Capture | TX frame | Checksum | Screen result | Notes |
|
|
| --- | --- | --- | --- | --- |
|
|
| `captures/rcp-response-cmd01.txt` | `00 00 01 00 80 DB` | valid | `CONNECT: NOT ACT` | 6-byte command-shaped frame accepted enough to change display. |
|
|
| `captures/rcp-response-cmd02.txt` | `00 00 02 00 80 DB` | invalid | `CONNECT: NOT ACT` | Bad checksum still changed display. |
|
|
| `captures/rcp-response-cmd02.txt` | `00 00 02 00 80 D8` | valid | `CONNECT: NOT ACT` | Valid checksum also changed display. |
|
|
| `captures/rcp-response-cmd03.txt` | `00 00 03 00 80 D9` | valid | `CONNECT: NOT ACT` | 6-byte command-shaped frame accepted enough to change display. |
|
|
| `captures/rcp-response-cmd04.txt` | `00 00 7F 00 80 A5` | valid | no screen change | First observed checksum-valid 6-byte frame that does not trigger `CONNECT: NOT ACT`. |
|
|
| `captures/rcp-response-cmd05.txt` | `00 00 80 00 80 5A` | valid | `CONNECT: NOT ACT` | 6-byte command-shaped frame accepted enough to change display. |
|
|
|
|
Implications from command-field tests:
|
|
|
|
- Screen change is not simply based on frame length or checksum validity.
|
|
- The command/status byte matters: `0x7F` appears ignored or treated as
|
|
non-link-establishing, despite a valid checksum.
|
|
- Tested commands `0x00`, `0x01`, `0x02`, `0x03`, and `0x80` can trigger
|
|
`CONNECT: NOT ACT`; `0x7F` did not.
|
|
- The RCP operating manual notes that `CAM POWER`, `MASTER`/`SLAVE`, and some
|
|
monitor functions are available only when connected to a CCU, so active state
|
|
may depend on CCU identity/status bits.
|
|
|
|
Next low-risk response experiments:
|
|
|
|
1. Repeat the same test with logging enabled so the pin 4 output before, during,
|
|
and after `CONNECT: NOT ACT` is captured.
|
|
2. Try sending the mirrored heartbeat continuously at a cadence close to the RCP
|
|
heartbeat, for example every 0.6 seconds, and watch whether the display state
|
|
changes.
|
|
3. Probe semantic fields within the six-byte frame shape, changing one byte at
|
|
a time and logging both screen state and pin 4 output. Prioritize small
|
|
command values and avoid broad brute-force sweeps.
|
|
4. Prefer capturing a real CCU/camera pin 7 response before broad guessing.
|
|
|
|
### Command Sweep Helper
|
|
|
|
A cautious command-byte sweep helper is available at
|
|
`scripts/serial_sweep_commands.py`. It sends only checksum-valid six-byte frames
|
|
using the current frame/checksum hypothesis and marks any RCP output that is not
|
|
the known heartbeat.
|
|
|
|
Recommended first sweep:
|
|
|
|
```powershell
|
|
python scripts/serial_sweep_commands.py --port COM5 --start 0x00 --end 0x20 --after-each 1.0 --log captures/rcp-sweep-cmd-00-20.txt
|
|
```
|
|
|
|
Optional dry run:
|
|
|
|
```powershell
|
|
python scripts/serial_sweep_commands.py --port COM5 --start 0x00 --end 0x20 --dry-run
|
|
```
|
|
|
|
Use small ranges and keep watching the RCP screen while the sweep runs. The log
|
|
captures TX/RX bytes, but it cannot record screen messages unless they are noted
|
|
manually afterward.
|
|
|
|
The `0x00-0x20` sweep produced `CONNECT: NOT ACT` roughly halfway through the
|
|
run, but the exact command was not recorded in the log. Rerun a narrower range
|
|
with manual screen prompts:
|
|
|
|
```powershell
|
|
python scripts/serial_sweep_commands.py --port COM5 --start 0x0C --end 0x14 --after-each 1.2 --prompt-screen --log captures/rcp-sweep-cmd-0c-14-screen.txt
|
|
```
|
|
|
|
At each prompt, press Enter for no screen change, type `CONNECT: NOT ACT` when
|
|
that appears, or type `q` to stop.
|
|
|
|
Prompted sweep result:
|
|
|
|
- Capture: `captures/rcp-sweep-cmd-0c-14-screen.txt`.
|
|
- The RCP was reset after each screen trigger to clear its state, so recorded
|
|
triggers should be treated as independent fresh observations.
|
|
- First recorded screen marker: after command `0x0C`, frame
|
|
`00 00 0C 00 80 D6`, screen `CONNECT: NOT ACT`.
|
|
- Later manual screen markers were recorded after `0x0D`, `0x10`, `0x11`,
|
|
`0x12`, `0x13`, and `0x14`.
|
|
- No manual screen markers were recorded after `0x0E` or `0x0F`.
|
|
- Pin 4 output remained the heartbeat `00 00 00 00 80 DA` throughout.
|
|
|
|
Interpretation:
|
|
|
|
- Commands `0x0C`, `0x0D`, `0x10`, `0x11`, `0x12`, `0x13`, and `0x14` have
|
|
independent evidence of triggering `CONNECT: NOT ACT` in this sweep.
|
|
- Commands `0x0E` and `0x0F` did not have a screen marker recorded in this
|
|
sweep and are current non-trigger candidates.
|
|
- Because pin 4 stayed heartbeat-only, this state change is visible on the LCD
|
|
but does not yet produce a new RCP-to-host serial response.
|
|
|
|
Second prompted sweep result:
|
|
|
|
- Capture: `captures/rcp-sweep-cmd-15-30-screen.txt`.
|
|
- The log includes one partial/restarted pass at the beginning, then a fuller
|
|
prompted sweep through `0x30`.
|
|
- Pin 4 output remained the heartbeat `00 00 00 00 80 DA` throughout.
|
|
|
|
Commands with recorded `CONNECT: NOT ACT` screen markers:
|
|
|
|
| Command | TX frame |
|
|
| ---: | --- |
|
|
| `0x15` | `00 00 15 00 80 CF` |
|
|
| `0x16` | `00 00 16 00 80 CC` |
|
|
| `0x17` | `00 00 17 00 80 CD` |
|
|
| `0x18` | `00 00 18 00 80 C2` |
|
|
| `0x19` | `00 00 19 00 80 C3` |
|
|
| `0x1A` | `00 00 1A 00 80 C0` |
|
|
| `0x1B` | `00 00 1B 00 80 C1` |
|
|
| `0x1C` | `00 00 1C 00 80 C6` |
|
|
| `0x1D` | `00 00 1D 00 80 C7` |
|
|
| `0x28` | `00 00 28 00 80 F2` |
|
|
| `0x29` | `00 00 29 00 80 F3` |
|
|
| `0x2C` | `00 00 2C 00 80 F6` |
|
|
| `0x2D` | `00 00 2D 00 80 F7` |
|
|
| `0x30` | `00 00 30 00 80 EA` |
|
|
|
|
Commands with no recorded screen marker in this sweep:
|
|
|
|
```text
|
|
0x1E 0x1F 0x20 0x21 0x22 0x23 0x24 0x25
|
|
0x26 0x27 0x2A 0x2B 0x2E 0x2F
|
|
```
|
|
|
|
Emerging pattern:
|
|
|
|
- Some command byte ranges trigger `CONNECT: NOT ACT` while nearby checksum-valid
|
|
commands do not.
|
|
- Triggering still does not make the RCP transmit anything except the heartbeat.
|
|
- `CONNECT: NOT ACT` appears to be a parser-recognized but not session-active
|
|
state. It may indicate the RCP recognizes the command class as CCU-like, but
|
|
the remaining status/identity/activation fields are wrong or incomplete.
|
|
|
|
### Targeted Field Matrix Probe
|
|
|
|
After the `0x15-0x30` sweep, the best next experiment is not a broader command
|
|
sweep. The command byte is clearly relevant, but active-session behavior may
|
|
depend on the state/value fields or the prefix bytes. Use
|
|
`scripts/serial_probe_matrix.py` to hold one promising command constant and vary
|
|
only a small set of fields.
|
|
|
|
Start with command `0x15` because it is already associated with the RCP's own
|
|
`CALL` output frames:
|
|
|
|
```powershell
|
|
python scripts/serial_probe_matrix.py --port COM5 --commands 0x15 --states "0x00 0x80" --values "0x00 0x80" --after-each 1.2 --prompt-screen --log captures/rcp-matrix-cmd15-state-value.txt
|
|
```
|
|
|
|
Dry-run frames:
|
|
|
|
```text
|
|
00 00 15 00 00 4F
|
|
00 00 15 00 80 CF
|
|
00 00 15 80 00 CF
|
|
00 00 15 80 80 4F
|
|
```
|
|
|
|
Why this is useful:
|
|
|
|
- `00 00 15 00 00 4F` and `00 00 15 80 00 CF` match the RCP's observed
|
|
`CALL` frames.
|
|
- `00 00 15 00 80 CF` matches the command-sweep shape that triggered
|
|
`CONNECT: NOT ACT`.
|
|
- `00 00 15 80 80 4F` checks whether both high/state bits together change the
|
|
parser state.
|
|
|
|
If all four still produce only `CONNECT: NOT ACT` or no change, the next matrix
|
|
should keep `cmd=0x15`, `state=0x00`, `value=0x80`, and vary only prefix bytes:
|
|
|
|
```powershell
|
|
python scripts/serial_probe_matrix.py --port COM5 --prefix2s "0x00-0x0F" --commands 0x15 --states 0x00 --values 0x80 --after-each 1.2 --prompt-screen --log captures/rcp-matrix-cmd15-prefix2-00-0f.txt
|
|
```
|
|
|
|
Treat any result other than heartbeat-only pin 4 output as high-priority. In
|
|
particular, look for a new RCP frame, a different LCD message, or any transition
|
|
from `CONNECT: NOT ACT` to an active/connected state.
|
|
|
|
### 2026-05-13 Command `0x15` State/Value Matrix Result
|
|
|
|
Capture:
|
|
|
|
- `captures/rcp-matrix-cmd15-state-value.txt`
|
|
|
|
Frames tested:
|
|
|
|
| Command | State | Value | TX frame | Screen result |
|
|
| ---: | ---: | ---: | --- | --- |
|
|
| `0x15` | `0x00` | `0x00` | `00 00 15 00 00 4F` | `CONNECT NOT ACT` |
|
|
| `0x15` | `0x00` | `0x80` | `00 00 15 00 80 CF` | `CONNECT NOT ACT` |
|
|
| `0x15` | `0x80` | `0x00` | `00 00 15 80 00 CF` | `CONNECT NOT ACT` |
|
|
| `0x15` | `0x80` | `0x80` | `00 00 15 80 80 4F` | `CONNECT NOT ACT` |
|
|
|
|
Analyzer result:
|
|
|
|
- Pin 4 RX stayed at heartbeat only: `00 00 00 00 80 DA`.
|
|
- No non-heartbeat RCP-to-host frames were observed.
|
|
- The RCP was sensitive to all four command `0x15` variants, including both
|
|
frames that match the panel's own `CALL` output, but none advanced the panel
|
|
beyond `CONNECT NOT ACT`.
|
|
|
|
Interpretation:
|
|
|
|
- For command `0x15`, the tested state/value high bits are not enough to produce
|
|
an active session.
|
|
- The missing host response is likely in another field, a required repeated
|
|
cadence, a multi-frame exchange, or a CCU/camera identity/status frame.
|
|
- Since command `0x15` is parser-visible across all tested state/value variants,
|
|
it is a good anchor for prefix-byte testing.
|
|
|
|
Recommended next matrix:
|
|
|
|
```powershell
|
|
python scripts/serial_probe_matrix.py --port COM5 --prefix2s "0x00-0x0F" --commands 0x15 --states 0x00 --values 0x80 --after-each 1.2 --prompt-screen --log captures/rcp-matrix-cmd15-prefix2-00-0f.txt
|
|
```
|
|
|
|
If all `prefix2` values behave the same, repeat with `prefix1s "0x00-0x0F"` and
|
|
`prefix2s 0x00`. Prefix bytes may encode device address, CCU identity, panel
|
|
number, or bus direction.
|
|
|
|
### 2026-05-13 Command `0x15` Prefix2 Matrix Result
|
|
|
|
Capture:
|
|
|
|
- `captures/rcp-matrix-cmd15-prefix2-00-0f.txt`
|
|
|
|
Test shape:
|
|
|
|
- `p1=0x00`
|
|
- `p2=0x00-0x0F`
|
|
- `cmd=0x15`
|
|
- `state=0x00`
|
|
- `value=0x80`
|
|
|
|
Analyzer result:
|
|
|
|
- Pin 4 RX stayed at heartbeat only: `00 00 00 00 80 DA`.
|
|
- No non-heartbeat RCP-to-host frames were observed.
|
|
- The log contains 263 heartbeat RX frames and 16 transmitted prefix2 variants.
|
|
|
|
Screen observations:
|
|
|
|
- `CONNECT NOT ACT` was recorded after prefix2 values `0x00`, `0x01`, `0x02`,
|
|
`0x03`, `0x04`, `0x05`, `0x06`, `0x08`, `0x09`, `0x0A`, `0x0B`, `0x0C`,
|
|
`0x0D`, and `0x0E`.
|
|
- No screen marker was recorded after prefix2 `0x07` or `0x0F`.
|
|
- One marker was typed as `CONNECT NTO ACT`; treat this as the same
|
|
observation unless later testing proves otherwise.
|
|
|
|
Interpretation:
|
|
|
|
- Prefix2 did not produce an active session in the tested low-nibble range.
|
|
- The missing response is still not visible on pin 4.
|
|
- The missing markers at `0x07` and `0x0F` may be real parser behavior, because
|
|
both have low three bits set, but this needs a focused confirmation run before
|
|
treating it as a rule.
|
|
|
|
Recommended confirmation:
|
|
|
|
```powershell
|
|
python scripts/serial_probe_matrix.py --port COM5 --prefix2s "0x06 0x07 0x08 0x0E 0x0F" --commands 0x15 --states 0x00 --values 0x80 --after-each 1.2 --prompt-screen --log captures/rcp-matrix-cmd15-prefix2-confirm.txt
|
|
```
|
|
|
|
Reset the RCP after any screen-triggering result. This keeps the comparison
|
|
between trigger and non-trigger prefix2 values clean.
|
|
|
|
### 2026-05-13 Prefix2 Confirmation Result
|
|
|
|
Capture:
|
|
|
|
- `captures/rcp-matrix-cmd15-prefix2-confirm.txt`
|
|
|
|
Test shape:
|
|
|
|
- `p1=0x00`
|
|
- `p2=0x06`, `0x07`, `0x08`, `0x0E`, `0x0F`
|
|
- `cmd=0x15`
|
|
- `state=0x00`
|
|
- `value=0x80`
|
|
|
|
Screen observations:
|
|
|
|
| Prefix2 | TX frame | Screen marker |
|
|
| ---: | --- | --- |
|
|
| `0x06` | `00 06 15 00 80 C9` | `CONNECT NOT ACT` |
|
|
| `0x07` | `00 07 15 00 80 C8` | none recorded |
|
|
| `0x08` | `00 08 15 00 80 C7` | `CONNECT NOT ACT` |
|
|
| `0x0E` | `00 0E 15 00 80 C1` | `CONNECT NOT ACT` |
|
|
| `0x0F` | `00 0F 15 00 80 C0` | none recorded |
|
|
|
|
Analyzer result:
|
|
|
|
- 65 heartbeat RX frames: `00 00 00 00 80 DA`.
|
|
- 14 apparent non-heartbeat RX frames after `p2=0x0F`:
|
|
`00 00 00 80 DA 00`.
|
|
- No other RCP-to-host frame shape was observed.
|
|
|
|
Interpretation:
|
|
|
|
- `p2=0x07` and `p2=0x0F` again failed to produce a recorded screen marker,
|
|
while neighboring values did.
|
|
- The apparent `00 00 00 80 DA 00` response after `p2=0x0F` is probably a
|
|
one-byte framing slip of the normal heartbeat stream, because it is exactly
|
|
the heartbeat sequence viewed from byte offset 1:
|
|
`00 00 00 00 80 DA 00 00 ...`.
|
|
- Because the shifted heartbeat also satisfies the current XOR checksum
|
|
hypothesis, checksum validity alone is not enough to prove frame alignment.
|
|
|
|
Recommended raw confirmation for `p2=0x0F`:
|
|
|
|
```powershell
|
|
python scripts/serial_probe_response.py --port COM5 --tx-frame "00 0F 15 00 80 C0" --repeat 1 --delay 1.5 --after 5 --frame-size 0 --log captures/rcp-prefix2-0f-raw.txt
|
|
```
|
|
|
|
Then repeat for `p2=0x07`:
|
|
|
|
```powershell
|
|
python scripts/serial_probe_response.py --port COM5 --tx-frame "00 07 15 00 80 C8" --repeat 1 --delay 1.5 --after 5 --frame-size 0 --log captures/rcp-prefix2-07-raw.txt
|
|
```
|
|
|
|
Raw capture avoids imposing 6-byte alignment on the received stream, so it
|
|
should show whether the apparent non-heartbeat is a real frame or just a shifted
|
|
view of the heartbeat.
|
|
|
|
### Series Resistor Note
|
|
|
|
Current host-to-RCP tests use a series resistor between adapter `TXD` and RCP
|
|
pin 7 as a protection measure. A 4.7 kOhm series resistor should normally still
|
|
work with a high-impedance RS-232 receiver input, so it is unlikely to explain a
|
|
selective pattern where nearby checksum-valid frames behave differently.
|
|
|
|
Possible resistor-related failure modes:
|
|
|
|
- If the RCP input is much lower impedance than expected, 4.7 kOhm could reduce
|
|
the voltage swing at pin 7.
|
|
- If the input is clamped internally, the resistor may limit current enough to
|
|
make the received waveform marginal.
|
|
- Marginal signaling would more likely produce random missed/garbled frames
|
|
than a repeatable distinction between specific prefix values.
|
|
|
|
Low-risk check:
|
|
|
|
- Measure pin 7 relative to pin 9 on the RCP side of the resistor while the
|
|
adapter is idle; it should show a strong RS-232 idle level, not near 0 V.
|
|
- If testing without the resistor, first try a smaller protection resistor such
|
|
as 1 kOhm rather than going straight to a direct connection.
|
|
- Compare one known-trigger frame, such as `00 06 15 00 80 C9`, and one
|
|
suspected non-trigger frame, such as `00 07 15 00 80 C8`, using the same reset
|
|
procedure.
|
|
|
|
### Direct Response Sweep Without Screen Logging
|
|
|
|
For response hunting, use `scripts/serial_direct_response_sweep.py` rather than
|
|
the older fixed-frame sweep. It sends checksum-valid 6-byte host frames, but
|
|
reads pin 4 as raw bytes and checks whether the received data can be explained
|
|
as the repeated heartbeat:
|
|
|
|
```text
|
|
00 00 00 00 80 DA
|
|
```
|
|
|
|
This avoids treating shifted heartbeat bytes such as `00 00 00 80 DA 00` as a
|
|
new response frame.
|
|
|
|
Recommended first direct sweep:
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0x00-0xFF" --states 0x00 --values 0x80 --after-each 0.6 --stop-on-anomaly --log captures/rcp-direct-cmd-00-ff.txt
|
|
```
|
|
|
|
For a long sweep where every anomaly should be logged but the panel needs a
|
|
fresh power cycle before continuing, use `--pause-on-anomaly` instead of
|
|
`--stop-on-anomaly`. After the prompt, power-cycle the RCP, wait for the normal
|
|
heartbeat, then press Enter.
|
|
|
|
What to watch for:
|
|
|
|
- If the script reports `Anomalies: 0`, the panel never sent raw bytes that
|
|
differed from the heartbeat stream during this sweep.
|
|
- If it stops on an anomaly, preserve the log and rerun only the reported frame
|
|
with raw capture before assuming it is a real response.
|
|
- Keep the same resistor/wiring setup for this run so the result remains
|
|
comparable to the earlier observations.
|
|
|
|
If the command-only direct sweep finds nothing, the next direct grid should be
|
|
split into two chunks to stay within the default safety limit:
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --prefix2s "0x00-0x0F" --commands "0x00-0x1F" --states 0x00 --values 0x80 --after-each 0.4 --stop-on-anomaly --log captures/rcp-direct-p2-00-0f-cmd-00-1f.txt
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --prefix2s "0x00-0x0F" --commands "0x20-0x3F" --states 0x00 --values 0x80 --after-each 0.4 --stop-on-anomaly --log captures/rcp-direct-p2-00-0f-cmd-20-3f.txt
|
|
```
|
|
|
|
### 2026-05-13 Direct Command Sweep Response Hit
|
|
|
|
Capture:
|
|
|
|
- `captures/rcp-direct-cmd-00-ff.txt`
|
|
|
|
Sweep shape:
|
|
|
|
- `p1=0x00`
|
|
- `p2=0x00`
|
|
- `cmd=0x00-0xFF`
|
|
- `state=0x00`
|
|
- `value=0x80`
|
|
- Stop on first raw RX anomaly.
|
|
|
|
Important result:
|
|
|
|
- The sweep stopped immediately after transmitting command `0xB5`:
|
|
`00 00 B5 00 80 6F`.
|
|
- The previous transmitted command was `0xB4`: `00 00 B4 00 80 6E`, about
|
|
0.6 seconds earlier.
|
|
- The RCP produced repeated non-heartbeat frames:
|
|
`07 80 6D 20 D8 48`.
|
|
- Final raw capture showed the same frame repeated, then the panel returned to
|
|
the normal heartbeat `00 00 00 00 80 DA`.
|
|
|
|
Observed response:
|
|
|
|
```text
|
|
07 80 6D 20 D8 48
|
|
07 80 6D 20 D8 48
|
|
07 80 6D 20 D8 48
|
|
...
|
|
00 00 00 00 80 DA
|
|
```
|
|
|
|
Checksum check:
|
|
|
|
- `5A xor 07 xor 80 xor 6D xor 20 xor D8 = 48`.
|
|
- This means `07 80 6D 20 D8 48` is a real checksum-valid 6-byte frame under the
|
|
current checksum hypothesis, not a shifted heartbeat artifact.
|
|
|
|
Interpretation:
|
|
|
|
- This is the first confirmed non-heartbeat RCP-to-host serial response on pin
|
|
4 during host-frame probing.
|
|
- `cmd=0xB5` is the most likely trigger, but `cmd=0xB4` should be retested
|
|
because it was sent one read window earlier and delayed responses are possible.
|
|
- The response frame shape suggests the RCP may be reporting a status or
|
|
identity-like frame with `p1=0x07`, `p2=0x80`, `cmd=0x6D`, `state=0x20`,
|
|
`value=0xD8`.
|
|
|
|
Recommended confirmation tests:
|
|
|
|
```powershell
|
|
python scripts/serial_probe_response.py --port COM5 --tx-frame "00 00 B4 00 80 6E" --repeat 1 --delay 1.5 --after 5 --frame-size 0 --log captures/rcp-confirm-cmd-b4-raw.txt
|
|
python scripts/serial_probe_response.py --port COM5 --tx-frame "00 00 B5 00 80 6F" --repeat 1 --delay 1.5 --after 5 --frame-size 0 --log captures/rcp-confirm-cmd-b5-raw.txt
|
|
python scripts/serial_probe_response.py --port COM5 --tx-frame "00 00 B6 00 80 6C" --repeat 1 --delay 1.5 --after 5 --frame-size 0 --log captures/rcp-confirm-cmd-b6-raw.txt
|
|
```
|
|
|
|
If `cmd=0xB5` reliably triggers the `07 80 6D 20 D8 48` response, test whether
|
|
the response depends on the state/value fields:
|
|
|
|
```powershell
|
|
python scripts/serial_probe_matrix.py --port COM5 --commands 0xB5 --states "0x00 0x80" --values "0x00 0x80" --after-each 1.2 --prompt-screen --log captures/rcp-matrix-cmd-b5-state-value.txt
|
|
```
|
|
|
|
### 2026-05-13 B4/B5/B6 Single-Frame Confirmation
|
|
|
|
Captures:
|
|
|
|
- `captures/rcp-confirm-cmd-b4-raw.txt`
|
|
- `captures/rcp-confirm-cmd-b5-raw.txt`
|
|
- `captures/rcp-confirm-cmd-b6-raw.txt`
|
|
|
|
Single frames tested:
|
|
|
|
| Command | TX frame | Pin 4 result |
|
|
| ---: | --- | --- |
|
|
| `0xB4` | `00 00 B4 00 80 6E` | heartbeat only |
|
|
| `0xB5` | `00 00 B5 00 80 6F` | heartbeat only |
|
|
| `0xB6` | `00 00 B6 00 80 6C` | heartbeat only |
|
|
|
|
Interpretation:
|
|
|
|
- The earlier `07 80 6D 20 D8 48` response did not reproduce from isolated
|
|
single-frame `B4`, `B5`, or `B6` tests.
|
|
- The response may require prior sweep history, a command sequence, repeated
|
|
cadence, or a temporary parser/session state produced by many earlier frames.
|
|
- The `B5` frame is still the best suspect because the direct sweep reported the
|
|
anomaly in the read window immediately after transmitting `B5`, but it is not
|
|
sufficient by itself in a fresh single-frame test.
|
|
|
|
Recommended focused replay:
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0xB0-0xB8" --states 0x00 --values 0x80 --after-each 0.6 --stop-on-anomaly --log captures/rcp-direct-cmd-b0-b8-replay.txt
|
|
```
|
|
|
|
If that does not reproduce the response, try the same range with a shorter
|
|
cadence to better mimic the long sweep:
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0xB0-0xB8" --states 0x00 --values 0x80 --after-each 0.25 --stop-on-anomaly --log captures/rcp-direct-cmd-b0-b8-fast.txt
|
|
```
|
|
|
|
If the focused range still does not reproduce it, rerun the longer sweep from
|
|
`0xA0-0xB8` rather than the full `0x00-0xFF` range:
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0xA0-0xB8" --states 0x00 --values 0x80 --after-each 0.6 --stop-on-anomaly --log captures/rcp-direct-cmd-a0-b8-replay.txt
|
|
```
|
|
|
|
### 2026-05-13 B0-B8 Focused Replay Hit
|
|
|
|
Capture:
|
|
|
|
- `captures/rcp-direct-cmd-b0-b8-replay.txt`
|
|
|
|
Replay shape:
|
|
|
|
- `p1=0x00`
|
|
- `p2=0x00`
|
|
- `cmd=0xB0-0xB8`
|
|
- `state=0x00`
|
|
- `value=0x80`
|
|
- `after-each=0.6`
|
|
- Stop on first raw RX anomaly.
|
|
|
|
Important result:
|
|
|
|
- The sweep sent `cmd=0xB0`, then `cmd=0xB1`.
|
|
- The anomaly was captured in the read window immediately after transmitting
|
|
`cmd=0xB1`: `00 00 B1 00 80 6B`.
|
|
- The RCP emitted one checksum-valid non-heartbeat frame:
|
|
`07 80 6C 20 D8 49`.
|
|
- The final read window returned to heartbeat-only traffic.
|
|
|
|
Checksum check:
|
|
|
|
- `5A xor 07 xor 80 xor 6C xor 20 xor D8 = 49`.
|
|
|
|
Comparison with the earlier full sweep hit:
|
|
|
|
| Trigger window | RCP response |
|
|
| --- | --- |
|
|
| After `cmd=0xB1` in focused `B0-B8` replay | `07 80 6C 20 D8 49` |
|
|
| After `cmd=0xB5` in full `00-FF` sweep | `07 80 6D 20 D8 48` |
|
|
|
|
Interpretation:
|
|
|
|
- The non-heartbeat response is reproducible with a short local sequence, so it
|
|
does not require the entire `0x00-0xFF` sweep history.
|
|
- The response may be sequence-dependent: `B1` alone is not yet proven as the
|
|
trigger because `B0` was sent one window earlier.
|
|
- The response command byte changed from `0x6D` to `0x6C`, which suggests the
|
|
RCP may be returning a status/identity code related to the host command or to
|
|
internal state.
|
|
|
|
Recommended tight confirmations:
|
|
|
|
```powershell
|
|
python scripts/serial_probe_response.py --port COM5 --tx-frame "00 00 B0 00 80 6A" --repeat 1 --delay 1.5 --after 5 --frame-size 0 --log captures/rcp-confirm-cmd-b0-raw.txt
|
|
python scripts/serial_probe_response.py --port COM5 --tx-frame "00 00 B1 00 80 6B" --repeat 1 --delay 1.5 --after 5 --frame-size 0 --log captures/rcp-confirm-cmd-b1-raw.txt
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0xB0-0xB1" --states 0x00 --values 0x80 --after-each 0.6 --stop-on-anomaly --log captures/rcp-direct-cmd-b0-b1-replay.txt
|
|
```
|
|
|
|
If `B1` alone is heartbeat-only but `B0-B1` reproduces the response, treat
|
|
`B0 -> B1` as a required two-frame sequence.
|
|
|
|
### 2026-05-13 B0/B1 Tight Confirmation Result
|
|
|
|
Captures:
|
|
|
|
- `captures/rcp-confirm-cmd-b0-raw.txt`
|
|
- `captures/rcp-confirm-cmd-b1-raw.txt`
|
|
- `captures/rcp-direct-cmd-b0-b1-replay.txt`
|
|
|
|
Results:
|
|
|
|
| Test | Pin 4 result |
|
|
| --- | --- |
|
|
| Single `B0`: `00 00 B0 00 80 6A` | heartbeat only |
|
|
| Single `B1`: `00 00 B1 00 80 6B` | heartbeat only |
|
|
| Sequence `B0 -> B1` | heartbeat only, `Anomalies: 0` |
|
|
|
|
Interpretation:
|
|
|
|
- The `07 80 6C 20 D8 49` response from the `B0-B8` replay did not reproduce
|
|
with the minimal `B0 -> B1` sequence.
|
|
- The response may be intermittent, cadence-sensitive, dependent on a longer
|
|
sequence such as `B0-B8`, or affected by panel state that was not identical
|
|
between runs.
|
|
- The next priority is measuring reproducibility of the same short range rather
|
|
than expanding the search space.
|
|
|
|
Recommended reproducibility test:
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0xB0-0xB8" --states 0x00 --values 0x80 --after-each 0.6 --cycles 5 --cycle-pause 2 --log captures/rcp-direct-cmd-b0-b8-cycles.txt
|
|
```
|
|
|
|
Run this without `--stop-on-anomaly` so all five cycles complete and the log can
|
|
show whether the response happens consistently, intermittently, or only once.
|
|
|
|
### Power-Cycle Isolation Test Plan
|
|
|
|
Use this plan when intentionally power-cycling the RCP between tests. The goal
|
|
is to distinguish a cold-boot reproducible protocol response from a response
|
|
that only appears after accumulated parser/session state.
|
|
|
|
Before each test:
|
|
|
|
1. Stop any serial script.
|
|
2. Power off the RCP.
|
|
3. Wait at least 5 seconds.
|
|
4. Power on the RCP.
|
|
5. Wait until the panel is stable and heartbeat traffic has resumed.
|
|
6. Run exactly one test command.
|
|
|
|
Keep the wiring and series resistor the same between tests unless the test name
|
|
explicitly says otherwise.
|
|
|
|
#### Set A: Cold-Boot Reproducibility
|
|
|
|
Run these first. They test whether the `B0-B8` response is repeatable from a
|
|
fresh power cycle.
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0xB0-0xB8" --states 0x00 --values 0x80 --settle 3 --after-each 0.6 --stop-on-anomaly --log captures/rcp-powercycle-a1-b0-b8.txt
|
|
```
|
|
|
|
Power-cycle, then:
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0xB0-0xB8" --states 0x00 --values 0x80 --settle 3 --after-each 0.6 --stop-on-anomaly --log captures/rcp-powercycle-a2-b0-b8.txt
|
|
```
|
|
|
|
Power-cycle, then:
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0xB0-0xB8" --states 0x00 --values 0x80 --settle 3 --after-each 0.6 --stop-on-anomaly --log captures/rcp-powercycle-a3-b0-b8.txt
|
|
```
|
|
|
|
Expected useful outcomes:
|
|
|
|
- If all three produce the same response, the sequence is cold-boot
|
|
reproducible.
|
|
- If only some produce a response, the behavior may be timing-sensitive or
|
|
intermittent.
|
|
- If none produce a response, the earlier hit likely depended on prior panel
|
|
state.
|
|
|
|
#### Set B: Minimum Sequence Length
|
|
|
|
Run this set only if Set A produces at least one response. Power-cycle between
|
|
each command. These tests find the shortest command prefix that can trigger a
|
|
non-heartbeat response.
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0xB0-0xB1" --states 0x00 --values 0x80 --settle 3 --after-each 0.6 --stop-on-anomaly --log captures/rcp-powercycle-b1-b0-b1.txt
|
|
```
|
|
|
|
Power-cycle, then:
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0xB0-0xB2" --states 0x00 --values 0x80 --settle 3 --after-each 0.6 --stop-on-anomaly --log captures/rcp-powercycle-b2-b0-b2.txt
|
|
```
|
|
|
|
Power-cycle, then:
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0xB0-0xB3" --states 0x00 --values 0x80 --settle 3 --after-each 0.6 --stop-on-anomaly --log captures/rcp-powercycle-b3-b0-b3.txt
|
|
```
|
|
|
|
Power-cycle, then:
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0xB0-0xB4" --states 0x00 --values 0x80 --settle 3 --after-each 0.6 --stop-on-anomaly --log captures/rcp-powercycle-b4-b0-b4.txt
|
|
```
|
|
|
|
#### Set C: Cadence Sensitivity
|
|
|
|
Run this set if Set A is inconsistent or if Set B does not identify a clean
|
|
minimum sequence. Power-cycle between each command.
|
|
|
|
Slow cadence:
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0xB0-0xB8" --states 0x00 --values 0x80 --settle 3 --after-each 1.2 --stop-on-anomaly --log captures/rcp-powercycle-c1-b0-b8-slow.txt
|
|
```
|
|
|
|
Fast cadence:
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0xB0-0xB8" --states 0x00 --values 0x80 --settle 3 --after-each 0.25 --stop-on-anomaly --log captures/rcp-powercycle-c2-b0-b8-fast.txt
|
|
```
|
|
|
|
Very fast cadence:
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0xB0-0xB8" --states 0x00 --values 0x80 --settle 3 --after-each 0.1 --stop-on-anomaly --log captures/rcp-powercycle-c3-b0-b8-very-fast.txt
|
|
```
|
|
|
|
#### Set D: Control Tests
|
|
|
|
Run these if the `B0-B8` range is producing responses. Power-cycle between
|
|
each command. These confirm the response is specific to the `B0` range.
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0xA8-0xAF" --states 0x00 --values 0x80 --settle 3 --after-each 0.6 --stop-on-anomaly --log captures/rcp-powercycle-d1-a8-af-control.txt
|
|
```
|
|
|
|
Power-cycle, then:
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0xB8-0xBF" --states 0x00 --values 0x80 --settle 3 --after-each 0.6 --stop-on-anomaly --log captures/rcp-powercycle-d2-b8-bf-control.txt
|
|
```
|
|
|
|
If a response appears in control ranges too, the trigger may be a broader
|
|
command class rather than a specific `B0-B8` sequence.
|
|
|
|
### 2026-05-13 Power-Cycle Set A Result
|
|
|
|
Captures:
|
|
|
|
- `captures/rcp-powercycle-a1-b0-b8.txt`
|
|
- `captures/rcp-powercycle-a2-b0-b8.txt`
|
|
- `captures/rcp-powercycle-a3-b0-b8.txt`
|
|
|
|
Each run was performed after a panel power cycle. All three runs produced the
|
|
same non-heartbeat response.
|
|
|
|
| Run | Trigger window | RCP response | Result |
|
|
| --- | --- | --- | --- |
|
|
| A1 | after `B1`: `00 00 B1 00 80 6B` | `07 80 6C 20 D8 49` repeated | anomaly |
|
|
| A2 | after `B1`: `00 00 B1 00 80 6B` | `07 80 6C 20 D8 49` repeated | anomaly |
|
|
| A3 | after `B1`: `00 00 B1 00 80 6B` | `07 80 6C 20 D8 49` repeated | anomaly |
|
|
|
|
Observed raw pattern in each run:
|
|
|
|
```text
|
|
07 80 6C 20 D8 49
|
|
07 80 6C 20 D8 49
|
|
07 80 6C 20 D8 49
|
|
...
|
|
00 00 00 00 80 DA
|
|
```
|
|
|
|
Interpretation:
|
|
|
|
- The `B0-B8` response is cold-boot reproducible.
|
|
- The response appears immediately after the `B1` transmit window when the test
|
|
starts from a fresh power cycle.
|
|
- The earlier `B0 -> B1` heartbeat-only result was likely affected by panel
|
|
state from previous experiments, timing, or not starting from an equivalent
|
|
cold condition.
|
|
- The next test should determine whether `B0 -> B1` is sufficient from a fresh
|
|
power cycle, or whether the script/test context of the `B0-B8` run matters.
|
|
|
|
Recommended next power-cycle tests:
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0xB0-0xB1" --states 0x00 --values 0x80 --settle 3 --after-each 0.6 --stop-on-anomaly --log captures/rcp-powercycle-b1-b0-b1.txt
|
|
```
|
|
|
|
Power-cycle, then:
|
|
|
|
```powershell
|
|
python scripts/serial_probe_response.py --port COM5 --tx-frame "00 00 B1 00 80 6B" --repeat 1 --delay 3 --after 5 --frame-size 0 --log captures/rcp-powercycle-b1-alone-raw.txt
|
|
```
|
|
|
|
If `B0-B1` reproduces but `B1` alone does not, treat `B0 -> B1` as the minimum
|
|
cold-boot sequence.
|
|
|
|
### 2026-05-13 Minimum Cold-Boot Sequence Result
|
|
|
|
Captures:
|
|
|
|
- `captures/rcp-powercycle-b0.txt`
|
|
- `captures/rcp-powercycle-b1-b0-b1.txt`
|
|
- `captures/rcp-powercycle-b1-alone-raw.txt`
|
|
|
|
Each test was run after a panel power cycle.
|
|
|
|
| Test | TX frame(s) | Pin 4 result |
|
|
| --- | --- | --- |
|
|
| `B0` alone | `00 00 B0 00 80 6A` | heartbeat only, `Anomalies: 0` |
|
|
| `B1` alone | `00 00 B1 00 80 6B` | heartbeat only |
|
|
| `B0 -> B1` | `00 00 B0 00 80 6A`, then `00 00 B1 00 80 6B` | `07 80 6C 20 D8 49` repeated |
|
|
|
|
Conclusion:
|
|
|
|
- The minimum confirmed cold-boot trigger is the two-frame sequence:
|
|
|
|
```text
|
|
Host -> RCP: 00 00 B0 00 80 6A
|
|
Host -> RCP: 00 00 B1 00 80 6B
|
|
RCP -> Host: 07 80 6C 20 D8 49
|
|
```
|
|
|
|
- Neither `B0` nor `B1` is sufficient alone from a cold panel.
|
|
- `B0` appears to prime the panel, and `B1` completes the query/trigger.
|
|
- The response repeats for a short period, then the panel returns to the normal
|
|
heartbeat `00 00 00 00 80 DA`.
|
|
|
|
Recommended next tests:
|
|
|
|
1. Timing sensitivity between `B0` and `B1`.
|
|
2. State/value sensitivity of the `B0 -> B1` pair.
|
|
3. Whether the response changes when sending nearby pairs such as `B1 -> B2`,
|
|
`B2 -> B3`, etc.
|
|
|
|
Suggested timing tests, with power cycle between each:
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0xB0-0xB1" --states 0x00 --values 0x80 --settle 3 --after-each 0.1 --stop-on-anomaly --log captures/rcp-powercycle-timing-b0-b1-100ms.txt
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0xB0-0xB1" --states 0x00 --values 0x80 --settle 3 --after-each 1.2 --stop-on-anomaly --log captures/rcp-powercycle-timing-b0-b1-1200ms.txt
|
|
```
|
|
|
|
Suggested nearby-pair tests, with power cycle between each:
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0xB1-0xB2" --states 0x00 --values 0x80 --settle 3 --after-each 0.6 --stop-on-anomaly --log captures/rcp-powercycle-pair-b1-b2.txt
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0xB2-0xB3" --states 0x00 --values 0x80 --settle 3 --after-each 0.6 --stop-on-anomaly --log captures/rcp-powercycle-pair-b2-b3.txt
|
|
```
|
|
|
|
### 2026-05-13 B0-B1 Timing Result
|
|
|
|
Captures:
|
|
|
|
- `captures/rcp-powercycle-timing-b0-b1-100ms.txt`
|
|
- `captures/rcp-powercycle-timing-b0-b1-1200ms.txt`
|
|
|
|
Each test was run after a panel power cycle.
|
|
|
|
| B0-to-B1 spacing | RCP response |
|
|
| ---: | --- |
|
|
| about 100 ms | `07 80 6C 20 D8 49` |
|
|
| about 1200 ms | `07 80 6C 20 D8 49` repeated |
|
|
|
|
Interpretation:
|
|
|
|
- The `B0 -> B1` trigger is not tightly timing-sensitive across the tested
|
|
range.
|
|
- `B0` appears to prime a state that remains valid for at least about 1.2
|
|
seconds.
|
|
- The sequence order is more important than exact short timing.
|
|
|
|
Recommended next tests:
|
|
|
|
Power-cycle between each test. Check whether the trigger is specific to the
|
|
`B0 -> B1` pair or whether nearby ordered pairs also trigger related responses:
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0xB1-0xB2" --states 0x00 --values 0x80 --settle 3 --after-each 0.6 --stop-on-anomaly --log captures/rcp-powercycle-pair-b1-b2.txt
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0xB2-0xB3" --states 0x00 --values 0x80 --settle 3 --after-each 0.6 --stop-on-anomaly --log captures/rcp-powercycle-pair-b2-b3.txt
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0xAF-0xB0" --states 0x00 --values 0x80 --settle 3 --after-each 0.6 --stop-on-anomaly --log captures/rcp-powercycle-pair-af-b0.txt
|
|
```
|
|
|
|
### 2026-05-13 Nearby Pair Results
|
|
|
|
Captures:
|
|
|
|
- `captures/rcp-powercycle-pair-af-b0.txt`
|
|
- `captures/rcp-powercycle-pair-b1-b2.txt`
|
|
- `captures/rcp-powercycle-pair-b2-b3.txt`
|
|
|
|
Each test was run after a panel power cycle.
|
|
|
|
| Host pair | Second frame window | RCP response |
|
|
| --- | --- | --- |
|
|
| `AF -> B0` | `00 00 B0 00 80 6A` | `07 80 6C 60 30 E1` repeated |
|
|
| `B1 -> B2` | `00 00 B2 00 80 68` | `07 80 36 10 0C F7` repeated |
|
|
| `B2 -> B3` | `00 00 B3 00 80 69` | `07 80 36 10 2C D7` repeated |
|
|
|
|
Previously confirmed:
|
|
|
|
| Host pair | Second frame window | RCP response |
|
|
| --- | --- | --- |
|
|
| `B0 -> B1` | `00 00 B1 00 80 6B` | `07 80 6C 20 D8 49` repeated |
|
|
|
|
Checksum checks:
|
|
|
|
- `07 80 6C 60 30 E1`: checksum valid.
|
|
- `07 80 36 10 0C F7`: checksum valid.
|
|
- `07 80 36 10 2C D7`: checksum valid.
|
|
|
|
Interpretation:
|
|
|
|
- The RCP responds to multiple adjacent two-frame host sequences in the
|
|
`AF-B3` region, not only `B0 -> B1`.
|
|
- The response appears in the read window after the second frame of each pair.
|
|
- The response payload changes by pair, which suggests these are real command
|
|
queries or status reads rather than a generic link-present acknowledgement.
|
|
- The repeated response pattern still returns to the normal heartbeat afterward.
|
|
|
|
Emerging map:
|
|
|
|
| Host sequence | RCP response fields |
|
|
| --- | --- |
|
|
| `AF -> B0` | `p1=07 p2=80 cmd=6C state=60 value=30 checksum=E1` |
|
|
| `B0 -> B1` | `p1=07 p2=80 cmd=6C state=20 value=D8 checksum=49` |
|
|
| `B1 -> B2` | `p1=07 p2=80 cmd=36 state=10 value=0C checksum=F7` |
|
|
| `B2 -> B3` | `p1=07 p2=80 cmd=36 state=10 value=2C checksum=D7` |
|
|
|
|
Recommended next tests:
|
|
|
|
Power-cycle between each. First continue the adjacent-pair map:
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0xB3-0xB4" --states 0x00 --values 0x80 --settle 3 --after-each 0.6 --stop-on-anomaly --log captures/rcp-powercycle-pair-b3-b4.txt
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0xB4-0xB5" --states 0x00 --values 0x80 --settle 3 --after-each 0.6 --stop-on-anomaly --log captures/rcp-powercycle-pair-b4-b5.txt
|
|
```
|
|
|
|
Then test whether adjacency and order matter:
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0xB0 0xB2" --states 0x00 --values 0x80 --settle 3 --after-each 0.6 --stop-on-anomaly --log captures/rcp-powercycle-pair-b0-b2-skip.txt
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0xB1 0xB0" --states 0x00 --values 0x80 --settle 3 --after-each 0.6 --stop-on-anomaly --log captures/rcp-powercycle-pair-b1-b0-reverse.txt
|
|
```
|
|
|
|
### 2026-05-13 Additional Pair/Control Results
|
|
|
|
User observation:
|
|
|
|
- All tests still showed `CONNECT NOT ACT` on the RCP/CCU screen, with no other
|
|
visible state change.
|
|
|
|
Serial captures:
|
|
|
|
- `captures/rcp-powercycle-pair-b3-b4.txt`
|
|
- `captures/rcp-powercycle-pair-b4-b5.txt`
|
|
- `captures/rcp-powercycle-pair-b0-b2-skip.txt`
|
|
- `captures/rcp-powercycle-pair-b1-b0-reverse.txt`
|
|
|
|
Each test was run after a panel power cycle.
|
|
|
|
| Host pair | Second frame window | RCP response |
|
|
| --- | --- | --- |
|
|
| `B3 -> B4` | `00 00 B4 00 80 6E` | `07 80 6D 40 30 C0` repeated |
|
|
| `B4 -> B5` | `00 00 B5 00 80 6F` | `07 80 6D 20 D8 48` repeated |
|
|
| `B0 -> B2` | `00 00 B2 00 80 68` | `07 80 36 10 0C F7` repeated |
|
|
| `B1 -> B0` | `00 00 B0 00 80 6A` | `07 80 6C 40 30 C1` repeated |
|
|
|
|
Interpretation:
|
|
|
|
- The screen state remains `CONNECT NOT ACT`, but pin 4 responses are changing
|
|
in a structured, checksum-valid way.
|
|
- The skip test `B0 -> B2` produced the same response as `B1 -> B2`, so the
|
|
second command may be the main selector once any valid priming frame is sent.
|
|
- The reverse test `B1 -> B0` also produced a valid response, so strict
|
|
ascending adjacency is not required.
|
|
- Current model: a first host frame primes/enters a response mode, and the
|
|
second host frame selects a status/query response.
|
|
|
|
Expanded observed response map:
|
|
|
|
| Second host command | Observed response(s) |
|
|
| ---: | --- |
|
|
| `B0` | `07 80 6C 60 30 E1` after `AF -> B0`; `07 80 6C 40 30 C1` after `B1 -> B0` |
|
|
| `B1` | `07 80 6C 20 D8 49` after `B0 -> B1` |
|
|
| `B2` | `07 80 36 10 0C F7` after `B1 -> B2` and `B0 -> B2` |
|
|
| `B3` | `07 80 36 10 2C D7` after `B2 -> B3` |
|
|
| `B4` | `07 80 6D 40 30 C0` after `B3 -> B4` |
|
|
| `B5` | `07 80 6D 20 D8 48` after `B4 -> B5` |
|
|
|
|
Recommended next tests:
|
|
|
|
Power-cycle between each. Test whether a generic primer plus selected second
|
|
command is enough:
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0x00 0xB0" --states 0x00 --values 0x80 --settle 3 --after-each 0.6 --stop-on-anomaly --log captures/rcp-powercycle-primer-00-b0.txt
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0x00 0xB2" --states 0x00 --values 0x80 --settle 3 --after-each 0.6 --stop-on-anomaly --log captures/rcp-powercycle-primer-00-b2.txt
|
|
```
|
|
|
|
Then map the next selected second commands:
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0xB5-0xB6" --states 0x00 --values 0x80 --settle 3 --after-each 0.6 --stop-on-anomaly --log captures/rcp-powercycle-pair-b5-b6.txt
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0xB6-0xB7" --states 0x00 --values 0x80 --settle 3 --after-each 0.6 --stop-on-anomaly --log captures/rcp-powercycle-pair-b6-b7.txt
|
|
```
|
|
|
|
### 2026-05-13 Generic Primer and B6-B7 Results
|
|
|
|
Captures:
|
|
|
|
- `captures/rcp-powercycle-primer-00-b0.txt`
|
|
- `captures/rcp-powercycle-primer-00-b2.txt`
|
|
- `captures/rcp-powercycle-pair-b5-b6.txt`
|
|
- `captures/rcp-powercycle-pair-b6-b7.txt`
|
|
|
|
Each test was run after a panel power cycle.
|
|
|
|
| Host pair | Second frame window | RCP response |
|
|
| --- | --- | --- |
|
|
| `00 -> B0` | `00 00 B0 00 80 6A` | `07 80 6C 40 30 C1` repeated |
|
|
| `00 -> B2` | `00 00 B2 00 80 68` | `07 80 36 10 0C F7` repeated |
|
|
| `B5 -> B6` | `00 00 B6 00 80 6C` | `07 80 1B 08 C6 08` repeated |
|
|
| `B6 -> B7` | `00 00 B7 00 80 6D` | `07 80 1B 08 D6 18` repeated |
|
|
|
|
Checksum checks:
|
|
|
|
- `07 80 6C 40 30 C1`: checksum valid.
|
|
- `07 80 36 10 0C F7`: checksum valid.
|
|
- `07 80 1B 08 C6 08`: checksum valid.
|
|
- `07 80 1B 08 D6 18`: checksum valid.
|
|
|
|
Interpretation:
|
|
|
|
- `00 -> B0` produced the same response as `B1 -> B0`.
|
|
- `00 -> B2` produced the same response as `B0 -> B2` and `B1 -> B2`.
|
|
- This supports the model that the first frame can be a generic valid primer,
|
|
and the second frame selects the response.
|
|
- The `B6` and `B7` selected responses introduce another response command class
|
|
(`cmd=0x1B`) with changing value bytes.
|
|
|
|
Updated selected-command map:
|
|
|
|
| Selected second command | Observed response |
|
|
| ---: | --- |
|
|
| `B0` | `07 80 6C 40 30 C1` after `00 -> B0` and `B1 -> B0`; `07 80 6C 60 30 E1` after `AF -> B0` |
|
|
| `B1` | `07 80 6C 20 D8 49` after `B0 -> B1` |
|
|
| `B2` | `07 80 36 10 0C F7` after `00 -> B2`, `B0 -> B2`, and `B1 -> B2` |
|
|
| `B3` | `07 80 36 10 2C D7` after `B2 -> B3` |
|
|
| `B4` | `07 80 6D 40 30 C0` after `B3 -> B4` |
|
|
| `B5` | `07 80 6D 20 D8 48` after `B4 -> B5` |
|
|
| `B6` | `07 80 1B 08 C6 08` after `B5 -> B6` |
|
|
| `B7` | `07 80 1B 08 D6 18` after `B6 -> B7` |
|
|
|
|
Recommended next controls:
|
|
|
|
Power-cycle between each. First prove whether `B2`, `B6`, and `B7` need a
|
|
primer, or whether they can respond as single frames from cold boot:
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands 0xB2 --states 0x00 --values 0x80 --settle 3 --after-each 0.6 --stop-on-anomaly --log captures/rcp-powercycle-single-b2.txt
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands 0xB6 --states 0x00 --values 0x80 --settle 3 --after-each 0.6 --stop-on-anomaly --log captures/rcp-powercycle-single-b6.txt
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands 0xB7 --states 0x00 --values 0x80 --settle 3 --after-each 0.6 --stop-on-anomaly --log captures/rcp-powercycle-single-b7.txt
|
|
```
|
|
|
|
Then continue the selected-command map using `00` as the primer:
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0x00 0xB3" --states 0x00 --values 0x80 --settle 3 --after-each 0.6 --stop-on-anomaly --log captures/rcp-powercycle-primer-00-b3.txt
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0x00 0xB4" --states 0x00 --values 0x80 --settle 3 --after-each 0.6 --stop-on-anomaly --log captures/rcp-powercycle-primer-00-b4.txt
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0x00 0xB5" --states 0x00 --values 0x80 --settle 3 --after-each 0.6 --stop-on-anomaly --log captures/rcp-powercycle-primer-00-b5.txt
|
|
```
|
|
|
|
### 2026-05-13 Single-Frame and One-Shot Primer Results
|
|
|
|
Captures:
|
|
|
|
- `captures/rcp-powercycle-single-b2.txt`
|
|
- `captures/rcp-powercycle-single-b6.txt`
|
|
- `captures/rcp-powercycle-single-b7.txt`
|
|
- `captures/rcp-powercycle-primer-00-b3.txt`
|
|
- `captures/rcp-powercycle-primer-00-b4.txt`
|
|
- `captures/rcp-powercycle-primer-00-b5.txt`
|
|
|
|
Single-frame controls, each after a panel power cycle:
|
|
|
|
| Test | Pin 4 result |
|
|
| --- | --- |
|
|
| `B2` alone | heartbeat only, `Anomalies: 0` |
|
|
| `B6` alone | heartbeat only, `Anomalies: 0` |
|
|
| `B7` alone | heartbeat only, `Anomalies: 0` |
|
|
|
|
Generic-primer map, each first run after a panel power cycle:
|
|
|
|
| Host pair | Second frame window | RCP response |
|
|
| --- | --- | --- |
|
|
| `00 -> B3` | `00 00 B3 00 80 69` | `07 80 36 10 2C D7` repeated |
|
|
| `00 -> B4` | `00 00 B4 00 80 6E` | `07 80 6D 40 30 C0` |
|
|
| `00 -> B5` | `00 00 B5 00 80 6F` | `07 80 6D 20 D8 48` repeated |
|
|
|
|
Repeated `00 -> B5` without power-cycling:
|
|
|
|
| Attempt | Power cycle before attempt? | Result |
|
|
| ---: | --- | --- |
|
|
| 1 | yes | `07 80 6D 20 D8 48` repeated |
|
|
| 2 | no | heartbeat only, `Anomalies: 0` |
|
|
| 3 | no | heartbeat only, `Anomalies: 0` |
|
|
|
|
Interpretation:
|
|
|
|
- A single selected command is not enough; the panel requires a preceding valid
|
|
primer frame.
|
|
- `00` works as a primer for `B0`, `B2`, `B3`, `B4`, and `B5`.
|
|
- The same primed query may be one-shot after power-up. After `00 -> B5`
|
|
returns its response, repeating `00 -> B5` without power-cycling does not
|
|
produce another non-heartbeat response.
|
|
- Future mapping should power-cycle before each selected-command test unless
|
|
intentionally studying latch/repeat behavior.
|
|
|
|
Current generic-primer selected-command map:
|
|
|
|
| Host query | RCP response |
|
|
| --- | --- |
|
|
| `00 -> B0` | `07 80 6C 40 30 C1` |
|
|
| `00 -> B2` | `07 80 36 10 0C F7` |
|
|
| `00 -> B3` | `07 80 36 10 2C D7` |
|
|
| `00 -> B4` | `07 80 6D 40 30 C0` |
|
|
| `00 -> B5` | `07 80 6D 20 D8 48` |
|
|
|
|
Recommended next tests:
|
|
|
|
Power-cycle before each query. Fill the missing `00 -> B1` entry and continue
|
|
the `00 -> selected` map:
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0x00 0xB1" --states 0x00 --values 0x80 --settle 3 --after-each 0.6 --stop-on-anomaly --log captures/rcp-powercycle-primer-00-b1.txt
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0x00 0xB6" --states 0x00 --values 0x80 --settle 3 --after-each 0.6 --stop-on-anomaly --log captures/rcp-powercycle-primer-00-b6.txt
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0x00 0xB7" --states 0x00 --values 0x80 --settle 3 --after-each 0.6 --stop-on-anomaly --log captures/rcp-powercycle-primer-00-b7.txt
|
|
```
|
|
|
|
Optional latch test, without power-cycling after the first run:
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0x00 0xB5" --states 0x00 --values 0x80 --settle 3 --after-each 0.6 --cycles 3 --cycle-pause 2 --log captures/rcp-latch-primer-00-b5-cycles.txt
|
|
```
|
|
|
|
## Current Inferred Behavior
|
|
|
|
The current evidence suggests the RCP is entering a discovery/query/status-read
|
|
phase, not a completed active-control handshake.
|
|
|
|
Working model:
|
|
|
|
```text
|
|
Host/CCU -> RCP: valid primer frame
|
|
Host/CCU -> RCP: selected query/status command
|
|
RCP -> Host/CCU: checksum-valid response frame repeated briefly
|
|
RCP -> Host/CCU: returns to heartbeat
|
|
```
|
|
|
|
Important details:
|
|
|
|
- Single selected commands such as `B2`, `B6`, and `B7` do not respond from a
|
|
cold panel.
|
|
- A preceding valid frame is required. `00 00 00 00 80 DA` works as a generic
|
|
primer for several selected commands.
|
|
- The second command selects the response payload.
|
|
- The LCD can remain `CONNECT NOT ACT` while serial responses vary in a
|
|
structured way. Serial response does not yet mean the active control session
|
|
is accepted.
|
|
- At least some primed queries appear one-shot after power-up. Repeating the
|
|
same primed query without power-cycling can produce only heartbeat traffic.
|
|
|
|
Likely protocol role:
|
|
|
|
- These `B0`-range commands may be a CCU discovery or capability/status query
|
|
phase.
|
|
- The CCU may query RCP model/capability/state blocks before sending a later
|
|
activation/session command.
|
|
- The next unknown is the command or command sequence that follows these
|
|
discovery responses and moves the panel from `CONNECT NOT ACT` to active.
|
|
|
|
## Primer-Candidate Broad Sweep
|
|
|
|
Use `scripts/serial_primer_candidate_sweep.py` for broader searches based on
|
|
the current primer/query model. It sends:
|
|
|
|
```text
|
|
primer frame -> candidate frame -> raw RX classification
|
|
```
|
|
|
|
For clean mapping, use `--prompt-power-cycle` and power-cycle before each
|
|
candidate. This avoids the one-shot/latch behavior contaminating later
|
|
candidates.
|
|
|
|
Example dry run:
|
|
|
|
```powershell
|
|
python scripts/serial_primer_candidate_sweep.py --port COM5 --candidates "0xB0-0xB7" --dry-run
|
|
```
|
|
|
|
Continue the known `B` range first:
|
|
|
|
```powershell
|
|
python scripts/serial_primer_candidate_sweep.py --port COM5 --candidates "0xB1 0xB6 0xB7 0xB8 0xB9 0xBA 0xBB 0xBC 0xBD 0xBE 0xBF" --prompt-power-cycle --stop-on-anomaly --log captures/rcp-primer-sweep-b1-bf.txt
|
|
```
|
|
|
|
Because `--stop-on-anomaly` stops at the first response, after each hit:
|
|
|
|
1. Save the reported candidate and response frame.
|
|
2. Power-cycle the panel.
|
|
3. Restart the sweep from the next unmapped candidate.
|
|
|
|
For non-stop mapping, omit `--stop-on-anomaly`, but still power-cycle at each
|
|
prompt:
|
|
|
|
```powershell
|
|
python scripts/serial_primer_candidate_sweep.py --port COM5 --candidates "0xB8-0xBF" --prompt-power-cycle --log captures/rcp-primer-sweep-b8-bf.txt
|
|
```
|
|
|
|
Suggested broad ranges after `B0-BF`:
|
|
|
|
```powershell
|
|
python scripts/serial_primer_candidate_sweep.py --port COM5 --candidates "0xA0-0xAF" --prompt-power-cycle --log captures/rcp-primer-sweep-a0-af.txt
|
|
python scripts/serial_primer_candidate_sweep.py --port COM5 --candidates "0xC0-0xCF" --prompt-power-cycle --log captures/rcp-primer-sweep-c0-cf.txt
|
|
python scripts/serial_primer_candidate_sweep.py --port COM5 --candidates "0x00-0x1F" --prompt-power-cycle --log captures/rcp-primer-sweep-00-1f.txt
|
|
```
|
|
|
|
Recommended first run:
|
|
|
|
```powershell
|
|
python scripts/serial_primer_candidate_sweep.py --port COM5 --candidates "0xB1 0xB6 0xB7 0xB8 0xB9 0xBA 0xBB 0xBC 0xBD 0xBE 0xBF" --prompt-power-cycle --log captures/rcp-primer-sweep-b1-bf.txt
|
|
```
|
|
|
|
## Primer Reuse and Sequential Query Tests
|
|
|
|
Two open questions:
|
|
|
|
1. After a cold boot, does the RCP only answer one selected query before it
|
|
latches/suppresses further responses?
|
|
2. Is a fresh primer required before every selected query, or can one primer
|
|
unlock several selected commands in sequence?
|
|
|
|
Use `scripts/serial_direct_response_sweep.py` for these tests because it can
|
|
send arbitrary command sequences without stopping between commands. For each
|
|
test below, power-cycle once before starting the script, then do not power-cycle
|
|
again until the script exits.
|
|
|
|
### Test S1: One Primer, Multiple Different Queries
|
|
|
|
Purpose: test whether one primer can unlock several different selected commands.
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0x00 0xB2 0xB3 0xB4 0xB5" --states 0x00 --values 0x80 --settle 3 --after-each 0.8 --log captures/rcp-seq-one-primer-b2-b5.txt
|
|
```
|
|
|
|
Interpretation:
|
|
|
|
- If only `B2` responds, the panel likely allows one selected response per
|
|
cold-boot/primer state.
|
|
- If `B2`, `B3`, `B4`, and `B5` all respond, one primer can unlock multiple
|
|
sequential queries.
|
|
- If some respond and some do not, there may be command-group or latch behavior.
|
|
|
|
### Test S2: Primer Before Every Query, No Power Cycle
|
|
|
|
Purpose: test whether a new primer can re-arm another selected query without
|
|
power-cycling.
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0x00 0xB2 0x00 0xB3 0x00 0xB4 0x00 0xB5" --states 0x00 --values 0x80 --settle 3 --after-each 0.8 --log captures/rcp-seq-reprimer-b2-b5.txt
|
|
```
|
|
|
|
Interpretation:
|
|
|
|
- If every selected command responds, a primer is required before each query but
|
|
power-cycling is not.
|
|
- If only the first selected command responds, power-cycle or another reset-like
|
|
command may be required to clear the latch.
|
|
|
|
### Test S3: Repeat Same Query With and Without Reprimer
|
|
|
|
Purpose: test whether the same selected query can be repeated in one powered
|
|
session.
|
|
|
|
Without re-primer:
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0x00 0xB5 0xB5 0xB5" --states 0x00 --values 0x80 --settle 3 --after-each 0.8 --log captures/rcp-seq-repeat-b5-no-reprimer.txt
|
|
```
|
|
|
|
Power-cycle, then with re-primer:
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0x00 0xB5 0x00 0xB5 0x00 0xB5" --states 0x00 --values 0x80 --settle 3 --after-each 0.8 --log captures/rcp-seq-repeat-b5-reprimer.txt
|
|
```
|
|
|
|
Interpretation:
|
|
|
|
- If only the first `B5` responds in both tests, the response is one-shot until
|
|
power cycle or a yet-unknown reset/ack command.
|
|
- If the re-primer version responds repeatedly, the primer re-arms the selected
|
|
query.
|
|
|
|
### 2026-05-13 Sequential Query Test Result
|
|
|
|
Captures:
|
|
|
|
- `captures/rcp-seq-one-primer-b2-b5.txt`
|
|
- `captures/rcp-seq-reprimer-b2-b5.txt`
|
|
- `captures/rcp-seq-repeat-b5-no-reprimer.txt`
|
|
- `captures/rcp-seq-repeat-b5-reprimer.txt`
|
|
|
|
Valid result:
|
|
|
|
| Test | Intended sequence | Actual sequence sent | Result |
|
|
| --- | --- | --- | --- |
|
|
| S1 | `00 -> B2 -> B3 -> B4 -> B5` | `00 -> B2 -> B3 -> B4 -> B5` | only `B2` responded: `07 80 36 10 0C F7` |
|
|
|
|
Tooling caveat:
|
|
|
|
- The original `serial_direct_response_sweep.py` de-duplicated command lists.
|
|
- Because of that, sequences containing repeated commands did not run as
|
|
intended.
|
|
- `S2`, `S3 no re-primer`, and `S3 re-primer` need to be rerun after the
|
|
script fix.
|
|
- The script has been updated to preserve repeated command values in explicit
|
|
command lists.
|
|
|
|
Interpretation from S1:
|
|
|
|
- One primer did not unlock a whole list of feature/status queries.
|
|
- After `00 -> B2` returned `07 80 36 10 0C F7`, later `B3`, `B4`, and `B5`
|
|
in the same powered session did not produce additional non-heartbeat frames.
|
|
- This supports a one-response latch model unless the re-primer test proves that
|
|
the primer can re-arm another query.
|
|
|
|
Rerun these tests after the script fix:
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0x00 0xB2 0x00 0xB3 0x00 0xB4 0x00 0xB5" --states 0x00 --values 0x80 --settle 3 --after-each 0.8 --log captures/rcp-seq-reprimer-b2-b5-v2.txt
|
|
```
|
|
|
|
Power-cycle, then:
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0x00 0xB5 0xB5 0xB5" --states 0x00 --values 0x80 --settle 3 --after-each 0.8 --log captures/rcp-seq-repeat-b5-no-reprimer-v2.txt
|
|
```
|
|
|
|
Power-cycle, then:
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0x00 0xB5 0x00 0xB5 0x00 0xB5" --states 0x00 --values 0x80 --settle 3 --after-each 0.8 --log captures/rcp-seq-repeat-b5-reprimer-v2.txt
|
|
```
|
|
|
|
### 2026-05-13 Sequential Query Rerun Result
|
|
|
|
Captures:
|
|
|
|
- `captures/rcp-seq-reprimer-b2-b5-v2.txt`
|
|
- `captures/rcp-seq-repeat-b5-no-reprimer-v2.txt`
|
|
- `captures/rcp-seq-repeat-b5-reprimer-v2.txt`
|
|
|
|
These reruns used the fixed `serial_direct_response_sweep.py`, which preserves
|
|
repeated command values in explicit sequences.
|
|
|
|
Results:
|
|
|
|
| Test | Sequence | Non-heartbeat response(s) |
|
|
| --- | --- | --- |
|
|
| Re-primer between different queries | `00 -> B2 -> 00 -> B3 -> 00 -> B4 -> 00 -> B5` | only `B2`: `07 80 36 10 0C F7` |
|
|
| Repeat `B5`, no re-primer | `00 -> B5 -> B5 -> B5` | only first `B5`: `07 80 6D 20 D8 48` |
|
|
| Repeat `B5`, re-primer each time | `00 -> B5 -> 00 -> B5 -> 00 -> B5` | only first `B5`: `07 80 6D 20 D8 48` |
|
|
|
|
Interpretation:
|
|
|
|
- The RCP appears to allow only one selected query response per powered session
|
|
in the current `CONNECT NOT ACT` state.
|
|
- Sending another primer (`00 00 00 00 80 DA`) after the first response does not
|
|
re-arm the query responder.
|
|
- Repeating the same selected query does not produce another response.
|
|
- This strongly suggests a one-shot discovery/status response followed by a
|
|
required next-stage command, acknowledgement, reset, or activation step.
|
|
|
|
Implication for CCU behavior:
|
|
|
|
- The CCU may not scan a list of feature queries in the current state. It may
|
|
send one discovery/status query, receive one response, then decide what
|
|
activation/session command to send next.
|
|
- Alternatively, additional feature reads may require an acknowledgement or
|
|
state-advance command that has not yet been identified.
|
|
|
|
Recommended next direction:
|
|
|
|
- Stop broad feature scanning for the moment.
|
|
- Search for the post-discovery acknowledgement/activation command that follows
|
|
one known response such as `00 -> B5 => 07 80 6D 20 D8 48`.
|
|
- Use a three-step pattern:
|
|
|
|
```text
|
|
primer -> selected query -> candidate activation/ack command
|
|
```
|
|
|
|
Known reproducible setup:
|
|
|
|
```text
|
|
Host -> RCP: 00 00 00 00 80 DA
|
|
Host -> RCP: 00 00 B5 00 80 6F
|
|
RCP -> Host: 07 80 6D 20 D8 48
|
|
Host -> RCP: candidate next-stage command
|
|
```
|
|
|
|
## Post-Discovery Candidate Sweep
|
|
|
|
Use `scripts/serial_post_discovery_sweep.py` to search for the command that
|
|
comes after one known discovery/status response. This is the likely next stage
|
|
after the one-shot response behavior.
|
|
|
|
Default setup:
|
|
|
|
```text
|
|
primer: 00 00 00 00 80 DA
|
|
query: 00 00 B5 00 80 6F
|
|
RCP: 07 80 6D 20 D8 48
|
|
then: candidate next-stage command
|
|
```
|
|
|
|
Recommended first post-discovery sweep:
|
|
|
|
```powershell
|
|
python scripts/serial_post_discovery_sweep.py --port COM5 --candidates "0x00-0x1F" --prompt-power-cycle --prompt-screen --log captures/rcp-post-discovery-b5-candidates-00-1f.txt
|
|
```
|
|
|
|
For each candidate:
|
|
|
|
1. Power-cycle the RCP.
|
|
2. Wait for heartbeat/panel stable.
|
|
3. Press Enter at the prompt.
|
|
4. Watch for any screen change after the candidate frame.
|
|
5. Type the screen state if it changes, or press Enter for no visible change.
|
|
|
|
Why this range first:
|
|
|
|
- Earlier frame-length tests showed small command values can change screen state
|
|
to `CONNECT NOT ACT`.
|
|
- If a simple ACK/activation command exists, it may be in the low command range.
|
|
|
|
Next ranges if `00-1F` does not change state:
|
|
|
|
```powershell
|
|
python scripts/serial_post_discovery_sweep.py --port COM5 --candidates "0x20-0x3F" --prompt-power-cycle --prompt-screen --log captures/rcp-post-discovery-b5-candidates-20-3f.txt
|
|
python scripts/serial_post_discovery_sweep.py --port COM5 --candidates "0x80-0x9F" --prompt-power-cycle --prompt-screen --log captures/rcp-post-discovery-b5-candidates-80-9f.txt
|
|
python scripts/serial_post_discovery_sweep.py --port COM5 --candidates "0xB0-0xBF" --prompt-power-cycle --prompt-screen --log captures/rcp-post-discovery-b5-candidates-b0-bf.txt
|
|
```
|
|
|
|
If any candidate changes the screen away from `CONNECT NOT ACT`, or produces a
|
|
new RCP response after the candidate stage, retest that candidate alone with
|
|
three fresh power cycles.
|
|
|
|
### 2026-05-13 Post-Discovery Sweep `00-1F` Result
|
|
|
|
Capture:
|
|
|
|
- `captures/rcp-post-discovery-b5-candidates-00-1f.txt`
|
|
|
|
Sweep setup:
|
|
|
|
```text
|
|
primer: 00 00 00 00 80 DA
|
|
query: 00 00 B5 00 80 6F
|
|
expected: 07 80 6D 20 D8 48
|
|
candidate: 00-1F
|
|
```
|
|
|
|
Screen result:
|
|
|
|
- Every candidate remained at `CONNECT NOT ACT` / `CONNECTION NOT ACT`.
|
|
- No candidate in `0x00-0x1F` moved the panel into an active state.
|
|
|
|
Serial result:
|
|
|
|
- Most candidates produced only heartbeat-compatible traffic after the candidate
|
|
frame.
|
|
- Candidate windows for `0x00`, `0x0E`, `0x0F`, `0x1A`, `0x1E`, and `0x1F`
|
|
included additional bytes matching the known discovery response
|
|
`07 80 6D 20 D8 48`.
|
|
- Those candidate-window anomalies are likely trailing/repeated discovery
|
|
response frames from the `B5` query, not new candidate-specific responses.
|
|
|
|
Notable outlier:
|
|
|
|
- During candidate `0x03`, the primer read window contained
|
|
`07 80 40 40 30 ED`, followed by heartbeat.
|
|
- This is checksum-valid, but it occurred before the `B5` query in that test
|
|
window. Treat it as an outlier until reproduced. Possible explanations include
|
|
incomplete power-cycle reset, a previous state/latch edge, or an accidental
|
|
timing artifact.
|
|
|
|
Interpretation:
|
|
|
|
- Low command range `0x00-0x1F` does not appear to contain the simple
|
|
post-discovery activation command when tested after the `B5` discovery query.
|
|
- The script's candidate read window can still catch residual discovery
|
|
response frames; candidate anomalies must be checked against the known query
|
|
response before treating them as new behavior.
|
|
|
|
Recommended next sweep:
|
|
|
|
Use a slightly longer query read window so the known discovery response has more
|
|
time to finish before the candidate frame:
|
|
|
|
```powershell
|
|
python scripts/serial_post_discovery_sweep.py --port COM5 --candidates "0x20-0x3F" --after-query 2.0 --prompt-power-cycle --prompt-screen --log captures/rcp-post-discovery-b5-candidates-20-3f.txt
|
|
```
|
|
|
|
If `20-3F` also keeps the screen at `CONNECT NOT ACT`, continue:
|
|
|
|
```powershell
|
|
python scripts/serial_post_discovery_sweep.py --port COM5 --candidates "0x80-0x9F" --after-query 2.0 --prompt-power-cycle --prompt-screen --log captures/rcp-post-discovery-b5-candidates-80-9f.txt
|
|
python scripts/serial_post_discovery_sweep.py --port COM5 --candidates "0xB0-0xBF" --after-query 2.0 --prompt-power-cycle --prompt-screen --log captures/rcp-post-discovery-b5-candidates-b0-bf.txt
|
|
```
|
|
|
|
## Post-Discovery Test Ladder
|
|
|
|
Before manually sweeping every command byte, sample representative patterns from
|
|
several command regions. The goal is to identify which command families are
|
|
worth expanding.
|
|
|
|
Use the same known discovery setup for each sample:
|
|
|
|
```text
|
|
primer: 00 00 00 00 80 DA
|
|
query: 00 00 B5 00 80 6F
|
|
RCP: 07 80 6D 20 D8 48
|
|
then: sampled candidate command
|
|
```
|
|
|
|
Power-cycle before each candidate prompt. Type any screen change, otherwise
|
|
press Enter.
|
|
|
|
### Ladder 1: Low-Range Sanity Sample
|
|
|
|
The full `00-1F` sweep did not activate the panel, but one outlier appeared
|
|
during the `0x03` test. Retest only representative low bytes plus the outlier:
|
|
|
|
```powershell
|
|
python scripts/serial_post_discovery_sweep.py --port COM5 --candidates "0x00 0x01 0x03 0x07 0x0F 0x10 0x1B 0x1F" --after-query 2.0 --prompt-power-cycle --prompt-screen --log captures/rcp-post-ladder-low-sample.txt
|
|
```
|
|
|
|
What this checks:
|
|
|
|
- `0x00`, `0x01`: no-op / ACK-like small commands.
|
|
- `0x03`: the outlier run produced `07 80 40 40 30 ED`.
|
|
- `0x07`, `0x0F`, `0x1F`: bit-mask/boundary values.
|
|
- `0x10`, `0x1B`: response command-family values observed in RCP frames.
|
|
|
|
### Ladder 2: Response-Command Echo Sample
|
|
|
|
Test host commands that match command bytes seen in RCP responses. If the CCU
|
|
acknowledges or advances using related command IDs, these are good candidates.
|
|
|
|
Observed RCP response command bytes so far:
|
|
|
|
```text
|
|
1B 36 40 6C 6D
|
|
```
|
|
|
|
Run:
|
|
|
|
```powershell
|
|
python scripts/serial_post_discovery_sweep.py --port COM5 --candidates "0x1B 0x36 0x40 0x6C 0x6D" --after-query 2.0 --prompt-power-cycle --prompt-screen --log captures/rcp-post-ladder-response-cmds.txt
|
|
```
|
|
|
|
Expand only if one of these changes screen state or produces a new
|
|
candidate-stage response.
|
|
|
|
### Ladder 3: Boundary and Bit-Pattern Sample
|
|
|
|
This tests command bytes that often mark command classes, flags, or boundaries:
|
|
|
|
```powershell
|
|
python scripts/serial_post_discovery_sweep.py --port COM5 --candidates "0x20 0x2F 0x30 0x3F 0x40 0x4F 0x50 0x5F 0x7F 0x80 0x8F 0x90 0x9F 0xA0 0xAF 0xB0 0xBF 0xC0 0xCF 0xE0 0xEF 0xF0 0xFF" --after-query 2.0 --prompt-power-cycle --prompt-screen --log captures/rcp-post-ladder-boundaries.txt
|
|
```
|
|
|
|
What this checks:
|
|
|
|
- Nibble/region boundaries.
|
|
- The high-bit transition at `0x80`.
|
|
- Known discovery query region around `0xB0`.
|
|
- High command space around `0xE0-0xFF`.
|
|
|
|
### Ladder 4: Known Query Region Sample
|
|
|
|
The `B0` range is known to produce discovery/status responses when used as the
|
|
selected query. It may also contain a next-stage command.
|
|
|
|
```powershell
|
|
python scripts/serial_post_discovery_sweep.py --port COM5 --candidates "0xB0 0xB1 0xB2 0xB3 0xB4 0xB5 0xB6 0xB7 0xB8 0xBF" --after-query 2.0 --prompt-power-cycle --prompt-screen --log captures/rcp-post-ladder-b-region.txt
|
|
```
|
|
|
|
If any `B` candidate changes behavior, expand locally around it rather than
|
|
sweeping the full byte space.
|
|
|
|
### Ladder 5: Alternate Discovery Response Bases
|
|
|
|
If all candidate ladders after `00 -> B5` leave the screen at `CONNECT NOT ACT`,
|
|
try the same sampled candidates after a different discovery query. Different RCP
|
|
responses may expect different follow-up ACKs.
|
|
|
|
Use `B2` discovery:
|
|
|
|
```powershell
|
|
python scripts/serial_post_discovery_sweep.py --port COM5 --query-command 0xB2 --candidates "0x00 0x01 0x1B 0x36 0x40 0x6C 0x6D 0x80 0xB0 0xB5 0xFF" --after-query 2.0 --prompt-power-cycle --prompt-screen --log captures/rcp-post-ladder-after-b2.txt
|
|
```
|
|
|
|
Use `B0` discovery:
|
|
|
|
```powershell
|
|
python scripts/serial_post_discovery_sweep.py --port COM5 --query-command 0xB0 --candidates "0x00 0x01 0x1B 0x36 0x40 0x6C 0x6D 0x80 0xB0 0xB5 0xFF" --after-query 2.0 --prompt-power-cycle --prompt-screen --log captures/rcp-post-ladder-after-b0.txt
|
|
```
|
|
|
|
Interpretation:
|
|
|
|
- If a candidate only works after one discovery response, the next-stage command
|
|
may depend on the returned block.
|
|
- If the same candidate works after multiple discovery responses, it is a
|
|
stronger activation/ACK candidate.
|
|
|
|
### When to Expand
|
|
|
|
Expand a region only when one of these occurs:
|
|
|
|
- Screen changes away from `CONNECT NOT ACT`.
|
|
- RCP sends a new candidate-stage frame that is not the known discovery response
|
|
trailing into the candidate window.
|
|
- The panel begins sending different heartbeat/status frames after the
|
|
candidate.
|
|
|
|
If none of the ladder samples produce a new behavior, stop command-byte guessing
|
|
and test other frame fields for the candidate stage: state byte, value byte, or
|
|
prefix bytes.
|
|
|
|
### 2026-05-13 Ladder 1 Result and Keepalive Hypothesis
|
|
|
|
Capture:
|
|
|
|
- `captures/rcp-post-ladder-low-sample.txt`
|
|
|
|
Ladder 1 candidates:
|
|
|
|
```text
|
|
00 01 03 07 0F 10 1B 1F
|
|
```
|
|
|
|
Result:
|
|
|
|
- Every sampled candidate left the screen at `CONNECT NOT ACT`.
|
|
- Candidate-stage RX was heartbeat-compatible for all candidates.
|
|
- The earlier `0x03` outlier did not reproduce.
|
|
- Query-stage response `07 80 6D 20 D8 48` reproduced reliably before each
|
|
candidate.
|
|
|
|
Interpretation:
|
|
|
|
- The low/outlier sample did not find a post-discovery activation/ACK command.
|
|
- `CONNECT NOT ACT` may be unrelated to a one-shot ACK. It may mean the RCP sees
|
|
host traffic but is not receiving the correct ongoing CCU heartbeat/session
|
|
cadence.
|
|
|
|
Alternative working model:
|
|
|
|
```text
|
|
Host sends discovery/status query
|
|
RCP answers once
|
|
Host must then send a sustained keepalive/session heartbeat
|
|
RCP remains CONNECT NOT ACT until that heartbeat/cadence is correct
|
|
```
|
|
|
|
### Keepalive After Discovery Tests
|
|
|
|
Use `scripts/serial_keepalive_after_query.py` to test whether a sustained host
|
|
heartbeat changes the RCP state after a known discovery response.
|
|
|
|
Default setup:
|
|
|
|
```text
|
|
primer: 00 00 00 00 80 DA
|
|
query: 00 00 B5 00 80 6F
|
|
RCP reply: 07 80 6D 20 D8 48
|
|
keepalive: repeated candidate frame
|
|
```
|
|
|
|
Test K1: repeat the known primer/heartbeat shape:
|
|
|
|
```powershell
|
|
python scripts/serial_keepalive_after_query.py --port COM5 --keepalive-command 0x00 --duration 15 --interval 0.6 --prompt-screen --log captures/rcp-keepalive-after-b5-cmd00-600ms.txt
|
|
```
|
|
|
|
Test K2: repeat the zero-state frame:
|
|
|
|
```powershell
|
|
python scripts/serial_keepalive_after_query.py --port COM5 --keepalive-frame "00 00 00 00 00 5A" --duration 15 --interval 0.6 --prompt-screen --log captures/rcp-keepalive-after-b5-zero-state-600ms.txt
|
|
```
|
|
|
|
Test K3: repeat the alternate state frame:
|
|
|
|
```powershell
|
|
python scripts/serial_keepalive_after_query.py --port COM5 --keepalive-frame "00 00 00 80 00 DA" --duration 15 --interval 0.6 --prompt-screen --log captures/rcp-keepalive-after-b5-state80-600ms.txt
|
|
```
|
|
|
|
Test K4: faster primer/heartbeat cadence:
|
|
|
|
```powershell
|
|
python scripts/serial_keepalive_after_query.py --port COM5 --keepalive-command 0x00 --duration 15 --interval 0.2 --prompt-screen --log captures/rcp-keepalive-after-b5-cmd00-200ms.txt
|
|
```
|
|
|
|
Power-cycle before each keepalive test. Watch for:
|
|
|
|
- Screen changing away from `CONNECT NOT ACT`.
|
|
- Pin 4 changing from heartbeat to another recurring status frame.
|
|
- RCP controls beginning to transmit additional button/status data.
|
|
|
|
### 2026-05-13 Keepalive After Discovery Result
|
|
|
|
Captures:
|
|
|
|
- `captures/rcp-keepalive-after-b5-cmd00-600ms.txt`
|
|
- `captures/rcp-keepalive-after-b5-zero-state-600ms.txt`
|
|
- `captures/rcp-keepalive-after-b5-state80-600ms.txt`
|
|
- `captures/rcp-keepalive-after-b5-cmd00-200ms.txt`
|
|
|
|
Result:
|
|
|
|
| Test | Keepalive frame | Cadence | Screen result | Pin 4 RX |
|
|
| --- | --- | --- | --- | --- |
|
|
| K1 | `00 00 00 00 80 DA` | 0.6 s | `CONNECT NOT ACT` | heartbeat-compatible |
|
|
| K2 | `00 00 00 00 00 5A` | 0.6 s | `CONNECT NOT ACT` | heartbeat-compatible |
|
|
| K3 | `00 00 00 80 00 DA` | 0.6 s | `CONNECT NOT ACT` | heartbeat-compatible |
|
|
| K4 | `00 00 00 00 80 DA` | 0.2 s | `CONNECT NOT ACT` | heartbeat-compatible |
|
|
|
|
Interpretation:
|
|
|
|
- A simple sustained host heartbeat after `00 -> B5` does not activate the RCP.
|
|
- The RCP continues emitting only the known heartbeat-compatible stream on pin
|
|
4 during these keepalive attempts.
|
|
- The correct next stage is probably not just "repeat the primer" or "hold a
|
|
no-op frame at CCU cadence".
|
|
- The better next branch is to map additional `primer -> request` commands that
|
|
cause one-shot RCP responses. Those response blocks may reveal the command
|
|
families, status bits, or identity data needed for the later activation step.
|
|
|
|
Recommended next request sweep:
|
|
|
|
```powershell
|
|
python scripts/serial_primer_candidate_sweep.py --port COM5 --candidates "0xB1 0xB6 0xB7 0xB8 0xB9 0xBA 0xBB 0xBC 0xBD 0xBE 0xBF" --prompt-power-cycle --log captures/rcp-primer-sweep-b1-bf.txt
|
|
```
|
|
|
|
Power-cycle before each candidate prompt. This fills the gaps around the known
|
|
`B0-B5` discovery/status region and checks whether `B8-BF` contain additional
|
|
one-shot readable blocks.
|
|
|
|
If this range is quiet, continue with neighboring command regions:
|
|
|
|
```powershell
|
|
python scripts/serial_primer_candidate_sweep.py --port COM5 --candidates "0xA0-0xAF" --prompt-power-cycle --log captures/rcp-primer-sweep-a0-af.txt
|
|
python scripts/serial_primer_candidate_sweep.py --port COM5 --candidates "0xC0-0xCF" --prompt-power-cycle --log captures/rcp-primer-sweep-c0-cf.txt
|
|
```
|
|
|
|
### 2026-05-13 Primer Sweep A/B/C Region Result
|
|
|
|
Captures:
|
|
|
|
- `captures/rcp-primer-sweep-a0-af.txt`
|
|
- `captures/rcp-primer-sweep-b1-bf.tx`
|
|
- `captures/rcp-primer-sweep-c0-cf.txt`
|
|
|
|
These sweeps used a fresh power cycle before each candidate, with the standard
|
|
primer shape before the selected request:
|
|
|
|
```text
|
|
primer: 00 00 00 00 80 DA
|
|
candidate: 00 00 CMD 00 80 CHECKSUM
|
|
```
|
|
|
|
New selected-command response map:
|
|
|
|
| Selected command | Observed RCP response |
|
|
| ---: | --- |
|
|
| `A0` | `07 80 68 40 30 C5` |
|
|
| `A1` | `07 80 68 20 D8 4D` |
|
|
| `A2` | `07 80 34 10 0C F5` |
|
|
| `A3` | `07 80 34 10 2C D5` |
|
|
| `A4` | `07 80 69 40 30 C4` |
|
|
| `A5` | `07 80 69 20 D8 4C` |
|
|
| `A6` | `07 80 1A 08 C6 09` |
|
|
| `A7` | `07 80 1A 08 D6 19` |
|
|
| `A8` | `07 80 6A 40 30 C7` |
|
|
| `A9` | `07 80 6A 20 D8 4F` |
|
|
| `AA` | `07 80 35 10 0C F4` |
|
|
| `AB` | `07 80 35 10 2C D4` |
|
|
| `AC` | `07 80 6B 40 30 C6` |
|
|
| `AD` | `07 80 6B 20 D8 4E` |
|
|
| `AE` | `07 80 0D 04 A3 77` |
|
|
| `AF` | `07 80 0D 04 AB 7F` |
|
|
| `B1` | `07 80 6C 20 D8 49` |
|
|
| `B6` | `07 80 1B 08 C6 08` |
|
|
| `B7` | `07 80 1B 08 F6 38` |
|
|
| `B8` | `07 80 EE 40 30 43` |
|
|
| `B9` | `07 80 6E 20 D8 4B` |
|
|
| `BA` | `07 80 37 10 0C F6` |
|
|
| `BB` | `07 80 37 10 2C D6` |
|
|
| `BC` | `07 80 EF 40 30 42` |
|
|
| `BD` | `07 80 6F 20 D8 4A` |
|
|
| `BE` | heartbeat only |
|
|
| `BF` | heartbeat only |
|
|
| `C0` | heartbeat only |
|
|
| `C1` | `07 80 70 20 D8 55` |
|
|
| `C2` | `07 80 38 10 0C F9` |
|
|
| `C3` | `07 80 38 10 2C D9` |
|
|
| `C4` | `07 80 71 40 30 DC` |
|
|
| `C5` | `07 80 71 20 D8 54` |
|
|
| `C6` | `07 80 1C 08 C6 0F` |
|
|
| `C7` | `07 80 1C 08 D6 1F` |
|
|
| `C8` | `07 80 72 40 30 DF` |
|
|
| `C9` | `07 80 72 20 D8 57` |
|
|
| `CA` | `07 80 39 10 0C F8` |
|
|
| `CB` | `07 80 39 10 2C D8` |
|
|
| `CC` | `07 80 F3 40 30 5E` |
|
|
| `CD` | `07 80 73 20 D8 56` |
|
|
| `CE` | `07 80 0E 04 A3 74` |
|
|
| `CF` | `07 80 0E 04 AB 7C` |
|
|
|
|
Interpretation:
|
|
|
|
- The RCP has a much larger one-shot readable status/query surface than first
|
|
assumed.
|
|
- The `A0-CF` region looks highly structured. Most commands return stable
|
|
six-byte responses with the same `07 80` prefix and valid XOR checksum.
|
|
- Pairs often share a response command byte and differ in state/value fields:
|
|
`A0/A1`, `A2/A3`, `A4/A5`, `A6/A7`, and similar patterns continue through
|
|
the `B` and `C` regions.
|
|
- `BE`, `BF`, and `C0` are current no-response candidates in this mapping.
|
|
- This strongly supports a discovery/status table model: the CCU may read a
|
|
specific set of one-shot blocks, then choose a later activation/session
|
|
command based on the returned table values.
|
|
|
|
### 2026-05-13 Paused Direct Sweep Result
|
|
|
|
Capture:
|
|
|
|
- `captures/rcp-direct-remaining-after-b5-pause.txt`
|
|
|
|
The paused direct sweep logged anomalies and then allowed a manual power cycle
|
|
before continuing. Because the script continues with the next command after the
|
|
pause, this run is useful for finding response-producing commands, but it is
|
|
not a clean `00 -> B5 -> candidate` post-discovery sweep.
|
|
|
|
Response hits observed in this run:
|
|
|
|
| Command at anomaly | Observed RCP response | Caution |
|
|
| ---: | --- | --- |
|
|
| `B5` | `07 80 6D 20 D8 48` | expected known query response |
|
|
| `40` | `07 80 50 40 30 FD` | repeated twice in this run |
|
|
| `6D` | `07 80 5B 20 D8 7E` | may depend on prior `6C` |
|
|
| `4F` | `07 80 0A 04 AB 78` | needs clean one-per-boot confirmation |
|
|
| `8F` | `07 80 0C 04 AB 7E` | may depend on prior sequence |
|
|
| `A0` | `07 80 E8 40 30 45` | differs from primer-sweep `A0` response |
|
|
| `B0` | `07 80 6C 40 30 C1` | known response |
|
|
| `CF` | `07 80 0E 04 AB 7C` | matches primer-sweep `CF` response |
|
|
| `EF` | `07 80 0F 04 EB 3D` | needs clean one-per-boot confirmation |
|
|
| `B1` | `07 80 6C 20 D8 49` | known response |
|
|
| `B3` | `07 80 36 10 2C D7` | known response |
|
|
| `B6` | `07 80 1B 08 C6 08` | known response |
|
|
| `B8` | `07 80 6E 40 30 C3` | differs from primer-sweep `B8` response |
|
|
| `BA` | `07 80 37 10 0C F6` | matches primer-sweep `BA` response |
|
|
| `BC` | `07 80 6F 40 30 C2` | differs from primer-sweep `BC` response |
|
|
|
|
Next confirmations:
|
|
|
|
- Retest `40`, `4F`, `8F`, `EF`, and the differing `A0/B8/BC` cases as clean
|
|
one-per-boot primer pairs.
|
|
- If a response differs between a plain/direct command and a primer-pair query,
|
|
treat the first host frame as a mode/context selector rather than only a
|
|
generic wake-up primer.
|
|
|
|
## Context Selector Confirmation Tests
|
|
|
|
Goal: confirm whether the first host frame is only a generic primer, or whether
|
|
it selects a response page/context for the next command.
|
|
|
|
The test method is to hold the second/query command constant and change only
|
|
the first frame:
|
|
|
|
```text
|
|
selector/primer -> selected query
|
|
```
|
|
|
|
Strong confirmation:
|
|
|
|
- Same selected query, different first frame, different RCP response.
|
|
- Example pattern: `00 -> B8` returns one block while `B7 -> B8` returns a
|
|
different block.
|
|
|
|
Weak or negative result:
|
|
|
|
- Same selected query always returns the same block regardless of the first
|
|
frame.
|
|
- The differing blocks from the paused direct sweep were caused by longer
|
|
sequence/timing effects rather than a two-frame selector.
|
|
|
|
### Test CS1: Known Generic `00` Page
|
|
|
|
This rechecks the current generic-primer page for the commands that had
|
|
different-looking responses in the paused direct sweep.
|
|
|
|
```powershell
|
|
python scripts/serial_primer_candidate_sweep.py --port COM5 --primer-command 0x00 --candidates "0xA0 0xB8 0xBC" --prompt-power-cycle --log captures/rcp-context-selector-00-a0-b8-bc.txt
|
|
```
|
|
|
|
Expected from prior primer sweeps:
|
|
|
|
| Pair | Expected response |
|
|
| --- | --- |
|
|
| `00 -> A0` | `07 80 68 40 30 C5` |
|
|
| `00 -> B8` | `07 80 EE 40 30 43` |
|
|
| `00 -> BC` | `07 80 EF 40 30 42` |
|
|
|
|
### Test CS2: Suspected Alternate Selectors
|
|
|
|
These test the pairings implied by the paused direct sweep. Power-cycle before
|
|
each prompt.
|
|
|
|
```powershell
|
|
python scripts/serial_primer_candidate_sweep.py --port COM5 --primer-command 0x9F --candidates 0xA0 --prompt-power-cycle --log captures/rcp-context-selector-9f-a0.txt
|
|
python scripts/serial_primer_candidate_sweep.py --port COM5 --primer-command 0xB7 --candidates 0xB8 --prompt-power-cycle --log captures/rcp-context-selector-b7-b8.txt
|
|
python scripts/serial_primer_candidate_sweep.py --port COM5 --primer-command 0xBB --candidates 0xBC --prompt-power-cycle --log captures/rcp-context-selector-bb-bc.txt
|
|
python scripts/serial_primer_candidate_sweep.py --port COM5 --primer-command 0xAF --candidates 0xB0 --prompt-power-cycle --log captures/rcp-context-selector-af-b0.txt
|
|
```
|
|
|
|
Compare against these paused/direct observations:
|
|
|
|
| Pair under test | Context hypothesis if reproduced |
|
|
| --- | --- |
|
|
| `9F -> A0` | `A0` may return `07 80 E8 40 30 45` after selector `9F`. |
|
|
| `B7 -> B8` | `B8` may return `07 80 6E 40 30 C3` after selector `B7`. |
|
|
| `BB -> BC` | `BC` may return `07 80 6F 40 30 C2` after selector `BB`. |
|
|
| `AF -> B0` | `B0` may return `07 80 6C 60 30 E1` after selector `AF`. |
|
|
|
|
### Test CS3: Check for Three-Frame Context
|
|
|
|
The paused sweep's `A0` response happened after `90` and `9F` had both been
|
|
sent in the same powered session. If `9F -> A0` does not reproduce the alternate
|
|
`A0` block, try the full three-frame setup:
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0x90 0x9F 0xA0" --states 0x00 --values 0x80 --settle 3 --after-each 0.8 --after 3 --log captures/rcp-context-seq-90-9f-a0.txt
|
|
```
|
|
|
|
Power-cycle once before this test and do not power-cycle until the script
|
|
exits.
|
|
|
|
Interpretation:
|
|
|
|
- If `9F -> A0` reproduces `07 80 E8 40 30 45`, a two-frame selector is likely.
|
|
- If only `90 -> 9F -> A0` reproduces it, the context/page setup may require
|
|
multiple host frames.
|
|
- If neither reproduces it, treat the paused direct `A0` response as a
|
|
sequence/timing artifact until another capture confirms it.
|
|
|
|
### Optional Single-Frame Controls
|
|
|
|
These check whether the candidate can respond as the first frame after boot.
|
|
|
|
```powershell
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands 0xA0 --states 0x00 --values 0x80 --settle 3 --after-each 1.5 --after 2 --log captures/rcp-context-single-a0.txt
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands 0xB8 --states 0x00 --values 0x80 --settle 3 --after-each 1.5 --after 2 --log captures/rcp-context-single-b8.txt
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands 0xBC --states 0x00 --values 0x80 --settle 3 --after-each 1.5 --after 2 --log captures/rcp-context-single-bc.txt
|
|
```
|
|
|
|
Power-cycle before each single-frame control.
|
|
|
|
### 2026-05-13 Context Selector Dataset Results
|
|
|
|
New captures:
|
|
|
|
- `captures/rcp-context-selector-00-a0-b8-bc.txt`
|
|
- `captures/rcp-context-selector-9f-a0.txt`
|
|
- `captures/rcp-context-selector-b7-b8.txt`
|
|
- `captures/rcp-context-selector-bb-bc.txt`
|
|
- `captures/rcp-context-selector-af-b0.txt`
|
|
- `captures/rcp-context-seq-90-9f-a0.txt`
|
|
- `captures/rcp-context-single-a0.txt`
|
|
- `captures/rcp-context-single-b8.txt`
|
|
- `captures/rcp-context-single-bc.txt`
|
|
|
|
Observed results:
|
|
|
|
| Test | Sequence | Observed response |
|
|
| --- | --- | --- |
|
|
| CS1 | `00 -> A0` | `07 80 E8 40 30 45` |
|
|
| CS1 | `00 -> B8` | `07 80 6E 40 30 C3` |
|
|
| CS1 | `00 -> BC` | `07 80 6F 40 30 C2` |
|
|
| CS2 | `9F -> A0` | heartbeat only |
|
|
| CS2 | `B7 -> B8` | `07 80 6E 40 30 C3` |
|
|
| CS2 | `BB -> BC` | `07 80 6F 40 30 C2` |
|
|
| CS2 | `AF -> B0` | `07 80 6C 40 30 C1` |
|
|
| CS3 | `90 -> 9F -> A0` | `07 80 68 40 30 C5` |
|
|
| Single-frame control | `A0` | heartbeat only |
|
|
| Single-frame control | `B8` | heartbeat only |
|
|
| Single-frame control | `BC` | heartbeat only |
|
|
|
|
Important comparison against earlier sweeps:
|
|
|
|
| Selected query | Earlier primer sweep response | New `00 -> query` response |
|
|
| ---: | --- | --- |
|
|
| `A0` | `07 80 68 40 30 C5` | `07 80 E8 40 30 45` |
|
|
| `B8` | `07 80 EE 40 30 43` | `07 80 6E 40 30 C3` |
|
|
| `BC` | `07 80 EF 40 30 42` | `07 80 6F 40 30 C2` |
|
|
|
|
Interpretation:
|
|
|
|
- Single `A0`, `B8`, and `BC` frames after boot produced heartbeat only, so
|
|
these responses require prior host traffic.
|
|
- The response is not determined only by the selected query command. The same
|
|
selected query can produce different response blocks in different setup
|
|
contexts.
|
|
- `B7 -> B8` and `BB -> BC` reproduced the alternate `B8`/`BC` responses seen
|
|
in the paused direct sweep.
|
|
- `90 -> 9F -> A0` reproduced the earlier `A0` response
|
|
`07 80 68 40 30 C5`, while `9F -> A0` alone produced no response.
|
|
- `00 -> A0` now produced the alternate `A0` response
|
|
`07 80 E8 40 30 45`, so the `00` first frame is not always a simple
|
|
deterministic "generic primer" in the current bench state.
|
|
- The evidence now favors a stateful/page-sensitive discovery model rather than
|
|
a single fixed primer model.
|
|
|
|
Working model after these datasets:
|
|
|
|
```text
|
|
Host sends one or more setup/selector frames.
|
|
RCP arms one readable response.
|
|
The next selected query returns a block from the currently selected page/state.
|
|
After that response, the RCP latches until power cycle or an unknown reset/state
|
|
advance command.
|
|
```
|
|
|
|
Recommended next confirmation:
|
|
|
|
1. Repeat `00 -> A0`, `00 -> B8`, and `00 -> BC` once more after clean power
|
|
cycles to see whether the alternate page is now stable.
|
|
2. Repeat `90 -> 9F -> A0` once more to confirm the earlier page can be selected
|
|
reliably.
|
|
3. Test whether `90 -> A0` alone selects the earlier page, or whether `9F` is
|
|
also required.
|
|
4. Test whether `00 -> 9F -> A0` behaves like `90 -> 9F -> A0`, which would
|
|
suggest `9F` is the real selector and `90` is only a setup/arming frame.
|
|
|
|
Suggested commands:
|
|
|
|
```powershell
|
|
python scripts/serial_primer_candidate_sweep.py --port COM5 --primer-command 0x00 --candidates "0xA0 0xB8 0xBC" --prompt-power-cycle --log captures/rcp-context-repeat-00-a0-b8-bc.txt
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0x90 0x9F 0xA0" --states 0x00 --values 0x80 --settle 3 --after-each 0.8 --after 3 --log captures/rcp-context-repeat-90-9f-a0.txt
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0x90 0xA0" --states 0x00 --values 0x80 --settle 3 --after-each 0.8 --after 3 --log captures/rcp-context-seq-90-a0.txt
|
|
python scripts/serial_direct_response_sweep.py --port COM5 --commands "0x00 0x9F 0xA0" --states 0x00 --values 0x80 --settle 3 --after-each 0.8 --after 3 --log captures/rcp-context-seq-00-9f-a0.txt
|
|
```
|
|
|
|
### 2026-05-13 Context Confirmation Result
|
|
|
|
New captures:
|
|
|
|
- `captures/rcp-context-repeat-00-a0-b8-bc.txt`
|
|
- `captures/rcp-context-repeat-90-9f-a0.txt`
|
|
- `captures/rcp-context-seq-90-a0.txt`
|
|
- `captures/rcp-context-seq-00-9f-a0.txt`
|
|
|
|
Observed results:
|
|
|
|
| Test | Sequence | Observed response |
|
|
| --- | --- | --- |
|
|
| Repeat `00` page | `00 -> A0` | `07 80 68 40 30 C5` |
|
|
| Repeat `00` page | `00 -> B8` | `07 80 6E 40 30 C3` |
|
|
| Repeat `00` page | `00 -> BC` | `07 80 6F 40 30 C2` |
|
|
| Repeat three-frame A0 | `90 -> 9F -> A0` | `07 80 68 40 30 C5` |
|
|
| A0 with `90` only | `90 -> A0` | `07 80 68 40 30 C5` |
|
|
| A0 with `00` then `9F` | `00 -> 9F -> A0` | `07 80 68 40 30 C5` |
|
|
|
|
Updated interpretation:
|
|
|
|
- `90 -> A0` is enough to produce the `A0` response
|
|
`07 80 68 40 30 C5`; `9F` is not required for that page.
|
|
- `00 -> 9F -> A0` also produces `07 80 68 40 30 C5`, so a frame before `9F`
|
|
can arm the response, but `9F` does not appear to select the alternate `A0`
|
|
response by itself.
|
|
- The repeat `00 -> A0` result returned to `07 80 68 40 30 C5`, while the
|
|
previous `00 -> A0` context dataset returned `07 80 E8 40 30 45`. Treat the
|
|
`E8` response as real but not yet deterministic from the current two-frame
|
|
model.
|
|
- `00 -> B8` and `00 -> BC` remained stable as `07 80 6E 40 30 C3` and
|
|
`07 80 6F 40 30 C2`, matching the earlier alternate-page observations.
|
|
|
|
Current best model:
|
|
|
|
```text
|
|
The RCP requires at least one setup frame before many query commands respond.
|
|
Some setup/query pairs are stable, for example 90 -> A0 and 00 -> B8.
|
|
Some response differences are still not explained by only the immediately
|
|
preceding frame, so a hidden boot/session/state bit or timing-sensitive page
|
|
selection may also be involved.
|
|
```
|
|
|
|
Next useful tests:
|
|
|
|
1. Retest `00 -> A0` several times in a row with a power cycle before each run
|
|
to measure whether `68` or `E8` is the dominant response.
|
|
2. Try direct pairs for the observed alternate `B8/BC` family:
|
|
`B8 -> B9`, `BC -> BD`, and `BD -> BE`.
|
|
3. Sweep the `D0-DF` region with the same primer-pair method to see whether the
|
|
structured discovery table continues after `CF`.
|
|
|
|
## Unlatch / State-Advance Sweep
|
|
|
|
Goal: intentionally put the RCP into the known one-response latched state, send
|
|
a wide set of possible reset/ack/state-advance commands, then verify whether a
|
|
known query can respond again without a power cycle.
|
|
|
|
Use `scripts/serial_unlatch_sweep.py`. For each candidate it performs:
|
|
|
|
```text
|
|
latch primer -> latch query -> candidate unlatch command -> verify primer -> verify query
|
|
```
|
|
|
|
Default latch and verify sequence:
|
|
|
|
```text
|
|
00 -> B5 produces known response: 07 80 6D 20 D8 48
|
|
candidate possible unlatch / state advance command
|
|
00 -> B5 verify whether the known response can happen again
|
|
```
|
|
|
|
Interpretation:
|
|
|
|
- If the verify query returns heartbeat only, the candidate did not unlatch the
|
|
one-response state.
|
|
- If the verify query returns `07 80 6D 20 D8 48` again, the candidate likely
|
|
cleared or advanced the latch.
|
|
- If the candidate itself changes the LCD or produces a new serial response,
|
|
log it as a possible state-advance command even if the verify query does not
|
|
respond.
|
|
|
|
First wide assortment, focused on known response command families, boundaries,
|
|
and current no-response gaps:
|
|
|
|
```powershell
|
|
python scripts/serial_unlatch_sweep.py --port COM5 --candidates "0x00 0x01 0x03 0x07 0x0A 0x0C 0x0D 0x0E 0x0F 0x10 0x1A 0x1B 0x1C 0x20 0x30 0x36 0x38 0x39 0x40 0x4F 0x50 0x5B 0x68 0x6C 0x6D 0x6E 0x6F 0x70 0x7F 0x80 0x8F 0x90 0x9F 0xA0 0xAF 0xB0 0xB5 0xB8 0xBC 0xBE 0xBF 0xC0 0xCF 0xD0 0xDF 0xE0 0xEF 0xF0 0xFF" --expected-verify-response "07 80 6D 20 D8 48" --prompt-power-cycle --prompt-screen --log captures/rcp-unlatch-wide-after-b5.txt
|
|
```
|
|
|
|
Power-cycle before each prompt. For the screen prompt:
|
|
|
|
- Press Enter if the screen stayed the same.
|
|
- Type the exact screen text if it changes.
|
|
- Type `q` to stop.
|
|
|
|
If this finds no verify responses, try the same idea after a different latch
|
|
query page:
|
|
|
|
```powershell
|
|
python scripts/serial_unlatch_sweep.py --port COM5 --latch-query-command 0xA0 --verify-query-command 0xA0 --candidates "0x00 0x01 0x0F 0x10 0x1A 0x1B 0x40 0x4F 0x68 0x6C 0x80 0x8F 0x90 0x9F 0xA0 0xB0 0xB8 0xBC 0xC0 0xCF 0xE0 0xEF 0xFF" --expected-verify-response "07 80 68 40 30 C5" --prompt-power-cycle --prompt-screen --log captures/rcp-unlatch-wide-after-a0.txt
|
|
```
|
|
|
|
For a fast dry run without touching the serial port:
|
|
|
|
```powershell
|
|
python scripts/serial_unlatch_sweep.py --port COM5 --candidates "0x00 0x01 0x90" --dry-run
|
|
```
|
|
|
|
### 2026-05-13 Unlatch Sweep Result
|
|
|
|
Captures:
|
|
|
|
- `captures/rcp-unlatch-wide-after-b5.txt`
|
|
- `captures/rcp-unlatch-wide-after-a0.txt`
|
|
|
|
User observation:
|
|
|
|
- No visible RCP state change was seen during the tests.
|
|
- The only screen note recorded in the logs was `CONNECT NOT ACT` after
|
|
candidate `0x00`, which matches the already-known non-active connected state.
|
|
|
|
Serial result:
|
|
|
|
| Latch/verify query | Candidates tested | Expected verify response | Result |
|
|
| --- | ---: | --- | --- |
|
|
| `B5` | 49 | `07 80 6D 20 D8 48` | no confirmed unlatch |
|
|
| `A0` | 23 | `07 80 68 40 30 C5` | no confirmed unlatch |
|
|
|
|
Notes:
|
|
|
|
- Candidate `0xBF` in the `B5` unlatch sweep produced a verify-query anomaly,
|
|
but the raw bytes were `00 00 00 00 00 00 80 DA`, not the expected
|
|
`07 80 6D 20 D8 48`. Treat this as a heartbeat/chunking/classifier artifact,
|
|
not a successful unlatch.
|
|
- No candidate-stage serial response clearly indicated a state advance.
|
|
- The broad command-byte assortment did not find a reset/ack/unlatch command in
|
|
the tested six-byte frame shape.
|
|
|
|
Tooling update:
|
|
|
|
- `scripts/serial_unlatch_sweep.py` now accepts `--expected-verify-response`.
|
|
- Future unlatch sweeps should use this option so only the desired repeated
|
|
query response counts as a hit.
|
|
|
|
## PT2/PT7 Compatibility Clue
|
|
|
|
Manual-derived note from a newer Sony RCP:
|
|
|
|
- A newer Sony RCP has a mode switch with `PT2` and `PT7` positions.
|
|
- `PT2` is documented for controlling the same camera line that the RCP-TX7 is
|
|
associated with.
|
|
|
|
Working implication:
|
|
|
|
- The TX7 may be a fixed/PT2-era protocol personality rather than a generic
|
|
Sony RCP protocol endpoint.
|
|
- If the CCU/RCP protocol family later split into PT2 and PT7 modes, then our
|
|
current frame shape may be electrically correct but still missing a
|
|
personality/mode/session assumption.
|
|
- The command bytes that look like "page selectors" may be table reads within
|
|
the PT2 personality rather than an activation handshake.
|
|
|
|
Next direction from this clue:
|
|
|
|
1. Treat PT2 compatibility as the default target for TX7 restoration tests.
|
|
2. Search newer-RCP manuals for whether PT2/PT7 is only a physical switch or
|
|
whether either mode has visible initialization, connect, or model-detect
|
|
behavior.
|
|
3. Prefer tests that emulate a CCU already speaking the TX7/PT2 personality,
|
|
rather than trying PT7-style/high-range activation guesses.
|
|
|
|
## Button Behavior While Latched
|
|
|
|
Open questions:
|
|
|
|
1. Does the one-response latched state suppress the RCP-origin button frames
|
|
that are known to appear while disconnected?
|
|
2. If the RCP sends `CAM POWER`, does an immediate host-side response using the
|
|
same or a similar command shape change the RCP state?
|
|
|
|
Known RCP-origin button frames:
|
|
|
|
| Button/action | RCP frame |
|
|
| --- | --- |
|
|
| Idle heartbeat | `00 00 00 00 80 DA` |
|
|
| `CAM POWER` | `00 00 07 80 00 DD` |
|
|
| `CALL` on/state high | `00 00 15 80 00 CF` |
|
|
| `CALL` off/state low | `00 00 15 00 00 4F` |
|
|
|
|
Use `scripts/serial_button_response_test.py` for these tests. It keeps RX and
|
|
TX in the same serial session, so it works around Windows COM-port exclusivity.
|
|
|
|
### Test BTN1: Offline Button Control
|
|
|
|
Purpose: establish a fresh control capture where the RCP is not intentionally
|
|
latched. During the listen window, press `CAM POWER` a few times and press/release
|
|
`CALL`.
|
|
|
|
```powershell
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 30 --prompt --log captures/rcp-buttons-offline-control.txt
|
|
```
|
|
|
|
Expected:
|
|
|
|
- `CAM POWER` should produce `00 00 07 80 00 DD`.
|
|
- `CALL` should produce one or both `00 00 15 80 00 CF` and
|
|
`00 00 15 00 00 4F`.
|
|
|
|
### Test BTN2: Latched Button Emission
|
|
|
|
Purpose: put the RCP into the known `00 -> B5` latched state, then see whether
|
|
`CAM POWER` and `CALL` still produce RCP-origin frames. During the listen
|
|
window, press the same buttons as BTN1.
|
|
|
|
```powershell
|
|
python scripts/serial_button_response_test.py --port COM5 --latch --latch-query-command 0xB5 --duration 30 --prompt --log captures/rcp-buttons-latched-after-b5.txt
|
|
```
|
|
|
|
Interpretation:
|
|
|
|
- If `CAM POWER`/`CALL` frames still appear, the latch suppresses selected query
|
|
responses but does not suppress basic panel-origin button events.
|
|
- If button frames disappear, the latch may be closer to a protocol/session
|
|
hold state that blocks some panel event transmission.
|
|
|
|
### Test BTN3: Respond to `CAM POWER` With Exact Echo
|
|
|
|
Purpose: when the RCP sends the `CAM POWER` frame, immediately send the same
|
|
six-byte frame back on the host-to-RCP line. Watch the screen for any visible
|
|
change.
|
|
|
|
```powershell
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 30 --prompt --respond-to-cam-power --respond-once --response-frame "00 00 07 80 00 DD" --log captures/rcp-buttons-cam-power-exact-echo.txt
|
|
```
|
|
|
|
At the prompt, press `CAM POWER` once. If the screen changes, note the exact
|
|
display text after the run.
|
|
|
|
### Test BTN4: Respond to `CAM POWER` With Host-Shaped Variant
|
|
|
|
Purpose: test a related command-shaped host frame where command `0x07` is kept
|
|
but the `0x80` bit is in the value field, matching the host-query shape used in
|
|
many discovery tests.
|
|
|
|
```powershell
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 30 --prompt --respond-to-cam-power --respond-once --response-frame "00 00 07 00 80 DD" --log captures/rcp-buttons-cam-power-host-shaped.txt
|
|
```
|
|
|
|
Interpretation:
|
|
|
|
- If exact echo changes nothing but the host-shaped variant changes the screen
|
|
or serial stream, the RCP may expect host responses in the same command class
|
|
but with host-side state/value layout.
|
|
- If neither changes anything, `CAM POWER` may be an outbound event requiring a
|
|
larger CCU state/session response rather than a direct ACK.
|
|
|
|
Optional latched version of BTN3:
|
|
|
|
```powershell
|
|
python scripts/serial_button_response_test.py --port COM5 --latch --latch-query-command 0xB5 --duration 30 --prompt --respond-to-cam-power --respond-once --response-frame "00 00 07 80 00 DD" --log captures/rcp-buttons-latched-cam-power-exact-echo.txt
|
|
```
|
|
|
|
### 2026-05-13 Button Test Result
|
|
|
|
Captures:
|
|
|
|
- `captures/rcp-buttons-offline-control.txt`
|
|
- `captures/rcp-buttons-latched-after-b5.txt`
|
|
- `captures/rcp-buttons-cam-power-exact-echo.txt`
|
|
- `captures/rcp-buttons-cam-power-host-shaped.txt`
|
|
|
|
Offline control:
|
|
|
|
- `CALL` produced `00 00 15 80 00 CF` and `00 00 15 00 00 4F`.
|
|
- `CAM POWER` produced `00 00 07 80 00 DD`.
|
|
- This matches the original offline button observations.
|
|
|
|
Latched after `00 -> B5`:
|
|
|
|
- The latch setup produced the known `B5` response
|
|
`07 80 6D 20 D8 48`.
|
|
- While in this state, `CALL` still produced both known call frames.
|
|
- While in this state, `CAM POWER` still produced `00 00 07 80 00 DD`.
|
|
|
|
Interpretation:
|
|
|
|
- The one-response latch suppresses additional selected-query responses, but it
|
|
does not suppress basic RCP-origin button/event frames.
|
|
- The panel is still actively reporting front-panel events after the discovery
|
|
response/latch state.
|
|
|
|
`CAM POWER` response tests:
|
|
|
|
| Test | Host response sent after `CAM POWER` | Screen result | Serial result |
|
|
| --- | --- | --- | --- |
|
|
| BTN3 exact echo | `00 00 07 80 00 DD` | `CONNECT NOT ACT` | heartbeat/button-event only |
|
|
| BTN4 host-shaped | `00 00 07 00 80 DD` | `CONNECT NOT ACT` | heartbeat only after response |
|
|
|
|
Interpretation:
|
|
|
|
- Both `CAM POWER` response shapes are recognized enough to produce the familiar
|
|
`CONNECT NOT ACT` display state.
|
|
- Neither response advanced the RCP into an active state or caused a new serial
|
|
status stream.
|
|
- `CAM POWER` is likely an outbound event that requires broader CCU/session
|
|
context, not a simple one-frame ACK.
|
|
|
|
Next useful button-side tests:
|
|
|
|
1. Repeat BTN3/BTN4 while already latched after `00 -> B5`; this checks whether
|
|
the same `CAM POWER` response has different meaning after the RCP has already
|
|
returned a discovery block.
|
|
2. Try responding to `CALL` with exact echo and host-shaped command `0x15`
|
|
variants, since earlier `0x15` matrix tests changed the screen but did not
|
|
activate the panel.
|
|
3. If a future session/keepalive candidate is found, rerun BTN1/BTN2 to see
|
|
whether more front-panel controls begin emitting serial events in an active
|
|
context.
|
|
|
|
### CALL Echo / Response Tests
|
|
|
|
Goal: test whether the RCP treats `CALL` differently from `CAM POWER` when the
|
|
host immediately echoes or acknowledges the outbound button event.
|
|
|
|
Known RCP-origin `CALL` frames:
|
|
|
|
```text
|
|
CALL high/on: 00 00 15 80 00 CF
|
|
CALL low/off: 00 00 15 00 00 4F
|
|
```
|
|
|
|
Test BTN5: exact echo of both known `CALL` shapes.
|
|
|
|
```powershell
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 30 --prompt --respond-to-call --respond-once --response-frame "00 00 15 80 00 CF" --response-frame "00 00 15 00 00 4F" --log captures/rcp-buttons-call-exact-echo.txt
|
|
```
|
|
|
|
Test BTN6: host-shaped `CALL` response, with command `0x15` and value `0x80`.
|
|
|
|
```powershell
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 30 --prompt --respond-to-call --respond-once --response-frame "00 00 15 00 80 CF" --log captures/rcp-buttons-call-host-shaped.txt
|
|
```
|
|
|
|
Test BTN7: host-shaped `CALL` response after the known `00 -> B5` latch.
|
|
|
|
```powershell
|
|
python scripts/serial_button_response_test.py --port COM5 --latch --latch-query-command 0xB5 --duration 30 --prompt --respond-to-call --respond-once --response-frame "00 00 15 00 80 CF" --log captures/rcp-buttons-latched-call-host-shaped.txt
|
|
```
|
|
|
|
During each test, press and release `CALL` once or twice. Record any screen
|
|
change after the run.
|
|
|
|
### 2026-05-13 CALL Echo Result
|
|
|
|
Captures:
|
|
|
|
- `captures/rcp-buttons-call-exact-echo.txt`
|
|
- `captures/rcp-buttons-call-host-shaped.txt`
|
|
- `captures/rcp-buttons-latched-call-host-shaped.txt`
|
|
|
|
User observation:
|
|
|
|
- All three CALL response tests ended with the RCP screen at `CONNECT NOT ACT`.
|
|
|
|
Serial result:
|
|
|
|
| Test | Host response after `CALL` | Serial result |
|
|
| --- | --- | --- |
|
|
| BTN5 exact echo | `00 00 15 80 00 CF` then `00 00 15 00 00 4F` | RCP sent `07 80 45 20 D0 68` once, then returned to heartbeat/CALL events |
|
|
| BTN6 host-shaped | `00 00 15 00 80 CF` | heartbeat/CALL events only |
|
|
| BTN7 latched host-shaped | `00 00 15 00 80 CF` after latch setup | heartbeat/CALL events only |
|
|
|
|
Interpretation:
|
|
|
|
- Exact CALL echo is more interesting than CAM POWER echo: it produced a new
|
|
checksum-valid RCP response frame, `07 80 45 20 D0 68`.
|
|
- The new frame did not visibly activate the RCP; the panel still ended at
|
|
`CONNECT NOT ACT`.
|
|
- The host-shaped `CALL` response did not reproduce the new frame, either
|
|
offline or after the `B5` latch setup.
|
|
- This suggests the RCP has at least one event-response path for CALL exact
|
|
echo, but that response is still not the missing active-session handshake.
|
|
|
|
Next CALL-focused checks:
|
|
|
|
1. Retest exact CALL echo three times with clean power cycles to see whether
|
|
`07 80 45 20 D0 68` is repeatable.
|
|
2. Test echoing only `CALL high/on` and only `CALL low/off` separately to see
|
|
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.
|
|
|
|
### 2026-05-13 CALL Exact-Echo Repro Result
|
|
|
|
Captures:
|
|
|
|
- `captures/rcp-buttons-call-exact-echo-repro-1.txt`
|
|
- `captures/rcp-buttons-call-exact-echo-repro-2.txt`
|
|
- `captures/rcp-buttons-call-exact-echo-repro-3.txt`
|
|
|
|
All three runs detected `CALL` high/on and sent the same exact echo pair:
|
|
|
|
```text
|
|
00 00 15 80 00 CF
|
|
00 00 15 00 00 4F
|
|
```
|
|
|
|
Observed serial result:
|
|
|
|
| Run | Result |
|
|
| --- | --- |
|
|
| repro 1 | random assortment of button presses; no `07 80 45 20 D0 68`; returned to heartbeat/CALL traffic |
|
|
| repro 2 | press-and-hold `CALL`; `07 80 45 20 D0 68` observed once, about 33 ms after the echo pair |
|
|
| repro 3 | quick `CALL` press only; no `07 80 45 20 D0 68`; returned to heartbeat traffic |
|
|
|
|
Interpretation:
|
|
|
|
- The `07 80 45 20 D0 68` frame is reproducible, but appears sensitive to
|
|
physical CALL timing. It has now been seen in the original exact-echo test
|
|
and in the press-and-hold repro run.
|
|
- Because each run sent the same two response frames after `CALL` high, the
|
|
strongest current hypothesis is that CALL must remain asserted briefly after
|
|
the host echo pair.
|
|
- Receive buffer alignment or an internal RCP state bit may still be involved,
|
|
but the quick-press miss and press-and-hold hit make button hold duration the
|
|
next variable to isolate.
|
|
- This frame is still best treated as a CALL/event-response clue, not as an
|
|
activation handshake.
|
|
|
|
Next tighter CALL tests:
|
|
|
|
1. Echo only `CALL high/on`.
|
|
2. Echo only `CALL low/off`.
|
|
3. Repeat the two-frame exact echo while deliberately holding CALL until the
|
|
script has logged either the watch frame or the next heartbeat.
|
|
4. Repeat the two-frame exact echo with shorter and longer response delays.
|
|
|
|
High-only echo:
|
|
|
|
```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" --watch-frame "07 80 45 20 D0 68" --log captures/rcp-buttons-call-high-only-echo.txt
|
|
```
|
|
|
|
Low-only echo:
|
|
|
|
```powershell
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 15 --prompt --respond-to-call --respond-once --response-frame "00 00 15 00 00 4F" --watch-frame "07 80 45 20 D0 68" --log captures/rcp-buttons-call-low-only-echo.txt
|
|
```
|
|
|
|
Two-frame echo with a shorter response delay:
|
|
|
|
```powershell
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 15 --prompt --respond-to-call --respond-once --response-delay 0.0 --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-delay-0ms.txt
|
|
```
|
|
|
|
Two-frame echo with a longer response delay:
|
|
|
|
```powershell
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 15 --prompt --respond-to-call --respond-once --response-delay 0.2 --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-delay-200ms.txt
|
|
```
|
|
|
|
### 2026-05-13 CALL Hold Timing Tests
|
|
|
|
Captures:
|
|
|
|
- `captures/rcp-buttons-call-high-only-echo.txt`
|
|
- `captures/rcp-buttons-call-low-only-echo.txt`
|
|
- `captures/rcp-buttons-call-exact-echo-delay-0ms.txt`
|
|
- `captures/rcp-buttons-call-exact-echo-delay-200ms.txt`
|
|
|
|
User procedure:
|
|
|
|
- All four tests used a roughly 2 second hold on the `CALL` button.
|
|
|
|
Observed result:
|
|
|
|
| Test | Host response | Result |
|
|
| --- | --- | --- |
|
|
| high-only echo | `00 00 15 80 00 CF` after CALL high | no `07 80 45 20 D0 68` |
|
|
| low-only echo | `00 00 15 00 00 4F` after CALL high | no `07 80 45 20 D0 68` |
|
|
| exact echo, 0 ms delay | high echo then low echo immediately | no `07 80 45 20 D0 68` |
|
|
| exact echo, 200 ms delay | high echo then low echo after 200 ms response delay | no `07 80 45 20 D0 68` |
|
|
|
|
Interpretation:
|
|
|
|
- Holding `CALL` alone is not sufficient to reproduce
|
|
`07 80 45 20 D0 68`.
|
|
- Echoing only one of the two CALL states is not sufficient in these tests.
|
|
- The previous successful repro used the two-frame exact echo with the script's
|
|
default 50 ms response delay. The failed 0 ms and 200 ms runs suggest the
|
|
timing window may be narrower than expected, or the frame depends on a
|
|
second uncontrolled variable.
|
|
- Current best hypothesis: `07 80 45 20 D0 68` requires the exact two-frame
|
|
CALL echo pair near the default delay timing, with CALL still asserted.
|
|
|
|
Next timing-bracket test:
|
|
|
|
```powershell
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 15 --prompt --respond-to-call --respond-once --response-delay 0.02 --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-delay-20ms.txt
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 15 --prompt --respond-to-call --respond-once --response-delay 0.05 --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-delay-50ms.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" --log captures/rcp-buttons-call-exact-echo-delay-80ms.txt
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 15 --prompt --respond-to-call --respond-once --response-delay 0.12 --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-delay-120ms.txt
|
|
```
|
|
|
|
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.
|
|
|
|
### 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.
|
|
|
|
### 2026-05-13 CALL 60-100 ms Repeat Result
|
|
|
|
Captures:
|
|
|
|
- `captures/rcp-buttons-call-exact-echo-delay-60ms.txt`
|
|
- `captures/rcp-buttons-call-exact-echo-delay-70ms.txt`
|
|
- `captures/rcp-buttons-call-exact-echo-delay-80ms-v2.txt`
|
|
- `captures/rcp-buttons-call-exact-echo-delay-90ms.txt`
|
|
- `captures/rcp-buttons-call-exact-echo-delay-100ms.txt`
|
|
|
|
Observed result:
|
|
|
|
| Delay | Result |
|
|
| --- | --- |
|
|
| 60 ms | no `0x45` response |
|
|
| 70 ms | no `0x45` response |
|
|
| 80 ms repeat | no `0x45` response |
|
|
| 90 ms | no `0x45` response |
|
|
| 100 ms | no `0x45` response |
|
|
|
|
Interpretation:
|
|
|
|
- The `07 80 45 30 D0 78` response from the earlier 80 ms run did not repeat in
|
|
the 80 ms repeat or nearby 60-100 ms bracket.
|
|
- The trigger is not controlled by the simple delay between CALL high detection
|
|
and the two-frame echo pair alone.
|
|
- A more likely variable is the spacing between the host's CALL-high echo and
|
|
CALL-low echo, or the RCP's internal heartbeat/call-scan phase when the echo
|
|
pair arrives.
|
|
|
|
Next test direction:
|
|
|
|
- Keep the initial response delay fixed near the values that have produced hits
|
|
before, but vary the spacing between the two echoed CALL frames.
|
|
|
|
Tooling note:
|
|
|
|
- `scripts/serial_button_response_test.py` now supports
|
|
`--response-frame-interval`, which inserts a delay between multiple
|
|
`--response-frame` values sent for the same observed button event.
|
|
|
|
Inter-frame timing ladder:
|
|
|
|
```powershell
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 15 --prompt --respond-to-call --respond-once --response-delay 0.05 --response-frame-interval 0.02 --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-frame-gap-20ms.txt
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 15 --prompt --respond-to-call --respond-once --response-delay 0.05 --response-frame-interval 0.05 --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-frame-gap-50ms.txt
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 15 --prompt --respond-to-call --respond-once --response-delay 0.05 --response-frame-interval 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-frame-gap-80ms.txt
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 15 --prompt --respond-to-call --respond-once --response-delay 0.08 --response-frame-interval 0.05 --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-delay-80ms-frame-gap-50ms.txt
|
|
```
|
|
|
|
For each run, power-cycle first and use the same roughly 2 second CALL hold.
|
|
|
|
### 2026-05-13 CALL Inter-Frame Gap Result
|
|
|
|
Captures:
|
|
|
|
- `captures/rcp-buttons-call-frame-gap-20ms.txt`
|
|
- `captures/rcp-buttons-call-frame-gap-50ms.txt`
|
|
- `captures/rcp-buttons-call-frame-gap-80ms.txt`
|
|
- `captures/rcp-buttons-call-delay-80ms-frame-gap-50ms.txt`
|
|
|
|
Observed result:
|
|
|
|
| Initial delay | Gap between host CALL echoes | Result |
|
|
| --- | --- | --- |
|
|
| 50 ms | 20 ms | `07 80 45 20 D0 68` |
|
|
| 50 ms | 50 ms | `07 80 45 20 D0 68` |
|
|
| 50 ms | 80 ms | `07 80 45 20 D0 68` |
|
|
| 80 ms | 50 ms | `07 80 45 20 D0 68` |
|
|
|
|
Interpretation:
|
|
|
|
- `07 80 45 20 D0 68` is now reproducible.
|
|
- The key change was adding a gap between the host's CALL-high echo and
|
|
CALL-low echo. Earlier tests sent the two response frames back-to-back.
|
|
- The exact gap is not especially narrow; 20 ms, 50 ms, and 80 ms all worked in
|
|
this run set.
|
|
- The RCP likely needs to process the high echo as one event before receiving
|
|
the low echo. Sending high and low in one tight burst can land outside that
|
|
event path.
|
|
- The `0x45` response is still not known to activate the panel, but it is a
|
|
real, reproducible event-response path.
|
|
|
|
Next step: answer the reproducible `0x45` response in the same run.
|
|
|
|
Test F1: host-shaped generic `0x45` ACK.
|
|
|
|
```powershell
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 15 --prompt --respond-to-call --respond-once --response-delay 0.05 --response-frame-interval 0.05 --response-frame "00 00 15 80 00 CF" --response-frame "00 00 15 00 00 4F" --watch-frame "07 80 45 20 D0 68" --followup-on-watch-frame --followup-frame "00 00 45 00 80 9F" --log captures/rcp-buttons-call-45-followup-generic-ack.txt
|
|
```
|
|
|
|
Test F2: host-shaped echo of the RCP `0x45` payload.
|
|
|
|
```powershell
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 15 --prompt --respond-to-call --respond-once --response-delay 0.05 --response-frame-interval 0.05 --response-frame "00 00 15 80 00 CF" --response-frame "00 00 15 00 00 4F" --watch-frame "07 80 45 20 D0 68" --followup-on-watch-frame --followup-frame "00 00 45 20 D0 EF" --log captures/rcp-buttons-call-45-followup-payload-echo.txt
|
|
```
|
|
|
|
Test F3: exact echo of the RCP `0x45` response frame.
|
|
|
|
```powershell
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 15 --prompt --respond-to-call --respond-once --response-delay 0.05 --response-frame-interval 0.05 --response-frame "00 00 15 80 00 CF" --response-frame "00 00 15 00 00 4F" --watch-frame "07 80 45 20 D0 68" --followup-on-watch-frame --followup-frame "07 80 45 20 D0 68" --log captures/rcp-buttons-call-45-followup-exact-echo.txt
|
|
```
|
|
|
|
For each follow-up test, note whether the LCD changes, whether more serial data
|
|
appears after the follow-up, and whether the panel returns to heartbeat only.
|
|
|
|
### 2026-05-13 CALL `0x45` Follow-Up Result
|
|
|
|
Captures:
|
|
|
|
- `captures/rcp-buttons-call-45-followup-generic-ack.txt`
|
|
- `captures/rcp-buttons-call-45-followup-payload-echo.txt`
|
|
- `captures/rcp-buttons-call-45-followup-exact-echo.txt`
|
|
|
|
Observed result:
|
|
|
|
| Test | Follow-up sent after `07 80 45 20 D0 68` | Serial result |
|
|
| --- | --- | --- |
|
|
| F1 generic ACK | `00 00 45 00 80 9F` | heartbeat only after follow-up |
|
|
| F2 payload echo | `00 00 45 20 D0 EF` | heartbeat only after follow-up |
|
|
| F3 exact echo | `07 80 45 20 D0 68` | heartbeat only after follow-up |
|
|
|
|
Notes:
|
|
|
|
- F1 and F2 reproduced the normal CALL-high echo path, then sent the follow-up
|
|
frame after the RCP emitted `07 80 45 20 D0 68`.
|
|
- F3 still reproduced `07 80 45 20 D0 68`, but the triggering CALL event was
|
|
captured as a split CALL-off frame rather than a clean CALL-on log line. The
|
|
script's rolling buffer still recognized the frame and sent the configured
|
|
responses.
|
|
- None of the three follow-up shapes caused a visible serial-side state change
|
|
in the captured data. After the follow-up, the RCP returned to heartbeat.
|
|
|
|
Interpretation:
|
|
|
|
- The `0x45` frame is likely an RCP-origin response/notification in the CALL
|
|
event path, but these simple host answers are not the missing activation
|
|
handshake.
|
|
- The panel may not expect a direct answer to `0x45`, or the answer needs more
|
|
session context than a single command frame.
|
|
- Since `0x45` can be produced from the CALL-off side too, the RCP may be
|
|
responding to a CALL state transition sequence rather than specifically to
|
|
CALL high.
|
|
|
|
Next direction:
|
|
|
|
- Use the reproducible CALL echo/gap sequence as a diagnostic, but return to
|
|
the main activation problem: what host/session traffic makes the RCP leave
|
|
`CONNECT NOT ACT`.
|
|
- Test whether a known discovery query still works immediately after the CALL
|
|
`0x45` path, and whether CALL `0x45` changes the one-shot/latch behavior.
|
|
|
|
CALL then discovery query:
|
|
|
|
```powershell
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 15 --prompt --respond-to-call --respond-once --response-delay 0.05 --response-frame-interval 0.05 --response-frame "00 00 15 80 00 CF" --response-frame "00 00 15 00 00 4F" --watch-frame "07 80 45 20 D0 68" --followup-on-watch-frame --followup-frame "00 00 00 00 80 DA" --followup-frame "00 00 B5 00 80 6F" --log captures/rcp-buttons-call-45-followup-discovery-b5.txt
|
|
```
|
|
|
|
If this produces the known `B5` response `07 80 6D 20 D8 48`, then the CALL
|
|
path does not consume the one-shot discovery response. If it returns heartbeat
|
|
only, CALL/`0x45` may put the RCP into a similar one-shot consumed state.
|
|
|
|
### 2026-05-13 CALL `0x45` Then Discovery Result
|
|
|
|
Capture:
|
|
|
|
- `captures/rcp-buttons-call-45-followup-discovery-b5.txt`
|
|
|
|
Observed sequence:
|
|
|
|
```text
|
|
RCP CALL high: 00 00 15 80 00 CF
|
|
Host CALL high echo: 00 00 15 80 00 CF
|
|
Host CALL low echo: 00 00 15 00 00 4F
|
|
RCP CALL response: 07 80 45 20 D0 68
|
|
Host primer: 00 00 00 00 80 DA
|
|
Host B5 query: 00 00 B5 00 80 6F
|
|
```
|
|
|
|
Result:
|
|
|
|
- After the follow-up `00 -> B5` query, the RCP returned heartbeat-compatible
|
|
traffic only.
|
|
- The known `B5` response `07 80 6D 20 D8 48` did not appear.
|
|
|
|
Interpretation:
|
|
|
|
- The CALL/`0x45` path does not unlock the known discovery query.
|
|
- It may consume or bypass the same cold one-shot discovery window, or the RCP
|
|
may simply ignore discovery-style queries once the CALL event path has been
|
|
exercised.
|
|
- This pushes the CALL path into the "useful diagnostic but probably not the
|
|
activation handshake" bucket.
|
|
|
|
### Cold No-Button CALL Injection Tests
|
|
|
|
Question: have we tried sending the CALL response frames without first pressing
|
|
the `CALL` button?
|
|
|
|
Answer: partially, but not in the exact form that now matters.
|
|
|
|
- Earlier command `0x15` matrix tests sent individual `0x15` frames from a cold
|
|
panel and saw `CONNECT NOT ACT`, but no non-heartbeat serial response.
|
|
- The newer reproducible `0x45` result depends on sending the CALL-high and
|
|
CALL-low frames as a pair with a gap. That exact cold/no-button pair has not
|
|
been tested yet.
|
|
|
|
Tooling note:
|
|
|
|
- `scripts/serial_button_response_test.py` now supports `--startup-frame`. These
|
|
frames are sent automatically after the listen window begins, without waiting
|
|
for a physical button event.
|
|
|
|
Test C1: cold CALL pair, 50 ms gap, no physical button press.
|
|
|
|
```powershell
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 12 --prompt --startup-delay 1.0 --startup-frame-interval 0.05 --startup-frame "00 00 15 80 00 CF" --startup-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-cold-call-pair-gap-50ms.txt
|
|
```
|
|
|
|
Test C2: cold CALL pair, 80 ms gap, no physical button press.
|
|
|
|
```powershell
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 12 --prompt --startup-delay 1.0 --startup-frame-interval 0.08 --startup-frame "00 00 15 80 00 CF" --startup-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-cold-call-pair-gap-80ms.txt
|
|
```
|
|
|
|
Test C3: cold CALL high only, no physical button press.
|
|
|
|
```powershell
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 12 --prompt --startup-delay 1.0 --startup-frame "00 00 15 80 00 CF" --watch-frame "07 80 45 20 D0 68" --watch-frame "07 80 45 30 D0 78" --log captures/rcp-buttons-cold-call-high-only.txt
|
|
```
|
|
|
|
Test C4: cold CALL low only, no physical button press.
|
|
|
|
```powershell
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 12 --prompt --startup-delay 1.0 --startup-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-cold-call-low-only.txt
|
|
```
|
|
|
|
For each test, power-cycle first and do not press any panel buttons. If C1/C2
|
|
produce `0x45`, the host can synthesize the CALL event path. If they do not,
|
|
the RCP's own physical CALL transition is required before the echo pair has
|
|
meaning.
|
|
|
|
### 2026-05-13 Cold No-Button CALL Injection Result
|
|
|
|
Captures:
|
|
|
|
- `captures/rcp-buttons-cold-call-pair-gap-50ms.txt`
|
|
- `captures/rcp-buttons-cold-call-pair-gap-80ms.txt`
|
|
- `captures/rcp-buttons-cold-call-high-only.txt`
|
|
- `captures/rcp-buttons-cold-call-low-only.txt`
|
|
|
|
Observed result:
|
|
|
|
| Test | Host startup frame(s) | Result |
|
|
| --- | --- | --- |
|
|
| C1 | `00 00 15 80 00 CF`, 50 ms gap, `00 00 15 00 00 4F` | `07 80 45 20 D0 68` |
|
|
| C2 | `00 00 15 80 00 CF`, 80 ms gap, `00 00 15 00 00 4F` | `07 80 45 20 D0 68` |
|
|
| C3 | `00 00 15 80 00 CF` only | heartbeat only |
|
|
| C4 | `00 00 15 00 00 4F` only | heartbeat only |
|
|
|
|
Interpretation:
|
|
|
|
- The host can synthesize the CALL `0x45` response path without pressing the
|
|
physical `CALL` button.
|
|
- The RCP does not require its own front-panel CALL transition before this path
|
|
has meaning.
|
|
- The required trigger is the ordered CALL-high then CALL-low pair with a small
|
|
inter-frame gap. Either frame alone is insufficient.
|
|
- This makes `00 00 15 80 00 CF -> 00 00 15 00 00 4F` a confirmed host-side
|
|
event stimulus, not merely an echo of physical button traffic.
|
|
- The response still returns to heartbeat afterward; this remains useful for
|
|
protocol probing but is not yet an activation/session handshake.
|
|
|
|
### Next CALL Tests
|
|
|
|
Two useful follow-ups now that the host can synthesize the CALL path:
|
|
|
|
1. Determine whether the synthetic CALL trigger is repeatable within one power
|
|
cycle, or whether the first `0x45` response latches/suppresses later ones.
|
|
2. Probe adjacent `0x45` family responses that might drive the illuminated CALL
|
|
button or another visible state.
|
|
|
|
### CALL Retrigger / Latch Tests
|
|
|
|
Tooling note:
|
|
|
|
- `scripts/serial_button_response_test.py` now supports repeating the startup
|
|
frame group with `--startup-repeat` and `--startup-repeat-interval`.
|
|
|
|
Test R1: two synthetic CALL trigger cycles, 2 second gap.
|
|
|
|
```powershell
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 16 --prompt --startup-delay 1.0 --startup-frame-interval 0.05 --startup-frame "00 00 15 80 00 CF" --startup-frame "00 00 15 00 00 4F" --startup-repeat 2 --startup-repeat-interval 2.0 --watch-frame "07 80 45 20 D0 68" --watch-frame "07 80 45 30 D0 78" --log captures/rcp-buttons-cold-call-repeat-2x-gap-2s.txt
|
|
```
|
|
|
|
Test R2: two synthetic CALL trigger cycles, 5 second gap.
|
|
|
|
```powershell
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 22 --prompt --startup-delay 1.0 --startup-frame-interval 0.05 --startup-frame "00 00 15 80 00 CF" --startup-frame "00 00 15 00 00 4F" --startup-repeat 2 --startup-repeat-interval 5.0 --watch-frame "07 80 45 20 D0 68" --watch-frame "07 80 45 30 D0 78" --log captures/rcp-buttons-cold-call-repeat-2x-gap-5s.txt
|
|
```
|
|
|
|
Test R3: three synthetic CALL trigger cycles, 2 second gap.
|
|
|
|
```powershell
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 24 --prompt --startup-delay 1.0 --startup-frame-interval 0.05 --startup-frame "00 00 15 80 00 CF" --startup-frame "00 00 15 00 00 4F" --startup-repeat 3 --startup-repeat-interval 2.0 --watch-frame "07 80 45 20 D0 68" --watch-frame "07 80 45 30 D0 78" --log captures/rcp-buttons-cold-call-repeat-3x-gap-2s.txt
|
|
```
|
|
|
|
Interpretation:
|
|
|
|
- If `Watch totals` shows one `0x45` hit per trigger cycle, this path is
|
|
repeatable and not a one-shot latch.
|
|
- If only the first cycle produces `0x45`, treat the CALL path as latched until
|
|
power cycle or some unknown reset.
|
|
- If later cycles produce `07 80 45 30 D0 78` instead of `...20...`, the RCP
|
|
may be stepping through a small state machine rather than simply suppressing
|
|
repeats.
|
|
|
|
### Adjacent `0x45` Family Follow-Up Tests
|
|
|
|
Goal: once the synthetic CALL pair has produced `07 80 45 20 D0 68`, send nearby
|
|
frames that might act like CALL lamp/tally control. Watch the CALL button lamp,
|
|
LCD, and serial stream after each follow-up.
|
|
|
|
Useful adjacent candidates:
|
|
|
|
| Candidate type | Follow-up frame | Why it is interesting |
|
|
| --- | --- | --- |
|
|
| host-shaped command below | `00 00 44 20 D0 EE` | adjacent command byte |
|
|
| host-shaped command known | `00 00 45 20 D0 EF` | same command, host-shaped |
|
|
| host-shaped command above | `00 00 46 20 D0 EC` | adjacent command byte |
|
|
| exact-family sibling seen once | `07 80 45 30 D0 78` | observed adjacent state |
|
|
| exact-family state below | `07 80 45 10 D0 58` | nearby state nibble |
|
|
| exact-family command above | `07 80 46 20 D0 6B` | nearby command nibble |
|
|
|
|
Run each candidate in a separate power cycle. The startup CALL pair is used only
|
|
to make the RCP produce the known `0x45` response first.
|
|
|
|
Test A1:
|
|
|
|
```powershell
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 15 --prompt --startup-delay 1.0 --startup-frame-interval 0.05 --startup-frame "00 00 15 80 00 CF" --startup-frame "00 00 15 00 00 4F" --watch-frame "07 80 45 20 D0 68" --followup-on-watch-frame --followup-frame "00 00 44 20 D0 EE" --log captures/rcp-buttons-call-adjacent-44-host.txt
|
|
```
|
|
|
|
Test A2:
|
|
|
|
```powershell
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 15 --prompt --startup-delay 1.0 --startup-frame-interval 0.05 --startup-frame "00 00 15 80 00 CF" --startup-frame "00 00 15 00 00 4F" --watch-frame "07 80 45 20 D0 68" --followup-on-watch-frame --followup-frame "00 00 45 20 D0 EF" --log captures/rcp-buttons-call-adjacent-45-host.txt
|
|
```
|
|
|
|
Test A3:
|
|
|
|
```powershell
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 15 --prompt --startup-delay 1.0 --startup-frame-interval 0.05 --startup-frame "00 00 15 80 00 CF" --startup-frame "00 00 15 00 00 4F" --watch-frame "07 80 45 20 D0 68" --followup-on-watch-frame --followup-frame "00 00 46 20 D0 EC" --log captures/rcp-buttons-call-adjacent-46-host.txt
|
|
```
|
|
|
|
Test A4:
|
|
|
|
```powershell
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 15 --prompt --startup-delay 1.0 --startup-frame-interval 0.05 --startup-frame "00 00 15 80 00 CF" --startup-frame "00 00 15 00 00 4F" --watch-frame "07 80 45 20 D0 68" --followup-on-watch-frame --followup-frame "07 80 45 30 D0 78" --log captures/rcp-buttons-call-adjacent-45-state30.txt
|
|
```
|
|
|
|
Test A5:
|
|
|
|
```powershell
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 15 --prompt --startup-delay 1.0 --startup-frame-interval 0.05 --startup-frame "00 00 15 80 00 CF" --startup-frame "00 00 15 00 00 4F" --watch-frame "07 80 45 20 D0 68" --followup-on-watch-frame --followup-frame "07 80 45 10 D0 58" --log captures/rcp-buttons-call-adjacent-45-state10.txt
|
|
```
|
|
|
|
Test A6:
|
|
|
|
```powershell
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 15 --prompt --startup-delay 1.0 --startup-frame-interval 0.05 --startup-frame "00 00 15 80 00 CF" --startup-frame "00 00 15 00 00 4F" --watch-frame "07 80 45 20 D0 68" --followup-on-watch-frame --followup-frame "07 80 46 20 D0 6B" --log captures/rcp-buttons-call-adjacent-46-exact.txt
|
|
```
|
|
|
|
Record for each run:
|
|
|
|
- whether the CALL button lamp changes
|
|
- whether the LCD changes
|
|
- whether any non-heartbeat serial data appears after the follow-up
|
|
|
|
### 2026-05-13 Initial CALL Retrigger Result
|
|
|
|
Captures:
|
|
|
|
- `captures/rcp-buttons-cold-call-repeat-2x-gap-2s.txt`
|
|
- `captures/rcp-buttons-cold-call-repeat-2x-gap-5s.txt`
|
|
- `captures/rcp-buttons-cold-call-repeat-3x-gap-2s.txt`
|
|
|
|
Observed result:
|
|
|
|
- All configured synthetic CALL trigger cycles were transmitted.
|
|
- Each run recorded only one visible `07 80 45 20 D0 68`.
|
|
- No LCD change was observed beyond the already known `CONNECT NOT ACT`.
|
|
|
|
Important tooling limitation:
|
|
|
|
- In this first version of the repeat test, the helper sent all startup trigger
|
|
groups before entering its main RX loop.
|
|
- That means the captured `0x45` frame count is not a clean per-cycle measure.
|
|
A single buffered `0x45` at the end does not prove whether only one cycle
|
|
triggered or multiple triggers collapsed into one unread serial burst.
|
|
|
|
Interpretation:
|
|
|
|
- These runs suggest the CALL path may be latched or at least not obviously
|
|
retriggering, but they are not strong enough to prove it.
|
|
- A corrected repeat test must read after each trigger group before sending the
|
|
next one.
|
|
|
|
Tooling update:
|
|
|
|
- `scripts/serial_button_response_test.py` now supports
|
|
`--startup-read-after-group`, which reads and logs RX after each startup-frame
|
|
group before the next repeat.
|
|
|
|
Corrected repeat tests:
|
|
|
|
```powershell
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 16 --prompt --startup-delay 1.0 --startup-frame-interval 0.05 --startup-frame "00 00 15 80 00 CF" --startup-frame "00 00 15 00 00 4F" --startup-repeat 2 --startup-repeat-interval 2.0 --startup-read-after-group 0.8 --watch-frame "07 80 45 20 D0 68" --watch-frame "07 80 45 30 D0 78" --log captures/rcp-buttons-cold-call-repeat-2x-gap-2s-v2.txt
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 22 --prompt --startup-delay 1.0 --startup-frame-interval 0.05 --startup-frame "00 00 15 80 00 CF" --startup-frame "00 00 15 00 00 4F" --startup-repeat 2 --startup-repeat-interval 5.0 --startup-read-after-group 0.8 --watch-frame "07 80 45 20 D0 68" --watch-frame "07 80 45 30 D0 78" --log captures/rcp-buttons-cold-call-repeat-2x-gap-5s-v2.txt
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 24 --prompt --startup-delay 1.0 --startup-frame-interval 0.05 --startup-frame "00 00 15 80 00 CF" --startup-frame "00 00 15 00 00 4F" --startup-repeat 3 --startup-repeat-interval 2.0 --startup-read-after-group 0.8 --watch-frame "07 80 45 20 D0 68" --watch-frame "07 80 45 30 D0 78" --log captures/rcp-buttons-cold-call-repeat-3x-gap-2s-v2.txt
|
|
```
|
|
|
|
### 2026-05-13 Corrected CALL Retrigger Result
|
|
|
|
Captures:
|
|
|
|
- `captures/rcp-buttons-cold-call-repeat-2x-gap-2s-v2.txt`
|
|
- `captures/rcp-buttons-cold-call-repeat-2x-gap-5s-v2.txt`
|
|
- `captures/rcp-buttons-cold-call-repeat-3x-gap-2s-v2.txt`
|
|
|
|
User observation:
|
|
|
|
- No LCD changes were observed beyond the already known `CONNECT NOT ACT`.
|
|
|
|
Observed serial result:
|
|
|
|
| Test | Trigger groups sent | `0x45` result |
|
|
| --- | --- | --- |
|
|
| 2x, 2 second gap | 2 | both groups produced `07 80 45 20 D0 68`, four copies each |
|
|
| 2x, 5 second gap | 2 | only first group produced `07 80 45 20 D0 68` |
|
|
| 3x, 2 second gap | 3 | only first group produced `07 80 45 20 D0 68` |
|
|
|
|
Interpretation:
|
|
|
|
- The synthetic CALL path is not a strict one-shot latch, because the 2x/2s run
|
|
clearly retriggered on the second group.
|
|
- It is also not cleanly repeatable on every later trigger, because the 2x/5s
|
|
and 3x/2s runs only produced the `0x45` burst on the first group.
|
|
- Each successful trigger can produce a short burst of repeated identical
|
|
`07 80 45 20 D0 68` frames rather than a single reply.
|
|
- Current best model: the CALL path is re-enterable but phase/state-sensitive.
|
|
Something about timing relative to the RCP's internal scan/heartbeat/session
|
|
state affects whether later trigger groups are accepted.
|
|
|
|
Practical takeaway:
|
|
|
|
- We can use the synthetic CALL pair as a reproducible probe, but not yet as a
|
|
guaranteed repeatable command in every cycle of a run.
|
|
- For future CALL-path experiments, treat one successful `0x45` burst per power
|
|
cycle as the reliable baseline, and repeated triggers as conditional behavior
|
|
worth probing rather than assuming.
|
|
|
|
Next retrigger refinement:
|
|
|
|
```powershell
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 20 --prompt --startup-delay 1.0 --startup-frame-interval 0.05 --startup-frame "00 00 15 80 00 CF" --startup-frame "00 00 15 00 00 4F" --startup-repeat 2 --startup-repeat-interval 2.0 --startup-read-after-group 1.5 --watch-frame "07 80 45 20 D0 68" --watch-frame "07 80 45 30 D0 78" --log captures/rcp-buttons-cold-call-repeat-2x-gap-2s-read1500ms.txt
|
|
python scripts/serial_button_response_test.py --port COM5 --duration 23 --prompt --startup-delay 1.0 --startup-frame-interval 0.05 --startup-frame "00 00 15 80 00 CF" --startup-frame "00 00 15 00 00 4F" --startup-repeat 2 --startup-repeat-interval 3.0 --startup-read-after-group 1.5 --watch-frame "07 80 45 20 D0 68" --watch-frame "07 80 45 30 D0 78" --log captures/rcp-buttons-cold-call-repeat-2x-gap-3s-read1500ms.txt
|
|
```
|
|
|
|
These should help distinguish whether the second-trigger variability is caused
|
|
by too-short post-trigger read windows, or by a genuine acceptance window/state
|
|
inside the RCP.
|
|
|
|
### 2026-05-13 Adjacent `0x45` Follow-Up Result
|
|
|
|
Captures:
|
|
|
|
- `captures/rcp-buttons-call-adjacent-44-host.txt`
|
|
- `captures/rcp-buttons-call-adjacent-45-host.txt`
|
|
- `captures/rcp-buttons-call-adjacent-46-host.txt`
|
|
- `captures/rcp-buttons-call-adjacent-45-state30.txt`
|
|
- `captures/rcp-buttons-call-adjacent-45-state10.txt`
|
|
- `captures/rcp-buttons-call-adjacent-46-exact.txt`
|
|
|
|
User observation:
|
|
|
|
- No LCD changes were observed beyond the already known `CONNECT NOT ACT`.
|
|
- No CALL button lamp change was observed in these runs.
|
|
|
|
Serial result:
|
|
|
|
| Test | Follow-up frame after `07 80 45 20 D0 68` | Result |
|
|
| --- | --- | --- |
|
|
| A1 | `00 00 44 20 D0 EE` | heartbeat only after follow-up |
|
|
| A2 | `00 00 45 20 D0 EF` | heartbeat only after follow-up |
|
|
| A3 | `00 00 46 20 D0 EC` | heartbeat only after follow-up |
|
|
| A4 | `07 80 45 30 D0 78` | heartbeat only after follow-up |
|
|
| A5 | `07 80 45 10 D0 58` | heartbeat only after follow-up |
|
|
| A6 | `07 80 46 20 D0 6B` | heartbeat only after follow-up |
|
|
|
|
Interpretation:
|
|
|
|
- None of the first adjacent `0x45` family probes appear to drive the CALL lamp
|
|
or advance the serial state.
|
|
- The obvious nearby command/state variants are not enough on their own to act
|
|
like a CALL lamp/tally command.
|
|
- The CALL `0x45` family remains useful as a probe point, but the lamp control
|
|
is probably elsewhere in the protocol or needs more session context.
|
|
|
|
### 2026-05-13 Outside-Region Clean Confirmation Result
|
|
|
|
Captures:
|
|
|
|
- `captures/rcp-outside-confirm-00-40-4f-8f-ef.txt`
|
|
- `captures/rcp-outside-repeat-00-40.txt`
|
|
- `captures/rcp-outside-repeat-00-4f.txt`
|
|
- `captures/rcp-outside-repeat-00-8f.txt`
|
|
- `captures/rcp-outside-repeat-00-ef.txt`
|
|
- `captures/rcp-outside-single-40.txt`
|
|
- `captures/rcp-outside-single-4f.txt`
|
|
- `captures/rcp-outside-single-8f.txt`
|
|
- `captures/rcp-outside-single-ef.txt`
|
|
|
|
Goal:
|
|
|
|
- Clean-confirm whether the paused direct-sweep outliers `0x40`, `0x4F`,
|
|
`0x8F`, and `0xEF` are real primer-dependent queries outside the mapped
|
|
`A/B/C` table.
|
|
- Check whether they also work as single first-frame commands after boot.
|
|
|
|
Primer-pair result:
|
|
|
|
```text
|
|
primer: 00 00 00 00 80 DA
|
|
candidate: 00 00 CMD 00 80 CHECKSUM
|
|
```
|
|
|
|
Observed responses:
|
|
|
|
| Pair | Multi-candidate confirm run | Single-candidate repeat | Current read |
|
|
| --- | --- | --- | --- |
|
|
| `00 -> 40` | heartbeat only in the 4-candidate pass | `07 80 50 40 30 FD` repeated | confirmed real, but missed once in the shared sweep |
|
|
| `00 -> 4F` | `07 80 0A 04 AB 78` | `07 80 0A 04 6B B8` repeated | confirmed real, response bytes vary across runs |
|
|
| `00 -> 8F` | `07 80 0C 04 AB 7E` repeated | `07 80 0C 04 AB 7E` once, then heartbeat | confirmed real and stable in content |
|
|
| `00 -> EF` | `07 80 0F 04 AB 7D` repeated | `07 80 0F 04 AB 7D` repeated | confirmed real; differs from earlier paused-sweep `07 80 0F 04 EB 3D` |
|
|
|
|
Single-frame control result:
|
|
|
|
All of these stayed heartbeat-compatible when sent as the first host frame
|
|
after boot, with no anomalies recorded:
|
|
|
|
- `00 00 40 00 80 9A`
|
|
- `00 00 4F 00 80 95`
|
|
- `00 00 8F 00 80 55`
|
|
- `00 00 EF 00 80 35`
|
|
|
|
Interpretation:
|
|
|
|
- `0x40`, `0x4F`, `0x8F`, and `0xEF` are now confirmed as real
|
|
primer-dependent readable/query responses outside the clean `A/B/C` map.
|
|
- None of the four behave like direct first-frame activation/session commands.
|
|
They sit much closer to the broader query/status surface than to an
|
|
unlatching handshake.
|
|
- `0x40` appears slightly context- or timing-sensitive because it missed in the
|
|
shared 4-candidate pass but reproduced cleanly when isolated.
|
|
- `0x4F` and `0xEF` need extra caution: the response family is real, but the
|
|
value bytes are not yet fully nailed down across all captures.
|
|
- `0x4F` has been seen as both `07 80 0A 04 AB 78` and
|
|
`07 80 0A 04 6B B8`.
|
|
- `0xEF` has been seen as both `07 80 0F 04 AB 7D` and the earlier paused
|
|
direct-sweep `07 80 0F 04 EB 3D`.
|
|
- Best current model: these are legitimate outer-table queries whose returned
|
|
payload can still depend on selector context, prior sequence, or exactly when
|
|
in the panel's internal state machine they are sampled.
|
|
|
|
## Host Identity / Capability Exchange Lead Ladder
|
|
|
|
Goal:
|
|
|
|
- Test whether the CCU is expected to identify itself before asking for
|
|
capability/state blocks.
|
|
- Separate "query selector/page" behavior from "host identity/session setup"
|
|
behavior.
|
|
- Check whether a short query burst behaves more like a capability poll than a
|
|
single one-shot request.
|
|
|
|
Tooling:
|
|
|
|
- Use `scripts/serial_sequence_probe.py` for fixed multi-frame sequences where
|
|
the canonical primer stays constant and only later frames vary.
|
|
- Use `scripts/serial_primer_candidate_sweep.py` when only a simple
|
|
`primer -> candidate` pair is needed.
|
|
|
|
### Test HI1: Prefix Variation On A Stable Query
|
|
|
|
Keep the known-good primer fixed and vary only the prefix bytes of the `A0`
|
|
query frame. If the response changes, the host prefix bytes may carry CCU
|
|
identity, addressing, or mode information rather than being ignored padding.
|
|
|
|
Power-cycle before each run.
|
|
|
|
```powershell
|
|
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 A0 00 80 7A" --read-after-frame 1.2 --log captures/rcp-hostid-prefix-0000-a0.txt
|
|
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 80 A0 00 80 FA" --read-after-frame 1.2 --log captures/rcp-hostid-prefix-0080-a0.txt
|
|
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "80 00 A0 00 80 FA" --read-after-frame 1.2 --log captures/rcp-hostid-prefix-8000-a0.txt
|
|
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "07 80 A0 00 80 FD" --read-after-frame 1.2 --log captures/rcp-hostid-prefix-0780-a0.txt
|
|
```
|
|
|
|
What to watch for:
|
|
|
|
- Same `A0` block as baseline: prefix bytes probably are not the missing host
|
|
identity on their own.
|
|
- Different structured block: prefix bytes likely select host identity, page,
|
|
or role.
|
|
- Heartbeat only: that prefix pair may be invalid or reserved.
|
|
|
|
### Test HI2: State/Value Variation On A Stable Query
|
|
|
|
Keep the canonical prefix and command byte, but vary the state/value fields on
|
|
the `A0` query. This checks whether the host is supposed to present status or
|
|
capability bits in fields that we have mostly left at `00 80`.
|
|
|
|
Power-cycle before each run.
|
|
|
|
```powershell
|
|
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 A0 00 80 7A" --read-after-frame 1.2 --log captures/rcp-hostid-a0-0080.txt
|
|
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 A0 20 D0 0A" --read-after-frame 1.2 --log captures/rcp-hostid-a0-20d0.txt
|
|
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 A0 40 30 8A" --read-after-frame 1.2 --log captures/rcp-hostid-a0-4030.txt
|
|
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 A0 60 30 AA" --read-after-frame 1.2 --log captures/rcp-hostid-a0-6030.txt
|
|
```
|
|
|
|
What to watch for:
|
|
|
|
- Same `A0` block every time: host state/value fields may be ignored here.
|
|
- Different block family or different returned value bytes: these fields may be
|
|
host-presented capability/status bits.
|
|
- LCD/LED changes without a different serial block: possible session-state side
|
|
effect rather than a simple table read.
|
|
|
|
### Test HI3: Primer -> Host-Announce -> Query
|
|
|
|
Try likely selector/identity-looking bytes as a middle frame before the stable
|
|
`A0` query. This is the direct "CCU says who it is first" test.
|
|
|
|
Power-cycle before each run.
|
|
|
|
```powershell
|
|
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 90 00 80 4A" --frame "00 00 A0 00 80 7A" --read-after-frame 1.0 --log captures/rcp-hostid-announce-90-then-a0.txt
|
|
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 9F 00 80 45" --frame "00 00 A0 00 80 7A" --read-after-frame 1.0 --log captures/rcp-hostid-announce-9f-then-a0.txt
|
|
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 AF 00 80 75" --frame "00 00 A0 00 80 7A" --read-after-frame 1.0 --log captures/rcp-hostid-announce-af-then-a0.txt
|
|
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 B7 00 80 6D" --frame "00 00 A0 00 80 7A" --read-after-frame 1.0 --log captures/rcp-hostid-announce-b7-then-a0.txt
|
|
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 BB 00 80 61" --frame "00 00 A0 00 80 7A" --read-after-frame 1.0 --log captures/rcp-hostid-announce-bb-then-a0.txt
|
|
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 FF 00 80 25" --frame "00 00 A0 00 80 7A" --read-after-frame 1.0 --log captures/rcp-hostid-announce-ff-then-a0.txt
|
|
```
|
|
|
|
What to watch for:
|
|
|
|
- Middle frame gets heartbeat only, third frame still returns plain `A0` block:
|
|
the announce byte probably is not sufficient.
|
|
- Middle frame changes the later `A0` response: strong evidence for a
|
|
host-identity/selector stage.
|
|
- Middle frame alone produces a new block: it may itself be a readable
|
|
capability/identity query rather than a pure host announce.
|
|
|
|
### Test HI4: Capability-Poll Block
|
|
|
|
Send a short family of related queries as if a CCU is polling multiple
|
|
capability blocks in one startup pass. This checks whether the panel expects a
|
|
cluster of reads instead of one isolated query.
|
|
|
|
Power-cycle before each run.
|
|
|
|
```powershell
|
|
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 A0 00 80 7A" --frame "00 00 A1 00 80 7B" --frame "00 00 A4 00 80 7E" --frame "00 00 A5 00 80 7F" --read-after-frame 0.8 --log captures/rcp-hostid-capblock-a-family.txt
|
|
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 B0 00 80 6A" --frame "00 00 B1 00 80 6B" --frame "00 00 B8 00 80 62" --frame "00 00 BC 00 80 66" --read-after-frame 0.8 --log captures/rcp-hostid-capblock-b-family.txt
|
|
```
|
|
|
|
What to watch for:
|
|
|
|
- Only the first query in the block responds: the one-shot model still dominates.
|
|
- Later queries also respond once the family is polled as a burst: this would be
|
|
a major new lead toward CCU-style startup behavior.
|
|
- A later query changes the LCD or LEDs even if the first one looks ordinary:
|
|
still worth treating as a lead.
|
|
|
|
### Test HI5: Repeated Poll Group
|
|
|
|
Repeat the same short poll group with a gap, to test whether the panel wants
|
|
periodic polling or whether only the first startup block matters.
|
|
|
|
Power-cycle before each run.
|
|
|
|
```powershell
|
|
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 B0 00 80 6A" --frame "00 00 B1 00 80 6B" --repeat 3 --repeat-interval 1.5 --read-after-frame 0.8 --read-after-group 0.8 --log captures/rcp-hostid-repeat-b0-b1.txt
|
|
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 A0 00 80 7A" --repeat 3 --repeat-interval 1.5 --read-after-frame 1.0 --read-after-group 0.8 --log captures/rcp-hostid-repeat-a0.txt
|
|
```
|
|
|
|
What to watch for:
|
|
|
|
- Only group 1 responds: startup window or latch behavior still dominates.
|
|
- Later groups begin to respond too: periodic polling may be part of the
|
|
expected CCU session.
|
|
- A later group changes visible state even with similar serial output: possible
|
|
session-timer or keepalive behavior.
|
|
|
|
Recommended order:
|
|
|
|
1. `HI3` because it most directly tests the "CCU identifies itself first"
|
|
hypothesis.
|
|
2. `HI4` because a capability-poll burst is a plausible Sony startup pattern.
|
|
3. `HI1` and `HI2` if the first two stay flat and we need to isolate which host
|
|
fields matter.
|
|
|
|
### 2026-05-13 Host Identity / Capability Result
|
|
|
|
Captures:
|
|
|
|
- `captures/rcp-hostid-prefix-0000-a0.txt`
|
|
- `captures/rcp-hostid-prefix-0080-a0.txt`
|
|
- `captures/rcp-hostid-prefix-8000-a0.txt`
|
|
- `captures/rcp-hostid-a0-0080.txt`
|
|
- `captures/rcp-hostid-a0-20d0.txt`
|
|
- `captures/rcp-hostid-a0-4030.txt`
|
|
- `captures/rcp-hostid-a0-6030.txt`
|
|
- `captures/rcp-hostid-announce-90-then-a0.txt`
|
|
- `captures/rcp-hostid-announce-9f-then-a0.txt`
|
|
- `captures/rcp-hostid-announce-af-then-a0.txt`
|
|
- `captures/rcp-hostid-announce-b7-then-a0.txt`
|
|
- `captures/rcp-hostid-announce-bb-then-a0.txt`
|
|
- `captures/rcp-hostid-announce-ff-then-a0.txt`
|
|
- `captures/rcp-hostid-capblock-a-family.txt`
|
|
- `captures/rcp-hostid-capblock-b-family.txt`
|
|
- `captures/rcp-hostid-repeat-a0.txt`
|
|
- `captures/rcp-hostid-repeat-b0-b1.txt`
|
|
|
|
Not run / no capture present:
|
|
|
|
- `captures/rcp-hostid-prefix-0780-a0.txt`
|
|
|
|
#### HI1: Prefix Variation On `A0`
|
|
|
|
Observed result:
|
|
|
|
| Query frame after primer | Result |
|
|
| --- | --- |
|
|
| `00 00 A0 00 80 7A` | conflicting captures: one run returned `07 80 E8 40 30 45`, another returned `07 80 68 40 30 C5` |
|
|
| `00 80 A0 00 80 FA` | heartbeat only |
|
|
| `80 00 A0 00 80 FA` | heartbeat only |
|
|
| `07 80 A0 00 80 FD` | not run |
|
|
|
|
Read:
|
|
|
|
- Nonzero host prefix bytes did not help. The tested `00 80` and `80 00`
|
|
prefixes suppressed the `A0` response entirely.
|
|
- The plain `00 00` prefix remains the only confirmed working host prefix for
|
|
`A0`, although the returned block still varies across runs.
|
|
|
|
#### HI2: State/Value Variation On `A0`
|
|
|
|
Observed result:
|
|
|
|
| Query frame after primer | Observed RCP response |
|
|
| --- | --- |
|
|
| `00 00 A0 00 80 7A` | `07 80 68 40 30 C5` repeated |
|
|
| `00 00 A0 20 D0 0A` | `07 80 E8 48 3A 47` repeated |
|
|
| `00 00 A0 40 30 8A` | `07 80 68 58 26 CB` repeated |
|
|
| `00 00 A0 60 30 AA` | `07 80 68 58 26 CB` repeated |
|
|
|
|
Read:
|
|
|
|
- This is the strongest new lead in the set.
|
|
- The `A0` response is not fixed: the host `state/value` fields clearly affect
|
|
the returned block.
|
|
- That strongly supports the idea that these fields are carrying host-presented
|
|
status, selector, or capability information, not just filler.
|
|
|
|
#### HI3: Primer -> Host-Announce -> `A0`
|
|
|
|
Observed result:
|
|
|
|
| Sequence | Middle-frame result | Later `A0` result |
|
|
| --- | --- | --- |
|
|
| `00 -> 90 -> A0` | `07 80 64 40 30 C9` repeated | no clean `A0`; only one more `07 80 64 40 30 C9` then heartbeat |
|
|
| `00 -> 9F -> A0` | heartbeat only after `9F` | heartbeat only after `A0`; a prior anomaly `07 80 40 40 30 ED` appeared immediately after the primer |
|
|
| `00 -> AF -> A0` | `07 80 0D 04 AB 7F` visible with a leading heartbeat fragment | heartbeat only after `A0` |
|
|
| `00 -> B7 -> A0` | `07 80 1B 08 D6 18` repeated | heartbeat only after `A0` |
|
|
| `00 -> BB -> A0` | `07 80 37 10 2C D6` repeated | no clean `A0`; only one more `07 80 37 10 2C D6` then heartbeat |
|
|
| `00 -> FF -> A0` | heartbeat only | heartbeat only |
|
|
|
|
Read:
|
|
|
|
- The "announce" bytes behaved more like readable/query commands than like a
|
|
host identity banner the panel accepts and then builds on.
|
|
- In most runs, the middle frame consumed the one-shot response opportunity and
|
|
the following `A0` did not produce its own block.
|
|
- So far this argues against a simple three-step handshake of
|
|
`primer -> host identity -> query`.
|
|
|
|
#### HI4: Capability-Poll Block
|
|
|
|
Observed result:
|
|
|
|
| Block | Result |
|
|
| --- | --- |
|
|
| `00 -> A0 -> A1 -> A4 -> A5` | only `A0` responded (`07 80 68 40 30 C5`); `A1`, `A4`, and `A5` were heartbeat only |
|
|
| `00 -> B0 -> B1 -> B8 -> BC` | only `B0` responded (`07 80 EC 40 30 41` with a leading heartbeat fragment); `B1`, `B8`, and `BC` were heartbeat only |
|
|
|
|
Read:
|
|
|
|
- A burst of related readable queries did not unlock later responses in the same
|
|
startup pass.
|
|
- The one-shot model still dominates: first successful readable query responds,
|
|
later ones in the burst are suppressed.
|
|
|
|
#### HI5: Repeated Poll Group
|
|
|
|
Observed result:
|
|
|
|
| Repeated group | Result |
|
|
| --- | --- |
|
|
| `00 -> A0`, repeated 3 times | only group 1 produced `07 80 68 40 30 C5`; groups 2 and 3 were heartbeat only |
|
|
| `00 -> B0 -> B1`, repeated 3 times | only group 1 `B0` produced a response; later groups were heartbeat only and `B1` never responded |
|
|
|
|
Read:
|
|
|
|
- Periodic polling without a power cycle did not open a sustained session.
|
|
- The panel still behaves like it offers one early readable response block, then
|
|
falls back to heartbeat-only behavior.
|
|
|
|
Overall interpretation:
|
|
|
|
- The cleanest new evidence is that host `state/value` fields matter a lot for
|
|
at least the `A0` family.
|
|
- The tested nonzero prefixes do not look like a missing CCU identity by
|
|
themselves.
|
|
- Candidate "announce" bytes mostly act like ordinary readable/query selectors,
|
|
not like a reusable host identity stage.
|
|
- Capability-poll bursts and repeated poll groups did not create a multi-query
|
|
session.
|
|
- Best current model: the startup exchange probably does involve host-presented
|
|
status or selector bits, but the currently tested sequences still land in a
|
|
one-shot query regime rather than an active maintained session.
|