use core::convert::Infallible;
use cortex_m::interrupt::free;
use crate::{
pac::{self, EXTI, RCC},
rcc_en_reset,
};
#[cfg(not(any(feature = "l5", feature = "g0")))]
use crate::pac::SYSCFG;
#[cfg(feature = "embedded-hal")]
use embedded_hal::digital::v2::{InputPin, OutputPin, ToggleableOutputPin};
use cfg_if::cfg_if;
use paste::paste;
#[derive(Copy, Clone)]
#[repr(u8)]
pub enum PinMode {
Input,
Output,
Alt(u8),
Analog,
}
impl PinMode {
fn val(&self) -> u8 {
match self {
Self::Input => 0b00,
Self::Output => 0b01,
Self::Alt(_) => 0b10,
Self::Analog => 0b11,
}
}
}
#[derive(Copy, Clone)]
#[repr(u8)]
pub enum OutputType {
PushPull = 0,
OpenDrain = 1,
}
#[derive(Copy, Clone)]
#[repr(u8)]
pub enum OutputSpeed {
Low = 0,
Medium = 0b01,
High = 0b11,
}
#[derive(Copy, Clone)]
#[repr(u8)]
pub enum Pull {
Floating = 0b00,
Up = 0b01,
Dn = 0b10,
}
#[derive(Copy, Clone)]
#[repr(u8)]
pub enum PinState {
High = 1,
Low = 0,
}
#[derive(Copy, Clone)]
#[repr(u8)]
pub enum CfgLock {
NotLocked = 0,
Locked = 1,
}
#[derive(Copy, Clone)]
#[repr(u8)]
pub enum ResetState {
NoAction = 0,
Reset = 1,
}
#[derive(Copy, Clone)]
pub enum Port {
A,
B,
C,
#[cfg(not(any(feature = "f410")))]
D,
#[cfg(not(any(
feature = "f301",
feature = "f3x4",
feature = "f410",
feature = "g0",
feature = "wb",
feature = "wl"
)))]
E,
#[cfg(not(any(
feature = "f401",
feature = "f410",
feature = "f411",
feature = "l4x1",
feature = "l4x2",
feature = "l412",
feature = "l4x3",
feature = "wb",
feature = "wl"
)))]
F,
#[cfg(not(any(
feature = "f373",
feature = "f301",
feature = "f3x4",
feature = "f410",
feature = "l4",
feature = "g0",
feature = "g4",
feature = "wb",
feature = "wl"
)))]
H,
}
impl Port {
fn cr_val(&self) -> u8 {
match self {
Self::A => 0,
Self::B => 1,
Self::C => 2,
#[cfg(not(any(feature = "f410")))]
Self::D => 3,
#[cfg(not(any(
feature = "f301",
feature = "f3x4",
feature = "f410",
feature = "g0",
feature = "wb",
feature = "wl"
)))]
Self::E => 4,
#[cfg(not(any(
feature = "f401",
feature = "f410",
feature = "f411",
feature = "l4x1",
feature = "l4x2",
feature = "l412",
feature = "l4x3",
feature = "wb",
feature = "wl"
)))]
Self::F => 5,
#[cfg(not(any(
feature = "f373",
feature = "f301",
feature = "f3x4",
feature = "f410",
feature = "l4",
feature = "g0",
feature = "g4",
feature = "wb",
feature = "wl"
)))]
Self::H => 7,
}
}
}
#[derive(Copy, Clone, Debug)]
pub enum Edge {
Rising,
Falling,
}
macro_rules! set_field2 { ($pin:expr, $port_letter:expr, $reg:ident, $field:ident, $bit:ident, $val:expr, [$($num:expr),+]) => {
paste! {
unsafe {
match $port_letter {
Port::A => {
match $pin {
$(
$num => (*pac::GPIOA::ptr()).$reg.modify(|_, w| w.[<$field $num>]().$bit($val)),
)+
_ => panic!("GPIO pins must be 0 - 15."),
}
}
Port::B => {
match $pin {
$(
$num => (*pac::GPIOB::ptr()).$reg.modify(|_, w| w.[<$field $num>]().$bit($val)),
)+
_ => panic!("GPIO pins must be 0 - 15."),
}
}
Port::C => {
match $pin {
$(
$num => (*pac::GPIOC::ptr()).$reg.modify(|_, w| w.[<$field $num>]().$bit($val)),
)+
_ => panic!("GPIO pins must be 0 - 15."),
}
}
#[cfg(not(any(feature = "f410")))]
Port::D => {
match $pin {
$(
$num => (*pac::GPIOD::ptr()).$reg.modify(|_, w| w.[<$field $num>]().$bit($val)),
)+
_ => panic!("GPIO pins must be 0 - 15."),
}
}
#[cfg(not(any(feature = "f301", feature = "f3x4", feature = "f410", feature = "g0", feature = "wb", feature = "wl")))]
Port::E => {
match $pin {
$(
$num => (*pac::GPIOE::ptr()).$reg.modify(|_, w| w.[<$field $num>]().$bit($val)),
)+
_ => panic!("GPIO pins must be 0 - 15."),
}
}
#[cfg(not(any(
feature = "f401",
feature = "f410",
feature = "f411",
feature = "l4x1",
feature = "l4x2",
feature = "l412",
feature = "l4x3",
feature = "wb",
feature = "wl"
)))]
Port::F => {
match $pin {
$(
$num => (*pac::GPIOF::ptr()).$reg.modify(|_, w| w.[<$field $num>]().$bit($val)),
)+
_ => panic!("GPIO pins must be 0 - 15."),
}
}
#[cfg(not(any(
feature = "f373",
feature = "f301",
feature = "f3x4",
feature = "f410",
feature = "l4",
feature = "g0",
feature = "g4",
feature = "wb",
feature = "wl"
)))]
Port::H => {
match $pin {
$(
$num => (*pac::GPIOH::ptr()).$reg.modify(|_, w| w.[<$field $num>]().$bit($val)),
)+
_ => panic!("GPIO pins must be 0 - 15."),
}
}
}
}
}
}
}
macro_rules! set_alt2 { ($pin:expr, $port_letter:expr, $field_af:ident, $val:expr, [$(($num:expr, $lh:ident)),+]) => {
paste! {
unsafe {
match $port_letter {
Port::A => {
match $pin {
$(
$num => {
(*pac::GPIOA::ptr()).moder.modify(|_, w| w.[<moder $num>]().bits(PinMode::Alt(0).val()));
#[cfg(any(feature = "l5", feature = "g0", feature = "h7", feature = "wb", feature = "wl"))]
(*pac::GPIOA::ptr()).[<afr $lh>].modify(|_, w| w.[<$field_af $num>]().bits($val));
#[cfg(not(any(feature = "l5", feature = "g0", feature = "h7", feature = "wb", feature = "wl")))]
(*pac::GPIOA::ptr()).[<afr $lh>].modify(|_, w| w.[<$field_af $lh $num>]().bits($val));
}
)+
_ => panic!("GPIO pins must be 0 - 15."),
}
}
Port::B => {
match $pin {
$(
$num => {
(*pac::GPIOB::ptr()).moder.modify(|_, w| w.[<moder $num>]().bits(PinMode::Alt(0).val()));
#[cfg(any(feature = "l5", feature = "g0", feature = "h7", feature = "wb", feature = "wl"))]
(*pac::GPIOB::ptr()).[<afr $lh>].modify(|_, w| w.[<$field_af $num>]().bits($val));
#[cfg(not(any(feature = "l5", feature = "g0", feature = "h7", feature = "wb", feature = "wl")))]
(*pac::GPIOB::ptr()).[<afr $lh>].modify(|_, w| w.[<$field_af $lh $num>]().bits($val));
}
)+
_ => panic!("GPIO pins must be 0 - 15."),
}
}
Port::C => {
match $pin {
$(
$num => {
(*pac::GPIOC::ptr()).moder.modify(|_, w| w.[<moder $num>]().bits(PinMode::Alt(0).val()));
#[cfg(any(feature = "l5", feature = "g0", feature = "h7", feature = "wb", feature = "wl"))]
(*pac::GPIOC::ptr()).[<afr $lh>].modify(|_, w| w.[<$field_af $num>]().bits($val));
#[cfg(not(any(feature = "l5", feature = "g0", feature = "h7", feature = "wb", feature = "wl")))]
(*pac::GPIOC::ptr()).[<afr $lh>].modify(|_, w| w.[<$field_af $lh $num>]().bits($val));
}
)+
_ => panic!("GPIO pins must be 0 - 15."),
}
}
#[cfg(not(any(feature = "f410")))]
Port::D => {
match $pin {
$(
$num => {
(*pac::GPIOD::ptr()).moder.modify(|_, w| w.[<moder $num>]().bits(PinMode::Alt(0).val()));
#[cfg(any(feature = "l5", feature = "g0", feature = "h7", feature = "wb", feature = "wl"))]
(*pac::GPIOD::ptr()).[<afr $lh>].modify(|_, w| w.[<$field_af $num>]().bits($val));
#[cfg(not(any(feature = "l5", feature = "g0", feature = "h7", feature = "wb", feature = "wl")))]
(*pac::GPIOD::ptr()).[<afr $lh>].modify(|_, w| w.[<$field_af $lh $num>]().bits($val));
}
)+
_ => panic!("GPIO pins must be 0 - 15."),
}
}
#[cfg(not(any(feature = "f301", feature = "f3x4", feature = "f410", feature = "g0", feature = "wb", feature = "wl")))]
Port::E => {
match $pin {
$(
$num => {
(*pac::GPIOE::ptr()).moder.modify(|_, w| w.[<moder $num>]().bits(PinMode::Alt(0).val()));
#[cfg(any(feature = "l5", feature = "g0", feature = "h7", feature = "wb", feature = "wl"))]
(*pac::GPIOE::ptr()).[<afr $lh>].modify(|_, w| w.[<$field_af $num>]().bits($val));
#[cfg(not(any(feature = "l5", feature = "g0", feature = "h7", feature = "wb", feature = "wl")))]
(*pac::GPIOE::ptr()).[<afr $lh>].modify(|_, w| w.[<$field_af $lh $num>]().bits($val));
}
)+
_ => panic!("GPIO pins must be 0 - 15."),
}
}
#[cfg(not(any(
feature = "f401",
feature = "f410",
feature = "f411",
feature = "l4x1",
feature = "l4x2",
feature = "l412",
feature = "l4x3",
feature = "wb",
feature = "wl"
)))]
Port::F => {
match $pin {
$(
$num => {
(*pac::GPIOF::ptr()).moder.modify(|_, w| w.[<moder $num>]().bits(PinMode::Alt(0).val()));
#[cfg(any(feature = "l5", feature = "g0", feature = "h7", feature = "wb", feature = "wl"))]
(*pac::GPIOF::ptr()).[<afr $lh>].modify(|_, w| w.[<$field_af $num>]().bits($val));
#[cfg(not(any(feature = "l5", feature = "g0", feature = "h7", feature = "wb", feature = "wl")))]
(*pac::GPIOF::ptr()).[<afr $lh>].modify(|_, w| w.[<$field_af $lh $num>]().bits($val));
}
)+
_ => panic!("GPIO pins must be 0 - 15."),
}
}
#[cfg(not(any(
feature = "f373",
feature = "f301",
feature = "f3x4",
feature = "f410",
feature = "l4",
feature = "g0",
feature = "g4",
feature = "wb",
feature = "wl"
)))]
Port::H => {
match $pin {
$(
$num => {
(*pac::GPIOH::ptr()).moder.modify(|_, w| w.[<moder $num>]().bits(PinMode::Alt(0).val()));
#[cfg(any(feature = "l5", feature = "g0", feature = "h7", feature = "wb", feature = "wl"))]
(*pac::GPIOH::ptr()).[<afr $lh>].modify(|_, w| w.[<$field_af $num>]().bits($val));
#[cfg(not(any(feature = "l5", feature = "g0", feature = "h7", feature = "wb", feature = "wl")))]
(*pac::GPIOH::ptr()).[<afr $lh>].modify(|_, w| w.[<$field_af $lh $num>]().bits($val));
}
)+
_ => panic!("GPIO pins must be 0 - 15."),
}
}
}
}
}
}
}
macro_rules! get_input_data { ($pin:expr, $port_letter:expr, [$($num:expr),+]) => {
paste! {
unsafe {
match $port_letter {
Port::A => {
match $pin {
$(
$num => (*pac::GPIOA::ptr()).idr.read().[<idr $num>]().bit_is_set(),
)+
_ => panic!("GPIO pins must be 0 - 15."),
}
}
Port::B => {
match $pin {
$(
$num => (*pac::GPIOB::ptr()).idr.read().[<idr $num>]().bit_is_set(),
)+
_ => panic!("GPIO pins must be 0 - 15."),
}
}
Port::C => {
match $pin {
$(
$num => (*pac::GPIOC::ptr()).idr.read().[<idr $num>]().bit_is_set(),
)+
_ => panic!("GPIO pins must be 0 - 15."),
}
}
#[cfg(not(any(feature = "f410")))]
Port::D => {
match $pin {
$(
$num => (*pac::GPIOD::ptr()).idr.read().[<idr $num>]().bit_is_set(),
)+
_ => panic!("GPIO pins must be 0 - 15."),
}
}
#[cfg(not(any(feature = "f301", feature = "f3x4", feature = "f410", feature = "g0", feature = "wb", feature = "wl")))]
Port::E => {
match $pin {
$(
$num => (*pac::GPIOE::ptr()).idr.read().[<idr $num>]().bit_is_set(),
)+
_ => panic!("GPIO pins must be 0 - 15."),
}
}
#[cfg(not(any(
feature = "f401",
feature = "f410",
feature = "f411",
feature = "l4x1",
feature = "l4x2",
feature = "l412",
feature = "l4x3",
feature = "wb",
feature = "wl"
)))]
Port::F => {
match $pin {
$(
$num => (*pac::GPIOF::ptr()).idr.read().[<idr $num>]().bit_is_set(),
)+
_ => panic!("GPIO pins must be 0 - 15."),
}
}
#[cfg(not(any(
feature = "f373",
feature = "f301",
feature = "f3x4",
feature = "f410",
feature = "l4",
feature = "g0",
feature = "g4",
feature = "wb",
feature = "wl"
)))]
Port::H => {
match $pin {
$(
$num => (*pac::GPIOH::ptr()).idr.read().[<idr $num>]().bit_is_set(),
)+
_ => panic!("GPIO pins must be 0 - 15."),
}
}
}
}
}
}
}
macro_rules! set_state { ($pin:expr, $port_letter:expr, $offset: expr, [$($num:expr),+]) => {
paste! {
unsafe {
match $port_letter {
Port::A => {
match $pin {
$(
$num => (*pac::GPIOA::ptr()).bsrr.write(|w| w.bits(1 << ($offset + $num))),
)+
_ => panic!("GPIO pins must be 0 - 15."),
}
}
Port::B => {
match $pin {
$(
$num => (*pac::GPIOB::ptr()).bsrr.write(|w| w.bits(1 << ($offset + $num))),
)+
_ => panic!("GPIO pins must be 0 - 15."),
}
}
Port::C => {
match $pin {
$(
$num => (*pac::GPIOC::ptr()).bsrr.write(|w| w.bits(1 << ($offset + $num))),
)+
_ => panic!("GPIO pins must be 0 - 15."),
}
}
#[cfg(not(any(feature = "f410")))]
Port::D => {
match $pin {
$(
$num => (*pac::GPIOD::ptr()).bsrr.write(|w| w.bits(1 << ($offset + $num))),
)+
_ => panic!("GPIO pins must be 0 - 15."),
}
}
#[cfg(not(any(feature = "f301", feature = "f3x4", feature = "f410", feature = "g0", feature = "wb", feature = "wl")))]
Port::E => {
match $pin {
$(
$num => (*pac::GPIOE::ptr()).bsrr.write(|w| w.bits(1 << ($offset + $num))),
)+
_ => panic!("GPIO pins must be 0 - 15."),
}
}
#[cfg(not(any(
feature = "f401",
feature = "f410",
feature = "f411",
feature = "l4x1",
feature = "l4x2",
feature = "l412",
feature = "l4x3",
feature = "wb",
feature = "wl"
)))]
Port::F => {
match $pin {
$(
$num => (*pac::GPIOF::ptr()).bsrr.write(|w| w.bits(1 << ($offset + $num))),
)+
_ => panic!("GPIO pins must be 0 - 15."),
}
}
#[cfg(not(any(
feature = "f373",
feature = "f301",
feature = "f3x4",
feature = "f410",
feature = "l4",
feature = "g0",
feature = "g4",
feature = "wb",
feature = "wl"
)))]
Port::H => {
match $pin {
$(
$num => (*pac::GPIOH::ptr()).bsrr.write(|w| w.bits(1 << ($offset + $num))),
)+
_ => panic!("GPIO pins must be 0 - 15."),
}
}
}
}
}
}
}
macro_rules! set_exti {
($pin:expr, $trigger:expr, $val:expr, [$(($num:expr, $crnum:expr)),+]) => {
let exti = unsafe { &(*pac::EXTI::ptr()) };
let syscfg = unsafe { &(*pac::SYSCFG::ptr()) };
paste! {
match $pin {
$(
$num => {
cfg_if! {
if #[cfg(all(feature = "h7", not(any(feature = "h747cm4", feature = "h747cm7"))))] {
exti.cpuimr1.modify(|_, w| w.[<mr $num>]().set_bit());
} else if #[cfg(any(feature = "h747cm4", feature = "h747cm7"))] {
exti.c1imr1.modify(|_, w| w.[<mr $num>]().set_bit());
}else if #[cfg(any(feature = "g4", feature = "wb", feature = "wl"))] {
exti.imr1.modify(|_, w| w.[<im $num>]().set_bit());
} else {
exti.imr1.modify(|_, w| w.[<mr $num>]().set_bit());
}
}
cfg_if! {
if #[cfg(any(feature = "g4", feature = "wb", feature = "wl"))] {
exti.rtsr1.modify(|_, w| w.[<rt $num>]().bit($trigger));
exti.ftsr1.modify(|_, w| w.[<ft $num>]().bit(!$trigger));
} else {
exti.rtsr1.modify(|_, w| w.[<tr $num>]().bit($trigger));
exti.ftsr1.modify(|_, w| w.[<tr $num>]().bit(!$trigger));
}
}
syscfg
.[<exticr $crnum>]
.modify(|_, w| unsafe { w.[<exti $num>]().bits($val) });
}
)+
_ => panic!("GPIO pins must be 0 - 15."),
}
}
}
}
#[cfg(feature = "f4")]
macro_rules! set_exti_f4 {
($pin:expr, $trigger:expr, $val:expr, [$(($num:expr, $crnum:expr)),+]) => {
let exti = unsafe { &(*pac::EXTI::ptr()) };
let syscfg = unsafe { &(*pac::SYSCFG::ptr()) };
paste! {
match $pin {
$(
$num => {
exti.imr.modify(|_, w| w.[<mr $num>]().unmasked());
exti.rtsr.modify(|_, w| w.[<tr $num>]().bit($trigger));
exti.ftsr.modify(|_, w| w.[<tr $num>]().bit(!$trigger));
syscfg
.[<exticr $crnum>]
.modify(|_, w| unsafe { w.[<exti $num>]().bits($val) });
}
)+
_ => panic!("GPIO pins must be 0 - 15."),
}
}
}
}
#[cfg(feature = "l5")]
macro_rules! set_exti_l5 {
($pin:expr, $trigger:expr, $val:expr, [$(($num:expr, $crnum:expr, $num2:expr)),+]) => {
let exti = unsafe { &(*pac::EXTI::ptr()) };
paste! {
match $pin {
$(
$num => {
exti.imr1.modify(|_, w| w.[<im $num>]().set_bit()); exti.rtsr1.modify(|_, w| w.[<rt $num>]().bit($trigger)); exti.ftsr1.modify(|_, w| w.[<ft $num>]().bit(!$trigger)); exti
.[<exticr $crnum>]
.modify(|_, w| unsafe { w.[<exti $num2>]().bits($val) });
}
)+
_ => panic!("GPIO pins must be 0 - 15."),
}
}
}
}
#[cfg(feature = "g0")]
macro_rules! set_exti_g0 {
($pin:expr, $trigger:expr, $val:expr, [$(($num:expr, $crnum:expr, $num2:expr)),+]) => {
let exti = unsafe { &(*pac::EXTI::ptr()) };
paste! {
match $pin {
$(
$num => {
exti.imr1.modify(|_, w| w.[<im $num>]().set_bit()); exti.rtsr1.modify(|_, w| w.[<tr $num>]().bit($trigger)); exti.ftsr1.modify(|_, w| w.[<tr $num>]().bit(!$trigger)); exti
.[<exticr $crnum>]
.modify(|_, w| unsafe { w.[<exti $num2>]().bits($val) });
}
)+
_ => panic!("GPIO pins must be 0 - 15."),
}
}
}
}
pub struct Pin {
pub port: Port,
pub pin: u8,
}
impl Pin {
pub fn new(port: Port, pin: u8, mode: PinMode) -> Self {
assert!(pin <= 15, "Pin must be 0 - 15.");
free(|_| {
let rcc = unsafe { &(*RCC::ptr()) };
match port {
Port::A => {
cfg_if! {
if #[cfg(feature = "f3")] {
if rcc.ahbenr.read().iopaen().bit_is_clear() {
rcc_en_reset!(ahb1, iopa, rcc);
}
} else if #[cfg(feature = "h7")] {
if rcc.ahb4enr.read().gpioaen().bit_is_clear() {
rcc.ahb4enr.modify(|_, w| w.gpioaen().set_bit());
rcc.ahb4rstr.modify(|_, w| w.gpioarst().set_bit());
rcc.ahb4rstr.modify(|_, w| w.gpioarst().clear_bit());
}
} else if #[cfg(feature = "f4")] {
if rcc.ahb1enr.read().gpioaen().bit_is_clear() {
rcc_en_reset!(ahb1, gpioa, rcc);
}
} else if #[cfg(feature = "g0")] {
if rcc.iopenr.read().iopaen().bit_is_clear() {
rcc.iopenr.modify(|_, w| w.iopaen().set_bit());
rcc.ioprstr.modify(|_, w| w.ioparst().set_bit());
rcc.ioprstr.modify(|_, w| w.ioparst().clear_bit());
}
} else { if rcc.ahb2enr.read().gpioaen().bit_is_clear() {
rcc_en_reset!(ahb2, gpioa, rcc);
}
}
}
}
Port::B => {
cfg_if! {
if #[cfg(feature = "f3")] {
if rcc.ahbenr.read().iopben().bit_is_clear() {
rcc_en_reset!(ahb1, iopa, rcc);
}
} else if #[cfg(feature = "h7")] {
if rcc.ahb4enr.read().gpioben().bit_is_clear() {
rcc.ahb4enr.modify(|_, w| w.gpioben().set_bit());
rcc.ahb4rstr.modify(|_, w| w.gpiobrst().set_bit());
rcc.ahb4rstr.modify(|_, w| w.gpiobrst().clear_bit());
}
} else if #[cfg(feature = "f4")] {
if rcc.ahb1enr.read().gpioben().bit_is_clear() {
rcc_en_reset!(ahb1, gpiob, rcc);
}
} else if #[cfg(feature = "g0")] {
if rcc.iopenr.read().iopben().bit_is_clear() {
rcc.iopenr.modify(|_, w| w.iopben().set_bit());
rcc.ioprstr.modify(|_, w| w.iopbrst().set_bit());
rcc.ioprstr.modify(|_, w| w.iopbrst().clear_bit());
}
} else { if rcc.ahb2enr.read().gpioben().bit_is_clear() {
rcc_en_reset!(ahb2, gpiob, rcc);
}
}
}
}
Port::C => {
cfg_if! {
if #[cfg(feature = "f3")] {
if rcc.ahbenr.read().iopcen().bit_is_clear() {
rcc_en_reset!(ahb1, iopa, rcc);
}
} else if #[cfg(feature = "h7")] {
if rcc.ahb4enr.read().gpiocen().bit_is_clear() {
rcc.ahb4enr.modify(|_, w| w.gpiocen().set_bit());
rcc.ahb4rstr.modify(|_, w| w.gpiocrst().set_bit());
rcc.ahb4rstr.modify(|_, w| w.gpiocrst().clear_bit());
}
} else if #[cfg(feature = "f4")] {
if rcc.ahb1enr.read().gpiocen().bit_is_clear() {
rcc_en_reset!(ahb1, gpioc, rcc);
}
} else if #[cfg(feature = "g0")] {
if rcc.iopenr.read().iopcen().bit_is_clear() {
rcc.iopenr.modify(|_, w| w.iopcen().set_bit());
rcc.ioprstr.modify(|_, w| w.iopcrst().set_bit());
rcc.ioprstr.modify(|_, w| w.iopcrst().clear_bit());
}
} else { if rcc.ahb2enr.read().gpiocen().bit_is_clear() {
rcc_en_reset!(ahb2, gpioc, rcc);
}
}
}
}
#[cfg(not(any(feature = "f410")))]
Port::D => {
cfg_if! {
if #[cfg(feature = "f3")] {
if rcc.ahbenr.read().iopden().bit_is_clear() {
rcc_en_reset!(ahb1, iopa, rcc);
}
} else if #[cfg(feature = "h7")] {
if rcc.ahb4enr.read().gpioden().bit_is_clear() {
rcc.ahb4enr.modify(|_, w| w.gpioden().set_bit());
rcc.ahb4rstr.modify(|_, w| w.gpiodrst().set_bit());
rcc.ahb4rstr.modify(|_, w| w.gpiodrst().clear_bit());
}
} else if #[cfg(feature = "f4")] {
if rcc.ahb1enr.read().gpioden().bit_is_clear() {
rcc_en_reset!(ahb1, gpiod, rcc);
}
} else if #[cfg(feature = "g0")] {
if rcc.iopenr.read().iopden().bit_is_clear() {
rcc.iopenr.modify(|_, w| w.iopden().set_bit());
rcc.ioprstr.modify(|_, w| w.iopdrst().set_bit());
rcc.ioprstr.modify(|_, w| w.iopdrst().clear_bit());
}
} else { if rcc.ahb2enr.read().gpioden().bit_is_clear() {
rcc_en_reset!(ahb2, gpiod, rcc);
}
}
}
}
#[cfg(not(any(
feature = "f301",
feature = "f3x4",
feature = "f410",
feature = "g0",
feature = "wb",
feature = "wl"
)))]
Port::E => {
cfg_if! {
if #[cfg(feature = "f3")] {
if rcc.ahbenr.read().iopeen().bit_is_clear() {
rcc_en_reset!(ahb1, iopa, rcc);
}
} else if #[cfg(feature = "h7")] {
if rcc.ahb4enr.read().gpioeen().bit_is_clear() {
rcc.ahb4enr.modify(|_, w| w.gpioeen().set_bit());
rcc.ahb4rstr.modify(|_, w| w.gpioerst().set_bit());
rcc.ahb4rstr.modify(|_, w| w.gpioerst().clear_bit());
}
} else if #[cfg(feature = "f4")] {
if rcc.ahb1enr.read().gpioeen().bit_is_clear() {
rcc_en_reset!(ahb1, gpioe, rcc);
}
} else if #[cfg(feature = "g0")] {
if rcc.iopenr.read().iopeen().bit_is_clear() {
rcc.iopenr.modify(|_, w| w.iopeen().set_bit());
rcc.ioprstr.modify(|_, w| w.ioperst().set_bit());
rcc.ioprstr.modify(|_, w| w.ioperst().clear_bit());
}
} else { if rcc.ahb2enr.read().gpioeen().bit_is_clear() {
rcc_en_reset!(ahb2, gpioe, rcc);
}
}
}
}
#[cfg(not(any(
feature = "f401",
feature = "f410",
feature = "f411",
feature = "l4x1",
feature = "l4x2",
feature = "l412",
feature = "l4x3",
feature = "wb",
feature = "wl"
)))]
Port::F => {
cfg_if! {
if #[cfg(feature = "f3")] {
if rcc.ahbenr.read().iopfen().bit_is_clear() {
rcc_en_reset!(ahb1, iopa, rcc);
}
} else if #[cfg(feature = "h7")] {
if rcc.ahb4enr.read().gpiofen().bit_is_clear() {
rcc.ahb4enr.modify(|_, w| w.gpiofen().set_bit());
rcc.ahb4rstr.modify(|_, w| w.gpiofrst().set_bit());
rcc.ahb4rstr.modify(|_, w| w.gpiofrst().clear_bit());
}
} else if #[cfg(feature = "f4")] {
if rcc.ahb1enr.read().gpiofen().bit_is_clear() {
rcc_en_reset!(ahb1, gpiof, rcc);
}
} else if #[cfg(feature = "g0")] {
if rcc.iopenr.read().iopfen().bit_is_clear() {
rcc.iopenr.modify(|_, w| w.iopfen().set_bit());
rcc.ioprstr.modify(|_, w| w.iopfrst().set_bit());
rcc.ioprstr.modify(|_, w| w.iopfrst().clear_bit());
}
} else { if rcc.ahb2enr.read().gpiofen().bit_is_clear() {
rcc_en_reset!(ahb2, gpiof, rcc);
}
}
}
}
#[cfg(not(any(
feature = "f373",
feature = "f301",
feature = "f3x4",
feature = "f410",
feature = "l4",
feature = "g0",
feature = "g4",
feature = "wb",
feature = "wl"
)))]
Port::H => {
cfg_if! {
if #[cfg(feature = "f3")] {
if rcc.ahbenr.read().iophen().bit_is_clear() {
rcc_en_reset!(ahb1, iopa, rcc);
}
} else if #[cfg(feature = "h7")] {
if rcc.ahb4enr.read().gpiohen().bit_is_clear() {
rcc.ahb4enr.modify(|_, w| w.gpiohen().set_bit());
rcc.ahb4rstr.modify(|_, w| w.gpiohrst().set_bit());
rcc.ahb4rstr.modify(|_, w| w.gpiohrst().clear_bit());
}
} else if #[cfg(feature = "f4")] {
if rcc.ahb1enr.read().gpiohen().bit_is_clear() {
rcc_en_reset!(ahb1, gpioh, rcc);
}
} else if #[cfg(feature = "g0")] {
if rcc.iopenr.read().iophen().bit_is_clear() {
rcc.iopenr.modify(|_, w| w.iophen().set_bit());
rcc.ioprstr.modify(|_, w| w.iophrst().set_bit());
rcc.ioprstr.modify(|_, w| w.iophrst().clear_bit());
}
} else { if rcc.ahb2enr.read().gpiohen().bit_is_clear() {
rcc_en_reset!(ahb2, gpioa, rcc);
}
}
}
}
}
});
let mut result = Self { port, pin };
result.mode(mode);
result
}
pub fn mode(&mut self, value: PinMode) {
set_field2!(
self.pin,
self.port,
moder,
moder,
bits,
value.val(),
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
);
if let PinMode::Alt(alt) = value {
self.alt_fn(alt);
}
}
pub fn output_type(&mut self, value: OutputType) {
set_field2!(
self.pin,
self.port,
otyper,
ot,
bit,
value as u8 != 0,
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
);
}
pub fn output_speed(&mut self, value: OutputSpeed) {
set_field2!(
self.pin,
self.port,
ospeedr,
ospeedr,
bits,
value as u8,
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
);
}
pub fn pull(&mut self, value: Pull) {
set_field2!(
self.pin,
self.port,
pupdr,
pupdr,
bits,
value as u8,
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
);
}
pub fn output_data(&mut self, value: PinState) {
set_field2!(
self.pin,
self.port,
odr,
odr,
bit,
value as u8 != 0,
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
);
}
#[cfg(not(feature = "f373"))]
pub fn cfg_lock(&mut self, value: CfgLock) {
set_field2!(
self.pin,
self.port,
lckr,
lck,
bit,
value as u8 != 0,
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
);
}
pub fn input_data(&mut self) -> PinState {
let val = get_input_data!(
self.pin,
self.port,
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
);
if val {
PinState::High
} else {
PinState::Low
}
}
pub fn set_state(&mut self, value: PinState) {
let offset = match value {
PinState::Low => 16,
PinState::High => 0,
};
set_state!(
self.pin,
self.port,
offset,
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
);
}
fn alt_fn(&mut self, value: u8) {
assert!(value <= 15, "Alt function must be 0 to 15.");
cfg_if! {
if #[cfg(any(feature = "l5", feature = "g0", feature = "wb", feature = "wl"))] {
set_alt2!(self.pin, self.port, afsel, value, [(0, l), (1, l), (2, l),
(3, l), (4, l), (5, l), (6, l), (7, l), (8, h), (9, h), (10, h), (11, h), (12, h),
(13, h), (14, h), (15, h)])
} else if #[cfg(feature = "h7")] {
set_alt2!(self.pin, self.port, afr, value, [(0, l), (1, l), (2, l),
(3, l), (4, l), (5, l), (6, l), (7, l), (8, h), (9, h), (10, h), (11, h), (12, h),
(13, h), (14, h), (15, h)])
} else { set_alt2!(self.pin, self.port, afr, value, [(0, l), (1, l), (2, l),
(3, l), (4, l), (5, l), (6, l), (7, l), (8, h), (9, h), (10, h), (11, h), (12, h),
(13, h), (14, h), (15, h)])
}
}
}
#[cfg(not(feature = "f373"))]
pub fn enable_interrupt(&mut self, edge: Edge) {
let rise_trigger = match edge {
Edge::Rising => {
true
}
Edge::Falling => {
false
}
};
cfg_if! {
if #[cfg(feature = "g0")] {
set_exti_g0!(self.pin, rise_trigger, self.port.cr_val(), [(0, 1, 0_7), (1, 1, 0_7), (2, 1, 0_7),
(3, 1, 0_7), (4, 2, 0_7), (5, 2, 0_7), (6, 2, 0_7), (7, 2, 0_7), (8, 3, 8_15),
(9, 3, 8_15), (10, 3, 8_15), (11, 3, 8_15), (12, 4, 8_15),
(13, 4, 8_15), (14, 4, 8_15), (15, 4, 8_15)]
);
} else if #[cfg(feature = "l5")] {
set_exti_l5!(self.pin, rise_trigger, self.port.cr_val(), [(0, 1, 0_7), (1, 1, 0_7), (2, 1, 0_7),
(3, 1, 0_7), (4, 2, 0_7), (5, 2, 0_7), (6, 2, 0_7), (7, 2, 0_7), (8, 3, 8_15),
(9, 3, 8_15), (10, 3, 8_15), (11, 3, 8_15), (12, 4, 8_15),
(13, 4, 8_15), (14, 4, 8_15), (15, 4, 8_15)]
);
} else if #[cfg(feature = "f4")] {
set_exti_f4!(self.pin, rise_trigger, self.port.cr_val(), [(0, 1), (1, 1), (2, 1),
(3, 1), (4, 2), (5, 2), (6, 2), (7, 2), (8, 3), (9, 3), (10, 3), (11, 3), (12, 4),
(13, 4), (14, 4), (15, 4)]
);
} else {
set_exti!(self.pin, rise_trigger, self.port.cr_val(), [(0, 1), (1, 1), (2, 1),
(3, 1), (4, 2), (5, 2), (6, 2), (7, 2), (8, 3), (9, 3), (10, 3), (11, 3), (12, 4),
(13, 4), (14, 4), (15, 4)]
);
}
}
}
pub fn is_high(&self) -> bool {
get_input_data!(
self.pin,
self.port,
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
)
}
pub fn is_low(&self) -> bool {
!self.is_high()
}
pub fn set_high(&mut self) {
set_state!(
self.pin,
self.port,
0,
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
);
}
pub fn set_low(&mut self) {
set_state!(
self.pin,
self.port,
16,
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
);
}
}
#[cfg(feature = "embedded-hal")]
#[cfg_attr(docsrs, doc(cfg(feature = "embedded-hal")))]
impl InputPin for Pin {
type Error = Infallible;
fn is_high(&self) -> Result<bool, Self::Error> {
Ok(Pin::is_high(self))
}
fn is_low(&self) -> Result<bool, Self::Error> {
Ok(Pin::is_low(self))
}
}
#[cfg(feature = "embedded-hal")]
#[cfg_attr(docsrs, doc(cfg(feature = "embedded-hal")))]
impl OutputPin for Pin {
type Error = Infallible;
fn set_low(&mut self) -> Result<(), Self::Error> {
Pin::set_low(self);
Ok(())
}
fn set_high(&mut self) -> Result<(), Self::Error> {
Pin::set_high(self);
Ok(())
}
}
#[cfg(feature = "embedded-hal")]
#[cfg_attr(docsrs, doc(cfg(feature = "embedded-hal")))]
impl ToggleableOutputPin for Pin {
type Error = Infallible;
fn toggle(&mut self) -> Result<(), Self::Error> {
if self.is_high() {
Pin::set_low(self);
} else {
Pin::set_high(self);
}
Ok(())
}
}