use core::marker::PhantomData;
use crate::pac::{gpio0, GPIO0_SECURE, GPIO1_SECURE, GPIO2_SECURE};
pub trait PinMode {}
pub enum Gpio {}
impl PinMode for Gpio {}
pub enum Uart {}
impl PinMode for Uart {}
pub enum Spi {}
impl PinMode for Spi {}
pub enum I2c {}
impl PinMode for I2c {}
pub struct Pin<const SHIELD_ID: usize, const PIN_ID: usize, Mode: PinMode> {
mode: PhantomData<Mode>,
}
impl<const SHIELD_ID: usize, const PIN_ID: usize, Mode: PinMode> Pin<SHIELD_ID, PIN_ID, Mode> {
fn block_and_mask(&self) -> (*const gpio0::RegisterBlock, u32) {
match (SHIELD_ID, PIN_ID) {
(0, 16) => (GPIO2_SECURE::PTR, 0b0001),
(0, 17) => (GPIO2_SECURE::PTR, 0b0010),
(1, 16) => (GPIO2_SECURE::PTR, 0b0100),
(1, 17) => (GPIO2_SECURE::PTR, 0b1000),
(0, pid) => (GPIO0_SECURE::PTR, 1 << pid),
(1, pid) => (GPIO1_SECURE::PTR, 1 << pid),
(_, _) => unreachable!(),
}
}
}
pub enum Pins {}
impl Pins {
#[allow(clippy::type_complexity)]
pub fn get_pins_secure(
gpio0: GPIO0_SECURE,
gpio1: GPIO1_SECURE,
gpio2: GPIO2_SECURE,
) -> (
Pin<0, 0, Gpio>,
Pin<0, 1, Gpio>,
Pin<0, 2, Gpio>,
Pin<0, 3, Gpio>,
Pin<0, 4, Gpio>,
Pin<0, 5, Gpio>,
Pin<0, 6, Gpio>,
Pin<0, 7, Gpio>,
Pin<0, 8, Gpio>,
Pin<0, 9, Gpio>,
Pin<0, 10, Gpio>,
Pin<0, 11, Gpio>,
Pin<0, 12, Gpio>,
Pin<0, 13, Gpio>,
Pin<0, 14, Gpio>,
Pin<0, 15, Gpio>,
Pin<0, 16, Gpio>,
Pin<0, 17, Gpio>,
Pin<1, 0, Gpio>,
Pin<1, 1, Gpio>,
Pin<1, 2, Gpio>,
Pin<1, 3, Gpio>,
Pin<1, 4, Gpio>,
Pin<1, 5, Gpio>,
Pin<1, 6, Gpio>,
Pin<1, 7, Gpio>,
Pin<1, 8, Gpio>,
Pin<1, 9, Gpio>,
Pin<1, 10, Gpio>,
Pin<1, 11, Gpio>,
Pin<1, 12, Gpio>,
Pin<1, 13, Gpio>,
Pin<1, 14, Gpio>,
Pin<1, 15, Gpio>,
Pin<1, 16, Gpio>,
Pin<1, 17, Gpio>,
) {
let _ = (gpio0, gpio1, gpio2);
(
Pin { mode: PhantomData },
Pin { mode: PhantomData },
Pin { mode: PhantomData },
Pin { mode: PhantomData },
Pin { mode: PhantomData },
Pin { mode: PhantomData },
Pin { mode: PhantomData },
Pin { mode: PhantomData },
Pin { mode: PhantomData },
Pin { mode: PhantomData },
Pin { mode: PhantomData },
Pin { mode: PhantomData },
Pin { mode: PhantomData },
Pin { mode: PhantomData },
Pin { mode: PhantomData },
Pin { mode: PhantomData },
Pin { mode: PhantomData },
Pin { mode: PhantomData },
Pin { mode: PhantomData },
Pin { mode: PhantomData },
Pin { mode: PhantomData },
Pin { mode: PhantomData },
Pin { mode: PhantomData },
Pin { mode: PhantomData },
Pin { mode: PhantomData },
Pin { mode: PhantomData },
Pin { mode: PhantomData },
Pin { mode: PhantomData },
Pin { mode: PhantomData },
Pin { mode: PhantomData },
Pin { mode: PhantomData },
Pin { mode: PhantomData },
Pin { mode: PhantomData },
Pin { mode: PhantomData },
Pin { mode: PhantomData },
Pin { mode: PhantomData },
)
}
}
macro_rules! impl_into_mode {
($(($shield:expr, $pin:expr) => $mode:ident)*) => {
$(
impl Pin<$shield, $pin, Gpio> {
#[doc = concat!("Turns the current GPIO pin into a ", stringify!($mode), " pin")]
pub fn into_mode(self) -> Pin<$shield, $pin, $mode> {
let (block, mask) = self.block_and_mask();
unsafe { &*block }.altfuncset.write(|w|unsafe { w.bits(mask) });
Pin {
mode: PhantomData
}
}
}
impl Pin<$shield, $pin, $mode> {
#[doc = concat!("Turns the current ", stringify!($mode), " pin into a GPIO pin")]
pub fn into_mode(self) -> Pin<$shield, $pin, Gpio> {
let (block, mask) = self.block_and_mask();
unsafe { &*block }.altfuncclr.write(|w|unsafe { w.bits(mask) });
Pin {
mode: PhantomData
}
}
}
)*
};
}
impl_into_mode! {
(0, 0) => Uart
(0, 1) => Uart
(0, 10) => Spi
(0, 11) => Spi
(0, 12) => Spi
(0, 13) => Spi
(0, 14) => I2c
(0, 15) => I2c
(1, 0) => Uart
(1, 1) => Uart
(1, 10) => Spi
(1, 11) => Spi
(1, 12) => Spi
(1, 13) => Spi
(1, 14) => I2c
(1, 15) => I2c
}
impl<const SHIELD_ID: usize, const PIN_ID: usize> embedded_hal::digital::v2::InputPin
for Pin<SHIELD_ID, PIN_ID, Gpio>
{
type Error = core::convert::Infallible;
fn is_high(&self) -> Result<bool, core::convert::Infallible> {
let (block, mask) = self.block_and_mask();
Ok((unsafe { &*block }.data.read().bits() & mask) != 0)
}
fn is_low(&self) -> Result<bool, core::convert::Infallible> {
self.is_high().map(|b| !b)
}
}