use std::collections::HashMap;
use std::time::Duration;
use consts::{AUXFNRNGMAP, LGCRNGIDX};
use num_derive::{FromPrimitive, ToPrimitive};
use bitvec::prelude::*;
use bitflags::bitflags;
use num_traits::{ToPrimitive, FromPrimitive};
use thiserror::Error;
use std::ops::{BitAnd, BitXor, BitOr, Not};
use std::iter::zip;
mod wordreg {
pub trait WordSize {
const WORDS: usize;
}
#[derive(Clone, Debug, PartialEq)]
pub struct Wx1;
impl WordSize for Wx1 {
const WORDS: usize = 1;
}
#[derive(Clone, Debug, PartialEq)]
pub struct Wx2;
impl WordSize for Wx2 {
const WORDS: usize = 2;
}
#[derive(Clone, Debug, PartialEq)]
pub struct Wx3;
impl WordSize for Wx3 {
const WORDS: usize = 3;
}
#[derive(Clone, Debug, PartialEq)]
pub struct Wx4;
impl WordSize for Wx4 {
const WORDS: usize = 4;
}
#[derive(Clone, Debug, PartialEq)]
pub struct Wx5;
impl WordSize for Wx5 {
const WORDS: usize = 5;
}
#[derive(Clone, Debug, PartialEq)]
pub struct Wx6;
impl WordSize for Wx6 {
const WORDS: usize = 6;
}
#[derive(Clone, Debug, PartialEq)]
pub struct Wx7;
impl WordSize for Wx7 {
const WORDS: usize = 7;
}
}
use wordreg::WordSize;
pub(crate) mod consts {
use super::DACMask;
use super::ClusterMask;
pub(crate) const CHANMAP: [DACMask; 64] = [
DACMask::CH00_03, DACMask::CH00_03, DACMask::CH00_03, DACMask::CH00_03,
DACMask::CH04_07, DACMask::CH04_07, DACMask::CH04_07, DACMask::CH04_07,
DACMask::CH08_11, DACMask::CH08_11, DACMask::CH08_11, DACMask::CH08_11,
DACMask::CH12_15, DACMask::CH12_15, DACMask::CH12_15, DACMask::CH12_15,
DACMask::CH16_19, DACMask::CH16_19, DACMask::CH16_19, DACMask::CH16_19,
DACMask::CH20_23, DACMask::CH20_23, DACMask::CH20_23, DACMask::CH20_23,
DACMask::CH24_27, DACMask::CH24_27, DACMask::CH24_27, DACMask::CH24_27,
DACMask::CH28_31, DACMask::CH28_31, DACMask::CH28_31, DACMask::CH28_31,
DACMask::CH32_35, DACMask::CH32_35, DACMask::CH32_35, DACMask::CH32_35,
DACMask::CH36_39, DACMask::CH36_39, DACMask::CH36_39, DACMask::CH36_39,
DACMask::CH40_43, DACMask::CH40_43, DACMask::CH40_43, DACMask::CH40_43,
DACMask::CH44_47, DACMask::CH44_47, DACMask::CH44_47, DACMask::CH44_47,
DACMask::CH48_51, DACMask::CH48_51, DACMask::CH48_51, DACMask::CH48_51,
DACMask::CH52_55, DACMask::CH52_55, DACMask::CH52_55, DACMask::CH52_55,
DACMask::CH56_59, DACMask::CH56_59, DACMask::CH56_59, DACMask::CH56_59,
DACMask::CH60_63, DACMask::CH60_63, DACMask::CH60_63, DACMask::CH60_63
];
pub(crate) const DACHCLUSTERMAP: [DACMask; 16] = [
DACMask::CH00_03, DACMask::CH04_07, DACMask::CH08_11, DACMask::CH12_15,
DACMask::CH16_19, DACMask::CH20_23, DACMask::CH24_27, DACMask::CH28_31,
DACMask::CH32_35, DACMask::CH36_39, DACMask::CH40_43, DACMask::CH44_47,
DACMask::CH48_51, DACMask::CH52_55, DACMask::CH56_59, DACMask::CH60_63,
];
pub(crate) const HSCLUSTERMAP: [ClusterMask; 8] = [
ClusterMask::CL0,
ClusterMask::CL1,
ClusterMask::CL2,
ClusterMask::CL3,
ClusterMask::CL4,
ClusterMask::CL5,
ClusterMask::CL6,
ClusterMask::CL7,
];
pub(crate) const AUXFNRNGMAP: [usize; 8] = [
1, 0, 3, 2, 5, 4, 7, 6
];
pub(crate) const LGCRNGIDX: usize = 11;
pub(crate) const SELECTORMAP: [usize; 32] = [
4, 5, 6, 7, 3, 2, 1, 0, 12, 13, 14, 15, 11, 10, 9, 8,
16, 17, 18, 19, 23, 22, 21, 20, 24, 25, 26, 27, 31, 30, 29, 28
];
pub(super) const CHANCONFSIZE: usize = 2;
pub(super) const AUXNCHANS: usize = 16;
pub(super) const NCHANS: usize = 64;
pub(crate) const NSELECTORS: usize = 32;
}
#[derive(Error, Debug)]
pub(crate) enum Error {
#[error("Supplied slice is too small")]
SliceTooSmall
}
pub trait ToU32s {
fn as_u32s(&self) -> Vec<u32>;
}
#[derive(Clone, Copy, FromPrimitive, ToPrimitive)]
#[repr(u32)]
pub enum OpCode {
SetDAC = 0x00000001,
UpdateDAC = 0x00000002,
CurrentRead = 0x00000004,
VoltageRead = 0x00000008,
UpdateSelector = 0x00000010,
UpdateLogic = 0x00000020,
UpdateChannel = 0x00000040,
Clear = 0x00000080,
HSPulseConfig = 0x00000100,
HSPulseStart = 0x00000200,
ModifyChannel = 0x00000400,
SetDACOffset = 0x00001000,
Delay = 0x00002000,
DACRange = 0x00004000,
AmpPrep = 0x00010000
}
impl ToU32s for OpCode {
fn as_u32s(&self) -> Vec<u32> {
[*self as u32].to_vec()
}
}
#[derive(PartialEq, Clone, Copy, FromPrimitive, ToPrimitive)]
#[repr(usize)]
pub enum AuxDACFn {
SELL = 0,
SELH = 1,
ARB4 = 2,
ARB3 = 3,
ARB1 = 4,
ARB2 = 5,
CREF = 6,
CSET = 7,
LGC = 10
}
impl AuxDACFn {
pub(crate) fn is_lower(&self) -> bool {
(*self as usize) % 2 != 0
}
}
#[derive(Copy, Clone, Eq)]
pub struct OutputRange(bool);
impl OutputRange {
pub const STD: OutputRange = Self(false);
pub const EXT: OutputRange = Self(true);
}
impl PartialEq for OutputRange {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl PartialEq<bool> for OutputRange {
fn eq(&self, other: &bool) -> bool {
self.0 == *other
}
}
pub struct Empty(u32);
impl Empty {
pub fn new() -> Empty {
Empty(0x0)
}
}
impl ToU32s for Empty {
fn as_u32s(&self) -> Vec<u32> {
[self.0].to_vec()
}
}
pub struct Terminate(u32);
impl Terminate {
pub fn new() -> Terminate {
Terminate(0x80008000)
}
}
impl ToU32s for Terminate {
fn as_u32s(&self) -> Vec<u32> {
[self.0].to_vec()
}
}
pub struct Duration50(u32);
impl Duration50 {
const MAX_DURATION_NS: u128 = 20u128 * (std::u32::MAX as u128);
pub fn from_nanos(ns: u128) -> Duration50 {
if ns > Self::MAX_DURATION_NS {
Duration50(std::u32::MAX)
} else {
Duration50((ns / 20) as u32)
}
}
pub fn from_duration(duration: &std::time::Duration) -> Duration50 {
Duration50::from_nanos(duration.as_nanos())
}
}
impl ToU32s for Duration50 {
fn as_u32s(&self) -> Vec<u32> {
[self.0].to_vec()
}
}
#[derive(Clone, Copy, FromPrimitive, ToPrimitive, Debug)]
#[repr(usize)]
pub enum DACCluster {
CL0 = 0,
CL1 = 1,
CL2 = 2,
CL3 = 3,
CL4 = 4,
CL5 = 5,
CL6 = 6,
CL7 = 7
}
bitflags! {
pub struct ClusterMask: u8 {
const NONE = 0b00000000;
const CL0 = 0b00000001;
const CL1 = 0b00000010;
const CL2 = 0b00000100;
const CL3 = 0b00001000;
const CL4 = 0b00010000;
const CL5 = 0b00100000;
const CL6 = 0b01000000;
const CL7 = 0b10000000;
const ALL = Self::CL0.bits | Self::CL1.bits | Self::CL2.bits |
Self::CL3.bits | Self::CL4.bits | Self::CL5.bits |
Self::CL6.bits | Self::CL7.bits;
}
}
impl ClusterMask {
pub fn new_from_cluster_idx(clusters: &[u8]) -> Self {
let mut mask = ClusterMask::NONE;
for cl in clusters {
mask |= consts::HSCLUSTERMAP[*cl as usize];
}
mask
}
}
pub struct HSDelay {
bits: BitVec<u32, Msb0>
}
impl HSDelay {
const RESOLUTION: u128 = 10u128;
const MAX_DELAY: u128 = Self::RESOLUTION * 2u128.pow(28);
const CLUSTERS: usize = 8;
const CLUSTSIZE: usize = 28;
#[doc(hidden)]
fn steps_to_bools(val: u32) -> [bool; Self::CLUSTSIZE] {
let mut bools: [bool; Self::CLUSTSIZE] = [false; Self::CLUSTSIZE];
for i in 0..Self::CLUSTSIZE {
bools[i] = ( (val as u32 >> i) & 1 ) == 1
}
bools
}
pub fn new() -> HSDelay {
HSDelay { bits: BitVec::repeat(false, Self::CLUSTERS*Self::CLUSTSIZE) }
}
pub fn set_cluster_nanos(&mut self, cluster: DACCluster, val: u128) {
let steps = if val > Self::MAX_DELAY {
Self::MAX_DELAY / Self::RESOLUTION
} else {
val / Self::RESOLUTION
} as u32;
let bools = HSDelay::steps_to_bools(steps);
let bits = self.bits.as_mut_bitslice();
let cluster = cluster as usize;
for i in 0..bools.len() {
bits.set(Self::CLUSTSIZE*(Self::CLUSTERS-1-cluster) + i,
bools[Self::CLUSTSIZE - 1 - i]);
}
}
pub fn set_cluster_from_duration(&mut self, cluster: DACCluster, val: &Duration) {
self.set_cluster_nanos(cluster, val.as_nanos());
}
}
impl ToU32s for HSDelay {
fn as_u32s(&self) -> Vec<u32> {
self.bits.as_raw_slice().to_vec()
}
}
pub struct PulseAttrs {
cluster: ClusterMask,
polarity: ClusterMask,
cancel: ClusterMask
}
impl PulseAttrs {
pub fn new(clusters: ClusterMask) -> Self {
Self::new_with_params(clusters, ClusterMask::NONE, ClusterMask::NONE)
}
pub fn new_with_params(clusters: ClusterMask, polarity: ClusterMask, cancel: ClusterMask) -> Self {
PulseAttrs {
cluster: clusters,
polarity: polarity,
cancel: cancel
}
}
}
impl ToU32s for PulseAttrs {
fn as_u32s(&self) -> Vec<u32> {
let value = u32::from_be_bytes([0x00,
self.cluster.bits(),
self.polarity.bits(),
self.cancel.bits()]);
[value].to_vec()
}
}
#[derive(FromPrimitive, ToPrimitive)]
pub struct Address(u32);
impl Address {
pub fn new(addr: u32) -> Address {
Address::from_u32(addr).unwrap()
}
}
impl ToU32s for Address {
fn as_u32s(&self) -> Vec<u32> {
[self.0].to_vec()
}
}
bitflags! {
pub struct DACMask: u32 {
const NONE = 0b00000000000000000000000000000000;
const CH00_03 = 0b00000000000000000000000000000001;
const CH04_07 = 0b00000000000000000000000000000010;
const CH08_11 = 0b00000000000000000000000000000100;
const CH12_15 = 0b00000000000000000000000000001000;
const CH16_19 = 0b00000000000000000000000000010000;
const CH20_23 = 0b00000000000000000000000000100000;
const CH24_27 = 0b00000000000000000000000001000000;
const CH28_31 = 0b00000000000000000000000010000000;
const CH32_35 = 0b00000000000000000000000100000000;
const CH36_39 = 0b00000000000000000000001000000000;
const CH40_43 = 0b00000000000000000000010000000000;
const CH44_47 = 0b00000000000000000000100000000000;
const CH48_51 = 0b00000000000000000001000000000000;
const CH52_55 = 0b00000000000000000010000000000000;
const CH56_59 = 0b00000000000000000100000000000000;
const CH60_63 = 0b00000000000000001000000000000000;
const AUX0 = 0b00000000000000010000000000000000;
const AUX1 = 0b00000000000000100000000000000000;
const DAC0 = Self::CH00_03.bits | Self::CH04_07.bits;
const DAC1 = Self::CH08_11.bits | Self::CH12_15.bits;
const DAC2 = Self::CH16_19.bits | Self::CH20_23.bits;
const DAC3 = Self::CH24_27.bits | Self::CH28_31.bits;
const DAC4 = Self::CH32_35.bits | Self::CH36_39.bits;
const DAC5 = Self::CH40_43.bits | Self::CH44_47.bits;
const DAC6 = Self::CH48_51.bits | Self::CH52_55.bits;
const DAC7 = Self::CH56_59.bits | Self::CH60_63.bits;
const ALL = Self::CH00_03.bits | Self::CH04_07.bits |
Self::CH08_11.bits | Self::CH12_15.bits |
Self::CH16_19.bits | Self::CH20_23.bits |
Self::CH24_27.bits | Self::CH28_31.bits |
Self::CH32_35.bits | Self::CH36_39.bits |
Self::CH40_43.bits | Self::CH44_47.bits |
Self::CH48_51.bits | Self::CH52_55.bits |
Self::CH56_59.bits | Self::CH60_63.bits;
}
}
impl DACMask {
pub fn set_channel(&mut self, chan: usize) {
self.set_channels(&[chan]);
}
pub fn unset_channel(&mut self, chan: usize) {
self.unset_channels(&[chan]);
}
pub fn set_channels(&mut self, chans: &[usize]) {
for c in chans {
*self |= consts::CHANMAP[*c];
}
}
pub fn unset_channels(&mut self, chans: &[usize]) {
for c in chans {
*self &= !consts::CHANMAP[*c];
}
}
pub fn clear(&mut self) {
self.bits = 0;
}
}
impl From<&DACMask> for u32 {
fn from(clusters: &DACMask) -> u32 {
clusters.bits() as u32
}
}
impl ToU32s for DACMask {
fn as_u32s(&self) -> Vec<u32> {
[u32::from(self)].to_vec()
}
}
#[cfg(test)]
mod dacmask_tests {
use super::DACMask;
#[test]
fn test_dac_mask() {
let mut clusters = DACMask::NONE;
clusters.set_channels(&[2, 3, 50, 61]);
assert_eq!(clusters, DACMask::CH00_03 | DACMask::CH48_51 |
DACMask::CH60_63);
assert_eq!(u32::from(&clusters), 0x00009001);
clusters.set_channel(12);
assert_eq!(clusters, DACMask::CH00_03 | DACMask::CH12_15 |
DACMask::CH48_51 | DACMask::CH60_63);
assert_eq!(u32::from(&clusters), 0x00009009);
clusters.unset_channel(61);
assert_eq!(clusters, DACMask::CH00_03 | DACMask::CH12_15 |
DACMask::CH48_51);
assert_eq!(u32::from(&clusters), 0x00001009);
clusters.clear();
assert_eq!(clusters, DACMask::NONE);
assert_eq!(u32::from(&clusters), 0x0);
}
}
#[derive(Clone, PartialEq, Copy, FromPrimitive, Debug)]
#[repr(u8)]
pub enum ChannelState {
Maintain = 0b00,
Open = 0b01,
VoltArb = 0b10,
HiSpeed = 0b11,
}
impl ChannelState {
fn as_bools(&self) -> [bool; consts::CHANCONFSIZE] {
let mut bools: [bool; consts::CHANCONFSIZE] = [false; consts::CHANCONFSIZE];
for i in 0..consts::CHANCONFSIZE {
bools[i] = ((*self as u8 >> i) & 1) == 1
}
bools
}
fn from_bools(bools: &[bool; consts::CHANCONFSIZE]) -> ChannelState {
let mut bitarr = bitarr![u8, Msb0; 0; 8];
for i in 0..consts::CHANCONFSIZE {
bitarr.set(8-consts::CHANCONFSIZE+i, bools[i])
}
let value: &[u8] = bitarr.as_raw_slice();
ChannelState::from_u8(value[0] as u8).unwrap()
}
fn from_bitslice(bools: &BitSlice<u32, Msb0>) -> Result<ChannelState, Error> {
let len: usize;
if bools.len() < consts::CHANCONFSIZE {
return Err(Error::SliceTooSmall);
}
if bools.len() > 8 {
len = 8;
} else {
len = bools.len()
}
let mut bitarr = bitarr![u8, Msb0; 0; 8];
for i in 0..len {
bitarr.set(8-len+i, bools[i])
}
let value: &[u8] = bitarr.as_raw_slice();
Ok(ChannelState::from_u8(value[0] as u8).unwrap())
}
}
impl From<&[bool; consts::CHANCONFSIZE]> for ChannelState {
fn from(bools: &[bool; consts::CHANCONFSIZE]) -> ChannelState {
ChannelState::from_bools(&bools)
}
}
pub struct ChannelConf {
bits: BitVec<u32, Msb0>,
}
impl ChannelConf {
pub fn new() -> ChannelConf {
let size = consts::NCHANS * consts::CHANCONFSIZE;
let vec: BitVec<u32, Msb0> = BitVec::repeat(false, size);
ChannelConf { bits: vec }
}
pub fn new_with_state(state: ChannelState) -> ChannelConf {
let mut conf = ChannelConf::new();
conf.set_all(state);
conf
}
#[doc(hidden)]
pub(crate) fn from_raw_words(words: &[u32]) -> ChannelConf {
let size = consts::NCHANS * consts::CHANCONFSIZE;
let mut vec: BitVec<u32, Msb0> = BitVec::with_capacity(size);
vec.extend_from_raw_slice(words);
ChannelConf { bits: vec }
}
pub fn set(&mut self, idx: usize, val: ChannelState) {
let bits = self.bits.as_mut_bitslice();
let bools = val.as_bools();
for i in 0..bools.len() {
let bitidx = consts::NCHANS*consts::CHANCONFSIZE -
(consts::CHANCONFSIZE*idx+i) - 1;
bits.set(bitidx, bools[i]);
}
}
pub fn get(&self, idx: usize) -> ChannelState {
let from = consts::NCHANS*consts::CHANCONFSIZE - (consts::CHANCONFSIZE*idx+1) - 1;
let to = consts::NCHANS*consts::CHANCONFSIZE - (consts::CHANCONFSIZE*(idx));
let v = &self.bits[from..to];
ChannelState::from_bitslice(v).unwrap()
}
pub fn len(&self) -> usize {
self.bits.len() / consts::CHANCONFSIZE
}
pub fn set_all(&mut self, val: ChannelState) {
let nchannels = self.len();
for i in 0..nchannels {
self.set(i, val);
}
}
pub(crate) fn mask(&self, val: ChannelState) -> ChanMask {
let mut mask = ChanMask::none();
for idx in 0..consts::NCHANS {
if self.get(idx) == val {
mask.set_enabled(idx, true);
}
}
mask
}
pub fn as_slice(&self) -> &[u32] {
self.bits.as_raw_slice()
}
}
impl ToU32s for ChannelConf {
fn as_u32s(&self) -> Vec<u32> {
let bits = self.bits.as_raw_slice();
bits.to_vec()
}
}
#[doc(hidden)]
pub struct ChannelConfIterator<'a> {
register: &'a ChannelConf,
index: usize,
}
impl<'a> IntoIterator for &'a ChannelConf {
type Item = ChannelState;
type IntoIter = ChannelConfIterator<'a>;
fn into_iter(self) -> Self::IntoIter {
ChannelConfIterator {
register: self,
index: 0,
}
}
}
impl<'a> Iterator for ChannelConfIterator<'a> {
type Item = ChannelState;
fn next(&mut self) -> Option<ChannelState> {
if self.index >= self.register.len() {
return None;
}
let v = self.register.get(self.index);
self.index += 1;
Some(v)
}
}
#[cfg(test)]
mod channelconf_tests {
use super::{ChannelConf, ChannelState};
use crate::registers::ToU32s;
use assert_matches::assert_matches;
#[test]
fn get_channel() {
let mut v = ChannelConf::new();
v.set(50, ChannelState::VoltArb);
let res = v.get(50);
assert_matches!(res, ChannelState::VoltArb);
v.set(0, ChannelState::Open);
let res = v.get(0);
assert_matches!(res, ChannelState::Open);
v.set(63, ChannelState::HiSpeed);
let res = v.get(63);
assert_matches!(res, ChannelState::HiSpeed);
}
#[test]
fn channel_len() {
let v = ChannelConf::new();
assert_eq!(v.len(), 64);
}
#[test]
fn bools_to_status() {
let status1 = ChannelState::from(&[true, false]);
assert_matches!(status1, ChannelState::VoltArb);
let status2 = ChannelState::from(&[false, true]);
assert_matches!(status2, ChannelState::Open);
}
#[test]
fn all_channel_test() {
let mut v = ChannelConf::new();
v.set_all(ChannelState::VoltArb);
for channel in &v {
assert_matches!(channel, ChannelState::VoltArb);
}
let slice = v.as_u32s();
assert_eq!(slice[0], 0xaaaaaaaa);
assert_eq!(slice[1], 0xaaaaaaaa);
assert_eq!(slice[2], 0xaaaaaaaa);
assert_eq!(slice[3], 0xaaaaaaaa);
}
#[test]
fn new_all_channels() {
let v = ChannelConf::new_with_state(ChannelState::VoltArb);
for channel in &v {
assert_matches!(channel, ChannelState::VoltArb);
}
let slice = v.as_u32s();
assert_eq!(slice[0], 0xaaaaaaaa);
assert_eq!(slice[1], 0xaaaaaaaa);
assert_eq!(slice[2], 0xaaaaaaaa);
assert_eq!(slice[3], 0xaaaaaaaa);
}
}
bitflags! {
pub struct CurrentSourceResistor: u8 {
const R220K = 0b01000000;
const R3_6M = 0b00100000;
const R68M = 0b00010000;
const R51 = 0b00000100;
const RDIGI = 0b00000010;
}
}
lazy_static! {
static ref FIXED_RESISTORS: HashMap<CurrentSourceResistor, f32> = {
let mut map: HashMap<CurrentSourceResistor, f32> = HashMap::new();
map.insert(CurrentSourceResistor::R220K, 220e3);
map.insert(CurrentSourceResistor::R3_6M, 3.6e6);
map.insert(CurrentSourceResistor::R68M, 68e6);
map.insert(CurrentSourceResistor::R51, 51.0);
map
};
}
impl CurrentSourceResistor {
fn value(self) -> Option<f32> {
FIXED_RESISTORS.get(&self).copied()
}
}
#[derive(Clone, Copy, FromPrimitive, ToPrimitive, PartialEq, Debug)]
#[repr(u8)]
pub enum CurrentSourceMOSFET {
NMOS = 0b10000000,
PMOS = 0b00001000
}
#[derive(Debug)]
#[repr(transparent)]
pub struct CurrentSourceState(u8);
impl CurrentSourceState {
pub fn vref() -> CurrentSourceState {
CurrentSourceState(0b10000001)
}
pub fn mos_with_resistors(mos: CurrentSourceMOSFET, res: CurrentSourceResistor)
-> CurrentSourceState {
let mut val: u8 = mos.to_u8().unwrap();
val |= res.bits();
CurrentSourceState(val)
}
pub fn to_u8(self) -> u8 {
self.0
}
pub fn get_mos(self) -> Option<CurrentSourceMOSFET> {
if (self.0 & CurrentSourceMOSFET::NMOS.to_u8().unwrap()) > 0 {
Some(CurrentSourceMOSFET::NMOS)
} else if (self.0 & CurrentSourceMOSFET::PMOS.to_u8().unwrap()) > 0 {
Some(CurrentSourceMOSFET::PMOS)
} else {
None
}
}
pub fn get_selected_resistors(self) -> Option<CurrentSourceResistor> {
let v: u8 = self.0 & 0b01110110;
if v == 0 {
None
} else {
Some(CurrentSourceResistor { bits: v })
}
}
}
pub struct SourceConf {
bits: BitVec<u32, Msb0>
}
impl SourceConf {
pub fn new() -> SourceConf {
let mut vec: BitVec<u32, Msb0> = BitVec::repeat(false, 32);
let bits = vec.as_mut_bitslice();
bits[0..10].store(0x1CD as u16);
SourceConf { bits: vec }
}
pub fn set_digipot(&mut self, val: u16) {
let actual_val;
if val > 0x3ff {
actual_val = 0x3ff;
} else {
actual_val = val;
}
let bits = self.bits.as_mut_bitslice();
bits[0..10].store(actual_val);
}
pub fn get_digipot(&self) -> u16 {
self.bits[0..10].load()
}
pub fn set_cursource_state(&mut self, val: CurrentSourceState) {
self.bits[24..32].store(val.to_u8());
}
pub fn get_cursource_state(&self) -> CurrentSourceState {
let val = self.bits[24..32].load::<u8>();
CurrentSourceState(val)
}
fn _find_digipot_and_voltage(current: f32) -> Option<(f32, f32)> {
let mut voltage: f32 = 1.0;
let acurrent = current.abs();
while voltage > 0.049 {
let res = voltage / acurrent;
if res < 19500.0 && res > 670.0 {
return Some((voltage, res));
}
voltage -= 0.05;
}
None
}
pub fn for_current(current: f32) -> Option<(SourceConf, f32)> {
let mut sourceconf = SourceConf::new();
let mosfet = if current > 0.0 {
CurrentSourceMOSFET::NMOS
} else {
CurrentSourceMOSFET::PMOS
};
for res in &[CurrentSourceResistor::R51, CurrentSourceResistor::R220K,
CurrentSourceResistor::R3_6M, CurrentSourceResistor::R68M] {
let voltage = res.value().unwrap() * current.abs();
if voltage > 0.05 && voltage <= 1.0 {
let state = CurrentSourceState::mos_with_resistors(mosfet, *res);
sourceconf.set_cursource_state(state);
return Some((sourceconf, voltage));
}
}
match Self::_find_digipot_and_voltage(current) {
Some ((resistance, voltage)) => {
let code = (1024.0*(1.0 - resistance/20000.0)).floor() as u16;
let state = CurrentSourceState::mos_with_resistors(mosfet,
CurrentSourceResistor::RDIGI);
sourceconf.set_digipot(code);
sourceconf.set_cursource_state(state);
Some((sourceconf, voltage))
}
None => None
}
}
}
impl ToU32s for SourceConf {
fn as_u32s(&self) -> Vec<u32> {
let bits = self.bits.as_raw_slice();
bits.to_vec()
}
}
#[cfg(test)]
mod sourceconftests {
use super::{SourceConf, ToU32s};
#[test]
fn test_sourceconf() {
let mut c = SourceConf::new();
c.set_digipot(0x200);
assert_eq!(c.get_digipot(), 0x200);
let slice = c.as_u32s();
assert_eq!(slice[0], 0x80000000);
c.set_digipot(0x500);
assert_eq!(c.get_digipot(), 0x3ff);
}
}
const DACVZERO: u32 = 0x80008000;
pub struct DACVoltage {
values: Vec<u32>
}
impl DACVoltage {
const NUMVOLTAGES: usize = 4;
pub fn new() -> DACVoltage {
Self::new_with_size_and_voltage(Self::NUMVOLTAGES, DACVZERO)
}
pub fn new_at_levels(low: u16, high: u16) -> DACVoltage {
let voltage: u32 =
((high as u32) << 16) | ((low as u32) & 0xFFFF);
Self::new_with_size_and_voltage(4, voltage)
}
fn new_with_size_and_voltage(size: usize, volt: u32) -> DACVoltage {
let mut vec: Vec<u32> = Vec::with_capacity(size);
for _ in 0..size {
vec.push(volt);
}
DACVoltage { values: vec }
}
pub(crate) fn from_raw_values(values: &[u32]) -> DACVoltage {
DACVoltage { values: values.to_vec() }
}
pub(crate) fn from_raw_values_opt(values: &[Option<u32>]) -> DACVoltage {
let mut raw_values = Vec::with_capacity(Self::NUMVOLTAGES);
for value in values {
let raw = match value {
Some(v) => *v,
None => DACVZERO
};
raw_values.push(raw);
}
DACVoltage { values: raw_values }
}
pub fn set_upper(&mut self, idx: usize, voltage: u16) {
self.values[idx] = (voltage as u32) << 16 |
(self.values[idx] & 0xFFFF);
}
pub fn get_upper(&self, idx: usize) -> u16 {
((self.values[idx] & 0xFFFF0000) >> 16) as u16
}
pub fn set_lower(&mut self, idx: usize, voltage: u16) {
self.values[idx] = (voltage as u32) << 0 |
(self.values[idx] & 0xFFFF0000);
}
pub fn get_lower(&self, idx: usize) -> u16 {
(self.values[idx] & 0xFFFF) as u16
}
pub fn set(&mut self, idx: usize, voltage: u16) {
self.set_lower(idx, voltage);
self.set_upper(idx, voltage);
}
pub fn get(&self, idx: usize) -> (u16, u16) {
(self.get_lower(idx), self.get_upper(idx))
}
pub fn len(&self) -> usize {
Self::NUMVOLTAGES
}
}
impl ToU32s for DACVoltage {
fn as_u32s(&self) -> Vec<u32> {
self.values.clone()
}
}
#[cfg(test)]
mod dacvoltage_tests {
use super::{DACVoltage};
#[test]
fn dacvoltage_new() {
let v = DACVoltage::new();
for value in v.values {
assert_eq!(value, 0x80008000);
}
}
#[test]
fn dacvoltage_set_upper() {
let mut v = DACVoltage::new();
v.set_upper(3, 0xA0A0);
assert_eq!(v.values[3], 0xA0A08000);
assert_eq!(v.get_upper(3), 0xA0A0);
assert_eq!(v.get_lower(3), 0x8000);
}
#[test]
fn dacvoltage_set_lower() {
let mut v = DACVoltage::new();
v.set_lower(2, 0x90F3);
assert_eq!(v.values[2], 0x800090F3);
assert_eq!(v.get_upper(2), 0x8000);
assert_eq!(v.get_lower(2), 0x90F3);
}
#[test]
fn dacvoltage_set_both() {
let mut v = DACVoltage::new();
v.set(1, 0x8534);
assert_eq!(v.values[1], 0x85348534);
assert_eq!(v.get_lower(1), 0x8534);
assert_eq!(v.get_upper(1), 0x8534);
assert_eq!(v.get(1), (0x8534, 0x8534));
}
}
bitflags! {
pub struct DACVoltageMask: u32 {
const NONE = 0b00000000000000000000000000000000;
const CH0 = 0b00000000000000000000000000001000;
const CH1 = 0b00000000000000000000000000000100;
const CH2 = 0b00000000000000000000000000000010;
const CH3 = 0b00000000000000000000000000000001;
const ALL = Self::CH0.bits | Self::CH1.bits |
Self::CH2.bits | Self::CH3.bits;
}
}
impl DACVoltageMask {
const ALL_MASKS: [Self; 4] = [Self::CH0, Self::CH1, Self::CH2, Self::CH3];
pub(crate) fn from_indices(indices: &[usize]) -> Self {
let mut mask = Self::NONE;
for idx in indices {
if *idx >= 4 {
break;
}
mask |= Self::ALL_MASKS[*idx]
}
mask
}
pub(crate) fn from_indices_opt<T>(voltages: &[Option<T>]) -> Self {
let mut mask = Self::NONE;
for (idx, smth) in voltages.iter().enumerate() {
if idx >=4 {
break;
}
if smth.is_some() {
mask |= Self::ALL_MASKS[idx];
}
}
mask
}
}
impl From<&DACVoltageMask> for u32 {
fn from(mask: &DACVoltageMask) -> u32 {
mask.bits() as u32
}
}
impl ToU32s for DACVoltageMask {
fn as_u32s(&self) -> Vec<u32> {
[u32::from(self)].to_vec()
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct U32Mask<T> {
_words: T,
bits: BitVec<u32, Msb0>,
}
impl<T: wordreg::WordSize> U32Mask<T> {
pub fn set_enabled(&mut self, idx: usize, status: bool) {
let len = self.bits.len();
let bits = self.bits.as_mut_bitslice();
bits.set(len-1-idx, status)
}
pub fn get_enabled(&self, idx: usize) -> bool {
let len = self.bits.len();
self.bits[len-1-idx]
}
pub fn len(&self) -> usize {
self.bits.len()
}
pub fn set_enabled_all(&mut self, status: bool) {
let len = self.bits.len();
let bits = self.bits.as_mut_bitslice();
for i in 0..len {
bits.set(len-1-i, status)
}
}
pub fn toggle(&mut self, idx: usize) {
self.set_enabled(idx, !self.get_enabled(idx));
}
pub fn as_slice(&self) -> &[u32] {
self.bits.as_raw_slice()
}
}
macro_rules! make_from_values_impl {
($ws:ty, $wx:expr) => {
#[allow(dead_code)]
pub(crate) fn from_bitvec(vec: BitVec<u32, Msb0>) -> U32Mask<$ws> {
U32Mask { _words: $wx, bits: vec }
}
pub fn from_vals(vals: &[u32]) -> U32Mask<$ws> {
let mut vec: BitVec<u32, Msb0> = BitVec::repeat(false, <$ws>::WORDS*32);
for idx in 0..vals.len() {
vec[idx*32..(idx+1)*32].store::<u32>(vals[idx]);
}
U32Mask { _words: $wx, bits: vec }
}
pub fn from_indices(chans: &[usize]) -> U32Mask<$ws> {
let mut mask = Self::new();
for c in chans {
if *c >= <$ws>::WORDS*32 { continue; }
mask.set_enabled(*c, true);
}
mask
}
pub fn none() -> Self {
Self::new()
}
pub fn all() -> Self {
let mut mask = Self::new();
mask.set_enabled_all(true);
mask
}
pub fn from_channels(chans: &[usize]) -> Self {
let mut mask = Self::new();
for c in chans {
mask.set_enabled(*c, true);
}
mask
}
pub fn set_channels_enabled(&mut self, chans: &[usize], enabled: bool) {
for c in chans {
self.set_enabled(*c, enabled);
}
}
pub fn channels(&self) -> Vec<usize> {
let mut res: Vec<usize> = Vec::with_capacity(consts::NCHANS);
for ch in 0..consts::NCHANS {
if self.get_enabled(ch) {
res.push(ch);
}
}
res
}
pub fn is_empty(&self) -> bool {
*self == Self::none()
}
}
}
impl<T: wordreg::WordSize> ToU32s for U32Mask<T> {
fn as_u32s(&self) -> Vec<u32> {
self.bits.as_raw_slice().to_vec()
}
}
impl U32Mask<wordreg::Wx1> {
pub fn new() -> U32Mask<wordreg::Wx1> {
let vec: BitVec<u32, Msb0> = BitVec::repeat(false, wordreg::Wx1::WORDS*32);
U32Mask { _words: wordreg::Wx1{}, bits: vec }
}
make_from_values_impl!(wordreg::Wx1, wordreg::Wx1{});
}
impl U32Mask<wordreg::Wx2> {
pub fn new() -> U32Mask<wordreg::Wx2> {
let vec: BitVec<u32, Msb0> = BitVec::repeat(false, wordreg::Wx2::WORDS*32);
U32Mask { _words: wordreg::Wx2{}, bits: vec }
}
make_from_values_impl!(wordreg::Wx2, wordreg::Wx2{});
}
impl U32Mask<wordreg::Wx3> {
pub fn new() -> U32Mask<wordreg::Wx3> {
let vec: BitVec<u32, Msb0> = BitVec::repeat(false, wordreg::Wx3::WORDS*32);
U32Mask { _words: wordreg::Wx3{}, bits: vec }
}
make_from_values_impl!(wordreg::Wx3, wordreg::Wx3{});
}
impl U32Mask<wordreg::Wx4> {
pub fn new() -> U32Mask<wordreg::Wx4> {
let vec: BitVec<u32, Msb0> = BitVec::repeat(false, wordreg::Wx4::WORDS*32);
U32Mask { _words: wordreg::Wx4{}, bits: vec }
}
make_from_values_impl!(wordreg::Wx4, wordreg::Wx4{});
}
pub type ChanMask = U32Mask<wordreg::Wx2>;
impl Not for &ChanMask {
type Output = ChanMask;
fn not(self) -> Self::Output {
let mut output = ChanMask::new();
let slice = self.bits.as_bitslice();
for i in 0..slice.len() {
output.set_enabled(consts::NCHANS-1-i, !slice[i]);
}
output
}
}
impl BitAnd for &ChanMask {
type Output = ChanMask;
fn bitand(self, other: Self) -> Self::Output {
let mut output = ChanMask::new();
let slice = self.bits.as_bitslice();
let other = other.bits.as_bitslice();
for (i, (t, o)) in zip(slice, other).enumerate() {
output.set_enabled(consts::NCHANS-1-i, *t & *o);
}
output
}
}
impl BitXor for &ChanMask {
type Output = ChanMask;
fn bitxor(self, other: Self) -> Self::Output {
let mut output = ChanMask::new();
let slice = self.bits.as_bitslice();
let other = other.bits.as_bitslice();
for (i, (t, o)) in zip(slice, other).enumerate() {
output.set_enabled(consts::NCHANS-1-i, *t ^ *o);
}
output
}
}
impl BitOr for &ChanMask {
type Output = ChanMask;
fn bitor(self, other: Self) -> Self::Output {
let mut output = ChanMask::new();
let slice = self.bits.as_bitslice();
let other = other.bits.as_bitslice();
for (i, (t, o)) in zip(slice, other).enumerate() {
output.set_enabled(consts::NCHANS-1-i, *t | *o);
}
output
}
}
pub type ArbMask = U32Mask<wordreg::Wx1>;
impl ArbMask {
pub(crate) fn from_aux_channels(chans: &[AuxDACFn]) -> Self {
let mut mask = ArbMask::none();
for c in chans {
let idx = if *c == AuxDACFn::LGC {
LGCRNGIDX
} else { AUXFNRNGMAP[*c as usize] };
mask.set_enabled(idx, true);
}
mask
}
}
impl Not for &ArbMask {
type Output = ArbMask;
fn not(self) -> Self::Output {
let mut output = ArbMask::new();
let slice = self.bits.as_bitslice();
for i in 0..slice.len() {
output.set_enabled(consts::AUXNCHANS-1-i, !slice[i]);
}
output
}
}
impl BitAnd for &ArbMask {
type Output = ArbMask;
fn bitand(self, other: Self) -> Self::Output {
let mut output = ArbMask::new();
let slice = self.bits.as_bitslice();
let other = other.bits.as_bitslice();
for (i, (t, o)) in zip(slice, other).enumerate() {
output.set_enabled(consts::AUXNCHANS-1-i, *t & *o);
}
output
}
}
impl BitXor for &ArbMask {
type Output = ArbMask;
fn bitxor(self, other: Self) -> Self::Output {
let mut output = ArbMask::new();
let slice = self.bits.as_bitslice();
let other = other.bits.as_bitslice();
for (i, (t, o)) in zip(slice, other).enumerate() {
output.set_enabled(consts::AUXNCHANS-1-i, *t ^ *o);
}
output
}
}
impl BitOr for &ArbMask {
type Output = ArbMask;
fn bitor(self, other: Self) -> Self::Output {
let mut output = ArbMask::new();
let slice = self.bits.as_bitslice();
let other = other.bits.as_bitslice();
for (i, (t, o)) in zip(slice, other).enumerate() {
output.set_enabled(consts::AUXNCHANS-1-i, *t | *o);
}
output
}
}
pub type SelectorMask = U32Mask<wordreg::Wx1>;
#[derive(Clone, Copy, FromPrimitive, ToPrimitive, Debug)]
#[repr(u32)]
pub enum Averaging {
Enabled = 1,
Disabled = 0
}
impl ToU32s for Averaging {
fn as_u32s(&self) -> Vec<u32> {
vec![*self as u32; 1]
}
}
#[cfg(test)]
mod adcmask_tests {
use super::ChanMask;
use crate::registers::ToU32s;
#[test]
fn get_set_channel() {
let mut v = ChanMask::new();
v.set_enabled(31, true);
v.set_enabled(0, true);
v.set_enabled(62, true);
assert_eq!(v.get_enabled(31), true);
assert_eq!(v.get_enabled(0), true);
assert_eq!(v.get_enabled(62), true);
v.set_enabled(62, false);
assert_eq!(v.get_enabled(62), false);
}
#[test]
fn get_set_all_channels() {
let mut v = ChanMask::new();
v.set_enabled_all(true);
for c in 0..v.len() {
assert_eq!(v.get_enabled(c), true);
}
}
#[test]
fn repr() {
let mut v = ChanMask::new();
v.set_enabled(31, true);
v.set_enabled(0, true);
v.set_enabled(62, true);
assert_eq!(&v.as_u32s(), &[0x40000000, 0x80000001]);
}
#[test]
fn toggle() {
let mut v = ChanMask::new();
v.set_enabled(31, true);
v.set_enabled(0, true);
v.set_enabled(62, true);
assert_eq!(v.get_enabled(31), true);
v.toggle(31);
assert_eq!(v.get_enabled(31), false);
}
}
pub type IOMask = U32Mask<wordreg::Wx1>;
#[cfg(test)]
mod iomask_tests {
use super::IOMask;
use crate::registers::ToU32s;
#[test]
fn get_set_channel() {
let mut v = IOMask::new();
v.set_enabled(31, true);
v.set_enabled(0, true);
assert_eq!(v.get_enabled(31), true);
assert_eq!(v.get_enabled(0), true);
v.set_enabled(31, false);
assert_eq!(v.get_enabled(31), false);
}
#[test]
fn get_set_all_channels() {
let mut v = IOMask::new();
v.set_enabled_all(true);
for c in 0..v.len() {
assert_eq!(v.get_enabled(c), true);
}
}
#[test]
fn repr() {
let mut v = IOMask::new();
v.set_enabled(31, true);
v.set_enabled(0, true);
assert_eq!(&v.as_u32s(), &[0x80000001]);
}
#[test]
fn from_vals() {
let mut v = IOMask::from_vals(&[0x80000001]);
assert_eq!(&v.as_u32s(), &[0x80000001]);
assert_eq!(v.get_enabled(31), true);
assert_eq!(v.get_enabled(0), true);
v.set_enabled(1, true);
assert_eq!(&v.as_u32s(), &[0x80000003]);
}
#[test]
fn toggle() {
let mut v = IOMask::new();
v.set_enabled(31, true);
v.set_enabled(0, true);
assert_eq!(v.get_enabled(31), true);
v.toggle(31);
assert_eq!(v.get_enabled(31), false);
}
}
#[derive(PartialEq, Copy, Clone)]
pub struct IODir(bool);
impl IODir {
pub const IN: IODir = Self(false);
pub const OUT: IODir = Self(true);
}
pub struct IOEnable {
bits: BitVec<u32, Lsb0>,
}
impl IOEnable {
const LEN: usize = 5;
pub fn new() -> IOEnable {
let vec: BitVec<u32, Lsb0> = BitVec::repeat(false, Self::LEN);
let mut io = IOEnable { bits: vec };
io.set_all_outputs(true);
io.set_en(false);
io
}
pub fn all_output() -> IOEnable {
Self::with_iodirs(IODir::OUT, IODir::OUT, IODir::OUT, IODir::OUT)
}
pub fn all_input() -> IOEnable {
Self::with_iodirs(IODir::IN, IODir::IN, IODir::IN, IODir::IN)
}
pub fn with_iodirs(cl0: IODir, cl1: IODir, cl2: IODir, cl3: IODir) -> IOEnable {
let vec: BitVec<u32, Lsb0> = BitVec::repeat(false, Self::LEN);
let mut io = IOEnable { bits: vec };
io.set_en(true);
if cl0 == IODir::OUT {
io.set_output(0, true);
}
if cl1 == IODir::OUT {
io.set_output(1, true);
}
if cl2 == IODir::OUT {
io.set_output(2, true);
}
if cl3 == IODir::OUT {
io.set_output(3, true);
}
io
}
pub fn set_en(&mut self, status: bool) {
self.set_output(Self::LEN-1, !status);
}
pub fn get_en(&self) -> bool {
!self.bits[Self::LEN-1]
}
pub fn set_output(&mut self, idx: usize, status: bool) {
self.bits.set(idx, status);
}
pub fn set_all_outputs(&mut self, status: bool) {
for i in 0..(Self::LEN-1) {
self.set_output(i, status);
}
}
}
impl ToU32s for IOEnable {
fn as_u32s(&self) -> Vec<u32> {
self.bits.as_raw_slice().to_vec()
}
}
#[cfg(test)]
mod ioenable_tests {
use super::{IOEnable, ToU32s};
#[test]
fn ioenable_new() {
assert_eq!(IOEnable::new().as_u32s(), &[0x1f]);
}
#[test]
fn ioenable_all() {
assert_eq!(IOEnable::all_output().as_u32s(), &[0xf]);
}
#[test]
fn ioenable_new_mut() {
let mut io = IOEnable::new();
io.set_en(true);
io.set_output(0, true);
io.set_output(1, true);
io.set_output(2, false);
io.set_output(3, true);
assert_eq!(io.as_u32s(), &[0xb]);
io.set_output(2, true);
assert_eq!(io.as_u32s(), &[0xf]);
}
}