1use crate::gpio;
4use crate::pac::PPS;
5
6pub trait PpsExt {
9 type Parts;
11
12 fn split(self) -> Self::Parts;
14}
15
16pub struct Parts {
18 pub inputs: input::Inputs,
19 pub outputs: output::Outputs,
20}
21
22pub trait MapPin<P, V> {
24 fn map_pin(self, virt_pin: V) -> MappedPin<P, V>;
26}
27
28pub struct NoPin;
31
32impl NoPin {
33 #[allow(clippy::new_without_default)]
35 pub fn new() -> NoPin {
36 NoPin
37 }
38}
39
40#[macro_export]
42macro_rules! pps_no_pin {
43 ($VPIN:expr) => { NoPin::new().map_pin($VPIN) }
44}
45
46impl<V> MapPin<NoPin, V> for NoPin {
47 fn map_pin(self, virt_pin: V) -> MappedPin<NoPin, V> {
48 MappedPin {
49 phys: self,
50 virt: virt_pin,
51 }
52 }
53}
54
55pub trait IsConnected {
57 const IS_CONNECTED: bool = true;
59
60 fn is_connected(&self) -> bool {
61 Self::IS_CONNECTED
62 }
63}
64
65impl<V> IsConnected for MappedPin<NoPin, V> {
66 const IS_CONNECTED: bool = false;
67}
68
69pub struct MappedPin<P, V> {
71 phys: P,
72 virt: V,
73}
74
75macro_rules! pps_tables {
76 { {$( $IDTYPE:ident, $IDNAME:ident );+ ;}
77 {$( $ODTYPE:ident, $ODNAME:ident );+ ;}
78 {$( $VINTYPE:ident, $INREG:ident { $( $INPTYPE:path, $INVAL:expr; )+ } )+ }
79 {$( $OPTYPE:path, $OREG:ident { $( $VOUTTYPE:ident, $OVAL:expr; )+ } )+ } }
80 => {
81
82 pub mod input {
84 $(
85 pub struct $IDTYPE {
86 pub(super) _dummy: ()
87 }
88 )+
89
90 pub struct Inputs {
91 $(
92 pub $IDNAME: $IDTYPE,
93 )+
94 }
95 }
96
97 pub mod output {
99 $(
100 pub struct $ODTYPE {
101 pub(super) _dummy: (),
102 }
103 )+
104
105 pub struct Outputs {
106 $(
107 pub $ODNAME: $ODTYPE,
108 )+
109 }
110 }
111
112 impl PpsExt for PPS {
113
114 type Parts = Parts;
115
116 fn split(self) -> Self::Parts {
118 Parts {
119 inputs: input::Inputs {
120 $(
121 $IDNAME: input::$IDTYPE { _dummy: () },
122 )+
123 },
124 outputs: output::Outputs {
125 $(
126 $ODNAME: output::$ODTYPE { _dummy: () },
127 )+
128 }
129 }
130 }
131 }
132
133 $(
134 $(
135 impl<MODE> MapPin<$INPTYPE, input::$VINTYPE> for $INPTYPE {
136
137 fn map_pin(self, virt_pin: input::$VINTYPE) -> MappedPin<$INPTYPE, input::$VINTYPE> {
138 unsafe {(*PPS::ptr()).$INREG.write(|w| w.$INREG().bits($INVAL))};
139 MappedPin{ phys: self, virt: virt_pin }
140 }
141 }
142
143 impl<MODE> IsConnected for MappedPin<$INPTYPE, input::$VINTYPE> {}
144
145 impl<MODE> MappedPin<$INPTYPE, input::$VINTYPE> {
146
147 pub fn unmap_pin(self) -> ($INPTYPE, input::$VINTYPE) {
148 (self.phys, self.virt)
149 }
150 }
151 )+
152 )+
153
154 $(
155 $(
156 impl<MODE> MapPin<$OPTYPE, output::$VOUTTYPE> for $OPTYPE {
157
158 fn map_pin(self, virt_pin: output::$VOUTTYPE) -> MappedPin<$OPTYPE, output::$VOUTTYPE> {
159 unsafe {(*PPS::ptr()).$OREG.write(|w| w.$OREG().bits($OVAL))};
160 MappedPin { phys: self, virt: virt_pin}
161 }
162 }
163
164 impl <MODE> IsConnected for MappedPin<$OPTYPE, output::$VOUTTYPE> {}
165
166 impl<MODE> MappedPin<$OPTYPE, output::$VOUTTYPE> {
167
168 pub fn unmap_pin(self) -> ($OPTYPE, output::$VOUTTYPE) {
169 unsafe { (*PPS::ptr()).$OREG.write(|w| w.$OREG().bits(0)) };
170 (self.phys, self.virt)
171 }
172 }
173 )+
174 )+
175}}
176
177include!("pps_tables.rs");