diff --git a/pkg/lvgl/Makefile.dep b/pkg/lvgl/Makefile.dep index 57c09af27b..ef93f432d4 100644 --- a/pkg/lvgl/Makefile.dep +++ b/pkg/lvgl/Makefile.dep @@ -12,6 +12,10 @@ ifneq (,$(filter lvgl_contrib,$(USEMODULE))) USEMODULE += xtimer endif +ifneq (,$(filter lvgl_contrib_touch,$(USEMODULE))) + USEMODULE += touch_dev +endif + # lvgl is not compatible with non 32bit platforms # Building lv_misc triggers the error: # "left shift count >= width of type [-Werror=shift-count-overflow]" diff --git a/pkg/lvgl/Makefile.include b/pkg/lvgl/Makefile.include index de90f66a1f..a1ca9d971d 100644 --- a/pkg/lvgl/Makefile.include +++ b/pkg/lvgl/Makefile.include @@ -31,3 +31,6 @@ CFLAGS += -DLVGL_TASK_THREAD_PRIO=$(LVGL_TASK_THREAD_PRIO) # lvgl module is not a concrete module, so declare it as a pseudomodule PSEUDOMODULES += lvgl + +# touch capabilities are available via a pseudomodule +PSEUDOMODULES += lvgl_contrib_touch diff --git a/pkg/lvgl/contrib/lvgl.c b/pkg/lvgl/contrib/lvgl.c index cf0a3b130c..6f1f8eb0e3 100644 --- a/pkg/lvgl/contrib/lvgl.c +++ b/pkg/lvgl/contrib/lvgl.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 Inria + * Copyright (C) 2019-2020 Inria * * This file is subject to the terms and conditions of the GNU Lesser * General Public License v2.1. See the file LICENSE in the top level @@ -17,6 +17,8 @@ * @} */ +#include + #include "thread.h" #include "xtimer.h" @@ -25,7 +27,8 @@ #include "lvgl/lvgl.h" #include "lv_conf.h" #include "lvgl_riot.h" -#include "disp_dev.h" + +#include "screen_dev.h" #ifndef LVGL_TASK_THREAD_PRIO #define LVGL_TASK_THREAD_PRIO (THREAD_PRIORITY_MAIN + 1) @@ -52,7 +55,9 @@ static kernel_pid_t _task_thread_pid; static lv_disp_buf_t disp_buf; static lv_color_t buf[LVGL_COLOR_BUF_SIZE]; -static disp_dev_t *_dev = NULL; + +static screen_dev_t *_screen_dev = NULL; + static void *_task_thread(void *arg) { @@ -80,11 +85,11 @@ static void *_task_thread(void *arg) static void _disp_map(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_p) { - if (!_dev) { + if (!_screen_dev->display) { return; } - disp_dev_map(_dev, area->x1, area->x2, area->y1, area->y2, + disp_dev_map(_screen_dev->display, area->x1, area->x2, area->y1, area->y2, (const uint16_t *)color_p); LOG_DEBUG("[lvgl] flush display\n"); @@ -92,22 +97,63 @@ static void _disp_map(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *col lv_disp_flush_ready(drv); } -void lvgl_init(disp_dev_t *dev) +#ifdef MODULE_TOUCH_DEV +/* adapted from https://github.com/lvgl/lvgl/tree/v6.1.2#add-littlevgl-to-your-project */ +static bool _touch_read(lv_indev_drv_t *indev_driver, lv_indev_data_t *data) +{ + if (!_screen_dev->touch) { + return false; + } + + (void)indev_driver; + static lv_coord_t last_x = 0; + static lv_coord_t last_y = 0; + + touch_t positions[1]; + uint8_t touches = touch_dev_touches(_screen_dev->touch, positions, 1); + + /* Save the state and save the pressed coordinates */ + data->state = (touches > 0) ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL; + if (data->state == LV_INDEV_STATE_PR) { + last_x = positions[0].x; + last_y = positions[0].y; + } + + /* Set the coordinates (if released use the last pressed coordinates) */ + data->point.x = last_x; + data->point.y = last_y; + + return false; +} +#endif + +void lvgl_init(screen_dev_t *screen_dev) { - _dev = dev; lv_init(); + _screen_dev = screen_dev; + assert(screen_dev->display); + lv_disp_drv_t disp_drv; lv_disp_drv_init(&disp_drv); /* Configure horizontal and vertical resolutions based on the underlying display device parameters */ - disp_drv.hor_res = disp_dev_width(dev); - disp_drv.ver_res = disp_dev_height(dev); + disp_drv.hor_res = disp_dev_width(screen_dev->display); + disp_drv.ver_res = disp_dev_height(screen_dev->display); disp_drv.flush_cb = _disp_map; disp_drv.buffer = &disp_buf; lv_disp_drv_register(&disp_drv); lv_disp_buf_init(&disp_buf, buf, NULL, LVGL_COLOR_BUF_SIZE); +#ifdef MODULE_TOUCH_DEV + assert(screen_dev->touch); + lv_indev_drv_t indev_drv; + lv_indev_drv_init(&indev_drv); + indev_drv.type = LV_INDEV_TYPE_POINTER; + indev_drv.read_cb = _touch_read; + lv_indev_drv_register(&indev_drv); +#endif + lv_task_handler(); _task_thread_pid = thread_create(_task_thread_stack, sizeof(_task_thread_stack), LVGL_TASK_THREAD_PRIO, THREAD_CREATE_STACKTEST, diff --git a/pkg/lvgl/include/lvgl_riot.h b/pkg/lvgl/include/lvgl_riot.h index 631156ae19..c65a7116ee 100644 --- a/pkg/lvgl/include/lvgl_riot.h +++ b/pkg/lvgl/include/lvgl_riot.h @@ -19,7 +19,7 @@ #ifndef LVGL_RIOT_H #define LVGL_RIOT_H -#include "disp_dev.h" +#include "screen_dev.h" #ifdef __cplusplus extern "C" { @@ -28,9 +28,9 @@ extern "C" { /** * @brief Initialize the lvgl display engine * - * @param[in] dev Pointer to the generic display device + * @param[in] screen_dev Pointer to the generic screen device */ -void lvgl_init(disp_dev_t *dev); +void lvgl_init(screen_dev_t *screen_dev); /** * @brief Wakeup lvgl when inactive