Skip to content

Commit 8ebd41e

Browse files
authored
Merge pull request #175 from rzeldent/lvgl9
LVGL v9.1 (although is pinned to 9.2 from repo). Reason to pin is that the PlatformIO registry does not have a version greater than LVGL 9.1. The version 9.1 has an issue with rotating the screen.
2 parents 28ed913 + c465c7e commit 8ebd41e

17 files changed

+1000
-634
lines changed

README.md

+143-113
Large diffs are not rendered by default.

include/esp32_smartdisplay.h

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33

44
#include <Arduino.h>
55
#include <lvgl.h>
6+
#include <display/lv_display_private.h>
7+
#include <misc/lv_timer_private.h>
8+
#include <indev/lv_indev_private.h>
69

710
// Use last PWM_CHANNEL for backlight
811
#define PWM_CHANNEL_BCKL (SOC_LEDC_CHANNEL_NUM - 1)

library.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
22
"$schema": "https://raw.githubusercontent.com/platformio/platformio-core/develop/platformio/assets/schema/library.json",
33
"name": "esp32_smartdisplay",
4-
"version": "2.0.10",
5-
"description": "LVGL driver for Sunton ESP32 Cheap Yellow Display display boards",
4+
"version": "3.0.0",
5+
"description": "LVGL v9.1 driver for Sunton ESP32 Cheap Yellow Display display boards",
66
"keywords": "LVGL Sunton CYD LCD TFT Touch",
77
"repository": {
88
"type": "git",
@@ -35,6 +35,6 @@
3535
"frameworks": "arduino",
3636
"platforms": "espressif32",
3737
"dependencies": {
38-
"lvgl/lvgl": "^8.4.0"
38+
"lvgl/lvgl": "https://github.com/lvgl/lvgl.git#d39fc17"
3939
}
4040
}

platformio.ini

+3-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@ build_flags =
5757
'-D ESP_LCD_PANEL_IO_ADDITIONS_VER_PATCH=1'
5858

5959
lib_deps =
60-
lvgl/lvgl@^8.4.0
60+
# Use direct git because rotation commit is after 9.1. So pin the build to v9.2
61+
https://github.com/lvgl/lvgl.git#d39fc17
62+
#lvgl/lvgl@^9.1.0
6163
# The platformio.test_dir contains the test_main.cpp just to have an setup() and loop() function
6264
# so it will compile
6365
${platformio.test_dir}

src/esp32_smartdisplay.c

+71-64
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,39 @@
1010
#define BRIGHTNESS_DARK_ZONE 250
1111

1212
// Functions to be defined in the tft/touch driver
13-
extern void lvgl_lcd_init(lv_disp_drv_t *disp_drv);
14-
extern void lvgl_touch_init(lv_indev_drv_t *disp_drv);
13+
extern lv_display_t *lvgl_lcd_init();
14+
extern lv_indev_t *lvgl_touch_init();
1515

16-
lv_disp_drv_t disp_drv;
17-
lv_timer_t *update_brightness_timer;
16+
lv_display_t *display;
1817

1918
#ifdef BOARD_HAS_TOUCH
20-
lv_indev_drv_t indev_drv;
19+
lv_indev_t *indev;
2120
touch_calibration_data_t touch_calibration_data;
22-
void (*driver_touch_read_cb)(struct _lv_indev_drv_t *indev_drv, lv_indev_data_t *data);
21+
void (*driver_touch_read_cb)(lv_indev_t *indev, lv_indev_data_t *data);
2322
#endif
2423

24+
void lvgl_display_resolution_changed_callback(lv_event_t *drv);
25+
26+
lv_timer_t *update_brightness_timer;
27+
2528
#ifdef LV_USE_LOG
26-
void lvgl_log(const char *buf)
29+
void lvgl_log(lv_log_level_t level, const char *buf)
2730
{
28-
log_printf("%s", buf);
31+
switch (level)
32+
{
33+
case LV_LOG_LEVEL_TRACE:
34+
log_printf("%s", buf);
35+
break;
36+
case LV_LOG_LEVEL_INFO:
37+
log_i("%s", buf);
38+
break;
39+
case LV_LOG_LEVEL_WARN:
40+
log_w("%s", buf);
41+
break;
42+
case LV_LOG_LEVEL_ERROR:
43+
log_e("%s", buf);
44+
break;
45+
}
2946
}
3047
#endif
3148

