纳入固件源码、屏幕组件、nand_xfer 工具和文档。忽略本机构建产物、sdkconfig,以及含本机路径的依赖锁。 Co-authored-by: Cursor <cursoragent@cursor.com>
238 lines
8.4 KiB
C
238 lines
8.4 KiB
C
#include "screen_init.h"
|
||
#include "config.h"
|
||
#include "LVGL/lvgl_init.h"
|
||
#include "driver/i2c_master.h"
|
||
|
||
|
||
|
||
const char *TAG_LVGL = "lvgl_init";//打印标签
|
||
#if EXAMPLE_USE_TOUCH
|
||
esp_lcd_touch_handle_t tp = NULL;
|
||
bool is_anim_paused = false;
|
||
i2c_master_bus_handle_t touch_bus_handle_touch; // 定义触摸屏I2C总线句柄(全局,供BMI270共享)
|
||
#endif
|
||
static void read_lcd_id(esp_lcd_panel_io_handle_t read_io)
|
||
{
|
||
uint8_t id_buf[3] = {0};
|
||
esp_err_t ret = esp_lcd_panel_io_rx_param(read_io, 0x03000400, id_buf, 3);
|
||
if (ret == ESP_OK) {
|
||
ESP_LOGI(TAG_LVGL, "LCD ID: %02X %02X %02X", id_buf[0], id_buf[1], id_buf[2]);
|
||
} else {
|
||
ESP_LOGE(TAG_LVGL, "Read ID failed: %s", esp_err_to_name(ret));
|
||
}
|
||
|
||
uint8_t id1 = 0;
|
||
uint8_t id2 = 0;
|
||
uint8_t id3 = 0;
|
||
esp_err_t ret1 = esp_lcd_panel_io_rx_param(read_io, 0x0300DA00, &id1, 1);
|
||
esp_err_t ret2 = esp_lcd_panel_io_rx_param(read_io, 0x0300DB00, &id2, 1);
|
||
esp_err_t ret3 = esp_lcd_panel_io_rx_param(read_io, 0x0300DC00, &id3, 1);
|
||
if (ret1 == ESP_OK && ret2 == ESP_OK && ret3 == ESP_OK) {
|
||
ESP_LOGI(TAG_LVGL, "LCD RDID: %02X %02X %02X", id1, id2, id3);
|
||
} else {
|
||
ESP_LOGE(TAG_LVGL, "Read RDID failed: %s %s %s",
|
||
esp_err_to_name(ret1), esp_err_to_name(ret2), esp_err_to_name(ret3));
|
||
}
|
||
}
|
||
/*
|
||
const qspi_amoled_lcd_init_cmd_t lcd_init_cmds[13] = {
|
||
{0xFE, (uint8_t[]){0x00}, 1, 0},
|
||
{0xC4, (uint8_t[]){0x80}, 1, 0},
|
||
{0x35, (uint8_t[]){0x00}, 1, 0},
|
||
{0x3A, (uint8_t[]){0x77}, 1, 0},
|
||
{0x53, (uint8_t[]){0x20}, 1, 0},
|
||
{0x51, (uint8_t[]){0x00}, 1, 0},
|
||
{0x63, (uint8_t[]){0xFF}, 1, 0},
|
||
{0x2A, (uint8_t[]){0x00, 0x16, 0x01, 0xAF}, 4, 0},
|
||
{0x2B, (uint8_t[]){0x00, 0x00, 0x01, 0xF5}, 4, 0},
|
||
{0x11, (uint8_t[]){0x00}, 0, 120},
|
||
{0x29, (uint8_t[]){0x00}, 0, 60},
|
||
{0x58, (uint8_t[]){0x07}, 1, 10},
|
||
{0x36, (uint8_t[]){0xA8}, 1, 0},
|
||
};
|
||
*/
|
||
const qspi_amoled_lcd_init_cmd_t lcd_init_cmds[] = {
|
||
// 0x11: 退出睡眠模式(Sleep Out),之后延时 60ms
|
||
{0x11, (uint8_t[]){0x00}, 0, 60},
|
||
|
||
// 0x2A: 列地址范围 0~239(0x00 0x00 ~ 0x00 0xEF)
|
||
{0x2A, (uint8_t[]){0x00, 0x00, 0x00, 0xEF}, 4, 0},
|
||
|
||
// 0x2B: 行地址范围 0~295(0x00 0x00 ~ 0x01 0x27)
|
||
{0x2B, (uint8_t[]){0x00, 0x00, 0x01, 0x27}, 4, 0},
|
||
|
||
// 0x44: 撕裂效应行(TE Line)设为 295
|
||
{0x44, (uint8_t[]){0x01, 0x27}, 2, 0},
|
||
|
||
// 0x3A: 像素格式(Pixel Format)0x55(通常为 16bit/18bit)
|
||
{0x3A, (uint8_t[]){0x55}, 1, 0},
|
||
|
||
// 0x35: TE 信号控制,0x00 = 关闭
|
||
{0x35, (uint8_t[]){0x00}, 1, 0},
|
||
|
||
// 0x53: 亮度控制寄存器,设为 0x20
|
||
{0x53, (uint8_t[]){0x20}, 1, 0},
|
||
|
||
// 0x51: 亮度值设为最高 0xFF,之后延时 60ms 再开启显示
|
||
{0x51, (uint8_t[]){0xFF}, 1, 60},
|
||
|
||
// 0x29: 开启显示(Display On),无需额外延时
|
||
{0x29, (uint8_t[]){0x00}, 0, 0},
|
||
};
|
||
|
||
|
||
|
||
// QSPI AMOLED供应商配置
|
||
qspi_amoled_vendor_config_t vendor_config =
|
||
{
|
||
.init_cmds = lcd_init_cmds,
|
||
.init_cmds_size = sizeof(lcd_init_cmds) / sizeof(lcd_init_cmds[0]),
|
||
.flags =
|
||
{
|
||
.use_qspi_interface = 1,
|
||
},
|
||
};
|
||
|
||
// LCD面板配置
|
||
const esp_lcd_panel_dev_config_t panel_config =
|
||
{
|
||
.reset_gpio_num = EXAMPLE_PIN_NUM_LCD_RST,
|
||
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER,
|
||
.bits_per_pixel = LCD_BIT_PER_PIXEL,
|
||
.vendor_config = &vendor_config,
|
||
};
|
||
|
||
|
||
extern esp_lcd_panel_io_handle_t io_handle;
|
||
|
||
void read_co5300_response(void) {
|
||
|
||
}
|
||
esp_err_t app_lcd_init(void)//QSPI初始化
|
||
{
|
||
esp_err_t ret = ESP_OK;
|
||
|
||
ESP_LOGI(TAG_LVGL, "Initialize QSPI bus");
|
||
|
||
// 使用原始的SPI总线最大传输大小,确保稳定传输
|
||
const spi_bus_config_t buscfg = QSPI_AMOLED_PANEL_BUS_QSPI_CONFIG(EXAMPLE_PIN_NUM_LCD_PCLK,
|
||
EXAMPLE_PIN_NUM_LCD_DATA0,
|
||
EXAMPLE_PIN_NUM_LCD_DATA1,
|
||
EXAMPLE_PIN_NUM_LCD_DATA2,
|
||
EXAMPLE_PIN_NUM_LCD_DATA3,
|
||
(EXAMPLE_LCD_H_RES * EXAMPLE_LVGL_BUF_HEIGHT * LCD_BIT_PER_PIXEL / 8) + 64);
|
||
|
||
ESP_ERROR_CHECK(spi_bus_initialize(LCD_HOST, &buscfg, SPI_DMA_CH_AUTO));
|
||
ESP_LOGI(TAG_LVGL, "Install panel IO");
|
||
esp_lcd_panel_io_spi_config_t io_config = {
|
||
.cs_gpio_num = EXAMPLE_PIN_NUM_LCD_CS,
|
||
.dc_gpio_num = -1,
|
||
.spi_mode = AMOLED_QSPI_MODE,
|
||
.pclk_hz = AMOLED_QSPI_MAX_PCLK,
|
||
.trans_queue_depth = 3,
|
||
.on_color_trans_done = example_notify_lvgl_flush_ready,
|
||
.user_ctx = NULL,
|
||
.lcd_cmd_bits = 32,
|
||
.lcd_param_bits = 8,
|
||
.flags = {
|
||
.quad_mode = true,
|
||
},
|
||
};
|
||
|
||
ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)LCD_HOST, &io_config, &io_handle));
|
||
ESP_LOGI(TAG_LVGL, "Install QSPI_AMOLED panel driver");
|
||
ESP_ERROR_CHECK(esp_lcd_new_panel_qspi_amoled(io_handle, &panel_config, &panel_handle));
|
||
ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle));
|
||
ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle));
|
||
ESP_ERROR_CHECK(esp_lcd_panel_set_gap(panel_handle, EXAMPLE_LCD_X_GAP, EXAMPLE_LCD_Y_GAP));
|
||
ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true));
|
||
/* 初始化时设置亮度为0,避免白光闪烁,等待 UI 加载后渐变亮屏 */
|
||
esp_err_t br = panel_qspi_amoled_set_brightness(panel_handle,100);
|
||
//uint8_t read_buf[3] = {0}; // RDDID 返回 3 个字节
|
||
/*
|
||
// 发送读指令 0x04,读取 3 个字节的回应数据
|
||
esp_err_t ret2 = esp_lcd_panel_io_rx_param(io_handle, 0x04, read_buf, 3);
|
||
|
||
if (ret2 == ESP_OK) {
|
||
ESP_LOGI("TAG", "读取回应成功!ID1: 0x%02X, ID2: 0x%02X, ID3: 0x%02X",
|
||
read_buf[0], read_buf[1], read_buf[2]);
|
||
// 根据数据手册,正常回应通常为:33h, 10h, 00h 或 33h, 11h, 00h
|
||
} else {
|
||
ESP_LOGE("TAG", "读取回应失败:%s", esp_err_to_name(ret2));
|
||
}*/
|
||
//read_lcd_id(io_handle);
|
||
//ESP_LOGI(TAG_LVGL,"br=%d",br);
|
||
//uint8_t blue_color[] = {0x00, 0x00, 0xFF};
|
||
//esp_err_t brt =panel_qspi_amoled_draw_bitmap(panel_handle, 0, 0, EXAMPLE_LCD_H_RES - 1, EXAMPLE_LCD_V_RES - 1, blue_color);
|
||
/*
|
||
if (br != ESP_OK)
|
||
{
|
||
ESP_LOGE(TAG_LVGL, "panel_qspi_amoled_set_brightness failed: %s", esp_err_to_name(br));
|
||
}
|
||
else
|
||
{
|
||
ESP_LOGI(TAG_LVGL, "Screen brightness set to 0 (等待 UI 加载后渐变亮屏)");
|
||
}
|
||
|
||
*/
|
||
/* Register done callback */
|
||
//ESP_ERROR_CHECK(esp_lcd_panel_io_register_event_callbacks(io_handle, &cbs, disp));
|
||
return ret;
|
||
}
|
||
|
||
|
||
|
||
esp_err_t app_touch_init(void)
|
||
{
|
||
ESP_LOGI(TAG_LVGL, "初始化 I2C 总线 (新驱动模式)");
|
||
|
||
// 1. 配置 I2C 总线
|
||
i2c_master_bus_config_t i2c_bus_config = {
|
||
.clk_source = I2C_CLK_SRC_DEFAULT,
|
||
.i2c_port = TOUCH_HOST,
|
||
.scl_io_num = EXAMPLE_PIN_NUM_TOUCH_SCL,
|
||
.sda_io_num = EXAMPLE_PIN_NUM_TOUCH_SDA,
|
||
.glitch_ignore_cnt = 7,
|
||
.flags.enable_internal_pullup = true,
|
||
};
|
||
ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_config, &touch_bus_handle_touch));
|
||
|
||
// 2. 配置触摸面板 IO(这里会自动适配新驱动)
|
||
esp_lcd_panel_io_handle_t tp_io_handle = NULL;
|
||
const esp_lcd_panel_io_i2c_config_t tp_io_config = {
|
||
.dev_addr = 0x15, // CST816/CST820 的默认地址,根据实际修改
|
||
.on_color_trans_done = NULL,
|
||
.user_ctx = NULL,
|
||
.control_phase_bytes = 1,
|
||
.dc_bit_offset = 0,
|
||
.lcd_cmd_bits = 8,
|
||
.lcd_param_bits = 8,
|
||
.scl_speed_hz = 400 * 1000,
|
||
.flags = {
|
||
.disable_control_phase = 1,
|
||
}};
|
||
|
||
// 使用新总线句柄创建 IO
|
||
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c_v2(touch_bus_handle_touch, &tp_io_config, &tp_io_handle));
|
||
|
||
// 3. 配置触摸芯片参数
|
||
const esp_lcd_touch_config_t tp_cfg = {
|
||
.x_max = EXAMPLE_LCD_H_RES,
|
||
.y_max = EXAMPLE_LCD_V_RES,
|
||
.rst_gpio_num = EXAMPLE_PIN_NUM_TOUCH_RST,
|
||
.int_gpio_num = EXAMPLE_PIN_NUM_TOUCH_INT,
|
||
.levels = {
|
||
.reset = 0,
|
||
.interrupt = 0,
|
||
},
|
||
.flags = {
|
||
.swap_xy = 1,
|
||
.mirror_x = 0,
|
||
.mirror_y = 1,
|
||
},
|
||
};
|
||
|
||
ESP_LOGI(TAG_LVGL, "创建触摸控制器句柄");
|
||
return esp_lcd_touch_new_i2c(tp_io_handle, &tp_cfg, &tp);
|
||
}
|