mirror of
https://github.com/garagetinkering/Video_Game_Mini_Maps.git
synced 2026-01-17 17:47:00 +01:00
initial commit
This commit is contained in:
@@ -0,0 +1 @@
|
||||
a191822f1d90de977e15f2d6f58783b288b782f82a980c4d6ea4c1fd75aba6f2
|
||||
37
managed_components/espressif__esp_lcd_jd9365/CHANGELOG.md
Normal file
37
managed_components/espressif__esp_lcd_jd9365/CHANGELOG.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# ChangeLog
|
||||
|
||||
## v1.0.4 - 2025-09-29
|
||||
|
||||
### bugfix:
|
||||
|
||||
* Check the return value of the underlying deletion function. If it fails, propagate the error
|
||||
|
||||
## v1.0.3 - 2025-09-15
|
||||
|
||||
### Changes:
|
||||
|
||||
* Updated phy_clk_src default value from MIPI_DSI_PHY_CLK_SRC_DEFAULT to 0
|
||||
|
||||
## v1.0.2 - 2025-01-13
|
||||
|
||||
### bugfix:
|
||||
|
||||
* Fixed the issue with macro inclusion
|
||||
|
||||
## v1.0.1 - 2024-11-10
|
||||
|
||||
### bugfix:
|
||||
|
||||
* Modified the order of reading the ID register
|
||||
|
||||
## v1.0.0 - 2024-08-12
|
||||
|
||||
### Enhancements:
|
||||
|
||||
* Component version maintenance, code improvement, and documentation enhancement
|
||||
|
||||
## v0.1.0 - 2024-05-07
|
||||
|
||||
### Enhancements:
|
||||
|
||||
* Implement the driver for the JD9365 MIPI-DSI LCD controller
|
||||
@@ -0,0 +1,4 @@
|
||||
idf_component_register(SRCS "esp_lcd_jd9365.c" INCLUDE_DIRS "include" PRIV_REQUIRES "driver" REQUIRES "esp_lcd")
|
||||
|
||||
include(package_manager)
|
||||
cu_pkg_define_version(${CMAKE_CURRENT_LIST_DIR})
|
||||
83
managed_components/espressif__esp_lcd_jd9365/README.md
Normal file
83
managed_components/espressif__esp_lcd_jd9365/README.md
Normal file
@@ -0,0 +1,83 @@
|
||||
# ESP LCD JD9365
|
||||
|
||||
[](https://components.espressif.com/components/espressif/esp_lcd_jd9365)
|
||||
|
||||
Implementation of the JD9365 LCD controller with esp_lcd component.
|
||||
|
||||
| LCD controller | Communication interface | Component name | Link to datasheet |
|
||||
| :------------: | :---------------------: | :------------: | :-----------------------------------------------------------------------------------: |
|
||||
| JD9365 | MIPI-DSI | esp_lcd_jd9365 | [PDF](https://dl.espressif.com/AE/esp-iot-solution/JD9365DA-H3_DS_V0.01_20200819.pdf) |
|
||||
|
||||
**Note**: MIPI-DSI interface only supports ESP-IDF v5.3 and above versions.
|
||||
|
||||
For more information on LCD, please refer to the [LCD documentation](https://docs.espressif.com/projects/esp-iot-solution/en/latest/display/lcd/index.html).
|
||||
|
||||
## Add to project
|
||||
|
||||
Packages from this repository are uploaded to [Espressif's component service](https://components.espressif.com/).
|
||||
You can add them to your project via `idf.py add-dependancy`, e.g.
|
||||
|
||||
```
|
||||
idf.py add-dependency "espressif/esp_lcd_jd9365"
|
||||
```
|
||||
|
||||
Alternatively, you can create `idf_component.yml`. More is in [Espressif's documentation](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-component-manager.html).
|
||||
|
||||
## Example use
|
||||
|
||||
```c
|
||||
/**
|
||||
* Uncomment these line if use custom initialization commands.
|
||||
* The array should be declared as static const and positioned outside the function.
|
||||
*/
|
||||
// static const jd9365_lcd_init_cmd_t lcd_init_cmds[] = {
|
||||
// {cmd, { data }, data_size, delay_ms}
|
||||
// {0xE0, (uint8_t []){0x00}, 1, 0},
|
||||
// {0xE1, (uint8_t []){0x93}, 1, 0},
|
||||
// {0xE2, (uint8_t []){0x65}, 1, 0},
|
||||
// {0xE3, (uint8_t []){0xF8}, 1, 0},
|
||||
// ...
|
||||
// };
|
||||
|
||||
ESP_LOGI(TAG, "MIPI DSI PHY Powered on");
|
||||
esp_ldo_channel_handle_t ldo_mipi_phy = NULL;
|
||||
esp_ldo_channel_config_t ldo_mipi_phy_config = {
|
||||
.chan_id = 3,
|
||||
.voltage_mv = 2500,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_ldo_acquire_channel(&ldo_mipi_phy_config, &ldo_mipi_phy));
|
||||
|
||||
ESP_LOGI(TAG, "Initialize MIPI DSI bus");
|
||||
esp_lcd_dsi_bus_handle_t mipi_dsi_bus = NULL;
|
||||
esp_lcd_dsi_bus_config_t bus_config = JD9365_PANEL_BUS_DSI_2CH_CONFIG();
|
||||
ESP_ERROR_CHECK(esp_lcd_new_dsi_bus(&bus_config, &mipi_dsi_bus));
|
||||
|
||||
ESP_LOGI(TAG, "Install panel IO");
|
||||
esp_lcd_panel_io_handle_t mipi_dbi_io = NULL;
|
||||
esp_lcd_dbi_io_config_t dbi_config = JD9365_PANEL_IO_DBI_CONFIG();
|
||||
ESP_ERROR_CHECK(esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &dbi_config, &mipi_dbi_io));
|
||||
|
||||
ESP_LOGI(TAG, "Install JD9365S panel driver");
|
||||
esp_lcd_panel_handle_t panel_handle = NULL;
|
||||
const esp_lcd_dpi_panel_config_t dpi_config = JD9365_800_1280_PANEL_60HZ_DPI_CONFIG(EXAMPLE_MIPI_DPI_PX_FORMAT);
|
||||
jd9365_vendor_config_t vendor_config = {
|
||||
.lane_num = 2,
|
||||
.flags = {
|
||||
.use_mipi_interface = 1,
|
||||
},
|
||||
.mipi_config = {
|
||||
.dsi_bus = mipi_dsi_bus,
|
||||
.dpi_config = &dpi_config,
|
||||
},
|
||||
};
|
||||
const esp_lcd_panel_dev_config_t panel_config = {
|
||||
.reset_gpio_num = EXAMPLE_LCD_IO_RST, // Set to -1 if not use
|
||||
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, // Implemented by LCD command `36h`
|
||||
.bits_per_pixel = EXAMPLE_LCD_BIT_PER_PIXEL, // Implemented by LCD command `3Ah` (16/18/24)
|
||||
.vendor_config = &vendor_config,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_lcd_new_panel_jd9365(mipi_dbi_io, &panel_config, &panel_handle));
|
||||
ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle));
|
||||
ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle));
|
||||
ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true));
|
||||
```
|
||||
531
managed_components/espressif__esp_lcd_jd9365/esp_lcd_jd9365.c
Normal file
531
managed_components/espressif__esp_lcd_jd9365/esp_lcd_jd9365.c
Normal file
@@ -0,0 +1,531 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if SOC_MIPI_DSI_SUPPORTED
|
||||
#include "esp_check.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_lcd_panel_commands.h"
|
||||
#include "esp_lcd_panel_interface.h"
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "esp_lcd_mipi_dsi.h"
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_lcd_jd9365.h"
|
||||
|
||||
#define JD9365_CMD_PAGE (0xE0)
|
||||
#define JD9365_PAGE_USER (0x00)
|
||||
|
||||
#define JD9365_CMD_DSI_INT0 (0x80)
|
||||
#define JD9365_DSI_1_LANE (0x00)
|
||||
#define JD9365_DSI_2_LANE (0x01)
|
||||
#define JD9365_DSI_3_LANE (0x10)
|
||||
#define JD9365_DSI_4_LANE (0x11)
|
||||
|
||||
#define JD9365_CMD_GS_BIT (1 << 0)
|
||||
#define JD9365_CMD_SS_BIT (1 << 1)
|
||||
|
||||
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 surrent value of LCD_CMD_COLMOD register
|
||||
const jd9365_lcd_init_cmd_t *init_cmds;
|
||||
uint16_t init_cmds_size;
|
||||
uint8_t lane_num;
|
||||
struct {
|
||||
unsigned int reset_level: 1;
|
||||
} flags;
|
||||
// To save the original functions of MIPI DPI panel
|
||||
esp_err_t (*del)(esp_lcd_panel_t *panel);
|
||||
esp_err_t (*init)(esp_lcd_panel_t *panel);
|
||||
} jd9365_panel_t;
|
||||
|
||||
static const char *TAG = "jd9365";
|
||||
|
||||
static esp_err_t panel_jd9365_del(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_jd9365_init(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_jd9365_reset(esp_lcd_panel_t *panel);
|
||||
static esp_err_t panel_jd9365_invert_color(esp_lcd_panel_t *panel, bool invert_color_data);
|
||||
static esp_err_t panel_jd9365_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y);
|
||||
static esp_err_t panel_jd9365_disp_on_off(esp_lcd_panel_t *panel, bool on_off);
|
||||
|
||||
esp_err_t esp_lcd_new_panel_jd9365(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_LOGI(TAG, "version: %d.%d.%d", ESP_LCD_JD9365_VER_MAJOR, ESP_LCD_JD9365_VER_MINOR,
|
||||
ESP_LCD_JD9365_VER_PATCH);
|
||||
ESP_RETURN_ON_FALSE(io && panel_dev_config && ret_panel, ESP_ERR_INVALID_ARG, TAG, "invalid arguments");
|
||||
jd9365_vendor_config_t *vendor_config = (jd9365_vendor_config_t *)panel_dev_config->vendor_config;
|
||||
ESP_RETURN_ON_FALSE(vendor_config && vendor_config->mipi_config.dpi_config && vendor_config->mipi_config.dsi_bus, ESP_ERR_INVALID_ARG, TAG,
|
||||
"invalid vendor config");
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
jd9365_panel_t *jd9365 = (jd9365_panel_t *)calloc(1, sizeof(jd9365_panel_t));
|
||||
ESP_RETURN_ON_FALSE(jd9365, ESP_ERR_NO_MEM, TAG, "no mem for jd9365 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->color_space) {
|
||||
case LCD_RGB_ELEMENT_ORDER_RGB:
|
||||
jd9365->madctl_val = 0;
|
||||
break;
|
||||
case LCD_RGB_ELEMENT_ORDER_BGR:
|
||||
jd9365->madctl_val |= LCD_CMD_BGR_BIT;
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported color space");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (panel_dev_config->bits_per_pixel) {
|
||||
case 16: // RGB565
|
||||
jd9365->colmod_val = 0x55;
|
||||
break;
|
||||
case 18: // RGB666
|
||||
jd9365->colmod_val = 0x66;
|
||||
break;
|
||||
case 24: // RGB888
|
||||
jd9365->colmod_val = 0x77;
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported pixel width");
|
||||
break;
|
||||
}
|
||||
|
||||
jd9365->io = io;
|
||||
jd9365->init_cmds = vendor_config->init_cmds;
|
||||
jd9365->init_cmds_size = vendor_config->init_cmds_size;
|
||||
jd9365->lane_num = vendor_config->mipi_config.lane_num;
|
||||
jd9365->reset_gpio_num = panel_dev_config->reset_gpio_num;
|
||||
jd9365->flags.reset_level = panel_dev_config->flags.reset_active_high;
|
||||
|
||||
// Create MIPI DPI panel
|
||||
esp_lcd_panel_handle_t panel_handle = NULL;
|
||||
ESP_GOTO_ON_ERROR(esp_lcd_new_panel_dpi(vendor_config->mipi_config.dsi_bus, vendor_config->mipi_config.dpi_config, &panel_handle), err, TAG,
|
||||
"create MIPI DPI panel failed");
|
||||
ESP_LOGD(TAG, "new MIPI DPI panel @%p", panel_handle);
|
||||
|
||||
// Save the original functions of MIPI DPI panel
|
||||
jd9365->del = panel_handle->del;
|
||||
jd9365->init = panel_handle->init;
|
||||
// Overwrite the functions of MIPI DPI panel
|
||||
panel_handle->del = panel_jd9365_del;
|
||||
panel_handle->init = panel_jd9365_init;
|
||||
panel_handle->reset = panel_jd9365_reset;
|
||||
panel_handle->mirror = panel_jd9365_mirror;
|
||||
panel_handle->invert_color = panel_jd9365_invert_color;
|
||||
panel_handle->disp_on_off = panel_jd9365_disp_on_off;
|
||||
panel_handle->user_data = jd9365;
|
||||
*ret_panel = panel_handle;
|
||||
ESP_LOGD(TAG, "new jd9365 panel @%p", jd9365);
|
||||
|
||||
return ESP_OK;
|
||||
|
||||
err:
|
||||
if (jd9365) {
|
||||
if (panel_dev_config->reset_gpio_num >= 0) {
|
||||
gpio_reset_pin(panel_dev_config->reset_gpio_num);
|
||||
}
|
||||
free(jd9365);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const jd9365_lcd_init_cmd_t vendor_specific_init_default[] = {
|
||||
// {cmd, { data }, data_size, delay_ms}
|
||||
{0xE0, (uint8_t []){0x00}, 1, 0},
|
||||
|
||||
{0xE1, (uint8_t []){0x93}, 1, 0},
|
||||
{0xE2, (uint8_t []){0x65}, 1, 0},
|
||||
{0xE3, (uint8_t []){0xF8}, 1, 0},
|
||||
|
||||
{0xE0, (uint8_t []){0x01}, 1, 0},
|
||||
{0x00, (uint8_t []){0x00}, 1, 0},
|
||||
{0x01, (uint8_t []){0x4E}, 1, 0},
|
||||
{0x03, (uint8_t []){0x00}, 1, 0},
|
||||
{0x04, (uint8_t []){0x65}, 1, 0},
|
||||
|
||||
{0x0C, (uint8_t []){0x74}, 1, 0},
|
||||
|
||||
{0x17, (uint8_t []){0x00}, 1, 0},
|
||||
{0x18, (uint8_t []){0xB7}, 1, 0},
|
||||
{0x19, (uint8_t []){0x00}, 1, 0},
|
||||
{0x1A, (uint8_t []){0x00}, 1, 0},
|
||||
{0x1B, (uint8_t []){0xB7}, 1, 0},
|
||||
{0x1C, (uint8_t []){0x00}, 1, 0},
|
||||
|
||||
{0x24, (uint8_t []){0xFE}, 1, 0},
|
||||
|
||||
{0x37, (uint8_t []){0x19}, 1, 0},
|
||||
|
||||
{0x38, (uint8_t []){0x05}, 1, 0},
|
||||
{0x39, (uint8_t []){0x00}, 1, 0},
|
||||
{0x3A, (uint8_t []){0x01}, 1, 0},
|
||||
{0x3B, (uint8_t []){0x01}, 1, 0},
|
||||
{0x3C, (uint8_t []){0x70}, 1, 0},
|
||||
{0x3D, (uint8_t []){0xFF}, 1, 0},
|
||||
{0x3E, (uint8_t []){0xFF}, 1, 0},
|
||||
{0x3F, (uint8_t []){0xFF}, 1, 0},
|
||||
|
||||
{0x40, (uint8_t []){0x06}, 1, 0},
|
||||
{0x41, (uint8_t []){0xA0}, 1, 0},
|
||||
{0x43, (uint8_t []){0x1E}, 1, 0},
|
||||
{0x44, (uint8_t []){0x0F}, 1, 0},
|
||||
{0x45, (uint8_t []){0x28}, 1, 0},
|
||||
{0x4B, (uint8_t []){0x04}, 1, 0},
|
||||
|
||||
{0x55, (uint8_t []){0x02}, 1, 0},
|
||||
{0x56, (uint8_t []){0x01}, 1, 0},
|
||||
{0x57, (uint8_t []){0xA9}, 1, 0},
|
||||
{0x58, (uint8_t []){0x0A}, 1, 0},
|
||||
{0x59, (uint8_t []){0x0A}, 1, 0},
|
||||
{0x5A, (uint8_t []){0x37}, 1, 0},
|
||||
{0x5B, (uint8_t []){0x19}, 1, 0},
|
||||
|
||||
{0x5D, (uint8_t []){0x78}, 1, 0},
|
||||
{0x5E, (uint8_t []){0x63}, 1, 0},
|
||||
{0x5F, (uint8_t []){0x54}, 1, 0},
|
||||
{0x60, (uint8_t []){0x49}, 1, 0},
|
||||
{0x61, (uint8_t []){0x45}, 1, 0},
|
||||
{0x62, (uint8_t []){0x38}, 1, 0},
|
||||
{0x63, (uint8_t []){0x3D}, 1, 0},
|
||||
{0x64, (uint8_t []){0x28}, 1, 0},
|
||||
{0x65, (uint8_t []){0x43}, 1, 0},
|
||||
{0x66, (uint8_t []){0x41}, 1, 0},
|
||||
{0x67, (uint8_t []){0x43}, 1, 0},
|
||||
{0x68, (uint8_t []){0x62}, 1, 0},
|
||||
{0x69, (uint8_t []){0x50}, 1, 0},
|
||||
{0x6A, (uint8_t []){0x57}, 1, 0},
|
||||
{0x6B, (uint8_t []){0x49}, 1, 0},
|
||||
{0x6C, (uint8_t []){0x44}, 1, 0},
|
||||
{0x6D, (uint8_t []){0x37}, 1, 0},
|
||||
{0x6E, (uint8_t []){0x23}, 1, 0},
|
||||
{0x6F, (uint8_t []){0x10}, 1, 0},
|
||||
{0x70, (uint8_t []){0x78}, 1, 0},
|
||||
{0x71, (uint8_t []){0x63}, 1, 0},
|
||||
{0x72, (uint8_t []){0x54}, 1, 0},
|
||||
{0x73, (uint8_t []){0x49}, 1, 0},
|
||||
{0x74, (uint8_t []){0x45}, 1, 0},
|
||||
{0x75, (uint8_t []){0x38}, 1, 0},
|
||||
{0x76, (uint8_t []){0x3D}, 1, 0},
|
||||
{0x77, (uint8_t []){0x28}, 1, 0},
|
||||
{0x78, (uint8_t []){0x43}, 1, 0},
|
||||
{0x79, (uint8_t []){0x41}, 1, 0},
|
||||
{0x7A, (uint8_t []){0x43}, 1, 0},
|
||||
{0x7B, (uint8_t []){0x62}, 1, 0},
|
||||
{0x7C, (uint8_t []){0x50}, 1, 0},
|
||||
{0x7D, (uint8_t []){0x57}, 1, 0},
|
||||
{0x7E, (uint8_t []){0x49}, 1, 0},
|
||||
{0x7F, (uint8_t []){0x44}, 1, 0},
|
||||
{0x80, (uint8_t []){0x37}, 1, 0},
|
||||
{0x81, (uint8_t []){0x23}, 1, 0},
|
||||
{0x82, (uint8_t []){0x10}, 1, 0},
|
||||
|
||||
{0xE0, (uint8_t []){0x02}, 1, 0},
|
||||
{0x00, (uint8_t []){0x47}, 1, 0},
|
||||
{0x01, (uint8_t []){0x47}, 1, 0},
|
||||
{0x02, (uint8_t []){0x45}, 1, 0},
|
||||
{0x03, (uint8_t []){0x45}, 1, 0},
|
||||
{0x04, (uint8_t []){0x4B}, 1, 0},
|
||||
{0x05, (uint8_t []){0x4B}, 1, 0},
|
||||
{0x06, (uint8_t []){0x49}, 1, 0},
|
||||
{0x07, (uint8_t []){0x49}, 1, 0},
|
||||
{0x08, (uint8_t []){0x41}, 1, 0},
|
||||
{0x09, (uint8_t []){0x1F}, 1, 0},
|
||||
{0x0A, (uint8_t []){0x1F}, 1, 0},
|
||||
{0x0B, (uint8_t []){0x1F}, 1, 0},
|
||||
{0x0C, (uint8_t []){0x1F}, 1, 0},
|
||||
{0x0D, (uint8_t []){0x1F}, 1, 0},
|
||||
{0x0E, (uint8_t []){0x1F}, 1, 0},
|
||||
{0x0F, (uint8_t []){0x5F}, 1, 0},
|
||||
{0x10, (uint8_t []){0x5F}, 1, 0},
|
||||
{0x11, (uint8_t []){0x57}, 1, 0},
|
||||
{0x12, (uint8_t []){0x77}, 1, 0},
|
||||
{0x13, (uint8_t []){0x35}, 1, 0},
|
||||
{0x14, (uint8_t []){0x1F}, 1, 0},
|
||||
{0x15, (uint8_t []){0x1F}, 1, 0},
|
||||
|
||||
{0x16, (uint8_t []){0x46}, 1, 0},
|
||||
{0x17, (uint8_t []){0x46}, 1, 0},
|
||||
{0x18, (uint8_t []){0x44}, 1, 0},
|
||||
{0x19, (uint8_t []){0x44}, 1, 0},
|
||||
{0x1A, (uint8_t []){0x4A}, 1, 0},
|
||||
{0x1B, (uint8_t []){0x4A}, 1, 0},
|
||||
{0x1C, (uint8_t []){0x48}, 1, 0},
|
||||
{0x1D, (uint8_t []){0x48}, 1, 0},
|
||||
{0x1E, (uint8_t []){0x40}, 1, 0},
|
||||
{0x1F, (uint8_t []){0x1F}, 1, 0},
|
||||
{0x20, (uint8_t []){0x1F}, 1, 0},
|
||||
{0x21, (uint8_t []){0x1F}, 1, 0},
|
||||
{0x22, (uint8_t []){0x1F}, 1, 0},
|
||||
{0x23, (uint8_t []){0x1F}, 1, 0},
|
||||
{0x24, (uint8_t []){0x1F}, 1, 0},
|
||||
{0x25, (uint8_t []){0x5F}, 1, 0},
|
||||
{0x26, (uint8_t []){0x5F}, 1, 0},
|
||||
{0x27, (uint8_t []){0x57}, 1, 0},
|
||||
{0x28, (uint8_t []){0x77}, 1, 0},
|
||||
{0x29, (uint8_t []){0x35}, 1, 0},
|
||||
{0x2A, (uint8_t []){0x1F}, 1, 0},
|
||||
{0x2B, (uint8_t []){0x1F}, 1, 0},
|
||||
|
||||
{0x58, (uint8_t []){0x40}, 1, 0},
|
||||
{0x59, (uint8_t []){0x00}, 1, 0},
|
||||
{0x5A, (uint8_t []){0x00}, 1, 0},
|
||||
{0x5B, (uint8_t []){0x10}, 1, 0},
|
||||
{0x5C, (uint8_t []){0x06}, 1, 0},
|
||||
{0x5D, (uint8_t []){0x40}, 1, 0},
|
||||
{0x5E, (uint8_t []){0x01}, 1, 0},
|
||||
{0x5F, (uint8_t []){0x02}, 1, 0},
|
||||
{0x60, (uint8_t []){0x30}, 1, 0},
|
||||
{0x61, (uint8_t []){0x01}, 1, 0},
|
||||
{0x62, (uint8_t []){0x02}, 1, 0},
|
||||
{0x63, (uint8_t []){0x03}, 1, 0},
|
||||
{0x64, (uint8_t []){0x6B}, 1, 0},
|
||||
{0x65, (uint8_t []){0x05}, 1, 0},
|
||||
{0x66, (uint8_t []){0x0C}, 1, 0},
|
||||
{0x67, (uint8_t []){0x73}, 1, 0},
|
||||
{0x68, (uint8_t []){0x09}, 1, 0},
|
||||
{0x69, (uint8_t []){0x03}, 1, 0},
|
||||
{0x6A, (uint8_t []){0x56}, 1, 0},
|
||||
{0x6B, (uint8_t []){0x08}, 1, 0},
|
||||
{0x6C, (uint8_t []){0x00}, 1, 0},
|
||||
{0x6D, (uint8_t []){0x04}, 1, 0},
|
||||
{0x6E, (uint8_t []){0x04}, 1, 0},
|
||||
{0x6F, (uint8_t []){0x88}, 1, 0},
|
||||
{0x70, (uint8_t []){0x00}, 1, 0},
|
||||
{0x71, (uint8_t []){0x00}, 1, 0},
|
||||
{0x72, (uint8_t []){0x06}, 1, 0},
|
||||
{0x73, (uint8_t []){0x7B}, 1, 0},
|
||||
{0x74, (uint8_t []){0x00}, 1, 0},
|
||||
{0x75, (uint8_t []){0xF8}, 1, 0},
|
||||
{0x76, (uint8_t []){0x00}, 1, 0},
|
||||
{0x77, (uint8_t []){0xD5}, 1, 0},
|
||||
{0x78, (uint8_t []){0x2E}, 1, 0},
|
||||
{0x79, (uint8_t []){0x12}, 1, 0},
|
||||
{0x7A, (uint8_t []){0x03}, 1, 0},
|
||||
{0x7B, (uint8_t []){0x00}, 1, 0},
|
||||
{0x7C, (uint8_t []){0x00}, 1, 0},
|
||||
{0x7D, (uint8_t []){0x03}, 1, 0},
|
||||
{0x7E, (uint8_t []){0x7B}, 1, 0},
|
||||
|
||||
{0xE0, (uint8_t []){0x04}, 1, 0},
|
||||
{0x00, (uint8_t []){0x0E}, 1, 0},
|
||||
{0x02, (uint8_t []){0xB3}, 1, 0},
|
||||
{0x09, (uint8_t []){0x60}, 1, 0},
|
||||
{0x0E, (uint8_t []){0x2A}, 1, 0},
|
||||
{0x36, (uint8_t []){0x59}, 1, 0},
|
||||
|
||||
{0xE0, (uint8_t []){0x00}, 1, 0},
|
||||
{0x11, (uint8_t []){0x00}, 1, 120},
|
||||
{0x29, (uint8_t []){0x00}, 1, 120},
|
||||
{0x35, (uint8_t []){0x00}, 1, 0},
|
||||
};
|
||||
|
||||
static esp_err_t panel_jd9365_del(esp_lcd_panel_t *panel)
|
||||
{
|
||||
jd9365_panel_t *jd9365 = (jd9365_panel_t *)panel->user_data;
|
||||
|
||||
// Delete MIPI DPI panel
|
||||
ESP_RETURN_ON_ERROR(jd9365->del(panel), TAG, "del jd9365 panel failed");
|
||||
if (jd9365->reset_gpio_num >= 0) {
|
||||
gpio_reset_pin(jd9365->reset_gpio_num);
|
||||
}
|
||||
ESP_LOGD(TAG, "del jd9365 panel @%p", jd9365);
|
||||
free(jd9365);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_jd9365_init(esp_lcd_panel_t *panel)
|
||||
{
|
||||
jd9365_panel_t *jd9365 = (jd9365_panel_t *)panel->user_data;
|
||||
esp_lcd_panel_io_handle_t io = jd9365->io;
|
||||
const jd9365_lcd_init_cmd_t *init_cmds = NULL;
|
||||
uint16_t init_cmds_size = 0;
|
||||
uint8_t lane_command = JD9365_DSI_2_LANE;
|
||||
bool is_user_set = true;
|
||||
bool is_cmd_overwritten = false;
|
||||
|
||||
switch (jd9365->lane_num) {
|
||||
case 0:
|
||||
lane_command = JD9365_DSI_2_LANE;
|
||||
break;
|
||||
case 1:
|
||||
lane_command = JD9365_DSI_1_LANE;
|
||||
break;
|
||||
case 2:
|
||||
lane_command = JD9365_DSI_2_LANE;
|
||||
break;
|
||||
case 3:
|
||||
lane_command = JD9365_DSI_3_LANE;
|
||||
break;
|
||||
case 4:
|
||||
lane_command = JD9365_DSI_4_LANE;
|
||||
break;
|
||||
default:
|
||||
ESP_LOGE(TAG, "Invalid lane number %d", jd9365->lane_num);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
uint8_t ID[3];
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_rx_param(io, 0x04, ID, 3), TAG, "read ID failed");
|
||||
ESP_LOGI(TAG, "LCD ID: %02X %02X %02X", ID[0], ID[1], ID[2]);
|
||||
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, JD9365_CMD_PAGE, (uint8_t[]) {
|
||||
JD9365_PAGE_USER
|
||||
}, 1), TAG, "send command failed");
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]) {
|
||||
jd9365->madctl_val,
|
||||
}, 1), TAG, "send command failed");
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_COLMOD, (uint8_t[]) {
|
||||
jd9365->colmod_val,
|
||||
}, 1), TAG, "send command failed");
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, JD9365_CMD_DSI_INT0, (uint8_t[]) {
|
||||
lane_command,
|
||||
}, 1), TAG, "send command failed");
|
||||
|
||||
// vendor specific initialization, it can be different between manufacturers
|
||||
// should consult the LCD supplier for initialization sequence code
|
||||
if (jd9365->init_cmds) {
|
||||
init_cmds = jd9365->init_cmds;
|
||||
init_cmds_size = jd9365->init_cmds_size;
|
||||
} else {
|
||||
init_cmds = vendor_specific_init_default;
|
||||
init_cmds_size = sizeof(vendor_specific_init_default) / sizeof(jd9365_lcd_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;
|
||||
jd9365->madctl_val = ((uint8_t *)init_cmds[i].data)[0];
|
||||
break;
|
||||
case LCD_CMD_COLMOD:
|
||||
is_cmd_overwritten = true;
|
||||
jd9365->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 "page set" cmd
|
||||
if ((init_cmds[i].cmd == JD9365_CMD_PAGE) && (init_cmds[i].data_bytes > 0)) {
|
||||
is_user_set = (((uint8_t *)init_cmds[i].data)[0] == JD9365_PAGE_USER);
|
||||
}
|
||||
}
|
||||
ESP_LOGD(TAG, "send init commands success");
|
||||
|
||||
ESP_RETURN_ON_ERROR(jd9365->init(panel), TAG, "init MIPI DPI panel failed");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_jd9365_reset(esp_lcd_panel_t *panel)
|
||||
{
|
||||
jd9365_panel_t *jd9365 = (jd9365_panel_t *)panel->user_data;
|
||||
esp_lcd_panel_io_handle_t io = jd9365->io;
|
||||
|
||||
// Perform hardware reset
|
||||
if (jd9365->reset_gpio_num >= 0) {
|
||||
gpio_set_level(jd9365->reset_gpio_num, !jd9365->flags.reset_level);
|
||||
vTaskDelay(pdMS_TO_TICKS(5));
|
||||
gpio_set_level(jd9365->reset_gpio_num, jd9365->flags.reset_level);
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
gpio_set_level(jd9365->reset_gpio_num, !jd9365->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));
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_jd9365_invert_color(esp_lcd_panel_t *panel, bool invert_color_data)
|
||||
{
|
||||
jd9365_panel_t *jd9365 = (jd9365_panel_t *)panel->user_data;
|
||||
esp_lcd_panel_io_handle_t io = jd9365->io;
|
||||
uint8_t command = 0;
|
||||
|
||||
ESP_RETURN_ON_FALSE(io, ESP_ERR_INVALID_STATE, TAG, "invalid panel IO");
|
||||
|
||||
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_jd9365_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y)
|
||||
{
|
||||
jd9365_panel_t *jd9365 = (jd9365_panel_t *)panel->user_data;
|
||||
esp_lcd_panel_io_handle_t io = jd9365->io;
|
||||
uint8_t madctl_val = jd9365->madctl_val;
|
||||
|
||||
ESP_RETURN_ON_FALSE(io, ESP_ERR_INVALID_STATE, TAG, "invalid panel IO");
|
||||
|
||||
// Control mirror through LCD command
|
||||
if (mirror_x) {
|
||||
madctl_val |= JD9365_CMD_GS_BIT;
|
||||
} else {
|
||||
madctl_val &= ~JD9365_CMD_GS_BIT;
|
||||
}
|
||||
if (mirror_y) {
|
||||
madctl_val |= JD9365_CMD_SS_BIT;
|
||||
} else {
|
||||
madctl_val &= ~JD9365_CMD_SS_BIT;
|
||||
}
|
||||
|
||||
ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t []) {
|
||||
madctl_val
|
||||
}, 1), TAG, "send command failed");
|
||||
jd9365->madctl_val = madctl_val;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t panel_jd9365_disp_on_off(esp_lcd_panel_t *panel, bool on_off)
|
||||
{
|
||||
jd9365_panel_t *jd9365 = (jd9365_panel_t *)panel->user_data;
|
||||
esp_lcd_panel_io_handle_t io = jd9365->io;
|
||||
int command = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,13 @@
|
||||
dependencies:
|
||||
cmake_utilities: 0.*
|
||||
idf: '>=5.3'
|
||||
description: ESP LCD JD9365(MIPI-DSI)
|
||||
issues: https://github.com/espressif/esp-iot-solution/issues
|
||||
repository: git://github.com/espressif/esp-iot-solution.git
|
||||
repository_info:
|
||||
commit_sha: 5f3e921d52c8b454449503bf7750df6fb6aa1764
|
||||
path: components/display/lcd/esp_lcd_jd9365
|
||||
targets:
|
||||
- esp32p4
|
||||
url: https://github.com/espressif/esp-iot-solution/tree/master/components/display/lcd/esp_lcd_jd9365
|
||||
version: 1.0.4
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if SOC_MIPI_DSI_SUPPORTED
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
#include "esp_lcd_mipi_dsi.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 */
|
||||
} jd9365_lcd_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 jd9365_lcd_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.
|
||||
*/
|
||||
uint16_t init_cmds_size; /*<! Number of commands in above array */
|
||||
struct {
|
||||
esp_lcd_dsi_bus_handle_t dsi_bus; /*!< MIPI-DSI bus configuration */
|
||||
const esp_lcd_dpi_panel_config_t *dpi_config; /*!< MIPI-DPI panel configuration */
|
||||
uint8_t lane_num; /*!< Number of MIPI-DSI lanes */
|
||||
} mipi_config;
|
||||
} jd9365_vendor_config_t;
|
||||
|
||||
/**
|
||||
* @brief Create LCD panel for model JD9365
|
||||
*
|
||||
* @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_OK on success
|
||||
* - Otherwise on fail
|
||||
*/
|
||||
esp_err_t esp_lcd_new_panel_jd9365(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 MIPI-DSI bus configuration structure
|
||||
*
|
||||
*/
|
||||
#define JD9365_PANEL_BUS_DSI_2CH_CONFIG() \
|
||||
{ \
|
||||
.bus_id = 0, \
|
||||
.num_data_lanes = 2, \
|
||||
.phy_clk_src = 0, \
|
||||
.lane_bit_rate_mbps = 1500, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief MIPI-DBI panel IO configuration structure
|
||||
*
|
||||
*/
|
||||
#define JD9365_PANEL_IO_DBI_CONFIG() \
|
||||
{ \
|
||||
.virtual_channel = 0, \
|
||||
.lcd_cmd_bits = 8, \
|
||||
.lcd_param_bits = 8, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief MIPI DPI configuration structure
|
||||
*
|
||||
* @note refresh_rate = (dpi_clock_freq_mhz * 1000000) / (h_res + hsync_pulse_width + hsync_back_porch + hsync_front_porch)
|
||||
* / (v_res + vsync_pulse_width + vsync_back_porch + vsync_front_porch)
|
||||
*
|
||||
* @param[in] px_format Pixel format of the panel
|
||||
*
|
||||
*/
|
||||
#define JD9365_800_1280_PANEL_60HZ_DPI_CONFIG(px_format) \
|
||||
{ \
|
||||
.dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT, \
|
||||
.dpi_clock_freq_mhz = 80, \
|
||||
.virtual_channel = 0, \
|
||||
.pixel_format = px_format, \
|
||||
.num_fbs = 1, \
|
||||
.video_timing = { \
|
||||
.h_size = 800, \
|
||||
.v_size = 1280, \
|
||||
.hsync_back_porch = 20, \
|
||||
.hsync_pulse_width = 20, \
|
||||
.hsync_front_porch = 40, \
|
||||
.vsync_back_porch = 12, \
|
||||
.vsync_pulse_width = 4, \
|
||||
.vsync_front_porch = 30, \
|
||||
}, \
|
||||
.flags.use_dma2d = true, \
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
202
managed_components/espressif__esp_lcd_jd9365/license.txt
Normal file
202
managed_components/espressif__esp_lcd_jd9365/license.txt
Normal file
@@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -0,0 +1,6 @@
|
||||
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
set(EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/unit-test-app/components")
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(test_esp_lcd_jd9365)
|
||||
@@ -0,0 +1 @@
|
||||
idf_component_register(SRCS "test_esp_lcd_jd9365.c")
|
||||
@@ -0,0 +1,5 @@
|
||||
## IDF Component Manager Manifest File
|
||||
dependencies:
|
||||
esp_lcd_jd9365:
|
||||
version: "*"
|
||||
path: "../../../esp_lcd_jd9365"
|
||||
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "driver/spi_master.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_lcd_panel_ops.h"
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "esp_lcd_mipi_dsi.h"
|
||||
#include "esp_ldo_regulator.h"
|
||||
#include "esp_dma_utils.h"
|
||||
#include "unity.h"
|
||||
#include "unity_test_runner.h"
|
||||
#include "unity_test_utils_memory.h"
|
||||
|
||||
#include "esp_lcd_jd9365.h"
|
||||
|
||||
#define TEST_LCD_H_RES (800)
|
||||
#define TEST_LCD_V_RES (1280)
|
||||
#define TEST_LCD_BIT_PER_PIXEL (24)
|
||||
#define TEST_PIN_NUM_LCD_RST (-1)
|
||||
#define TEST_PIN_NUM_BK_LIGHT (-1) // set to -1 if not used
|
||||
#define TEST_LCD_BK_LIGHT_ON_LEVEL (1)
|
||||
#define TEST_LCD_BK_LIGHT_OFF_LEVEL !TEST_LCD_BK_LIGHT_ON_LEVEL
|
||||
#define TEST_MIPI_DSI_LANE_NUM (2)
|
||||
|
||||
#if TEST_LCD_BIT_PER_PIXEL == 24
|
||||
#define TEST_MIPI_DPI_PX_FORMAT (LCD_COLOR_PIXEL_FORMAT_RGB888)
|
||||
#elif TEST_LCD_BIT_PER_PIXEL == 18
|
||||
#define TEST_MIPI_DPI_PX_FORMAT (LCD_COLOR_PIXEL_FORMAT_RGB666)
|
||||
#elif TEST_LCD_BIT_PER_PIXEL == 16
|
||||
#define TEST_MIPI_DPI_PX_FORMAT (LCD_COLOR_PIXEL_FORMAT_RGB565)
|
||||
#endif
|
||||
|
||||
#define TEST_DELAY_TIME_MS (3000)
|
||||
|
||||
#define TEST_MIPI_DSI_PHY_PWR_LDO_CHAN (3)
|
||||
#define TEST_MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV (2500)
|
||||
|
||||
static char *TAG = "jd9365_test";
|
||||
static esp_ldo_channel_handle_t ldo_mipi_phy = NULL;
|
||||
static esp_lcd_panel_handle_t panel_handle = NULL;
|
||||
static esp_lcd_dsi_bus_handle_t mipi_dsi_bus = NULL;
|
||||
static esp_lcd_panel_io_handle_t mipi_dbi_io = NULL;
|
||||
static SemaphoreHandle_t refresh_finish = NULL;
|
||||
|
||||
IRAM_ATTR static bool test_notify_refresh_ready(esp_lcd_panel_handle_t panel, esp_lcd_dpi_panel_event_data_t *edata, void *user_ctx)
|
||||
{
|
||||
SemaphoreHandle_t refresh_finish = (SemaphoreHandle_t)user_ctx;
|
||||
BaseType_t need_yield = pdFALSE;
|
||||
|
||||
xSemaphoreGiveFromISR(refresh_finish, &need_yield);
|
||||
|
||||
return (need_yield == pdTRUE);
|
||||
}
|
||||
|
||||
static void test_init_lcd(void)
|
||||
{
|
||||
#if TEST_PIN_NUM_BK_LIGHT >= 0
|
||||
ESP_LOGI(TAG, "Turn on LCD backlight");
|
||||
gpio_config_t bk_gpio_config = {
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pin_bit_mask = 1ULL << TEST_PIN_NUM_BK_LIGHT
|
||||
};
|
||||
TEST_ESP_OK(gpio_config(&bk_gpio_config));
|
||||
TEST_ESP_OK(gpio_set_level(TEST_PIN_NUM_BK_LIGHT, TEST_LCD_BK_LIGHT_ON_LEVEL));
|
||||
#endif
|
||||
|
||||
// Turn on the power for MIPI DSI PHY, so it can go from "No Power" state to "Shutdown" state
|
||||
#ifdef TEST_MIPI_DSI_PHY_PWR_LDO_CHAN
|
||||
ESP_LOGI(TAG, "MIPI DSI PHY Powered on");
|
||||
esp_ldo_channel_config_t ldo_mipi_phy_config = {
|
||||
.chan_id = TEST_MIPI_DSI_PHY_PWR_LDO_CHAN,
|
||||
.voltage_mv = TEST_MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV,
|
||||
};
|
||||
TEST_ESP_OK(esp_ldo_acquire_channel(&ldo_mipi_phy_config, &ldo_mipi_phy));
|
||||
#endif
|
||||
|
||||
ESP_LOGI(TAG, "Initialize MIPI DSI bus");
|
||||
esp_lcd_dsi_bus_config_t bus_config = JD9365_PANEL_BUS_DSI_2CH_CONFIG();
|
||||
TEST_ESP_OK(esp_lcd_new_dsi_bus(&bus_config, &mipi_dsi_bus));
|
||||
|
||||
ESP_LOGI(TAG, "Install panel IO");
|
||||
esp_lcd_dbi_io_config_t dbi_config = JD9365_PANEL_IO_DBI_CONFIG();
|
||||
TEST_ESP_OK(esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &dbi_config, &mipi_dbi_io));
|
||||
|
||||
ESP_LOGI(TAG, "Install LCD driver of jd9365");
|
||||
esp_lcd_dpi_panel_config_t dpi_config = JD9365_800_1280_PANEL_60HZ_DPI_CONFIG(TEST_MIPI_DPI_PX_FORMAT);
|
||||
jd9365_vendor_config_t vendor_config = {
|
||||
.mipi_config = {
|
||||
.dsi_bus = mipi_dsi_bus,
|
||||
.dpi_config = &dpi_config,
|
||||
.lane_num = TEST_MIPI_DSI_LANE_NUM,
|
||||
},
|
||||
};
|
||||
const esp_lcd_panel_dev_config_t panel_config = {
|
||||
.reset_gpio_num = TEST_PIN_NUM_LCD_RST,
|
||||
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
|
||||
.bits_per_pixel = TEST_LCD_BIT_PER_PIXEL,
|
||||
.vendor_config = &vendor_config,
|
||||
};
|
||||
TEST_ESP_OK(esp_lcd_new_panel_jd9365(mipi_dbi_io, &panel_config, &panel_handle));
|
||||
TEST_ESP_OK(esp_lcd_panel_reset(panel_handle));
|
||||
TEST_ESP_OK(esp_lcd_panel_init(panel_handle));
|
||||
TEST_ESP_OK(esp_lcd_panel_disp_on_off(panel_handle, true));
|
||||
|
||||
refresh_finish = xSemaphoreCreateBinary();
|
||||
TEST_ASSERT_NOT_NULL(refresh_finish);
|
||||
esp_lcd_dpi_panel_event_callbacks_t cbs = {
|
||||
.on_color_trans_done = test_notify_refresh_ready,
|
||||
};
|
||||
TEST_ESP_OK(esp_lcd_dpi_panel_register_event_callbacks(panel_handle, &cbs, refresh_finish));
|
||||
}
|
||||
|
||||
static void test_deinit_lcd(void)
|
||||
{
|
||||
TEST_ESP_OK(esp_lcd_panel_del(panel_handle));
|
||||
TEST_ESP_OK(esp_lcd_panel_io_del(mipi_dbi_io));
|
||||
TEST_ESP_OK(esp_lcd_del_dsi_bus(mipi_dsi_bus));
|
||||
panel_handle = NULL;
|
||||
mipi_dbi_io = NULL;
|
||||
mipi_dsi_bus = NULL;
|
||||
|
||||
if (ldo_mipi_phy) {
|
||||
TEST_ESP_OK(esp_ldo_release_channel(ldo_mipi_phy));
|
||||
ldo_mipi_phy = NULL;
|
||||
}
|
||||
|
||||
vSemaphoreDelete(refresh_finish);
|
||||
refresh_finish = NULL;
|
||||
|
||||
#if TEST_PIN_NUM_BK_LIGHT >= 0
|
||||
TEST_ESP_OK(gpio_reset_pin(TEST_PIN_NUM_BK_LIGHT));
|
||||
#endif
|
||||
}
|
||||
|
||||
static void test_draw_color_bar(esp_lcd_panel_handle_t panel_handle, uint16_t h_res, uint16_t v_res)
|
||||
{
|
||||
uint8_t byte_per_pixel = (TEST_LCD_BIT_PER_PIXEL + 7) / 8;
|
||||
uint16_t row_line = v_res / byte_per_pixel / 8;
|
||||
uint8_t *color = (uint8_t *)heap_caps_calloc(1, row_line * h_res * byte_per_pixel, MALLOC_CAP_DMA);
|
||||
|
||||
for (int j = 0; j < byte_per_pixel * 8; j++) {
|
||||
for (int i = 0; i < row_line * h_res; i++) {
|
||||
for (int k = 0; k < byte_per_pixel; k++) {
|
||||
color[i * byte_per_pixel + k] = (BIT(j) >> (k * 8)) & 0xff;
|
||||
}
|
||||
}
|
||||
TEST_ESP_OK(esp_lcd_panel_draw_bitmap(panel_handle, 0, j * row_line, h_res, (j + 1) * row_line, color));
|
||||
xSemaphoreTake(refresh_finish, portMAX_DELAY);
|
||||
}
|
||||
|
||||
uint16_t color_line = row_line * byte_per_pixel * 8;
|
||||
uint16_t res_line = v_res - color_line;
|
||||
if (res_line) {
|
||||
for (int i = 0; i < res_line * h_res; i++) {
|
||||
for (int k = 0; k < byte_per_pixel; k++) {
|
||||
color[i * byte_per_pixel + k] = 0xff;
|
||||
}
|
||||
}
|
||||
TEST_ESP_OK(esp_lcd_panel_draw_bitmap(panel_handle, 0, color_line, h_res, v_res, color));
|
||||
xSemaphoreTake(refresh_finish, portMAX_DELAY);
|
||||
}
|
||||
|
||||
free(color);
|
||||
}
|
||||
|
||||
TEST_CASE("test jd9365 to draw pattern with MIPI interface", "[jd9365][draw_pattern]")
|
||||
{
|
||||
ESP_LOGI(TAG, "Initialize LCD device");
|
||||
test_init_lcd();
|
||||
|
||||
ESP_LOGI(TAG, "Show color bar pattern drawn by hardware");
|
||||
TEST_ESP_OK(esp_lcd_dpi_panel_set_pattern(panel_handle, MIPI_DSI_PATTERN_BAR_VERTICAL));
|
||||
vTaskDelay(pdMS_TO_TICKS(TEST_DELAY_TIME_MS));
|
||||
TEST_ESP_OK(esp_lcd_dpi_panel_set_pattern(panel_handle, MIPI_DSI_PATTERN_BAR_HORIZONTAL));
|
||||
vTaskDelay(pdMS_TO_TICKS(TEST_DELAY_TIME_MS));
|
||||
TEST_ESP_OK(esp_lcd_dpi_panel_set_pattern(panel_handle, MIPI_DSI_PATTERN_NONE));
|
||||
|
||||
ESP_LOGI(TAG, "Deinitialize LCD device");
|
||||
test_deinit_lcd();
|
||||
}
|
||||
|
||||
TEST_CASE("test jd9365 to draw color bar with MIPI interface", "[jd9365][draw_color_bar]")
|
||||
{
|
||||
ESP_LOGI(TAG, "Initialize LCD device");
|
||||
test_init_lcd();
|
||||
|
||||
ESP_LOGI(TAG, "Show color bar drawn by software");
|
||||
test_draw_color_bar(panel_handle, TEST_LCD_H_RES, TEST_LCD_V_RES);
|
||||
vTaskDelay(pdMS_TO_TICKS(TEST_DELAY_TIME_MS));
|
||||
|
||||
ESP_LOGI(TAG, "Deinitialize LCD device");
|
||||
test_deinit_lcd();
|
||||
}
|
||||
|
||||
TEST_CASE("test jd9365 to rotate with MIPI interface", "[jd9365][rotate]")
|
||||
{
|
||||
ESP_LOGI(TAG, "Initialize LCD device");
|
||||
test_init_lcd();
|
||||
|
||||
ESP_LOGI(TAG, "Mirror the screen");
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
TEST_ASSERT_NOT_EQUAL(esp_lcd_panel_mirror(panel_handle, i & 2, i & 1), ESP_FAIL);
|
||||
|
||||
ESP_LOGI(TAG, "Mirror: %d", i);
|
||||
test_draw_color_bar(panel_handle, TEST_LCD_H_RES, TEST_LCD_V_RES);
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Deinitialize LCD device");
|
||||
test_deinit_lcd();
|
||||
}
|
||||
|
||||
// Some resources are lazy allocated in the LCD driver, the threadhold is left for that case
|
||||
#define TEST_MEMORY_LEAK_THRESHOLD (300)
|
||||
|
||||
static size_t before_free_8bit;
|
||||
static size_t before_free_32bit;
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
|
||||
unity_utils_check_leak(before_free_8bit, after_free_8bit, "8BIT", TEST_MEMORY_LEAK_THRESHOLD);
|
||||
unity_utils_check_leak(before_free_32bit, after_free_32bit, "32BIT", TEST_MEMORY_LEAK_THRESHOLD);
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
/**
|
||||
* __ ___ ___ _____ __ ____
|
||||
* \ \ / \/ _ \___ / / /_| ___|
|
||||
* \ \/ /\ / (_) ||_ \| '_ \___ \
|
||||
* /\_/ / /_// \__, |__) | (_) |__) |
|
||||
* \___/___,' /_/____/ \___/____/
|
||||
*/
|
||||
printf(" __ ___ ___ _____ __ ____\r\n");
|
||||
printf(" \\ \\ / \\/ _ \\___ / / /_| ___|\r\n");
|
||||
printf(" \\ \\/ /\\ / (_) ||_ \\| '_ \\___ \\\r\n");
|
||||
printf("/\\_/ / /_// \\__, |__) | (_) |__) |\r\n");
|
||||
printf("\\___/___,' /_/____/ \\___/____/\r\n");
|
||||
unity_run_menu();
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
CONFIG_ESP_TASK_WDT_EN=n
|
||||
CONFIG_FREERTOS_HZ=1000
|
||||
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4096
|
||||
@@ -0,0 +1,4 @@
|
||||
CONFIG_COMPILER_OPTIMIZATION_PERF=y
|
||||
CONFIG_SPIRAM=y
|
||||
CONFIG_SPIRAM_SPEED_200M=y
|
||||
CONFIG_IDF_EXPERIMENTAL_FEATURES=y
|
||||
Reference in New Issue
Block a user