fix(protocol): correct A5 frame classification and chunk counter formula
This commit is contained in:
@@ -527,7 +527,7 @@ def classify_frame(frame: S3Frame) -> str:
|
||||
|
||||
Returns one of:
|
||||
"terminator" — page_key == 0x0000
|
||||
"probe_or_strt" — data contains b"STRT" (the initial probe response)
|
||||
"probe_or_strt" — data contains b"STRT\xff\xfe" (the initial probe response)
|
||||
"metadata" — data contains ASCII compliance-config markers
|
||||
"waveform" — predominantly binary (< 20 % printable ASCII)
|
||||
"unknown" — none of the above criteria matched
|
||||
@@ -539,7 +539,7 @@ def classify_frame(frame: S3Frame) -> str:
|
||||
if frame.page_key == 0x0000:
|
||||
return "terminator"
|
||||
data = bytes(frame.data)
|
||||
if b"STRT" in data:
|
||||
if b"STRT\xff\xfe" in data:
|
||||
return "probe_or_strt"
|
||||
if any(m in data for m in _METADATA_FRAME_MARKERS):
|
||||
return "metadata"
|
||||
@@ -677,6 +677,7 @@ def write_blastware_file(
|
||||
term_frame = None
|
||||
|
||||
all_bytes = bytearray()
|
||||
seen_metadata = False
|
||||
|
||||
for fi, frame in enumerate(body_frames):
|
||||
ftype = classify_frame(frame)
|
||||
@@ -686,11 +687,20 @@ def write_blastware_file(
|
||||
# Probe frame: always process regardless of classification.
|
||||
# It holds the STRT record; probe_skip positions us past it.
|
||||
skip = probe_skip
|
||||
elif ftype == "waveform":
|
||||
elif seen_metadata:
|
||||
# Drop all frames that come after the compliance/metadata block.
|
||||
# (e.g. extra waveform chunks fetched after stop_after_metadata)
|
||||
log.debug(
|
||||
"write_blastware_file: frame %d after metadata — skipping", fi
|
||||
)
|
||||
continue
|
||||
elif ftype in ("waveform", "metadata"):
|
||||
skip = 13 if fi == 1 else 12
|
||||
if ftype == "metadata":
|
||||
seen_metadata = True
|
||||
else:
|
||||
# Skip metadata, probe_or_strt, and unknown frames.
|
||||
if b"STRT" in bytes(frame.data):
|
||||
# Skip probe_or_strt and unknown frames.
|
||||
if b"STRT\xff\xfe" in bytes(frame.data):
|
||||
log.warning(
|
||||
"write_blastware_file: frame %d (%s) contains STRT — skipping",
|
||||
fi, ftype,
|
||||
|
||||
@@ -126,10 +126,12 @@ DATA_LENGTHS: dict[int, int] = {
|
||||
_BULK_CHUNK_OFFSET = 0x1004 # offset field for probe + all regular chunk requests ✅
|
||||
_BULK_TERM_OFFSET = 0x005A # offset field for termination request ✅
|
||||
_BULK_COUNTER_STEP = 0x0400 # chunk counter increment per chunk ✅
|
||||
# Chunk counter formula: chunk_num * 0x0400 for ALL chunks including chunk 1.
|
||||
# Earlier captures showed 0x1004 for chunk 1 — that was a Blastware artifact, not a
|
||||
# protocol requirement. Confirmed 2026-04-06: 0x0400 for chunk 1 works; 0x1004
|
||||
# causes a 120-second device timeout. Formula n * 0x0400 is used for all chunks.
|
||||
# Chunk counter formula: key4[2:4] + (chunk_num - 1) * 0x0400
|
||||
# where key4[2:4] is the event's circular-buffer base offset ((key4[2]<<8)|key4[3]).
|
||||
# Earlier captures showed 0x1004 for chunk 1 of key 01110000 — that was a Blastware
|
||||
# artifact. For keys where key4[2:4] != 0x0000 (e.g. key 01111884) the old
|
||||
# "n * 0x0400" formula sends counters from the wrong buffer region and the device
|
||||
# returns data from a different event. Confirmed correct 2026-04-24.
|
||||
|
||||
# Default timeout values (seconds).
|
||||
# MiniMate Plus is a slow device — keep these generous.
|
||||
|
||||
Reference in New Issue
Block a user