Add LVGL and set up with display/touch drivers

This commit is contained in:
maddiebaka
2025-12-26 11:04:16 -05:00
parent cb92f69ee3
commit 3256ab2e65
7 changed files with 269 additions and 58 deletions
+53 -1
View File
@@ -1,4 +1,19 @@
dependencies: 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: espressif/cmake_utilities:
component_hash: component_hash:
351350613ceafba240b761b4ea991e0f231ac7a9f59a9ee901f751bddc0bb18f 351350613ceafba240b761b4ea991e0f231ac7a9f59a9ee901f751bddc0bb18f
@@ -25,13 +40,50 @@ dependencies:
registry_url: https://components.espressif.com/ registry_url: https://components.espressif.com/
type: service type: service
version: 2.0.1 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: idf:
source: source:
type: idf type: idf
version: 5.5.1 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: direct_dependencies:
- atanisoft/esp_lcd_touch_xpt2046
- espressif/esp_lcd_ili9341 - espressif/esp_lcd_ili9341
- espressif/esp_lvgl_port
- idf - idf
manifest_hash: 5c04a0422ee419cb472e6df05c9d4292985ae0cd069ef8404da0161609cc967c - lvgl/lvgl
manifest_hash: d2b549f17124d3d38e4add4614fb10956ada1a576e4c5f6a623ea3756bcd3ba5
target: esp32 target: esp32
version: 2.0.0 version: 2.0.0
+2 -1
View File
@@ -1,3 +1,4 @@
idf_component_register(SRCS "spincoat-plater-firmware.c" "dshot_esc_encoder.c" "display.c" 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 ".") INCLUDE_DIRS ".")
+34 -6
View File
@@ -9,36 +9,64 @@ menu "Pin Mapping Configuration"
default 27 default 27
help help
This is the pin used for receiving UART telemetry from the ESC. This is the pin used for receiving UART telemetry from the ESC.
config TFT_MISO_PIN config TFT_MISO
int "SPI LCD MISO pin" int "SPI LCD MISO pin"
default 12 default 12
help help
This is the pin for MISO on the SPI LCD. This is the pin for MISO on the SPI LCD.
config TFT_MOSI_PIN config TFT_MOSI
int "SPI LCD MOSI pin" int "SPI LCD MOSI pin"
default 13 default 13
help help
This is the pin for MOSI on the SPI LCD. This is the pin for MOSI on the SPI LCD.
config TFT_SCKL_PIN config TFT_SCKL
int "SPI LCD SCKL pin" int "SPI LCD SCKL pin"
default 14 default 14
help help
This is the pin for SCKL on the SPI LCD. This is the pin for SCKL on the SPI LCD.
config TFT_CS_PIN config TFT_CS
int "SPI LCD CS pin" int "SPI LCD CS pin"
default 15 default 15
help help
This is the pin for CS on the SPI LCD. This is the pin for CS on the SPI LCD.
config TFT_DC_PIN config TFT_DC
int "SPI LCD DC pin" int "SPI LCD DC pin"
default 2 default 2
help help
This is the pin for DC on the SPI LCD. This is the pin for DC on the SPI LCD.
config TFT_BL_PIN config TFT_BL
int "SPI LCD BL (backlight) pin" int "SPI LCD BL (backlight) pin"
default 21 default 21
help help
This is the pin for backlight control on the SPI LCD. 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 config TFT_HRES
int "The horizontal resolution of the TFT display" int "The horizontal resolution of the TFT display"
default 320 default 320
+166 -36
View File
@@ -18,9 +18,17 @@
#include "esp_lcd_panel_io.h" #include "esp_lcd_panel_io.h"
#include "esp_lcd_panel_commands.h" #include "esp_lcd_panel_commands.h"
#include "esp_lcd_ili9341.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; 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"; 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) void touch_driver_read(lv_indev_t * indev, lv_indev_data_t * data) {
ESP_ERROR_CHECK(esp_lcd_touch_read_data(tp));
uint16_t x[1];
uint16_t y[1];
uint16_t strength[1];
uint8_t count = 0;
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;
}
}
/**
* 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)
{ {
refresh_finish = xSemaphoreCreateBinary(); lv_obj_t * label;
TEST_ASSERT_NOT_NULL(refresh_finish);
uint16_t row_line = TFT_VRES / TFT_BPP; lv_obj_t * btn1 = lv_btn_create(lv_scr_act());
uint8_t byte_per_pixel = TFT_BPP / 8; lv_obj_add_event_cb(btn1, btn_event_cb, LV_EVENT_ALL, NULL);
uint8_t *color = (uint8_t *)heap_caps_calloc(1, row_line * TFT_VRES * byte_per_pixel, MALLOC_CAP_DMA); lv_obj_set_width(btn1, 120);
TEST_ASSERT_NOT_NULL(color); lv_obj_set_height(btn1, 100);
lv_obj_align(btn1, LV_ALIGN_CENTER, 0, -40);
for (int j = 0; j < TFT_BPP; j++) { label = lv_label_create(btn1);
for (int i = 0; i < row_line * TFT_HRES ; i++) { lv_label_set_text(label, "Button");
for (int k = 0; k < byte_per_pixel; k++) { lv_obj_center(label);
color[i * byte_per_pixel + k] = (SPI_SWAP_DATA_TX(BIT(j), TFT_BPP) >> (k * 8)) & 0xff;
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);
} }
}
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); /**
} * Initializes the SPI bus and starts communication with xpt2046 touch controller.
free(color); */
vSemaphoreDelete(refresh_finish); 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"); ESP_LOGI(TAG, "Turn on backlight");
gpio_config_t io_conf = { gpio_config_t io_conf = {
.pin_bit_mask = (1ULL << GPIO_TFT_BL), .pin_bit_mask = (1ULL << CONFIG_TFT_BL),
.mode = GPIO_MODE_OUTPUT, .mode = GPIO_MODE_OUTPUT,
.pull_up_en = GPIO_PULLUP_ENABLE, .pull_up_en = GPIO_PULLUP_ENABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE, .pull_down_en = GPIO_PULLDOWN_DISABLE,
@@ -76,22 +163,21 @@ void init_spi_lcd(void) {
}; };
gpio_config(&io_conf); gpio_config(&io_conf);
gpio_set_level(GPIO_TFT_BL, 1); gpio_set_level(CONFIG_TFT_BL, 1);
ESP_LOGI(TAG, "Initialize SPI bus"); ESP_LOGI(TAG, "Initialize SPI bus");
const spi_bus_config_t bus_config = ILI9341_PANEL_BUS_SPI_CONFIG(GPIO_TFT_SCKL, const spi_bus_config_t bus_config = ILI9341_PANEL_BUS_SPI_CONFIG(CONFIG_TFT_SCKL,
GPIO_TFT_MOSI, TFT_HRES * 80 * TFT_BPP / 8); CONFIG_TFT_MOSI, TFT_HRES * 80 * TFT_BPP / 8);
TEST_ESP_OK(spi_bus_initialize(LCD_SPI_HOST, &bus_config, SPI_DMA_CH_AUTO)); TEST_ESP_OK(spi_bus_initialize(LCD_SPI_HOST, &bus_config, SPI_DMA_CH_AUTO));
ESP_LOGI(TAG, "Install panel IO"); 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(CONFIG_TFT_CS, CONFIG_TFT_DC,
const esp_lcd_panel_io_spi_config_t io_config = ILI9341_PANEL_IO_SPI_CONFIG(GPIO_TFT_CS, GPIO_TFT_DC,
notify_refresh_ready, NULL); 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)); 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_LOGI(TAG, "Install ili9341 panel driver");
esp_lcd_panel_handle_t panel_handle = NULL;
const esp_lcd_panel_dev_config_t panel_config = { const esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = -1, // Shared with Touch reset .reset_gpio_num = -1, // Shared with Touch reset
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) #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)); TEST_ESP_OK(esp_lcd_panel_disp_on_off(panel_handle, true));
#endif #endif
ESP_LOGI(TAG, "Finished init of spi LCD."); ESP_LOGI(TAG, "Finished init of spi LCD");
ESP_LOGI(TAG, "Drawing bitmap.");; }
test_draw_bitmap(panel_handle);
vTaskDelay(pdMS_TO_TICKS(3000)); /**
* Initializes the LVGL display and sets everything up so that LVGL can draw to the TFT LCD.
// 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."); void init_lvgl_display(void) {
gpio_reset_pin(GPIO_TFT_BL); static lv_disp_t * disp_handle = NULL;
TEST_ESP_OK(esp_lcd_panel_del(panel_handle));
TEST_ESP_OK(esp_lcd_panel_io_del(io_handle)); const lvgl_port_cfg_t lvgl_cfg = ESP_LVGL_PORT_INIT_CONFIG();
TEST_ESP_OK(spi_bus_free(LCD_SPI_HOST)); 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();
} }
+5 -8
View File
@@ -5,23 +5,20 @@
#include "esp_lcd_panel_io.h" #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_HRES CONFIG_TFT_HRES
#define TFT_VRES CONFIG_TFT_VRES #define TFT_VRES CONFIG_TFT_VRES
#define TFT_BPP CONFIG_TFT_BPP #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. * Draws a test bitmap of stripes of colors to the LCD.
*/ */
void test_draw_bitmap(esp_lcd_panel_handle_t panel_handle); 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);
+3
View File
@@ -15,3 +15,6 @@ dependencies:
# # All dependencies of `main` are public by default. # # All dependencies of `main` are public by default.
# public: true # public: true
espressif/esp_lcd_ili9341: ^2.0.0 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
+1 -1
View File
@@ -206,7 +206,7 @@ void parse_telemetry(void) {
} }
void app_main(void) { void app_main(void) {
init_spi_lcd(); init_display();
init_rmt_esc_tx(); init_rmt_esc_tx();
throttle.throttle = 300; throttle.throttle = 300;