diff --git a/boards/adafruit-clue/Makefile.dep b/boards/adafruit-clue/Makefile.dep index 1d896eaf29..501bf04aaa 100644 --- a/boards/adafruit-clue/Makefile.dep +++ b/boards/adafruit-clue/Makefile.dep @@ -6,5 +6,9 @@ ifneq (,$(filter saul_default,$(USEMODULE))) USEMODULE += sht3x endif +ifneq (,$(filter disp_dev,$(USEMODULE))) + USEMODULE += ili9341 +endif + include $(RIOTBOARD)/common/nrf52/bootloader_nrfutil.dep.mk include $(RIOTBOARD)/common/nrf52/Makefile.dep diff --git a/boards/pinetime/Makefile.dep b/boards/pinetime/Makefile.dep index f3a5ebd2eb..aee3ae5527 100644 --- a/boards/pinetime/Makefile.dep +++ b/boards/pinetime/Makefile.dep @@ -7,5 +7,9 @@ ifneq (,$(filter mtd,$(USEMODULE))) USEMODULE += mtd_spi_nor endif +ifneq (,$(filter disp_dev,$(USEMODULE))) + USEMODULE += ili9341 +endif + # include common nrf52 dependencies include $(RIOTBOARD)/common/nrf52/Makefile.dep diff --git a/boards/stm32f429i-disc1/Makefile.dep b/boards/stm32f429i-disc1/Makefile.dep index 5472bf8b8d..4b04c828e4 100644 --- a/boards/stm32f429i-disc1/Makefile.dep +++ b/boards/stm32f429i-disc1/Makefile.dep @@ -1,3 +1,11 @@ ifneq (,$(filter saul_default,$(USEMODULE))) USEMODULE += saul_gpio endif + +ifneq (,$(filter disp_dev,$(USEMODULE))) + USEMODULE += ili9341 +endif + +ifneq (,$(filter touch_dev,$(USEMODULE))) + USEMODULE += stmpe811 +endif diff --git a/drivers/disp_dev/disp_dev.c b/drivers/disp_dev/disp_dev.c index acd716239e..5653d59656 100644 --- a/drivers/disp_dev/disp_dev.c +++ b/drivers/disp_dev/disp_dev.c @@ -21,9 +21,46 @@ #include #include #include +#include #include "disp_dev.h" +disp_dev_reg_t *disp_dev_reg = NULL; + +int disp_dev_reg_add(disp_dev_reg_t *dev) +{ + disp_dev_reg_t *tmp = disp_dev_reg; + + if (dev == NULL) { + return -ENODEV; + } + + /* prepare new entry */ + dev->next = NULL; + /* add to registry */ + if (disp_dev_reg == NULL) { + disp_dev_reg = dev; + } + else { + while (tmp->next != NULL) { + tmp = tmp->next; + } + tmp->next = dev; + } + return 0; +} + +disp_dev_reg_t *disp_dev_reg_find_screen(uint8_t screen_id) +{ + disp_dev_reg_t *tmp = disp_dev_reg; + + while (tmp && tmp->screen_id != screen_id) { + tmp = tmp->next; + } + + return tmp; +} + void disp_dev_map(const disp_dev_t *dev, uint16_t x1, uint16_t x2, uint16_t y1, uint16_t y2, const uint16_t *color) diff --git a/drivers/ili9341/include/ili9341_params.h b/drivers/ili9341/include/ili9341_params.h index b86105872f..ddc627fb8b 100644 --- a/drivers/ili9341/include/ili9341_params.h +++ b/drivers/ili9341/include/ili9341_params.h @@ -81,6 +81,21 @@ static const ili9341_params_t ili9341_params[] = ILI9341_PARAMS, }; +/** + * @brief Default screen identifiers + */ +#ifndef ILI9341_PARAM_SCREEN_IDS +#define ILI9341_PARAM_SCREEN_IDS 0 +#endif + +/** + * @brief Configure screen identifiers + */ +static const uint8_t ili9341_screen_ids[] = +{ + ILI9341_PARAM_SCREEN_IDS, +}; + #ifdef __cplusplus } #endif diff --git a/drivers/include/disp_dev.h b/drivers/include/disp_dev.h index c5c21f7b9a..a2d8e680b4 100644 --- a/drivers/include/disp_dev.h +++ b/drivers/include/disp_dev.h @@ -101,6 +101,40 @@ struct disp_dev { const disp_dev_driver_t *driver; /**< Pointer to driver of the display device */ }; +/** + * @brief Disp dev registry entry + */ +typedef struct disp_dev_reg { + struct disp_dev_reg *next; /**< pointer to the next display device in the list */ + disp_dev_t *dev; /**< pointer to the device descriptor */ + uint8_t screen_id; /**< id of the screen this display is attached to */ +} disp_dev_reg_t; + +/** + * @brief Export the display device registry as global variable + */ +extern disp_dev_reg_t *disp_dev_reg; + +/** + * @brief Add pointer to a display device item to the list of display items + * + * @param[in] dev Pointer to the display device + * + * @return 0 on success + * @return -ENODEV on invalid entry +*/ +int disp_dev_reg_add(disp_dev_reg_t *dev); + +/** + * @brief Find the display device that is attached to a given screen + * + * @param[in] screen_id Identifier (number) of the screen + * + * @return pointer to the display device in the registry + * @return NULL if there's no match +*/ +disp_dev_reg_t *disp_dev_reg_find_screen(uint8_t screen_id); + /** * @brief Map an area to display on the device * diff --git a/drivers/include/screen_dev.h b/drivers/include/screen_dev.h index 775c6cb7ea..b61937c86f 100644 --- a/drivers/include/screen_dev.h +++ b/drivers/include/screen_dev.h @@ -11,6 +11,17 @@ * @ingroup drivers_display * @brief Define the generic API of a screen device * + * The screen device API is a generic API built on top of display and touch + * device APIs. + * + * Each display/touch device driver implementing this interface has to expose + * a set of predefined functions and it has to register itself to the central + * display/touch device registry. From here devices can be found, listed, and + * accessed. + * + * The display and touch devices are linked to a screen by providing the + * screen id (basically an index) they correspond to. + * * @see drivers_disp_dev @see drivers_touch_dev * * @experimental This API is experimental and in an early state - expect diff --git a/drivers/include/stmpe811.h b/drivers/include/stmpe811.h index 8cc4e6fbfa..1f353198ff 100644 --- a/drivers/include/stmpe811.h +++ b/drivers/include/stmpe811.h @@ -64,7 +64,7 @@ typedef struct { * * @param[in] arg optional context for the callback */ -typedef void (*touch_event_cb_t)(void *arg); +typedef void (*stmpe811_event_cb_t)(void *arg); /** * @brief Device initialization parameters @@ -85,6 +85,8 @@ typedef struct { touch_dev_t *dev; /**< Pointer to the generic touch device */ #endif stmpe811_params_t params; /**< Device parameters */ + stmpe811_event_cb_t cb; /**< Configured IRQ event callback */ + void *cb_arg; /**< Extra argument for the callback */ uint16_t prev_x; /**< Previous X coordinate */ uint16_t prev_y; /**< Previous Y coordinate */ } stmpe811_t; @@ -103,7 +105,7 @@ typedef struct { * @return -STMPE811_ERR_I2C on any I2C error */ int stmpe811_init(stmpe811_t *dev, const stmpe811_params_t * params, - touch_event_cb_t cb, void *arg); + stmpe811_event_cb_t cb, void *arg); /** * @brief Read the touch position diff --git a/drivers/include/touch_dev.h b/drivers/include/touch_dev.h index bb4121ca9c..49bba79586 100644 --- a/drivers/include/touch_dev.h +++ b/drivers/include/touch_dev.h @@ -41,6 +41,13 @@ typedef struct { uint16_t y; /**< Y coordinate */ } touch_t; +/** + * @brief Signature of touch event callback triggered from interrupt + * + * @param[in] arg optional context for the callback + */ +typedef void (*touch_event_cb_t)(void *arg); + /** * @brief Generic type for a touch driver */ @@ -75,6 +82,15 @@ typedef struct { * @return number of touch positions, 0 means no touch */ uint8_t (*touches)(const touch_dev_t *dev, touch_t *touches, size_t len); + + /** + * @brief Set and configure the touch event callback + * + * @param[in] dev Pointer to the touch device + * @param[in] cb The callback function + * @param[in] arg Context argument + */ + void (*set_event_callback)(const touch_dev_t *dev, touch_event_cb_t cb, void *arg); } touch_dev_driver_t; /** @@ -84,6 +100,40 @@ struct touch_dev { const touch_dev_driver_t *driver; /**< Pointer to driver of the touch device */ }; +/** + * @brief Touch dev registry entry + */ +typedef struct touch_dev_reg { + struct touch_dev_reg *next; /**< pointer to the next touch device in the list */ + touch_dev_t *dev; /**< pointer to the device descriptor */ + uint8_t screen_id; /**< id of the screen this touch device is attached to */ +} touch_dev_reg_t; + +/** + * @brief Export the touch device registry as global variable + */ +extern touch_dev_reg_t *touch_dev_reg; + +/** + * @brief Add pointer to a touch device item to the list of touch items + * + * @param[in] dev Pointer to the touch device + * + * @return 0 on success + * @return -ENODEV on invalid entry +*/ +int touch_dev_reg_add(touch_dev_reg_t *dev); + +/** + * @brief Find the touch device that is attached to a given screen + * + * @param[in] screen_id Identifier (number) of the screen + * + * @return pointer to the touch device in the registry + * @return NULL if there's no match +*/ +touch_dev_reg_t *touch_dev_reg_find_screen(uint8_t screen_id); + /** * @brief Get the height of the touch device * @@ -116,6 +166,15 @@ uint16_t touch_dev_width(const touch_dev_t *dev); */ uint8_t touch_dev_touches(const touch_dev_t *dev, touch_t *touches, size_t len); +/** + * @brief Set and configure the touch event callback + * + * @param[in] dev Pointer to the touch device + * @param[in] cb The callback function + * @param[in] arg Context argument + */ +void touch_dev_set_touch_event_callback(const touch_dev_t *dev, touch_event_cb_t cb, void *arg); + #ifdef __cplusplus } #endif diff --git a/drivers/stmpe811/include/stmpe811_params.h b/drivers/stmpe811/include/stmpe811_params.h index 2fa2dcb8f9..e81d8808bc 100644 --- a/drivers/stmpe811/include/stmpe811_params.h +++ b/drivers/stmpe811/include/stmpe811_params.h @@ -67,6 +67,21 @@ static const stmpe811_params_t stmpe811_params[] = STMPE811_PARAMS }; +/** + * @brief Default screen identifiers + */ +#ifndef STMPE811_PARAM_SCREEN_IDS +#define STMPE811_PARAM_SCREEN_IDS 0 +#endif + +/** + * @brief Configure screen identifiers + */ +static const uint8_t stmpe811_screen_ids[] = +{ + STMPE811_PARAM_SCREEN_IDS, +}; + #ifdef __cplusplus } #endif diff --git a/drivers/stmpe811/stmpe811.c b/drivers/stmpe811/stmpe811.c index 3d77d9585e..7094337194 100644 --- a/drivers/stmpe811/stmpe811.c +++ b/drivers/stmpe811/stmpe811.c @@ -34,6 +34,16 @@ #define STMPE811_DEV_I2C (dev->params.i2c) #define STMPE811_DEV_ADDR (dev->params.addr) +static void _gpio_irq(void *arg) +{ + const stmpe811_t *dev = (const stmpe811_t *)arg; + assert(dev); + + if (dev->cb) { + dev->cb(dev->cb_arg); + } +} + static int _soft_reset(const stmpe811_t *dev) { if (i2c_write_reg(STMPE811_DEV_I2C, STMPE811_DEV_ADDR, @@ -66,9 +76,12 @@ static void _clear_interrupt_status(const stmpe811_t *dev) i2c_write_reg(STMPE811_DEV_I2C, STMPE811_DEV_ADDR, STMPE811_INT_STA, 0xff, 0); } -int stmpe811_init(stmpe811_t *dev, const stmpe811_params_t * params, touch_event_cb_t cb, void *arg) +int stmpe811_init(stmpe811_t *dev, const stmpe811_params_t * params, stmpe811_event_cb_t cb, void *arg) { dev->params = *params; + dev->cb = cb; + dev->cb_arg = arg; + int ret = STMPE811_OK; /* Acquire I2C device */ @@ -160,9 +173,9 @@ int stmpe811_init(stmpe811_t *dev, const stmpe811_params_t * params, touch_event /* clear interrupt status */ _clear_interrupt_status(dev); - if (gpio_is_valid(dev->params.int_pin) && cb) { + if (gpio_is_valid(dev->params.int_pin)) { DEBUG("[stmpe811] init: configuring touchscreen interrupt\n"); - gpio_init_int(dev->params.int_pin, GPIO_IN, GPIO_FALLING, cb, arg); + gpio_init_int(dev->params.int_pin, GPIO_IN, GPIO_FALLING, _gpio_irq, dev); /* Enable touchscreen interrupt */ ret += i2c_write_reg(STMPE811_DEV_I2C, STMPE811_DEV_ADDR, diff --git a/drivers/stmpe811/stmpe811_touch_dev.c b/drivers/stmpe811/stmpe811_touch_dev.c index c0b6af1d40..1e4ee268f9 100644 --- a/drivers/stmpe811/stmpe811_touch_dev.c +++ b/drivers/stmpe811/stmpe811_touch_dev.c @@ -72,8 +72,18 @@ uint8_t _stmpe811_touches(const touch_dev_t *touch_dev, touch_t *touches, size_t return ret; } +void _stmpe811_set_event_callback(const touch_dev_t *touch_dev, touch_event_cb_t cb, void *arg) +{ + stmpe811_t *dev = (stmpe811_t *)touch_dev; + assert(dev); + + dev->cb = (stmpe811_event_cb_t)cb; + dev->cb_arg = arg; +} + const touch_dev_driver_t stmpe811_touch_dev_driver = { .height = _stmpe811_height, .width = _stmpe811_width, .touches = _stmpe811_touches, + .set_event_callback = _stmpe811_set_event_callback, }; diff --git a/drivers/touch_dev/touch_dev.c b/drivers/touch_dev/touch_dev.c index 913e504691..8076ca416f 100644 --- a/drivers/touch_dev/touch_dev.c +++ b/drivers/touch_dev/touch_dev.c @@ -22,9 +22,46 @@ #include #include #include +#include #include "touch_dev.h" +touch_dev_reg_t *touch_dev_reg = NULL; + +int touch_dev_reg_add(touch_dev_reg_t *dev) +{ + touch_dev_reg_t *tmp = touch_dev_reg; + + if (dev == NULL) { + return -ENODEV; + } + + /* prepare new entry */ + dev->next = NULL; + /* add to registry */ + if (touch_dev_reg == NULL) { + touch_dev_reg = dev; + } + else { + while (tmp->next != NULL) { + tmp = tmp->next; + } + tmp->next = dev; + } + return 0; +} + +touch_dev_reg_t *touch_dev_reg_find_screen(uint8_t screen_id) +{ + touch_dev_reg_t *tmp = touch_dev_reg; + + while (tmp && tmp->screen_id != screen_id) { + tmp = tmp->next; + } + + return tmp; +} + uint16_t touch_dev_height(const touch_dev_t *dev) { assert(dev); @@ -45,3 +82,9 @@ uint8_t touch_dev_touches(const touch_dev_t *dev, touch_t *touches, size_t len) return dev->driver->touches(dev, touches, len); } + +void touch_dev_set_touch_event_callback(const touch_dev_t *dev, touch_event_cb_t cb, void *arg) +{ + assert(dev); + dev->driver->set_event_callback(dev, cb, arg); +} diff --git a/makefiles/pseudomodules.inc.mk b/makefiles/pseudomodules.inc.mk index c4e4673ebf..e6c4f6ba1f 100644 --- a/makefiles/pseudomodules.inc.mk +++ b/makefiles/pseudomodules.inc.mk @@ -305,5 +305,6 @@ NO_PSEUDOMODULES += auto_init_loramac NO_PSEUDOMODULES += auto_init_multimedia NO_PSEUDOMODULES += auto_init_security NO_PSEUDOMODULES += auto_init_usbus +NO_PSEUDOMODULES += auto_init_screen # Packages may also add modules to PSEUDOMODULES in their `Makefile.include`. diff --git a/pkg/lvgl/Makefile.dep b/pkg/lvgl/Makefile.dep index 68c08e03a9..7aa99187c1 100644 --- a/pkg/lvgl/Makefile.dep +++ b/pkg/lvgl/Makefile.dep @@ -1,3 +1,4 @@ +USEMODULE += lvgl USEMODULE += lvgl_core USEMODULE += lvgl_draw USEMODULE += lvgl_font @@ -16,6 +17,8 @@ ifneq (,$(filter lvgl_contrib_touch,$(USEMODULE))) USEMODULE += touch_dev endif +DEFAULT_MODULE += auto_init_screen + # 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.lvgl_module b/pkg/lvgl/Makefile.lvgl_module index 75bf9bde99..eb44812a13 100644 --- a/pkg/lvgl/Makefile.lvgl_module +++ b/pkg/lvgl/Makefile.lvgl_module @@ -1,6 +1,7 @@ CFLAGS += -Wno-unused-parameter CFLAGS += -Wno-sign-compare CFLAGS += -Wno-unused-function +CFLAGS += -Wno-maybe-uninitialized ifeq (llvm,$(TOOLCHAIN)) CFLAGS += -Wno-missing-braces diff --git a/pkg/lvgl/contrib/lvgl.c b/pkg/lvgl/contrib/lvgl.c index 3ea44fcd77..94546e72c0 100644 --- a/pkg/lvgl/contrib/lvgl.c +++ b/pkg/lvgl/contrib/lvgl.c @@ -19,6 +19,7 @@ #include +#include "kernel_defines.h" #include "thread.h" #include "xtimer.h" @@ -97,7 +98,7 @@ static void _disp_map(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *col lv_disp_flush_ready(drv); } -#ifdef MODULE_TOUCH_DEV +#if IS_USED(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) { @@ -145,16 +146,21 @@ void lvgl_init(screen_dev_t *screen_dev) 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); +#if IS_USED(MODULE_TOUCH_DEV) + if (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(); +} + +void lvgl_start(void) +{ _task_thread_pid = thread_create(_task_thread_stack, sizeof(_task_thread_stack), LVGL_TASK_THREAD_PRIO, THREAD_CREATE_STACKTEST, _task_thread, NULL, "_task_thread"); diff --git a/pkg/lvgl/include/lvgl_riot.h b/pkg/lvgl/include/lvgl_riot.h index c65a7116ee..7c16cb7879 100644 --- a/pkg/lvgl/include/lvgl_riot.h +++ b/pkg/lvgl/include/lvgl_riot.h @@ -32,6 +32,11 @@ extern "C" { */ void lvgl_init(screen_dev_t *screen_dev); +/** + * Start the lvgl task handler background thread +*/ +void lvgl_start(void); + /** * @brief Wakeup lvgl when inactive * diff --git a/sys/auto_init/Makefile b/sys/auto_init/Makefile index 7c5a9c9e23..f1ac62ab8a 100644 --- a/sys/auto_init/Makefile +++ b/sys/auto_init/Makefile @@ -26,4 +26,8 @@ ifneq (,$(filter auto_init_security,$(USEMODULE))) DIRS += security endif +ifneq (,$(filter auto_init_screen,$(USEMODULE))) + DIRS += screen +endif + include $(RIOTBASE)/Makefile.base diff --git a/sys/auto_init/auto_init.c b/sys/auto_init/auto_init.c index 3479ff3602..bad383816f 100644 --- a/sys/auto_init/auto_init.c +++ b/sys/auto_init/auto_init.c @@ -270,4 +270,10 @@ void auto_init(void) auto_init_dfplayer(); } } + + if (IS_USED(MODULE_AUTO_INIT_SCREEN)) { + LOG_DEBUG("Auto init screen devices\n"); + extern void auto_init_screen(void); + auto_init_screen(); + } } diff --git a/sys/auto_init/screen/Makefile b/sys/auto_init/screen/Makefile new file mode 100644 index 0000000000..848e9e1442 --- /dev/null +++ b/sys/auto_init/screen/Makefile @@ -0,0 +1,3 @@ +MODULE = auto_init_screen + +include $(RIOTMAKE)/auto_init.inc.mk diff --git a/sys/auto_init/screen/auto_init_ili9341.c b/sys/auto_init/screen/auto_init_ili9341.c new file mode 100644 index 0000000000..5ce7d86d71 --- /dev/null +++ b/sys/auto_init/screen/auto_init_ili9341.c @@ -0,0 +1,53 @@ +/* + * Copyright (C) 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 + * directory for more details. + */ + +/** + * @ingroup sys_auto_init + * @{ + * @file + * @brief initializes ili9341 display device + * + * @author Alexandre Abadie + * @} + */ + +#include +#include + +#include "log.h" + +#include "disp_dev.h" + +#include "ili9341.h" +#include "ili9341_params.h" +#include "ili9341_disp_dev.h" + +#define ILI9341_NUMOF ARRAY_SIZE(ili9341_params) + +static ili9341_t ili9341_devs[ILI9341_NUMOF]; +static disp_dev_reg_t disp_dev_entries[ILI9341_NUMOF]; + +void auto_init_ili9341(void) +{ + assert(ILI9341_NUMOF == ARRAY_SIZE(ili9341_screen_ids)); + + for (size_t i = 0; i < ILI9341_NUMOF; i++) { + LOG_DEBUG("[auto_init_screen] initializing ili9341 #%u\n", i); + if (ili9341_init(&ili9341_devs[i], &ili9341_params[i]) < 0) { + LOG_ERROR("[auto_init_screen] error initializing ili9341 #%u\n", i); + continue; + } + + disp_dev_entries[i].dev = (disp_dev_t *)&ili9341_devs[i]; + disp_dev_entries[i].screen_id = ili9341_screen_ids[i]; + disp_dev_entries[i].dev->driver = &ili9341_disp_dev_driver; + + /* add to disp_dev registry */ + disp_dev_reg_add(&(disp_dev_entries[i])); + } +} diff --git a/sys/auto_init/screen/auto_init_lvgl.c b/sys/auto_init/screen/auto_init_lvgl.c new file mode 100644 index 0000000000..1cc6876e20 --- /dev/null +++ b/sys/auto_init/screen/auto_init_lvgl.c @@ -0,0 +1,64 @@ +/* + * Copyright (C) 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 + * directory for more details. + */ + +/** + * @ingroup sys_auto_init + * @{ + * @file + * @brief initializes lvgl high level GUI api + * + * @author Alexandre Abadie + * @} + */ + +#include "log.h" +#include "kernel_defines.h" + +#include "lvgl_riot.h" + +#include "screen_dev.h" +#include "disp_dev.h" + +#if IS_USED(MODULE_TOUCH_DEV) +#include "touch_dev.h" +#endif + +static screen_dev_t s_screen; +extern disp_dev_reg_t *disp_dev_reg; + +#if IS_USED(MODULE_TOUCH_DEV) +static void _touch_event_callback(void *arg) +{ + (void)arg; + lvgl_wakeup(); +} +#endif + +#ifndef CONFIG_LVGL_SCREEN_DEFAULT +#define CONFIG_LVGL_SCREEN_DEFAULT 0 /**< Default screen ID used by LVGL */ +#endif + +void auto_init_lvgl(void) +{ + LOG_DEBUG("[auto_init_screen] initializing lvgl\n"); + + /* Only a single screen is supported by lvgl */ + disp_dev_reg_t *disp_dev = disp_dev_reg_find_screen(CONFIG_LVGL_SCREEN_DEFAULT); + s_screen.display = disp_dev->dev; + +#if IS_USED(MODULE_TOUCH_DEV) + touch_dev_reg_t *touch_dev = touch_dev_reg_find_screen(CONFIG_LVGL_SCREEN_DEFAULT); + if (touch_dev) { + s_screen.touch = touch_dev->dev; + touch_dev_set_touch_event_callback(touch_dev->dev, _touch_event_callback, NULL); + } +#endif + + /* Initialize lvgl with the generic screen */ + lvgl_init(&s_screen); +} diff --git a/sys/auto_init/screen/auto_init_stmpe811.c b/sys/auto_init/screen/auto_init_stmpe811.c new file mode 100644 index 0000000000..fd004b5356 --- /dev/null +++ b/sys/auto_init/screen/auto_init_stmpe811.c @@ -0,0 +1,52 @@ +/* + * Copyright (C) 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 + * directory for more details. + */ + +/** + * @ingroup sys_auto_init + * @{ + * @file + * @brief initializes stmpe811 display device + * + * @author Alexandre Abadie + * @} + */ + +#include + +#include "log.h" + +#include "touch_dev.h" + +#include "stmpe811.h" +#include "stmpe811_params.h" +#include "stmpe811_touch_dev.h" + +#define STMPE811_NUMOF ARRAY_SIZE(stmpe811_params) + +stmpe811_t stmpe811_devs[STMPE811_NUMOF]; +static touch_dev_reg_t touch_dev_entries[STMPE811_NUMOF]; + +void auto_init_stmpe811(void) +{ + assert(STMPE811_NUMOF == ARRAY_SIZE(stmpe811_screen_ids)); + + for (size_t i = 0; i < STMPE811_NUMOF; i++) { + LOG_DEBUG("[auto_init_screen] initializing stmpe811 #%u\n", i); + if (stmpe811_init(&stmpe811_devs[i], &stmpe811_params[i], NULL, NULL) < 0) { + LOG_ERROR("[auto_init_screen] error initializing stmpe811 #%u\n", i); + continue; + } + + touch_dev_entries[i].dev = (touch_dev_t *)&stmpe811_devs[i]; + touch_dev_entries[i].screen_id = stmpe811_screen_ids[i]; + touch_dev_entries[i].dev->driver = &stmpe811_touch_dev_driver; + + /* add to touch_dev registry */ + touch_dev_reg_add(&(touch_dev_entries[i])); + } +} diff --git a/sys/auto_init/screen/init.c b/sys/auto_init/screen/init.c new file mode 100644 index 0000000000..501db6ef49 --- /dev/null +++ b/sys/auto_init/screen/init.c @@ -0,0 +1,46 @@ +/* + * Copyright (C) 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 + * directory for more details. + */ + +/** + * @ingroup sys_auto_init + * @{ + * @file + * @brief automatically initializes screen display and touch devices + * + * @author Alexandre Abadie + * @} + */ + +#include + +#define ENABLE_DEBUG (0) +#include "debug.h" + +void auto_init_screen(void) +{ + if (IS_USED(MODULE_DISP_DEV)) { + DEBUG("auto_init_screen: init display drivers\n"); + if (IS_USED(MODULE_ILI9341)) { + extern void auto_init_ili9341(void); + auto_init_ili9341(); + } + } + + if (IS_USED(MODULE_TOUCH_DEV)) { + DEBUG("auto_init_screen: init touch drivers\n"); + if (IS_USED(MODULE_STMPE811)) { + extern void auto_init_stmpe811(void); + auto_init_stmpe811(); + } + } + + if (IS_USED(MODULE_LVGL)) { + extern void auto_init_lvgl(void); + auto_init_lvgl(); + } +} diff --git a/tests/pkg_lvgl/Makefile b/tests/pkg_lvgl/Makefile index 7e1d12ed65..4795f07f0a 100644 --- a/tests/pkg_lvgl/Makefile +++ b/tests/pkg_lvgl/Makefile @@ -6,7 +6,6 @@ DISABLE_MODULE += test_utils_interactive_sync USEPKG += lvgl USEMODULE += lvgl_contrib -USEMODULE += ili9341 CFLAGS += -DTHREAD_STACKSIZE_MAIN=2048 diff --git a/tests/pkg_lvgl/Makefile.ci b/tests/pkg_lvgl/Makefile.ci index a583c83789..3cfe4bbcb8 100644 --- a/tests/pkg_lvgl/Makefile.ci +++ b/tests/pkg_lvgl/Makefile.ci @@ -3,6 +3,7 @@ BOARD_INSUFFICIENT_MEMORY := \ bluepill \ bluepill-stm32f030c8 \ i-nucleo-lrwan1 \ + nucleo-f030r8 \ nucleo-f031k6 \ nucleo-f042k6 \ nucleo-f302r8 \ @@ -20,4 +21,5 @@ BOARD_INSUFFICIENT_MEMORY := \ stm32f030f4-demo \ stm32f0discovery \ stm32l0538-disco \ + stm32mp157c-dk2 \ # diff --git a/tests/pkg_lvgl/main.c b/tests/pkg_lvgl/main.c index af7516ab7c..751f60efb8 100644 --- a/tests/pkg_lvgl/main.c +++ b/tests/pkg_lvgl/main.c @@ -24,16 +24,7 @@ #include "lvgl/lvgl.h" #include "lvgl_riot.h" - -#include "screen_dev.h" - -#include "ili9341.h" -#include "ili9341_params.h" #include "disp_dev.h" -#include "ili9341_disp_dev.h" - -static ili9341_t s_disp_dev; -static screen_dev_t s_screen; #define CPU_LABEL_COLOR "FF0000" #define MEM_LABEL_COLOR "0000FF" @@ -127,18 +118,10 @@ void sysmon_create(void) int main(void) { - /* Configure the generic display driver interface */ - s_screen.display = (disp_dev_t *)&s_disp_dev; - s_screen.display->driver = &ili9341_disp_dev_driver; - /* Enable backlight */ disp_dev_backlight_on(); - /* Initialize the concrete display driver */ - ili9341_init(&s_disp_dev, &ili9341_params[0]); - - /* Initialize lvgl with the generic display and touch drivers */ - lvgl_init(&s_screen); + lvgl_start(); /* Create the system monitor widget */ sysmon_create(); diff --git a/tests/pkg_lvgl_touch/Makefile b/tests/pkg_lvgl_touch/Makefile index ee21be62f4..3d34d38d10 100644 --- a/tests/pkg_lvgl_touch/Makefile +++ b/tests/pkg_lvgl_touch/Makefile @@ -6,10 +6,8 @@ DISABLE_MODULE += test_utils_interactive_sync USEPKG += lvgl USEMODULE += lvgl_contrib -USEMODULE += ili9341 # Add touch capabilities USEMODULE += lvgl_contrib_touch -USEMODULE += stmpe811 include $(RIOTBASE)/Makefile.include diff --git a/tests/pkg_lvgl_touch/Makefile.ci b/tests/pkg_lvgl_touch/Makefile.ci index e142e789a4..8531e5411a 100644 --- a/tests/pkg_lvgl_touch/Makefile.ci +++ b/tests/pkg_lvgl_touch/Makefile.ci @@ -3,6 +3,7 @@ BOARD_INSUFFICIENT_MEMORY := \ bluepill \ bluepill-stm32f030c8 \ i-nucleo-lrwan1 \ + nucleo-f030r8 \ nucleo-f031k6 \ nucleo-f042k6 \ nucleo-f302r8 \ @@ -19,4 +20,5 @@ BOARD_INSUFFICIENT_MEMORY := \ stm32f030f4-demo \ stm32f0discovery \ stm32l0538-disco \ + stm32mp157c-dk2 \ # diff --git a/tests/pkg_lvgl_touch/main.c b/tests/pkg_lvgl_touch/main.c index 47c68bb1d2..0b76ef9edb 100644 --- a/tests/pkg_lvgl_touch/main.c +++ b/tests/pkg_lvgl_touch/main.c @@ -23,27 +23,8 @@ #include "lvgl/lvgl.h" #include "lvgl_riot.h" -#include "ili9341.h" -#include "ili9341_params.h" #include "disp_dev.h" -#include "ili9341_disp_dev.h" -#include "stmpe811.h" -#include "stmpe811_params.h" -#include "touch_dev.h" -#include "stmpe811_touch_dev.h" - -#include "screen_dev.h" - -static screen_dev_t s_screen; -static ili9341_t s_disp_dev; -static stmpe811_t s_touch_dev; - -static void _stmpe811_event_cb(void *arg) -{ - (void)arg; - lvgl_wakeup(); -} static void btn_event_cb(lv_obj_t * btn, lv_event_t event) { @@ -55,22 +36,8 @@ static void btn_event_cb(lv_obj_t * btn, lv_event_t event) int main(void) { - /* Configure the generic display driver interface */ - s_screen.display = (disp_dev_t *)&s_disp_dev; - s_screen.display->driver = &ili9341_disp_dev_driver; - - /* Initialize the concrete display driver */ - ili9341_init(&s_disp_dev, &ili9341_params[0]); - - /* Configure the generic touch driver interface */ - s_screen.touch = (touch_dev_t *)&s_touch_dev; - s_screen.touch->driver = &stmpe811_touch_dev_driver; - - /* Initialize the concrete touch driver */ - stmpe811_init(&s_touch_dev, &stmpe811_params[0], _stmpe811_event_cb, NULL); - - /* Initialize lvgl with the generic screen */ - lvgl_init(&s_screen); + /* Enable backlight */ + disp_dev_backlight_on(); /* Add a button to the current screen */ lv_obj_t * btn = lv_btn_create(lv_scr_act(), NULL); @@ -78,8 +45,8 @@ int main(void) /* Set the button position and size */ lv_coord_t x_size = 100; lv_coord_t y_size = 50; - lv_coord_t x_pos = (disp_dev_width(s_screen.display) - x_size) / 2; - lv_coord_t y_pos = (disp_dev_height(s_screen.display) - y_size) / 2; + lv_coord_t x_pos = (lv_obj_get_width(lv_scr_act()) - x_size) / 2; + lv_coord_t y_pos = (lv_obj_get_height(lv_scr_act()) - y_size) / 2; lv_obj_set_pos(btn, x_pos, y_pos); lv_obj_set_size(btn, 100, 50); @@ -90,5 +57,7 @@ int main(void) lv_obj_t * label = lv_label_create(btn, NULL); lv_label_set_text(label, "Click me"); + lvgl_start(); + return 0; }