Files
Sony-rcp/docs/discovery-notes.md
2026-05-13 19:40:50 +10:00

217 KiB

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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.

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:

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:

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.

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:

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:

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:

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:

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:

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:

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.

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:

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:

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:

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:

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

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

python scripts/serial_primer_candidate_sweep.py --port COM5 --candidates "0xB0-0xB7" --dry-run

Continue the known B range first:

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:

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:

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:

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.

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.

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:

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:

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:

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:

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:

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:
primer -> selected query -> candidate activation/ack command

Known reproducible setup:

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:

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:

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:

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:

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:

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:

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:

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:

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:

1B 36 40 6C 6D

Run:

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:

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.

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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.

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.

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:

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.

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:

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:

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:

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:

latch primer -> latch query -> candidate unlatch command -> verify primer -> verify query

Default latch and verify sequence:

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:

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:

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:

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.

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.

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.

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.

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:

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:

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.

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.

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.

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:

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.

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:

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:

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.

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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.

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.

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.

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:

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:

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.

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.

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.

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.

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.

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.

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.

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:

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:

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:

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:

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:

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:

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:

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:

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:

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.

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.

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.

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.

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.

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.

Negative-Space Test Ladder

Goal:

  • Find out what the panel quietly ignores versus what changes its internal parser/session state.
  • Check whether repetitive "host heartbeat" traffic alone changes anything.
  • Recheck whether a known readable query needs silence afterward, or whether the act of repetition itself suppresses later behavior.
  • See whether a malformed checksum has any special effect beyond the already known CONNECT NOT ACT parser-visible state.

Recommended observation:

  • Power-cycle before each test.
  • Note any LCD change, especially whether it remains blank/idle or reaches the usual CONNECT NOT ACT.
  • Note any visible LED change, even if the serial log looks ordinary.

NS1: Assumed Host Heartbeat Only

Send only the current assumed host heartbeat frame repeatedly for a longer window, with no follow-up query.

python scripts/serial_probe_response.py --port COM5 --tx-frame "00 00 00 00 80 DA" --repeat 80 --interval 0.25 --delay 3 --after 3 --frame-size 0 --log captures/rcp-negative-heartbeat-only.txt

Read goal:

  • If this alone eventually changes visible state, cadence may matter more than command diversity.
  • If it remains heartbeat-only and visually inert, the primer/heartbeat frame is probably necessary but not sufficient.

2026-05-13 NS1 Partial Result

User observation from two power-cycled runs:

  • During the entire NS1 script run, the panel did not enter CONNECT NOT ACT / CONNECTION NOT ACT.
  • About 2 seconds after the repeating heartbeat-only script stopped, the panel entered CONNECT NOT ACT.
  • Manually interrupting the script showed the same pattern: while the stream was active, no CONNECT NOT ACT; about 2 seconds after transmission ceased, the panel entered CONNECT NOT ACT.
  • Once the panel was already in CONNECT NOT ACT, restarting the heartbeat-only script did not immediately clear that state.

Interpretation:

  • Continuous transmission of the assumed host heartbeat appears to hold the panel out of the CONNECT NOT ACT display state.
  • The transition into CONNECT NOT ACT now looks less like "bad packet was received" and more like "host traffic stopped and a connection/activity timer expired."
  • That suggests the panel may treat regular host traffic as evidence of a live link, even when the session is not fully active.
  • It also suggests CONNECT NOT ACT may be a post-timeout idle/failure state rather than an immediate parse-error state.
  • The fact that restarting the stream does not snap the LCD back out of CONNECT NOT ACT implies the entry condition and exit condition are probably different. Keeping traffic alive may prevent the state, but leaving the state may require a separate activation/ack/session step.

Next refinement worth doing:

  • Repeat NS1 with different transmit intervals such as 100 ms, 500 ms, and 1.5 s to estimate the timeout threshold for preventing CONNECT NOT ACT.

NS2: Primer Only, Short Burst Groups

Use the sequence probe to send the same primer in repeated groups, with a gap between groups, to see whether grouped startup chatter matters differently than an uninterrupted stream.

python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --repeat 6 --repeat-interval 1.0 --read-after-frame 0.6 --read-after-group 0.6 --log captures/rcp-negative-primer-groups.txt

Read goal:

  • If a later group produces anything non-heartbeat, the panel may have a boot window or cadence threshold.
  • If every group is ignored, plain primer repetition is probably dead air from the panel's point of view.

NS3: Known Readable Query Once, Then Silence

Send a known readable query once after the canonical primer and then do nothing else for a longer read window.

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 --read-after-group 5.0 --log captures/rcp-negative-a0-once-then-silence.txt
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 B0 00 80 6A" --read-after-frame 1.2 --read-after-group 5.0 --log captures/rcp-negative-b0-once-then-silence.txt

Read goal:

  • If the panel emits extra delayed frames after the initial block, it may be expecting a host response or entering a timed wait state.
  • If it cleanly returns to heartbeat-only, the one-shot read probably ends the interaction by itself.

NS4: Known Readable Query Repeated

Send the same readable query repeatedly after a primer, without power-cycling, to separate "one-shot per boot" from "suppressed only by mixed traffic."

python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 A0 00 80 7A" --repeat 5 --repeat-interval 1.0 --read-after-frame 1.0 --read-after-group 0.8 --log captures/rcp-negative-a0-repeat.txt
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 B0 00 80 6A" --repeat 5 --repeat-interval 1.0 --read-after-frame 1.0 --read-after-group 0.8 --log captures/rcp-negative-b0-repeat.txt

Read goal:

  • If only the first group responds, that strengthens the one-shot-per-boot model.
  • If a later group responds again, repeated identical polling may be more valid than mixed-family polling.

NS5: Malformed Checksum Once

Send one malformed checksum frame with the same shape as the assumed heartbeat, then observe whether the panel does anything beyond ordinary heartbeat and the known parser-visible display state.

python scripts/serial_probe_response.py --port COM5 --tx-frame "00 00 00 00 80 00" --repeat 1 --delay 3 --after 8 --frame-size 0 --log captures/rcp-negative-bad-heartbeat-once.txt
python scripts/serial_probe_response.py --port COM5 --tx-frame "00 00 A0 00 80 00" --repeat 1 --delay 3 --after 8 --frame-size 0 --log captures/rcp-negative-bad-a0-once.txt

Read goal:

  • If malformed frames cause no special serial result beyond heartbeat, checksum errors are probably tolerated only enough to flip link-visible state.
  • If malformed A0 produces a different visible or serial effect than malformed heartbeat, the parser may be doing more command-byte inspection before checksum rejection than expected.

NS6: Deliberate Silence Control

This is a no-transmit control to compare against all of the above. Just watch RX with no host traffic.

python scripts/serial_button_response_test.py --port COM5 --duration 20

Read goal:

  • Confirm the natural idle pattern and visible state with zero host traffic in the exact same bench setup.

Recommended order:

  1. NS6 silence control
  2. NS1 heartbeat only
  3. NS3 query once then silence
  4. NS4 repeated same query
  5. NS5 malformed checksum once
  6. NS2 primer groups

2026-05-13 Negative-Space Result

