Browse Source

Shortened TypeDefinitions,

made init a private function,
added a crate internal extended waveshareinterface,
added a combined  Connection_interface::data_and_command function,
added a wake_up function,
added a updated_and_display_partial_frame_function
embedded-hal-1.0
Christoph Groß 7 years ago
parent
commit
7fa1a27f40
  1. 174
      src/epd1in54/mod.rs
  2. 182
      src/epd2in9/mod.rs
  3. 240
      src/epd4in2/mod.rs
  4. 52
      src/interface/connection_interface.rs
  5. 141
      src/interface/mod.rs

174
src/epd1in54/mod.rs

@ -39,32 +39,76 @@ use interface::connection_interface::ConnectionInterface;
/// EPD1in54 driver /// EPD1in54 driver
/// ///
pub struct EPD1in54<SPI, CS, BUSY, DataCommand, RST, Delay> { pub struct EPD1in54<SPI, CS, BUSY, DC, RST, Delay> {
/// SPI /// SPI
interface: ConnectionInterface<SPI, CS, BUSY, DataCommand, RST, Delay>, interface: ConnectionInterface<SPI, CS, BUSY, DC, RST, Delay>,
/// EPD (width, height) /// EPD (width, height)
//epd: EPD, //epd: EPD,
/// Color /// Color
background_color: Color, background_color: Color,
} }
impl<SPI, CS, BUSY, DataCommand, RST, Delay, E> EPD1in54<SPI, CS, BUSY, DataCommand, RST, Delay> impl<SPI, CS, BUSY, DC, RST, Delay, E> EPD1in54<SPI, CS, BUSY, DC, RST, Delay>
where where
SPI: Write<u8, Error = E>, SPI: Write<u8, Error = E>,
CS: OutputPin, CS: OutputPin,
BUSY: InputPin, BUSY: InputPin,
DataCommand: OutputPin, DC: OutputPin,
RST: OutputPin, RST: OutputPin,
Delay: DelayUs<u16> + DelayMs<u16>, Delay: DelayUs<u16> + DelayMs<u16>,
{} {
fn init(&mut self) -> Result<(), E> {
self.interface.reset();
// 3 Databytes:
// A[7:0]
// 0.. A[8]
// 0.. B[2:0]
// Default Values: A = Height of Screen (0x127), B = 0x00 (GD, SM and TB=0?)
self.interface.command(Command::DRIVER_OUTPUT_CONTROL)?;
self.interface.data(HEIGHT as u8)?;
self.interface.data((HEIGHT >> 8) as u8)?;
self.interface.data(0x00)?;
// 3 Databytes: (and default values from datasheet and arduino)
// 1 .. A[6:0] = 0xCF | 0xD7
// 1 .. B[6:0] = 0xCE | 0xD6
// 1 .. C[6:0] = 0x8D | 0x9D
//TODO: test
self.interface.command(Command::BOOSTER_SOFT_START_CONTROL)?;
self.interface.data(0xD7)?;
self.interface.data(0xD6)?;
self.interface.data(0x9D)?;
// One Databyte with value 0xA8 for 7V VCOM
self.interface.command(Command::WRITE_VCOM_REGISTER)?;
self.interface.data(0xA8)?;
// One Databyte with default value 0x1A for 4 dummy lines per gate
self.interface.command(Command::SET_DUMMY_LINE_PERIOD)?;
self.interface.data(0x1A)?;
// One Databyte with default value 0x08 for 2us per line
self.interface.command(Command::SET_GATE_LINE_WIDTH)?;
self.interface.data(0x08)?;
// One Databyte with default value 0x03
// -> address: x increment, y increment, address counter is updated in x direction
self.interface.command(Command::DATA_ENTRY_MODE_SETTING)?;
self.interface.data(0x03)?;
impl<SPI, CS, BUSY, DataCommand, RST, Delay, E> WaveshareInterface<SPI, CS, BUSY, DataCommand, RST, Delay, E> self.set_lut()
for EPD1in54<SPI, CS, BUSY, DataCommand, RST, Delay> }
}
impl<SPI, CS, BUSY, DC, RST, Delay, E> WaveshareInterface<SPI, CS, BUSY, DC, RST, Delay, E>
for EPD1in54<SPI, CS, BUSY, DC, RST, Delay>
where where
SPI: Write<u8, Error = E>, SPI: Write<u8, Error = E>,
CS: OutputPin, CS: OutputPin,
BUSY: InputPin, BUSY: InputPin,
DataCommand: OutputPin, DC: OutputPin,
RST: OutputPin, RST: OutputPin,
Delay: DelayUs<u16> + DelayMs<u16>, Delay: DelayUs<u16> + DelayMs<u16>,
{ {
@ -77,8 +121,10 @@ where
} }
fn new( fn new(
interface: ConnectionInterface<SPI, CS, BUSY, DataCommand, RST, Delay>, spi: SPI, cs: CS, busy: BUSY, dc: DC, rst: RST, delay: Delay,
) -> Result<Self, E> { ) -> Result<Self, E> {
let interface = ConnectionInterface::new(spi, cs, busy, dc, rst, delay);
let mut epd = EPD1in54 { let mut epd = EPD1in54 {
interface, interface,
background_color: DEFAULT_BACKGROUND_COLOR, background_color: DEFAULT_BACKGROUND_COLOR,
@ -89,63 +135,22 @@ where
Ok(epd) Ok(epd)
} }
fn init(&mut self) -> Result<(), E> { fn wake_up(&mut self) -> Result<(), E> {
self.reset(); self.init()
}
// 3 Databytes:
// A[7:0]
// 0.. A[8]
// 0.. B[2:0]
// Default Values: A = Height of Screen (0x127), B = 0x00 (GD, SM and TB=0?)
self.interface.send_command(Command::DRIVER_OUTPUT_CONTROL)?;
self.interface.send_data(HEIGHT as u8)?;
self.interface.send_data((HEIGHT >> 8) as u8)?;
self.interface.send_data(0x00)?;
// 3 Databytes: (and default values from datasheet and arduino)
// 1 .. A[6:0] = 0xCF | 0xD7
// 1 .. B[6:0] = 0xCE | 0xD6
// 1 .. C[6:0] = 0x8D | 0x9D
//TODO: test
self.interface.send_command(Command::BOOSTER_SOFT_START_CONTROL)?;
self.interface.send_data(0xD7)?;
self.interface.send_data(0xD6)?;
self.interface.send_data(0x9D)?;
// One Databyte with value 0xA8 for 7V VCOM
self.interface.send_command(Command::WRITE_VCOM_REGISTER)?;
self.interface.send_data(0xA8)?;
// One Databyte with default value 0x1A for 4 dummy lines per gate
self.interface.send_command(Command::SET_DUMMY_LINE_PERIOD)?;
self.interface.send_data(0x1A)?;
// One Databyte with default value 0x08 for 2us per line
self.interface.send_command(Command::SET_GATE_LINE_WIDTH)?;
self.interface.send_data(0x08)?;
// One Databyte with default value 0x03
// -> address: x increment, y increment, address counter is updated in x direction
self.interface.send_command(Command::DATA_ENTRY_MODE_SETTING)?;
self.interface.send_data(0x03)?;
self.set_lut()
}
fn sleep(&mut self) -> Result<(), E> { fn sleep(&mut self) -> Result<(), E> {
self.interface.send_command(Command::DEEP_SLEEP_MODE)?; self.interface.command(Command::DEEP_SLEEP_MODE)?;
// 0x00 for Normal mode (Power on Reset), 0x01 for Deep Sleep Mode // 0x00 for Normal mode (Power on Reset), 0x01 for Deep Sleep Mode
//TODO: is 0x00 needed here? //TODO: is 0x00 needed here?
self.interface.send_data(0x00)?; self.interface.data(0x00)?;
self.wait_until_idle(); self.wait_until_idle();
Ok(()) Ok(())
} }
fn reset(&mut self) {
self.interface.reset()
}
fn delay_ms(&mut self, delay: u16) { fn delay_ms(&mut self, delay: u16) {
self.interface.delay_ms(delay) self.interface.delay_ms(delay)
} }
@ -153,8 +158,7 @@ where
fn update_frame(&mut self, buffer: &[u8]) -> Result<(), E> { fn update_frame(&mut self, buffer: &[u8]) -> Result<(), E> {
self.use_full_frame()?; self.use_full_frame()?;
self.interface.send_command(Command::WRITE_RAM)?; self.interface.command_with_data(Command::WRITE_RAM, buffer)
self.interface.send_multiple_data(buffer)
} }
//TODO: update description: last 3 bits will be ignored for width and x_pos //TODO: update description: last 3 bits will be ignored for width and x_pos
@ -169,25 +173,19 @@ where
self.set_ram_area(x, y, x + width, y + height)?; self.set_ram_area(x, y, x + width, y + height)?;
self.set_ram_counter(x, y)?; self.set_ram_counter(x, y)?;
self.interface.send_command(Command::WRITE_RAM)?; self.interface.command(Command::WRITE_RAM)?;
self.interface.send_multiple_data(buffer) self.interface.multiple_data(buffer)
} }
fn display_frame(&mut self) -> Result<(), E> { fn display_frame(&mut self) -> Result<(), E> {
// enable clock signal, enable cp, display pattern -> 0xC4 (tested with the arduino version) // enable clock signal, enable cp, display pattern -> 0xC4 (tested with the arduino version)
//TODO: test control_1 or control_2 with default value 0xFF (from the datasheet) //TODO: test control_1 or control_2 with default value 0xFF (from the datasheet)
self.interface.send_command(Command::DISPLAY_UPDATE_CONTROL_2)?; self.interface.command_with_data(Command::DISPLAY_UPDATE_CONTROL_2, &[0xC4])?;
self.interface.send_data(0xC4)?;
self.interface.send_command(Command::MASTER_ACTIVATION)?; self.interface.command(Command::MASTER_ACTIVATION)?;
// MASTER Activation should not be interupted to avoid currption of panel images // MASTER Activation should not be interupted to avoid currption of panel images
// therefore a terminate command is send // therefore a terminate command is send
self.interface.send_command(Command::TERMINATE_COMMANDS_AND_FRAME_WRITE) self.interface.command(Command::NOP)
}
fn update_and_display_frame(&mut self, buffer: &[u8]) -> Result<(), E> {
self.update_frame(buffer)?;
self.display_frame()
} }
fn clear_frame(&mut self) -> Result<(), E> { fn clear_frame(&mut self) -> Result<(), E> {
@ -196,14 +194,19 @@ where
// clear the ram with the background color // clear the ram with the background color
let color = self.background_color.get_byte_value(); let color = self.background_color.get_byte_value();
self.interface.send_command(Command::WRITE_RAM)?; self.interface.command(Command::WRITE_RAM)?;
self.interface.send_data_x_times(color, WIDTH / 8 * HEIGHT) self.interface.data_x_times(color, WIDTH / 8 * HEIGHT)
} }
/// Sets the backgroundcolor for various commands like [WaveshareInterface::clear_frame()](clear_frame())
fn set_background_color(&mut self, background_color: Color) { fn set_background_color(&mut self, background_color: Color) {
self.background_color = background_color; self.background_color = background_color;
} }
fn background_color(&self) -> &Color {
&self.background_color
}
} }
impl<SPI, CS, BUSY, DC, RST, D, E> EPD1in54<SPI, CS, BUSY, DC, RST, D> impl<SPI, CS, BUSY, DC, RST, D, E> EPD1in54<SPI, CS, BUSY, DC, RST, D>
@ -239,28 +242,28 @@ where
// x is positioned in bytes, so the last 3 bits which show the position inside a byte in the ram // x is positioned in bytes, so the last 3 bits which show the position inside a byte in the ram
// aren't relevant // aren't relevant
self.interface.send_command(Command::SET_RAM_X_ADDRESS_START_END_POSITION)?; self.interface.command(Command::SET_RAM_X_ADDRESS_START_END_POSITION)?;
self.interface.send_data((start_x >> 3) as u8)?; self.interface.data((start_x >> 3) as u8)?;
self.interface.send_data((end_x >> 3) as u8)?; self.interface.data((end_x >> 3) as u8)?;
// 2 Databytes: A[7:0] & 0..A[8] for each - start and end // 2 Databytes: A[7:0] & 0..A[8] for each - start and end
self.interface.send_command(Command::SET_RAM_Y_ADDRESS_START_END_POSITION)?; self.interface.command(Command::SET_RAM_Y_ADDRESS_START_END_POSITION)?;
self.interface.send_data(start_y as u8)?; self.interface.data(start_y as u8)?;
self.interface.send_data((start_y >> 8) as u8)?; self.interface.data((start_y >> 8) as u8)?;
self.interface.send_data(end_y as u8)?; self.interface.data(end_y as u8)?;
self.interface.send_data((end_y >> 8) as u8) self.interface.data((end_y >> 8) as u8)
} }
pub(crate) fn set_ram_counter(&mut self, x: u16, y: u16) -> Result<(), E> { pub(crate) fn set_ram_counter(&mut self, x: u16, y: u16) -> Result<(), E> {
// x is positioned in bytes, so the last 3 bits which show the position inside a byte in the ram // x is positioned in bytes, so the last 3 bits which show the position inside a byte in the ram
// aren't relevant // aren't relevant
self.interface.send_command(Command::SET_RAM_X_ADDRESS_COUNTER)?; self.interface.command_with_data(Command::SET_RAM_X_ADDRESS_COUNTER, &[(x >> 3) as u8])?;
self.interface.send_data((x >> 3) as u8)?;
// 2 Databytes: A[7:0] & 0..A[8] // 2 Databytes: A[7:0] & 0..A[8]
self.interface.send_command(Command::SET_RAM_Y_ADDRESS_COUNTER)?; self.interface.command_with_data(
self.interface.send_data(y as u8)?; Command::SET_RAM_Y_ADDRESS_COUNTER,
self.interface.send_data((y >> 8) as u8)?; &[y as u8, (y >> 8) as u8]
)?;
self.wait_until_idle(); self.wait_until_idle();
Ok(()) Ok(())
@ -283,7 +286,6 @@ where
fn set_lut_helper(&mut self, buffer: &[u8]) -> Result<(), E> { fn set_lut_helper(&mut self, buffer: &[u8]) -> Result<(), E> {
assert!(buffer.len() == 30); assert!(buffer.len() == 30);
self.interface.send_command(Command::WRITE_LUT_REGISTER)?; self.interface.command_with_data(Command::WRITE_LUT_REGISTER, buffer)
self.interface.send_multiple_data(buffer)
} }
} }

