use std::convert::TryInto;
use std::collections::BTreeMap;
use crate::registers;
use crate::registers::OutputRange;
use crate::registers::ToU32s;
use crate::registers::Terminate;
use crate::registers::consts::{DACHCLUSTERMAP, SELECTORMAP};
use crate::registers::{OpCode, Empty, DACMask, ArbMask, DACVoltage, DACVoltageMask};
use crate::registers::{ChannelConf, SourceConf, ChannelState};
use crate::registers::{IOEnable, IOMask, IODir, ChanMask, Averaging};
use crate::registers::{Duration50, Address, HSDelay, DACCluster};
use crate::registers::{ClusterMask, PulseAttrs, AuxDACFn, SelectorMask};
use num_traits::FromPrimitive;
use thiserror::Error;
macro_rules! make_vec_instr_impl {
($t:ident, $f:ident, $n:expr) => {
#[doc(hidden)]
type S = Self;
fn create() -> $t {
$t { $f: Vec::with_capacity(Self::LENGTH) }
}
fn len(&self) -> usize {
self.$f.len()
}
fn push_u32s(&mut self, reg: &[u32]) {
self.$f.extend_from_slice(®);
}
fn view(&self) -> &[u32] {
&self.$f
}
fn name(&self) -> &'static str {
$n
}
}
}
macro_rules! dacvoltage {
($low: expr, $high: expr) => {
(($high as u32) << 16) | (($low as u32) & 0xFFFF)
}
}
macro_rules! dacvoltages_ok {
($low: expr, $high: expr) => {
match $low {
low if low == u16::MAX => $high >= u16::MAX - 1,
low => match $high {
high if high == u16::MAX => true,
high => low <= high + 1
}
}
}
}
#[derive(Error, Debug)]
pub enum InstructionError {
#[error("Invalid DAC composition at DAC-: {0} DAC+: {1}")]
InvalidDACComposition(u16, u16),
#[error("CREF and CSET must be both set and within 1.5 V of each other")]
InvalidCREFCSETCombination,
#[error("Selected channel is outside the maximum range of {0}")]
ChannelRangeError(usize)
}
pub trait Instruction {
#[doc(hidden)]
const LENGTH: usize = 9;
#[doc(hidden)]
const U32SIZE: usize = std::mem::size_of::<u32>();
type S: Instruction;
fn create() -> Self::S;
fn push_u32s(&mut self, reg: &[u32]);
fn len(&self) -> usize;
fn view(&self) -> &[u32];
fn name(&self) -> &'static str;
fn compile(&mut self) -> &mut Self {
if self.len() == Self::LENGTH {
return self;
}
for _ in 0..(Self::LENGTH-self.len()-1) {
self.push_register(&Empty::new());
}
for _ in 0..(Self::LENGTH-self.len()) {
self.push_register(&Terminate::new());
}
self
}
#[doc(hidden)]
fn from_registers(registers: &[&dyn ToU32s]) -> Self::S {
let mut instr = Self::create();
for reg in registers {
instr.push_u32s(®.as_u32s());
}
instr
}
fn push_register<T: ToU32s>(&mut self, register: &T) {
self.push_u32s(®ister.as_u32s());
}
fn to_bytevec(&self) -> Vec<u8> {
let cap = Self::LENGTH * Self::U32SIZE;
let mut vec: Vec<u8> = Vec::with_capacity(cap);
for num in self.view() {
vec.extend_from_slice(&num.to_le_bytes());
}
vec
}
}
pub struct ResetDAC {
instrs: Vec<u32>
}
impl ResetDAC {
pub fn new() -> Self {
Self::from_registers(&[&OpCode::SetDAC,
&DACMask::ALL,
&Empty::new(),
&DACVoltageMask::ALL,
&DACVoltage::new()])
}
}
impl Instruction for ResetDAC { make_vec_instr_impl!(ResetDAC, instrs, "RESET"); }
pub struct UpdateDAC {
instrs: Vec<u32>
}
impl UpdateDAC {
pub fn new() -> Self {
Self::from_registers(&[&OpCode::UpdateDAC])
}
}
impl Instruction for UpdateDAC { make_vec_instr_impl!(UpdateDAC, instrs, "UP DAC"); }
pub struct SetDAC {
instrs: Vec<u32>
}
impl SetDAC {
pub fn new() -> Self {
Self::from_registers(&[&OpCode::SetDAC,
&Empty::new(), &Empty::new(),
&Empty::new(), &Empty::new(),
&Empty::new(), &Empty::new(),
&Empty::new()])
}
pub fn new_all_ground() -> Self {
let mut instr = SetDAC::create();
instr.push_register(&OpCode::SetDAC);
instr.push_register(&DACMask::ALL);
instr.push_register(&Empty::new());
instr.push_register(&DACVoltageMask::ALL);
instr.push_register(&DACVoltage::new());
instr
}
pub fn new_all_at_bias(low: u16, high: u16) -> Result<Self, InstructionError> {
if !dacvoltages_ok!(low, high) {
return Err(InstructionError::InvalidDACComposition(low, high));
}
let mut instr = SetDAC::create();
instr.push_register(&OpCode::SetDAC);
instr.push_register(&DACMask::ALL);
instr.push_register(&Empty::new());
instr.push_register(&DACVoltageMask::ALL);
instr.push_register(&DACVoltage::new_at_levels(low, high));
Ok(instr)
}
pub(crate) fn new_logic(level: f32) -> (DACRange, Self) {
let range = if level > 3.81 {
OutputRange::EXT
} else {
OutputRange::STD
};
let mask = ArbMask::from_aux_channels(&[AuxDACFn::LGC]);
let dacrange = DACRange::aux_chans_at_range(&mask, &range);
let setdac = if range == OutputRange::STD {
SetDAC::for_logic(level*2.62)
} else {
SetDAC::for_logic(level*1.31)
};
(dacrange, setdac)
}
pub fn with_regs(chanmask: &DACMask, voltages: &DACVoltage, voltmask: &DACVoltageMask) ->
Result<Self, InstructionError> {
for idx in 0..voltages.len() {
let l = voltages.get_lower(idx);
let h = voltages.get_upper(idx);
if !dacvoltages_ok!(l, h) {
return Err(InstructionError::InvalidDACComposition(l, h));
}
}
Ok(SetDAC::with_regs_unchecked(chanmask, voltages, voltmask))
}
fn with_regs_unchecked(chanmask: &DACMask, voltages: &DACVoltage, voltmask: &DACVoltageMask) -> Self {
let mut instr = SetDAC::create();
instr.push_register(&OpCode::SetDAC);
instr.push_register(chanmask);
instr.push_register(&Empty::new());
instr.push_register(voltmask);
instr.push_register(voltages);
instr
}
#[deprecated(note="This will get removed once stability of the new `from_channels` is ensured")]
pub fn from_channels_old(input: &[(u16, u16, u16)], base: (u16, u16), state: &ChannelState)
-> Result<(UpdateChannel, Vec<Self>), InstructionError> {
let mut result: Vec<Self> = Vec::new();
let (low, high) = (base.0, base.1);
let mut channels: [(u16, u16); 64] = [(low, high); 64];
let mut floats = ChannelConf::new_with_state(ChannelState::Open);
let mut bucket: BTreeMap<[u32; 4], Vec<u16>> = BTreeMap::new();
let mut keys: Vec<[u32; 4]> = Vec::with_capacity(64);
for (idx, clow, chigh) in input {
channels[*idx as usize] = (*clow, *chigh);
floats.set(*idx as usize, *state);
}
for (idx, chunk) in channels.chunks(4usize).enumerate() {
let unchanged: bool = {
let mut res = true;
for (clow, chigh) in chunk {
if *clow != low || *chigh != high {
res = false;
break;
}
}
res
};
if unchanged { continue; }
let key = {
let mut res: [u32; 4] = [0x80008000; 4];
for _idx in 0..4usize {
let value = chunk[_idx];
res[_idx as usize] = dacvoltage!(value.0, value.1);
}
res
};
if bucket.contains_key(&key) {
let entry = bucket.get_mut(&key).unwrap();
entry.push(2u16.pow(idx as u32) as u16);
} else {
keys.push(key);
bucket.insert(key, vec![2u16.pow(idx as u32) as u16]);
}
}
result.push(SetDAC::new_all_at_bias(low, high)?);
for key in keys {
let bits: u32 = (*bucket.get(&key).unwrap()).iter().sum::<u16>() as u32;
let mask = DACMask::from_bits(bits).unwrap();
let voltages = DACVoltage::from_raw_values(&key);
result.push(SetDAC::with_regs(&mask, &voltages, &DACVoltageMask::ALL)?);
}
Ok((UpdateChannel::from_regs_default_source(&floats), result))
}
pub fn from_channels(input: &[(u16, u16, u16)], base: Option<(u16, u16)>,
selected_state: &ChannelState, unselected_state: &ChannelState) ->
Result<(UpdateChannel, Vec<Self>), InstructionError> {
let mut result: Vec<Self> = Vec::new();
let mut chanconf = ChannelConf::new_with_state(*unselected_state);
let mut bucket: BTreeMap<[Option<u32>; 4], DACMask> = BTreeMap::new();
let mut dacs: [Option<u32>; 64] = [None; 64];
match base {
Some((vlow, vhigh)) => {
result.push(SetDAC::new_all_at_bias(vlow, vhigh)?);
},
_ => {}
}
for (ch, clow, chigh) in input {
let idx = *ch as usize;
chanconf.set(idx, *selected_state);
dacs[idx] = Some(dacvoltage!(*clow, *chigh));
}
for (cidx, chunk) in dacs.chunks(4).enumerate() {
if cidx >= 16usize {
break;
}
if chunk.iter().all(|item| item.is_none()) {
continue;
}
let key: [Option<u32>; 4] = chunk.try_into().unwrap();
if bucket.contains_key(&key) {
let entry = bucket.get_mut(&key).unwrap();
*entry |= DACHCLUSTERMAP[cidx];
} else {
bucket.insert(key, DACHCLUSTERMAP[cidx]);
}
}
for (voltage, dacmask) in &bucket {
let voltages = DACVoltage::from_raw_values_opt(voltage);
let dacvoltagemask = DACVoltageMask::from_indices_opt(voltage);
result.push(SetDAC::with_regs(&dacmask, &voltages, &dacvoltagemask)?);
}
Ok((UpdateChannel::from_regs_default_source(&chanconf), result))
}
fn for_logic(voltage: f32) -> Self {
let mut voltages = DACVoltage::new();
let idx = AuxDACFn::LGC;
let dac_idx = (idx as usize - 8usize) / 2usize;
if idx.is_lower() {
voltages.set_lower(dac_idx, vidx!(voltage));
} else {
voltages.set_upper(dac_idx, vidx!(voltage));
}
SetDAC::with_regs_unchecked(&DACMask::AUX1, &voltages, &DACVoltageMask::ALL)
}
pub(crate) fn from_channels_aux(input: &[(AuxDACFn, f32)])
-> Result<Vec<Self>, InstructionError> {
let mut result: Vec<SetDAC> = Vec::with_capacity(4usize);
let mask = DACMask::AUX0;
let mut voltages = DACVoltage::new();
let mut cset: Option<f32> = None;
let mut cref: Option<f32> = None;
for (idx, voltage) in input {
match idx {
AuxDACFn::CSET => {
cset = Some(*voltage)
},
AuxDACFn::CREF => {
cref = Some(*voltage)
},
AuxDACFn::LGC => {
result.push(SetDAC::for_logic(*voltage));
continue;
}
_ => {}
}
let dac_idx = (*idx as usize) / 2usize;
if idx.is_lower() { voltages.set_lower(dac_idx, vidx!(*voltage));
} else { voltages.set_upper(dac_idx, vidx!(*voltage));
}
}
if !(cset.is_none() && cref.is_none()) {
let csetv = cset.ok_or(InstructionError::InvalidCREFCSETCombination)?;
let crefv = cref.ok_or(InstructionError::InvalidCREFCSETCombination)?;
if (csetv - crefv).abs() > 1.5 {
return Err(InstructionError::InvalidCREFCSETCombination);
}
}
result.push(SetDAC::with_regs_unchecked(&mask, &voltages, &DACVoltageMask::ALL));
Ok(result)
}
pub fn set_mask(&mut self, chanmask: &DACMask) {
self.instrs[1] = chanmask.as_u32s()[0];
}
pub fn set_voltages(&mut self, voltages: &DACVoltage) {
let voltages_u32 = voltages.as_u32s();
for (idx, num) in voltages_u32.iter().enumerate() {
self.instrs[idx+4] = *num;
}
}
}
impl Instruction for SetDAC { make_vec_instr_impl!(SetDAC, instrs, "LD VOLT"); }
pub struct UpdateChannel {
instrs: Vec<u32>
}
impl UpdateChannel {
pub fn new() -> Self {
Self::from_registers(&[&OpCode::UpdateChannel,
&SourceConf::new(), &Empty::new(), &Empty::new(),
&ChannelConf::new()])
}
pub fn from_regs(sourceconf: &SourceConf, chanconf: &ChannelConf) -> Self {
let mut instr = Self::create();
instr.push_register(&OpCode::UpdateChannel);
instr.push_register(sourceconf);
instr.push_register(&Empty::new());
instr.push_register(&Empty::new());
instr.push_register(chanconf);
instr
}
pub fn from_regs_default_source(chanconf: &ChannelConf) -> Self {
let mut instr = UpdateChannel::create();
instr.push_register(&OpCode::UpdateChannel);
instr.push_register(&SourceConf::new());
instr.push_register(&Empty::new());
instr.push_register(&Empty::new());
instr.push_register(chanconf);
instr
}
pub fn from_regs_global_state(state: ChannelState) -> Self {
let mut conf = ChannelConf::new();
conf.set_all(state);
Self::from_regs_default_source(&conf)
}
pub fn mask(&self, val: ChannelState) -> ChanMask {
ChannelConf::from_raw_words(&self.instrs[4..8]).mask(val)
}
}
impl Instruction for UpdateChannel { make_vec_instr_impl!(UpdateChannel, instrs, "UP CH"); }
pub struct ModifyChannel {
instrs: Vec<u32>
}
impl ModifyChannel {
pub fn new() -> Self {
Self::from_registers(&[&OpCode::ModifyChannel,
&Empty::new(), &ChanMask::new(),
&ChanMask::new(), &ChanMask::new() ])
}
pub fn from_masks(gnd: &ChanMask, capgnd: &ChanMask, cursrc: &ChanMask) -> Self {
Self::from_registers(&[&OpCode::ModifyChannel, &Empty::new(), gnd,
capgnd, cursrc])
}
}
impl Instruction for ModifyChannel { make_vec_instr_impl!(ModifyChannel, instrs, "MOD CH"); }
pub struct Delay {
instrs: Vec<u32>
}
impl Delay {
pub(crate) const MIN_NS: u128 = 320;
pub fn from_nanos(ns: u128) -> Delay {
let mut instr = Delay::create();
let actual_ns = if ns <= Self::MIN_NS {
0
} else {
ns - Self::MIN_NS
};
instr.push_register(&OpCode::Delay);
instr.push_register(&Duration50::from_nanos(actual_ns));
instr
}
pub fn from_duration(duration: &std::time::Duration) -> Delay {
Delay::from_nanos(duration.as_nanos())
}
}
impl Instruction for Delay { make_vec_instr_impl!(Delay, instrs, "DELAY"); }
pub struct UpdateLogic {
instrs: Vec<u32>
}
impl UpdateLogic {
pub fn new(output: bool, enable: bool) -> Self {
let mut mask = IOMask::new();
mask.set_enabled_all(output);
let mut en = IOEnable::new();
en.set_en(enable);
Self::with_regs(&mask, &en)
}
pub fn with_regs(iomask: &IOMask, ioenable: &IOEnable) -> Self {
let mut instr = Self::create();
instr.push_register(&OpCode::UpdateLogic);
instr.push_register(iomask);
instr.push_register(ioenable);
instr
}
pub fn with_mask(mask: &IOMask) -> Self {
let mut ioenable = IOEnable::new();
ioenable.set_en(true);
Self::with_regs(&mask, &ioenable)
}
pub fn with_directions(cl0: IODir, cl1: IODir, cl2: IODir, cl3: IODir, mask: &IOMask) -> Self {
let ioenable = IOEnable::with_iodirs(cl0, cl1, cl2, cl3);
Self::with_regs(&mask, &ioenable)
}
}
impl Instruction for UpdateLogic { make_vec_instr_impl!(UpdateLogic, instrs, "UP LGC"); }
pub struct CurrentRead {
instrs: Vec<u32>
}
impl CurrentRead {
pub fn new(channels: &ChanMask, addr: u32, flag_addr: u32, flag: u32) -> Self {
let mut instr = Self::create();
instr.push_register(&OpCode::CurrentRead);
instr.push_register(channels);
instr.push_register(&Address::new(addr));
instr.push_register(&Address::new(flag_addr));
instr.push_register(&Address::new(flag));
instr
}
}
impl Instruction for CurrentRead { make_vec_instr_impl!(CurrentRead, instrs, "C READ"); }
pub struct VoltageRead {
instrs: Vec<u32>
}
impl VoltageRead {
pub fn new(channels: &ChanMask, averaging: bool, addr: u32, flag_addr: u32, flag: u32) -> Self {
let mut instr = Self::create();
instr.push_register(&OpCode::VoltageRead);
instr.push_register(channels);
if averaging {
instr.push_register(&Averaging::Enabled);
} else {
instr.push_register(&Averaging::Disabled);
}
instr.push_register(&Address::new(addr));
instr.push_register(&Address::new(flag_addr));
instr.push_register(&Address::new(flag));
instr
}
}
impl Instruction for VoltageRead { make_vec_instr_impl!(VoltageRead, instrs, "V READ"); }
pub struct HSConfig {
instrs: Vec<u32>
}
impl HSConfig {
const MIN_DELAY: u32 = 40;
const DEAD_TIME: u32 = 10;
pub fn new(timings: [u32; 8]) -> Self {
let mut instr = Self::create();
let mut delays = HSDelay::new();
for i in 0..timings.len() {
let actual_timing = if timings[i] == 0 {
0u32
} else if timings[i] > 0 && timings[i] <= Self::MIN_DELAY {
Self::MIN_DELAY - Self::DEAD_TIME
} else {
timings[i] - Self::DEAD_TIME
};
delays.set_cluster_nanos(DACCluster::from_usize(i).unwrap(),
actual_timing as u128);
}
instr.push_register(&OpCode::HSPulseConfig);
instr.push_register(&delays);
instr
}
pub fn new_from_durations(timings: [&std::time::Duration; 8]) -> Self {
let mut delays: [u32; 8] = [0u32; 8];
for i in 0..timings.len() {
delays[i] = timings[i].as_nanos() as u32;
}
HSConfig::new(delays)
}
}
impl Instruction for HSConfig { make_vec_instr_impl!(HSConfig, instrs, "HS CONF"); }
pub struct HSPulse {
instrs: Vec<u32>
}
impl HSPulse {
pub fn new(clusters: ClusterMask) -> Self {
Self::new_from_attrs(&PulseAttrs::new(clusters))
}
pub fn new_from_cluster_idx(clusters: &[u8]) -> Self {
let clusters = ClusterMask::new_from_cluster_idx(clusters);
Self::new(clusters)
}
pub fn new_from_attrs(attrs: &PulseAttrs) -> Self {
let mut instr = Self::create();
instr.push_register(&OpCode::HSPulseStart);
instr.push_register(attrs);
instr
}
}
impl Instruction for HSPulse { make_vec_instr_impl!(HSPulse, instrs, "HS PLS"); }
pub struct UpdateSelector {
instrs: Vec<u32>
}
impl UpdateSelector {
pub fn new(channels: &SelectorMask) -> Self {
let mut instr = Self::create();
instr.push_register(&OpCode::UpdateSelector);
instr.push_register(channels);
instr
}
pub fn new_from_channels(chans: &[usize]) -> Result<Self, InstructionError> {
let maxchan: usize = registers::consts::NSELECTORS;
let mut actualchans: Vec<usize> = Vec::with_capacity(chans.len());
for c in chans {
if *c >= maxchan {
return Err(InstructionError::ChannelRangeError(maxchan));
}
actualchans.push(SELECTORMAP[*c]);
}
let mask = SelectorMask::from_channels(&actualchans);
let mut instr = Self::create();
instr.push_register(&OpCode::UpdateSelector);
instr.push_register(&mask);
Ok(instr)
}
}
impl Instruction for UpdateSelector { make_vec_instr_impl!(UpdateSelector, instrs, "UP SEL"); }
pub struct DACRange {
instrs: Vec<u32>
}
impl DACRange {
pub fn new(en_channels: &ChanMask, rng_channels: &ChanMask, en_aux_channels: &ArbMask, rng_aux_channels: &ArbMask) -> Self {
let mut instr = DACRange::create();
instr.push_register(&OpCode::DACRange);
instr.push_register(en_aux_channels);
instr.push_register(en_channels);
instr.push_register(rng_aux_channels);
instr.push_register(rng_channels);
instr
}
pub fn new_with_ranges(chans: &ChanMask, rng_chans: &OutputRange, aux_chans: &ArbMask, rng_aux_chans: &OutputRange) -> Self {
let rng_chans_actual: ChanMask;
if *rng_chans == OutputRange::STD {
rng_chans_actual = ChanMask::none();
} else {
rng_chans_actual = ChanMask::all();
}
let rng_aux_chans_actual: ArbMask;
if *rng_aux_chans == OutputRange::STD {
rng_aux_chans_actual = ArbMask::none();
} else {
rng_aux_chans_actual = ArbMask::all();
}
DACRange::new(chans, &rng_chans_actual, aux_chans, &rng_aux_chans_actual)
}
pub fn chans_at_range(chans: &ChanMask, rng: &OutputRange) -> Self {
DACRange::new_with_ranges(chans, rng, &ArbMask::none(), &OutputRange::STD)
}
pub fn aux_chans_at_range(chans: &ArbMask, rng: &OutputRange) -> Self {
DACRange::new_with_ranges(&ChanMask::none(), &OutputRange::STD, chans, rng)
}
}
impl Instruction for DACRange { make_vec_instr_impl!(DACRange, instrs, "DAC RNG"); }
pub struct AmpPrep {
instrs: Vec<u32>
}
impl AmpPrep {
pub fn new(channels: &ChanMask) -> Self {
let mut instr = Self::create();
instr.push_register(&OpCode::AmpPrep);
instr.push_register(channels);
instr
}
pub fn new_from_channels(channels: &[usize]) -> Self {
let mut instr = Self::create();
let mut mask = ChanMask::new();
for c in channels {
mask.set_enabled(*c, true);
}
instr.push_register(&OpCode::AmpPrep);
instr.push_register(&mask);
instr
}
}
impl Instruction for AmpPrep { make_vec_instr_impl!(AmpPrep, instrs, "AMP PRP"); }
pub struct Clear {
instrs: Vec<u32>
}
impl Clear {
pub fn new() -> Self {
Self::from_registers(&[&OpCode::Clear])
}
}
impl Instruction for Clear { make_vec_instr_impl!(Clear, instrs, "CLR"); }
#[cfg(test)]
mod tests {
use crate::registers::*;
use crate::instructions::*;
#[test]
fn new_reset_dac() {
let mut instr = ResetDAC::new();
assert_eq!(instr.compile().view(),
&[0x1, 0xffff, 0x0, 0xf, 0x80008000, 0x80008000, 0x80008000,
0x80008000, 0x80008000]);
assert_eq!(instr.to_bytevec(),
&[0x01, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x0F, 0x00, 0x00, 0x00,
0x00, 0x80, 0x00, 0x80,
0x00, 0x80, 0x00, 0x80,
0x00, 0x80, 0x00, 0x80,
0x00, 0x80, 0x00, 0x80,
0x00, 0x80, 0x00, 0x80]);
}
#[test]
fn new_update_dac() {
let mut instr = UpdateDAC::new();
assert_eq!(instr.compile().view(),
&[0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80008000]);
assert_eq!(instr.to_bytevec(),
&[0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x80, 0x00, 0x80]);
}
#[test]
fn new_clear() {
let mut instr = Clear::new();
assert_eq!(instr.compile().view(),
&[0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80008000]);
assert_eq!(instr.to_bytevec(),
&[0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x80, 0x00, 0x80]);
}
#[test]
fn new_set_dac_with_regs() {
let mut mask = DACMask::NONE;
mask.set_channels(&[0, 1, 2, 3, 4, 5, 6, 7]);
assert_eq!(mask, DACMask::CH00_03 | DACMask::CH04_07);
let mut voltages = DACVoltage::new();
voltages.set_upper(0, 0x8000);
voltages.set_lower( 0, 0x0000);
voltages.set_upper(1, 0x8000);
voltages.set_lower( 1, 0x8000);
voltages.set_upper(2, 0x9000);
voltages.set_lower( 2, 0x8000);
voltages.set_upper(3, 0xFFFF);
voltages.set_lower( 3, 0x9999);
assert_eq!(voltages.as_u32s(),
&[0x80000000, 0x80008000, 0x90008000, 0xFFFF9999]);
let mut instr = SetDAC::with_regs(&mask, &voltages, &DACVoltageMask::ALL).unwrap();
assert_eq!(instr.compile().view(),
&[0x1, 0x3, 0x0, 0x0000000f, 0x80000000, 0x80008000,
0x90008000, 0xFFFF9999, 0x80008000]);
assert_eq!(instr.to_bytevec(),
&[0x01, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x0f, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x80,
0x00, 0x80, 0x00, 0x80,
0x00, 0x80, 0x00, 0x90,
0x99, 0x99, 0xFF, 0xFF,
0x00, 0x80, 0x00, 0x80]);
}
#[test]
fn new_set_dac_edit_regs() {
let mut mask = DACMask::NONE;
mask.set_channels(&[0, 1, 2, 3, 4, 5, 6, 7]);
assert_eq!(mask, DACMask::CH00_03 | DACMask::CH04_07);
let mut voltages = DACVoltage::new();
voltages.set_upper(0, 0x0000);
voltages.set_lower( 0, 0x8000);
voltages.set_upper(1, 0x8000);
voltages.set_lower( 1, 0x8000);
voltages.set_upper(2, 0x8000);
voltages.set_lower( 2, 0x9000);
voltages.set_upper(3, 0x9000);
voltages.set_lower( 3, 0xFFFF);
assert_eq!(voltages.as_u32s(),
&[0x00008000, 0x80008000, 0x80009000, 0x9000FFFF]);
let mut instr = SetDAC::new();
instr.set_mask(&mask);
instr.set_voltages(&voltages);
assert_eq!(instr.compile().view(),
&[0x1, 0x3, 0x0, 0x0, 0x8000, 0x80008000,
0x80009000, 0x9000FFFF, 0x80008000]);
assert_eq!(instr.to_bytevec(),
&[0x01, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x80, 0x00, 0x00,
0x00, 0x80, 0x00, 0x80,
0x00, 0x90, 0x00, 0x80,
0xFF, 0xFF, 0x00, 0x90,
0x00, 0x80, 0x00, 0x80]);
}
#[test]
fn new_update_channel_with_regs() {
let mut chanconf = ChannelConf::new();
chanconf.set_all(ChannelState::VoltArb);
let sourceconf = SourceConf::new();
let mut instr = UpdateChannel::from_regs(&sourceconf, &chanconf);
assert_eq!(instr.compile().view(), &[0x40, 0x73400000,
0x00000000, 0x00000000, 0xaaaaaaaa, 0xaaaaaaaa,
0xaaaaaaaa, 0xaaaaaaaa, 0x80008000]);
assert_eq!(instr.to_bytevec(),
&[0x40, 0x00, 0x00, 0x00,
0x00, 0x00, 0x40, 0x73,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa,
0x00, 0x80, 0x00, 0x80]);
}
#[test]
fn new_update_logic() {
let mut instr = UpdateLogic::new(true, true);
assert_eq!(instr.compile().view(),
&[0x20, 0xffffffff, 0xf, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80008000]);
assert_eq!(instr.to_bytevec(),
&[0x20, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff,
0x0f, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x80, 0x00, 0x80]);
}
#[test]
fn new_current_read() {
let mut mask = ChanMask::new();
mask.set_enabled(31, true);
mask.set_enabled(0, true);
mask.set_enabled(62, true);
let mut instr = CurrentRead::new(&mask, 0x60000000, 0x78000000, 0xcafebabe);
assert_eq!(instr.compile().view(), &[0x4, 0x40000000, 0x80000001,
0x60000000, 0x78000000, 0xcafebabe, 0x0, 0x0, 0x80008000]);
assert_eq!(instr.to_bytevec(),
&[0x04, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x40,
0x01, 0x00, 0x00, 0x80,
0x00, 0x00, 0x00, 0x60,
0x00, 0x00, 0x00, 0x78,
0xbe, 0xba, 0xfe, 0xca,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x80, 0x00, 0x80]);
}
#[test]
fn new_voltage_read() {
let mut mask = ChanMask::new();
mask.set_enabled(31, true);
mask.set_enabled(0, true);
mask.set_enabled(62, true);
let mut instr = VoltageRead::new(&mask, true, 0x60000000, 0x78000000, 0xcafebabe);
assert_eq!(instr.compile().view(), &[0x8, 0x40000000, 0x80000001,
0x1, 0x60000000, 0x78000000, 0xcafebabe, 0x0, 0x80008000]);
assert_eq!(instr.to_bytevec(),
&[0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x40,
0x01, 0x00, 0x00, 0x80,
0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x60,
0x00, 0x00, 0x00, 0x78,
0xbe, 0xba, 0xfe, 0xca,
0x00, 0x00, 0x00, 0x00,
0x00, 0x80, 0x00, 0x80]);
}
}