Captures:

  • captures/rcp-negative-heartbeat-only.txt
  • captures/rcp-negative-heartbeat-100ms.txt
  • captures/rcp-negative-heartbeat-500ms.txt
  • captures/rcp-negative-heartbeat-1500ms.txt
  • captures/rcp-negative-primer-groups.txt
  • captures/rcp-negative-a0-once-then-silence.txt
  • captures/rcp-negative-b0-once-then-silence.txt
  • captures/rcp-negative-a0-repeat.txt
  • captures/rcp-negative-b0-repeat.txt
  • captures/rcp-negative-bad-heartbeat-once.txt
  • captures/rcp-negative-bad-a0-once.txt

NS1: Assumed Host Heartbeat Only

Observed serial result:

  • The repeated host heartbeat usually left RX at ordinary heartbeat, but some runs produced a short early structured response burst near the second host heartbeat:
    • 07 80 40 60 30 CD
    • 07 80 40 40 30 ED
    • 07 80 C0 40 30 6D
  • These bursts were transient. After them, the link returned to ordinary heartbeat RX while the host heartbeat stream continued.

Observed LCD/timing result from user notes:

  • 100 ms interval: CONNECT NOT ACT appeared near the end before the script fully finished.
  • 500 ms interval: CONNECT NOT ACT appeared once the script finished.
  • 1500 ms interval: the panel timed out at the very end, just before the script finished.
  • Earlier manual observation also still stands: while the heartbeat stream is actively running, the panel can remain out of CONNECT NOT ACT, then fall into it roughly 2 seconds after traffic stops.

Read:

  • Regular heartbeat traffic clearly affects the panel's visible connection timeout behavior.
  • The panel is not treating 00 00 00 00 80 DA as a full activation command, but it does appear to treat it as meaningful host-presence traffic.
  • The brief 0x40 / 0xC0 response bursts suggest some heartbeat cadences can momentarily steer the panel into a different readable state family even without an explicit query.

NS2: Primer Groups

Observed result:

  • Repeated single-frame primer groups produced only heartbeat-compatible RX.
  • No anomalies were logged.

Read:

  • Sparse primer pings alone do not seem to provoke the panel into a readable state.
  • Grouped startup chatter is weaker than a continuous heartbeat stream.

NS3: Known Query Once, Then Silence

Observed result:

Sequence Immediate response Tail behavior
00 -> A0, then silence 07 80 68 40 30 C5 repeated a short additional 07 80 68 40 30 C5 tail, then heartbeat only
00 -> B0, then silence 07 80 6C 40 30 C1 repeated a short additional 07 80 6C 40 30 C1 tail, then heartbeat only

Read:

  • A successful one-shot readable query continues to drain out a short burst for a moment even after host transmission stops.
  • After that short burst, the panel returns cleanly to ordinary heartbeat-only behavior.

NS4: Known Query Repeated

Observed result:

Repeated sequence Result
00 -> A0, repeated 5 times only group 1 produced 07 80 68 40 30 C5; groups 2-5 were heartbeat only
00 -> B0, repeated 5 times only group 1 produced 07 80 6C 40 30 C1; groups 2-5 were heartbeat only

Read:

  • Repeating the exact same known-good readable query does not make it reusable.
  • This strengthens the one-shot-per-boot model for these query families.

NS5: Malformed Checksum Once

Observed result:

  • A malformed heartbeat-shaped frame 00 00 00 00 80 00 produced only ordinary heartbeat RX afterward.
  • A malformed A0-shaped frame 00 00 A0 00 80 00 also produced only ordinary heartbeat RX afterward.

Read:

  • Malformed frames do not seem to trigger a special serial reaction on their own.
  • Whatever visible CONNECT NOT ACT behavior malformed frames may cause on the LCD, it is not accompanied by a distinctive RX response block in these runs.

Overall interpretation:

  • Silence and malformed traffic are serially boring.
  • Successful readable queries still behave as one-shot bursts followed by a return to heartbeat.
  • Repeating those same queries still does not reopen them.
  • Continuous heartbeat traffic is the one negative-space case that clearly changes panel behavior:
    • it can delay or suppress entry into CONNECT NOT ACT
    • it can sometimes provoke brief 0x40 / 0xC0 response-family bursts without any explicit query command

Heartbeat-Maintained Reuse Test

Goal:

  • Check whether keeping a host heartbeat alive between query attempts makes the one-shot readable blocks reusable without power-cycling.

Working idea:

  • Earlier repeat tests used primer -> query groups with idle gaps.
  • The new negative-space tests suggest steady heartbeat traffic may hold the panel in a more connection-aware state.
  • So the next question is whether interleaving regular heartbeats between query attempts can reopen A0 or B0.

HR1: A0 With Heartbeat Maintenance

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 00 00 80 DA" --frame "00 00 00 00 80 DA" --frame "00 00 00 00 80 DA" --repeat 4 --frame-interval 0.25 --read-after-frame 0.35 --read-after-group 0.5 --log captures/rcp-heartbeat-maintained-a0.txt

HR2: B0 With Heartbeat Maintenance

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 00 00 80 DA" --frame "00 00 00 00 80 DA" --frame "00 00 00 00 80 DA" --repeat 4 --frame-interval 0.25 --read-after-frame 0.35 --read-after-group 0.5 --log captures/rcp-heartbeat-maintained-b0.txt

HR3: Denser Heartbeat Maintenance Around A0

python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 00 00 80 DA" --frame "00 00 A0 00 80 7A" --frame "00 00 00 00 80 DA" --frame "00 00 00 00 80 DA" --repeat 4 --frame-interval 0.10 --read-after-frame 0.25 --read-after-group 0.5 --log captures/rcp-heartbeat-maintained-a0-dense.txt

What to watch for:

  • group 1 only responds: heartbeat maintenance is not enough; the latch still dominates
  • later groups respond with the same readable block: heartbeat maintenance partially reopens the one-shot query path
  • later groups do not return A0/B0 but do return 0x40/0xC0 blocks: heartbeat cadence may be moving the panel into a different selector/state family instead of truly reusing the original query

2026-05-13 Heartbeat-Maintained Reuse Result

Captures:

  • captures/rcp-heartbeat-maintained-a0.txt
  • captures/rcp-heartbeat-maintained-b0.txt
  • captures/rcp-heartbeat-maintained-a0-dense.txt

User LCD observation:

  • In all three heartbeat-maintained runs, the panel never entered CONNECT NOT ACT / CONNECTION NOT ACT while the script was running.

HR1: A0 With Heartbeat Maintenance

Observed result:

  • Group 1:
    • A0 produced 07 80 68 40 30 C5
    • the next heartbeat frame drained the tail of that same A0 burst
  • Groups 2-4:
    • A0 produced heartbeat-compatible RX only
    • surrounding heartbeat frames also stayed heartbeat-only

Read:

  • Keeping heartbeat traffic alive after the first A0 response did not make A0 reusable.
  • It did, however, keep the panel in the non-CONNECT NOT ACT display state.

HR2: B0 With Heartbeat Maintenance

Observed result:

  • Group 1:
    • B0 produced one readable block 07 80 6C 40 30 C1
  • Groups 2-4:
    • B0 produced heartbeat-compatible RX only
    • surrounding heartbeat frames stayed heartbeat-only

