use pros_core::{bail_on, error::PortError, map_errno};
use pros_sys::{adi_port_config_e_t, E_ADI_ERR, PROS_ERR};
use snafu::Snafu;
pub mod analog;
pub mod digital;
pub mod pwm;
pub mod encoder;
pub mod gyro;
pub mod linetracker;
pub mod motor;
pub mod potentiometer;
pub mod solenoid;
pub mod switch;
pub mod ultrasonic;
pub use analog::AdiAnalogIn;
pub use digital::{AdiDigitalIn, AdiDigitalOut};
pub use encoder::AdiEncoder;
pub use gyro::AdiGyro;
pub use linetracker::AdiLineTracker;
pub use motor::AdiMotor;
pub use potentiometer::AdiPotentiometer;
pub use solenoid::AdiSolenoid;
pub use ultrasonic::AdiUltrasonic;
#[derive(Debug, Eq, PartialEq)]
pub struct AdiPort {
index: u8,
expander_index: Option<u8>,
}
impl AdiPort {
pub const unsafe fn new(index: u8, expander_index: Option<u8>) -> Self {
Self {
index,
expander_index,
}
}
pub const fn index(&self) -> u8 {
self.index
}
pub const fn expander_index(&self) -> Option<u8> {
self.expander_index
}
pub(crate) fn internal_expander_index(&self) -> u8 {
self.expander_index
.unwrap_or(pros_sys::adi::INTERNAL_ADI_PORT as u8)
}
pub fn configured_type(&self) -> Result<AdiDeviceType, AdiError> {
bail_on!(PROS_ERR, unsafe {
pros_sys::ext_adi::ext_adi_port_get_config(self.internal_expander_index(), self.index())
})
.try_into()
}
}
pub trait AdiDevice {
type PortIndexOutput;
fn port_index(&self) -> Self::PortIndexOutput;
fn expander_port_index(&self) -> Option<u8>;
fn device_type(&self) -> AdiDeviceType;
}
#[repr(i32)]
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum AdiDeviceType {
AnalogIn = pros_sys::adi::E_ADI_ANALOG_IN,
PwmOut = pros_sys::adi::E_ADI_ANALOG_OUT,
DigitalIn = pros_sys::adi::E_ADI_DIGITAL_IN,
DigitalOut = pros_sys::adi::E_ADI_DIGITAL_OUT,
LegacyGyro = pros_sys::adi::E_ADI_LEGACY_GYRO,
LegacyServo = pros_sys::adi::E_ADI_LEGACY_SERVO,
LegacyPwm = pros_sys::adi::E_ADI_LEGACY_PWM,
LegacyEncoder = pros_sys::E_ADI_LEGACY_ENCODER,
LegacyUltrasonic = pros_sys::E_ADI_LEGACY_ULTRASONIC,
}
impl TryFrom<adi_port_config_e_t> for AdiDeviceType {
type Error = AdiError;
fn try_from(value: adi_port_config_e_t) -> Result<Self, Self::Error> {
bail_on!(E_ADI_ERR, value);
match value {
pros_sys::E_ADI_ANALOG_IN => Ok(AdiDeviceType::AnalogIn),
pros_sys::E_ADI_ANALOG_OUT => Ok(AdiDeviceType::PwmOut),
pros_sys::E_ADI_DIGITAL_IN => Ok(AdiDeviceType::DigitalIn),
pros_sys::E_ADI_DIGITAL_OUT => Ok(AdiDeviceType::DigitalOut),
pros_sys::E_ADI_LEGACY_GYRO => Ok(AdiDeviceType::LegacyGyro),
pros_sys::E_ADI_LEGACY_SERVO => Ok(AdiDeviceType::LegacyServo),
pros_sys::E_ADI_LEGACY_PWM => Ok(AdiDeviceType::LegacyPwm),
pros_sys::E_ADI_LEGACY_ENCODER => Ok(AdiDeviceType::LegacyEncoder),
pros_sys::E_ADI_LEGACY_ULTRASONIC => Ok(AdiDeviceType::LegacyUltrasonic),
_ => Err(AdiError::UnknownDeviceType),
}
}
}
impl From<AdiDeviceType> for adi_port_config_e_t {
fn from(value: AdiDeviceType) -> Self {
value as _
}
}
#[derive(Debug, Snafu)]
pub enum AdiError {
AlreadyInUse,
UnknownDeviceType,
PortNotConfigured,
ExpanderPortMismatch,
InvalidValue,
#[snafu(display("{source}"), context(false))]
Port {
source: PortError,
},
}
map_errno! {
AdiError {
EACCES => Self::AlreadyInUse,
EADDRINUSE => Self::PortNotConfigured,
EINVAL => Self::InvalidValue,
}
inherit PortError;
}