chore: checkpoint 第一版
ci / verify (push) Canceled after 0s

This commit is contained in:
Codex Local
2026-09-06 17:04:11 +08:00
parent a8cdec98d1
commit 0c2151ace9
659 changed files with 185855 additions and 554 deletions
@@ -0,0 +1,76 @@
set(srcs
"hw_init.c"
"input/touch_init.c"
"input/touch_rotation_helper.c"
"input/knob_init.c"
"helpers/lcd_orientation_helper.c"
)
if(CONFIG_EXAMPLE_LCD_INTERFACE_MIPI_DSI)
list(APPEND srcs "lcd/lcd_init_mipi_dsi.c")
elseif(CONFIG_EXAMPLE_LCD_INTERFACE_QSPI)
list(APPEND srcs "lcd/lcd_init_qspi.c")
elseif(CONFIG_EXAMPLE_LCD_INTERFACE_RGB)
list(APPEND srcs "lcd/lcd_init_rgb.c")
elseif(CONFIG_EXAMPLE_LCD_INTERFACE_SPI_WITH_PSRAM)
list(APPEND srcs "lcd/lcd_init_spi_with_psram.c")
elseif(CONFIG_EXAMPLE_LCD_INTERFACE_SPI_WITHOUT_PSRAM)
list(APPEND srcs "lcd/lcd_init_spi_without_psram.c")
else()
list(APPEND srcs "lcd/lcd_init_spi_with_psram.c")
endif()
set(include_dirs "." "lcd" "input" "helpers")
set(component_requires driver;esp_lcd;esp_lvgl_adapter)
if(CONFIG_EXAMPLE_LCD_INTERFACE_MIPI_DSI)
list(APPEND component_requires esp_lcd_ek79007)
list(APPEND component_requires espressif__esp_lcd_touch_gt911)
endif()
if(CONFIG_EXAMPLE_LCD_INTERFACE_QSPI)
list(APPEND component_requires esp_lcd_st77916)
list(APPEND component_requires espressif__esp_lcd_touch_cst816s)
endif()
if(CONFIG_EXAMPLE_LCD_INTERFACE_RGB)
list(APPEND component_requires espressif__esp_lcd_touch_gt1151)
endif()
if(CONFIG_EXAMPLE_LCD_INTERFACE_SPI_WITH_PSRAM)
list(APPEND component_requires espressif__esp_lcd_ili9341)
list(APPEND component_requires espressif__esp_lcd_touch_gt911)
endif()
if(CONFIG_EXAMPLE_LCD_INTERFACE_SPI_WITHOUT_PSRAM)
list(APPEND component_requires espressif__esp_lcd_gc9a01)
if("espressif__knob" IN_LIST build_components)
list(APPEND component_requires espressif__knob)
elseif("knob" IN_LIST build_components)
list(APPEND component_requires knob)
endif()
if("espressif__button" IN_LIST build_components)
list(APPEND component_requires espressif__button)
elseif("button" IN_LIST build_components)
list(APPEND component_requires button)
endif()
endif()
idf_component_register(
SRCS ${srcs}
INCLUDE_DIRS ${include_dirs}
REQUIRES ${component_requires}
)
if(CONFIG_EXAMPLE_LCD_INTERFACE_MIPI_DSI)
message(STATUS "hw_init: MIPI DSI + Touch")
elseif(CONFIG_EXAMPLE_LCD_INTERFACE_QSPI)
message(STATUS "hw_init: QSPI + Touch")
elseif(CONFIG_EXAMPLE_LCD_INTERFACE_RGB)
message(STATUS "hw_init: RGB + Touch")
elseif(CONFIG_EXAMPLE_LCD_INTERFACE_SPI_WITH_PSRAM)
message(STATUS "hw_init: SPI (PSRAM) + Touch")
elseif(CONFIG_EXAMPLE_LCD_INTERFACE_SPI_WITHOUT_PSRAM)
message(STATUS "hw_init: SPI (No PSRAM) + Encoder")
endif()
@@ -0,0 +1,79 @@
menu "Hardware Configuration"
choice EXAMPLE_LCD_INTERFACE
prompt "LCD Interface Type"
default EXAMPLE_LCD_INTERFACE_MIPI_DSI if IDF_TARGET_ESP32P4
default EXAMPLE_LCD_INTERFACE_SPI_WITH_PSRAM if IDF_TARGET_ESP32S3
default EXAMPLE_LCD_INTERFACE_SPI_WITHOUT_PSRAM if IDF_TARGET_ESP32C3
default EXAMPLE_LCD_INTERFACE_SPI_WITH_PSRAM
help
Select the LCD interface type for your display.
Resolution and input device will be set automatically based on the interface.
config EXAMPLE_LCD_INTERFACE_MIPI_DSI
bool "MIPI DSI Interface (1024x600, Touch)"
depends on IDF_TARGET_ESP32P4
help
MIPI DSI interface for high-resolution displays.
Resolution: 1024x600
Input: Touch panel
Only available on ESP32-P4.
config EXAMPLE_LCD_INTERFACE_QSPI
bool "QSPI Interface (360x360, Touch)"
depends on !IDF_TARGET_ESP32C3
help
QSPI (Quad SPI) interface for medium-resolution displays.
Resolution: 360x360
Input: Touch panel
Requires PSRAM. Not available on ESP32-C3.
config EXAMPLE_LCD_INTERFACE_RGB
bool "RGB Interface (800x480, Touch)"
depends on IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4
help
RGB parallel interface for medium to high-resolution displays.
Resolution: 800x480
Input: Touch panel
Requires PSRAM. Available on ESP32-S3 and ESP32-P4.
config EXAMPLE_LCD_INTERFACE_SPI_WITH_PSRAM
bool "SPI Interface with PSRAM (320x240, Touch)"
depends on !IDF_TARGET_ESP32C3
help
Standard SPI interface with PSRAM support.
Resolution: 320x240
Input: Touch panel
Not available on ESP32-C3.
config EXAMPLE_LCD_INTERFACE_SPI_WITHOUT_PSRAM
bool "SPI Interface without PSRAM (240x240, Encoder)"
help
Standard SPI interface without PSRAM.
Resolution: 240x240
Input: Encoder/Knob
Suitable for resource-constrained chips.
endchoice
choice EXAMPLE_DISPLAY_ROTATION
prompt "Display Rotation"
default EXAMPLE_DISPLAY_ROTATION_0
help
Select the rotation applied to both the LCD panel and the touch controller
so that LVGL coordinates match the screen orientation.
config EXAMPLE_DISPLAY_ROTATION_0
bool "Rotate 0 degrees"
config EXAMPLE_DISPLAY_ROTATION_90
bool "Rotate 90 degrees clockwise"
config EXAMPLE_DISPLAY_ROTATION_180
bool "Rotate 180 degrees"
config EXAMPLE_DISPLAY_ROTATION_270
bool "Rotate 270 degrees clockwise"
endchoice
endmenu
@@ -0,0 +1,116 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "lcd_orientation_helper.h"
typedef struct {
int m00;
int m01;
int m10;
int m11;
} lcd_orientation_matrix_t;
static lcd_orientation_matrix_t matrix_from_flags(bool swap_xy, bool mirror_x, bool mirror_y)
{
int axis_x_x = 1;
int axis_x_y = 0;
int axis_y_x = 0;
int axis_y_y = 1;
if (swap_xy) {
int tmp_x = axis_x_x;
int tmp_y = axis_x_y;
axis_x_x = axis_y_x;
axis_x_y = axis_y_y;
axis_y_x = tmp_x;
axis_y_y = tmp_y;
}
if (mirror_x) {
axis_x_x = -axis_x_x;
axis_x_y = -axis_x_y;
}
if (mirror_y) {
axis_y_x = -axis_y_x;
axis_y_y = -axis_y_y;
}
lcd_orientation_matrix_t matrix = {
.m00 = axis_x_x,
.m01 = axis_y_x,
.m10 = axis_x_y,
.m11 = axis_y_y,
};
return matrix;
}
static lcd_orientation_matrix_t matrix_multiply(lcd_orientation_matrix_t lhs, lcd_orientation_matrix_t rhs)
{
lcd_orientation_matrix_t result = {
.m00 = lhs.m00 * rhs.m00 + lhs.m01 * rhs.m10,
.m01 = lhs.m00 * rhs.m01 + lhs.m01 * rhs.m11,
.m10 = lhs.m10 * rhs.m00 + lhs.m11 * rhs.m10,
.m11 = lhs.m10 * rhs.m01 + lhs.m11 * rhs.m11,
};
return result;
}
static lcd_orientation_matrix_t matrix_from_rotation(esp_lv_adapter_rotation_t rotation)
{
switch (rotation) {
case ESP_LV_ADAPTER_ROTATE_90:
return matrix_from_flags(true, true, false);
case ESP_LV_ADAPTER_ROTATE_180:
return matrix_from_flags(false, true, true);
case ESP_LV_ADAPTER_ROTATE_270:
return matrix_from_flags(true, false, true);
case ESP_LV_ADAPTER_ROTATE_0:
default:
return matrix_from_flags(false, false, false);
}
}
void lcd_get_orientation_flags(bool base_swap_xy, bool base_mirror_x, bool base_mirror_y,
esp_lv_adapter_rotation_t rotation,
bool *swap_xy, bool *mirror_x, bool *mirror_y)
{
lcd_orientation_matrix_t base = matrix_from_flags(base_swap_xy, base_mirror_x, base_mirror_y);
lcd_orientation_matrix_t rotation_matrix = matrix_from_rotation(rotation);
lcd_orientation_matrix_t desired = matrix_multiply(rotation_matrix, base);
for (int test_swap = 0; test_swap <= 1; ++test_swap) {
for (int test_mirror_x = 0; test_mirror_x <= 1; ++test_mirror_x) {
for (int test_mirror_y = 0; test_mirror_y <= 1; ++test_mirror_y) {
lcd_orientation_matrix_t candidate = matrix_from_flags(test_swap, test_mirror_x, test_mirror_y);
if (candidate.m00 == desired.m00 &&
candidate.m01 == desired.m01 &&
candidate.m10 == desired.m10 &&
candidate.m11 == desired.m11) {
if (swap_xy) {
*swap_xy = (bool)test_swap;
}
if (mirror_x) {
*mirror_x = (bool)test_mirror_x;
}
if (mirror_y) {
*mirror_y = (bool)test_mirror_y;
}
return;
}
}
}
}
if (swap_xy) {
*swap_xy = base_swap_xy;
}
if (mirror_x) {
*mirror_x = base_mirror_x;
}
if (mirror_y) {
*mirror_y = base_mirror_y;
}
}
@@ -0,0 +1,22 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#include "esp_lv_adapter_display.h"
#ifdef __cplusplus
extern "C" {
#endif
void lcd_get_orientation_flags(bool base_swap_xy, bool base_mirror_x, bool base_mirror_y,
esp_lv_adapter_rotation_t rotation,
bool *swap_xy, bool *mirror_x, bool *mirror_y);
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,18 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "hw_init.h"
#if !CONFIG_EXAMPLE_LCD_INTERFACE_MIPI_DSI && \
!CONFIG_EXAMPLE_LCD_INTERFACE_QSPI && \
!CONFIG_EXAMPLE_LCD_INTERFACE_RGB && \
!CONFIG_EXAMPLE_LCD_INTERFACE_SPI_WITH_PSRAM && \
!CONFIG_EXAMPLE_LCD_INTERFACE_SPI_WITHOUT_PSRAM
#error "No LCD interface selected! Please select one in menuconfig."
#endif
#if !HW_USE_TOUCH && !HW_USE_ENCODER
#error "No input device configured!"
#endif
@@ -0,0 +1,75 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "esp_log.h"
#include "esp_lcd_panel_ops.h"
#include "esp_lcd_panel_io.h"
#include "esp_lv_adapter_display.h"
#include "sdkconfig.h"
#ifdef __cplusplus
extern "C" {
#endif
#if CONFIG_EXAMPLE_LCD_INTERFACE_MIPI_DSI
#define HW_LCD_H_RES 1024
#define HW_LCD_V_RES 600
#define HW_USE_TOUCH 1
#define HW_USE_ENCODER 0
#elif CONFIG_EXAMPLE_LCD_INTERFACE_QSPI
#define HW_LCD_H_RES 360
#define HW_LCD_V_RES 360
#define HW_USE_TOUCH 0
#define HW_USE_ENCODER 1
#elif CONFIG_EXAMPLE_LCD_INTERFACE_RGB
#define HW_LCD_H_RES 800
#define HW_LCD_V_RES 480
#define HW_USE_TOUCH 1
#define HW_USE_ENCODER 0
#elif CONFIG_EXAMPLE_LCD_INTERFACE_SPI_WITH_PSRAM
#define HW_LCD_H_RES 320
#define HW_LCD_V_RES 240
#define HW_USE_TOUCH 1
#define HW_USE_ENCODER 0
#elif CONFIG_EXAMPLE_LCD_INTERFACE_SPI_WITHOUT_PSRAM
#define HW_LCD_H_RES 240
#define HW_LCD_V_RES 240
#define HW_USE_TOUCH 0
#define HW_USE_ENCODER 1
#else
#define HW_LCD_H_RES 320
#define HW_LCD_V_RES 240
#define HW_USE_TOUCH 1
#define HW_USE_ENCODER 0
#endif
esp_err_t hw_lcd_init(esp_lcd_panel_handle_t *panel_handle,
esp_lcd_panel_io_handle_t *io_handle,
esp_lv_adapter_tear_avoid_mode_t tear_avoid_mode,
esp_lv_adapter_rotation_t rotation);
#if HW_USE_TOUCH
#include "esp_lcd_touch.h"
esp_err_t hw_touch_init(esp_lcd_touch_handle_t *touch_handle,
esp_lv_adapter_rotation_t rotation);
#endif
#if HW_USE_ENCODER
#include "iot_knob.h"
#include "iot_button.h"
const knob_config_t *hw_knob_get_config(void);
button_handle_t hw_knob_get_button(void);
#endif
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,31 @@
version: "1.0.0"
dependencies:
idf:
version: ">=5.5.0"
esp_lvgl_adapter:
version: "==0.1.0-beta.1"
esp_lcd_ek79007:
version: "*"
rules:
- if: "target == esp32p4"
esp_lcd_st77916:
version: "*"
esp_lcd_ili9341:
version: "^2"
esp_lcd_gc9a01:
version: "^2"
espressif/esp_lcd_touch_gt911:
version: "^1"
espressif/esp_lcd_touch_gt1151:
version: "^1"
espressif/esp_lcd_touch_cst816s:
version: "^1"
@@ -0,0 +1,66 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "hw_init.h"
#if HW_USE_ENCODER
#include <stdbool.h>
#include "esp_log.h"
#include "iot_knob.h"
#include "iot_button.h"
#include "button_gpio.h"
#define HW_ENCODER_A (GPIO_NUM_10)
#define HW_ENCODER_B (GPIO_NUM_6)
#define HW_ENCODER_ENTER (GPIO_NUM_9)
static const char *TAG = "hw_knob_init";
static const knob_config_t hw_knob_encoder_config = {
.default_direction = 0,
.gpio_encoder_a = HW_ENCODER_A,
.gpio_encoder_b = HW_ENCODER_B,
.enable_power_save = false,
};
static button_handle_t s_encoder_button_handle = NULL;
const knob_config_t *hw_knob_get_config(void)
{
return &hw_knob_encoder_config;
}
button_handle_t hw_knob_get_button(void)
{
if (s_encoder_button_handle == NULL) {
ESP_LOGI(TAG, "Initializing encoder button on GPIO %d", HW_ENCODER_ENTER);
const button_config_t btn_cfg = {
.long_press_time = 0,
.short_press_time = 0,
};
const button_gpio_config_t btn_gpio_cfg = {
.gpio_num = HW_ENCODER_ENTER,
.active_level = 0,
.enable_power_save = false,
.disable_pull = false,
};
esp_err_t ret = iot_button_new_gpio_device(&btn_cfg, &btn_gpio_cfg, &s_encoder_button_handle);
if (ret != ESP_OK || s_encoder_button_handle == NULL) {
ESP_LOGE(TAG, "Failed to create encoder button: %d", ret);
return NULL;
}
ESP_LOGI(TAG, "Encoder button initialized successfully");
}
return s_encoder_button_handle;
}
#endif
@@ -0,0 +1,142 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "driver/i2c_master.h"
#include <stdbool.h>
#include "esp_log.h"
#include "hw_init.h"
#include "input/touch_rotation_helper.h"
#if HW_USE_TOUCH
#if CONFIG_EXAMPLE_LCD_INTERFACE_RGB
#include "esp_lcd_touch_gt1151.h"
#define HW_LCD_TOUCH_RST (GPIO_NUM_NC)
#define HW_LCD_TOUCH_INT (GPIO_NUM_NC)
#define HW_I2C_SDA (GPIO_NUM_47)
#define HW_I2C_SCL (GPIO_NUM_48)
#define TOUCH_CONTROLLER_NAME "GT1151"
#define TOUCH_ROTATION_TYPE TOUCH_ROTATION_STANDARD
#define TOUCH_CONTROLLER_TYPE_GT1151 1
#elif CONFIG_EXAMPLE_LCD_INTERFACE_MIPI_DSI
#include "esp_lcd_touch_gt911.h"
#define HW_LCD_TOUCH_RST (GPIO_NUM_NC)
#define HW_LCD_TOUCH_INT (GPIO_NUM_NC)
#define HW_I2C_SDA (GPIO_NUM_7)
#define HW_I2C_SCL (GPIO_NUM_8)
#define TOUCH_CONTROLLER_NAME "GT911"
#define TOUCH_ROTATION_TYPE TOUCH_ROTATION_MIPI_DSI
#define TOUCH_CONTROLLER_TYPE_GT911 1
#elif CONFIG_EXAMPLE_LCD_INTERFACE_QSPI
#include "esp_lcd_touch_cst816s.h"
#define HW_LCD_TOUCH_RST (GPIO_NUM_NC)
#define HW_LCD_TOUCH_INT (GPIO_NUM_10)
#define HW_I2C_SDA (GPIO_NUM_2)
#define HW_I2C_SCL (GPIO_NUM_1)
#define TOUCH_CONTROLLER_NAME "CST816S"
#define TOUCH_ROTATION_TYPE TOUCH_ROTATION_STANDARD
#define TOUCH_CONTROLLER_TYPE_CST816S 1
#elif CONFIG_EXAMPLE_LCD_INTERFACE_SPI_WITH_PSRAM
#include "esp_lcd_touch_gt911.h"
#define HW_LCD_TOUCH_RST (GPIO_NUM_NC)
#define HW_LCD_TOUCH_INT (GPIO_NUM_3)
#define HW_I2C_SDA (GPIO_NUM_8)
#define HW_I2C_SCL (GPIO_NUM_18)
#define TOUCH_CONTROLLER_NAME "GT911"
#define TOUCH_ROTATION_TYPE TOUCH_ROTATION_STANDARD
#define TOUCH_CONTROLLER_TYPE_GT911 1
#else
#include "esp_lcd_touch_gt911.h"
#define HW_LCD_TOUCH_RST (GPIO_NUM_NC)
#define HW_LCD_TOUCH_INT (GPIO_NUM_NC)
#define HW_I2C_SDA (GPIO_NUM_7)
#define HW_I2C_SCL (GPIO_NUM_8)
#define TOUCH_CONTROLLER_NAME "GT911"
#define TOUCH_ROTATION_TYPE TOUCH_ROTATION_STANDARD
#define TOUCH_CONTROLLER_TYPE_GT911 1
#endif
#define HW_I2C_NUM (I2C_NUM_0)
#define HW_I2C_CLK_SPEED_HZ (400000)
static const char *TAG = "hw_touch_init";
static i2c_master_bus_handle_t s_touch_i2c_bus = NULL;
static esp_err_t hw_touch_i2c_init(void)
{
if (s_touch_i2c_bus) {
return ESP_OK;
}
i2c_master_bus_config_t i2c_bus_conf = {
.clk_source = I2C_CLK_SRC_DEFAULT,
.sda_io_num = HW_I2C_SDA,
.scl_io_num = HW_I2C_SCL,
.i2c_port = HW_I2C_NUM,
};
ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_conf, &s_touch_i2c_bus));
return ESP_OK;
}
esp_err_t hw_touch_init(esp_lcd_touch_handle_t *ret_touch, esp_lv_adapter_rotation_t rotation)
{
ESP_LOGI(TAG, "Initializing touch controller (%s)", TOUCH_CONTROLLER_NAME);
ESP_ERROR_CHECK(hw_touch_i2c_init());
bool swap_xy = false;
bool mirror_x = false;
bool mirror_y = false;
touch_get_rotation_flags(TOUCH_ROTATION_TYPE, rotation, &swap_xy, &mirror_x, &mirror_y);
const esp_lcd_touch_config_t tp_cfg = {
.x_max = HW_LCD_H_RES,
.y_max = HW_LCD_V_RES,
.rst_gpio_num = HW_LCD_TOUCH_RST,
.int_gpio_num = HW_LCD_TOUCH_INT,
.levels = {
.reset = 0,
.interrupt = 0,
},
.flags = {
.swap_xy = swap_xy,
.mirror_x = mirror_x,
.mirror_y = mirror_y,
},
};
esp_lcd_panel_io_handle_t tp_io_handle = NULL;
/* Initialize touch controller based on type */
#if defined(TOUCH_CONTROLLER_TYPE_GT1151)
esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_GT1151_CONFIG();
tp_io_config.scl_speed_hz = HW_I2C_CLK_SPEED_HZ;
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(s_touch_i2c_bus, &tp_io_config, &tp_io_handle));
return esp_lcd_touch_new_i2c_gt1151(tp_io_handle, &tp_cfg, ret_touch);
#elif defined(TOUCH_CONTROLLER_TYPE_CST816S)
esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_CST816S_CONFIG();
tp_io_config.scl_speed_hz = HW_I2C_CLK_SPEED_HZ;
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(s_touch_i2c_bus, &tp_io_config, &tp_io_handle));
return esp_lcd_touch_new_i2c_cst816s(tp_io_handle, &tp_cfg, ret_touch);
#elif defined(TOUCH_CONTROLLER_TYPE_GT911)
esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_GT911_CONFIG();
tp_io_config.scl_speed_hz = HW_I2C_CLK_SPEED_HZ;
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(s_touch_i2c_bus, &tp_io_config, &tp_io_handle));
return esp_lcd_touch_new_i2c_gt911(tp_io_handle, &tp_cfg, ret_touch);
#else
#error "No touch controller type defined"
#endif
}
#endif
@@ -0,0 +1,78 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "touch_rotation_helper.h"
void touch_get_rotation_flags(touch_rotation_type_t type, esp_lv_adapter_rotation_t rotation,
bool *swap_xy, bool *mirror_x, bool *mirror_y)
{
bool swap = false;
bool x_mirror, y_mirror;
if (type == TOUCH_ROTATION_MIPI_DSI) {
x_mirror = true;
y_mirror = true;
switch (rotation) {
case ESP_LV_ADAPTER_ROTATE_90:
swap = true;
x_mirror = false;
y_mirror = true;
break;
case ESP_LV_ADAPTER_ROTATE_180:
swap = false;
x_mirror = false;
y_mirror = false;
break;
case ESP_LV_ADAPTER_ROTATE_270:
swap = true;
x_mirror = true;
y_mirror = false;
break;
case ESP_LV_ADAPTER_ROTATE_0:
default:
swap = false;
x_mirror = true;
y_mirror = true;
break;
}
} else {
x_mirror = false;
y_mirror = false;
switch (rotation) {
case ESP_LV_ADAPTER_ROTATE_90:
swap = true;
x_mirror = true;
y_mirror = false;
break;
case ESP_LV_ADAPTER_ROTATE_180:
swap = false;
x_mirror = true;
y_mirror = true;
break;
case ESP_LV_ADAPTER_ROTATE_270:
swap = true;
x_mirror = false;
y_mirror = true;
break;
case ESP_LV_ADAPTER_ROTATE_0:
default:
swap = false;
x_mirror = false;
y_mirror = false;
break;
}
}
if (swap_xy) {
*swap_xy = swap;
}
if (mirror_x) {
*mirror_x = x_mirror;
}
if (mirror_y) {
*mirror_y = y_mirror;
}
}
@@ -0,0 +1,26 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#include "esp_lv_adapter_display.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
TOUCH_ROTATION_STANDARD,
TOUCH_ROTATION_MIPI_DSI,
} touch_rotation_type_t;
void touch_get_rotation_flags(touch_rotation_type_t type, esp_lv_adapter_rotation_t rotation,
bool *swap_xy, bool *mirror_x, bool *mirror_y);
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,78 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*/
#include "hw_init.h"
#if CONFIG_EXAMPLE_LCD_INTERFACE_MIPI_DSI
#include "esp_ldo_regulator.h"
#include "esp_lcd_mipi_dsi.h"
#include "esp_lcd_panel_ops.h"
#include "esp_lcd_ek79007.h"
#include "driver/gpio.h"
static const char *TAG = "hw_lcd_init";
#define HW_LDO_MIPI_CHAN (3)
#define HW_LDO_MIPI_VOLTAGE_MV (2500)
#define HW_LCD_BIT_PER_PIXEL (16)
#define HW_MIPI_DPI_PX_FORMAT (LCD_COLOR_PIXEL_FORMAT_RGB565)
#define HW_PIN_NUM_LCD_RST (27)
static esp_lcd_dsi_bus_handle_t s_mipi_dsi_bus;
static esp_lcd_panel_io_handle_t s_mipi_dbi_io;
static esp_lcd_panel_handle_t s_panel_handle;
static void lcd_ldo_power_on(void)
{
esp_ldo_channel_handle_t ldo_mipi_phy = NULL;
esp_ldo_channel_config_t ldo_mipi_phy_config = {
.chan_id = HW_LDO_MIPI_CHAN,
.voltage_mv = HW_LDO_MIPI_VOLTAGE_MV,
};
ESP_ERROR_CHECK(esp_ldo_acquire_channel(&ldo_mipi_phy_config, &ldo_mipi_phy));
}
esp_err_t hw_lcd_init(esp_lcd_panel_handle_t *panel_handle, esp_lcd_panel_io_handle_t *io_handle, esp_lv_adapter_tear_avoid_mode_t tear_avoid_mode, esp_lv_adapter_rotation_t rotation)
{
lcd_ldo_power_on();
ESP_LOGD(TAG, "Install LCD driver");
esp_lcd_dsi_bus_config_t bus_config = EK79007_PANEL_BUS_DSI_2CH_CONFIG();
ESP_ERROR_CHECK(esp_lcd_new_dsi_bus(&bus_config, &s_mipi_dsi_bus));
ESP_LOGI(TAG, "Install panel IO");
esp_lcd_dbi_io_config_t dbi_config = EK79007_PANEL_IO_DBI_CONFIG();
ESP_ERROR_CHECK(esp_lcd_new_panel_io_dbi(s_mipi_dsi_bus, &dbi_config, &s_mipi_dbi_io));
ESP_LOGI(TAG, "Install LCD driver of ek79007");
esp_lcd_dpi_panel_config_t dpi_config = EK79007_1024_600_PANEL_60HZ_CONFIG(HW_MIPI_DPI_PX_FORMAT);
dpi_config.num_fbs = esp_lv_adapter_get_required_frame_buffer_count(tear_avoid_mode, rotation);
ek79007_vendor_config_t vendor_config = {
.mipi_config = {
.dsi_bus = s_mipi_dsi_bus,
.dpi_config = &dpi_config,
},
};
const esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = HW_PIN_NUM_LCD_RST,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = HW_LCD_BIT_PER_PIXEL,
.vendor_config = &vendor_config,
};
ESP_ERROR_CHECK(esp_lcd_new_panel_ek79007(s_mipi_dbi_io, &panel_config, &s_panel_handle));
ESP_ERROR_CHECK(esp_lcd_panel_reset(s_panel_handle));
ESP_ERROR_CHECK(esp_lcd_panel_init(s_panel_handle));
*panel_handle = s_panel_handle;
if (io_handle) {
*io_handle = s_mipi_dbi_io;
}
return ESP_OK;
}
#endif
@@ -0,0 +1,314 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*/
#include "esp_system.h"
#include "esp_lcd_st77916.h"
#include "driver/gpio.h"
#include "hw_init.h"
#include "helpers/lcd_orientation_helper.h"
#if CONFIG_EXAMPLE_LCD_INTERFACE_QSPI
static const char *TAG = "hw_lcd_init";
#define HW_PIN_NUM_BK_LIGHT (GPIO_NUM_44)
#define HW_LCD_BK_LIGHT_ON_LEVEL (1)
#define HW_LCD_BASE_SWAP_XY (false)
#define HW_LCD_BASE_MIRROR_X (false)
#define HW_LCD_BASE_MIRROR_Y (false)
#define HW_LCD_DATA3 (GPIO_NUM_12)
#define HW_LCD_DATA2 (GPIO_NUM_11)
#define HW_LCD_DATA1 (GPIO_NUM_13)
#define HW_LCD_DATA0 (GPIO_NUM_46)
#define HW_LCD_PCLK (GPIO_NUM_18)
#define HW_LCD_CS (GPIO_NUM_14)
#define HW_LCD_DC (GPIO_NUM_45)
#define HW_LCD_RST (GPIO_NUM_47)
#define HW_LCD_POWER_OFF (GPIO_NUM_9)
#define HW_LCD_PIXEL_CLOCK_HZ (80 * 1000 * 1000)
#define HW_LCD_COLOR_SPACE (LCD_RGB_ELEMENT_ORDER_RGB)
#define HW_LCD_BITS_PER_PIXEL (16)
#define HW_LCD_CMD_BITS (32)
#define HW_LCD_PARAM_BITS (8)
#define HW_LCD_MAX_TRANSFER_SZ (HW_LCD_H_RES * HW_LCD_V_RES * 2)
static esp_lcd_panel_io_handle_t s_panel_io_handle;
static esp_lcd_panel_handle_t s_panel_handle;
static const st77916_lcd_init_cmd_t st77916_qspi_init[] = {
{0xF0, (uint8_t []){0x28}, 1, 0},
{0xF2, (uint8_t []){0x28}, 1, 0},
{0x73, (uint8_t []){0xF0}, 1, 0},
{0x7C, (uint8_t []){0xD1}, 1, 0},
{0x83, (uint8_t []){0xE0}, 1, 0},
{0x84, (uint8_t []){0x61}, 1, 0},
{0xF2, (uint8_t []){0x82}, 1, 0},
{0xF0, (uint8_t []){0x00}, 1, 0},
{0xF0, (uint8_t []){0x01}, 1, 0},
{0xF1, (uint8_t []){0x01}, 1, 0},
{0xB0, (uint8_t []){0x56}, 1, 0},
{0xB1, (uint8_t []){0x4D}, 1, 0},
{0xB2, (uint8_t []){0x24}, 1, 0},
{0xB4, (uint8_t []){0x87}, 1, 0},
{0xB5, (uint8_t []){0x44}, 1, 0},
{0xB6, (uint8_t []){0x8B}, 1, 0},
{0xB7, (uint8_t []){0x40}, 1, 0},
{0xB8, (uint8_t []){0x86}, 1, 0},
{0xBA, (uint8_t []){0x00}, 1, 0},
{0xBB, (uint8_t []){0x08}, 1, 0},
{0xBC, (uint8_t []){0x08}, 1, 0},
{0xBD, (uint8_t []){0x00}, 1, 0},
{0xC0, (uint8_t []){0x80}, 1, 0},
{0xC1, (uint8_t []){0x10}, 1, 0},
{0xC2, (uint8_t []){0x37}, 1, 0},
{0xC3, (uint8_t []){0x80}, 1, 0},
{0xC4, (uint8_t []){0x10}, 1, 0},
{0xC5, (uint8_t []){0x37}, 1, 0},
{0xC6, (uint8_t []){0xA9}, 1, 0},
{0xC7, (uint8_t []){0x41}, 1, 0},
{0xC8, (uint8_t []){0x01}, 1, 0},
{0xC9, (uint8_t []){0xA9}, 1, 0},
{0xCA, (uint8_t []){0x41}, 1, 0},
{0xCB, (uint8_t []){0x01}, 1, 0},
{0xD0, (uint8_t []){0x91}, 1, 0},
{0xD1, (uint8_t []){0x68}, 1, 0},
{0xD2, (uint8_t []){0x68}, 1, 0},
{0xF5, (uint8_t []){0x00, 0xA5}, 2, 0},
{0xDD, (uint8_t []){0x4F}, 1, 0},
{0xDE, (uint8_t []){0x4F}, 1, 0},
{0xF1, (uint8_t []){0x10}, 1, 0},
{0xF0, (uint8_t []){0x00}, 1, 0},
{0xF0, (uint8_t []){0x02}, 1, 0},
{0xE0, (uint8_t []){0xF0, 0x0A, 0x10, 0x09, 0x09, 0x36, 0x35, 0x33, 0x4A, 0x29, 0x15, 0x15, 0x2E, 0x34}, 14, 0},
{0xE1, (uint8_t []){0xF0, 0x0A, 0x0F, 0x08, 0x08, 0x05, 0x34, 0x33, 0x4A, 0x39, 0x15, 0x15, 0x2D, 0x33}, 14, 0},
{0xF0, (uint8_t []){0x10}, 1, 0},
{0xF3, (uint8_t []){0x10}, 1, 0},
{0xE0, (uint8_t []){0x07}, 1, 0},
{0xE1, (uint8_t []){0x00}, 1, 0},
{0xE2, (uint8_t []){0x00}, 1, 0},
{0xE3, (uint8_t []){0x00}, 1, 0},
{0xE4, (uint8_t []){0xE0}, 1, 0},
{0xE5, (uint8_t []){0x06}, 1, 0},
{0xE6, (uint8_t []){0x21}, 1, 0},
{0xE7, (uint8_t []){0x01}, 1, 0},
{0xE8, (uint8_t []){0x05}, 1, 0},
{0xE9, (uint8_t []){0x02}, 1, 0},
{0xEA, (uint8_t []){0xDA}, 1, 0},
{0xEB, (uint8_t []){0x00}, 1, 0},
{0xEC, (uint8_t []){0x00}, 1, 0},
{0xED, (uint8_t []){0x0F}, 1, 0},
{0xEE, (uint8_t []){0x00}, 1, 0},
{0xEF, (uint8_t []){0x00}, 1, 0},
{0xF8, (uint8_t []){0x00}, 1, 0},
{0xF9, (uint8_t []){0x00}, 1, 0},
{0xFA, (uint8_t []){0x00}, 1, 0},
{0xFB, (uint8_t []){0x00}, 1, 0},
{0xFC, (uint8_t []){0x00}, 1, 0},
{0xFD, (uint8_t []){0x00}, 1, 0},
{0xFE, (uint8_t []){0x00}, 1, 0},
{0xFF, (uint8_t []){0x00}, 1, 0},
{0x60, (uint8_t []){0x40}, 1, 0},
{0x61, (uint8_t []){0x04}, 1, 0},
{0x62, (uint8_t []){0x00}, 1, 0},
{0x63, (uint8_t []){0x42}, 1, 0},
{0x64, (uint8_t []){0xD9}, 1, 0},
{0x65, (uint8_t []){0x00}, 1, 0},
{0x66, (uint8_t []){0x00}, 1, 0},
{0x67, (uint8_t []){0x00}, 1, 0},
{0x68, (uint8_t []){0x00}, 1, 0},
{0x69, (uint8_t []){0x00}, 1, 0},
{0x6A, (uint8_t []){0x00}, 1, 0},
{0x6B, (uint8_t []){0x00}, 1, 0},
{0x70, (uint8_t []){0x40}, 1, 0},
{0x71, (uint8_t []){0x03}, 1, 0},
{0x72, (uint8_t []){0x00}, 1, 0},
{0x73, (uint8_t []){0x42}, 1, 0},
{0x74, (uint8_t []){0xD8}, 1, 0},
{0x75, (uint8_t []){0x00}, 1, 0},
{0x76, (uint8_t []){0x00}, 1, 0},
{0x77, (uint8_t []){0x00}, 1, 0},
{0x78, (uint8_t []){0x00}, 1, 0},
{0x79, (uint8_t []){0x00}, 1, 0},
{0x7A, (uint8_t []){0x00}, 1, 0},
{0x7B, (uint8_t []){0x00}, 1, 0},
{0x80, (uint8_t []){0x48}, 1, 0},
{0x81, (uint8_t []){0x00}, 1, 0},
{0x82, (uint8_t []){0x06}, 1, 0},
{0x83, (uint8_t []){0x02}, 1, 0},
{0x84, (uint8_t []){0xD6}, 1, 0},
{0x85, (uint8_t []){0x04}, 1, 0},
{0x86, (uint8_t []){0x00}, 1, 0},
{0x87, (uint8_t []){0x00}, 1, 0},
{0x88, (uint8_t []){0x48}, 1, 0},
{0x89, (uint8_t []){0x00}, 1, 0},
{0x8A, (uint8_t []){0x08}, 1, 0},
{0x8B, (uint8_t []){0x02}, 1, 0},
{0x8C, (uint8_t []){0xD8}, 1, 0},
{0x8D, (uint8_t []){0x04}, 1, 0},
{0x8E, (uint8_t []){0x00}, 1, 0},
{0x8F, (uint8_t []){0x00}, 1, 0},
{0x90, (uint8_t []){0x48}, 1, 0},
{0x91, (uint8_t []){0x00}, 1, 0},
{0x92, (uint8_t []){0x0A}, 1, 0},
{0x93, (uint8_t []){0x02}, 1, 0},
{0x94, (uint8_t []){0xDA}, 1, 0},
{0x95, (uint8_t []){0x04}, 1, 0},
{0x96, (uint8_t []){0x00}, 1, 0},
{0x97, (uint8_t []){0x00}, 1, 0},
{0x98, (uint8_t []){0x48}, 1, 0},
{0x99, (uint8_t []){0x00}, 1, 0},
{0x9A, (uint8_t []){0x0C}, 1, 0},
{0x9B, (uint8_t []){0x02}, 1, 0},
{0x9C, (uint8_t []){0xDC}, 1, 0},
{0x9D, (uint8_t []){0x04}, 1, 0},
{0x9E, (uint8_t []){0x00}, 1, 0},
{0x9F, (uint8_t []){0x00}, 1, 0},
{0xA0, (uint8_t []){0x48}, 1, 0},
{0xA1, (uint8_t []){0x00}, 1, 0},
{0xA2, (uint8_t []){0x05}, 1, 0},
{0xA3, (uint8_t []){0x02}, 1, 0},
{0xA4, (uint8_t []){0xD5}, 1, 0},
{0xA5, (uint8_t []){0x04}, 1, 0},
{0xA6, (uint8_t []){0x00}, 1, 0},
{0xA7, (uint8_t []){0x00}, 1, 0},
{0xA8, (uint8_t []){0x48}, 1, 0},
{0xA9, (uint8_t []){0x00}, 1, 0},
{0xAA, (uint8_t []){0x07}, 1, 0},
{0xAB, (uint8_t []){0x02}, 1, 0},
{0xAC, (uint8_t []){0xD7}, 1, 0},
{0xAD, (uint8_t []){0x04}, 1, 0},
{0xAE, (uint8_t []){0x00}, 1, 0},
{0xAF, (uint8_t []){0x00}, 1, 0},
{0xB0, (uint8_t []){0x48}, 1, 0},
{0xB1, (uint8_t []){0x00}, 1, 0},
{0xB2, (uint8_t []){0x09}, 1, 0},
{0xB3, (uint8_t []){0x02}, 1, 0},
{0xB4, (uint8_t []){0xD9}, 1, 0},
{0xB5, (uint8_t []){0x04}, 1, 0},
{0xB6, (uint8_t []){0x00}, 1, 0},
{0xB7, (uint8_t []){0x00}, 1, 0},
{0xB8, (uint8_t []){0x48}, 1, 0},
{0xB9, (uint8_t []){0x00}, 1, 0},
{0xBA, (uint8_t []){0x0B}, 1, 0},
{0xBB, (uint8_t []){0x02}, 1, 0},
{0xBC, (uint8_t []){0xDB}, 1, 0},
{0xBD, (uint8_t []){0x04}, 1, 0},
{0xBE, (uint8_t []){0x00}, 1, 0},
{0xBF, (uint8_t []){0x00}, 1, 0},
{0xC0, (uint8_t []){0x10}, 1, 0},
{0xC1, (uint8_t []){0x47}, 1, 0},
{0xC2, (uint8_t []){0x56}, 1, 0},
{0xC3, (uint8_t []){0x65}, 1, 0},
{0xC4, (uint8_t []){0x74}, 1, 0},
{0xC5, (uint8_t []){0x88}, 1, 0},
{0xC6, (uint8_t []){0x99}, 1, 0},
{0xC7, (uint8_t []){0x01}, 1, 0},
{0xC8, (uint8_t []){0xBB}, 1, 0},
{0xC9, (uint8_t []){0xAA}, 1, 0},
{0xD0, (uint8_t []){0x10}, 1, 0},
{0xD1, (uint8_t []){0x47}, 1, 0},
{0xD2, (uint8_t []){0x56}, 1, 0},
{0xD3, (uint8_t []){0x65}, 1, 0},
{0xD4, (uint8_t []){0x74}, 1, 0},
{0xD5, (uint8_t []){0x88}, 1, 0},
{0xD6, (uint8_t []){0x99}, 1, 0},
{0xD7, (uint8_t []){0x01}, 1, 0},
{0xD8, (uint8_t []){0xBB}, 1, 0},
{0xD9, (uint8_t []){0xAA}, 1, 0},
{0xF3, (uint8_t []){0x01}, 1, 0},
{0xF0, (uint8_t []){0x00}, 1, 0},
{0x21, (uint8_t []){}, 0, 0},
{0x11, (uint8_t []){}, 0, 0},
{0x00, (uint8_t []){}, 0, 120},
};
esp_err_t hw_lcd_init(esp_lcd_panel_handle_t *panel_handle, esp_lcd_panel_io_handle_t *io_handle, esp_lv_adapter_tear_avoid_mode_t tear_avoid_mode, esp_lv_adapter_rotation_t rotation)
{
ESP_LOGD(TAG, "Initialize QSPI bus");
const spi_bus_config_t buscfg = {
.sclk_io_num = HW_LCD_PCLK,
.data0_io_num = HW_LCD_DATA0,
.data1_io_num = HW_LCD_DATA1,
.data2_io_num = HW_LCD_DATA2,
.data3_io_num = HW_LCD_DATA3,
.max_transfer_sz = HW_LCD_MAX_TRANSFER_SZ,
.flags = SPICOMMON_BUSFLAG_QUAD,
};
ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO));
ESP_LOGD(TAG, "Install panel IO");
esp_lcd_panel_io_spi_config_t io_config = {
.dc_gpio_num = HW_LCD_DC,
.cs_gpio_num = HW_LCD_CS,
.pclk_hz = HW_LCD_PIXEL_CLOCK_HZ,
.lcd_cmd_bits = HW_LCD_CMD_BITS,
.lcd_param_bits = HW_LCD_PARAM_BITS,
.spi_mode = 0,
.trans_queue_depth = 1,
.flags = {
.quad_mode = 1,
},
};
ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)SPI2_HOST, &io_config, &s_panel_io_handle));
ESP_LOGD(TAG, "Power on LCD");
gpio_config_t power_gpio_config = {
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = 1ULL << HW_LCD_POWER_OFF
};
ESP_ERROR_CHECK(gpio_config(&power_gpio_config));
gpio_set_level(HW_LCD_POWER_OFF, 0);
ESP_LOGD(TAG, "Install LCD driver");
const st77916_vendor_config_t vendor_config = {
.init_cmds = st77916_qspi_init,
.init_cmds_size = sizeof(st77916_qspi_init) / sizeof(st77916_lcd_init_cmd_t),
.flags = {
.use_qspi_interface = 1,
},
};
esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = HW_LCD_RST,
.rgb_ele_order = HW_LCD_COLOR_SPACE,
.bits_per_pixel = HW_LCD_BITS_PER_PIXEL,
.vendor_config = (void *) &vendor_config,
.flags = {
.reset_active_high = true,
},
};
ESP_LOGI(TAG, "Install st77916 panel driver");
ESP_ERROR_CHECK(esp_lcd_new_panel_st77916(s_panel_io_handle, (const esp_lcd_panel_dev_config_t *)&panel_config, &s_panel_handle));
esp_lcd_panel_reset(s_panel_handle);
esp_lcd_panel_init(s_panel_handle);
bool swap_xy = false;
bool mirror_x = false;
bool mirror_y = false;
lcd_get_orientation_flags(HW_LCD_BASE_SWAP_XY, HW_LCD_BASE_MIRROR_X, HW_LCD_BASE_MIRROR_Y,
rotation, &swap_xy, &mirror_x, &mirror_y);
ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(s_panel_handle, swap_xy));
ESP_ERROR_CHECK(esp_lcd_panel_mirror(s_panel_handle, mirror_x, mirror_y));
esp_lcd_panel_disp_on_off(s_panel_handle, true);
*io_handle = s_panel_io_handle;
*panel_handle = s_panel_handle;
gpio_config_t bk_gpio_config = {
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = 1ULL << HW_PIN_NUM_BK_LIGHT
};
ESP_ERROR_CHECK(gpio_config(&bk_gpio_config));
ESP_LOGI(TAG, "Turning on LCD backlight");
gpio_set_level(HW_PIN_NUM_BK_LIGHT, HW_LCD_BK_LIGHT_ON_LEVEL);
return ESP_OK;
}
#endif
@@ -0,0 +1,113 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*/
#include "hw_init.h"
#if CONFIG_EXAMPLE_LCD_INTERFACE_RGB
#include "esp_lcd_panel_rgb.h"
#include "driver/gpio.h"
static const char *TAG = "hw_lcd_init";
#define HW_LCD_PIXEL_CLOCK_HZ (18 * 1000 * 1000)
#define HW_LCD_HSYNC (40)
#define HW_LCD_HBP (40)
#define HW_LCD_HFP (48)
#define HW_LCD_VSYNC (23)
#define HW_LCD_VBP (32)
#define HW_LCD_VFP (13)
#define HW_LCD_RGB_VSYNC (GPIO_NUM_3)
#define HW_LCD_RGB_HSYNC (GPIO_NUM_46)
#define HW_LCD_RGB_DE (GPIO_NUM_17)
#define HW_LCD_RGB_PCLK (GPIO_NUM_9)
#define HW_LCD_RGB_DISP (GPIO_NUM_NC)
#define HW_LCD_RGB_DATA0 (GPIO_NUM_10)
#define HW_LCD_RGB_DATA1 (GPIO_NUM_11)
#define HW_LCD_RGB_DATA2 (GPIO_NUM_12)
#define HW_LCD_RGB_DATA3 (GPIO_NUM_13)
#define HW_LCD_RGB_DATA4 (GPIO_NUM_14)
#define HW_LCD_RGB_DATA5 (GPIO_NUM_21)
#define HW_LCD_RGB_DATA6 (GPIO_NUM_8)
#define HW_LCD_RGB_DATA7 (GPIO_NUM_18)
#define HW_LCD_RGB_DATA8 (GPIO_NUM_45)
#define HW_LCD_RGB_DATA9 (GPIO_NUM_38)
#define HW_LCD_RGB_DATA10 (GPIO_NUM_39)
#define HW_LCD_RGB_DATA11 (GPIO_NUM_40)
#define HW_LCD_RGB_DATA12 (GPIO_NUM_41)
#define HW_LCD_RGB_DATA13 (GPIO_NUM_42)
#define HW_LCD_RGB_DATA14 (GPIO_NUM_2)
#define HW_LCD_RGB_DATA15 (GPIO_NUM_1)
#define HW_LCD_DATA_WIDTH (16)
#define HW_LCD_BIT_PER_PIXEL (16)
#define HW_LCD_BOUNCE_BUFFER_HEIGHT (20)
static esp_lcd_panel_handle_t s_panel_handle;
esp_err_t hw_lcd_init(esp_lcd_panel_handle_t *panel_handle, esp_lcd_panel_io_handle_t *io_handle, esp_lv_adapter_tear_avoid_mode_t tear_avoid_mode, esp_lv_adapter_rotation_t rotation)
{
ESP_LOGI(TAG, "Initialize RGB panel");
esp_lcd_rgb_panel_config_t panel_conf = {
.clk_src = LCD_CLK_SRC_DEFAULT,
.dma_burst_size = 64,
.data_width = HW_LCD_DATA_WIDTH,
.bits_per_pixel = HW_LCD_BIT_PER_PIXEL,
.de_gpio_num = HW_LCD_RGB_DE,
.pclk_gpio_num = HW_LCD_RGB_PCLK,
.vsync_gpio_num = HW_LCD_RGB_VSYNC,
.hsync_gpio_num = HW_LCD_RGB_HSYNC,
.disp_gpio_num = HW_LCD_RGB_DISP,
.data_gpio_nums = {
HW_LCD_RGB_DATA0,
HW_LCD_RGB_DATA1,
HW_LCD_RGB_DATA2,
HW_LCD_RGB_DATA3,
HW_LCD_RGB_DATA4,
HW_LCD_RGB_DATA5,
HW_LCD_RGB_DATA6,
HW_LCD_RGB_DATA7,
HW_LCD_RGB_DATA8,
HW_LCD_RGB_DATA9,
HW_LCD_RGB_DATA10,
HW_LCD_RGB_DATA11,
HW_LCD_RGB_DATA12,
HW_LCD_RGB_DATA13,
HW_LCD_RGB_DATA14,
HW_LCD_RGB_DATA15,
},
.timings = {
.pclk_hz = HW_LCD_PIXEL_CLOCK_HZ,
.h_res = HW_LCD_H_RES,
.v_res = HW_LCD_V_RES,
.hsync_back_porch = HW_LCD_HBP,
.hsync_front_porch = HW_LCD_HFP,
.hsync_pulse_width = HW_LCD_HSYNC,
.vsync_back_porch = HW_LCD_VBP,
.vsync_front_porch = HW_LCD_VFP,
.vsync_pulse_width = HW_LCD_VSYNC,
.flags = {
.pclk_active_neg = true,
},
},
.flags.fb_in_psram = 1,
.num_fbs = esp_lv_adapter_get_required_frame_buffer_count(tear_avoid_mode, rotation),
.bounce_buffer_size_px = HW_LCD_H_RES * HW_LCD_BOUNCE_BUFFER_HEIGHT,
};
ESP_ERROR_CHECK(esp_lcd_new_rgb_panel(&panel_conf, &s_panel_handle));
ESP_ERROR_CHECK(esp_lcd_panel_reset(s_panel_handle));
ESP_ERROR_CHECK(esp_lcd_panel_init(s_panel_handle));
*panel_handle = s_panel_handle;
if (io_handle) {
*io_handle = NULL;
}
return ESP_OK;
}
#endif
@@ -0,0 +1,123 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*/
#include "esp_system.h"
#include "esp_lcd_ili9341.h"
#include "driver/gpio.h"
#include "hw_init.h"
#include "helpers/lcd_orientation_helper.h"
#if CONFIG_EXAMPLE_LCD_INTERFACE_SPI_WITH_PSRAM
static const char *TAG = "hw_lcd_init";
#define HW_PIN_NUM_BK_LIGHT (GPIO_NUM_47)
#define HW_LCD_BK_LIGHT_ON_LEVEL (1)
#define HW_LCD_BASE_SWAP_XY (false)
#define HW_LCD_BASE_MIRROR_X (true)
#define HW_LCD_BASE_MIRROR_Y (true)
#define HW_LCD_DATA0 (GPIO_NUM_6)
#define HW_LCD_PCLK (GPIO_NUM_7)
#define HW_LCD_CS (GPIO_NUM_5)
#define HW_LCD_DC (GPIO_NUM_4)
#define HW_LCD_RST (GPIO_NUM_48)
#define HW_LCD_PIXEL_CLOCK_HZ (40 * 1000 * 1000)
#define HW_LCD_COLOR_SPACE (LCD_RGB_ELEMENT_ORDER_RGB)
#define HW_LCD_BITS_PER_PIXEL (16)
#define HW_LCD_CMD_BITS (8)
#define HW_LCD_PARAM_BITS (8)
#define HW_LCD_MAX_TRANSFER_SZ (HW_LCD_H_RES * HW_LCD_V_RES * 2)
static esp_lcd_panel_io_handle_t s_panel_io_handle;
static esp_lcd_panel_handle_t s_panel_handle;
static const ili9341_lcd_init_cmd_t vendor_specific_init_default[] = {
{0xC8, (uint8_t []){0xFF, 0x93, 0x42}, 3, 0},
{0xC0, (uint8_t []){0x0E, 0x0E}, 2, 0},
{0xC5, (uint8_t []){0xD0}, 1, 0},
{0xC1, (uint8_t []){0x02}, 1, 0},
{0xB4, (uint8_t []){0x02}, 1, 0},
{0xE0, (uint8_t []){0x00, 0x03, 0x08, 0x06, 0x13, 0x09, 0x39, 0x39, 0x48, 0x02, 0x0a, 0x08, 0x17, 0x17, 0x0F}, 15, 0},
{0xE1, (uint8_t []){0x00, 0x28, 0x29, 0x01, 0x0d, 0x03, 0x3f, 0x33, 0x52, 0x04, 0x0f, 0x0e, 0x37, 0x38, 0x0F}, 15, 0},
{0xB1, (uint8_t []){00, 0x1B}, 2, 0},
{0x36, (uint8_t []){0x08}, 1, 0},
{0x3A, (uint8_t []){0x55}, 1, 0},
{0xB7, (uint8_t []){0x06}, 1, 0},
{0x11, (uint8_t []){0}, 0x80, 0},
{0x29, (uint8_t []){0}, 0x80, 0},
{0, (uint8_t []){0}, 0xff, 0},
};
esp_err_t hw_lcd_init(esp_lcd_panel_handle_t *panel_handle, esp_lcd_panel_io_handle_t *io_handle, esp_lv_adapter_tear_avoid_mode_t tear_avoid_mode, esp_lv_adapter_rotation_t rotation)
{
ESP_LOGD(TAG, "Initialize SPI bus");
const spi_bus_config_t buscfg = {
.sclk_io_num = HW_LCD_PCLK,
.mosi_io_num = HW_LCD_DATA0,
.miso_io_num = GPIO_NUM_NC,
.quadwp_io_num = GPIO_NUM_NC,
.quadhd_io_num = GPIO_NUM_NC,
.max_transfer_sz = HW_LCD_MAX_TRANSFER_SZ,
};
ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO));
ESP_LOGD(TAG, "Install panel IO");
esp_lcd_panel_io_spi_config_t io_config = {
.dc_gpio_num = HW_LCD_DC,
.cs_gpio_num = HW_LCD_CS,
.pclk_hz = HW_LCD_PIXEL_CLOCK_HZ,
.lcd_cmd_bits = HW_LCD_CMD_BITS,
.lcd_param_bits = HW_LCD_PARAM_BITS,
.spi_mode = 0,
.trans_queue_depth = 1,
};
ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)SPI2_HOST, &io_config, &s_panel_io_handle));
ESP_LOGD(TAG, "Install LCD driver");
const ili9341_vendor_config_t vendor_config = {
.init_cmds = vendor_specific_init_default,
.init_cmds_size = sizeof(vendor_specific_init_default) / sizeof(vendor_specific_init_default[0]),
};
esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = HW_LCD_RST,
.flags.reset_active_high = true,
.rgb_ele_order = HW_LCD_COLOR_SPACE,
.bits_per_pixel = HW_LCD_BITS_PER_PIXEL,
.vendor_config = (void *) &vendor_config,
};
ESP_LOGI(TAG, "Install ili9341 panel driver");
ESP_ERROR_CHECK(esp_lcd_new_panel_ili9341(s_panel_io_handle, (const esp_lcd_panel_dev_config_t *)&panel_config, &s_panel_handle));
esp_lcd_panel_reset(s_panel_handle);
esp_lcd_panel_init(s_panel_handle);
bool swap_xy = false;
bool mirror_x = true;
bool mirror_y = true;
lcd_get_orientation_flags(HW_LCD_BASE_SWAP_XY, HW_LCD_BASE_MIRROR_X, HW_LCD_BASE_MIRROR_Y,
rotation, &swap_xy, &mirror_x, &mirror_y);
ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(s_panel_handle, swap_xy));
ESP_ERROR_CHECK(esp_lcd_panel_mirror(s_panel_handle, mirror_x, mirror_y));
esp_lcd_panel_disp_on_off(s_panel_handle, true);
*io_handle = s_panel_io_handle;
*panel_handle = s_panel_handle;
gpio_config_t bk_gpio_config = {
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = 1ULL << HW_PIN_NUM_BK_LIGHT
};
ESP_ERROR_CHECK(gpio_config(&bk_gpio_config));
ESP_LOGI(TAG, "Turning on LCD backlight");
gpio_set_level(HW_PIN_NUM_BK_LIGHT, HW_LCD_BK_LIGHT_ON_LEVEL);
return ESP_OK;
}
#endif
@@ -0,0 +1,90 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*/
#include "esp_system.h"
#include "esp_lcd_gc9a01.h"
#include "hw_init.h"
#include "helpers/lcd_orientation_helper.h"
#if CONFIG_EXAMPLE_LCD_INTERFACE_SPI_WITHOUT_PSRAM
static const char *TAG = "hw_lcd_init";
#define HW_LCD_BASE_SWAP_XY (false)
#define HW_LCD_BASE_MIRROR_X (true)
#define HW_LCD_BASE_MIRROR_Y (false)
#define HW_LCD_DATA0 (GPIO_NUM_0)
#define HW_LCD_PCLK (GPIO_NUM_1)
#define HW_LCD_CS (GPIO_NUM_7)
#define HW_LCD_DC (GPIO_NUM_2)
#define HW_LCD_RST (GPIO_NUM_NC)
#define HW_LCD_PIXEL_CLOCK_HZ (80 * 1000 * 1000)
#define HW_LCD_COLOR_SPACE (LCD_RGB_ELEMENT_ORDER_BGR)
#define HW_LCD_BITS_PER_PIXEL (16)
#define HW_LCD_CMD_BITS (8)
#define HW_LCD_PARAM_BITS (8)
#define HW_LCD_MAX_TRANSFER_SZ (HW_LCD_H_RES * 80 * 2)
static esp_lcd_panel_io_handle_t s_panel_io_handle;
static esp_lcd_panel_handle_t s_panel_handle;
esp_err_t hw_lcd_init(esp_lcd_panel_handle_t *panel_handle, esp_lcd_panel_io_handle_t *io_handle, esp_lv_adapter_tear_avoid_mode_t tear_avoid_mode, esp_lv_adapter_rotation_t rotation)
{
ESP_LOGD(TAG, "Initialize SPI bus");
const spi_bus_config_t buscfg = {
.sclk_io_num = HW_LCD_PCLK,
.mosi_io_num = HW_LCD_DATA0,
.miso_io_num = GPIO_NUM_NC,
.quadwp_io_num = GPIO_NUM_NC,
.quadhd_io_num = GPIO_NUM_NC,
.max_transfer_sz = HW_LCD_MAX_TRANSFER_SZ,
};
ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO));
ESP_LOGD(TAG, "Install panel IO");
esp_lcd_panel_io_spi_config_t io_config = {
.dc_gpio_num = HW_LCD_DC,
.cs_gpio_num = HW_LCD_CS,
.pclk_hz = HW_LCD_PIXEL_CLOCK_HZ,
.lcd_cmd_bits = HW_LCD_CMD_BITS,
.lcd_param_bits = HW_LCD_PARAM_BITS,
.spi_mode = 0,
.trans_queue_depth = 10,
};
ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)SPI2_HOST, &io_config, &s_panel_io_handle));
ESP_LOGD(TAG, "Install LCD driver");
esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = HW_LCD_RST,
.rgb_ele_order = HW_LCD_COLOR_SPACE,
.bits_per_pixel = HW_LCD_BITS_PER_PIXEL,
};
ESP_LOGI(TAG, "Install gc9a01 panel driver");
ESP_ERROR_CHECK(esp_lcd_new_panel_gc9a01(s_panel_io_handle, &panel_config, &s_panel_handle));
esp_lcd_panel_reset(s_panel_handle);
esp_lcd_panel_init(s_panel_handle);
bool swap_xy = false;
bool mirror_x = true;
bool mirror_y = false;
lcd_get_orientation_flags(HW_LCD_BASE_SWAP_XY, HW_LCD_BASE_MIRROR_X, HW_LCD_BASE_MIRROR_Y,
rotation, &swap_xy, &mirror_x, &mirror_y);
ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(s_panel_handle, swap_xy));
ESP_ERROR_CHECK(esp_lcd_panel_mirror(s_panel_handle, mirror_x, mirror_y));
ESP_ERROR_CHECK(esp_lcd_panel_invert_color(s_panel_handle, true));
esp_lcd_panel_disp_on_off(s_panel_handle, true);
*io_handle = s_panel_io_handle;
*panel_handle = s_panel_handle;
return ESP_OK;
}
#endif