Files
seismo-relay/docs/instantel_protocol_reference.md

17 KiB
Raw Blame History

Instantel MiniMate Plus — Blastware RS-232 Protocol Reference v0.1.0

"The Rosetta Stone"

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


1. Physical Layer

Parameter Value Certainty
Interface RS-232 serial CONFIRMED
Baud rate 38400 CONFIRMED (from bridge log header)
Data bits 8 CONFIRMED (standard for this baud/era)
Parity None 🔶 INFERRED (no parity errors observed)
Stop bits 1 🔶 INFERRED (standard assumption)
Flow control None (no RTS/CTS activity) 🔶 INFERRED

2. Frame Structure

Every message follows this structure:

[ACK] [STX] [PAYLOAD...] [CHECKSUM] [ETX]
 0x41  0x02   N bytes       1 byte    0x03

Byte Definitions

Byte Value Meaning Certainty
ACK 0x41 (ASCII 'A') Acknowledgment / ready token. Always sent as a standalone byte before a frame. Both sides send it. CONFIRMED
STX 0x02 Start of frame CONFIRMED
ETX 0x03 End of frame CONFIRMED
CHECKSUM 1 byte 8-bit sum of all payload bytes between STX and CHECKSUM, modulo 256 CONFIRMED (verified on multiple frames)

Important Notes

  • The 0x41 ACK byte always arrives in a separate read() call before the frame due to RS-232 inter-byte timing at 38400 baud.
  • Your frame parser must buffer until ETX 0x03 is received — do not treat each read() as a complete frame.
  • The 0x41 and 0x02 are not part of the checksum calculation. Only bytes after STX and before CHECKSUM are summed.

Checksum Verification Example

Frame:   02 10 10 00 5B 00 00 00 00 00 00 00 00 00 00 00 00 00 6B 03
Payload: 10+10+00+5B+00+00+00+00+00+00+00+00+00+00+00+00+00 = 0x6B ✅
Frame:   10 02 00 10 10 A4 00 00 00 00 00 00 30 00 00 00 00 00 00 E4 03
Payload: 10+02+00+10+10+A4+00+00+00+00+00+00+30+00+00+00+00+00+00 = 0xE4 ✅

3. Payload Structure

The payload (bytes between STX 0x02 and CHECKSUM) has consistent internal structure:

[CMD] [??] [ADDR] [FLAGS] [SUB_CMD] [OFFSET_HI] [OFFSET_LO] [PARAMS × N bytes]
Field Position Notes Certainty
CMD byte 0 Command or response code CONFIRMED
?? byte 1 Always 0x10 in most frames. Possibly device class or protocol version 🔶 INFERRED
ADDR byte 2 Always 0x10. Possibly device address on bus 🔶 INFERRED
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

4. Communication Pattern

4.1 ACK Handshake (Every Transaction)

Side A  →  0x41                    (ACK: "I'm ready / got your last frame")
Side A  →  02 [payload] [chk] 03   (actual frame)
Side B  →  0x41                    (ACK)
Side B  →  02 [payload] [chk] 03   (response frame)

4.2 Two-Step Paged Read Pattern

All data reads use a two-step length-then-data pattern:

Step 1 — Ask how much data exists:
  BW  → 0x41
  BW  → 02 [CMD] 10 10 00 [SUB] 00 00 [00 00 ...] [chk] 03   (offset = 0)

Step 2 — Device replies with total length:
  S3  → 0x41
  S3  → 02 [RSP] 00 10 10 [SUB] 00 00 00 00 00 00 [LEN_HI] [LEN_LO] ... [chk] 03

Step 3 — Request data at that length as offset:
  BW  → 0x41
  BW  → 02 [CMD] 10 10 00 [SUB] 00 00 [LEN_HI] [LEN_LO] [00 ...] [chk] 03

Step 4 — Device sends actual data payload:
  S3  → 0x41
  S3  → 02 [RSP] 00 10 10 [SUB] 00 00 [LEN_HI] [LEN_LO] ... [DATA...] [chk] 03

This two-step is used for every data command. It is not optional.


5. Command Reference Table

5.1 Request Commands (Blastware → S3)

