mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-10 04:43:33 +00:00
example: LCD and touch panel share the same SPI bus
This commit is contained in:
4
examples/peripherals/lcd/spi_lcd_touch/CMakeLists.txt
Normal file
4
examples/peripherals/lcd/spi_lcd_touch/CMakeLists.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(spi_lcd_touch)
|
96
examples/peripherals/lcd/spi_lcd_touch/README.md
Normal file
96
examples/peripherals/lcd/spi_lcd_touch/README.md
Normal file
@@ -0,0 +1,96 @@
|
||||
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- |
|
||||
|
||||
# SPI LCD and Touch Panel Example
|
||||
|
||||
[esp_lcd](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/lcd.html) provides several panel drivers out-of box, e.g. ST7789, SSD1306, NT35510. However, there're a lot of other panels on the market, it's beyond `esp_lcd` component's responsibility to include them all.
|
||||
|
||||
`esp_lcd` allows user to add their own panel drivers in the project scope (i.e. panel driver can live outside of esp-idf), so that the upper layer code like LVGL porting code can be reused without any modifications, as long as user-implemented panel driver follows the interface defined in the `esp_lcd` component.
|
||||
|
||||
This example shows how to use GC9A01 or ILI9341 display driver from Component manager in esp-idf project. These components are using API provided by `esp_lcd` component. This example will draw a fancy dash board with the LVGL library. For more information about porting the LVGL library, you can also refer to [another lvgl porting example](../i80_controller/README.md).
|
||||
|
||||
## Touch controller STMPE610
|
||||
|
||||
In this example you can enable touch controller STMPE610 connected via SPI. The SPI connection is shared with LCD screen.
|
||||
|
||||
## How to use the example
|
||||
|
||||
### Hardware Required
|
||||
|
||||
* An ESP development board
|
||||
* An GC9A01 or ILI9341 LCD panel, with SPI interface (with/without STMPE610 SPI touch)
|
||||
* An USB cable for power supply and programming
|
||||
|
||||
### Hardware Connection
|
||||
|
||||
The connection between ESP Board and the LCD is as follows:
|
||||
|
||||
```
|
||||
ESP Board GC9A01/ILI9341 Panel + TOUCH
|
||||
┌──────────────────────┐ ┌────────────────────┐
|
||||
│ GND ├─────────────►│ GND │
|
||||
│ │ │ │
|
||||
│ 3V3 ├─────────────►│ VCC │
|
||||
│ │ │ │
|
||||
│ PCLK ├─────────────►│ SCL │
|
||||
│ │ │ │
|
||||
│ MOSI ├─────────────►│ MOSI │
|
||||
│ │ │ │
|
||||
│ MISO |◄─────────────┤ MISO │
|
||||
│ │ │ │
|
||||
│ RST ├─────────────►│ RES │
|
||||
│ │ │ │
|
||||
│ DC ├─────────────►│ DC │
|
||||
│ │ │ │
|
||||
│ LCD CS ├─────────────►│ LCD CS │
|
||||
│ │ │ │
|
||||
│ TOUCH CS ├─────────────►│ TOUCH CS │
|
||||
│ │ │ │
|
||||
│ BK_LIGHT ├─────────────►│ BLK │
|
||||
└──────────────────────┘ └────────────────────┘
|
||||
```
|
||||
|
||||
The GPIO number used by this example can be changed in [lvgl_example_main.c](main/spi_lcd_touch_example_main.c).
|
||||
Especially, please pay attention to the level used to turn on the LCD backlight, some LCD module needs a low level to turn it on, while others take a high level. You can change the backlight level macro `EXAMPLE_LCD_BK_LIGHT_ON_LEVEL` in [lvgl_example_main.c](main/spi_lcd_touch_example_main.c).
|
||||
|
||||
### Build and Flash
|
||||
|
||||
Run `idf.py -p PORT build flash monitor` to build, flash and monitor the project. A fancy animation will show up on the LCD as expected.
|
||||
|
||||
The first time you run `idf.py` for the example will cost extra time as the build system needs to address the component dependencies and downloads the missing components from registry into `managed_components` folder.
|
||||
|
||||
(To exit the serial monitor, type ``Ctrl-]``.)
|
||||
|
||||
See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects.
|
||||
|
||||
### Example Output
|
||||
|
||||
```bash
|
||||
...
|
||||
I (409) cpu_start: Starting scheduler on APP CPU.
|
||||
I (419) example: Turn off LCD backlight
|
||||
I (419) gpio: GPIO[2]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
|
||||
I (429) example: Initialize SPI bus
|
||||
I (439) example: Install panel IO
|
||||
I (439) gpio: GPIO[5]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
|
||||
I (449) example: Install GC9A01 panel driver
|
||||
I (459) gpio: GPIO[3]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
|
||||
I (589) gpio: GPIO[0]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
|
||||
I (589) example: Initialize touch controller STMPE610
|
||||
I (589) STMPE610: TouchPad ID: 0x0811
|
||||
I (589) STMPE610: TouchPad Ver: 0x03
|
||||
I (599) example: Turn on LCD backlight
|
||||
I (599) example: Initialize LVGL library
|
||||
I (609) example: Register display driver to LVGL
|
||||
I (619) example: Install LVGL tick timer
|
||||
I (619) example: Display LVGL Meter Widget
|
||||
...
|
||||
```
|
||||
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
* Why the LCD doesn't light up?
|
||||
* Check the backlight's turn-on level, and update it in `EXAMPLE_LCD_BK_LIGHT_ON_LEVEL`
|
||||
|
||||
For any technical queries, please open an [issue] (https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon.
|
@@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS "spi_lcd_touch_example_main.c" "lvgl_demo_ui.c"
|
||||
INCLUDE_DIRS ".")
|
@@ -0,0 +1,35 @@
|
||||
menu "Example Configuration"
|
||||
|
||||
choice EXAMPLE_LCD_CONTROLLER
|
||||
prompt "LCD controller model"
|
||||
default EXAMPLE_LCD_CONTROLLER_ILI9341
|
||||
help
|
||||
Select LCD controller model
|
||||
|
||||
config EXAMPLE_LCD_CONTROLLER_ILI9341
|
||||
bool "ILI9341"
|
||||
|
||||
config EXAMPLE_LCD_CONTROLLER_GC9A01
|
||||
bool "GC9A01"
|
||||
endchoice
|
||||
|
||||
config EXAMPLE_LCD_TOUCH_ENABLED
|
||||
bool "Enable LCD touch"
|
||||
default n
|
||||
help
|
||||
Enable this option if you wish to use display touch. You can select from touch controllers.
|
||||
|
||||
choice EXAMPLE_LCD_TOUCH_CONTROLLER
|
||||
prompt "LCD touch controller model"
|
||||
depends on EXAMPLE_LCD_TOUCH_ENABLED
|
||||
default EXAMPLE_LCD_TOUCH_CONTROLLER_STMPE610
|
||||
help
|
||||
Select LCD touch controller model
|
||||
|
||||
config EXAMPLE_LCD_TOUCH_CONTROLLER_STMPE610
|
||||
bool "STMPE610"
|
||||
help
|
||||
Touch controller STMPE610 connected via SPI.
|
||||
endchoice
|
||||
|
||||
endmenu
|
@@ -0,0 +1,6 @@
|
||||
dependencies:
|
||||
idf: ">=4.4"
|
||||
lvgl/lvgl: "~8.3.0"
|
||||
esp_lcd_ili9341: "^1.0"
|
||||
esp_lcd_gc9a01: "^1.0"
|
||||
esp_lcd_touch_stmpe610: "^1.0"
|
85
examples/peripherals/lcd/spi_lcd_touch/main/lvgl_demo_ui.c
Normal file
85
examples/peripherals/lcd/spi_lcd_touch/main/lvgl_demo_ui.c
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: CC0-1.0
|
||||
*/
|
||||
|
||||
// This demo UI is adapted from LVGL official example: https://docs.lvgl.io/master/widgets/extra/meter.html#simple-meter
|
||||
|
||||
#include "lvgl.h"
|
||||
|
||||
static lv_obj_t *meter;
|
||||
static lv_obj_t * btn;
|
||||
static lv_disp_rot_t rotation = LV_DISP_ROT_NONE;
|
||||
|
||||
static void set_value(void *indic, int32_t v)
|
||||
{
|
||||
lv_meter_set_indicator_end_value(meter, indic, v);
|
||||
}
|
||||
|
||||
static void btn_cb(lv_event_t * e)
|
||||
{
|
||||
lv_disp_t *disp = lv_event_get_user_data(e);
|
||||
rotation++;
|
||||
if (rotation > LV_DISP_ROT_270) {
|
||||
rotation = LV_DISP_ROT_NONE;
|
||||
}
|
||||
lv_disp_set_rotation(disp, rotation);
|
||||
}
|
||||
|
||||
void example_lvgl_demo_ui(lv_disp_t *disp, lv_obj_t *scr)
|
||||
{
|
||||
meter = lv_meter_create(scr);
|
||||
lv_obj_center(meter);
|
||||
lv_obj_set_size(meter, 200, 200);
|
||||
|
||||
/*Add a scale first*/
|
||||
lv_meter_scale_t *scale = lv_meter_add_scale(meter);
|
||||
lv_meter_set_scale_ticks(meter, scale, 41, 2, 10, lv_palette_main(LV_PALETTE_GREY));
|
||||
lv_meter_set_scale_major_ticks(meter, scale, 8, 4, 15, lv_color_black(), 10);
|
||||
|
||||
lv_meter_indicator_t *indic;
|
||||
|
||||
/*Add a blue arc to the start*/
|
||||
indic = lv_meter_add_arc(meter, scale, 3, lv_palette_main(LV_PALETTE_BLUE), 0);
|
||||
lv_meter_set_indicator_start_value(meter, indic, 0);
|
||||
lv_meter_set_indicator_end_value(meter, indic, 20);
|
||||
|
||||
/*Make the tick lines blue at the start of the scale*/
|
||||
indic = lv_meter_add_scale_lines(meter, scale, lv_palette_main(LV_PALETTE_BLUE), lv_palette_main(LV_PALETTE_BLUE), false, 0);
|
||||
lv_meter_set_indicator_start_value(meter, indic, 0);
|
||||
lv_meter_set_indicator_end_value(meter, indic, 20);
|
||||
|
||||
/*Add a red arc to the end*/
|
||||
indic = lv_meter_add_arc(meter, scale, 3, lv_palette_main(LV_PALETTE_RED), 0);
|
||||
lv_meter_set_indicator_start_value(meter, indic, 80);
|
||||
lv_meter_set_indicator_end_value(meter, indic, 100);
|
||||
|
||||
/*Make the tick lines red at the end of the scale*/
|
||||
indic = lv_meter_add_scale_lines(meter, scale, lv_palette_main(LV_PALETTE_RED), lv_palette_main(LV_PALETTE_RED), false, 0);
|
||||
lv_meter_set_indicator_start_value(meter, indic, 80);
|
||||
lv_meter_set_indicator_end_value(meter, indic, 100);
|
||||
|
||||
/*Add a needle line indicator*/
|
||||
indic = lv_meter_add_needle_line(meter, scale, 4, lv_palette_main(LV_PALETTE_GREY), -10);
|
||||
|
||||
btn = lv_btn_create(scr);
|
||||
lv_obj_t * lbl = lv_label_create(btn);
|
||||
lv_label_set_text_static(lbl, LV_SYMBOL_REFRESH" ROTATE");
|
||||
lv_obj_align(btn, LV_ALIGN_BOTTOM_LEFT, 30, -30);
|
||||
/*Button event*/
|
||||
lv_obj_add_event_cb(btn, btn_cb, LV_EVENT_CLICKED, disp);
|
||||
|
||||
/*Create an animation to set the value*/
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_exec_cb(&a, set_value);
|
||||
lv_anim_set_var(&a, indic);
|
||||
lv_anim_set_values(&a, 0, 100);
|
||||
lv_anim_set_time(&a, 2000);
|
||||
lv_anim_set_repeat_delay(&a, 100);
|
||||
lv_anim_set_playback_time(&a, 500);
|
||||
lv_anim_set_playback_delay(&a, 100);
|
||||
lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE);
|
||||
lv_anim_start(&a);
|
||||
}
|
@@ -0,0 +1,312 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: CC0-1.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
#include "esp_lcd_panel_ops.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/spi_master.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "lvgl.h"
|
||||
|
||||
#if CONFIG_EXAMPLE_LCD_CONTROLLER_ILI9341
|
||||
#include "esp_lcd_ili9341.h"
|
||||
#elif CONFIG_EXAMPLE_LCD_CONTROLLER_GC9A01
|
||||
#include "esp_lcd_gc9a01.h"
|
||||
#endif
|
||||
|
||||
#if CONFIG_EXAMPLE_LCD_TOUCH_CONTROLLER_STMPE610
|
||||
#include "esp_lcd_touch_stmpe610.h"
|
||||
#endif
|
||||
|
||||
static const char *TAG = "example";
|
||||
|
||||
// Using SPI2 in the example
|
||||
#define LCD_HOST SPI2_HOST
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////// Please update the following configuration according to your LCD spec //////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define EXAMPLE_LCD_PIXEL_CLOCK_HZ (20 * 1000 * 1000)
|
||||
#define EXAMPLE_LCD_BK_LIGHT_ON_LEVEL 1
|
||||
#define EXAMPLE_LCD_BK_LIGHT_OFF_LEVEL !EXAMPLE_LCD_BK_LIGHT_ON_LEVEL
|
||||
#define EXAMPLE_PIN_NUM_SCLK 18
|
||||
#define EXAMPLE_PIN_NUM_MOSI 19
|
||||
#define EXAMPLE_PIN_NUM_MISO 21
|
||||
#define EXAMPLE_PIN_NUM_LCD_DC 5
|
||||
#define EXAMPLE_PIN_NUM_LCD_RST 3
|
||||
#define EXAMPLE_PIN_NUM_LCD_CS 4
|
||||
#define EXAMPLE_PIN_NUM_BK_LIGHT 2
|
||||
#define EXAMPLE_PIN_NUM_TOUCH_CS 15
|
||||
|
||||
// The pixel number in horizontal and vertical
|
||||
#if CONFIG_EXAMPLE_LCD_CONTROLLER_ILI9341
|
||||
#define EXAMPLE_LCD_H_RES 240
|
||||
#define EXAMPLE_LCD_V_RES 320
|
||||
#elif CONFIG_EXAMPLE_LCD_CONTROLLER_GC9A01
|
||||
#define EXAMPLE_LCD_H_RES 240
|
||||
#define EXAMPLE_LCD_V_RES 240
|
||||
#endif
|
||||
// Bit number used to represent command and parameter
|
||||
#define EXAMPLE_LCD_CMD_BITS 8
|
||||
#define EXAMPLE_LCD_PARAM_BITS 8
|
||||
|
||||
#define EXAMPLE_LVGL_TICK_PERIOD_MS 2
|
||||
|
||||
|
||||
#if CONFIG_EXAMPLE_LCD_TOUCH_ENABLED
|
||||
esp_lcd_touch_handle_t tp = NULL;
|
||||
#endif
|
||||
|
||||
extern void example_lvgl_demo_ui(lv_disp_t *disp, lv_obj_t *scr);
|
||||
|
||||
static bool example_notify_lvgl_flush_ready(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_io_event_data_t *edata, void *user_ctx)
|
||||
{
|
||||
lv_disp_drv_t *disp_driver = (lv_disp_drv_t *)user_ctx;
|
||||
lv_disp_flush_ready(disp_driver);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void example_lvgl_flush_cb(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map)
|
||||
{
|
||||
esp_lcd_panel_handle_t panel_handle = (esp_lcd_panel_handle_t) drv->user_data;
|
||||
int offsetx1 = area->x1;
|
||||
int offsetx2 = area->x2;
|
||||
int offsety1 = area->y1;
|
||||
int offsety2 = area->y2;
|
||||
// copy a buffer's content to a specific area of the display
|
||||
esp_lcd_panel_draw_bitmap(panel_handle, offsetx1, offsety1, offsetx2 + 1, offsety2 + 1, color_map);
|
||||
}
|
||||
|
||||
/* Rotate display and touch, when rotated screen in LVGL. Called when driver parameters are updated. */
|
||||
static void example_lvgl_port_update_callback(lv_disp_drv_t *drv)
|
||||
{
|
||||
esp_lcd_panel_handle_t panel_handle = (esp_lcd_panel_handle_t) drv->user_data;
|
||||
|
||||
switch (drv->rotated) {
|
||||
case LV_DISP_ROT_NONE:
|
||||
// Rotate LCD display
|
||||
esp_lcd_panel_swap_xy(panel_handle, false);
|
||||
esp_lcd_panel_mirror(panel_handle, true, false);
|
||||
#if CONFIG_EXAMPLE_LCD_TOUCH_ENABLED
|
||||
// Rotate LCD touch
|
||||
esp_lcd_touch_set_mirror_y(tp, false);
|
||||
esp_lcd_touch_set_mirror_x(tp, false);
|
||||
#endif
|
||||
break;
|
||||
case LV_DISP_ROT_90:
|
||||
// Rotate LCD display
|
||||
esp_lcd_panel_swap_xy(panel_handle, true);
|
||||
esp_lcd_panel_mirror(panel_handle, true, true);
|
||||
#if CONFIG_EXAMPLE_LCD_TOUCH_ENABLED
|
||||
// Rotate LCD touch
|
||||
esp_lcd_touch_set_mirror_y(tp, false);
|
||||
esp_lcd_touch_set_mirror_x(tp, false);
|
||||
#endif
|
||||
break;
|
||||
case LV_DISP_ROT_180:
|
||||
// Rotate LCD display
|
||||
esp_lcd_panel_swap_xy(panel_handle, false);
|
||||
esp_lcd_panel_mirror(panel_handle, false, true);
|
||||
#if CONFIG_EXAMPLE_LCD_TOUCH_ENABLED
|
||||
// Rotate LCD touch
|
||||
esp_lcd_touch_set_mirror_y(tp, false);
|
||||
esp_lcd_touch_set_mirror_x(tp, false);
|
||||
#endif
|
||||
break;
|
||||
case LV_DISP_ROT_270:
|
||||
// Rotate LCD display
|
||||
esp_lcd_panel_swap_xy(panel_handle, true);
|
||||
esp_lcd_panel_mirror(panel_handle, false, false);
|
||||
#if CONFIG_EXAMPLE_LCD_TOUCH_ENABLED
|
||||
// Rotate LCD touch
|
||||
esp_lcd_touch_set_mirror_y(tp, false);
|
||||
esp_lcd_touch_set_mirror_x(tp, false);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_EXAMPLE_LCD_TOUCH_ENABLED
|
||||
static void example_lvgl_touch_cb(lv_indev_drv_t * drv, lv_indev_data_t * data)
|
||||
{
|
||||
uint16_t touchpad_x[1] = {0};
|
||||
uint16_t touchpad_y[1] = {0};
|
||||
uint8_t touchpad_cnt = 0;
|
||||
|
||||
/* Read touch controller data */
|
||||
esp_lcd_touch_read_data(drv->user_data);
|
||||
|
||||
/* Get coordinates */
|
||||
bool touchpad_pressed = esp_lcd_touch_get_coordinates(drv->user_data, touchpad_x, touchpad_y, NULL, &touchpad_cnt, 1);
|
||||
|
||||
if (touchpad_pressed && touchpad_cnt > 0) {
|
||||
data->point.x = touchpad_x[0];
|
||||
data->point.y = touchpad_y[0];
|
||||
data->state = LV_INDEV_STATE_PRESSED;
|
||||
} else {
|
||||
data->state = LV_INDEV_STATE_RELEASED;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void example_increase_lvgl_tick(void *arg)
|
||||
{
|
||||
/* Tell LVGL how many milliseconds has elapsed */
|
||||
lv_tick_inc(EXAMPLE_LVGL_TICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
static lv_disp_draw_buf_t disp_buf; // contains internal graphic buffer(s) called draw buffer(s)
|
||||
static lv_disp_drv_t disp_drv; // contains callback functions
|
||||
|
||||
ESP_LOGI(TAG, "Turn off LCD backlight");
|
||||
gpio_config_t bk_gpio_config = {
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pin_bit_mask = 1ULL << EXAMPLE_PIN_NUM_BK_LIGHT
|
||||
};
|
||||
ESP_ERROR_CHECK(gpio_config(&bk_gpio_config));
|
||||
|
||||
ESP_LOGI(TAG, "Initialize SPI bus");
|
||||
spi_bus_config_t buscfg = {
|
||||
.sclk_io_num = EXAMPLE_PIN_NUM_SCLK,
|
||||
.mosi_io_num = EXAMPLE_PIN_NUM_MOSI,
|
||||
.miso_io_num = EXAMPLE_PIN_NUM_MISO,
|
||||
.quadwp_io_num = -1,
|
||||
.quadhd_io_num = -1,
|
||||
.max_transfer_sz = EXAMPLE_LCD_H_RES * 80 * sizeof(uint16_t),
|
||||
};
|
||||
ESP_ERROR_CHECK(spi_bus_initialize(LCD_HOST, &buscfg, SPI_DMA_CH_AUTO));
|
||||
|
||||
ESP_LOGI(TAG, "Install panel IO");
|
||||
esp_lcd_panel_io_handle_t io_handle = NULL;
|
||||
esp_lcd_panel_io_spi_config_t io_config = {
|
||||
.dc_gpio_num = EXAMPLE_PIN_NUM_LCD_DC,
|
||||
.cs_gpio_num = EXAMPLE_PIN_NUM_LCD_CS,
|
||||
.pclk_hz = EXAMPLE_LCD_PIXEL_CLOCK_HZ,
|
||||
.lcd_cmd_bits = EXAMPLE_LCD_CMD_BITS,
|
||||
.lcd_param_bits = EXAMPLE_LCD_PARAM_BITS,
|
||||
.spi_mode = 0,
|
||||
.trans_queue_depth = 10,
|
||||
.on_color_trans_done = example_notify_lvgl_flush_ready,
|
||||
.user_ctx = &disp_drv,
|
||||
};
|
||||
// Attach the LCD to the SPI bus
|
||||
ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)LCD_HOST, &io_config, &io_handle));
|
||||
|
||||
ESP_LOGI(TAG, "Install GC9A01 panel driver");
|
||||
esp_lcd_panel_handle_t panel_handle = NULL;
|
||||
esp_lcd_panel_dev_config_t panel_config = {
|
||||
.reset_gpio_num = EXAMPLE_PIN_NUM_LCD_RST,
|
||||
#if CONFIG_EXAMPLE_LCD_CONTROLLER_ILI9341
|
||||
.color_space = ESP_LCD_COLOR_SPACE_RGB,
|
||||
#elif CONFIG_EXAMPLE_LCD_CONTROLLER_GC9A01
|
||||
.color_space = ESP_LCD_COLOR_SPACE_BGR,
|
||||
#endif
|
||||
.bits_per_pixel = 16,
|
||||
};
|
||||
#if CONFIG_EXAMPLE_LCD_CONTROLLER_ILI9341
|
||||
ESP_ERROR_CHECK(esp_lcd_new_panel_ili9341(io_handle, &panel_config, &panel_handle));
|
||||
#elif CONFIG_EXAMPLE_LCD_CONTROLLER_GC9A01
|
||||
ESP_ERROR_CHECK(esp_lcd_new_panel_gc9a01(io_handle, &panel_config, &panel_handle));
|
||||
#endif
|
||||
|
||||
ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle));
|
||||
ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle));
|
||||
#if CONFIG_EXAMPLE_LCD_CONTROLLER_GC9A01
|
||||
ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel_handle, true));
|
||||
#endif
|
||||
ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, true, false));
|
||||
|
||||
// user can flush pre-defined pattern to the screen before we turn on the screen or backlight
|
||||
ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true));
|
||||
|
||||
#if CONFIG_EXAMPLE_LCD_TOUCH_ENABLED
|
||||
esp_lcd_panel_io_handle_t tp_io_handle = NULL;
|
||||
esp_lcd_panel_io_spi_config_t tp_io_config = ESP_LCD_TOUCH_IO_SPI_STMPE610_CONFIG(EXAMPLE_PIN_NUM_TOUCH_CS);
|
||||
// Attach the TOUCH to the SPI bus
|
||||
ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)LCD_HOST, &tp_io_config, &tp_io_handle));
|
||||
|
||||
esp_lcd_touch_config_t tp_cfg = {
|
||||
.x_max = EXAMPLE_LCD_H_RES,
|
||||
.y_max = EXAMPLE_LCD_V_RES,
|
||||
.rst_gpio_num = -1,
|
||||
.int_gpio_num = -1,
|
||||
.flags = {
|
||||
.swap_xy = 0,
|
||||
.mirror_x = 0,
|
||||
.mirror_y = 0,
|
||||
},
|
||||
};
|
||||
|
||||
#if CONFIG_EXAMPLE_LCD_TOUCH_CONTROLLER_STMPE610
|
||||
ESP_LOGI(TAG, "Initialize touch controller STMPE610");
|
||||
ESP_ERROR_CHECK(esp_lcd_touch_new_spi_stmpe610(tp_io_handle, &tp_cfg, &tp));
|
||||
#endif // CONFIG_EXAMPLE_LCD_TOUCH_CONTROLLER_STMPE610
|
||||
#endif // CONFIG_EXAMPLE_LCD_TOUCH_ENABLED
|
||||
|
||||
ESP_LOGI(TAG, "Turn on LCD backlight");
|
||||
gpio_set_level(EXAMPLE_PIN_NUM_BK_LIGHT, EXAMPLE_LCD_BK_LIGHT_ON_LEVEL);
|
||||
|
||||
ESP_LOGI(TAG, "Initialize LVGL library");
|
||||
lv_init();
|
||||
// alloc draw buffers used by LVGL
|
||||
// it's recommended to choose the size of the draw buffer(s) to be at least 1/10 screen sized
|
||||
lv_color_t *buf1 = heap_caps_malloc(EXAMPLE_LCD_H_RES * 20 * sizeof(lv_color_t), MALLOC_CAP_DMA);
|
||||
assert(buf1);
|
||||
lv_color_t *buf2 = heap_caps_malloc(EXAMPLE_LCD_H_RES * 20 * sizeof(lv_color_t), MALLOC_CAP_DMA);
|
||||
assert(buf2);
|
||||
// initialize LVGL draw buffers
|
||||
lv_disp_draw_buf_init(&disp_buf, buf1, buf2, EXAMPLE_LCD_H_RES * 20);
|
||||
|
||||
ESP_LOGI(TAG, "Register display driver to LVGL");
|
||||
lv_disp_drv_init(&disp_drv);
|
||||
disp_drv.hor_res = EXAMPLE_LCD_H_RES;
|
||||
disp_drv.ver_res = EXAMPLE_LCD_V_RES;
|
||||
disp_drv.flush_cb = example_lvgl_flush_cb;
|
||||
disp_drv.drv_update_cb = example_lvgl_port_update_callback;
|
||||
disp_drv.draw_buf = &disp_buf;
|
||||
disp_drv.user_data = panel_handle;
|
||||
lv_disp_t *disp = lv_disp_drv_register(&disp_drv);
|
||||
|
||||
ESP_LOGI(TAG, "Install LVGL tick timer");
|
||||
// Tick interface for LVGL (using esp_timer to generate 2ms periodic event)
|
||||
const esp_timer_create_args_t lvgl_tick_timer_args = {
|
||||
.callback = &example_increase_lvgl_tick,
|
||||
.name = "lvgl_tick"
|
||||
};
|
||||
esp_timer_handle_t lvgl_tick_timer = NULL;
|
||||
ESP_ERROR_CHECK(esp_timer_create(&lvgl_tick_timer_args, &lvgl_tick_timer));
|
||||
ESP_ERROR_CHECK(esp_timer_start_periodic(lvgl_tick_timer, EXAMPLE_LVGL_TICK_PERIOD_MS * 1000));
|
||||
|
||||
#if CONFIG_EXAMPLE_LCD_TOUCH_ENABLED
|
||||
static lv_indev_drv_t indev_drv; // Input device driver (Touch)
|
||||
lv_indev_drv_init(&indev_drv);
|
||||
indev_drv.type = LV_INDEV_TYPE_POINTER;
|
||||
indev_drv.disp = disp;
|
||||
indev_drv.read_cb = example_lvgl_touch_cb;
|
||||
indev_drv.user_data = tp;
|
||||
|
||||
lv_indev_drv_register(&indev_drv);
|
||||
#endif
|
||||
|
||||
ESP_LOGI(TAG, "Display LVGL Meter Widget");
|
||||
lv_obj_t *scr = lv_disp_get_scr_act(disp);
|
||||
example_lvgl_demo_ui(disp, scr);
|
||||
|
||||
while (1) {
|
||||
// raise the task priority of LVGL and/or reduce the handler period can improve the performance
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
// The task running lv_timer_handler should have lower priority than that running `lv_tick_inc`
|
||||
lv_timer_handler();
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
CONFIG_LV_USE_USER_DATA=y
|
||||
CONFIG_LV_COLOR_16_SWAP=y
|
||||
CONFIG_LV_COLOR_DEPTH_16=y
|
Reference in New Issue
Block a user