1use core::marker::PhantomData;
3use embedded_hal::digital::{ErrorType, InputPin, OutputPin, StatefulOutputPin};
4use paste::paste;
5
6pub trait PinMode: crate::Sealed {}
8
9pub struct Input;
10pub struct InputOutput;
11pub struct Af1;
12pub struct Af2;
13
14impl crate::Sealed for Input {}
15impl crate::Sealed for InputOutput {}
16impl crate::Sealed for Af1 {}
17impl crate::Sealed for Af2 {}
18
19impl PinMode for Input {}
20impl PinMode for InputOutput {}
21impl PinMode for Af1 {}
22impl PinMode for Af2 {}
23
24pub trait PowerSupply: crate::Sealed {}
26
27pub struct Vddio;
28pub struct Vddioh;
29
30impl crate::Sealed for Vddio {}
31impl crate::Sealed for Vddioh {}
32
33impl PowerSupply for Vddio {}
34impl PowerSupply for Vddioh {}
35
36pub trait PadMode: crate::Sealed {}
38
39pub struct HighImpedance;
40pub struct PullUpWeak;
41pub struct PullUpStrong;
42pub struct PullDownWeak;
43pub struct PullDownStrong;
44
45impl crate::Sealed for HighImpedance {}
46impl crate::Sealed for PullUpWeak {}
47impl crate::Sealed for PullUpStrong {}
48impl crate::Sealed for PullDownWeak {}
49impl crate::Sealed for PullDownStrong {}
50
51impl PadMode for HighImpedance {}
52impl PadMode for PullUpWeak {}
53impl PadMode for PullUpStrong {}
54impl PadMode for PullDownWeak {}
55impl PadMode for PullDownStrong {}
56
57pub trait DriveStrength: crate::Sealed {}
59
60pub struct Strength0;
61pub struct Strength1;
62pub struct Strength2;
63pub struct Strength3;
64
65impl crate::Sealed for Strength0 {}
66impl crate::Sealed for Strength1 {}
67impl crate::Sealed for Strength2 {}
68impl crate::Sealed for Strength3 {}
69
70impl DriveStrength for Strength0 {}
71impl DriveStrength for Strength1 {}
72impl DriveStrength for Strength2 {}
73impl DriveStrength for Strength3 {}
74
75pub struct Pin<
83 const P: u8,
84 const N: u8,
85 MODE: PinMode = Input,
86 SUPPLY: PowerSupply = Vddio,
87 PAD: PadMode = HighImpedance,
88 DRIVE: DriveStrength = Strength0,
89> {
90 _mode: PhantomData<MODE>,
91 _supply: PhantomData<SUPPLY>,
92 _pad: PhantomData<PAD>,
93 _drive: PhantomData<DRIVE>,
94}
95
96impl<const P: u8, const N: u8, MODE: PinMode> Pin<P, N, MODE> {
98 const fn new() -> Self {
99 Self {
100 _mode: PhantomData,
101 _supply: PhantomData,
102 _pad: PhantomData,
103 _drive: PhantomData,
104 }
105 }
106
107 #[doc(hidden)]
108 #[inline(always)]
109 fn _output_enable(&mut self) {
110 let gpio = unsafe { &*gpiox_ptr::<P>() };
112 gpio.outen_set().write(|w| unsafe { w.bits(1 << N) });
113 }
114
115 #[doc(hidden)]
116 #[inline(always)]
117 fn _output_disable(&mut self) {
118 let gpio = unsafe { &*gpiox_ptr::<P>() };
120 gpio.outen_clr().write(|w| unsafe { w.bits(1 << N) });
121 }
122
123 #[doc(hidden)]
124 #[inline(always)]
125 fn _into_af1(&mut self) {
126 let gpio = unsafe { &*gpiox_ptr::<P>() };
127 gpio.en0_set().write(|w| unsafe { w.bits(1 << N) });
129 gpio.en1_clr().write(|w| unsafe { w.bits(1 << N) });
131 gpio.en0_clr().write(|w| unsafe { w.bits(1 << N) });
133 }
134
135 #[doc(hidden)]
136 #[inline(always)]
137 fn _into_af2(&mut self) {
138 let gpio = unsafe { &*gpiox_ptr::<P>() };
139 gpio.en0_set().write(|w| unsafe { w.bits(1 << N) });
141 gpio.en1_set().write(|w| unsafe { w.bits(1 << N) });
143 gpio.en1_clr().write(|w| unsafe { w.bits(1 << N) });
145 }
146
147 #[doc(hidden)]
148 #[inline(always)]
149 fn _is_high(&self) -> bool {
150 let gpio = unsafe { &*gpiox_ptr::<P>() };
152 gpio.in_().read().gpio_in().bits() & (1 << N) != 0
153 }
154
155 #[doc(hidden)]
156 #[inline(always)]
157 fn _is_low(&self) -> bool {
158 let gpio = unsafe { &*gpiox_ptr::<P>() };
160 gpio.in_().read().gpio_in().bits() & (1 << N) == 0
161 }
162
163 #[doc(hidden)]
164 #[inline(always)]
165 fn _set_high(&mut self) {
166 let gpio = unsafe { &*gpiox_ptr::<P>() };
168 gpio.out_set().write(|w| unsafe { w.bits(1 << N) });
169 }
170
171 #[doc(hidden)]
172 #[inline(always)]
173 fn _set_low(&mut self) {
174 let gpio = unsafe { &*gpiox_ptr::<P>() };
176 gpio.out_clr().write(|w| unsafe { w.bits(1 << N) });
177 }
178
179 #[doc(hidden)]
180 #[inline(always)]
181 fn _is_set_high(&self) -> bool {
182 let gpio = unsafe { &*gpiox_ptr::<P>() };
184 gpio.out().read().bits() & (1 << N) != 0
185 }
186
187 #[doc(hidden)]
188 #[inline(always)]
189 fn _is_set_low(&self) -> bool {
190 let gpio = unsafe { &*gpiox_ptr::<P>() };
192 gpio.out().read().bits() & (1 << N) == 0
193 }
194
195 #[inline(always)]
197 pub fn is_high(&self) -> bool {
198 self._is_high()
199 }
200
201 #[inline(always)]
203 pub fn is_low(&self) -> bool {
204 self._is_low()
205 }
206}
207
208impl<const P: u8, const N: u8> Pin<P, N, Input> {
210 #[inline(always)]
212 pub fn into_input_output(self) -> Pin<P, N, InputOutput> {
213 let mut pin = Pin::<P, N, InputOutput>::new();
215 pin._output_enable();
216 pin
217 }
218
219 #[inline(always)]
221 pub fn into_af1(self) -> Pin<P, N, Af1> {
222 let mut pin = Pin::<P, N, Af1>::new();
223 pin._into_af1();
224 pin
225 }
226
227 #[inline(always)]
229 pub fn into_af2(self) -> Pin<P, N, Af2> {
230 let mut pin = Pin::<P, N, Af2>::new();
231 pin._into_af2();
232 pin
233 }
234}
235
236impl<const P: u8, const N: u8> Pin<P, N, InputOutput> {
238 #[inline(always)]
240 pub fn into_input(self) -> Pin<P, N, Input> {
241 let mut pin = Pin::<P, N, Input>::new();
243 pin._output_disable();
244 pin
245 }
246
247 #[inline(always)]
249 pub fn set_high(&mut self) {
250 self._set_high();
251 }
252
253 #[inline(always)]
255 pub fn set_low(&mut self) {
256 self._set_low();
257 }
258
259 #[inline(always)]
261 pub fn is_set_high(&self) -> bool {
262 self._is_set_high()
263 }
264
265 #[inline(always)]
267 pub fn is_set_low(&self) -> bool {
268 self._is_set_low()
269 }
270
271 #[inline(always)]
273 pub fn set_power_vddio(&mut self) {
274 let gpio = unsafe { &*gpiox_ptr::<P>() };
275 gpio.vssel()
276 .modify(|r, w| unsafe { w.bits(r.bits() & !(1 << N)) });
277 }
278
279 #[inline(always)]
281 pub fn set_power_vddioh(&mut self) {
282 let gpio = unsafe { &*gpiox_ptr::<P>() };
283 gpio.vssel()
284 .modify(|r, w| unsafe { w.bits(r.bits() | (1 << N)) });
285 }
286}
287
288impl<const P: u8, const N: u8, MODE: PinMode> ErrorType for Pin<P, N, MODE> {
290 type Error = core::convert::Infallible;
291}
292
293impl<const P: u8, const N: u8, MODE: PinMode> InputPin for Pin<P, N, MODE> {
295 #[inline(always)]
296 fn is_high(&mut self) -> Result<bool, Self::Error> {
297 Ok(self._is_high())
298 }
299
300 #[inline(always)]
301 fn is_low(&mut self) -> Result<bool, Self::Error> {
302 Ok(self._is_low())
303 }
304}
305
306impl<const P: u8, const N: u8> OutputPin for Pin<P, N, InputOutput> {
308 #[inline(always)]
309 fn set_high(&mut self) -> Result<(), Self::Error> {
310 self._set_high();
311 Ok(())
312 }
313
314 #[inline(always)]
315 fn set_low(&mut self) -> Result<(), Self::Error> {
316 self._set_low();
317 Ok(())
318 }
319}
320
321impl<const P: u8, const N: u8> StatefulOutputPin for Pin<P, N, InputOutput> {
323 #[inline(always)]
324 fn is_set_high(&mut self) -> Result<bool, Self::Error> {
325 Ok(self._is_set_high())
326 }
327
328 #[inline(always)]
329 fn is_set_low(&mut self) -> Result<bool, Self::Error> {
330 Ok(self._is_set_low())
331 }
332}
333
334macro_rules! gpio {
342 ($MODULE_PAC:ident, $MODULE_HAL:ident, $GCR_TYPE:ident, $PORT_NUM:expr, [$($PIN_NUM:literal),*]) => {
343 paste!{
344 pub mod $MODULE_HAL {
345 pub struct Parts {
347 $(
348 pub [<p $PORT_NUM _ $PIN_NUM>]: [<P $PORT_NUM _ $PIN_NUM>],
349 )+
350 }
351
352 pub struct GpioPeripheral {
382 _gpio: $crate::pac::$MODULE_PAC,
383 }
384
385 impl GpioPeripheral {
386 pub fn new(gpio: $crate::pac::$MODULE_PAC, reg: &mut crate::gcr::GcrRegisters) -> Self {
388 use crate::gcr::ClockForPeripheral;
390 unsafe { gpio.enable_clock(&mut reg.$GCR_TYPE); };
391 Self {
392 _gpio: gpio,
393 }
394 }
395 pub fn split(self) -> Parts {
397 Parts {
398 $(
399 [<p $PORT_NUM _ $PIN_NUM>]: [<P $PORT_NUM _ $PIN_NUM>]::new(),
400 )+
401 }
402 }
403 }
404
405 $(
412 #[doc=stringify!([<P $PORT_NUM _ $PIN_NUM>])]
413 #[doc=" pin"]
414 pub type [<P $PORT_NUM _ $PIN_NUM>] = super::Pin<$PORT_NUM, $PIN_NUM>;
415 )+
416 }
417
418 pub use $MODULE_HAL::GpioPeripheral as $MODULE_PAC;
420 }
421 };
422}
423
424gpio!(
425 Gpio0,
426 gpio0,
427 gcr,
428 0,
429 [
430 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
431 25, 26, 27, 28, 29, 30
432 ]
433);
434gpio!(Gpio1, gpio1, gcr, 1, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
435gpio!(Gpio2, gpio2, lpgcr, 2, [0, 1, 2, 3, 4, 5, 6, 7]);
436
437#[inline(always)]
439const fn gpiox_ptr<const P: u8>() -> *const crate::pac::gpio0::RegisterBlock {
440 match P {
441 0 => crate::pac::Gpio0::ptr(),
442 1 => crate::pac::Gpio1::ptr(),
443 2 => crate::pac::Gpio2::ptr(),
444 _ => panic!("Invalid GPIO port number"),
445 }
446}