CMD Byte SUB Byte Name Description Certainty
02 5B POLL / KEEPALIVE Sent continuously. Requests device identity/status. CONFIRMED
02 15 SERIAL NUMBER REQUEST Requests device serial number. CONFIRMED
02 01 FULL CONFIG READ Requests complete device configuration block (~0x98 bytes). Contains firmware version, model, serial, channel config, scaling. CONFIRMED
02 08 EVENT INDEX READ Requests the event record index (0x58 bytes). Contains event count and record pointers. CONFIRMED
02 06 CHANNEL CONFIG READ Requests channel configuration block (0x24 bytes). CONFIRMED
02 1C TRIGGER CONFIG READ Requests trigger settings block (0x2C bytes). CONFIRMED
02 1E EVENT HEADER READ Reads event header by index. Contains timestamp and sample rate info. CONFIRMED
02 0A WAVEFORM HEADER READ Reads waveform header keyed by timestamp (0x30 bytes/page). CONFIRMED
02 0C FULL WAVEFORM RECORD Downloads complete waveform record (0xD2 bytes/page). Contains project strings, PPV floats, channel labels. CONFIRMED
02 5A BULK WAVEFORM STREAM Initiates bulk download of raw ADC sample data. Keyed by timestamp. Large multi-page transfer. CONFIRMED
02 24 WAVEFORM PAGE A? Paged waveform read, channel group A. 🔶 INFERRED
02 25 WAVEFORM PAGE B? Paged waveform read, channel group B. 🔶 INFERRED
02 1F EVENT ADVANCE / ACK Sent after waveform download completes. Possibly advances record pointer or closes event. 🔶 INFERRED

5.2 Response Commands (S3 → Blastware)

Responses use the bitwise complement of the request CMD byte. Pattern: CMD + RSP = 0xFF (approximately). More precisely, response bytes observed:

Request CMD Response CMD Notes Certainty
02 + 5B 10 02 + A4 Poll response CONFIRMED
02 + 15 10 02 + EA Serial number response CONFIRMED
02 + 01 10 02 + FE Full config response CONFIRMED
02 + 08 10 02 + F7 Event index response CONFIRMED
02 + 06 10 02 + F9 Channel config response CONFIRMED
02 + 1C 10 02 + E3 Trigger config response CONFIRMED
02 + 1E 10 02 + E1 Event header response CONFIRMED
02 + 0A 10 02 + F5 Waveform header response CONFIRMED
02 + 0C 10 02 + F3 Full waveform record response CONFIRMED
02 + 5A 10 02 + A5 Bulk waveform stream response CONFIRMED
02 + 1F 10 02 + E0 Event advance response 🔶 INFERRED

🔶 INFERRED pattern: Response SUB byte appears to be (0xFF - request SUB). E.g., 0xFF - 0x5B = 0xA4. This holds for all observed pairs and can be used to predict unknown response codes.


6. Session Startup Sequence

1.  Device powers on / resets
2.  S3  →  "Operating System"  (raw ASCII string, no frame, no ACK)
3.  BW  →  0x41 + POLL (CMD 5B)
4.  S3  →  0x41 + POLL RESPONSE (CMD A4, length=0x30)
5.  BW  →  0x41 + POLL (CMD 5B, offset=0x30)
6.  S3  →  0x41 + POLL RESPONSE with data: "Instantel" + "MiniMate Plus"
7.  [Poll loop repeats 3-5× during init]
8.  BW issues CMD 06  → channel config
9.  BW issues CMD 15  → serial number
10. BW issues CMD 01  → full config block
11. BW issues CMD 08  → event index
12. BW issues CMD 1E  → first event header
13. BW issues CMD 0A  → waveform header (timestamp-keyed)
14. BW issues CMD 0C  → full waveform record download
15. BW issues CMD 1F  → advance to next event
16. [Repeat 12-15 for each stored event]
17. BW issues CMD 5A  → bulk raw waveform stream
18. Poll loop resumes (CMD 5B keepalive every ~80ms)

7. Known Data Payloads

7.1 Poll Response (CMD A4) — Device Identity Block

Triggered by two-step read with SUB 5B.
Data payload (0x30 bytes) contains:

Offset 0x00:  0x08           — string length prefix
Offset 0x01:  "Instantel"    — manufacturer name (null-padded to 20 bytes)
Offset 0x15:  "MiniMate Plus" — model name (null-padded to 20 bytes)

Raw example:

00 00 00 08 49 6E 73 74 61 6E 74 65 6C 00 00 00 00 00 00 00 00 00 00 00 00 00
4D 69 6E 69 4D 61 74 65 20 50 6C 75 73 00 00 00 00 00 00 00 00 00

7.2 Serial Number Response (CMD EA)

