fix: update STRT parsing to extract additional bytes for total_samples and pretrig_samples
This commit is contained in:
@@ -171,25 +171,39 @@ the `b'STRT'` magic bytes:
|
|||||||
```
|
```
|
||||||
+0..3 b'STRT' magic
|
+0..3 b'STRT' magic
|
||||||
+4..5 flags 0xFF 0xFE (single-shot) or 0xFF 0xFD (continuous)
|
+4..5 flags 0xFF 0xFE (single-shot) or 0xFF 0xFD (continuous)
|
||||||
+6..9 key4 4-byte event key
|
+6..9 next_key4 ← key of the NEXT stored event (NOT the current event) ← confirmed 2026-04-14
|
||||||
+10..13 prev_key4
|
+10..13 prev_key4 ← key of the PREVIOUS stored event ← confirmed 2026-04-14
|
||||||
+14..15 uint16 BE total_samples (full event sample-set count) ← confirmed 4-9-26
|
+14..15 UNKNOWN (values seen: 0xDA63=55907, 0xF38F=62351, 0x5685=22149) — NOT total_samples
|
||||||
+16..17 uint16 BE pretrig_samples (pre-trigger sample-set count)
|
+16..17 UNKNOWN (values seen: 0x0122=290, 0x011A=282, 0x00FA=250) — NOT pretrig_samples
|
||||||
+18 uint8 record-MODE byte — NOT rectime in seconds
|
+18 uint8 record-MODE byte — NOT rectime in seconds
|
||||||
+19..20 typically 0x00 0x00
|
+19..20 0x00 0x00
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**CONFIRMED field values (2026-04-14) from 3 desk-thump events, firmware S338.17:**
|
||||||
|
|
||||||
|
| Field | What it is | Confirmed |
|
||||||
|
|---|---|---|
|
||||||
|
| +4..5 | 0xFFFE single-shot / 0xFFFD continuous | ✅ |
|
||||||
|
| +6..9 | next_event_key (NOT current) | ✅ 3 events |
|
||||||
|
| +10..13 | prev_event_key | ✅ 3 events |
|
||||||
|
| +18 | mode byte: 0x46 ('F') = single-shot, 0x0E = continuous | ✅ |
|
||||||
|
|
||||||
|
**UNCONFIRMED — total_samples and pretrig_samples locations unknown:**
|
||||||
|
The prior documented offsets (+14..15 for total_samples, +16..17 for pretrig_samples) were
|
||||||
|
WRONG — confirmed by cross-checking STRT-derived rectime against compliance record_time
|
||||||
|
(4-14-26): all 3 events give STRT-derived rectime of 21–61 s vs actual 3.0 s (ratio 7–20×).
|
||||||
|
The "confirmed 4-9-26" note in prior versions was incorrect.
|
||||||
|
|
||||||
|
The true offsets for total_samples and pretrig_samples within STRT have not been located.
|
||||||
|
**Until they are found, `_decode_a5_waveform` relies on the compliance-config cross-check
|
||||||
|
fallback for all total_samples and pretrig_samples values.**
|
||||||
|
|
||||||
**CRITICAL — strt[18] is a record-mode byte, NOT rectime_seconds (confirmed 2026-04-14):**
|
**CRITICAL — strt[18] is a record-mode byte, NOT rectime_seconds (confirmed 2026-04-14):**
|
||||||
Analysis of 15 distinct STRT records across the 4-9-26 ACH capture shows:
|
Analysis of 15 distinct STRT records across the 4-9-26 ACH capture shows:
|
||||||
- `flags=0xFFFE` (single-shot) → `strt[18] = 0x46` ('F') for EVERY event regardless of duration
|
- `flags=0xFFFE` (single-shot) → `strt[18] = 0x46` ('F') for EVERY event regardless of duration
|
||||||
- `flags=0xFFFD` (continuous) → `strt[18] = 0x0E` for EVERY event regardless of duration
|
- `flags=0xFFFD` (continuous) → `strt[18] = 0x0E` for EVERY event regardless of duration
|
||||||
|
|
||||||
The actual record duration (post-trigger seconds) must be computed as:
|
Do NOT use `strt[18]` for rectime.
|
||||||
```python
|
|
||||||
rectime_seconds = int(round((total_samples - pretrig_samples) / sample_rate))
|
|
||||||
```
|
|
||||||
`_decode_a5_waveform` uses `sample_rate=1024` as a default; the server overrides with
|
|
||||||
`compliance_config.sample_rate` when available. Do NOT use `strt[18]` for rectime.
|
|
||||||
|
|
||||||
**Pre-trigger time is separate from record_time (confirmed 2026-04-14):**
|
**Pre-trigger time is separate from record_time (confirmed 2026-04-14):**
|
||||||
Blastware documentation states: "The default Time Scale is -0.25 second to 1 second — this
|
Blastware documentation states: "The default Time Scale is -0.25 second to 1 second — this
|
||||||
@@ -197,17 +211,17 @@ negative number accounts for the pre-trigger set for compliance monitoring." Th
|
|||||||
- `record_time` (3.0 s) is POST-TRIGGER duration only
|
- `record_time` (3.0 s) is POST-TRIGGER duration only
|
||||||
- Pre-trigger = 0.25 s = 256 samples at 1024 sps (compliance monitoring standard default)
|
- Pre-trigger = 0.25 s = 256 samples at 1024 sps (compliance monitoring standard default)
|
||||||
- The pre-trigger field has NOT yet been located in the raw compliance config bytes
|
- The pre-trigger field has NOT yet been located in the raw compliance config bytes
|
||||||
- When STRT layout is invalid, `_decode_a5_waveform` falls back to pretrig = 0.25 × sr
|
- `_decode_a5_waveform` falls back to pretrig = 0.25 × sr from compliance standard
|
||||||
- TODO: locate pretrig_time offset in ComplianceConfig — search around anchor or channel blocks
|
- TODO: locate pretrig_time offset in ComplianceConfig — search around anchor or channel blocks
|
||||||
|
|
||||||
The device bulk-streams zero-padded frames BEYOND the configured record window. The
|
The device bulk-streams zero-padded frames BEYOND the configured record window. The
|
||||||
viewer clips `displayCount = total_samples = pretrig + post_trig` to exclude this padding.
|
viewer clips `displayCount = total_samples = pretrig + post_trig` to exclude this padding.
|
||||||
|
|
||||||
**Sanity check — pretrig_samples must be less than total_samples:**
|
**Validity checks in `_decode_a5_waveform`:**
|
||||||
If `pretrig_samples >= total_samples` the STRT parse is invalid. Possible causes:
|
Check 1: `pretrig_samples >= total_samples` → invalid (original check).
|
||||||
DLE-stuffed `0x10` byte within prev_key4 or key4 shifted field offsets, or a different
|
Check 2: STRT-derived rectime differs from `compliance_config.record_time` by more than 2×
|
||||||
STRT record variant. `_decode_a5_waveform` logs `raw strt[0:21]` at WARNING level and
|
→ invalid. Both failures fall back to the compliance-config derived values.
|
||||||
clamps `pretrig_samples = 0` so the viewer renders (showing the full waveform from t=0).
|
`_decode_a5_waveform` logs `raw strt[0:21]` at WARNING level on any failure.
|
||||||
Observed once (2026-04-14) with `strt[16:18] = 0x41 0x01` → pretrig=16641 (impossible).
|
Observed once (2026-04-14) with `strt[16:18] = 0x41 0x01` → pretrig=16641 (impossible).
|
||||||
Root cause not yet identified — capture the warning log hex dump to diagnose.
|
Root cause not yet identified — capture the warning log hex dump to diagnose.
|
||||||
|
|
||||||
|
|||||||
@@ -1389,11 +1389,18 @@ def _decode_a5_waveform(
|
|||||||
#
|
#
|
||||||
# NOTE: strt[8:10] is the LOWER 2 bytes of key4, NOT total_samples.
|
# NOTE: strt[8:10] is the LOWER 2 bytes of key4, NOT total_samples.
|
||||||
# Confirmed from raw_rx capture (4-9-26): strt[14:16] = total_samples. ✅
|
# Confirmed from raw_rx capture (4-9-26): strt[14:16] = total_samples. ✅
|
||||||
strt = w0[strt_pos : strt_pos + 21]
|
# Extract 32 bytes so we can see past the first 21 — the true total_samples
|
||||||
|
# and pretrig_samples offsets have not yet been confirmed and may be > +20.
|
||||||
|
strt = w0[strt_pos : strt_pos + 32]
|
||||||
if len(strt) < 21:
|
if len(strt) < 21:
|
||||||
log.warning("_decode_a5_waveform: STRT record truncated (%dB)", len(strt))
|
log.warning("_decode_a5_waveform: STRT record truncated (%dB)", len(strt))
|
||||||
return
|
return
|
||||||
|
|
||||||
|
log.info(
|
||||||
|
"_decode_a5_waveform: STRT raw[0:32]: %s",
|
||||||
|
strt[:32].hex(' '),
|
||||||
|
)
|
||||||
|
|
||||||
total_samples = struct.unpack_from(">H", strt, 14)[0]
|
total_samples = struct.unpack_from(">H", strt, 14)[0]
|
||||||
pretrig_samples = struct.unpack_from(">H", strt, 16)[0]
|
pretrig_samples = struct.unpack_from(">H", strt, 16)[0]
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user