1use core::marker::PhantomData;
2
3use void::Void;
4
5use crate::{
6 hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin, PinState},
7 pac::{gpio, GPIO as P0},
8};
9
10pub struct Disconnected;
12
13pub struct Input<MODE> {
15 _mode: PhantomData<MODE>,
16}
17
18pub struct Floating;
20pub struct PullDown;
22pub struct PullUp;
24
25pub struct Output;
27
28pub struct AlternateFunction<const PID: u8, const PUPD: u8>;
30
31macro_rules! alternate_functions {
32 (
33 $($AF:ident: ($pid:literal, $pupd:literal)),+
34 ) => {
35 $(
36 paste::paste! {
37 pub type [<Af $AF>] = AlternateFunction<$pid, $pupd>;
38 }
39 )+
40 };
41}
42
43alternate_functions! {
44 Uart1Rx: ( 1, 0b01),
45 Uart1Tx: ( 2, 0b01),
46 Uart2Rx: ( 3, 0b01),
47 Uart2Tx: ( 4, 0b01),
48 SysClk: ( 5, 0b01),
49 LpClk: ( 6, 0b01),
50 I2cScl: ( 9, 0b00),
51 I2cSda: (10, 0b00),
52 Pwm5: (11, 0b11),
53 Pwm6: (12, 0b11),
54 Pwm7: (13, 0b11),
55 Adc: (15, 0b01),
56 Pwm0: (16, 0b11),
57 Pwm1: (17, 0b11),
58 BleDiag: (18, 0b01),
59 Uart1Ctsn: (19, 0b01),
60 Uart1Rtsn: (20, 0b01),
61 Pwm2: (23, 0b11),
62 Pwm3: (24, 0b11),
63 Pwm4: (25, 0b11),
64 SpiDi: (26, 0b01),
65 SpiDo: (27, 0b01),
66 SpiClk: (28, 0b01),
67 SpiCsn0: (29, 0b01),
68 SpiCsn1: (30, 0b01)
69}
70
71pub struct Pin<MODE> {
78 pin: u8,
79 _mode: PhantomData<MODE>,
80}
81
82impl<MODE> Pin<MODE> {
83 fn new(pin: u8) -> Self {
84 Self {
85 pin,
86 _mode: PhantomData,
87 }
88 }
89
90 #[inline]
91 pub fn pin(&self) -> u8 {
92 self.pin
93 }
94
95 fn block(&self) -> &gpio::RegisterBlock {
96 unsafe { &*P0::ptr() }
97 }
98
99 pub(crate) fn pin_mode(&self) -> &gpio::P0_MODE_REG {
101 &self.block().p0_mode_reg[self.pin as usize]
102 }
103
104 pub fn into_floating_input(self) -> Pin<Input<Floating>> {
106 self.pin_mode().write(|w| {
107 unsafe {
108 w.pupd().bits(0b00);
109 w.pid().bits(0);
110 }
111 w
112 });
113
114 Pin {
115 _mode: PhantomData,
116 pin: self.pin,
117 }
118 }
119 pub fn into_pullup_input(self) -> Pin<Input<PullUp>> {
120 self.pin_mode().write(|w| {
121 unsafe {
122 w.pupd().bits(0b01);
123 w.pid().bits(0);
124 }
125 w
126 });
127
128 Pin {
129 _mode: PhantomData,
130 pin: self.pin,
131 }
132 }
133
134 pub fn into_pulldown_input(self) -> Pin<Input<PullDown>> {
135 self.pin_mode().write(|w| {
136 unsafe {
137 w.pupd().bits(0b10);
138 w.pid().bits(0);
139 }
140 w
141 });
142
143 Pin {
144 _mode: PhantomData,
145 pin: self.pin,
146 }
147 }
148
149 pub fn into_output(self, initial_output: PinState) -> Pin<Output> {
151 let mut pin = Pin {
152 _mode: PhantomData,
153 pin: self.pin,
154 };
155
156 match initial_output {
157 PinState::Low => pin.set_low().unwrap(),
158 PinState::High => pin.set_high().unwrap(),
159 }
160
161 self.pin_mode().write(|w| {
162 unsafe {
163 w.pupd().bits(0b11);
164 w.pid().bits(0);
165 }
166 w
167 });
168
169 pin
170 }
171
172 pub fn into_alternate<const PID: u8, const PUPD: u8>(
173 self,
174 ) -> Pin<AlternateFunction<PID, PUPD>> {
175 self.pin_mode().write(|w| {
176 unsafe {
177 w.pupd().bits(PUPD);
178 w.pid().bits(PID);
179 }
180 w
181 });
182
183 Pin {
184 _mode: PhantomData,
185 pin: self.pin,
186 }
187 }
188
189 pub fn into_disconnected(self) -> Pin<Disconnected> {
194 self.pin_mode().reset();
196
197 Pin {
198 _mode: PhantomData,
199 pin: self.pin,
200 }
201 }
202}
203
204impl<MODE> InputPin for Pin<Input<MODE>> {
205 type Error = Void;
206
207 fn is_high(&self) -> Result<bool, Self::Error> {
208 self.is_low().map(|v| !v)
209 }
210
211 fn is_low(&self) -> Result<bool, Self::Error> {
212 Ok(self.block().p0_data_reg.read().bits() & (1 << self.pin()) == 0)
213 }
214}
215
216impl OutputPin for Pin<Output> {
217 type Error = Void;
218
219 fn set_high(&mut self) -> Result<(), Self::Error> {
221 unsafe {
222 self.block()
223 .p0_set_data_reg
224 .write(|w| w.bits(1u16 << self.pin()));
225 }
226 Ok(())
227 }
228
229 fn set_low(&mut self) -> Result<(), Self::Error> {
231 unsafe {
232 self.block()
233 .p0_reset_data_reg
234 .write(|w| w.bits(1u16 << self.pin()));
235 }
236 Ok(())
237 }
238}
239
240impl StatefulOutputPin for Pin<Output> {
241 fn is_set_high(&self) -> Result<bool, Self::Error> {
243 self.is_set_low().map(|v| !v)
244 }
245
246 fn is_set_low(&self) -> Result<bool, Self::Error> {
248 Ok(self.block().p0_data_reg.read().bits() & (1 << self.pin()) == 0)
251 }
252}
253
254macro_rules! gpio {
255 (
256 $PX:ident, $pxsvd:ident, $px:ident, [
257 $($PXi:ident: ($pxi:ident, $i:expr, $MODE:ty),)+
258 ]
259 ) => {
260 pub mod $px {
262 use super::{
263 Pin,
264
265 Floating,
266 Disconnected,
267 Input,
268 PinState,
269 Output,
270 PullDown,
271 PullUp,
272 AlternateFunction,
273
274 PhantomData,
275 $PX
276 };
277
278 use crate::hal::digital::v2::{OutputPin, StatefulOutputPin, InputPin};
279 use void::Void;
280
281
282 pub struct Parts {
288 $(
289 pub $pxi: $PXi<$MODE>,
291 )+
292 }
293
294 impl Parts {
295 pub fn new(_gpio: $PX) -> Self {
296 Self {
297 $(
298 $pxi: $PXi {
299 _mode: PhantomData,
300 },
301 )+
302 }
303 }
304 }
305
306 $(
311 pub struct $PXi<MODE> {
312 _mode: PhantomData<MODE>,
313 }
314
315
316 impl<MODE> $PXi<MODE> {
317 pub fn into_floating_input(self) -> $PXi<Input<Floating>> {
319 unsafe { &(*$PX::ptr()).p0_mode_reg[$i] }.write(|w| {
320 unsafe {
321 w.pupd().bits(0b00);
322 w.pid().bits(0);
323 }
324 w
325 });
326
327 $PXi {
328 _mode: PhantomData,
329 }
330 }
331 pub fn into_pulldown_input(self) -> $PXi<Input<PullDown>> {
332 unsafe { &(*$PX::ptr()).p0_mode_reg[$i] }.write(|w| {
333 unsafe {
334 w.pupd().bits(0b01);
335 w.pid().bits(0);
336 }
337 w
338 });
339
340 $PXi {
341 _mode: PhantomData,
342 }
343 }
344 pub fn into_pullup_input(self) -> $PXi<Input<PullUp>> {
345 unsafe { &(*$PX::ptr()).p0_mode_reg[$i] }.write(|w| {
346 unsafe {
347 w.pupd().bits(0b10);
348 w.pid().bits(0);
349 }
350 w
351 });
352
353 $PXi {
354 _mode: PhantomData,
355 }
356 }
357
358 pub fn into_output(self, initial_output: PinState)
360 -> $PXi<Output>
361 {
362 let mut pin = $PXi {
363 _mode: PhantomData,
364 };
365
366 match initial_output {
367 PinState::Low => pin.set_low().unwrap(),
368 PinState::High => pin.set_high().unwrap(),
369 }
370
371 unsafe { &(*$PX::ptr()).p0_mode_reg[$i] }.write(|w| {
372 unsafe {
373 w.pupd().bits(0b11);
374 w.pid().bits(0);
375 }
376 w
377 });
378
379 pin
380 }
381
382 pub fn into_alternate<const PID: u8, const PUPD: u8>(self) -> $PXi<AlternateFunction<PID, PUPD>> {
383 let pin = $PXi {
384 _mode: PhantomData,
385 };
386
387 unsafe { &(*$PX::ptr()).p0_mode_reg[$i] }.write(|w| {
388 unsafe {
389 w.pupd().bits(PUPD);
390 w.pid().bits(PID);
391 }
392 w
393 });
394
395 pin
396 }
397
398
399 pub fn into_disconnected(self) -> $PXi<Disconnected> {
404 unsafe { &(*$PX::ptr()).p0_mode_reg[$i] }.reset();
406
407 $PXi {
408 _mode: PhantomData,
409 }
410 }
411
412 pub fn degrade(self) -> Pin<MODE> {
414 Pin::new($i)
415 }
416 }
417
418 impl<MODE> InputPin for $PXi<Input<MODE>> {
419 type Error = Void;
420
421 fn is_high(&self) -> Result<bool, Self::Error> {
422 self.is_low().map(|v| !v)
423 }
424
425 fn is_low(&self) -> Result<bool, Self::Error> {
426 Ok(unsafe { ((*$PX::ptr()).p0_data_reg.read().bits() & (1 << $i)) == 0 })
427 }
428 }
429
430 impl<MODE> From<$PXi<MODE>> for Pin<MODE> {
431 fn from(value: $PXi<MODE>) -> Self {
432 value.degrade()
433 }
434 }
435
436 impl OutputPin for $PXi<Output> {
437 type Error = Void;
438
439 fn set_high(&mut self) -> Result<(), Self::Error> {
441 unsafe { (*$PX::ptr()).p0_set_data_reg.write(|w| w.bits(1u16 << $i)); }
442 Ok(())
443 }
444
445 fn set_low(&mut self) -> Result<(), Self::Error> {
447 unsafe { (*$PX::ptr()).p0_reset_data_reg.write(|w| w.bits(1u16 << $i)); }
448 Ok(())
449 }
450 }
451
452 impl StatefulOutputPin for $PXi<Output> {
453 fn is_set_high(&self) -> Result<bool, Self::Error> {
455 self.is_set_low().map(|v| !v)
456 }
457
458 fn is_set_low(&self) -> Result<bool, Self::Error> {
460 Ok(unsafe { ((*$PX::ptr()).p0_data_reg.read().bits() & (1 << $i)) == 0 })
463 }
464 }
465 )+
466 }
467 }
468}
469
470gpio!(P0, p0, p0, [
474 P0_00: (p0_00, 0, Disconnected),
475 P0_01: (p0_01, 1, Disconnected),
476 P0_02: (p0_02, 2, Disconnected),
477 P0_03: (p0_03, 3, Disconnected),
478 P0_04: (p0_04, 4, Disconnected),
479 P0_05: (p0_05, 5, Disconnected),
480 P0_06: (p0_06, 6, Disconnected),
481 P0_07: (p0_07, 7, Disconnected),
482 P0_08: (p0_08, 8, Disconnected),
483 P0_09: (p0_09, 9, Disconnected),
484 P0_10: (p0_10, 10, Disconnected),
485 P0_11: (p0_11, 11, Disconnected),
486]);