diff --git a/README.md b/README.md index fa71d41c..6ff60638 100644 --- a/README.md +++ b/README.md @@ -7,33 +7,53 @@ It provides an application framework that is based on code from the [Flipper Zer ![Tactility shown on a Lilygo T-Deck device and on PC](docs/pics/tactility-showcase.jpg) -Tactility features: -- A hardware abstraction layer -- UI capabilities (via LVGL) -- An application platform that can run apps and services -- PC app support to speed up development for ESP32 apps +Noteworthy features: +- Touch UI capabilities (via LVGL) with support for input devices such as on-device trackball or keyboard. +- An application platform that can run apps and services. +- Basic applications to boost productivity, such as a Wi-Fi connectivity app. +- Run Tactility apps on PC to speed up development. Requirements: - 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 +## Making apps is easy! -UI is created with [lvgl](https://github.com/lvgl/lvgl). -Any LVGL-capable device is supported. +Apps are described in "manifest". The manifest provides some basic information on +the app name and icon, but also tells Tactility what needs to happen when the app runs. -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) +UI is created with [lvgl](https://github.com/lvgl/lvgl) which has lots of [widgets](https://docs.lvgl.io/8.3/widgets/index.html)! +Creating a touch-capable UI is [easy](https://docs.lvgl.io/8.3/get-started/quick-overview.html) and doesn't require your own render loop! + +```c +static void app_show(TT_UNUSED App app, lv_obj_t* parent) { + lv_obj_t* label = lv_label_create(parent); + lv_label_set_text(label, "Hello, world!"); + lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); + // Widgets are auto-removed from the parent when the app is closed +} + +const AppManifest hello_world_app = { + .id = "helloworld", + .name = "Hello World", + .icon = NULL, + .type = AppTypeUser, + .on_start = NULL, + .on_stop = NULL, + .on_show = &app_show, + .on_hide = NULL +}; +``` + +This shows as follows: + +![hello world app](docs/pics/hello-world.png) ## Supported Hardware -### Devices - -Most hardware configurations should work, but it might require you to set up the drivers yourself. +Any ESP32 device with a touch screen should be able to run Tactility, +because LVGL is set up in a platform-agnostic manner. +Implementing drivers can take some effort, so Tactility provides support for several devices. Predefined configurations are available for: @@ -74,6 +94,8 @@ The build scripts will detect if ESP-IDF is available. They will adapter if you ### Development +Take a look at the [App Lifecycle](docs/app-lifecycle.md). + Directories explained: - `app-esp`: The ESP32 application example diff --git a/app-esp/src/hello_world/hello_world.c b/app-esp/src/hello_world/hello_world.c index ef805f10..3d80faa0 100644 --- a/app-esp/src/hello_world/hello_world.c +++ b/app-esp/src/hello_world/hello_world.c @@ -3,9 +3,6 @@ static void app_show(TT_UNUSED App app, lv_obj_t* parent) { lv_obj_t* label = lv_label_create(parent); - lv_label_set_recolor(label, true); - lv_obj_set_width(label, 200); - lv_obj_set_style_text_align(label, LV_TEXT_ALIGN_CENTER, 0); lv_label_set_text(label, "Hello, world!"); lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); } @@ -17,5 +14,6 @@ const AppManifest hello_world_app = { .type = AppTypeUser, .on_start = NULL, .on_stop = NULL, - .on_show = &app_show + .on_show = &app_show, + .on_hide = NULL }; diff --git a/app-sim/src/hello_world/hello_world.c b/app-sim/src/hello_world/hello_world.c index bb101e77..bfdb03a9 100644 --- a/app-sim/src/hello_world/hello_world.c +++ b/app-sim/src/hello_world/hello_world.c @@ -4,9 +4,6 @@ static void app_show(TT_UNUSED App app, lv_obj_t* parent) { lv_obj_t* label = lv_label_create(parent); - lv_label_set_recolor(label, true); - lv_obj_set_width(label, 200); - lv_obj_set_style_text_align(label, LV_TEXT_ALIGN_CENTER, 0); lv_label_set_text(label, "Hello, world!"); lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); } @@ -18,5 +15,6 @@ const AppManifest hello_world_app = { .type = AppTypeUser, .on_start = NULL, .on_stop = NULL, - .on_show = &app_show + .on_show = &app_show, + .on_hide = NULL }; diff --git a/docs/app-lifecycle.md b/docs/app-lifecycle.md new file mode 100644 index 00000000..6ad68830 --- /dev/null +++ b/docs/app-lifecycle.md @@ -0,0 +1,12 @@ +# Application Lifecycle + +The app goes through these states: + +![app lifecycle state diagram](pics/app-lifecycle.png) + +Let's look at a scenario where an app launches another app: + +1. `first` app starts: `first.on_create()` -> `first.on_show()` +2. `second` app starts: `first.on_hide()` -> `second.on_create()` -> `second.on_show()` +3. `second` app stops: `second.on_hide()` -> `second.on_destroy()` -> `first.on_show()` +4. `first` app stops: `first.on_hide()` -> `first.on_destroy()` diff --git a/docs/app-lifecycle.puml b/docs/app-lifecycle.puml new file mode 100644 index 00000000..2ed42a27 --- /dev/null +++ b/docs/app-lifecycle.puml @@ -0,0 +1,9 @@ +@startuml +[*] --> on_create : app is started +on_create --> on_show : app becomes visible +on_show --> on_hide : app is no longer visible +on_hide --> on_destroy : app is being closed +on_destroy --> [*] +skinparam ranksep 25 +skinparam padding 2 +@enduml \ No newline at end of file diff --git a/docs/pics/app-lifecycle.png b/docs/pics/app-lifecycle.png new file mode 100644 index 00000000..9b5edf02 Binary files /dev/null and b/docs/pics/app-lifecycle.png differ diff --git a/docs/pics/hello-world.png b/docs/pics/hello-world.png new file mode 100644 index 00000000..21f6ab00 Binary files /dev/null and b/docs/pics/hello-world.png differ