Read:

  • Same outcome as A0: heartbeat maintenance did not reopen the one-shot query path for B0.

HR3: Denser Heartbeat Maintenance Around A0

Observed result:

  • Group 1:
    • the second heartbeat frame, before A0, provoked 07 80 40 40 30 ED
    • the following A0 frame itself produced only heartbeat-compatible RX
  • Groups 2-4:
    • no A0 response
    • surrounding heartbeat frames stayed heartbeat-compatible

Read:

  • Denser heartbeat traffic can push the panel into the transient 0x40 family state before the A0 query arrives.
  • In that case, the heartbeat-induced 0x40 response appears to consume the one-shot response opportunity and suppress the A0 block.

Overall interpretation:

  • Heartbeat maintenance is strong enough to affect the panel's visible connection state, but not strong enough by itself to make A0/B0 reusable.
  • The latch/one-shot behavior still dominates the readable query families.
  • Dense heartbeat traffic can compete with or displace a later explicit query by provoking a transient 0x40-family response first.
  • Best current model:
    • heartbeat cadence helps hold a "live host present" condition
    • a separate selector/query opportunity still exists only once per boot or once per internal state phase
    • some heartbeat cadences can spend that opportunity on 0x40/0xC0 family responses instead of A0/B0

Next branch worth testing:

  • intentionally provoke the transient heartbeat-induced 0x40/0xC0 family, then immediately query nearby commands to see whether that state exposes a new readable page
  • or combine heartbeat maintenance with the synthetic CALL path, to test whether "host present" plus an event-path trigger behaves differently than "host present" plus a plain table query

Camera-Info-Stream Hypothesis Ladder

Goal:

  • Test the idea that the panel wants more than a plain link heartbeat.
  • Treat one frame family as "host present" and another as possible camera-state/camera-info traffic.
  • Check whether the transient heartbeat-induced 0x40 / 0xC0 family is a different readable page or context, not just noise.

Working model:

  1. host heartbeat says "I am here"
  2. a second family says "here is current camera state"
  3. only then does the panel become fully active

CI1: Provoke 0x40 Family, Then Query B0

Use the same dense double-heartbeat pattern that previously provoked 07 80 40 40 30 ED, then immediately ask for a known B0 block.

python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 00 00 80 DA" --frame "00 00 B0 00 80 6A" --frame "00 00 00 00 80 DA" --frame "00 00 00 00 80 DA" --repeat 4 --frame-interval 0.10 --read-after-frame 0.25 --read-after-group 0.5 --log captures/rcp-camerainfo-40-then-b0.txt

Question:

  • Does the 0x40 family suppress B0, alter B0, or allow a different B0 response family than the normal 07 80 6C 40 30 C1?

CI2: Provoke 0x40 Family, Then Query B5

Same idea, but use the strongest discovery-like block we have.

python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 00 00 80 DA" --frame "00 00 B5 00 80 6F" --frame "00 00 00 00 80 DA" --frame "00 00 00 00 80 DA" --repeat 4 --frame-interval 0.10 --read-after-frame 0.25 --read-after-group 0.5 --log captures/rcp-camerainfo-40-then-b5.txt

Question:

  • If B5 is really a discovery/status block, does entering the heartbeat-driven 0x40 state make it return a different page, or consume it entirely?

CI3: Probe Commands Aligned With The Heartbeat-Induced Family

Try a simple 00 -> 40 and 00 -> C0 query again, but now with a small heartbeat run-up first instead of a bare primer.

python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 00 00 80 DA" --frame "00 00 40 00 80 9A" --read-after-frame 0.4 --read-after-group 1.0 --log captures/rcp-camerainfo-preheart-40.txt
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 00 00 80 DA" --frame "00 00 C0 00 80 1A" --read-after-frame 0.4 --read-after-group 1.0 --log captures/rcp-camerainfo-preheart-c0.txt

Question:

  • Do these commands return something closer to the transient 0x40 / 0xC0 response families when the panel has just seen two host heartbeats?

CI4: Sustained Mixed Stream, Status-Block Style

Instead of repeating one query, rotate through a small set of known readable blocks while keeping heartbeat in the stream.

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 00 00 80 DA" --frame "00 00 B0 00 80 6A" --frame "00 00 00 00 80 DA" --frame "00 00 B5 00 80 6F" --repeat 3 --frame-interval 0.20 --read-after-frame 0.25 --read-after-group 0.8 --log captures/rcp-camerainfo-mixed-a0-b0-b5.txt

Question:

  • Does a rotating "camera info block" stream behave differently from hammering a single one-shot query?

CI5: Sustained Mixed Stream, Heartbeat-Driven Family

Rotate heartbeat around 0x40-family and normal query candidates to see whether the panel prefers a page/state rhythm instead of a static query.

python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 40 00 80 9A" --frame "00 00 00 00 80 DA" --frame "00 00 B0 00 80 6A" --frame "00 00 00 00 80 DA" --frame "00 00 C0 00 80 1A" --repeat 3 --frame-interval 0.20 --read-after-frame 0.25 --read-after-group 0.8 --log captures/rcp-camerainfo-mixed-40-b0-c0.txt

Question:

  • Does mixing the heartbeat-aligned family with a known readable block expose a reusable page, a new response family, or any visible panel state change?

CI6: Sparse Heartbeat Run-Up, Then A0

Try the same idea as the dense 0x40 trigger, but with slower heartbeat spacing that previously nudged the 0xC0 family.

python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 00 00 80 DA" --frame "00 00 A0 00 80 7A" --repeat 3 --frame-interval 1.50 --read-after-frame 0.45 --read-after-group 1.0 --log captures/rcp-camerainfo-c0-then-a0.txt

Question:

  • Does a slower heartbeat-derived state family behave differently from the dense 0x40 case?

What to watch for:

  • the panel stays out of CONNECT NOT ACT for the whole run
  • a known readable block changes family or value fields
  • a later query responds where it previously would not
  • the transient 0x40 / 0xC0 family appears immediately before a different stable block
  • any lamp or display change beyond the usual timeout behavior

Recommended order:

  1. CI1
  2. CI2
  3. CI4
  4. CI5
  5. CI6

2026-05-13 Camera-Info-Stream Result

Captures:

  • captures/rcp-camerainfo-40-then-b0.txt
  • captures/rcp-camerainfo-40-then-b5.txt
  • captures/rcp-camerainfo-preheart-40.txt
  • captures/rcp-camerainfo-preheart-c0.txt
  • captures/rcp-camerainfo-mixed-a0-b0-b5.txt
  • captures/rcp-camerainfo-mixed-40-b0-c0.txt
  • captures/rcp-camerainfo-c0-then-a0.txt

User observation:

  • In CI6, the panel appeared to enter CONNECT NOT ACT and then emit a single latch/readable response afterward.

CI1: Provoke 0x40/0xC0, Then Query B0

Observed result:

  • Group 1:
    • the second heartbeat produced 07 80 C0 40 30 6D
    • the following B0 query produced only heartbeat-compatible RX
  • Groups 2-4:
    • no structured B0 response
    • all later frames stayed heartbeat-compatible

