1use core::marker::PhantomData;
2use embedded_hal::digital::{self as hal_digital};
3
4pub struct Pin<'a, MODE, MUTEX> {
9 pin_mask: u32,
10 port_driver: &'a MUTEX,
11 _m: PhantomData<MODE>,
12}
13
14impl<'a, MODE, MUTEX, PD> Pin<'a, MODE, MUTEX>
15where
16 PD: crate::PortDriver,
17 MUTEX: crate::PortMutex<Port = PD>,
18{
19 pub(crate) fn new(pin_number: u8, port_driver: &'a MUTEX) -> Self {
20 assert!(pin_number < 32);
21 Self {
22 pin_mask: 1 << pin_number,
23 port_driver,
24 _m: PhantomData,
25 }
26 }
27
28 pub fn pin_mask(&self) -> u32 {
29 self.pin_mask
30 }
31
32 pub(crate) fn port_driver(&self) -> &MUTEX {
33 self.port_driver
34 }
35
36 pub fn access_port_driver<F, R>(&self, f: F) -> R
37 where
38 F: FnOnce(&mut PD) -> R,
39 {
40 self.port_driver.lock(|pd| f(pd))
41 }
42}
43
44#[derive(Debug)]
46pub struct PinError<PDE> {
47 driver_error: PDE,
48}
49
50impl<PDE> PinError<PDE> {
51 pub fn driver_error(&self) -> &PDE {
53 &self.driver_error
54 }
55}
56
57impl<PDE> hal_digital::Error for PinError<PDE>
58where
59 PDE: core::fmt::Debug,
60{
61 fn kind(&self) -> hal_digital::ErrorKind {
62 hal_digital::ErrorKind::Other
63 }
64}
65
66impl<PDE> From<PDE> for PinError<PDE> {
67 fn from(value: PDE) -> Self {
68 Self {
69 driver_error: value,
70 }
71 }
72}
73
74impl<'a, MODE, MUTEX, PD> hal_digital::ErrorType for Pin<'a, MODE, MUTEX>
75where
76 PD: crate::PortDriver,
77 PD::Error: core::fmt::Debug,
78 MUTEX: crate::PortMutex<Port = PD>,
79{
80 type Error = PinError<PD::Error>;
81}
82
83impl<'a, MODE, MUTEX, PD> Pin<'a, MODE, MUTEX>
84where
85 PD: crate::PortDriver + crate::PortDriverTotemPole,
86 MUTEX: crate::PortMutex<Port = PD>,
87{
88 pub fn into_input(self) -> Result<Pin<'a, crate::mode::Input, MUTEX>, PinError<PD::Error>> {
92 self.port_driver
93 .lock(|drv| drv.set_direction(self.pin_mask, crate::Direction::Input, false))?;
94 Ok(Pin {
95 pin_mask: self.pin_mask,
96 port_driver: self.port_driver,
97 _m: PhantomData,
98 })
99 }
100
101 pub fn into_output(self) -> Result<Pin<'a, crate::mode::Output, MUTEX>, PinError<PD::Error>> {
106 self.port_driver
107 .lock(|drv| drv.set_direction(self.pin_mask, crate::Direction::Output, false))?;
108 Ok(Pin {
109 pin_mask: self.pin_mask,
110 port_driver: self.port_driver,
111 _m: PhantomData,
112 })
113 }
114
115 pub fn into_output_high(
120 self,
121 ) -> Result<Pin<'a, crate::mode::Output, MUTEX>, PinError<PD::Error>> {
122 self.port_driver
123 .lock(|drv| drv.set_direction(self.pin_mask, crate::Direction::Output, true))?;
124 Ok(Pin {
125 pin_mask: self.pin_mask,
126 port_driver: self.port_driver,
127 _m: PhantomData,
128 })
129 }
130}
131
132impl<'a, MODE, MUTEX, PD> Pin<'a, MODE, MUTEX>
133where
134 PD: crate::PortDriver + crate::PortDriverPolarity,
135 MUTEX: crate::PortMutex<Port = PD>,
136{
137 pub fn into_inverted(self) -> Result<Self, PinError<PD::Error>> {
139 self.port_driver
140 .lock(|drv| drv.set_polarity(self.pin_mask, true))?;
141 Ok(self)
142 }
143
144 pub fn set_inverted(&mut self, inverted: bool) -> Result<(), PinError<PD::Error>> {
146 self.port_driver
147 .lock(|drv| drv.set_polarity(self.pin_mask, inverted))?;
148 Ok(())
149 }
150}
151
152impl<'a, MODE: crate::mode::HasInput, MUTEX, PD> Pin<'a, MODE, MUTEX>
153where
154 PD: crate::PortDriver,
155 MUTEX: crate::PortMutex<Port = PD>,
156{
157 pub fn is_high(&self) -> Result<bool, PinError<PD::Error>> {
159 self.port_driver
160 .lock(|drv| Ok(drv.get(self.pin_mask, 0)? == self.pin_mask))
161 }
162
163 pub fn is_low(&self) -> Result<bool, PinError<PD::Error>> {
165 self.port_driver
166 .lock(|drv| Ok(drv.get(0, self.pin_mask)? == self.pin_mask))
167 }
168}
169
170impl<'a, MODE: crate::mode::HasInput, MUTEX, PD> Pin<'a, MODE, MUTEX>
171where
172 PD: crate::PortDriver + crate::PortDriverPullUp,
173 MUTEX: crate::PortMutex<Port = PD>,
174{
175 pub fn enable_pull_up(&mut self, enable: bool) -> Result<(), PinError<PD::Error>> {
179 self.port_driver
180 .lock(|drv| drv.set_pull_up(self.pin_mask, enable))?;
181 Ok(())
182 }
183}
184
185impl<'a, MODE: crate::mode::HasInput, MUTEX, PD> Pin<'a, MODE, MUTEX>
186where
187 PD: crate::PortDriver + crate::PortDriverPullDown,
188 MUTEX: crate::PortMutex<Port = PD>,
189{
190 pub fn enable_pull_down(&mut self, enable: bool) -> Result<(), PinError<PD::Error>> {
194 self.port_driver
195 .lock(|drv| drv.set_pull_down(self.pin_mask, enable))?;
196 Ok(())
197 }
198}
199
200impl<'a, MODE: crate::mode::HasInput, MUTEX, PD> hal_digital::InputPin for Pin<'a, MODE, MUTEX>
201where
202 PD: crate::PortDriver,
203 <PD as crate::PortDriver>::Error: core::fmt::Debug,
204 MUTEX: crate::PortMutex<Port = PD>,
205{
206 fn is_high(&mut self) -> Result<bool, Self::Error> {
207 Pin::is_high(self)
208 }
209
210 fn is_low(&mut self) -> Result<bool, Self::Error> {
211 Pin::is_low(self)
212 }
213}
214
215impl<'a, MODE: crate::mode::HasOutput, MUTEX, PD> Pin<'a, MODE, MUTEX>
216where
217 PD: crate::PortDriver,
218 MUTEX: crate::PortMutex<Port = PD>,
219{
220 pub fn set_high(&mut self) -> Result<(), PinError<PD::Error>> {
224 self.port_driver.lock(|drv| drv.set(self.pin_mask, 0))?;
225 Ok(())
226 }
227
228 pub fn set_low(&mut self) -> Result<(), PinError<PD::Error>> {
232 self.port_driver.lock(|drv| drv.set(0, self.pin_mask))?;
233 Ok(())
234 }
235
236 pub fn is_set_high(&self) -> Result<bool, PinError<PD::Error>> {
240 self.port_driver
241 .lock(|drv| Ok(drv.is_set(self.pin_mask, 0)? == self.pin_mask))
242 }
243
244 pub fn is_set_low(&self) -> Result<bool, PinError<PD::Error>> {
248 self.port_driver
249 .lock(|drv| Ok(drv.is_set(0, self.pin_mask)? == self.pin_mask))
250 }
251
252 pub fn toggle(&mut self) -> Result<(), PinError<PD::Error>> {
254 self.port_driver.lock(|drv| drv.toggle(self.pin_mask))?;
255 Ok(())
256 }
257}
258
259impl<'a, MODE: crate::mode::HasOutput, MUTEX, PD> hal_digital::OutputPin for Pin<'a, MODE, MUTEX>
260where
261 PD: crate::PortDriver,
262 <PD as crate::PortDriver>::Error: core::fmt::Debug,
263 MUTEX: crate::PortMutex<Port = PD>,
264{
265 fn set_low(&mut self) -> Result<(), Self::Error> {
266 Pin::set_low(self)
267 }
268
269 fn set_high(&mut self) -> Result<(), Self::Error> {
270 Pin::set_high(self)
271 }
272}
273
274impl<'a, MODE: crate::mode::HasOutput, MUTEX, PD> hal_digital::StatefulOutputPin
275 for Pin<'a, MODE, MUTEX>
276where
277 PD: crate::PortDriver,
278 <PD as crate::PortDriver>::Error: core::fmt::Debug,
279 MUTEX: crate::PortMutex<Port = PD>,
280{
281 fn is_set_high(&mut self) -> Result<bool, Self::Error> {
282 Pin::is_set_high(self)
283 }
284
285 fn is_set_low(&mut self) -> Result<bool, Self::Error> {
286 Pin::is_set_low(self)
287 }
288
289 fn toggle(&mut self) -> Result<(), Self::Error> {
290 Pin::toggle(self)
291 }
292}