feat(seq): hardware-sequencer engine core (native-tested, not yet wired)#580
Open
hongquanli wants to merge 8 commits into
Open
feat(seq): hardware-sequencer engine core (native-tested, not yet wired)#580hongquanli wants to merge 8 commits into
hongquanli wants to merge 8 commits into
Conversation
Phase A Task A1 of the firmware-v2 plan (AI-docs 2026-07-04-firmware-v2-plan.md). Pure C++11, no Arduino deps; structs are the future SEQ_UPLOAD_PROGRAM wire format. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…lock tests Phase A Task A2: SeqHal + ExposurePlan (µs-timestamped edges owned by the HAL), FakeHal scripted test harness, engine state machine passing single-frame and piezo-settle scenarios. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Phase A Task A3. Engine already used the explicit settle_armed_ latch the plan's refactor step targets; tests lock the behavior in. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…-channel z offsets Phase A Task A4. Locks in the core time-saving behavior: PREP(k+1) launches at exposure end (readout start), and the next exposure waits for readout AND moves. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Phase A Task A5. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…rlap opt-out Phase A Task A6. readout_overlap_safe=0 defers PREP(k+1) until that camera's readout completes (no motion during rolling-shutter readout); ready-line and timeout paths locked by tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Phase A Task A7. Cancel never truncates an exposure and honors return_to_start; min_trigger_period_us spacing enforced; whole-run invariants: frames == Nz*Nch, exposures never overlap, no motion/DAC command inside any exposure window. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
Summary
Phase A of the firmware v2 modernization program (design + plan in AI-docs,
2026-07-04-firmware-v2-{design,plan}.md— see design §5 for the timing semantics this implements).Adds the hardware-sequenced acquisition engine as a pure C++11 module (
firmware/controller/src/sequencer/) with no Arduino dependencies and no serial/hardware wiring yet — that lands in later phases (protocol v2 Phase B/C, hardware binding Phase D). The firmware's runtime behavior is unchanged by this PR; the new files compile into the teensy41 target but nothing calls them.What the engine does (once wired)
One uploaded program = one multichannel z-stack executed autonomously: per (layer, channel) step it moves the stack axis (stepper or piezo DAC) and filter wheel, pre-arms the intensity DAC, waits for settle + filter-in-position + camera trigger-ready (input line or timing model), schedules µs-timestamped trigger/illumination edges (level or edge mode, keeping the v1 electrical contract: level pulse width = strobe_delay + exposure), and — the core time-saver — launches the next step's filter/z moves at exposure end, during camera readout. Rolling-shutter cameras can opt out via
readout_overlap_safe=0. Cancel never truncates an exposure; faults abort with specific error codes.Files
src/sequencer/seq_types.{h,cpp}— acquisition program structs (future SEQ_UPLOAD_PROGRAM wire format) + validationsrc/sequencer/seq_hal.h— hardware interface (ExposurePlanµs edge schedule; Phase D binds TMC/DAC/GPIO)src/sequencer/seq_engine.{h,cpp}— the timing state machinetest/test_seq_types/,test/test_seq_engine/— 22 Unity tests incl. a scripted fake HAL + virtual clockTesting
pio test -e native: 102/102 (16 engine-timing scenarios: readout overlap, WAIT gating, ready-line + timeout abort, rolling-shutter opt-out, cancel semantics, min trigger period, whole-run invariants: frames == Nz×Nch, exposures never overlap, no motion command inside any exposure window)pio run -e teensy41: SUCCESS (target build unaffected)🤖 Generated with Claude Code