no more error in display, but no refresh
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user