1use crate::i2c_type;
2use crate::maybe_async_attr;
3use crate::registers::*;
4use crate::Aem10900Config;
5use crate::Error;
6use heapless::Vec;
7
8pub struct Aem10900<I2C> {
9 pub i2c: I2C,
10 pub dev_adr: u8,
11 pub conf: Aem10900Config,
12}
13
14impl<I2C> Aem10900<I2C>
15where
16 I2C: i2c_type::i2c::I2c,
17{
18 pub fn new(i2c: I2C, dev_adr: u8) -> Self {
22 Self {
23 i2c,
24 dev_adr,
25 conf: Aem10900Config::default(),
26 }
27 }
28
29 pub fn bus(&mut self) -> &mut I2C {
31 &mut self.i2c
32 }
33
34 #[maybe_async_attr]
36 pub async fn write_regs(&mut self, start_adr: u8, write: &[u8]) -> Result<(), Error<I2C>> {
37 let mut write_buf: Vec<u8, 26> = Vec::new();
38 write_buf.push(start_adr).unwrap();
39 write_buf.extend_from_slice(write).unwrap();
40 self.i2c
41 .write(self.dev_adr, &write_buf)
42 .await
43 .map_err(Error::Communication)
44 }
45 #[maybe_async_attr]
47 pub async fn read_regs(&mut self, start_adr: u8, read: &mut [u8]) -> Result<(), Error<I2C>> {
48 self.i2c
49 .write_read(self.dev_adr, &[start_adr], read)
50 .await
51 .map_err(Error::Communication)
52 }
53
54 #[maybe_async_attr]
56 pub async fn init(&mut self) -> Result<(), Error<I2C>> {
57 self.check_connection().await?;
58 self.write_cfg_regs().await?;
59 self.verify_cfg_regs().await?;
60 Ok(())
61 }
62
63 #[maybe_async_attr]
65 async fn check_connection(&mut self) -> Result<(), Error<I2C>> {
66 let mut part_number: [u8; 5] = [0; 5];
67 self.read_regs(Pn0::ADDRESS, &mut part_number).await?;
68
69 if part_number != [0x00, 0x77, 0x2D, 0x33, 0x8F] {
71 return Err(Error::Config("Part Number"));
72 }
73 Ok(())
90 }
91
92 #[maybe_async_attr]
94 async fn write_cfg_regs(&mut self) -> Result<(), Error<I2C>> {
95 let mut byte_arr: [u8; 11] = [0; 11];
96 byte_arr[0] = self.conf.mpptcfg.to_le_bytes()[0];
97 byte_arr[1] = self.conf.vovdis.to_le_bytes()[0];
98 byte_arr[2] = self.conf.vovch.to_le_bytes()[0];
99 byte_arr[3] = self.conf.tempcold.to_le_bytes()[0];
100 byte_arr[4] = self.conf.temphot.to_le_bytes()[0];
101 byte_arr[5] = self.conf.pwr.to_le_bytes()[0];
102 byte_arr[6] = self.conf.sleep.to_le_bytes()[0];
103 byte_arr[7] = self.conf.stomon.to_le_bytes()[0];
104 byte_arr[8] = self.conf.apm.to_le_bytes()[0];
105 byte_arr[9] = self.conf.irqen.to_le_bytes()[0];
106 byte_arr[10] = self.conf.ctrl.to_le_bytes()[0];
107
108 self.write_regs(Mpptcfg::ADDRESS, &byte_arr).await
109 }
110
111 #[maybe_async_attr]
113 async fn verify_cfg_regs(&mut self) -> Result<(), Error<I2C>> {
114 let mut byte_arr: [u8; 11] = [0; 11];
115
116 self.read_regs(Mpptcfg::ADDRESS, &mut byte_arr).await?;
117
118 if self.conf.mpptcfg
119 != Mpptcfg::try_from_le_bytes(&[byte_arr[0]])
120 .map_err(|_| Error::Value("Mpptcfg could not be extracted"))?
121 {
122 return Err(Error::Config("Mpptcfg"));
123 }
124 if self.conf.vovdis != Vovdis::from_le_bytes(&[byte_arr[1]]) {
125 return Err(Error::Config("Vovdis"));
126 }
127 if self.conf.vovch != Vovch::from_le_bytes(&[byte_arr[2]]) {
128 return Err(Error::Config("Vovch"));
129 }
130 if self.conf.tempcold != Tempcold::from_le_bytes(&[byte_arr[3]]) {
131 return Err(Error::Config("Tempcold"));
132 }
133 if self.conf.temphot != Temphot::from_le_bytes(&[byte_arr[4]]) {
134 return Err(Error::Config("Temphot"));
135 }
136 if self.conf.pwr != Pwr::from_le_bytes(&[byte_arr[5]]) {
137 return Err(Error::Config("Pwr"));
138 }
139 if self.conf.sleep != Sleep::from_le_bytes(&[byte_arr[6]]) {
140 return Err(Error::Config("Sleep"));
141 }
142 if self.conf.stomon
143 != Stomon::try_from_le_bytes(&[byte_arr[7]])
144 .map_err(|_| Error::Value("Stomon could not be extracted"))?
145 {
146 return Err(Error::Config("Stomon"));
147 }
148 if self.conf.apm
149 != Apm::try_from_le_bytes(&[byte_arr[8]])
150 .map_err(|_| Error::Value("Apm could not be extracted"))?
151 {
152 return Err(Error::Config("Apm"));
153 }
154 if self.conf.irqen != Irqen::from_le_bytes(&[byte_arr[9]]) {
155 return Err(Error::Config("Irqen"));
156 }
157 if self.conf.ctrl != Ctrl::from_le_bytes(&[byte_arr[10]]) {
158 return Err(Error::Config("Ctrl"));
159 }
160
161 Ok(())
162 }
163
164 #[maybe_async_attr]
166 pub async fn read_irq_flag(&mut self) -> Result<Irqflg, Error<I2C>> {
167 let mut byte_arr: [u8; 1] = [0];
168
169 self.read_regs(Irqflg::ADDRESS, &mut byte_arr).await?;
170 Ok(Irqflg::from_le_bytes(&byte_arr))
171 }
172
173 #[maybe_async_attr]
175 pub async fn read_apm_data(&mut self) -> Result<ApmData, Error<I2C>> {
176 let mut byte_arr: [u8; 3] = [0; 3];
177
178 self.read_regs(Apm0::ADDRESS, &mut byte_arr).await?;
179 let apm0 = Apm0::from_le_bytes(&[byte_arr[0]]);
180 let apm1 = Apm1::from_le_bytes(&[byte_arr[1]]);
181 let apm2 = Apm2::from_le_bytes(&[byte_arr[2]]);
182
183 let data: u32 =
184 ((apm2.data & 0x0F) as u32) << 16 | ((apm1.data as u32) << 8) | (apm0.data as u32);
185
186 match self.conf.apm.mode {
187 Mode::PowerMeter => {
188 let shift = (apm2.data >> 4) & 0x0F;
189 Ok(ApmData::PowerMeterResult((data << shift) as f32 * 0.10166))
192 }
193 Mode::PulseCounter => Ok(ApmData::PulseCounterResult(data)),
194 }
195 }
196
197 #[maybe_async_attr]
199 pub async fn read_battery_voltage(&mut self) -> Result<f32, Error<I2C>> {
200 let mut byte_arr: [u8; 1] = [0];
201
202 self.read_regs(Sto::ADDRESS, &mut byte_arr).await?;
203 let sto = Sto::from_le_bytes(&[byte_arr[0]]);
204
205 Ok(4.8 * (sto.data as f32) / 256.0)
207 }
208
209 #[maybe_async_attr]
211 pub async fn read_source_voltage(&mut self) -> Result<f32, Error<I2C>> {
212 let mut byte_arr: [u8; 1] = [0];
213
214 self.read_regs(Src::ADDRESS, &mut byte_arr).await?;
215 let src = Src::from_le_bytes(&[byte_arr[0]]);
216
217 self.source_voltage_lookup(src)
219 }
220
221 fn source_voltage_lookup(&self, src: Src) -> Result<f32, Error<I2C>> {
223 const SRC_VOLTAGE_MIN_KEY: u8 = 0x06;
225 const SRC_VOLTAGE_MAX_KEY: u8 = 0x3A;
226 const TABLE_LENGTH: usize = (SRC_VOLTAGE_MAX_KEY - SRC_VOLTAGE_MIN_KEY + 1) as usize;
227
228 const SOURCE_VOLTAGE_LOOKUP_TABLE: [u16; TABLE_LENGTH] = [
229 113, 128, 142, 158, 172, 188, 203, 217, 233, 247, 263, 278, 292, 315, 345, 375, 405,
230 435, 465, 495, 525, 555, 585, 615, 645, 675, 705, 735, 765, 795, 825, 855, 885, 915,
231 945, 975, 1005, 1035, 1065, 1095, 1125, 1155, 1185, 1215, 1245, 1275, 1305, 1335, 1365,
232 1395, 1425, 1455, 1485,
233 ];
234
235 if src.data < SRC_VOLTAGE_MIN_KEY || src.data > SRC_VOLTAGE_MAX_KEY {
236 return Err(Error::Value("Src.data is not within allowed range"));
237 }
238 Ok(SOURCE_VOLTAGE_LOOKUP_TABLE[(src.data - SRC_VOLTAGE_MIN_KEY) as usize] as f32 / 1000.0)
239 }
240}
241
242pub enum ApmData {
244 PowerMeterResult(f32),
246 PulseCounterResult(u32),
248}