diff --git a/src/dev/device.h b/src/dev/device.h index 75039f34..a17ef6dd 100644 --- a/src/dev/device.h +++ b/src/dev/device.h @@ -30,6 +30,9 @@ class BaseDevice { public: bool has_battery = false; bool has_backligth_control = true; +#if HASP_TARGET_PC + bool pc_is_running = true; +#endif virtual void reboot() {} diff --git a/src/drv/tft/tft_driver_sdl2.cpp b/src/drv/tft/tft_driver_sdl2.cpp index 82ca964d..c6c94651 100644 --- a/src/drv/tft/tft_driver_sdl2.cpp +++ b/src/drv/tft/tft_driver_sdl2.cpp @@ -75,6 +75,10 @@ void TftSdl::init(int32_t w, int h) * You have to call 'lv_tick_inc()' in periodically to inform LittelvGL about how much time were elapsed * Create an SDL thread to do this*/ SDL_CreateThread(tick_thread, "tick", NULL); + +#if HASP_USE_LVGL_TASK +#error "SDL2 LVGL task is not implemented" +#endif } void TftSdl::show_info() { diff --git a/src/drv/tft/tft_driver_win32drv.cpp b/src/drv/tft/tft_driver_win32drv.cpp index 38babbb9..25a85747 100644 --- a/src/drv/tft/tft_driver_win32drv.cpp +++ b/src/drv/tft/tft_driver_win32drv.cpp @@ -13,6 +13,7 @@ #include "dev/device.h" #include "hasp_debug.h" +#include "hasp_gui.h" #ifdef HASP_CUSTOMIZE_BOOTLOGO #include "custom/bootlogo.h" // Sketch tab header for xbm images @@ -48,21 +49,66 @@ int32_t TftWin32Drv::height() return _height; } +static void win32_message_loop(lv_task_t* param) +{ + MSG Message; +#if HASP_USE_LVGL_TASK + while(haspDevice.pc_is_running && GetMessageW(&Message, NULL, 0, 0)) { + TranslateMessage(&Message); + DispatchMessageW(&Message); + } + // apparently GetMessageW doesn't deliver WM_QUIT + haspDevice.pc_is_running = false; +#else + BOOL Result = PeekMessageW(&Message, NULL, 0, 0, TRUE); + if(Result != 0 && Result != -1) { + TranslateMessage(&Message); + DispatchMessageW(&Message); + if(Message.message == WM_QUIT) haspDevice.pc_is_running = false; + } +#endif +} + +static DWORD gui_entrypoint(HANDLE semaphore) +{ + /* Add a display + * Use the 'win32drv' driver which creates window on PC's monitor to simulate a display + * The following input devices are handled: mouse, keyboard, mousewheel */ + lv_win32_init(0, SW_SHOWNORMAL, haspTft.width(), haspTft.height(), 0); + lv_win32_set_title(haspDevice.get_hostname()); + +#if HASP_USE_LVGL_TASK + // let the init() function continue + ReleaseSemaphore(semaphore, 1, NULL); + // run the LVGL task as a thread + HANDLE thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)gui_task, NULL, 0, NULL); + // run a blocking message loop on this thread + win32_message_loop(NULL); + // wait for the LVGL task now + WaitForSingleObject(thread, 4000); +#else + // create a LVGL tick thread + CreateThread(NULL, 0, tick_thread, NULL, 0, NULL); + // create a LVGL task for the message loop + lv_task_create(win32_message_loop, 5, LV_TASK_PRIO_HIGHEST, NULL); +#endif + return 0; +} + void TftWin32Drv::init(int32_t w, int h) { _width = w; _height = h; - /* Add a display - * Use the 'win32drv' driver which creates window on PC's monitor to simulate a display - * The following input devices are handled: mouse, keyboard, mousewheel */ - lv_win32_init(0, SW_SHOWNORMAL, w, h, 0); - lv_win32_set_title(haspDevice.get_hostname()); - - /* Tick init. - * You have to call 'lv_tick_inc()' in periodically to inform LittelvGL about how much time were elapsed - * Create a Windows thread to do this*/ - CreateThread(NULL, 0, tick_thread, NULL, 0, NULL); +#if HASP_USE_LVGL_TASK + // run a thread for creating the window and running the message loop + HANDLE semaphore = CreateSemaphore(NULL, 0, 1, NULL); + HANDLE thread = CreateThread(NULL, 0, gui_entrypoint, semaphore, 0, NULL); + WaitForSingleObject(semaphore, INFINITE); +#else + // do not use the gui_task(), just init the GUI and return + gui_entrypoint(NULL); +#endif } void TftWin32Drv::show_info() { diff --git a/src/hasp_gui.cpp b/src/hasp_gui.cpp index d39195e8..af4c8388 100644 --- a/src/hasp_gui.cpp +++ b/src/hasp_gui.cpp @@ -382,23 +382,34 @@ void guiEverySecond(void) // nothing } -#if defined(ESP32) && defined(HASP_USE_ESP_MQTT) - #if HASP_USE_LVGL_TASK == 1 -static void gui_task(void* args) +void gui_task(void* args) { LOG_TRACE(TAG_GUI, "Start to run LVGL"); - while(1) { + while(haspDevice.pc_is_running) { + // no idea what MQTT has to do with LVGL - the #if is copied from the code below +#if defined(ESP32) && defined(HASP_USE_ESP_MQTT) /* Try to take the semaphore, call lvgl related function on success */ - // if(pdTRUE == xSemaphoreTake(xGuiSemaphore, pdMS_TO_TICKS(10))) { if(pdTRUE == xSemaphoreTake(xGuiSemaphore, portMAX_DELAY)) { lv_task_handler(); xSemaphoreGive(xGuiSemaphore); vTaskDelay(pdMS_TO_TICKS(5)); } +#else + // optimize lv_task_handler() by actually using the returned delay value + auto time_start = millis(); + uint32_t sleep_time = lv_task_handler(); + delay(sleep_time); + auto time_end = millis(); + lv_tick_inc(time_end - time_start); +#endif } } +#endif // HASP_USE_LVGL_TASK +#if defined(ESP32) && defined(HASP_USE_ESP_MQTT) + +#if HASP_USE_LVGL_TASK == 1 esp_err_t gui_setup_lvgl_task() { #if CONFIG_FREERTOS_UNICORE == 0 diff --git a/src/hasp_gui.h b/src/hasp_gui.h index a95e877a..8b5b12af 100644 --- a/src/hasp_gui.h +++ b/src/hasp_gui.h @@ -60,6 +60,11 @@ uint32_t guiScreenshotEtag(); void gui_flush_cb(lv_disp_drv_t* disp, const lv_area_t* area, lv_color_t* color_p); void gui_antiburn_cb(lv_disp_drv_t* disp, const lv_area_t* area, lv_color_t* color_p); +/* ===== Main LVGL Task ===== */ +#if HASP_USE_LVGL_TASK == 1 +void gui_task(void* args); +#endif + /* ===== Locks ===== */ #ifdef ESP32 IRAM_ATTR bool gui_acquire(TickType_t timeout); @@ -73,4 +78,4 @@ bool guiGetConfig(const JsonObject& settings); bool guiSetConfig(const JsonObject& settings); #endif // HASP_USE_CONFIG -#endif // HASP_GUI_H \ No newline at end of file +#endif // HASP_GUI_H diff --git a/src/main_pc.cpp b/src/main_pc.cpp index 2b4f7362..cb6f7c03 100644 --- a/src/main_pc.cpp +++ b/src/main_pc.cpp @@ -189,8 +189,7 @@ int main(int argc, char* argv[]) loop(); } #elif USE_WIN32DRV - extern bool lv_win32_quit_signal; - while(!lv_win32_quit_signal) { + while(haspDevice.pc_is_running) { loop(); } #endif diff --git a/user_setups/win32/windows_gdi_64bits.ini b/user_setups/win32/windows_gdi_64bits.ini index e3a86401..039c4004 100644 --- a/user_setups/win32/windows_gdi_64bits.ini +++ b/user_setups/win32/windows_gdi_64bits.ini @@ -29,6 +29,7 @@ build_flags = -D HASP_USE_JPGDECODE=0 -D HASP_USE_MQTT=1 -D HASP_USE_SYSLOG=0 + -D HASP_USE_LVGL_TASK=1 -D MQTT_MAX_PACKET_SIZE=2048 -D HASP_ATTRIBUTE_FAST_MEM= -D IRAM_ATTR= ; No IRAM_ATTR available