pros_devices/adi/
encoder.rs

1//! ADI encoder device.
2
3use pros_core::bail_on;
4use pros_sys::{ext_adi_encoder_t, PROS_ERR};
5
6use super::{AdiDevice, AdiDeviceType, AdiError, AdiPort};
7use crate::Position;
8
9/// ADI encoder device.
10/// Requires two adi ports.
11#[derive(Debug, Eq, PartialEq)]
12pub struct AdiEncoder {
13    raw: ext_adi_encoder_t,
14    port_top: AdiPort,
15    port_bottom: AdiPort,
16}
17
18impl AdiEncoder {
19    /// Create a new encoder from a top and bottom [`AdiPort`].
20    ///
21    /// If using an [`AdiExpander`], both ports must be on the same expander module.
22    pub fn new(ports: (AdiPort, AdiPort), reverse: bool) -> Result<Self, AdiError> {
23        let port_top = ports.0;
24        let port_bottom = ports.1;
25
26        if port_top.internal_expander_index() != port_bottom.internal_expander_index() {
27            return Err(AdiError::ExpanderPortMismatch);
28        }
29
30        let raw = bail_on!(PROS_ERR, unsafe {
31            pros_sys::ext_adi_encoder_init(
32                port_top.internal_expander_index(),
33                port_top.index(),
34                port_bottom.index(),
35                reverse,
36            )
37        });
38
39        Ok(Self {
40            raw,
41            port_top,
42            port_bottom,
43        })
44    }
45
46    /// Resets the encoder to zero.
47    pub fn zero(&mut self) -> Result<(), AdiError> {
48        bail_on!(PROS_ERR, unsafe { pros_sys::adi_encoder_reset(self.raw) });
49        Ok(())
50    }
51
52    /// Gets the number of ticks recorded by the encoder.
53    pub fn position(&self) -> Result<Position, AdiError> {
54        let degrees = bail_on!(PROS_ERR, unsafe { pros_sys::adi_encoder_get(self.raw) });
55
56        Ok(Position::from_degrees(degrees as f64))
57    }
58}
59
60impl AdiDevice for AdiEncoder {
61    type PortIndexOutput = (u8, u8);
62
63    fn port_index(&self) -> Self::PortIndexOutput {
64        (self.port_top.index(), self.port_bottom.index())
65    }
66
67    fn expander_port_index(&self) -> Option<u8> {
68        self.port_top.expander_index()
69    }
70
71    fn device_type(&self) -> AdiDeviceType {
72        AdiDeviceType::LegacyEncoder
73    }
74}