1use core::marker::PhantomData;
6
7use crate::pac::{gpio0, GPIO0_SECURE, GPIO1_SECURE, GPIO2_SECURE};
8
9pub trait PinMode {}
10
11pub enum Gpio {}
12impl PinMode for Gpio {}
13pub enum Uart {}
14impl PinMode for Uart {}
15pub enum Spi {}
16impl PinMode for Spi {}
17pub enum I2c {}
18impl PinMode for I2c {}
19
20pub struct Pin<const SHIELD_ID: usize, const PIN_ID: usize, Mode: PinMode> {
21 mode: PhantomData<Mode>,
22}
23impl<const SHIELD_ID: usize, const PIN_ID: usize, Mode: PinMode> Pin<SHIELD_ID, PIN_ID, Mode> {
24 fn block_and_mask(&self) -> (*const gpio0::RegisterBlock, u32) {
25 match (SHIELD_ID, PIN_ID) {
26 (0, 16) => (GPIO2_SECURE::PTR, 0b0001),
27 (0, 17) => (GPIO2_SECURE::PTR, 0b0010),
28 (1, 16) => (GPIO2_SECURE::PTR, 0b0100),
29 (1, 17) => (GPIO2_SECURE::PTR, 0b1000),
30 (0, pid) => (GPIO0_SECURE::PTR, 1 << pid),
31 (1, pid) => (GPIO1_SECURE::PTR, 1 << pid),
32 (_, _) => unreachable!(),
33 }
34 }
35}
36
37pub enum Pins {}
38impl Pins {
39 #[allow(clippy::type_complexity)]
40 pub fn get_pins_secure(
41 gpio0: GPIO0_SECURE,
42 gpio1: GPIO1_SECURE,
43 gpio2: GPIO2_SECURE,
44 ) -> (
45 Pin<0, 0, Gpio>,
46 Pin<0, 1, Gpio>,
47 Pin<0, 2, Gpio>,
48 Pin<0, 3, Gpio>,
49 Pin<0, 4, Gpio>,
50 Pin<0, 5, Gpio>,
51 Pin<0, 6, Gpio>,
52 Pin<0, 7, Gpio>,
53 Pin<0, 8, Gpio>,
54 Pin<0, 9, Gpio>,
55 Pin<0, 10, Gpio>,
56 Pin<0, 11, Gpio>,
57 Pin<0, 12, Gpio>,
58 Pin<0, 13, Gpio>,
59 Pin<0, 14, Gpio>,
60 Pin<0, 15, Gpio>,
61 Pin<0, 16, Gpio>,
62 Pin<0, 17, Gpio>,
63 Pin<1, 0, Gpio>,
64 Pin<1, 1, Gpio>,
65 Pin<1, 2, Gpio>,
66 Pin<1, 3, Gpio>,
67 Pin<1, 4, Gpio>,
68 Pin<1, 5, Gpio>,
69 Pin<1, 6, Gpio>,
70 Pin<1, 7, Gpio>,
71 Pin<1, 8, Gpio>,
72 Pin<1, 9, Gpio>,
73 Pin<1, 10, Gpio>,
74 Pin<1, 11, Gpio>,
75 Pin<1, 12, Gpio>,
76 Pin<1, 13, Gpio>,
77 Pin<1, 14, Gpio>,
78 Pin<1, 15, Gpio>,
79 Pin<1, 16, Gpio>,
80 Pin<1, 17, Gpio>,
81 ) {
82 let _ = (gpio0, gpio1, gpio2);
86 (
87 Pin { mode: PhantomData },
88 Pin { mode: PhantomData },
89 Pin { mode: PhantomData },
90 Pin { mode: PhantomData },
91 Pin { mode: PhantomData },
92 Pin { mode: PhantomData },
93 Pin { mode: PhantomData },
94 Pin { mode: PhantomData },
95 Pin { mode: PhantomData },
96 Pin { mode: PhantomData },
97 Pin { mode: PhantomData },
98 Pin { mode: PhantomData },
99 Pin { mode: PhantomData },
100 Pin { mode: PhantomData },
101 Pin { mode: PhantomData },
102 Pin { mode: PhantomData },
103 Pin { mode: PhantomData },
104 Pin { mode: PhantomData },
105 Pin { mode: PhantomData },
106 Pin { mode: PhantomData },
107 Pin { mode: PhantomData },
108 Pin { mode: PhantomData },
109 Pin { mode: PhantomData },
110 Pin { mode: PhantomData },
111 Pin { mode: PhantomData },
112 Pin { mode: PhantomData },
113 Pin { mode: PhantomData },
114 Pin { mode: PhantomData },
115 Pin { mode: PhantomData },
116 Pin { mode: PhantomData },
117 Pin { mode: PhantomData },
118 Pin { mode: PhantomData },
119 Pin { mode: PhantomData },
120 Pin { mode: PhantomData },
121 Pin { mode: PhantomData },
122 Pin { mode: PhantomData },
123 )
124 }
125}
126
127macro_rules! impl_into_mode {
128 ($(($shield:expr, $pin:expr) => $mode:ident)*) => {
129 $(
130 impl Pin<$shield, $pin, Gpio> {
131 #[doc = concat!("Turns the current GPIO pin into a ", stringify!($mode), " pin")]
132 pub fn into_mode(self) -> Pin<$shield, $pin, $mode> {
133 let (block, mask) = self.block_and_mask();
134 unsafe { &*block }.altfuncset.write(|w|unsafe { w.bits(mask) });
135 Pin {
136 mode: PhantomData
137 }
138 }
139 }
140 impl Pin<$shield, $pin, $mode> {
141 #[doc = concat!("Turns the current ", stringify!($mode), " pin into a GPIO pin")]
142 pub fn into_mode(self) -> Pin<$shield, $pin, Gpio> {
143 let (block, mask) = self.block_and_mask();
144 unsafe { &*block }.altfuncclr.write(|w|unsafe { w.bits(mask) });
145 Pin {
146 mode: PhantomData
147 }
148 }
149 }
150 )*
151 };
152}
153
154impl_into_mode! {
155 (0, 0) => Uart
156 (0, 1) => Uart
157 (0, 10) => Spi
158 (0, 11) => Spi
159 (0, 12) => Spi
160 (0, 13) => Spi
161 (0, 14) => I2c
162 (0, 15) => I2c
163 (1, 0) => Uart
164 (1, 1) => Uart
165 (1, 10) => Spi
166 (1, 11) => Spi
167 (1, 12) => Spi
168 (1, 13) => Spi
169 (1, 14) => I2c
170 (1, 15) => I2c
171}
172
173impl<const SHIELD_ID: usize, const PIN_ID: usize> embedded_hal::digital::v2::InputPin
174 for Pin<SHIELD_ID, PIN_ID, Gpio>
175{
176 type Error = core::convert::Infallible;
177
178 fn is_high(&self) -> Result<bool, core::convert::Infallible> {
179 let (block, mask) = self.block_and_mask();
180 Ok((unsafe { &*block }.data.read().bits() & mask) != 0)
181 }
182
183 fn is_low(&self) -> Result<bool, core::convert::Infallible> {
184 self.is_high().map(|b| !b)
185 }
186}