Trait nicompiler_backend::channel::BaseChannel
source · 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§
fn samp_rate(&self) -> f64
fn name(&self) -> &str
fn task_type(&self) -> TaskType
sourcefn is_fresh_compiled(&self) -> bool
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
.
sourcefn instr_list(&self) -> &BTreeSet<InstrBook>
fn instr_list(&self) -> &BTreeSet<InstrBook>
Provies a reference to the edit cache of instrbook list.
sourcefn instr_val(&self) -> &Vec<Instruction>
fn instr_val(&self) -> &Vec<Instruction>
Retrieves the values of compiled instructions.
sourcefn fresh_compiled_(&mut self) -> &mut bool
fn fresh_compiled_(&mut self) -> &mut bool
Mutable access to the fresh_compiled
status.
sourcefn instr_list_(&mut self) -> &mut BTreeSet<InstrBook>
fn instr_list_(&mut self) -> &mut BTreeSet<InstrBook>
Mutable access to the instruction list.
sourcefn instr_end_(&mut self) -> &mut Vec<usize>
fn instr_end_(&mut self) -> &mut Vec<usize>
Mutable access to the ending points of compiled instructions.
sourcefn instr_val_(&mut self) -> &mut Vec<Instruction>
fn instr_val_(&mut self) -> &mut Vec<Instruction>
Mutable access to the values of compiled instructions.
Provided Methods§
sourcefn is_compiled(&self) -> bool
fn is_compiled(&self) -> bool
Channel is marked as compiled if its compilation-data field instr_end
is nonempty
sourcefn is_edited(&self) -> bool
fn is_edited(&self) -> bool
Channel is marked as edited if its edit-cache field instr_list
is nonempty
sourcefn editable(&self) -> bool
fn editable(&self) -> bool
Channel is marked as editable if it is a AO channel or DO line channel (name contains “line”)
sourcefn streamable(&self) -> bool
fn streamable(&self) -> bool
Channel is marked as streamable if it is a AO channel or DO port channel (name does not contain “line”)
sourcefn compile(&mut self, stop_pos: usize)
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 specifiedstop_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)
sourcefn binfind_first_intersect_instr(&self, start_pos: usize) -> usize
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);
sourcefn clear_edit_cache(&mut self)
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
.
sourcefn clear_compile_cache(&mut self)
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
.
sourcefn compiled_stop_time(&self) -> f64
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.
sourcefn edit_stop_time(&self) -> f64
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
.
sourcefn add_instr(
&mut self,
instr: Instruction,
t: f64,
duration: f64,
keep_val: bool
)
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)"
sourcefn constant(&mut self, value: f64, t: f64, duration: f64, keep_val: bool)
fn constant(&mut self, value: f64, t: f64, duration: f64, keep_val: bool)
Utility function to add a constant instruction to the channel
sourcefn fill_signal_nsamps(
&self,
start_pos: usize,
end_pos: usize,
num_samps: usize,
buffer: &mut ArrayViewMut1<'_, f64>
)
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 anndarray::ArrayViewMut1<f64>
that will hold the sampled signal values.
Panics
- If the channel is not compiled.
- If
end_pos
is not greater thanstart_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.
sourcefn calc_signal_nsamps(
&self,
start_time: f64,
end_time: f64,
num_samps: usize
) -> Vec<f64>
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