pub trait BaseChannel {
Show 25 methods // Required methods fn samp_rate(&self) -> f64; fn name(&self) -> &str; fn task_type(&self) -> TaskType; fn is_fresh_compiled(&self) -> bool; fn instr_list(&self) -> &BTreeSet<InstrBook>; fn instr_end(&self) -> &Vec<usize>; fn instr_val(&self) -> &Vec<Instruction>; fn fresh_compiled_(&mut self) -> &mut bool; fn instr_list_(&mut self) -> &mut BTreeSet<InstrBook>; fn instr_end_(&mut self) -> &mut Vec<usize>; fn instr_val_(&mut self) -> &mut Vec<Instruction>; // Provided methods fn is_compiled(&self) -> bool { ... } fn is_edited(&self) -> bool { ... } fn editable(&self) -> bool { ... } fn streamable(&self) -> bool { ... } fn compile(&mut self, stop_pos: usize) { ... } fn binfind_first_intersect_instr(&self, start_pos: usize) -> usize { ... } fn clear_edit_cache(&mut self) { ... } fn clear_compile_cache(&mut self) { ... } fn compiled_stop_time(&self) -> f64 { ... } fn edit_stop_time(&self) -> f64 { ... } fn add_instr( &mut self, instr: Instruction, t: f64, duration: f64, keep_val: bool ) { ... } fn constant(&mut self, value: f64, t: f64, duration: f64, keep_val: bool) { ... } fn fill_signal_nsamps( &self, start_pos: usize, end_pos: usize, num_samps: usize, buffer: &mut ArrayViewMut1<'_, f64> ) { ... } fn calc_signal_nsamps( &self, start_time: f64, end_time: f64, num_samps: usize ) -> Vec<f64> { ... }
}
Expand description

The BaseChannel trait defines the core methods required for a channel’s interaction with NI devices. It encapsulates both editing and compilation behaviors of a channel.

Implementing this trait allows a type to represent a channel on a NI device, providing methods to access and modify essential properties such as the sampling rate, physical name, and type of task. Additionally, it provides methods to access and edit the underlying instruction list and compiled instructions, enabling the creation, modification, and execution of tasks on the hardware.

Required Methods

Implementors of this trait must provide implementations for a set of methods that allow:

  • Accessing immutable properties of the channel.
  • Mutating certain properties and states of the channel.

This trait ensures that any type representing a channel offers the necessary functionality to interact with NI devices, ensuring consistency and safety in channel operations.

Required Methods§

source

fn samp_rate(&self) -> f64

source

fn name(&self) -> &str

source

fn task_type(&self) -> TaskType

source

fn is_fresh_compiled(&self) -> bool

The fresh_compiled field is set to true by each BaseChannel::compile call and false by each BaseChannel::add_instr.

source

fn instr_list(&self) -> &BTreeSet<InstrBook>

Provies a reference to the edit cache of instrbook list.

source

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

Returns the ending points of compiled instructions.

source

fn instr_val(&self) -> &Vec<Instruction>

Retrieves the values of compiled instructions.

source

fn fresh_compiled_(&mut self) -> &mut bool

Mutable access to the fresh_compiled status.

source

fn instr_list_(&mut self) -> &mut BTreeSet<InstrBook>

Mutable access to the instruction list.

source

fn instr_end_(&mut self) -> &mut Vec<usize>

Mutable access to the ending points of compiled instructions.

source

fn instr_val_(&mut self) -> &mut Vec<Instruction>

Mutable access to the values of compiled instructions.

Provided Methods§

source

fn is_compiled(&self) -> bool

Channel is marked as compiled if its compilation-data field instr_end is nonempty

source

fn is_edited(&self) -> bool

Channel is marked as edited if its edit-cache field instr_list is nonempty

source

fn editable(&self) -> bool

Channel is marked as editable if it is a AO channel or DO line channel (name contains “line”)

source

fn streamable(&self) -> bool

Channel is marked as streamable if it is a AO channel or DO port channel (name does not contain “line”)

source

fn compile(&mut self, stop_pos: usize)

Compiles the instructions in the channel up to the specified stop_pos.

The compile method processes the instruction list (instr_list) to generate a compiled list of end positions (instr_end) and corresponding values (instr_val). During compilation, it ensures that instructions are contiguous, adding padding as necessary. If two consecutive instructions have the same value, they are merged into a single instruction.

Arguments
  • stop_pos: The position up to which the instructions should be compiled. This is used to determine if padding is required at the end of the compiled instruction list.
Panics

This method will panic in the following scenarios:

  • If the last instruction’s end position in the instr_list exceeds the specified stop_pos.
  • If the channel is being recompiled but the previously compiled end position matches stop_pos.
Examples
let mut channel = Channel::new(TaskType::DO, "port0/line0", 1e7);

// Add some instructions to the channel.
channel.add_instr(Instruction::new_const(1.), 0., 1., false);
channel.add_instr(Instruction::new_const(0.), 1., 1., false);

// Compile the instructions up to a specified stop position.
channel.compile(3e7 as usize); // Compile up to 3 seconds (given a sampling rate of 10^7)
source

fn binfind_first_intersect_instr(&self, start_pos: usize) -> usize

Utility function for signal sampling.

Assuming a compiled channel (does not check), this utility function uses a binary search to efficiently determine the index of the first instruction whose end position is no less than the given start_pos.

Note: This function assumes that instr_end is sorted in ascending order. It does not perform any checks for this condition.

Arguments
  • start_pos - The starting position for which to find the intersecting instruction.
Returns

Returns the index i of the first instruction such that self.instr_end[i] >= pos If no such instruction is found, the function returns an index pointing to where the pos would be inserted to maintain the sorted order.

