Skip to content

G6 v1 panel-protocol compliance: CRC integrity + parity fix#27

Merged
mbreiser merged 6 commits into
mainfrom
crc-integrity
May 24, 2026
Merged

G6 v1 panel-protocol compliance: CRC integrity + parity fix#27
mbreiser merged 6 commits into
mainfrom
crc-integrity

Conversation

@mbreiser
Copy link
Copy Markdown
Contributor

Summary

Brings the MATLAB G6 encoder/reader into v1 panel-protocol spec compliance, mirroring the changes already merged in reiserlab/webDisplayTools (PR commit a348ae1).

  • Header byte 18: CRC-8/AUTOSAR over header bytes 1-17 (was: XOR over all frame data)
  • Per-frame trailer: 2-byte CRC-16/CCITT-FALSE (little-endian) over {FR_magic, frame_index, panel_blocks} of each frame
  • load_pat / load_pat_g6: new 'strict' name-value option — CRC failures throw under strict mode, warn otherwise (UI-tolerant by default)
  • compute_header popcount overflow fix: total_ones was accumulating in uint8, saturating at 255 — broke parity for GS16 panels (~800 ones). Now accumulates in double.
  • Arena ID 4 assigned to G6_3x16_full (already defined in configs/arenas/)
  • g6_encoding_reference.json regenerated; cross-repo byte-identical with webDisplayTools/data/
  • 9 G6 .pat files in patterns/web_generated/ regenerated (matrix expanded from 4 → 9 to cover all 4 registered G6 arenas × both GS modes, plus 1-frame edge case)

Verification

  • addpath(genpath('.')); test_g6_crc() → 11/11 checks pass
  • node tests/verify-pat-crc.js patterns/web_generated/ (from webDisplayTools) → 9/9 G6 files pass strict CRC, 4 G4 skipped
  • PatternPreviewerApp.loadFile(...) on all 9 patterns → zero warnings
  • Cross-repo JSON SHA-256 matches webDisplayTools/data/g6_encoding_reference.json

Migration

Pre-release context: no G6 patterns have ever been displayed on hardware, so this is a one-way migration — old G6 v2 .pat files written before this change are no longer parseable (file-size formula mismatch).

Test plan

  • cd maDisplayTools && matlab -batch "addpath(genpath('.')); test_g6_crc" shows 11/11 PASS
  • node tests/verify-pat-crc.js maDisplayTools/patterns/web_generated/ (from webDisplayTools) shows 9 pass / 0 fail
  • Open one G6 .pat via PatternPreviewerApp GUI — loads with no warnings

🤖 Generated with Claude Code

mbreiser and others added 6 commits May 24, 2026 00:08
bitget returns the input class (uint8), and `total_ones = total_ones +
bitget(...)` accumulated in uint8 saturates at 255. For GS16 panels the
popcount can reach ~800, so the saturation flipped the parity bit for
any panel with >255 ones — caught when MATLAB-encoded GS16 patterns
failed byte-equivalence vs the JS encoder.

Accumulate in double; cast each bitget result to double before adding.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bring the MATLAB G6 encoder/reader into v1 panel-protocol spec compliance.

Algorithms (LUT-driven, persistent caching, universal-check at first use):
- g6/crc8_autosar.m: poly 0x2F, init 0xFF, xorout 0xFF; universal check 0xDF
  over "123456789". Casts to double to avoid uint8 saturation in the LUT-
  index arithmetic (255+1 saturates to 255 otherwise — bit me in testing).
- g6/crc16_ccitt_false.m: poly 0x1021, init 0xFFFF; universal check 0x29B1.

Encoder integration (g6/g6_save_pattern.m):
- Header byte 18 now CRC-8/AUTOSAR over header bytes 1-17 (was: XOR over
  all frame data).
- Each frame ends with a 2-byte CRC-16/CCITT-FALSE trailer (little-endian)
  over {FR_magic, frame_index, panel_blocks} of that frame.
- all_frames preallocated to total_frames_size to avoid O(N^2) growth via
  `[all_frames, ...]` concatenation. Cast to double() to avoid uint8
  saturation on `row_count * length(installed_cols) * block_size`.

