use core::marker::PhantomData;
use embedded_hal::digital::{ErrorType, InputPin, OutputPin, StatefulOutputPin};
use paste::paste;
pub trait PinMode: crate::Sealed {}
pub struct Input;
pub struct InputOutput;
pub struct Af1;
pub struct Af2;
impl crate::Sealed for Input {}
impl crate::Sealed for InputOutput {}
impl crate::Sealed for Af1 {}
impl crate::Sealed for Af2 {}
impl PinMode for Input {}
impl PinMode for InputOutput {}
impl PinMode for Af1 {}
impl PinMode for Af2 {}
pub trait PowerSupply: crate::Sealed {}
pub struct Vddio;
pub struct Vddioh;
impl crate::Sealed for Vddio {}
impl crate::Sealed for Vddioh {}
impl PowerSupply for Vddio {}
impl PowerSupply for Vddioh {}
pub trait PadMode: crate::Sealed {}
pub struct HighImpedance;
pub struct PullUpWeak;
pub struct PullUpStrong;
pub struct PullDownWeak;
pub struct PullDownStrong;
impl crate::Sealed for HighImpedance {}
impl crate::Sealed for PullUpWeak {}
impl crate::Sealed for PullUpStrong {}
impl crate::Sealed for PullDownWeak {}
impl crate::Sealed for PullDownStrong {}
impl PadMode for HighImpedance {}
impl PadMode for PullUpWeak {}
impl PadMode for PullUpStrong {}
impl PadMode for PullDownWeak {}
impl PadMode for PullDownStrong {}
pub trait DriveStrength: crate::Sealed {}
pub struct Strength0;
pub struct Strength1;
pub struct Strength2;
pub struct Strength3;
impl crate::Sealed for Strength0 {}
impl crate::Sealed for Strength1 {}
impl crate::Sealed for Strength2 {}
impl crate::Sealed for Strength3 {}
impl DriveStrength for Strength0 {}
impl DriveStrength for Strength1 {}
impl DriveStrength for Strength2 {}
impl DriveStrength for Strength3 {}
pub struct Pin<
const P: u8,
const N: u8,
MODE: PinMode = Input,
SUPPLY: PowerSupply = Vddio,
PAD: PadMode = HighImpedance,
DRIVE: DriveStrength = Strength0,
> {
_mode: PhantomData<MODE>,
_supply: PhantomData<SUPPLY>,
_pad: PhantomData<PAD>,
_drive: PhantomData<DRIVE>,
}
impl<const P: u8, const N: u8, MODE: PinMode> Pin<P, N, MODE> {
const fn new() -> Self {
Self {
_mode: PhantomData,
_supply: PhantomData,
_pad: PhantomData,
_drive: PhantomData,
}
}
#[doc(hidden)]
#[inline(always)]
fn _output_enable(&mut self) {
let gpio = unsafe { &*gpiox_ptr::<P>() };
gpio.outen_set().write(|w| unsafe { w.bits(1 << N) });
}
#[doc(hidden)]
#[inline(always)]
fn _output_disable(&mut self) {
let gpio = unsafe { &*gpiox_ptr::<P>() };
gpio.outen_clr().write(|w| unsafe { w.bits(1 << N) });
}
#[doc(hidden)]
#[inline(always)]
fn _into_af1(&mut self) {
let gpio = unsafe { &*gpiox_ptr::<P>() };
gpio.en0_set().write(|w| unsafe { w.bits(1 << N) });
gpio.en1_clr().write(|w| unsafe { w.bits(1 << N) });
gpio.en0_clr().write(|w| unsafe { w.bits(1 << N) });
}
#[doc(hidden)]
#[inline(always)]
fn _into_af2(&mut self) {
let gpio = unsafe { &*gpiox_ptr::<P>() };
gpio.en0_set().write(|w| unsafe { w.bits(1 << N) });
gpio.en1_set().write(|w| unsafe { w.bits(1 << N) });
gpio.en1_clr().write(|w| unsafe { w.bits(1 << N) });
}
#[doc(hidden)]
#[inline(always)]
fn _is_high(&self) -> bool {
let gpio = unsafe { &*gpiox_ptr::<P>() };
gpio.in_().read().gpio_in().bits() & (1 << N) != 0
}
#[doc(hidden)]
#[inline(always)]
fn _is_low(&self) -> bool {
let gpio = unsafe { &*gpiox_ptr::<P>() };
gpio.in_().read().gpio_in().bits() & (1 << N) == 0
}
#[doc(hidden)]
#[inline(always)]
fn _set_high(&mut self) {
let gpio = unsafe { &*gpiox_ptr::<P>() };
gpio.out_set().write(|w| unsafe { w.bits(1 << N) });
}
#[doc(hidden)]
#[inline(always)]
fn _set_low(&mut self) {
let gpio = unsafe { &*gpiox_ptr::<P>() };
gpio.out_clr().write(|w| unsafe { w.bits(1 << N) });
}
#[doc(hidden)]
#[inline(always)]
fn _is_set_high(&self) -> bool {
let gpio = unsafe { &*gpiox_ptr::<P>() };
gpio.out().read().bits() & (1 << N) != 0
}
#[doc(hidden)]
#[inline(always)]
fn _is_set_low(&self) -> bool {
let gpio = unsafe { &*gpiox_ptr::<P>() };
gpio.out().read().bits() & (1 << N) == 0
}
#[inline(always)]
pub fn is_high(&self) -> bool {
self._is_high()
}
#[inline(always)]
pub fn is_low(&self) -> bool {
self._is_low()
}
}
impl<const P: u8, const N: u8> Pin<P, N, Input> {
#[inline(always)]
pub fn into_input_output(self) -> Pin<P, N, InputOutput> {
let mut pin = Pin::<P, N, InputOutput>::new();
pin._output_enable();
pin
}
#[inline(always)]
pub fn into_af1(self) -> Pin<P, N, Af1> {
let mut pin = Pin::<P, N, Af1>::new();
pin._into_af1();
pin
}
#[inline(always)]
pub fn into_af2(self) -> Pin<P, N, Af2> {
let mut pin = Pin::<P, N, Af2>::new();
pin._into_af2();
pin
}
}
impl<const P: u8, const N: u8> Pin<P, N, InputOutput> {
#[inline(always)]
pub fn into_input(self) -> Pin<P, N, Input> {
let mut pin = Pin::<P, N, Input>::new();
pin._output_disable();
pin
}
#[inline(always)]
pub fn set_high(&mut self) {
self._set_high();
}
#[inline(always)]
pub fn set_low(&mut self) {
self._set_low();
}
#[inline(always)]
pub fn is_set_high(&self) -> bool {
self._is_set_high()
}
#[inline(always)]
pub fn is_set_low(&self) -> bool {
self._is_set_low()
}
#[inline(always)]
pub fn set_power_vddio(&mut self) {
let gpio = unsafe { &*gpiox_ptr::<P>() };
gpio.vssel()
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << N)) });
}
#[inline(always)]
pub fn set_power_vddioh(&mut self) {
let gpio = unsafe { &*gpiox_ptr::<P>() };
gpio.vssel()
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << N)) });
}
}
impl<const P: u8, const N: u8, MODE: PinMode> ErrorType for Pin<P, N, MODE> {
type Error = core::convert::Infallible;
}
impl<const P: u8, const N: u8, MODE: PinMode> InputPin for Pin<P, N, MODE> {
#[inline(always)]
fn is_high(&mut self) -> Result<bool, Self::Error> {
Ok(self._is_high())
}
#[inline(always)]
fn is_low(&mut self) -> Result<bool, Self::Error> {
Ok(self._is_low())
}
}
impl<const P: u8, const N: u8> OutputPin for Pin<P, N, InputOutput> {
#[inline(always)]
fn set_high(&mut self) -> Result<(), Self::Error> {
self._set_high();
Ok(())
}
#[inline(always)]
fn set_low(&mut self) -> Result<(), Self::Error> {
self._set_low();
Ok(())
}
}
impl<const P: u8, const N: u8> StatefulOutputPin for Pin<P, N, InputOutput> {
#[inline(always)]
fn is_set_high(&mut self) -> Result<bool, Self::Error> {
Ok(self._is_set_high())
}
#[inline(always)]
fn is_set_low(&mut self) -> Result<bool, Self::Error> {
Ok(self._is_set_low())
}
}
macro_rules! gpio {
($MODULE_PAC:ident, $MODULE_HAL:ident, $GCR_TYPE:ident, $PORT_NUM:expr, [$($PIN_NUM:literal),*]) => {
paste!{
pub mod $MODULE_HAL {
pub struct Parts {
$(
pub [<p $PORT_NUM _ $PIN_NUM>]: [<P $PORT_NUM _ $PIN_NUM>],
)+
}
pub struct GpioPeripheral {
_gpio: $crate::pac::$MODULE_PAC,
}
impl GpioPeripheral {
pub fn new(gpio: $crate::pac::$MODULE_PAC, reg: &mut crate::gcr::GcrRegisters) -> Self {
use crate::gcr::ClockForPeripheral;
unsafe { gpio.enable_clock(&mut reg.$GCR_TYPE); };
Self {
_gpio: gpio,
}
}
pub fn split(self) -> Parts {
Parts {
$(
[<p $PORT_NUM _ $PIN_NUM>]: [<P $PORT_NUM _ $PIN_NUM>]::new(),
)+
}
}
}
$(
#[doc=stringify!([<P $PORT_NUM _ $PIN_NUM>])]
#[doc=" pin"]
pub type [<P $PORT_NUM _ $PIN_NUM>] = super::Pin<$PORT_NUM, $PIN_NUM>;
)+
}
pub use $MODULE_HAL::GpioPeripheral as $MODULE_PAC;
}
};
}
gpio!(
Gpio0,
gpio0,
gcr,
0,
[
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
]
);
gpio!(Gpio1, gpio1, gcr, 1, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
gpio!(Gpio2, gpio2, lpgcr, 2, [0, 1, 2, 3, 4, 5, 6, 7]);
#[inline(always)]
const fn gpiox_ptr<const P: u8>() -> *const crate::pac::gpio0::RegisterBlock {
match P {
0 => crate::pac::Gpio0::ptr(),
1 => crate::pac::Gpio1::ptr(),
2 => crate::pac::Gpio2::ptr(),
_ => panic!("Invalid GPIO port number"),
}
}