1#![allow(unused_imports)]
3#![allow(non_camel_case_types)]
4
5use core::marker::PhantomData;
6
7pub struct Input<MODE> {
9 _mode: PhantomData<MODE>,
10}
11
12pub struct Floating;
14pub struct PullDown;
16pub struct PullUp;
18
19pub struct Output<MODE> {
21 _mode: PhantomData<MODE>,
22}
23
24pub trait GpioExt {
26 type Parts;
28
29 fn split(
31 self,
32 ) -> Self::Parts;
34}
35
36pub struct PushPull;
38pub struct OpenDrain;
40
41pub enum Level {
49 Low,
50 High,
51}
52
53
54pub struct Pin<MODE> {
61 pub pin: u8,
62 #[cfg(feature = "52840")]
63 pub port: bool,
64 _mode: PhantomData<MODE>,
65}
66
67use crate::target::P0;
68
69#[cfg(feature = "52840")]
70use crate::target::{ P1 };
71
72use crate::hal::digital::{OutputPin, StatefulOutputPin, InputPin};
73
74impl<MODE> Pin<MODE> {
75 pub fn into_floating_input(self) -> Pin<Input<Floating>> {
77 unsafe {
78 &(*{
79 #[cfg(any(feature = "52810", feature = "52832"))]
80 { P0::ptr() }
81 #[cfg(feature = "52840")]
82 { if !self.port { P0::ptr() } else { P1::ptr() } }
83 }).pin_cnf[self.pin as usize]
84 }
85 .write(|w| {
86 w.dir().input()
87 .input().connect()
88 .pull().disabled()
89 .drive().s0s1()
90 .sense().disabled()
91 });
92
93 Pin {
94 _mode: PhantomData,
95 #[cfg(feature = "52840")]
96 port: self.port,
97 pin: self.pin
98 }
99 }
100 pub fn into_pullup_input(self) -> Pin<Input<PullUp>> {
101 unsafe {
102 &(*{
103 #[cfg(any(feature = "52810", feature = "52832"))]
104 { P0::ptr() }
105 #[cfg(feature = "52840")]
106 { if !self.port { P0::ptr() } else { P1::ptr() } }
107 }).pin_cnf[self.pin as usize]
108 }
109 .write(|w| {
110 w.dir().input()
111 .input().connect()
112 .pull().pullup()
113 .drive().s0s1()
114 .sense().disabled()
115 });
116
117 Pin {
118 _mode: PhantomData,
119 #[cfg(feature = "52840")]
120 port: self.port,
121 pin: self.pin
122 }
123 }
124 pub fn into_pulldown_input(self) -> Pin<Input<PullDown>> {
125 unsafe {
126 &(*{
127 #[cfg(any(feature = "52810", feature = "52832"))]
128 { P0::ptr() }
129 #[cfg(feature = "52840")]
130 { if !self.port { P0::ptr() } else { P1::ptr() } }
131 }).pin_cnf[self.pin as usize]
132 }
133 .write(|w| {
134 w.dir().input()
135 .input().connect()
136 .pull().pulldown()
137 .drive().s0s1()
138 .sense().disabled()
139 });
140
141 Pin {
142 _mode: PhantomData,
143 #[cfg(feature = "52840")]
144 port: self.port,
145 pin: self.pin
146 }
147 }
148
149 pub fn into_push_pull_output(self, initial_output: Level)
151 -> Pin<Output<PushPull>>
152 {
153 let mut pin = Pin {
154 _mode: PhantomData,
155 #[cfg(feature = "52840")]
156 port: self.port,
157 pin: self.pin
158 };
159
160 match initial_output {
161 Level::Low => pin.set_low(),
162 Level::High => pin.set_high(),
163 }
164
165 unsafe {
166 &(*{
167 #[cfg(any(feature = "52810", feature = "52832"))]
168 { P0::ptr() }
169 #[cfg(feature = "52840")]
170 { if !self.port { P0::ptr() } else { P1::ptr() } }
171 }).pin_cnf[self.pin as usize]
172 }
173 .write(|w| {
174 w.dir().output()
175 .input().connect() .pull().disabled()
177 .drive().s0s1()
178 .sense().disabled()
179 });
180
181 pin
182 }
183
184 pub fn into_open_drain_output(self,
189 config: OpenDrainConfig,
190 initial_output: Level,
191 )
192 -> Pin<Output<OpenDrain>>
193 {
194 let mut pin = Pin {
195 _mode: PhantomData,
196 #[cfg(feature = "52840")]
197 port: self.port,
198 pin: self.pin
199 };
200
201 match initial_output {
202 Level::Low => pin.set_low(),
203 Level::High => pin.set_high(),
204 }
205
206 let pin_cnf = unsafe {
209 &(*{
210 #[cfg(any(feature = "52810", feature = "52832"))]
211 { P0::ptr() }
212 #[cfg(feature = "52840")]
213 { if !self.port { P0::ptr() } else { P1::ptr() } }
214 }).pin_cnf[self.pin as usize]
215 };
216 pin_cnf.write(|w| {
217 w
218 .dir().output()
219 .input().disconnect()
220 .pull().disabled()
221 .drive().variant(config.variant())
222 .sense().disabled()
223 });
224
225 pin
226 }
227}
228
229impl<MODE> InputPin for Pin<Input<MODE>> {
230 fn is_high(&self) -> bool {
231 !self.is_low()
232 }
233
234 fn is_low(&self) -> bool {
235 unsafe { (
236 (*{
237 #[cfg(any(feature = "52810", feature = "52832"))]
238 { P0::ptr() }
239 #[cfg(feature = "52840")]
240 { if !self.port { P0::ptr() } else { P1::ptr() } }
241 }).in_.read().bits() & (1 << self.pin)
242 ) == 0 }
243 }
244}
245
246impl<MODE> OutputPin for Pin<Output<MODE>> {
247 fn set_high(&mut self) {
249 unsafe {
252 (*{
253 #[cfg(any(feature = "52810", feature = "52832"))]
254 { P0::ptr() }
255 #[cfg(feature = "52840")]
256 { if !self.port { P0::ptr() } else { P1::ptr() } }
257 }).outset.write(|w| w.bits(1u32 << self.pin));
258 }
259 }
260
261 fn set_low(&mut self) {
263 unsafe {
266 (*{
267 #[cfg(any(feature = "52810", feature = "52832"))]
268 { P0::ptr() }
269 #[cfg(feature = "52840")]
270 { if !self.port { P0::ptr() } else { P1::ptr() } }
271 }).outclr.write(|w| w.bits(1u32 << self.pin));
272 }
273 }
274}
275
276impl<MODE> StatefulOutputPin for Pin<Output<MODE>> {
277 fn is_set_high(&self) -> bool {
279 !self.is_set_low()
280 }
281
282 fn is_set_low(&self) -> bool {
284 unsafe { (
287 (*{
288 #[cfg(any(feature = "52810", feature = "52832"))]
289 { P0::ptr() }
290 #[cfg(feature = "52840")]
291 { if !self.port { P0::ptr() } else { P1::ptr() } }
292 }).out.read().bits() & (1 << self.pin)
293 ) == 0 }
294 }
295}
296
297pub enum OpenDrainConfig {
299 Disconnect0Standard1,
300 Disconnect0HighDrive1,
301 Standard0Disconnect1,
302 HighDrive0Disconnect1,
303}
304
305use crate::target::p0::{
306 pin_cnf,
307 PIN_CNF,
308};
309
310impl OpenDrainConfig {
311 fn variant(self) -> pin_cnf::DRIVEW {
312 use self::OpenDrainConfig::*;
313
314 match self {
315 Disconnect0Standard1 => pin_cnf::DRIVEW::D0S1,
316 Disconnect0HighDrive1 => pin_cnf::DRIVEW::D0H1,
317 Standard0Disconnect1 => pin_cnf::DRIVEW::S0D1,
318 HighDrive0Disconnect1 => pin_cnf::DRIVEW::H0D1,
319 }
320 }
321}
322
323macro_rules! gpio {
324 (
325 $PX:ident, $pxsvd:ident, $px:ident, $port_value:expr, [
326 $($PXi:ident: ($pxi:ident, $i:expr, $MODE:ty),)+
327 ]
328 ) => {
329 pub mod $px {
331 use super::{
332 Pin,
333
334 Floating,
336 GpioExt,
337 Input,
338 Level,
339 OpenDrain,
340 OpenDrainConfig,
341 Output,
342 PullDown,
343 PullUp,
344 PushPull,
345
346 PhantomData,
347 };
348
349 use crate::target;
350 use crate::target::$PX;
351 use crate::hal::digital::{OutputPin, StatefulOutputPin, InputPin};
352
353
354
355 pub struct Parts {
361 $(
362 pub $pxi: $PXi<$MODE>,
364 )+
365 }
366
367 impl GpioExt for $PX {
368 type Parts = Parts;
369
370 fn split(self) -> Parts {
371 Parts {
372 $(
373 $pxi: $PXi {
374 _mode: PhantomData,
375 },
376 )+
377 }
378 }
379 }
380
381 $(
386 pub struct $PXi<MODE> {
387 _mode: PhantomData<MODE>,
388 }
389
390
391 impl<MODE> $PXi<MODE> {
392 pub fn into_floating_input(self) -> $PXi<Input<Floating>> {
394 unsafe { &(*$PX::ptr()).pin_cnf[$i] }.write(|w| {
395 w.dir().input()
396 .input().connect()
397 .pull().disabled()
398 .drive().s0s1()
399 .sense().disabled()
400 });
401
402 $PXi {
403 _mode: PhantomData,
404 }
405 }
406 pub fn into_pulldown_input(self) -> $PXi<Input<PullDown>> {
407 unsafe { &(*$PX::ptr()).pin_cnf[$i] }.write(|w| {
408 w.dir().input()
409 .input().connect()
410 .pull().pulldown()
411 .drive().s0s1()
412 .sense().disabled()
413 });
414
415 $PXi {
416 _mode: PhantomData,
417 }
418 }
419 pub fn into_pullup_input(self) -> $PXi<Input<PullUp>> {
420 unsafe { &(*$PX::ptr()).pin_cnf[$i] }.write(|w| {
421 w.dir().input()
422 .input().connect()
423 .pull().pullup()
424 .drive().s0s1()
425 .sense().disabled()
426 });
427
428 $PXi {
429 _mode: PhantomData,
430 }
431 }
432
433 pub fn into_push_pull_output(self, initial_output: Level)
435 -> $PXi<Output<PushPull>>
436 {
437 let mut pin = $PXi {
438 _mode: PhantomData,
439 };
440
441 match initial_output {
442 Level::Low => pin.set_low(),
443 Level::High => pin.set_high(),
444 }
445
446 unsafe { &(*$PX::ptr()).pin_cnf[$i] }.write(|w| {
447 w.dir().output()
448 .input().disconnect()
449 .pull().disabled()
450 .drive().s0s1()
451 .sense().disabled()
452 });
453
454 pin
455 }
456
457 pub fn into_open_drain_output(self,
462 config: OpenDrainConfig,
463 initial_output: Level,
464 )
465 -> $PXi<Output<OpenDrain>>
466 {
467 let mut pin = $PXi {
468 _mode: PhantomData,
469 };
470
471 match initial_output {
472 Level::Low => pin.set_low(),
473 Level::High => pin.set_high(),
474 }
475
476 let pin_cnf = unsafe {
479 &(*$PX::ptr()).pin_cnf[$i]
480 };
481 pin_cnf.write(|w| {
482 w
483 .dir().output()
484 .input().disconnect()
485 .pull().disabled()
486 .drive().variant(config.variant())
487 .sense().disabled()
488 });
489
490 pin
491 }
492
493 pub fn degrade(self) -> Pin<MODE> {
495 Pin {
496 _mode: PhantomData,
497 #[cfg(feature = "52840")]
498 port: $port_value,
499 pin: $i
500 }
501 }
502 }
503
504 impl<MODE> InputPin for $PXi<Input<MODE>> {
505 fn is_high(&self) -> bool {
506 !self.is_low()
507 }
508
509 fn is_low(&self) -> bool {
510 unsafe { ((*$PX::ptr()).in_.read().bits() & (1 << $i)) == 0 }
511 }
512 }
513
514 impl<MODE> OutputPin for $PXi<Output<MODE>> {
515 fn set_high(&mut self) {
517 unsafe { (*$PX::ptr()).outset.write(|w| w.bits(1u32 << $i)); }
520 }
521
522 fn set_low(&mut self) {
524 unsafe { (*$PX::ptr()).outclr.write(|w| w.bits(1u32 << $i)); }
527 }
528 }
529
530 impl<MODE> StatefulOutputPin for $PXi<Output<MODE>> {
531 fn is_set_high(&self) -> bool {
533 !self.is_set_low()
534 }
535
536 fn is_set_low(&self) -> bool {
538 unsafe { ((*$PX::ptr()).out.read().bits() & (1 << $i)) == 0 }
541 }
542 }
543 )+
544 }
545 }
546}
547
548gpio!(P0, p0, p0, false, [
555 P0_00: (p0_00, 0, Input<Floating>),
556 P0_01: (p0_01, 1, Input<Floating>),
557 P0_02: (p0_02, 2, Input<Floating>),
558 P0_03: (p0_03, 3, Input<Floating>),
559 P0_04: (p0_04, 4, Input<Floating>),
560 P0_05: (p0_05, 5, Input<Floating>),
561 P0_06: (p0_06, 6, Input<Floating>),
562 P0_07: (p0_07, 7, Input<Floating>),
563 P0_08: (p0_08, 8, Input<Floating>),
564 P0_09: (p0_09, 9, Input<Floating>),
565 P0_10: (p0_10, 10, Input<Floating>),
566 P0_11: (p0_11, 11, Input<Floating>),
567 P0_12: (p0_12, 12, Input<Floating>),
568 P0_13: (p0_13, 13, Input<Floating>),
569 P0_14: (p0_14, 14, Input<Floating>),
570 P0_15: (p0_15, 15, Input<Floating>),
571 P0_16: (p0_16, 16, Input<Floating>),
572 P0_17: (p0_17, 17, Input<Floating>),
573 P0_18: (p0_18, 18, Input<Floating>),
574 P0_19: (p0_19, 19, Input<Floating>),
575 P0_20: (p0_20, 20, Input<Floating>),
576 P0_21: (p0_21, 21, Input<Floating>),
577 P0_22: (p0_22, 22, Input<Floating>),
578 P0_23: (p0_23, 23, Input<Floating>),
579 P0_24: (p0_24, 24, Input<Floating>),
580 P0_25: (p0_25, 25, Input<Floating>),
581 P0_26: (p0_26, 26, Input<Floating>),
582 P0_27: (p0_27, 27, Input<Floating>),
583 P0_28: (p0_28, 28, Input<Floating>),
584 P0_29: (p0_29, 29, Input<Floating>),
585 P0_30: (p0_30, 30, Input<Floating>),
586 P0_31: (p0_31, 31, Input<Floating>),
587]);
588
589#[cfg(feature = "52840")]
592gpio!(P1, p0, p1, true, [
593 P1_00: (p1_00, 0, Input<Floating>),
594 P1_01: (p1_01, 1, Input<Floating>),
595 P1_02: (p1_02, 2, Input<Floating>),
596 P1_03: (p1_03, 3, Input<Floating>),
597 P1_04: (p1_04, 4, Input<Floating>),
598 P1_05: (p1_05, 5, Input<Floating>),
599 P1_06: (p1_06, 6, Input<Floating>),
600 P1_07: (p1_07, 7, Input<Floating>),
601 P1_08: (p1_08, 8, Input<Floating>),
602 P1_09: (p1_09, 9, Input<Floating>),
603 P1_10: (p1_10, 10, Input<Floating>),
604 P1_11: (p1_11, 11, Input<Floating>),
605 P1_12: (p1_12, 12, Input<Floating>),
606 P1_13: (p1_13, 13, Input<Floating>),
607 P1_14: (p1_14, 14, Input<Floating>),
608 P1_15: (p1_15, 15, Input<Floating>),
609]);