pros_devices/adi/
digital.rs1use pros_core::bail_on;
4use pros_sys::PROS_ERR;
5
6use super::{AdiDevice, AdiDeviceType, AdiError, AdiPort};
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub enum LogicLevel {
15 High,
19
20 Low,
24}
25
26impl LogicLevel {
27 pub const fn is_high(&self) -> bool {
29 match self {
30 Self::High => true,
31 Self::Low => false,
32 }
33 }
34
35 pub const fn is_low(&self) -> bool {
37 match self {
38 Self::High => false,
39 Self::Low => true,
40 }
41 }
42}
43
44impl core::ops::Not for LogicLevel {
45 type Output = Self;
46
47 fn not(self) -> Self::Output {
48 match self {
49 Self::Low => Self::High,
50 Self::High => Self::Low,
51 }
52 }
53}
54
55#[derive(Debug, Eq, PartialEq)]
57pub struct AdiDigitalIn {
59 port: AdiPort,
60}
61
62impl AdiDigitalIn {
63 pub fn new(port: AdiPort) -> Result<Self, AdiError> {
65 bail_on!(PROS_ERR, unsafe {
66 pros_sys::ext_adi_port_set_config(
67 port.internal_expander_index(),
68 port.index(),
69 pros_sys::E_ADI_DIGITAL_IN,
70 )
71 });
72
73 Ok(Self { port })
74 }
75
76 pub fn level(&self) -> Result<LogicLevel, AdiError> {
78 let value = bail_on!(PROS_ERR, unsafe {
79 pros_sys::ext_adi_digital_read(self.port.internal_expander_index(), self.port.index())
80 }) != 0;
81
82 Ok(match value {
83 true => LogicLevel::High,
84 false => LogicLevel::Low,
85 })
86 }
87
88 pub fn is_high(&self) -> Result<bool, AdiError> {
90 Ok(self.level()?.is_high())
91 }
92
93 pub fn is_low(&self) -> Result<bool, AdiError> {
95 Ok(self.level()?.is_high())
96 }
97}
98
99impl AdiDevice for AdiDigitalIn {
100 type PortIndexOutput = u8;
101
102 fn port_index(&self) -> Self::PortIndexOutput {
103 self.port.index()
104 }
105
106 fn expander_port_index(&self) -> Option<u8> {
107 self.port.expander_index()
108 }
109
110 fn device_type(&self) -> AdiDeviceType {
111 AdiDeviceType::DigitalIn
112 }
113}
114
115#[derive(Debug, Eq, PartialEq)]
117pub struct AdiDigitalOut {
118 port: AdiPort,
119}
120
121impl AdiDigitalOut {
122 pub fn new(port: AdiPort) -> Result<Self, AdiError> {
124 bail_on!(PROS_ERR, unsafe {
125 pros_sys::ext_adi_port_set_config(
126 port.internal_expander_index(),
127 port.index(),
128 pros_sys::E_ADI_DIGITAL_OUT,
129 )
130 });
131
132 Ok(Self { port })
133 }
134
135 pub fn set_level(&mut self, level: LogicLevel) -> Result<(), AdiError> {
137 bail_on!(PROS_ERR, unsafe {
138 pros_sys::ext_adi_digital_write(
139 self.port.internal_expander_index(),
140 self.port.index(),
141 level.is_high(),
142 )
143 });
144
145 Ok(())
146 }
147
148 pub fn set_high(&mut self) -> Result<(), AdiError> {
151 self.set_level(LogicLevel::High)
152 }
153
154 pub fn set_low(&mut self) -> Result<(), AdiError> {
157 self.set_level(LogicLevel::Low)
158 }
159}
160
161impl AdiDevice for AdiDigitalOut {
162 type PortIndexOutput = u8;
163
164 fn port_index(&self) -> Self::PortIndexOutput {
165 self.port.index()
166 }
167
168 fn expander_port_index(&self) -> Option<u8> {
169 self.port.expander_index()
170 }
171
172 fn device_type(&self) -> AdiDeviceType {
173 AdiDeviceType::DigitalOut
174 }
175}