1#![cfg_attr(not(test), no_std)]
28
29pub mod regs;
30
31use embedded_hal::blocking::i2c;
32use packed_struct::prelude::*;
33use paste::paste;
34use regs::*;
35
36#[repr(u8)]
37#[derive(Debug, Copy, Clone)]
38pub enum AddrSelect {
43 GND = 0b10000,
44 _499 = 0b10001,
45 _806 = 0b10010,
46 _1270 = 0b10011,
47 _2050 = 0b10100,
48 _3240 = 0b10101,
49 _5230 = 0b10110,
50 _8450 = 0b10111,
51 _13300 = 0b11000,
52 _21500 = 0b11001,
53 _34000 = 0b11010,
54 _54900 = 0b11011,
55 _88700 = 0b11100,
56 _140000 = 0b11101,
57 _226000 = 0b11110,
58 VDD = 0b11111,
59}
60
61#[derive(Debug, Copy, Clone)]
63pub enum ProductId {
64 PAC1941_1,
65 PAC1942_1,
66 PAC1943_1,
67 PAC1944_1,
68 PAC1941_2,
69 PAC1942_2,
70}
71
72pub struct PAC194X<I>
74where
75 I: i2c::Read + i2c::Write + i2c::WriteRead,
76{
77 i2c: I,
78 address: u8,
79}
80
81#[derive(Debug, PartialEq)]
83pub enum Error<E> {
84 I2c(E),
86 Internal,
88}
89
90macro_rules! read_fn {
91 ($var:ident: $type:ty) => {
92 paste! {
93 #[doc = stringify!(Reads the $type register and deserializes into the appropriate struct)]
94 pub fn [<read_ $var>](&mut self) -> Result<$type, Error<E>> {
95 Ok($type::unpack(&self.block_read($type::addr())?).unwrap())
96 }
97 }
98 };
99}
100
101macro_rules! read_n_fn {
102 ($var:ident: $type:ty) => {
103 paste! {
104 #[doc = stringify!(Reads the $type register and deserializes into the appropriate struct)]
105 pub fn [<read_ $var>](&mut self, n: u8) -> Result<$type, Error<E>> {
106 assert!((1..=4).contains(&n),"Channel n must be between 1 and 4");
107 Ok($type::unpack(&self.block_read_n($type::addr(),n)?).unwrap())
108 }
109 }
110 };
111}
112
113macro_rules! write_fn {
114 ($var:ident: $type:ty) => {
115 paste! {
116 #[doc = stringify!(Writes out the $type register)]
117 pub fn [<write_ $var>](&mut self, $var: $type) -> Result<(), Error<E>> {
118 const PACKED_SIZE_WITH_ADDR: usize = core::mem::size_of::<<$type as PackedStruct>::ByteArray>() + 1;
119 let mut bytes = [0u8; PACKED_SIZE_WITH_ADDR];
120 bytes[0] = $type::addr() as u8;
121 $var.pack_to_slice(&mut bytes[1..]).unwrap();
122 self.block_write(&bytes)?;
123 Ok(())
124 }
125 }
126 };
127}
128
129macro_rules! write_n_fn {
130 ($var:ident: $type:ty) => {
131 paste! {
132 #[doc = stringify!(Writes out the $type register)]
133 pub fn [<write_ $var>](&mut self, $var: $type, n: u8) -> Result<(), Error<E>> {
134 assert!((1..=4).contains(&n),"Channel n must be between 1 and 4");
135 const PACKED_SIZE_WITH_ADDR: usize = core::mem::size_of::<<$type as PackedStruct>::ByteArray>() + 1;
136 let mut bytes = [0u8; PACKED_SIZE_WITH_ADDR];
137 bytes[0] = ($type::addr() as u8) + n - 1;
138 $var.pack_to_slice(&mut bytes[1..]).unwrap();
139 self.block_write(&bytes)?;
140 Ok(())
141 }
142 }
143 };
144}
145
146macro_rules! read_write {
147 ($var:ident: $type:ty) => {
148 write_fn!($var: $type);
149 read_fn!($var: $type);
150 };
151}
152
153macro_rules! read_write_n {
154 ($var:ident: $type:ty) => {
155 write_n_fn!($var: $type);
156 read_n_fn!($var: $type);
157 };
158}
159
160fn vbus_to_real(raw: u16, fsr: VBusFSR) -> f32 {
161 9.0 * match fsr {
162 VBusFSR::Unipolar => (raw as f32) / 65536.0,
163 VBusFSR::BipolarHV => (i16::from_ne_bytes(raw.to_le_bytes()) as f32) / 65536.0,
164 VBusFSR::BipolarLV => (i16::from_ne_bytes(raw.to_le_bytes()) as f32) / 32768.0,
165 }
166}
167
168fn vsense_to_real(raw: u16, fsr: VSenseFSR) -> f32 {
169 0.1 * match fsr {
170 VSenseFSR::Unipolar => (raw as f32) / 65536.0,
171 VSenseFSR::BipolarHV => (i16::from_ne_bytes(raw.to_le_bytes()) as f32) / 65536.0,
172 VSenseFSR::BipolarLV => (i16::from_ne_bytes(raw.to_le_bytes()) as f32) / 32768.0,
173 }
174}
175
176impl<E, I> PAC194X<I>
177where
178 I: i2c::Read<Error = E> + i2c::Write<Error = E> + i2c::WriteRead<Error = E>,
179{
180 pub fn new(i2c: I, addr_sel: AddrSelect) -> Self {
185 Self {
186 i2c,
187 address: addr_sel as u8,
188 }
189 }
190
191 fn send_byte(&mut self, addr: Address) -> Result<(), Error<E>> {
194 self.i2c
195 .write(self.address, &[addr as u8])
196 .map_err(Error::I2c)?;
197 Ok(())
198 }
199
200 fn receive_byte(&mut self) -> Result<u8, Error<E>> {
203 let mut buf = [0u8; 1];
204 self.i2c.read(self.address, &mut buf).map_err(Error::I2c)?;
205 Ok(buf[0])
206 }
207
208 fn block_write(&mut self, bytes: &[u8]) -> Result<(), Error<E>> {
211 self.i2c.write(self.address, bytes).map_err(Error::I2c)?;
212 Ok(())
213 }
214
215 fn block_read<const N: usize>(&mut self, addr: Address) -> Result<[u8; N], Error<E>> {
218 let mut buf = [0u8; N];
219 self.i2c
220 .write_read(self.address, &[addr as u8], &mut buf)
221 .map_err(Error::I2c)?;
222 Ok(buf)
223 }
224
225 fn block_read_n<const N: usize>(&mut self, addr: Address, n: u8) -> Result<[u8; N], Error<E>> {
227 let mut buf = [0u8; N];
228 self.i2c
229 .write_read(self.address, &[(addr as u8) + (n - 1)], &mut buf)
230 .map_err(Error::I2c)?;
231 Ok(buf)
232 }
233
234 pub fn refresh(&mut self) -> Result<(), Error<E>> {
239 self.send_byte(Address::Refresh)
240 }
241
242 pub fn refresh_v(&mut self) -> Result<(), Error<E>> {
246 self.send_byte(Address::RefreshV)
247 }
248
249 pub fn regresh_g(&mut self) -> Result<(), Error<E>> {
252 self.i2c
253 .write(0u8, &[Address::RefreshG as u8])
254 .map_err(Error::I2c)?;
255 Ok(())
256 }
257
258 pub fn product_id(&mut self) -> Result<ProductId, Error<E>> {
260 self.send_byte(regs::Address::ProductId)?;
261 Ok(match self.receive_byte()? {
262 0b0110_1000 => ProductId::PAC1941_1,
263 0b0110_1001 => ProductId::PAC1942_1,
264 0b0110_1010 => ProductId::PAC1943_1,
265 0b0110_1011 => ProductId::PAC1944_1,
266 0b0110_1100 => ProductId::PAC1941_2,
267 0b0110_1101 => ProductId::PAC1942_2,
268 _ => unreachable!(),
269 })
270 }
271
272 pub fn manufacturer_id(&mut self) -> Result<u8, Error<E>> {
275 self.send_byte(regs::Address::ManufacturerId)?;
276 self.receive_byte()
277 }
278
279 pub fn revision_id(&mut self) -> Result<u8, Error<E>> {
282 self.send_byte(regs::Address::RevisionId)?;
283 self.receive_byte()
284 }
285
286 pub fn read_bus_voltage_n(&mut self, n: u8) -> Result<f32, Error<E>> {
288 assert!((1..=4).contains(&n), "Channel n must be between 1 and 4");
289 let fsr_reg = self.read_neg_pwr_fsr_lat()?;
290 let fsr = match n {
291 1 => fsr_reg.cfg_vb1,
292 2 => fsr_reg.cfg_vb2,
293 3 => fsr_reg.cfg_vb3,
294 4 => fsr_reg.cfg_vb4,
295 _ => unreachable!(),
296 };
297 Ok(vbus_to_real(self.read_vbusn(n)?.voltage, fsr))
298 }
299
300 pub fn read_sense_voltage_n(&mut self, n: u8) -> Result<f32, Error<E>> {
303 assert!((1..=4).contains(&n), "Channel n must be between 1 and 4");
304 let fsr_reg = self.read_neg_pwr_fsr_lat()?;
305 let fsr = match n {
306 1 => fsr_reg.cfg_vs1,
307 2 => fsr_reg.cfg_vs2,
308 3 => fsr_reg.cfg_vs3,
309 4 => fsr_reg.cfg_vs4,
310 _ => unreachable!(),
311 };
312 Ok(vsense_to_real(self.read_vsensen(n)?.voltage, fsr))
313 }
314
315 pub fn read_avg_bus_voltage_n(&mut self, n: u8) -> Result<f32, Error<E>> {
317 assert!((1..=4).contains(&n), "Channel n must be between 1 and 4");
318 let fsr_reg = self.read_neg_pwr_fsr_lat()?;
319 let fsr = match n {
320 1 => fsr_reg.cfg_vb1,
321 2 => fsr_reg.cfg_vb2,
322 3 => fsr_reg.cfg_vb3,
323 4 => fsr_reg.cfg_vb4,
324 _ => unreachable!(),
325 };
326 Ok(vbus_to_real(self.read_vbusn_avg(n)?.voltage, fsr))
327 }
328
329 pub fn read_avg_sense_voltage_n(&mut self, n: u8) -> Result<f32, Error<E>> {
331 assert!((1..=4).contains(&n), "Channel n must be between 1 and 4");
332 let fsr_reg = self.read_neg_pwr_fsr_lat()?;
333 let fsr = match n {
334 1 => fsr_reg.cfg_vs1,
335 2 => fsr_reg.cfg_vs2,
336 3 => fsr_reg.cfg_vs3,
337 4 => fsr_reg.cfg_vs4,
338 _ => unreachable!(),
339 };
340 Ok(vsense_to_real(self.read_vsensen(n)?.voltage, fsr))
341 }
342
343 read_write!(ctrl: Ctrl);
345 read_write!(acc_count: AccCount);
346 read_n_fn!(vaccn: Vaccn);
347 read_n_fn!(vbusn: Vbusn);
348 read_n_fn!(vsensen: Vsensen);
349 read_n_fn!(vbusn_avg: VbusnAvg);
350 read_n_fn!(vsensen_avg: VsensenAvg);
351 read_n_fn!(vpowern: Vpowern);
352 read_write!(smub_settings: SmbusSettings);
353 read_write!(neg_pwr_fsr: NegPwrFsr);
354 read_fn!(slow: Slow);
355 read_fn!(ctrl_act: CtrlAct);
356 read_write!(neg_pwr_fsr_act: NegPwrFsrAct);
357 read_fn!(ctrl_lat: CtrlLat);
358 read_write!(neg_pwr_fsr_lat: NegPwrFsrLat);
359 read_write!(accum_config: AccumConfig);
360 read_fn!(alert_statuc: AlertStatus);
361 read_write!(slow_alert1: SlowAlert1);
362 read_write!(gpio_alert2: GpioAlert2);
363 read_write!(acc_fullness_limits: AccFullnessLimits);
364 read_write_n!(oc_limitn: OcLimitn);
365 read_write_n!(uc_limitn: UcLimitn);
366 read_write_n!(op_limitn: OpLimitn);
367 read_write_n!(ov_limitn: OvLimitn);
368 read_write_n!(uv_limitn: UvLimitn);
369 read_write!(oc_limit_n_samples: OcLimitNSamples);
370 read_write!(uc_limit_n_samples: UcLimitNSamples);
371 read_write!(op_limit_n_samples: OpLimitNSamples);
372 read_write!(ov_limit_n_samples: OvLimitNSamples);
373 read_write!(uv_limit_n_samples: UvLimitNSamples);
374 read_write!(alert_enable: AlertEnable);
375 read_write!(accum_config_act: AccumConfigAct);
376 read_write!(accum_config_lat: AccumConfigLat);
377}
378
379#[cfg(test)]
380mod tests {
381 use super::*;
382 #[test]
383 fn addr_values() {
384 assert_eq!(Address::AlertEnable as u8, 0x49);
385 assert_eq!(Address::RevisionId as u8, 0xFF);
386 }
387}