Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 35 additions & 16 deletions drivers/display/display_dummy.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,29 @@
struct dummy_display_config {
uint16_t height;
uint16_t width;
int rotation;
};

struct dummy_display_data {
enum display_pixel_format current_pixel_format;
enum display_orientation current_orientation;
};

static int dummy_display_init(const struct device *dev)
{
struct dummy_display_data *disp_data = dev->data;
const struct dummy_display_config *disp_cfg = dev->config;

disp_data->current_pixel_format = PIXEL_FORMAT_ARGB_8888;
if (disp_cfg->rotation == 0U) {
disp_data->current_orientation = DISPLAY_ORIENTATION_NORMAL;
} else if (disp_cfg->rotation == 90U) {
disp_data->current_orientation = DISPLAY_ORIENTATION_ROTATED_90;
} else if (disp_cfg->rotation == 180U) {
disp_data->current_orientation = DISPLAY_ORIENTATION_ROTATED_180;
} else {
disp_data->current_orientation = DISPLAY_ORIENTATION_ROTATED_270;
}

return 0;
}
Expand Down Expand Up @@ -93,8 +105,8 @@ static void dummy_display_get_capabilities(const struct device *dev,
PIXEL_FORMAT_MONO01 |
PIXEL_FORMAT_MONO10;
capabilities->current_pixel_format = disp_data->current_pixel_format;
capabilities->screen_info = SCREEN_INFO_MONO_VTILED |
SCREEN_INFO_MONO_MSB_FIRST;
capabilities->current_orientation = disp_data->current_orientation;
capabilities->screen_info = SCREEN_INFO_MONO_VTILED | SCREEN_INFO_MONO_MSB_FIRST;
}

static int dummy_display_set_pixel_format(const struct device *dev,
Expand All @@ -106,6 +118,15 @@ static int dummy_display_set_pixel_format(const struct device *dev,
return 0;
}

static int dummy_display_set_orientation(const struct device *dev,
const enum display_orientation orientation)
{
struct dummy_display_data *disp_data = dev->data;

disp_data->current_orientation = orientation;
return 0;
}

static const struct display_driver_api dummy_display_api = {
.blanking_on = dummy_display_blanking_on,
.blanking_off = dummy_display_blanking_off,
Expand All @@ -114,21 +135,19 @@ static const struct display_driver_api dummy_display_api = {
.set_contrast = dummy_display_set_contrast,
.get_capabilities = dummy_display_get_capabilities,
.set_pixel_format = dummy_display_set_pixel_format,
.set_orientation = dummy_display_set_orientation,
};

#define DISPLAY_DUMMY_DEFINE(n) \
static const struct dummy_display_config dd_config_##n = { \
.height = DT_INST_PROP(n, height), \
.width = DT_INST_PROP(n, width), \
}; \
\
static struct dummy_display_data dd_data_##n; \
\
DEVICE_DT_INST_DEFINE(n, &dummy_display_init, NULL, \
&dd_data_##n, \
&dd_config_##n, \
POST_KERNEL, \
CONFIG_DISPLAY_INIT_PRIORITY, \
&dummy_display_api); \
#define DISPLAY_DUMMY_DEFINE(n) \
static const struct dummy_display_config dd_config_##n = { \
.height = DT_INST_PROP(n, height), \
.width = DT_INST_PROP(n, width), \
.rotation = DT_INST_PROP(n, rotation), \
}; \
\
static struct dummy_display_data dd_data_##n; \
\
DEVICE_DT_INST_DEFINE(n, &dummy_display_init, NULL, &dd_data_##n, &dd_config_##n, \
POST_KERNEL, CONFIG_DISPLAY_INIT_PRIORITY, &dummy_display_api);

DT_INST_FOREACH_STATUS_OKAY(DISPLAY_DUMMY_DEFINE)
13 changes: 13 additions & 0 deletions dts/bindings/display/zephyr,dummy-dc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,16 @@ description: Dummy display controller
compatible: "zephyr,dummy-dc"

include: display-controller.yaml

properties:

rotation:
type: int
default: 0
enum:
- 0
- 90
- 180
- 270
description: |
Display rotation (CW) in degrees. Defaults to 0, display default.
2 changes: 2 additions & 0 deletions modules/lvgl/include/lvgl_display.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ int set_lvgl_rendering_cb(lv_disp_drv_t *disp_drv);

void lvgl_flush_display(struct lvgl_display_flush *request);

int lvgl_reload_display_capabilities(void);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a comment that this should not be called while rendering is in progress.


#ifdef CONFIG_LV_Z_USE_ROUNDER_CB
void lvgl_rounder_cb(lv_disp_drv_t *disp_drv, lv_area_t *area);
#endif
Expand Down
41 changes: 11 additions & 30 deletions modules/lvgl/input/lvgl_pointer_input.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,65 +61,46 @@ static void lvgl_pointer_process_event(const struct device *dev, struct input_ev
return;
}

lv_point_t tmp_point = {
.x = data->point_x,
.y = data->point_y,
};
point->x = data->point_x;
point->y = data->point_y;

if (cfg->invert_x) {
if (cap->current_orientation == DISPLAY_ORIENTATION_NORMAL ||
cap->current_orientation == DISPLAY_ORIENTATION_ROTATED_180) {
tmp_point.x = cap->x_resolution - tmp_point.x;
point->x = cap->x_resolution - point->x;
} else {
tmp_point.x = cap->y_resolution - tmp_point.x;
point->x = cap->y_resolution - point->x;
}
}

