use core::marker::PhantomData;
use crate::afio;
use crate::pac::EXTI;
use crate::rcc::APB2;
pub enum IOPinSpeed {
Mhz10 = 0b01,
Mhz2 = 0b10,
Mhz50 = 0b11,
}
pub trait OutputSpeed<CR> {
fn set_speed(&mut self, cr: &mut CR, speed: IOPinSpeed);
}
pub trait GpioExt {
type Parts;
fn split(self, apb2: &mut APB2) -> Self::Parts;
}
pub trait Mode<MODE> {}
pub trait Active {}
pub struct Input<MODE> {
_mode: PhantomData<MODE>,
}
impl<MODE> Active for Input<MODE> {}
pub struct Debugger;
pub struct Floating;
pub struct PullDown;
pub struct PullUp;
pub struct Output<MODE> {
_mode: PhantomData<MODE>,
}
impl<MODE> Active for Output<MODE> {}
pub struct PushPull;
pub struct OpenDrain;
pub struct Analog;
impl Active for Analog {}
pub struct Alternate<MODE> {
_mode: PhantomData<MODE>,
}
impl<MODE> Active for Alternate<MODE> {}
pub enum State {
High,
Low,
}
#[allow(non_camel_case_types)]
#[derive(Debug, PartialEq)]
pub enum Edge {
RISING,
FALLING,
RISING_FALLING,
}
pub trait ExtiPin {
fn make_interrupt_source(&mut self, afio: &mut afio::Parts);
fn trigger_on_edge(&mut self, exti: &EXTI, level: Edge);
fn enable_interrupt(&mut self, exti: &EXTI);
fn disable_interrupt(&mut self, exti: &EXTI);
fn clear_interrupt_pending_bit(&mut self);
fn check_interrupt(&mut self) -> bool;
}
pub enum Dynamic {
InputFloating,
InputPullUp,
InputPullDown,
OutputPushPull,
OutputOpenDrain,
}
impl Active for Dynamic {}
#[derive(Debug, PartialEq)]
pub enum PinModeError {
IncorrectMode,
}
impl Dynamic {
fn is_input(&self) -> bool {
use Dynamic::*;
match self {
InputFloating | InputPullUp | InputPullDown | OutputOpenDrain => true,
OutputPushPull => false,
}
}
fn is_output(&self) -> bool {
use Dynamic::*;
match self {
InputFloating | InputPullUp | InputPullDown => false,
OutputPushPull | OutputOpenDrain => true,
}
}
}
pub trait PinMode<CR> {
unsafe fn set_mode(cr: &mut CR) -> Self;
}
impl<MODE> Input<MODE> {
const fn _new() -> Self {
Self { _mode: PhantomData }
}
}
impl<MODE> Output<MODE> {
const fn _new() -> Self {
Self { _mode: PhantomData }
}
}
impl<MODE> Alternate<MODE> {
const fn _new() -> Self {
Self { _mode: PhantomData }
}
}
impl Debugger {
const fn _new() -> Self {
Self {}
}
}
macro_rules! gpio {
($GPIOX:ident, $gpiox:ident, $gpioy:ident, $PXx:ident, $extigpionr:expr, [
$($PXi:ident: ($pxi:ident, $i:expr, $MODE:ty, $CR:ident, $exticri:ident),)+
]) => {
pub mod $gpiox {
use core::convert::Infallible;
use core::marker::PhantomData;
use crate::hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin, toggleable};
use crate::pac::{$gpioy, $GPIOX};
use crate::pac::EXTI;
use crate::afio;
use crate::rcc::{APB2, Enable, Reset};
use super::{
Alternate, Floating, GpioExt, Input,
OpenDrain,
Output,
PullDown,
PullUp,
PushPull,
Analog,
State,
Active,
Debugger,
Pxx,
Mode,
Edge,
ExtiPin,
PinMode,
Dynamic,
PinModeError,
OutputSpeed,
IOPinSpeed,
};
pub struct Parts {
pub crl: CRL,
pub crh: CRH,
$(
pub $pxi: $PXi<$MODE>,
)+
}
impl GpioExt for $GPIOX {
type Parts = Parts;
fn split(self, apb: &mut APB2) -> Parts {
$GPIOX::enable(apb);
$GPIOX::reset(apb);
Parts {
crl: CRL { _0: () },
crh: CRH { _0: () },
$(
$pxi: $PXi { mode: <$MODE>::_new() },
)+
}
}
}
pub struct CRL {
_0: (),
}
impl CRL {
#[allow(dead_code)]
pub(crate) fn cr(&mut self) -> &$gpioy::CRL {
unsafe { &(*$GPIOX::ptr()).crl }
}
}
pub struct CRH {
_0: (),
}
impl CRH {
pub(crate) fn cr(&mut self) -> &$gpioy::CRH {
unsafe { &(*$GPIOX::ptr()).crh }
}
}
pub struct Generic<MODE> {
i: u8,
_mode: PhantomData<MODE>,
}
impl<MODE> Generic<MODE> {
pub fn downgrade(self) -> Pxx<MODE> {
Pxx::$PXx(self)
}
}
impl<MODE> OutputPin for Generic<Output<MODE>> {
type Error = Infallible;
fn set_high(&mut self) -> Result<(), Self::Error> {
Ok(unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << self.i)) })
}
fn set_low(&mut self) -> Result<(), Self::Error> {
Ok(unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << (16 + self.i))) })
}
}
impl<MODE> InputPin for Generic<Input<MODE>> {
type Error = Infallible;
fn is_high(&self) -> Result<bool, Self::Error> {
self.is_low().map(|b| !b)
}
fn is_low(&self) -> Result<bool, Self::Error> {
Ok(unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << self.i) == 0 })
}
}
impl<MODE> ExtiPin for Generic<Input<MODE>> {
fn make_interrupt_source(&mut self, afio: &mut afio::Parts) {
let offset = 4 * (self.i % 4);
match self.i {
0..=3 => {
afio.exticr1.exticr1().modify(|r, w| unsafe {
w.bits((r.bits() & !(0xf << offset)) | ($extigpionr << offset))
});
},
4..=7 => {
afio.exticr2.exticr2().modify(|r, w| unsafe {
w.bits((r.bits() & !(0xf << offset)) | ($extigpionr << offset))
});
},
8..=11 => {
afio.exticr3.exticr3().modify(|r, w| unsafe {
w.bits((r.bits() & !(0xf << offset)) | ($extigpionr << offset))
});
},
12..=15 => {
afio.exticr4.exticr4().modify(|r, w| unsafe {
w.bits((r.bits() & !(0xf << offset)) | ($extigpionr << offset))
});
},
_ => unreachable!(),
}
}
fn trigger_on_edge(&mut self, exti: &EXTI, edge: Edge) {
match edge {
Edge::RISING => {
exti.rtsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) });
exti.ftsr.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.i)) });
},
Edge::FALLING => {
exti.ftsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) });
exti.rtsr.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.i)) });
},
Edge::RISING_FALLING => {
exti.rtsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) });
exti.ftsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) });
}
}
}
fn enable_interrupt(&mut self, exti: &EXTI) {
exti.imr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) });
}
fn disable_interrupt(&mut self, exti: &EXTI) {
exti.imr.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.i)) });
}
fn clear_interrupt_pending_bit(&mut self) {
unsafe { (*EXTI::ptr()).pr.write(|w| w.bits(1 << self.i) ) };
}
fn check_interrupt(&mut self) -> bool {
unsafe { ((*EXTI::ptr()).pr.read().bits() & (1 << self.i)) != 0 }
}
}
impl <MODE> StatefulOutputPin for Generic<Output<MODE>> {
fn is_set_high(&self) -> Result<bool, Self::Error> {
self.is_set_low().map(|b| !b)
}
fn is_set_low(&self) -> Result<bool, Self::Error> {
Ok(unsafe { (*$GPIOX::ptr()).odr.read().bits() & (1 << self.i) == 0 })
}
}
impl <MODE> toggleable::Default for Generic<Output<MODE>> {}
impl InputPin for Generic<Output<OpenDrain>> {
type Error = Infallible;
fn is_high(&self) -> Result<bool, Self::Error> {
self.is_low().map(|b| !b)
}
fn is_low(&self) -> Result<bool, Self::Error> {
Ok(unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << self.i) == 0 })
}
}
pub type $PXx<MODE> = Pxx<MODE>;
impl<MODE> Mode<MODE> for Generic<MODE> {}
$(
pub struct $PXi<MODE> {
mode: MODE,
}
impl<MODE> Mode<MODE> for $PXi<MODE> {}
impl $PXi<Debugger> {
#[allow(dead_code)]
pub(crate) unsafe fn activate(self) -> $PXi<Input<Floating>> {
$PXi { mode: Input::_new() }
}
}
impl<MODE> $PXi<MODE> where MODE: Active {
#[inline]
pub fn into_alternate_push_pull(
self,
cr: &mut $CR,
) -> $PXi<Alternate<PushPull>> {
const OFFSET: u32 = (4 * $i) % 32;
const CNF: u32 = 0b10;
const MODE: u32 = 0b11;
const BITS: u32 = (CNF << 2) | MODE;
cr
.cr()
.modify(|r, w| unsafe {
w.bits((r.bits() & !(0b1111 << OFFSET)) | (BITS << OFFSET))
});
$PXi { mode: Alternate::_new() }
}
#[inline]
pub fn into_alternate_open_drain(
self,
cr: &mut $CR,
) -> $PXi<Alternate<OpenDrain>> {
const OFFSET: u32 = (4 * $i) % 32;
const CNF: u32 = 0b11;
const MODE: u32 = 0b11;
const BITS: u32 = (CNF << 2) | MODE;
cr
.cr()
.modify(|r, w| unsafe {
w.bits((r.bits() & !(0b1111 << OFFSET)) | (BITS << OFFSET))
});
$PXi { mode: Alternate::_new() }
}
#[inline]
pub fn into_floating_input(
self,
cr: &mut $CR,
) -> $PXi<Input<Floating>> {
unsafe {
$PXi::<Input<Floating>>::set_mode(cr)
}
}
#[inline]
pub fn into_pull_down_input(
self,
cr: &mut $CR,
) -> $PXi<Input<PullDown>> {
unsafe {
$PXi::<Input<PullDown>>::set_mode(cr)
}
}
#[inline]
pub fn into_pull_up_input(
self,
cr: &mut $CR,
) -> $PXi<Input<PullUp>> {
unsafe {
$PXi::<Input<PullUp>>::set_mode(cr)
}
}
#[inline]
pub fn into_open_drain_output(
self,
cr: &mut $CR,
) -> $PXi<Output<OpenDrain>> {
self.into_open_drain_output_with_state(cr, State::Low)
}
#[inline]
pub fn into_open_drain_output_with_state(
mut self,
cr: &mut $CR,
initial_state: State,
) -> $PXi<Output<OpenDrain>> {
self.set_state(initial_state);
unsafe {
$PXi::<Output<OpenDrain>>::set_mode(cr)
}
}
#[inline]
pub fn into_push_pull_output(
self,
cr: &mut $CR,
) -> $PXi<Output<PushPull>> {
self.into_push_pull_output_with_state(cr, State::Low)
}
#[inline]
pub fn into_push_pull_output_with_state(
mut self,
cr: &mut $CR,
initial_state: State,
) -> $PXi<Output<PushPull>> {
self.set_state(initial_state);
unsafe {
$PXi::<Output<PushPull>>::set_mode(cr)
}
}
#[inline]
pub fn into_analog(self, cr: &mut $CR) -> $PXi<Analog> {
unsafe {
$PXi::<Analog>::set_mode(cr)
}
}
#[inline]
pub fn into_dynamic(self, cr: &mut $CR) -> $PXi<Dynamic> {
self.into_floating_input(cr);
$PXi::<Dynamic>{mode: Dynamic::InputFloating}
}
}
macro_rules! impl_temp_output {
(
$fn_name:ident,
$stateful_fn_name:ident,
$mode:ty
) => {
#[inline]
pub fn $fn_name(
&mut self,
cr: &mut $CR,
mut f: impl FnMut(&mut $PXi<$mode>)
) {
let mut temp = unsafe { $PXi::<$mode>::set_mode(cr) };
f(&mut temp);
unsafe {
Self::set_mode(cr);
}
}
#[inline]
pub fn $stateful_fn_name(
&mut self,
cr: &mut $CR,
state: State,
mut f: impl FnMut(&mut $PXi<$mode>)
) {
self.set_state(state);
let mut temp = unsafe { $PXi::<$mode>::set_mode(cr) };
f(&mut temp);
unsafe {
Self::set_mode(cr);
}
}
}
}
macro_rules! impl_temp_input {
(
$fn_name:ident,
$mode:ty
) => {
#[inline]
pub fn $fn_name(
&mut self,
cr: &mut $CR,
mut f: impl FnMut(&mut $PXi<$mode>)
) {
let mut temp = unsafe { $PXi::<$mode>::set_mode(cr) };
f(&mut temp);
unsafe {
Self::set_mode(cr);
}
}
}
}
impl<MODE> $PXi<MODE> where MODE: Active, $PXi<MODE>: PinMode<$CR> {
impl_temp_output!(
as_push_pull_output,
as_push_pull_output_with_state,
Output<PushPull>
);
impl_temp_output!(
as_open_drain_output,
as_open_drain_output_with_state,
Output<OpenDrain>
);
impl_temp_input!(
as_floating_input,
Input<Floating>
);
impl_temp_input!(
as_pull_up_input,
Input<PullUp>
);
impl_temp_input!(
as_pull_down_input,
Input<PullDown>
);
}
impl<MODE> $PXi<MODE> where MODE: Active {
#[inline]
fn into_generic(self) -> Generic<MODE> {
Generic {
i: $i,
_mode: PhantomData,
}
}
pub fn downgrade(self) -> Pxx<MODE> {
self.into_generic().downgrade()
}
}
impl<MODE> OutputPin for $PXi<Output<MODE>> {
type Error = Infallible;
#[inline]
fn set_high(&mut self) -> Result<(), Self::Error> {
Ok(self.set_state(State::High))
}
#[inline]
fn set_low(&mut self) -> Result<(), Self::Error> {
Ok(self.set_state(State::Low))
}
}
impl<MODE> StatefulOutputPin for $PXi<Output<MODE>> {
#[inline]
fn is_set_high(&self) -> Result<bool, Self::Error> {
self.is_set_low().map(|b| !b)
}
#[inline]
fn is_set_low(&self) -> Result<bool, Self::Error> {
Ok(self._is_set_low())
}
}
impl<MODE> OutputSpeed<$CR> for $PXi<Output<MODE>> {
fn set_speed(&mut self, cr: &mut $CR, speed: IOPinSpeed){
const OFFSET: u32 = (4 * $i) % 32;
cr.cr().modify(|r, w| unsafe {
w.bits((r.bits() & !(0b11 << OFFSET)) | ((speed as u32) << OFFSET))
});
}
}
impl OutputSpeed<$CR> for $PXi<Alternate<PushPull>> {
fn set_speed(&mut self, cr: &mut $CR, speed: IOPinSpeed){
const OFFSET: u32 = (4 * $i) % 32;
cr.cr().modify(|r, w| unsafe {
w.bits((r.bits() & !(0b11 << OFFSET)) | ((speed as u32) << OFFSET))
});
}
}
impl<MODE> toggleable::Default for $PXi<Output<MODE>> {}
impl<MODE> InputPin for $PXi<Input<MODE>> {
type Error = Infallible;
#[inline]
fn is_high(&self) -> Result<bool, Self::Error> {
self.is_low().map(|b| !b)
}
#[inline]
fn is_low(&self) -> Result<bool, Self::Error> {
Ok(self._is_low())
}
}
impl InputPin for $PXi<Output<OpenDrain>> {
type Error = Infallible;
#[inline]
fn is_high(&self) -> Result<bool, Self::Error> {
self.is_low().map(|b| !b)
}
#[inline]
fn is_low(&self) -> Result<bool, Self::Error> {
Ok(self._is_low())
}
}
impl $PXi<Dynamic> {
#[inline]
pub fn make_pull_up_input(&mut self, cr: &mut $CR) {
unsafe { $PXi::<Input<PullUp>>::set_mode(cr) };
self.mode = Dynamic::InputPullUp;
}
#[inline]
pub fn make_pull_down_input(&mut self, cr: &mut $CR) {
unsafe { $PXi::<Input<PullDown>>::set_mode(cr) };
self.mode = Dynamic::InputPullDown;
}
#[inline]
pub fn make_floating_input(&mut self, cr: &mut $CR) {
unsafe { $PXi::<Input<Floating>>::set_mode(cr) };
self.mode = Dynamic::InputFloating;
}
#[inline]
pub fn make_push_pull_output(&mut self, cr: &mut $CR) {
unsafe { $PXi::<Output<PushPull>>::set_mode(cr) };
self.mode = Dynamic::OutputPushPull;
}
#[inline]
pub fn make_open_drain_output(&mut self, cr: &mut $CR) {
unsafe { $PXi::<Output<OpenDrain>>::set_mode(cr) };
self.mode = Dynamic::OutputOpenDrain;
}
}
impl OutputPin for $PXi<Dynamic> {
type Error = PinModeError;
fn set_high(&mut self) -> Result<(), Self::Error> {
if self.mode.is_output() {
self.set_state(State::High);
Ok(())
}
else {
Err(PinModeError::IncorrectMode)
}
}
fn set_low(&mut self) -> Result<(), Self::Error> {
if self.mode.is_output() {
self.set_state(State::Low);
Ok(())
}
else {
Err(PinModeError::IncorrectMode)
}
}
}
impl InputPin for $PXi<Dynamic> {
type Error = PinModeError;
fn is_high(&self) -> Result<bool, Self::Error> {
self.is_low().map(|b| !b)
}
fn is_low(&self) -> Result<bool, Self::Error> {
if self.mode.is_input() {
Ok(self._is_low())
}
else {
Err(PinModeError::IncorrectMode)
}
}
}
impl<MODE> ExtiPin for $PXi<Input<MODE>> {
fn make_interrupt_source(&mut self, afio: &mut afio::Parts) {
let offset = 4 * ($i % 4);
afio.$exticri.$exticri().modify(|r, w| unsafe {
let mut exticr = r.bits();
exticr = (exticr & !(0xf << offset)) | ($extigpionr << offset);
w.bits(exticr)
});
}
fn trigger_on_edge(&mut self, exti: &EXTI, edge: Edge) {
match edge {
Edge::RISING => {
exti.rtsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) });
exti.ftsr.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << $i)) });
},
Edge::FALLING => {
exti.ftsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) });
exti.rtsr.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << $i)) });
},
Edge::RISING_FALLING => {
exti.rtsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) });
exti.ftsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) });
}
}
}
#[inline]
fn enable_interrupt(&mut self, exti: &EXTI) {
exti.imr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) });
}
#[inline]
fn disable_interrupt(&mut self, exti: &EXTI) {
exti.imr.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << $i)) });
}
#[inline]
fn clear_interrupt_pending_bit(&mut self) {
unsafe { (*EXTI::ptr()).pr.write(|w| w.bits(1 << $i) ) };
}
#[inline]
fn check_interrupt(&mut self) -> bool {
unsafe { ((*EXTI::ptr()).pr.read().bits() & (1 << $i)) != 0 }
}
}
impl<MODE> $PXi<MODE> {
fn set_state(&mut self, state: State) {
match state {
State::High => unsafe {
(*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << $i))
}
State::Low => unsafe {
(*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << (16 + $i)))
}
}
}
fn _is_set_low(&self) -> bool {
unsafe { (*$GPIOX::ptr()).odr.read().bits() & (1 << $i) == 0 }
}
fn _is_low(&self) -> bool {
unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << $i) == 0 }
}
}
impl PinMode<$CR> for $PXi<Input<Floating>> {
unsafe fn set_mode(cr: &mut $CR) -> Self {
const OFFSET: u32 = (4 * $i) % 32;
const CNF: u32 = 0b01;
const MODE: u32 = 0b00;
const BITS: u32 = (CNF << 2) | MODE;
cr
.cr()
.modify(|r, w| {
w.bits((r.bits() & !(0b1111 << OFFSET)) | (BITS << OFFSET))
});
$PXi { mode: Input::_new() }
}
}
impl PinMode<$CR> for $PXi<Input<PullDown>> {
unsafe fn set_mode(cr: &mut $CR) -> Self {
const OFFSET: u32 = (4 * $i) % 32;
const CNF: u32 = 0b10;
const MODE: u32 = 0b00;
const BITS: u32 = (CNF << 2) | MODE;
(*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << (16 + $i)));
cr
.cr()
.modify(|r, w| {
w.bits((r.bits() & !(0b1111 << OFFSET)) | (BITS << OFFSET))
});
$PXi { mode: Input::_new() }
}
}
impl PinMode<$CR> for $PXi<Input<PullUp>> {
unsafe fn set_mode(cr: &mut $CR) -> Self {
const OFFSET: u32 = (4 * $i) % 32;
const CNF: u32 = 0b10;
const MODE: u32 = 0b00;
const BITS: u32 = (CNF << 2) | MODE;
(*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << $i));
cr
.cr()
.modify(|r, w| {
w.bits((r.bits() & !(0b1111 << OFFSET)) | (BITS << OFFSET))
});
$PXi { mode: Input::_new() }
}
}
impl PinMode<$CR> for $PXi<Output<OpenDrain>> {
unsafe fn set_mode(cr: &mut $CR) -> Self {
const OFFSET: u32 = (4 * $i) % 32;
const CNF: u32 = 0b01;
const MODE: u32 = 0b11;
const BITS: u32 = (CNF << 2) | MODE;
cr
.cr()
.modify(|r, w| {
w.bits((r.bits() & !(0b1111 << OFFSET)) | (BITS << OFFSET))
});
$PXi { mode: Output::_new() }
}
}
impl PinMode<$CR> for $PXi<Output<PushPull>> {
unsafe fn set_mode(cr: &mut $CR) -> Self {
const OFFSET: u32 = (4 * $i) % 32;
const CNF: u32 = 0b00;
const MODE: u32 = 0b11;
const BITS: u32 = (CNF << 2) | MODE;
cr
.cr()
.modify(|r, w| {
w.bits((r.bits() & !(0b1111 << OFFSET)) | (BITS << OFFSET))
});
$PXi { mode: Output::_new() }
}
}
impl PinMode<$CR> for $PXi<Analog> {
unsafe fn set_mode(cr: &mut $CR) -> Self {
const OFFSET: u32 = (4 * $i) % 32;
const CNF: u32 = 0b00;
const MODE: u32 = 0b00;
const BITS: u32 = (CNF << 2) | MODE;
cr
.cr()
.modify(|r, w| {
w.bits((r.bits() & !(0b1111 << OFFSET)) | (BITS << OFFSET))
});
$PXi { mode: Analog{} }
}
}
)+
}
}
}
macro_rules! impl_pxx {
($(($port:ident :: $pin:ident)),*) => {
use embedded_hal::digital::v2::{InputPin, StatefulOutputPin, OutputPin};
use core::convert::Infallible;
pub enum Pxx<MODE> {
$(
$pin($port::Generic<MODE>)
),*
}
impl<MODE> OutputPin for Pxx<Output<MODE>> {
type Error = Infallible;
fn set_high(&mut self) -> Result<(), Infallible> {
match self {
$(Pxx::$pin(pin) => pin.set_high()),*
}
}
fn set_low(&mut self) -> Result<(), Infallible> {
match self {
$(Pxx::$pin(pin) => pin.set_low()),*
}
}
}
impl<MODE> StatefulOutputPin for Pxx<Output<MODE>> {
fn is_set_high(&self) -> Result<bool, Self::Error> {
match self {
$(Pxx::$pin(pin) => pin.is_set_high()),*
}
}
fn is_set_low(&self) -> Result<bool, Self::Error> {
match self {
$(Pxx::$pin(pin) => pin.is_set_low()),*
}
}
}
impl<MODE> InputPin for Pxx<Input<MODE>> {
type Error = Infallible;
fn is_high(&self) -> Result<bool, Infallible> {
match self {
$(Pxx::$pin(pin) => pin.is_high()),*
}
}
fn is_low(&self) -> Result<bool, Infallible> {
match self {
$(Pxx::$pin(pin) => pin.is_low()),*
}
}
}
impl InputPin for Pxx<Output<OpenDrain>> {
type Error = Infallible;
fn is_high(&self) -> Result<bool, Infallible> {
match self {
$(Pxx::$pin(pin) => pin.is_high()),*
}
}
fn is_low(&self) -> Result<bool, Infallible> {
match self {
$(Pxx::$pin(pin) => pin.is_low()),*
}
}
}
impl<MODE> ExtiPin for Pxx<Input<MODE>> {
fn make_interrupt_source(&mut self, afio: &mut afio::Parts) {
match self {
$(Pxx::$pin(pin) => pin.make_interrupt_source(afio)),*
}
}
fn trigger_on_edge(&mut self, exti: &EXTI, level: Edge) {
match self {
$(Pxx::$pin(pin) => pin.trigger_on_edge(exti, level)),*
}
}
fn enable_interrupt(&mut self, exti: &EXTI) {
match self {
$(Pxx::$pin(pin) => pin.enable_interrupt(exti)),*
}
}
fn disable_interrupt(&mut self, exti: &EXTI) {
match self {
$(Pxx::$pin(pin) => pin.disable_interrupt(exti)),*
}
}
fn clear_interrupt_pending_bit(&mut self) {
match self {
$(Pxx::$pin(pin) => pin.clear_interrupt_pending_bit()),*
}
}
fn check_interrupt(&mut self) -> bool {
match self {
$(Pxx::$pin(pin) => pin.check_interrupt()),*
}
}
}
}
}
impl_pxx! {
(gpioa::PAx),
(gpiob::PBx),
(gpioc::PCx),
(gpiod::PDx),
(gpioe::PEx)
}
gpio!(GPIOA, gpioa, gpioa, PAx, 0, [
PA0: (pa0, 0, Input<Floating>, CRL, exticr1),
PA1: (pa1, 1, Input<Floating>, CRL, exticr1),
PA2: (pa2, 2, Input<Floating>, CRL, exticr1),
PA3: (pa3, 3, Input<Floating>, CRL, exticr1),
PA4: (pa4, 4, Input<Floating>, CRL, exticr2),
PA5: (pa5, 5, Input<Floating>, CRL, exticr2),
PA6: (pa6, 6, Input<Floating>, CRL, exticr2),
PA7: (pa7, 7, Input<Floating>, CRL, exticr2),
PA8: (pa8, 8, Input<Floating>, CRH, exticr3),
PA9: (pa9, 9, Input<Floating>, CRH, exticr3),
PA10: (pa10, 10, Input<Floating>, CRH, exticr3),
PA11: (pa11, 11, Input<Floating>, CRH, exticr3),
PA12: (pa12, 12, Input<Floating>, CRH, exticr4),
PA13: (pa13, 13, Debugger, CRH, exticr4),
PA14: (pa14, 14, Debugger, CRH, exticr4),
PA15: (pa15, 15, Debugger, CRH, exticr4),
]);
gpio!(GPIOB, gpiob, gpioa, PBx, 1, [
PB0: (pb0, 0, Input<Floating>, CRL, exticr1),
PB1: (pb1, 1, Input<Floating>, CRL, exticr1),
PB2: (pb2, 2, Input<Floating>, CRL, exticr1),
PB3: (pb3, 3, Debugger, CRL, exticr1),
PB4: (pb4, 4, Debugger, CRL, exticr2),
PB5: (pb5, 5, Input<Floating>, CRL, exticr2),
PB6: (pb6, 6, Input<Floating>, CRL, exticr2),
PB7: (pb7, 7, Input<Floating>, CRL, exticr2),
PB8: (pb8, 8, Input<Floating>, CRH, exticr3),
PB9: (pb9, 9, Input<Floating>, CRH, exticr3),
PB10: (pb10, 10, Input<Floating>, CRH, exticr3),
PB11: (pb11, 11, Input<Floating>, CRH, exticr3),
PB12: (pb12, 12, Input<Floating>, CRH, exticr4),
PB13: (pb13, 13, Input<Floating>, CRH, exticr4),
PB14: (pb14, 14, Input<Floating>, CRH, exticr4),
PB15: (pb15, 15, Input<Floating>, CRH, exticr4),
]);
gpio!(GPIOC, gpioc, gpioa, PCx, 2, [
PC0: (pc0, 0, Input<Floating>, CRL, exticr1),
PC1: (pc1, 1, Input<Floating>, CRL, exticr1),
PC2: (pc2, 2, Input<Floating>, CRL, exticr1),
PC3: (pc3, 3, Input<Floating>, CRL, exticr1),
PC4: (pc4, 4, Input<Floating>, CRL, exticr2),
PC5: (pc5, 5, Input<Floating>, CRL, exticr2),
PC6: (pc6, 6, Input<Floating>, CRL, exticr2),
PC7: (pc7, 7, Input<Floating>, CRL, exticr2),
PC8: (pc8, 8, Input<Floating>, CRH, exticr3),
PC9: (pc9, 9, Input<Floating>, CRH, exticr3),
PC10: (pc10, 10, Input<Floating>, CRH, exticr3),
PC11: (pc11, 11, Input<Floating>, CRH, exticr3),
PC12: (pc12, 12, Input<Floating>, CRH, exticr4),
PC13: (pc13, 13, Input<Floating>, CRH, exticr4),
PC14: (pc14, 14, Input<Floating>, CRH, exticr4),
PC15: (pc15, 15, Input<Floating>, CRH, exticr4),
]);
gpio!(GPIOD, gpiod, gpioa, PDx, 3, [
PD0: (pd0, 0, Input<Floating>, CRL, exticr1),
PD1: (pd1, 1, Input<Floating>, CRL, exticr1),
PD2: (pd2, 2, Input<Floating>, CRL, exticr1),
PD3: (pd3, 3, Input<Floating>, CRL, exticr1),
PD4: (pd4, 4, Input<Floating>, CRL, exticr2),
PD5: (pd5, 5, Input<Floating>, CRL, exticr2),
PD6: (pd6, 6, Input<Floating>, CRL, exticr2),
PD7: (pd7, 7, Input<Floating>, CRL, exticr2),
PD8: (pd8, 8, Input<Floating>, CRH, exticr3),
PD9: (pd9, 9, Input<Floating>, CRH, exticr3),
PD10: (pd10, 10, Input<Floating>, CRH, exticr3),
PD11: (pd11, 11, Input<Floating>, CRH, exticr3),
PD12: (pd12, 12, Input<Floating>, CRH, exticr4),
PD13: (pd13, 13, Input<Floating>, CRH, exticr4),
PD14: (pd14, 14, Input<Floating>, CRH, exticr4),
PD15: (pd15, 15, Input<Floating>, CRH, exticr4),
]);
gpio!(GPIOE, gpioe, gpioa, PEx, 4, [
PE0: (pe0, 0, Input<Floating>, CRL, exticr1),
PE1: (pe1, 1, Input<Floating>, CRL, exticr1),
PE2: (pe2, 2, Input<Floating>, CRL, exticr1),
PE3: (pe3, 3, Input<Floating>, CRL, exticr1),
PE4: (pe4, 4, Input<Floating>, CRL, exticr2),
PE5: (pe5, 5, Input<Floating>, CRL, exticr2),
PE6: (pe6, 6, Input<Floating>, CRL, exticr2),
PE7: (pe7, 7, Input<Floating>, CRL, exticr2),
PE8: (pe8, 8, Input<Floating>, CRH, exticr3),
PE9: (pe9, 9, Input<Floating>, CRH, exticr3),
PE10: (pe10, 10, Input<Floating>, CRH, exticr3),
PE11: (pe11, 11, Input<Floating>, CRH, exticr3),
PE12: (pe12, 12, Input<Floating>, CRH, exticr4),
PE13: (pe13, 13, Input<Floating>, CRH, exticr4),
PE14: (pe14, 14, Input<Floating>, CRH, exticr4),
PE15: (pe15, 15, Input<Floating>, CRH, exticr4),
]);