vroland / epdiy

EPDiy is a driver board for affordable e-Paper (or E-ink) displays.

Home Page:https://vroland.github.io/epdiy-hardware/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Why epd_hl_update_area always redraw fullscreen in s3_lcd branch?

lanistor opened this issue · comments

In epd_hl_update_area function, the diff_area will be seted to full screen before redraw, if i use real different area to redraw, the rendering will be misaligned.

I don't know why, may someone tell me?

  EpdRect diff_area = epd_difference_image_cropped(
	  state->front_fb,
	  state->back_fb,
	  area,
	  state->difference_fb,
	  state->dirty_lines,
      &previously_white,
      &previously_black
  );

  ESP_LOGI("epdiy", "highlevel diff area: x: %d, y: %d, w: %d, h: %d", diff_area.x, diff_area.y, diff_area.width, diff_area.height);

  if (diff_area.height == 0 || diff_area.width == 0) {
      return EPD_DRAW_SUCCESS;
  }

  uint32_t t1 = esp_timer_get_time() / 1000;

  previously_white = false;
  previously_black = false;

  diff_area.x = 0;
  diff_area.y = 0;
  diff_area.width = epd_width();
  diff_area.height = epd_height();

  enum EpdDrawError err;
  if (previously_white) {
      err = epd_draw_base(epd_full_screen(), state->front_fb, diff_area, MODE_PACKING_2PPB | PREVIOUSLY_WHITE | mode, temperature, state->dirty_lines, state->waveform);
  } else if (previously_black) {
      err = epd_draw_base(epd_full_screen(), state->front_fb, diff_area, MODE_PACKING_2PPB | PREVIOUSLY_BLACK | mode, temperature, state->dirty_lines, state->waveform);
  } else {
      err = epd_draw_base(epd_full_screen(), state->difference_fb, diff_area, MODE_PACKING_1PPB_DIFFERENCE | mode, temperature, state->dirty_lines, state->waveform);
  }

Hello Lanistor,
Will take a look. Please use main branch only

Please add also information about what board you are using to make your tests. Since you are using that branch I assume is v7, but I don't want to guess, please bring full information to reproduce what you are exposing in this Issue.

I'm using the v5 board, in main branch, i still find the code:
截屏2024-03-13 10 48 33

In old v5 branch, i found a good way to eliminate afterimages without increasing rendering time (1024*758 screen just need 1000ms). But i cannot run it perfectly on s3 branch, Here is the old code:

void epdiy_repaint(EpdRect area) {
  epd_clear_area_cycles(area, 1, 12);
  epd_hl_update_area_directly(&hl, updateMode, temperature, area);
}

enum EpdDrawError epd_hl_update_area_directly(EpdiyHighlevelState* state, enum EpdDrawMode mode, int temperature, EpdRect area) {
  assert(state != NULL);
  // Not right to rotate here since this copies part of buffer directly

  bool previously_white = true;
  bool previously_black = false;
  // Check rotation FIX
  EpdRect rotated_area = _inverse_rotated_area(area.x, area.y, area.width, area.height);
  area.x = rotated_area.x;
  area.y = rotated_area.y;
  area.width = rotated_area.width;
  area.height = rotated_area.height;

  memset(state->dirty_lines + area.y, 1, area.height);

  enum EpdDrawError err;
  if (previously_white) {
      err = epd_draw_base(epd_full_screen(), state->front_fb, area, MODE_PACKING_2PPB | PREVIOUSLY_WHITE | mode, temperature, state->dirty_lines, state->waveform);
  } else if (previously_black) {
      err = epd_draw_base(epd_full_screen(), state->front_fb, area, MODE_PACKING_2PPB | PREVIOUSLY_BLACK | mode, temperature, state->dirty_lines, state->waveform);
  } else {
      err = epd_draw_base(epd_full_screen(), state->difference_fb, area, MODE_PACKING_1PPB_DIFFERENCE | mode, temperature, state->dirty_lines, state->waveform);
  }

  for (int l=area.y; l < area.y + area.height; l++) {
	if (state->dirty_lines[l] > 0) {
      uint8_t* lfb = state->front_fb + EPD_WIDTH / 2 * l;
      uint8_t* lbb = state->back_fb + EPD_WIDTH / 2 * l;

      for (int x=area.x; x < area.x + area.width; x++) {
          if (x % 2) {
            *(lbb + x / 2) = (*(lfb + x / 2) & 0xF0) | (*(lbb + x / 2) & 0x0F);
          } else {
            *(lbb + x / 2) = (*(lfb + x / 2) & 0x0F) | (*(lbb + x / 2) & 0xF0);
          }
      }
	}
  }
  return err;
}

But, on s3 branch, i cannot run epd_hl_update_area_directly normally, this will cause rendering misaligned, and i repaired it like this:

void epdiy_repaint(EpdRect area) {
  epd_clear_area_cycles(area, 1, 12);
  epdiy_set_area_to_white(area);
  // directly call epd_hl_update_area
  epd_hl_update_area(&hl, updateMode, temperature, area);
}

void epdiy_set_area_to_white(EpdRect& area) {
  for (int l=area.y; l < area.y + area.height; l++) {
    uint8_t* lfb = hl.front_fb + epd_width() / 2 * l;
    uint8_t* lbb = hl.back_fb + epd_width() / 2 * l;

    for (int x=area.x; x < area.x + area.width; x++) {
      if (x % 2) {
        *(lbb + x / 2) = 0xF0 | (*(lbb + x / 2) & 0x0F);
      } else {
        *(lbb + x / 2) = 0x0F | (*(lbb + x / 2) & 0xF0);
      }
    }
  }
}

But this will increase rendering time a lot, nearly 300~500ms. And epd_hl_update_area also become much slower than epd_hl_update_area_directly.

I don't know how to resolve it, i had work on it for several days.

@martinberlin @vroland Now i'm sure there is somthing wrong on the following line in epd_hl_update_area, in main branch with v5 board:

err = epd_draw_base(epd_full_screen(), state->front_fb, diff_area, MODE_PACKING_2PPB | PREVIOUSLY_WHITE | mode, temperature, state->dirty_lines, state->waveform);

This will make rendering misaligned. It will render several times, the previous times were all correct, but the last time rendering will cheaper to the left about 5 pixels.
I think this may be the reason to always use MODE_PACKING_1PPB_DIFFERENCE mode in epd_hl_update_area.

I think I made the change to set it to the whole area with the S3 implementation, and I'm working on fixing that in the S3 vector instructions branch and subsequent refactor. On V5 with current main that shift shouldn't happen though, so that seems like a bug...
@lanistor Can you point me to an example to reproduce somewhere? It will take me a bit since I'm traveling until around the end of March, but seems worthy of investigation.

I think I made the change to set it to the whole area with the S3 implementation, and I'm working on fixing that in the S3 vector instructions branch and subsequent refactor. On V5 with current main that shift shouldn't happen though, so that seems like a bug... @lanistor Can you point me to an example to reproduce somewhere? It will take me a bit since I'm traveling until around the end of March, but seems worthy of investigation.

It's a little hard to create a demo from out project, i will do it sometime.

I just saw you're passing mode and then adding additional flags... What is the complete set of MODE flags (i.e., the value of mode) at the time of drawing? The distortion could be the result of conflicting mode flags. Also, do you have a picture of the distortion?

I just saw you're passing mode and then adding additional flags... What is the complete set of MODE flags (i.e., the value of mode) at the time of drawing? The distortion could be the result of conflicting mode flags. Also, do you have a picture of the distortion?

I'm always using theMODE_DU MODE.

Ok then, I minimal demo to reproduce this would be very helpful.