vex_rt/adi/
digital_in.rs

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