lpc55-hal 0.5.0

Hardware Abstraction Layer (HAL) for the NXP LPC55S6x ARM Cortex-33 microcontrollers
Documentation
use crate::{
    drivers::pins::Pin,
    peripherals::{inputmux::InputMux, syscon},
    raw,
    typestates::{
        init_state,
        pin::{gpio::direction, state, PinId},
    },
};
use core::ops::Deref;

pub enum Mode {
    RisingEdge,
    FallingEdge,
    ActiveLow,
    ActiveHigh,
}

/// Bit position 0 - 7 indicating which of the 8 external interrupt positions to use
#[repr(u8)]
#[derive(Copy, Clone, Debug)]
pub enum Slot {
    Slot0 = 0,
    Slot1 = 1,
    Slot2 = 2,
    Slot3 = 3,
    Slot4 = 4,
    Slot5 = 5,
    Slot6 = 6,
    Slot7 = 7,
}

use Mode::*;

impl<State> Deref for Pint<State> {
    type Target = raw::pint::RegisterBlock;
    fn deref(&self) -> &Self::Target {
        &self.raw
    }
}

crate::wrap_stateful_peripheral!(Pint, PINT);

impl<State> Pint<State> {
    pub fn enabled(mut self, syscon: &mut syscon::Syscon) -> Pint<init_state::Enabled> {
        syscon.enable_clock(&mut self.raw);

        Pint {
            raw: self.raw,
            _state: init_state::Enabled(()),
        }
    }

    pub fn disabled(mut self, syscon: &mut syscon::Syscon) -> Pint<init_state::Disabled> {
        syscon.disable_clock(&mut self.raw);

        Pint {
            raw: self.raw,
            _state: init_state::Disabled,
        }
    }
}

impl Pint<init_state::Enabled> {
    /// LPC55 supports 8 external pin interrupts, from any PIO pin.
    /// Use `slot` to indicate (0-7) which slot you'd like to use.
    /// `mode` indicates what kind of interrupt to generate.
    /// You can call this function twice to enable both `RisingEdge` and `FallingEdge` interrupts for same pin + slot.
    pub fn enable_interrupt<PIN: PinId>(
        &mut self,
        mux: &mut InputMux<init_state::Enabled>,
        _pin: &Pin<PIN, state::Gpio<direction::Input>>,
        slot: Slot,
        mode: Mode,
    ) {
        // Enable pin as external interrupt for ext int source `slot`
        mux.raw.pintsel[slot as usize]
            .write(|w| unsafe { w.intpin().bits((PIN::PORT << 5) as u8 | (PIN::NUMBER)) });

        let bit = 1 << (slot as u8);

        // Clear respective slot bit (default rising)
        self.raw
            .isel
            .modify(|r, w| unsafe { w.pmode().bits(r.pmode().bits() & (!bit)) });

        match mode {
            RisingEdge => {
                // enable level/rising interrupt
                self.raw.sienr.write(|w| unsafe { w.setenrl().bits(bit) });
            }
            FallingEdge => {
                // enable falling interrupt
                self.raw.sienf.write(|w| unsafe { w.setenaf().bits(bit) });
            }
            _ => {
                // Make level interrupt
                self.raw
                    .isel
                    .modify(|r, w| unsafe { w.pmode().bits(r.pmode().bits() | bit) });

                // enable level/rising interrupt
                self.raw.sienr.write(|w| unsafe { w.setenrl().bits(bit) });

                match mode {
                    ActiveHigh => {
                        // Make level active high
                        self.raw.sienf.write(|w| unsafe { w.setenaf().bits(bit) });
                    }
                    ActiveLow => {
                        // Make level active low
                        self.raw.cienf.write(|w| unsafe { w.cenaf().bits(bit) });
                    }
                    _ => {}
                }
            }
        }
    }
}