Refactor GPIO module to make traits accessible in esp-hal-common crate (#9)

* Extract all of the enums/structs/traits that we easily can from gpio!

* Pull the remaining traits (which we're able to) out of gpio!
This commit is contained in:
Jesse Braham 2022-01-24 16:34:45 +00:00 committed by GitHub
parent 70109ffe36
commit ef5d1ac7f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -6,247 +6,179 @@
//! //!
//! [embedded-hal]: https://docs.rs/embedded-hal/latest/embedded_hal/ //! [embedded-hal]: https://docs.rs/embedded-hal/latest/embedded_hal/
use core::marker::PhantomData;
pub use paste::paste; pub use paste::paste;
#[macro_export] #[derive(Copy, Clone)]
macro_rules! impl_output { pub enum Event {
( RisingEdge = 1,
$gpio_function:ident, FallingEdge = 2,
$pxi:ident: AnyEdge = 3,
( LowLevel = 4,
$pin_num:expr, $iomux_reg:expr, $bit:expr, $out_en_set:ident, HighLevel = 5,
$out_en_clear:ident, $out_set:ident, $out_clear:ident, $out_reg:ident }
)
$( ,( $( $af_signal:ident: $af:ident ),* ))?
) => {
impl<MODE> embedded_hal::digital::v2::OutputPin for $pxi<Output<MODE>> {
type Error = Infallible;
fn set_high(&mut self) -> Result<(), Self::Error> { pub struct Unknown {}
unsafe { (*GPIO::ptr()).$out_set.write(|w| w.bits(1 << $bit)) };
Ok(())
}
fn set_low(&mut self) -> Result<(), Self::Error> { pub struct Input<MODE> {
unsafe { (*GPIO::ptr()).$out_clear.write(|w| w.bits(1 << $bit)) }; _mode: PhantomData<MODE>,
Ok(()) }
}
}
impl<MODE> embedded_hal::digital::v2::StatefulOutputPin for $pxi<Output<MODE>> { pub struct RTCInput<MODE> {
fn is_set_high(&self) -> Result<bool, Self::Error> { _mode: PhantomData<MODE>,
unsafe { Ok((*GPIO::ptr()).$out_reg.read().bits() & (1 << $bit) != 0) } }
}
fn is_set_low(&self) -> Result<bool, Self::Error> { pub struct Floating;
Ok(!self.is_set_high()?)
}
}
impl<MODE> embedded_hal::digital::v2::ToggleableOutputPin for $pxi<Output<MODE>> { pub struct PullDown;
type Error = Infallible;
fn toggle(&mut self) -> Result<(), Self::Error> { pub struct PullUp;
if self.is_set_high()? {
Ok(self.set_low()?)
} else {
Ok(self.set_high()?)
}
}
}
impl<MODE> $pxi<MODE> { pub struct Output<MODE> {
pub fn into_pull_up_input(self) -> $pxi<Input<PullUp>> { _mode: PhantomData<MODE>,
self.init_input(false, false); }
$pxi { _mode: PhantomData }
}
pub fn into_pull_down_input(self) -> $pxi<Input<PullDown>> { pub struct RTCOutput<MODE> {
self.init_input(true, false); _mode: PhantomData<MODE>,
$pxi { _mode: PhantomData } }
}
fn init_output(&self, alternate: AlternateFunction, open_drain: bool) { pub struct OpenDrain;
let gpio = unsafe { &*GPIO::ptr() };
let iomux = unsafe { &*IO_MUX::ptr() };
gpio.$out_en_set.write(|w| unsafe { w.bits(1 << $bit) }); pub struct PushPull;
gpio.pin[$pin_num].modify(|_, w| w.pin_pad_driver().bit(open_drain));
gpio.func_out_sel_cfg[$pin_num]
.modify(|_, w| unsafe { w.out_sel().bits(OutputSignal::GPIO as OutputSignalType) });
paste! { pub struct Analog;
iomux.$iomux_reg.modify(|_, w| unsafe {
w.mcu_sel()
.bits(alternate as u8)
.fun_ie()
.clear_bit()
.fun_wpd()
.clear_bit()
.fun_wpu()
.clear_bit()
.fun_drv()
.bits(DriveStrength::I20mA as u8)
.slp_sel()
.clear_bit()
});
}
}
pub fn into_push_pull_output(self) -> $pxi<Output<PushPull>> { pub struct Alternate<MODE> {
self.init_output(AlternateFunction::$gpio_function, false); _mode: PhantomData<MODE>,
$pxi { _mode: PhantomData } }
}
pub fn into_open_drain_output(self) -> $pxi<Output<OpenDrain>> { pub struct AF0;
self.init_output(AlternateFunction::$gpio_function, true);
$pxi { _mode: PhantomData }
}
pub fn into_alternate_1(self) -> $pxi<Alternate<AF1>> { pub struct AF1;
self.init_output(AlternateFunction::Function1, false);
$pxi { _mode: PhantomData }
}
pub fn into_alternate_2(self) -> $pxi<Alternate<AF2>> { pub struct AF2;
self.init_output(AlternateFunction::Function2, false);
$pxi { _mode: PhantomData }
}
}
impl<MODE> OutputPin for $pxi<MODE> { pub enum DriveStrength {
fn set_to_open_drain_output(&mut self) -> &mut Self { I5mA = 0,
self.init_output(AlternateFunction::$gpio_function, true); I10mA = 1,
self I20mA = 2,
} I40mA = 3,
}
fn set_to_push_pull_output(&mut self) -> &mut Self { #[derive(PartialEq)]
self.init_output(AlternateFunction::$gpio_function, false); pub enum AlternateFunction {
self Function0 = 0,
} Function1 = 1,
Function2 = 2,
Function3 = 3,
Function4 = 4,
Function5 = 5,
}
fn enable_output(&mut self, on: bool) -> &mut Self { pub trait RTCPin {}
if on {
unsafe { &*GPIO::ptr() }
.$out_en_set
.write(|w| unsafe { w.bits(1 << $bit) });
} else {
unsafe { &*GPIO::ptr() }
.$out_en_clear
.write(|w| unsafe { w.bits(1 << $bit) });
}
self
}
fn set_output_high(&mut self, high: bool) -> &mut Self { pub trait AnalogPin {}
if high {
unsafe { (*GPIO::ptr()).$out_set.write(|w| w.bits(1 << $bit)) };
} else {
unsafe { (*GPIO::ptr()).$out_clear.write(|w| w.bits(1 << $bit)) };
}
self
}
fn set_drive_strength(&mut self, strength: DriveStrength) -> &mut Self { pub trait Pin {
paste! { fn sleep_mode(&mut self, on: bool) -> &mut Self;
unsafe { &*IO_MUX::ptr() }
.$iomux_reg
.modify(|_, w| unsafe { w.fun_drv().bits(strength as u8) });
}
self
}
fn enable_open_drain(&mut self, on: bool) -> &mut Self { fn set_alternate_function(&mut self, alternate: AlternateFunction) -> &mut Self;
unsafe { &*GPIO::ptr() }.pin[$pin_num].modify(|_, w| w.pin_pad_driver().bit(on));
self
}
fn internal_pull_up_in_sleep_mode(&mut self, on: bool) -> &mut Self { fn listen(&mut self, event: Event) {
paste! { self.listen_with_options(event, true, false, false)
unsafe { &*IO_MUX::ptr() } }
.$iomux_reg
.modify(|_, w| w.mcu_wpu().bit(on));
}
self
}
fn internal_pull_down_in_sleep_mode(&mut self, on: bool) -> &mut Self { fn listen_with_options(
paste!{ &mut self,
unsafe { &*IO_MUX::ptr() } event: Event,
.$iomux_reg int_enable: bool,
.modify(|_, w| w.mcu_wpd().bit(on)); nmi_enable: bool,
} wake_up_from_light_sleep: bool,
self );
}
fn enable_output_in_sleep_mode(&mut self, on: bool) -> &mut Self { fn unlisten(&mut self);
paste! {
unsafe { &*IO_MUX::ptr() }
.$iomux_reg
.modify(|_, w| w.mcu_oe().bit(on));
}
self
}
fn connect_peripheral_to_output_with_options( fn clear_interrupt(&mut self);
&mut self,
signal: OutputSignal,
invert: bool,
invert_enable: bool,
enable_from_gpio: bool,
force_via_gpio_mux: bool,
) -> &mut Self {
let af = if force_via_gpio_mux {
AlternateFunction::$gpio_function
} else {
match signal {
$( $(
OutputSignal::$af_signal => AlternateFunction::$af,
)* )?
_ => AlternateFunction::$gpio_function
}
};
if af == AlternateFunction::$gpio_function && signal as usize > OUTPUT_SIGNAL_MAX as usize { fn is_pcore_interrupt_set(&mut self) -> bool;
panic!("Cannot connect this peripheral to GPIO");
}
self.set_alternate_function(af); fn is_pcore_non_maskable_interrupt_set(&mut self) -> bool;
let clipped_signal = if signal as usize <= OUTPUT_SIGNAL_MAX as usize { signal as OutputSignalType } else { OUTPUT_SIGNAL_MAX }; fn is_acore_interrupt_set(&mut self) -> bool;
unsafe { &*GPIO::ptr() }.func_out_sel_cfg[$pin_num].modify(|_, w| unsafe { fn is_acore_non_maskable_interrupt_set(&mut self) -> bool;
w
.out_sel().bits(clipped_signal)
.inv_sel().bit(invert)
.oen_sel().bit(enable_from_gpio)
.oen_inv_sel().bit(invert_enable)
});
self fn enable_hold(&mut self, on: bool);
} }
fn internal_pull_up(&mut self, on: bool) -> &mut Self { pub trait InputPin: Pin {
paste!{ type InputSignal;
unsafe { &*IO_MUX::ptr() }.$iomux_reg.modify(|_, w| w.fun_wpu().bit(on));
}
self
}
fn internal_pull_down(&mut self, on: bool) -> &mut Self { fn set_to_input(&mut self) -> &mut Self;
paste! {
unsafe { &*IO_MUX::ptr() }.$iomux_reg.modify(|_, w| w.fun_wpd().bit(on)); fn enable_input(&mut self, on: bool) -> &mut Self;
}
self fn enable_input_in_sleep_mode(&mut self, on: bool) -> &mut Self;
}
} fn is_input_high(&mut self) -> bool;
};
fn connect_input_to_peripheral(&mut self, signal: Self::InputSignal) -> &mut Self {
self.connect_input_to_peripheral_with_options(signal, false, false)
}
fn connect_input_to_peripheral_with_options(
&mut self,
signal: Self::InputSignal,
invert: bool,
force_via_gpio_mux: bool,
) -> &mut Self;
}
pub trait OutputPin: Pin {
type OutputSignal;
fn set_to_open_drain_output(&mut self) -> &mut Self;
fn set_to_push_pull_output(&mut self) -> &mut Self;
fn enable_output(&mut self, on: bool) -> &mut Self;
fn set_output_high(&mut self, on: bool) -> &mut Self;
fn set_drive_strength(&mut self, strength: DriveStrength) -> &mut Self;
fn enable_open_drain(&mut self, on: bool) -> &mut Self;
fn enable_output_in_sleep_mode(&mut self, on: bool) -> &mut Self;
fn internal_pull_up_in_sleep_mode(&mut self, on: bool) -> &mut Self;
fn internal_pull_down_in_sleep_mode(&mut self, on: bool) -> &mut Self;
fn connect_peripheral_to_output(&mut self, signal: Self::OutputSignal) -> &mut Self {
self.connect_peripheral_to_output_with_options(signal, false, false, false, false)
}
fn connect_peripheral_to_output_with_options(
&mut self,
signal: Self::OutputSignal,
invert: bool,
invert_enable: bool,
enable_from_gpio: bool,
force_via_gpio_mux: bool,
) -> &mut Self;
fn internal_pull_up(&mut self, on: bool) -> &mut Self;
fn internal_pull_down(&mut self, on: bool) -> &mut Self;
} }
#[macro_export] #[macro_export]
macro_rules! impl_input { macro_rules! impl_input {
( (
$gpio_function:ident, $gpio_function:ident,
$input_signal:ty,
$pxi:ident: $pxi:ident:
( (
$pin_num:expr, $iomux_reg:expr, $bit:expr, $out_en_clear:ident, $pin_num:expr, $iomux_reg:expr, $bit:expr, $out_en_clear:ident,
@ -301,6 +233,8 @@ macro_rules! impl_input {
} }
impl<MODE> InputPin for $pxi<MODE> { impl<MODE> InputPin for $pxi<MODE> {
type InputSignal = $input_signal;
fn set_to_input(&mut self) -> &mut Self { fn set_to_input(&mut self) -> &mut Self {
self.init_input(false, false); self.init_input(false, false);
self self
@ -330,17 +264,16 @@ macro_rules! impl_input {
fn connect_input_to_peripheral_with_options( fn connect_input_to_peripheral_with_options(
&mut self, &mut self,
signal: InputSignal, signal: Self::InputSignal,
invert: bool, invert: bool,
force_via_gpio_mux: bool, force_via_gpio_mux: bool,
) -> &mut Self { ) -> &mut Self {
let af = if force_via_gpio_mux { let af = if force_via_gpio_mux {
AlternateFunction::$gpio_function AlternateFunction::$gpio_function
} else { } else {
match signal { match signal {
$( $( $( $(
InputSignal::$af_signal => AlternateFunction::$af, Self::InputSignal::$af_signal => AlternateFunction::$af,
)* )? )* )?
_ => AlternateFunction::$gpio_function _ => AlternateFunction::$gpio_function
} }
@ -444,11 +377,13 @@ macro_rules! impl_input {
#[macro_export] #[macro_export]
macro_rules! impl_input_wrap { macro_rules! impl_input_wrap {
( (
$gpio_function:ident, $pxi:ident, $pin_num:expr, $iomux_reg:expr, $type:ident, Bank0, SingleCore $gpio_function:ident,
$pxi:ident, $pin_num:expr, $iomux_reg:expr, $type:ident, Bank0, SingleCore
$( ,( $( $af_input_signal:ident : $af_input:ident ),* ) )? $( ,( $( $af_input_signal:ident : $af_input:ident ),* ) )?
) => { ) => {
impl_input!( impl_input!(
$gpio_function, $gpio_function,
InputSignal,
$pxi: $pxi:
( (
$pin_num, $iomux_reg, $pin_num % 32, enable_w1tc, in_, data_next, $pin_num, $iomux_reg, $pin_num % 32, enable_w1tc, in_, data_next,
@ -459,11 +394,13 @@ macro_rules! impl_input_wrap {
}; };
( (
$gpio_function:ident, $pxi:ident, $pin_num:expr, $iomux_reg:expr, $type:ident, Bank1, SingleCore $gpio_function:ident,
$pxi:ident, $pin_num:expr, $iomux_reg:expr, $type:ident, Bank1, SingleCore
$( ,( $( $af_input_signal:ident : $af_input:ident ),* ) )? $( ,( $( $af_input_signal:ident : $af_input:ident ),* ) )?
) => { ) => {
impl_input!( impl_input!(
$gpio_function, $gpio_function,
InputSignal,
$pxi: $pxi:
( (
$pin_num, $iomux_reg, $pin_num % 32, enable1_w1tc, in1, data_next, $pin_num, $iomux_reg, $pin_num % 32, enable1_w1tc, in1, data_next,
@ -474,11 +411,13 @@ macro_rules! impl_input_wrap {
}; };
( (
$gpio_function:ident, $pxi:ident, $pin_num:expr, $iomux_reg:expr, $type:ident, Bank0, DualCore $gpio_function:ident,
$pxi:ident, $pin_num:expr, $iomux_reg:expr, $type:ident, Bank0, DualCore
$( ,( $( $af_input_signal:ident : $af_input:ident ),* ) )? $( ,( $( $af_input_signal:ident : $af_input:ident ),* ) )?
) => { ) => {
impl_input!( impl_input!(
$gpio_function, $gpio_function,
InputSignal,
$pxi: $pxi:
( (
$pin_num, $iomux_reg, $pin_num % 32, enable_w1tc, in_, data_next, $pin_num, $iomux_reg, $pin_num % 32, enable_w1tc, in_, data_next,
@ -489,11 +428,13 @@ macro_rules! impl_input_wrap {
}; };
( (
$gpio_function:ident, $pxi:ident, $pin_num:expr, $iomux_reg:expr, $type:ident, Bank1, DualCore $gpio_function:ident,
$pxi:ident, $pin_num:expr, $iomux_reg:expr, $type:ident, Bank1, DualCore
$( ,( $( $af_input_signal:ident : $af_input:ident ),* ) )? $( ,( $( $af_input_signal:ident : $af_input:ident ),* ) )?
) => { ) => {
impl_input!( impl_input!(
$gpio_function, $gpio_function,
InputSignal,
$pxi: $pxi:
( (
$pin_num, $iomux_reg, $pin_num % 32, enable1_w1tc, in1, data_next, $pin_num, $iomux_reg, $pin_num % 32, enable1_w1tc, in1, data_next,
@ -504,14 +445,255 @@ macro_rules! impl_input_wrap {
}; };
} }
#[macro_export]
macro_rules! impl_output {
(
$gpio_function:ident,
$output_signal:ty,
$pxi:ident:
(
$pin_num:expr, $iomux_reg:expr, $bit:expr, $out_en_set:ident,
$out_en_clear:ident, $out_set:ident, $out_clear:ident, $out_reg:ident
)
$( ,( $( $af_signal:ident: $af:ident ),* ))?
) => {
impl<MODE> embedded_hal::digital::v2::OutputPin for $pxi<Output<MODE>> {
type Error = Infallible;
fn set_high(&mut self) -> Result<(), Self::Error> {
unsafe { (*GPIO::ptr()).$out_set.write(|w| w.bits(1 << $bit)) };
Ok(())
}
fn set_low(&mut self) -> Result<(), Self::Error> {
unsafe { (*GPIO::ptr()).$out_clear.write(|w| w.bits(1 << $bit)) };
Ok(())
}
}
impl<MODE> embedded_hal::digital::v2::StatefulOutputPin for $pxi<Output<MODE>> {
fn is_set_high(&self) -> Result<bool, Self::Error> {
unsafe { Ok((*GPIO::ptr()).$out_reg.read().bits() & (1 << $bit) != 0) }
}
fn is_set_low(&self) -> Result<bool, Self::Error> {
Ok(!self.is_set_high()?)
}
}
impl<MODE> embedded_hal::digital::v2::ToggleableOutputPin for $pxi<Output<MODE>> {
type Error = Infallible;
fn toggle(&mut self) -> Result<(), Self::Error> {
if self.is_set_high()? {
Ok(self.set_low()?)
} else {
Ok(self.set_high()?)
}
}
}
impl<MODE> $pxi<MODE> {
pub fn into_pull_up_input(self) -> $pxi<Input<PullUp>> {
self.init_input(false, false);
$pxi { _mode: PhantomData }
}
pub fn into_pull_down_input(self) -> $pxi<Input<PullDown>> {
self.init_input(true, false);
$pxi { _mode: PhantomData }
}
fn init_output(&self, alternate: AlternateFunction, open_drain: bool) {
let gpio = unsafe { &*GPIO::ptr() };
let iomux = unsafe { &*IO_MUX::ptr() };
gpio.$out_en_set.write(|w| unsafe { w.bits(1 << $bit) });
gpio.pin[$pin_num].modify(|_, w| w.pin_pad_driver().bit(open_drain));
gpio.func_out_sel_cfg[$pin_num]
.modify(|_, w| unsafe { w.out_sel().bits(OutputSignal::GPIO as OutputSignalType) });
paste! {
iomux.$iomux_reg.modify(|_, w| unsafe {
w.mcu_sel()
.bits(alternate as u8)
.fun_ie()
.clear_bit()
.fun_wpd()
.clear_bit()
.fun_wpu()
.clear_bit()
.fun_drv()
.bits(DriveStrength::I20mA as u8)
.slp_sel()
.clear_bit()
});
}
}
pub fn into_push_pull_output(self) -> $pxi<Output<PushPull>> {
self.init_output(AlternateFunction::$gpio_function, false);
$pxi { _mode: PhantomData }
}
pub fn into_open_drain_output(self) -> $pxi<Output<OpenDrain>> {
self.init_output(AlternateFunction::$gpio_function, true);
$pxi { _mode: PhantomData }
}
pub fn into_alternate_1(self) -> $pxi<Alternate<AF1>> {
self.init_output(AlternateFunction::Function1, false);
$pxi { _mode: PhantomData }
}
pub fn into_alternate_2(self) -> $pxi<Alternate<AF2>> {
self.init_output(AlternateFunction::Function2, false);
$pxi { _mode: PhantomData }
}
}
impl<MODE> OutputPin for $pxi<MODE> {
type OutputSignal = $output_signal;
fn set_to_open_drain_output(&mut self) -> &mut Self {
self.init_output(AlternateFunction::$gpio_function, true);
self
}
fn set_to_push_pull_output(&mut self) -> &mut Self {
self.init_output(AlternateFunction::$gpio_function, false);
self
}
fn enable_output(&mut self, on: bool) -> &mut Self {
if on {
unsafe { &*GPIO::ptr() }
.$out_en_set
.write(|w| unsafe { w.bits(1 << $bit) });
} else {
unsafe { &*GPIO::ptr() }
.$out_en_clear
.write(|w| unsafe { w.bits(1 << $bit) });
}
self
}
fn set_output_high(&mut self, high: bool) -> &mut Self {
if high {
unsafe { (*GPIO::ptr()).$out_set.write(|w| w.bits(1 << $bit)) };
} else {
unsafe { (*GPIO::ptr()).$out_clear.write(|w| w.bits(1 << $bit)) };
}
self
}
fn set_drive_strength(&mut self, strength: DriveStrength) -> &mut Self {
paste! {
unsafe { &*IO_MUX::ptr() }
.$iomux_reg
.modify(|_, w| unsafe { w.fun_drv().bits(strength as u8) });
}
self
}
fn enable_open_drain(&mut self, on: bool) -> &mut Self {
unsafe { &*GPIO::ptr() }.pin[$pin_num].modify(|_, w| w.pin_pad_driver().bit(on));
self
}
fn internal_pull_up_in_sleep_mode(&mut self, on: bool) -> &mut Self {
paste! {
unsafe { &*IO_MUX::ptr() }
.$iomux_reg
.modify(|_, w| w.mcu_wpu().bit(on));
}
self
}
fn internal_pull_down_in_sleep_mode(&mut self, on: bool) -> &mut Self {
paste!{
unsafe { &*IO_MUX::ptr() }
.$iomux_reg
.modify(|_, w| w.mcu_wpd().bit(on));
}
self
}
fn enable_output_in_sleep_mode(&mut self, on: bool) -> &mut Self {
paste! {
unsafe { &*IO_MUX::ptr() }
.$iomux_reg
.modify(|_, w| w.mcu_oe().bit(on));
}
self
}
fn connect_peripheral_to_output_with_options(
&mut self,
signal: Self::OutputSignal,
invert: bool,
invert_enable: bool,
enable_from_gpio: bool,
force_via_gpio_mux: bool,
) -> &mut Self {
let af = if force_via_gpio_mux {
AlternateFunction::$gpio_function
} else {
match signal {
$( $(
Self::OutputSignal::$af_signal => AlternateFunction::$af,
)* )?
_ => AlternateFunction::$gpio_function
}
};
if af == AlternateFunction::$gpio_function && signal as usize > OUTPUT_SIGNAL_MAX as usize {
panic!("Cannot connect this peripheral to GPIO");
}
self.set_alternate_function(af);
let clipped_signal = if signal as usize <= OUTPUT_SIGNAL_MAX as usize { signal as OutputSignalType } else { OUTPUT_SIGNAL_MAX };
unsafe { &*GPIO::ptr() }.func_out_sel_cfg[$pin_num].modify(|_, w| unsafe {
w
.out_sel().bits(clipped_signal)
.inv_sel().bit(invert)
.oen_sel().bit(enable_from_gpio)
.oen_inv_sel().bit(invert_enable)
});
self
}
fn internal_pull_up(&mut self, on: bool) -> &mut Self {
paste!{
unsafe { &*IO_MUX::ptr() }.$iomux_reg.modify(|_, w| w.fun_wpu().bit(on));
}
self
}
fn internal_pull_down(&mut self, on: bool) -> &mut Self {
paste! {
unsafe { &*IO_MUX::ptr() }.$iomux_reg.modify(|_, w| w.fun_wpd().bit(on));
}
self
}
}
};
}
#[macro_export] #[macro_export]
macro_rules! impl_output_wrap { macro_rules! impl_output_wrap {
( (
$gpio_function:ident, $pxi:ident, $pin_num:expr, $iomux_reg:expr, IO, Bank0 $gpio_function:ident,
$pxi:ident, $pin_num:expr, $iomux_reg:expr, IO, Bank0
$( ,( $( $af_output_signal:ident : $af_output:ident ),* ))? $( ,( $( $af_output_signal:ident : $af_output:ident ),* ))?
) => { ) => {
impl_output!( impl_output!(
$gpio_function, $gpio_function,
OutputSignal,
$pxi: $pxi:
( (
$pin_num, $iomux_reg, $pin_num % 32, enable_w1ts, enable_w1tc, $pin_num, $iomux_reg, $pin_num % 32, enable_w1ts, enable_w1tc,
@ -522,11 +704,13 @@ macro_rules! impl_output_wrap {
}; };
( (
$gpio_function:ident, $pxi:ident, $pin_num:expr, $iomux_reg:expr, IO, Bank1 $gpio_function:ident,
$pxi:ident, $pin_num:expr, $iomux_reg:expr, IO, Bank1
$( ,( $( $af_output_signal:ident : $af_output:ident ),* ))? $( ,( $( $af_output_signal:ident : $af_output:ident ),* ))?
) => { ) => {
impl_output!( impl_output!(
$gpio_function, $gpio_function,
OutputSignal,
$pxi: $pxi:
( (
$pin_num, $iomux_reg, $pin_num % 32, enable1_w1ts, enable1_w1tc, $pin_num, $iomux_reg, $pin_num % 32, enable1_w1ts, enable1_w1tc,
@ -537,7 +721,8 @@ macro_rules! impl_output_wrap {
}; };
( (
$gpio_function:ident, $pxi:ident, $pin_num:expr, $iomux_reg:expr, $type:ident, $bank:ident $gpio_function:ident,
$pxi:ident, $pin_num:expr, $iomux_reg:expr, $type:ident, $bank:ident
$( ,( $( $af_output_signal:ident : $af_output:ident ),* ))? $( ,( $( $af_output_signal:ident : $af_output:ident ),* ))?
) => {}; ) => {};
} }
@ -583,164 +768,16 @@ macro_rules! gpio {
fn split(self) -> Self::Parts; fn split(self) -> Self::Parts;
} }
pub trait Pin { impl GpioExt for GPIO {
fn sleep_mode(&mut self, on: bool) -> &mut Self; type Parts = Pins;
fn set_alternate_function(&mut self, alternate: AlternateFunction) -> &mut Self; fn split(self) -> Self::Parts {
Pins {
fn listen(&mut self, event: Event) { $(
self.listen_with_options(event, true, false, false) $pname: $pxi { _mode: PhantomData },
)+
}
} }
fn listen_with_options(
&mut self,
event: Event,
int_enable: bool,
nmi_enable: bool,
wake_up_from_light_sleep: bool,
);
fn unlisten(&mut self);
fn clear_interrupt(&mut self);
fn is_pcore_interrupt_set(&mut self) -> bool;
fn is_pcore_non_maskable_interrupt_set(&mut self) -> bool;
fn is_acore_interrupt_set(&mut self) -> bool;
fn is_acore_non_maskable_interrupt_set(&mut self) -> bool;
fn enable_hold(&mut self, on: bool);
}
pub trait InputPin: Pin {
fn set_to_input(&mut self) -> &mut Self;
fn enable_input(&mut self, on: bool) -> &mut Self;
fn enable_input_in_sleep_mode(&mut self, on: bool) -> &mut Self;
fn is_input_high(&mut self) -> bool;
fn connect_input_to_peripheral(&mut self, signal: InputSignal) -> &mut Self {
self.connect_input_to_peripheral_with_options(signal, false, false)
}
fn connect_input_to_peripheral_with_options(
&mut self,
signal: InputSignal,
invert: bool,
force_via_gpio_mux: bool,
) -> &mut Self;
}
pub trait OutputPin: Pin {
fn set_to_open_drain_output(&mut self) -> &mut Self;
fn set_to_push_pull_output(&mut self) -> &mut Self;
fn enable_output(&mut self, on: bool) -> &mut Self;
fn set_output_high(&mut self, on: bool) -> &mut Self;
fn set_drive_strength(&mut self, strength: DriveStrength) -> &mut Self;
fn enable_open_drain(&mut self, on: bool) -> &mut Self;
fn enable_output_in_sleep_mode(&mut self, on: bool) -> &mut Self;
fn internal_pull_up_in_sleep_mode(&mut self, on: bool) -> &mut Self;
fn internal_pull_down_in_sleep_mode(&mut self, on: bool) -> &mut Self;
fn connect_peripheral_to_output(&mut self, signal: OutputSignal) -> &mut Self {
self.connect_peripheral_to_output_with_options(signal, false, false, false, false)
}
fn connect_peripheral_to_output_with_options(
&mut self,
signal: OutputSignal,
invert: bool,
invert_enable: bool,
enable_from_gpio: bool,
force_via_gpio_mux: bool,
) -> &mut Self;
fn internal_pull_up(&mut self, on: bool) -> &mut Self;
fn internal_pull_down(&mut self, on: bool) -> &mut Self;
}
pub trait RTCPin {}
pub trait AnalogPin {}
#[derive(Copy, Clone)]
pub enum Event {
RisingEdge = 1,
FallingEdge = 2,
AnyEdge = 3,
LowLevel = 4,
HighLevel = 5,
}
pub struct Unknown {}
pub struct Input<MODE> {
_mode: PhantomData<MODE>,
}
pub struct RTCInput<MODE> {
_mode: PhantomData<MODE>,
}
pub struct Floating;
pub struct PullDown;
pub struct PullUp;
pub struct Output<MODE> {
_mode: PhantomData<MODE>,
}
pub struct RTCOutput<MODE> {
_mode: PhantomData<MODE>,
}
pub struct OpenDrain;
pub struct PushPull;
pub struct Analog;
pub struct Alternate<MODE> {
_mode: PhantomData<MODE>,
}
pub struct AF0;
pub struct AF1;
pub struct AF2;
pub enum DriveStrength {
I5mA = 0,
I10mA = 1,
I20mA = 2,
I40mA = 3,
}
#[derive(PartialEq)]
pub enum AlternateFunction {
Function0 = 0,
Function1 = 1,
Function2 = 2,
Function3 = 3,
Function4 = 4,
Function5 = 5,
} }
pub fn connect_low_to_peripheral(signal: InputSignal) { pub fn connect_low_to_peripheral(signal: InputSignal) {
@ -765,18 +802,6 @@ macro_rules! gpio {
}); });
} }
impl GpioExt for GPIO {
type Parts = Pins;
fn split(self) -> Self::Parts {
Pins {
$(
$pname: $pxi { _mode: PhantomData },
)+
}
}
}
pub struct Pins { pub struct Pins {
$( $(
pub $pname: $pxi<Unknown>, pub $pname: $pxi<Unknown>,