Skip to content

Commit

Permalink
switched to lvgl 9.1
Browse files Browse the repository at this point in the history
  • Loading branch information
KlausMu committed Apr 8, 2024
1 parent 1a15307 commit a1ce03d
Show file tree
Hide file tree
Showing 18 changed files with 267 additions and 325 deletions.
65 changes: 35 additions & 30 deletions Platformio/hardware/ESP32/lvgl_hal_esp32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,30 @@
#include "sleep_hal_esp32.h"

// -----------------------
// https://docs.lvgl.io/8.3/porting/display.html?highlight=lv_disp_draw_buf_init#buffering-modes
// https://docs.lvgl.io/master/porting/display.html#two-buffers
// With two buffers, the rendering and refreshing of the display become parallel operations
// Second buffer needs 15.360 bytes more memory in heap.
#define useTwoBuffersForlvgl

// Display flushing
void my_disp_flush( lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p ){
uint32_t w = ( area->x2 - area->x1 + 1 );
uint32_t h = ( area->y2 - area->y1 + 1 );
static void my_disp_flush( 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);

tft.startWrite();
tft.setAddrWindow(area->x1, area->y1, w, h);
#ifdef useTwoBuffersForlvgl
tft.pushPixelsDMA((uint16_t*)&color_p->full, w * h);
tft.pushPixelsDMA((uint16_t*)px_map, w * h);
#else
tft.pushColors((uint16_t*)&color_p->full, w * h, true);
tft.pushColors((uint16_t *)px_map, w * h, true);
#endif
tft.endWrite();

lv_disp_flush_ready( disp );
lv_display_flush_ready(disp);
}