@@ -34,9 +51,9 @@ void smartdisplay_lcd_set_backlight(float duty)
3451
{
3552
log_v("duty:%2f", duty);
3653

37-
if (duty > 1.0)
54+
if (duty > 1.0f)
3855
duty = 1.0f;
39-
if (duty < 0.0)
56+
if (duty < 0.0f)
4057
duty = 0.0f;
4158
#if ESP_ARDUINO_VERSION_MAJOR >= 3
4259
ledcWrite(GPIO_BCKL, duty * PWM_MAX_BCKL);
@@ -74,7 +91,7 @@ void adaptive_brightness(lv_timer_t *timer)
7491

7592
void smartdisplay_lcd_set_brightness_cb(smartdisplay_lcd_adaptive_brightness_cb_t cb, uint interval)
7693
{
77-
log_v("adaptive_brightness_cb:0x%08x, interval:%d", cb, interval);
94+
log_v("adaptive_brightness_cb:0x%08x, interval:%u", cb, interval);
7895

7996
// Delete current timer if any
8097
if (update_brightness_timer)
@@ -100,12 +117,12 @@ void smartdisplay_led_set_rgb(bool r, bool g, bool b)
100117

101118
#ifdef BOARD_HAS_TOUCH
102119
// See: https://www.maximintegrated.com/en/design/technical-documents/app-notes/5/5296.html
103-
void lvgl_touch_calibration_transform(lv_indev_drv_t *disp_drv, lv_indev_data_t *data)
120+
void lvgl_touch_calibration_transform(lv_indev_t *indev, lv_indev_data_t *data)
104121
{
105-
log_v("disp_drv:0x%08x, data:0x%08x", disp_drv, data);
122+
log_v("indev:0x%08x, data:0x%08x", indev, data);
106123

107124
// Call low level read from the driver
108-
driver_touch_read_cb(disp_drv, data);
125+
driver_touch_read_cb(indev, data);
109126
// Check if transformation is required
110127
if (touch_calibration_data.valid && data->state == LV_INDEV_STATE_PRESSED)
111128
{
@@ -137,37 +154,6 @@ touch_calibration_data_t smartdisplay_compute_touch_calibration(const lv_point_t
137154
};
138155
#endif
139156

140-
// Called when driver parameters are updated (rotation)
141-
// Top of the display is top left when connector is at the bottom
142-
// The rotation values are relative to how you would rotate the physical display in the clockwise direction.
143-
// Thus, LV_DISP_ROT_90 means you rotate the hardware 90 degrees clockwise, and the display rotates 90 degrees counterclockwise to compensate.
144-
void lvgl_update_callback(lv_disp_drv_t *drv)
145-
{
146-
if (drv->sw_rotate == false)
147-
{
148-
const esp_lcd_panel_handle_t panel_handle = disp_drv.user_data;
149-
switch (drv->rotated)
150-
{
151-
case LV_DISP_ROT_NONE:
152-
ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel_handle, DISPLAY_SWAP_XY));
153-
ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y));
154-
break;
155-
case LV_DISP_ROT_90:
156-
ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel_handle, !DISPLAY_SWAP_XY));
157-
ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, DISPLAY_MIRROR_X, !DISPLAY_MIRROR_Y));
158-
break;
159-
case LV_DISP_ROT_180:
160-
ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel_handle, DISPLAY_SWAP_XY));
161-
ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, !DISPLAY_MIRROR_X, !DISPLAY_MIRROR_Y));
162-
break;
163-
case LV_DISP_ROT_270:
164-
ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel_handle, !DISPLAY_SWAP_XY));
165-
ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, !DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y));
166-
break;
167-
}
168-
}
169-
}
170-
171157
void smartdisplay_init()
172158
{
173159
log_d("smartdisplay_init");
@@ -206,31 +192,52 @@ void smartdisplay_init()
206192
ledcAttachPin(GPIO_BCKL, PWM_CHANNEL_BCKL);
207193
#endif
208194
// Setup TFT display
209-
lv_disp_drv_init(&disp_drv);
210-
disp_drv.hor_res = DISPLAY_WIDTH;
211-
disp_drv.ver_res = DISPLAY_HEIGHT;
212-
// Create drawBuffer
213-
disp_drv.draw_buf = (lv_disp_draw_buf_t *)malloc(sizeof(lv_disp_draw_buf_t));
214-
void *drawBuffer = heap_caps_malloc(sizeof(lv_color_t) * LVGL_BUFFER_PIXELS, LVGL_BUFFER_MALLOC_FLAGS);
215-
lv_disp_draw_buf_init(disp_drv.draw_buf, drawBuffer, NULL, LVGL_BUFFER_PIXELS);
216-
// Register callback for changes to the driver parameters (rotation!)
217-
disp_drv.drv_update_cb = lvgl_update_callback;
218-
// Initialize specific driver
219-
lvgl_lcd_init(&disp_drv);
220-
__attribute__((unused)) lv_disp_t *display = lv_disp_drv_register(&disp_drv);
221-
// Clear screen
195+
display = lvgl_lcd_init();
196+
// Register callback for hardware rotation
197+
if (!display->sw_rotate)
198+
lv_display_add_event_cb(display, lvgl_display_resolution_changed_callback, LV_EVENT_RESOLUTION_CHANGED, NULL);
199+
200+
// Clear screen
222201
lv_obj_clean(lv_scr_act());
223202
// Turn backlight on (50%)
224203
smartdisplay_lcd_set_backlight(0.5f);
225204

226205
// If there is a touch controller defined
227206
#ifdef BOARD_HAS_TOUCH
228207
// Setup touch
229-
lv_indev_drv_init(&indev_drv);
230-
indev_drv.disp = display;
231-
lvgl_touch_init(&indev_drv);
232-
driver_touch_read_cb = indev_drv.read_cb;
233-
indev_drv.read_cb = lvgl_touch_calibration_transform;
234-
lv_indev_drv_register(&indev_drv);
208+
indev = lvgl_touch_init();
209+
indev->disp = display;
210+
// Intercept callback
211+
driver_touch_read_cb = indev->read_cb;
212+
indev->read_cb = lvgl_touch_calibration_transform;
213+
lv_indev_enable(indev, true);
235214
#endif
215+
}
216+
217+
// Called when driver resolution is updated (including rotation)
218+
// Top of the display is top left when connector is at the bottom
219+
// The rotation values are relative to how you would rotate the physical display in the clockwise direction.
220+
// Thus, LV_DISPLAY_ROTATION_90 means you rotate the hardware 90 degrees clockwise, and the display rotates 90 degrees counterclockwise to compensate.
221+
void lvgl_display_resolution_changed_callback(lv_event_t *event)
222+
{
223+
const esp_lcd_panel_handle_t panel_handle = display->user_data;
224+
switch (display->rotation)
225+
{
226+
case LV_DISPLAY_ROTATION_0:
227+
ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel_handle, DISPLAY_SWAP_XY));
228+
ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y));
229+
break;
230+
case LV_DISPLAY_ROTATION_90:
231+
ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel_handle, !DISPLAY_SWAP_XY));
232+
ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, DISPLAY_MIRROR_X, !DISPLAY_MIRROR_Y));
233+
break;
234+
case LV_DISPLAY_ROTATION_180:
235+
ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel_handle, DISPLAY_SWAP_XY));
236+
ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, !DISPLAY_MIRROR_X, !DISPLAY_MIRROR_Y));
237+
break;
238+
case LV_DISPLAY_ROTATION_270:
239+
ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel_handle, !DISPLAY_SWAP_XY));
240+
ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, !DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y));
241+
break;
242+
}
236243
}

