Skip to main content

ap33772s_rs/commands/data_objects/
standard_power_range_data_object.rs

1use crate::commands::data_objects::source_power_range_data_object::{
2    PeakCurrent, SourceMaximumCurrent,
3};
4use crate::units::*;
5use crate::{
6    commands::data_objects::source_power_range_data_object::PowerType, errors::Ap33772sError,
7};
8use arbitrary_int::u2;
9use bitbybit::bitfield;
10
11/// Represents the standard power range for the AP33772S.
12/// Many Power supplies will support various `objects` that implement the StandardPowerRange.
13/// This contains all the necessary information to select or query what the
14/// power range capabilities are.
15#[bitfield(u16, default = 0x00, defmt_bitfields(feature = "defmt"))]
16#[derive(Debug, PartialEq)]
17pub struct StandardPowerRangeDataObject {
18    #[bits(0..=7, r)]
19    pub raw_max_voltage: u8,
20    #[bits(8..=9, r)]
21    pub minimum_voltage_or_peak_current: u2,
22    #[bits(10..=13, r)]
23    pub max_current: SourceMaximumCurrent,
24    #[bit(14, r)]
25    pub source_power_type: PowerType,
26    #[bit(15, r)]
27    pub is_detected: bool,
28}
29
30/// Maximum Voltage of 21 (21000 mV) with 100mV resolution
31/// U16 can hold values up to 65535
32/// 0 = 0mV
33/// 1 = 100mV
34/// 2 = 200mV
35/// ...
36/// 210 = 21000mV (21V)
37/// This means the maximum raw value is 210
38/// 210 * 100 = 21000mV
39/// Therefore the voltage should be checked multiplied and stored in a U16
40impl StandardPowerRangeDataObject {
41    /// The Voltage Resolution defined in mV per LSB
42    pub const VOLTAGE_RESOLUTION: u16 = 100;
43    /// The Maximum Voltage that can be requested using this data object, this is not the `max_voltage` that the data object can provide,
44    /// but rather the Absolute Maximum Voltage that the Standard rage profile can support.
45    /// Use [max_voltage function](crate::commands::data_objects::standard_power_range_data_object::StandardPowerRangeDataObject::max_voltage)
46    /// to find out what value is supported.
47    /// It is is defined in mV
48    pub const ABSOLUTE_MAXIMUM_VOLTAGE: u16 = 21000; // mV
49    /// Returns the maximum voltage that can be requested using this data object.
50    pub fn max_voltage(&self) -> Result<ElectricPotential, Ap33772sError> {
51        let scaled_voltage = u16::from(self.raw_max_voltage())
52            .checked_mul(Self::VOLTAGE_RESOLUTION)
53            .ok_or(Ap33772sError::ConversionFailed)?;
54        Ok(ElectricPotential::new::<millivolt>(f32::from(
55            scaled_voltage,
56        )))
57    }
58
59    /// Returns the peak current that can be requested using this data object.
60    pub fn peak_current(&self) -> Option<PeakCurrent> {
61        match self.source_power_type() {
62            PowerType::Fixed => Some(PeakCurrent::from(self.minimum_voltage_or_peak_current())),
63            PowerType::Adjustable => None,
64        }
65    }
66
67    /// Returns the minimum voltage that can be requested using this data object.
68    pub fn minimum_voltage(&self) -> Option<MinimumVoltage> {
69        match self.source_power_type() {
70            PowerType::Fixed => None,
71            PowerType::Adjustable => {
72                Some(MinimumVoltage::from(self.minimum_voltage_or_peak_current()))
73            }
74        }
75    }
76}
77
78/// The supported minimum voltages for the Standard Power Range Data Object when working in Programmable Power Supply mode
79#[derive(Debug, PartialEq)]
80#[cfg_attr(feature = "defmt", derive(defmt::Format))]
81pub enum MinimumVoltage {
82    Reserved = 0,
83    _3_3 = 1,
84    _3_3To5 = 2,
85    Others = 3,
86}
87
88impl From<u2> for MinimumVoltage {
89    fn from(value: u2) -> Self {
90        match value.value() {
91            0 => MinimumVoltage::Reserved,
92            1 => MinimumVoltage::_3_3,
93            2 => MinimumVoltage::_3_3To5,
94            3 => MinimumVoltage::Others,
95            _ => unreachable!("This will never happen due to rust type safety"),
96        }
97    }
98}
99
100impl core::fmt::Display for StandardPowerRangeDataObject {
101    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
102        write!(
103            f,
104            "StandardPowerDataObject {{ max_voltage: {:?} V, minimum_voltage: {:?}, peak_current: {:?}, max_current: {:?} A, source_power_type: {:?}, is_detected: {} }}",
105            self.max_voltage()
106                .unwrap_or(ElectricPotential::new::<millivolt>(f32::NEG_INFINITY))
107                .get::<millivolt>(),
108            self.minimum_voltage(),
109            self.peak_current(),
110            self.max_current(),
111            self.source_power_type(),
112            self.is_detected()
113        )
114    }
115}