From fd74c5724eb3f6cbb07a469b4da3b5426fbdc61d Mon Sep 17 00:00:00 2001 From: rkcf Date: Sat, 4 Feb 2023 14:29:16 -0600 Subject: [PATCH] add lcd display and lvgl display library --- README.org | 6 +++ main/esp32-sequencer.c | 95 +++++++++++++++++++++++++++++++++++++++++- main/idf_component.yml | 1 + 3 files changed, 100 insertions(+), 2 deletions(-) diff --git a/README.org b/README.org index cfca22e..43f89a5 100644 --- a/README.org +++ b/README.org @@ -1,6 +1,12 @@ * ESP32 Sequencer A basic step sequencer based on the esp32. +** Project Setup + +#+BEGIN_SRC shell +idf.py add-dependency "lvgl/lvgl>=8.*" +#+END_SRC + ** TFT LCD Screen Pinout | LCD Pin | ESP32 Pin | Function | diff --git a/main/esp32-sequencer.c b/main/esp32-sequencer.c index 601568d..e531ce0 100644 --- a/main/esp32-sequencer.c +++ b/main/esp32-sequencer.c @@ -1,30 +1,42 @@ #include #include +#include "core/lv_disp.h" #include "driver/gpio.h" #include "driver/gptimer.h" #include "driver/ledc.h" #include "driver/spi_common.h" #include "esp_attr.h" #include "esp_err.h" +#include "esp_heap_caps.h" +#include "esp_lcd_panel_interface.h" #include "esp_lcd_types.h" #include "esp_log.h" #include "esp_random.h" +#include "esp_timer.h" #include "freertos/FreeRTOS.h" #include "freertos/portmacro.h" +#include "freertos/projdefs.h" #include "freertos/queue.h" #include "freertos/task.h" #include "hal/gpio_types.h" #include "hal/lcd_types.h" #include "hal/ledc_types.h" +#include "hal/lv_hal_disp.h" #include "hal/spi_types.h" #include "hal/timer_types.h" +#include "misc/lv_area.h" +#include "misc/lv_color.h" +#include "misc/lv_timer.h" #include "soc/clk_tree_defs.h" #include "driver/spi_master.h" #include "esp_lcd_panel_io.h" #include "esp_lcd_panel_vendor.h" #include "esp_lcd_panel_ops.h" #include "esp_lcd_ili9341.h" +#include "lvgl.h" +#include "widgets/lv_label.h" + /* Inputs */ // Clock In @@ -54,6 +66,8 @@ static QueueHandle_t control_event_queue = NULL; #define LCD_CS_PIN 36 #define LCD_BK_LIGHT_PIN 41 +#define LVGL_TICK_MS 2 + /* Timers */ static gptimer_handle_t tap_tempo_timer = NULL; static gptimer_handle_t gate_timer = NULL; @@ -258,7 +272,27 @@ static void ledc_init(void) { ESP_ERROR_CHECK(ledc_channel_config(&ledc_gate_channel)); } -static void lcd_init(void) { +static void 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; + esp_lcd_panel_draw_bitmap(panel_handle, offsetx1, offsety1, offsetx2 + 1, offsety2 + 1, color_map); +} + +static void lvgl_port_update_cb(lv_disp_drv_t *drv) { + esp_lcd_panel_handle_t panel_handle = (esp_lcd_panel_handle_t)drv->user_data; + esp_lcd_panel_swap_xy(panel_handle, false); + esp_lcd_panel_mirror(panel_handle, true, false); +} + +static void lvgl_increase_tick(void *arg) { + lv_tick_inc(LVGL_TICK_MS); +} + +/* Setup for TFT LCD Display and LVGL GUI */ +static void display_init(void) { ESP_LOGI(TAG, "Initialing LCD"); // Configure backlight gpio_reset_pin(LCD_BK_LIGHT_PIN); @@ -302,6 +336,60 @@ static void lcd_init(void) { // Turn on the panel ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(lcd_handle, true)); + + ESP_LOGI(TAG, "Initalizing LVGL"); + lv_init(); + + // Allocate draw buffers + lv_color_t *buf1 = + heap_caps_malloc(LCD_H_RES * 20 * sizeof(lv_color_t), MALLOC_CAP_DMA); + lv_color_t *buf2 = + heap_caps_malloc(LCD_H_RES * 20 * sizeof(lv_color_t), MALLOC_CAP_DMA); + // Initialize draw buffers + static lv_disp_draw_buf_t disp_buf; + lv_disp_draw_buf_init(&disp_buf, buf1, buf2, LCD_H_RES * 20); + + // Initialize display driver then register it + static lv_disp_drv_t disp_drv; + lv_disp_drv_init(&disp_drv); + disp_drv.hor_res = LCD_H_RES; + disp_drv.ver_res = LCD_V_RES; + disp_drv.flush_cb = lvgl_flush_cb; + disp_drv.drv_update_cb = lvgl_port_update_cb; + disp_drv.draw_buf = &disp_buf; + disp_drv.user_data = lcd_handle; + lv_disp_t *disp = lv_disp_drv_register(&disp_drv); + + // Install LVGL tick timer + esp_timer_handle_t lvgl_tick_timer = NULL; + const esp_timer_create_args_t lvgl_tick_timer_args = { + .callback = &lvgl_increase_tick, + .name = "lvgl_tick" + }; + ESP_ERROR_CHECK(esp_timer_create(&lvgl_tick_timer_args, &lvgl_tick_timer)); + ESP_ERROR_CHECK(esp_timer_start_periodic(lvgl_tick_timer, LVGL_TICK_MS * 1000)); +} + +static void gui_create(void) { + // Get current screen + lv_obj_t * screen = lv_disp_get_scr_act(NULL); + + // Set background color + /* lv_obj_set_style_bg_color(lv_scr_act(), lv_color_hex(0x003a57), LV_PART_MAIN); */ + + // Create and set lable text + lv_obj_t * title_label = lv_label_create(lv_scr_act()); + lv_label_set_text(title_label, "Hello World!"); + + // Align label to center top + /* lv_obj_align(title_label, LV_ALIGN_CENTER, 0, 0); */ +} + +static void gui_task(void *pvParameter) { + while (1) { + vTaskDelay(pdMS_TO_TICKS(10)); + lv_task_handler(); + } } static void pulse_cv(bool triggered) { @@ -322,7 +410,10 @@ void app_main(void) { gpio_init(); controls_init(); /* Initialize LCD */ - lcd_init(); + display_init(); + gui_create(); + xTaskCreatePinnedToCore(gui_task, "gui", 4096*2, NULL, 0, NULL, 1); + // Start task to handle control events xTaskCreate(control_event_handler, "control event handler", 2048, NULL, 10, NULL); diff --git a/main/idf_component.yml b/main/idf_component.yml index 3619054..4e53db2 100644 --- a/main/idf_component.yml +++ b/main/idf_component.yml @@ -1,5 +1,6 @@ ## IDF Component Manager Manifest File dependencies: + lvgl/lvgl: ">=8.*" espressif/esp_lcd_ili9341: "*" ## Required IDF version idf: