1#![doc = include_str!("../README.md")]
2#![deny(unsafe_code, missing_docs)]
3#![no_std]
4
5use bitfield_struct::bitfield;
6use core::include_str;
7use core::marker::PhantomData;
8
9pub struct Ad57xxShared<DEV, IC> {
11    spi: DEV,
12    cfg: Config,
13    pcfg: u16,
14    _ic: PhantomData<IC>,
15}
16
17impl<DEV, IC> Ad57xxShared<DEV, IC> {
18    pub(crate) fn create(spi: DEV) -> Self {
19        Ad57xxShared {
20            spi,
21            cfg: Config::default(),
22            pcfg: 0,
23            _ic: PhantomData,
24        }
25    }
26    pub fn destroy(self) -> DEV {
28        self.spi
29    }
30}
31
32
33
34trait Ad57xxPrivate {}
35
36pub trait Ad57xx<DEV, E> where 
38u16:  From<<Self as Ad57xx<DEV, E>>::PCFG> + Into<<Self as Ad57xx<DEV, E>>::PCFG>,
39u8:  From<<Self as Ad57xx<DEV, E>>::CH>,
40u8:  From<Command::<<Self as Ad57xx<DEV, E>>::CH>>,
41{
42    type CH: Copy;
44    type PCFG: Copy;
46
47
48    fn spi_write(&mut self, payload: &[u8; 3]) -> Result<(), Error<E>>;
50
51    fn spi_read(&mut self, cmd: u8) -> Result<u16, Error<E>>;
53
54    fn set_dac_output(&mut self, chan: Self::CH, val: u16) -> Result<(), Error<E>> {
66        self.write(Command::DacRegister(chan), Data::DacValue(val))
67    }
68
69    fn set_config(&mut self, cfg: Config) -> Result<(), Error<E>>;
71    fn get_config(&mut self) -> Result<Config, Error<E>>;
73
74    fn set_power_config(&mut self, pcfg: Self::PCFG) -> Result<(), Error<E>>;
76
77    fn get_power_config(&mut self) -> Result<Self::PCFG, Error<E>>;
79
80
81    fn set_output_range(&mut self, chan: Self::CH, range: OutputRange) -> Result<(), Error<E>> {
83        self.write(Command::RangeSelectRegister(chan), Data::OutputRange(range))
84    }
85    fn clear_dacs(&mut self) -> Result<(), Error<E>> {
87        self.write(Command::<Self::CH>::ControlRegister(Function::Clear), Data::None)
88    }
89    fn load_dacs(&mut self) -> Result<(), Error<E>> {
91        self.write(Command::<Self::CH>::ControlRegister(Function::Load), Data::None)
92    }
93
94    fn write(&mut self, cmd: Command<Self::CH>, data: Data<Self::PCFG>) -> Result<(), Error<E>> {
96        let payload: [u8; 3] = match cmd {
97            Command::DacRegister(addr) => {
98                if let Data::DacValue(val) = data {
99                    [
100                        CommandByte::new()
101                            .with_addr(u8::from(addr))
102                            .with_reg(u8::from(cmd))
103                            .into(),
104                        (val >> 8) as u8,
105                        val as u8,
106                    ]
107                } else {
108                    return Err(Error::InvalidArgument);
109                }
110            }
111            Command::RangeSelectRegister(addr) => {
112                if let Data::OutputRange(val) = data {
113                    [
114                        CommandByte::new()
115                            .with_addr(u8::from(addr))
116                            .with_reg(u8::from(cmd))
117                            .into(),
118                        0x00,
119                        val as u8,
120                    ]
121                } else {
122                    return Err(Error::InvalidArgument);
123                }
124            }
125            Command::PowerControlRegister => {
126                if let Data::PowerControl(pcfg) = data {
127                    [
128                        CommandByte::new().with_reg(u8::from(cmd)).into(),
129                        (u16::from(pcfg) >> 8) as u8,
130                        (u16::from(pcfg)) as u8,
131                    ]
132                } else {
133                    return Err(Error::InvalidArgument);
134                }
135            }
136            Command::ControlRegister(func) if func == Function::Config => {
137                if let Data::Control(cfg) = data {
138                    [
139                        CommandByte::new()
140                            .with_reg(u8::from(cmd))
141                            .with_addr(func as u8)
142                            .into(),
143                        0x00,
144                        u8::from(cfg) as u8,
145                    ]
146                } else {
147                    return Err(Error::InvalidArgument);
148                }
149            }
150            Command::ControlRegister(func) => {
151                if let Data::None = data {
152                    [
153                        CommandByte::new()
154                            .with_reg(u8::from(cmd))
155                            .with_addr(func as u8)
156                            .into(),
157                        0x00,
158                        0x00,
159                    ]
160                } else {
161                    return Err(Error::InvalidArgument);
162                }
163            }
164        };
165        self.spi_write(&payload)
166    }
167
168    fn read(&mut self, cmd: Command<Self::CH>) -> Result<Data<Self::PCFG>, Error<E>> {
170        let addr = match cmd {
171            Command::DacRegister(addr) => u8::from(addr),
172            Command::RangeSelectRegister(addr) => u8::from(addr),
173            Command::PowerControlRegister => 0,
174            Command::ControlRegister(function) => function as u8,
175        };
176        let cmd_byte = CommandByte::new()
178            .with_rw(true)
179            .with_reg(u8::from(cmd))
180            .with_addr(addr);
181        let data = self.spi_read(u8::from(cmd_byte))?;
182        match cmd {
183            Command::DacRegister(_) => Ok(Data::DacValue(data)),
184            Command::RangeSelectRegister(_) => Ok(Data::OutputRange(OutputRange::from(data))),
185            Command::PowerControlRegister => Ok(Data::PowerControl(data.into())),
186            Command::ControlRegister(func) if func == Function::Config => {
187                Ok(Data::Control(Config::from(data as u8)))
188            }
189            Command::ControlRegister(_) => Err(Error::ReadError),
190        }
191    }
192}
193
194#[derive(Debug)]
196pub enum Error<E> {
197    Spi(E),
199    InvalidArgument,
201    ReadError,
203}
204
205#[derive(Debug)]
207pub enum Data<PCFG> {
208    DacValue(u16),
210    OutputRange(OutputRange),
212    Control(Config),
214    PowerControl(PCFG),
216    None,
218}
219#[derive(Debug, Clone, Copy)]
221#[repr(u8)]
222pub enum Command<C> {
223    DacRegister(C),
225    RangeSelectRegister(C),
227    PowerControlRegister,
229    ControlRegister(Function),
231}
232impl<C> From<Command<C>> for u8 {
233    fn from(cmd: Command<C>) -> Self {
234        match cmd {
235            Command::DacRegister(_) => 0b000,
236            Command::RangeSelectRegister(_) => 0b001,
237            Command::PowerControlRegister => 0b010,
238            Command::ControlRegister(_) => 0b011,
239        }
240    }
241}
242
243#[derive(Debug, PartialEq, Eq, Clone, Copy)]
245#[repr(u8)]
246pub enum Function {
247    Nop = 0b000,
249    Config = 0b001,
251    Clear = 0b100,
253    Load = 0b101,
255}
256
257#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
262#[repr(u16)]
263pub enum OutputRange {
264    Unipolar5V = 0b000,
266    Unipolar10V = 0b001,
268    Unipolar10_8V = 0b010,
270    Bipolar5V = 0b011,
272    Bipolar10V = 0b100,
274    Bipolar10_8V = 0b101,
276    InvalidReadback,
278}
279impl From<u16> for OutputRange {
280    fn from(value: u16) -> Self {
281        match value {
282            0b000 => Self::Unipolar5V,
283            0b001 => Self::Unipolar10V,
284            0b010 => Self::Unipolar10_8V,
285            0b011 => Self::Bipolar5V,
286            0b100 => Self::Bipolar10V,
287            0b101 => Self::Bipolar10_8V,
288            _ => Self::InvalidReadback,
289        }
290    }
291}
292
293#[bitfield(u8)]
294struct CommandByte {
295    #[bits(3)]
296    addr: u8,
297
298    #[bits(3)]
299    reg: u8,
300
301    #[bits(1)]
302    _zero: bool,
303
304    #[bits(1)]
305    rw: bool,
306}
307
308#[bitfield(u8)]
310pub struct Config {
311    #[bits(default = false)]
314    pub sdo_disable: bool,
315
316    #[bits(default = false)]
324    pub clr_select: bool,
325    #[bits(default = true)]
329    pub clamp_enable: bool,
330    #[bits(default = false)]
333    pub(crate) tsd_enable: bool,
334    #[bits(4)]
336    _unused: u16,
337}
338
339#[doc(hidden)]
341pub mod marker {
342    pub struct Ad57x4 {}
343    pub struct Ad57x2 {}
344}
345
346pub mod ad57x2;
347pub mod ad57x4;
348
349mod private {
350    use super::marker;
351    pub trait Sealed {}
352
353    impl Sealed for marker::Ad57x4 {}
354    impl Sealed for marker::Ad57x2 {}
355}