Repository navigation
fix: NVCM programmed check reads STATUS Done bit, not the auto-boot test - #50
Merged
Merged
Conversation
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>
This was referenced Jul 2, 2026
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refs #44
Root cause
_interpret_nvcm_blob(motion_connector.py:551onnext) derived its verdict from the auto-boot test bytes of theOW_FACTORY_NVCM_CHECKblob:boot_0x40_responds == 0→ PROGRAMMED. That signal is unconditionally "programmed": the CrossLink I2C slave config port at0x40only 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 stalescripts/nvcm_probe.pyverdict logic that predates that finding.Fix
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._NvcmCheckThreadpassesboot_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 (STATUS00 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):
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