inherent gpio methods (#1284)

This commit is contained in:
Zgarbul Andrey 2024-04-03 19:47:47 +03:00 committed by GitHub
parent ba73154c36
commit 13c81177c5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 534 additions and 318 deletions

View File

@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added async support for TWAI (#1320)
- Add TWAI support for ESP32-C6 (#1323)
- `GpioPin::steal` unsafe API (#1363)
- Inherent implementions of GPIO pin `set_low`, `is_low`, etc.
### Fixed

View File

@ -542,68 +542,37 @@ pub struct GpioPin<MODE, const GPIONUM: u8> {
_mode: PhantomData<MODE>,
}
#[cfg(feature = "embedded-hal-02")]
impl<MODE, const GPIONUM: u8> embedded_hal_02::digital::v2::InputPin
for GpioPin<Input<MODE>, GPIONUM>
impl<MODE, const GPIONUM: u8> GpioPin<Input<MODE>, GPIONUM>
where
Self: GpioProperties,
{
type Error = core::convert::Infallible;
fn is_high(&self) -> Result<bool, Self::Error> {
Ok(<Self as GpioProperties>::Bank::read_input() & (1 << (GPIONUM % 32)) != 0)
/// Is the input pin high?
#[inline]
pub fn is_high(&self) -> bool {
<Self as GpioProperties>::Bank::read_input() & (1 << (GPIONUM % 32)) != 0
}
fn is_low(&self) -> Result<bool, Self::Error> {
Ok(!self.is_high()?)
/// Is the input pin low?
#[inline]
pub fn is_low(&self) -> bool {
!self.is_high()
}
}
#[cfg(feature = "embedded-hal-02")]
impl<const GPIONUM: u8> embedded_hal_02::digital::v2::InputPin
for GpioPin<Output<OpenDrain>, GPIONUM>
impl<const GPIONUM: u8> GpioPin<Output<OpenDrain>, GPIONUM>
where
Self: GpioProperties,
{
type Error = core::convert::Infallible;
fn is_high(&self) -> Result<bool, Self::Error> {
Ok(<Self as GpioProperties>::Bank::read_input() & (1 << (GPIONUM % 32)) != 0)
/// Is the input pin high?
#[inline]
pub fn is_high(&self) -> bool {
<Self as GpioProperties>::Bank::read_input() & (1 << (GPIONUM % 32)) != 0
}
fn is_low(&self) -> Result<bool, Self::Error> {
Ok(!self.is_high()?)
}
}
#[cfg(feature = "embedded-hal")]
impl<MODE, const GPIONUM: u8> embedded_hal::digital::ErrorType for GpioPin<Input<MODE>, GPIONUM>
where
Self: GpioProperties,
{
type Error = core::convert::Infallible;
}
#[cfg(feature = "embedded-hal")]
impl<MODE, const GPIONUM: u8> embedded_hal::digital::InputPin for GpioPin<Input<MODE>, GPIONUM>
where
Self: GpioProperties,
{
fn is_high(&mut self) -> Result<bool, Self::Error> {
Ok(<Self as GpioProperties>::Bank::read_input() & (1 << (GPIONUM % 32)) != 0)
}
fn is_low(&mut self) -> Result<bool, Self::Error> {
Ok(!self.is_high()?)
}
}
#[cfg(feature = "embedded-hal")]
impl<const GPIONUM: u8> embedded_hal::digital::InputPin for GpioPin<Output<OpenDrain>, GPIONUM>
where
Self: GpioProperties,
<Self as GpioProperties>::PinType: IsOutputPin,
{
fn is_high(&mut self) -> Result<bool, Self::Error> {
Ok(<Self as GpioProperties>::Bank::read_input() & (1 << (GPIONUM % 32)) != 0)
}
fn is_low(&mut self) -> Result<bool, Self::Error> {
Ok(!self.is_high()?)
/// Is the input pin low?
#[inline]
pub fn is_low(&self) -> bool {
!self.is_high()
}
}
@ -906,97 +875,49 @@ where
}
}
#[cfg(feature = "embedded-hal-02")]
impl<MODE, const GPIONUM: u8> embedded_hal_02::digital::v2::OutputPin
for GpioPin<Output<MODE>, GPIONUM>
impl<MODE, const GPIONUM: u8> GpioPin<Output<MODE>, GPIONUM>
where
Self: GpioProperties,
<Self as GpioProperties>::PinType: IsOutputPin,
{
type Error = core::convert::Infallible;
fn set_high(&mut self) -> Result<(), Self::Error> {
/// Drives the pin high.
#[inline]
pub fn set_high(&mut self) {
<Self as GpioProperties>::Bank::write_output_set(1 << (GPIONUM % 32));
Ok(())
}
fn set_low(&mut self) -> Result<(), Self::Error> {
/// Drives the pin low.
#[inline]
pub fn set_low(&mut self) {
<Self as GpioProperties>::Bank::write_output_clear(1 << (GPIONUM % 32));
Ok(())
}
}
#[cfg(feature = "embedded-hal-02")]
impl<MODE, const GPIONUM: u8> embedded_hal_02::digital::v2::StatefulOutputPin
for GpioPin<Output<MODE>, GPIONUM>
where
Self: GpioProperties,
<Self as GpioProperties>::PinType: IsOutputPin,
{
fn is_set_high(&self) -> Result<bool, Self::Error> {
Ok(<Self as GpioProperties>::Bank::read_output() & (1 << (GPIONUM % 32)) != 0)
}
fn is_set_low(&self) -> Result<bool, Self::Error> {
Ok(!self.is_set_high()?)
}
}
// TODO: add `set_state(PinState)`
// Drives the pin high or low depending on the provided value.
#[cfg(feature = "embedded-hal-02")]
impl<MODE, const GPIONUM: u8> embedded_hal_02::digital::v2::ToggleableOutputPin
for GpioPin<Output<MODE>, GPIONUM>
where
Self: GpioProperties,
<Self as GpioProperties>::PinType: IsOutputPin,
{
type Error = core::convert::Infallible;
fn toggle(&mut self) -> Result<(), Self::Error> {
use embedded_hal_02::digital::v2::{OutputPin as _, StatefulOutputPin as _};
if self.is_set_high()? {
Ok(self.set_low()?)
/// Is the pin in drive high mode?
#[inline]
pub fn is_set_high(&self) -> bool {
<Self as GpioProperties>::Bank::read_output() & (1 << (GPIONUM % 32)) != 0
}
/// Is the pin in drive low mode?
#[inline]
pub fn is_set_low(&self) -> bool {
!self.is_set_high()
}
/// Toggle pin output.
#[inline]
pub fn toggle(&mut self) {
if self.is_set_high() {
self.set_low();
} else {
Ok(self.set_high()?)
self.set_high();
}
}
}
#[cfg(feature = "embedded-hal")]
impl<MODE, const GPIONUM: u8> embedded_hal::digital::ErrorType for GpioPin<Output<MODE>, GPIONUM>
where
Self: GpioProperties,
<Self as GpioProperties>::PinType: IsOutputPin,
{
type Error = core::convert::Infallible;
}
#[cfg(feature = "embedded-hal")]
impl<MODE, const GPIONUM: u8> embedded_hal::digital::OutputPin for GpioPin<Output<MODE>, GPIONUM>
where
Self: GpioProperties,
<Self as GpioProperties>::PinType: IsOutputPin,
{
fn set_low(&mut self) -> Result<(), Self::Error> {
<Self as GpioProperties>::Bank::write_output_clear(1 << (GPIONUM % 32));
Ok(())
}
fn set_high(&mut self) -> Result<(), Self::Error> {
<Self as GpioProperties>::Bank::write_output_set(1 << (GPIONUM % 32));
Ok(())
}
}
#[cfg(feature = "embedded-hal")]
impl<MODE, const GPIONUM: u8> embedded_hal::digital::StatefulOutputPin
for GpioPin<Output<MODE>, GPIONUM>
where
Self: GpioProperties,
<Self as GpioProperties>::PinType: IsOutputPin,
{
fn is_set_high(&mut self) -> Result<bool, Self::Error> {
Ok(<Self as GpioProperties>::Bank::read_output() & (1 << (GPIONUM % 32)) != 0)
}
fn is_set_low(&mut self) -> Result<bool, Self::Error> {
Ok(!self.is_set_high()?)
}
}
impl<MODE, const GPIONUM: u8> crate::peripheral::Peripheral for GpioPin<MODE, GPIONUM>
where
Self: GpioProperties,
@ -1772,131 +1693,91 @@ where
}
}
#[cfg(feature = "embedded-hal-02")]
impl<MODE, TYPE> embedded_hal_02::digital::v2::InputPin for AnyPin<Input<MODE>, TYPE> {
type Error = core::convert::Infallible;
fn is_high(&self) -> Result<bool, Self::Error> {
impl<MODE, TYPE> AnyPin<Input<MODE>, TYPE> {
/// Is the input pin high?
#[inline]
pub fn is_high(&self) -> bool {
let inner = &self.inner;
handle_gpio_input!(inner, target, { target.is_high() })
}
fn is_low(&self) -> Result<bool, Self::Error> {
/// Is the input pin low?
#[inline]
pub fn is_low(&self) -> bool {
let inner = &self.inner;
handle_gpio_input!(inner, target, { target.is_low() })
}
}
#[cfg(feature = "embedded-hal")]
impl<MODE, TYPE> embedded_hal::digital::ErrorType for AnyPin<Input<MODE>, TYPE> {
type Error = core::convert::Infallible;
}
#[cfg(feature = "embedded-hal")]
impl<MODE, TYPE> embedded_hal::digital::InputPin for AnyPin<Input<MODE>, TYPE> {
fn is_high(&mut self) -> Result<bool, Self::Error> {
let inner = &mut self.inner;
handle_gpio_input!(inner, target, { target.is_high() })
}
fn is_low(&mut self) -> Result<bool, Self::Error> {
let inner = &mut self.inner;
handle_gpio_input!(inner, target, { target.is_low() })
}
}
#[cfg(feature = "embedded-hal-02")]
impl<MODE, TYPE> embedded_hal_02::digital::v2::OutputPin for AnyPin<Output<MODE>, TYPE> {
type Error = core::convert::Infallible;
fn set_low(&mut self) -> Result<(), Self::Error> {
impl<MODE, TYPE> AnyPin<Output<MODE>, TYPE> {
/// Drives the pin low.
#[inline]
pub fn set_low(&mut self) {
let inner = &mut self.inner;
handle_gpio_output!(inner, target, { target.set_low() })
}
fn set_high(&mut self) -> Result<(), Self::Error> {
/// Drives the pin high.
#[inline]
pub fn set_high(&mut self) {
let inner = &mut self.inner;
handle_gpio_output!(inner, target, { target.set_high() })
}
}
#[cfg(feature = "embedded-hal-02")]
impl<MODE, TYPE> embedded_hal_02::digital::v2::StatefulOutputPin for AnyPin<Output<MODE>, TYPE> {
fn is_set_high(&self) -> Result<bool, Self::Error> {
// TODO: add `set_state(PinState)`
// Drives the pin high or low depending on the provided value.
/// Is the pin in drive high mode?
#[inline]
pub fn is_set_high(&self) -> bool {
let inner = &self.inner;
handle_gpio_output!(inner, target, { target.is_set_high() })
}
fn is_set_low(&self) -> Result<bool, Self::Error> {
/// Is the pin in drive low mode?
#[inline]
pub fn is_set_low(&self) -> bool {
let inner = &self.inner;
handle_gpio_output!(inner, target, { target.is_set_low() })
}
}
#[cfg(feature = "embedded-hal-02")]
impl<MODE, TYPE> embedded_hal_02::digital::v2::ToggleableOutputPin for AnyPin<Output<MODE>, TYPE> {
type Error = core::convert::Infallible;
fn toggle(&mut self) -> Result<(), Self::Error> {
/// Toggle pin output.
#[inline]
pub fn toggle(&mut self) {
let inner = &mut self.inner;
handle_gpio_output!(inner, target, { target.toggle() })
}
}
#[cfg(feature = "embedded-hal")]
impl<MODE, TYPE> embedded_hal::digital::ErrorType for AnyPin<Output<MODE>, TYPE> {
type Error = core::convert::Infallible;
}
#[cfg(feature = "embedded-hal")]
impl<MODE, TYPE> embedded_hal::digital::OutputPin for AnyPin<Output<MODE>, TYPE> {
fn set_low(&mut self) -> Result<(), Self::Error> {
let inner = &mut self.inner;
handle_gpio_output!(inner, target, { target.set_low() })
}
fn set_high(&mut self) -> Result<(), Self::Error> {
let inner = &mut self.inner;
handle_gpio_output!(inner, target, { target.set_high() })
}
}
#[cfg(feature = "embedded-hal")]
impl<MODE, TYPE> embedded_hal::digital::StatefulOutputPin for AnyPin<Output<MODE>, TYPE> {
fn is_set_high(&mut self) -> Result<bool, Self::Error> {
let inner = &mut self.inner;
handle_gpio_output!(inner, target, { target.is_set_high() })
}
fn is_set_low(&mut self) -> Result<bool, Self::Error> {
let inner = &mut self.inner;
handle_gpio_output!(inner, target, { target.is_set_low() })
}
}
#[cfg(feature = "async")]
impl<MODE, TYPE> embedded_hal_async::digital::Wait for AnyPin<Input<MODE>, TYPE> {
async fn wait_for_high(&mut self) -> Result<(), Self::Error> {
impl<MODE, TYPE> AnyPin<Input<MODE>, TYPE> {
/// Wait until the pin is high. If it is already high, return immediately.
pub async fn wait_for_high(&mut self) {
let inner = &mut self.inner;
handle_gpio_input!(inner, target, { target.wait_for_high().await })
}
async fn wait_for_low(&mut self) -> Result<(), Self::Error> {
/// Wait until the pin is low. If it is already low, return immediately.
pub async fn wait_for_low(&mut self) {
let inner = &mut self.inner;
handle_gpio_input!(inner, target, { target.wait_for_low().await })
}
async fn wait_for_rising_edge(&mut self) -> Result<(), Self::Error> {
/// Wait for the pin to undergo a transition from low to high.
pub async fn wait_for_rising_edge(&mut self) {
let inner = &mut self.inner;
handle_gpio_input!(inner, target, { target.wait_for_rising_edge().await })
}
async fn wait_for_falling_edge(&mut self) -> Result<(), Self::Error> {
/// Wait for the pin to undergo a transition from high to low.
pub async fn wait_for_falling_edge(&mut self) {
let inner = &mut self.inner;
handle_gpio_input!(inner, target, { target.wait_for_falling_edge().await })
}
async fn wait_for_any_edge(&mut self) -> Result<(), Self::Error> {
/// Wait for the pin to undergo any transition, i.e low to high OR high to
/// low.
pub async fn wait_for_any_edge(&mut self) {
let inner = &mut self.inner;
handle_gpio_input!(inner, target, { target.wait_for_any_edge().await })
}
@ -3138,7 +3019,6 @@ mod asynch {
use core::task::{Context, Poll};
use embassy_sync::waitqueue::AtomicWaker;
use embedded_hal_async::digital::Wait;
use super::*;
@ -3146,54 +3026,68 @@ mod asynch {
const NEW_AW: AtomicWaker = AtomicWaker::new();
static PIN_WAKERS: [AtomicWaker; NUM_PINS] = [NEW_AW; NUM_PINS];
impl<MODE, const GPIONUM: u8> Wait for GpioPin<Input<MODE>, GPIONUM>
impl<MODE, const GPIONUM: u8> GpioPin<Input<MODE>, GPIONUM>
where
Self: GpioProperties,
<Self as GpioProperties>::PinType: IsInputPin,
{
async fn wait_for_high(&mut self) -> Result<(), Self::Error> {
/// Wait until the pin is high. If it is already high, return
/// immediately.
pub async fn wait_for_high(&mut self) {
PinFuture::new(self, Event::HighLevel).await
}
async fn wait_for_low(&mut self) -> Result<(), Self::Error> {
/// Wait until the pin is low. If it is already low, return immediately.
pub async fn wait_for_low(&mut self) {
PinFuture::new(self, Event::LowLevel).await
}
async fn wait_for_rising_edge(&mut self) -> Result<(), Self::Error> {
/// Wait for the pin to undergo a transition from low to high.
pub async fn wait_for_rising_edge(&mut self) {
PinFuture::new(self, Event::RisingEdge).await
}
async fn wait_for_falling_edge(&mut self) -> Result<(), Self::Error> {
/// Wait for the pin to undergo a transition from high to low.
pub async fn wait_for_falling_edge(&mut self) {
PinFuture::new(self, Event::FallingEdge).await
}
async fn wait_for_any_edge(&mut self) -> Result<(), Self::Error> {
/// Wait for the pin to undergo any transition, i.e low to high OR high
/// to low.
pub async fn wait_for_any_edge(&mut self) {
PinFuture::new(self, Event::AnyEdge).await
}
}
impl<const GPIONUM: u8> Wait for GpioPin<Output<OpenDrain>, GPIONUM>
impl<const GPIONUM: u8> GpioPin<Output<OpenDrain>, GPIONUM>
where
Self: GpioProperties,
<Self as GpioProperties>::PinType: IsInputPin + IsOutputPin,
{
async fn wait_for_high(&mut self) -> Result<(), Self::Error> {
/// Wait until the pin is high. If it is already high, return
/// immediately.
pub async fn wait_for_high(&mut self) {
PinFuture::new(self, Event::HighLevel).await
}
async fn wait_for_low(&mut self) -> Result<(), Self::Error> {
/// Wait until the pin is low. If it is already low, return immediately.
pub async fn wait_for_low(&mut self) {
PinFuture::new(self, Event::LowLevel).await
}
async fn wait_for_rising_edge(&mut self) -> Result<(), Self::Error> {
/// Wait for the pin to undergo a transition from low to high.
pub async fn wait_for_rising_edge(&mut self) {
PinFuture::new(self, Event::RisingEdge).await
}
async fn wait_for_falling_edge(&mut self) -> Result<(), Self::Error> {
/// Wait for the pin to undergo a transition from high to low.
pub async fn wait_for_falling_edge(&mut self) {
PinFuture::new(self, Event::FallingEdge).await
}
async fn wait_for_any_edge(&mut self) -> Result<(), Self::Error> {
/// Wait for the pin to undergo any transition, i.e low to high OR high
/// to low.
pub async fn wait_for_any_edge(&mut self) {
PinFuture::new(self, Event::AnyEdge).await
}
}
@ -3204,7 +3098,7 @@ mod asynch {
impl<'a, P> PinFuture<'a, P>
where
P: crate::gpio::Pin + embedded_hal::digital::ErrorType,
P: crate::gpio::Pin,
{
pub fn new(pin: &'a mut P, event: Event) -> Self {
pin.listen(event);
@ -3214,9 +3108,9 @@ mod asynch {
impl<'a, P> core::future::Future for PinFuture<'a, P>
where
P: crate::gpio::Pin + embedded_hal::digital::ErrorType,
P: crate::gpio::Pin,
{
type Output = Result<(), P::Error>;
type Output = ();
fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
PIN_WAKERS[self.pin.number() as usize].register(cx.waker());
@ -3224,7 +3118,7 @@ mod asynch {
// if pin is no longer listening its been triggered
// therefore the future has resolved
if !self.pin.is_listening() {
Poll::Ready(Ok(()))
Poll::Ready(())
} else {
Poll::Pending
}
@ -3278,3 +3172,334 @@ mod asynch {
}
}
}
#[cfg(feature = "embedded-hal-02")]
mod embedded_hal_02_impls {
use embedded_hal_02::digital::v2 as digital;
use super::*;
impl<MODE, const GPIONUM: u8> digital::InputPin for GpioPin<Input<MODE>, GPIONUM>
where
Self: GpioProperties,
{
type Error = core::convert::Infallible;
fn is_high(&self) -> Result<bool, Self::Error> {
Ok(self.is_high())
}
fn is_low(&self) -> Result<bool, Self::Error> {
Ok(self.is_low())
}
}
impl<const GPIONUM: u8> digital::InputPin for GpioPin<Output<OpenDrain>, GPIONUM>
where
Self: GpioProperties,
{
type Error = core::convert::Infallible;
fn is_high(&self) -> Result<bool, Self::Error> {
Ok(<Self as GpioProperties>::Bank::read_input() & (1 << (GPIONUM % 32)) != 0)
}
fn is_low(&self) -> Result<bool, Self::Error> {
Ok(self.is_low())
}
}
impl<MODE, const GPIONUM: u8> digital::OutputPin for GpioPin<Output<MODE>, GPIONUM>
where
Self: GpioProperties,
<Self as GpioProperties>::PinType: IsOutputPin,
{
type Error = core::convert::Infallible;
fn set_high(&mut self) -> Result<(), Self::Error> {
self.set_high();
Ok(())
}
fn set_low(&mut self) -> Result<(), Self::Error> {
self.set_low();
Ok(())
}
}
impl<MODE, const GPIONUM: u8> digital::StatefulOutputPin for GpioPin<Output<MODE>, GPIONUM>
where
Self: GpioProperties,
<Self as GpioProperties>::PinType: IsOutputPin,
{
fn is_set_high(&self) -> Result<bool, Self::Error> {
Ok(self.is_set_high())
}
fn is_set_low(&self) -> Result<bool, Self::Error> {
Ok(self.is_set_low())
}
}
impl<MODE, const GPIONUM: u8> digital::ToggleableOutputPin for GpioPin<Output<MODE>, GPIONUM>
where
Self: GpioProperties,
<Self as GpioProperties>::PinType: IsOutputPin,
{
type Error = core::convert::Infallible;
fn toggle(&mut self) -> Result<(), Self::Error> {
self.toggle();
Ok(())
}
}
impl<MODE, TYPE> digital::InputPin for AnyPin<Input<MODE>, TYPE> {
type Error = core::convert::Infallible;
fn is_high(&self) -> Result<bool, Self::Error> {
Ok(self.is_high())
}
fn is_low(&self) -> Result<bool, Self::Error> {
Ok(self.is_low())
}
}
impl<MODE, TYPE> digital::OutputPin for AnyPin<Output<MODE>, TYPE> {
type Error = core::convert::Infallible;
fn set_low(&mut self) -> Result<(), Self::Error> {
self.set_low();
Ok(())
}
fn set_high(&mut self) -> Result<(), Self::Error> {
self.set_high();
Ok(())
}
}
impl<MODE, TYPE> digital::StatefulOutputPin for AnyPin<Output<MODE>, TYPE> {
fn is_set_high(&self) -> Result<bool, Self::Error> {
Ok(self.is_set_high())
}
fn is_set_low(&self) -> Result<bool, Self::Error> {
Ok(self.is_set_low())
}
}
impl<MODE, TYPE> digital::ToggleableOutputPin for AnyPin<Output<MODE>, TYPE> {
type Error = core::convert::Infallible;
fn toggle(&mut self) -> Result<(), Self::Error> {
self.toggle();
Ok(())
}
}
}
#[cfg(feature = "embedded-hal")]
mod embedded_hal_impls {
use embedded_hal::digital;
use super::*;
impl<MODE, const GPIONUM: u8> digital::ErrorType for GpioPin<Input<MODE>, GPIONUM>
where
Self: GpioProperties,
{
type Error = core::convert::Infallible;
}
impl<MODE, const GPIONUM: u8> digital::InputPin for GpioPin<Input<MODE>, GPIONUM>
where
Self: GpioProperties,
{
fn is_high(&mut self) -> Result<bool, Self::Error> {
Ok(Self::is_high(self))
}
fn is_low(&mut self) -> Result<bool, Self::Error> {
Ok(Self::is_low(self))
}
}
impl<const GPIONUM: u8> digital::InputPin for GpioPin<Output<OpenDrain>, GPIONUM>
where
Self: GpioProperties,
<Self as GpioProperties>::PinType: IsOutputPin,
{
fn is_high(&mut self) -> Result<bool, Self::Error> {
Ok(Self::is_high(self))
}
fn is_low(&mut self) -> Result<bool, Self::Error> {
Ok(Self::is_low(self))
}
}
impl<MODE, const GPIONUM: u8> digital::ErrorType for GpioPin<Output<MODE>, GPIONUM>
where
Self: GpioProperties,
<Self as GpioProperties>::PinType: IsOutputPin,
{
type Error = core::convert::Infallible;
}
impl<MODE, const GPIONUM: u8> digital::OutputPin for GpioPin<Output<MODE>, GPIONUM>
where
Self: GpioProperties,
<Self as GpioProperties>::PinType: IsOutputPin,
{
fn set_low(&mut self) -> Result<(), Self::Error> {
self.set_low();
Ok(())
}
fn set_high(&mut self) -> Result<(), Self::Error> {
self.set_high();
Ok(())
}
}
impl<MODE, const GPIONUM: u8> digital::StatefulOutputPin for GpioPin<Output<MODE>, GPIONUM>
where
Self: GpioProperties,
<Self as GpioProperties>::PinType: IsOutputPin,
{
fn is_set_high(&mut self) -> Result<bool, Self::Error> {
Ok(Self::is_set_high(self))
}
fn is_set_low(&mut self) -> Result<bool, Self::Error> {
Ok(Self::is_set_low(self))
}
}
impl<MODE, TYPE> digital::ErrorType for AnyPin<Input<MODE>, TYPE> {
type Error = core::convert::Infallible;
}
impl<MODE, TYPE> digital::InputPin for AnyPin<Input<MODE>, TYPE> {
fn is_high(&mut self) -> Result<bool, Self::Error> {
Ok(Self::is_high(self))
}
fn is_low(&mut self) -> Result<bool, Self::Error> {
Ok(Self::is_low(self))
}
}
impl<MODE, TYPE> digital::ErrorType for AnyPin<Output<MODE>, TYPE> {
type Error = core::convert::Infallible;
}
impl<MODE, TYPE> digital::OutputPin for AnyPin<Output<MODE>, TYPE> {
fn set_low(&mut self) -> Result<(), Self::Error> {
self.set_low();
Ok(())
}
fn set_high(&mut self) -> Result<(), Self::Error> {
self.set_high();
Ok(())
}
}
impl<MODE, TYPE> digital::StatefulOutputPin for AnyPin<Output<MODE>, TYPE> {
fn is_set_high(&mut self) -> Result<bool, Self::Error> {
Ok(Self::is_set_high(self))
}
fn is_set_low(&mut self) -> Result<bool, Self::Error> {
Ok(Self::is_set_low(self))
}
}
}
#[cfg(feature = "embedded-hal")]
#[cfg(feature = "async")]
mod embedded_hal_async_impls {
use embedded_hal_async::digital::Wait;
use super::*;
impl<MODE, const GPIONUM: u8> Wait for GpioPin<Input<MODE>, GPIONUM>
where
Self: GpioProperties,
<Self as GpioProperties>::PinType: IsInputPin,
{
async fn wait_for_high(&mut self) -> Result<(), Self::Error> {
self.wait_for_high().await;
Ok(())
}
async fn wait_for_low(&mut self) -> Result<(), Self::Error> {
self.wait_for_low().await;
Ok(())
}
async fn wait_for_rising_edge(&mut self) -> Result<(), Self::Error> {
self.wait_for_rising_edge().await;
Ok(())
}
async fn wait_for_falling_edge(&mut self) -> Result<(), Self::Error> {
self.wait_for_falling_edge().await;
Ok(())
}
async fn wait_for_any_edge(&mut self) -> Result<(), Self::Error> {
self.wait_for_any_edge().await;
Ok(())
}
}
impl<const GPIONUM: u8> Wait for GpioPin<Output<OpenDrain>, GPIONUM>
where
Self: GpioProperties,
<Self as GpioProperties>::PinType: IsInputPin + IsOutputPin,
{
async fn wait_for_high(&mut self) -> Result<(), Self::Error> {
self.wait_for_high().await;
Ok(())
}
async fn wait_for_low(&mut self) -> Result<(), Self::Error> {
self.wait_for_low().await;
Ok(())
}
async fn wait_for_rising_edge(&mut self) -> Result<(), Self::Error> {
self.wait_for_rising_edge().await;
Ok(())
}
async fn wait_for_falling_edge(&mut self) -> Result<(), Self::Error> {
self.wait_for_falling_edge().await;
Ok(())
}
async fn wait_for_any_edge(&mut self) -> Result<(), Self::Error> {
self.wait_for_any_edge().await;
Ok(())
}
}
impl<MODE, TYPE> embedded_hal_async::digital::Wait for AnyPin<Input<MODE>, TYPE> {
async fn wait_for_high(&mut self) -> Result<(), Self::Error> {
self.wait_for_high().await;
Ok(())
}
async fn wait_for_low(&mut self) -> Result<(), Self::Error> {
self.wait_for_low().await;
Ok(())
}
async fn wait_for_rising_edge(&mut self) -> Result<(), Self::Error> {
self.wait_for_rising_edge().await;
Ok(())
}
async fn wait_for_falling_edge(&mut self) -> Result<(), Self::Error> {
self.wait_for_falling_edge().await;
Ok(())
}
async fn wait_for_any_edge(&mut self) -> Result<(), Self::Error> {
self.wait_for_any_edge().await;
Ok(())
}
}
}

View File

@ -3,12 +3,10 @@
//! This assumes that a LED is connected to the pin assigned to `led`. (GPIO0)
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
//% FEATURES: embedded-hal-02
#![no_std]
#![no_main]
use embedded_hal_02::digital::v2::{OutputPin, ToggleableOutputPin};
use esp_backtrace as _;
use esp_hal::{clock::ClockControl, delay::Delay, gpio::IO, peripherals::Peripherals, prelude::*};
@ -20,18 +18,18 @@ fn main() -> ! {
// Set GPIO0 as an output, and set its state high initially.
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
let mut led = io.pins.gpio0.into_push_pull_output();
let mut led = io.pins.gpio8.into_push_pull_output();
led.set_high().unwrap();
led.set_high();
// Initialize the Delay peripheral, and use it to toggle the LED state in a
// loop.
let delay = Delay::new(&clocks);
loop {
led.toggle().unwrap();
led.toggle();
delay.delay_millis(500);
led.toggle().unwrap();
led.toggle();
// or using `fugit` duration
delay.delay(2.secs());
}

View File

@ -52,10 +52,10 @@ fn main() -> ! {
fn toggle_pins(leds: &mut [AnyPin<Output<PushPull>>], button: &AnyPin<Input<PullDown>>) {
for pin in leds.iter_mut() {
pin.toggle().unwrap();
pin.toggle();
}
if button.is_low().unwrap() {
if button.is_low() {
esp_println::println!("Button pressed");
}
}

View File

@ -43,10 +43,10 @@ async fn control_led(
loop {
if control.wait().await {
esp_println::println!("LED on");
led.set_low().unwrap();
led.set_low();
} else {
esp_println::println!("LED off");
led.set_high().unwrap();
led.set_high();
}
}
}

View File

@ -59,10 +59,10 @@ async fn control_led(
loop {
if control.wait().await {
esp_println::println!("LED on");
led.set_low().unwrap();
led.set_low();
} else {
esp_println::println!("LED off");
led.set_high().unwrap();
led.set_high();
}
}
}

View File

@ -31,7 +31,7 @@ compile_error!("Run this example in release mode");
async fn signal_task(mut pin: Gpio5<Output<PushPull>>) {
loop {
for _ in 0..10 {
pin.toggle().unwrap();
pin.toggle();
Timer::after(Duration::from_micros(10)).await;
}
Timer::after(Duration::from_millis(1000)).await;

View File

@ -40,7 +40,7 @@ async fn main(_spawner: Spawner) {
loop {
esp_println::println!("Waiting...");
input.wait_for_rising_edge().await.unwrap();
input.wait_for_rising_edge().await;
esp_println::println!("Ping!");
Timer::after(Duration::from_millis(100)).await;
}

View File

@ -23,7 +23,7 @@ fn main() -> ! {
let mut led = io.pins.gpio1.into_push_pull_output();
let button = io.pins.gpio9.into_pull_down_input();
led.set_high().unwrap();
led.set_high();
// setup ETM
let gpio_ext = GpioEtmChannels::new(peripherals.GPIO_SD);

View File

@ -4,7 +4,6 @@
//! It also blinks an LED like the blinky example.
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
//% FEATURES: embedded-hal-02
#![no_std]
#![no_main]
@ -12,7 +11,6 @@
use core::cell::RefCell;
use critical_section::Mutex;
use embedded_hal_02::digital::v2::{OutputPin, ToggleableOutputPin};
use esp_backtrace as _;
use esp_hal::{
clock::ClockControl,
@ -50,14 +48,14 @@ fn main() -> ! {
button.listen(Event::FallingEdge);
BUTTON.borrow_ref_mut(cs).replace(button)
});
led.set_high().unwrap();
led.set_high();
// Initialize the Delay peripheral, and use it to toggle the LED state in a
// loop.
let delay = Delay::new(&clocks);
loop {
led.toggle().unwrap();
led.toggle();
delay.delay_millis(500);
}
}

View File

@ -18,12 +18,10 @@
//! D7 GPIO15
//% CHIPS: esp32s3
//% FEATURES: embedded-hal-02
#![no_std]
#![no_main]
use embedded_hal_02::digital::v2::OutputPin;
use esp_backtrace as _;
use esp_hal::{
clock::ClockControl,
@ -97,9 +95,9 @@ fn main() -> ! {
// https://gist.github.com/sukesh-ak/610508bc84779a26efdcf969bf51a2d1
// https://github.com/lovyan03/LovyanGFX/blob/302169a6f23e9a2a6451f03311c366d182193831/src/lgfx/v1/panel/Panel_ST7796.hpp#L28
reset.set_low().unwrap();
reset.set_low();
delay.delay_micros(8_000);
reset.set_high().unwrap();
reset.set_high();
delay.delay_micros(64_000);
// const CMD_FRMCTR1: u8 = 0xB1;
@ -210,7 +208,7 @@ fn main() -> ! {
const RED: u16 = 0b00000_000000_11111;
const BLUE: u16 = 0b11111_000000_00000;
backlight.set_high().unwrap();
backlight.set_high();
let total_pixels = width as usize * height as usize;
let total_bytes = total_pixels * 2;

View File

@ -2,12 +2,10 @@
//! Connect GPIO5 to GPIO4
//% CHIPS: esp32 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
//% FEATURES: embedded-hal-02
#![no_std]
#![no_main]
use embedded_hal_02::digital::v2::OutputPin;
use esp_backtrace as _;
use esp_hal::{
clock::ClockControl,
@ -75,9 +73,9 @@ fn main() -> ! {
// simulate input
for i in 0u32..5u32 {
out.set_high().unwrap();
out.set_high();
delay.delay_micros(i * 10 + 20);
out.set_low().unwrap();
out.set_low();
delay.delay_micros(i * 20 + 20);
}

View File

@ -61,9 +61,9 @@ fn main() -> ! {
let mut master_mosi = io.pins.gpio8.into_push_pull_output();
let slave_cs = io.pins.gpio3;
let mut master_cs = io.pins.gpio9.into_push_pull_output();
master_cs.set_high().unwrap();
master_sclk.set_low().unwrap();
master_mosi.set_low().unwrap();
master_cs.set_high();
master_sclk.set_low();
master_mosi.set_low();
let dma = Dma::new(peripherals.DMA);
let dma_channel = dma.channel0;
@ -115,31 +115,31 @@ fn main() -> ! {
// Bit-bang out the contents of master_send and read into master_receive
// as quickly as manageable. MSB first. Mode 0, so sampled on the rising
// edge and set on the falling edge.
master_cs.set_low().unwrap();
master_cs.set_low();
for (j, v) in master_send.iter().enumerate() {
let mut b = *v;
let mut rb = 0u8;
for _ in 0..8 {
if b & 128 != 0 {
master_mosi.set_high().unwrap();
master_mosi.set_high();
} else {
master_mosi.set_low().unwrap();
master_mosi.set_low();
}
master_sclk.set_low().unwrap();
master_sclk.set_low();
b <<= 1;
rb <<= 1;
// NB: adding about 24 NOPs here makes the clock's duty cycle
// run at about 50% ... but we don't strictly need the delay,
// either.
master_sclk.set_high().unwrap();
if master_miso.is_high().unwrap() {
master_sclk.set_high();
if master_miso.is_high() {
rb |= 1;
}
}
master_receive[j] = rb;
}
master_cs.set_high().unwrap();
master_sclk.set_low().unwrap();
master_cs.set_high();
master_sclk.set_low();
// the buffers and spi is moved into the transfer and we can get it back via
// `wait`
transfer.wait().unwrap();
@ -155,23 +155,23 @@ fn main() -> ! {
slave_receive.fill(0xff);
let transfer = spi.dma_read(&mut slave_receive).unwrap();
master_cs.set_high().unwrap();
master_cs.set_high();
master_cs.set_low().unwrap();
master_cs.set_low();
for v in master_send.iter() {
let mut b = *v;
for _ in 0..8 {
if b & 128 != 0 {
master_mosi.set_high().unwrap();
master_mosi.set_high();
} else {
master_mosi.set_low().unwrap();
master_mosi.set_low();
}
b <<= 1;
master_sclk.set_low().unwrap();
master_sclk.set_high().unwrap();
master_sclk.set_low();
master_sclk.set_high();
}
}
master_cs.set_high().unwrap();
master_cs.set_high();
transfer.wait().unwrap();
println!(
"slave got {:x?} .. {:x?}",
@ -184,20 +184,20 @@ fn main() -> ! {
master_receive.fill(0);
master_cs.set_low().unwrap();
master_cs.set_low();
for (j, _) in master_send.iter().enumerate() {
let mut rb = 0u8;
for _ in 0..8 {
master_sclk.set_low().unwrap();
master_sclk.set_low();
rb <<= 1;
master_sclk.set_high().unwrap();
if master_miso.is_high().unwrap() {
master_sclk.set_high();
if master_miso.is_high() {
rb |= 1;
}
}
master_receive[j] = rb;
}
master_cs.set_high().unwrap();
master_cs.set_high();
transfer.wait().unwrap();
println!(

View File

@ -11,7 +11,6 @@ use core::cell::RefCell;
use critical_section::Mutex;
use defmt_rtt as _;
use embedded_hal::digital::{InputPin as _, OutputPin as _, StatefulOutputPin as _};
use esp_backtrace as _;
use esp_hal::{
clock::ClockControl,
@ -74,7 +73,6 @@ pub fn interrupt_handler() {
mod tests {
use defmt::assert_eq;
use embassy_time::{Duration, Timer};
use embedded_hal_async::digital::Wait;
use esp_hal::gpio::{Event, Pin};
use portable_atomic::{AtomicUsize, Ordering};
@ -84,7 +82,7 @@ mod tests {
fn init() -> Context {
let mut ctx = Context::init();
// make sure tests don't interfere with each other
ctx.io4.set_low().ok();
ctx.io4.set_low();
ctx
}
@ -97,15 +95,15 @@ mod tests {
embassy_futures::select::select(
async {
loop {
io2.wait_for_rising_edge().await.unwrap();
io2.wait_for_rising_edge().await;
counter.fetch_add(1, Ordering::SeqCst);
}
},
async {
for _ in 0..5 {
io4.set_high().unwrap();
io4.set_high();
Timer::after(Duration::from_millis(25)).await;
io4.set_low().unwrap();
io4.set_low();
Timer::after(Duration::from_millis(25)).await;
}
},
@ -128,30 +126,30 @@ mod tests {
}
#[test]
fn test_gpio_input(mut ctx: Context) {
fn test_gpio_input(ctx: Context) {
// `InputPin`:
assert_eq!(ctx.io2.is_low(), Ok(true));
assert_eq!(ctx.io2.is_high(), Ok(false));
assert_eq!(ctx.io2.is_low(), true);
assert_eq!(ctx.io2.is_high(), false);
}
#[test]
fn test_gpio_output(mut ctx: Context) {
// `StatefulOutputPin`:
assert_eq!(ctx.io4.is_set_low(), Ok(true));
assert_eq!(ctx.io4.is_set_high(), Ok(false));
assert!(ctx.io4.set_high().is_ok());
assert_eq!(ctx.io4.is_set_low(), Ok(false));
assert_eq!(ctx.io4.is_set_high(), Ok(true));
assert_eq!(ctx.io4.is_set_low(), true);
assert_eq!(ctx.io4.is_set_high(), false);
ctx.io4.set_high();
assert_eq!(ctx.io4.is_set_low(), false);
assert_eq!(ctx.io4.is_set_high(), true);
// `ToggleableOutputPin`:
assert!(ctx.io4.toggle().is_ok());
assert_eq!(ctx.io4.is_set_low(), Ok(true));
assert_eq!(ctx.io4.is_set_high(), Ok(false));
assert!(ctx.io4.toggle().is_ok());
assert_eq!(ctx.io4.is_set_low(), Ok(false));
assert_eq!(ctx.io4.is_set_high(), Ok(true));
ctx.io4.toggle();
assert_eq!(ctx.io4.is_set_low(), true);
assert_eq!(ctx.io4.is_set_high(), false);
ctx.io4.toggle();
assert_eq!(ctx.io4.is_set_low(), false);
assert_eq!(ctx.io4.is_set_high(), true);
// Leave in initial state for next test
assert!(ctx.io4.toggle().is_ok());
ctx.io4.toggle();
}
#[test]
@ -161,23 +159,23 @@ mod tests {
ctx.io2.listen(Event::AnyEdge);
INPUT_PIN.borrow_ref_mut(cs).replace(ctx.io2);
});
assert!(ctx.io4.set_high().is_ok());
ctx.io4.set_high();
ctx.delay.delay_millis(1);
assert!(ctx.io4.set_low().is_ok());
ctx.io4.set_low();
ctx.delay.delay_millis(1);
assert!(ctx.io4.set_high().is_ok());
ctx.io4.set_high();
ctx.delay.delay_millis(1);
assert!(ctx.io4.set_low().is_ok());
ctx.io4.set_low();
ctx.delay.delay_millis(1);
assert!(ctx.io4.set_high().is_ok());
ctx.io4.set_high();
ctx.delay.delay_millis(1);
assert!(ctx.io4.set_low().is_ok());
ctx.io4.set_low();
ctx.delay.delay_millis(1);
assert!(ctx.io4.set_high().is_ok());
ctx.io4.set_high();
ctx.delay.delay_millis(1);
assert!(ctx.io4.set_low().is_ok());
ctx.io4.set_low();
ctx.delay.delay_millis(1);
assert!(ctx.io4.set_high().is_ok());
ctx.io4.set_high();
ctx.delay.delay_millis(1);
let count = critical_section::with(|cs| *COUNTER.borrow_ref(cs));
@ -194,32 +192,32 @@ mod tests {
let mut io4 = ctx.io4.into_open_drain_output();
io4.internal_pull_up(true);
assert!(io2.set_high().is_ok());
assert!(io4.set_high().is_ok());
io2.set_high();
io4.set_high();
ctx.delay.delay_millis(1);
assert_eq!(io2.is_high(), Ok(true));
assert_eq!(io4.is_high(), Ok(true));
assert_eq!(io2.is_high(), true);
assert_eq!(io4.is_high(), true);
assert!(io2.set_low().is_ok());
assert!(io4.set_high().is_ok());
io2.set_low();
io4.set_high();
ctx.delay.delay_millis(1);
assert_eq!(io2.is_low(), Ok(true));
assert_eq!(io4.is_low(), Ok(true));
assert_eq!(io2.is_low(), true);
assert_eq!(io4.is_low(), true);
assert!(io2.set_high().is_ok());
assert!(io4.set_high().is_ok());
io2.set_high();
io4.set_high();
ctx.delay.delay_millis(1);
assert_eq!(io2.is_high(), Ok(true));
assert_eq!(io4.is_high(), Ok(true));
assert_eq!(io2.is_high(), true);
assert_eq!(io4.is_high(), true);
assert!(io2.set_high().is_ok());
assert!(io4.set_low().is_ok());
io2.set_high();
io4.set_low();
ctx.delay.delay_millis(1);
assert_eq!(io2.is_low(), Ok(true));
assert_eq!(io4.is_low(), Ok(true));
assert_eq!(io2.is_low(), true);
assert_eq!(io4.is_low(), true);
}
}