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}