182
src/epd2in9/mod.rs

@ -38,33 +38,78 @@ use interface::connection_interface::ConnectionInterface;
/// EPD2in9 driver /// EPD2in9 driver
/// ///
pub struct EPD2in9<SPI, CS, BUSY, DataCommand, RST, Delay> { pub struct EPD2in9<SPI, CS, BUSY, DC, RST, Delay> {
/// SPI /// SPI
interface: ConnectionInterface<SPI, CS, BUSY, DataCommand, RST, Delay>, interface: ConnectionInterface<SPI, CS, BUSY, DC, RST, Delay>,
/// EPD (width, height) /// EPD (width, height)
//epd: EPD, //epd: EPD,
/// Color /// Color
background_color: Color, background_color: Color,
} }
impl<SPI, CS, BUSY, DataCommand, RST, Delay, E> EPD2in9<SPI, CS, BUSY, DataCommand, RST, Delay> impl<SPI, CS, BUSY, DC, RST, Delay, E> EPD2in9<SPI, CS, BUSY, DC, RST, Delay>
where where
SPI: Write<u8, Error = E>, SPI: Write<u8, Error = E>,
CS: OutputPin, CS: OutputPin,
BUSY: InputPin, BUSY: InputPin,
DataCommand: OutputPin, DC: OutputPin,
RST: OutputPin, RST: OutputPin,
Delay: DelayUs<u16> + DelayMs<u16>, Delay: DelayUs<u16> + DelayMs<u16>,
{} {
fn init(&mut self) -> Result<(), E> {
self.interface.reset();
// 3 Databytes:
// A[7:0]
// 0.. A[8]
// 0.. B[2:0]
// Default Values: A = Height of Screen (0x127), B = 0x00 (GD, SM and TB=0?)
self.interface.command(Command::DRIVER_OUTPUT_CONTROL)?;
self.interface.data(HEIGHT as u8)?;
self.interface.data((HEIGHT >> 8) as u8)?;
self.interface.data(0x00)?;
// 3 Databytes: (and default values from datasheet and arduino)
// 1 .. A[6:0] = 0xCF | 0xD7
// 1 .. B[6:0] = 0xCE | 0xD6
// 1 .. C[6:0] = 0x8D | 0x9D
//TODO: test
self.interface.command(Command::BOOSTER_SOFT_START_CONTROL)?;
self.interface.data(0xD7)?;
self.interface.data(0xD6)?;
self.interface.data(0x9D)?;
// One Databyte with value 0xA8 for 7V VCOM
self.interface.command(Command::WRITE_VCOM_REGISTER)?;
self.interface.data(0xA8)?;
impl<SPI, CS, BUSY, DataCommand, RST, Delay, E> // One Databyte with default value 0x1A for 4 dummy lines per gate
WaveshareInterface<SPI, CS, BUSY, DataCommand, RST, Delay, E> self.interface.command(Command::SET_DUMMY_LINE_PERIOD)?;
for EPD2in9<SPI, CS, BUSY, DataCommand, RST, Delay> self.interface.data(0x1A)?;
// One Databyte with default value 0x08 for 2us per line
self.interface.command(Command::SET_GATE_LINE_WIDTH)?;
self.interface.data(0x08)?;
// One Databyte with default value 0x03
// -> address: x increment, y increment, address counter is updated in x direction
self.interface.command(Command::DATA_ENTRY_MODE_SETTING)?;
self.interface.data(0x03)?;
self.set_lut()
}
}
impl<SPI, CS, BUSY, DC, RST, Delay, E>
WaveshareInterface<SPI, CS, BUSY, DC, RST, Delay, E>
for EPD2in9<SPI, CS, BUSY, DC, RST, Delay>
where where
SPI: Write<u8, Error = E>, SPI: Write<u8, Error = E>,
CS: OutputPin, CS: OutputPin,
BUSY: InputPin, BUSY: InputPin,
DataCommand: OutputPin, DC: OutputPin,
RST: OutputPin, RST: OutputPin,
Delay: DelayUs<u16> + DelayMs<u16>, Delay: DelayUs<u16> + DelayMs<u16>,
{ {
@ -77,11 +122,13 @@ where
} }
fn new( fn new(
interface: ConnectionInterface<SPI, CS, BUSY, DataCommand, RST, Delay>, spi: SPI, cs: CS, busy: BUSY, dc: DC, rst: RST, delay: Delay,
) -> Result<Self, E> { ) -> Result<Self, E> {
//let epd = EPD::new(WIDTH, HEIGHT); //let epd = EPD::new(WIDTH, HEIGHT);
//let background_color = Color::White; //let background_color = Color::White;
let interface = ConnectionInterface::new(spi, cs, busy, dc, rst, delay);
let mut epd = EPD2in9 { let mut epd = EPD2in9 {
interface, interface,
background_color: DEFAULT_BACKGROUND_COLOR, background_color: DEFAULT_BACKGROUND_COLOR,
@ -92,61 +139,20 @@ where
Ok(epd) Ok(epd)
} }
fn init(&mut self) -> Result<(), E> {
self.reset();
// 3 Databytes:
// A[7:0]
// 0.. A[8]
// 0.. B[2:0]
// Default Values: A = Height of Screen (0x127), B = 0x00 (GD, SM and TB=0?)
self.interface.send_command(Command::DRIVER_OUTPUT_CONTROL)?;
self.interface.send_data(HEIGHT as u8)?;
self.interface.send_data((HEIGHT >> 8) as u8)?;
self.interface.send_data(0x00)?;
// 3 Databytes: (and default values from datasheet and arduino)
// 1 .. A[6:0] = 0xCF | 0xD7
// 1 .. B[6:0] = 0xCE | 0xD6
// 1 .. C[6:0] = 0x8D | 0x9D
//TODO: test
self.interface.send_command(Command::BOOSTER_SOFT_START_CONTROL)?;
self.interface.send_data(0xD7)?;
self.interface.send_data(0xD6)?;
self.interface.send_data(0x9D)?;
// One Databyte with value 0xA8 for 7V VCOM
self.interface.send_command(Command::WRITE_VCOM_REGISTER)?;
self.interface.send_data(0xA8)?;
// One Databyte with default value 0x1A for 4 dummy lines per gate
self.interface.send_command(Command::SET_DUMMY_LINE_PERIOD)?;
self.interface.send_data(0x1A)?;
// One Databyte with default value 0x08 for 2us per line
self.interface.send_command(Command::SET_GATE_LINE_WIDTH)?;
self.interface.send_data(0x08)?;
// One Databyte with default value 0x03
// -> address: x increment, y increment, address counter is updated in x direction
self.interface.send_command(Command::DATA_ENTRY_MODE_SETTING)?;
self.interface.send_data(0x03)?;
self.set_lut()
}
fn sleep(&mut self) -> Result<(), E> { fn sleep(&mut self) -> Result<(), E> {
self.interface.send_command(Command::DEEP_SLEEP_MODE)?; self.interface.command(Command::DEEP_SLEEP_MODE)?;
// 0x00 for Normal mode (Power on Reset), 0x01 for Deep Sleep Mode // 0x00 for Normal mode (Power on Reset), 0x01 for Deep Sleep Mode
//TODO: is 0x00 needed here? //TODO: is 0x00 needed here?
self.interface.send_data(0x00)?; self.interface.data(0x00)?;
self.wait_until_idle(); self.wait_until_idle();
Ok(()) Ok(())
} }
fn reset(&mut self) { fn wake_up(&mut self) -> Result<(), E> {
self.interface.reset() self.init()
} }
fn delay_ms(&mut self, delay: u16) { fn delay_ms(&mut self, delay: u16) {
@ -156,8 +162,8 @@ where
fn update_frame(&mut self, buffer: &[u8]) -> Result<(), E> { fn update_frame(&mut self, buffer: &[u8]) -> Result<(), E> {
self.use_full_frame()?; self.use_full_frame()?;
self.interface.send_command(Command::WRITE_RAM)?; self.interface.command(Command::WRITE_RAM)?;
self.interface.send_multiple_data(buffer) self.interface.multiple_data(buffer)
} }
//TODO: update description: last 3 bits will be ignored for width and x_pos //TODO: update description: last 3 bits will be ignored for width and x_pos
@ -172,20 +178,20 @@ where
self.set_ram_area(x, y, x + width, y + height)?; self.set_ram_area(x, y, x + width, y + height)?;
self.set_ram_counter(x, y)?; self.set_ram_counter(x, y)?;
self.interface.send_command(Command::WRITE_RAM)?; self.interface.command(Command::WRITE_RAM)?;
self.interface.send_multiple_data(buffer) self.interface.multiple_data(buffer)
} }
fn display_frame(&mut self) -> Result<(), E> { fn display_frame(&mut self) -> Result<(), E> {
// enable clock signal, enable cp, display pattern -> 0xC4 (tested with the arduino version) // enable clock signal, enable cp, display pattern -> 0xC4 (tested with the arduino version)
//TODO: test control_1 or control_2 with default value 0xFF (from the datasheet) //TODO: test control_1 or control_2 with default value 0xFF (from the datasheet)
self.interface.send_command(Command::DISPLAY_UPDATE_CONTROL_2)?; self.interface.command(Command::DISPLAY_UPDATE_CONTROL_2)?;
self.interface.send_data(0xC4)?; self.interface.data(0xC4)?;
self.interface.send_command(Command::MASTER_ACTIVATION)?; self.interface.command(Command::MASTER_ACTIVATION)?;
// MASTER Activation should not be interupted to avoid currption of panel images // MASTER Activation should not be interupted to avoid currption of panel images
// therefore a terminate command is send // therefore a terminate command is send
self.interface.send_command(Command::TERMINATE_COMMANDS_AND_FRAME_WRITE) self.interface.command(Command::NOP)
} }
fn update_and_display_frame(&mut self, buffer: &[u8]) -> Result<(), E> { fn update_and_display_frame(&mut self, buffer: &[u8]) -> Result<(), E> {
@ -193,20 +199,36 @@ where
self.display_frame() self.display_frame()
} }
fn update_and_display_partial_frame(
&mut self,
buffer: &[u8],
x: u16,
y: u16,
width: u16,
height: u16,
) -> Result<(), E> {
self.update_partial_frame(buffer, x, y, width, height)?;
self.display_frame()
}
fn clear_frame(&mut self) -> Result<(), E> { fn clear_frame(&mut self) -> Result<(), E> {
self.use_full_frame()?; self.use_full_frame()?;
// clear the ram with the background color // clear the ram with the background color
let color = self.background_color.get_byte_value(); let color = self.background_color.get_byte_value();
self.interface.send_command(Command::WRITE_RAM)?; self.interface.command(Command::WRITE_RAM)?;
self.interface.send_data_x_times(color, WIDTH / 8 * HEIGHT) self.interface.data_x_times(color, WIDTH / 8 * HEIGHT)
} }
/// Sets the backgroundcolor for various commands like [WaveshareInterface::clear_frame()](clear_frame()) /// Sets the backgroundcolor for various commands like [WaveshareInterface::clear_frame()](clear_frame())
fn set_background_color(&mut self, background_color: Color) { fn set_background_color(&mut self, background_color: Color) {
self.background_color = background_color; self.background_color = background_color;
} }
fn background_color(&self) -> &Color {
&self.background_color
}
} }
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>
@ -242,28 +264,28 @@ where
// x is positioned in bytes, so the last 3 bits which show the position inside a byte in the ram // x is positioned in bytes, so the last 3 bits which show the position inside a byte in the ram
// aren't relevant // aren't relevant
self.interface.send_command(Command::SET_RAM_X_ADDRESS_START_END_POSITION)?; self.interface.command(Command::SET_RAM_X_ADDRESS_START_END_POSITION)?;
self.interface.send_data((start_x >> 3) as u8)?; self.interface.data((start_x >> 3) as u8)?;
self.interface.send_data((end_x >> 3) as u8)?; self.interface.data((end_x >> 3) as u8)?;
// 2 Databytes: A[7:0] & 0..A[8] for each - start and end // 2 Databytes: A[7:0] & 0..A[8] for each - start and end
self.interface.send_command(Command::SET_RAM_Y_ADDRESS_START_END_POSITION)?; self.interface.command(Command::SET_RAM_Y_ADDRESS_START_END_POSITION)?;
self.interface.send_data(start_y as u8)?; self.interface.data(start_y as u8)?;
self.interface.send_data((start_y >> 8) as u8)?; self.interface.data((start_y >> 8) as u8)?;
self.interface.send_data(end_y as u8)?; self.interface.data(end_y as u8)?;
self.interface.send_data((end_y >> 8) as u8) self.interface.data((end_y >> 8) as u8)
} }
pub(crate) fn set_ram_counter(&mut self, x: u16, y: u16) -> Result<(), E> { pub(crate) fn set_ram_counter(&mut self, x: u16, y: u16) -> Result<(), E> {
// x is positioned in bytes, so the last 3 bits which show the position inside a byte in the ram // x is positioned in bytes, so the last 3 bits which show the position inside a byte in the ram
// aren't relevant // aren't relevant
self.interface.send_command(Command::SET_RAM_X_ADDRESS_COUNTER)?; self.interface.command(Command::SET_RAM_X_ADDRESS_COUNTER)?;
self.interface.send_data((x >> 3) as u8)?; self.interface.data((x >> 3) as u8)?;
// 2 Databytes: A[7:0] & 0..A[8] // 2 Databytes: A[7:0] & 0..A[8]
self.interface.send_command(Command::SET_RAM_Y_ADDRESS_COUNTER)?; self.interface.command(Command::SET_RAM_Y_ADDRESS_COUNTER)?;
self.interface.send_data(y as u8)?; self.interface.data(y as u8)?;
self.interface.send_data((y >> 8) as u8)?; self.interface.data((y >> 8) as u8)?;
self.wait_until_idle(); self.wait_until_idle();
Ok(()) Ok(())
@ -286,7 +308,7 @@ where
fn set_lut_helper(&mut self, buffer: &[u8]) -> Result<(), E> { fn set_lut_helper(&mut self, buffer: &[u8]) -> Result<(), E> {
assert!(buffer.len() == 30); assert!(buffer.len() == 30);
self.interface.send_command(Command::WRITE_LUT_REGISTER)?; self.interface.command(Command::WRITE_LUT_REGISTER)?;
self.interface.send_multiple_data(buffer) self.interface.multiple_data(buffer)
} }
} }

