Fix partial refresh color inversion problem

This commit is contained in:
GW_MC
2026-01-29 14:41:48 +08:00
parent 6b0dcafd8b
commit 392bf804a2
2 changed files with 43 additions and 28 deletions

View File

@@ -11,6 +11,7 @@
#define DISPLAY_BUFFER_SIZE (EINK_HEIGHT* EINK_WIDTH) / 8 // 1 bit per pixels
#define MINIMUM_PIN_SETUP_DELAY_MS 10
#define MINIMUM_POWER_ON_DELAY_MS 100
#define PARTIAL_REFRESH_THRESHOLD 5 // Full refresh every N partial refreshes
static uint8_t* DRAW_BUFFER; // 1 bit per pixel
static uint8_t* OLD_DRAW_BUFFER; // 1 bit per pixel
@@ -99,32 +100,43 @@ esp_err_t EInkDisplayHandler::deep_sleep_display(void) {
esp_err_t EInkDisplayHandler::refresh_display() {
esp_err_t err = ESP_OK;
{
ESP_LOGI(TAG, "Waiting for display to be idle...");
TransactionGuard transaction_guard(this->epd_handler_);
err = transaction_guard.begin(pdMS_TO_TICKS(10000));
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to begin transaction for display refresh: %s", esp_err_to_name(err));
return err;
}
if (is_deep_sleep_) {
epd_init_internal_(transaction_guard.transaction_id());
}
epd_handler_.wait_for_idle();
ESP_LOGI(TAG, "Starting display refresh...");
err = epd_handler_.epd_write_cmd(0x92, transaction_guard.transaction_id()); // enter normal mode
if (is_deep_sleep_) {
err = full_write(draw_buffer_, true);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to enter normal mode: %s", esp_err_to_name(err));
ESP_LOGE(TAG, "Full write failed during refresh_display: %s", esp_err_to_name(err));
return err;
}
err = epd_handler_.epd_write_cmd(0x12, transaction_guard.transaction_id()); // display refresh
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to send display refresh command: %s", esp_err_to_name(err));
return err;
} else {
// refresh does not correctly work after recovering from deep sleep due to sram reset
{
ESP_LOGI(TAG, "Waiting for display to be idle...");
TransactionGuard transaction_guard(this->epd_handler_);
err = transaction_guard.begin(pdMS_TO_TICKS(10000));
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to begin transaction for display refresh: %s", esp_err_to_name(err));
return err;
}
if (is_deep_sleep_) {
epd_init_internal_(transaction_guard.transaction_id());
}
epd_handler_.wait_for_idle();
ESP_LOGI(TAG, "Starting display refresh...");
err = epd_handler_.epd_write_cmd(0x92, transaction_guard.transaction_id()); // enter normal mode
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to enter normal mode: %s", esp_err_to_name(err));
return err;
}
err = epd_handler_.epd_write_cmd(0x12, transaction_guard.transaction_id()); // display refresh
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to send display refresh command: %s", esp_err_to_name(err));
return err;
}
vTaskDelay(pdMS_TO_TICKS(MINIMUM_PIN_SETUP_DELAY_MS)); // at least 200us delay
epd_handler_.wait_for_idle();
}
vTaskDelay(pdMS_TO_TICKS(MINIMUM_PIN_SETUP_DELAY_MS)); // at least 200us delay
epd_handler_.wait_for_idle();
}
{
@@ -235,6 +247,7 @@ esp_err_t EInkDisplayHandler::partial_refresh(const uint8_t* incoming_partial_fr
ESP_LOGI(TAG, "Partial refresh skipped (not last partial update)");
return ESP_OK;
}
{
TransactionGuard transaction_guard(this->epd_handler_);
err = transaction_guard.begin(pdMS_TO_TICKS(5000));
@@ -359,7 +372,7 @@ esp_err_t EInkDisplayHandler::partial_refresh(const uint8_t* incoming_partial_fr
// Send only the partial area data, not the full display buffer
ESP_LOGI(TAG, "Sending new partial buffer: %zu bytes (area: %dx%d)",
partial_buffer_size, area_width_bytes * 8, area_height);
err = epd_handler_.transfer_spi_data(partial_buffer, partial_buffer_size, transaction_guard.transaction_id());
err = epd_handler_.transfer_spi_data(partial_buffer, partial_buffer_size, transaction_guard.transaction_id(), true); // Inverted for partial refresh
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to send partial_buffer data for partial refresh: %s", esp_err_to_name(err));
heap_caps_free(partial_buffer);
@@ -391,6 +404,13 @@ esp_err_t EInkDisplayHandler::partial_refresh(const uint8_t* incoming_partial_fr
}
}
ESP_LOGI(TAG, "Partial refresh complete");
err = deep_sleep_display();
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to enter deep sleep after partial refresh: %s", esp_err_to_name(err));
return err;
}
if (force_full_refresh_) {
ESP_LOGI(TAG, "Full refresh already requested, skipping partial refresh count increment");
err = refresh_display();
@@ -400,6 +420,7 @@ esp_err_t EInkDisplayHandler::partial_refresh(const uint8_t* incoming_partial_fr
}
return ESP_OK;
}
{
SemaphoreGuard guard(refresh_mutex_);
if (guard.take(pdMS_TO_TICKS(5000)) != pdTRUE) {
@@ -418,11 +439,6 @@ esp_err_t EInkDisplayHandler::partial_refresh(const uint8_t* incoming_partial_fr
}
}
err = deep_sleep_display();
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to enter deep sleep after partial refresh: %s", esp_err_to_name(err));
return err;
}
refresh_area_.reset();