Skip to main content

ap33772s_rs/commands/data_objects/
source_power_range_data_object.rs

1use arbitrary_int::u2;
2use bitbybit::bitenum;
3
4use crate::commands::data_objects::extended_power_range_data_object::MinimumVoltage as ExtendedMinimumVoltage;
5use crate::commands::data_objects::standard_power_range_data_object::MinimumVoltage as StandardMinimumVoltage;
6use crate::errors::{Ap33772sError, RequestError};
7use crate::types::command_structures::{
8    ExtendedPowerRangeDataObject, StandardPowerRangeDataObject,
9};
10use crate::units::*;
11
12/// Represents A wrapper for the underlying Power Range Data Objects
13/// The AP33772s supports both Standard and Extended Power Range Data Objects
14/// Individual functions are supplied for generic functionality between the two types
15#[derive(Debug, PartialEq, Clone)]
16pub enum SourcePowerRangeDataObject {
17    Standard(StandardPowerRangeDataObject),
18    Extended(ExtendedPowerRangeDataObject),
19}
20
21impl SourcePowerRangeDataObject {
22    pub fn voltage_resolution(&self) -> u16 {
23        match self {
24            SourcePowerRangeDataObject::Standard(_) => {
25                StandardPowerRangeDataObject::VOLTAGE_RESOLUTION
26            }
27            SourcePowerRangeDataObject::Extended(_) => {
28                ExtendedPowerRangeDataObject::VOLTAGE_RESOLUTION
29            }
30        }
31    }
32    pub fn source_power_type(&self) -> PowerType {
33        match self {
34            SourcePowerRangeDataObject::Standard(data_object) => data_object.source_power_type(),
35            SourcePowerRangeDataObject::Extended(data_object) => data_object.source_power_type(),
36        }
37    }
38    pub fn is_detected(&self) -> bool {
39        match self {
40            SourcePowerRangeDataObject::Standard(data_object) => data_object.is_detected(),
41            SourcePowerRangeDataObject::Extended(data_object) => data_object.is_detected(),
42        }
43    }
44    pub fn get_max_voltage(&self) -> Result<ElectricPotential, Ap33772sError> {
45        match self {
46            SourcePowerRangeDataObject::Standard(data_object) => data_object.max_voltage(),
47            SourcePowerRangeDataObject::Extended(data_object) => data_object.max_voltage(),
48        }
49    }
50    pub fn get_max_current(&self) -> SourceMaximumCurrent {
51        match self {
52            SourcePowerRangeDataObject::Standard(data_object) => data_object.max_current(),
53            SourcePowerRangeDataObject::Extended(data_object) => data_object.max_current(),
54        }
55    }
56    pub fn get_min_voltage(&self) -> Result<ElectricPotential, Ap33772sError> {
57        match self {
58            SourcePowerRangeDataObject::Standard(data_object) => {
59                match data_object.minimum_voltage() {
60                    Some(voltage) => match voltage {
61                        StandardMinimumVoltage::_3_3 => {
62                            Ok(ElectricPotential::new::<millivolt>(3300.0))
63                        }
64                        StandardMinimumVoltage::_3_3To5 => {
65                            Ok(ElectricPotential::new::<millivolt>(5000.0)
66                                + ElectricPotential::new::<millivolt>(
67                                    StandardPowerRangeDataObject::VOLTAGE_RESOLUTION as f32,
68                                ))
69                        }
70                        _ => Err(Ap33772sError::ConversionFailed),
71                    },
72                    None => Err(Ap33772sError::InvalidRequest(RequestError::MissingArgument)),
73                }
74            }
75            SourcePowerRangeDataObject::Extended(data_object) => {
76                match data_object.minimum_voltage() {
77                    Some(voltage) => match voltage {
78                        ExtendedMinimumVoltage::Fifteen => {
79                            Ok(ElectricPotential::new::<millivolt>(15000.0))
80                        }
81                        ExtendedMinimumVoltage::FifteenLessThanVoltageMinimumLessThanTwenty => {
82                            Ok(ElectricPotential::new::<millivolt>(20000.0)
83                                + ElectricPotential::new::<millivolt>(
84                                    ExtendedPowerRangeDataObject::VOLTAGE_RESOLUTION as f32,
85                                ))
86                        }
87                        _ => Err(Ap33772sError::ConversionFailed),
88                    },
89                    None => Err(Ap33772sError::InvalidRequest(RequestError::MissingArgument)),
90                }
91            }
92        }
93    }
94}
95impl core::fmt::Display for SourcePowerRangeDataObject {
96    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
97        match self {
98            SourcePowerRangeDataObject::Standard(data_object) => {
99                write!(f, "Standard({data_object})")
100            }
101            SourcePowerRangeDataObject::Extended(data_object) => {
102                write!(f, "Extended({data_object})")
103            }
104        }
105    }
106}
107
108#[cfg(feature = "defmt")]
109impl defmt::Format for SourcePowerRangeDataObject {
110    fn format(&self, fmt: defmt::Formatter) {
111        match self {
112            SourcePowerRangeDataObject::Standard(data_object) => {
113                defmt::write!(fmt, "Standard({:?})", data_object)
114            }
115            SourcePowerRangeDataObject::Extended(data_object) => {
116                defmt::write!(fmt, "Extended({:?})", data_object)
117            }
118        }
119    }
120}
121
122/// The different operational modes that the USB C Specification Supports
123#[bitenum(u1, exhaustive = true)]
124#[derive(Debug, PartialEq)]
125#[cfg_attr(feature = "defmt", derive(defmt::Format))]
126pub enum PowerType {
127    /// In this mode, Programmable Power Supply (PPS) is not used and the voltage will at a fixed rate defined
128    /// by the Power Data Object
129    Fixed = 0,
130    /// In this mode, Programmable Power Supply (PPS) can be used and the voltage can be tweaked dependent on
131    /// the configuration of the Power Data Object
132    Adjustable = 1,
133}
134/// Represents the peak current conditions as defined in the USB C specification.
135/// The exact meaning of each condition is currently unclear; these names are placeholders
136/// based on available documentation.
137#[bitenum(u2, exhaustive = true)]
138#[derive(Debug, PartialEq)]
139#[cfg_attr(feature = "defmt", derive(defmt::Format))]
140pub enum PeakCurrent {
141    ConditionOne = 0,
142    ConditionTwo = 1,
143    ConditionThree = 2,
144    ConditionFour = 3,
145}
146
147impl From<u2> for PeakCurrent {
148    fn from(value: u2) -> Self {
149        match value.value() {
150            0 => PeakCurrent::ConditionOne,
151            1 => PeakCurrent::ConditionTwo,
152            2 => PeakCurrent::ConditionThree,
153            3 => PeakCurrent::ConditionFour,
154            _ => unreachable!("This will never happen due to rust type safety"),
155        }
156    }
157}
158
159/// Represents the different Source Maximum Current Levels the device supports.
160#[bitenum(u4, exhaustive = true)]
161#[derive(Debug, PartialEq)]
162#[cfg_attr(feature = "defmt", derive(defmt::Format))]
163pub enum SourceMaximumCurrent {
164    LessThan1_24 = 0,
165    _1_24To1_49 = 1,
166    _1_50To1_74 = 2,
167    _1_75To1_99 = 3,
168    _2_00To2_24 = 4,
169    _2_25To2_49 = 5,
170    _2_50To2_74 = 6,
171    _2_75To2_99 = 7,
172    _3_00To3_24 = 8,
173    _3_25To3_49 = 9,
174    _3_50To3_74 = 10,
175    _3_75To3_99 = 11,
176    _4_00To4_24 = 12,
177    _4_25To4_49 = 13,
178    _4_50To4_99 = 14,
179    Maximum = 15,
180}
181
182impl SourceMaximumCurrent {
183    /// Returns the maximum current that can be requested using this data object for each level of the [SourceMaximumCurrent]
184    pub fn max_range(&self) -> ElectricCurrent {
185        match self {
186            SourceMaximumCurrent::LessThan1_24 => ElectricCurrent::new::<milliampere>(1240.0),
187            SourceMaximumCurrent::_1_24To1_49 => ElectricCurrent::new::<milliampere>(1490.0),
188            SourceMaximumCurrent::_1_50To1_74 => ElectricCurrent::new::<milliampere>(1740.0),
189            SourceMaximumCurrent::_1_75To1_99 => ElectricCurrent::new::<milliampere>(1990.0),
190            SourceMaximumCurrent::_2_00To2_24 => ElectricCurrent::new::<milliampere>(2240.0),
191            SourceMaximumCurrent::_2_25To2_49 => ElectricCurrent::new::<milliampere>(2490.0),
192            SourceMaximumCurrent::_2_50To2_74 => ElectricCurrent::new::<milliampere>(2740.0),
193            SourceMaximumCurrent::_2_75To2_99 => ElectricCurrent::new::<milliampere>(2990.0),
194            SourceMaximumCurrent::_3_00To3_24 => ElectricCurrent::new::<milliampere>(3240.0),
195            SourceMaximumCurrent::_3_25To3_49 => ElectricCurrent::new::<milliampere>(3490.0),
196            SourceMaximumCurrent::_3_50To3_74 => ElectricCurrent::new::<milliampere>(3740.0),
197            SourceMaximumCurrent::_3_75To3_99 => ElectricCurrent::new::<milliampere>(3990.0),
198            SourceMaximumCurrent::_4_00To4_24 => ElectricCurrent::new::<milliampere>(4240.0),
199            SourceMaximumCurrent::_4_25To4_49 => ElectricCurrent::new::<milliampere>(4490.0),
200            SourceMaximumCurrent::_4_50To4_99 => ElectricCurrent::new::<milliampere>(4990.0),
201            SourceMaximumCurrent::Maximum => ElectricCurrent::new::<milliampere>(f32::INFINITY),
202        }
203    }
204    /// Returns the minimum current that can be requested using this data object for each level of the [SourceMaximumCurrent]
205    pub fn min_range(&self) -> ElectricCurrent {
206        match self {
207            SourceMaximumCurrent::LessThan1_24 => ElectricCurrent::new::<milliampere>(0.0),
208            SourceMaximumCurrent::_1_24To1_49 => ElectricCurrent::new::<milliampere>(1240.0),
209            SourceMaximumCurrent::_1_50To1_74 => ElectricCurrent::new::<milliampere>(1500.0),
210            SourceMaximumCurrent::_1_75To1_99 => ElectricCurrent::new::<milliampere>(1750.0),
211            SourceMaximumCurrent::_2_00To2_24 => ElectricCurrent::new::<milliampere>(2000.0),
212            SourceMaximumCurrent::_2_25To2_49 => ElectricCurrent::new::<milliampere>(2250.0),
213            SourceMaximumCurrent::_2_50To2_74 => ElectricCurrent::new::<milliampere>(2500.0),
214            SourceMaximumCurrent::_2_75To2_99 => ElectricCurrent::new::<milliampere>(2750.0),
215            SourceMaximumCurrent::_3_00To3_24 => ElectricCurrent::new::<milliampere>(3000.0),
216            SourceMaximumCurrent::_3_25To3_49 => ElectricCurrent::new::<milliampere>(3250.0),
217            SourceMaximumCurrent::_3_50To3_74 => ElectricCurrent::new::<milliampere>(3500.0),
218            SourceMaximumCurrent::_3_75To3_99 => ElectricCurrent::new::<milliampere>(3750.0),
219            SourceMaximumCurrent::_4_00To4_24 => ElectricCurrent::new::<milliampere>(4000.0),
220            SourceMaximumCurrent::_4_25To4_49 => ElectricCurrent::new::<milliampere>(4250.0),
221            SourceMaximumCurrent::_4_50To4_99 => ElectricCurrent::new::<milliampere>(4500.0),
222            SourceMaximumCurrent::Maximum => ElectricCurrent::new::<milliampere>(4990.0),
223        }
224    }
225}