240
src/epd4in2/mod.rs

@ -51,7 +51,7 @@ use hal::{
digital::*, digital::*,
}; };
use interface::{connection_interface::ConnectionInterface, WaveshareInterface}; use interface::{connection_interface::ConnectionInterface, WaveshareInterface, InternalWiAdditions};
//The Lookup Tables for the Display //The Lookup Tables for the Display
mod constants; mod constants;
@ -67,71 +67,30 @@ use self::command::Command;
pub struct EPD4in2<SPI, CS, BUSY, DC, RST, D> { pub struct EPD4in2<SPI, CS, BUSY, DC, RST, D> {
/// Connection Interface /// Connection Interface
interface: ConnectionInterface<SPI, CS, BUSY, DC, RST, D>, interface: ConnectionInterface<SPI, CS, BUSY, DC, RST, D>,
/// Width
width: u16,
/// Height
height: u16,
/// Background Color /// Background Color
color: Color, color: Color,
} }
impl<SPI, CS, BUSY, DataCommand, RST, Delay, SpiError>
WaveshareInterface<SPI, CS, BUSY, DataCommand, RST, Delay, SpiError>
for EPD4in2<SPI, CS, BUSY, DataCommand, RST, Delay>
impl<SPI, CS, BUSY, DC, RST, Delay, ERR>
InternalWiAdditions<SPI, CS, BUSY, DC, RST, Delay, ERR>
for EPD4in2<SPI, CS, BUSY, DC, RST, Delay>
where where
SPI: Write<u8, Error = SpiError>, SPI: Write<u8, Error = ERR>,
CS: OutputPin, CS: OutputPin,
BUSY: InputPin, BUSY: InputPin,
DataCommand: OutputPin, DC: OutputPin,
RST: OutputPin, RST: OutputPin,
Delay: DelayUs<u16> + DelayMs<u16>, Delay: DelayUs<u16> + DelayMs<u16>,
{ {
fn get_width(&self) -> u16 { fn init(&mut self) -> Result<(), ERR> {
self.width
}
fn get_height(&self) -> u16 {
self.height
}
/// Creates a new driver from a SPI peripheral, CS Pin, Busy InputPin, DC
///
/// This already initialises the device. That means [init()](init()) isn't needed directly afterwards
///
/// # Example
///
/// ```ignore
/// //buffer = some image data;
///
/// let mut epd4in2 = EPD4in2::new(spi, cs, busy, dc, rst, delay);
///
/// epd4in2.display_and_transfer_frame(buffer, None);
///
/// epd4in2.sleep();
/// ```
fn new(interface: ConnectionInterface<SPI, CS, BUSY, DataCommand, RST, Delay>) -> Result<Self, SpiError> {
let width = WIDTH as u16;
let height = HEIGHT as u16;
let color = Color::White;
let mut epd = EPD4in2 {
interface,
width,
height,
color,
};
epd.init()?;
Ok(epd)
}
fn init(&mut self) -> Result<(), SpiError> {
// reset the device // reset the device
self.reset(); self.interface.reset();
// set the power settings // set the power settings
self.send_command(Command::POWER_SETTING)?; self.command(Command::POWER_SETTING)?;
self.send_data(0x03)?; //VDS_EN, VDG_EN self.send_data(0x03)?; //VDS_EN, VDG_EN
self.send_data(0x00)?; //VCOM_HV, VGHL_LV[1], VGHL_LV[0] self.send_data(0x00)?; //VCOM_HV, VGHL_LV[1], VGHL_LV[0]
self.send_data(0x2b)?; //VDH self.send_data(0x2b)?; //VDH
@ -139,17 +98,17 @@ where
self.send_data(0xff)?; //VDHR self.send_data(0xff)?; //VDHR
// start the booster // start the booster
self.send_command(Command::BOOSTER_SOFT_START)?; self.command(Command::BOOSTER_SOFT_START)?;
for _ in 0..3 { for _ in 0..3 {
self.send_data(0x17)?; //07 0f 17 1f 27 2F 37 2f self.send_data(0x17)?; //07 0f 17 1f 27 2F 37 2f
} }
// power on // power on
self.send_command(Command::POWER_ON)?; self.command(Command::POWER_ON)?;
self.wait_until_idle(); self.wait_until_idle();
// set the panel settings // set the panel settings
self.send_command(Command::PANEL_SETTING)?; self.command(Command::PANEL_SETTING)?;
// 0x0F Red Mode, LUT from OTP // 0x0F Red Mode, LUT from OTP
// 0x1F B/W Mode, LUT from OTP // 0x1F B/W Mode, LUT from OTP
// 0x2F Red Mode, LUT set by registers // 0x2F Red Mode, LUT set by registers
@ -165,63 +124,97 @@ where
// 150Hz and 171Hz wasn't tested yet // 150Hz and 171Hz wasn't tested yet
// TODO: Test these other frequencies // TODO: Test these other frequencies
// 3A 100HZ 29 150Hz 39 200HZ 31 171HZ DEFAULT: 3c 50Hz // 3A 100HZ 29 150Hz 39 200HZ 31 171HZ DEFAULT: 3c 50Hz
self.send_command(Command::PLL_CONTROL)?; self.command(Command::PLL_CONTROL)?;
self.send_data(0x3A)?; self.send_data(0x3A)?;
self.set_lut()?; self.set_lut()?;
Ok(()) Ok(())
} }
}
fn sleep(&mut self) -> Result<(), SpiError> { impl<SPI, CS, BUSY, DC, RST, Delay, ERR>
self.send_command(Command::VCOM_AND_DATA_INTERVAL_SETTING)?; WaveshareInterface<SPI, CS, BUSY, DC, RST, Delay, ERR>
for EPD4in2<SPI, CS, BUSY, DC, RST, Delay>
where
SPI: Write<u8, Error = ERR>,
CS: OutputPin,
BUSY: InputPin,
DC: OutputPin,
RST: OutputPin,
Delay: DelayUs<u16> + DelayMs<u16>,
{
/// Creates a new driver from a SPI peripheral, CS Pin, Busy InputPin, DC
///
/// This already initialises the device. That means [init()](init()) isn't needed directly afterwards
///
/// # Example
///
/// ```ignore
/// //buffer = some image data;
///
/// let mut epd4in2 = EPD4in2::new(spi, cs, busy, dc, rst, delay);
///
/// epd4in2.display_and_transfer_frame(buffer, None);
///
/// epd4in2.sleep();
/// ```
fn new(spi: SPI, cs: CS, busy: BUSY, dc: DC, rst: RST, delay: Delay) -> Result<Self, ERR> {
let interface = ConnectionInterface::new(spi, cs, busy, dc, rst, delay);
let color = Color::White;
let mut epd = EPD4in2 {
interface,
color,
};
epd.init()?;
Ok(epd)
}
fn wake_up(&mut self) -> Result<(), ERR> {
self.init()
}
fn sleep(&mut self) -> Result<(), ERR> {
self.command(Command::VCOM_AND_DATA_INTERVAL_SETTING)?;
self.send_data(0x17)?; //border floating self.send_data(0x17)?; //border floating
self.send_command(Command::VCM_DC_SETTING)?; // VCOM to 0V self.command(Command::VCM_DC_SETTING)?; // VCOM to 0V
self.send_command(Command::PANEL_SETTING)?; self.command(Command::PANEL_SETTING)?;
self.delay_ms(100); self.delay_ms(100);
self.send_command(Command::POWER_SETTING)?; //VG&VS to 0V fast self.command(Command::POWER_SETTING)?; //VG&VS to 0V fast
for _ in 0..4 { for _ in 0..4 {
self.send_data(0x00)?; self.send_data(0x00)?;
} }
self.delay_ms(100); self.delay_ms(100);
self.send_command(Command::POWER_OFF)?; self.command(Command::POWER_OFF)?;
self.wait_until_idle(); self.wait_until_idle();
self.send_command(Command::DEEP_SLEEP)?; self.interface.command_with_data(Command::DEEP_SLEEP, &[0xA5])
self.send_data(0xA5)?;
Ok(())
} }
fn reset(&mut self) { fn update_frame(&mut self, buffer: &[u8]) -> Result<(), ERR> {
self.interface.reset()
}
fn delay_ms(&mut self, delay: u16) {
self.interface.delay_ms(delay)
}
fn update_frame(&mut self, buffer: &[u8]) -> Result<(), SpiError> {
let color_value = self.color.get_byte_value(); let color_value = self.color.get_byte_value();
self.send_resolution()?; self.send_resolution()?;
self.send_command(Command::VCM_DC_SETTING)?; self.interface.command_with_data(Command::VCM_DC_SETTING, &[0x12])?;
self.send_data(0x12)?;
self.send_command(Command::VCOM_AND_DATA_INTERVAL_SETTING)?; self.command(Command::VCOM_AND_DATA_INTERVAL_SETTING)?;
//TODO: this was a send_command instead of a send_data. check if it's alright and doing what it should do (setting the default values) //TODO: this was a send_command instead of a send_data. check if it's alright and doing what it should do (setting the default values)
//self.send_command_u8(0x97)?; //VBDF 17|D7 VBDW 97 VBDB 57 VBDF F7 VBDW 77 VBDB 37 VBDR B7 //self.send_command_u8(0x97)?; //VBDF 17|D7 VBDW 97 VBDB 57 VBDF F7 VBDW 77 VBDB 37 VBDR B7
self.send_data(0x97)?; self.send_data(0x97)?;
self.send_command(Command::DATA_START_TRANSMISSION_1)?; self.command(Command::DATA_START_TRANSMISSION_1)?;
for _ in 0..(buffer.len()) { for _ in 0..(buffer.len()) {
self.send_data(color_value)?; self.send_data(color_value)?;
} }
self.delay_ms(2); self.delay_ms(2);
self.send_command(Command::DATA_START_TRANSMISSION_2)?; self.command(Command::DATA_START_TRANSMISSION_2)?;
//self.send_multiple_data(buffer)?; //self.send_multiple_data(buffer)?;
for &elem in buffer.iter() { for &elem in buffer.iter() {
@ -238,14 +231,14 @@ where
y: u16, y: u16,
width: u16, width: u16,
height: u16, height: u16,
) -> Result<(), SpiError> { ) -> Result<(), ERR> {
if buffer.len() as u16 != width / 8 * height { if buffer.len() as u16 != width / 8 * height {
//TODO: panic!! or sth like that //TODO: panic!! or sth like that
//return Err("Wrong buffersize"); //return Err("Wrong buffersize");
} }
self.send_command(Command::PARTIAL_IN)?; self.command(Command::PARTIAL_IN)?;
self.send_command(Command::PARTIAL_WINDOW)?; self.command(Command::PARTIAL_WINDOW)?;
self.send_data((x >> 8) as u8)?; self.send_data((x >> 8) as u8)?;
let tmp = x & 0xf8; let tmp = x & 0xf8;
self.send_data(tmp as u8)?; // x should be the multiple of 8, the last 3 bit will always be ignored self.send_data(tmp as u8)?; // x should be the multiple of 8, the last 3 bit will always be ignored
@ -264,38 +257,32 @@ where
//TODO: handle dtm somehow //TODO: handle dtm somehow
let is_dtm1 = false; let is_dtm1 = false;
if is_dtm1 { if is_dtm1 {
self.send_command(Command::DATA_START_TRANSMISSION_1)? self.command(Command::DATA_START_TRANSMISSION_1)?
} else { } else {
self.send_command(Command::DATA_START_TRANSMISSION_2)? self.command(Command::DATA_START_TRANSMISSION_2)?
} }
self.send_multiple_data(buffer)?; self.send_multiple_data(buffer)?;
self.send_command(Command::PARTIAL_OUT) self.command(Command::PARTIAL_OUT)
} }
fn update_and_display_frame(&mut self, buffer: &[u8]) -> Result<(), SpiError> {
self.update_frame(buffer)?;
self.display_frame()
}
fn display_frame(&mut self) -> Result<(), SpiError> {
self.send_command(Command::DISPLAY_REFRESH)?; fn display_frame(&mut self) -> Result<(), ERR> {
self.command(Command::DISPLAY_REFRESH)?;
self.wait_until_idle(); self.wait_until_idle();
Ok(()) Ok(())
} }
// TODO: add this abstraction function fn clear_frame(&mut self) -> Result<(), ERR> {
// fn update_and_display_frame(&mut self, buffer: &[u8]) -> Result<(), E>;
fn clear_frame(&mut self) -> Result<(), SpiError> {
self.send_resolution()?; self.send_resolution()?;
let size = self.width / 8 * self.height; let size = WIDTH / 8 * HEIGHT;
let color_value = self.color.get_byte_value(); let color_value = self.color.get_byte_value();
self.send_command(Command::DATA_START_TRANSMISSION_1)?; self.command(Command::DATA_START_TRANSMISSION_1)?;
self.delay_ms(2); self.delay_ms(2);
for _ in 0..size { for _ in 0..size {
self.send_data(color_value)?; self.send_data(color_value)?;
@ -303,7 +290,7 @@ where
self.delay_ms(2); self.delay_ms(2);
self.send_command(Command::DATA_START_TRANSMISSION_2)?; self.command(Command::DATA_START_TRANSMISSION_2)?;
self.delay_ms(2); self.delay_ms(2);
for _ in 0..size { for _ in 0..size {
self.send_data(color_value)?; self.send_data(color_value)?;
@ -315,38 +302,55 @@ where
fn set_background_color(&mut self, color: Color) { fn set_background_color(&mut self, color: Color) {
self.color = color; self.color = color;
} }
fn background_color(&self) -> &Color {
&self.color
}
fn get_width(&self) -> u16 {
WIDTH
}
fn get_height(&self) -> u16 {
HEIGHT
}
fn delay_ms(&mut self, delay: u16) {
self.interface.delay_ms(delay)
}
} }
impl<SPI, CS, BUSY, DC, RST, D, SpiError> EPD4in2<SPI, CS, BUSY, DC, RST, D> impl<SPI, CS, BUSY, DC, RST, D, ERR> EPD4in2<SPI, CS, BUSY, DC, RST, D>
where where
SPI: Write<u8, Error = SpiError>, SPI: Write<u8, Error = ERR>,
CS: OutputPin, CS: OutputPin,
BUSY: InputPin, BUSY: InputPin,
DC: OutputPin, DC: OutputPin,
RST: OutputPin, RST: OutputPin,
D: DelayUs<u16> + DelayMs<u16>, D: DelayUs<u16> + DelayMs<u16>,
{ {
fn send_command(&mut self, command: Command) -> Result<(), SpiError> { fn command(&mut self, command: Command) -> Result<(), ERR> {
self.interface.send_command(command) self.interface.command(command)
} }
fn send_data(&mut self, val: u8) -> Result<(), SpiError> { fn send_data(&mut self, val: u8) -> Result<(), ERR> {
self.interface.send_data(val) self.interface.data(val)
} }
fn send_multiple_data(&mut self, data: &[u8]) -> Result<(), SpiError> { fn send_multiple_data(&mut self, data: &[u8]) -> Result<(), ERR> {
self.interface.send_multiple_data(data) self.interface.multiple_data(data)
} }
fn wait_until_idle(&mut self) { fn wait_until_idle(&mut self) {
self.interface.wait_until_idle(true) self.interface.wait_until_idle(true)
} }
fn send_resolution(&mut self) -> Result<(), SpiError> { fn send_resolution(&mut self) -> Result<(), ERR> {
let w = self.get_width(); let w = self.get_width();
let h = self.get_height(); let h = self.get_height();
self.send_command(Command::RESOLUTION_SETTING)?; self.command(Command::RESOLUTION_SETTING)?;
self.send_data((w >> 8) as u8)?; self.send_data((w >> 8) as u8)?;
self.send_data(w as u8)?; self.send_data(w as u8)?;
self.send_data((h >> 8) as u8)?; self.send_data((h >> 8) as u8)?;
@ -355,7 +359,7 @@ where
/// Fill the look-up table for the EPD /// Fill the look-up table for the EPD
//TODO: make public? //TODO: make public?
fn set_lut(&mut self) -> Result<(), SpiError> { fn set_lut(&mut self) -> Result<(), ERR> {
self.set_lut_helper(&LUT_VCOM0, &LUT_WW, &LUT_BW, &LUT_WB, &LUT_BB) self.set_lut_helper(&LUT_VCOM0, &LUT_WW, &LUT_BW, &LUT_WB, &LUT_BB)
} }
@ -364,7 +368,7 @@ where
/// Is automatically done by [EPD4in2::display_frame_quick()](EPD4in2::display_frame_quick()) /// Is automatically done by [EPD4in2::display_frame_quick()](EPD4in2::display_frame_quick())
/// //TODO: make public? /// //TODO: make public?
#[cfg(feature = "epd4in2_fast_update")] #[cfg(feature = "epd4in2_fast_update")]
fn set_lut_quick(&mut self) -> Result<(), SpiError> { fn set_lut_quick(&mut self) -> Result<(), ERR> {
self.set_lut_helper( self.set_lut_helper(
&LUT_VCOM0_QUICK, &LUT_VCOM0_QUICK,
&LUT_WW_QUICK, &LUT_WW_QUICK,
@ -381,25 +385,25 @@ where
lut_bw: &[u8], lut_bw: &[u8],
lut_wb: &[u8], lut_wb: &[u8],
lut_bb: &[u8], lut_bb: &[u8],
) -> Result<(), SpiError> { ) -> Result<(), ERR> {
// LUT VCOM // LUT VCOM
self.send_command(Command::LUT_FOR_VCOM)?; self.command(Command::LUT_FOR_VCOM)?;
self.send_multiple_data(lut_vcom)?; self.send_multiple_data(lut_vcom)?;
// LUT WHITE to WHITE // LUT WHITE to WHITE
self.send_command(Command::LUT_WHITE_TO_WHITE)?; self.command(Command::LUT_WHITE_TO_WHITE)?;
self.send_multiple_data(lut_ww)?; self.send_multiple_data(lut_ww)?;
// LUT BLACK to WHITE // LUT BLACK to WHITE
self.send_command(Command::LUT_BLACK_TO_WHITE)?; self.command(Command::LUT_BLACK_TO_WHITE)?;
self.send_multiple_data(lut_bw)?; self.send_multiple_data(lut_bw)?;
// LUT WHITE to BLACK // LUT WHITE to BLACK
self.send_command(Command::LUT_WHITE_TO_BLACK)?; self.command(Command::LUT_WHITE_TO_BLACK)?;
self.send_multiple_data(lut_wb)?; self.send_multiple_data(lut_wb)?;
// LUT BLACK to BLACK // LUT BLACK to BLACK
self.send_command(Command::LUT_BLACK_TO_BLACK)?; self.command(Command::LUT_BLACK_TO_BLACK)?;
self.send_multiple_data(lut_bb)?; self.send_multiple_data(lut_bb)?;
Ok(()) Ok(())

52
src/interface/connection_interface.rs

@ -7,7 +7,7 @@ use interface::Command;
/// The Connection Interface of all (?) Waveshare EPD-Devices /// The Connection Interface of all (?) Waveshare EPD-Devices
/// ///
pub struct ConnectionInterface<SPI, CS, BUSY, DC, RST, D> { pub(crate) struct ConnectionInterface<SPI, CS, BUSY, DC, RST, D> {
/// SPI /// SPI
spi: SPI, spi: SPI,
/// CS for SPI /// CS for SPI
@ -22,17 +22,17 @@ pub struct ConnectionInterface<SPI, CS, BUSY, DC, RST, D> {
delay: D, delay: D,
} }
impl<SPI, CS, BUSY, DataCommand, RST, Delay, ErrorSpeziale> impl<SPI, CS, BUSY, DC, RST, Delay, ERR>
ConnectionInterface<SPI, CS, BUSY, DataCommand, RST, Delay> ConnectionInterface<SPI, CS, BUSY, DC, RST, Delay>
where where
SPI: Write<u8, Error = ErrorSpeziale>, SPI: Write<u8, Error = ERR>,
CS: OutputPin, CS: OutputPin,
BUSY: InputPin, BUSY: InputPin,
DataCommand: OutputPin, DC: OutputPin,
RST: OutputPin, RST: OutputPin,
Delay: DelayUs<u16> + DelayMs<u16>, Delay: DelayUs<u16> + DelayMs<u16>,
{ {
pub fn new(spi: SPI, cs: CS, busy: BUSY, dc: DataCommand, rst: RST, delay: Delay) -> Self { pub fn new(spi: SPI, cs: CS, busy: BUSY, dc: DC, rst: RST, delay: Delay) -> Self {
ConnectionInterface { ConnectionInterface {
spi, spi,
cs, cs,
@ -45,10 +45,10 @@ where
/// Basic function for sending [Commands](Command). /// Basic function for sending [Commands](Command).
/// ///
/// Enables direct interaction with the device with the help of [send_data()](ConnectionInterface::send_data()) /// Enables direct interaction with the device with the help of [data()](ConnectionInterface::data())
/// Should rarely be needed! ///
/// //TODO: make public? /// //TODO: make public?
pub(crate) fn send_command<T: Command>(&mut self, command: T) -> Result<(), ErrorSpeziale> { pub(crate) fn command<T: Command>(&mut self, command: T) -> Result<(), ERR> {
// low for commands // low for commands
self.dc.set_low(); self.dc.set_low();
@ -58,11 +58,10 @@ where
/// Basic function for sending a single u8 of data over spi /// Basic function for sending a single u8 of data over spi
/// ///
/// Enables direct interaction with the device with the help of [Esend_command()](ConnectionInterface::send_command()) /// Enables direct interaction with the device with the help of [Ecommand()](ConnectionInterface::command())
/// ///
/// Should rarely be needed!
/// //TODO: make public? /// //TODO: make public?
pub(crate) fn send_data(&mut self, val: u8) -> Result<(), ErrorSpeziale> { pub(crate) fn data(&mut self, val: u8) -> Result<(), ERR> {
// high for data // high for data
self.dc.set_high(); self.dc.set_high();
@ -70,17 +69,24 @@ where
self.with_cs(|epd| epd.spi.write(&[val])) self.with_cs(|epd| epd.spi.write(&[val]))
} }
/// Basic function for sending a single u8 of data over spi /// Basic function for sending [Commands](Command) and the data belonging to it.
///
/// //TODO: make public?
pub(crate) fn command_with_data<T: Command>(&mut self, command: T, data: &[u8]) -> Result<(), ERR> {
self.command(command)?;
self.multiple_data(data)
}
/// Basic function for sending the same byte of data (one u8) multiple times over spi
/// ///
/// Enables direct interaction with the device with the help of [Esend_command()](ConnectionInterface::send_command()) /// Enables direct interaction with the device with the help of [command()](ConnectionInterface::command())
/// ///
/// Should rarely be needed!
/// //TODO: make public? /// //TODO: make public?
pub(crate) fn send_data_x_times( pub(crate) fn data_x_times(
&mut self, &mut self,
val: u8, val: u8,
repetitions: u16, repetitions: u16,
) -> Result<(), ErrorSpeziale> { ) -> Result<(), ERR> {
// high for data // high for data
self.dc.set_high(); self.dc.set_high();
@ -95,11 +101,10 @@ where
/// Basic function for sending an array of u8-values of data over spi /// Basic function for sending an array of u8-values of data over spi
/// ///
/// Enables direct interaction with the device with the help of [send_command()](EPD4in2::send_command()) /// Enables direct interaction with the device with the help of [command()](EPD4in2::command())
/// ///
/// Should rarely be needed!
/// //TODO: make public? /// //TODO: make public?
pub(crate) fn send_multiple_data(&mut self, data: &[u8]) -> Result<(), ErrorSpeziale> { pub(crate) fn multiple_data(&mut self, data: &[u8]) -> Result<(), ERR> {
// high for data // high for data
self.dc.set_high(); self.dc.set_high();
@ -108,9 +113,9 @@ where
} }
// spi write helper/abstraction function // spi write helper/abstraction function
pub(crate) fn with_cs<F>(&mut self, f: F) -> Result<(), ErrorSpeziale> fn with_cs<F>(&mut self, f: F) -> Result<(), ERR>
where where
F: FnOnce(&mut Self) -> Result<(), ErrorSpeziale>, F: FnOnce(&mut Self) -> Result<(), ERR>,
{ {
// activate spi with cs low // activate spi with cs low
self.cs.set_low(); self.cs.set_low();
@ -134,6 +139,7 @@ where
/// - FALSE for epd2in9, epd1in54 (for all Display Type A ones?) /// - FALSE for epd2in9, epd1in54 (for all Display Type A ones?)
/// ///
/// Most likely there was a mistake with the 2in9 busy connection /// Most likely there was a mistake with the 2in9 busy connection
/// //TODO: use the #cfg feature to make this compile the right way for the certain types
pub(crate) fn wait_until_idle(&mut self, is_busy_low: bool) { pub(crate) fn wait_until_idle(&mut self, is_busy_low: bool) {
self.delay_ms(1); self.delay_ms(1);
//low: busy, high: idle //low: busy, high: idle
@ -158,7 +164,7 @@ where
pub(crate) 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 arduino version)
self.delay_ms(200); self.delay_ms(200);
self.rst.set_high(); self.rst.set_high();

141
src/interface/mod.rs

@ -7,8 +7,7 @@ use hal::{
use drawing::color::Color; use drawing::color::Color;
/// Interface for the physical connection between display and the controlling device /// Interface for the physical connection between display and the controlling device
pub mod connection_interface; pub(crate) mod connection_interface;
use self::connection_interface::ConnectionInterface;
/// All commands need to have this trait which gives the address of the command /// 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) /// which needs to be send via SPI with activated CommandsPin (Data/Command Pin in CommandMode)
@ -18,58 +17,111 @@ pub(crate) trait Command {
//TODO: add LUT trait with set_fast_lut and set_manual_lut and set_normal_lut or sth like that? //TODO: add LUT trait with set_fast_lut and set_manual_lut and set_normal_lut or sth like that?
// for partial updates // for partial updates
trait LUTSupport<Error> { trait LUTSupport<ERR> {
fn set_lut(&mut self) -> Result<(), Error>; fn set_lut(&mut self) -> Result<(), ERR>;
fn set_lut_quick(&mut self) -> Result<(), Error>; fn set_lut_quick(&mut self) -> Result<(), ERR>;
fn set_lut_manual(&mut self, data: &[u8]) -> Result<(), Error>; fn set_lut_manual(&mut self, data: &[u8]) -> Result<(), ERR>;
} }
pub trait WaveshareInterface<SPI, CS, BUSY, DataCommand, RST, Delay, Error> pub(crate) trait InternalWiAdditions<SPI, CS, BUSY, DC, RST, Delay, ERR>
where where
SPI: Write<u8>, SPI: Write<u8>,
CS: OutputPin, CS: OutputPin,
BUSY: InputPin, BUSY: InputPin,
DataCommand: OutputPin, DC: OutputPin,
RST: OutputPin,
Delay: DelayUs<u16> + DelayMs<u16>,
{
/// 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(&mut self) -> Result<(), ERR>;
}
pub trait WaveshareInterface<SPI, CS, BUSY, DC, RST, Delay, ERR>
where
SPI: Write<u8>,
CS: OutputPin,
BUSY: InputPin,
DC: OutputPin,
RST: OutputPin, RST: OutputPin,
Delay: DelayUs<u16> + DelayMs<u16>, Delay: DelayUs<u16> + DelayMs<u16>,
{ {
/// Get the width of the display
fn get_width(&self) -> u16;
/// Get the height of the display
fn get_height(&self) -> u16;
/// Creates a new driver from a SPI peripheral, CS Pin, Busy InputPin, DC /// 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 /// This already initialises the device. That means [init()](WaveshareInterface::init()) isn't needed directly afterwards
fn new( fn new(
interface: ConnectionInterface<SPI, CS, BUSY, DataCommand, RST, Delay>, spi: SPI, cs: CS, busy: BUSY, dc: DC, rst: RST, delay: Delay,
) -> Result<Self, Error> ) -> Result<Self, ERR>
where where
Self: Sized; Self: Sized;
/// This initialises the EPD and powers it up // TODO: add this abstraction function
/// Loads a full image on the EPD and displays it
fn update_and_display_frame(&mut self, buffer: &[u8]) -> Result<(), ERR> {
self.update_frame(buffer)?;
self.display_frame()
}
/// Loads a partial image on the EPD and displays it
fn update_and_display_partial_frame(
&mut self,
buffer: &[u8],
x: u16,
y: u16,
width: u16,
height: u16,
) -> Result<(), ERR> {
self.update_partial_frame(buffer, x, y, width, height)?;
self.display_frame()
}
/// Let the device enter deep-sleep mode to save power.
/// ///
/// This function is already called from [new()](WaveshareInterface::new()) /// 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<(), ERR>;
fn wake_up(&mut self) -> Result<(), ERR>;
/// 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 get_width(&self) -> u16;
/// Get the height of the display
fn get_height(&self) -> u16;
/// Abstraction of setting the delay for simpler calls
/// ///
/// This function calls [reset()](WaveshareInterface::reset()), /// maximum delay ~65 seconds (u16:max in ms)
/// so you don't need to call reset your self when trying to wake your device up fn delay_ms(&mut self, delay: u16);
/// after setting it to sleep.
fn init(&mut self) -> Result<(), Error>;
// void DisplayFrame(const unsigned char* frame_buffer); // void DisplayFrame(const unsigned char* frame_buffer);
/// Transmit a full frame to the SRAM of the DPD /// Transmit a full frame to the SRAM of the DPD
/// ///
fn update_frame(&mut self, buffer: &[u8]) -> Result<(), Error>; fn update_frame(&mut self, buffer: &[u8]) -> Result<(), ERR>;
//TODO: is dtm always used? /// Transmits partial data to the SRAM of the EPD
/// Transmit partial data to the SRAM of the EPD,
/// the final parameter dtm chooses between the 2
/// internal buffers
/// ///
/// Normally it should be dtm2, so use false /// BUFFER needs to be of size: w / 8 * h !
///
/// BUFFER needs to be of size: w / 8 * l !
fn update_partial_frame( fn update_partial_frame(
&mut self, &mut self,
buffer: &[u8], buffer: &[u8],
@ -77,37 +129,14 @@ where
y: u16, y: u16,
width: u16, width: u16,
height: u16, height: u16,
) -> Result<(), Error>; ) -> Result<(), ERR>;
/// Displays the frame data from SRAM /// Displays the frame data from SRAM
fn display_frame(&mut self) -> Result<(), Error>; fn display_frame(&mut self) -> Result<(), ERR>;
// TODO: add this abstraction function /// Clears the frame from the buffer with the declared background color
fn update_and_display_frame(&mut self, buffer: &[u8]) -> Result<(), Error>; /// The background color can be changed with [`set_background_color`]
/// Clears the frame from the buffer
/// ///
/// Uses the chosen background color /// Uses the chosen background color
fn clear_frame(&mut self) -> Result<(), Error>; fn clear_frame(&mut self) -> Result<(), ERR>;
/// 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<(), Error>;
/// Resets the device.
///
/// Often used to awake the module from deep sleep. See [sleep()](WaveshareInterface::sleep())
fn reset(&mut self);
/// Abstraction of setting the delay for simpler calls
///
/// maximum delay ~65 seconds (u16:max in ms)
fn delay_ms(&mut self, delay: u16);
} }

Loading…
Cancel
Save