Sensor-fw side of the drip-scan single-frame feature (companion to OpenwaterHealth/openmotion-camera-fpga#8; design spec in that repo at docs/superpowers/specs/2026-07-19-drip-scan-single-frame-design.md §4.4). SDK companion: OpenwaterHealth/openmotion-sdk#167.
Scope:
- New OW_CAMERA subcommand OW_CAMERA_IMAGE_MODE = 0x30 (reserved byte = enable 0/1, data[0] = camera bitmask). Response carries per-camera gap counters.
- Image mode suspends histogram streaming (mutually exclusive), aborts in-flight histogram DMA, and arms repeating 2408-B one-shot DMA per masked camera into the existing receive buffers (cam 1 = spi6_buffer in SRAM4 for BDMA, unchanged).
- Data-paced receive: RxCplt builds the USB envelope in place and forwards on the HISTO endpoint with stream type 0x03 (OW_IMAGE_PACKET), then re-arms the camera's DMA.
- Per-camera ~2 ms line timeout serviced from the main loop: abort + re-arm + gap counter.
- Exit restores histogram arming; the next histogram frame is consumed and discarded firmware-side (FPGA first-frame-garbage caveat from the feature/5 line-readout work).
- Host pytest for wire-format constants + CRC table; HIL suite tests/test_image_mode_hil.py (bench).
Laser per-pulse parameters untouched; sensor retiming + FSIN-rate orchestration are host/SDK-side. FPGA side is sim-complete + Diamond-built (163489 B bitstream, register map v2).
Sensor-fw side of the drip-scan single-frame feature (companion to OpenwaterHealth/openmotion-camera-fpga#8; design spec in that repo at docs/superpowers/specs/2026-07-19-drip-scan-single-frame-design.md §4.4). SDK companion: OpenwaterHealth/openmotion-sdk#167.
Scope:
Laser per-pulse parameters untouched; sensor retiming + FSIN-rate orchestration are host/SDK-side. FPGA side is sim-complete + Diamond-built (163489 B bitstream, register map v2).