Snapshot of JC3636W518EN kit before demo folder cleanup
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
9ee85bfd86
1862 files changed
+668877
No files matched your search
@@ -0,0 +1,661 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ESP_Panel_Library.h"
|
||||
|
||||
#ifdef ESP_PANEL_USE_BOARD
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include "driver/gpio.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/**
|
||||
* Macros for adding host of bus
|
||||
*
|
||||
*/
|
||||
#define _ADD_HOST(name, host, config, id) host.addHost##name(config, id)
|
||||
#define ADD_HOST(name, host, config, id) _ADD_HOST(name, host, config, id)
|
||||
/**
|
||||
* Macros for creating panel bus
|
||||
*
|
||||
*/
|
||||
#define _CREATE_BUS_INIT_HOST(name, host_config, io_config, host_id) \
|
||||
make_shared<ESP_PanelBus_##name>(host_config, io_config, host_id)
|
||||
#define CREATE_BUS_INIT_HOST(name, host_config, io_config, host_id) \
|
||||
_CREATE_BUS_INIT_HOST(name, host_config, io_config, host_id)
|
||||
#define _CREATE_BUS_SKIP_HOST(name, io_config, host_id) make_shared<ESP_PanelBus_##name>(io_config, host_id)
|
||||
#define CREATE_BUS_SKIP_HOST(name, io_config, host_id) _CREATE_BUS_SKIP_HOST(name, io_config, host_id)
|
||||
/**
|
||||
* Macros for configuration of panel IO
|
||||
*
|
||||
*/
|
||||
#define _LCD_PANEL_IO_3WIRE_SPI_CONFIG(name, line_config, scl_active_edge) \
|
||||
name##_PANEL_IO_3WIRE_SPI_CONFIG(line_config, scl_active_edge)
|
||||
#define LCD_PANEL_IO_3WIRE_SPI_CONFIG(name, line_config, scl_active_edge) \
|
||||
_LCD_PANEL_IO_3WIRE_SPI_CONFIG(name, line_config, scl_active_edge)
|
||||
/**
|
||||
* Macros for creating device
|
||||
*
|
||||
*/
|
||||
#define _CREATE_LCD(name, bus, cfg) make_shared<ESP_PanelLcd_##name>(bus, cfg)
|
||||
#define CREATE_LCD(name, bus, cfg) _CREATE_LCD(name, bus, cfg)
|
||||
#define _CREATE_LCD_TOUCH(name, bus, cfg) make_shared<ESP_PanelTouch_##name>(bus, cfg)
|
||||
#define CREATE_LCD_TOUCH(name, bus, cfg) _CREATE_LCD_TOUCH(name, bus, cfg)
|
||||
#define _CREATE_EXPANDER(name, host_id, address) make_shared<ESP_IOExpander_##name>(host_id, address)
|
||||
#define CREATE_EXPANDER(name, host_id, address) _CREATE_EXPANDER(name, host_id, address)
|
||||
|
||||
static const char *TAG = "ESP_Panel";
|
||||
|
||||
#if ESP_PANEL_USE_LCD && defined(ESP_PANEL_LCD_VENDOR_INIT_CMD)
|
||||
static const esp_lcd_panel_vendor_init_cmd_t lcd_init_cmds[] = ESP_PANEL_LCD_VENDOR_INIT_CMD();
|
||||
#endif
|
||||
|
||||
ESP_Panel::ESP_Panel():
|
||||
_is_initialed(false),
|
||||
_use_external_expander(false),
|
||||
_lcd_bus_ptr(nullptr),
|
||||
_lcd_ptr(nullptr),
|
||||
_touch_bus_ptr(nullptr),
|
||||
_touch_ptr(nullptr),
|
||||
_backlight_ptr(nullptr),
|
||||
_expander_ptr(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_Panel::~ESP_Panel()
|
||||
{
|
||||
if (!_is_initialed) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!del()) {
|
||||
ESP_LOGE(TAG, "Delete panel failed");
|
||||
}
|
||||
|
||||
end:
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
ESP_LOGD(TAG, "Destroyed");
|
||||
}
|
||||
|
||||
void ESP_Panel::configExpander(ESP_IOExpander *expander)
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
if (expander == nullptr) {
|
||||
ESP_LOGD(TAG, "Config NULL IO expander pointer");
|
||||
} else {
|
||||
_use_external_expander = true;
|
||||
}
|
||||
|
||||
_expander_ptr.reset(expander);
|
||||
}
|
||||
|
||||
bool ESP_Panel::init(void)
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
ESP_PanelHost host;
|
||||
shared_ptr<ESP_PanelBus> lcd_bus_ptr = nullptr;
|
||||
shared_ptr<ESP_PanelLcd> lcd_ptr = nullptr;
|
||||
shared_ptr<ESP_PanelBus> touch_bus_ptr = nullptr;
|
||||
shared_ptr<ESP_PanelTouch> touch_ptr = nullptr;
|
||||
shared_ptr<ESP_IOExpander> expander_ptr = _expander_ptr;
|
||||
shared_ptr<ESP_PanelBacklight> backlight_ptr = nullptr;
|
||||
|
||||
ESP_LOGD(TAG, "Panel init start");
|
||||
|
||||
/* LCD related */
|
||||
#if ESP_PANEL_USE_LCD
|
||||
ESP_LOGD(TAG, "Use LCD");
|
||||
|
||||
#if ESP_PANEL_LCD_BUS_TYPE == ESP_PANEL_BUS_TYPE_SPI
|
||||
ESP_LOGD(TAG, "Use SPI bus");
|
||||
// SPI bus
|
||||
#if !ESP_PANEL_LCD_BUS_SKIP_INIT_HOST
|
||||
spi_bus_config_t lcd_bus_host_config = {
|
||||
.mosi_io_num = ESP_PANEL_LCD_SPI_IO_MOSI,
|
||||
.miso_io_num = ESP_PANEL_LCD_SPI_IO_MISO,
|
||||
.sclk_io_num = ESP_PANEL_LCD_SPI_IO_SCK,
|
||||
.quadwp_io_num = GPIO_NUM_NC,
|
||||
.quadhd_io_num = GPIO_NUM_NC,
|
||||
.data4_io_num = GPIO_NUM_NC,
|
||||
.data5_io_num = GPIO_NUM_NC,
|
||||
.data6_io_num = GPIO_NUM_NC,
|
||||
.data7_io_num = GPIO_NUM_NC,
|
||||
.max_transfer_sz = ESP_PANEL_HOST_SPI_MAX_TRANSFER_SIZE,
|
||||
.flags = SPICOMMON_BUSFLAG_MASTER,
|
||||
.intr_flags = 0,
|
||||
};
|
||||
#endif
|
||||
// SPI panel IO
|
||||
esp_lcd_panel_io_spi_config_t lcd_panel_io_config = {
|
||||
.cs_gpio_num = ESP_PANEL_LCD_SPI_IO_CS,
|
||||
.dc_gpio_num = ESP_PANEL_LCD_SPI_IO_DC,
|
||||
.spi_mode = ESP_PANEL_LCD_SPI_MODE,
|
||||
.pclk_hz = ESP_PANEL_LCD_SPI_CLK_HZ,
|
||||
.trans_queue_depth = ESP_PANEL_LCD_SPI_TRANS_QUEUE_SZ,
|
||||
.on_color_trans_done = NULL,
|
||||
.user_ctx = NULL,
|
||||
.lcd_cmd_bits = ESP_PANEL_LCD_SPI_CMD_BITS,
|
||||
.lcd_param_bits = ESP_PANEL_LCD_SPI_PARAM_BITS,
|
||||
.flags = {
|
||||
.dc_low_on_data = 0,
|
||||
.octal_mode = 0,
|
||||
.quad_mode = 0,
|
||||
.sio_mode = 0,
|
||||
.lsb_first = 0,
|
||||
.cs_high_active = 0,
|
||||
},
|
||||
};
|
||||
|
||||
#elif ESP_PANEL_LCD_BUS_TYPE == ESP_PANEL_BUS_TYPE_QSPI
|
||||
ESP_LOGD(TAG, "Use QSPI bus");
|
||||
// QSPI bus
|
||||
#if !ESP_PANEL_LCD_BUS_SKIP_INIT_HOST
|
||||
spi_bus_config_t lcd_bus_host_config = {
|
||||
.data0_io_num = ESP_PANEL_LCD_SPI_IO_DATA0,
|
||||
.data1_io_num = ESP_PANEL_LCD_SPI_IO_DATA1,
|
||||
.sclk_io_num = ESP_PANEL_LCD_SPI_IO_SCK,
|
||||
.data2_io_num = ESP_PANEL_LCD_SPI_IO_DATA2,
|
||||
.data3_io_num = ESP_PANEL_LCD_SPI_IO_DATA3,
|
||||
.data4_io_num = -1,
|
||||
.data5_io_num = -1,
|
||||
.data6_io_num = -1,
|
||||
.data7_io_num = -1,
|
||||
.max_transfer_sz = ESP_PANEL_HOST_SPI_MAX_TRANSFER_SIZE,
|
||||
.flags = SPICOMMON_BUSFLAG_MASTER,
|
||||
.intr_flags = 0,
|
||||
};
|
||||
#endif
|
||||
// QSPI panel IO
|
||||
esp_lcd_panel_io_spi_config_t lcd_panel_io_config = {
|
||||
.cs_gpio_num = ESP_PANEL_LCD_SPI_IO_CS,
|
||||
.dc_gpio_num = -1,
|
||||
.spi_mode = ESP_PANEL_LCD_SPI_MODE,
|
||||
.pclk_hz = ESP_PANEL_LCD_SPI_CLK_HZ,
|
||||
.trans_queue_depth = ESP_PANEL_LCD_SPI_TRANS_QUEUE_SZ,
|
||||
.on_color_trans_done = NULL,
|
||||
.user_ctx = NULL,
|
||||
.lcd_cmd_bits = ESP_PANEL_LCD_SPI_CMD_BITS,
|
||||
.lcd_param_bits = ESP_PANEL_LCD_SPI_PARAM_BITS,
|
||||
.flags = {
|
||||
.dc_low_on_data = 0,
|
||||
.octal_mode = 0,
|
||||
.quad_mode = 1,
|
||||
.sio_mode = 0,
|
||||
.lsb_first = 0,
|
||||
.cs_high_active = 0,
|
||||
},
|
||||
};
|
||||
|
||||
#elif ESP_PANEL_LCD_BUS_TYPE == ESP_PANEL_BUS_TYPE_RGB
|
||||
|
||||
ESP_LOGD(TAG, "Use RGB bus");
|
||||
// 3-wire SPI panel IO
|
||||
#if !ESP_PANEL_LCD_BUS_SKIP_INIT_HOST
|
||||
spi_line_config_t line_config = {
|
||||
.cs_io_type = (panel_io_type_t)ESP_PANEL_LCD_3WIRE_SPI_CS_USE_EXPNADER,
|
||||
.cs_gpio_num = ESP_PANEL_LCD_3WIRE_SPI_IO_CS,
|
||||
.scl_io_type = (panel_io_type_t)ESP_PANEL_LCD_3WIRE_SPI_SCL_USE_EXPNADER,
|
||||
.scl_gpio_num = ESP_PANEL_LCD_3WIRE_SPI_IO_SCK,
|
||||
.sda_io_type = (panel_io_type_t)ESP_PANEL_LCD_3WIRE_SPI_SDA_USE_EXPNADER,
|
||||
.sda_gpio_num = ESP_PANEL_LCD_3WIRE_SPI_IO_SDA,
|
||||
.io_expander = NULL,
|
||||
};
|
||||
esp_lcd_panel_io_3wire_spi_config_t lcd_panel_io_config =
|
||||
LCD_PANEL_IO_3WIRE_SPI_CONFIG(ESP_PANEL_LCD_NAME, line_config, ESP_PANEL_LCD_3WIRE_SPI_SCL_ACTIVE_EDGE);
|
||||
#endif
|
||||
// RGB panel
|
||||
esp_lcd_rgb_panel_config_t rgb_panel_config = {
|
||||
.clk_src = LCD_CLK_SRC_DEFAULT,
|
||||
.timings = {
|
||||
.pclk_hz = ESP_PANEL_LCD_RGB_CLK_HZ,
|
||||
.h_res = ESP_PANEL_LCD_WIDTH,
|
||||
.v_res = ESP_PANEL_LCD_HEIGHT,
|
||||
.hsync_pulse_width = ESP_PANEL_LCD_RGB_HPW,
|
||||
.hsync_back_porch = ESP_PANEL_LCD_RGB_HBP,
|
||||
.hsync_front_porch = ESP_PANEL_LCD_RGB_HFP,
|
||||
.vsync_pulse_width = ESP_PANEL_LCD_RGB_VPW,
|
||||
.vsync_back_porch = ESP_PANEL_LCD_RGB_VBP,
|
||||
.vsync_front_porch = ESP_PANEL_LCD_RGB_VFP,
|
||||
.flags = {
|
||||
.pclk_active_neg = ESP_PANEL_LCD_RGB_PCLK_ACTIVE_NEG,
|
||||
},
|
||||
},
|
||||
.data_width = ESP_PANEL_LCD_RGB_DATA_WIDTH,
|
||||
.bits_per_pixel = ESP_PANEL_LCD_RGB_PIXEL_BITS,
|
||||
.num_fbs = ESP_PANEL_LCD_RGB_FRAME_BUF_NUM,
|
||||
.bounce_buffer_size_px = ESP_PANEL_LCD_RGB_BOUNCE_BUF_SIZE,
|
||||
.sram_trans_align = 4,
|
||||
.psram_trans_align = 64,
|
||||
.hsync_gpio_num = ESP_PANEL_LCD_RGB_IO_HSYNC,
|
||||
.vsync_gpio_num = ESP_PANEL_LCD_RGB_IO_VSYNC,
|
||||
.de_gpio_num = ESP_PANEL_LCD_RGB_IO_DE,
|
||||
.pclk_gpio_num = ESP_PANEL_LCD_RGB_IO_PCLK,
|
||||
.disp_gpio_num = ESP_PANEL_LCD_RGB_IO_DISP,
|
||||
.data_gpio_nums = {
|
||||
ESP_PANEL_LCD_RGB_IO_DATA0,
|
||||
ESP_PANEL_LCD_RGB_IO_DATA1,
|
||||
ESP_PANEL_LCD_RGB_IO_DATA2,
|
||||
ESP_PANEL_LCD_RGB_IO_DATA3,
|
||||
ESP_PANEL_LCD_RGB_IO_DATA4,
|
||||
ESP_PANEL_LCD_RGB_IO_DATA5,
|
||||
ESP_PANEL_LCD_RGB_IO_DATA6,
|
||||
ESP_PANEL_LCD_RGB_IO_DATA7,
|
||||
ESP_PANEL_LCD_RGB_IO_DATA8,
|
||||
ESP_PANEL_LCD_RGB_IO_DATA9,
|
||||
ESP_PANEL_LCD_RGB_IO_DATA10,
|
||||
ESP_PANEL_LCD_RGB_IO_DATA11,
|
||||
ESP_PANEL_LCD_RGB_IO_DATA12,
|
||||
ESP_PANEL_LCD_RGB_IO_DATA13,
|
||||
ESP_PANEL_LCD_RGB_IO_DATA14,
|
||||
ESP_PANEL_LCD_RGB_IO_DATA15,
|
||||
},
|
||||
.flags = {
|
||||
.fb_in_psram = 1,
|
||||
},
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#error "This function is not ready and will be implemented in the future."
|
||||
|
||||
#endif /* ESP_PANEL_LCD_BUS_TYPE */
|
||||
|
||||
// LCD vendor configuration
|
||||
esp_lcd_panel_vendor_config_t lcd_vendor_config = {
|
||||
#ifdef ESP_PANEL_LCD_VENDOR_INIT_CMD
|
||||
.init_cmds = lcd_init_cmds,
|
||||
.init_cmds_size = sizeof(lcd_init_cmds) / sizeof(lcd_init_cmds[0]),
|
||||
#endif
|
||||
#if ESP_PANEL_LCD_BUS_TYPE == ESP_PANEL_BUS_TYPE_RGB
|
||||
.rgb_config = &rgb_panel_config,
|
||||
.flags = {
|
||||
#if !ESP_PANEL_LCD_BUS_SKIP_INIT_HOST
|
||||
.mirror_by_cmd = ESP_PANEL_LCD_FLAGS_MIRROR_BY_CMD,
|
||||
.auto_del_panel_io = ESP_PANEL_LCD_FLAGS_AUTO_DEL_PANEL_IO,
|
||||
#endif
|
||||
},
|
||||
#elif ESP_PANEL_LCD_BUS_TYPE == ESP_PANEL_BUS_TYPE_QSPI
|
||||
.flags = {
|
||||
.use_qspi_interface = true,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
// LCD device configuration
|
||||
esp_lcd_panel_dev_config_t lcd_config = {
|
||||
.reset_gpio_num = ESP_PANEL_LCD_IO_RST,
|
||||
.rgb_ele_order = (lcd_rgb_element_order_t)ESP_PANEL_LCD_BGR_ORDER,
|
||||
.data_endian = LCD_RGB_DATA_ENDIAN_BIG,
|
||||
.bits_per_pixel = ESP_PANEL_LCD_COLOR_BITS,
|
||||
.flags = {
|
||||
.reset_active_high = ESP_PANEL_LCD_RST_LEVEL,
|
||||
},
|
||||
.vendor_config = &lcd_vendor_config,
|
||||
};
|
||||
|
||||
ESP_LOGD(TAG, "Create LCD bus");
|
||||
#if ESP_PANEL_LCD_BUS_TYPE == ESP_PANEL_BUS_TYPE_RGB
|
||||
/* For non-RGB LCD, should use `CREATE_BUS_INIT_HOST()` to init host instead of `ADD_HOST()` */
|
||||
#if !ESP_PANEL_LCD_BUS_SKIP_INIT_HOST
|
||||
lcd_bus_ptr = CREATE_BUS_INIT_HOST(ESP_PANEL_LCD_BUS_NAME, lcd_panel_io_config, rgb_panel_config, ESP_PANEL_LCD_BUS_HOST);
|
||||
#else
|
||||
lcd_bus_ptr = CREATE_BUS_SKIP_HOST(ESP_PANEL_LCD_BUS_NAME, rgb_panel_config, ESP_PANEL_LCD_BUS_HOST);
|
||||
#endif
|
||||
#else
|
||||
/* For non-RGB LCD, should use `ADD_HOST()` to init host when `ESP_PANEL_LCD_BUS_SKIP_INIT_HOST` enabled */
|
||||
#if !ESP_PANEL_LCD_BUS_SKIP_INIT_HOST
|
||||
ESP_PANEL_CHECK_FALSE_RET(ADD_HOST(ESP_PANEL_LCD_BUS_NAME, host, lcd_bus_host_config, ESP_PANEL_LCD_BUS_HOST),
|
||||
false, "Add host failed");
|
||||
#endif
|
||||
lcd_bus_ptr = CREATE_BUS_SKIP_HOST(ESP_PANEL_LCD_BUS_NAME, lcd_panel_io_config, ESP_PANEL_LCD_BUS_HOST);
|
||||
#endif
|
||||
|
||||
ESP_PANEL_CHECK_NULL_RET(lcd_bus_ptr, false, "Create LCD bus failed");
|
||||
|
||||
ESP_LOGD(TAG, "Create LCD device");
|
||||
lcd_ptr = CREATE_LCD(ESP_PANEL_LCD_NAME, lcd_bus_ptr.get(), lcd_config);
|
||||
ESP_PANEL_CHECK_NULL_RET(lcd_ptr, false, "Create LCD device failed");
|
||||
#endif /* ESP_PANEL_USE_LCD */
|
||||
|
||||
/* Touch related configuration */
|
||||
#if ESP_PANEL_USE_TOUCH
|
||||
ESP_LOGD(TAG, "Use touch");
|
||||
#if ESP_PANEL_TOUCH_BUS_TYPE == ESP_PANEL_BUS_TYPE_I2C
|
||||
|
||||
ESP_LOGD(TAG, "Use I2C bus");
|
||||
// I2C bus
|
||||
#if !ESP_PANEL_TOUCH_BUS_SKIP_INIT_HOST
|
||||
i2c_config_t touch_host_config = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_io_num = ESP_PANEL_TOUCH_I2C_IO_SDA,
|
||||
.scl_io_num = ESP_PANEL_TOUCH_I2C_IO_SCL,
|
||||
.sda_pullup_en = ESP_PANEL_TOUCH_I2C_SDA_PULLUP,
|
||||
.scl_pullup_en = ESP_PANEL_TOUCH_I2C_SCL_PULLUP,
|
||||
.master = {
|
||||
.clk_speed = ESP_PANEL_TOUCH_I2C_CLK_HZ,
|
||||
},
|
||||
.clk_flags = I2C_SCLK_SRC_FLAG_FOR_NOMAL,
|
||||
};
|
||||
#endif
|
||||
// I2C touch panel IO
|
||||
esp_lcd_panel_io_i2c_config_t touch_panel_io_config = ESP_PANEL_TOUCH_I2C_PANEL_IO_CONFIG(ESP_PANEL_TOUCH_NAME);
|
||||
|
||||
#elif ESP_PANEL_TOUCH_BUS_TYPE == ESP_PANEL_BUS_TYPE_SPI
|
||||
|
||||
ESP_LOGD(TAG, "Use SPI bus");
|
||||
// SPI bus
|
||||
#if !ESP_PANEL_TOUCH_BUS_SKIP_INIT_HOST
|
||||
spi_bus_config_t touch_host_config = {
|
||||
.mosi_io_num = ESP_PANEL_TOUCH_SPI_IO_MOSI,
|
||||
.miso_io_num = ESP_PANEL_TOUCH_SPI_IO_MISO,
|
||||
.sclk_io_num = ESP_PANEL_TOUCH_SPI_IO_SCK,
|
||||
.quadwp_io_num = GPIO_NUM_NC,
|
||||
.quadhd_io_num = GPIO_NUM_NC,
|
||||
.data4_io_num = GPIO_NUM_NC,
|
||||
.data5_io_num = GPIO_NUM_NC,
|
||||
.data6_io_num = GPIO_NUM_NC,
|
||||
.data7_io_num = GPIO_NUM_NC,
|
||||
.max_transfer_sz = ESP_PANEL_HOST_SPI_MAX_TRANSFER_SIZE,
|
||||
.flags = SPICOMMON_BUSFLAG_MASTER,
|
||||
.intr_flags = 0,
|
||||
};
|
||||
#endif
|
||||
// SPI panel IO
|
||||
esp_lcd_panel_io_spi_config_t touch_panel_io_config = ESP_PANEL_TOUCH_SPI_PANEL_IO_CONFIG(ESP_PANEL_TOUCH_NAME,
|
||||
ESP_PANEL_TOUCH_SPI_IO_CS);
|
||||
|
||||
#else
|
||||
|
||||
#error "This function is not ready and will be implemented in the future."
|
||||
|
||||
#endif /* ESP_PANEL_TOUCH_BUS_TYPE */
|
||||
|
||||
// Touch device configuration
|
||||
esp_lcd_touch_config_t lcd_touch_config = {
|
||||
.x_max = ESP_PANEL_TOUCH_H_RES,
|
||||
.y_max = ESP_PANEL_TOUCH_V_RES,
|
||||
.rst_gpio_num = (gpio_num_t)ESP_PANEL_TOUCH_IO_RST,
|
||||
.int_gpio_num = (gpio_num_t)ESP_PANEL_TOUCH_IO_INT,
|
||||
.levels = {
|
||||
.reset = ESP_PANEL_TOUCH_RST_LEVEL,
|
||||
.interrupt = ESP_PANEL_TOUCH_INT_LEVEL,
|
||||
},
|
||||
.flags = {
|
||||
.swap_xy = false,
|
||||
.mirror_x = false,
|
||||
.mirror_y = false,
|
||||
},
|
||||
.process_coordinates = NULL,
|
||||
.interrupt_callback = NULL,
|
||||
.user_data = NULL,
|
||||
};
|
||||
|
||||
#if !ESP_PANEL_TOUCH_BUS_SKIP_INIT_HOST
|
||||
ESP_PANEL_CHECK_FALSE_RET(ADD_HOST(ESP_PANEL_TOUCH_BUS_NAME, host, touch_host_config, ESP_PANEL_TOUCH_BUS_HOST),
|
||||
false, "Add host failed");
|
||||
#endif
|
||||
|
||||
ESP_LOGD(TAG, "Create touch bus");
|
||||
touch_bus_ptr = CREATE_BUS_SKIP_HOST(ESP_PANEL_TOUCH_BUS_NAME, touch_panel_io_config, ESP_PANEL_TOUCH_BUS_HOST);
|
||||
ESP_PANEL_CHECK_NULL_RET(touch_bus_ptr, false, "Create touch bus failed");
|
||||
|
||||
ESP_LOGD(TAG, "Create touch device");
|
||||
touch_ptr = CREATE_LCD_TOUCH(ESP_PANEL_TOUCH_NAME, touch_bus_ptr.get(), lcd_touch_config);
|
||||
ESP_PANEL_CHECK_NULL_RET(touch_ptr, false, "Create touch device failed");
|
||||
#endif /* ESP_PANEL_USE_TOUCH */
|
||||
|
||||
// Create backlight device
|
||||
#if ESP_PANEL_USE_BACKLIGHT
|
||||
ESP_LOGD(TAG, "Use backlight");
|
||||
ESP_LOGD(TAG, "Create backlight device");
|
||||
backlight_ptr = make_shared<ESP_PanelBacklight>(ESP_PANEL_BACKLIGHT_IO, ESP_PANEL_BACKLIGHT_ON_LEVEL, ESP_PANEL_LCD_BL_USE_PWM);
|
||||
ESP_PANEL_CHECK_NULL_RET(backlight_ptr, false, "Create backlight failed");
|
||||
#endif /* ESP_PANEL_USE_BACKLIGHT */
|
||||
|
||||
// Create IO expander device
|
||||
#if ESP_PANEL_USE_EXPANDER
|
||||
ESP_LOGD(TAG, "Use IO expander");
|
||||
if (expander_ptr == nullptr) {
|
||||
#if !ESP_PANEL_EXPANDER_SKIP_INIT_HOST
|
||||
i2c_config_t expander_host_config = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_io_num = ESP_PANEL_EXPANDER_I2C_IO_SDA,
|
||||
.scl_io_num = ESP_PANEL_EXPANDER_I2C_IO_SCL,
|
||||
.sda_pullup_en = ESP_PANEL_EXPANDER_I2C_SDA_PULLUP,
|
||||
.scl_pullup_en = ESP_PANEL_EXPANDER_I2C_SCL_PULLUP,
|
||||
.master = {
|
||||
.clk_speed = ESP_PANEL_EXPANDER_I2C_CLK_HZ,
|
||||
},
|
||||
.clk_flags = I2C_SCLK_SRC_FLAG_FOR_NOMAL,
|
||||
};
|
||||
ESP_PANEL_CHECK_FALSE_RET(ADD_HOST(I2C, host, expander_host_config, ESP_PANEL_TOUCH_BUS_HOST), false,
|
||||
"Add host failed");
|
||||
#endif
|
||||
expander_ptr = CREATE_EXPANDER(ESP_PANEL_EXPANDER_NAME, ESP_PANEL_EXPANDER_HOST, ESP_PANEL_EXPANDER_I2C_ADDRESS);
|
||||
}
|
||||
#endif /* ESP_PANEL_USE_EXPANDER */
|
||||
|
||||
ESP_LOGD(TAG, "Initialize host");
|
||||
ESP_PANEL_CHECK_FALSE_RET(host.begin(), false, "Initialize host failed");
|
||||
|
||||
// Save the created devices
|
||||
_lcd_bus_ptr = lcd_bus_ptr;
|
||||
_lcd_ptr = lcd_ptr;
|
||||
_touch_bus_ptr = touch_bus_ptr;
|
||||
_touch_ptr = touch_ptr;
|
||||
_backlight_ptr = backlight_ptr;
|
||||
_expander_ptr = expander_ptr;
|
||||
_is_initialed = true;
|
||||
|
||||
ESP_LOGD(TAG, "Panel init end");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_Panel::begin(void)
|
||||
{
|
||||
ESP_PANEL_CHECK_FALSE_RET(_is_initialed, false, "Panel is not initialized");
|
||||
|
||||
ESP_LOGD(TAG, "Panel begin start");
|
||||
// Run additional code before starting the panel if needed
|
||||
#ifdef ESP_PANEL_BEGIN_START_FUNCTION
|
||||
ESP_PANEL_BEGIN_START_FUNCTION(this);
|
||||
#endif
|
||||
|
||||
#if ESP_PANEL_USE_EXPANDER
|
||||
// Run additional code before starting the IO expander if needed
|
||||
#ifdef ESP_PANEL_BEGIN_EXPANDER_START_FUNCTION
|
||||
ESP_PANEL_BEGIN_EXPANDER_START_FUNCTION(this);
|
||||
#endif
|
||||
ESP_LOGD(TAG, "Begin IO expander");
|
||||
_expander_ptr->init();
|
||||
_expander_ptr->begin();
|
||||
// Run additional code after the IO expander is started if needed
|
||||
#ifdef ESP_PANEL_BEGIN_EXPANDER_END_FUNCTION
|
||||
ESP_PANEL_BEGIN_EXPANDER_END_FUNCTION(this);
|
||||
#endif
|
||||
#endif /* ESP_PANEL_USE_EXPANDER */
|
||||
|
||||
#if ESP_PANEL_USE_LCD
|
||||
// Run additional code before starting the bus and LCD if needed
|
||||
#ifdef ESP_PANEL_BEGIN_LCD_START_FUNCTION
|
||||
ESP_PANEL_BEGIN_LCD_START_FUNCTION(this);
|
||||
#endif
|
||||
ESP_LOGD(TAG, "Begin LCD");
|
||||
#if ESP_PANEL_USE_EXPANDER && ((ESP_PANEL_LCD_3WIRE_SPI_CS_USE_EXPNADER) || (ESP_PANEL_LCD_3WIRE_SPI_SCL_USE_EXPNADER) || \
|
||||
(ESP_PANEL_LCD_3WIRE_SPI_SDA_USE_EXPNADER))
|
||||
shared_ptr<ESP_PanelBus_RGB> lcd_bus_ptr = static_pointer_cast<ESP_PanelBus_RGB>(_lcd_bus_ptr);
|
||||
lcd_bus_ptr->configSpiLine(ESP_PANEL_LCD_3WIRE_SPI_CS_USE_EXPNADER, ESP_PANEL_LCD_3WIRE_SPI_SCL_USE_EXPNADER,
|
||||
ESP_PANEL_LCD_3WIRE_SPI_SDA_USE_EXPNADER, _expander_ptr.get());
|
||||
#endif
|
||||
ESP_PANEL_CHECK_FALSE_RET(_lcd_bus_ptr->begin(), false, "Begin LCD bus failed");
|
||||
ESP_PANEL_CHECK_FALSE_RET(_lcd_ptr->init(), false, "Initialize LCD failed");
|
||||
ESP_PANEL_CHECK_FALSE_RET(_lcd_ptr->reset(), false, "Reset LCD failed");
|
||||
// Operate LCD device according to the optional configurations
|
||||
#ifdef ESP_PANEL_LCD_SWAP_XY
|
||||
ESP_PANEL_CHECK_FALSE_RET(_lcd_ptr->swapXY(ESP_PANEL_LCD_SWAP_XY), false, "Swap XY failed");
|
||||
#endif
|
||||
#ifdef ESP_PANEL_LCD_MIRROR_X
|
||||
ESP_PANEL_CHECK_FALSE_RET(_lcd_ptr->mirrorX(ESP_PANEL_LCD_MIRROR_X), false, "Mirror X failed");
|
||||
#endif
|
||||
#ifdef ESP_PANEL_LCD_MIRROR_Y
|
||||
ESP_PANEL_CHECK_FALSE_RET(_lcd_ptr->mirrorY(ESP_PANEL_LCD_MIRROR_Y), false, "Mirror Y failed");
|
||||
#endif
|
||||
#ifdef ESP_PANEL_LCD_INEVRT_COLOR
|
||||
ESP_PANEL_CHECK_FALSE_RET(_lcd_ptr->invertColor(ESP_PANEL_LCD_INEVRT_COLOR), false, "Invert color failed");
|
||||
#endif
|
||||
ESP_PANEL_CHECK_FALSE_RET(_lcd_ptr->begin(), false, "Begin LCD failed");
|
||||
/**
|
||||
* Turn on display only when meets one of the following conditions:
|
||||
* - The LCD bus is not RGB bus
|
||||
* - The LCD bus is "3wire-SPI + RGB" bus and the `ESP_PANEL_LCD_FLAGS_AUTO_DEL_PANEL_IO` is disabled
|
||||
* - The LCD bus is RGB (with or without 3-wire SPI) bus and the `ESP_PANEL_LCD_RGB_IO_DISP` pin is used
|
||||
*
|
||||
*/
|
||||
#if (ESP_PANEL_LCD_BUS_TYPE != ESP_PANEL_BUS_TYPE_RGB) || \
|
||||
(defined(ESP_PANEL_LCD_RGB_IO_DISP) && (ESP_PANEL_LCD_RGB_IO_DISP != -1)) || \
|
||||
(defined(ESP_PANEL_LCD_FLAGS_AUTO_DEL_PANEL_IO) && !ESP_PANEL_LCD_FLAGS_AUTO_DEL_PANEL_IO)
|
||||
ESP_PANEL_CHECK_FALSE_RET(_lcd_ptr->displayOn(), false, "Display on failed");
|
||||
#endif
|
||||
// Run additional code after the LCD is started if needed
|
||||
#ifdef ESP_PANEL_BEGIN_LCD_END_FUNCTION
|
||||
ESP_PANEL_BEGIN_LCD_END_FUNCTION(this);
|
||||
#endif
|
||||
#endif /* ESP_PANEL_USE_LCD */
|
||||
|
||||
#if ESP_PANEL_USE_TOUCH
|
||||
// Run additional code before starting the bus and touch if needed
|
||||
#ifdef ESP_PANEL_BEGIN_TOUCH_START_FUNCTION
|
||||
ESP_PANEL_BEGIN_TOUCH_START_FUNCTION(this);
|
||||
#endif
|
||||
ESP_LOGD(TAG, "Begin touch");
|
||||
ESP_PANEL_CHECK_FALSE_RET(_touch_bus_ptr->begin(), false, "Begin touch bus failed");
|
||||
ESP_PANEL_CHECK_FALSE_RET(_touch_ptr->init(), false, "Initialize touch failed");
|
||||
ESP_PANEL_CHECK_FALSE_RET(_touch_ptr->begin(), false, "Begin touch failed");
|
||||
#ifdef ESP_PANEL_TOUCH_SWAP_XY
|
||||
ESP_PANEL_CHECK_FALSE_RET(_touch_ptr->swapXY(ESP_PANEL_TOUCH_SWAP_XY), false, "Swap XY failed");
|
||||
#endif
|
||||
#ifdef ESP_PANEL_TOUCH_MIRROR_X
|
||||
ESP_PANEL_CHECK_FALSE_RET(_touch_ptr->mirrorX(ESP_PANEL_TOUCH_MIRROR_X), false, "Mirror X failed");
|
||||
#endif
|
||||
#ifdef ESP_PANEL_TOUCH_MIRROR_Y
|
||||
ESP_PANEL_CHECK_FALSE_RET(_touch_ptr->mirrorY(ESP_PANEL_TOUCH_MIRROR_Y), false, "Mirror Y failed");
|
||||
#endif
|
||||
// Run additional code after the touch is started if needed
|
||||
#ifdef ESP_PANEL_BEGIN_TOUCH_END_FUNCTION
|
||||
ESP_PANEL_BEGIN_TOUCH_END_FUNCTION(this);
|
||||
#endif
|
||||
#endif /* ESP_PANEL_USE_TOUCH */
|
||||
|
||||
#if ESP_PANEL_USE_BACKLIGHT
|
||||
// Run additional code before starting the backlight if needed
|
||||
#ifdef ESP_PANEL_BEGIN_BACKLIGHT_START_FUNCTION
|
||||
ESP_PANEL_BEGIN_BACKLIGHT_START_FUNCTION(this);
|
||||
#endif
|
||||
ESP_LOGD(TAG, "Begin backlight");
|
||||
ESP_PANEL_CHECK_FALSE_RET(_backlight_ptr->begin(), false, "Initialize backlight failed");
|
||||
#if ESP_PANEL_BACKLIGHT_IDLE_OFF
|
||||
ESP_PANEL_CHECK_FALSE_RET(_backlight_ptr->off(), false, "Turn off backlight failed");
|
||||
#else
|
||||
ESP_PANEL_CHECK_FALSE_RET(_backlight_ptr->on(), false, "Turn on backlight failed");
|
||||
#endif
|
||||
// Run additional code after the backlight is started if needed
|
||||
#ifdef ESP_PANEL_BEGIN_BACKLIGHT_END_FUNCTION
|
||||
ESP_PANEL_BEGIN_BACKLIGHT_END_FUNCTION(this);
|
||||
#endif
|
||||
#endif /* ESP_PANEL_USE_BACKLIGHT */
|
||||
|
||||
ESP_LOGD(TAG, "Panel begin end");
|
||||
// Run additional code after the panel is started if needed
|
||||
#ifdef ESP_PANEL_BEGIN_END_FUNCTION
|
||||
ESP_PANEL_BEGIN_END_FUNCTION(this);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_Panel::del(void)
|
||||
{
|
||||
ESP_PANEL_CHECK_FALSE_RET(_is_initialed, false, "Panel is not initialized");
|
||||
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
if (_lcd_bus_ptr != nullptr) {
|
||||
ESP_LOGD(TAG, "Delete LCD bus");
|
||||
_lcd_bus_ptr = nullptr;
|
||||
}
|
||||
|
||||
if (_lcd_ptr != nullptr) {
|
||||
ESP_LOGD(TAG, "Delete LCD device");
|
||||
_lcd_ptr = nullptr;
|
||||
}
|
||||
|
||||
if (_touch_bus_ptr != nullptr) {
|
||||
ESP_LOGD(TAG, "Delete touch bus");
|
||||
_touch_bus_ptr = nullptr;
|
||||
}
|
||||
|
||||
if (_touch_ptr != nullptr) {
|
||||
ESP_LOGD(TAG, "Delete touch device");
|
||||
_touch_ptr = nullptr;
|
||||
}
|
||||
|
||||
if (_backlight_ptr != nullptr) {
|
||||
ESP_LOGD(TAG, "Delete backlight bus");
|
||||
_backlight_ptr = nullptr;
|
||||
}
|
||||
|
||||
if (!_use_external_expander && (_expander_ptr != nullptr)) {
|
||||
ESP_LOGD(TAG, "Delete IO expander");
|
||||
_expander_ptr = nullptr;
|
||||
}
|
||||
|
||||
_is_initialed = false;
|
||||
ESP_LOGD(TAG, "Delete panel");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ESP_PanelLcd *ESP_Panel::getLcd(void)
|
||||
{
|
||||
if (_lcd_ptr == nullptr) {
|
||||
ESP_LOGD(TAG, "Get invalid LCD pointer");
|
||||
}
|
||||
|
||||
return _lcd_ptr.get();
|
||||
}
|
||||
|
||||
ESP_PanelTouch *ESP_Panel::getTouch(void)
|
||||
{
|
||||
if (_touch_ptr == nullptr) {
|
||||
ESP_LOGD(TAG, "Get invalid touch pointer");
|
||||
}
|
||||
|
||||
return _touch_ptr.get();
|
||||
}
|
||||
|
||||
ESP_PanelBacklight *ESP_Panel::getBacklight(void)
|
||||
{
|
||||
if (_backlight_ptr == nullptr) {
|
||||
ESP_LOGD(TAG, "Get invalid backlight pointer");
|
||||
}
|
||||
|
||||
return _backlight_ptr.get();
|
||||
}
|
||||
|
||||
ESP_IOExpander *ESP_Panel::getExpander(void)
|
||||
{
|
||||
if (_expander_ptr == nullptr) {
|
||||
ESP_LOGD(TAG, "Get invalid expander pointer");
|
||||
}
|
||||
|
||||
return _expander_ptr.get();
|
||||
}
|
||||
|
||||
#endif /* ESP_PANEL_USE_BOARD */
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "ESP_Panel_Library.h"
|
||||
|
||||
#ifdef ESP_PANEL_USE_BOARD
|
||||
#include <memory>
|
||||
|
||||
/**
|
||||
* @brief Panel device class
|
||||
*
|
||||
* @note This class is mainly aimed at development boards, which integrates other independent drivers such as LCD, Touch, and Backlight.
|
||||
* @note For supported development boards, the drivers internally automatically use preset parameters to configure each independent driver.
|
||||
* @note For custom development boards, users need to adjust the parameters according to the actual hardware through the `ESP_Panel_Board_Custom.h` file.
|
||||
*/
|
||||
class ESP_Panel {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new panel device
|
||||
*
|
||||
*/
|
||||
ESP_Panel();
|
||||
|
||||
/**
|
||||
* @brief Destroy the panel device
|
||||
*
|
||||
*/
|
||||
~ESP_Panel();
|
||||
|
||||
/**
|
||||
* @brief Configure the IO expander from the outside. This function should be called before `init()`
|
||||
*
|
||||
* @param expander Pointer of IO expander
|
||||
*
|
||||
*/
|
||||
void configExpander(ESP_IOExpander *expander);
|
||||
|
||||
/**
|
||||
* @brief Initialize the panel device, the `begin()` function should be called after this function
|
||||
*
|
||||
* @note This function typically creates objects for the LCD, Touch, Backlight, and other devices based on the configuration. It then initializes the bus host used by each device.
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool init(void);
|
||||
|
||||
/**
|
||||
* @brief Startup the panel device. This function should be called after `init()`
|
||||
*
|
||||
* @note This function typically initializes the LCD, Touch, Backlight, and other devices based on the configuration.
|
||||
*
|
||||
* @return true
|
||||
*/
|
||||
bool begin(void);
|
||||
|
||||
/**
|
||||
* @brief Delete the panel device, release the resources. This function should be called after `init()`
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool del(void);
|
||||
|
||||
/**
|
||||
* @brief Here are the functions to get the pointer of each device
|
||||
*
|
||||
*/
|
||||
ESP_PanelLcd *getLcd(void);
|
||||
ESP_PanelTouch *getTouch(void);
|
||||
ESP_PanelBacklight *getBacklight(void);
|
||||
ESP_IOExpander *getExpander(void);
|
||||
|
||||
/**
|
||||
* @brief Here are the functions to get the some parameters of the devices
|
||||
*
|
||||
*/
|
||||
uint16_t getLcdWidth(void);
|
||||
uint16_t getLcdHeight(void);
|
||||
|
||||
private:
|
||||
bool _is_initialed;
|
||||
bool _use_external_expander;
|
||||
std::shared_ptr<ESP_PanelBus> _lcd_bus_ptr;
|
||||
std::shared_ptr<ESP_PanelBus> _touch_bus_ptr;
|
||||
std::shared_ptr<ESP_PanelLcd> _lcd_ptr;
|
||||
std::shared_ptr<ESP_PanelTouch> _touch_ptr;
|
||||
std::shared_ptr<ESP_PanelBacklight> _backlight_ptr;
|
||||
std::shared_ptr<ESP_IOExpander> _expander_ptr;
|
||||
};
|
||||
|
||||
inline uint16_t ESP_Panel::getLcdWidth(void)
|
||||
{
|
||||
#ifdef ESP_PANEL_LCD_WIDTH
|
||||
return ESP_PANEL_LCD_WIDTH;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint16_t ESP_Panel::getLcdHeight(void)
|
||||
{
|
||||
#ifdef ESP_PANEL_LCD_HEIGHT
|
||||
return ESP_PANEL_LCD_HEIGHT;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* ESP_PANEL_USE_BOARD */
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include "ESP_Panel_Conf_Internal.h"
|
||||
#if ESP_PANEL_ENABLE_LOG
|
||||
#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
|
||||
#endif
|
||||
#include "esp_log.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_check.h"
|
||||
|
||||
#if ESP_PANEL_ENABLE_LOG
|
||||
#define ESP_PANEL_ENABLE_TAG_DEBUG_LOG() do { \
|
||||
esp_log_level_set(TAG, ESP_LOG_DEBUG); \
|
||||
} while(0)
|
||||
#else
|
||||
#define ESP_PANEL_ENABLE_TAG_DEBUG_LOG() do {} while(0)
|
||||
#endif
|
||||
|
||||
#if ESP_PANEL_CHECK_RESULT_ASSERT
|
||||
#define ESP_PANEL_CHECK_ERR_RET(x, ...) assert((x) == ESP_OK)
|
||||
#define ESP_PANEL_CHECK_NULL_RET(x, ...) assert((x) != NULL)
|
||||
#define ESP_PANEL_CHECK_FALSE_RET(x, ...) assert((x) != false)
|
||||
#else
|
||||
#if ESP_PANEL_ENABLE_LOG
|
||||
#define ESP_PANEL_ERROR_CHECK_LOG_FORMAT(err, format) "[%s] %s(%u): " format, esp_err_to_name(err), __FUNCTION__, __LINE__
|
||||
#define ESP_PANEL_ERROR_CHECK_LOGE(tag, err, format, ...) ESP_LOGE(tag, ESP_PANEL_ERROR_CHECK_LOG_FORMAT(err, format), ##__VA_ARGS__)
|
||||
#define ESP_PANEL_OTHER_CHECK_LOG_FORMAT(format) "%s(%u): " format, __FUNCTION__, __LINE__
|
||||
#define ESP_PANEL_OTHER_CHECK_LOGE(tag, format, ...) ESP_LOGE(tag, ESP_PANEL_OTHER_CHECK_LOG_FORMAT(format), ##__VA_ARGS__)
|
||||
#else
|
||||
#define ESP_PANEL_ERROR_CHECK_LOGE(tag, err, format, ...) do {} while(0)
|
||||
#define ESP_PANEL_OTHER_CHECK_LOGE(tag, format, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#define ESP_PANEL_CHECK_ERR_RET(x, ret, fmt, ...) do { \
|
||||
esp_err_t err_rc_ = (x); \
|
||||
if (unlikely(err_rc_ != ESP_OK)) { \
|
||||
ESP_PANEL_ERROR_CHECK_LOGE(TAG, err_rc_, fmt, ##__VA_ARGS__); \
|
||||
return ret; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define ESP_PANEL_CHECK_NULL_RET(x, ret, fmt, ...) do { \
|
||||
if ((x) == NULL) { \
|
||||
ESP_PANEL_OTHER_CHECK_LOGE(TAG, fmt, ##__VA_ARGS__); \
|
||||
return ret; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define ESP_PANEL_CHECK_FALSE_RET(x, ret, fmt, ...) do { \
|
||||
if ((x) == false) { \
|
||||
ESP_PANEL_OTHER_CHECK_LOGE(TAG, fmt, ##__VA_ARGS__); \
|
||||
return ret; \
|
||||
} \
|
||||
} while(0)
|
||||
#endif
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "esp_lcd_panel_rgb.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
/**
|
||||
* @brief Panel bus type macros
|
||||
*
|
||||
*/
|
||||
#define ESP_PANEL_BUS_TYPE_UNKNOWN (0)
|
||||
#define ESP_PANEL_BUS_TYPE_SPI (1)
|
||||
#define ESP_PANEL_BUS_TYPE_QSPI (2)
|
||||
#define ESP_PANEL_BUS_TYPE_RGB (3)
|
||||
#define ESP_PANEL_BUS_TYPE_I2C (4)
|
||||
#define ESP_PANEL_BUS_TYPE_I80 (5)
|
||||
#define ESP_PANEL_BUS_TYPE_MAX (6)
|
||||
|
||||
#define _ESP_PANEL_TOUCH_I2C_PANEL_IO_CONFIG(name) ESP_LCD_TOUCH_IO_I2C_ ## name ## _CONFIG()
|
||||
/**
|
||||
* @brief This macro is used to generate the I2C panel IO configuration according to the touch panel name.
|
||||
*
|
||||
* Taking GT911 as an example, the following is the actual code after macro expansion:
|
||||
*
|
||||
* ESP_PANEL_TOUCH_I2C_PANEL_IO_CONFIG(GT911) => ESP_LCD_TOUCH_IO_I2C_GT911_CONFIG()
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_I2C_PANEL_IO_CONFIG(name) _ESP_PANEL_TOUCH_I2C_PANEL_IO_CONFIG(name)
|
||||
|
||||
#define _ESP_PANEL_TOUCH_SPI_PANEL_IO_CONFIG(name, cs_io) ESP_LCD_TOUCH_IO_SPI_ ## name ## _CONFIG(cs_io)
|
||||
/**
|
||||
* @brief This macro is used to generate the SPI panel IO configuration according to the touch panel name.
|
||||
*
|
||||
* Taking XPT2046 as an example, the following is the actual code after macro expansion:
|
||||
*
|
||||
* ESP_PANEL_TOUCH_SPI_PANEL_IO_CONFIG(XPT2046, 5) => ESP_LCD_TOUCH_IO_SPI_XPT2046_CONFIG(5)
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_SPI_PANEL_IO_CONFIG(name, cs_io) _ESP_PANEL_TOUCH_SPI_PANEL_IO_CONFIG(name, cs_io)
|
||||
|
||||
/**
|
||||
* @brief Formater for single LCD vendor command with 8-bit parameter
|
||||
*
|
||||
* @param delay_ms Delay in milliseconds after this command
|
||||
* @param command LCD command
|
||||
* @param ... Array of 8-bit command parameters, should be like `{data0, data1, data2, ...}`
|
||||
*
|
||||
*/
|
||||
#define ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(delay_ms, command, ...) {command, (uint8_t []) __VA_ARGS__, sizeof((uint8_t []) \
|
||||
__VA_ARGS__), delay_ms}
|
||||
/**
|
||||
* @brief Formater for single LCD vendor command with no parameter
|
||||
*
|
||||
* @param delay_ms Delay in milliseconds after this command
|
||||
* @param command LCD command
|
||||
*
|
||||
*/
|
||||
#define ESP_PANEL_LCD_CMD_WITH_NONE_PARAM(delay_ms, command) {command, (uint8_t []){ 0x00 }, 0, delay_ms}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "ESP_Panel_Conf_Internal.h"
|
||||
#include "ESP_Panel_Board_Internal.h"
|
||||
|
||||
/* Library Version */
|
||||
#define ESP_PANEL_VERSION_MAJOR 0
|
||||
#define ESP_PANEL_VERSION_MINOR 1
|
||||
#define ESP_PANEL_VERSION_PATCH 4
|
||||
|
||||
/* File `ESP_Panel_Conf.h` */
|
||||
#define ESP_PANEL_CONF_VERSION_MAJOR 0
|
||||
#define ESP_PANEL_CONF_VERSION_MINOR 1
|
||||
#define ESP_PANEL_CONF_VERSION_PATCH 1
|
||||
|
||||
/* File `ESP_Panel_Board_Custom.h` */
|
||||
#define ESP_PANEL_BOARD_CUSTOM_VERSION_MAJOR 0
|
||||
#define ESP_PANEL_BOARD_CUSTOM_VERSION_MINOR 1
|
||||
#define ESP_PANEL_BOARD_CUSTOM_VERSION_PATCH 1
|
||||
|
||||
/* File `ESP_Panel_Board_Supported.h` */
|
||||
#define ESP_PANEL_BOARD_SUPPORTED_VERSION_MAJOR 0
|
||||
#define ESP_PANEL_BOARD_SUPPORTED_VERSION_MINOR 2
|
||||
#define ESP_PANEL_BOARD_SUPPORTED_VERSION_PATCH 0
|
||||
|
||||
/* Check if the current configuration file version is compatible with the library version */
|
||||
// File `ESP_Panel_Conf.h`
|
||||
// If the version is not defined, set it to `0.1.0`
|
||||
#if !defined(ESP_PANEL_CONF_FILE_VERSION_MAJOR) && \
|
||||
!defined(ESP_PANEL_CONF_FILE_VERSION_MINOR) && \
|
||||
!defined(ESP_PANEL_CONF_FILE_VERSION_PATCH)
|
||||
#define ESP_PANEL_CONF_FILE_VERSION_MAJOR 0
|
||||
#define ESP_PANEL_CONF_FILE_VERSION_MINOR 1
|
||||
#define ESP_PANEL_CONF_FILE_VERSION_PATCH 0
|
||||
#endif
|
||||
// Check if the current configuration file version is compatible with the library version
|
||||
#if ESP_PANEL_CONF_FILE_VERSION_MAJOR != ESP_PANEL_CONF_VERSION_MAJOR
|
||||
#error "The file `ESP_Panel_Conf.h` version is not compatible. Please update it with the file from the library"
|
||||
#elif ESP_PANEL_CONF_FILE_VERSION_MINOR < ESP_PANEL_CONF_VERSION_MINOR
|
||||
#warning "The file `ESP_Panel_Conf.h` version is outdated. Some new configurations are missing"
|
||||
#elif ESP_PANEL_CONF_FILE_VERSION_MINOR > ESP_PANEL_CONF_VERSION_MINOR
|
||||
#warning "The file `ESP_Panel_Conf.h` version is newer than the library. Some new configurations are not supported"
|
||||
#endif /* ESP_PANEL_CONF_INCLUDE_INSIDE */
|
||||
|
||||
// File `ESP_Panel_Board_Custom.h` & `ESP_Panel_Board_Supported.h`
|
||||
#ifdef ESP_PANEL_USE_BOARD
|
||||
/* For using a supported board */
|
||||
#if CONFIG_ESP_PANEL_USE_SUPPORTED_BOARD || ESP_PANEL_USE_SUPPORTED_BOARD
|
||||
// If the version is not defined, set it to `0.1.0`
|
||||
#if !defined(ESP_PANEL_BOARD_SUPPORTED_FILE_VERSION_MAJOR) && \
|
||||
!defined(ESP_PANEL_BOARD_SUPPORTED_FILE_VERSION_MINOR) && \
|
||||
!defined(ESP_PANEL_BOARD_SUPPORTED_FILE_VERSION_PATCH)
|
||||
#define ESP_PANEL_BOARD_SUPPORTED_FILE_VERSION_MAJOR 0
|
||||
#define ESP_PANEL_BOARD_SUPPORTED_FILE_VERSION_MINOR 1
|
||||
#define ESP_PANEL_BOARD_SUPPORTED_FILE_VERSION_PATCH 0
|
||||
#endif
|
||||
// Check if the current configuration file version is compatible with the library version
|
||||
#if ESP_PANEL_BOARD_SUPPORTED_FILE_VERSION_MAJOR != ESP_PANEL_BOARD_SUPPORTED_VERSION_MAJOR
|
||||
#error "The file `ESP_Panel_Board_Supported.h` version is not compatible. Please update it with the file from the library"
|
||||
#elif ESP_PANEL_BOARD_SUPPORTED_FILE_VERSION_MINOR < ESP_PANEL_BOARD_SUPPORTED_VERSION_MINOR
|
||||
#warning "The file `ESP_Panel_Board_Supported.h` version is outdated. Some new configurations are missing"
|
||||
#elif ESP_PANEL_BOARD_SUPPORTED_FILE_VERSION_MINOR > ESP_PANEL_BOARD_SUPPORTED_VERSION_MINOR
|
||||
#warning "The file `ESP_Panel_Board_Supported.h` version is newer than the library. Some new configurations are not supported"
|
||||
#endif
|
||||
|
||||
#else /* For using a custom board */
|
||||
|
||||
// If the version is not defined, set it to `0.1.0`
|
||||
#if !defined(ESP_PANEL_BOARD_CUSTOM_FILE_VERSION_MAJOR) && \
|
||||
!defined(ESP_PANEL_BOARD_CUSTOM_FILE_VERSION_MINOR) && \
|
||||
!defined(ESP_PANEL_BOARD_CUSTOM_FILE_VERSION_PATCH)
|
||||
#define ESP_PANEL_BOARD_CUSTOM_FILE_VERSION_MAJOR 0
|
||||
#define ESP_PANEL_BOARD_CUSTOM_FILE_VERSION_MINOR 1
|
||||
#define ESP_PANEL_BOARD_CUSTOM_FILE_VERSION_PATCH 0
|
||||
#endif
|
||||
// Check if the current configuration file version is compatible with the library version
|
||||
#if ESP_PANEL_BOARD_CUSTOM_FILE_VERSION_MAJOR != ESP_PANEL_BOARD_CUSTOM_VERSION_MAJOR
|
||||
#error "The file `ESP_Panel_Board_Custom.h` version is not compatible. Please update it with the file from the library"
|
||||
#elif ESP_PANEL_BOARD_CUSTOM_FILE_VERSION_MINOR < ESP_PANEL_BOARD_CUSTOM_VERSION_MINOR
|
||||
#warning "The file `ESP_Panel_Board_Custom.h` version is outdated. Some new configurations are missing"
|
||||
#elif ESP_PANEL_BOARD_CUSTOM_FILE_VERSION_MINOR > ESP_PANEL_BOARD_CUSTOM_VERSION_MINOR
|
||||
#warning "The file `ESP_Panel_Board_Custom.h` version is newer than the library. Some new configurations are not supported"
|
||||
#endif
|
||||
#endif /* CONFIG_ESP_PANEL_USE_SUPPORTED_BOARD || ESP_PANEL_USE_SUPPORTED_BOARD */
|
||||
#endif /* ESP_PANEL_USE_BOARD */
|
||||
+146
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// *INDENT-OFF*
|
||||
|
||||
/* Handle special Kconfig options */
|
||||
#ifndef ESP_PANEL_KCONFIG_IGNORE
|
||||
#include "sdkconfig.h"
|
||||
#ifdef CONFIG_ESP_PANEL_CONF_SKIP
|
||||
#define ESP_PANEL_CONF_SKIP
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "ESP_PanelTypes.h"
|
||||
|
||||
/* If "ESP_Panel_*_Board.h" are available from here, try to use them later */
|
||||
#ifdef __has_include
|
||||
#if __has_include("ESP_Panel_Board_Supported.h")
|
||||
#ifndef ESP_PANEL_SUPPORTED_BOARD_INCLUDE_SIMPLE
|
||||
#define ESP_PANEL_SUPPORTED_BOARD_INCLUDE_SIMPLE
|
||||
#endif
|
||||
#elif __has_include("../../ESP_Panel_Board_Supported.h")
|
||||
#ifndef ESP_PANEL_SUPPORTED_BOARD_INCLUDE_OUTSIDE
|
||||
#define ESP_PANEL_SUPPORTED_BOARD_INCLUDE_OUTSIDE
|
||||
#endif
|
||||
#endif
|
||||
#if __has_include("ESP_Panel_Board_Custom.h")
|
||||
#ifndef ESP_PANEL_CUSTOM_BOARD_INCLUDE_SIMPLE
|
||||
#define ESP_PANEL_CUSTOM_BOARD_INCLUDE_SIMPLE
|
||||
#endif
|
||||
#elif __has_include("../../ESP_Panel_Board_Custom.h")
|
||||
#ifndef ESP_PANEL_CUSTOM_BOARD_INCLUDE_OUTSIDE
|
||||
#define ESP_PANEL_CUSTOM_BOARD_INCLUDE_OUTSIDE
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* If "ESP_Panel_Board_*.h" are not skipped, include them */
|
||||
#ifndef ESP_PANEL_CONF_SKIP
|
||||
#ifdef ESP_PANEL_SUPPORTED_BOARD_PATH /* If there is a path defined for "ESP_Panel_Board_Supported.h", use it */
|
||||
#define __TO_STR_AUX(x) #x
|
||||
#define __TO_STR(x) __TO_STR_AUX(x)
|
||||
#include __TO_STR(ESP_PANEL_SUPPORTED_BOARD_PATH)
|
||||
#undef __TO_STR_AUX
|
||||
#undef __TO_STR
|
||||
#elif defined(ESP_PANEL_SUPPORTED_BOARD_INCLUDE_SIMPLE) /* Or simply include if "ESP_Panel_Board_Supported.h" is available */
|
||||
#include "ESP_Panel_Board_Supported.h"
|
||||
#elif defined(ESP_PANEL_SUPPORTED_BOARD_INCLUDE_OUTSIDE) /* Or include if "../../ESP_Panel_Board_Supported.h" is available */
|
||||
#include "../../ESP_Panel_Board_Supported.h"
|
||||
#endif
|
||||
#ifdef ESP_PANEL_CUSTOM_BOARD_PATH /* If there is a path defined for "ESP_Panel_Board_Custom.h" use it */
|
||||
#define __TO_STR_AUX(x) #x
|
||||
#define __TO_STR(x) __TO_STR_AUX(x)
|
||||
#include __TO_STR(ESP_PANEL_CUSTOM_BOARD_PATH)
|
||||
#undef __TO_STR_AUX
|
||||
#undef __TO_STR
|
||||
#elif defined(ESP_PANEL_CUSTOM_BOARD_INCLUDE_SIMPLE) /* Or simply include if "ESP_Panel_Board_Custom.h" is available */
|
||||
#include "ESP_Panel_Board_Custom.h"
|
||||
#elif defined(ESP_PANEL_CUSTOM_BOARD_INCLUDE_OUTSIDE) /* Or include if "../../ESP_Panel_Board_Custom.h" is available */
|
||||
#include "../../ESP_Panel_Board_Custom.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Check if select both custom and supported board */
|
||||
#if (CONFIG_ESP_PANEL_USE_SUPPORTED_BOARD || ESP_PANEL_USE_SUPPORTED_BOARD) && \
|
||||
(CONFIG_ESP_PANEL_USE_CUSTOM_BOARD || ESP_PANEL_USE_CUSTOM_BOARD)
|
||||
#error "Please select either a custom or a supported development board, cannot enable both simultaneously"
|
||||
#endif
|
||||
|
||||
/* Check if use board */
|
||||
#if CONFIG_ESP_PANEL_USE_SUPPORTED_BOARD || ESP_PANEL_USE_SUPPORTED_BOARD || \
|
||||
CONFIG_ESP_PANEL_USE_CUSTOM_BOARD || ESP_PANEL_USE_CUSTOM_BOARD
|
||||
#define ESP_PANEL_USE_BOARD
|
||||
#endif
|
||||
|
||||
#ifdef ESP_PANEL_USE_BOARD
|
||||
/* For using a supported board */
|
||||
#if CONFIG_ESP_PANEL_USE_SUPPORTED_BOARD || ESP_PANEL_USE_SUPPORTED_BOARD
|
||||
// Include the supported board header file
|
||||
#include "board/ESP_PanelBoard.h"
|
||||
#endif
|
||||
|
||||
/* Define some special macros for devices */
|
||||
/*-------------------------------- LCD Related --------------------------------*/
|
||||
#if ESP_PANEL_USE_LCD
|
||||
#if ESP_PANEL_LCD_BUS_TYPE == ESP_PANEL_BUS_TYPE_SPI
|
||||
|
||||
#include "hal/spi_types.h"
|
||||
#define ESP_PANEL_LCD_BUS_NAME SPI
|
||||
#define ESP_PANEL_LCD_BUS_HOST ((spi_host_device_t)ESP_PANEL_LCD_BUS_HOST_ID)
|
||||
|
||||
#elif ESP_PANEL_LCD_BUS_TYPE == ESP_PANEL_BUS_TYPE_QSPI
|
||||
|
||||
#include "hal/spi_types.h"
|
||||
#define ESP_PANEL_LCD_BUS_NAME QSPI
|
||||
#define ESP_PANEL_LCD_BUS_HOST ((spi_host_device_t)ESP_PANEL_LCD_BUS_HOST_ID)
|
||||
|
||||
#elif ESP_PANEL_LCD_BUS_TYPE == ESP_PANEL_BUS_TYPE_RGB
|
||||
|
||||
#ifndef SOC_LCD_RGB_SUPPORTED
|
||||
#error "LCD RGB is only supported for ESP32-S3, please select the correct board."
|
||||
#endif
|
||||
#define ESP_PANEL_LCD_BUS_NAME RGB
|
||||
#define ESP_PANEL_LCD_BUS_HOST (-1)
|
||||
|
||||
#else
|
||||
|
||||
#error "Unkonw LCD panel bus type selected, please refer to the README for supported bus types"
|
||||
|
||||
#endif /* ESP_PANEL_LCD_BUS_TYPE */
|
||||
#endif /* ESP_PANEL_USE_LCD */
|
||||
/*-------------------------------- Touch Related --------------------------------*/
|
||||
#if ESP_PANEL_USE_TOUCH
|
||||
#if ESP_PANEL_TOUCH_BUS_TYPE == ESP_PANEL_BUS_TYPE_I2C
|
||||
|
||||
#include "hal/i2c_types.h"
|
||||
#define ESP_PANEL_TOUCH_BUS_NAME I2C
|
||||
#define ESP_PANEL_TOUCH_BUS_HOST ((i2c_port_t)ESP_PANEL_TOUCH_BUS_HOST_ID)
|
||||
|
||||
#elif ESP_PANEL_TOUCH_BUS_TYPE == ESP_PANEL_BUS_TYPE_SPI
|
||||
|
||||
#include "hal/spi_types.h"
|
||||
#define ESP_PANEL_TOUCH_BUS_NAME SPI
|
||||
#define ESP_PANEL_TOUCH_BUS_HOST ((spi_host_device_t)ESP_PANEL_TOUCH_BUS_HOST_ID)
|
||||
|
||||
#else
|
||||
|
||||
#error "Unkonw Touch bus type selected, please refer to the README for supported bus types."
|
||||
|
||||
#endif /* ESP_PANEL_TOUCH_BUS_TYPE */
|
||||
#endif /* ESP_PANEL_USE_TOUCH */
|
||||
/*-------------------------------- IO Expander Related --------------------------------*/
|
||||
#if ESP_PANEL_USE_EXPANDER
|
||||
|
||||
#include "hal/i2c_types.h"
|
||||
#define ESP_PANEL_EXPANDER_HOST ((i2c_port_t)ESP_PANEL_EXPANDER_HOST_ID)
|
||||
|
||||
#endif /* ESP_PANEL_USE_EXPANDER */
|
||||
#endif /* ESP_PANEL_USE_BOARD */
|
||||
|
||||
// *INDENT-OFF*
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// *INDENT-OFF*
|
||||
|
||||
/* Handle special Kconfig options */
|
||||
#ifndef ESP_PANEL_KCONFIG_IGNORE
|
||||
#include "sdkconfig.h"
|
||||
#ifdef CONFIG_ESP_PANEL_CONF_SKIP
|
||||
#define ESP_PANEL_CONF_SKIP
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* If "ESP_Panel_Conf.h" is available from here, try to use it later */
|
||||
#ifdef __has_include
|
||||
#if __has_include("ESP_Panel_Conf.h")
|
||||
#ifndef ESP_PANEL_CONF_INCLUDE_SIMPLE
|
||||
#define ESP_PANEL_CONF_INCLUDE_SIMPLE
|
||||
#endif
|
||||
#elif __has_include("../../ESP_Panel_Conf.h")
|
||||
#ifndef ESP_PANEL_CONF_INCLUDE_OUTSIDE
|
||||
#define ESP_PANEL_CONF_INCLUDE_OUTSIDE
|
||||
#endif
|
||||
#else
|
||||
#define ESP_PANEL_CONF_INCLUDE_INSIDE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* If "ESP_Panel_Conf.h" is not skipped, include it */
|
||||
#ifndef ESP_PANEL_CONF_SKIP
|
||||
#ifdef ESP_PANEL_CONF_PATH /* If there is a path defined for "ESP_Panel_Conf.h" use it */
|
||||
#define __TO_STR_AUX(x) #x
|
||||
#define __TO_STR(x) __TO_STR_AUX(x)
|
||||
#include __TO_STR(ESP_PANEL_CONF_PATH)
|
||||
#undef __TO_STR_AUX
|
||||
#undef __TO_STR
|
||||
#elif defined(ESP_PANEL_CONF_INCLUDE_SIMPLE) /* Or simply include if "ESP_Panel_Conf.h" is available */
|
||||
#include "ESP_Panel_Conf.h"
|
||||
#elif defined(ESP_PANEL_CONF_INCLUDE_OUTSIDE) /* Or include if "../../ESP_Panel_Conf.h" is available */
|
||||
#include "../../ESP_Panel_Conf.h"
|
||||
#elif defined(ESP_PANEL_CONF_INCLUDE_INSIDE) /* Or include the default configuration */
|
||||
#include "../ESP_Panel_Conf.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ESP_PANEL_CONF_INCLUDE_INSIDE
|
||||
/* Supplement macro definitions based on sdkconfig, use default values if not defined */
|
||||
/*-------------------------------- Debug configurations --------------------------------*/
|
||||
#ifndef ESP_PANEL_CHECK_RESULT_ASSERT
|
||||
#ifdef CONFIG_ESP_PANEL_CHECK_RESULT_ASSERT
|
||||
#define ESP_PANEL_CHECK_RESULT_ASSERT CONFIG_ESP_PANEL_CHECK_RESULT_ASSERT
|
||||
#else
|
||||
#define ESP_PANEL_CHECK_RESULT_ASSERT (0)
|
||||
#endif
|
||||
#endif
|
||||
#ifndef ESP_PANEL_ENABLE_LOG
|
||||
#ifdef CONFIG_ESP_PANEL_ENABLE_LOG
|
||||
#define ESP_PANEL_ENABLE_LOG CONFIG_ESP_PANEL_ENABLE_LOG
|
||||
#else
|
||||
#define ESP_PANEL_ENABLE_LOG (0)
|
||||
#endif
|
||||
#endif
|
||||
/*----------------------------- Touch driver configurations -----------------------------*/
|
||||
#ifndef ESP_PANEL_TOUCH_MAX_POINTS
|
||||
#ifdef CONFIG_ESP_PANEL_TOUCH_MAX_POINTS
|
||||
#define ESP_PANEL_TOUCH_MAX_POINTS CONFIG_ESP_PANEL_TOUCH_MAX_POINTS
|
||||
#else
|
||||
#define ESP_PANEL_TOUCH_MAX_POINTS (5)
|
||||
#endif
|
||||
#endif
|
||||
#ifndef ESP_PANEL_TOUCH_MAX_BUTTONS
|
||||
#ifdef CONFIG_ESP_PANEL_TOUCH_MAX_BUTTONS
|
||||
#define ESP_PANEL_TOUCH_MAX_BUTTONS CONFIG_ESP_PANEL_TOUCH_MAX_BUTTONS
|
||||
#else
|
||||
#define ESP_PANEL_TOUCH_MAX_BUTTONS (1)
|
||||
#endif
|
||||
#endif
|
||||
#ifndef ESP_PANEL_TOUCH_XPT2046_Z_THRESHOLD
|
||||
#ifdef CONFIG_ESP_PANEL_TOUCH_XPT2046_Z_THRESHOLD
|
||||
#define ESP_PANEL_TOUCH_XPT2046_Z_THRESHOLD CONFIG_ESP_PANEL_TOUCH_XPT2046_Z_THRESHOLD
|
||||
#else
|
||||
#define ESP_PANEL_TOUCH_XPT2046_Z_THRESHOLD (400)
|
||||
#endif
|
||||
#endif
|
||||
#ifndef ESP_PANEL_TOUCH_XPT2046_INTERRUPT_MODE
|
||||
#ifdef CONFIG_ESP_PANEL_TOUCH_XPT2046_INTERRUPT_MODE
|
||||
#define ESP_PANEL_TOUCH_XPT2046_INTERRUPT_MODE CONFIG_ESP_PANEL_TOUCH_XPT2046_INTERRUPT_MODE
|
||||
#else
|
||||
#define ESP_PANEL_TOUCH_XPT2046_INTERRUPT_MODE (0)
|
||||
#endif
|
||||
#endif
|
||||
#ifndef ESP_PANEL_TOUCH_XPT2046_VREF_ON_MODE
|
||||
#ifdef CONFIG_ESP_PANEL_TOUCH_XPT2046_VREF_ON_MODE
|
||||
#define ESP_PANEL_TOUCH_XPT2046_VREF_ON_MODE CONFIG_ESP_PANEL_TOUCH_XPT2046_VREF_ON_MODE
|
||||
#else
|
||||
#define ESP_PANEL_TOUCH_XPT2046_VREF_ON_MODE (0)
|
||||
#endif
|
||||
#endif
|
||||
#ifndef ESP_PANEL_TOUCH_XPT2046_CONVERT_ADC_TO_COORDS
|
||||
#ifdef CONFIG_ESP_PANEL_TOUCH_XPT2046_CONVERT_ADC_TO_COORDS
|
||||
#define ESP_PANEL_TOUCH_XPT2046_CONVERT_ADC_TO_COORDS CONFIG_ESP_PANEL_TOUCH_XPT2046_CONVERT_ADC_TO_COORDS
|
||||
#else
|
||||
#define ESP_PANEL_TOUCH_XPT2046_CONVERT_ADC_TO_COORDS (1)
|
||||
#endif
|
||||
#endif
|
||||
#ifndef ESP_PANEL_TOUCH_XPT2046_ENABLE_LOCKING
|
||||
#ifdef CONFIG_ESP_PANEL_TOUCH_XPT2046_ENABLE_LOCKING
|
||||
#define ESP_PANEL_TOUCH_XPT2046_ENABLE_LOCKING CONFIG_ESP_PANEL_TOUCH_XPT2046_ENABLE_LOCKING
|
||||
#else
|
||||
#define ESP_PANEL_TOUCH_XPT2046_ENABLE_LOCKING (1)
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// *INDENT-OFF*
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/* Drivers */
|
||||
#include "ESP_Panel_Conf_Internal.h"
|
||||
#include "ESP_Panel_Board_Internal.h"
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "ESP_PanelTypes.h"
|
||||
#include "ESP_PanelVersions.h"
|
||||
|
||||
/* Host */
|
||||
#include "host/ESP_PanelHost.h"
|
||||
|
||||
/* Bus */
|
||||
#include "bus/ESP_PanelBus.h"
|
||||
#include "bus/I2C.h"
|
||||
#include "bus/SPI.h"
|
||||
#include "bus/RGB.h"
|
||||
#include "bus/QSPI.h"
|
||||
|
||||
/* LCD */
|
||||
#include "lcd/ESP_PanelLcd.h"
|
||||
#include "lcd/GC9503.h"
|
||||
#include "lcd/GC9A01.h"
|
||||
#include "lcd/GC9B71.h"
|
||||
#include "lcd/ILI9341.h"
|
||||
#include "lcd/SH8601.h"
|
||||
#include "lcd/SPD2010.h"
|
||||
#include "lcd/ST7262.h"
|
||||
#include "lcd/ST7701.h"
|
||||
#include "lcd/ST7789.h"
|
||||
#include "lcd/ST77916.h"
|
||||
#include "lcd/ST77922.h"
|
||||
|
||||
/* Touch */
|
||||
#include "touch/ESP_PanelTouch.h"
|
||||
#include "touch/CST816S.h"
|
||||
#include "touch/FT5x06.h"
|
||||
#include "touch/GT1151.h"
|
||||
#include "touch/GT911.h"
|
||||
#include "touch/ST1633.h"
|
||||
#include "touch/ST7123.h"
|
||||
#include "touch/TT21100.h"
|
||||
#include "touch/XPT2046.h"
|
||||
|
||||
/* Backlight */
|
||||
#include "backlight/ESP_PanelBacklight.h"
|
||||
|
||||
/* 3rd-party Libraries */
|
||||
#include "ESP_IOExpander_Library.h"
|
||||
|
||||
/* Panel */
|
||||
#include "ESP_Panel.h"
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "ESP_PanelBacklight.h"
|
||||
|
||||
static const char *TAG = "ESP_PanelBacklight";
|
||||
|
||||
ESP_PanelBacklight::ESP_PanelBacklight(int io_num, bool light_up_level, bool use_pwm):
|
||||
_is_initialized(false),
|
||||
_use_pwm(use_pwm),
|
||||
_light_up_level(light_up_level),
|
||||
_io_num(io_num),
|
||||
_timer_config(ESP_PANEL_BACKLIGHT_LEDC_TIMER_CONFIG_DEFAULT()),
|
||||
_channel_config(ESP_PANEL_BACKLIGHT_LEDC_CHANNEL_CONFIG_DEFAULT(io_num, light_up_level))
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelBacklight::ESP_PanelBacklight(const ledc_timer_config_t &timer_config, const ledc_channel_config_t &channel_config):
|
||||
_is_initialized(false),
|
||||
_use_pwm(true),
|
||||
_timer_config(timer_config),
|
||||
_channel_config(channel_config)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelBacklight::~ESP_PanelBacklight()
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
if (!_is_initialized && !del()) {
|
||||
ESP_LOGE(TAG, "Delete device failed");
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Destroyed");
|
||||
}
|
||||
|
||||
bool ESP_PanelBacklight::begin(void)
|
||||
{
|
||||
ESP_PANEL_CHECK_FALSE_RET(_io_num >= 0, false, "Invalid IO number");
|
||||
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
ESP_LOGD(TAG, "begin start");
|
||||
|
||||
if (_use_pwm) {
|
||||
ESP_LOGD(TAG, "Use PWM(LEDC) to control");
|
||||
|
||||
ESP_PANEL_CHECK_ERR_RET(ledc_timer_config(&_timer_config), false, "LEDC timer config failed");
|
||||
ESP_PANEL_CHECK_ERR_RET(ledc_channel_config(&_channel_config), false, "LEDC channel config failed");
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Use GPIO to control");
|
||||
|
||||
gpio_config_t io_config = ESP_PANEL_BACKLIGHT_GPIO_CONFIG_DEFAULT(_io_num);
|
||||
ESP_PANEL_CHECK_ERR_RET(gpio_config(&io_config), false, "GPIO config failed");
|
||||
ESP_PANEL_CHECK_ERR_RET(gpio_set_level((gpio_num_t)_io_num, _light_up_level), false, "GPIO set level failed");
|
||||
}
|
||||
|
||||
_is_initialized = true;
|
||||
ESP_LOGD(TAG, "begin end");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_PanelBacklight::setBrightness(uint8_t percent)
|
||||
{
|
||||
ESP_PANEL_CHECK_FALSE_RET(_is_initialized, false, "Device has not been initialized");
|
||||
|
||||
ESP_LOGD(TAG, "Set brightness to %d%%", percent);
|
||||
|
||||
percent = percent > 100 ? 100 : percent;
|
||||
if (_use_pwm) {
|
||||
uint32_t duty_cycle = (BIT(_timer_config.duty_resolution) * percent) / 100;
|
||||
ledc_channel_t channel = _channel_config.channel;
|
||||
ledc_mode_t mode = _channel_config.speed_mode;
|
||||
|
||||
ESP_PANEL_CHECK_ERR_RET(ledc_set_duty(mode, channel, duty_cycle), false, "LEDC set duty failed");
|
||||
ESP_PANEL_CHECK_ERR_RET(ledc_update_duty(mode, channel), false, "LEDC update duty failed");
|
||||
} else {
|
||||
bool level = (percent > 0) ? _light_up_level : !_light_up_level;
|
||||
|
||||
ESP_PANEL_CHECK_ERR_RET(gpio_set_level((gpio_num_t)_io_num, level), false, "GPIO set level failed");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_PanelBacklight::on(void)
|
||||
{
|
||||
return setBrightness(100);
|
||||
}
|
||||
|
||||
bool ESP_PanelBacklight::off(void)
|
||||
{
|
||||
return setBrightness(0);
|
||||
}
|
||||
|
||||
bool ESP_PanelBacklight::del(void)
|
||||
{
|
||||
ESP_PANEL_CHECK_FALSE_RET(_is_initialized, false, "Device has not been initialized");
|
||||
|
||||
if (_use_pwm) {
|
||||
ledc_mode_t mode = _channel_config.speed_mode;
|
||||
ledc_channel_t channel = _channel_config.channel;
|
||||
|
||||
ESP_PANEL_CHECK_ERR_RET(ledc_stop(mode, channel, _light_up_level), false, "LEDC stop failed");
|
||||
} else {
|
||||
gpio_reset_pin((gpio_num_t)_io_num);
|
||||
}
|
||||
|
||||
_is_initialized = false;
|
||||
ESP_LOGD(TAG, "Delete device");
|
||||
|
||||
return true;
|
||||
}
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "driver/ledc.h"
|
||||
|
||||
/**
|
||||
* @brief Backlight LEDC default configuration macros
|
||||
*
|
||||
*/
|
||||
#define ESP_PANEL_BACKLIGHT_LEDC_TIMER_CONFIG_DEFAULT() \
|
||||
{ \
|
||||
.speed_mode = LEDC_LOW_SPEED_MODE, \
|
||||
.duty_resolution = LEDC_TIMER_10_BIT, \
|
||||
.timer_num = LEDC_TIMER_0, \
|
||||
.freq_hz = 5000, \
|
||||
.clk_cfg = LEDC_AUTO_CLK, \
|
||||
}
|
||||
#define ESP_PANEL_BACKLIGHT_LEDC_CHANNEL_CONFIG_DEFAULT(io_num, on_level) \
|
||||
{ \
|
||||
.gpio_num = io_num, \
|
||||
.speed_mode = LEDC_LOW_SPEED_MODE, \
|
||||
.channel = LEDC_CHANNEL_0, \
|
||||
.intr_type = LEDC_INTR_DISABLE, \
|
||||
.timer_sel = LEDC_TIMER_0, \
|
||||
.duty = 0, \
|
||||
.hpoint = 0, \
|
||||
.flags = { \
|
||||
.output_invert = !on_level, \
|
||||
}, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Backlight GPIO default configuration macro
|
||||
*
|
||||
*/
|
||||
#define ESP_PANEL_BACKLIGHT_GPIO_CONFIG_DEFAULT(io_num) \
|
||||
{ \
|
||||
.pin_bit_mask = BIT64(io_num), \
|
||||
.mode = GPIO_MODE_OUTPUT, \
|
||||
.pull_up_en = GPIO_PULLUP_DISABLE, \
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE, \
|
||||
.intr_type = GPIO_INTR_DISABLE, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The backlight device class
|
||||
*
|
||||
*/
|
||||
class ESP_PanelBacklight {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new backlight device in a simple way, the `begin()` function should be called after this
|
||||
*
|
||||
* @note This function uses some default values to config the backlight device, please use `config*()` functions to
|
||||
* change them
|
||||
*
|
||||
* @param io_num GPIO number
|
||||
* @param light_up_level Level when light up
|
||||
* @param use_pwm Use PWM(LEDC) if set to true
|
||||
*/
|
||||
ESP_PanelBacklight(int io_num, bool light_up_level, bool use_pwm);
|
||||
|
||||
/**
|
||||
* @brief Construct a new backlight device with using PWM(LEDC) in a complex way, the `begin()` function should be
|
||||
* called after this
|
||||
*
|
||||
* @param timer_config LEDC timer configuration
|
||||
* @param channel_config LEDC channel configuration
|
||||
*/
|
||||
ESP_PanelBacklight(const ledc_timer_config_t &timer_config, const ledc_channel_config_t &channel_config);
|
||||
|
||||
/**
|
||||
* @brief Destroy the backlight device
|
||||
*
|
||||
*/
|
||||
~ESP_PanelBacklight();
|
||||
|
||||
/**
|
||||
* @brief Startup the backlight device
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool begin(void);
|
||||
|
||||
/**
|
||||
* @brief Set the brightness of the backlight by percent
|
||||
*
|
||||
* @note This function should be called after `begin()`
|
||||
* @note When not using PWM, calling this function only controls the backlight switch and cannot adjust
|
||||
* the brightness
|
||||
*
|
||||
* @param percent The brightness percent, 0-100
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool setBrightness(uint8_t percent);
|
||||
|
||||
/**
|
||||
* @brief Turn on the backlight
|
||||
*
|
||||
* @note This function should be called after `begin()`
|
||||
* @note This function is same as `setBrightness(100)`
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool on(void);
|
||||
|
||||
/**
|
||||
* @brief Turn off the backlight
|
||||
*
|
||||
* @note This function should be called after `begin()`
|
||||
* @note This function is same as `setBrightness(0)`
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool off(void);
|
||||
|
||||
/**
|
||||
* @brief Delete the backlight device, release the resources
|
||||
*
|
||||
* @note This function should be called after `begin()`
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool del(void);
|
||||
|
||||
private:
|
||||
bool _is_initialized;
|
||||
bool _use_pwm;
|
||||
bool _light_up_level;
|
||||
uint8_t _io_num;
|
||||
ledc_timer_config_t _timer_config;
|
||||
ledc_channel_config_t _channel_config;
|
||||
};
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
# Board Contribution Guide
|
||||
|
||||
1. Newly added development boards must ensure the hardware schematics are open-source. Please provide a link or file.
|
||||
2. This library currently only supports the APIs provided in ESP-IDF. It does not support other Arduino library APIs, such as Wire.
|
||||
|
||||
**Note**:
|
||||
1. It is recommended to use the vscode + Arduino CLI development environment.
|
||||
2. Pull the ESP32_Display_Panel repository into the Arduino library directory before making modifications.
|
||||
3. The project uses pre-commit to enforce commit standards. It is recommended to install the pre-commit library before committing using the following command:
|
||||
|
||||
```
|
||||
pip3 install pre-commit && pre-commit install
|
||||
```
|
||||
|
||||
## Modification Content
|
||||
|
||||
Using the adaption of the [`M5Stack M5DIAL`](https://github.com/esp-arduino-libs/ESP32_Display_Panel/commit/1886c668468626b9dd2ae975f7db12df5413378e) development board as an example. Following this guide, changes below will be made under the project:
|
||||
|
||||
```
|
||||
| -ESP32_Display_Panel
|
||||
| -src
|
||||
| -board
|
||||
| -m5stack [A]
|
||||
| -M5DIAL.h [A]
|
||||
| -ESP_PanelBoard [M]
|
||||
| -README.md [M]
|
||||
| -ESP_PanelVersions.h [M]
|
||||
| -CHANGELOG.md [M]
|
||||
| -ESP_Panel_Board_Custom.h
|
||||
| -ESP_Panel_Board_Supported.h [M]
|
||||
| -library.properties [M]
|
||||
| -README_CN.md [M]
|
||||
| -README.md [M]
|
||||
```
|
||||
Note: [A] stands for 'append' and [M] stands for 'modify'
|
||||
|
||||
## Modification Process
|
||||
|
||||
Using the adaption of `M5Stack M5DIAL` as an example, follow these steps to modify the relevant files:
|
||||
|
||||
1. **[M]** *[ESP_Panel_Board_Supported.h](../../ESP_Panel_Board_Supported.h)*: Add a macro for the new development board, such as `BOARD_M5STACK_M5DIAL`. Ensure the macro is in uppercase. Include the manufacturer's name and link, as well as the target development board's link.
|
||||
2. **[A]** *[src/board/m5stack/M5DIAL.h](../board/m5stack/M5DIAL.h)*: Use the *ESP_Panel_Board_Custom.h* file in the root directory as a template to create a new configuration header file for the development board. Follow the naming conventions of existing development boards.
|
||||
3. **[M]** *[src/board/ESP_PanelBoard.h](../board/ESP_PanelBoard.h)*: Add the macro check for the new development board by referring to the existing boards in the file, and modify the file to use the correct header file for this development board.
|
||||
|
||||
**Note**: At this point, you can verify the above steps:
|
||||
|
||||
- Choose an example, such as *[examples/Panel/PanelTest](../../examples/Panel/PanelTest/)*.
|
||||
- modify the macro `ESP_PANEL_USE_SUPPORTED_BOARD` to enable this header file. Define the development board macro, such as `BOARD_M5STACK_M5DIAL`, to enable the new header file *[src/board/m5stack/M5DIAL.h](../board/m5stack/M5DIAL.h)*.
|
||||
- Verify the example's ino file. If successful, proceed to the following steps.
|
||||
|
||||
4. **[M]** *[src/board/m5stack/M5DIAL.h](../board/m5stack/M5DIAL.h)*: Modify the configuration header file for the new development board:
|
||||
- Review the hardware schematics of the development board, focusing on the BUS type used for the LCD screen, the LCD driver name, the BUS type used for touch, the touch driver name, and the chip pin numbers used for each interface of the LCD and touch.
|
||||
- The best practice is to first get the screen working, then work on the touch functionality.
|
||||
- If the new development board's driver is compatible with an existing driver, there is no need to add a new driver. Simply note in the comments that this driver is compatible with an existing one and use the existing driver.
|
||||
- If the driver used by the new development board is not compatible with existing drivers or has other special configurations, you can achieve this by modifying the macro functions at the end of the new development board's configuration header file, such as `ESP_PANEL_BEGIN_BACKLIGHT_START_FUNCTION`, `ESP_PANEL_BEGIN_END_FUNCTION`, etc. Refer to *[src/board/espressif/ESP32_S3_BOX_3.h](../board/espressif/ESP32_S3_BOX_3.h)* or *[src/board/m5stack/M5DIAL.h](../board/m5stack/M5DIAL.h)* for specific implementations.
|
||||
- Run examples other than *[examples/LCD](../../examples/LCD/)* and *[examples/Touch](../../examples/Touch/)*, and continuously adjust the configuration header file to ensure correct settings.
|
||||
|
||||
5. **[M]** *[ESP_Panel_Board_Supported](../../ESP_Panel_Board_Supported.h)*, *[library.properties](../../library.properties)*, *[board/Board_Instructions.md](../board/Board_Instructions.md)*, *[README_CN.md](../../README_CN.md)*, *[README.md](../../README.md)*: Update the supported development boards information in these files.
|
||||
6. **[M]** *[src/board/Board_Instructions.md](../board/Board_Instructions.md)*: Update the recommended configuration for the new development board.
|
||||
7. **[M]** *[src/ESP_PanelVersions.h](../ESP_PanelVersions.h)*: Ensure that the version under `Library Version` should be ahead of the latest tag version in terms of the tag version; when changes occur to *[ESP_Panel_Board_Custom.h](../../ESP_Panel_Board_Custom.h)*, *[ESP_Panel_Board_Supported.h](../../ESP_Panel_Board_Supported.h)*, and *[ESP_Panel_Conf.h](../../ESP_Panel_Conf.h)* in the root directory, ensure that the version number at the end of the corresponding file and at the beginging of *[src/ESP_PanelVersions.h](../ESP_PanelVersions.h)* should be ahead of the latest tag version in terms of the minor version.
|
||||
8. **[M]** *[CHANGELOG.md](../../CHANGELOG.md)*: Update the changelog.
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
# 开发板贡献指南
|
||||
|
||||
1. 新添加的开发板需要确保硬件原理图开源,需要提供链接或文件。
|
||||
2. 该库目前仅支持 ESP-IDF 提供的 API,不支持其他 Arduino 库 API,如 Wire。
|
||||
|
||||
**注意**:
|
||||
1. 推荐使用 vscode + Arduino CLI 开发环境。
|
||||
2. 在进行修改之前,将 ESP32_Display_Panel 仓库拉入 Arduino 库目录中。
|
||||
3. 项目使用 pre-commit 来规范提交内容,因此建议在提交之前安装 pre-commit 库,使用以下命令:
|
||||
|
||||
```
|
||||
pip3 install pre-commit && pre-commit install
|
||||
```
|
||||
|
||||
## 需修改内容
|
||||
|
||||
以适配 [`M5Stack M5DIAL`](https://github.com/esp-arduino-libs/ESP32_Display_Panel/commit/1886c668468626b9dd2ae975f7db12df5413378e) 开发板为例。按照本指南,以下更改将在项目中进行:
|
||||
|
||||
```
|
||||
| -ESP32_Display_Panel
|
||||
| -src
|
||||
| -board
|
||||
| -m5stack [A]
|
||||
| -M5DIAL.h [A]
|
||||
| -ESP_PanelBoard [M]
|
||||
| -README.md [M]
|
||||
| -ESP_PanelVersions.h [M]
|
||||
| -CHANGELOG.md [M]
|
||||
| -ESP_Panel_Board_Custom.h
|
||||
| -ESP_Panel_Board_Supported.h [M]
|
||||
| -library.properties [M]
|
||||
| -README_CN.md [M]
|
||||
| -README.md [M]
|
||||
```
|
||||
注:[A] 代表 '添加',[M] 代表 '修改'
|
||||
|
||||
## 各文件修改流程
|
||||
|
||||
以适配 `M5Stack M5DIAL` 为例,按照以下步骤修改相关文件:
|
||||
|
||||
1. **[M]** *[ESP_Panel_Board_Supported.h](../../ESP_Panel_Board_Supported.h)*:为新开发板添加一个宏,例如 `BOARD_M5STACK_M5DIAL`。命名时注意宏名大写。注意附上开发板制造商的名称和链接,以及目标开发板的链接。
|
||||
2. **[A]** *[src/board/m5stack/M5DIAL.h](../board/m5stack/M5DIAL.h)*:使用根目录中的 *ESP_Panel_Board_Custom.h* 文件作为模板,为开发板创建一个新的配置头文件。文件命名请参考已有开发板。
|
||||
3. **[M]** *[src/board/ESP_PanelBoard.h](../board/ESP_PanelBoard.h)*:参照文件中其他开发板的写法,添加新开发板的宏名判断,并注意修改此开发板所使用的头文件。
|
||||
|
||||
**注意**:此时,可以验证上述步骤:
|
||||
|
||||
- 选择一个示例,例如 *[examples/Panel/PanelTest](../../examples/Panel/PanelTest/)*。
|
||||
- 修改宏 `ESP_PANEL_USE_SUPPORTED_BOARD` 以启用此头文件。定义开发板宏,例如 `BOARD_M5STACK_M5DIAL`,以启用新的头文件 *[src/board/m5stack/M5DIAL.h](../board/m5stack/M5DIAL.h)*。
|
||||
- 验证示例的 ino 文件。如果成功,继续后续步骤。
|
||||
|
||||
4. **[M]** *[src/board/m5stack/M5DIAL.h](../board/m5stack/M5DIAL.h)*:修改新开发板的配置头文件:
|
||||
- 审查开发板的硬件原理图,重点关注LCD 屏幕所使用 BUS 类型、 LCD 驱动名、touch 所使用 BUS 类型、touch 驱动名,以及 LCD 和 touch 各接口所使用的芯片管脚号。
|
||||
- 修改技巧是先亮屏再 touch。
|
||||
- 如果新开发板的驱动程序与现有驱动程序兼容,则无需添加新驱动程序。只需在注释中注明该驱动程序与现有驱动程序兼容,并使用现有驱动程序。
|
||||
- 如果新开发板使用的驱动程序与现有驱动程序不兼容或有其他特殊配置,可以通过修改新开发板配置头文件末尾的宏函数来实现,例如 `ESP_PANEL_BEGIN_BACKLIGHT_START_FUNCTION`、`ESP_PANEL_BEGIN_END_FUNCTION` 等。具体实现请参考 *[src/board/espressif/ESP32_S3_BOX_3.h](../board/espressif/ESP32_S3_BOX_3.h)* 或 *[src/board/m5stack/M5DIAL.h](../board/m5stack/M5DIAL.h)*。
|
||||
- 运行除 *[examples/LCD](../../examples/LCD/)* 和 *[examples/Touch](../../examples/Touch/)* 以外的示例,并不断调整配置头文件以确保设置正确。
|
||||
|
||||
5. **[M]** *[ESP_Panel_Board_Supported](../../ESP_Panel_Board_Supported.h)*、*[library.properties](../../library.properties)*、*[board/Board_Instructions.md](../board/Board_Instructions.md)*、*[README_CN.md](../../README_CN.md)*、*[README.md](../../README.md)*:更新上述文件中“已支持开发板”说明。
|
||||
6. **[M]** *[src/board/Board_Instructions.md](../board/Board_Instructions.md)*:更新新开发板的推荐配置。
|
||||
7. **[M]** *[src/ESP_PanelVersions.h](../ESP_PanelVersions.h)*:确保 `Library Version` 下的版本应小版本领先于最新 tag 版本。当根目录下的 *[ESP_Panel_Board_Custom.h](../../ESP_Panel_Board_Custom.h)*、*[ESP_Panel_Board_Supported.h](../../ESP_Panel_Board_Supported.h)* 和 *[ESP_Panel_Conf.h](../../ESP_Panel_Conf.h)* 发生变化时,相应文件末尾和 *[src/ESP_PanelVersions.h](../ESP_PanelVersions.h)* 开头的版本号应中版本领先于最新 tag 版本。
|
||||
8. **[M]** *[CHANGELOG.md](../../CHANGELOG.md)*:更新变更日志。
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
# Board Instructions
|
||||
|
||||
## Internal Supported Development Boards
|
||||
|
||||
### [Espressif](https://www.espressif.com/en/products/devkits)
|
||||
|
||||
| **Picture** | **Name** | **LCD Bus** | **LCD Controller** | **LCD resolution** | **Touch Bus** | **Touch Controller** |
|
||||
| :--------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------: | :--------------: | :----------------: | :----------------: | :-----------: | :------------------: |
|
||||
| <img src="https://docs.espressif.com/projects/esp-dev-kits/en/latest/_images/esp32-c3-lcdkit-isometric-raw.png" width="150"> | [ESP32-C3-LCDkit](https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32c3/esp32-c3-lcdkit/index.html) | SPI | GC9A01 | 240x240 | - | - |
|
||||
| <img src="https://github.com/espressif/esp-box/raw/master/docs/_static/esp32_s3_box.png" width="150"> | [ESP32-S3-Box](https://github.com/espressif/esp-box/tree/master) | SPI | ILI9342 | 320x240 | I2C | TT21100 |
|
||||
| <img src="https://github.com/espressif/esp-box/raw/master/docs/_static/esp32_s3_box_3.png" width="150"> |[ESP32-S3-Box-3](https://github.com/espressif/esp-box/tree/master) | SPI | ILI9342 | 320x240 | I2C | GT911 |
|
||||
<img src="https://raw.githubusercontent.com/espressif/esp-box/c4c954888e11250423f083df0067d99e22d59fbe/docs/_static/esp32_s3_box_3.png" width="150"> |[ESP32-S3-Box-3(beta)](https://github.com/espressif/esp-box/tree/c4c954888e11250423f083df0067d99e22d59fbe) | SPI | ILI9342 | 320x240 | I2C | TT21100 |
|
||||
| <img src="https://github.com/espressif/esp-box/raw/master/docs/_static/esp32_s3_box_lite.png" width="150"> | [ESP32-S3-Box-Lite](https://github.com/espressif/esp-box/tree/master) | SPI | ST7789 | 320x240 | - | - |
|
||||
| <img src="https://github.com/espressif/esp-who/raw/master/docs/_static/get-started/ESP32-S3-EYE-isometric.png" width="100"> | [ESP32-S3-EYE](https://github.com/espressif/esp-who/blob/master/docs/en/get-started/ESP32-S3-EYE_Getting_Started_Guide.md) | SPI | ST7789 | 240x240 | - | - |
|
||||
| <img src="https://docs.espressif.com/projects/esp-adf/en/latest/_images/esp32-s3-korvo-2-v3.0-overview.png" width="150"> | [ESP32-S3-Korvo-2](https://docs.espressif.com/projects/esp-adf/en/latest/design-guide/dev-boards/user-guide-esp32-s3-korvo-2.html) | SPI | ILI9342 | 320x240 | I2C | TT21100 |
|
||||
| <img src="https://docs.espressif.com/projects/esp-dev-kits/en/latest/_images/ESP32-S3-LCD-EV-Board_480x480.png" width="150"> | [ESP32-S3-LCD-EV-Board](https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32s3/esp32-s3-lcd-ev-board/index.html) | 3-wire SPI + RGB | GC9503 | 480x480 | I2C | FT5x06 |
|
||||
| <img src="https://docs.espressif.com/projects/esp-dev-kits/en/latest/_images/ESP32-S3-LCD-EV-Board_800x480.png" width="150"> | [ESP32-S3-LCD-EV-Board-2](https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32s3/esp32-s3-lcd-ev-board/index.html) | RGB | ST7262E43 | 800x480 | I2C | GT1151 |
|
||||
| <img src="https://docs.espressif.com/projects/esp-dev-kits/en/latest/_images/pic_product_esp32_s3_otg.png" width="150"> | [ESP32-S3-USB-OTG](https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32s3/esp32-s3-usb-otg/index.html) | SPI | ST7789 | 240x240 | - | - |
|
||||
|
||||
### [M5Stack](https://m5stack.com/)
|
||||
|
||||
| **Picture** | **Name** | **LCD Bus** | **LCD Controller** | **LCD resolution** | **Touch Bus** | **Touch Controller** |
|
||||
|--------- |------------------ |--------- |---------------- |---------------- |----------- |------------------ |
|
||||
| <img src="https://static-cdn.m5stack.com/resource/docs/products/core/core2/core2_01.webp" width="150"> | [M5STACK_M5CORE2](https://docs.m5stack.com/en/core/core2) | SPI | ILI9342C | 320x240 | I2C | FT6336U |
|
||||
| <img src="https://static-cdn.m5stack.com/resource/docs/products/core/M5Dial/img-2afd549e-8af8-47b4-823a-e90e063a0139.webp" width="150"> | [M5STACK_M5DIAL](https://docs.m5stack.com/en/core/M5Dial) | SPI | GC9A01 | 240x240 | I2C | FT5x06 |
|
||||
| <img src="https://static-cdn.m5stack.com/resource/docs/products/core/CoreS3/img-96063e2a-637a-4d11-ac47-1ce4f1cdfd3e.webp" width="150"> | [M5STACK_M5CORES3](https://docs.m5stack.com/en/core/CoreS3) | SPI | ILI9342C | 320x240 | I2C | FT6336U |
|
||||
|
||||
|
||||
### [Shenzhen Jingcai Intelligent](https://www.displaysmodule.com/)
|
||||
|
||||
| **Picture** | **Name** | **LCD Bus** | **LCD Controller** | **LCD resolution** | **Touch Bus** | **Touch Controller** |
|
||||
| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------: | :--------------: | :--------------: | :----------------: | :-----------: | :------------------: |
|
||||
| [<img src="https://www.displaysmodule.com/photo/ps162171631-experience_the_power_of_the_esp32_display_module_sku_esp32_4848s040c_i_y_3.jpg" width="150">](https://www.displaysmodule.com/sale-41828962-experience-the-power-of-the-esp32-display-module-sku-esp32-4848s040c-i-y-3.html) | [ESP32-4848S040C_I_Y_3](http://pan.jczn1688.com/directlink/1/ESP32%20module/4.0inch_ESP32-4848S040.zip) | 3-wire SPI + RGB | ST7701 | 480x480 | I2C | GT911 |
|
||||
|
||||
## Recommended Configurations in the Arduino IDE
|
||||
|
||||
Below are recommended configurations for developing GUI applications on different development boards. These settings can be adjusted according to specific requirements, and users can navigate to the `Tools` menu in the Arduino IDE to configure the following settings.
|
||||
|
||||
| Supported Boards | Selected Board | PSRAM | Flash Mode | Flash Size | USB CDC On Boot | Partition Scheme |
|
||||
| :---------------------: | :----------------: | :------: | :--------: | :--------: | :-------------: | :---------------------: |
|
||||
| ESP32-C3-LCDkit | ESP32C3 Dev Module | Disabled | QIO | 4MB (32Mb) | Enabled | Default 4MB with spiffs |
|
||||
| ESP32-S3-Box | ESP32-S3-Box | - | - | - | - | 16M Flash (3MB) |
|
||||
| ESP32-S3-Box-3 | ESP32S3 Dev Module | OPI | QIO 80MHz | 16MB | Enabled | 16M Flash (3MB) |
|
||||
| ESP32-S3-Box-3(beta) | ESP32S3 Dev Module | OPI | QIO 80MHz | 16MB | Enabled | 16M Flash (3MB) |
|
||||
| ESP32-S3-Box-Lite | ESP32-S3-Box | - | - | - | - | 16M Flash (3MB) |
|
||||
| ESP32-S3-EYE | ESP32S3 Dev Module | OPI | QIO 80MHz | 8MB | Enabled | 8M with spiffs |
|
||||
| ESP32-S3-Korvo-2 | ESP32S3 Dev Module | OPI | QIO 80MHz | 16MB | Disabled | 16M Flash (3MB) |
|
||||
| ESP32-S3-LCD-EV-Board | ESP32S3 Dev Module | OPI | QIO 80MHz | 16MB | **See Note 1** | 16M Flash (3MB) |
|
||||
| ESP32-S3-LCD-EV-Board-2 | ESP32S3 Dev Module | OPI | QIO 80MHz | 16MB | **See Note 1** | 16M Flash (3MB) |
|
||||
| ESP32-S3-USB-OTG | ESP32-S3-USB-OTG | - | - | - | - | 8M with spiffs |
|
||||
| M5STACK-M5CORE2 | M5Stack-Core2 | Enabled | - | - | - | Default |
|
||||
| M5STACK-M5DIAL | ESP32S3 Dev Module | OPI | QIO 80MHz | 8MB | Disabled | Default |
|
||||
| M5STACK-M5CORES3 | ESP32S3 Dev Module | OPI | QIO 80MHz | 16MB | Enabled | Default 4MB with spiffs |
|
||||
| ESP32-4848S040C_I_Y_3 | ESP32S3 Dev Module | OPI | QIO 80MHz | 16MB | Disabled | 16M Flash (3MB) |
|
||||
|
||||
**Notes:**
|
||||
|
||||
1. Enable or disable `USB CDC On Boot` based on the type of port used:
|
||||
|
||||
* Disable this configuration if using **UART** port; enable it if using **USB** port.
|
||||
* If this configuration differs from previous flashing, first enable `Erase All Flash Before Sketch Upload`, then it can be disabled after flashing.
|
||||
* If this configuration does not match the actual port type, it will prevent the development board from printing serial logs correctly.
|
||||
|
||||
2. To view more output logs, set `Core Debug Level` to `Info` or a lower level.
|
||||
3. If the predefined partition schemes provided by ESP32 do not meet the requirements, users can also select `Custom` in the "Partition Scheme" and create a custom partition table file `Custom.csv` in the `hardware/esp32/3.x.x/tools/partitions` directory under the [arduino-esp32 installation directory](#where-are-the-installation-directory-for-arduino-esp32-and-the-sdk-located). For detailed information on partition tables, please refer to the [ESP-IDF documentation](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/partition-tables.html).
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// *INDENT-OFF*
|
||||
|
||||
// Check if multiple boards are enabled
|
||||
#if defined(BOARD_ESP32_C3_LCDKIT) + defined(BOARD_ESP32_S3_BOX) + defined(BOARD_ESP32_S3_BOX_3) + \
|
||||
defined(BOARD_ESP32_S3_BOX_3_BETA) + defined(BOARD_ESP32_S3_BOX_LITE) + defined(BOARD_ESP32_S3_EYE) + \
|
||||
defined(BOARD_ESP32_S3_KORVO_2) + defined(BOARD_ESP32_S3_LCD_EV_BOARD) + \
|
||||
defined(BOARD_ESP32_S3_LCD_EV_BOARD_V1_5) + defined(BOARD_ESP32_S3_LCD_EV_BOARD_2) + \
|
||||
defined(BOARD_ESP32_S3_LCD_EV_BOARD_2_V1_5) + defined(BOARD_ESP32_S3_USB_OTG) + \
|
||||
defined(BOARD_M5STACK_M5CORE2) + defined(BOARD_M5STACK_M5DIAL) + defined(BOARD_M5STACK_M5CORES3) + \
|
||||
defined(BOARD_ESP32_4848S040C_I_Y_3) \
|
||||
> 1
|
||||
#error "Multiple boards enabled! Please check file `ESP_Panel_Board_Supported.h` and make sure only one board is enabled."
|
||||
#endif
|
||||
|
||||
// Include board specific header file
|
||||
/* Espressif */
|
||||
#if defined(BOARD_ESP32_C3_LCDKIT) || CONFIG_BOARD_ESP32_C3_LCDKIT
|
||||
#include "board/espressif/ESP32_C3_LCDKIT.h"
|
||||
#elif defined(BOARD_ESP32_S3_BOX) || CONFIG_BOARD_ESP32_S3_BOX
|
||||
#include "board/espressif/ESP32_S3_BOX.h"
|
||||
#elif defined(BOARD_ESP32_S3_BOX_3) || CONFIG_BOARD_ESP32_S3_BOX_3
|
||||
#include "board/espressif/ESP32_S3_BOX_3.h"
|
||||
#elif defined(BOARD_ESP32_S3_BOX_3_BETA) || CONFIG_BOARD_ESP32_S3_BOX_3_BETA
|
||||
#include "board/espressif/ESP32_S3_BOX_3_BETA.h"
|
||||
#elif defined(BOARD_ESP32_S3_BOX_LITE) || CONFIG_BOARD_ESP32_S3_BOX_LITE
|
||||
#include "board/espressif/ESP32_S3_BOX_LITE.h"
|
||||
#elif defined(BOARD_ESP32_S3_EYE) || CONFIG_BOARD_ESP32_S3_EYE
|
||||
#include "board/espressif/ESP32_S3_EYE.h"
|
||||
#elif defined(BOARD_ESP32_S3_KORVO_2) || CONFIG_BOARD_ESP32_S3_KORVO_2
|
||||
#include "board/espressif/ESP32_S3_KORVO_2.h"
|
||||
#elif defined(BOARD_ESP32_S3_LCD_EV_BOARD) || CONFIG_BOARD_ESP32_S3_LCD_EV_BOARD
|
||||
#include "board/espressif/ESP32_S3_LCD_EV_BOARD.h"
|
||||
#elif defined(BOARD_ESP32_S3_LCD_EV_BOARD_V1_5) || CONFIG_BOARD_ESP32_S3_LCD_EV_BOARD_V1_5
|
||||
#include "board/espressif/ESP32_S3_LCD_EV_BOARD_V1_5.h"
|
||||
#elif defined(BOARD_ESP32_S3_LCD_EV_BOARD_2) || CONFIG_BOARD_ESP32_S3_LCD_EV_BOARD_2
|
||||
#include "board/espressif/ESP32_S3_LCD_EV_BOARD_2.h"
|
||||
#elif defined(BOARD_ESP32_S3_LCD_EV_BOARD_2_V1_5) || CONFIG_BOARD_ESP32_S3_LCD_EV_BOARD_2_V1_5
|
||||
#include "board/espressif/ESP32_S3_LCD_EV_BOARD_2_V1_5.h"
|
||||
#elif defined(BOARD_ESP32_S3_USB_OTG) || CONFIG_BOARD_ESP32_S3_USB_OTG
|
||||
#include "board/espressif/ESP32_S3_USB_OTG.h"
|
||||
/* M5Stack */
|
||||
#elif defined(BOARD_M5STACK_M5CORE2) || CONFIG_BOARD_M5STACK_M5CORE2
|
||||
#include "board/m5stack/M5CORE2.h"
|
||||
#elif defined(BOARD_M5STACK_M5DIAL) || CONFIG_BOARD_M5STACK_M5DIAL
|
||||
#include "board/m5stack/M5DIAL.h"
|
||||
#elif defined(BOARD_M5STACK_M5CORES3) || CONFIG_BOARD_M5STACK_M5CORES3
|
||||
#include "board/m5stack/M5CORES3.h"
|
||||
/* Jingcai */
|
||||
#elif defined(BOARD_ESP32_4848S040C_I_Y_3) || CONFIG_BOARD_ESP32_4848S040C_I_Y_3
|
||||
#include "board/jingcai/ESP32_4848S040C_I_Y_3.h"
|
||||
#else
|
||||
#error "Unkonw board selected! Please check file `ESP_Panel_Board_Supported.h` and make sure only one board is enabled."
|
||||
#endif
|
||||
|
||||
// *INDENT-OFF*
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// *INDENT-OFF*
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// Please update the following macros to configure the LCD panel /////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 1 when using an LCD panel */
|
||||
#define ESP_PANEL_USE_LCD (1) // 0/1
|
||||
|
||||
#if ESP_PANEL_USE_LCD
|
||||
/**
|
||||
* LCD Controller Name.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_NAME GC9A01
|
||||
|
||||
/* LCD resolution in pixels */
|
||||
#define ESP_PANEL_LCD_WIDTH (240)
|
||||
#define ESP_PANEL_LCD_HEIGHT (240)
|
||||
|
||||
/* LCD Bus Settings */
|
||||
/**
|
||||
* If set to 1, the bus will skip to initialize the corresponding host. Users need to initialize the host in advance.
|
||||
* It is useful if other devices use the same host. Please ensure that the host is initialized only once.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BUS_SKIP_INIT_HOST (0) // 0/1
|
||||
/**
|
||||
* LCD Bus Type.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BUS_TYPE (ESP_PANEL_BUS_TYPE_SPI)
|
||||
/**
|
||||
* LCD Bus Parameters.
|
||||
*
|
||||
* Please refer to https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/peripherals/lcd.html and
|
||||
* https://docs.espressif.com/projects/esp-iot-solution/en/latest/display/lcd/index.html for more details.
|
||||
*
|
||||
*/
|
||||
#if ESP_PANEL_LCD_BUS_TYPE == ESP_PANEL_BUS_TYPE_SPI
|
||||
|
||||
#define ESP_PANEL_LCD_BUS_HOST_ID (1) // Typically set to 1
|
||||
#define ESP_PANEL_LCD_SPI_IO_CS (7)
|
||||
#if !ESP_PANEL_LCD_BUS_SKIP_INIT_HOST
|
||||
#define ESP_PANEL_LCD_SPI_IO_SCK (1)
|
||||
#define ESP_PANEL_LCD_SPI_IO_MOSI (0)
|
||||
#define ESP_PANEL_LCD_SPI_IO_MISO (-1) // -1 if not used
|
||||
#endif
|
||||
#define ESP_PANEL_LCD_SPI_IO_DC (2)
|
||||
#define ESP_PANEL_LCD_SPI_MODE (0) // 0/1/2/3, typically set to 0
|
||||
#define ESP_PANEL_LCD_SPI_CLK_HZ (40 * 1000 * 1000)
|
||||
// Should be an integer divisor of 80M, typically set to 40M
|
||||
#define ESP_PANEL_LCD_SPI_TRANS_QUEUE_SZ (10) // Typically set to 10
|
||||
#define ESP_PANEL_LCD_SPI_CMD_BITS (8) // Typically set to 8
|
||||
#define ESP_PANEL_LCD_SPI_PARAM_BITS (8) // Typically set to 8
|
||||
|
||||
#endif /* ESP_PANEL_LCD_BUS_TYPE */
|
||||
|
||||
/**
|
||||
* LCD Venbdor Initialization Commands.
|
||||
*
|
||||
* Vendor specific initialization can be different between manufacturers, should consult the LCD supplier for
|
||||
* initialization sequence code. Please uncomment and change the following macro definitions. Otherwise, the LCD driver
|
||||
* will use the default initialization sequence code.
|
||||
*
|
||||
* There are two formats for the sequence code:
|
||||
* 1. Raw data: {command, (uint8_t []){ data0, data1, ... }, data_size, delay_ms}
|
||||
* 2. Formater: ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(delay_ms, command, { data0, data1, ... }) and
|
||||
* ESP_PANEL_LCD_CMD_WITH_NONE_PARAM(delay_ms, command)
|
||||
*/
|
||||
// #define ESP_PANEL_LCD_VENDOR_INIT_CMD \
|
||||
// { \
|
||||
// {0xFF, (uint8_t []){0x77, 0x01, 0x00, 0x00, 0x10}, 5, 0}, \
|
||||
// {0xC0, (uint8_t []){0x3B, 0x00}, 2, 0}, \
|
||||
// {0xC1, (uint8_t []){0x0D, 0x02}, 2, 0}, \
|
||||
// {0x29, (uint8_t []){0x00}, 0, 120}, \
|
||||
// or \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xFF, {0x77, 0x01, 0x00, 0x00, 0x10}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC0, {0x3B, 0x00}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC1, {0x0D, 0x02}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_NONE_PARAM(120, 0x29), \
|
||||
// }
|
||||
|
||||
/* LCD Color Settings */
|
||||
/* LCD color depth in bits */
|
||||
#define ESP_PANEL_LCD_COLOR_BITS (16) // 8/16/18/24
|
||||
/*
|
||||
* LCD RGB Element Order. Choose one of the following:
|
||||
* - 0: RGB
|
||||
* - 1: BGR
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BGR_ORDER (1) // 0/1
|
||||
#define ESP_PANEL_LCD_INEVRT_COLOR (1) // 0/1
|
||||
|
||||
/* LCD Transformation Flags */
|
||||
#define ESP_PANEL_LCD_SWAP_XY (0) // 0/1
|
||||
#define ESP_PANEL_LCD_MIRROR_X (1) // 0/1
|
||||
#define ESP_PANEL_LCD_MIRROR_Y (0) // 0/1
|
||||
|
||||
/* LCD Other Settings */
|
||||
/* IO num of RESET pin, set to -1 if not use */
|
||||
#define ESP_PANEL_LCD_IO_RST (-1)
|
||||
#define ESP_PANEL_LCD_RST_LEVEL (0) // 0: low level, 1: high level
|
||||
|
||||
#endif /* ESP_PANEL_USE_LCD */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// Please update the following macros to configure the touch panel ///////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 1 when using an touch panel */
|
||||
#define ESP_PANEL_USE_TOUCH (0) // 0/1
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please update the following macros to configure the backlight ////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define ESP_PANEL_USE_BACKLIGHT (1) // 0/1
|
||||
#if ESP_PANEL_USE_BACKLIGHT
|
||||
/* IO num of backlight pin */
|
||||
#define ESP_PANEL_BACKLIGHT_IO (5)
|
||||
#define ESP_PANEL_BACKLIGHT_ON_LEVEL (1) // 0: low level, 1: high level
|
||||
|
||||
/* Set to 1 if you want to turn off the backlight after initializing the panel; otherwise, set it to turn on */
|
||||
#define ESP_PANEL_BACKLIGHT_IDLE_OFF (0) // 0: on, 1: off
|
||||
|
||||
/* Set to 1 if use PWM for brightness control */
|
||||
#define ESP_PANEL_LCD_BL_USE_PWM (1) // 0/1
|
||||
#endif /* ESP_PANEL_USE_BACKLIGHT */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please update the following macros to configure the IO expander //////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 0 if not using IO Expander */
|
||||
#define ESP_PANEL_USE_EXPANDER (0) // 0/1
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please utilize the following macros to execute any additional code if required. //////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// #define ESP_PANEL_BEGIN_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_EXPANDER_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_EXPANDER_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_LCD_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_LCD_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_TOUCH_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_TOUCH_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_BACKLIGHT_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_BACKLIGHT_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_END_FUNCTION( panel )
|
||||
|
||||
// *INDENT-OFF*
|
||||
+203
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// *INDENT-OFF*
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// Please update the following macros to configure the LCD panel /////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 1 when using an LCD panel */
|
||||
#define ESP_PANEL_USE_LCD (1) // 0/1
|
||||
|
||||
#if ESP_PANEL_USE_LCD
|
||||
/**
|
||||
* LCD Controller Name.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_NAME ST7789
|
||||
|
||||
/* LCD resolution in pixels */
|
||||
#define ESP_PANEL_LCD_WIDTH (320)
|
||||
#define ESP_PANEL_LCD_HEIGHT (240)
|
||||
|
||||
/* LCD Bus Settings */
|
||||
/**
|
||||
* If set to 1, the bus will skip to initialize the corresponding host. Users need to initialize the host in advance.
|
||||
* It is useful if other devices use the same host. Please ensure that the host is initialized only once.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BUS_SKIP_INIT_HOST (0) // 0/1
|
||||
/**
|
||||
* LCD Bus Type.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BUS_TYPE (ESP_PANEL_BUS_TYPE_SPI)
|
||||
/**
|
||||
* LCD Bus Parameters.
|
||||
*
|
||||
* Please refer to https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/peripherals/lcd.html and
|
||||
* https://docs.espressif.com/projects/esp-iot-solution/en/latest/display/lcd/index.html for more details.
|
||||
*
|
||||
*/
|
||||
#if ESP_PANEL_LCD_BUS_TYPE == ESP_PANEL_BUS_TYPE_SPI
|
||||
|
||||
#define ESP_PANEL_LCD_BUS_HOST_ID (1) // Typically set to 1
|
||||
#define ESP_PANEL_LCD_SPI_IO_CS (5)
|
||||
#if !ESP_PANEL_LCD_BUS_SKIP_INIT_HOST
|
||||
#define ESP_PANEL_LCD_SPI_IO_SCK (7)
|
||||
#define ESP_PANEL_LCD_SPI_IO_MOSI (6)
|
||||
#define ESP_PANEL_LCD_SPI_IO_MISO (-1) // -1 if not used
|
||||
#endif
|
||||
#define ESP_PANEL_LCD_SPI_IO_DC (4)
|
||||
#define ESP_PANEL_LCD_SPI_MODE (0) // 0/1/2/3, typically set to 0
|
||||
#define ESP_PANEL_LCD_SPI_CLK_HZ (40 * 1000 * 1000)
|
||||
// Should be an integer divisor of 80M, typically set to 40M
|
||||
#define ESP_PANEL_LCD_SPI_TRANS_QUEUE_SZ (10) // Typically set to 10
|
||||
#define ESP_PANEL_LCD_SPI_CMD_BITS (8) // Typically set to 8
|
||||
#define ESP_PANEL_LCD_SPI_PARAM_BITS (8) // Typically set to 8
|
||||
|
||||
#endif /* ESP_PANEL_LCD_BUS_TYPE */
|
||||
|
||||
/**
|
||||
* LCD Venbdor Initialization Commands.
|
||||
*
|
||||
* Vendor specific initialization can be different between manufacturers, should consult the LCD supplier for
|
||||
* initialization sequence code. Please uncomment and change the following macro definitions. Otherwise, the LCD driver
|
||||
* will use the default initialization sequence code.
|
||||
*
|
||||
* There are two formats for the sequence code:
|
||||
* 1. Raw data: {command, (uint8_t []){ data0, data1, ... }, data_size, delay_ms}
|
||||
* 2. Formater: ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(delay_ms, command, { data0, data1, ... }) and
|
||||
* ESP_PANEL_LCD_CMD_WITH_NONE_PARAM(delay_ms, command)
|
||||
*/
|
||||
// #define ESP_PANEL_LCD_VENDOR_INIT_CMD \
|
||||
// { \
|
||||
// {0xFF, (uint8_t []){0x77, 0x01, 0x00, 0x00, 0x10}, 5, 0}, \
|
||||
// {0xC0, (uint8_t []){0x3B, 0x00}, 2, 0}, \
|
||||
// {0xC1, (uint8_t []){0x0D, 0x02}, 2, 0}, \
|
||||
// {0x29, (uint8_t []){0x00}, 0, 120}, \
|
||||
// or \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xFF, {0x77, 0x01, 0x00, 0x00, 0x10}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC0, {0x3B, 0x00}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC1, {0x0D, 0x02}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_NONE_PARAM(120, 0x29), \
|
||||
// }
|
||||
|
||||
/* LCD Color Settings */
|
||||
/* LCD color depth in bits */
|
||||
#define ESP_PANEL_LCD_COLOR_BITS (16) // 8/16/18/24
|
||||
/*
|
||||
* LCD RGB Element Order. Choose one of the following:
|
||||
* - 0: RGB
|
||||
* - 1: BGR
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BGR_ORDER (1) // 0/1
|
||||
#define ESP_PANEL_LCD_INEVRT_COLOR (0) // 0/1
|
||||
|
||||
/* LCD Transformation Flags */
|
||||
#define ESP_PANEL_LCD_SWAP_XY (0) // 0/1
|
||||
#define ESP_PANEL_LCD_MIRROR_X (1) // 0/1
|
||||
#define ESP_PANEL_LCD_MIRROR_Y (1) // 0/1
|
||||
|
||||
/* LCD Other Settings */
|
||||
/* IO num of RESET pin, set to -1 if not use */
|
||||
#define ESP_PANEL_LCD_IO_RST (48)
|
||||
#define ESP_PANEL_LCD_RST_LEVEL (0) // 0: low level, 1: high level
|
||||
|
||||
#endif /* ESP_PANEL_USE_LCD */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// Please update the following macros to configure the touch panel ///////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 1 when using an touch panel */
|
||||
#define ESP_PANEL_USE_TOUCH (1) // 0/1
|
||||
#if ESP_PANEL_USE_TOUCH
|
||||
/**
|
||||
* Touch controller name.
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_NAME TT21100
|
||||
|
||||
/* Touch resolution in pixels */
|
||||
#define ESP_PANEL_TOUCH_H_RES (ESP_PANEL_LCD_WIDTH) // Typically set to the same value as the width of LCD
|
||||
#define ESP_PANEL_TOUCH_V_RES (ESP_PANEL_LCD_HEIGHT) // Typically set to the same value as the height of LCD
|
||||
|
||||
/* Touch Panel Bus Settings */
|
||||
/**
|
||||
* If set to 1, the bus will skip to initialize the corresponding host. Users need to initialize the host in advance.
|
||||
* It is useful if other devices use the same host. Please ensure that the host is initialized only once.
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_BUS_SKIP_INIT_HOST (0) // 0/1
|
||||
/**
|
||||
* Touch panel bus type.
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_BUS_TYPE (ESP_PANEL_BUS_TYPE_I2C)
|
||||
/* Touch panel bus parameters */
|
||||
#if ESP_PANEL_TOUCH_BUS_TYPE == ESP_PANEL_BUS_TYPE_I2C
|
||||
|
||||
#define ESP_PANEL_TOUCH_BUS_HOST_ID (0) // Typically set to 0
|
||||
#define ESP_PANEL_TOUCH_I2C_ADDRESS (0) // Typically set to 0 to use default address
|
||||
#if !ESP_PANEL_TOUCH_BUS_SKIP_INIT_HOST
|
||||
#define ESP_PANEL_TOUCH_I2C_CLK_HZ (400 * 1000)
|
||||
// Typically set to 400K
|
||||
#define ESP_PANEL_TOUCH_I2C_SCL_PULLUP (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_I2C_SDA_PULLUP (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_I2C_IO_SCL (18)
|
||||
#define ESP_PANEL_TOUCH_I2C_IO_SDA (8)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* Touch Transformation Flags */
|
||||
#define ESP_PANEL_TOUCH_SWAP_XY (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_MIRROR_X (1) // 0/1
|
||||
#define ESP_PANEL_TOUCH_MIRROR_Y (0) // 0/1
|
||||
|
||||
/* Touch Other Settings */
|
||||
/* IO num of RESET pin, set to -1 if not use */
|
||||
#define ESP_PANEL_TOUCH_IO_RST (-1)
|
||||
#define ESP_PANEL_TOUCH_RST_LEVEL (0) // 0: low level, 1: high level
|
||||
/* IO num of INT pin, set to -1 if not use */
|
||||
#define ESP_PANEL_TOUCH_IO_INT (3)
|
||||
#define ESP_PANEL_TOUCH_INT_LEVEL (0) // 0: low level, 1: high level
|
||||
|
||||
#endif /* ESP_PANEL_USE_TOUCH */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please update the following macros to configure the backlight ////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define ESP_PANEL_USE_BACKLIGHT (1) // 0/1
|
||||
#if ESP_PANEL_USE_BACKLIGHT
|
||||
/* IO num of backlight pin */
|
||||
#define ESP_PANEL_BACKLIGHT_IO (45)
|
||||
#define ESP_PANEL_BACKLIGHT_ON_LEVEL (1) // 0: low level, 1: high level
|
||||
|
||||
/* Set to 1 if you want to turn off the backlight after initializing the panel; otherwise, set it to turn on */
|
||||
#define ESP_PANEL_BACKLIGHT_IDLE_OFF (0) // 0: on, 1: off
|
||||
|
||||
/* Set to 1 if use PWM for brightness control */
|
||||
#define ESP_PANEL_LCD_BL_USE_PWM (1) // 0/1
|
||||
#endif /* ESP_PANEL_USE_BACKLIGHT */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please update the following macros to configure the IO expander //////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 0 if not using IO Expander */
|
||||
#define ESP_PANEL_USE_EXPANDER (0) // 0/1
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please utilize the following macros to execute any additional code if required. //////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// #define ESP_PANEL_BEGIN_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_EXPANDER_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_EXPANDER_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_LCD_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_LCD_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_TOUCH_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_TOUCH_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_BACKLIGHT_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_BACKLIGHT_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_END_FUNCTION( panel )
|
||||
|
||||
// *INDENT-OFF*
|
||||
+211
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// *INDENT-OFF*
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// Please update the following macros to configure the LCD panel /////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 1 when using an LCD panel */
|
||||
#define ESP_PANEL_USE_LCD (1) // 0/1
|
||||
|
||||
#if ESP_PANEL_USE_LCD
|
||||
/**
|
||||
* LCD Controller Name.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_NAME ILI9341
|
||||
|
||||
/* LCD resolution in pixels */
|
||||
#define ESP_PANEL_LCD_WIDTH (320)
|
||||
#define ESP_PANEL_LCD_HEIGHT (240)
|
||||
|
||||
/* LCD Bus Settings */
|
||||
/**
|
||||
* If set to 1, the bus will skip to initialize the corresponding host. Users need to initialize the host in advance.
|
||||
* It is useful if other devices use the same host. Please ensure that the host is initialized only once.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BUS_SKIP_INIT_HOST (0) // 0/1
|
||||
/**
|
||||
* LCD Bus Type.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BUS_TYPE (ESP_PANEL_BUS_TYPE_SPI)
|
||||
/**
|
||||
* LCD Bus Parameters.
|
||||
*
|
||||
* Please refer to https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/peripherals/lcd.html and
|
||||
* https://docs.espressif.com/projects/esp-iot-solution/en/latest/display/lcd/index.html for more details.
|
||||
*
|
||||
*/
|
||||
#if ESP_PANEL_LCD_BUS_TYPE == ESP_PANEL_BUS_TYPE_SPI
|
||||
|
||||
#define ESP_PANEL_LCD_BUS_HOST_ID (1) // Typically set to 1
|
||||
#define ESP_PANEL_LCD_SPI_IO_CS (5)
|
||||
#if !ESP_PANEL_LCD_BUS_SKIP_INIT_HOST
|
||||
#define ESP_PANEL_LCD_SPI_IO_SCK (7)
|
||||
#define ESP_PANEL_LCD_SPI_IO_MOSI (6)
|
||||
#define ESP_PANEL_LCD_SPI_IO_MISO (-1) // -1 if not used
|
||||
#endif
|
||||
#define ESP_PANEL_LCD_SPI_IO_DC (4)
|
||||
#define ESP_PANEL_LCD_SPI_MODE (0) // 0/1/2/3, typically set to 0
|
||||
#define ESP_PANEL_LCD_SPI_CLK_HZ (40 * 1000 * 1000)
|
||||
// Should be an integer divisor of 80M, typically set to 40M
|
||||
#define ESP_PANEL_LCD_SPI_TRANS_QUEUE_SZ (10) // Typically set to 10
|
||||
#define ESP_PANEL_LCD_SPI_CMD_BITS (8) // Typically set to 8
|
||||
#define ESP_PANEL_LCD_SPI_PARAM_BITS (8) // Typically set to 8
|
||||
|
||||
#endif /* ESP_PANEL_LCD_BUS_TYPE */
|
||||
|
||||
/**
|
||||
* LCD Venbdor Initialization Commands.
|
||||
*
|
||||
* Vendor specific initialization can be different between manufacturers, should consult the LCD supplier for
|
||||
* initialization sequence code. Please uncomment and change the following macro definitions. Otherwise, the LCD driver
|
||||
* will use the default initialization sequence code.
|
||||
*
|
||||
* There are two formats for the sequence code:
|
||||
* 1. Raw data: {command, (uint8_t []){ data0, data1, ... }, data_size, delay_ms}
|
||||
* 2. Formater: ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(delay_ms, command, { data0, data1, ... })
|
||||
* ESP_PANEL_LCD_CMD_WITH_NONE_PARAM(delay_ms, command)
|
||||
*/
|
||||
#define ESP_PANEL_LCD_VENDOR_INIT_CMD() \
|
||||
{ \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC8, {0xFF, 0x93, 0x42}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC0, {0x0E, 0x0E}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC5, {0xD0}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC1, {0x02}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xB4, {0x02}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xE0, {0x00, 0x03, 0x08, 0x06, 0x13, 0x09, 0x39, 0x39, 0x48, 0x02, 0x0a, 0x08, \
|
||||
0x17, 0x17, 0x0F}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xE1, {0x00, 0x28, 0x29, 0x01, 0x0d, 0x03, 0x3f, 0x33, 0x52, 0x04, 0x0f, 0x0e, \
|
||||
0x37, 0x38, 0x0F}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xB1, {00, 0x1B}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xB7, {0x06}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_NONE_PARAM(100, 0x11), \
|
||||
}
|
||||
|
||||
/* LCD Color Settings */
|
||||
/* LCD color depth in bits */
|
||||
#define ESP_PANEL_LCD_COLOR_BITS (16) // 8/16/18/24
|
||||
/*
|
||||
* LCD RGB Element Order. Choose one of the following:
|
||||
* - 0: RGB
|
||||
* - 1: BGR
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BGR_ORDER (1) // 0/1
|
||||
#define ESP_PANEL_LCD_INEVRT_COLOR (0) // 0/1
|
||||
|
||||
/* LCD Transformation Flags */
|
||||
#define ESP_PANEL_LCD_SWAP_XY (0) // 0/1
|
||||
#define ESP_PANEL_LCD_MIRROR_X (1) // 0/1
|
||||
#define ESP_PANEL_LCD_MIRROR_Y (1) // 0/1
|
||||
|
||||
/* LCD Other Settings */
|
||||
/* IO num of RESET pin, set to -1 if not use */
|
||||
#define ESP_PANEL_LCD_IO_RST (48)
|
||||
#define ESP_PANEL_LCD_RST_LEVEL (1) // 0: low level, 1: high level
|
||||
|
||||
#endif /* ESP_PANEL_USE_LCD */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// Please update the following macros to configure the touch panel ///////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 1 when using an touch panel */
|
||||
#define ESP_PANEL_USE_TOUCH (1) // 0/1
|
||||
#if ESP_PANEL_USE_TOUCH
|
||||
/**
|
||||
* Touch controller name.
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_NAME GT911
|
||||
|
||||
/* Touch resolution in pixels */
|
||||
#define ESP_PANEL_TOUCH_H_RES (ESP_PANEL_LCD_WIDTH) // Typically set to the same value as the width of LCD
|
||||
#define ESP_PANEL_TOUCH_V_RES (ESP_PANEL_LCD_HEIGHT) // Typically set to the same value as the height of LCD
|
||||
|
||||
/* Touch Panel Bus Settings */
|
||||
/**
|
||||
* If set to 1, the bus will skip to initialize the corresponding host. Users need to initialize the host in advance.
|
||||
* It is useful if other devices use the same host. Please ensure that the host is initialized only once.
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_BUS_SKIP_INIT_HOST (0) // 0/1
|
||||
/**
|
||||
* Touch panel bus type.
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_BUS_TYPE (ESP_PANEL_BUS_TYPE_I2C)
|
||||
/* Touch panel bus parameters */
|
||||
#if ESP_PANEL_TOUCH_BUS_TYPE == ESP_PANEL_BUS_TYPE_I2C
|
||||
|
||||
#define ESP_PANEL_TOUCH_BUS_HOST_ID (0) // Typically set to 0
|
||||
#define ESP_PANEL_TOUCH_I2C_ADDRESS (0) // Typically set to 0 to use default address
|
||||
#if !ESP_PANEL_TOUCH_BUS_SKIP_INIT_HOST
|
||||
#define ESP_PANEL_TOUCH_I2C_CLK_HZ (400 * 1000)
|
||||
// Typically set to 400K
|
||||
#define ESP_PANEL_TOUCH_I2C_SCL_PULLUP (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_I2C_SDA_PULLUP (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_I2C_IO_SCL (18)
|
||||
#define ESP_PANEL_TOUCH_I2C_IO_SDA (8)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* Touch Transformation Flags */
|
||||
#define ESP_PANEL_TOUCH_SWAP_XY (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_MIRROR_X (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_MIRROR_Y (0) // 0/1
|
||||
|
||||
/* Touch Other Settings */
|
||||
/* IO num of RESET pin, set to -1 if not use */
|
||||
#define ESP_PANEL_TOUCH_IO_RST (-1)
|
||||
#define ESP_PANEL_TOUCH_RST_LEVEL (0) // 0: low level, 1: high level
|
||||
/* IO num of INT pin, set to -1 if not use */
|
||||
#define ESP_PANEL_TOUCH_IO_INT (3)
|
||||
#define ESP_PANEL_TOUCH_INT_LEVEL (0) // 0: low level, 1: high level
|
||||
|
||||
#endif /* ESP_PANEL_USE_TOUCH */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please update the following macros to configure the backlight ////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define ESP_PANEL_USE_BACKLIGHT (1) // 0/1
|
||||
#if ESP_PANEL_USE_BACKLIGHT
|
||||
/* IO num of backlight pin */
|
||||
#define ESP_PANEL_BACKLIGHT_IO (47)
|
||||
#define ESP_PANEL_BACKLIGHT_ON_LEVEL (1) // 0: low level, 1: high level
|
||||
|
||||
/* Set to 1 if you want to turn off the backlight after initializing the panel; otherwise, set it to turn on */
|
||||
#define ESP_PANEL_BACKLIGHT_IDLE_OFF (0) // 0: on, 1: off
|
||||
|
||||
/* Set to 1 if use PWM for brightness control */
|
||||
#define ESP_PANEL_LCD_BL_USE_PWM (1) // 0/1
|
||||
#endif /* ESP_PANEL_USE_BACKLIGHT */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please update the following macros to configure the IO expander //////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 0 if not using IO Expander */
|
||||
#define ESP_PANEL_USE_EXPANDER (0) // 0/1
|
||||
|
||||
// #define ESP_PANEL_BEGIN_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_EXPANDER_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_EXPANDER_END_FUNCTION( panel )
|
||||
|
||||
#define ESP_PANEL_BEGIN_LCD_START_FUNCTION( panel ) \
|
||||
{ \
|
||||
/* Maintain the touch INT signal in a low state during the reset process to set its I2C address to `0x5D` */ \
|
||||
gpio_set_direction((gpio_num_t)ESP_PANEL_TOUCH_IO_INT, GPIO_MODE_OUTPUT); \
|
||||
gpio_set_level((gpio_num_t)ESP_PANEL_TOUCH_IO_INT, 0); \
|
||||
vTaskDelay(pdMS_TO_TICKS(10)); \
|
||||
}
|
||||
|
||||
// #define ESP_PANEL_BEGIN_LCD_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_TOUCH_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_TOUCH_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_BACKLIGHT_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_BACKLIGHT_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_END_FUNCTION( panel )
|
||||
|
||||
// *INDENT-OFF*
|
||||
+203
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// *INDENT-OFF*
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// Please update the following macros to configure the LCD panel /////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 1 when using an LCD panel */
|
||||
#define ESP_PANEL_USE_LCD (1) // 0/1
|
||||
|
||||
#if ESP_PANEL_USE_LCD
|
||||
/**
|
||||
* LCD Controller Name.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_NAME ST7789
|
||||
|
||||
/* LCD resolution in pixels */
|
||||
#define ESP_PANEL_LCD_WIDTH (320)
|
||||
#define ESP_PANEL_LCD_HEIGHT (240)
|
||||
|
||||
/* LCD Bus Settings */
|
||||
/**
|
||||
* If set to 1, the bus will skip to initialize the corresponding host. Users need to initialize the host in advance.
|
||||
* It is useful if other devices use the same host. Please ensure that the host is initialized only once.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BUS_SKIP_INIT_HOST (0) // 0/1
|
||||
/**
|
||||
* LCD Bus Type.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BUS_TYPE (ESP_PANEL_BUS_TYPE_SPI)
|
||||
/**
|
||||
* LCD Bus Parameters.
|
||||
*
|
||||
* Please refer to https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/peripherals/lcd.html and
|
||||
* https://docs.espressif.com/projects/esp-iot-solution/en/latest/display/lcd/index.html for more details.
|
||||
*
|
||||
*/
|
||||
#if ESP_PANEL_LCD_BUS_TYPE == ESP_PANEL_BUS_TYPE_SPI
|
||||
|
||||
#define ESP_PANEL_LCD_BUS_HOST_ID (1) // Typically set to 1
|
||||
#define ESP_PANEL_LCD_SPI_IO_CS (5)
|
||||
#if !ESP_PANEL_LCD_BUS_SKIP_INIT_HOST
|
||||
#define ESP_PANEL_LCD_SPI_IO_SCK (7)
|
||||
#define ESP_PANEL_LCD_SPI_IO_MOSI (6)
|
||||
#define ESP_PANEL_LCD_SPI_IO_MISO (-1) // -1 if not used
|
||||
#endif
|
||||
#define ESP_PANEL_LCD_SPI_IO_DC (4)
|
||||
#define ESP_PANEL_LCD_SPI_MODE (0) // 0/1/2/3, typically set to 0
|
||||
#define ESP_PANEL_LCD_SPI_CLK_HZ (40 * 1000 * 1000)
|
||||
// Should be an integer divisor of 80M, typically set to 40M
|
||||
#define ESP_PANEL_LCD_SPI_TRANS_QUEUE_SZ (10) // Typically set to 10
|
||||
#define ESP_PANEL_LCD_SPI_CMD_BITS (8) // Typically set to 8
|
||||
#define ESP_PANEL_LCD_SPI_PARAM_BITS (8) // Typically set to 8
|
||||
|
||||
#endif /* ESP_PANEL_LCD_BUS_TYPE */
|
||||
|
||||
/**
|
||||
* LCD Venbdor Initialization Commands.
|
||||
*
|
||||
* Vendor specific initialization can be different between manufacturers, should consult the LCD supplier for
|
||||
* initialization sequence code. Please uncomment and change the following macro definitions. Otherwise, the LCD driver
|
||||
* will use the default initialization sequence code.
|
||||
*
|
||||
* There are two formats for the sequence code:
|
||||
* 1. Raw data: {command, (uint8_t []){ data0, data1, ... }, data_size, delay_ms}
|
||||
* 2. Formater: ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(delay_ms, command, { data0, data1, ... })
|
||||
* ESP_PANEL_LCD_CMD_WITH_NONE_PARAM(delay_ms, command)
|
||||
*/
|
||||
// #define ESP_PANEL_LCD_VENDOR_INIT_CMD \
|
||||
// { \
|
||||
// {0xFF, (uint8_t []){0x77, 0x01, 0x00, 0x00, 0x10}, 5, 0}, \
|
||||
// {0xC0, (uint8_t []){0x3B, 0x00}, 2, 0}, \
|
||||
// {0xC1, (uint8_t []){0x0D, 0x02}, 2, 0}, \
|
||||
// {0x29, (uint8_t []){0x00}, 0, 120}, \
|
||||
// or \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xFF, {0x77, 0x01, 0x00, 0x00, 0x10}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC0, {0x3B, 0x00}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC1, {0x0D, 0x02}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_NONE_PARAM(120, 0x29), \
|
||||
// }
|
||||
|
||||
/* LCD Color Settings */
|
||||
/* LCD color depth in bits */
|
||||
#define ESP_PANEL_LCD_COLOR_BITS (16) // 8/16/18/24
|
||||
/*
|
||||
* LCD RGB Element Order. Choose one of the following:
|
||||
* - 0: RGB
|
||||
* - 1: BGR
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BGR_ORDER (1) // 0/1
|
||||
#define ESP_PANEL_LCD_INEVRT_COLOR (0) // 0/1
|
||||
|
||||
/* LCD Transformation Flags */
|
||||
#define ESP_PANEL_LCD_SWAP_XY (0) // 0/1
|
||||
#define ESP_PANEL_LCD_MIRROR_X (1) // 0/1
|
||||
#define ESP_PANEL_LCD_MIRROR_Y (1) // 0/1
|
||||
|
||||
/* LCD Other Settings */
|
||||
/* IO num of RESET pin, set to -1 if not use */
|
||||
#define ESP_PANEL_LCD_IO_RST (48)
|
||||
#define ESP_PANEL_LCD_RST_LEVEL (1) // 0: low level, 1: high level
|
||||
|
||||
#endif /* ESP_PANEL_USE_LCD */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// Please update the following macros to configure the touch panel ///////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 1 when using an touch panel */
|
||||
#define ESP_PANEL_USE_TOUCH (1) // 0/1
|
||||
#if ESP_PANEL_USE_TOUCH
|
||||
/**
|
||||
* Touch controller name.
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_NAME TT21100
|
||||
|
||||
/* Touch resolution in pixels */
|
||||
#define ESP_PANEL_TOUCH_H_RES (ESP_PANEL_LCD_WIDTH) // Typically set to the same value as the width of LCD
|
||||
#define ESP_PANEL_TOUCH_V_RES (ESP_PANEL_LCD_HEIGHT) // Typically set to the same value as the height of LCD
|
||||
|
||||
/* Touch Panel Bus Settings */
|
||||
/**
|
||||
* If set to 1, the bus will skip to initialize the corresponding host. Users need to initialize the host in advance.
|
||||
* It is useful if other devices use the same host. Please ensure that the host is initialized only once.
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_BUS_SKIP_INIT_HOST (0) // 0/1
|
||||
/**
|
||||
* Touch panel bus type.
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_BUS_TYPE (ESP_PANEL_BUS_TYPE_I2C)
|
||||
/* Touch panel bus parameters */
|
||||
#if ESP_PANEL_TOUCH_BUS_TYPE == ESP_PANEL_BUS_TYPE_I2C
|
||||
|
||||
#define ESP_PANEL_TOUCH_BUS_HOST_ID (0) // Typically set to 0
|
||||
#define ESP_PANEL_TOUCH_I2C_ADDRESS (0) // Typically set to 0 to use default address
|
||||
#if !ESP_PANEL_TOUCH_BUS_SKIP_INIT_HOST
|
||||
#define ESP_PANEL_TOUCH_I2C_CLK_HZ (400 * 1000)
|
||||
// Typically set to 400K
|
||||
#define ESP_PANEL_TOUCH_I2C_SCL_PULLUP (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_I2C_SDA_PULLUP (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_I2C_IO_SCL (18)
|
||||
#define ESP_PANEL_TOUCH_I2C_IO_SDA (8)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* Touch Transformation Flags */
|
||||
#define ESP_PANEL_TOUCH_SWAP_XY (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_MIRROR_X (1) // 0/1
|
||||
#define ESP_PANEL_TOUCH_MIRROR_Y (0) // 0/1
|
||||
|
||||
/* Touch Other Settings */
|
||||
/* IO num of RESET pin, set to -1 if not use */
|
||||
#define ESP_PANEL_TOUCH_IO_RST (-1)
|
||||
#define ESP_PANEL_TOUCH_RST_LEVEL (0) // 0: low level, 1: high level
|
||||
/* IO num of INT pin, set to -1 if not use */
|
||||
#define ESP_PANEL_TOUCH_IO_INT (3)
|
||||
#define ESP_PANEL_TOUCH_INT_LEVEL (0) // 0: low level, 1: high level
|
||||
|
||||
#endif /* ESP_PANEL_USE_TOUCH */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please update the following macros to configure the backlight ////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define ESP_PANEL_USE_BACKLIGHT (1) // 0/1
|
||||
#if ESP_PANEL_USE_BACKLIGHT
|
||||
/* IO num of backlight pin */
|
||||
#define ESP_PANEL_BACKLIGHT_IO (47)
|
||||
#define ESP_PANEL_BACKLIGHT_ON_LEVEL (1) // 0: low level, 1: high level
|
||||
|
||||
/* Set to 1 if you want to turn off the backlight after initializing the panel; otherwise, set it to turn on */
|
||||
#define ESP_PANEL_BACKLIGHT_IDLE_OFF (0) // 0: on, 1: off
|
||||
|
||||
/* Set to 1 if use PWM for brightness control */
|
||||
#define ESP_PANEL_LCD_BL_USE_PWM (1) // 0/1
|
||||
#endif /* ESP_PANEL_USE_BACKLIGHT */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please update the following macros to configure the IO expander //////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 0 if not using IO Expander */
|
||||
#define ESP_PANEL_USE_EXPANDER (0) // 0/1
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please utilize the following macros to execute any additional code if required. //////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// #define ESP_PANEL_BEGIN_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_EXPANDER_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_EXPANDER_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_LCD_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_LCD_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_TOUCH_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_TOUCH_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_BACKLIGHT_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_BACKLIGHT_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_END_FUNCTION( panel )
|
||||
|
||||
// *INDENT-OFF*
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// *INDENT-OFF*
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// Please update the following macros to configure the LCD panel /////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 1 when using an LCD panel */
|
||||
#define ESP_PANEL_USE_LCD (1) // 0/1
|
||||
|
||||
#if ESP_PANEL_USE_LCD
|
||||
/**
|
||||
* LCD Controller Name.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_NAME ST7789
|
||||
|
||||
/* LCD resolution in pixels */
|
||||
#define ESP_PANEL_LCD_WIDTH (320)
|
||||
#define ESP_PANEL_LCD_HEIGHT (240)
|
||||
|
||||
/* LCD Bus Settings */
|
||||
/**
|
||||
* If set to 1, the bus will skip to initialize the corresponding host. Users need to initialize the host in advance.
|
||||
* It is useful if other devices use the same host. Please ensure that the host is initialized only once.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BUS_SKIP_INIT_HOST (0) // 0/1
|
||||
/**
|
||||
* LCD Bus Type.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BUS_TYPE (ESP_PANEL_BUS_TYPE_SPI)
|
||||
/**
|
||||
* LCD Bus Parameters.
|
||||
*
|
||||
* Please refer to https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/peripherals/lcd.html and
|
||||
* https://docs.espressif.com/projects/esp-iot-solution/en/latest/display/lcd/index.html for more details.
|
||||
*
|
||||
*/
|
||||
#if ESP_PANEL_LCD_BUS_TYPE == ESP_PANEL_BUS_TYPE_SPI
|
||||
|
||||
#define ESP_PANEL_LCD_BUS_HOST_ID (1) // Typically set to 1
|
||||
#define ESP_PANEL_LCD_SPI_IO_CS (5)
|
||||
#if !ESP_PANEL_LCD_BUS_SKIP_INIT_HOST
|
||||
#define ESP_PANEL_LCD_SPI_IO_SCK (7)
|
||||
#define ESP_PANEL_LCD_SPI_IO_MOSI (6)
|
||||
#define ESP_PANEL_LCD_SPI_IO_MISO (-1) // -1 if not used
|
||||
#endif
|
||||
#define ESP_PANEL_LCD_SPI_IO_DC (4)
|
||||
#define ESP_PANEL_LCD_SPI_MODE (0) // 0/1/2/3, typically set to 0
|
||||
#define ESP_PANEL_LCD_SPI_CLK_HZ (40 * 1000 * 1000)
|
||||
// Should be an integer divisor of 80M, typically set to 40M
|
||||
#define ESP_PANEL_LCD_SPI_TRANS_QUEUE_SZ (10) // Typically set to 10
|
||||
#define ESP_PANEL_LCD_SPI_CMD_BITS (8) // Typically set to 8
|
||||
#define ESP_PANEL_LCD_SPI_PARAM_BITS (8) // Typically set to 8
|
||||
|
||||
#endif /* ESP_PANEL_LCD_BUS_TYPE */
|
||||
|
||||
/**
|
||||
* LCD Venbdor Initialization Commands.
|
||||
*
|
||||
* Vendor specific initialization can be different between manufacturers, should consult the LCD supplier for
|
||||
* initialization sequence code. Please uncomment and change the following macro definitions. Otherwise, the LCD driver
|
||||
* will use the default initialization sequence code.
|
||||
*
|
||||
* There are two formats for the sequence code:
|
||||
* 1. Raw data: {command, (uint8_t []){ data0, data1, ... }, data_size, delay_ms}
|
||||
* 2. Formater: ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(delay_ms, command, { data0, data1, ... }) and
|
||||
* ESP_PANEL_LCD_CMD_WITH_NONE_PARAM(delay_ms, command)
|
||||
*/
|
||||
// #define ESP_PANEL_LCD_VENDOR_INIT_CMD \
|
||||
// { \
|
||||
// {0xFF, (uint8_t []){0x77, 0x01, 0x00, 0x00, 0x10}, 5, 0}, \
|
||||
// {0xC0, (uint8_t []){0x3B, 0x00}, 2, 0}, \
|
||||
// {0xC1, (uint8_t []){0x0D, 0x02}, 2, 0}, \
|
||||
// {0x29, (uint8_t []){0x00}, 0, 120}, \
|
||||
// or \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xFF, {0x77, 0x01, 0x00, 0x00, 0x10}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC0, {0x3B, 0x00}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC1, {0x0D, 0x02}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_NONE_PARAM(120, 0x29), \
|
||||
// }
|
||||
|
||||
/* LCD Color Settings */
|
||||
/* LCD color depth in bits */
|
||||
#define ESP_PANEL_LCD_COLOR_BITS (16) // 8/16/18/24
|
||||
/*
|
||||
* LCD RGB Element Order. Choose one of the following:
|
||||
* - 0: RGB
|
||||
* - 1: BGR
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BGR_ORDER (0) // 0/1
|
||||
#define ESP_PANEL_LCD_INEVRT_COLOR (1) // 0/1
|
||||
|
||||
/* LCD Transformation Flags */
|
||||
#define ESP_PANEL_LCD_SWAP_XY (1) // 0/1
|
||||
#define ESP_PANEL_LCD_MIRROR_X (0) // 0/1
|
||||
#define ESP_PANEL_LCD_MIRROR_Y (1) // 0/1
|
||||
|
||||
/* LCD Other Settings */
|
||||
/* IO num of RESET pin, set to -1 if not use */
|
||||
#define ESP_PANEL_LCD_IO_RST (48)
|
||||
#define ESP_PANEL_LCD_RST_LEVEL (0) // 0: low level, 1: high level
|
||||
|
||||
#endif /* ESP_PANEL_USE_LCD */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// Please update the following macros to configure the touch panel ///////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 1 when using an touch panel */
|
||||
#define ESP_PANEL_USE_TOUCH (0) // 0/1
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please update the following macros to configure the backlight ////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define ESP_PANEL_USE_BACKLIGHT (1) // 0/1
|
||||
#if ESP_PANEL_USE_BACKLIGHT
|
||||
/* IO num of backlight pin */
|
||||
#define ESP_PANEL_BACKLIGHT_IO (45)
|
||||
#define ESP_PANEL_BACKLIGHT_ON_LEVEL (0) // 0: low level, 1: high level
|
||||
|
||||
/* Set to 1 if you want to turn off the backlight after initializing the panel; otherwise, set it to turn on */
|
||||
#define ESP_PANEL_BACKLIGHT_IDLE_OFF (0) // 0: on, 1: off
|
||||
|
||||
/* Set to 1 if use PWM for brightness control */
|
||||
#define ESP_PANEL_LCD_BL_USE_PWM (1) // 0/1
|
||||
#endif /* ESP_PANEL_USE_BACKLIGHT */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please update the following macros to configure the IO expander //////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 0 if not using IO Expander */
|
||||
#define ESP_PANEL_USE_EXPANDER (0) // 0/1
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please utilize the following macros to execute any additional code if required. //////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// #define ESP_PANEL_BEGIN_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_EXPANDER_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_EXPANDER_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_LCD_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_LCD_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_TOUCH_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_TOUCH_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_BACKLIGHT_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_BACKLIGHT_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_END_FUNCTION( panel )
|
||||
|
||||
// *INDENT-OFF*
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// *INDENT-OFF*
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// Please update the following macros to configure the LCD panel /////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 1 when using an LCD panel */
|
||||
#define ESP_PANEL_USE_LCD (1) // 0/1
|
||||
|
||||
#if ESP_PANEL_USE_LCD
|
||||
/**
|
||||
* LCD Controller Name.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_NAME ST7789
|
||||
|
||||
/* LCD resolution in pixels */
|
||||
#define ESP_PANEL_LCD_WIDTH (240)
|
||||
#define ESP_PANEL_LCD_HEIGHT (240)
|
||||
|
||||
/* LCD Bus Settings */
|
||||
/**
|
||||
* If set to 1, the bus will skip to initialize the corresponding host. Users need to initialize the host in advance.
|
||||
* It is useful if other devices use the same host. Please ensure that the host is initialized only once.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BUS_SKIP_INIT_HOST (0) // 0/1
|
||||
/**
|
||||
* LCD Bus Type.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BUS_TYPE (ESP_PANEL_BUS_TYPE_SPI)
|
||||
/**
|
||||
* LCD Bus Parameters.
|
||||
*
|
||||
* Please refer to https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/peripherals/lcd.html and
|
||||
* https://docs.espressif.com/projects/esp-iot-solution/en/latest/display/lcd/index.html for more details.
|
||||
*
|
||||
*/
|
||||
#if ESP_PANEL_LCD_BUS_TYPE == ESP_PANEL_BUS_TYPE_SPI
|
||||
|
||||
#define ESP_PANEL_LCD_BUS_HOST_ID (1) // Typically set to 1
|
||||
#define ESP_PANEL_LCD_SPI_IO_CS (44)
|
||||
#if !ESP_PANEL_LCD_BUS_SKIP_INIT_HOST
|
||||
#define ESP_PANEL_LCD_SPI_IO_SCK (21)
|
||||
#define ESP_PANEL_LCD_SPI_IO_MOSI (47)
|
||||
#define ESP_PANEL_LCD_SPI_IO_MISO (-1) // -1 if not used
|
||||
#endif
|
||||
#define ESP_PANEL_LCD_SPI_IO_DC (43)
|
||||
#define ESP_PANEL_LCD_SPI_MODE (0) // 0/1/2/3, typically set to 0
|
||||
#define ESP_PANEL_LCD_SPI_CLK_HZ (40 * 1000 * 1000)
|
||||
// Should be an integer divisor of 80M, typically set to 40M
|
||||
#define ESP_PANEL_LCD_SPI_TRANS_QUEUE_SZ (10) // Typically set to 10
|
||||
#define ESP_PANEL_LCD_SPI_CMD_BITS (8) // Typically set to 8
|
||||
#define ESP_PANEL_LCD_SPI_PARAM_BITS (8) // Typically set to 8
|
||||
|
||||
#endif /* ESP_PANEL_LCD_BUS_TYPE */
|
||||
|
||||
/**
|
||||
* LCD Venbdor Initialization Commands.
|
||||
*
|
||||
* Vendor specific initialization can be different between manufacturers, should consult the LCD supplier for
|
||||
* initialization sequence code. Please uncomment and change the following macro definitions. Otherwise, the LCD driver
|
||||
* will use the default initialization sequence code.
|
||||
*
|
||||
* There are two formats for the sequence code:
|
||||
* 1. Raw data: {command, (uint8_t []){ data0, data1, ... }, data_size, delay_ms}
|
||||
* 2. Formater: ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(delay_ms, command, { data0, data1, ... }) and
|
||||
* ESP_PANEL_LCD_CMD_WITH_NONE_PARAM(delay_ms, command)
|
||||
*/
|
||||
// #define ESP_PANEL_LCD_VENDOR_INIT_CMD \
|
||||
// { \
|
||||
// {0xFF, (uint8_t []){0x77, 0x01, 0x00, 0x00, 0x10}, 5, 0}, \
|
||||
// {0xC0, (uint8_t []){0x3B, 0x00}, 2, 0}, \
|
||||
// {0xC1, (uint8_t []){0x0D, 0x02}, 2, 0}, \
|
||||
// {0x29, (uint8_t []){0x00}, 0, 120}, \
|
||||
// or \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xFF, {0x77, 0x01, 0x00, 0x00, 0x10}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC0, {0x3B, 0x00}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC1, {0x0D, 0x02}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_NONE_PARAM(120, 0x29), \
|
||||
// }
|
||||
|
||||
/* LCD Color Settings */
|
||||
/* LCD color depth in bits */
|
||||
#define ESP_PANEL_LCD_COLOR_BITS (16) // 8/16/18/24
|
||||
/*
|
||||
* LCD RGB Element Order. Choose one of the following:
|
||||
* - 0: RGB
|
||||
* - 1: BGR
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BGR_ORDER (0) // 0/1
|
||||
#define ESP_PANEL_LCD_INEVRT_COLOR (1) // 0/1
|
||||
|
||||
/* LCD Transformation Flags */
|
||||
#define ESP_PANEL_LCD_SWAP_XY (0) // 0/1
|
||||
#define ESP_PANEL_LCD_MIRROR_X (0) // 0/1
|
||||
#define ESP_PANEL_LCD_MIRROR_Y (0) // 0/1
|
||||
|
||||
/* LCD Other Settings */
|
||||
/* IO num of RESET pin, set to -1 if not use */
|
||||
#define ESP_PANEL_LCD_IO_RST (-1)
|
||||
#define ESP_PANEL_LCD_RST_LEVEL (0) // 0: low level, 1: high level
|
||||
|
||||
#endif /* ESP_PANEL_USE_LCD */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// Please update the following macros to configure the touch panel ///////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 1 when using an touch panel */
|
||||
#define ESP_PANEL_USE_TOUCH (0) // 0/1
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please update the following macros to configure the backlight ////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define ESP_PANEL_USE_BACKLIGHT (1) // 0/1
|
||||
#if ESP_PANEL_USE_BACKLIGHT
|
||||
/* IO num of backlight pin */
|
||||
#define ESP_PANEL_BACKLIGHT_IO (48)
|
||||
#define ESP_PANEL_BACKLIGHT_ON_LEVEL (0) // 0: low level, 1: high level
|
||||
|
||||
/* Set to 1 if you want to turn off the backlight after initializing the panel; otherwise, set it to turn on */
|
||||
#define ESP_PANEL_BACKLIGHT_IDLE_OFF (0) // 0: on, 1: off
|
||||
|
||||
/* Set to 1 if use PWM for brightness control */
|
||||
#define ESP_PANEL_LCD_BL_USE_PWM (1) // 0/1
|
||||
#endif /* ESP_PANEL_USE_BACKLIGHT */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please update the following macros to configure the IO expander //////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 0 if not using IO Expander */
|
||||
#define ESP_PANEL_USE_EXPANDER (0) // 0/1
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please utilize the following macros to execute any additional code if required. //////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// #define ESP_PANEL_BEGIN_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_EXPANDER_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_EXPANDER_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_LCD_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_LCD_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_TOUCH_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_TOUCH_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_BACKLIGHT_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_BACKLIGHT_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_END_FUNCTION( panel )
|
||||
|
||||
// *INDENT-OFF*
|
||||
+237
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// *INDENT-OFF*
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// Please update the following macros to configure the LCD panel /////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 1 when using an LCD panel */
|
||||
#define ESP_PANEL_USE_LCD (1) // 0/1
|
||||
|
||||
#if ESP_PANEL_USE_LCD
|
||||
/**
|
||||
* LCD Controller Name.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_NAME ST7789
|
||||
|
||||
/* LCD resolution in pixels */
|
||||
#define ESP_PANEL_LCD_WIDTH (320)
|
||||
#define ESP_PANEL_LCD_HEIGHT (240)
|
||||
|
||||
/* LCD Bus Settings */
|
||||
/**
|
||||
* If set to 1, the bus will skip to initialize the corresponding host. Users need to initialize the host in advance.
|
||||
* It is useful if other devices use the same host. Please ensure that the host is initialized only once.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BUS_SKIP_INIT_HOST (0) // 0/1
|
||||
/**
|
||||
* LCD Bus Type.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BUS_TYPE (ESP_PANEL_BUS_TYPE_SPI)
|
||||
/**
|
||||
* LCD Bus Parameters.
|
||||
*
|
||||
* Please refer to https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/peripherals/lcd.html and
|
||||
* https://docs.espressif.com/projects/esp-iot-solution/en/latest/display/lcd/index.html for more details.
|
||||
*
|
||||
*/
|
||||
#if ESP_PANEL_LCD_BUS_TYPE == ESP_PANEL_BUS_TYPE_SPI
|
||||
|
||||
#define ESP_PANEL_LCD_BUS_HOST_ID (1) // Typically set to 1
|
||||
#define ESP_PANEL_LCD_SPI_IO_CS (-1)
|
||||
#if !ESP_PANEL_LCD_BUS_SKIP_INIT_HOST
|
||||
#define ESP_PANEL_LCD_SPI_IO_SCK (1)
|
||||
#define ESP_PANEL_LCD_SPI_IO_MOSI (0)
|
||||
#define ESP_PANEL_LCD_SPI_IO_MISO (-1) // -1 if not used
|
||||
#endif
|
||||
#define ESP_PANEL_LCD_SPI_IO_DC (2)
|
||||
#define ESP_PANEL_LCD_SPI_MODE (0) // 0/1/2/3, typically set to 0
|
||||
#define ESP_PANEL_LCD_SPI_CLK_HZ (40 * 1000 * 1000)
|
||||
// Should be an integer divisor of 80M, typically set to 40M
|
||||
#define ESP_PANEL_LCD_SPI_TRANS_QUEUE_SZ (10) // Typically set to 10
|
||||
#define ESP_PANEL_LCD_SPI_CMD_BITS (8) // Typically set to 8
|
||||
#define ESP_PANEL_LCD_SPI_PARAM_BITS (8) // Typically set to 8
|
||||
|
||||
#endif /* ESP_PANEL_LCD_BUS_TYPE */
|
||||
|
||||
/**
|
||||
* LCD Venbdor Initialization Commands.
|
||||
*
|
||||
* Vendor specific initialization can be different between manufacturers, should consult the LCD supplier for
|
||||
* initialization sequence code. Please uncomment and change the following macro definitions. Otherwise, the LCD driver
|
||||
* will use the default initialization sequence code.
|
||||
*
|
||||
* There are two formats for the sequence code:
|
||||
* 1. Raw data: {command, (uint8_t []){ data0, data1, ... }, data_size, delay_ms}
|
||||
* 2. Formater: ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(delay_ms, command, { data0, data1, ... }) and
|
||||
* ESP_PANEL_LCD_CMD_WITH_NONE_PARAM(delay_ms, command)
|
||||
*/
|
||||
// #define ESP_PANEL_LCD_VENDOR_INIT_CMD \
|
||||
// { \
|
||||
// {0xFF, (uint8_t []){0x77, 0x01, 0x00, 0x00, 0x10}, 5, 0}, \
|
||||
// {0xC0, (uint8_t []){0x3B, 0x00}, 2, 0}, \
|
||||
// {0xC1, (uint8_t []){0x0D, 0x02}, 2, 0}, \
|
||||
// {0x29, (uint8_t []){0x00}, 0, 120}, \
|
||||
// or \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xFF, {0x77, 0x01, 0x00, 0x00, 0x10}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC0, {0x3B, 0x00}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC1, {0x0D, 0x02}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_NONE_PARAM(120, 0x29), \
|
||||
// }
|
||||
|
||||
/* LCD Color Settings */
|
||||
/* LCD color depth in bits */
|
||||
#define ESP_PANEL_LCD_COLOR_BITS (16) // 8/16/18/24
|
||||
/*
|
||||
* LCD RGB Element Order. Choose one of the following:
|
||||
* - 0: RGB
|
||||
* - 1: BGR
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BGR_ORDER (1) // 0/1
|
||||
#define ESP_PANEL_LCD_INEVRT_COLOR (0) // 0/1
|
||||
|
||||
/* LCD Transformation Flags */
|
||||
#define ESP_PANEL_LCD_SWAP_XY (0) // 0/1
|
||||
#define ESP_PANEL_LCD_MIRROR_X (1) // 0/1
|
||||
#define ESP_PANEL_LCD_MIRROR_Y (1) // 0/1
|
||||
|
||||
/* LCD Other Settings */
|
||||
/* IO num of RESET pin, set to -1 if not use */
|
||||
#define ESP_PANEL_LCD_IO_RST (-1)
|
||||
#define ESP_PANEL_LCD_RST_LEVEL (0) // 0: low level, 1: high level
|
||||
|
||||
#endif /* ESP_PANEL_USE_LCD */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// Please update the following macros to configure the touch panel ///////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 1 when using an touch panel */
|
||||
#define ESP_PANEL_USE_TOUCH (1) // 0/1
|
||||
#if ESP_PANEL_USE_TOUCH
|
||||
/**
|
||||
* Touch controller name.
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_NAME TT21100
|
||||
|
||||
/* Touch resolution in pixels */
|
||||
#define ESP_PANEL_TOUCH_H_RES (ESP_PANEL_LCD_WIDTH) // Typically set to the same value as the width of LCD
|
||||
#define ESP_PANEL_TOUCH_V_RES (ESP_PANEL_LCD_HEIGHT) // Typically set to the same value as the height of LCD
|
||||
|
||||
/* Touch Panel Bus Settings */
|
||||
/**
|
||||
* If set to 1, the bus will skip to initialize the corresponding host. Users need to initialize the host in advance.
|
||||
* It is useful if other devices use the same host. Please ensure that the host is initialized only once.
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_BUS_SKIP_INIT_HOST (0) // 0/1
|
||||
/**
|
||||
* Touch panel bus type.
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_BUS_TYPE (ESP_PANEL_BUS_TYPE_I2C)
|
||||
/* Touch panel bus parameters */
|
||||
#if ESP_PANEL_TOUCH_BUS_TYPE == ESP_PANEL_BUS_TYPE_I2C
|
||||
|
||||
#define ESP_PANEL_TOUCH_BUS_HOST_ID (0) // Typically set to 0
|
||||
#define ESP_PANEL_TOUCH_I2C_ADDRESS (0) // Typically set to 0 to use default address
|
||||
#if !ESP_PANEL_TOUCH_BUS_SKIP_INIT_HOST
|
||||
#define ESP_PANEL_TOUCH_I2C_CLK_HZ (400 * 1000)
|
||||
// Typically set to 400K
|
||||
#define ESP_PANEL_TOUCH_I2C_SCL_PULLUP (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_I2C_SDA_PULLUP (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_I2C_IO_SCL (18)
|
||||
#define ESP_PANEL_TOUCH_I2C_IO_SDA (17)
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#error "The function is not ready and will be implemented in the future."
|
||||
|
||||
#endif
|
||||
|
||||
/* Touch Transformation Flags */
|
||||
#define ESP_PANEL_TOUCH_SWAP_XY (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_MIRROR_X (1) // 0/1
|
||||
#define ESP_PANEL_TOUCH_MIRROR_Y (0) // 0/1
|
||||
|
||||
/* Touch Other Settings */
|
||||
/* IO num of RESET pin, set to -1 if not use */
|
||||
#define ESP_PANEL_TOUCH_IO_RST (-1)
|
||||
#define ESP_PANEL_TOUCH_RST_LEVEL (0) // 0: low level, 1: high level
|
||||
/* IO num of INT pin, set to -1 if not use */
|
||||
#define ESP_PANEL_TOUCH_IO_INT (-1)
|
||||
#define ESP_PANEL_TOUCH_INT_LEVEL (0) // 0: low level, 1: high level
|
||||
|
||||
#endif /* ESP_PANEL_USE_TOUCH */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please update the following macros to configure the backlight ////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define ESP_PANEL_USE_BACKLIGHT (0) // 0/1
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please update the following macros to configure the IO expander //////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 0 if not using IO Expander */
|
||||
#define ESP_PANEL_USE_EXPANDER (1) // 0/1
|
||||
#if ESP_PANEL_USE_EXPANDER
|
||||
/**
|
||||
* IO expander name.
|
||||
*/
|
||||
#define ESP_PANEL_EXPANDER_NAME TCA95xx_8bit
|
||||
|
||||
/* IO expander Settings */
|
||||
/**
|
||||
* If set to 1, the driver will skip to initialize the corresponding host. Users need to initialize the host in advance.
|
||||
* It is useful if other devices use the same host. Please ensure that the host is initialized only once.
|
||||
*/
|
||||
#define ESP_PANEL_EXPANDER_SKIP_INIT_HOST (0) // 0/1
|
||||
/* IO expander parameters */
|
||||
#define ESP_PANEL_EXPANDER_I2C_ADDRESS (0x20)//38
|
||||
#if !ESP_PANEL_EXPANDER_SKIP_INIT_HOST
|
||||
#define ESP_PANEL_EXPANDER_HOST_ID (0) // Typically set to 0
|
||||
#define ESP_PANEL_EXPANDER_I2C_CLK_HZ (400 * 1000)
|
||||
// Typically set to 400K
|
||||
#define ESP_PANEL_EXPANDER_I2C_SCL_PULLUP (0) // 0/1
|
||||
#define ESP_PANEL_EXPANDER_I2C_SDA_PULLUP (0) // 0/1
|
||||
#define ESP_PANEL_EXPANDER_I2C_IO_SCL (18)
|
||||
#define ESP_PANEL_EXPANDER_I2C_IO_SDA (17)
|
||||
#endif
|
||||
#endif /* ESP_PANEL_USE_EXPANDER */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please utilize the following macros to execute any additional code if required. //////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// #define ESP_PANEL_BEGIN_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_EXPANDER_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_EXPANDER_END_FUNCTION( panel )
|
||||
|
||||
#define ESP_PANEL_BEGIN_LCD_START_FUNCTION( panel ) \
|
||||
{ \
|
||||
ESP_LOGD(TAG, "Run BOARD_ESP32_S3_KORVO_2 LCD start function"); \
|
||||
ESP_PANEL_CHECK_NULL_RET(_expander_ptr, false, "Invalid IO expander pointer"); \
|
||||
panel->_expander_ptr->multiPinMode(IO_EXPANDER_PIN_NUM_1 | IO_EXPANDER_PIN_NUM_2 | IO_EXPANDER_PIN_NUM_3, OUTPUT); \
|
||||
/* Reset LCD */ \
|
||||
panel->_expander_ptr->digitalWrite(2, LOW); \
|
||||
vTaskDelay(pdMS_TO_TICKS(20)); \
|
||||
panel->_expander_ptr->digitalWrite(2, LOW); \
|
||||
vTaskDelay(pdMS_TO_TICKS(120)); \
|
||||
panel->_expander_ptr->digitalWrite(2, HIGH); \
|
||||
/* Turn on backlight_ptr */ \
|
||||
panel->_expander_ptr->digitalWrite(1, HIGH); \
|
||||
/* Keep LCD CS low */ \
|
||||
panel->_expander_ptr->digitalWrite(3, LOW); \
|
||||
}
|
||||
|
||||
// #define ESP_PANEL_BEGIN_LCD_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_TOUCH_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_TOUCH_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_BACKLIGHT_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_BACKLIGHT_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_END_FUNCTION( panel )
|
||||
|
||||
// *INDENT-OFF*
|
||||
+267
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// *INDENT-OFF*
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// Please update the following macros to configure the LCD panel /////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 1 when using an LCD panel */
|
||||
#define ESP_PANEL_USE_LCD (1) // 0/1
|
||||
|
||||
#if ESP_PANEL_USE_LCD
|
||||
/**
|
||||
* LCD Controller Name.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_NAME GC9503
|
||||
|
||||
/* LCD resolution in pixels */
|
||||
#define ESP_PANEL_LCD_WIDTH (480)
|
||||
#define ESP_PANEL_LCD_HEIGHT (480)
|
||||
|
||||
/* LCD Bus Settings */
|
||||
/**
|
||||
* If set to 1, the bus will skip to initialize the corresponding host. Users need to initialize the host in advance.
|
||||
* It is useful if other devices use the same host. Please ensure that the host is initialized only once.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BUS_SKIP_INIT_HOST (0) // 0/1
|
||||
/**
|
||||
* LCD Bus Type.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BUS_TYPE (ESP_PANEL_BUS_TYPE_RGB)
|
||||
/**
|
||||
* LCD Bus Parameters.
|
||||
*
|
||||
* Please refer to https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/peripherals/lcd.html and
|
||||
* https://docs.espressif.com/projects/esp-iot-solution/en/latest/display/lcd/index.html for more details.
|
||||
*
|
||||
*/
|
||||
#if ESP_PANEL_LCD_BUS_TYPE == ESP_PANEL_BUS_TYPE_RGB
|
||||
|
||||
#define ESP_PANEL_LCD_RGB_CLK_HZ (16 * 1000 * 1000)
|
||||
#define ESP_PANEL_LCD_RGB_HPW (10)
|
||||
#define ESP_PANEL_LCD_RGB_HBP (10)
|
||||
#define ESP_PANEL_LCD_RGB_HFP (20)
|
||||
#define ESP_PANEL_LCD_RGB_VPW (10)
|
||||
#define ESP_PANEL_LCD_RGB_VBP (10)
|
||||
#define ESP_PANEL_LCD_RGB_VFP (10)
|
||||
#define ESP_PANEL_LCD_RGB_PCLK_ACTIVE_NEG (0) // 0: rising edge, 1: falling edge
|
||||
#define ESP_PANEL_LCD_RGB_DATA_WIDTH (16) // 8 | 16
|
||||
#define ESP_PANEL_LCD_RGB_PIXEL_BITS (16) // 24 | 16
|
||||
#define ESP_PANEL_LCD_RGB_FRAME_BUF_NUM (1) // 1/2/3
|
||||
#define ESP_PANEL_LCD_RGB_BOUNCE_BUF_SIZE (ESP_PANEL_LCD_WIDTH * 10)
|
||||
// Bounce buffer size in bytes. This function is used to avoid screen drift.
|
||||
// To enable the bounce buffer, set it to a non-zero value.
|
||||
// Typically set to `ESP_PANEL_LCD_WIDTH * 10`
|
||||
#define ESP_PANEL_LCD_RGB_IO_HSYNC (46)
|
||||
#define ESP_PANEL_LCD_RGB_IO_VSYNC (3)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DE (17) // -1 if not used
|
||||
#define ESP_PANEL_LCD_RGB_IO_PCLK (9)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DISP (-1) // -1 if not used
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA0 (10)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA1 (11)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA2 (12)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA3 (13)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA4 (14)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA5 (21)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA6 (47)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA7 (48)
|
||||
#if ESP_PANEL_LCD_RGB_DATA_WIDTH > 8
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA8 (45)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA9 (38)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA10 (39)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA11 (40)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA12 (41)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA13 (42)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA14 (2)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA15 (1)
|
||||
#endif
|
||||
#if !ESP_PANEL_LCD_BUS_SKIP_INIT_HOST
|
||||
#define ESP_PANEL_LCD_3WIRE_SPI_IO_CS (1)
|
||||
#define ESP_PANEL_LCD_3WIRE_SPI_IO_SCK (2)
|
||||
#define ESP_PANEL_LCD_3WIRE_SPI_IO_SDA (3)
|
||||
#define ESP_PANEL_LCD_3WIRE_SPI_CS_USE_EXPNADER (1) // 0/1
|
||||
#define ESP_PANEL_LCD_3WIRE_SPI_SCL_USE_EXPNADER (1) // 0/1
|
||||
#define ESP_PANEL_LCD_3WIRE_SPI_SDA_USE_EXPNADER (1) // 0/1
|
||||
#define ESP_PANEL_LCD_3WIRE_SPI_SCL_ACTIVE_EDGE (0) // 0: rising edge, 1: falling edge
|
||||
#define ESP_PANEL_LCD_FLAGS_AUTO_DEL_PANEL_IO (1) // Delete the panel IO instance automatically if set to 1.
|
||||
// If the 3-wire SPI pins are sharing other pins of the RGB
|
||||
// interface to save GPIOs, Please set it to 1 to release
|
||||
// the panel IO and its pins (except CS signal).
|
||||
#define ESP_PANEL_LCD_FLAGS_MIRROR_BY_CMD (!ESP_PANEL_LCD_FLAGS_AUTO_DEL_PANEL_IO)
|
||||
// The `mirror()` function will be implemented by LCD
|
||||
// command if set to 1.
|
||||
#endif
|
||||
|
||||
#endif /* ESP_PANEL_LCD_BUS_TYPE */
|
||||
|
||||
/**
|
||||
* LCD Venbdor Initialization Commands.
|
||||
*
|
||||
* Vendor specific initialization can be different between manufacturers, should consult the LCD supplier for
|
||||
* initialization sequence code. Please uncomment and change the following macro definitions. Otherwise, the LCD driver
|
||||
* will use the default initialization sequence code.
|
||||
*
|
||||
* There are two formats for the sequence code:
|
||||
* 1. Raw data: {command, (uint8_t []){ data0, data1, ... }, data_size, delay_ms}
|
||||
* 2. Formater: ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(delay_ms, command, { data0, data1, ... }) and
|
||||
* ESP_PANEL_LCD_CMD_WITH_NONE_PARAM(delay_ms, command)
|
||||
*/
|
||||
// #define ESP_PANEL_LCD_VENDOR_INIT_CMD \
|
||||
// { \
|
||||
// {0xFF, (uint8_t []){0x77, 0x01, 0x00, 0x00, 0x10}, 5, 0}, \
|
||||
// {0xC0, (uint8_t []){0x3B, 0x00}, 2, 0}, \
|
||||
// {0xC1, (uint8_t []){0x0D, 0x02}, 2, 0}, \
|
||||
// {0x29, (uint8_t []){0x00}, 0, 120}, \
|
||||
// or \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xFF, {0x77, 0x01, 0x00, 0x00, 0x10}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC0, {0x3B, 0x00}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC1, {0x0D, 0x02}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_NONE_PARAM(120, 0x29), \
|
||||
// }
|
||||
|
||||
/* LCD Color Settings */
|
||||
/* LCD color depth in bits */
|
||||
#define ESP_PANEL_LCD_COLOR_BITS (18) // 8/16/18/24
|
||||
/*
|
||||
* LCD RGB Element Order. Choose one of the following:
|
||||
* - 0: RGB
|
||||
* - 1: BGR
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BGR_ORDER (0) // 0/1
|
||||
#define ESP_PANEL_LCD_INEVRT_COLOR (0) // 0/1
|
||||
|
||||
/* LCD Transformation Flags */
|
||||
#define ESP_PANEL_LCD_SWAP_XY (0) // 0/1
|
||||
#define ESP_PANEL_LCD_MIRROR_X (0) // 0/1
|
||||
#define ESP_PANEL_LCD_MIRROR_Y (0) // 0/1
|
||||
|
||||
/* LCD Other Settings */
|
||||
/* IO num of RESET pin, set to -1 if not use */
|
||||
#define ESP_PANEL_LCD_IO_RST (-1)
|
||||
#define ESP_PANEL_LCD_RST_LEVEL (0) // 0: low level, 1: high level
|
||||
|
||||
#endif /* ESP_PANEL_USE_LCD */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// Please update the following macros to configure the touch panel ///////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 1 when using an touch panel */
|
||||
#define ESP_PANEL_USE_TOUCH (1) // 0/1
|
||||
#if ESP_PANEL_USE_TOUCH
|
||||
/**
|
||||
* Touch controller name.
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_NAME FT5x06
|
||||
|
||||
/* Touch resolution in pixels */
|
||||
#define ESP_PANEL_TOUCH_H_RES (ESP_PANEL_LCD_WIDTH) // Typically set to the same value as the width of LCD
|
||||
#define ESP_PANEL_TOUCH_V_RES (ESP_PANEL_LCD_HEIGHT) // Typically set to the same value as the height of LCD
|
||||
|
||||
/* Touch Panel Bus Settings */
|
||||
/**
|
||||
* If set to 1, the bus will skip to initialize the corresponding host. Users need to initialize the host in advance.
|
||||
* It is useful if other devices use the same host. Please ensure that the host is initialized only once.
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_BUS_SKIP_INIT_HOST (0) // 0/1
|
||||
/**
|
||||
* Touch panel bus type.
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_BUS_TYPE (ESP_PANEL_BUS_TYPE_I2C)
|
||||
/* Touch panel bus parameters */
|
||||
#if ESP_PANEL_TOUCH_BUS_TYPE == ESP_PANEL_BUS_TYPE_I2C
|
||||
|
||||
#define ESP_PANEL_TOUCH_BUS_HOST_ID (0) // Typically set to 0
|
||||
#define ESP_PANEL_TOUCH_I2C_ADDRESS (0) // Typically set to 0 to use default address
|
||||
#if !ESP_PANEL_TOUCH_BUS_SKIP_INIT_HOST
|
||||
#define ESP_PANEL_TOUCH_I2C_CLK_HZ (400 * 1000)
|
||||
// Typically set to 400K
|
||||
#define ESP_PANEL_TOUCH_I2C_SCL_PULLUP (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_I2C_SDA_PULLUP (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_I2C_IO_SCL (18)
|
||||
#define ESP_PANEL_TOUCH_I2C_IO_SDA (8)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* Touch Transformation Flags */
|
||||
#define ESP_PANEL_TOUCH_SWAP_XY (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_MIRROR_X (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_MIRROR_Y (0) // 0/1
|
||||
|
||||
/* Touch Other Settings */
|
||||
/* IO num of RESET pin, set to -1 if not use */
|
||||
#define ESP_PANEL_TOUCH_IO_RST (-1)
|
||||
#define ESP_PANEL_TOUCH_RST_LEVEL (0) // 0: low level, 1: high level
|
||||
/* IO num of INT pin, set to -1 if not use */
|
||||
#define ESP_PANEL_TOUCH_IO_INT (-1)
|
||||
#define ESP_PANEL_TOUCH_INT_LEVEL (0) // 0: low level, 1: high level
|
||||
|
||||
#endif /* ESP_PANEL_USE_TOUCH */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please update the following macros to configure the backlight ////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define ESP_PANEL_USE_BACKLIGHT (0) // 0/1
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please update the following macros to configure the IO expander //////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 0 if not using IO Expander */
|
||||
#define ESP_PANEL_USE_EXPANDER (1) // 0/1
|
||||
#if ESP_PANEL_USE_EXPANDER
|
||||
/**
|
||||
* IO expander name.
|
||||
*/
|
||||
#define ESP_PANEL_EXPANDER_NAME TCA95xx_8bit
|
||||
|
||||
/* IO expander Settings */
|
||||
/**
|
||||
* If set to 1, the driver will skip to initialize the corresponding host. Users need to initialize the host in advance.
|
||||
* It is useful if other devices use the same host. Please ensure that the host is initialized only once.
|
||||
*/
|
||||
#define ESP_PANEL_EXPANDER_SKIP_INIT_HOST (0) // 0/1
|
||||
/* IO expander parameters */
|
||||
#define ESP_PANEL_EXPANDER_I2C_ADDRESS (0x20)
|
||||
#if !ESP_PANEL_EXPANDER_SKIP_INIT_HOST
|
||||
#define ESP_PANEL_EXPANDER_HOST_ID (0) // Typically set to 0
|
||||
#define ESP_PANEL_EXPANDER_I2C_CLK_HZ (400 * 1000)
|
||||
// Typically set to 400K
|
||||
#define ESP_PANEL_EXPANDER_I2C_SCL_PULLUP (0) // 0/1
|
||||
#define ESP_PANEL_EXPANDER_I2C_SDA_PULLUP (0) // 0/1
|
||||
#define ESP_PANEL_EXPANDER_I2C_IO_SCL (18)
|
||||
#define ESP_PANEL_EXPANDER_I2C_IO_SDA (8)
|
||||
#endif
|
||||
#endif /* ESP_PANEL_USE_EXPANDER */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please utilize the following macros to execute any additional code if required. //////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// #define ESP_PANEL_BEGIN_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_EXPANDER_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_EXPANDER_END_FUNCTION( panel )
|
||||
|
||||
#define ESP_PANEL_BEGIN_LCD_START_FUNCTION( panel ) \
|
||||
{ \
|
||||
ESP_LOGD(TAG, "Run ESP32_S3_LCD_EV_BOARD LCD start function"); \
|
||||
/* For the v1.5 version sub board, need to set `ESP_PANEL_LCD_RGB_IO_VSYNC` to high before initialize LCD */ \
|
||||
gpio_set_direction((gpio_num_t)ESP_PANEL_LCD_RGB_IO_VSYNC, GPIO_MODE_OUTPUT); \
|
||||
gpio_set_level((gpio_num_t)ESP_PANEL_LCD_RGB_IO_VSYNC, 0); \
|
||||
vTaskDelay(pdMS_TO_TICKS(10)); \
|
||||
gpio_set_level((gpio_num_t)ESP_PANEL_LCD_RGB_IO_VSYNC, 1); \
|
||||
vTaskDelay(pdMS_TO_TICKS(120)); \
|
||||
}
|
||||
|
||||
// #define ESP_PANEL_BEGIN_LCD_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_TOUCH_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_TOUCH_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_BACKLIGHT_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_BACKLIGHT_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_END_FUNCTION( panel )
|
||||
|
||||
// *INDENT-OFF*
|
||||
+216
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// *INDENT-OFF*
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// Please update the following macros to configure the LCD panel /////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 1 when using an LCD panel */
|
||||
#define ESP_PANEL_USE_LCD (1) // 0/1
|
||||
|
||||
#if ESP_PANEL_USE_LCD
|
||||
/**
|
||||
* LCD Controller Name.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_NAME ST7262
|
||||
|
||||
/* LCD resolution in pixels */
|
||||
#define ESP_PANEL_LCD_WIDTH (800)
|
||||
#define ESP_PANEL_LCD_HEIGHT (480)
|
||||
|
||||
/* LCD Bus Settings */
|
||||
/**
|
||||
* If set to 1, the bus will skip to initialize the corresponding host. Users need to initialize the host in advance.
|
||||
* It is useful if other devices use the same host. Please ensure that the host is initialized only once.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BUS_SKIP_INIT_HOST (1) // 0/1
|
||||
/**
|
||||
* LCD Bus Type.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BUS_TYPE (ESP_PANEL_BUS_TYPE_RGB)
|
||||
/**
|
||||
* LCD Bus Parameters.
|
||||
*
|
||||
* Please refer to https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/peripherals/lcd.html and
|
||||
* https://docs.espressif.com/projects/esp-iot-solution/en/latest/display/lcd/index.html for more details.
|
||||
*
|
||||
*/
|
||||
#if ESP_PANEL_LCD_BUS_TYPE == ESP_PANEL_BUS_TYPE_RGB
|
||||
|
||||
#define ESP_PANEL_LCD_RGB_CLK_HZ (16 * 1000 * 1000)
|
||||
#define ESP_PANEL_LCD_RGB_HPW (40)
|
||||
#define ESP_PANEL_LCD_RGB_HBP (40)
|
||||
#define ESP_PANEL_LCD_RGB_HFP (40)
|
||||
#define ESP_PANEL_LCD_RGB_VPW (23)
|
||||
#define ESP_PANEL_LCD_RGB_VBP (32)
|
||||
#define ESP_PANEL_LCD_RGB_VFP (13)
|
||||
#define ESP_PANEL_LCD_RGB_PCLK_ACTIVE_NEG (1) // 0: rising edge, 1: falling edge
|
||||
#define ESP_PANEL_LCD_RGB_DATA_WIDTH (16) // 8 | 16
|
||||
#define ESP_PANEL_LCD_RGB_PIXEL_BITS (16) // 24 | 16
|
||||
#define ESP_PANEL_LCD_RGB_FRAME_BUF_NUM (1) // 1/2/3
|
||||
#define ESP_PANEL_LCD_RGB_BOUNCE_BUF_SIZE (ESP_PANEL_LCD_WIDTH * 10)
|
||||
// Bounce buffer size in bytes. This function is used to avoid screen drift.
|
||||
// To enable the bounce buffer, set it to a non-zero value.
|
||||
// Typically set to `ESP_PANEL_LCD_WIDTH * 10`
|
||||
#define ESP_PANEL_LCD_RGB_IO_HSYNC (46)
|
||||
#define ESP_PANEL_LCD_RGB_IO_VSYNC (3)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DE (17) // -1 if not used
|
||||
#define ESP_PANEL_LCD_RGB_IO_PCLK (9)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DISP (-1) // -1 if not used
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA0 (10)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA1 (11)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA2 (12)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA3 (13)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA4 (14)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA5 (21)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA6 (47)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA7 (48)
|
||||
#if ESP_PANEL_LCD_RGB_DATA_WIDTH > 8
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA8 (45)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA9 (38)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA10 (39)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA11 (40)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA12 (41)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA13 (42)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA14 (2)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA15 (1)
|
||||
#endif
|
||||
|
||||
#endif /* ESP_PANEL_LCD_BUS_TYPE */
|
||||
|
||||
/**
|
||||
* LCD Venbdor Initialization Commands.
|
||||
*
|
||||
* Vendor specific initialization can be different between manufacturers, should consult the LCD supplier for
|
||||
* initialization sequence code. Please uncomment and change the following macro definitions. Otherwise, the LCD driver
|
||||
* will use the default initialization sequence code.
|
||||
*
|
||||
* There are two formats for the sequence code:
|
||||
* 1. Raw data: {command, (uint8_t []){ data0, data1, ... }, data_size, delay_ms}
|
||||
* 2. Formater: ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(delay_ms, command, { data0, data1, ... }) and
|
||||
* ESP_PANEL_LCD_CMD_WITH_NONE_PARAM(delay_ms, command)
|
||||
*/
|
||||
// #define ESP_PANEL_LCD_VENDOR_INIT_CMD \
|
||||
// { \
|
||||
// {0xFF, (uint8_t []){0x77, 0x01, 0x00, 0x00, 0x10}, 5, 0}, \
|
||||
// {0xC0, (uint8_t []){0x3B, 0x00}, 2, 0}, \
|
||||
// {0xC1, (uint8_t []){0x0D, 0x02}, 2, 0}, \
|
||||
// {0x29, (uint8_t []){0x00}, 0, 120}, \
|
||||
// or \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xFF, {0x77, 0x01, 0x00, 0x00, 0x10}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC0, {0x3B, 0x00}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC1, {0x0D, 0x02}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_NONE_PARAM(120, 0x29), \
|
||||
// }
|
||||
|
||||
/* LCD Color Settings */
|
||||
/* LCD color depth in bits */
|
||||
#define ESP_PANEL_LCD_COLOR_BITS (24) // 8/16/18/24
|
||||
/*
|
||||
* LCD RGB Element Order. Choose one of the following:
|
||||
* - 0: RGB
|
||||
* - 1: BGR
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BGR_ORDER (0) // 0/1
|
||||
#define ESP_PANEL_LCD_INEVRT_COLOR (0) // 0/1
|
||||
|
||||
/* LCD Transformation Flags */
|
||||
#define ESP_PANEL_LCD_SWAP_XY (0) // 0/1
|
||||
#define ESP_PANEL_LCD_MIRROR_X (0) // 0/1
|
||||
#define ESP_PANEL_LCD_MIRROR_Y (0) // 0/1
|
||||
|
||||
/* LCD Other Settings */
|
||||
/* IO num of RESET pin, set to -1 if not use */
|
||||
#define ESP_PANEL_LCD_IO_RST (-1)
|
||||
#define ESP_PANEL_LCD_RST_LEVEL (0) // 0: low level, 1: high level
|
||||
|
||||
#endif /* ESP_PANEL_USE_LCD */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// Please update the following macros to configure the touch panel ///////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 1 when using an touch panel */
|
||||
#define ESP_PANEL_USE_TOUCH (1) // 0/1
|
||||
#if ESP_PANEL_USE_TOUCH
|
||||
/**
|
||||
* Touch controller name.
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_NAME GT1151
|
||||
|
||||
/* Touch resolution in pixels */
|
||||
#define ESP_PANEL_TOUCH_H_RES (ESP_PANEL_LCD_WIDTH) // Typically set to the same value as the width of LCD
|
||||
#define ESP_PANEL_TOUCH_V_RES (ESP_PANEL_LCD_HEIGHT) // Typically set to the same value as the height of LCD
|
||||
|
||||
/* Touch Panel Bus Settings */
|
||||
/**
|
||||
* If set to 1, the bus will skip to initialize the corresponding host. Users need to initialize the host in advance.
|
||||
* It is useful if other devices use the same host. Please ensure that the host is initialized only once.
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_BUS_SKIP_INIT_HOST (0) // 0/1
|
||||
/**
|
||||
* Touch panel bus type.
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_BUS_TYPE (ESP_PANEL_BUS_TYPE_I2C)
|
||||
/* Touch panel bus parameters */
|
||||
#if ESP_PANEL_TOUCH_BUS_TYPE == ESP_PANEL_BUS_TYPE_I2C
|
||||
|
||||
#define ESP_PANEL_TOUCH_BUS_HOST_ID (0) // Typically set to 0
|
||||
#define ESP_PANEL_TOUCH_I2C_ADDRESS (0) // Typically set to 0 to use default address
|
||||
#if !ESP_PANEL_TOUCH_BUS_SKIP_INIT_HOST
|
||||
#define ESP_PANEL_TOUCH_I2C_CLK_HZ (400 * 1000)
|
||||
// Typically set to 400K
|
||||
#define ESP_PANEL_TOUCH_I2C_SCL_PULLUP (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_I2C_SDA_PULLUP (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_I2C_IO_SCL (18)
|
||||
#define ESP_PANEL_TOUCH_I2C_IO_SDA (8)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* Touch Transformation Flags */
|
||||
#define ESP_PANEL_TOUCH_SWAP_XY (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_MIRROR_X (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_MIRROR_Y (0) // 0/1
|
||||
|
||||
/* Touch Other Settings */
|
||||
/* IO num of RESET pin, set to -1 if not use */
|
||||
#define ESP_PANEL_TOUCH_IO_RST (-1)
|
||||
#define ESP_PANEL_TOUCH_RST_LEVEL (0) // 0: low level, 1: high level
|
||||
/* IO num of INT pin, set to -1 if not use */
|
||||
#define ESP_PANEL_TOUCH_IO_INT (-1)
|
||||
#define ESP_PANEL_TOUCH_INT_LEVEL (0) // 0: low level, 1: high level
|
||||
|
||||
#endif /* ESP_PANEL_USE_TOUCH */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please update the following macros to configure the backlight ////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define ESP_PANEL_USE_BACKLIGHT (0) // 0/1
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please update the following macros to configure the IO expander //////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 0 if not using IO Expander */
|
||||
#define ESP_PANEL_USE_EXPANDER (0) // 0/1
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please utilize the following macros to execute any additional code if required. //////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// #define ESP_PANEL_BEGIN_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_EXPANDER_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_EXPANDER_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_LCD_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_LCD_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_TOUCH_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_TOUCH_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_BACKLIGHT_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_BACKLIGHT_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_END_FUNCTION( panel )
|
||||
|
||||
// *INDENT-OFF*
|
||||
+216
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// *INDENT-OFF*
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// Please update the following macros to configure the LCD panel /////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 1 when using an LCD panel */
|
||||
#define ESP_PANEL_USE_LCD (1) // 0/1
|
||||
|
||||
#if ESP_PANEL_USE_LCD
|
||||
/**
|
||||
* LCD Controller Name.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_NAME ST7262
|
||||
|
||||
/* LCD resolution in pixels */
|
||||
#define ESP_PANEL_LCD_WIDTH (800)
|
||||
#define ESP_PANEL_LCD_HEIGHT (480)
|
||||
|
||||
/* LCD Bus Settings */
|
||||
/**
|
||||
* If set to 1, the bus will skip to initialize the corresponding host. Users need to initialize the host in advance.
|
||||
* It is useful if other devices use the same host. Please ensure that the host is initialized only once.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BUS_SKIP_INIT_HOST (1) // 0/1
|
||||
/**
|
||||
* LCD Bus Type.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BUS_TYPE (ESP_PANEL_BUS_TYPE_RGB)
|
||||
/**
|
||||
* LCD Bus Parameters.
|
||||
*
|
||||
* Please refer to https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/peripherals/lcd.html and
|
||||
* https://docs.espressif.com/projects/esp-iot-solution/en/latest/display/lcd/index.html for more details.
|
||||
*
|
||||
*/
|
||||
#if ESP_PANEL_LCD_BUS_TYPE == ESP_PANEL_BUS_TYPE_RGB
|
||||
|
||||
#define ESP_PANEL_LCD_RGB_CLK_HZ (16 * 1000 * 1000)
|
||||
#define ESP_PANEL_LCD_RGB_HPW (40)
|
||||
#define ESP_PANEL_LCD_RGB_HBP (40)
|
||||
#define ESP_PANEL_LCD_RGB_HFP (40)
|
||||
#define ESP_PANEL_LCD_RGB_VPW (23)
|
||||
#define ESP_PANEL_LCD_RGB_VBP (32)
|
||||
#define ESP_PANEL_LCD_RGB_VFP (13)
|
||||
#define ESP_PANEL_LCD_RGB_PCLK_ACTIVE_NEG (1) // 0: rising edge, 1: falling edge
|
||||
#define ESP_PANEL_LCD_RGB_DATA_WIDTH (16) // 8 | 16
|
||||
#define ESP_PANEL_LCD_RGB_PIXEL_BITS (16) // 24 | 16
|
||||
#define ESP_PANEL_LCD_RGB_FRAME_BUF_NUM (1) // 1/2/3
|
||||
#define ESP_PANEL_LCD_RGB_BOUNCE_BUF_SIZE (ESP_PANEL_LCD_WIDTH * 10)
|
||||
// Bounce buffer size in bytes. This function is used to avoid screen drift.
|
||||
// To enable the bounce buffer, set it to a non-zero value.
|
||||
// Typically set to `ESP_PANEL_LCD_WIDTH * 10`
|
||||
#define ESP_PANEL_LCD_RGB_IO_HSYNC (46)
|
||||
#define ESP_PANEL_LCD_RGB_IO_VSYNC (3)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DE (17) // -1 if not used
|
||||
#define ESP_PANEL_LCD_RGB_IO_PCLK (9)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DISP (-1) // -1 if not used
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA0 (10)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA1 (11)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA2 (12)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA3 (13)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA4 (14)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA5 (21)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA6 (8)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA7 (18)
|
||||
#if ESP_PANEL_LCD_RGB_DATA_WIDTH > 8
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA8 (45)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA9 (38)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA10 (39)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA11 (40)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA12 (41)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA13 (42)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA14 (2)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA15 (1)
|
||||
#endif
|
||||
|
||||
#endif /* ESP_PANEL_LCD_BUS_TYPE */
|
||||
|
||||
/**
|
||||
* LCD Venbdor Initialization Commands.
|
||||
*
|
||||
* Vendor specific initialization can be different between manufacturers, should consult the LCD supplier for
|
||||
* initialization sequence code. Please uncomment and change the following macro definitions. Otherwise, the LCD driver
|
||||
* will use the default initialization sequence code.
|
||||
*
|
||||
* There are two formats for the sequence code:
|
||||
* 1. Raw data: {command, (uint8_t []){ data0, data1, ... }, data_size, delay_ms}
|
||||
* 2. Formater: ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(delay_ms, command, { data0, data1, ... }) and
|
||||
* ESP_PANEL_LCD_CMD_WITH_NONE_PARAM(delay_ms, command)
|
||||
*/
|
||||
// #define ESP_PANEL_LCD_VENDOR_INIT_CMD \
|
||||
// { \
|
||||
// {0xFF, (uint8_t []){0x77, 0x01, 0x00, 0x00, 0x10}, 5, 0}, \
|
||||
// {0xC0, (uint8_t []){0x3B, 0x00}, 2, 0}, \
|
||||
// {0xC1, (uint8_t []){0x0D, 0x02}, 2, 0}, \
|
||||
// {0x29, (uint8_t []){0x00}, 0, 120}, \
|
||||
// or \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xFF, {0x77, 0x01, 0x00, 0x00, 0x10}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC0, {0x3B, 0x00}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC1, {0x0D, 0x02}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_NONE_PARAM(120, 0x29), \
|
||||
// }
|
||||
|
||||
/* LCD Color Settings */
|
||||
/* LCD color depth in bits */
|
||||
#define ESP_PANEL_LCD_COLOR_BITS (24) // 8/16/18/24
|
||||
/*
|
||||
* LCD RGB Element Order. Choose one of the following:
|
||||
* - 0: RGB
|
||||
* - 1: BGR
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BGR_ORDER (0) // 0/1
|
||||
#define ESP_PANEL_LCD_INEVRT_COLOR (0) // 0/1
|
||||
|
||||
/* LCD Transformation Flags */
|
||||
#define ESP_PANEL_LCD_SWAP_XY (0) // 0/1
|
||||
#define ESP_PANEL_LCD_MIRROR_X (0) // 0/1
|
||||
#define ESP_PANEL_LCD_MIRROR_Y (0) // 0/1
|
||||
|
||||
/* LCD Other Settings */
|
||||
/* IO num of RESET pin, set to -1 if not use */
|
||||
#define ESP_PANEL_LCD_IO_RST (-1)
|
||||
#define ESP_PANEL_LCD_RST_LEVEL (0) // 0: low level, 1: high level
|
||||
|
||||
#endif /* ESP_PANEL_USE_LCD */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// Please update the following macros to configure the touch panel ///////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 1 when using an touch panel */
|
||||
#define ESP_PANEL_USE_TOUCH (1) // 0/1
|
||||
#if ESP_PANEL_USE_TOUCH
|
||||
/**
|
||||
* Touch controller name.
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_NAME GT1151
|
||||
|
||||
/* Touch resolution in pixels */
|
||||
#define ESP_PANEL_TOUCH_H_RES (ESP_PANEL_LCD_WIDTH) // Typically set to the same value as the width of LCD
|
||||
#define ESP_PANEL_TOUCH_V_RES (ESP_PANEL_LCD_HEIGHT) // Typically set to the same value as the height of LCD
|
||||
|
||||
/* Touch Panel Bus Settings */
|
||||
/**
|
||||
* If set to 1, the bus will skip to initialize the corresponding host. Users need to initialize the host in advance.
|
||||
* It is useful if other devices use the same host. Please ensure that the host is initialized only once.
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_BUS_SKIP_INIT_HOST (0) // 0/1
|
||||
/**
|
||||
* Touch panel bus type.
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_BUS_TYPE (ESP_PANEL_BUS_TYPE_I2C)
|
||||
/* Touch panel bus parameters */
|
||||
#if ESP_PANEL_TOUCH_BUS_TYPE == ESP_PANEL_BUS_TYPE_I2C
|
||||
|
||||
#define ESP_PANEL_TOUCH_BUS_HOST_ID (0) // Typically set to 0
|
||||
#define ESP_PANEL_TOUCH_I2C_ADDRESS (0) // Typically set to 0 to use default address
|
||||
#if !ESP_PANEL_TOUCH_BUS_SKIP_INIT_HOST
|
||||
#define ESP_PANEL_TOUCH_I2C_CLK_HZ (400 * 1000)
|
||||
// Typically set to 400K
|
||||
#define ESP_PANEL_TOUCH_I2C_SCL_PULLUP (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_I2C_SDA_PULLUP (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_I2C_IO_SCL (48)
|
||||
#define ESP_PANEL_TOUCH_I2C_IO_SDA (47)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* Touch Transformation Flags */
|
||||
#define ESP_PANEL_TOUCH_SWAP_XY (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_MIRROR_X (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_MIRROR_Y (0) // 0/1
|
||||
|
||||
/* Touch Other Settings */
|
||||
/* IO num of RESET pin, set to -1 if not use */
|
||||
#define ESP_PANEL_TOUCH_IO_RST (-1)
|
||||
#define ESP_PANEL_TOUCH_RST_LEVEL (0) // 0: low level, 1: high level
|
||||
/* IO num of INT pin, set to -1 if not use */
|
||||
#define ESP_PANEL_TOUCH_IO_INT (-1)
|
||||
#define ESP_PANEL_TOUCH_INT_LEVEL (0) // 0: low level, 1: high level
|
||||
|
||||
#endif /* ESP_PANEL_USE_TOUCH */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please update the following macros to configure the backlight ////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define ESP_PANEL_USE_BACKLIGHT (0) // 0/1
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please update the following macros to configure the IO expander //////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 0 if not using IO Expander */
|
||||
#define ESP_PANEL_USE_EXPANDER (0) // 0/1
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please utilize the following macros to execute any additional code if required. //////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// #define ESP_PANEL_BEGIN_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_EXPANDER_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_EXPANDER_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_LCD_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_LCD_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_TOUCH_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_TOUCH_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_BACKLIGHT_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_BACKLIGHT_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_END_FUNCTION( panel )
|
||||
|
||||
// *INDENT-OFF*
|
||||
+267
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// *INDENT-OFF*
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// Please update the following macros to configure the LCD panel /////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 1 when using an LCD panel */
|
||||
#define ESP_PANEL_USE_LCD (1) // 0/1
|
||||
|
||||
#if ESP_PANEL_USE_LCD
|
||||
/**
|
||||
* LCD Controller Name.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_NAME GC9503
|
||||
|
||||
/* LCD resolution in pixels */
|
||||
#define ESP_PANEL_LCD_WIDTH (480)
|
||||
#define ESP_PANEL_LCD_HEIGHT (480)
|
||||
|
||||
/* LCD Bus Settings */
|
||||
/**
|
||||
* If set to 1, the bus will skip to initialize the corresponding host. Users need to initialize the host in advance.
|
||||
* It is useful if other devices use the same host. Please ensure that the host is initialized only once.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BUS_SKIP_INIT_HOST (0) // 0/1
|
||||
/**
|
||||
* LCD Bus Type.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BUS_TYPE (ESP_PANEL_BUS_TYPE_RGB)
|
||||
/**
|
||||
* LCD Bus Parameters.
|
||||
*
|
||||
* Please refer to https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/peripherals/lcd.html and
|
||||
* https://docs.espressif.com/projects/esp-iot-solution/en/latest/display/lcd/index.html for more details.
|
||||
*
|
||||
*/
|
||||
#if ESP_PANEL_LCD_BUS_TYPE == ESP_PANEL_BUS_TYPE_RGB
|
||||
|
||||
#define ESP_PANEL_LCD_RGB_CLK_HZ (16 * 1000 * 1000)
|
||||
#define ESP_PANEL_LCD_RGB_HPW (10)
|
||||
#define ESP_PANEL_LCD_RGB_HBP (10)
|
||||
#define ESP_PANEL_LCD_RGB_HFP (20)
|
||||
#define ESP_PANEL_LCD_RGB_VPW (10)
|
||||
#define ESP_PANEL_LCD_RGB_VBP (10)
|
||||
#define ESP_PANEL_LCD_RGB_VFP (10)
|
||||
#define ESP_PANEL_LCD_RGB_PCLK_ACTIVE_NEG (0) // 0: rising edge, 1: falling edge
|
||||
#define ESP_PANEL_LCD_RGB_DATA_WIDTH (16) // 8 | 16
|
||||
#define ESP_PANEL_LCD_RGB_PIXEL_BITS (16) // 24 | 16
|
||||
#define ESP_PANEL_LCD_RGB_FRAME_BUF_NUM (1) // 1/2/3
|
||||
#define ESP_PANEL_LCD_RGB_BOUNCE_BUF_SIZE (ESP_PANEL_LCD_WIDTH * 10)
|
||||
// Bounce buffer size in bytes. This function is used to avoid screen drift.
|
||||
// To enable the bounce buffer, set it to a non-zero value.
|
||||
// Typically set to `ESP_PANEL_LCD_WIDTH * 10`
|
||||
#define ESP_PANEL_LCD_RGB_IO_HSYNC (46)
|
||||
#define ESP_PANEL_LCD_RGB_IO_VSYNC (3)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DE (17) // -1 if not used
|
||||
#define ESP_PANEL_LCD_RGB_IO_PCLK (9)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DISP (-1) // -1 if not used
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA0 (10)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA1 (11)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA2 (12)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA3 (13)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA4 (14)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA5 (21)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA6 (8)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA7 (18)
|
||||
#if ESP_PANEL_LCD_RGB_DATA_WIDTH > 8
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA8 (45)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA9 (38)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA10 (39)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA11 (40)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA12 (41)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA13 (42)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA14 (2)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA15 (1)
|
||||
#endif
|
||||
#if !ESP_PANEL_LCD_BUS_SKIP_INIT_HOST
|
||||
#define ESP_PANEL_LCD_3WIRE_SPI_IO_CS (1)
|
||||
#define ESP_PANEL_LCD_3WIRE_SPI_IO_SCK (2)
|
||||
#define ESP_PANEL_LCD_3WIRE_SPI_IO_SDA (3)
|
||||
#define ESP_PANEL_LCD_3WIRE_SPI_CS_USE_EXPNADER (1) // 0/1
|
||||
#define ESP_PANEL_LCD_3WIRE_SPI_SCL_USE_EXPNADER (1) // 0/1
|
||||
#define ESP_PANEL_LCD_3WIRE_SPI_SDA_USE_EXPNADER (1) // 0/1
|
||||
#define ESP_PANEL_LCD_3WIRE_SPI_SCL_ACTIVE_EDGE (0) // 0: rising edge, 1: falling edge
|
||||
#define ESP_PANEL_LCD_FLAGS_AUTO_DEL_PANEL_IO (1) // Delete the panel IO instance automatically if set to 1.
|
||||
// If the 3-wire SPI pins are sharing other pins of the RGB
|
||||
// interface to save GPIOs, Please set it to 1 to release
|
||||
// the panel IO and its pins (except CS signal).
|
||||
#define ESP_PANEL_LCD_FLAGS_MIRROR_BY_CMD (!ESP_PANEL_LCD_FLAGS_AUTO_DEL_PANEL_IO)
|
||||
// The `mirror()` function will be implemented by LCD
|
||||
// command if set to 1.
|
||||
#endif
|
||||
|
||||
#endif /* ESP_PANEL_LCD_BUS_TYPE */
|
||||
|
||||
/**
|
||||
* LCD Venbdor Initialization Commands.
|
||||
*
|
||||
* Vendor specific initialization can be different between manufacturers, should consult the LCD supplier for
|
||||
* initialization sequence code. Please uncomment and change the following macro definitions. Otherwise, the LCD driver
|
||||
* will use the default initialization sequence code.
|
||||
*
|
||||
* There are two formats for the sequence code:
|
||||
* 1. Raw data: {command, (uint8_t []){ data0, data1, ... }, data_size, delay_ms}
|
||||
* 2. Formater: ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(delay_ms, command, { data0, data1, ... }) and
|
||||
* ESP_PANEL_LCD_CMD_WITH_NONE_PARAM(delay_ms, command)
|
||||
*/
|
||||
// #define ESP_PANEL_LCD_VENDOR_INIT_CMD \
|
||||
// { \
|
||||
// {0xFF, (uint8_t []){0x77, 0x01, 0x00, 0x00, 0x10}, 5, 0}, \
|
||||
// {0xC0, (uint8_t []){0x3B, 0x00}, 2, 0}, \
|
||||
// {0xC1, (uint8_t []){0x0D, 0x02}, 2, 0}, \
|
||||
// {0x29, (uint8_t []){0x00}, 0, 120}, \
|
||||
// or \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xFF, {0x77, 0x01, 0x00, 0x00, 0x10}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC0, {0x3B, 0x00}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC1, {0x0D, 0x02}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_NONE_PARAM(120, 0x29), \
|
||||
// }
|
||||
|
||||
/* LCD Color Settings */
|
||||
/* LCD color depth in bits */
|
||||
#define ESP_PANEL_LCD_COLOR_BITS (18) // 8/16/18/24
|
||||
/*
|
||||
* LCD RGB Element Order. Choose one of the following:
|
||||
* - 0: RGB
|
||||
* - 1: BGR
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BGR_ORDER (0) // 0/1
|
||||
#define ESP_PANEL_LCD_INEVRT_COLOR (0) // 0/1
|
||||
|
||||
/* LCD Transformation Flags */
|
||||
#define ESP_PANEL_LCD_SWAP_XY (0) // 0/1
|
||||
#define ESP_PANEL_LCD_MIRROR_X (0) // 0/1
|
||||
#define ESP_PANEL_LCD_MIRROR_Y (0) // 0/1
|
||||
|
||||
/* LCD Other Settings */
|
||||
/* IO num of RESET pin, set to -1 if not use */
|
||||
#define ESP_PANEL_LCD_IO_RST (-1)
|
||||
#define ESP_PANEL_LCD_RST_LEVEL (0) // 0: low level, 1: high level
|
||||
|
||||
#endif /* ESP_PANEL_USE_LCD */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// Please update the following macros to configure the touch panel ///////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 1 when using an touch panel */
|
||||
#define ESP_PANEL_USE_TOUCH (1) // 0/1
|
||||
#if ESP_PANEL_USE_TOUCH
|
||||
/**
|
||||
* Touch controller name.
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_NAME FT5x06
|
||||
|
||||
/* Touch resolution in pixels */
|
||||
#define ESP_PANEL_TOUCH_H_RES (ESP_PANEL_LCD_WIDTH) // Typically set to the same value as the width of LCD
|
||||
#define ESP_PANEL_TOUCH_V_RES (ESP_PANEL_LCD_HEIGHT) // Typically set to the same value as the height of LCD
|
||||
|
||||
/* Touch Panel Bus Settings */
|
||||
/**
|
||||
* If set to 1, the bus will skip to initialize the corresponding host. Users need to initialize the host in advance.
|
||||
* It is useful if other devices use the same host. Please ensure that the host is initialized only once.
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_BUS_SKIP_INIT_HOST (0) // 0/1
|
||||
/**
|
||||
* Touch panel bus type.
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_BUS_TYPE (ESP_PANEL_BUS_TYPE_I2C)
|
||||
/* Touch panel bus parameters */
|
||||
#if ESP_PANEL_TOUCH_BUS_TYPE == ESP_PANEL_BUS_TYPE_I2C
|
||||
|
||||
#define ESP_PANEL_TOUCH_BUS_HOST_ID (0) // Typically set to 0
|
||||
#define ESP_PANEL_TOUCH_I2C_ADDRESS (0) // Typically set to 0 to use default address
|
||||
#if !ESP_PANEL_TOUCH_BUS_SKIP_INIT_HOST
|
||||
#define ESP_PANEL_TOUCH_I2C_CLK_HZ (400 * 1000)
|
||||
// Typically set to 400K
|
||||
#define ESP_PANEL_TOUCH_I2C_SCL_PULLUP (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_I2C_SDA_PULLUP (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_I2C_IO_SCL (48)
|
||||
#define ESP_PANEL_TOUCH_I2C_IO_SDA (47)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* Touch Transformation Flags */
|
||||
#define ESP_PANEL_TOUCH_SWAP_XY (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_MIRROR_X (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_MIRROR_Y (0) // 0/1
|
||||
|
||||
/* Touch Other Settings */
|
||||
/* IO num of RESET pin, set to -1 if not use */
|
||||
#define ESP_PANEL_TOUCH_IO_RST (-1)
|
||||
#define ESP_PANEL_TOUCH_RST_LEVEL (0) // 0: low level, 1: high level
|
||||
/* IO num of INT pin, set to -1 if not use */
|
||||
#define ESP_PANEL_TOUCH_IO_INT (-1)
|
||||
#define ESP_PANEL_TOUCH_INT_LEVEL (0) // 0: low level, 1: high level
|
||||
|
||||
#endif /* ESP_PANEL_USE_TOUCH */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please update the following macros to configure the backlight ////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define ESP_PANEL_USE_BACKLIGHT (0) // 0/1
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please update the following macros to configure the IO expander //////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 0 if not using IO Expander */
|
||||
#define ESP_PANEL_USE_EXPANDER (1) // 0/1
|
||||
#if ESP_PANEL_USE_EXPANDER
|
||||
/**
|
||||
* IO expander name.
|
||||
*/
|
||||
#define ESP_PANEL_EXPANDER_NAME TCA95xx_8bit
|
||||
|
||||
/* IO expander Settings */
|
||||
/**
|
||||
* If set to 1, the driver will skip to initialize the corresponding host. Users need to initialize the host in advance.
|
||||
* It is useful if other devices use the same host. Please ensure that the host is initialized only once.
|
||||
*/
|
||||
#define ESP_PANEL_EXPANDER_SKIP_INIT_HOST (0) // 0/1
|
||||
/* IO expander parameters */
|
||||
#define ESP_PANEL_EXPANDER_I2C_ADDRESS (0x20)
|
||||
#if !ESP_PANEL_EXPANDER_SKIP_INIT_HOST
|
||||
#define ESP_PANEL_EXPANDER_HOST_ID (0) // Typically set to 0
|
||||
#define ESP_PANEL_EXPANDER_I2C_CLK_HZ (400 * 1000)
|
||||
// Typically set to 400K
|
||||
#define ESP_PANEL_EXPANDER_I2C_SCL_PULLUP (0) // 0/1
|
||||
#define ESP_PANEL_EXPANDER_I2C_SDA_PULLUP (0) // 0/1
|
||||
#define ESP_PANEL_EXPANDER_I2C_IO_SCL (48)
|
||||
#define ESP_PANEL_EXPANDER_I2C_IO_SDA (47)
|
||||
#endif
|
||||
#endif /* ESP_PANEL_USE_EXPANDER */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please utilize the following macros to execute any additional code if required. //////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// #define ESP_PANEL_BEGIN_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_EXPANDER_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_EXPANDER_END_FUNCTION( panel )
|
||||
|
||||
#define ESP_PANEL_BEGIN_LCD_START_FUNCTION( panel ) \
|
||||
{ \
|
||||
ESP_LOGD(TAG, "Run ESP32_S3_LCD_EV_BOARD_V1_5 LCD start function"); \
|
||||
/* For the v1.5 version sub board, need to set `ESP_PANEL_LCD_RGB_IO_VSYNC` to high before initialize LCD */ \
|
||||
gpio_set_direction((gpio_num_t)ESP_PANEL_LCD_RGB_IO_VSYNC, GPIO_MODE_OUTPUT); \
|
||||
gpio_set_level((gpio_num_t)ESP_PANEL_LCD_RGB_IO_VSYNC, 0); \
|
||||
vTaskDelay(pdMS_TO_TICKS(10)); \
|
||||
gpio_set_level((gpio_num_t)ESP_PANEL_LCD_RGB_IO_VSYNC, 1); \
|
||||
vTaskDelay(pdMS_TO_TICKS(120)); \
|
||||
}
|
||||
|
||||
// #define ESP_PANEL_BEGIN_LCD_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_TOUCH_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_TOUCH_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_BACKLIGHT_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_BACKLIGHT_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_END_FUNCTION( panel )
|
||||
|
||||
// *INDENT-OFF*
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// *INDENT-OFF*
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// Please update the following macros to configure the LCD panel /////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 1 when using an LCD panel */
|
||||
#define ESP_PANEL_USE_LCD (1) // 0/1
|
||||
|
||||
#if ESP_PANEL_USE_LCD
|
||||
/**
|
||||
* LCD Controller Name.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_NAME ST7789
|
||||
|
||||
/* LCD resolution in pixels */
|
||||
#define ESP_PANEL_LCD_WIDTH (240)
|
||||
#define ESP_PANEL_LCD_HEIGHT (240)
|
||||
|
||||
/* LCD Bus Settings */
|
||||
/**
|
||||
* If set to 1, the bus will skip to initialize the corresponding host. Users need to initialize the host in advance.
|
||||
* It is useful if other devices use the same host. Please ensure that the host is initialized only once.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BUS_SKIP_INIT_HOST (0) // 0/1
|
||||
/**
|
||||
* LCD Bus Type.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BUS_TYPE (ESP_PANEL_BUS_TYPE_SPI)
|
||||
/**
|
||||
* LCD Bus Parameters.
|
||||
*
|
||||
* Please refer to https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/peripherals/lcd.html and
|
||||
* https://docs.espressif.com/projects/esp-iot-solution/en/latest/display/lcd/index.html for more details.
|
||||
*
|
||||
*/
|
||||
#if ESP_PANEL_LCD_BUS_TYPE == ESP_PANEL_BUS_TYPE_SPI
|
||||
|
||||
#define ESP_PANEL_LCD_BUS_HOST_ID (1) // Typically set to 1
|
||||
#define ESP_PANEL_LCD_SPI_IO_CS (5)
|
||||
#if !ESP_PANEL_LCD_BUS_SKIP_INIT_HOST
|
||||
#define ESP_PANEL_LCD_SPI_IO_SCK (6)
|
||||
#define ESP_PANEL_LCD_SPI_IO_MOSI (7)
|
||||
#define ESP_PANEL_LCD_SPI_IO_MISO (-1) // -1 if not used
|
||||
#endif
|
||||
#define ESP_PANEL_LCD_SPI_IO_DC (4)
|
||||
#define ESP_PANEL_LCD_SPI_MODE (0) // 0/1/2/3, typically set to 0
|
||||
#define ESP_PANEL_LCD_SPI_CLK_HZ (40 * 1000 * 1000)
|
||||
// Should be an integer divisor of 80M, typically set to 40M
|
||||
#define ESP_PANEL_LCD_SPI_TRANS_QUEUE_SZ (10) // Typically set to 10
|
||||
#define ESP_PANEL_LCD_SPI_CMD_BITS (8) // Typically set to 8
|
||||
#define ESP_PANEL_LCD_SPI_PARAM_BITS (8) // Typically set to 8
|
||||
|
||||
#endif /* ESP_PANEL_LCD_BUS_TYPE */
|
||||
|
||||
/**
|
||||
* LCD Venbdor Initialization Commands.
|
||||
*
|
||||
* Vendor specific initialization can be different between manufacturers, should consult the LCD supplier for
|
||||
* initialization sequence code. Please uncomment and change the following macro definitions. Otherwise, the LCD driver
|
||||
* will use the default initialization sequence code.
|
||||
*
|
||||
* There are two formats for the sequence code:
|
||||
* 1. Raw data: {command, (uint8_t []){ data0, data1, ... }, data_size, delay_ms}
|
||||
* 2. Formater: ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(delay_ms, command, { data0, data1, ... }) and
|
||||
* ESP_PANEL_LCD_CMD_WITH_NONE_PARAM(delay_ms, command)
|
||||
*/
|
||||
// #define ESP_PANEL_LCD_VENDOR_INIT_CMD \
|
||||
// { \
|
||||
// {0xFF, (uint8_t []){0x77, 0x01, 0x00, 0x00, 0x10}, 5, 0}, \
|
||||
// {0xC0, (uint8_t []){0x3B, 0x00}, 2, 0}, \
|
||||
// {0xC1, (uint8_t []){0x0D, 0x02}, 2, 0}, \
|
||||
// {0x29, (uint8_t []){0x00}, 0, 120}, \
|
||||
// or \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xFF, {0x77, 0x01, 0x00, 0x00, 0x10}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC0, {0x3B, 0x00}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC1, {0x0D, 0x02}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_NONE_PARAM(120, 0x29), \
|
||||
// }
|
||||
|
||||
/* LCD Color Settings */
|
||||
/* LCD color depth in bits */
|
||||
#define ESP_PANEL_LCD_COLOR_BITS (16) // 8/16/18/24
|
||||
/*
|
||||
* LCD RGB Element Order. Choose one of the following:
|
||||
* - 0: RGB
|
||||
* - 1: BGR
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BGR_ORDER (0) // 0/1
|
||||
#define ESP_PANEL_LCD_INEVRT_COLOR (1) // 0/1
|
||||
|
||||
/* LCD Transformation Flags */
|
||||
#define ESP_PANEL_LCD_SWAP_XY (0) // 0/1
|
||||
#define ESP_PANEL_LCD_MIRROR_X (0) // 0/1
|
||||
#define ESP_PANEL_LCD_MIRROR_Y (0) // 0/1
|
||||
|
||||
/* LCD Other Settings */
|
||||
/* IO num of RESET pin, set to -1 if not use */
|
||||
#define ESP_PANEL_LCD_IO_RST (8)
|
||||
#define ESP_PANEL_LCD_RST_LEVEL (0) // 0: low level, 1: high level
|
||||
|
||||
#endif /* ESP_PANEL_USE_LCD */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// Please update the following macros to configure the touch panel ///////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 1 when using an touch panel */
|
||||
#define ESP_PANEL_USE_TOUCH (0) // 0/1
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please update the following macros to configure the backlight ////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define ESP_PANEL_USE_BACKLIGHT (1) // 0/1
|
||||
#if ESP_PANEL_USE_BACKLIGHT
|
||||
/* IO num of backlight pin */
|
||||
#define ESP_PANEL_BACKLIGHT_IO (9)
|
||||
#define ESP_PANEL_BACKLIGHT_ON_LEVEL (1) // 0: low level, 1: high level
|
||||
|
||||
/* Set to 1 if you want to turn off the backlight after initializing the panel; otherwise, set it to turn on */
|
||||
#define ESP_PANEL_BACKLIGHT_IDLE_OFF (0) // 0: on, 1: off
|
||||
|
||||
/* Set to 1 if use PWM for brightness control */
|
||||
#define ESP_PANEL_LCD_BL_USE_PWM (1) // 0/1
|
||||
#endif /* ESP_PANEL_USE_BACKLIGHT */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please update the following macros to configure the IO expander //////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 0 if not using IO Expander */
|
||||
#define ESP_PANEL_USE_EXPANDER (0) // 0/1
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please utilize the following macros to execute any additional code if required. //////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// #define ESP_PANEL_BEGIN_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_EXPANDER_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_EXPANDER_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_LCD_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_LCD_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_TOUCH_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_TOUCH_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_BACKLIGHT_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_BACKLIGHT_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_END_FUNCTION( panel )
|
||||
|
||||
// *INDENT-OFF*
|
||||
+265
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// *INDENT-OFF*
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// Please update the following macros to configure the LCD panel /////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 1 when using an LCD panel */
|
||||
#define ESP_PANEL_USE_LCD (1) // 0/1
|
||||
|
||||
#if ESP_PANEL_USE_LCD
|
||||
/**
|
||||
* LCD Controller Name
|
||||
*/
|
||||
#define ESP_PANEL_LCD_NAME ST7701
|
||||
|
||||
/* LCD resolution in pixels */
|
||||
#define ESP_PANEL_LCD_WIDTH (480)
|
||||
#define ESP_PANEL_LCD_HEIGHT (480)
|
||||
|
||||
/* LCD Bus Settings */
|
||||
/**
|
||||
* If set to 1, the bus will skip to initialize the corresponding host. Users need to initialize the host in advance.
|
||||
* It is useful if other devices use the same host. Please ensure that the host is initialized only once.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BUS_SKIP_INIT_HOST (0) // 0/1
|
||||
/**
|
||||
* LCD Bus Type.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BUS_TYPE (ESP_PANEL_BUS_TYPE_RGB)
|
||||
/**
|
||||
* LCD Bus Parameters.
|
||||
*
|
||||
* Please refer to https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/peripherals/lcd.html and
|
||||
* https://docs.espressif.com/projects/esp-iot-solution/en/latest/display/lcd/index.html for more details.
|
||||
*
|
||||
*/
|
||||
#if ESP_PANEL_LCD_BUS_TYPE == ESP_PANEL_BUS_TYPE_RGB
|
||||
|
||||
#define ESP_PANEL_LCD_RGB_CLK_HZ (11 * 1000 * 1000)
|
||||
#define ESP_PANEL_LCD_RGB_HPW (10)
|
||||
#define ESP_PANEL_LCD_RGB_HBP (10)
|
||||
#define ESP_PANEL_LCD_RGB_HFP (20)
|
||||
#define ESP_PANEL_LCD_RGB_VPW (10)
|
||||
#define ESP_PANEL_LCD_RGB_VBP (10)
|
||||
#define ESP_PANEL_LCD_RGB_VFP (10)
|
||||
#define ESP_PANEL_LCD_RGB_PCLK_ACTIVE_NEG (0) // 0: rising edge, 1: falling edge
|
||||
#define ESP_PANEL_LCD_RGB_DATA_WIDTH (16) // 8 | 16
|
||||
#define ESP_PANEL_LCD_RGB_PIXEL_BITS (16) // 24 | 16
|
||||
#define ESP_PANEL_LCD_RGB_FRAME_BUF_NUM (1) // 1/2/3
|
||||
#define ESP_PANEL_LCD_RGB_BOUNCE_BUF_SIZE (ESP_PANEL_LCD_WIDTH * 10)
|
||||
// Bounce buffer size in bytes. This function is used to avoid screen drift.
|
||||
// To enable the bounce buffer, set it to a non-zero value.
|
||||
// Typically set to `ESP_PANEL_LCD_WIDTH * 10`
|
||||
#define ESP_PANEL_LCD_RGB_IO_HSYNC (16)
|
||||
#define ESP_PANEL_LCD_RGB_IO_VSYNC (17)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DE (18) // -1 if not used
|
||||
#define ESP_PANEL_LCD_RGB_IO_PCLK (21)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DISP (-1) // -1 if not used
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA0 (4)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA1 (5)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA2 (6)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA3 (7)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA4 (15)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA5 (8)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA6 (20)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA7 (3)
|
||||
#if ESP_PANEL_LCD_RGB_DATA_WIDTH > 8
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA8 (46)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA9 (9)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA10 (10)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA11 (11)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA12 (12)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA13 (13)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA14 (14)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA15 (0)
|
||||
#endif
|
||||
#if !ESP_PANEL_LCD_BUS_SKIP_INIT_HOST
|
||||
#define ESP_PANEL_LCD_3WIRE_SPI_IO_CS (39)
|
||||
#define ESP_PANEL_LCD_3WIRE_SPI_IO_SCK (48)
|
||||
#define ESP_PANEL_LCD_3WIRE_SPI_IO_SDA (47)
|
||||
#define ESP_PANEL_LCD_3WIRE_SPI_CS_USE_EXPNADER (0) // 0/1
|
||||
#define ESP_PANEL_LCD_3WIRE_SPI_SCL_USE_EXPNADER (0) // 0/1
|
||||
#define ESP_PANEL_LCD_3WIRE_SPI_SDA_USE_EXPNADER (0) // 0/1
|
||||
#define ESP_PANEL_LCD_3WIRE_SPI_SCL_ACTIVE_EDGE (0) // 0: rising edge, 1: falling edge
|
||||
#define ESP_PANEL_LCD_FLAGS_AUTO_DEL_PANEL_IO (0) // Delete the panel IO instance automatically if set to 1.
|
||||
// If the 3-wire SPI pins are sharing other pins of the RGB interface to save GPIOs,
|
||||
// Please set it to 1 to release the panel IO and its pins (except CS signal).
|
||||
#define ESP_PANEL_LCD_FLAGS_MIRROR_BY_CMD (!ESP_PANEL_LCD_FLAGS_AUTO_DEL_PANEL_IO)
|
||||
// The `mirror()` function will be implemented by LCD command if set to 1.
|
||||
#endif
|
||||
|
||||
#endif /* ESP_PANEL_LCD_BUS_TYPE */
|
||||
|
||||
/**
|
||||
* LCD Venbdor Initialization Commands.
|
||||
*
|
||||
* Vendor specific initialization can be different between manufacturers, should consult the LCD supplier for
|
||||
* initialization sequence code. Please uncomment and change the following macro definitions. Otherwise, the LCD driver
|
||||
* will use the default initialization sequence code.
|
||||
*
|
||||
* There are two formats for the sequence code:
|
||||
* 1. Raw data: {command, (uint8_t []){ data0, data1, ... }, data_size, delay_ms}
|
||||
* 2. Formater: ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(delay_ms, command, { data0, data1, ... }) and
|
||||
* ESP_PANEL_LCD_CMD_WITH_NONE_PARAM(delay_ms, command)
|
||||
*/
|
||||
#define ESP_PANEL_LCD_VENDOR_INIT_CMD() \
|
||||
{ \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xFF, {0x77, 0x01, 0x00, 0x00, 0x10}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC0, {0x3B, 0x00}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC1, {0x0D, 0x02}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC2, {0x31, 0x05}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xCD, {0x00}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xB0, {0x00, 0x11, 0x18, 0x0E, 0x11, 0x06, 0x07, 0x08, 0x07, 0x22, 0x04, 0x12, 0x0F, 0xAA, 0x31, 0x18}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xB1, {0x00, 0x11, 0x19, 0x0E, 0x12, 0x07, 0x08, 0x08, 0x08, 0x22, 0x04, 0x11, 0x11, 0xA9, 0x32, 0x18}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xFF, {0x77, 0x01, 0x00, 0x00, 0x11}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xB0, {0x60}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xB1, {0x32}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xB2, {0x07}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xB3, {0x80}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xB5, {0x49}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xB7, {0x85}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xB8, {0x21}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC1, {0x78}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC2, {0x78}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xE0, {0x00, 0x1B, 0x02}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xE1, {0x08, 0xA0, 0x00, 0x00, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x44, 0x44}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xE2, {0x11, 0x11, 0x44, 0x44, 0xED, 0xA0, 0x00, 0x00, 0xEC, 0xA0, 0x00, 0x00}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xE3, {0x00, 0x00, 0x11, 0x11}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xE4, {0x44, 0x44}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xE5, {0x0A, 0xE9, 0xD8, 0xA0, 0x0C, 0xEB, 0xD8, 0xA0, 0x0E, 0xED, 0xD8, 0xA0, 0x10, 0xEF, 0xD8, 0xA0}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xE6, {0x00, 0x00, 0x11, 0x11}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xE7, {0x44, 0x44}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xE8, {0x09, 0xE8, 0xD8, 0xA0, 0x0B, 0xEA, 0xD8, 0xA0, 0x0D, 0xEC, 0xD8, 0xA0, 0x0F, 0xEE, 0xD8, 0xA0}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xEB, {0x02, 0x00, 0xE4, 0xE4, 0x88, 0x00, 0x40}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xEC, {0x3C, 0x00}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xED, {0xAB, 0x89, 0x76, 0x54, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x20, 0x45, 0x67, 0x98, 0xBA}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xFF, {0x77, 0x01, 0x00, 0x00, 0x13}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xE5, {0xE4}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xFF, {0x77, 0x01, 0x00, 0x00, 0x00}), \
|
||||
ESP_PANEL_LCD_CMD_WITH_NONE_PARAM(120, 0x11), \
|
||||
}
|
||||
|
||||
/* LCD Color Settings */
|
||||
/* LCD color depth in bits */
|
||||
#define ESP_PANEL_LCD_COLOR_BITS (18) // 8/16/18/24
|
||||
/*
|
||||
* LCD RGB Element Order. Choose one of the following:
|
||||
* - 0: RGB
|
||||
* - 1: BGR
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BGR_ORDER (0) // 0/1
|
||||
#define ESP_PANEL_LCD_INEVRT_COLOR (0) // 0/1
|
||||
|
||||
/* LCD Transformation Flags */
|
||||
#define ESP_PANEL_LCD_SWAP_XY (0) // 0/1
|
||||
#define ESP_PANEL_LCD_MIRROR_X (0) // 0/1
|
||||
#define ESP_PANEL_LCD_MIRROR_Y (0) // 0/1
|
||||
|
||||
/* LCD Other Settings */
|
||||
/* IO num of RESET pin, set to -1 if not use */
|
||||
#define ESP_PANEL_LCD_IO_RST (-1)
|
||||
#define ESP_PANEL_LCD_RST_LEVEL (0) // 0: low level, 1: high level
|
||||
|
||||
#endif /* ESP_PANEL_USE_LCD */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// Please update the following macros to configure the touch panel ///////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 1 when using an touch panel */
|
||||
#define ESP_PANEL_USE_TOUCH (1) // 0/1
|
||||
#if ESP_PANEL_USE_TOUCH
|
||||
/**
|
||||
* Touch controller name
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_NAME GT911
|
||||
|
||||
/* Touch resolution in pixels */
|
||||
#define ESP_PANEL_TOUCH_H_RES (ESP_PANEL_LCD_WIDTH) // Typically set to the same value as the width of LCD
|
||||
#define ESP_PANEL_TOUCH_V_RES (ESP_PANEL_LCD_HEIGHT) // Typically set to the same value as the height of LCD
|
||||
|
||||
/* Touch Panel Bus Settings */
|
||||
/**
|
||||
* If set to 1, the bus will skip to initialize the corresponding host. Users need to initialize the host in advance.
|
||||
* It is useful if other devices use the same host. Please ensure that the host is initialized only once.
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_BUS_SKIP_INIT_HOST (0) // 0/1
|
||||
/**
|
||||
* Touch panel bus type
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_BUS_TYPE (ESP_PANEL_BUS_TYPE_I2C)
|
||||
/* Touch panel bus parameters */
|
||||
#if ESP_PANEL_TOUCH_BUS_TYPE == ESP_PANEL_BUS_TYPE_I2C
|
||||
|
||||
#define ESP_PANEL_TOUCH_BUS_HOST_ID (0) // Typically set to 0
|
||||
#define ESP_PANEL_TOUCH_I2C_ADDRESS (0) // Typically set to 0 to use default address
|
||||
#if !ESP_PANEL_TOUCH_BUS_SKIP_INIT_HOST
|
||||
#define ESP_PANEL_TOUCH_I2C_CLK_HZ (400 * 1000)
|
||||
// Typically set to 400K
|
||||
#define ESP_PANEL_TOUCH_I2C_SCL_PULLUP (1) // 0/1
|
||||
#define ESP_PANEL_TOUCH_I2C_SDA_PULLUP (1) // 0/1
|
||||
#define ESP_PANEL_TOUCH_I2C_IO_SCL (45)
|
||||
#define ESP_PANEL_TOUCH_I2C_IO_SDA (19)
|
||||
#endif
|
||||
|
||||
#endif /* ESP_PANEL_TOUCH_BUS_TYPE */
|
||||
|
||||
/* Touch Transformation Flags */
|
||||
#define ESP_PANEL_TOUCH_SWAP_XY (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_MIRROR_X (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_MIRROR_Y (0) // 0/1
|
||||
|
||||
/* Touch Other Settings */
|
||||
/* IO num of RESET pin, set to -1 if not use */
|
||||
#define ESP_PANEL_TOUCH_IO_RST (-1)
|
||||
#define ESP_PANEL_TOUCH_RST_LEVEL (0) // 0: low level, 1: high level
|
||||
/* IO num of INT pin, set to -1 if not use */
|
||||
#define ESP_PANEL_TOUCH_IO_INT (-1)
|
||||
#define ESP_PANEL_TOUCH_INT_LEVEL (0) // 0: low level, 1: high level
|
||||
|
||||
#endif /* ESP_PANEL_USE_TOUCH */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please update the following macros to configure the backlight ////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define ESP_PANEL_USE_BACKLIGHT (1) // 0/1
|
||||
#if ESP_PANEL_USE_BACKLIGHT
|
||||
/* IO num of backlight pin */
|
||||
#define ESP_PANEL_BACKLIGHT_IO (38)
|
||||
#define ESP_PANEL_BACKLIGHT_ON_LEVEL (1) // 0: low level, 1: high level
|
||||
|
||||
/* Set to 1 if turn off the backlight after initializing the panel; otherwise, set it to turn on */
|
||||
#define ESP_PANEL_BACKLIGHT_IDLE_OFF (0) // 0: on, 1: off
|
||||
|
||||
/* Set to 1 if use PWM for brightness control */
|
||||
#define ESP_PANEL_LCD_BL_USE_PWM (1) // 0/1
|
||||
#endif /* ESP_PANEL_USE_BACKLIGHT */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please update the following macros to configure the IO expander //////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 0 if not using IO Expander */
|
||||
#define ESP_PANEL_USE_EXPANDER (0) // 0/1
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please utilize the following macros to execute any additional code if required. //////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// #define ESP_PANEL_BEGIN_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_EXPANDER_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_EXPANDER_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_LCD_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_LCD_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_TOUCH_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_TOUCH_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_BACKLIGHT_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_BACKLIGHT_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_END_FUNCTION( panel )
|
||||
|
||||
// *INDENT-OFF*
|
||||
+244
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// *INDENT-OFF*
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// Please update the following macros to configure the LCD panel /////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 1 when using an LCD panel */
|
||||
#define ESP_PANEL_USE_LCD (1) // 0/1
|
||||
|
||||
#if ESP_PANEL_USE_LCD
|
||||
/**
|
||||
* LCD Controller Name.
|
||||
* LCD Controller of M5Core2 is ILI9342C, but the driver is compatible with ILI9341.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_NAME ILI9341
|
||||
|
||||
/* LCD resolution in pixels */
|
||||
#define ESP_PANEL_LCD_WIDTH (320)
|
||||
#define ESP_PANEL_LCD_HEIGHT (240)
|
||||
|
||||
/* LCD Bus Settings */
|
||||
/**
|
||||
* If set to 1, the bus will skip to initialize the corresponding host. Users need to initialize the host in advance.
|
||||
* It is useful if other devices use the same host. Please ensure that the host is initialized only once.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BUS_SKIP_INIT_HOST (0) // 0/1
|
||||
/**
|
||||
* LCD Bus Type.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BUS_TYPE (ESP_PANEL_BUS_TYPE_SPI)
|
||||
/**
|
||||
* LCD Bus Parameters.
|
||||
*
|
||||
* Please refer to https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/peripherals/lcd.html and
|
||||
* https://docs.espressif.com/projects/esp-iot-solution/en/latest/display/lcd/index.html for more details.
|
||||
*
|
||||
*/
|
||||
#if ESP_PANEL_LCD_BUS_TYPE == ESP_PANEL_BUS_TYPE_SPI
|
||||
|
||||
#define ESP_PANEL_LCD_BUS_HOST_ID (1) // Typically set to 1
|
||||
#define ESP_PANEL_LCD_SPI_IO_CS (5)
|
||||
#if !ESP_PANEL_LCD_BUS_SKIP_INIT_HOST
|
||||
#define ESP_PANEL_LCD_SPI_IO_SCK (18)
|
||||
#define ESP_PANEL_LCD_SPI_IO_MOSI (23)
|
||||
#define ESP_PANEL_LCD_SPI_IO_MISO (-1) // -1 if not used
|
||||
#endif
|
||||
#define ESP_PANEL_LCD_SPI_IO_DC (15)
|
||||
#define ESP_PANEL_LCD_SPI_MODE (0) // 0/1/2/3, typically set to 0
|
||||
#define ESP_PANEL_LCD_SPI_CLK_HZ (40 * 1000 * 1000)
|
||||
// Should be an integer divisor of 80M, typically set to 40M
|
||||
#define ESP_PANEL_LCD_SPI_TRANS_QUEUE_SZ (10) // Typically set to 10
|
||||
#define ESP_PANEL_LCD_SPI_CMD_BITS (8) // Typically set to 8
|
||||
#define ESP_PANEL_LCD_SPI_PARAM_BITS (8) // Typically set to 8
|
||||
|
||||
#endif /* ESP_PANEL_LCD_BUS_TYPE */
|
||||
|
||||
/**
|
||||
* LCD Venbdor Initialization Commands.
|
||||
*
|
||||
* Vendor specific initialization can be different between manufacturers, should consult the LCD supplier for
|
||||
* initialization sequence code. Please uncomment and change the following macro definitions. Otherwise, the LCD driver
|
||||
* will use the default initialization sequence code.
|
||||
*
|
||||
* There are two formats for the sequence code:
|
||||
* 1. Raw data: {command, (uint8_t []){ data0, data1, ... }, data_size, delay_ms}
|
||||
* 2. Formater: ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(delay_ms, command, { data0, data1, ... }) and
|
||||
* ESP_PANEL_LCD_CMD_WITH_NONE_PARAM(delay_ms, command)
|
||||
*/
|
||||
// #define ESP_PANEL_LCD_VENDOR_INIT_CMD \
|
||||
// { \
|
||||
// {0xFF, (uint8_t []){0x77, 0x01, 0x00, 0x00, 0x10}, 5, 0}, \
|
||||
// {0xC0, (uint8_t []){0x3B, 0x00}, 2, 0}, \
|
||||
// {0xC1, (uint8_t []){0x0D, 0x02}, 2, 0}, \
|
||||
// {0x29, (uint8_t []){0x00}, 0, 120}, \
|
||||
// or \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xFF, {0x77, 0x01, 0x00, 0x00, 0x10}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC0, {0x3B, 0x00}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC1, {0x0D, 0x02}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_NONE_PARAM(120, 0x29), \
|
||||
// }
|
||||
|
||||
/* LCD Color Settings */
|
||||
/* LCD color depth in bits */
|
||||
#define ESP_PANEL_LCD_COLOR_BITS (16) // 8/16/18/24
|
||||
/*
|
||||
* LCD RGB Element Order. Choose one of the following:
|
||||
* - 0: RGB
|
||||
* - 1: BGR
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BGR_ORDER (1) // 0/1
|
||||
#define ESP_PANEL_LCD_INEVRT_COLOR (1) // 0/1
|
||||
|
||||
/* LCD Transformation Flags */
|
||||
#define ESP_PANEL_LCD_SWAP_XY (0) // 0/1
|
||||
#define ESP_PANEL_LCD_MIRROR_X (0) // 0/1
|
||||
#define ESP_PANEL_LCD_MIRROR_Y (0) // 0/1
|
||||
|
||||
/* LCD Other Settings */
|
||||
/* IO num of RESET pin, set to -1 if not use */
|
||||
#define ESP_PANEL_LCD_IO_RST (-1)
|
||||
#define ESP_PANEL_LCD_RST_LEVEL (0) // 0: low level, 1: high level
|
||||
|
||||
#endif /* ESP_PANEL_USE_LCD */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// Please update the following macros to configure the touch panel ///////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 1 when using an touch panel */
|
||||
#define ESP_PANEL_USE_TOUCH (1) // 0/1
|
||||
#if ESP_PANEL_USE_TOUCH
|
||||
/**
|
||||
* Touch controller name.
|
||||
* Touch Controller of M5Core2 is FT6336U, but the driver is compatible with FT5x06.
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_NAME FT5x06
|
||||
|
||||
/* Touch resolution in pixels */
|
||||
#define ESP_PANEL_TOUCH_H_RES (ESP_PANEL_LCD_WIDTH) // Typically set to the same value as the width of LCD
|
||||
#define ESP_PANEL_TOUCH_V_RES (ESP_PANEL_LCD_HEIGHT) // Typically set to the same value as the height of LCD
|
||||
|
||||
/* Touch Panel Bus Settings */
|
||||
/**
|
||||
* If set to 1, the bus will skip to initialize the corresponding host. Users need to initialize the host in advance.
|
||||
* It is useful if other devices use the same host. Please ensure that the host is initialized only once.
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_BUS_SKIP_INIT_HOST (0) // 0/1
|
||||
/**
|
||||
* Touch panel bus type.
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_BUS_TYPE (ESP_PANEL_BUS_TYPE_I2C)
|
||||
/* Touch panel bus parameters */
|
||||
#if ESP_PANEL_TOUCH_BUS_TYPE == ESP_PANEL_BUS_TYPE_I2C
|
||||
|
||||
#define ESP_PANEL_TOUCH_BUS_HOST_ID (0) // Typically set to 0
|
||||
#define ESP_PANEL_TOUCH_I2C_ADDRESS (0) // Typically set to 0 to use default address
|
||||
#if !ESP_PANEL_TOUCH_BUS_SKIP_INIT_HOST
|
||||
#define ESP_PANEL_TOUCH_I2C_CLK_HZ (400 * 1000)
|
||||
// Typically set to 400K
|
||||
#define ESP_PANEL_TOUCH_I2C_SCL_PULLUP (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_I2C_SDA_PULLUP (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_I2C_IO_SCL (22)
|
||||
#define ESP_PANEL_TOUCH_I2C_IO_SDA (21)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* Touch Transformation Flags */
|
||||
#define ESP_PANEL_TOUCH_SWAP_XY (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_MIRROR_X (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_MIRROR_Y (0) // 0/1
|
||||
|
||||
/* Touch Other Settings */
|
||||
/* IO num of RESET pin, set to -1 if not use */
|
||||
#define ESP_PANEL_TOUCH_IO_RST (-1)
|
||||
#define ESP_PANEL_TOUCH_RST_LEVEL (0) // 0: low level, 1: high level
|
||||
/* IO num of INT pin, set to -1 if not use */
|
||||
#define ESP_PANEL_TOUCH_IO_INT (39)
|
||||
#define ESP_PANEL_TOUCH_INT_LEVEL (0) // 0: low level, 1: high level
|
||||
|
||||
#endif /* ESP_PANEL_USE_TOUCH */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please update the following macros to configure the backlight ////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define ESP_PANEL_USE_BACKLIGHT (0) // 0/1
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please update the following macros to configure the IO expander //////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 0 if not using IO Expander */
|
||||
#define ESP_PANEL_USE_EXPANDER (0) // 0/1
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please utilize the following macros to execute any additional code if required. //////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// #define ESP_PANEL_BEGIN_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_EXPANDER_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_EXPANDER_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_LCD_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_LCD_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_TOUCH_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_TOUCH_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_BACKLIGHT_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_BACKLIGHT_END_FUNCTION( panel )
|
||||
#define ESP_PANEL_BEGIN_END_FUNCTION( panel ) \
|
||||
{ \
|
||||
static const uint8_t AXP_ADDR = 0x34; \
|
||||
static const uint8_t I2C_MASTER_TIMEOUT_MS = 1000; \
|
||||
static i2c_port_t i2c_master_port = I2C_NUM_0; \
|
||||
\
|
||||
uint8_t device_id = 0; \
|
||||
uint8_t read_value = 0; \
|
||||
uint8_t write_value = 0; \
|
||||
uint8_t reg_addr = 0; \
|
||||
uint8_t write_buf[2] = {0}; \
|
||||
\
|
||||
reg_addr = 0x03; \
|
||||
i2c_master_write_read_device(i2c_master_port, AXP_ADDR, ®_addr, 1, &device_id, 1, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS); \
|
||||
if (device_id == 0x03) { \
|
||||
reg_addr = 0x28; \
|
||||
i2c_master_write_read_device(i2c_master_port, AXP_ADDR, ®_addr, 1, &read_value, 1, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS); \
|
||||
write_value = (read_value & 0x0F) | ((((3300 - 1800) / 100) & 0x0F) << 4); \
|
||||
write_buf[0] = 0x28; \
|
||||
write_buf[1] = write_value; \
|
||||
i2c_master_write_to_device(i2c_master_port, AXP_ADDR, write_buf, sizeof(write_buf), I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS); \
|
||||
\
|
||||
reg_addr = 0x12; \
|
||||
i2c_master_write_read_device(i2c_master_port, AXP_ADDR, ®_addr, 1, &read_value, 1, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS); \
|
||||
write_value = (read_value | (0x01 << 2)); \
|
||||
write_buf[0] = 0x12; \
|
||||
write_buf[1] = write_value; \
|
||||
i2c_master_write_to_device(i2c_master_port, AXP_ADDR, write_buf, sizeof(write_buf), I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS); \
|
||||
\
|
||||
reg_addr = 0x12; \
|
||||
i2c_master_write_read_device(i2c_master_port, AXP_ADDR, ®_addr, 1, &read_value, 1, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS); \
|
||||
write_value = (read_value | (0x01 << 1)); \
|
||||
write_buf[0] = 0x12; \
|
||||
write_buf[1] = write_value; \
|
||||
i2c_master_write_to_device(i2c_master_port, AXP_ADDR, write_buf, sizeof(write_buf), I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS); \
|
||||
} else if (device_id == 0x4A) { \
|
||||
reg_addr = 0x90; \
|
||||
read_value = device_id; \
|
||||
i2c_master_write_read_device(i2c_master_port, AXP_ADDR, ®_addr, 1, &read_value, 1, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS); \
|
||||
write_value = (read_value | (1 << 4)); \
|
||||
write_buf[0] = 0x90; \
|
||||
write_buf[1] = write_value; \
|
||||
i2c_master_write_to_device(i2c_master_port, AXP_ADDR, write_buf, sizeof(write_buf), I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS); \
|
||||
\
|
||||
write_value = (3000 - 500) / 100; \
|
||||
write_buf[0] = 0x94; \
|
||||
write_buf[1] = write_value; \
|
||||
i2c_master_write_to_device(i2c_master_port, AXP_ADDR, write_buf, sizeof(write_buf), I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS); \
|
||||
} else { \
|
||||
\
|
||||
} \
|
||||
}
|
||||
// *INDENT-OFF*
|
||||
+249
@@ -0,0 +1,249 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <Arduino.h>
|
||||
#include <ESP_Panel_Library.h>
|
||||
// *INDENT-OFF*
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// Please update the following macros to configure the LCD panel /////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 1 when using an LCD panel */
|
||||
#define ESP_PANEL_USE_LCD (1) // 0/1
|
||||
|
||||
#if ESP_PANEL_USE_LCD
|
||||
/**
|
||||
* LCD Controller Name.
|
||||
* LCD Controller of M5CoreS3 is ILI9342C, but the driver is compatible with ILI9341.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_NAME ILI9341
|
||||
|
||||
/* LCD resolution in pixels */
|
||||
#define ESP_PANEL_LCD_WIDTH (320)
|
||||
#define ESP_PANEL_LCD_HEIGHT (240)
|
||||
|
||||
/* LCD Bus Settings */
|
||||
/**
|
||||
* If set to 1, the bus will skip to initialize the corresponding host. Users need to initialize the host in advance.
|
||||
* It is useful if other devices use the same host. Please ensure that the host is initialized only once.
|
||||
*
|
||||
* Set to 1 if only the RGB interface is used without the 3-wire SPI interface,
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BUS_SKIP_INIT_HOST (0) // 0/1
|
||||
/**
|
||||
* LCD Bus Type.
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BUS_TYPE (ESP_PANEL_BUS_TYPE_SPI)
|
||||
/**
|
||||
* LCD Bus Parameters.
|
||||
*
|
||||
* Please refer to https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/peripherals/lcd.html and
|
||||
* https://docs.espressif.com/projects/esp-iot-solution/en/latest/display/lcd/index.html for more details.
|
||||
*
|
||||
*/
|
||||
#if ESP_PANEL_LCD_BUS_TYPE == ESP_PANEL_BUS_TYPE_SPI
|
||||
|
||||
#define ESP_PANEL_LCD_BUS_HOST_ID (1) // Typically set to 1
|
||||
#define ESP_PANEL_LCD_SPI_IO_CS (3)
|
||||
#if !ESP_PANEL_LCD_BUS_SKIP_INIT_HOST
|
||||
#define ESP_PANEL_LCD_SPI_IO_SCK (36)
|
||||
#define ESP_PANEL_LCD_SPI_IO_MOSI (37)
|
||||
#define ESP_PANEL_LCD_SPI_IO_MISO (-1) // -1 if not used
|
||||
#endif
|
||||
#define ESP_PANEL_LCD_SPI_IO_DC (35)
|
||||
#define ESP_PANEL_LCD_SPI_MODE (0) // 0/1/2/3, typically set to 0
|
||||
#define ESP_PANEL_LCD_SPI_CLK_HZ (40 * 1000 * 1000)
|
||||
// Should be an integer divisor of 80M, typically set to 40M
|
||||
#define ESP_PANEL_LCD_SPI_TRANS_QUEUE_SZ (10) // Typically set to 10
|
||||
#define ESP_PANEL_LCD_SPI_CMD_BITS (8) // Typically set to 8
|
||||
#define ESP_PANEL_LCD_SPI_PARAM_BITS (8) // Typically set to 8
|
||||
|
||||
#endif /* ESP_PANEL_LCD_BUS_TYPE */
|
||||
|
||||
/**
|
||||
* LCD Venbdor Initialization Commands.
|
||||
*
|
||||
* Vendor specific initialization can be different between manufacturers, should consult the LCD supplier for
|
||||
* initialization sequence code. Please uncomment and change the following macro definitions. Otherwise, the LCD driver
|
||||
* will use the default initialization sequence code.
|
||||
*
|
||||
* There are two formats for the sequence code:
|
||||
* 1. Raw data: {command, (uint8_t []){ data0, data1, ... }, data_size, delay_ms}
|
||||
* 2. Formater: ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(delay_ms, command, { data0, data1, ... }) and
|
||||
* ESP_PANEL_LCD_CMD_WITH_NONE_PARAM(delay_ms, command)
|
||||
*/
|
||||
// #define ESP_PANEL_LCD_VENDOR_INIT_CMD() \
|
||||
// { \
|
||||
// {0xFF, (uint8_t []){0x77, 0x01, 0x00, 0x00, 0x10}, 5, 0}, \
|
||||
// {0xC0, (uint8_t []){0x3B, 0x00}, 2, 0}, \
|
||||
// {0xC1, (uint8_t []){0x0D, 0x02}, 2, 0}, \
|
||||
// {0x29, (uint8_t []){0x00}, 0, 120}, \
|
||||
// or \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xFF, {0x77, 0x01, 0x00, 0x00, 0x10}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC0, {0x3B, 0x00}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC1, {0x0D, 0x02}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_NONE_PARAM(120, 0x29), \
|
||||
// }
|
||||
|
||||
/* LCD Color Settings */
|
||||
/* LCD color depth in bits */
|
||||
#define ESP_PANEL_LCD_COLOR_BITS (16) // 8/16/18/24
|
||||
/*
|
||||
* LCD RGB Element Order. Choose one of the following:
|
||||
* - 0: RGB
|
||||
* - 1: BGR
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BGR_ORDER (1) // 0/1
|
||||
#define ESP_PANEL_LCD_INEVRT_COLOR (1) // 0/1
|
||||
|
||||
/* LCD Transformation Flags */
|
||||
#define ESP_PANEL_LCD_SWAP_XY (0) // 0/1
|
||||
#define ESP_PANEL_LCD_MIRROR_X (0) // 0/1
|
||||
#define ESP_PANEL_LCD_MIRROR_Y (0) // 0/1
|
||||
|
||||
/* LCD Other Settings */
|
||||
/* IO num of RESET pin, set to -1 if not use */
|
||||
#define ESP_PANEL_LCD_IO_RST (-1)
|
||||
#define ESP_PANEL_LCD_RST_LEVEL (0) // 0: low level, 1: high level
|
||||
|
||||
#endif /* ESP_PANEL_USE_LCD */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// Please update the following macros to configure the touch panel ///////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 1 when using an touch panel */
|
||||
#define ESP_PANEL_USE_TOUCH (1) // 0/1
|
||||
#if ESP_PANEL_USE_TOUCH
|
||||
/**
|
||||
* Touch controller name.
|
||||
* Touch Controller of M5CoreS3 is FT6336U, but the driver is compatible with FT5x06.
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_NAME FT5x06
|
||||
|
||||
/* Touch resolution in pixels */
|
||||
#define ESP_PANEL_TOUCH_H_RES (ESP_PANEL_LCD_WIDTH) // Typically set to the same value as the width of LCD
|
||||
#define ESP_PANEL_TOUCH_V_RES (ESP_PANEL_LCD_HEIGHT) // Typically set to the same value as the height of LCD
|
||||
|
||||
/* Touch Panel Bus Settings */
|
||||
/**
|
||||
* If set to 1, the bus will skip to initialize the corresponding host. Users need to initialize the host in advance.
|
||||
* It is useful if other devices use the same host. Please ensure that the host is initialized only once.
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_BUS_SKIP_INIT_HOST (0) // 0/1
|
||||
/**
|
||||
* Touch panel bus type.
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_BUS_TYPE (ESP_PANEL_BUS_TYPE_I2C)
|
||||
/* Touch panel bus parameters */
|
||||
#if ESP_PANEL_TOUCH_BUS_TYPE == ESP_PANEL_BUS_TYPE_I2C
|
||||
|
||||
#define ESP_PANEL_TOUCH_BUS_HOST_ID (0) // Typically set to 0
|
||||
#define ESP_PANEL_TOUCH_I2C_ADDRESS (0) // Typically set to 0 to use default address
|
||||
#if !ESP_PANEL_TOUCH_BUS_SKIP_INIT_HOST
|
||||
#define ESP_PANEL_TOUCH_I2C_CLK_HZ (400 * 1000)
|
||||
// Typically set to 400K
|
||||
#define ESP_PANEL_TOUCH_I2C_SCL_PULLUP (1) // 0/1
|
||||
#define ESP_PANEL_TOUCH_I2C_SDA_PULLUP (1) // 0/1
|
||||
#define ESP_PANEL_TOUCH_I2C_IO_SCL (11)
|
||||
#define ESP_PANEL_TOUCH_I2C_IO_SDA (12)
|
||||
#endif
|
||||
|
||||
#endif /* ESP_PANEL_TOUCH_BUS_TYPE */
|
||||
|
||||
/* Touch Transformation Flags */
|
||||
#define ESP_PANEL_TOUCH_SWAP_XY (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_MIRROR_X (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_MIRROR_Y (0) // 0/1
|
||||
|
||||
/* Touch Other Settings */
|
||||
/* IO num of RESET pin, set to -1 if not use */
|
||||
#define ESP_PANEL_TOUCH_IO_RST (-1)
|
||||
#define ESP_PANEL_TOUCH_RST_LEVEL (0) // 0: low level, 1: high level
|
||||
/* IO num of INT pin, set to -1 if not use */
|
||||
#define ESP_PANEL_TOUCH_IO_INT (-1)
|
||||
#define ESP_PANEL_TOUCH_INT_LEVEL (0) // 0: low level, 1: high level
|
||||
|
||||
#endif /* ESP_PANEL_USE_TOUCH */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please update the following macros to configure the backlight ////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define ESP_PANEL_USE_BACKLIGHT (0) // 0/1
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please update the following macros to configure the IO expander //////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 0 if not using IO Expander */
|
||||
#define ESP_PANEL_USE_EXPANDER (0) // 0/1
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please utilize the following macros to execute any additional code if required. //////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define ESP_PANEL_BEGIN_START_FUNCTION( panel ) \
|
||||
{ \
|
||||
const uint8_t AXP_ADDR = 0x34; \
|
||||
const uint8_t I2C_MASTER_TIMEOUT_MS = 1000; \
|
||||
const i2c_port_t i2c_master_port = I2C_NUM_0; \
|
||||
\
|
||||
uint8_t read_value = 0; \
|
||||
uint8_t write_value = 0; \
|
||||
uint8_t reg_addr = 0; \
|
||||
uint8_t write_buf[2] = {0}; \
|
||||
\
|
||||
ESP_LOGD(TAG, "Start AXP2101 Power"); \
|
||||
write_buf[0] = 0x90; \
|
||||
write_buf[1] = 0xBF; \
|
||||
i2c_master_write_to_device(i2c_master_port, AXP_ADDR, write_buf, sizeof(write_buf), pdMS_TO_TICKS(I2C_MASTER_TIMEOUT_MS)); \
|
||||
write_buf[0] = 0x02; \
|
||||
write_buf[1] = 0b00000101; \
|
||||
i2c_master_write_to_device(i2c_master_port, 0x58, write_buf, sizeof(write_buf), pdMS_TO_TICKS(I2C_MASTER_TIMEOUT_MS)); \
|
||||
write_buf[0] = 0x03; \
|
||||
write_buf[1] = 0b00000011; \
|
||||
i2c_master_write_to_device(i2c_master_port, 0x58, write_buf, sizeof(write_buf), pdMS_TO_TICKS(I2C_MASTER_TIMEOUT_MS)); \
|
||||
write_buf[0] = 0x04; \
|
||||
write_buf[1] = 0b00011000; \
|
||||
i2c_master_write_to_device(i2c_master_port, 0x58, write_buf, sizeof(write_buf), pdMS_TO_TICKS(I2C_MASTER_TIMEOUT_MS)); \
|
||||
write_buf[0] = 0x05; \
|
||||
write_buf[1] = 0b00001100; \
|
||||
i2c_master_write_to_device(i2c_master_port, 0x58, write_buf, sizeof(write_buf), pdMS_TO_TICKS(I2C_MASTER_TIMEOUT_MS)); \
|
||||
write_buf[0] = 0x11; \
|
||||
write_buf[1] = 0b00010000; \
|
||||
i2c_master_write_to_device(i2c_master_port, 0x58, write_buf, sizeof(write_buf), pdMS_TO_TICKS(I2C_MASTER_TIMEOUT_MS)); \
|
||||
write_buf[0] = 0x12; \
|
||||
write_buf[1] = 0b11111111; \
|
||||
i2c_master_write_to_device(i2c_master_port, 0x58, write_buf, sizeof(write_buf), pdMS_TO_TICKS(I2C_MASTER_TIMEOUT_MS)); \
|
||||
write_buf[0] = 0x13; \
|
||||
write_buf[1] = 0b11111111; \
|
||||
i2c_master_write_to_device(i2c_master_port, 0x58, write_buf, sizeof(write_buf), pdMS_TO_TICKS(I2C_MASTER_TIMEOUT_MS)); \
|
||||
\
|
||||
}
|
||||
// #define ESP_PANEL_BEGIN_EXPANDER_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_EXPANDER_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_LCD_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_LCD_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_TOUCH_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_TOUCH_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_BACKLIGHT_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_BACKLIGHT_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_END_FUNCTION( panel )
|
||||
|
||||
/**
|
||||
* Do not change the following versions, they are used to check if the configurations in this file are compatible with
|
||||
* the current version of `ESP_Panel_Board_Custom.h` in the library. The detailed rules are as follows:
|
||||
*
|
||||
* 1. If the major version is not consistent, then the configurations in this file are incompatible with the library
|
||||
* and must be replaced with the file from the library.
|
||||
* 2. If the minor version is not consistent, this file might be missing some new configurations, which will be set to
|
||||
* default values. It is recommended to replace it with the file from the library.
|
||||
* 3. Even if the patch version is not consistent, it will not affect normal functionality.
|
||||
*
|
||||
*/
|
||||
#define ESP_PANEL_BOARD_CUSTOM_FILE_VERSION_MAJOR 0
|
||||
#define ESP_PANEL_BOARD_CUSTOM_FILE_VERSION_MINOR 1
|
||||
#define ESP_PANEL_BOARD_CUSTOM_FILE_VERSION_PATCH 1
|
||||
|
||||
// *INDENT-OFF*
|
||||
+362
@@ -0,0 +1,362 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// *INDENT-OFF*
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// Please update the following macros to configure the LCD panel /////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 1 when using an LCD panel */
|
||||
#define ESP_PANEL_USE_LCD (1) // 0/1
|
||||
|
||||
#if ESP_PANEL_USE_LCD
|
||||
/**
|
||||
* LCD Controller Name. Choose one of the following:
|
||||
* - GC9A01, GC9B71, GC9503
|
||||
* - ILI9341
|
||||
* - NV3022B
|
||||
* - SH8601
|
||||
* - SPD2010
|
||||
* - ST7262, ST7701, ST7789, ST7796, ST77916, ST77922
|
||||
*/
|
||||
#define ESP_PANEL_LCD_NAME GC9A01
|
||||
|
||||
/* LCD resolution in pixels */
|
||||
#define ESP_PANEL_LCD_WIDTH (240)
|
||||
#define ESP_PANEL_LCD_HEIGHT (240)
|
||||
|
||||
/* LCD Bus Settings */
|
||||
/**
|
||||
* If set to 1, the bus will skip to initialize the corresponding host. Users need to initialize the host in advance.
|
||||
* It is useful if other devices use the same host. Please ensure that the host is initialized only once.
|
||||
*
|
||||
* Set to 1 if only the RGB interface is used without the 3-wire SPI interface,
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BUS_SKIP_INIT_HOST (0) // 0/1
|
||||
/**
|
||||
* LCD Bus Type. Choose one of the following:
|
||||
* - ESP_PANEL_BUS_TYPE_I2C (not ready)
|
||||
* - ESP_PANEL_BUS_TYPE_SPI
|
||||
* - ESP_PANEL_BUS_TYPE_QSPI
|
||||
* - ESP_PANEL_BUS_TYPE_I80 (not ready)
|
||||
* - ESP_PANEL_BUS_TYPE_RGB (only supported for ESP32-S3)
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BUS_TYPE (ESP_PANEL_BUS_TYPE_SPI)
|
||||
/**
|
||||
* LCD Bus Parameters.
|
||||
*
|
||||
* Please refer to https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/peripherals/lcd.html and
|
||||
* https://docs.espressif.com/projects/esp-iot-solution/en/latest/display/lcd/index.html for more details.
|
||||
*
|
||||
*/
|
||||
#if ESP_PANEL_LCD_BUS_TYPE == ESP_PANEL_BUS_TYPE_SPI
|
||||
|
||||
#define ESP_PANEL_LCD_BUS_HOST_ID (1) // Typically set to 1
|
||||
#define ESP_PANEL_LCD_SPI_IO_CS (7)
|
||||
#if !ESP_PANEL_LCD_BUS_SKIP_INIT_HOST
|
||||
#define ESP_PANEL_LCD_SPI_IO_SCK (6)
|
||||
#define ESP_PANEL_LCD_SPI_IO_MOSI (5)
|
||||
#define ESP_PANEL_LCD_SPI_IO_MISO (-1) // -1 if not used
|
||||
#endif
|
||||
#define ESP_PANEL_LCD_SPI_IO_DC (4)
|
||||
#define ESP_PANEL_LCD_SPI_MODE (0) // 0/1/2/3, typically set to 0
|
||||
#define ESP_PANEL_LCD_SPI_CLK_HZ (40 * 1000 * 1000)
|
||||
// Should be an integer divisor of 80M, typically set to 40M
|
||||
#define ESP_PANEL_LCD_SPI_TRANS_QUEUE_SZ (10) // Typically set to 10
|
||||
#define ESP_PANEL_LCD_SPI_CMD_BITS (8) // Typically set to 8
|
||||
#define ESP_PANEL_LCD_SPI_PARAM_BITS (8) // Typically set to 8
|
||||
|
||||
#elif ESP_PANEL_LCD_BUS_TYPE == ESP_PANEL_BUS_TYPE_QSPI
|
||||
|
||||
#define ESP_PANEL_LCD_BUS_HOST_ID (1) // Typically set to 1
|
||||
#define ESP_PANEL_LCD_SPI_IO_CS (5)
|
||||
#if !ESP_PANEL_LCD_BUS_SKIP_INIT_HOST
|
||||
#define ESP_PANEL_LCD_SPI_IO_SCK (9)
|
||||
#define ESP_PANEL_LCD_SPI_IO_DATA0 (10)
|
||||
#define ESP_PANEL_LCD_SPI_IO_DATA1 (11)
|
||||
#define ESP_PANEL_LCD_SPI_IO_DATA2 (12)
|
||||
#define ESP_PANEL_LCD_SPI_IO_DATA3 (13)
|
||||
#endif
|
||||
#define ESP_PANEL_LCD_SPI_MODE (0) // 0/1/2/3, typically set to 0
|
||||
#define ESP_PANEL_LCD_SPI_CLK_HZ (40 * 1000 * 1000)
|
||||
// Should be an integer divisor of 80M, typically set to 40M
|
||||
#define ESP_PANEL_LCD_SPI_TRANS_QUEUE_SZ (10) // Typically set to 10
|
||||
#define ESP_PANEL_LCD_SPI_CMD_BITS (32) // Typically set to 32
|
||||
#define ESP_PANEL_LCD_SPI_PARAM_BITS (8) // Typically set to 8
|
||||
|
||||
#elif ESP_PANEL_LCD_BUS_TYPE == ESP_PANEL_BUS_TYPE_RGB
|
||||
|
||||
#define ESP_PANEL_LCD_RGB_CLK_HZ (16 * 1000 * 1000)
|
||||
#define ESP_PANEL_LCD_RGB_HPW (10)
|
||||
#define ESP_PANEL_LCD_RGB_HBP (10)
|
||||
#define ESP_PANEL_LCD_RGB_HFP (20)
|
||||
#define ESP_PANEL_LCD_RGB_VPW (10)
|
||||
#define ESP_PANEL_LCD_RGB_VBP (10)
|
||||
#define ESP_PANEL_LCD_RGB_VFP (10)
|
||||
#define ESP_PANEL_LCD_RGB_PCLK_ACTIVE_NEG (0) // 0: rising edge, 1: falling edge
|
||||
#define ESP_PANEL_LCD_RGB_DATA_WIDTH (16) // 8 | 16
|
||||
#define ESP_PANEL_LCD_RGB_PIXEL_BITS (16) // 24 | 16
|
||||
#define ESP_PANEL_LCD_RGB_FRAME_BUF_NUM (1) // 1/2/3
|
||||
#define ESP_PANEL_LCD_RGB_BOUNCE_BUF_SIZE (0) // Bounce buffer size in bytes. This function is used to avoid screen drift.
|
||||
// To enable the bounce buffer, set it to a non-zero value. Typically set to `ESP_PANEL_LCD_WIDTH * 10`
|
||||
// The size of the Bounce Buffer must satisfy `width_of_lcd * height_of_lcd = size_of_buffer * N`,
|
||||
// where N is an even number.
|
||||
#define ESP_PANEL_LCD_RGB_IO_HSYNC (46)
|
||||
#define ESP_PANEL_LCD_RGB_IO_VSYNC (3)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DE (17) // -1 if not used
|
||||
#define ESP_PANEL_LCD_RGB_IO_PCLK (9)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DISP (-1) // -1 if not used
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA0 (10)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA1 (11)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA2 (12)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA3 (13)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA4 (14)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA5 (21)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA6 (47)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA7 (48)
|
||||
#if ESP_PANEL_LCD_RGB_DATA_WIDTH > 8
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA8 (45)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA9 (38)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA10 (39)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA11 (40)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA12 (41)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA13 (42)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA14 (2)
|
||||
#define ESP_PANEL_LCD_RGB_IO_DATA15 (1)
|
||||
#endif
|
||||
#if !ESP_PANEL_LCD_BUS_SKIP_INIT_HOST
|
||||
#define ESP_PANEL_LCD_3WIRE_SPI_IO_CS (0)
|
||||
#define ESP_PANEL_LCD_3WIRE_SPI_IO_SCK (1)
|
||||
#define ESP_PANEL_LCD_3WIRE_SPI_IO_SDA (2)
|
||||
#define ESP_PANEL_LCD_3WIRE_SPI_CS_USE_EXPNADER (0) // 0/1
|
||||
#define ESP_PANEL_LCD_3WIRE_SPI_SCL_USE_EXPNADER (0) // 0/1
|
||||
#define ESP_PANEL_LCD_3WIRE_SPI_SDA_USE_EXPNADER (0) // 0/1
|
||||
#define ESP_PANEL_LCD_3WIRE_SPI_SCL_ACTIVE_EDGE (0) // 0: rising edge, 1: falling edge
|
||||
#define ESP_PANEL_LCD_FLAGS_AUTO_DEL_PANEL_IO (0) // Delete the panel IO instance automatically if set to 1.
|
||||
// If the 3-wire SPI pins are sharing other pins of the RGB interface to save GPIOs,
|
||||
// Please set it to 1 to release the panel IO and its pins (except CS signal).
|
||||
#define ESP_PANEL_LCD_FLAGS_MIRROR_BY_CMD (!ESP_PANEL_LCD_FLAGS_AUTO_DEL_PANEL_IO)
|
||||
// The `mirror()` function will be implemented by LCD command if set to 1.
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#error "The function is not ready and will be implemented in the future."
|
||||
|
||||
#endif /* ESP_PANEL_LCD_BUS_TYPE */
|
||||
|
||||
/**
|
||||
* LCD Venbdor Initialization Commands.
|
||||
*
|
||||
* Vendor specific initialization can be different between manufacturers, should consult the LCD supplier for
|
||||
* initialization sequence code. Please uncomment and change the following macro definitions. Otherwise, the LCD driver
|
||||
* will use the default initialization sequence code.
|
||||
*
|
||||
* There are two formats for the sequence code:
|
||||
* 1. Raw data: {command, (uint8_t []){ data0, data1, ... }, data_size, delay_ms}
|
||||
* 2. Formater: ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(delay_ms, command, { data0, data1, ... }) and
|
||||
* ESP_PANEL_LCD_CMD_WITH_NONE_PARAM(delay_ms, command)
|
||||
*/
|
||||
// #define ESP_PANEL_LCD_VENDOR_INIT_CMD \
|
||||
// { \
|
||||
// {0xFF, (uint8_t []){0x77, 0x01, 0x00, 0x00, 0x10}, 5, 0}, \
|
||||
// {0xC0, (uint8_t []){0x3B, 0x00}, 2, 0}, \
|
||||
// {0xC1, (uint8_t []){0x0D, 0x02}, 2, 0}, \
|
||||
// {0x29, (uint8_t []){0x00}, 0, 120}, \
|
||||
// or \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xFF, {0x77, 0x01, 0x00, 0x00, 0x10}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC0, {0x3B, 0x00}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC1, {0x0D, 0x02}), \
|
||||
// ESP_PANEL_LCD_CMD_WITH_NONE_PARAM(120, 0x29), \
|
||||
// }
|
||||
|
||||
/* LCD Color Settings */
|
||||
/* LCD color depth in bits */
|
||||
#define ESP_PANEL_LCD_COLOR_BITS (16) // 8/16/18/24
|
||||
/*
|
||||
* LCD RGB Element Order. Choose one of the following:
|
||||
* - 0: RGB
|
||||
* - 1: BGR
|
||||
*/
|
||||
#define ESP_PANEL_LCD_BGR_ORDER (1) // 0/1
|
||||
#define ESP_PANEL_LCD_INEVRT_COLOR (1) // 0/1
|
||||
|
||||
/* LCD Transformation Flags */
|
||||
#define ESP_PANEL_LCD_SWAP_XY (0) // 0/1
|
||||
#define ESP_PANEL_LCD_MIRROR_X (1) // 0/1
|
||||
#define ESP_PANEL_LCD_MIRROR_Y (0) // 0/1
|
||||
|
||||
/* LCD Other Settings */
|
||||
/* IO num of RESET pin, set to -1 if not use */
|
||||
#define ESP_PANEL_LCD_IO_RST (8)
|
||||
#define ESP_PANEL_LCD_RST_LEVEL (0) // 0: low level, 1: high level
|
||||
|
||||
#endif /* ESP_PANEL_USE_LCD */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// Please update the following macros to configure the touch panel ///////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 1 when using an touch panel */
|
||||
#define ESP_PANEL_USE_TOUCH (1) // 0/1
|
||||
#if ESP_PANEL_USE_TOUCH
|
||||
/**
|
||||
* Touch controller name. Choose one of the following:
|
||||
* - CST816S
|
||||
* - FT5x06
|
||||
* - GT911, GT1151
|
||||
* - ST1633, ST7123
|
||||
* - TT21100
|
||||
* - XPT2046
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_NAME FT5x06
|
||||
|
||||
/* Touch resolution in pixels */
|
||||
#define ESP_PANEL_TOUCH_H_RES (ESP_PANEL_LCD_WIDTH) // Typically set to the same value as the width of LCD
|
||||
#define ESP_PANEL_TOUCH_V_RES (ESP_PANEL_LCD_HEIGHT) // Typically set to the same value as the height of LCD
|
||||
|
||||
/* Touch Panel Bus Settings */
|
||||
/**
|
||||
* If set to 1, the bus will skip to initialize the corresponding host. Users need to initialize the host in advance.
|
||||
* It is useful if other devices use the same host. Please ensure that the host is initialized only once.
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_BUS_SKIP_INIT_HOST (0) // 0/1
|
||||
/**
|
||||
* Touch panel bus type. Choose one of the following:
|
||||
* - ESP_PANEL_BUS_TYPE_I2C
|
||||
* - ESP_PANEL_BUS_TYPE_SPI
|
||||
*/
|
||||
#define ESP_PANEL_TOUCH_BUS_TYPE (ESP_PANEL_BUS_TYPE_I2C)
|
||||
/* Touch panel bus parameters */
|
||||
#if ESP_PANEL_TOUCH_BUS_TYPE == ESP_PANEL_BUS_TYPE_I2C
|
||||
|
||||
#define ESP_PANEL_TOUCH_BUS_HOST_ID (0) // Typically set to 0
|
||||
#define ESP_PANEL_TOUCH_I2C_ADDRESS (0) // Typically set to 0 to use default address
|
||||
#if !ESP_PANEL_TOUCH_BUS_SKIP_INIT_HOST
|
||||
#define ESP_PANEL_TOUCH_I2C_CLK_HZ (400 * 1000)
|
||||
// Typically set to 400K
|
||||
#define ESP_PANEL_TOUCH_I2C_SCL_PULLUP (1) // 0/1
|
||||
#define ESP_PANEL_TOUCH_I2C_SDA_PULLUP (1) // 0/1
|
||||
#define ESP_PANEL_TOUCH_I2C_IO_SCL (12)
|
||||
#define ESP_PANEL_TOUCH_I2C_IO_SDA (11)
|
||||
#endif
|
||||
|
||||
#elif ESP_PANEL_TOUCH_BUS_TYPE == ESP_PANEL_BUS_TYPE_SPI
|
||||
|
||||
#define ESP_PANEL_TOUCH_BUS_HOST_ID (1) // Typically set to 1
|
||||
#define ESP_PANEL_TOUCH_SPI_IO_CS (5)
|
||||
#if !ESP_PANEL_TOUCH_BUS_SKIP_INIT_HOST
|
||||
#define ESP_PANEL_TOUCH_SPI_IO_SCK (7)
|
||||
#define ESP_PANEL_TOUCH_SPI_IO_MOSI (6)
|
||||
#define ESP_PANEL_TOUCH_SPI_IO_MISO (9)
|
||||
#endif
|
||||
#define ESP_PANEL_TOUCH_SPI_CLK_HZ (1 * 1000 * 1000)
|
||||
// Should be an integer divisor of 80M, typically set to 1M
|
||||
|
||||
#else
|
||||
|
||||
#error "The function is not ready and will be implemented in the future."
|
||||
|
||||
#endif /* ESP_PANEL_TOUCH_BUS_TYPE */
|
||||
|
||||
/* Touch Transformation Flags */
|
||||
#define ESP_PANEL_TOUCH_SWAP_XY (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_MIRROR_X (0) // 0/1
|
||||
#define ESP_PANEL_TOUCH_MIRROR_Y (0) // 0/1
|
||||
|
||||
/* Touch Other Settings */
|
||||
/* IO num of RESET pin, set to -1 if not use */
|
||||
#define ESP_PANEL_TOUCH_IO_RST (-1)
|
||||
#define ESP_PANEL_TOUCH_RST_LEVEL (0) // 0: low level, 1: high level
|
||||
/* IO num of INT pin, set to -1 if not use */
|
||||
#define ESP_PANEL_TOUCH_IO_INT (14)
|
||||
#define ESP_PANEL_TOUCH_INT_LEVEL (0) // 0: low level, 1: high level
|
||||
|
||||
#endif /* ESP_PANEL_USE_TOUCH */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please update the following macros to configure the backlight ////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define ESP_PANEL_USE_BACKLIGHT (1) // 0/1
|
||||
#if ESP_PANEL_USE_BACKLIGHT
|
||||
/* IO num of backlight pin */
|
||||
#define ESP_PANEL_BACKLIGHT_IO (9)
|
||||
#define ESP_PANEL_BACKLIGHT_ON_LEVEL (1) // 0: low level, 1: high level
|
||||
|
||||
/* Set to 1 if turn off the backlight after initializing the panel; otherwise, set it to turn on */
|
||||
#define ESP_PANEL_BACKLIGHT_IDLE_OFF (0) // 0: on, 1: off
|
||||
|
||||
/* Set to 1 if use PWM for brightness control */
|
||||
#define ESP_PANEL_LCD_BL_USE_PWM (1) // 0/1
|
||||
#endif /* ESP_PANEL_USE_BACKLIGHT */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please update the following macros to configure the IO expander //////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Set to 0 if not using IO Expander */
|
||||
#define ESP_PANEL_USE_EXPANDER (0) // 0/1
|
||||
#if ESP_PANEL_USE_EXPANDER
|
||||
/**
|
||||
* IO expander name. Choose one of the following:
|
||||
* - CH422G
|
||||
* - HT8574
|
||||
* - TCA95xx_8bit
|
||||
* - TCA95xx_16bit
|
||||
*/
|
||||
#define ESP_PANEL_EXPANDER_NAME TCA95xx_8bit
|
||||
|
||||
/* IO expander Settings */
|
||||
/**
|
||||
* If set to 1, the driver will skip to initialize the corresponding host. Users need to initialize the host in advance.
|
||||
* It is useful if other devices use the same host. Please ensure that the host is initialized only once.
|
||||
*/
|
||||
#define ESP_PANEL_EXPANDER_SKIP_INIT_HOST (0) // 0/1
|
||||
/* IO expander parameters */
|
||||
#define ESP_PANEL_EXPANDER_I2C_ADDRESS (0x20) // The actual I2C address. Even for the same model of IC,
|
||||
// the I2C address may be different, and confirmation based on
|
||||
// the actual hardware connection is required
|
||||
#if !ESP_PANEL_EXPANDER_SKIP_INIT_HOST
|
||||
#define ESP_PANEL_EXPANDER_HOST_ID (0) // Typically set to 0
|
||||
#define ESP_PANEL_EXPANDER_I2C_CLK_HZ (400 * 1000)
|
||||
// Typically set to 400K
|
||||
#define ESP_PANEL_EXPANDER_I2C_SCL_PULLUP (1) // 0/1
|
||||
#define ESP_PANEL_EXPANDER_I2C_SDA_PULLUP (1) // 0/1
|
||||
#define ESP_PANEL_EXPANDER_I2C_IO_SCL (18)
|
||||
#define ESP_PANEL_EXPANDER_I2C_IO_SDA (8)
|
||||
#endif
|
||||
#endif /* ESP_PANEL_USE_EXPANDER */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Please utilize the following macros to execute any additional code if required. //////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// #define ESP_PANEL_BEGIN_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_EXPANDER_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_EXPANDER_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_LCD_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_LCD_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_TOUCH_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_TOUCH_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_BACKLIGHT_START_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_BACKLIGHT_END_FUNCTION( panel )
|
||||
// #define ESP_PANEL_BEGIN_END_FUNCTION( panel )
|
||||
|
||||
/**
|
||||
* Do not change the following versions, they are used to check if the configurations in this file are compatible with
|
||||
* the current version of `ESP_Panel_Board_Custom.h` in the library. The detailed rules are as follows:
|
||||
*
|
||||
* 1. If the major version is not consistent, then the configurations in this file are incompatible with the library
|
||||
* and must be replaced with the file from the library.
|
||||
* 2. If the minor version is not consistent, this file might be missing some new configurations, which will be set to
|
||||
* default values. It is recommended to replace it with the file from the library.
|
||||
* 3. Even if the patch version is not consistent, it will not affect normal functionality.
|
||||
*
|
||||
*/
|
||||
#define ESP_PANEL_BOARD_CUSTOM_FILE_VERSION_MAJOR 0
|
||||
#define ESP_PANEL_BOARD_CUSTOM_FILE_VERSION_MINOR 1
|
||||
#define ESP_PANEL_BOARD_CUSTOM_FILE_VERSION_PATCH 1
|
||||
|
||||
// *INDENT-OFF*
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "ESP_PanelBus.h"
|
||||
|
||||
static const char *TAG = "ESP_PanelBus";
|
||||
|
||||
ESP_PanelBus::ESP_PanelBus(int host_id, uint8_t bus_type, bool host_need_init):
|
||||
host_id(host_id),
|
||||
host_need_init(host_need_init),
|
||||
bus_type(bus_type),
|
||||
handle(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
bool ESP_PanelBus::readRegisterData(uint32_t address, void *data, uint32_t data_size)
|
||||
{
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_panel_io_rx_param(handle, address, data, data_size), false,
|
||||
"Read register(0x%x) failed", address);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_PanelBus::writeRegisterData(uint32_t address, const void *data, uint32_t data_size)
|
||||
{
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_panel_io_tx_param(handle, address, data, data_size), false,
|
||||
"Read register(0x%x) failed", address);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_PanelBus::writeColorData(uint32_t address, const void *color, uint32_t color_size)
|
||||
{
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_panel_io_tx_param(handle, address, color, color_size), false,
|
||||
"Read register(0x%x) failed", address);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_PanelBus::del(void)
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
// RGB bus which needs to initialize the host inside can be deleted
|
||||
if ((bus_type == ESP_PANEL_BUS_TYPE_RGB) && !host_need_init) {
|
||||
ESP_LOGD(TAG, "Use RGB bus without host init, skip delete panel IO");
|
||||
return true;
|
||||
}
|
||||
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_panel_io_del(handle), false, "Delete panel IO failed");
|
||||
|
||||
ESP_LOGD(TAG, "Delete panel IO @%p", handle);
|
||||
handle = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ESP_PanelBus::configHostId(int id)
|
||||
{
|
||||
host_id = id;
|
||||
}
|
||||
|
||||
esp_lcd_panel_io_handle_t ESP_PanelBus::getHandle(void)
|
||||
{
|
||||
if (handle == NULL) {
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
ESP_LOGD(TAG, "Get invalid handle");
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
uint8_t ESP_PanelBus::getType(void)
|
||||
{
|
||||
if ((bus_type == ESP_PANEL_BUS_TYPE_UNKNOWN) || (bus_type >= ESP_PANEL_BUS_TYPE_MAX)) {
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
ESP_LOGD(TAG, "Get invalid type");
|
||||
|
||||
bus_type = ESP_PANEL_BUS_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
return bus_type;
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "esp_lcd_types.h"
|
||||
#include "ESP_PanelTypes.h"
|
||||
|
||||
/**
|
||||
* @brief Bus object class
|
||||
*
|
||||
* @note This class is a base class for all types of bus. Due to it is a virtual class, users cannot use it directly
|
||||
*/
|
||||
class ESP_PanelBus {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new bus object, the `begin()` function should be called after this function
|
||||
*
|
||||
* @param host_id The host ID of bus
|
||||
* @param bus_type The type of bus.
|
||||
* - ESP_PANEL_BUS_TYPE_I2C: I2C bus
|
||||
* - ESP_PANEL_BUS_TYPE_SPI: SPI bus
|
||||
* - ESP_PANEL_BUS_TYPE_RGB: RGB bus
|
||||
* - ESP_PANEL_BUS_TYPE_QSPI: QSPI bus
|
||||
* @param host_need_init Whether the host should be initialized inside.
|
||||
* - true: the host needs to be initialized inside
|
||||
* - false: the host should been initialized by users
|
||||
*/
|
||||
ESP_PanelBus(int host_id, uint8_t bus_type, bool host_need_init);
|
||||
|
||||
/**
|
||||
* @brief Destroy the bus object
|
||||
*
|
||||
*/
|
||||
virtual ~ESP_PanelBus() = default;
|
||||
|
||||
/**
|
||||
* @brief Here are some functions to configure the bus object. These functions should be called before `begin()`
|
||||
*
|
||||
*/
|
||||
void configHostId(int id);
|
||||
|
||||
/**
|
||||
* @brief Startup the bus
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
virtual bool begin(void) = 0;
|
||||
|
||||
/**
|
||||
* @brief Delete the bus object, release the resources
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool del(void);
|
||||
|
||||
/**
|
||||
* @brief Read the register data
|
||||
*
|
||||
* @param address The address of the register
|
||||
* @param data The buffer to store the register data
|
||||
* @param data_size The size of the data (in bytes)
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool readRegisterData(uint32_t address, void *data, uint32_t data_size);
|
||||
|
||||
/**
|
||||
* @brief Write the register data
|
||||
*
|
||||
* @param address The address of the register
|
||||
* @param data The buffer to store the register data
|
||||
* @param data_size The size of the data (in bytes)
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool writeRegisterData(uint32_t address, const void *data, uint32_t data_size);
|
||||
|
||||
/**
|
||||
* @brief Write the color data
|
||||
*
|
||||
* @param address The address of the register
|
||||
* @param data The buffer to store the color data
|
||||
* @param data_size The size of the data (in bytes)
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool writeColorData(uint32_t address, const void *color, uint32_t color_size);
|
||||
|
||||
/**
|
||||
* @brief Get the type of bus
|
||||
*
|
||||
* @return
|
||||
* - ESP_PANEL_BUS_TYPE_UNKNOWN: Unkown bus
|
||||
* - ESP_PANEL_BUS_TYPE_SPI: SPI bus
|
||||
* - ESP_PANEL_BUS_TYPE_RGB: RGB (DPI)bus
|
||||
* - ESP_PANEL_BUS_TYPE_QSPI: QSPI bus
|
||||
* - ESP_PANEL_BUS_TYPE_I2C: I2C bus
|
||||
* - ESP_PANEL_BUS_TYPE_I80: I80 (Parallel/8080/DBI) bus
|
||||
*/
|
||||
uint8_t getType(void);
|
||||
|
||||
/**
|
||||
* @brief Get the IO handle of bus
|
||||
*
|
||||
* @return
|
||||
* - NULL: if fail
|
||||
* - Others: the handle of bus
|
||||
*/
|
||||
esp_lcd_panel_io_handle_t getHandle(void);
|
||||
|
||||
protected:
|
||||
int host_id;
|
||||
bool host_need_init;
|
||||
uint8_t bus_type;
|
||||
esp_lcd_panel_io_handle_t handle;
|
||||
};
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "I2C.h"
|
||||
|
||||
static const char *TAG = "ESP_PanelBus_I2C";
|
||||
|
||||
ESP_PanelBus_I2C::ESP_PanelBus_I2C(int scl_io, int sda_io, const esp_lcd_panel_io_i2c_config_t &io_config):
|
||||
ESP_PanelBus((int)ESP_PANEL_HOST_I2C_ID_DEFAULT, ESP_PANEL_BUS_TYPE_I2C, true),
|
||||
host_config((i2c_config_t)ESP_PANEL_HOST_I2C_CONFIG_DEFAULT(scl_io, sda_io)),
|
||||
io_config(io_config)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelBus_I2C::ESP_PanelBus_I2C(const i2c_config_t &host_config, const esp_lcd_panel_io_i2c_config_t &io_config,
|
||||
i2c_port_t host_id):
|
||||
ESP_PanelBus((int)host_id, ESP_PANEL_BUS_TYPE_I2C, true),
|
||||
host_config(host_config),
|
||||
io_config(io_config)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelBus_I2C::ESP_PanelBus_I2C(const esp_lcd_panel_io_i2c_config_t &io_config, i2c_port_t host_id):
|
||||
ESP_PanelBus((int)host_id, ESP_PANEL_BUS_TYPE_I2C, false),
|
||||
io_config(io_config)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelBus_I2C::~ESP_PanelBus_I2C()
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
if (handle == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!del()) {
|
||||
ESP_LOGE(TAG, "Delete panel io failed");
|
||||
}
|
||||
|
||||
if (host_need_init) {
|
||||
if (i2c_driver_delete((i2c_port_t)host_id) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Delete host[%d] driver failed", host_id);
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Delete host[%d] driver", host_id);
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
ESP_LOGD(TAG, "Destroyed");
|
||||
}
|
||||
|
||||
void ESP_PanelBus_I2C::configI2cPullupEnable(bool sda_pullup_en, bool scl_pullup_en)
|
||||
{
|
||||
host_config.sda_pullup_en = sda_pullup_en ? GPIO_PULLUP_ENABLE : GPIO_PULLUP_DISABLE;
|
||||
host_config.scl_pullup_en = scl_pullup_en ? GPIO_PULLUP_ENABLE : GPIO_PULLUP_DISABLE;
|
||||
}
|
||||
|
||||
void ESP_PanelBus_I2C::configI2cFreqHz(uint32_t hz)
|
||||
{
|
||||
host_config.master.clk_speed = hz;
|
||||
}
|
||||
|
||||
void ESP_PanelBus_I2C::configI2cAddress(uint32_t address)
|
||||
{
|
||||
io_config.dev_addr = address;
|
||||
}
|
||||
|
||||
void ESP_PanelBus_I2C::configI2cCtrlPhaseBytes(uint32_t num)
|
||||
{
|
||||
io_config.control_phase_bytes = num;
|
||||
}
|
||||
|
||||
void ESP_PanelBus_I2C::configI2cDcBitOffset(uint32_t num)
|
||||
{
|
||||
io_config.dc_bit_offset = num;
|
||||
}
|
||||
|
||||
void ESP_PanelBus_I2C::configI2cCommandBits(uint32_t num)
|
||||
{
|
||||
io_config.lcd_cmd_bits = num;
|
||||
}
|
||||
|
||||
void ESP_PanelBus_I2C::configI2cParamBits(uint32_t num)
|
||||
{
|
||||
io_config.lcd_param_bits = num;
|
||||
}
|
||||
|
||||
void ESP_PanelBus_I2C::configI2cFlags(bool dc_low_on_data, bool disable_control_phase)
|
||||
{
|
||||
io_config.flags.dc_low_on_data = dc_low_on_data;
|
||||
io_config.flags.disable_control_phase = disable_control_phase;
|
||||
}
|
||||
|
||||
bool ESP_PanelBus_I2C::begin(void)
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
if (host_need_init) {
|
||||
ESP_PANEL_CHECK_ERR_RET(i2c_param_config((i2c_port_t)host_id, &host_config), false, "Configure host[%d] failed", host_id);
|
||||
ESP_PANEL_CHECK_ERR_RET(i2c_driver_install((i2c_port_t)host_id, host_config.mode, 0, 0, 0), false,
|
||||
"Install host[%d] failed", host_id);
|
||||
ESP_LOGD(TAG, "Init host[%d]", (int)host_id);
|
||||
}
|
||||
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_new_panel_io_i2c((esp_lcd_i2c_bus_handle_t)host_id, &io_config, &handle), false,
|
||||
"Create panel io failed");
|
||||
ESP_LOGD(TAG, "Panel IO @%p created", handle);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "host/ESP_PanelHost.h"
|
||||
#include "ESP_PanelBus.h"
|
||||
|
||||
/**
|
||||
* @brief I2C bus object class
|
||||
*
|
||||
* @note This class is a derived class of `ESP_PanelBus`, user can use it directly
|
||||
*/
|
||||
class ESP_PanelBus_I2C: public ESP_PanelBus {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a I2C bus object in a common way, the host will be initialized by the driver
|
||||
*
|
||||
* @note This function uses some default values (ESP_PANEL_HOST_I2C_CONFIG_DEFAULT) to config the bus object,
|
||||
* use `config*()` functions to change them
|
||||
* @note The `init()` function should be called after this function
|
||||
*
|
||||
* @param scl_io I2C SCL pin
|
||||
* @param sda_io I2C SDA pin
|
||||
* @param io_config I2C panel IO configuration
|
||||
*/
|
||||
ESP_PanelBus_I2C(int scl_io, int sda_io, const esp_lcd_panel_io_i2c_config_t &io_config);
|
||||
|
||||
/**
|
||||
* @brief Construct a I2C bus object in a complex way, the host will be initialized by the driver
|
||||
*
|
||||
* @note The `init()` function should be called after this function
|
||||
*
|
||||
* @param host_config I2C host configuration
|
||||
* @param io_config I2C panel IO configuration
|
||||
* @param host_id I2C host ID, default is `ESP_PANEL_HOST_I2C_ID_DEFAULT`
|
||||
*/
|
||||
ESP_PanelBus_I2C(const i2c_config_t &host_config, const esp_lcd_panel_io_i2c_config_t &io_config,
|
||||
i2c_port_t host_id = ESP_PANEL_HOST_I2C_ID_DEFAULT);
|
||||
|
||||
/**
|
||||
* @brief Construct a I2C bus object in a complex way, the host needs to be initialized by the user
|
||||
*
|
||||
* @note The `init()` function should be called after this function
|
||||
*
|
||||
* @param io_config I2C panel IO configuration
|
||||
* @param host_id I2C host ID, default is `ESP_PANEL_HOST_I2C_ID_DEFAULT`
|
||||
*/
|
||||
ESP_PanelBus_I2C(const esp_lcd_panel_io_i2c_config_t &io_config, i2c_port_t host_id = ESP_PANEL_HOST_I2C_ID_DEFAULT);
|
||||
|
||||
/**
|
||||
* @brief Destroy the I2C bus object
|
||||
*
|
||||
*/
|
||||
~ESP_PanelBus_I2C() override;
|
||||
|
||||
/**
|
||||
* @brief Here are some functions to configure the I2C bus object. These functions should be called before `begin()`
|
||||
*
|
||||
*/
|
||||
void configI2cPullupEnable(bool sda_pullup_en, bool scl_pullup_en);
|
||||
void configI2cFreqHz(uint32_t hz);
|
||||
void configI2cAddress(uint32_t address);
|
||||
void configI2cCtrlPhaseBytes(uint32_t num);
|
||||
void configI2cDcBitOffset(uint32_t num);
|
||||
void configI2cCommandBits(uint32_t num);
|
||||
void configI2cParamBits(uint32_t num);
|
||||
void configI2cFlags(bool dc_low_on_data, bool disable_control_phase);
|
||||
|
||||
/**
|
||||
* @brief Startup the bus
|
||||
*
|
||||
* @note This function should be called after `init()`
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool begin(void) override;
|
||||
|
||||
private:
|
||||
i2c_config_t host_config;
|
||||
esp_lcd_panel_io_i2c_config_t io_config;
|
||||
};
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "QSPI.h"
|
||||
|
||||
static const char *TAG = "ESP_PanelBus_QSPI";
|
||||
|
||||
ESP_PanelBus_QSPI::ESP_PanelBus_QSPI(int cs_io, int sck_io, int d0_io, int d1_io, int d2_io, int d3_io):
|
||||
ESP_PanelBus((int)ESP_PANEL_HOST_SPI_ID_DEFAULT, ESP_PANEL_BUS_TYPE_QSPI, true),
|
||||
host_config((spi_bus_config_t)ESP_PANEL_HOST_QSPI_CONFIG_DEFAULT(sck_io, d0_io, d1_io, d2_io, d3_io)),
|
||||
io_config((esp_lcd_panel_io_spi_config_t)ESP_PANEL_IO_QSPI_CONFIG_DEFAULT(cs_io))
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelBus_QSPI::ESP_PanelBus_QSPI(int cs_io):
|
||||
ESP_PanelBus((int)ESP_PANEL_HOST_SPI_ID_DEFAULT, ESP_PANEL_BUS_TYPE_QSPI, false),
|
||||
io_config((esp_lcd_panel_io_spi_config_t)ESP_PANEL_IO_QSPI_CONFIG_DEFAULT(cs_io))
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelBus_QSPI::ESP_PanelBus_QSPI(const spi_bus_config_t &host_config, const esp_lcd_panel_io_spi_config_t &io_config,
|
||||
spi_host_device_t host_id):
|
||||
ESP_PanelBus((int)host_id, ESP_PANEL_BUS_TYPE_QSPI, true),
|
||||
host_config(host_config),
|
||||
io_config(io_config)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelBus_QSPI::ESP_PanelBus_QSPI(const esp_lcd_panel_io_spi_config_t &io_config, spi_host_device_t host_id):
|
||||
ESP_PanelBus((int)host_id, ESP_PANEL_BUS_TYPE_QSPI, false),
|
||||
io_config(io_config)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelBus_QSPI::~ESP_PanelBus_QSPI()
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
if (handle == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!del()) {
|
||||
ESP_LOGE(TAG, "Delete panel io failed");
|
||||
}
|
||||
|
||||
if (host_need_init) {
|
||||
if (spi_bus_free((spi_host_device_t)host_id) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Delete host[%d] driver failed", host_id);
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Delete host[%d] driver", host_id);
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
ESP_LOGD(TAG, "Destroyed");
|
||||
}
|
||||
|
||||
void ESP_PanelBus_QSPI::configQspiMode(uint8_t mode)
|
||||
{
|
||||
io_config.spi_mode = mode;
|
||||
}
|
||||
|
||||
void ESP_PanelBus_QSPI::configQspiFreqHz(uint32_t hz)
|
||||
{
|
||||
io_config.pclk_hz = hz;
|
||||
}
|
||||
|
||||
void ESP_PanelBus_QSPI::configQspiTransQueueDepth(uint8_t depth)
|
||||
{
|
||||
io_config.trans_queue_depth = depth;
|
||||
}
|
||||
|
||||
bool ESP_PanelBus_QSPI::begin(void)
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
if (host_need_init) {
|
||||
ESP_PANEL_CHECK_ERR_RET(spi_bus_initialize((spi_host_device_t)host_id, &host_config, SPI_DMA_CH_AUTO), false,
|
||||
"Initializeost Host[%d] failed", host_id);
|
||||
ESP_LOGD(TAG, "Init host[%d]", host_id);
|
||||
}
|
||||
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)host_id, &io_config, &handle), false,
|
||||
"Create panel io failed");
|
||||
ESP_LOGD(TAG, "Panel IO @%p created", handle);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "driver/spi_master.h"
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "host/ESP_PanelHost.h"
|
||||
#include "ESP_PanelBus.h"
|
||||
|
||||
/**
|
||||
* @brief Macro for QSPI bus default host ID
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Macro for QSPI panel IO configuration
|
||||
*
|
||||
*/
|
||||
#define ESP_PANEL_IO_QSPI_CONFIG_DEFAULT(cs_io) \
|
||||
{ \
|
||||
.cs_gpio_num = cs_io, \
|
||||
.dc_gpio_num = -1, \
|
||||
.spi_mode = 0, \
|
||||
.pclk_hz = SPI_MASTER_FREQ_40M, \
|
||||
.trans_queue_depth = 10, \
|
||||
.on_color_trans_done = NULL, \
|
||||
.user_ctx = NULL, \
|
||||
.lcd_cmd_bits = 32, \
|
||||
.lcd_param_bits = 8, \
|
||||
.flags = { \
|
||||
.dc_low_on_data = 0, \
|
||||
.octal_mode = 0, \
|
||||
.quad_mode = 1, \
|
||||
.sio_mode = 0, \
|
||||
.lsb_first = 0, \
|
||||
.cs_high_active = 0, \
|
||||
}, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QSPI bus object class
|
||||
*
|
||||
* @note This class is a derived class of `ESP_PanelBus`, user can use it directly
|
||||
*/
|
||||
class ESP_PanelBus_QSPI: public ESP_PanelBus {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a QSPI bus object in a common way, the host will be initialized by the driver
|
||||
*
|
||||
* @note This function uses some default values (ESP_PANEL_IO_QSPI_CONFIG_DEFAULT) to config the bus object,
|
||||
* use `config*()` functions to change them
|
||||
* @note The `init()` function should be called after this function
|
||||
*
|
||||
* @param cs_io QSPI CS pin
|
||||
* @param sck_io QSPI SCK pin
|
||||
* @param d0_io QSPI D0 pin
|
||||
* @param d1_io QSPI D1 pin
|
||||
* @param d2_io QSPI D2 pin
|
||||
* @param d3_io QSPI D3 pin
|
||||
*/
|
||||
ESP_PanelBus_QSPI(int cs_io, int sck_io, int d0_io, int d1_io, int d2_io, int d3_io);
|
||||
|
||||
/**
|
||||
* @brief Construct a QSPI bus object in a common way, the host needs to be initialized by the user
|
||||
*
|
||||
* @note This function uses some default values (ESP_PANEL_IO_QSPI_CONFIG_DEFAULT) to config the bus object,
|
||||
* use `config*()` functions to change them
|
||||
* @note The `init()` function should be called after this function
|
||||
*
|
||||
* @param cs_io QSPI CS pin
|
||||
*/
|
||||
ESP_PanelBus_QSPI(int cs_io);
|
||||
|
||||
/**
|
||||
* @brief Construct a QSPI bus object in a complex way, the host will be initialized by the driver
|
||||
*
|
||||
* @param host_config QSPI host configuration
|
||||
* @param io_config QSPI panel IO configuration
|
||||
* @param host_id QSPI host ID, default is `ESP_PANEL_HOST_SPI_ID_DEFAULT`
|
||||
*/
|
||||
ESP_PanelBus_QSPI(const spi_bus_config_t &host_config, const esp_lcd_panel_io_spi_config_t &io_config,
|
||||
spi_host_device_t host_id = ESP_PANEL_HOST_SPI_ID_DEFAULT);
|
||||
|
||||
/**
|
||||
* @brief Construct a QSPI bus object in a complex way, the host needs to be initialized by the user
|
||||
*
|
||||
* @param io_config QSPI panel IO configuration
|
||||
* @param host_id QSPI host ID, default is `ESP_PANEL_HOST_SPI_ID_DEFAULT`
|
||||
*/
|
||||
ESP_PanelBus_QSPI(const esp_lcd_panel_io_spi_config_t &io_config, spi_host_device_t host_id = ESP_PANEL_HOST_SPI_ID_DEFAULT);
|
||||
|
||||
/**
|
||||
* @brief Destroy the QSPI bus object
|
||||
*
|
||||
*/
|
||||
~ESP_PanelBus_QSPI() override;
|
||||
|
||||
/**
|
||||
* @brief Here are some functions to configure the QSPI bus object. These functions should be called before `begin()`
|
||||
*
|
||||
*/
|
||||
void configQspiMode(uint8_t mode);
|
||||
void configQspiFreqHz(uint32_t hz);
|
||||
void configQspiTransQueueDepth(uint8_t depth);
|
||||
|
||||
/**
|
||||
* @brief Startup the bus
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool begin(void) override;
|
||||
|
||||
private:
|
||||
spi_bus_config_t host_config;
|
||||
esp_lcd_panel_io_spi_config_t io_config;
|
||||
};
|
||||
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if SOC_LCD_RGB_SUPPORTED
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "RGB.h"
|
||||
|
||||
static const char *TAG = "ESP_PanelBus_RGB";
|
||||
|
||||
ESP_PanelBus_RGB::ESP_PanelBus_RGB(
|
||||
uint16_t width, uint16_t height,
|
||||
int cs_io, int sck_io, int sda_io,
|
||||
int d0_io, int d1_io, int d2_io, int d3_io, int d4_io, int d5_io, int d6_io, int d7_io,
|
||||
int d8_io, int d9_io, int d10_io, int d11_io, int d12_io, int d13_io, int d14_io, int d15_io,
|
||||
int hsync_io, int vsync_io, int pclk_io, int de_io, int disp_io):
|
||||
ESP_PanelBus(-1, ESP_PANEL_BUS_TYPE_RGB, true),
|
||||
rgb_config((esp_lcd_rgb_panel_config_t)ESP_PANEL_RGB_16BIT_CONFIG_DEFAULT(
|
||||
width, height,
|
||||
d0_io, d1_io, d2_io, d3_io, d4_io, d5_io, d6_io, d7_io,
|
||||
d8_io, d9_io, d10_io, d11_io, d12_io, d13_io, d14_io, d15_io,
|
||||
hsync_io, vsync_io, pclk_io, de_io, disp_io)),
|
||||
spi_config((esp_lcd_panel_io_3wire_spi_config_t)ESP_PANEL_IO_3WIRE_SPI_CONFIG_DEFAULT(cs_io, sck_io, sda_io))
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelBus_RGB::ESP_PanelBus_RGB(
|
||||
uint16_t width, uint16_t height,
|
||||
int cs_io, int sck_io, int sda_io,
|
||||
int d0_io, int d1_io, int d2_io, int d3_io, int d4_io, int d5_io, int d6_io, int d7_io,
|
||||
int hsync_io, int vsync_io, int pclk_io, int de_io, int disp_io):
|
||||
ESP_PanelBus(-1, ESP_PANEL_BUS_TYPE_RGB, true),
|
||||
rgb_config((esp_lcd_rgb_panel_config_t)ESP_PANEL_RGB_8BIT_CONFIG_DEFAULT(
|
||||
width, height,
|
||||
d0_io, d1_io, d2_io, d3_io, d4_io, d5_io, d6_io, d7_io,
|
||||
hsync_io, vsync_io, pclk_io, de_io, disp_io)),
|
||||
spi_config((esp_lcd_panel_io_3wire_spi_config_t)ESP_PANEL_IO_3WIRE_SPI_CONFIG_DEFAULT(cs_io, sck_io, sda_io))
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelBus_RGB::ESP_PanelBus_RGB(
|
||||
uint16_t width, uint16_t height,
|
||||
int d0_io, int d1_io, int d2_io, int d3_io, int d4_io, int d5_io, int d6_io, int d7_io,
|
||||
int d8_io, int d9_io, int d10_io, int d11_io, int d12_io, int d13_io, int d14_io, int d15_io,
|
||||
int hsync_io, int vsync_io, int pclk_io, int de_io, int disp_io):
|
||||
ESP_PanelBus(-1, ESP_PANEL_BUS_TYPE_RGB, false),
|
||||
rgb_config((esp_lcd_rgb_panel_config_t)ESP_PANEL_RGB_16BIT_CONFIG_DEFAULT(
|
||||
width, height,
|
||||
d0_io, d1_io, d2_io, d3_io, d4_io, d5_io, d6_io, d7_io,
|
||||
d8_io, d9_io, d10_io, d11_io, d12_io, d13_io, d14_io, d15_io,
|
||||
hsync_io, vsync_io, pclk_io, de_io, disp_io))
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelBus_RGB::ESP_PanelBus_RGB(
|
||||
uint16_t width, uint16_t height,
|
||||
int d0_io, int d1_io, int d2_io, int d3_io, int d4_io, int d5_io, int d6_io, int d7_io,
|
||||
int hsync_io, int vsync_io, int pclk_io, int de_io, int disp_io):
|
||||
ESP_PanelBus(-1, ESP_PANEL_BUS_TYPE_RGB, false),
|
||||
rgb_config((esp_lcd_rgb_panel_config_t)ESP_PANEL_RGB_8BIT_CONFIG_DEFAULT(
|
||||
width, height,
|
||||
d0_io, d1_io, d2_io, d3_io, d4_io, d5_io, d6_io, d7_io,
|
||||
hsync_io, vsync_io, pclk_io, de_io, disp_io))
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelBus_RGB::ESP_PanelBus_RGB(const esp_lcd_panel_io_3wire_spi_config_t &spi_config,
|
||||
const esp_lcd_rgb_panel_config_t &rgb_config, int host_id):
|
||||
ESP_PanelBus(host_id, ESP_PANEL_BUS_TYPE_RGB, true),
|
||||
rgb_config(rgb_config),
|
||||
spi_config(spi_config)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelBus_RGB::ESP_PanelBus_RGB(const esp_lcd_rgb_panel_config_t &rgb_config, int host_id):
|
||||
ESP_PanelBus(host_id, ESP_PANEL_BUS_TYPE_RGB, false),
|
||||
rgb_config(rgb_config)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelBus_RGB::~ESP_PanelBus_RGB()
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
if (host_need_init) {
|
||||
if (handle == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!del()) {
|
||||
ESP_LOGE(TAG, "Delete panel io failed");
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
ESP_LOGD(TAG, "Destroyed");
|
||||
}
|
||||
|
||||
void ESP_PanelBus_RGB::configRgbTimingFreqHz(uint32_t hz)
|
||||
{
|
||||
rgb_config.timings.pclk_hz = hz;
|
||||
}
|
||||
|
||||
void ESP_PanelBus_RGB::configRgbTimingPorch(uint16_t hpw, uint16_t hbp, uint16_t hfp,
|
||||
uint16_t vpw, uint16_t vbp, uint16_t vfp)
|
||||
{
|
||||
rgb_config.timings.hsync_pulse_width = hpw;
|
||||
rgb_config.timings.hsync_back_porch = hbp;
|
||||
rgb_config.timings.hsync_front_porch = hfp;
|
||||
rgb_config.timings.vsync_pulse_width = vpw;
|
||||
rgb_config.timings.vsync_back_porch = vbp;
|
||||
rgb_config.timings.vsync_front_porch = vfp;
|
||||
}
|
||||
|
||||
void ESP_PanelBus_RGB::configRgbTimingFlags(bool hsync_idle_low, bool vsync_idle_low, bool de_idle_high,
|
||||
bool pclk_active_neg, bool pclk_idle_high)
|
||||
{
|
||||
rgb_config.timings.flags.hsync_idle_low = hsync_idle_low;
|
||||
rgb_config.timings.flags.vsync_idle_low = vsync_idle_low;
|
||||
rgb_config.timings.flags.de_idle_high = de_idle_high;
|
||||
rgb_config.timings.flags.pclk_active_neg = pclk_active_neg;
|
||||
rgb_config.timings.flags.pclk_idle_high = pclk_idle_high;
|
||||
}
|
||||
|
||||
void ESP_PanelBus_RGB::configRgbFrameBufferNumber(uint8_t num)
|
||||
{
|
||||
rgb_config.num_fbs = num;
|
||||
}
|
||||
|
||||
void ESP_PanelBus_RGB::configRgbBounceBufferSize(uint32_t size_in_pixel)
|
||||
{
|
||||
rgb_config.bounce_buffer_size_px = size_in_pixel;
|
||||
}
|
||||
|
||||
void ESP_PanelBus_RGB::configRgbFlagDispActiveLow(void)
|
||||
{
|
||||
rgb_config.timings.flags.pclk_active_neg = 1;
|
||||
}
|
||||
|
||||
void ESP_PanelBus_RGB::configSpiLine(bool cs_use_expaneer, bool sck_use_expander, bool sda_use_expander,
|
||||
ESP_IOExpander *io_expander)
|
||||
{
|
||||
if (cs_use_expaneer) {
|
||||
spi_config.line_config.cs_io_type = IO_TYPE_EXPANDER;
|
||||
spi_config.line_config.cs_expander_pin = (esp_io_expander_pin_num_t)BIT(spi_config.line_config.cs_gpio_num);
|
||||
}
|
||||
if (sck_use_expander) {
|
||||
spi_config.line_config.scl_io_type = IO_TYPE_EXPANDER;
|
||||
spi_config.line_config.scl_expander_pin = (esp_io_expander_pin_num_t)BIT(spi_config.line_config.scl_gpio_num);
|
||||
}
|
||||
if (sda_use_expander) {
|
||||
spi_config.line_config.sda_io_type = IO_TYPE_EXPANDER;
|
||||
spi_config.line_config.sda_expander_pin = (esp_io_expander_pin_num_t)BIT(spi_config.line_config.sda_gpio_num);
|
||||
}
|
||||
if (io_expander != NULL) {
|
||||
spi_config.line_config.io_expander = io_expander->getHandle();
|
||||
}
|
||||
}
|
||||
|
||||
bool ESP_PanelBus_RGB::begin(void)
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
if (host_need_init) {
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_new_panel_io_3wire_spi(&spi_config, &handle), false, "Create panel io failed");
|
||||
ESP_LOGD(TAG, "Create panel io @%p", handle);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const esp_lcd_rgb_panel_config_t *ESP_PanelBus_RGB::getRgbConfig()
|
||||
{
|
||||
return &rgb_config;
|
||||
}
|
||||
|
||||
#endif /* SOC_LCD_RGB_SUPPORTED */
|
||||
@@ -0,0 +1,328 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if SOC_LCD_RGB_SUPPORTED
|
||||
#include "esp_lcd_panel_rgb.h"
|
||||
#include "ESP_IOExpander.h"
|
||||
#include "base/esp_lcd_panel_io_additions.h"
|
||||
#include "ESP_PanelBus.h"
|
||||
|
||||
/**
|
||||
* For the ESP32-S3, the RGB peripheral only supports 16-bit RGB565.and 8-bit RGB888 color formats. For more details,
|
||||
* please refer to the part `Display > LCD Screen > RGB LCD Introduction` in ESP-IoT-Solution Programming Guide
|
||||
* (https://docs.espressif.com/projects/esp-iot-solution/en/latest/display/lcd/rgb_lcd.html#color-formats).
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Macro for 16-bit RGB timing configuration
|
||||
*
|
||||
* @note Typically, for a 480x480 LCD with 16-bit RGB565 color format, the refresh rate is 60Hz
|
||||
*/
|
||||
#define ESP_PANEL_RGB_TIMING_16BIT_CONFIG_DEFAULT(width, height) \
|
||||
{ \
|
||||
.pclk_hz = 16 * 1000 * 1000, \
|
||||
.h_res = width, \
|
||||
.v_res = height, \
|
||||
.hsync_pulse_width = 10, \
|
||||
.hsync_back_porch = 10, \
|
||||
.hsync_front_porch = 20, \
|
||||
.vsync_pulse_width = 10, \
|
||||
.vsync_back_porch = 10, \
|
||||
.vsync_front_porch = 10, \
|
||||
.flags = { \
|
||||
.hsync_idle_low = 0, \
|
||||
.vsync_idle_low = 0, \
|
||||
.de_idle_high = 0, \
|
||||
.pclk_active_neg = 0, \
|
||||
.pclk_idle_high = 0, \
|
||||
}, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Macro for 16-bit RGB565 RGB configuration
|
||||
*
|
||||
*/
|
||||
#define ESP_PANEL_RGB_16BIT_CONFIG_DEFAULT(width, height, \
|
||||
d0_io, d1_io, d2_io, d3_io, d4_io, d5_io, d6_io, d7_io, \
|
||||
d8_io, d9_io, d10_io, d11_io, d12_io, d13_io, d14_io, d15_io, \
|
||||
hsync_io, vsync_io, pclk_io, de_io, disp_io) \
|
||||
{ \
|
||||
.clk_src = LCD_CLK_SRC_DEFAULT, \
|
||||
.timings = ESP_PANEL_RGB_TIMING_16BIT_CONFIG_DEFAULT(width, height), \
|
||||
.data_width = 16, \
|
||||
.bits_per_pixel = 16, \
|
||||
.num_fbs = 1, \
|
||||
.bounce_buffer_size_px = 0, \
|
||||
.psram_trans_align = 64, \
|
||||
.hsync_gpio_num = hsync_io, \
|
||||
.vsync_gpio_num = vsync_io, \
|
||||
.de_gpio_num = de_io, \
|
||||
.pclk_gpio_num = pclk_io, \
|
||||
.disp_gpio_num = disp_io, \
|
||||
.data_gpio_nums = { \
|
||||
d0_io, d1_io, d2_io, d3_io, d4_io, d5_io, d6_io, d7_io, \
|
||||
d8_io, d9_io, d10_io, d11_io, d12_io, d13_io, d14_io, d15_io \
|
||||
}, \
|
||||
.flags = { \
|
||||
.disp_active_low = 0, \
|
||||
.refresh_on_demand = 0, \
|
||||
.fb_in_psram = 1, \
|
||||
.double_fb = 0, \
|
||||
.no_fb = 0, \
|
||||
.bb_invalidate_cache = 0, \
|
||||
}, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Macro for 8-bit RGB timing configuration
|
||||
*
|
||||
* @note Typically, for a 320x480 LCD with 8-bit RGB888 color format, the refresh rate is 48Hz
|
||||
*/
|
||||
#define ESP_PANEL_RGB_TIMING_8BIT_CONFIG_DEFAULT(width, height) \
|
||||
{ \
|
||||
.pclk_hz = 24 * 1000 * 1000, \
|
||||
.h_res = width, \
|
||||
.v_res = height, \
|
||||
.hsync_pulse_width = 3, \
|
||||
.hsync_back_porch = 3, \
|
||||
.hsync_front_porch = 6, \
|
||||
.vsync_pulse_width = 1, \
|
||||
.vsync_back_porch = 6, \
|
||||
.vsync_front_porch = 6, \
|
||||
.flags = { \
|
||||
.hsync_idle_low = 0, \
|
||||
.vsync_idle_low = 0, \
|
||||
.de_idle_high = 0, \
|
||||
.pclk_active_neg = 0, \
|
||||
.pclk_idle_high = 0, \
|
||||
}, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Macro for 8-bit RGB888 RGB configuration
|
||||
*
|
||||
*/
|
||||
#define ESP_PANEL_RGB_8BIT_CONFIG_DEFAULT(width, height, \
|
||||
d0_io, d1_io, d2_io, d3_io, d4_io, d5_io, d6_io, d7_io, \
|
||||
hsync_io, vsync_io, pclk_io, de_io, disp_io) \
|
||||
{ \
|
||||
.clk_src = LCD_CLK_SRC_DEFAULT, \
|
||||
.timings = ESP_PANEL_RGB_TIMING_8BIT_CONFIG_DEFAULT(width, height), \
|
||||
.data_width = 8, \
|
||||
.bits_per_pixel = 24, \
|
||||
.num_fbs = 1, \
|
||||
.bounce_buffer_size_px = 0, \
|
||||
.psram_trans_align = 64, \
|
||||
.hsync_gpio_num = hsync_io, \
|
||||
.vsync_gpio_num = vsync_io, \
|
||||
.de_gpio_num = de_io, \
|
||||
.pclk_gpio_num = pclk_io, \
|
||||
.disp_gpio_num = disp_io, \
|
||||
.data_gpio_nums = { \
|
||||
d0_io, d1_io, d2_io, d3_io, d4_io, d5_io, d6_io, d7_io, \
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, \
|
||||
}, \
|
||||
.flags = { \
|
||||
.disp_active_low = 0, \
|
||||
.refresh_on_demand = 0, \
|
||||
.fb_in_psram = 1, \
|
||||
.double_fb = 0, \
|
||||
.no_fb = 0, \
|
||||
.bb_invalidate_cache = 0, \
|
||||
}, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Macro for 3-wire SPI panel IO configuration
|
||||
*
|
||||
*/
|
||||
#define ESP_PANEL_IO_3WIRE_SPI_CONFIG_DEFAULT(cs_io, sck_io, sda_io) \
|
||||
{ \
|
||||
.line_config = { \
|
||||
.cs_io_type = IO_TYPE_GPIO, \
|
||||
.cs_gpio_num = cs_io, \
|
||||
.scl_io_type = IO_TYPE_GPIO, \
|
||||
.scl_gpio_num = sck_io, \
|
||||
.sda_io_type = IO_TYPE_GPIO, \
|
||||
.sda_gpio_num = sda_io, \
|
||||
.io_expander = NULL, \
|
||||
}, \
|
||||
.expect_clk_speed = PANEL_IO_3WIRE_SPI_CLK_MAX, \
|
||||
.spi_mode = 0, \
|
||||
.lcd_cmd_bytes = 1, \
|
||||
.lcd_param_bytes = 1, \
|
||||
.flags = { \
|
||||
.use_dc_bit = 1, \
|
||||
.dc_zero_on_data = 0, \
|
||||
.lsb_first = 0, \
|
||||
.cs_high_active = 0, \
|
||||
.del_keep_cs_inactive = 1, \
|
||||
}, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief RGB bus object class
|
||||
*
|
||||
* @note This class is a derived class of `ESP_PanelBus`, user can use it directly
|
||||
*/
|
||||
class ESP_PanelBus_RGB: public ESP_PanelBus {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a 3-wire SPI + 16-bit RGB bus object in a common way, the 3-wire SPI host will be initialized
|
||||
* by the driver
|
||||
*
|
||||
* @note This function uses some default values (ESP_PANEL_IO_3WIRE_SPI_CONFIG_DEFAULT and
|
||||
* ESP_PANEL_RGB_16BIT_CONFIG_DEFAULT) to config the bus object, use `config*()` functions to change them
|
||||
* @note The `init()` function should be called after this function
|
||||
*
|
||||
* @param width The width of the panel (horizontal resolution)
|
||||
* @param height The height of the panel (vertical resolution)
|
||||
* @param cs_io 3-wire SPI CS pin
|
||||
* @param sck_io 3-wire SPI SCK pin
|
||||
* @param sda_io 3-wire SPI SDA pin
|
||||
* @param dN_io RGB data pins, N is [0, 15]
|
||||
* @param hsync_io RGB HSYNC pin
|
||||
* @param vsync_io RGB VSYNC pin
|
||||
* @param pclk_io RGB PCLK pin
|
||||
* @param de_io RGB DE pin, set to -1 if not used
|
||||
* @param disp_io RGB DISP pin, default is -1
|
||||
*/
|
||||
ESP_PanelBus_RGB(uint16_t width, uint16_t height,
|
||||
int cs_io, int sck_io, int sda_io,
|
||||
int d0_io, int d1_io, int d2_io, int d3_io, int d4_io, int d5_io, int d6_io, int d7_io,
|
||||
int d8_io, int d9_io, int d10_io, int d11_io, int d12_io, int d13_io, int d14_io, int d15_io,
|
||||
int hsync_io, int vsync_io, int pclk_io, int de_io, int disp_io = -1);
|
||||
|
||||
/**
|
||||
* @brief Construct a 3-wire SPI + 8-bit RGB bus object in a common way, the 3-wire SPI host will be initialized
|
||||
* by the driver
|
||||
*
|
||||
* @note This function uses some default values (ESP_PANEL_IO_3WIRE_SPI_CONFIG_DEFAULT and
|
||||
* ESP_PANEL_RGB_8BIT_CONFIG_DEFAULT) to config the bus object, use `config*()` functions to change them
|
||||
* @note The `init()` function should be called after this function
|
||||
*
|
||||
* @param width The width of the panel (horizontal resolution)
|
||||
* @param height The height of the panel (vertical resolution)
|
||||
* @param cs_io 3-wire SPI CS pin
|
||||
* @param sck_io 3-wire SPI SCK pin
|
||||
* @param sda_io 3-wire SPI SDA pin
|
||||
* @param dN_io RGB data pins, N is [0, 7]
|
||||
* @param hsync_io RGB HSYNC pin
|
||||
* @param vsync_io RGB VSYNC pin
|
||||
* @param pclk_io RGB PCLK pin
|
||||
* @param de_io RGB DE pin, set to -1 if not used
|
||||
* @param disp_io RGB DISP pin, default is -1
|
||||
*/
|
||||
ESP_PanelBus_RGB(uint16_t width, uint16_t height,
|
||||
int cs_io, int sck_io, int sda_io,
|
||||
int d0_io, int d1_io, int d2_io, int d3_io, int d4_io, int d5_io, int d6_io, int d7_io,
|
||||
int hsync_io, int vsync_io, int pclk_io, int de_io, int disp_io = -1);
|
||||
|
||||
/**
|
||||
* @brief Construct a single 16-bit RGB bus object in a common way, no host will be initialized
|
||||
*
|
||||
* @note This function uses some default values (ESP_PANEL_RGB_16BIT_CONFIG_DEFAULT) to config the bus object,
|
||||
* use `config*()` functions to change them
|
||||
* @note The `init()` function should be called after this function
|
||||
*
|
||||
* @param width The width of the panel (horizontal resolution)
|
||||
* @param height The height of the panel (vertical resolution)
|
||||
* @param dN_io RGB data pins, N is [0, 16]
|
||||
* @param hsync_io RGB HSYNC pin
|
||||
* @param vsync_io RGB VSYNC pin
|
||||
* @param pclk_io RGB PCLK pin
|
||||
* @param de_io RGB DE pin, set to -1 if not used
|
||||
* @param disp_io RGB DISP pin, default is -1
|
||||
*/
|
||||
ESP_PanelBus_RGB(uint16_t width, uint16_t height,
|
||||
int d0_io, int d1_io, int d2_io, int d3_io, int d4_io, int d5_io, int d6_io, int d7_io,
|
||||
int d8_io, int d9_io, int d10_io, int d11_io, int d12_io, int d13_io, int d14_io, int d15_io,
|
||||
int hsync_io, int vsync_io, int pclk_io, int de_io, int disp_io = -1);
|
||||
|
||||
/**
|
||||
* @brief Construct a single 8-bit RGB bus object in a common way, no host will be initialized
|
||||
*
|
||||
* @note This function uses some default values (ESP_PANEL_RGB_8BIT_CONFIG_DEFAULT) to config the bus object,
|
||||
* use `config*()` functions to change them
|
||||
* @note The `init()` function should be called after this function
|
||||
*
|
||||
* @param width The width of the panel (horizontal resolution)
|
||||
* @param height The height of the panel (vertical resolution)
|
||||
* @param dN_io RGB data pins, N is [0, 16]
|
||||
* @param hsync_io RGB HSYNC pin
|
||||
* @param vsync_io RGB VSYNC pin
|
||||
* @param pclk_io RGB PCLK pin
|
||||
* @param de_io RGB DE pin, set to -1 if not used
|
||||
* @param disp_io RGB DISP pin, default is -1
|
||||
*/
|
||||
ESP_PanelBus_RGB(uint16_t width, uint16_t height,
|
||||
int d0_io, int d1_io, int d2_io, int d3_io, int d4_io, int d5_io, int d6_io, int d7_io,
|
||||
int hsync_io, int vsync_io, int pclk_io, int de_io, int disp_io = -1);
|
||||
|
||||
/**
|
||||
* @brief Construct a 3-wire SPI + 16-bit RGB bus object in a complex way, the 3-wire SPI host will be initialized
|
||||
* by the driver
|
||||
*
|
||||
* @note The `init()` function should be called after this function
|
||||
*
|
||||
* @param spi_config 3-wire SPI panel IO configuration
|
||||
* @param rgb_config RGB configuration
|
||||
* @param host_id Host ID, it is only used to maintain consistency in formatting and set to `-1` by default
|
||||
*/
|
||||
ESP_PanelBus_RGB(const esp_lcd_panel_io_3wire_spi_config_t &io_config, const esp_lcd_rgb_panel_config_t &rgb_config,
|
||||
int host_id = -1);
|
||||
|
||||
/**
|
||||
* @brief Construct a single RGB bus object in a complex way, no host will be initialized
|
||||
*
|
||||
* @note The `init()` function should be called after this function
|
||||
*
|
||||
* @param rgb_config RGB configuration
|
||||
* @param host_id Host ID, it is only used to maintain consistency in formatting and set to `-1` by default
|
||||
*/
|
||||
ESP_PanelBus_RGB(const esp_lcd_rgb_panel_config_t &rgb_config, int host_id = -1);
|
||||
|
||||
/**
|
||||
* @brief Destroy the RGB bus object
|
||||
*
|
||||
*/
|
||||
~ESP_PanelBus_RGB() override;
|
||||
|
||||
/**
|
||||
* @brief Here are some functions to configure the RGB bus object
|
||||
*
|
||||
* @note These functions should be called before `begin()`
|
||||
*
|
||||
*/
|
||||
void configRgbTimingFreqHz(uint32_t hz);
|
||||
void configRgbTimingPorch(uint16_t hpw, uint16_t hbp, uint16_t hfp, uint16_t vpw, uint16_t vbp, uint16_t vfp);
|
||||
void configRgbTimingFlags(bool hsync_idle_low, bool vsync_idle_low, bool de_idle_high, bool pclk_active_neg,
|
||||
bool pclk_idle_high);
|
||||
void configRgbFrameBufferNumber(uint8_t num);
|
||||
void configRgbBounceBufferSize(uint32_t size_in_pixel);
|
||||
void configRgbFlagDispActiveLow(void);
|
||||
void configSpiLine(bool cs_use_expaneer, bool sck_use_expander, bool sda_use_expander, ESP_IOExpander *io_expander);
|
||||
|
||||
/**
|
||||
* @brief Startup the bus.
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool begin(void) override;
|
||||
|
||||
const esp_lcd_rgb_panel_config_t *getRgbConfig();
|
||||
|
||||
private:
|
||||
esp_lcd_rgb_panel_config_t rgb_config;
|
||||
esp_lcd_panel_io_3wire_spi_config_t spi_config;
|
||||
};
|
||||
|
||||
#endif /* SOC_LCD_RGB_SUPPORTED */
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "host/ESP_PanelHost.h"
|
||||
#include "SPI.h"
|
||||
|
||||
static const char *TAG = "ESP_PanelBus_SPI";
|
||||
|
||||
ESP_PanelBus_SPI::ESP_PanelBus_SPI(int cs_io, int dc_io, int sck_io, int sda_io, int sdo_io):
|
||||
ESP_PanelBus((int)ESP_PANEL_HOST_SPI_ID_DEFAULT, ESP_PANEL_BUS_TYPE_SPI, true),
|
||||
host_config((spi_bus_config_t)ESP_PANEL_HOST_SPI_CONFIG_DEFAULT(sck_io, sda_io, sdo_io)),
|
||||
io_config((esp_lcd_panel_io_spi_config_t)ESP_PANEL_IO_SPI_CONFIG_DEFAULT(cs_io, dc_io))
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelBus_SPI::ESP_PanelBus_SPI(int sck_io, int mosi_io, int miso_io, const esp_lcd_panel_io_spi_config_t &io_config):
|
||||
ESP_PanelBus((int)ESP_PANEL_HOST_SPI_ID_DEFAULT, ESP_PANEL_BUS_TYPE_SPI, true),
|
||||
host_config((spi_bus_config_t)ESP_PANEL_HOST_SPI_CONFIG_DEFAULT(sck_io, mosi_io, miso_io)),
|
||||
io_config(io_config)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelBus_SPI::ESP_PanelBus_SPI(int cs_io, int dc_io):
|
||||
ESP_PanelBus((int)ESP_PANEL_HOST_SPI_ID_DEFAULT, ESP_PANEL_BUS_TYPE_SPI, false),
|
||||
io_config((esp_lcd_panel_io_spi_config_t)ESP_PANEL_IO_SPI_CONFIG_DEFAULT(cs_io, dc_io))
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelBus_SPI::ESP_PanelBus_SPI(const spi_bus_config_t &host_config, const esp_lcd_panel_io_spi_config_t &io_config,
|
||||
spi_host_device_t host_id):
|
||||
ESP_PanelBus((int)host_id, ESP_PANEL_BUS_TYPE_SPI, true),
|
||||
host_config(host_config),
|
||||
io_config(io_config)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelBus_SPI::ESP_PanelBus_SPI(const esp_lcd_panel_io_spi_config_t &io_config, spi_host_device_t host_id):
|
||||
ESP_PanelBus((int)host_id, ESP_PANEL_BUS_TYPE_SPI, false),
|
||||
io_config(io_config)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelBus_SPI::~ESP_PanelBus_SPI()
|
||||
{
|
||||
if (handle == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!del()) {
|
||||
ESP_LOGE(TAG, "Delete panel io failed");
|
||||
}
|
||||
|
||||
if (host_need_init) {
|
||||
if (spi_bus_free((spi_host_device_t)host_id) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Delete host[%d] driver failed", host_id);
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Delete host[%d] driver", host_id);
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
ESP_LOGD(TAG, "Destroyed");
|
||||
}
|
||||
|
||||
void ESP_PanelBus_SPI::configSpiMode(uint8_t mode)
|
||||
{
|
||||
io_config.spi_mode = mode;
|
||||
}
|
||||
|
||||
void ESP_PanelBus_SPI::configSpiFreqHz(uint32_t hz)
|
||||
{
|
||||
io_config.pclk_hz = hz;
|
||||
}
|
||||
|
||||
void ESP_PanelBus_SPI::configSpiCommandBits(uint32_t num)
|
||||
{
|
||||
io_config.lcd_cmd_bits = num;
|
||||
}
|
||||
|
||||
void ESP_PanelBus_SPI::configSpiParamBits(uint32_t num)
|
||||
{
|
||||
io_config.lcd_param_bits = num;
|
||||
}
|
||||
|
||||
void ESP_PanelBus_SPI::configSpiTransQueueDepth(uint8_t depth)
|
||||
{
|
||||
io_config.trans_queue_depth = depth;
|
||||
}
|
||||
|
||||
bool ESP_PanelBus_SPI::begin(void)
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
if (host_need_init) {
|
||||
ESP_PANEL_CHECK_ERR_RET(spi_bus_initialize((spi_host_device_t)host_id, &host_config, SPI_DMA_CH_AUTO), false,
|
||||
"Initializeost Host[%d] failed", host_id);
|
||||
ESP_LOGD(TAG, "Init host[%d]", host_id);
|
||||
}
|
||||
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)host_id, &io_config, &handle), false,
|
||||
"Create panel io failed");
|
||||
ESP_LOGD(TAG, "Create panel io @%p", handle);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "driver/spi_master.h"
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "host/ESP_PanelHost.h"
|
||||
#include "ESP_PanelBus.h"
|
||||
|
||||
/**
|
||||
* @brief Macro for SPI panel IO configuration
|
||||
*
|
||||
*/
|
||||
#define ESP_PANEL_IO_SPI_CONFIG_DEFAULT(cs_io, dc_io) \
|
||||
{ \
|
||||
.cs_gpio_num = cs_io, \
|
||||
.dc_gpio_num = dc_io, \
|
||||
.spi_mode = 0, \
|
||||
.pclk_hz = SPI_MASTER_FREQ_40M, \
|
||||
.trans_queue_depth = 10, \
|
||||
.on_color_trans_done = NULL, \
|
||||
.user_ctx = NULL, \
|
||||
.lcd_cmd_bits = 8, \
|
||||
.lcd_param_bits = 8, \
|
||||
.flags = { \
|
||||
.dc_low_on_data = 0, \
|
||||
.octal_mode = 0, \
|
||||
.quad_mode = 0, \
|
||||
.sio_mode = 0, \
|
||||
.lsb_first = 0, \
|
||||
.cs_high_active = 0, \
|
||||
}, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SPI bus object class
|
||||
*
|
||||
* @note This class is a derived class of `ESP_PanelBus`, user can use it directly
|
||||
*/
|
||||
class ESP_PanelBus_SPI: public ESP_PanelBus {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a SPI bus object in a common way, the host will be initialized by the driver
|
||||
*
|
||||
* @note This function uses some default values (ESP_PANEL_HOST_SPI_CONFIG_DEFAULT && ESP_PANEL_IO_SPI_CONFIG_DEFAULT)
|
||||
* to config the bus object, use `config*()` functions to change them
|
||||
* @note The `init()` function should be called after this function
|
||||
*
|
||||
* @param cs_io SPI CS pin
|
||||
* @param dc_io SPI DC pin
|
||||
* @param sck_io SPI SCK pin
|
||||
* @param sda_io SPI MOSI pin
|
||||
* @param sdo_io SPI MISO pin, default is `-1`
|
||||
*/
|
||||
ESP_PanelBus_SPI(int cs_io, int dc_io, int sck_io, int sda_io, int sdo_io = -1);
|
||||
|
||||
/**
|
||||
* @brief Construct a SPI bus object in a common way, the host will be initialized by the driver
|
||||
*
|
||||
* @note This function uses some default values (ESP_PANEL_HOST_SPI_CONFIG_DEFAULT) to config the bus object,
|
||||
* use `config*()` functions to change them
|
||||
* @note The `init()` function should be called after this function
|
||||
*
|
||||
* @param sck_io SPI SCK pin
|
||||
* @param mosi_io SPI MOSI pin
|
||||
* @param miso_io SPI MISO pin
|
||||
* @param io_config SPI panel IO configuration
|
||||
*/
|
||||
ESP_PanelBus_SPI(int sck_io, int mosi_io, int miso_io, const esp_lcd_panel_io_spi_config_t &io_config);
|
||||
|
||||
/**
|
||||
* @brief Construct a SPI bus object in a common way, the host needs to be initialized by the user
|
||||
*
|
||||
* @note This function uses some default values (ESP_PANEL_IO_SPI_CONFIG_DEFAULT) to config the bus object,
|
||||
* use `config*()` functions to change them
|
||||
* @note The `init()` function should be called after this function
|
||||
*
|
||||
* @param cs_io SPI CS pin
|
||||
* @param dc_io SPI DC pin
|
||||
*/
|
||||
ESP_PanelBus_SPI(int cs_io, int dc_io);
|
||||
|
||||
/**
|
||||
* @brief Construct a SPI bus object in a complex way, the host will be initialized by the driver
|
||||
*
|
||||
* @note The `init()` function should be called after this function
|
||||
*
|
||||
* @param host_config SPI host configuration
|
||||
* @param io_config SPI panel IO configuration
|
||||
* @param host_id SPI host ID, default is `ESP_PANEL_HOST_SPI_ID_DEFAULT`
|
||||
*/
|
||||
ESP_PanelBus_SPI(const spi_bus_config_t &host_config, const esp_lcd_panel_io_spi_config_t &io_config,
|
||||
spi_host_device_t host_id = ESP_PANEL_HOST_SPI_ID_DEFAULT);
|
||||
|
||||
/**
|
||||
* @brief Construct a SPI bus object in a complex way, the host needs to be initialized by the user
|
||||
*
|
||||
* @note The `init()` function should be called after this function
|
||||
*
|
||||
* @param io_config SPI panel IO configuration
|
||||
* @param host_id SPI host ID, default is `ESP_PANEL_HOST_SPI_ID_DEFAULT`
|
||||
*/
|
||||
ESP_PanelBus_SPI(const esp_lcd_panel_io_spi_config_t &io_config, spi_host_device_t host_id = ESP_PANEL_HOST_SPI_ID_DEFAULT);
|
||||
|
||||
/**
|
||||
* @brief Destroy the SPI bus object
|
||||
*
|
||||
*/
|
||||
~ESP_PanelBus_SPI() override;
|
||||
|
||||
/**
|
||||
* @brief Here are some functions to configure the SPI bus object. These functions should be called before `begin()`
|
||||
*
|
||||
*/
|
||||
void configSpiMode(uint8_t mode);
|
||||
void configSpiFreqHz(uint32_t hz);
|
||||
void configSpiCommandBits(uint32_t num);
|
||||
void configSpiParamBits(uint32_t num);
|
||||
void configSpiTransQueueDepth(uint8_t depth);
|
||||
|
||||
/**
|
||||
* @brief Startup the bus
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool begin(void) override;
|
||||
|
||||
private:
|
||||
spi_bus_config_t host_config;
|
||||
esp_lcd_panel_io_spi_config_t io_config;
|
||||
};
|
||||
+447
@@ -0,0 +1,447 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/spi_master.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_lcd_panel_io_interface.h"
|
||||
|
||||
#include "esp_lcd_panel_io_additions.h"
|
||||
|
||||
#define LCD_CMD_BYTES_MAX (sizeof(uint32_t)) // Maximum number of bytes for LCD command
|
||||
#define LCD_PARAM_BYTES_MAX (sizeof(uint32_t)) // Maximum number of bytes for LCD parameter
|
||||
|
||||
#define DATA_DC_BIT_0 (0) // DC bit = 0
|
||||
#define DATA_DC_BIT_1 (1) // DC bit = 1
|
||||
#define DATA_NO_DC_BIT (2) // No DC bit
|
||||
#define WRITE_ORDER_LSB_MASK (0x01) // Bit mask for LSB first write order
|
||||
#define WRITE_ORDER_MSB_MASK (0x80) // Bit mask for MSB first write order
|
||||
|
||||
/**
|
||||
* @brief Enumeration of SPI lines
|
||||
*/
|
||||
typedef enum {
|
||||
CS = 0,
|
||||
SCL,
|
||||
SDA,
|
||||
} spi_line_t;
|
||||
|
||||
/**
|
||||
* @brief Panel IO instance for 3-wire SPI interface
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
esp_lcd_panel_io_t base; /*!< Base class of generic lcd panel io */
|
||||
panel_io_type_t cs_io_type; /*!< IO type of CS line */
|
||||
int cs_io_num; /*!< IO used for CS line */
|
||||
panel_io_type_t scl_io_type; /*!< IO type of SCL line */
|
||||
int scl_io_num; /*!< IO used for SCL line */
|
||||
panel_io_type_t sda_io_type; /*!< IO type of SDA line */
|
||||
int sda_io_num; /*!< GPIO used for SDA line */
|
||||
esp_io_expander_handle_t io_expander; /*!< IO expander handle, set to NULL if not used */
|
||||
uint32_t scl_half_period_us; /*!< SCL half period in us */
|
||||
uint32_t lcd_cmd_bytes: 3; /*!< Bytes of LCD command (1 ~ 4) */
|
||||
uint32_t cmd_dc_bit: 2; /*!< DC bit of command */
|
||||
uint32_t lcd_param_bytes: 3; /*!< Bytes of LCD parameter (1 ~ 4) */
|
||||
uint32_t param_dc_bit: 2; /*!< DC bit of parameter */
|
||||
uint32_t write_order_mask: 8; /*!< Bit mask of write order */
|
||||
struct {
|
||||
uint32_t cs_high_active: 1; /*!< If this flag is enabled, CS line is high active */
|
||||
uint32_t sda_scl_idle_high: 1; /*!< If this flag is enabled, SDA and SCL line are high when idle */
|
||||
uint32_t scl_active_rising_edge: 1; /*!< If this flag is enabled, SCL line is active on rising edge */
|
||||
uint32_t del_keep_cs_inactive: 1; /*!< If this flag is enabled, keep CS line inactive even if panel_io is deleted */
|
||||
} flags;
|
||||
} esp_lcd_panel_io_3wire_spi_t;
|
||||
|
||||
static const char *TAG = "lcd_panel.io.3wire_spi";
|
||||
|
||||
static esp_err_t panel_io_rx_param(esp_lcd_panel_io_t *io, int lcd_cmd, void *param, size_t param_size);
|
||||
static esp_err_t panel_io_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, const void *param, size_t param_size);
|
||||
static esp_err_t panel_io_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, const void *color, size_t color_size);
|
||||
static esp_err_t panel_io_del(esp_lcd_panel_io_t *io);
|
||||
static esp_err_t panel_io_register_event_callbacks(esp_lcd_panel_io_handle_t io, const esp_lcd_panel_io_callbacks_t *cbs, void *user_ctx);
|
||||
|
||||
static esp_err_t set_line_level(esp_lcd_panel_io_3wire_spi_t *panel_io, spi_line_t line, uint32_t level);
|
||||
static esp_err_t reset_line_io(esp_lcd_panel_io_3wire_spi_t *panel_io, spi_line_t line);
|
||||
static esp_err_t spi_write_package(esp_lcd_panel_io_3wire_spi_t *panel_io, bool is_cmd, uint32_t data);
|
||||
|
||||
esp_err_t esp_lcd_new_panel_io_3wire_spi(const esp_lcd_panel_io_3wire_spi_config_t *io_config, esp_lcd_panel_io_handle_t *ret_io)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(io_config && ret_io, ESP_ERR_INVALID_ARG, TAG, "Invalid argument");
|
||||
ESP_RETURN_ON_FALSE(io_config->expect_clk_speed <= PANEL_IO_3WIRE_SPI_CLK_MAX, ESP_ERR_INVALID_ARG, TAG, "Invalid Clock frequency");
|
||||
ESP_RETURN_ON_FALSE(io_config->lcd_cmd_bytes > 0 && io_config->lcd_cmd_bytes <= LCD_CMD_BYTES_MAX, ESP_ERR_INVALID_ARG,
|
||||
TAG, "Invalid LCD command bytes");
|
||||
ESP_RETURN_ON_FALSE(io_config->lcd_param_bytes > 0 && io_config->lcd_param_bytes <= LCD_PARAM_BYTES_MAX, ESP_ERR_INVALID_ARG,
|
||||
TAG, "Invalid LCD parameter bytes");
|
||||
|
||||
const spi_line_config_t *line_config = &io_config->line_config;
|
||||
ESP_RETURN_ON_FALSE(line_config->io_expander || (line_config->cs_io_type == IO_TYPE_GPIO &&
|
||||
line_config->scl_io_type == IO_TYPE_GPIO && line_config->sda_io_type == IO_TYPE_GPIO),
|
||||
ESP_ERR_INVALID_ARG, TAG, "IO Expander handle is required if any IO is not gpio");
|
||||
|
||||
esp_lcd_panel_io_3wire_spi_t *panel_io = calloc(1, sizeof(esp_lcd_panel_io_3wire_spi_t));
|
||||
ESP_RETURN_ON_FALSE(panel_io, ESP_ERR_NO_MEM, TAG, "No memory");
|
||||
|
||||
panel_io->cs_io_type = line_config->cs_io_type;
|
||||
panel_io->cs_io_num = line_config->cs_gpio_num;
|
||||
panel_io->scl_io_type = line_config->scl_io_type;
|
||||
panel_io->scl_io_num = line_config->scl_gpio_num;
|
||||
panel_io->sda_io_type = line_config->sda_io_type;
|
||||
panel_io->sda_io_num = line_config->sda_gpio_num;
|
||||
panel_io->io_expander = line_config->io_expander;
|
||||
uint32_t expect_clk_speed = io_config->expect_clk_speed ? io_config->expect_clk_speed : PANEL_IO_3WIRE_SPI_CLK_MAX;
|
||||
panel_io->scl_half_period_us = 1000000 / (expect_clk_speed * 2);
|
||||
panel_io->lcd_cmd_bytes = io_config->lcd_cmd_bytes;
|
||||
panel_io->lcd_param_bytes = io_config->lcd_param_bytes;
|
||||
if (io_config->flags.use_dc_bit) {
|
||||
panel_io->param_dc_bit = io_config->flags.dc_zero_on_data ? DATA_DC_BIT_0 : DATA_DC_BIT_1;
|
||||
panel_io->cmd_dc_bit = io_config->flags.dc_zero_on_data ? DATA_DC_BIT_1 : DATA_DC_BIT_0;
|
||||
} else {
|
||||
panel_io->param_dc_bit = DATA_NO_DC_BIT;
|
||||
panel_io->cmd_dc_bit = DATA_NO_DC_BIT;
|
||||
}
|
||||
panel_io->write_order_mask = io_config->flags.lsb_first ? WRITE_ORDER_LSB_MASK : WRITE_ORDER_MSB_MASK;
|
||||
panel_io->flags.cs_high_active = io_config->flags.cs_high_active;
|
||||
panel_io->flags.del_keep_cs_inactive = io_config->flags.del_keep_cs_inactive;
|
||||
panel_io->flags.sda_scl_idle_high = io_config->spi_mode & 0x1;
|
||||
if (panel_io->flags.sda_scl_idle_high) {
|
||||
panel_io->flags.scl_active_rising_edge = (io_config->spi_mode & 0x2) ? 1 : 0;
|
||||
} else {
|
||||
panel_io->flags.scl_active_rising_edge = (io_config->spi_mode & 0x2) ? 0 : 1;
|
||||
}
|
||||
|
||||
panel_io->base.rx_param = panel_io_rx_param;
|
||||
panel_io->base.tx_param = panel_io_tx_param;
|
||||
panel_io->base.tx_color = panel_io_tx_color;
|
||||
panel_io->base.del = panel_io_del;
|
||||
panel_io->base.register_event_callbacks = panel_io_register_event_callbacks;
|
||||
|
||||
// Get GPIO mask and IO expander pin mask
|
||||
esp_err_t ret = ESP_OK;
|
||||
int64_t gpio_mask = 0;
|
||||
uint32_t expander_pin_mask = 0;
|
||||
if (panel_io->cs_io_type == IO_TYPE_GPIO) {
|
||||
gpio_mask |= BIT64(panel_io->cs_io_num);
|
||||
} else {
|
||||
expander_pin_mask |= panel_io->cs_io_num;
|
||||
}
|
||||
if (panel_io->scl_io_type == IO_TYPE_GPIO) {
|
||||
gpio_mask |= BIT64(panel_io->scl_io_num);
|
||||
} else {
|
||||
expander_pin_mask |= panel_io->scl_io_num;
|
||||
}
|
||||
if (panel_io->sda_io_type == IO_TYPE_GPIO) {
|
||||
gpio_mask |= BIT64(panel_io->sda_io_num);
|
||||
} else {
|
||||
expander_pin_mask |= panel_io->sda_io_num;
|
||||
}
|
||||
// Configure GPIOs
|
||||
if (gpio_mask) {
|
||||
ESP_GOTO_ON_ERROR(gpio_config(&((gpio_config_t) {
|
||||
.pin_bit_mask = gpio_mask,
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pull_up_en = GPIO_PULLUP_DISABLE,
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||
.intr_type = GPIO_INTR_DISABLE,
|
||||
})), err, TAG, "GPIO config failed");
|
||||
}
|
||||
// Configure pins of IO expander
|
||||
if (expander_pin_mask) {
|
||||
ESP_GOTO_ON_ERROR(esp_io_expander_set_dir(panel_io->io_expander, expander_pin_mask, IO_EXPANDER_OUTPUT), err,
|
||||
TAG, "Expander set dir failed");
|
||||
}
|
||||
|
||||
// Set CS, SCL and SDA to idle level
|
||||
uint32_t cs_idle_level = panel_io->flags.cs_high_active ? 0 : 1;
|
||||
uint32_t sda_scl_idle_level = panel_io->flags.sda_scl_idle_high ? 1 : 0;
|
||||
ESP_GOTO_ON_ERROR(set_line_level(panel_io, CS, cs_idle_level), err, TAG, "Set CS level failed");
|
||||
ESP_GOTO_ON_ERROR(set_line_level(panel_io, SCL, sda_scl_idle_level), err, TAG, "Set SCL level failed");
|
||||
ESP_GOTO_ON_ERROR(set_line_level(panel_io, SDA, sda_scl_idle_level), err, TAG, "Set SDA level failed");
|
||||
|
||||
*ret_io = (esp_lcd_panel_io_handle_t)panel_io;
|
||||
return ESP_OK;
|
||||
|
||||
err:
|
||||
if (gpio_mask) {
|
||||
for (int i = 0; i < 64; i++) {
|
||||
if (gpio_mask & BIT64(i)) {
|
||||
gpio_reset_pin(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (expander_pin_mask) {
|
||||
esp_io_expander_set_dir(panel_io->io_expander, expander_pin_mask, IO_EXPANDER_INPUT);
|
||||
}
|
||||
free(panel_io);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t panel_io_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, const void *param, size_t param_size)
|
||||
{
|
||||
esp_lcd_panel_io_3wire_spi_t *panel_io = __containerof(io, esp_lcd_panel_io_3wire_spi_t, base);
|
||||
|
||||
// Send command
|
||||
if (lcd_cmd >= 0) {
|
||||
ESP_RETURN_ON_ERROR(spi_write_package(panel_io, true, lcd_cmd), TAG, "SPI write package failed");
|
||||
}
|
||||
|
||||
// Send parameter
|
||||
if (param != NULL && param_size > 0) {
|
||||
uint32_t param_data = 0;
|
||||
uint32_t param_bytes = panel_io->lcd_param_bytes;
|
||||
size_t param_count = param_size / param_bytes;
|
||||
|
||||
// Iteratively get parameter packages and send them one by one
|
||||
for (int i = 0; i < param_count; i++) {
|
||||
param_data = 0;
|
||||
for (int j = 0; j < param_bytes; j++) {
|
||||
param_data |= ((uint8_t *)param)[i * param_bytes + j] << (j * 8);
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(spi_write_package(panel_io, false, param_data), TAG, "SPI write package failed");
|
||||
}
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_io_del(esp_lcd_panel_io_t *io)
|
||||
{
|
||||
esp_lcd_panel_io_3wire_spi_t *panel_io = __containerof(io, esp_lcd_panel_io_3wire_spi_t, base);
|
||||
|
||||
if (!panel_io->flags.del_keep_cs_inactive) {
|
||||
ESP_RETURN_ON_ERROR(reset_line_io(panel_io, CS), TAG, "Reset CS line failed");
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Delete but keep CS line inactive");
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(reset_line_io(panel_io, SCL), TAG, "Reset SCL line failed");
|
||||
ESP_RETURN_ON_ERROR(reset_line_io(panel_io, SDA), TAG, "Reset SDA line failed");
|
||||
free(panel_io);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function is not ready and only for compatibility
|
||||
*/
|
||||
static esp_err_t panel_io_rx_param(esp_lcd_panel_io_t *io, int lcd_cmd, void *param, size_t param_size)
|
||||
{
|
||||
ESP_LOGE(TAG, "Rx param is not supported");
|
||||
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function is not ready and only for compatibility
|
||||
*/
|
||||
static esp_err_t panel_io_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, const void *color, size_t color_size)
|
||||
{
|
||||
ESP_LOGE(TAG, "Tx color is not supported");
|
||||
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function is not ready and only for compatibility
|
||||
*/
|
||||
static esp_err_t panel_io_register_event_callbacks(esp_lcd_panel_io_handle_t io, const esp_lcd_panel_io_callbacks_t *cbs, void *user_ctx)
|
||||
{
|
||||
ESP_LOGE(TAG, "Register event callbacks is not supported");
|
||||
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the level of specified line.
|
||||
*
|
||||
* This function can use GPIO or IO expander according to the type of line
|
||||
*
|
||||
* @param[in] panel_io Pointer to panel IO instance
|
||||
* @param[in] line Target line
|
||||
* @param[out] level Target level, 0 - Low, 1 - High
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - ESP_ERR_INVALID_ARG: Invalid argument
|
||||
* - Others: Fail
|
||||
*/
|
||||
static esp_err_t set_line_level(esp_lcd_panel_io_3wire_spi_t *panel_io, spi_line_t line, uint32_t level)
|
||||
{
|
||||
panel_io_type_t line_type = IO_TYPE_GPIO;
|
||||
int line_io = 0;
|
||||
switch (line) {
|
||||
case CS:
|
||||
line_type = panel_io->cs_io_type;
|
||||
line_io = panel_io->cs_io_num;
|
||||
break;
|
||||
case SCL:
|
||||
line_type = panel_io->scl_io_type;
|
||||
line_io = panel_io->scl_io_num;
|
||||
break;
|
||||
case SDA:
|
||||
line_type = panel_io->sda_io_type;
|
||||
line_io = panel_io->sda_io_num;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (line_type == IO_TYPE_GPIO) {
|
||||
// ESP_LOGE(TAG, "line_io: %d, level: %d", line_io, level);
|
||||
return gpio_set_level(line_io, level);
|
||||
} else {
|
||||
return esp_io_expander_set_level(panel_io->io_expander, (esp_io_expander_pin_num_t)line_io, level != 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset the IO of specified line
|
||||
*
|
||||
* This function can use GPIO or IO expander according to the type of line
|
||||
*
|
||||
* @param[in] panel_io Pointer to panel IO instance
|
||||
* @param[in] line Target line
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - ESP_ERR_INVALID_ARG: Invalid argument
|
||||
* - Others: Fail
|
||||
*/
|
||||
static esp_err_t reset_line_io(esp_lcd_panel_io_3wire_spi_t *panel_io, spi_line_t line)
|
||||
{
|
||||
panel_io_type_t line_type = IO_TYPE_GPIO;
|
||||
int line_io = 0;
|
||||
switch (line) {
|
||||
case CS:
|
||||
line_type = panel_io->cs_io_type;
|
||||
line_io = panel_io->cs_io_num;
|
||||
break;
|
||||
case SCL:
|
||||
line_type = panel_io->scl_io_type;
|
||||
line_io = panel_io->scl_io_num;
|
||||
break;
|
||||
case SDA:
|
||||
line_type = panel_io->sda_io_type;
|
||||
line_io = panel_io->sda_io_num;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (line_type == IO_TYPE_GPIO) {
|
||||
return gpio_reset_pin(line_io);
|
||||
} else {
|
||||
return esp_io_expander_set_dir(panel_io->io_expander, (esp_io_expander_pin_num_t)line_io, IO_EXPANDER_INPUT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Delay for given microseconds
|
||||
*
|
||||
* @note This function uses `esp_rom_delay_us()` for delays < 1000us and `vTaskDelay()` for longer delays.
|
||||
*
|
||||
* @param[in] delay_us Delay time in microseconds
|
||||
*
|
||||
*/
|
||||
static void delay_us(uint32_t delay_us)
|
||||
{
|
||||
if (delay_us >= 1000) {
|
||||
vTaskDelay(pdMS_TO_TICKS(delay_us / 1000));
|
||||
} else {
|
||||
esp_rom_delay_us(delay_us);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write one byte to LCD panel
|
||||
*
|
||||
* @param[in] panel_io Pointer to panel IO instance
|
||||
* @param[in] dc_bit DC bit
|
||||
* @param[in] data 8-bit data to write
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - ESP_ERR_INVALID_ARG: Invalid argument
|
||||
* - Others: Fail
|
||||
*/
|
||||
static esp_err_t spi_write_byte(esp_lcd_panel_io_3wire_spi_t *panel_io, int dc_bit, uint8_t data)
|
||||
{
|
||||
uint16_t data_temp = data;
|
||||
uint8_t data_bits = (dc_bit != DATA_NO_DC_BIT) ? 9 : 8;
|
||||
uint16_t write_order_mask = panel_io->write_order_mask;
|
||||
uint32_t scl_active_befor_level = panel_io->flags.scl_active_rising_edge ? 0 : 1;
|
||||
uint32_t scl_active_after_level = !scl_active_befor_level;
|
||||
uint32_t scl_half_period_us = panel_io->scl_half_period_us;
|
||||
|
||||
for (uint8_t i = 0; i < data_bits; i++) {
|
||||
// Send DC bit first
|
||||
if (data_bits == 9 && i == 0) {
|
||||
ESP_RETURN_ON_ERROR(set_line_level(panel_io, SDA, dc_bit), TAG, "Set SDA level failed");
|
||||
} else { // Then send data bit
|
||||
// SDA set to data bit
|
||||
ESP_RETURN_ON_ERROR(set_line_level(panel_io, SDA, data_temp & write_order_mask), TAG, "Set SDA level failed");
|
||||
// Get next bit
|
||||
data_temp = (write_order_mask == WRITE_ORDER_LSB_MASK) ? data_temp >> 1 : data_temp << 1;
|
||||
}
|
||||
// Generate SCL active edge
|
||||
ESP_RETURN_ON_ERROR(set_line_level(panel_io, SCL, scl_active_befor_level), TAG, "Set SCL level failed");
|
||||
delay_us(scl_half_period_us);
|
||||
ESP_RETURN_ON_ERROR(set_line_level(panel_io, SCL, scl_active_after_level), TAG, "Set SCL level failed");
|
||||
delay_us(scl_half_period_us);
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write a package of data to LCD panel in big-endian order
|
||||
*
|
||||
* @param[in] panel_io Pointer to panel IO instance
|
||||
* @param[in] is_cmd True for command, false for data
|
||||
* @param[in] data Data to write, with
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - ESP_ERR_INVALID_ARG: Invalid argument
|
||||
* - Others: Fail
|
||||
*/
|
||||
static esp_err_t spi_write_package(esp_lcd_panel_io_3wire_spi_t *panel_io, bool is_cmd, uint32_t data)
|
||||
{
|
||||
uint32_t data_bytes = is_cmd ? panel_io->lcd_cmd_bytes : panel_io->lcd_param_bytes;
|
||||
uint32_t cs_idle_level = panel_io->flags.cs_high_active ? 0 : 1;
|
||||
uint32_t sda_scl_idle_level = panel_io->flags.sda_scl_idle_high ? 1 : 0;
|
||||
uint32_t scl_active_befor_level = panel_io->flags.scl_active_rising_edge ? 0 : 1;
|
||||
uint32_t time_us = panel_io->scl_half_period_us;
|
||||
// Swap command bytes order due to different endianness
|
||||
uint32_t swap_data = SPI_SWAP_DATA_TX(data, data_bytes * 8);
|
||||
int data_dc_bit = is_cmd ? panel_io->cmd_dc_bit : panel_io->param_dc_bit;
|
||||
|
||||
// CS active
|
||||
ESP_RETURN_ON_ERROR(set_line_level(panel_io, CS, !cs_idle_level), TAG, "Set CS level failed");
|
||||
delay_us(time_us);
|
||||
ESP_RETURN_ON_ERROR(set_line_level(panel_io, SCL, scl_active_befor_level), TAG, "Set SCL level failed");
|
||||
// Send data byte by byte
|
||||
for (int i = 0; i < data_bytes; i++) {
|
||||
// Only set DC bit for the first byte
|
||||
if (i == 0) {
|
||||
ESP_RETURN_ON_ERROR(spi_write_byte(panel_io, data_dc_bit, swap_data & 0xff), TAG, "SPI write byte failed");
|
||||
} else {
|
||||
ESP_RETURN_ON_ERROR(spi_write_byte(panel_io, DATA_NO_DC_BIT, swap_data & 0xff), TAG, "SPI write byte failed");
|
||||
}
|
||||
swap_data >>= 8;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(set_line_level(panel_io, SCL, sda_scl_idle_level), TAG, "Set SCL level failed");
|
||||
ESP_RETURN_ON_ERROR(set_line_level(panel_io, SDA, sda_scl_idle_level), TAG, "Set SDA level failed");
|
||||
delay_us(time_us);
|
||||
// CS inactive
|
||||
ESP_RETURN_ON_ERROR(set_line_level(panel_io, CS, cs_idle_level), TAG, "Set CS level failed");
|
||||
delay_us(time_us);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "esp_lcd_types.h"
|
||||
#include "base/esp_io_expander.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Maximum SPI clock speed
|
||||
#define PANEL_IO_3WIRE_SPI_CLK_MAX (500 * 1000UL)
|
||||
|
||||
/**
|
||||
* @brief Panel IO type, use GPIO or IO expander
|
||||
*/
|
||||
typedef enum {
|
||||
IO_TYPE_GPIO = 0,
|
||||
IO_TYPE_EXPANDER,
|
||||
} panel_io_type_t;
|
||||
|
||||
/**
|
||||
* @brief SPI line configuration structure
|
||||
*/
|
||||
typedef struct {
|
||||
panel_io_type_t cs_io_type; /*!< IO type of CS line */
|
||||
union {
|
||||
int cs_gpio_num; /*!< GPIO used for CS line */
|
||||
esp_io_expander_pin_num_t cs_expander_pin; /*!< IO expander pin used for CS line */
|
||||
};
|
||||
panel_io_type_t scl_io_type; /*!< IO type of SCL line */
|
||||
union {
|
||||
int scl_gpio_num; /*!< GPIO used for SCL line */
|
||||
esp_io_expander_pin_num_t scl_expander_pin; /*!< IO expander pin used for SCL line */
|
||||
};
|
||||
panel_io_type_t sda_io_type; /*!< IO type of SDA line */
|
||||
union {
|
||||
int sda_gpio_num; /*!< GPIO used for SDA line */
|
||||
esp_io_expander_pin_num_t sda_expander_pin; /*!< IO expander pin used for SDA line */
|
||||
};
|
||||
esp_io_expander_handle_t io_expander; /*!< IO expander handle, set to NULL if not used */
|
||||
} spi_line_config_t;
|
||||
|
||||
/**
|
||||
* @brief Panel IO configuration structure
|
||||
*/
|
||||
typedef struct {
|
||||
spi_line_config_t line_config; /*!< SPI line configuration */
|
||||
uint32_t expect_clk_speed; /*!< Expected SPI clock speed, in Hz (1 ~ 500000
|
||||
* If this value is 0, it will be set to `PANEL_IO_3WIRE_SPI_CLK_MAX` by defaul
|
||||
* The actual frequency may be very different due to the limitation of the software delay */
|
||||
uint32_t spi_mode: 2; /*!< Traditional SPI mode (0 ~ 3) */
|
||||
uint32_t lcd_cmd_bytes: 3; /*!< Bytes of LCD command (1 ~ 4) */
|
||||
uint32_t lcd_param_bytes: 3; /*!< Bytes of LCD parameter (1 ~ 4) */
|
||||
struct {
|
||||
uint32_t use_dc_bit: 1; /*!< If this flag is enabled, transmit DC bit at the beginning of every command and data */
|
||||
uint32_t dc_zero_on_data: 1; /*!< If this flag is enabled, DC bit = 0 means transfer data, DC bit = 1 means transfer command */
|
||||
uint32_t lsb_first: 1; /*!< If this flag is enabled, transmit LSB bit first */
|
||||
uint32_t cs_high_active: 1; /*!< If this flag is enabled, CS line is high active */
|
||||
uint32_t del_keep_cs_inactive: 1; /*!< If this flag is enabled, keep CS line inactive even if panel_io is deleted */
|
||||
} flags;
|
||||
} esp_lcd_panel_io_3wire_spi_config_t;
|
||||
|
||||
/**
|
||||
* @brief Create a new panel IO instance for 3-wire SPI interface (simulate by software)
|
||||
*
|
||||
* @note This function uses GPIO or IO expander to simulate SPI interface by software and just supports to write data.
|
||||
* It is only suitable for some applications with low speed SPI interface. (Such as initializing RGB panel)
|
||||
*
|
||||
* @param[in] io_config Panel IO configuration
|
||||
* @param[out] ret_io Pointer to return the created panel IO instance
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - ESP_ERR_INVALID_ARG: Invalid argument
|
||||
* - ESP_ERR_NO_MEM: Failed to allocate memory for panel IO instance
|
||||
* - Others: Fail
|
||||
*/
|
||||
esp_err_t esp_lcd_new_panel_io_3wire_spi(const esp_lcd_panel_io_3wire_spi_config_t *io_config, esp_lcd_panel_io_handle_t *ret_io);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
+180
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "ESP_PanelHost.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
static const char *TAG = "ESP_PanelHost";
|
||||
|
||||
ESP_PanelHost::ESP_PanelHost()
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelHost::~ESP_PanelHost()
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
ESP_LOGD(TAG, "Destroyed");
|
||||
}
|
||||
|
||||
bool ESP_PanelHost::addHostI2C(const i2c_config_t &host_config, i2c_port_t host_id)
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
auto ret = _i2c_host_config_map.find(host_id);
|
||||
if (ret == _i2c_host_config_map.end()) {
|
||||
_i2c_host_config_map.insert(pair<i2c_port_t, i2c_config_t>(host_id, host_config));
|
||||
ESP_LOGD(TAG, "Add host I2C[%d]", (int)host_id);
|
||||
|
||||
return true;
|
||||
}
|
||||
ESP_LOGD(TAG, "Host I2C[%d] is already exist", (int)host_id);
|
||||
ESP_PANEL_CHECK_FALSE_RET(!memcmp(&ret->second, &host_config, sizeof(i2c_config_t)), false,
|
||||
"Attempt to add with a different configuartion");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_PanelHost::addHostI2C(int scl_io, int sda_io, i2c_port_t host_id)
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
i2c_config_t host_config = ESP_PANEL_HOST_I2C_CONFIG_DEFAULT(scl_io, sda_io);
|
||||
|
||||
auto ret = _i2c_host_config_map.find(host_id);
|
||||
if (ret == _i2c_host_config_map.end()) {
|
||||
_i2c_host_config_map.insert(pair<i2c_port_t, i2c_config_t>(host_id, host_config));
|
||||
ESP_LOGD(TAG, "Add host I2C[%d]", (int)host_id);
|
||||
|
||||
return true;
|
||||
}
|
||||
ESP_LOGD(TAG, "Host I2C[%d] is already exist", (int)host_id);
|
||||
ESP_PANEL_CHECK_FALSE_RET(!memcmp(&ret->second, &host_config, sizeof(i2c_config_t)), false,
|
||||
"Attempt to add with a different configuartion");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_PanelHost::addHostSPI(const spi_bus_config_t &host_config, spi_host_device_t host_id)
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
auto ret = _spi_host_config_map.find(host_id);
|
||||
if (ret == _spi_host_config_map.end()) {
|
||||
_spi_host_config_map.insert(pair<spi_host_device_t, spi_bus_config_t>(host_id, host_config));
|
||||
ESP_LOGD(TAG, "Add host SPI[%d]", (int)host_id);
|
||||
|
||||
return true;
|
||||
}
|
||||
ESP_LOGD(TAG, "Host SPI[%d] is already exist", (int)host_id);
|
||||
|
||||
ESP_PANEL_CHECK_FALSE_RET(compare_spi_host_config(ret->second, host_config), false,
|
||||
"Attempt to add with a different configuartion");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_PanelHost::addHostSPI(int sck_io, int sda_io, int sdo_io, spi_host_device_t host_id)
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
spi_bus_config_t host_config = ESP_PANEL_HOST_SPI_CONFIG_DEFAULT(sck_io, sda_io, sdo_io);
|
||||
|
||||
auto ret = _spi_host_config_map.find(host_id);
|
||||
if (ret == _spi_host_config_map.end()) {
|
||||
_spi_host_config_map.insert(pair<spi_host_device_t, spi_bus_config_t>(host_id, host_config));
|
||||
ESP_LOGD(TAG, "Add host SPI[%d]", (int)host_id);
|
||||
|
||||
return true;
|
||||
}
|
||||
ESP_LOGD(TAG, "Host SPI[%d] is already exist", (int)host_id);
|
||||
|
||||
ESP_PANEL_CHECK_FALSE_RET(compare_spi_host_config(ret->second, host_config), false,
|
||||
"Attempt to add with a different configuartion");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_PanelHost::addHostQSPI(const spi_bus_config_t &host_config, spi_host_device_t host_id)
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
auto ret = _spi_host_config_map.find(host_id);
|
||||
if (ret == _spi_host_config_map.end()) {
|
||||
_spi_host_config_map.insert(pair<spi_host_device_t, spi_bus_config_t>(host_id, host_config));
|
||||
ESP_LOGD(TAG, "Add host SPI[%d]", (int)host_id);
|
||||
|
||||
return true;
|
||||
}
|
||||
ESP_LOGD(TAG, "Host SPI[%d] is already exist", (int)host_id);
|
||||
ESP_PANEL_CHECK_FALSE_RET(!memcmp(&ret->second, &host_config, sizeof(spi_bus_config_t)), false,
|
||||
"Attempt to add with a different configuartion");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_PanelHost::addHostQSPI(int sck_io, int d0_io, int d1_io, int d2_io, int d3_io, spi_host_device_t host_id)
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
spi_bus_config_t host_config = ESP_PANEL_HOST_QSPI_CONFIG_DEFAULT(sck_io, d0_io, d1_io, d2_io, d3_io);
|
||||
|
||||
auto ret = _spi_host_config_map.find(host_id);
|
||||
if (ret == _spi_host_config_map.end()) {
|
||||
_spi_host_config_map.insert(pair<spi_host_device_t, spi_bus_config_t>(host_id, host_config));
|
||||
ESP_LOGD(TAG, "Add host SPI[%d]", (int)host_id);
|
||||
|
||||
return true;
|
||||
}
|
||||
ESP_LOGD(TAG, "Host SPI[%d] is already exist", (int)host_id);
|
||||
ESP_PANEL_CHECK_FALSE_RET(!memcmp(&ret->second, &host_config, sizeof(spi_bus_config_t)), false,
|
||||
"Attempt to add with a different configuartion");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_PanelHost::begin(void)
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
// Initialize all I2C hosts
|
||||
if (_i2c_host_config_map.size() > 0) {
|
||||
for (auto &it : _i2c_host_config_map) {
|
||||
ESP_PANEL_CHECK_ERR_RET(i2c_param_config(it.first, &it.second), false, "I2C[%d] config param failed", it.first);
|
||||
ESP_PANEL_CHECK_ERR_RET(i2c_driver_install(it.first, it.second.mode, 0, 0, 0), false, "I2C[%d] install driver failed",
|
||||
it.first);
|
||||
ESP_LOGD(TAG, "Initialize host I2C[%d]", (int)it.first);
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize all SPI hosts
|
||||
if (_spi_host_config_map.size() > 0) {
|
||||
for (auto &it : _spi_host_config_map) {
|
||||
ESP_PANEL_CHECK_ERR_RET(spi_bus_initialize(it.first, &it.second, SPI_DMA_CH_AUTO), false, "SPI[%d] initialize failed",
|
||||
it.first);
|
||||
ESP_LOGD(TAG, "Initialize host SPI[%d]", (int)it.first);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_PanelHost::compare_spi_host_config(spi_bus_config_t &old_config, const spi_bus_config_t &new_config)
|
||||
{
|
||||
spi_bus_config_t temp_config = { };
|
||||
memcpy(&temp_config, &new_config, sizeof(spi_bus_config_t));
|
||||
|
||||
if (temp_config.miso_io_num == -1) {
|
||||
temp_config.miso_io_num = old_config.miso_io_num;
|
||||
} else if (old_config.miso_io_num == -1) {
|
||||
old_config.miso_io_num = temp_config.miso_io_num;
|
||||
}
|
||||
|
||||
return !memcmp(&old_config, &temp_config, sizeof(spi_bus_config_t));
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include "driver/i2c.h"
|
||||
#include "driver/spi_master.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
/**
|
||||
* I2C Host Default Configuration
|
||||
*
|
||||
*/
|
||||
#define ESP_PANEL_HOST_I2C_ID_DEFAULT (I2C_NUM_0)
|
||||
#define ESP_PANEL_HOST_I2C_CONFIG_DEFAULT(scl_io, sda_io) \
|
||||
{ \
|
||||
.mode = I2C_MODE_MASTER, \
|
||||
.sda_io_num = sda_io, \
|
||||
.scl_io_num = scl_io, \
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE, \
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE, \
|
||||
.master = { \
|
||||
.clk_speed = 400000, \
|
||||
}, \
|
||||
.clk_flags = I2C_SCLK_SRC_FLAG_FOR_NOMAL, \
|
||||
}
|
||||
|
||||
/**
|
||||
* SPI & QSPI Host Default Configuration
|
||||
*
|
||||
*/
|
||||
#define ESP_PANEL_HOST_SPI_ID_DEFAULT (SPI2_HOST)
|
||||
/* Refer to `hal/spi_ll.h` in SDK (ESP-IDF) */
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
#define ESP_PANEL_HOST_SPI_MAX_TRANSFER_SIZE ((1 << 24) >> 3)
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#define ESP_PANEL_HOST_SPI_MAX_TRANSFER_SIZE ((1 << 23) >> 3)
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
|
||||
#define ESP_PANEL_HOST_SPI_MAX_TRANSFER_SIZE ((1 << 18) >> 3)
|
||||
#endif
|
||||
#define ESP_PANEL_HOST_SPI_CONFIG_DEFAULT(sck_io, sda_io, sdo_io) \
|
||||
{ \
|
||||
.mosi_io_num = sda_io, \
|
||||
.miso_io_num = sdo_io, \
|
||||
.sclk_io_num = sck_io, \
|
||||
.quadwp_io_num = -1, \
|
||||
.quadhd_io_num = -1, \
|
||||
.data4_io_num = -1, \
|
||||
.data5_io_num = -1, \
|
||||
.data6_io_num = -1, \
|
||||
.data7_io_num = -1, \
|
||||
.max_transfer_sz = ESP_PANEL_HOST_SPI_MAX_TRANSFER_SIZE, \
|
||||
.flags = SPICOMMON_BUSFLAG_MASTER, \
|
||||
.intr_flags = 0, \
|
||||
}
|
||||
#define ESP_PANEL_HOST_QSPI_CONFIG_DEFAULT(sck_io, d0_io, d1_io, d2_io, d3_io) \
|
||||
{ \
|
||||
.data0_io_num = d0_io, \
|
||||
.data1_io_num = d1_io, \
|
||||
.sclk_io_num = sck_io, \
|
||||
.data2_io_num = d2_io, \
|
||||
.data3_io_num = d3_io, \
|
||||
.data4_io_num = -1, \
|
||||
.data5_io_num = -1, \
|
||||
.data6_io_num = -1, \
|
||||
.data7_io_num = -1, \
|
||||
.max_transfer_sz = ESP_PANEL_HOST_SPI_MAX_TRANSFER_SIZE, \
|
||||
.flags = SPICOMMON_BUSFLAG_MASTER, \
|
||||
.intr_flags = 0, \
|
||||
}
|
||||
|
||||
class ESP_PanelHost {
|
||||
public:
|
||||
ESP_PanelHost();
|
||||
~ESP_PanelHost();
|
||||
|
||||
bool addHostI2C(const i2c_config_t &host_config, i2c_port_t host_id);
|
||||
bool addHostI2C(int scl_io, int sda_io, i2c_port_t host_id);
|
||||
|
||||
bool addHostSPI(const spi_bus_config_t &host_config, spi_host_device_t host_id);
|
||||
bool addHostSPI(int sck_io, int sda_io, int sdo_io, spi_host_device_t host_id);
|
||||
|
||||
bool addHostQSPI(const spi_bus_config_t &host_config, spi_host_device_t host_id);
|
||||
bool addHostQSPI(int sck_io, int d0_io, int d1_io, int d2_io, int d3_io, spi_host_device_t host_id);
|
||||
|
||||
bool begin(void);
|
||||
|
||||
private:
|
||||
bool compare_spi_host_config(spi_bus_config_t &old_config, const spi_bus_config_t &new_config);
|
||||
|
||||
std::map<i2c_port_t, i2c_config_t> _i2c_host_config_map;
|
||||
std::map<spi_host_device_t, spi_bus_config_t> _spi_host_config_map;
|
||||
};
|
||||
@@ -0,0 +1,467 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "cstring"
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_lcd_panel_ops.h"
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "esp_lcd_panel_rgb.h"
|
||||
#include "esp_memory_utils.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "driver/spi_master.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "bus/RGB.h"
|
||||
#include "bus/ESP_PanelBus.h"
|
||||
#include "ESP_PanelLcd.h"
|
||||
|
||||
#define VENDOR_CONFIG_DEFAULT() \
|
||||
{ \
|
||||
.init_cmds = NULL, \
|
||||
.init_cmds_size = 0, \
|
||||
.flags = { \
|
||||
.mirror_by_cmd = 1, \
|
||||
.auto_del_panel_io = 0, \
|
||||
.use_qspi_interface = 0, \
|
||||
} \
|
||||
}
|
||||
#define CALLBACK_DATA_DEFAULT() \
|
||||
{ \
|
||||
.lcd_ptr = this, \
|
||||
.user_data = NULL, \
|
||||
}
|
||||
|
||||
static const char *TAG = "ESP_PanelLcd";
|
||||
|
||||
ESP_PanelLcd::ESP_PanelLcd(ESP_PanelBus *bus, uint8_t color_bits, int rst_io):
|
||||
x_coord_align(0),
|
||||
y_coord_align(0),
|
||||
bus(bus),
|
||||
panel_config(ESP_PANEL_LCD_DEVICE_CONFIG_DEFAULT(rst_io, color_bits, &vendor_config)),
|
||||
vendor_config(VENDOR_CONFIG_DEFAULT()),
|
||||
handle(NULL),
|
||||
_swap_xy(false),
|
||||
_mirror_x(false),
|
||||
_mirror_y(false),
|
||||
_gap_x(0),
|
||||
_gap_y(0),
|
||||
onRefreshFinishCallback(NULL),
|
||||
_refresh_finish_sem(NULL),
|
||||
callback_data(CALLBACK_DATA_DEFAULT())
|
||||
{
|
||||
switch (bus->getType()) {
|
||||
case ESP_PANEL_BUS_TYPE_QSPI:
|
||||
vendor_config.flags.use_qspi_interface = 1;
|
||||
break;
|
||||
#if SOC_LCD_RGB_SUPPORTED
|
||||
/* Retrieve RGB configuration from the bus and register it into the vendor configuration */
|
||||
case ESP_PANEL_BUS_TYPE_RGB:
|
||||
vendor_config.rgb_config = static_cast<ESP_PanelBus_RGB *>(bus)->getRgbConfig();
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ESP_PanelLcd::ESP_PanelLcd(ESP_PanelBus *bus, const esp_lcd_panel_dev_config_t &panel_config):
|
||||
x_coord_align(0),
|
||||
y_coord_align(0),
|
||||
bus(bus),
|
||||
panel_config(panel_config),
|
||||
vendor_config(VENDOR_CONFIG_DEFAULT()),
|
||||
handle(NULL),
|
||||
_swap_xy(false),
|
||||
_mirror_x(false),
|
||||
_mirror_y(false),
|
||||
_gap_x(0),
|
||||
_gap_y(0),
|
||||
onRefreshFinishCallback(NULL),
|
||||
_refresh_finish_sem(NULL),
|
||||
callback_data(CALLBACK_DATA_DEFAULT())
|
||||
{
|
||||
/* Save vendor configuration to local and register the local one into panel configuration */
|
||||
if (panel_config.vendor_config != NULL) {
|
||||
vendor_config = *(esp_lcd_panel_vendor_config_t *)panel_config.vendor_config;
|
||||
}
|
||||
this->panel_config.vendor_config = &vendor_config;
|
||||
|
||||
#if SOC_LCD_RGB_SUPPORTED
|
||||
/* Retrieve RGB configuration from the bus and register it into the vendor configuration */
|
||||
if (bus->getType() == ESP_PANEL_BUS_TYPE_RGB) {
|
||||
const esp_lcd_rgb_panel_config_t *rgb_config = static_cast<ESP_PanelBus_RGB *>(bus)->getRgbConfig();
|
||||
vendor_config.rgb_config = rgb_config;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ESP_PanelLcd::configVendorCommands(const esp_lcd_panel_vendor_init_cmd_t init_cmd[], uint32_t init_cmd_size)
|
||||
{
|
||||
ESP_PANEL_CHECK_FALSE_RET((init_cmd == NULL) || (init_cmd_size > 0), false, "Size of init commands is invalid");
|
||||
|
||||
vendor_config.init_cmds = init_cmd;
|
||||
vendor_config.init_cmds_size = init_cmd_size;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ESP_PanelLcd::configColorRgbOrder(bool BGR_order)
|
||||
{
|
||||
if (BGR_order) {
|
||||
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR;
|
||||
} else {
|
||||
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB;
|
||||
}
|
||||
}
|
||||
|
||||
void ESP_PanelLcd::configMirrorByCommand(bool en)
|
||||
{
|
||||
vendor_config.flags.mirror_by_cmd = en;
|
||||
}
|
||||
|
||||
void ESP_PanelLcd::configAutoReleaseBus(bool en)
|
||||
{
|
||||
vendor_config.flags.auto_del_panel_io = en;
|
||||
}
|
||||
|
||||
bool ESP_PanelLcd::begin(void)
|
||||
{
|
||||
ESP_PANEL_CHECK_NULL_RET(handle, false, "Invalid handle");
|
||||
ESP_PANEL_CHECK_NULL_RET(bus, false, "Invalid bus");
|
||||
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
ESP_LOGD(TAG, "Begin start");
|
||||
|
||||
/* Initialize LCD panel */
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_panel_init(handle), false, "Init panel failed");
|
||||
|
||||
/* For non-RGB interface, create Semaphore for using API `drawBitmapWaitUntilFinish()` */
|
||||
if (bus->getType() != ESP_PANEL_BUS_TYPE_RGB) {
|
||||
_refresh_finish_sem = xSemaphoreCreateBinary();
|
||||
ESP_PANEL_CHECK_NULL_RET(_refresh_finish_sem, false, "Create semaphore failed");
|
||||
}
|
||||
|
||||
/* Register transimit done callback for non-RGB interface and RGB interface */
|
||||
if (bus->getType() != ESP_PANEL_BUS_TYPE_RGB) {
|
||||
esp_lcd_panel_io_callbacks_t io_cb = {
|
||||
.on_color_trans_done = (esp_lcd_panel_io_color_trans_done_cb_t)onRefreshFinish,
|
||||
};
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_panel_io_register_event_callbacks(bus->getHandle(), &io_cb, &callback_data), false,
|
||||
"Register IO callback failed");
|
||||
}
|
||||
#if SOC_LCD_RGB_SUPPORTED
|
||||
else {
|
||||
const esp_lcd_rgb_panel_config_t *rgb_config = static_cast<ESP_PanelBus_RGB *>(bus)->getRgbConfig();
|
||||
esp_lcd_rgb_panel_event_callbacks_t rgb_event_cb = { NULL };
|
||||
if (rgb_config->bounce_buffer_size_px == 0) {
|
||||
// When bounce buffer is disabled, use `on_vsync` callback to notify draw bitmap finish
|
||||
rgb_event_cb.on_vsync = (esp_lcd_rgb_panel_vsync_cb_t)onRefreshFinish;
|
||||
} else {
|
||||
// When bounce buffer is enabled, use `on_bounce_frame_finish` callback to notify draw bitmap finish
|
||||
rgb_event_cb.on_bounce_frame_finish = (esp_lcd_rgb_panel_bounce_buf_finish_cb_t)onRefreshFinish;
|
||||
}
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_rgb_panel_register_event_callbacks(handle, &rgb_event_cb, &callback_data),
|
||||
false, "Register RGB callback failed");
|
||||
}
|
||||
#endif
|
||||
|
||||
ESP_LOGD(TAG, "Begin end");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_PanelLcd::reset(void)
|
||||
{
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_panel_reset(handle), false, "Reset panel failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_PanelLcd::del(void)
|
||||
{
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_panel_del(handle), false, "Delete panel failed");
|
||||
|
||||
ESP_LOGD(TAG, "LCD panel @%p deleted", handle);
|
||||
handle = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_PanelLcd::drawBitmap(uint16_t x_start, uint16_t y_start, uint16_t width, uint16_t height, const uint8_t *color_data)
|
||||
{
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_panel_draw_bitmap(handle, x_start, y_start, x_start + width, y_start + height, color_data),
|
||||
false, "Draw bitmap failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_PanelLcd::drawBitmapWaitUntilFinish(uint16_t x_start, uint16_t y_start, uint16_t width, uint16_t height,
|
||||
const uint8_t *color_data, int timeout_ms)
|
||||
{
|
||||
ESP_PANEL_CHECK_NULL_RET(bus, false, "Invalid bus");
|
||||
|
||||
/* For RGB LCD, since `drawBitmap()` uses `memcpy()` instead of DMA operation, doesn't need to wait */
|
||||
if (bus->getType() == ESP_PANEL_BUS_TYPE_RGB) {
|
||||
ESP_PANEL_CHECK_FALSE_RET(drawBitmap(x_start, y_start, width, height, color_data), false, "Draw bitmap failed");
|
||||
return true;
|
||||
}
|
||||
|
||||
/* For other LCDs, since `drawBitmap()` use DMA operation, need to use semaphore to wait */
|
||||
ESP_PANEL_CHECK_NULL_RET(_refresh_finish_sem, false, "Semaphore is not created");
|
||||
|
||||
ESP_PANEL_CHECK_FALSE_RET(drawBitmap(x_start, y_start, width, height, color_data), false, "Draw bitmap failed");
|
||||
|
||||
/* Wait for the semaphore to be given by the callback function */
|
||||
BaseType_t timeout_tick = (timeout_ms < 0) ? portMAX_DELAY : pdMS_TO_TICKS(timeout_ms);
|
||||
if (xSemaphoreTake(_refresh_finish_sem, timeout_tick) != pdTRUE) {
|
||||
ESP_LOGD(TAG, "Draw bitmap wait for finish timeout");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_PanelLcd::mirrorX(bool en)
|
||||
{
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_panel_mirror(handle, en, _mirror_y), false, "Mirror X failed");
|
||||
_mirror_x = en;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_PanelLcd::mirrorY(bool en)
|
||||
{
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_panel_mirror(handle, _mirror_x, en), false, "Mirror X failed");
|
||||
_mirror_y = en;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_PanelLcd::swapXY(bool en)
|
||||
{
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_panel_swap_xy(handle, en), false, "Swap XY failed");
|
||||
_swap_xy = en;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_PanelLcd::setGapX(uint16_t gap)
|
||||
{
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_panel_set_gap(handle, gap, _gap_y), false, "Set X gap failed");
|
||||
_gap_x = gap;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_PanelLcd::setGapY(uint16_t gap)
|
||||
{
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_panel_set_gap(handle, _gap_x, gap), false, "Set Y gap failed");
|
||||
_gap_y = gap;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_PanelLcd::invertColor(bool en)
|
||||
{
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_panel_invert_color(handle, en), false, "Invert color failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_PanelLcd::displayOn(void)
|
||||
{
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_panel_disp_off(handle, false), false, "Display on failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_PanelLcd::displayOff(void)
|
||||
{
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_panel_disp_off(handle, true), false, "Display off failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_PanelLcd::attachRefreshFinishCallback(std::function<bool (void *)> callback, void *user_data)
|
||||
{
|
||||
// For RGB LCD, if the "XIP on PSRAM" function is not enabled, the callback function and user data should be
|
||||
// placed in SRAM
|
||||
#if SOC_LCD_RGB_SUPPORTED && CONFIG_LCD_RGB_ISR_IRAM_SAFE && \
|
||||
!(CONFIG_SPIRAM_RODATA && CONFIG_SPIRAM_FETCH_INSTRUCTIONS)
|
||||
if (bus->getType() == ESP_PANEL_BUS_TYPE_RGB) {
|
||||
ESP_PANEL_CHECK_FALSE_RET((esp_ptr_in_iram(callback), false, "Callback function should be placed in IRAM, add
|
||||
`IRAM_ATTR` before the function"));
|
||||
ESP_PANEL_CHECK_FALSE_RET((esp_ptr_internal(user_data), false, "User data should be placed in SRAM"));
|
||||
}
|
||||
#endif
|
||||
|
||||
// *INDENT-OFF*
|
||||
callback_data.user_data = user_data;
|
||||
onRefreshFinishCallback = callback;
|
||||
// *INDENT-OFF*
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_PanelLcd::colorBarTest(uint16_t width, uint16_t height)
|
||||
{
|
||||
ESP_PANEL_CHECK_NULL_RET(bus, false, "Invalid bus");
|
||||
|
||||
int bits_per_piexl = getColorBits();
|
||||
ESP_PANEL_CHECK_FALSE_RET(bits_per_piexl > 0, false, "Invalid color bits");
|
||||
|
||||
int bytes_per_piexl = bits_per_piexl / 8;
|
||||
int line_per_bar = height / bits_per_piexl;
|
||||
int line_count = 0;
|
||||
uint8_t *single_bar_buf = NULL;
|
||||
int res_line_count = 0;
|
||||
|
||||
/* Malloc memory for a single color bar */
|
||||
try {
|
||||
single_bar_buf = new uint8_t[line_per_bar * width * bytes_per_piexl];
|
||||
} catch (std::bad_alloc &e) {
|
||||
ESP_PANEL_CHECK_FALSE_RET(false, false, "Malloc color buffer failed");
|
||||
}
|
||||
|
||||
bool ret = true;
|
||||
|
||||
/* Draw color bar from top left to bottom right, the order is B - G - R */
|
||||
for (int j = 0; j < bits_per_piexl; j++) {
|
||||
for (int i = 0; i < line_per_bar * width; i++) {
|
||||
for (int k = 0; k < bytes_per_piexl; k++) {
|
||||
if ((bus->getType() == ESP_PANEL_BUS_TYPE_SPI) || (bus->getType() == ESP_PANEL_BUS_TYPE_QSPI)) {
|
||||
// For SPI interface, the data bytes should be swapped since the data is sent by LSB first
|
||||
single_bar_buf[i * bytes_per_piexl + k] = SPI_SWAP_DATA_TX(BIT(j), bits_per_piexl) >> (k * 8);
|
||||
} else {
|
||||
single_bar_buf[i * bytes_per_piexl + k] = BIT(j) >> (k * 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
line_count += line_per_bar;
|
||||
ret = drawBitmapWaitUntilFinish(0, j * line_per_bar, width, line_per_bar, single_bar_buf);
|
||||
if (ret != true) {
|
||||
ESP_LOGE(TAG, "Draw bitmap failed");
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill the rest of the screen with white color */
|
||||
res_line_count = height - line_count;
|
||||
if (res_line_count > 0) {
|
||||
ESP_LOGD(TAG, "Fill the rest lines (%d) with white color", res_line_count);
|
||||
|
||||
memset(single_bar_buf, 0xff, res_line_count * width * bytes_per_piexl);
|
||||
ret = drawBitmapWaitUntilFinish(0, line_count, width, res_line_count, single_bar_buf);
|
||||
if (ret != true) {
|
||||
ESP_LOGE(TAG, "Draw bitmap failed");
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
delete[] single_bar_buf;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ESP_PanelLcd::getColorBits(void)
|
||||
{
|
||||
#if SOC_LCD_RGB_SUPPORTED
|
||||
ESP_PANEL_CHECK_NULL_RET(bus, -1, "Invalid bus");
|
||||
if (bus->getType() == ESP_PANEL_BUS_TYPE_RGB) {
|
||||
const esp_lcd_rgb_panel_config_t *rgb_config = static_cast<ESP_PanelBus_RGB *>(bus)->getRgbConfig();
|
||||
ESP_PANEL_CHECK_NULL_RET(rgb_config, -1, "Invalid RGB config");
|
||||
|
||||
return rgb_config->bits_per_pixel;
|
||||
}
|
||||
#endif
|
||||
|
||||
return panel_config.bits_per_pixel;
|
||||
}
|
||||
|
||||
bool ESP_PanelLcd::getSwapXYFlag(void)
|
||||
{
|
||||
return _swap_xy;
|
||||
}
|
||||
|
||||
bool ESP_PanelLcd::getMirrorXFlag(void)
|
||||
{
|
||||
return _mirror_x;
|
||||
}
|
||||
|
||||
bool ESP_PanelLcd::getMirrorYFlag(void)
|
||||
{
|
||||
return _mirror_y;
|
||||
}
|
||||
|
||||
#if SOC_LCD_RGB_SUPPORTED
|
||||
void *ESP_PanelLcd::getRgbBufferByIndex(uint8_t index)
|
||||
{
|
||||
ESP_PANEL_CHECK_NULL_RET(handle, NULL, "Invalid handle");
|
||||
|
||||
void *buffer[3] = { NULL };
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_rgb_panel_get_frame_buffer(handle, index + 1, &buffer[0], &buffer[1], &buffer[2]),
|
||||
NULL, "Get RGB buffer failed");
|
||||
|
||||
return buffer[index];
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t ESP_PanelLcd::getXCoordAlign(void)
|
||||
{
|
||||
return x_coord_align;
|
||||
}
|
||||
|
||||
uint8_t ESP_PanelLcd::getYCoordAlign(void)
|
||||
{
|
||||
return y_coord_align;
|
||||
}
|
||||
|
||||
esp_lcd_panel_handle_t ESP_PanelLcd::getHandle(void)
|
||||
{
|
||||
if (handle == NULL) {
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
ESP_LOGD(TAG, "Get invalid handle");
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
ESP_PanelBus *ESP_PanelLcd::getBus(void)
|
||||
{
|
||||
if (bus == NULL) {
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
ESP_LOGD(TAG, "Get invalid bus");
|
||||
}
|
||||
|
||||
return bus;
|
||||
}
|
||||
|
||||
IRAM_ATTR bool ESP_PanelLcd::onRefreshFinish(void *panel_io, void *edata, void *user_ctx)
|
||||
{
|
||||
ESP_PanelLcdCallbackData_t *callback_data = (ESP_PanelLcdCallbackData_t *)user_ctx;
|
||||
if (callback_data == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ESP_PanelLcd *lcd_ptr = (ESP_PanelLcd *)callback_data->lcd_ptr;
|
||||
if (lcd_ptr == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BaseType_t need_yield = pdFALSE;
|
||||
if (lcd_ptr->onRefreshFinishCallback != NULL) {
|
||||
need_yield = lcd_ptr->onRefreshFinishCallback(callback_data->user_data) ? pdTRUE : need_yield;
|
||||
}
|
||||
if (lcd_ptr->_refresh_finish_sem != NULL) {
|
||||
xSemaphoreGiveFromISR(lcd_ptr->_refresh_finish_sem, &need_yield);
|
||||
}
|
||||
|
||||
return (need_yield == pdTRUE);
|
||||
}
|
||||
@@ -0,0 +1,417 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include "esp_lcd_panel_ops.h"
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
#include "esp_lcd_panel_rgb.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "base/esp_lcd_custom_types.h"
|
||||
#include "bus/ESP_PanelBus.h"
|
||||
|
||||
/**
|
||||
* @brief LCD device default configuration macro
|
||||
*
|
||||
*/
|
||||
#define ESP_PANEL_LCD_DEVICE_CONFIG_DEFAULT(rst_io, color_bits, vendor_cfg) \
|
||||
{ \
|
||||
.reset_gpio_num = rst_io, \
|
||||
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, \
|
||||
.data_endian = LCD_RGB_DATA_ENDIAN_BIG, \
|
||||
.bits_per_pixel = color_bits, \
|
||||
.flags = { \
|
||||
.reset_active_high = 0, \
|
||||
}, \
|
||||
.vendor_config = vendor_cfg, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The LCD device class
|
||||
*
|
||||
* @note This class is a base class for all LCDs. Due to it is a virtual class, users cannot use it directly
|
||||
*/
|
||||
class ESP_PanelLcd {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new LCD device in a simple way, the `init()` function should be called after this function
|
||||
*
|
||||
* @note This function uses some default values to config the LCD device, please use `config*()` functions to
|
||||
* change them
|
||||
* @note Vendor specific initialization can be different between manufacturers, should consult the LCD supplier
|
||||
* for initialization sequence code, and use `configVendorCommands()` to configure
|
||||
*
|
||||
* @param bus Pointer of panel bus
|
||||
* @param color_bits Bits per pixel
|
||||
* @param rst_io Reset pin
|
||||
*/
|
||||
ESP_PanelLcd(ESP_PanelBus *bus, uint8_t color_bits, int rst_io);
|
||||
|
||||
/**
|
||||
* @brief Construct a new LCD device in a complex way, the `init()` function should be called after this function
|
||||
*
|
||||
* @param bus Pointer of panel bus
|
||||
* @param panel_config LCD device configuration
|
||||
*/
|
||||
ESP_PanelLcd(ESP_PanelBus *bus, const esp_lcd_panel_dev_config_t &panel_config);
|
||||
|
||||
/**
|
||||
* @brief Destroy the LCD device
|
||||
*
|
||||
*/
|
||||
virtual ~ESP_PanelLcd() = default;
|
||||
|
||||
/**
|
||||
* @brief Configure the vendor initialization commands. This function should be called before `init()`
|
||||
*
|
||||
* @note Vendor specific initialization can be different between manufacturers, should consult the LCD supplier
|
||||
* for initialization sequence code.
|
||||
* @note There are two formats for the sequence code:
|
||||
* 1. Raw data: {command, (uint8_t []){ data0, data1, ... }, data_size, delay_ms}
|
||||
* 2. Formater: ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(delay_ms, command, { data0, data1, ... }) and
|
||||
* ESP_PANEL_LCD_CMD_WITH_NONE_PARAM(delay_ms, command)
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool configVendorCommands(const esp_lcd_panel_vendor_init_cmd_t init_cmd[], uint32_t init_cmd_size);
|
||||
|
||||
/**
|
||||
* @brief Configure the color order of LCD to BGR, default is RGB. This function should be called before `init()`
|
||||
*
|
||||
* @param bgr_order true: BGR order, false: RGB order
|
||||
*
|
||||
*/
|
||||
void configColorRgbOrder(bool BGR_order);
|
||||
|
||||
/**
|
||||
* @brief Configure driver to mirror by command, default is false (by software). This function should be called before
|
||||
* `init()`
|
||||
*
|
||||
* @note This function is only useful for some LCDs without GRAM, like RGB LCD.
|
||||
* @note After using this function, the `mirror()` function will be implemented by LCD command. Otherwise, the
|
||||
* `mirror()`function will be implemented by software
|
||||
* @note This function is conflict with `configAutoReleaseBus()`, please don't use them at the same time
|
||||
*
|
||||
* @param en ture: enable, false: disable
|
||||
*
|
||||
*/
|
||||
void configMirrorByCommand(bool en);
|
||||
|
||||
/**
|
||||
* @brief Configure driver to release bus automatically, default is false. This function should be called before
|
||||
* `init()`
|
||||
*
|
||||
* @note This function is only useful for some LCDs without GRAM, like RGB LCD.
|
||||
* @note If the "3-wire SPI" interface are sharing pins of the "RGB" interface to save GPIOs, please call
|
||||
* this function to release the bus object and pins (except CS signal). And then, the "3-wire SPI" interface
|
||||
* cannot be used to transmit commands any more.
|
||||
* @note This function is conflict with `configMirrorByCommand()`, please don't use them at the same time
|
||||
*
|
||||
* @param en ture: enable, false: disable
|
||||
*
|
||||
*/
|
||||
void configAutoReleaseBus(bool en);
|
||||
|
||||
/**
|
||||
* @brief Initialize the LCD device, the `begin()` function should be called after this function
|
||||
*
|
||||
* @note This function typically calls `esp_lcd_new_panel_*()` to create the LCD panel handle
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
virtual bool init(void) = 0;
|
||||
|
||||
/**
|
||||
* @brief Startup the LCD device
|
||||
*
|
||||
* @note This function should be called after `init()`
|
||||
* @note This function typically calls `esp_lcd_panel_init()` to initialize the LCD device
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool begin(void);
|
||||
|
||||
/**
|
||||
* @brief Reset the LCD. If the `rst_io` is not set, this function will do reset by software instead of hardware
|
||||
*
|
||||
* @note This function should be called after `init()`
|
||||
* @note This function typically calls `esp_lcd_panel_reset()` to reset the LCD device
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool reset(void);
|
||||
|
||||
/**
|
||||
* @brief Delete the LCD device, release the resources
|
||||
*
|
||||
* @note This function should be called after `init()`
|
||||
* @note This function typically calls `esp_lcd_panel_del()` to delete the LCD device
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool del(void);
|
||||
|
||||
/**
|
||||
* @brief Draw the bitmap to the LCD without waiting for the drawing to finish
|
||||
*
|
||||
* @note This function should be called after `begin()`
|
||||
* @note This function typically calls `esp_lcd_panel_draw_bitmap()` to draw the bitmap
|
||||
* @note This function is non-blocking, the drawing will be finished in the background. So the bitmap data should
|
||||
* not be modified until the drawing is finished
|
||||
* @note For RGB interface, this function is same as `drawBitmapWaitUntilFinish()`
|
||||
*
|
||||
* @param x_start X coordinate of the start point, the range is [0, lcd_width - 1]
|
||||
* @param y_start Y coordinate of the start point, the range is [0, lcd_height - 1]
|
||||
* @param width Width of the bitmap, the range is [1, lcd_width]
|
||||
* @param height Height of the bitmap, the range is [1, lcd_height]
|
||||
* @param color_data Pointer of the color data array
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool drawBitmap(uint16_t x_start, uint16_t y_start, uint16_t width, uint16_t height, const uint8_t *color_data);
|
||||
|
||||
/**
|
||||
* @brief Draw the bitmap to the LCD device with a timeout to wait for the drawing to finish
|
||||
*
|
||||
* @note This function should be called after `begin()`
|
||||
* @note This function not only calls `esp_lcd_panel_draw_bitmap()` to draw the bitmap, but also waits for the
|
||||
* drawing to finish until the timeout is reached.
|
||||
* @note This function is blocking and will quit after the drawing is finished. So the bitmap data can be
|
||||
* immediately modified
|
||||
* @note For RGB interface, this function is same as `drawBitmap()`
|
||||
*
|
||||
* @param x_start X coordinate of the start point, the range is [0, lcd_width - 1]
|
||||
* @param y_start Y coordinate of the start point, the range is [0, lcd_height - 1]
|
||||
* @param width Width of the bitmap, the range is [1, lcd_width]
|
||||
* @param height Height of the bitmap, the range is [1, lcd_height]
|
||||
* @param color_data Pointer of the color data array
|
||||
* @param timeout_ms Timeout in milliseconds, -1 means wait forever
|
||||
*
|
||||
* @return true if success, otherwise false or timeout
|
||||
*/
|
||||
bool drawBitmapWaitUntilFinish(uint16_t x_start, uint16_t y_start, uint16_t width, uint16_t height,
|
||||
const uint8_t *color_data, int timeout_ms = -1);
|
||||
|
||||
/**
|
||||
* @brief Mirror the X axis
|
||||
*
|
||||
* @note This function should be called after `begin()`
|
||||
* @note This function typically calls `esp_lcd_panel_mirror()` to mirror the axis
|
||||
*
|
||||
* @param en true: enable, false: disable
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool mirrorX(bool en);
|
||||
|
||||
/**
|
||||
* @brief Mirror the Y axis
|
||||
*
|
||||
* @note This function should be called after `begin()`
|
||||
* @note This function typically calls `esp_lcd_panel_mirror()` to mirror the axis
|
||||
*
|
||||
* @param en true: enable, false: disable
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool mirrorY(bool en);
|
||||
|
||||
/**
|
||||
* @brief Swap the X and Y axis
|
||||
*
|
||||
* @note This function should be called after `begin()`
|
||||
* @note This function typically calls `esp_lcd_panel_swap_xy()` to mirror the axises
|
||||
*
|
||||
* @param en true: enable, false: disable
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool swapXY(bool en);
|
||||
|
||||
/**
|
||||
* @brief Set the Gap in the X axis
|
||||
*
|
||||
* @note This function should be called after `begin()`
|
||||
* @note This function typically calls `esp_lcd_panel_set_gap()` to set the gap
|
||||
*
|
||||
* @param gap The gap in pixel
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool setGapX(uint16_t gap);
|
||||
|
||||
/**
|
||||
* @brief Set the Gap in the Y axis
|
||||
*
|
||||
* @note This function should be called after `begin()`
|
||||
* @note This function typically calls `esp_lcd_panel_set_gap()` to set the gap
|
||||
*
|
||||
* @param gap The gap in pixel
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool setGapY(uint16_t gap);
|
||||
|
||||
/**
|
||||
* @brief Invert every bit of pixel color data, like frome `0x55` to `0xAA`
|
||||
*
|
||||
* @note This function should be called after `begin()`
|
||||
* @note This function typically calls `esp_lcd_panel_invert_color()` to invert the color
|
||||
*
|
||||
* @param en true: invert, false: restore
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool invertColor(bool en);
|
||||
|
||||
/**
|
||||
* @brief Turn on the display
|
||||
*
|
||||
* @note This function should be called after `begin()`
|
||||
* @note This function typically calls `esp_lcd_panel_disp_on_off()` to control the display
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool displayOn(void);
|
||||
|
||||
/**
|
||||
* @brief Turn off the display
|
||||
*
|
||||
* @note This function should be called after `begin()`
|
||||
* @note This function typically calls `esp_lcd_panel_disp_on_off()` to control the display
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool displayOff(void);
|
||||
|
||||
/**
|
||||
* @brief Attach a callback function, which will be called when the refreshing is finished
|
||||
*
|
||||
* @note For RGB LCD, the function will be called when VSYNC end signal is detected, which means
|
||||
* the whole frame refreshing is finished
|
||||
* @note For other LCDs, the function will be called when every single drawing is finished
|
||||
*
|
||||
* @param callback The callback function. Its return value decides whether a high priority task has been waken up
|
||||
* by this function
|
||||
* @param user_data The user data which will be passed to the callback function
|
||||
*/
|
||||
bool attachRefreshFinishCallback(std::function<bool (void *)> callback, void *user_data = NULL);
|
||||
|
||||
/**
|
||||
* @brief Draw color bar from top left to bottom right, the order is BGR. This function is used for testing.
|
||||
*
|
||||
* @note Every bar indicate 1 bit. For example, if the `bits_per_pixel` is `16`, there will be `16` bars.
|
||||
* @note If the `height` can't be divided by `bits_per_pixel`, the reset area will be filled with white color.
|
||||
*
|
||||
* @param width The width of the color bar
|
||||
* @param height The height of the color bar
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool colorBarTest(uint16_t width, uint16_t height);
|
||||
|
||||
/**
|
||||
* @brief Get the bits of pixel color
|
||||
*
|
||||
* @return
|
||||
* - -1: if fail
|
||||
* - others: the bits of pixel color
|
||||
*/
|
||||
int getColorBits(void);
|
||||
|
||||
/**
|
||||
* @brief Get the flag of the X and Y axis swap
|
||||
*
|
||||
* @return true if swap, otherwise not swap
|
||||
*/
|
||||
bool getSwapXYFlag(void);
|
||||
|
||||
/**
|
||||
* @brief Get the flag of the X axis mirror
|
||||
*
|
||||
* @return true if mirror, otherwise not mirror
|
||||
*/
|
||||
bool getMirrorXFlag(void);
|
||||
|
||||
/**
|
||||
* @brief Get the flag of the Y axis mirror
|
||||
*
|
||||
* @return true if mirror, otherwise not mirror
|
||||
*/
|
||||
bool getMirrorYFlag(void);
|
||||
|
||||
#if SOC_LCD_RGB_SUPPORTED
|
||||
/**
|
||||
* @brief Get the RGB buffer by index (default is 0), only valid for RGB LCD
|
||||
*
|
||||
* @note This function should be called after `begin()`
|
||||
*
|
||||
* @param index
|
||||
*
|
||||
* @return
|
||||
* - NULL: if fail
|
||||
* - others: the pointer of the RGB buffer
|
||||
*/
|
||||
void *getRgbBufferByIndex(uint8_t index = 0);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Get the X coordinate align
|
||||
*
|
||||
* @return The X coordinate align
|
||||
*/
|
||||
uint8_t getXCoordAlign(void);
|
||||
|
||||
/**
|
||||
* @brief Get the Y coordinate align
|
||||
*
|
||||
* @return The Y coordinate align
|
||||
*/
|
||||
uint8_t getYCoordAlign(void);
|
||||
|
||||
/**
|
||||
* @brief Get the panel handle
|
||||
*
|
||||
* @return The handle of the LCD panel, or NULL if fail
|
||||
*/
|
||||
esp_lcd_panel_handle_t getHandle(void);
|
||||
|
||||
/**
|
||||
* @brief Get the panel bus
|
||||
*
|
||||
* @return The pointer of the LCD Bus, or NULL if fail
|
||||
*/
|
||||
ESP_PanelBus *getBus(void);
|
||||
|
||||
protected:
|
||||
uint8_t x_coord_align;
|
||||
uint8_t y_coord_align;
|
||||
ESP_PanelBus *bus;
|
||||
esp_lcd_panel_dev_config_t panel_config;
|
||||
esp_lcd_panel_vendor_config_t vendor_config;
|
||||
esp_lcd_panel_handle_t handle;
|
||||
|
||||
private:
|
||||
static bool onRefreshFinish(void *panel_io, void *edata, void *user_ctx);
|
||||
|
||||
bool _swap_xy;
|
||||
bool _mirror_x;
|
||||
bool _mirror_y;
|
||||
uint16_t _gap_x;
|
||||
uint16_t _gap_y;
|
||||
std::function<bool (void *)> onRefreshFinishCallback;
|
||||
SemaphoreHandle_t _refresh_finish_sem;
|
||||
|
||||
typedef struct {
|
||||
void *lcd_ptr;
|
||||
void *user_data;
|
||||
} ESP_PanelLcdCallbackData_t;
|
||||
ESP_PanelLcdCallbackData_t callback_data;
|
||||
};
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if SOC_LCD_RGB_SUPPORTED
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "GC9503.h"
|
||||
|
||||
static const char *TAG = "GC9503_CPP";
|
||||
|
||||
ESP_PanelLcd_GC9503::ESP_PanelLcd_GC9503(ESP_PanelBus *bus, uint8_t color_bits, int rst_io):
|
||||
ESP_PanelLcd(bus, color_bits, rst_io)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelLcd_GC9503::ESP_PanelLcd_GC9503(ESP_PanelBus *bus, const esp_lcd_panel_dev_config_t &panel_config):
|
||||
ESP_PanelLcd(bus, panel_config)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelLcd_GC9503::~ESP_PanelLcd_GC9503()
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
if (handle == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!del()) {
|
||||
ESP_LOGE(TAG, "Delete device failed");
|
||||
}
|
||||
|
||||
end:
|
||||
ESP_LOGD(TAG, "Destroyed");
|
||||
}
|
||||
|
||||
bool ESP_PanelLcd_GC9503::init(void)
|
||||
{
|
||||
ESP_PANEL_CHECK_NULL_RET(bus, false, "Invalid bus");
|
||||
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_new_panel_gc9503(bus->getHandle(), &panel_config, &handle), false, "Create panel failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if SOC_LCD_RGB_SUPPORTED
|
||||
#include "ESP_PanelLcd.h"
|
||||
#include "base/esp_lcd_custom_types.h"
|
||||
#include "base/esp_lcd_gc9503.h"
|
||||
|
||||
/**
|
||||
* @brief GC9503 LCD device object class
|
||||
*
|
||||
* @note This class is a derived class of `ESP_PanelLcd`, user can use it directly
|
||||
*/
|
||||
class ESP_PanelLcd_GC9503: public ESP_PanelLcd {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new LCD device in a simple way, the `init()` function should be called after this function
|
||||
*
|
||||
* @note This function uses some default values to config the LCD device, please use `config*()` functions to
|
||||
* change them
|
||||
* @note Vendor specific initialization can be different between manufacturers, should consult the LCD supplier
|
||||
* for initialization sequence code, and use `configVendorCommands()` to configure
|
||||
*
|
||||
* @param bus Pointer of panel bus
|
||||
* @param color_bits Bits per pixel (16/18/24)
|
||||
* @param rst_io Reset pin, set to -1 if no use
|
||||
*/
|
||||
ESP_PanelLcd_GC9503(ESP_PanelBus *bus, uint8_t color_bits, int rst_io = -1);
|
||||
|
||||
/**
|
||||
* @brief Construct a new LCD in a complex way, the `init()` function should be called after this function
|
||||
*
|
||||
* @param bus Pointer of panel bus
|
||||
* @param panel_config LCD device configuration
|
||||
*/
|
||||
ESP_PanelLcd_GC9503(ESP_PanelBus *bus, const esp_lcd_panel_dev_config_t &panel_config);
|
||||
|
||||
/**
|
||||
* @brief Destroy the LCD device
|
||||
*
|
||||
*/
|
||||
~ESP_PanelLcd_GC9503() override;
|
||||
|
||||
/**
|
||||
* @brief Initialize the LCD device, the `begin()` function should be called after this function
|
||||
*
|
||||
* @note This function typically calls `esp_lcd_new_panel_*()` to create the LCD panel handle
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool init(void) override;
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "GC9A01.h"
|
||||
|
||||
static const char *TAG = "GC9A01_CPP";
|
||||
|
||||
ESP_PanelLcd_GC9A01::ESP_PanelLcd_GC9A01(ESP_PanelBus *bus, uint8_t color_bits, int rst_io):
|
||||
ESP_PanelLcd(bus, color_bits, rst_io)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelLcd_GC9A01::ESP_PanelLcd_GC9A01(ESP_PanelBus *bus, const esp_lcd_panel_dev_config_t &panel_config):
|
||||
ESP_PanelLcd(bus, panel_config)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelLcd_GC9A01::~ESP_PanelLcd_GC9A01()
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
if (handle == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!del()) {
|
||||
ESP_LOGE(TAG, "Delete device failed");
|
||||
}
|
||||
|
||||
end:
|
||||
ESP_LOGD(TAG, "Destroyed");
|
||||
}
|
||||
|
||||
bool ESP_PanelLcd_GC9A01::init(void)
|
||||
{
|
||||
ESP_PANEL_CHECK_NULL_RET(bus, false, "Invalid bus");
|
||||
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_new_panel_gc9a01(bus->getHandle(), &panel_config, &handle), false, "Create panel failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ESP_PanelLcd.h"
|
||||
#include "base/esp_lcd_custom_types.h"
|
||||
#include "base/esp_lcd_gc9a01.h"
|
||||
|
||||
/**
|
||||
* @brief GC9A01 LCD device object class
|
||||
*
|
||||
* @note This class is a derived class of `ESP_PanelLcd`, user can use it directly
|
||||
*/
|
||||
class ESP_PanelLcd_GC9A01: public ESP_PanelLcd {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new LCD device in a simple way, the `init()` function should be called after this function
|
||||
*
|
||||
* @note This function uses some default values to config the LCD device, please use `config*()` functions to
|
||||
* change them
|
||||
* @note Vendor specific initialization can be different between manufacturers, should consult the LCD supplier
|
||||
* for initialization sequence code, and use `configVendorCommands()` to configure
|
||||
*
|
||||
* @param bus Pointer of panel bus
|
||||
* @param color_bits Bits per pixel (16/18)
|
||||
* @param rst_io Reset pin, set to -1 if no use
|
||||
*/
|
||||
ESP_PanelLcd_GC9A01(ESP_PanelBus *bus, uint8_t color_bits, int rst_io = -1);
|
||||
|
||||
/**
|
||||
* @brief Construct a new LCD in a complex way, the `init()` function should be called after this function
|
||||
*
|
||||
* @param bus Pointer of panel bus
|
||||
* @param panel_config LCD device configuration
|
||||
*/
|
||||
ESP_PanelLcd_GC9A01(ESP_PanelBus *bus, const esp_lcd_panel_dev_config_t &panel_config);
|
||||
|
||||
/**
|
||||
* @brief Destroy the LCD device
|
||||
*
|
||||
*/
|
||||
~ESP_PanelLcd_GC9A01() override;
|
||||
|
||||
/**
|
||||
* @brief Initialize the LCD device, the `begin()` function should be called after this function
|
||||
*
|
||||
* @note This function typically calls `esp_lcd_new_panel_*()` to create the LCD panel handle
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool init(void) override;
|
||||
};
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "GC9B71.h"
|
||||
|
||||
static const char *TAG = "GC9B71_CPP";
|
||||
|
||||
ESP_PanelLcd_GC9B71::ESP_PanelLcd_GC9B71(ESP_PanelBus *bus, uint8_t color_bits, int rst_io):
|
||||
ESP_PanelLcd(bus, color_bits, rst_io)
|
||||
{
|
||||
x_coord_align = 2;
|
||||
y_coord_align = 2;
|
||||
}
|
||||
|
||||
ESP_PanelLcd_GC9B71::ESP_PanelLcd_GC9B71(ESP_PanelBus *bus, const esp_lcd_panel_dev_config_t &panel_config):
|
||||
ESP_PanelLcd(bus, panel_config)
|
||||
{
|
||||
x_coord_align = 2;
|
||||
y_coord_align = 2;
|
||||
}
|
||||
|
||||
ESP_PanelLcd_GC9B71::~ESP_PanelLcd_GC9B71()
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
if (handle == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!del()) {
|
||||
ESP_LOGE(TAG, "Delete device failed");
|
||||
}
|
||||
|
||||
end:
|
||||
ESP_LOGD(TAG, "Destroyed");
|
||||
}
|
||||
|
||||
bool ESP_PanelLcd_GC9B71::init(void)
|
||||
{
|
||||
ESP_PANEL_CHECK_NULL_RET(bus, false, "Invalid bus");
|
||||
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_new_panel_gc9b71(bus->getHandle(), &panel_config, &handle), false, "Create panel failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ESP_PanelLcd.h"
|
||||
#include "base/esp_lcd_custom_types.h"
|
||||
#include "base/esp_lcd_gc9b71.h"
|
||||
|
||||
/**
|
||||
* @brief GC9B71 LCD device object class
|
||||
*
|
||||
* @note This class is a derived class of `ESP_PanelLcd`, user can use it directly
|
||||
*/
|
||||
class ESP_PanelLcd_GC9B71: public ESP_PanelLcd {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new LCD device in a simple way, the `init()` function should be called after this function
|
||||
*
|
||||
* @note This function uses some default values to config the LCD device, please use `config*()` functions to
|
||||
* change them
|
||||
* @note Vendor specific initialization can be different between manufacturers, should consult the LCD supplier
|
||||
* for initialization sequence code, and use `configVendorCommands()` to configure
|
||||
*
|
||||
* @param bus Pointer of panel bus
|
||||
* @param color_bits Bits per pixel (16/18/24)
|
||||
* @param rst_io Reset pin, set to -1 if no use
|
||||
*/
|
||||
ESP_PanelLcd_GC9B71(ESP_PanelBus *bus, uint8_t color_bits, int rst_io = -1);
|
||||
|
||||
/**
|
||||
* @brief Construct a new LCD in a complex way, the `init()` function should be called after this function
|
||||
*
|
||||
* @param bus Pointer of panel bus
|
||||
* @param panel_config LCD device configuration
|
||||
*/
|
||||
ESP_PanelLcd_GC9B71(ESP_PanelBus *bus, const esp_lcd_panel_dev_config_t &panel_config);
|
||||
|
||||
/**
|
||||
* @brief Destroy the LCD device
|
||||
*
|
||||
*/
|
||||
~ESP_PanelLcd_GC9B71() override;
|
||||
|
||||
/**
|
||||
* @brief Initialize the LCD device, the `begin()` function should be called after this function
|
||||
*
|
||||
* @note This function typically calls `esp_lcd_new_panel_*()` to create the LCD panel handle
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool init(void) override;
|
||||
};
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "ILI9341.h"
|
||||
|
||||
static const char *TAG = "ILI9341_CPP";
|
||||
|
||||
ESP_PanelLcd_ILI9341::ESP_PanelLcd_ILI9341(ESP_PanelBus *bus, uint8_t color_bits, int rst_io):
|
||||
ESP_PanelLcd(bus, color_bits, rst_io)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelLcd_ILI9341::ESP_PanelLcd_ILI9341(ESP_PanelBus *bus, const esp_lcd_panel_dev_config_t &panel_config):
|
||||
ESP_PanelLcd(bus, panel_config)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelLcd_ILI9341::~ESP_PanelLcd_ILI9341()
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
if (handle == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!del()) {
|
||||
ESP_LOGE(TAG, "Delete device failed");
|
||||
}
|
||||
|
||||
end:
|
||||
ESP_LOGD(TAG, "Destroyed");
|
||||
}
|
||||
|
||||
bool ESP_PanelLcd_ILI9341::init(void)
|
||||
{
|
||||
ESP_PANEL_CHECK_NULL_RET(bus, false, "Invalid bus");
|
||||
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_new_panel_ili9341(bus->getHandle(), &panel_config, &handle), false, "Create panel failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ESP_PanelLcd.h"
|
||||
#include "base/esp_lcd_custom_types.h"
|
||||
#include "base/esp_lcd_ili9341.h"
|
||||
|
||||
/**
|
||||
* @brief ILI9341 LCD device object class
|
||||
*
|
||||
* @note This class is a derived class of `ESP_PanelLcd`, user can use it directly
|
||||
*/
|
||||
class ESP_PanelLcd_ILI9341: public ESP_PanelLcd {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new LCD device in a simple way, the `init()` function should be called after this function
|
||||
*
|
||||
* @note This function uses some default values to config the LCD device, please use `config*()` functions to
|
||||
* change them
|
||||
* @note Vendor specific initialization can be different between manufacturers, should consult the LCD supplier
|
||||
* for initialization sequence code, and use `configVendorCommands()` to configure
|
||||
*
|
||||
* @param bus Pointer of panel bus
|
||||
* @param color_bits Bits per pixel (16/18)
|
||||
* @param rst_io Reset pin, set to -1 if no use
|
||||
*/
|
||||
ESP_PanelLcd_ILI9341(ESP_PanelBus *bus, uint8_t color_bits, int rst_io = -1);
|
||||
|
||||
/**
|
||||
* @brief Construct a new LCD device in a complex way, the `init()` function should be called after this function
|
||||
*
|
||||
* @param bus Pointer of panel bus
|
||||
* @param panel_config LCD device configuration
|
||||
*/
|
||||
ESP_PanelLcd_ILI9341(ESP_PanelBus *bus, const esp_lcd_panel_dev_config_t &panel_config);
|
||||
|
||||
/**
|
||||
* @brief Destroy the LCD device
|
||||
*
|
||||
*/
|
||||
~ESP_PanelLcd_ILI9341() override;
|
||||
|
||||
/**
|
||||
* @brief Initialize the LCD device, the `begin()` function should be called after this function
|
||||
*
|
||||
* @note This function typically calls `esp_lcd_new_panel_*()` to create the LCD panel handle
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool init(void) override;
|
||||
};
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "NV3022B.h"
|
||||
|
||||
static const char *TAG = "NV3022B_CPP";
|
||||
|
||||
ESP_PanelLcd_NV3022B::ESP_PanelLcd_NV3022B(ESP_PanelBus *bus, uint8_t color_bits, int rst_io):
|
||||
ESP_PanelLcd(bus, color_bits, rst_io)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelLcd_NV3022B::ESP_PanelLcd_NV3022B(ESP_PanelBus *bus, const esp_lcd_panel_dev_config_t &panel_config):
|
||||
ESP_PanelLcd(bus, panel_config)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelLcd_NV3022B::~ESP_PanelLcd_NV3022B()
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
if (handle == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!del()) {
|
||||
ESP_LOGE(TAG, "Delete device failed");
|
||||
}
|
||||
|
||||
end:
|
||||
ESP_LOGD(TAG, "Destroyed");
|
||||
}
|
||||
|
||||
bool ESP_PanelLcd_NV3022B::init(void)
|
||||
{
|
||||
ESP_PANEL_CHECK_NULL_RET(bus, false, "Invalid bus");
|
||||
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_new_panel_nv3022b(bus->getHandle(), &panel_config, &handle), false, "Create panel failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ESP_PanelLcd.h"
|
||||
#include "base/esp_lcd_custom_types.h"
|
||||
#include "base/esp_lcd_nv3022b.h"
|
||||
|
||||
/**
|
||||
* @brief NV3022B LCD device object class
|
||||
*
|
||||
* @note This class is a derived class of `ESP_PanelLcd`, user can use it directly
|
||||
*/
|
||||
class ESP_PanelLcd_NV3022B: public ESP_PanelLcd {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new LCD device in a simple way, the `init()` function should be called after this function
|
||||
*
|
||||
* @note This function uses some default values to config the LCD device, please use `config*()` functions to
|
||||
* change them
|
||||
* @note Vendor specific initialization can be different between manufacturers, should consult the LCD supplier
|
||||
* for initialization sequence code, and use `configVendorCommands()` to configure
|
||||
*
|
||||
* @param bus Pointer of panel bus
|
||||
* @param color_bits Bits per pixel (16/18/24)
|
||||
* @param rst_io Reset pin, set to -1 if no use
|
||||
*/
|
||||
ESP_PanelLcd_NV3022B(ESP_PanelBus *bus, uint8_t color_bits, int rst_io = -1);
|
||||
|
||||
/**
|
||||
* @brief Construct a new LCD in a complex way, the `init()` function should be called after this function
|
||||
*
|
||||
* @param bus Pointer of panel bus
|
||||
* @param panel_config LCD device configuration
|
||||
*/
|
||||
ESP_PanelLcd_NV3022B(ESP_PanelBus *bus, const esp_lcd_panel_dev_config_t &panel_config);
|
||||
|
||||
/**
|
||||
* @brief Destroy the LCD device
|
||||
*
|
||||
*/
|
||||
~ESP_PanelLcd_NV3022B() override;
|
||||
|
||||
/**
|
||||
* @brief Initialize the LCD device, the `begin()` function should be called after this function
|
||||
*
|
||||
* @note This function typically calls `esp_lcd_new_panel_*()` to create the LCD panel handle
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool init(void) override;
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
# LCD Controllers
|
||||
|
||||
| **Name** | **Version** |
|
||||
| -------------------------------------------------------------------------------- | ----------- |
|
||||
| [GC9A01](https://components.espressif.com/components/espressif/esp_lcd_gc9a01) | 2.0.0 |
|
||||
| [GC9B71](https://components.espressif.com/components/espressif/esp_lcd_gc9b71) | 1.0.1 |
|
||||
| [GC9503](https://components.espressif.com/components/espressif/esp_lcd_gc9503) | 3.0.1 |
|
||||
| [ILI9341](https://components.espressif.com/components/espressif/esp_lcd_ili9341) | 2.0.0 |
|
||||
| [NV3022B](https://components.espressif.com/components/espressif/esp_lcd_nv3022b) | 0.0.1 |
|
||||
| [SH8601](https://components.espressif.com/components/espressif/esp_lcd_sh8601) | 1.0.0 |
|
||||
| [SPD2010](https://components.espressif.com/components/espressif/esp_lcd_spd2010) | 1.0.1 |
|
||||
| ST7262 | - |
|
||||
| [ST7701](https://components.espressif.com/components/espressif/esp_lcd_st7701) | 1.0.1 |
|
||||
| ST7789 | - |
|
||||
| [ST7796](https://components.espressif.com/components/espressif/esp_lcd_st7796) | 1.2.1 |
|
||||
| [ST77916](https://components.espressif.com/components/espressif/esp_lcd_st77916) | 0.0.2 |
|
||||
| [ST77922](https://components.espressif.com/components/espressif/esp_lcd_st77922) | 0.0.2 |
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "SH8601.h"
|
||||
|
||||
static const char *TAG = "SH8601_CPP";
|
||||
|
||||
ESP_PanelLcd_SH8601::ESP_PanelLcd_SH8601(ESP_PanelBus *bus, uint8_t color_bits, int rst_io):
|
||||
ESP_PanelLcd(bus, color_bits, rst_io)
|
||||
{
|
||||
x_coord_align = 2;
|
||||
y_coord_align = 2;
|
||||
}
|
||||
|
||||
ESP_PanelLcd_SH8601::ESP_PanelLcd_SH8601(ESP_PanelBus *bus, const esp_lcd_panel_dev_config_t &panel_config):
|
||||
ESP_PanelLcd(bus, panel_config)
|
||||
{
|
||||
x_coord_align = 2;
|
||||
y_coord_align = 2;
|
||||
}
|
||||
|
||||
ESP_PanelLcd_SH8601::~ESP_PanelLcd_SH8601()
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
if (handle == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!del()) {
|
||||
ESP_LOGE(TAG, "Delete device failed");
|
||||
}
|
||||
|
||||
end:
|
||||
ESP_LOGD(TAG, "Destroyed");
|
||||
}
|
||||
|
||||
bool ESP_PanelLcd_SH8601::init(void)
|
||||
{
|
||||
ESP_PANEL_CHECK_NULL_RET(bus, false, "Invalid bus");
|
||||
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_new_panel_sh8601(bus->getHandle(), &panel_config, &handle), false, "Create panel failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ESP_PanelLcd.h"
|
||||
#include "base/esp_lcd_custom_types.h"
|
||||
#include "base/esp_lcd_sh8601.h"
|
||||
|
||||
/**
|
||||
* @brief SH8601 LCD device object class
|
||||
*
|
||||
* @note This class is a derived class of `ESP_PanelLcd`, user can use it directly
|
||||
*/
|
||||
class ESP_PanelLcd_SH8601: public ESP_PanelLcd {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new LCD device in a simple way, the `init()` function should be called after this function
|
||||
*
|
||||
* @note This function uses some default values to config the LCD device, please use `config*()` functions to
|
||||
* change them
|
||||
* @note Vendor specific initialization can be different between manufacturers, should consult the LCD supplier
|
||||
* for initialization sequence code, and use `configVendorCommands()` to configure
|
||||
*
|
||||
* @param bus Pointer of panel bus
|
||||
* @param color_bits Bits per pixel (16/18/24)
|
||||
* @param rst_io Reset pin, set to -1 if no use
|
||||
*/
|
||||
ESP_PanelLcd_SH8601(ESP_PanelBus *bus, uint8_t color_bits, int rst_io = -1);
|
||||
|
||||
/**
|
||||
* @brief Construct a new LCD in a complex way, the `init()` function should be called after this function
|
||||
*
|
||||
* @param bus Pointer of panel bus
|
||||
* @param panel_config LCD device configuration
|
||||
*/
|
||||
ESP_PanelLcd_SH8601(ESP_PanelBus *bus, const esp_lcd_panel_dev_config_t &panel_config);
|
||||
|
||||
/**
|
||||
* @brief Destroy the LCD device
|
||||
*
|
||||
*/
|
||||
~ESP_PanelLcd_SH8601() override;
|
||||
|
||||
/**
|
||||
* @brief Initialize the LCD device, the `begin()` function should be called after this function
|
||||
*
|
||||
* @note This function typically calls `esp_lcd_new_panel_*()` to create the LCD panel handle
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool init(void) override;
|
||||
};
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "SPD2010.h"
|
||||
|
||||
static const char *TAG = "SPD2010_CPP";
|
||||
|
||||
ESP_PanelLcd_SPD2010::ESP_PanelLcd_SPD2010(ESP_PanelBus *bus, uint8_t color_bits, int rst_io):
|
||||
ESP_PanelLcd(bus, color_bits, rst_io)
|
||||
{
|
||||
x_coord_align = 4;
|
||||
}
|
||||
|
||||
ESP_PanelLcd_SPD2010::ESP_PanelLcd_SPD2010(ESP_PanelBus *bus, const esp_lcd_panel_dev_config_t &panel_config):
|
||||
ESP_PanelLcd(bus, panel_config)
|
||||
{
|
||||
x_coord_align = 4;
|
||||
}
|
||||
|
||||
ESP_PanelLcd_SPD2010::~ESP_PanelLcd_SPD2010()
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
if (handle == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!del()) {
|
||||
ESP_LOGE(TAG, "Delete device failed");
|
||||
}
|
||||
|
||||
end:
|
||||
ESP_LOGD(TAG, "Destroyed");
|
||||
}
|
||||
|
||||
bool ESP_PanelLcd_SPD2010::init(void)
|
||||
{
|
||||
ESP_PANEL_CHECK_NULL_RET(bus, false, "Invalid bus");
|
||||
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_new_panel_spd2010(bus->getHandle(), &panel_config, &handle), false, "Create panel failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ESP_PanelLcd.h"
|
||||
#include "base/esp_lcd_custom_types.h"
|
||||
#include "base/esp_lcd_spd2010.h"
|
||||
|
||||
/**
|
||||
* @brief SPD2010 LCD device object class
|
||||
*
|
||||
* @note This class is a derived class of `ESP_PanelLcd`, user can use it directly
|
||||
*/
|
||||
class ESP_PanelLcd_SPD2010: public ESP_PanelLcd {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new LCD device in a simple way, the `init()` function should be called after this function
|
||||
*
|
||||
* @note This function uses some default values to config the LCD device, please use `config*()` functions to
|
||||
* change them
|
||||
* @note Vendor specific initialization can be different between manufacturers, should consult the LCD supplier
|
||||
* for initialization sequence code, and use `configVendorCommands()` to configure
|
||||
*
|
||||
* @param bus Pointer of panel bus
|
||||
* @param color_bits Bits per pixel (16/18/24)
|
||||
* @param rst_io Reset pin, set to -1 if no use
|
||||
*/
|
||||
ESP_PanelLcd_SPD2010(ESP_PanelBus *bus, uint8_t color_bits, int rst_io = -1);
|
||||
|
||||
/**
|
||||
* @brief Construct a new LCD in a complex way, the `init()` function should be called after this function
|
||||
*
|
||||
* @param bus Pointer of panel bus
|
||||
* @param panel_config LCD device configuration
|
||||
*/
|
||||
ESP_PanelLcd_SPD2010(ESP_PanelBus *bus, const esp_lcd_panel_dev_config_t &panel_config);
|
||||
|
||||
/**
|
||||
* @brief Destroy the LCD device
|
||||
*
|
||||
*/
|
||||
~ESP_PanelLcd_SPD2010() override;
|
||||
|
||||
/**
|
||||
* @brief Initialize the LCD device, the `begin()` function should be called after this function
|
||||
*
|
||||
* @note This function typically calls `esp_lcd_new_panel_*()` to create the LCD panel handle
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool init(void) override;
|
||||
};
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if SOC_LCD_RGB_SUPPORTED
|
||||
#include "driver/gpio.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "esp_lcd_panel_rgb.h"
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "bus/RGB.h"
|
||||
#include "ST7262.h"
|
||||
|
||||
static const char *TAG = "ST7262_CPP";
|
||||
|
||||
ESP_PanelLcd_ST7262::ESP_PanelLcd_ST7262(ESP_PanelBus *bus, uint8_t color_bits, int rst_io):
|
||||
ESP_PanelLcd(bus, color_bits, rst_io)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelLcd_ST7262::ESP_PanelLcd_ST7262(ESP_PanelBus *bus, const esp_lcd_panel_dev_config_t &panel_config):
|
||||
ESP_PanelLcd(bus, panel_config)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelLcd_ST7262::~ESP_PanelLcd_ST7262()
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
if (handle == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!del()) {
|
||||
ESP_LOGE(TAG, "Delete device failed");
|
||||
}
|
||||
|
||||
end:
|
||||
ESP_LOGD(TAG, "Destroyed");
|
||||
}
|
||||
|
||||
bool ESP_PanelLcd_ST7262::init(void)
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
if (panel_config.reset_gpio_num >= 0) {
|
||||
gpio_config_t gpio_conf = {
|
||||
.pin_bit_mask = BIT64(panel_config.reset_gpio_num),
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pull_up_en = GPIO_PULLUP_DISABLE,
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||
.intr_type = GPIO_INTR_DISABLE,
|
||||
};
|
||||
ESP_PANEL_CHECK_ERR_RET(gpio_config(&gpio_conf), false, "`Config RST gpio failed");
|
||||
}
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_new_rgb_panel(vendor_config.rgb_config, &handle), false, "Create panel failed");
|
||||
|
||||
ESP_LOGD(TAG, "LCD panel @%p created", handle);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_PanelLcd_ST7262::reset(void)
|
||||
{
|
||||
ESP_PANEL_CHECK_NULL_RET(handle, false, "Invalid handle");
|
||||
|
||||
if (panel_config.reset_gpio_num >= 0) {
|
||||
gpio_set_level((gpio_num_t)panel_config.reset_gpio_num, panel_config.flags.reset_active_high);
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
gpio_set_level((gpio_num_t)panel_config.reset_gpio_num, !panel_config.flags.reset_active_high);
|
||||
vTaskDelay(pdMS_TO_TICKS(120));
|
||||
}
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_panel_reset(handle), false, "Reset panel failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /* SOC_LCD_RGB_SUPPORTED */
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if SOC_LCD_RGB_SUPPORTED
|
||||
#include "ESP_PanelLcd.h"
|
||||
|
||||
/**
|
||||
* @brief ST7262 LCD device object class
|
||||
*
|
||||
* @note This class is a derived class of `ESP_PanelLcd`, user can use it directly
|
||||
*/
|
||||
class ESP_PanelLcd_ST7262: public ESP_PanelLcd {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new LCD device in a simple way, the `init()` function should be called after this function
|
||||
*
|
||||
* @note This function uses some default values to config the LCD device, please use `config*()` functions to
|
||||
* change them
|
||||
*
|
||||
* @param bus Pointer of panel bus
|
||||
* @param color_bits Bits per pixel (24)
|
||||
* @param rst_io Reset pin, set to `-1` if no use
|
||||
*/
|
||||
ESP_PanelLcd_ST7262(ESP_PanelBus *bus, uint8_t color_bits, int rst_io = -1);
|
||||
|
||||
/**
|
||||
* @brief Construct a new LCD device in a complex way, the `init()` function should be called after this function
|
||||
*
|
||||
* @param bus Pointer of panel bus
|
||||
* @param panel_config LCD device configuration
|
||||
*/
|
||||
ESP_PanelLcd_ST7262(ESP_PanelBus *bus, const esp_lcd_panel_dev_config_t &panel_config);
|
||||
|
||||
/**
|
||||
* @brief Destroy the LCD device
|
||||
*
|
||||
*/
|
||||
~ESP_PanelLcd_ST7262() override;
|
||||
|
||||
/**
|
||||
* @brief Initialize the LCD device, the `begin()` function should be called after this function
|
||||
*
|
||||
* @note This function typically calls `esp_lcd_new_panel_*()` to create the LCD panel handle
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool init(void) override;
|
||||
|
||||
/**
|
||||
* @brief Reset the LCD. If the `rst_io` is not set, this function will do reset by software instead of hardware
|
||||
*
|
||||
* @note This function should be called after `init()`
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool reset(void);
|
||||
};
|
||||
|
||||
#endif /* SOC_LCD_RGB_SUPPORTED */
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if SOC_LCD_RGB_SUPPORTED
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "ST7701.h"
|
||||
|
||||
static const char *TAG = "ST7701_CPP";
|
||||
|
||||
ESP_PanelLcd_ST7701::ESP_PanelLcd_ST7701(ESP_PanelBus *bus, uint8_t color_bits, int rst_io):
|
||||
ESP_PanelLcd(bus, color_bits, rst_io)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelLcd_ST7701::ESP_PanelLcd_ST7701(ESP_PanelBus *bus, const esp_lcd_panel_dev_config_t &panel_config):
|
||||
ESP_PanelLcd(bus, panel_config)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelLcd_ST7701::~ESP_PanelLcd_ST7701()
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
if (handle == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!del()) {
|
||||
ESP_LOGE(TAG, "Delete device failed");
|
||||
}
|
||||
|
||||
end:
|
||||
ESP_LOGD(TAG, "Destroyed");
|
||||
}
|
||||
|
||||
bool ESP_PanelLcd_ST7701::init(void)
|
||||
{
|
||||
ESP_PANEL_CHECK_NULL_RET(bus, false, "Invalid bus");
|
||||
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_new_panel_st7701(bus->getHandle(), &panel_config, &handle), false, "Create panel failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if SOC_LCD_RGB_SUPPORTED
|
||||
#include "ESP_PanelLcd.h"
|
||||
#include "base/esp_lcd_custom_types.h"
|
||||
#include "base/esp_lcd_st7701.h"
|
||||
|
||||
/**
|
||||
* @brief ST7701 LCD device object class
|
||||
*
|
||||
* @note This class is a derived class of `ESP_PanelLcd`, user can use it directly
|
||||
*/
|
||||
class ESP_PanelLcd_ST7701: public ESP_PanelLcd {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new LCD device in a simple way, the `init()` function should be called after this function
|
||||
*
|
||||
* @note This function uses some default values to config the LCD device, please use `config*()` functions to
|
||||
* change them
|
||||
* @note Vendor specific initialization can be different between manufacturers, should consult the LCD supplier
|
||||
* for initialization sequence code, and use `configVendorCommands()` to configure
|
||||
*
|
||||
* @param bus Pointer of panel bus
|
||||
* @param color_bits Bits per pixel (16/18/24)
|
||||
* @param rst_io Reset pin, set to -1 if no use
|
||||
*/
|
||||
ESP_PanelLcd_ST7701(ESP_PanelBus *bus, uint8_t color_bits, int rst_io = -1);
|
||||
|
||||
/**
|
||||
* @brief Construct a new LCD in a complex way, the `init()` function should be called after this function
|
||||
*
|
||||
* @param bus Pointer of panel bus
|
||||
* @param panel_config LCD device configuration
|
||||
*/
|
||||
ESP_PanelLcd_ST7701(ESP_PanelBus *bus, const esp_lcd_panel_dev_config_t &panel_config);
|
||||
|
||||
/**
|
||||
* @brief Destroy the LCD device
|
||||
*
|
||||
*/
|
||||
~ESP_PanelLcd_ST7701() override;
|
||||
|
||||
/**
|
||||
* @brief Initialize the LCD device, the `begin()` function should be called after this function
|
||||
*
|
||||
* @note This function typically calls `esp_lcd_new_panel_*()` to create the LCD panel handle
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool init(void) override;
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "ST7789.h"
|
||||
|
||||
static const char *TAG = "ST7789_CPP";
|
||||
|
||||
ESP_PanelLcd_ST7789::ESP_PanelLcd_ST7789(ESP_PanelBus *bus, uint8_t color_bits, int rst_io):
|
||||
ESP_PanelLcd(bus, color_bits, rst_io)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelLcd_ST7789::ESP_PanelLcd_ST7789(ESP_PanelBus *bus, const esp_lcd_panel_dev_config_t &panel_config):
|
||||
ESP_PanelLcd(bus, panel_config)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelLcd_ST7789::~ESP_PanelLcd_ST7789()
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
if (handle == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!del()) {
|
||||
ESP_LOGE(TAG, "Delete device failed");
|
||||
}
|
||||
|
||||
end:
|
||||
ESP_LOGD(TAG, "Destroyed");
|
||||
}
|
||||
|
||||
bool ESP_PanelLcd_ST7789::init(void)
|
||||
{
|
||||
ESP_PANEL_CHECK_NULL_RET(bus, false, "Invalid bus");
|
||||
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_new_panel_st7789(bus->getHandle(), &panel_config, &handle), false, "Create panel failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ESP_PanelLcd.h"
|
||||
#include "base/esp_lcd_custom_types.h"
|
||||
#include "base/esp_lcd_st7789.h"
|
||||
|
||||
/**
|
||||
* @brief ST7789 LCD device object class
|
||||
*
|
||||
* @note This class is a derived class of `ESP_PanelLcd`, user can use it directly
|
||||
*/
|
||||
class ESP_PanelLcd_ST7789: public ESP_PanelLcd {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new LCD device in a simple way, the `init()` function should be called after this function
|
||||
*
|
||||
* @note This function uses some default values to config the LCD device, please use `config*()` functions to
|
||||
* change them
|
||||
* @note Vendor specific initialization can be different between manufacturers, should consult the LCD supplier
|
||||
* for initialization sequence code, and use `configVendorCommands()` to configure
|
||||
*
|
||||
* @param bus Pointer of panel bus
|
||||
* @param color_bits Bits per pixel (16/18)
|
||||
* @param rst_io Reset pin, set to -1 if no use
|
||||
*/
|
||||
ESP_PanelLcd_ST7789(ESP_PanelBus *bus, uint8_t color_bits, int rst_io = -1);
|
||||
|
||||
/**
|
||||
* @brief Construct a new LCD in a complex way, the `init()` function should be called after this function
|
||||
*
|
||||
* @param bus Pointer of panel bus
|
||||
* @param panel_config LCD device configuration
|
||||
*/
|
||||
ESP_PanelLcd_ST7789(ESP_PanelBus *bus, const esp_lcd_panel_dev_config_t &panel_config);
|
||||
|
||||
/**
|
||||
* @brief Destroy the LCD device
|
||||
*
|
||||
*/
|
||||
~ESP_PanelLcd_ST7789() override;
|
||||
|
||||
/**
|
||||
* @brief Initialize the LCD device, the `begin()` function should be called after this function
|
||||
*
|
||||
* @note This function typically calls `esp_lcd_new_panel_*()` to create the LCD panel handle
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool init(void) override;
|
||||
};
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "ST77916.h"
|
||||
|
||||
static const char *TAG = "ST77916_CPP";
|
||||
|
||||
ESP_PanelLcd_ST77916::ESP_PanelLcd_ST77916(ESP_PanelBus *bus, uint8_t color_bits, int rst_io):
|
||||
ESP_PanelLcd(bus, color_bits, rst_io)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelLcd_ST77916::ESP_PanelLcd_ST77916(ESP_PanelBus *bus, const esp_lcd_panel_dev_config_t &panel_config):
|
||||
ESP_PanelLcd(bus, panel_config)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelLcd_ST77916::~ESP_PanelLcd_ST77916()
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
if (handle == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!del()) {
|
||||
ESP_LOGE(TAG, "Delete device failed");
|
||||
}
|
||||
|
||||
end:
|
||||
ESP_LOGD(TAG, "Destroyed");
|
||||
}
|
||||
|
||||
bool ESP_PanelLcd_ST77916::init(void)
|
||||
{
|
||||
ESP_PANEL_CHECK_NULL_RET(bus, false, "Invalid bus");
|
||||
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_new_panel_st77916(bus->getHandle(), &panel_config, &handle), false, "Create panel failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ESP_PanelLcd.h"
|
||||
#include "base/esp_lcd_custom_types.h"
|
||||
#include "base/esp_lcd_st77916.h"
|
||||
|
||||
/**
|
||||
* @brief ST77916 LCD device object class
|
||||
*
|
||||
* @note This class is a derived class of `ESP_PanelLcd`, user can use it directly
|
||||
*/
|
||||
class ESP_PanelLcd_ST77916: public ESP_PanelLcd {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new LCD device in a simple way, the `init()` function should be called after this function
|
||||
*
|
||||
* @note This function uses some default values to config the LCD device, please use `config*()` functions to
|
||||
* change them
|
||||
* @note Vendor specific initialization can be different between manufacturers, should consult the LCD supplier
|
||||
* for initialization sequence code, and use `configVendorCommands()` to configure
|
||||
*
|
||||
* @param bus Pointer of panel bus
|
||||
* @param color_bits Bits per pixel (16/18)
|
||||
* @param rst_io Reset pin, set to -1 if no use
|
||||
*/
|
||||
ESP_PanelLcd_ST77916(ESP_PanelBus *bus, uint8_t color_bits, int rst_io = -1);
|
||||
|
||||
/**
|
||||
* @brief Construct a new LCD in a complex way, the `init()` function should be called after this function
|
||||
*
|
||||
* @param bus Pointer of panel bus
|
||||
* @param panel_config LCD device configuration
|
||||
*/
|
||||
ESP_PanelLcd_ST77916(ESP_PanelBus *bus, const esp_lcd_panel_dev_config_t &panel_config);
|
||||
|
||||
/**
|
||||
* @brief Destroy the LCD device
|
||||
*
|
||||
*/
|
||||
~ESP_PanelLcd_ST77916() override;
|
||||
|
||||
/**
|
||||
* @brief Initialize the LCD device, the `begin()` function should be called after this function
|
||||
*
|
||||
* @note This function typically calls `esp_lcd_new_panel_*()` to create the LCD panel handle
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool init(void) override;
|
||||
};
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "ST77922.h"
|
||||
|
||||
static const char *TAG = "ST77922_CPP";
|
||||
|
||||
ESP_PanelLcd_ST77922::ESP_PanelLcd_ST77922(ESP_PanelBus *bus, uint8_t color_bits, int rst_io):
|
||||
ESP_PanelLcd(bus, color_bits, rst_io)
|
||||
{
|
||||
x_coord_align = 4;
|
||||
}
|
||||
|
||||
ESP_PanelLcd_ST77922::ESP_PanelLcd_ST77922(ESP_PanelBus *bus, const esp_lcd_panel_dev_config_t &panel_config):
|
||||
ESP_PanelLcd(bus, panel_config)
|
||||
{
|
||||
x_coord_align = 4;
|
||||
}
|
||||
|
||||
ESP_PanelLcd_ST77922::~ESP_PanelLcd_ST77922()
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
if (handle == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!del()) {
|
||||
ESP_LOGE(TAG, "Delete device failed");
|
||||
}
|
||||
|
||||
end:
|
||||
ESP_LOGD(TAG, "Destroyed");
|
||||
}
|
||||
|
||||
bool ESP_PanelLcd_ST77922::init(void)
|
||||
{
|
||||
ESP_PANEL_CHECK_NULL_RET(bus, false, "Invalid bus");
|
||||
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_new_panel_st77922(bus->getHandle(), &panel_config, &handle), false, "Create panel failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ESP_PanelLcd.h"
|
||||
#include "base/esp_lcd_custom_types.h"
|
||||
#include "base/esp_lcd_st77922.h"
|
||||
|
||||
/**
|
||||
* @brief ST77922 LCD device object class
|
||||
*
|
||||
* @note This class is a derived class of `ESP_PanelLcd`, user can use it directly
|
||||
*/
|
||||
class ESP_PanelLcd_ST77922: public ESP_PanelLcd {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new LCD device in a simple way, the `init()` function should be called after this function
|
||||
*
|
||||
* @note This function uses some default values to config the LCD device, please use `config*()` functions to
|
||||
* change them
|
||||
* @note Vendor specific initialization can be different between manufacturers, should consult the LCD supplier
|
||||
* for initialization sequence code, and use `configVendorCommands()` to configure
|
||||
*
|
||||
* @param bus Pointer of panel bus
|
||||
* @param color_bits Bits per pixel (16/18/24)
|
||||
* @param rst_io Reset pin, set to -1 if no use
|
||||
*/
|
||||
ESP_PanelLcd_ST77922(ESP_PanelBus *bus, uint8_t color_bits, int rst_io = -1);
|
||||
|
||||
/**
|
||||
* @brief Construct a new LCD in a complex way, the `init()` function should be called after this function
|
||||
*
|
||||
* @param bus Pointer of panel bus
|
||||
* @param panel_config LCD device configuration
|
||||
*/
|
||||
ESP_PanelLcd_ST77922(ESP_PanelBus *bus, const esp_lcd_panel_dev_config_t &panel_config);
|
||||
|
||||
/**
|
||||
* @brief Destroy the LCD device
|
||||
*
|
||||
*/
|
||||
~ESP_PanelLcd_ST77922() override;
|
||||
|
||||
/**
|
||||
* @brief Initialize the LCD device, the `begin()` function should be called after this function
|
||||
*
|
||||
* @note This function typically calls `esp_lcd_new_panel_*()` to create the LCD panel handle
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool init(void) override;
|
||||
};
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "ST7796.h"
|
||||
|
||||
static const char *TAG = "ST7796_CPP";
|
||||
|
||||
ESP_PanelLcd_ST7796::ESP_PanelLcd_ST7796(ESP_PanelBus *bus, uint8_t color_bits, int rst_io):
|
||||
ESP_PanelLcd(bus, color_bits, rst_io)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelLcd_ST7796::ESP_PanelLcd_ST7796(ESP_PanelBus *bus, const esp_lcd_panel_dev_config_t &panel_config):
|
||||
ESP_PanelLcd(bus, panel_config)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelLcd_ST7796::~ESP_PanelLcd_ST7796()
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
if (handle == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!del()) {
|
||||
ESP_LOGE(TAG, "Delete device failed");
|
||||
}
|
||||
|
||||
end:
|
||||
ESP_LOGD(TAG, "Destroyed");
|
||||
}
|
||||
|
||||
bool ESP_PanelLcd_ST7796::init(void)
|
||||
{
|
||||
ESP_PANEL_CHECK_NULL_RET(bus, false, "Invalid bus");
|
||||
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_new_panel_st7796(bus->getHandle(), &panel_config, &handle), false, "Create panel failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ESP_PanelLcd.h"
|
||||
#include "base/esp_lcd_st7796.h"
|
||||
#include "base/esp_lcd_custom_types.h"
|
||||
|
||||
/**
|
||||
* @brief ST7796 LCD device object class
|
||||
*
|
||||
* @note This class is a derived class of `ESP_PanelLcd`, user can use it directly
|
||||
*/
|
||||
class ESP_PanelLcd_ST7796: public ESP_PanelLcd {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new LCD device in a simple way, the `init()` function should be called after this function
|
||||
*
|
||||
* @note This function uses some default values to config the LCD device, please use `config*()` functions to
|
||||
* change them
|
||||
* @note Vendor specific initialization can be different between manufacturers, should consult the LCD supplier
|
||||
* for initialization sequence code, and use `configVendorCommands()` to configure
|
||||
*
|
||||
* @param bus Pointer of panel bus
|
||||
* @param color_bits Bits per pixel (16/18/24)
|
||||
* @param rst_io Reset pin, set to -1 if no use
|
||||
*/
|
||||
ESP_PanelLcd_ST7796(ESP_PanelBus *bus, uint8_t color_bits, int rst_io = -1);
|
||||
|
||||
/**
|
||||
* @brief Construct a new LCD in a complex way, the `init()` function should be called after this function
|
||||
*
|
||||
* @param bus Pointer of panel bus
|
||||
* @param panel_config LCD device configuration
|
||||
*/
|
||||
ESP_PanelLcd_ST7796(ESP_PanelBus *bus, const esp_lcd_panel_dev_config_t &panel_config);
|
||||
|
||||
/**
|
||||
* @brief Destroy the LCD device
|
||||
*
|
||||
*/
|
||||
~ESP_PanelLcd_ST7796() override;
|
||||
|
||||
/**
|
||||
* @brief Initialize the LCD device, the `begin()` function should be called after this function
|
||||
*
|
||||
* @note This function typically calls `esp_lcd_new_panel_*()` to create the LCD panel handle
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool init(void) override;
|
||||
};
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "esp_lcd_panel_rgb.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief LCD panel initialization commands.
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
int cmd; /*<! The specific LCD command */
|
||||
const void *data; /*<! Buffer that holds the command specific data */
|
||||
size_t data_bytes; /*<! Size of `data` in memory, in bytes */
|
||||
unsigned int delay_ms; /*<! Delay in milliseconds after this command */
|
||||
} esp_lcd_panel_vendor_init_cmd_t;
|
||||
|
||||
/**
|
||||
* @brief LCD panel vendor configuration.
|
||||
*
|
||||
* @note This structure needs to be passed to the `vendor_config` field in `esp_lcd_panel_dev_config_t`.
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
const esp_lcd_panel_vendor_init_cmd_t *init_cmds; /*!< Pointer to initialization commands array. Set to NULL if using default commands.
|
||||
* The array should be declared as `static const` and positioned outside the function.
|
||||
* Please refer to `vendor_specific_init_default` in source file.
|
||||
*/
|
||||
unsigned int init_cmds_size; /*<! Number of commands in above array */
|
||||
|
||||
#if SOC_LCD_RGB_SUPPORTED
|
||||
const esp_lcd_rgb_panel_config_t *rgb_config; /*!< RGB panel configuration. */
|
||||
#endif
|
||||
|
||||
struct {
|
||||
unsigned int mirror_by_cmd: 1; /*<! The `mirror()` function will be implemented by LCD command if set to 1.
|
||||
* Otherwise, the function will be implemented by software.
|
||||
*/
|
||||
unsigned int auto_del_panel_io: 1; /*<! Delete the panel IO instance automatically if set to 1. All `*_by_cmd` flags will be invalid.
|
||||
* If the panel IO pins are sharing other pins of the RGB interface to save GPIOs,
|
||||
* Please set it to 1 to release the panel IO and its pins (except CS signal).
|
||||
*/
|
||||
/* Only available for QSPI interface */
|
||||
unsigned int use_qspi_interface: 1; /*<! Set to 1 if use QSPI interface, default is SPI interface */
|
||||
} flags;
|
||||
} esp_lcd_panel_vendor_config_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
+397
@@ -0,0 +1,397 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if SOC_LCD_RGB_SUPPORTED
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_lcd_panel_commands.h"
|
||||
#include "esp_lcd_panel_interface.h"
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "esp_lcd_panel_rgb.h"
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "esp_lcd_custom_types.h"
|
||||
#include "esp_lcd_gc9503.h"
|
||||
|
||||
#define GC9503_CMD_MADCTL (0xB1) // Memory data access control
|
||||
#define GC9503_CMD_MADCTL_DEFAULT (0x10) // Default value of Memory data access control
|
||||
#define GC9503_CMD_SS_BIT (1 << 0) // Source driver scan direction, 0: top to bottom, 1: bottom to top
|
||||
#define GC9503_CMD_GS_BIT (1 << 1) // Gate driver scan direction, 0: left to right, 1: right to left
|
||||
#define GC9503_CMD_BGR_BIT (1 << 5) // RGB/BGR order, 0: RGB, 1: BGR
|
||||
|
||||
typedef struct {
|
||||
esp_lcd_panel_io_handle_t io;
|
||||
int reset_gpio_num;
|
||||
uint8_t madctl_val; // Save current value of GC9503_CMD_MADCTL register
|
||||
uint8_t colmod_val; // Save current value of LCD_CMD_COLMOD register
|
||||
const esp_lcd_panel_vendor_init_cmd_t *init_cmds;
|
||||
uint16_t init_cmds_size;
|
||||
struct {
|
||||
unsigned int mirror_by_cmd: 1;
|
||||
unsigned int auto_del_panel_io: 1;
|
||||
unsigned int display_on_off_use_cmd: 1;
|
||||
unsigned int reset_level: 1;
|
||||
} flags;
|
||||
// To save the original functions of RGB panel
|
||||
esp_err_t (*init)(esp_lcd_panel_t *panel);
|
||||
esp_err_t (*del)(esp_lcd_panel_t *panel);
|
||||
esp_err_t (*reset)(esp_lcd_panel_t *panel);
|
||||
esp_err_t (*mirror)(esp_lcd_panel_t *panel, bool x_axis, bool y_axis);
|
||||
esp_err_t (*disp_on_off)(esp_lcd_panel_t *panel, bool on_off);
|
||||
} gc9503_panel_t;
|
||||
|
||||
static const char *TAG = "gc9503";
|
||||
|
||||
static esp_err_t panel_gc9503_send_init_cmds(gc9503_panel_t *gc9503);
|
||||
|
||||
static esp_err_t panel_gc9503_init(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_gc9503_del(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_gc9503_reset(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_gc9503_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y);
|
||||
static esp_err_t panel_gc9503_disp_on_off(esp_lcd_panel_t *panel, bool off);
|
||||
|
||||
esp_err_t esp_lcd_new_panel_gc9503(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config,
|
||||
esp_lcd_panel_handle_t *ret_panel)
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
ESP_RETURN_ON_FALSE(io && panel_dev_config && ret_panel, ESP_ERR_INVALID_ARG, TAG, "invalid arguments");
|
||||
esp_lcd_panel_vendor_config_t *vendor_config = (esp_lcd_panel_vendor_config_t *)panel_dev_config->vendor_config;
|
||||
ESP_RETURN_ON_FALSE(vendor_config && vendor_config->rgb_config, ESP_ERR_INVALID_ARG, TAG, "`verndor_config` and `rgb_config` are necessary");
|
||||
ESP_RETURN_ON_FALSE(!vendor_config->flags.auto_del_panel_io || !vendor_config->flags.mirror_by_cmd,
|
||||
ESP_ERR_INVALID_ARG, TAG, "`mirror_by_cmd` and `auto_del_panel_io` cannot work together");
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
gpio_config_t io_conf = { 0 };
|
||||
|
||||
gc9503_panel_t *gc9503 = (gc9503_panel_t *)calloc(1, sizeof(gc9503_panel_t));
|
||||
ESP_RETURN_ON_FALSE(gc9503, ESP_ERR_NO_MEM, TAG, "no mem for gc9503 panel");
|
||||
|
||||
if (panel_dev_config->reset_gpio_num >= 0) {
|
||||
io_conf.mode = GPIO_MODE_OUTPUT;
|
||||
io_conf.pin_bit_mask = 1ULL << panel_dev_config->reset_gpio_num;
|
||||
ESP_GOTO_ON_ERROR(gpio_config(&io_conf), err, TAG, "configure GPIO for RST line failed");
|
||||
}
|
||||
|
||||
gc9503->madctl_val = GC9503_CMD_MADCTL_DEFAULT;
|
||||
switch (panel_dev_config->rgb_ele_order) {
|
||||
case LCD_RGB_ELEMENT_ORDER_RGB:
|
||||
gc9503->madctl_val &= ~GC9503_CMD_BGR_BIT;
|
||||
break;
|
||||
case LCD_RGB_ELEMENT_ORDER_BGR:
|
||||
gc9503->madctl_val |= GC9503_CMD_BGR_BIT;
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported color element order");
|
||||
break;
|
||||
}
|
||||
|
||||
gc9503->colmod_val = 0;
|
||||
switch (panel_dev_config->bits_per_pixel) {
|
||||
case 16: // RGB565
|
||||
gc9503->colmod_val = 0x50;
|
||||
break;
|
||||
case 18: // RGB666
|
||||
gc9503->colmod_val = 0x60;
|
||||
break;
|
||||
case 24: // RGB888
|
||||
gc9503->colmod_val = 0x70;
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported pixel width");
|
||||
break;
|
||||
}
|
||||
|
||||
gc9503->io = io;
|
||||
gc9503->init_cmds = vendor_config->init_cmds;
|
||||
gc9503->init_cmds_size = vendor_config->init_cmds_size;
|
||||
gc9503->reset_gpio_num = panel_dev_config->reset_gpio_num;
|
||||
gc9503->flags.reset_level = panel_dev_config->flags.reset_active_high;
|
||||
gc9503->flags.auto_del_panel_io = vendor_config->flags.auto_del_panel_io;
|
||||
gc9503->flags.mirror_by_cmd = vendor_config->flags.mirror_by_cmd;
|
||||
gc9503->flags.display_on_off_use_cmd = (vendor_config->rgb_config->disp_gpio_num >= 0) ? 0 : 1;
|
||||
|
||||
if (gc9503->flags.auto_del_panel_io) {
|
||||
if (gc9503->reset_gpio_num >= 0) { // Perform hardware reset
|
||||
gpio_set_level(gc9503->reset_gpio_num, gc9503->flags.reset_level);
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
gpio_set_level(gc9503->reset_gpio_num, !gc9503->flags.reset_level);
|
||||
} else { // Perform software reset
|
||||
ESP_GOTO_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_SWRESET, NULL, 0), err, TAG, "send command failed");
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(120));
|
||||
|
||||
/**
|
||||
* In order to enable the 3-wire SPI interface pins (such as SDA and SCK) to share other pins of the RGB interface
|
||||
* (such as HSYNC) and save GPIOs, we need to send LCD initialization commands via the 3-wire SPI interface before
|
||||
* `esp_lcd_new_rgb_panel()` is called.
|
||||
*/
|
||||
ESP_GOTO_ON_ERROR(panel_gc9503_send_init_cmds(gc9503), err, TAG, "send init commands failed");
|
||||
// After sending the initialization commands, the 3-wire SPI interface can be deleted
|
||||
ESP_GOTO_ON_ERROR(esp_lcd_panel_io_del(io), err, TAG, "delete panel IO failed");
|
||||
gc9503->io = NULL;
|
||||
ESP_LOGD(TAG, "delete panel IO");
|
||||
}
|
||||
|
||||
// Create RGB panel
|
||||
ESP_GOTO_ON_ERROR(esp_lcd_new_rgb_panel(vendor_config->rgb_config, ret_panel), err, TAG, "create RGB panel failed");
|
||||
ESP_LOGD(TAG, "new RGB panel @%p", ret_panel);
|
||||
|
||||
// Save the original functions of RGB panel
|
||||
gc9503->init = (*ret_panel)->init;
|
||||
gc9503->del = (*ret_panel)->del;
|
||||
gc9503->reset = (*ret_panel)->reset;
|
||||
gc9503->mirror = (*ret_panel)->mirror;
|
||||
gc9503->disp_on_off = (*ret_panel)->disp_on_off;
|
||||
// Overwrite the functions of RGB panel
|
||||
(*ret_panel)->init = panel_gc9503_init;
|
||||
(*ret_panel)->del = panel_gc9503_del;
|
||||
(*ret_panel)->reset = panel_gc9503_reset;
|
||||
(*ret_panel)->mirror = panel_gc9503_mirror;
|
||||
(*ret_panel)->disp_on_off = panel_gc9503_disp_on_off;
|
||||
(*ret_panel)->user_data = gc9503;
|
||||
ESP_LOGD(TAG, "new gc9503 panel @%p", gc9503);
|
||||
|
||||
ESP_LOGI(TAG, "LCD panel create success, version: %d.%d.%d", ESP_LCD_GC9503_VER_MAJOR, ESP_LCD_GC9503_VER_MINOR,
|
||||
ESP_LCD_GC9503_VER_PATCH);
|
||||
return ESP_OK;
|
||||
|
||||
err:
|
||||
if (gc9503) {
|
||||
if (panel_dev_config->reset_gpio_num >= 0) {
|
||||
gpio_reset_pin(panel_dev_config->reset_gpio_num);
|
||||
}
|
||||
free(gc9503);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// *INDENT-OFF*
|
||||
static const esp_lcd_panel_vendor_init_cmd_t vendor_specific_init_default[] = {
|
||||
// {cmd, { data }, data_size, delay_ms}
|
||||
{0xf0, (uint8_t []){0x55, 0xaa, 0x52, 0x08, 0x00}, 5, 0},
|
||||
{0xf6, (uint8_t []){0x5a, 0x87}, 2, 0},
|
||||
{0xc1, (uint8_t []){0x3f}, 1, 0},
|
||||
{0xc2, (uint8_t []){0x0e}, 1, 0},
|
||||
{0xc6, (uint8_t []){0xf8}, 1, 0},
|
||||
{0xc9, (uint8_t []){0x10}, 1, 0},
|
||||
{0xcd, (uint8_t []){0x25}, 1, 0},
|
||||
{0xf8, (uint8_t []){0x8a}, 1, 0},
|
||||
{0xac, (uint8_t []){0x45}, 1, 0},
|
||||
{0xa0, (uint8_t []){0xdd}, 1, 0},
|
||||
{0xa7, (uint8_t []){0x47}, 1, 0},
|
||||
{0xfa, (uint8_t []){0x00, 0x00, 0x00, 0x04}, 4, 0},
|
||||
{0x86, (uint8_t []){0x99, 0xa3, 0xa3, 0x51}, 4, 0},
|
||||
{0xa3, (uint8_t []){0xee}, 1, 0},
|
||||
{0xfd, (uint8_t []){0x3c, 0x3c, 0x00}, 3, 0},
|
||||
{0x71, (uint8_t []){0x48}, 1, 0},
|
||||
{0x72, (uint8_t []){0x48}, 1, 0},
|
||||
{0x73, (uint8_t []){0x00, 0x44}, 2, 0},
|
||||
{0x97, (uint8_t []){0xee}, 1, 0},
|
||||
{0x83, (uint8_t []){0x93}, 1, 0},
|
||||
{0x9a, (uint8_t []){0x72}, 1, 0},
|
||||
{0x9b, (uint8_t []){0x5a}, 1, 0},
|
||||
{0x82, (uint8_t []){0x2c, 0x2c}, 2, 0},
|
||||
{0x6d, (uint8_t []){0x00, 0x1f, 0x19, 0x1a, 0x10, 0x0e, 0x0c, 0x0a, 0x02, 0x07, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
|
||||
0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x08, 0x01, 0x09, 0x0b, 0x0d, 0x0f, 0x1a, 0x19, 0x1f, 0x00}, 32, 0},
|
||||
{0x64, (uint8_t []){0x38, 0x05, 0x01, 0xdb, 0x03, 0x03, 0x38, 0x04, 0x01, 0xdc, 0x03, 0x03, 0x7a, 0x7a, 0x7a, 0x7a}, 16, 0},
|
||||
{0x65, (uint8_t []){0x38, 0x03, 0x01, 0xdd, 0x03, 0x03, 0x38, 0x02, 0x01, 0xde, 0x03, 0x03, 0x7a, 0x7a, 0x7a, 0x7a}, 16, 0},
|
||||
{0x66, (uint8_t []){0x38, 0x01, 0x01, 0xdf, 0x03, 0x03, 0x38, 0x00, 0x01, 0xe0, 0x03, 0x03, 0x7a, 0x7a, 0x7a, 0x7a}, 16, 0},
|
||||
{0x67, (uint8_t []){0x30, 0x01, 0x01, 0xe1, 0x03, 0x03, 0x30, 0x02, 0x01, 0xe2, 0x03, 0x03, 0x7a, 0x7a, 0x7a, 0x7a}, 16, 0},
|
||||
{0x68, (uint8_t []){0x00, 0x08, 0x15, 0x08, 0x15, 0x7a, 0x7a, 0x08, 0x15, 0x08, 0x15, 0x7a, 0x7a}, 13, 0},
|
||||
{0x60, (uint8_t []){0x38, 0x08, 0x7a, 0x7a, 0x38, 0x09, 0x7a, 0x7a}, 8, 0},
|
||||
{0x63, (uint8_t []){0x31, 0xe4, 0x7a, 0x7a, 0x31, 0xe5, 0x7a, 0x7a}, 8, 0},
|
||||
{0x69, (uint8_t []){0x04, 0x22, 0x14, 0x22, 0x14, 0x22, 0x08}, 7, 0},
|
||||
{0x6b, (uint8_t []){0x07}, 1, 0},
|
||||
{0x7a, (uint8_t []){0x08, 0x13}, 2, 0},
|
||||
{0x7b, (uint8_t []){0x08, 0x13}, 2, 0},
|
||||
{0xd1, (uint8_t []){0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00,
|
||||
0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee,
|
||||
0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03,
|
||||
0xff}, 52, 0},
|
||||
{0xd2, (uint8_t []){0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00,
|
||||
0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee,
|
||||
0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03,
|
||||
0xff}, 52, 0},
|
||||
{0xd3, (uint8_t []){0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00,
|
||||
0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee,
|
||||
0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03,
|
||||
0xff}, 52, 0},
|
||||
{0xd4, (uint8_t []){0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00,
|
||||
0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee,
|
||||
0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03,
|
||||
0xff}, 52, 0},
|
||||
{0xd5, (uint8_t []){0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00,
|
||||
0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee,
|
||||
0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03,
|
||||
0xff}, 52, 0},
|
||||
{0xd6, (uint8_t []){0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00,
|
||||
0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee,
|
||||
0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03,
|
||||
0xff}, 52, 0},
|
||||
{0x11, (uint8_t []){0x00}, 0, 120},
|
||||
{0x29, (uint8_t []){0x00}, 0, 20},
|
||||
};
|
||||
// *INDENT-OFF*
|
||||
|
||||
static esp_err_t panel_gc9503_send_init_cmds(gc9503_panel_t *gc9503)
|
||||
{
|
||||
esp_lcd_panel_io_handle_t io = gc9503->io;
|
||||
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, GC9503_CMD_MADCTL, (uint8_t[]) {
|
||||
gc9503->madctl_val,
|
||||
}, 1), TAG, "send command failed");;
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_COLMOD, (uint8_t[]) {
|
||||
gc9503->colmod_val,
|
||||
}, 1), TAG, "send command failed");;
|
||||
|
||||
// Vendor specific initialization, it can be different between manufacturers
|
||||
// should consult the LCD supplier for initialization sequence code
|
||||
const esp_lcd_panel_vendor_init_cmd_t *init_cmds = NULL;
|
||||
uint16_t init_cmds_size = 0;
|
||||
if (gc9503->init_cmds) {
|
||||
init_cmds = gc9503->init_cmds;
|
||||
init_cmds_size = gc9503->init_cmds_size;
|
||||
} else {
|
||||
init_cmds = vendor_specific_init_default;
|
||||
init_cmds_size = sizeof(vendor_specific_init_default) / sizeof(esp_lcd_panel_vendor_init_cmd_t);
|
||||
}
|
||||
|
||||
bool is_cmd_overwritten = false;
|
||||
for (int i = 0; i < init_cmds_size; i++) {
|
||||
// Check if the command has been used or conflicts with the internal
|
||||
switch (init_cmds[i].cmd) {
|
||||
case LCD_CMD_MADCTL:
|
||||
is_cmd_overwritten = true;
|
||||
gc9503->madctl_val = ((uint8_t *)init_cmds[i].data)[0];
|
||||
break;
|
||||
case LCD_CMD_COLMOD:
|
||||
is_cmd_overwritten = true;
|
||||
gc9503->colmod_val = ((uint8_t *)init_cmds[i].data)[0];
|
||||
break;
|
||||
default:
|
||||
is_cmd_overwritten = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_cmd_overwritten) {
|
||||
ESP_LOGW(TAG, "The %02Xh command has been used and will be overwritten by external initialization sequence",
|
||||
init_cmds[i].cmd);
|
||||
}
|
||||
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, init_cmds[i].cmd, init_cmds[i].data, init_cmds[i].data_bytes),
|
||||
TAG, "send command failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(init_cmds[i].delay_ms));
|
||||
}
|
||||
ESP_LOGD(TAG, "send init commands success");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_gc9503_init(esp_lcd_panel_t *panel)
|
||||
{
|
||||
gc9503_panel_t *gc9503 = (gc9503_panel_t *)panel->user_data;
|
||||
|
||||
if (!gc9503->flags.auto_del_panel_io) {
|
||||
ESP_RETURN_ON_ERROR(panel_gc9503_send_init_cmds(gc9503), TAG, "send init commands failed");
|
||||
}
|
||||
// Init RGB panel
|
||||
ESP_RETURN_ON_ERROR(gc9503->init(panel), TAG, "init RGB panel failed");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_gc9503_del(esp_lcd_panel_t *panel)
|
||||
{
|
||||
gc9503_panel_t *gc9503 = (gc9503_panel_t *)panel->user_data;
|
||||
|
||||
if (gc9503->reset_gpio_num >= 0) {
|
||||
gpio_reset_pin(gc9503->reset_gpio_num);
|
||||
}
|
||||
// Delete RGB panel
|
||||
gc9503->del(panel);
|
||||
free(gc9503);
|
||||
ESP_LOGD(TAG, "del gc9503 panel @%p", gc9503);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_gc9503_reset(esp_lcd_panel_t *panel)
|
||||
{
|
||||
gc9503_panel_t *gc9503 = (gc9503_panel_t *)panel->user_data;
|
||||
esp_lcd_panel_io_handle_t io = gc9503->io;
|
||||
|
||||
// Perform hardware reset
|
||||
if (gc9503->reset_gpio_num >= 0) {
|
||||
gpio_set_level(gc9503->reset_gpio_num, gc9503->flags.reset_level);
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
gpio_set_level(gc9503->reset_gpio_num, !gc9503->flags.reset_level);
|
||||
vTaskDelay(pdMS_TO_TICKS(120));
|
||||
} else if (io) { // Perform software reset
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_SWRESET, NULL, 0), TAG, "send command failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(120));
|
||||
}
|
||||
// Reset RGB panel
|
||||
ESP_RETURN_ON_ERROR(gc9503->reset(panel), TAG, "reset RGB panel failed");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_gc9503_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y)
|
||||
{
|
||||
gc9503_panel_t *gc9503 = (gc9503_panel_t *)panel->user_data;
|
||||
esp_lcd_panel_io_handle_t io = gc9503->io;
|
||||
|
||||
if (gc9503->flags.mirror_by_cmd) {
|
||||
ESP_RETURN_ON_FALSE(io, ESP_FAIL, TAG, "Panel IO is deleted, cannot send command");
|
||||
// Control mirror through LCD command
|
||||
if (mirror_x) {
|
||||
gc9503->madctl_val |= GC9503_CMD_GS_BIT;
|
||||
} else {
|
||||
gc9503->madctl_val &= ~GC9503_CMD_GS_BIT;
|
||||
}
|
||||
if (mirror_y) {
|
||||
gc9503->madctl_val |= GC9503_CMD_SS_BIT;
|
||||
} else {
|
||||
gc9503->madctl_val &= ~GC9503_CMD_SS_BIT;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, GC9503_CMD_MADCTL, (uint8_t[]) {
|
||||
gc9503->madctl_val,
|
||||
}, 1), TAG, "send command failed");;
|
||||
} else {
|
||||
// Control mirror through RGB panel
|
||||
ESP_RETURN_ON_ERROR(gc9503->mirror(panel, mirror_x, mirror_y), TAG, "RGB panel mirror failed");
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_gc9503_disp_on_off(esp_lcd_panel_t *panel, bool on_off)
|
||||
{
|
||||
gc9503_panel_t *gc9503 = (gc9503_panel_t *)panel->user_data;
|
||||
esp_lcd_panel_io_handle_t io = gc9503->io;
|
||||
int command = 0;
|
||||
|
||||
if (gc9503->flags.display_on_off_use_cmd) {
|
||||
ESP_RETURN_ON_FALSE(io, ESP_FAIL, TAG, "Panel IO is deleted, cannot send command");
|
||||
// Control display on/off through LCD command
|
||||
if (on_off) {
|
||||
command = LCD_CMD_DISPON;
|
||||
} else {
|
||||
command = LCD_CMD_DISPOFF;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, command, NULL, 0), TAG, "send command failed");
|
||||
} else {
|
||||
// Control display on/off through display control signal
|
||||
ESP_RETURN_ON_ERROR(gc9503->disp_on_off(panel, on_off), TAG, "RGB panel disp_on_off failed");
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* SOC_LCD_RGB_SUPPORTED */
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
* @brief ESP LCD: GC9503
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if SOC_LCD_RGB_SUPPORTED
|
||||
#include <stdint.h>
|
||||
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
#include "esp_lcd_panel_rgb.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_LCD_GC9503_VER_MAJOR (3)
|
||||
#define ESP_LCD_GC9503_VER_MINOR (0)
|
||||
#define ESP_LCD_GC9503_VER_PATCH (1)
|
||||
|
||||
/**
|
||||
* @brief Create LCD panel for model GC9503
|
||||
*
|
||||
* @note When `auto_del_panel_io` is set to 1, this function will first initialize the GC9503 with vendor specific initialization and then calls `esp_lcd_new_rgb_panel()` to create an RGB LCD panel. And the `esp_lcd_panel_init()` function will only initialize RGB.
|
||||
* @note When `auto_del_panel_io` is set to 0, this function will only call `esp_lcd_new_rgb_panel()` to create an RGB LCD panel. And the `esp_lcd_panel_init()` function will initialize both the GC9503 and RGB.
|
||||
* @note Vendor specific initialization can be different between manufacturers, should consult the LCD supplier for initialization sequence code.
|
||||
*
|
||||
* @param[in] io LCD panel IO handle
|
||||
* @param[in] panel_dev_config General panel device configuration (`vendor_config` and `rgb_config` are necessary)
|
||||
* @param[out] ret_panel Returned LCD panel handle
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG if parameter is invalid
|
||||
* - ESP_OK on success
|
||||
* - Otherwise on fail
|
||||
*/
|
||||
esp_err_t esp_lcd_new_panel_gc9503(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config,
|
||||
esp_lcd_panel_handle_t *ret_panel);
|
||||
|
||||
/**
|
||||
* @brief 3-wire SPI panel IO configuration structure
|
||||
*
|
||||
* @param[in] line_cfg SPI line configuration
|
||||
* @param[in] scl_active_edge SCL signal active edge, 0: rising edge, 1: falling edge
|
||||
*
|
||||
*/
|
||||
#define GC9503_PANEL_IO_3WIRE_SPI_CONFIG(line_cfg, scl_active_edge) \
|
||||
{ \
|
||||
.line_config = line_cfg, \
|
||||
.expect_clk_speed = PANEL_IO_3WIRE_SPI_CLK_MAX, \
|
||||
.spi_mode = scl_active_edge ? 1 : 0, \
|
||||
.lcd_cmd_bytes = 1, \
|
||||
.lcd_param_bytes = 1, \
|
||||
.flags = { \
|
||||
.use_dc_bit = 1, \
|
||||
.dc_zero_on_data = 0, \
|
||||
.lsb_first = 0, \
|
||||
.cs_high_active = 0, \
|
||||
.del_keep_cs_inactive = 1, \
|
||||
}, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief RGB timing structure
|
||||
*
|
||||
* @note refresh_rate = (pclk_hz * data_width) / (h_res + hsync_pulse_width + hsync_back_porch + hsync_front_porch)
|
||||
* / (v_res + vsync_pulse_width + vsync_back_porch + vsync_front_porch)
|
||||
* / bits_per_pixel
|
||||
*
|
||||
*/
|
||||
#define GC9503_480_480_PANEL_60HZ_RGB_TIMING() \
|
||||
{ \
|
||||
.pclk_hz = 16 * 1000 * 1000, \
|
||||
.h_res = 480, \
|
||||
.v_res = 480, \
|
||||
.hsync_pulse_width = 10, \
|
||||
.hsync_back_porch = 10, \
|
||||
.hsync_front_porch = 20, \
|
||||
.vsync_pulse_width = 10, \
|
||||
.vsync_back_porch = 10, \
|
||||
.vsync_front_porch = 10, \
|
||||
.flags.pclk_active_neg = 0, \
|
||||
}
|
||||
#endif /* SOC_LCD_RGB_SUPPORTED */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
+386
@@ -0,0 +1,386 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "esp_lcd_custom_types.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_lcd_panel_interface.h"
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
#include "esp_lcd_panel_ops.h"
|
||||
#include "esp_lcd_panel_commands.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
|
||||
#include "esp_lcd_gc9a01.h"
|
||||
|
||||
static const char *TAG = "gc9a01";
|
||||
|
||||
static esp_err_t panel_gc9a01_del(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_gc9a01_reset(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_gc9a01_init(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_gc9a01_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data);
|
||||
static esp_err_t panel_gc9a01_invert_color(esp_lcd_panel_t *panel, bool invert_color_data);
|
||||
static esp_err_t panel_gc9a01_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y);
|
||||
static esp_err_t panel_gc9a01_swap_xy(esp_lcd_panel_t *panel, bool swap_axes);
|
||||
static esp_err_t panel_gc9a01_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap);
|
||||
static esp_err_t panel_gc9a01_disp_on_off(esp_lcd_panel_t *panel, bool off);
|
||||
|
||||
typedef struct {
|
||||
esp_lcd_panel_t base;
|
||||
esp_lcd_panel_io_handle_t io;
|
||||
int reset_gpio_num;
|
||||
bool reset_level;
|
||||
int x_gap;
|
||||
int y_gap;
|
||||
uint8_t fb_bits_per_pixel;
|
||||
uint8_t madctl_val; // save current value of LCD_CMD_MADCTL register
|
||||
uint8_t colmod_val; // save current value of LCD_CMD_COLMOD register
|
||||
const esp_lcd_panel_vendor_init_cmd_t *init_cmds;
|
||||
uint16_t init_cmds_size;
|
||||
} gc9a01_panel_t;
|
||||
|
||||
esp_err_t esp_lcd_new_panel_gc9a01(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
gc9a01_panel_t *gc9a01 = NULL;
|
||||
gpio_config_t io_conf = { 0 };
|
||||
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
ESP_GOTO_ON_FALSE(io && panel_dev_config && ret_panel, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
||||
gc9a01 = (gc9a01_panel_t *)calloc(1, sizeof(gc9a01_panel_t));
|
||||
ESP_GOTO_ON_FALSE(gc9a01, ESP_ERR_NO_MEM, err, TAG, "no mem for gc9a01 panel");
|
||||
|
||||
if (panel_dev_config->reset_gpio_num >= 0) {
|
||||
io_conf.mode = GPIO_MODE_OUTPUT;
|
||||
io_conf.pin_bit_mask = 1ULL << panel_dev_config->reset_gpio_num;
|
||||
ESP_GOTO_ON_ERROR(gpio_config(&io_conf), err, TAG, "configure GPIO for RST line failed");
|
||||
}
|
||||
|
||||
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
switch (panel_dev_config->color_space) {
|
||||
case ESP_LCD_COLOR_SPACE_RGB:
|
||||
gc9a01->madctl_val = 0;
|
||||
break;
|
||||
case ESP_LCD_COLOR_SPACE_BGR:
|
||||
gc9a01->madctl_val |= LCD_CMD_BGR_BIT;
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported color space");
|
||||
break;
|
||||
}
|
||||
#else
|
||||
switch (panel_dev_config->rgb_endian) {
|
||||
case LCD_RGB_ENDIAN_RGB:
|
||||
gc9a01->madctl_val = 0;
|
||||
break;
|
||||
case LCD_RGB_ENDIAN_BGR:
|
||||
gc9a01->madctl_val |= LCD_CMD_BGR_BIT;
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported rgb endian");
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (panel_dev_config->bits_per_pixel) {
|
||||
case 16: // RGB565
|
||||
gc9a01->colmod_val = 0x55;
|
||||
gc9a01->fb_bits_per_pixel = 16;
|
||||
break;
|
||||
case 18: // RGB666
|
||||
gc9a01->colmod_val = 0x66;
|
||||
// each color component (R/G/B) should occupy the 6 high bits of a byte, which means 3 full bytes are required for a pixel
|
||||
gc9a01->fb_bits_per_pixel = 24;
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported pixel width");
|
||||
break;
|
||||
}
|
||||
|
||||
gc9a01->io = io;
|
||||
gc9a01->reset_gpio_num = panel_dev_config->reset_gpio_num;
|
||||
gc9a01->reset_level = panel_dev_config->flags.reset_active_high;
|
||||
if (panel_dev_config->vendor_config) {
|
||||
gc9a01->init_cmds = ((esp_lcd_panel_vendor_config_t *)panel_dev_config->vendor_config)->init_cmds;
|
||||
gc9a01->init_cmds_size = ((esp_lcd_panel_vendor_config_t *)panel_dev_config->vendor_config)->init_cmds_size;
|
||||
}
|
||||
gc9a01->base.del = panel_gc9a01_del;
|
||||
gc9a01->base.reset = panel_gc9a01_reset;
|
||||
gc9a01->base.init = panel_gc9a01_init;
|
||||
gc9a01->base.draw_bitmap = panel_gc9a01_draw_bitmap;
|
||||
gc9a01->base.invert_color = panel_gc9a01_invert_color;
|
||||
gc9a01->base.set_gap = panel_gc9a01_set_gap;
|
||||
gc9a01->base.mirror = panel_gc9a01_mirror;
|
||||
gc9a01->base.swap_xy = panel_gc9a01_swap_xy;
|
||||
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
gc9a01->base.disp_off = panel_gc9a01_disp_on_off;
|
||||
#else
|
||||
gc9a01->base.disp_on_off = panel_gc9a01_disp_on_off;
|
||||
#endif
|
||||
*ret_panel = &(gc9a01->base);
|
||||
ESP_LOGD(TAG, "new gc9a01 panel @%p", gc9a01);
|
||||
|
||||
ESP_LOGI(TAG, "LCD panel create success, version: %d.%d.%d", ESP_LCD_GC9A01_VER_MAJOR, ESP_LCD_GC9A01_VER_MINOR,
|
||||
ESP_LCD_GC9A01_VER_PATCH);
|
||||
|
||||
return ESP_OK;
|
||||
|
||||
err:
|
||||
if (gc9a01) {
|
||||
if (panel_dev_config->reset_gpio_num >= 0) {
|
||||
gpio_reset_pin(panel_dev_config->reset_gpio_num);
|
||||
}
|
||||
free(gc9a01);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t panel_gc9a01_del(esp_lcd_panel_t *panel)
|
||||
{
|
||||
gc9a01_panel_t *gc9a01 = __containerof(panel, gc9a01_panel_t, base);
|
||||
|
||||
if (gc9a01->reset_gpio_num >= 0) {
|
||||
gpio_reset_pin(gc9a01->reset_gpio_num);
|
||||
}
|
||||
ESP_LOGD(TAG, "del gc9a01 panel @%p", gc9a01);
|
||||
free(gc9a01);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_gc9a01_reset(esp_lcd_panel_t *panel)
|
||||
{
|
||||
gc9a01_panel_t *gc9a01 = __containerof(panel, gc9a01_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = gc9a01->io;
|
||||
|
||||
// perform hardware reset
|
||||
if (gc9a01->reset_gpio_num >= 0) {
|
||||
gpio_set_level(gc9a01->reset_gpio_num, gc9a01->reset_level);
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
gpio_set_level(gc9a01->reset_gpio_num, !gc9a01->reset_level);
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
} else { // perform software reset
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_SWRESET, NULL, 0), TAG, "send command failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(20)); // spec, wait at least 5ms before sending new command
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static const esp_lcd_panel_vendor_init_cmd_t vendor_specific_init_default[] = {
|
||||
// {cmd, { data }, data_size, delay_ms}
|
||||
// Enable Inter Register
|
||||
{0xfe, (uint8_t []){0x00}, 0, 0},
|
||||
{0xef, (uint8_t []){0x00}, 0, 0},
|
||||
{0xeb, (uint8_t []){0x14}, 1, 0},
|
||||
{0x84, (uint8_t []){0x60}, 1, 0},
|
||||
{0x85, (uint8_t []){0xff}, 1, 0},
|
||||
{0x86, (uint8_t []){0xff}, 1, 0},
|
||||
{0x87, (uint8_t []){0xff}, 1, 0},
|
||||
{0x8e, (uint8_t []){0xff}, 1, 0},
|
||||
{0x8f, (uint8_t []){0xff}, 1, 0},
|
||||
{0x88, (uint8_t []){0x0a}, 1, 0},
|
||||
{0x89, (uint8_t []){0x23}, 1, 0},
|
||||
{0x8a, (uint8_t []){0x00}, 1, 0},
|
||||
{0x8b, (uint8_t []){0x80}, 1, 0},
|
||||
{0x8c, (uint8_t []){0x01}, 1, 0},
|
||||
{0x8d, (uint8_t []){0x03}, 1, 0},
|
||||
{0x90, (uint8_t []){0x08, 0x08, 0x08, 0x08}, 4, 0},
|
||||
{0xff, (uint8_t []){0x60, 0x01, 0x04}, 3, 0},
|
||||
{0xC3, (uint8_t []){0x13}, 1, 0},
|
||||
{0xC4, (uint8_t []){0x13}, 1, 0},
|
||||
{0xC9, (uint8_t []){0x30}, 1, 0},
|
||||
{0xbe, (uint8_t []){0x11}, 1, 0},
|
||||
{0xe1, (uint8_t []){0x10, 0x0e}, 2, 0},
|
||||
{0xdf, (uint8_t []){0x21, 0x0c, 0x02}, 3, 0},
|
||||
// Set gamma
|
||||
{0xF0, (uint8_t []){0x45, 0x09, 0x08, 0x08, 0x26, 0x2a}, 6, 0},
|
||||
{0xF1, (uint8_t []){0x43, 0x70, 0x72, 0x36, 0x37, 0x6f}, 6, 0},
|
||||
{0xF2, (uint8_t []){0x45, 0x09, 0x08, 0x08, 0x26, 0x2a}, 6, 0},
|
||||
{0xF3, (uint8_t []){0x43, 0x70, 0x72, 0x36, 0x37, 0x6f}, 6, 0},
|
||||
{0xed, (uint8_t []){0x1b, 0x0b}, 2, 0},
|
||||
{0xae, (uint8_t []){0x77}, 1, 0},
|
||||
{0xcd, (uint8_t []){0x63}, 1, 0},
|
||||
{0x70, (uint8_t []){0x07, 0x07, 0x04, 0x0e, 0x0f, 0x09, 0x07, 0x08, 0x03}, 9, 0},
|
||||
{0xE8, (uint8_t []){0x34}, 1, 0}, // 4 dot inversion
|
||||
{0x60, (uint8_t []){0x38, 0x0b, 0x6D, 0x6D, 0x39, 0xf0, 0x6D, 0x6D}, 8, 0},
|
||||
{0x61, (uint8_t []){0x38, 0xf4, 0x6D, 0x6D, 0x38, 0xf7, 0x6D, 0x6D}, 8, 0},
|
||||
{0x62, (uint8_t []){0x38, 0x0D, 0x71, 0xED, 0x70, 0x70, 0x38, 0x0F, 0x71, 0xEF, 0x70, 0x70}, 12, 0},
|
||||
{0x63, (uint8_t []){0x38, 0x11, 0x71, 0xF1, 0x70, 0x70, 0x38, 0x13, 0x71, 0xF3, 0x70, 0x70}, 12, 0},
|
||||
{0x64, (uint8_t []){0x28, 0x29, 0xF1, 0x01, 0xF1, 0x00, 0x07}, 7, 0},
|
||||
{0x66, (uint8_t []){0x3C, 0x00, 0xCD, 0x67, 0x45, 0x45, 0x10, 0x00, 0x00, 0x00}, 10, 0},
|
||||
{0x67, (uint8_t []){0x00, 0x3C, 0x00, 0x00, 0x00, 0x01, 0x54, 0x10, 0x32, 0x98}, 10, 0},
|
||||
{0x74, (uint8_t []){0x10, 0x45, 0x80, 0x00, 0x00, 0x4E, 0x00}, 7, 0},
|
||||
{0x98, (uint8_t []){0x3e, 0x07}, 2, 0},
|
||||
{0x99, (uint8_t []){0x3e, 0x07}, 2, 0},
|
||||
};
|
||||
|
||||
static esp_err_t panel_gc9a01_init(esp_lcd_panel_t *panel)
|
||||
{
|
||||
gc9a01_panel_t *gc9a01 = __containerof(panel, gc9a01_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = gc9a01->io;
|
||||
|
||||
// LCD goes into sleep mode and display will be turned off after power on reset, exit sleep mode first
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_SLPOUT, NULL, 0), TAG, "send command failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]) {
|
||||
gc9a01->madctl_val,
|
||||
}, 1), TAG, "send command failed");
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_COLMOD, (uint8_t[]) {
|
||||
gc9a01->colmod_val,
|
||||
}, 1), TAG, "send command failed");
|
||||
|
||||
const esp_lcd_panel_vendor_init_cmd_t *init_cmds = NULL;
|
||||
uint16_t init_cmds_size = 0;
|
||||
if (gc9a01->init_cmds) {
|
||||
init_cmds = gc9a01->init_cmds;
|
||||
init_cmds_size = gc9a01->init_cmds_size;
|
||||
} else {
|
||||
init_cmds = vendor_specific_init_default;
|
||||
init_cmds_size = sizeof(vendor_specific_init_default) / sizeof(esp_lcd_panel_vendor_init_cmd_t);
|
||||
}
|
||||
|
||||
bool is_cmd_overwritten = false;
|
||||
for (int i = 0; i < init_cmds_size; i++) {
|
||||
// Check if the command has been used or conflicts with the internal
|
||||
switch (init_cmds[i].cmd) {
|
||||
case LCD_CMD_MADCTL:
|
||||
is_cmd_overwritten = true;
|
||||
gc9a01->madctl_val = ((uint8_t *)init_cmds[i].data)[0];
|
||||
break;
|
||||
case LCD_CMD_COLMOD:
|
||||
is_cmd_overwritten = true;
|
||||
gc9a01->colmod_val = ((uint8_t *)init_cmds[i].data)[0];
|
||||
break;
|
||||
default:
|
||||
is_cmd_overwritten = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_cmd_overwritten) {
|
||||
ESP_LOGW(TAG, "The %02Xh command has been used and will be overwritten by external initialization sequence", init_cmds[i].cmd);
|
||||
}
|
||||
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, init_cmds[i].cmd, init_cmds[i].data, init_cmds[i].data_bytes), TAG, "send command failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(init_cmds[i].delay_ms));
|
||||
}
|
||||
ESP_LOGD(TAG, "send init commands success");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_gc9a01_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data)
|
||||
{
|
||||
gc9a01_panel_t *gc9a01 = __containerof(panel, gc9a01_panel_t, base);
|
||||
assert((x_start < x_end) && (y_start < y_end) && "start position must be smaller than end position");
|
||||
esp_lcd_panel_io_handle_t io = gc9a01->io;
|
||||
|
||||
x_start += gc9a01->x_gap;
|
||||
x_end += gc9a01->x_gap;
|
||||
y_start += gc9a01->y_gap;
|
||||
y_end += gc9a01->y_gap;
|
||||
|
||||
// define an area of frame memory where MCU can access
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_CASET, (uint8_t[]) {
|
||||
(x_start >> 8) & 0xFF,
|
||||
x_start & 0xFF,
|
||||
((x_end - 1) >> 8) & 0xFF,
|
||||
(x_end - 1) & 0xFF,
|
||||
}, 4), TAG, "send command failed");
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_RASET, (uint8_t[]) {
|
||||
(y_start >> 8) & 0xFF,
|
||||
y_start & 0xFF,
|
||||
((y_end - 1) >> 8) & 0xFF,
|
||||
(y_end - 1) & 0xFF,
|
||||
}, 4), TAG, "send command failed");
|
||||
// transfer frame buffer
|
||||
size_t len = (x_end - x_start) * (y_end - y_start) * gc9a01->fb_bits_per_pixel / 8;
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_color(io, LCD_CMD_RAMWR, color_data, len), TAG, "send color failed");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_gc9a01_invert_color(esp_lcd_panel_t *panel, bool invert_color_data)
|
||||
{
|
||||
gc9a01_panel_t *gc9a01 = __containerof(panel, gc9a01_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = gc9a01->io;
|
||||
int command = 0;
|
||||
if (invert_color_data) {
|
||||
command = LCD_CMD_INVON;
|
||||
} else {
|
||||
command = LCD_CMD_INVOFF;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, command, NULL, 0), TAG, "send command failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_gc9a01_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y)
|
||||
{
|
||||
gc9a01_panel_t *gc9a01 = __containerof(panel, gc9a01_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = gc9a01->io;
|
||||
if (mirror_x) {
|
||||
gc9a01->madctl_val |= LCD_CMD_MX_BIT;
|
||||
} else {
|
||||
gc9a01->madctl_val &= ~LCD_CMD_MX_BIT;
|
||||
}
|
||||
if (mirror_y) {
|
||||
gc9a01->madctl_val |= LCD_CMD_MY_BIT;
|
||||
} else {
|
||||
gc9a01->madctl_val &= ~LCD_CMD_MY_BIT;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]) {
|
||||
gc9a01->madctl_val
|
||||
}, 1), TAG, "send command failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_gc9a01_swap_xy(esp_lcd_panel_t *panel, bool swap_axes)
|
||||
{
|
||||
gc9a01_panel_t *gc9a01 = __containerof(panel, gc9a01_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = gc9a01->io;
|
||||
if (swap_axes) {
|
||||
gc9a01->madctl_val |= LCD_CMD_MV_BIT;
|
||||
} else {
|
||||
gc9a01->madctl_val &= ~LCD_CMD_MV_BIT;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]) {
|
||||
gc9a01->madctl_val
|
||||
}, 1), TAG, "send command failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_gc9a01_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap)
|
||||
{
|
||||
gc9a01_panel_t *gc9a01 = __containerof(panel, gc9a01_panel_t, base);
|
||||
gc9a01->x_gap = x_gap;
|
||||
gc9a01->y_gap = y_gap;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_gc9a01_disp_on_off(esp_lcd_panel_t *panel, bool on_off)
|
||||
{
|
||||
gc9a01_panel_t *gc9a01 = __containerof(panel, gc9a01_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = gc9a01->io;
|
||||
int command = 0;
|
||||
|
||||
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
on_off = !on_off;
|
||||
#endif
|
||||
|
||||
if (on_off) {
|
||||
command = LCD_CMD_DISPON;
|
||||
} else {
|
||||
command = LCD_CMD_DISPOFF;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, command, NULL, 0), TAG, "send command failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
* @brief ESP LCD: GC9A01
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_LCD_GC9A01_VER_MAJOR (2)
|
||||
#define ESP_LCD_GC9A01_VER_MINOR (0)
|
||||
#define ESP_LCD_GC9A01_VER_PATCH (0)
|
||||
|
||||
/**
|
||||
* @brief Create LCD panel for model GC9A01
|
||||
*
|
||||
* @note Vendor specific initialization can be different between manufacturers, should consult the LCD supplier for initialization sequence code.
|
||||
*
|
||||
* @param[in] io LCD panel IO handle
|
||||
* @param[in] panel_dev_config general panel device configuration
|
||||
* @param[out] ret_panel Returned LCD panel handle
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG if parameter is invalid
|
||||
* - ESP_ERR_NO_MEM if out of memory
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t esp_lcd_new_panel_gc9a01(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel);
|
||||
|
||||
/**
|
||||
* @brief LCD panel bus configuration structure
|
||||
*
|
||||
* @param[in] sclk SPI clock pin number
|
||||
* @param[in] mosi SPI MOSI pin number
|
||||
* @param[in] max_trans_sz Maximum transfer size in bytes
|
||||
*
|
||||
*/
|
||||
#define GC9A01_PANEL_BUS_SPI_CONFIG(sclk, mosi, max_trans_sz) \
|
||||
{ \
|
||||
.sclk_io_num = sclk, \
|
||||
.mosi_io_num = mosi, \
|
||||
.miso_io_num = -1, \
|
||||
.quadhd_io_num = -1, \
|
||||
.quadwp_io_num = -1, \
|
||||
.max_transfer_sz = max_trans_sz, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief LCD panel IO configuration structure
|
||||
*
|
||||
* @param[in] cs SPI chip select pin number
|
||||
* @param[in] dc SPI data/command pin number
|
||||
* @param[in] cb Callback function when SPI transfer is done
|
||||
* @param[in] cb_ctx Callback function context
|
||||
*
|
||||
*/
|
||||
#define GC9A01_PANEL_IO_SPI_CONFIG(cs, dc, callback, callback_ctx) \
|
||||
{ \
|
||||
.cs_gpio_num = cs, \
|
||||
.dc_gpio_num = dc, \
|
||||
.spi_mode = 0, \
|
||||
.pclk_hz = 80 * 1000 * 1000, \
|
||||
.trans_queue_depth = 10, \
|
||||
.on_color_trans_done = callback, \
|
||||
.user_ctx = callback_ctx, \
|
||||
.lcd_cmd_bits = 8, \
|
||||
.lcd_param_bits = 8, \
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
+415
@@ -0,0 +1,415 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_lcd_panel_interface.h"
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
#include "esp_lcd_panel_ops.h"
|
||||
#include "esp_lcd_panel_commands.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "esp_lcd_custom_types.h"
|
||||
#include "esp_lcd_gc9b71.h"
|
||||
|
||||
#define LCD_OPCODE_WRITE_CMD (0x02ULL)
|
||||
#define LCD_OPCODE_READ_CMD (0x03ULL)
|
||||
#define LCD_OPCODE_WRITE_COLOR (0x32ULL)
|
||||
|
||||
static const char *TAG = "gc9b71";
|
||||
|
||||
static esp_err_t panel_gc9b71_del(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_gc9b71_reset(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_gc9b71_init(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_gc9b71_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data);
|
||||
static esp_err_t panel_gc9b71_invert_color(esp_lcd_panel_t *panel, bool invert_color_data);
|
||||
static esp_err_t panel_gc9b71_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y);
|
||||
static esp_err_t panel_gc9b71_swap_xy(esp_lcd_panel_t *panel, bool swap_axes);
|
||||
static esp_err_t panel_gc9b71_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap);
|
||||
static esp_err_t panel_gc9b71_disp_on_off(esp_lcd_panel_t *panel, bool off);
|
||||
|
||||
typedef struct {
|
||||
esp_lcd_panel_t base;
|
||||
esp_lcd_panel_io_handle_t io;
|
||||
int reset_gpio_num;
|
||||
int x_gap;
|
||||
int y_gap;
|
||||
uint8_t fb_bits_per_pixel;
|
||||
uint8_t madctl_val; // save current value of LCD_CMD_MADCTL register
|
||||
uint8_t colmod_val; // save current value of LCD_CMD_COLMOD register
|
||||
const esp_lcd_panel_vendor_init_cmd_t *init_cmds;
|
||||
uint16_t init_cmds_size;
|
||||
struct {
|
||||
unsigned int use_qspi_interface: 1;
|
||||
unsigned int reset_level: 1;
|
||||
} flags;
|
||||
} gc9b71_panel_t;
|
||||
|
||||
esp_err_t esp_lcd_new_panel_gc9b71(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel)
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
ESP_RETURN_ON_FALSE(io && panel_dev_config && ret_panel, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
gc9b71_panel_t *gc9b71 = NULL;
|
||||
gc9b71 = calloc(1, sizeof(gc9b71_panel_t));
|
||||
ESP_GOTO_ON_FALSE(gc9b71, ESP_ERR_NO_MEM, err, TAG, "no mem for gc9b71 panel");
|
||||
|
||||
if (panel_dev_config->reset_gpio_num >= 0) {
|
||||
gpio_config_t io_conf = {
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pin_bit_mask = 1ULL << panel_dev_config->reset_gpio_num,
|
||||
};
|
||||
ESP_GOTO_ON_ERROR(gpio_config(&io_conf), err, TAG, "configure GPIO for RST line failed");
|
||||
}
|
||||
|
||||
switch (panel_dev_config->rgb_ele_order) {
|
||||
case LCD_RGB_ELEMENT_ORDER_RGB:
|
||||
gc9b71->madctl_val = 0;
|
||||
break;
|
||||
case LCD_RGB_ELEMENT_ORDER_BGR:
|
||||
gc9b71->madctl_val |= LCD_CMD_BGR_BIT;
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported color element order");
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t fb_bits_per_pixel = 0;
|
||||
switch (panel_dev_config->bits_per_pixel) {
|
||||
case 16: // RGB565
|
||||
gc9b71->colmod_val = 0x55;
|
||||
fb_bits_per_pixel = 16;
|
||||
break;
|
||||
case 18: // RGB666
|
||||
gc9b71->colmod_val = 0x66;
|
||||
// each color component (R/G/B) should occupy the 6 high bits of a byte, which means 3 full bytes are required for a pixel
|
||||
fb_bits_per_pixel = 24;
|
||||
break;
|
||||
case 24: // RGB888
|
||||
gc9b71->colmod_val = 0x77;
|
||||
fb_bits_per_pixel = 24;
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported pixel width");
|
||||
break;
|
||||
}
|
||||
|
||||
gc9b71->io = io;
|
||||
gc9b71->reset_gpio_num = panel_dev_config->reset_gpio_num;
|
||||
gc9b71->fb_bits_per_pixel = fb_bits_per_pixel;
|
||||
esp_lcd_panel_vendor_config_t *vendor_config = (esp_lcd_panel_vendor_config_t *)panel_dev_config->vendor_config;
|
||||
if (vendor_config) {
|
||||
gc9b71->init_cmds = vendor_config->init_cmds;
|
||||
gc9b71->init_cmds_size = vendor_config->init_cmds_size;
|
||||
gc9b71->flags.use_qspi_interface = vendor_config->flags.use_qspi_interface;
|
||||
}
|
||||
gc9b71->flags.reset_level = panel_dev_config->flags.reset_active_high;
|
||||
gc9b71->base.del = panel_gc9b71_del;
|
||||
gc9b71->base.reset = panel_gc9b71_reset;
|
||||
gc9b71->base.init = panel_gc9b71_init;
|
||||
gc9b71->base.draw_bitmap = panel_gc9b71_draw_bitmap;
|
||||
gc9b71->base.invert_color = panel_gc9b71_invert_color;
|
||||
gc9b71->base.set_gap = panel_gc9b71_set_gap;
|
||||
gc9b71->base.mirror = panel_gc9b71_mirror;
|
||||
gc9b71->base.swap_xy = panel_gc9b71_swap_xy;
|
||||
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
gc9b71->base.disp_off = panel_gc9b71_disp_on_off;
|
||||
#else
|
||||
gc9b71->base.disp_on_off = panel_gc9b71_disp_on_off;
|
||||
#endif
|
||||
*ret_panel = &(gc9b71->base);
|
||||
ESP_LOGD(TAG, "new gc9b71 panel @%p", gc9b71);
|
||||
|
||||
ESP_LOGI(TAG, "LCD panel create success, version: %d.%d.%d", ESP_LCD_GC9B71_VER_MAJOR, ESP_LCD_GC9B71_VER_MINOR,
|
||||
ESP_LCD_GC9B71_VER_PATCH);
|
||||
|
||||
return ESP_OK;
|
||||
|
||||
err:
|
||||
if (gc9b71) {
|
||||
if (panel_dev_config->reset_gpio_num >= 0) {
|
||||
gpio_reset_pin(panel_dev_config->reset_gpio_num);
|
||||
}
|
||||
free(gc9b71);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t tx_param(gc9b71_panel_t *gc9b71, esp_lcd_panel_io_handle_t io, int lcd_cmd, const void *param, size_t param_size)
|
||||
{
|
||||
if (gc9b71->flags.use_qspi_interface) {
|
||||
lcd_cmd &= 0xff;
|
||||
lcd_cmd <<= 8;
|
||||
lcd_cmd |= LCD_OPCODE_WRITE_CMD << 24;
|
||||
}
|
||||
return esp_lcd_panel_io_tx_param(io, lcd_cmd, param, param_size);
|
||||
}
|
||||
|
||||
static esp_err_t tx_color(gc9b71_panel_t *gc9b71, esp_lcd_panel_io_handle_t io, int lcd_cmd, const void *param, size_t param_size)
|
||||
{
|
||||
if (gc9b71->flags.use_qspi_interface) {
|
||||
lcd_cmd &= 0xff;
|
||||
lcd_cmd <<= 8;
|
||||
lcd_cmd |= LCD_OPCODE_WRITE_COLOR << 24;
|
||||
}
|
||||
return esp_lcd_panel_io_tx_color(io, lcd_cmd, param, param_size);
|
||||
}
|
||||
|
||||
static esp_err_t panel_gc9b71_del(esp_lcd_panel_t *panel)
|
||||
{
|
||||
gc9b71_panel_t *gc9b71 = __containerof(panel, gc9b71_panel_t, base);
|
||||
|
||||
if (gc9b71->reset_gpio_num >= 0) {
|
||||
gpio_reset_pin(gc9b71->reset_gpio_num);
|
||||
}
|
||||
ESP_LOGD(TAG, "del gc9b71 panel @%p", gc9b71);
|
||||
free(gc9b71);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_gc9b71_reset(esp_lcd_panel_t *panel)
|
||||
{
|
||||
gc9b71_panel_t *gc9b71 = __containerof(panel, gc9b71_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = gc9b71->io;
|
||||
|
||||
// Perform hardware reset
|
||||
if (gc9b71->reset_gpio_num >= 0) {
|
||||
gpio_set_level(gc9b71->reset_gpio_num, gc9b71->flags.reset_level);
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
gpio_set_level(gc9b71->reset_gpio_num, !gc9b71->flags.reset_level);
|
||||
vTaskDelay(pdMS_TO_TICKS(120));
|
||||
} else { // Perform software reset
|
||||
ESP_RETURN_ON_ERROR(tx_param(gc9b71, io, LCD_CMD_SWRESET, NULL, 0), TAG, "send command failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(20));
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static const esp_lcd_panel_vendor_init_cmd_t vendor_specific_init_default[] = {
|
||||
// {cmd, { data }, data_size, delay_ms}
|
||||
{0xfe, (uint8_t []){0x00}, 0, 0},
|
||||
{0xef, (uint8_t []){0x00}, 0, 0},
|
||||
{0x80, (uint8_t []){0x11}, 1, 0},
|
||||
{0x81, (uint8_t []){0x70}, 1, 0},
|
||||
{0x82, (uint8_t []){0x09}, 1, 0},
|
||||
{0x83, (uint8_t []){0x03}, 1, 0},
|
||||
{0x84, (uint8_t []){0x62}, 1, 0},
|
||||
{0x89, (uint8_t []){0x18}, 1, 0},
|
||||
{0x8A, (uint8_t []){0x40}, 1, 0},
|
||||
{0x8B, (uint8_t []){0x0A}, 1, 0},
|
||||
{0xEC, (uint8_t []){0x07}, 1, 0},
|
||||
{0x74, (uint8_t []){0x01, 0x80, 0x00, 0x00, 0x00, 0x00}, 6, 0},
|
||||
{0x98, (uint8_t []){0x3E}, 1, 0},
|
||||
{0x99, (uint8_t []){0x3E}, 1, 0},
|
||||
{0xA1, (uint8_t []){0x01, 0x04}, 2, 0},
|
||||
{0xA2, (uint8_t []){0x01, 0x04}, 2, 0},
|
||||
{0xCB, (uint8_t []){0x02}, 1, 0},
|
||||
{0x7C, (uint8_t []){0xB6, 0x24}, 2, 0},
|
||||
{0xAC, (uint8_t []){0x74}, 1, 0},
|
||||
{0xF6, (uint8_t []){0x80}, 1, 0},
|
||||
{0xB5, (uint8_t []){0x09, 0x09}, 2, 0},
|
||||
{0xEB, (uint8_t []){0x01, 0x81}, 2, 0},
|
||||
{0x60, (uint8_t []){0x38, 0x06, 0x13, 0x56}, 4, 0},
|
||||
{0x63, (uint8_t []){0x38, 0x08, 0x13, 0x56}, 4, 0},
|
||||
{0x61, (uint8_t []){0x3B, 0x1b, 0x58, 0x38}, 4, 0},
|
||||
{0x62, (uint8_t []){0x3B, 0x1b, 0x58, 0x38}, 4, 0},
|
||||
{0x64, (uint8_t []){0x38, 0x0a, 0x73, 0x16, 0x13, 0x56}, 6, 0},
|
||||
{0x66, (uint8_t []){0x38, 0x0b, 0x73, 0x17, 0x13, 0x56}, 6, 0},
|
||||
{0x68, (uint8_t []){0x00, 0x0B, 0x22, 0x0B, 0x22, 0x1C, 0x1C}, 7, 0},
|
||||
{0x69, (uint8_t []){0x00, 0x0B, 0x26, 0x0B, 0x26, 0x1C, 0x1C}, 7, 0},
|
||||
{0x6A, (uint8_t []){0x15, 0x00}, 2, 0},
|
||||
{
|
||||
0x6E, (uint8_t [])
|
||||
{
|
||||
0x08, 0x02, 0x1a, 0x00, 0x12, 0x12, 0x11, 0x11, 0x14, 0x14, 0x13, 0x13, 0x04, 0x19, 0x1e, 0x1d,
|
||||
0x1d, 0x1e, 0x19, 0x04, 0x0b, 0x0b, 0x0c, 0x0c, 0x09, 0x09, 0x0a, 0x0a, 0x00, 0x1a, 0x01, 0x07
|
||||
},
|
||||
32, 0
|
||||
},
|
||||
{0x6C, (uint8_t []){0xCC, 0x0C, 0xCC, 0x84, 0xCC, 0x04, 0x50}, 7, 0},
|
||||
{0x7D, (uint8_t []){0x72}, 1, 0},
|
||||
{0x70, (uint8_t []){0x02, 0x03, 0x09, 0x07, 0x09, 0x03, 0x09, 0x07, 0x09, 0x03}, 10, 0},
|
||||
{0x90, (uint8_t []){0x06, 0x06, 0x05, 0x06}, 4, 0},
|
||||
{0x93, (uint8_t []){0x45, 0xFF, 0x00}, 3, 0},
|
||||
{0xC3, (uint8_t []){0x15}, 1, 0},
|
||||
{0xC4, (uint8_t []){0x36}, 1, 0},
|
||||
{0xC9, (uint8_t []){0x3d}, 1, 0},
|
||||
{0xF0, (uint8_t []){0x47, 0x07, 0x0A, 0x0A, 0x00, 0x29}, 6, 0},
|
||||
{0xF2, (uint8_t []){0x47, 0x07, 0x0a, 0x0A, 0x00, 0x29}, 6, 0},
|
||||
{0xF1, (uint8_t []){0x42, 0x91, 0x10, 0x2D, 0x2F, 0x6F}, 6, 0},
|
||||
{0xF3, (uint8_t []){0x42, 0x91, 0x10, 0x2D, 0x2F, 0x6F}, 6, 0},
|
||||
{0xF9, (uint8_t []){0x30}, 1, 0},
|
||||
{0xBE, (uint8_t []){0x11}, 1, 0},
|
||||
{0xFB, (uint8_t []){0x00, 0x00}, 2, 0},
|
||||
{0x11, (uint8_t []){0x00}, 0, 1000},
|
||||
};
|
||||
|
||||
static esp_err_t panel_gc9b71_init(esp_lcd_panel_t *panel)
|
||||
{
|
||||
gc9b71_panel_t *gc9b71 = __containerof(panel, gc9b71_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = gc9b71->io;
|
||||
const esp_lcd_panel_vendor_init_cmd_t *init_cmds = NULL;
|
||||
uint16_t init_cmds_size = 0;
|
||||
bool is_cmd_overwritten = false;
|
||||
|
||||
ESP_RETURN_ON_ERROR(tx_param(gc9b71, io, LCD_CMD_MADCTL, (uint8_t[]) {
|
||||
gc9b71->madctl_val,
|
||||
}, 1), TAG, "send command failed");
|
||||
ESP_RETURN_ON_ERROR(tx_param(gc9b71, io, LCD_CMD_COLMOD, (uint8_t[]) {
|
||||
gc9b71->colmod_val,
|
||||
}, 1), TAG, "send command failed");
|
||||
|
||||
// vendor specific initialization, it can be different between manufacturers
|
||||
// should consult the LCD supplier for initialization sequence code
|
||||
if (gc9b71->init_cmds) {
|
||||
init_cmds = gc9b71->init_cmds;
|
||||
init_cmds_size = gc9b71->init_cmds_size;
|
||||
} else {
|
||||
init_cmds = vendor_specific_init_default;
|
||||
init_cmds_size = sizeof(vendor_specific_init_default) / sizeof(esp_lcd_panel_vendor_init_cmd_t);
|
||||
}
|
||||
|
||||
for (int i = 0; i < init_cmds_size; i++) {
|
||||
// Check if the command has been used or conflicts with the internal
|
||||
switch (init_cmds[i].cmd) {
|
||||
case LCD_CMD_MADCTL:
|
||||
is_cmd_overwritten = true;
|
||||
gc9b71->madctl_val = ((uint8_t *)init_cmds[i].data)[0];
|
||||
break;
|
||||
case LCD_CMD_COLMOD:
|
||||
is_cmd_overwritten = true;
|
||||
gc9b71->colmod_val = ((uint8_t *)init_cmds[i].data)[0];
|
||||
break;
|
||||
default:
|
||||
is_cmd_overwritten = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_cmd_overwritten) {
|
||||
ESP_LOGW(TAG, "The %02Xh command has been used and will be overwritten by external initialization sequence", init_cmds[i].cmd);
|
||||
}
|
||||
|
||||
ESP_RETURN_ON_ERROR(tx_param(gc9b71, io, init_cmds[i].cmd, init_cmds[i].data, init_cmds[i].data_bytes), TAG,
|
||||
"send command failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(init_cmds[i].delay_ms));
|
||||
}
|
||||
ESP_LOGD(TAG, "send init commands success");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_gc9b71_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data)
|
||||
{
|
||||
gc9b71_panel_t *gc9b71 = __containerof(panel, gc9b71_panel_t, base);
|
||||
assert((x_start < x_end) && (y_start < y_end) && "start position must be smaller than end position");
|
||||
esp_lcd_panel_io_handle_t io = gc9b71->io;
|
||||
|
||||
x_start += gc9b71->x_gap;
|
||||
x_end += gc9b71->x_gap;
|
||||
y_start += gc9b71->y_gap;
|
||||
y_end += gc9b71->y_gap;
|
||||
|
||||
// define an area of frame memory where MCU can access
|
||||
ESP_RETURN_ON_ERROR(tx_param(gc9b71, io, LCD_CMD_CASET, (uint8_t[]) {
|
||||
(x_start >> 8) & 0xFF,
|
||||
x_start & 0xFF,
|
||||
((x_end - 1) >> 8) & 0xFF,
|
||||
(x_end - 1) & 0xFF,
|
||||
}, 4), TAG, "send command failed");
|
||||
ESP_RETURN_ON_ERROR(tx_param(gc9b71, io, LCD_CMD_RASET, (uint8_t[]) {
|
||||
(y_start >> 8) & 0xFF,
|
||||
y_start & 0xFF,
|
||||
((y_end - 1) >> 8) & 0xFF,
|
||||
(y_end - 1) & 0xFF,
|
||||
}, 4), TAG, "send command failed");
|
||||
// transfer frame buffer
|
||||
size_t len = (x_end - x_start) * (y_end - y_start) * gc9b71->fb_bits_per_pixel / 8;
|
||||
ESP_RETURN_ON_ERROR(tx_color(gc9b71, io, LCD_CMD_RAMWR, color_data, len), TAG, "send color failed");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_gc9b71_invert_color(esp_lcd_panel_t *panel, bool invert_color_data)
|
||||
{
|
||||
gc9b71_panel_t *gc9b71 = __containerof(panel, gc9b71_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = gc9b71->io;
|
||||
int command = 0;
|
||||
if (invert_color_data) {
|
||||
command = LCD_CMD_INVON;
|
||||
} else {
|
||||
command = LCD_CMD_INVOFF;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(tx_param(gc9b71, io, command, NULL, 0), TAG, "send command failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_gc9b71_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y)
|
||||
{
|
||||
gc9b71_panel_t *gc9b71 = __containerof(panel, gc9b71_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = gc9b71->io;
|
||||
if (mirror_x) {
|
||||
gc9b71->madctl_val |= LCD_CMD_MX_BIT;
|
||||
} else {
|
||||
gc9b71->madctl_val &= ~LCD_CMD_MX_BIT;
|
||||
}
|
||||
if (mirror_y) {
|
||||
gc9b71->madctl_val |= LCD_CMD_MY_BIT;
|
||||
} else {
|
||||
gc9b71->madctl_val &= ~LCD_CMD_MY_BIT;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(tx_param(gc9b71, io, LCD_CMD_MADCTL, (uint8_t[]) {
|
||||
gc9b71->madctl_val
|
||||
}, 1), TAG, "send command failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_gc9b71_swap_xy(esp_lcd_panel_t *panel, bool swap_axes)
|
||||
{
|
||||
gc9b71_panel_t *gc9b71 = __containerof(panel, gc9b71_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = gc9b71->io;
|
||||
if (swap_axes) {
|
||||
gc9b71->madctl_val |= LCD_CMD_MV_BIT;
|
||||
} else {
|
||||
gc9b71->madctl_val &= ~LCD_CMD_MV_BIT;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(tx_param(gc9b71, io, LCD_CMD_MADCTL, (uint8_t[]) {
|
||||
gc9b71->madctl_val
|
||||
}, 1), TAG, "send command failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_gc9b71_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap)
|
||||
{
|
||||
gc9b71_panel_t *gc9b71 = __containerof(panel, gc9b71_panel_t, base);
|
||||
gc9b71->x_gap = x_gap;
|
||||
gc9b71->y_gap = y_gap;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_gc9b71_disp_on_off(esp_lcd_panel_t *panel, bool on_off)
|
||||
{
|
||||
gc9b71_panel_t *gc9b71 = __containerof(panel, gc9b71_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = gc9b71->io;
|
||||
int command = 0;
|
||||
|
||||
if (on_off) {
|
||||
command = LCD_CMD_DISPON;
|
||||
} else {
|
||||
command = LCD_CMD_DISPOFF;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(tx_param(gc9b71, io, command, NULL, 0), TAG, "send command failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_LCD_GC9B71_VER_MAJOR (1)
|
||||
#define ESP_LCD_GC9B71_VER_MINOR (0)
|
||||
#define ESP_LCD_GC9B71_VER_PATCH (1)
|
||||
|
||||
/**
|
||||
* @brief Create LCD panel for model GC9B71
|
||||
*
|
||||
* @param[in] io LCD panel IO handle
|
||||
* @param[in] panel_dev_config General panel device configuration (Use `vendor_config` to select QSPI interface or override default initialization commands)
|
||||
* @param[out] ret_panel Returned LCD panel handle
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - Otherwise: Fail
|
||||
*/
|
||||
esp_err_t esp_lcd_new_panel_gc9b71(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel);
|
||||
|
||||
/**
|
||||
* @brief LCD panel bus configuration structure
|
||||
*
|
||||
*/
|
||||
#define GC9B71_PANEL_BUS_SPI_CONFIG(sclk, mosi, max_trans_sz) \
|
||||
{ \
|
||||
.sclk_io_num = sclk, \
|
||||
.mosi_io_num = mosi, \
|
||||
.miso_io_num = -1, \
|
||||
.quadhd_io_num = -1, \
|
||||
.quadwp_io_num = -1, \
|
||||
.max_transfer_sz = max_trans_sz, \
|
||||
}
|
||||
#define GC9B71_PANEL_BUS_QSPI_CONFIG(sclk, d0, d1, d2, d3, max_trans_sz) \
|
||||
{ \
|
||||
.sclk_io_num = sclk, \
|
||||
.data0_io_num = d0, \
|
||||
.data1_io_num = d1, \
|
||||
.data2_io_num = d2, \
|
||||
.data3_io_num = d3, \
|
||||
.max_transfer_sz = max_trans_sz, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief LCD panel IO configuration structure
|
||||
*
|
||||
*/
|
||||
#define GC9B71_PANEL_IO_SPI_CONFIG(cs, dc, cb, cb_ctx) \
|
||||
{ \
|
||||
.cs_gpio_num = cs, \
|
||||
.dc_gpio_num = dc, \
|
||||
.spi_mode = 0, \
|
||||
.pclk_hz = 80 * 1000 * 1000, \
|
||||
.trans_queue_depth = 10, \
|
||||
.on_color_trans_done = cb, \
|
||||
.user_ctx = cb_ctx, \
|
||||
.lcd_cmd_bits = 8, \
|
||||
.lcd_param_bits = 8, \
|
||||
}
|
||||
#define GC9B71_PANEL_IO_QSPI_CONFIG(cs, cb, cb_ctx) \
|
||||
{ \
|
||||
.cs_gpio_num = cs, \
|
||||
.dc_gpio_num = -1, \
|
||||
.spi_mode = 0, \
|
||||
.pclk_hz = 20 * 1000 * 1000, \
|
||||
.trans_queue_depth = 10, \
|
||||
.on_color_trans_done = cb, \
|
||||
.user_ctx = cb_ctx, \
|
||||
.lcd_cmd_bits = 32, \
|
||||
.lcd_param_bits = 8, \
|
||||
.flags = { \
|
||||
.quad_mode = true, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
+385
@@ -0,0 +1,385 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_lcd_panel_interface.h"
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
#include "esp_lcd_panel_ops.h"
|
||||
#include "esp_lcd_panel_commands.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
|
||||
#include "esp_lcd_custom_types.h"
|
||||
#include "esp_lcd_ili9341.h"
|
||||
|
||||
static const char *TAG = "ili9341";
|
||||
|
||||
static esp_err_t panel_ili9341_del(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_ili9341_reset(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_ili9341_init(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_ili9341_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data);
|
||||
static esp_err_t panel_ili9341_invert_color(esp_lcd_panel_t *panel, bool invert_color_data);
|
||||
static esp_err_t panel_ili9341_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y);
|
||||
static esp_err_t panel_ili9341_swap_xy(esp_lcd_panel_t *panel, bool swap_axes);
|
||||
static esp_err_t panel_ili9341_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap);
|
||||
static esp_err_t panel_ili9341_disp_on_off(esp_lcd_panel_t *panel, bool off);
|
||||
|
||||
typedef struct {
|
||||
esp_lcd_panel_t base;
|
||||
esp_lcd_panel_io_handle_t io;
|
||||
int reset_gpio_num;
|
||||
bool reset_level;
|
||||
int x_gap;
|
||||
int y_gap;
|
||||
uint8_t fb_bits_per_pixel;
|
||||
uint8_t madctl_val; // save current value of LCD_CMD_MADCTL register
|
||||
uint8_t colmod_val; // save current value of LCD_CMD_COLMOD register
|
||||
const esp_lcd_panel_vendor_init_cmd_t *init_cmds;
|
||||
uint16_t init_cmds_size;
|
||||
} ili9341_panel_t;
|
||||
|
||||
esp_err_t esp_lcd_new_panel_ili9341(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel)
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
ili9341_panel_t *ili9341 = NULL;
|
||||
gpio_config_t io_conf = { 0 };
|
||||
|
||||
ESP_GOTO_ON_FALSE(io && panel_dev_config && ret_panel, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
||||
ili9341 = (ili9341_panel_t *)calloc(1, sizeof(ili9341_panel_t));
|
||||
ESP_GOTO_ON_FALSE(ili9341, ESP_ERR_NO_MEM, err, TAG, "no mem for ili9341 panel");
|
||||
|
||||
if (panel_dev_config->reset_gpio_num >= 0) {
|
||||
io_conf.mode = GPIO_MODE_OUTPUT;
|
||||
io_conf.pin_bit_mask = 1ULL << panel_dev_config->reset_gpio_num;
|
||||
ESP_GOTO_ON_ERROR(gpio_config(&io_conf), err, TAG, "configure GPIO for RST line failed");
|
||||
}
|
||||
|
||||
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
switch (panel_dev_config->color_space) {
|
||||
case ESP_LCD_COLOR_SPACE_RGB:
|
||||
ili9341->madctl_val = 0;
|
||||
break;
|
||||
case ESP_LCD_COLOR_SPACE_BGR:
|
||||
ili9341->madctl_val |= LCD_CMD_BGR_BIT;
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported color space");
|
||||
break;
|
||||
}
|
||||
#else
|
||||
switch (panel_dev_config->rgb_endian) {
|
||||
case LCD_RGB_ENDIAN_RGB:
|
||||
ili9341->madctl_val = 0;
|
||||
break;
|
||||
case LCD_RGB_ENDIAN_BGR:
|
||||
ili9341->madctl_val |= LCD_CMD_BGR_BIT;
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported rgb endian");
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (panel_dev_config->bits_per_pixel) {
|
||||
case 16: // RGB565
|
||||
ili9341->colmod_val = 0x55;
|
||||
ili9341->fb_bits_per_pixel = 16;
|
||||
break;
|
||||
case 18: // RGB666
|
||||
ili9341->colmod_val = 0x66;
|
||||
// each color component (R/G/B) should occupy the 6 high bits of a byte, which means 3 full bytes are required for a pixel
|
||||
ili9341->fb_bits_per_pixel = 24;
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported pixel width");
|
||||
break;
|
||||
}
|
||||
|
||||
ili9341->io = io;
|
||||
ili9341->reset_gpio_num = panel_dev_config->reset_gpio_num;
|
||||
ili9341->reset_level = panel_dev_config->flags.reset_active_high;
|
||||
if (panel_dev_config->vendor_config) {
|
||||
ili9341->init_cmds = ((esp_lcd_panel_vendor_config_t *)panel_dev_config->vendor_config)->init_cmds;
|
||||
ili9341->init_cmds_size = ((esp_lcd_panel_vendor_config_t *)panel_dev_config->vendor_config)->init_cmds_size;
|
||||
}
|
||||
ili9341->base.del = panel_ili9341_del;
|
||||
ili9341->base.reset = panel_ili9341_reset;
|
||||
ili9341->base.init = panel_ili9341_init;
|
||||
ili9341->base.draw_bitmap = panel_ili9341_draw_bitmap;
|
||||
ili9341->base.invert_color = panel_ili9341_invert_color;
|
||||
ili9341->base.set_gap = panel_ili9341_set_gap;
|
||||
ili9341->base.mirror = panel_ili9341_mirror;
|
||||
ili9341->base.swap_xy = panel_ili9341_swap_xy;
|
||||
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
ili9341->base.disp_off = panel_ili9341_disp_on_off;
|
||||
#else
|
||||
ili9341->base.disp_on_off = panel_ili9341_disp_on_off;
|
||||
#endif
|
||||
*ret_panel = &(ili9341->base);
|
||||
ESP_LOGD(TAG, "new ili9341 panel @%p", ili9341);
|
||||
|
||||
ESP_LOGI(TAG, "LCD panel create success, version: %d.%d.%d", ESP_LCD_ILI9341_VER_MAJOR, ESP_LCD_ILI9341_VER_MINOR,
|
||||
ESP_LCD_ILI9341_VER_PATCH);
|
||||
|
||||
return ESP_OK;
|
||||
|
||||
err:
|
||||
if (ili9341) {
|
||||
if (panel_dev_config->reset_gpio_num >= 0) {
|
||||
gpio_reset_pin(panel_dev_config->reset_gpio_num);
|
||||
}
|
||||
free(ili9341);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t panel_ili9341_del(esp_lcd_panel_t *panel)
|
||||
{
|
||||
ili9341_panel_t *ili9341 = __containerof(panel, ili9341_panel_t, base);
|
||||
|
||||
if (ili9341->reset_gpio_num >= 0) {
|
||||
gpio_reset_pin(ili9341->reset_gpio_num);
|
||||
}
|
||||
ESP_LOGD(TAG, "del ili9341 panel @%p", ili9341);
|
||||
free(ili9341);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_ili9341_reset(esp_lcd_panel_t *panel)
|
||||
{
|
||||
ili9341_panel_t *ili9341 = __containerof(panel, ili9341_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = ili9341->io;
|
||||
|
||||
// perform hardware reset
|
||||
if (ili9341->reset_gpio_num >= 0) {
|
||||
gpio_set_level(ili9341->reset_gpio_num, ili9341->reset_level);
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
gpio_set_level(ili9341->reset_gpio_num, !ili9341->reset_level);
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
} else { // perform software reset
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_SWRESET, NULL, 0), TAG, "send command failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(20)); // spec, wait at least 5ms before sending new command
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static const esp_lcd_panel_vendor_init_cmd_t vendor_specific_init_default[] = {
|
||||
// {cmd, { data }, data_size, delay_ms}
|
||||
/* Power contorl B, power control = 0, DC_ENA = 1 */
|
||||
{0xCF, (uint8_t []){0x00, 0xAA, 0XE0}, 3, 0},
|
||||
/* Power on sequence control,
|
||||
* cp1 keeps 1 frame, 1st frame enable
|
||||
* vcl = 0, ddvdh=3, vgh=1, vgl=2
|
||||
* DDVDH_ENH=1
|
||||
*/
|
||||
{0xED, (uint8_t []){0x67, 0x03, 0X12, 0X81}, 4, 0},
|
||||
/* Driver timing control A,
|
||||
* non-overlap=default +1
|
||||
* EQ=default - 1, CR=default
|
||||
* pre-charge=default - 1
|
||||
*/
|
||||
{0xE8, (uint8_t []){0x8A, 0x01, 0x78}, 3, 0},
|
||||
/* Power control A, Vcore=1.6V, DDVDH=5.6V */
|
||||
{0xCB, (uint8_t []){0x39, 0x2C, 0x00, 0x34, 0x02}, 5, 0},
|
||||
/* Pump ratio control, DDVDH=2xVCl */
|
||||
{0xF7, (uint8_t []){0x20}, 1, 0},
|
||||
|
||||
{0xF7, (uint8_t []){0x20}, 1, 0},
|
||||
/* Driver timing control, all=0 unit */
|
||||
{0xEA, (uint8_t []){0x00, 0x00}, 2, 0},
|
||||
/* Power control 1, GVDD=4.75V */
|
||||
{0xC0, (uint8_t []){0x23}, 1, 0},
|
||||
/* Power control 2, DDVDH=VCl*2, VGH=VCl*7, VGL=-VCl*3 */
|
||||
{0xC1, (uint8_t []){0x11}, 1, 0},
|
||||
/* VCOM control 1, VCOMH=4.025V, VCOML=-0.950V */
|
||||
{0xC5, (uint8_t []){0x43, 0x4C}, 2, 0},
|
||||
/* VCOM control 2, VCOMH=VMH-2, VCOML=VML-2 */
|
||||
{0xC7, (uint8_t []){0xA0}, 1, 0},
|
||||
/* Frame rate control, f=fosc, 70Hz fps */
|
||||
{0xB1, (uint8_t []){0x00, 0x1B}, 2, 0},
|
||||
/* Enable 3G, disabled */
|
||||
{0xF2, (uint8_t []){0x00}, 1, 0},
|
||||
/* Gamma set, curve 1 */
|
||||
{0x26, (uint8_t []){0x01}, 1, 0},
|
||||
/* Positive gamma correction */
|
||||
{0xE0, (uint8_t []){0x1F, 0x36, 0x36, 0x3A, 0x0C, 0x05, 0x4F, 0X87, 0x3C, 0x08, 0x11, 0x35, 0x19, 0x13, 0x00}, 15, 0},
|
||||
/* Negative gamma correction */
|
||||
{0xE1, (uint8_t []){0x00, 0x09, 0x09, 0x05, 0x13, 0x0A, 0x30, 0x78, 0x43, 0x07, 0x0E, 0x0A, 0x26, 0x2C, 0x1F}, 15, 0},
|
||||
/* Entry mode set, Low vol detect disabled, normal display */
|
||||
{0xB7, (uint8_t []){0x07}, 1, 0},
|
||||
/* Display function control */
|
||||
{0xB6, (uint8_t []){0x08, 0x82, 0x27}, 3, 0},
|
||||
};
|
||||
|
||||
static esp_err_t panel_ili9341_init(esp_lcd_panel_t *panel)
|
||||
{
|
||||
ili9341_panel_t *ili9341 = __containerof(panel, ili9341_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = ili9341->io;
|
||||
|
||||
// LCD goes into sleep mode and display will be turned off after power on reset, exit sleep mode first
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_SLPOUT, NULL, 0), TAG, "send command failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]) {
|
||||
ili9341->madctl_val,
|
||||
}, 1), TAG, "send command failed");
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_COLMOD, (uint8_t[]) {
|
||||
ili9341->colmod_val,
|
||||
}, 1), TAG, "send command failed");
|
||||
|
||||
const esp_lcd_panel_vendor_init_cmd_t *init_cmds = NULL;
|
||||
uint16_t init_cmds_size = 0;
|
||||
if (ili9341->init_cmds) {
|
||||
init_cmds = ili9341->init_cmds;
|
||||
init_cmds_size = ili9341->init_cmds_size;
|
||||
} else {
|
||||
init_cmds = vendor_specific_init_default;
|
||||
init_cmds_size = sizeof(vendor_specific_init_default) / sizeof(esp_lcd_panel_vendor_init_cmd_t);
|
||||
}
|
||||
|
||||
bool is_cmd_overwritten = false;
|
||||
for (int i = 0; i < init_cmds_size; i++) {
|
||||
// Check if the command has been used or conflicts with the internal
|
||||
switch (init_cmds[i].cmd) {
|
||||
case LCD_CMD_MADCTL:
|
||||
is_cmd_overwritten = true;
|
||||
ili9341->madctl_val = ((uint8_t *)init_cmds[i].data)[0];
|
||||
break;
|
||||
case LCD_CMD_COLMOD:
|
||||
is_cmd_overwritten = true;
|
||||
ili9341->colmod_val = ((uint8_t *)init_cmds[i].data)[0];
|
||||
break;
|
||||
default:
|
||||
is_cmd_overwritten = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_cmd_overwritten) {
|
||||
ESP_LOGW(TAG, "The %02Xh command has been used and will be overwritten by external initialization sequence", init_cmds[i].cmd);
|
||||
}
|
||||
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, init_cmds[i].cmd, init_cmds[i].data, init_cmds[i].data_bytes), TAG, "send command failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(init_cmds[i].delay_ms));
|
||||
}
|
||||
ESP_LOGD(TAG, "send init commands success");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_ili9341_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data)
|
||||
{
|
||||
ili9341_panel_t *ili9341 = __containerof(panel, ili9341_panel_t, base);
|
||||
assert((x_start < x_end) && (y_start < y_end) && "start position must be smaller than end position");
|
||||
esp_lcd_panel_io_handle_t io = ili9341->io;
|
||||
|
||||
x_start += ili9341->x_gap;
|
||||
x_end += ili9341->x_gap;
|
||||
y_start += ili9341->y_gap;
|
||||
y_end += ili9341->y_gap;
|
||||
|
||||
// define an area of frame memory where MCU can access
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_CASET, (uint8_t[]) {
|
||||
(x_start >> 8) & 0xFF,
|
||||
x_start & 0xFF,
|
||||
((x_end - 1) >> 8) & 0xFF,
|
||||
(x_end - 1) & 0xFF,
|
||||
}, 4), TAG, "send command failed");
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_RASET, (uint8_t[]) {
|
||||
(y_start >> 8) & 0xFF,
|
||||
y_start & 0xFF,
|
||||
((y_end - 1) >> 8) & 0xFF,
|
||||
(y_end - 1) & 0xFF,
|
||||
}, 4), TAG, "send command failed");
|
||||
// transfer frame buffer
|
||||
size_t len = (x_end - x_start) * (y_end - y_start) * ili9341->fb_bits_per_pixel / 8;
|
||||
esp_lcd_panel_io_tx_color(io, LCD_CMD_RAMWR, color_data, len);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_ili9341_invert_color(esp_lcd_panel_t *panel, bool invert_color_data)
|
||||
{
|
||||
ili9341_panel_t *ili9341 = __containerof(panel, ili9341_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = ili9341->io;
|
||||
int command = 0;
|
||||
if (invert_color_data) {
|
||||
command = LCD_CMD_INVON;
|
||||
} else {
|
||||
command = LCD_CMD_INVOFF;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, command, NULL, 0), TAG, "send command failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_ili9341_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y)
|
||||
{
|
||||
ili9341_panel_t *ili9341 = __containerof(panel, ili9341_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = ili9341->io;
|
||||
if (mirror_x) {
|
||||
ili9341->madctl_val |= LCD_CMD_MX_BIT;
|
||||
} else {
|
||||
ili9341->madctl_val &= ~LCD_CMD_MX_BIT;
|
||||
}
|
||||
if (mirror_y) {
|
||||
ili9341->madctl_val |= LCD_CMD_MY_BIT;
|
||||
} else {
|
||||
ili9341->madctl_val &= ~LCD_CMD_MY_BIT;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]) {
|
||||
ili9341->madctl_val
|
||||
}, 1), TAG, "send command failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_ili9341_swap_xy(esp_lcd_panel_t *panel, bool swap_axes)
|
||||
{
|
||||
ili9341_panel_t *ili9341 = __containerof(panel, ili9341_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = ili9341->io;
|
||||
if (swap_axes) {
|
||||
ili9341->madctl_val |= LCD_CMD_MV_BIT;
|
||||
} else {
|
||||
ili9341->madctl_val &= ~LCD_CMD_MV_BIT;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]) {
|
||||
ili9341->madctl_val
|
||||
}, 1), TAG, "send command failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_ili9341_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap)
|
||||
{
|
||||
ili9341_panel_t *ili9341 = __containerof(panel, ili9341_panel_t, base);
|
||||
ili9341->x_gap = x_gap;
|
||||
ili9341->y_gap = y_gap;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_ili9341_disp_on_off(esp_lcd_panel_t *panel, bool on_off)
|
||||
{
|
||||
ili9341_panel_t *ili9341 = __containerof(panel, ili9341_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = ili9341->io;
|
||||
int command = 0;
|
||||
|
||||
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
on_off = !on_off;
|
||||
#endif
|
||||
|
||||
if (on_off) {
|
||||
command = LCD_CMD_DISPON;
|
||||
} else {
|
||||
command = LCD_CMD_DISPOFF;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, command, NULL, 0), TAG, "send command failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
* @brief ESP LCD: ILI9341
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_LCD_ILI9341_VER_MAJOR (2)
|
||||
#define ESP_LCD_ILI9341_VER_MINOR (0)
|
||||
#define ESP_LCD_ILI9341_VER_PATCH (0)
|
||||
|
||||
/**
|
||||
* @brief Create LCD panel for model ILI9341
|
||||
*
|
||||
* @note Vendor specific initialization can be different between manufacturers, should consult the LCD supplier for initialization sequence code.
|
||||
*
|
||||
* @param[in] io LCD panel IO handle
|
||||
* @param[in] panel_dev_config general panel device configuration
|
||||
* @param[out] ret_panel Returned LCD panel handle
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG if parameter is invalid
|
||||
* - ESP_ERR_NO_MEM if out of memory
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t esp_lcd_new_panel_ili9341(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel);
|
||||
|
||||
/**
|
||||
* @brief LCD panel bus configuration structure
|
||||
*
|
||||
* @param[in] sclk SPI clock pin number
|
||||
* @param[in] mosi SPI MOSI pin number
|
||||
* @param[in] max_trans_sz Maximum transfer size in bytes
|
||||
*
|
||||
*/
|
||||
#define ILI9341_PANEL_BUS_SPI_CONFIG(sclk, mosi, max_trans_sz) \
|
||||
{ \
|
||||
.sclk_io_num = sclk, \
|
||||
.mosi_io_num = mosi, \
|
||||
.miso_io_num = -1, \
|
||||
.quadhd_io_num = -1, \
|
||||
.quadwp_io_num = -1, \
|
||||
.max_transfer_sz = max_trans_sz, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief LCD panel IO configuration structure
|
||||
*
|
||||
* @param[in] cs SPI chip select pin number
|
||||
* @param[in] dc SPI data/command pin number
|
||||
* @param[in] cb Callback function when SPI transfer is done
|
||||
* @param[in] cb_ctx Callback function context
|
||||
*
|
||||
*/
|
||||
#define ILI9341_PANEL_IO_SPI_CONFIG(cs, dc, callback, callback_ctx) \
|
||||
{ \
|
||||
.cs_gpio_num = cs, \
|
||||
.dc_gpio_num = dc, \
|
||||
.spi_mode = 0, \
|
||||
.pclk_hz = 40 * 1000 * 1000, \
|
||||
.trans_queue_depth = 10, \
|
||||
.on_color_trans_done = callback, \
|
||||
.user_ctx = callback_ctx, \
|
||||
.lcd_cmd_bits = 8, \
|
||||
.lcd_param_bits = 8, \
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
+378
@@ -0,0 +1,378 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_lcd_panel_interface.h"
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
#include "esp_lcd_panel_ops.h"
|
||||
#include "esp_lcd_panel_commands.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
|
||||
#include "esp_lcd_custom_types.h"
|
||||
#include "esp_lcd_nv3022b.h"
|
||||
|
||||
static const char *TAG = "lcd_panel.nv3022b";
|
||||
|
||||
static esp_err_t panel_nv3022b_del(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_nv3022b_reset(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_nv3022b_init(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_nv3022b_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data);
|
||||
static esp_err_t panel_nv3022b_invert_color(esp_lcd_panel_t *panel, bool invert_color_data);
|
||||
static esp_err_t panel_nv3022b_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y);
|
||||
static esp_err_t panel_nv3022b_swap_xy(esp_lcd_panel_t *panel, bool swap_axes);
|
||||
static esp_err_t panel_nv3022b_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap);
|
||||
static esp_err_t panel_nv3022b_disp_on_off(esp_lcd_panel_t *panel, bool off);
|
||||
|
||||
typedef struct {
|
||||
esp_lcd_panel_t base;
|
||||
esp_lcd_panel_io_handle_t io;
|
||||
int reset_gpio_num;
|
||||
bool reset_level;
|
||||
int x_gap;
|
||||
int y_gap;
|
||||
uint8_t fb_bits_per_pixel;
|
||||
uint8_t madctl_val; // save current value of LCD_CMD_MADCTL register
|
||||
uint8_t colmod_val; // save current value of LCD_CMD_COLMOD register
|
||||
const esp_lcd_panel_vendor_init_cmd_t *init_cmds;
|
||||
uint16_t init_cmds_size;
|
||||
} nv3022b_panel_t;
|
||||
|
||||
esp_err_t esp_lcd_new_panel_nv3022b(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel)
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
nv3022b_panel_t *nv3022b = NULL;
|
||||
gpio_config_t io_conf = { 0 };
|
||||
|
||||
ESP_GOTO_ON_FALSE(io && panel_dev_config && ret_panel, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
||||
nv3022b = (nv3022b_panel_t *)calloc(1, sizeof(nv3022b_panel_t));
|
||||
ESP_GOTO_ON_FALSE(nv3022b, ESP_ERR_NO_MEM, err, TAG, "no mem for nv3022b panel");
|
||||
|
||||
if (panel_dev_config->reset_gpio_num >= 0) {
|
||||
io_conf.mode = GPIO_MODE_OUTPUT;
|
||||
io_conf.pin_bit_mask = 1ULL << panel_dev_config->reset_gpio_num;
|
||||
ESP_GOTO_ON_ERROR(gpio_config(&io_conf), err, TAG, "configure GPIO for RST line failed");
|
||||
}
|
||||
|
||||
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
switch (panel_dev_config->color_space) {
|
||||
case ESP_LCD_COLOR_SPACE_RGB:
|
||||
nv3022b->madctl_val = 0;
|
||||
break;
|
||||
case ESP_LCD_COLOR_SPACE_BGR:
|
||||
nv3022b->madctl_val |= LCD_CMD_BGR_BIT;
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported color space");
|
||||
break;
|
||||
}
|
||||
#else
|
||||
switch (panel_dev_config->rgb_endian) {
|
||||
case LCD_RGB_ENDIAN_RGB:
|
||||
nv3022b->madctl_val = 0;
|
||||
break;
|
||||
case LCD_RGB_ENDIAN_BGR:
|
||||
nv3022b->madctl_val |= LCD_CMD_BGR_BIT;
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported rgb endian");
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (panel_dev_config->bits_per_pixel) {
|
||||
case 12: // RGB444
|
||||
nv3022b->colmod_val = 0x33;
|
||||
nv3022b->fb_bits_per_pixel = 16;
|
||||
break;
|
||||
case 16: // RGB565
|
||||
nv3022b->colmod_val = 0x55;
|
||||
nv3022b->fb_bits_per_pixel = 16;
|
||||
break;
|
||||
case 18: // RGB666
|
||||
nv3022b->colmod_val = 0x66;
|
||||
// each color component (R/G/B) should occupy the 6 high bits of a byte, which means 3 full bytes are required for a pixel
|
||||
nv3022b->fb_bits_per_pixel = 24;
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported pixel width");
|
||||
break;
|
||||
}
|
||||
|
||||
nv3022b->io = io;
|
||||
nv3022b->reset_gpio_num = panel_dev_config->reset_gpio_num;
|
||||
nv3022b->reset_level = panel_dev_config->flags.reset_active_high;
|
||||
if (panel_dev_config->vendor_config) {
|
||||
nv3022b->init_cmds = ((esp_lcd_panel_vendor_config_t *)panel_dev_config->vendor_config)->init_cmds;
|
||||
nv3022b->init_cmds_size = ((esp_lcd_panel_vendor_config_t *)panel_dev_config->vendor_config)->init_cmds_size;
|
||||
}
|
||||
nv3022b->base.del = panel_nv3022b_del;
|
||||
nv3022b->base.reset = panel_nv3022b_reset;
|
||||
nv3022b->base.init = panel_nv3022b_init;
|
||||
nv3022b->base.draw_bitmap = panel_nv3022b_draw_bitmap;
|
||||
nv3022b->base.invert_color = panel_nv3022b_invert_color;
|
||||
nv3022b->base.set_gap = panel_nv3022b_set_gap;
|
||||
nv3022b->base.mirror = panel_nv3022b_mirror;
|
||||
nv3022b->base.swap_xy = panel_nv3022b_swap_xy;
|
||||
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
nv3022b->base.disp_off = panel_nv3022b_disp_on_off;
|
||||
#else
|
||||
nv3022b->base.disp_on_off = panel_nv3022b_disp_on_off;
|
||||
#endif
|
||||
*ret_panel = &(nv3022b->base);
|
||||
ESP_LOGD(TAG, "new nv3022b panel @%p", nv3022b);
|
||||
|
||||
ESP_LOGI(TAG, "LCD panel create success, version: %d.%d.%d", ESP_LCD_NV3022B_VER_MAJOR, ESP_LCD_NV3022B_VER_MINOR,
|
||||
ESP_LCD_NV3022B_VER_PATCH);
|
||||
|
||||
return ESP_OK;
|
||||
|
||||
err:
|
||||
if (nv3022b) {
|
||||
if (panel_dev_config->reset_gpio_num >= 0) {
|
||||
gpio_reset_pin(panel_dev_config->reset_gpio_num);
|
||||
}
|
||||
free(nv3022b);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t panel_nv3022b_del(esp_lcd_panel_t *panel)
|
||||
{
|
||||
nv3022b_panel_t *nv3022b = __containerof(panel, nv3022b_panel_t, base);
|
||||
|
||||
if (nv3022b->reset_gpio_num >= 0) {
|
||||
gpio_reset_pin(nv3022b->reset_gpio_num);
|
||||
}
|
||||
ESP_LOGD(TAG, "del nv3022b panel @%p", nv3022b);
|
||||
free(nv3022b);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_nv3022b_reset(esp_lcd_panel_t *panel)
|
||||
{
|
||||
nv3022b_panel_t *nv3022b = __containerof(panel, nv3022b_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = nv3022b->io;
|
||||
|
||||
// perform hardware reset
|
||||
if (nv3022b->reset_gpio_num >= 0) {
|
||||
gpio_set_level(nv3022b->reset_gpio_num, nv3022b->reset_level);
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
gpio_set_level(nv3022b->reset_gpio_num, !nv3022b->reset_level);
|
||||
vTaskDelay(pdMS_TO_TICKS(120));
|
||||
} else { // perform software reset
|
||||
esp_lcd_panel_io_tx_param(io, LCD_CMD_SWRESET, NULL, 0);
|
||||
vTaskDelay(pdMS_TO_TICKS(120));
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static const esp_lcd_panel_vendor_init_cmd_t vendor_specific_init_default[] = {
|
||||
// {cmd, { data }, data_size, delay_ms}
|
||||
{0xfd, (uint8_t []){0x06, 0x08}, 2, 0},
|
||||
{0x61, (uint8_t []){0x07, 0x07}, 2, 0},
|
||||
{0x73, (uint8_t []){0x70}, 1, 0},
|
||||
{0x73, (uint8_t []){0x00}, 1, 0},
|
||||
{0x62, (uint8_t []){0x00, 0x44, 0x40}, 3, 0},
|
||||
{0x65, (uint8_t []){0x08, 0x10, 0x21}, 3, 0},
|
||||
{0x66, (uint8_t []){0x08, 0x10, 0x21}, 3, 0},
|
||||
{0x67, (uint8_t []){0x21, 0x40}, 2, 0},
|
||||
{0x68, (uint8_t []){0x9f, 0x30, 0x27, 0x21}, 4, 0},
|
||||
{0xb1, (uint8_t []){0x0f, 0x02, 0x01}, 3, 0},
|
||||
{0xb4, (uint8_t []){0x01}, 1, 0},
|
||||
{0xb5, (uint8_t []){0x02, 0x02, 0x0a, 0x14}, 4, 0},
|
||||
{0xb6, (uint8_t []){0x44, 0x01, 0x9f, 0x00, 0x02}, 5, 0},
|
||||
{0xe6, (uint8_t []){0x00, 0xff}, 2, 0},
|
||||
{0xe7, (uint8_t []){0x01, 0x04, 0x03, 0x03, 0x00, 0x12}, 6, 0},
|
||||
{0xe8, (uint8_t []){0x00, 0x70, 0x00}, 3, 0},
|
||||
{0xec, (uint8_t []){0x52}, 1, 0},
|
||||
{0xdf, (uint8_t []){0x11}, 1, 0},
|
||||
{0xe0, (uint8_t []){0x06, 0x05, 0x0b, 0x12, 0x10, 0x10, 0x10, 0x15}, 8, 0},
|
||||
{0xe3, (uint8_t []){0x15, 0x10, 0x11, 0x0e, 0x12, 0x0d, 0x06, 0x06}, 8, 0},
|
||||
{0xe1, (uint8_t []){0x35, 0x75}, 2, 0},
|
||||
{0xe4, (uint8_t []){0x74, 0x35}, 2, 0},
|
||||
{0xe2, (uint8_t []){0x22, 0x22, 0x21, 0x35, 0x36, 0x3f}, 6, 0},
|
||||
{0xe5, (uint8_t []){0x3f, 0x35, 0x34, 0x21, 0x22, 0x22}, 6, 0},
|
||||
{0xf1, (uint8_t []){0x01, 0x01, 0x02}, 3, 0},
|
||||
{0xf6, (uint8_t []){0x09, 0x30, 0x00, 0x00}, 4, 0},
|
||||
{0xfd, (uint8_t []){0xfa, 0xfc}, 2, 0},
|
||||
{0x35, (uint8_t []){0x00}, 1, 0},
|
||||
{0x11, (uint8_t []){0x00}, 0, 200},
|
||||
{0x2a, (uint8_t []){0x00, 0x00, 0x00, 0xef}, 4, 0},
|
||||
{0x2b, (uint8_t []){0x00, 0x00, 0x01, 0x1b}, 4, 0},
|
||||
{0x29, (uint8_t []){0}, 0, 10},
|
||||
{0x2c, (uint8_t []){0}, 0, 0},
|
||||
};
|
||||
|
||||
static esp_err_t panel_nv3022b_init(esp_lcd_panel_t *panel)
|
||||
{
|
||||
nv3022b_panel_t *nv3022b = __containerof(panel, nv3022b_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = nv3022b->io;
|
||||
|
||||
// LCD goes into sleep mode and display will be turned off after power on reset, exit sleep mode first
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_SLPOUT, NULL, 0), TAG, "send command failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]) {
|
||||
nv3022b->madctl_val,
|
||||
}, 1), TAG, "send command failed");
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_COLMOD, (uint8_t[]) {
|
||||
nv3022b->colmod_val,
|
||||
}, 1), TAG, "send command failed");
|
||||
|
||||
const esp_lcd_panel_vendor_init_cmd_t *init_cmds = NULL;
|
||||
uint16_t init_cmds_size = 0;
|
||||
if (nv3022b->init_cmds) {
|
||||
init_cmds = nv3022b->init_cmds;
|
||||
init_cmds_size = nv3022b->init_cmds_size;
|
||||
} else {
|
||||
init_cmds = vendor_specific_init_default;
|
||||
init_cmds_size = sizeof(vendor_specific_init_default) / sizeof(esp_lcd_panel_vendor_init_cmd_t);
|
||||
}
|
||||
|
||||
bool is_cmd_overwritten = false;
|
||||
for (int i = 0; i < init_cmds_size; i++) {
|
||||
// Check if the command has been used or conflicts with the internal
|
||||
switch (init_cmds[i].cmd) {
|
||||
case LCD_CMD_MADCTL:
|
||||
is_cmd_overwritten = true;
|
||||
nv3022b->madctl_val = ((uint8_t *)init_cmds[i].data)[0];
|
||||
break;
|
||||
case LCD_CMD_COLMOD:
|
||||
is_cmd_overwritten = true;
|
||||
nv3022b->colmod_val = ((uint8_t *)init_cmds[i].data)[0];
|
||||
break;
|
||||
default:
|
||||
is_cmd_overwritten = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_cmd_overwritten) {
|
||||
ESP_LOGW(TAG, "The %02Xh command has been used and will be overwritten by external initialization sequence", init_cmds[i].cmd);
|
||||
}
|
||||
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, init_cmds[i].cmd, init_cmds[i].data, init_cmds[i].data_bytes), TAG, "send command failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(init_cmds[i].delay_ms));
|
||||
}
|
||||
ESP_LOGD(TAG, "send init commands success");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_nv3022b_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data)
|
||||
{
|
||||
nv3022b_panel_t *nv3022b = __containerof(panel, nv3022b_panel_t, base);
|
||||
assert((x_start < x_end) && (y_start < y_end) && "start position must be smaller than end position");
|
||||
esp_lcd_panel_io_handle_t io = nv3022b->io;
|
||||
|
||||
x_start += nv3022b->x_gap;
|
||||
x_end += nv3022b->x_gap;
|
||||
y_start += nv3022b->y_gap;
|
||||
y_end += nv3022b->y_gap;
|
||||
|
||||
// define an area of frame memory where MCU can access
|
||||
esp_lcd_panel_io_tx_param(io, LCD_CMD_CASET, (uint8_t[]) {
|
||||
(x_start >> 8) & 0xFF,
|
||||
x_start & 0xFF,
|
||||
((x_end - 1) >> 8) & 0xFF,
|
||||
(x_end - 1) & 0xFF,
|
||||
}, 4);
|
||||
esp_lcd_panel_io_tx_param(io, LCD_CMD_RASET, (uint8_t[]) {
|
||||
(y_start >> 8) & 0xFF,
|
||||
y_start & 0xFF,
|
||||
((y_end - 1) >> 8) & 0xFF,
|
||||
(y_end - 1) & 0xFF,
|
||||
}, 4);
|
||||
// transfer frame buffer
|
||||
size_t len = (x_end - x_start) * (y_end - y_start) * nv3022b->fb_bits_per_pixel / 8;
|
||||
esp_lcd_panel_io_tx_color(io, LCD_CMD_RAMWR, color_data, len);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_nv3022b_invert_color(esp_lcd_panel_t *panel, bool invert_color_data)
|
||||
{
|
||||
nv3022b_panel_t *nv3022b = __containerof(panel, nv3022b_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = nv3022b->io;
|
||||
int command = 0;
|
||||
if (invert_color_data) {
|
||||
command = LCD_CMD_INVON;
|
||||
} else {
|
||||
command = LCD_CMD_INVOFF;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, command, NULL, 0), TAG, "send command failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_nv3022b_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y)
|
||||
{
|
||||
nv3022b_panel_t *nv3022b = __containerof(panel, nv3022b_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = nv3022b->io;
|
||||
if (mirror_x) {
|
||||
nv3022b->madctl_val |= LCD_CMD_MX_BIT;
|
||||
} else {
|
||||
nv3022b->madctl_val &= ~LCD_CMD_MX_BIT;
|
||||
}
|
||||
if (mirror_y) {
|
||||
nv3022b->madctl_val |= LCD_CMD_MY_BIT;
|
||||
} else {
|
||||
nv3022b->madctl_val &= ~LCD_CMD_MY_BIT;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]) {
|
||||
nv3022b->madctl_val
|
||||
}, 1), TAG, "send command failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_nv3022b_swap_xy(esp_lcd_panel_t *panel, bool swap_axes)
|
||||
{
|
||||
nv3022b_panel_t *nv3022b = __containerof(panel, nv3022b_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = nv3022b->io;
|
||||
if (swap_axes) {
|
||||
nv3022b->madctl_val |= LCD_CMD_MV_BIT;
|
||||
} else {
|
||||
nv3022b->madctl_val &= ~LCD_CMD_MV_BIT;
|
||||
}
|
||||
esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]) {
|
||||
nv3022b->madctl_val
|
||||
}, 1);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_nv3022b_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap)
|
||||
{
|
||||
nv3022b_panel_t *nv3022b = __containerof(panel, nv3022b_panel_t, base);
|
||||
nv3022b->x_gap = x_gap;
|
||||
nv3022b->y_gap = y_gap;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_nv3022b_disp_on_off(esp_lcd_panel_t *panel, bool on_off)
|
||||
{
|
||||
nv3022b_panel_t *nv3022b = __containerof(panel, nv3022b_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = nv3022b->io;
|
||||
int command = 0;
|
||||
|
||||
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
on_off = !on_off;
|
||||
#endif
|
||||
|
||||
if (on_off) {
|
||||
command = LCD_CMD_DISPON;
|
||||
} else {
|
||||
command = LCD_CMD_DISPOFF;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, command, NULL, 0), TAG, "send command failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_LCD_NV3022B_VER_MAJOR (0)
|
||||
#define ESP_LCD_NV3022B_VER_MINOR (0)
|
||||
#define ESP_LCD_NV3022B_VER_PATCH (1)
|
||||
|
||||
/**
|
||||
* @brief Create LCD panel for model nv3022b
|
||||
*
|
||||
* @note Vendor specific initialization can be different between manufacturers, should consult the LCD supplier for initialization sequence code.
|
||||
*
|
||||
* @param[in] io LCD panel IO handle
|
||||
* @param[in] panel_dev_config general panel device configuration
|
||||
* @param[out] ret_panel Returned LCD panel handle
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG if parameter is invalid
|
||||
* - ESP_ERR_NO_MEM if out of memory
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t esp_lcd_new_panel_nv3022b(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel);
|
||||
|
||||
/**
|
||||
* @brief LCD panel bus configuration structure
|
||||
*
|
||||
* @param[in] sclk SPI clock pin number
|
||||
* @param[in] mosi SPI MOSI pin number
|
||||
* @param[in] max_trans_sz Maximum transfer size in bytes
|
||||
*
|
||||
*/
|
||||
#define NV3022B_PANEL_BUS_SPI_CONFIG(sclk, mosi, max_trans_sz) \
|
||||
{ \
|
||||
.sclk_io_num = sclk, \
|
||||
.mosi_io_num = mosi, \
|
||||
.miso_io_num = -1, \
|
||||
.quadhd_io_num = -1, \
|
||||
.quadwp_io_num = -1, \
|
||||
.max_transfer_sz = max_trans_sz, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief LCD panel IO configuration structure
|
||||
*
|
||||
* @param[in] cs SPI chip select pin number
|
||||
* @param[in] dc SPI data/command pin number
|
||||
* @param[in] cb Callback function when SPI transfer is done
|
||||
* @param[in] cb_ctx Callback function context
|
||||
*
|
||||
*/
|
||||
#define NV3022B_PANEL_IO_SPI_CONFIG(cs, dc, callback, callback_ctx) \
|
||||
{ \
|
||||
.cs_gpio_num = cs, \
|
||||
.dc_gpio_num = dc, \
|
||||
.spi_mode = 0, \
|
||||
.pclk_hz = 40 * 1000 * 1000, \
|
||||
.trans_queue_depth = 10, \
|
||||
.on_color_trans_done = callback, \
|
||||
.user_ctx = callback_ctx, \
|
||||
.lcd_cmd_bits = 8, \
|
||||
.lcd_param_bits = 8, \
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
+351
@@ -0,0 +1,351 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_lcd_panel_interface.h"
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
#include "esp_lcd_panel_ops.h"
|
||||
#include "esp_lcd_panel_commands.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "esp_lcd_custom_types.h"
|
||||
#include "esp_lcd_sh8601.h"
|
||||
|
||||
#define LCD_OPCODE_WRITE_CMD (0x02ULL)
|
||||
#define LCD_OPCODE_READ_CMD (0x03ULL)
|
||||
#define LCD_OPCODE_WRITE_COLOR (0x32ULL)
|
||||
|
||||
static const char *TAG = "sh8601";
|
||||
|
||||
static esp_err_t panel_sh8601_del(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_sh8601_reset(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_sh8601_init(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_sh8601_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data);
|
||||
static esp_err_t panel_sh8601_invert_color(esp_lcd_panel_t *panel, bool invert_color_data);
|
||||
static esp_err_t panel_sh8601_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y);
|
||||
static esp_err_t panel_sh8601_swap_xy(esp_lcd_panel_t *panel, bool swap_axes);
|
||||
static esp_err_t panel_sh8601_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap);
|
||||
static esp_err_t panel_sh8601_disp_on_off(esp_lcd_panel_t *panel, bool off);
|
||||
|
||||
typedef struct {
|
||||
esp_lcd_panel_t base;
|
||||
esp_lcd_panel_io_handle_t io;
|
||||
int reset_gpio_num;
|
||||
int x_gap;
|
||||
int y_gap;
|
||||
uint8_t fb_bits_per_pixel;
|
||||
uint8_t madctl_val; // save current value of LCD_CMD_MADCTL register
|
||||
uint8_t colmod_val; // save surrent value of LCD_CMD_COLMOD register
|
||||
const esp_lcd_panel_vendor_init_cmd_t *init_cmds;
|
||||
uint16_t init_cmds_size;
|
||||
struct {
|
||||
unsigned int use_qspi_interface: 1;
|
||||
unsigned int reset_level: 1;
|
||||
} flags;
|
||||
} sh8601_panel_t;
|
||||
|
||||
esp_err_t esp_lcd_new_panel_sh8601(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel)
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
ESP_RETURN_ON_FALSE(io && panel_dev_config && ret_panel, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
sh8601_panel_t *sh8601 = NULL;
|
||||
sh8601 = calloc(1, sizeof(sh8601_panel_t));
|
||||
ESP_GOTO_ON_FALSE(sh8601, ESP_ERR_NO_MEM, err, TAG, "no mem for sh8601 panel");
|
||||
|
||||
if (panel_dev_config->reset_gpio_num >= 0) {
|
||||
gpio_config_t io_conf = {
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pin_bit_mask = 1ULL << panel_dev_config->reset_gpio_num,
|
||||
};
|
||||
ESP_GOTO_ON_ERROR(gpio_config(&io_conf), err, TAG, "configure GPIO for RST line failed");
|
||||
}
|
||||
|
||||
switch (panel_dev_config->rgb_ele_order) {
|
||||
case LCD_RGB_ELEMENT_ORDER_RGB:
|
||||
sh8601->madctl_val = 0;
|
||||
break;
|
||||
case LCD_RGB_ELEMENT_ORDER_BGR:
|
||||
sh8601->madctl_val |= LCD_CMD_BGR_BIT;
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported color element order");
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t fb_bits_per_pixel = 0;
|
||||
switch (panel_dev_config->bits_per_pixel) {
|
||||
case 16: // RGB565
|
||||
sh8601->colmod_val = 0x55;
|
||||
fb_bits_per_pixel = 16;
|
||||
break;
|
||||
case 18: // RGB666
|
||||
sh8601->colmod_val = 0x66;
|
||||
// each color component (R/G/B) should occupy the 6 high bits of a byte, which means 3 full bytes are required for a pixel
|
||||
fb_bits_per_pixel = 24;
|
||||
break;
|
||||
case 24: // RGB888
|
||||
sh8601->colmod_val = 0x77;
|
||||
fb_bits_per_pixel = 24;
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported pixel width");
|
||||
break;
|
||||
}
|
||||
|
||||
sh8601->io = io;
|
||||
sh8601->reset_gpio_num = panel_dev_config->reset_gpio_num;
|
||||
sh8601->fb_bits_per_pixel = fb_bits_per_pixel;
|
||||
esp_lcd_panel_vendor_config_t *vendor_config = (esp_lcd_panel_vendor_config_t *)panel_dev_config->vendor_config;
|
||||
if (vendor_config) {
|
||||
sh8601->init_cmds = vendor_config->init_cmds;
|
||||
sh8601->init_cmds_size = vendor_config->init_cmds_size;
|
||||
sh8601->flags.use_qspi_interface = vendor_config->flags.use_qspi_interface;
|
||||
}
|
||||
sh8601->flags.reset_level = panel_dev_config->flags.reset_active_high;
|
||||
sh8601->base.del = panel_sh8601_del;
|
||||
sh8601->base.reset = panel_sh8601_reset;
|
||||
sh8601->base.init = panel_sh8601_init;
|
||||
sh8601->base.draw_bitmap = panel_sh8601_draw_bitmap;
|
||||
sh8601->base.invert_color = panel_sh8601_invert_color;
|
||||
sh8601->base.set_gap = panel_sh8601_set_gap;
|
||||
sh8601->base.mirror = panel_sh8601_mirror;
|
||||
sh8601->base.swap_xy = panel_sh8601_swap_xy;
|
||||
sh8601->base.disp_on_off = panel_sh8601_disp_on_off;
|
||||
*ret_panel = &(sh8601->base);
|
||||
ESP_LOGD(TAG, "new sh8601 panel @%p", sh8601);
|
||||
|
||||
ESP_LOGI(TAG, "LCD panel create success, version: %d.%d.%d", ESP_LCD_SH8601_VER_MAJOR, ESP_LCD_SH8601_VER_MINOR,
|
||||
ESP_LCD_SH8601_VER_PATCH);
|
||||
|
||||
return ESP_OK;
|
||||
|
||||
err:
|
||||
if (sh8601) {
|
||||
if (panel_dev_config->reset_gpio_num >= 0) {
|
||||
gpio_reset_pin(panel_dev_config->reset_gpio_num);
|
||||
}
|
||||
free(sh8601);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t tx_param(sh8601_panel_t *sh8601, esp_lcd_panel_io_handle_t io, int lcd_cmd, const void *param, size_t param_size)
|
||||
{
|
||||
if (sh8601->flags.use_qspi_interface) {
|
||||
lcd_cmd &= 0xff;
|
||||
lcd_cmd <<= 8;
|
||||
lcd_cmd |= LCD_OPCODE_WRITE_CMD << 24;
|
||||
}
|
||||
return esp_lcd_panel_io_tx_param(io, lcd_cmd, param, param_size);
|
||||
}
|
||||
|
||||
static esp_err_t tx_color(sh8601_panel_t *sh8601, esp_lcd_panel_io_handle_t io, int lcd_cmd, const void *param, size_t param_size)
|
||||
{
|
||||
if (sh8601->flags.use_qspi_interface) {
|
||||
lcd_cmd &= 0xff;
|
||||
lcd_cmd <<= 8;
|
||||
lcd_cmd |= LCD_OPCODE_WRITE_COLOR << 24;
|
||||
}
|
||||
return esp_lcd_panel_io_tx_color(io, lcd_cmd, param, param_size);
|
||||
}
|
||||
|
||||
static esp_err_t panel_sh8601_del(esp_lcd_panel_t *panel)
|
||||
{
|
||||
sh8601_panel_t *sh8601 = __containerof(panel, sh8601_panel_t, base);
|
||||
|
||||
if (sh8601->reset_gpio_num >= 0) {
|
||||
gpio_reset_pin(sh8601->reset_gpio_num);
|
||||
}
|
||||
ESP_LOGD(TAG, "del sh8601 panel @%p", sh8601);
|
||||
free(sh8601);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_sh8601_reset(esp_lcd_panel_t *panel)
|
||||
{
|
||||
sh8601_panel_t *sh8601 = __containerof(panel, sh8601_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = sh8601->io;
|
||||
|
||||
// Perform hardware reset
|
||||
if (sh8601->reset_gpio_num >= 0) {
|
||||
gpio_set_level(sh8601->reset_gpio_num, sh8601->flags.reset_level);
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
gpio_set_level(sh8601->reset_gpio_num, !sh8601->flags.reset_level);
|
||||
vTaskDelay(pdMS_TO_TICKS(150));
|
||||
} else { // Perform software reset
|
||||
ESP_RETURN_ON_ERROR(tx_param(sh8601, io, LCD_CMD_SWRESET, NULL, 0), TAG, "send command failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(80));
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static const esp_lcd_panel_vendor_init_cmd_t vendor_specific_init_default[] = {
|
||||
// {cmd, { data }, data_size, delay_ms}
|
||||
{0x44, (uint8_t []){0x00, 0xc8}, 2, 0},
|
||||
{0x35, (uint8_t []){0x00}, 0, 0},
|
||||
{0x53, (uint8_t []){0x20}, 1, 25},
|
||||
};
|
||||
|
||||
static esp_err_t panel_sh8601_init(esp_lcd_panel_t *panel)
|
||||
{
|
||||
sh8601_panel_t *sh8601 = __containerof(panel, sh8601_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = sh8601->io;
|
||||
const esp_lcd_panel_vendor_init_cmd_t *init_cmds = NULL;
|
||||
uint16_t init_cmds_size = 0;
|
||||
bool is_cmd_overwritten = false;
|
||||
|
||||
ESP_RETURN_ON_ERROR(tx_param(sh8601, io, LCD_CMD_MADCTL, (uint8_t[]) {
|
||||
sh8601->madctl_val,
|
||||
}, 1), TAG, "send command failed");
|
||||
ESP_RETURN_ON_ERROR(tx_param(sh8601, io, LCD_CMD_COLMOD, (uint8_t[]) {
|
||||
sh8601->colmod_val,
|
||||
}, 1), TAG, "send command failed");
|
||||
|
||||
// vendor specific initialization, it can be different between manufacturers
|
||||
// should consult the LCD supplier for initialization sequence code
|
||||
if (sh8601->init_cmds) {
|
||||
init_cmds = sh8601->init_cmds;
|
||||
init_cmds_size = sh8601->init_cmds_size;
|
||||
} else {
|
||||
init_cmds = vendor_specific_init_default;
|
||||
init_cmds_size = sizeof(vendor_specific_init_default) / sizeof(esp_lcd_panel_vendor_init_cmd_t);
|
||||
}
|
||||
|
||||
for (int i = 0; i < init_cmds_size; i++) {
|
||||
// Check if the command has been used or conflicts with the internal
|
||||
switch (init_cmds[i].cmd) {
|
||||
case LCD_CMD_MADCTL:
|
||||
is_cmd_overwritten = true;
|
||||
sh8601->madctl_val = ((uint8_t *)init_cmds[i].data)[0];
|
||||
break;
|
||||
case LCD_CMD_COLMOD:
|
||||
is_cmd_overwritten = true;
|
||||
sh8601->colmod_val = ((uint8_t *)init_cmds[i].data)[0];
|
||||
break;
|
||||
default:
|
||||
is_cmd_overwritten = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_cmd_overwritten) {
|
||||
ESP_LOGW(TAG, "The %02Xh command has been used and will be overwritten by external initialization sequence", init_cmds[i].cmd);
|
||||
}
|
||||
|
||||
ESP_RETURN_ON_ERROR(tx_param(sh8601, io, init_cmds[i].cmd, init_cmds[i].data, init_cmds[i].data_bytes), TAG,
|
||||
"send command failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(init_cmds[i].delay_ms));
|
||||
}
|
||||
ESP_LOGD(TAG, "send init commands success");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_sh8601_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data)
|
||||
{
|
||||
sh8601_panel_t *sh8601 = __containerof(panel, sh8601_panel_t, base);
|
||||
assert((x_start < x_end) && (y_start < y_end) && "start position must be smaller than end position");
|
||||
esp_lcd_panel_io_handle_t io = sh8601->io;
|
||||
|
||||
x_start += sh8601->x_gap;
|
||||
x_end += sh8601->x_gap;
|
||||
y_start += sh8601->y_gap;
|
||||
y_end += sh8601->y_gap;
|
||||
|
||||
// define an area of frame memory where MCU can access
|
||||
ESP_RETURN_ON_ERROR(tx_param(sh8601, io, LCD_CMD_CASET, (uint8_t[]) {
|
||||
(x_start >> 8) & 0xFF,
|
||||
x_start & 0xFF,
|
||||
((x_end - 1) >> 8) & 0xFF,
|
||||
(x_end - 1) & 0xFF,
|
||||
}, 4), TAG, "send command failed");
|
||||
ESP_RETURN_ON_ERROR(tx_param(sh8601, io, LCD_CMD_RASET, (uint8_t[]) {
|
||||
(y_start >> 8) & 0xFF,
|
||||
y_start & 0xFF,
|
||||
((y_end - 1) >> 8) & 0xFF,
|
||||
(y_end - 1) & 0xFF,
|
||||
}, 4), TAG, "send command failed");
|
||||
// transfer frame buffer
|
||||
size_t len = (x_end - x_start) * (y_end - y_start) * sh8601->fb_bits_per_pixel / 8;
|
||||
tx_color(sh8601, io, LCD_CMD_RAMWR, color_data, len);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_sh8601_invert_color(esp_lcd_panel_t *panel, bool invert_color_data)
|
||||
{
|
||||
sh8601_panel_t *sh8601 = __containerof(panel, sh8601_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = sh8601->io;
|
||||
int command = 0;
|
||||
if (invert_color_data) {
|
||||
command = LCD_CMD_INVON;
|
||||
} else {
|
||||
command = LCD_CMD_INVOFF;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(tx_param(sh8601, io, command, NULL, 0), TAG, "send command failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_sh8601_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y)
|
||||
{
|
||||
sh8601_panel_t *sh8601 = __containerof(panel, sh8601_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = sh8601->io;
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
if (mirror_x) {
|
||||
sh8601->madctl_val |= BIT(6);
|
||||
} else {
|
||||
sh8601->madctl_val &= ~BIT(6);
|
||||
}
|
||||
if (mirror_y) {
|
||||
ESP_LOGE(TAG, "mirror_y is not supported by this panel");
|
||||
ret = ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(tx_param(sh8601, io, LCD_CMD_MADCTL, (uint8_t[]) {
|
||||
sh8601->madctl_val
|
||||
}, 1), TAG, "send command failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t panel_sh8601_swap_xy(esp_lcd_panel_t *panel, bool swap_axes)
|
||||
{
|
||||
ESP_LOGE(TAG, "swap_xy is not supported by this panel");
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
static esp_err_t panel_sh8601_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap)
|
||||
{
|
||||
sh8601_panel_t *sh8601 = __containerof(panel, sh8601_panel_t, base);
|
||||
sh8601->x_gap = x_gap;
|
||||
sh8601->y_gap = y_gap;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_sh8601_disp_on_off(esp_lcd_panel_t *panel, bool on_off)
|
||||
{
|
||||
sh8601_panel_t *sh8601 = __containerof(panel, sh8601_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = sh8601->io;
|
||||
int command = 0;
|
||||
|
||||
if (on_off) {
|
||||
command = LCD_CMD_DISPON;
|
||||
} else {
|
||||
command = LCD_CMD_DISPOFF;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(tx_param(sh8601, io, command, NULL, 0), TAG, "send command failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_LCD_SH8601_VER_MAJOR (1)
|
||||
#define ESP_LCD_SH8601_VER_MINOR (0)
|
||||
#define ESP_LCD_SH8601_VER_PATCH (0)
|
||||
|
||||
/**
|
||||
* @brief Create LCD panel for model SH8601
|
||||
*
|
||||
* @param[in] io LCD panel IO handle
|
||||
* @param[in] panel_dev_config General panel device configuration (Use `vendor_config` to select QSPI interface or override default initialization commands)
|
||||
* @param[out] ret_panel Returned LCD panel handle
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - Otherwise: Fail
|
||||
*/
|
||||
esp_err_t esp_lcd_new_panel_sh8601(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel);
|
||||
|
||||
/**
|
||||
* @brief LCD panel bus configuration structure
|
||||
*
|
||||
*/
|
||||
#define SH8601_PANEL_BUS_SPI_CONFIG(sclk, mosi, max_trans_sz) \
|
||||
{ \
|
||||
.sclk_io_num = sclk, \
|
||||
.mosi_io_num = mosi, \
|
||||
.miso_io_num = -1, \
|
||||
.quadhd_io_num = -1, \
|
||||
.quadwp_io_num = -1, \
|
||||
.max_transfer_sz = max_trans_sz, \
|
||||
}
|
||||
#define SH8601_PANEL_BUS_QSPI_CONFIG(sclk, d0, d1, d2, d3, max_trans_sz) \
|
||||
{ \
|
||||
.sclk_io_num = sclk, \
|
||||
.data0_io_num = d0, \
|
||||
.data1_io_num = d1, \
|
||||
.data2_io_num = d2, \
|
||||
.data3_io_num = d3, \
|
||||
.max_transfer_sz = max_trans_sz, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief LCD panel IO configuration structure
|
||||
*
|
||||
*/
|
||||
#define SH8601_PANEL_IO_SPI_CONFIG(cs, dc, cb, cb_ctx) \
|
||||
{ \
|
||||
.cs_gpio_num = cs, \
|
||||
.dc_gpio_num = dc, \
|
||||
.spi_mode = 0, \
|
||||
.pclk_hz = 40 * 1000 * 1000, \
|
||||
.trans_queue_depth = 10, \
|
||||
.on_color_trans_done = cb, \
|
||||
.user_ctx = cb_ctx, \
|
||||
.lcd_cmd_bits = 8, \
|
||||
.lcd_param_bits = 8, \
|
||||
}
|
||||
#define SH8601_PANEL_IO_QSPI_CONFIG(cs, cb, cb_ctx) \
|
||||
{ \
|
||||
.cs_gpio_num = cs, \
|
||||
.dc_gpio_num = -1, \
|
||||
.spi_mode = 0, \
|
||||
.pclk_hz = 40 * 1000 * 1000, \
|
||||
.trans_queue_depth = 10, \
|
||||
.on_color_trans_done = cb, \
|
||||
.user_ctx = cb_ctx, \
|
||||
.lcd_cmd_bits = 32, \
|
||||
.lcd_param_bits = 8, \
|
||||
.flags = { \
|
||||
.quad_mode = true, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
+768
@@ -0,0 +1,768 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_lcd_panel_interface.h"
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
#include "esp_lcd_panel_ops.h"
|
||||
#include "esp_lcd_panel_commands.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "esp_lcd_custom_types.h"
|
||||
#include "esp_lcd_spd2010.h"
|
||||
|
||||
#define LCD_OPCODE_WRITE_CMD (0x02ULL)
|
||||
#define LCD_OPCODE_READ_CMD (0x0BULL)
|
||||
#define LCD_OPCODE_WRITE_COLOR (0x32ULL)
|
||||
|
||||
#define SPD2010_CMD_SET (0xFF)
|
||||
#define SPD2010_CMD_SET_BYTE0 (0x20)
|
||||
#define SPD2010_CMD_SET_BYTE1 (0x10)
|
||||
#define SPD2010_CMD_SET_USER (0x00)
|
||||
|
||||
static const char *TAG = "spd2010";
|
||||
|
||||
static esp_err_t panel_spd2010_del(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_spd2010_reset(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_spd2010_init(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_spd2010_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data);
|
||||
static esp_err_t panel_spd2010_invert_color(esp_lcd_panel_t *panel, bool invert_color_data);
|
||||
static esp_err_t panel_spd2010_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y);
|
||||
static esp_err_t panel_spd2010_swap_xy(esp_lcd_panel_t *panel, bool swap_axes);
|
||||
static esp_err_t panel_spd2010_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap);
|
||||
static esp_err_t panel_spd2010_disp_on_off(esp_lcd_panel_t *panel, bool off);
|
||||
|
||||
typedef struct {
|
||||
esp_lcd_panel_t base;
|
||||
esp_lcd_panel_io_handle_t io;
|
||||
int reset_gpio_num;
|
||||
int x_gap;
|
||||
int y_gap;
|
||||
uint8_t fb_bits_per_pixel;
|
||||
uint8_t madctl_val; // save current value of LCD_CMD_MADCTL register
|
||||
uint8_t colmod_val; // save current value of LCD_CMD_COLMOD register
|
||||
const esp_lcd_panel_vendor_init_cmd_t *init_cmds;
|
||||
uint16_t init_cmds_size;
|
||||
struct {
|
||||
unsigned int use_qspi_interface: 1;
|
||||
unsigned int reset_level: 1;
|
||||
} flags;
|
||||
} spd2010_panel_t;
|
||||
|
||||
esp_err_t esp_lcd_new_panel_spd2010(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel)
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
ESP_RETURN_ON_FALSE(io && panel_dev_config && ret_panel, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
spd2010_panel_t *spd2010 = NULL;
|
||||
spd2010 = calloc(1, sizeof(spd2010_panel_t));
|
||||
ESP_GOTO_ON_FALSE(spd2010, ESP_ERR_NO_MEM, err, TAG, "no mem for spd2010 panel");
|
||||
|
||||
if (panel_dev_config->reset_gpio_num >= 0) {
|
||||
gpio_config_t io_conf = {
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pin_bit_mask = 1ULL << panel_dev_config->reset_gpio_num,
|
||||
};
|
||||
ESP_GOTO_ON_ERROR(gpio_config(&io_conf), err, TAG, "configure GPIO for RST line failed");
|
||||
}
|
||||
|
||||
switch (panel_dev_config->rgb_ele_order) {
|
||||
case LCD_RGB_ELEMENT_ORDER_RGB:
|
||||
spd2010->madctl_val = 0;
|
||||
break;
|
||||
case LCD_RGB_ELEMENT_ORDER_BGR:
|
||||
spd2010->madctl_val |= LCD_CMD_BGR_BIT;
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported color element order");
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t fb_bits_per_pixel = 0;
|
||||
switch (panel_dev_config->bits_per_pixel) {
|
||||
case 16: // RGB565
|
||||
spd2010->colmod_val = 0x55;
|
||||
fb_bits_per_pixel = 16;
|
||||
break;
|
||||
case 18: // RGB666
|
||||
spd2010->colmod_val = 0x66;
|
||||
// each color component (R/G/B) should occupy the 6 high bits of a byte, which means 3 full bytes are required for a pixel
|
||||
fb_bits_per_pixel = 24;
|
||||
break;
|
||||
case 24: // RGB888
|
||||
spd2010->colmod_val = 0x77;
|
||||
fb_bits_per_pixel = 24;
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported pixel width");
|
||||
break;
|
||||
}
|
||||
|
||||
spd2010->io = io;
|
||||
spd2010->reset_gpio_num = panel_dev_config->reset_gpio_num;
|
||||
spd2010->fb_bits_per_pixel = fb_bits_per_pixel;
|
||||
esp_lcd_panel_vendor_config_t *vendor_config = (esp_lcd_panel_vendor_config_t *)panel_dev_config->vendor_config;
|
||||
if (vendor_config) {
|
||||
spd2010->init_cmds = vendor_config->init_cmds;
|
||||
spd2010->init_cmds_size = vendor_config->init_cmds_size;
|
||||
spd2010->flags.use_qspi_interface = vendor_config->flags.use_qspi_interface;
|
||||
}
|
||||
spd2010->flags.reset_level = panel_dev_config->flags.reset_active_high;
|
||||
spd2010->base.del = panel_spd2010_del;
|
||||
spd2010->base.reset = panel_spd2010_reset;
|
||||
spd2010->base.init = panel_spd2010_init;
|
||||
spd2010->base.draw_bitmap = panel_spd2010_draw_bitmap;
|
||||
spd2010->base.invert_color = panel_spd2010_invert_color;
|
||||
spd2010->base.set_gap = panel_spd2010_set_gap;
|
||||
spd2010->base.mirror = panel_spd2010_mirror;
|
||||
spd2010->base.swap_xy = panel_spd2010_swap_xy;
|
||||
spd2010->base.disp_on_off = panel_spd2010_disp_on_off;
|
||||
*ret_panel = &(spd2010->base);
|
||||
ESP_LOGD(TAG, "new spd2010 panel @%p", spd2010);
|
||||
|
||||
ESP_LOGI(TAG, "LCD panel create success, version: %d.%d.%d", ESP_LCD_SPD2010_VER_MAJOR, ESP_LCD_SPD2010_VER_MINOR,
|
||||
ESP_LCD_SPD2010_VER_PATCH);
|
||||
|
||||
return ESP_OK;
|
||||
|
||||
err:
|
||||
if (spd2010) {
|
||||
if (panel_dev_config->reset_gpio_num >= 0) {
|
||||
gpio_reset_pin(panel_dev_config->reset_gpio_num);
|
||||
}
|
||||
free(spd2010);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t tx_param(spd2010_panel_t *spd2010, esp_lcd_panel_io_handle_t io, int lcd_cmd, const void *param, size_t param_size)
|
||||
{
|
||||
if (spd2010->flags.use_qspi_interface) {
|
||||
lcd_cmd &= 0xff;
|
||||
lcd_cmd <<= 8;
|
||||
lcd_cmd |= LCD_OPCODE_WRITE_CMD << 24;
|
||||
}
|
||||
return esp_lcd_panel_io_tx_param(io, lcd_cmd, param, param_size);
|
||||
}
|
||||
|
||||
static esp_err_t tx_color(spd2010_panel_t *spd2010, esp_lcd_panel_io_handle_t io, int lcd_cmd, const void *param, size_t param_size)
|
||||
{
|
||||
if (spd2010->flags.use_qspi_interface) {
|
||||
lcd_cmd &= 0xff;
|
||||
lcd_cmd <<= 8;
|
||||
lcd_cmd |= LCD_OPCODE_WRITE_COLOR << 24;
|
||||
}
|
||||
return esp_lcd_panel_io_tx_color(io, lcd_cmd, param, param_size);
|
||||
}
|
||||
|
||||
static esp_err_t panel_spd2010_del(esp_lcd_panel_t *panel)
|
||||
{
|
||||
spd2010_panel_t *spd2010 = __containerof(panel, spd2010_panel_t, base);
|
||||
|
||||
if (spd2010->reset_gpio_num >= 0) {
|
||||
gpio_reset_pin(spd2010->reset_gpio_num);
|
||||
}
|
||||
ESP_LOGD(TAG, "del spd2010 panel @%p", spd2010);
|
||||
free(spd2010);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_spd2010_reset(esp_lcd_panel_t *panel)
|
||||
{
|
||||
spd2010_panel_t *spd2010 = __containerof(panel, spd2010_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = spd2010->io;
|
||||
|
||||
// Perform hardware reset
|
||||
if (spd2010->reset_gpio_num >= 0) {
|
||||
gpio_set_level(spd2010->reset_gpio_num, spd2010->flags.reset_level);
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
gpio_set_level(spd2010->reset_gpio_num, !spd2010->flags.reset_level);
|
||||
vTaskDelay(pdMS_TO_TICKS(120));
|
||||
} else { // Perform software reset
|
||||
ESP_RETURN_ON_ERROR(tx_param(spd2010, io, LCD_CMD_SWRESET, NULL, 0), TAG, "send command failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(20));
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static const esp_lcd_panel_vendor_init_cmd_t vendor_specific_init_default[] = {
|
||||
// {cmd, { data }, data_size, delay_ms}
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x10}, 3, 0},
|
||||
{0x0C, (uint8_t []){0x11}, 1, 0},
|
||||
{0x10, (uint8_t []){0x02}, 1, 0},
|
||||
{0x11, (uint8_t []){0x11}, 1, 0},
|
||||
{0x15, (uint8_t []){0x42}, 1, 0},
|
||||
{0x16, (uint8_t []){0x11}, 1, 0},
|
||||
{0x1A, (uint8_t []){0x02}, 1, 0},
|
||||
{0x1B, (uint8_t []){0x11}, 1, 0},
|
||||
{0x61, (uint8_t []){0x80}, 1, 0},
|
||||
{0x62, (uint8_t []){0x80}, 1, 0},
|
||||
{0x54, (uint8_t []){0x44}, 1, 0},
|
||||
{0x58, (uint8_t []){0x88}, 1, 0},
|
||||
{0x5C, (uint8_t []){0xcc}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x10}, 3, 0},
|
||||
{0x20, (uint8_t []){0x80}, 1, 0},
|
||||
{0x21, (uint8_t []){0x81}, 1, 0},
|
||||
{0x22, (uint8_t []){0x31}, 1, 0},
|
||||
{0x23, (uint8_t []){0x20}, 1, 0},
|
||||
{0x24, (uint8_t []){0x11}, 1, 0},
|
||||
{0x25, (uint8_t []){0x11}, 1, 0},
|
||||
{0x26, (uint8_t []){0x12}, 1, 0},
|
||||
{0x27, (uint8_t []){0x12}, 1, 0},
|
||||
{0x30, (uint8_t []){0x80}, 1, 0},
|
||||
{0x31, (uint8_t []){0x81}, 1, 0},
|
||||
{0x32, (uint8_t []){0x31}, 1, 0},
|
||||
{0x33, (uint8_t []){0x20}, 1, 0},
|
||||
{0x34, (uint8_t []){0x11}, 1, 0},
|
||||
{0x35, (uint8_t []){0x11}, 1, 0},
|
||||
{0x36, (uint8_t []){0x12}, 1, 0},
|
||||
{0x37, (uint8_t []){0x12}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x10}, 3, 0},
|
||||
{0x41, (uint8_t []){0x11}, 1, 0},
|
||||
{0x42, (uint8_t []){0x22}, 1, 0},
|
||||
{0x43, (uint8_t []){0x33}, 1, 0},
|
||||
{0x49, (uint8_t []){0x11}, 1, 0},
|
||||
{0x4A, (uint8_t []){0x22}, 1, 0},
|
||||
{0x4B, (uint8_t []){0x33}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x15}, 3, 0},
|
||||
{0x00, (uint8_t []){0x00}, 1, 0},
|
||||
{0x01, (uint8_t []){0x00}, 1, 0},
|
||||
{0x02, (uint8_t []){0x00}, 1, 0},
|
||||
{0x03, (uint8_t []){0x00}, 1, 0},
|
||||
{0x04, (uint8_t []){0x10}, 1, 0},
|
||||
{0x05, (uint8_t []){0x0C}, 1, 0},
|
||||
{0x06, (uint8_t []){0x23}, 1, 0},
|
||||
{0x07, (uint8_t []){0x22}, 1, 0},
|
||||
{0x08, (uint8_t []){0x21}, 1, 0},
|
||||
{0x09, (uint8_t []){0x20}, 1, 0},
|
||||
{0x0A, (uint8_t []){0x33}, 1, 0},
|
||||
{0x0B, (uint8_t []){0x32}, 1, 0},
|
||||
{0x0C, (uint8_t []){0x34}, 1, 0},
|
||||
{0x0D, (uint8_t []){0x35}, 1, 0},
|
||||
{0x0E, (uint8_t []){0x01}, 1, 0},
|
||||
{0x0F, (uint8_t []){0x01}, 1, 0},
|
||||
{0x20, (uint8_t []){0x00}, 1, 0},
|
||||
{0x21, (uint8_t []){0x00}, 1, 0},
|
||||
{0x22, (uint8_t []){0x00}, 1, 0},
|
||||
{0x23, (uint8_t []){0x00}, 1, 0},
|
||||
{0x24, (uint8_t []){0x0C}, 1, 0},
|
||||
{0x25, (uint8_t []){0x10}, 1, 0},
|
||||
{0x26, (uint8_t []){0x20}, 1, 0},
|
||||
{0x27, (uint8_t []){0x21}, 1, 0},
|
||||
{0x28, (uint8_t []){0x22}, 1, 0},
|
||||
{0x29, (uint8_t []){0x23}, 1, 0},
|
||||
{0x2A, (uint8_t []){0x33}, 1, 0},
|
||||
{0x2B, (uint8_t []){0x32}, 1, 0},
|
||||
{0x2C, (uint8_t []){0x34}, 1, 0},
|
||||
{0x2D, (uint8_t []){0x35}, 1, 0},
|
||||
{0x2E, (uint8_t []){0x01}, 1, 0},
|
||||
{0x2F, (uint8_t []){0x01}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x16}, 3, 0},
|
||||
{0x00, (uint8_t []){0x00}, 1, 0},
|
||||
{0x01, (uint8_t []){0x00}, 1, 0},
|
||||
{0x02, (uint8_t []){0x00}, 1, 0},
|
||||
{0x03, (uint8_t []){0x00}, 1, 0},
|
||||
{0x04, (uint8_t []){0x08}, 1, 0},
|
||||
{0x05, (uint8_t []){0x04}, 1, 0},
|
||||
{0x06, (uint8_t []){0x19}, 1, 0},
|
||||
{0x07, (uint8_t []){0x18}, 1, 0},
|
||||
{0x08, (uint8_t []){0x17}, 1, 0},
|
||||
{0x09, (uint8_t []){0x16}, 1, 0},
|
||||
{0x0A, (uint8_t []){0x33}, 1, 0},
|
||||
{0x0B, (uint8_t []){0x32}, 1, 0},
|
||||
{0x0C, (uint8_t []){0x34}, 1, 0},
|
||||
{0x0D, (uint8_t []){0x35}, 1, 0},
|
||||
{0x0E, (uint8_t []){0x01}, 1, 0},
|
||||
{0x0F, (uint8_t []){0x01}, 1, 0},
|
||||
{0x20, (uint8_t []){0x00}, 1, 0},
|
||||
{0x21, (uint8_t []){0x00}, 1, 0},
|
||||
{0x22, (uint8_t []){0x00}, 1, 0},
|
||||
{0x23, (uint8_t []){0x00}, 1, 0},
|
||||
{0x24, (uint8_t []){0x04}, 1, 0},
|
||||
{0x25, (uint8_t []){0x08}, 1, 0},
|
||||
{0x26, (uint8_t []){0x16}, 1, 0},
|
||||
{0x27, (uint8_t []){0x17}, 1, 0},
|
||||
{0x28, (uint8_t []){0x18}, 1, 0},
|
||||
{0x29, (uint8_t []){0x19}, 1, 0},
|
||||
{0x2A, (uint8_t []){0x33}, 1, 0},
|
||||
{0x2B, (uint8_t []){0x32}, 1, 0},
|
||||
{0x2C, (uint8_t []){0x34}, 1, 0},
|
||||
{0x2D, (uint8_t []){0x35}, 1, 0},
|
||||
{0x2E, (uint8_t []){0x01}, 1, 0},
|
||||
{0x2F, (uint8_t []){0x01}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x12}, 3, 0},
|
||||
{0x00, (uint8_t []){0x99}, 1, 0},
|
||||
{0x2A, (uint8_t []){0x28}, 1, 0},
|
||||
{0x2B, (uint8_t []){0x0f}, 1, 0},
|
||||
{0x2C, (uint8_t []){0x16}, 1, 0},
|
||||
{0x2D, (uint8_t []){0x28}, 1, 0},
|
||||
{0x2E, (uint8_t []){0x0f}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0xA0}, 3, 0},
|
||||
{0x08, (uint8_t []){0xdc}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x45}, 3, 0},
|
||||
{0x01, (uint8_t []){0x9C}, 1, 0},
|
||||
{0x03, (uint8_t []){0x9C}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x42}, 3, 0},
|
||||
{0x05, (uint8_t []){0x2c}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x11}, 3, 0},
|
||||
{0x50, (uint8_t []){0x01}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x00}, 3, 0},
|
||||
{0x2A, (uint8_t []){0x00, 0x00, 0x01, 0x9B}, 4, 0},
|
||||
{0x2B, (uint8_t []){0x00, 0x00, 0x01, 0x9B}, 4, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x40}, 3, 0},
|
||||
{0x86, (uint8_t []){0x00}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x00}, 3, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x12}, 3, 0},
|
||||
{0x0D, (uint8_t []){0x66}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x17}, 3, 0},
|
||||
{0x39, (uint8_t []){0x3c}, 1, 0},
|
||||
{0xff, (uint8_t []){0x20, 0x10, 0x31}, 3, 0},
|
||||
{0x38, (uint8_t []){0x03}, 1, 0},
|
||||
{0x39, (uint8_t []){0xf0}, 1, 0},
|
||||
{0x36, (uint8_t []){0x03}, 1, 0},
|
||||
{0x37, (uint8_t []){0xe8}, 1, 0},
|
||||
{0x34, (uint8_t []){0x03}, 1, 0},
|
||||
{0x35, (uint8_t []){0xCF}, 1, 0},
|
||||
{0x32, (uint8_t []){0x03}, 1, 0},
|
||||
{0x33, (uint8_t []){0xBA}, 1, 0},
|
||||
{0x30, (uint8_t []){0x03}, 1, 0},
|
||||
{0x31, (uint8_t []){0xA2}, 1, 0},
|
||||
{0x2e, (uint8_t []){0x03}, 1, 0},
|
||||
{0x2f, (uint8_t []){0x95}, 1, 0},
|
||||
{0x2c, (uint8_t []){0x03}, 1, 0},
|
||||
{0x2d, (uint8_t []){0x7e}, 1, 0},
|
||||
{0x2a, (uint8_t []){0x03}, 1, 0},
|
||||
{0x2b, (uint8_t []){0x62}, 1, 0},
|
||||
{0x28, (uint8_t []){0x03}, 1, 0},
|
||||
{0x29, (uint8_t []){0x44}, 1, 0},
|
||||
{0x26, (uint8_t []){0x02}, 1, 0},
|
||||
{0x27, (uint8_t []){0xfc}, 1, 0},
|
||||
{0x24, (uint8_t []){0x02}, 1, 0},
|
||||
{0x25, (uint8_t []){0xd0}, 1, 0},
|
||||
{0x22, (uint8_t []){0x02}, 1, 0},
|
||||
{0x23, (uint8_t []){0x98}, 1, 0},
|
||||
{0x20, (uint8_t []){0x02}, 1, 0},
|
||||
{0x21, (uint8_t []){0x6f}, 1, 0},
|
||||
{0x1e, (uint8_t []){0x02}, 1, 0},
|
||||
{0x1f, (uint8_t []){0x32}, 1, 0},
|
||||
{0x1c, (uint8_t []){0x01}, 1, 0},
|
||||
{0x1d, (uint8_t []){0xf6}, 1, 0},
|
||||
{0x1a, (uint8_t []){0x01}, 1, 0},
|
||||
{0x1b, (uint8_t []){0xb8}, 1, 0},
|
||||
{0x18, (uint8_t []){0x01}, 1, 0},
|
||||
{0x19, (uint8_t []){0x6E}, 1, 0},
|
||||
{0x16, (uint8_t []){0x01}, 1, 0},
|
||||
{0x17, (uint8_t []){0x41}, 1, 0},
|
||||
{0x14, (uint8_t []){0x00}, 1, 0},
|
||||
{0x15, (uint8_t []){0xfd}, 1, 0},
|
||||
{0x12, (uint8_t []){0x00}, 1, 0},
|
||||
{0x13, (uint8_t []){0xCf}, 1, 0},
|
||||
{0x10, (uint8_t []){0x00}, 1, 0},
|
||||
{0x11, (uint8_t []){0x98}, 1, 0},
|
||||
{0x0e, (uint8_t []){0x00}, 1, 0},
|
||||
{0x0f, (uint8_t []){0x89}, 1, 0},
|
||||
{0x0c, (uint8_t []){0x00}, 1, 0},
|
||||
{0x0d, (uint8_t []){0x79}, 1, 0},
|
||||
{0x0a, (uint8_t []){0x00}, 1, 0},
|
||||
{0x0b, (uint8_t []){0x67}, 1, 0},
|
||||
{0x08, (uint8_t []){0x00}, 1, 0},
|
||||
{0x09, (uint8_t []){0x55}, 1, 0},
|
||||
{0x06, (uint8_t []){0x00}, 1, 0},
|
||||
{0x07, (uint8_t []){0x3F}, 1, 0},
|
||||
{0x04, (uint8_t []){0x00}, 1, 0},
|
||||
{0x05, (uint8_t []){0x28}, 1, 0},
|
||||
{0x02, (uint8_t []){0x00}, 1, 0},
|
||||
{0x03, (uint8_t []){0x0E}, 1, 0},
|
||||
{0xff, (uint8_t []){0x20, 0x10, 0x00}, 3, 0},
|
||||
{0xff, (uint8_t []){0x20, 0x10, 0x32}, 3, 0},
|
||||
{0x38, (uint8_t []){0x03}, 1, 0},
|
||||
{0x39, (uint8_t []){0xf0}, 1, 0},
|
||||
{0x36, (uint8_t []){0x03}, 1, 0},
|
||||
{0x37, (uint8_t []){0xe8}, 1, 0},
|
||||
{0x34, (uint8_t []){0x03}, 1, 0},
|
||||
{0x35, (uint8_t []){0xCF}, 1, 0},
|
||||
{0x32, (uint8_t []){0x03}, 1, 0},
|
||||
{0x33, (uint8_t []){0xBA}, 1, 0},
|
||||
{0x30, (uint8_t []){0x03}, 1, 0},
|
||||
{0x31, (uint8_t []){0xA2}, 1, 0},
|
||||
{0x2e, (uint8_t []){0x03}, 1, 0},
|
||||
{0x2f, (uint8_t []){0x95}, 1, 0},
|
||||
{0x2c, (uint8_t []){0x03}, 1, 0},
|
||||
{0x2d, (uint8_t []){0x7e}, 1, 0},
|
||||
{0x2a, (uint8_t []){0x03}, 1, 0},
|
||||
{0x2b, (uint8_t []){0x62}, 1, 0},
|
||||
{0x28, (uint8_t []){0x03}, 1, 0},
|
||||
{0x29, (uint8_t []){0x44}, 1, 0},
|
||||
{0x26, (uint8_t []){0x02}, 1, 0},
|
||||
{0x27, (uint8_t []){0xfc}, 1, 0},
|
||||
{0x24, (uint8_t []){0x02}, 1, 0},
|
||||
{0x25, (uint8_t []){0xd0}, 1, 0},
|
||||
{0x22, (uint8_t []){0x02}, 1, 0},
|
||||
{0x23, (uint8_t []){0x98}, 1, 0},
|
||||
{0x20, (uint8_t []){0x02}, 1, 0},
|
||||
{0x21, (uint8_t []){0x6f}, 1, 0},
|
||||
{0x1e, (uint8_t []){0x02}, 1, 0},
|
||||
{0x1f, (uint8_t []){0x32}, 1, 0},
|
||||
{0x1c, (uint8_t []){0x01}, 1, 0},
|
||||
{0x1d, (uint8_t []){0xf6}, 1, 0},
|
||||
{0x1a, (uint8_t []){0x01}, 1, 0},
|
||||
{0x1b, (uint8_t []){0xb8}, 1, 0},
|
||||
{0x18, (uint8_t []){0x01}, 1, 0},
|
||||
{0x19, (uint8_t []){0x6E}, 1, 0},
|
||||
{0x16, (uint8_t []){0x01}, 1, 0},
|
||||
{0x17, (uint8_t []){0x41}, 1, 0},
|
||||
{0x14, (uint8_t []){0x00}, 1, 0},
|
||||
{0x15, (uint8_t []){0xfd}, 1, 0},
|
||||
{0x12, (uint8_t []){0x00}, 1, 0},
|
||||
{0x13, (uint8_t []){0xCf}, 1, 0},
|
||||
{0x10, (uint8_t []){0x00}, 1, 0},
|
||||
{0x11, (uint8_t []){0x98}, 1, 0},
|
||||
{0x0e, (uint8_t []){0x00}, 1, 0},
|
||||
{0x0f, (uint8_t []){0x89}, 1, 0},
|
||||
{0x0c, (uint8_t []){0x00}, 1, 0},
|
||||
{0x0d, (uint8_t []){0x79}, 1, 0},
|
||||
{0x0a, (uint8_t []){0x00}, 1, 0},
|
||||
{0x0b, (uint8_t []){0x67}, 1, 0},
|
||||
{0x08, (uint8_t []){0x00}, 1, 0},
|
||||
{0x09, (uint8_t []){0x55}, 1, 0},
|
||||
{0x06, (uint8_t []){0x00}, 1, 0},
|
||||
{0x07, (uint8_t []){0x3F}, 1, 0},
|
||||
{0x04, (uint8_t []){0x00}, 1, 0},
|
||||
{0x05, (uint8_t []){0x28}, 1, 0},
|
||||
{0x02, (uint8_t []){0x00}, 1, 0},
|
||||
{0x03, (uint8_t []){0x0E}, 1, 0},
|
||||
{0xff, (uint8_t []){0x20, 0x10, 0x00}, 3, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x11}, 3, 0},
|
||||
{0x60, (uint8_t []){0x01}, 1, 0},
|
||||
{0x65, (uint8_t []){0x03}, 1, 0},
|
||||
{0x66, (uint8_t []){0x38}, 1, 0},
|
||||
{0x67, (uint8_t []){0x04}, 1, 0},
|
||||
{0x68, (uint8_t []){0x34}, 1, 0},
|
||||
{0x69, (uint8_t []){0x03}, 1, 0},
|
||||
{0x61, (uint8_t []){0x03}, 1, 0},
|
||||
{0x62, (uint8_t []){0x38}, 1, 0},
|
||||
{0x63, (uint8_t []){0x04}, 1, 0},
|
||||
{0x64, (uint8_t []){0x34}, 1, 0},
|
||||
{0x0A, (uint8_t []){0x11}, 1, 0},
|
||||
{0x0B, (uint8_t []){0x20}, 1, 0},
|
||||
{0x0c, (uint8_t []){0x20}, 1, 0},
|
||||
{0x55, (uint8_t []){0x06}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x42}, 3, 0},
|
||||
{0x05, (uint8_t []){0x3D}, 1, 0},
|
||||
{0x06, (uint8_t []){0x03}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x00}, 3, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x12}, 3, 0},
|
||||
{0x1F, (uint8_t []){0xDC}, 1, 0},
|
||||
{0xff, (uint8_t []){0x20, 0x10, 0x17}, 3, 0},
|
||||
{0x11, (uint8_t []){0xAA}, 1, 0},
|
||||
{0x16, (uint8_t []){0x12}, 1, 0},
|
||||
{0x0B, (uint8_t []){0xC3}, 1, 0},
|
||||
{0x10, (uint8_t []){0x0E}, 1, 0},
|
||||
{0x14, (uint8_t []){0xAA}, 1, 0},
|
||||
{0x18, (uint8_t []){0xA0}, 1, 0},
|
||||
{0x1A, (uint8_t []){0x80}, 1, 0},
|
||||
{0x1F, (uint8_t []){0x80}, 1, 0},
|
||||
{0xff, (uint8_t []){0x20, 0x10, 0x11}, 3, 0},
|
||||
{0x30, (uint8_t []){0xEE}, 1, 0},
|
||||
{0xff, (uint8_t []){0x20, 0x10, 0x12}, 3, 0},
|
||||
{0x15, (uint8_t []){0x0F}, 1, 0},
|
||||
{0xff, (uint8_t []){0x20, 0x10, 0x2D}, 3, 0},
|
||||
{0x01, (uint8_t []){0x3E}, 1, 0},
|
||||
{0xff, (uint8_t []){0x20, 0x10, 0x40}, 3, 0},
|
||||
{0x83, (uint8_t []){0xC4}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x12}, 3, 0},
|
||||
{0x00, (uint8_t []){0xCC}, 1, 0},
|
||||
{0x36, (uint8_t []){0xA0}, 1, 0},
|
||||
{0x2A, (uint8_t []){0x2D}, 1, 0},
|
||||
{0x2B, (uint8_t []){0x1e}, 1, 0},
|
||||
{0x2C, (uint8_t []){0x26}, 1, 0},
|
||||
{0x2D, (uint8_t []){0x2D}, 1, 0},
|
||||
{0x2E, (uint8_t []){0x1e}, 1, 0},
|
||||
{0x1F, (uint8_t []){0xE6}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0xA0}, 3, 0},
|
||||
{0x08, (uint8_t []){0xE6}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x12}, 3, 0},
|
||||
{0x10, (uint8_t []){0x0F}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x18}, 3, 0},
|
||||
{0x01, (uint8_t []){0x01}, 1, 0},
|
||||
{0x00, (uint8_t []){0x1E}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x43}, 3, 0},
|
||||
{0x03, (uint8_t []){0x04}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x18}, 3, 0},
|
||||
{0x3A, (uint8_t []){0x01}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x50}, 3, 0},
|
||||
{0x05, (uint8_t []){0x08}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x00}, 3, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x50}, 3, 0},
|
||||
{0x00, (uint8_t []){0xA6}, 1, 0},
|
||||
{0x01, (uint8_t []){0xA6}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x00}, 3, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x50}, 3, 0},
|
||||
{0x08, (uint8_t []){0x55}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x00}, 3, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x10}, 3, 0},
|
||||
{0x0B, (uint8_t []){0x43}, 1, 0},
|
||||
{0x0C, (uint8_t []){0x12}, 1, 0},
|
||||
{0x10, (uint8_t []){0x01}, 1, 0},
|
||||
{0x11, (uint8_t []){0x12}, 1, 0},
|
||||
{0x15, (uint8_t []){0x00}, 1, 0},
|
||||
{0x16, (uint8_t []){0x00}, 1, 0},
|
||||
{0x1A, (uint8_t []){0x00}, 1, 0},
|
||||
{0x1B, (uint8_t []){0x00}, 1, 0},
|
||||
{0x61, (uint8_t []){0x00}, 1, 0},
|
||||
{0x62, (uint8_t []){0x00}, 1, 0},
|
||||
{0x51, (uint8_t []){0x11}, 1, 0},
|
||||
{0x55, (uint8_t []){0x55}, 1, 0},
|
||||
{0x58, (uint8_t []){0x00}, 1, 0},
|
||||
{0x5C, (uint8_t []){0x00}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x10}, 3, 0},
|
||||
{0x20, (uint8_t []){0x81}, 1, 0},
|
||||
{0x21, (uint8_t []){0x82}, 1, 0},
|
||||
{0x22, (uint8_t []){0x72}, 1, 0},
|
||||
{0x30, (uint8_t []){0x00}, 1, 0},
|
||||
{0x31, (uint8_t []){0x00}, 1, 0},
|
||||
{0x32, (uint8_t []){0x00}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x10}, 3, 0},
|
||||
{0x44, (uint8_t []){0x44}, 1, 0},
|
||||
{0x45, (uint8_t []){0x55}, 1, 0},
|
||||
{0x46, (uint8_t []){0x66}, 1, 0},
|
||||
{0x47, (uint8_t []){0x77}, 1, 0},
|
||||
{0x49, (uint8_t []){0x00}, 1, 0},
|
||||
{0x4A, (uint8_t []){0x00}, 1, 0},
|
||||
{0x4B, (uint8_t []){0x00}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x17}, 3, 0},
|
||||
{0x37, (uint8_t []){0x00}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x15}, 3, 0},
|
||||
{0x04, (uint8_t []){0x08}, 1, 0},
|
||||
{0x05, (uint8_t []){0x04}, 1, 0},
|
||||
{0x06, (uint8_t []){0x1C}, 1, 0},
|
||||
{0x07, (uint8_t []){0x1A}, 1, 0},
|
||||
{0x08, (uint8_t []){0x18}, 1, 0},
|
||||
{0x09, (uint8_t []){0x16}, 1, 0},
|
||||
{0x24, (uint8_t []){0x05}, 1, 0},
|
||||
{0x25, (uint8_t []){0x09}, 1, 0},
|
||||
{0x26, (uint8_t []){0x17}, 1, 0},
|
||||
{0x27, (uint8_t []){0x19}, 1, 0},
|
||||
{0x28, (uint8_t []){0x1B}, 1, 0},
|
||||
{0x29, (uint8_t []){0x1D}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x16}, 3, 0},
|
||||
{0x04, (uint8_t []){0x09}, 1, 0},
|
||||
{0x05, (uint8_t []){0x05}, 1, 0},
|
||||
{0x06, (uint8_t []){0x1D}, 1, 0},
|
||||
{0x07, (uint8_t []){0x1B}, 1, 0},
|
||||
{0x08, (uint8_t []){0x19}, 1, 0},
|
||||
{0x09, (uint8_t []){0x17}, 1, 0},
|
||||
{0x24, (uint8_t []){0x04}, 1, 0},
|
||||
{0x25, (uint8_t []){0x08}, 1, 0},
|
||||
{0x26, (uint8_t []){0x16}, 1, 0},
|
||||
{0x27, (uint8_t []){0x18}, 1, 0},
|
||||
{0x28, (uint8_t []){0x1A}, 1, 0},
|
||||
{0x29, (uint8_t []){0x1C}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x18}, 3, 0},
|
||||
{0x1F, (uint8_t []){0x02}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x11}, 3, 0},
|
||||
{0x15, (uint8_t []){0x99}, 1, 0},
|
||||
{0x16, (uint8_t []){0x99}, 1, 0},
|
||||
{0x1C, (uint8_t []){0x88}, 1, 0},
|
||||
{0x1D, (uint8_t []){0x88}, 1, 0},
|
||||
{0x1E, (uint8_t []){0x88}, 1, 0},
|
||||
{0x13, (uint8_t []){0xf0}, 1, 0},
|
||||
{0x14, (uint8_t []){0x34}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x12}, 3, 0},
|
||||
{0x12, (uint8_t []){0x89}, 1, 0},
|
||||
{0x06, (uint8_t []){0x06}, 1, 0},
|
||||
{0x18, (uint8_t []){0x00}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x11}, 3, 0},
|
||||
{0x0A, (uint8_t []){0x00}, 1, 0},
|
||||
{0x0B, (uint8_t []){0xF0}, 1, 0},
|
||||
{0x0c, (uint8_t []){0xF0}, 1, 0},
|
||||
{0x6A, (uint8_t []){0x10}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x00}, 3, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x11}, 3, 0},
|
||||
{0x08, (uint8_t []){0x70}, 1, 0},
|
||||
{0x09, (uint8_t []){0x00}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x00}, 3, 0},
|
||||
{0x35, (uint8_t []){0x00}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x12}, 3, 0},
|
||||
{0x21, (uint8_t []){0x70}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x2D}, 3, 0},
|
||||
{0x02, (uint8_t []){0x00}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x20, 0x10, 0x00}, 3, 0},
|
||||
{0x11, (uint8_t []){0x00}, 0, 120},
|
||||
};
|
||||
|
||||
static esp_err_t panel_spd2010_init(esp_lcd_panel_t *panel)
|
||||
{
|
||||
spd2010_panel_t *spd2010 = __containerof(panel, spd2010_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = spd2010->io;
|
||||
const esp_lcd_panel_vendor_init_cmd_t *init_cmds = NULL;
|
||||
uint16_t init_cmds_size = 0;
|
||||
bool is_user_set = true;
|
||||
bool is_cmd_overwritten = false;
|
||||
|
||||
ESP_RETURN_ON_ERROR(tx_param(spd2010, io, SPD2010_CMD_SET, (uint8_t[]) {
|
||||
SPD2010_CMD_SET_BYTE0, SPD2010_CMD_SET_BYTE1, SPD2010_CMD_SET_USER
|
||||
}, 3), TAG, "send command failed");
|
||||
ESP_RETURN_ON_ERROR(tx_param(spd2010, io, LCD_CMD_MADCTL, (uint8_t[]) {
|
||||
spd2010->madctl_val,
|
||||
}, 1), TAG, "send command failed");
|
||||
ESP_RETURN_ON_ERROR(tx_param(spd2010, io, LCD_CMD_COLMOD, (uint8_t[]) {
|
||||
spd2010->colmod_val,
|
||||
}, 1), TAG, "send command failed");
|
||||
|
||||
// vendor specific initialization, it can be different between manufacturers
|
||||
// should consult the LCD supplier for initialization sequence code
|
||||
if (spd2010->init_cmds) {
|
||||
init_cmds = spd2010->init_cmds;
|
||||
init_cmds_size = spd2010->init_cmds_size;
|
||||
} else {
|
||||
init_cmds = vendor_specific_init_default;
|
||||
init_cmds_size = sizeof(vendor_specific_init_default) / sizeof(esp_lcd_panel_vendor_init_cmd_t);
|
||||
}
|
||||
|
||||
for (int i = 0; i < init_cmds_size; i++) {
|
||||
// Check if the command has been used or conflicts with the internal only when command2 is disable
|
||||
if (is_user_set && (init_cmds[i].data_bytes > 0)) {
|
||||
switch (init_cmds[i].cmd) {
|
||||
case LCD_CMD_MADCTL:
|
||||
is_cmd_overwritten = true;
|
||||
spd2010->madctl_val = ((uint8_t *)init_cmds[i].data)[0];
|
||||
break;
|
||||
case LCD_CMD_COLMOD:
|
||||
is_cmd_overwritten = true;
|
||||
spd2010->colmod_val = ((uint8_t *)init_cmds[i].data)[0];
|
||||
break;
|
||||
default:
|
||||
is_cmd_overwritten = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_cmd_overwritten) {
|
||||
is_cmd_overwritten = false;
|
||||
ESP_LOGW(TAG, "The %02Xh command has been used and will be overwritten by external initialization sequence",
|
||||
init_cmds[i].cmd);
|
||||
}
|
||||
}
|
||||
|
||||
// Send command
|
||||
ESP_RETURN_ON_ERROR(tx_param(spd2010, io, init_cmds[i].cmd, init_cmds[i].data, init_cmds[i].data_bytes), TAG,
|
||||
"send command failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(init_cmds[i].delay_ms));
|
||||
|
||||
// Check if the current cmd is the "command set" cmd
|
||||
if ((init_cmds[i].cmd == SPD2010_CMD_SET) && (init_cmds[i].data_bytes > 2)) {
|
||||
is_user_set = (((uint8_t *)init_cmds[i].data)[2] == SPD2010_CMD_SET_USER);
|
||||
}
|
||||
}
|
||||
ESP_LOGD(TAG, "send init commands success");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_spd2010_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data)
|
||||
{
|
||||
spd2010_panel_t *spd2010 = __containerof(panel, spd2010_panel_t, base);
|
||||
assert((x_start < x_end) && (y_start < y_end) && "start position must be smaller than end position");
|
||||
esp_lcd_panel_io_handle_t io = spd2010->io;
|
||||
|
||||
x_start += spd2010->x_gap;
|
||||
x_end += spd2010->x_gap;
|
||||
y_start += spd2010->y_gap;
|
||||
y_end += spd2010->y_gap;
|
||||
|
||||
// define an area of frame memory where MCU can access
|
||||
ESP_RETURN_ON_ERROR(tx_param(spd2010, io, LCD_CMD_CASET, (uint8_t[]) {
|
||||
(x_start >> 8) & 0xFF,
|
||||
x_start & 0xFF,
|
||||
((x_end - 1) >> 8) & 0xFF,
|
||||
(x_end - 1) & 0xFF,
|
||||
}, 4), TAG, "send command failed");
|
||||
ESP_RETURN_ON_ERROR(tx_param(spd2010, io, LCD_CMD_RASET, (uint8_t[]) {
|
||||
(y_start >> 8) & 0xFF,
|
||||
y_start & 0xFF,
|
||||
((y_end - 1) >> 8) & 0xFF,
|
||||
(y_end - 1) & 0xFF,
|
||||
}, 4), TAG, "send command failed");
|
||||
// transfer frame buffer
|
||||
size_t len = (x_end - x_start) * (y_end - y_start) * spd2010->fb_bits_per_pixel / 8;
|
||||
ESP_RETURN_ON_ERROR(tx_color(spd2010, io, LCD_CMD_RAMWR, color_data, len), TAG, "send color failed");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_spd2010_invert_color(esp_lcd_panel_t *panel, bool invert_color_data)
|
||||
{
|
||||
spd2010_panel_t *spd2010 = __containerof(panel, spd2010_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = spd2010->io;
|
||||
int command = 0;
|
||||
if (invert_color_data) {
|
||||
command = LCD_CMD_INVON;
|
||||
} else {
|
||||
command = LCD_CMD_INVOFF;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(tx_param(spd2010, io, command, NULL, 0), TAG, "send command failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_spd2010_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y)
|
||||
{
|
||||
spd2010_panel_t *spd2010 = __containerof(panel, spd2010_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = spd2010->io;
|
||||
if (mirror_x) {
|
||||
spd2010->madctl_val |= BIT(1);
|
||||
} else {
|
||||
spd2010->madctl_val &= ~BIT(1);
|
||||
}
|
||||
if (mirror_y) {
|
||||
spd2010->madctl_val |= BIT(0);
|
||||
} else {
|
||||
spd2010->madctl_val &= ~BIT(0);
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(tx_param(spd2010, io, LCD_CMD_MADCTL, (uint8_t[]) {
|
||||
spd2010->madctl_val
|
||||
}, 1), TAG, "send command failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_spd2010_swap_xy(esp_lcd_panel_t *panel, bool swap_axes)
|
||||
{
|
||||
ESP_LOGE(TAG, "swap_xy is not supported by this panel");
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
static esp_err_t panel_spd2010_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap)
|
||||
{
|
||||
spd2010_panel_t *spd2010 = __containerof(panel, spd2010_panel_t, base);
|
||||
spd2010->x_gap = x_gap;
|
||||
spd2010->y_gap = y_gap;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_spd2010_disp_on_off(esp_lcd_panel_t *panel, bool on_off)
|
||||
{
|
||||
spd2010_panel_t *spd2010 = __containerof(panel, spd2010_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = spd2010->io;
|
||||
int command = 0;
|
||||
|
||||
if (on_off) {
|
||||
command = LCD_CMD_DISPON;
|
||||
} else {
|
||||
command = LCD_CMD_DISPOFF;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(tx_param(spd2010, io, command, NULL, 0), TAG, "send command failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_LCD_SPD2010_VER_MAJOR (1)
|
||||
#define ESP_LCD_SPD2010_VER_MINOR (0)
|
||||
#define ESP_LCD_SPD2010_VER_PATCH (1)
|
||||
|
||||
/**
|
||||
* @brief Create LCD panel for model SPD2010
|
||||
*
|
||||
* @param[in] io LCD panel IO handle
|
||||
* @param[in] panel_dev_config General panel device configuration (Use `vendor_config` to select QSPI interface or override default initialization commands)
|
||||
* @param[out] ret_panel Returned LCD panel handle
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - Otherwise: Fail
|
||||
*/
|
||||
esp_err_t esp_lcd_new_panel_spd2010(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel);
|
||||
|
||||
/**
|
||||
* @brief LCD panel bus configuration structure
|
||||
*
|
||||
*/
|
||||
#define SPD2010_PANEL_BUS_SPI_CONFIG(sclk, mosi, max_trans_sz) \
|
||||
{ \
|
||||
.sclk_io_num = sclk, \
|
||||
.mosi_io_num = mosi, \
|
||||
.miso_io_num = -1, \
|
||||
.quadhd_io_num = -1, \
|
||||
.quadwp_io_num = -1, \
|
||||
.max_transfer_sz = max_trans_sz, \
|
||||
}
|
||||
#define SPD2010_PANEL_BUS_QSPI_CONFIG(sclk, d0, d1, d2, d3, max_trans_sz) \
|
||||
{ \
|
||||
.sclk_io_num = sclk, \
|
||||
.data0_io_num = d0, \
|
||||
.data1_io_num = d1, \
|
||||
.data2_io_num = d2, \
|
||||
.data3_io_num = d3, \
|
||||
.max_transfer_sz = max_trans_sz, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief LCD panel IO configuration structure
|
||||
*
|
||||
*/
|
||||
#define SPD2010_PANEL_IO_SPI_CONFIG(cs, dc, cb, cb_ctx) \
|
||||
{ \
|
||||
.cs_gpio_num = cs, \
|
||||
.dc_gpio_num = dc, \
|
||||
.spi_mode = 3, \
|
||||
.pclk_hz = 80 * 1000 * 1000, \
|
||||
.trans_queue_depth = 10, \
|
||||
.on_color_trans_done = cb, \
|
||||
.user_ctx = cb_ctx, \
|
||||
.lcd_cmd_bits = 8, \
|
||||
.lcd_param_bits = 8, \
|
||||
}
|
||||
#define SPD2010_PANEL_IO_QSPI_CONFIG(cs, cb, cb_ctx) \
|
||||
{ \
|
||||
.cs_gpio_num = cs, \
|
||||
.dc_gpio_num = -1, \
|
||||
.spi_mode = 3, \
|
||||
.pclk_hz = 20 * 1000 * 1000, \
|
||||
.trans_queue_depth = 10, \
|
||||
.on_color_trans_done = cb, \
|
||||
.user_ctx = cb_ctx, \
|
||||
.lcd_cmd_bits = 32, \
|
||||
.lcd_param_bits = 8, \
|
||||
.flags = { \
|
||||
.quad_mode = true, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
+404
@@ -0,0 +1,404 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if SOC_LCD_RGB_SUPPORTED
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_lcd_panel_commands.h"
|
||||
#include "esp_lcd_panel_interface.h"
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "esp_lcd_panel_rgb.h"
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "esp_lcd_custom_types.h"
|
||||
#include "esp_lcd_st7701.h"
|
||||
|
||||
#define ST7701_CMD_SDIR (0xC7)
|
||||
#define ST7701_CMD_SS_BIT (1 << 2)
|
||||
|
||||
#define ST7701_CMD_CND2BKxSEL (0xFF)
|
||||
#define ST7701_CMD_BKxSEL_BYTE0 (0x77)
|
||||
#define ST7701_CMD_BKxSEL_BYTE1 (0x01)
|
||||
#define ST7701_CMD_BKxSEL_BYTE2 (0x00)
|
||||
#define ST7701_CMD_BKxSEL_BYTE3 (0x00)
|
||||
#define ST7701_CMD_CN2_BIT (1 << 4)
|
||||
#define ST7701_CMD_BKxSEL_BK0 (0x00)
|
||||
#define ST7701_CMD_BKxSEL_BK1 (0x01)
|
||||
#define ST7701_CMD_BKxSEL_BK2 (0x03)
|
||||
|
||||
typedef struct {
|
||||
esp_lcd_panel_io_handle_t io;
|
||||
int reset_gpio_num;
|
||||
uint8_t madctl_val; // Save current value of LCD_CMD_MADCTL register
|
||||
uint8_t colmod_val; // Save current value of LCD_CMD_COLMOD register
|
||||
const esp_lcd_panel_vendor_init_cmd_t *init_cmds;
|
||||
uint16_t init_cmds_size;
|
||||
struct {
|
||||
unsigned int mirror_by_cmd: 1;
|
||||
unsigned int auto_del_panel_io: 1;
|
||||
unsigned int display_on_off_use_cmd: 1;
|
||||
unsigned int reset_level: 1;
|
||||
} flags;
|
||||
// To save the original functions of RGB panel
|
||||
esp_err_t (*init)(esp_lcd_panel_t *panel);
|
||||
esp_err_t (*del)(esp_lcd_panel_t *panel);
|
||||
esp_err_t (*reset)(esp_lcd_panel_t *panel);
|
||||
esp_err_t (*mirror)(esp_lcd_panel_t *panel, bool x_axis, bool y_axis);
|
||||
esp_err_t (*disp_on_off)(esp_lcd_panel_t *panel, bool on_off);
|
||||
} st7701_panel_t;
|
||||
|
||||
static const char *TAG = "st7701";
|
||||
|
||||
static esp_err_t panel_st7701_send_init_cmds(st7701_panel_t *st7701);
|
||||
|
||||
static esp_err_t panel_st7701_init(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_st7701_del(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_st7701_reset(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_st7701_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y);
|
||||
static esp_err_t panel_st7701_disp_on_off(esp_lcd_panel_t *panel, bool off);
|
||||
|
||||
esp_err_t esp_lcd_new_panel_st7701(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config,
|
||||
esp_lcd_panel_handle_t *ret_panel)
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
ESP_RETURN_ON_FALSE(io && panel_dev_config && ret_panel, ESP_ERR_INVALID_ARG, TAG, "invalid arguments");
|
||||
esp_lcd_panel_vendor_config_t *vendor_config = (esp_lcd_panel_vendor_config_t *)panel_dev_config->vendor_config;
|
||||
ESP_RETURN_ON_FALSE(vendor_config && vendor_config->rgb_config, ESP_ERR_INVALID_ARG, TAG, "`verndor_config` and `rgb_config` are necessary");
|
||||
ESP_RETURN_ON_FALSE(!vendor_config->flags.auto_del_panel_io || !vendor_config->flags.mirror_by_cmd,
|
||||
ESP_ERR_INVALID_ARG, TAG, "`mirror_by_cmd` and `auto_del_panel_io` cannot work together");
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
st7701_panel_t *st7701 = (st7701_panel_t *)calloc(1, sizeof(st7701_panel_t));
|
||||
ESP_RETURN_ON_FALSE(st7701, ESP_ERR_NO_MEM, TAG, "no mem for st7701 panel");
|
||||
|
||||
if (panel_dev_config->reset_gpio_num >= 0) {
|
||||
gpio_config_t io_conf = {
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pin_bit_mask = 1ULL << panel_dev_config->reset_gpio_num,
|
||||
};
|
||||
ESP_GOTO_ON_ERROR(gpio_config(&io_conf), err, TAG, "configure GPIO for RST line failed");
|
||||
}
|
||||
|
||||
switch (panel_dev_config->rgb_ele_order) {
|
||||
case LCD_RGB_ELEMENT_ORDER_RGB:
|
||||
st7701->madctl_val = 0;
|
||||
break;
|
||||
case LCD_RGB_ELEMENT_ORDER_BGR:
|
||||
st7701->madctl_val |= LCD_CMD_BGR_BIT;
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported color element order");
|
||||
break;
|
||||
}
|
||||
|
||||
st7701->colmod_val = 0;
|
||||
switch (panel_dev_config->bits_per_pixel) {
|
||||
case 16: // RGB565
|
||||
st7701->colmod_val = 0x50;
|
||||
break;
|
||||
case 18: // RGB666
|
||||
st7701->colmod_val = 0x60;
|
||||
break;
|
||||
case 24: // RGB888
|
||||
st7701->colmod_val = 0x70;
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported pixel width");
|
||||
break;
|
||||
}
|
||||
|
||||
st7701->io = io;
|
||||
st7701->init_cmds = vendor_config->init_cmds;
|
||||
st7701->init_cmds_size = vendor_config->init_cmds_size;
|
||||
st7701->reset_gpio_num = panel_dev_config->reset_gpio_num;
|
||||
st7701->flags.mirror_by_cmd = vendor_config->flags.mirror_by_cmd;
|
||||
st7701->flags.display_on_off_use_cmd = (vendor_config->rgb_config->disp_gpio_num >= 0) ? 0 : 1;
|
||||
st7701->flags.auto_del_panel_io = vendor_config->flags.auto_del_panel_io;
|
||||
st7701->flags.reset_level = panel_dev_config->flags.reset_active_high;
|
||||
|
||||
if (st7701->flags.auto_del_panel_io) {
|
||||
if (st7701->reset_gpio_num >= 0) { // Perform hardware reset
|
||||
gpio_set_level(st7701->reset_gpio_num, st7701->flags.reset_level);
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
gpio_set_level(st7701->reset_gpio_num, !st7701->flags.reset_level);
|
||||
} else { // Perform software reset
|
||||
ESP_GOTO_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_SWRESET, NULL, 0), err, TAG, "send command failed");
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(120));
|
||||
|
||||
/**
|
||||
* In order to enable the 3-wire SPI interface pins (such as SDA and SCK) to share other pins of the RGB interface
|
||||
* (such as HSYNC) and save GPIOs, we need to send LCD initialization commands via the 3-wire SPI interface before
|
||||
* `esp_lcd_new_rgb_panel()` is called.
|
||||
*/
|
||||
ESP_GOTO_ON_ERROR(panel_st7701_send_init_cmds(st7701), err, TAG, "send init commands failed");
|
||||
// After sending the initialization commands, the 3-wire SPI interface can be deleted
|
||||
ESP_GOTO_ON_ERROR(esp_lcd_panel_io_del(io), err, TAG, "delete panel IO failed");
|
||||
st7701->io = NULL;
|
||||
ESP_LOGD(TAG, "delete panel IO");
|
||||
}
|
||||
|
||||
// Create RGB panel
|
||||
ESP_GOTO_ON_ERROR(esp_lcd_new_rgb_panel(vendor_config->rgb_config, ret_panel), err, TAG, "create RGB panel failed");
|
||||
ESP_LOGD(TAG, "new RGB panel @%p", *ret_panel);
|
||||
|
||||
// Save the original functions of RGB panel
|
||||
st7701->init = (*ret_panel)->init;
|
||||
st7701->del = (*ret_panel)->del;
|
||||
st7701->reset = (*ret_panel)->reset;
|
||||
st7701->mirror = (*ret_panel)->mirror;
|
||||
st7701->disp_on_off = (*ret_panel)->disp_on_off;
|
||||
// Overwrite the functions of RGB panel
|
||||
(*ret_panel)->init = panel_st7701_init;
|
||||
(*ret_panel)->del = panel_st7701_del;
|
||||
(*ret_panel)->reset = panel_st7701_reset;
|
||||
(*ret_panel)->mirror = panel_st7701_mirror;
|
||||
(*ret_panel)->disp_on_off = panel_st7701_disp_on_off;
|
||||
(*ret_panel)->user_data = st7701;
|
||||
ESP_LOGD(TAG, "new st7701 panel @%p", st7701);
|
||||
|
||||
ESP_LOGI(TAG, "LCD panel create success, version: %d.%d.%d", ESP_LCD_ST7701_VER_MAJOR, ESP_LCD_ST7701_VER_MINOR,
|
||||
ESP_LCD_ST7701_VER_PATCH);
|
||||
|
||||
return ESP_OK;
|
||||
|
||||
err:
|
||||
if (st7701) {
|
||||
if (panel_dev_config->reset_gpio_num >= 0) {
|
||||
gpio_reset_pin(panel_dev_config->reset_gpio_num);
|
||||
}
|
||||
free(st7701);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const esp_lcd_panel_vendor_init_cmd_t vendor_specific_init_default[] = {
|
||||
// {cmd, { data }, data_size, delay_ms}
|
||||
{0xFF, (uint8_t []){0x77, 0x01, 0x00, 0x00, 0x13}, 5, 0},
|
||||
{0xEF, (uint8_t []){0x08}, 1, 0},
|
||||
{0xFF, (uint8_t []){0x77, 0x01, 0x00, 0x00, 0x10}, 5, 0},
|
||||
{0xC0, (uint8_t []){0x3B, 0x00}, 2, 0},
|
||||
{0xC1, (uint8_t []){0x10, 0x02}, 2, 0},
|
||||
{0xC2, (uint8_t []){0x20, 0x06}, 2, 0},
|
||||
{0xCC, (uint8_t []){0x10}, 1, 0},
|
||||
{0xB0, (uint8_t []){0x00, 0x13, 0x5A, 0x0F, 0x12, 0x07, 0x09, 0x08, 0x08, 0x24, 0x07, 0x13, 0x12, 0x6B, 0x73, 0xFF}, 16, 0},
|
||||
{0xB1, (uint8_t []){0x00, 0x13, 0x5A, 0x0F, 0x12, 0x07, 0x09, 0x08, 0x08, 0x24, 0x07, 0x13, 0x12, 0x6B, 0x73, 0xFF}, 16, 0},
|
||||
{0xFF, (uint8_t []){0x77, 0x01, 0x00, 0x00, 0x11}, 5, 0},
|
||||
{0xB0, (uint8_t []){0x8D}, 1, 0},
|
||||
{0xB1, (uint8_t []){0x48}, 1, 0},
|
||||
{0xB2, (uint8_t []){0x89}, 1, 0},
|
||||
{0xB3, (uint8_t []){0x80}, 1, 0},
|
||||
{0xB5, (uint8_t []){0x49}, 1, 0},
|
||||
{0xB7, (uint8_t []){0x85}, 1, 0},
|
||||
{0xB8, (uint8_t []){0x32}, 1, 0},
|
||||
{0xC1, (uint8_t []){0x78}, 1, 0},
|
||||
{0xC2, (uint8_t []){0x78}, 1, 0},
|
||||
{0xD0, (uint8_t []){0x88}, 1, 100},
|
||||
{0xE0, (uint8_t []){0x00, 0x00, 0x02}, 3, 0},
|
||||
{0xE1, (uint8_t []){0x05, 0xC0, 0x07, 0xC0, 0x04, 0xC0, 0x06, 0xC0, 0x00, 0x44, 0x44}, 11, 0},
|
||||
{0xE2, (uint8_t []){0x00, 0x00, 0x33, 0x33, 0x01, 0xC0, 0x00, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x00}, 13, 0},
|
||||
{0xE3, (uint8_t []){0x00, 0x00, 0x11, 0x11}, 4, 0},
|
||||
{0xE4, (uint8_t []){0x44, 0x44}, 2, 0},
|
||||
{0xE5, (uint8_t []){0x0D, 0xF1, 0x10, 0x98, 0x0F, 0xF3, 0x10, 0x98, 0x09, 0xED, 0x10, 0x98, 0x0B, 0xEF, 0x10, 0x98}, 16, 0},
|
||||
{0xE6, (uint8_t []){0x00, 0x00, 0x11, 0x11}, 4, 0},
|
||||
{0xE7, (uint8_t []){0x44, 0x44}, 2, 0},
|
||||
{0xE8, (uint8_t []){0x0C, 0xF0, 0x10, 0x98, 0x0E, 0xF2, 0x10, 0x98, 0x08, 0xEC, 0x10, 0x98, 0x0A, 0xEE, 0x10, 0x98}, 16, 0},
|
||||
{0xEB, (uint8_t []){0x00, 0x01, 0xE4, 0xE4, 0x44, 0x88, 0x00}, 7, 0},
|
||||
{0xED, (uint8_t []){0xFF, 0x04, 0x56, 0x7F, 0xBA, 0x2F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF2, 0xAB, 0xF7, 0x65, 0x40, 0xFF}, 16, 0},
|
||||
{0xEF, (uint8_t []){0x10, 0x0D, 0x04, 0x08, 0x3F, 0x1F}, 6, 0},
|
||||
{0xFF, (uint8_t []){0x77, 0x01, 0x00, 0x00, 0x00}, 5, 0},
|
||||
{0x11, (uint8_t []){0x00}, 0, 120},
|
||||
{0x29, (uint8_t []){0x00}, 0, 0},
|
||||
};
|
||||
|
||||
static esp_err_t panel_st7701_send_init_cmds(st7701_panel_t *st7701)
|
||||
{
|
||||
esp_lcd_panel_io_handle_t io = st7701->io;
|
||||
const esp_lcd_panel_vendor_init_cmd_t *init_cmds = NULL;
|
||||
uint16_t init_cmds_size = 0;
|
||||
bool is_command2_disable = true;
|
||||
bool is_cmd_overwritten = false;
|
||||
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, ST7701_CMD_CND2BKxSEL, (uint8_t []) {
|
||||
ST7701_CMD_BKxSEL_BYTE0, ST7701_CMD_BKxSEL_BYTE1, ST7701_CMD_BKxSEL_BYTE2, ST7701_CMD_BKxSEL_BYTE3, 0x00
|
||||
}, 5), TAG, "Write cmd failed");
|
||||
// Set color format
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t []) {
|
||||
st7701->madctl_val
|
||||
}, 1), TAG, "Write cmd failed");
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_COLMOD, (uint8_t []) {
|
||||
st7701->colmod_val
|
||||
}, 1), TAG, "Write cmd failed");
|
||||
|
||||
// vendor specific initialization, it can be different between manufacturers
|
||||
// should consult the LCD supplier for initialization sequence code
|
||||
if (st7701->init_cmds) {
|
||||
init_cmds = st7701->init_cmds;
|
||||
init_cmds_size = st7701->init_cmds_size;
|
||||
} else {
|
||||
init_cmds = vendor_specific_init_default;
|
||||
init_cmds_size = sizeof(vendor_specific_init_default) / sizeof(esp_lcd_panel_vendor_init_cmd_t);
|
||||
}
|
||||
|
||||
for (int i = 0; i < init_cmds_size; i++) {
|
||||
// Check if the command has been used or conflicts with the internal only when command2 is disable
|
||||
if (is_command2_disable && (init_cmds[i].data_bytes > 0)) {
|
||||
switch (init_cmds[i].cmd) {
|
||||
case LCD_CMD_MADCTL:
|
||||
is_cmd_overwritten = true;
|
||||
st7701->madctl_val = ((uint8_t *)init_cmds[i].data)[0];
|
||||
break;
|
||||
case LCD_CMD_COLMOD:
|
||||
is_cmd_overwritten = true;
|
||||
st7701->colmod_val = ((uint8_t *)init_cmds[i].data)[0];
|
||||
break;
|
||||
default:
|
||||
is_cmd_overwritten = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_cmd_overwritten) {
|
||||
is_cmd_overwritten = false;
|
||||
ESP_LOGW(TAG, "The %02Xh command has been used and will be overwritten by external initialization sequence",
|
||||
init_cmds[i].cmd);
|
||||
}
|
||||
}
|
||||
|
||||
// Send command
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, init_cmds[i].cmd, init_cmds[i].data, init_cmds[i].data_bytes),
|
||||
TAG, "send command failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(init_cmds[i].delay_ms));
|
||||
|
||||
// Check if the current cmd is the command2 disable cmd
|
||||
if ((init_cmds[i].cmd == ST7701_CMD_CND2BKxSEL) && (init_cmds[i].data_bytes > 4)) {
|
||||
is_command2_disable = !(((uint8_t *)init_cmds[i].data)[4] & ST7701_CMD_CN2_BIT);
|
||||
}
|
||||
}
|
||||
ESP_LOGD(TAG, "send init commands success");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_st7701_init(esp_lcd_panel_t *panel)
|
||||
{
|
||||
st7701_panel_t *st7701 = (st7701_panel_t *)panel->user_data;
|
||||
|
||||
if (!st7701->flags.auto_del_panel_io) {
|
||||
ESP_RETURN_ON_ERROR(panel_st7701_send_init_cmds(st7701), TAG, "send init commands failed");
|
||||
}
|
||||
// Init RGB panel
|
||||
ESP_RETURN_ON_ERROR(st7701->init(panel), TAG, "init RGB panel failed");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_st7701_del(esp_lcd_panel_t *panel)
|
||||
{
|
||||
st7701_panel_t *st7701 = (st7701_panel_t *)panel->user_data;
|
||||
|
||||
if (st7701->reset_gpio_num >= 0) {
|
||||
gpio_reset_pin(st7701->reset_gpio_num);
|
||||
}
|
||||
// Delete RGB panel
|
||||
st7701->del(panel);
|
||||
free(st7701);
|
||||
ESP_LOGD(TAG, "del st7701 panel @%p", st7701);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_st7701_reset(esp_lcd_panel_t *panel)
|
||||
{
|
||||
st7701_panel_t *st7701 = (st7701_panel_t *)panel->user_data;
|
||||
esp_lcd_panel_io_handle_t io = st7701->io;
|
||||
|
||||
// Perform hardware reset
|
||||
if (st7701->reset_gpio_num >= 0) {
|
||||
gpio_set_level(st7701->reset_gpio_num, st7701->flags.reset_level);
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
gpio_set_level(st7701->reset_gpio_num, !st7701->flags.reset_level);
|
||||
vTaskDelay(pdMS_TO_TICKS(120));
|
||||
} else if (io) { // Perform software reset
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_SWRESET, NULL, 0), TAG, "send command failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(120));
|
||||
}
|
||||
// Reset RGB panel
|
||||
ESP_RETURN_ON_ERROR(st7701->reset(panel), TAG, "reset RGB panel failed");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_st7701_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y)
|
||||
{
|
||||
st7701_panel_t *st7701 = (st7701_panel_t *)panel->user_data;
|
||||
esp_lcd_panel_io_handle_t io = st7701->io;
|
||||
uint8_t sdir_val = 0;
|
||||
|
||||
if (st7701->flags.mirror_by_cmd) {
|
||||
ESP_RETURN_ON_FALSE(io, ESP_FAIL, TAG, "Panel IO is deleted, cannot send command");
|
||||
// Control mirror through LCD command
|
||||
if (mirror_x) {
|
||||
sdir_val = ST7701_CMD_SS_BIT;
|
||||
} else {
|
||||
sdir_val = 0;
|
||||
}
|
||||
if (mirror_y) {
|
||||
st7701->madctl_val |= LCD_CMD_ML_BIT;
|
||||
} else {
|
||||
st7701->madctl_val &= ~LCD_CMD_ML_BIT;
|
||||
}
|
||||
|
||||
// Enable the Command2 BK0
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, ST7701_CMD_CND2BKxSEL, (uint8_t []) {
|
||||
ST7701_CMD_BKxSEL_BYTE0, ST7701_CMD_BKxSEL_BYTE1, ST7701_CMD_BKxSEL_BYTE2, ST7701_CMD_BKxSEL_BYTE3,
|
||||
ST7701_CMD_BKxSEL_BK0 | ST7701_CMD_CN2_BIT,
|
||||
}, 5), TAG, "send command failed");
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, ST7701_CMD_SDIR, (uint8_t[]) {
|
||||
sdir_val,
|
||||
}, 1), TAG, "send command failed");;
|
||||
|
||||
// Disable Command2
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, ST7701_CMD_CND2BKxSEL, (uint8_t []) {
|
||||
ST7701_CMD_BKxSEL_BYTE0, ST7701_CMD_BKxSEL_BYTE1, ST7701_CMD_BKxSEL_BYTE2, ST7701_CMD_BKxSEL_BYTE3, 0,
|
||||
}, 5), TAG, "send command failed");
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]) {
|
||||
st7701->madctl_val,
|
||||
}, 1), TAG, "send command failed");;
|
||||
} else {
|
||||
// Control mirror through RGB panel
|
||||
ESP_RETURN_ON_ERROR(st7701->mirror(panel, mirror_x, mirror_y), TAG, "RGB panel mirror failed");
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_st7701_disp_on_off(esp_lcd_panel_t *panel, bool on_off)
|
||||
{
|
||||
st7701_panel_t *st7701 = (st7701_panel_t *)panel->user_data;
|
||||
esp_lcd_panel_io_handle_t io = st7701->io;
|
||||
int command = 0;
|
||||
|
||||
if (st7701->flags.display_on_off_use_cmd) {
|
||||
ESP_RETURN_ON_FALSE(io, ESP_FAIL, TAG, "Panel IO is deleted, cannot send command");
|
||||
// Control display on/off through LCD command
|
||||
if (on_off) {
|
||||
command = LCD_CMD_DISPON;
|
||||
} else {
|
||||
command = LCD_CMD_DISPOFF;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, command, NULL, 0), TAG, "send command failed");
|
||||
} else {
|
||||
// Control display on/off through display control signal
|
||||
ESP_RETURN_ON_ERROR(st7701->disp_on_off(panel, on_off), TAG, "RGB panel disp_on_off failed");
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* SOC_LCD_RGB_SUPPORTED */
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if SOC_LCD_RGB_SUPPORTED
|
||||
#include <stdint.h>
|
||||
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
#include "esp_lcd_panel_rgb.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_LCD_ST7701_VER_MAJOR (1)
|
||||
#define ESP_LCD_ST7701_VER_MINOR (0)
|
||||
#define ESP_LCD_ST7701_VER_PATCH (1)
|
||||
|
||||
/**
|
||||
* @brief Create LCD panel for model ST7701
|
||||
*
|
||||
* @note When `auto_del_panel_io` is set to 1, this function will first initialize the ST7701 with vendor specific initialization and then calls `esp_lcd_new_rgb_panel()` to create an RGB LCD panel. And the `esp_lcd_panel_init()` function will only initialize RGB.
|
||||
* @note When `auto_del_panel_io` is set to 0, this function will only call `esp_lcd_new_rgb_panel()` to create an RGB LCD panel. And the `esp_lcd_panel_init()` function will initialize both the ST7701 and RGB.
|
||||
* @note Vendor specific initialization can be different between manufacturers, should consult the LCD supplier for initialization sequence code.
|
||||
*
|
||||
* @param[in] io LCD panel IO handle
|
||||
* @param[in] panel_dev_config General panel device configuration (`vendor_config` and `rgb_config` are necessary)
|
||||
* @param[out] ret_panel Returned LCD panel handle
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG if parameter is invalid
|
||||
* - ESP_OK on success
|
||||
* - Otherwise on fail
|
||||
*/
|
||||
esp_err_t esp_lcd_new_panel_st7701(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config,
|
||||
esp_lcd_panel_handle_t *ret_panel);
|
||||
|
||||
/**
|
||||
* @brief 3-wire SPI panel IO configuration structure
|
||||
*
|
||||
* @param[in] line_cfg SPI line configuration
|
||||
* @param[in] scl_active_edge SCL signal active edge, 0: rising edge, 1: falling edge
|
||||
*
|
||||
*/
|
||||
#define ST7701_PANEL_IO_3WIRE_SPI_CONFIG(line_cfg, scl_active_edge) \
|
||||
{ \
|
||||
.line_config = line_cfg, \
|
||||
.expect_clk_speed = PANEL_IO_3WIRE_SPI_CLK_MAX, \
|
||||
.spi_mode = scl_active_edge ? 1 : 0, \
|
||||
.lcd_cmd_bytes = 1, \
|
||||
.lcd_param_bytes = 1, \
|
||||
.flags = { \
|
||||
.use_dc_bit = 1, \
|
||||
.dc_zero_on_data = 0, \
|
||||
.lsb_first = 0, \
|
||||
.cs_high_active = 0, \
|
||||
.del_keep_cs_inactive = 1, \
|
||||
}, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief RGB timing structure
|
||||
*
|
||||
* @note refresh_rate = (pclk_hz * data_width) / (h_res + hsync_pulse_width + hsync_back_porch + hsync_front_porch)
|
||||
* / (v_res + vsync_pulse_width + vsync_back_porch + vsync_front_porch)
|
||||
* / bits_per_pixel
|
||||
*
|
||||
*/
|
||||
#define ST7701_480_480_PANEL_60HZ_RGB_TIMING() \
|
||||
{ \
|
||||
.pclk_hz = 16 * 1000 * 1000, \
|
||||
.h_res = 480, \
|
||||
.v_res = 480, \
|
||||
.hsync_pulse_width = 10, \
|
||||
.hsync_back_porch = 10, \
|
||||
.hsync_front_porch = 20, \
|
||||
.vsync_pulse_width = 10, \
|
||||
.vsync_back_porch = 10, \
|
||||
.vsync_front_porch = 10, \
|
||||
.flags.pclk_active_neg = false, \
|
||||
}
|
||||
#endif /* SOC_LCD_RGB_SUPPORTED */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
+337
@@ -0,0 +1,337 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_lcd_panel_interface.h"
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
#include "esp_lcd_panel_ops.h"
|
||||
#include "esp_lcd_panel_commands.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
|
||||
#include "esp_lcd_custom_types.h"
|
||||
#include "esp_lcd_st7789.h"
|
||||
|
||||
static const char *TAG = "st7789";
|
||||
|
||||
static esp_err_t panel_st7789_del(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_st7789_reset(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_st7789_init(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_st7789_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data);
|
||||
static esp_err_t panel_st7789_invert_color(esp_lcd_panel_t *panel, bool invert_color_data);
|
||||
static esp_err_t panel_st7789_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y);
|
||||
static esp_err_t panel_st7789_swap_xy(esp_lcd_panel_t *panel, bool swap_axes);
|
||||
static esp_err_t panel_st7789_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap);
|
||||
static esp_err_t panel_st7789_disp_on_off(esp_lcd_panel_t *panel, bool off);
|
||||
|
||||
typedef struct {
|
||||
esp_lcd_panel_t base;
|
||||
esp_lcd_panel_io_handle_t io;
|
||||
int reset_gpio_num;
|
||||
bool reset_level;
|
||||
int x_gap;
|
||||
int y_gap;
|
||||
uint8_t fb_bits_per_pixel;
|
||||
uint8_t madctl_val; // save current value of LCD_CMD_MADCTL register
|
||||
uint8_t colmod_val; // save current value of LCD_CMD_COLMOD register
|
||||
const esp_lcd_panel_vendor_init_cmd_t *init_cmds;
|
||||
uint16_t init_cmds_size;
|
||||
} st7789_panel_t;
|
||||
|
||||
esp_err_t esp_lcd_new_panel_st7789(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel)
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
st7789_panel_t *st7789 = NULL;
|
||||
gpio_config_t io_conf = { 0 };
|
||||
|
||||
ESP_GOTO_ON_FALSE(io && panel_dev_config && ret_panel, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
||||
st7789 = (st7789_panel_t *)calloc(1, sizeof(st7789_panel_t));
|
||||
ESP_GOTO_ON_FALSE(st7789, ESP_ERR_NO_MEM, err, TAG, "no mem for st7789 panel");
|
||||
|
||||
if (panel_dev_config->reset_gpio_num >= 0) {
|
||||
io_conf.mode = GPIO_MODE_OUTPUT;
|
||||
io_conf.pin_bit_mask = 1ULL << panel_dev_config->reset_gpio_num;
|
||||
ESP_GOTO_ON_ERROR(gpio_config(&io_conf), err, TAG, "configure GPIO for RST line failed");
|
||||
}
|
||||
|
||||
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
switch (panel_dev_config->color_space) {
|
||||
case ESP_LCD_COLOR_SPACE_RGB:
|
||||
st7789->madctl_val = 0;
|
||||
break;
|
||||
case ESP_LCD_COLOR_SPACE_BGR:
|
||||
st7789->madctl_val |= LCD_CMD_BGR_BIT;
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported color space");
|
||||
break;
|
||||
}
|
||||
#else
|
||||
switch (panel_dev_config->rgb_endian) {
|
||||
case LCD_RGB_ENDIAN_RGB:
|
||||
st7789->madctl_val = 0;
|
||||
break;
|
||||
case LCD_RGB_ENDIAN_BGR:
|
||||
st7789->madctl_val |= LCD_CMD_BGR_BIT;
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported rgb endian");
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (panel_dev_config->bits_per_pixel) {
|
||||
case 16: // RGB565
|
||||
st7789->colmod_val = 0x55;
|
||||
st7789->fb_bits_per_pixel = 16;
|
||||
break;
|
||||
case 18: // RGB666
|
||||
st7789->colmod_val = 0x66;
|
||||
// each color component (R/G/B) should occupy the 6 high bits of a byte, which means 3 full bytes are required for a pixel
|
||||
st7789->fb_bits_per_pixel = 24;
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported pixel width");
|
||||
break;
|
||||
}
|
||||
|
||||
st7789->io = io;
|
||||
st7789->reset_gpio_num = panel_dev_config->reset_gpio_num;
|
||||
st7789->reset_level = panel_dev_config->flags.reset_active_high;
|
||||
if (panel_dev_config->vendor_config) {
|
||||
st7789->init_cmds = ((esp_lcd_panel_vendor_config_t *)panel_dev_config->vendor_config)->init_cmds;
|
||||
st7789->init_cmds_size = ((esp_lcd_panel_vendor_config_t *)panel_dev_config->vendor_config)->init_cmds_size;
|
||||
}
|
||||
st7789->base.del = panel_st7789_del;
|
||||
st7789->base.reset = panel_st7789_reset;
|
||||
st7789->base.init = panel_st7789_init;
|
||||
st7789->base.draw_bitmap = panel_st7789_draw_bitmap;
|
||||
st7789->base.invert_color = panel_st7789_invert_color;
|
||||
st7789->base.set_gap = panel_st7789_set_gap;
|
||||
st7789->base.mirror = panel_st7789_mirror;
|
||||
st7789->base.swap_xy = panel_st7789_swap_xy;
|
||||
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
st7789->base.disp_off = panel_st7789_disp_on_off;
|
||||
#else
|
||||
st7789->base.disp_on_off = panel_st7789_disp_on_off;
|
||||
#endif
|
||||
*ret_panel = &(st7789->base);
|
||||
ESP_LOGD(TAG, "new st7789 panel @%p", st7789);
|
||||
|
||||
ESP_LOGI(TAG, "LCD panel create success, version: %d.%d.%d", ESP_LCD_ST7789_VER_MAJOR, ESP_LCD_ST7789_VER_MINOR,
|
||||
ESP_LCD_ST7789_VER_PATCH);
|
||||
|
||||
return ESP_OK;
|
||||
|
||||
err:
|
||||
if (st7789) {
|
||||
if (panel_dev_config->reset_gpio_num >= 0) {
|
||||
gpio_reset_pin(panel_dev_config->reset_gpio_num);
|
||||
}
|
||||
free(st7789);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t panel_st7789_del(esp_lcd_panel_t *panel)
|
||||
{
|
||||
st7789_panel_t *st7789 = __containerof(panel, st7789_panel_t, base);
|
||||
|
||||
if (st7789->reset_gpio_num >= 0) {
|
||||
gpio_reset_pin(st7789->reset_gpio_num);
|
||||
}
|
||||
ESP_LOGD(TAG, "del st7789 panel @%p", st7789);
|
||||
free(st7789);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_st7789_reset(esp_lcd_panel_t *panel)
|
||||
{
|
||||
st7789_panel_t *st7789 = __containerof(panel, st7789_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = st7789->io;
|
||||
|
||||
// perform hardware reset
|
||||
if (st7789->reset_gpio_num >= 0) {
|
||||
gpio_set_level(st7789->reset_gpio_num, st7789->reset_level);
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
gpio_set_level(st7789->reset_gpio_num, !st7789->reset_level);
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
} else { // perform software reset
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_SWRESET, NULL, 0), TAG, "send command failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(20)); // spec, wait at least 5ms before sending new command
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_st7789_init(esp_lcd_panel_t *panel)
|
||||
{
|
||||
st7789_panel_t *st7789 = __containerof(panel, st7789_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = st7789->io;
|
||||
|
||||
// LCD goes into sleep mode and display will be turned off after power on reset, exit sleep mode first
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_SLPOUT, NULL, 0), TAG, "send command failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]) {
|
||||
st7789->madctl_val,
|
||||
}, 1), TAG, "send command failed");
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_COLMOD, (uint8_t[]) {
|
||||
st7789->colmod_val,
|
||||
}, 1), TAG, "send command failed");
|
||||
|
||||
const esp_lcd_panel_vendor_init_cmd_t *init_cmds = NULL;
|
||||
uint16_t init_cmds_size = 0;
|
||||
if (st7789->init_cmds) {
|
||||
init_cmds = st7789->init_cmds;
|
||||
init_cmds_size = st7789->init_cmds_size;
|
||||
} else {
|
||||
init_cmds = NULL;
|
||||
init_cmds_size = 0;
|
||||
}
|
||||
|
||||
bool is_cmd_overwritten = false;
|
||||
for (int i = 0; i < init_cmds_size; i++) {
|
||||
// Check if the command has been used or conflicts with the internal
|
||||
switch (init_cmds[i].cmd) {
|
||||
case LCD_CMD_MADCTL:
|
||||
is_cmd_overwritten = true;
|
||||
st7789->madctl_val = ((uint8_t *)init_cmds[i].data)[0];
|
||||
break;
|
||||
case LCD_CMD_COLMOD:
|
||||
is_cmd_overwritten = true;
|
||||
st7789->colmod_val = ((uint8_t *)init_cmds[i].data)[0];
|
||||
break;
|
||||
default:
|
||||
is_cmd_overwritten = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_cmd_overwritten) {
|
||||
ESP_LOGW(TAG, "The %02Xh command has been used and will be overwritten by external initialization sequence", init_cmds[i].cmd);
|
||||
}
|
||||
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, init_cmds[i].cmd, init_cmds[i].data, init_cmds[i].data_bytes), TAG, "send command failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(init_cmds[i].delay_ms));
|
||||
}
|
||||
ESP_LOGD(TAG, "send init commands success");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_st7789_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data)
|
||||
{
|
||||
st7789_panel_t *st7789 = __containerof(panel, st7789_panel_t, base);
|
||||
assert((x_start < x_end) && (y_start < y_end) && "start position must be smaller than end position");
|
||||
esp_lcd_panel_io_handle_t io = st7789->io;
|
||||
|
||||
x_start += st7789->x_gap;
|
||||
x_end += st7789->x_gap;
|
||||
y_start += st7789->y_gap;
|
||||
y_end += st7789->y_gap;
|
||||
|
||||
// define an area of frame memory where MCU can access
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_CASET, (uint8_t[]) {
|
||||
(x_start >> 8) & 0xFF,
|
||||
x_start & 0xFF,
|
||||
((x_end - 1) >> 8) & 0xFF,
|
||||
(x_end - 1) & 0xFF,
|
||||
}, 4), TAG, "send command failed");
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_RASET, (uint8_t[]) {
|
||||
(y_start >> 8) & 0xFF,
|
||||
y_start & 0xFF,
|
||||
((y_end - 1) >> 8) & 0xFF,
|
||||
(y_end - 1) & 0xFF,
|
||||
}, 4), TAG, "send command failed");
|
||||
// transfer frame buffer
|
||||
size_t len = (x_end - x_start) * (y_end - y_start) * st7789->fb_bits_per_pixel / 8;
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_color(io, LCD_CMD_RAMWR, color_data, len), TAG, "send color failed");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_st7789_invert_color(esp_lcd_panel_t *panel, bool invert_color_data)
|
||||
{
|
||||
st7789_panel_t *st7789 = __containerof(panel, st7789_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = st7789->io;
|
||||
int command = 0;
|
||||
if (invert_color_data) {
|
||||
command = LCD_CMD_INVON;
|
||||
} else {
|
||||
command = LCD_CMD_INVOFF;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, command, NULL, 0), TAG, "send command failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_st7789_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y)
|
||||
{
|
||||
st7789_panel_t *st7789 = __containerof(panel, st7789_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = st7789->io;
|
||||
if (mirror_x) {
|
||||
st7789->madctl_val |= LCD_CMD_MX_BIT;
|
||||
} else {
|
||||
st7789->madctl_val &= ~LCD_CMD_MX_BIT;
|
||||
}
|
||||
if (mirror_y) {
|
||||
st7789->madctl_val |= LCD_CMD_MY_BIT;
|
||||
} else {
|
||||
st7789->madctl_val &= ~LCD_CMD_MY_BIT;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]) {
|
||||
st7789->madctl_val
|
||||
}, 1), TAG, "send command failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_st7789_swap_xy(esp_lcd_panel_t *panel, bool swap_axes)
|
||||
{
|
||||
st7789_panel_t *st7789 = __containerof(panel, st7789_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = st7789->io;
|
||||
if (swap_axes) {
|
||||
st7789->madctl_val |= LCD_CMD_MV_BIT;
|
||||
} else {
|
||||
st7789->madctl_val &= ~LCD_CMD_MV_BIT;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]) {
|
||||
st7789->madctl_val
|
||||
}, 1), TAG, "send command failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_st7789_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap)
|
||||
{
|
||||
st7789_panel_t *st7789 = __containerof(panel, st7789_panel_t, base);
|
||||
st7789->x_gap = x_gap;
|
||||
st7789->y_gap = y_gap;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_st7789_disp_on_off(esp_lcd_panel_t *panel, bool on_off)
|
||||
{
|
||||
st7789_panel_t *st7789 = __containerof(panel, st7789_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = st7789->io;
|
||||
int command = 0;
|
||||
|
||||
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
on_off = !on_off;
|
||||
#endif
|
||||
|
||||
if (on_off) {
|
||||
command = LCD_CMD_DISPON;
|
||||
} else {
|
||||
command = LCD_CMD_DISPOFF;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, command, NULL, 0), TAG, "send command failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
* @brief ESP LCD: ST7789
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_LCD_ST7789_VER_MAJOR (0)
|
||||
#define ESP_LCD_ST7789_VER_MINOR (0)
|
||||
#define ESP_LCD_ST7789_VER_PATCH (1)
|
||||
|
||||
/**
|
||||
* @brief Create LCD panel for model ST7789
|
||||
*
|
||||
* @note Vendor specific initialization can be different between manufacturers, should consult the LCD supplier for initialization sequence code.
|
||||
*
|
||||
* @param[in] io LCD panel IO handle
|
||||
* @param[in] panel_dev_config general panel device configuration
|
||||
* @param[out] ret_panel Returned LCD panel handle
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG if parameter is invalid
|
||||
* - ESP_ERR_NO_MEM if out of memory
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t esp_lcd_new_panel_st7789(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel);
|
||||
|
||||
/**
|
||||
* @brief LCD panel bus configuration structure
|
||||
*
|
||||
* @param[in] sclk SPI clock pin number
|
||||
* @param[in] mosi SPI MOSI pin number
|
||||
* @param[in] max_trans_sz Maximum transfer size in bytes
|
||||
*
|
||||
*/
|
||||
#define ST7789_PANEL_BUS_SPI_CONFIG(sclk, mosi, max_trans_sz) \
|
||||
{ \
|
||||
.sclk_io_num = sclk, \
|
||||
.mosi_io_num = mosi, \
|
||||
.miso_io_num = -1, \
|
||||
.quadhd_io_num = -1, \
|
||||
.quadwp_io_num = -1, \
|
||||
.max_transfer_sz = max_trans_sz, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief LCD panel IO configuration structure
|
||||
*
|
||||
* @param[in] cs SPI chip select pin number
|
||||
* @param[in] dc SPI data/command pin number
|
||||
* @param[in] cb Callback function when SPI transfer is done
|
||||
* @param[in] cb_ctx Callback function context
|
||||
*
|
||||
*/
|
||||
#define ST7789_PANEL_IO_SPI_CONFIG(cs, dc, callback, callback_ctx) \
|
||||
{ \
|
||||
.cs_gpio_num = cs, \
|
||||
.dc_gpio_num = dc, \
|
||||
.spi_mode = 0, \
|
||||
.pclk_hz = 40 * 1000 * 1000, \
|
||||
.trans_queue_depth = 10, \
|
||||
.on_color_trans_done = callback, \
|
||||
.user_ctx = callback_ctx, \
|
||||
.lcd_cmd_bits = 8, \
|
||||
.lcd_param_bits = 8, \
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
+579
@@ -0,0 +1,579 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_lcd_panel_interface.h"
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
#include "esp_lcd_panel_ops.h"
|
||||
#include "esp_lcd_panel_commands.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "esp_lcd_custom_types.h"
|
||||
#include "esp_lcd_st77916.h"
|
||||
|
||||
#define LCD_OPCODE_WRITE_CMD (0x02ULL)
|
||||
#define LCD_OPCODE_READ_CMD (0x0BULL)
|
||||
#define LCD_OPCODE_WRITE_COLOR (0x32ULL)
|
||||
|
||||
#define ST77916_CMD_SET (0xF0)
|
||||
#define ST77916_PARAM_SET (0x00)
|
||||
|
||||
static const char *TAG = "st77916";
|
||||
|
||||
static esp_err_t panel_st77916_del(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_st77916_reset(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_st77916_init(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_st77916_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data);
|
||||
static esp_err_t panel_st77916_invert_color(esp_lcd_panel_t *panel, bool invert_color_data);
|
||||
static esp_err_t panel_st77916_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y);
|
||||
static esp_err_t panel_st77916_swap_xy(esp_lcd_panel_t *panel, bool swap_axes);
|
||||
static esp_err_t panel_st77916_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap);
|
||||
static esp_err_t panel_st77916_disp_on_off(esp_lcd_panel_t *panel, bool off);
|
||||
|
||||
typedef struct {
|
||||
esp_lcd_panel_t base;
|
||||
esp_lcd_panel_io_handle_t io;
|
||||
int reset_gpio_num;
|
||||
int x_gap;
|
||||
int y_gap;
|
||||
uint8_t fb_bits_per_pixel;
|
||||
uint8_t madctl_val; // save current value of LCD_CMD_MADCTL register
|
||||
uint8_t colmod_val; // save surrent value of LCD_CMD_COLMOD register
|
||||
const esp_lcd_panel_vendor_init_cmd_t *init_cmds;
|
||||
uint16_t init_cmds_size;
|
||||
struct {
|
||||
unsigned int use_qspi_interface: 1;
|
||||
unsigned int reset_level: 1;
|
||||
} flags;
|
||||
} st77916_panel_t;
|
||||
|
||||
esp_err_t esp_lcd_new_panel_st77916(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel)
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
ESP_RETURN_ON_FALSE(io && panel_dev_config && ret_panel, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
st77916_panel_t *st77916 = NULL;
|
||||
st77916 = calloc(1, sizeof(st77916_panel_t));
|
||||
ESP_GOTO_ON_FALSE(st77916, ESP_ERR_NO_MEM, err, TAG, "no mem for st77916 panel");
|
||||
|
||||
if (panel_dev_config->reset_gpio_num >= 0) {
|
||||
gpio_config_t io_conf = {
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pin_bit_mask = 1ULL << panel_dev_config->reset_gpio_num,
|
||||
};
|
||||
ESP_GOTO_ON_ERROR(gpio_config(&io_conf), err, TAG, "configure GPIO for RST line failed");
|
||||
}
|
||||
|
||||
switch (panel_dev_config->rgb_ele_order) {
|
||||
case LCD_RGB_ELEMENT_ORDER_RGB:
|
||||
st77916->madctl_val = 0;
|
||||
break;
|
||||
case LCD_RGB_ELEMENT_ORDER_BGR:
|
||||
st77916->madctl_val |= LCD_CMD_BGR_BIT;
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported color element order");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (panel_dev_config->bits_per_pixel) {
|
||||
case 16: // RGB565
|
||||
st77916->colmod_val = 0x55;
|
||||
st77916->fb_bits_per_pixel = 16;
|
||||
break;
|
||||
case 18: // RGB666
|
||||
st77916->colmod_val = 0x66;
|
||||
// each color component (R/G/B) should occupy the 6 high bits of a byte, which means 3 full bytes are required for a pixel
|
||||
st77916->fb_bits_per_pixel = 24;
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported pixel width");
|
||||
break;
|
||||
}
|
||||
|
||||
st77916->io = io;
|
||||
st77916->reset_gpio_num = panel_dev_config->reset_gpio_num;
|
||||
st77916->flags.reset_level = panel_dev_config->flags.reset_active_high;
|
||||
esp_lcd_panel_vendor_config_t *vendor_config = (esp_lcd_panel_vendor_config_t *)panel_dev_config->vendor_config;
|
||||
if (vendor_config) {
|
||||
st77916->init_cmds = vendor_config->init_cmds;
|
||||
st77916->init_cmds_size = vendor_config->init_cmds_size;
|
||||
st77916->flags.use_qspi_interface = vendor_config->flags.use_qspi_interface;
|
||||
}
|
||||
st77916->base.del = panel_st77916_del;
|
||||
st77916->base.reset = panel_st77916_reset;
|
||||
st77916->base.init = panel_st77916_init;
|
||||
st77916->base.draw_bitmap = panel_st77916_draw_bitmap;
|
||||
st77916->base.invert_color = panel_st77916_invert_color;
|
||||
st77916->base.set_gap = panel_st77916_set_gap;
|
||||
st77916->base.mirror = panel_st77916_mirror;
|
||||
st77916->base.swap_xy = panel_st77916_swap_xy;
|
||||
st77916->base.disp_on_off = panel_st77916_disp_on_off;
|
||||
*ret_panel = &(st77916->base);
|
||||
ESP_LOGD(TAG, "new st77916 panel @%p", st77916);
|
||||
|
||||
ESP_LOGI(TAG, "LCD panel create success, version: %d.%d.%d", ESP_LCD_ST77916_VER_MAJOR, ESP_LCD_ST77916_VER_MINOR,
|
||||
ESP_LCD_ST77916_VER_PATCH);
|
||||
|
||||
return ESP_OK;
|
||||
|
||||
err:
|
||||
if (st77916) {
|
||||
if (panel_dev_config->reset_gpio_num >= 0) {
|
||||
gpio_reset_pin(panel_dev_config->reset_gpio_num);
|
||||
}
|
||||
free(st77916);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t tx_param(st77916_panel_t *st77916, esp_lcd_panel_io_handle_t io, int lcd_cmd, const void *param, size_t param_size)
|
||||
{
|
||||
if (st77916->flags.use_qspi_interface) {
|
||||
lcd_cmd &= 0xff;
|
||||
lcd_cmd <<= 8;
|
||||
lcd_cmd |= LCD_OPCODE_WRITE_CMD << 24;
|
||||
}
|
||||
return esp_lcd_panel_io_tx_param(io, lcd_cmd, param, param_size);
|
||||
}
|
||||
|
||||
static esp_err_t tx_color(st77916_panel_t *st77916, esp_lcd_panel_io_handle_t io, int lcd_cmd, const void *param, size_t param_size)
|
||||
{
|
||||
if (st77916->flags.use_qspi_interface) {
|
||||
lcd_cmd &= 0xff;
|
||||
lcd_cmd <<= 8;
|
||||
lcd_cmd |= LCD_OPCODE_WRITE_COLOR << 24;
|
||||
}
|
||||
return esp_lcd_panel_io_tx_color(io, lcd_cmd, param, param_size);
|
||||
}
|
||||
|
||||
static esp_err_t panel_st77916_del(esp_lcd_panel_t *panel)
|
||||
{
|
||||
st77916_panel_t *st77916 = __containerof(panel, st77916_panel_t, base);
|
||||
|
||||
if (st77916->reset_gpio_num >= 0) {
|
||||
gpio_reset_pin(st77916->reset_gpio_num);
|
||||
}
|
||||
ESP_LOGD(TAG, "del st77916 panel @%p", st77916);
|
||||
free(st77916);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_st77916_reset(esp_lcd_panel_t *panel)
|
||||
{
|
||||
st77916_panel_t *st77916 = __containerof(panel, st77916_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = st77916->io;
|
||||
|
||||
// Perform hardware reset
|
||||
if (st77916->reset_gpio_num >= 0) {
|
||||
gpio_set_level(st77916->reset_gpio_num, st77916->flags.reset_level);
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
gpio_set_level(st77916->reset_gpio_num, !st77916->flags.reset_level);
|
||||
vTaskDelay(pdMS_TO_TICKS(120));
|
||||
} else { // Perform software reset
|
||||
ESP_RETURN_ON_ERROR(tx_param(st77916, io, LCD_CMD_SWRESET, NULL, 0), TAG, "send command failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(120));
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static const esp_lcd_panel_vendor_init_cmd_t vendor_specific_init_default[] = {
|
||||
{0xF0, (uint8_t []){0x08}, 1, 0},
|
||||
{0xF2, (uint8_t []){0x08}, 1, 0},
|
||||
{0x9B, (uint8_t []){0x51}, 1, 0},
|
||||
{0x86, (uint8_t []){0x53}, 1, 0},
|
||||
{0xF2, (uint8_t []){0x80}, 1, 0},
|
||||
{0xF0, (uint8_t []){0x00}, 1, 0},
|
||||
{0xF0, (uint8_t []){0x01}, 1, 0},
|
||||
{0xF1, (uint8_t []){0x01}, 1, 0},
|
||||
{0xB0, (uint8_t []){0x54}, 1, 0},
|
||||
{0xB1, (uint8_t []){0x3F}, 1, 0},
|
||||
{0xB2, (uint8_t []){0x2A}, 1, 0},
|
||||
{0xB4, (uint8_t []){0x46}, 1, 0},
|
||||
{0xB5, (uint8_t []){0x34}, 1, 0},
|
||||
{0xB6, (uint8_t []){0xD5}, 1, 0},
|
||||
{0xB7, (uint8_t []){0x30}, 1, 0},
|
||||
{0xB8, (uint8_t []){0x04}, 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 []){0x51}, 1, 0},
|
||||
{0xC9, (uint8_t []){0xA9}, 1, 0},
|
||||
{0xCA, (uint8_t []){0x41}, 1, 0},
|
||||
{0xCB, (uint8_t []){0x51}, 1, 0},
|
||||
{0xD0, (uint8_t []){0x91}, 1, 0},
|
||||
{0xD1, (uint8_t []){0x68}, 1, 0},
|
||||
{0xD2, (uint8_t []){0x69}, 1, 0},
|
||||
{0xF5, (uint8_t []){0x00, 0xA5}, 2, 0},
|
||||
{0xDD, (uint8_t []){0x35}, 1, 0},
|
||||
{0xDE, (uint8_t []){0x35}, 1, 0},
|
||||
{0xF1, (uint8_t []){0x10}, 1, 0},
|
||||
{0xF0, (uint8_t []){0x00}, 1, 0},
|
||||
{0xF0, (uint8_t []){0x02}, 1, 0},
|
||||
{0xE0, (uint8_t []){0x70, 0x09, 0x12, 0x0C, 0x0B, 0x27, 0x38, 0x54, 0x4E, 0x19, 0x15, 0x15, 0x2C, 0x2F}, 14, 0},
|
||||
{0xE1, (uint8_t []){0x70, 0x08, 0x11, 0x0C, 0x0B, 0x27, 0x38, 0x43, 0x4C, 0x18, 0x14, 0x14, 0x2B, 0x2D}, 14, 0},
|
||||
{0xF0, (uint8_t []){0x10}, 1, 0},
|
||||
{0xF3, (uint8_t []){0x10}, 1, 0},
|
||||
{0xE0, (uint8_t []){0x0A}, 1, 0},
|
||||
{0xE1, (uint8_t []){0x00}, 1, 0},
|
||||
{0xE2, (uint8_t []){0x0B}, 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 []){0x00}, 1, 0},
|
||||
{0xE8, (uint8_t []){0x05}, 1, 0},
|
||||
{0xE9, (uint8_t []){0x82}, 1, 0},
|
||||
{0xEA, (uint8_t []){0xDF}, 1, 0},
|
||||
{0xEB, (uint8_t []){0x89}, 1, 0},
|
||||
{0xEC, (uint8_t []){0x20}, 1, 0},
|
||||
{0xED, (uint8_t []){0x14}, 1, 0},
|
||||
{0xEE, (uint8_t []){0xFF}, 1, 0},
|
||||
{0xEF, (uint8_t []){0x00}, 1, 0},
|
||||
{0xF8, (uint8_t []){0xFF}, 1, 0},
|
||||
{0xF9, (uint8_t []){0x00}, 1, 0},
|
||||
{0xFA, (uint8_t []){0x00}, 1, 0},
|
||||
{0xFB, (uint8_t []){0x30}, 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 []){0x42}, 1, 0},
|
||||
{0x61, (uint8_t []){0xE0}, 1, 0},
|
||||
{0x62, (uint8_t []){0x40}, 1, 0},
|
||||
{0x63, (uint8_t []){0x40}, 1, 0},
|
||||
{0x64, (uint8_t []){0x02}, 1, 0},
|
||||
{0x65, (uint8_t []){0x00}, 1, 0},
|
||||
{0x66, (uint8_t []){0x40}, 1, 0},
|
||||
{0x67, (uint8_t []){0x03}, 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 []){0x42}, 1, 0},
|
||||
{0x71, (uint8_t []){0xE0}, 1, 0},
|
||||
{0x72, (uint8_t []){0x40}, 1, 0},
|
||||
{0x73, (uint8_t []){0x40}, 1, 0},
|
||||
{0x74, (uint8_t []){0x02}, 1, 0},
|
||||
{0x75, (uint8_t []){0x00}, 1, 0},
|
||||
{0x76, (uint8_t []){0x40}, 1, 0},
|
||||
{0x77, (uint8_t []){0x03}, 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 []){0x38}, 1, 0},
|
||||
{0x81, (uint8_t []){0x00}, 1, 0},
|
||||
{0x82, (uint8_t []){0x04}, 1, 0},
|
||||
{0x83, (uint8_t []){0x02}, 1, 0},
|
||||
{0x84, (uint8_t []){0xDC}, 1, 0},
|
||||
{0x85, (uint8_t []){0x00}, 1, 0},
|
||||
{0x86, (uint8_t []){0x00}, 1, 0},
|
||||
{0x87, (uint8_t []){0x00}, 1, 0},
|
||||
{0x88, (uint8_t []){0x38}, 1, 0},
|
||||
{0x89, (uint8_t []){0x00}, 1, 0},
|
||||
{0x8A, (uint8_t []){0x06}, 1, 0},
|
||||
{0x8B, (uint8_t []){0x02}, 1, 0},
|
||||
{0x8C, (uint8_t []){0xDE}, 1, 0},
|
||||
{0x8D, (uint8_t []){0x00}, 1, 0},
|
||||
{0x8E, (uint8_t []){0x00}, 1, 0},
|
||||
{0x8F, (uint8_t []){0x00}, 1, 0},
|
||||
{0x90, (uint8_t []){0x38}, 1, 0},
|
||||
{0x91, (uint8_t []){0x00}, 1, 0},
|
||||
{0x92, (uint8_t []){0x08}, 1, 0},
|
||||
{0x93, (uint8_t []){0x02}, 1, 0},
|
||||
{0x94, (uint8_t []){0xE0}, 1, 0},
|
||||
{0x95, (uint8_t []){0x00}, 1, 0},
|
||||
{0x96, (uint8_t []){0x00}, 1, 0},
|
||||
{0x97, (uint8_t []){0x00}, 1, 0},
|
||||
{0x98, (uint8_t []){0x38}, 1, 0},
|
||||
{0x99, (uint8_t []){0x00}, 1, 0},
|
||||
{0x9A, (uint8_t []){0x0A}, 1, 0},
|
||||
{0x9B, (uint8_t []){0x02}, 1, 0},
|
||||
{0x9C, (uint8_t []){0xE2}, 1, 0},
|
||||
{0x9D, (uint8_t []){0x00}, 1, 0},
|
||||
{0x9E, (uint8_t []){0x00}, 1, 0},
|
||||
{0x9F, (uint8_t []){0x00}, 1, 0},
|
||||
{0xA0, (uint8_t []){0x38}, 1, 0},
|
||||
{0xA1, (uint8_t []){0x00}, 1, 0},
|
||||
{0xA2, (uint8_t []){0x03}, 1, 0},
|
||||
{0xA3, (uint8_t []){0x02}, 1, 0},
|
||||
{0xA4, (uint8_t []){0xDB}, 1, 0},
|
||||
{0xA5, (uint8_t []){0x00}, 1, 0},
|
||||
{0xA6, (uint8_t []){0x00}, 1, 0},
|
||||
{0xA7, (uint8_t []){0x00}, 1, 0},
|
||||
{0xA8, (uint8_t []){0x38}, 1, 0},
|
||||
{0xA9, (uint8_t []){0x00}, 1, 0},
|
||||
{0xAA, (uint8_t []){0x05}, 1, 0},
|
||||
{0xAB, (uint8_t []){0x02}, 1, 0},
|
||||
{0xAC, (uint8_t []){0xDD}, 1, 0},
|
||||
{0xAD, (uint8_t []){0x00}, 1, 0},
|
||||
{0xAE, (uint8_t []){0x00}, 1, 0},
|
||||
{0xAF, (uint8_t []){0x00}, 1, 0},
|
||||
{0xB0, (uint8_t []){0x38}, 1, 0},
|
||||
{0xB1, (uint8_t []){0x00}, 1, 0},
|
||||
{0xB2, (uint8_t []){0x07}, 1, 0},
|
||||
{0xB3, (uint8_t []){0x02}, 1, 0},
|
||||
{0xB4, (uint8_t []){0xDF}, 1, 0},
|
||||
{0xB5, (uint8_t []){0x00}, 1, 0},
|
||||
{0xB6, (uint8_t []){0x00}, 1, 0},
|
||||
{0xB7, (uint8_t []){0x00}, 1, 0},
|
||||
{0xB8, (uint8_t []){0x38}, 1, 0},
|
||||
{0xB9, (uint8_t []){0x00}, 1, 0},
|
||||
{0xBA, (uint8_t []){0x09}, 1, 0},
|
||||
{0xBB, (uint8_t []){0x02}, 1, 0},
|
||||
{0xBC, (uint8_t []){0xE1}, 1, 0},
|
||||
{0xBD, (uint8_t []){0x00}, 1, 0},
|
||||
{0xBE, (uint8_t []){0x00}, 1, 0},
|
||||
{0xBF, (uint8_t []){0x00}, 1, 0},
|
||||
{0xC0, (uint8_t []){0x22}, 1, 0},
|
||||
{0xC1, (uint8_t []){0xAA}, 1, 0},
|
||||
{0xC2, (uint8_t []){0x65}, 1, 0},
|
||||
{0xC3, (uint8_t []){0x74}, 1, 0},
|
||||
{0xC4, (uint8_t []){0x47}, 1, 0},
|
||||
{0xC5, (uint8_t []){0x56}, 1, 0},
|
||||
{0xC6, (uint8_t []){0x00}, 1, 0},
|
||||
{0xC7, (uint8_t []){0x88}, 1, 0},
|
||||
{0xC8, (uint8_t []){0x99}, 1, 0},
|
||||
{0xC9, (uint8_t []){0x33}, 1, 0},
|
||||
{0xD0, (uint8_t []){0x11}, 1, 0},
|
||||
{0xD1, (uint8_t []){0xAA}, 1, 0},
|
||||
{0xD2, (uint8_t []){0x65}, 1, 0},
|
||||
{0xD3, (uint8_t []){0x74}, 1, 0},
|
||||
{0xD4, (uint8_t []){0x47}, 1, 0},
|
||||
{0xD5, (uint8_t []){0x56}, 1, 0},
|
||||
{0xD6, (uint8_t []){0x00}, 1, 0},
|
||||
{0xD7, (uint8_t []){0x88}, 1, 0},
|
||||
{0xD8, (uint8_t []){0x99}, 1, 0},
|
||||
{0xD9, (uint8_t []){0x33}, 1, 0},
|
||||
{0xF3, (uint8_t []){0x01}, 1, 0},
|
||||
{0xF0, (uint8_t []){0x00}, 1, 0},
|
||||
{0xF0, (uint8_t []){0x01}, 1, 0},
|
||||
{0xF1, (uint8_t []){0x01}, 1, 0},
|
||||
{0xA0, (uint8_t []){0x0B}, 1, 0},
|
||||
{0xA3, (uint8_t []){0x2A}, 1, 0},
|
||||
{0xA5, (uint8_t []){0xC3}, 1, 1},
|
||||
{0xA3, (uint8_t []){0x2B}, 1, 0},
|
||||
{0xA5, (uint8_t []){0xC3}, 1, 1},
|
||||
{0xA3, (uint8_t []){0x2C}, 1, 0},
|
||||
{0xA5, (uint8_t []){0xC3}, 1, 1},
|
||||
{0xA3, (uint8_t []){0x2D}, 1, 0},
|
||||
{0xA5, (uint8_t []){0xC3}, 1, 1},
|
||||
{0xA3, (uint8_t []){0x2E}, 1, 0},
|
||||
{0xA5, (uint8_t []){0xC3}, 1, 1},
|
||||
{0xA3, (uint8_t []){0x2F}, 1, 0},
|
||||
{0xA5, (uint8_t []){0xC3}, 1, 1},
|
||||
{0xA3, (uint8_t []){0x30}, 1, 0},
|
||||
{0xA5, (uint8_t []){0xC3}, 1, 1},
|
||||
{0xA3, (uint8_t []){0x31}, 1, 0},
|
||||
{0xA5, (uint8_t []){0xC3}, 1, 1},
|
||||
{0xA3, (uint8_t []){0x32}, 1, 0},
|
||||
{0xA5, (uint8_t []){0xC3}, 1, 1},
|
||||
{0xA3, (uint8_t []){0x33}, 1, 0},
|
||||
{0xA5, (uint8_t []){0xC3}, 1, 1},
|
||||
{0xA0, (uint8_t []){0x09}, 1, 0},
|
||||
{0xF1, (uint8_t []){0x10}, 1, 0},
|
||||
{0xF0, (uint8_t []){0x00}, 1, 0},
|
||||
{0x2A, (uint8_t []){0x00, 0x00, 0x01, 0x67}, 4, 0},
|
||||
{0x2B, (uint8_t []){0x01, 0x68, 0x01, 0x68}, 4, 0},
|
||||
{0x4D, (uint8_t []){0x00}, 1, 0},
|
||||
{0x4E, (uint8_t []){0x00}, 1, 0},
|
||||
{0x4F, (uint8_t []){0x00}, 1, 0},
|
||||
{0x4C, (uint8_t []){0x01}, 1, 10},
|
||||
{0x4C, (uint8_t []){0x00}, 1, 0},
|
||||
{0x2A, (uint8_t []){0x00, 0x00, 0x01, 0x67}, 4, 0},
|
||||
{0x2B, (uint8_t []){0x00, 0x00, 0x01, 0x67}, 4, 0},
|
||||
{0x21, (uint8_t []){0x00}, 1, 0},
|
||||
{0x11, (uint8_t []){0x00}, 1, 120},
|
||||
};
|
||||
|
||||
static esp_err_t panel_st77916_init(esp_lcd_panel_t *panel)
|
||||
{
|
||||
st77916_panel_t *st77916 = __containerof(panel, st77916_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = st77916->io;
|
||||
const esp_lcd_panel_vendor_init_cmd_t *init_cmds = NULL;
|
||||
uint16_t init_cmds_size = 0;
|
||||
bool is_user_set = true;
|
||||
bool is_cmd_overwritten = false;
|
||||
|
||||
ESP_RETURN_ON_ERROR(tx_param(st77916, io, LCD_CMD_MADCTL, (uint8_t[]) {
|
||||
st77916->madctl_val,
|
||||
}, 1), TAG, "send command failed");
|
||||
ESP_RETURN_ON_ERROR(tx_param(st77916, io, LCD_CMD_COLMOD, (uint8_t[]) {
|
||||
st77916->colmod_val,
|
||||
}, 1), TAG, "send command failed");
|
||||
|
||||
// vendor specific initialization, it can be different between manufacturers
|
||||
// should consult the LCD supplier for initialization sequence code
|
||||
if (st77916->init_cmds) {
|
||||
init_cmds = st77916->init_cmds;
|
||||
init_cmds_size = st77916->init_cmds_size;
|
||||
} else {
|
||||
init_cmds = vendor_specific_init_default;
|
||||
init_cmds_size = sizeof(vendor_specific_init_default) / sizeof(esp_lcd_panel_vendor_init_cmd_t);
|
||||
}
|
||||
|
||||
for (int i = 0; i < init_cmds_size; i++) {
|
||||
// Check if the command has been used or conflicts with the internal
|
||||
if (is_user_set && (init_cmds[i].data_bytes > 0)) {
|
||||
switch (init_cmds[i].cmd) {
|
||||
case LCD_CMD_MADCTL:
|
||||
is_cmd_overwritten = true;
|
||||
st77916->madctl_val = ((uint8_t *)init_cmds[i].data)[0];
|
||||
break;
|
||||
case LCD_CMD_COLMOD:
|
||||
is_cmd_overwritten = true;
|
||||
st77916->colmod_val = ((uint8_t *)init_cmds[i].data)[0];
|
||||
break;
|
||||
default:
|
||||
is_cmd_overwritten = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_cmd_overwritten) {
|
||||
is_cmd_overwritten = false;
|
||||
ESP_LOGW(TAG, "The %02Xh command has been used and will be overwritten by external initialization sequence", init_cmds[i].cmd);
|
||||
}
|
||||
}
|
||||
|
||||
// Send command
|
||||
ESP_RETURN_ON_ERROR(tx_param(st77916, io, init_cmds[i].cmd, init_cmds[i].data, init_cmds[i].data_bytes), TAG, "send command failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(init_cmds[i].delay_ms));
|
||||
|
||||
// Check if the current cmd is the "command set" cmd
|
||||
if ((init_cmds[i].cmd == ST77916_CMD_SET)) {
|
||||
is_user_set = ((uint8_t *)init_cmds[i].data)[0] == ST77916_PARAM_SET ? true : false;
|
||||
}
|
||||
}
|
||||
ESP_LOGD(TAG, "send init commands success");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_st77916_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data)
|
||||
{
|
||||
st77916_panel_t *st77916 = __containerof(panel, st77916_panel_t, base);
|
||||
assert((x_start < x_end) && (y_start < y_end) && "start position must be smaller than end position");
|
||||
esp_lcd_panel_io_handle_t io = st77916->io;
|
||||
|
||||
x_start += st77916->x_gap;
|
||||
x_end += st77916->x_gap;
|
||||
y_start += st77916->y_gap;
|
||||
y_end += st77916->y_gap;
|
||||
|
||||
// define an area of frame memory where MCU can access
|
||||
ESP_RETURN_ON_ERROR(tx_param(st77916, io, LCD_CMD_CASET, (uint8_t[]) {
|
||||
(x_start >> 8) & 0xFF,
|
||||
x_start & 0xFF,
|
||||
((x_end - 1) >> 8) & 0xFF,
|
||||
(x_end - 1) & 0xFF,
|
||||
}, 4), TAG, "send command failed");
|
||||
ESP_RETURN_ON_ERROR(tx_param(st77916, io, LCD_CMD_RASET, (uint8_t[]) {
|
||||
(y_start >> 8) & 0xFF,
|
||||
y_start & 0xFF,
|
||||
((y_end - 1) >> 8) & 0xFF,
|
||||
(y_end - 1) & 0xFF,
|
||||
}, 4), TAG, "send command failed");
|
||||
// transfer frame buffer
|
||||
size_t len = (x_end - x_start) * (y_end - y_start) * st77916->fb_bits_per_pixel / 8;
|
||||
tx_color(st77916, io, LCD_CMD_RAMWR, color_data, len);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_st77916_invert_color(esp_lcd_panel_t *panel, bool invert_color_data)
|
||||
{
|
||||
st77916_panel_t *st77916 = __containerof(panel, st77916_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = st77916->io;
|
||||
int command = 0;
|
||||
if (invert_color_data) {
|
||||
command = LCD_CMD_INVON;
|
||||
} else {
|
||||
command = LCD_CMD_INVOFF;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(tx_param(st77916, io, command, NULL, 0), TAG, "send command failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_st77916_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y)
|
||||
{
|
||||
st77916_panel_t *st77916 = __containerof(panel, st77916_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = st77916->io;
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
if (mirror_x) {
|
||||
st77916->madctl_val |= BIT(6);
|
||||
} else {
|
||||
st77916->madctl_val &= ~BIT(6);
|
||||
}
|
||||
if (mirror_y) {
|
||||
st77916->madctl_val |= BIT(7);
|
||||
} else {
|
||||
st77916->madctl_val &= ~BIT(7);
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(tx_param(st77916, io, LCD_CMD_MADCTL, (uint8_t[]) {
|
||||
st77916->madctl_val
|
||||
}, 1), TAG, "send command failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t panel_st77916_swap_xy(esp_lcd_panel_t *panel, bool swap_axes)
|
||||
{
|
||||
st77916_panel_t *st77916 = __containerof(panel, st77916_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = st77916->io;
|
||||
if (swap_axes) {
|
||||
st77916->madctl_val |= LCD_CMD_MV_BIT;
|
||||
} else {
|
||||
st77916->madctl_val &= ~LCD_CMD_MV_BIT;
|
||||
}
|
||||
esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]) {
|
||||
st77916->madctl_val
|
||||
}, 1);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_st77916_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap)
|
||||
{
|
||||
st77916_panel_t *st77916 = __containerof(panel, st77916_panel_t, base);
|
||||
st77916->x_gap = x_gap;
|
||||
st77916->y_gap = y_gap;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_st77916_disp_on_off(esp_lcd_panel_t *panel, bool on_off)
|
||||
{
|
||||
st77916_panel_t *st77916 = __containerof(panel, st77916_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = st77916->io;
|
||||
int command = 0;
|
||||
|
||||
if (on_off) {
|
||||
command = LCD_CMD_DISPON;
|
||||
} else {
|
||||
command = LCD_CMD_DISPOFF;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(tx_param(st77916, io, command, NULL, 0), TAG, "send command failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_LCD_ST77916_VER_MAJOR (0)
|
||||
#define ESP_LCD_ST77916_VER_MINOR (0)
|
||||
#define ESP_LCD_ST77916_VER_PATCH (2)
|
||||
|
||||
/**
|
||||
* @brief Create LCD panel for model ST77916
|
||||
*
|
||||
* @param[in] io LCD panel IO handle
|
||||
* @param[in] panel_dev_config General panel device configuration (Use `vendor_config` to select QSPI interface or override default initialization commands)
|
||||
* @param[out] ret_panel Returned LCD panel handle
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - Otherwise: Fail
|
||||
*/
|
||||
esp_err_t esp_lcd_new_panel_st77916(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel);
|
||||
|
||||
/**
|
||||
* @brief LCD panel bus configuration structure
|
||||
*
|
||||
*/
|
||||
#define ST77916_PANEL_BUS_SPI_CONFIG(sclk, mosi, max_trans_sz) \
|
||||
{ \
|
||||
.sclk_io_num = sclk, \
|
||||
.mosi_io_num = mosi, \
|
||||
.miso_io_num = -1, \
|
||||
.quadhd_io_num = -1, \
|
||||
.quadwp_io_num = -1, \
|
||||
.max_transfer_sz = max_trans_sz, \
|
||||
}
|
||||
#define ST77916_PANEL_BUS_QSPI_CONFIG(sclk, d0, d1, d2, d3, max_trans_sz)\
|
||||
{ \
|
||||
.sclk_io_num = sclk, \
|
||||
.data0_io_num = d0, \
|
||||
.data1_io_num = d1, \
|
||||
.data2_io_num = d2, \
|
||||
.data3_io_num = d3, \
|
||||
.max_transfer_sz = max_trans_sz, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief LCD panel IO configuration structure
|
||||
*
|
||||
*/
|
||||
#define ST77916_PANEL_IO_SPI_CONFIG(cs, dc, cb, cb_ctx) \
|
||||
{ \
|
||||
.cs_gpio_num = cs, \
|
||||
.dc_gpio_num = dc, \
|
||||
.spi_mode = 0, \
|
||||
.pclk_hz = 40 * 1000 * 1000, \
|
||||
.trans_queue_depth = 10, \
|
||||
.on_color_trans_done = cb, \
|
||||
.user_ctx = cb_ctx, \
|
||||
.lcd_cmd_bits = 8, \
|
||||
.lcd_param_bits = 8, \
|
||||
}
|
||||
#define ST77916_PANEL_IO_QSPI_CONFIG(cs, cb, cb_ctx) \
|
||||
{ \
|
||||
.cs_gpio_num = cs, \
|
||||
.dc_gpio_num = -1, \
|
||||
.spi_mode = 0, \
|
||||
.pclk_hz = 40 * 1000 * 1000, \
|
||||
.trans_queue_depth = 10, \
|
||||
.on_color_trans_done = cb, \
|
||||
.user_ctx = cb_ctx, \
|
||||
.lcd_cmd_bits = 32, \
|
||||
.lcd_param_bits = 8, \
|
||||
.flags = { \
|
||||
.quad_mode = true, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
+419
@@ -0,0 +1,419 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_lcd_panel_interface.h"
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
#include "esp_lcd_panel_ops.h"
|
||||
#include "esp_lcd_panel_commands.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "esp_lcd_custom_types.h"
|
||||
#include "esp_lcd_st77922.h"
|
||||
|
||||
#define LCD_OPCODE_WRITE_CMD (0x02ULL)
|
||||
#define LCD_OPCODE_READ_CMD (0x0BULL)
|
||||
#define LCD_OPCODE_WRITE_COLOR (0x32ULL)
|
||||
|
||||
#define ST77922_CMD_SET (0xF0)
|
||||
|
||||
static const char *TAG = "st77922";
|
||||
|
||||
static esp_err_t panel_st77922_del(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_st77922_reset(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_st77922_init(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_st77922_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data);
|
||||
static esp_err_t panel_st77922_invert_color(esp_lcd_panel_t *panel, bool invert_color_data);
|
||||
static esp_err_t panel_st77922_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y);
|
||||
static esp_err_t panel_st77922_swap_xy(esp_lcd_panel_t *panel, bool swap_axes);
|
||||
static esp_err_t panel_st77922_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap);
|
||||
static esp_err_t panel_st77922_disp_on_off(esp_lcd_panel_t *panel, bool off);
|
||||
|
||||
typedef struct {
|
||||
esp_lcd_panel_t base;
|
||||
esp_lcd_panel_io_handle_t io;
|
||||
int reset_gpio_num;
|
||||
int x_gap;
|
||||
int y_gap;
|
||||
uint8_t fb_bits_per_pixel;
|
||||
uint8_t madctl_val; // save current value of LCD_CMD_MADCTL register
|
||||
uint8_t colmod_val; // save surrent value of LCD_CMD_COLMOD register
|
||||
const esp_lcd_panel_vendor_init_cmd_t *init_cmds;
|
||||
uint16_t init_cmds_size;
|
||||
struct {
|
||||
unsigned int use_qspi_interface: 1;
|
||||
unsigned int reset_level: 1;
|
||||
} flags;
|
||||
} st77922_panel_t;
|
||||
|
||||
esp_err_t esp_lcd_new_panel_st77922(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel)
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
ESP_RETURN_ON_FALSE(io && panel_dev_config && ret_panel, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
st77922_panel_t *st77922 = NULL;
|
||||
st77922 = calloc(1, sizeof(st77922_panel_t));
|
||||
ESP_GOTO_ON_FALSE(st77922, ESP_ERR_NO_MEM, err, TAG, "no mem for st77922 panel");
|
||||
|
||||
if (panel_dev_config->reset_gpio_num >= 0) {
|
||||
gpio_config_t io_conf = {
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pin_bit_mask = 1ULL << panel_dev_config->reset_gpio_num,
|
||||
};
|
||||
ESP_GOTO_ON_ERROR(gpio_config(&io_conf), err, TAG, "configure GPIO for RST line failed");
|
||||
}
|
||||
|
||||
switch (panel_dev_config->rgb_ele_order) {
|
||||
case LCD_RGB_ELEMENT_ORDER_RGB:
|
||||
st77922->madctl_val = 0;
|
||||
break;
|
||||
case LCD_RGB_ELEMENT_ORDER_BGR:
|
||||
st77922->madctl_val |= LCD_CMD_BGR_BIT;
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported color element order");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (panel_dev_config->bits_per_pixel) {
|
||||
case 16: // RGB565
|
||||
st77922->colmod_val = 0x55;
|
||||
st77922->fb_bits_per_pixel = 16;
|
||||
break;
|
||||
case 18: // RGB666
|
||||
st77922->colmod_val = 0x66;
|
||||
// each color component (R/G/B) should occupy the 6 high bits of a byte, which means 3 full bytes are required for a pixel
|
||||
st77922->fb_bits_per_pixel = 24;
|
||||
break;
|
||||
case 24: // RGB888
|
||||
st77922->colmod_val = 0x77;
|
||||
st77922->fb_bits_per_pixel = 24;
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported pixel width");
|
||||
break;
|
||||
}
|
||||
|
||||
st77922->io = io;
|
||||
st77922->reset_gpio_num = panel_dev_config->reset_gpio_num;
|
||||
st77922->flags.reset_level = panel_dev_config->flags.reset_active_high;
|
||||
esp_lcd_panel_vendor_config_t *vendor_config = (esp_lcd_panel_vendor_config_t *)panel_dev_config->vendor_config;
|
||||
if (vendor_config) {
|
||||
st77922->init_cmds = vendor_config->init_cmds;
|
||||
st77922->init_cmds_size = vendor_config->init_cmds_size;
|
||||
st77922->flags.use_qspi_interface = vendor_config->flags.use_qspi_interface;
|
||||
}
|
||||
st77922->base.del = panel_st77922_del;
|
||||
st77922->base.reset = panel_st77922_reset;
|
||||
st77922->base.init = panel_st77922_init;
|
||||
st77922->base.draw_bitmap = panel_st77922_draw_bitmap;
|
||||
st77922->base.invert_color = panel_st77922_invert_color;
|
||||
st77922->base.set_gap = panel_st77922_set_gap;
|
||||
st77922->base.mirror = panel_st77922_mirror;
|
||||
st77922->base.swap_xy = panel_st77922_swap_xy;
|
||||
st77922->base.disp_on_off = panel_st77922_disp_on_off;
|
||||
*ret_panel = &(st77922->base);
|
||||
ESP_LOGD(TAG, "new st77922 panel @%p", st77922);
|
||||
|
||||
ESP_LOGI(TAG, "LCD panel create success, version: %d.%d.%d", ESP_LCD_ST77922_VER_MAJOR, ESP_LCD_ST77922_VER_MINOR,
|
||||
ESP_LCD_ST77922_VER_PATCH);
|
||||
|
||||
return ESP_OK;
|
||||
|
||||
err:
|
||||
if (st77922) {
|
||||
if (panel_dev_config->reset_gpio_num >= 0) {
|
||||
gpio_reset_pin(panel_dev_config->reset_gpio_num);
|
||||
}
|
||||
free(st77922);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t tx_param(st77922_panel_t *st77922, esp_lcd_panel_io_handle_t io, int lcd_cmd, const void *param, size_t param_size)
|
||||
{
|
||||
if (st77922->flags.use_qspi_interface) {
|
||||
lcd_cmd &= 0xff;
|
||||
lcd_cmd <<= 8;
|
||||
lcd_cmd |= LCD_OPCODE_WRITE_CMD << 24;
|
||||
}
|
||||
return esp_lcd_panel_io_tx_param(io, lcd_cmd, param, param_size);
|
||||
}
|
||||
|
||||
static esp_err_t tx_color(st77922_panel_t *st77922, esp_lcd_panel_io_handle_t io, int lcd_cmd, const void *param, size_t param_size)
|
||||
{
|
||||
if (st77922->flags.use_qspi_interface) {
|
||||
lcd_cmd &= 0xff;
|
||||
lcd_cmd <<= 8;
|
||||
lcd_cmd |= LCD_OPCODE_WRITE_COLOR << 24;
|
||||
}
|
||||
return esp_lcd_panel_io_tx_color(io, lcd_cmd, param, param_size);
|
||||
}
|
||||
|
||||
static esp_err_t panel_st77922_del(esp_lcd_panel_t *panel)
|
||||
{
|
||||
st77922_panel_t *st77922 = __containerof(panel, st77922_panel_t, base);
|
||||
|
||||
if (st77922->reset_gpio_num >= 0) {
|
||||
gpio_reset_pin(st77922->reset_gpio_num);
|
||||
}
|
||||
ESP_LOGD(TAG, "del st77922 panel @%p", st77922);
|
||||
free(st77922);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_st77922_reset(esp_lcd_panel_t *panel)
|
||||
{
|
||||
st77922_panel_t *st77922 = __containerof(panel, st77922_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = st77922->io;
|
||||
|
||||
// Perform hardware reset
|
||||
if (st77922->reset_gpio_num >= 0) {
|
||||
gpio_set_level(st77922->reset_gpio_num, st77922->flags.reset_level);
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
gpio_set_level(st77922->reset_gpio_num, !st77922->flags.reset_level);
|
||||
vTaskDelay(pdMS_TO_TICKS(120));
|
||||
} else { // Perform software reset
|
||||
ESP_RETURN_ON_ERROR(tx_param(st77922, io, LCD_CMD_SWRESET, NULL, 0), TAG, "send command failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(120));
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static const esp_lcd_panel_vendor_init_cmd_t vendor_specific_init_default[] = {
|
||||
{0x28, (uint8_t []){0x00}, 0, 0},
|
||||
{0x10, (uint8_t []){0x00}, 0, 0},
|
||||
{0x2A, (uint8_t []){0x00, 0x00, 0x02, 0x13}, 4, 0},
|
||||
{0x2B, (uint8_t []){0x00, 0x00, 0x01, 0x2B}, 4, 0},
|
||||
{0xD0, (uint8_t []){0x80}, 1, 0},
|
||||
// ======================CMD2======================
|
||||
{0xF1, (uint8_t []){0x00}, 1, 0},
|
||||
{0x60, (uint8_t []){0x00, 0x00, 0x00}, 3, 0},
|
||||
{0x65, (uint8_t []){0x00}, 1, 0},
|
||||
{0x66, (uint8_t []){0x00, 0x3F}, 2, 0},
|
||||
{0xBE, (uint8_t []){0x1E, 0x01, 0x06}, 3, 0}, // VCM SSI
|
||||
{0x70, (uint8_t []){0x02, 0x7D, 0x12, 0x14, 0x30, 0x00, 0x07, 0x52, 0x01, 0x00, 0x00, 0x1A}, 12, 0}, // VFP, VBP, Gate line
|
||||
{0x71, (uint8_t []){0xD0}, 1, 0}, // MIPI CMD Mode
|
||||
{0x7B, (uint8_t []){0x00, 0x08, 0x08}, 3, 0},
|
||||
{0x80, (uint8_t []){0x55, 0x62, 0x2F, 0x17, 0xF0, 0x52, 0x70, 0xD2, 0x52, 0x62, 0xEA}, 11, 0},
|
||||
{0x81, (uint8_t []){0x26, 0x52, 0x72, 0x27}, 4, 0},
|
||||
{0x84, (uint8_t []){0x92, 0x25}, 2, 0},
|
||||
{0x86, (uint8_t []){0xC6, 0x04, 0xB1, 0x02, 0x58, 0x12, 0x58, 0x10, 0x13, 0x01, 0xAA, 0x00, 0xAA, 0xAA}, 14, 0},
|
||||
{0x87, (uint8_t []){0x10, 0x10, 0x58, 0x00, 0x02, 0x3A}, 6, 0},
|
||||
{0x88, (uint8_t []){0x00, 0x00, 0x2C, 0x10, 0x04, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x06}, 15, 0},
|
||||
{0x89, (uint8_t []){0x00, 0x00, 0x00}, 3, 0},
|
||||
{0x8A, (uint8_t []){0x13, 0x00, 0x2C, 0x00, 0x00, 0x2C, 0x10, 0x10, 0x00, 0x3E, 0x19}, 11, 0},
|
||||
{0x8B, (uint8_t []){0x15, 0xB1, 0xB1, 0x44, 0x96, 0x2C, 0x10, 0x97, 0x8E}, 9, 0}, // VGL Pump
|
||||
{0x8C, (uint8_t []){0x1D, 0xB1, 0xB1, 0x44, 0x96, 0x2C, 0x10, 0x50, 0x0F, 0x01, 0xC5, 0x12, 0x09}, 13, 0}, // VGH Pump
|
||||
{0x8D, (uint8_t []){0x0C}, 1, 0},
|
||||
{0x8E, (uint8_t []){0x33, 0x01, 0x0C, 0x13, 0x01, 0x01}, 6, 0},
|
||||
{0x90, (uint8_t []){0x00, 0x44, 0x33, 0x36, 0x00, 0x79, 0x40, 0xB6, 0xB6}, 9, 0},
|
||||
{0x91, (uint8_t []){0x00, 0x44, 0x33, 0x37, 0x00, 0x78, 0x40, 0xB6, 0xB6}, 9, 0},
|
||||
{0x92, (uint8_t []){0x02, 0x44, 0x55, 0x82, 0x86, 0x2F, 0x00, 0x04, 0x73, 0xB6}, 10, 0},
|
||||
{0x93, (uint8_t []){0x0C, 0x00, 0x11, 0x81, 0x87, 0x3F, 0x00, 0x00, 0x73, 0x73}, 10, 0},
|
||||
{0x94, (uint8_t []){0x08, 0x00, 0x00, 0x00, 0x00, 0x00}, 6, 0},
|
||||
{0x95, (uint8_t []){0x1A, 0x1A, 0x00, 0x00, 0xFF}, 5, 0},
|
||||
{0x96, (uint8_t []){0x44, 0x35, 0x07, 0x16, 0x20, 0x21, 0x07, 0x06, 0xB6, 0xB6, 0x00, 0x40}, 12, 0},
|
||||
{0x97, (uint8_t []){0x44, 0x35, 0x25, 0x34, 0x22, 0x23, 0x05, 0x04, 0xB6, 0xB6, 0x00, 0x40}, 12, 0},
|
||||
{0xBA, (uint8_t []){0x55, 0xB6, 0xB6, 0xB6, 0xB6}, 5, 0},
|
||||
{0x9A, (uint8_t []){0x40, 0x0C, 0x56, 0x01, 0x08, 0xB6, 0xB6}, 7, 0},
|
||||
{0x9B, (uint8_t []){0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00}, 7, 0},
|
||||
{0x9C, (uint8_t []){0x00, 0x12, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00}, 13, 0},
|
||||
{0x9D, (uint8_t []){0x80, 0x15, 0x00, 0x07, 0x01, 0x80, 0x73, 0x73}, 8, 0},
|
||||
{0x9E, (uint8_t []){0x00, 0x00, 0x00, 0x00, 0x80, 0x1E, 0x01}, 7, 0},
|
||||
{0x9F, (uint8_t []){0xA0, 0x09, 0x00, 0x57}, 4, 0},
|
||||
{0xB3, (uint8_t []){0x00, 0x30, 0x0F, 0x00, 0x00, 0x00, 0x00}, 7, 0},
|
||||
{0xB4, (uint8_t []){0x10, 0x1C, 0x19, 0x14, 0x18, 0x01, 0x1D, 0x03, 0x12, 0x0A, 0x11, 0x08}, 12, 0},
|
||||
{0xB5, (uint8_t []){0x1C, 0x1C, 0x19, 0x14, 0x18, 0x00, 0x1D, 0x02, 0x10, 0x0B, 0x13, 0x09}, 12, 0},
|
||||
{0xB6, (uint8_t []){0xFF, 0xFF, 0x00, 0x0F, 0xFE, 0x0F, 0xFE}, 7, 0},
|
||||
{0xB7, (uint8_t []){0x00, 0x09, 0x10, 0x0B, 0x0A, 0x06, 0x38, 0x04, 0x04, 0x4F, 0x09, 0x15, 0x15, 0x30, 0x37, 0x0F}, 16, 0}, // GammaP
|
||||
{0xB8, (uint8_t []){0x00, 0x09, 0x0F, 0x0A, 0x09, 0x05, 0x37, 0x03, 0x03, 0x4F, 0x09, 0x15, 0x15, 0x31, 0x36, 0x0F}, 16, 0}, // GammaN
|
||||
{0xB9, (uint8_t []){0x23, 0x23}, 2, 0},
|
||||
{0xBF, (uint8_t []){0x0F, 0x13, 0x13, 0x09, 0x09, 0x09}, 6, 0}, // VGHP/VGLP
|
||||
// ======================CMD3======================
|
||||
{0xF2, (uint8_t []){0x00}, 1, 0},
|
||||
{0x73, (uint8_t []){0x04, 0xBA, 0x1A, 0x58, 0x5B}, 5, 0}, // VOP= 5v
|
||||
{0x77, (uint8_t []){0x6B, 0x5B, 0xFB, 0xC3, 0xC5}, 5, 0},
|
||||
{0x7A, (uint8_t []){0x15, 0x27}, 2, 0},
|
||||
{0x7B, (uint8_t []){0x04, 0x57}, 2, 0},
|
||||
{0x7E, (uint8_t []){0x01, 0x0E}, 2, 0},
|
||||
{0xBF, (uint8_t []){0x36}, 1, 0},
|
||||
{0xE3, (uint8_t []){0x43, 0x43}, 2, 0}, // VMF
|
||||
// ======================CMD1======================
|
||||
{0xF0, (uint8_t []){0x00}, 1, 0},
|
||||
{0x21, (uint8_t []){0x00}, 1, 0},
|
||||
{0x11, (uint8_t []){0x00}, 1, 120},
|
||||
{0x35, (uint8_t []){0x00}, 1, 20},
|
||||
};
|
||||
|
||||
static esp_err_t panel_st77922_init(esp_lcd_panel_t *panel)
|
||||
{
|
||||
st77922_panel_t *st77922 = __containerof(panel, st77922_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = st77922->io;
|
||||
const esp_lcd_panel_vendor_init_cmd_t *init_cmds = NULL;
|
||||
uint16_t init_cmds_size = 0;
|
||||
bool is_user_set = true;
|
||||
bool is_cmd_overwritten = false;
|
||||
|
||||
// Switch to CMD1
|
||||
// ESP_RETURN_ON_ERROR(tx_param(st77922, io, ST77922_CMD_SET, NULL, 0), TAG, "send command failed");
|
||||
ESP_RETURN_ON_ERROR(tx_param(st77922, io, LCD_CMD_MADCTL, (uint8_t[]) {
|
||||
st77922->madctl_val,
|
||||
}, 1), TAG, "send command failed");
|
||||
ESP_RETURN_ON_ERROR(tx_param(st77922, io, LCD_CMD_COLMOD, (uint8_t[]) {
|
||||
st77922->colmod_val,
|
||||
}, 1), TAG, "send command failed");
|
||||
|
||||
// vendor specific initialization, it can be different between manufacturers
|
||||
// should consult the LCD supplier for initialization sequence code
|
||||
if (st77922->init_cmds) {
|
||||
init_cmds = st77922->init_cmds;
|
||||
init_cmds_size = st77922->init_cmds_size;
|
||||
} else {
|
||||
init_cmds = vendor_specific_init_default;
|
||||
init_cmds_size = sizeof(vendor_specific_init_default) / sizeof(esp_lcd_panel_vendor_init_cmd_t);
|
||||
}
|
||||
|
||||
for (int i = 0; i < init_cmds_size; i++) {
|
||||
// Check if the command has been used or conflicts with the internal
|
||||
if (is_user_set && (init_cmds[i].data_bytes > 0)) {
|
||||
switch (init_cmds[i].cmd) {
|
||||
case LCD_CMD_MADCTL:
|
||||
is_cmd_overwritten = true;
|
||||
st77922->madctl_val = ((uint8_t *)init_cmds[i].data)[0];
|
||||
break;
|
||||
case LCD_CMD_COLMOD:
|
||||
is_cmd_overwritten = true;
|
||||
st77922->colmod_val = ((uint8_t *)init_cmds[i].data)[0];
|
||||
break;
|
||||
default:
|
||||
is_cmd_overwritten = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_cmd_overwritten) {
|
||||
is_cmd_overwritten = false;
|
||||
ESP_LOGW(TAG, "The %02Xh command has been used and will be overwritten by external initialization sequence", init_cmds[i].cmd);
|
||||
}
|
||||
}
|
||||
|
||||
// Send command
|
||||
ESP_RETURN_ON_ERROR(tx_param(st77922, io, init_cmds[i].cmd, init_cmds[i].data, init_cmds[i].data_bytes), TAG, "send command failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(init_cmds[i].delay_ms));
|
||||
|
||||
// Check if the current cmd is the "command set" cmd
|
||||
is_user_set = (init_cmds[i].cmd == ST77922_CMD_SET) ? true : false;
|
||||
}
|
||||
ESP_LOGD(TAG, "send init commands success");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_st77922_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data)
|
||||
{
|
||||
st77922_panel_t *st77922 = __containerof(panel, st77922_panel_t, base);
|
||||
assert((x_start < x_end) && (y_start < y_end) && "start position must be smaller than end position");
|
||||
esp_lcd_panel_io_handle_t io = st77922->io;
|
||||
|
||||
x_start += st77922->x_gap;
|
||||
x_end += st77922->x_gap;
|
||||
y_start += st77922->y_gap;
|
||||
y_end += st77922->y_gap;
|
||||
|
||||
// define an area of frame memory where MCU can access
|
||||
ESP_RETURN_ON_ERROR(tx_param(st77922, io, LCD_CMD_CASET, (uint8_t[]) {
|
||||
(x_start >> 8) & 0xFF,
|
||||
x_start & 0xFF,
|
||||
((x_end - 1) >> 8) & 0xFF,
|
||||
(x_end - 1) & 0xFF,
|
||||
}, 4), TAG, "send command failed");
|
||||
ESP_RETURN_ON_ERROR(tx_param(st77922, io, LCD_CMD_RASET, (uint8_t[]) {
|
||||
(y_start >> 8) & 0xFF,
|
||||
y_start & 0xFF,
|
||||
((y_end - 1) >> 8) & 0xFF,
|
||||
(y_end - 1) & 0xFF,
|
||||
}, 4), TAG, "send command failed");
|
||||
// transfer frame buffer
|
||||
size_t len = (x_end - x_start) * (y_end - y_start) * st77922->fb_bits_per_pixel / 8;
|
||||
tx_color(st77922, io, LCD_CMD_RAMWR, color_data, len);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_st77922_invert_color(esp_lcd_panel_t *panel, bool invert_color_data)
|
||||
{
|
||||
st77922_panel_t *st77922 = __containerof(panel, st77922_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = st77922->io;
|
||||
int command = 0;
|
||||
if (invert_color_data) {
|
||||
command = LCD_CMD_INVON;
|
||||
} else {
|
||||
command = LCD_CMD_INVOFF;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(tx_param(st77922, io, command, NULL, 0), TAG, "send command failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_st77922_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y)
|
||||
{
|
||||
st77922_panel_t *st77922 = __containerof(panel, st77922_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = st77922->io;
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
if (mirror_x) {
|
||||
st77922->madctl_val |= BIT(6);
|
||||
} else {
|
||||
st77922->madctl_val &= ~BIT(6);
|
||||
}
|
||||
if (mirror_y) {
|
||||
st77922->madctl_val |= BIT(7);
|
||||
} else {
|
||||
st77922->madctl_val &= ~BIT(7);
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(tx_param(st77922, io, LCD_CMD_MADCTL, (uint8_t[]) {
|
||||
st77922->madctl_val
|
||||
}, 1), TAG, "send command failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t panel_st77922_swap_xy(esp_lcd_panel_t *panel, bool swap_axes)
|
||||
{
|
||||
ESP_LOGE(TAG, "swap_xy is not supported by this panel");
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
static esp_err_t panel_st77922_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap)
|
||||
{
|
||||
st77922_panel_t *st77922 = __containerof(panel, st77922_panel_t, base);
|
||||
st77922->x_gap = x_gap;
|
||||
st77922->y_gap = y_gap;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_st77922_disp_on_off(esp_lcd_panel_t *panel, bool on_off)
|
||||
{
|
||||
st77922_panel_t *st77922 = __containerof(panel, st77922_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = st77922->io;
|
||||
int command = 0;
|
||||
|
||||
if (on_off) {
|
||||
command = LCD_CMD_DISPON;
|
||||
} else {
|
||||
command = LCD_CMD_DISPOFF;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(tx_param(st77922, io, command, NULL, 0), TAG, "send command failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_LCD_ST77922_VER_MAJOR (0)
|
||||
#define ESP_LCD_ST77922_VER_MINOR (0)
|
||||
#define ESP_LCD_ST77922_VER_PATCH (2)
|
||||
|
||||
/**
|
||||
* @brief Create LCD panel for model ST77922
|
||||
*
|
||||
* @param[in] io LCD panel IO handle
|
||||
* @param[in] panel_dev_config General panel device configuration (Use `vendor_config` to select QSPI interface or override default initialization commands)
|
||||
* @param[out] ret_panel Returned LCD panel handle
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - Otherwise: Fail
|
||||
*/
|
||||
esp_err_t esp_lcd_new_panel_st77922(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel);
|
||||
|
||||
/**
|
||||
* @brief LCD panel bus configuration structure
|
||||
*
|
||||
*/
|
||||
#define ST77922_PANEL_BUS_SPI_CONFIG(sclk, mosi, max_trans_sz) \
|
||||
{ \
|
||||
.sclk_io_num = sclk, \
|
||||
.mosi_io_num = mosi, \
|
||||
.miso_io_num = -1, \
|
||||
.quadhd_io_num = -1, \
|
||||
.quadwp_io_num = -1, \
|
||||
.max_transfer_sz = max_trans_sz, \
|
||||
}
|
||||
#define ST77922_PANEL_BUS_QSPI_CONFIG(sclk, d0, d1, d2, d3, max_trans_sz)\
|
||||
{ \
|
||||
.sclk_io_num = sclk, \
|
||||
.data0_io_num = d0, \
|
||||
.data1_io_num = d1, \
|
||||
.data2_io_num = d2, \
|
||||
.data3_io_num = d3, \
|
||||
.max_transfer_sz = max_trans_sz, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief LCD panel IO configuration structure
|
||||
*
|
||||
*/
|
||||
#define ST77922_PANEL_IO_SPI_CONFIG(cs, dc, cb, cb_ctx) \
|
||||
{ \
|
||||
.cs_gpio_num = cs, \
|
||||
.dc_gpio_num = dc, \
|
||||
.spi_mode = 0, \
|
||||
.pclk_hz = 40 * 1000 * 1000, \
|
||||
.trans_queue_depth = 10, \
|
||||
.on_color_trans_done = cb, \
|
||||
.user_ctx = cb_ctx, \
|
||||
.lcd_cmd_bits = 8, \
|
||||
.lcd_param_bits = 8, \
|
||||
}
|
||||
#define ST77922_PANEL_IO_QSPI_CONFIG(cs, cb, cb_ctx) \
|
||||
{ \
|
||||
.cs_gpio_num = cs, \
|
||||
.dc_gpio_num = -1, \
|
||||
.spi_mode = 0, \
|
||||
.pclk_hz = 40 * 1000 * 1000, \
|
||||
.trans_queue_depth = 10, \
|
||||
.on_color_trans_done = cb, \
|
||||
.user_ctx = cb_ctx, \
|
||||
.lcd_cmd_bits = 32, \
|
||||
.lcd_param_bits = 8, \
|
||||
.flags = { \
|
||||
.quad_mode = true, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
+357
@@ -0,0 +1,357 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_lcd_panel_interface.h"
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
#include "esp_lcd_panel_ops.h"
|
||||
#include "esp_lcd_panel_commands.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
|
||||
#include "esp_lcd_custom_types.h"
|
||||
#include "esp_lcd_st7796.h"
|
||||
|
||||
static const char *TAG = "st7796";
|
||||
|
||||
static esp_err_t panel_st7796_del(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_st7796_reset(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_st7796_init(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_st7796_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data);
|
||||
static esp_err_t panel_st7796_invert_color(esp_lcd_panel_t *panel, bool invert_color_data);
|
||||
static esp_err_t panel_st7796_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y);
|
||||
static esp_err_t panel_st7796_swap_xy(esp_lcd_panel_t *panel, bool swap_axes);
|
||||
static esp_err_t panel_st7796_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap);
|
||||
static esp_err_t panel_st7796_disp_on_off(esp_lcd_panel_t *panel, bool off);
|
||||
|
||||
typedef struct {
|
||||
esp_lcd_panel_t base;
|
||||
esp_lcd_panel_io_handle_t io;
|
||||
int reset_gpio_num;
|
||||
bool reset_level;
|
||||
int x_gap;
|
||||
int y_gap;
|
||||
uint8_t fb_bits_per_pixel;
|
||||
uint8_t madctl_val; // save current value of LCD_CMD_MADCTL register
|
||||
uint8_t colmod_val; // save current value of LCD_CMD_COLMOD register
|
||||
const esp_lcd_panel_vendor_init_cmd_t *init_cmds;
|
||||
uint16_t init_cmds_size;
|
||||
} st7796_panel_t;
|
||||
|
||||
esp_err_t esp_lcd_new_panel_st7796(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel)
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
st7796_panel_t *st7796 = NULL;
|
||||
gpio_config_t io_conf = { 0 };
|
||||
|
||||
ESP_GOTO_ON_FALSE(io && panel_dev_config && ret_panel, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
||||
st7796 = (st7796_panel_t *)calloc(1, sizeof(st7796_panel_t));
|
||||
ESP_GOTO_ON_FALSE(st7796, ESP_ERR_NO_MEM, err, TAG, "no mem for st7796 panel");
|
||||
|
||||
if (panel_dev_config->reset_gpio_num >= 0) {
|
||||
io_conf.mode = GPIO_MODE_OUTPUT;
|
||||
io_conf.pin_bit_mask = 1ULL << panel_dev_config->reset_gpio_num;
|
||||
ESP_GOTO_ON_ERROR(gpio_config(&io_conf), err, TAG, "configure GPIO for RST line failed");
|
||||
}
|
||||
|
||||
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
switch (panel_dev_config->color_space) {
|
||||
case ESP_LCD_COLOR_SPACE_RGB:
|
||||
st7796->madctl_val = 0;
|
||||
break;
|
||||
case ESP_LCD_COLOR_SPACE_BGR:
|
||||
st7796->madctl_val |= LCD_CMD_BGR_BIT;
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported color space");
|
||||
break;
|
||||
}
|
||||
#else
|
||||
switch (panel_dev_config->rgb_endian) {
|
||||
case LCD_RGB_ENDIAN_RGB:
|
||||
st7796->madctl_val = 0;
|
||||
break;
|
||||
case LCD_RGB_ENDIAN_BGR:
|
||||
st7796->madctl_val |= LCD_CMD_BGR_BIT;
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported rgb endian");
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (panel_dev_config->bits_per_pixel) {
|
||||
case 16: // RGB565
|
||||
st7796->colmod_val = 0x05;
|
||||
st7796->fb_bits_per_pixel = 16;
|
||||
break;
|
||||
case 18: // RGB666
|
||||
st7796->colmod_val = 0x06;
|
||||
// each color component (R/G/B) should occupy the 6 high bits of a byte, which means 3 full bytes are required for a pixel
|
||||
st7796->fb_bits_per_pixel = 24;
|
||||
break;
|
||||
case 24: // RGB888
|
||||
st7796->colmod_val = 0x07;
|
||||
st7796->fb_bits_per_pixel = 24;
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported pixel width");
|
||||
break;
|
||||
}
|
||||
|
||||
st7796->io = io;
|
||||
st7796->reset_gpio_num = panel_dev_config->reset_gpio_num;
|
||||
st7796->reset_level = panel_dev_config->flags.reset_active_high;
|
||||
if (panel_dev_config->vendor_config) {
|
||||
st7796->init_cmds = ((esp_lcd_panel_vendor_config_t *)panel_dev_config->vendor_config)->init_cmds;
|
||||
st7796->init_cmds_size = ((esp_lcd_panel_vendor_config_t *)panel_dev_config->vendor_config)->init_cmds_size;
|
||||
}
|
||||
st7796->base.del = panel_st7796_del;
|
||||
st7796->base.reset = panel_st7796_reset;
|
||||
st7796->base.init = panel_st7796_init;
|
||||
st7796->base.draw_bitmap = panel_st7796_draw_bitmap;
|
||||
st7796->base.invert_color = panel_st7796_invert_color;
|
||||
st7796->base.set_gap = panel_st7796_set_gap;
|
||||
st7796->base.mirror = panel_st7796_mirror;
|
||||
st7796->base.swap_xy = panel_st7796_swap_xy;
|
||||
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
st7796->base.disp_off = panel_st7796_disp_on_off;
|
||||
#else
|
||||
st7796->base.disp_on_off = panel_st7796_disp_on_off;
|
||||
#endif
|
||||
*ret_panel = &(st7796->base);
|
||||
ESP_LOGD(TAG, "new st7796 panel @%p", st7796);
|
||||
|
||||
ESP_LOGI(TAG, "LCD panel create success, version: %d.%d.%d", ESP_LCD_ST7796_VER_MAJOR, ESP_LCD_ST7796_VER_MINOR,
|
||||
ESP_LCD_ST7796_VER_PATCH);
|
||||
|
||||
return ESP_OK;
|
||||
|
||||
err:
|
||||
if (st7796) {
|
||||
if (panel_dev_config->reset_gpio_num >= 0) {
|
||||
gpio_reset_pin(panel_dev_config->reset_gpio_num);
|
||||
}
|
||||
free(st7796);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t panel_st7796_del(esp_lcd_panel_t *panel)
|
||||
{
|
||||
st7796_panel_t *st7796 = __containerof(panel, st7796_panel_t, base);
|
||||
|
||||
if (st7796->reset_gpio_num >= 0) {
|
||||
gpio_reset_pin(st7796->reset_gpio_num);
|
||||
}
|
||||
ESP_LOGD(TAG, "del st7796 panel @%p", st7796);
|
||||
free(st7796);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_st7796_reset(esp_lcd_panel_t *panel)
|
||||
{
|
||||
st7796_panel_t *st7796 = __containerof(panel, st7796_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = st7796->io;
|
||||
|
||||
// perform hardware reset
|
||||
if (st7796->reset_gpio_num >= 0) {
|
||||
gpio_set_level(st7796->reset_gpio_num, st7796->reset_level);
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
gpio_set_level(st7796->reset_gpio_num, !st7796->reset_level);
|
||||
vTaskDelay(pdMS_TO_TICKS(120));
|
||||
} else { // perform software reset
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_SWRESET, NULL, 0), TAG, "send command failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(120)); // spec, wait at least 5ms before sending new command
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static const esp_lcd_panel_vendor_init_cmd_t vendor_specific_init_default[] = {
|
||||
// {cmd, { data }, data_size, delay_ms}
|
||||
{0xf0, (uint8_t []){0xc3}, 1, 0},
|
||||
{0xf0, (uint8_t []){0x96}, 1, 0},
|
||||
{0xb4, (uint8_t []){0x01}, 1, 0},
|
||||
{0xb7, (uint8_t []){0xc6}, 1, 0},
|
||||
{0xe8, (uint8_t []){0x40, 0x8a, 0x00, 0x00, 0x29, 0x19, 0xa5, 0x33}, 8, 0},
|
||||
{0xc1, (uint8_t []){0x06}, 1, 0},
|
||||
{0xc2, (uint8_t []){0xa7}, 1, 0},
|
||||
{0xc5, (uint8_t []){0x18}, 1, 0},
|
||||
{0xe0, (uint8_t []){0xf0, 0x09, 0x0b, 0x06, 0x04, 0x15, 0x2f, 0x54, 0x42, 0x3c, 0x17, 0x14, 0x18, 0x1b}, 14, 0},
|
||||
{0xe1, (uint8_t []){0xf0, 0x09, 0x0b, 0x06, 0x04, 0x03, 0x2d, 0x43, 0x42, 0x3b, 0x16, 0x14, 0x17, 0x1b}, 14, 0},
|
||||
{0xf0, (uint8_t []){0x3c}, 1, 0},
|
||||
{0xf0, (uint8_t []){0x69}, 1, 0},
|
||||
};
|
||||
|
||||
static esp_err_t panel_st7796_init(esp_lcd_panel_t *panel)
|
||||
{
|
||||
st7796_panel_t *st7796 = __containerof(panel, st7796_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = st7796->io;
|
||||
|
||||
// LCD goes into sleep mode and display will be turned off after power on reset, exit sleep mode first
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_SLPOUT, NULL, 0), TAG, "send command failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]) {
|
||||
st7796->madctl_val,
|
||||
}, 1), TAG, "send command failed");
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_COLMOD, (uint8_t[]) {
|
||||
st7796->colmod_val,
|
||||
}, 1), TAG, "send command failed");
|
||||
|
||||
const esp_lcd_panel_vendor_init_cmd_t *init_cmds = NULL;
|
||||
uint16_t init_cmds_size = 0;
|
||||
if (st7796->init_cmds) {
|
||||
init_cmds = st7796->init_cmds;
|
||||
init_cmds_size = st7796->init_cmds_size;
|
||||
} else {
|
||||
init_cmds = vendor_specific_init_default;
|
||||
init_cmds_size = sizeof(vendor_specific_init_default) / sizeof(esp_lcd_panel_vendor_init_cmd_t);
|
||||
}
|
||||
|
||||
bool is_cmd_overwritten = false;
|
||||
for (int i = 0; i < init_cmds_size; i++) {
|
||||
// Check if the command has been used or conflicts with the internal
|
||||
switch (init_cmds[i].cmd) {
|
||||
case LCD_CMD_MADCTL:
|
||||
is_cmd_overwritten = true;
|
||||
st7796->madctl_val = ((uint8_t *)init_cmds[i].data)[0];
|
||||
break;
|
||||
case LCD_CMD_COLMOD:
|
||||
is_cmd_overwritten = true;
|
||||
st7796->colmod_val = ((uint8_t *)init_cmds[i].data)[0];
|
||||
break;
|
||||
default:
|
||||
is_cmd_overwritten = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_cmd_overwritten) {
|
||||
ESP_LOGW(TAG, "The %02Xh command has been used and will be overwritten by external initialization sequence", init_cmds[i].cmd);
|
||||
}
|
||||
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, init_cmds[i].cmd, init_cmds[i].data, init_cmds[i].data_bytes), TAG, "send command failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(init_cmds[i].delay_ms));
|
||||
}
|
||||
ESP_LOGD(TAG, "send init commands success");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_st7796_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data)
|
||||
{
|
||||
st7796_panel_t *st7796 = __containerof(panel, st7796_panel_t, base);
|
||||
assert((x_start < x_end) && (y_start < y_end) && "start position must be smaller than end position");
|
||||
esp_lcd_panel_io_handle_t io = st7796->io;
|
||||
|
||||
x_start += st7796->x_gap;
|
||||
x_end += st7796->x_gap;
|
||||
y_start += st7796->y_gap;
|
||||
y_end += st7796->y_gap;
|
||||
|
||||
// define an area of frame memory where MCU can access
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_CASET, (uint8_t[]) {
|
||||
(x_start >> 8) & 0xFF,
|
||||
x_start & 0xFF,
|
||||
((x_end - 1) >> 8) & 0xFF,
|
||||
(x_end - 1) & 0xFF,
|
||||
}, 4), TAG, "send command failed");
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_RASET, (uint8_t[]) {
|
||||
(y_start >> 8) & 0xFF,
|
||||
y_start & 0xFF,
|
||||
((y_end - 1) >> 8) & 0xFF,
|
||||
(y_end - 1) & 0xFF,
|
||||
}, 4), TAG, "send command failed");
|
||||
// transfer frame buffer
|
||||
size_t len = (x_end - x_start) * (y_end - y_start) * st7796->fb_bits_per_pixel / 8;
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_color(io, LCD_CMD_RAMWR, color_data, len), TAG, "send command failed");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_st7796_invert_color(esp_lcd_panel_t *panel, bool invert_color_data)
|
||||
{
|
||||
st7796_panel_t *st7796 = __containerof(panel, st7796_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = st7796->io;
|
||||
int command = 0;
|
||||
if (invert_color_data) {
|
||||
command = LCD_CMD_INVON;
|
||||
} else {
|
||||
command = LCD_CMD_INVOFF;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, command, NULL, 0), TAG, "send command failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_st7796_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y)
|
||||
{
|
||||
st7796_panel_t *st7796 = __containerof(panel, st7796_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = st7796->io;
|
||||
if (mirror_x) {
|
||||
st7796->madctl_val |= LCD_CMD_MX_BIT;
|
||||
} else {
|
||||
st7796->madctl_val &= ~LCD_CMD_MX_BIT;
|
||||
}
|
||||
if (mirror_y) {
|
||||
st7796->madctl_val |= LCD_CMD_MY_BIT;
|
||||
} else {
|
||||
st7796->madctl_val &= ~LCD_CMD_MY_BIT;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]) {
|
||||
st7796->madctl_val
|
||||
}, 1), TAG, "send command failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_st7796_swap_xy(esp_lcd_panel_t *panel, bool swap_axes)
|
||||
{
|
||||
st7796_panel_t *st7796 = __containerof(panel, st7796_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = st7796->io;
|
||||
if (swap_axes) {
|
||||
st7796->madctl_val |= LCD_CMD_MV_BIT;
|
||||
} else {
|
||||
st7796->madctl_val &= ~LCD_CMD_MV_BIT;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]) {
|
||||
st7796->madctl_val
|
||||
}, 1), TAG, "send command failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_st7796_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap)
|
||||
{
|
||||
st7796_panel_t *st7796 = __containerof(panel, st7796_panel_t, base);
|
||||
st7796->x_gap = x_gap;
|
||||
st7796->y_gap = y_gap;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_st7796_disp_on_off(esp_lcd_panel_t *panel, bool on_off)
|
||||
{
|
||||
st7796_panel_t *st7796 = __containerof(panel, st7796_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = st7796->io;
|
||||
int command = 0;
|
||||
|
||||
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
on_off = !on_off;
|
||||
#endif
|
||||
|
||||
if (on_off) {
|
||||
command = LCD_CMD_DISPON;
|
||||
} else {
|
||||
command = LCD_CMD_DISPOFF;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, command, NULL, 0), TAG, "send command failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
* @brief ESP LCD: ST7796
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hal/lcd_types.h"
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_LCD_ST7796_VER_MAJOR (1)
|
||||
#define ESP_LCD_ST7796_VER_MINOR (2)
|
||||
#define ESP_LCD_ST7796_VER_PATCH (1)
|
||||
/**
|
||||
* @brief Create LCD panel for model ST7796
|
||||
*
|
||||
* @note Vendor specific initialization can be different between manufacturers, should consult the LCD supplier for initialization sequence code.
|
||||
*
|
||||
* @param[in] io LCD panel IO handle
|
||||
* @param[in] panel_dev_config general panel device configuration
|
||||
* @param[out] ret_panel Returned LCD panel handle
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG if parameter is invalid
|
||||
* - ESP_ERR_NO_MEM if out of memory
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t esp_lcd_new_panel_st7796(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel);
|
||||
|
||||
/**
|
||||
* @brief LCD panel bus configuration structure
|
||||
*
|
||||
* @param[in] max_trans_bytes Maximum bytes of data to be transferred in one transaction. Normally set to the size of one frame bytes.
|
||||
* @param[in] data_width Data bus width
|
||||
* @param[in] dc I80 data/command pin number
|
||||
* @param[in] wr I80 write clock pin number
|
||||
* @param[in] d[0:15] I80 data pin number 0 ~ 15. Set to -1 if not used.
|
||||
*
|
||||
*/
|
||||
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 4, 1)
|
||||
#define ST7796_PANEL_BUS_I80_CONFIG(max_trans_bytes, data_width, dc, wr, d0, d1, d2, d3, d4, \
|
||||
d5, d6, d7, d8 , d9, d10, d11, d12, d13, d14, d15) \
|
||||
{ \
|
||||
.clk_src = LCD_CLK_SRC_PLL160M, \
|
||||
.dc_gpio_num = dc, \
|
||||
.wr_gpio_num = wr, \
|
||||
.data_gpio_nums = { \
|
||||
d0, d1, d2, d3, d4, d5, d6, d7, d8 , d9, d10, d11, d12, d13, d14, d15 \
|
||||
}, \
|
||||
.bus_width = data_width, \
|
||||
.max_transfer_bytes = max_trans_bytes, \
|
||||
}
|
||||
#else
|
||||
#define ST7796_PANEL_BUS_I80_CONFIG(max_trans_bytes, data_width, dc, wr, d0, d1, d2, d3, d4, \
|
||||
d5, d6, d7, d8 , d9, d10, d11, d12, d13, d14, d15) \
|
||||
{ \
|
||||
.clk_src = LCD_CLK_SRC_PLL160M, \
|
||||
.dc_gpio_num = dc, \
|
||||
.wr_gpio_num = wr, \
|
||||
.data_gpio_nums = { \
|
||||
d0, d1, d2, d3, d4, d5, d6, d7, d8 , d9, d10, d11, d12, d13, d14, d15 \
|
||||
}, \
|
||||
.bus_width = data_width, \
|
||||
.max_transfer_bytes = max_trans_bytes, \
|
||||
.psram_trans_align = 64, \
|
||||
.sram_trans_align = 4, \
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief LCD panel IO configuration structure
|
||||
*
|
||||
* @param[in] cs I80 chip select pin number
|
||||
* @param[in] cb Callback function when data transfer is done
|
||||
* @param[in] cb_ctx Callback function context
|
||||
*
|
||||
*/
|
||||
#define ST7796_PANEL_IO_I80_CONFIG(cs, cb, cb_ctx) \
|
||||
{ \
|
||||
.cs_gpio_num = cs, \
|
||||
.pclk_hz = 10 * 1000 * 1000, \
|
||||
.trans_queue_depth = 10, \
|
||||
.dc_levels = { \
|
||||
.dc_idle_level = 0, \
|
||||
.dc_cmd_level = 0, \
|
||||
.dc_dummy_level = 0, \
|
||||
.dc_data_level = 1, \
|
||||
}, \
|
||||
.flags = { \
|
||||
.swap_color_bytes = 1, \
|
||||
}, \
|
||||
.on_color_trans_done = cb, \
|
||||
.user_ctx = cb_ctx, \
|
||||
.lcd_cmd_bits = 8, \
|
||||
.lcd_param_bits = 8, \
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ESP_PanelLog.h"
|
||||
#include "CST816S.h"
|
||||
|
||||
static const char *TAG = "CST816S_CPP";
|
||||
|
||||
ESP_PanelTouch_CST816S::ESP_PanelTouch_CST816S(ESP_PanelBus *bus, uint16_t width, uint16_t height,
|
||||
int rst_io, int int_io):
|
||||
ESP_PanelTouch(bus, width, height, rst_io, int_io)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelTouch_CST816S::ESP_PanelTouch_CST816S(ESP_PanelBus *bus, const esp_lcd_touch_config_t &config):
|
||||
ESP_PanelTouch(bus, config)
|
||||
{
|
||||
}
|
||||
|
||||
ESP_PanelTouch_CST816S::~ESP_PanelTouch_CST816S()
|
||||
{
|
||||
ESP_PANEL_ENABLE_TAG_DEBUG_LOG();
|
||||
|
||||
if (handle == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!del()) {
|
||||
ESP_LOGE(TAG, "Delete device failed");
|
||||
}
|
||||
|
||||
end:
|
||||
ESP_LOGD(TAG, "Destroyed");
|
||||
}
|
||||
|
||||
bool ESP_PanelTouch_CST816S::begin(void)
|
||||
{
|
||||
ESP_PANEL_CHECK_NULL_RET(bus, false, "Invalid bus");
|
||||
|
||||
ESP_PANEL_CHECK_ERR_RET(esp_lcd_touch_new_i2c_cst816s(bus->getHandle(), &config, &handle), false, "New driver failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/esp_lcd_touch_cst816s.h"
|
||||
#include "ESP_PanelTouch.h"
|
||||
|
||||
/**
|
||||
* @brief CST816S touch device object class
|
||||
*
|
||||
* @note This class is a derived class of `ESP_PanelTouch`, user can use it directly
|
||||
*/
|
||||
class ESP_PanelTouch_CST816S : public ESP_PanelTouch {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new touch device in a simple way, the `init()` function should be called after this function
|
||||
*
|
||||
* @param bus Pointer to panel bus
|
||||
* @param width The width of the touch screen
|
||||
* @param height The height of the touch screen
|
||||
* @param rst_io The reset pin of the touch screen, set to `-1` if not used
|
||||
* @param int_io The interrupt pin of the touch screen, set to `-1` if not used
|
||||
*/
|
||||
ESP_PanelTouch_CST816S(ESP_PanelBus *bus, uint16_t width, uint16_t height, int rst_io = -1, int int_io = -1);
|
||||
|
||||
/**
|
||||
* @brief Construct a new touch device in a complex way, the `init()` function should be called after this function
|
||||
*
|
||||
* @param bus Pointer to panel bus
|
||||
* @param config Touch device configuration
|
||||
*/
|
||||
ESP_PanelTouch_CST816S(ESP_PanelBus *bus, const esp_lcd_touch_config_t &config);
|
||||
|
||||
/**
|
||||
* @brief Destroy the LCD device
|
||||
*
|
||||
*/
|
||||
~ESP_PanelTouch_CST816S() override;
|
||||
|
||||
/**
|
||||
* @brief Startup the touch device
|
||||
*
|
||||
* @return true if success, otherwise false
|
||||
*/
|
||||
bool begin(void) override;
|
||||
};
|
||||
Loaded 100 of 1862 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user