Skip to content

fix: NVCM programmed check reads STATUS Done bit, not the auto-boot test - #50

Merged
boringethan merged 2 commits into
nextfrom
fix/44-nvcm-check
Jul 2, 2026
Merged

boringethan merged 2 commits into
nextfrom
fix/44-nvcm-check

Conversation

@boringethan

@boringethan boringethan commented Jul 2, 2026 •

Copy link
Copy Markdown
Contributor

Refs #44

Root cause

_interpret_nvcm_blob (motion_connector.py:551 on next) derived its verdict from the auto-boot test bytes of the OW_FACTORY_NVCM_CHECK blob: boot_0x40_responds == 0 → PROGRAMMED. That signal is unconditionally "programmed": the CrossLink I2C slave config port at 0x40 only becomes active after receiving the activation key, so after a key-less CRESETB release it never ACKs regardless of NVCM state. Every camera with a valid IDCODE therefore reported PROGRAMMED — blank parts included.

This is the exact trap sensor-fw already hit and fixed in its own runtime detector (openmotion-sensor-fw commit c40a6b4, "fix(nvcm): rewrite fpga_detect_nvcm to use Done bit instead of boot test" — hardware-verified there). The app's interpreter was ported from the stale scripts/nvcm_probe.py verdict logic that predates that finding.

Fix

  • New utils/nvcm_verdict.py (pure, Qt-free): verdict now comes from the STATUS register Done bit (bit 8 → blob[8] bit 0, big-endian status bytes), which the blob already carries. The Done fuse is the last step burned during NVCM programming and is what gates auto-boot: Done=1 → PROGRAMMED, Done=0 → BLANK. A failed STATUS read or IDCODE mismatch → INCONCLUSIVE. Detail strings now include the raw STATUS bytes.
  • _NvcmCheckThread passes boot_test=False — the boot probe carries no information and just adds CRESETB cycling per camera.
  • tests/test_nvcm_verdict.py: 16 unit cases, including a regression case built from the real blank-camera blob recorded in the sensor-fw NVCM notebook (STATUS 00 00 02 08, boot test claiming "0x40 gone") — old code returned PROGRAMMED for it, new code returns BLANK — and a sweep proving the verdict is independent of the boot-test bytes.

Companion SDK PR fixing the same verdict logic in the reference script: OpenwaterHealth/openmotion-sdk#118.

Hand-test

On a sensor with known-blank NVCM cameras (e.g. the left module verified all-blank in sensor-fw c40a6b4, minus any cameras burned since):

  1. Sensors page → Check NVCM (all).
  2. Blank cameras must now report BLANK — STATUS Done bit clear (status 00 00 02 08) (previously: PROGRAMMED).
  3. An NVCM-burned camera (e.g. the camera burned via the Flash button + Done-fuse retry) must report PROGRAMMED — STATUS Done bit set.
  4. Unpowered/absent camera slots → NO RESPONSE / INCONCLUSIVE, not PROGRAMMED.
  5. Header line "All 8 cameras PROGRAMMED" should only appear when every camera is Done=1.

Note (pre-existing behavior): the check forces the FPGAs into config mode, so checked cameras need an FPGA reprogram / power-cycle before normal streaming.

🤖 Generated with Claude Code

The Check NVCM sweep reported PROGRAMMED for every camera with a valid
IDCODE (issue #44). The verdict came from the auto-boot test byte
(boot_0x40_responds == 0 -> PROGRAMMED), but the CrossLink I2C config
port at 0x40 only becomes active after receiving the activation key, so
after a key-less CRESETB release it never ACKs regardless of NVCM state
-- blank parts also read as programmed. sensor-fw hit the same trap and
rewrote its detector for exactly this reason (commit c40a6b4).

Interpret the blob via the STATUS register Done bit instead (bit 8 =
blob[8] bit 0, big-endian): the Done fuse is the last step burned during
NVCM programming and is what gates auto-boot. The interpreter moves to
utils/nvcm_verdict.py (pure, Qt-free) with unit tests, including a
regression case built from the real blank-camera blob recorded in the
sensor-fw NVCM notebook. The sweep now passes boot_test=False since the
boot probe carries no information.

Refs #44

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Bench falsification of the first cut (blind test with one known-blank
camera among 16): the SRAM-configuration Done bit (bit 8) reads 0 on
EVERY camera in the probe's ISC flow - the sequence holds the part
unconfigured - so all 16 reported BLANK. The bit that empirically
discriminates is STATUS bit 19 (byte1 & 0x08): set on all 15 programmed
cameras (00 08 02 08), clear on the known blank (00 00 02 08, matching
the sensor-fw notebook's blank blob). Feature row / feabits / NVCM rows
read all-0xFF for both populations in this mode and cannot discriminate.

Refs #44

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@boringethan
boringethan marked this pull request as ready for review July 2, 2026 21:59
@boringethan
boringethan merged commit cb08844 into next Jul 2, 2026
@boringethan
boringethan deleted the fix/44-nvcm-check branch July 2, 2026 22:21
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