diff --git a/docs/instantel_protocol_reference.md b/docs/instantel_protocol_reference.md index f8b70f2..7c25695 100644 --- a/docs/instantel_protocol_reference.md +++ b/docs/instantel_protocol_reference.md @@ -3,6 +3,7 @@ > Reverse-engineered via RS-232 serial bridge sniffing between Blastware software and an Instantel MiniMate Plus seismograph (S/N: BE18189). > All findings derived from live packet capture. No vendor documentation was used. > **Certainty Ratings:** โœ… CONFIRMED | ๐Ÿ”ถ INFERRED | โ“ SPECULATIVE +> Certainty ratings apply only to protocol semantics, not to capture tooling behavior. --- @@ -16,6 +17,18 @@ | 2026-02-26 | ยง10 DLE Stuffing | **UPGRADED:** Section upgraded from โ“ SPECULATIVE to โœ… CONFIRMED. Full stuffing rules and parser state machine documented. | | 2026-02-26 | ยง11 Checksum | **UPDATED:** Frame builder and parser rewritten to handle DLE framing and byte stuffing correctly. | | 2026-02-26 | ยง14 Open Questions | DLE question removed (resolved). Timestamp year question removed (resolved). | +| 2026-02-26 | ยง7.2 Serial Number Response | **CORRECTED:** Trailing bytes are `0x79 0x11` only (2 bytes, not 3). `0x20` was misidentified as a trailing byte โ€” it is the frame checksum. | +| 2026-02-26 | ยง7.2 Serial Number Response | **UPDATED:** Two-unit comparison confirms `0x11` = firmware minor version (S337.**17** โ†’ `0x11` = 17). Byte 0 is unit-specific, derivation unknown. | +| 2026-02-26 | ยง15 Binary Log Format | **NEW:** `.bin` logger format strips DLE from ETX (`0x10 0x03` โ†’ `0x03`). Not raw wire bytes. | +| 2026-02-26 | ยง5.1 Request Commands | **ADDED:** Three new read commands confirmed: SUB `09`, `1A`, `2E`. | +| 2026-02-26 | ยง5.3 Write Commands | **NEW SECTION:** Full write command family documented from compliance setup capture. SUBs `68`โ€“`83`. | +| 2026-02-26 | ยง7.5 Full Waveform Record | **UPDATED:** Project strings field layout fully mapped from write payload diff. Client field confirmed at byte +230 in SUB `71` frame. | +| 2026-02-26 | ยง14 Open Questions | Write commands question resolved. Session `152427` had swapped port labels โ€” superseded by sessions `184518` and `185019`. | +| 2026-02-26 | Global | **CORRECTED:** Firmware version `S338.17` โ†’ `S337.17` everywhere, including hex encoding at config offset `0x34`. | +| 2026-02-26 | ยง3 Payload Structure | **DOWNGRADED:** ADDR field certainty `๐Ÿ”ถ INFERRED` โ†’ `โ“ SPECULATIVE`. Added note that bytes 1โ€“2 purpose is unconfirmed. | +| 2026-02-26 | ยง5.2 Response SUBs | **STRENGTHENED:** `0xFF - SUB` rule wording clarified โ€” high confidence, no counterexample, not yet formally proven. | +| 2026-02-26 | ยง15 โ†’ Appendix A | **RENAMED:** Binary log format section moved to Appendix A with explicit note that it describes tooling behavior, not protocol. | +| 2026-02-26 | Header | **ADDED:** Certainty legend clarification โ€” ratings apply to protocol semantics only, not tooling behavior. | --- @@ -103,12 +116,14 @@ The payload (bytes between DLE+STX and CHECKSUM, after de-stuffing) has consiste |---|---|---|---| | CMD | byte 0 | Command or response code | โœ… CONFIRMED | | DLE | byte 1 | Always `0x10`. Part of address/routing scheme. On wire this is stuffed as `0x10 0x10`. | โœ… CONFIRMED โ€” 2026-02-26 | -| ADDR | byte 2 | Always `0x10`. Device address or bus ID. Also stuffed on wire. | ๐Ÿ”ถ INFERRED | +| ADDR | byte 2 | Always observed as `0x10`. Also stuffed on wire. Purpose unknown โ€” may not be an address. | โ“ SPECULATIVE | | FLAGS | byte 3 | Usually `0x00`. Non-zero values seen in event-keyed requests. | ๐Ÿ”ถ INFERRED | | SUB_CMD | byte 4 | The actual operation being requested. | โœ… CONFIRMED | | OFFSET_HI | byte 5 | High byte of data offset for paged reads. | โœ… CONFIRMED | | OFFSET_LO | byte 6 | Low byte of data offset. | โœ… CONFIRMED | +> โ“ **NOTE on bytes 1โ€“2:** After de-stuffing, bytes 1 and 2 are both `0x10` in every observed frame across all captured sessions and both units. Their semantic meaning is not yet confirmed. No capture has shown either field vary across units, commands, or directions. They may represent routing, bus ID, or fixed header constants โ€” or the field boundaries assumed here may be wrong entirely. + > ๐Ÿ”ถ **NOTE:** Because bytes 1 and 2 are both `0x10`, they appear on the wire as four consecutive `0x10` bytes (`0x10 0x10 0x10 0x10`). This is normal โ€” both are stuffed. Do not mistake them for DLE+STX or DLE+ETX. --- @@ -167,12 +182,15 @@ Step 4 โ€” Device sends actual data payload: | `24` | **WAVEFORM PAGE A?** | Paged waveform read, possibly channel group A. | ๐Ÿ”ถ INFERRED | | `25` | **WAVEFORM PAGE B?** | Paged waveform read, possibly channel group B. | ๐Ÿ”ถ INFERRED | | `1F` | **EVENT ADVANCE / CLOSE** | Sent after waveform download completes. Likely advances internal record pointer. | ๐Ÿ”ถ INFERRED | +| `09` | **UNKNOWN READ A** | Read command, response (`F6`) returns 0xCA (202) bytes. Purpose unknown. | ๐Ÿ”ถ INFERRED | +| `1A` | **CHANNEL SCALING / COMPLIANCE CONFIG READ** | Read command, response (`E5`) returns large block containing IEEE 754 floats and `0x082A` (โ‰ˆ 0.209 in/s trigger threshold candidate). Bidirectional during compliance setup. | ๐Ÿ”ถ INFERRED | +| `2E` | **UNKNOWN READ B** | Read command, response (`D1`) returns 0x1A (26) bytes. Purpose unknown. | ๐Ÿ”ถ INFERRED | All requests use CMD byte `0x02`. All responses use CMD byte `0x10 0x02` (which, after de-stuffing, is just the DLE+CMD combination โ€” see ยง3). ### 5.2 Response SUB Bytes (S3 โ†’ Blastware) -> ๐Ÿ”ถ **INFERRED pattern:** Response SUB = `0xFF - Request SUB`. Verified on all observed pairs. +> ๐Ÿ”ถ **INFERRED pattern:** Response SUB = `0xFF - Request SUB`. Verified on all observed pairs to date โ€” no counterexample has been observed across read commands, write commands, or either unit. Confidence is high but not formally proven across the full command space. | Request SUB | Response SUB | Certainty | |---|---|---| @@ -187,6 +205,43 @@ All requests use CMD byte `0x02`. All responses use CMD byte `0x10 0x02` (which, | `0C` | `F3` | โœ… CONFIRMED | | `5A` | `A5` | โœ… CONFIRMED | | `1F` | `E0` | ๐Ÿ”ถ INFERRED | +| `09` | `F6` | โœ… CONFIRMED | +| `1A` | `E5` | โœ… CONFIRMED | +| `2E` | `D1` | โœ… CONFIRMED | + +--- + +### 5.3 Write Commands (Blastware โ†’ Device) + +> โœ… **CONFIRMED โ€” 2026-02-26** from compliance setup capture (session `185019`). + +Write commands are initiated by Blastware (`BW->S3`) and use SUB bytes in the `0x60`โ€“`0x83` range. The device acknowledges each write with a short response frame containing no data payload. + +**Pattern:** Write SUB = Read SUB + `0x60` (e.g. `0x08` EVENT INDEX READ โ†’ `0x68` EVENT INDEX WRITE). + +| SUB | Name | Description | Response SUB | Certainty | +|---|---|---|---|---| +| `68` | **EVENT INDEX WRITE** | Writes event index block (mirrors SUB `08` read). Contains event count and timestamps. | `97` | โœ… CONFIRMED | +| `69` | **WAVEFORM DATA WRITE** | Writes large waveform/channel data block (0xCA bytes, mirrors SUB `09`). | `96` | โœ… CONFIRMED | +| `71` | **COMPLIANCE / PROJECT STRINGS WRITE** | Writes compliance config and all project string fields. Contains setup name, project, client, operator, sensor location, and extended notes. Also contains channel scaling floats and `0x082A` threshold value. | `8E` | โœ… CONFIRMED | +| `72` | **WRITE CONFIRM A** | Short frame, no data. Likely commit/confirm step after `71`. | `8D` | โœ… CONFIRMED | +| `73` | **WRITE CONFIRM B** | Short frame, no data. | `8C` | โœ… CONFIRMED | +| `74` | **WRITE CONFIRM C** | Short frame, no data. | `8B` | โœ… CONFIRMED | +| `82` | **TRIGGER CONFIG WRITE** | Writes trigger config block (0x1C bytes, mirrors SUB `1C` read). | `7D` | โœ… CONFIRMED | +| `83` | **TRIGGER WRITE CONFIRM** | Short frame, no data. Likely commit step after `82`. | `7C` | โœ… CONFIRMED | + +**Write response SUB pairs** follow the same `0xFF - request` rule: + +| Write SUB | Response SUB | +|---|---| +| `68` | `97` | +| `69` | `96` | +| `71` | `8E` | +| `72` | `8D` | +| `73` | `8C` | +| `74` | `8B` | +| `82` | `7D` | +| `83` | `7C` | --- @@ -237,10 +292,27 @@ Raw payload (after de-stuffing): Data payload = 0x0A bytes: ``` -"BE18189\x00" โ€” 7 ASCII bytes + null terminator -79 11 20 โ€” 3 trailing bytes (HW revision? calibration ID?) โ“ +"BE18189\x00" โ€” 7 ASCII bytes + null terminator (8 bytes) +79 11 โ€” 2 trailing bytes ``` +| Trailing Byte | Value (Unit 1) | Value (Unit 2) | Meaning | Certainty | +|---|---|---|---|---| +| `trail[0]` | `0x79` | `0x70` | Unit-specific โ€” factory calibration ID or HW stamp? | โ“ SPECULATIVE | +| `trail[1]` | `0x11` | `0x11` | Firmware minor version โ€” `0x11` = 17 = `S337.**17**` | โœ… CONFIRMED โ€” 2026-02-26 | + +Two-unit comparison data: +``` +Unit 1: serial="BE18189" trail=79 11 firmware=S337.17 +Unit 2: serial="BE11529" trail=70 11 firmware=S337.17 +``` + +> โœ… **2026-02-26 โ€” CORRECTED:** Previously documented as `79 11 20` (3 bytes). `0x20` is the **frame checksum**, not payload data. Actual data block is exactly 10 bytes (`0x0A`). + +> โœ… **2026-02-26 โ€” CONFIRMED:** `trail[1]` = firmware minor version. Both units share firmware `S337.17` โ†’ minor = 17 = `0x11`. Will change if firmware differs between units. + +> โ“ **Still unknown:** `trail[0]` is unit-specific. Does not derive from serial string via sum, XOR, or modulo. Possibly written at factory calibration. Needs a third unit or write-command capture to determine. + ### 7.3 Full Config Response (SUB FE) โ€” 0x98 bytes | Offset | Raw | Decoded | Certainty | @@ -251,7 +323,7 @@ Data payload = 0x0A bytes: | 0x14 | `3F 80 00 00` | IEEE 754 float = **1.0** (Tran scale factor) | ๐Ÿ”ถ INFERRED | | 0x18 | `41 00 00 00` | IEEE 754 float = **8.0** (unknown โ€” MicL range?) | ๐Ÿ”ถ INFERRED | | 0x1C | `3F 80 00 00` ร—6 | IEEE 754 float = **1.0** ร—6 (remaining channel scales) | ๐Ÿ”ถ INFERRED | -| 0x34 | `53 33 33 38 2E 31 37 00` | `"S338.17\x00"` โ€” Firmware version | โœ… CONFIRMED | +| 0x34 | `53 33 33 37 2E 31 37 00` | `"S337.17\x00"` โ€” Firmware version | โœ… CONFIRMED | | 0x3C | `31 30 2E 37 32 00` | `"10.72\x00"` โ€” DSP / secondary firmware version | โœ… CONFIRMED | | 0x44 | `49 6E 73 74 61 6E 74 65 6C...` | `"Instantel"` โ€” Manufacturer (repeated) | โœ… CONFIRMED | | 0x6D | `4D 69 6E 69 4D 61 74 65 20 50 6C 75 73` | `"MiniMate Plus"` โ€” Model name | โœ… CONFIRMED | @@ -269,6 +341,23 @@ Offset 0x50: 10 02 FF DC โ€” Sub-block pointer or data segment header ### 7.5 Full Waveform Record (SUB F3) โ€” 0xD2 bytes ร— 2 pages +> โœ… **2026-02-26 โ€” UPDATED:** Project strings field layout confirmed by diffing compliance setup write payload (SUB `71`). Client field change `"Hello Claude"` โ†’ `"Claude test2"` isolated exact byte position. + +**Project strings field layout** (confirmed from SUB `71` write frame, offset +230 from frame start): + +``` +Offset Field label (null-padded, ~16 bytes) Field value (null-padded, ~32 bytes) +------ ------------------------------------ ------------------------------------ ++0x00 "Standard Recording Setup" โ† setup name (no label) ++0x28 "Project:" project description string ++0x50 "Client:" client name string โ† confirmed at +230 ++0x78 "User Name:" operator name string ++0xA0 "Seis Loc:" sensor location string ++0xC8 "Extended Notes" notes string +``` + +> ๐Ÿ”ถ Offsets are approximate โ€” exact byte boundaries need one more targeted capture with a known-length string change to pin down padding rules. + Confirmed ASCII strings extracted from payload: ``` @@ -514,7 +603,7 @@ Build in this order โ€” each step is independently testable: | Manufacturer | Instantel | | Model | MiniMate Plus | | Serial Number | BE18189 | -| Firmware | S338.17 | +| Firmware | S337.17 | | DSP / Secondary FW | 10.72 | | Channels | Tran, Vert, Long, MicL (4 channels) | | Sample Rate | ~1024 sps (๐Ÿ”ถ INFERRED) | @@ -523,15 +612,41 @@ Build in this order โ€” each step is independently testable: --- +--- + +## Appendix A โ€” s3_bridge Capture Format +> โœ… **CONFIRMED โ€” 2026-02-26** + +> โš ๏ธ **This behavior is not part of the Instantel protocol. It is an artifact of the bridge logger implementation.** + +The `.bin` files produced by `s3_bridge` are **not raw wire bytes**. The logger makes one modification: + +| Wire sequence | In .bin file | Notes | +|---|---|---| +| `0x10 0x03` (DLE+ETX) | `0x03` | DLE stripped from end-of-frame marker | +| All other bytes | Unchanged | ACK, DLE+STX, stuffed payload, checksum all preserved verbatim | + +**Practical impact for parsing `.bin` files:** +- Frame end: scan for bare `0x03` (not `0x10 0x03`) +- Checksum: the byte immediately before the bare `0x03` is the checksum +- Everything else (ACK detection, DLE+STX, payload de-stuffing) works as documented in ยง10 + +> โš ๏ธ This means checksums cannot be verified on frames where the stuffed payload ends in `0x10` โ€” that trailing `0x10` would normally be the DLE prefix of ETX, but the logger strips it, making the frame boundary ambiguous in that edge case. In practice this has not been observed in captured data. + +--- + ## 14. Open Questions / Still Needs Cracking | Question | Priority | Added | |---|---|---| | Byte at timestamp offset 3 โ€” hours, minutes, or padding? | MEDIUM | 2026-02-26 | -| Meaning of `79 11 20` trailing bytes in serial number response | MEDIUM | 2026-02-26 | +| `trail[0]` in serial number response โ€” unit-specific byte, derivation unknown. `trail[1]` resolved as firmware minor version. | MEDIUM | 2026-02-26 | | Full channel ID mapping in SUB `5A` stream (01/02/03/04 โ†’ which sensor?) | MEDIUM | 2026-02-26 | -| Write / set commands for device configuration | MEDIUM | 2026-02-26 | -| Full trigger configuration field mapping (SUB `1C` response) | LOW | 2026-02-26 | +| Exact byte boundaries of project string fields in SUB `71` write frame โ€” padding rules unconfirmed | MEDIUM | 2026-02-26 | +| Purpose of SUB `09` / response `F6` โ€” 202-byte read block | MEDIUM | 2026-02-26 | +| Purpose of SUB `2E` / response `D1` โ€” 26-byte read block | MEDIUM | 2026-02-26 | +| Full field mapping of SUB `1A` / response `E5` โ€” channel scaling / compliance config block | MEDIUM | 2026-02-26 | +| Full trigger configuration field mapping (SUB `1C` / write `82`) | LOW | 2026-02-26 | | Whether SUB `24`/`25` are distinct from SUB `5A` or redundant | LOW | 2026-02-26 | | Meaning of `0x07 E7` field in config block | LOW | 2026-02-26 | | MicL channel units โ€” PSI, dB linear, or dB(L)? | LOW | 2026-02-26 |