Skip to main content

ap33772s_rs/commands/data_objects/
extended_power_range_data_object.rs

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