pros_devices/adi/
encoder.rs1use 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#[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 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 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 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}