Read:

  • The heartbeat-induced 0xC0 family did not open a new B0 page.
  • It appears to consume or displace the normal one-shot response opportunity.

CI2: Provoke 0x40, Then Query B5

Observed result:

  • Group 1:
    • the second heartbeat produced 07 80 40 40 30 ED
    • the following B5 query produced only heartbeat-compatible RX
  • Groups 2-4:
    • B5 remained heartbeat-compatible only

Read:

  • Same story as CI1: the heartbeat-driven family does not seem to lead into a richer B5 discovery page.
  • It suppresses or replaces it.

CI3: Probe Commands Aligned With The Heartbeat-Induced Family

Observed result:

Sequence Result
double heartbeat, then 00 -> 40 heartbeat-induced 07 80 40 40 30 ED, then 00 -> 40 gave heartbeat only
double heartbeat, then 00 -> C0 heartbeat-induced 07 80 40 40 30 ED, then 00 -> C0 only drained more 07 80 40 40 30 ED plus heartbeat

Read:

  • The pre-heartbeat 0x40 state does not make the explicit 40 or C0 commands bloom into a clear new readable block.
  • The explicit commands mostly arrive after the transient state is already in progress.

CI4: Sustained Mixed Stream, Status-Block Style

Observed result:

  • Group 1:
    • A0 produced 07 80 68 40 30 C5
    • later B0 and B5 in the same mixed stream were heartbeat only
  • Groups 2-3:
    • A0, B0, and B5 were all heartbeat-compatible only

Read:

  • A rotating "camera info block" stream did not keep opening new readable status pages.
  • The first successful block still wins, then the rest are suppressed.

CI5: Sustained Mixed Stream, Heartbeat-Driven Family

Observed result:

  • Group 1:
    • 00 -> 40 produced 07 80 50 40 30 FD
    • later B0 and C0 in the same stream were heartbeat only
  • Groups 2-3:
    • all later frames were heartbeat-compatible only

Read:

  • This confirms 00 -> 40 is a stable explicit query family in its own right.
  • But, again, the first successful readable family suppresses later queries in the same stream.

CI6: Sparse Heartbeat Run-Up, Then A0

Observed result:

  • Group 1:
    • two widely spaced heartbeat frames stayed heartbeat-compatible
    • the later A0 produced a delayed 07 80 68 40 30 C5 burst
  • Groups 2-3:
    • the same pattern returned heartbeat-compatible RX only

Read:

  • This matches the user's observation well: a slow run-up can leave the panel visibly in CONNECT NOT ACT, yet a later single readable/latch response can still occur afterward.
  • That suggests the visible display state and the one-shot readable window are related, but not identical.
  • A panel that has already fallen into CONNECT NOT ACT may still accept one later readable query under the right timing.

Overall interpretation:

  • The "camera info stream" hypothesis is not wrong, but this particular test set did not show a sustained multi-block camera-state feed.
  • The heartbeat-induced 0x40 / 0xC0 family is real, but it mostly acts like a competing one-shot response family, not a gateway into a larger page.
  • Mixed streams still collapse into "first successful block wins."
  • The cleanest new points are:
    • 00 -> 40 is a real explicit readable family: 07 80 50 40 30 FD
    • heartbeat cadence can provoke 0x40 / 0xC0 families without an explicit query
    • a visible CONNECT NOT ACT state does not completely forbid one later readable/latch response

Next branch worth testing:

  • isolate the delayed-after-CONNECT NOT ACT case from CI6 with a small timing ladder around the final A0
  • compare A0, B0, and 40 after a deliberate wait-until-CONNECT NOT ACT phase
  • test whether the 0x40 / 0xC0 families are better thought of as alternate readable pages rather than camera-info keepalives

CONNECT NOT ACT vs Latch-State Decoupling Test

Goal:

  • Prove that the visible CONNECT NOT ACT state and the one-shot readable/latch state are related, but not the same thing.
  • Show one case where the latch is spent even though the panel does not enter CONNECT NOT ACT.
  • Show another case where the panel does enter CONNECT NOT ACT and can still produce one later readable response.

Interpretation target:

  • If both paths happen, the LCD state is not a direct indicator of whether the one-shot readable window is still available.

DL1: Latch Spent While CONNECT NOT ACT Stays Away

This is the "no visible timeout, but latch already consumed" proof.

Watch the LCD throughout. The expected result is that the panel stays out of CONNECT NOT ACT while running.

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 00 00 80 DA" --frame "00 00 00 00 80 DA" --frame "00 00 00 00 80 DA" --repeat 3 --frame-interval 0.25 --read-after-frame 0.35 --read-after-group 0.5 --log captures/rcp-decouple-no-connectnotact-a0.txt

What proves decoupling:

  • group 1: A0 responds
  • later groups: A0 does not respond
  • LCD never enters CONNECT NOT ACT during the run

That shows the latch can be spent even while the display does not show the timeout/not-active state.

DL2: Deliberate CONNECT NOT ACT, Then Late A0

This is the "visible timeout, but one late readable response still exists" proof.

Method:

  • power-cycle
  • watch for the panel to show CONNECT NOT ACT between the first heartbeat and the later A0
python scripts/serial_sequence_probe.py --port COM5 --prompt --pre-read 1.0 --frame "00 00 00 00 80 DA" --frame "00 00 A0 00 80 7A" --frame-interval 2.50 --read-after-frame 0.30 --read-after-group 1.0 --log captures/rcp-decouple-connectnotact-then-a0.txt

What proves decoupling:

  • the panel visibly enters CONNECT NOT ACT
  • the later A0 still returns 07 80 68 40 30 C5

That shows the visible CONNECT NOT ACT state does not automatically mean the readable/latch opportunity is gone.

DL3: Deliberate CONNECT NOT ACT, Then Two Late A0 Queries

This tightens DL2 by checking whether the first late query can consume the remaining one-shot readable window while the LCD state stays the same.

python scripts/serial_sequence_probe.py --port COM5 --prompt --pre-read 1.0 --frame "00 00 00 00 80 DA" --frame "00 00 A0 00 80 7A" --frame "00 00 A0 00 80 7A" --frame-interval 2.50 --read-after-frame 0.30 --read-after-group 1.0 --log captures/rcp-decouple-connectnotact-then-a0-a0.txt

What proves decoupling:

  • panel enters CONNECT NOT ACT
  • first late A0 responds
  • second late A0 does not
  • LCD remains in the same visible state

That shows the latch/readable state can change while the display state does not.

DL4: Compare Late A0, B0, and 40 After CONNECT NOT ACT

This checks whether only some readable families survive the visible timeout state.

python scripts/serial_sequence_probe.py --port COM5 --prompt --pre-read 1.0 --frame "00 00 00 00 80 DA" --frame "00 00 B0 00 80 6A" --frame-interval 2.50 --read-after-frame 0.30 --read-after-group 1.0 --log captures/rcp-decouple-connectnotact-then-b0.txt
python scripts/serial_sequence_probe.py --port COM5 --prompt --pre-read 1.0 --frame "00 00 00 00 80 DA" --frame "00 00 40 00 80 9A" --frame-interval 2.50 --read-after-frame 0.30 --read-after-group 1.0 --log captures/rcp-decouple-connectnotact-then-40.txt