Data payload (0x0A bytes):

"BE18189"  (7 ASCII bytes, null-terminated)
79 11 20   (3 trailing bytes — purpose unknown) ❓ SPECULATIVE: possibly manufacture date or calibration ID

7.3 Full Config Response (CMD FE) — 0x98 bytes

This is the richest single payload. Confirmed fields:

Offset 0x00:  "BE18189\x00"   — Serial number
Offset 0x08:  79 11           — Unknown (hardware revision?) ❓
Offset 0x0A:  00 01           — Unknown flags
Offset 0x0C:  10 02 9C 00     — Sub-block pointer or version tag
Offset 0x14:  3F 80 00 00     — IEEE 754 float = 1.0  (channel scale factor, Tran)
Offset 0x18:  41 00 00 00     — IEEE 754 float = 8.0  (channel scale factor, unknown)
Offset 0x1C:  3F 80 00 00 ×6  — IEEE 754 float = 1.0 each (remaining channel scales)
Offset 0x34:  "S338.17\x00"   — Firmware version string
Offset 0x3C:  "10.72\x00"     — Secondary firmware/DSP version
Offset 0x42:  07 E7           — 0x07E7 = 2023 decimal? Year field ❓
Offset 0x44:  "Instantel\x00" — Manufacturer (repeated)
Offset 0x60:  "Instantel\x00" — Manufacturer (second copy)
Offset 0x6D:  "MiniMate Plus" — Model name

7.4 Event Index Response (CMD F7) — 0x58 bytes

Offset 0x00:  00 58 09        — Total records or index size ❓
Offset 0x03:  00 00 00 01     — Possibly record count = 1 ❓
Offset 0x07:  01 07 CB 00 06 1E  — Timestamp 1 (see Section 8)
Offset 0x0D:  01 07 CB 00 14 00  — Timestamp 2
Offset 0x13:  00 00 00 17 3B    — Unknown ❓
...
Offset 0x50:  10 02 FF DC     — Sub-block pointer ❓

7.5 Full Waveform Record (CMD F3) — 0xD2 bytes × 2 pages

Contains all metadata for a stored blast event. Confirmed ASCII strings:

"Project:"                    — label
"I-70 at SR 51-75978 - Loc 1 - 4256 SR51 "  — project description
"BE18189"                     — serial number
"Histogram"                   — record type label
"Tran"                        — Transverse channel label
"Vert"                        — Vertical channel label
"Long"                        — Longitudinal channel label
"MicL"                        — Microphone / air overpressure channel label

Peak values as IEEE 754 big-endian floats (event 1):

Tran:  3D BB 45 7A  =  0.0916 in/s  (or mm/s depending on unit config)
Vert:  3D B9 56 E1  =  0.0907 in/s
Long:  3D 75 C2 7C  =  0.0605 in/s
MicL:  39 BE 18 B8  =  0.000145     (PSI or linear dB) ❓ units unconfirmed

Peak values (event 2):

Tran:  3D 56 CB B9  =  0.0521 in/s
Vert:  3C F5 C2 7C  =  0.0300 in/s
Long:  3C F5 C2 7C  =  0.0300 in/s
MicL:  39 64 1D AA  =  0.0000875

7.6 Bulk Waveform Stream (CMD A5) — Raw ADC Sample Records

Each repeating sample record structure (🔶 INFERRED):

[CH_ID] [S0_HI] [S0_LO] [S1_HI] [S1_LO] ... [S8_HI] [S8_LO] [00 00] [01] [FLOAT_HI] [FLOAT_MID] [FLOAT_LO]
  01      00      0A      00       0B      ...                                 43          xx           xx
  • CH_ID — Channel identifier (01 = Tran, 02 = Vert, etc.) 🔶 INFERRED
  • 9× signed 16-bit big-endian ADC samples (~0x000A = baseline noise)
  • Trailing IEEE 754 float — appears to be the peak value for this sample window
  • 0x43 prefix on float = value in range 130260 (scaled mm/s or in/s ×1000)

Sample record appears to be fixed width. At 1024 sps, 9 samples ≈ 8.8ms per record. SPECULATIVE — sample rate unconfirmed from this data alone.


8. Timestamp Format

Timestamps appear in event headers and waveform keys. Observed example:

01 07 CB 00 06 1E

Best guess decode (🔶 INFERRED):

01        — record type / validity flag?
07 CB     — 0x07CB = 1995  ← suspicious, may be a different epoch or BCD
00        — padding?
06        — month (June)
1E        — day (30)

