You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
epd-waveshare/src/traits.rs

189 lines
5.7 KiB
Rust

use crate::color::Color;
use core::marker::Sized;
use embedded_hal::{
blocking::{delay::*, spi::Write},
digital::v2::*,
};
/// All commands need to have this trait which gives the address of the command
/// which needs to be send via SPI with activated CommandsPin (Data/Command Pin in CommandMode)
pub(crate) trait Command {
fn address(self) -> u8;
}
/// Seperates the different LUT for the Display Refresh process
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum RefreshLUT {
/// The "normal" full Lookuptable for the Refresh-Sequence
FULL,
/// The quick LUT where not the full refresh sequence is followed.
/// This might lead to some
QUICK,
}
impl Default for RefreshLUT {
fn default() -> Self {
RefreshLUT::FULL
}
}
pub(crate) trait InternalWiAdditions<SPI, CS, BUSY, DC, RST>
where
SPI: Write<u8>,
CS: OutputPin,
BUSY: InputPin,
DC: OutputPin,
RST: OutputPin,
{
/// This initialises the EPD and powers it up
///
/// This function is already called from
/// - [new()](WaveshareInterface::new())
/// - [`wake_up`]
///
///
/// This function calls [reset()](WaveshareInterface::reset()),
/// so you don't need to call reset your self when trying to wake your device up
/// after setting it to sleep.
fn init<DELAY: DelayMs<u8>>(
&mut self,
spi: &mut SPI,
delay: &mut DELAY,
) -> Result<(), SPI::Error>;
}
/// Functions to interact with three color panels
pub trait WaveshareThreeColorDisplay<SPI, CS, BUSY, DC, RST>:
WaveshareDisplay<SPI, CS, BUSY, DC, RST>
where
SPI: Write<u8>,
CS: OutputPin,
BUSY: InputPin,
DC: OutputPin,
RST: OutputPin,
{
/// Transmit data to the SRAM of the EPD
///
/// Updates both the black and the secondary color layers
fn update_color_frame(
&mut self,
spi: &mut SPI,
black: &[u8],
color: &[u8],
) -> Result<(), SPI::Error>;
}
/// All the functions to interact with the EPDs
///
/// This trait includes all public functions to use the EPDS
pub trait WaveshareDisplay<SPI, CS, BUSY, DC, RST>
where
SPI: Write<u8>,
CS: OutputPin,
BUSY: InputPin,
DC: OutputPin,
RST: OutputPin,
{
/// Creates a new driver from a SPI peripheral, CS Pin, Busy InputPin, DC
///
/// This already initialises the device. That means [init()](WaveshareInterface::init()) isn't needed directly afterwards
fn new<DELAY: DelayMs<u8>>(
spi: &mut SPI,
cs: CS,
busy: BUSY,
dc: DC,
rst: RST,
delay: &mut DELAY,
) -> Result<Self, SPI::Error>
where
Self: Sized;
/// Let the device enter deep-sleep mode to save power.
///
/// The deep sleep mode returns to standby with a hardware reset.
/// But you can also use [wake_up()](WaveshareInterface::wake_up()) to awaken.
/// But as you need to power it up once more anyway you can also just directly use [new()](WaveshareInterface::new()) for resetting
/// and initialising which already contains the reset
fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error>;
/// Wakes the device up from sleep
fn wake_up<DELAY: DelayMs<u8>>(
&mut self,
spi: &mut SPI,
delay: &mut DELAY,
) -> Result<(), SPI::Error>;
/// Sets the backgroundcolor for various commands like [clear_frame()](WaveshareInterface::clear_frame())
fn set_background_color(&mut self, color: Color);
/// Get current background color
fn background_color(&self) -> &Color;
/// Get the width of the display
fn width(&self) -> u32;
/// Get the height of the display
fn height(&self) -> u32;
/// Transmit a full frame to the SRAM of the EPD
fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error>;
/// Transmits partial data to the SRAM of the EPD
///
/// (x,y) is the top left corner
///
/// BUFFER needs to be of size: width / 8 * height !
fn update_partial_frame(
&mut self,
spi: &mut SPI,
buffer: &[u8],
x: u32,
y: u32,
width: u32,
height: u32,
) -> Result<(), SPI::Error>;
/// Displays the frame data from SRAM
///
/// This function waits until the device isn`t busy anymore
fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error>;
/// Clears the frame buffer on the EPD with the declared background color
///
/// The background color can be changed with [`set_background_color`]
fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error>;
/// Trait for using various Waveforms from different LUTs
/// E.g. for partial refreshes
///
/// A full refresh is needed after a certain amount of quick refreshes!
///
/// WARNING: Quick Refresh might lead to ghosting-effects/problems with your display. Especially for the 4.2in Display!
///
/// If None is used the old value will be loaded on the LUTs once more
fn set_lut(
&mut self,
spi: &mut SPI,
refresh_rate: Option<RefreshLUT>,
) -> Result<(), SPI::Error>;
/// Checks if the display is busy transmitting data
///
/// This is normally handled by the more complicated commands themselves,
/// but in the case you send data and commands directly you might need to check
/// if the device is still busy
fn is_busy(&self) -> bool;
}
/// Tiny optional extension trait
pub trait WaveshareDisplayExt<SPI, CS, BUSY, DC, RST>
where
SPI: Write<u8>,
CS: OutputPin,
BUSY: InputPin,
DC: OutputPin,
RST: OutputPin,
{
// provide a combined update&display and save some time (skipping a busy check in between)
fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error>;
}