From 90ac69ab9c9a3e97393ad9377e8b978719cfff13 Mon Sep 17 00:00:00 2001 From: nick Date: Tue, 9 Jun 2026 21:46:59 -0600 Subject: [PATCH] dashboard: replace lvgl demo with overland boot screen --- firmware/esp32-s3-dashboard/README.md | 16 ++ .../esp32-s3-dashboard/esp32-s3-dashboard.ino | 154 +++++++++++------- 2 files changed, 115 insertions(+), 55 deletions(-) diff --git a/firmware/esp32-s3-dashboard/README.md b/firmware/esp32-s3-dashboard/README.md index a74b963..8ae24ef 100644 --- a/firmware/esp32-s3-dashboard/README.md +++ b/firmware/esp32-s3-dashboard/README.md @@ -36,3 +36,19 @@ Arduino IDE expects the primary `.ino` filename to match the folder name. Current sketch path: firmware/esp32-s3-dashboard/esp32-s3-dashboard.ino + + +## Current Bring-Up Screen + +The dashboard sketch now replaces the stock Waveshare LVGL demo with a simple Overland Controller boot/status screen. + +Current screen shows: + +- Overland Controller title +- Waveshare ESP32-S3 Touch LCD 5B hardware target +- 1024x600 display note +- `/api/v1` Cargo API base +- WiFi placeholder +- Touch test button + +This is intentionally not connected to WiFi or the Cargo ESP yet. diff --git a/firmware/esp32-s3-dashboard/esp32-s3-dashboard.ino b/firmware/esp32-s3-dashboard/esp32-s3-dashboard.ino index 0efab77..54ee61a 100644 --- a/firmware/esp32-s3-dashboard/esp32-s3-dashboard.ino +++ b/firmware/esp32-s3-dashboard/esp32-s3-dashboard.ino @@ -3,93 +3,137 @@ #include #include "lvgl_v8_port.h" -#include using namespace esp_panel::drivers; using namespace esp_panel::board; -/** - * To use the built-in examples and demos of LVGL uncomment the includes below respectively. - */ - // #include - // #include +static lv_obj_t *touch_count_label = nullptr; +static uint32_t touch_count = 0; + +static void touch_test_event_cb(lv_event_t *event) +{ + if (lv_event_get_code(event) != LV_EVENT_CLICKED) { + return; + } + + touch_count++; + + if (touch_count_label != nullptr) { + lv_label_set_text_fmt(touch_count_label, "Touch test count: %lu", (unsigned long)touch_count); + } + + Serial.print("Touch test count: "); + Serial.println(touch_count); +} + +static void create_overland_boot_screen() +{ + lv_obj_t *screen = lv_scr_act(); + lv_obj_clean(screen); + + lv_obj_set_style_bg_color(screen, lv_color_hex(0x101418), 0); + + lv_obj_t *title = lv_label_create(screen); + lv_label_set_text(title, "Overland Controller"); + lv_obj_set_style_text_color(title, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(title, &lv_font_montserrat_30, 0); + lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 40); + + lv_obj_t *subtitle = lv_label_create(screen); + lv_label_set_text(subtitle, "ESP32-S3 Dashboard Bring-Up"); + lv_obj_set_style_text_color(subtitle, lv_color_hex(0xB8C0C8), 0); + lv_obj_set_style_text_font(subtitle, &lv_font_montserrat_20, 0); + lv_obj_align_to(subtitle, title, LV_ALIGN_OUT_BOTTOM_MID, 0, 12); + + lv_obj_t *card = lv_obj_create(screen); + lv_obj_set_size(card, 760, 330); + lv_obj_align(card, LV_ALIGN_CENTER, 0, 25); + lv_obj_set_style_radius(card, 18, 0); + lv_obj_set_style_bg_color(card, lv_color_hex(0x1F2933), 0); + lv_obj_set_style_border_color(card, lv_color_hex(0x3A4652), 0); + lv_obj_set_style_border_width(card, 2, 0); + lv_obj_set_style_pad_all(card, 24, 0); + + lv_obj_t *status = lv_label_create(card); + lv_label_set_text( + status, + "Hardware: Waveshare ESP32-S3 Touch LCD 5B\n" + "Display: 1024 x 600\n" + "Touch: Capacitive\n" + "Cargo API Base: /api/v1\n" + "WiFi: Not connected yet\n" + "Mode: Local dashboard bring-up" + ); + lv_obj_set_style_text_color(status, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(status, &lv_font_montserrat_20, 0); + lv_obj_set_style_text_line_space(status, 10, 0); + lv_obj_align(status, LV_ALIGN_TOP_LEFT, 0, 0); + + lv_obj_t *button = lv_btn_create(card); + lv_obj_set_size(button, 260, 72); + lv_obj_align(button, LV_ALIGN_BOTTOM_LEFT, 0, 0); + lv_obj_add_event_cb(button, touch_test_event_cb, LV_EVENT_CLICKED, nullptr); + + lv_obj_t *button_label = lv_label_create(button); + lv_label_set_text(button_label, "Touch Test"); + lv_obj_set_style_text_font(button_label, &lv_font_montserrat_20, 0); + lv_obj_center(button_label); + + touch_count_label = lv_label_create(card); + lv_label_set_text(touch_count_label, "Touch test count: 0"); + lv_obj_set_style_text_color(touch_count_label, lv_color_hex(0xB8C0C8), 0); + lv_obj_set_style_text_font(touch_count_label, &lv_font_montserrat_20, 0); + lv_obj_align(touch_count_label, LV_ALIGN_BOTTOM_LEFT, 300, -22); + + lv_obj_t *footer = lv_label_create(screen); + lv_label_set_text(footer, "Next: WiFi client -> GET /api/v1/status from Cargo ESP"); + lv_obj_set_style_text_color(footer, lv_color_hex(0x7D8996), 0); + lv_obj_set_style_text_font(footer, &lv_font_montserrat_16, 0); + lv_obj_align(footer, LV_ALIGN_BOTTOM_MID, 0, -28); +} void setup() { - String title = "LVGL porting example"; - Serial.begin(115200); + delay(1000); + + Serial.println(); + Serial.println("================================"); + Serial.println("Overland Controller Dashboard"); + Serial.println("================================"); + Serial.println("Target: Waveshare ESP32-S3 Touch LCD 5B"); + Serial.println("Display: 1024x600"); + Serial.println("API Base: /api/v1"); Serial.println("Initializing board"); Board *board = new Board(); board->init(); - #if LVGL_PORT_AVOID_TEARING_MODE +#if LVGL_PORT_AVOID_TEARING_MODE auto lcd = board->getLCD(); - // When avoid tearing function is enabled, the frame buffer number should be set in the board driver lcd->configFrameBufferNumber(LVGL_PORT_DISP_BUFFER_NUM); #if ESP_PANEL_DRIVERS_BUS_ENABLE_RGB && CONFIG_IDF_TARGET_ESP32S3 auto lcd_bus = lcd->getBus(); - /** - * As the anti-tearing feature typically consumes more PSRAM bandwidth, for the ESP32-S3, we need to utilize the - * "bounce buffer" functionality to enhance the RGB data bandwidth. - * This feature will consume `bounce_buffer_size * bytes_per_pixel * 2` of SRAM memory. - */ if (lcd_bus->getBasicAttributes().type == ESP_PANEL_BUS_TYPE_RGB) { static_cast(lcd_bus)->configRGB_BounceBufferSize(lcd->getFrameWidth() * 10); } #endif #endif + assert(board->begin()); Serial.println("Initializing LVGL"); lvgl_port_init(board->getLCD(), board->getTouch()); - Serial.println("Creating UI"); - /* Lock the mutex due to the LVGL APIs are not thread-safe */ + Serial.println("Creating Overland boot screen"); lvgl_port_lock(-1); - - /** - * Create the simple labels - */ - lv_obj_t *label_1 = lv_label_create(lv_scr_act()); - lv_label_set_text(label_1, "Hello World!"); - lv_obj_set_style_text_font(label_1, &lv_font_montserrat_30, 0); - lv_obj_align(label_1, LV_ALIGN_CENTER, 0, -20); - lv_obj_t *label_2 = lv_label_create(lv_scr_act()); - lv_label_set_text_fmt( - label_2, "ESP32_Display_Panel (%d.%d.%d)", - ESP_PANEL_VERSION_MAJOR, ESP_PANEL_VERSION_MINOR, ESP_PANEL_VERSION_PATCH - ); - lv_obj_set_style_text_font(label_2, &lv_font_montserrat_16, 0); - lv_obj_align_to(label_2, label_1, LV_ALIGN_OUT_BOTTOM_MID, 0, 10); - lv_obj_t *label_3 = lv_label_create(lv_scr_act()); - lv_label_set_text_fmt(label_3, "LVGL (%d.%d.%d)", LVGL_VERSION_MAJOR, LVGL_VERSION_MINOR, LVGL_VERSION_PATCH); - lv_obj_set_style_text_font(label_3, &lv_font_montserrat_16, 0); - lv_obj_align_to(label_3, label_2, LV_ALIGN_OUT_BOTTOM_MID, 0, 10); - - /** - * Try an example. Don't forget to uncomment header. - * See all the examples online: https://docs.lvgl.io/master/examples.html - * source codes: https://github.com/lvgl/lvgl/tree/e7f88efa5853128bf871dde335c0ca8da9eb7731/examples - */ - // lv_example_btn_1(); - - /** - * Or try out a demo. - * Don't forget to uncomment header and enable the demos in `lv_conf.h`. E.g. `LV_USE_DEMO_WIDGETS` - */ - lv_demo_widgets(); - // lv_demo_benchmark(); - // lv_demo_music(); - // lv_demo_stress(); - - /* Release the mutex */ + create_overland_boot_screen(); lvgl_port_unlock(); + + Serial.println("Dashboard boot screen ready"); } void loop() { - Serial.println("IDLE loop"); delay(1000); }