Add LVGL and set up with display/touch drivers
This commit is contained in:
+53
-1
@@ -1,4 +1,19 @@
|
||||
dependencies:
|
||||
atanisoft/esp_lcd_touch_xpt2046:
|
||||
component_hash:
|
||||
7e6381b67b6e487379118368b8e91624dc87036ef5734818de1db9eb35697998
|
||||
dependencies:
|
||||
- name: espressif/esp_lcd_touch
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: '>=1.0.4'
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.0.6
|
||||
espressif/cmake_utilities:
|
||||
component_hash:
|
||||
351350613ceafba240b761b4ea991e0f231ac7a9f59a9ee901f751bddc0bb18f
|
||||
@@ -25,13 +40,50 @@ dependencies:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 2.0.1
|
||||
espressif/esp_lcd_touch:
|
||||
component_hash:
|
||||
3f85a7d95af876f1a6ecca8eb90a81614890d0f03a038390804e5a77e2caf862
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4.2'
|
||||
source:
|
||||
registry_url: https://components.espressif.com
|
||||
type: service
|
||||
version: 1.2.1
|
||||
espressif/esp_lvgl_port:
|
||||
component_hash:
|
||||
f872401524cb645ee6ff1c9242d44fb4ddcfd4d37d7be8b9ed3f4e85a404efcd
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.1'
|
||||
- name: lvgl/lvgl
|
||||
registry_url: https://components.espressif.com
|
||||
require: public
|
||||
version: '>=8,<10'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 2.7.0
|
||||
idf:
|
||||
source:
|
||||
type: idf
|
||||
version: 5.5.1
|
||||
lvgl/lvgl:
|
||||
component_hash:
|
||||
17e68bfd21f0edf4c3ee838e2273da840bf3930e5dbc3bfa6c1190c3aed41f9f
|
||||
dependencies: []
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 9.4.0
|
||||
direct_dependencies:
|
||||
- atanisoft/esp_lcd_touch_xpt2046
|
||||
- espressif/esp_lcd_ili9341
|
||||
- espressif/esp_lvgl_port
|
||||
- idf
|
||||
manifest_hash: 5c04a0422ee419cb472e6df05c9d4292985ae0cd069ef8404da0161609cc967c
|
||||
- lvgl/lvgl
|
||||
manifest_hash: d2b549f17124d3d38e4add4614fb10956ada1a576e4c5f6a623ea3756bcd3ba5
|
||||
target: esp32
|
||||
version: 2.0.0
|
||||
|
||||
+2
-1
@@ -1,3 +1,4 @@
|
||||
idf_component_register(SRCS "spincoat-plater-firmware.c" "dshot_esc_encoder.c" "display.c"
|
||||
PRIV_REQUIRES esp_driver_rmt esp_driver_gpio esp_driver_uart esp_driver_spi esp_lcd unity
|
||||
PRIV_REQUIRES esp_driver_rmt esp_driver_gpio esp_driver_uart esp_driver_spi
|
||||
esp_lcd unity lvgl esp_lvgl_port esp_lcd_touch_xpt2046
|
||||
INCLUDE_DIRS ".")
|
||||
|
||||
+34
-6
@@ -9,36 +9,64 @@ menu "Pin Mapping Configuration"
|
||||
default 27
|
||||
help
|
||||
This is the pin used for receiving UART telemetry from the ESC.
|
||||
config TFT_MISO_PIN
|
||||
config TFT_MISO
|
||||
int "SPI LCD MISO pin"
|
||||
default 12
|
||||
help
|
||||
This is the pin for MISO on the SPI LCD.
|
||||
config TFT_MOSI_PIN
|
||||
config TFT_MOSI
|
||||
int "SPI LCD MOSI pin"
|
||||
default 13
|
||||
help
|
||||
This is the pin for MOSI on the SPI LCD.
|
||||
config TFT_SCKL_PIN
|
||||
config TFT_SCKL
|
||||
int "SPI LCD SCKL pin"
|
||||
default 14
|
||||
help
|
||||
This is the pin for SCKL on the SPI LCD.
|
||||
config TFT_CS_PIN
|
||||
config TFT_CS
|
||||
int "SPI LCD CS pin"
|
||||
default 15
|
||||
help
|
||||
This is the pin for CS on the SPI LCD.
|
||||
config TFT_DC_PIN
|
||||
config TFT_DC
|
||||
int "SPI LCD DC pin"
|
||||
default 2
|
||||
help
|
||||
This is the pin for DC on the SPI LCD.
|
||||
config TFT_BL_PIN
|
||||
config TFT_BL
|
||||
int "SPI LCD BL (backlight) pin"
|
||||
default 21
|
||||
help
|
||||
This is the pin for backlight control on the SPI LCD.
|
||||
|
||||
|
||||
config TOUCH_IRQ
|
||||
int "SPI touchscreen IRQ pin"
|
||||
default 36
|
||||
help
|
||||
This is the pin for IRQ on the SPI touchscreen.
|
||||
config TOUCH_MOSI
|
||||
int "SPI touchscreen MOSI pin"
|
||||
default 32
|
||||
help
|
||||
This is the pin for MOSI on the SPI touchscreen.
|
||||
config TOUCH_MISO
|
||||
int "SPI touchscreen MISO pin"
|
||||
default 39
|
||||
help
|
||||
This is the pin for MISO on the SPI touchscreen.
|
||||
config TOUCH_CLK
|
||||
int "SPI touchscreen CLK pin"
|
||||
default 25
|
||||
help
|
||||
This is the pin for CLK on the SPI touchscreen.
|
||||
config TOUCH_CS
|
||||
int "SPI touchscreen CS pin"
|
||||
default 33
|
||||
help
|
||||
This is the pin for CS on the SPI touchscreen.
|
||||
|
||||
config TFT_HRES
|
||||
int "The horizontal resolution of the TFT display"
|
||||
default 320
|
||||
|
||||
+167
-37
@@ -18,9 +18,17 @@
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "esp_lcd_panel_commands.h"
|
||||
#include "esp_lcd_ili9341.h"
|
||||
#include "esp_lcd_touch_xpt2046.h"
|
||||
|
||||
#include "lvgl.h"
|
||||
#include "esp_lvgl_port.h"
|
||||
|
||||
SemaphoreHandle_t refresh_finish = NULL;
|
||||
|
||||
esp_lcd_panel_io_handle_t io_handle = NULL;
|
||||
esp_lcd_panel_handle_t panel_handle = NULL;
|
||||
esp_lcd_touch_handle_t tp = NULL;
|
||||
|
||||
static const char * TAG = "spincoat-plater-firmware/display";
|
||||
|
||||
/**
|
||||
@@ -36,29 +44,108 @@ IRAM_ATTR static bool notify_refresh_ready(esp_lcd_panel_io_handle_t panel_io, e
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a test bitmap of stripes of colors to the LCD.
|
||||
* Callback for LVGL pointer input device, it reads from the esp_lcd_touch driver and updates
|
||||
* the LVGL internal state for event handling.
|
||||
*/
|
||||
void test_draw_bitmap(esp_lcd_panel_handle_t panel_handle)
|
||||
{
|
||||
refresh_finish = xSemaphoreCreateBinary();
|
||||
TEST_ASSERT_NOT_NULL(refresh_finish);
|
||||
void touch_driver_read(lv_indev_t * indev, lv_indev_data_t * data) {
|
||||
ESP_ERROR_CHECK(esp_lcd_touch_read_data(tp));
|
||||
|
||||
uint16_t row_line = TFT_VRES / TFT_BPP;
|
||||
uint8_t byte_per_pixel = TFT_BPP / 8;
|
||||
uint8_t *color = (uint8_t *)heap_caps_calloc(1, row_line * TFT_VRES * byte_per_pixel, MALLOC_CAP_DMA);
|
||||
TEST_ASSERT_NOT_NULL(color);
|
||||
uint16_t x[1];
|
||||
uint16_t y[1];
|
||||
uint16_t strength[1];
|
||||
uint8_t count = 0;
|
||||
|
||||
for (int j = 0; j < TFT_BPP; j++) {
|
||||
for (int i = 0; i < row_line * TFT_HRES ; i++) {
|
||||
for (int k = 0; k < byte_per_pixel; k++) {
|
||||
color[i * byte_per_pixel + k] = (SPI_SWAP_DATA_TX(BIT(j), TFT_BPP) >> (k * 8)) & 0xff;
|
||||
}
|
||||
}
|
||||
TEST_ESP_OK(esp_lcd_panel_draw_bitmap(panel_handle, 0, j * row_line, TFT_HRES , (j + 1) * row_line, color));
|
||||
xSemaphoreTake(refresh_finish, portMAX_DELAY);
|
||||
bool touchpad_pressed = esp_lcd_touch_get_coordinates(tp, x, y, strength, &count, 1);
|
||||
|
||||
if(touchpad_pressed == true) {
|
||||
//ESP_LOGI(TAG, "Touchpad pressed from LVGL..\n");
|
||||
data->point.x = x[0];
|
||||
data->point.y = y[0];
|
||||
data->state = LV_INDEV_STATE_PRESSED;
|
||||
} else {
|
||||
data->state = LV_INDEV_STATE_RELEASED;
|
||||
}
|
||||
free(color);
|
||||
vSemaphoreDelete(refresh_finish);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for LVGL button events.
|
||||
*/
|
||||
static void btn_event_cb(lv_event_t * e) {
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
|
||||
//ESP_LOGI(TAG, "Button callback fired.");
|
||||
|
||||
if(code == LV_EVENT_CLICKED) {
|
||||
ESP_LOGI(TAG, "LVGL button pressed.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a test UI
|
||||
*/
|
||||
void lv_example_btn_1(void)
|
||||
{
|
||||
lv_obj_t * label;
|
||||
|
||||
lv_obj_t * btn1 = lv_btn_create(lv_scr_act());
|
||||
lv_obj_add_event_cb(btn1, btn_event_cb, LV_EVENT_ALL, NULL);
|
||||
lv_obj_set_width(btn1, 120);
|
||||
lv_obj_set_height(btn1, 100);
|
||||
lv_obj_align(btn1, LV_ALIGN_CENTER, 0, -40);
|
||||
|
||||
label = lv_label_create(btn1);
|
||||
lv_label_set_text(label, "Button");
|
||||
lv_obj_center(label);
|
||||
|
||||
lv_obj_t * btn2 = lv_btn_create(lv_scr_act());
|
||||
lv_obj_add_event_cb(btn2, btn_event_cb, LV_EVENT_ALL, NULL);
|
||||
lv_obj_align(btn2, LV_ALIGN_CENTER, 0, 40);
|
||||
lv_obj_add_flag(btn2, LV_OBJ_FLAG_CHECKABLE);
|
||||
lv_obj_set_height(btn2, LV_SIZE_CONTENT);
|
||||
|
||||
label = lv_label_create(btn2);
|
||||
lv_label_set_text(label, "Toggle");
|
||||
lv_obj_center(label);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the SPI bus and starts communication with xpt2046 touch controller.
|
||||
*/
|
||||
void init_touchscreen_xpt2046(void) {
|
||||
|
||||
ESP_LOGI(TAG, "Initialize touchscreen SPI bus");
|
||||
|
||||
const spi_bus_config_t ts_bus_config = {
|
||||
.mosi_io_num = CONFIG_TOUCH_MOSI,
|
||||
.miso_io_num = CONFIG_TOUCH_MISO,
|
||||
.sclk_io_num = CONFIG_TOUCH_CLK,
|
||||
.quadwp_io_num = -1,
|
||||
.quadhd_io_num = -1,
|
||||
.max_transfer_sz = 4096,
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK(spi_bus_initialize(TOUCH_SPI_HOST, &ts_bus_config, SPI_DMA_CH_AUTO));
|
||||
|
||||
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_XPT2046_CONFIG(CONFIG_TOUCH_CS);
|
||||
ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(TOUCH_SPI_HOST, &tp_io_config, &tp_io_handle));
|
||||
|
||||
esp_lcd_touch_config_t tp_cfg = {
|
||||
.x_max = TFT_HRES,
|
||||
.y_max = TFT_VRES,
|
||||
.rst_gpio_num = -1,
|
||||
.int_gpio_num = -1,
|
||||
.flags = {
|
||||
.swap_xy = 1,
|
||||
.mirror_x = 0,
|
||||
.mirror_y = 0,
|
||||
},
|
||||
};
|
||||
|
||||
ESP_LOGI(TAG, "Initialize touch controller XPT2046");
|
||||
ESP_ERROR_CHECK(esp_lcd_touch_new_spi_xpt2046(tp_io_handle, &tp_cfg, &tp));
|
||||
ESP_LOGI(TAG, "Finished initialization of XPT2046 touch driver");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,7 +155,7 @@ void init_spi_lcd(void) {
|
||||
ESP_LOGI(TAG, "Turn on backlight");
|
||||
|
||||
gpio_config_t io_conf = {
|
||||
.pin_bit_mask = (1ULL << GPIO_TFT_BL),
|
||||
.pin_bit_mask = (1ULL << CONFIG_TFT_BL),
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pull_up_en = GPIO_PULLUP_ENABLE,
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||
@@ -76,22 +163,21 @@ void init_spi_lcd(void) {
|
||||
};
|
||||
|
||||
gpio_config(&io_conf);
|
||||
gpio_set_level(GPIO_TFT_BL, 1);
|
||||
gpio_set_level(CONFIG_TFT_BL, 1);
|
||||
|
||||
ESP_LOGI(TAG, "Initialize SPI bus");
|
||||
const spi_bus_config_t bus_config = ILI9341_PANEL_BUS_SPI_CONFIG(GPIO_TFT_SCKL,
|
||||
GPIO_TFT_MOSI, TFT_HRES * 80 * TFT_BPP / 8);
|
||||
const spi_bus_config_t bus_config = ILI9341_PANEL_BUS_SPI_CONFIG(CONFIG_TFT_SCKL,
|
||||
CONFIG_TFT_MOSI, TFT_HRES * 80 * TFT_BPP / 8);
|
||||
TEST_ESP_OK(spi_bus_initialize(LCD_SPI_HOST, &bus_config, SPI_DMA_CH_AUTO));
|
||||
|
||||
ESP_LOGI(TAG, "Install panel IO");
|
||||
esp_lcd_panel_io_handle_t io_handle = NULL;
|
||||
const esp_lcd_panel_io_spi_config_t io_config = ILI9341_PANEL_IO_SPI_CONFIG(GPIO_TFT_CS, GPIO_TFT_DC,
|
||||
const esp_lcd_panel_io_spi_config_t io_config = ILI9341_PANEL_IO_SPI_CONFIG(CONFIG_TFT_CS, CONFIG_TFT_DC,
|
||||
notify_refresh_ready, NULL);
|
||||
|
||||
TEST_ESP_OK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)LCD_SPI_HOST, &io_config, &io_handle));
|
||||
|
||||
ESP_LOGI(TAG, "Install ili9341 panel driver");
|
||||
esp_lcd_panel_handle_t panel_handle = NULL;
|
||||
|
||||
const esp_lcd_panel_dev_config_t panel_config = {
|
||||
.reset_gpio_num = -1, // Shared with Touch reset
|
||||
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
@@ -113,15 +199,59 @@ void init_spi_lcd(void) {
|
||||
TEST_ESP_OK(esp_lcd_panel_disp_on_off(panel_handle, true));
|
||||
#endif
|
||||
|
||||
ESP_LOGI(TAG, "Finished init of spi LCD.");
|
||||
ESP_LOGI(TAG, "Drawing bitmap.");;
|
||||
test_draw_bitmap(panel_handle);
|
||||
vTaskDelay(pdMS_TO_TICKS(3000));
|
||||
|
||||
// Tear it back down, move this into a function to clean up after ourselves if it's ever needed.
|
||||
ESP_LOGI(TAG, "Destroying and cleaning up LCD/SPI handles.");
|
||||
gpio_reset_pin(GPIO_TFT_BL);
|
||||
TEST_ESP_OK(esp_lcd_panel_del(panel_handle));
|
||||
TEST_ESP_OK(esp_lcd_panel_io_del(io_handle));
|
||||
TEST_ESP_OK(spi_bus_free(LCD_SPI_HOST));
|
||||
ESP_LOGI(TAG, "Finished init of spi LCD");
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the LVGL display and sets everything up so that LVGL can draw to the TFT LCD.
|
||||
*/
|
||||
void init_lvgl_display(void) {
|
||||
static lv_disp_t * disp_handle = NULL;
|
||||
|
||||
const lvgl_port_cfg_t lvgl_cfg = ESP_LVGL_PORT_INIT_CONFIG();
|
||||
TEST_ESP_OK(lvgl_port_init(&lvgl_cfg));
|
||||
|
||||
const lvgl_port_display_cfg_t disp_cfg = {
|
||||
.io_handle = io_handle,
|
||||
.panel_handle = panel_handle,
|
||||
.buffer_size = LVGL_BUF_SIZE,
|
||||
.double_buffer = true,
|
||||
.hres = TFT_HRES,
|
||||
.vres = TFT_VRES,
|
||||
.monochrome = false,
|
||||
.color_format = LV_COLOR_FORMAT_RGB565,
|
||||
.rotation = {
|
||||
.swap_xy = true,
|
||||
.mirror_x = false,
|
||||
.mirror_y = false,
|
||||
},
|
||||
.flags = {
|
||||
.buff_dma = false,
|
||||
.swap_bytes = false,
|
||||
}
|
||||
};
|
||||
disp_handle = lvgl_port_add_disp(&disp_cfg);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the LVGL input driver as a pointer type so that LVGL can read input and dispatch
|
||||
* UI events.
|
||||
*/
|
||||
void init_input(void) {
|
||||
lv_indev_t * indev = lv_indev_create();
|
||||
lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER);
|
||||
lv_indev_set_read_cb(indev, touch_driver_read);
|
||||
}
|
||||
|
||||
/**
|
||||
* Main function that completely initializes the TFT LCD, the touchscreen, the LVGL display,
|
||||
* input device and draws the UI.
|
||||
*/
|
||||
void init_display(void) {
|
||||
init_spi_lcd();
|
||||
init_touchscreen_xpt2046();
|
||||
init_lvgl_display();
|
||||
init_input();
|
||||
lv_example_btn_1();
|
||||
}
|
||||
|
||||
+9
-12
@@ -4,17 +4,14 @@
|
||||
|
||||
#include "esp_lcd_panel_io.h"
|
||||
|
||||
#define LCD_SPI_HOST SPI2_HOST
|
||||
#define LCD_SPI_HOST SPI2_HOST
|
||||
#define TOUCH_SPI_HOST SPI3_HOST
|
||||
|
||||
#define GPIO_TFT_MISO CONFIG_TFT_MISO_PIN
|
||||
#define GPIO_TFT_MOSI CONFIG_TFT_MOSI_PIN
|
||||
#define GPIO_TFT_SCKL CONFIG_TFT_SCKL_PIN
|
||||
#define GPIO_TFT_CS CONFIG_TFT_CS_PIN
|
||||
#define GPIO_TFT_DC CONFIG_TFT_DC_PIN
|
||||
#define GPIO_TFT_BL CONFIG_TFT_BL_PIN // Backlight
|
||||
#define TFT_HRES CONFIG_TFT_HRES
|
||||
#define TFT_VRES CONFIG_TFT_VRES
|
||||
#define TFT_BPP CONFIG_TFT_BPP
|
||||
#define TFT_HRES CONFIG_TFT_HRES
|
||||
#define TFT_VRES CONFIG_TFT_VRES
|
||||
#define TFT_BPP CONFIG_TFT_BPP
|
||||
|
||||
#define LVGL_BUF_SIZE TFT_VRES * TFT_HRES / 10 * (TFT_BPP / 8)
|
||||
|
||||
/**
|
||||
* Draws a test bitmap of stripes of colors to the LCD.
|
||||
@@ -22,6 +19,6 @@
|
||||
void test_draw_bitmap(esp_lcd_panel_handle_t panel_handle);
|
||||
|
||||
/**
|
||||
* Initializes the SPI LCD in preparation for writing graphics to it.
|
||||
* Initializes the display TFT and touchscreen.
|
||||
*/
|
||||
void init_spi_lcd(void);
|
||||
void init_display(void);
|
||||
|
||||
@@ -15,3 +15,6 @@ dependencies:
|
||||
# # All dependencies of `main` are public by default.
|
||||
# public: true
|
||||
espressif/esp_lcd_ili9341: ^2.0.0
|
||||
lvgl/lvgl: ^9.4.0
|
||||
espressif/esp_lvgl_port: ^2.3.0
|
||||
atanisoft/esp_lcd_touch_xpt2046: ^1.0.2
|
||||
|
||||
@@ -206,7 +206,7 @@ void parse_telemetry(void) {
|
||||
}
|
||||
|
||||
void app_main(void) {
|
||||
init_spi_lcd();
|
||||
init_display();
|
||||
|
||||
init_rmt_esc_tx();
|
||||
throttle.throttle = 300;
|
||||
|
||||
Reference in New Issue
Block a user