if (cfg->invert_y) {
if (cap->current_orientation == DISPLAY_ORIENTATION_NORMAL ||
cap->current_orientation == DISPLAY_ORIENTATION_ROTATED_180) {
tmp_point.y = cap->y_resolution - tmp_point.y;
point->y = cap->y_resolution - point->y;
} else {
tmp_point.y = cap->x_resolution - tmp_point.y;
point->y = cap->x_resolution - point->y;
}
}

/* rotate touch point to match display rotation */
/* Compensate off-by-one error in LVGL rotation code (lv_indev.c) */
switch (cap->current_orientation) {
case DISPLAY_ORIENTATION_NORMAL:
point->x = tmp_point.x;
point->y = tmp_point.y;
break;
case DISPLAY_ORIENTATION_ROTATED_90:
point->x = tmp_point.y;
point->y = cap->y_resolution - tmp_point.x;
point->y -= 1;
break;
case DISPLAY_ORIENTATION_ROTATED_180:
point->x = cap->x_resolution - tmp_point.x;
point->y = cap->y_resolution - tmp_point.y;
point->x -= 1;
point->y -= 1;
break;
case DISPLAY_ORIENTATION_ROTATED_270:
point->x = cap->x_resolution - tmp_point.y;
point->y = tmp_point.x;
point->x -= 1;
break;
default:
LOG_ERR("Invalid display orientation");
break;
}

/* filter readings within display */
if (point->x <= 0) {
point->x = 0;
} else if (point->x >= cap->x_resolution) {
point->x = cap->x_resolution - 1;
}

if (point->y <= 0) {
point->y = 0;
} else if (point->y >= cap->y_resolution) {
point->y = cap->y_resolution - 1;
}

if (k_msgq_put(cfg->common_config.event_msgq, &data->common_data.pending_event,
K_NO_WAIT) != 0) {
LOG_WRN("Could not put input data into queue");
Expand Down
5 changes: 5 additions & 0 deletions modules/lvgl/lvgl.c
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,11 @@ static int lvgl_init(void)
return -EPERM;
}

if (lvgl_reload_display_capabilities() != 0) {
LOG_ERR("Error reloading display capabilities.");
return -EPERM;
}

err = lvgl_init_input_devices();
if (err < 0) {
LOG_ERR("Failed to initialize input devices.");
Expand Down
50 changes: 46 additions & 4 deletions modules/lvgl/lvgl_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,53 @@ void lvgl_flush_display(struct lvgl_display_flush *request)
k_yield();
#else
/* Write directly to the display */
struct lvgl_disp_data *data =
(struct lvgl_disp_data *)request->disp_drv->user_data;
struct lvgl_disp_data *data = (struct lvgl_disp_data *)request->disp_drv->user_data;

display_write(data->display_dev, request->x, request->y,
&request->desc, request->buf);
display_write(data->display_dev, request->x, request->y, &request->desc, request->buf);
lv_disp_flush_ready(request->disp_drv);
#endif
}

int lvgl_reload_display_capabilities(void)
{
lv_disp_t *disp = lv_disp_get_next(NULL);
struct lvgl_disp_data *disp_data = NULL;

if (!disp) {
return -EINVAL;
}

while (disp) {
if (disp->driver == NULL) {
continue;
}

disp_data = (struct lvgl_disp_data *)disp->driver->user_data;
if (disp_data == NULL) {
continue;
}

display_get_capabilities(disp_data->display_dev, &disp_data->cap);

switch (disp_data->cap.current_orientation) {
case DISPLAY_ORIENTATION_NORMAL:
disp->driver->rotated = LV_DISP_ROT_NONE;
break;
case DISPLAY_ORIENTATION_ROTATED_90:
disp->driver->rotated = LV_DISP_ROT_90;
break;
case DISPLAY_ORIENTATION_ROTATED_180:
disp->driver->rotated = LV_DISP_ROT_180;
break;
case DISPLAY_ORIENTATION_ROTATED_270:
disp->driver->rotated = LV_DISP_ROT_270;
break;
default:
return -EINVAL;
}

disp = lv_disp_get_next(disp);
}

return 0;
}
8 changes: 8 additions & 0 deletions tests/lib/gui/lvgl_input/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# SPDX-License-Identifier: Apache-2.0

cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(lvgl)

FILE(GLOB app_sources src/*.c)
target_sources(app PRIVATE ${app_sources})
23 changes: 23 additions & 0 deletions tests/lib/gui/lvgl_input/app.overlay
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright (c) 2024 Fabian Blatz <[email protected]>
*
* SPDX-License-Identifier: Apache-2.0
*/

/ {
chosen {
zephyr,display = &dummy_dc;
};

dummy_dc: dummy_dc {
compatible = "zephyr,dummy-dc";
height = <240>;
width = <320>;
};

/delete-node/ lvgl_pointer;
lvgl_pointer {
compatible = "zephyr,lvgl-pointer-input";
};

};
12 changes: 12 additions & 0 deletions tests/lib/gui/lvgl_input/prj.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
CONFIG_ZTEST=y

CONFIG_DISPLAY=y
CONFIG_SDL_DISPLAY=n
CONFIG_DUMMY_DISPLAY=y

CONFIG_LOG=y
CONFIG_INPUT=y
CONFIG_INPUT_MODE_SYNCHRONOUS=y

CONFIG_LVGL=y
CONFIG_LV_Z_MEM_POOL_SIZE=16384
Loading