forked from zephyrproject-rtos/zephyr
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlvgl_display.c
140 lines (119 loc) · 3.79 KB
/
lvgl_display.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/*
* Copyright (c) 2019 Jan Van Winkel <[email protected]>
* Copyright 2023 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <errno.h>
#include "lvgl_display.h"
#ifdef CONFIG_LV_Z_FLUSH_THREAD
K_SEM_DEFINE(flush_complete, 0, 1);
/* Message queue will only ever need to queue one message */
K_MSGQ_DEFINE(flush_queue, sizeof(struct lvgl_display_flush), 1, 1);
void lvgl_flush_thread_entry(void *arg1, void *arg2, void *arg3)
{
struct lvgl_display_flush flush;
struct lvgl_disp_data *data;
while (1) {
k_msgq_get(&flush_queue, &flush, K_FOREVER);
data = (struct lvgl_disp_data *)flush.disp_drv->user_data;
flush.desc.frame_incomplete = !lv_disp_flush_is_last(flush.disp_drv);
display_write(data->display_dev, flush.x, flush.y, &flush.desc,
flush.buf);
lv_disp_flush_ready(flush.disp_drv);
k_sem_give(&flush_complete);
}
}
K_THREAD_DEFINE(lvgl_flush_thread, CONFIG_LV_Z_FLUSH_THREAD_STACK_SIZE, lvgl_flush_thread_entry,
NULL, NULL, NULL, CONFIG_LV_Z_FLUSH_THREAD_PRIORITY, 0, 0);
void lvgl_wait_cb(lv_disp_drv_t *disp_drv)
{
k_sem_take(&flush_complete, K_FOREVER);
}
#endif /* CONFIG_LV_Z_FLUSH_THREAD */
#ifdef CONFIG_LV_Z_USE_ROUNDER_CB
void lvgl_rounder_cb(lv_disp_drv_t *disp_drv, lv_area_t *area)
{
#if CONFIG_LV_Z_AREA_X_ALIGNMENT_WIDTH != 1
__ASSERT(POPCOUNT(CONFIG_LV_Z_AREA_X_ALIGNMENT_WIDTH) == 1, "Invalid X alignment width");
area->x1 &= ~(CONFIG_LV_Z_AREA_X_ALIGNMENT_WIDTH - 1);
area->x2 |= (CONFIG_LV_Z_AREA_X_ALIGNMENT_WIDTH - 1);
#endif
#if CONFIG_LV_Z_AREA_Y_ALIGNMENT_WIDTH != 1
__ASSERT(POPCOUNT(CONFIG_LV_Z_AREA_Y_ALIGNMENT_WIDTH) == 1, "Invalid Y alignment width");
area->y1 &= ~(CONFIG_LV_Z_AREA_Y_ALIGNMENT_WIDTH - 1);
area->y2 |= (CONFIG_LV_Z_AREA_Y_ALIGNMENT_WIDTH - 1);
#endif
}
#else
#define lvgl_rounder_cb NULL
#endif
int set_lvgl_rendering_cb(lv_disp_drv_t *disp_drv)
{
int err = 0;
struct lvgl_disp_data *data = (struct lvgl_disp_data *)disp_drv->user_data;
#ifdef CONFIG_LV_Z_FLUSH_THREAD
disp_drv->wait_cb = lvgl_wait_cb;
#endif
switch (data->cap.current_pixel_format) {
case PIXEL_FORMAT_ARGB_8888:
disp_drv->flush_cb = lvgl_flush_cb_32bit;
disp_drv->rounder_cb = lvgl_rounder_cb;
#ifdef CONFIG_LV_COLOR_DEPTH_32
disp_drv->set_px_cb = NULL;
#else
disp_drv->set_px_cb = lvgl_set_px_cb_32bit;
#endif
break;
case PIXEL_FORMAT_RGB_888:
disp_drv->flush_cb = lvgl_flush_cb_24bit;
disp_drv->rounder_cb = lvgl_rounder_cb;
disp_drv->set_px_cb = lvgl_set_px_cb_24bit;
break;
case PIXEL_FORMAT_RGB_565:
case PIXEL_FORMAT_BGR_565:
disp_drv->flush_cb = lvgl_flush_cb_16bit;
disp_drv->rounder_cb = lvgl_rounder_cb;
#ifdef CONFIG_LV_COLOR_DEPTH_16
disp_drv->set_px_cb = NULL;
#else
disp_drv->set_px_cb = lvgl_set_px_cb_16bit;
#endif
break;
case PIXEL_FORMAT_MONO01:
case PIXEL_FORMAT_MONO10:
disp_drv->flush_cb = lvgl_flush_cb_mono;
disp_drv->rounder_cb = lvgl_rounder_cb_mono;
disp_drv->set_px_cb = lvgl_set_px_cb_mono;
break;
default:
disp_drv->flush_cb = NULL;
disp_drv->rounder_cb = NULL;
disp_drv->set_px_cb = NULL;
err = -ENOTSUP;
break;
}
return err;
}
void lvgl_flush_display(struct lvgl_display_flush *request)
{
#ifdef CONFIG_LV_Z_FLUSH_THREAD
/*
* LVGL will only start a flush once the previous one is complete,
* so we can reset the flush state semaphore here.
*/
k_sem_reset(&flush_complete);
k_msgq_put(&flush_queue, request, K_FOREVER);
/* Explicitly yield, in case the calling thread is a cooperative one */
k_yield();
#else
/* Write directly to the display */
struct lvgl_disp_data *data =
(struct lvgl_disp_data *)request->disp_drv->user_data;
request->desc.frame_incomplete = !lv_disp_flush_is_last(request->disp_drv);
display_write(data->display_dev, request->x, request->y,
&request->desc, request->buf);
lv_disp_flush_ready(request->disp_drv);
#endif
}