pub struct Device { /* private fields */ }
Expand description

Represents a National Instruments (NI) device.

A Device is the primary structure used to interact with NI hardware. It groups multiple channels, each of which corresponds to a physical channel on an NI device. This struct provides easy access to various properties of the device, such as its physical name, task type, and several clock and trigger configurations. For editing and compiling behavior of devices, see the BaseDevice trait.

Fields

  • channels: A collection of channels associated with this device.
  • name: Name of the device as seen by the NI driver.
  • task_type: Specifies the task type associated with the device.
  • samp_rate: The sampling rate of the device in Hz.
  • samp_clk_src: Optional source of the sampling clock; supply None for on-board clock source.
  • trig_line: Optional identifier for the port through which to import/export the task start trigger. Supply None for trivial triggering behavior.
  • export_trig: Optional Boolean indicating if the device exports its start trigger. If true, the device exports the start trigger of the NI-task associated with this device through trig_line. If false or None, the device is set to import the start trigger. In case that any device in an experiment has nontrivial triggering behavior, one and only one of the devices must have export_trig set to true.
  • ref_clk_line: Optional source of the reference clock to phase-lock the device clock to.
  • export_ref_clk: Optional indicator of whether to export the reference clock. If true, the device exports its reference clock. If false or None, it imports the reference clock. Use None for trivial behavior.
  • ref_clk_rate: Optional rate of the reference clock in Hz.

Synchronization Methods

For experiments that do not require synchronization between devices, set all optional fields of Device to None. However, for more accurate and cohesive experiments, we recommend at least implementing start-trigger synchronization.

Start-trigger Synchronization

Relevant fields: trig_line, export_trig.

Refer to the official NI documentation on start-trigger synchronization.

This method designates one device to export its start trigger and others to import. When the experiment begins, tasks on devices with export_trig set to false are set to wait for a digital edge trigger from the trig_line channel. The device with export_trig set to true exports its start trigger to trig_line.

Note: It’s essential to physically connect the device that exports its trigger (where export_trig is true) to the corresponding lines on devices that import the trigger.

For PCIe devices, use a PFI label. For PXIe devices, use the label PXI_Trig followed by a number in the range 0-7. This backend crate ensures task synchronization such that threads handling tasks set to import the trigger always start listening for triggers before the exporting task begins.

For PXIe devices linked to a chassis, ensure that you configure trigger bus routing using NI-MAX (on Windows) or the NI Hardware Configuration Utilities (on Linux) when specifying backplane trigger lines. Detailed information can be found here.

It’s important to note that after starting, each device’s task utilizes its internal clock, which may result in incremental drifts between devices over time. For longer signals, it’s advisable to use additional synchronization methods to ensure clock alignment.

Example:

Here, the device PXI1Slot6 exports its start trigger to PXI1_Trig0, while PXI1Slot7 imports its start trigger from the same line.

let mut exp = Experiment::new();
exp.add_do_device("PXI1Slot6", 1e6);
exp.add_do_device("PXI1Slot7", 1e6);
exp.device_cfg_trig("PXI1Slot6", "PXI1_Trig0", true);
exp.device_cfg_trig("PXI1Slot7", "PXI1_Trig0", false);

The compiler will panic if more than one device exports trigger

let mut exp = Experiment::new();
exp.add_do_device("PXI1Slot6", 1e6);
exp.add_do_device("PXI1Slot7", 1e6);
exp.device_cfg_trig("PXI1Slot6", "PXI1_Trig0", true);
exp.device_cfg_trig("PXI1Slot7", "PXI1_Trig0", true);

The compiler will panic if some device is expecting a start trigger yet no device exports one.

let mut exp = Experiment::new();
exp.add_do_device("PXI1Slot6", 1e6);
exp.add_do_channel("PXI1Slot6", 0, 4);
exp.device_cfg_trig("PXI1Slot6", "PXI1_Trig0", false);
exp.go_high("PXI1Slot6", "port0/line4", 0.5);
exp.compile_with_stoptime(1.); // Panics here

Phase-lock to Reference Clock

Relevant fields: ref_clk_line, ref_clk_rate, export_ref_clk.

Refer to the NI documentation on phase-lock synchronization.

A subset of NI devices support this flexible synchronization method, which allows devices synchronized in this manner to operate at different sampling rates. Devices phase-lock their on-board oscillators to an external reference at ref_clk_line and indicate its frequency via ref_clk_rate. A device can optionally export its 10MHz onboard reference clock to ref_clk_line by setting export_ref_clk to true.

Note: Devices phase-locked in this manner still require start-trigger synchronization to ensure synchronized start times.

Example:

The device PXI1Slot6 exports its start trigger signal to PXI1_Trig0 and its 10MHz reference clock to PXI1_Trig7. The device PXI1Slot4 acts accordingly.

use nicompiler_backend::*;
let mut exp = Experiment::new();
exp.add_ao_device("PXI1Slot3", 1e6);
exp.device_cfg_trig("PXI1Slot3", "PXI1_Trig0", true);
exp.device_cfg_ref_clk("PXI1Slot3", "PXI1_Trig7", 1e7, true);

exp.add_ao_device("PXI1Slot4", 1e6);
exp.device_cfg_trig("PXI1Slot4", "PXI1_Trig0", false);
exp.device_cfg_ref_clk("PXI1Slot4", "PXI1_Trig7", 1e7, false);

Importing Sample Clock

Relevant fields: samp_clk_src.

Check out the NI documentation on sample clock synchronization.

