diff --git a/.claude/settings.local.json b/.claude/settings.local.json index cc4d5e74..87bf95aa 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -4,7 +4,9 @@ "Bash(pio)", "Bash(pio run)", "Bash(cpplint:*)", - "Bash(grep:*)" + "Bash(grep:*)", + "Bash(pio test:*)", + "Bash(pio run:*)" ], "deny": [] } diff --git a/inc/sp140/lvgl/lv_conf.h b/inc/sp140/lvgl/lv_conf.h index e913cdc1..76423aa7 100644 --- a/inc/sp140/lvgl/lv_conf.h +++ b/inc/sp140/lvgl/lv_conf.h @@ -1,88 +1,46 @@ /** * @file lv_conf.h - * Configuration file for LVGL + * Configuration file for LVGL v9 */ #ifndef LV_CONF_H // NOLINT(build/header_guard) #define LV_CONF_H // NOLINT(build/header_guard) -#include - /*==================== COLOR SETTINGS *====================*/ -/*Color depth: 1 (1 byte per pixel), 8 (RGB332), 16 (RGB565), 32 (ARGB8888)*/ +/*Color depth: 8 (A8), 16 (RGB565), 24 (RGB888), 32 (XRGB8888)*/ #define LV_COLOR_DEPTH 16 -/*Swap the 2 bytes of RGB565 color. Useful if the display has an 8-bit interface*/ -#define LV_COLOR_16_SWAP 0 - -/*Enable features to draw on transparent background*/ -#define LV_COLOR_SCREEN_TRANSP 0 - -/*Images pixels with this color will not be drawn if they are chroma keyed)*/ -#define LV_COLOR_CHROMA_KEY lv_color_hex(0x00ff00) /*pure green*/ - /*========================= - MEMORY SETTINGS + STDLIB SETTINGS *=========================*/ -/*1: use custom malloc/free, 0: use the built-in `lv_mem_alloc()` and `lv_mem_free()`*/ -#define LV_MEM_CUSTOM 0 -#if LV_MEM_CUSTOM == 0 - /*Size of the memory available for `lv_mem_alloc()` in bytes (>= 2kB)*/ - #define LV_MEM_SIZE (48U * 1024U) /*[bytes]*/ - - /*Set an address for the memory pool instead of allocating it as a normal array. Can be in external SRAM too.*/ - #define LV_MEM_ADR 0 /*0: unused*/ - /*Instead of an address give a memory allocator that will be called to get a memory pool for LVGL. E.g. my_malloc*/ - #if LV_MEM_ADR == 0 +/*Use LVGL's built-in memory manager*/ +#define LV_USE_STDLIB_MALLOC LV_STDLIB_BUILTIN - #endif +/*Size of the memory available for `lv_malloc()` in bytes (>= 2kB)*/ +#define LV_MEM_SIZE (48U * 1024U) -#else /*LV_MEM_CUSTOM*/ - #define LV_MEM_CUSTOM_INCLUDE /*Header for the dynamic memory function*/ - #define LV_MEM_CUSTOM_ALLOC malloc - #define LV_MEM_CUSTOM_FREE free - #define LV_MEM_CUSTOM_REALLOC realloc -#endif /*LV_MEM_CUSTOM*/ +#define LV_USE_STDLIB_STRING LV_STDLIB_BUILTIN +#define LV_USE_STDLIB_SPRINTF LV_STDLIB_BUILTIN -/*Number of the intermediate memory buffer used during rendering and other internal processing mechanisms. - *You will see an error log message if there wasn't enough buffers. */ -#define LV_MEM_BUF_MAX_NUM 16 +/*========================= + OS SETTINGS + *=========================*/ -/*Use the standard `memcpy` and `memset` instead of LVGL's own functions. (Might or might not be faster).*/ -#define LV_MEMCPY_MEMSET_STD 0 +/*Use no OS - keep existing lvglMutex for now*/ +#define LV_USE_OS LV_OS_NONE /*==================== HAL SETTINGS *====================*/ -/*Default display refresh period. LVG will redraw changed areas with this period time*/ -#define LV_DISP_DEF_REFR_PERIOD 30 /*[ms]*/ - -/*Input device read period in milliseconds*/ -#define LV_INDEV_DEF_READ_PERIOD 30 /*[ms]*/ - -/*Disable input devices to save resources*/ -#define LV_USE_INDEV_TOUCHSCREEN 0 /*Disable touchscreen support*/ -#define LV_USE_INDEV_TOUCHPAD 0 /*Disable touchpad support*/ -#define LV_USE_INDEV_MOUSE 0 /*Disable mouse support*/ -#define LV_USE_INDEV_KEYPAD 0 /*Disable keypad support*/ -#define LV_USE_INDEV_ENCODER 0 /*Disable encoder support*/ -#define LV_USE_INDEV_BUTTON 0 /*Disable button input device emulation*/ - -/*Use a custom tick source that tells the elapsed time in milliseconds. - *It removes the need to manually update the tick with `lv_tick_inc()`)*/ -#define LV_TICK_CUSTOM 0 -#if LV_TICK_CUSTOM - #define LV_TICK_CUSTOM_INCLUDE "Arduino.h" /*Header for the system time function*/ - #define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis()) /*Expression evaluating to current system time in ms*/ -#endif /*LV_TICK_CUSTOM*/ - -/*Default Dot Per Inch. Used to initialize default sizes such as widgets sized, style paddings. - *(Not so important, you can adjust it to modify default sizes and spaces)*/ +/*Default display refresh, period. LVGL will redraw changed areas with this period time*/ +#define LV_DEF_REFR_PERIOD 30 /*[ms]*/ + +/*Default Dot Per Inch. Used to initialize default sizes such as widgets sized, style paddings.*/ #define LV_DPI_DEF 130 /*[px/inch]*/ /*======================= @@ -93,67 +51,27 @@ * Drawing *-----------*/ -/*Enable complex draw engine. - *Required to draw shadow, gradient, rounded corners, circles, arc, skew lines, image transformations or any masks*/ -#define LV_DRAW_COMPLEX 1 -#if LV_DRAW_COMPLEX != 0 +/*Enable complex draw engine*/ +#define LV_DRAW_SW_COMPLEX 1 - /*Allow buffering some shadow calculation. - *LV_SHADOW_CACHE_SIZE is the max. shadow size to buffer, where shadow size is `shadow_width + radius` - *Caching has LV_SHADOW_CACHE_SIZE^2 RAM cost*/ - #define LV_SHADOW_CACHE_SIZE 0 +/*Allow buffering some shadow calculation. + *LV_DRAW_SW_SHADOW_CACHE_SIZE is the max. shadow size to buffer*/ +#define LV_DRAW_SW_SHADOW_CACHE_SIZE 0 - /* Set number of maximally cached circle data. - * The circumference of 1/4 circle are saved for anti-aliasing - * radius * 4 bytes are used per circle (the most often used radiuses are saved) - * 0: to disable caching */ - #define LV_CIRCLE_CACHE_SIZE 4 -#endif /*LV_DRAW_COMPLEX*/ +/*Set number of maximally cached circle data*/ +#define LV_DRAW_SW_CIRCLE_CACHE_SIZE 4 -/** - * "Simple layers" are used when a widget has `style_opa < 255` to buffer the widget into a layer - * and blend it as an image with the given opacity. - * Note that `bg_opa`, `text_opa` etc don't require buffering into layer) - * The widget can be buffered in smaller chunks to avoid using large buffers. - * - * - LV_LAYER_SIMPLE_BUF_SIZE: [bytes] the optimal target buffer size. LVGL will try to allocate it - * - LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE: [bytes] used if `LV_LAYER_SIMPLE_BUF_SIZE` couldn't be allocated. - * - * Both buffer sizes are in bytes. - * "Transformed layers" (where transform_angle/zoom properties are used) use larger buffers - * and can't be drawn in chunks. So these settings affects only widgets with opacity. - */ -#define LV_LAYER_SIMPLE_BUF_SIZE (24 * 1024) -#define LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE (3 * 1024) - -/*Default image cache size. Image caching keeps the images opened. - *If only the built-in image formats are used there is no real advantage of caching. (I.e. if no new image decoder is added) - *With complex image decoders (e.g. PNG or JPG) caching can save the continuous open/decode of images. - *However the opened images might consume additional RAM. - *0: to disable caching*/ -#define LV_IMG_CACHE_DEF_SIZE 0 - -/*Number of stops allowed per gradient. Increase this to allow more stops. - *This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/ +/*Buffer size for simple layers*/ +#define LV_DRAW_LAYER_SIMPLE_BUF_SIZE (24 * 1024) + +/*Default image cache size*/ +#define LV_IMAGE_CACHE_DEF_SIZE 0 + +/*Number of stops allowed per gradient*/ #define LV_GRADIENT_MAX_STOPS 2 -/*Default gradient buffer size. - *When LVGL calculates the gradient "maps" it can save them into a cache to avoid calculating them again. - *LV_GRAD_CACHE_DEF_SIZE sets the size of this cache in bytes. - *If the cache is too small the map will be allocated only while it's required for the drawing. - *0 mean no caching.*/ -#define LV_GRAD_CACHE_DEF_SIZE 0 - -/*Allow dithering the gradients (to achieve visual smooth color gradients on limited color depth display) - *LV_DITHER_GRADIENT implies allocating one or two more lines of the object's rendering surface - *The increase in memory consumption is (32 bits * object width) plus 24 bits * object width if using error diffusion */ -#define LV_DITHER_GRADIENT 0 -#if LV_DITHER_GRADIENT - /*Add support for error diffusion dithering. - *Error diffusion dithering gets a much better visual result, but implies more CPU consumption and memory when drawing. - *The increase in memory consumption is (24 bits * object's width)*/ - #define LV_DITHER_ERROR_DIFFUSION 0 -#endif +/*Number of parallel draw units (1 = single threaded)*/ +#define LV_DRAW_THREAD_COUNT 1 /*------------- * Fonts @@ -191,8 +109,6 @@ /** * Enable handling large font and/or fonts with a lot of characters. - * The limit depends on the font size, font face and bpp. - * Compiler error will be triggered if a font needs it. */ #define LV_FONT_FMT_TXT_LARGE 0 @@ -208,9 +124,6 @@ /** * Select a character encoding for strings. - * Your IDE or editor should have the same character encoding - * - LV_TXT_ENC_UTF8 - * - LV_TXT_ENC_ASCII */ #define LV_TXT_ENC LV_TXT_ENC_UTF8 @@ -221,19 +134,15 @@ * WIDGET USAGE *=================*/ -/* -Documentation of the widgets: https://docs.lvgl.io/latest/en/html/widgets/index.html -*/ - -#define LV_USE_ANIMIMG 0 +#define LV_USE_ANIMIMAGE 0 #define LV_USE_ARC 1 #define LV_USE_BAR 1 -#define LV_USE_BTN 1 +#define LV_USE_BUTTON 1 -#define LV_USE_BTNMATRIX 1 /* Required by other components */ +#define LV_USE_BUTTONMATRIX 1 /* Required by other components */ #define LV_USE_CANVAS 0 /* Don't need canvas */ @@ -243,7 +152,7 @@ Documentation of the widgets: https://docs.lvgl.io/latest/en/html/widgets/index. #define LV_USE_DROPDOWN 0 /* Don't need dropdown */ -#define LV_USE_IMG 1 /*Requires: lv_label*/ +#define LV_USE_IMAGE 1 /*Requires: lv_label*/ #define LV_USE_LABEL 1 #if LV_USE_LABEL @@ -272,6 +181,9 @@ Documentation of the widgets: https://docs.lvgl.io/latest/en/html/widgets/index. /* keyboard widget (set to 0 since we don't use it) */ #define LV_USE_KEYBOARD 0 +/*Extra widgets*/ +#define LV_USE_LED 1 + /*================== * THEMES *==================*/ @@ -305,10 +217,11 @@ Documentation of the widgets: https://docs.lvgl.io/latest/en/html/widgets/index. *====================*/ #define LV_USE_FS_STDIO 0 -#if LV_USE_FS_STDIO - #define LV_FS_STDIO_LETTER 'A' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ - #define LV_FS_STDIO_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/ - #define LV_FS_STDIO_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ -#endif + +/*==================== + * DEMOS & EXAMPLES + *====================*/ + +#define LV_BUILD_EXAMPLES 0 #endif /*LV_CONF_H*/ diff --git a/inc/sp140/lvgl/lvgl_core.h b/inc/sp140/lvgl/lvgl_core.h index 23cbe605..0b3be14a 100644 --- a/inc/sp140/lvgl/lvgl_core.h +++ b/inc/sp140/lvgl/lvgl_core.h @@ -12,19 +12,16 @@ #define SCREEN_WIDTH 160 #define SCREEN_HEIGHT 128 -// LVGL buffer size - optimize for our display -// Use half screen size for single flush to balance performance and memory usage -#define LVGL_BUFFER_SIZE (SCREEN_WIDTH * SCREEN_HEIGHT / 2) +// LVGL buffer size in bytes - half screen for partial rendering +// v9 uses byte-based buffers: width * height * bytes_per_pixel / 2 +#define LVGL_BUF_BYTES (SCREEN_WIDTH * SCREEN_HEIGHT * 2 / 2) // LVGL refresh time in ms - match the config file setting #define LVGL_REFRESH_TIME 40 // Core LVGL globals extern int8_t displayCS; // Display chip select pin -extern lv_disp_drv_t disp_drv; -extern lv_disp_draw_buf_t draw_buf; -extern lv_color_t buf[LVGL_BUFFER_SIZE]; -extern lv_color_t buf2[LVGL_BUFFER_SIZE]; // Second buffer for double buffering +extern lv_display_t* main_display; extern Adafruit_ST7735* tft_driver; extern uint32_t lvgl_last_update; // Shared SPI bus mutex (guards TFT + MCP2515 access) @@ -33,7 +30,7 @@ extern SemaphoreHandle_t spiBusMutex; // Core function declarations void setupLvglBuffer(); void setupLvglDisplay(const STR_DEVICE_DATA_140_V1& deviceData, int8_t dc_pin, int8_t rst_pin, SPIClass* spi); -void lvgl_flush_cb(lv_disp_drv_t* disp, const lv_area_t* area, lv_color_t* color_p); +void lvgl_flush_cb(lv_display_t* disp, const lv_area_t* area, uint8_t* px_map); void lv_tick_handler(); void updateLvgl(); void displayLvglSplash(const STR_DEVICE_DATA_140_V1& deviceData, int duration); diff --git a/platformio.ini b/platformio.ini index e526f348..19cecb91 100644 --- a/platformio.ini +++ b/platformio.ini @@ -59,7 +59,7 @@ lib_deps = https://github.com/rlogiacco/CircularBuffer@1.4.0 https://github.com/openppg/SINE-ESC-CAN#8caa93996b5d000fe10ca5265bd1c472dfdf885b https://github.com/openppg/ANT-BMS-CAN#fd54852bc6f1c9608e37af9ca7c13ea4135c095b - lvgl/lvgl@^8.4.0 + lvgl/lvgl@^9.5.0 h2zero/NimBLE-Arduino@^2.3.9 lib_ignore = Adafruit SleepyDog Library diff --git a/src/assets/img/cruise-control-340255-30.c b/src/assets/img/cruise-control-340255-30.c index a01aed14..5e45845b 100644 --- a/src/assets/img/cruise-control-340255-30.c +++ b/src/assets/img/cruise-control-340255-30.c @@ -54,14 +54,17 @@ const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_CRUISE_CO 0x00, 0x00, 0x00, 0x00, }; -const lv_img_dsc_t cruise_control_340255_30 = { - { - LV_IMG_CF_ALPHA_1BIT, - 0, - 0, - 30, - 30, +const lv_image_dsc_t cruise_control_340255_30 = { + .header = { + .magic = LV_IMAGE_HEADER_MAGIC, + .cf = LV_COLOR_FORMAT_A1, + .flags = 0, + .w = 30, + .h = 30, + .stride = 4, /* ceil(30/8) = 4 bytes per row */ + .reserved_2 = 0, }, - 120, - cruise_control_340255_30_map, + .data_size = 120, + .data = cruise_control_340255_30_map, + .reserved = NULL, }; diff --git a/src/assets/img/energy-539741-26.c b/src/assets/img/energy-539741-26.c index 5cb8531c..3c99eb7f 100644 --- a/src/assets/img/energy-539741-26.c +++ b/src/assets/img/energy-539741-26.c @@ -50,15 +50,17 @@ const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ENERGY_53 0x00, 0x00, 0x00, }; -const lv_img_dsc_t energy_539741_26 = { - // Header struct (lv_img_header_t) - { - LV_IMG_CF_ALPHA_1BIT, // Color format - 0, // Always zero - 0, // Reserved - 24, // Width - 26, // Height +const lv_image_dsc_t energy_539741_26 = { + .header = { + .magic = LV_IMAGE_HEADER_MAGIC, + .cf = LV_COLOR_FORMAT_A1, + .flags = 0, + .w = 24, + .h = 26, + .stride = 3, /* ceil(24/8) = 3 bytes per row */ + .reserved_2 = 0, }, - 78, // Data size - energy_539741_26_map, // Pointer to image data + .data_size = 78, + .data = energy_539741_26_map, + .reserved = NULL, }; diff --git a/src/assets/img/warning_2135850_30.c b/src/assets/img/warning_2135850_30.c index 8cce6f75..95ec877a 100644 --- a/src/assets/img/warning_2135850_30.c +++ b/src/assets/img/warning_2135850_30.c @@ -54,15 +54,17 @@ const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_WARNING_2 0x00, 0x00, 0x00, 0x00, }; -const lv_img_dsc_t warning_2135850_30 = { - // Header struct (lv_img_header_t) - { - LV_IMG_CF_ALPHA_1BIT, // Color format - 0, // Always zero - 0, // Reserved - 30, // Width - 30, // Height +const lv_image_dsc_t warning_2135850_30 = { + .header = { + .magic = LV_IMAGE_HEADER_MAGIC, + .cf = LV_COLOR_FORMAT_A1, + .flags = 0, + .w = 30, + .h = 30, + .stride = 4, /* ceil(30/8) = 4 bytes per row */ + .reserved_2 = 0, }, - 120, // Data size - warning_2135850_30_map, // Pointer to image data + .data_size = 120, + .data = warning_2135850_30_map, + .reserved = NULL, }; diff --git a/src/sp140/lvgl/lvgl_alerts.cpp b/src/sp140/lvgl/lvgl_alerts.cpp index 83996971..a0d7d8e9 100644 --- a/src/sp140/lvgl/lvgl_alerts.cpp +++ b/src/sp140/lvgl/lvgl_alerts.cpp @@ -32,12 +32,12 @@ void loadAlertSnapshot(const AlertSnapshot& snap) { if (critical_text_label == NULL) return; lv_label_set_text(critical_text_label, txt); lv_obj_set_style_text_color(critical_text_label, lv_color_make(255, 0, 0), 0); - lv_obj_clear_flag(critical_text_label, LV_OBJ_FLAG_HIDDEN); + lv_obj_remove_flag(critical_text_label, LV_OBJ_FLAG_HIDDEN); } else { if (alert_text_label == NULL) return; lv_label_set_text(alert_text_label, txt); lv_obj_set_style_text_color(alert_text_label, lv_color_make(255, 165, 0), 0); - lv_obj_clear_flag(alert_text_label, LV_OBJ_FLAG_HIDDEN); + lv_obj_remove_flag(alert_text_label, LV_OBJ_FLAG_HIDDEN); } } @@ -137,7 +137,7 @@ void updateAlertCounterDisplay(const AlertCounts& counts) { snprintf(buf, sizeof(buf), "%u", counts.warningCount); } lv_label_set_text(warning_counter_label, buf); - lv_obj_clear_flag(warning_counter_circle, LV_OBJ_FLAG_HIDDEN); + lv_obj_remove_flag(warning_counter_circle, LV_OBJ_FLAG_HIDDEN); } else { lv_obj_add_flag(warning_counter_circle, LV_OBJ_FLAG_HIDDEN); } @@ -151,7 +151,7 @@ void updateAlertCounterDisplay(const AlertCounts& counts) { snprintf(buf, sizeof(buf), "%u", counts.criticalCount); } lv_label_set_text(critical_counter_label, buf); - lv_obj_clear_flag(critical_counter_circle, LV_OBJ_FLAG_HIDDEN); + lv_obj_remove_flag(critical_counter_circle, LV_OBJ_FLAG_HIDDEN); // Simple positioning: align with alert text if no warnings, otherwise right of warning circle if (counts.warningCount == 0) { @@ -195,7 +195,7 @@ void lv_showAlertTextWithLevel(SensorID id, AlertLevel level, bool critical) { // Place critical text to the right of the red bubble lv_obj_align_to(critical_text_label, critical_counter_circle, LV_ALIGN_OUT_RIGHT_MID, 4, 0); } - lv_obj_clear_flag(critical_text_label, LV_OBJ_FLAG_HIDDEN); + lv_obj_remove_flag(critical_text_label, LV_OBJ_FLAG_HIDDEN); } else { // Use alert_text_label for warning alerts if (alert_text_label == NULL) return; @@ -213,9 +213,9 @@ void lv_showAlertTextWithLevel(SensorID id, AlertLevel level, bool critical) { // Hide altitude since warning takes that space setAltitudeVisibility(false); if (warning_counter_circle && critical_counter_circle && altitude_char_labels[0]) { - lv_coord_t altY = lv_obj_get_y(altitude_char_labels[0]); + int32_t altY = lv_obj_get_y(altitude_char_labels[0]); // Align warning bubble X with critical bubble X so texts line up - lv_coord_t critX = lv_obj_get_x(critical_counter_circle); + int32_t critX = lv_obj_get_x(critical_counter_circle); // Place orange bubble aligned with critical bubble lv_obj_set_pos(warning_counter_circle, critX, altY + 2); // Place warning text to the right of the orange bubble @@ -231,7 +231,7 @@ void lv_showAlertTextWithLevel(SensorID id, AlertLevel level, bool critical) { lv_obj_align_to(alert_text_label, warning_counter_circle, LV_ALIGN_OUT_RIGHT_MID, 4, 0); } } - lv_obj_clear_flag(alert_text_label, LV_OBJ_FLAG_HIDDEN); + lv_obj_remove_flag(alert_text_label, LV_OBJ_FLAG_HIDDEN); } } diff --git a/src/sp140/lvgl/lvgl_core.cpp b/src/sp140/lvgl/lvgl_core.cpp index 24f927fd..b4df9d35 100644 --- a/src/sp140/lvgl/lvgl_core.cpp +++ b/src/sp140/lvgl/lvgl_core.cpp @@ -4,10 +4,9 @@ #include "../../../inc/sp140/esp32s3-config.h" // Global variables for core LVGL functionality -lv_disp_drv_t disp_drv; -lv_disp_draw_buf_t draw_buf; -lv_color_t buf[LVGL_BUFFER_SIZE]; -lv_color_t buf2[LVGL_BUFFER_SIZE]; // Second buffer for double buffering +lv_display_t* main_display = nullptr; +static uint8_t buf[LVGL_BUF_BYTES]; +static uint8_t buf2[LVGL_BUF_BYTES]; Adafruit_ST7735* tft_driver = nullptr; uint32_t lvgl_last_update = 0; // Define the shared SPI bus mutex @@ -16,9 +15,6 @@ SemaphoreHandle_t spiBusMutex = NULL; void setupLvglBuffer() { // Initialize LVGL library lv_init(); - - // Setup double buffer for LVGL to reduce tearing - lv_disp_draw_buf_init(&draw_buf, buf, buf2, LVGL_BUFFER_SIZE); } void setupLvglDisplay( @@ -50,33 +46,28 @@ void setupLvglDisplay( // Initialize LVGL buffer setupLvglBuffer(); - // Initialize display driver (use global disp_drv) - lv_disp_drv_init(&disp_drv); - - // Set display driver properties - disp_drv.hor_res = SCREEN_WIDTH; - disp_drv.ver_res = SCREEN_HEIGHT; - disp_drv.flush_cb = lvgl_flush_cb; - disp_drv.draw_buf = &draw_buf; + // Create display and configure it + main_display = lv_display_create(SCREEN_WIDTH, SCREEN_HEIGHT); + lv_display_set_flush_cb(main_display, lvgl_flush_cb); + lv_display_set_buffers(main_display, buf, buf2, sizeof(buf), LV_DISPLAY_RENDER_MODE_PARTIAL); + lv_display_set_color_format(main_display, LV_COLOR_FORMAT_RGB565); - // Register the display driver - lv_disp_drv_register(&disp_drv); USBSerial.println("Display driver registered"); // Set LVGL default theme - using default font lv_theme_t* theme = lv_theme_default_init( - lv_disp_get_default(), // Display + main_display, // Display lv_palette_main(LV_PALETTE_BLUE), // Primary color lv_palette_main(LV_PALETTE_AMBER), // Secondary color deviceData.theme == 1, // Dark mode LV_FONT_DEFAULT); // Default font - lv_disp_set_theme(lv_disp_get_default(), theme); + lv_display_set_theme(main_display, theme); } // Optimize the flush callback to minimize SPI transfers // CS pin management is handled here where actual SPI communication occurs -void lvgl_flush_cb(lv_disp_drv_t* disp, const lv_area_t* area, lv_color_t* color_p) { +void lvgl_flush_cb(lv_display_t* disp, const lv_area_t* area, uint8_t* px_map) { uint32_t w = (area->x2 - area->x1 + 1); uint32_t h = (area->y2 - area->y1 + 1); @@ -87,7 +78,7 @@ void lvgl_flush_cb(lv_disp_drv_t* disp, const lv_area_t* area, lv_color_t* color // SPI bus timeout - BMS might be doing long operation, skip display flush USBSerial.println("[DISPLAY] SPI bus timeout - skipping display flush"); // Must still signal LVGL that flush is done to avoid deadlock - lv_disp_flush_ready(disp); + lv_display_flush_ready(disp); return; } } @@ -99,7 +90,7 @@ void lvgl_flush_cb(lv_disp_drv_t* disp, const lv_area_t* area, lv_color_t* color // Push colors - using DMA if available uint32_t len = w * h; - tft_driver->writePixels((uint16_t*)color_p, len); // NOLINT(readability/casting) + tft_driver->writePixels((uint16_t*)px_map, len); // NOLINT(readability/casting) tft_driver->endWrite(); // Deselect display CS when done @@ -109,7 +100,7 @@ void lvgl_flush_cb(lv_disp_drv_t* disp, const lv_area_t* area, lv_color_t* color } // Indicate to LVGL that flush is done - lv_disp_flush_ready(disp); + lv_display_flush_ready(disp); } // LVGL tick handler - to be called from timer or in main loop @@ -130,7 +121,7 @@ void updateLvgl() { // Update LVGL at the defined refresh rate if (current_ms - lvgl_last_update > LVGL_REFRESH_TIME) { lv_tick_handler(); - lv_task_handler(); + lv_timer_handler(); lvgl_last_update = current_ms; } } @@ -140,10 +131,10 @@ void displayLvglSplash(const STR_DEVICE_DATA_140_V1& deviceData, int duration) { // Create a new screen for the splash lv_obj_t* splash_screen = lv_obj_create(NULL); - lv_scr_load(splash_screen); + lv_screen_load(splash_screen); // Disable scrollbars - lv_obj_clear_flag(splash_screen, LV_OBJ_FLAG_SCROLLABLE); + lv_obj_remove_flag(splash_screen, LV_OBJ_FLAG_SCROLLABLE); // Set background color based on theme lv_obj_set_style_bg_color(splash_screen, diff --git a/src/sp140/lvgl/lvgl_main_screen.cpp b/src/sp140/lvgl/lvgl_main_screen.cpp index a9e52236..225c2d30 100644 --- a/src/sp140/lvgl/lvgl_main_screen.cpp +++ b/src/sp140/lvgl/lvgl_main_screen.cpp @@ -58,7 +58,7 @@ void setAltitudeVisibility(bool visible) { for (int i = 0; i < 7; i++) { if (altitude_char_labels[i]) { if (visible) { - lv_obj_clear_flag(altitude_char_labels[i], LV_OBJ_FLAG_HIDDEN); + lv_obj_remove_flag(altitude_char_labels[i], LV_OBJ_FLAG_HIDDEN); } else { lv_obj_add_flag(altitude_char_labels[i], LV_OBJ_FLAG_HIDDEN); } @@ -104,7 +104,7 @@ void init_temp_styles(bool darkMode) { // Function to show the loading overlay void showLoadingOverlay() { if (spinner_overlay != NULL) { - lv_obj_clear_flag(spinner_overlay, LV_OBJ_FLAG_HIDDEN); + lv_obj_remove_flag(spinner_overlay, LV_OBJ_FLAG_HIDDEN); } } @@ -118,14 +118,14 @@ void hideLoadingOverlay() { // Setup the main screen layout once void setupMainScreen(bool darkMode) { if (main_screen != NULL) { - lv_obj_del(main_screen); + lv_obj_delete(main_screen); } // Create main screen main_screen = lv_obj_create(NULL); // Disable scrollbars - lv_obj_clear_flag(main_screen, LV_OBJ_FLAG_SCROLLABLE); + lv_obj_remove_flag(main_screen, LV_OBJ_FLAG_SCROLLABLE); // Set theme based on dark/light mode lv_obj_set_style_bg_color(main_screen, @@ -233,7 +233,7 @@ void setupMainScreen(bool darkMode) { // Layout: [thousands][hundreds][tens][ones][.][tenths][m] (7 positions total) int char_width = 19; // Slightly tighter character width spacing int decimal_width = 8; // Slightly wider decimal point for proportional spacing - int char_height = 24; // Larger character height + int char_height = 30; // Match lv_font_montserrat_28 line_height (v9: 30px) int unit_width = 12; // Narrower width for unit character to reduce buffer // Calculate total width needed and position from the right @@ -425,7 +425,7 @@ void setupMainScreen(bool darkMode) { // Draw divider lines // Create horizontal line between top and middle sections lv_obj_t* h_line1 = lv_line_create(main_screen); - static lv_point_t h_line1_points[] = {{0, 37}, {SCREEN_WIDTH, 37}}; + static lv_point_precise_t h_line1_points[] = {{0, 37}, {SCREEN_WIDTH, 37}}; lv_line_set_points(h_line1, h_line1_points, 2); lv_obj_set_style_line_color(h_line1, LVGL_GRAY, @@ -434,7 +434,7 @@ void setupMainScreen(bool darkMode) { // Create horizontal line between middle and bottom sections (stop at new section boundary) lv_obj_t* h_line2 = lv_line_create(main_screen); - static lv_point_t h_line2_points[] = {{0, 70}, {148, 70}}; + static lv_point_precise_t h_line2_points[] = {{0, 70}, {148, 70}}; lv_line_set_points(h_line2, h_line2_points, 2); lv_obj_set_style_line_color(h_line2, LVGL_GRAY, @@ -443,7 +443,7 @@ void setupMainScreen(bool darkMode) { // Create vertical line in middle section lv_obj_t* v_line1 = lv_line_create(main_screen); - static lv_point_t v_line1_points[] = {{102, 37}, {102, 70}}; + static lv_point_precise_t v_line1_points[] = {{102, 37}, {102, 70}}; lv_line_set_points(v_line1, v_line1_points, 2); lv_obj_set_style_line_color(v_line1, LVGL_GRAY, @@ -452,7 +452,7 @@ void setupMainScreen(bool darkMode) { // Create vertical line in bottom section lv_obj_t* v_line2 = lv_line_create(main_screen); - static lv_point_t v_line2_points[] = {{117, 70}, {117, 128}}; + static lv_point_precise_t v_line2_points[] = {{117, 70}, {117, 128}}; lv_line_set_points(v_line2, v_line2_points, 2); lv_obj_set_style_line_color(v_line2, LVGL_GRAY, @@ -461,7 +461,7 @@ void setupMainScreen(bool darkMode) { // Create vertical line for new far-right section lv_obj_t* v_line3 = lv_line_create(main_screen); - static lv_point_t v_line3_points[] = {{148, 37}, {148, 128}}; + static lv_point_precise_t v_line3_points[] = {{148, 37}, {148, 128}}; lv_line_set_points(v_line3, v_line3_points, 2); lv_obj_set_style_line_color(v_line3, LVGL_GRAY, @@ -471,7 +471,7 @@ void setupMainScreen(bool darkMode) { // Create horizontal dividers for temperature section // Line between B and E at Y=89 lv_obj_t* h_line3 = lv_line_create(main_screen); - static lv_point_t h_line3_points[] = {{117, 89}, {148, 89}}; + static lv_point_precise_t h_line3_points[] = {{117, 89}, {148, 89}}; lv_line_set_points(h_line3, h_line3_points, 2); lv_obj_set_style_line_color(h_line3, LVGL_GRAY, @@ -480,7 +480,7 @@ void setupMainScreen(bool darkMode) { // Line between E and M at Y=109 lv_obj_t* h_line4 = lv_line_create(main_screen); - static lv_point_t h_line4_points[] = {{117, 109}, {148, 109}}; + static lv_point_precise_t h_line4_points[] = {{117, 109}, {148, 109}}; lv_line_set_points(h_line4, h_line4_points, 2); lv_obj_set_style_line_color(h_line4, LVGL_GRAY, @@ -498,8 +498,8 @@ void setupMainScreen(bool darkMode) { lv_obj_add_flag(arm_indicator, LV_OBJ_FLAG_HIDDEN); // Create cruise control icon (initially hidden) - cruise_icon_img = lv_img_create(main_screen); - lv_img_set_src(cruise_icon_img, &cruise_control_340255_30); // Use the new 30x30 image descriptor + cruise_icon_img = lv_image_create(main_screen); + lv_image_set_src(cruise_icon_img, &cruise_control_340255_30); // Use the new 30x30 image descriptor // Set icon color using recoloring based on theme lv_color_t icon_color; @@ -508,34 +508,34 @@ void setupMainScreen(bool darkMode) { } else { icon_color = lv_color_black(); // Black icon on light background } - lv_obj_set_style_img_recolor(cruise_icon_img, icon_color, LV_PART_MAIN); - lv_obj_set_style_img_recolor_opa(cruise_icon_img, LV_OPA_COVER, LV_PART_MAIN); // Make icon fully opaque + lv_obj_set_style_image_recolor(cruise_icon_img, icon_color, LV_PART_MAIN); + lv_obj_set_style_image_recolor_opa(cruise_icon_img, LV_OPA_COVER, LV_PART_MAIN); // Make icon fully opaque lv_obj_align(cruise_icon_img, LV_ALIGN_CENTER, 5, -11); lv_obj_move_foreground(cruise_icon_img); // Ensure icon is on the top layer lv_obj_add_flag(cruise_icon_img, LV_OBJ_FLAG_HIDDEN); // Hide initially // Create charging icon (initially hidden) - charging_icon_img = lv_img_create(main_screen); - lv_img_set_src(charging_icon_img, &energy_539741_26); + charging_icon_img = lv_image_create(main_screen); + lv_image_set_src(charging_icon_img, &energy_539741_26); lv_obj_align_to(charging_icon_img, battery_label, LV_ALIGN_OUT_RIGHT_MID, 3, 0); // Align to right of battery label // Set charging icon color based on theme - lv_obj_set_style_img_recolor(charging_icon_img, icon_color, LV_PART_MAIN); // Use same icon_color as cruise - lv_obj_set_style_img_recolor_opa(charging_icon_img, LV_OPA_COVER, LV_PART_MAIN); + lv_obj_set_style_image_recolor(charging_icon_img, icon_color, LV_PART_MAIN); // Use same icon_color as cruise + lv_obj_set_style_image_recolor_opa(charging_icon_img, LV_OPA_COVER, LV_PART_MAIN); lv_obj_move_foreground(charging_icon_img); // Ensure icon is on top lv_obj_add_flag(charging_icon_img, LV_OBJ_FLAG_HIDDEN); // Hide initially // Create arm fail warning icon (initially hidden) - arm_fail_warning_icon_img = lv_img_create(main_screen); - lv_img_set_src(arm_fail_warning_icon_img, &warning_2135850_30); + arm_fail_warning_icon_img = lv_image_create(main_screen); + lv_image_set_src(arm_fail_warning_icon_img, &warning_2135850_30); // Align in the same position as the cruise icon lv_obj_align(arm_fail_warning_icon_img, LV_ALIGN_CENTER, 12, -9); // Set icon color based on theme (using the same logic as cruise icon) - lv_obj_set_style_img_recolor(arm_fail_warning_icon_img, icon_color, LV_PART_MAIN); - lv_obj_set_style_img_recolor_opa(arm_fail_warning_icon_img, LV_OPA_COVER, LV_PART_MAIN); + lv_obj_set_style_image_recolor(arm_fail_warning_icon_img, icon_color, LV_PART_MAIN); + lv_obj_set_style_image_recolor_opa(arm_fail_warning_icon_img, LV_OPA_COVER, LV_PART_MAIN); lv_obj_move_foreground(arm_fail_warning_icon_img); // Ensure icon is on top lv_obj_add_flag(arm_fail_warning_icon_img, LV_OBJ_FLAG_HIDDEN); // Hide initially @@ -549,7 +549,8 @@ void setupMainScreen(bool darkMode) { lv_obj_set_style_border_width(spinner_overlay, 0, LV_PART_MAIN); // Create spinning animation at the top center - now place on top of overlay - spinner = lv_spinner_create(spinner_overlay, 1000, 60); // 1000ms period, 60 arcade width + spinner = lv_spinner_create(spinner_overlay); + lv_spinner_set_anim_params(spinner, 1000, 60); // 1000ms period, 60 arc width lv_obj_set_size(spinner, 80, 80); // Even larger spinner for visibility lv_obj_align(spinner, LV_ALIGN_CENTER, 0, 0); // Position at center of screen @@ -578,7 +579,7 @@ void setupMainScreen(bool darkMode) { // Create horizontal divider line running from section start to screen edge climb_rate_divider_lines[i] = lv_line_create(main_screen); - static lv_point_t line_points[13][2]; // Static array for all line points + static lv_point_precise_t line_points[13][2]; // Static array for all line points line_points[i][0].x = 148; // Start at section boundary line_points[i][0].y = y_pos; line_points[i][1].x = 160; // End at screen edge @@ -637,5 +638,5 @@ void setupMainScreen(bool darkMode) { init_temp_styles(darkMode); // Load the screen - lv_scr_load(main_screen); + lv_screen_load(main_screen); } diff --git a/src/sp140/lvgl/lvgl_updates.cpp b/src/sp140/lvgl/lvgl_updates.cpp index 765ea99d..d0c806b2 100644 --- a/src/sp140/lvgl/lvgl_updates.cpp +++ b/src/sp140/lvgl/lvgl_updates.cpp @@ -42,7 +42,7 @@ static void cruise_flash_timer_cb(lv_timer_t* timer) { // Toggle visibility if (lv_obj_has_flag(cruise_icon_img, LV_OBJ_FLAG_HIDDEN)) { - lv_obj_clear_flag(cruise_icon_img, LV_OBJ_FLAG_HIDDEN); + lv_obj_remove_flag(cruise_icon_img, LV_OBJ_FLAG_HIDDEN); } else { lv_obj_add_flag(cruise_icon_img, LV_OBJ_FLAG_HIDDEN); } @@ -79,7 +79,7 @@ void startCruiseIconFlash() { isFlashingCruiseIcon = true; // Start with the icon visible - lv_obj_clear_flag(cruise_icon_img, LV_OBJ_FLAG_HIDDEN); + lv_obj_remove_flag(cruise_icon_img, LV_OBJ_FLAG_HIDDEN); // Create the timer (250ms interval for on/off cycle) cruise_flash_timer = lv_timer_create(cruise_flash_timer_cb, 250, NULL); @@ -87,11 +87,11 @@ void startCruiseIconFlash() { // Failed to create timer, reset state isFlashingCruiseIcon = false; lv_obj_add_flag(cruise_icon_img, LV_OBJ_FLAG_HIDDEN); // Hide it again - lv_obj_set_style_img_recolor(cruise_icon_img, original_cruise_icon_color, LV_PART_MAIN); // Restore color on failure + lv_obj_set_style_image_recolor(cruise_icon_img, original_cruise_icon_color, LV_PART_MAIN); // Restore color on failure USBSerial.println("Error: Failed to create cruise flash timer!"); } else { // Set icon to red for flashing - lv_obj_set_style_img_recolor(cruise_icon_img, LVGL_RED, LV_PART_MAIN); + lv_obj_set_style_image_recolor(cruise_icon_img, LVGL_RED, LV_PART_MAIN); } xSemaphoreGive(lvglMutex); @@ -117,7 +117,7 @@ static void arm_fail_flash_timer_cb(lv_timer_t* timer) { // Toggle visibility if (lv_obj_has_flag(arm_fail_warning_icon_img, LV_OBJ_FLAG_HIDDEN)) { - lv_obj_clear_flag(arm_fail_warning_icon_img, LV_OBJ_FLAG_HIDDEN); + lv_obj_remove_flag(arm_fail_warning_icon_img, LV_OBJ_FLAG_HIDDEN); } else { lv_obj_add_flag(arm_fail_warning_icon_img, LV_OBJ_FLAG_HIDDEN); } @@ -133,7 +133,7 @@ static void arm_fail_flash_timer_cb(lv_timer_t* timer) { // Ensure icon is hidden after flashing lv_obj_add_flag(arm_fail_warning_icon_img, LV_OBJ_FLAG_HIDDEN); // Restore original color after flashing is done - lv_obj_set_style_img_recolor(arm_fail_warning_icon_img, original_arm_fail_icon_color, LV_PART_MAIN); + lv_obj_set_style_image_recolor(arm_fail_warning_icon_img, original_arm_fail_icon_color, LV_PART_MAIN); } } @@ -156,10 +156,10 @@ void startArmFailIconFlash() { isFlashingArmFailIcon = true; // Start with the icon visible - lv_obj_clear_flag(arm_fail_warning_icon_img, LV_OBJ_FLAG_HIDDEN); + lv_obj_remove_flag(arm_fail_warning_icon_img, LV_OBJ_FLAG_HIDDEN); // Set icon to red for flashing - lv_obj_set_style_img_recolor(arm_fail_warning_icon_img, LVGL_RED, LV_PART_MAIN); + lv_obj_set_style_image_recolor(arm_fail_warning_icon_img, LVGL_RED, LV_PART_MAIN); // Create the timer (250ms interval for on/off cycle) arm_fail_flash_timer = lv_timer_create(arm_fail_flash_timer_cb, 250, NULL); @@ -167,7 +167,7 @@ void startArmFailIconFlash() { // Failed to create timer, reset state isFlashingArmFailIcon = false; lv_obj_add_flag(arm_fail_warning_icon_img, LV_OBJ_FLAG_HIDDEN); // Hide it again - lv_obj_set_style_img_recolor(arm_fail_warning_icon_img, original_arm_fail_icon_color, LV_PART_MAIN); // Restore color + lv_obj_set_style_image_recolor(arm_fail_warning_icon_img, original_arm_fail_icon_color, LV_PART_MAIN); // Restore color USBSerial.println("Error: Failed to create arm fail flash timer!"); } @@ -187,7 +187,7 @@ static void critical_border_flash_timer_cb(lv_timer_t* timer) { lv_obj_set_style_border_opa(critical_border, LV_OPA_0, LV_PART_MAIN); lv_timer_set_period(timer, 700); // Off duration // Invalidate entire screen when hiding to ensure clean removal of border pixels - lv_obj_invalidate(lv_scr_act()); + lv_obj_invalidate(lv_screen_active()); } else { lv_obj_set_style_border_opa(critical_border, LV_OPA_100, LV_PART_MAIN); lv_timer_set_period(timer, 300); // On duration @@ -200,7 +200,7 @@ static void critical_border_flash_timer_cb(lv_timer_t* timer) { lv_obj_invalidate(critical_border); } // Force immediate refresh to minimize tearing - lv_refr_now(lv_disp_get_default()); + lv_refr_now(lv_display_get_default()); } } @@ -224,7 +224,7 @@ void stopCriticalBorderFlash() { if (critical_border != NULL) { lv_obj_set_style_border_opa(critical_border, LV_OPA_0, LV_PART_MAIN); // Invalidate entire screen to ensure clean removal - lv_obj_invalidate(lv_scr_act()); + lv_obj_invalidate(lv_screen_active()); } isFlashingCriticalBorder = false; xSemaphoreGive(lvglMutex); @@ -243,7 +243,7 @@ void startCriticalBorderFlashDirect() { lv_obj_invalidate(critical_border); // Ensure clean initial draw critical_border_flash_timer = lv_timer_create(critical_border_flash_timer_cb, 300, NULL); // Force immediate refresh for clean start - lv_refr_now(lv_disp_get_default()); + lv_refr_now(lv_display_get_default()); } } @@ -254,9 +254,9 @@ void stopCriticalBorderFlashDirect() { } if (critical_border != NULL) { lv_obj_set_style_border_opa(critical_border, LV_OPA_0, LV_PART_MAIN); - lv_obj_invalidate(lv_scr_act()); // Ensure clean removal of border + lv_obj_invalidate(lv_screen_active()); // Ensure clean removal of border // Force immediate refresh for clean stop - lv_refr_now(lv_disp_get_default()); + lv_refr_now(lv_display_get_default()); } isFlashingCriticalBorder = false; } @@ -596,7 +596,7 @@ void updateLvglMainScreen( lv_label_set_text(altitude_char_labels[5], digit_buffers[5]); // Adjust width of position 4 back to narrow for meters (decimal point) - lv_obj_set_size(altitude_char_labels[4], 8, 24); // decimal_width=8, char_height=24 + lv_obj_set_size(altitude_char_labels[4], 8, 30); // decimal_width=8, char_height=30 // Unit lv_label_set_text(altitude_char_labels[6], "m"); @@ -616,7 +616,7 @@ void updateLvglMainScreen( static char digit_buffers_ft[7][12]; // Static buffers for feet // Adjust width of position 4 for feet (should be normal width, not narrow) - lv_obj_set_size(altitude_char_labels[4], 17, 24); // char_width=19, char_height=24 + lv_obj_set_size(altitude_char_labels[4], 17, 30); // char_width=19, char_height=30 // Clear all positions first for (int i = 0; i < 7; i++) { @@ -678,10 +678,10 @@ void updateLvglMainScreen( lv_label_set_text_fmt(batt_temp_label, "%d", static_cast(batteryTemp)); if (batteryTemp >= bmsCellTempThresholds.critHigh) { lv_obj_add_style(batt_temp_bg, &style_critical, 0); - lv_obj_clear_flag(batt_temp_bg, LV_OBJ_FLAG_HIDDEN); + lv_obj_remove_flag(batt_temp_bg, LV_OBJ_FLAG_HIDDEN); } else if (batteryTemp >= bmsCellTempThresholds.warnHigh) { lv_obj_add_style(batt_temp_bg, &style_warning, 0); - lv_obj_clear_flag(batt_temp_bg, LV_OBJ_FLAG_HIDDEN); + lv_obj_remove_flag(batt_temp_bg, LV_OBJ_FLAG_HIDDEN); } else { lv_obj_add_flag(batt_temp_bg, LV_OBJ_FLAG_HIDDEN); } @@ -702,10 +702,10 @@ void updateLvglMainScreen( if (escTemp >= escMosTempThresholds.critHigh) { lv_obj_add_style(esc_temp_bg, &style_critical, 0); - lv_obj_clear_flag(esc_temp_bg, LV_OBJ_FLAG_HIDDEN); + lv_obj_remove_flag(esc_temp_bg, LV_OBJ_FLAG_HIDDEN); } else if (escTemp >= escMosTempThresholds.warnHigh) { lv_obj_add_style(esc_temp_bg, &style_warning, 0); - lv_obj_clear_flag(esc_temp_bg, LV_OBJ_FLAG_HIDDEN); + lv_obj_remove_flag(esc_temp_bg, LV_OBJ_FLAG_HIDDEN); } else { lv_obj_add_flag(esc_temp_bg, LV_OBJ_FLAG_HIDDEN); } @@ -726,10 +726,10 @@ void updateLvglMainScreen( if (motorTemp >= motorTempThresholds.critHigh) { lv_obj_add_style(motor_temp_bg, &style_critical, 0); - lv_obj_clear_flag(motor_temp_bg, LV_OBJ_FLAG_HIDDEN); + lv_obj_remove_flag(motor_temp_bg, LV_OBJ_FLAG_HIDDEN); } else if (motorTemp >= motorTempThresholds.warnHigh) { lv_obj_add_style(motor_temp_bg, &style_warning, 0); - lv_obj_clear_flag(motor_temp_bg, LV_OBJ_FLAG_HIDDEN); + lv_obj_remove_flag(motor_temp_bg, LV_OBJ_FLAG_HIDDEN); } else { lv_obj_add_flag(motor_temp_bg, LV_OBJ_FLAG_HIDDEN); } @@ -743,7 +743,7 @@ void updateLvglMainScreen( if (armed) { // Set background to CYAN when armed, regardless of cruise state lv_obj_set_style_bg_color(arm_indicator, LVGL_CYAN, LV_PART_MAIN); - lv_obj_clear_flag(arm_indicator, LV_OBJ_FLAG_HIDDEN); + lv_obj_remove_flag(arm_indicator, LV_OBJ_FLAG_HIDDEN); } else { lv_obj_add_flag(arm_indicator, LV_OBJ_FLAG_HIDDEN); } @@ -752,19 +752,19 @@ void updateLvglMainScreen( // Only update based on `cruising` state if not currently flashing if (!isFlashingCruiseIcon) { if (cruising) { - lv_obj_clear_flag(cruise_icon_img, LV_OBJ_FLAG_HIDDEN); + lv_obj_remove_flag(cruise_icon_img, LV_OBJ_FLAG_HIDDEN); } else { lv_obj_add_flag(cruise_icon_img, LV_OBJ_FLAG_HIDDEN); } // Restore original color after flashing is done - lv_obj_set_style_img_recolor(cruise_icon_img, original_cruise_icon_color, LV_PART_MAIN); + lv_obj_set_style_image_recolor(cruise_icon_img, original_cruise_icon_color, LV_PART_MAIN); } // Update Charging Icon Visibility - only when BMS is connected and reports charging if (charging_icon_img != NULL) { // Check object exists bool showChargingIcon = (bmsTelemetry.bmsState == TelemetryState::CONNECTED) && bmsTelemetry.is_charging; if (showChargingIcon) { - lv_obj_clear_flag(charging_icon_img, LV_OBJ_FLAG_HIDDEN); + lv_obj_remove_flag(charging_icon_img, LV_OBJ_FLAG_HIDDEN); } else { lv_obj_add_flag(charging_icon_img, LV_OBJ_FLAG_HIDDEN); } @@ -775,7 +775,7 @@ void updateLvglMainScreen( if (!isFlashingArmFailIcon && arm_fail_warning_icon_img != NULL) { lv_obj_add_flag(arm_fail_warning_icon_img, LV_OBJ_FLAG_HIDDEN); // Ensure color is reset if flashing ended abruptly elsewhere (though cb should handle it) - lv_obj_set_style_img_recolor(arm_fail_warning_icon_img, original_arm_fail_icon_color, LV_PART_MAIN); + lv_obj_set_style_image_recolor(arm_fail_warning_icon_img, original_arm_fail_icon_color, LV_PART_MAIN); } // Update climb rate indicator diff --git a/src/sp140/main.cpp b/src/sp140/main.cpp index d9fdd005..c84a863c 100644 --- a/src/sp140/main.cpp +++ b/src/sp140/main.cpp @@ -783,7 +783,7 @@ void setup() { // Load main screen if (main_screen != NULL) { - lv_scr_load(main_screen); + lv_screen_load(main_screen); USBSerial.println("Main screen loaded"); } else { USBSerial.println("Error: Main screen object is NULL after setup attempt");