Added lvgl init, display not refresh correctly

This commit is contained in:
GW_MC
2026-01-26 22:50:02 +08:00
parent 30dfdd630a
commit 6fbbfcde4f
4 changed files with 585 additions and 120 deletions

View File

@@ -15,6 +15,7 @@
#include "io/nvs_handler.h"
#include "info/info.h"
#include "display/eink_display_handler.h"
#include "display/lvgl_handler.h"
#include "ui/ui_handler.h"
#include "ui/app_registry.h"
#include "ui/apps/shutdown_app.h"
@@ -26,6 +27,8 @@
#include "network.h"
#include <esp_task_wdt.h>
#include "lvgl.h"
// nvs storage namespaces, 15 characters max
#define DEFAULT_STORAGE_NAMESPACE "storage"
#define WIFI_CREDENTIALS_STORAGE_NAMESPACE "wifi_cred"
@@ -40,120 +43,10 @@ void init_queues(
);
void app_main(void) {
display_chip_info();
QueueHandle_t touch_event_queue = NULL;
EventGroupHandle_t system_event_group = NULL, system_lifecycle_event_group = NULL;
init_queues(touch_event_queue, system_event_group, system_lifecycle_event_group);
if (touch_event_queue == NULL || system_event_group == NULL || system_lifecycle_event_group == NULL) {
ESP_LOGE("Main", "Failed to create one or more queues/event groups");
vTaskDelay(5000 / portTICK_PERIOD_MS);
return esp_restart();
}
ESP_LOGI(TAG, "Queues initialized.\n");
// Initialize LVGL
const lvgl_port_cfg_t lvgl_cfg = ESP_LVGL_PORT_INIT_CONFIG();
esp_err_t err = lvgl_port_init(&lvgl_cfg);
if (err != ESP_OK) {
ESP_LOGE(TAG, "LVGL port initialization failed: %s", esp_err_to_name(err));
vTaskDelay(5000 / portTICK_PERIOD_MS);
return esp_restart();
}
ESP_LOGI(TAG, "LVGL port initialized successfully.\n");
SemaphoreHandle_t lvgl_mutex = xSemaphoreCreateMutex();
if (lvgl_mutex == NULL) {
ESP_LOGE("Main", "Failed to create LVGL mutex");
vTaskDelay(5000 / portTICK_PERIOD_MS);
return esp_restart();
}
//
// KVStorageHandler* kv_storage_handler = new NVSStorageHandler(
// DEFAULT_STORAGE_NAMESPACE
// );
// auto wifi_handler = std::make_unique<WifiHandler>(
// std::unique_ptr<KVStorageHandler>(new NVSStorageHandler(WIFI_CREDENTIALS_STORAGE_NAMESPACE))
// );
// NetworkHandler* network_handler = new NetworkHandler(std::move(wifi_handler));
EInkDisplayHandler* display_handler = new EInkDisplayHandler();
//
// kv_storage_handler->init(system_event_group);
// network_handler->init(system_event_group);
// Initialize display and touch
display_handler->init_devices(system_event_group);
display_handler->clear_display();
// ESP_LOGV(TAG, "Starting touch task...\n");
// display_handler->start_touch_task();
// ESP_LOGV(TAG, "Touch task started.\n");
//
// LVGL tick timer
// auto lvgl_tick_timer_callback = [](TimerHandle_t xTimer) {
// lv_tick_inc(5);
// };
// TickType_t lvgl_tick_period = pdMS_TO_TICKS(5);
// if (lvgl_tick_period == 0) {
// lvgl_tick_period = 1; // ensure at least 1 tick to avoid FreeRTOS assert
// }
// ESP_LOGV(TAG, "Creating LVGL tick timer with period %u ticks...\n", (unsigned)lvgl_tick_period);
// TimerHandle_t lvgl_tick_timer = xTimerCreate(
// "lvgl_tick_timer",
// lvgl_tick_period,
// pdTRUE,
// NULL,
// lvgl_tick_timer_callback
// );
// if (lvgl_tick_timer == NULL) {
// ESP_LOGE("Main", "Failed to create LVGL tick timer");
// vTaskDelay(5000 / portTICK_PERIOD_MS);
// return esp_restart();
// }
// ESP_LOGV(TAG, "Starting LVGL tick timer...\n");
// xTimerStart(lvgl_tick_timer, 0);
//
ESP_LOGI(TAG, "Waiting for system to be ready...\n");
xEventGroupWaitBits(
system_event_group,
// DISPLAY_READY_BIT | STORAGE_READY_BIT | NETWORK_READY_BIT,
DISPLAY_READY_BIT,
// do not clear on exit, require explicit reset
pdFALSE,
pdTRUE,
portMAX_DELAY
);
ESP_LOGI(TAG, "System is ready. Starting main application...\n");
// Register apps with AppRegistry by creating their descriptors
// Each descriptor will create and register the app instance
// DemoAppDescriptor* demo_descriptor = new DemoAppDescriptor();
// ShutdownAppDescriptor* shutdown_descriptor = new ShutdownAppDescriptor();
// DiscordAppDescriptor::instance(); // Use singleton pattern for Discord app
// MtrAppDescriptor* mtr_descriptor = new MtrAppDescriptor();
// Pass network handler to MtrApp so it can fetch arrival data
// MtrApp* mtr_app = dynamic_cast<MtrApp*>(mtr_descriptor->get_app_instance());
// if (mtr_app) {
// mtr_app->set_network_handler(network_handler);
// }
// ESP_LOGI(TAG, "Apps registered with AppRegistry\n");
// Initialize UI Handler (will render app icons from registry)
// UIHandler ui_handler;
// if (ui_handler.init() != ESP_OK) {
// ESP_LOGE(TAG, "Failed to initialize UI handler");
// vTaskDelay(5000 / portTICK_PERIOD_MS);
// return esp_restart();
// }
// ESP_LOGI(TAG, "UI handler initialized successfully\n");
// ESP_LOGI(TAG, "Main screen displayed with app icons. Tap an icon to launch an app.\n");
// Run checkerboard draw in its own FreeRTOS task to avoid watchdog triggers
void EInk_Checkerboard(
EInkDisplayHandler* display_handler
) {
struct CheckerboardTaskParams {
EInkDisplayHandler* display_handler;
};
@@ -230,6 +123,181 @@ void app_main(void) {
ESP_LOGE(TAG, "Failed to create checkerboard task");
delete checker_params;
}
}
void LVGL_Checkerboard(
LVGLHandler* lvgl_handler
) {
struct CheckerboardTaskParams {
LVGLHandler* lvgl_handler;
};
auto checkerboard_task_fn = [](void* pvParameters) {
CheckerboardTaskParams* params = static_cast<CheckerboardTaskParams*>(pvParameters);
if (params == nullptr || params->lvgl_handler == nullptr) {
ESP_LOGE(TAG, "Invalid parameters for LVGL checkerboard task");
delete params;
vTaskDelete(NULL);
return;
}
auto* handler = static_cast<LVGLHandler*>(params->lvgl_handler);
// Add safety checks
if (!handler) {
ESP_LOGE("LVGL", "Handler is null!");
return;
}
ESP_LOGI("HEAP", "Free: %d", esp_get_free_heap_size());
// Acquire LVGL lock with proper timeout
if (!lvgl_port_lock(pdMS_TO_TICKS(1000))) {
ESP_LOGE(TAG, "Failed to acquire LVGL lock for checkerboard");
delete params;
vTaskDelete(NULL);
return;
}
// Create LVGL objects for checkerboard
lv_obj_t* scr = lv_scr_act();
if (scr == nullptr) {
ESP_LOGE(TAG, "Failed to get active LVGL screen");
lvgl_port_unlock();
delete params;
vTaskDelete(NULL);
return;
}
lv_obj_t* checkerboard = lv_obj_create(scr);
if (checkerboard == nullptr) {
ESP_LOGE(TAG, "Failed to create LVGL checkerboard object");
lvgl_port_unlock();
delete params;
vTaskDelete(NULL);
return;
}
lv_obj_set_size(checkerboard, DISPLAY_WIDTH, DISPLAY_HEIGHT);
lv_obj_center(checkerboard);
const int CELL_SIZE = 40;
// Create checkerboard pattern using LVGL
for (int y = 0; y < DISPLAY_HEIGHT; y += CELL_SIZE) {
for (int x = 0; x < DISPLAY_WIDTH; x += CELL_SIZE) {
lv_color_t color = (((x / CELL_SIZE) % 2) == ((y / CELL_SIZE) % 2)) ? lv_color_hex(0xFFFFFF) : lv_color_hex(0x000000);
lv_obj_t* cell = lv_obj_create(checkerboard);
if (cell == nullptr) {
ESP_LOGE(TAG, "Failed to create LVGL checkerboard cell");
continue;
}
lv_obj_set_size(cell, CELL_SIZE, CELL_SIZE);
lv_obj_set_style_bg_color(cell, color, 0);
lv_obj_set_pos(cell, x, y);
}
}
ESP_LOGI(TAG, "LVGL Checkerboard pattern displayed successfully.");
lvgl_port_unlock();
delete params;
vTaskDelete(NULL);
};
CheckerboardTaskParams* checker_params = new CheckerboardTaskParams();
checker_params->lvgl_handler = lvgl_handler;
BaseType_t res = xTaskCreate(
checkerboard_task_fn,
"lvgl_checkerboard_task",
8192,
static_cast<void*>(checker_params),
tskIDLE_PRIORITY + 1,
NULL
);
if (res != pdPASS) {
ESP_LOGE(TAG, "Failed to create LVGL checkerboard task");
delete checker_params;
}
}
void app_main(void) {
display_chip_info();
QueueHandle_t touch_event_queue = NULL;
EventGroupHandle_t system_event_group = NULL, system_lifecycle_event_group = NULL;
init_queues(touch_event_queue, system_event_group, system_lifecycle_event_group);
if (touch_event_queue == NULL || system_event_group == NULL || system_lifecycle_event_group == NULL) {
ESP_LOGE("Main", "Failed to create one or more queues/event groups");
vTaskDelay(5000 / portTICK_PERIOD_MS);
return esp_restart();
}
ESP_LOGI(TAG, "Queues initialized.\n");
//
// KVStorageHandler* kv_storage_handler = new NVSStorageHandler(
// DEFAULT_STORAGE_NAMESPACE
// );
// auto wifi_handler = std::make_unique<WifiHandler>(
// std::unique_ptr<KVStorageHandler>(new NVSStorageHandler(WIFI_CREDENTIALS_STORAGE_NAMESPACE))
// );
// NetworkHandler* network_handler = new NetworkHandler(std::move(wifi_handler));
EInkDisplayHandler* display_handler = new EInkDisplayHandler();
// Initialize display and touch
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();
}
//
// kv_storage_handler->init(system_event_group);
// network_handler->init(system_event_group);
//
ESP_LOGI(TAG, "Waiting for system to be ready...\n");
xEventGroupWaitBits(
system_event_group,
// DISPLAY_READY_BIT | STORAGE_READY_BIT | NETWORK_READY_BIT,
DISPLAY_READY_BIT,
// do not clear on exit, require explicit reset
pdFALSE,
pdTRUE,
portMAX_DELAY
);
ESP_LOGI(TAG, "System is ready. Starting main application...\n");
// Show checkerboard pattern on display for testing
LVGL_Checkerboard(&lvgl_handler);
// Register apps with AppRegistry by creating their descriptors
// Each descriptor will create and register the app instance
// DemoAppDescriptor* demo_descriptor = new DemoAppDescriptor();
// ShutdownAppDescriptor* shutdown_descriptor = new ShutdownAppDescriptor();
// DiscordAppDescriptor::instance(); // Use singleton pattern for Discord app
// MtrAppDescriptor* mtr_descriptor = new MtrAppDescriptor();
// Pass network handler to MtrApp so it can fetch arrival data
// MtrApp* mtr_app = dynamic_cast<MtrApp*>(mtr_descriptor->get_app_instance());
// if (mtr_app) {
// mtr_app->set_network_handler(network_handler);
// }
// ESP_LOGI(TAG, "Apps registered with AppRegistry\n");
// Initialize UI Handler (will render app icons from registry)
// UIHandler ui_handler;
// if (ui_handler.init() != ESP_OK) {
// ESP_LOGE(TAG, "Failed to initialize UI handler");
// vTaskDelay(5000 / portTICK_PERIOD_MS);
// return esp_restart();
// }
// ESP_LOGI(TAG, "UI handler initialized successfully\n");
// ESP_LOGI(TAG, "Main screen displayed with app icons. Tap an icon to launch an app.\n");
// wait for shutdown signal
ESP_LOGI(TAG, "Waiting for shutdown signal...\n");
@@ -255,8 +323,7 @@ void app_main(void) {
// delete demo_descriptor;
// delete shutdown_descriptor;
// delete mtr_descriptor;
delete display_handler;
vSemaphoreDelete(lvgl_mutex);
vEventGroupDelete(system_event_group);
vQueueDelete(touch_event_queue);
ESP_LOGI(TAG, "Cleanup complete.\n");