Skip to main content

hal_mik32/
gpio.rs

1//! GPIO
2use 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
18/// Floating input (type state)
19pub struct Floating;
20
21/// Pulled down input (type state)
22pub struct PullDown;
23
24/// Pulled up input (type state)
25pub struct PullUp;
26
27/// Output mode (type state)
28pub struct Output;
29
30/// Func2Mode mode (type state)
31pub struct Func2Mode;
32pub struct Func3Mode;
33
34/// Analog mode (type state)
35pub 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
797/// Single digital push-pull output pin.
798impl<const P: u8, const N: u8> OutputPin for Pin<P, N, Output> {
799    /// Drives the pin high.
800    #[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    /// Drives the pin low.
821    #[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    // GPIO
922    // UART 0 RX
923    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    // GPIO
929    // UART 0 TX
930    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    // GPIO
936    // UART 0 NCTS
937    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    // GPIO
944    // UART 0 NRTS
945    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    // GPIO
1027    // UART 1 RX
1028    pub type Pin08 = Pin<1, 8>;
1029    impl OutputPermitted for Pin<1, 8> {}
1030    impl SerialPermitted for Pin<1, 8> {}
1031
1032    // GPIO
1033    // UART 1 TX
1034    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}