use super::*;
struct Assert<const L: u8, const R: u8>;
impl<const L: u8, const R: u8> Assert<L, R> {
pub const LESS: u8 = R - L - 1;
}
impl<MODE, HL, const P: char, const N: u8> Pin<MODE, HL, P, N> {
fn set_alternate<const A: u8>(&mut self) {
#[allow(path_statements, clippy::no_effect)]
{
Assert::<A, 16>::LESS;
}
let offset = 2 * { N };
unsafe {
if N < 8 {
let offset2 = 4 * { N };
(*Gpio::<P>::ptr()).afrl.modify(|r, w| {
w.bits((r.bits() & !(0b1111 << offset2)) | ((A as u32) << offset2))
});
} else {
let offset2 = 4 * { N - 8 };
(*Gpio::<P>::ptr()).afrh.modify(|r, w| {
w.bits((r.bits() & !(0b1111 << offset2)) | ((A as u32) << offset2))
});
}
(*Gpio::<P>::ptr())
.moder
.modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset)));
}
}
pub fn into_alternate<const A: u8>(
mut self,
_moder: &mut MODER<P>,
_otyper: &mut OTYPER<P>,
_afr: &mut Afr<HL, P>,
) -> Pin<Alternate<PushPull, A>, HL, P, N> {
self.set_alternate::<A>();
Pin::new()
}
pub fn into_alternate_push_pull<const A: u8>(
self,
moder: &mut MODER<P>,
otyper: &mut OTYPER<P>,
afr: &mut Afr<HL, P>,
) -> Pin<Alternate<PushPull, A>, HL, P, N> {
self.into_alternate::<A>(moder, otyper, afr)
}
#[allow(path_statements)]
pub fn into_alternate_open_drain<const A: u8>(
self,
moder: &mut MODER<P>,
otyper: &mut OTYPER<P>,
afr: &mut Afr<HL, P>,
) -> Pin<Alternate<OpenDrain, A>, HL, P, N> {
self.into_alternate::<A>(moder, otyper, afr)
.set_open_drain()
}
pub fn into_floating_input(
mut self,
_moder: &mut MODER<P>,
_pupdr: &mut PUPDR<P>,
) -> Pin<Input<Floating>, HL, P, N> {
self.mode::<Input<Floating>>();
Pin::new()
}
pub fn into_pull_down_input(
mut self,
_moder: &mut MODER<P>,
_pupdr: &mut PUPDR<P>,
) -> Pin<Input<PullDown>, HL, P, N> {
self.mode::<Input<PullDown>>();
Pin::new()
}
pub fn into_pull_up_input(
mut self,
_moder: &mut MODER<P>,
_pupdr: &mut PUPDR<P>,
) -> Pin<Input<PullUp>, HL, P, N> {
self.mode::<Input<PullUp>>();
Pin::new()
}
pub fn into_open_drain_output(
mut self,
_moder: &mut MODER<P>,
_otyper: &mut OTYPER<P>,
) -> Pin<Output<OpenDrain>, HL, P, N> {
self.mode::<Output<OpenDrain>>();
Pin::new()
}
pub fn into_open_drain_output_in_state(
mut self,
_moder: &mut MODER<P>,
_otyper: &mut OTYPER<P>,
initial_state: PinState,
) -> Pin<Output<OpenDrain>, HL, P, N> {
self._set_state(initial_state);
self.mode::<Output<OpenDrain>>();
Pin::new()
}
pub fn into_push_pull_output(
mut self,
_moder: &mut MODER<P>,
_otyper: &mut OTYPER<P>,
) -> Pin<Output<PushPull>, HL, P, N> {
self._set_low();
self.mode::<Output<PushPull>>();
Pin::new()
}
pub fn into_push_pull_output_in_state(
mut self,
_moder: &mut MODER<P>,
_otyper: &mut OTYPER<P>,
initial_state: PinState,
) -> Pin<Output<PushPull>, HL, P, N> {
self._set_state(initial_state);
self.mode::<Output<PushPull>>();
Pin::new()
}
pub fn into_analog(
mut self,
_moder: &mut MODER<P>,
_pupdr: &mut PUPDR<P>,
) -> Pin<Analog, HL, P, N> {
self.mode::<Analog>();
Pin::new()
}
#[inline(always)]
fn mode<M: PinMode>(&mut self) {
let offset = 2 * N;
unsafe {
(*Gpio::<P>::ptr())
.pupdr
.modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (M::PUPDR << offset)));
if let Some(otyper) = M::OTYPER {
(*Gpio::<P>::ptr())
.otyper
.modify(|r, w| w.bits(r.bits() & !(0b1 << N) | (otyper << N)));
}
(*Gpio::<P>::ptr())
.moder
.modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (M::MODER << offset)));
}
}
}
impl<MODE, HL, const P: char, const N: u8> Pin<MODE, HL, P, N>
where
MODE: PinMode,
{
fn with_mode<M, F, R>(&mut self, f: F) -> R
where
M: PinMode,
F: FnOnce(&mut Pin<M, HL, P, N>) -> R,
{
self.mode::<M>();
let _resetti = ResetMode { pin: self };
let mut witness = Pin::new();
f(&mut witness)
}
pub fn with_floating_input<R>(
&mut self,
f: impl FnOnce(&mut Pin<Input<Floating>, HL, P, N>) -> R,
) -> R {
self.with_mode(f)
}
pub fn with_pull_down_input<R>(
&mut self,
f: impl FnOnce(&mut Pin<Input<PullDown>, HL, P, N>) -> R,
) -> R {
self.with_mode(f)
}
pub fn with_pull_up_input<R>(
&mut self,
f: impl FnOnce(&mut Pin<Input<PullUp>, HL, P, N>) -> R,
) -> R {
self.with_mode(f)
}
pub fn with_analog<R>(&mut self, f: impl FnOnce(&mut Pin<Analog, HL, P, N>) -> R) -> R {
self.with_mode(f)
}
pub fn with_open_drain_output<R>(
&mut self,
f: impl FnOnce(&mut Pin<Output<OpenDrain>, HL, P, N>) -> R,
) -> R {
self.with_mode(f)
}
pub fn with_open_drain_output_in_state<R>(
&mut self,
state: PinState,
f: impl FnOnce(&mut Pin<Output<OpenDrain>, HL, P, N>) -> R,
) -> R {
self._set_state(state);
self.with_mode(f)
}
pub fn with_push_pull_output<R>(
&mut self,
f: impl FnOnce(&mut Pin<Output<PushPull>, HL, P, N>) -> R,
) -> R {
self.with_mode(f)
}
pub fn with_push_pull_output_in_state<R>(
&mut self,
state: PinState,
f: impl FnOnce(&mut Pin<Output<PushPull>, HL, P, N>) -> R,
) -> R {
self._set_state(state);
self.with_mode(f)
}
}
struct ResetMode<'a, ORIG: PinMode, HL, const P: char, const N: u8> {
pin: &'a mut Pin<ORIG, HL, P, N>,
}
impl<'a, ORIG: PinMode, HL, const P: char, const N: u8> Drop for ResetMode<'a, ORIG, HL, P, N> {
fn drop(&mut self) {
self.pin.mode::<ORIG>();
}
}
pub trait PinMode: crate::Sealed {
#[doc(hidden)]
const PUPDR: u32;
#[doc(hidden)]
const MODER: u32;
#[doc(hidden)]
const OTYPER: Option<u32> = None;
}
impl crate::Sealed for Input<Floating> {}
impl PinMode for Input<Floating> {
const PUPDR: u32 = 0b00;
const MODER: u32 = 0b00;
}
impl crate::Sealed for Input<PullDown> {}
impl PinMode for Input<PullDown> {
const PUPDR: u32 = 0b10;
const MODER: u32 = 0b00;
}
impl crate::Sealed for Input<PullUp> {}
impl PinMode for Input<PullUp> {
const PUPDR: u32 = 0b01;
const MODER: u32 = 0b00;
}
impl crate::Sealed for Analog {}
impl PinMode for Analog {
const PUPDR: u32 = 0b00;
const MODER: u32 = 0b11;
}
impl crate::Sealed for Output<OpenDrain> {}
impl PinMode for Output<OpenDrain> {
const PUPDR: u32 = 0b00;
const MODER: u32 = 0b01;
const OTYPER: Option<u32> = Some(0b1);
}
impl crate::Sealed for Output<PushPull> {}
impl PinMode for Output<PushPull> {
const PUPDR: u32 = 0b00;
const MODER: u32 = 0b01;
const OTYPER: Option<u32> = Some(0b0);
}