Module hw

Module hw 

Source
Expand description

This module provides hardware abstraction traits that can be used by display drivers. You should implement all the traits on a single struct, so that you can pass this one hardware struct to your display driver.

Example that remains generic over the specific SPI bus:

use embassy_embedded_hal::shared_bus::asynch::spi::SpiDevice as EmbassySpiDevice;
use embassy_embedded_hal::shared_bus::SpiDeviceError;
use embassy_rp::gpio::{Input, Level, Output, Pin, Pull};
use embassy_rp::spi;
use embassy_rp::Peri;
use embassy_sync::blocking_mutex::raw::NoopRawMutex;
use embedded_hal::digital::PinState;
use epd_waveshare_async::hw::{BusyHw, DcHw, DelayHw, ErrorHw, ResetHw, SpiHw};
use thiserror::Error as ThisError;

/// Defines the hardware to use for connecting to the display.
pub struct DisplayHw<'a, SPI> {
    dc: Output<'a>,
    reset: Output<'a>,
    busy: Input<'a>,
    delay: embassy_time::Delay,
    _spi_type: PhantomData<SPI>,
}

impl<'a, SPI: spi::Instance> DisplayHw<'a, SPI> {
    pub fn new<DC: Pin, RESET: Pin, BUSY: Pin>(
        dc: Peri<'a, DC>,
        reset: Peri<'a, RESET>,
        busy: Peri<'a, BUSY>,
    ) -> Self {
        let dc = Output::new(dc, Level::High);
        let reset = Output::new(reset, Level::High);
        let busy = Input::new(busy, Pull::Up);

        Self {
            dc,
            reset,
            busy,
            delay: embassy_time::Delay,
            _spi_type: PhantomData,
        }
    }
}

impl<'a, SPI> ErrorHw for DisplayHw<'a, SPI> {
    type Error = Error;
}

impl<'a, SPI> DcHw for DisplayHw<'a, SPI> {
    type Dc = Output<'a>;

    fn dc(&mut self) -> &mut Self::Dc {
        &mut self.dc
    }
}

impl<'a, SPI> ResetHw for DisplayHw<'a, SPI> {
    type Reset = Output<'a>;

    fn reset(&mut self) -> &mut Self::Reset {
        &mut self.reset
    }
}

impl<'a, SPI> BusyHw for DisplayHw<'a, SPI> {
    type Busy = Input<'a>;

    fn busy(&mut self) -> &mut Self::Busy {
        &mut self.busy
    }

    fn busy_when(&self) -> embedded_hal::digital::PinState {
        epd_waveshare_async::epd2in9::DEFAULT_BUSY_WHEN
    }
}

impl<'a, SPI> DelayHw for DisplayHw<'a, SPI> {
    type Delay = embassy_time::Delay;

    fn delay(&mut self) -> &mut Self::Delay {
        &mut self.delay
    }
}

impl<'a, SPI: spi::Instance + 'a> SpiHw for DisplayHw<'a, SPI> {
    type Spi = EmbassySpiDevice<'a, NoopRawMutex, spi::Spi<'a, SPI, spi::Async>, Output<'a>>;
}

type RawSpiError = SpiDeviceError<spi::Error, Infallible>;

#[derive(Debug, ThisError)]
pub enum Error {
    #[error("SPI error: {0:?}")]
    SpiError(RawSpiError),
}

impl From<Infallible> for Error {
    fn from(_: Infallible) -> Self {
        unreachable!()
    }
}

impl From<RawSpiError> for Error {
    fn from(e: RawSpiError) -> Self {
        Error::SpiError(e)
    }
}

Traitsยง

BusyHw
Provides access to the Busy pin for EPD status monitoring.
DcHw
Provides access to the Data/Command pin for EPD control.
DelayHw
Provides access to delay functionality for EPD timing control.
ErrorHw
Provides access to a shared error type.
ResetHw
Provides access to the Reset pin for EPD control.
SpiHw
Describes the SPI hardware to use for interacting with the EPD.