Useful outcomes:

  • only A0 responds late: the post-timeout window may be family-specific
  • A0, B0, and 40 all respond late: the timeout state is clearly not the same as the latch state
  • none respond late: the CI6 late response was timing-sensitive and needs a tighter delay ladder

DL5: Tight Delay Ladder Around Late A0

If DL2 or DL3 looks close but inconsistent, bracket the timeout edge.

python scripts/serial_sequence_probe.py --port COM5 --prompt --pre-read 1.0 --frame "00 00 00 00 80 DA" --frame "00 00 A0 00 80 7A" --frame-interval 2.00 --read-after-frame 0.30 --read-after-group 1.0 --log captures/rcp-decouple-delay-2000ms-a0.txt
python scripts/serial_sequence_probe.py --port COM5 --prompt --pre-read 1.0 --frame "00 00 00 00 80 DA" --frame "00 00 A0 00 80 7A" --frame-interval 2.25 --read-after-frame 0.30 --read-after-group 1.0 --log captures/rcp-decouple-delay-2250ms-a0.txt
python scripts/serial_sequence_probe.py --port COM5 --prompt --pre-read 1.0 --frame "00 00 00 00 80 DA" --frame "00 00 A0 00 80 7A" --frame-interval 2.50 --read-after-frame 0.30 --read-after-group 1.0 --log captures/rcp-decouple-delay-2500ms-a0.txt
python scripts/serial_sequence_probe.py --port COM5 --prompt --pre-read 1.0 --frame "00 00 00 00 80 DA" --frame "00 00 A0 00 80 7A" --frame-interval 2.75 --read-after-frame 0.30 --read-after-group 1.0 --log captures/rcp-decouple-delay-2750ms-a0.txt

Recommended order:

  1. DL1
  2. DL2
  3. DL3
  4. DL4
  5. DL5 only if DL2/DL3 are close but inconsistent

2026-05-13 CONNECT NOT ACT vs Latch-State Decoupling Result

Captures:

  • captures/rcp-decouple-no-connectnotact-a0.txt
  • captures/rcp-decouple-connectnotact-then-a0.txt
  • captures/rcp-decouple-connectnotact-then-a0-a0.txt

User LCD observation:

  • DL1: the panel never presented CONNECT NOT ACT while the script was running.
  • DL2 and DL3: the panel presented CONNECT NOT ACT at the start of the script.

DL1: Latch Spent While CONNECT NOT ACT Stays Away

Observed result:

  • Group 1:
    • A0 produced a readable block, but this run returned 07 80 E8 40 30 45 rather than 07 80 68 40 30 C5
  • Groups 2-3:
    • A0 produced heartbeat-compatible RX only
  • LCD:
    • no CONNECT NOT ACT while the script was active

Read:

  • This is strong evidence for decoupling in one direction: the readable/latch state can be consumed while the panel does not show CONNECT NOT ACT.
  • It also reinforces that the A0 family can vary between at least 68 and E8 forms depending on context/timing.

DL2: Deliberate CONNECT NOT ACT, Then Late A0

Observed result:

  • The panel showed CONNECT NOT ACT early in the run.
  • The later A0 query produced heartbeat-compatible RX only.
  • No delayed A0 readable block appeared at this exact timing.

Read:

  • At a 2.50 s gap in this two-frame form, visible CONNECT NOT ACT did not guarantee a late readable response.
  • This weakens the simple "enter CONNECT NOT ACT, then A0 always still works once" idea.

DL3: Deliberate CONNECT NOT ACT, Then Two Late A0 Queries

Observed result:

  • The panel showed CONNECT NOT ACT early in the run.
  • Both later A0 queries produced heartbeat-compatible RX only.
  • No readable block appeared on either late A0.

Read:

  • This does not provide the hoped-for second half of the decoupling proof.
  • Instead, it says that once the panel has visibly entered CONNECT NOT ACT in this specific timing pattern, the late A0 opportunity may already be gone or may require narrower timing than 2.50 s.

Overall interpretation:

  • We now have solid evidence for one half of the claim: CONNECT NOT ACT is not required for the latch/readable state to be consumed.
  • We do not yet have equally solid evidence for the other half at this timing: a visible CONNECT NOT ACT state did not still yield a late A0 response in DL2 or DL3.
  • So the current safest statement is: the LCD state and the latch/readable state are not directly coupled, but the exact post-timeout behavior is more timing-sensitive than the earlier CI6 observation first suggested.

Best next move:

  • run DL4 and then a tight DL5 delay bracket
  • especially around 2.00 s, 2.25 s, 2.50 s, and 2.75 s
  • because the difference between the earlier CI6 late hit and these no-hit decoupling runs is now most likely timing, framing shape, or both

Heartbeat-Family Echo Probes

Goal:

  • Test whether the newer heartbeat-induced response families behave more like camera-state blocks that the host is expected to mirror or acknowledge.
  • Compare exact echo versus host-shaped mirror for the same apparent payload.

Best current echo candidates:

  • heartbeat-induced:
    • 07 80 40 40 30 ED
    • 07 80 40 60 30 CD
    • 07 80 C0 40 30 6D
  • explicit 00 -> 40 family:
    • 07 80 50 40 30 FD
  • context-sensitive A0 variant:
    • 07 80 E8 40 30 45

Host-shaped mirrors:

  • 00 00 40 40 30 6A
  • 00 00 40 60 30 4A
  • 00 00 C0 40 30 EA
  • 00 00 50 40 30 7A
  • 00 00 E8 40 30 C2

HE1: Exact Echo Of 07 80 40 40 30 ED

python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 00 00 80 DA" --frame "07 80 40 40 30 ED" --frame "00 00 00 00 80 DA" --frame "00 00 00 00 80 DA" --repeat 3 --frame-interval 0.10 --read-after-frame 0.25 --read-after-group 0.5 --log captures/rcp-heartbeat-echo-exact-404030ed.txt

HE2: Host-Shaped Mirror Of 07 80 40 40 30 ED

python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 00 00 80 DA" --frame "00 00 40 40 30 6A" --frame "00 00 00 00 80 DA" --frame "00 00 00 00 80 DA" --repeat 3 --frame-interval 0.10 --read-after-frame 0.25 --read-after-group 0.5 --log captures/rcp-heartbeat-echo-host-404030.txt

HE3: Exact Echo Of 07 80 C0 40 30 6D

python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 00 00 80 DA" --frame "07 80 C0 40 30 6D" --frame "00 00 00 00 80 DA" --frame "00 00 00 00 80 DA" --repeat 3 --frame-interval 0.10 --read-after-frame 0.25 --read-after-group 0.5 --log captures/rcp-heartbeat-echo-exact-c040306d.txt

HE4: Host-Shaped Mirror Of 07 80 C0 40 30 6D

python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 00 00 80 DA" --frame "00 00 C0 40 30 EA" --frame "00 00 00 00 80 DA" --frame "00 00 00 00 80 DA" --repeat 3 --frame-interval 0.10 --read-after-frame 0.25 --read-after-group 0.5 --log captures/rcp-heartbeat-echo-host-c04030.txt

HE5: Exact Echo Of Explicit 00 -> 40 Response

