mcp4725_async/
lib.rs

1#![doc = include_str!("../README.md")]
2#![no_std]
3
4mod types;
5#[cfg(test)]
6mod tests;
7
8pub use types::*;
9
10use embedded_hal_async::i2c::{I2c, SevenBitAddress};
11
12/// The MCP4725 device
13pub struct MCP4725<I: I2c<SevenBitAddress>> {
14    i2c: I,
15    address: SevenBitAddress,
16}
17
18impl<I: I2c<SevenBitAddress>> MCP4725<I> {
19    /// Create a new device from an I2C peripheral and address.
20    pub fn new(i2c: I, address: SevenBitAddress) -> Self {
21        Self { i2c, address }
22    }
23    
24    /// Destroy this device and get the I2C instance back.
25    pub fn destroy(self) -> I {
26        self.i2c
27    }
28    
29    /// Convenience function to just set the output voltage. Only the lower 12 bits of the DAC value
30    /// are used. If `write_eeprom` is true, the DAC value will also be written to the EEPROM and
31    /// the EEPROM power down mode will be set to `Normal`.
32    pub async fn set_voltage(&mut self, dac: u16, write_eeprom: bool) -> Result<(), I::Error> {
33        if write_eeprom {
34            self.write(PowerDownMode::Normal, dac, write_eeprom).await
35        } else {
36            self.fast_write(PowerDownMode::Normal, dac).await
37        }
38    }
39    
40    /// Perform a read command. This will return the value in the DAC register and the EEPROM data.
41    pub async fn read(&mut self) -> Result<(RegisterStatus, EEPROMStatus), I::Error> {
42        let mut packet = [0u8; 5];
43        self.i2c.read(self.address, &mut packet).await?;
44        
45        Ok((
46            RegisterStatus::new([packet[0], packet[1], packet[2]]),
47            EEPROMStatus::new([packet[3], packet[4]]),
48        ))
49    }
50
51    /// Perform a fast write. This can set the power down mode and the DAC value. This only changes
52    /// the DAC register and does not affect the EEPROM. Only the lower 12 bits of the DAC value
53    /// are used.
54    pub async fn fast_write(&mut self, power_down_mode: PowerDownMode, dac: u16) -> Result<(), I::Error> {
55        let data =
56            (dac & 0xFFF) |
57            ((power_down_mode as u16) << 12);
58        let data = data.to_be_bytes();
59        let data = [data[0], data[1], data[0], data[1]];
60        self.i2c.write(self.address, &data).await
61    }
62    
63    /// Perform a normal write. This can set the power down mode and the DAC value, and optionally
64    /// write to the EEPROM. Only the lower 12 bits of the DAC value are used.
65    pub async fn write(&mut self, power_down_mode: PowerDownMode, dac: u16, write_eeprom: bool) -> Result<(), I::Error> {
66        let data =
67            ((if write_eeprom { 0b011 } else {0b010}) << 5) |
68            ((power_down_mode as u8) << 1);
69        let dac = dac << 4;
70        
71        let dac = dac.to_be_bytes();
72        let packet = [data, dac[0], dac[1]];
73        let packet = [packet[0], packet[1], packet[2], packet[0], packet[1], packet[2]];
74        self.i2c.write(self.address, &packet).await
75    }
76}