src/lvgl_panel_gc9a01_spi.c

+29-21
Original file line numberDiff line numberDiff line change
@@ -10,33 +10,39 @@ bool gc9a01_color_trans_done(esp_lcd_panel_io_handle_t panel_io_handle, esp_lcd_
1010
{
1111
log_v("panel_io_handle:0x%08x, panel_io_event_data:%0x%08x, user_ctx:0x%08x", panel_io_handle, panel_io_event_data, user_ctx);
1212

13-
lv_disp_drv_t *disp_driver = user_ctx;
14-
lv_disp_flush_ready(disp_driver);
13+
lv_display_t *display = user_ctx;
14+
lv_display_flush_ready(display);
1515
return false;
1616
}
1717

18-
void gc9a01_lv_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map)
18+
void gc9a01_lv_flush(lv_display_t *display, const lv_area_t *area, uint8_t *px_map)
1919
{
20-
log_v("drv:0x%08x, area:%0x%08x, color_map:0x%08x", drv, area, color_map);
20+
log_v("display:0x%08x, area:%0x%08x, color_map:0x%08x", display, area, px_map);
2121

22-
esp_lcd_panel_handle_t panel_handle = drv->user_data;
23-
#if LV_COLOR_16_SWAP != 1
24-
#warning "LV_COLOR_16_SWAP should be 1 for max performance"
25-
ushort pixels = lv_area_get_size(area);
26-
lv_color16_t *p = color_map;
22+
esp_lcd_panel_handle_t panel_handle = display->user_data;
23+
uint32_t pixels = lv_area_get_size(area);
24+
uint16_t *p = (uint16_t *)px_map;
2725
while (pixels--)
28-
p++->full = (uint16_t)((p->full >> 8) | (p->full << 8));
29-
#endif
30-
ESP_ERROR_CHECK(esp_lcd_panel_draw_bitmap(panel_handle, area->x1, area->y1, area->x2 + 1, area->y2 + 1, color_map));
26+
{
27+
*p = (uint16_t)((*p >> 8) | (*p << 8));
28+
p++;
29+
}
30+
31+
ESP_ERROR_CHECK(esp_lcd_panel_draw_bitmap(panel_handle, area->x1, area->y1, area->x2 + 1, area->y2 + 1, px_map));
3132
};
3233

33-
void lvgl_lcd_init(lv_disp_drv_t *drv)
34+
lv_display_t *lvgl_lcd_init()
3435
{
35-
log_v("disp_drv:0x%08x", drv);
36+
lv_display_t *display = lv_display_create(DISPLAY_WIDTH, DISPLAY_HEIGHT);
37+
log_v("display:0x%08x", display);
38+
// Create drawBuffer
39+
uint32_t drawBufferSize = sizeof(lv_color_t) * LVGL_BUFFER_PIXELS;
40+
void *drawBuffer = heap_caps_malloc(drawBufferSize, LVGL_BUFFER_MALLOC_FLAGS);
41+
lv_display_set_buffers(display, drawBuffer, NULL, drawBufferSize, LV_DISPLAY_RENDER_MODE_PARTIAL);
3642

3743
// Hardware rotation is supported
38-
drv->sw_rotate = 0;
39-
drv->rotated = LV_DISP_ROT_NONE;
44+
display->sw_rotate = 0;
45+
display->rotation = LV_DISPLAY_ROTATION_0;
4046

4147
// Create SPI bus
4248
const spi_bus_config_t spi_bus_config = {
@@ -58,7 +64,7 @@ void lvgl_lcd_init(lv_disp_drv_t *drv)
5864
.spi_mode = GC9A01_SPI_CONFIG_SPI_MODE,
5965
.pclk_hz = GC9A01_SPI_CONFIG_PCLK_HZ,
6066
.trans_queue_depth = GC9A01_SPI_CONFIG_TRANS_QUEUE_DEPTH,
61-
.user_ctx = drv,
67+
.user_ctx = display,
6268
.on_color_trans_done = gc9a01_color_trans_done,
6369
.lcd_cmd_bits = GC9A01_SPI_CONFIG_LCD_CMD_BITS,
6470
.lcd_param_bits = GC9A01_SPI_CONFIG_LCD_PARAM_BITS,
@@ -91,17 +97,19 @@ void lvgl_lcd_init(lv_disp_drv_t *drv)
9197
#if (DISPLAY_SWAP_XY)
9298
ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel_handle, DISPLAY_SWAP_XY));
9399
#endif
94-
#if (DISPLAY_MIRROR_X || DISPLAY_MIRROR_Y)
100+
#if (DISPLAY_MIRROR_X || DISPLAY_MIRROR_Y)
95101
ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y));
96-
#endif
102+
#endif
97103
#if (DISPLAY_GAP_X || DISPLAY_GAP_Y)
98104
ESP_ERROR_CHECK(esp_lcd_panel_set_gap(panel_handle, DISPLAY_GAP_X, DISPLAY_GAP_Y));
99105
#endif
100106
// Turn display on
101107
ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true));
102108

103-
drv->user_data = panel_handle;
104-
drv->flush_cb = gc9a01_lv_flush;
109+
display->user_data = panel_handle;
110+
display->flush_cb = gc9a01_lv_flush;
111+
112+
return display;
105113
}
106114

107115
#endif

0 commit comments

Comments
 (0)