python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 40 00 80 9A" --frame "07 80 50 40 30 FD" --frame "00 00 00 00 80 DA" --frame "00 00 00 00 80 DA" --repeat 2 --frame-interval 0.20 --read-after-frame 0.30 --read-after-group 0.6 --log captures/rcp-heartbeat-echo-exact-504030fd.txt

HE6: Host-Shaped Mirror Of Explicit 00 -> 40 Response

python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 40 00 80 9A" --frame "00 00 50 40 30 7A" --frame "00 00 00 00 80 DA" --frame "00 00 00 00 80 DA" --repeat 2 --frame-interval 0.20 --read-after-frame 0.30 --read-after-group 0.6 --log captures/rcp-heartbeat-echo-host-504030.txt

HE7: Echo The A0 Variant From DL1

python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 A0 00 80 7A" --frame "07 80 E8 40 30 45" --frame "00 00 00 00 80 DA" --frame "00 00 00 00 80 DA" --repeat 2 --frame-interval 0.20 --read-after-frame 0.30 --read-after-group 0.6 --log captures/rcp-heartbeat-echo-exact-e8403045.txt
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 A0 00 80 7A" --frame "00 00 E8 40 30 C2" --frame "00 00 00 00 80 DA" --frame "00 00 00 00 80 DA" --repeat 2 --frame-interval 0.20 --read-after-frame 0.30 --read-after-group 0.6 --log captures/rcp-heartbeat-echo-host-e84030.txt

What would count as a hit:

  • any new non-heartbeat RCP frame after the echo/mirror
  • the panel leaving or changing behavior around CONNECT NOT ACT
  • a previously one-shot query family becoming readable again
  • the echo path producing a repeatable family-specific response

Recommended order:

  1. HE2
  2. HE4
  3. HE1
  4. HE3
  5. HE6
  6. HE7

2026-05-13 Heartbeat-Family Echo Result

Captures:

  • captures/rcp-heartbeat-echo-host-404030.txt
  • captures/rcp-heartbeat-echo-host-c04030.txt
  • captures/rcp-heartbeat-echo-exact-404030ed.txt
  • captures/rcp-heartbeat-echo-exact-c040306d.txt
  • captures/rcp-heartbeat-echo-host-504030.txt
  • captures/rcp-heartbeat-echo-exact-504030fd.txt
  • captures/rcp-heartbeat-echo-exact-e8403045.txt
  • captures/rcp-heartbeat-echo-host-e84030.txt

HE1 / HE2 / HE3 / HE4: Echoing The Heartbeat-Induced 0x40 / 0xC0 Families

Observed result:

  • 07 80 40 40 30 ED exact echo: no new structured response after the echo.
  • 00 00 40 40 30 6A host-shaped mirror: no new structured response after the mirror.
  • 07 80 C0 40 30 6D exact echo: no new structured response after the echo.
  • 00 00 C0 40 30 EA host-shaped mirror: no new structured response after the mirror.

Read:

  • The heartbeat-induced 0x40 / 0xC0 families do not currently look like payloads the panel expects to receive back as an echo or mirror.
  • They behave more like one-way readable/context responses than a bidirectional acknowledge-and-continue exchange.

HE5 / HE6: Echoing The Explicit 00 -> 40 Response Family

Observed result:

  • 00 -> 40 again produced the known readable block 07 80 50 40 30 FD.
  • Exact echo of that block, 07 80 50 40 30 FD, produced no new structured response.
  • Host-shaped mirror, 00 00 50 40 30 7A, also produced no new structured response.
  • In the host-shaped mirror run, a later plain heartbeat again provoked the transient 07 80 40 40 30 ED family rather than any direct reply to the mirror.

Read:

  • The explicit 00 -> 40 family also does not behave like something the panel wants echoed back in either exact or host-shaped form.
  • The reappearance of 07 80 40 40 30 ED after the mirror reinforces that the heartbeat/context state machine is still active in the background and can dominate what happens next.

HE7: Echoing The A0 Variant From DL1

Observed result:

Two distinct outcomes appeared here:

  • Exact echo path:
    • 00 -> A0 did not log its usual readable block in the immediate window
    • sending exact 07 80 E8 40 30 45 produced a new unexpected response: 07 C0 7A 50 A6 11
  • Host-shaped mirror path:
    • 00 00 E8 40 30 C2 produced another new structured response: 07 80 FA 50 26 51

Read:

  • This is the first heartbeat-family echo probe set that produced genuinely new structured responses rather than just heartbeat.
  • The E8/FA area now looks much more interesting than the 40/C0 exact echo families.
  • We do not yet know whether:
    • 07 C0 7A 50 A6 11 is a valid stable family or a context-fragmented reply
    • 07 80 FA 50 26 51 is a proper readable page, an error/status block, or a transformed reply to the E8-family mirror
  • But these are strong enough to treat as new leads rather than noise.

Overall interpretation:

  • Most heartbeat-family responses do not behave like simple values the host should echo back.
  • The exception is the A0-variant / E8 area, where echoing or host-mirroring produced fresh structured responses.
  • So the most promising echo branch is no longer generic 40/C0 heartbeat mirroring, but focused follow-up around:
    • 07 80 E8 40 30 45
    • 07 80 FA 50 26 51
    • 07 C0 7A 50 A6 11

Next branch worth testing:

  • reproduce the E8-mirror path cleanly and see whether FA and 7A are stable
  • try host-shaped and exact echoes of 07 80 FA 50 26 51
  • probe whether FA / 7A correspond to nearby explicit host queries such as 00 -> FA or 00 -> 7A

HE8: Exact Echo Of 07 80 FA 50 26 51

Recreate the E8 host-mirror path that previously produced 07 80 FA 50 26 51, then immediately send the exact FA frame back.

python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 A0 00 80 7A" --frame "00 00 E8 40 30 C2" --frame "07 80 FA 50 26 51" --frame "00 00 00 00 80 DA" --frame "00 00 00 00 80 DA" --repeat 2 --frame-interval 0.20 --read-after-frame 0.30 --read-after-group 0.8 --log captures/rcp-heartbeat-echo-exact-fa502651.txt

HE9: Host-Shaped Mirror Of 07 80 FA 50 26 51

Host-shaped checksum for 00 00 FA 50 26 ?? is D6.

python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 A0 00 80 7A" --frame "00 00 E8 40 30 C2" --frame "00 00 FA 50 26 D6" --frame "00 00 00 00 80 DA" --frame "00 00 00 00 80 DA" --repeat 2 --frame-interval 0.20 --read-after-frame 0.30 --read-after-group 0.8 --log captures/rcp-heartbeat-echo-host-fa5026.txt

What would count as a hit:

  • any fresh structured response after the FA echo or mirror
  • a repeat of 07 80 FA 50 26 51 or 07 C0 7A 50 A6 11
  • any new family in the 50 / 7A / FA region
  • visible panel behavior changing beyond the usual CONNECT NOT ACT

2026-05-13 FA Echo Follow-Up Result

Captures:

  • captures/rcp-heartbeat-echo-exact-fa502651.txt
  • captures/rcp-heartbeat-echo-host-fa5026.txt

