1use core::cell::Cell;
3use core::convert::Infallible;
4use core::marker::PhantomData;
5use critical_section::Mutex;
6use embedded_hal::digital::{ErrorType, InputPin, OutputPin, StatefulOutputPin};
7
8use mik32_pac::Peripherals;
9
10const GPIO_IRQ_LINE_SHIFT: u32 = 4;
11const GPIO_IRQ_LINE_MUX_MASK: u32 = 0b1111;
12const GPIO_MODE_BIT_LEVEL: u32 = 1 << 0;
13const GPIO_MODE_BIT_EDGE: u32 = 1 << 1;
14const GPIO_MODE_BIT_ANY_EDGE: u32 = 1 << 2;
15
16static CURRENT_IRQ_LINE_MUX: Mutex<Cell<u32>> = Mutex::new(Cell::new(0));
17
18pub struct Floating;
20
21pub struct PullDown;
23
24pub struct PullUp;
26
27pub struct Output;
29
30pub struct Func2Mode;
32pub struct Func3Mode;
33
34pub struct Analog;
36
37#[derive(Debug, Clone, Copy, PartialEq, Eq)]
38#[repr(u32)]
39pub enum DriveStrength {
40 Ma2 = 0b00,
41 Ma4 = 0b01,
42 Ma8 = 0b10,
43}
44
45impl DriveStrength {
46 #[inline(always)]
47 const fn bits(self) -> u32 {
48 self as u32
49 }
50}
51
52#[derive(Debug, Clone, Copy, PartialEq, Eq)]
53#[repr(u8)]
54pub enum InterruptLine {
55 Line0 = 0,
56 Line1 = 1,
57 Line2 = 2,
58 Line3 = 3,
59 Line4 = 4,
60 Line5 = 5,
61 Line6 = 6,
62 Line7 = 7,
63}
64
65impl InterruptLine {
66 #[inline(always)]
67 const fn index(self) -> u32 {
68 self as u32
69 }
70
71 #[inline(always)]
72 const fn mask(self) -> u32 {
73 1u32 << self.index()
74 }
75
76 #[inline(always)]
77 const fn mux_shift(self) -> u32 {
78 GPIO_IRQ_LINE_SHIFT * self.index()
79 }
80}
81
82#[derive(Debug, Clone, Copy, PartialEq, Eq)]
83#[repr(u8)]
84pub enum InterruptMode {
85 Low = 0,
86 High = GPIO_MODE_BIT_LEVEL as u8,
87 Falling = GPIO_MODE_BIT_EDGE as u8,
88 Rising = (GPIO_MODE_BIT_LEVEL | GPIO_MODE_BIT_EDGE) as u8,
89 Change = (GPIO_MODE_BIT_EDGE | GPIO_MODE_BIT_ANY_EDGE) as u8,
90}
91
92impl InterruptMode {
93 #[inline(always)]
94 const fn bits(self) -> u32 {
95 self as u32
96 }
97}
98
99#[derive(Debug, Clone, Copy, PartialEq, Eq)]
100#[repr(u8)]
101pub enum LineConfig {
102 Line0Port0_0 = 0 | (0 << GPIO_IRQ_LINE_SHIFT),
103 Line0Port0_8 = 1 | (0 << GPIO_IRQ_LINE_SHIFT),
104 Line0Port1_0 = 2 | (0 << GPIO_IRQ_LINE_SHIFT),
105 Line0Port1_8 = 3 | (0 << GPIO_IRQ_LINE_SHIFT),
106 Line0Port2_0 = 4 | (0 << GPIO_IRQ_LINE_SHIFT),
107 Line0Port0_4 = 5 | (0 << GPIO_IRQ_LINE_SHIFT),
108 Line0Port0_12 = 6 | (0 << GPIO_IRQ_LINE_SHIFT),
109 Line0Port1_4 = 7 | (0 << GPIO_IRQ_LINE_SHIFT),
110 Line0Port1_12 = 8 | (0 << GPIO_IRQ_LINE_SHIFT),
111 Line0Port2_4 = 9 | (0 << GPIO_IRQ_LINE_SHIFT),
112
113 Line1Port0_1 = 0 | (1 << GPIO_IRQ_LINE_SHIFT),
114 Line1Port0_9 = 1 | (1 << GPIO_IRQ_LINE_SHIFT),
115 Line1Port1_1 = 2 | (1 << GPIO_IRQ_LINE_SHIFT),
116 Line1Port1_9 = 3 | (1 << GPIO_IRQ_LINE_SHIFT),
117 Line1Port2_1 = 4 | (1 << GPIO_IRQ_LINE_SHIFT),
118 Line1Port0_5 = 5 | (1 << GPIO_IRQ_LINE_SHIFT),
119 Line1Port0_13 = 6 | (1 << GPIO_IRQ_LINE_SHIFT),
120 Line1Port1_5 = 7 | (1 << GPIO_IRQ_LINE_SHIFT),
121 Line1Port1_13 = 8 | (1 << GPIO_IRQ_LINE_SHIFT),
122 Line1Port2_5 = 9 | (1 << GPIO_IRQ_LINE_SHIFT),
123
124 Line2Port0_2 = 0 | (2 << GPIO_IRQ_LINE_SHIFT),
125 Line2Port0_10 = 1 | (2 << GPIO_IRQ_LINE_SHIFT),
126 Line2Port1_2 = 2 | (2 << GPIO_IRQ_LINE_SHIFT),
127 Line2Port1_10 = 3 | (2 << GPIO_IRQ_LINE_SHIFT),
128 Line2Port2_2 = 4 | (2 << GPIO_IRQ_LINE_SHIFT),
129 Line2Port0_6 = 5 | (2 << GPIO_IRQ_LINE_SHIFT),
130 Line2Port0_14 = 6 | (2 << GPIO_IRQ_LINE_SHIFT),
131 Line2Port1_6 = 7 | (2 << GPIO_IRQ_LINE_SHIFT),
132 Line2Port1_14 = 8 | (2 << GPIO_IRQ_LINE_SHIFT),
133 Line2Port2_6 = 9 | (2 << GPIO_IRQ_LINE_SHIFT),
134
135 Line3Port0_3 = 0 | (3 << GPIO_IRQ_LINE_SHIFT),
136 Line3Port0_11 = 1 | (3 << GPIO_IRQ_LINE_SHIFT),
137 Line3Port1_3 = 2 | (3 << GPIO_IRQ_LINE_SHIFT),
138 Line3Port1_11 = 3 | (3 << GPIO_IRQ_LINE_SHIFT),
139 Line3Port2_3 = 4 | (3 << GPIO_IRQ_LINE_SHIFT),
140 Line3Port0_7 = 5 | (3 << GPIO_IRQ_LINE_SHIFT),
141 Line3Port0_15 = 6 | (3 << GPIO_IRQ_LINE_SHIFT),
142 Line3Port1_7 = 7 | (3 << GPIO_IRQ_LINE_SHIFT),
143 Line3Port1_15 = 8 | (3 << GPIO_IRQ_LINE_SHIFT),
144 Line3Port2_7 = 9 | (3 << GPIO_IRQ_LINE_SHIFT),
145
146 Line4Port0_4 = 0 | (4 << GPIO_IRQ_LINE_SHIFT),
147 Line4Port0_12 = 1 | (4 << GPIO_IRQ_LINE_SHIFT),
148 Line4Port1_4 = 2 | (4 << GPIO_IRQ_LINE_SHIFT),
149 Line4Port1_12 = 3 | (4 << GPIO_IRQ_LINE_SHIFT),
150 Line4Port2_4 = 4 | (4 << GPIO_IRQ_LINE_SHIFT),
151 Line4Port0_0 = 5 | (4 << GPIO_IRQ_LINE_SHIFT),
152 Line4Port0_8 = 6 | (4 << GPIO_IRQ_LINE_SHIFT),
153 Line4Port1_0 = 7 | (4 << GPIO_IRQ_LINE_SHIFT),
154 Line4Port1_8 = 8 | (4 << GPIO_IRQ_LINE_SHIFT),
155 Line4Port2_0 = 9 | (4 << GPIO_IRQ_LINE_SHIFT),
156
157 Line5Port0_5 = 0 | (5 << GPIO_IRQ_LINE_SHIFT),
158 Line5Port0_13 = 1 | (5 << GPIO_IRQ_LINE_SHIFT),
159 Line5Port1_5 = 2 | (5 << GPIO_IRQ_LINE_SHIFT),
160 Line5Port1_13 = 3 | (5 << GPIO_IRQ_LINE_SHIFT),
161 Line5Port2_5 = 4 | (5 << GPIO_IRQ_LINE_SHIFT),
162 Line5Port0_1 = 5 | (5 << GPIO_IRQ_LINE_SHIFT),
163 Line5Port0_9 = 6 | (5 << GPIO_IRQ_LINE_SHIFT),
164 Line5Port1_1 = 7 | (5 << GPIO_IRQ_LINE_SHIFT),
165 Line5Port1_9 = 8 | (5 << GPIO_IRQ_LINE_SHIFT),
166 Line5Port2_1 = 9 | (5 << GPIO_IRQ_LINE_SHIFT),
167
168 Line6Port0_6 = 0 | (6 << GPIO_IRQ_LINE_SHIFT),
169 Line6Port0_14 = 1 | (6 << GPIO_IRQ_LINE_SHIFT),
170 Line6Port1_6 = 2 | (6 << GPIO_IRQ_LINE_SHIFT),
171 Line6Port1_14 = 3 | (6 << GPIO_IRQ_LINE_SHIFT),
172 Line6Port2_6 = 4 | (6 << GPIO_IRQ_LINE_SHIFT),
173 Line6Port0_2 = 5 | (6 << GPIO_IRQ_LINE_SHIFT),
174 Line6Port0_10 = 6 | (6 << GPIO_IRQ_LINE_SHIFT),
175 Line6Port1_2 = 7 | (6 << GPIO_IRQ_LINE_SHIFT),
176 Line6Port1_10 = 8 | (6 << GPIO_IRQ_LINE_SHIFT),
177 Line6Port2_2 = 9 | (6 << GPIO_IRQ_LINE_SHIFT),
178
179 Line7Port0_7 = 0 | (7 << GPIO_IRQ_LINE_SHIFT),
180 Line7Port0_15 = 1 | (7 << GPIO_IRQ_LINE_SHIFT),
181 Line7Port1_7 = 2 | (7 << GPIO_IRQ_LINE_SHIFT),
182 Line7Port1_15 = 3 | (7 << GPIO_IRQ_LINE_SHIFT),
183 Line7Port2_7 = 4 | (7 << GPIO_IRQ_LINE_SHIFT),
184 Line7Port0_3 = 5 | (7 << GPIO_IRQ_LINE_SHIFT),
185 Line7Port0_11 = 6 | (7 << GPIO_IRQ_LINE_SHIFT),
186 Line7Port1_3 = 7 | (7 << GPIO_IRQ_LINE_SHIFT),
187 Line7Port1_11 = 8 | (7 << GPIO_IRQ_LINE_SHIFT),
188 Line7Port2_3 = 9 | (7 << GPIO_IRQ_LINE_SHIFT),
189}
190
191impl LineConfig {
192 #[inline(always)]
193 const fn bits(self) -> u32 {
194 self as u32
195 }
196
197 #[inline(always)]
198 const fn line(self) -> InterruptLine {
199 match self.bits() >> GPIO_IRQ_LINE_SHIFT {
200 0 => InterruptLine::Line0,
201 1 => InterruptLine::Line1,
202 2 => InterruptLine::Line2,
203 3 => InterruptLine::Line3,
204 4 => InterruptLine::Line4,
205 5 => InterruptLine::Line5,
206 6 => InterruptLine::Line6,
207 _ => InterruptLine::Line7,
208 }
209 }
210
211 #[inline(always)]
212 const fn mux(self) -> u32 {
213 self.bits() & GPIO_IRQ_LINE_MUX_MASK
214 }
215}
216
217pub struct GpioPort<const P: u8>;
218
219pub struct GpioInterrupts;
220
221pub fn init_port<const P: u8>() -> GpioPort<P> {
222 let p = unsafe { Peripherals::steal() };
223 enable_gpio_pin_clocks::<P>(&p);
224 GpioPort
225}
226
227pub fn init_interrupts() -> GpioInterrupts {
228 let p = unsafe { Peripherals::steal() };
229 enable_gpio_irq_clock(&p);
230 GpioInterrupts
231}
232
233pub fn init_interrupt_line(config: LineConfig, mode: InterruptMode) {
234 let p = unsafe { Peripherals::steal() };
235
236 let line = config.line();
237 let line_mask = line.mask();
238 let mode_bits = mode.bits();
239
240 critical_section::with(|cs| {
241 let mux = CURRENT_IRQ_LINE_MUX.borrow(cs);
242 let shift = line.mux_shift();
243 let mut current = mux.get();
244
245 current &= !(GPIO_IRQ_LINE_MUX_MASK << shift);
246 current |= config.mux() << shift;
247
248 mux.set(current);
249 p.gpio_irq.line_mux().write(|w| unsafe { w.bits(current) });
250 });
251
252 if mode_bits & GPIO_MODE_BIT_LEVEL != 0 {
253 p.gpio_irq
254 .level_set()
255 .write(|w| unsafe { w.bits(line_mask) });
256 } else {
257 p.gpio_irq
258 .level_clear()
259 .write(|w| unsafe { w.bits(line_mask) });
260 }
261
262 if mode_bits & GPIO_MODE_BIT_EDGE != 0 {
263 p.gpio_irq.edge().write(|w| unsafe { w.bits(line_mask) });
264 } else {
265 p.gpio_irq.level().write(|w| unsafe { w.bits(line_mask) });
266 }
267
268 if mode_bits & GPIO_MODE_BIT_ANY_EDGE != 0 {
269 p.gpio_irq
270 .any_edge_set()
271 .write(|w| unsafe { w.bits(line_mask) });
272 } else {
273 p.gpio_irq
274 .any_edge_clear()
275 .write(|w| unsafe { w.bits(line_mask) });
276 }
277
278 enable_interrupt_line(line);
279}
280
281pub fn deinit_interrupt_line(line: InterruptLine) {
282 let p = unsafe { Peripherals::steal() };
283
284 let line_mask = line.mask();
285
286 disable_interrupt_line(line);
287
288 critical_section::with(|cs| {
289 let mux = CURRENT_IRQ_LINE_MUX.borrow(cs);
290 let shift = line.mux_shift();
291 let current = mux.get() & !(GPIO_IRQ_LINE_MUX_MASK << shift);
292
293 mux.set(current);
294 p.gpio_irq.line_mux().write(|w| unsafe { w.bits(current) });
295 });
296
297 p.gpio_irq.level().write(|w| unsafe { w.bits(line_mask) });
298 p.gpio_irq
299 .level_clear()
300 .write(|w| unsafe { w.bits(line_mask) });
301 p.gpio_irq
302 .any_edge_clear()
303 .write(|w| unsafe { w.bits(line_mask) });
304}
305
306#[inline(always)]
307pub fn enable_interrupt_line(line: InterruptLine) {
308 let p = unsafe { Peripherals::steal() };
309
310 p.gpio_irq
311 .enable_set()
312 .write(|w| unsafe { w.bits(line.mask()) });
313}
314
315#[inline(always)]
316pub fn disable_interrupt_line(line: InterruptLine) {
317 let p = unsafe { Peripherals::steal() };
318
319 p.gpio_irq
320 .enable_clear()
321 .write(|w| unsafe { w.bits(line.mask()) });
322}
323
324#[inline(always)]
325pub fn line_interrupt_state(line: InterruptLine) -> bool {
326 let p = unsafe { Peripherals::steal() };
327
328 p.gpio_irq.interrupt().read().bits() & line.mask() != 0
329}
330
331#[inline(always)]
332pub fn line_pin_state(line: InterruptLine) -> bool {
333 let p = unsafe { Peripherals::steal() };
334
335 p.gpio_irq.state().read().bits() & line.mask() != 0
336}
337
338#[inline(always)]
339pub fn clear_interrupt(line: InterruptLine) {
340 let p = unsafe { Peripherals::steal() };
341
342 p.gpio_irq.clear().write(|w| unsafe { w.bits(line.mask()) });
343}
344
345#[inline(always)]
346pub fn clear_interrupts() {
347 let p = unsafe { Peripherals::steal() };
348
349 p.gpio_irq.clear().write(|w| unsafe { w.bits(0xff) });
350}
351
352pub trait InterruptSource<const LINE: u8> {
353 const LINE_CONFIG: LineConfig;
354}
355
356pub struct InterruptPin<PIN, const LINE: u8>
357where
358 PIN: InterruptSource<LINE>,
359{
360 pin: PIN,
361}
362
363impl<PIN, const LINE: u8> InterruptPin<PIN, LINE>
364where
365 PIN: InterruptSource<LINE>,
366{
367 pub fn new(pin: PIN, mode: InterruptMode) -> Self {
368 init_interrupt_line(PIN::LINE_CONFIG, mode);
369 Self { pin }
370 }
371
372 pub fn release(self) -> PIN {
373 self.pin
374 }
375
376 pub const fn line_config(&self) -> LineConfig {
377 PIN::LINE_CONFIG
378 }
379
380 pub const fn line(&self) -> InterruptLine {
381 PIN::LINE_CONFIG.line()
382 }
383
384 pub fn enable(&self) {
385 enable_interrupt_line(self.line());
386 }
387
388 pub fn disable(&self) {
389 disable_interrupt_line(self.line());
390 }
391
392 pub fn is_pending(&self) -> bool {
393 line_interrupt_state(self.line())
394 }
395
396 pub fn is_high(&self) -> bool {
397 line_pin_state(self.line())
398 }
399
400 pub fn is_low(&self) -> bool {
401 !self.is_high()
402 }
403
404 pub fn clear_interrupt(&self) {
405 clear_interrupt(self.line());
406 }
407}
408
409macro_rules! impl_interrupt_source {
410 ($port:literal, $pin:literal, $line:literal, $config:ident) => {
411 impl<MODE> InterruptSource<$line> for Pin<$port, $pin, MODE> {
412 const LINE_CONFIG: LineConfig = LineConfig::$config;
413 }
414 };
415}
416
417impl_interrupt_source!(0, 0, 0, Line0Port0_0);
418impl_interrupt_source!(0, 8, 0, Line0Port0_8);
419impl_interrupt_source!(1, 0, 0, Line0Port1_0);
420impl_interrupt_source!(1, 8, 0, Line0Port1_8);
421impl_interrupt_source!(2, 0, 0, Line0Port2_0);
422impl_interrupt_source!(0, 4, 0, Line0Port0_4);
423impl_interrupt_source!(0, 12, 0, Line0Port0_12);
424impl_interrupt_source!(1, 4, 0, Line0Port1_4);
425impl_interrupt_source!(1, 12, 0, Line0Port1_12);
426impl_interrupt_source!(2, 4, 0, Line0Port2_4);
427
428impl_interrupt_source!(0, 1, 1, Line1Port0_1);
429impl_interrupt_source!(0, 9, 1, Line1Port0_9);
430impl_interrupt_source!(1, 1, 1, Line1Port1_1);
431impl_interrupt_source!(1, 9, 1, Line1Port1_9);
432impl_interrupt_source!(2, 1, 1, Line1Port2_1);
433impl_interrupt_source!(0, 5, 1, Line1Port0_5);
434impl_interrupt_source!(0, 13, 1, Line1Port0_13);
435impl_interrupt_source!(1, 5, 1, Line1Port1_5);
436impl_interrupt_source!(1, 13, 1, Line1Port1_13);
437impl_interrupt_source!(2, 5, 1, Line1Port2_5);
438
439impl_interrupt_source!(0, 2, 2, Line2Port0_2);
440impl_interrupt_source!(0, 10, 2, Line2Port0_10);
441impl_interrupt_source!(1, 2, 2, Line2Port1_2);
442impl_interrupt_source!(1, 10, 2, Line2Port1_10);
443impl_interrupt_source!(2, 2, 2, Line2Port2_2);
444impl_interrupt_source!(0, 6, 2, Line2Port0_6);
445impl_interrupt_source!(0, 14, 2, Line2Port0_14);
446impl_interrupt_source!(1, 6, 2, Line2Port1_6);
447impl_interrupt_source!(1, 14, 2, Line2Port1_14);
448impl_interrupt_source!(2, 6, 2, Line2Port2_6);
449
450impl_interrupt_source!(0, 3, 3, Line3Port0_3);
451impl_interrupt_source!(0, 11, 3, Line3Port0_11);
452impl_interrupt_source!(1, 3, 3, Line3Port1_3);
453impl_interrupt_source!(1, 11, 3, Line3Port1_11);
454impl_interrupt_source!(2, 3, 3, Line3Port2_3);
455impl_interrupt_source!(0, 7, 3, Line3Port0_7);
456impl_interrupt_source!(0, 15, 3, Line3Port0_15);
457impl_interrupt_source!(1, 7, 3, Line3Port1_7);
458impl_interrupt_source!(1, 15, 3, Line3Port1_15);
459impl_interrupt_source!(2, 7, 3, Line3Port2_7);
460
461impl_interrupt_source!(0, 4, 4, Line4Port0_4);
462impl_interrupt_source!(0, 12, 4, Line4Port0_12);
463impl_interrupt_source!(1, 4, 4, Line4Port1_4);
464impl_interrupt_source!(1, 12, 4, Line4Port1_12);
465impl_interrupt_source!(2, 4, 4, Line4Port2_4);
466impl_interrupt_source!(0, 0, 4, Line4Port0_0);
467impl_interrupt_source!(0, 8, 4, Line4Port0_8);
468impl_interrupt_source!(1, 0, 4, Line4Port1_0);
469impl_interrupt_source!(1, 8, 4, Line4Port1_8);
470impl_interrupt_source!(2, 0, 4, Line4Port2_0);
471
472impl_interrupt_source!(0, 5, 5, Line5Port0_5);
473impl_interrupt_source!(0, 13, 5, Line5Port0_13);
474impl_interrupt_source!(1, 5, 5, Line5Port1_5);
475impl_interrupt_source!(1, 13, 5, Line5Port1_13);
476impl_interrupt_source!(2, 5, 5, Line5Port2_5);
477impl_interrupt_source!(0, 1, 5, Line5Port0_1);
478impl_interrupt_source!(0, 9, 5, Line5Port0_9);
479impl_interrupt_source!(1, 1, 5, Line5Port1_1);
480impl_interrupt_source!(1, 9, 5, Line5Port1_9);
481impl_interrupt_source!(2, 1, 5, Line5Port2_1);
482
483impl_interrupt_source!(0, 6, 6, Line6Port0_6);
484impl_interrupt_source!(0, 14, 6, Line6Port0_14);
485impl_interrupt_source!(1, 6, 6, Line6Port1_6);
486impl_interrupt_source!(1, 14, 6, Line6Port1_14);
487impl_interrupt_source!(2, 6, 6, Line6Port2_6);
488impl_interrupt_source!(0, 2, 6, Line6Port0_2);
489impl_interrupt_source!(0, 10, 6, Line6Port0_10);
490impl_interrupt_source!(1, 2, 6, Line6Port1_2);
491impl_interrupt_source!(1, 10, 6, Line6Port1_10);
492impl_interrupt_source!(2, 2, 6, Line6Port2_2);
493
494impl_interrupt_source!(0, 7, 7, Line7Port0_7);
495impl_interrupt_source!(0, 15, 7, Line7Port0_15);
496impl_interrupt_source!(1, 7, 7, Line7Port1_7);
497impl_interrupt_source!(1, 15, 7, Line7Port1_15);
498impl_interrupt_source!(2, 7, 7, Line7Port2_7);
499impl_interrupt_source!(0, 3, 7, Line7Port0_3);
500impl_interrupt_source!(0, 11, 7, Line7Port0_11);
501impl_interrupt_source!(1, 3, 7, Line7Port1_3);
502impl_interrupt_source!(1, 11, 7, Line7Port1_11);
503impl_interrupt_source!(2, 3, 7, Line7Port2_3);
504
505pub struct Pin<const P: u8, const N: u8, MODE = Floating> {
506 _mode: PhantomData<MODE>,
507}
508
509impl<const P: u8, const N: u8, MODE> Pin<P, N, MODE> {
510 pub const fn new() -> Self {
511 Self { _mode: PhantomData }
512 }
513
514 pub fn set_drive_strength(&mut self, drive_strength: DriveStrength) {
515 let p = unsafe { Peripherals::steal() };
516
517 set_drive_strength::<P, N>(&p, drive_strength);
518 }
519
520 pub fn with_drive_strength(mut self, drive_strength: DriveStrength) -> Self {
521 self.set_drive_strength(drive_strength);
522 self
523 }
524}
525
526pub trait OutputPermitted {}
527pub trait SerialPermitted {}
528pub trait TimerSerialPermitted {}
529pub trait AnalogPermitted {}
530pub trait InputMode {}
531
532impl InputMode for Floating {}
533impl InputMode for PullDown {}
534impl InputMode for PullUp {}
535
536impl<const P: u8, const N: u8, MODE> Pin<P, N, MODE>
537where
538 MODE: InputMode,
539{
540 pub fn into_interrupt_pin<const LINE: u8>(self, mode: InterruptMode) -> InterruptPin<Self, LINE>
541 where
542 Self: InterruptSource<LINE>,
543 {
544 InterruptPin::new(self, mode)
545 }
546}
547
548#[inline(always)]
549fn set_gpio_function<const P: u8, const N: u8>(p: &Peripherals) {
550 let shift = 2 * N;
551 let mask = 0b11u32 << shift;
552
553 match P {
554 0 => p
555 .pad_config
556 .pad0_cfg()
557 .modify(|r, w| unsafe { w.bits(r.bits() & !mask) }),
558 1 => p
559 .pad_config
560 .pad1_cfg()
561 .modify(|r, w| unsafe { w.bits(r.bits() & !mask) }),
562 2 => p
563 .pad_config
564 .pad2_cfg()
565 .modify(|r, w| unsafe { w.bits(r.bits() & !mask) }),
566 _ => panic!("Invalid port number {}", P),
567 };
568}
569
570#[inline(always)]
571fn set_alternate_function<const P: u8, const N: u8>(p: &Peripherals, function: u32) {
572 let shift = 2 * N;
573 let mask = 0b11u32 << shift;
574 let value = function << shift;
575
576 match P {
577 0 => p
578 .pad_config
579 .pad0_cfg()
580 .modify(|r, w| unsafe { w.bits((r.bits() & !mask) | value) }),
581 1 => p
582 .pad_config
583 .pad1_cfg()
584 .modify(|r, w| unsafe { w.bits((r.bits() & !mask) | value) }),
585 2 => p
586 .pad_config
587 .pad2_cfg()
588 .modify(|r, w| unsafe { w.bits((r.bits() & !mask) | value) }),
589 _ => panic!("Invalid port number {}", P),
590 };
591}
592
593#[inline(always)]
594fn set_pull<const P: u8, const N: u8>(p: &Peripherals, pull: u32) {
595 let shift = 2 * N;
596 let mask = 0b11u32 << shift;
597
598 match P {
599 0 => p
600 .pad_config
601 .pad0_pupd()
602 .modify(|r, w| unsafe { w.bits((r.bits() & !mask) | (pull << shift)) }),
603 1 => p
604 .pad_config
605 .pad1_pupd()
606 .modify(|r, w| unsafe { w.bits((r.bits() & !mask) | (pull << shift)) }),
607 2 => p
608 .pad_config
609 .pad2_pupd()
610 .modify(|r, w| unsafe { w.bits((r.bits() & !mask) | (pull << shift)) }),
611 _ => panic!("Invalid port number {}", P),
612 };
613}
614
615#[inline(always)]
616fn set_drive_strength<const P: u8, const N: u8>(p: &Peripherals, drive_strength: DriveStrength) {
617 let shift = 2 * N;
618 let mask = 0b11u32 << shift;
619 let value = drive_strength.bits() << shift;
620
621 match P {
622 0 => p
623 .pad_config
624 .pad0_ds()
625 .modify(|r, w| unsafe { w.bits((r.bits() & !mask) | value) }),
626 1 => p
627 .pad_config
628 .pad1_ds()
629 .modify(|r, w| unsafe { w.bits((r.bits() & !mask) | value) }),
630 2 => p
631 .pad_config
632 .pad2_ds()
633 .modify(|r, w| unsafe { w.bits((r.bits() & !mask) | value) }),
634 _ => panic!("Invalid port number {}", P),
635 };
636}
637
638#[inline(always)]
639fn set_direction_in<const P: u8, const N: u8>(p: &Peripherals) {
640 match P {
641 0 => p
642 .gpio16_0
643 .direction_in()
644 .modify(|r, w| unsafe { w.bits(r.bits() | (1u32 << N)) }),
645 1 => p
646 .gpio16_1
647 .direction_in()
648 .modify(|r, w| unsafe { w.bits(r.bits() | (1u32 << N)) }),
649 2 => p
650 .gpio8_2
651 .direction_in()
652 .modify(|r, w| unsafe { w.bits(r.bits() | (1u32 << N)) }),
653 _ => panic!("Invalid port number {}", P),
654 };
655}
656
657#[inline(always)]
658fn enable_pad_config_clock(p: &Peripherals) {
659 p.pm.clk_apb_m_set()
660 .modify(|_, w| w.pad_config().enable().pm().enable());
661}
662
663#[inline(always)]
664fn enable_gpio_clock<const P: u8>(p: &Peripherals) {
665 match P {
666 0 => p.pm.clk_apb_p_set().modify(|_, w| w.gpio_0().enable()),
667 1 => p.pm.clk_apb_p_set().modify(|_, w| w.gpio_1().enable()),
668 2 => p.pm.clk_apb_p_set().modify(|_, w| w.gpio_2().enable()),
669 _ => panic!("Invalid port number {}", P),
670 };
671}
672
673#[inline(always)]
674fn enable_gpio_pin_clocks<const P: u8>(p: &Peripherals) {
675 enable_pad_config_clock(p);
676 enable_gpio_clock::<P>(p);
677}
678
679#[inline(always)]
680fn enable_gpio_irq_clock(p: &Peripherals) {
681 p.pm.clk_apb_p_set().modify(|_, w| w.gpio_irq().enable());
682}
683
684impl<const P: u8, const N: u8, MODE> Pin<P, N, MODE> {
685 pub fn into_output(self) -> Pin<P, N, Output>
686 where
687 Pin<P, N>: OutputPermitted,
688 {
689 let p = unsafe { Peripherals::steal() };
690
691 set_gpio_function::<P, N>(&p);
692 set_pull::<P, N>(&p, 0);
693
694 match P {
695 0 => {
696 p.gpio16_0
697 .direction_out()
698 .modify(|r, w| unsafe { w.bits(r.bits() | (1u32 << N)) });
699 }
700 1 => {
701 p.gpio16_1
702 .direction_out()
703 .modify(|r, w| unsafe { w.bits(r.bits() | (1u32 << N)) });
704 }
705 2 => {
706 p.gpio8_2
707 .direction_out()
708 .modify(|r, w| unsafe { w.bits(r.bits() | (1u32 << N)) });
709 }
710 _ => panic!("Invalid port number {}", P),
711 }
712
713 Pin::new()
714 }
715
716 pub fn into_floating_input(self) -> Pin<P, N, Floating> {
717 let p = unsafe { Peripherals::steal() };
718
719 set_gpio_function::<P, N>(&p);
720 set_pull::<P, N>(&p, 0);
721 set_direction_in::<P, N>(&p);
722
723 Pin::new()
724 }
725
726 pub fn into_pull_up_input(self) -> Pin<P, N, PullUp> {
727 let p = unsafe { Peripherals::steal() };
728
729 set_gpio_function::<P, N>(&p);
730 set_pull::<P, N>(&p, 1);
731 set_direction_in::<P, N>(&p);
732
733 Pin::new()
734 }
735
736 pub fn into_pull_down_input(self) -> Pin<P, N, PullDown> {
737 let p = unsafe { Peripherals::steal() };
738
739 set_gpio_function::<P, N>(&p);
740 set_pull::<P, N>(&p, 2);
741 set_direction_in::<P, N>(&p);
742
743 Pin::new()
744 }
745
746 pub fn into_serial_port(self) -> Pin<P, N, Func2Mode>
747 where
748 Pin<P, N>: SerialPermitted,
749 {
750 let p = unsafe { Peripherals::steal() };
751
752 set_alternate_function::<P, N>(&p, 0b01);
753 set_pull::<P, N>(&p, 0);
754
755 Pin::new()
756 }
757
758 pub fn into_serial_port_pull_up(self) -> Pin<P, N, Func2Mode>
759 where
760 Pin<P, N>: SerialPermitted,
761 {
762 let p = unsafe { Peripherals::steal() };
763
764 set_alternate_function::<P, N>(&p, 0b01);
765 set_pull::<P, N>(&p, 1);
766
767 Pin::new()
768 }
769
770 pub fn into_timer_serial_port(self) -> Pin<P, N, Func3Mode>
771 where
772 Pin<P, N>: TimerSerialPermitted,
773 {
774 let p = unsafe { Peripherals::steal() };
775
776 set_alternate_function::<P, N>(&p, 0b10);
777 set_pull::<P, N>(&p, 0);
778 Pin::new()
779 }
780
781 pub fn into_analog(self) -> Pin<P, N, Analog>
782 where
783 Pin<P, N>: AnalogPermitted,
784 {
785 let p = unsafe { Peripherals::steal() };
786
787 set_alternate_function::<P, N>(&p, 0b11);
788 set_pull::<P, N>(&p, 0);
789 Pin::new()
790 }
791}
792
793impl<const P: u8, const N: u8, MODE> ErrorType for Pin<P, N, MODE> {
794 type Error = Infallible;
795}
796
797impl<const P: u8, const N: u8> OutputPin for Pin<P, N, Output> {
799 #[inline(always)]
801 fn set_high(&mut self) -> Result<(), Self::Error> {
802 let p = unsafe { Peripherals::steal() };
803
804 match P {
805 0 => {
806 p.gpio16_0.set().write(|w| unsafe { w.bits(1u32 << N) });
807 }
808 1 => {
809 p.gpio16_1.set().write(|w| unsafe { w.bits(1u32 << N) });
810 }
811 2 => {
812 p.gpio8_2.set().write(|w| unsafe { w.bits(1u32 << N) });
813 }
814 _ => panic!("Invalid port number {}", P),
815 }
816
817 Ok(())
818 }
819
820 #[inline(always)]
822 fn set_low(&mut self) -> Result<(), Self::Error> {
823 let p = unsafe { Peripherals::steal() };
824
825 match P {
826 0 => {
827 p.gpio16_0.clear().write(|w| unsafe { w.bits(1u32 << N) });
828 }
829 1 => {
830 p.gpio16_1.clear().write(|w| unsafe { w.bits(1u32 << N) });
831 }
832 2 => {
833 p.gpio8_2.clear().write(|w| unsafe { w.bits(1u32 << N) });
834 }
835 _ => panic!("Invalid port number {}", P),
836 }
837
838 Ok(())
839 }
840}
841
842impl<const P: u8, const N: u8> StatefulOutputPin for Pin<P, N, Output> {
843 #[inline(always)]
844 fn is_set_high(&mut self) -> Result<bool, Self::Error> {
845 let p = unsafe { Peripherals::steal() };
846
847 let mask = 1u32 << N;
848
849 let is_set = match P {
850 0 => p.gpio16_0.output().read().bits() & mask != 0,
851 1 => p.gpio16_1.output().read().bits() & mask != 0,
852 2 => p.gpio8_2.output().read().bits() & mask != 0,
853 _ => panic!("Invalid port number {}", P),
854 };
855
856 Ok(is_set)
857 }
858
859 #[inline(always)]
860 fn is_set_low(&mut self) -> Result<bool, Self::Error> {
861 self.is_set_high().map(|is_high| !is_high)
862 }
863}
864
865impl<const P: u8, const N: u8, MODE> InputPin for Pin<P, N, MODE>
866where
867 MODE: InputMode,
868{
869 #[inline(always)]
870 fn is_high(&mut self) -> Result<bool, Self::Error> {
871 let p = unsafe { Peripherals::steal() };
872
873 let mask = 1u32 << N;
874
875 let is_set = match P {
876 0 => p.gpio16_0.state().read().bits() & mask != 0,
877 1 => p.gpio16_1.state().read().bits() & mask != 0,
878 2 => p.gpio8_2.state().read().bits() & mask != 0,
879 _ => panic!("Invalid port number {}", P),
880 };
881
882 Ok(is_set)
883 }
884
885 #[inline(always)]
886 fn is_low(&mut self) -> Result<bool, Self::Error> {
887 self.is_high().map(|is_high| !is_high)
888 }
889}
890
891pub mod port_0 {
892 use super::{AnalogPermitted, OutputPermitted, Pin, SerialPermitted, TimerSerialPermitted};
893
894 pub type Pin00 = Pin<0, 0>;
895 impl OutputPermitted for Pin<0, 0> {}
896 impl SerialPermitted for Pin<0, 0> {}
897 impl TimerSerialPermitted for Pin<0, 0> {}
898
899 pub type Pin01 = Pin<0, 1>;
900 impl OutputPermitted for Pin<0, 1> {}
901 impl SerialPermitted for Pin<0, 1> {}
902 impl TimerSerialPermitted for Pin<0, 1> {}
903
904 pub type Pin02 = Pin<0, 2>;
905 impl OutputPermitted for Pin<0, 2> {}
906 impl SerialPermitted for Pin<0, 2> {}
907 impl TimerSerialPermitted for Pin<0, 2> {}
908 impl AnalogPermitted for Pin<0, 2> {}
909
910 pub type Pin03 = Pin<0, 3>;
911 impl OutputPermitted for Pin<0, 3> {}
912 impl SerialPermitted for Pin<0, 3> {}
913 impl TimerSerialPermitted for Pin<0, 3> {}
914
915 pub type Pin04 = Pin<0, 4>;
916 impl OutputPermitted for Pin<0, 4> {}
917 impl SerialPermitted for Pin<0, 4> {}
918 impl TimerSerialPermitted for Pin<0, 4> {}
919 impl AnalogPermitted for Pin<0, 4> {}
920
921 pub type Pin05 = Pin<0, 5>;
924 impl OutputPermitted for Pin<0, 5> {}
925 impl SerialPermitted for Pin<0, 5> {}
926 impl TimerSerialPermitted for Pin<0, 5> {}
927
928 pub type Pin06 = Pin<0, 6>;
931 impl OutputPermitted for Pin<0, 6> {}
932 impl SerialPermitted for Pin<0, 6> {}
933 impl TimerSerialPermitted for Pin<0, 6> {}
934
935 pub type Pin07 = Pin<0, 7>;
938 impl OutputPermitted for Pin<0, 7> {}
939 impl SerialPermitted for Pin<0, 7> {}
940 impl TimerSerialPermitted for Pin<0, 7> {}
941 impl AnalogPermitted for Pin<0, 7> {}
942
943 pub type Pin08 = Pin<0, 8>;
946 impl OutputPermitted for Pin<0, 8> {}
947 impl SerialPermitted for Pin<0, 8> {}
948 impl TimerSerialPermitted for Pin<0, 8> {}
949
950 pub type Pin09 = Pin<0, 9>;
951 impl OutputPermitted for Pin<0, 9> {}
952 impl SerialPermitted for Pin<0, 9> {}
953 impl TimerSerialPermitted for Pin<0, 9> {}
954 impl AnalogPermitted for Pin<0, 9> {}
955
956 pub type Pin10 = Pin<0, 10>;
957 impl OutputPermitted for Pin<0, 10> {}
958 impl SerialPermitted for Pin<0, 10> {}
959 impl TimerSerialPermitted for Pin<0, 10> {}
960
961 pub type Pin11 = Pin<0, 11>;
962 impl OutputPermitted for Pin<0, 11> {}
963 impl TimerSerialPermitted for Pin<0, 11> {}
964 impl AnalogPermitted for Pin<0, 11> {}
965
966 pub type Pin12 = Pin<0, 12>;
967 impl OutputPermitted for Pin<0, 12> {}
968 impl TimerSerialPermitted for Pin<0, 12> {}
969
970 pub type Pin13 = Pin<0, 13>;
971 impl OutputPermitted for Pin<0, 13> {}
972 impl TimerSerialPermitted for Pin<0, 13> {}
973 impl AnalogPermitted for Pin<0, 13> {}
974
975 pub type Pin14 = Pin<0, 14>;
976 impl OutputPermitted for Pin<0, 14> {}
977
978 pub type Pin15 = Pin<0, 15>;
979 impl OutputPermitted for Pin<0, 15> {}
980}
981
982pub mod port_1 {
983 use super::{AnalogPermitted, OutputPermitted, Pin, SerialPermitted, TimerSerialPermitted};
984
985 pub type Pin00 = Pin<1, 0>;
986 impl OutputPermitted for Pin<1, 0> {}
987 impl SerialPermitted for Pin<1, 0> {}
988 impl TimerSerialPermitted for Pin<1, 0> {}
989
990 pub type Pin01 = Pin<1, 1>;
991 impl OutputPermitted for Pin<1, 1> {}
992 impl SerialPermitted for Pin<1, 1> {}
993 impl TimerSerialPermitted for Pin<1, 1> {}
994
995 pub type Pin02 = Pin<1, 2>;
996 impl OutputPermitted for Pin<1, 2> {}
997 impl SerialPermitted for Pin<1, 2> {}
998 impl TimerSerialPermitted for Pin<1, 2> {}
999
1000 pub type Pin03 = Pin<1, 3>;
1001 impl OutputPermitted for Pin<1, 3> {}
1002 impl SerialPermitted for Pin<1, 3> {}
1003 impl TimerSerialPermitted for Pin<1, 3> {}
1004
1005 pub type Pin04 = Pin<1, 4>;
1006 impl OutputPermitted for Pin<1, 4> {}
1007 impl SerialPermitted for Pin<1, 4> {}
1008 impl TimerSerialPermitted for Pin<1, 4> {}
1009
1010 pub type Pin05 = Pin<1, 5>;
1011 impl OutputPermitted for Pin<1, 5> {}
1012 impl SerialPermitted for Pin<1, 5> {}
1013 impl TimerSerialPermitted for Pin<1, 5> {}
1014 impl AnalogPermitted for Pin<1, 5> {}
1015
1016 pub type Pin06 = Pin<1, 6>;
1017 impl OutputPermitted for Pin<1, 6> {}
1018 impl SerialPermitted for Pin<1, 6> {}
1019 impl TimerSerialPermitted for Pin<1, 6> {}
1020
1021 pub type Pin07 = Pin<1, 7>;
1022 impl OutputPermitted for Pin<1, 7> {}
1023 impl SerialPermitted for Pin<1, 7> {}
1024 impl AnalogPermitted for Pin<1, 7> {}
1025
1026 pub type Pin08 = Pin<1, 8>;
1029 impl OutputPermitted for Pin<1, 8> {}
1030 impl SerialPermitted for Pin<1, 8> {}
1031
1032 pub type Pin09 = Pin<1, 9>;
1035 impl OutputPermitted for Pin<1, 9> {}
1036 impl SerialPermitted for Pin<1, 9> {}
1037
1038 pub type Pin10 = Pin<1, 10>;
1039 impl OutputPermitted for Pin<1, 10> {}
1040 impl SerialPermitted for Pin<1, 10> {}
1041 impl AnalogPermitted for Pin<1, 10> {}
1042
1043 pub type Pin11 = Pin<1, 11>;
1044 impl OutputPermitted for Pin<1, 11> {}
1045 impl SerialPermitted for Pin<1, 11> {}
1046 impl AnalogPermitted for Pin<1, 11> {}
1047
1048 pub type Pin12 = Pin<1, 12>;
1049 impl OutputPermitted for Pin<1, 12> {}
1050 impl SerialPermitted for Pin<1, 12> {}
1051 impl TimerSerialPermitted for Pin<1, 12> {}
1052 impl AnalogPermitted for Pin<1, 12> {}
1053
1054 pub type Pin13 = Pin<1, 13>;
1055 impl OutputPermitted for Pin<1, 13> {}
1056 impl SerialPermitted for Pin<1, 13> {}
1057 impl TimerSerialPermitted for Pin<1, 13> {}
1058 impl AnalogPermitted for Pin<1, 13> {}
1059
1060 pub type Pin14 = Pin<1, 14>;
1061 impl OutputPermitted for Pin<1, 14> {}
1062 impl SerialPermitted for Pin<1, 14> {}
1063 impl TimerSerialPermitted for Pin<1, 14> {}
1064
1065 pub type Pin15 = Pin<1, 15>;
1066 impl OutputPermitted for Pin<1, 15> {}
1067 impl SerialPermitted for Pin<1, 15> {}
1068 impl TimerSerialPermitted for Pin<1, 15> {}
1069}
1070
1071pub mod port_2 {
1072 use super::{OutputPermitted, Pin, SerialPermitted, TimerSerialPermitted};
1073
1074 pub type Pin00 = Pin<2, 0>;
1075 impl OutputPermitted for Pin<2, 0> {}
1076 impl SerialPermitted for Pin<2, 0> {}
1077 impl TimerSerialPermitted for Pin<2, 0> {}
1078
1079 pub type Pin01 = Pin<2, 1>;
1080 impl OutputPermitted for Pin<2, 1> {}
1081 impl SerialPermitted for Pin<2, 1> {}
1082 impl TimerSerialPermitted for Pin<2, 1> {}
1083
1084 pub type Pin02 = Pin<2, 2>;
1085 impl OutputPermitted for Pin<2, 2> {}
1086 impl SerialPermitted for Pin<2, 2> {}
1087 impl TimerSerialPermitted for Pin<2, 2> {}
1088
1089 pub type Pin03 = Pin<2, 3>;
1090 impl OutputPermitted for Pin<2, 3> {}
1091 impl SerialPermitted for Pin<2, 3> {}
1092 impl TimerSerialPermitted for Pin<2, 3> {}
1093
1094 pub type Pin04 = Pin<2, 4>;
1095 impl OutputPermitted for Pin<2, 4> {}
1096 impl SerialPermitted for Pin<2, 4> {}
1097
1098 pub type Pin05 = Pin<2, 5>;
1099 impl OutputPermitted for Pin<2, 5> {}
1100 impl SerialPermitted for Pin<2, 5> {}
1101
1102 pub type Pin06 = Pin<2, 6>;
1103 impl OutputPermitted for Pin<2, 6> {}
1104 impl SerialPermitted for Pin<2, 6> {}
1105 impl TimerSerialPermitted for Pin<2, 6> {}
1106
1107 pub type Pin07 = Pin<2, 7>;
1108 impl OutputPermitted for Pin<2, 7> {}
1109 impl TimerSerialPermitted for Pin<2, 7> {}
1110}