Skip to content

Commit

Permalink
WIP. Try to fix partial refresh
Browse files Browse the repository at this point in the history
  • Loading branch information
dkm committed Aug 28, 2020
1 parent 129553b commit 1aaf636
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 27 deletions.
13 changes: 6 additions & 7 deletions src/epd2in13_v2/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,7 @@ pub(crate) enum DisplayUpdateControl2V {
LOAD_LUT = 0x10,

// This is not documented but is used in Waveshare's code.
// It seems that it swaps B/W and Red RAM.
SWAP_RAM = 0x8,
UNDOCUMENTED_BIT = 0x8,

DISPLAY = 0x04,

Expand Down Expand Up @@ -108,32 +107,32 @@ impl DisplayUpdateControl2 {
self.0 |= DisplayUpdateControl2V::ENABLE_CLOCK as u8;
self
}

pub fn enable_analog(mut self) -> Self {
self.0 |= DisplayUpdateControl2V::ENABLE_ANALOG as u8;
self
}

pub fn swap_ram(mut self) -> Self {
self.0 |= DisplayUpdateControl2V::SWAP_RAM as u8;
self
}

pub fn load_temp(mut self) -> Self {
self.0 |= DisplayUpdateControl2V::LOAD_TEMP as u8;
self
}

pub fn load_lut(mut self) -> Self {
self.0 |= DisplayUpdateControl2V::LOAD_LUT as u8;
self
}

pub fn display(mut self) -> Self {
self.0 |= DisplayUpdateControl2V::DISPLAY as u8;
self
}

pub fn disable_analog(mut self) -> Self {
self.0 |= DisplayUpdateControl2V::DISABLE_ANALOG as u8;
self
}

pub fn disable_clock(mut self) -> Self {
self.0 |= DisplayUpdateControl2V::DISABLE_CLOCK as u8;
self
Expand Down
58 changes: 38 additions & 20 deletions src/epd2in13_v2/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,14 @@ where
self.set_ram_address_counters(spi, 0, 0)?;

self.cmd_with_data(spi, Command::WRITE_RAM, buffer)?;

if self.refresh == RefreshLUT::FULL {
// Always keep the base buffer equal to current if not doing partial refresh.
self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?;
self.set_ram_address_counters(spi, 0, 0)?;

self.cmd_with_data(spi, Command::WRITE_RAM_RED, buffer)?;
}
Ok(())
}

Expand All @@ -227,15 +235,32 @@ where
) -> Result<(), SPI::Error> {
assert!((width * height / 8) as usize == buffer.len());

// This should not be used when doing partial refresh. The RAM_RED must
// be updated with the last buffer having been displayed. Doing partial
// update directly in RAM makes this update impossible (we can't read
// RAM content). Using this function will most probably make the actual
// display incorrect as the controler will compare with something
// incorrect.
assert!(self.refresh == RefreshLUT::FULL);

self.set_ram_area(spi, x, y, x + width, y + height)?;
self.set_ram_address_counters(spi, x, y)?;

self.cmd_with_data(spi, Command::WRITE_RAM, buffer)?;

if self.refresh == RefreshLUT::FULL {
// Always keep the base buffer equals to current if not doing partial refresh.
self.set_ram_area(spi, x, y, x + width, y + height)?;
self.set_ram_address_counters(spi, x, y)?;

self.cmd_with_data(spi, Command::WRITE_RAM_RED, buffer)?;
}

Ok(())
}

/// Never use directly this function when using partial refresh, or also
/// keep the base buffer in syncd using `set_partial_base_buffer` function.
fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> {
if self.refresh == RefreshLUT::FULL {
self.set_display_update_control_2(
Expand All @@ -253,44 +278,38 @@ where
self.command(spi, Command::MASTER_ACTIVATION)?;
self.wait_until_idle();

// If partial refresh, swap the buffer so that the current buffer
// becomes the new base for comparison.
// if self.refresh == RefreshLUT::QUICK {
// // self.set_partial_base_buffer(spi, buffer )?;
// self.set_display_update_control_2(spi, DisplayUpdateControl2::new().swap_ram())?;
// self.command(spi, Command::MASTER_ACTIVATION)?;
// self.wait_until_idle();
// }

Ok(())
}

fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> {
self.update_frame(spi, buffer)?;
self.display_frame(spi)?;

// If partial refresh, swap the buffer so that the current buffer
// becomes the new base for comparison.
if self.refresh == RefreshLUT::QUICK {
self.set_partial_base_buffer(spi, buffer)?;
//self.set_display_update_control_2(spi, DisplayUpdateControl2::new().swap_ram())?;
self.command(spi, Command::MASTER_ACTIVATION)?;
self.wait_until_idle();

// We still need to do this as current RAM nows holds the previous
// reference. If we use the `update_partial_frame()` then we may
// end-up with old data.
// self.update_frame(spi, buffer)?;
}
Ok(())
}

fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> {
let color = self.background_color.get_byte_value();

self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?;
self.set_ram_address_counters(spi, 0, 0)?;

self.command(spi, Command::WRITE_RAM)?;
self.interface
.data_x_times(spi, color, WIDTH * HEIGHT / 8)?;

// Always keep the base buffer equals to current if not doing partial refresh.
if self.refresh == RefreshLUT::FULL {
self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?;
self.set_ram_address_counters(spi, 0, 0)?;

self.command(spi, Command::WRITE_RAM_RED)?;
self.interface
.data_x_times(spi, color, WIDTH * HEIGHT / 8)?;
}
Ok(())
}

Expand Down Expand Up @@ -343,7 +362,6 @@ where
spi: &mut SPI,
buffer: &[u8],
) -> Result<(), SPI::Error> {
// self.update_frame(spi, buffer)?;
assert!((WIDTH * HEIGHT / 8) as usize == buffer.len());
self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?;
self.set_ram_address_counters(spi, 0, 0)?;
Expand Down

0 comments on commit 1aaf636

Please sign in to comment.