#![macro_use]
use crate::pac::gpio;
use core::convert::Infallible;
use embassy_hal_internal::{Peri, PeripheralType};
pub mod pin_ctrl;
mod flash_pin;
pub use flash_pin::*;
pub struct Flex<'d> {
pub(crate) pin: Peri<'d, AnyPin>,
}
impl<'d> Flex<'d> {
#[inline]
pub fn new(pin: Peri<'d, impl Pin>) -> Self {
Self { pin: pin.into() }
}
#[inline(never)]
pub fn set_as_input(&mut self, pull: Pull) {
let r = self.pin.block();
let n = 2 * self.pin.pin() as usize;
r.pupdr().modify(|w| w.0 = (w.0 & !(0x03 << n)) | (pull.to_pupdr() << n));
r.moder().modify(|w| w.0 = w.0 & !(0x03 << n));
}
#[inline(never)]
pub fn set_as_output(&mut self) {
let r = self.pin.block();
let n = 2 * self.pin.pin() as usize;
r.ospeedr().modify(|w| w.0 |= 0x03 << n); r.pupdr().modify(|w| w.0 = w.0 & !(0x03 << n)); r.otyper().modify(|w| w.0 = w.0 & !(0x01 << (n >> 1))); r.moder().modify(|w| w.0 = (w.0 & !(0x03 << n)) | (0x01 << n));
}
#[inline(never)]
pub fn set_as_input_output_pull(&mut self, pull: Pull) {
let r = self.pin.block();
let n = 2 * self.pin.pin() as usize;
r.pupdr().modify(|w| w.0 = (w.0 & !(0x03 << n)) | (pull.to_pupdr() << n));
r.otyper().modify(|w| w.0 = w.0 | (0x01 << (n >> 1))); r.moder().modify(|w| w.0 = (w.0 & !(0x03 << n)) | (0x01 << n));
}
#[inline]
pub fn is_high(&self) -> bool {
pin_ctrl::pin_is_high(self.pin.block(), 1 << self.pin.pin())
}
#[inline]
pub fn is_low(&self) -> bool {
pin_ctrl::pin_is_low(self.pin.block(), 1 << self.pin.pin())
}
#[inline]
pub fn get_level(&self) -> Level {
self.is_high().into()
}
#[inline]
pub fn is_set_high(&self) -> bool {
!self.is_set_low()
}
#[inline]
pub fn is_set_low(&self) -> bool {
pin_ctrl::pin_is_set_low(self.pin.block(), 1 << self.pin.pin())
}
#[inline]
pub fn get_output_level(&self) -> Level {
self.is_set_high().into()
}
#[inline]
pub fn set_high(&mut self) {
self.pin.set_high();
}
#[inline]
pub fn set_low(&mut self) {
self.pin.set_low();
}
#[inline]
pub fn set_level(&mut self, level: Level) {
match level {
Level::Low => self.pin.set_low(),
Level::High => self.pin.set_high(),
}
}
#[inline]
pub fn toggle(&mut self) {
if self.is_set_low() {
self.set_high()
} else {
self.set_low()
}
}
}
impl<'d> Drop for Flex<'d> {
#[inline]
fn drop(&mut self) {
}
}
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Pull {
None,
Up,
Down,
}
impl Pull {
const fn to_pupdr(self) -> u32 {
match self {
Pull::None => 0,
Pull::Up => 1,
Pull::Down => 2,
}
}
}
pub struct Input<'d> {
pub(crate) pin: Flex<'d>,
}
impl<'d> Input<'d> {
#[inline]
pub fn new(pin: Peri<'d, impl Pin>, pull: Pull) -> Self {
let mut pin = Flex::new(pin);
pin.set_as_input(pull);
Self { pin }
}
#[inline]
pub fn is_high(&self) -> bool {
self.pin.is_high()
}
#[inline]
pub fn is_low(&self) -> bool {
self.pin.is_low()
}
#[inline]
pub fn get_level(&self) -> Level {
self.pin.get_level()
}
}
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Level {
Low,
High,
}
impl From<bool> for Level {
fn from(val: bool) -> Self {
match val {
true => Self::High,
false => Self::Low,
}
}
}
impl From<Level> for bool {
fn from(level: Level) -> bool {
match level {
Level::Low => false,
Level::High => true,
}
}
}
pub struct Output<'d> {
pub(crate) pin: Flex<'d>,
}
impl<'d> Output<'d> {
#[inline]
pub fn new(pin: Peri<'d, impl Pin>, initial_output: Level) -> Self {
let mut pin = Flex::new(pin);
match initial_output {
Level::High => pin.set_high(),
Level::Low => pin.set_low(),
}
pin.set_as_output();
Self { pin }
}
#[inline]
pub fn set_high(&mut self) {
self.pin.set_high();
}
#[inline]
pub fn set_low(&mut self) {
self.pin.set_low();
}
#[inline]
pub fn set_level(&mut self, level: Level) {
self.pin.set_level(level)
}
#[inline]
pub fn is_set_high(&self) -> bool {
self.pin.is_set_high()
}
#[inline]
pub fn is_set_low(&self) -> bool {
self.pin.is_set_low()
}
#[inline]
pub fn get_output_level(&self) -> Level {
self.pin.get_output_level()
}
#[inline]
pub fn toggle(&mut self) {
self.pin.toggle();
}
}
pub struct OutputOpenDrain<'d> {
pub(crate) pin: Flex<'d>,
}
impl<'d> OutputOpenDrain<'d> {
#[inline]
pub fn new(pin: Peri<'d, impl Pin>, initial_output: Level) -> Self {
let mut pin = Flex::new(pin);
match initial_output {
Level::High => pin.set_high(),
Level::Low => pin.set_low(),
}
pin.set_as_input_output_pull(Pull::None);
Self { pin }
}
#[inline]
pub fn new_pull(pin: Peri<'d, impl Pin>, initial_output: Level, pull: Pull) -> Self {
let mut pin = Flex::new(pin);
match initial_output {
Level::High => pin.set_high(),
Level::Low => pin.set_low(),
}
pin.set_as_input_output_pull(pull);
Self { pin }
}
#[inline]
pub fn is_high(&self) -> bool {
!self.pin.is_low()
}
#[inline]
pub fn is_low(&self) -> bool {
self.pin.is_low()
}
#[inline]
pub fn get_level(&self) -> Level {
self.pin.get_level()
}
#[inline]
pub fn set_high(&mut self) {
self.pin.set_high();
}
#[inline]
pub fn set_low(&mut self) {
self.pin.set_low();
}
#[inline]
pub fn set_level(&mut self, level: Level) {
self.pin.set_level(level);
}
#[inline]
pub fn is_set_high(&self) -> bool {
self.pin.is_set_high()
}
#[inline]
pub fn is_set_low(&self) -> bool {
self.pin.is_set_low()
}
#[inline]
pub fn get_output_level(&self) -> Level {
self.pin.get_output_level()
}
#[inline]
pub fn toggle(&mut self) {
self.pin.toggle()
}
}
pub(crate) trait SealedPin {
fn pin_port(&self) -> u8;
#[inline]
fn _pin(&self) -> u8 {
self.pin_port() % 16
}
#[inline]
fn _port(&self) -> u8 {
self.pin_port() / 16
}
#[inline]
fn block(&self) -> gpio::Gpio {
crate::chip::gpio_block(self._port() as _)
}
#[inline]
fn set_high(&self) {
pin_ctrl::pin_set_high(self.block(), 1 << self._pin())
}
#[inline]
fn set_low(&self) {
pin_ctrl::pin_set_low(self.block(), 1 << self._pin())
}
}
#[allow(private_bounds)]
pub trait Pin: PeripheralType + Into<AnyPin> + SealedPin + Sized + 'static {
#[cfg(feature = "exti")]
type ExtiChannel: crate::exti::Channel;
#[inline]
fn pin(&self) -> u8 {
self._pin()
}
#[inline]
fn port(&self) -> u8 {
self._port()
}
}
pub struct AnyPin {
pin_port: u8,
}
impl AnyPin {
#[inline]
pub unsafe fn steal(pin_port: u8) -> Peri<'static, Self> {
Peri::new_unchecked(Self { pin_port })
}
#[inline]
fn _port(&self) -> u8 {
self.pin_port / 16
}
pub fn block(&self) -> gpio::Gpio {
crate::chip::gpio_block(self._port() as _)
}
}
impl Copy for AnyPin {}
impl Clone for AnyPin {
fn clone(&self) -> Self {
*self
}
}
impl PeripheralType for AnyPin {}
impl Pin for AnyPin {
#[cfg(feature = "exti")]
type ExtiChannel = crate::exti::AnyChannel;
}
impl SealedPin for AnyPin {
#[inline]
fn pin_port(&self) -> u8 {
self.pin_port
}
}
crate::foreach_pin!(
($pin_name:ident, $port_name:ident, $port_num:expr, $pin_num:expr, $exti_ch:ident) => {
impl Pin for $crate::peripherals::$pin_name {
#[cfg(feature = "exti")]
type ExtiChannel = peripherals::$exti_ch;
}
impl SealedPin for $crate::peripherals::$pin_name {
#[inline]
fn pin_port(&self) -> u8 {
$port_num * 16 + $pin_num
}
}
impl From<$crate::chip::peripherals::$pin_name> for AnyPin {
fn from(val: $crate::peripherals::$pin_name) -> Self {
Self {
pin_port: val.pin_port(),
}
}
}
impl flash_pin::PinGpio for $crate::peripherals::$pin_name {
const GPIO: $crate::pac::gpio::Gpio = $crate::pac::$port_name;
const MASK: u32 = 1 << $pin_num;
}
};
);
impl<'d> embedded_hal::digital::ErrorType for Input<'d> {
type Error = Infallible;
}
impl<'d> embedded_hal::digital::InputPin for Input<'d> {
#[inline]
fn is_high(&mut self) -> Result<bool, Self::Error> {
Ok(Input::is_high(self))
}
#[inline]
fn is_low(&mut self) -> Result<bool, Self::Error> {
Ok(Input::is_low(self))
}
}
impl<'d> embedded_hal::digital::ErrorType for Output<'d> {
type Error = Infallible;
}
impl<'d> embedded_hal::digital::OutputPin for Output<'d> {
#[inline]
fn set_high(&mut self) -> Result<(), Self::Error> {
Output::set_high(self);
Ok(())
}
#[inline]
fn set_low(&mut self) -> Result<(), Self::Error> {
Output::set_low(self);
Ok(())
}
}
impl<'d> embedded_hal::digital::StatefulOutputPin for Output<'d> {
#[inline]
fn is_set_high(&mut self) -> Result<bool, Self::Error> {
Ok(Output::is_set_high(self))
}
#[inline]
fn is_set_low(&mut self) -> Result<bool, Self::Error> {
Ok(Output::is_set_low(self))
}
}
impl<'d> embedded_hal::digital::ErrorType for OutputOpenDrain<'d> {
type Error = Infallible;
}
impl<'d> embedded_hal::digital::InputPin for OutputOpenDrain<'d> {
#[inline]
fn is_high(&mut self) -> Result<bool, Self::Error> {
Ok(OutputOpenDrain::is_high(self))
}
#[inline]
fn is_low(&mut self) -> Result<bool, Self::Error> {
Ok(OutputOpenDrain::is_low(self))
}
}
impl<'d> embedded_hal::digital::OutputPin for OutputOpenDrain<'d> {
#[inline]
fn set_high(&mut self) -> Result<(), Self::Error> {
OutputOpenDrain::set_high(self);
Ok(())
}
#[inline]
fn set_low(&mut self) -> Result<(), Self::Error> {
OutputOpenDrain::set_low(self);
Ok(())
}
}
impl<'d> embedded_hal::digital::StatefulOutputPin for OutputOpenDrain<'d> {
#[inline]
fn is_set_high(&mut self) -> Result<bool, Self::Error> {
Ok(OutputOpenDrain::is_set_high(self))
}
#[inline]
fn is_set_low(&mut self) -> Result<bool, Self::Error> {
Ok(OutputOpenDrain::is_set_low(self))
}
}
impl<'d> embedded_hal::digital::InputPin for Flex<'d> {
#[inline]
fn is_high(&mut self) -> Result<bool, Self::Error> {
Ok(Flex::is_high(self))
}
#[inline]
fn is_low(&mut self) -> Result<bool, Self::Error> {
Ok(Flex::is_low(self))
}
}
impl<'d> embedded_hal::digital::OutputPin for Flex<'d> {
#[inline]
fn set_high(&mut self) -> Result<(), Self::Error> {
Flex::set_high(self);
Ok(())
}
#[inline]
fn set_low(&mut self) -> Result<(), Self::Error> {
Flex::set_low(self);
Ok(())
}
}
impl<'d> embedded_hal::digital::ErrorType for Flex<'d> {
type Error = Infallible;
}
impl<'d> embedded_hal::digital::StatefulOutputPin for Flex<'d> {
#[inline]
fn is_set_high(&mut self) -> Result<bool, Self::Error> {
Ok(Flex::is_set_high(self))
}
#[inline]
fn is_set_low(&mut self) -> Result<bool, Self::Error> {
Ok(Flex::is_set_low(self))
}
}