axp192_dd/
driver.rs

1use super::{I2c, RegisterInterface, bisync, only_async, only_sync};
2use crate::{AXP192_I2C_ADDRESS, AxpError, AxpInterface, AxpLowLevel, DcId, LdoId, adc_helpers::*};
3
4#[bisync]
5impl<I2CBus, E> RegisterInterface for AxpInterface<I2CBus>
6where
7    I2CBus: I2c<Error = E>,
8    E: core::fmt::Debug,
9{
10    type AddressType = u8;
11    type Error = AxpError<E>;
12    async fn read_register(
13        &mut self,
14        address: u8,
15        _size_bits: u32,
16        data: &mut [u8],
17    ) -> Result<(), Self::Error> {
18        self.i2c_bus
19            .write_read(AXP192_I2C_ADDRESS, &[address], data)
20            .await
21            .map_err(AxpError::I2c)
22    }
23    async fn write_register(
24        &mut self,
25        address: u8,
26        _size_bits: u32,
27        data: &[u8],
28    ) -> Result<(), Self::Error> {
29        let mut buffer = [0u8; 5];
30        if (1 + data.len()) > buffer.len() {
31            return Err(AxpError::NotSupported("Write data length exceeds buffer"));
32        }
33        buffer[0] = address;
34        buffer[1..1 + data.len()].copy_from_slice(data);
35        self.i2c_bus
36            .write(AXP192_I2C_ADDRESS, &buffer[..1 + data.len()])
37            .await
38            .map_err(AxpError::I2c)
39    }
40}
41
42pub struct Axp192<
43    I2CImpl: RegisterInterface<AddressType = u8, Error = AxpError<I2CBusErr>>,
44    I2CBusErr: core::fmt::Debug,
45> {
46    pub ll: AxpLowLevel<I2CImpl>,
47    _marker: core::marker::PhantomData<I2CBusErr>,
48}
49
50impl<I2CBus, E> Axp192<AxpInterface<I2CBus>, E>
51where
52    I2CBus: I2c<Error = E>,
53    E: core::fmt::Debug,
54{
55    pub fn new(i2c: I2CBus) -> Self {
56        Self {
57            ll: AxpLowLevel::new(AxpInterface::new(i2c)),
58            _marker: core::marker::PhantomData,
59        }
60    }
61}
62
63pub trait CurrentAxpDriverInterface<E>:
64    RegisterInterface<AddressType = u8, Error = AxpError<E>>
65{
66}
67
68impl<T, E> CurrentAxpDriverInterface<E> for T
69where
70    T: RegisterInterface<AddressType = u8, Error = AxpError<E>>,
71    E: core::fmt::Debug,
72{
73}
74
75include!("bisync_helpers.rs");
76
77impl<I2CImpl, I2CBusErr> Axp192<I2CImpl, I2CBusErr>
78where
79    I2CImpl: CurrentAxpDriverInterface<I2CBusErr>,
80    I2CBusErr: core::fmt::Debug,
81{
82    #[bisync]
83    pub async fn get_battery_voltage_mv(&mut self) -> Result<f32, AxpError<I2CBusErr>> {
84        let mut op = self.ll.battery_voltage_adc();
85        let raw_fieldset = read_internal(&mut op).await?;
86        let adc_val = adc_12bit_from_raw_u16(raw_fieldset.raw());
87        Ok(adc_val as f32 * 1.1)
88    }
89
90    #[bisync]
91    pub async fn get_battery_charge_current_ma(&mut self) -> Result<f32, AxpError<I2CBusErr>> {
92        let mut op = self.ll.battery_charge_current_adc();
93        let raw_fieldset = read_internal(&mut op).await?;
94        let adc_val = adc_13bit_from_raw_u16(raw_fieldset.raw());
95        Ok(adc_val as f32 * 0.5)
96    }
97
98    #[bisync]
99    pub async fn get_battery_instantaneous_power_uw(&mut self) -> Result<f32, AxpError<I2CBusErr>> {
100        let mut op = self.ll.battery_instantaneous_power_adc();
101        let raw_fieldset = read_internal(&mut op).await?;
102        let adc_val = adc_24bit_from_raw_u32(raw_fieldset.raw());
103        Ok(adc_val as f32 * 0.55)
104    }
105
106    #[bisync]
107    pub async fn set_dcdc_enable(
108        &mut self,
109        dc: DcId,
110        enable: bool,
111    ) -> Result<(), AxpError<I2CBusErr>> {
112        let mut op = self.ll.power_output_control();
113        modify_internal(&mut op, |r| match dc {
114            DcId::Dcdc1 => r.set_dcdc_1_output_enable(enable),
115            DcId::Dcdc2 => r.set_dcdc_2_output_enable(enable),
116            DcId::Dcdc3 => r.set_dcdc_3_output_enable(enable),
117        })
118        .await
119    }
120
121    #[bisync]
122    pub async fn set_dcdc_voltage(
123        &mut self,
124        dc: DcId,
125        voltage_mv: u16,
126    ) -> Result<(), AxpError<I2CBusErr>> {
127        if !(700..=3500).contains(&voltage_mv) {
128            return Err(AxpError::InvalidVoltage(voltage_mv));
129        }
130        let raw_setting = ((voltage_mv.saturating_sub(700)) / 25) as u8;
131
132        match dc {
133            DcId::Dcdc1 => {
134                let mut op = self.ll.dc_dc_1_voltage_setting();
135                modify_internal(&mut op, |r| r.set_voltage_setting(raw_setting)).await
136            }
137            DcId::Dcdc2 => {
138                let mut op = self.ll.dc_dc_2_voltage_setting();
139                modify_internal(&mut op, |r| r.set_voltage_setting(raw_setting)).await
140            }
141            DcId::Dcdc3 => {
142                let mut op = self.ll.dc_dc_3_voltage_setting();
143                modify_internal(&mut op, |r| r.set_voltage_setting(raw_setting)).await
144            }
145        }
146    }
147
148    #[bisync]
149    pub async fn set_ldo_voltage_mv(
150        &mut self,
151        ldo: LdoId,
152        voltage_mv: u16,
153    ) -> Result<(), AxpError<I2CBusErr>> {
154        if !(1800..=3300).contains(&voltage_mv) {
155            return Err(AxpError::InvalidVoltage(voltage_mv));
156        }
157        let raw_setting = ((voltage_mv.saturating_sub(1800)) / 100) as u8;
158        if raw_setting > 0x0F {
159            return Err(AxpError::InvalidVoltage(voltage_mv));
160        }
161
162        let mut op = self.ll.ldo_2_and_3_voltage_setting();
163        modify_internal(&mut op, |r| match ldo {
164            LdoId::Ldo2 => r.set_ldo_2_voltage_setting(raw_setting),
165            LdoId::Ldo3 => r.set_ldo_3_voltage_setting(raw_setting),
166        })
167        .await
168    }
169
170    #[bisync]
171    pub async fn set_gpio0_ldo_voltage_mv(
172        &mut self,
173        voltage_mv: u16,
174    ) -> Result<(), AxpError<I2CBusErr>> {
175        if !(1800..=3300).contains(&voltage_mv) {
176            return Err(AxpError::InvalidVoltage(voltage_mv));
177        }
178        let raw_4bit_setting = ((voltage_mv.saturating_sub(1800)) / 100) as u8;
179        if raw_4bit_setting > 0x0F {
180            return Err(AxpError::InvalidVoltage(voltage_mv));
181        }
182
183        let mut op = self.ll.gpio_0_ldo_voltage_setting();
184        write_internal(&mut op, |r| {
185            r.set_voltage_setting_raw(raw_4bit_setting);
186        })
187        .await
188    }
189
190    #[bisync]
191    pub async fn set_battery_charge_high_temp_threshold_mv(
192        &mut self,
193        threshold_mv: u16,
194    ) -> Result<(), AxpError<I2CBusErr>> {
195        if threshold_mv > 3264 {
196            return Err(AxpError::InvalidVoltage(threshold_mv));
197        }
198        let raw_setting_u16 = (threshold_mv * 10 + 64) / 128;
199        let raw_setting = raw_setting_u16 as u8;
200
201        let mut op = self.ll.battery_charge_high_temp_threshold();
202        write_internal(&mut op, |r| {
203            r.set_threshold_setting_raw(raw_setting);
204        })
205        .await
206    }
207
208    #[bisync]
209    pub async fn set_battery_charge_low_temp_threshold_mv(
210        &mut self,
211        threshold_mv: u16,
212    ) -> Result<(), AxpError<I2CBusErr>> {
213        if threshold_mv > 3264 {
214            return Err(AxpError::InvalidVoltage(threshold_mv));
215        }
216        let raw_setting_u16 = (threshold_mv * 10 + 64) / 128;
217        let raw_setting = raw_setting_u16 as u8;
218
219        let mut op = self.ll.battery_charge_low_temp_threshold();
220        write_internal(&mut op, |r| {
221            r.set_threshold_setting_raw(raw_setting);
222        })
223        .await
224    }
225}