pamoja_sensors/ina226/
sim.rs1use pamoja_hal::sim::WordPart;
12
13use super::{
14 bus_register, current_register, minimum_current_lsb_microamps, power_register, register,
15 shunt_register, MaskEnable, DEVICE_ID, MANUFACTURER_ID,
16};
17
18pub const SHUNT_MILLIOHMS: u32 = 100;
20
21pub const MAX_MICROAMPS: u32 = 3_200_000;
23
24pub const BUS_MICROVOLTS: u32 = 12_000_000;
26
27pub const MICROAMPS: i32 = 500_000;
29
30#[must_use]
41pub fn part(address: u8) -> WordPart {
42 reporting(
43 address,
44 SHUNT_MILLIOHMS,
45 MAX_MICROAMPS,
46 BUS_MICROVOLTS,
47 MICROAMPS,
48 )
49}
50
51#[must_use]
79pub fn reporting(
80 address: u8,
81 shunt_milliohms: u32,
82 max_microamps: u32,
83 bus_microvolts: u32,
84 microamps: i32,
85) -> WordPart {
86 let lsb = minimum_current_lsb_microamps(max_microamps);
87 let shunt_nanovolts = i64::from(microamps) * i64::from(shunt_milliohms);
88 let microwatts = i64::from(bus_microvolts) * i64::from(microamps).abs() / 1_000_000;
89 let quiet = MaskEnable::from_register(0);
90 let flags = MaskEnable {
91 alert_function_flag: true,
92 conversion_ready_flag: true,
93 math_overflow: true,
94 ..quiet
95 }
96 .to_register();
97 let ready = MaskEnable {
98 conversion_ready_flag: true,
99 ..quiet
100 }
101 .to_register();
102 WordPart::new(address)
103 .holding(register::MANUFACTURER_ID, MANUFACTURER_ID)
104 .holding(register::DIE_ID, DEVICE_ID << 4)
105 .holding(register::MASK_ENABLE, ready)
106 .read_only(register::MASK_ENABLE, flags)
107 .holding(
108 register::SHUNT_VOLTAGE,
109 shunt_register(shunt_nanovolts as i32) as u16,
110 )
111 .holding(register::BUS_VOLTAGE, bus_register(bus_microvolts))
112 .holding(register::CURRENT, current_register(microamps, lsb) as u16)
113 .holding(register::POWER, power_register(microwatts as u32, lsb))
114}
115
116#[cfg(test)]
117mod tests {
118 use super::*;
119 use crate::ina226::{identify, Ina226};
120 use pamoja_hal::script::DelayLog;
121
122 #[test]
123 fn the_part_identifies_as_an_ina226() {
124 let part = part(0x40);
125 assert!(identify(
126 part.word(register::MANUFACTURER_ID),
127 part.word(register::DIE_ID)
128 )
129 .is_ok());
130 }
131
132 #[test]
133 fn a_driver_with_the_same_shunt_reads_the_load() {
134 let mut monitor = Ina226::new(part(0x40), 0x40, DelayLog::new());
135 let reading = monitor.measure().expect("a reading");
136 let step = i64::from(minimum_current_lsb_microamps(MAX_MICROAMPS));
137 assert_eq!(reading.bus_microvolts(), BUS_MICROVOLTS);
138 assert!((i64::from(reading.current_microamps()) - i64::from(MICROAMPS)).abs() < step);
139
140 let discharging = reporting(0x45, 2, 20_000_000, 3_300_000, -10_000_000);
141 let mut monitor = Ina226::new(discharging, 0x45, DelayLog::new()).with_shunt(2, 20_000_000);
142 let reading = monitor.measure().expect("a reading");
143 let step = i64::from(minimum_current_lsb_microamps(20_000_000));
144 assert!((i64::from(reading.current_microamps()) + 10_000_000).abs() < step);
145 assert_eq!(reading.bus_microvolts(), 3_300_000);
146 }
147}