Examples
let mut channel = Channel::new(TaskType::DO, "port0/line0", 1e7);
channel.instr_end_().extend([10, 20, 30, 40, 50].iter());

assert_eq!(channel.binfind_first_intersect_instr(15), 1);
assert_eq!(channel.binfind_first_intersect_instr(20), 1);
assert_eq!(channel.binfind_first_intersect_instr(25), 2);
assert_eq!(channel.binfind_first_intersect_instr(55), 5);
assert_eq!(channel.binfind_first_intersect_instr(5), 0);
source

fn clear_edit_cache(&mut self)

Clears the instr_list field of the channel.

If the compiled cache is empty, it also sets the fresh_compiled field to true.

source

fn clear_compile_cache(&mut self)

Clears the compiled cache of the channel.

Specifically, the method clears the instr_end and instr_val fields. If the edit cache is empty, it also sets the fresh_compiled field to true.

source

fn compiled_stop_time(&self) -> f64

Returns the stop time of the compiled instructions.

If the channel is not compiled, it returns 0. Otherwise, it retrieves the last end position from the compiled cache and converts it to a time value using the sampling rate.

source

fn edit_stop_time(&self) -> f64

Returns the stop time of the edited instructions.

Retrieves the last instruction from the edit cache and converts its end position to a time value using the sampling rate. If the edit cache is empty, it returns 0.

source

fn add_instr( &mut self, instr: Instruction, t: f64, duration: f64, keep_val: bool )

Adds an instruction to the channel.

This is the primary method for adding instructions. It computes the discrete position interval associated with the given instruction, updates the fresh_compiled field, and inserts the instruction if it does not overlap with existing ones.

Arguments
  • instr: The instruction to be added.
  • t: The start time for the instruction.
  • duration: The duration of the instruction.
  • keep_val: Boolean value indicating whether to keep the instruction value after its end time.
Panics

This method will panic if the new instruction overlaps with any existing instruction.

Example
let mut channel = Channel::new(TaskType::DO, "port0/line0", 1e7);

// Ask the DO channel to go high at t=1 for 0.5 seconds, then return to default value (0)
channel.add_instr(Instruction::new_const(1.), 1., 0.5, false);

// Asks the DO channel to go high at t=0.5 for 0.001 seconds and keep its value.
// This will be merged with the instruction above during compilation.
channel.add_instr(Instruction::new_const(1.), 0.5, 0.001, true);

// The following line is effectively the same as the two lines above after compilation.
// However, adding it immediately after the previous instructions will cause an overlap panic.
// Uncommenting the line below will trigger the panic.
// channel.add_instr(Instruction::new_const(1.), 0.5, 1., false);

Expected failure:

let mut channel = Channel::new(TaskType::DO, "port0/line0", 1e7);
channel.add_instr(Instruction::new_const(1.), 1., 0.5, false);
channel.add_instr(Instruction::new_const(1.), 0.5, 0.001, true);
channel.add_instr(Instruction::new_const(1.), 0.5, 1., false); // This will panic

The panic message will be:

"Channel port0/line0
 Instruction InstrBook([CONST, {value: 1}], 5000000-15000000, false) overlaps with the next instruction InstrBook([CONST, {value: 1}], 5000000-5010000, true)"
source

fn constant(&mut self, value: f64, t: f64, duration: f64, keep_val: bool)

Utility function to add a constant instruction to the channel

source

fn fill_signal_nsamps( &self, start_pos: usize, end_pos: usize, num_samps: usize, buffer: &mut ArrayViewMut1<'_, f64> )

Fills a buffer (1D view of array) with the signal samples derived from a channel’s instructions.

This method samples the float-point signal from channel’s compile cache between the positions start_pos and end_pos, and replaces the contents of the buffer with results. The number of samples is given by num_samps. Time-dependent instructions assume that the buffer is already populated with correctly sampled time values.

Arguments
  • start_pos - The starting position in the channel’s instructions to begin sampling.
  • end_pos - The ending position in the channel’s instructions to stop sampling.
  • num_samps - The number of samples required.
  • buffer - A mutable reference to an ndarray::ArrayViewMut1<f64> that will hold the sampled signal values.
Panics
  • If the channel is not compiled.
  • If end_pos is not greater than start_pos.
  • If end_pos exceeds the duration of the channel’s compiled instructions.
Example
let mut channel = Channel::new(TaskType::AO, "ao0", 1e6);
// Sample 100 samples from t=0 to t=10s
let (start_pos, end_pos, num_samps) = (0, 1e7 as usize, 100);

// Add an sine instruction sig=sin(2*pi*t*7.5) + 1 from t=0.5~9.5 which keeps its value
let sine_instr = Instruction::new_sine(7.5, None, None, Some(1.0));
channel.add_instr(sine_instr, 0.5, 9., true);
channel.compile(1e7 as usize); // Compile the channel to stop at 10s (1e7 samples)

let mut buffer = ndarray::Array1::<f64>::zeros(num_samps);
channel.fill_signal_nsamps(start_pos, end_pos, num_samps, &mut buffer.view_mut());

assert_eq!(buffer[0], 0.);
assert_eq!(buffer[99], 2.);
Notes

The method uses binary search to find the starting and ending instruction indices that intersect with the provided interval [start_pos, end_pos]. It then iterates over these instructions to sample the signal and populate the buffer. Time conversion is done internally to map between the position indices and the buffer’s time values.

source

fn calc_signal_nsamps( &self, start_time: f64, end_time: f64, num_samps: usize ) -> Vec<f64>

Calls fill_signal_nsamps with the appropriate buffer and returns signal vector. The in-place version fill_signal_nsamps is preferred to this method for efficiency. This is mainly a wrapper to expose channel-signal sampling to Python

Implementors§