Skip to content

Conversation

@wilfredjonathanjames
Copy link

@wilfredjonathanjames wilfredjonathanjames commented Dec 15, 2025

noticed Display3in7 update_partial_frame was todo! so added it

pr notes:

  • turned off ping ping mode (switching between display buffers per render.) could be turned back on with a more complex solution. not sure it's worth it
  • changed the software interface init sleep from 300ms to 10 per the technical sheet
  • added the other two luts in case someone, like me, wants to use them. a2 is faster for black/white but leaves greater ghosting. if interested change
            Some(RefreshLut::Quick) => &LUT_1GRAY_DU,
            // to
            Some(RefreshLut::Quick) => &LUT_1GRAY_A2,
  • added the r ram write command. someone may want to add ping-pong updates. testing implies b/w displays use r ram as ping pong buffer 2(?). technical sheet is unclear
WriteRamRed = 0x26 

use notes:

  • no need to call display_frame- partial updates execute immediately in their own display mode
  • du and a2 luts cannot(?) write whites. use for +blacks only. faster this way
  • as noted in the technical sheet, remember to do a full refresh after 4-5 partial updates to prevent damage
  • if using a rotated display, you may need to swap width/height when constructing the buffer window and passing driver coordinates:
pub fn update_partial(g: &mut GraphicsInterfaces, x: u32, y: u32, width: u32, height: u32) {
  // EPD expects data column-major, so for us we need to read 90deg clockwise
  let bytes_per_column = height.div_ceil(8) as usize;
  let num_columns = width as usize;
  let total_bytes = bytes_per_column * num_columns;

  const MAX_WINDOW_BYTES: usize = WIDTH.div_ceil(8) as usize * HEIGHT as usize;
  let mut window = [0u8; MAX_WINDOW_BYTES];
  let window = &mut window[..total_bytes];

  let buffer = g.display.buffer();
  let src_stride = (WIDTH / 8) as usize;

  for col in 0..num_columns {
    let src_x = x + col as u32;
    let src_start = src_x as usize * src_stride + y as usize / 8;

    let dst_offset = col * bytes_per_column;
    window[dst_offset..dst_offset + bytes_per_column]
      .copy_from_slice(&buffer[src_start..src_start + bytes_per_column]);
  }

 // Note the swapped width/height and x/y -> y/x for EPD driver
  g.epd
    .update_partial_frame(
      &mut g.spi,
      &mut g.delay,
      window,
      y,      // -> becomes X on EPD (because rotated)
      x,      // -> becomes Y on EPD
      height, // -> becomes width on EPD
      width,  // -> becomes height on EPD
    )
    .unwrap();
}

my repo is already diverging, so i'm simply raising this pr for posterity. happy to make any minor changes requested but won't be contributing heavily. would love to hear if there are any improvements

@auto-assign auto-assign bot requested a review from caemor December 15, 2025 05:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants