1use core::marker::PhantomData;
2use mk20d7::sim::SCGC5;
3
4pub trait GpioExt {
6 type Parts;
8
9 fn split(self, scgc5: &SCGC5) -> Self::Parts;
11}
12
13pub struct Input<MODE> {
15 _mode: PhantomData<MODE>,
16}
17
18pub struct Floating;
20
21pub struct PullDown;
23
24pub struct PullUp;
26
27pub struct Output<MODE> {
29 _mode: PhantomData<MODE>,
30}
31
32pub struct PushPull;
34
35pub struct OpenDrain;
37
38pub struct Alternate<MODE> {
39 _mode: PhantomData<MODE>,
40}
41
42pub struct ALT0;
44
45pub struct ALT1;
47
48pub struct ALT2;
50
51pub struct ALT3;
53
54pub struct ALT4;
56
57pub struct ALT5;
59
60pub struct ALT6;
62
63pub struct ALT7;
65
66enum PinMux {
68 ALT0,
69 ALT1,
70 ALT2,
71 ALT3,
72 ALT4,
73 ALT5,
74 ALT6,
75 ALT7,
76}
77
78enum PinMode {
80 Output,
81
82 #[allow(dead_code)]
83 Input,
84}
85
86macro_rules! gpio {
87 ($PORTX:ident, $portx:ident, $PTX:ident, $ptx:ident, $gpiox:ident, $docport:expr, [ $($PTXi:ident: ($ptxi:ident, $i:expr, $MODE:ty, $docpin:expr),)+]) =>
88 {
89 #[doc = "General Purpose Input/Output Port "]
90 #[doc = $docport]
91 pub mod $gpiox {
92 use core::marker::PhantomData;
93
94 use hal::digital::{
95 OutputPin, StatefulOutputPin, InputPin,
96 toggleable,
97 };
98
99 use mk20d7::{sim::SCGC5, $PORTX, $PTX, $portx, $ptx};
100
101 use super::{
102 Floating, GpioExt, Input, Output,
103 PushPull,
104 Alternate, ALT0, ALT1, ALT2, ALT3, ALT4, ALT5, ALT6, ALT7,
105 PinMux, PinMode,
106 };
107
108 pub struct Parts {
110 pub dfcr: DFCR,
113
114 pub dfer: DFER,
116
117 pub dfwr: DFWR,
119
120 pub gpchr: GPCHR,
122
123 pub gpclr: GPCLR,
125
126 pub isfr: ISFR,
128
129 pub pcr: PCR,
131
132 pub pcor: PCOR,
135
136 pub pddr: PDDR,
138
139 pub pdir: PDIR,
141
142 pub pdor: PDOR,
144
145 pub psor: PSOR,
147
148 pub ptor: PTOR,
150
151 $(
152 #[doc = "General Purpose Input/Output Port "]
153 #[doc = $docport]
154 #[doc = " Pin "]
155 #[doc = $docpin]
156 pub $ptxi: $PTXi<$MODE>,
157 )+
158 }
159
160 impl GpioExt for ($PTX, $PORTX) {
161 type Parts = Parts;
162
163 fn split(self, scgc5: &SCGC5) -> Self::Parts {
164 scgc5.write(|w| w.$portx().set_bit());
167
168 Parts {
169 dfcr: DFCR { _0: () },
170 dfer: DFER { _0: () },
171 dfwr: DFWR { _0: () },
172 gpchr: GPCHR { _0: () },
173 gpclr: GPCLR { _0: () },
174 isfr: ISFR { _0: () },
175 pcr: PCR { _0: () },
176 pcor: PCOR { _0: () },
177 pddr: PDDR { _0: () },
178 pdir: PDIR { _0: () },
179 pdor: PDOR { _0: () },
180 psor: PSOR { _0: () },
181 ptor: PTOR { _0: () },
182 $(
183 $ptxi: $PTXi {_mode: PhantomData},
184 )+
185 }
186 }
187 }
188
189 pub struct DFCR {
191 _0: (),
192 }
193
194 impl DFCR {
195 #[allow(dead_code)]
196 pub(crate) fn dfcr(&mut self) -> &$portx::DFCR {
197 unsafe { &(*$PORTX::ptr()).dfcr }
198 }
199 }
200
201 pub struct DFER {
203 _0: (),
204 }
205
206 impl DFER {
207 #[allow(dead_code)]
208 pub(crate) fn dfer(&mut self) -> &$portx::DFER {
209 unsafe { &(*$PORTX::ptr()).dfer }
210 }
211 }
212
213 pub struct DFWR {
215 _0: (),
216 }
217
218 impl DFWR {
219 #[allow(dead_code)]
220 pub(crate) fn dfwr(&mut self) -> &$portx::DFWR {
221 unsafe { &(*$PORTX::ptr()).dfwr }
222 }
223 }
224
225 pub struct GPCHR {
227 _0: (),
228 }
229
230 pub struct GPCLR {
232 _0: (),
233 }
234
235 pub struct ISFR {
237 _0: (),
238 }
239
240 impl ISFR {
241 #[allow(dead_code)]
242 pub(crate) fn isfr(&mut self) -> &$portx::ISFR {
243 unsafe { &(*$PORTX::ptr()).isfr }
244 }
245 }
246
247 pub struct PCR {
249 _0: (),
250 }
251
252 impl PCR {
253 pub(crate) fn pcr(&mut self) -> &[$portx::PCR; 32] {
254 unsafe { &(*$PORTX::ptr()).pcr }
255 }
256 }
257
258 pub struct PCOR {
260 _0: (),
261 }
262
263 impl PCOR {
264 pub(crate) fn pcor(&mut self) -> &$ptx::PCOR {
265 unsafe { &(*$PTX::ptr()).pcor }
266 }
267 }
268
269 pub struct PDDR {
271 _0: (),
272 }
273
274 impl PDDR {
275 pub(crate) fn pddr(&mut self) -> &$ptx::PDDR {
276 unsafe { &(*$PTX::ptr()).pddr }
277 }
278 }
279
280 pub struct PDIR {
282 _0: (),
283 }
284
285 impl PDIR {
286 pub(crate) fn pdir(&mut self) -> &$ptx::PDIR {
287 unsafe { &(*$PTX::ptr()).pdir }
288 }
289 }
290
291 pub struct PDOR {
293 _0: (),
294 }
295
296 impl PDOR {
297 pub(crate) fn pdor(&mut self) -> &$ptx::PDOR {
298 unsafe { &(*$PTX::ptr()).pdor }
299 }
300 }
301
302 pub struct PSOR {
304 _0: (),
305 }
306
307 impl PSOR {
308 pub(crate) fn psor(&mut self) -> &$ptx::PSOR {
309 unsafe { &(*$PTX::ptr()).psor }
310 }
311 }
312
313 pub struct PTOR {
315 _0: (),
316 }
317
318 impl PTOR {
319 #[allow(dead_code)]
320 pub(crate) fn ptor(&mut self) -> &$ptx::PTOR {
321 unsafe { &(*$PTX::ptr()).ptor }
322 }
323 }
324
325 fn set_pin_mux(pin: usize, pcr: &mut PCR, pin_mux: PinMux) {
326 let alt = match pin_mux {
327 PinMux::ALT0 => $portx::pcr::MUXW::_000,
328 PinMux::ALT1 => $portx::pcr::MUXW::_001,
329 PinMux::ALT2 => $portx::pcr::MUXW::_010,
330 PinMux::ALT3 => $portx::pcr::MUXW::_011,
331 PinMux::ALT4 => $portx::pcr::MUXW::_100,
332 PinMux::ALT5 => $portx::pcr::MUXW::_101,
333 PinMux::ALT6 => $portx::pcr::MUXW::_110,
334 PinMux::ALT7 => $portx::pcr::MUXW::_111,
335 };
336
337 pcr.pcr()[pin].write(|w| w.mux().variant(alt));
338 }
339
340 fn set_pin_mode(pin: u32, pddr: &mut PDDR, pin_mode: PinMode) {
341 let bit = match pin_mode {
342 PinMode::Output => 1 << pin,
343 PinMode::Input => !(1 << pin),
344 };
345 pddr.pddr().modify(|r, w| unsafe { w.bits(r.bits() | bit) });
346 }
347
348 $(
352 #[doc = "General Purpose Input/Output Port "]
353 #[doc = $docport]
354 #[doc = " Pin "]
355 #[doc = $docpin]
356 pub struct $PTXi<MODE> {
357 _mode: PhantomData<MODE>,
358 }
359
360 impl<MODE> $PTXi<MODE> {
361 pub fn into_alternate_alt0(self, pcr: &mut PCR) -> $PTXi<Alternate<ALT0>> {
362 set_pin_mux($i, pcr, PinMux::ALT0);
363 $PTXi { _mode: PhantomData }
364 }
365
366 pub fn into_alternate_alt1(self, pcr: &mut PCR) -> $PTXi<Alternate<ALT1>> {
367 set_pin_mux($i, pcr, PinMux::ALT1);
368 $PTXi { _mode: PhantomData }
369 }
370
371 pub fn into_alternate_alt2(self, pcr: &mut PCR) -> $PTXi<Alternate<ALT2>> {
372 set_pin_mux($i, pcr, PinMux::ALT2);
373 $PTXi { _mode: PhantomData }
374 }
375
376 pub fn into_alternate_alt3(self, pcr: &mut PCR) -> $PTXi<Alternate<ALT3>> {
377 set_pin_mux($i, pcr, PinMux::ALT3);
378 $PTXi { _mode: PhantomData }
379 }
380
381 pub fn into_alternate_alt4(self, pcr: &mut PCR) -> $PTXi<Alternate<ALT4>> {
382 set_pin_mux($i, pcr, PinMux::ALT4);
383 $PTXi { _mode: PhantomData }
384 }
385
386 pub fn into_alternate_alt5(self, pcr: &mut PCR) -> $PTXi<Alternate<ALT5>> {
387 set_pin_mux($i, pcr, PinMux::ALT5);
388 $PTXi { _mode: PhantomData }
389 }
390
391 pub fn into_alternate_alt6(self, pcr: &mut PCR) -> $PTXi<Alternate<ALT6>> {
392 set_pin_mux($i, pcr, PinMux::ALT6);
393 $PTXi { _mode: PhantomData }
394 }
395
396 pub fn into_alternate_alt7(self, pcr: &mut PCR) -> $PTXi<Alternate<ALT7>> {
397 set_pin_mux($i, pcr, PinMux::ALT7);
398 $PTXi { _mode: PhantomData }
399 }
400
401 pub fn into_push_pull_output(self, pcr: &mut PCR, pddr: &mut PDDR) -> $PTXi<Output<PushPull>> {
402 set_pin_mux($i, pcr, PinMux::ALT1);
403 set_pin_mode($i, pddr, PinMode::Output);
404 $PTXi { _mode: PhantomData }
405 }
406 }
407
408 impl<MODE> StatefulOutputPin for $PTXi<Output<MODE>> {
409 fn is_set_high(&self) -> bool {
410 !self.is_set_low()
411 }
412
413 fn is_set_low(&self) -> bool {
414 (PDOR { _0: () }).pdor().read().bits() & (1 << $i) == 0
415 }
416 }
417
418 impl<MODE> OutputPin for $PTXi<Output<MODE>> {
419 fn set_high(&mut self) {
420 (PSOR { _0: () }).psor().write(|w| unsafe { w.bits(1 << $i) })
421 }
422
423 fn set_low(&mut self) {
424 (PCOR { _0: () }).pcor().write(|w| unsafe { w.bits(1 << $i) })
425 }
426 }
427
428 impl<MODE> toggleable::Default for $PTXi<Output<MODE>> {}
429
430 impl<MODE> InputPin for $PTXi<Input<MODE>> {
431 fn is_high(&self) -> bool {
432 !self.is_low()
433 }
434
435 fn is_low(&self) -> bool {
436 (PDIR { _0: () }).pdir().read().bits() & (1 << $i) == 0
437 }
438 }
439 )+
440 }
441 }
442}
443
444gpio!(PORTA, porta, PTA, pta, gpioa, "A", [
446 PTA0: (pta0, 0, Input<Floating>, "0"),
447 PTA1: (pta1, 1, Input<Floating>, "1"),
448 PTA2: (pta2, 2, Input<Floating>, "2"),
449 PTA3: (pta3, 3, Input<Floating>, "3"),
450 PTA4: (pta4, 4, Input<Floating>, "4"),
451 PTA5: (pta5, 5, Input<Floating>, "5"),
452 PTA12: (pta12, 12, Input<Floating>, "12"),
453 PTA13: (pta13, 13, Input<Floating>, "13"),
454 PTA18: (pta18, 18, Input<Floating>, "18"),
455 PTA19: (pta19, 19, Input<Floating>, "19"),
456]);
457
458gpio!(PORTB, portb, PTB, ptb, gpiob, "B", [
459 PTB0: (ptb0, 0, Input<Floating>, "0"),
460 PTB1: (ptb1, 1, Input<Floating>, "1"),
461 PTB2: (ptb2, 2, Input<Floating>, "2"),
462 PTB3: (ptb3, 3, Input<Floating>, "3"),
463 PTB16: (ptb16, 16, Input<Floating>, "16"),
464 PTB17: (ptb17, 17, Input<Floating>, "17"),
465 PTB18: (ptb18, 18, Input<Floating>, "18"),
466 PTB19: (ptb19, 19, Input<Floating>, "19"),
467]);
468
469gpio!(PORTC, portc, PTC, ptc, gpioc, "C", [
470 PTC0: (ptc0, 0, Input<Floating>, "0"),
471 PTC1: (ptc1, 1, Input<Floating>, "1"),
472 PTC2: (ptc2, 2, Input<Floating>, "2"),
473 PTC3: (ptc3, 3, Input<Floating>, "3"),
474 PTC4: (ptc4, 4, Input<Floating>, "4"),
475 PTC5: (ptc5, 5, Input<Floating>, "5"),
476 PTC6: (ptc6, 6, Input<Floating>, "6"),
477 PTC7: (ptc7, 7, Input<Floating>, "7"),
478 PTC8: (ptc8, 8, Input<Floating>, "8"),
479 PTC9: (ptc9, 9, Input<Floating>, "9"),
480 PTC10: (ptc10, 10, Input<Floating>, "10"),
481 PTC11: (ptc11, 11, Input<Floating>, "11"),
482]);
483
484gpio!(PORTD, portd, PTD, ptd, gpiod, "D", [
485 PTD0: (ptd0, 0, Input<Floating>, "0"),
486 PTD1: (ptd1, 1, Input<Floating>, "1"),
487 PTD2: (ptd2, 2, Input<Floating>, "2"),
488 PTD3: (ptd3, 3, Input<Floating>, "3"),
489 PTD4: (ptd4, 4, Input<Floating>, "4"),
490 PTD5: (ptd5, 5, Input<Floating>, "5"),
491 PTD6: (ptd6, 6, Input<Floating>, "6"),
492 PTD7: (ptd7, 7, Input<Floating>, "7"),
493]);
494
495gpio!(PORTE, porte, PTE, pte, gpioe, "E", [
496 PTE0: (pte0, 0, Input<Floating>, "0"),
497 PTE1: (pte1, 1, Input<Floating>, "1"),
498]);