240 lines
8.0 KiB
C
240 lines
8.0 KiB
C
/*
|
|
* SPDX-FileCopyrightText: 2026 User
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
#include "freertos/semphr.h"
|
|
#include "driver/gpio.h"
|
|
#include "driver/i2c_master.h"
|
|
#include "esp_log.h"
|
|
#include "esp_heap_caps.h"
|
|
#include "esp_lcd_panel_ops.h"
|
|
#include "esp_lcd_panel_io.h"
|
|
#include "esp_lcd_mipi_dsi.h"
|
|
#include "esp_ldo_regulator.h"
|
|
#include "esp_lcd_touch_gt911.h"
|
|
#include "lvgl.h"
|
|
#include "esp_timer.h"
|
|
#include "esp_lv_adapter.h"
|
|
#include "esp_lcd_jd9365_10_1.h"
|
|
|
|
#define TAG "JD9365_LVGL"
|
|
|
|
// Display config
|
|
#define LCD_H_RES 800
|
|
#define LCD_V_RES 1280
|
|
#define LCD_BIT_PER_PIXEL 16 // RGB565 for better performance
|
|
#define LCD_RST_GPIO 27
|
|
#define LCD_BK_GPIO 26
|
|
#define LCD_BK_ON_LEVEL 1
|
|
|
|
// MIPI DSI config
|
|
#define MIPI_DSI_LANE_NUM 2
|
|
#define MIPI_DSI_PHY_LDO_CHAN 3
|
|
#define MIPI_DSI_PHY_LDO_VOLTAGE_MV 2500
|
|
|
|
// Touch config (GT911)
|
|
#define TOUCH_I2C_SDA 7
|
|
#define TOUCH_I2C_SCL 8
|
|
#define TOUCH_INT_GPIO 3
|
|
#define TOUCH_RST_GPIO 2
|
|
#define TOUCH_I2C_FREQ_HZ 400000
|
|
|
|
static esp_lcd_panel_handle_t panel_handle = NULL;
|
|
static esp_lcd_touch_handle_t touch_handle = NULL;
|
|
static lv_display_t *display = NULL;
|
|
static uint8_t *buf1 = NULL;
|
|
static uint8_t *buf2 = NULL;
|
|
|
|
// ================= Callbacks ===================
|
|
static bool on_color_trans_done(esp_lcd_panel_handle_t panel, esp_lcd_dpi_panel_event_data_t *event_data, void *user_ctx)
|
|
{
|
|
if (display) {
|
|
lv_display_flush_ready(display);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
static void lvgl_touch_cb(lv_indev_t *indev, lv_indev_data_t *data)
|
|
{
|
|
uint16_t x[1], y[1];
|
|
uint8_t touch_cnt = 0;
|
|
|
|
esp_lcd_touch_read_data(touch_handle);
|
|
if (esp_lcd_touch_get_coordinates(touch_handle, x, y, NULL, &touch_cnt, 1) && touch_cnt > 0) {
|
|
data->point.x = x[0];
|
|
data->point.y = y[0];
|
|
data->state = LV_INDEV_STATE_PRESSED;
|
|
} else {
|
|
data->state = LV_INDEV_STATE_RELEASED;
|
|
}
|
|
}
|
|
|
|
// ================= LCD init ===================
|
|
static void lcd_init(void)
|
|
{
|
|
gpio_config_t bk_gpio = { .mode = GPIO_MODE_OUTPUT, .pin_bit_mask = 1ULL << LCD_BK_GPIO };
|
|
gpio_config(&bk_gpio);
|
|
gpio_set_level(LCD_BK_GPIO, LCD_BK_ON_LEVEL);
|
|
|
|
esp_ldo_channel_handle_t ldo_mipi = NULL;
|
|
esp_ldo_channel_config_t ldo_cfg = { .chan_id = MIPI_DSI_PHY_LDO_CHAN, .voltage_mv = MIPI_DSI_PHY_LDO_VOLTAGE_MV };
|
|
esp_ldo_acquire_channel(&ldo_cfg, &ldo_mipi);
|
|
|
|
esp_lcd_dsi_bus_handle_t mipi_dsi_bus = NULL;
|
|
esp_lcd_dsi_bus_config_t bus_cfg = JD9365_PANEL_BUS_DSI_2CH_CONFIG();
|
|
esp_lcd_new_dsi_bus(&bus_cfg, &mipi_dsi_bus);
|
|
|
|
esp_lcd_panel_io_handle_t mipi_dbi_io = NULL;
|
|
esp_lcd_dbi_io_config_t io_cfg = JD9365_PANEL_IO_DBI_CONFIG();
|
|
esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &io_cfg, &mipi_dbi_io);
|
|
|
|
esp_lcd_dpi_panel_config_t dpi_cfg = JD9365_800_1280_PANEL_60HZ_DPI_CONFIG(LCD_COLOR_PIXEL_FORMAT_RGB565);
|
|
dpi_cfg.num_fbs = esp_lv_adapter_get_required_frame_buffer_count(
|
|
ESP_LV_ADAPTER_TEAR_AVOID_MODE_DEFAULT_MIPI_DSI, // Tearing mode
|
|
ESP_LV_ADAPTER_ROTATE_90 // Rotation
|
|
);
|
|
jd9365_vendor_config_t vendor_cfg = {
|
|
.flags = { .use_mipi_interface = 1 },
|
|
.mipi_config = { .dsi_bus = mipi_dsi_bus, .dpi_config = &dpi_cfg, .lane_num = MIPI_DSI_LANE_NUM }
|
|
};
|
|
esp_lcd_panel_dev_config_t panel_cfg = {
|
|
.reset_gpio_num = LCD_RST_GPIO,
|
|
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
|
|
.bits_per_pixel = LCD_BIT_PER_PIXEL,
|
|
.vendor_config = &vendor_cfg
|
|
};
|
|
esp_lcd_new_panel_jd9365(mipi_dbi_io, &panel_cfg, &panel_handle);
|
|
|
|
esp_lcd_panel_reset(panel_handle);
|
|
esp_lcd_panel_init(panel_handle);
|
|
ESP_ERROR_CHECK(esp_lcd_dpi_panel_get_frame_buffer(panel_handle, 2, (void **)&buf1, (void **)&buf2));
|
|
esp_lcd_panel_disp_on_off(panel_handle, true);
|
|
|
|
|
|
}
|
|
|
|
// ================= Touch init ===================
|
|
static void touch_init(void)
|
|
{
|
|
i2c_master_bus_config_t i2c_bus_cfg = {
|
|
.i2c_port = I2C_NUM_0,
|
|
.sda_io_num = TOUCH_I2C_SDA,
|
|
.scl_io_num = TOUCH_I2C_SCL,
|
|
.clk_source = I2C_CLK_SRC_DEFAULT,
|
|
.glitch_ignore_cnt = 7,
|
|
.flags.enable_internal_pullup = true,
|
|
};
|
|
i2c_master_bus_handle_t i2c_bus = NULL;
|
|
ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus));
|
|
|
|
esp_lcd_panel_io_handle_t touch_io = NULL;
|
|
esp_lcd_panel_io_i2c_config_t touch_io_cfg = ESP_LCD_TOUCH_IO_I2C_GT911_CONFIG();
|
|
touch_io_cfg.scl_speed_hz = TOUCH_I2C_FREQ_HZ;
|
|
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(i2c_bus, &touch_io_cfg, &touch_io));
|
|
|
|
esp_lcd_touch_config_t touch_cfg = {
|
|
.x_max = LCD_H_RES,
|
|
.y_max = LCD_V_RES,
|
|
.rst_gpio_num = TOUCH_RST_GPIO,
|
|
.int_gpio_num = TOUCH_INT_GPIO,
|
|
.levels = { .reset = 0, .interrupt = 0 },
|
|
.flags = { .swap_xy = 1, .mirror_x = 1, .mirror_y = 0 },
|
|
};
|
|
ESP_ERROR_CHECK(esp_lcd_touch_new_i2c_gt911(touch_io, &touch_cfg, &touch_handle));
|
|
}
|
|
|
|
// ================= LVGL init ===================
|
|
static void lvgl_init(void)
|
|
{
|
|
|
|
esp_lv_adapter_config_t cfg = ESP_LV_ADAPTER_DEFAULT_CONFIG();
|
|
ESP_ERROR_CHECK(esp_lv_adapter_init(&cfg));
|
|
|
|
esp_lv_adapter_display_config_t disp_cfg = ESP_LV_ADAPTER_DISPLAY_MIPI_DEFAULT_CONFIG(
|
|
panel_handle, // LCD panel handle
|
|
NULL, // LCD panel IO handle (can be NULL for some interfaces)
|
|
LCD_H_RES, // Horizontal resolution
|
|
LCD_V_RES, // Vertical resolution
|
|
ESP_LV_ADAPTER_ROTATE_90 // Rotation
|
|
);
|
|
display = esp_lv_adapter_register_display(&disp_cfg);
|
|
assert(display != NULL);
|
|
|
|
esp_lv_adapter_touch_config_t touch_cfg = ESP_LV_ADAPTER_TOUCH_DEFAULT_CONFIG(display, touch_handle);
|
|
lv_indev_t *touch = esp_lv_adapter_register_touch(&touch_cfg);
|
|
lv_indev_set_read_cb(touch, lvgl_touch_cb);
|
|
assert(touch != NULL);
|
|
|
|
ESP_ERROR_CHECK(esp_lv_adapter_start());
|
|
}
|
|
|
|
static lv_obj_t * label2;
|
|
|
|
static void slider_event_cb(lv_event_t * e)
|
|
{
|
|
lv_obj_t * slider = lv_event_get_target_obj(e);
|
|
|
|
/*Refresh the text*/
|
|
lv_label_set_text_fmt(label2, "%" LV_PRId32, lv_slider_get_value(slider));
|
|
//lv_obj_align_to(label2, slider, LV_ALIGN_OUT_TOP_MID, 0, -15); /*Align top of the slider*/
|
|
}
|
|
|
|
uint32_t my_get_milliseconds()
|
|
{
|
|
return esp_timer_get_time() / 1000;
|
|
}
|
|
|
|
// ================= UI ===================
|
|
static void create_ui(void)
|
|
{
|
|
if (esp_lv_adapter_lock(-1) == ESP_OK) {
|
|
lv_obj_t *tileview = lv_tileview_create(lv_scr_act());
|
|
|
|
// Page 1 - Blue
|
|
lv_obj_t *tile1 = lv_tileview_add_tile(tileview, 0, 0, LV_DIR_BOTTOM);
|
|
lv_obj_set_style_bg_color(tile1, lv_color_hex(0x2196F3), 0);
|
|
lv_obj_t *label1 = lv_label_create(tile1);
|
|
lv_label_set_text(label1, "Seite 1\n\nSwipe nach oben");
|
|
lv_obj_set_style_text_color(label1, lv_color_black(), 0);
|
|
lv_obj_set_style_text_font(label1, &lv_font_montserrat_14, 0);
|
|
lv_obj_center(label1);
|
|
|
|
lv_obj_t * slider = lv_slider_create(tile1);
|
|
lv_obj_set_width(slider, 200); /*Set the width*/
|
|
lv_obj_center(slider); /*Align to the center of the parent (screen)*/
|
|
lv_obj_add_event_cb(slider, slider_event_cb, LV_EVENT_VALUE_CHANGED, NULL);
|
|
|
|
// Page 2 - Green
|
|
lv_obj_t *tile2 = lv_tileview_add_tile(tileview, 0, 1, LV_DIR_TOP);
|
|
lv_obj_set_style_bg_color(tile2, lv_color_hex(0x4CAF50), 0);
|
|
label2 = lv_label_create(tile2);
|
|
lv_label_set_text(label2, "Seite 2\n\nSwipe nach unten");
|
|
lv_obj_set_style_text_color(label2, lv_color_black(), 0);
|
|
lv_obj_set_style_text_font(label2, &lv_font_montserrat_14, 0);
|
|
lv_obj_center(label2);
|
|
esp_lv_adapter_unlock();
|
|
}
|
|
}
|
|
|
|
// ================= Main ===================
|
|
void app_main(void)
|
|
{
|
|
ESP_LOGI(TAG, "Starting JD9365 + LVGL 9 (Portrait RGB565)");
|
|
|
|
lcd_init();
|
|
touch_init();
|
|
|
|
lvgl_init();
|
|
create_ui();
|
|
//lv_tick_set_cb(xTaskGetTickCount);
|
|
//lv_tick_set_cb(my_get_milliseconds);
|
|
while (1) {
|
|
lv_timer_handler();
|
|
vTaskDelay(pdMS_TO_TICKS(10));
|
|
}
|
|
}
|