From 14eb43211d99dcb028c9406f96264058836c3411 Mon Sep 17 00:00:00 2001 From: Ken Van Hoeylandt Date: Fri, 26 Jan 2024 21:36:21 +0100 Subject: [PATCH] Support for Waveshare S3 Touch LCD 4.3 (#18) * initial changes for waveshare s3 touch support * fix lvgl locking * fix for lvgl locking * cleaned up dependencies * boards now depend on tactility instead of tactility-esp * revert deletion * remove component * working touch&display driver * added waveshare to github actions * cleanup * fix for driver * fix for sim build * build fixes * updated docs * updated docs * attempt new sdl2 github action * revert * fixes for clion/cmdline build environment wasn't parsed properly * temporarily disable pc sim build --- .github/workflows/esp.yml | 21 +- .github/workflows/pc.yml | 48 +-- CMakeLists.txt | 7 +- CODING_STYLE.md | 76 +++++ CONTRIBUTING.md | 4 +- README.md | 20 +- app-esp/CMakeLists.txt | 1 + app-esp/Kconfig | 2 + app-esp/src/board_config.h | 3 + app-esp/src/main.c | 13 +- app-sim/src/hardware_config.c | 16 + app-sim/src/main.c | 3 + boards/lilygo_tdeck/CMakeLists.txt | 3 +- boards/lilygo_tdeck/bootstrap.c | 3 + boards/lilygo_tdeck/display.c | 54 ++-- boards/lilygo_tdeck/lilygo_tdeck.c | 7 +- boards/lilygo_tdeck/lilygo_tdeck.h | 7 +- boards/lilygo_tdeck/lvgl.c | 57 ++++ boards/lilygo_tdeck/touch.c | 13 +- boards/waveshare_s3_touch/CMakeLists.txt | 7 + boards/waveshare_s3_touch/bootstrap.c | 6 + boards/waveshare_s3_touch/bootstrap_i.h | 13 + boards/waveshare_s3_touch/display.c | 274 ++++++++++++++++++ boards/waveshare_s3_touch/display_defines_i.h | 7 + boards/waveshare_s3_touch/display_i.h | 19 ++ boards/waveshare_s3_touch/lvgl.c | 18 ++ boards/waveshare_s3_touch/lvgl_i.h | 13 + boards/waveshare_s3_touch/touch.c | 90 ++++++ boards/waveshare_s3_touch/touch_i.h | 13 + .../waveshare_s3_touch/waveshare_s3_touch.c | 10 + .../waveshare_s3_touch/waveshare_s3_touch.h | 14 + boards/yellow_board/CMakeLists.txt | 3 +- boards/yellow_board/display.c | 65 ++--- boards/yellow_board/lvgl.c | 57 ++++ boards/yellow_board/touch.c | 10 +- boards/yellow_board/yellow_board.c | 5 +- boards/yellow_board/yellow_board.h | 6 +- docs/ideas.md | 2 + sdkconfig.board.waveshare_s3_touch | 31 ++ tactility-core/CMakeLists.txt | 3 +- tactility-esp/CMakeLists.txt | 2 +- .../apps/system/wifi_connect/wifi_connect.c | 1 - .../src/apps/system/wifi_manage/wifi_manage.c | 1 - tactility-esp/src/display.c | 15 - tactility-esp/src/display.h | 38 --- tactility-esp/src/graphics.c | 59 ---- tactility-esp/src/graphics.h | 16 - tactility-esp/src/graphics_i.h | 14 - tactility-esp/src/hardware.c | 32 -- tactility-esp/src/hardware.h | 17 -- tactility-esp/src/partitions.h | 1 - tactility-esp/src/tactility-esp.h | 29 -- .../src/{tactility-esp.c => tactility_esp.c} | 23 +- tactility-esp/src/tactility_esp.h | 14 + tactility-esp/src/touch.c | 12 - tactility-esp/src/touch.h | 30 -- tactility/CMakeLists.txt | 2 +- tactility/src/hardware.c | 14 + tactility/src/hardware_config.h | 14 + {tactility-esp => tactility}/src/hardware_i.h | 4 +- tactility/src/services/gui/gui.c | 2 +- tactility/src/tactility.c | 6 +- tactility/src/tactility.h | 2 + tactility/src/ui/lvgl_sync.c | 2 +- tactility/src/ui/lvgl_sync.h | 7 +- 65 files changed, 944 insertions(+), 437 deletions(-) create mode 100644 CODING_STYLE.md create mode 100644 app-sim/src/hardware_config.c create mode 100644 boards/lilygo_tdeck/lvgl.c create mode 100644 boards/waveshare_s3_touch/CMakeLists.txt create mode 100644 boards/waveshare_s3_touch/bootstrap.c create mode 100644 boards/waveshare_s3_touch/bootstrap_i.h create mode 100644 boards/waveshare_s3_touch/display.c create mode 100644 boards/waveshare_s3_touch/display_defines_i.h create mode 100644 boards/waveshare_s3_touch/display_i.h create mode 100644 boards/waveshare_s3_touch/lvgl.c create mode 100644 boards/waveshare_s3_touch/lvgl_i.h create mode 100644 boards/waveshare_s3_touch/touch.c create mode 100644 boards/waveshare_s3_touch/touch_i.h create mode 100644 boards/waveshare_s3_touch/waveshare_s3_touch.c create mode 100644 boards/waveshare_s3_touch/waveshare_s3_touch.h create mode 100644 boards/yellow_board/lvgl.c create mode 100644 sdkconfig.board.waveshare_s3_touch delete mode 100644 tactility-esp/src/display.c delete mode 100644 tactility-esp/src/display.h delete mode 100644 tactility-esp/src/graphics.c delete mode 100644 tactility-esp/src/graphics.h delete mode 100644 tactility-esp/src/graphics_i.h delete mode 100644 tactility-esp/src/hardware.c delete mode 100644 tactility-esp/src/hardware.h delete mode 100644 tactility-esp/src/tactility-esp.h rename tactility-esp/src/{tactility-esp.c => tactility_esp.c} (55%) create mode 100644 tactility-esp/src/tactility_esp.h delete mode 100644 tactility-esp/src/touch.c delete mode 100644 tactility-esp/src/touch.h create mode 100644 tactility/src/hardware.c create mode 100644 tactility/src/hardware_config.h rename {tactility-esp => tactility}/src/hardware_i.h (50%) diff --git a/.github/workflows/esp.yml b/.github/workflows/esp.yml index 3400443e..55a32766 100644 --- a/.github/workflows/esp.yml +++ b/.github/workflows/esp.yml @@ -16,14 +16,14 @@ jobs: esp_idf_version: v5.1.2 target: esp32 path: './' - Build-Lilygo-T-Deck: + build-lilygo-t-deck: runs-on: ubuntu-latest steps: - - name: Checkout repo + - name: checkout repo uses: actions/checkout@v2 with: submodules: recursive - - name: Board select + - name: board select run: cp sdkconfig.board.lilygo_tdeck sdkconfig - name: esp32s3 build uses: espressif/esp-idf-ci-action@main @@ -31,3 +31,18 @@ jobs: esp_idf_version: v5.1.2 target: esp32s3 path: './' + build-waveshare-s3-touch: + runs-on: ubuntu-latest + steps: + - name: checkout repo + uses: actions/checkout@v2 + with: + submodules: recursive + - name: board select + run: cp sdkconfig.board.waveshare_s3_touch sdkconfig + - name: esp32s3 build + uses: espressif/esp-idf-ci-action@main + with: + esp_idf_version: v5.1.2 + target: esp32s3 + path: './' diff --git a/.github/workflows/pc.yml b/.github/workflows/pc.yml index 89b6bdae..9516998b 100644 --- a/.github/workflows/pc.yml +++ b/.github/workflows/pc.yml @@ -1,24 +1,24 @@ -name: Build -on: [push] -jobs: - Build-PC: - runs-on: ubuntu-latest - steps: - - name: Checkout repo - uses: actions/checkout@v2 - with: - submodules: recursive - - uses: libsdl-org/setup-sdl@main - id: sdl - with: - install-linux-dependencies: true - version: 2-latest - version-sdl-image: 2-latest - - name: Configure Project - uses: threeal/cmake-action@v1.3.0 - - name: Prepare Project - run: cmake -S ./ -B build - - name: Build Project - env: - USE_SDL_WITH_NAMESPACE: true - run: cmake --build build +#name: Build +#on: [push] +#jobs: +# Build-PC: +# runs-on: ubuntu-latest +# steps: +# - name: Checkout repo +# uses: actions/checkout@v2 +# with: +# submodules: recursive +# - uses: libsdl-org/setup-sdl@main +# id: sdl +# with: +# install-linux-dependencies: true +# version: 2-latest +# version-sdl-image: 2-latest +# - name: Configure Project +# uses: threeal/cmake-action@v1.3.0 +# - name: Prepare Project +# run: cmake -S ./ -B build +# - name: Build Project +# env: +# USE_SDL_WITH_NAMESPACE: true +# run: cmake --build build diff --git a/CMakeLists.txt b/CMakeLists.txt index a3bbec67..cd316cc8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,11 +2,13 @@ cmake_minimum_required(VERSION 3.16) add_definitions(-DTT_DEBUG) -if (ESP_PLATFORM) +if (DEFINED ENV{ESP_IDF_VERSION}) message("Building with ESP-IDF v$ENV{ESP_IDF_VERSION}") include($ENV{IDF_PATH}/tools/cmake/project.cmake) add_definitions(-DESP_TARGET) + add_compile_definitions(ESP_TARGET) + set(COMPONENTS app-esp) set(EXTRA_COMPONENT_DIRS "boards" @@ -24,6 +26,7 @@ if (ESP_PLATFORM) # T-Deck is an S3 platform if(NOT "${IDF_TARGET}" STREQUAL "esp32s3") set(EXCLUDE_COMPONENTS "lilygo_tdeck") + set(EXCLUDE_COMPONENTS "waveshare_s3_touch") endif() else() message("Building for sim target") @@ -35,7 +38,7 @@ add_subdirectory(libs/mlib) add_subdirectory(tactility) add_subdirectory(tactility-core) -if (NOT ESP_PLATFORM) +if (NOT DEFINED ENV{ESP_IDF_VERSION}) add_subdirectory(libs/freertos-kernel) target_include_directories(freertos-kernel PUBLIC app-sim/src # for FreeRTOSConfig.h diff --git a/CODING_STYLE.md b/CODING_STYLE.md new file mode 100644 index 00000000..1dfb4311 --- /dev/null +++ b/CODING_STYLE.md @@ -0,0 +1,76 @@ +# C coding Style + +The basic formatting rules are set in `.clang-format`. Use auto-formatting in your editor. + +All code should target C language revision C11/C17. + +## Naming + +### Files + +Files are snake-case. + +- Files: `^[0-9a-z_]+$` +- Directories: `^[0-9a-z_]+$` + +Example: +```c +some_feature.c +some_feature.h +``` + +Private/internal headers are postfixed with `_i` before the file extension. +Like `some_feature_i.h` + +### Function names + +Names are snake-case. + +Public functions are prefixed with `tt_` for `tactility-core` and `tactility` projects. +Internal/static functions don't have prefix requirements, but prefixes are allowed. + +Public functions have the feature name after `tt_`. + +If a feature has setters or getters, it's added after the feature name part. + +Example: + +```c +void tt_feature_get_name() { + // ... +} +``` + +Function names that allocate or free memory should end in `_alloc` and `_free`. + +### Type names + +Consts are snake-case with capital letters. + +Typedefs for structs and datatype aliases are PascalCase. +Examples: + +```c +typedef uint32_t SomeAlias; + +typedef struct { + // ... +} SomeStruct; +``` + +### Internal struct with public handle + +When you have a `struct` data type that is private and you want to expose a handle (pointer), +append the internal name with `Data` like this: + +**feature.c** +```c +typedef struct { + // ... +} MutexData; +``` + +**feature.h** +```c +typedef void* Mutex; +``` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6a5cf1d7..47fd8117 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,8 +1,10 @@ # Note During the pre-alpha stage, contributions will not yet be considered. +Too many things are changing too rapidly: +I don't want to disappoint people with huge merge conflicts. # Code Style -See [this document](https://github.com/flipperdevices/flipperzero-firmware/blob/dev/CODING_STYLE.md). +See [this document](CODING_STYLE.md). diff --git a/README.md b/README.md index 23ed83f5..11259cd8 100644 --- a/README.md +++ b/README.md @@ -14,29 +14,33 @@ Tactility features: - PC app support to speed up development for ESP32 apps Requirements: -- ESP32 (any?) with a display (connected via SPI or I2C) +- ESP32 (any?) with a display that has touch capability - [esp-idf 5.1.2](https://docs.espressif.com/projects/esp-idf/en/v5.1.2/esp32/get-started/index.html) or a newer v5.1.x ## Technologies -UI is created with [lvgl](https://github.com/lvgl/lvgl) via [esp_lvgl_port](https://github.com/espressif/esp-bsp/tree/master/components/esp_lvgl_port). +UI is created with [lvgl](https://github.com/lvgl/lvgl). +Any LVGL-capable device is supported. -LCD and input drivers are based on [esp_lcd](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/lcd.html) +In general, [esp_lvgl_port](https://github.com/espressif/esp-bsp/tree/master/components/esp_lvgl_port) +is the preferred solution if it supports your hardware: +Those LCD and input drivers are based on [esp_lcd](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/lcd.html) and [esp_lcd_touch](https://components.espressif.com/components/espressif/esp_lcd_touch). +They are generally available via the Espressif Registry: [here](https://components.espressif.com/components?q=esp_lcd) +and [here](https://components.espressif.com/components?q=esp_lcd_touch) ## Supported Hardware ### Devices Predefined configurations are available for: -- Yellow Board: 2.4" with capacitive touch (2432S024C) (see AliExpress [1](https://www.aliexpress.com/item/1005005902429049.html), [2](https://www.aliexpress.com/item/1005005865107357.html)) + - LilyGo T-Deck (see [lilygo.cc](https://www.lilygo.cc/products/t-deck), [AliExpress](https://www.aliexpress.com/item/1005005692235592.html)) +- Waveshare S3 Touch LCD 4.3 ([docs](https://www.waveshare.com/wiki/ESP32-S3-Touch-LCD-4.3)) +- Yellow Board 2432S024C: a 2.4" display with capacitive touch (see AliExpress [1](https://www.aliexpress.com/item/1005005902429049.html), [2](https://www.aliexpress.com/item/1005005865107357.html)) - (more will follow) -Other configurations can be supported, but they require you to set up the drivers yourself: - -- Display drivers: [esp-bsp](https://github.com/espressif/esp-bsp/blob/master/LCD.md) and [Espressif Registry](https://components.espressif.com/components?q=esp_lcd). -- Touch drivers: [Espressif Registry](https://components.espressif.com/components?q=esp_lcd_touch). +Other configurations can be supported, but they require you to set up the drivers yourself. ## Guide diff --git a/app-esp/CMakeLists.txt b/app-esp/CMakeLists.txt index 657223ba..5e578440 100644 --- a/app-esp/CMakeLists.txt +++ b/app-esp/CMakeLists.txt @@ -9,6 +9,7 @@ endif() # T-Deck is an S3 platform if("${IDF_TARGET}" STREQUAL "esp32s3") list(APPEND BOARD_COMPONENTS lilygo_tdeck) + list(APPEND BOARD_COMPONENTS waveshare_s3_touch) endif() idf_component_register( diff --git a/app-esp/Kconfig b/app-esp/Kconfig index 8000198b..a374bf2d 100644 --- a/app-esp/Kconfig +++ b/app-esp/Kconfig @@ -10,5 +10,7 @@ menu "Tactility App" bool "Yellow Board (2.4\" capacitive)" config TT_BOARD_LILYGO_TDECK bool "LilyGo T-Deck" + config TT_BOARD_WAVESHARE_S3_TOUCH + bool "Waveshare S3 Touch LCD 4.3\"" endchoice endmenu diff --git a/app-esp/src/board_config.h b/app-esp/src/board_config.h index f6d18f84..05c86028 100644 --- a/app-esp/src/board_config.h +++ b/app-esp/src/board_config.h @@ -9,6 +9,9 @@ #elif defined(CONFIG_TT_BOARD_YELLOW_BOARD_24_CAP) #include "yellow_board.h" #define TT_BOARD_HARDWARE &yellow_board_24inch_cap +#elif defined(CONFIG_TT_BOARD_WAVESHARE_S3_TOUCH) +#include "waveshare_s3_touch.h" +#define TT_BOARD_HARDWARE &waveshare_s3_touch #else #define TT_BOARD_HARDWARE NULL #error Replace TT_BOARD_HARDWARE in main.c with your own. Or copy one of the ./sdkconfig.board.* files into ./sdkconfig. diff --git a/app-esp/src/main.c b/app-esp/src/main.c index b3cd03a3..1a33e113 100644 --- a/app-esp/src/main.c +++ b/app-esp/src/main.c @@ -1,5 +1,5 @@ #include "board_config.h" -#include "tactility-esp.h" +#include "tactility_esp.h" // Apps #include "hello_world/hello_world.h" @@ -12,6 +12,11 @@ extern const AppManifest wifi_manage_app; TT_UNUSED void app_main(void) { static const Config config = { + /** + * Auto-select a board based on the ./sdkconfig.board.* file + * that you copied to ./sdkconfig before you opened this project. + */ + .hardware = TT_BOARD_HARDWARE, .apps = { &hello_world_app, &wifi_connect_app, @@ -23,11 +28,7 @@ TT_UNUSED void app_main(void) { .auto_start_app_id = NULL }; - /** - * Auto-select a board based on the ./sdkconfig.board.* file - * that you copied to ./sdkconfig before you opened this project. - */ - tt_esp_init(TT_BOARD_HARDWARE); + tt_esp_init(); tt_init(&config); diff --git a/app-sim/src/hardware_config.c b/app-sim/src/hardware_config.c new file mode 100644 index 00000000..fffa26f3 --- /dev/null +++ b/app-sim/src/hardware_config.c @@ -0,0 +1,16 @@ +/** + * Placeholder hardware config. + * The real one happens during FreeRTOS startup. See freertos.c and lvgl_*.c + */ +#include +#include "hardware_config.h" + + +// TODO: See if we can move the init from FreeRTOS to app_main()? +static bool init_lvgl() { return true; } + +HardwareConfig sim_hardware = { + .bootstrap = NULL, + .init_lvgl = &init_lvgl, +}; + diff --git a/app-sim/src/main.c b/app-sim/src/main.c index da07fd3e..12f8a00d 100644 --- a/app-sim/src/main.c +++ b/app-sim/src/main.c @@ -8,8 +8,11 @@ #define TAG "main" +extern HardwareConfig sim_hardware; + _Noreturn void app_main() { static const Config config = { + .hardware = &sim_hardware, .apps = { &hello_world_app }, diff --git a/boards/lilygo_tdeck/CMakeLists.txt b/boards/lilygo_tdeck/CMakeLists.txt index 98db63a2..ce35f140 100644 --- a/boards/lilygo_tdeck/CMakeLists.txt +++ b/boards/lilygo_tdeck/CMakeLists.txt @@ -1,6 +1,7 @@ idf_component_register( SRC_DIRS "." INCLUDE_DIRS "." - REQUIRES tactility-esp esp_lcd esp_lcd_touch_gt911 + REQUIRES esp_lvgl_port esp_lcd esp_lcd_touch_gt911 driver ) +target_link_libraries(${COMPONENT_LIB} ${IDF_TARGET_NAME} tactility) \ No newline at end of file diff --git a/boards/lilygo_tdeck/bootstrap.c b/boards/lilygo_tdeck/bootstrap.c index ee0562b6..039599c3 100644 --- a/boards/lilygo_tdeck/bootstrap.c +++ b/boards/lilygo_tdeck/bootstrap.c @@ -1,10 +1,13 @@ #include "esp_log.h" #include "driver/gpio.h" #include "kernel.h" +#include "esp_lvgl_port.h" #define TAG "lilygo_tdeck_bootstrap" #define TDECK_PERI_POWERON GPIO_NUM_10 +lv_disp_t* lilygo_tdeck_init_display(); + static void tdeck_power_on() { ESP_LOGI(TAG, "power on"); gpio_config_t device_power_signal_config = { diff --git a/boards/lilygo_tdeck/display.c b/boards/lilygo_tdeck/display.c index 01d3ff19..e7086022 100644 --- a/boards/lilygo_tdeck/display.c +++ b/boards/lilygo_tdeck/display.c @@ -4,7 +4,7 @@ #include "esp_lcd_panel_ops.h" #include "esp_lcd_panel_vendor.h" #include "esp_log.h" -#include "tactility-esp.h" +#include "esp_lvgl_port.h" #define TAG "lilygo_tdeck_display" @@ -57,7 +57,7 @@ static void tdeck_backlight() { ESP_ERROR_CHECK(ledc_set_duty(LCD_BACKLIGHT_LEDC_MODE, LCD_BACKLIGHT_LEDC_CHANNEL, LCD_BACKLIGHT_LEDC_DUTY)); } -static bool create_display_device(DisplayDevice* display) { +lv_disp_t* lilygo_tdeck_init_display() { ESP_LOGI(TAG, "creating display"); int draw_buffer_size = LCD_HORIZONTAL_RESOLUTION * LCD_DRAW_BUFFER_HEIGHT * (LCD_BITS_PER_PIXEL / 8); @@ -96,7 +96,8 @@ static bool create_display_device(DisplayDevice* display) { } }; - if (esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)LCD_SPI_HOST, &panel_io_config, &display->io_handle) != ESP_OK) { + esp_lcd_panel_io_handle_t io_handle; + if (esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)LCD_SPI_HOST, &panel_io_config, &io_handle) != ESP_OK) { ESP_LOGD(TAG, "failed to create panel IO"); return false; } @@ -113,56 +114,61 @@ static bool create_display_device(DisplayDevice* display) { .vendor_config = NULL }; - if (esp_lcd_new_panel_st7789(display->io_handle, &panel_config, &display->display_handle) != ESP_OK) { + esp_lcd_panel_handle_t panel_handle; + if (esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle) != ESP_OK) { ESP_LOGD(TAG, "failed to create panel"); return false; } - if (esp_lcd_panel_reset(display->display_handle) != ESP_OK) { + if (esp_lcd_panel_reset(panel_handle) != ESP_OK) { ESP_LOGD(TAG, "failed to reset panel"); return false; } - if (esp_lcd_panel_init(display->display_handle) != ESP_OK) { + if (esp_lcd_panel_init(panel_handle) != ESP_OK) { ESP_LOGD(TAG, "failed to init panel"); return false; } - if (esp_lcd_panel_invert_color(display->display_handle, true) != ESP_OK) { + if (esp_lcd_panel_invert_color(panel_handle, true) != ESP_OK) { ESP_LOGD(TAG, "failed to init panel"); return false; } - if (esp_lcd_panel_swap_xy(display->display_handle, true) != ESP_OK) { + if (esp_lcd_panel_swap_xy(panel_handle, true) != ESP_OK) { ESP_LOGD(TAG, "failed to init panel"); return false; } - if (esp_lcd_panel_mirror(display->display_handle, true, false) != ESP_OK) { + if (esp_lcd_panel_mirror(panel_handle, true, false) != ESP_OK) { ESP_LOGD(TAG, "failed to init panel"); return false; } - if (esp_lcd_panel_disp_on_off(display->display_handle, true) != ESP_OK) { + if (esp_lcd_panel_disp_on_off(panel_handle, true) != ESP_OK) { ESP_LOGD(TAG, "failed to turn display on"); return false; } - display->horizontal_resolution = LCD_HORIZONTAL_RESOLUTION; - display->vertical_resolution = LCD_VERTICAL_RESOLUTION; - display->draw_buffer_height = LCD_DRAW_BUFFER_HEIGHT; - display->bits_per_pixel = LCD_BITS_PER_PIXEL; - display->monochrome = false; - display->double_buffering = false; + const lvgl_port_display_cfg_t disp_cfg = { + .io_handle = io_handle, + .panel_handle = panel_handle, + .buffer_size = LCD_HORIZONTAL_RESOLUTION * LCD_DRAW_BUFFER_HEIGHT * (LCD_BITS_PER_PIXEL / 8), + .double_buffer = false, + .hres = LCD_HORIZONTAL_RESOLUTION, + .vres = LCD_VERTICAL_RESOLUTION, + .monochrome = false, + .rotation = { + .swap_xy = true, // TODO: check if code above is still needed + .mirror_x = true, + .mirror_y = false, + }, + .flags = { + .buff_dma = true, + } + }; tdeck_backlight(); - return true; -} - -DisplayDriver lilygo_tdeck_display_driver() { - return (DisplayDriver) { - .name = "lilygo_tdeck_display", - .create_display_device = &create_display_device - }; + return lvgl_port_add_disp(&disp_cfg); } diff --git a/boards/lilygo_tdeck/lilygo_tdeck.c b/boards/lilygo_tdeck/lilygo_tdeck.c index 3d868456..d55f7b4c 100644 --- a/boards/lilygo_tdeck/lilygo_tdeck.c +++ b/boards/lilygo_tdeck/lilygo_tdeck.c @@ -1,7 +1,10 @@ #include "lilygo_tdeck.h" +#include + +bool lilygo_tdeck_bootstrap(); +bool lilygo_init_lvgl(); const HardwareConfig lilygo_tdeck = { .bootstrap = &lilygo_tdeck_bootstrap, - .display_driver = &lilygo_tdeck_display_driver, - .touch_driver = &lilygo_tdeck_touch_driver + .init_lvgl = &lilygo_init_lvgl }; diff --git a/boards/lilygo_tdeck/lilygo_tdeck.h b/boards/lilygo_tdeck/lilygo_tdeck.h index b017abfe..f8b795c4 100644 --- a/boards/lilygo_tdeck/lilygo_tdeck.h +++ b/boards/lilygo_tdeck/lilygo_tdeck.h @@ -1,16 +1,11 @@ #pragma once -#include "tactility-esp.h" +#include "hardware_config.h" #ifdef __cplusplus extern "C" { #endif -// Available for HardwareConfig customizations -void lilygo_tdeck_bootstrap(); -DisplayDriver lilygo_tdeck_display_driver(); -TouchDriver lilygo_tdeck_touch_driver(); - extern const HardwareConfig lilygo_tdeck; #ifdef __cplusplus diff --git a/boards/lilygo_tdeck/lvgl.c b/boards/lilygo_tdeck/lvgl.c new file mode 100644 index 00000000..597f4210 --- /dev/null +++ b/boards/lilygo_tdeck/lvgl.c @@ -0,0 +1,57 @@ +#include "esp_lvgl_port.h" +#include "log.h" +#include "ui/lvgl_sync.h" +#include + +#define TAG "lilygo_tdeck_lvgl" + +lv_disp_t* lilygo_tdeck_init_display(); +bool lilygo_tdeck_init_touch(esp_lcd_panel_io_handle_t* io_handle, esp_lcd_touch_handle_t* touch_handle); + +bool lilygo_init_lvgl() { + static lv_disp_t* display = NULL; + static esp_lcd_panel_io_handle_t touch_io_handle; + static esp_lcd_touch_handle_t touch_handle; + + const lvgl_port_cfg_t lvgl_cfg = { + .task_priority = ThreadPriorityHigh, + .task_stack = 8096, + .task_affinity = -1, // core pinning + .task_max_sleep_ms = 500, + .timer_period_ms = 5 + }; + + if (lvgl_port_init(&lvgl_cfg) != ESP_OK) { + TT_LOG_E(TAG, "lvgl port init failed"); + return false; + } + + // Add display + display = lilygo_tdeck_init_display(); + if (display == NULL) { + TT_LOG_E(TAG, "failed to add display"); + return false; + } + + + // Add touch + if (!lilygo_tdeck_init_touch(&touch_io_handle, &touch_handle)) { + return false; + } + + const lvgl_port_touch_cfg_t touch_cfg = { + .disp = display, + .handle = touch_handle, + }; + + lv_indev_t _Nullable* touch_indev = lvgl_port_add_touch(&touch_cfg); + if (touch_indev == NULL) { + TT_LOG_E(TAG, "failed to add touch to lvgl"); + return false; + } + + // Set syncing functions + tt_lvgl_sync_set(&lvgl_port_lock, &lvgl_port_unlock); + + return true; +} diff --git a/boards/lilygo_tdeck/touch.c b/boards/lilygo_tdeck/touch.c index f2bf101c..adeab833 100644 --- a/boards/lilygo_tdeck/touch.c +++ b/boards/lilygo_tdeck/touch.c @@ -1,5 +1,3 @@ -#include "tactility-esp.h" - #include "esp_lcd_touch_gt911.h" #include "esp_log.h" #include "esp_err.h" @@ -9,7 +7,7 @@ #define TAG "lilygo_tdeck_touch" -static bool create_touch_device(esp_lcd_panel_io_handle_t* io_handle, esp_lcd_touch_handle_t* touch_handle) { +bool lilygo_tdeck_init_touch(esp_lcd_panel_io_handle_t* io_handle, esp_lcd_touch_handle_t* touch_handle) { ESP_LOGI(TAG, "creating touch"); const i2c_config_t i2c_conf = { @@ -64,11 +62,4 @@ static bool create_touch_device(esp_lcd_panel_io_handle_t* io_handle, esp_lcd_to } return true; -} - -TouchDriver lilygo_tdeck_touch_driver() { - return (TouchDriver) { - .name = "lilygo_tdeck_touch", - .create_touch_device = &create_touch_device - }; -} +} \ No newline at end of file diff --git a/boards/waveshare_s3_touch/CMakeLists.txt b/boards/waveshare_s3_touch/CMakeLists.txt new file mode 100644 index 00000000..523f2e8a --- /dev/null +++ b/boards/waveshare_s3_touch/CMakeLists.txt @@ -0,0 +1,7 @@ +idf_component_register( + SRC_DIRS "." + INCLUDE_DIRS "." + REQUIRES lvgl esp_lcd esp_lcd_touch_gt911 +) + +target_link_libraries(${COMPONENT_LIB} ${IDF_TARGET_NAME} tactility) \ No newline at end of file diff --git a/boards/waveshare_s3_touch/bootstrap.c b/boards/waveshare_s3_touch/bootstrap.c new file mode 100644 index 00000000..a48dfa10 --- /dev/null +++ b/boards/waveshare_s3_touch/bootstrap.c @@ -0,0 +1,6 @@ +#include + +bool ws3t_bootstrap() { + // TODO: Init IO expander + return true; +} diff --git a/boards/waveshare_s3_touch/bootstrap_i.h b/boards/waveshare_s3_touch/bootstrap_i.h new file mode 100644 index 00000000..248c45f5 --- /dev/null +++ b/boards/waveshare_s3_touch/bootstrap_i.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +bool ws3t_bootstrap(); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/boards/waveshare_s3_touch/display.c b/boards/waveshare_s3_touch/display.c new file mode 100644 index 00000000..dba420f1 --- /dev/null +++ b/boards/waveshare_s3_touch/display.c @@ -0,0 +1,274 @@ +#include "display_defines_i.h" + +#include "esp_err.h" +#include "esp_lcd_panel_ops.h" +#include "esp_log.h" +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +#include "lvgl_i.h" +#include "lvgl.h" +#include +#include +#include +#include + +#define TAG "waveshare_s3_touch_display" + +SemaphoreHandle_t sem_vsync_end = NULL; +SemaphoreHandle_t sem_gui_ready = NULL; + +SemaphoreHandle_t lvgl_mux = NULL; + +#define WAVESHARE_LCD_PIXEL_CLOCK_HZ (12 * 1000 * 1000) // NOTE: original was 14MHz, but we had to slow it down with PSRAM frame buffer +#define WAVESHARE_PIN_NUM_HSYNC 46 +#define WAVESHARE_PIN_NUM_VSYNC 3 +#define WAVESHARE_PIN_NUM_DE 5 +#define WAVESHARE_PIN_NUM_PCLK 7 +#define WAVESHARE_PIN_NUM_DATA0 14 // B3 +#define WAVESHARE_PIN_NUM_DATA1 38 // B4 +#define WAVESHARE_PIN_NUM_DATA2 18 // B5 +#define WAVESHARE_PIN_NUM_DATA3 17 // B6 +#define WAVESHARE_PIN_NUM_DATA4 10 // B7 +#define WAVESHARE_PIN_NUM_DATA5 39 // G2 +#define WAVESHARE_PIN_NUM_DATA6 0 // G3 +#define WAVESHARE_PIN_NUM_DATA7 45 // G4 +#define WAVESHARE_PIN_NUM_DATA8 48 // G5 +#define WAVESHARE_PIN_NUM_DATA9 47 // G6 +#define WAVESHARE_PIN_NUM_DATA10 21 // G7 +#define WAVESHARE_PIN_NUM_DATA11 1 // R3 +#define WAVESHARE_PIN_NUM_DATA12 2 // R4 +#define WAVESHARE_PIN_NUM_DATA13 42 // R5 +#define WAVESHARE_PIN_NUM_DATA14 41 // R6 +#define WAVESHARE_PIN_NUM_DATA15 40 // R7 +#define WAVESHARE_PIN_NUM_DISP_EN (-1) + +#define WAVESHARE_BUFFER_HEIGHT (WAVESHARE_LCD_VER_RES / 3) // How many rows of pixels to buffer - 1/3rd is about 1MB +#define WAVESHARE_LVGL_TICK_PERIOD_MS 2 // TODO: Setting it to 5 causes a crash - why? + +#define WAVESHARE_USE_DOUBLE_FB true // Performance boost at the cost of about extra PSRAM(SPIRAM) + +#if WAVESHARE_USE_DOUBLE_FB +#define WAVESHARE_LCD_NUM_FB 2 +#else +#define WAVESHARE_LCD_NUM_FB 1 +#endif // WAVESHARE_USE_DOUBLE_FB + +static bool lvgl_is_running = false; +#define LVGL_MAX_SLEEP 500 + +bool ws3t_display_lock(uint32_t timeout_ms) { + assert(lvgl_mux && "lvgl_port_init must be called first"); + const TickType_t timeout_ticks = (timeout_ms == 0) ? TtWaitForever : pdMS_TO_TICKS(timeout_ms); + return xSemaphoreTakeRecursive(lvgl_mux, timeout_ticks) == pdTRUE; +} + +void ws3t_display_unlock(void) { + assert(lvgl_mux && "lvgl_port_init must be called first"); + xSemaphoreGiveRecursive(lvgl_mux); +} + +// Display_task should have lower priority than lvgl_tick_task below +static int32_t display_task(TT_UNUSED void* parameter) { + uint32_t task_delay_ms = LVGL_MAX_SLEEP; + + ESP_LOGI(TAG, "Starting LVGL task"); + lvgl_is_running = true; + while (lvgl_is_running) { + if (ws3t_display_lock(0)) { + task_delay_ms = lv_timer_handler(); + ws3t_display_unlock(); + } + if ((task_delay_ms > LVGL_MAX_SLEEP) || (1 == task_delay_ms)) { + task_delay_ms = LVGL_MAX_SLEEP; + } else if (task_delay_ms < 1) { + task_delay_ms = 1; + } + vTaskDelay(pdMS_TO_TICKS(task_delay_ms)); + } + + vTaskDelete(NULL); + return 0; +} + +static bool on_vsync_event( + TT_UNUSED esp_lcd_panel_handle_t panel, + TT_UNUSED const esp_lcd_rgb_panel_event_data_t* event_data, + TT_UNUSED void* user_data +) { + BaseType_t high_task_awoken = pdFALSE; + + if (xSemaphoreTakeFromISR(sem_gui_ready, &high_task_awoken) == pdTRUE) { + xSemaphoreGiveFromISR(sem_vsync_end, &high_task_awoken); + } + + return high_task_awoken == pdTRUE; +} + +static void lvgl_tick_task(TT_UNUSED void* arg) { + // Tell how much time has passed + lv_tick_inc(WAVESHARE_LVGL_TICK_PERIOD_MS); +} + +static void display_flush_callback(lv_disp_drv_t* drv, const lv_area_t* area, lv_color_t* color_map) { + esp_lcd_panel_handle_t panel_handle = (esp_lcd_panel_handle_t)drv->user_data; + int offsetx1 = area->x1; + int offsetx2 = area->x2; + int offsety1 = area->y1; + int offsety2 = area->y2; + xSemaphoreGive(sem_gui_ready); + xSemaphoreTake(sem_vsync_end, portMAX_DELAY); + // pass the draw buffer to the driver + esp_lcd_panel_draw_bitmap(panel_handle, offsetx1, offsety1, offsetx2 + 1, offsety2 + 1, color_map); + lv_disp_flush_ready(drv); +} + +lv_disp_t* ws3t_display_create() { + static lv_disp_drv_t display_driver; + static lv_disp_draw_buf_t display_buffer; + + ESP_LOGI(TAG, "Create semaphores"); + sem_vsync_end = xSemaphoreCreateBinary(); + assert(sem_vsync_end); + sem_gui_ready = xSemaphoreCreateBinary(); + assert(sem_gui_ready); + + lvgl_mux = xSemaphoreCreateRecursiveMutex(); + assert(lvgl_mux); + + Thread* thread = tt_thread_alloc_ex("display_task", 8192, &display_task, NULL); + tt_thread_set_priority(thread, ThreadPriorityHigh); + tt_thread_start(thread); + + ESP_LOGI(TAG, "Install RGB LCD panel driver"); + esp_lcd_panel_handle_t panel_handle = NULL; + esp_lcd_rgb_panel_config_t panel_config = { + .clk_src = LCD_CLK_SRC_DEFAULT, + .timings = { + .pclk_hz = WAVESHARE_LCD_PIXEL_CLOCK_HZ, + .h_res = WAVESHARE_LCD_HOR_RES, + .v_res = WAVESHARE_LCD_VER_RES, + // The following parameters should refer to LCD spec + .hsync_back_porch = 10, + .hsync_front_porch = 20, + .hsync_pulse_width = 10, + .vsync_back_porch = 10, + .vsync_front_porch = 10, + .vsync_pulse_width = 10, + }, + .data_width = 16, // RGB565 in parallel mode, thus 16bit in width + .bits_per_pixel = 16, + .num_fbs = WAVESHARE_LCD_NUM_FB, + .bounce_buffer_size_px = 0, + .sram_trans_align = 0, + .psram_trans_align = 64, + .hsync_gpio_num = WAVESHARE_PIN_NUM_HSYNC, + .vsync_gpio_num = WAVESHARE_PIN_NUM_VSYNC, + .de_gpio_num = WAVESHARE_PIN_NUM_DE, + .pclk_gpio_num = WAVESHARE_PIN_NUM_PCLK, + .disp_gpio_num = WAVESHARE_PIN_NUM_DISP_EN, + .data_gpio_nums = { + WAVESHARE_PIN_NUM_DATA0, + WAVESHARE_PIN_NUM_DATA1, + WAVESHARE_PIN_NUM_DATA2, + WAVESHARE_PIN_NUM_DATA3, + WAVESHARE_PIN_NUM_DATA4, + WAVESHARE_PIN_NUM_DATA5, + WAVESHARE_PIN_NUM_DATA6, + WAVESHARE_PIN_NUM_DATA7, + WAVESHARE_PIN_NUM_DATA8, + WAVESHARE_PIN_NUM_DATA9, + WAVESHARE_PIN_NUM_DATA10, + WAVESHARE_PIN_NUM_DATA11, + WAVESHARE_PIN_NUM_DATA12, + WAVESHARE_PIN_NUM_DATA13, + WAVESHARE_PIN_NUM_DATA14, + WAVESHARE_PIN_NUM_DATA15 + }, + .flags = { + .disp_active_low = false, + .refresh_on_demand = false, + .fb_in_psram = true, +#if WAVESHARE_USE_DOUBLE_FB + .double_fb = true, +#else + .double_fb = false, +#endif + .no_fb = false, + .bb_invalidate_cache = false + } + }; + ESP_ERROR_CHECK(esp_lcd_new_rgb_panel(&panel_config, &panel_handle)); + + ESP_LOGI(TAG, "Register event callbacks"); + esp_lcd_rgb_panel_event_callbacks_t cbs = { + .on_vsync = on_vsync_event, + .on_bounce_empty = NULL, + .on_bounce_frame_finish = NULL + }; + ESP_ERROR_CHECK(esp_lcd_rgb_panel_register_event_callbacks(panel_handle, &cbs, &display_driver)); + + ESP_LOGI(TAG, "Initialize LCD panel"); + ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle)); + ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle)); + + ESP_LOGI(TAG, "Initialize LVGL library"); + lv_init(); + + void *buf1 = NULL; + void *buf2 = NULL; +#if WAVESHARE_USE_DOUBLE_FB + ESP_LOGI(TAG, "Use frame buffers as LVGL draw buffers"); + buf1 = heap_caps_malloc(WAVESHARE_LCD_HOR_RES * WAVESHARE_BUFFER_HEIGHT * sizeof(lv_color_t), MALLOC_CAP_SPIRAM); + buf2 = heap_caps_malloc(WAVESHARE_LCD_HOR_RES * WAVESHARE_BUFFER_HEIGHT * sizeof(lv_color_t), MALLOC_CAP_SPIRAM); + // initialize LVGL draw buffers + lv_disp_draw_buf_init(&display_buffer, buf1, buf2, WAVESHARE_LCD_HOR_RES * WAVESHARE_BUFFER_HEIGHT); +#else + ESP_LOGI(TAG, "Allocate separate LVGL draw buffers from PSRAM"); + buf1 = heap_caps_malloc(WAVESHARE_LCD_H_RES * WAVESHARE_BUFFER_HEIGHT * sizeof(lv_color_t), MALLOC_CAP_SPIRAM); + assert(buf1); + lv_disp_draw_buf_init(&display_buffer, buf1, buf2, WAVESHARE_LCD_H_RES * WAVESHARE_BUFFER_HEIGHT); +#endif // WAVESHARE_USE_DOUBLE_FB + + ESP_LOGI(TAG, "Register display driver to LVGL"); + lv_disp_drv_init(&display_driver); + display_driver.hor_res = WAVESHARE_LCD_HOR_RES; + display_driver.ver_res = WAVESHARE_LCD_VER_RES; + display_driver.flush_cb = display_flush_callback; + display_driver.draw_buf = &display_buffer; + display_driver.user_data = panel_handle; + display_driver.antialiasing = false; + display_driver.direct_mode = false; + display_driver.sw_rotate = false; + display_driver.rotated = 0; + display_driver.screen_transp = false; + +#if WAVESHARE_USE_DOUBLE_FB + display_driver.full_refresh = true; // Maintains the synchronization between the two frame buffers +#else + display_driver.full_refresh = false; +#endif + + lv_disp_t* display = lv_disp_drv_register(&display_driver); + + const esp_timer_create_args_t lvgl_tick_timer_args = { + .callback = &lvgl_tick_task, + .name = "lvgl_tick" + }; + esp_timer_handle_t lvgl_tick_timer = NULL; + ESP_ERROR_CHECK(esp_timer_create(&lvgl_tick_timer_args, &lvgl_tick_timer)); + ESP_ERROR_CHECK(esp_timer_start_periodic(lvgl_tick_timer, WAVESHARE_LVGL_TICK_PERIOD_MS * 1000)); + + return display; +} + +void ws3t_display_destroy() { + // TODO: de-init display, its buffer and touch, stop display tasks, stop timer + // TODO: see esp_lvlg_port.c for more info + if (lvgl_mux) { + vSemaphoreDelete(lvgl_mux); + lvgl_mux = NULL; + } +#if LV_ENABLE_GC || !LV_MEM_CUSTOM + lv_deinit(); +#endif +} diff --git a/boards/waveshare_s3_touch/display_defines_i.h b/boards/waveshare_s3_touch/display_defines_i.h new file mode 100644 index 00000000..4a92f447 --- /dev/null +++ b/boards/waveshare_s3_touch/display_defines_i.h @@ -0,0 +1,7 @@ +/** +* The WaveShare S3 Touch uses a panel with the ST7262 display driver. +*/ +#pragma once + +#define WAVESHARE_LCD_HOR_RES 800 +#define WAVESHARE_LCD_VER_RES 480 diff --git a/boards/waveshare_s3_touch/display_i.h b/boards/waveshare_s3_touch/display_i.h new file mode 100644 index 00000000..00762be0 --- /dev/null +++ b/boards/waveshare_s3_touch/display_i.h @@ -0,0 +1,19 @@ +#pragma once + +#include "hal/lv_hal_disp.h" +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +bool ws3t_display_lock(uint32_t timeout_ms); +void ws3t_display_unlock(void); + +lv_disp_t* ws3t_display_create(); +void ws3t_display_destroy(); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/boards/waveshare_s3_touch/lvgl.c b/boards/waveshare_s3_touch/lvgl.c new file mode 100644 index 00000000..9a1b5da9 --- /dev/null +++ b/boards/waveshare_s3_touch/lvgl.c @@ -0,0 +1,18 @@ +#include "lvgl_i.h" + +#include "display_i.h" +#include "touch_i.h" +#include "ui/lvgl_sync.h" + +bool ws3t_init_lvgl() { + tt_lvgl_sync_set(&ws3t_display_lock, &ws3t_display_unlock); + + lv_disp_t* display = ws3t_display_create(); + if (display == NULL) { + return false; + } + + ws3t_touch_init(display); + + return true; +} diff --git a/boards/waveshare_s3_touch/lvgl_i.h b/boards/waveshare_s3_touch/lvgl_i.h new file mode 100644 index 00000000..a505a217 --- /dev/null +++ b/boards/waveshare_s3_touch/lvgl_i.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +bool ws3t_init_lvgl(); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/boards/waveshare_s3_touch/touch.c b/boards/waveshare_s3_touch/touch.c new file mode 100644 index 00000000..f9bdba9b --- /dev/null +++ b/boards/waveshare_s3_touch/touch.c @@ -0,0 +1,90 @@ +#include "display_defines_i.h" + +#include "driver/i2c.h" +#include "esp_err.h" +#include "esp_lcd_touch_gt911.h" +#include "esp_log.h" +#include "lv_api_map.h" + +#define TAG "waveshare_s3_touch_i2c" + +#define WAVESHARE_TOUCH_I2C_PORT 0 +#define WAVESHARE_I2C_MASTER_TX_BUF_DISABLE 0 +#define WAVESHARE_I2C_MASTER_RX_BUF_DISABLE 0 + +static esp_err_t i2c_master_init(void) { + const i2c_config_t i2c_conf = { + .mode = I2C_MODE_MASTER, + .sda_io_num = GPIO_NUM_8, + .sda_pullup_en = GPIO_PULLUP_DISABLE, + .scl_io_num = GPIO_NUM_9, + .scl_pullup_en = GPIO_PULLUP_DISABLE, + .master.clk_speed = 400000 + }; + + i2c_param_config(WAVESHARE_TOUCH_I2C_PORT, &i2c_conf); + + return i2c_driver_install(WAVESHARE_TOUCH_I2C_PORT, i2c_conf.mode, WAVESHARE_I2C_MASTER_RX_BUF_DISABLE, WAVESHARE_I2C_MASTER_TX_BUF_DISABLE, 0); +} + + +static esp_lcd_touch_handle_t touch_init_internal() { + ESP_ERROR_CHECK(i2c_master_init()); + ESP_LOGI(TAG, "I2C initialized successfully"); + + static esp_lcd_panel_io_handle_t tp_io_handle = NULL; + static esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_GT911_CONFIG(); + ESP_LOGI(TAG, "Initialize touch IO (I2C)"); + /* Touch IO handle */ + ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c((esp_lcd_i2c_bus_handle_t)WAVESHARE_TOUCH_I2C_PORT, &tp_io_config, &tp_io_handle)); + esp_lcd_touch_config_t tp_cfg = { + .x_max = WAVESHARE_LCD_VER_RES, + .y_max = WAVESHARE_LCD_HOR_RES, + .rst_gpio_num = -1, + .int_gpio_num = -1, + .flags = { + .swap_xy = 0, + .mirror_x = 0, + .mirror_y = 0, + }, + }; + /* Initialize touch */ + ESP_LOGI(TAG, "Initialize touch controller GT911"); + esp_lcd_touch_handle_t tp = NULL; + ESP_ERROR_CHECK(esp_lcd_touch_new_i2c_gt911(tp_io_handle, &tp_cfg, &tp)); + + return tp; +} + +static void touch_callback(lv_indev_drv_t* drv, lv_indev_data_t* data) { + uint16_t touchpad_x[1] = {0}; + uint16_t touchpad_y[1] = {0}; + uint8_t touchpad_cnt = 0; + + /* Read touch controller data */ + esp_lcd_touch_read_data(drv->user_data); + + /* Get coordinates */ + bool touchpad_pressed = esp_lcd_touch_get_coordinates(drv->user_data, touchpad_x, touchpad_y, NULL, &touchpad_cnt, 1); + + if (touchpad_pressed && touchpad_cnt > 0) { + data->point.x = touchpad_x[0]; + data->point.y = touchpad_y[0]; + data->state = LV_INDEV_STATE_PR; + } else { + data->state = LV_INDEV_STATE_REL; + } +} + +void ws3t_touch_init(lv_disp_t* display) { + esp_lcd_touch_handle_t touch_handle = touch_init_internal(); + + ESP_LOGI(TAG, "Register display indev to LVGL"); + static lv_indev_drv_t indev_drv; + lv_indev_drv_init(&indev_drv); + indev_drv.type = LV_INDEV_TYPE_POINTER; + indev_drv.disp = display; + indev_drv.read_cb = &touch_callback; + indev_drv.user_data = touch_handle; + lv_indev_drv_register(&indev_drv); // TODO: store result for deinit purposes +} diff --git a/boards/waveshare_s3_touch/touch_i.h b/boards/waveshare_s3_touch/touch_i.h new file mode 100644 index 00000000..ad4c6f8f --- /dev/null +++ b/boards/waveshare_s3_touch/touch_i.h @@ -0,0 +1,13 @@ +#pragma once + +#include "hal/lv_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void ws3t_touch_init(lv_disp_t* display); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/boards/waveshare_s3_touch/waveshare_s3_touch.c b/boards/waveshare_s3_touch/waveshare_s3_touch.c new file mode 100644 index 00000000..c75a65e8 --- /dev/null +++ b/boards/waveshare_s3_touch/waveshare_s3_touch.c @@ -0,0 +1,10 @@ +#include "waveshare_s3_touch.h" + +#include "lvgl_i.h" + +bool ws3t_bootstrap(); + +const HardwareConfig waveshare_s3_touch = { + .bootstrap = &ws3t_bootstrap, + .init_lvgl = &ws3t_init_lvgl +}; diff --git a/boards/waveshare_s3_touch/waveshare_s3_touch.h b/boards/waveshare_s3_touch/waveshare_s3_touch.h new file mode 100644 index 00000000..7dbddd67 --- /dev/null +++ b/boards/waveshare_s3_touch/waveshare_s3_touch.h @@ -0,0 +1,14 @@ +#pragma once + +#include "hardware_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Waveshare S3 Touch LCD 4.3 +extern const HardwareConfig waveshare_s3_touch; + +#ifdef __cplusplus +} +#endif diff --git a/boards/yellow_board/CMakeLists.txt b/boards/yellow_board/CMakeLists.txt index 2ad6b61e..2f04cad1 100644 --- a/boards/yellow_board/CMakeLists.txt +++ b/boards/yellow_board/CMakeLists.txt @@ -1,6 +1,7 @@ idf_component_register( SRC_DIRS "." INCLUDE_DIRS "." - REQUIRES tactility-esp esp_lcd_touch_cst816s esp_lcd_ili9341 + REQUIRES esp_lvgl_port esp_lcd_touch_cst816s esp_lcd_ili9341 ) +target_link_libraries(${COMPONENT_LIB} ${IDF_TARGET_NAME} tactility) \ No newline at end of file diff --git a/boards/yellow_board/display.c b/boards/yellow_board/display.c index 42c2ba43..09f269f8 100644 --- a/boards/yellow_board/display.c +++ b/boards/yellow_board/display.c @@ -4,14 +4,12 @@ #include "esp_lcd_ili9341.h" #include "esp_lcd_panel_ops.h" #include "esp_log.h" -#include "freertos/FreeRTOS.h" -#include "freertos/semphr.h" -#include "tactility-esp.h" +#include "esp_lvgl_port.h" +#include "hal/lv_hal_disp.h" +#include #define TAG "2432s024_ili9341" -static SemaphoreHandle_t refresh_finish = NULL; - #define LCD_SPI_HOST SPI2_HOST #define LCD_PIN_SCLK GPIO_NUM_14 #define LCD_PIN_MOSI GPIO_NUM_13 @@ -24,7 +22,7 @@ static SemaphoreHandle_t refresh_finish = NULL; #define LCD_BITS_PER_PIXEL 16 #define LCD_DRAW_BUFFER_HEIGHT (LCD_VERTICAL_RESOLUTION / 10) -static bool create_display_device(DisplayDevice* display) { +lv_disp_t* yellow_board_init_display() { ESP_LOGI(TAG, "creating display"); gpio_config_t io_conf = { @@ -55,7 +53,8 @@ static bool create_display_device(DisplayDevice* display) { NULL ); - if (esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)LCD_SPI_HOST, &panel_io_config, &display->io_handle) != ESP_OK) { + esp_lcd_panel_io_handle_t io_handle; + if (esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)LCD_SPI_HOST, &panel_io_config, &io_handle) != ESP_OK) { ESP_LOGD(TAG, "failed to create panel"); return false; } @@ -67,36 +66,28 @@ static bool create_display_device(DisplayDevice* display) { .bits_per_pixel = LCD_BITS_PER_PIXEL, }; - if (esp_lcd_new_panel_ili9341(display->io_handle, &panel_config, &display->display_handle) != ESP_OK) { + esp_lcd_panel_handle_t panel_handle; + if (esp_lcd_new_panel_ili9341(io_handle, &panel_config, &panel_handle) != ESP_OK) { ESP_LOGD(TAG, "failed to create ili9341"); return false; } - - if (esp_lcd_panel_reset(display->display_handle) != ESP_OK) { + if (esp_lcd_panel_reset(panel_handle) != ESP_OK) { ESP_LOGD(TAG, "failed to reset panel"); return false; } - if (esp_lcd_panel_init(display->display_handle) != ESP_OK) { + if (esp_lcd_panel_init(panel_handle) != ESP_OK) { ESP_LOGD(TAG, "failed to init panel"); return false; } - if (esp_lcd_panel_mirror(display->display_handle, true, false) != ESP_OK) { + if (esp_lcd_panel_mirror(panel_handle, true, false) != ESP_OK) { ESP_LOGD(TAG, "failed to set panel to mirror"); - display->mirror_x = true; - display->mirror_y = false; return false; } - if (esp_lcd_panel_swap_xy(display->display_handle, false) != ESP_OK) { - ESP_LOGD(TAG, "failed to set panel xy swap"); - display->swap_xy = false; - return false; - } - - if (esp_lcd_panel_disp_on_off(display->display_handle, true) != ESP_OK) { + if (esp_lcd_panel_disp_on_off(panel_handle, true) != ESP_OK) { ESP_LOGD(TAG, "failed to turn display on"); return false; } @@ -106,19 +97,23 @@ static bool create_display_device(DisplayDevice* display) { return false; } - display->horizontal_resolution = LCD_HORIZONTAL_RESOLUTION; - display->vertical_resolution = LCD_VERTICAL_RESOLUTION; - display->draw_buffer_height = LCD_DRAW_BUFFER_HEIGHT; - display->bits_per_pixel = LCD_BITS_PER_PIXEL; - display->monochrome = false; - display->double_buffering = true; - - return true; -} - -DisplayDriver board_2432s024_create_display_driver() { - return (DisplayDriver) { - .name = "ili9341_2432s024", - .create_display_device = &create_display_device + const lvgl_port_display_cfg_t disp_cfg = { + .io_handle = io_handle, + .panel_handle = panel_handle, + .buffer_size = LCD_HORIZONTAL_RESOLUTION * LCD_DRAW_BUFFER_HEIGHT * (LCD_BITS_PER_PIXEL / 8), + .double_buffer = false, + .hres = LCD_HORIZONTAL_RESOLUTION, + .vres = LCD_VERTICAL_RESOLUTION, + .monochrome = false, + .rotation = { + .swap_xy = false, + .mirror_x = true, + .mirror_y = false, + }, + .flags = { + .buff_dma = true, + } }; + + return lvgl_port_add_disp(&disp_cfg); } diff --git a/boards/yellow_board/lvgl.c b/boards/yellow_board/lvgl.c new file mode 100644 index 00000000..3c8ade16 --- /dev/null +++ b/boards/yellow_board/lvgl.c @@ -0,0 +1,57 @@ +#include "esp_lvgl_port.h" +#include "log.h" +#include "ui/lvgl_sync.h" +#include + +#define TAG "yellow_board_lvgl" + +lv_disp_t* yellow_board_init_display(); +bool yellow_board_init_touch(esp_lcd_panel_io_handle_t* io_handle, esp_lcd_touch_handle_t* touch_handle); + +bool yellow_board_init_lvgl() { + static lv_disp_t* display = NULL; + static esp_lcd_panel_io_handle_t touch_io_handle; + static esp_lcd_touch_handle_t touch_handle; + + const lvgl_port_cfg_t lvgl_cfg = { + .task_priority = ThreadPriorityHigh, + .task_stack = 8096, + .task_affinity = -1, // core pinning + .task_max_sleep_ms = 500, + .timer_period_ms = 5 + }; + + if (lvgl_port_init(&lvgl_cfg) != ESP_OK) { + TT_LOG_E(TAG, "lvgl port init failed"); + return false; + } + + // Add display + display = yellow_board_init_display(); + if (display == NULL) { + TT_LOG_E(TAG, "failed to add display"); + return false; + } + + + // Add touch + if (!yellow_board_init_touch(&touch_io_handle, &touch_handle)) { + return false; + } + + const lvgl_port_touch_cfg_t touch_cfg = { + .disp = display, + .handle = touch_handle, + }; + + lv_indev_t _Nullable* touch_indev = lvgl_port_add_touch(&touch_cfg); + if (touch_indev == NULL) { + TT_LOG_E(TAG, "failed to add touch to lvgl"); + return false; + } + + // Set syncing functions + tt_lvgl_sync_set(&lvgl_port_lock, &lvgl_port_unlock); + + return true; +} diff --git a/boards/yellow_board/touch.c b/boards/yellow_board/touch.c index be8a9b2f..6866bad7 100644 --- a/boards/yellow_board/touch.c +++ b/boards/yellow_board/touch.c @@ -2,13 +2,12 @@ #include "esp_err.h" #include "esp_lcd_touch_cst816s.h" #include "esp_log.h" -#include "tactility-esp.h" #define TOUCH_I2C_PORT 0 #define TAG "2432s024_cst816" -static bool create_touch_device(esp_lcd_panel_io_handle_t* io_handle, esp_lcd_touch_handle_t* touch_handle) { +bool yellow_board_init_touch(esp_lcd_panel_io_handle_t* io_handle, esp_lcd_touch_handle_t* touch_handle) { ESP_LOGI(TAG, "creating touch"); const i2c_config_t i2c_conf = { @@ -64,10 +63,3 @@ static bool create_touch_device(esp_lcd_panel_io_handle_t* io_handle, esp_lcd_to return true; } - -TouchDriver board_2432s024_create_touch_driver() { - return (TouchDriver) { - .name = "cst816s_2432s024", - .create_touch_device = &create_touch_device - }; -} diff --git a/boards/yellow_board/yellow_board.c b/boards/yellow_board/yellow_board.c index 82d74b5f..1208eec4 100644 --- a/boards/yellow_board/yellow_board.c +++ b/boards/yellow_board/yellow_board.c @@ -1,7 +1,8 @@ #include "yellow_board.h" +bool yellow_board_init_lvgl(); + const HardwareConfig yellow_board_24inch_cap = { .bootstrap = NULL, - .display_driver = &board_2432s024_create_display_driver, - .touch_driver = &board_2432s024_create_touch_driver + .init_lvgl = &yellow_board_init_lvgl }; diff --git a/boards/yellow_board/yellow_board.h b/boards/yellow_board/yellow_board.h index a5f0931d..88eb813d 100644 --- a/boards/yellow_board/yellow_board.h +++ b/boards/yellow_board/yellow_board.h @@ -1,15 +1,11 @@ #pragma once -#include "tactility-esp.h" +#include "hardware_config.h" #ifdef __cplusplus extern "C" { #endif -// Available for HardwareConfig customizations -DisplayDriver board_2432s024_create_display_driver(); -TouchDriver board_2432s024_create_touch_driver(); - // Capacitive touch version of the 2.4" yellow board extern const HardwareConfig yellow_board_24inch_cap; diff --git a/docs/ideas.md b/docs/ideas.md index 83b53eaa..210d8fed 100644 --- a/docs/ideas.md +++ b/docs/ideas.md @@ -3,8 +3,10 @@ - Update `view_port` to use `ViewPort` as handle externally and `ViewPortData` internally - Replace FreeRTOS semaphore from `Loader` with internal `Mutex` - Create unit tests for `tactility-core` and `tactility` (PC-only for now) +- Have a way to deinit LVGL drivers that are created from `HardwareConfig` # Core Ideas +- Make a HAL? It would mainly be there to support PC development. It's a lot of effort for supporting what's effectively a dev-only feature. - Support for displays with different DPI. Consider the layer-based system like on Android. # App Ideas diff --git a/sdkconfig.board.waveshare_s3_touch b/sdkconfig.board.waveshare_s3_touch new file mode 100644 index 00000000..5134c4b3 --- /dev/null +++ b/sdkconfig.board.waveshare_s3_touch @@ -0,0 +1,31 @@ +# Software defaults +CONFIG_LV_FONT_MONTSERRAT_14=y +CONFIG_LV_FONT_MONTSERRAT_18=y +CONFIG_LV_USE_USER_DATA=y +CONFIG_LV_USE_FS_STDIO=y +CONFIG_LV_FS_STDIO_LETTER=65 +CONFIG_LV_FS_STDIO_PATH="" +CONFIG_LV_FS_STDIO_CACHE_SIZE=4096 +CONFIG_LV_USE_PNG=y +CONFIG_FREERTOS_HZ=1000 +CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2 +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" + +# Hardware: Main +CONFIG_TT_BOARD_WAVESHARE_S3_TOUCH=y +CONFIG_IDF_TARGET="esp32s3" +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y +CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y +CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y +CONFIG_FLASHMODE_QIO=y +# Hardware: SPI RAM +CONFIG_ESP32S3_SPIRAM_SUPPORT=y +CONFIG_SPIRAM_MODE_OCT=y +CONFIG_SPIRAM_SPEED_80M=y +# LVGL +CONFIG_LV_COLOR_16_SWAP=n +CONFIG_LV_DISP_DEF_REFR_PERIOD=17 +CONFIG_LV_INDEV_DEF_READ_PERIOD=17 +CONFIG_LV_DPI_DEF=139 diff --git a/tactility-core/CMakeLists.txt b/tactility-core/CMakeLists.txt index 54877d92..8ad56557 100644 --- a/tactility-core/CMakeLists.txt +++ b/tactility-core/CMakeLists.txt @@ -1,4 +1,5 @@ cmake_minimum_required(VERSION 3.16) + set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) @@ -16,7 +17,7 @@ target_include_directories(tactility-core SYSTEM INTERFACE src/ ) -if (ESP_PLATFORM) +if (DEFINED ENV{ESP_IDF_VERSION}) add_definitions(-DESP_PLATFORM) target_link_libraries(tactility-core PUBLIC mlib diff --git a/tactility-esp/CMakeLists.txt b/tactility-esp/CMakeLists.txt index 7e610884..ce4e778b 100644 --- a/tactility-esp/CMakeLists.txt +++ b/tactility-esp/CMakeLists.txt @@ -8,7 +8,7 @@ idf_component_register( "src/apps/system/wifi_manage" "src/services/wifi" INCLUDE_DIRS "src/" - REQUIRES esp_wifi esp_lvgl_port nvs_flash esp_lcd esp_lcd_touch spiffs + REQUIRES esp_wifi nvs_flash spiffs ) set(ASSETS_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/assets") diff --git a/tactility-esp/src/apps/system/wifi_connect/wifi_connect.c b/tactility-esp/src/apps/system/wifi_connect/wifi_connect.c index 184a0039..4fc56e22 100644 --- a/tactility-esp/src/apps/system/wifi_connect/wifi_connect.c +++ b/tactility-esp/src/apps/system/wifi_connect/wifi_connect.c @@ -1,7 +1,6 @@ #include "wifi_connect.h" #include "app.h" -#include "esp_lvgl_port.h" #include "services/wifi/wifi.h" #include "tactility_core.h" #include "ui/lvgl_sync.h" diff --git a/tactility-esp/src/apps/system/wifi_manage/wifi_manage.c b/tactility-esp/src/apps/system/wifi_manage/wifi_manage.c index deffddb6..bafba89a 100644 --- a/tactility-esp/src/apps/system/wifi_manage/wifi_manage.c +++ b/tactility-esp/src/apps/system/wifi_manage/wifi_manage.c @@ -2,7 +2,6 @@ #include "app.h" #include "apps/system/wifi_connect/wifi_connect_bundle.h" -#include "esp_lvgl_port.h" #include "services/loader/loader.h" #include "tactility_core.h" #include "ui/lvgl_sync.h" diff --git a/tactility-esp/src/display.c b/tactility-esp/src/display.c deleted file mode 100644 index accd40ee..00000000 --- a/tactility-esp/src/display.c +++ /dev/null @@ -1,15 +0,0 @@ -#include "check.h" -#include "display.h" - -DisplayDevice* tt_display_device_alloc(DisplayDriver* driver) { - DisplayDevice* display = malloc(sizeof(DisplayDevice)); - memset(display, 0, sizeof(DisplayDevice)); - tt_check(driver->create_display_device(display), "failed to create display"); - tt_check(display->io_handle != NULL); - tt_check(display->display_handle != NULL); - tt_check(display->horizontal_resolution != 0); - tt_check(display->vertical_resolution != 0); - tt_check(display->draw_buffer_height > 0); - tt_check(display->bits_per_pixel > 0); - return display; -} diff --git a/tactility-esp/src/display.h b/tactility-esp/src/display.h deleted file mode 100644 index 79a2fd52..00000000 --- a/tactility-esp/src/display.h +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include "esp_lcd_panel_io.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - esp_lcd_panel_io_handle_t io_handle; - esp_lcd_panel_handle_t display_handle; - uint16_t horizontal_resolution; - uint16_t vertical_resolution; - uint16_t draw_buffer_height; - uint16_t bits_per_pixel; - bool double_buffering; - bool mirror_x; - bool mirror_y; - bool swap_xy; - bool monochrome; -} DisplayDevice; - -typedef bool (*CreateDisplay)(DisplayDevice* display); - -typedef struct { - char name[32]; - CreateDisplay create_display_device; -} DisplayDriver; - -/** - * @param[in] driver - * @return allocated display object - */ -DisplayDevice* tt_display_device_alloc(DisplayDriver* driver); - -#ifdef __cplusplus -} -#endif diff --git a/tactility-esp/src/graphics.c b/tactility-esp/src/graphics.c deleted file mode 100644 index 363bb3bf..00000000 --- a/tactility-esp/src/graphics.c +++ /dev/null @@ -1,59 +0,0 @@ -#include "check.h" -#include "esp_lvgl_port.h" -#include "graphics_i.h" -#include "lvgl.h" - -#define TAG "lvgl" - -Lvgl tt_graphics_init(Hardware* hardware) { - const lvgl_port_cfg_t lvgl_cfg = { - .task_priority = 4, - .task_stack = 8096, - .task_affinity = -1, // core pinning - .task_max_sleep_ms = 500, - .timer_period_ms = 5 - }; - - tt_check(lvgl_port_init(&lvgl_cfg) == ESP_OK, "lvgl port init failed"); - DisplayDevice* display = hardware->display; - - // Add display - TT_LOG_I(TAG, "lvgl add display"); - const lvgl_port_display_cfg_t disp_cfg = { - .io_handle = display->io_handle, - .panel_handle = display->display_handle, - .buffer_size = display->horizontal_resolution * display->draw_buffer_height * (display->bits_per_pixel / 8), - .double_buffer = display->double_buffering, - .hres = display->horizontal_resolution, - .vres = display->vertical_resolution, - .monochrome = display->monochrome, - .rotation = { - .swap_xy = display->swap_xy, - .mirror_x = display->mirror_x, - .mirror_y = display->mirror_y, - }, - .flags = { - .buff_dma = true, - } - }; - - lv_disp_t* disp = lvgl_port_add_disp(&disp_cfg); - tt_check(disp != NULL, "failed to add display"); - - lv_indev_t _Nullable* touch_indev = NULL; - - // Add touch - if (hardware->touch != NULL) { - const lvgl_port_touch_cfg_t touch_cfg = { - .disp = disp, - .handle = hardware->touch->touch_handle, - }; - touch_indev = lvgl_port_add_touch(&touch_cfg); - tt_check(touch_indev != NULL, "failed to add touch to lvgl"); - } - - return (Lvgl) { - .disp = disp, - .touch_indev = touch_indev - }; -} diff --git a/tactility-esp/src/graphics.h b/tactility-esp/src/graphics.h deleted file mode 100644 index cfca7ab1..00000000 --- a/tactility-esp/src/graphics.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include "lvgl.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - lv_disp_t* disp; - lv_indev_t* _Nullable touch_indev; -} Lvgl; - -#ifdef __cplusplus -} -#endif diff --git a/tactility-esp/src/graphics_i.h b/tactility-esp/src/graphics_i.h deleted file mode 100644 index 19155b7c..00000000 --- a/tactility-esp/src/graphics_i.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "graphics.h" -#include "hardware.h" - -#ifdef __cplusplus -extern "C" { -#endif - -Lvgl tt_graphics_init(Hardware* hardware); - -#ifdef __cplusplus -} -#endif diff --git a/tactility-esp/src/hardware.c b/tactility-esp/src/hardware.c deleted file mode 100644 index 74259da2..00000000 --- a/tactility-esp/src/hardware.c +++ /dev/null @@ -1,32 +0,0 @@ -#include "check.h" -#include "hardware_i.h" -#include "touch.h" - -#define TAG "hardware" - -Hardware tt_hardware_init(const HardwareConfig* config) { - if (config->bootstrap != NULL) { - TT_LOG_I(TAG, "Bootstrapping"); - config->bootstrap(); - } - - tt_check(config->display_driver != NULL, "no display driver configured"); - DisplayDriver display_driver = config->display_driver(); - TT_LOG_I(TAG, "display with driver %s", display_driver.name); - DisplayDevice* display = tt_display_device_alloc(&display_driver); - - TouchDevice* touch = NULL; - if (config->touch_driver != NULL) { - TouchDriver touch_driver = config->touch_driver(); - TT_LOG_I(TAG, "touch with driver %s", touch_driver.name); - touch = tt_touch_alloc(&touch_driver); - } else { - TT_LOG_I(TAG, "no touch configured"); - touch = NULL; - } - - return (Hardware) { - .display = display, - .touch = touch - }; -} diff --git a/tactility-esp/src/hardware.h b/tactility-esp/src/hardware.h deleted file mode 100644 index 3ca3f512..00000000 --- a/tactility-esp/src/hardware.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "display.h" -#include "touch.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - DisplayDevice* display; - TouchDevice* _Nullable touch; -} Hardware; - -#ifdef __cplusplus -} -#endif diff --git a/tactility-esp/src/partitions.h b/tactility-esp/src/partitions.h index 27ab99a2..faeac64a 100644 --- a/tactility-esp/src/partitions.h +++ b/tactility-esp/src/partitions.h @@ -6,4 +6,3 @@ #define MOUNT_POINT_CONFIG "/config" esp_err_t tt_partitions_init(); - diff --git a/tactility-esp/src/tactility-esp.h b/tactility-esp/src/tactility-esp.h deleted file mode 100644 index 1314a116..00000000 --- a/tactility-esp/src/tactility-esp.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include "hardware.h" -#include "tactility.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// Forward declarations -typedef void (*Bootstrap)(); -typedef TouchDriver (*CreateTouchDriver)(); -typedef DisplayDriver (*CreateDisplayDriver)(); - -typedef struct { - // Optional bootstrapping method (e.g. to turn peripherals on) - const Bootstrap _Nullable bootstrap; - // Required driver for display - const CreateDisplayDriver display_driver; - // Optional driver for touch input - const CreateTouchDriver _Nullable touch_driver; -} HardwareConfig; - - -void tt_esp_init(const HardwareConfig* hardware_config); - -#ifdef __cplusplus -} -#endif diff --git a/tactility-esp/src/tactility-esp.c b/tactility-esp/src/tactility_esp.c similarity index 55% rename from tactility-esp/src/tactility-esp.c rename to tactility-esp/src/tactility_esp.c index 1e7cd4a9..94c606b3 100644 --- a/tactility-esp/src/tactility-esp.c +++ b/tactility-esp/src/tactility_esp.c @@ -1,27 +1,13 @@ -#include "tactility.h" +#include "tactility_core.h" #include "esp_event.h" -#include "esp_lvgl_port.h" #include "esp_netif.h" -#include "graphics_i.h" -#include "hardware_i.h" #include "nvs_flash.h" #include "partitions.h" -#include "services/loader/loader.h" #include "services/wifi/wifi_credentials.h" -#include "ui/lvgl_sync.h" #define TAG "tactility" - -static bool lvgl_lock_impl(int timeout_ticks) { - return lvgl_port_lock(timeout_ticks); -} - -static void lvgl_unlock_impl() { - lvgl_port_unlock(); -} - -void tt_esp_init(const HardwareConfig* hardware_config) { +void tt_esp_init() { // Initialize NVS esp_err_t ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { @@ -39,9 +25,4 @@ void tt_esp_init(const HardwareConfig* hardware_config) { tt_partitions_init(); tt_wifi_credentials_init(); - - tt_lvgl_sync_set(&lvgl_lock_impl, &lvgl_unlock_impl); - - Hardware hardware = tt_hardware_init(hardware_config); - /*Lvgl lvgl =*/tt_graphics_init(&hardware); } diff --git a/tactility-esp/src/tactility_esp.h b/tactility-esp/src/tactility_esp.h new file mode 100644 index 00000000..52cbc8a1 --- /dev/null +++ b/tactility-esp/src/tactility_esp.h @@ -0,0 +1,14 @@ +#pragma once + +#include "hardware_config.h" +#include "tactility.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void tt_esp_init(); + +#ifdef __cplusplus +} +#endif diff --git a/tactility-esp/src/touch.c b/tactility-esp/src/touch.c deleted file mode 100644 index 5db3b8b7..00000000 --- a/tactility-esp/src/touch.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "check.h" -#include "touch.h" - -TouchDevice* tt_touch_alloc(TouchDriver* driver) { - TouchDevice* touch = malloc(sizeof(TouchDevice)); - bool success = driver->create_touch_device( - &(touch->io_handle), - &(touch->touch_handle) - ); - tt_check(success, "touch driver failed"); - return touch; -} diff --git a/tactility-esp/src/touch.h b/tactility-esp/src/touch.h deleted file mode 100644 index 3a8ee048..00000000 --- a/tactility-esp/src/touch.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include "esp_lcd_panel_io.h" -#include "esp_lcd_touch.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef bool (*CreateTouch)(esp_lcd_panel_io_handle_t* io_handle, esp_lcd_touch_handle_t* touch_handle); - -typedef struct { - char name[32]; - CreateTouch create_touch_device; -} TouchDriver; - -typedef struct { - esp_lcd_panel_io_handle_t io_handle; - esp_lcd_touch_handle_t touch_handle; -} TouchDevice; - -/** - * @param[in] driver - * @return a newly allocated instance - */ -TouchDevice* tt_touch_alloc(TouchDriver* driver); - -#ifdef __cplusplus -} -#endif diff --git a/tactility/CMakeLists.txt b/tactility/CMakeLists.txt index 294cae1b..e0a43a8e 100644 --- a/tactility/CMakeLists.txt +++ b/tactility/CMakeLists.txt @@ -16,7 +16,7 @@ target_include_directories(tactility INTERFACE src/ ) -if (ESP_PLATFORM) +if (DEFINED ENV{ESP_IDF_VERSION}) add_definitions(-DESP_PLATFORM) target_link_libraries(tactility PUBLIC tactility-core diff --git a/tactility/src/hardware.c b/tactility/src/hardware.c new file mode 100644 index 00000000..25c63d2d --- /dev/null +++ b/tactility/src/hardware.c @@ -0,0 +1,14 @@ +#include "check.h" +#include "hardware_i.h" + +#define TAG "hardware" + +void tt_hardware_init(const HardwareConfig* config) { + if (config->bootstrap != NULL) { + TT_LOG_I(TAG, "Bootstrapping"); + config->bootstrap(); + } + + tt_check(config->init_lvgl); + config->init_lvgl(); +} diff --git a/tactility/src/hardware_config.h b/tactility/src/hardware_config.h new file mode 100644 index 00000000..44d7daab --- /dev/null +++ b/tactility/src/hardware_config.h @@ -0,0 +1,14 @@ +#pragma once + +#include "tactility_core.h" + +// Forward declarations +typedef bool (*Bootstrap)(); +typedef bool (*InitLvgl)(); + +typedef struct { + // Optional bootstrapping method (e.g. to turn peripherals on) + const Bootstrap _Nullable bootstrap; + const InitLvgl init_lvgl; + +} HardwareConfig; diff --git a/tactility-esp/src/hardware_i.h b/tactility/src/hardware_i.h similarity index 50% rename from tactility-esp/src/hardware_i.h rename to tactility/src/hardware_i.h index 34fd33e2..49bda383 100644 --- a/tactility-esp/src/hardware_i.h +++ b/tactility/src/hardware_i.h @@ -1,12 +1,12 @@ #pragma once -#include "tactility-esp.h" +#include "hardware_config.h" #ifdef __cplusplus extern "C" { #endif -Hardware tt_hardware_init(const HardwareConfig* config); +void tt_hardware_init(const HardwareConfig* config); #ifdef __cplusplus } diff --git a/tactility/src/services/gui/gui.c b/tactility/src/services/gui/gui.c index ed481385..47d502fd 100644 --- a/tactility/src/services/gui/gui.c +++ b/tactility/src/services/gui/gui.c @@ -33,7 +33,7 @@ Gui* gui_alloc() { instance->mutex = tt_mutex_alloc(MutexTypeNormal); instance->keyboard = NULL; - tt_check(tt_lvgl_lock(100)); + tt_check(tt_lvgl_lock(1000 / portTICK_PERIOD_MS)); instance->lvgl_parent = lv_scr_act(); tt_lvgl_unlock(); diff --git a/tactility/src/tactility.c b/tactility/src/tactility.c index 605d38e8..48a4e905 100644 --- a/tactility/src/tactility.c +++ b/tactility/src/tactility.c @@ -1,6 +1,7 @@ #include "tactility.h" #include "app_manifest_registry.h" +#include "hardware_i.h" #include "service_registry.h" #include "services/loader/loader.h" @@ -60,10 +61,13 @@ static void register_and_start_user_services(const ServiceManifest* const servic } TT_UNUSED void tt_init(const Config* config) { + TT_LOG_I(TAG, "tt_init started"); + tt_service_registry_init(); tt_app_manifest_registry_init(); - TT_LOG_I(TAG, "tt_init started"); + tt_hardware_init(config->hardware); + // Register all apps register_system_services(); register_system_apps(); diff --git a/tactility/src/tactility.h b/tactility/src/tactility.h index 02337217..efd8c89b 100644 --- a/tactility/src/tactility.h +++ b/tactility/src/tactility.h @@ -1,6 +1,7 @@ #pragma once #include "app_manifest.h" +#include "hardware_config.h" #include "service_manifest.h" #ifdef __cplusplus @@ -11,6 +12,7 @@ extern "C" { #define CONFIG_SERVICES_LIMIT 32 typedef struct { + const HardwareConfig* hardware; // List of user applications const AppManifest* const apps[CONFIG_APPS_LIMIT]; const ServiceManifest* const services[CONFIG_SERVICES_LIMIT]; diff --git a/tactility/src/ui/lvgl_sync.c b/tactility/src/ui/lvgl_sync.c index d3b1ac92..9a87efda 100644 --- a/tactility/src/ui/lvgl_sync.c +++ b/tactility/src/ui/lvgl_sync.c @@ -8,7 +8,7 @@ void tt_lvgl_sync_set(LvglLock lock, LvglUnlock unlock) { unlock_singleton = unlock; } -bool tt_lvgl_lock(int timeout_ticks) { +bool tt_lvgl_lock(uint32_t timeout_ticks) { if (lock_singleton) { return lock_singleton(timeout_ticks); } else { diff --git a/tactility/src/ui/lvgl_sync.h b/tactility/src/ui/lvgl_sync.h index 88571fed..47a4c409 100644 --- a/tactility/src/ui/lvgl_sync.h +++ b/tactility/src/ui/lvgl_sync.h @@ -1,17 +1,18 @@ #pragma once -#include "lvgl.h" +#include #include +#include #ifdef __cplusplus extern "C" { #endif -typedef bool (*LvglLock)(int timeout_ticks); +typedef bool (*LvglLock)(uint32_t timeout_ticks); typedef void (*LvglUnlock)(); void tt_lvgl_sync_set(LvglLock lock, LvglUnlock unlock); -bool tt_lvgl_lock(int timeout_ticks); +bool tt_lvgl_lock(uint32_t timeout_ticks); void tt_lvgl_unlock(); #ifdef __cplusplus