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 "`."]
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);
}
pub mod qspi {
use super::{pin_sealed, BankQspi, DynBankId, DynPinId, PinId};
pin_ids!(Qspi: 0;Sclk, 1;Ss, 2;Sd0, 3;Sd1, 4;Sd2, 5;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::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::Clock => FUNCSEL_A::CLOCK,
DynFunction::Usb => FUNCSEL_A::USB,
DynFunction::Null => FUNCSEL_A::NULL,
};
if funcsel != FUNCSEL_A::NULL {
pin.pad_ctrl().modify(|_, w| w.ie().set_bit());
} else {
pin.pad_ctrl().modify(|_, w| w.ie().clear_bit());
}
pin.io_ctrl().modify(|_, 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));
}