use core::{convert::Infallible, future::poll_fn, marker::PhantomData, task::Poll};
use embassy_hal_internal::{Peri, PeripheralType, impl_peripheral, interrupt::InterruptExt as _};
use embassy_sync::waitqueue::AtomicWaker;
use crate::{
event_link::{IcuInterrupt as _, InterruptEvent},
interrupt,
interrupt::typelevel::{Handler as InterruptHandler, Interrupt as InterruptType},
pac::{
self,
common::RW,
pfs::Pfs,
pfs::vals::{OutputType, PortDirection, PortMode},
},
write_protect::ProtectedModify as _,
};
#[cfg(not(ra8))]
use crate::pac::icu::vals::{Fclksel, Irqmd};
#[cfg(ra8)]
use crate::pac::icu_common::vals::{Fclksel, Irqmd};
#[cfg(any(pfs_ra8, pfs_port_drive))]
use crate::pac::pfs::vals::PortDrive;
#[derive(Copy, Clone, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct PinId(u8);
impl PinId {
#[inline(always)]
pub const fn from_port_pin(port: u8, pin: u8) -> Self {
assert!(port <= 9);
assert!(pin <= 15);
let pin_number = ((port & 0x0F) << 4) | (pin & 0x0F);
Self(pin_number)
}
#[inline(always)]
pub const fn port(&self) -> u8 {
(self.0 >> 4) & 0x0F
}
#[inline(always)]
pub const fn pin(&self) -> u8 {
self.0 & 0x0F
}
}
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum DriveCapacity {
Low,
Middle,
}
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum OutputMode {
PushPull,
OpenDrain,
}
#[derive(Clone, Copy)]
pub enum GpioTrigger {
#[allow(missing_docs)]
Falling,
#[allow(missing_docs)]
Rising,
#[allow(missing_docs)]
Both,
}
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Debounce {
Off,
Min1,
Min8,
Min32,
Min64,
}
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Level {
#[allow(missing_docs)]
Low,
#[allow(missing_docs)]
High,
}
#[allow(private_bounds)]
pub trait GpioIrq<I: InterruptiblePin>: SealedGpioIrq {}
pub(crate) trait SealedGpioIrq: PeripheralType {}
macro_rules! declare_port_irq {
($num:literal) => {
paste::paste! {
impl crate::gpio::SealedGpioIrq for crate::peripherals::[< GPIO_IRQ $num >] {}
}
};
}
pub(crate) use declare_port_irq;
pub struct AnyPin {
pub(crate) pin_port: PinId,
}
#[allow(private_bounds)]
pub trait ControlKind: SealedControlKind {}
trait SealedControlKind {}
pub enum Basic {}
impl ControlKind for Basic {}
impl SealedControlKind for Basic {}
pub enum WithPullUp {}
impl ControlKind for WithPullUp {}
impl SealedControlKind for WithPullUp {}
pub enum WithOpenDrain {}
impl ControlKind for WithOpenDrain {}
impl SealedControlKind for WithOpenDrain {}
pub struct Flex<'d, C: ControlKind> {
pin: Peri<'d, AnyPin>,
phantom: PhantomData<C>,
}
#[allow(private_bounds)]
pub struct InterruptFlex<'d, I: InterruptiblePin, C: ControlKind> {
pin: Flex<'d, C>,
phantom: PhantomData<&'d I>,
phantom_k: PhantomData<C>,
}
pub struct Input<'d, C: ControlKind> {
pin: Flex<'d, C>,
}
pub struct Output<'d, C: ControlKind> {
pin: Flex<'d, C>,
}
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Copy, Clone)]
#[repr(u8)]
pub enum PortFunction {
#[doc = "Hi-Z / JTAG / SWD"]
HiZ = 0x0,
#[doc = "Low-Power Asynchronous General Purpose Timer"]
Agt = 0x01,
#[doc = "General PWM Timer"]
Gpt0 = 0x02,
#[doc = "General PWM Timer"]
Gpt1 = 0x03,
#[doc = "Serial Communications Interface"]
Sci0 = 0x04,
#[doc = "Serial Communications Interface"]
Sci1 = 0x05,
#[doc = "Serial Peripheral Interface"]
Spi = 0x06,
#[doc = "Inter-Integrated Circuit Bus Interface"]
I2c = 0x07,
#[doc = "Key Interrupt Function"]
Kint = 0x08,
#[doc = "CLKOUT / Analog Comparator / Real-Time Clock"]
ClkCmpRtc = 0x09,
#[doc = "Clock Frequency Accuracy / ADC14"]
CacAdc = 0x0a,
#[doc = "Capacitive Touch"]
Ctsu = 0x0c,
#[doc = "Segment LCD"]
Slcdc = 0x0d,
#[doc = "Controller Area Network Bus"]
Can = 0x10,
#[doc = "Serial Sound Interface Enhanced"]
Ssie = 0x12,
#[doc = "USB Full-Speed"]
UsbFs = 0x13,
}
pub struct InputInterruptHandler<I: Pin> {
_phantom: PhantomData<I>,
}
trait PortPin {
fn port_pin(&self, port: u8, pin: u8) -> pac::common::Reg<pac::pfs::regs::Pin, RW>;
}
impl PortPin for Pfs {
#[inline(always)]
fn port_pin(&self, port_num: u8, pin_num: u8) -> pac::common::Reg<pac::pfs::regs::Pin, RW> {
self.pin((usize::from(port_num) * 16) + usize::from(pin_num))
}
}
pub(crate) trait SealedPin {
fn pin_port(&self) -> PinId;
#[inline(always)]
fn _pin(&self) -> u8 {
self.pin_port().pin()
}
#[inline(always)]
fn _port(&self) -> u8 {
self.pin_port().port()
}
#[inline]
#[cfg(any(pfs_ra8, pfs_port_drive))]
fn set_drive_capacity(&self, drive_capacity: DriveCapacity) {
let pfs = pac::PFS;
let port_num = self._port() as _;
let pin_num = self._pin() as _;
let pfs_reg = pfs.port_pin(port_num, pin_num);
pfs_reg.protected_modify(|r| match drive_capacity {
DriveCapacity::Low => r.set_dscr(PortDrive::Low),
DriveCapacity::Middle => r.set_dscr(PortDrive::Middle),
});
}
fn set_output_mode(&self, output_mode: OutputMode) {
let pfs = pac::PFS;
let port_num = self._port() as _;
let pin_num = self._pin() as _;
let pfs_reg = pfs.port_pin(port_num, pin_num);
match output_mode {
OutputMode::PushPull => pfs_reg.protected_modify(|r| r.set_ncodr(OutputType::Cmos)),
OutputMode::OpenDrain => pfs_reg.protected_modify(|r| r.set_ncodr(OutputType::Nmos)),
}
}
fn set_pull_up(&self, pull_up: bool) {
let pfs = pac::PFS;
let port_num = self._port() as _;
let pin_num = self._pin() as _;
let pfs_reg = pfs.port_pin(port_num, pin_num);
trace!("P{}{:02}: set_pull_up({})", port_num, pin_num, pull_up);
pfs_reg.protected_modify(|r| r.set_pcr(pull_up));
#[cfg(feature = "strict-assert")]
assert_eq!(pfs_reg.read().pcr(), pull_up, "set_pull_up failed");
trace!("P{}{:02}: {}", port_num, pin_num, pfs_reg.read());
}
#[inline(always)]
fn set_high(&self) {
let port = self.regs();
port.pcntr3().write(|r| r.set_posr(self._pin() as _, true));
}
#[inline(always)]
fn set_low(&self) {
let port = self.regs();
port.pcntr3().write(|r| r.set_porr(self._pin() as _, true));
}
#[inline]
fn is_high(&self) -> bool {
let port = self.regs();
port.pcntr2().read().pidr(self._pin() as _)
}
#[inline]
fn is_low(&self) -> bool {
!self.is_high()
}
#[inline]
fn level(&self) -> Level {
let port = self.regs();
match port.pcntr2().read().pidr(self._pin() as _) {
false => Level::Low,
true => Level::High,
}
}
#[inline(always)]
fn set_level(&self, level: Level) {
match level {
Level::Low => self.set_low(),
Level::High => self.set_high(),
}
}
#[inline(always)]
fn is_set_low(&self) -> bool {
!self.is_set_high()
}
#[inline(always)]
fn is_set_high(&self) -> bool {
let port = self.regs();
port.pcntr1().read().podr(self._pin() as _)
}
#[inline]
fn output_level(&self) -> Level {
match self.is_set_high() {
true => Level::High,
false => Level::Low,
}
}
#[inline(always)]
fn toggle(&self) {
match self.is_set_high() {
true => self.set_low(),
false => self.set_high(),
}
}
#[inline]
fn set_as_output(&self) {
let pfs = pac::PFS;
let port_num = self._port() as _;
let pin_num = self._pin() as _;
let pfs_reg = pfs.port_pin(port_num, pin_num);
trace!("P{}{:02}: → Output", port_num, pin_num);
pfs_reg.protected_modify(|r| {
r.set_pmr(PortMode::Gpio);
r.set_pdr(PortDirection::Output);
r.set_pcr(false);
});
#[cfg(feature = "strict-assert")]
{
let status = pfs_reg.read();
assert_eq!(status.pmr(), PortMode::Gpio);
assert_eq!(status.pdr(), PortDirection::Output);
assert_eq!(status.pcr(), false);
}
}
#[inline]
fn set_as_input(&self) {
let pfs = pac::PFS;
let port_num = self._port() as _;
let pin_num = self._pin() as _;
let pfs_reg = pfs.port_pin(port_num, pin_num);
trace!("P{}{:02}: → Input", port_num, pin_num);
pfs_reg.protected_modify(|r| {
r.set_pmr(PortMode::Gpio);
r.set_pdr(PortDirection::Input);
});
#[cfg(feature = "strict-assert")]
{
let status = pfs_reg.read();
assert_eq!(status.pmr(), PortMode::Gpio);
assert_eq!(status.pdr(), PortDirection::Input);
}
}
fn set_as_analog(&self) {
let pfs = pac::PFS;
let port_num = self._port() as _;
let pin_num = self._pin() as _;
let pfs_reg = pfs.port_pin(port_num, pin_num);
pfs_reg.protected_modify(|r| {
r.set_pdr(PortDirection::Input);
r.set_asel(true);
r.set_pcr(false);
});
#[cfg(feature = "strict-assert")]
{
let status = pfs_reg.read();
assert_eq!(status.pdr(), PortDirection::Input);
assert_eq!(status.asel(), true);
assert_eq!(status.pcr(), false);
}
}
fn set_as_pf(&self, port_func: PortFunction) {
let port_num = self._port() as _;
let pin_num = self._pin() as _;
let pfs = crate::pac::PFS;
let pfs_reg = pfs.port_pin(port_num, pin_num);
pfs_reg.protected_modify(|r| r.set_pmr(PortMode::Gpio));
pfs_reg.protected_modify(|r| {
r.set_pmr(PortMode::Peripheral);
r.set_psel(port_func.into());
});
debug!("P{}{:02}: {}", port_num, pin_num, pfs_reg.read());
#[cfg(feature = "strict-assert")]
{
let status = pfs_reg.read();
assert_eq!(status.pmr(), PortMode::Peripheral, "PMR was ignored");
assert_eq!(status.psel(), port_func.into(), "PSEL was ignored");
}
}
fn regs(&self) -> crate::pac::port::Port;
}
#[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()
}
#[inline]
fn pin_port(&self) -> PinId {
SealedPin::pin_port(self)
}
}
#[allow(private_bounds)]
pub trait PullUpPin: SealedPullUpPin {}
pub(crate) trait SealedPullUpPin: Pin {}
#[allow(private_bounds)]
pub trait OpenDrainPin: SealedOpenDrainPin {}
pub(crate) trait SealedOpenDrainPin: Pin {}
#[allow(private_bounds)]
pub trait InterruptiblePin: SealedIntPin + Pin {}
pub(crate) trait SealedIntPin {
const INTERRUPT_EVENT: InterruptEvent;
fn waker() -> &'static AtomicWaker;
}
impl From<PortFunction> for pac::pfs::vals::PortFunction {
fn from(value: PortFunction) -> Self {
Self::from_bits(value as u8)
}
}
impl From<bool> for Level {
fn from(value: bool) -> Self {
match value {
false => Self::Low,
true => Self::High,
}
}
}
impl Pin for AnyPin {}
impl SealedPin for AnyPin {
#[inline(always)]
fn pin_port(&self) -> PinId {
self.pin_port
}
#[inline(always)]
fn regs(&self) -> crate::pac::port::Port {
let port_ptr = crate::pac::PORT0.as_ptr() as usize;
let offset = 0x20 * self._port() as usize;
unsafe { crate::pac::port::Port::from_ptr(port_ptr.wrapping_add(offset) as _) }
}
}
impl AnyPin {
#[inline]
pub unsafe fn steal(pin_port: PinId) -> Peri<'static, Self> {
unsafe { Peri::new_unchecked(Self { pin_port }) }
}
#[cfg(feature = "unstable-pac")]
#[inline]
pub fn block(&self) -> crate::pac::port::Port {
SealedPin::regs(self)
}
}
impl<'d> Input<'d, Basic> {
pub fn new_basic(pin: Peri<'d, impl Pin>) -> Self {
Self::new(pin)
}
}
impl<'d> Input<'d, WithPullUp> {
#[inline]
pub fn new_with_pull_up(pin: Peri<'d, impl Pin>, pull_up: bool) -> Self {
let mut this = Self::new(pin);
this.set_pull_up(pull_up);
this
}
pub fn set_pull_up(&mut self, pull_up: bool) {
self.pin.set_pull_up(pull_up);
}
}
impl<'d, C: ControlKind> Input<'d, C> {
#[inline]
pub fn new(pin: Peri<'d, impl Pin>) -> Self {
let mut pin = Flex::new(pin);
pin.set_as_input();
Self { pin }
}
#[inline]
pub fn is_low(&mut self) -> bool {
self.pin.is_low()
}
#[inline]
pub fn is_high(&mut self) -> bool {
self.pin.is_high()
}
#[inline]
pub fn level(&mut self) -> Level {
self.pin.level()
}
}
impl<'d> Output<'d, Basic> {
pub fn new_basic(
pin: Peri<'d, impl Pin>,
initial: Level,
#[cfg(any(pfs_ra8, pfs_port_drive))] drive_capacity: DriveCapacity,
) -> Self {
Self::new(
pin,
initial,
#[cfg(any(pfs_ra8, pfs_port_drive))]
drive_capacity,
)
}
}
impl<'d> Output<'d, WithOpenDrain> {
#[inline]
pub fn new_with_open_drain(
pin: Peri<'d, impl Pin>,
initial: Level,
#[cfg(any(pfs_ra8, pfs_port_drive))] drive_capacity: DriveCapacity,
output_mode: OutputMode,
) -> Self {
let mut this = Self::new(
pin,
initial,
#[cfg(any(pfs_ra8, pfs_port_drive))]
drive_capacity,
);
this.set_output_mode(output_mode);
this
}
#[inline]
pub fn set_output_mode(&mut self, output_mode: OutputMode) {
self.pin.set_output_mode(output_mode);
}
}
impl<'d, C: ControlKind> Output<'d, C> {
#[inline]
pub(crate) fn new(
pin: Peri<'d, impl Pin>,
initial: Level,
#[cfg(any(pfs_ra8, pfs_port_drive))] drive_capacity: DriveCapacity,
) -> Self {
let mut this = Flex::new(pin);
this.set_as_output();
this.set_level(initial);
#[cfg(any(pfs_ra8, pfs_port_drive))]
this.set_drive_capacity(drive_capacity);
Self { pin: this }
}
#[inline]
#[cfg(any(pfs_ra8, pfs_port_drive))]
pub fn set_drive_capacity(&mut self, drive_capacity: DriveCapacity) {
self.pin.set_drive_capacity(drive_capacity)
}
#[inline(always)]
pub fn set_low(&mut self) {
self.pin.set_low();
}
#[inline(always)]
pub fn set_high(&mut self) {
self.pin.set_high();
}
#[inline(always)]
pub fn set_level(&mut self, level: Level) {
self.pin.set_level(level)
}
#[inline(always)]
pub fn toggle(&mut self) {
self.pin.toggle();
}
#[inline]
pub fn is_set_low(&mut self) -> bool {
self.pin.is_set_low()
}
#[inline]
pub fn is_set_high(&mut self) -> bool {
self.pin.is_set_high()
}
#[inline]
pub fn output_level(&mut self) -> Level {
self.pin.output_level()
}
#[inline]
pub fn print_pfs_state(&self) {
self.pin.print_pfs_state();
}
}
impl<'d> Flex<'d, WithPullUp> {
#[inline]
pub fn new_with_pull_up(pin: Peri<'d, impl PullUpPin>, pull_up: bool) -> Self {
let mut this = Self {
pin: pin.into(),
phantom: PhantomData,
};
this.set_pull_up(pull_up);
trace!(
"Flex<WithPullUp>: port={}, pin={}",
this.pin._port(),
this.pin._pin()
);
this
}
pub fn set_pull_up(&mut self, pull_up: bool) {
self.pin.set_pull_up(pull_up);
}
}
impl<'d> Flex<'d, WithOpenDrain> {
#[inline]
pub fn new_with_open_drain(
pin: Peri<'d, impl OpenDrainPin>,
pull_up: bool,
output_mode: OutputMode,
) -> Self {
let mut this = Self {
pin: pin.into(),
phantom: PhantomData,
};
this.set_pull_up(pull_up);
this.set_output_mode(output_mode);
trace!(
"Flex<OpenDrain>: port={}, pin={}",
this.pin._port(),
this.pin._pin()
);
this
}
#[inline]
pub fn set_pull_up(&mut self, pull_up: bool) {
self.pin.set_pull_up(pull_up);
}
#[inline]
pub fn set_output_mode(&mut self, output_mode: OutputMode) {
self.pin.set_output_mode(output_mode);
}
}
impl<'d> Flex<'d, Basic> {
#[inline]
pub fn new_basic(pin: Peri<'d, impl Pin>) -> Self {
let this = Self {
pin: pin.into(),
phantom: PhantomData,
};
trace!(
"Flex<Basic>: port={}, pin={}",
this.pin._port(),
this.pin._pin()
);
this
}
}
impl<'d, C: ControlKind> Flex<'d, C> {
#[inline]
pub(crate) fn new(pin: Peri<'d, impl Pin>) -> Self {
let this = Self {
pin: pin.into(),
phantom: PhantomData,
};
trace!(
"Flex<Basic>: port={}, pin={}",
this.pin._port(),
this.pin._pin()
);
this
}
#[inline]
pub fn set_as_input(&mut self) {
self.pin.set_as_input();
}
#[inline]
pub fn is_low(&mut self) -> bool {
self.pin.is_low()
}
#[inline]
pub fn is_high(&mut self) -> bool {
self.pin.is_high()
}
#[inline]
pub fn level(&mut self) -> Level {
self.pin.level()
}
#[inline]
pub fn set_as_output(&mut self) {
self.pin.set_as_output();
}
#[inline]
#[cfg(any(pfs_ra8, pfs_port_drive))]
pub fn set_drive_capacity(&mut self, drive_capacity: DriveCapacity) {
self.pin.set_drive_capacity(drive_capacity)
}
#[inline(always)]
pub fn set_low(&mut self) {
self.pin.set_low();
}
#[inline(always)]
pub fn set_high(&mut self) {
self.pin.set_high();
}
#[inline(always)]
pub fn set_level(&mut self, level: Level) {
self.pin.set_level(level)
}
#[inline(always)]
pub fn toggle(&mut self) {
self.pin.toggle();
}
#[inline]
pub fn is_set_low(&mut self) -> bool {
self.pin.is_set_low()
}
#[inline]
pub fn is_set_high(&mut self) -> bool {
self.pin.is_set_high()
}
#[inline]
pub fn output_level(&mut self) -> Level {
self.pin.output_level()
}
pub fn set_as_analog(&mut self) {
self.pin.set_as_analog();
}
pub fn set_as_pf(&mut self, func: PortFunction) {
self.pin.set_as_pf(func);
}
pub fn print_pfs_state(&self) {
#[cfg(feature = "defmt")]
{
let pfs = pac::PFS;
let port_num = self.pin._port() as _;
let pin_num = self.pin._pin() as _;
let pfs_reg = pfs.port_pin(port_num, pin_num);
debug!("P{}{:02}: {}", port_num, pin_num, pfs_reg.read());
}
}
}
impl<'d, C: ControlKind> Drop for Flex<'d, C> {
fn drop(&mut self) {
trace!("P{}{:02} Flex::drop", self.pin.port(), self.pin._pin());
self.set_as_input();
self.pin.set_pull_up(false);
}
}
impl<'d, I: InterruptiblePin> InterruptFlex<'d, I, WithPullUp> {
pub fn set_pull_up(&mut self, pull_up: bool) {
self.pin.set_pull_up(pull_up);
}
}
impl<'d, I: InterruptiblePin, C: ControlKind> InterruptFlex<'d, I, C> {
#[inline]
pub fn new<Int: InterruptType>(
pin: Peri<'d, I>,
gpio_irq: Peri<'d, impl GpioIrq<I>>,
irq: impl interrupt::typelevel::Binding<Int, InputInterruptHandler<I>>,
) -> Self {
let _ = gpio_irq;
let _ = irq;
unsafe {
Int::IRQ.enable();
Int::IRQ.icu_enable(I::INTERRUPT_EVENT);
}
let pfs = pac::PFS;
let pin = Flex::new(pin);
let port_num = pin.pin._port() as _;
let pin_num = pin.pin._pin() as _;
let pfs_reg = pfs.port_pin(port_num, pin_num);
pfs_reg.protected_modify(|r| r.set_isel(true));
let mut this = Self {
pin,
phantom: PhantomData,
phantom_k: PhantomData,
};
this.set_as_input();
this.set_trigger(GpioTrigger::Falling);
this.set_debounce(Debounce::Off);
this
}
pub fn set_trigger(&mut self, trigger: GpioTrigger) {
#[cfg(not(ra8m1))]
let icu = pac::ICU;
#[cfg(ra8m1)]
let icu = pac::ICU_COMMON;
let reg = icu.irqcr((I::INTERRUPT_EVENT as u8 - 1) as _);
match trigger {
GpioTrigger::Falling => reg.modify(|r| r.set_irqmd(Irqmd::FallingEdge)),
GpioTrigger::Rising => reg.modify(|r| r.set_irqmd(Irqmd::RisingEdge)),
GpioTrigger::Both => reg.modify(|r| r.set_irqmd(Irqmd::AnyEdge)),
}
}
pub fn set_debounce(&mut self, debounce: Debounce) {
#[cfg(not(ra8m1))]
let icu = pac::ICU;
#[cfg(ra8m1)]
let icu = pac::ICU_COMMON;
let reg = icu.irqcr((I::INTERRUPT_EVENT as u8 - 1) as _);
match debounce {
Debounce::Off => reg.modify(|r| r.set_flten(false)),
Debounce::Min1 => {
reg.modify(|r| {
r.set_flten(true);
r.set_fclksel(Fclksel::Pclkb1);
});
}
Debounce::Min8 => {
reg.modify(|r| {
r.set_flten(true);
r.set_fclksel(Fclksel::Pclkb8);
});
}
Debounce::Min32 => {
reg.modify(|r| {
r.set_flten(true);
r.set_fclksel(Fclksel::Pclkb32);
});
}
Debounce::Min64 => {
reg.modify(|r| {
r.set_flten(true);
r.set_fclksel(Fclksel::Pclkb64);
});
}
}
}
#[inline]
pub fn set_as_input(&mut self) {
self.pin.set_as_input();
}
pub async fn wait_for_low(&mut self) {
poll_fn(|cx| {
if self.pin.is_low() {
return Poll::Ready(());
}
I::waker().register(cx.waker());
Poll::Pending
})
.await
}
pub async fn wait_for_high(&mut self) {
poll_fn(|cx| {
if self.pin.is_high() {
return Poll::Ready(());
}
I::waker().register(cx.waker());
Poll::Pending
})
.await
}
pub async fn wait_for_event(&mut self) -> Level {
let mut event = false;
poll_fn(|cx| {
if !event {
event = true;
I::waker().register(cx.waker());
Poll::Pending
} else {
Poll::Ready(self.pin.level())
}
})
.await
}
#[inline]
pub fn is_low(&mut self) -> bool {
self.pin.is_low()
}
#[inline]
pub fn is_high(&mut self) -> bool {
self.pin.is_high()
}
#[inline]
pub fn level(&mut self) -> Level {
self.pin.level()
}
#[inline]
pub fn set_as_output(&mut self) {
self.pin.set_as_output();
}
#[inline]
#[cfg(any(pfs_ra8, pfs_port_drive))]
pub fn set_drive_capacity(&mut self, drive_capacity: DriveCapacity) {
self.pin.set_drive_capacity(drive_capacity)
}
#[inline]
pub fn set_low(&mut self) {
self.pin.set_low();
}
#[inline]
pub fn set_high(&mut self) {
self.pin.set_high();
}
#[inline]
pub fn set_level(&mut self, level: Level) {
self.pin.set_level(level)
}
#[inline]
pub fn toggle(&mut self) {
self.pin.toggle();
}
#[inline]
pub fn is_set_low(&mut self) -> bool {
self.pin.is_set_low()
}
#[inline]
pub fn is_set_high(&mut self) -> bool {
self.pin.is_set_high()
}
#[inline]
pub fn output_level(&mut self) -> Level {
self.pin.output_level()
}
pub fn set_as_pf(&mut self, func: PortFunction) {
self.pin.set_as_pf(func);
}
pub fn print_pfs_state(&self) {
self.pin.print_pfs_state();
}
}
macro_rules! gpio_pin {
($pin_name:ident, $port_number:literal, $pin_number:literal, $port:ident) => {
impl crate::gpio::Pin for crate::peripherals::$pin_name {}
impl crate::gpio::SealedPin for crate::peripherals::$pin_name {
#[inline(always)]
fn pin_port(&self) -> crate::gpio::PinId {
crate::gpio::PinId::from_port_pin($port_number, $pin_number)
}
#[inline(always)]
fn regs(&self) -> crate::pac::port::Port {
unsafe { crate::pac::port::Port::from_ptr(crate::pac::$port.as_ptr() as _) }
}
}
impl From<crate::peripherals::$pin_name> for crate::gpio::AnyPin {
fn from(val: crate::peripherals::$pin_name) -> Self {
use crate::gpio::SealedPin as _;
Self {
pin_port: val.pin_port(),
}
}
}
};
}
pub(crate) use gpio_pin;
impl_peripheral!(AnyPin);
impl<Pin: InterruptiblePin, Int: InterruptType> InterruptHandler<Int>
for InputInterruptHandler<Pin>
{
unsafe fn on_interrupt() {
Int::IRQ.icu_unpend();
Pin::waker().wake()
}
}
impl<'d, C: ControlKind> embedded_hal_1::digital::ErrorType for Input<'d, C> {
type Error = Infallible;
}
impl<'d, C: ControlKind> embedded_hal_1::digital::InputPin for Input<'d, C> {
fn is_high(&mut self) -> Result<bool, Self::Error> {
Ok(self.is_high())
}
fn is_low(&mut self) -> Result<bool, Self::Error> {
Ok(self.is_low())
}
}
impl<'d, C: ControlKind> embedded_hal_1::digital::ErrorType for Output<'d, C> {
type Error = Infallible;
}
impl<'d, C: ControlKind> embedded_hal_1::digital::OutputPin for Output<'d, C> {
fn set_low(&mut self) -> Result<(), Self::Error> {
self.set_low();
Ok(())
}
fn set_high(&mut self) -> Result<(), Self::Error> {
self.set_high();
Ok(())
}
}
impl<'d, C: ControlKind> embedded_hal_1::digital::StatefulOutputPin for Output<'d, C> {
fn is_set_high(&mut self) -> Result<bool, Self::Error> {
Ok(self.is_set_high())
}
fn is_set_low(&mut self) -> Result<bool, Self::Error> {
Ok(self.is_set_low())
}
fn toggle(&mut self) -> Result<(), Self::Error> {
self.toggle();
Ok(())
}
}