1use embedded_hal_async::delay::DelayNs;
11use embedded_hal_async::spi::SpiDevice;
12
13use crate::config::Config;
14use crate::error::{Error, InitStage};
15use crate::proto::{self, build_init_sequence};
16use crate::readings::PhaseReadings;
17use crate::registers::*;
18use crate::status::PhaseStatus;
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22#[cfg_attr(feature = "defmt", derive(defmt::Format))]
23pub enum Phase {
24 A,
26 B,
28 C,
30}
31
32impl Phase {
33 #[inline]
35 fn index(self) -> usize {
36 match self {
37 Phase::A => 0,
38 Phase::B => 1,
39 Phase::C => 2,
40 }
41 }
42}
43
44pub struct Atm90e32<SPI, D> {
76 spi: SPI,
77 delay: D,
78}
79
80impl<SPI, D> Atm90e32<SPI, D>
81where
82 SPI: SpiDevice,
83 D: DelayNs,
84{
85 pub fn new(spi: SPI, delay: D) -> Self {
91 Self { spi, delay }
92 }
93
94 pub fn release(self) -> (SPI, D) {
96 (self.spi, self.delay)
97 }
98
99 pub async fn read_register(&mut self, addr: u16) -> Result<u16, Error<SPI::Error>> {
101 let tx = proto::build_read_frame(addr);
102 let mut rx = [0u8; 4];
103 self.spi.transfer(&mut rx, &tx).await.map_err(Error::Spi)?;
104 Ok(proto::parse_read_response(&rx))
105 }
106
107 pub async fn write_register(&mut self, addr: u16, value: u16) -> Result<(), Error<SPI::Error>> {
109 let tx = proto::build_write_frame(addr, value);
110 self.spi.write(&tx).await.map_err(Error::Spi)
111 }
112
113 pub async fn probe(&mut self) -> Result<u16, Error<SPI::Error>> {
119 let status = self.read_register(REG_SYSSTATUS0).await?;
120 if status == 0x0000 || status == 0xFFFF {
121 Err(Error::NotPresent)
122 } else {
123 Ok(status)
124 }
125 }
126
127 pub async fn init(&mut self, config: &Config) -> Result<(), Error<SPI::Error>> {
135 self.write_register(REG_SOFTRESET, 0x789A)
137 .await
138 .map_err(|_| Error::InitFailed(InitStage::SoftReset))?;
139 self.delay.delay_ms(config.post_reset_delay_ms).await;
140
141 for step in build_init_sequence(config).iter() {
143 self.write_register(step.addr, step.value)
144 .await
145 .map_err(|_| Error::InitFailed(step.stage))?;
146 }
147
148 Ok(())
149 }
150
151 pub async fn read_all_phases(&mut self) -> Result<PhaseReadings, Error<SPI::Error>> {
159 let ua = self.read_register(REG_URMS_A).await?;
160 let ub = self.read_register(REG_URMS_B).await?;
161 let uc = self.read_register(REG_URMS_C).await?;
162
163 let ia = self.read_register(REG_IRMS_A).await?;
164 let ib = self.read_register(REG_IRMS_B).await?;
165 let ic = self.read_register(REG_IRMS_C).await?;
166
167 let pa_h = self.read_register(REG_PMEAN_A).await?;
168 let pa_l = self.read_register(REG_PMEAN_A_LSB).await?;
169 let pb_h = self.read_register(REG_PMEAN_B).await?;
170 let pb_l = self.read_register(REG_PMEAN_B_LSB).await?;
171 let pc_h = self.read_register(REG_PMEAN_C).await?;
172 let pc_l = self.read_register(REG_PMEAN_C_LSB).await?;
173
174 let qa_h = self.read_register(REG_QMEAN_A).await?;
175 let qa_l = self.read_register(REG_QMEAN_A_LSB).await?;
176 let qb_h = self.read_register(REG_QMEAN_B).await?;
177 let qb_l = self.read_register(REG_QMEAN_B_LSB).await?;
178 let qc_h = self.read_register(REG_QMEAN_C).await?;
179 let qc_l = self.read_register(REG_QMEAN_C_LSB).await?;
180
181 let pfa = self.read_register(REG_PFMEAN_A).await?;
182 let pfb = self.read_register(REG_PFMEAN_B).await?;
183 let pfc = self.read_register(REG_PFMEAN_C).await?;
184
185 let freq = self.read_register(REG_FREQ).await?;
186
187 let ang_a = self.read_register(REG_PANGLE_A).await?;
188 let ang_b = self.read_register(REG_PANGLE_B).await?;
189 let ang_c = self.read_register(REG_PANGLE_C).await?;
190
191 Ok(PhaseReadings {
192 voltage: [ua, ub, uc],
193 current: [ia, ib, ic],
194 power: [
195 proto::combine_power_words(pa_h, pa_l),
196 proto::combine_power_words(pb_h, pb_l),
197 proto::combine_power_words(pc_h, pc_l),
198 ],
199 reactive: [
200 proto::combine_power_words(qa_h, qa_l),
201 proto::combine_power_words(qb_h, qb_l),
202 proto::combine_power_words(qc_h, qc_l),
203 ],
204 pf: [pfa as i16, pfb as i16, pfc as i16],
205 frequency: freq,
206 phase_angle: [ang_a, ang_b, ang_c],
207 })
208 }
209
210 pub async fn read_voltage(&mut self, phase: Phase) -> Result<u16, Error<SPI::Error>> {
218 const REGS: [u16; 3] = [REG_URMS_A, REG_URMS_B, REG_URMS_C];
219 self.read_register(REGS[phase.index()]).await
220 }
221
222 pub async fn read_current(&mut self, phase: Phase) -> Result<u16, Error<SPI::Error>> {
228 const REGS: [u16; 3] = [REG_IRMS_A, REG_IRMS_B, REG_IRMS_C];
229 self.read_register(REGS[phase.index()]).await
230 }
231
232 pub async fn read_active_power(&mut self, phase: Phase) -> Result<i32, Error<SPI::Error>> {
238 const HI: [u16; 3] = [REG_PMEAN_A, REG_PMEAN_B, REG_PMEAN_C];
239 const LO: [u16; 3] = [REG_PMEAN_A_LSB, REG_PMEAN_B_LSB, REG_PMEAN_C_LSB];
240 let idx = phase.index();
241 let hi = self.read_register(HI[idx]).await?;
242 let lo = self.read_register(LO[idx]).await?;
243 Ok(proto::combine_power_words(hi, lo))
244 }
245
246 pub async fn read_reactive_power(&mut self, phase: Phase) -> Result<i32, Error<SPI::Error>> {
252 const HI: [u16; 3] = [REG_QMEAN_A, REG_QMEAN_B, REG_QMEAN_C];
253 const LO: [u16; 3] = [REG_QMEAN_A_LSB, REG_QMEAN_B_LSB, REG_QMEAN_C_LSB];
254 let idx = phase.index();
255 let hi = self.read_register(HI[idx]).await?;
256 let lo = self.read_register(LO[idx]).await?;
257 Ok(proto::combine_power_words(hi, lo))
258 }
259
260 pub async fn read_power_factor(&mut self, phase: Phase) -> Result<i16, Error<SPI::Error>> {
266 const REGS: [u16; 3] = [REG_PFMEAN_A, REG_PFMEAN_B, REG_PFMEAN_C];
267 let raw = self.read_register(REGS[phase.index()]).await?;
268 Ok(raw as i16)
269 }
270
271 pub async fn read_frequency(&mut self) -> Result<u16, Error<SPI::Error>> {
277 self.read_register(REG_FREQ).await
278 }
279
280 pub async fn read_phase_angle(&mut self, phase: Phase) -> Result<u16, Error<SPI::Error>> {
286 const REGS: [u16; 3] = [REG_PANGLE_A, REG_PANGLE_B, REG_PANGLE_C];
287 self.read_register(REGS[phase.index()]).await
288 }
289
290 pub async fn read_chip_temperature(&mut self) -> Result<u16, Error<SPI::Error>> {
296 self.read_register(REG_TEMP).await
297 }
298
299 pub async fn read_status(&mut self) -> Result<PhaseStatus, Error<SPI::Error>> {
304 let s0 = self.read_register(REG_EMMSTATE0).await?;
305 let s1 = self.read_register(REG_EMMSTATE1).await?;
306 Ok(PhaseStatus::from_emm(s0, s1))
307 }
308}