
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