Files
ink-board/main/main.cpp

223 lines
7.0 KiB
C++

#include <stdio.h>
#include <inttypes.h>
#include <stdexcept>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_chip_info.h"
#include "esp_flash.h"
#include "esp_system.h"
#include "esp_log.h"
#include "esp_event.h"
//
#include "common/constants.h"
#include "common/queue_defs.h"
#include "common/system_context.h"
#include "io/nvs_handler.h"
#include "io/fs_handler.h"
#include "info/info.h"
#include "display/eink_display_handler.h"
#include "display/lvgl_handler.h"
#include "ui/ui_handler.h"
#include "ui/apps/registry.h"
#include <tick/lv_tick.h>
#include "esp_lvgl_port.h"
#include "lvgl.h"
#include "network.h"
#include <esp_task_wdt.h>
#include "lvgl.h"
#include <esp_netif_sntp.h>
// nvs storage namespaces, 15 characters max
#define DEFAULT_STORAGE_NAMESPACE "storage"
#define TAG "Main"
extern "C" void app_main(void);
void init_queues(
QueueHandle_t& touch_queue,
EventGroupHandle_t& system_event_group,
EventGroupHandle_t& system_lifecycle_event_group
);
void app_main(void) {
display_chip_info();
// set to hkt
setenv("TZ", "HKT-8", 1);
tzset();
// Initialize default event loop early - required for UI events
esp_err_t err = esp_event_loop_create_default();
if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) {
ESP_LOGE(TAG, "Failed to create default event loop: %s", esp_err_to_name(err));
vTaskDelay(5000 / portTICK_PERIOD_MS);
return esp_restart();
}
ESP_LOGI(TAG, "Default event loop created.\n");
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 fs_handler = std::make_shared<LittleFSHandler>();
esp_err_t fs_err = fs_handler->init("/littlefs");
if (fs_err != ESP_OK) {
ESP_LOGE(TAG, "Failed to initialize LittleFS: %s", esp_err_to_name(fs_err));
vTaskDelay(5000 / portTICK_PERIOD_MS);
return esp_restart();
}
auto wifi_handler = std::make_unique<WifiHandler>(fs_handler);
NetworkHandler* network_handler = new NetworkHandler(std::move(wifi_handler));
EInkDisplayHandler* display_handler = new EInkDisplayHandler();
// Initialize display and touch
// display_handler->init_devices(system_event_group);
display_handler->init_devices();
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));
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);
// Make network handler available to apps
SystemContext::instance().set_network_handler(network_handler);
//
ESP_LOGI(TAG, "Waiting for system to be ready...\n");
xEventGroupWaitBits(
system_event_group,
DISPLAY_READY_BIT | NETWORK_READY_BIT,
// do not clear on exit, require explicit reset
pdFALSE,
pdTRUE,
portMAX_DELAY
);
esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG("pool.ntp.org");
esp_netif_sntp_init(&config);
ESP_LOGI(TAG, "System is ready. Starting main application...\n");
AppRegistry& app_registry = AppRegistry::instance();
err = app_registry.init();
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to initialize App Registry: %s", esp_err_to_name(err));
vTaskDelay(5000 / portTICK_PERIOD_MS);
return esp_restart();
}
UIHandler ui_handler;
err = ui_handler.init();
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to initialize UI handler: %s", esp_err_to_name(err));
vTaskDelay(5000 / portTICK_PERIOD_MS);
return esp_restart();
}
ESP_LOGI(TAG, "UI handler initialized.\n");
// Allow LVGL system to stabilize before creating objects
vTaskDelay(pdMS_TO_TICKS(100));
// wait for shutdown signal
ESP_LOGI(TAG, "Waiting for shutdown signal...\n");
EventBits_t bits = xEventGroupWaitBits(
system_lifecycle_event_group,
SYSTEM_SHUTDOWN_BIT | SYSTEM_RESTART_BIT,
// do not clear on exit, require explicit reset
pdFALSE,
pdFALSE,
portMAX_DELAY
);
ESP_LOGI(TAG, "Shutdown signal received. Cleaning up...\n");
// Show shutdown screen using the shutdown descriptor's app instance
// ShutdownApp* shutdown_app = dynamic_cast<ShutdownApp*>(shutdown_descriptor->get_app_instance());
// if (shutdown_app) {
// ui_handler.switch_app(shutdown_app);
// }
vTaskDelay(1000 / portTICK_PERIOD_MS); // Display shutdown message briefly
// Cleanup
// ui_handler.deinit();
// delete demo_descriptor;
// delete shutdown_descriptor;
// delete mtr_descriptor;
vEventGroupDelete(system_event_group);
vQueueDelete(touch_event_queue);
ESP_LOGI(TAG, "Cleanup complete.\n");
// handle shutdown or restart
if (bits & SYSTEM_SHUTDOWN_BIT) {
// if (shutdown_display_handler != nullptr) {
// ESP_LOGI(TAG, "Calling display shutdown handler...\n");
// shutdown_display_handler();
// } else {
// ESP_LOGI(TAG, "No display shutdown handler to call.\n");
// }
ESP_LOGI(TAG, "System is shutting down.\n");
fflush(stdout);
// wait for start bit to be set again if future restart is desired, else expect manual power cycle
EventBits_t bits = xEventGroupWaitBits(
system_lifecycle_event_group,
SYSTEM_START_BIT,
pdFALSE,
pdFALSE,
portMAX_DELAY
);
if (bits & SYSTEM_START_BIT) {
ESP_LOGI(TAG, "SYSTEM_START_BIT received, restarting system.\n");
} else {
ESP_LOGW(TAG, "No restart signal received, waiting for manual power cycle.\n");
while (true) {
vTaskDelay(portMAX_DELAY);
}
}
} else if (bits & SYSTEM_RESTART_BIT) {
// if (restart_display_handler != nullptr) {
// ESP_LOGI(TAG, "Calling display restart handler...\n");
// restart_display_handler();
// } else {
// ESP_LOGI(TAG, "No display restart handler to call.\n");
// }
ESP_LOGI(TAG, "System is restarting.\n");
fflush(stdout);
} else {
ESP_LOGW(TAG, "Unknown shutdown signal received. Restarting by default.\n");
fflush(stdout);
}
return esp_restart();
}
void init_queues(
QueueHandle_t& touch_queue,
EventGroupHandle_t& system_event_group,
EventGroupHandle_t& system_lifecycle_event_group
) {
// Implementation of queue initialization
touch_queue = xQueueCreate(10, sizeof(touch_event_t));
system_event_group = xEventGroupCreate();
system_lifecycle_event_group = xEventGroupCreate();
}