SPECULATIVE: The year 0x07CB = 1995 seems wrong for modern equipment. Possible interpretations:

  • BCD encoded: 07 CB → not valid BCD
  • Epoch offset from some base year
  • Or the full timestamp uses more bytes and the year field is elsewhere

This needs more capture samples with known event dates to crack definitively.


9. Out-of-Band / Non-Frame Messages

Some messages arrive as raw ASCII with no framing at all:

Message Direction Trigger Certainty
"Operating System" S3 → BW Device boot/reset/UART init CONFIRMED

These raw ASCII bursts indicate the device's firmware is printing a boot string to the UART before switching to binary protocol mode. Your implementation should handle these gracefully — ignore any non-0x02 STX bytes during the connection phase until the poll handshake succeeds.


10. Byte Escape / Stuffing

SPECULATIVE / UNKNOWN

The payload bytes 0x02 and 0x03 (STX/ETX) appear naturally in data payloads. It is not yet confirmed whether the protocol uses any byte stuffing or escaping to handle these collisions. In many embedded protocols these are escaped as 0x10 0x02 and 0x10 0x03 (DLE stuffing). The byte 0x10 appears frequently in payloads and may be a DLE (Data Link Escape) byte.

Recommendation: When building the frame parser, watch for 0x10 preceding 0x02 or 0x03 inside a frame — this may indicate DLE stuffing is in use.


11. Checksum Reference Implementation

def calc_checksum(payload: bytes) -> int:
    """
    8-bit sum of all payload bytes (between STX and CHKSUM), modulo 256.
    Do NOT include STX (0x02), ACK (0x41), CHKSUM, or ETX (0x03).
    """
    return sum(payload) & 0xFF

def build_frame(payload: bytes) -> bytes:
    """Build a complete frame: ACK + STX + payload + checksum + ETX"""
    chk = calc_checksum(payload)
    return bytes([0x41, 0x02]) + payload + bytes([chk, 0x03])

def parse_frame(raw: bytes) -> bytes | None:
    """
    Extract and validate payload from a raw frame.
    raw should start at STX (0x02) — strip leading 0x41 ACK before calling.
    Returns payload bytes if checksum valid, None otherwise.
    """
    if raw[0] != 0x02 or raw[-1] != 0x03:
        return None
    payload = raw[1:-2]
    chk = raw[-2]
    if calc_checksum(payload) != chk:
        return None
    return payload

Build in this order — each step is independently testable:

  1. Serial framer — buffered reader that accumulates bytes until ETX 0x03, strips ACK, validates checksum
  2. connect(port, baud=38400) — open port, wait for boot ASCII, send first POLL
  3. identify() — CMD 5B two-step read → returns manufacturer, model strings
  4. get_serial() — CMD 15 two-step read → returns serial number string
  5. get_config() — CMD 01 two-step read → returns full config dict (firmware, scaling, etc.)
  6. get_event_count() — CMD 08 two-step read → returns number of stored events
  7. get_event_header(index) — CMD 1E read → returns timestamp, sample rate
  8. get_event_record(timestamp) — CMD 0C paginated read → returns PPV dict per channel
  9. download_waveform(timestamp) — CMD 5A bulk stream → returns raw ADC arrays per channel
  10. set_*() write commands — not yet captured, requires additional sniffing

13. Device Under Test

Field Value
Manufacturer Instantel
Model MiniMate Plus
Serial Number BE18189
Firmware S338.17
DSP/Secondary FW 10.72
Channels Tran, Vert, Long, MicL (4 channels)
Sample Rate ~1024 sps ( INFERRED)
Bridge Setup COM5 (Blastware) ↔ COM4 (Device), 38400 baud

14. Open Questions / Still Needs Cracking

Question Priority
Exact timestamp encoding (year field especially) HIGH
Whether DLE 0x10 byte stuffing is used for STX/ETX in payload HIGH
Meaning of 79 11 bytes following serial number MEDIUM
Write/set commands for device configuration MEDIUM
Channel ID mapping in CMD 5A stream (which byte = which sensor) MEDIUM
Meaning of 0x07 E7 field in config block LOW
Full trigger configuration field mapping LOW
Whether CMD 24/CMD 25 are distinct from CMD 5A or redundant LOW

Document generated from live RS-232 bridge captures. All findings are reverse-engineered. No Instantel proprietary documentation was referenced.