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<const P: char, const N: u8, const A: u8, MODE> From<Pin<P, N, Input<MODE>>>
for Pin<P, N, Alternate<A, PushPull>>
{
#[inline(always)]
fn from(f: Pin<P, N, Input<MODE>>) -> Self {
f.into_alternate::<A>()
}
}
impl<const P: char, const N: u8, const A: u8, MODE> From<Pin<P, N, Output<MODE>>>
for Pin<P, N, Alternate<A, PushPull>>
{
#[inline(always)]
fn from(f: Pin<P, N, Output<MODE>>) -> Self {
f.into_alternate::<A>()
}
}
impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Analog>>
for Pin<P, N, Alternate<A, PushPull>>
{
#[inline(always)]
fn from(f: Pin<P, N, Analog>) -> Self {
f.into_alternate::<A>()
}
}
impl<const P: char, const N: u8, const A: u8, const B: u8> From<Pin<P, N, Alternate<B, OpenDrain>>>
for Pin<P, N, Alternate<A, PushPull>>
{
#[inline(always)]
fn from(f: Pin<P, N, Alternate<B, OpenDrain>>) -> Self {
f.into_alternate::<A>()
}
}
impl<const P: char, const N: u8, const A: u8, MODE> From<Pin<P, N, Input<MODE>>>
for Pin<P, N, Alternate<A, OpenDrain>>
{
#[inline(always)]
fn from(f: Pin<P, N, Input<MODE>>) -> Self {
f.into_alternate_open_drain::<A>()
}
}
impl<const P: char, const N: u8, const A: u8, MODE> From<Pin<P, N, Output<MODE>>>
for Pin<P, N, Alternate<A, OpenDrain>>
{
#[inline(always)]
fn from(f: Pin<P, N, Output<MODE>>) -> Self {
f.into_alternate_open_drain::<A>()
}
}
impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Analog>>
for Pin<P, N, Alternate<A, OpenDrain>>
{
#[inline(always)]
fn from(f: Pin<P, N, Analog>) -> Self {
f.into_alternate_open_drain::<A>()
}
}
impl<const P: char, const N: u8, const A: u8, const B: u8> From<Pin<P, N, Alternate<B, PushPull>>>
for Pin<P, N, Alternate<A, OpenDrain>>
{
#[inline(always)]
fn from(f: Pin<P, N, Alternate<B, PushPull>>) -> Self {
f.into_alternate_open_drain::<A>()
}
}
impl<const P: char, const N: u8> From<Pin<P, N, Input<Floating>>> for Pin<P, N, Input<PullDown>> {
#[inline(always)]
fn from(f: Pin<P, N, Input<Floating>>) -> Self {
f.into_pull_down_input()
}
}
impl<const P: char, const N: u8> From<Pin<P, N, Input<PullUp>>> for Pin<P, N, Input<PullDown>> {
#[inline(always)]
fn from(f: Pin<P, N, Input<PullUp>>) -> Self {
f.into_pull_down_input()
}
}
impl<const P: char, const N: u8, MODE> From<Pin<P, N, Output<MODE>>>
for Pin<P, N, Input<PullDown>>
{
#[inline(always)]
fn from(f: Pin<P, N, Output<MODE>>) -> Self {
f.into_pull_down_input()
}
}
impl<const P: char, const N: u8> From<Pin<P, N, Analog>> for Pin<P, N, Input<PullDown>> {
#[inline(always)]
fn from(f: Pin<P, N, Analog>) -> Self {
f.into_pull_down_input()
}
}
impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, PushPull>>>
for Pin<P, N, Input<PullDown>>
{
#[inline(always)]
fn from(f: Pin<P, N, Alternate<A, PushPull>>) -> Self {
f.into_pull_down_input()
}
}
impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, OpenDrain>>>
for Pin<P, N, Input<PullDown>>
{
#[inline(always)]
fn from(f: Pin<P, N, Alternate<A, OpenDrain>>) -> Self {
f.into_pull_down_input()
}
}
impl<const P: char, const N: u8> From<Pin<P, N, Input<Floating>>> for Pin<P, N, Input<PullUp>> {
#[inline(always)]
fn from(f: Pin<P, N, Input<Floating>>) -> Self {
f.into_pull_up_input()
}
}
impl<const P: char, const N: u8> From<Pin<P, N, Input<PullDown>>> for Pin<P, N, Input<PullUp>> {
#[inline(always)]
fn from(f: Pin<P, N, Input<PullDown>>) -> Self {
f.into_pull_up_input()
}
}
impl<const P: char, const N: u8, MODE> From<Pin<P, N, Output<MODE>>> for Pin<P, N, Input<PullUp>> {
#[inline(always)]
fn from(f: Pin<P, N, Output<MODE>>) -> Self {
f.into_pull_up_input()
}
}
impl<const P: char, const N: u8> From<Pin<P, N, Analog>> for Pin<P, N, Input<PullUp>> {
#[inline(always)]
fn from(f: Pin<P, N, Analog>) -> Self {
f.into_pull_up_input()
}
}
impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, PushPull>>>
for Pin<P, N, Input<PullUp>>
{
#[inline(always)]
fn from(f: Pin<P, N, Alternate<A, PushPull>>) -> Self {
f.into_pull_up_input()
}
}
impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, OpenDrain>>>
for Pin<P, N, Input<PullUp>>
{
#[inline(always)]
fn from(f: Pin<P, N, Alternate<A, OpenDrain>>) -> Self {
f.into_pull_up_input()
}
}
impl<const P: char, const N: u8> From<Pin<P, N, Input<PullDown>>> for Pin<P, N, Input<Floating>> {
#[inline(always)]
fn from(f: Pin<P, N, Input<PullDown>>) -> Self {
f.into_floating_input()
}
}
impl<const P: char, const N: u8> From<Pin<P, N, Input<PullUp>>> for Pin<P, N, Input<Floating>> {
#[inline(always)]
fn from(f: Pin<P, N, Input<PullUp>>) -> Self {
f.into_floating_input()
}
}
impl<const P: char, const N: u8, MODE> From<Pin<P, N, Output<MODE>>>
for Pin<P, N, Input<Floating>>
{
#[inline(always)]
fn from(f: Pin<P, N, Output<MODE>>) -> Self {
f.into_floating_input()
}
}
impl<const P: char, const N: u8> From<Pin<P, N, Analog>> for Pin<P, N, Input<Floating>> {
#[inline(always)]
fn from(f: Pin<P, N, Analog>) -> Self {
f.into_floating_input()
}
}
impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, PushPull>>>
for Pin<P, N, Input<Floating>>
{
#[inline(always)]
fn from(f: Pin<P, N, Alternate<A, PushPull>>) -> Self {
f.into_floating_input()
}
}
impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, OpenDrain>>>
for Pin<P, N, Input<Floating>>
{
#[inline(always)]
fn from(f: Pin<P, N, Alternate<A, OpenDrain>>) -> Self {
f.into_floating_input()
}
}
impl<const P: char, const N: u8, MODE> From<Pin<P, N, Input<MODE>>>
for Pin<P, N, Output<OpenDrain>>
{
#[inline(always)]
fn from(f: Pin<P, N, Input<MODE>>) -> Self {
f.into_open_drain_output()
}
}
impl<const P: char, const N: u8> From<Pin<P, N, Output<PushPull>>>
for Pin<P, N, Output<OpenDrain>>
{
#[inline(always)]
fn from(f: Pin<P, N, Output<PushPull>>) -> Self {
f.into_open_drain_output()
}
}
impl<const P: char, const N: u8> From<Pin<P, N, Analog>> for Pin<P, N, Output<OpenDrain>> {
#[inline(always)]
fn from(f: Pin<P, N, Analog>) -> Self {
f.into_open_drain_output()
}
}
impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, PushPull>>>
for Pin<P, N, Output<OpenDrain>>
{
#[inline(always)]
fn from(f: Pin<P, N, Alternate<A, PushPull>>) -> Self {
f.into_open_drain_output()
}
}
impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, OpenDrain>>>
for Pin<P, N, Output<OpenDrain>>
{
#[inline(always)]
fn from(f: Pin<P, N, Alternate<A, OpenDrain>>) -> Self {
f.into_open_drain_output()
}
}
impl<const P: char, const N: u8, MODE> From<Pin<P, N, Input<MODE>>>
for Pin<P, N, Output<PushPull>>
{
#[inline(always)]
fn from(f: Pin<P, N, Input<MODE>>) -> Self {
f.into_push_pull_output()
}
}
impl<const P: char, const N: u8> From<Pin<P, N, Output<OpenDrain>>>
for Pin<P, N, Output<PushPull>>
{
#[inline(always)]
fn from(f: Pin<P, N, Output<OpenDrain>>) -> Self {
f.into_push_pull_output()
}
}
impl<const P: char, const N: u8> From<Pin<P, N, Analog>> for Pin<P, N, Output<PushPull>> {
#[inline(always)]
fn from(f: Pin<P, N, Analog>) -> Self {
f.into_push_pull_output()
}
}
impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, PushPull>>>
for Pin<P, N, Output<PushPull>>
{
#[inline(always)]
fn from(f: Pin<P, N, Alternate<A, PushPull>>) -> Self {
f.into_push_pull_output()
}
}
impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, OpenDrain>>>
for Pin<P, N, Output<PushPull>>
{
#[inline(always)]
fn from(f: Pin<P, N, Alternate<A, OpenDrain>>) -> Self {
f.into_push_pull_output()
}
}
impl<const P: char, const N: u8, MODE> From<Pin<P, N, Input<MODE>>> for Pin<P, N, Analog> {
#[inline(always)]
fn from(f: Pin<P, N, Input<MODE>>) -> Self {
f.into_analog()
}
}
impl<const P: char, const N: u8, MODE> From<Pin<P, N, Output<MODE>>> for Pin<P, N, Analog> {
#[inline(always)]
fn from(f: Pin<P, N, Output<MODE>>) -> Self {
f.into_analog()
}
}
impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, PushPull>>>
for Pin<P, N, Analog>
{
#[inline(always)]
fn from(f: Pin<P, N, Alternate<A, PushPull>>) -> Self {
f.into_analog()
}
}
impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, OpenDrain>>>
for Pin<P, N, Analog>
{
#[inline(always)]
fn from(f: Pin<P, N, Alternate<A, OpenDrain>>) -> Self {
f.into_analog()
}
}
impl<const P: char, const N: u8, MODE> Pin<P, N, MODE> {
pub(super) 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) -> Pin<P, N, Alternate<A, PushPull>> {
self.set_alternate::<A>();
Pin::new()
}
#[allow(path_statements)]
pub fn into_alternate_open_drain<const A: u8>(self) -> Pin<P, N, Alternate<A, OpenDrain>> {
self.into_alternate::<A>().set_open_drain()
}
pub fn into_floating_input(mut self) -> Pin<P, N, Input<Floating>> {
self.mode::<Input<Floating>>();
Pin::new()
}
pub fn into_pull_down_input(mut self) -> Pin<P, N, Input<PullDown>> {
self.mode::<Input<PullDown>>();
Pin::new()
}
pub fn into_pull_up_input(mut self) -> Pin<P, N, Input<PullUp>> {
self.mode::<Input<PullUp>>();
Pin::new()
}
pub fn into_open_drain_output(mut self) -> Pin<P, N, Output<OpenDrain>> {
self.mode::<Output<OpenDrain>>();
Pin::new()
}
pub fn into_open_drain_output_in_state(
mut self,
initial_state: PinState,
) -> Pin<P, N, Output<OpenDrain>> {
self._set_state(initial_state);
self.mode::<Output<OpenDrain>>();
Pin::new()
}
pub fn into_push_pull_output(mut self) -> Pin<P, N, Output<PushPull>> {
self._set_low();
self.mode::<Output<PushPull>>();
Pin::new()
}
pub fn into_push_pull_output_in_state(
mut self,
initial_state: PinState,
) -> Pin<P, N, Output<PushPull>> {
self._set_state(initial_state);
self.mode::<Output<PushPull>>();
Pin::new()
}
pub fn into_analog(mut self) -> Pin<P, N, Analog> {
self.mode::<Analog>();
Pin::new()
}
pub fn into_dynamic(self) -> DynamicPin<P, N> {
self.into_floating_input();
DynamicPin::new(Dynamic::InputFloating)
}
#[inline(always)]
pub(super) 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<const P: char, const N: u8, MODE> Pin<P, N, MODE>
where
MODE: PinMode,
{
fn with_mode<M, F, R>(&mut self, f: F) -> R
where
M: PinMode,
F: FnOnce(&mut Pin<P, N, M>) -> 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<P, N, Input<Floating>>) -> R,
) -> R {
self.with_mode(f)
}
pub fn with_pull_down_input<R>(
&mut self,
f: impl FnOnce(&mut Pin<P, N, Input<PullDown>>) -> R,
) -> R {
self.with_mode(f)
}
pub fn with_pull_up_input<R>(
&mut self,
f: impl FnOnce(&mut Pin<P, N, Input<PullUp>>) -> R,
) -> R {
self.with_mode(f)
}
pub fn with_analog<R>(&mut self, f: impl FnOnce(&mut Pin<P, N, Analog>) -> R) -> R {
self.with_mode(f)
}
pub fn with_open_drain_output<R>(
&mut self,
f: impl FnOnce(&mut Pin<P, N, Output<OpenDrain>>) -> R,
) -> R {
self.with_mode(f)
}
pub fn with_open_drain_output_in_state<R>(
&mut self,
state: PinState,
f: impl FnOnce(&mut Pin<P, N, Output<OpenDrain>>) -> R,
) -> R {
self._set_state(state);
self.with_mode(f)
}
pub fn with_push_pull_output<R>(
&mut self,
f: impl FnOnce(&mut Pin<P, N, Output<PushPull>>) -> R,
) -> R {
self.with_mode(f)
}
pub fn with_push_pull_output_in_state<R>(
&mut self,
state: PinState,
f: impl FnOnce(&mut Pin<P, N, Output<PushPull>>) -> R,
) -> R {
self._set_state(state);
self.with_mode(f)
}
}
struct ResetMode<'a, const P: char, const N: u8, ORIG: PinMode> {
pin: &'a mut Pin<P, N, ORIG>,
}
impl<'a, const P: char, const N: u8, ORIG: PinMode> Drop for ResetMode<'a, P, N, ORIG> {
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);
}