#[cfg(feature = "unproven")]
use crate::ehal::digital::v2::InputPin;
use crate::gpio::{
self, pin::*, AnyPin, FloatingInterrupt, PinMode, PullDownInterrupt, PullUpInterrupt,
};
use crate::pac;
use super::EIC;
pub trait EicPin {
type Floating;
type PullUp;
type PullDown;
fn into_floating_ei(self) -> Self::Floating;
fn into_pull_up_ei(self) -> Self::PullUp;
fn into_pull_down_ei(self) -> Self::PullDown;
}
pub type Sense = pac::eic::config::SENSE0_A;
pub type ExternalInterruptID = usize;
pub trait ExternalInterrupt {
fn id(&self) -> ExternalInterruptID;
}
macro_rules! ei {
(
$PadType:ident [ $num:expr ] {
$(
$(#[$attr:meta])*
$PinType:ident,
)+
}
) => {
crate::paste::item! {
pub struct [<$PadType $num>]<GPIO>
where
GPIO: AnyPin,
{
_pin: Pin<GPIO::Id, GPIO::Mode>,
}
impl<GPIO: AnyPin> [<$PadType $num>]<GPIO> {
pub fn new(pin: GPIO) -> Self {
[<$PadType $num>]{
_pin:pin.into()
}
}
pub fn enable_event(&mut self, eic: &mut EIC) {
eic.eic.evctrl.modify(|_, w| {
w.[<extinteo $num>]().set_bit()
});
}
pub fn enable_interrupt(&mut self, eic: &mut EIC) {
eic.eic.intenset.modify(|_, w| {
w.[<extint $num>]().set_bit()
});
}
pub fn enable_interrupt_wake(&mut self, eic: &mut EIC) {
eic.eic.wakeup.modify(|_, w| {
w.[<wakeupen $num>]().set_bit()
})
}
pub fn disable_interrupt(&mut self, eic: &mut EIC) {
eic.eic.intenclr.modify(|_, w| {
w.[<extint $num>]().set_bit()
});
}
pub fn is_interrupt(&mut self) -> bool {
unsafe { &(*pac::EIC::ptr()) }.intflag.read().[<extint $num>]().bit_is_set()
}
pub fn clear_interrupt(&mut self) {
unsafe { &(*pac::EIC::ptr()) }.intflag.modify(|_, w| {
w.[<extint $num>]().set_bit()
});
}
pub fn sense(&mut self, _eic: &mut EIC, sense: Sense) {
let offset = ($num >> 3) & 0b0001;
let config = unsafe { &(*pac::EIC::ptr()).config[offset] };
config.modify(|_, w| unsafe {
match $num & 0b111 {
0b000 => w.sense0().bits(sense as u8),
0b001 => w.sense1().bits(sense as u8),
0b010 => w.sense2().bits(sense as u8),
0b011 => w.sense3().bits(sense as u8),
0b100 => w.sense4().bits(sense as u8),
0b101 => w.sense5().bits(sense as u8),
0b110 => w.sense6().bits(sense as u8),
0b111 => w.sense7().bits(sense as u8),
_ => unreachable!(),
}
});
}
pub fn filter(&mut self, _eic: &mut EIC, filter: bool) {
let offset = ($num >> 3) & 0b0001;
let config = unsafe { &(*pac::EIC::ptr()).config[offset] };
config.modify(|_, w| {
match $num & 0b111 {
0b000 => w.filten0().bit(filter),
0b001 => w.filten1().bit(filter),
0b010 => w.filten2().bit(filter),
0b011 => w.filten3().bit(filter),
0b100 => w.filten4().bit(filter),
0b101 => w.filten5().bit(filter),
0b110 => w.filten6().bit(filter),
0b111 => w.filten7().bit(filter),
_ => unreachable!(),
}
});
}
}
impl<GPIO: AnyPin> ExternalInterrupt for [<$PadType $num>]<GPIO> {
fn id(&self) -> ExternalInterruptID {
$num
}
}
#[cfg(feature = "unproven")]
impl<GPIO, C> InputPin for [<$PadType $num>]<GPIO>
where
GPIO: AnyPin<Mode = Interrupt<C>>,
C: InterruptConfig,
{
type Error = core::convert::Infallible;
#[inline]
fn is_high(&self) -> Result<bool, Self::Error> {
self._pin.is_high()
}
#[inline]
fn is_low(&self) -> Result<bool, Self::Error> {
self._pin.is_low()
}
}
$(
$(#[$attr])*
impl<M: PinMode> EicPin for Pin<gpio::$PinType, M> {
type Floating = [<$PadType $num>]<Pin<gpio::$PinType, FloatingInterrupt>>;
type PullUp = [<$PadType $num>]<Pin<gpio::$PinType, PullUpInterrupt>>;
type PullDown = [<$PadType $num>]<Pin<gpio::$PinType, PullDownInterrupt>>;
fn into_floating_ei(self) -> Self::Floating {
[<$PadType $num>]::new(self.into_floating_interrupt())
}
fn into_pull_up_ei(self) -> Self::PullUp {
[<$PadType $num>]::new(self.into_pull_up_interrupt())
}
fn into_pull_down_ei(self) -> Self::PullDown {
[<$PadType $num>]::new(self.into_pull_down_interrupt())
}
}
$(#[$attr])*
impl<M: PinMode> ExternalInterrupt for Pin<gpio::$PinType, M> {
fn id(&self) -> ExternalInterruptID {
$num
}
}
)+
}
};
}
#[cfg(feature = "samd11")]
mod impls {
use super::*;
ei!(ExtInt[1] {
PA15,
});
ei!(ExtInt[2] {
PA02,
});
ei!(ExtInt[3] {
PA31,
});
ei!(ExtInt[4] {
PA04,
PA24,
});
ei!(ExtInt[5] {
PA05,
PA25,
});
ei!(ExtInt[6] {
PA08,
});
ei!(ExtInt[7] {
PA09,
});
}
#[cfg(feature = "samd21")]
mod impls {
use super::*;
ei!(ExtInt[0] {
#[cfg(feature = "has-pa00")]
PA00,
PA16,
#[cfg(feature = "has-pb00")]
PB00,
#[cfg(feature = "pins-64")]
PB16,
});
ei!(ExtInt[1] {
#[cfg(feature = "has-pa01")]
PA01,
PA17,
#[cfg(feature = "has-pb01")]
PB01,
#[cfg(feature = "pins-64")]
PB17,
});
ei!(ExtInt[2] {
PA02,
PA18,
#[cfg(feature = "has-pb02")]
PB02,
});
ei!(ExtInt[3] {
PA03,
PA19,
#[cfg(feature = "has-pb03")]
PB03,
});
ei!(ExtInt[4] {
PA04,
#[cfg(feature = "pins-48")]
PA20,
#[cfg(feature = "has-pb04")]
PB04,
});
ei!(ExtInt[5] {
PA05,
#[cfg(feature = "pins-48")]
PA21,
#[cfg(feature = "has-pb05")]
PB05,
});
ei!(ExtInt[6] {
PA06,
PA22,
#[cfg(feature = "pins-64")]
PB06,
#[cfg(feature = "has-pb22")]
PB22,
});
ei!(ExtInt[7] {
PA07,
PA23,
#[cfg(feature = "pins-64")]
PB07,
#[cfg(feature = "has-pb23")]
PB23,
});
ei!(ExtInt[8] {
#[cfg(feature = "has-pa28")]
PA28,
#[cfg(feature = "pins-48")]
PB08,
});
ei!(ExtInt[9] {
PA09,
#[cfg(feature = "pins-48")]
PB09,
});
ei!(ExtInt[10] {
PA10,
PA30,
#[cfg(feature = "pins-48")]
PB10,
});
ei!(ExtInt[11] {
PA11,
PA31,
#[cfg(feature = "pins-48")]
PB11,
});
ei!(ExtInt[12] {
#[cfg(feature = "pins-48")]
PA12,
PA24,
#[cfg(feature = "pins-64")]
PB12,
});
ei!(ExtInt[13] {
#[cfg(feature = "pins-48")]
PA13,
PA25,
#[cfg(feature = "pins-64")]
PB13,
});
ei!(ExtInt[14] {
PA14,
#[cfg(feature = "pins-64")]
PB14,
#[cfg(feature = "pins-64")]
PB30,
});
ei!(ExtInt[15] {
PA15,
#[cfg(feature = "has-pa27")]
PA27,
#[cfg(feature = "pins-64")]
PB15,
#[cfg(feature = "pins-64")]
PB31,
});
}
pub use impls::*;