no more error in display, but no refresh

This commit is contained in:
GW_MC
2026-01-25 15:28:07 +08:00
parent 580d6a0a5b
commit 57f698425b
3 changed files with 46 additions and 16 deletions

View File

@@ -107,6 +107,12 @@ void EInkDisplayHandler::init() {
}
memset(_framebuffer, 0xFF, DISPLAY_BUFFER_SIZE); // Initialize to white
// Perform initial full refresh to clear display BEFORE creating LVGL display
// This prevents LVGL from trying to render during the initial clear
ESP_LOGI(TAG, "Performing initial display clear...");
_perform_full_refresh(_framebuffer);
ESP_LOGI(TAG, "Initial display clear complete");
// Create LVGL display manually (no esp_lcd panel for e-paper)
lv_display_t* disp = lv_display_create(DISPLAY_WIDTH, DISPLAY_HEIGHT);
if (disp == nullptr) {
@@ -160,10 +166,6 @@ void EInkDisplayHandler::init() {
ESP_LOGI(TAG, "LVGL touch input registered");
}
// Perform initial full refresh to clear display
ESP_LOGI(TAG, "Performing initial display clear...");
_perform_full_refresh(_framebuffer);
// Set display ready bits
xEventGroupSetBits(_system_event_group, DISPLAY_READY_BIT | TOUCH_CALIBRATED_BIT);
ESP_LOGI(TAG, "E-Ink display handler initialized successfully");
@@ -290,6 +292,7 @@ void EInkDisplayHandler::_lvgl_touch_read_cb(lv_indev_t* indev, lv_indev_data_t*
esp_lcd_touch_get_data(tp_handle, point_data, &touch_cnt, 1);
if (touch_cnt > 0) {
ESP_LOGI(TAG, "Touch data read successfully: x=%d, y=%d", point_data[0].x, point_data[0].y);
data->point.x = point_data[0].x;
data->point.y = point_data[0].y;
data->state = LV_INDEV_STATE_PRESSED;
@@ -344,17 +347,17 @@ void EInkDisplayHandler::_perform_full_refresh(const uint8_t* framebuffer) {
xSemaphoreGive(_spi_mutex);
// Step 2: Write new data (0x13) with data inversion
// Step 2: Write new data (0x13)
epd_write_cmd(0x13);
xSemaphoreTake(_spi_mutex, portMAX_DELAY);
gpio_set_level(PIN_DC, 1); // Data mode
// Use queued transactions with inverted framebuffer data
static uint8_t tx_buffer[100]; // Buffer for batch of inverted bytes
// Use queued transactions with framebuffer data
static uint8_t tx_buffer[100]; // Buffer for batch of bytes
for (size_t i = 0; i < DISPLAY_BUFFER_SIZE; i++) {
size_t buf_idx = i % 100;
tx_buffer[buf_idx] = ~framebuffer[i]; // Invert data per manufacturer spec
tx_buffer[buf_idx] = framebuffer[i]; // Write data directly (no inversion)
spi_transaction_t t = {};
t.length = 8;
@@ -415,18 +418,29 @@ void EInkDisplayHandler::_perform_partial_refresh(const uint8_t* framebuffer) {
};
epd_write_cmd_with_data(0x90, window_data, 9);
// Step 4: Write new data with inversion (0x13 command)
// Step 4: Write new data (0x13 command)
epd_write_cmd(0x13);
xSemaphoreTake(_spi_mutex, portMAX_DELAY);
gpio_set_level(PIN_DC, 1); // Data mode
// Send data in chunks with task yields to prevent blocking
static uint8_t tx_byte;
const size_t CHUNK_SIZE = 1000; // Send 1000 bytes between yields
for (size_t i = 0; i < DISPLAY_BUFFER_SIZE; i++) {
tx_byte = framebuffer[i]; // Write data directly (no inversion)
spi_transaction_t t = {};
t.length = 8;
uint8_t byte = ~framebuffer[i]; // Invert data per manufacturer spec
t.tx_buffer = &byte;
t.tx_buffer = &tx_byte;
spi_device_polling_transmit(_spi, &t);
// Yield to other tasks every CHUNK_SIZE bytes
if (i % CHUNK_SIZE == (CHUNK_SIZE - 1)) {
xSemaphoreGive(_spi_mutex);
vTaskDelay(1); // Allow other tasks to run
xSemaphoreTake(_spi_mutex, portMAX_DELAY);
gpio_set_level(PIN_DC, 1); // Re-set data mode after yield
}
}
xSemaphoreGive(_spi_mutex);
@@ -446,10 +460,10 @@ void EInkDisplayHandler::_perform_partial_refresh(const uint8_t* framebuffer) {
void EInkDisplayHandler::_wait_for_busy() {
ESP_LOGI(TAG, "Waiting for display ready (BUSY pin)...");
int timeout = 0;
while (gpio_get_level(PIN_BUSY) == BUSY_INACTIVE_LEVEL) { // 0=BUSY, 1=FREE
while (gpio_get_level(PIN_BUSY) == BUSY_ACTIVE_LEVEL) { // 0=BUSY, 1=FREE
vTaskDelay(pdMS_TO_TICKS(100));
timeout++;
if (timeout > 50) { // 5 second timeout
if (timeout > 100) { // 10 second timeout
ESP_LOGW(TAG, "Display BUSY timeout!");
break;
}