// Read the touchpad
void my_touchpad_read(lv_indev_drv_t * indev_driver, lv_indev_data_t * data){
static void my_touchpad_read(lv_indev_t *indev_driver, lv_indev_data_t *data) {
int16_t touchX;
int16_t touchY;
get_touchpoint(&touchX, &touchY);
Expand All @@ -38,10 +38,10 @@ void my_touchpad_read(lv_indev_drv_t * indev_driver, lv_indev_data_t * data){
}

if( !touched ){
data->state = LV_INDEV_STATE_REL;
data->state = LV_INDEV_STATE_RELEASED;
}
else{
data->state = LV_INDEV_STATE_PR;
data->state = LV_INDEV_STATE_PRESSED;

// Set the coordinates
data->point.x = SCR_WIDTH - touchX;
Expand All @@ -56,35 +56,40 @@ void my_touchpad_read(lv_indev_drv_t * indev_driver, lv_indev_data_t * data){
}
}

static lv_disp_draw_buf_t draw_buf;
/*LVGL draw into this buffer, 1/10 screen size usually works well. The size is in bytes*/
#define DRAW_BUF_SIZE (SCR_WIDTH * SCR_HEIGHT / 10 * (LV_COLOR_DEPTH / 8))

static uint32_t my_tick_get_cb(void) {
return millis();
}

void init_lvgl_HAL() {
// first init TFT
init_tft();

// new in lvgl 9
lv_tick_set_cb(my_tick_get_cb);

// https://github.com/lvgl/lvgl/blob/release/v9.0/docs/CHANGELOG.rst#display-api
// https://docs.lvgl.io/master/get-started/quick-overview.html#add-lvgl-into-your-project
lv_display_t *disp = lv_display_create(SCR_WIDTH, SCR_HEIGHT);
lv_display_set_flush_cb(disp, my_disp_flush);

// https://github.com/lvgl/lvgl/blob/release/v9.0/docs/CHANGELOG.rst#migration-guide
// lv_display_set_buffers(display, buf1, buf2, buf_size_byte, mode) is more or less the equivalent of lv_disp_draw_buf_init(&draw_buf_dsc, buf1, buf2, buf_size_px) from v8, however in v9 the buffer size is set in bytes.
#ifdef useTwoBuffersForlvgl
lv_color_t * bufA = (lv_color_t *) malloc(sizeof(lv_color_t) * SCR_WIDTH * SCR_HEIGHT / 10);
lv_color_t * bufB = (lv_color_t *) malloc(sizeof(lv_color_t) * SCR_WIDTH * SCR_HEIGHT / 10);
lv_disp_draw_buf_init(&draw_buf, bufA, bufB, SCR_WIDTH * SCR_HEIGHT / 10);
uint8_t *bufA = (uint8_t *) malloc(DRAW_BUF_SIZE);
uint8_t *bufB = (uint8_t *) malloc(DRAW_BUF_SIZE);
lv_display_set_buffers(disp, bufA, bufB, DRAW_BUF_SIZE, LV_DISPLAY_RENDER_MODE_PARTIAL);
#else
lv_color_t * bufA = (lv_color_t *) malloc(sizeof(lv_color_t) * SCR_WIDTH * SCR_HEIGHT / 10);
lv_disp_draw_buf_init(&draw_buf, bufA, NULL, SCR_WIDTH * SCR_HEIGHT / 10);
uint8_t *bufA = (uint8_t *) malloc(DRAW_BUF_SIZE);
lv_display_set_buffers(disp, bufA, NULL, DRAW_BUF_SIZE, LV_DISPLAY_RENDER_MODE_PARTIAL);
#endif

// Initialize the display driver --------------------------------------------------------------------------
static lv_disp_drv_t disp_drv;
lv_disp_drv_init( &disp_drv );
disp_drv.hor_res = SCR_WIDTH;
disp_drv.ver_res = SCR_HEIGHT;
disp_drv.flush_cb = my_disp_flush;
disp_drv.draw_buf = &draw_buf;
lv_disp_drv_register( &disp_drv );

// Initialize the touchscreen driver
static lv_indev_drv_t indev_drv;
lv_indev_drv_init( &indev_drv );
indev_drv.type = LV_INDEV_TYPE_POINTER;
indev_drv.read_cb = my_touchpad_read;
lv_indev_drv_register( &indev_drv );
// https://github.com/lvgl/lvgl/blob/release/v9.0/docs/CHANGELOG.rst#indev-api
static lv_indev_t * indev = lv_indev_create();
lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER);
lv_indev_set_read_cb(indev, my_touchpad_read);

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ long HeapUsed()
#elif defined(__linux__)
long HeapUsed() {
// don't know how to get used heap size in linux
return 800000;
return 80000;
}
#endif

Expand Down
114 changes: 22 additions & 92 deletions Platformio/hardware/windows_linux/lvgl_hal_windows_linux.cpp
Original file line number Diff line number Diff line change
@@ -1,44 +1,4 @@
#include <stdlib.h>
#include <sys/time.h>
#include <lvgl.h>
#include <SDL2/SDL_thread.h>
#include "sdl/sdl.h"
#include "SDL2/SDL_events.h"

long long current_timestamp_hal_windowsLinux() {
struct timeval te;
gettimeofday(&te, NULL); // get current time
long long milliseconds = te.tv_sec*1000LL + te.tv_usec/1000; // calculate milliseconds
// printf("milliseconds: %lld\r\n", milliseconds);
return milliseconds;
}
/**
* A task to measure the elapsed time for LittlevGL
* @param data unused
* @return never return
*/
static int tick_thread(void * data)
{
(void)data;

long long lastTimestamp = current_timestamp_hal_windowsLinux();
long long newTimestamp = 0;
while(1) {
// we don't use this blackbox
// SDL_Delay(5); /*Sleep for 5 millisecond*/
// lv_tick_inc(5); /*Tell lvgl that 5 milliseconds were elapsed*/

newTimestamp = current_timestamp_hal_windowsLinux();
if ((newTimestamp - lastTimestamp) > 5) {
lv_tick_inc(newTimestamp - lastTimestamp);
lastTimestamp = newTimestamp;
}
}

return 0;
}

static lv_disp_draw_buf_t draw_buf;

void init_lvgl_HAL() {
// Workaround for sdl2 `-m32` crash
Expand All @@ -47,63 +7,33 @@ void init_lvgl_HAL() {
setenv("DBUS_FATAL_WARNINGS", "0", 1);
#endif

#ifdef useTwoBuffersForlvgl
lv_color_t * bufA = (lv_color_t *) malloc(sizeof(lv_color_t) * SDL_HOR_RES * SDL_VER_RES / 10);
lv_color_t * bufB = (lv_color_t *) malloc(sizeof(lv_color_t) * SDL_HOR_RES * SDL_VER_RES / 10);
lv_disp_draw_buf_init(&draw_buf, bufA, bufB, SDL_HOR_RES * SDL_VER_RES / 10);
#else
lv_color_t * bufA = (lv_color_t *) malloc(sizeof(lv_color_t) * SDL_HOR_RES * SDL_VER_RES / 10);
lv_disp_draw_buf_init(&draw_buf, bufA, NULL, SDL_HOR_RES * SDL_VER_RES / 10);
#endif
// https://github.com/lvgl/lv_platformio/issues/59
// https://github.com/lvgl/lv_port_pc_eclipse/blob/master/main.c#L111
// https://github.com/lvgl/lv_port_pc_eclipse/blob/master/lv_conf.h#L832-L839
lv_group_set_default(lv_group_create());

// Initialize the display driver --------------------------------------------------------------------------
static lv_disp_drv_t disp_drv;
lv_disp_drv_init( &disp_drv );
disp_drv.hor_res = SDL_HOR_RES;
disp_drv.ver_res = SDL_VER_RES;
disp_drv.flush_cb = sdl_display_flush; /*Used when `LV_VDB_SIZE != 0` in lv_conf.h (buffered drawing)*/
disp_drv.draw_buf = &draw_buf;
//disp_drv.disp_fill = monitor_fill; /*Used when `LV_VDB_SIZE == 0` in lv_conf.h (unbuffered drawing)*/
//disp_drv.disp_map = monitor_map; /*Used when `LV_VDB_SIZE == 0` in lv_conf.h (unbuffered drawing)*/
lv_disp_drv_register( &disp_drv );
lv_display_t * disp = lv_sdl_window_create(SDL_HOR_RES, SDL_VER_RES);
lv_display_set_default(disp);

/* Add the mouse as input device
* Use the 'mouse' driver which reads the PC's mouse*/
static lv_indev_drv_t indev_drv_mouse;
lv_indev_drv_init( &indev_drv_mouse );
indev_drv_mouse.type = LV_INDEV_TYPE_POINTER;
indev_drv_mouse.read_cb = sdl_mouse_read; /*This function will be called periodically (by the library) to get the mouse position and state*/
lv_indev_drv_register( &indev_drv_mouse );
lv_indev_t * mouse = lv_sdl_mouse_create();
lv_indev_set_group(mouse, lv_group_get_default());
lv_indev_set_display(mouse, disp);

// /* Add the keyboard as input device
// * did not work */
// static lv_indev_drv_t indev_drv_keyboard;
// lv_indev_drv_init( &indev_drv_keyboard );
// indev_drv_keyboard.type = LV_INDEV_TYPE_KEYPAD;
// indev_drv_keyboard.read_cb = sdl_keyboard_read; /*This function will be called periodically (by the library) to get the keyboard events*/
// lv_indev_t *keyboard_device = lv_indev_drv_register( &indev_drv_keyboard );
// lv_group_t *group = lv_group_create();
// lv_indev_set_group(keyboard_device, group);
// lv_group_add_obj(group, lv_scr_act());
// lv_group_add_obj(group, tabview);
// lv_group_add_obj(group, lv_tabview_get_content(tabview));
// lv_group_add_obj(group, tabs);
//
// need to be in a loop
// printf("last key: %d\n",lv_indev_get_key(keyboard_device));
// LV_IMAGE_DECLARE(mouse_cursor_icon); /*Declare the image file.*/
// lv_obj_t * cursor_obj;
// cursor_obj = lv_image_create(lv_screen_active()); /*Create an image object for the cursor */
// lv_image_set_src(cursor_obj, &mouse_cursor_icon); /*Set the image source*/
// lv_indev_set_cursor(mouse, cursor_obj); /*Connect the image object to the driver*/

sdl_init();
lv_indev_t * mousewheel = lv_sdl_mousewheel_create();
lv_indev_set_display(mousewheel, disp);
lv_indev_set_group(mousewheel, lv_group_get_default());

// Get the SDL window via an event
SDL_Event aWindowIdFinder;
SDL_PollEvent(&aWindowIdFinder);
SDL_Window *mSimWindow = SDL_GetWindowFromID(aWindowIdFinder.window.windowID);

SDL_SetWindowTitle(mSimWindow, "OMOTE simulator");
lv_indev_t * keyboard = lv_sdl_keyboard_create();
lv_indev_set_display(keyboard, disp);
lv_indev_set_group(keyboard, lv_group_get_default());

/* Tick init.
* You have to call 'lv_tick_inc()' in periodically to inform lvgl about how much time were elapsed
* Create an SDL thread to do this*/
SDL_CreateThread(tick_thread, "tick", NULL);
lv_sdl_window_set_title(disp, "OMOTE simulator");
lv_sdl_window_set_zoom(disp, SDL_ZOOM);

}
50 changes: 20 additions & 30 deletions Platformio/platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ default_envs = esp32
custom_screen_width = 240
custom_screen_heigth = 320
lib_deps =
lvgl/lvgl@^8.3.11
lvgl/lvgl@^9.1.0
build_flags =
;-- OMOTE -----------------------------------------------------------------
-D ENABLE_WIFI_AND_MQTT=1
Expand All @@ -28,14 +28,12 @@ build_flags =
-D SCR_HEIGHT=${env.custom_screen_heigth}
;-- lvgl ------------------------------------------------------------------
; lvgl variant 1:
; Don't use lv_conf.h. Tweak params via platfom.ini. See lv_conf_internal.h line 31. Don't change this line.
; Don't use lv_conf.h. Tweak params via platfom.ini. See lv_conf_internal.h line 49. Don't change this line.
-D LV_CONF_SKIP=1
; Set this in specific environments below. Will be different in Arduino and Windows/Linux
;-D LV_TICK_CUSTOM=1
; dynamic memory. Takes as much as it gets from heap (DRAM). Needs approx. 25%-30% more memory than static memory.
;-D LV_MEM_CUSTOM=1
;-D LV_USE_STDLIB_MALLOC=1
; Set this in specific environments below. 32 bit and 64 bit need differenz sizes.
;-D LV_MEM_CUSTOM=0
;-D LV_USE_STDLIB_MALLOC=0
;-D LV_MEM_SIZE="(32U * 1024U)"
; fonts and theme
-D LV_FONT_MONTSERRAT_10=1
Expand All @@ -48,14 +46,13 @@ build_flags =
; Enable the log module
-D LV_USE_LOG=1
-D LV_LOG_PRINTF=1
; trace really gives a lot of messages ...
;-D LV_LOG_LEVEL=LV_LOG_LEVEL_TRACE
;-D LV_LOG_LEVEL=LV_LOG_LEVEL_INFO
;-D LV_LOG_LEVEL=LV_LOG_LEVEL_WARN
-D LV_LOG_LEVEL=LV_LOG_LEVEL_ERROR
;-D LV_LOG_LEVEL=LV_LOG_LEVEL_USER
;-D LV_LOG_LEVEL=LV_LOG_LEVEL_NONE
; trace really gives a lot of messages ...
;-D LV_LOG_LEVEL=LV_LOG_LEVEL_TRACE
; ---
; Enable asserts if an operation is failed or an invalid data is found.
; If LV_USE_LOG is enabled an error message will be printed on failure*/
Expand All @@ -68,8 +65,10 @@ build_flags =
; ---------
; lvgl variant 2:
; or define where lv_conf.h is, relative to the `lvgl` folder
;-D LV_CONF_PATH=../../../../src/gui_general_and_keys/lv_conf.h
;-D LV_CONF_PATH=../../../../src/gui/lv_conf.h
; --- interesting lvgl debug infos (OSD)
; LV_USE_SYSMON needs to be set for LV_USE_PERF_MONITOR and LV_USE_MEM_MONITOR to work
;-D LV_USE_SYSMON=1
;-D LV_USE_PERF_MONITOR=1
;-D LV_USE_MEM_MONITOR=1
;-D LV_USE_REFR_DEBUG=1
Expand Down Expand Up @@ -109,11 +108,9 @@ build_flags =
;-D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
;-D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE
;-- lvgl arduino ----------------------------------------------------------
; use millis() from "Arduino.h" to tell the elapsed time in milliseconds
-D LV_TICK_CUSTOM=1
; static memory, will be allocated in static DRAM
-D LV_MEM_CUSTOM=0
-D LV_MEM_SIZE="(32U * 1024U)"
-D LV_USE_STDLIB_MALLOC=0
-D LV_MEM_SIZE="(44U * 1024U)"
;-- TFT_eSPI --------------------------------------------------------------
-D DISABLE_ALL_LIBRARY_WARNINGS=1
; The following lines replace the TFT_eSPI User_setup.h-file
Expand Down Expand Up @@ -151,30 +148,23 @@ build_src_filter =
; use this if you are using Ubuntu or WSL2 (64 bit compiler)
[env:linux_64bit]
platform = native@^1.2.1
lib_deps =
${env.lib_deps}
;we need the master branch from github because of this commit https://github.com/lvgl/lv_drivers/commit/7b9dee11c93ad27e2591182457c1eba7677473be
lv_drivers=https://github.com/lvgl/lv_drivers
;lvgl/lv_drivers@^8.3.0
build_flags =
${env.build_flags}
;-- lvgl ------------------------------------------------------------------
; in lvgl 9, lv_drivers is not needed anymore
-D LV_USE_SDL=1
; 64 bit needs a lot more static memory
-D LV_MEM_CUSTOM=0
-D LV_MEM_SIZE="(64U * 1024U)"
;SDL2 from msys64
-l SDL2
; settings for lv_drivers
-D LV_LVGL_H_INCLUDE_SIMPLE
-D LV_DRV_NO_CONF
-D USE_SDL
-D SDL_INCLUDE_PATH="\"SDL2/SDL.h\""
-D LV_USE_STDLIB_MALLOC=0
-D LV_MEM_SIZE="(88U * 1024U)"
;-- OMOTE -----------------------------------------------------------------
-D SDL_HOR_RES=${env.custom_screen_width}
-D SDL_VER_RES=${env.custom_screen_heigth}
-D SDL_ZOOM=2
;-- hardware abstraction, needed to find hardwareLayer.h ------------------
-I hardware
-I hardware/windows_linux/lib/MQTT-C/include
;SDL2 from msys64
-l SDL2
build_src_filter =
+<*>
+<../hardware/windows_linux/*>
Expand All @@ -193,14 +183,14 @@ extends = env:windows_64bit
build_unflags =
${env:windows_64bit.build_unflags}
;-- lvgl ------------------------------------------------------------------
-D LV_MEM_CUSTOM=0
-D LV_MEM_SIZE="(64U * 1024U)"
-D LV_USE_STDLIB_MALLOC=0
-D LV_MEM_SIZE="(88U * 1024U)"
build_flags =
${env:windows_64bit.build_flags}
;-- lvgl ------------------------------------------------------------------
; 32 bit needs exact the same lvgl memory as on ESP32
-D LV_MEM_CUSTOM=0
-D LV_MEM_SIZE="(32U * 1024U)"
-D LV_MEM_SIZE="(44U * 1024U)"
; Take care. If you have a 64 bit compiler, this setting will tell the compiler to cross compile to 32 bit.
; Compiling is successfull, but linker fails. So use this env only with a 32 bit compiler.
; Probably a custom linker script would be needed for cross compiling to work.
Expand Down
Loading

0 comments on commit a1ce03d

Please sign in to comment.