vex_rt/adi/
digital_out.rs

1use crate::{
2    bindings,
3    error::{get_errno, Error},
4};
5
6/// A struct which represents a V5 ADI port configured as an ADI digital output.
7pub struct AdiDigitalOutput {
8    port: u8,
9    expander_port: u8,
10}
11
12impl AdiDigitalOutput {
13    /// Initializes an ADI digital output on an ADI port.
14    ///
15    /// # Safety
16    ///
17    /// This function is unsafe because it allows the user to create multiple
18    /// mutable references to the same ADI digital output. You likely want to
19    /// implement [`Robot::new()`](crate::robot::Robot::new()) instead.
20    pub unsafe fn new(port: u8, expander_port: u8) -> Result<Self, AdiDigitalOutputError> {
21        match bindings::ext_adi_port_set_config(
22            expander_port,
23            port,
24            bindings::adi_port_config_e_E_ADI_DIGITAL_OUT,
25        ) {
26            bindings::PROS_ERR_ => Err(AdiDigitalOutputError::from_errno()),
27            _ => Ok(Self {
28                port,
29                expander_port,
30            }),
31        }
32    }
33
34    /// Sets the digital value (true or false) of the output.
35    pub fn write(&mut self, value: bool) -> Result<(), AdiDigitalOutputError> {
36        match unsafe { bindings::ext_adi_digital_write(self.expander_port, self.port, value) } {
37            bindings::PROS_ERR_ => Err(AdiDigitalOutputError::from_errno()),
38            _ => Ok(()),
39        }
40    }
41}
42
43/// Represents possible errors for ADI digital output operations.
44#[derive(Debug)]
45pub enum AdiDigitalOutputError {
46    /// Port is out of range (1-8).
47    PortsOutOfRange,
48    /// Port cannot be configured as an ADI digital output.
49    PortsNotDigitalOutput,
50    /// Unknown error.
51    Unknown(i32),
52}
53
54impl AdiDigitalOutputError {
55    fn from_errno() -> Self {
56        match get_errno() {
57            libc::ENXIO => Self::PortsOutOfRange,
58            libc::EADDRINUSE => Self::PortsNotDigitalOutput,
59            x => Self::Unknown(x),
60        }
61    }
62}
63
64impl From<AdiDigitalOutputError> for Error {
65    fn from(err: AdiDigitalOutputError) -> Self {
66        match err {
67            AdiDigitalOutputError::PortsOutOfRange => Error::Custom("port is out of range".into()),
68            AdiDigitalOutputError::PortsNotDigitalOutput => {
69                Error::Custom("port is not an adi digital output".into())
70            }
71            AdiDigitalOutputError::Unknown(n) => Error::System(n),
72        }
73    }
74}