use crate::typelevel::Sealed;
use super::{DynFunction, DynPullType};
pub(crate) mod pin_sealed;
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum DynBankId {
Bank0,
Qspi,
}
pub trait BankId: Sealed {}
pub struct BankBank0;
impl Sealed for BankBank0 {}
impl BankId for BankBank0 {}
pub struct BankQspi;
impl Sealed for BankQspi {}
impl BankId for BankQspi {}
pub trait PinId: pin_sealed::PinIdOps {
fn as_dyn(&self) -> DynPinId;
}
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct DynPinId {
pub bank: DynBankId,
pub num: u8,
}
impl PinId for DynPinId {
#[inline]
fn as_dyn(&self) -> DynPinId {
*self
}
}
macro_rules! pin_ids {
($bank:ident: $($id:expr;$name:ident),*) => {
pin_ids!($bank as $bank: $($id;$name),*);
};
($bank:ident as $prefix:ident: $($id:tt),*) => {
pin_ids!($bank as $prefix: $($id;$id),*);
};
($bank:ident as $prefix:ident: $($id:expr;$name:tt),*) => {
paste::paste!{
$(
#[doc = "Type level variant for the pin `" $name "` in bank `" $prefix "`."]
#[derive(Debug)]
pub struct [<$prefix $name>] (pub(crate) ());
impl crate::typelevel::Sealed for [<$prefix $name>] {}
impl PinId for [<$prefix $name>] {
#[inline]
fn as_dyn(&self) -> DynPinId {
DynPinId {
bank: DynBankId::$bank,
num: $id
}
}
}
impl pin_sealed::TypeLevelPinId for [<$prefix $name>] {
type Bank = [<Bank $bank>];
const ID: DynPinId = DynPinId {
bank: DynBankId::$bank,
num: $id
};
fn new() -> Self {
Self(())
}
}
)*
}
};
}
pub mod bank0 {
use super::{pin_sealed, BankBank0, DynBankId, DynPinId, PinId};
pin_ids!(
Bank0 as Gpio:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10,11,12,13,14,15,16,17,18,19,
20,21,22,23,24,25,26,27,28,29,
30,31,32,33,34,35,36,37,38,39,
40,41,42,43,44,45,46,47
);
}
pub mod qspi {
use super::{pin_sealed, BankQspi, DynBankId, DynPinId, PinId};
pin_ids!(Qspi: 56;UsbDp, 57;UsbDm, 58;Sclk, 59;Ss, 60;Sd0, 61;Sd1, 62;Sd2, 63;Sd3);
}
pub(crate) fn set_function<P: PinId>(pin: &P, function: DynFunction) {
use crate::pac::io_bank0::gpio::gpio_ctrl::FUNCSEL_A;
let funcsel = match function {
DynFunction::Xip => FUNCSEL_A::JTAG,
DynFunction::Hstx => FUNCSEL_A::JTAG,
DynFunction::Spi => FUNCSEL_A::SPI,
DynFunction::Uart => FUNCSEL_A::UART,
DynFunction::I2c => FUNCSEL_A::I2C,
DynFunction::Pwm => FUNCSEL_A::PWM,
DynFunction::Sio(sio) => {
let mask = pin.mask();
match sio {
crate::gpio::DynSioConfig::Input => {
pin.sio_oe_clr().write(|w| unsafe { w.bits(mask) });
}
crate::gpio::DynSioConfig::Output => {
pin.sio_oe_set().write(|w| unsafe { w.bits(mask) });
}
}
FUNCSEL_A::SIO
}
DynFunction::Pio0 => FUNCSEL_A::PIO0,
DynFunction::Pio1 => FUNCSEL_A::PIO1,
DynFunction::Pio2 => FUNCSEL_A::PIO2,
DynFunction::Clock => FUNCSEL_A::GPCK,
DynFunction::XipCs1 => FUNCSEL_A::GPCK,
DynFunction::Usb => FUNCSEL_A::USB,
DynFunction::UartAux => FUNCSEL_A::UART_AUX,
DynFunction::Null => FUNCSEL_A::NULL,
};
if funcsel != FUNCSEL_A::NULL {
pin.pad_ctrl().modify(|_, w| {
w.ie().set_bit();
w.od().clear_bit();
w.iso().clear_bit();
w
});
} else {
pin.pad_ctrl().modify(|_, w| {
w.ie().clear_bit();
w.od().set_bit();
w.iso().set_bit();
w
});
}
unsafe {
pin.io_ctrl()
.write_with_zero(|w| w.funcsel().variant(funcsel));
}
}
pub(crate) fn set_pull_type<P: PinId>(pin: &P, pull_type: DynPullType) {
let (pue, pde) = match pull_type {
DynPullType::None => (false, false),
DynPullType::Up => (true, false),
DynPullType::Down => (false, true),
DynPullType::BusKeep => (true, true),
};
pin.pad_ctrl()
.modify(|_, w| w.pue().bit(pue).pde().bit(pde));
}