libarc2/
registers.rs

1//! Data that can be serialised into ArC2 instructions.
2//!
3//! A register is a piece of u32-encodable information that can is used
4//! to form one or more instructions that ArC2 can parse. All registers
5//! are expected to implement the [`ToU32s`][`crate::registers::ToU32s`]
6//! trait that converts them into a serialisable `Vec<u32>`. This can be
7//! then be processed by ArC2.
8
9use std::collections::HashMap;
10use std::time::Duration;
11use consts::{AUXFNRNGMAP, LGCRNGIDX};
12use num_derive::{FromPrimitive, ToPrimitive};
13use bitvec::prelude::*;
14use bitflags::bitflags;
15use num_traits::{ToPrimitive, FromPrimitive};
16use thiserror::Error;
17use std::ops::{BitAnd, BitXor, BitOr, Not};
18use std::iter::zip;
19
20mod wordreg {
21
22    /// A trait denoting a word size; ie how many words
23    /// a register is using.
24    pub trait WordSize {
25        const WORDS: usize;
26    }
27
28    /// One word
29    #[derive(Clone, Debug, PartialEq)]
30    pub struct Wx1;
31    impl WordSize for Wx1 {
32        const WORDS: usize = 1;
33    }
34
35    /// Two words
36    #[derive(Clone, Debug, PartialEq)]
37    pub struct Wx2;
38    impl WordSize for Wx2 {
39        const WORDS: usize = 2;
40    }
41
42    /// Three words
43    #[derive(Clone, Debug, PartialEq)]
44    pub struct Wx3;
45    impl WordSize for Wx3 {
46        const WORDS: usize = 3;
47    }
48
49    /// Four words
50    #[derive(Clone, Debug, PartialEq)]
51    pub struct Wx4;
52    impl WordSize for Wx4 {
53        const WORDS: usize = 4;
54    }
55
56    /// Five words
57    #[derive(Clone, Debug, PartialEq)]
58    pub struct Wx5;
59    impl WordSize for Wx5 {
60        const WORDS: usize = 5;
61    }
62
63    /// Six words
64    #[derive(Clone, Debug, PartialEq)]
65    pub struct Wx6;
66    impl WordSize for Wx6 {
67        const WORDS: usize = 6;
68    }
69
70    /// Seven words
71    #[derive(Clone, Debug, PartialEq)]
72    pub struct Wx7;
73    impl WordSize for Wx7 {
74        const WORDS: usize = 7;
75    }
76}
77
78use wordreg::WordSize;
79
80
81pub(crate) mod consts {
82    use super::DACMask;
83    use super::ClusterMask;
84
85    pub(crate) const CHANMAP: [DACMask; 64] = [
86        DACMask::CH00_03, DACMask::CH00_03, DACMask::CH00_03, DACMask::CH00_03,
87        DACMask::CH04_07, DACMask::CH04_07, DACMask::CH04_07, DACMask::CH04_07,
88        DACMask::CH08_11, DACMask::CH08_11, DACMask::CH08_11, DACMask::CH08_11,
89        DACMask::CH12_15, DACMask::CH12_15, DACMask::CH12_15, DACMask::CH12_15,
90        DACMask::CH16_19, DACMask::CH16_19, DACMask::CH16_19, DACMask::CH16_19,
91        DACMask::CH20_23, DACMask::CH20_23, DACMask::CH20_23, DACMask::CH20_23,
92        DACMask::CH24_27, DACMask::CH24_27, DACMask::CH24_27, DACMask::CH24_27,
93        DACMask::CH28_31, DACMask::CH28_31, DACMask::CH28_31, DACMask::CH28_31,
94        DACMask::CH32_35, DACMask::CH32_35, DACMask::CH32_35, DACMask::CH32_35,
95        DACMask::CH36_39, DACMask::CH36_39, DACMask::CH36_39, DACMask::CH36_39,
96        DACMask::CH40_43, DACMask::CH40_43, DACMask::CH40_43, DACMask::CH40_43,
97        DACMask::CH44_47, DACMask::CH44_47, DACMask::CH44_47, DACMask::CH44_47,
98        DACMask::CH48_51, DACMask::CH48_51, DACMask::CH48_51, DACMask::CH48_51,
99        DACMask::CH52_55, DACMask::CH52_55, DACMask::CH52_55, DACMask::CH52_55,
100        DACMask::CH56_59, DACMask::CH56_59, DACMask::CH56_59, DACMask::CH56_59,
101        DACMask::CH60_63, DACMask::CH60_63, DACMask::CH60_63, DACMask::CH60_63
102    ];
103
104    pub(crate) const DACHCLUSTERMAP: [DACMask; 16] = [
105        DACMask::CH00_03, DACMask::CH04_07, DACMask::CH08_11, DACMask::CH12_15,
106        DACMask::CH16_19, DACMask::CH20_23, DACMask::CH24_27, DACMask::CH28_31,
107        DACMask::CH32_35, DACMask::CH36_39, DACMask::CH40_43, DACMask::CH44_47,
108        DACMask::CH48_51, DACMask::CH52_55, DACMask::CH56_59, DACMask::CH60_63,
109    ];
110
111    pub(crate) const HSCLUSTERMAP: [ClusterMask; 8] = [
112        ClusterMask::CL0,
113        ClusterMask::CL1,
114        ClusterMask::CL2,
115        ClusterMask::CL3,
116        ClusterMask::CL4,
117        ClusterMask::CL5,
118        ClusterMask::CL6,
119        ClusterMask::CL7,
120    ];
121
122    /// Convert between AuxDACFn and index in the ArbMask used for range selection
123    pub(crate) const AUXFNRNGMAP: [usize; 8] = [
124        1, 0, 3, 2, 5, 4, 7, 6
125    ];
126    /// Hardcoded index for the LGC bit position in the range channel mask
127    pub(crate) const LGCRNGIDX: usize = 11;
128
129    /// Convert selector channels to bitmask bits
130    pub(crate) const SELECTORMAP: [usize; 32] = [
131    // Selector channel and bitmask bit. Ch 0 → bit 4, ch 1 → bit 5 etc
132    //   0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15
133         4,  5,  6,  7,  3,  2,  1,  0, 12, 13, 14, 15, 11, 10,  9,  8,
134    //  16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31
135        16, 17, 18, 19, 23, 22, 21, 20, 24, 25, 26, 27, 31, 30, 29, 28
136    ];
137
138    pub(super) const CHANCONFSIZE: usize = 2;
139    pub(super) const AUXNCHANS: usize = 16;
140    pub(super) const NCHANS: usize = 64;
141
142    // Number of selector circuits available
143    pub(crate) const NSELECTORS: usize = 32;
144}
145
146#[derive(Error, Debug)]
147pub(crate) enum Error {
148    #[error("Supplied slice is too small")]
149    SliceTooSmall
150}
151
152
153/// Convert a value into a `Vec<u32>`.
154pub trait ToU32s {
155
156    /// Convert an object, typically a register, into a serialisable
157    /// vector of u32s. These are the values that are actually written
158    /// to the ArC2 buffer.
159    fn as_u32s(&self) -> Vec<u32>;
160}
161
162
163/// Opcodes designate an ArC2 operation
164///
165/// An [`OpCode`] is typically the first register in an ArC2 instruction
166/// and may be followed by a series of arguments.
167#[derive(Clone, Copy, FromPrimitive, ToPrimitive)]
168#[repr(u32)]
169pub enum OpCode {
170    /// Set a DAC configuration.
171    SetDAC         = 0x00000001,
172    /// Enable a DAC configuration previously set with [`OpCode::SetDAC`].
173    UpdateDAC      = 0x00000002,
174    /// Read Current operation.
175    CurrentRead    = 0x00000004,
176    /// Read voltage operation.
177    VoltageRead    = 0x00000008,
178    /// Set selector.
179    UpdateSelector = 0x00000010,
180    /// Set logic levels.
181    UpdateLogic    = 0x00000020,
182    /// Update channel configuration.
183    UpdateChannel  = 0x00000040,
184    /// Clear instrument buffer.
185    Clear          = 0x00000080,
186    /// Configure for high speed pulse operation.
187    HSPulseConfig  = 0x00000100,
188    /// Initiate a high speed pulse operation.
189    HSPulseStart   = 0x00000200,
190    /// Modify channel configuration.
191    ModifyChannel  = 0x00000400,
192    /// Set DAC Offsets (currently nop).
193    SetDACOffset   = 0x00001000,
194    /// Delay (20 ns precision)
195    Delay          = 0x00002000,
196    /// DAC Range
197    DACRange       = 0x00004000,
198    /// OpAmp preparation
199    AmpPrep        = 0x00010000
200}
201
202impl ToU32s for OpCode {
203    fn as_u32s(&self) -> Vec<u32> {
204        [*self as u32].to_vec()
205    }
206}
207
208
209/// Auxiliary DAC function
210///
211/// This is typically used with
212/// [`Instrument::config_aux_channels`][`crate::instrument::Instrument::config_aux_channels()`] to
213/// set the configuration for the auxiliary DACs that manage the selectors and the current source
214/// operation. Although logic level is also adjusted via the auxiliary DACs there is a dedicated
215/// function for this operation and it is not done via the
216/// [`Instrument::config_aux_channels`][`crate::instrument::Instrument::config_aux_channels()`]
217/// route.
218#[derive(PartialEq, Clone, Copy, FromPrimitive, ToPrimitive)]
219#[repr(usize)]
220pub enum AuxDACFn {
221    /// Selector circuit pulls down to this voltage
222    SELL = 0,
223    /// Selector circuit pulls up to this voltage
224    SELH = 1,
225    /// Arbitrary power supply for DUTs - Max current 100 mA
226    ARB4 = 2,
227    /// Arbitrary power supply for DUTs - Max current 100 mA
228    ARB3 = 3,
229    /// Arbitrary power supply for DUTs - Max current 100 mA
230    ARB1 = 4,
231    /// Arbitrary power supply for DUTs - Max current 100 mA
232    ARB2 = 5,
233    /// Reference voltage that the current source sources/sinks
234    /// current from/to. There should be a ≥3 V headroom between
235    /// CREF and the expected operating point of the current source
236    /// Must be within 1.5 V of CSET.
237    CREF = 6,
238    /// Sets output current of the current source. The difference
239    /// between CSET and CREF divided by the resistor selected
240    /// dictates the output current. This should never exceed 1.5 V.
241    /// Must be within 1.5 V of CREF.
242    CSET = 7,
243    /// Controls the logic level
244    LGC = 10
245}
246
247impl AuxDACFn {
248
249    /// Returns `true` if this AUX function occupies
250    /// the lower 16 bits of the corresponding DAC
251    /// instruction - See the protocol document for more
252    pub(crate) fn is_lower(&self) -> bool {
253        (*self as usize) % 2 != 0
254    }
255}
256
257
258/// Output range for the DAC RNG instruction. There are only two options:
259/// (a) [`OutputRange::STD`] standard ± 10 V range (at 300 μV precision)
260/// or (b) [`OutputRange::EXT`] extended ± 20 V range (at 600 μV precision)
261#[derive(Copy, Clone, Eq)]
262pub struct OutputRange(bool);
263
264impl OutputRange {
265    /// Standard output range ± 10 V - 300 μV precision
266    pub const STD: OutputRange = Self(false);
267    /// Extended output range ± 20 V - 600 μV precision
268    pub const EXT: OutputRange = Self(true);
269
270}
271
272impl PartialEq for OutputRange {
273    fn eq(&self, other: &Self) -> bool {
274        self.0 == other.0
275    }
276}
277
278impl PartialEq<bool> for OutputRange {
279    fn eq(&self, other: &bool) -> bool {
280        self.0 == *other
281    }
282}
283
284/// An empty register, typically used to pad instructions
285/// to full length.
286///
287/// An [`Empty`] should never need to be invoked manually
288/// as empty instructions are added appropriately
289/// when an instruction is compiled.
290pub struct Empty(u32);
291
292impl Empty {
293    /// Create a new empty register
294    pub fn new() -> Empty {
295        Empty(0x0)
296    }
297}
298
299impl ToU32s for Empty {
300    fn as_u32s(&self) -> Vec<u32> {
301        [self.0].to_vec()
302    }
303}
304
305
306/// Register used to terminate instructions.
307///
308/// As with [`Empty`] this should not need
309/// to be invoked manually as it is typically compiled into
310/// an instruction.
311pub struct Terminate(u32);
312
313impl Terminate {
314    pub fn new() -> Terminate {
315        Terminate(0x80008000)
316    }
317}
318
319impl ToU32s for Terminate {
320    fn as_u32s(&self) -> Vec<u32> {
321        [self.0].to_vec()
322    }
323}
324
325
326
327/// Register used to denote durations (50 MHz precision)
328///
329/// The `Duration` register is used to encode duration. This might be
330/// required, for instance, to allow for delays when settling during
331/// configuration of the system DACs or to create arbitrary waveforms
332/// where the precision of High Speed Driver is not required. Durations
333/// can either be created by specifying the nanosecond delay or from a
334/// [`std::time::Duration`] object.
335///
336/// ## Examples
337/// ```
338/// use libarc2::registers::{Duration50, ToU32s};
339/// use std::time::Duration;
340///
341/// let delay0 = Duration50::from_nanos(1210);
342/// // int(1210/20) = 60 or 0x3C
343/// assert_eq!(delay0.as_u32s()[0], 0x3C);
344///
345/// let delay1 = Duration50::from_duration(&Duration::from_nanos(1210));
346/// assert_eq!(delay1.as_u32s()[0], 0x3C);
347///
348/// // This one exceeds the maximum value and will be capped.
349/// let delay2 = Duration50::from_nanos(87000000000);
350/// assert_eq!(delay2.as_u32s()[0], 0xFFFFFFFF);
351/// ```
352pub struct Duration50(u32);
353
354impl Duration50 {
355    // This is the maximum duration we can fit in a 32bit integer on
356    // a 50 MHz clock (20 ns increments)
357    // We can fit up to 2^32 20 ns steps
358    // We choose u128 as the underlying type to maintain compatibility
359    // with the std::time::Duration API. Values will never exceed this
360    // value otherwise.
361    const MAX_DURATION_NS: u128 = 20u128 * (std::u32::MAX as u128);
362
363    /// Create a new delay register with 20 ns precision. Please note
364    /// that even though a `u128` is used as an argument the maximum
365    /// delay value that is supported by ArC2 is `2^32 × 20 ns`. Values
366    /// over that maximum will be capped.
367    pub fn from_nanos(ns: u128) -> Duration50 {
368        if ns > Self::MAX_DURATION_NS {
369            Duration50(std::u32::MAX)
370        } else {
371            Duration50((ns / 20) as u32)
372        }
373    }
374
375    /// Create a new delay register with 20 ns precision from a
376    /// [`Duration`][`std::time::Duration`] object.
377    pub fn from_duration(duration: &std::time::Duration) -> Duration50 {
378        Duration50::from_nanos(duration.as_nanos())
379    }
380}
381
382impl ToU32s for Duration50 {
383    fn as_u32s(&self) -> Vec<u32> {
384        [self.0].to_vec()
385    }
386}
387
388
389/// High Speed DAC clusters to manipulate
390#[derive(Clone, Copy, FromPrimitive, ToPrimitive, Debug)]
391#[repr(usize)]
392pub enum DACCluster {
393    /// Cluster 0
394    CL0 = 0,
395    /// Cluster 1
396    CL1 = 1,
397    /// Cluster 2
398    CL2 = 2,
399    /// Cluster 3
400    CL3 = 3,
401    /// Cluster 4
402    CL4 = 4,
403    /// Cluster 5
404    CL5 = 5,
405    /// Cluster 6
406    CL6 = 6,
407    /// Cluster 7
408    CL7 = 7
409}
410
411bitflags! {
412    /// High Speed cluster selection bitmask
413    ///
414    /// [`ClusterMask`] is used to create a suitable bitmask for
415    /// activating a high speed pulse on one or more output DAC
416    /// clusters.
417    pub struct ClusterMask: u8 {
418        const NONE = 0b00000000;
419        const CL0  = 0b00000001;
420        const CL1  = 0b00000010;
421        const CL2  = 0b00000100;
422        const CL3  = 0b00001000;
423        const CL4  = 0b00010000;
424        const CL5  = 0b00100000;
425        const CL6  = 0b01000000;
426        const CL7  = 0b10000000;
427
428        const ALL = Self::CL0.bits | Self::CL1.bits | Self::CL2.bits |
429                    Self::CL3.bits | Self::CL4.bits | Self::CL5.bits |
430                    Self::CL6.bits | Self::CL7.bits;
431    }
432}
433
434
435impl ClusterMask {
436
437    /// Create a new [`ClusterMask`] by providing a slice of
438    /// clusters instead of a bitmask.
439    pub fn new_from_cluster_idx(clusters: &[u8]) -> Self {
440        let mut mask = ClusterMask::NONE;
441        for cl in clusters {
442            mask |= consts::HSCLUSTERMAP[*cl as usize];
443        }
444
445        mask
446    }
447
448}
449
450
451/// Delays for high speed pulse drivers
452///
453/// This register is used to configure the delays of the high speed
454/// pulse drivers. It is essentially a 224-bit integer containing
455/// all cluster timings adhering to following layout.
456///
457/// ```text
458/// [CL7][CL6][CL5][CL4][CL3][CL2][CL1][CL0]
459///                                       ^
460///                                       |
461///                                       +-- LSB
462/// ```
463///
464/// ## Example
465/// ```
466/// use libarc2::registers::{HSDelay, ToU32s, DACCluster};
467/// use std::time::Duration;
468///
469/// let mut delay = HSDelay::new();
470///
471/// // Set cluster 0 to 100 ns
472/// delay.set_cluster_nanos(DACCluster::CL0, 100);
473/// assert_eq!(delay.as_u32s(), [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa]);
474///
475/// // And back to 0
476/// delay.set_cluster_nanos(DACCluster::CL0, 0);
477/// assert_eq!(delay.as_u32s(), [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]);
478///
479/// // Set cluster 1 to 220 ns
480/// delay.set_cluster_nanos(DACCluster::CL1, 220);
481/// assert_eq!(delay.as_u32s(), [0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x60000000]);
482///
483/// // And also cluster 0 to 300 ns using a Duration
484/// delay.set_cluster_from_duration(DACCluster::CL0, &Duration::from_nanos(300));
485/// assert_eq!(delay.as_u32s(), [0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x6000001e]);
486/// ```
487pub struct HSDelay {
488    bits: BitVec<u32, Msb0>
489}
490
491impl HSDelay {
492
493    const RESOLUTION: u128 = 10u128;
494    const MAX_DELAY: u128 = Self::RESOLUTION * 2u128.pow(28);
495    const CLUSTERS: usize = 8;
496    const CLUSTSIZE: usize = 28;
497
498    #[doc(hidden)]
499    fn steps_to_bools(val: u32) -> [bool; Self::CLUSTSIZE] {
500        let mut bools: [bool; Self::CLUSTSIZE] = [false; Self::CLUSTSIZE];
501        for i in 0..Self::CLUSTSIZE {
502            bools[i] = ( (val as u32 >> i) & 1 ) == 1
503        }
504        bools
505    }
506
507    /// Create a new delay with all clusters set to 0
508    pub fn new() -> HSDelay {
509        HSDelay { bits: BitVec::repeat(false, Self::CLUSTERS*Self::CLUSTSIZE) }
510    }
511
512    /// Set the delay of a cluster to a specified amount of ns. This is in
513    /// increments of 10 ns (100 MHz clock). Delays will be capped to
514    /// 2^{28} × 10 ns.
515    pub fn set_cluster_nanos(&mut self, cluster: DACCluster, val: u128) {
516        let steps = if val > Self::MAX_DELAY {
517            Self::MAX_DELAY / Self::RESOLUTION
518        } else {
519            val / Self::RESOLUTION
520        } as u32;
521
522        let bools = HSDelay::steps_to_bools(steps);
523
524        let bits = self.bits.as_mut_bitslice();
525
526        let cluster = cluster as usize;
527
528        for i in 0..bools.len() {
529            bits.set(Self::CLUSTSIZE*(Self::CLUSTERS-1-cluster) + i,
530                bools[Self::CLUSTSIZE - 1 - i]);
531        }
532
533    }
534
535    /// Same as [`set_cluster_nanos`][`Self::set_cluster_nanos`] but with a
536    /// [`Duration`] argument instead.
537    pub fn set_cluster_from_duration(&mut self, cluster: DACCluster, val: &Duration) {
538        self.set_cluster_nanos(cluster, val.as_nanos());
539    }
540}
541
542impl ToU32s for HSDelay {
543    fn as_u32s(&self) -> Vec<u32> {
544        self.bits.as_raw_slice().to_vec()
545    }
546}
547
548/// High Speed Pulse attributes
549///
550/// [`PulseAttrs`] is used to specify the attributes of an high speed
551/// pulsing operation (which is typically followed after an HSConfig one).
552/// Essentially it is used to define which output DAC clusters are used.
553///
554/// The default constructor covers the most basic operation which is is a
555/// typical low/high/low pulse. The additional function
556/// [`new_with_params()`][`Self::new_with_params`] allows to provide more
557/// arguments that handle two different usecases
558///
559/// (A) The pulse on this channel is lower than the baseline voltage used on
560/// the other channels. This is quite common when doing differential biasing.
561/// For instance if a 2.0 V pulse is applied between high and low this can be
562/// split into a 1.0 V pulse on the high channel and -1.0 V pulse on the low
563/// channel. In that case the `polarity` bit of the cluster the low channel
564/// belongs to should be asserted.
565///
566/// (B) The pulse previously configured
567/// with a [`HSConfig`][`crate::instructions::HSConfig`] instruction has a zero-width
568/// pulse width. This is a special case that essentially means "pulse +
569/// hold". In this case the additional arguments of
570/// [`new_with_params()`][`Self::new_with_params`] define the behaviour of
571/// ArC2. If `polarity` is `true` (high) then once the pulse will revert to
572/// the `DAC+` value of the last [`SetDAC`][`crate::instructions::SetDAC`] instruction.
573/// If `polarity` is `false` (low) then ArC2 will revert to `DAC-`. If instead
574/// `cancel` is set to `true` then `polarity` will be ignored and ArC2 will
575/// connect the channel to a 10 MΩ resistor.
576///
577/// ## Example
578///
579/// ```
580/// use libarc2::registers::{PulseAttrs, ClusterMask, ToU32s};
581///
582/// // Create a high speed pulse attribute for operation on DAC Clusters 0 and 1.
583/// let attrs = PulseAttrs::new(ClusterMask::CL0 | ClusterMask::CL1);
584///
585/// assert_eq!(attrs.as_u32s(), &[0x00030000]);
586///
587/// // Similar but with extra parameters
588/// let attrs = PulseAttrs::new_with_params(ClusterMask::CL0, ClusterMask::CL0, ClusterMask::CL0);
589///
590/// assert_eq!(attrs.as_u32s(), &[0x00010101]);
591/// ```
592pub struct PulseAttrs {
593    // cluster bitmask
594    cluster: ClusterMask,
595    // polarity flag
596    // if polarity is 0 it means that the pulse direction
597    // will be low V → high V → low V. Low and High V are set
598    // as usual with the SetDAC command. Most of the times
599    // polarity will be 0 unless a specific operation is required
600    // in conjuction with a cluster configured with 0ns pulse
601    // width. In this case if polarity is 1 the instrument will go
602    // from whatever its state to DAC+. If polarity is 0 will
603    // revert to DAC- instead.
604    polarity: ClusterMask,
605    // If cancel is 1 and pulse width is 0 the channel will be
606    // connected to a 10 MΩ resistor instead of returning to
607    // DAC+ or DAC- depending on the value of polarity.
608    cancel: ClusterMask
609}
610
611impl PulseAttrs {
612
613    /// Create a new pulse attribute register enabling the specified
614    /// DAC clusters for a low/high/low operation.
615    pub fn new(clusters: ClusterMask) -> Self {
616        Self::new_with_params(clusters, ClusterMask::NONE, ClusterMask::NONE)
617    }
618
619    /// Provide additional arguments (see documentation for [`PulseAttrs`]).
620    pub fn new_with_params(clusters: ClusterMask, polarity: ClusterMask, cancel: ClusterMask) -> Self {
621        PulseAttrs {
622            cluster: clusters,
623            polarity: polarity,
624            cancel: cancel
625        }
626    }
627}
628
629impl ToU32s for PulseAttrs {
630    fn as_u32s(&self) -> Vec<u32> {
631        let value = u32::from_be_bytes([0x00,
632                                        self.cluster.bits(),
633                                        self.polarity.bits(),
634                                        self.cancel.bits()]);
635        [value].to_vec()
636    }
637}
638
639
640/// An FPGA memory address associated with an operation
641///
642/// This is practically a [`u32`] underneath and can be treated
643/// as such. Typically is associated with an operation that would need
644/// to output data into the FPGA's memory such as
645/// [`CurrentRead`][`crate::instructions::CurrentRead`] or
646/// [`VoltageRead`][`crate::instructions::VoltageRead`].
647#[derive(FromPrimitive, ToPrimitive)]
648pub struct Address(u32);
649
650impl Address {
651    pub fn new(addr: u32) -> Address {
652        Address::from_u32(addr).unwrap()
653    }
654}
655
656impl ToU32s for Address {
657    fn as_u32s(&self) -> Vec<u32> {
658        [self.0].to_vec()
659    }
660}
661
662
663bitflags! {
664    /// DAC channel selection register.
665    ///
666    /// [`DACMask`] is used to create a suitable bitmask for a given
667    /// selection of channels. Output channels in ArC2 are organised
668    /// in 8 clusters and there is also an additional auxilliary DAC
669    /// used for internal configuration. Each cluster contains 8
670    /// possible channels that can be toggled up to a total of 64.
671    /// This is usually paired with the
672    /// [`OpCode::UpdateDAC`][`super::opcode::OpCode::UpdateDAC`]
673    /// opcode to set the voltages of a channel. All the DACs are
674    /// organised in halves so if one wants to address channel
675    /// 3 (zero-indexed) would have to toggle the bits that correspond
676    /// to DAC0; 1st half ([`DACMask::CH00_03`]), whereas for channel 29
677    /// that would have to be DAC3; 2nd half ([`DACMask::CH28_31`]).
678    ///
679    /// Although one can create a suitable bitmask manually this
680    /// implementation provides some convenient functions that can
681    /// be used instead of calculating which of 16 halves corresponds
682    /// to a given channel. This is abstracted away under functions
683    /// [`set_channel`][`DACMask::set_channel`] and
684    /// [`unset_channel`][`DACMask::unset_channel`].
685    ///
686    /// ## Example
687    /// ```
688    /// use libarc2::registers::DACMask;
689    ///
690    /// // Create a new DAC bitmask
691    /// let mut clusters = DACMask::NONE;
692    ///
693    /// clusters.set_channels(&[2, 3, 50, 61]);
694    ///
695    /// assert_eq!(clusters, DACMask::CH00_03 | DACMask::CH48_51 |
696    ///     DACMask::CH60_63);
697    /// assert_eq!(u32::from(&clusters), 0x00009001);
698    /// clusters.set_channel(12);
699    /// assert_eq!(clusters, DACMask::CH00_03 | DACMask::CH12_15 |
700    ///     DACMask::CH48_51 | DACMask::CH60_63);
701    /// assert_eq!(u32::from(&clusters), 0x00009009);
702    ///
703    /// clusters.unset_channel(61);
704    /// assert_eq!(clusters, DACMask::CH00_03 | DACMask::CH12_15 |
705    ///     DACMask::CH48_51);
706    /// assert_eq!(u32::from(&clusters), 0x00001009);
707    ///
708    /// clusters.clear();
709    /// assert_eq!(clusters, DACMask::NONE);
710    /// assert_eq!(u32::from(&clusters), 0x0);
711    /// ```
712    pub struct DACMask: u32 {
713        /// No Flags; invalid state
714        const NONE    = 0b00000000000000000000000000000000;
715        /// DAC0; first half
716        const CH00_03 = 0b00000000000000000000000000000001;
717        /// DAC0; second half
718        const CH04_07 = 0b00000000000000000000000000000010;
719        /// DAC1; first half
720        const CH08_11 = 0b00000000000000000000000000000100;
721        /// DAC1; second half
722        const CH12_15 = 0b00000000000000000000000000001000;
723        /// DAC2; first half
724        const CH16_19 = 0b00000000000000000000000000010000;
725        /// DAC2; second half
726        const CH20_23 = 0b00000000000000000000000000100000;
727        /// DAC3; first half
728        const CH24_27 = 0b00000000000000000000000001000000;
729        /// DAC3; second half
730        const CH28_31 = 0b00000000000000000000000010000000;
731        /// DAC4; first half
732        const CH32_35 = 0b00000000000000000000000100000000;
733        /// DAC4; second half
734        const CH36_39 = 0b00000000000000000000001000000000;
735        /// DAC5; first half
736        const CH40_43 = 0b00000000000000000000010000000000;
737        /// DAC5; second half
738        const CH44_47 = 0b00000000000000000000100000000000;
739        /// DAC6; first half
740        const CH48_51 = 0b00000000000000000001000000000000;
741        /// DAC6; second half
742        const CH52_55 = 0b00000000000000000010000000000000;
743        /// DAC7; first half
744        const CH56_59 = 0b00000000000000000100000000000000;
745        /// DAC7; second half
746        const CH60_63 = 0b00000000000000001000000000000000;
747        /// AUX DAC0
748        const AUX0    = 0b00000000000000010000000000000000;
749        /// AUX DAC1
750        const AUX1    = 0b00000000000000100000000000000000;
751        /// All channels of DAC0
752        const DAC0    = Self::CH00_03.bits | Self::CH04_07.bits;
753        /// All channels of DAC1
754        const DAC1    = Self::CH08_11.bits | Self::CH12_15.bits;
755        /// All channels of DAC2
756        const DAC2    = Self::CH16_19.bits | Self::CH20_23.bits;
757        /// All channels of DAC3
758        const DAC3    = Self::CH24_27.bits | Self::CH28_31.bits;
759        /// All channels of DAC4
760        const DAC4    = Self::CH32_35.bits | Self::CH36_39.bits;
761        /// All channels of DAC5
762        const DAC5    = Self::CH40_43.bits | Self::CH44_47.bits;
763        /// All channels of DAC6
764        const DAC6    = Self::CH48_51.bits | Self::CH52_55.bits;
765        /// All channels of DAC7
766        const DAC7    = Self::CH56_59.bits | Self::CH60_63.bits;
767        /// All channels
768        const ALL = Self::CH00_03.bits | Self::CH04_07.bits |
769                    Self::CH08_11.bits | Self::CH12_15.bits |
770                    Self::CH16_19.bits | Self::CH20_23.bits |
771                    Self::CH24_27.bits | Self::CH28_31.bits |
772                    Self::CH32_35.bits | Self::CH36_39.bits |
773                    Self::CH40_43.bits | Self::CH44_47.bits |
774                    Self::CH48_51.bits | Self::CH52_55.bits |
775                    Self::CH56_59.bits | Self::CH60_63.bits;
776    }
777}
778
779impl DACMask {
780
781    /// Enable the specified channel.
782    pub fn set_channel(&mut self, chan: usize) {
783        self.set_channels(&[chan]);
784    }
785
786    /// Disable the specified channel.
787    pub fn unset_channel(&mut self, chan: usize) {
788        self.unset_channels(&[chan]);
789    }
790
791    /// Enable the specified channels.
792    pub fn set_channels(&mut self, chans: &[usize]) {
793        for c in chans {
794            *self |= consts::CHANMAP[*c];
795        }
796    }
797
798    /// Disable the specified channels.
799    pub fn unset_channels(&mut self, chans: &[usize]) {
800        for c in chans {
801            *self &= !consts::CHANMAP[*c];
802        }
803    }
804
805    /// Clear all channels. This is effectively [`DACMask::NONE`].
806    pub fn clear(&mut self) {
807        self.bits = 0;
808    }
809
810}
811
812impl From<&DACMask> for u32 {
813    fn from(clusters: &DACMask) -> u32 {
814        clusters.bits() as u32
815    }
816}
817
818impl ToU32s for DACMask {
819    fn as_u32s(&self) -> Vec<u32> {
820        [u32::from(self)].to_vec()
821    }
822}
823
824#[cfg(test)]
825mod dacmask_tests {
826    use super::DACMask;
827
828    #[test]
829    fn test_dac_mask() {
830
831        let mut clusters = DACMask::NONE;
832
833        clusters.set_channels(&[2, 3, 50, 61]);
834        assert_eq!(clusters, DACMask::CH00_03 | DACMask::CH48_51 |
835            DACMask::CH60_63);
836        assert_eq!(u32::from(&clusters), 0x00009001);
837
838        clusters.set_channel(12);
839        assert_eq!(clusters, DACMask::CH00_03 | DACMask::CH12_15 |
840            DACMask::CH48_51 | DACMask::CH60_63);
841        assert_eq!(u32::from(&clusters), 0x00009009);
842
843        clusters.unset_channel(61);
844        assert_eq!(clusters, DACMask::CH00_03 | DACMask::CH12_15 |
845            DACMask::CH48_51);
846        assert_eq!(u32::from(&clusters), 0x00001009);
847
848        clusters.clear();
849        assert_eq!(clusters, DACMask::NONE);
850        assert_eq!(u32::from(&clusters), 0x0);
851
852    }
853}
854
855
856/// Channel configurations currently supported by ArC2.
857/// Use these with [`ChannelConf`] to control
858/// individual ArC2 channels.
859#[derive(Clone, PartialEq, Copy, FromPrimitive, Debug)]
860#[repr(u8)]
861pub enum ChannelState {
862    /// Keep current state
863    Maintain = 0b00,
864    /// Open channel; channel will not be connected
865    /// to anything.
866    Open = 0b01,
867    /// Channel is set for arbitrary voltage operation
868    VoltArb = 0b10,
869    /// High-Speed pulse channel
870    HiSpeed = 0b11,
871}
872
873impl ChannelState {
874
875    fn as_bools(&self) -> [bool; consts::CHANCONFSIZE] {
876
877        let mut bools: [bool; consts::CHANCONFSIZE] = [false; consts::CHANCONFSIZE];
878
879        for i in 0..consts::CHANCONFSIZE {
880            bools[i] = ((*self as u8 >> i) & 1) == 1
881        }
882
883        bools
884    }
885
886    fn from_bools(bools: &[bool; consts::CHANCONFSIZE]) -> ChannelState {
887        let mut bitarr = bitarr![u8, Msb0; 0; 8];
888
889        for i in 0..consts::CHANCONFSIZE {
890           bitarr.set(8-consts::CHANCONFSIZE+i, bools[i])
891        }
892
893        let value: &[u8] = bitarr.as_raw_slice();
894        ChannelState::from_u8(value[0] as u8).unwrap()
895
896    }
897
898    fn from_bitslice(bools: &BitSlice<u32, Msb0>) -> Result<ChannelState, Error> {
899
900        let len: usize;
901
902        if bools.len() < consts::CHANCONFSIZE {
903            return Err(Error::SliceTooSmall);
904        }
905
906        if bools.len() > 8 {
907            len = 8;
908        } else {
909            len = bools.len()
910        }
911
912        let mut bitarr = bitarr![u8, Msb0; 0; 8];
913
914        for i in 0..len {
915           bitarr.set(8-len+i, bools[i])
916        }
917
918        let value: &[u8] = bitarr.as_raw_slice();
919        Ok(ChannelState::from_u8(value[0] as u8).unwrap())
920    }
921
922}
923
924impl From<&[bool; consts::CHANCONFSIZE]> for ChannelState {
925    fn from(bools: &[bool; consts::CHANCONFSIZE]) -> ChannelState {
926        ChannelState::from_bools(&bools)
927    }
928}
929
930/// A set of DAC channel output configuration.
931///
932/// A `ChannelConf` is currently designed for 3 bits per channel for
933/// a total of 64 channels (192-bits). The underlying implementation uses a
934/// [`BitVec`][bitvec::vec::BitVec] storing MSB bits and backed by [`u32`]s.
935/// This matches the structure that ArC2 is expecting for the channel
936/// configuration. `ChannelConf` is typically paired with
937/// [`OpCode::UpdateChannel`].
938///
939/// To create a new register call [`ChannelConf::new()`] with the
940/// desired number of channels. For typical ArC2 scenarios this should be 64.
941/// By default the register is populated with zeros (which is an invalid
942/// status for ArC2) and must be configured appropriately by setting the
943/// invididual channels to a [`ChannelState`] value. The register will take
944/// care of flipping the correct bits in the internal representation in order
945/// to have a consistent 32bit representation.
946///
947/// **See also**: [`ChannelState`] for the available channel configurations.
948///
949/// ## Examples
950///
951/// ```
952/// use libarc2::registers::{ChannelConf, ChannelState, ToU32s};
953///
954/// // Initialise a new channel configuration register
955/// let mut reg = ChannelConf::new();
956///
957/// // Number of allocated channels
958/// let nchan = reg.len();
959///
960/// // Set channel 31 to High speed pulsing mode
961/// reg.set(31, ChannelState::HiSpeed);
962///
963/// // Set all channels to arbitrary voltage operation
964/// reg.set_all(ChannelState::VoltArb);
965///
966/// // Traverse channels (non-consuming iterator)
967/// for channel in &reg {
968///     println!("{:?}", channel);
969/// }
970///
971/// // Print the internal representation
972/// // Should return
973/// //  0x92492492
974/// //  0x49249249
975/// //  0x24924924
976/// //  0x92492492
977/// //  0x49249249
978/// //  0x24924924
979/// for value in reg.as_u32s() {
980///    println!("0x{:x}", value);
981/// }
982/// ```
983pub struct ChannelConf {
984    bits: BitVec<u32, Msb0>,
985}
986
987impl ChannelConf {
988
989    /// Create a new register with 64 channels.
990    /// This will be expanded to `CHANSIZE` × channels
991    /// in the internal bit vector representation.
992    pub fn new() -> ChannelConf {
993        // CHANSIZE bits for each channel
994        let size = consts::NCHANS * consts::CHANCONFSIZE;
995        let vec: BitVec<u32, Msb0> = BitVec::repeat(false, size);
996
997        ChannelConf { bits: vec }
998    }
999
1000    /// Create a new register with 64 channels and set all channels to
1001    /// the specified state.
1002    pub fn new_with_state(state: ChannelState) -> ChannelConf {
1003        let mut conf = ChannelConf::new();
1004        conf.set_all(state);
1005
1006        conf
1007    }
1008
1009    /// Create a new register from raw words. This is only meant
1010    /// to be used when reconstucting ChannelConfs from existing
1011    /// instructions and not when creating a new register from
1012    /// scratch.
1013    #[doc(hidden)]
1014    pub(crate) fn from_raw_words(words: &[u32]) -> ChannelConf {
1015        let size = consts::NCHANS * consts::CHANCONFSIZE;
1016        let mut vec: BitVec<u32, Msb0> = BitVec::with_capacity(size);
1017        vec.extend_from_raw_slice(words);
1018
1019        ChannelConf { bits: vec }
1020    }
1021
1022    /// Set a channel to a [`ChannelState`] value
1023    pub fn set(&mut self, idx: usize, val: ChannelState) {
1024        let bits = self.bits.as_mut_bitslice();
1025        let bools = val.as_bools();
1026
1027        for i in 0..bools.len() {
1028            let bitidx = consts::NCHANS*consts::CHANCONFSIZE -
1029                (consts::CHANCONFSIZE*idx+i) - 1;
1030            bits.set(bitidx, bools[i]);
1031        }
1032    }
1033
1034    /// Get the [`state`][`ChannelState`] of a channel
1035    pub fn get(&self, idx: usize) -> ChannelState {
1036        let from = consts::NCHANS*consts::CHANCONFSIZE - (consts::CHANCONFSIZE*idx+1) - 1;
1037        let to = consts::NCHANS*consts::CHANCONFSIZE - (consts::CHANCONFSIZE*(idx));
1038
1039        let v = &self.bits[from..to];
1040
1041        ChannelState::from_bitslice(v).unwrap()
1042    }
1043
1044    /// Get the number of allocated channels
1045    pub fn len(&self) -> usize {
1046        // len is always a multiple of CHANSIZE
1047        self.bits.len() / consts::CHANCONFSIZE
1048    }
1049
1050    /// Set the status of all channels to the same value
1051    pub fn set_all(&mut self, val: ChannelState) {
1052        let nchannels = self.len();
1053
1054        for i in 0..nchannels {
1055            self.set(i, val);
1056        }
1057    }
1058
1059    /// Generate a [`mask`][`ChanMask`] that contains all channels
1060    /// at the specified channel state. This is typically done through
1061    /// the [`UpdateChannel`][`crate::instruction::UpdateChannel`]
1062    /// instruction.
1063    ///
1064    /// ```
1065    /// use libarc2::instructions::*;
1066    /// use libarc2::registers::*;
1067    ///
1068    /// let mut conf = ChannelConf::new();
1069    /// conf.set(3, ChannelState::VoltArb);
1070    /// conf.set(19, ChannelState::VoltArb);
1071    /// let upch = UpdateChannel::from_regs_default_source(&conf);
1072    ///
1073    /// let mask = upch.mask(ChannelState::VoltArb);
1074    ///
1075    /// assert_eq!(mask.as_slice(), &[0x00000000, 0x00080008]);
1076    /// ```
1077    pub(crate) fn mask(&self, val: ChannelState) -> ChanMask {
1078        let mut mask = ChanMask::none();
1079
1080        for idx in 0..consts::NCHANS {
1081            if self.get(idx) == val {
1082                mask.set_enabled(idx, true);
1083            }
1084        }
1085
1086        mask
1087    }
1088
1089    /// Get the serialisable format of this register specified
1090    /// as a slice of whatever the internal representation is. This
1091    /// is presently a [`u32`] as this is the size of words that
1092    /// ArC2 is expecting as input.
1093    pub fn as_slice(&self) -> &[u32] {
1094        self.bits.as_raw_slice()
1095    }
1096}
1097
1098impl ToU32s for ChannelConf {
1099    fn as_u32s(&self) -> Vec<u32> {
1100        let bits = self.bits.as_raw_slice();
1101        bits.to_vec()
1102    }
1103}
1104
1105#[doc(hidden)]
1106pub struct ChannelConfIterator<'a> {
1107    register: &'a ChannelConf,
1108    index: usize,
1109}
1110
1111impl<'a> IntoIterator for &'a ChannelConf {
1112
1113    type Item = ChannelState;
1114    type IntoIter = ChannelConfIterator<'a>;
1115
1116    fn into_iter(self) -> Self::IntoIter {
1117        ChannelConfIterator {
1118            register: self,
1119            index: 0,
1120        }
1121    }
1122
1123}
1124
1125impl<'a> Iterator for ChannelConfIterator<'a> {
1126
1127    type Item = ChannelState;
1128
1129    fn next(&mut self) -> Option<ChannelState> {
1130        if self.index >= self.register.len() {
1131            return None;
1132        }
1133
1134        let v = self.register.get(self.index);
1135        self.index += 1;
1136        Some(v)
1137    }
1138
1139}
1140
1141
1142#[cfg(test)]
1143mod channelconf_tests {
1144
1145    use super::{ChannelConf, ChannelState};
1146    use crate::registers::ToU32s;
1147    use assert_matches::assert_matches;
1148
1149    #[test]
1150    fn get_channel() {
1151        let mut v = ChannelConf::new();
1152        v.set(50, ChannelState::VoltArb);
1153        let res = v.get(50);
1154        assert_matches!(res, ChannelState::VoltArb);
1155
1156        v.set(0, ChannelState::Open);
1157        let res = v.get(0);
1158        assert_matches!(res, ChannelState::Open);
1159
1160        v.set(63, ChannelState::HiSpeed);
1161        let res = v.get(63);
1162        assert_matches!(res, ChannelState::HiSpeed);
1163    }
1164
1165    #[test]
1166    fn channel_len() {
1167        let v = ChannelConf::new();
1168        assert_eq!(v.len(), 64);
1169    }
1170
1171    #[test]
1172    fn bools_to_status() {
1173        let status1 = ChannelState::from(&[true, false]);
1174        assert_matches!(status1, ChannelState::VoltArb);
1175
1176        let status2 = ChannelState::from(&[false, true]);
1177        assert_matches!(status2, ChannelState::Open);
1178    }
1179
1180    #[test]
1181    fn all_channel_test() {
1182        let mut v = ChannelConf::new();
1183        v.set_all(ChannelState::VoltArb);
1184
1185        for channel in &v {
1186            assert_matches!(channel, ChannelState::VoltArb);
1187        }
1188
1189        let slice = v.as_u32s();
1190
1191        assert_eq!(slice[0], 0xaaaaaaaa);
1192        assert_eq!(slice[1], 0xaaaaaaaa);
1193        assert_eq!(slice[2], 0xaaaaaaaa);
1194        assert_eq!(slice[3], 0xaaaaaaaa);
1195    }
1196
1197    #[test]
1198    fn new_all_channels() {
1199        let v = ChannelConf::new_with_state(ChannelState::VoltArb);
1200
1201        for channel in &v {
1202            assert_matches!(channel, ChannelState::VoltArb);
1203        }
1204
1205        let slice = v.as_u32s();
1206
1207        assert_eq!(slice[0], 0xaaaaaaaa);
1208        assert_eq!(slice[1], 0xaaaaaaaa);
1209        assert_eq!(slice[2], 0xaaaaaaaa);
1210        assert_eq!(slice[3], 0xaaaaaaaa);
1211    }
1212}
1213
1214bitflags! {
1215    /// Resistor selection for current source configuration
1216    ///
1217    /// Use this struct with [`CurrentSourceState::mos_with_resistors`] to
1218    /// create an appropriately configured register for sourcing/sinking
1219    /// current.
1220    pub struct CurrentSourceResistor: u8 {
1221        const R220K = 0b01000000;
1222        const R3_6M = 0b00100000;
1223        const R68M  = 0b00010000;
1224        const R51   = 0b00000100;
1225        const RDIGI = 0b00000010;
1226    }
1227}
1228
1229lazy_static! {
1230    static ref FIXED_RESISTORS: HashMap<CurrentSourceResistor, f32> = {
1231        let mut map: HashMap<CurrentSourceResistor, f32> = HashMap::new();
1232        map.insert(CurrentSourceResistor::R220K, 220e3);
1233        map.insert(CurrentSourceResistor::R3_6M, 3.6e6);
1234        map.insert(CurrentSourceResistor::R68M, 68e6);
1235        map.insert(CurrentSourceResistor::R51, 51.0);
1236        map
1237    };
1238}
1239
1240impl CurrentSourceResistor {
1241    fn value(self) -> Option<f32> {
1242        FIXED_RESISTORS.get(&self).copied()
1243    }
1244}
1245
1246
1247#[derive(Clone, Copy, FromPrimitive, ToPrimitive, PartialEq, Debug)]
1248#[repr(u8)]
1249pub enum CurrentSourceMOSFET {
1250    NMOS = 0b10000000,
1251    PMOS = 0b00001000
1252}
1253
1254#[derive(Debug)]
1255#[repr(transparent)]
1256pub struct CurrentSourceState(u8);
1257
1258impl CurrentSourceState {
1259
1260    /// Generate a new current source configuration connected to the
1261    /// internal 2.5 V reference source
1262    pub fn vref() -> CurrentSourceState {
1263        // Assert bits 0 and 7 (2.5V and NMOS)
1264        CurrentSourceState(0b10000001)
1265    }
1266
1267    /// Generate a current source configuration with either a PMOS or NMOS and at
1268    /// least one current source resistor. This can be any of the fixed series
1269    /// resistances or a digipot. Please not that the actual digipot value is not
1270    /// configured here but through the higher level instruction
1271    /// [`crate::instructions::UpdateChannel`].
1272    ///
1273    /// ```
1274    /// use libarc2::registers::{CurrentSourceState, CurrentSourceMOSFET};
1275    /// use libarc2::registers::CurrentSourceResistor;
1276    ///
1277    /// let state0 = CurrentSourceState::mos_with_resistors(
1278    ///     CurrentSourceMOSFET::PMOS, CurrentSourceResistor::R220K | CurrentSourceResistor::RDIGI);
1279    ///
1280    /// let rawval = state0.to_u8();
1281    /// assert_eq!(rawval, 0b01001010);
1282    /// assert!(rawval & CurrentSourceResistor::R220K.bits() > 0);
1283    /// assert!(rawval & CurrentSourceResistor::RDIGI.bits() > 0);
1284    /// assert!(rawval & CurrentSourceResistor::R51.bits() == 0);
1285    /// ```
1286    pub fn mos_with_resistors(mos: CurrentSourceMOSFET, res: CurrentSourceResistor)
1287        -> CurrentSourceState {
1288
1289        // This is safe as we know it fits in a u8
1290        let mut val: u8 = mos.to_u8().unwrap();
1291        val |= res.bits();
1292
1293        CurrentSourceState(val)
1294    }
1295
1296    /// Get the internal representation of this register
1297    pub fn to_u8(self) -> u8 {
1298        self.0
1299    }
1300
1301    /// Get selected MOSFET for this register
1302    pub fn get_mos(self) -> Option<CurrentSourceMOSFET> {
1303        if (self.0 & CurrentSourceMOSFET::NMOS.to_u8().unwrap()) > 0 {
1304            Some(CurrentSourceMOSFET::NMOS)
1305        } else if (self.0 & CurrentSourceMOSFET::PMOS.to_u8().unwrap()) > 0 {
1306            Some(CurrentSourceMOSFET::PMOS)
1307        } else {
1308            None
1309        }
1310    }
1311
1312    /// Returns the bitflags for the selected current source resistor,
1313    /// or None if no resistors are selected
1314    pub fn get_selected_resistors(self) -> Option<CurrentSourceResistor> {
1315        let v: u8 = self.0 & 0b01110110;
1316        if v == 0 {
1317            None
1318        } else {
1319            Some(CurrentSourceResistor { bits: v })
1320        }
1321    }
1322}
1323
1324
1325/// Output source configuration
1326///
1327/// This register configures the status of the output source and
1328/// it's usually followed by a
1329/// [`ChannelConf`][`crate::registers::ChannelConf`].
1330/// There are two things that are specified by this register. The
1331/// *output digipot* and the state of the *current source*.
1332pub struct SourceConf {
1333    bits: BitVec<u32, Msb0>
1334}
1335
1336impl SourceConf {
1337
1338    /// Create a new source configuration register. This will
1339    /// initialise the digipot to a safe value (`0x1CD` or roughly
1340    /// 11 kΩ).
1341    pub fn new() -> SourceConf {
1342        let mut vec: BitVec<u32, Msb0> = BitVec::repeat(false, 32);
1343        let bits = vec.as_mut_bitslice();
1344        bits[0..10].store(0x1CD as u16);
1345
1346        SourceConf { bits: vec }
1347    }
1348
1349    /// Set digipot raw value. This is clamped to 2^10-1
1350    pub fn set_digipot(&mut self, val: u16) {
1351        let actual_val;
1352        if val > 0x3ff {
1353            actual_val = 0x3ff;
1354        } else {
1355            actual_val = val;
1356        }
1357
1358        let bits = self.bits.as_mut_bitslice();
1359        bits[0..10].store(actual_val);
1360    }
1361
1362    /// Get the current digipot raw value.
1363    pub fn get_digipot(&self) -> u16 {
1364        self.bits[0..10].load()
1365    }
1366
1367    /// Set state output. See [`CurrentSourceState`] for possible
1368    /// values.
1369    pub fn set_cursource_state(&mut self, val: CurrentSourceState) {
1370        self.bits[24..32].store(val.to_u8());
1371    }
1372
1373    /// Retrieves the current source state stores in this register.
1374    pub fn get_cursource_state(&self) -> CurrentSourceState {
1375        let val = self.bits[24..32].load::<u8>();
1376        CurrentSourceState(val)
1377    }
1378
1379    fn _find_digipot_and_voltage(current: f32) -> Option<(f32, f32)> {
1380        let mut voltage: f32 = 1.0;
1381        let acurrent = current.abs();
1382
1383        // We start from 1.0 V and work our way down in 50 mV steps to
1384        // find the first valid digipot resistance. If we drop below
1385        // then no voltage/resistance configuration exists.
1386        while voltage > 0.049 {
1387            let res = voltage / acurrent;
1388            // Resistance must be between 670 Ω and 19.5 kΩ
1389            // (safe digipot values)
1390            if res < 19500.0 && res > 670.0 {
1391                return Some((voltage, res));
1392            }
1393            voltage -= 0.05;
1394        }
1395        None
1396    }
1397
1398    /// Construct a new source configuration for a specified current.
1399    /// This will also return the associated voltage drop required
1400    /// between the CREF and CSET references to satisfy the requirements.
1401    /// If no possible configuration exists for the selected current the
1402    /// function will return `None`.
1403    pub fn for_current(current: f32) -> Option<(SourceConf, f32)> {
1404
1405        let mut sourceconf = SourceConf::new();
1406
1407        let mosfet = if current > 0.0 {
1408            CurrentSourceMOSFET::NMOS
1409        } else {
1410            CurrentSourceMOSFET::PMOS
1411        };
1412
1413        // Check if we can produce the necessary current with on of the values
1414        // in the fixed resistor bank
1415        for res in &[CurrentSourceResistor::R51, CurrentSourceResistor::R220K,
1416            CurrentSourceResistor::R3_6M, CurrentSourceResistor::R68M] {
1417
1418            // unwrap here is safe as the fixed resistors have predefined
1419            // values in the FIXED_RESISTORS map
1420            let voltage = res.value().unwrap() * current.abs();
1421            if voltage > 0.05 && voltage <= 1.0 {
1422                // found voltage + resistor combination
1423                let state = CurrentSourceState::mos_with_resistors(mosfet, *res);
1424                sourceconf.set_cursource_state(state);
1425                return Some((sourceconf, voltage));
1426            }
1427        }
1428
1429        // If we reach this point it means we need to use the digipot instead of
1430        // the fixed resistors
1431        match Self::_find_digipot_and_voltage(current) {
1432            Some ((resistance, voltage)) => {
1433                let code = (1024.0*(1.0 - resistance/20000.0)).floor() as u16;
1434                let state = CurrentSourceState::mos_with_resistors(mosfet,
1435                    CurrentSourceResistor::RDIGI);
1436                sourceconf.set_digipot(code);
1437                sourceconf.set_cursource_state(state);
1438                Some((sourceconf, voltage))
1439            }
1440            None => None
1441        }
1442
1443    }
1444
1445}
1446
1447impl ToU32s for SourceConf {
1448    fn as_u32s(&self) -> Vec<u32> {
1449        let bits = self.bits.as_raw_slice();
1450        bits.to_vec()
1451    }
1452}
1453
1454#[cfg(test)]
1455mod sourceconftests {
1456
1457    use super::{SourceConf, ToU32s};
1458
1459    #[test]
1460    fn test_sourceconf() {
1461        let mut c = SourceConf::new();
1462        c.set_digipot(0x200);
1463        assert_eq!(c.get_digipot(), 0x200);
1464
1465        let slice = c.as_u32s();
1466        assert_eq!(slice[0], 0x80000000);
1467
1468        // Digipot must never exceed 0x3ff
1469        c.set_digipot(0x500);
1470        assert_eq!(c.get_digipot(), 0x3ff);
1471
1472    }
1473}
1474
1475
1476const DACVZERO: u32 = 0x80008000;
1477
1478/// Voltage configuration for DACs
1479///
1480/// This struct is used to configure the output voltages of the on-board
1481/// DACs. DAC voltage are represented with a `u16` value, `0x0000` being
1482/// the lowest possible voltage and `0xFFFF` being the highest. Assuming
1483/// the absolute maximum voltages are the same for two polarities value
1484/// `0x8000` is 0.0 volts which is the default value used when creating
1485/// this register.
1486///
1487/// DACs have two outputs, upper and lower with upper > lower in
1488/// most circumstances. These are represented by a single word (u32) with
1489/// the upper 16 bits containing the upper voltage and the lower 16 bits
1490/// the lower voltage. In normal non fast pulsing scenarios both output
1491/// voltages should be the same and the user is advised to use the
1492/// [`DACVoltage::set()`] function to set a voltage for a DAC. By
1493/// default a new `DACVoltage` has four different channels as this
1494/// is exactly the number of channels that fit in 1/2 of a DAC cluster.
1495/// See documentation of [`DACMask`][`crate::registers::DACMask`] for
1496/// more details on that.
1497///
1498/// ## Examples
1499/// ```
1500/// use libarc2::registers::DACVoltage;
1501///
1502/// // Make a new register
1503/// let mut reg0 = DACVoltage::new();
1504/// // Set both values of the second channel
1505/// reg0.set(1, 0x8534);
1506/// assert_eq!(reg0.get(1), (0x8534, 0x8534));
1507///
1508/// let mut reg1 = DACVoltage::new();
1509/// // Set the upper half voltage of the third channel
1510/// reg1.set_upper(2, 0x8534);
1511/// assert_eq!(reg1.get(2), (0x8000, 0x8534));
1512/// ```
1513pub struct DACVoltage {
1514    values: Vec<u32>
1515}
1516
1517impl DACVoltage {
1518
1519    const NUMVOLTAGES: usize = 4;
1520
1521    /// Create a new register with four channels
1522    pub fn new() -> DACVoltage {
1523        Self::new_with_size_and_voltage(Self::NUMVOLTAGES, DACVZERO)
1524    }
1525
1526    /// Create a new register with all four channels set at
1527    /// the specified levels
1528    ///
1529    /// ```
1530    /// use libarc2::registers::{DACVoltage, ToU32s};
1531    ///
1532    /// let reg = DACVoltage::new_at_levels(0xaaaa, 0xbbbb);
1533    ///
1534    /// for i in 0..4 {
1535    ///     assert_eq!(reg.get(i), (0xaaaa, 0xbbbb));
1536    /// }
1537    ///
1538    /// assert_eq!(reg.as_u32s(), &[0xbbbbaaaa, 0xbbbbaaaa,
1539    ///     0xbbbbaaaa, 0xbbbbaaaa]);
1540    /// ```
1541    pub fn new_at_levels(low: u16, high: u16) -> DACVoltage {
1542        let voltage: u32 =
1543            ((high as u32) << 16) | ((low as u32) & 0xFFFF);
1544        Self::new_with_size_and_voltage(4, voltage)
1545    }
1546
1547    fn new_with_size_and_voltage(size: usize, volt: u32) -> DACVoltage {
1548        let mut vec: Vec<u32> = Vec::with_capacity(size);
1549
1550        for _ in 0..size {
1551            vec.push(volt);
1552        }
1553
1554        DACVoltage { values: vec }
1555    }
1556
1557    pub(crate) fn from_raw_values(values: &[u32]) -> DACVoltage {
1558        DACVoltage { values: values.to_vec() }
1559    }
1560
1561    // Similar to `from_raw_values` but Optional inputs, Somes will
1562    // be unwrapped, Nones will be replaced with zero
1563    pub(crate) fn from_raw_values_opt(values: &[Option<u32>]) -> DACVoltage {
1564        let mut raw_values = Vec::with_capacity(Self::NUMVOLTAGES);
1565        for value in values {
1566            let raw = match value {
1567                Some(v) => *v,
1568                None => DACVZERO
1569            };
1570            raw_values.push(raw);
1571        }
1572
1573        DACVoltage { values: raw_values }
1574    }
1575
1576    /// Set the upper value of a specified channel index
1577    pub fn set_upper(&mut self, idx: usize, voltage: u16) {
1578        self.values[idx] = (voltage as u32) << 16 |
1579            (self.values[idx] & 0xFFFF);
1580    }
1581
1582    /// Get the upper value of a specified channel index
1583    pub fn get_upper(&self, idx: usize) -> u16 {
1584        ((self.values[idx] & 0xFFFF0000) >> 16) as u16
1585    }
1586
1587    /// Set the lower value of a specified channel index
1588    pub fn set_lower(&mut self, idx: usize, voltage: u16) {
1589        self.values[idx] = (voltage as u32) <<  0 |
1590            (self.values[idx] & 0xFFFF0000);
1591    }
1592
1593    /// Get the lower value of a specified channel index
1594    pub fn get_lower(&self, idx: usize) -> u16 {
1595        (self.values[idx] & 0xFFFF) as u16
1596    }
1597
1598    /// Set both upper and lower of a specified channel index
1599    pub fn set(&mut self, idx: usize, voltage: u16) {
1600        self.set_lower(idx, voltage);
1601        self.set_upper(idx, voltage);
1602    }
1603
1604    /// Get both upper and lower of a specified channel index.
1605    /// The first `u16` of the tuple is lower, the second upper.
1606    pub fn get(&self, idx: usize) -> (u16, u16) {
1607        (self.get_lower(idx), self.get_upper(idx))
1608    }
1609
1610    /// Number of configured channels
1611    pub fn len(&self) -> usize {
1612        Self::NUMVOLTAGES
1613    }
1614
1615}
1616
1617impl ToU32s for DACVoltage {
1618    fn as_u32s(&self) -> Vec<u32> {
1619        self.values.clone()
1620    }
1621}
1622
1623#[cfg(test)]
1624mod dacvoltage_tests {
1625
1626    use super::{DACVoltage};
1627
1628    #[test]
1629    fn dacvoltage_new() {
1630        let v = DACVoltage::new();
1631        for value in v.values {
1632            assert_eq!(value, 0x80008000);
1633        }
1634    }
1635
1636    #[test]
1637    fn dacvoltage_set_upper() {
1638        let mut v = DACVoltage::new();
1639        v.set_upper(3, 0xA0A0);
1640
1641        assert_eq!(v.values[3], 0xA0A08000);
1642        assert_eq!(v.get_upper(3), 0xA0A0);
1643        assert_eq!(v.get_lower(3), 0x8000);
1644    }
1645
1646    #[test]
1647    fn dacvoltage_set_lower() {
1648        let mut v = DACVoltage::new();
1649        v.set_lower(2, 0x90F3);
1650
1651        assert_eq!(v.values[2], 0x800090F3);
1652        assert_eq!(v.get_upper(2), 0x8000);
1653        assert_eq!(v.get_lower(2), 0x90F3);
1654    }
1655
1656    #[test]
1657    fn dacvoltage_set_both() {
1658        let mut v = DACVoltage::new();
1659
1660        v.set(1, 0x8534);
1661        assert_eq!(v.values[1], 0x85348534);
1662        assert_eq!(v.get_lower(1), 0x8534);
1663        assert_eq!(v.get_upper(1), 0x8534);
1664        assert_eq!(v.get(1), (0x8534, 0x8534));
1665    }
1666
1667}
1668
1669
1670bitflags! {
1671    /// Channel selector for DAC half-clusters
1672    ///
1673    /// [`DACVoltageMask`] is used to create a bitmask that limits
1674    /// the application of a [`SetDAC`][`crate::instructions::SetDAC`]
1675    /// instruction to one or more channels. Typically ArC2 will apply
1676    /// the configured voltages to all four channels of a DAC half-cluster
1677    /// but this can be limited to specific channels if a suitable
1678    /// [`DACVoltageMask`] is supplied.
1679    pub struct DACVoltageMask: u32 {
1680        /// Select no channels
1681        const NONE = 0b00000000000000000000000000000000;
1682        /// Channel 0
1683        const CH0  = 0b00000000000000000000000000001000;
1684        /// Channel 1
1685        const CH1  = 0b00000000000000000000000000000100;
1686        /// Channel 2
1687        const CH2  = 0b00000000000000000000000000000010;
1688        /// Channel 3
1689        const CH3  = 0b00000000000000000000000000000001;
1690        /// Select all channels
1691        const ALL  = Self::CH0.bits | Self::CH1.bits |
1692                     Self::CH2.bits | Self::CH3.bits;
1693    }
1694}
1695
1696impl DACVoltageMask {
1697
1698    const ALL_MASKS: [Self; 4] = [Self::CH0, Self::CH1, Self::CH2, Self::CH3];
1699
1700    /// Create a new DACVoltageMask from individual indices within a
1701    /// DAC half-cluster
1702    pub(crate) fn from_indices(indices: &[usize]) -> Self {
1703        let mut mask = Self::NONE;
1704        for idx in indices {
1705
1706            if *idx >= 4 {
1707                break;
1708            }
1709
1710            mask |= Self::ALL_MASKS[*idx]
1711        }
1712
1713        mask
1714    }
1715
1716    /// Create a new DACVoltageMask from individual voltages within
1717    /// a DAC half-cluster. This must be 4-items long, None values will
1718    /// deselect the associated index
1719    pub(crate) fn from_indices_opt<T>(voltages: &[Option<T>]) -> Self {
1720        let mut mask = Self::NONE;
1721        for (idx, smth) in voltages.iter().enumerate() {
1722            if idx >=4 {
1723                break;
1724            }
1725
1726            if smth.is_some() {
1727                mask |= Self::ALL_MASKS[idx];
1728            }
1729        }
1730
1731        mask
1732    }
1733}
1734
1735impl From<&DACVoltageMask> for u32 {
1736    fn from(mask: &DACVoltageMask) -> u32 {
1737        mask.bits() as u32
1738    }
1739}
1740
1741impl ToU32s for DACVoltageMask {
1742    fn as_u32s(&self) -> Vec<u32> {
1743        [u32::from(self)].to_vec()
1744    }
1745}
1746
1747
1748/// A generic bitmask of the specified word size
1749#[derive(Clone, Debug, PartialEq)]
1750pub struct U32Mask<T> {
1751    _words: T,
1752    bits: BitVec<u32, Msb0>,
1753}
1754
1755
1756impl<T: wordreg::WordSize> U32Mask<T> {
1757
1758    /// Set a channel to enabled (`true`) or disabled (`false`).
1759    pub fn set_enabled(&mut self, idx: usize, status: bool) {
1760        let len = self.bits.len();
1761        let bits = self.bits.as_mut_bitslice();
1762        bits.set(len-1-idx, status)
1763    }
1764
1765    /// Get the state of a channel, enabled (`true`) or disabled (`false`).
1766    pub fn get_enabled(&self, idx: usize) -> bool {
1767        let len = self.bits.len();
1768        self.bits[len-1-idx]
1769    }
1770
1771    /// Get the number of allocated channels.
1772    pub fn len(&self) -> usize {
1773        self.bits.len()
1774    }
1775
1776    /// Set all channels to enabled (`true`) or disabled (`false`).
1777    pub fn set_enabled_all(&mut self, status: bool) {
1778        let len = self.bits.len();
1779        let bits = self.bits.as_mut_bitslice();
1780        for i in 0..len {
1781            bits.set(len-1-i, status)
1782        }
1783    }
1784
1785    /// Toggle selected channel.
1786    pub fn toggle(&mut self, idx: usize) {
1787        self.set_enabled(idx, !self.get_enabled(idx));
1788    }
1789
1790    /// Get the serialisable format of this register specified
1791    /// as a slice of whatever the internal representation is. This
1792    /// is presently a [`u32`] as this is the size of words that
1793    /// ArC2 is expecting as input.
1794    pub fn as_slice(&self) -> &[u32] {
1795        self.bits.as_raw_slice()
1796    }
1797
1798}
1799
1800// Used to create the `from_vals` and `from_indices` function of U32Mask<T>
1801macro_rules! make_from_values_impl {
1802    ($ws:ty, $wx:expr) => {
1803
1804        /// Create a new [`U32Mask`] from an existing bitvec
1805        #[allow(dead_code)]
1806        pub(crate) fn from_bitvec(vec: BitVec<u32, Msb0>) -> U32Mask<$ws> {
1807            U32Mask { _words: $wx, bits: vec }
1808        }
1809
1810        /// Create a new [`U32Mask`] from a series of `u32s`.
1811        pub fn from_vals(vals: &[u32]) -> U32Mask<$ws> {
1812            let mut vec: BitVec<u32, Msb0> = BitVec::repeat(false, <$ws>::WORDS*32);
1813            for idx in 0..vals.len() {
1814                vec[idx*32..(idx+1)*32].store::<u32>(vals[idx]);
1815            }
1816
1817            U32Mask { _words: $wx, bits: vec }
1818        }
1819
1820        /// Create a new [`U32Mask`] from a series of selected indices
1821        pub fn from_indices(chans: &[usize]) -> U32Mask<$ws> {
1822            let mut mask = Self::new();
1823
1824            for c in chans {
1825                if *c >= <$ws>::WORDS*32 { continue; }
1826                mask.set_enabled(*c, true);
1827            }
1828
1829            mask
1830        }
1831
1832        /// Create a new bitmask with no channels selected
1833        pub fn none() -> Self {
1834            Self::new()
1835        }
1836
1837        /// Create a new bitmask with all channels selected
1838        pub fn all() -> Self {
1839            let mut mask = Self::new();
1840            mask.set_enabled_all(true);
1841
1842            mask
1843        }
1844
1845        /// Create a new bitmask with all channels in `chans` selected
1846        pub fn from_channels(chans: &[usize]) -> Self {
1847            let mut mask = Self::new();
1848            for c in chans {
1849                mask.set_enabled(*c, true);
1850            }
1851
1852            mask
1853        }
1854
1855        /// Set all the channels from `chans` to the specified state. This
1856        /// will add to the existing channels
1857        pub fn set_channels_enabled(&mut self, chans: &[usize], enabled: bool) {
1858            for c in chans {
1859                self.set_enabled(*c, enabled);
1860            }
1861        }
1862
1863        /// Get a list of the enabled channels for this mask
1864        pub fn channels(&self) -> Vec<usize> {
1865
1866            let mut res: Vec<usize> = Vec::with_capacity(consts::NCHANS);
1867
1868            for ch in 0..consts::NCHANS {
1869                if self.get_enabled(ch) {
1870                    res.push(ch);
1871                }
1872            }
1873
1874            res
1875
1876        }
1877
1878        /// Check if no channels are selected in this bitmask
1879        pub fn is_empty(&self) -> bool {
1880            *self == Self::none()
1881        }
1882    }
1883}
1884
1885impl<T: wordreg::WordSize> ToU32s for U32Mask<T> {
1886    fn as_u32s(&self) -> Vec<u32> {
1887        self.bits.as_raw_slice().to_vec()
1888    }
1889}
1890
1891impl U32Mask<wordreg::Wx1> {
1892    pub fn new() -> U32Mask<wordreg::Wx1> {
1893        let vec: BitVec<u32, Msb0> = BitVec::repeat(false, wordreg::Wx1::WORDS*32);
1894        U32Mask { _words: wordreg::Wx1{}, bits: vec }
1895    }
1896
1897    make_from_values_impl!(wordreg::Wx1, wordreg::Wx1{});
1898}
1899
1900impl U32Mask<wordreg::Wx2> {
1901    pub fn new() -> U32Mask<wordreg::Wx2> {
1902        let vec: BitVec<u32, Msb0> = BitVec::repeat(false, wordreg::Wx2::WORDS*32);
1903        U32Mask { _words: wordreg::Wx2{}, bits: vec }
1904    }
1905
1906    make_from_values_impl!(wordreg::Wx2, wordreg::Wx2{});
1907}
1908
1909impl U32Mask<wordreg::Wx3> {
1910    pub fn new() -> U32Mask<wordreg::Wx3> {
1911        let vec: BitVec<u32, Msb0> = BitVec::repeat(false, wordreg::Wx3::WORDS*32);
1912        U32Mask { _words: wordreg::Wx3{}, bits: vec }
1913    }
1914
1915    make_from_values_impl!(wordreg::Wx3, wordreg::Wx3{});
1916}
1917
1918impl U32Mask<wordreg::Wx4> {
1919    pub fn new() -> U32Mask<wordreg::Wx4> {
1920        let vec: BitVec<u32, Msb0> = BitVec::repeat(false, wordreg::Wx4::WORDS*32);
1921        U32Mask { _words: wordreg::Wx4{}, bits: vec }
1922    }
1923
1924    make_from_values_impl!(wordreg::Wx4, wordreg::Wx4{});
1925}
1926
1927
1928/// Channel configuration bitmask.
1929///
1930/// A `ChanMask` is used to select one or more channels. Essentially
1931/// it defines which channels the Read Current, Read Voltage, Amp Prep
1932/// or Modify Channel operations are applied to.
1933///
1934/// See [`U32Mask`][`crate::registers::U32Mask`] for details and
1935/// methods.
1936///
1937/// ## Example
1938///
1939/// ### Toggling individual channels
1940/// ```
1941/// use libarc2::registers::{ChanMask, ToU32s};
1942///
1943/// // new chanmask with everything set to 0
1944/// let mut chan = ChanMask::new();
1945///
1946/// // set some channels
1947/// chan.set_enabled(31, true);
1948/// chan.set_enabled(0, true);
1949/// chan.set_enabled(62, true);
1950///
1951/// assert_eq!(chan.get_enabled(31), true);
1952///
1953/// // u32 representation
1954/// assert_eq!(chan.as_u32s(), &[0x40000000, 0x80000001]);
1955/// ```
1956/// ### Creating a mask from a set of indices
1957/// ```
1958/// use libarc2::registers::{ChanMask, ToU32s};
1959///
1960/// let channels: Vec<usize> = vec![0, 7, 45];
1961/// let chan = ChanMask::from_indices(&channels);
1962/// assert_eq!(chan.get_enabled(0), true);
1963/// assert_eq!(chan.get_enabled(7), true);
1964/// assert_eq!(chan.get_enabled(45), true)
1965///
1966/// ```
1967///
1968///
1969pub type ChanMask = U32Mask<wordreg::Wx2>;
1970
1971impl Not for &ChanMask {
1972
1973    type Output = ChanMask;
1974
1975    fn not(self) -> Self::Output {
1976        let mut output = ChanMask::new();
1977
1978        let slice = self.bits.as_bitslice();
1979
1980        for i in 0..slice.len() {
1981            output.set_enabled(consts::NCHANS-1-i, !slice[i]);
1982        }
1983
1984        output
1985    }
1986}
1987
1988impl BitAnd for &ChanMask {
1989
1990    type Output = ChanMask;
1991
1992    fn bitand(self, other: Self) -> Self::Output {
1993        let mut output = ChanMask::new();
1994
1995        let slice = self.bits.as_bitslice();
1996        let other = other.bits.as_bitslice();
1997
1998        for (i, (t, o)) in zip(slice, other).enumerate() {
1999            output.set_enabled(consts::NCHANS-1-i, *t & *o);
2000        }
2001
2002        output
2003
2004    }
2005
2006}
2007
2008impl BitXor for &ChanMask {
2009
2010    type Output = ChanMask;
2011
2012    fn bitxor(self, other: Self) -> Self::Output {
2013        let mut output = ChanMask::new();
2014
2015        let slice = self.bits.as_bitslice();
2016        let other = other.bits.as_bitslice();
2017
2018        for (i, (t, o)) in zip(slice, other).enumerate() {
2019            output.set_enabled(consts::NCHANS-1-i, *t ^ *o);
2020        }
2021        output
2022    }
2023
2024}
2025
2026impl BitOr for &ChanMask {
2027    type Output = ChanMask;
2028
2029    fn bitor(self, other: Self) -> Self::Output {
2030        let mut output = ChanMask::new();
2031
2032        let slice = self.bits.as_bitslice();
2033        let other = other.bits.as_bitslice();
2034
2035        for (i, (t, o)) in zip(slice, other).enumerate() {
2036            output.set_enabled(consts::NCHANS-1-i, *t | *o);
2037        }
2038        output
2039    }
2040}
2041
2042/// Arbitrary DAC Channel configuration bitmask.
2043///
2044/// Similar to [`ChanMask`][`crate::registers::ChanMask`] this is
2045/// used to select the channels of arbitrary DACs.
2046pub type ArbMask = U32Mask<wordreg::Wx1>;
2047
2048impl ArbMask {
2049    pub(crate) fn from_aux_channels(chans: &[AuxDACFn]) -> Self {
2050        let mut mask = ArbMask::none();
2051        for c in chans {
2052            // special handling for the Logic range DAC
2053            let idx = if *c == AuxDACFn::LGC {
2054                LGCRNGIDX
2055            } else { AUXFNRNGMAP[*c as usize] };
2056            mask.set_enabled(idx, true);
2057        }
2058
2059        mask
2060    }
2061}
2062
2063impl Not for &ArbMask {
2064    type Output = ArbMask;
2065
2066    fn not(self) -> Self::Output {
2067        let mut output = ArbMask::new();
2068
2069        let slice = self.bits.as_bitslice();
2070
2071        for i in 0..slice.len() {
2072            output.set_enabled(consts::AUXNCHANS-1-i, !slice[i]);
2073        }
2074
2075        output
2076    }
2077
2078}
2079
2080impl BitAnd for &ArbMask {
2081
2082    type Output = ArbMask;
2083
2084    fn bitand(self, other: Self) -> Self::Output {
2085        let mut output = ArbMask::new();
2086
2087        let slice = self.bits.as_bitslice();
2088        let other = other.bits.as_bitslice();
2089
2090        for (i, (t, o)) in zip(slice, other).enumerate() {
2091            output.set_enabled(consts::AUXNCHANS-1-i, *t & *o);
2092        }
2093
2094        output
2095    }
2096
2097}
2098
2099impl BitXor for &ArbMask {
2100
2101    type Output = ArbMask;
2102
2103    fn bitxor(self, other: Self) -> Self::Output {
2104        let mut output = ArbMask::new();
2105
2106        let slice = self.bits.as_bitslice();
2107        let other = other.bits.as_bitslice();
2108
2109        for (i, (t, o)) in zip(slice, other).enumerate() {
2110            output.set_enabled(consts::AUXNCHANS-1-i, *t ^ *o);
2111        }
2112        output
2113    }
2114
2115}
2116
2117impl BitOr for &ArbMask {
2118    type Output = ArbMask;
2119
2120    fn bitor(self, other: Self) -> Self::Output {
2121        let mut output = ArbMask::new();
2122
2123        let slice = self.bits.as_bitslice();
2124        let other = other.bits.as_bitslice();
2125
2126        for (i, (t, o)) in zip(slice, other).enumerate() {
2127            output.set_enabled(consts::AUXNCHANS-1-i, *t | *o);
2128        }
2129        output
2130    }
2131}
2132
2133/// Selector selection bitmask
2134///
2135/// A `SelectorMask` is used to select which selector circuits are
2136/// enabled. Selectors are essentially exposed as a set of 32
2137/// dedicated digital channels. Unlike generic I/O channels selector
2138/// circuits are output only.
2139pub type SelectorMask = U32Mask<wordreg::Wx1>;
2140
2141
2142/// Averaging for read operations
2143#[derive(Clone, Copy, FromPrimitive, ToPrimitive, Debug)]
2144#[repr(u32)]
2145pub enum Averaging {
2146    Enabled = 1,
2147    Disabled = 0
2148}
2149
2150impl ToU32s for Averaging {
2151    fn as_u32s(&self) -> Vec<u32> {
2152        vec![*self as u32; 1]
2153    }
2154}
2155
2156
2157#[cfg(test)]
2158mod adcmask_tests {
2159    use super::ChanMask;
2160    use crate::registers::ToU32s;
2161
2162    #[test]
2163    fn get_set_channel() {
2164        let mut v = ChanMask::new();
2165        v.set_enabled(31, true);
2166        v.set_enabled(0, true);
2167        v.set_enabled(62, true);
2168
2169        assert_eq!(v.get_enabled(31), true);
2170        assert_eq!(v.get_enabled(0), true);
2171        assert_eq!(v.get_enabled(62), true);
2172
2173        v.set_enabled(62, false);
2174        assert_eq!(v.get_enabled(62), false);
2175
2176    }
2177
2178    #[test]
2179    fn get_set_all_channels() {
2180        let mut v = ChanMask::new();
2181        v.set_enabled_all(true);
2182
2183        for c in 0..v.len() {
2184            assert_eq!(v.get_enabled(c), true);
2185        }
2186
2187    }
2188
2189    #[test]
2190    fn repr() {
2191        let mut v = ChanMask::new();
2192        v.set_enabled(31, true);
2193        v.set_enabled(0, true);
2194        v.set_enabled(62, true);
2195
2196        assert_eq!(&v.as_u32s(), &[0x40000000, 0x80000001]);
2197
2198    }
2199
2200    #[test]
2201    fn toggle() {
2202        let mut v = ChanMask::new();
2203        v.set_enabled(31, true);
2204        v.set_enabled(0, true);
2205        v.set_enabled(62, true);
2206
2207        assert_eq!(v.get_enabled(31), true);
2208
2209        v.toggle(31);
2210        assert_eq!(v.get_enabled(31), false);
2211    }
2212
2213}
2214
2215
2216/// I/O channel configuration bitmask.
2217///
2218/// An `IOMask` is used to configure the I/O channels of ArC2. Essentially
2219/// it defines which channels will be configured during the Update I/O
2220/// instruction.
2221///
2222/// See [`U32Mask`][`crate::registers::U32Mask`] for details and
2223/// methods.
2224///
2225/// ## Example
2226/// ```
2227/// use libarc2::registers::{IOMask, ToU32s};
2228///
2229/// let mut chan = IOMask::new();
2230///
2231/// // set some channels
2232/// chan.set_enabled(31, true);
2233/// chan.set_enabled(0, true);
2234///
2235/// assert_eq!(chan.get_enabled(31), true);
2236///
2237/// // u32 representation
2238/// assert_eq!(chan.as_u32s(), &[0x80000001]);
2239/// ```
2240pub type IOMask = U32Mask<wordreg::Wx1>;
2241
2242
2243#[cfg(test)]
2244mod iomask_tests {
2245    use super::IOMask;
2246    use crate::registers::ToU32s;
2247
2248    #[test]
2249    fn get_set_channel() {
2250        let mut v = IOMask::new();
2251        v.set_enabled(31, true);
2252        v.set_enabled(0, true);
2253
2254        assert_eq!(v.get_enabled(31), true);
2255        assert_eq!(v.get_enabled(0), true);
2256
2257        v.set_enabled(31, false);
2258        assert_eq!(v.get_enabled(31), false);
2259
2260    }
2261
2262    #[test]
2263    fn get_set_all_channels() {
2264        let mut v = IOMask::new();
2265        v.set_enabled_all(true);
2266
2267        for c in 0..v.len() {
2268            assert_eq!(v.get_enabled(c), true);
2269        }
2270
2271    }
2272
2273    #[test]
2274    fn repr() {
2275        let mut v = IOMask::new();
2276        v.set_enabled(31, true);
2277        v.set_enabled(0, true);
2278
2279        assert_eq!(&v.as_u32s(), &[0x80000001]);
2280
2281    }
2282
2283    #[test]
2284    fn from_vals() {
2285        let mut v = IOMask::from_vals(&[0x80000001]);
2286
2287        assert_eq!(&v.as_u32s(), &[0x80000001]);
2288        assert_eq!(v.get_enabled(31), true);
2289        assert_eq!(v.get_enabled(0), true);
2290        v.set_enabled(1, true);
2291        assert_eq!(&v.as_u32s(), &[0x80000003]);
2292
2293    }
2294
2295    #[test]
2296    fn toggle() {
2297        let mut v = IOMask::new();
2298        v.set_enabled(31, true);
2299        v.set_enabled(0, true);
2300
2301        assert_eq!(v.get_enabled(31), true);
2302
2303        v.toggle(31);
2304        assert_eq!(v.get_enabled(31), false);
2305    }
2306
2307}
2308
2309/// IO Direction for logic instructions. This is typically used to
2310/// set the direction of the 4 GPIO clusters (4×8 channels). There
2311/// are obviously only two options.
2312#[derive(PartialEq, Copy, Clone)]
2313pub struct IODir(bool);
2314
2315impl IODir {
2316    /// Set IO cluster as input
2317    pub const IN: IODir = Self(false);
2318    /// Set IO cluster as output
2319    pub const OUT: IODir = Self(true);
2320}
2321
2322/// IO enable configuration register.
2323///
2324/// Use this register to set whether I/Os are enabled and what's
2325/// their direction.
2326///
2327/// This register is laid out as a 4 bit bitmask plus one EN bit.
2328///
2329/// ```text
2330/// 0b[X][ CH3 CH2 CH1 CH0 ]
2331///    |    |   |   |   |
2332///    |    +---+---+---+ --- Set direction: LOW input; high OUPUT
2333///    |
2334///    + --- Set low to enable
2335/// ```
2336///
2337/// ## Example
2338/// ```
2339/// use libarc2::registers::{IOEnable, ToU32s};
2340///
2341/// // all IOs disabled and set as output: 0b[1][1111]
2342/// let none = IOEnable::new();
2343///
2344/// assert_eq!(none.as_u32s(), &[0x1f]);
2345///
2346/// // all IOs enabled and set as output: 0b[0][1111]
2347/// let all_outputs = IOEnable::all_output();
2348///
2349/// assert_eq!(all_outputs.as_u32s(), &[0xf]);
2350/// ```
2351pub struct IOEnable {
2352    bits: BitVec<u32, Lsb0>,
2353}
2354
2355impl IOEnable {
2356    const LEN: usize = 5;
2357
2358    /// Create a new `IOEnable`. IOs are OFF and set as outputs
2359    pub fn new() -> IOEnable {
2360        let vec: BitVec<u32, Lsb0> = BitVec::repeat(false, Self::LEN);
2361        let mut io = IOEnable { bits: vec };
2362        io.set_all_outputs(true);
2363
2364        // IO is active low so we must set it to 1
2365        io.set_en(false);
2366
2367        io
2368    }
2369
2370    /// Create a new `IOEnable` with all IOs enabled and set to output
2371    pub fn all_output() -> IOEnable {
2372        Self::with_iodirs(IODir::OUT, IODir::OUT, IODir::OUT, IODir::OUT)
2373    }
2374
2375    /// Create a new `IOEnable` with all IOs enabled and set to input
2376    pub fn all_input() -> IOEnable {
2377        Self::with_iodirs(IODir::IN, IODir::IN, IODir::IN, IODir::IN)
2378    }
2379
2380    /// Create a new `IOEnable` with the IO clusters set at the specified
2381    /// directions. Each cluster represents a contiguous block of 8 GPIOs.
2382    /// Cluster 0: 0–7, Cluster 1: 8–15, Cluster 2: 16-23, Cluster 4: 24–32.
2383    pub fn with_iodirs(cl0: IODir, cl1: IODir, cl2: IODir, cl3: IODir) -> IOEnable {
2384        let vec: BitVec<u32, Lsb0> = BitVec::repeat(false, Self::LEN);
2385        let mut io = IOEnable { bits: vec };
2386        io.set_en(true);
2387
2388        if cl0 == IODir::OUT {
2389            io.set_output(0, true);
2390        }
2391
2392        if cl1 == IODir::OUT {
2393            io.set_output(1, true);
2394        }
2395
2396        if cl2 == IODir::OUT {
2397            io.set_output(2, true);
2398        }
2399
2400        if cl3 == IODir::OUT {
2401            io.set_output(3, true);
2402        }
2403
2404        io
2405    }
2406
2407    /// Toggle the enable bit
2408    pub fn set_en(&mut self, status: bool) {
2409        // IO Enable is active low
2410        self.set_output(Self::LEN-1, !status);
2411    }
2412
2413    pub fn get_en(&self) -> bool {
2414        !self.bits[Self::LEN-1]
2415    }
2416
2417    /// Set an I/O cluster as output (`true`) or not (`false`)
2418    ///
2419    /// ```text
2420    /// 0b[X][ CH3 CH2 CH1 CH0 ]
2421    ///    |    |   |   |   |
2422    ///    |    +---+---+---+ --- Set direction: LOW input; high OUPUT
2423    ///    |
2424    ///    + --- Set low to enable
2425    /// ```
2426    pub fn set_output(&mut self, idx: usize, status: bool) {
2427        self.bits.set(idx, status);
2428    }
2429
2430    /// Set all I/O clusters as output (`true`) or not (`false`)
2431    pub fn set_all_outputs(&mut self, status: bool) {
2432        for i in 0..(Self::LEN-1) {
2433            self.set_output(i, status);
2434        }
2435    }
2436
2437}
2438
2439impl ToU32s for IOEnable {
2440    fn as_u32s(&self) -> Vec<u32> {
2441        self.bits.as_raw_slice().to_vec()
2442    }
2443}
2444
2445#[cfg(test)]
2446mod ioenable_tests {
2447    use super::{IOEnable, ToU32s};
2448
2449    #[test]
2450    fn ioenable_new() {
2451        // 0b[ 1 ] [ 1111 ]
2452        //     ^     ^^^^
2453        //     |     ||||
2454        //     |     ++++----- all four clusters as outputs...
2455        //     +-- ... and disabled (active low)
2456        assert_eq!(IOEnable::new().as_u32s(), &[0x1f]);
2457    }
2458
2459    #[test]
2460    fn ioenable_all() {
2461        // 0b[ 0 ] [ 1111 ]
2462        //     ^     ^^^^
2463        //     |     ||||
2464        //     |     ++++----- all four clusters as outputs...
2465        //     +-- ... and enabled (active low)
2466        assert_eq!(IOEnable::all_output().as_u32s(), &[0xf]);
2467    }
2468
2469
2470    #[test]
2471    fn ioenable_new_mut() {
2472        let mut io = IOEnable::new();
2473        io.set_en(true);
2474        io.set_output(0, true);
2475        io.set_output(1, true);
2476        io.set_output(2, false);
2477        io.set_output(3, true);
2478
2479        assert_eq!(io.as_u32s(), &[0xb]);
2480
2481        io.set_output(2, true);
2482        assert_eq!(io.as_u32s(), &[0xf]);
2483    }
2484}