Files
tactility/Modules/lvgl-module/source/lvgl_devices.c
T
Ken Van Hoeylandt f9453d8956 Migrate devices, create drivers, other improvements & fixes (#574)
Migrated devices to kernel drivers:

- guition-jc3248w535c
- m5stack-core2
- m5stack-cores3
- m5stack-papers3

New drivers:

- axp192-module
- axp2101-module

Fixes:

- Fix SD card LDO for P4 devices
- Updated PowerOff app to work with kernel displays
- Fix for `lvgl_try_lock()` timing
- Fix for touch events with slow updating displays

Improvements:

- `GuiService` now keeps trying to lock to prevent silent failures caused by drivers.
- `GuiService` now uses lvgl-module calls for locking/unlocking
- display driver now has capability `DISPLAY_CAPABILITY_SLOW_REFRESH`
2026-07-19 00:39:26 +02:00

111 lines
4.4 KiB
C

#include <tactility/device.h>
#include <tactility/drivers/display.h>
#include <tactility/drivers/keyboard.h>
#include <tactility/drivers/pointer.h>
#include <tactility/log.h>
#include <tactility/lvgl_display.h>
#include <tactility/lvgl_keyboard.h>
#include <tactility/lvgl_module.h>
#include <tactility/lvgl_pointer.h>
#include <lvgl.h>
#define TAG "lvgl"
void lvgl_devices_attach() {
lvgl_lock();
lv_disp_t* lvgl_display = NULL;
bool display_updates_slowly = false;
struct Device* kernel_display_device = NULL;
device_get_first_by_type(&DISPLAY_TYPE, &kernel_display_device);
// Placeholder drivers (boards not yet migrated to the kernel display driver) register with a
// NULL api: they exist so the devicetree node resolves, but have nothing for LVGL to bind to.
if (kernel_display_device != NULL && device_get_driver(kernel_display_device)->api == NULL) {
device_put(kernel_display_device);
kernel_display_device = NULL;
}
if (kernel_display_device != NULL) {
uint16_t vres = display_get_resolution_y(kernel_display_device);
enum DisplayColorFormat color_format = display_get_color_format(kernel_display_device);
bool swap_bytes = color_format == DISPLAY_COLOR_FORMAT_RGB565_SWAPPED ||
color_format == DISPLAY_COLOR_FORMAT_BGR565_SWAPPED ||
color_format == DISPLAY_COLOR_FORMAT_BGR565;
bool display_requires_full_frame = display_has_capability(kernel_display_device, DISPLAY_CAPABILITY_REQUIRES_FULL_FRAME);
display_updates_slowly = display_has_capability(kernel_display_device, DISPLAY_CAPABILITY_SLOW_REFRESH);
struct LvglDisplayConfig lvgl_display_config = {
.buffer_height = vres > 10 ? vres / 10 : vres,
.swap_bytes = swap_bytes,
.force_full_frame = display_requires_full_frame
};
if (lvgl_display_add(kernel_display_device, &lvgl_display_config, &lvgl_display) == ERROR_NONE) {
LOG_I(TAG, "Bound %s to LVGL", kernel_display_device->name);
} else {
LOG_E(TAG, "Failed to bind %s to LVGL", kernel_display_device->name);
}
device_put(kernel_display_device);
}
struct Device* kernel_pointer_device = NULL;
device_get_first_by_type(&POINTER_TYPE, &kernel_pointer_device);
if (kernel_pointer_device != NULL && device_get_driver(kernel_pointer_device)->api == NULL) {
device_put(kernel_pointer_device);
kernel_pointer_device = NULL;
}
if (kernel_pointer_device != NULL) {
lv_indev_t* lvgl_pointer_device;
if (lvgl_pointer_add(kernel_pointer_device, lvgl_display, &lvgl_pointer_device) == ERROR_NONE) {
LOG_I(TAG, "Bound %s to LVGL", kernel_pointer_device->name);
// Slow panels cause taps to be missed due to the long update time, prevent that
if (display_updates_slowly ) {
lv_indev_set_long_press_time(lvgl_pointer_device, 2000);
}
} else {
LOG_E(TAG, "Failed to bind %s to LVG", kernel_pointer_device->name);
}
device_put(kernel_pointer_device);
}
struct Device* kernel_keyboard_device = NULL;
device_get_first_by_type(&KEYBOARD_TYPE, &kernel_keyboard_device);
lv_indev_t* lvgl_keyboard_device;
if (kernel_keyboard_device != NULL) {
if (lvgl_keyboard_add(kernel_keyboard_device, lvgl_display, &lvgl_keyboard_device) == ERROR_NONE) {
LOG_I(TAG, "Bound %s to LVGL", kernel_keyboard_device->name);
} else {
LOG_E(TAG, "Failed to bind %s to LVGL", kernel_keyboard_device->name);
}
device_put(kernel_keyboard_device);
}
lvgl_unlock();
}
void lvgl_devices_detach() {
lvgl_lock();
lv_indev_t* device = lv_indev_get_next(NULL);
while (device != NULL) {
lv_indev_type_t type = lv_indev_get_type(device);
if (type == LV_INDEV_TYPE_POINTER) {
lvgl_pointer_remove(device);
} else if (type == LV_INDEV_TYPE_KEYPAD) {
lvgl_keyboard_remove(device);
} else {
lv_indev_delete(device);
}
// Always get the first item, because getting the next one doesn't work as the current pointer just became corrupt
device = lv_indev_get_next(NULL);
}
lv_disp_t* display = lv_disp_get_next(NULL);
while (display != NULL) {
lv_display_delete(display);
display = lv_disp_get_next(NULL);
}
lvgl_lock();
}