From 3a5fb66a6f9da1c501de78f9b146d29ed04aff3d Mon Sep 17 00:00:00 2001 From: Fritz Heiden Date: Mon, 26 May 2025 18:57:35 +0200 Subject: [PATCH] refactor: make display class more concise --- include/lv_conf.h | 4 +- src/ui/display.cpp | 143 ++++++++++++++++++++++++++++++++------------- 2 files changed, 104 insertions(+), 43 deletions(-) diff --git a/include/lv_conf.h b/include/lv_conf.h index f604fbb..aab9a5d 100644 --- a/include/lv_conf.h +++ b/include/lv_conf.h @@ -861,14 +861,14 @@ #define LV_USE_SNAPSHOT 0 /*1: Enable system monitor component*/ -#define LV_USE_SYSMON 0 +#define LV_USE_SYSMON 1 #if LV_USE_SYSMON /*Get the idle percentage. E.g. uint32_t my_get_idle(void);*/ #define LV_SYSMON_GET_IDLE lv_timer_get_idle /*1: Show CPU usage and FPS count * Requires `LV_USE_SYSMON = 1`*/ - #define LV_USE_PERF_MONITOR 0 + #define LV_USE_PERF_MONITOR 1 #if LV_USE_PERF_MONITOR #define LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_RIGHT diff --git a/src/ui/display.cpp b/src/ui/display.cpp index 17c0d9b..950dd81 100644 --- a/src/ui/display.cpp +++ b/src/ui/display.cpp @@ -7,8 +7,6 @@ #include #include -#include - #ifndef SCREEN_WIDTH #define SCREEN_WIDTH 320 #endif @@ -17,27 +15,34 @@ #define SCREEN_HEIGHT 240 #endif -#define DRAW_BUF_SIZE (SCREEN_WIDTH * SCREEN_HEIGHT / 10 * (LV_COLOR_DEPTH / 8)) +#define DRAW_BUF_SIZE (SCREEN_WIDTH * SCREEN_HEIGHT / 6 * (LV_COLOR_DEPTH / 8)) namespace Display { - using std::vector; using UserInputManager::InputEvent; - const uint8_t MAIN_VIEW = 1; - const String USER_INPUT_HANDLE = "display"; - - uint32_t draw_buf[DRAW_BUF_SIZE / 4]; - uint32_t getTime(); void handleLvglLogs(lv_log_level_t level, const char *buf); - void handleUpdateValues(lv_timer_t *timer); + void handleUpdateView(lv_timer_t *timer); void handleReadUserInput(lv_indev_t *indev, lv_indev_data_t *data); void setCurrentView(uint8_t view); + lv_display_t *setupDisplay(); + lv_indev_t *setupInputDevice(); + static void flushCallback(lv_display_t *disp, const lv_area_t *area, uint8_t *px_map); + static void resolutionChangedEventCallback(lv_event_t *e); - lv_timer_t *update_values_timer; + typedef struct + { + TFT_eSPI *tft; + } lv_tft_espi_t; + + const String USER_INPUT_HANDLE = "display"; + uint32_t draw_buf[DRAW_BUF_SIZE / 4]; + static lv_color_t *buf1 = (lv_color_t *)heap_caps_aligned_alloc(32, DRAW_BUF_SIZE, MALLOC_CAP_DMA); + static lv_color_t *buf2 = (lv_color_t *)heap_caps_aligned_alloc(32, DRAW_BUF_SIZE, MALLOC_CAP_DMA); + + lv_timer_t *update_view_timer; lv_indev_t *indev; - - uint8_t current_view = 0; + lv_display_t *display; void init() { @@ -45,19 +50,14 @@ namespace Display lv_log_register_print_cb(handleLvglLogs); lv_tick_set_cb(getTime); - update_values_timer = lv_timer_create(handleUpdateValues, 5, NULL); - lv_timer_ready(update_values_timer); + display = setupDisplay(); + indev = setupInputDevice(); - lv_display_t *display; - display = lv_tft_espi_create(SCREEN_HEIGHT, SCREEN_WIDTH, draw_buf, sizeof(draw_buf)); - lv_display_set_rotation(display, LV_DISPLAY_ROTATION_90); + lv_obj_t *parent = lv_screen_active(); + MainView::render(parent, indev); - UserInputManager::registerForEvents(USER_INPUT_HANDLE); - indev = lv_indev_create(); - lv_indev_set_type(indev, LV_INDEV_TYPE_KEYPAD); - lv_indev_set_read_cb(indev, handleReadUserInput); - - setCurrentView(MAIN_VIEW); + update_view_timer = lv_timer_create(handleUpdateView, 5, NULL); + lv_timer_ready(update_view_timer); } void update() @@ -65,6 +65,75 @@ namespace Display lv_timer_handler(); } + lv_display_t *setupDisplay() + { + void *buf = draw_buf; + uint32_t buf_size_bytes = sizeof(draw_buf); + + lv_tft_espi_t *dsc = (lv_tft_espi_t *)lv_malloc_zeroed(sizeof(lv_tft_espi_t)); + LV_ASSERT_MALLOC(dsc); + if (dsc == NULL) + return NULL; + + lv_display_t *disp = lv_display_create(SCREEN_HEIGHT, SCREEN_WIDTH); + if (disp == NULL) + { + lv_free(dsc); + return NULL; + } + + dsc->tft = new TFT_eSPI(SCREEN_HEIGHT, SCREEN_WIDTH); + dsc->tft->begin(); /* TFT init */ + dsc->tft->setRotation(0); + lv_display_set_driver_data(disp, (void *)dsc); + lv_display_set_flush_cb(disp, flushCallback); + lv_display_add_event_cb(disp, resolutionChangedEventCallback, LV_EVENT_RESOLUTION_CHANGED, NULL); + lv_display_set_buffers(disp, buf1, buf2, SCREEN_HEIGHT * SCREEN_WIDTH / 6, LV_DISPLAY_RENDER_MODE_PARTIAL); + lv_display_set_rotation(disp, LV_DISPLAY_ROTATION_90); + return disp; + } + + static void flushCallback(lv_display_t *disp, const lv_area_t *area, uint8_t *px_map) + { + lv_tft_espi_t *dsc = (lv_tft_espi_t *)lv_display_get_driver_data(disp); + + uint32_t w = (area->x2 - area->x1 + 1); + uint32_t h = (area->y2 - area->y1 + 1); + + dsc->tft->startWrite(); + dsc->tft->setAddrWindow(area->x1, area->y1, w, h); + dsc->tft->pushColors((uint16_t *)px_map, w * h, true); + dsc->tft->endWrite(); + + lv_display_flush_ready(disp); + } + + static void resolutionChangedEventCallback(lv_event_t *e) + { + lv_display_t *disp = (lv_display_t *)lv_event_get_target(e); + lv_tft_espi_t *dsc = (lv_tft_espi_t *)lv_display_get_driver_data(disp); + int32_t hor_res = lv_display_get_horizontal_resolution(disp); + int32_t ver_res = lv_display_get_vertical_resolution(disp); + lv_display_rotation_t rot = lv_display_get_rotation(disp); + + /* handle rotation */ + switch (rot) + { + case LV_DISPLAY_ROTATION_0: + dsc->tft->setRotation(0); /* Portrait orientation */ + break; + case LV_DISPLAY_ROTATION_90: + dsc->tft->setRotation(1); /* Landscape orientation */ + break; + case LV_DISPLAY_ROTATION_180: + dsc->tft->setRotation(2); /* Portrait orientation, flipped */ + break; + case LV_DISPLAY_ROTATION_270: + dsc->tft->setRotation(3); /* Landscape orientation, flipped */ + break; + } + } + void handleLvglLogs(lv_log_level_t level, const char *buf) { Serial.printf("LVGL: %s\r\n", buf); @@ -75,27 +144,19 @@ namespace Display return esp_timer_get_time() / 1000; } - void setCurrentView(uint8_t view) + void handleUpdateView(lv_timer_t *timer) { - current_view = view; - lv_obj_t *parent = lv_screen_active(); - lv_obj_clean(parent); - switch (view) - { - case MAIN_VIEW: - MainView::render(parent, indev); - break; - } + MainView::update(); } - void handleUpdateValues(lv_timer_t *timer) + lv_indev_t *setupInputDevice() { - switch (current_view) - { - case MAIN_VIEW: - MainView::update(); - break; - } + UserInputManager::registerForEvents(USER_INPUT_HANDLE); + lv_indev_t *indev = lv_indev_create(); + lv_indev_set_type(indev, LV_INDEV_TYPE_KEYPAD); + lv_indev_set_read_cb(indev, handleReadUserInput); + + return indev; } void handleReadUserInput(lv_indev_t *indev, lv_indev_data_t *data)