Fixed partial refresh problem, but refresh may blackout un touched pixels
This commit is contained in:
@@ -183,22 +183,43 @@ esp_err_t EInkDisplayHandler::partial_refresh(const uint8_t* partial_framebuffer
|
||||
ESP_LOGE(TAG, "Partial refresh area x1 and x2 must be byte-aligned (x1 %% 8 == 0 and x2 %% 8 == 7)");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
// no rounding needed, area is expected to be aligned
|
||||
// ------DD
|
||||
// DDDDD000
|
||||
// ------DD
|
||||
// DDDDD111
|
||||
// ------DD
|
||||
// DDDDDDDD
|
||||
// ------DD
|
||||
// DDDDDDDD
|
||||
// -------D
|
||||
|
||||
// area should be multiple of 8 in x direction
|
||||
const int32_t x_bank_start = area.x1 >> 3;
|
||||
const int32_t x_bank_end = area.x2 >> 3;
|
||||
std::vector<uint8_t> window_data = {
|
||||
// x start
|
||||
static_cast<uint8_t>((area.x1 >> 8) & 0xFF), // x start high byte
|
||||
static_cast<uint8_t>(area.x1 & 0x07), // x start low byte
|
||||
// x end
|
||||
static_cast<uint8_t>((area.x2 >> 8) & 0xFF),
|
||||
static_cast<uint8_t>(area.x2 & 0x07),
|
||||
// y start
|
||||
static_cast<uint8_t>((area.y1 >> 8) & 0xFF),
|
||||
// x start, [9:8] bit -> 6 and 7 bits of x_bank_start
|
||||
static_cast<uint8_t>((x_bank_start >> 5) & 0x03),
|
||||
// x start, [7:3] bit + 3 bits of 0 -> 5 bits of x_bank_start and pad 3 LSBs as 0
|
||||
static_cast<uint8_t>((x_bank_start & 0x1F) << 3),
|
||||
// x end, [9:8] bit
|
||||
static_cast<uint8_t>((x_bank_end >> 5) & 0x03),
|
||||
// x end, [7:3] bit + 3 bits of 1
|
||||
static_cast<uint8_t>(((x_bank_end & 0x1F) << 3) | 0x07),
|
||||
// y start, [9:8] bit
|
||||
static_cast<uint8_t>((area.y1 >> 8) & 0x03),
|
||||
// y start, [7:0] bit
|
||||
static_cast<uint8_t>(area.y1 & 0xFF),
|
||||
// y end
|
||||
static_cast<uint8_t>((area.y2 >> 8) & 0xFF),
|
||||
// y end, [9:8] bit
|
||||
static_cast<uint8_t>((area.y2 >> 8) & 0x03),
|
||||
// y end, [7:0] bit
|
||||
static_cast<uint8_t>(area.y2 & 0xFF),
|
||||
0x01 // Gates scan both inside and outside of the partial window
|
||||
};
|
||||
ESP_LOGI(TAG, "Setting partial window: x1=%d, y1=%d, x2=%d, y2=%d",
|
||||
area.x1, area.y1, area.x2, area.y2);
|
||||
ESP_LOGI(TAG, "Partial window data: %02X %02X %02X %02X %02X %02X %02X %02X",
|
||||
window_data[0], window_data[1], window_data[2], window_data[3], window_data[4],
|
||||
window_data[5], window_data[6], window_data[7]);
|
||||
err = epd_write_cmd_with_data(0x90, window_data, transaction_guard.transaction_id()); // Set partial window
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to send set partial window command: %s", esp_err_to_name(err));
|
||||
|
||||
@@ -83,20 +83,32 @@ void EInk_Checkerboard(
|
||||
}
|
||||
}
|
||||
// Yield and reset watchdog periodically
|
||||
if (y % 50 == 0) {
|
||||
const size_t YIELD_INTERVAL = 16;
|
||||
if (y % YIELD_INTERVAL == 0) {
|
||||
if (wdt_err == ESP_OK) {
|
||||
esp_task_wdt_reset();
|
||||
}
|
||||
vTaskDelay(1 / portTICK_PERIOD_MS);
|
||||
// partial refresh to show progress
|
||||
int32_t y_start = static_cast<int32_t>((y >= YIELD_INTERVAL - 1) ? (y - (YIELD_INTERVAL - 1)) : 0);
|
||||
int32_t y_end = static_cast<int32_t>(y);
|
||||
// get the partial framebuffer for this area
|
||||
uint8_t* partial_framebuffer = &framebuffer[y_start * (DISPLAY_WIDTH / 8)];
|
||||
esp_err_t err = display_handler->partial_refresh(partial_framebuffer, RefreshArea { 0, y_start, DISPLAY_WIDTH - 1, y_end });
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Partial refresh failed at y=%d: %s", y, esp_err_to_name(err));
|
||||
}
|
||||
// wait for 4 seconds to prevent spamming the display
|
||||
// vTaskDelay(2000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
// Perform full write to display
|
||||
esp_err_t err = display_handler->full_write(framebuffer);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Checkerboard full write failed: %s", esp_err_to_name(err));
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Checkerboard pattern displayed successfully.");
|
||||
}
|
||||
// esp_err_t err = display_handler->full_write(framebuffer);
|
||||
// if (err != ESP_OK) {
|
||||
// ESP_LOGE(TAG, "Checkerboard full write failed: %s", esp_err_to_name(err));
|
||||
// } else {
|
||||
// ESP_LOGI(TAG, "Checkerboard pattern displayed successfully.");
|
||||
// }
|
||||
delete[] framebuffer;
|
||||
|
||||
// Remove task from watchdog before deletion
|
||||
@@ -239,18 +251,19 @@ void app_main(void) {
|
||||
// NetworkHandler* network_handler = new NetworkHandler(std::move(wifi_handler));
|
||||
EInkDisplayHandler* display_handler = new EInkDisplayHandler();
|
||||
// Initialize display and touch
|
||||
display_handler->init_devices();
|
||||
display_handler->init_devices(system_event_group);
|
||||
// display_handler->init_devices();
|
||||
display_handler->clear_display();
|
||||
ESP_LOGI(TAG, "E-Ink display handler initialized.\n");
|
||||
// LVGL Handler
|
||||
std::unique_ptr<EInkDisplayHandler> display_uptr(display_handler);
|
||||
LVGLHandler lvgl_handler(std::move(display_uptr));
|
||||
esp_err_t err = lvgl_handler.initLVGL(system_event_group);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to initialize LVGL handler: %s", esp_err_to_name(err));
|
||||
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
||||
return esp_restart();
|
||||
}
|
||||
// std::unique_ptr<EInkDisplayHandler> display_uptr(display_handler);
|
||||
// LVGLHandler lvgl_handler(std::move(display_uptr));
|
||||
// esp_err_t err = lvgl_handler.initLVGL(system_event_group);
|
||||
// if (err != ESP_OK) {
|
||||
// ESP_LOGE(TAG, "Failed to initialize LVGL handler: %s", esp_err_to_name(err));
|
||||
// vTaskDelay(5000 / portTICK_PERIOD_MS);
|
||||
// return esp_restart();
|
||||
// }
|
||||
|
||||
//
|
||||
// kv_storage_handler->init(system_event_group);
|
||||
@@ -270,7 +283,8 @@ void app_main(void) {
|
||||
ESP_LOGI(TAG, "System is ready. Starting main application...\n");
|
||||
|
||||
// Show checkerboard pattern on display for testing
|
||||
LVGL_Checkerboard(&lvgl_handler);
|
||||
EInk_Checkerboard(display_handler);
|
||||
// LVGL_Checkerboard(&lvgl_handler);
|
||||
|
||||
// Register apps with AppRegistry by creating their descriptors
|
||||
// Each descriptor will create and register the app instance
|
||||
|
||||
Reference in New Issue
Block a user