GPIO interconnect (#2128)

* Allow accessing signal list via ErasedPin

* Replace AnyPin with more flexible signal config

* Update tests and examples

* Fix enable_from_gpio value

* Access signals from pin drivers

* DummyPin is not a pin

* Remove redundant public fns

* Various fixes, rename ErasedPin

* Changelog

* rustfmt

* Update i8080

* Typos and endless recursion

* Drop Pin suffix from traits

* Extract AF conversion

* Touch up changelog

* Clean up spi tests

* Refactor pull resistor handling

* Don't disable configured output functionality

* Clean up TODO

* Tweak docs

* Clean up examples
This commit is contained in:
Dániel Buga 2024-09-11 17:15:55 +02:00 committed by GitHub
parent f2e0211c1b
commit 7a733a75db
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
41 changed files with 1495 additions and 1426 deletions

View File

@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Previously unavailable memory is available via `.dram2_uninit` section (#2079)
- You can now use `Input`, `Output`, `OutputOpenDrain` and `Flex` pins as EXTI and RTCIO wakeup sources (#2095)
- Added `Rtc::set_current_time` to allow setting RTC time, and `Rtc::current_time` to getting RTC time while taking into account boot time (#1883)
- Added APIs to allow connecting signals through the GPIO matrix. (#2128)
### Changed
@ -37,6 +38,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- The (previously undocumented) `ErasedPin` enum has been replaced with the `ErasedPin` struct. (#2094)
- Renamed and merged `Rtc::get_time_us` and `Rtc::get_time_ms` into `Rtc::time_since_boot` (#1883)
- ESP32: Added support for touch sensing on GPIO32 and 33 (#2109)
- Replaced `AnyPin` with `InputSignal` and `OutputSignal` and renamed `ErasedPin` to `AnyPin` (#2128)
### Fixed

View File

@ -48,7 +48,7 @@ You no longer have to spell out the GPIO pin type for `Input`, `Output`, `Output
However, if you want to, you can keep using their typed form!
```rust
let pin = Input::new(io.gpio0); // pin will have the type `Input<'some>` (or `Input<'some, ErasedPin>` if you want to be explicit about it)
let pin = Input::new(io.gpio0); // pin will have the type `Input<'some>` (or `Input<'some, AnyPin>` if you want to be explicit about it)
let pin = Input::new_typed(io.gpio0); // pin will have the type `Input<'some, GpioPin<0>>`
```

View File

@ -1,169 +0,0 @@
use super::*;
/// A type-erased GPIO pin, with additional configuration options.
///
/// Note that accessing unsupported pin functions (e.g. trying to use an
/// input-only pin as output) will panic.
pub struct AnyPin<'d> {
pin: ErasedPin,
is_inverted: bool,
_phantom: PhantomData<&'d ()>,
}
impl<'d> AnyPin<'d> {
/// Create wrapper for the given pin.
#[inline]
pub fn new<P>(pin: impl crate::peripheral::Peripheral<P = P> + 'd) -> Self
where
P: Pin,
{
crate::into_ref!(pin);
let pin = pin.degrade_internal(private::Internal);
Self {
pin,
is_inverted: false,
_phantom: PhantomData,
}
}
/// Create wrapper for the given pin. The peripheral signal will be
/// inverted.
#[inline]
pub fn new_inverted<P>(pin: impl crate::peripheral::Peripheral<P = P> + 'd) -> Self
where
P: Pin,
{
crate::into_ref!(pin);
let pin = pin.degrade_internal(private::Internal);
Self {
pin,
is_inverted: true,
_phantom: PhantomData,
}
}
}
impl<'d> crate::peripheral::Peripheral for AnyPin<'d> {
type P = Self;
unsafe fn clone_unchecked(&mut self) -> Self::P {
Self {
pin: unsafe { self.pin.clone_unchecked() },
is_inverted: self.is_inverted,
_phantom: PhantomData,
}
}
}
impl<'d> private::Sealed for AnyPin<'d> {}
impl<'d> Pin for AnyPin<'d> {
delegate::delegate! {
to self.pin {
fn number(&self, _internal: private::Internal) -> u8;
fn degrade_internal(&self, _internal: private::Internal) -> ErasedPin;
fn sleep_mode(&mut self, on: bool, _internal: private::Internal);
fn set_alternate_function(&mut self, alternate: AlternateFunction, _internal: private::Internal);
fn is_listening(&self, _internal: private::Internal) -> bool;
fn listen_with_options(
&mut self,
event: Event,
int_enable: bool,
nmi_enable: bool,
wake_up_from_light_sleep: bool,
_internal: private::Internal,
);
fn unlisten(&mut self, _internal: private::Internal);
fn is_interrupt_set(&self, _internal: private::Internal) -> bool;
fn clear_interrupt(&mut self, _internal: private::Internal);
}
}
}
impl<'d> OutputPin for AnyPin<'d> {
delegate::delegate! {
to self.pin {
fn set_to_open_drain_output(&mut self, _internal: private::Internal);
fn set_to_push_pull_output(&mut self, _internal: private::Internal);
fn enable_output(&mut self, on: bool, _internal: private::Internal);
fn set_output_high(&mut self, on: bool, _internal: private::Internal);
fn set_drive_strength(&mut self, strength: DriveStrength, _internal: private::Internal);
fn enable_open_drain(&mut self, on: bool, _internal: private::Internal);
fn enable_output_in_sleep_mode(&mut self, on: bool, _internal: private::Internal);
fn internal_pull_up_in_sleep_mode(&mut self, on: bool, _internal: private::Internal);
fn internal_pull_down_in_sleep_mode(&mut self, on: bool, _internal: private::Internal);
fn internal_pull_up(&mut self, on: bool, _internal: private::Internal);
fn internal_pull_down(&mut self, on: bool, _internal: private::Internal);
fn disconnect_peripheral_from_output(&mut self, _internal: private::Internal);
fn is_set_high(&self, _internal: private::Internal) -> bool;
}
}
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,
_internal: private::Internal,
) {
if self.is_inverted {
self.pin.connect_peripheral_to_output_with_options(
signal,
true,
false,
false,
true,
private::Internal,
);
} else {
self.pin.connect_peripheral_to_output_with_options(
signal,
invert,
invert_enable,
enable_from_gpio,
force_via_gpio_mux,
private::Internal,
);
}
}
}
impl<'d> InputPin for AnyPin<'d> {
delegate::delegate! {
to self.pin {
fn init_input(&self, pull_down: bool, pull_up: bool, _internal: private::Internal);
fn enable_input(&mut self, on: bool, _internal: private::Internal);
fn enable_input_in_sleep_mode(&mut self, on: bool, _internal: private::Internal);
fn is_input_high(&self, _internal: private::Internal) -> bool;
fn disconnect_input_from_peripheral(&mut self, signal: InputSignal, _internal: private::Internal);
}
}
fn connect_input_to_peripheral_with_options(
&mut self,
signal: InputSignal,
invert: bool,
force_via_gpio_mux: bool,
_internal: private::Internal,
) {
if self.is_inverted {
self.pin.connect_input_to_peripheral_with_options(
signal,
true,
true,
private::Internal,
);
} else {
self.pin.connect_input_to_peripheral_with_options(
signal,
invert,
force_via_gpio_mux,
private::Internal,
);
}
}
}

View File

@ -1,11 +1,12 @@
//! "Dummy" pins".
//! Placeholder pins.
//!
//! These are useful to pass them into peripheral drivers where you don't want
//! an actual pin but one is required.
use super::*;
/// DummyPin, not useful everywhere as it panics if number() is called
#[derive(Default)]
#[derive(Default, Clone)]
pub struct DummyPin {
value: bool,
}
@ -27,43 +28,72 @@ impl crate::peripheral::Peripheral for DummyPin {
impl private::Sealed for DummyPin {}
impl Pin for DummyPin {
fn number(&self, _: private::Internal) -> u8 {
panic!("DummyPin not supported here!");
impl PeripheralInput for DummyPin {
fn input_signals(&self, _: private::Internal) -> [Option<InputSignal>; 6] {
[None; 6]
}
fn degrade_internal(&self, _: private::Internal) -> ErasedPin {
panic!("Can not type erase the DummyPin!");
fn init_input(&self, _pull: Pull, _: private::Internal) {}
fn enable_input(&mut self, _on: bool, _: private::Internal) {}
fn enable_input_in_sleep_mode(&mut self, _on: bool, _: private::Internal) {}
fn is_input_high(&self, _: private::Internal) -> bool {
self.value
}
fn sleep_mode(&mut self, _on: bool, _: private::Internal) {}
fn connect_input_to_peripheral(&mut self, signal: InputSignal, _: private::Internal) {
let value = if self.value { ONE_INPUT } else { ZERO_INPUT };
fn set_alternate_function(&mut self, _alternate: AlternateFunction, _: private::Internal) {}
fn is_listening(&self, _: private::Internal) -> bool {
false
unsafe { &*GPIO::PTR }
.func_in_sel_cfg(signal as usize - FUNC_IN_SEL_OFFSET)
.modify(|_, w| unsafe {
w.sel()
.set_bit()
.in_inv_sel()
.bit(false)
.in_sel()
.bits(value)
});
}
fn listen_with_options(
&mut self,
_event: Event,
_int_enable: bool,
_nmi_enable: bool,
_wake_up_from_light_sleep: bool,
_: private::Internal,
) {
}
fn unlisten(&mut self, _: private::Internal) {}
fn is_interrupt_set(&self, _: private::Internal) -> bool {
false
}
fn clear_interrupt(&mut self, _: private::Internal) {}
fn disconnect_input_from_peripheral(&mut self, _signal: InputSignal, _: private::Internal) {}
}
impl OutputPin for DummyPin {
impl PeripheralSignal for Level {
delegate::delegate! {
to match self {
Level::High => DummyPin { value: true },
Level::Low => DummyPin { value: false },
} {
fn pull_direction(&self, pull: Pull, _internal: private::Internal);
}
}
}
impl PeripheralInput for Level {
delegate::delegate! {
to match self {
Level::High => DummyPin { value: true },
Level::Low => DummyPin { value: false },
} {
fn init_input(&self, _pull: Pull, _internal: private::Internal);
fn enable_input(&mut self, _on: bool, _internal: private::Internal);
fn enable_input_in_sleep_mode(&mut self, _on: bool, _internal: private::Internal);
fn is_input_high(&self, _internal: private::Internal) -> bool;
fn connect_input_to_peripheral(&mut self, _signal: InputSignal, _internal: private::Internal);
fn disconnect_input_from_peripheral(&mut self, _signal: InputSignal, _internal: private::Internal);
fn input_signals(&self, _internal: private::Internal) -> [Option<InputSignal>; 6];
}
}
}
impl PeripheralSignal for DummyPin {
fn pull_direction(&self, _pull: Pull, _internal: private::Internal) {}
}
impl PeripheralOutput for DummyPin {
fn set_to_open_drain_output(&mut self, _: private::Internal) {}
fn set_to_push_pull_output(&mut self, _: private::Internal) {}
@ -84,53 +114,17 @@ impl OutputPin for DummyPin {
fn internal_pull_down_in_sleep_mode(&mut self, _on: bool, _: private::Internal) {}
fn internal_pull_up(&mut self, _on: bool, _: private::Internal) {}
fn internal_pull_down(&mut self, _on: bool, _: private::Internal) {}
fn connect_peripheral_to_output(&mut self, _signal: OutputSignal, _: private::Internal) {}
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,
_: private::Internal,
) {
}
fn disconnect_peripheral_from_output(&mut self, _: private::Internal) {}
fn is_set_high(&self, _: private::Internal) -> bool {
self.value
}
}
impl InputPin for DummyPin {
fn init_input(&self, _pull_down: bool, _pull_up: bool, _: private::Internal) {}
fn enable_input(&mut self, _on: bool, _: private::Internal) {}
fn enable_input_in_sleep_mode(&mut self, _on: bool, _: private::Internal) {}
fn is_input_high(&self, _: private::Internal) -> bool {
self.value
fn output_signals(&self, _: private::Internal) -> [Option<OutputSignal>; 6] {
[None; 6]
}
fn connect_input_to_peripheral(&mut self, _signal: InputSignal, _: private::Internal) {}
fn connect_peripheral_to_output(&mut self, _signal: OutputSignal, _: private::Internal) {}
fn connect_input_to_peripheral_with_options(
&mut self,
_signal: InputSignal,
_invert: bool,
_force_via_gpio_mux: bool,
_: private::Internal,
) {
}
fn disconnect_input_from_peripheral(&mut self, _signal: InputSignal, _: private::Internal) {}
fn disconnect_from_peripheral_output(&mut self, _signal: OutputSignal, _: private::Internal) {}
}
impl embedded_hal_02::digital::v2::OutputPin for DummyPin {
@ -147,10 +141,10 @@ impl embedded_hal_02::digital::v2::OutputPin for DummyPin {
}
impl embedded_hal_02::digital::v2::StatefulOutputPin for DummyPin {
fn is_set_high(&self) -> Result<bool, Self::Error> {
Ok(OutputPin::is_set_high(self, private::Internal))
Ok(PeripheralOutput::is_set_high(self, private::Internal))
}
fn is_set_low(&self) -> Result<bool, Self::Error> {
Ok(!OutputPin::is_set_high(self, private::Internal))
Ok(!PeripheralOutput::is_set_high(self, private::Internal))
}
}
@ -172,10 +166,10 @@ impl embedded_hal::digital::OutputPin for DummyPin {
impl embedded_hal::digital::StatefulOutputPin for DummyPin {
fn is_set_high(&mut self) -> Result<bool, Self::Error> {
Ok(OutputPin::is_set_high(self, private::Internal))
Ok(PeripheralOutput::is_set_high(self, private::Internal))
}
fn is_set_low(&mut self) -> Result<bool, Self::Error> {
Ok(!OutputPin::is_set_high(self, private::Internal))
Ok(!PeripheralOutput::is_set_high(self, private::Internal))
}
}

View File

@ -152,11 +152,7 @@ impl<const C: u8> GpioEtmEventChannel<C> {
{
crate::into_ref!(pin);
pin.init_input(
pin_config.pull == Pull::Down,
pin_config.pull == Pull::Up,
private::Internal,
);
pin.init_input(pin_config.pull, private::Internal);
enable_event_channel(C, pin.number(private::Internal));
GpioEtmEventChannelRising { _pin: pin }
@ -173,11 +169,7 @@ impl<const C: u8> GpioEtmEventChannel<C> {
{
crate::into_ref!(pin);
pin.init_input(
pin_config.pull == Pull::Down,
pin_config.pull == Pull::Up,
private::Internal,
);
pin.init_input(pin_config.pull, private::Internal);
enable_event_channel(C, pin.number(private::Internal));
GpioEtmEventChannelFalling { _pin: pin }
@ -194,11 +186,7 @@ impl<const C: u8> GpioEtmEventChannel<C> {
{
crate::into_ref!(pin);
pin.init_input(
pin_config.pull == Pull::Down,
pin_config.pull == Pull::Up,
private::Internal,
);
pin.init_input(pin_config.pull, private::Internal);
enable_event_channel(C, pin.number(private::Internal));
GpioEtmEventChannelAny { _pin: pin }
@ -318,8 +306,7 @@ impl<const C: u8> GpioEtmTaskChannel<C> {
pin.set_output_high(pin_config.initial_state.into(), private::Internal);
if pin_config.open_drain {
pin.internal_pull_down(pin_config.pull == Pull::Down, private::Internal);
pin.internal_pull_up(pin_config.pull == Pull::Up, private::Internal);
pin.pull_direction(pin_config.pull, private::Internal);
pin.set_to_open_drain_output(private::Internal);
} else {
pin.set_to_push_pull_output(private::Internal);
@ -342,8 +329,7 @@ impl<const C: u8> GpioEtmTaskChannel<C> {
pin.set_output_high(pin_config.initial_state.into(), private::Internal);
if pin_config.open_drain {
pin.internal_pull_down(pin_config.pull == Pull::Down, private::Internal);
pin.internal_pull_up(pin_config.pull == Pull::Up, private::Internal);
pin.pull_direction(pin_config.pull, private::Internal);
pin.set_to_open_drain_output(private::Internal);
} else {
pin.set_to_push_pull_output(private::Internal);
@ -366,8 +352,7 @@ impl<const C: u8> GpioEtmTaskChannel<C> {
pin.set_output_high(pin_config.initial_state.into(), private::Internal);
if pin_config.open_drain {
pin.internal_pull_down(pin_config.pull == Pull::Down, private::Internal);
pin.internal_pull_up(pin_config.pull == Pull::Up, private::Internal);
pin.pull_direction(pin_config.pull, private::Internal);
pin.set_to_open_drain_output(private::Internal);
} else {
pin.set_to_push_pull_output(private::Internal);

View File

@ -0,0 +1,418 @@
//! Peripheral signal interconnect using IOMUX or GPIOMUX.
use crate::{
gpio::{
self,
AlternateFunction,
AnyPin,
DummyPin,
GpioPin,
GpioProperties,
InputPin,
Level,
OutputSignalType,
PeripheralInput,
PeripheralOutput,
PeripheralSignal,
Pin,
Pull,
FUNC_IN_SEL_OFFSET,
GPIO_FUNCTION,
INPUT_SIGNAL_MAX,
OUTPUT_SIGNAL_MAX,
},
peripheral::Peripheral,
peripherals::GPIO,
private::{self, Sealed},
};
/// A configurable input signal between a peripheral and a GPIO pin.
///
/// Obtained by calling [`GpioPin::peripheral_input()`],
/// [`super::Flex::peripheral_input()`] or [`super::Input::peripheral_input()`].
///
/// Multiple input signals can be connected to one pin.
pub struct InputSignal {
pin: AnyPin,
is_inverted: bool,
}
impl Clone for InputSignal {
fn clone(&self) -> Self {
Self {
pin: unsafe { self.pin.clone_unchecked() },
is_inverted: self.is_inverted,
}
}
}
impl Peripheral for InputSignal {
type P = Self;
unsafe fn clone_unchecked(&mut self) -> Self::P {
self.clone()
}
}
impl Sealed for InputSignal {}
impl InputSignal {
pub(crate) fn new(pin: AnyPin) -> Self {
Self {
pin,
is_inverted: false,
}
}
/// Inverts the peripheral's input signal.
///
/// Calling this function multiple times toggles the setting.
pub fn invert(&mut self) {
self.is_inverted = !self.is_inverted;
}
/// Consumed the signal and returns a new one that inverts the peripheral's
/// input signal.
///
/// Calling this function multiple times toggles the setting.
pub fn inverted(mut self) -> Self {
self.invert();
self
}
/// - signal: The input signal to connect to the pin
/// - invert: Configures whether or not to invert the input value
/// - input: The GPIO number to connect to the input signal
fn connect(&self, signal: usize, invert: bool, input: u8) {
unsafe { &*GPIO::PTR }
.func_in_sel_cfg(signal - FUNC_IN_SEL_OFFSET)
.modify(|_, w| unsafe {
w.sel()
.set_bit()
.in_inv_sel()
.bit(invert)
.in_sel()
.bits(input)
});
}
}
impl PeripheralSignal for InputSignal {
delegate::delegate! {
to self.pin {
fn pull_direction(&self, pull: Pull, _internal: private::Internal);
}
}
}
impl PeripheralInput for InputSignal {
/// Connect the pin to a peripheral input signal.
///
/// Since there can only be one input signal connected to a peripheral at a
/// time, this function will disconnect any previously connected input
/// signals.
fn connect_input_to_peripheral(&mut self, signal: gpio::InputSignal, _: private::Internal) {
let signal_nr = signal as usize;
let af = if self.is_inverted {
GPIO_FUNCTION
} else {
self.pin
.input_signals(private::Internal)
.into_iter()
.position(|s| s == Some(signal))
.ok_or(())
.and_then(AlternateFunction::try_from)
.unwrap_or(GPIO_FUNCTION)
};
if af == GPIO_FUNCTION && signal_nr > INPUT_SIGNAL_MAX as usize {
panic!("Cannot connect GPIO to this peripheral");
}
self.pin.set_alternate_function(af, private::Internal);
if signal_nr <= INPUT_SIGNAL_MAX as usize {
self.connect(
signal_nr,
self.is_inverted,
self.pin.number(private::Internal),
);
}
}
/// Remove this pin from a connected peripheral input.
///
/// Clears the entry in the GPIO matrix / Io mux that associates this input
/// pin with the given [input `signal`](`InputSignal`). Any other
/// connected signals remain intact.
fn disconnect_input_from_peripheral(
&mut self,
signal: gpio::InputSignal,
_: private::Internal,
) {
self.pin
.set_alternate_function(GPIO_FUNCTION, private::Internal);
unsafe { &*GPIO::PTR }
.func_in_sel_cfg(signal as usize - FUNC_IN_SEL_OFFSET)
.modify(|_, w| w.sel().clear_bit());
}
delegate::delegate! {
to self.pin {
fn init_input(&self, pull: Pull, _internal: private::Internal);
fn is_input_high(&self, _internal: private::Internal) -> bool;
fn input_signals(&self, _internal: private::Internal) -> [Option<gpio::InputSignal>; 6];
fn enable_input(&mut self, on: bool, _internal: private::Internal);
fn enable_input_in_sleep_mode(&mut self, on: bool, _internal: private::Internal);
}
}
}
/// A configurable output signal between a peripheral and a GPIO pin.
///
/// Obtained by calling [`GpioPin::into_peripheral_output()`],
/// [`super::Flex::into_peripheral_output()`] or
/// [`super::Output::into_peripheral_output()`].
///
/// Multiple pins can be connected to one output signal.
pub struct OutputSignal {
pin: AnyPin,
is_inverted: bool,
}
impl Peripheral for OutputSignal {
type P = Self;
unsafe fn clone_unchecked(&mut self) -> Self::P {
Self {
pin: self.pin.clone_unchecked(),
is_inverted: self.is_inverted,
}
}
}
impl Sealed for OutputSignal {}
impl OutputSignal {
pub(crate) fn new(pin: AnyPin) -> Self {
Self {
pin,
is_inverted: false,
}
}
/// Inverts the peripheral's output signal.
///
/// Calling this function multiple times toggles the setting.
pub fn invert(&mut self) {
self.is_inverted = !self.is_inverted;
}
/// Consumed the signal and returns a new one that inverts the peripheral's
/// output signal.
///
/// Calling this function multiple times toggles the setting.
pub fn inverted(mut self) -> Self {
self.invert();
self
}
/// - signal: The output signal to connect to the pin
/// - invert: Configures whether or not to invert the output value
/// - invert_enable: Configures whether or not to invert the output enable
/// signal
/// - enable_from_gpio: Configures to select the source of output enable
/// signal.
/// - false: Use output enable signal from peripheral
/// - true: Force the output enable signal to be sourced from bit n of
/// GPIO_ENABLE_REG
/// - output: The GPIO number to connect to the output signal
fn connect(
&self,
signal: OutputSignalType,
invert: bool,
invert_enable: bool,
enable_from_gpio: bool,
output: u8,
) {
unsafe { &*GPIO::PTR }
.func_out_sel_cfg(output as usize)
.modify(|_, w| unsafe {
w.out_sel()
.bits(signal)
.inv_sel()
.bit(invert)
.oen_sel()
.bit(enable_from_gpio)
.oen_inv_sel()
.bit(invert_enable)
});
}
}
impl PeripheralSignal for OutputSignal {
delegate::delegate! {
to self.pin {
fn pull_direction(&self, pull: Pull, _internal: private::Internal);
}
}
}
impl PeripheralOutput for OutputSignal {
/// Connect the pin to a peripheral output signal.
fn connect_peripheral_to_output(&mut self, signal: gpio::OutputSignal, _: private::Internal) {
let af = if self.is_inverted {
GPIO_FUNCTION
} else {
self.pin
.output_signals(private::Internal)
.into_iter()
.position(|s| s == Some(signal))
.ok_or(())
.and_then(AlternateFunction::try_from)
.unwrap_or(GPIO_FUNCTION)
};
self.pin.set_alternate_function(af, private::Internal);
let clipped_signal = if signal as usize <= OUTPUT_SIGNAL_MAX as usize {
signal as OutputSignalType
} else {
OUTPUT_SIGNAL_MAX
};
self.connect(
clipped_signal,
self.is_inverted,
false,
false,
self.pin.number(private::Internal),
);
}
/// Remove this output pin from a connected [signal](`OutputSignal`).
///
/// Clears the entry in the GPIO matrix / Io mux that associates this output
/// pin with a previously connected [signal](`OutputSignal`). Any other
/// outputs connected to the peripheral remain intact.
fn disconnect_from_peripheral_output(
&mut self,
signal: gpio::OutputSignal,
_: private::Internal,
) {
self.pin
.set_alternate_function(GPIO_FUNCTION, private::Internal);
unsafe { &*GPIO::PTR }
.func_in_sel_cfg(signal as usize - FUNC_IN_SEL_OFFSET)
.modify(|_, w| w.sel().clear_bit());
}
delegate::delegate! {
to self.pin {
fn set_to_open_drain_output(&mut self, _internal: private::Internal);
fn set_to_push_pull_output(&mut self, _internal: private::Internal);
fn enable_output(&mut self, on: bool, _internal: private::Internal);
fn set_output_high(&mut self, on: bool, _internal: private::Internal);
fn set_drive_strength(&mut self, strength: gpio::DriveStrength, _internal: private::Internal);
fn enable_open_drain(&mut self, on: bool, _internal: private::Internal);
fn enable_output_in_sleep_mode(&mut self, on: bool, _internal: private::Internal);
fn internal_pull_up_in_sleep_mode(&mut self, on: bool, _internal: private::Internal);
fn internal_pull_down_in_sleep_mode(&mut self, on: bool, _internal: private::Internal);
fn is_set_high(&self, _internal: private::Internal) -> bool;
fn output_signals(&self, _internal: private::Internal) -> [Option<gpio::OutputSignal>; 6];
}
}
}
#[derive(Clone)]
enum AnyInputSignalInner {
Input(InputSignal),
Constant(Level),
Dummy(DummyPin),
}
/// A type-erased input signal.
#[derive(Clone)]
pub struct AnyInputSignal(AnyInputSignalInner);
impl Peripheral for AnyInputSignal {
type P = Self;
unsafe fn clone_unchecked(&mut self) -> Self::P {
self.clone()
}
}
impl From<InputSignal> for AnyInputSignal {
fn from(input: InputSignal) -> Self {
Self(AnyInputSignalInner::Input(input))
}
}
impl From<Level> for AnyInputSignal {
fn from(level: Level) -> Self {
Self(AnyInputSignalInner::Constant(level))
}
}
impl From<DummyPin> for AnyInputSignal {
fn from(pin: DummyPin) -> Self {
Self(AnyInputSignalInner::Dummy(pin))
}
}
impl From<AnyPin> for AnyInputSignal {
fn from(input: AnyPin) -> Self {
Self(AnyInputSignalInner::Input(input.peripheral_input()))
}
}
impl<const GPIONUM: u8> From<GpioPin<GPIONUM>> for AnyInputSignal
where
GpioPin<GPIONUM>: InputPin + GpioProperties,
{
fn from(pin: GpioPin<GPIONUM>) -> Self {
Self(AnyInputSignalInner::Input(pin.peripheral_input()))
}
}
impl Sealed for AnyInputSignal {}
impl PeripheralSignal for AnyInputSignal {
delegate::delegate! {
to match &self.0 {
AnyInputSignalInner::Input(pin) => pin,
AnyInputSignalInner::Constant(level) => level,
AnyInputSignalInner::Dummy(pin) => pin,
} {
fn pull_direction(&self, pull: Pull, _internal: private::Internal);
}
}
}
impl PeripheralInput for AnyInputSignal {
delegate::delegate! {
to match &self.0 {
AnyInputSignalInner::Input(pin) => pin,
AnyInputSignalInner::Constant(level) => level,
AnyInputSignalInner::Dummy(pin) => pin,
} {
fn init_input(&self, pull: Pull, _internal: private::Internal);
fn is_input_high(&self, _internal: private::Internal) -> bool;
fn input_signals(&self, _internal: private::Internal) -> [Option<gpio::InputSignal>; 6];
}
to match &mut self.0 {
AnyInputSignalInner::Input(pin) => pin,
AnyInputSignalInner::Constant(level) => level,
AnyInputSignalInner::Dummy(pin) => pin,
} {
fn enable_input(&mut self, on: bool, _internal: private::Internal);
fn enable_input_in_sleep_mode(&mut self, on: bool, _internal: private::Internal);
fn connect_input_to_peripheral(&mut self, signal: crate::gpio::InputSignal, _internal: private::Internal);
fn disconnect_input_from_peripheral(&mut self, signal: crate::gpio::InputSignal, _internal: private::Internal);
}
}
}

View File

@ -264,7 +264,7 @@ macro_rules! lp_gpio {
($this:expr, $inner:ident, $code:tt) => {
match $this {
$(
ErasedPinInner::[<Gpio $gpionum >]($inner) => {
AnyPinInner::[<Gpio $gpionum >]($inner) => {
$code
},
)+

File diff suppressed because it is too large Load Diff

View File

@ -57,7 +57,7 @@ use fugit::HertzU32;
use crate::{
clock::Clocks,
gpio::{InputPin, InputSignal, OutputPin, OutputSignal},
gpio::{InputSignal, OutputSignal, PeripheralInput, PeripheralOutput, Pull},
interrupt::InterruptHandler,
peripheral::{Peripheral, PeripheralRef},
peripherals::i2c0::{RegisterBlock, COMD},
@ -321,7 +321,10 @@ impl<'d, T, DM: crate::Mode> I2C<'d, T, DM>
where
T: Instance,
{
fn new_internal<SDA: OutputPin + InputPin, SCL: OutputPin + InputPin>(
fn new_internal<
SDA: PeripheralOutput + PeripheralInput,
SCL: PeripheralOutput + PeripheralInput,
>(
i2c: impl Peripheral<P = T> + 'd,
sda: impl Peripheral<P = SDA> + 'd,
scl: impl Peripheral<P = SCL> + 'd,
@ -355,27 +358,29 @@ where
scl.set_to_open_drain_output(crate::private::Internal);
scl.enable_input(true, crate::private::Internal);
scl.internal_pull_up(true, crate::private::Internal);
scl.connect_peripheral_to_output(
i2c.peripheral.scl_output_signal(),
crate::private::Internal,
);
scl.pull_direction(Pull::Up, crate::private::Internal);
scl.connect_input_to_peripheral(
i2c.peripheral.scl_input_signal(),
crate::private::Internal,
);
scl.connect_peripheral_to_output(
i2c.peripheral.scl_output_signal(),
crate::private::Internal,
);
sda.set_to_open_drain_output(crate::private::Internal);
sda.enable_input(true, crate::private::Internal);
sda.internal_pull_up(true, crate::private::Internal);
sda.connect_peripheral_to_output(
i2c.peripheral.sda_output_signal(),
crate::private::Internal,
);
sda.pull_direction(Pull::Up, crate::private::Internal);
sda.connect_input_to_peripheral(
i2c.peripheral.sda_input_signal(),
crate::private::Internal,
);
sda.connect_peripheral_to_output(
i2c.peripheral.sda_output_signal(),
crate::private::Internal,
);
i2c.peripheral.setup(frequency, timeout);
i2c
@ -396,7 +401,7 @@ where
/// Create a new I2C instance
/// This will enable the peripheral but the peripheral won't get
/// automatically disabled when this gets dropped.
pub fn new<SDA: OutputPin + InputPin, SCL: OutputPin + InputPin>(
pub fn new<SDA: PeripheralOutput + PeripheralInput, SCL: PeripheralOutput + PeripheralInput>(
i2c: impl Peripheral<P = T> + 'd,
sda: impl Peripheral<P = SDA> + 'd,
scl: impl Peripheral<P = SCL> + 'd,
@ -408,7 +413,10 @@ where
/// Create a new I2C instance with a custom timeout value.
/// This will enable the peripheral but the peripheral won't get
/// automatically disabled when this gets dropped.
pub fn new_with_timeout<SDA: OutputPin + InputPin, SCL: OutputPin + InputPin>(
pub fn new_with_timeout<
SDA: PeripheralOutput + PeripheralInput,
SCL: PeripheralOutput + PeripheralInput,
>(
i2c: impl Peripheral<P = T> + 'd,
sda: impl Peripheral<P = SDA> + 'd,
scl: impl Peripheral<P = SCL> + 'd,
@ -437,7 +445,10 @@ where
/// Create a new I2C instance
/// This will enable the peripheral but the peripheral won't get
/// automatically disabled when this gets dropped.
pub fn new_async<SDA: OutputPin + InputPin, SCL: OutputPin + InputPin>(
pub fn new_async<
SDA: PeripheralOutput + PeripheralInput,
SCL: PeripheralOutput + PeripheralInput,
>(
i2c: impl Peripheral<P = T> + 'd,
sda: impl Peripheral<P = SDA> + 'd,
scl: impl Peripheral<P = SCL> + 'd,
@ -449,7 +460,10 @@ where
/// Create a new I2C instance with a custom timeout value.
/// This will enable the peripheral but the peripheral won't get
/// automatically disabled when this gets dropped.
pub fn new_with_timeout_async<SDA: OutputPin + InputPin, SCL: OutputPin + InputPin>(
pub fn new_with_timeout_async<
SDA: PeripheralOutput + PeripheralInput,
SCL: PeripheralOutput + PeripheralInput,
>(
i2c: impl Peripheral<P = T> + 'd,
sda: impl Peripheral<P = SDA> + 'd,
scl: impl Peripheral<P = SCL> + 'd,

View File

@ -107,7 +107,7 @@ use crate::{
TxPrivate,
WriteBuffer,
},
gpio::OutputPin,
gpio::PeripheralOutput,
interrupt::InterruptHandler,
into_ref,
peripheral::Peripheral,
@ -495,10 +495,11 @@ where
}
/// Configures the I2S peripheral to use a master clock (MCLK) output pin.
pub fn with_mclk<P: OutputPin>(self, pin: impl Peripheral<P = P> + 'd) -> Self {
pub fn with_mclk<P: PeripheralOutput>(self, pin: impl Peripheral<P = P> + 'd) -> Self {
into_ref!(pin);
pin.set_to_push_pull_output(crate::private::Internal);
pin.connect_peripheral_to_output(I::mclk_signal(), crate::private::Internal);
self
}
}
@ -890,7 +891,7 @@ mod private {
use crate::peripherals::{i2s1::RegisterBlock, I2S1};
use crate::{
dma::{ChannelRx, ChannelTx, DmaChannel, DmaDescriptor, DmaPeripheral},
gpio::{InputPin, InputSignal, OutputPin, OutputSignal},
gpio::{InputSignal, OutputSignal, PeripheralInput, PeripheralOutput},
interrupt::InterruptHandler,
into_ref,
peripherals::I2S0,
@ -923,31 +924,34 @@ mod private {
pub fn with_bclk<P>(self, pin: impl crate::peripheral::Peripheral<P = P> + 'd) -> Self
where
P: OutputPin,
P: PeripheralOutput,
{
into_ref!(pin);
pin.set_to_push_pull_output(private::Internal);
pin.connect_peripheral_to_output(T::bclk_signal(), private::Internal);
self
}
pub fn with_ws<P>(self, pin: impl crate::peripheral::Peripheral<P = P> + 'd) -> Self
where
P: OutputPin,
P: PeripheralOutput,
{
into_ref!(pin);
pin.set_to_push_pull_output(private::Internal);
pin.connect_peripheral_to_output(T::ws_signal(), private::Internal);
self
}
pub fn with_dout<P>(self, pin: impl crate::peripheral::Peripheral<P = P> + 'd) -> Self
where
P: OutputPin,
P: PeripheralOutput,
{
into_ref!(pin);
pin.set_to_push_pull_output(private::Internal);
pin.connect_peripheral_to_output(T::dout_signal(), private::Internal);
self
}
}
@ -976,31 +980,34 @@ mod private {
pub fn with_bclk<P>(self, pin: impl crate::peripheral::Peripheral<P = P> + 'd) -> Self
where
P: OutputPin,
P: PeripheralOutput,
{
into_ref!(pin);
pin.set_to_push_pull_output(crate::private::Internal);
pin.connect_peripheral_to_output(T::bclk_rx_signal(), crate::private::Internal);
pin.set_to_push_pull_output(private::Internal);
pin.connect_peripheral_to_output(T::bclk_rx_signal(), private::Internal);
self
}
pub fn with_ws<P>(self, pin: impl crate::peripheral::Peripheral<P = P> + 'd) -> Self
where
P: OutputPin,
P: PeripheralOutput,
{
into_ref!(pin);
pin.set_to_push_pull_output(crate::private::Internal);
pin.connect_peripheral_to_output(T::ws_rx_signal(), crate::private::Internal);
pin.set_to_push_pull_output(private::Internal);
pin.connect_peripheral_to_output(T::ws_rx_signal(), private::Internal);
self
}
pub fn with_din<P>(self, pin: impl crate::peripheral::Peripheral<P = P> + 'd) -> Self
where
P: InputPin,
P: PeripheralInput,
{
into_ref!(pin);
pin.init_input(false, false, crate::private::Internal);
pin.connect_input_to_peripheral(T::din_signal(), crate::private::Internal);
pin.init_input(crate::gpio::Pull::None, private::Internal);
pin.connect_input_to_peripheral(T::din_signal(), private::Internal);
self
}
}

View File

@ -81,7 +81,7 @@ use crate::{
RxPrivate,
WriteBuffer,
},
gpio::{InputPin, InputSignal, OutputPin, OutputSignal},
gpio::{InputPin, InputSignal, OutputPin, OutputSignal, Pull},
lcd_cam::{cam::private::RxPins, private::calculate_clkm, BitOrder, ByteOrder},
peripheral::{Peripheral, PeripheralRef},
peripherals::LCD_CAM,
@ -311,7 +311,7 @@ impl<'d, CH: DmaChannel> Camera<'d, CH> {
pub fn with_pixel_clock<PCLK: InputPin>(self, pclk: impl Peripheral<P = PCLK> + 'd) -> Self {
crate::into_ref!(pclk);
pclk.init_input(false, false, crate::private::Internal);
pclk.init_input(Pull::None, crate::private::Internal);
pclk.connect_input_to_peripheral(InputSignal::CAM_PCLK, crate::private::Internal);
self
@ -327,9 +327,9 @@ impl<'d, CH: DmaChannel> Camera<'d, CH> {
crate::into_ref!(vsync);
crate::into_ref!(h_enable);
vsync.init_input(false, false, crate::private::Internal);
vsync.init_input(Pull::None, crate::private::Internal);
vsync.connect_input_to_peripheral(InputSignal::CAM_V_SYNC, crate::private::Internal);
h_enable.init_input(false, false, crate::private::Internal);
h_enable.init_input(Pull::None, crate::private::Internal);
h_enable.connect_input_to_peripheral(InputSignal::CAM_H_ENABLE, crate::private::Internal);
self.lcd_cam
@ -351,11 +351,11 @@ impl<'d, CH: DmaChannel> Camera<'d, CH> {
crate::into_ref!(hsync);
crate::into_ref!(h_enable);
vsync.init_input(false, false, crate::private::Internal);
vsync.init_input(Pull::None, crate::private::Internal);
vsync.connect_input_to_peripheral(InputSignal::CAM_V_SYNC, crate::private::Internal);
hsync.init_input(false, false, crate::private::Internal);
hsync.init_input(Pull::None, crate::private::Internal);
hsync.connect_input_to_peripheral(InputSignal::CAM_H_SYNC, crate::private::Internal);
h_enable.init_input(false, false, crate::private::Internal);
h_enable.init_input(Pull::None, crate::private::Internal);
h_enable.connect_input_to_peripheral(InputSignal::CAM_H_ENABLE, crate::private::Internal);
self.lcd_cam
@ -475,21 +475,21 @@ impl RxEightBits {
crate::into_ref!(pin_6);
crate::into_ref!(pin_7);
pin_0.init_input(false, false, crate::private::Internal);
pin_0.init_input(Pull::None, crate::private::Internal);
pin_0.connect_input_to_peripheral(InputSignal::CAM_DATA_0, crate::private::Internal);
pin_1.init_input(false, false, crate::private::Internal);
pin_1.init_input(Pull::None, crate::private::Internal);
pin_1.connect_input_to_peripheral(InputSignal::CAM_DATA_1, crate::private::Internal);
pin_2.init_input(false, false, crate::private::Internal);
pin_2.init_input(Pull::None, crate::private::Internal);
pin_2.connect_input_to_peripheral(InputSignal::CAM_DATA_2, crate::private::Internal);
pin_3.init_input(false, false, crate::private::Internal);
pin_3.init_input(Pull::None, crate::private::Internal);
pin_3.connect_input_to_peripheral(InputSignal::CAM_DATA_3, crate::private::Internal);
pin_4.init_input(false, false, crate::private::Internal);
pin_4.init_input(Pull::None, crate::private::Internal);
pin_4.connect_input_to_peripheral(InputSignal::CAM_DATA_4, crate::private::Internal);
pin_5.init_input(false, false, crate::private::Internal);
pin_5.init_input(Pull::None, crate::private::Internal);
pin_5.connect_input_to_peripheral(InputSignal::CAM_DATA_5, crate::private::Internal);
pin_6.init_input(false, false, crate::private::Internal);
pin_6.init_input(Pull::None, crate::private::Internal);
pin_6.connect_input_to_peripheral(InputSignal::CAM_DATA_6, crate::private::Internal);
pin_7.init_input(false, false, crate::private::Internal);
pin_7.init_input(Pull::None, crate::private::Internal);
pin_7.connect_input_to_peripheral(InputSignal::CAM_DATA_7, crate::private::Internal);
Self { _pins: () }
@ -563,37 +563,37 @@ impl RxSixteenBits {
crate::into_ref!(pin_14);
crate::into_ref!(pin_15);
pin_0.init_input(false, false, crate::private::Internal);
pin_0.init_input(Pull::None, crate::private::Internal);
pin_0.connect_input_to_peripheral(InputSignal::CAM_DATA_0, crate::private::Internal);
pin_1.init_input(false, false, crate::private::Internal);
pin_1.init_input(Pull::None, crate::private::Internal);
pin_1.connect_input_to_peripheral(InputSignal::CAM_DATA_1, crate::private::Internal);
pin_2.init_input(false, false, crate::private::Internal);
pin_2.init_input(Pull::None, crate::private::Internal);
pin_2.connect_input_to_peripheral(InputSignal::CAM_DATA_2, crate::private::Internal);
pin_3.init_input(false, false, crate::private::Internal);
pin_3.init_input(Pull::None, crate::private::Internal);
pin_3.connect_input_to_peripheral(InputSignal::CAM_DATA_3, crate::private::Internal);
pin_4.init_input(false, false, crate::private::Internal);
pin_4.init_input(Pull::None, crate::private::Internal);
pin_4.connect_input_to_peripheral(InputSignal::CAM_DATA_4, crate::private::Internal);
pin_5.init_input(false, false, crate::private::Internal);
pin_5.init_input(Pull::None, crate::private::Internal);
pin_5.connect_input_to_peripheral(InputSignal::CAM_DATA_5, crate::private::Internal);
pin_6.init_input(false, false, crate::private::Internal);
pin_6.init_input(Pull::None, crate::private::Internal);
pin_6.connect_input_to_peripheral(InputSignal::CAM_DATA_6, crate::private::Internal);
pin_7.init_input(false, false, crate::private::Internal);
pin_7.init_input(Pull::None, crate::private::Internal);
pin_7.connect_input_to_peripheral(InputSignal::CAM_DATA_7, crate::private::Internal);
pin_8.init_input(false, false, crate::private::Internal);
pin_8.init_input(Pull::None, crate::private::Internal);
pin_8.connect_input_to_peripheral(InputSignal::CAM_DATA_8, crate::private::Internal);
pin_9.init_input(false, false, crate::private::Internal);
pin_9.init_input(Pull::None, crate::private::Internal);
pin_9.connect_input_to_peripheral(InputSignal::CAM_DATA_9, crate::private::Internal);
pin_10.init_input(false, false, crate::private::Internal);
pin_10.init_input(Pull::None, crate::private::Internal);
pin_10.connect_input_to_peripheral(InputSignal::CAM_DATA_10, crate::private::Internal);
pin_11.init_input(false, false, crate::private::Internal);
pin_11.init_input(Pull::None, crate::private::Internal);
pin_11.connect_input_to_peripheral(InputSignal::CAM_DATA_11, crate::private::Internal);
pin_12.init_input(false, false, crate::private::Internal);
pin_12.init_input(Pull::None, crate::private::Internal);
pin_12.connect_input_to_peripheral(InputSignal::CAM_DATA_12, crate::private::Internal);
pin_13.init_input(false, false, crate::private::Internal);
pin_13.init_input(Pull::None, crate::private::Internal);
pin_13.connect_input_to_peripheral(InputSignal::CAM_DATA_13, crate::private::Internal);
pin_14.init_input(false, false, crate::private::Internal);
pin_14.init_input(Pull::None, crate::private::Internal);
pin_14.connect_input_to_peripheral(InputSignal::CAM_DATA_14, crate::private::Internal);
pin_15.init_input(false, false, crate::private::Internal);
pin_15.init_input(Pull::None, crate::private::Internal);
pin_15.connect_input_to_peripheral(InputSignal::CAM_DATA_15, crate::private::Internal);
Self { _pins: () }

View File

@ -76,7 +76,7 @@ use crate::{
ReadBuffer,
TxPrivate,
},
gpio::{OutputPin, OutputSignal},
gpio::{OutputSignal, PeripheralOutput},
lcd_cam::{
asynch::LcdDoneFuture,
lcd::{i8080::private::TxPins, ClockMode, DelayMode, Phase, Polarity},
@ -309,7 +309,7 @@ where
}
/// Associates a CS pin with the I8080 interface.
pub fn with_cs<CS: OutputPin>(self, cs: impl Peripheral<P = CS> + 'd) -> Self {
pub fn with_cs<CS: PeripheralOutput>(self, cs: impl Peripheral<P = CS> + 'd) -> Self {
crate::into_ref!(cs);
cs.set_to_push_pull_output(crate::private::Internal);
cs.connect_peripheral_to_output(OutputSignal::LCD_CS, crate::private::Internal);
@ -318,7 +318,7 @@ where
}
/// Configures the control pins for the I8080 interface.
pub fn with_ctrl_pins<DC: OutputPin, WRX: OutputPin>(
pub fn with_ctrl_pins<DC: PeripheralOutput, WRX: PeripheralOutput>(
self,
dc: impl Peripheral<P = DC> + 'd,
wrx: impl Peripheral<P = WRX> + 'd,
@ -593,14 +593,14 @@ pub struct TxEightBits<'d, P0, P1, P2, P3, P4, P5, P6, P7> {
impl<'d, P0, P1, P2, P3, P4, P5, P6, P7> TxEightBits<'d, P0, P1, P2, P3, P4, P5, P6, P7>
where
P0: OutputPin,
P1: OutputPin,
P2: OutputPin,
P3: OutputPin,
P4: OutputPin,
P5: OutputPin,
P6: OutputPin,
P7: OutputPin,
P0: PeripheralOutput,
P1: PeripheralOutput,
P2: PeripheralOutput,
P3: PeripheralOutput,
P4: PeripheralOutput,
P5: PeripheralOutput,
P6: PeripheralOutput,
P7: PeripheralOutput,
{
#[allow(clippy::too_many_arguments)]
/// Creates a new `TxEightBits` instance with the provided output pins.
@ -638,14 +638,14 @@ where
impl<'d, P0, P1, P2, P3, P4, P5, P6, P7> TxPins for TxEightBits<'d, P0, P1, P2, P3, P4, P5, P6, P7>
where
P0: OutputPin,
P1: OutputPin,
P2: OutputPin,
P3: OutputPin,
P4: OutputPin,
P5: OutputPin,
P6: OutputPin,
P7: OutputPin,
P0: PeripheralOutput,
P1: PeripheralOutput,
P2: PeripheralOutput,
P3: PeripheralOutput,
P4: PeripheralOutput,
P5: PeripheralOutput,
P6: PeripheralOutput,
P7: PeripheralOutput,
{
type Word = u8;
@ -701,22 +701,22 @@ pub struct TxSixteenBits<'d, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P
impl<'d, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15>
TxSixteenBits<'d, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15>
where
P0: OutputPin,
P1: OutputPin,
P2: OutputPin,
P3: OutputPin,
P4: OutputPin,
P5: OutputPin,
P6: OutputPin,
P7: OutputPin,
P8: OutputPin,
P9: OutputPin,
P10: OutputPin,
P11: OutputPin,
P12: OutputPin,
P13: OutputPin,
P14: OutputPin,
P15: OutputPin,
P0: PeripheralOutput,
P1: PeripheralOutput,
P2: PeripheralOutput,
P3: PeripheralOutput,
P4: PeripheralOutput,
P5: PeripheralOutput,
P6: PeripheralOutput,
P7: PeripheralOutput,
P8: PeripheralOutput,
P9: PeripheralOutput,
P10: PeripheralOutput,
P11: PeripheralOutput,
P12: PeripheralOutput,
P13: PeripheralOutput,
P14: PeripheralOutput,
P15: PeripheralOutput,
{
#[allow(clippy::too_many_arguments)]
/// Creates a new `TxSixteenBits` instance with the provided output pins.
@ -779,22 +779,22 @@ where
impl<'d, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15> TxPins
for TxSixteenBits<'d, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15>
where
P0: OutputPin,
P1: OutputPin,
P2: OutputPin,
P3: OutputPin,
P4: OutputPin,
P5: OutputPin,
P6: OutputPin,
P7: OutputPin,
P8: OutputPin,
P9: OutputPin,
P10: OutputPin,
P11: OutputPin,
P12: OutputPin,
P13: OutputPin,
P14: OutputPin,
P15: OutputPin,
P0: PeripheralOutput,
P1: PeripheralOutput,
P2: PeripheralOutput,
P3: PeripheralOutput,
P4: PeripheralOutput,
P5: PeripheralOutput,
P6: PeripheralOutput,
P7: PeripheralOutput,
P8: PeripheralOutput,
P9: PeripheralOutput,
P10: PeripheralOutput,
P11: PeripheralOutput,
P12: PeripheralOutput,
P13: PeripheralOutput,
P14: PeripheralOutput,
P15: PeripheralOutput,
{
type Word = u16;
fn configure(&mut self) {

View File

@ -11,7 +11,7 @@
use super::timer::{TimerIFace, TimerSpeed};
use crate::{
gpio::{OutputPin, OutputSignal},
gpio::{OutputSignal, PeripheralOutput},
peripheral::{Peripheral, PeripheralRef},
peripherals::ledc::RegisterBlock,
};
@ -95,7 +95,7 @@ pub mod config {
}
/// Channel interface
pub trait ChannelIFace<'a, S: TimerSpeed + 'a, O: OutputPin + 'a>
pub trait ChannelIFace<'a, S: TimerSpeed + 'a, O: PeripheralOutput + 'a>
where
Channel<'a, S, O>: ChannelHW<O>,
{
@ -118,7 +118,7 @@ where
}
/// Channel HW interface
pub trait ChannelHW<O: OutputPin> {
pub trait ChannelHW<O: PeripheralOutput> {
/// Configure Channel HW except for the duty which is set via
/// [`Self::set_duty_hw`].
fn configure_hw(&mut self) -> Result<(), Error>;
@ -144,14 +144,14 @@ pub trait ChannelHW<O: OutputPin> {
}
/// Channel struct
pub struct Channel<'a, S: TimerSpeed, O: OutputPin> {
pub struct Channel<'a, S: TimerSpeed, O: PeripheralOutput> {
ledc: &'a RegisterBlock,
timer: Option<&'a dyn TimerIFace<S>>,
number: Number,
output_pin: PeripheralRef<'a, O>,
}
impl<'a, S: TimerSpeed, O: OutputPin> Channel<'a, S, O> {
impl<'a, S: TimerSpeed, O: PeripheralOutput> Channel<'a, S, O> {
/// Return a new channel
pub fn new(number: Number, output_pin: impl Peripheral<P = O> + 'a) -> Self {
crate::into_ref!(output_pin);
@ -165,7 +165,7 @@ impl<'a, S: TimerSpeed, O: OutputPin> Channel<'a, S, O> {
}
}
impl<'a, S: TimerSpeed, O: OutputPin> ChannelIFace<'a, S, O> for Channel<'a, S, O>
impl<'a, S: TimerSpeed, O: PeripheralOutput> ChannelIFace<'a, S, O> for Channel<'a, S, O>
where
Channel<'a, S, O>: ChannelHW<O>,
{
@ -337,7 +337,7 @@ mod ehal1 {
}
}
impl<'a, O: OutputPin, S: crate::ledc::timer::TimerSpeed> Channel<'a, S, O> {
impl<'a, O: PeripheralOutput, S: crate::ledc::timer::TimerSpeed> Channel<'a, S, O> {
#[cfg(esp32)]
fn set_channel(&mut self, timer_number: u8) {
if S::IS_HS {
@ -537,7 +537,7 @@ impl<'a, O: OutputPin, S: crate::ledc::timer::TimerSpeed> Channel<'a, S, O> {
impl<'a, O, S> ChannelHW<O> for Channel<'a, S, O>
where
O: OutputPin,
O: PeripheralOutput,
S: crate::ledc::timer::TimerSpeed,
{
/// Configure Channel HW
@ -604,6 +604,7 @@ where
#[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))]
Number::Channel7 => OutputSignal::LEDC_LS_SIG7,
};
self.output_pin
.connect_peripheral_to_output(signal, crate::private::Internal);
} else {

View File

@ -12,7 +12,7 @@
use core::marker::PhantomData;
use crate::{
gpio::OutputPin,
gpio::PeripheralOutput,
mcpwm::{timer::Timer, PwmPeripheral},
peripheral::{Peripheral, PeripheralRef},
private,
@ -204,7 +204,7 @@ impl<const OP: u8, PWM: PwmPeripheral> Operator<OP, PWM> {
}
/// Use the A output with the given pin and configuration
pub fn with_pin_a<'d, Pin: OutputPin>(
pub fn with_pin_a<'d, Pin: PeripheralOutput>(
self,
pin: impl Peripheral<P = Pin> + 'd,
config: PwmPinConfig<true>,
@ -213,7 +213,7 @@ impl<const OP: u8, PWM: PwmPeripheral> Operator<OP, PWM> {
}
/// Use the B output with the given pin and configuration
pub fn with_pin_b<'d, Pin: OutputPin>(
pub fn with_pin_b<'d, Pin: PeripheralOutput>(
self,
pin: impl Peripheral<P = Pin> + 'd,
config: PwmPinConfig<false>,
@ -222,7 +222,7 @@ impl<const OP: u8, PWM: PwmPeripheral> Operator<OP, PWM> {
}
/// Use both the A and the B output with the given pins and configurations
pub fn with_pins<'d, PinA: OutputPin, PinB: OutputPin>(
pub fn with_pins<'d, PinA: PeripheralOutput, PinB: PeripheralOutput>(
self,
pin_a: impl Peripheral<P = PinA> + 'd,
config_a: PwmPinConfig<true>,
@ -239,7 +239,7 @@ impl<const OP: u8, PWM: PwmPeripheral> Operator<OP, PWM> {
///
/// This is useful for complementary or mirrored signals with or without
/// configured deadtime
pub fn with_linked_pins<'d, PinA: OutputPin, PinB: OutputPin>(
pub fn with_linked_pins<'d, PinA: PeripheralOutput, PinB: PeripheralOutput>(
self,
pin_a: impl Peripheral<P = PinA> + 'd,
config_a: PwmPinConfig<true>,
@ -288,7 +288,7 @@ pub struct PwmPin<'d, Pin, PWM, const OP: u8, const IS_A: bool> {
phantom: PhantomData<PWM>,
}
impl<'d, Pin: OutputPin, PWM: PwmPeripheral, const OP: u8, const IS_A: bool>
impl<'d, Pin: PeripheralOutput, PWM: PwmPeripheral, const OP: u8, const IS_A: bool>
PwmPin<'d, Pin, PWM, OP, IS_A>
{
fn new(pin: impl Peripheral<P = Pin> + 'd, config: PwmPinConfig<IS_A>) -> Self {
@ -304,6 +304,7 @@ impl<'d, Pin: OutputPin, PWM: PwmPeripheral, const OP: u8, const IS_A: bool>
pin.pin
.connect_peripheral_to_output(output_signal, private::Internal);
pin.pin.enable_output(true, private::Internal);
pin
}
@ -414,8 +415,8 @@ impl<'d, Pin: OutputPin, PWM: PwmPeripheral, const OP: u8, const IS_A: bool>
}
}
impl<'d, Pin: OutputPin, PWM: PwmPeripheral, const OP: u8, const IS_A: bool> embedded_hal_02::PwmPin
for PwmPin<'d, Pin, PWM, OP, IS_A>
impl<'d, Pin: PeripheralOutput, PWM: PwmPeripheral, const OP: u8, const IS_A: bool>
embedded_hal_02::PwmPin for PwmPin<'d, Pin, PWM, OP, IS_A>
{
type Duty = u16;
@ -448,14 +449,14 @@ impl<'d, Pin: OutputPin, PWM: PwmPeripheral, const OP: u8, const IS_A: bool> emb
}
/// Implement no error type for the PwmPin because the method are infallible
impl<'d, Pin: OutputPin, PWM: PwmPeripheral, const OP: u8, const IS_A: bool>
impl<'d, Pin: PeripheralOutput, PWM: PwmPeripheral, const OP: u8, const IS_A: bool>
embedded_hal::pwm::ErrorType for PwmPin<'d, Pin, PWM, OP, IS_A>
{
type Error = core::convert::Infallible;
}
/// Implement the trait SetDutyCycle for PwmPin
impl<'d, Pin: OutputPin, PWM: PwmPeripheral, const OP: u8, const IS_A: bool>
impl<'d, Pin: PeripheralOutput, PWM: PwmPeripheral, const OP: u8, const IS_A: bool>
embedded_hal::pwm::SetDutyCycle for PwmPin<'d, Pin, PWM, OP, IS_A>
{
/// Get the max duty of the PwmPin
@ -522,7 +523,7 @@ pub struct LinkedPins<'d, PinA, PinB, PWM, const OP: u8> {
pin_b: PwmPin<'d, PinB, PWM, OP, false>,
}
impl<'d, PinA: OutputPin, PinB: OutputPin, PWM: PwmPeripheral, const OP: u8>
impl<'d, PinA: PeripheralOutput, PinB: PeripheralOutput, PWM: PwmPeripheral, const OP: u8>
LinkedPins<'d, PinA, PinB, PWM, OP>
{
fn new(

View File

@ -43,6 +43,7 @@ use crate::{
gpio::InputSignal,
peripheral::{Peripheral, PeripheralRef},
peripherals,
private::Internal,
system::{Peripheral as PeripheralEnable, PeripheralClockControl},
};
@ -101,10 +102,12 @@ impl<'d> Usb<'d> {
.modify(|_, w| w.sw_hw_usb_phy_sel().set_bit().sw_usb_phy_sel().set_bit());
}
crate::gpio::connect_high_to_peripheral(InputSignal::USB_OTG_IDDIG); // connected connector is mini-B side
crate::gpio::connect_high_to_peripheral(InputSignal::USB_SRP_BVALID); // HIGH to force USB device mode
crate::gpio::connect_high_to_peripheral(InputSignal::USB_OTG_VBUSVALID); // receiving a valid Vbus from device
crate::gpio::connect_low_to_peripheral(InputSignal::USB_OTG_AVALID);
use crate::gpio::{Level, PeripheralInput};
Level::High.connect_input_to_peripheral(InputSignal::USB_OTG_IDDIG, Internal); // connected connector is mini-B side
Level::High.connect_input_to_peripheral(InputSignal::USB_SRP_BVALID, Internal); // HIGH to force USB device mode
Level::High.connect_input_to_peripheral(InputSignal::USB_OTG_VBUSVALID, Internal); // receiving a valid Vbus from device
Level::Low.connect_input_to_peripheral(InputSignal::USB_OTG_AVALID, Internal);
}
}

View File

@ -49,7 +49,7 @@ use crate::{
TxPrivate,
WriteBuffer,
},
gpio::{InputPin, OutputPin},
gpio::{PeripheralInput, PeripheralOutput},
interrupt::InterruptHandler,
peripheral::{self, Peripheral},
peripherals,
@ -279,13 +279,13 @@ pub fn no_clk_pin() -> &'static mut NoClkPin {
/// Wraps a GPIO pin which will be used as the clock output signal
pub struct ClkOutPin<'d, P>
where
P: OutputPin,
P: PeripheralOutput,
{
pin: PeripheralRef<'d, P>,
}
impl<'d, P> ClkOutPin<'d, P>
where
P: OutputPin,
P: PeripheralOutput,
{
/// Create a ClkOutPin
pub fn new(pin: impl Peripheral<P = P> + 'd) -> Self {
@ -295,7 +295,7 @@ where
}
impl<'d, P> TxClkPin for ClkOutPin<'d, P>
where
P: OutputPin,
P: PeripheralOutput,
{
fn configure(&mut self) {
self.pin.set_to_push_pull_output(crate::private::Internal);
@ -309,13 +309,13 @@ where
/// Wraps a GPIO pin which will be used as the TX clock input signal
pub struct ClkInPin<'d, P>
where
P: InputPin,
P: PeripheralInput,
{
pin: PeripheralRef<'d, P>,
}
impl<'d, P> ClkInPin<'d, P>
where
P: InputPin,
P: PeripheralInput,
{
/// Create a new ClkInPin
pub fn new(pin: impl Peripheral<P = P> + 'd) -> Self {
@ -325,14 +325,15 @@ where
}
impl<'d, P> TxClkPin for ClkInPin<'d, P>
where
P: InputPin,
P: PeripheralInput,
{
fn configure(&mut self) {
let pcr = unsafe { &*crate::peripherals::PCR::PTR };
pcr.parl_clk_tx_conf()
.modify(|_, w| unsafe { w.parl_clk_tx_sel().bits(3).parl_clk_tx_div_num().bits(0) }); // PAD_CLK_TX, no divider
self.pin.init_input(false, false, crate::private::Internal);
self.pin
.init_input(crate::gpio::Pull::None, crate::private::Internal);
self.pin.connect_input_to_peripheral(
crate::gpio::InputSignal::PARL_TX_CLK,
crate::private::Internal,
@ -343,14 +344,14 @@ where
/// Wraps a GPIO pin which will be used as the RX clock input signal
pub struct RxClkInPin<'d, P>
where
P: InputPin,
P: PeripheralInput,
{
pin: PeripheralRef<'d, P>,
sample_edge: SampleEdge,
}
impl<'d, P> RxClkInPin<'d, P>
where
P: InputPin,
P: PeripheralInput,
{
/// Create a new RxClkInPin
pub fn new(pin: impl Peripheral<P = P> + 'd, sample_edge: SampleEdge) -> Self {
@ -360,14 +361,15 @@ where
}
impl<'d, P> RxClkPin for RxClkInPin<'d, P>
where
P: InputPin,
P: PeripheralInput,
{
fn configure(&mut self) {
let pcr = unsafe { &*crate::peripherals::PCR::PTR };
pcr.parl_clk_rx_conf()
.modify(|_, w| unsafe { w.parl_clk_rx_sel().bits(3).parl_clk_rx_div_num().bits(0) }); // PAD_CLK_TX, no divider
self.pin.init_input(false, false, crate::private::Internal);
self.pin
.init_input(crate::gpio::Pull::None, crate::private::Internal);
self.pin.connect_input_to_peripheral(
crate::gpio::InputSignal::PARL_RX_CLK,
crate::private::Internal,
@ -381,7 +383,7 @@ where
pub struct TxPinConfigWithValidPin<'d, P, VP>
where
P: NotContainsValidSignalPin + TxPins + ConfigurePins,
VP: OutputPin,
VP: PeripheralOutput,
{
tx_pins: P,
valid_pin: PeripheralRef<'d, VP>,
@ -390,7 +392,7 @@ where
impl<'d, P, VP> TxPinConfigWithValidPin<'d, P, VP>
where
P: NotContainsValidSignalPin + TxPins + ConfigurePins,
VP: OutputPin,
VP: PeripheralOutput,
{
/// Create a [TxPinConfigWithValidPin]
pub fn new(tx_pins: P, valid_pin: impl Peripheral<P = VP> + 'd) -> Self {
@ -402,14 +404,14 @@ where
impl<'d, P, VP> TxPins for TxPinConfigWithValidPin<'d, P, VP>
where
P: NotContainsValidSignalPin + TxPins + ConfigurePins,
VP: OutputPin,
VP: PeripheralOutput,
{
}
impl<'d, P, VP> ConfigurePins for TxPinConfigWithValidPin<'d, P, VP>
where
P: NotContainsValidSignalPin + TxPins + ConfigurePins,
VP: OutputPin,
VP: PeripheralOutput,
{
fn configure(&mut self) -> Result<(), Error> {
self.tx_pins.configure()?;
@ -472,7 +474,7 @@ macro_rules! tx_pins {
impl<'d, $($pin),+> $name<'d, $($pin),+>
where
$($pin: OutputPin),+
$($pin: PeripheralOutput),+
{
/// Create a new TX pin
#[allow(clippy::too_many_arguments)]
@ -488,7 +490,7 @@ macro_rules! tx_pins {
impl<'d, $($pin),+> ConfigurePins for $name<'d, $($pin),+>
where
$($pin: OutputPin),+
$($pin: PeripheralOutput),+
{
fn configure(&mut self) -> Result<(), Error>{
$(
@ -590,7 +592,7 @@ impl<'d, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15>
pub struct RxPinConfigWithValidPin<'d, P, VP>
where
P: NotContainsValidSignalPin + RxPins + ConfigurePins,
VP: InputPin,
VP: PeripheralInput,
{
rx_pins: P,
valid_pin: PeripheralRef<'d, VP>,
@ -601,7 +603,7 @@ where
impl<'d, P, VP> RxPinConfigWithValidPin<'d, P, VP>
where
P: NotContainsValidSignalPin + RxPins + ConfigurePins,
VP: InputPin,
VP: PeripheralInput,
{
/// Create a new [RxPinConfigWithValidPin]
pub fn new(
@ -623,19 +625,19 @@ where
impl<'d, P, VP> RxPins for RxPinConfigWithValidPin<'d, P, VP>
where
P: NotContainsValidSignalPin + RxPins + ConfigurePins,
VP: InputPin,
VP: PeripheralInput,
{
}
impl<'d, P, VP> ConfigurePins for RxPinConfigWithValidPin<'d, P, VP>
where
P: NotContainsValidSignalPin + RxPins + ConfigurePins,
VP: InputPin,
VP: PeripheralInput,
{
fn configure(&mut self) -> Result<(), Error> {
self.rx_pins.configure()?;
self.valid_pin
.init_input(false, false, crate::private::Internal);
.init_input(crate::gpio::Pull::None, crate::private::Internal);
self.valid_pin
.connect_input_to_peripheral(Instance::rx_valid_pin_signal(), crate::private::Internal);
Instance::set_rx_sw_en(false);
@ -719,7 +721,7 @@ macro_rules! rx_pins {
impl<'d, $($pin),+> $name<'d, $($pin),+>
where
$($pin: InputPin),+
$($pin: PeripheralInput),+
{
/// Create a new RX pin
#[allow(clippy::too_many_arguments)]
@ -735,12 +737,12 @@ macro_rules! rx_pins {
impl<'d, $($pin),+> ConfigurePins for $name<'d, $($pin),+>
where
$($pin: InputPin),+
$($pin: PeripheralInput),+
{
fn configure(&mut self) -> Result<(), Error> {
$(
self.[< pin_ $pin:lower >].init_input(false, false, $crate::private::Internal);
self.[< pin_ $pin:lower >].connect_input_to_peripheral(crate::gpio::InputSignal::$signal, $crate::private::Internal);
self.[< pin_ $pin:lower >].init_input(crate::gpio::Pull::None, crate::private::Internal);
self.[< pin_ $pin:lower >].connect_input_to_peripheral(crate::gpio::InputSignal::$signal, crate::private::Internal);
)+
private::Instance::set_rx_bit_width( private::WidSel::[< Bits $width >]);

View File

@ -9,11 +9,7 @@
use core::marker::PhantomData;
use crate::{
gpio::{InputPin, InputSignal, Pull, ONE_INPUT, ZERO_INPUT},
peripheral::Peripheral,
peripherals::GPIO,
};
use crate::gpio::{interconnect::AnyInputSignal, InputSignal, PeripheralInput, Pull};
/// Configuration for an PCNT input pin
#[derive(Clone, Copy, Debug)]
@ -32,55 +28,19 @@ impl Default for PcntInputConfig {
pub use crate::peripherals::pcnt::unit::conf0::{CTRL_MODE as CtrlMode, EDGE_MODE as EdgeMode};
/// PcntPin can be always high, always low, or an actual pin
#[derive(Clone, Copy)]
#[derive(Clone)]
pub struct PcntSource {
source: u8,
inverted: bool,
source: AnyInputSignal,
}
impl PcntSource {
/// Creates a `PcntSource` from an input pin with the specified
/// configuration.
pub fn from_pin<'a, P: InputPin>(
pin: impl Peripheral<P = P> + 'a,
pin_config: PcntInputConfig,
) -> Self {
crate::into_ref!(pin);
pub fn from(source: impl Into<AnyInputSignal>, pin_config: PcntInputConfig) -> Self {
let source = source.into();
source.init_input(pin_config.pull, crate::private::Internal);
pin.init_input(
pin_config.pull == Pull::Down,
pin_config.pull == Pull::Up,
crate::private::Internal,
);
Self {
source: pin.number(crate::private::Internal),
inverted: false,
}
}
/// Creates a `PcntSource` that is always high.
pub fn always_high() -> Self {
Self {
source: ONE_INPUT,
inverted: false,
}
}
/// Creates a `PcntSource` that is always low.
pub fn always_low() -> Self {
Self {
source: ZERO_INPUT,
inverted: false,
}
}
/// Inverts the `PcntSource` signal.
pub fn invert(self) -> Self {
Self {
source: self.source,
inverted: !self.inverted,
}
Self { source }
}
}
@ -135,7 +95,7 @@ impl<'d, const UNIT: usize, const NUM: usize> Channel<'d, UNIT, NUM> {
}
/// Set the control signal (pin/high/low) for this channel
pub fn set_ctrl_signal(&self, source: PcntSource) -> &Self {
pub fn set_ctrl_signal(&self, mut source: PcntSource) -> &Self {
let signal = match UNIT {
0 => match NUM {
0 => InputSignal::PCNT0_CTRL_CH0,
@ -185,19 +145,15 @@ impl<'d, const UNIT: usize, const NUM: usize> Channel<'d, UNIT, NUM> {
};
if (signal as usize) <= crate::gpio::INPUT_SIGNAL_MAX as usize {
unsafe { &*GPIO::PTR }
.func_in_sel_cfg(signal as usize)
.modify(|_, w| unsafe {
w.sel().set_bit();
w.in_inv_sel().bit(source.inverted);
w.in_sel().bits(source.source)
});
source
.source
.connect_input_to_peripheral(signal, crate::private::Internal);
}
self
}
/// Set the edge signal (pin/high/low) for this channel
pub fn set_edge_signal(&self, source: PcntSource) -> &Self {
pub fn set_edge_signal(&self, mut source: PcntSource) -> &Self {
let signal = match UNIT {
0 => match NUM {
0 => InputSignal::PCNT0_SIG_CH0,
@ -247,13 +203,9 @@ impl<'d, const UNIT: usize, const NUM: usize> Channel<'d, UNIT, NUM> {
};
if (signal as usize) <= crate::gpio::INPUT_SIGNAL_MAX as usize {
unsafe { &*GPIO::PTR }
.func_in_sel_cfg(signal as usize)
.modify(|_, w| unsafe {
w.sel().set_bit();
w.in_inv_sel().bit(source.inverted);
w.in_sel().bits(source.source)
});
source
.source
.connect_input_to_peripheral(signal, crate::private::Internal);
}
self
}

View File

@ -35,10 +35,10 @@ use core::{
/// dedicated struct is memory efficiency:
///
/// Peripheral singletons are typically either zero-sized (for concrete
/// peripherals like `PA9` or `Spi4`) or very small (for example `AnyPin` which
/// is 1 byte). However `&mut T` is always 4 bytes for 32-bit targets, even if T
/// is zero-sized. PeripheralRef stores a copy of `T` instead, so it's the same
/// size.
/// peripherals like `PA9` or `Spi4`) or very small (for example `AnyPin`
/// which is 1 byte). However `&mut T` is always 4 bytes for 32-bit targets,
/// even if T is zero-sized. PeripheralRef stores a copy of `T` instead, so it's
/// the same size.
///
/// but it is the size of `T` not the size
/// of a pointer. This is useful if T is a zero sized type.

View File

@ -85,7 +85,7 @@ use core::marker::PhantomData;
use fugit::HertzU32;
use crate::{
gpio::{InputPin, OutputPin},
gpio::{PeripheralInput, PeripheralOutput},
interrupt::InterruptHandler,
peripheral::Peripheral,
rmt::private::CreateInstance,
@ -295,10 +295,77 @@ impl<'d> Rmt<'d, crate::Async> {
}
}
fn configure_rx_channel<
'd,
P: PeripheralInput,
T: private::RxChannelInternal<M>,
M: crate::Mode,
>(
pin: impl Peripheral<P = P> + 'd,
config: RxChannelConfig,
) -> Result<T, Error> {
if config.filter_threshold > 0b111_1111 {
return Err(Error::InvalidArgument);
}
cfg_if::cfg_if! {
if #[cfg(any(esp32, esp32s2))] {
let threshold = 0b111_1111_1111_1111;
} else {
let threshold = 0b11_1111_1111_1111;
}
}
if config.idle_threshold > threshold {
return Err(Error::InvalidArgument);
}
crate::into_ref!(pin);
pin.init_input(crate::gpio::Pull::None, crate::private::Internal);
pin.connect_input_to_peripheral(T::input_signal(), crate::private::Internal);
T::set_divider(config.clk_divider);
T::set_carrier(
config.carrier_modulation,
config.carrier_high,
config.carrier_low,
config.carrier_level,
);
T::set_filter_threshold(config.filter_threshold);
T::set_idle_threshold(config.idle_threshold);
Ok(T::new())
}
fn configure_tx_channel<
'd,
P: PeripheralOutput,
T: private::TxChannelInternal<M>,
M: crate::Mode,
>(
pin: impl Peripheral<P = P> + 'd,
config: TxChannelConfig,
) -> Result<T, Error> {
crate::into_ref!(pin);
pin.set_to_push_pull_output(crate::private::Internal);
pin.connect_peripheral_to_output(T::output_signal(), crate::private::Internal);
T::set_divider(config.clk_divider);
T::set_carrier(
config.carrier_modulation,
config.carrier_high,
config.carrier_low,
config.carrier_level,
);
T::set_idle_output(config.idle_output, config.idle_output_level);
Ok(T::new())
}
/// Creates a TX channel
pub trait TxChannelCreator<'d, T, P>
where
P: OutputPin,
P: PeripheralOutput,
T: TxChannel,
{
/// Configure the TX channel
@ -310,26 +377,14 @@ where
where
Self: Sized,
{
crate::into_ref!(pin);
pin.set_to_push_pull_output(crate::private::Internal);
pin.connect_peripheral_to_output(T::output_signal(), crate::private::Internal);
T::set_divider(config.clk_divider);
T::set_carrier(
config.carrier_modulation,
config.carrier_high,
config.carrier_low,
config.carrier_level,
);
T::set_idle_output(config.idle_output, config.idle_output_level);
Ok(T::new())
configure_tx_channel(pin, config)
}
}
/// Creates a TX channel in async mode
pub trait TxChannelCreatorAsync<'d, T, P>
where
P: OutputPin,
P: PeripheralOutput,
T: TxChannelAsync,
{
/// Configure the TX channel
@ -341,26 +396,14 @@ where
where
Self: Sized,
{
crate::into_ref!(pin);
pin.set_to_push_pull_output(crate::private::Internal);
pin.connect_peripheral_to_output(T::output_signal(), crate::private::Internal);
T::set_divider(config.clk_divider);
T::set_carrier(
config.carrier_modulation,
config.carrier_high,
config.carrier_low,
config.carrier_level,
);
T::set_idle_output(config.idle_output, config.idle_output_level);
Ok(T::new())
configure_tx_channel(pin, config)
}
}
/// Creates a RX channel
pub trait RxChannelCreator<'d, T, P>
where
P: InputPin,
P: PeripheralInput,
T: RxChannel,
{
/// Configure the RX channel
@ -372,41 +415,14 @@ where
where
Self: Sized,
{
if config.filter_threshold > 0b111_1111 {
return Err(Error::InvalidArgument);
}
#[cfg(any(esp32, esp32s2))]
if config.idle_threshold > 0b111_1111_1111_1111 {
return Err(Error::InvalidArgument);
}
#[cfg(not(any(esp32, esp32s2)))]
if config.idle_threshold > 0b11_1111_1111_1111 {
return Err(Error::InvalidArgument);
}
crate::into_ref!(pin);
pin.init_input(false, false, crate::private::Internal);
pin.connect_input_to_peripheral(T::input_signal(), crate::private::Internal);
T::set_divider(config.clk_divider);
T::set_carrier(
config.carrier_modulation,
config.carrier_high,
config.carrier_low,
config.carrier_level,
);
T::set_filter_threshold(config.filter_threshold);
T::set_idle_threshold(config.idle_threshold);
Ok(T::new())
configure_rx_channel(pin, config)
}
}
/// Creates a RX channel in async mode
pub trait RxChannelCreatorAsync<'d, T, P>
where
P: InputPin,
P: PeripheralInput,
T: RxChannelAsync,
{
/// Configure the RX channel
@ -418,34 +434,7 @@ where
where
Self: Sized,
{
if config.filter_threshold > 0b111_1111 {
return Err(Error::InvalidArgument);
}
#[cfg(any(esp32, esp32s2))]
if config.idle_threshold > 0b111_1111_1111_1111 {
return Err(Error::InvalidArgument);
}
#[cfg(not(any(esp32, esp32s2)))]
if config.idle_threshold > 0b11_1111_1111_1111 {
return Err(Error::InvalidArgument);
}
crate::into_ref!(pin);
pin.init_input(false, false, crate::private::Internal);
pin.connect_input_to_peripheral(T::input_signal(), crate::private::Internal);
T::set_divider(config.clk_divider);
T::set_carrier(
config.carrier_modulation,
config.carrier_high,
config.carrier_low,
config.carrier_level,
);
T::set_filter_threshold(config.filter_threshold);
T::set_idle_threshold(config.idle_threshold);
Ok(T::new())
configure_rx_channel(pin, config)
}
}
@ -586,7 +575,7 @@ macro_rules! impl_tx_channel_creator {
impl<'d, P> $crate::rmt::TxChannelCreator<'d, $crate::rmt::Channel<$crate::Blocking, $channel>, P>
for ChannelCreator<$crate::Blocking, $channel>
where
P: $crate::gpio::OutputPin,
P: $crate::gpio::PeripheralOutput,
{
}
@ -595,7 +584,7 @@ macro_rules! impl_tx_channel_creator {
impl<'d, P> $crate::rmt::TxChannelCreatorAsync<'d, $crate::rmt::Channel<$crate::Async, $channel>, P>
for ChannelCreator<$crate::Async, $channel>
where
P: $crate::gpio::OutputPin,
P: $crate::gpio::PeripheralOutput,
{
}
@ -608,7 +597,7 @@ macro_rules! impl_rx_channel_creator {
impl<'d, P> $crate::rmt::RxChannelCreator<'d, $crate::rmt::Channel<$crate::Blocking, $channel>, P>
for ChannelCreator<$crate::Blocking, $channel>
where
P: $crate::gpio::InputPin,
P: $crate::gpio::PeripheralInput,
{
}
@ -617,7 +606,7 @@ macro_rules! impl_rx_channel_creator {
impl<'d, P> $crate::rmt::RxChannelCreatorAsync<'d, $crate::rmt::Channel<$crate::Async, $channel>, P>
for ChannelCreator<$crate::Async, $channel>
where
P: $crate::gpio::InputPin,
P: $crate::gpio::PeripheralInput,
{
}

View File

@ -82,7 +82,7 @@ use super::{
use crate::{
clock::Clocks,
dma::{DmaPeripheral, DmaRxBuffer, DmaTxBuffer, Rx, Tx},
gpio::{InputPin, InputSignal, OutputPin, OutputSignal},
gpio::{InputSignal, OutputSignal, PeripheralInput, PeripheralOutput},
interrupt::InterruptHandler,
peripheral::{Peripheral, PeripheralRef},
peripherals::spi2::RegisterBlock,
@ -457,6 +457,35 @@ pub struct Spi<'d, T, M> {
_mode: PhantomData<M>,
}
impl<'d, T, M> Spi<'d, T, M>
where
T: Instance,
{
/// Assign the SCK (Serial Clock) pin for the SPI instance.
///
/// Sets the specified pin to push-pull output and connects it to the SPI
/// clock signal.
pub fn with_sck<SCK: PeripheralOutput>(self, sclk: impl Peripheral<P = SCK> + 'd) -> Self {
crate::into_ref!(sclk);
sclk.set_to_push_pull_output(private::Internal);
sclk.connect_peripheral_to_output(self.spi.sclk_signal(), private::Internal);
self
}
/// Assign the CS (Chip Select) pin for the SPI instance.
///
/// Sets the specified pin to push-pull output and connects it to the SPI CS
/// signal.
pub fn with_cs<CS: PeripheralOutput>(self, cs: impl Peripheral<P = CS> + 'd) -> Self {
crate::into_ref!(cs);
cs.set_to_push_pull_output(private::Internal);
cs.connect_peripheral_to_output(self.spi.cs_signal(), private::Internal);
self
}
}
impl<'d, T> Spi<'d, T, FullDuplexMode>
where
T: Instance,
@ -513,23 +542,11 @@ where
Self::new_internal(spi, frequency, mode)
}
/// Assign the SCK (Serial Clock) pin for the SPI instance.
///
/// Sets the specified pin to push-pull output and connects it to the SPI
/// clock signal.
pub fn with_sck<SCK: OutputPin>(self, sck: impl Peripheral<P = SCK> + 'd) -> Self {
crate::into_ref!(sck);
sck.set_to_push_pull_output(private::Internal);
sck.connect_peripheral_to_output(self.spi.sclk_signal(), private::Internal);
self
}
/// Assign the MOSI (Master Out Slave In) pin for the SPI instance.
///
/// Sets the specified pin to push-pull output and connects it to the SPI
/// MOSI signal.
pub fn with_mosi<MOSI: OutputPin>(self, mosi: impl Peripheral<P = MOSI> + 'd) -> Self {
pub fn with_mosi<MOSI: PeripheralOutput>(self, mosi: impl Peripheral<P = MOSI> + 'd) -> Self {
crate::into_ref!(mosi);
mosi.set_to_push_pull_output(private::Internal);
mosi.connect_peripheral_to_output(self.spi.mosi_signal(), private::Internal);
@ -540,26 +557,14 @@ where
/// Assign the MISO (Master In Slave Out) pin for the SPI instance.
///
/// Sets the specified pin to input and connects it to the SPI MISO signal.
pub fn with_miso<MISO: InputPin>(self, miso: impl Peripheral<P = MISO> + 'd) -> Self {
pub fn with_miso<MISO: PeripheralInput>(self, miso: impl Peripheral<P = MISO> + 'd) -> Self {
crate::into_ref!(miso);
miso.init_input(false, false, private::Internal);
miso.init_input(crate::gpio::Pull::None, private::Internal);
miso.connect_input_to_peripheral(self.spi.miso_signal(), private::Internal);
self
}
/// Assign the CS (Chip Select) pin for the SPI instance.
///
/// Sets the specified pin to push-pull output and connects it to the SPI CS
/// signal.
pub fn with_cs<CS: OutputPin>(self, cs: impl Peripheral<P = CS> + 'd) -> Self {
crate::into_ref!(cs);
cs.set_to_push_pull_output(private::Internal);
cs.connect_peripheral_to_output(self.spi.cs_signal(), private::Internal);
self
}
/// Set the bit order for the SPI instance.
///
/// The default is MSB first for both read and write.
@ -572,38 +577,43 @@ where
///
/// All pins are optional. Pass [crate::gpio::NO_PIN] if you don't need the
/// given pin.
pub fn with_pins<SCK: OutputPin, MOSI: OutputPin, MISO: InputPin, CS: OutputPin>(
pub fn with_pins<
SCK: PeripheralOutput,
MOSI: PeripheralOutput,
MISO: PeripheralInput,
CS: PeripheralOutput,
>(
self,
sck: Option<impl Peripheral<P = SCK> + 'd>,
mosi: Option<impl Peripheral<P = MOSI> + 'd>,
miso: Option<impl Peripheral<P = MISO> + 'd>,
cs: Option<impl Peripheral<P = CS> + 'd>,
) -> Self {
if let Some(sck) = sck {
crate::into_ref!(sck);
sck.set_to_push_pull_output(private::Internal);
sck.connect_peripheral_to_output(self.spi.sclk_signal(), private::Internal);
}
let this = if let Some(sck) = sck {
self.with_sck(sck)
} else {
self
};
if let Some(mosi) = mosi {
crate::into_ref!(mosi);
mosi.set_to_push_pull_output(private::Internal);
mosi.connect_peripheral_to_output(self.spi.mosi_signal(), private::Internal);
}
let this = if let Some(mosi) = mosi {
this.with_mosi(mosi)
} else {
this
};
if let Some(miso) = miso {
crate::into_ref!(miso);
miso.init_input(false, false, private::Internal);
miso.connect_input_to_peripheral(self.spi.miso_signal(), private::Internal);
}
let this = if let Some(miso) = miso {
this.with_miso(miso)
} else {
this
};
if let Some(cs) = cs {
crate::into_ref!(cs);
cs.set_to_push_pull_output(private::Internal);
cs.connect_peripheral_to_output(self.spi.cs_signal(), private::Internal);
}
let this = if let Some(cs) = cs {
this.with_cs(cs)
} else {
this
};
self
this
}
pub(crate) fn new_internal(
@ -651,32 +661,21 @@ where
Self::new_internal(spi, frequency, mode)
}
/// Assign the SCK (Serial Clock) pin for the SPI instance.
///
/// Sets the specified pin to push-pull output and connects it to the SPI
/// clock signal.
pub fn with_sck<SCK: OutputPin>(self, sck: impl Peripheral<P = SCK> + 'd) -> Self {
crate::into_ref!(sck);
sck.set_to_push_pull_output(private::Internal);
sck.connect_peripheral_to_output(self.spi.sclk_signal(), private::Internal);
self
}
/// Assign the MOSI (Master Out Slave In) pin for the SPI instance in
/// half-duplex mode.
///
/// Enables both input and output functionality for the pin, and connects it
/// to the MOSI signal and SIO0 input signal.
pub fn with_mosi<MOSI: OutputPin + InputPin>(
pub fn with_mosi<MOSI: PeripheralOutput + PeripheralInput>(
self,
mosi: impl Peripheral<P = MOSI> + 'd,
) -> Self {
crate::into_ref!(mosi);
mosi.enable_output(true, private::Internal);
mosi.connect_peripheral_to_output(self.spi.mosi_signal(), private::Internal);
mosi.enable_input(true, private::Internal);
mosi.enable_output(true, private::Internal);
mosi.connect_input_to_peripheral(self.spi.sio0_input_signal(), private::Internal);
mosi.connect_peripheral_to_output(self.spi.mosi_signal(), private::Internal);
self
}
@ -686,15 +685,16 @@ where
///
/// Enables both input and output functionality for the pin, and connects it
/// to the MISO signal and SIO1 input signal.
pub fn with_miso<MISO: OutputPin + InputPin>(
pub fn with_miso<MISO: PeripheralOutput + PeripheralInput>(
self,
miso: impl Peripheral<P = MISO> + 'd,
) -> Self {
crate::into_ref!(miso);
miso.enable_output(true, private::Internal);
miso.connect_peripheral_to_output(self.spi.sio1_output_signal(), private::Internal);
miso.enable_input(true, private::Internal);
miso.enable_output(true, private::Internal);
miso.connect_input_to_peripheral(self.spi.miso_signal(), private::Internal);
miso.connect_peripheral_to_output(self.spi.sio1_output_signal(), private::Internal);
self
}
@ -703,15 +703,16 @@ where
///
/// Enables both input and output functionality for the pin, and connects it
/// to the SIO2 output and input signals.
pub fn with_sio2<SIO2: OutputPin + InputPin>(
pub fn with_sio2<SIO2: PeripheralOutput + PeripheralInput>(
self,
sio2: impl Peripheral<P = SIO2> + 'd,
) -> Self {
crate::into_ref!(sio2);
sio2.enable_output(true, private::Internal);
sio2.connect_peripheral_to_output(self.spi.sio2_output_signal(), private::Internal);
sio2.enable_input(true, private::Internal);
sio2.enable_output(true, private::Internal);
sio2.connect_input_to_peripheral(self.spi.sio2_input_signal(), private::Internal);
sio2.connect_peripheral_to_output(self.spi.sio2_output_signal(), private::Internal);
self
}
@ -720,27 +721,16 @@ where
///
/// Enables both input and output functionality for the pin, and connects it
/// to the SIO3 output and input signals.
pub fn with_sio3<SIO3: OutputPin + InputPin>(
pub fn with_sio3<SIO3: PeripheralOutput + PeripheralInput>(
self,
sio3: impl Peripheral<P = SIO3> + 'd,
) -> Self {
crate::into_ref!(sio3);
sio3.enable_output(true, private::Internal);
sio3.connect_peripheral_to_output(self.spi.sio3_output_signal(), private::Internal);
sio3.enable_input(true, private::Internal);
sio3.enable_output(true, private::Internal);
sio3.connect_input_to_peripheral(self.spi.sio3_input_signal(), private::Internal);
self
}
/// Assign the CS (Chip Select) pin for the SPI instance.
///
/// Sets the specified pin to push-pull output and connects it to the SPI CS
/// signal.
pub fn with_cs<CS: OutputPin>(self, cs: impl Peripheral<P = CS> + 'd) -> Self {
crate::into_ref!(cs);
cs.set_to_push_pull_output(private::Internal);
cs.connect_peripheral_to_output(self.spi.cs_signal(), private::Internal);
sio3.connect_peripheral_to_output(self.spi.sio3_output_signal(), private::Internal);
self
}
@ -750,12 +740,12 @@ where
/// All pins are optional. Pass [crate::gpio::NO_PIN] if you don't need the
/// given pin.
pub fn with_pins<
SCK: OutputPin,
MOSI: OutputPin + InputPin,
MISO: OutputPin + InputPin,
SIO2: OutputPin + InputPin,
SIO3: OutputPin + InputPin,
CS: OutputPin,
SCK: PeripheralOutput,
MOSI: PeripheralOutput + PeripheralInput,
MISO: PeripheralOutput + PeripheralInput,
SIO2: PeripheralOutput + PeripheralInput,
SIO3: PeripheralOutput + PeripheralInput,
CS: PeripheralOutput,
>(
self,
sck: Option<impl Peripheral<P = SCK> + 'd>,
@ -765,51 +755,43 @@ where
sio3: Option<impl Peripheral<P = SIO3> + 'd>,
cs: Option<impl Peripheral<P = CS> + 'd>,
) -> Self {
if let Some(sck) = sck {
crate::into_ref!(sck);
sck.set_to_push_pull_output(private::Internal);
sck.connect_peripheral_to_output(self.spi.sclk_signal(), private::Internal);
}
let this = if let Some(sck) = sck {
self.with_sck(sck)
} else {
self
};
if let Some(mosi) = mosi {
crate::into_ref!(mosi);
mosi.enable_output(true, private::Internal);
mosi.connect_peripheral_to_output(self.spi.mosi_signal(), private::Internal);
mosi.enable_input(true, private::Internal);
mosi.connect_input_to_peripheral(self.spi.sio0_input_signal(), private::Internal);
}
let this = if let Some(mosi) = mosi {
this.with_mosi(mosi)
} else {
this
};
if let Some(miso) = miso {
crate::into_ref!(miso);
miso.enable_output(true, private::Internal);
miso.connect_peripheral_to_output(self.spi.sio1_output_signal(), private::Internal);
miso.enable_input(true, private::Internal);
miso.connect_input_to_peripheral(self.spi.miso_signal(), private::Internal);
}
let this = if let Some(miso) = miso {
this.with_miso(miso)
} else {
this
};
if let Some(sio2) = sio2 {
crate::into_ref!(sio2);
sio2.enable_output(true, private::Internal);
sio2.connect_peripheral_to_output(self.spi.sio2_output_signal(), private::Internal);
sio2.enable_input(true, private::Internal);
sio2.connect_input_to_peripheral(self.spi.sio2_input_signal(), private::Internal);
}
let this = if let Some(sio2) = sio2 {
this.with_sio2(sio2)
} else {
this
};
if let Some(sio3) = sio3 {
crate::into_ref!(sio3);
sio3.enable_output(true, private::Internal);
sio3.connect_peripheral_to_output(self.spi.sio3_output_signal(), private::Internal);
sio3.enable_input(true, private::Internal);
sio3.connect_input_to_peripheral(self.spi.sio3_input_signal(), private::Internal);
}
let this = if let Some(sio3) = sio3 {
this.with_sio3(sio3)
} else {
this
};
if let Some(cs) = cs {
crate::into_ref!(cs);
cs.set_to_push_pull_output(private::Internal);
cs.connect_peripheral_to_output(self.spi.cs_signal(), private::Internal);
}
let this = if let Some(cs) = cs {
this.with_cs(cs)
} else {
this
};
self
this
}
pub(crate) fn new_internal(

View File

@ -73,7 +73,7 @@ use core::marker::PhantomData;
use super::{Error, FullDuplexMode, SpiMode};
use crate::{
dma::{DescriptorChain, DmaPeripheral, Rx, Tx},
gpio::{InputPin, InputSignal, OutputPin, OutputSignal},
gpio::{InputSignal, OutputSignal, PeripheralInput, PeripheralOutput, Pull},
peripheral::{Peripheral, PeripheralRef},
peripherals::spi2::RegisterBlock,
private,
@ -106,25 +106,31 @@ where
T: Instance,
{
/// Constructs an SPI instance in 8bit dataframe mode.
pub fn new<SCK: InputPin, MOSI: InputPin, MISO: OutputPin, CS: InputPin>(
pub fn new<
SCK: PeripheralInput,
MOSI: PeripheralInput,
MISO: PeripheralOutput,
CS: PeripheralInput,
>(
spi: impl Peripheral<P = T> + 'd,
sck: impl Peripheral<P = SCK> + 'd,
sclk: impl Peripheral<P = SCK> + 'd,
mosi: impl Peripheral<P = MOSI> + 'd,
miso: impl Peripheral<P = MISO> + 'd,
cs: impl Peripheral<P = CS> + 'd,
mode: SpiMode,
) -> Spi<'d, T, FullDuplexMode> {
crate::into_ref!(spi, sck, mosi, miso, cs);
sck.init_input(false, false, private::Internal);
sck.connect_input_to_peripheral(spi.sclk_signal(), private::Internal);
crate::into_ref!(spi, sclk, mosi, miso, cs);
mosi.init_input(false, false, private::Internal);
sclk.init_input(Pull::None, private::Internal);
sclk.connect_input_to_peripheral(spi.sclk_signal(), private::Internal);
mosi.init_input(Pull::None, private::Internal);
mosi.connect_input_to_peripheral(spi.mosi_signal(), private::Internal);
miso.set_to_push_pull_output(private::Internal);
miso.connect_peripheral_to_output(spi.miso_signal(), private::Internal);
cs.init_input(false, false, private::Internal);
cs.init_input(Pull::None, private::Internal);
cs.connect_input_to_peripheral(spi.cs_signal(), private::Internal);
Self::new_internal(spi, mode)
@ -148,7 +154,7 @@ where
}
}
/// DMA (Direct Memory Access) funtionality (Slave).
/// DMA (Direct Memory Access) functionality (Slave).
pub mod dma {
use super::*;
#[cfg(spi3)]

View File

@ -133,7 +133,7 @@ use core::marker::PhantomData;
use self::filter::{Filter, FilterType};
use crate::{
gpio::{InputPin, InputSignal, OutputPin, OutputSignal},
gpio::{InputSignal, OutputSignal, PeripheralInput, PeripheralOutput, Pull},
interrupt::InterruptHandler,
peripheral::{Peripheral, PeripheralRef},
peripherals::twai0::RegisterBlock,
@ -716,7 +716,7 @@ where
T: Instance,
DM: crate::Mode,
{
fn new_internal<TX: OutputPin, RX: InputPin>(
fn new_internal<TX: PeripheralOutput, RX: PeripheralInput>(
_peripheral: impl Peripheral<P = T> + 'd,
rx_pin: impl Peripheral<P = RX> + 'd,
tx_pin: impl Peripheral<P = TX> + 'd,
@ -736,13 +736,15 @@ where
.mode()
.write(|w| w.reset_mode().set_bit());
rx_pin.init_input(Pull::None, crate::private::Internal);
rx_pin.connect_input_to_peripheral(T::INPUT_SIGNAL, crate::private::Internal);
if no_transceiver {
tx_pin.set_to_open_drain_output(crate::private::Internal);
} else {
tx_pin.set_to_push_pull_output(crate::private::Internal);
}
tx_pin.set_to_push_pull_output(crate::private::Internal);
tx_pin.connect_peripheral_to_output(T::OUTPUT_SIGNAL, crate::private::Internal);
rx_pin.init_input(false, false, crate::private::Internal);
rx_pin.connect_input_to_peripheral(T::INPUT_SIGNAL, crate::private::Internal);
// Set the operating mode based on provided option
match mode {
@ -903,7 +905,7 @@ where
/// Create a new instance of [TwaiConfiguration]
///
/// You will need to use a transceiver to connect to the TWAI bus
pub fn new<RX: InputPin, TX: OutputPin>(
pub fn new<RX: PeripheralInput, TX: PeripheralOutput>(
peripheral: impl Peripheral<P = T> + 'd,
rx_pin: impl Peripheral<P = RX> + 'd,
tx_pin: impl Peripheral<P = TX> + 'd,
@ -918,7 +920,7 @@ where
///
/// You don't need a transceiver by following the description in the
/// `twai.rs` example
pub fn new_no_transceiver<RX: InputPin, TX: OutputPin>(
pub fn new_no_transceiver<RX: PeripheralInput, TX: PeripheralOutput>(
peripheral: impl Peripheral<P = T> + 'd,
rx_pin: impl Peripheral<P = RX> + 'd,
tx_pin: impl Peripheral<P = TX> + 'd,
@ -947,7 +949,7 @@ where
/// Create a new instance of [TwaiConfiguration] in async mode
///
/// You will need to use a transceiver to connect to the TWAI bus
pub fn new_async<RX: InputPin, TX: OutputPin>(
pub fn new_async<RX: PeripheralInput, TX: PeripheralOutput>(
peripheral: impl Peripheral<P = T> + 'd,
rx_pin: impl Peripheral<P = RX> + 'd,
tx_pin: impl Peripheral<P = TX> + 'd,
@ -964,7 +966,7 @@ where
///
/// You don't need a transceiver by following the description in the
/// `twai.rs` example
pub fn new_async_no_transceiver<RX: InputPin, TX: OutputPin>(
pub fn new_async_no_transceiver<RX: PeripheralInput, TX: PeripheralOutput>(
peripheral: impl Peripheral<P = T> + 'd,
rx_pin: impl Peripheral<P = RX> + 'd,
tx_pin: impl Peripheral<P = TX> + 'd,

View File

@ -94,12 +94,12 @@
//! ```rust, no_run
#![doc = crate::before_snippet!()]
//! # use esp_hal::uart::Uart;
//! use esp_hal::gpio::{AnyPin, Io};
//! use esp_hal::gpio::Io;
//!
//! let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
//!
//! let rx = AnyPin::new_inverted(io.pins.gpio2);
//! let tx = AnyPin::new_inverted(io.pins.gpio1);
//! let rx = io.pins.gpio2.peripheral_input().inverted();
//! let tx = io.pins.gpio1.into_peripheral_output().inverted();
//! let mut uart1 = Uart::new(
//! peripherals.UART1,
//! rx,
@ -112,7 +112,7 @@
//! ```rust, no_run
#![doc = crate::before_snippet!()]
//! # use esp_hal::uart::{UartTx, UartRx};
//! use esp_hal::gpio::{AnyPin, Io};
//! use esp_hal::gpio::Io;
//!
//! let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
//!
@ -131,7 +131,7 @@ use core::marker::PhantomData;
use self::config::Config;
use crate::{
clock::Clocks,
gpio::{InputPin, InputSignal, OutputPin, OutputSignal},
gpio::{InputSignal, OutputSignal, PeripheralInput, PeripheralOutput, Pull},
interrupt::InterruptHandler,
peripheral::{Peripheral, PeripheralRef},
peripherals::{uart0::RegisterBlock, Interrupt},
@ -451,15 +451,15 @@ where
}
}
fn with_rx<RX: InputPin>(self, rx: impl Peripheral<P = RX> + 'd) -> Self {
fn with_rx<RX: PeripheralInput>(self, rx: impl Peripheral<P = RX> + 'd) -> Self {
crate::into_ref!(rx);
rx.init_input(false, false, Internal);
rx.init_input(Pull::Up, Internal);
rx.connect_input_to_peripheral(T::rx_signal(), Internal);
self
}
fn with_tx<TX: OutputPin>(self, tx: impl Peripheral<P = TX> + 'd) -> Self {
fn with_tx<TX: PeripheralOutput>(self, tx: impl Peripheral<P = TX> + 'd) -> Self {
crate::into_ref!(tx);
tx.set_to_push_pull_output(Internal);
tx.connect_peripheral_to_output(T::tx_signal(), Internal);
@ -536,7 +536,7 @@ where
}
/// Configure RTS pin
pub fn with_rts<RTS: OutputPin>(self, rts: impl Peripheral<P = RTS> + 'd) -> Self {
pub fn with_rts<RTS: PeripheralOutput>(self, rts: impl Peripheral<P = RTS> + 'd) -> Self {
crate::into_ref!(rts);
rts.set_to_push_pull_output(Internal);
rts.connect_peripheral_to_output(T::rts_signal(), Internal);
@ -581,7 +581,7 @@ where
T: Instance + 'd,
{
/// Create a new UART TX instance in [`Blocking`] mode.
pub fn new<TX: OutputPin>(
pub fn new<TX: PeripheralOutput>(
uart: impl Peripheral<P = T> + 'd,
tx: impl Peripheral<P = TX> + 'd,
) -> Result<Self, Error> {
@ -590,7 +590,7 @@ where
/// Create a new UART TX instance with configuration options in
/// [`Blocking`] mode.
pub fn new_with_config<TX: OutputPin>(
pub fn new_with_config<TX: PeripheralOutput>(
uart: impl Peripheral<P = T> + 'd,
config: Config,
tx: impl Peripheral<P = TX> + 'd,
@ -620,9 +620,9 @@ where
}
/// Configure CTS pin
pub fn with_cts<CTS: InputPin>(self, cts: impl Peripheral<P = CTS> + 'd) -> Self {
pub fn with_cts<CTS: PeripheralInput>(self, cts: impl Peripheral<P = CTS> + 'd) -> Self {
crate::into_ref!(cts);
cts.init_input(false, false, Internal);
cts.init_input(Pull::None, Internal);
cts.connect_input_to_peripheral(T::cts_signal(), Internal);
self
@ -794,7 +794,7 @@ where
T: Instance + 'd,
{
/// Create a new UART RX instance in [`Blocking`] mode.
pub fn new<RX: InputPin>(
pub fn new<RX: PeripheralInput>(
uart: impl Peripheral<P = T> + 'd,
rx: impl Peripheral<P = RX> + 'd,
) -> Result<Self, Error> {
@ -803,7 +803,7 @@ where
/// Create a new UART RX instance with configuration options in
/// [`Blocking`] mode.
pub fn new_with_config<RX: InputPin>(
pub fn new_with_config<RX: PeripheralInput>(
uart: impl Peripheral<P = T> + 'd,
config: Config,
rx: impl Peripheral<P = RX> + 'd,
@ -820,7 +820,7 @@ where
{
/// Create a new UART instance with configuration options in [`Blocking`]
/// mode.
pub fn new_with_config<TX: OutputPin, RX: InputPin>(
pub fn new_with_config<TX: PeripheralOutput, RX: PeripheralInput>(
uart: impl Peripheral<P = T> + 'd,
config: Config,
rx: impl Peripheral<P = RX> + 'd,
@ -835,7 +835,7 @@ where
}
/// Create a new UART instance with defaults in [`Blocking`] mode.
pub fn new<TX: OutputPin, RX: InputPin>(
pub fn new<TX: PeripheralOutput, RX: PeripheralInput>(
uart: impl Peripheral<P = T> + 'd,
rx: impl Peripheral<P = RX> + 'd,
tx: impl Peripheral<P = TX> + 'd,
@ -857,16 +857,16 @@ where
}
/// Configure CTS pin
pub fn with_cts<CTS: InputPin>(self, cts: impl Peripheral<P = CTS> + 'd) -> Self {
pub fn with_cts<CTS: PeripheralInput>(self, cts: impl Peripheral<P = CTS> + 'd) -> Self {
crate::into_ref!(cts);
cts.init_input(false, false, Internal);
cts.init_input(Pull::None, Internal);
cts.connect_input_to_peripheral(T::cts_signal(), Internal);
self
}
/// Configure RTS pin
pub fn with_rts<RTS: OutputPin>(self, rts: impl Peripheral<P = RTS> + 'd) -> Self {
pub fn with_rts<RTS: PeripheralOutput>(self, rts: impl Peripheral<P = RTS> + 'd) -> Self {
crate::into_ref!(rts);
rts.set_to_push_pull_output(Internal);
rts.connect_peripheral_to_output(T::rts_signal(), Internal);
@ -2058,7 +2058,7 @@ mod asynch {
{
/// Create a new UART instance with configuration options in [`Async`]
/// mode.
pub fn new_async_with_config<RX: InputPin, TX: OutputPin>(
pub fn new_async_with_config<RX: PeripheralInput, TX: PeripheralOutput>(
uart: impl Peripheral<P = T> + 'd,
config: Config,
rx: impl Peripheral<P = RX> + 'd,
@ -2086,7 +2086,7 @@ mod asynch {
}
/// Create a new UART instance with defaults in [`Async`] mode.
pub fn new_async<RX: InputPin, TX: OutputPin>(
pub fn new_async<RX: PeripheralInput, TX: PeripheralOutput>(
uart: impl Peripheral<P = T> + 'd,
rx: impl Peripheral<P = RX> + 'd,
tx: impl Peripheral<P = TX> + 'd,
@ -2121,7 +2121,7 @@ mod asynch {
T: Instance + 'd,
{
/// Create a new UART TX instance in [`Async`] mode.
pub fn new_async<TX: OutputPin>(
pub fn new_async<TX: PeripheralOutput>(
uart: impl Peripheral<P = T> + 'd,
tx: impl Peripheral<P = TX> + 'd,
) -> Result<Self, Error> {
@ -2130,7 +2130,7 @@ mod asynch {
/// Create a new UART TX instance with configuration options in
/// [`Async`] mode.
pub fn new_async_with_config<TX: OutputPin>(
pub fn new_async_with_config<TX: PeripheralOutput>(
uart: impl Peripheral<P = T> + 'd,
config: Config,
tx: impl Peripheral<P = TX> + 'd,
@ -2202,7 +2202,7 @@ mod asynch {
T: Instance + 'd,
{
/// Create a new UART RX instance in [`Async`] mode.
pub fn new_async<RX: InputPin>(
pub fn new_async<RX: PeripheralInput>(
uart: impl Peripheral<P = T> + 'd,
rx: impl Peripheral<P = RX> + 'd,
) -> Result<Self, Error> {
@ -2211,7 +2211,7 @@ mod asynch {
/// Create a new UART RX instance with configuration options in
/// [`Async`] mode.
pub fn new_async_with_config<RX: InputPin>(
pub fn new_async_with_config<RX: PeripheralInput>(
uart: impl Peripheral<P = T> + 'd,
config: Config,
rx: impl Peripheral<P = RX> + 'd,

View File

@ -12,13 +12,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added `have-strchr` feature to disable including `strchr` (#2096)
### Changed
- esp-wifi now allocates memory from the global allocator provided by `esp-alloc` (#2099)
### Fixed
- Feature `wifi-logs` doesn't break the build anymore (#2117)
### Removed
- Removed the `clocks` parameter from `esp_wifi::initialize` (#1999)
## 0.9.1 - 2024-09-03
### Added
@ -43,8 +47,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Removed
- Removed the `clocks` parameter from `esp_wifi::initialize` (#1999)
## 0.8.0 - 2024-08-29
### Added

View File

@ -14,7 +14,7 @@
use esp_backtrace as _;
use esp_hal::{
delay::Delay,
gpio::{ErasedPin, Input, Io, Level, Output, Pin, Pull},
gpio::{Input, Io, Level, Output, Pin, Pull},
prelude::*,
};
@ -47,7 +47,7 @@ fn main() -> ! {
}
}
fn toggle_pins(leds: &mut [Output<ErasedPin>], button: &Input<ErasedPin>) {
fn toggle_pins(leds: &mut [Output], button: &Input) {
for pin in leds.iter_mut() {
pin.toggle();
}

View File

@ -6,7 +6,7 @@
//! This is an example of running the embassy executor with IC2. It uses an
//! LIS3DH to get accelerometer data.
//!
//! Folowing pins are used:
//! Following pins are used:
//! - SDA => GPIO4
//! - SCL => GPIO5

View File

@ -3,7 +3,7 @@
//! This example dumps the calibration data from a BMP180 sensor by reading by reading
//! with the direct I2C API and the embedded-hal-async I2C API.
//!
//! Folowing pins are used:
//! Following pins are used:
//! - SDA => GPIO4
//! - SCL => GPIO5
//!

View File

@ -21,7 +21,7 @@ use esp_backtrace as _;
use esp_hal::{
cpu_control::{CpuControl, Stack},
get_core,
gpio::{ErasedPin, Io, Level, Output, Pin},
gpio::{Io, Level, Output, Pin},
timer::{timg::TimerGroup, ErasedTimer},
};
use esp_hal_embassy::Executor;
@ -34,7 +34,7 @@ static mut APP_CORE_STACK: Stack<8192> = Stack::new();
/// duration of time.
#[embassy_executor::task]
async fn control_led(
mut led: Output<'static, ErasedPin>,
mut led: Output<'static>,
control: &'static Signal<CriticalSectionRawMutex, bool>,
) {
println!("Starting control_led() on core {}", get_core() as usize);

View File

@ -20,7 +20,7 @@ use esp_backtrace as _;
use esp_hal::{
cpu_control::{CpuControl, Stack},
get_core,
gpio::{ErasedPin, Io, Level, Output, Pin},
gpio::{Io, Level, Output, Pin},
interrupt::{software::SoftwareInterruptControl, Priority},
prelude::*,
timer::{timg::TimerGroup, ErasedTimer},
@ -35,7 +35,7 @@ static mut APP_CORE_STACK: Stack<8192> = Stack::new();
/// duration of time.
#[embassy_executor::task]
async fn control_led(
mut led: Output<'static, ErasedPin>,
mut led: Output<'static>,
control: &'static Signal<CriticalSectionRawMutex, bool>,
) {
println!("Starting control_led() on core {}", get_core() as usize);

View File

@ -53,15 +53,15 @@ fn main() -> ! {
println!("setup channel 0");
let ch0 = &u0.channel0;
let mut pin_a = io.pins.gpio4;
let mut pin_b = io.pins.gpio5;
let pin_a = io.pins.gpio4;
let pin_b = io.pins.gpio5;
ch0.set_ctrl_signal(PcntSource::from_pin(
&mut pin_a,
ch0.set_ctrl_signal(PcntSource::from(
pin_a.peripheral_input(),
PcntInputConfig { pull: Pull::Up },
));
ch0.set_edge_signal(PcntSource::from_pin(
&mut pin_b,
ch0.set_edge_signal(PcntSource::from(
pin_b.peripheral_input(),
PcntInputConfig { pull: Pull::Up },
));
ch0.set_ctrl_mode(channel::CtrlMode::Reverse, channel::CtrlMode::Keep);
@ -69,12 +69,12 @@ fn main() -> ! {
println!("setup channel 1");
let ch1 = &u0.channel1;
ch1.set_ctrl_signal(PcntSource::from_pin(
&mut pin_b,
ch1.set_ctrl_signal(PcntSource::from(
pin_b.peripheral_input(),
PcntInputConfig { pull: Pull::Up },
));
ch1.set_edge_signal(PcntSource::from_pin(
&mut pin_a,
ch1.set_edge_signal(PcntSource::from(
pin_a.peripheral_input(),
PcntInputConfig { pull: Pull::Up },
));
ch1.set_ctrl_mode(channel::CtrlMode::Reverse, channel::CtrlMode::Keep);

View File

@ -2,16 +2,13 @@
//!
//! The following wiring is assumed:
//! - SCLK => GPIO0
//! - MISO => GPIO2
//! - MOSI => GPIO4
//! - MISO/MOSI => GPIO2
//! - CS => GPIO5
//!
//! Depending on your target and the board you are using you have to change the
//! pins.
//!
//! This example transfers data via SPI.
//! Connect MISO and MOSI pins to see the outgoing data is read as incoming
//! data.
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
@ -21,7 +18,7 @@
use esp_backtrace as _;
use esp_hal::{
delay::Delay,
gpio::{AnyPin, Io},
gpio::Io,
prelude::*,
spi::{master::Spi, SpiMode},
};
@ -33,12 +30,11 @@ fn main() -> ! {
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
let sclk = io.pins.gpio0;
let miso = io.pins.gpio2;
let mosi = io.pins.gpio4;
let miso_mosi = io.pins.gpio2;
let cs = io.pins.gpio5;
let miso = AnyPin::new(miso);
let mosi = AnyPin::new(mosi);
let miso = miso_mosi.peripheral_input();
let mosi = miso_mosi.into_peripheral_output();
let mut spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0).with_pins(
Some(sclk),

View File

@ -11,7 +11,7 @@ use core::cell::RefCell;
use critical_section::Mutex;
use esp_hal::{
delay::Delay,
gpio::{AnyPin, ErasedPin, Input, Io, Level, Output, Pin, Pull},
gpio::{AnyPin, Input, Io, Level, Output, Pin, Pull},
macros::handler,
timer::timg::TimerGroup,
InterruptConfigurable,
@ -22,8 +22,8 @@ static COUNTER: Mutex<RefCell<u32>> = Mutex::new(RefCell::new(0));
static INPUT_PIN: Mutex<RefCell<Option<Input>>> = Mutex::new(RefCell::new(None));
struct Context {
test_gpio1: ErasedPin,
test_gpio2: ErasedPin,
test_gpio1: AnyPin,
test_gpio2: AnyPin,
delay: Delay,
}
@ -267,8 +267,8 @@ mod tests {
// https://github.com/esp-rs/esp-hal/issues/1943
#[test]
fn test_gpio_touch_anypin_output(ctx: Context) {
let any_pin2 = AnyPin::new(ctx.test_gpio1);
let any_pin3 = AnyPin::new(ctx.test_gpio2);
let any_pin2 = ctx.test_gpio1;
let any_pin3 = ctx.test_gpio2;
let out_pin = Output::new(any_pin2, Level::High);
let in_pin = Input::new(any_pin3, Pull::Down);
@ -281,8 +281,8 @@ mod tests {
// https://github.com/esp-rs/esp-hal/issues/1943
#[test]
fn test_gpio_touch_anypin_input(ctx: Context) {
let any_pin2 = AnyPin::new(ctx.test_gpio1);
let any_pin3 = AnyPin::new(ctx.test_gpio2);
let any_pin2 = ctx.test_gpio1;
let any_pin3 = ctx.test_gpio2;
let out_pin = Output::new(any_pin3, Level::Low);
let in_pin = Input::new(any_pin2, Pull::Down);

View File

@ -7,7 +7,7 @@
use esp_hal::{
delay::Delay,
gpio::{AnyPin, Io, Level, Output, Pull},
gpio::{AnyPin, Io, Level, Output, Pin, Pull},
pcnt::{
channel::{EdgeMode, PcntInputConfig, PcntSource},
Pcnt,
@ -17,8 +17,8 @@ use hil_test as _;
struct Context<'d> {
pcnt: Pcnt<'d>,
input: AnyPin<'d>,
output: AnyPin<'d>,
input: AnyPin,
output: AnyPin,
delay: Delay,
}
@ -35,8 +35,8 @@ mod tests {
let (din, dout) = hil_test::common_test_pins!(io);
let din = AnyPin::new(din);
let dout = AnyPin::new(dout);
let din = din.degrade();
let dout = dout.degrade();
Context {
pcnt: Pcnt::new(peripherals.PCNT),
@ -51,7 +51,7 @@ mod tests {
let unit = ctx.pcnt.unit0;
// Setup channel 0 to increment the count when gpio2 does LOW -> HIGH
unit.channel0.set_edge_signal(PcntSource::from_pin(
unit.channel0.set_edge_signal(PcntSource::from(
ctx.input,
PcntInputConfig { pull: Pull::Down },
));
@ -90,7 +90,7 @@ mod tests {
let unit = ctx.pcnt.unit1;
// Setup channel 0 to increment the count when gpio2 does LOW -> HIGH
unit.channel0.set_edge_signal(PcntSource::from_pin(
unit.channel0.set_edge_signal(PcntSource::from(
ctx.input,
PcntInputConfig { pull: Pull::Up },
));
@ -131,7 +131,7 @@ mod tests {
unit.set_high_limit(Some(3)).unwrap();
// Setup channel 0 to increment the count when gpio2 does LOW -> HIGH
unit.channel0.set_edge_signal(PcntSource::from_pin(
unit.channel0.set_edge_signal(PcntSource::from(
ctx.input,
PcntInputConfig { pull: Pull::Up },
));
@ -194,7 +194,7 @@ mod tests {
unit.clear();
// Setup channel 0 to increment the count when gpio2 does LOW -> HIGH
unit.channel0.set_edge_signal(PcntSource::from_pin(
unit.channel0.set_edge_signal(PcntSource::from(
ctx.input,
PcntInputConfig { pull: Pull::Up },
));
@ -261,7 +261,7 @@ mod tests {
unit.clear();
// Setup channel 0 to decrement the count when gpio2 does LOW -> HIGH
unit.channel0.set_edge_signal(PcntSource::from_pin(
unit.channel0.set_edge_signal(PcntSource::from(
ctx.input,
PcntInputConfig { pull: Pull::Up },
));
@ -319,7 +319,7 @@ mod tests {
let unit = ctx.pcnt.unit2;
// Setup channel 1 to increment the count when gpio2 does LOW -> HIGH
unit.channel1.set_edge_signal(PcntSource::from_pin(
unit.channel1.set_edge_signal(PcntSource::from(
ctx.input,
PcntInputConfig { pull: Pull::Up },
));

View File

@ -8,7 +8,7 @@
use esp_hal::{
dma::{Channel, Dma, DmaPriority, DmaRxBuf},
dma_buffers,
gpio::{ErasedPin, Io, Level, Output},
gpio::{AnyPin, Io, Level, Output},
prelude::*,
spi::{
master::{Address, Command, Spi, SpiDma},
@ -34,7 +34,7 @@ cfg_if::cfg_if! {
struct Context {
spi: esp_hal::peripherals::SPI2,
dma_channel: Channel<'static, DmaChannel0, Blocking>,
miso: ErasedPin,
miso: AnyPin,
miso_mirror: Output<'static>,
}

View File

@ -38,10 +38,10 @@ cfg_if::cfg_if! {
struct Context {
spi: esp_hal::peripherals::SPI2,
pcnt_source: PcntSource,
pcnt: esp_hal::peripherals::PCNT,
dma_channel: Channel<'static, DmaChannel0, Blocking>,
mosi: AnyPin<'static>,
mosi_mirror: AnyPin<'static>,
mosi: AnyPin,
}
fn execute(
@ -103,10 +103,9 @@ mod tests {
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
let (mosi, mosi_mirror) = hil_test::common_test_pins!(io);
let (mosi, _) = hil_test::common_test_pins!(io);
let mosi = AnyPin::new(mosi);
let mosi_mirror = AnyPin::new(mosi_mirror);
let mosi = mosi.degrade();
let dma = Dma::new(peripherals.DMA);
@ -122,10 +121,13 @@ mod tests {
Context {
spi: peripherals.SPI2,
pcnt_source: PcntSource::from(
mosi.peripheral_input(),
PcntInputConfig { pull: Pull::None },
),
pcnt: peripherals.PCNT,
dma_channel,
mosi,
mosi_mirror,
}
}
@ -146,10 +148,7 @@ mod tests {
let pcnt = Pcnt::new(ctx.pcnt);
let unit = pcnt.unit0;
unit.channel0.set_edge_signal(PcntSource::from_pin(
ctx.mosi_mirror,
PcntInputConfig { pull: Pull::None },
));
unit.channel0.set_edge_signal(ctx.pcnt_source);
unit.channel0
.set_input_mode(EdgeMode::Hold, EdgeMode::Increment);
@ -173,10 +172,7 @@ mod tests {
let pcnt = Pcnt::new(ctx.pcnt);
let unit = pcnt.unit0;
unit.channel0.set_edge_signal(PcntSource::from_pin(
ctx.mosi_mirror,
PcntInputConfig { pull: Pull::None },
));
unit.channel0.set_edge_signal(ctx.pcnt_source);
unit.channel0
.set_input_mode(EdgeMode::Hold, EdgeMode::Increment);
@ -200,10 +196,7 @@ mod tests {
let pcnt = Pcnt::new(ctx.pcnt);
let unit = pcnt.unit0;
unit.channel0.set_edge_signal(PcntSource::from_pin(
ctx.mosi_mirror,
PcntInputConfig { pull: Pull::None },
));
unit.channel0.set_edge_signal(ctx.pcnt_source);
unit.channel0
.set_input_mode(EdgeMode::Hold, EdgeMode::Increment);
@ -227,10 +220,7 @@ mod tests {
let pcnt = Pcnt::new(ctx.pcnt);
let unit = pcnt.unit0;
unit.channel0.set_edge_signal(PcntSource::from_pin(
ctx.mosi_mirror,
PcntInputConfig { pull: Pull::None },
));
unit.channel0.set_edge_signal(ctx.pcnt_source);
unit.channel0
.set_input_mode(EdgeMode::Hold, EdgeMode::Increment);

View File

@ -10,7 +10,7 @@
use esp_hal::{
dma::{Channel, Dma, DmaPriority, DmaRxBuf, DmaTxBuf},
dma_buffers,
gpio::{ErasedPin, Io, Level, Output},
gpio::{AnyPin, Io, Level, Output},
prelude::*,
spi::{
master::{Address, Command, Spi, SpiDma},
@ -36,7 +36,7 @@ cfg_if::cfg_if! {
struct Context {
spi: esp_hal::peripherals::SPI2,
dma_channel: Channel<'static, DmaChannel0, Blocking>,
mosi: ErasedPin,
mosi: AnyPin,
mosi_mirror: Output<'static>,
}

View File

@ -31,12 +31,13 @@ mod tests {
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
let sclk = io.pins.gpio0;
let (miso, mosi) = hil_test::common_test_pins!(io);
let (_, mosi) = hil_test::common_test_pins!(io);
let spi = Spi::new(peripherals.SPI2, 1000u32.kHz(), SpiMode::Mode0)
let mosi_loopback = mosi.peripheral_input();
let spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0)
.with_sck(sclk)
.with_mosi(mosi)
.with_miso(miso);
.with_miso(mosi_loopback);
Context { spi }
}

View File

@ -48,7 +48,7 @@ mod tests {
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
let sclk = io.pins.gpio0;
let (miso, mosi) = hil_test::common_test_pins!(io);
let (_, mosi) = hil_test::common_test_pins!(io);
let dma = Dma::new(peripherals.DMA);
@ -60,10 +60,11 @@ mod tests {
}
}
let mosi_loopback = mosi.peripheral_input();
let spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0)
.with_sck(sclk)
.with_mosi(mosi)
.with_miso(miso)
.with_miso(mosi_loopback)
.with_dma(dma_channel.configure(false, DmaPriority::Priority0));
Context { spi }

View File

@ -10,7 +10,7 @@ use embedded_hal_async::spi::SpiBus;
use esp_hal::{
dma::{Dma, DmaPriority, DmaRxBuf, DmaTxBuf},
dma_buffers,
gpio::{ErasedPin, Io, Level, Output, Pull},
gpio::{Io, Pull},
pcnt::{
channel::{EdgeMode, PcntInputConfig, PcntSource},
unit::Unit,
@ -42,9 +42,8 @@ const DMA_BUFFER_SIZE: usize = 5;
struct Context {
spi: SpiDmaBus<'static, SPI2, DmaChannel0, FullDuplexMode, Async>,
pcnt_source: PcntSource,
pcnt_unit: Unit<'static, 0>,
out_pin: Output<'static>,
mosi_mirror: ErasedPin,
}
#[cfg(test)]
@ -62,13 +61,7 @@ mod tests {
let pcnt = Pcnt::new(peripherals.PCNT);
let sclk = io.pins.gpio0;
let (mosi_mirror, mosi) = hil_test::common_test_pins!(io);
let miso = io.pins.gpio4;
let mosi_mirror = mosi_mirror.degrade();
let mut out_pin = Output::new(io.pins.gpio5, Level::Low);
out_pin.set_low();
assert_eq!(out_pin.is_set_low(), true);
let (_, mosi) = hil_test::common_test_pins!(io);
let dma = Dma::new(peripherals.DMA);
@ -84,28 +77,26 @@ mod tests {
let dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap();
let dma_tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer).unwrap();
let mosi_loopback = mosi.peripheral_input();
let mosi_loopback_pcnt = mosi.peripheral_input();
let spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0)
.with_sck(sclk)
.with_mosi(mosi)
.with_miso(miso)
.with_miso(mosi_loopback)
.with_dma(dma_channel.configure_for_async(false, DmaPriority::Priority0))
.with_buffers(dma_rx_buf, dma_tx_buf);
Context {
spi,
pcnt_source: PcntSource::from(mosi_loopback_pcnt, PcntInputConfig { pull: Pull::Down }),
pcnt_unit: pcnt.unit0,
out_pin,
mosi_mirror,
}
}
#[test]
#[timeout(3)]
async fn test_async_dma_read_dma_write_pcnt(mut ctx: Context) {
ctx.pcnt_unit.channel0.set_edge_signal(PcntSource::from_pin(
ctx.mosi_mirror,
PcntInputConfig { pull: Pull::Down },
));
ctx.pcnt_unit.channel0.set_edge_signal(ctx.pcnt_source);
ctx.pcnt_unit
.channel0
.set_input_mode(EdgeMode::Hold, EdgeMode::Increment);
@ -115,8 +106,6 @@ mod tests {
// Fill the buffer where each byte has 3 pos edges.
let transmit = [0b0110_1010; DMA_BUFFER_SIZE];
assert_eq!(ctx.out_pin.is_set_low(), true);
for i in 1..4 {
receive.copy_from_slice(&[5, 5, 5, 5, 5]);
SpiBus::read(&mut ctx.spi, &mut receive).await.unwrap();
@ -130,10 +119,7 @@ mod tests {
#[test]
#[timeout(3)]
async fn test_async_dma_read_dma_transfer_pcnt(mut ctx: Context) {
ctx.pcnt_unit.channel0.set_edge_signal(PcntSource::from_pin(
ctx.mosi_mirror,
PcntInputConfig { pull: Pull::Down },
));
ctx.pcnt_unit.channel0.set_edge_signal(ctx.pcnt_source);
ctx.pcnt_unit
.channel0
.set_input_mode(EdgeMode::Hold, EdgeMode::Increment);
@ -143,8 +129,6 @@ mod tests {
// Fill the buffer where each byte has 3 pos edges.
let transmit = [0b0110_1010; DMA_BUFFER_SIZE];
assert_eq!(ctx.out_pin.is_set_low(), true);
for i in 1..4 {
receive.copy_from_slice(&[5, 5, 5, 5, 5]);
SpiBus::read(&mut ctx.spi, &mut receive).await.unwrap();

View File

@ -8,7 +8,7 @@
use esp_hal::{
dma::{Dma, DmaPriority, DmaRxBuf, DmaTxBuf},
dma_buffers,
gpio::{ErasedPin, Io, Level, Output, Pull},
gpio::{Io, Pull},
pcnt::{
channel::{EdgeMode, PcntInputConfig, PcntSource},
unit::Unit,
@ -38,9 +38,8 @@ cfg_if::cfg_if! {
struct Context {
spi: SpiDma<'static, SPI2, DmaChannel0, FullDuplexMode, Blocking>,
pcnt_source: PcntSource,
pcnt_unit: Unit<'static, 0>,
out_pin: Output<'static>,
mosi_mirror: ErasedPin,
}
#[cfg(test)]
@ -56,8 +55,7 @@ mod tests {
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
let sclk = io.pins.gpio0;
let (mosi_mirror, mosi) = hil_test::common_test_pins!(io);
let miso = io.pins.gpio4;
let (_, mosi) = hil_test::common_test_pins!(io);
let dma = Dma::new(peripherals.DMA);
@ -69,24 +67,20 @@ mod tests {
}
}
let mosi_loopback = mosi.peripheral_input();
let mosi_loopback_pcnt = mosi.peripheral_input();
let spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0)
.with_sck(sclk)
.with_mosi(mosi)
.with_miso(miso)
.with_miso(mosi_loopback)
.with_dma(dma_channel.configure(false, DmaPriority::Priority0));
let pcnt = Pcnt::new(peripherals.PCNT);
let mut out_pin = Output::new(io.pins.gpio5, Level::Low);
out_pin.set_low();
assert_eq!(out_pin.is_set_low(), true);
let mosi_mirror = mosi_mirror.degrade();
Context {
spi,
pcnt_source: PcntSource::from(mosi_loopback_pcnt, PcntInputConfig { pull: Pull::Down }),
pcnt_unit: pcnt.unit0,
out_pin,
mosi_mirror,
}
}
@ -101,18 +95,13 @@ mod tests {
let unit = ctx.pcnt_unit;
let mut spi = ctx.spi;
unit.channel0.set_edge_signal(PcntSource::from_pin(
ctx.mosi_mirror,
PcntInputConfig { pull: Pull::Down },
));
unit.channel0.set_edge_signal(ctx.pcnt_source);
unit.channel0
.set_input_mode(EdgeMode::Hold, EdgeMode::Increment);
// Fill the buffer where each byte has 3 pos edges.
dma_tx_buf.as_mut_slice().fill(0b0110_1010);
assert_eq!(ctx.out_pin.is_set_low(), true);
for i in 1..4 {
dma_rx_buf.as_mut_slice().copy_from_slice(&[5, 5, 5, 5, 5]);
let transfer = spi.dma_read(dma_rx_buf).map_err(|e| e.0).unwrap();
@ -136,18 +125,13 @@ mod tests {
let unit = ctx.pcnt_unit;
let mut spi = ctx.spi;
unit.channel0.set_edge_signal(PcntSource::from_pin(
ctx.mosi_mirror,
PcntInputConfig { pull: Pull::Down },
));
unit.channel0.set_edge_signal(ctx.pcnt_source);
unit.channel0
.set_input_mode(EdgeMode::Hold, EdgeMode::Increment);
// Fill the buffer where each byte has 3 pos edges.
dma_tx_buf.as_mut_slice().fill(0b0110_1010);
assert_eq!(ctx.out_pin.is_set_low(), true);
for i in 1..4 {
dma_rx_buf.as_mut_slice().copy_from_slice(&[5, 5, 5, 5, 5]);
let transfer = spi.dma_read(dma_rx_buf).map_err(|e| e.0).unwrap();

View File

@ -8,7 +8,7 @@
use esp_hal::{
dma::{Dma, DmaPriority, DmaRxBuf, DmaTxBuf},
dma_buffers,
gpio::{AnyPin, Io, Pull},
gpio::{Io, Pull},
pcnt::{
channel::{EdgeMode, PcntInputConfig, PcntSource},
unit::Unit,
@ -40,7 +40,7 @@ cfg_if::cfg_if! {
struct Context {
spi: SpiDma<'static, SPI2, DmaChannel0, HalfDuplexMode, Blocking>,
pcnt_unit: Unit<'static, 0>,
mosi_mirror: AnyPin<'static>,
pcnt_source: PcntSource,
}
#[cfg(test)]
@ -59,9 +59,7 @@ mod tests {
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
let sclk = io.pins.gpio0;
let (mosi, mosi_mirror) = hil_test::common_test_pins!(io);
let mosi_mirror = AnyPin::new(mosi_mirror);
let (mosi, _) = hil_test::common_test_pins!(io);
let pcnt = Pcnt::new(peripherals.PCNT);
let dma = Dma::new(peripherals.DMA);
@ -74,6 +72,8 @@ mod tests {
}
}
let mosi_loopback = mosi.peripheral_input();
let spi = Spi::new_half_duplex(peripherals.SPI2, 100.kHz(), SpiMode::Mode0)
.with_sck(sclk)
.with_mosi(mosi)
@ -81,7 +81,7 @@ mod tests {
Context {
spi,
mosi_mirror,
pcnt_source: PcntSource::from(mosi_loopback, PcntInputConfig { pull: Pull::Down }),
pcnt_unit: pcnt.unit0,
}
}
@ -97,10 +97,7 @@ mod tests {
let unit = ctx.pcnt_unit;
let mut spi = ctx.spi;
unit.channel0.set_edge_signal(PcntSource::from_pin(
ctx.mosi_mirror,
PcntInputConfig { pull: Pull::Down },
));
unit.channel0.set_edge_signal(ctx.pcnt_source);
unit.channel0
.set_input_mode(EdgeMode::Hold, EdgeMode::Increment);
@ -148,10 +145,7 @@ mod tests {
let unit = ctx.pcnt_unit;
let mut spi = ctx.spi.with_buffers(dma_rx_buf, dma_tx_buf);
unit.channel0.set_edge_signal(PcntSource::from_pin(
ctx.mosi_mirror,
PcntInputConfig { pull: Pull::Down },
));
unit.channel0.set_edge_signal(ctx.pcnt_source);
unit.channel0
.set_input_mode(EdgeMode::Hold, EdgeMode::Increment);