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;