Skip to main content

uldaqrs/
lib.rs

1//! # Safe Rust bindings for the uldaq library
2//!
3//! This crate provides safe, ergonomic bindings to the
4//! [uldaq](https://github.com/mccdaq/uldaq) library, used for interacting with
5//! Measurement Computing / Data Translation DAQ devices (such as the DT9837
6//! series) on Linux.
7//!
8//! The unsafe FFI layer lives in the [`uldaq-sys`] crate; this crate wraps it
9//! in a safe API:
10//!
11//! - [`get_device_inventory`] enumerates the connected devices.
12//! - [`DaqDevice`] is a RAII handle to a device: it is created with
13//!   [`DaqDevice::create`], connected with [`DaqDevice::connect`], and
14//!   automatically disconnected and released when dropped.
15//! - [`DaqDevice::daq_in_scan`] / [`DaqDevice::a_out_scan`] start continuous
16//!   scans into caller-provided `f64` buffers, with
17//!   [`DaqDevice::daq_in_scan_status`] / [`DaqDevice::a_out_scan_status`] to
18//!   poll their progress and the corresponding stop functions to end them.
19//!
20//! ## Device setup
21//!
22//! Before starting a scan, input channels are typically configured with
23//! [`DaqDevice::set_ai_sensor_sensitivity`],
24//! [`DaqDevice::set_ai_coupling_mode`] and
25//! [`DaqDevice::set_ai_iepe_mode`].
26//!
27//! ## Example
28//!
29//! ```no_run
30//! use uldaqrs::{
31//!     CouplingMode, DaqDevice, DaqDeviceDescriptor, DaqInChanDescriptor, DaqInScanFlag,
32//!     DaqDeviceInterface, IepeMode, Range, ScanOption, get_device_inventory,
33//! };
34//!
35//! // 1. Find a device by name
36//! let devs = get_device_inventory(DaqDeviceInterface::ANY)?;
37//! let desc: DaqDeviceDescriptor = devs
38//!     .iter()
39//!     .find(|d| d.product_name.contains("DT9837"))
40//!     .cloned()
41//!     .ok_or("No DT9837 device found")?;
42//!
43//! // 2. Create and connect
44//! let dev = DaqDevice::create(&desc)?;
45//! dev.connect()?;
46//!
47//! // 3. Configure the input channels
48//! for ch in 0..4u32 {
49//!     dev.set_ai_sensor_sensitivity(ch, 1.0)?;
50//!     dev.set_ai_coupling_mode(ch, CouplingMode::Ac)?;
51//!     dev.set_ai_iepe_mode(ch, IepeMode::Enabled)?;
52//! }
53//!
54//! // 4. Start a continuous scan of 4 channels, 1024 samples per channel
55//! let channels = (0..4)
56//!     .map(|ch| DaqInChanDescriptor::analog_se(ch, Range::Bip1Volts))
57//!     .collect::<Vec<_>>();
58//! let mut data = vec![0.0f64; channels.len() * 1024];
59//! let actual_rate = dev.daq_in_scan(
60//!     &channels,
61//!     1024,
62//!     48000.0,
63//!     ScanOption::CONTINUOUS,
64//!     DaqInScanFlag::DEFAULT,
65//!     &mut data,
66//! )?;
67//!
68//! // 5. ... poll dev.daq_in_scan_status() and process `data` ...
69//!
70//! dev.daq_in_scan_stop()?;
71//! # Ok::<(), Box<dyn std::error::Error>>(())
72//! ```
73//!
74//! ## Prerequisites
75//!
76//! This crate requires `libusb-1.0` to be installed and is currently only
77//! working on Linux systems. Only tested on Linux Mint 22.1 xia.
78//!
79//! Install the `libusb` library and header files with:
80//!
81//! ```bash
82//! sudo apt install libusb-1.0-0-dev
83//! ```
84//!
85//! ## Author information
86//!
87//! - [J.A. de Jong (Redu-Sone B.V. / ASCEE)](mailto:j.a.dejong@ascee.nl)
88
89mod device;
90mod error;
91mod types;
92
93pub use device::{get_device_inventory, DaqDevice, DaqDeviceDescriptor};
94pub use error::{check, Error, Result, UlError};
95pub use types::*;