Skip to main content

ap33772s_rs/
errors.rs

1//! This Module contains all the public facing Errors that can occur when using this driver
2use crate::{hal, types::command_structures::PowerDataObject};
3
4/// Represents the different errors that can occur while interacting with the AP33772S device.
5#[derive(PartialEq, Clone, Debug)]
6#[non_exhaustive]
7pub enum Ap33772sError {
8    /// Represents an I2C Error this is specifcally a low level bus communication error
9    I2c(hal::ErrorKind),
10    /// Represents a conversion error, this can happen if the data being converted is in the wrong scale/format
11    ConversionFailed,
12    /// Represents a data malformed error, this can happen if the data being received is
13    /// not in the expected format. Usuaully will occur if a reserved bit is being used and
14    /// the enum cannot represent the state correctly. The u8 inside the error represents the value that was not expected
15    DataMalformed(u8),
16    /// This can occur when sending a Power Request and the arguments to the function are not correct, these are checked before transmitting
17    /// a PD Request Message
18    InvalidRequest(RequestError),
19    /// This can occur when there is another device on the bus using the same I2C Address. Specifically the u8 returns the value
20    /// thats supposed to be the command version of the device.
21    WrongCommandVersion(u8), // The value stored at the command version location
22    /// This can occur when the device has not booted correctly Or the device is already initialised. If this is the case it
23    /// could be solved by performing a `hard reset` followed by unplugging both the Stemma Connector if using the RotoPD and the USB C PD Device
24    InitialisationFailure,
25    /// This is a preemptive error that can occur when the user tries to negotiate with the device to use a Power Data Object that is not detected
26    /// Inside this error contains the Power Data Object that was not detected
27    PowerDataObjectNotDetected(PowerDataObject),
28}
29
30/// This Error is specifically an internal error that is used before communication with the device is taken.
31/// The eror enum catches incompatible configurations and notifies the user accordingly.
32#[derive(PartialEq, Clone, Debug)]
33#[non_exhaustive]
34#[cfg_attr(feature = "defmt", derive(defmt::Format))]
35pub enum RequestError {
36    MissingArgument,
37    VoltageOutOfRange,
38    CurrentOutOfRange,
39}
40impl<E: hal::Error> From<E> for Ap33772sError {
41    fn from(e: E) -> Self {
42        Ap33772sError::I2c(e.kind())
43    }
44}
45
46// Allows Error Bubbling when working with both std and no-std rust
47impl core::error::Error for Ap33772sError {}
48
49impl core::fmt::Display for Ap33772sError {
50    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
51        match self {
52            Ap33772sError::I2c(err) => write!(f, "I2C error: {err:?}"),
53            Ap33772sError::ConversionFailed => write!(f, "Conversion error"),
54            Ap33772sError::DataMalformed(_value) => write!(f, "Malformed Data error"),
55            Ap33772sError::WrongCommandVersion(value) => {
56                write!(
57                    f,
58                    "Device not found. Raw value at command version location: {value}"
59                )
60            }
61            Ap33772sError::InitialisationFailure => write!(f, "Failed to initialise correctly!"),
62            Ap33772sError::InvalidRequest(err) => write!(f, "Invalid request: {err:?}"),
63            Ap33772sError::PowerDataObjectNotDetected(power_data_object) => {
64                write!(
65                    f,
66                    "Power Data Object not detected on source: {power_data_object:?}"
67                )
68            }
69        }
70    }
71}
72
73#[cfg(feature = "defmt")]
74impl defmt::Format for Ap33772sError {
75    fn format(&self, f: defmt::Formatter) {
76        use crate::hal::Error;
77        use crate::hal::ErrorKind;
78        defmt::write!(
79            f,
80            "AP33772S Error: {}",
81            match self {
82                Ap33772sError::I2c(err) => {
83                    // Convert the ErrorKind into a string for defmt
84                    let kind_str = match err.kind() {
85                        ErrorKind::Bus => "Bus",
86                        ErrorKind::ArbitrationLoss => "ArbitrationLoss",
87                        ErrorKind::NoAcknowledge(_) => "NoAcknowledge",
88                        ErrorKind::Overrun => "Overrun",
89                        ErrorKind::Other => "Other",
90                        _ => "Unknown",
91                    };
92                    defmt::write!(f, "AP33772S Error: I2C error ({})", kind_str);
93                }
94
95                Ap33772sError::ConversionFailed => defmt::write!(f, "Conversion error"),
96                Ap33772sError::DataMalformed(value) =>
97                    defmt::write!(f, "Malformed Data error: {:?}", value),
98                Ap33772sError::WrongCommandVersion(value) => {
99                    defmt::write!(
100                        f,
101                        "Device not found. Raw value at command version location: {:?}",
102                        value
103                    )
104                }
105                Ap33772sError::InvalidRequest(err) =>
106                    defmt::write!(f, "Invalid request: {:?}", err),
107                Ap33772sError::InitialisationFailure =>
108                    defmt::write!(f, "Failed to initialise correctly!"),
109                Ap33772sError::PowerDataObjectNotDetected(power_data_object) => {
110                    defmt::write!(
111                        f,
112                        "Power Data Object not detected on source: {:?}",
113                        power_data_object
114                    )
115                }
116            }
117        );
118    }
119}