Some NI devices do not support reference clock synchronization. As an alternative, they can directly use external clock signals for their sampling clock. However, this constrains them to operate at the same rate as the imported sample clock.

Example:

Building on the previous example, an additional PXI1Slot6 sources its sample clock from the 10MHz signal exported by PXI1Slot3.

use nicompiler_backend::*;
let mut exp = Experiment::new();
exp.add_ao_device("PXI1Slot3", 1e6);
exp.device_cfg_trig("PXI1Slot3", "PXI1_Trig0", true);
exp.device_cfg_ref_clk("PXI1Slot3", "PXI1_Trig7", 1e7, true);

exp.add_ao_device("PXI1Slot4", 1e6);
exp.device_cfg_trig("PXI1Slot4", "PXI1_Trig0", false);
exp.device_cfg_ref_clk("PXI1Slot4", "PXI1_Trig7", 1e7, false);

exp.add_do_device("PXI1Slot6", 1e7);
exp.device_cfg_samp_clk_src("PXI1Slot6", "PXI1_Trig7");
exp.device_cfg_trig("PXI1Slot6", "PXI1_Trig0", false);

Implementations§

source§

impl Device

source

pub fn new(name: &str, task_type: TaskType, samp_rate: f64) -> Self

Constructs a new Device instance.

This constructor initializes a device with the provided parameters. The channels field is initialized as an empty collection. All synchronization fields are initialized to None by default. For nontrivial synchronization behavior, use the methods BaseDevice::cfg_samp_clk_src, BaseDevice::cfg_trig, and BaseDevice::cfg_ref_clk.

Arguments
  • name: Name of the device as seen by the NI driver.
  • task_type: The type of task associated with the device.
  • samp_rate: Desired sampling rate in Hz.
Returns

A new instance of Device with the specified configurations and all synchronization-related fields set to None.

Trait Implementations§

source§

impl BaseDevice for Device

source§

fn channels(&self) -> &HashMap<String, Channel>

source§

fn name(&self) -> &str

source§

fn task_type(&self) -> TaskType

source§

fn samp_rate(&self) -> f64

source§

fn samp_clk_src(&self) -> Option<&str>

source§

fn trig_line(&self) -> Option<&str>

source§

fn export_trig(&self) -> Option<bool>

source§

fn ref_clk_line(&self) -> Option<&str>

source§

fn export_ref_clk(&self) -> Option<bool>

source§

fn ref_clk_rate(&self) -> Option<f64>

source§

fn channels_(&mut self) -> &mut HashMap<String, Channel>

source§

fn samp_clk_src_(&mut self) -> &mut Option<String>

source§

fn trig_line_(&mut self) -> &mut Option<String>

source§

fn export_trig_(&mut self) -> &mut Option<bool>

source§

fn ref_clk_line_(&mut self) -> &mut Option<String>

source§

fn export_ref_clk_(&mut self) -> &mut Option<bool>

source§

fn ref_clk_rate_(&mut self) -> &mut Option<f64>

source§

fn cfg_samp_clk_src(&mut self, src: &str)

Configures the sample clock source for the device. Read more
source§

fn cfg_trig(&mut self, trig_line: &str, export_trig: bool)

Configures the trigger settings for the device. Read more
source§

fn cfg_ref_clk( &mut self, ref_clk_line: &str, ref_clk_rate: f64, export_ref_clk: bool )

Configures the reference clock settings for the device. Read more
source§

fn editable_channels(&self) -> Vec<&Channel>

Returns a vector of references to editable channels
source§

fn editable_channels_(&mut self) -> Vec<&mut Channel>

Returns a vector of mutable references to editable channels
source§

fn add_channel(&mut self, name: &str)

Adds a new channel to the device. Read more
source§

fn is_compiled(&self) -> bool

A device is compiled if any of its editable channels are compiled. Also see BaseChannel::is_compiled
source§

fn is_edited(&self) -> bool

A device is marked edited if any of its editable channels are edited. Also see BaseChannel::is_edited
source§

fn is_fresh_compiled(&self) -> bool

A device is marked fresh-compiled if all if its editable channels are freshly compiled. Also see BaseChannel::is_fresh_compiled
source§

fn clear_edit_cache(&mut self)

Clears the edit-cache fields for all editable channels. Also see BaseChannel::clear_edit_cache
source§

fn clear_compile_cache(&mut self)

Clears the compile-cache fields for all editable channels. Also see BaseChannel::clear_compile_cache
source§

fn compile(&mut self, stop_pos: usize)

Compiles all editable channels to produce a continuous instruction stream. Read more
source§

fn compiled_channels( &self, require_streamable: bool, require_editable: bool ) -> Vec<&Channel>

Returns a vector of compiled channels based on the given criteria. Read more
source§

fn compiled_stop_time(&self) -> f64

Calculates the maximum stop time among all compiled channels. Read more
source§

fn edit_stop_time(&self) -> f64

Calculates the maximum stop time among all editable channels. Read more
source§

fn fill_signal_nsamps( &self, start_pos: usize, end_pos: usize, nsamps: usize, buffer: &mut Array2<f64>, require_streamable: bool, require_editable: bool )

Generates a signal by sampling float-point values from compiled instructions. Read more
source§

fn calc_signal_nsamps( &self, start_pos: usize, end_pos: usize, nsamps: usize, require_streamable: bool, require_editable: bool ) -> Array2<f64>

Computes and returns the signal values for specified channels in a device. Read more
source§

fn unique_port_numbers(&self) -> Vec<usize>

Retrieves a list of unique port numbers from the device’s channels. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> Ungil for Twhere T: Send,