Reader integration (maDisplayTools.m::load_pat_g6):
- New 'strict' name-value argument; default false. Three-tier policy:
  UI tolerant warnings (default), CI strict error, firmware fatal (per
  spec; not implemented here).
- V2 header CRC verified (byte 18 over bytes 1-17). V1 unchanged.
- V2 frames: per-frame CRC-16 trailer parsed and verified after panels.
  Gated on header version >= 2; V1 path skips the trailer.
- maDisplayTools.load_pat plumbs varargin through to load_pat_g6.

Old G6 v2 .pat files (no CRC trailer) fail file-size validation under
the new reader — they must be regenerated. Pre-release context: no G6
patterns have ever displayed on hardware, so no backward-compat needed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3 rows × 16 columns = 48 panels — max-density G6 arena (fills the
48-bit panel_mask). Geometry definition already exists at
configs/arenas/G6_3x16_full.yaml; this commit gives it a stable arena_id
so it can appear in pattern file headers.

Mirrored in webDisplayTools/js/arena-configs.js (separate PR).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
g6/test_g6_crc.m — 11 checks: universal vectors (0xDF, 0x29B1 over
"123456789"), CRC-8 protocol-specific vectors from the panel-protocol
spec (2L Oneshot all-zero → 0xC6, 16L Oneshot all-zero → 0x6D), the
canonical CRC-16 frame-header vector, JSON cross-check, plus
round-trip + header/frame corruption tests asserting strict mode
errors and tolerant mode warns.

g6/generate_g6_encoding_reference.m — adds a crc_test_vectors section
(CRC-8 + CRC-16 algorithm params and pinned vectors) and a
canonical_patterns section (G6_2x10 GS2 1-frame checker with SHA-256
of the encoded bytes — the byte-equivalence anchor for MATLAB ↔ JS
encoder regression). The naive `strrep` pretty-printer was replaced
with `jsonencode(... 'PrettyPrint', true)` because the former
corrupted strings containing literal '{' or '}'.

g6/g6_encoding_reference.json — regenerated; SHA-256 matches the
webDisplayTools/data/ mirror.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
All G6 patterns under patterns/web_generated/ regenerated using
webDisplayTools/tests/generate-roundtrip-patterns.js (the canonical
producer for "web_generated" files). New CRC-8 header byte + per-frame
CRC-16 trailer; correct parity bits on every panel block.

Modified (existing files, new format adds +40 bytes per file for the
20-frame patterns: per-frame CRC-16 trailer × 20 frames):
- web_G6_2x10_gs16_square_grating_G6.pat
- web_G6_2x10_gs2_square_grating_G6.pat
- web_G6_2x8of10_gs16_sine_grating_G6.pat
- web_G6_3x12of18_gs16_horiz_grating_G6.pat

Added (matrix expansion — GS2 coverage for partial arenas, full G6_3x16,
1-frame all-zero edge case):
- web_G6_2x10_gs2_blank_G6.pat
- web_G6_2x8of10_gs2_square_grating_G6.pat
- web_G6_3x12of18_gs2_horiz_grating_G6.pat
- web_G6_3x16_full_gs2_square_grating_G6.pat
- web_G6_3x16_full_gs16_sine_grating_G6.pat
- manifest.json (per-file metadata + sha256 from the JS generator)

All 9 G6 files pass strict-mode CRC validation
(`node tests/verify-pat-crc.js patterns/web_generated/`). G4 files not
touched (G4 format predates the CRC scheme).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Codex skill artifact dir (plan reviews, prompts, output JSONL).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@mbreiser mbreiser merged commit 094e961 into main May 24, 2026
@mbreiser mbreiser deleted the crc-integrity branch May 24, 2026 04:27
mbreiser added a commit that referenced this pull request May 24, 2026
Header CRC-8/AUTOSAR + per-frame CRC-16/CCITT-FALSE trailer (per PR #27).
Pre-2026-05-24 G6 v2 files are obsolete and need regeneration. G4 unaffected.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant