1use super::{I2c, RegisterInterface, bisync, only_async, only_sync};
2use crate::{
3 AlertFlags, AveragingMode, BUS_VOLTAGE_LSB_MV, ChannelId, ConversionTime, Ina3221Error,
4 Ina3221Interface, Ina3221LowLevel, OperatingMode, SHUNT_VOLTAGE_LSB_UV,
5};
6
7#[bisync]
8impl<I2CBus, E> RegisterInterface for Ina3221Interface<I2CBus>
9where
10 I2CBus: I2c<Error = E>,
11 E: core::fmt::Debug,
12{
13 type AddressType = u8;
14 type Error = Ina3221Error<E>;
15 async fn read_register(
16 &mut self,
17 address: u8,
18 _size_bits: u32,
19 data: &mut [u8],
20 ) -> Result<(), Self::Error> {
21 self.i2c_bus
22 .write_read(self.address, &[address], data)
23 .await
24 .map_err(Ina3221Error::I2c)
25 }
26 async fn write_register(
27 &mut self,
28 address: u8,
29 _size_bits: u32,
30 data: &[u8],
31 ) -> Result<(), Self::Error> {
32 let mut buffer = [0u8; 5];
33 if (1 + data.len()) > buffer.len() {
34 return Err(Ina3221Error::NotSupported(
35 "Write data length exceeds buffer",
36 ));
37 }
38 buffer[0] = address;
39 buffer[1..1 + data.len()].copy_from_slice(data);
40 self.i2c_bus
41 .write(self.address, &buffer[..1 + data.len()])
42 .await
43 .map_err(Ina3221Error::I2c)
44 }
45}
46
47pub struct Ina3221<
48 I2CImpl: RegisterInterface<AddressType = u8, Error = Ina3221Error<I2CBusErr>>,
49 I2CBusErr: core::fmt::Debug,
50> {
51 pub ll: Ina3221LowLevel<I2CImpl>,
52 _marker: core::marker::PhantomData<I2CBusErr>,
53}
54
55impl<I2CBus, E> Ina3221<Ina3221Interface<I2CBus>, E>
56where
57 I2CBus: I2c<Error = E>,
58 E: core::fmt::Debug,
59{
60 pub fn new(i2c: I2CBus, address: u8) -> Self {
61 Self {
62 ll: Ina3221LowLevel::new(Ina3221Interface::new(i2c, address)),
63 _marker: core::marker::PhantomData,
64 }
65 }
66}
67
68include!("bisync_helpers.rs");
69
70impl<I2CImpl, I2CBusErr> Ina3221<I2CImpl, I2CBusErr>
71where
72 I2CImpl: RegisterInterface<AddressType = u8, Error = Ina3221Error<I2CBusErr>>,
73 I2CBusErr: core::fmt::Debug,
74{
75 #[bisync]
82 pub async fn get_bus_voltage_mv(
83 &mut self,
84 channel: ChannelId,
85 ) -> Result<f32, Ina3221Error<I2CBusErr>> {
86 let mut op = match channel {
87 ChannelId::Channel1 => self.ll.channel_1_bus_voltage(),
88 ChannelId::Channel2 => self.ll.channel_2_bus_voltage(),
89 ChannelId::Channel3 => self.ll.channel_3_bus_voltage(),
90 };
91
92 let bus_data = read_internal(&mut op).await?;
93
94 let raw_value = bus_data.bus_data() as u16;
95 let sign = bus_data.sign();
96
97 let voltage_mv = if sign {
98 -(raw_value as f32 * BUS_VOLTAGE_LSB_MV)
99 } else {
100 raw_value as f32 * BUS_VOLTAGE_LSB_MV
101 };
102
103 Ok(voltage_mv)
104 }
105
106 #[bisync]
109 pub async fn get_shunt_voltage_uv(
110 &mut self,
111 channel: ChannelId,
112 ) -> Result<f32, Ina3221Error<I2CBusErr>> {
113 let mut op = match channel {
114 ChannelId::Channel1 => self.ll.channel_1_shunt_voltage(),
115 ChannelId::Channel2 => self.ll.channel_2_shunt_voltage(),
116 ChannelId::Channel3 => self.ll.channel_3_shunt_voltage(),
117 };
118
119 let shunt_data = read_internal(&mut op).await?;
120
121 let raw_value = shunt_data.shunt_data() as u16;
122 let sign = shunt_data.sign();
123
124 let voltage_uv = if sign {
125 -(raw_value as f32 * SHUNT_VOLTAGE_LSB_UV)
126 } else {
127 raw_value as f32 * SHUNT_VOLTAGE_LSB_UV
128 };
129
130 Ok(voltage_uv)
131 }
132
133 #[bisync]
136 pub async fn get_current_ma(
137 &mut self,
138 channel: ChannelId,
139 shunt_resistor_mohms: f32,
140 ) -> Result<f32, Ina3221Error<I2CBusErr>> {
141 let shunt_voltage_uv = self.get_shunt_voltage_uv(channel).await?;
142 Ok(shunt_voltage_uv / shunt_resistor_mohms)
144 }
145
146 #[bisync]
149 pub async fn get_power_mw(
150 &mut self,
151 channel: ChannelId,
152 shunt_resistor_mohms: f32,
153 ) -> Result<f32, Ina3221Error<I2CBusErr>> {
154 let bus_voltage_mv = self.get_bus_voltage_mv(channel).await?;
155 let current_ma = self.get_current_ma(channel, shunt_resistor_mohms).await?;
156 Ok((bus_voltage_mv * current_ma) / 1000.0)
158 }
159
160 #[bisync]
166 pub async fn set_channel_enable(
167 &mut self,
168 channel: ChannelId,
169 enable: bool,
170 ) -> Result<(), Ina3221Error<I2CBusErr>> {
171 let mut op = self.ll.configuration();
172 modify_internal(&mut op, |r| match channel {
173 ChannelId::Channel1 => r.set_ch_1_enable(enable),
174 ChannelId::Channel2 => r.set_ch_2_enable(enable),
175 ChannelId::Channel3 => r.set_ch_3_enable(enable),
176 })
177 .await
178 }
179
180 #[bisync]
182 pub async fn is_channel_enabled(
183 &mut self,
184 channel: ChannelId,
185 ) -> Result<bool, Ina3221Error<I2CBusErr>> {
186 let mut op = self.ll.configuration();
187 let config = read_internal(&mut op).await?;
188 Ok(match channel {
189 ChannelId::Channel1 => config.ch_1_enable(),
190 ChannelId::Channel2 => config.ch_2_enable(),
191 ChannelId::Channel3 => config.ch_3_enable(),
192 })
193 }
194
195 #[bisync]
197 pub async fn set_all_channels_enable(
198 &mut self,
199 ch1: bool,
200 ch2: bool,
201 ch3: bool,
202 ) -> Result<(), Ina3221Error<I2CBusErr>> {
203 let mut op = self.ll.configuration();
204 modify_internal(&mut op, |r| {
205 r.set_ch_1_enable(ch1);
206 r.set_ch_2_enable(ch2);
207 r.set_ch_3_enable(ch3);
208 })
209 .await
210 }
211
212 #[bisync]
218 pub async fn get_operating_mode(&mut self) -> Result<OperatingMode, Ina3221Error<I2CBusErr>> {
219 let mut op = self.ll.configuration();
220 let config = read_internal(&mut op).await?;
221 Ok(OperatingMode::from_raw(config.operating_mode() as u8))
222 }
223
224 #[bisync]
226 pub async fn set_operating_mode(
227 &mut self,
228 mode: OperatingMode,
229 ) -> Result<(), Ina3221Error<I2CBusErr>> {
230 let mut op = self.ll.configuration();
231 modify_internal(&mut op, |r| r.set_operating_mode(mode as u8)).await
232 }
233
234 #[bisync]
236 pub async fn get_averaging_mode(&mut self) -> Result<AveragingMode, Ina3221Error<I2CBusErr>> {
237 let mut op = self.ll.configuration();
238 let config = read_internal(&mut op).await?;
239 Ok(AveragingMode::from_raw(config.averaging_mode() as u8))
240 }
241
242 #[bisync]
244 pub async fn set_averaging_mode(
245 &mut self,
246 mode: AveragingMode,
247 ) -> Result<(), Ina3221Error<I2CBusErr>> {
248 let mut op = self.ll.configuration();
249 modify_internal(&mut op, |r| r.set_averaging_mode(mode as u8)).await
250 }
251
252 #[bisync]
254 pub async fn get_vbus_conversion_time(
255 &mut self,
256 ) -> Result<ConversionTime, Ina3221Error<I2CBusErr>> {
257 let mut op = self.ll.configuration();
258 let config = read_internal(&mut op).await?;
259 Ok(ConversionTime::from_raw(config.vbus_conversion_time() as u8))
260 }
261
262 #[bisync]
264 pub async fn set_vbus_conversion_time(
265 &mut self,
266 time: ConversionTime,
267 ) -> Result<(), Ina3221Error<I2CBusErr>> {
268 let mut op = self.ll.configuration();
269 modify_internal(&mut op, |r| r.set_vbus_conversion_time(time as u8)).await
270 }
271
272 #[bisync]
274 pub async fn get_vshunt_conversion_time(
275 &mut self,
276 ) -> Result<ConversionTime, Ina3221Error<I2CBusErr>> {
277 let mut op = self.ll.configuration();
278 let config = read_internal(&mut op).await?;
279 Ok(ConversionTime::from_raw(
280 config.vshunt_conversion_time() as u8
281 ))
282 }
283
284 #[bisync]
286 pub async fn set_vshunt_conversion_time(
287 &mut self,
288 time: ConversionTime,
289 ) -> Result<(), Ina3221Error<I2CBusErr>> {
290 let mut op = self.ll.configuration();
291 modify_internal(&mut op, |r| r.set_vshunt_conversion_time(time as u8)).await
292 }
293
294 #[bisync]
300 pub async fn get_critical_alert_limit_uv(
301 &mut self,
302 channel: ChannelId,
303 ) -> Result<f32, Ina3221Error<I2CBusErr>> {
304 let raw = match channel {
305 ChannelId::Channel1 => {
306 let mut op = self.ll.channel_1_critical_alert_limit();
307 read_internal(&mut op).await?.limit_data()
308 }
309 ChannelId::Channel2 => {
310 let mut op = self.ll.channel_2_critical_alert_limit();
311 read_internal(&mut op).await?.limit_data()
312 }
313 ChannelId::Channel3 => {
314 let mut op = self.ll.channel_3_critical_alert_limit();
315 read_internal(&mut op).await?.limit_data()
316 }
317 };
318 Ok(raw as f32 * SHUNT_VOLTAGE_LSB_UV)
319 }
320
321 #[bisync]
323 pub async fn set_critical_alert_limit_uv(
324 &mut self,
325 channel: ChannelId,
326 limit_uv: f32,
327 ) -> Result<(), Ina3221Error<I2CBusErr>> {
328 let raw = (limit_uv / SHUNT_VOLTAGE_LSB_UV) as u16;
329 match channel {
330 ChannelId::Channel1 => {
331 let mut op = self.ll.channel_1_critical_alert_limit();
332 modify_internal(&mut op, |r| r.set_limit_data(raw)).await
333 }
334 ChannelId::Channel2 => {
335 let mut op = self.ll.channel_2_critical_alert_limit();
336 modify_internal(&mut op, |r| r.set_limit_data(raw)).await
337 }
338 ChannelId::Channel3 => {
339 let mut op = self.ll.channel_3_critical_alert_limit();
340 modify_internal(&mut op, |r| r.set_limit_data(raw)).await
341 }
342 }
343 }
344
345 #[bisync]
347 pub async fn get_warning_alert_limit_uv(
348 &mut self,
349 channel: ChannelId,
350 ) -> Result<f32, Ina3221Error<I2CBusErr>> {
351 let raw = match channel {
352 ChannelId::Channel1 => {
353 let mut op = self.ll.channel_1_warning_alert_limit();
354 read_internal(&mut op).await?.limit_data()
355 }
356 ChannelId::Channel2 => {
357 let mut op = self.ll.channel_2_warning_alert_limit();
358 read_internal(&mut op).await?.limit_data()
359 }
360 ChannelId::Channel3 => {
361 let mut op = self.ll.channel_3_warning_alert_limit();
362 read_internal(&mut op).await?.limit_data()
363 }
364 };
365 Ok(raw as f32 * SHUNT_VOLTAGE_LSB_UV)
366 }
367
368 #[bisync]
370 pub async fn set_warning_alert_limit_uv(
371 &mut self,
372 channel: ChannelId,
373 limit_uv: f32,
374 ) -> Result<(), Ina3221Error<I2CBusErr>> {
375 let raw = (limit_uv / SHUNT_VOLTAGE_LSB_UV) as u16;
376 match channel {
377 ChannelId::Channel1 => {
378 let mut op = self.ll.channel_1_warning_alert_limit();
379 modify_internal(&mut op, |r| r.set_limit_data(raw)).await
380 }
381 ChannelId::Channel2 => {
382 let mut op = self.ll.channel_2_warning_alert_limit();
383 modify_internal(&mut op, |r| r.set_limit_data(raw)).await
384 }
385 ChannelId::Channel3 => {
386 let mut op = self.ll.channel_3_warning_alert_limit();
387 modify_internal(&mut op, |r| r.set_limit_data(raw)).await
388 }
389 }
390 }
391
392 #[bisync]
394 pub async fn get_power_valid_limits_mv(
395 &mut self,
396 ) -> Result<(f32, f32), Ina3221Error<I2CBusErr>> {
397 let mut op_upper = self.ll.power_valid_upper_limit();
398 let upper = read_internal(&mut op_upper).await?.limit_data();
399
400 let mut op_lower = self.ll.power_valid_lower_limit();
401 let lower = read_internal(&mut op_lower).await?.limit_data();
402
403 Ok((
404 lower as f32 * BUS_VOLTAGE_LSB_MV,
405 upper as f32 * BUS_VOLTAGE_LSB_MV,
406 ))
407 }
408
409 #[bisync]
411 pub async fn set_power_valid_limits_mv(
412 &mut self,
413 lower_mv: f32,
414 upper_mv: f32,
415 ) -> Result<(), Ina3221Error<I2CBusErr>> {
416 let lower_raw = (lower_mv / BUS_VOLTAGE_LSB_MV) as u16;
417 let upper_raw = (upper_mv / BUS_VOLTAGE_LSB_MV) as u16;
418
419 let mut op_lower = self.ll.power_valid_lower_limit();
420 modify_internal(&mut op_lower, |r| r.set_limit_data(lower_raw)).await?;
421
422 let mut op_upper = self.ll.power_valid_upper_limit();
423 modify_internal(&mut op_upper, |r| r.set_limit_data(upper_raw)).await
424 }
425
426 #[bisync]
432 pub async fn set_critical_alert_latch(
433 &mut self,
434 enable: bool,
435 ) -> Result<(), Ina3221Error<I2CBusErr>> {
436 let mut op = self.ll.mask_enable();
437 modify_internal(&mut op, |r| r.set_critical_alert_enable(enable)).await
438 }
439
440 #[bisync]
442 pub async fn set_warning_alert_latch(
443 &mut self,
444 enable: bool,
445 ) -> Result<(), Ina3221Error<I2CBusErr>> {
446 let mut op = self.ll.mask_enable();
447 modify_internal(&mut op, |r| r.set_warning_alert_enable(enable)).await
448 }
449
450 #[bisync]
452 pub async fn get_alert_flags(&mut self) -> Result<AlertFlags, Ina3221Error<I2CBusErr>> {
453 let mut op = self.ll.mask_enable();
454 let reg = read_internal(&mut op).await?;
455 Ok(AlertFlags {
456 conversion_ready: reg.conversion_ready_flag(),
457 timing_control: reg.timing_control_flag(),
458 power_valid: reg.power_valid_flag(),
459 warning_ch1: reg.warning_flag_ch_1(),
460 warning_ch2: reg.warning_flag_ch_2(),
461 warning_ch3: reg.warning_flag_ch_3(),
462 summation: reg.summation_flag(),
463 critical_ch1: reg.critical_flag_ch_1(),
464 critical_ch2: reg.critical_flag_ch_2(),
465 critical_ch3: reg.critical_flag_ch_3(),
466 })
467 }
468
469 #[bisync]
471 pub async fn is_conversion_ready(&mut self) -> Result<bool, Ina3221Error<I2CBusErr>> {
472 let flags = self.get_alert_flags().await?;
473 Ok(flags.conversion_ready)
474 }
475
476 #[bisync]
482 pub async fn set_summation_channel_enable(
483 &mut self,
484 channel: ChannelId,
485 enable: bool,
486 ) -> Result<(), Ina3221Error<I2CBusErr>> {
487 let mut op = self.ll.mask_enable();
488 modify_internal(&mut op, |r| match channel {
489 ChannelId::Channel1 => r.set_sum_control_ch_1(enable),
490 ChannelId::Channel2 => r.set_sum_control_ch_2(enable),
491 ChannelId::Channel3 => r.set_sum_control_ch_3(enable),
492 })
493 .await
494 }
495
496 #[bisync]
498 pub async fn get_shunt_voltage_sum_uv(&mut self) -> Result<f32, Ina3221Error<I2CBusErr>> {
499 let mut op = self.ll.shunt_voltage_sum();
500 let data = read_internal(&mut op).await?;
501 let raw = data.sum_data() as u16;
502 let sign = data.sign();
503
504 let voltage_uv = if sign {
505 -(raw as f32 * SHUNT_VOLTAGE_LSB_UV)
506 } else {
507 raw as f32 * SHUNT_VOLTAGE_LSB_UV
508 };
509 Ok(voltage_uv)
510 }
511
512 #[bisync]
514 pub async fn get_shunt_voltage_sum_limit_uv(&mut self) -> Result<f32, Ina3221Error<I2CBusErr>> {
515 let mut op = self.ll.shunt_voltage_sum_limit();
516 let data = read_internal(&mut op).await?;
517 Ok(data.limit_data() as f32 * SHUNT_VOLTAGE_LSB_UV)
518 }
519
520 #[bisync]
522 pub async fn set_shunt_voltage_sum_limit_uv(
523 &mut self,
524 limit_uv: f32,
525 ) -> Result<(), Ina3221Error<I2CBusErr>> {
526 let raw = (limit_uv / SHUNT_VOLTAGE_LSB_UV) as u16;
527 let mut op = self.ll.shunt_voltage_sum_limit();
528 modify_internal(&mut op, |r| r.set_limit_data(raw)).await
529 }
530
531 #[bisync]
537 pub async fn get_manufacturer_id(&mut self) -> Result<u16, Ina3221Error<I2CBusErr>> {
538 let mut op = self.ll.manufacturer_id();
539 let id = read_internal(&mut op).await?;
540 Ok(id.manufacturer_id() as u16)
541 }
542
543 #[bisync]
545 pub async fn get_die_id(&mut self) -> Result<u16, Ina3221Error<I2CBusErr>> {
546 let mut op = self.ll.die_id();
547 let id = read_internal(&mut op).await?;
548 Ok(id.die_id() as u16)
549 }
550
551 #[bisync]
553 pub async fn reset(&mut self) -> Result<(), Ina3221Error<I2CBusErr>> {
554 let mut op = self.ll.configuration();
555 modify_internal(&mut op, |r| r.set_reset(true)).await
556 }
557}
558
559#[cfg(feature = "uom")]
564impl<I2CImpl, I2CBusErr> Ina3221<I2CImpl, I2CBusErr>
565where
566 I2CImpl: RegisterInterface<AddressType = u8, Error = Ina3221Error<I2CBusErr>>,
567 I2CBusErr: core::fmt::Debug,
568{
569 #[bisync]
571 pub async fn get_bus_voltage(
572 &mut self,
573 channel: ChannelId,
574 ) -> Result<crate::ElectricPotential, Ina3221Error<I2CBusErr>> {
575 let mv = self.get_bus_voltage_mv(channel).await?;
576 Ok(crate::ElectricPotential::new::<crate::millivolt>(mv))
577 }
578
579 #[bisync]
581 pub async fn get_shunt_voltage(
582 &mut self,
583 channel: ChannelId,
584 ) -> Result<crate::ElectricPotential, Ina3221Error<I2CBusErr>> {
585 let uv = self.get_shunt_voltage_uv(channel).await?;
586 Ok(crate::ElectricPotential::new::<crate::microvolt>(uv))
587 }
588
589 #[bisync]
591 pub async fn get_current(
592 &mut self,
593 channel: ChannelId,
594 shunt_resistor: crate::ElectricalResistance,
595 ) -> Result<crate::ElectricCurrent, Ina3221Error<I2CBusErr>> {
596 let shunt_mohms = shunt_resistor.get::<crate::milliohm>();
597 let ma = self.get_current_ma(channel, shunt_mohms).await?;
598 Ok(crate::ElectricCurrent::new::<crate::milliampere>(ma))
599 }
600
601 #[bisync]
603 pub async fn set_critical_alert_limit(
604 &mut self,
605 channel: ChannelId,
606 limit: crate::ElectricPotential,
607 ) -> Result<(), Ina3221Error<I2CBusErr>> {
608 let uv = limit.get::<crate::microvolt>();
609 self.set_critical_alert_limit_uv(channel, uv).await
610 }
611
612 #[bisync]
614 pub async fn set_warning_alert_limit(
615 &mut self,
616 channel: ChannelId,
617 limit: crate::ElectricPotential,
618 ) -> Result<(), Ina3221Error<I2CBusErr>> {
619 let uv = limit.get::<crate::microvolt>();
620 self.set_warning_alert_limit_uv(channel, uv).await
621 }
622
623 #[bisync]
625 pub async fn set_power_valid_limits(
626 &mut self,
627 lower: crate::ElectricPotential,
628 upper: crate::ElectricPotential,
629 ) -> Result<(), Ina3221Error<I2CBusErr>> {
630 let lower_mv = lower.get::<crate::millivolt>();
631 let upper_mv = upper.get::<crate::millivolt>();
632 self.set_power_valid_limits_mv(lower_mv, upper_mv).await
633 }
634}