Skip to main content

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.