diff --git a/docs/instantel_protocol_reference.md b/docs/instantel_protocol_reference.md index 4188c95..c65d41e 100644 --- a/docs/instantel_protocol_reference.md +++ b/docs/instantel_protocol_reference.md @@ -40,6 +40,10 @@ | 2026-03-02 | §14 Open Questions | `0x082A` hypothesis refined: 2090 decimal. At 1024 sps, 2 sec record = 2048 samples. Possible that 0x082A = total samples including 0.25s pre-trigger (256 samples) at some adjusted rate. Needs capture with different record time. | | 2026-03-02 | §14 Open Questions | **NEW items added:** Trigger sample width (default=2), Auto Window (1-9 sec), Aux Trigger (enabled/disabled) — all confirmed settings from operator manual not yet mapped in protocol. | | 2026-03-02 | §14 Open Questions | Monitoring LCD Cycle resolved — removed from open questions. | +| 2026-03-02 | Appendix A | **CORRECTED:** Previous entry stated logger strips DLE from ETX. This was wrong — it applied to an older logger version. `s3_bridge v0.5.0` confirmed to preserve raw wire bytes including `0x10 0x03` intact. HxD inspection of new capture confirmed `10 03` present in S3→BW record payloads. | +| 2026-03-02 | Appendix A | **UPDATED:** New capture architecture: two flat raw wire dumps per session (`raw_s3.bin`, `raw_bw.bin`), one per direction, no record wrapper. Replaces structured `.bin` format for parser input. | +| 2026-03-02 | Appendix A | **PARSER:** Deterministic DLE state machine implemented (`s3_parser.py`). Three states: `IDLE → IN_FRAME → AFTER_DLE`. Replaces heuristic global scanning. Properly handles DLE stuffing (`10 10` → literal `10`). Only complete STX→ETX pairs counted as frames. | +| 2026-03-02 | Appendix A | **VALIDATED:** `raw_bw.bin` yields 7 complete frames via state machine. `raw_s3.bin` contains large structured responses (first frame payload ~3922 bytes). Both files confirmed lossless. BW bare `0x02` pattern confirmed as asymmetric framing (BW sends bare STX, S3 sends DLE+STX). | --- @@ -829,6 +833,99 @@ The `.bin` files produced by `s3_bridge` are **not raw wire bytes**. The logger --- +## Appendix C — Logger & Parser Validation (2026-03-02) + +> Documents the logger integrity verification and parser refactor completed 2026-03-02. Tooling behavior only — not protocol semantics. + +### C.1 Logger Validation + +**Concern:** Earlier sessions noted that the `s3_bridge` logger may have been stripping `0x10` from `DLE ETX` sequences, producing bare `0x03` terminators in the capture file. + +**Resolution:** HxD inspection of a new capture produced by `s3_bridge v0.5.0` confirmed that `10 03` sequences are present intact inside S3→BW record payloads. The `forward_loop` function writes raw bytes to the `.bin` before any sniffer or framing logic runs — there is no ETX stripping in v0.5.0. + +The earlier stripping behavior applied to a previous logger version. v0.5.0 is confirmed lossless with respect to wire bytes. + +**Confirmed wire framing:** +- Frame start: `0x10 0x02` (DLE STX) ✅ +- Frame end: `0x10 0x03` (DLE ETX) ✅ +- DLE stuffing: `0x10 0x10` in payload = literal `0x10` ✅ + +### C.2 Capture Architecture (Current) + +As of 2026-03-02 the capture pipeline produces two flat raw wire dump files per session: + +| File | Contents | +|---|---| +| `raw_s3.bin` | All bytes transmitted by S3 (device → Blastware), in order | +| `raw_bw.bin` | All bytes transmitted by BW (Blastware → device), in order | + +No record headers, no timestamps, no framing logic applied by the dumper. Files are flat concatenations of `serial.read()` chunks. Frame boundaries must be recovered by the parser. + +### C.3 Parser Design — DLE State Machine + +A deterministic state machine replaces all prior heuristic scanning. + +**States:** + +``` +STATE_IDLE — scanning for frame start +STATE_IN_FRAME — consuming payload bytes +STATE_AFTER_DLE — last byte was 0x10, awaiting qualifier +``` + +**Transitions:** + +| Current State | Byte | Action | Next State | +|---|---|---|---| +| IDLE | `10 02` | Begin new frame | IN_FRAME | +| IDLE | any | Discard | IDLE | +| IN_FRAME | `!= 10` | Append to payload | IN_FRAME | +| IN_FRAME | `10` | — | AFTER_DLE | +| AFTER_DLE | `10` | Append literal `0x10` | IN_FRAME | +| AFTER_DLE | `03` | Frame complete, emit | IDLE | +| AFTER_DLE | other | Treat as payload (recovery) | IN_FRAME | + +**Properties:** +- Does not scan globally for `10 02` +- Only complete STX→ETX pairs are emitted as frames +- Incomplete trailing frames at EOF are discarded (expected at capture boundaries) +- DLE stuffing handled correctly + +### C.4 Observed Traffic (Validation Captures) + +**`raw_bw.bin`** (Blastware → S3): +- 7 complete frames via state machine +- Mostly small command/control frames, several zero-length payloads +- Bare `0x02` used as STX (asymmetric — BW does not use DLE STX) +- Contains project metadata strings: `"Standard Recording Setup.set"`, `"Claude test2"`, `"Location #1 - Brians House"` + +**`raw_s3.bin`** (S3 → Blastware): +- First frame payload ~3922 bytes (large structured response) +- Repeated `"Instantel"` / `"MiniMate Plus"` / `"BE18189"` strings throughout +- Multiple medium-length structured frames +- DLE+ETX confirmed intact + +### C.5 Key Lessons + +1. **Global byte counting ≠ frame counting.** `0x10 0x02` appears inside payloads. Only state machine transitions produce valid frame boundaries. +2. **STX count ≠ frame count.** Only STX→ETX pairs within proper state transitions count. +3. **EOF mid-frame is normal.** Capture termination during active traffic produces an incomplete trailing frame. Not an error. +4. **Layer separation.** The parser extracts frames only. Decoding block IDs, validating checksums, and interpreting semantics are responsibilities of a separate protocol decoder layer above it. + +### C.6 Parser Layer Architecture + +``` +raw_s3.bin / raw_bw.bin + ↓ +DLE Frame Parser (s3_parser.py) <- framing only + ↓ +Protocol Decoder (future) <- SUB IDs, block layout, checksums + ↓ +Semantic Interpretation <- settings, events, responses +``` + +--- + *All findings reverse-engineered from live RS-232 bridge captures.* *Cross-referenced from 2026-03-02 with Instantel MiniMate Plus Operator Manual (716U0101 Rev 15).* *This is a living document — append changelog entries and timestamps as new findings are confirmed or corrected.*