Synchronized start¶
DtolManager.start_synchronized(names) starts several subsystems together via
the DT-Open Layers simultaneous-start primitives, so their first samples begin
within one sample period of each other — tighter than a software start loop can
achieve.
What it does¶
It runs the four-step SDK sequence (and always releases the list afterward):
olDaGetSSList # obtain a simultaneous-start list for the board
olDaPutDassToSSList × N # add each task's subsystem
olDaSimultaneousPreStart # arm every subsystem
olDaSimultaneousStart # start them all on one trigger
olDaReleaseSSList # always, even if a step raised
Usage¶
import anyio
from dtollib import AnalogInputVoltage, CounterEdgeCount, DtolManager, TaskSpec
from dtollib.backend.dataacq import DataAcqBackend
ai_spec = TaskSpec(name="ai", board="DT9806(00)",
channels=[AnalogInputVoltage(physical_channel=0)])
ct_spec = TaskSpec(name="ct", board="DT9806(00)",
channels=[CounterEdgeCount(physical_channel=0)])
async def main() -> None:
backend = DataAcqBackend() # one shared backend → one HDRVR namespace
async with DtolManager() as mgr:
await mgr.add("ai", ai_spec, backend=backend)
await mgr.add("ct", ct_spec, backend=backend)
await mgr.start_synchronized(["ai", "ct"])
# both subsystems are now RUNNING, started together.
anyio.run(main)
Scope and constraints¶
- Single board. Every named task must target the same board. Cross-board
coordination over the Sync Bus (
olDaSetSyncMode) is not yet implemented. - One shared backend. Pass the same
backend=to eachadd(). The SS-list is built from one HDRVR's subsystem handles; tasks on separate backend instances live in separate handle namespaces and cannot be coordinated. The manager raisesDtolValidationErrorif the named tasks don't share a backend. - Tasks must be committed, not started.
DtolManager.add()commits during registration, so single-value and counter tasks are ready immediately. - Continuous-AI tasks must complete their
record()register → queue → commit sequence first. Open the recorder withautostart=False, let it wire the §12.3.2 callback bridge and commit, then callstart_synchronizedto begin acquisition in lockstep with the other subsystems. A first-classrecord_synchronized()helper is deferred (OQ-5c).
Verifying alignment¶
On the bench, capture both subsystems through a RawCountsSink and compare the
first-sample timestamps — they should fall within one sample period. The fake
backend models the state transitions (PRESTARTED → RUNNING) and the
ordering invariants (put before pre-start, pre-start before start) so the
sequence is unit-tested without hardware.