dtollib.backend¶
Session orchestration above the capi layer — HDRVR refcount, capability
cache, and the notification bridge. The real backend never touches ctypes
directly; that is the capi layer's job.
dataacq¶
dtollib.backend.dataacq ¶
Real DataAcq SDK backend — :class:DataAcqBackend.
This class is Layer 3 of the C-boundary stack (docs/design.md §10.3):
- Layer 1: :mod:
dtollib.capi.prototypes— raw ctypes signatures. - Layer 2: :class:
~dtollib.capi.OpenLayersApi— output-pointer extraction + ECODE classification. - Layer 3 (this module) — session-level orchestration: HDRVR ref-counting, capability cache, notification-wrapper pinning, buffer pool.
The class is constructed once per process and shared across every
:class:~dtollib.tasks.DtolSession. See
:class:~dtollib.manager.DtolManager for the per-session sharing
discipline.
DataAcqBackend ¶
Real DataAcq SDK backend.
Construction either accepts a pre-loaded
:class:~dtollib.capi.OpenLayersDlls (dependency injection — used
by tests) or calls :func:~dtollib.capi.load_openlayers itself.
Thread safety: a single :class:threading.RLock guards every SDK
call. The lock is conservative — see docs/design.md §16.3.
Bind the SDK and prepare the session caches.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dlls
|
OpenLayersDlls | None
|
Pre-loaded SDK handle pair. If |
None
|
Source code in src/dtollib/backend/dataacq.py
abort ¶
add_channel ¶
Add a channel to the channel/gain list with all per-type setters.
Caller MUST have already called :meth:set_multi_sensor_type
on this channel if it reports IOType.MULTI_SENSOR
(docs/design.md §8.5a).
Source code in src/dtollib/backend/dataacq.py
alloc_buffer ¶
olDmCallocBuffer / olDmMallocBuffer.
Source code in src/dtollib/backend/dataacq.py
arm ¶
olDaConfig — second config, after olDaSetWndHandle + queue.
Continuous mode only. The second olDaConfig wires the message
window into the SDK's buffer-rotation state machine; without it the
SDK never posts OLDA_WM_BUFFER_DONE on the DT9805/06.
Source code in src/dtollib/backend/dataacq.py
code_to_volts ¶
Convert a raw code to input volts from the configured scaling.
olDaCodeToVolts returns ECODE=9 ("Invalid Encoding") on the
DT9805/DT9806 A/D (bench-verified 2026-05-28; docs/decisions.md),
so we query the subsystem encoding / resolution / range once
(cached after commit) and convert ourselves via
:func:~dtollib.capi.conversion.code_to_input_volts.
Source code in src/dtollib/backend/dataacq.py
commit ¶
olDaConfig — first config (after channel/clock/wrap setup).
For single-value tasks this is the only config. For continuous
tasks it is config #1; :meth:arm runs config #2 after the
window handle is wired and buffers are queued (docs/decisions.md,
"Bench-verified continuous-mode setup").
Source code in src/dtollib/backend/dataacq.py
copy_buffer ¶
olDmCopyBuffer — copy an HBUF's valid samples to a host buffer.
Source code in src/dtollib/backend/dataacq.py
copy_inprocess_buffer ¶
olDmCopyFromBuffer — copy the in-process HBUF without waiting.
Source code in src/dtollib/backend/dataacq.py
copy_to_buffer ¶
olDmCopyToBuffer — fill an HBUF from a host byte payload.
enum_boards ¶
Enumerate every installed DT-Open Layers board.
Uses olDaEnumBoardsEx for the registry-aware enumeration so
the driver name and instance are populated. Falls back to
olDaEnumBoards + olDaGetBoardInfo if the Ex variant
fails (older drivers).
Source code in src/dtollib/backend/dataacq.py
enum_subsystems ¶
Enumerate subsystems on board_name.
Implementation note: olDaEnumSubSystems enumerates raw
HDASS handles, but the SDK's preferred discovery shape is
"try to acquire each (subsys_type, element) pair until one
fails". We do the latter — it's portable across SDK
revisions and surfaces the element index for each subsystem
without an extra round-trip.
Source code in src/dtollib/backend/dataacq.py
flush_buffers ¶
free_buffer ¶
get_buffer ¶
get_buffer_valid_samples ¶
get_cjc_temperature ¶
get_clock_frequency ¶
get_dass ¶
get_queue_size ¶
get_scaling ¶
Return (vmin, vmax, resolution_bits, twos_complement) for hdass.
Queries the subsystem range / resolution / encoding once (after
olDaConfig) and caches it. Exposed so the continuous block path
(:func:dtollib.streaming.record) can build a
:class:~dtollib.capi.conversion.BlockConversion plan with the same
scaling the single-value code_to_volts path uses.
Source code in src/dtollib/backend/dataacq.py
get_single_float ¶
get_single_floats ¶
olDaGetSingleFloats — simultaneous SH + engineering units.
Source code in src/dtollib/backend/dataacq.py
get_single_value ¶
get_single_values ¶
olDaGetSingleValues — simultaneous SH; requires cached n_channels.
Source code in src/dtollib/backend/dataacq.py
get_ss_list ¶
get_state ¶
olDaGetSSState → :class:SubsystemState.
get_version ¶
initialize ¶
Open board_name; return its HDRVR. Ref-counted across sessions.
Source code in src/dtollib/backend/dataacq.py
is_running ¶
measure_frequency ¶
olDaMeasureFrequency — measured input frequency (Hz).
mute ¶
put_buffer ¶
put_dass_to_ss_list ¶
put_single_value ¶
One-shot raw-code write via olDaPutSingleValue.
put_single_values ¶
Simultaneous raw-code write via olDaPutSingleValues.
query_capabilities ¶
Build a :class:CapabilitySet for hdass (cached).
Source code in src/dtollib/backend/dataacq.py
read_bridge_sensor_hardware_teds ¶
olDaReadBridgeSensorHardwareTeds passthrough.
read_bridge_sensor_virtual_teds ¶
olDaReadBridgeSensorVirtualTeds passthrough.
read_buffer_payload ¶
Build an ndarray view over the HBUF payload — drainer-thread call.
Returns a NumPy view; the caller copies before requeueing the HBUF.
Dtype is inferred from olDmGetDataWidth (2 bytes → int16, 4
bytes → int32).
Source code in src/dtollib/backend/dataacq.py
read_events ¶
read_strain_gage_hardware_teds ¶
olDaReadStrainGageHardwareTeds passthrough.
read_strain_gage_virtual_teds ¶
register_notification ¶
Route SDK buffer-done events for hdass to callback.
Creates a hidden message-only window on a dedicated pump thread,
calls olDaSetWndHandle to point the SDK at it, and pins the
:class:~dtollib.backend._message_window.MessageWindow on
self._notification_wrappers[id(hdass)] so neither the window,
the pump thread, nor the WNDPROC is collected while the SDK holds
the handle.
callback(msg_id, wparam, lparam) runs on the pump thread for
each OLDA_WM_* message — the window-handle mechanism is the
only one that delivers events on the DT9805/06 (docs/decisions.md).
Returns the :class:MessageWindow as the opaque handle for
:meth:unregister_notification.
Source code in src/dtollib/backend/dataacq.py
release_dass ¶
Release hdass and drop its capability + scaling cache entries.
Source code in src/dtollib/backend/dataacq.py
release_ss_list ¶
set_cascade_mode ¶
set_channel_list ¶
Set list size + each entry via two SDK calls (drainer-thread safe).
Source code in src/dtollib/backend/dataacq.py
set_clock ¶
Configure clock source + frequency (+ divider when external).
Source code in src/dtollib/backend/dataacq.py
set_ct_clock ¶
olDaSetCTClockSource + olDaSetCTClockFrequency.
Source code in src/dtollib/backend/dataacq.py
set_ct_mode ¶
set_data_flow ¶
set_digital_io_list_entry ¶
set_dma_usage ¶
set_gate_type ¶
set_measure_edges ¶
olDaSetMeasureStartEdge + olDaSetMeasureStopEdge.
Source code in src/dtollib/backend/dataacq.py
set_multi_sensor_type ¶
Re-type a MULTI_SENSOR channel. Caller orders this BEFORE per-type setters.
Source code in src/dtollib/backend/dataacq.py
set_pulse ¶
olDaSetPulseType + olDaSetPulseWidth.
Source code in src/dtollib/backend/dataacq.py
set_return_cjc_in_stream ¶
olDaSetReturnCjcTemperatureInStream — interleaved-CJC streaming.
set_stop_on_error ¶
set_synchronous_digital_io_usage ¶
set_thermocouple_type ¶
Set TC type via olDaSetThermocoupleType.
Source code in src/dtollib/backend/dataacq.py
set_trigger ¶
Configure start-trigger + analog-threshold parameters when given.
Source code in src/dtollib/backend/dataacq.py
set_triggered_scan ¶
Enable triggered scan + configure the retrigger mode.
Source code in src/dtollib/backend/dataacq.py
set_wrap_mode ¶
simultaneous_pre_start ¶
simultaneous_start ¶
start ¶
olDaStart — skipped for single-value subsystems.
Single-value mode has no run state: after olDaConfig the
subsystem is ready for olDaGetSingleValue and olDaStart
returns ECODE=27 ("Dataflow mismatch"). The session calls start
unconditionally as a convention, so we make it a no-op there.
Source code in src/dtollib/backend/dataacq.py
stop ¶
terminate ¶
Drop a reference to hdrvr; close on final release.
Source code in src/dtollib/backend/dataacq.py
unmute ¶
unregister_notification ¶
Detach the window handle, stop the pump, and drop the window.
Source code in src/dtollib/backend/dataacq.py
volts_to_bridge_based_sensor ¶
volts_to_bridge_based_sensor(
v_unstrained,
v_strained,
v_excitation,
temperature_coefficient,
gage_resistance,
lead_resistance,
rated_output_mv_per_v,
shunt_correction,
)
olDaVoltsToBridgeBasedSensor passthrough (pure SDK conversion).
Source code in src/dtollib/backend/dataacq.py
volts_to_strain ¶
volts_to_strain(
config,
v_unstrained,
v_strained,
v_excitation,
gage_factor,
gage_resistance,
lead_resistance,
poisson_ratio,
shunt_correction,
)
olDaVoltsToStrain passthrough (pure SDK conversion, no lock needed).