Result summary:

  • Both runs behaved the same way.
  • In group 1, the host-shaped E8 step 00 00 E8 40 30 C2 produced a new structured family: 07 80 7A 50 26 D1
  • That 7A family appeared twice immediately after the E8 host-mirror step in both runs.
  • The following FA step, whether exact echo 07 80 FA 50 26 51 or host-shaped mirror 00 00 FA 50 26 D6, did not produce a fresh distinct reply. The receive window only showed one more 07 80 7A 50 26 D1 followed by heartbeat.
  • In group 2, both runs were heartbeat-only after the same sequence.

Interpretation:

  • The meaningful branch point still appears to be the host-shaped E8 frame, not the subsequent FA echo/mirror.
  • 07 80 FA 50 26 51 is not yet behaving like a value the host should directly answer to advance the exchange.
  • 07 80 7A 50 26 D1 is now a stronger candidate for a real sibling response family in this branch than 07 C0 7A 50 A6 11, because it reproduced in both HE8 and HE9 group-1 runs.
  • The fact that HE8 and HE9 were serially identical suggests the panel likely emitted a delayed/queued 7A-family response from the E8 host-mirror step, rather than parsing the FA follow-up as a meaningful new command.

Best current model of this branch:

  • 00 00 E8 40 30 C2 can lead into a 7A / FA response family.
  • 07 80 FA 50 26 51 may be one branch member, but answering it directly did not produce a second-stage exchange.
  • The next useful probe should probably target 07 80 7A 50 26 D1 directly, or compare exact-vs-host handling of 7A rather than FA.

HE10: Exact Echo Of 07 80 7A 50 26 D1

Recreate the host-shaped E8 path that now reproducibly yields 07 80 7A 50 26 D1, then immediately send that exact 7A frame back.

python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 A0 00 80 7A" --frame "00 00 E8 40 30 C2" --frame "07 80 7A 50 26 D1" --frame "00 00 00 00 80 DA" --frame "00 00 00 00 80 DA" --repeat 2 --frame-interval 0.20 --read-after-frame 0.30 --read-after-group 0.8 --log captures/rcp-heartbeat-echo-exact-7a5026d1.txt

HE11: Host-Shaped Mirror Of 07 80 7A 50 26 D1

Host-shaped checksum for 00 00 7A 50 26 ?? is 56.

python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 A0 00 80 7A" --frame "00 00 E8 40 30 C2" --frame "00 00 7A 50 26 56" --frame "00 00 00 00 80 DA" --frame "00 00 00 00 80 DA" --repeat 2 --frame-interval 0.20 --read-after-frame 0.30 --read-after-group 0.8 --log captures/rcp-heartbeat-echo-host-7a5026.txt

What would count as a hit:

  • any new non-heartbeat response after the 7A echo or mirror
  • a stable second-stage family after 07 80 7A 50 26 D1
  • recurrence of FA, 7A, or another new 50-region family
  • any visible panel behavior change beyond the usual CONNECT NOT ACT

2026-05-13 7A Echo Follow-Up Result

Captures:

  • captures/rcp-heartbeat-echo-exact-7a5026d1.txt
  • captures/rcp-heartbeat-echo-host-7a5026.txt

Result summary:

  • Both runs again point to the host-shaped E8 step as the meaningful branch trigger.
  • In group 1, 00 00 E8 40 30 C2 reproduced 07 80 7A 50 26 D1 in both tests.
  • The exact-echo run was the cleanest:
    • 00 00 E8 40 30 C2 produced one 07 80 7A 50 26 D1
    • exact echo 07 80 7A 50 26 D1 produced only heartbeat afterwards
  • The host-shaped mirror run behaved like the earlier FA tests:
    • 00 00 E8 40 30 C2 produced 07 80 7A 50 26 D1 twice
    • host-shaped 00 00 7A 50 26 56 then only drained one more 07 80 7A 50 26 D1 followed by heartbeat
  • In group 2, both tests were heartbeat-only after the same sequence.

Interpretation:

  • 07 80 7A 50 26 D1 is now a confirmed reproducible response family on the host-shaped E8 branch.
  • But directly echoing 7A, whether exact or host-shaped, still did not create a second-stage exchange, visible state change, or reusable session behavior.
  • This makes 7A look more like another readable/event family emitted by the branch, not yet like the next host command the panel expects.
  • The asymmetry is useful:
    • host-shaped E8 can provoke 7A
    • 7A itself does not obviously provoke anything back

Best current model of the E8 branch:

  • 00 00 E8 40 30 C2 is the active stimulus.
  • 07 80 7A 50 26 D1 is the most reproducible downstream response in that branch.
  • 07 80 FA 50 26 51 and 07 C0 7A 50 A6 11 remain side-family observations, but neither has overtaken 7A as the strongest lead.

HE12: Nearby Host-Shaped E8 Neighbors

Test whether the 7A branch is specific to E8, or whether nearby host-shaped commands in the same region also provoke structured responses.

Checksums:

  • 00 00 E7 40 30 CD
  • 00 00 E9 40 30 C3
  • 00 00 EA 40 30 C0

HE12a: Host-Shaped E7

python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 A0 00 80 7A" --frame "00 00 E7 40 30 CD" --frame "00 00 00 00 80 DA" --frame "00 00 00 00 80 DA" --repeat 2 --frame-interval 0.20 --read-after-frame 0.30 --read-after-group 0.8 --log captures/rcp-heartbeat-neighbor-e7.txt

HE12b: Host-Shaped E9

python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 A0 00 80 7A" --frame "00 00 E9 40 30 C3" --frame "00 00 00 00 80 DA" --frame "00 00 00 00 80 DA" --repeat 2 --frame-interval 0.20 --read-after-frame 0.30 --read-after-group 0.8 --log captures/rcp-heartbeat-neighbor-e9.txt

HE12c: Host-Shaped EA

python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 A0 00 80 7A" --frame "00 00 EA 40 30 C0" --frame "00 00 00 00 80 DA" --frame "00 00 00 00 80 DA" --repeat 2 --frame-interval 0.20 --read-after-frame 0.30 --read-after-group 0.8 --log captures/rcp-heartbeat-neighbor-ea.txt

What would count as a hit:

  • any non-heartbeat response after E7, E9, or EA
  • recurrence of 07 80 7A 50 26 D1
  • recurrence of 07 80 FA 50 26 51 or 07 C0 7A 50 A6 11
  • any new stable family that suggests E8 belongs to a broader selector block

2026-05-13 E8 Neighbor Result

Captures:

  • captures/rcp-heartbeat-neighbor-e7.txt
  • captures/rcp-heartbeat-neighbor-e9.txt
  • captures/rcp-heartbeat-neighbor-ea.txt

Result summary:

  • E7, E9, and EA do not behave the same way, so this is not a simple "everything around E8 lands in the same branch" region.
  • All three effects only appeared in group 1. Group 2 was heartbeat-only in every run.

Observed outputs:

Host step Structured result
00 00 E7 40 30 CD later heartbeat provoked 07 80 40 40 30 ED
00 00 E9 40 30 C3 produced 07 80 7A 28 D3 5C
00 00 EA 40 30 C0 later heartbeat provoked 07 80 C0 40 30 6D

