1use core::marker::PhantomData;
4
5pub trait GpioExt {
7 type Parts;
9
10 fn split(self) -> Self::Parts;
12}
13
14pub struct Input<MODE> {
16 _mode: PhantomData<MODE>,
17}
18
19pub struct Analog;
21pub struct Floating;
23pub struct PullDown;
25pub struct PullUp;
27
28pub struct Output<MODE> {
30 _mode: PhantomData<MODE>,
31}
32
33pub struct PushPull;
35pub struct OpenDrain;
37
38macro_rules! port {
39 ($PORTX:ident, $portx:ident, [
40 $($PXi:ident: ($pxi:ident, $i:expr, $MODE:ty $(, $has_ansel:expr)?),)+
41 ]) => {
42 pub mod $portx {
44 use core::marker::PhantomData;
45 use core::convert::Infallible;
46
47 use embedded_hal_0_2::digital::v2 as eh02;
48 use embedded_hal::digital as eh;
49 use crate::pac::$PORTX;
50
51 #[allow(unused_imports)]
52 use super::Analog;
53 use super::{
54 Floating, GpioExt, Input, OpenDrain, Output,
55 PullDown, PullUp, PushPull,
56 };
57
58 pub struct Parts {
60 $(
61 pub $pxi: $PXi<$MODE>,
63 )+
64 }
65
66 impl GpioExt for $PORTX {
67 type Parts = Parts;
68
69 fn split(self) -> Parts {
70 Parts {
71 $(
72 $pxi: $PXi { _mode: PhantomData },
73 )+
74 }
75 }
76 }
77
78 $(
79 pub struct $PXi<MODE> {
81 _mode: PhantomData<MODE>,
82 }
83
84 impl<MODE> $PXi<MODE> {
85 pub fn into_floating_input(
87 self,
88 ) -> $PXi<Input<Floating>> {
89 unsafe {
90 $(
91 _ = $has_ansel; (*$PORTX::ptr()).anselclr.write(|w| w.bits(1 << $i));
93 )?
94 (*$PORTX::ptr()).trisset.write(|w| w.bits(1 << $i));
95 (*$PORTX::ptr()).cnpuclr.write(|w| w.bits(1 << $i));
96 (*$PORTX::ptr()).cnpdclr.write(|w| w.bits(1 << $i));
97 }
98 $PXi { _mode: PhantomData }
99 }
100
101 pub fn into_pull_down_input(
103 self,
104 ) -> $PXi<Input<PullDown>> {
105 unsafe {
106 $(
107 _ = $has_ansel; (*$PORTX::ptr()).anselclr.write(|w| w.bits(1 << $i));
109 )?
110 (*$PORTX::ptr()).trisset.write(|w| w.bits(1 << $i));
111 (*$PORTX::ptr()).cnpuclr.write(|w| w.bits(1 << $i));
112 (*$PORTX::ptr()).cnpdset.write(|w| w.bits(1 << $i));
113 }
114 $PXi { _mode: PhantomData }
115 }
116
117 pub fn into_pull_up_input(
119 self,
120 ) -> $PXi<Input<PullUp>> {
121 unsafe {
122 $(
123 _ = $has_ansel; (*$PORTX::ptr()).anselclr.write(|w| w.bits(1 << $i));
125 )?
126 (*$PORTX::ptr()).trisset.write(|w| w.bits(1 << $i));
127 (*$PORTX::ptr()).cnpuset.write(|w| w.bits(1 << $i));
128 (*$PORTX::ptr()).cnpdclr.write(|w| w.bits(1 << $i));
129 }
130 $PXi { _mode: PhantomData }
131 }
132
133 pub fn into_open_drain_output(
135 self,
136 ) -> $PXi<Output<OpenDrain>> {
137 unsafe {
138 $(
139 _ = $has_ansel; (*$PORTX::ptr()).anselclr.write(|w| w.bits(1 << $i));
141 )?
142 (*$PORTX::ptr()).trisclr.write(|w| w.bits(1 << $i));
143 (*$PORTX::ptr()).odcset.write(|w| w.bits(1 << $i));
144 (*$PORTX::ptr()).cnpuclr.write(|w| w.bits(1 << $i));
145 (*$PORTX::ptr()).cnpdclr.write(|w| w.bits(1 << $i));
146 }
147 $PXi { _mode: PhantomData }
148 }
149
150 pub fn into_push_pull_output(
152 self,
153 ) -> $PXi<Output<PushPull>> {
154 unsafe {
155 $(
156 _ = $has_ansel; (*$PORTX::ptr()).anselclr.write(|w| w.bits(1 << $i));
158 )?
159 (*$PORTX::ptr()).trisclr.write(|w| w.bits(1 << $i));
160 (*$PORTX::ptr()).odcclr.write(|w| w.bits(1 << $i));
161 (*$PORTX::ptr()).cnpuclr.write(|w| w.bits(1 << $i));
162 (*$PORTX::ptr()).cnpdclr.write(|w| w.bits(1 << $i));
163 }
164 $PXi { _mode: PhantomData }
165 }
166
167 $(
168 pub fn into_analog_input(
170 self,
171 ) -> $PXi<Input<Analog>> {
172 _ = $has_ansel; unsafe {
174 (*$PORTX::ptr()).anselset.write(|w| w.bits(1 << $i));
175 (*$PORTX::ptr()).trisset.write(|w| w.bits(1 << $i));
176 (*$PORTX::ptr()).cnpuclr.write(|w| w.bits(1 << $i));
177 (*$PORTX::ptr()).cnpdclr.write(|w| w.bits(1 << $i));
178 }
179 $PXi { _mode: PhantomData }
180 }
181 )?
182 }
183
184 impl $PXi<Output<OpenDrain>> {
185 pub fn internal_pull_up(&mut self, on: bool) {
187 unsafe {
188 if on {
189 (*$PORTX::ptr()).cnpuset.write(|w| w.bits(1 << $i));
190 } else {
191 (*$PORTX::ptr()).cnpuclr.write(|w| w.bits(1 << $i));
192 }
193 }
194 }
195 }
196
197 impl<MODE> eh02::OutputPin for $PXi<Output<MODE>> {
198
199 type Error = ();
200
201 fn set_high(&mut self) -> Result<(), Self::Error> {
202 unsafe { (*$PORTX::ptr()).latset.write(|w| w.bits(1 << $i)) }
204 Ok(())
205 }
206
207 fn set_low(&mut self) -> Result<(), Self::Error>{
208 unsafe { (*$PORTX::ptr()).latclr.write(|w| w.bits(1 << $i)) }
210 Ok(())
211 }
212 }
213
214 impl<MODE> eh02::StatefulOutputPin for $PXi<Output<MODE>> {
215
216 fn is_set_high(&self) -> Result<bool, Self::Error> {
217 Ok(unsafe { (*$PORTX::ptr()).lat.read().bits() & (1 << $i) != 0 })
218 }
219
220 fn is_set_low(&self) -> Result<bool, Self::Error> {
221 Ok(unsafe { (*$PORTX::ptr()).lat.read().bits() & (1 << $i) == 0 })
222 }
223 }
224
225 impl<MODE> eh02::ToggleableOutputPin for $PXi<Output<MODE>> {
226
227 type Error = ();
228
229 fn toggle(&mut self) -> Result<(), Self::Error> {
230 unsafe { (*$PORTX::ptr()).latinv.write(|w| w.bits(1 << $i)) };
231 Ok(())
232 }
233 }
234
235 impl<MODE> eh02::InputPin for $PXi<Input<MODE>> {
236
237 type Error = ();
238
239 fn is_high(&self) -> Result<bool, Self::Error> {
240 Ok(unsafe { (*$PORTX::ptr()).port.read().bits() & (1 << $i) != 0 })
241 }
242
243 fn is_low(&self) -> Result<bool, Self::Error> {
244 Ok(unsafe { (*$PORTX::ptr()).port.read().bits() & (1 << $i) == 0 })
245 }
246 }
247
248 impl eh02::InputPin for $PXi<Output<OpenDrain>> {
249
250 type Error = ();
251
252 fn is_high(&self) -> Result<bool, Self::Error> {
253 Ok(unsafe { (*$PORTX::ptr()).port.read().bits() & (1 << $i) != 0 })
254 }
255
256 fn is_low(&self) -> Result<bool, Self::Error> {
257 Ok(unsafe { (*$PORTX::ptr()).port.read().bits() & (1 << $i) == 0 })
258 }
259 }
260
261 impl<MODE> eh::ErrorType for $PXi<MODE> {
262 type Error = Infallible;
263 }
264
265 impl<MODE> eh::InputPin for $PXi<Input<MODE>> {
266
267 fn is_high(&mut self) -> Result<bool, Self::Error> {
268 Ok(unsafe { (*$PORTX::ptr()).port.read().bits() & (1 << $i) != 0 })
269 }
270
271 fn is_low(&mut self) -> Result<bool, Self::Error> {
272 Ok(unsafe { (*$PORTX::ptr()).port.read().bits() & (1 << $i) == 0 })
273 }
274 }
275
276 impl eh::InputPin for $PXi<Output<OpenDrain>> {
277
278 fn is_high(&mut self) -> Result<bool, Self::Error> {
279 Ok(unsafe { (*$PORTX::ptr()).port.read().bits() & (1 << $i) != 0 })
280 }
281
282 fn is_low(&mut self) -> Result<bool, Self::Error> {
283 Ok(unsafe { (*$PORTX::ptr()).port.read().bits() & (1 << $i) == 0 })
284 }
285 }
286
287 impl<MODE> eh::OutputPin for $PXi<Output<MODE>> {
288
289 fn set_low(&mut self) -> Result<(), Self::Error> {
290 unsafe { (*$PORTX::ptr()).latclr.write(|w| w.bits(1 << $i)) }
291 Ok(())
292 }
293
294 fn set_high(&mut self) -> Result<(), Self::Error> {
295 unsafe { (*$PORTX::ptr()).latset.write(|w| w.bits(1 << $i)) }
296 Ok(())
297 }
298 }
299
300 impl<MODE> eh::StatefulOutputPin for $PXi<Output<MODE>> {
301
302 fn is_set_high(&mut self) -> Result<bool, Self::Error> {
303 Ok(unsafe { (*$PORTX::ptr()).lat.read().bits() & (1 << $i) != 0 })
304 }
305
306 fn is_set_low(&mut self) -> Result<bool, Self::Error> {
307 Ok(unsafe { (*$PORTX::ptr()).lat.read().bits() & (1 << $i) == 0 })
308 }
309
310 fn toggle(&mut self) -> Result<(), Self::Error> {
311 unsafe { (*$PORTX::ptr()).latinv.write(|w| w.bits(1 << $i)) };
312 Ok(())
313 }
314 }
315 )+
316 }
317 }
318}
319
320include!("gpio_tables.rs");