Merge pull request #14188 from aabadie/pr/pkg/littlevgl_full
pkg/lvgl: add logic for managing touch devices + introduce screen_dev wrapper
This commit is contained in:
commit
06dca07b0a
51
drivers/include/screen_dev.h
Normal file
51
drivers/include/screen_dev.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup drivers_screen_dev Screen device generic API
|
||||
* @ingroup drivers_display
|
||||
* @brief Define the generic API of a screen device
|
||||
*
|
||||
* @see drivers_disp_dev @see drivers_touch_dev
|
||||
*
|
||||
* @experimental This API is experimental and in an early state - expect
|
||||
* changes!
|
||||
* @{
|
||||
*
|
||||
* @author Alexandre Abadie <alexandre.abadie@inria.fr>
|
||||
*/
|
||||
|
||||
#ifndef SCREEN_DEV_H
|
||||
#define SCREEN_DEV_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "disp_dev.h"
|
||||
|
||||
#ifdef MODULE_TOUCH_DEV
|
||||
#include "touch_dev.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Screen device descriptor
|
||||
*/
|
||||
typedef struct {
|
||||
disp_dev_t *display; /**< Pointer to the display device */
|
||||
#if MODULE_TOUCH_DEV || DOXYGEN
|
||||
touch_dev_t *touch; /**< Pointer to the touch device */
|
||||
#endif
|
||||
} screen_dev_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SCREEN_DEV_H */
|
||||
/** @} */
|
||||
@ -107,6 +107,8 @@ uint16_t touch_dev_width(const touch_dev_t *dev);
|
||||
*
|
||||
* If @p touches is NULL, this function only returns the number of touches.
|
||||
*
|
||||
* Touch position coordinates use the top left corner as origin.
|
||||
*
|
||||
* @param[in] dev Pointer to the touch device
|
||||
* @param[out] touches The array of touches
|
||||
* @param[in] len The touches array len
|
||||
|
||||
@ -27,6 +27,9 @@
|
||||
#include "stmpe811.h"
|
||||
#include "stmpe811_touch_dev.h"
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
|
||||
uint16_t _stmpe811_height(const touch_dev_t *touch_dev)
|
||||
{
|
||||
const stmpe811_t *dev = (const stmpe811_t *)touch_dev;
|
||||
@ -57,8 +60,13 @@ uint8_t _stmpe811_touches(const touch_dev_t *touch_dev, touch_t *touches, size_t
|
||||
if (ret && touches != NULL) {
|
||||
stmpe811_touch_position_t pos;
|
||||
stmpe811_read_touch_position(dev, &pos);
|
||||
touches[0].x = pos.x;
|
||||
touches[0].y = pos.y;
|
||||
/* STMPE811 driver returns the position with origin at the bottom left
|
||||
corner and portrait orientation, so convert them to use top left corner
|
||||
as origin and landscape orientation. */
|
||||
touches[0].x = pos.y;
|
||||
touches[0].y = dev->params.xmax - pos.x;
|
||||
|
||||
DEBUG("X: %i, Y: %i\n", touches[0].x, touches[0].y)
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@ -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]"
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 <assert.h>
|
||||
|
||||
#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,
|
||||
|
||||
@ -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
|
||||
|
||||
@ -25,12 +25,15 @@
|
||||
#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 dev;
|
||||
static ili9341_t s_disp_dev;
|
||||
static screen_dev_t s_screen;
|
||||
|
||||
#define CPU_LABEL_COLOR "FF0000"
|
||||
#define MEM_LABEL_COLOR "0000FF"
|
||||
@ -128,17 +131,17 @@ void sysmon_create(void)
|
||||
int main(void)
|
||||
{
|
||||
/* Configure the generic display driver interface */
|
||||
disp_dev_t *disp_dev = (disp_dev_t *)&dev;
|
||||
disp_dev->driver = &ili9341_disp_dev_driver;
|
||||
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(&dev, &ili9341_params[0]);
|
||||
ili9341_init(&s_disp_dev, &ili9341_params[0]);
|
||||
|
||||
/* Initialize lvgl with the generic display driver interface */
|
||||
lvgl_init(disp_dev);
|
||||
/* Initialize lvgl with the generic display and touch drivers */
|
||||
lvgl_init(&s_screen);
|
||||
|
||||
/* Create the system monitor widget */
|
||||
sysmon_create();
|
||||
|
||||
15
tests/pkg_lvgl_touch/Makefile
Normal file
15
tests/pkg_lvgl_touch/Makefile
Normal file
@ -0,0 +1,15 @@
|
||||
BOARD ?= stm32f429i-disc1
|
||||
include ../Makefile.tests_common
|
||||
|
||||
# No interactive_sync
|
||||
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
|
||||
17
tests/pkg_lvgl_touch/Makefile.ci
Normal file
17
tests/pkg_lvgl_touch/Makefile.ci
Normal file
@ -0,0 +1,17 @@
|
||||
BOARD_INSUFFICIENT_MEMORY := \
|
||||
blackpill \
|
||||
bluepill \
|
||||
i-nucleo-lrwan1 \
|
||||
nucleo-f031k6 \
|
||||
nucleo-f042k6 \
|
||||
nucleo-f302r8 \
|
||||
nucleo-f303k8 \
|
||||
nucleo-f334r8 \
|
||||
nucleo-l031k6 \
|
||||
nucleo-l053r8 \
|
||||
saml10-xpro \
|
||||
saml11-xpro \
|
||||
stm32f030f4-demo \
|
||||
stm32f0discovery \
|
||||
stm32l0538-disco \
|
||||
#
|
||||
18
tests/pkg_lvgl_touch/README.md
Normal file
18
tests/pkg_lvgl_touch/README.md
Normal file
@ -0,0 +1,18 @@
|
||||
LittlevGL sample application
|
||||
============================
|
||||
|
||||
This application shows a usage of LittlevGL with touch capabilities.
|
||||
|
||||
### Flashing the application
|
||||
|
||||
The application works without modification on the stm32f429i-disc1 board. To
|
||||
build, flash and run the application for this board, just use:
|
||||
|
||||
```
|
||||
make BOARD=stm32f429i-disc1 -C tests/pkg_lvgl_touch flash
|
||||
```
|
||||
|
||||
### Expected result
|
||||
|
||||
The application simply displays a button that can be clicked. Each time the
|
||||
button is clicked, the message "Button clicked!" is displayed in the terminal.
|
||||
94
tests/pkg_lvgl_touch/main.c
Normal file
94
tests/pkg_lvgl_touch/main.c
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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 tests
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief LittlevGL example application with clickable button
|
||||
*
|
||||
* @author Alexandre Abadie <alexandre.abadie@inria.fr>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#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)
|
||||
{
|
||||
(void)btn;
|
||||
if (event == LV_EVENT_CLICKED) {
|
||||
puts("Button clicked!");
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
/* Add a button to the current screen */
|
||||
lv_obj_t * btn = lv_btn_create(lv_scr_act(), NULL);
|
||||
|
||||
/* 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_obj_set_pos(btn, x_pos, y_pos);
|
||||
lv_obj_set_size(btn, 100, 50);
|
||||
|
||||
/*Assign a callback to the button*/
|
||||
lv_obj_set_event_cb(btn, btn_event_cb);
|
||||
|
||||
/* Add a label to the button */
|
||||
lv_obj_t * label = lv_label_create(btn, NULL);
|
||||
lv_label_set_text(label, "Click me");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -37,7 +37,7 @@ static stmpe811_t stmpe811;
|
||||
static void _touch_event_cb(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
puts("Pressed!");
|
||||
printf("Event: ");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
@ -61,7 +61,10 @@ int main(void)
|
||||
|
||||
if (current_touches != last_touches) {
|
||||
if (current_touches == 0) {
|
||||
puts("Released!");
|
||||
puts("released!");
|
||||
}
|
||||
if (current_touches > 0) {
|
||||
puts("pressed!");
|
||||
}
|
||||
last_touches = current_touches;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user