use pros_core::bail_on;
use pros_sys::{ext_adi_encoder_t, PROS_ERR};
use super::{AdiDevice, AdiDeviceType, AdiError, AdiPort};
use crate::Position;
#[derive(Debug, Eq, PartialEq)]
pub struct AdiEncoder {
raw: ext_adi_encoder_t,
port_top: AdiPort,
port_bottom: AdiPort,
}
impl AdiEncoder {
pub fn new(ports: (AdiPort, AdiPort), reverse: bool) -> Result<Self, AdiError> {
let port_top = ports.0;
let port_bottom = ports.1;
if port_top.internal_expander_index() != port_bottom.internal_expander_index() {
return Err(AdiError::ExpanderPortMismatch);
}
let raw = bail_on!(PROS_ERR, unsafe {
pros_sys::ext_adi_encoder_init(
port_top.internal_expander_index(),
port_top.index(),
port_bottom.index(),
reverse,
)
});
Ok(Self {
raw,
port_top,
port_bottom,
})
}
pub fn zero(&mut self) -> Result<(), AdiError> {
bail_on!(PROS_ERR, unsafe { pros_sys::adi_encoder_reset(self.raw) });
Ok(())
}
pub fn position(&self) -> Result<Position, AdiError> {
let degrees = bail_on!(PROS_ERR, unsafe { pros_sys::adi_encoder_get(self.raw) });
Ok(Position::from_degrees(degrees as f64))
}
}
impl AdiDevice for AdiEncoder {
type PortIndexOutput = (u8, u8);
fn port_index(&self) -> Self::PortIndexOutput {
(self.port_top.index(), self.port_bottom.index())
}
fn expander_port_index(&self) -> Option<u8> {
self.port_top.expander_index()
}
fn device_type(&self) -> AdiDeviceType {
AdiDeviceType::LegacyEncoder
}
}