7 changed files with 388 additions and 365 deletions
@ -0,0 +1,17 @@ |
|||||||
|
pub(crate) const WIDTH: usize = 128; |
||||||
|
pub(crate) const HEIGHT: usize = 296; |
||||||
|
|
||||||
|
// Original Waveforms from Waveshare
|
||||||
|
pub(crate) const LUT_FULL_UPDATE: [u8; 30] =[ |
||||||
|
0x02, 0x02, 0x01, 0x11, 0x12, 0x12, 0x22, 0x22,
|
||||||
|
0x66, 0x69, 0x69, 0x59, 0x58, 0x99, 0x99, 0x88,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xF8, 0xB4, 0x13, 0x51,
|
||||||
|
0x35, 0x51, 0x51, 0x19, 0x01, 0x00
|
||||||
|
]; |
||||||
|
|
||||||
|
pub(crate) const LUT_PARTIAL_UPDATE: [u8; 30] =[ |
||||||
|
0x10, 0x18, 0x18, 0x08, 0x18, 0x18, 0x08, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x13, 0x14, 0x44, 0x12,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
]; |
||||||
@ -1,102 +0,0 @@ |
|||||||
pub(crate) const LUT_VCOM0: [u8; 44] = [ |
|
||||||
0x00, 0x17, 0x00, 0x00, 0x00, 0x02,
|
|
||||||
0x00, 0x17, 0x17, 0x00, 0x00, 0x02,
|
|
||||||
0x00, 0x0A, 0x01, 0x00, 0x00, 0x01,
|
|
||||||
0x00, 0x0E, 0x0E, 0x00, 0x00, 0x02,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
||||||
]; |
|
||||||
|
|
||||||
pub(crate) const LUT_VCOM0_QUICK: [u8; 44] = [ |
|
||||||
0x00, 0x0E, 0x00, 0x00, 0x00, 0x01,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
||||||
]; |
|
||||||
|
|
||||||
pub(crate) const LUT_WW: [u8; 42] =[ |
|
||||||
0x40, 0x17, 0x00, 0x00, 0x00, 0x02, |
|
||||||
0x90, 0x17, 0x17, 0x00, 0x00, 0x02, |
|
||||||
0x40, 0x0A, 0x01, 0x00, 0x00, 0x01, |
|
||||||
0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02, |
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
||||||
]; |
|
||||||
|
|
||||||
pub(crate) const LUT_WW_QUICK: [u8; 42] =[ |
|
||||||
0xA0, 0x0E, 0x00, 0x00, 0x00, 0x01, |
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
||||||
]; |
|
||||||
|
|
||||||
|
|
||||||
pub(crate) const LUT_BW: [u8; 42] =[ |
|
||||||
0x40, 0x17, 0x00, 0x00, 0x00, 0x02, |
|
||||||
0x90, 0x17, 0x17, 0x00, 0x00, 0x02, |
|
||||||
0x40, 0x0A, 0x01, 0x00, 0x00, 0x01, |
|
||||||
0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02, |
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
]; |
|
||||||
|
|
||||||
pub(crate) const LUT_BW_QUICK: [u8; 42] =[ |
|
||||||
0xA0, 0x0E, 0x00, 0x00, 0x00, 0x01, |
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
]; |
|
||||||
|
|
||||||
|
|
||||||
pub(crate) const LUT_BB: [u8; 42] =[ |
|
||||||
0x80, 0x17, 0x00, 0x00, 0x00, 0x02, |
|
||||||
0x90, 0x17, 0x17, 0x00, 0x00, 0x02, |
|
||||||
0x80, 0x0A, 0x01, 0x00, 0x00, 0x01, |
|
||||||
0x50, 0x0E, 0x0E, 0x00, 0x00, 0x02, |
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
]; |
|
||||||
|
|
||||||
pub(crate) const LUT_BB_QUICK: [u8; 42] =[ |
|
||||||
0x50, 0x0E, 0x00, 0x00, 0x00, 0x01, |
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
]; |
|
||||||
|
|
||||||
|
|
||||||
pub(crate) const LUT_WB: [u8; 42] =[ |
|
||||||
0x80, 0x17, 0x00, 0x00, 0x00, 0x02, |
|
||||||
0x90, 0x17, 0x17, 0x00, 0x00, 0x02, |
|
||||||
0x80, 0x0A, 0x01, 0x00, 0x00, 0x01, |
|
||||||
0x50, 0x0E, 0x0E, 0x00, 0x00, 0x02, |
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
]; |
|
||||||
|
|
||||||
pub(crate) const LUT_WB_QUICK: [u8; 42] =[ |
|
||||||
0x50, 0x0E, 0x00, 0x00, 0x00, 0x01, |
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
]; |
|
||||||
@ -0,0 +1,142 @@ |
|||||||
|
use hal::{ |
||||||
|
blocking::{ |
||||||
|
spi::Write, |
||||||
|
delay::* |
||||||
|
}, |
||||||
|
spi::{Mode, Phase, Polarity}, |
||||||
|
digital::* |
||||||
|
}; |
||||||
|
|
||||||
|
use interface::Command; |
||||||
|
|
||||||
|
/// EPD4in2 driver
|
||||||
|
///
|
||||||
|
pub struct DataInterface<SPI, CS, BUSY, DC, RST, D> { |
||||||
|
/// SPI
|
||||||
|
spi: SPI, |
||||||
|
/// CS for SPI
|
||||||
|
cs: CS, |
||||||
|
/// Low for busy, Wait until display is ready!
|
||||||
|
busy: BUSY, |
||||||
|
/// Data/Command Control Pin (High for data, Low for command)
|
||||||
|
dc: DC, |
||||||
|
/// Pin for Reseting
|
||||||
|
rst: RST, |
||||||
|
/// The concrete Delay implementation
|
||||||
|
delay: D, |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
impl<SPI, CS, BUSY, DC, RST, D, E> DataInterface<SPI, CS, BUSY, DC, RST, D> |
||||||
|
where
|
||||||
|
SPI: Write<u8, Error = E>, |
||||||
|
CS: OutputPin, |
||||||
|
BUSY: InputPin, |
||||||
|
DC: OutputPin, |
||||||
|
RST: OutputPin, |
||||||
|
D: DelayUs<u16> + DelayMs<u16>, |
||||||
|
{ |
||||||
|
pub fn new(spi: SPI, cs: CS, busy: BUSY, dc: DC, rst: RST, delay: D) -> Self { |
||||||
|
DataInterface {spi, cs, busy, dc, rst, delay } |
||||||
|
} |
||||||
|
|
||||||
|
/// Basic function for sending [Commands](Command).
|
||||||
|
///
|
||||||
|
/// Enables direct interaction with the device with the help of [EPD4in2::send_data()](EPD4in2::send_data())
|
||||||
|
/// Should rarely be needed!
|
||||||
|
/// //TODO: make public?
|
||||||
|
fn send_command<T: Command>(&mut self, command: T) -> Result<(), E> { |
||||||
|
// low for commands
|
||||||
|
self.dc.set_low();
|
||||||
|
|
||||||
|
// Transfer the command over spi
|
||||||
|
self.with_cs(|epd| { |
||||||
|
epd.spi.write(&[command.address()]) |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
/// Basic function for sending a single u8 of data over spi
|
||||||
|
///
|
||||||
|
/// Enables direct interaction with the device with the help of [EPD4in2::send_command()](EPD4in2::send_command())
|
||||||
|
///
|
||||||
|
/// Should rarely be needed!
|
||||||
|
/// //TODO: make public?
|
||||||
|
fn send_data(&mut self, val: u8) -> Result<(), E> { |
||||||
|
// high for data
|
||||||
|
self.dc.set_high(); |
||||||
|
|
||||||
|
// Transfer data (u8) over spi
|
||||||
|
self.with_cs(|epd| { |
||||||
|
epd.spi.write(&[val]) |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
/// Basic function for sending an array of u8-values of data over spi
|
||||||
|
///
|
||||||
|
/// Enables direct interaction with the device with the help of [EPD4in2::send_command()](EPD4in2::send_command())
|
||||||
|
///
|
||||||
|
/// Should rarely be needed!
|
||||||
|
/// //TODO: make public?
|
||||||
|
fn send_multiple_data(&mut self, data: &[u8]) -> Result<(), E> { |
||||||
|
// high for data
|
||||||
|
self.dc.set_high(); |
||||||
|
|
||||||
|
// Transfer data (u8-array) over spi
|
||||||
|
self.with_cs(|epd| { |
||||||
|
epd.spi.write(data) |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
// spi write helper/abstraction function
|
||||||
|
fn with_cs<F>(&mut self, f: F) -> Result<(), E> |
||||||
|
where
|
||||||
|
F: FnOnce(&mut Self) -> Result<(), E>, |
||||||
|
{ |
||||||
|
// activate spi with cs low
|
||||||
|
self.cs.set_low(); |
||||||
|
// transfer spi data
|
||||||
|
let result = f(self); |
||||||
|
// deativate spi with cs high
|
||||||
|
self.cs.set_high(); |
||||||
|
// return result
|
||||||
|
result |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/// Waits until device isn't busy anymore (busy == HIGH)
|
||||||
|
///
|
||||||
|
/// 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
|
||||||
|
pub fn wait_until_idle(&mut self) { |
||||||
|
//low: busy, high: idle
|
||||||
|
while self.busy.is_low() { |
||||||
|
//TODO: shorten the time? it was 100 in the beginning
|
||||||
|
self.delay_ms(10); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/// Abstraction of setting the delay for simpler calls
|
||||||
|
pub fn delay_ms(&mut self, delay: u16) { |
||||||
|
self.delay.delay_ms(delay); |
||||||
|
} |
||||||
|
|
||||||
|
/// Resets the device.
|
||||||
|
///
|
||||||
|
/// 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?
|
||||||
|
pub fn reset(&mut self) { |
||||||
|
self.rst.set_low(); |
||||||
|
|
||||||
|
//TODO: why 200ms? (besides being in the waveshare code)
|
||||||
|
self.delay_ms(200); |
||||||
|
|
||||||
|
self.rst.set_high(); |
||||||
|
|
||||||
|
//TODO: same as 3 lines above
|
||||||
|
self.delay_ms(200); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,105 @@ |
|||||||
|
use hal::{ |
||||||
|
blocking::{ |
||||||
|
spi::Write, |
||||||
|
delay::* |
||||||
|
}, |
||||||
|
spi::{Mode, Phase, Polarity}, |
||||||
|
digital::* |
||||||
|
}; |
||||||
|
|
||||||
|
pub mod data_interface; |
||||||
|
|
||||||
|
//TODO: test spi mode
|
||||||
|
/// SPI mode -
|
||||||
|
/// For more infos see [Requirements: SPI](index.html#spi)
|
||||||
|
pub const SPI_MODE: Mode = Mode { |
||||||
|
phase: Phase::CaptureOnFirstTransition, |
||||||
|
polarity: Polarity::IdleLow, |
||||||
|
}; |
||||||
|
|
||||||
|
use core::marker::Sized; |
||||||
|
|
||||||
|
pub(crate) trait Command { |
||||||
|
fn address(&self) -> u8; |
||||||
|
} |
||||||
|
|
||||||
|
pub trait WaveshareInterface<SPI, CS, BUSY, DC, RST, D, E> |
||||||
|
where
|
||||||
|
SPI: Write<u8, Error = E>, |
||||||
|
CS: OutputPin, |
||||||
|
BUSY: InputPin, |
||||||
|
DC: OutputPin, |
||||||
|
RST: OutputPin, |
||||||
|
D: DelayUs<u16> + DelayMs<u16>, |
||||||
|
{ |
||||||
|
/// Get the width of the display
|
||||||
|
fn get_width(&self) -> u32; |
||||||
|
fn get_height(&self) -> u32; |
||||||
|
fn new( |
||||||
|
spi: SPI,
|
||||||
|
cs: CS,
|
||||||
|
busy: BUSY,
|
||||||
|
dc: DC,
|
||||||
|
rst: RST,
|
||||||
|
delay: D |
||||||
|
) -> Result<Self, E> |
||||||
|
where Self: Sized; |
||||||
|
fn init(&mut self) -> Result<(), E>; |
||||||
|
fn sleep(&mut self) -> Result<(), E>; |
||||||
|
fn reset(&mut self); |
||||||
|
fn wait_until_idle(&mut self); |
||||||
|
fn delay_ms(&mut self, delay: u32); |
||||||
|
|
||||||
|
/* |
||||||
|
fn clear_frame(&mut self, reset_color: Option<Color>) -> Result<(), E> |
||||||
|
|
||||||
|
fn display_frame_quick(&mut self) -> Result<(), E> |
||||||
|
|
||||||
|
fn display_frame(&mut self) -> Result<(), E> |
||||||
|
|
||||||
|
pub fn display_and_transfer_frame( |
||||||
|
&mut self,
|
||||||
|
buffer: &[u8],
|
||||||
|
color: Option<u8> |
||||||
|
) -> Result<(), E> |
||||||
|
|
||||||
|
pub fn set_partial_window( |
||||||
|
&mut self,
|
||||||
|
buffer: &[u8],
|
||||||
|
x: u16,
|
||||||
|
y: u16,
|
||||||
|
w: u16,
|
||||||
|
l: u16,
|
||||||
|
is_dtm1: bool |
||||||
|
) -> Result<(), 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