Interpretation:

  • E8 still appears special, because it is the one that most cleanly enters the reproducible 07 80 7A 50 26 D1 branch.
  • E9 is the first nearby neighbor to produce a clearly related but distinct 7A-family frame:
    • 07 80 7A 28 D3 5C
  • E7 and EA look more like they bias the panel toward known heartbeat-family transients (07 80 40 40 30 ED and 07 80 C0 40 30 6D) rather than the 7A / FA branch.
  • So the emerging picture is not a broad contiguous "E* equals same page" block, but a mixed neighborhood where nearby host-shaped values steer the panel into different transient/readable families.

Best current follow-up:

  • treat E9 as the strongest neighbor lead
  • test exact and host-shaped handling of 07 80 7A 28 D3 5C
  • optionally compare E8 vs E9 timing to see whether the differing 7A payloads reflect selector choice or timing/context

HE13: Exact Echo Of 07 80 7A 28 D3 5C

Recreate the E9 neighbor path, then immediately send the exact 7A-family response back to the panel.

python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 A0 00 80 7A" --frame "00 00 E9 40 30 C3" --frame "07 80 7A 28 D3 5C" --frame "00 00 00 00 80 DA" --frame "00 00 00 00 80 DA" --repeat 2 --frame-interval 0.20 --read-after-frame 0.30 --read-after-group 0.8 --log captures/rcp-heartbeat-echo-exact-7a28d35c.txt

HE14: Host-Shaped Mirror Of 07 80 7A 28 D3 5C

Host-shaped checksum for 00 00 7A 28 D3 ?? is DB.

python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 A0 00 80 7A" --frame "00 00 E9 40 30 C3" --frame "00 00 7A 28 D3 DB" --frame "00 00 00 00 80 DA" --frame "00 00 00 00 80 DA" --repeat 2 --frame-interval 0.20 --read-after-frame 0.30 --read-after-group 0.8 --log captures/rcp-heartbeat-echo-host-7a28d3.txt

What would count as a hit:

  • any non-heartbeat response after the exact or host-shaped 7A 28 D3 frame
  • a repeat of 07 80 7A 28 D3 5C
  • crossover into the E8-style 07 80 7A 50 26 D1 or 07 80 FA 50 26 51 branch
  • any new stable family that suggests E9 is a second entry point into the same broader selector surface

2026-05-13 E9 Mirror Result

Captures:

  • captures/rcp-heartbeat-echo-exact-7a28d35c.txt
  • captures/rcp-heartbeat-echo-host-7a28d3.txt

Result summary:

  • E9 cleanly reproduced its 7A-family response in group 1 in both tests:
    • 07 80 7A 28 D3 5C
  • Exact echo 07 80 7A 28 D3 5C produced only heartbeat afterwards.
  • Host-shaped mirror 00 00 7A 28 D3 DB did not open a new stage either; it only drained more copies of 07 80 7A 28 D3 5C before falling back to heartbeat.
  • Group 2 was heartbeat-only in both tests.

Interpretation:

  • E9 behaves very much like the E8 branch structurally:
    • the host-shaped E9 step is the active stimulus
    • the downstream 7A response is real and reproducible
    • but directly echoing or mirroring that 7A response does not advance the exchange
  • So E8 and E9 now look like sibling selector-style entry points into related but distinct 7A-family outputs:
    • E8 -> 07 80 7A 50 26 D1
    • E9 -> 07 80 7A 28 D3 5C
  • This strengthens the idea that the Ex region may be selecting pages or classes of status rather than carrying the real session-advance command.

Best current next move:

  • test more nearby Ex values to see whether this is a broader selector strip
  • or try explicit host queries for the downstream family bytes (00 -> 7A, 00 -> FA) after E8/E9 selection

HE15: Continue Outward In The Ex Neighborhood

Push one step farther out from the now-interesting E8 / E9 region and see whether the selector-like behavior continues, shifts family again, or collapses back into heartbeat-only behavior.

Checksums:

  • 00 00 E6 40 30 CC
  • 00 00 EB 40 30 C1
  • 00 00 EC 40 30 C6

HE15a: Host-Shaped E6

python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 A0 00 80 7A" --frame "00 00 E6 40 30 CC" --frame "00 00 00 00 80 DA" --frame "00 00 00 00 80 DA" --repeat 2 --frame-interval 0.20 --read-after-frame 0.30 --read-after-group 0.8 --log captures/rcp-heartbeat-neighbor-e6.txt

HE15b: Host-Shaped EB

python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 A0 00 80 7A" --frame "00 00 EB 40 30 C1" --frame "00 00 00 00 80 DA" --frame "00 00 00 00 80 DA" --repeat 2 --frame-interval 0.20 --read-after-frame 0.30 --read-after-group 0.8 --log captures/rcp-heartbeat-neighbor-eb.txt

HE15c: Host-Shaped EC

python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 A0 00 80 7A" --frame "00 00 EC 40 30 C6" --frame "00 00 00 00 80 DA" --frame "00 00 00 00 80 DA" --repeat 2 --frame-interval 0.20 --read-after-frame 0.30 --read-after-group 0.8 --log captures/rcp-heartbeat-neighbor-ec.txt

What would count as a hit:

  • any new non-heartbeat response after E6, EB, or EC
  • recurrence of the E8-style 07 80 7A 50 26 D1 or E9-style 07 80 7A 28 D3 5C
  • recurrence of known heartbeat-family transients like 07 80 40 40 30 ED or 07 80 C0 40 30 6D
  • any additional family that strengthens the idea of a selector strip across the Ex region

2026-05-13 Outward Ex Result

Captures:

  • captures/rcp-heartbeat-neighbor-e6.txt
  • captures/rcp-heartbeat-neighbor-eb.txt
  • captures/rcp-heartbeat-neighbor-ec.txt

Result summary:

  • E6 and EB behaved the same way:
    • no immediate structured reply at the Ex step
    • the following heartbeat provoked 07 80 40 40 30 ED
  • EC produced a new structured family in group 1:
    • 07 80 7B 50 26 D0
  • As with the other recent selector tests, all interesting behavior was group 1 only. Group 2 was heartbeat-only.

Observed outputs:

Host step Structured result
00 00 E6 40 30 CC later heartbeat provoked 07 80 40 40 30 ED
00 00 EB 40 30 C1 later heartbeat provoked 07 80 40 40 30 ED
00 00 EC 40 30 C6 produced 07 80 7B 50 26 D0

Interpretation:

  • The Ex neighborhood is continuing to look like a selector-like strip with mixed outcomes, not a uniform command class.
  • E6, E7, and EB now cluster together as values that bias into the 07 80 40 40 30 ED heartbeat-family transient.
  • E8 and E9 open distinct 7A-family responses:
    • E8 -> 07 80 7A 50 26 D1
    • E9 -> 07 80 7A 28 D3 5C
  • EC now extends that pattern one step further with a new sibling:
    • EC -> 07 80 7B 50 26 D0
  • EA remains its own case steering toward 07 80 C0 40 30 6D.

Best current follow-up:

  • treat EC as the next strong lead and test exact/host-shaped handling of 07 80 7B 50 26 D0
  • optionally try ED next to see whether the 7B branch continues