#![allow(unknown_lints)]
#![allow(clippy::all)]
use core::convert::Infallible;
use core::marker::PhantomData;
use crate::rcc;
use crate::stm32l0x1;
use hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin};
#[doc(hidden)]
mod private {
pub trait Sealed {}
impl Sealed for super::Analog {}
impl Sealed for super::Floating {}
impl Sealed for super::PullDown {}
impl Sealed for super::PullUp {}
impl<MODE> Sealed for super::Input<MODE> {}
impl Sealed for super::PushPull {}
impl Sealed for super::OpenDrain {}
impl<MODE, PUMODE> Sealed for super::Output<MODE, PUMODE> {}
}
#[doc(hidden)]
pub trait AnalogMode: private::Sealed {
fn modify_pupdr_bits(original: u32, offset: u32) -> u32;
}
pub struct Analog(());
impl AnalogMode for Analog {
#[inline]
fn modify_pupdr_bits(original: u32, offset: u32) -> u32 {
original & !(0b11 << offset)
}
}
#[doc(hidden)]
pub trait PullMode: private::Sealed {
fn modify_pupdr_bits(original: u32, offset: u32) -> u32;
}
pub struct Floating;
impl PullMode for Floating {
#[inline]
fn modify_pupdr_bits(original: u32, offset: u32) -> u32 {
original & !(0b11 << offset)
}
}
pub struct PullDown;
impl PullMode for PullDown {
#[inline]
fn modify_pupdr_bits(original: u32, offset: u32) -> u32 {
(original & !(0b11 << offset)) | (0b10 << offset)
}
}
pub struct PullUp;
impl PullMode for PullUp {
#[inline]
fn modify_pupdr_bits(original: u32, offset: u32) -> u32 {
(original & !(0b11 << offset)) | (0b01 << offset)
}
}
#[doc(hidden)]
pub struct Input<MODE> {
#[doc(hidden)]
_mode: PhantomData<MODE>,
}
#[doc(hidden)]
pub trait OutputMode: private::Sealed {
fn modify_otyper_bits(original: u32, idx: u8) -> u32;
}
pub struct PushPull;
impl OutputMode for PushPull {
#[inline]
fn modify_otyper_bits(original: u32, idx: u8) -> u32 {
original & !(0b1 << idx)
}
}
pub struct OpenDrain;
impl OutputMode for OpenDrain {
#[inline]
fn modify_otyper_bits(original: u32, idx: u8) -> u32 {
original | (0b1 << idx)
}
}
pub struct Output<MODE, PUMODE> {
#[doc(hidden)]
_mode: PhantomData<MODE>,
#[doc(hidden)]
_pu: PhantomData<PUMODE>,
}
#[allow(missing_docs)]
#[repr(C)]
pub enum PinSpeed {
Low = 0,
Medium,
High,
VeryHigh,
}
macro_rules! impl_parts {
($($GPIOX:ident, $gpiox:ident;)+) => {
$(
use stm32l0x1::$GPIOX;
impl AFRL<$GPIOX> {
pub(crate) fn afr(&mut self) -> &stm32l0x1::$gpiox::AFRL {
unsafe { &(*$GPIOX::ptr()).afrl }
}
}
impl AFRH<$GPIOX> {
pub(crate) fn afr(&mut self) -> &stm32l0x1::$gpiox::AFRH {
unsafe { &(*$GPIOX::ptr()).afrh }
}
}
impl MODER<$GPIOX> {
pub(crate) fn moder(&mut self) -> &stm32l0x1::$gpiox::MODER {
unsafe { &(*$GPIOX::ptr()).moder }
}
}
impl OTYPER<$GPIOX> {
pub(crate) fn otyper(&mut self) -> &stm32l0x1::$gpiox::OTYPER {
unsafe { &(*$GPIOX::ptr()).otyper }
}
}
impl PUPDR<$GPIOX> {
pub(crate) fn pupdr(&mut self) -> &stm32l0x1::$gpiox::PUPDR {
unsafe { &(*$GPIOX::ptr()).pupdr }
}
}
impl OSPEEDR<$GPIOX> {
pub(crate) fn ospeedr(&mut self) -> &stm32l0x1::$gpiox::OSPEEDR {
unsafe { &(*$GPIOX::ptr()).ospeedr }
}
}
)+
}
}
macro_rules! impl_gpio {
($name:ident, $GPIOX:ident, $gpioen:ident, $gpiorst:ident) => {
impl_gpio!($name, $GPIOX, $gpioen, $gpiorst, AFRL: [], AFRH: []);
};
($name:ident, $GPIOX:ident, $gpioen:ident, $gpiorst:ident, AFRL: [$($PXiL:ident, $iL:expr;)*]) => {
impl_gpio!($name, $GPIOX, $gpioen, $gpiorst, AFRL: [$($PXiL, $iL;)*], AFRH: []);
};
($name:ident, $GPIOX:ident, $gpioen:ident, $gpiorst:ident, AFRL: [$($PXiL:ident, $iL:expr;)*], AFRH: [$($PXiH:ident, $iH:expr;)*]) => {
impl_pins!($GPIOX, AFRL: [$($PXiL, $iL;)*]);
impl_pins!($GPIOX, AFRH: [$($PXiH, $iH;)*]);
#[allow(non_snake_case)]
pub struct $name {
$(
/// Pin
pub $PXiL: $PXiL<Analog>,
)*
$(
pub $PXiH: $PXiH<Analog>,
)*
}
impl $name {
pub fn new(_gpio: $GPIOX, iop: &mut rcc::IOP) -> Self {
iop.enr().modify(|_,w| w.$gpioen().set_bit());
while iop.enr().read().$gpioen().bit_is_clear() {}
Self {
$(
$PXiL: $PXiL(PhantomData),
)*
$(
$PXiH: $PXiH(PhantomData),
)*
}
}
}
}
}
macro_rules! impl_pin {
($GPIOX:ident, $PXi:ident, $AFR:ident, $i:expr) => {
pub struct $PXi<MODE>(PhantomData<MODE>);
impl<MODE> $PXi<MODE> {
const OFFSET: u32 = 2 * $i;
pub fn into_analog(self) -> $PXi<Analog> {
let mut moder: MODER<$GPIOX> = MODER(PhantomData);
let mut pupdr: PUPDR<$GPIOX> = PUPDR(PhantomData);
pupdr.pupdr().modify(|r, w| unsafe {
w.bits(Analog::modify_pupdr_bits(r.bits(), Self::OFFSET))
});
moder
.moder()
.modify(|r, w| unsafe { w.bits(r.bits() | (0b11 << Self::OFFSET)) });
$PXi(PhantomData)
}
pub fn into_input<Mode: PullMode>(self) -> $PXi<Input<Mode>> {
let mut moder: MODER<$GPIOX> = MODER(PhantomData);
let mut pupdr: PUPDR<$GPIOX> = PUPDR(PhantomData);
moder
.moder()
.modify(|r, w| unsafe { w.bits(r.bits() & !(0b11 << Self::OFFSET)) });
pupdr.pupdr().modify(|r, w| unsafe {
w.bits(Mode::modify_pupdr_bits(r.bits(), Self::OFFSET))
});
$PXi(PhantomData)
}
#[inline]
pub fn set_pin_speed(&self, spd: PinSpeed) {
let mut ospeedr: OSPEEDR<$GPIOX> = OSPEEDR(PhantomData);
ospeedr.ospeedr().modify(|r, w| unsafe {
w.bits((r.bits() & !(0b11 << Self::OFFSET)) | ((spd as u32) << Self::OFFSET))
});
}
pub fn into_output<OMode: OutputMode, PUMode: PullMode>(
self,
) -> $PXi<Output<OMode, PUMode>> {
let mut moder: MODER<$GPIOX> = MODER(PhantomData);
let mut otyper: OTYPER<$GPIOX> = OTYPER(PhantomData);
let mut pupdr: PUPDR<$GPIOX> = PUPDR(PhantomData);
moder.moder().modify(|r, w| unsafe {
w.bits((r.bits() & !(0b11 << Self::OFFSET)) | (0b01 << Self::OFFSET))
});
pupdr.pupdr().modify(|r, w| unsafe {
w.bits(PUMode::modify_pupdr_bits(r.bits(), Self::OFFSET))
});
otyper
.otyper()
.modify(|r, w| unsafe { w.bits(OMode::modify_otyper_bits(r.bits(), $i)) });
$PXi(PhantomData)
}
pub fn into_alt_fun<AF: AltFun>(self) -> $PXi<AF> {
let mut moder: MODER<$GPIOX> = MODER(PhantomData);
let mut afr: $AFR<$GPIOX> = $AFR(PhantomData);
const AFR_OFFSET: usize = ($i % 8) * 4;
moder.moder().modify(|r, w| unsafe {
w.bits((r.bits() & !(0b11 << Self::OFFSET)) | (0b10 << Self::OFFSET))
});
afr.afr().modify(|r, w| unsafe {
w.bits((r.bits() & !(0b1111 << AFR_OFFSET)) | (AF::NUM << AFR_OFFSET))
});
$PXi(PhantomData)
}
}
impl<OMODE, PUMODE> OutputPin for $PXi<Output<OMODE, PUMODE>> {
type Error = Infallible;
fn set_high(&mut self) -> Result<(), Self::Error> {
Ok(unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << $i)) })
}
fn set_low(&mut self) -> Result<(), Self::Error> {
Ok(unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << (16 + $i))) })
}
}
impl<OMODE, PUMODE> StatefulOutputPin for $PXi<Output<OMODE, PUMODE>> {
fn is_set_high(&self) -> Result<bool, Self::Error> {
self.is_set_low().map(|r| !r)
}
fn is_set_low(&self) -> Result<bool, Self::Error> {
Ok(unsafe { (*$GPIOX::ptr()).odr.read().bits() & (1 << $i) == 0 })
}
}
impl<PUMODE> InputPin for $PXi<Input<PUMODE>> {
type Error = Infallible;
fn is_high(&self) -> Result<bool, Self::Error> {
self.is_low().map(|r| !r)
}
fn is_low(&self) -> Result<bool, Self::Error> {
Ok(unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << $i) == 0 })
}
}
};
}
macro_rules! impl_pins {
($GPIOX:ident, $ARF:ident: [$($PXi:ident, $i:expr;)*]) => {
$(
impl_pin!($GPIOX, $PXi, $ARF, $i);
)*
}
}
pub struct AFRL<GPIO>(PhantomData<GPIO>);
pub struct AFRH<GPIO>(PhantomData<GPIO>);
pub struct MODER<GPIO>(PhantomData<GPIO>);
pub struct OTYPER<GPIO>(PhantomData<GPIO>);
pub struct PUPDR<GPIO>(PhantomData<GPIO>);
pub struct OSPEEDR<GPIO>(PhantomData<GPIO>);
macro_rules! impl_af {
( [$($af:ident, $i:expr;)*] ) => {
$(
pub struct $af;
impl super::AltFun for $af {
const NUM: u32 = $i;
}
)*
}
}
#[doc(hidden)]
pub trait AltFun {
const NUM: u32;
}
#[allow(non_snake_case)]
pub mod AF {
impl_af!([AF0, 0; AF1, 1; AF2, 2; AF3, 3; AF4, 4; AF5, 5; AF6, 6; AF7, 7; AF8, 8; AF9, 9; AF10, 10; AF11, 11; AF12, 12; AF13, 13; AF14, 14; AF15, 15;]);
}
impl_parts!(
GPIOA, gpioa;
GPIOB, gpiob;
GPIOC, gpiob; );
impl_gpio!(A, GPIOA, iopaen, gpioarst,
AFRL: [PA0, 0; PA1, 1; PA2, 2; PA3, 3; PA4, 4; PA5, 5; PA6, 6; PA7, 7;],
AFRH: [PA8, 8; PA9, 9; PA10, 10; PA11, 11; PA12, 12; PA13, 13; PA14, 14; PA15, 15; ]
);
impl_gpio!(B, GPIOB, iopben, gpiobrst,
AFRL: [PB0, 0; PB1, 1; PB2, 2; PB3, 3; PB4, 4; PB5, 5; PB6, 6; PB7, 7;],
AFRH: [PB8, 8; PB9, 9; PB10, 10; PB11, 11; PB12, 12; PB13, 13; PB14, 14; PB15, 15; ]
);
impl_gpio!(C, GPIOC, iopcen, gpiocrst,
AFRL: [PC0, 0; PC1, 1; PC2, 2; PC3, 3; PC4, 4; PC5, 5; PC6, 6; PC7, 7;],
AFRH: [PC8, 8; PC9, 9; PC10, 10; PC11, 11; PC12, 12; PC13, 13; PC14, 14; PC15, 15; ]
);