lpc55_hal/peripherals/
pint.rs

1use crate::{
2    drivers::pins::Pin,
3    peripherals::{inputmux::InputMux, syscon},
4    raw,
5    typestates::{
6        init_state,
7        pin::{gpio::direction, state, PinId},
8    },
9};
10use core::ops::Deref;
11
12pub enum Mode {
13    RisingEdge,
14    FallingEdge,
15    ActiveLow,
16    ActiveHigh,
17}
18
19/// Bit position 0 - 7 indicating which of the 8 external interrupt positions to use
20#[repr(u8)]
21#[derive(Copy, Clone, Debug)]
22pub enum Slot {
23    Slot0 = 0,
24    Slot1 = 1,
25    Slot2 = 2,
26    Slot3 = 3,
27    Slot4 = 4,
28    Slot5 = 5,
29    Slot6 = 6,
30    Slot7 = 7,
31}
32
33use Mode::*;
34
35impl<State> Deref for Pint<State> {
36    type Target = raw::pint::RegisterBlock;
37    fn deref(&self) -> &Self::Target {
38        &self.raw
39    }
40}
41
42crate::wrap_stateful_peripheral!(Pint, PINT);
43
44impl<State> Pint<State> {
45    pub fn enabled(mut self, syscon: &mut syscon::Syscon) -> Pint<init_state::Enabled> {
46        syscon.enable_clock(&mut self.raw);
47
48        Pint {
49            raw: self.raw,
50            _state: init_state::Enabled(()),
51        }
52    }
53
54    pub fn disabled(mut self, syscon: &mut syscon::Syscon) -> Pint<init_state::Disabled> {
55        syscon.disable_clock(&mut self.raw);
56
57        Pint {
58            raw: self.raw,
59            _state: init_state::Disabled,
60        }
61    }
62}
63
64impl Pint<init_state::Enabled> {
65    /// LPC55 supports 8 external pin interrupts, from any PIO pin.
66    /// Use `slot` to indicate (0-7) which slot you'd like to use.
67    /// `mode` indicates what kind of interrupt to generate.
68    /// You can call this function twice to enable both `RisingEdge` and `FallingEdge` interrupts for same pin + slot.
69    pub fn enable_interrupt<PIN: PinId>(
70        &mut self,
71        mux: &mut InputMux<init_state::Enabled>,
72        _pin: &Pin<PIN, state::Gpio<direction::Input>>,
73        slot: Slot,
74        mode: Mode,
75    ) {
76        // Enable pin as external interrupt for ext int source `slot`
77        mux.raw.pintsel[slot as usize]
78            .write(|w| unsafe { w.intpin().bits((PIN::PORT << 5) as u8 | (PIN::NUMBER)) });
79
80        let bit = 1 << (slot as u8);
81
82        // Clear respective slot bit (default rising)
83        self.raw
84            .isel
85            .modify(|r, w| unsafe { w.pmode().bits(r.pmode().bits() & (!bit)) });
86
87        match mode {
88            RisingEdge => {
89                // enable level/rising interrupt
90                self.raw.sienr.write(|w| unsafe { w.setenrl().bits(bit) });
91            }
92            FallingEdge => {
93                // enable falling interrupt
94                self.raw.sienf.write(|w| unsafe { w.setenaf().bits(bit) });
95            }
96            _ => {
97                // Make level interrupt
98                self.raw
99                    .isel
100                    .modify(|r, w| unsafe { w.pmode().bits(r.pmode().bits() | bit) });
101
102                // enable level/rising interrupt
103                self.raw.sienr.write(|w| unsafe { w.setenrl().bits(bit) });
104
105                match mode {
106                    ActiveHigh => {
107                        // Make level active high
108                        self.raw.sienf.write(|w| unsafe { w.setenaf().bits(bit) });
109                    }
110                    ActiveLow => {
111                        // Make level active low
112                        self.raw.cienf.write(|w| unsafe { w.cenaf().bits(bit) });
113                    }
114                    _ => {}
115                }
116            }
117        }
118    }
119}