#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Gain {
X1 = 0,
X2 = 1,
X4 = 2,
X6 = 3,
X8 = 4,
X12 = 5,
X24 = 6,
}
impl Gain {
pub fn multiplier(self) -> f64 {
match self {
Gain::X1 => 1.0,
Gain::X2 => 2.0,
Gain::X4 => 4.0,
Gain::X6 => 6.0,
Gain::X8 => 8.0,
Gain::X12 => 12.0,
Gain::X24 => 24.0,
}
}
pub(crate) fn code(self) -> u8 {
self as u8
}
}
impl Default for Gain {
fn default() -> Self {
Gain::X24
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum InputType {
Normal = 0,
Shorted = 1,
BiasMeas = 2,
Mvdd = 3,
Temp = 4,
TestSig = 5,
BiasDrp = 6,
BiasDrn = 7,
}
impl Default for InputType {
fn default() -> Self {
InputType::Normal
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ChannelConfig {
pub power: bool,
pub gain: Gain,
pub input_type: InputType,
pub bias: bool,
pub srb2: bool,
pub srb1: bool,
}
impl Default for ChannelConfig {
fn default() -> Self {
Self {
power: true,
gain: Gain::X24,
input_type: InputType::Normal,
bias: true,
srb2: true,
srb1: false,
}
}
}
impl ChannelConfig {
pub fn gain(mut self, g: Gain) -> Self { self.gain = g; self }
pub fn input_type(mut self, t: InputType) -> Self { self.input_type = t; self }
pub fn power(mut self, on: bool) -> Self { self.power = on; self }
pub fn bias(mut self, b: bool) -> Self { self.bias = b; self }
pub fn srb2(mut self, s: bool) -> Self { self.srb2 = s; self }
pub fn srb1(mut self, s: bool) -> Self { self.srb1 = s; self }
pub fn to_command(&self, channel_letter: char) -> String {
format!(
"x{}{}{}{}{}{}{}X",
channel_letter,
if self.power { '0' } else { '1' }, self.gain.code(),
self.input_type as u8,
if self.bias { '1' } else { '0' },
if self.srb2 { '1' } else { '0' },
if self.srb1 { '1' } else { '0' },
)
}
}
pub const CHANNEL_LETTERS: [char; 16] = [
'1','2','3','4','5','6','7','8', 'Q','W','E','R','T','Y','U','I', ];
pub const GAIN_VALUES: [f64; 7] = [1.0, 2.0, 4.0, 6.0, 8.0, 12.0, 24.0];
pub fn gain_from_code(code: u8) -> f64 {
GAIN_VALUES.get(code as usize).copied().unwrap_or(1.0)
}
#[derive(Debug, Clone)]
pub struct GainTracker {
gains: Vec<f64>,
}
impl GainTracker {
pub fn new(default_gains: Vec<f64>) -> Self {
Self { gains: default_gains }
}
pub fn gain_for(&self, channel_idx: usize) -> f64 {
self.gains.get(channel_idx).copied().unwrap_or(1.0)
}
pub fn apply_command(&mut self, cmd: &str) -> bool {
let bytes = cmd.as_bytes();
let mut i = 0;
while i + 8 < bytes.len() {
if bytes[i] == b'x' && bytes[i + 8] == b'X' {
let letter = bytes[i + 1] as char;
let gain_code = bytes[i + 3].wrapping_sub(b'0');
if let Some(ch_idx) = CHANNEL_LETTERS.iter().position(|&c| c == letter) {
if (gain_code as usize) < GAIN_VALUES.len() {
self.gains[ch_idx] = GAIN_VALUES[gain_code as usize];
}
}
i += 9;
} else {
i += 1;
}
}
if cmd == "d" {
for g in &mut self.gains {
*g = 24.0;
}
}
true
}
pub fn gains(&self) -> &[f64] {
&self.gains
}
}