improved traits, now it should be ready to convert 4.2"
parent
ceee294cda
commit
80e5c0ffb1
|
|
@ -1,5 +1,8 @@
|
||||||
//! SPI Commands for the Waveshare 2.9" E-Ink Display
|
//! SPI Commands for the Waveshare 2.9" E-Ink Display
|
||||||
|
|
||||||
|
use interface;
|
||||||
|
|
||||||
|
|
||||||
/// EPD2IN9 commands
|
/// EPD2IN9 commands
|
||||||
///
|
///
|
||||||
/// Should rarely (never?) be needed directly.
|
/// Should rarely (never?) be needed directly.
|
||||||
|
|
@ -10,7 +13,7 @@
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub(crate) enum Command {
|
pub enum Command {
|
||||||
/// Driver Output control
|
/// Driver Output control
|
||||||
/// 3 Databytes:
|
/// 3 Databytes:
|
||||||
/// A[7:0]
|
/// A[7:0]
|
||||||
|
|
@ -39,9 +42,9 @@ pub(crate) enum Command {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
impl Command {
|
impl interface::Command for Command {
|
||||||
/// Returns the address of the command
|
/// Returns the address of the command
|
||||||
pub fn addr(self) -> u8 {
|
fn address(self) -> u8 {
|
||||||
self as u8
|
self as u8
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -49,11 +52,12 @@ impl Command {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::Command;
|
||||||
|
use interface::Command as CommandTrait;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn command_addr() {
|
fn command_addr() {
|
||||||
//assert_eq!(Command::POWER_SAVING.addr(), 0xE3);
|
assert_eq!(Command::DRIVER_OUTPUT_CONTROL.address(), 0x01);
|
||||||
|
|
||||||
//assert_eq!(Command::PANEL_SETTING.addr(), 0x00);
|
//assert_eq!(Command::PANEL_SETTING.addr(), 0x00);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,6 @@ use hal::{
|
||||||
spi::Write,
|
spi::Write,
|
||||||
delay::*
|
delay::*
|
||||||
},
|
},
|
||||||
spi::{Mode, Phase, Polarity},
|
|
||||||
digital::*
|
digital::*
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -69,7 +68,7 @@ use interface::*;
|
||||||
|
|
||||||
use interface::data_interface::DataInterface;
|
use interface::data_interface::DataInterface;
|
||||||
|
|
||||||
/// EPD4in2 driver
|
/// EPD2in9 driver
|
||||||
///
|
///
|
||||||
pub struct EPD2in9<SPI, CS, BUSY, DC, RST, D> {
|
pub struct EPD2in9<SPI, CS, BUSY, DC, RST, D> {
|
||||||
/// SPI
|
/// SPI
|
||||||
|
|
@ -80,7 +79,6 @@ pub struct EPD2in9<SPI, CS, BUSY, DC, RST, D> {
|
||||||
height: u32,
|
height: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl<SPI, CS, BUSY, DC, RST, D, E> EPD2in9<SPI, CS, BUSY, DC, RST, D>
|
impl<SPI, CS, BUSY, DC, RST, D, E> EPD2in9<SPI, CS, BUSY, DC, RST, D>
|
||||||
where
|
where
|
||||||
SPI: Write<u8, Error = E>,
|
SPI: Write<u8, Error = E>,
|
||||||
|
|
@ -103,6 +101,7 @@ where
|
||||||
RST: OutputPin,
|
RST: OutputPin,
|
||||||
D: DelayUs<u16> + DelayMs<u16>,
|
D: DelayUs<u16> + DelayMs<u16>,
|
||||||
{
|
{
|
||||||
|
|
||||||
fn get_width(&self) -> u32 {
|
fn get_width(&self) -> u32 {
|
||||||
self.width
|
self.width
|
||||||
}
|
}
|
||||||
|
|
@ -136,20 +135,45 @@ where
|
||||||
|
|
||||||
|
|
||||||
fn init(&mut self) -> Result<(), E> {
|
fn init(&mut self) -> Result<(), E> {
|
||||||
//TODO:
|
unimplemented!()
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
fn sleep(&mut self) -> Result<(), E> {
|
fn sleep(&mut self) -> Result<(), E> {
|
||||||
Ok(())
|
unimplemented!()
|
||||||
}
|
}
|
||||||
fn reset(&mut self) {
|
fn reset(&mut self) {
|
||||||
//TODO:
|
self.interface.reset()
|
||||||
}
|
}
|
||||||
fn wait_until_idle(&mut self) {
|
|
||||||
|
|
||||||
|
fn delay_ms(&mut self, delay: u16) {
|
||||||
|
self.interface.delay_ms(delay)
|
||||||
}
|
}
|
||||||
fn delay_ms(&mut self, delay: u32) {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
fn update_frame(&mut self, buffer: &[u8]) -> Result<(), E>{
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_partial_frame(&mut self, buffer: &[u8], x: u16, y: u16, width: u16, height: u16) -> Result<(), E>{
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn display_frame(&mut self) -> Result<(), E>{
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: add this abstraction function
|
||||||
|
// fn update_and_display_frame(&mut self, buffer: &[u8]) -> Result<(), E>;
|
||||||
|
|
||||||
|
|
||||||
|
fn clear_frame(&mut self) -> Result<(), E>{
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the backgroundcolor for various commands like [WaveshareInterface::clear_frame()](clear_frame())
|
||||||
|
fn set_background_color(&mut self, color: Color){
|
||||||
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ use hal::{
|
||||||
spi::Write,
|
spi::Write,
|
||||||
delay::*
|
delay::*
|
||||||
},
|
},
|
||||||
spi::{Mode, Phase, Polarity},
|
|
||||||
digital::*
|
digital::*
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -11,7 +10,7 @@ use interface::Command;
|
||||||
|
|
||||||
/// EPD4in2 driver
|
/// EPD4in2 driver
|
||||||
///
|
///
|
||||||
pub struct DataInterface<SPI, CS, BUSY, DC, RST, D> {
|
pub(crate) struct DataInterface<SPI, CS, BUSY, DC, RST, D> {
|
||||||
/// SPI
|
/// SPI
|
||||||
spi: SPI,
|
spi: SPI,
|
||||||
/// CS for SPI
|
/// CS for SPI
|
||||||
|
|
@ -36,7 +35,7 @@ where
|
||||||
RST: OutputPin,
|
RST: OutputPin,
|
||||||
D: DelayUs<u16> + DelayMs<u16>,
|
D: DelayUs<u16> + DelayMs<u16>,
|
||||||
{
|
{
|
||||||
pub fn new(spi: SPI, cs: CS, busy: BUSY, dc: DC, rst: RST, delay: D) -> Self {
|
pub(crate) fn new(spi: SPI, cs: CS, busy: BUSY, dc: DC, rst: RST, delay: D) -> Self {
|
||||||
DataInterface {spi, cs, busy, dc, rst, delay }
|
DataInterface {spi, cs, busy, dc, rst, delay }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -45,7 +44,7 @@ where
|
||||||
/// Enables direct interaction with the device with the help of [EPD4in2::send_data()](EPD4in2::send_data())
|
/// Enables direct interaction with the device with the help of [EPD4in2::send_data()](EPD4in2::send_data())
|
||||||
/// Should rarely be needed!
|
/// Should rarely be needed!
|
||||||
/// //TODO: make public?
|
/// //TODO: make public?
|
||||||
fn send_command<T: Command>(&mut self, command: T) -> Result<(), E> {
|
pub(crate) fn send_command<T: Command>(&mut self, command: T) -> Result<(), E> {
|
||||||
// low for commands
|
// low for commands
|
||||||
self.dc.set_low();
|
self.dc.set_low();
|
||||||
|
|
||||||
|
|
@ -61,7 +60,7 @@ where
|
||||||
///
|
///
|
||||||
/// Should rarely be needed!
|
/// Should rarely be needed!
|
||||||
/// //TODO: make public?
|
/// //TODO: make public?
|
||||||
fn send_data(&mut self, val: u8) -> Result<(), E> {
|
pub(crate) fn send_data(&mut self, val: u8) -> Result<(), E> {
|
||||||
// high for data
|
// high for data
|
||||||
self.dc.set_high();
|
self.dc.set_high();
|
||||||
|
|
||||||
|
|
@ -77,7 +76,7 @@ where
|
||||||
///
|
///
|
||||||
/// Should rarely be needed!
|
/// Should rarely be needed!
|
||||||
/// //TODO: make public?
|
/// //TODO: make public?
|
||||||
fn send_multiple_data(&mut self, data: &[u8]) -> Result<(), E> {
|
pub(crate) fn send_multiple_data(&mut self, data: &[u8]) -> Result<(), E> {
|
||||||
// high for data
|
// high for data
|
||||||
self.dc.set_high();
|
self.dc.set_high();
|
||||||
|
|
||||||
|
|
@ -88,7 +87,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
// spi write helper/abstraction function
|
// spi write helper/abstraction function
|
||||||
fn with_cs<F>(&mut self, f: F) -> Result<(), E>
|
pub(crate) fn with_cs<F>(&mut self, f: F) -> Result<(), E>
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut Self) -> Result<(), E>,
|
F: FnOnce(&mut Self) -> Result<(), E>,
|
||||||
{
|
{
|
||||||
|
|
@ -108,7 +107,7 @@ where
|
||||||
/// This is normally handled by the more complicated commands themselves,
|
/// 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
|
/// but in the case you send data and commands directly you might need to check
|
||||||
/// if the device is still busy
|
/// if the device is still busy
|
||||||
pub fn wait_until_idle(&mut self) {
|
pub(crate) fn wait_until_idle(&mut self) {
|
||||||
//low: busy, high: idle
|
//low: busy, high: idle
|
||||||
while self.busy.is_low() {
|
while self.busy.is_low() {
|
||||||
//TODO: shorten the time? it was 100 in the beginning
|
//TODO: shorten the time? it was 100 in the beginning
|
||||||
|
|
@ -117,17 +116,19 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Abstraction of setting the delay for simpler calls
|
/// Abstraction of setting the delay for simpler calls
|
||||||
pub fn delay_ms(&mut self, delay: u16) {
|
///
|
||||||
|
/// maximum delay ~65 seconds (u16:max in ms)
|
||||||
|
pub(crate) fn delay_ms(&mut self, delay: u16) {
|
||||||
self.delay.delay_ms(delay);
|
self.delay.delay_ms(delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resets the device.
|
/// Resets the device.
|
||||||
///
|
///
|
||||||
/// Often used to awake the module from deep sleep. See [EPD4in2::sleep()](EPD4in2::sleep())
|
/// Often used to awake the module from deep sleep. See [EPD4in2::sleep()](EPD4in2::sleep())
|
||||||
///
|
///
|
||||||
/// TODO: Takes at least 400ms of delay alone, can it be shortened?
|
/// TODO: Takes at least 400ms of delay alone, can it be shortened?
|
||||||
pub fn reset(&mut self) {
|
pub(crate) fn reset(&mut self) {
|
||||||
self.rst.set_low();
|
self.rst.set_low();
|
||||||
|
|
||||||
//TODO: why 200ms? (besides being in the waveshare code)
|
//TODO: why 200ms? (besides being in the waveshare code)
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@ use hal::{
|
||||||
digital::*
|
digital::*
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use drawing::color::Color;
|
||||||
|
|
||||||
pub mod data_interface;
|
pub mod data_interface;
|
||||||
|
|
||||||
//TODO: test spi mode
|
//TODO: test spi mode
|
||||||
|
|
@ -20,7 +22,7 @@ pub const SPI_MODE: Mode = Mode {
|
||||||
use core::marker::Sized;
|
use core::marker::Sized;
|
||||||
|
|
||||||
pub(crate) trait Command {
|
pub(crate) trait Command {
|
||||||
fn address(&self) -> u8;
|
fn address(self) -> u8;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait WaveshareInterface<SPI, CS, BUSY, DC, RST, D, E>
|
pub trait WaveshareInterface<SPI, CS, BUSY, DC, RST, D, E>
|
||||||
|
|
@ -34,7 +36,13 @@ pub trait WaveshareInterface<SPI, CS, BUSY, DC, RST, D, E>
|
||||||
{
|
{
|
||||||
/// Get the width of the display
|
/// Get the width of the display
|
||||||
fn get_width(&self) -> u32;
|
fn get_width(&self) -> u32;
|
||||||
|
|
||||||
|
/// Get the height of the display
|
||||||
fn get_height(&self) -> u32;
|
fn get_height(&self) -> u32;
|
||||||
|
|
||||||
|
/// 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(
|
fn new(
|
||||||
spi: SPI,
|
spi: SPI,
|
||||||
cs: CS,
|
cs: CS,
|
||||||
|
|
@ -44,13 +52,66 @@ pub trait WaveshareInterface<SPI, CS, BUSY, DC, RST, D, E>
|
||||||
delay: D
|
delay: D
|
||||||
) -> Result<Self, E>
|
) -> Result<Self, E>
|
||||||
where Self: Sized;
|
where Self: Sized;
|
||||||
|
|
||||||
|
/// This initialises the EPD and powers it up
|
||||||
|
///
|
||||||
|
/// This function is already called from [new()](WaveshareInterface::new())
|
||||||
|
///
|
||||||
|
/// 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(&mut self) -> Result<(), E>;
|
fn init(&mut self) -> Result<(), E>;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
fn update_frame(&mut self, buffer: &[u8]) -> Result<(), E>;
|
||||||
|
|
||||||
|
fn update_partial_frame(&mut self, buffer: &[u8], x: u16, y: u16, width: u16, height: u16) -> Result<(), E>;
|
||||||
|
|
||||||
|
/// Displays the frame data from SRAM
|
||||||
|
fn display_frame(&mut self) -> Result<(), E>;
|
||||||
|
|
||||||
|
// TODO: add this abstraction function
|
||||||
|
// fn update_and_display_frame(&mut self, buffer: &[u8]) -> Result<(), E>;
|
||||||
|
|
||||||
|
/// Clears the frame from the buffer
|
||||||
|
///
|
||||||
|
/// Uses the chosen background color
|
||||||
|
fn clear_frame(&mut self) -> Result<(), E>;
|
||||||
|
|
||||||
|
/// Sets the backgroundcolor for various commands like [clear_frame()](WaveshareInterface::clear_frame())
|
||||||
|
fn set_background_color(&mut self, color: Color);
|
||||||
|
|
||||||
|
|
||||||
|
/// 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 [reset()](WaveshareInterface::reset()) to awaken.
|
||||||
|
/// But as you need to power it up once more anyway you can also just directly use [init()](WaveshareInterface::init()) for resetting
|
||||||
|
/// and initialising which already contains the reset
|
||||||
fn sleep(&mut self) -> Result<(), E>;
|
fn sleep(&mut self) -> Result<(), E>;
|
||||||
|
|
||||||
|
/// Resets the device.
|
||||||
|
///
|
||||||
|
/// Often used to awake the module from deep sleep. See [sleep()](WaveshareInterface::sleep())
|
||||||
fn reset(&mut self);
|
fn reset(&mut self);
|
||||||
fn wait_until_idle(&mut self);
|
|
||||||
fn delay_ms(&mut self, delay: u32);
|
/// Abstraction of setting the delay for simpler calls
|
||||||
|
///
|
||||||
|
/// maximum delay ~65 seconds (u16:max in ms)
|
||||||
|
fn delay_ms(&mut self, delay: u16);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
-display_frame
|
||||||
|
-clear_frame
|
||||||
|
-set_full_frame
|
||||||
|
-set_partial_frame
|
||||||
|
|
||||||
|
//
|
||||||
|
-set_quick_lut?
|
||||||
|
-set_normal_mode
|
||||||
|
|
||||||
|
|
||||||
fn clear_frame(&mut self, reset_color: Option<Color>) -> Result<(), E>
|
fn clear_frame(&mut self, reset_color: Option<Color>) -> Result<(), E>
|
||||||
|
|
||||||
fn display_frame_quick(&mut self) -> Result<(), E>
|
fn display_frame_quick(&mut self) -> Result<(), E>
|
||||||
|
|
@ -75,31 +136,4 @@ pub trait WaveshareInterface<SPI, CS, BUSY, DC, RST, D, E>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub trait TestInterface
|
|
||||||
{
|
|
||||||
fn get_width(&self) -> u32;
|
|
||||||
fn get_height(&self) -> u32;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
struct testStruct {
|
|
||||||
width: u32,
|
|
||||||
height: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TestInterface for testStruct {
|
|
||||||
fn get_width(&self) -> u32 {
|
|
||||||
self.width
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_height(&self) -> u32 {
|
|
||||||
self.height
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Loading…
Reference in New Issue