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)");
|
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;
|
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 = {
|
std::vector<uint8_t> window_data = {
|
||||||
// x start
|
// x start, [9:8] bit -> 6 and 7 bits of x_bank_start
|
||||||
static_cast<uint8_t>((area.x1 >> 8) & 0xFF), // x start high byte
|
static_cast<uint8_t>((x_bank_start >> 5) & 0x03),
|
||||||
static_cast<uint8_t>(area.x1 & 0x07), // x start low byte
|
// x start, [7:3] bit + 3 bits of 0 -> 5 bits of x_bank_start and pad 3 LSBs as 0
|
||||||
// x end
|
static_cast<uint8_t>((x_bank_start & 0x1F) << 3),
|
||||||
static_cast<uint8_t>((area.x2 >> 8) & 0xFF),
|
// x end, [9:8] bit
|
||||||
static_cast<uint8_t>(area.x2 & 0x07),
|
static_cast<uint8_t>((x_bank_end >> 5) & 0x03),
|
||||||
// y start
|
// x end, [7:3] bit + 3 bits of 1
|
||||||
static_cast<uint8_t>((area.y1 >> 8) & 0xFF),
|
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),
|
static_cast<uint8_t>(area.y1 & 0xFF),
|
||||||
// y end
|
// y end, [9:8] bit
|
||||||
static_cast<uint8_t>((area.y2 >> 8) & 0xFF),
|
static_cast<uint8_t>((area.y2 >> 8) & 0x03),
|
||||||
|
// y end, [7:0] bit
|
||||||
static_cast<uint8_t>(area.y2 & 0xFF),
|
static_cast<uint8_t>(area.y2 & 0xFF),
|
||||||
0x01 // Gates scan both inside and outside of the partial window
|
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
|
err = epd_write_cmd_with_data(0x90, window_data, transaction_guard.transaction_id()); // Set partial window
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "Failed to send set partial window command: %s", esp_err_to_name(err));
|
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
|
// 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) {
|
if (wdt_err == ESP_OK) {
|
||||||
esp_task_wdt_reset();
|
esp_task_wdt_reset();
|
||||||
}
|
}
|
||||||
vTaskDelay(1 / portTICK_PERIOD_MS);
|
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
|
// Perform full write to display
|
||||||
esp_err_t err = display_handler->full_write(framebuffer);
|
// esp_err_t err = display_handler->full_write(framebuffer);
|
||||||
if (err != ESP_OK) {
|
// if (err != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "Checkerboard full write failed: %s", esp_err_to_name(err));
|
// ESP_LOGE(TAG, "Checkerboard full write failed: %s", esp_err_to_name(err));
|
||||||
} else {
|
// } else {
|
||||||
ESP_LOGI(TAG, "Checkerboard pattern displayed successfully.");
|
// ESP_LOGI(TAG, "Checkerboard pattern displayed successfully.");
|
||||||
}
|
// }
|
||||||
delete[] framebuffer;
|
delete[] framebuffer;
|
||||||
|
|
||||||
// Remove task from watchdog before deletion
|
// Remove task from watchdog before deletion
|
||||||
@@ -239,18 +251,19 @@ void app_main(void) {
|
|||||||
// NetworkHandler* network_handler = new NetworkHandler(std::move(wifi_handler));
|
// NetworkHandler* network_handler = new NetworkHandler(std::move(wifi_handler));
|
||||||
EInkDisplayHandler* display_handler = new EInkDisplayHandler();
|
EInkDisplayHandler* display_handler = new EInkDisplayHandler();
|
||||||
// Initialize display and touch
|
// Initialize display and touch
|
||||||
display_handler->init_devices();
|
display_handler->init_devices(system_event_group);
|
||||||
|
// display_handler->init_devices();
|
||||||
display_handler->clear_display();
|
display_handler->clear_display();
|
||||||
ESP_LOGI(TAG, "E-Ink display handler initialized.\n");
|
ESP_LOGI(TAG, "E-Ink display handler initialized.\n");
|
||||||
// LVGL Handler
|
// LVGL Handler
|
||||||
std::unique_ptr<EInkDisplayHandler> display_uptr(display_handler);
|
// std::unique_ptr<EInkDisplayHandler> display_uptr(display_handler);
|
||||||
LVGLHandler lvgl_handler(std::move(display_uptr));
|
// LVGLHandler lvgl_handler(std::move(display_uptr));
|
||||||
esp_err_t err = lvgl_handler.initLVGL(system_event_group);
|
// esp_err_t err = lvgl_handler.initLVGL(system_event_group);
|
||||||
if (err != ESP_OK) {
|
// if (err != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "Failed to initialize LVGL handler: %s", esp_err_to_name(err));
|
// ESP_LOGE(TAG, "Failed to initialize LVGL handler: %s", esp_err_to_name(err));
|
||||||
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
// vTaskDelay(5000 / portTICK_PERIOD_MS);
|
||||||
return esp_restart();
|
// return esp_restart();
|
||||||
}
|
// }
|
||||||
|
|
||||||
//
|
//
|
||||||
// kv_storage_handler->init(system_event_group);
|
// 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");
|
ESP_LOGI(TAG, "System is ready. Starting main application...\n");
|
||||||
|
|
||||||
// Show checkerboard pattern on display for testing
|
// 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
|
// Register apps with AppRegistry by creating their descriptors
|
||||||
// Each descriptor will create and register the app instance
|
// Each descriptor will create and register the app instance
|
||||||
|
|||||||
Reference in New Issue
Block a user