1#![no_std]
30
31use bitflags::bitflags;
32use embedded_hal as hal;
33use hal::blocking::spi::Transfer;
34use hal::digital::v2::OutputPin;
35use measurements::Voltage;
36
37#[derive(Debug)]
38pub enum Error<E, PE> {
39    Spi(E),
40    Pin(PE),
41    VoltageTooHigh,
42    VoltageTooLow,
43    NotInitialized,
44    NotReady,
45}
46
47pub enum ClockSource {
48    Internal = 1,
49    External = 0,
50}
51
52pub enum Input {
53    VInPlus = 0b0100,
54    VInMinus = 0b0000,
55}
56
57pub enum Channel {
58    CH0 = 0b0000,
59    CH1 = 0b0001,
60    CH2 = 0b0010,
61    CH3 = 0b0011,
62    CH4 = 0b0100,
63    CH5 = 0b0101,
64    CH6 = 0b0110,
65    CH7 = 0b0111,
66    AGND = 0b1000,
67    AVDD = 0b1001,
68    REFINPlus = 0b1011,
69    REFINMinus = 0b1100,
70    TEMPDiodeP = 0b1101,
71    TEMPDiodeM = 0b1110,
72    VCM = 0b1111,
73}
74
75bitflags! {
76    pub struct StatusRegister: u8 {
77        const DR = 0b00000100;
78        const CRCCFG = 0b00000010;
79        const POR = 0b00000001;
80    }
81}
82
83pub struct MCP346x<SPI, CS, MODE> {
84    spi: SPI,
85    cs: CS,
86    _mode: MODE,
87    address: u8,
88    status: Option<StatusRegister>,
89}
90
91fn generate_fast_command_byte(device_address: u8, command: u8) -> [u8; 1] {
92    [(device_address << 6) | (command << 2); 1]
93}
94
95fn generate_register_command_byte(
96    device_address: u8,
97    register_address: u8,
98    command_type: u8,
99) -> [u8; 1] {
100    [(device_address << 6) | (register_address << 2) | command_type; 1]
101}
102
103impl<SPI, CS, E> MCP346x<SPI, CS, Unconfigured>
104where
105    SPI: Transfer<u8, Error = E>,
106    CS: OutputPin,
107{
108    pub fn new(spi: SPI, cs: CS, address: u8) -> Self {
109        Self {
110            spi,
111            cs,
112            _mode: Unconfigured,
113            address,
114            status: None,
115        }
116    }
117}
118
119impl<SPI, CS, MODE, E, PE> MCP346x<SPI, CS, MODE>
120where
121    SPI: Transfer<u8, Error = E>,
122    CS: OutputPin<Error = PE>,
123{
124    fn spi_write(&mut self, write_buffer: &[u8]) -> Result<(), Error<E, PE>> {
125        self.cs.set_low().map_err(Error::Pin)?;
126        let mut transfer_buffer = [0; 40];
127        let transfer_slice = &mut transfer_buffer[0..write_buffer.len()];
128        transfer_slice.copy_from_slice(write_buffer);
129        self.spi.transfer(transfer_slice).map_err(Error::Spi)?;
130        self.cs.set_high().map_err(Error::Pin)?;
131        Ok(())
132    }
133
134    fn spi_transfer(
135        &mut self,
136        read_buffer: &mut [u8],
137        write_buffer: &[u8],
138    ) -> Result<(), Error<E, PE>> {
139        self.cs.set_low().map_err(Error::Pin)?;
140        let mut transfer_buffer = [0; 40];
141        let transfer_slice = &mut transfer_buffer[0..write_buffer.len()];
142        transfer_slice.copy_from_slice(write_buffer);
143        self.spi
144            .transfer(&mut transfer_buffer[0..read_buffer.len().max(write_buffer.len())])
145            .map_err(Error::Spi)?;
146        read_buffer.copy_from_slice(&transfer_buffer[0..read_buffer.len()]);
147        self.cs.set_high().map_err(Error::Pin)?;
148        Ok(())
149    }
150
151    fn tranfer_with_status_register(
152        &mut self,
153        read_buf: &mut [u8],
154        command: &[u8],
155    ) -> Result<StatusRegister, Error<E, PE>> {
156        let mut buf = [0; 40];
157        self.spi_transfer(&mut buf[0..read_buf.len() + 1], command)?;
158        let mut status_register_raw = [0; 1];
159        status_register_raw.clone_from_slice(&buf[0..1]);
160        let status_register =
161            StatusRegister::from_bits_truncate(u8::from_be_bytes(status_register_raw));
162        read_buf.copy_from_slice(&buf[1..read_buf.len() + 1]);
163        Ok(status_register)
164    }
165
166    fn set_mode(&mut self, mode: u8) -> Result<(), Error<E, PE>> {
167        let command: [u8; 1] = [mode; 1];
168        self.spi_write(&command)?;
169        Ok(())
170    }
171
172    fn static_read(&mut self, register: u8, buf: &mut [u8]) -> Result<(), Error<E, PE>> {
173        let command: [u8; 1] = generate_register_command_byte(self.address, register, 0b01);
174        let _ = self.tranfer_with_status_register(buf, &command);
175        Ok(())
176    }
177
178    fn incremental_write(&mut self, register: u8, buf: &mut [u8]) -> Result<(), Error<E, PE>> {
179        let command: [u8; 1] = generate_register_command_byte(self.address, register, 0b10);
180        let mut buffer: [u8; 10] = [0; 10];
181        let _ = &mut buffer[0..1].copy_from_slice(&command);
182        let _ = &mut buffer[1..buf.len() + 1].copy_from_slice(buf);
183        self.spi_write(&buffer[0..buf.len() + 1])?;
184        Ok(())
185    }
186
187    fn read_data_register_16bit(&mut self) -> Result<i16, Error<E, PE>> {
188        let mut buf: [u8; 2] = [0; 2];
189        self.static_read(0x00, &mut buf)?;
190        let measurement = i16::from_be_bytes(buf);
191        Ok(measurement)
192    }
193
194    pub fn into_continuous_mode(
195        mut self,
196    ) -> Result<MCP346x<SPI, CS, ContinuousMode>, Error<E, PE>> {
197        self.set_mode(0b00)?;
198        Ok(MCP346x {
199            spi: self.spi,
200            cs: self.cs,
201            _mode: ContinuousMode,
202            address: self.address,
203            status: self.status,
204        })
205    }
206
207    pub fn into_scan_mode(mut self) -> Result<MCP346x<SPI, CS, ScanMode>, Error<E, PE>> {
208        self.set_mode(0b10)?;
209        Ok(MCP346x {
210            spi: self.spi,
211            cs: self.cs,
212            _mode: ScanMode,
213            address: self.address,
214            status: self.status,
215        })
216    }
217
218    pub fn into_oneshot_mode(mut self) -> Result<MCP346x<SPI, CS, OneShotMode>, Error<E, PE>> {
219        self.set_mode(0b11)?;
220        Ok(MCP346x {
221            spi: self.spi,
222            cs: self.cs,
223            _mode: OneShotMode,
224            address: self.address,
225            status: self.status,
226        })
227    }
228
229    pub fn set_clock_source(&mut self, clock_source: ClockSource) -> Result<(), Error<E, PE>> {
233        let mut buf: [u8; 1] = [0; 1];
234        self.static_read(0x01, &mut buf)?;
235        buf[0] = ((clock_source as u8) << 4) | (!(0b11 << 4) & buf[0]);
236        self.incremental_write(0x01, &mut buf)?;
237        Ok(())
238    }
239
240    pub fn set_irq_internal_pullup(&mut self, pullup: bool) -> Result<(), Error<E, PE>> {
244        let mut buf = [0; 1];
245        self.static_read(0x05, &mut buf)?;
246        buf[0] = ((pullup as u8) << 3) | (!(0b1 << 3) & buf[0]);
247        self.incremental_write(0x5, &mut buf)?;
248        Ok(())
249    }
250
251    pub fn set_mux_input(&mut self, input: Input, channel: Channel) -> Result<(), Error<E, PE>> {
258        let mut buf = [0; 1];
259        self.static_read(0x06, &mut buf)?;
260        let shift = input as u8;
261        buf[0] = ((channel as u8) << shift) | ((0b1111 << shift) & buf[0]);
262        self.incremental_write(0x06, &mut buf)?;
263        Ok(())
264    }
265
266    fn int_measure(&mut self) -> Result<Voltage, Error<E, PE>> {
267        let measurement = self.read_data_register_16bit()?;
268        Ok(Voltage::from_volts(measurement as f64))
269    }
270
271    fn int_start_conversion(&mut self) -> Result<(), Error<E, PE>> {
272        let command: [u8; 1] = generate_fast_command_byte(self.address, 0b1010);
273        self.spi_write(&command)?;
274        Ok(())
275    }
276
277    pub fn standby(&mut self) -> Result<(), Error<E, PE>> {
278        let command: [u8; 1] = generate_fast_command_byte(self.address, 0b1011);
279        self.spi_write(&command)?;
280        Ok(())
281    }
282
283    pub fn shutdown(&mut self) -> Result<(), Error<E, PE>> {
284        let command: [u8; 1] = generate_fast_command_byte(self.address, 0b1100);
285        self.spi_write(&command)?;
286        Ok(())
287    }
288
289    pub fn full_shutdown(mut self) -> Result<(), Error<E, PE>> {
290        let command: [u8; 1] = generate_fast_command_byte(self.address, 0b1101);
291        self.spi_write(&command)?;
292        Ok(())
293    }
294
295    pub fn reset(mut self) -> Result<MCP346x<SPI, CS, Unconfigured>, Error<E, PE>> {
296        let command: [u8; 1] = generate_fast_command_byte(self.address, 0b1110);
297        self.spi_write(&command)?;
298        Ok(MCP346x {
299            spi: self.spi,
300            cs: self.cs,
301            _mode: Unconfigured,
302            address: self.address,
303            status: self.status,
304        })
305    }
306}
307
308impl<SPI, CS, E, PE> MCP346x<SPI, CS, ContinuousMode>
309where
310    SPI: Transfer<u8, Error = E>,
311    CS: OutputPin<Error = PE>,
312{
313    pub fn measure(&mut self) -> Result<Voltage, Error<E, PE>> {
314        self.int_measure()
315    }
316
317    pub fn start_conversion(&mut self) -> Result<(), Error<E, PE>> {
318        self.int_start_conversion()
319    }
320}
321
322impl<SPI, CS, E, PE> MCP346x<SPI, CS, OneShotMode>
323where
324    SPI: Transfer<u8, Error = E>,
325    CS: OutputPin<Error = PE>,
326{
327    pub fn measure(&mut self) -> Result<Voltage, Error<E, PE>> {
328        self.start_conversion()?;
329        self.int_measure()
330    }
331
332    pub fn start_conversion(&mut self) -> Result<(), Error<E, PE>> {
333        self.int_start_conversion()
334    }
335}
336
337impl<SPI, CS, E, PE> MCP346x<SPI, CS, ScanMode>
338where
339    SPI: Transfer<u8, Error = E>,
340    CS: OutputPin<Error = PE>,
341{
342    pub fn measure(&mut self) -> Result<Voltage, Error<E, PE>> {
343        self.int_measure()
344    }
345
346    pub fn start_conversion(&mut self) -> Result<(), Error<E, PE>> {
347        self.int_start_conversion()
348    }
349}
350
351pub struct ContinuousMode;
352pub struct OneShotMode;
353pub struct ScanMode;
354pub struct Unconfigured;