use crate::ll_api::{GpioInitParam, ll_cmd::*};
use core::convert::Infallible;
use embassy_hal_internal::{Peri, PeripheralType};
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 port = self.pin._port();
let pin = self.pin._pin();
let flag = pull.to_pupdr();
ll_invoke_inner!(INVOKE_ID_GPIO_INIT, port, pin, flag);
}
#[inline(never)]
pub fn set_as_output(&mut self) {
let port = self.pin._port();
let pin = self.pin._pin();
let flag = GpioInitParam::OutPP.param();
ll_invoke_inner!(INVOKE_ID_GPIO_INIT, port, pin, flag);
}
#[inline(never)]
pub fn set_as_open_drain(&mut self) {
let port = self.pin._port();
let pin = self.pin._pin();
let flag = GpioInitParam::OutOD.param();
ll_invoke_inner!(INVOKE_ID_GPIO_INIT, port, pin, flag);
}
pub fn set_as_alternate(&mut self, mode: AltMode) {
let port = self.pin._port();
let pin = self.pin._pin();
let flag = mode.to_flag();
ll_invoke_inner!(INVOKE_ID_GPIO_INIT, port, pin, flag);
}
pub fn set_as_analog(&mut self) {
let port = self.pin._port();
let pin = self.pin._pin();
let flag = GpioInitParam::Analog.param();
ll_invoke_inner!(INVOKE_ID_GPIO_INIT, port, pin, flag);
}
#[inline]
pub fn is_high(&self) -> bool {
let port = self.pin._port();
let pin = self.pin._pin();
ll_invoke_inner!(INVOKE_ID_GPIO_GET_INPUT, port, pin) > 0
}
#[inline]
pub fn is_low(&self) -> bool {
let port = self.pin._port();
let pin = self.pin._pin();
ll_invoke_inner!(INVOKE_ID_GPIO_GET_INPUT, port, pin) == 0
}
#[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 {
let port = self.pin._port();
let pin = self.pin._pin();
ll_invoke_inner!(INVOKE_ID_GPIO_GET_OUTPUT, port, pin) == 0
}
#[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)]
pub enum Pull {
None,
Up,
Down,
}
impl Pull {
const fn to_pupdr(self) -> u32 {
match self {
Pull::None => GpioInitParam::InFloating.param(),
Pull::Up => GpioInitParam::InPU.param(),
Pull::Down => GpioInitParam::InPD.param(),
}
}
}
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)]
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_open_drain();
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 enum AltMode {
AFIN,
AFOD,
AFPP,
AF(u8),
}
impl AltMode {
fn to_flag(&self) -> u32 {
match self {
AltMode::AFIN => GpioInitParam::AFIN.param(),
AltMode::AFOD => GpioInitParam::AFOD.param(),
AltMode::AFPP => GpioInitParam::AFPP.param(),
AltMode::AF(idx) => GpioInitParam::AF(*idx).param(),
}
}
}
pub struct Alternate<'d> {
pub(crate) _pin: Flex<'d>,
}
impl<'d> Alternate<'d> {
#[inline]
pub fn new(pin: Peri<'d, impl Pin>, mode: AltMode) -> Self {
let mut pin = Flex::new(pin);
pin.set_as_alternate(mode);
Self { _pin: pin }
}
}
pub struct Analog<'d> {
pub(crate) _pin: Flex<'d>,
}
impl<'d> Analog<'d> {
#[inline]
pub fn new(pin: Peri<'d, impl Pin>) -> Self {
let mut pin = Flex::new(pin);
pin.set_as_analog();
Self { _pin: pin }
}
}
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 set_high(&self) {
let port = self._port();
let pin = self._pin();
ll_invoke_inner!(INVOKE_ID_GPIO_SET, port, pin, 1);
}
#[inline]
fn set_low(&self) {
let port = self._port();
let pin = self._pin();
ll_invoke_inner!(INVOKE_ID_GPIO_SET, port, pin, 0);
}
}
#[allow(private_bounds)]
pub trait Pin: PeripheralType + Into<AnyPin> + SealedPin + Sized + 'static {
#[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> {
unsafe { Peri::new_unchecked(Self { pin_port }) }
}
#[inline]
fn _port(&self) -> u8 {
self.pin_port / 16
}
}
impl Copy for AnyPin {}
impl Clone for AnyPin {
fn clone(&self) -> Self {
*self
}
}
impl PeripheralType for AnyPin {}
impl Pin for AnyPin {}
impl SealedPin for AnyPin {
#[inline]
fn pin_port(&self) -> u8 {
self.pin_port
}
}
crate::foreach_pin!(
($pin_name:ident, $port_num:expr, $pin_num:expr) => {
impl Pin for $crate::peripherals::$pin_name {
}
impl SealedPin for $crate::peripherals::$pin_name {
#[inline]
fn pin_port(&self) -> u8 {
$port_num * 16 + $pin_num
}
}
impl From<$crate::peripherals::$pin_name> for AnyPin {
fn from(val: $crate::peripherals::$pin_name) -> Self {
Self {
pin_port: val.pin_port(),
}
}
}
};
);
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))
}
}