pic32_hal/
pps.rs

1//! Peripheral Pin Select (PPS)
2
3use crate::gpio;
4use crate::pac::PPS;
5
6/// Extension trait to split a PPS peripheral into Parts corresponding to
7/// virtual ports
8pub trait PpsExt {
9    /// The type to split the PPS into
10    type Parts;
11
12    /// Splits the PPS peripheral into virtual ports
13    fn split(self) -> Self::Parts;
14}
15
16/// Virtual input and output ports created from the PPS peripheral struct
17pub struct Parts {
18    pub inputs: input::Inputs,
19    pub outputs: output::Outputs,
20}
21
22/// Phyiscal pin P that can be mapped to a virtual pin V
23pub trait MapPin<P, V> {
24    /// Map this physical pin to `virt_pin`
25    fn map_pin(self, virt_pin: V) -> MappedPin<P, V>;
26}
27
28/// Dummy to be used instead of a physical pin to leave a virtual pin of a
29/// peripheral unconnected
30pub struct NoPin;
31
32impl NoPin {
33    // Create a new NoPin
34    #[allow(clippy::new_without_default)]
35    pub fn new() -> NoPin {
36        NoPin
37    }
38}
39
40/// Move a virtual pin into a respective `MappedPin` mapped to a `NoPin`
41#[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
55/// Indicates whether a Mapped pin is connected to a physical pin or to a NoPin
56pub trait IsConnected {
57    /// true if connected to a physical pin
58    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
69/// Physical pin mapped to a particular virtual pin
70pub 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    /// Virtual input pins
83    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    /// Virtual output pins
98    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        /// Splits the PPS peripheral into virtual ports
117        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");