| type | reference | ||||||
|---|---|---|---|---|---|---|---|
| title | API Reference | ||||||
| created | 2026-08-29 | ||||||
| tags |
|
||||||
| related |
|
Release 1.1.0 disables the legacy 4 MHz gpio_capture_diagnostic() command;
its capability bit is clear. gpio_clock_diagnostic() accepts only 1 MHz.
ThingDAQ.get_temperature() returns TemperatureReading(status, millidegrees_c), with a celsius property. It works in IDLE, CONFIGURED and
RUNNING on firmware 1.1.0, does not change acquisition, and returns None
for a non-valid sensor reading. TemperatureStatus is exported from thingdone_daq.
See [[Protocol-V2]] for wire details and the fixed-rate release policy.
ThingDAQ.get_runtime_health() returns an immutable RuntimeHealth with
stack_available, watchdog_enabled, stack_total_bytes,
stack_min_free_bytes, stack_max_used_bytes, reset_cause and
watchdog_timeout_ms. It requires the firmware hardening build and works during
acquisition. The watermark persists until reboot; RESET_STATS does not clear it.
Use the acquisition's existing ThingDAQ instance to query it. See
[[Firmware-Runtime-Hardening]] for measurement limits and long-test guidance.
Important
Release 1.1.0 uses [[Protocol-V2]]: 450 MHz core, both ADCs and GPIO at
1 MHz, with 8 or 16 GPIO inputs. Phase-numbered results and legacy v1
examples below are historical; their 600 MHz / 4 MHz claims are not current
release settings. Use live INFO metadata. TimestampAligner does not support
the new unequal-duration ADC/GPIO frames; use block sample timestamps.
This page describes the stable synchronous user surface. Import normal
operations and immutable models from thingdone_daq; use
thingdone_daq.low_level only for protocol tooling that intentionally owns raw
frames, parsers, readers, or byte transports.
from thingdone_daq import ThingDAQ, discover, enumerate_candidates, select_device| Entry point | Behavior |
|---|---|
enumerate_candidates() |
Metadata-only VID/PID filter; opens no ports |
discover(timeout=...) |
Bounded read-only INFO probe of plausible candidates |
select_device(devices, hardware_serial=...) |
Selects stable INFO/USB serial identity, never a cached port path |
ThingDAQ.open(...) |
Opens transport/device/port/discovered target or performs discovery; synchronizes stable INFO |
ThingDAQ.simulated(...) |
Opens the deterministic protocol peer through InMemoryTransport |
ThingDAQ.open(hardware_serial=N) is the recommended physical selection.
expected_identity=ExpectedDeviceIdentity(...) can additionally pin exact
firmware/build/board/MCU/protocol identity. session_policy="adopt" is the
default; use "stop" to force an existing CONFIGURED/RUNNING device to IDLE.
Both constructors return a typed context manager. close() normally attempts
STOP before deterministic shutdown. close(stop=False) deliberately preserves
device state and should be limited to tools that explicitly need it.
daq.info() returns DeviceInfo; the last synchronized value is also
daq.device_info. Key fields include:
hardware_serial,firmware_version,build_id,board_id,mcu_id;device_state, applied stream/source/checksum, and protocol version;- supported stream/source/checksum/profile/capability masks;
- 8 MHz timestamp frequency and fixed frame sizes;
- ADC rate, phase, resolution/range, A0/A1 route, initialization calibration, trigger, DMA, and resource metadata; and
- GPIO rate, D6-D13 bit order, ring/resource metadata, and diagnostic policy.
info.capabilities returns DeviceCapabilities with:
caps.supports_source(source)
caps.supports_checksum(algorithm)
caps.supports_configuration(configuration)
caps.supports(capability_bit)
caps.supported_checksum_algorithmsModels reject reserved bits, inconsistent masks, wrong fixed protocol values, and incompatible applied configurations at decode time.
Convenience configuration:
applied = daq.configure(
adc=True,
gpio=True,
source=Source.HARDWARE,
checksum_algorithm=ChecksumAlgorithm.ADLER32,
adc_pair_rate_hz=1_000_000,
gpio_sample_rate_hz=4_000_000,
adc_resolution_bits=12,
)Or pass an explicit wire model:
request = DAQConfiguration(
stream_mask=StreamMask.ADC | StreamMask.GPIO,
source=Source.SYNTHETIC,
data_checksum_algorithm=ChecksumAlgorithm.CRC32C,
)
applied = daq.configure(
request,
adc_pair_rate_hz=1_000_000,
gpio_sample_rate_hz=4_000_000,
adc_resolution_bits=12,
)The three numeric keywords are exact INFO preconditions, not CONFIGURE body
fields. A requirement for a disabled stream is invalid. Unsupported
stream/source/profile/checksum/rate/resolution selections raise
DeviceCapabilityError before CONFIGURE is written. The returned
DAQConfiguration is the exact device echo. A changed echo raises
UnexpectedMessageError while retaining the observed state for cleanup.
daq.start() requires CONFIGURED, verifies the echoed applied configuration,
activates a new nonzero run ID, and returns it. daq.stop() is idempotent in
IDLE/CONFIGURED/RUNNING and returns DeviceState.IDLE. daq.configuration,
daq.state, and daq.run_id expose the facade's latest authoritative state.
configure_control_only() exists for older zero-stream Phase 03 firmware; it
is not a way to request disabled acquisition from production firmware.
item = daq.read_block(timeout=0.5)
for item in daq.blocks(count=10, timeout=0.5):
...blocks(count=N) counts only ADCBlock/GPIOBlock; any loss reports are
additional yielded items. With strict=False, StreamItem is:
ADCBlock | GPIOBlock | StreamGap | HostQueueLoss | StreamAnomaly
With strict=True, unexpected gap/queue-loss/anomaly/health evidence raises a
typed exception instead of becoming an ordinary item.
Important properties and methods:
| Member | Meaning |
|---|---|
run_id, sequence, first_sample_ticks, flags |
Wire identity and continuity |
item_count |
1,012 converter pairs |
adc0, adc1 |
Lazy unchanged raw-code views for A0/A1 |
pair(i) / pairs() |
One or all (ADC0, ADC1) pairs |
pair_ticks(i) / pair_seconds(i) |
Nominal ADC0/ADC1 times |
interleaved() |
ADC0 then ADC1 AdcSample iterator with identity/ticks |
resolution_bits, code_range, source |
Applied data interpretation |
calibration, trigger, acquisition |
Firmware evidence attached to the block |
calibrated_channels(record, ...) |
Explicit lazy voltage channel views |
calibrated_interleaved(record, ...) |
Explicit timestamped voltage samples |
as_numpy() |
Lazy optional NumPy integration |
For pair i, ADC0 is at t0 + 8i ticks and ADC1 at t0 + 8i + 4 ticks.
AdcSample includes pair_index, converter, pin, code, and
timestamp_ticks. Interleaving does not increase analog bandwidth; see
[[Hardware-Safety]].
Important properties and methods:
| Member | Meaning |
|---|---|
run_id, sequence, first_sample_ticks, flags |
Wire identity and continuity |
item_count |
4,048 packed snapshots |
samples / payload_view |
Read-only packed-byte view |
sample(i) |
One packed D6-D13 byte |
sample_ticks(i) / sample_seconds(i) |
Nominal time at t0 + 2i ticks |
channel(pin) |
Lazy Boolean view for exactly one D6-D13 pin |
as_numpy() |
Optional zero-copy packed array and selected-channel operations |
The bit map is fixed: D6 through D13 occupy bits 0 through 7. There is no eager eight-channel expansion.
Stable public names include:
CalibrationRecord,CalibrationDatabase,CalibrationStore, andCalibrationKey;ConverterCalibration;estimate_offset_gain(),apply_correction(), andapply_corrections();save_calibration(path, record)andload_calibration(path, serial, profile, ...); andcalibrated_channels()/calibrated_interleaved().
There is no default calibration path. Records are immutable, schema-versioned,
atomically written to an explicit path, and matched against serial, optional
case-sensitive profile, resolution, complete code range, and nominal input
range before use. Calibrated results retain source blocks, raw codes,
provenance, and a visible calibrated=True marker. Residual timing skew is
recorded but not applied. See [[Calibration]].
TimestampAligner(max_pending_intervals=N) accepts ADCBlock, GPIOBlock, or
StreamGap through push(). It returns zero or more:
AlignedInterval | AlignmentLoss | StreamGap
flush() marks unresolved sides at an explicit wall-clock/STOP boundary;
finish() marks end-of-input and rejects later pushes. AlignedInterval
retains both blocks, run/source, first/end ticks, present/missing streams, and
nominal seconds. align_by_timestamp(iterable, ...) is the finite iterable
convenience form.
daq.status() returns the full immutable firmware Status. Its nested
counters/ADC evidence expose per-source acquisition, framing, transmission,
drop, queue, parser, transport, lifecycle, and diagnostic values.
daq.loss_counters(refresh=True) returns LossCounters containing independent:
firmware: FirmwareLossEvidence;host: HostCounters;- observed stream-gap, host-queue-loss, and anomaly counts; and
- protocol telemetry disagreement evidence.
daq.validate_stream_health(status=None) returns a healthy STATUS or raises
UnexpectedStreamValidationError. reconcile_run_counters(status, run_id=...)
returns a detailed RunCounterReconciliation with conservation equations and
fault snapshot. Applications should inspect both live events and cumulative
counters.
| Category | Principal public exception |
|---|---|
| Closed/illegal lifecycle | DAQClosedError, DAQStateError |
| Unsupported request | DeviceCapabilityError |
| Typed firmware rejection | DeviceCommandError |
| Bounded command/block wait | CommandTimeoutError, BlockTimeoutError |
| Identity/synchronization | DeviceIdentityMismatchError, DeviceSynchronizationError |
| Discovery selection | DeviceNotFoundError, MultipleDevicesFoundError |
| Disconnect/protocol | DeviceDisconnectedError, ReaderProtocolError, ProtocolError |
| Loss/anomaly/health | UnexpectedStreamGapError, UnexpectedHostQueueLossError, UnexpectedStreamAnomalyError, UnexpectedStreamValidationError |
| Calibration | CalibrationFormatError, CalibrationMismatchError |
| Cleanup | DAQShutdownError |
Transport-specific open, busy, timeout, and disconnect errors are also public.
Command timeouts and terminal reader failures carry RecoveryEvidence when
available.
The thingdone_daq console script provides metadata-only list, INFO (info or
probe), STATUS, reconciliation, configure/start/stop/reset, and bounded
monitor/capture commands. --json emits one machine-readable document.
Capture can select raw or explicitly calibrated ADC previews, selected GPIO
channels, strict loss policy, and simulator mode. SIGINT/SIGTERM are converted
into cleanup-aware interruption so STOP is attempted before exit 130.
All repository examples run against the simulator by default; the physical
path requires --real. See [[Quickstart]] for the exact commands and hardware
requirements.