256 lines
8.2 KiB
C++
256 lines
8.2 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 "common/constants.h"
|
|
#include "common/queue_defs.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/app_registry.h"
|
|
#include "ui/apps/shutdown_app.h"
|
|
#include "ui/apps/discord_app.h"
|
|
#include "ui/apps/mtr_app.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"
|
|
|
|
// 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();
|
|
|
|
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));
|
|
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");
|
|
|
|
DiscordAppDescriptor::instance();
|
|
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));
|
|
|
|
// Create main screen and button for random rectangle demo
|
|
// lv_obj_t* scr = lv_scr_act();
|
|
|
|
// // Create a button
|
|
// lv_obj_t* btn = lv_btn_create(scr);
|
|
// lv_obj_set_size(btn, 200, 60);
|
|
// lv_obj_align(btn, LV_ALIGN_TOP_MID, 0, 20);
|
|
// lv_obj_set_style_border_width(btn, 2, 0);
|
|
// lv_obj_set_style_border_color(btn, lv_color_make(0, 0, 0), 0);
|
|
|
|
// // Add label to button
|
|
// lv_obj_t* label = lv_label_create(btn);
|
|
// lv_label_set_text(label, "Create Random Rect");
|
|
// lv_obj_center(label);
|
|
// lv_obj_set_style_text_color(label, lv_color_make(0, 0, 0), 0);
|
|
|
|
// // Event handler for button - creates random rectangles
|
|
// auto btn_event_cb = [](lv_event_t* e) {
|
|
// lv_obj_t* scr = lv_scr_act();
|
|
|
|
// // Create a random rectangle
|
|
// lv_obj_t* rect = lv_obj_create(scr);
|
|
|
|
// // Random size (30-100 pixels)
|
|
// lv_coord_t width = 30 + (esp_random() % 70);
|
|
// lv_coord_t height = 30 + (esp_random() % 70);
|
|
// lv_obj_set_size(rect, width, height);
|
|
|
|
// // Random position (avoid top 100px where button is)
|
|
// lv_coord_t x = esp_random() % (LV_HOR_RES - width);
|
|
// lv_coord_t y = 100 + (esp_random() % (LV_VER_RES - 100 - height));
|
|
// lv_obj_set_pos(rect, x, y);
|
|
|
|
// lv_obj_set_style_bg_color(rect, lv_color_make(0, 0, 0), 0);
|
|
// lv_obj_set_style_bg_opa(rect, LV_OPA_COVER, 0);
|
|
|
|
// // Make rectangle clickable
|
|
// lv_obj_add_flag(rect, LV_OBJ_FLAG_CLICKABLE);
|
|
|
|
// // Event handler to delete rectangle when clicked
|
|
// auto rect_event_cb = [](lv_event_t* e) {
|
|
// lv_obj_t* rect = static_cast<lv_obj_t*>(lv_event_get_target(e));
|
|
// lv_obj_del(rect);
|
|
// ESP_LOGI(TAG, "Rectangle deleted");
|
|
// };
|
|
|
|
// lv_obj_add_event_cb(rect, rect_event_cb, LV_EVENT_CLICKED, NULL);
|
|
|
|
// ESP_LOGI(TAG, "Created rectangle at (%d, %d) with size %dx%d", x, y, width, height);
|
|
// };
|
|
|
|
// lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_CLICKED, NULL);
|
|
|
|
// ESP_LOGI(TAG, "Random rectangle demo initialized. Tap button to create rectangles.\n");
|
|
|
|
// 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();
|
|
}
|