mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 19:13:21 +00:00
Merge branch 'feat/support_lcd_on_s31' into 'master'
feat(lcd): support rgb and i80 lcd on s31 Closes IDF-14750, IDF-14751, IDF-14753, and IDF-14754 See merge request espressif/esp-idf!47312
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
#include "soc/hp_sys_clkrst_struct.h"
|
#include "soc/hp_sys_clkrst_struct.h"
|
||||||
|
|
||||||
#define LCD_LL_GET(_attr) LCD_LL_ ## _attr
|
#define LCD_LL_GET(_attr) LCD_LL_ ## _attr
|
||||||
|
#define LCD_LL_SUPPORT(_feat) LCD_LL_SUPPORT_ ## _feat
|
||||||
#define LCD_LL_RGB_BUS_WIDTH 24
|
#define LCD_LL_RGB_BUS_WIDTH 24
|
||||||
#define LCD_LL_RGB_PANEL_NUM 1
|
#define LCD_LL_RGB_PANEL_NUM 1
|
||||||
#define LCD_LL_I80_BUS_WIDTH 24
|
#define LCD_LL_I80_BUS_WIDTH 24
|
||||||
@@ -45,7 +46,10 @@ extern "C" {
|
|||||||
#define LCD_LL_CLK_FRAC_DIV_N_MAX 256 // LCD_CLK = LCD_CLK_S / (N + b/a), the N register is 8 bit-width
|
#define LCD_LL_CLK_FRAC_DIV_N_MAX 256 // LCD_CLK = LCD_CLK_S / (N + b/a), the N register is 8 bit-width
|
||||||
#define LCD_LL_CLK_FRAC_DIV_AB_MAX 64 // LCD_CLK = LCD_CLK_S / (N + b/a), the a/b register is 6 bit-width
|
#define LCD_LL_CLK_FRAC_DIV_AB_MAX 64 // LCD_CLK = LCD_CLK_S / (N + b/a), the a/b register is 6 bit-width
|
||||||
#define LCD_LL_PCLK_DIV_MAX 64 // LCD_PCLK = LCD_CLK / MO, the MO register is 6 bit-width
|
#define LCD_LL_PCLK_DIV_MAX 64 // LCD_PCLK = LCD_CLK / MO, the MO register is 6 bit-width
|
||||||
#define LCD_LL_FIFO_DEPTH 8 // Async FIFO depth
|
|
||||||
|
typedef enum {
|
||||||
|
LCD_LL_MEM_LP_MODE_SHUT_DOWN,
|
||||||
|
} lcd_ll_mem_lp_mode_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief LCD data byte swizzle mode
|
* @brief LCD data byte swizzle mode
|
||||||
@@ -172,6 +176,65 @@ static inline void lcd_ll_set_group_clock_coeff(lcd_cam_dev_t *dev, int div_num,
|
|||||||
lcd_ll_set_group_clock_coeff(__VA_ARGS__); \
|
lcd_ll_set_group_clock_coeff(__VA_ARGS__); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Force power on the LCD memory block, regardless of the outside PMU logic
|
||||||
|
*
|
||||||
|
* @param dev Peripheral instance address
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_mem_force_power_on(lcd_cam_dev_t *dev)
|
||||||
|
{
|
||||||
|
(void)dev;
|
||||||
|
// P4 does not have transfer buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Force the LCD memory block into low power mode, regardless of the outside PMU logic
|
||||||
|
*
|
||||||
|
* @param dev Peripheral instance address
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_mem_force_low_power(lcd_cam_dev_t *dev)
|
||||||
|
{
|
||||||
|
(void)dev;
|
||||||
|
// P4 does not have transfer buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Power control the LCD memory block by the outside PMU logic
|
||||||
|
*
|
||||||
|
* @param dev Peripheral instance address
|
||||||
|
* @param mode LCD memory low power mode in low power stage
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_mem_power_by_pmu(lcd_cam_dev_t *dev)
|
||||||
|
{
|
||||||
|
(void)dev;
|
||||||
|
// P4 does not have transfer buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set low power mode for LCD memory block
|
||||||
|
*
|
||||||
|
* @param dev Peripheral instance address
|
||||||
|
* @param mode LCD memory low power mode in low power stage
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_mem_set_low_power_mode(lcd_cam_dev_t *dev, lcd_ll_mem_lp_mode_t mode)
|
||||||
|
{
|
||||||
|
(void)dev;
|
||||||
|
HAL_ASSERT(mode == LCD_LL_MEM_LP_MODE_SHUT_DOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enable the transfer buffer(memory block) for LCD module
|
||||||
|
*
|
||||||
|
* @param dev Peripheral instance address
|
||||||
|
* @param en True to enable, False to disable
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_enable_trans_buffer(lcd_cam_dev_t *dev, bool en)
|
||||||
|
{
|
||||||
|
(void)dev;
|
||||||
|
(void)en;
|
||||||
|
// P4 does not have transfer buffer
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set the PCLK clock level state when there's no transaction undergoing
|
* @brief Set the PCLK clock level state when there's no transaction undergoing
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -85,18 +85,16 @@ const soc_lcd_rgb_signal_desc_t soc_lcd_rgb_signals[1] = {
|
|||||||
/**
|
/**
|
||||||
* LCD_CAM Registers to be saved during sleep retention
|
* LCD_CAM Registers to be saved during sleep retention
|
||||||
* - LCD Clock Configuration registers: LCDCAM_LCD_CLOCK_REG (0x0)
|
* - LCD Clock Configuration registers: LCDCAM_LCD_CLOCK_REG (0x0)
|
||||||
* - LCD RGB/YUV Configuration registers: LCDCAM_LCD_RGB_YUV_REG (0x10)
|
|
||||||
* - LCD User Configuration registers: LCDCAM_LCD_USER_REG (0x14), LCDCAM_LCD_MISC_REG (0x18)
|
* - LCD User Configuration registers: LCDCAM_LCD_USER_REG (0x14), LCDCAM_LCD_MISC_REG (0x18)
|
||||||
* - LCD Control registers: LCDCAM_LCD_CTRL_REG (0x1c), LCDCAM_LCD_CTRL1_REG (0x20), LCDCAM_LCD_CTRL2_REG (0x24)
|
* - LCD Control registers: LCDCAM_LCD_CTRL_REG (0x1c) (Note: lcd_rgb_mode_en is in this register)
|
||||||
* - LCD Command Value registers: LCDCAM_LCD_FIRST_CMD_VAL_REG (0x28), LCDCAM_LCD_LATTER_CMD_VAL_REG (0x2c)
|
|
||||||
* - LCD Delay Mode Configuration registers: LCDCAM_LCD_DLY_MODE_CFG1_REG (0x30), LCDCAM_LCD_DLY_MODE_CFG2_REG (0x38)
|
* - LCD Delay Mode Configuration registers: LCDCAM_LCD_DLY_MODE_CFG1_REG (0x30), LCDCAM_LCD_DLY_MODE_CFG2_REG (0x38)
|
||||||
* - LCD DMA Interrupt Enable register: LCDCAM_LC_DMA_INT_ENA_REG (0x64)
|
* - LCD DMA Interrupt Enable register: LCDCAM_LC_DMA_INT_ENA_REG (0x64)
|
||||||
*
|
*
|
||||||
* NOTE: Only I80 LCD supports sleep retention, not RGB LCD.
|
* NOTE: Only I80 LCD supports sleep retention, not RGB LCD.
|
||||||
*/
|
*/
|
||||||
#define LCD_RETENTION_REGS_CNT 12
|
#define LCD_RETENTION_REGS_CNT 7
|
||||||
#define LCD_RETENTION_REGS_BASE (DR_REG_LCDCAM_BASE + 0x0)
|
#define LCD_RETENTION_REGS_BASE (DR_REG_LCDCAM_BASE + 0x0)
|
||||||
static const uint32_t lcd_cam_regs_map[4] = {0x2005ff1, 0x0, 0x0, 0x0};
|
static const uint32_t lcd_cam_regs_map[4] = {0x20050e1, 0x0, 0x0, 0x0};
|
||||||
static const regdma_entries_config_t lcd_regs_retention[] = {
|
static const regdma_entries_config_t lcd_regs_retention[] = {
|
||||||
// backup stage: save configuration registers
|
// backup stage: save configuration registers
|
||||||
// restore stage: restore the configuration registers
|
// restore stage: restore the configuration registers
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "soc/system_struct.h"
|
#include "soc/system_struct.h"
|
||||||
|
|
||||||
#define LCD_LL_GET(_attr) LCD_LL_ ## _attr
|
#define LCD_LL_GET(_attr) LCD_LL_ ## _attr
|
||||||
|
#define LCD_LL_SUPPORT(_feat) LCD_LL_SUPPORT_ ## _feat
|
||||||
#define LCD_LL_RGB_BUS_WIDTH 16
|
#define LCD_LL_RGB_BUS_WIDTH 16
|
||||||
#define LCD_LL_RGB_PANEL_NUM 1
|
#define LCD_LL_RGB_PANEL_NUM 1
|
||||||
#define LCD_LL_I80_BUS_WIDTH 16
|
#define LCD_LL_I80_BUS_WIDTH 16
|
||||||
@@ -39,6 +40,10 @@ extern "C" {
|
|||||||
#define LCD_LL_PCLK_DIV_MAX 64 // LCD_PCLK = LCD_CLK / MO, the MO register is 6 bit-width
|
#define LCD_LL_PCLK_DIV_MAX 64 // LCD_PCLK = LCD_CLK / MO, the MO register is 6 bit-width
|
||||||
#define LCD_LL_FIFO_DEPTH 16 // Async FIFO depth
|
#define LCD_LL_FIFO_DEPTH 16 // Async FIFO depth
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
LCD_LL_MEM_LP_MODE_SHUT_DOWN,
|
||||||
|
} lcd_ll_mem_lp_mode_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief LCD data byte swizzle mode
|
* @brief LCD data byte swizzle mode
|
||||||
*/
|
*/
|
||||||
@@ -143,6 +148,65 @@ static inline void lcd_ll_set_group_clock_coeff(lcd_cam_dev_t *dev, int div_num,
|
|||||||
dev->lcd_clock.lcd_clkm_div_b = div_b;
|
dev->lcd_clock.lcd_clkm_div_b = div_b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Force power on the LCD memory block, regardless of the outside PMU logic
|
||||||
|
*
|
||||||
|
* @param dev Peripheral instance address
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_mem_force_power_on(lcd_cam_dev_t *dev)
|
||||||
|
{
|
||||||
|
(void)dev;
|
||||||
|
// S3 does not have transfer buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Force the LCD memory block into low power mode, regardless of the outside PMU logic
|
||||||
|
*
|
||||||
|
* @param dev Peripheral instance address
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_mem_force_low_power(lcd_cam_dev_t *dev)
|
||||||
|
{
|
||||||
|
(void)dev;
|
||||||
|
// S3 does not have transfer buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Power control the LCD memory block by the outside PMU logic
|
||||||
|
*
|
||||||
|
* @param dev Peripheral instance address
|
||||||
|
* @param mode LCD memory low power mode in low power stage
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_mem_power_by_pmu(lcd_cam_dev_t *dev)
|
||||||
|
{
|
||||||
|
(void)dev;
|
||||||
|
// S3 does not have transfer buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set low power mode for LCD memory block
|
||||||
|
*
|
||||||
|
* @param dev Peripheral instance address
|
||||||
|
* @param mode LCD memory low power mode in low power stage
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_mem_set_low_power_mode(lcd_cam_dev_t *dev, lcd_ll_mem_lp_mode_t mode)
|
||||||
|
{
|
||||||
|
(void)dev;
|
||||||
|
HAL_ASSERT(mode == LCD_LL_MEM_LP_MODE_SHUT_DOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enable the transfer buffer(memory block) for LCD module
|
||||||
|
*
|
||||||
|
* @param dev Peripheral instance address
|
||||||
|
* @param en True to enable, False to disable
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_enable_trans_buffer(lcd_cam_dev_t *dev, bool en)
|
||||||
|
{
|
||||||
|
(void)dev;
|
||||||
|
(void)en;
|
||||||
|
// S3 does not have transfer buffer
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set the PCLK clock level state when there's no transaction undergoing
|
* @brief Set the PCLK clock level state when there's no transaction undergoing
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -0,0 +1,854 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h> /* For NULL declaration */
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "hal/misc.h"
|
||||||
|
#include "soc/lcd_cam_reg.h"
|
||||||
|
#include "soc/lcd_cam_struct.h"
|
||||||
|
#include "hal/assert.h"
|
||||||
|
#include "hal/lcd_types.h"
|
||||||
|
#include "soc/hp_sys_clkrst_struct.h"
|
||||||
|
#include "soc/hp_system_struct.h"
|
||||||
|
|
||||||
|
#define LCD_LL_GET(_attr) LCD_LL_ ## _attr
|
||||||
|
#define LCD_LL_SUPPORT(_feat) LCD_LL_SUPPORT_ ## _feat
|
||||||
|
#define LCD_LL_RGB_BUS_WIDTH 24
|
||||||
|
#define LCD_LL_RGB_PANEL_NUM 1
|
||||||
|
#define LCD_LL_I80_BUS_WIDTH 24
|
||||||
|
#define LCD_LL_I80_BUS_NUM 1
|
||||||
|
|
||||||
|
#define LCD_LL_SUPPORT_IOMUX 1
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define LCD_LL_GET_HW(id) (((id) == 0) ? (&LCD_CAM) : NULL)
|
||||||
|
|
||||||
|
// Interrupt event, bit mask
|
||||||
|
#define LCD_LL_EVENT_VSYNC_END (1 << 0)
|
||||||
|
#define LCD_LL_EVENT_TRANS_DONE (1 << 1)
|
||||||
|
#define LCD_LL_EVENT_UNDERRUN (1 << 4)
|
||||||
|
|
||||||
|
#define LCD_LL_EVENT_I80 (LCD_LL_EVENT_TRANS_DONE | LCD_LL_EVENT_UNDERRUN)
|
||||||
|
#define LCD_LL_EVENT_RGB (LCD_LL_EVENT_VSYNC_END | LCD_LL_EVENT_UNDERRUN)
|
||||||
|
|
||||||
|
#define LCD_LL_CLK_FRAC_DIV_N_MAX 256 // LCD_CLK = LCD_CLK_S / (N + b/a), the N register is 8 bit-width
|
||||||
|
#define LCD_LL_CLK_FRAC_DIV_AB_MAX 64 // LCD_CLK = LCD_CLK_S / (N + b/a), the a/b register is 6 bit-width
|
||||||
|
#define LCD_LL_PCLK_DIV_MAX 64 // LCD_PCLK = LCD_CLK / MO, the MO register is 6 bit-width
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
LCD_LL_MEM_LP_MODE_DEEP_SLEEP, // memory will enter deep sleep during low power stage, keep memory data
|
||||||
|
LCD_LL_MEM_LP_MODE_LIGHT_SLEEP, // memory will enter light sleep during low power stage, keep memory data
|
||||||
|
LCD_LL_MEM_LP_MODE_SHUT_DOWN, // memory will be powered down during low power stage
|
||||||
|
LCD_LL_MEM_LP_MODE_DISABLE, // disable the low power stage
|
||||||
|
} lcd_ll_mem_lp_mode_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief LCD data byte swizzle mode
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
LCD_LL_SWIZZLE_AB2BA, /*!< AB -> BA */
|
||||||
|
LCD_LL_SWIZZLE_ABC2ACB, /*!< ABC -> ACB */
|
||||||
|
LCD_LL_SWIZZLE_ABC2BAC, /*!< ABC -> BAC */
|
||||||
|
LCD_LL_SWIZZLE_ABC2BCA, /*!< ABC -> BCA */
|
||||||
|
LCD_LL_SWIZZLE_ABC2CAB, /*!< ABC -> CAB */
|
||||||
|
LCD_LL_SWIZZLE_ABC2CBA, /*!< ABC -> CBA */
|
||||||
|
} lcd_ll_swizzle_mode_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enable the bus clock for LCD module
|
||||||
|
*
|
||||||
|
* @param group_id Group ID
|
||||||
|
* @param enable true to enable, false to disable
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_enable_bus_clock(int group_id, bool enable)
|
||||||
|
{
|
||||||
|
(void)group_id;
|
||||||
|
HP_SYS_CLKRST.lcdcam_ctrl0.reg_lcdcam_apb_clk_en = enable;
|
||||||
|
HP_SYS_CLKRST.lcdcam_ctrl0.reg_lcdcam_sys_clk_en = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||||
|
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
|
||||||
|
#define lcd_ll_enable_bus_clock(...) do { \
|
||||||
|
(void)__DECLARE_RCC_RC_ATOMIC_ENV; \
|
||||||
|
lcd_ll_enable_bus_clock(__VA_ARGS__); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reset the LCD module
|
||||||
|
*
|
||||||
|
* @param group_id Group ID
|
||||||
|
*/
|
||||||
|
static inline void _lcd_ll_reset_register(int group_id)
|
||||||
|
{
|
||||||
|
(void)group_id;
|
||||||
|
HP_SYS_CLKRST.lcdcam_ctrl0.reg_lcdcam_apb_rst_en = 1;
|
||||||
|
HP_SYS_CLKRST.lcdcam_ctrl0.reg_lcdcam_apb_rst_en = 0;
|
||||||
|
HP_SYS_CLKRST.lcdcam_ctrl0.reg_lcdcam_rst_en = 1;
|
||||||
|
HP_SYS_CLKRST.lcdcam_ctrl0.reg_lcdcam_rst_en = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||||
|
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
|
||||||
|
#define lcd_ll_reset_register(...) do { \
|
||||||
|
(void)__DECLARE_RCC_RC_ATOMIC_ENV; \
|
||||||
|
_lcd_ll_reset_register(__VA_ARGS__); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enable clock gating
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param en True to enable, False to disable
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_enable_clock(lcd_cam_dev_t *dev, bool en)
|
||||||
|
{
|
||||||
|
(void)dev;
|
||||||
|
HP_SYS_CLKRST.lcdcam_lcdcam_ctrl0.reg_lcdcam_clk_en = en;
|
||||||
|
HP_SYS_CLKRST.lcdcam_lcd_ctrl0.reg_lcd_clk_en = en;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Select clock source for LCD peripheral
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param src Clock source
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_select_clk_src(lcd_cam_dev_t *dev, lcd_clock_source_t src)
|
||||||
|
{
|
||||||
|
(void)dev;
|
||||||
|
switch (src) {
|
||||||
|
case LCD_CLK_SRC_XTAL:
|
||||||
|
HP_SYS_CLKRST.lcdcam_lcd_ctrl0.reg_lcd_clk_src_sel = 0;
|
||||||
|
break;
|
||||||
|
case LCD_CLK_SRC_PLL160M:
|
||||||
|
HP_SYS_CLKRST.lcdcam_lcd_ctrl0.reg_lcd_clk_src_sel = 1;
|
||||||
|
break;
|
||||||
|
case LCD_CLK_SRC_APLL:
|
||||||
|
HP_SYS_CLKRST.lcdcam_lcd_ctrl0.reg_lcd_clk_src_sel = 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// disable the clock
|
||||||
|
HP_SYS_CLKRST.lcdcam_lcd_ctrl0.reg_lcd_clk_src_sel = 3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set clock coefficient of LCD peripheral
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param div_num Integer part of the divider
|
||||||
|
* @param div_a denominator of the divider
|
||||||
|
* @param div_b numerator of the divider
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void lcd_ll_set_group_clock_coeff(lcd_cam_dev_t *dev, int div_num, int div_a, int div_b)
|
||||||
|
{
|
||||||
|
(void)dev;
|
||||||
|
// lcd_clk = module_clock_src / (div_num + div_b / div_a)
|
||||||
|
HAL_ASSERT(div_num > 0 && div_num <= LCD_LL_CLK_FRAC_DIV_N_MAX);
|
||||||
|
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.lcdcam_lcd_ctrl0, reg_lcd_clk_div_num, div_num - 1);
|
||||||
|
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.lcdcam_lcd_ctrl0, reg_lcd_clk_div_denominator, div_a);
|
||||||
|
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.lcdcam_lcd_ctrl0, reg_lcd_clk_div_numerator, div_b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Force power on the LCD memory block, regardless of the outside PMU logic
|
||||||
|
*
|
||||||
|
* @param dev Peripheral instance address
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_mem_force_power_on(lcd_cam_dev_t *dev)
|
||||||
|
{
|
||||||
|
(void)dev;
|
||||||
|
HP_SYSTEM.sys_lcdcam_mem_lp_ctrl.sys_lcdcam_mem_lp_force_ctrl = 1;
|
||||||
|
HP_SYSTEM.sys_lcdcam_mem_lp_ctrl.sys_lcdcam_mem_lp_en = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Force the LCD memory block into low power mode, regardless of the outside PMU logic
|
||||||
|
*
|
||||||
|
* @param dev Peripheral instance address
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_mem_force_low_power(lcd_cam_dev_t *dev)
|
||||||
|
{
|
||||||
|
(void)dev;
|
||||||
|
HP_SYSTEM.sys_lcdcam_mem_lp_ctrl.sys_lcdcam_mem_lp_force_ctrl = 1;
|
||||||
|
HP_SYSTEM.sys_lcdcam_mem_lp_ctrl.sys_lcdcam_mem_lp_en = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Power control the LCD memory block by the outside PMU logic
|
||||||
|
*
|
||||||
|
* @param dev Peripheral instance address
|
||||||
|
* @param mode LCD memory low power mode in low power stage
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_mem_power_by_pmu(lcd_cam_dev_t *dev)
|
||||||
|
{
|
||||||
|
(void)dev;
|
||||||
|
HP_SYSTEM.sys_lcdcam_mem_lp_ctrl.sys_lcdcam_mem_lp_force_ctrl = 0;
|
||||||
|
HP_SYSTEM.sys_lcdcam_mem_lp_ctrl.sys_lcdcam_mem_lp_en = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set low power mode for LCD memory block
|
||||||
|
*
|
||||||
|
* @param dev Peripheral instance address
|
||||||
|
* @param mode LCD memory low power mode in low power stage
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_mem_set_low_power_mode(lcd_cam_dev_t *dev, lcd_ll_mem_lp_mode_t mode)
|
||||||
|
{
|
||||||
|
(void)dev;
|
||||||
|
HP_SYSTEM.sys_lcdcam_mem_lp_ctrl.sys_lcdcam_mem_lp_mode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enable the transfer buffer(memory block) for LCD module
|
||||||
|
*
|
||||||
|
* @note Only for RGB mode
|
||||||
|
* @param dev Peripheral instance address
|
||||||
|
* @param en True to enable, False to disable
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_enable_trans_buffer(lcd_cam_dev_t *dev, bool en)
|
||||||
|
{
|
||||||
|
dev->lcd_trans_buff_cfg.lcd_trans_buffer_ena = en;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the PCLK clock level state when there's no transaction undergoing
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param level 1 is high level, 0 is low level
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void lcd_ll_set_clock_idle_level(lcd_cam_dev_t *dev, bool level)
|
||||||
|
{
|
||||||
|
dev->lcd_clock.lcd_ck_idle_edge = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the PCLK sample edge
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param active_on_neg True: sample on negedge, False: sample on posedge
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void lcd_ll_set_pixel_clock_edge(lcd_cam_dev_t *dev, bool active_on_neg)
|
||||||
|
{
|
||||||
|
dev->lcd_clock.lcd_ck_out_edge = active_on_neg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set PCLK prescale
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param prescale Prescale value, PCLK = LCD_CLK / prescale
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void lcd_ll_set_pixel_clock_prescale(lcd_cam_dev_t *dev, uint32_t prescale)
|
||||||
|
{
|
||||||
|
HAL_ASSERT(prescale > 0 && prescale <= LCD_LL_PCLK_DIV_MAX);
|
||||||
|
// Formula: pixel_clk = lcd_clk / (1 + clkcnt_n)
|
||||||
|
// clkcnt_n can't be zero
|
||||||
|
uint32_t scale = 1;
|
||||||
|
if (prescale == 1) {
|
||||||
|
dev->lcd_clock.lcd_clk_equ_sysclk = 1;
|
||||||
|
} else {
|
||||||
|
dev->lcd_clock.lcd_clk_equ_sysclk = 0;
|
||||||
|
scale = prescale - 1;
|
||||||
|
}
|
||||||
|
dev->lcd_clock.lcd_clkcnt_n = scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enable YUV-RGB converter
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param en True to enable converter, False to disable converter
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_enable_color_convert(lcd_cam_dev_t *dev, bool en)
|
||||||
|
{
|
||||||
|
dev->lcd_rgb_yuv.lcd_conv_enable = en;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set convert data line width
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param width data line width
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_set_convert_data_width(lcd_cam_dev_t *dev, uint32_t width)
|
||||||
|
{
|
||||||
|
HAL_ASSERT(width == 8 || width == 16);
|
||||||
|
dev->lcd_rgb_yuv.lcd_conv_mode_8bits_on = (width == 8) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the color range of input data
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param range Color range
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_set_input_color_range(lcd_cam_dev_t *dev, lcd_color_range_t range)
|
||||||
|
{
|
||||||
|
if (range == LCD_COLOR_RANGE_LIMIT) {
|
||||||
|
dev->lcd_rgb_yuv.lcd_conv_data_in_mode = 0;
|
||||||
|
} else if (range == LCD_COLOR_RANGE_FULL) {
|
||||||
|
dev->lcd_rgb_yuv.lcd_conv_data_in_mode = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the color range of output data
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param range Color range
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_set_output_color_range(lcd_cam_dev_t *dev, lcd_color_range_t range)
|
||||||
|
{
|
||||||
|
if (range == LCD_COLOR_RANGE_LIMIT) {
|
||||||
|
dev->lcd_rgb_yuv.lcd_conv_data_out_mode = 0;
|
||||||
|
} else if (range == LCD_COLOR_RANGE_FULL) {
|
||||||
|
dev->lcd_rgb_yuv.lcd_conv_data_out_mode = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set YUV conversion standard
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param std YUV conversion standard
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_set_yuv_convert_std(lcd_cam_dev_t *dev, lcd_yuv_conv_std_t std)
|
||||||
|
{
|
||||||
|
if (std == LCD_YUV_CONV_STD_BT601) {
|
||||||
|
dev->lcd_rgb_yuv.lcd_conv_protocol_mode = 0;
|
||||||
|
} else if (std == LCD_YUV_CONV_STD_BT709) {
|
||||||
|
dev->lcd_rgb_yuv.lcd_conv_protocol_mode = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the converter mode: RGB to YUV
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param in_color_format Input color format
|
||||||
|
* @param out_color_format Output color format
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_set_rgb2yuv_convert_mode(lcd_cam_dev_t *dev, lcd_color_format_t in_color_format, lcd_color_format_t out_color_format)
|
||||||
|
{
|
||||||
|
(void)in_color_format;
|
||||||
|
dev->lcd_rgb_yuv.lcd_conv_trans_mode = 1;
|
||||||
|
dev->lcd_rgb_yuv.lcd_conv_yuv2yuv_mode = 3;
|
||||||
|
switch (out_color_format) {
|
||||||
|
case LCD_COLOR_FMT_YUV422_UYVY:
|
||||||
|
dev->lcd_rgb_yuv.lcd_conv_yuv_mode = 0;
|
||||||
|
break;
|
||||||
|
case LCD_COLOR_FMT_YUV420_OUYY_EVYY:
|
||||||
|
dev->lcd_rgb_yuv.lcd_conv_yuv_mode = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the converter mode: YUV to RGB
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param in_color_format Input color format
|
||||||
|
* @param out_color_format Output color format
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_set_yuv2rgb_convert_mode(lcd_cam_dev_t *dev, lcd_color_format_t in_color_format, lcd_color_format_t out_color_format)
|
||||||
|
{
|
||||||
|
(void)out_color_format;
|
||||||
|
dev->lcd_rgb_yuv.lcd_conv_trans_mode = 0;
|
||||||
|
dev->lcd_rgb_yuv.lcd_conv_yuv2yuv_mode = 3;
|
||||||
|
switch (in_color_format) {
|
||||||
|
case LCD_COLOR_FMT_YUV422_UYVY:
|
||||||
|
dev->lcd_rgb_yuv.lcd_conv_yuv_mode = 0;
|
||||||
|
break;
|
||||||
|
case LCD_COLOR_FMT_YUV420_OUYY_EVYY:
|
||||||
|
dev->lcd_rgb_yuv.lcd_conv_yuv_mode = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the converter mode: YUV to YUV
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param in_color_format Input color format
|
||||||
|
* @param out_color_format Output color format
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_set_yuv2yuv_convert_mode(lcd_cam_dev_t *dev, lcd_color_format_t in_color_format, lcd_color_format_t out_color_format)
|
||||||
|
{
|
||||||
|
dev->lcd_rgb_yuv.lcd_conv_trans_mode = 1;
|
||||||
|
switch (in_color_format) {
|
||||||
|
case LCD_COLOR_FMT_YUV422_UYVY:
|
||||||
|
dev->lcd_rgb_yuv.lcd_conv_yuv_mode = 0;
|
||||||
|
break;
|
||||||
|
case LCD_COLOR_FMT_YUV420_OUYY_EVYY:
|
||||||
|
dev->lcd_rgb_yuv.lcd_conv_yuv_mode = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
switch (out_color_format) {
|
||||||
|
case LCD_COLOR_FMT_YUV422_UYVY:
|
||||||
|
dev->lcd_rgb_yuv.lcd_conv_yuv2yuv_mode = 0;
|
||||||
|
break;
|
||||||
|
case LCD_COLOR_FMT_YUV420_OUYY_EVYY:
|
||||||
|
dev->lcd_rgb_yuv.lcd_conv_yuv2yuv_mode = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set clock cycles of each transaction phases
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param cmd_cycles Clock cycles of CMD phase
|
||||||
|
* @param dummy_cycles Clock cycles of DUMMY phase
|
||||||
|
* @param data_cycles Clock cycles of DATA phase
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void lcd_ll_set_phase_cycles(lcd_cam_dev_t *dev, uint32_t cmd_cycles, uint32_t dummy_cycles, uint32_t data_cycles)
|
||||||
|
{
|
||||||
|
HAL_ASSERT(cmd_cycles <= 2);
|
||||||
|
dev->lcd_user.lcd_cmd = (cmd_cycles > 0);
|
||||||
|
dev->lcd_user.lcd_dummy = (dummy_cycles > 0);
|
||||||
|
dev->lcd_user.lcd_dout = (data_cycles > 0);
|
||||||
|
dev->lcd_user.lcd_cmd_2_cycle_en = cmd_cycles > 1;
|
||||||
|
if (dummy_cycles > 0) {
|
||||||
|
dev->lcd_user.lcd_dummy_cyclelen = dummy_cycles - 1;
|
||||||
|
}
|
||||||
|
if (data_cycles > 0) {
|
||||||
|
dev->lcd_user.lcd_dout_cyclelen = data_cycles - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set clock cycles of blank phases
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param fk_cycles Clock cycles of front blank
|
||||||
|
* @param bk_cycles Clock cycles of back blank
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_set_blank_cycles(lcd_cam_dev_t *dev, uint32_t fk_cycles, uint32_t bk_cycles)
|
||||||
|
{
|
||||||
|
dev->lcd_misc.lcd_bk_en = (fk_cycles || bk_cycles);
|
||||||
|
if (fk_cycles > 0) {
|
||||||
|
dev->lcd_misc.lcd_vfk_cyclelen = fk_cycles - 1;
|
||||||
|
}
|
||||||
|
if (bk_cycles > 0) {
|
||||||
|
dev->lcd_misc.lcd_vbk_cyclelen = bk_cycles - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set data read stride, i.e., number of bytes the LCD reads from the DMA in each step
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param stride data stride size, in bits
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_set_dma_read_stride(lcd_cam_dev_t *dev, uint32_t stride)
|
||||||
|
{
|
||||||
|
switch (stride) {
|
||||||
|
case 8:
|
||||||
|
dev->lcd_user.lcd_byte_mode = 0;
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
dev->lcd_user.lcd_byte_mode = 1;
|
||||||
|
break;
|
||||||
|
case 24:
|
||||||
|
dev->lcd_user.lcd_byte_mode = 2;
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
dev->lcd_user.lcd_byte_mode = 3;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the wire width of LCD output
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param width LCD output wire width
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_set_data_wire_width(lcd_cam_dev_t *dev, uint32_t width)
|
||||||
|
{
|
||||||
|
switch (width) {
|
||||||
|
case 8:
|
||||||
|
dev->lcd_misc.lcd_wire_mode = 0;
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
dev->lcd_misc.lcd_wire_mode = 1;
|
||||||
|
break;
|
||||||
|
case 24:
|
||||||
|
dev->lcd_misc.lcd_wire_mode = 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Whether to continue the data phase when the DMA has content to send
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param en True: The number of data cycles will be controller by DMA buffer size, instead of lcd_dout_cyclelen
|
||||||
|
* False: The number of data cycles will be controlled by lcd_dout_cyclelen
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_enable_output_always_on(lcd_cam_dev_t *dev, bool en)
|
||||||
|
{
|
||||||
|
dev->lcd_user.lcd_always_out_en = en;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Start the LCD transaction
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void lcd_ll_start(lcd_cam_dev_t *dev)
|
||||||
|
{
|
||||||
|
dev->lcd_user.lcd_update_reg = 1; // update parameters before start transaction
|
||||||
|
dev->lcd_user.lcd_start = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Stop the LCD transaction
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void lcd_ll_stop(lcd_cam_dev_t *dev)
|
||||||
|
{
|
||||||
|
dev->lcd_user.lcd_start = 0;
|
||||||
|
dev->lcd_user.lcd_update_reg = 1; // self clear
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reset LCD TX controller and RGB/YUV converter
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_reset(lcd_cam_dev_t *dev)
|
||||||
|
{
|
||||||
|
dev->lcd_user.lcd_reset = 1; // self clear
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Whether to reverse the data bit order
|
||||||
|
*
|
||||||
|
* @note It acts before the YUV-RGB converter
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param en True to reverse, False to not reverse
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void lcd_ll_reverse_dma_data_bit_order(lcd_cam_dev_t *dev, bool en)
|
||||||
|
{
|
||||||
|
dev->lcd_user.lcd_bit_order = en;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Whether to reverse the output data bit order
|
||||||
|
*
|
||||||
|
* @note It acts after the YUV-RGB converter
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param en True to reverse, False to not reverse
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_reverse_wire_bit_order(lcd_cam_dev_t *dev, bool en)
|
||||||
|
{
|
||||||
|
dev->lcd_user.lcd_dout_bit_order = en;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Whether to swap adjacent two bytes
|
||||||
|
*
|
||||||
|
* @note This acts before the YUV-RGB converter, mainly to change the data endian.
|
||||||
|
* e.g. {B1,B0},{B3,B2} => {B0,B1}{B2,B3}.
|
||||||
|
* Only valid when `lcd_ll_set_dma_read_stride` set the DMA read stride >= 16 bits
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param en True to swap the byte order, False to not swap
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void lcd_ll_swap_dma_data_byte_order(lcd_cam_dev_t *dev, bool en)
|
||||||
|
{
|
||||||
|
dev->lcd_user.lcd_byte_order = en;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enable the byte swizzle
|
||||||
|
*
|
||||||
|
* @note The swizzle module acts after the YUV-RGB converter, used to reorder the data bytes before the data output line
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param en True to enable, False to disable
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void lcd_ll_enable_swizzle(lcd_cam_dev_t *dev, bool en)
|
||||||
|
{
|
||||||
|
dev->lcd_user.lcd_dout_byte_swizzle_enable = en;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set data byte swizzle mode
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param mode Swizzle mode
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_set_swizzle_mode(lcd_cam_dev_t *dev, lcd_ll_swizzle_mode_t mode)
|
||||||
|
{
|
||||||
|
dev->lcd_user.lcd_dout_byte_swizzle_mode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reset Async TX FIFO
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void lcd_ll_fifo_reset(lcd_cam_dev_t *dev)
|
||||||
|
{
|
||||||
|
dev->lcd_misc.lcd_afifo_reset = 1; // self clear
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the level state of DC line, on different transaction phases
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param idle_phase Level state of DC line on IDLE phase
|
||||||
|
* @param cmd_phase Level state of DC line on CMD phase
|
||||||
|
* @param dummy_phase Level state of DC line on DUMMY phase
|
||||||
|
* @param data_phase Level state of DC line on DATA phase
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void lcd_ll_set_dc_level(lcd_cam_dev_t *dev, bool idle_phase, bool cmd_phase, bool dummy_phase, bool data_phase)
|
||||||
|
{
|
||||||
|
dev->lcd_misc.lcd_cd_idle_edge = idle_phase;
|
||||||
|
dev->lcd_misc.lcd_cd_cmd_set = (cmd_phase != idle_phase);
|
||||||
|
dev->lcd_misc.lcd_cd_dummy_set = (dummy_phase != idle_phase);
|
||||||
|
dev->lcd_misc.lcd_cd_data_set = (data_phase != idle_phase);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set cycle of delay for DC line
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param delay Ticks of delay
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_set_dc_delay_ticks(lcd_cam_dev_t *dev, uint32_t delay)
|
||||||
|
{
|
||||||
|
dev->lcd_dly_mode_cfg1.lcd_cd_mode = delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the LCD command (the data at CMD phase)
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param data_width Data line width
|
||||||
|
* @param command command value
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void lcd_ll_set_command(lcd_cam_dev_t *dev, uint32_t data_width, uint32_t command)
|
||||||
|
{
|
||||||
|
// i80 interface only supports 8-bit or 16-bit data width
|
||||||
|
HAL_ASSERT(data_width == 8 || data_width == 16);
|
||||||
|
// if command phase has two cycles, in the first cycle we use lcd_first_cmd_val
|
||||||
|
// in the second cycle, we use lcd_latter_cmd_val
|
||||||
|
if (data_width == 8) {
|
||||||
|
dev->lcd_first_cmd_val.val = command & 0xFF;
|
||||||
|
dev->lcd_latter_cmd_val.val = (command >> 8) & 0xFF;
|
||||||
|
} else if (data_width == 16) {
|
||||||
|
dev->lcd_first_cmd_val.val = command;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Whether to enable RGB interface
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param en True to enable RGB interface, False to disable RGB interface
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_enable_rgb_mode(lcd_cam_dev_t *dev, bool en)
|
||||||
|
{
|
||||||
|
dev->lcd_misc.lcd_rgb_mode_en = en;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Whether to send the next frame automatically
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param en True to enable, False to disable
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_enable_auto_next_frame(lcd_cam_dev_t *dev, bool en)
|
||||||
|
{
|
||||||
|
// in RGB mode, enabling "next frame" means LCD controller keeps sending frame data
|
||||||
|
dev->lcd_misc.lcd_next_frame_en = en;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Whether to output HSYNC signal in porch resion
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param en True to enable, False to disable
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_enable_output_hsync_in_porch_region(lcd_cam_dev_t *dev, bool en)
|
||||||
|
{
|
||||||
|
dev->lcd_rgb_ctrl.lcd_hs_blank_en = en;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set HSYNC signal offset in the line
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param offset_in_line Offset value
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_set_hsync_position(lcd_cam_dev_t *dev, uint32_t offset_in_line)
|
||||||
|
{
|
||||||
|
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->lcd_rgb_ctrl, lcd_hsync_position, offset_in_line);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set RGB LCD horizontal timing
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param hsw Horizontal sync width
|
||||||
|
* @param hbp Horizontal back porch
|
||||||
|
* @param active_width Horizontal active width
|
||||||
|
* @param hfp Horizontal front porch
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_set_horizontal_timing(lcd_cam_dev_t *dev, uint32_t hsw, uint32_t hbp, uint32_t active_width, uint32_t hfp)
|
||||||
|
{
|
||||||
|
dev->lcd_rgb_ctrl.lcd_hsync_width = hsw - 1;
|
||||||
|
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->lcd_rgb_blank, lcd_hb_front, hbp + hsw - 1);
|
||||||
|
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->lcd_rgb_horizontal, lcd_ha_width, active_width - 1);
|
||||||
|
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->lcd_rgb_horizontal, lcd_ht_width, hsw + hbp + active_width + hfp - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set RGB vertical timing
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param vsw Vertical sync width
|
||||||
|
* @param vbp Vertical back porch
|
||||||
|
* @param active_height Vertical active height
|
||||||
|
* @param vfp Vertical front porch
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_set_vertical_timing(lcd_cam_dev_t *dev, uint32_t vsw, uint32_t vbp, uint32_t active_height, uint32_t vfp)
|
||||||
|
{
|
||||||
|
dev->lcd_rgb_ctrl.lcd_vsync_width = vsw - 1;
|
||||||
|
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->lcd_rgb_blank, lcd_vb_front, vbp + vsw - 1);
|
||||||
|
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->lcd_rgb_vertical, lcd_va_height, active_height - 1);
|
||||||
|
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->lcd_rgb_vertical, lcd_vt_height, vsw + vbp + active_height + vfp - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set level state for hsync, vsync, de at IDLE phase
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param hsync_idle_level HSYNC level on IDLE phase
|
||||||
|
* @param vsync_idle_level VSYNC level on IDLE phase
|
||||||
|
* @param de_idle_level DE level on IDLE phase
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_set_idle_level(lcd_cam_dev_t *dev, bool hsync_idle_level, bool vsync_idle_level, bool de_idle_level)
|
||||||
|
{
|
||||||
|
dev->lcd_rgb_ctrl.lcd_hsync_idle_pol = hsync_idle_level;
|
||||||
|
dev->lcd_rgb_ctrl.lcd_vsync_idle_pol = vsync_idle_level;
|
||||||
|
dev->lcd_rgb_ctrl.lcd_de_idle_pol = de_idle_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set extra delay for HSYNC, VSYNC, and DE signals
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param hsync_delay HSYNC delay
|
||||||
|
* @param vsync_delay VSYNC delay
|
||||||
|
* @param de_delay DE delay
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_set_delay_ticks(lcd_cam_dev_t *dev, uint32_t hsync_delay, uint32_t vsync_delay, uint32_t de_delay)
|
||||||
|
{
|
||||||
|
dev->lcd_dly_mode_cfg1.lcd_hsync_mode = hsync_delay;
|
||||||
|
dev->lcd_dly_mode_cfg1.lcd_vsync_mode = vsync_delay;
|
||||||
|
dev->lcd_dly_mode_cfg1.lcd_de_mode = de_delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enable/disable interrupt by mask
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param mask Interrupt mask
|
||||||
|
* @param en True to enable interrupt, False to disable interrupt
|
||||||
|
*/
|
||||||
|
static inline void lcd_ll_enable_interrupt(lcd_cam_dev_t *dev, uint32_t mask, bool en)
|
||||||
|
{
|
||||||
|
if (en) {
|
||||||
|
dev->lc_dma_int_ena.val |= mask & 0x13;
|
||||||
|
} else {
|
||||||
|
dev->lc_dma_int_ena.val &= ~(mask & 0x13);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||||
|
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
|
||||||
|
#define lcd_ll_enable_interrupt(...) do { \
|
||||||
|
(void)__DECLARE_RCC_ATOMIC_ENV; \
|
||||||
|
lcd_ll_enable_interrupt(__VA_ARGS__); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get interrupt status value
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @return Interrupt status value
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline uint32_t lcd_ll_get_interrupt_status(lcd_cam_dev_t *dev)
|
||||||
|
{
|
||||||
|
return dev->lc_dma_int_st.val & 0x13;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clear interrupt status by mask
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @param mask Interrupt status mask
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void lcd_ll_clear_interrupt_status(lcd_cam_dev_t *dev, uint32_t mask)
|
||||||
|
{
|
||||||
|
dev->lc_dma_int_clr.val = mask & 0x13;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get address of interrupt status register address
|
||||||
|
*
|
||||||
|
* @param dev LCD register base address
|
||||||
|
* @return Interrupt status register address
|
||||||
|
*/
|
||||||
|
static inline volatile void *lcd_ll_get_interrupt_status_reg(lcd_cam_dev_t *dev)
|
||||||
|
{
|
||||||
|
return &dev->lc_dma_int_st;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,153 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "hal/lcd_periph.h"
|
||||||
|
#include "soc/gpio_sig_map.h"
|
||||||
|
#include "soc/io_mux_reg.h"
|
||||||
|
#include "soc/gpio_num.h"
|
||||||
|
|
||||||
|
const soc_lcd_i80_signal_desc_t soc_lcd_i80_signals[1] = {
|
||||||
|
[0] = {
|
||||||
|
.module = PERIPH_LCD_CAM_MODULE,
|
||||||
|
.irq_id = ETS_LCD_CAM_INTR_SOURCE,
|
||||||
|
.data_sigs = {
|
||||||
|
LCD_DATA_OUT_PAD_OUT0_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT1_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT2_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT3_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT4_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT5_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT6_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT7_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT8_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT9_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT10_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT11_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT12_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT13_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT14_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT15_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT16_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT17_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT18_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT19_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT20_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT21_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT22_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT23_IDX,
|
||||||
|
},
|
||||||
|
.cs_sig = LCD_CS_PAD_OUT_IDX,
|
||||||
|
.dc_sig = LCD_DC_PAD_OUT_IDX,
|
||||||
|
.wr_sig = LCD_PCLK_PAD_OUT_IDX,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const soc_lcd_rgb_signal_desc_t soc_lcd_rgb_signals[1] = {
|
||||||
|
[0] = {
|
||||||
|
.module = PERIPH_LCD_CAM_MODULE,
|
||||||
|
.irq_id = ETS_LCD_CAM_INTR_SOURCE,
|
||||||
|
.data_sigs = {
|
||||||
|
LCD_DATA_OUT_PAD_OUT0_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT1_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT2_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT3_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT4_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT5_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT6_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT7_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT8_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT9_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT10_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT11_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT12_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT13_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT14_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT15_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT16_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT17_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT18_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT19_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT20_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT21_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT22_IDX,
|
||||||
|
LCD_DATA_OUT_PAD_OUT23_IDX,
|
||||||
|
},
|
||||||
|
.hsync_sig = LCD_H_SYNC_PAD_OUT_IDX,
|
||||||
|
.vsync_sig = LCD_V_SYNC_PAD_OUT_IDX,
|
||||||
|
.pclk_sig = LCD_PCLK_PAD_OUT_IDX,
|
||||||
|
.de_sig = LCD_H_ENABLE_PAD_OUT_IDX,
|
||||||
|
.disp_sig = SIG_GPIO_OUT_IDX,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const soc_lcd_rgb_iomux_desc_t soc_lcd_rgb_iomux_descs[1] = {
|
||||||
|
[0] = {
|
||||||
|
.data_pins = {
|
||||||
|
{ .gpio_num = GPIO_NUM_8, .func = FUNC_GPIO8_LCD_DATA0_OUT_PAD },
|
||||||
|
{ .gpio_num = GPIO_NUM_9, .func = FUNC_GPIO9_LCD_DATA1_OUT_PAD },
|
||||||
|
{ .gpio_num = GPIO_NUM_10, .func = FUNC_GPIO10_LCD_DATA2_OUT_PAD },
|
||||||
|
{ .gpio_num = GPIO_NUM_11, .func = FUNC_GPIO11_LCD_DATA3_OUT_PAD },
|
||||||
|
{ .gpio_num = GPIO_NUM_12, .func = FUNC_GPIO12_LCD_DATA4_OUT_PAD },
|
||||||
|
{ .gpio_num = GPIO_NUM_13, .func = FUNC_GPIO13_LCD_DATA5_OUT_PAD },
|
||||||
|
{ .gpio_num = GPIO_NUM_14, .func = FUNC_GPIO14_LCD_DATA6_OUT_PAD },
|
||||||
|
{ .gpio_num = GPIO_NUM_15, .func = FUNC_GPIO15_LCD_DATA7_OUT_PAD },
|
||||||
|
{ .gpio_num = GPIO_NUM_16, .func = FUNC_GPIO16_LCD_DATA8_OUT_PAD },
|
||||||
|
{ .gpio_num = GPIO_NUM_17, .func = FUNC_GPIO17_LCD_DATA9_OUT_PAD },
|
||||||
|
{ .gpio_num = GPIO_NUM_18, .func = FUNC_GPIO18_LCD_DATA10_OUT_PAD },
|
||||||
|
{ .gpio_num = GPIO_NUM_19, .func = FUNC_GPIO19_LCD_DATA11_OUT_PAD },
|
||||||
|
{ .gpio_num = GPIO_NUM_33, .func = FUNC_GPIO33_LCD_DATA12_OUT_PAD },
|
||||||
|
{ .gpio_num = GPIO_NUM_34, .func = FUNC_GPIO34_LCD_DATA13_OUT_PAD },
|
||||||
|
{ .gpio_num = GPIO_NUM_35, .func = FUNC_GPIO35_LCD_DATA14_OUT_PAD },
|
||||||
|
{ .gpio_num = GPIO_NUM_36, .func = FUNC_GPIO36_LCD_DATA15_OUT_PAD },
|
||||||
|
{ .gpio_num = GPIO_NUM_37, .func = FUNC_GPIO37_LCD_DATA16_OUT_PAD },
|
||||||
|
{ .gpio_num = GPIO_NUM_38, .func = FUNC_GPIO38_LCD_DATA17_OUT_PAD },
|
||||||
|
{ .gpio_num = GPIO_NUM_39, .func = FUNC_GPIO39_LCD_DATA18_OUT_PAD },
|
||||||
|
{ .gpio_num = GPIO_NUM_2, .func = FUNC_GPIO2_LCD_DATA19_OUT_PAD },
|
||||||
|
{ .gpio_num = GPIO_NUM_3, .func = FUNC_GPIO3_LCD_DATA20_OUT_PAD },
|
||||||
|
{ .gpio_num = GPIO_NUM_4, .func = FUNC_GPIO4_LCD_DATA21_OUT_PAD },
|
||||||
|
{ .gpio_num = GPIO_NUM_5, .func = FUNC_GPIO5_LCD_DATA22_OUT_PAD },
|
||||||
|
{ .gpio_num = GPIO_NUM_7, .func = FUNC_GPIO7_LCD_DATA23_OUT_PAD },
|
||||||
|
},
|
||||||
|
.hsync_pin = { .gpio_num = GPIO_NUM_44, .func = FUNC_GPIO44_LCD_H_SYNC_PAD },
|
||||||
|
.vsync_pin = { .gpio_num = GPIO_NUM_45, .func = FUNC_GPIO45_LCD_V_SYNC_PAD },
|
||||||
|
.pclk_pin = { .gpio_num = GPIO_NUM_40, .func = FUNC_GPIO40_LCD_PCLK_PAD },
|
||||||
|
.de_pin = { .gpio_num = GPIO_NUM_43, .func = FUNC_GPIO43_LCD_H_ENABLE_PAD },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LCD_CAM Registers to be saved during sleep retention
|
||||||
|
* - LCD Clock Configuration registers: LCDCAM_LCD_CLOCK_REG (0x0)
|
||||||
|
* - LCD User Configuration registers: LCDCAM_LCD_USER_REG (0x14), LCDCAM_LCD_MISC_REG (0x18)
|
||||||
|
* - LCD Delay Mode Configuration registers: LCDCAM_LCD_DLY_MODE_CFG1_REG (0x34), LCDCAM_LCD_DLY_MODE_CFG2_REG (0x38)
|
||||||
|
* - LCD Transfer Buffer Configuration registers: LCDCAM_LCD_TRANS_BUFF_CFG_REG(0x3C)
|
||||||
|
* - LCD DMA Interrupt Enable register: LCDCAM_LC_DMA_INT_ENA_REG (0x64)
|
||||||
|
*
|
||||||
|
* NOTE: Only I80 LCD supports sleep retention, not RGB LCD.
|
||||||
|
*/
|
||||||
|
#define LCD_RETENTION_REGS_CNT 7
|
||||||
|
#define LCD_RETENTION_REGS_BASE (DR_REG_LCDCAM_BASE + 0x0)
|
||||||
|
static const uint32_t lcd_cam_regs_map[4] = {0x200e061, 0x0, 0x0, 0x0};
|
||||||
|
static const regdma_entries_config_t lcd_regs_retention[] = {
|
||||||
|
// backup stage: save configuration registers
|
||||||
|
// restore stage: restore the configuration registers
|
||||||
|
[0] = {
|
||||||
|
.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_LCDCAM_LINK(0x00),
|
||||||
|
LCD_RETENTION_REGS_BASE, LCD_RETENTION_REGS_BASE,
|
||||||
|
LCD_RETENTION_REGS_CNT, 0, 0,
|
||||||
|
lcd_cam_regs_map[0], lcd_cam_regs_map[1],
|
||||||
|
lcd_cam_regs_map[2], lcd_cam_regs_map[3]),
|
||||||
|
.owner = ENTRY(0) | ENTRY(2),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const soc_i80_lcd_retention_info_t soc_i80_lcd_retention_info[1] = {
|
||||||
|
[0] = {
|
||||||
|
.regdma_entry_array = lcd_regs_retention,
|
||||||
|
.array_size = ARRAY_SIZE(lcd_regs_retention),
|
||||||
|
.retention_module = SLEEP_RETENTION_MODULE_LCDCAM
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
#include "soc/soc_caps.h"
|
#include "soc/soc_caps.h"
|
||||||
#include "soc/periph_defs.h"
|
#include "soc/periph_defs.h"
|
||||||
#include "soc/regdma.h"
|
#include "soc/regdma.h"
|
||||||
@@ -36,6 +37,24 @@ typedef struct {
|
|||||||
} soc_lcd_rgb_signal_desc_t;
|
} soc_lcd_rgb_signal_desc_t;
|
||||||
|
|
||||||
extern const soc_lcd_rgb_signal_desc_t soc_lcd_rgb_signals[LCD_LL_GET(RGB_PANEL_NUM)];
|
extern const soc_lcd_rgb_signal_desc_t soc_lcd_rgb_signals[LCD_LL_GET(RGB_PANEL_NUM)];
|
||||||
|
|
||||||
|
#if LCD_LL_SUPPORT(IOMUX)
|
||||||
|
typedef struct {
|
||||||
|
const int gpio_num;
|
||||||
|
const int func;
|
||||||
|
} soc_lcd_iomux_pin_desc_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const soc_lcd_iomux_pin_desc_t data_pins[LCD_LL_GET(RGB_BUS_WIDTH)];
|
||||||
|
const soc_lcd_iomux_pin_desc_t hsync_pin;
|
||||||
|
const soc_lcd_iomux_pin_desc_t vsync_pin;
|
||||||
|
const soc_lcd_iomux_pin_desc_t pclk_pin;
|
||||||
|
const soc_lcd_iomux_pin_desc_t de_pin;
|
||||||
|
} soc_lcd_rgb_iomux_desc_t;
|
||||||
|
|
||||||
|
extern const soc_lcd_rgb_iomux_desc_t soc_lcd_rgb_iomux_descs[LCD_LL_GET(RGB_PANEL_NUM)];
|
||||||
|
#endif // LCD_LL_SUPPORT(IOMUX)
|
||||||
|
|
||||||
#endif // SOC_HAS(LCDCAM_RGB_LCD)
|
#endif // SOC_HAS(LCDCAM_RGB_LCD)
|
||||||
|
|
||||||
#if SOC_HAS(LCDCAM_I80_LCD)
|
#if SOC_HAS(LCDCAM_I80_LCD)
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ static inline void spimem_flash_ll_reset(spi_mem_dev_t *dev)
|
|||||||
*
|
*
|
||||||
* @return true if last command is done, otherwise false.
|
* @return true if last command is done, otherwise false.
|
||||||
*/
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
static inline bool spimem_flash_ll_cmd_is_done(const spi_mem_dev_t *dev)
|
static inline bool spimem_flash_ll_cmd_is_done(const spi_mem_dev_t *dev)
|
||||||
{
|
{
|
||||||
return (dev->cmd.val == 0);
|
return (dev->cmd.val == 0);
|
||||||
@@ -421,6 +422,7 @@ static inline void spimem_flash_ll_program_page(spi_mem_dev_t *dev, const void *
|
|||||||
* @param dev Beginning address of the peripheral registers.
|
* @param dev Beginning address of the peripheral registers.
|
||||||
* @param pe_ops Is page program/erase operation or not.
|
* @param pe_ops Is page program/erase operation or not.
|
||||||
*/
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
static inline void spimem_flash_ll_user_start(spi_mem_dev_t *dev, bool pe_ops)
|
static inline void spimem_flash_ll_user_start(spi_mem_dev_t *dev, bool pe_ops)
|
||||||
{
|
{
|
||||||
uint32_t usr_pe = (pe_ops ? 0x60000 : 0x40000);
|
uint32_t usr_pe = (pe_ops ? 0x60000 : 0x40000);
|
||||||
@@ -434,6 +436,7 @@ static inline void spimem_flash_ll_user_start(spi_mem_dev_t *dev, bool pe_ops)
|
|||||||
*
|
*
|
||||||
* @return true if the host is idle, otherwise false
|
* @return true if the host is idle, otherwise false
|
||||||
*/
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
static inline bool spimem_flash_ll_host_idle(const spi_mem_dev_t *dev)
|
static inline bool spimem_flash_ll_host_idle(const spi_mem_dev_t *dev)
|
||||||
{
|
{
|
||||||
return dev->cmd.mst_st == 0;
|
return dev->cmd.mst_st == 0;
|
||||||
@@ -522,6 +525,7 @@ static inline void spimem_flash_ll_set_clock(spi_mem_dev_t *dev, spimem_flash_ll
|
|||||||
* @param dev Beginning address of the peripheral registers.
|
* @param dev Beginning address of the peripheral registers.
|
||||||
* @param bitlen Length of input, in bits.
|
* @param bitlen Length of input, in bits.
|
||||||
*/
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
static inline void spimem_flash_ll_set_miso_bitlen(spi_mem_dev_t *dev, uint32_t bitlen)
|
static inline void spimem_flash_ll_set_miso_bitlen(spi_mem_dev_t *dev, uint32_t bitlen)
|
||||||
{
|
{
|
||||||
dev->user.usr_miso = bitlen > 0;
|
dev->user.usr_miso = bitlen > 0;
|
||||||
@@ -549,6 +553,7 @@ static inline void spimem_flash_ll_set_mosi_bitlen(spi_mem_dev_t *dev, uint32_t
|
|||||||
* @param command Command to send
|
* @param command Command to send
|
||||||
* @param bitlen Length of the command
|
* @param bitlen Length of the command
|
||||||
*/
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
static inline void spimem_flash_ll_set_command(spi_mem_dev_t *dev, uint32_t command, uint32_t bitlen)
|
static inline void spimem_flash_ll_set_command(spi_mem_dev_t *dev, uint32_t command, uint32_t bitlen)
|
||||||
{
|
{
|
||||||
dev->user.usr_command = 1;
|
dev->user.usr_command = 1;
|
||||||
@@ -602,6 +607,7 @@ static inline void spimem_flash_ll_set_extra_address(spi_mem_dev_t *dev, uint32_
|
|||||||
* @param dev Beginning address of the peripheral registers.
|
* @param dev Beginning address of the peripheral registers.
|
||||||
* @param addr Address to send
|
* @param addr Address to send
|
||||||
*/
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
static inline void spimem_flash_ll_set_address(spi_mem_dev_t *dev, uint32_t addr)
|
static inline void spimem_flash_ll_set_address(spi_mem_dev_t *dev, uint32_t addr)
|
||||||
{
|
{
|
||||||
dev->addr = addr;
|
dev->addr = addr;
|
||||||
@@ -626,6 +632,7 @@ static inline void spimem_flash_ll_set_usr_address(spi_mem_dev_t *dev, uint32_t
|
|||||||
* @param dev Beginning address of the peripheral registers.
|
* @param dev Beginning address of the peripheral registers.
|
||||||
* @param dummy_n Cycles of dummy phases
|
* @param dummy_n Cycles of dummy phases
|
||||||
*/
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
static inline void spimem_flash_ll_set_dummy(spi_mem_dev_t *dev, uint32_t dummy_n)
|
static inline void spimem_flash_ll_set_dummy(spi_mem_dev_t *dev, uint32_t dummy_n)
|
||||||
{
|
{
|
||||||
dev->user.usr_dummy = dummy_n ? 1 : 0;
|
dev->user.usr_dummy = dummy_n ? 1 : 0;
|
||||||
@@ -720,6 +727,7 @@ static inline uint32_t spimem_flash_ll_calculate_clock_reg(uint8_t clkdiv)
|
|||||||
|
|
||||||
* @param level 1: 1: output high, 0: output low
|
* @param level 1: 1: output high, 0: output low
|
||||||
*/
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
static inline void spimem_flash_ll_set_wp_level(spi_mem_dev_t *dev, bool level)
|
static inline void spimem_flash_ll_set_wp_level(spi_mem_dev_t *dev, bool level)
|
||||||
{
|
{
|
||||||
dev->ctrl.wp_reg = level;
|
dev->ctrl.wp_reg = level;
|
||||||
@@ -767,6 +775,7 @@ static inline void spimem_ctrlr_ll_unset_clock(uint8_t mspi_id)
|
|||||||
/**
|
/**
|
||||||
* @brief Reset whole memory spi
|
* @brief Reset whole memory spi
|
||||||
*/
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
static inline void spimem_flash_ll_sync_reset(void)
|
static inline void spimem_flash_ll_sync_reset(void)
|
||||||
{
|
{
|
||||||
SPIMEM1.ctrl2.sync_reset = 0;
|
SPIMEM1.ctrl2.sync_reset = 0;
|
||||||
@@ -785,6 +794,7 @@ static inline void spimem_flash_ll_sync_reset(void)
|
|||||||
* @param user1_reg user1_reg
|
* @param user1_reg user1_reg
|
||||||
* @param user2_reg user2_reg
|
* @param user2_reg user2_reg
|
||||||
*/
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
static inline void spimem_flash_ll_get_common_command_register_info(spi_mem_dev_t *dev, uint32_t *ctrl_reg, uint32_t *user_reg, uint32_t *user1_reg, uint32_t *user2_reg)
|
static inline void spimem_flash_ll_get_common_command_register_info(spi_mem_dev_t *dev, uint32_t *ctrl_reg, uint32_t *user_reg, uint32_t *user1_reg, uint32_t *user2_reg)
|
||||||
{
|
{
|
||||||
*ctrl_reg = dev->ctrl.val;
|
*ctrl_reg = dev->ctrl.val;
|
||||||
@@ -801,6 +811,7 @@ static inline void spimem_flash_ll_get_common_command_register_info(spi_mem_dev_
|
|||||||
* @param user1_reg user1_reg
|
* @param user1_reg user1_reg
|
||||||
* @param user2_reg user2_reg
|
* @param user2_reg user2_reg
|
||||||
*/
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
static inline void spimem_flash_ll_set_common_command_register_info(spi_mem_dev_t *dev, uint32_t ctrl_reg, uint32_t user_reg, uint32_t user1_reg, uint32_t user2_reg)
|
static inline void spimem_flash_ll_set_common_command_register_info(spi_mem_dev_t *dev, uint32_t ctrl_reg, uint32_t user_reg, uint32_t user1_reg, uint32_t user2_reg)
|
||||||
{
|
{
|
||||||
dev->ctrl.val = ctrl_reg;
|
dev->ctrl.val = ctrl_reg;
|
||||||
|
|||||||
@@ -2,11 +2,14 @@ set(srcs "test_app_main.c"
|
|||||||
"test_dport.c"
|
"test_dport.c"
|
||||||
"test_fp.c"
|
"test_fp.c"
|
||||||
"test_dport_xt_highint5.S"
|
"test_dport_xt_highint5.S"
|
||||||
"test_random.c"
|
|
||||||
"test_intr_alloc.c"
|
"test_intr_alloc.c"
|
||||||
"test_rtc_wdt.c"
|
"test_rtc_wdt.c"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if(CONFIG_SOC_RNG_SUPPORTED)
|
||||||
|
list(APPEND srcs "test_random.c")
|
||||||
|
endif()
|
||||||
|
|
||||||
if(CONFIG_SOC_GP_LDO_SUPPORTED)
|
if(CONFIG_SOC_GP_LDO_SUPPORTED)
|
||||||
list(APPEND srcs "test_ldo.c")
|
list(APPEND srcs "test_ldo.c")
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if CONFIG_LCD_ENABLE_DEBUG_LOG
|
#if CONFIG_LCD_ENABLE_DEBUG_LOG
|
||||||
// The local log level must be defined before including esp_log.h
|
// The local log level must be defined before including esp_log.h
|
||||||
// Set the maximum log level for gptimer driver
|
// Set the maximum log level for dsi lcd driver
|
||||||
#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE
|
#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE
|
||||||
#endif
|
#endif
|
||||||
#include "hal/mipi_dsi_periph.h"
|
#include "hal/mipi_dsi_periph.h"
|
||||||
|
|||||||
@@ -273,6 +273,9 @@ esp_err_t esp_lcd_del_i80_bus(esp_lcd_i80_bus_handle_t bus)
|
|||||||
ESP_GOTO_ON_FALSE(bus, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
ESP_GOTO_ON_FALSE(bus, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
||||||
ESP_GOTO_ON_FALSE(LIST_EMPTY(&bus->device_list), ESP_ERR_INVALID_STATE, err, TAG, "device list not empty");
|
ESP_GOTO_ON_FALSE(LIST_EMPTY(&bus->device_list), ESP_ERR_INVALID_STATE, err, TAG, "device list not empty");
|
||||||
int bus_id = bus->bus_id;
|
int bus_id = bus->bus_id;
|
||||||
|
PERIPH_RCC_ATOMIC() {
|
||||||
|
lcd_ll_enable_clock(bus->hal.dev, false);
|
||||||
|
}
|
||||||
#if I80_USE_RETENTION_LINK
|
#if I80_USE_RETENTION_LINK
|
||||||
const periph_retention_module_t module_id = soc_i80_lcd_retention_info[bus_id].retention_module;
|
const periph_retention_module_t module_id = soc_i80_lcd_retention_info[bus_id].retention_module;
|
||||||
if (sleep_retention_is_module_created(module_id)) {
|
if (sleep_retention_is_module_created(module_id)) {
|
||||||
@@ -737,7 +740,7 @@ static void lcd_periph_trigger_quick_trans_done_event(esp_lcd_i80_bus_handle_t b
|
|||||||
.length = 4,
|
.length = 4,
|
||||||
.flags = {
|
.flags = {
|
||||||
.mark_eof = true, // mark the "EOF" flag to trigger LCD EOF interrupt
|
.mark_eof = true, // mark the "EOF" flag to trigger LCD EOF interrupt
|
||||||
.mark_final = true, // singly link list, mark final descriptor
|
.mark_final = GDMA_FINAL_LINK_TO_NULL, // singly link list, mark final descriptor
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
gdma_link_mount_buffers(bus->dma_link, 0, &mount_config, 1, NULL);
|
gdma_link_mount_buffers(bus->dma_link, 0, &mount_config, 1, NULL);
|
||||||
@@ -759,6 +762,7 @@ static void lcd_start_transaction(esp_lcd_i80_bus_t *bus, lcd_i80_trans_descript
|
|||||||
lcd_ll_set_phase_cycles(bus->hal.dev, cmd_cycles, dummy_cycles, data_cycles);
|
lcd_ll_set_phase_cycles(bus->hal.dev, cmd_cycles, dummy_cycles, data_cycles);
|
||||||
lcd_ll_set_blank_cycles(bus->hal.dev, 1, 1);
|
lcd_ll_set_blank_cycles(bus->hal.dev, 1, 1);
|
||||||
|
|
||||||
|
lcd_ll_reset(bus->hal.dev);
|
||||||
// reset FIFO before starting a new transaction, in case there remains some dirty data in the FIFO because of the "fake trigger".
|
// reset FIFO before starting a new transaction, in case there remains some dirty data in the FIFO because of the "fake trigger".
|
||||||
lcd_ll_fifo_reset(bus->hal.dev);
|
lcd_ll_fifo_reset(bus->hal.dev);
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if CONFIG_LCD_ENABLE_DEBUG_LOG
|
#if CONFIG_LCD_ENABLE_DEBUG_LOG
|
||||||
// The local log level must be defined before including esp_log.h
|
// The local log level must be defined before including esp_log.h
|
||||||
// Set the maximum log level for gptimer driver
|
// Set the maximum log level for i80 lcd driver
|
||||||
#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE
|
#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE
|
||||||
#endif
|
#endif
|
||||||
#include "soc/soc_caps.h"
|
#include "soc/soc_caps.h"
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if CONFIG_LCD_ENABLE_DEBUG_LOG
|
#if CONFIG_LCD_ENABLE_DEBUG_LOG
|
||||||
// The local log level must be defined before including esp_log.h
|
// The local log level must be defined before including esp_log.h
|
||||||
// Set the maximum log level for gptimer driver
|
// Set the maximum log level for rgb lcd driver
|
||||||
#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE
|
#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE
|
||||||
#endif
|
#endif
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
@@ -41,7 +41,6 @@
|
|||||||
#include "esp_cache.h"
|
#include "esp_cache.h"
|
||||||
#include "esp_memory_utils.h"
|
#include "esp_memory_utils.h"
|
||||||
#include "hal/lcd_periph.h"
|
#include "hal/lcd_periph.h"
|
||||||
#include "soc/io_mux_reg.h"
|
|
||||||
#include "hal/lcd_hal.h"
|
#include "hal/lcd_hal.h"
|
||||||
#include "hal/lcd_ll.h"
|
#include "hal/lcd_ll.h"
|
||||||
#include "hal/cache_hal.h"
|
#include "hal/cache_hal.h"
|
||||||
@@ -95,6 +94,11 @@ static esp_err_t lcd_rgb_panel_configure_gpio(esp_rgb_panel_t *rgb_panel, const
|
|||||||
static void lcd_rgb_panel_release_gpio(esp_rgb_panel_t *rgb_panel);
|
static void lcd_rgb_panel_release_gpio(esp_rgb_panel_t *rgb_panel);
|
||||||
static void lcd_rgb_panel_start_transmission(esp_rgb_panel_t *rgb_panel);
|
static void lcd_rgb_panel_start_transmission(esp_rgb_panel_t *rgb_panel);
|
||||||
static void rgb_lcd_default_isr_handler(void *args);
|
static void rgb_lcd_default_isr_handler(void *args);
|
||||||
|
static esp_err_t lcd_rgb_panel_configure_gpio_matrix(const esp_lcd_rgb_panel_config_t *panel_config, int panel_id, uint64_t *gpio_reserve_mask);
|
||||||
|
#if LCD_LL_SUPPORT(IOMUX)
|
||||||
|
static bool lcd_rgb_panel_can_use_iomux(const esp_lcd_rgb_panel_config_t *panel_config, const soc_lcd_rgb_iomux_desc_t *iomux_desc);
|
||||||
|
static esp_err_t lcd_rgb_panel_configure_iomux(const esp_lcd_rgb_panel_config_t *panel_config, const soc_lcd_rgb_iomux_desc_t *iomux_desc, uint64_t *gpio_reserve_mask);
|
||||||
|
#endif // LCD_LL_SUPPORT(IOMUX)
|
||||||
|
|
||||||
struct esp_rgb_panel_t {
|
struct esp_rgb_panel_t {
|
||||||
esp_lcd_panel_t base; // Base class of generic lcd panel
|
esp_lcd_panel_t base; // Base class of generic lcd panel
|
||||||
@@ -207,6 +211,7 @@ static esp_err_t lcd_rgb_panel_alloc_frame_buffers(esp_rgb_panel_t *rgb_panel, c
|
|||||||
|
|
||||||
// flush data from cache to the physical memory
|
// flush data from cache to the physical memory
|
||||||
if (rgb_panel->flags.fb_behind_cache) {
|
if (rgb_panel->flags.fb_behind_cache) {
|
||||||
|
ESP_LOGD(TAG, "frame buffer %d at %p is behind the cache", i, rgb_panel->fbs[i]);
|
||||||
esp_cache_msync(rgb_panel->fbs[i], rgb_panel->fb_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED);
|
esp_cache_msync(rgb_panel->fbs[i], rgb_panel->fb_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -245,6 +250,10 @@ static esp_err_t lcd_rgb_panel_destroy(esp_rgb_panel_t *rgb_panel)
|
|||||||
if (rgb_panel->clk_src) {
|
if (rgb_panel->clk_src) {
|
||||||
esp_clk_tree_enable_src(rgb_panel->clk_src, false);
|
esp_clk_tree_enable_src(rgb_panel->clk_src, false);
|
||||||
}
|
}
|
||||||
|
// force power off LCD trans buffer power
|
||||||
|
lcd_ll_mem_force_low_power(rgb_panel->hal.dev);
|
||||||
|
// disable the LCD trans buffer
|
||||||
|
lcd_ll_enable_trans_buffer(rgb_panel->hal.dev, false);
|
||||||
if (rgb_panel->panel_id >= 0) {
|
if (rgb_panel->panel_id >= 0) {
|
||||||
PERIPH_RCC_RELEASE_ATOMIC(soc_lcd_rgb_signals[rgb_panel->panel_id].module, ref_count) {
|
PERIPH_RCC_RELEASE_ATOMIC(soc_lcd_rgb_signals[rgb_panel->panel_id].module, ref_count) {
|
||||||
if (ref_count == 0) {
|
if (ref_count == 0) {
|
||||||
@@ -389,13 +398,19 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf
|
|||||||
PERIPH_RCC_ATOMIC() {
|
PERIPH_RCC_ATOMIC() {
|
||||||
lcd_ll_enable_clock(hal->dev, true);
|
lcd_ll_enable_clock(hal->dev, true);
|
||||||
}
|
}
|
||||||
|
// power down memory during low power stage
|
||||||
|
lcd_ll_mem_set_low_power_mode(hal->dev, LCD_LL_MEM_LP_MODE_SHUT_DOWN);
|
||||||
|
// let PMU control the LCD trans buffer power
|
||||||
|
lcd_ll_mem_power_by_pmu(hal->dev);
|
||||||
|
// enable the LCD trans buffer to improve the performance and prevent underrun
|
||||||
|
lcd_ll_enable_trans_buffer(hal->dev, true);
|
||||||
// set clock source
|
// set clock source
|
||||||
ret = lcd_rgb_panel_select_clock_src(rgb_panel, rgb_panel_config->clk_src);
|
ret = lcd_rgb_panel_select_clock_src(rgb_panel, rgb_panel_config->clk_src);
|
||||||
ESP_GOTO_ON_ERROR(ret, err, TAG, "set source clock failed");
|
ESP_GOTO_ON_ERROR(ret, err, TAG, "set source clock failed");
|
||||||
|
|
||||||
// reset peripheral and FIFO after we select a correct clock source
|
// reset peripheral and FIFO after we select a correct clock source
|
||||||
lcd_ll_fifo_reset(hal->dev);
|
|
||||||
lcd_ll_reset(hal->dev);
|
lcd_ll_reset(hal->dev);
|
||||||
|
lcd_ll_fifo_reset(hal->dev);
|
||||||
// install interrupt service, (LCD peripheral shares the interrupt source with Camera by different mask)
|
// install interrupt service, (LCD peripheral shares the interrupt source with Camera by different mask)
|
||||||
int isr_flags = LCD_RGB_INTR_ALLOC_FLAGS | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED;
|
int isr_flags = LCD_RGB_INTR_ALLOC_FLAGS | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED;
|
||||||
ret = esp_intr_alloc_intrstatus(soc_lcd_rgb_signals[panel_id].irq_id, isr_flags,
|
ret = esp_intr_alloc_intrstatus(soc_lcd_rgb_signals[panel_id].irq_id, isr_flags,
|
||||||
@@ -592,8 +607,8 @@ static esp_err_t rgb_panel_del(esp_lcd_panel_t *panel)
|
|||||||
static esp_err_t rgb_panel_reset(esp_lcd_panel_t *panel)
|
static esp_err_t rgb_panel_reset(esp_lcd_panel_t *panel)
|
||||||
{
|
{
|
||||||
esp_rgb_panel_t *rgb_panel = __containerof(panel, esp_rgb_panel_t, base);
|
esp_rgb_panel_t *rgb_panel = __containerof(panel, esp_rgb_panel_t, base);
|
||||||
lcd_ll_fifo_reset(rgb_panel->hal.dev);
|
|
||||||
lcd_ll_reset(rgb_panel->hal.dev);
|
lcd_ll_reset(rgb_panel->hal.dev);
|
||||||
|
lcd_ll_fifo_reset(rgb_panel->hal.dev);
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -809,35 +824,16 @@ static esp_err_t lcd_rgb_panel_configure_gpio(esp_rgb_panel_t *rgb_panel, const
|
|||||||
int panel_id = rgb_panel->panel_id;
|
int panel_id = rgb_panel->panel_id;
|
||||||
// Set the number of output data lines
|
// Set the number of output data lines
|
||||||
lcd_ll_set_data_wire_width(rgb_panel->hal.dev, panel_config->data_width);
|
lcd_ll_set_data_wire_width(rgb_panel->hal.dev, panel_config->data_width);
|
||||||
// connect peripheral signals via GPIO matrix
|
#if LCD_LL_SUPPORT(IOMUX)
|
||||||
for (size_t i = 0; i < panel_config->data_width; i++) {
|
const soc_lcd_rgb_iomux_desc_t *iomux_desc = &soc_lcd_rgb_iomux_descs[panel_id];
|
||||||
if (GPIO_IS_VALID_OUTPUT_GPIO(panel_config->data_gpio_nums[i])) {
|
if (lcd_rgb_panel_can_use_iomux(panel_config, iomux_desc)) {
|
||||||
gpio_matrix_output(panel_config->data_gpio_nums[i],
|
ESP_RETURN_ON_ERROR(lcd_rgb_panel_configure_iomux(panel_config, iomux_desc, &gpio_reserve_mask), TAG, "configure RGB iomux failed");
|
||||||
soc_lcd_rgb_signals[panel_id].data_sigs[i], false, false);
|
ESP_LOGD(TAG, "RGB panel uses IOMUX (data_width=%zu)", panel_config->data_width);
|
||||||
gpio_reserve_mask |= (1ULL << panel_config->data_gpio_nums[i]);
|
} else
|
||||||
}
|
#endif // LCD_LL_SUPPORT(IOMUX)
|
||||||
}
|
{
|
||||||
if (GPIO_IS_VALID_OUTPUT_GPIO(panel_config->hsync_gpio_num)) {
|
ESP_RETURN_ON_ERROR(lcd_rgb_panel_configure_gpio_matrix(panel_config, panel_id, &gpio_reserve_mask), TAG, "configure RGB GPIO matrix failed");
|
||||||
gpio_matrix_output(panel_config->hsync_gpio_num,
|
ESP_LOGD(TAG, "RGB panel uses GPIO matrix (data_width=%zu)", panel_config->data_width);
|
||||||
soc_lcd_rgb_signals[panel_id].hsync_sig, false, false);
|
|
||||||
gpio_reserve_mask |= (1ULL << panel_config->hsync_gpio_num);
|
|
||||||
}
|
|
||||||
if (GPIO_IS_VALID_OUTPUT_GPIO(panel_config->vsync_gpio_num)) {
|
|
||||||
gpio_matrix_output(panel_config->vsync_gpio_num,
|
|
||||||
soc_lcd_rgb_signals[panel_id].vsync_sig, false, false);
|
|
||||||
gpio_reserve_mask |= (1ULL << panel_config->vsync_gpio_num);
|
|
||||||
}
|
|
||||||
// PCLK may not be necessary in some cases (i.e. VGA output)
|
|
||||||
if (GPIO_IS_VALID_OUTPUT_GPIO(panel_config->pclk_gpio_num)) {
|
|
||||||
gpio_matrix_output(panel_config->pclk_gpio_num,
|
|
||||||
soc_lcd_rgb_signals[panel_id].pclk_sig, false, false);
|
|
||||||
gpio_reserve_mask |= (1ULL << panel_config->pclk_gpio_num);
|
|
||||||
}
|
|
||||||
// DE signal might not be necessary for some RGB LCD
|
|
||||||
if (GPIO_IS_VALID_OUTPUT_GPIO(panel_config->de_gpio_num)) {
|
|
||||||
gpio_matrix_output(panel_config->de_gpio_num,
|
|
||||||
soc_lcd_rgb_signals[panel_id].de_sig, false, false);
|
|
||||||
gpio_reserve_mask |= (1ULL << panel_config->de_gpio_num);
|
|
||||||
}
|
}
|
||||||
// disp enable GPIO is optional, it is a general purpose output GPIO
|
// disp enable GPIO is optional, it is a general purpose output GPIO
|
||||||
if (GPIO_IS_VALID_OUTPUT_GPIO(panel_config->disp_gpio_num)) {
|
if (GPIO_IS_VALID_OUTPUT_GPIO(panel_config->disp_gpio_num)) {
|
||||||
@@ -859,6 +855,93 @@ static esp_err_t lcd_rgb_panel_configure_gpio(esp_rgb_panel_t *rgb_panel, const
|
|||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LCD_LL_SUPPORT(IOMUX)
|
||||||
|
static bool lcd_rgb_panel_can_use_iomux(const esp_lcd_rgb_panel_config_t *panel_config, const soc_lcd_rgb_iomux_desc_t *iomux_desc)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < panel_config->data_width; i++) {
|
||||||
|
if (panel_config->data_gpio_nums[i] != iomux_desc->data_pins[i].gpio_num) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (GPIO_IS_VALID_OUTPUT_GPIO(panel_config->hsync_gpio_num) && panel_config->hsync_gpio_num != iomux_desc->hsync_pin.gpio_num) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (GPIO_IS_VALID_OUTPUT_GPIO(panel_config->vsync_gpio_num) && panel_config->vsync_gpio_num != iomux_desc->vsync_pin.gpio_num) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (GPIO_IS_VALID_OUTPUT_GPIO(panel_config->pclk_gpio_num) && panel_config->pclk_gpio_num != iomux_desc->pclk_pin.gpio_num) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (GPIO_IS_VALID_OUTPUT_GPIO(panel_config->de_gpio_num) && panel_config->de_gpio_num != iomux_desc->de_pin.gpio_num) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t lcd_rgb_panel_configure_iomux(const esp_lcd_rgb_panel_config_t *panel_config, const soc_lcd_rgb_iomux_desc_t *iomux_desc, uint64_t *gpio_reserve_mask)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < panel_config->data_width; i++) {
|
||||||
|
const soc_lcd_iomux_pin_desc_t *pin = &iomux_desc->data_pins[i];
|
||||||
|
ESP_RETURN_ON_ERROR(gpio_iomux_output(pin->gpio_num, pin->func), TAG, "set data[%zu] iomux failed", i);
|
||||||
|
*gpio_reserve_mask |= (1ULL << pin->gpio_num);
|
||||||
|
}
|
||||||
|
if (GPIO_IS_VALID_OUTPUT_GPIO(panel_config->hsync_gpio_num)) {
|
||||||
|
ESP_RETURN_ON_ERROR(gpio_iomux_output(iomux_desc->hsync_pin.gpio_num, iomux_desc->hsync_pin.func), TAG, "set hsync iomux failed");
|
||||||
|
*gpio_reserve_mask |= (1ULL << panel_config->hsync_gpio_num);
|
||||||
|
}
|
||||||
|
if (GPIO_IS_VALID_OUTPUT_GPIO(panel_config->vsync_gpio_num)) {
|
||||||
|
ESP_RETURN_ON_ERROR(gpio_iomux_output(iomux_desc->vsync_pin.gpio_num, iomux_desc->vsync_pin.func), TAG, "set vsync iomux failed");
|
||||||
|
*gpio_reserve_mask |= (1ULL << panel_config->vsync_gpio_num);
|
||||||
|
}
|
||||||
|
// PCLK may not be necessary in some cases (i.e. VGA output)
|
||||||
|
if (GPIO_IS_VALID_OUTPUT_GPIO(panel_config->pclk_gpio_num)) {
|
||||||
|
ESP_RETURN_ON_ERROR(gpio_iomux_output(iomux_desc->pclk_pin.gpio_num, iomux_desc->pclk_pin.func), TAG, "set pclk iomux failed");
|
||||||
|
*gpio_reserve_mask |= (1ULL << panel_config->pclk_gpio_num);
|
||||||
|
}
|
||||||
|
// DE signal might not be necessary for some RGB LCD
|
||||||
|
if (GPIO_IS_VALID_OUTPUT_GPIO(panel_config->de_gpio_num)) {
|
||||||
|
ESP_RETURN_ON_ERROR(gpio_iomux_output(iomux_desc->de_pin.gpio_num, iomux_desc->de_pin.func), TAG, "set de iomux failed");
|
||||||
|
*gpio_reserve_mask |= (1ULL << panel_config->de_gpio_num);
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
#endif // LCD_LL_SUPPORT(IOMUX)
|
||||||
|
|
||||||
|
static esp_err_t lcd_rgb_panel_configure_gpio_matrix(const esp_lcd_rgb_panel_config_t *panel_config, int panel_id, uint64_t *gpio_reserve_mask)
|
||||||
|
{
|
||||||
|
// connect peripheral signals via GPIO matrix
|
||||||
|
for (size_t i = 0; i < panel_config->data_width; i++) {
|
||||||
|
if (GPIO_IS_VALID_OUTPUT_GPIO(panel_config->data_gpio_nums[i])) {
|
||||||
|
gpio_matrix_output(panel_config->data_gpio_nums[i],
|
||||||
|
soc_lcd_rgb_signals[panel_id].data_sigs[i], false, false);
|
||||||
|
*gpio_reserve_mask |= (1ULL << panel_config->data_gpio_nums[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (GPIO_IS_VALID_OUTPUT_GPIO(panel_config->hsync_gpio_num)) {
|
||||||
|
gpio_matrix_output(panel_config->hsync_gpio_num,
|
||||||
|
soc_lcd_rgb_signals[panel_id].hsync_sig, false, false);
|
||||||
|
*gpio_reserve_mask |= (1ULL << panel_config->hsync_gpio_num);
|
||||||
|
}
|
||||||
|
if (GPIO_IS_VALID_OUTPUT_GPIO(panel_config->vsync_gpio_num)) {
|
||||||
|
gpio_matrix_output(panel_config->vsync_gpio_num,
|
||||||
|
soc_lcd_rgb_signals[panel_id].vsync_sig, false, false);
|
||||||
|
*gpio_reserve_mask |= (1ULL << panel_config->vsync_gpio_num);
|
||||||
|
}
|
||||||
|
// PCLK may not be necessary in some cases (i.e. VGA output)
|
||||||
|
if (GPIO_IS_VALID_OUTPUT_GPIO(panel_config->pclk_gpio_num)) {
|
||||||
|
gpio_matrix_output(panel_config->pclk_gpio_num,
|
||||||
|
soc_lcd_rgb_signals[panel_id].pclk_sig, false, false);
|
||||||
|
*gpio_reserve_mask |= (1ULL << panel_config->pclk_gpio_num);
|
||||||
|
}
|
||||||
|
// DE signal might not be necessary for some RGB LCD
|
||||||
|
if (GPIO_IS_VALID_OUTPUT_GPIO(panel_config->de_gpio_num)) {
|
||||||
|
gpio_matrix_output(panel_config->de_gpio_num,
|
||||||
|
soc_lcd_rgb_signals[panel_id].de_sig, false, false);
|
||||||
|
*gpio_reserve_mask |= (1ULL << panel_config->de_gpio_num);
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static void lcd_rgb_panel_release_gpio(esp_rgb_panel_t *rgb_panel)
|
static void lcd_rgb_panel_release_gpio(esp_rgb_panel_t *rgb_panel)
|
||||||
{
|
{
|
||||||
if (rgb_panel->gpio_reserve_mask) {
|
if (rgb_panel->gpio_reserve_mask) {
|
||||||
@@ -1197,10 +1280,10 @@ static IRAM_ATTR void lcd_rgb_panel_try_restart_transmission(esp_rgb_panel_t *pa
|
|||||||
static void lcd_rgb_panel_start_transmission(esp_rgb_panel_t *rgb_panel)
|
static void lcd_rgb_panel_start_transmission(esp_rgb_panel_t *rgb_panel)
|
||||||
{
|
{
|
||||||
// reset FIFO of DMA and LCD, in case there remains old frame data
|
// reset FIFO of DMA and LCD, in case there remains old frame data
|
||||||
gdma_reset(rgb_panel->dma_chan);
|
|
||||||
lcd_ll_stop(rgb_panel->hal.dev);
|
lcd_ll_stop(rgb_panel->hal.dev);
|
||||||
lcd_ll_reset(rgb_panel->hal.dev);
|
lcd_ll_reset(rgb_panel->hal.dev);
|
||||||
lcd_ll_fifo_reset(rgb_panel->hal.dev);
|
lcd_ll_fifo_reset(rgb_panel->hal.dev);
|
||||||
|
gdma_reset(rgb_panel->dma_chan);
|
||||||
|
|
||||||
// pre-fill bounce buffers if needed
|
// pre-fill bounce buffers if needed
|
||||||
if (rgb_panel->bb_size) {
|
if (rgb_panel->bb_size) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
| Supported Targets | ESP32 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
|
| Supported Targets | ESP32 | ESP32-P4 | ESP32-S2 | ESP32-S3 | ESP32-S31 |
|
||||||
| ----------------- | ----- | -------- | -------- | -------- |
|
| ----------------- | ----- | -------- | -------- | -------- | --------- |
|
||||||
|
|
||||||
This test app is used to test LCDs with intel 8080 interface.
|
This test app is used to test LCDs with intel 8080 interface.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -100,6 +100,28 @@ extern "C" {
|
|||||||
#define TEST_LCD_DATA13_GPIO (25)
|
#define TEST_LCD_DATA13_GPIO (25)
|
||||||
#define TEST_LCD_DATA14_GPIO (16)
|
#define TEST_LCD_DATA14_GPIO (16)
|
||||||
#define TEST_LCD_DATA15_GPIO (17)
|
#define TEST_LCD_DATA15_GPIO (17)
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S31
|
||||||
|
#define TEST_LCD_BK_LIGHT_GPIO (1)
|
||||||
|
#define TEST_LCD_RST_GPIO (56)
|
||||||
|
#define TEST_LCD_CS_GPIO (2)
|
||||||
|
#define TEST_LCD_DC_GPIO (54)
|
||||||
|
#define TEST_LCD_PCLK_GPIO (5)
|
||||||
|
#define TEST_LCD_DATA0_GPIO (11)
|
||||||
|
#define TEST_LCD_DATA1_GPIO (52)
|
||||||
|
#define TEST_LCD_DATA2_GPIO (8)
|
||||||
|
#define TEST_LCD_DATA3_GPIO (50)
|
||||||
|
#define TEST_LCD_DATA4_GPIO (6)
|
||||||
|
#define TEST_LCD_DATA5_GPIO (48)
|
||||||
|
#define TEST_LCD_DATA6_GPIO (13)
|
||||||
|
#define TEST_LCD_DATA7_GPIO (46)
|
||||||
|
#define TEST_LCD_DATA8_GPIO (16)
|
||||||
|
#define TEST_LCD_DATA9_GPIO (9)
|
||||||
|
#define TEST_LCD_DATA10_GPIO (10)
|
||||||
|
#define TEST_LCD_DATA11_GPIO (17)
|
||||||
|
#define TEST_LCD_DATA12_GPIO (12)
|
||||||
|
#define TEST_LCD_DATA13_GPIO (18)
|
||||||
|
#define TEST_LCD_DATA14_GPIO (14)
|
||||||
|
#define TEST_LCD_DATA15_GPIO (15)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: CC0-1.0
|
* SPDX-License-Identifier: CC0-1.0
|
||||||
*/
|
*/
|
||||||
@@ -9,7 +9,6 @@
|
|||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "unity.h"
|
#include "unity.h"
|
||||||
#include "esp_random.h"
|
|
||||||
#include "esp_lcd_panel_io.h"
|
#include "esp_lcd_panel_io.h"
|
||||||
#include "esp_lcd_panel_vendor.h"
|
#include "esp_lcd_panel_vendor.h"
|
||||||
#include "esp_lcd_nt35510.h"
|
#include "esp_lcd_nt35510.h"
|
||||||
@@ -432,9 +431,9 @@ TEST_CASE("lcd_panel_with_i80_interface (st7789, 8bits)", "[lcd]")
|
|||||||
gpio_set_level(TEST_LCD_BK_LIGHT_GPIO, 1);
|
gpio_set_level(TEST_LCD_BK_LIGHT_GPIO, 1);
|
||||||
|
|
||||||
for (int i = 0; i < 200; i++) {
|
for (int i = 0; i < 200; i++) {
|
||||||
uint8_t color_byte = esp_random() & 0xFF;
|
uint8_t color_byte = rand() & 0xFF;
|
||||||
int x_start = esp_random() % (TEST_LCD_H_RES - 100);
|
int x_start = rand() % (TEST_LCD_H_RES - 100);
|
||||||
int y_start = esp_random() % (TEST_LCD_V_RES - 100);
|
int y_start = rand() % (TEST_LCD_V_RES - 100);
|
||||||
memset(img, color_byte, TEST_IMG_SIZE);
|
memset(img, color_byte, TEST_IMG_SIZE);
|
||||||
esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_start + 100, y_start + 100, img);
|
esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_start + 100, y_start + 100, img);
|
||||||
}
|
}
|
||||||
@@ -460,7 +459,7 @@ TEST_CASE("i80_lcd_send_colors_to_fixed_region", "[lcd]")
|
|||||||
size_t color_size = (x_end - x_start) * (y_end - y_start) * 2;
|
size_t color_size = (x_end - x_start) * (y_end - y_start) * 2;
|
||||||
void *color_data = malloc(color_size);
|
void *color_data = malloc(color_size);
|
||||||
TEST_ASSERT_NOT_NULL(color_data);
|
TEST_ASSERT_NOT_NULL(color_data);
|
||||||
uint8_t color_byte = esp_random() & 0xFF;
|
uint8_t color_byte = rand() & 0xFF;
|
||||||
memset(color_data, color_byte, color_size);
|
memset(color_data, color_byte, color_size);
|
||||||
|
|
||||||
printf("creating i80 bus and IO driver\r\n");
|
printf("creating i80 bus and IO driver\r\n");
|
||||||
@@ -545,7 +544,7 @@ TEST_CASE("i80_lcd_send_colors_to_fixed_region", "[lcd]")
|
|||||||
}
|
}
|
||||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
// change to another color
|
// change to another color
|
||||||
color_byte = esp_random() & 0xFF;
|
color_byte = rand() & 0xFF;
|
||||||
memset(color_data, color_byte, color_size);
|
memset(color_data, color_byte, color_size);
|
||||||
for (int i = 0; i < steps; i++) {
|
for (int i = 0; i < steps; i++) {
|
||||||
TEST_ESP_OK(esp_lcd_panel_io_tx_color(io_handle, -1, color_data + i * color_size_per_step, color_size_per_step));
|
TEST_ESP_OK(esp_lcd_panel_io_tx_color(io_handle, -1, color_data + i * color_size_per_step, color_size_per_step));
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
import pytest
|
import pytest
|
||||||
from pytest_embedded import Dut
|
from pytest_embedded import Dut
|
||||||
from pytest_embedded_idf.utils import idf_parametrize
|
from pytest_embedded_idf.utils import idf_parametrize
|
||||||
|
from pytest_embedded_idf.utils import soc_filtered_targets
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.generic
|
@pytest.mark.generic
|
||||||
@@ -13,7 +14,7 @@ from pytest_embedded_idf.utils import idf_parametrize
|
|||||||
],
|
],
|
||||||
indirect=True,
|
indirect=True,
|
||||||
)
|
)
|
||||||
@idf_parametrize('target', ['esp32', 'esp32s2', 'esp32s3', 'esp32p4'], indirect=['target'])
|
@idf_parametrize('target', soc_filtered_targets('SOC_LCD_I80_SUPPORTED == 1'), indirect=['target'])
|
||||||
def test_i80_lcd(dut: Dut) -> None:
|
def test_i80_lcd(dut: Dut) -> None:
|
||||||
dut.run_all_single_board_cases()
|
dut.run_all_single_board_cases()
|
||||||
|
|
||||||
@@ -26,7 +27,11 @@ def test_i80_lcd(dut: Dut) -> None:
|
|||||||
],
|
],
|
||||||
indirect=True,
|
indirect=True,
|
||||||
)
|
)
|
||||||
@idf_parametrize('target', ['esp32', 'esp32s2', 'esp32s3', 'esp32p4'], indirect=['target'])
|
@idf_parametrize(
|
||||||
|
'target',
|
||||||
|
soc_filtered_targets('SOC_LCD_I80_SUPPORTED == 1 and SOC_FLASH_ENC_SUPPORTED == 1'),
|
||||||
|
indirect=['target'],
|
||||||
|
)
|
||||||
def test_i80_lcd_with_virt_flash_enc(dut: Dut) -> None:
|
def test_i80_lcd_with_virt_flash_enc(dut: Dut) -> None:
|
||||||
print(' - Erase flash')
|
print(' - Erase flash')
|
||||||
dut.serial.erase_flash()
|
dut.serial.erase_flash()
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
| Supported Targets | ESP32-P4 | ESP32-S3 |
|
| Supported Targets | ESP32-P4 | ESP32-S3 | ESP32-S31 |
|
||||||
| ----------------- | -------- | -------- |
|
| ----------------- | -------- | -------- | --------- |
|
||||||
|
|
||||||
This test app is used to test RGB565 interfaced LCDs.
|
This test app is used to test RGB565 interfaced LCDs.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -68,6 +68,30 @@ extern "C" {
|
|||||||
#define TEST_LCD_DATA15_GPIO 19 // R4
|
#define TEST_LCD_DATA15_GPIO 19 // R4
|
||||||
#define TEST_LCD_DISP_EN_GPIO -1
|
#define TEST_LCD_DISP_EN_GPIO -1
|
||||||
|
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S31
|
||||||
|
|
||||||
|
#define TEST_LCD_VSYNC_GPIO 45
|
||||||
|
#define TEST_LCD_HSYNC_GPIO 44
|
||||||
|
#define TEST_LCD_DE_GPIO 43
|
||||||
|
#define TEST_LCD_PCLK_GPIO 40
|
||||||
|
#define TEST_LCD_DATA0_GPIO 11 // B3
|
||||||
|
#define TEST_LCD_DATA1_GPIO 12 // B4
|
||||||
|
#define TEST_LCD_DATA2_GPIO 13 // B5
|
||||||
|
#define TEST_LCD_DATA3_GPIO 14 // B6
|
||||||
|
#define TEST_LCD_DATA4_GPIO 15 // B7
|
||||||
|
#define TEST_LCD_DATA5_GPIO 18 // G2
|
||||||
|
#define TEST_LCD_DATA6_GPIO 19 // G3
|
||||||
|
#define TEST_LCD_DATA7_GPIO 33 // G4
|
||||||
|
#define TEST_LCD_DATA8_GPIO 34 // G5
|
||||||
|
#define TEST_LCD_DATA9_GPIO 35 // G6
|
||||||
|
#define TEST_LCD_DATA10_GPIO 36 // G7
|
||||||
|
#define TEST_LCD_DATA11_GPIO 2 // R3
|
||||||
|
#define TEST_LCD_DATA12_GPIO 3 // R4
|
||||||
|
#define TEST_LCD_DATA13_GPIO 4 // R5
|
||||||
|
#define TEST_LCD_DATA14_GPIO 5 // R6
|
||||||
|
#define TEST_LCD_DATA15_GPIO 7 // R7
|
||||||
|
#define TEST_LCD_DISP_EN_GPIO -1
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#error "Unsupported target"
|
#error "Unsupported target"
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
#include "unity.h"
|
#include "unity.h"
|
||||||
#include "esp_lcd_panel_rgb.h"
|
#include "esp_lcd_panel_rgb.h"
|
||||||
#include "esp_lcd_panel_ops.h"
|
#include "esp_lcd_panel_ops.h"
|
||||||
#include "esp_random.h"
|
|
||||||
#include "esp_timer.h"
|
#include "esp_timer.h"
|
||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
#include "test_rgb_board.h"
|
#include "test_rgb_board.h"
|
||||||
@@ -101,9 +100,9 @@ TEST_CASE("lcd_rgb_panel_stream_mode", "[lcd]")
|
|||||||
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, LCD_CLK_SRC_DEFAULT, false, false, NULL, NULL);
|
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, LCD_CLK_SRC_DEFAULT, false, false, NULL, NULL);
|
||||||
printf("flush random color block\r\n");
|
printf("flush random color block\r\n");
|
||||||
for (int i = 0; i < 200; i++) {
|
for (int i = 0; i < 200; i++) {
|
||||||
uint8_t color_byte = esp_random() & 0xFF;
|
uint8_t color_byte = rand() & 0xFF;
|
||||||
int x_start = esp_random() % (TEST_LCD_H_RES - 100);
|
int x_start = rand() % (TEST_LCD_H_RES - 100);
|
||||||
int y_start = esp_random() % (TEST_LCD_V_RES - 100);
|
int y_start = rand() % (TEST_LCD_V_RES - 100);
|
||||||
memset(img, color_byte, TEST_IMG_SIZE);
|
memset(img, color_byte, TEST_IMG_SIZE);
|
||||||
esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_start + 100, y_start + 100, img);
|
esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_start + 100, y_start + 100, img);
|
||||||
vTaskDelay(pdMS_TO_TICKS(10));
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
@@ -121,10 +120,10 @@ TEST_CASE("lcd_rgb_panel_8bit_interface", "[lcd]")
|
|||||||
printf("initialize RGB panel with stream mode\r\n");
|
printf("initialize RGB panel with stream mode\r\n");
|
||||||
// bpp for RGB888 is 24
|
// bpp for RGB888 is 24
|
||||||
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(8, LCD_COLOR_FMT_RGB888, 0, LCD_CLK_SRC_DEFAULT, false, false, NULL, NULL);
|
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(8, LCD_COLOR_FMT_RGB888, 0, LCD_CLK_SRC_DEFAULT, false, false, NULL, NULL);
|
||||||
uint8_t color_byte = esp_random() & 0xFF;
|
uint8_t color_byte = rand() & 0xFF;
|
||||||
printf("flush random color block 0x%x\r\n", color_byte);
|
printf("flush random color block 0x%x\r\n", color_byte);
|
||||||
int x_start = esp_random() % (TEST_LCD_H_RES - 100);
|
int x_start = rand() % (TEST_LCD_H_RES - 100);
|
||||||
int y_start = esp_random() % (TEST_LCD_V_RES - 100);
|
int y_start = rand() % (TEST_LCD_V_RES - 100);
|
||||||
memset(img, color_byte, 100 * 100 * 3);
|
memset(img, color_byte, 100 * 100 * 3);
|
||||||
esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_start + 100, y_start + 100, img);
|
esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_start + 100, y_start + 100, img);
|
||||||
vTaskDelay(pdMS_TO_TICKS(2000));
|
vTaskDelay(pdMS_TO_TICKS(2000));
|
||||||
@@ -151,9 +150,9 @@ TEST_CASE("lcd_rgb_panel_refresh_on_demand", "[lcd]")
|
|||||||
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, LCD_CLK_SRC_DEFAULT, true, false, test_rgb_panel_trans_done, cur_task);
|
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, LCD_CLK_SRC_DEFAULT, true, false, test_rgb_panel_trans_done, cur_task);
|
||||||
printf("flush random color block\r\n");
|
printf("flush random color block\r\n");
|
||||||
for (int i = 0; i < 200; i++) {
|
for (int i = 0; i < 200; i++) {
|
||||||
uint8_t color_byte = esp_random() & 0xFF;
|
uint8_t color_byte = rand() & 0xFF;
|
||||||
int x_start = esp_random() % (TEST_LCD_H_RES - 100);
|
int x_start = rand() % (TEST_LCD_H_RES - 100);
|
||||||
int y_start = esp_random() % (TEST_LCD_V_RES - 100);
|
int y_start = rand() % (TEST_LCD_V_RES - 100);
|
||||||
memset(img, color_byte, TEST_IMG_SIZE);
|
memset(img, color_byte, TEST_IMG_SIZE);
|
||||||
esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_start + 100, y_start + 100, img);
|
esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_start + 100, y_start + 100, img);
|
||||||
esp_lcd_rgb_panel_refresh(panel_handle);
|
esp_lcd_rgb_panel_refresh(panel_handle);
|
||||||
@@ -176,9 +175,9 @@ TEST_CASE("lcd_rgb_panel_bounce_buffer", "[lcd]")
|
|||||||
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 20 * TEST_LCD_H_RES, LCD_CLK_SRC_DEFAULT, false, false, test_rgb_panel_trans_done, cur_task);
|
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 20 * TEST_LCD_H_RES, LCD_CLK_SRC_DEFAULT, false, false, test_rgb_panel_trans_done, cur_task);
|
||||||
printf("flush random color block\r\n");
|
printf("flush random color block\r\n");
|
||||||
for (int i = 0; i < 200; i++) {
|
for (int i = 0; i < 200; i++) {
|
||||||
uint8_t color_byte = esp_random() & 0xFF;
|
uint8_t color_byte = rand() & 0xFF;
|
||||||
int x_start = esp_random() % (TEST_LCD_H_RES - 100);
|
int x_start = rand() % (TEST_LCD_H_RES - 100);
|
||||||
int y_start = esp_random() % (TEST_LCD_V_RES - 100);
|
int y_start = rand() % (TEST_LCD_V_RES - 100);
|
||||||
memset(img, color_byte, TEST_IMG_SIZE);
|
memset(img, color_byte, TEST_IMG_SIZE);
|
||||||
esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_start + 100, y_start + 100, img);
|
esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_start + 100, y_start + 100, img);
|
||||||
// wait for flush done
|
// wait for flush done
|
||||||
@@ -198,9 +197,9 @@ TEST_CASE("lcd_rgb_panel_update_pclk", "[lcd]")
|
|||||||
printf("initialize RGB panel with stream mode\r\n");
|
printf("initialize RGB panel with stream mode\r\n");
|
||||||
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, LCD_CLK_SRC_DEFAULT, false, false, NULL, NULL);
|
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, LCD_CLK_SRC_DEFAULT, false, false, NULL, NULL);
|
||||||
printf("flush one clock block to the LCD\r\n");
|
printf("flush one clock block to the LCD\r\n");
|
||||||
uint8_t color_byte = esp_random() & 0xFF;
|
uint8_t color_byte = rand() & 0xFF;
|
||||||
int x_start = esp_random() % (TEST_LCD_H_RES - 100);
|
int x_start = rand() % (TEST_LCD_H_RES - 100);
|
||||||
int y_start = esp_random() % (TEST_LCD_V_RES - 100);
|
int y_start = rand() % (TEST_LCD_V_RES - 100);
|
||||||
memset(img, color_byte, TEST_IMG_SIZE);
|
memset(img, color_byte, TEST_IMG_SIZE);
|
||||||
esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_start + 100, y_start + 100, img);
|
esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_start + 100, y_start + 100, img);
|
||||||
printf("The LCD driver should keep flushing the color block in the background (as it's in stream mode)\r\n");
|
printf("The LCD driver should keep flushing the color block in the background (as it's in stream mode)\r\n");
|
||||||
@@ -226,9 +225,9 @@ TEST_CASE("lcd_rgb_panel_restart", "[lcd]")
|
|||||||
printf("initialize RGB panel with stream mode\r\n");
|
printf("initialize RGB panel with stream mode\r\n");
|
||||||
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, LCD_CLK_SRC_DEFAULT, false, false, NULL, NULL);
|
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, LCD_CLK_SRC_DEFAULT, false, false, NULL, NULL);
|
||||||
printf("flush one clock block to the LCD\r\n");
|
printf("flush one clock block to the LCD\r\n");
|
||||||
uint8_t color_byte = esp_random() & 0xFF;
|
uint8_t color_byte = rand() & 0xFF;
|
||||||
int x_start = esp_random() % (TEST_LCD_H_RES - 100);
|
int x_start = rand() % (TEST_LCD_H_RES - 100);
|
||||||
int y_start = esp_random() % (TEST_LCD_V_RES - 100);
|
int y_start = rand() % (TEST_LCD_V_RES - 100);
|
||||||
memset(img, color_byte, TEST_IMG_SIZE);
|
memset(img, color_byte, TEST_IMG_SIZE);
|
||||||
esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_start + 100, y_start + 100, img);
|
esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_start + 100, y_start + 100, img);
|
||||||
printf("The LCD driver should keep flushing the color block in the background (as it's in stream mode)\r\n");
|
printf("The LCD driver should keep flushing the color block in the background (as it's in stream mode)\r\n");
|
||||||
@@ -250,7 +249,7 @@ TEST_CASE("lcd_rgb_panel_rotate", "[lcd]")
|
|||||||
uint64_t t = 0;
|
uint64_t t = 0;
|
||||||
uint8_t *img = malloc(w * h * sizeof(uint16_t));
|
uint8_t *img = malloc(w * h * sizeof(uint16_t));
|
||||||
TEST_ASSERT_NOT_NULL(img);
|
TEST_ASSERT_NOT_NULL(img);
|
||||||
uint8_t color_byte = esp_random() & 0xFF;
|
uint8_t color_byte = rand() & 0xFF;
|
||||||
memset(img, color_byte, w * h * sizeof(uint16_t));
|
memset(img, color_byte, w * h * sizeof(uint16_t));
|
||||||
|
|
||||||
printf("initialize RGB panel with stream mode\r\n");
|
printf("initialize RGB panel with stream mode\r\n");
|
||||||
@@ -282,9 +281,9 @@ TEST_CASE("lcd_rgb_panel_user_frame_buffer", "[lcd]")
|
|||||||
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, LCD_CLK_SRC_DEFAULT, false, true, NULL, NULL);
|
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, LCD_CLK_SRC_DEFAULT, false, true, NULL, NULL);
|
||||||
|
|
||||||
printf("flush one clock block to the LCD\r\n");
|
printf("flush one clock block to the LCD\r\n");
|
||||||
uint8_t color_byte = esp_random() & 0xFF;
|
uint8_t color_byte = rand() & 0xFF;
|
||||||
int x_start = esp_random() % (TEST_LCD_H_RES - 100);
|
int x_start = rand() % (TEST_LCD_H_RES - 100);
|
||||||
int y_start = esp_random() % (TEST_LCD_V_RES - 100);
|
int y_start = rand() % (TEST_LCD_V_RES - 100);
|
||||||
memset(img, color_byte, TEST_IMG_SIZE);
|
memset(img, color_byte, TEST_IMG_SIZE);
|
||||||
esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_start + 100, y_start + 100, img);
|
esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_start + 100, y_start + 100, img);
|
||||||
printf("The LCD driver should keep flushing the color block in the background (as it's in stream mode)\r\n");
|
printf("The LCD driver should keep flushing the color block in the background (as it's in stream mode)\r\n");
|
||||||
@@ -316,9 +315,9 @@ TEST_CASE("lcd_rgb_panel_use_apll", "[lcd]")
|
|||||||
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, LCD_CLK_SRC_APLL, false, false, NULL, NULL);
|
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, LCD_CLK_SRC_APLL, false, false, NULL, NULL);
|
||||||
printf("flush random color block\r\n");
|
printf("flush random color block\r\n");
|
||||||
for (int i = 0; i < 200; i++) {
|
for (int i = 0; i < 200; i++) {
|
||||||
uint8_t color_byte = esp_random() & 0xFF;
|
uint8_t color_byte = rand() & 0xFF;
|
||||||
int x_start = esp_random() % (TEST_LCD_H_RES - 100);
|
int x_start = rand() % (TEST_LCD_H_RES - 100);
|
||||||
int y_start = esp_random() % (TEST_LCD_V_RES - 100);
|
int y_start = rand() % (TEST_LCD_V_RES - 100);
|
||||||
memset(img, color_byte, TEST_IMG_SIZE);
|
memset(img, color_byte, TEST_IMG_SIZE);
|
||||||
esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_start + 100, y_start + 100, img);
|
esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_start + 100, y_start + 100, img);
|
||||||
vTaskDelay(pdMS_TO_TICKS(10));
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
@@ -356,9 +355,9 @@ TEST_CASE("lcd_rgb_panel_iram_safe", "[lcd]")
|
|||||||
printf("initialize RGB panel with stream mode\r\n");
|
printf("initialize RGB panel with stream mode\r\n");
|
||||||
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, LCD_CLK_SRC_DEFAULT, false, false, test_rgb_panel_count_in_callback, &callback_calls);
|
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, LCD_CLK_SRC_DEFAULT, false, false, test_rgb_panel_count_in_callback, &callback_calls);
|
||||||
printf("flush one clock block to the LCD\r\n");
|
printf("flush one clock block to the LCD\r\n");
|
||||||
uint8_t color_byte = esp_random() & 0xFF;
|
uint8_t color_byte = rand() & 0xFF;
|
||||||
int x_start = esp_random() % (TEST_LCD_H_RES - 100);
|
int x_start = rand() % (TEST_LCD_H_RES - 100);
|
||||||
int y_start = esp_random() % (TEST_LCD_V_RES - 100);
|
int y_start = rand() % (TEST_LCD_V_RES - 100);
|
||||||
memset(img, color_byte, TEST_IMG_SIZE);
|
memset(img, color_byte, TEST_IMG_SIZE);
|
||||||
esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_start + 100, y_start + 100, img);
|
esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_start + 100, y_start + 100, img);
|
||||||
printf("The LCD driver should keep flushing the color block in the background (as it's in stream mode)\r\n");
|
printf("The LCD driver should keep flushing the color block in the background (as it's in stream mode)\r\n");
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
import pytest
|
import pytest
|
||||||
from pytest_embedded import Dut
|
from pytest_embedded import Dut
|
||||||
from pytest_embedded_idf.utils import idf_parametrize
|
from pytest_embedded_idf.utils import idf_parametrize
|
||||||
|
from pytest_embedded_idf.utils import soc_filtered_targets
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.octal_psram
|
@pytest.mark.octal_psram
|
||||||
@@ -50,8 +51,8 @@ def test_rgb_lcd_esp32s3_with_virt_flash_enc(dut: Dut) -> None:
|
|||||||
],
|
],
|
||||||
indirect=True,
|
indirect=True,
|
||||||
)
|
)
|
||||||
@idf_parametrize('target', ['esp32p4'], indirect=['target'])
|
@idf_parametrize('target', ['esp32p4', 'esp32s31'], indirect=['target'])
|
||||||
def test_rgb_lcd_esp32p4(dut: Dut) -> None:
|
def test_rgb_lcd(dut: Dut) -> None:
|
||||||
dut.run_all_single_board_cases()
|
dut.run_all_single_board_cases()
|
||||||
|
|
||||||
|
|
||||||
@@ -63,8 +64,12 @@ def test_rgb_lcd_esp32p4(dut: Dut) -> None:
|
|||||||
],
|
],
|
||||||
indirect=True,
|
indirect=True,
|
||||||
)
|
)
|
||||||
@idf_parametrize('target', ['esp32p4'], indirect=['target'])
|
@idf_parametrize(
|
||||||
def test_rgb_lcd_esp32p4_with_virt_flash_enc(dut: Dut) -> None:
|
'target',
|
||||||
|
soc_filtered_targets('IDF_TARGET in ["esp32p4", "esp32s31"] and SOC_FLASH_ENC_SUPPORTED == 1'),
|
||||||
|
indirect=['target'],
|
||||||
|
)
|
||||||
|
def test_rgb_lcd_with_virt_flash_enc(dut: Dut) -> None:
|
||||||
print(' - Erase flash')
|
print(' - Erase flash')
|
||||||
dut.serial.erase_flash()
|
dut.serial.erase_flash()
|
||||||
|
|
||||||
|
|||||||
@@ -2,5 +2,5 @@ CONFIG_SPIRAM=y
|
|||||||
CONFIG_SPIRAM_MODE_OCT=y
|
CONFIG_SPIRAM_MODE_OCT=y
|
||||||
CONFIG_SPIRAM_SPEED_80M=y
|
CONFIG_SPIRAM_SPEED_80M=y
|
||||||
|
|
||||||
# Enable the XIP-PSRAM feature, so the ext-mem cache won't be disabled when SPI1 is operating the main flash
|
# Enable the XIP-PSRAM feature, to increase PSRAM bandwidth
|
||||||
CONFIG_SPIRAM_XIP_FROM_PSRAM=y
|
CONFIG_SPIRAM_XIP_FROM_PSRAM=y
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
CONFIG_SPIRAM=y
|
||||||
|
CONFIG_SPIRAM_MODE_OCT=y
|
||||||
|
CONFIG_SPIRAM_SPEED_250M=y
|
||||||
|
|
||||||
|
# Enable the XIP-PSRAM feature, to increase PSRAM bandwidth
|
||||||
|
CONFIG_SPIRAM_XIP_FROM_PSRAM=y
|
||||||
@@ -34,6 +34,7 @@ extern "C" {
|
|||||||
*
|
*
|
||||||
* @return linear address
|
* @return linear address
|
||||||
*/
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
static inline uint32_t mmu_ll_vaddr_to_laddr(uint32_t vaddr)
|
static inline uint32_t mmu_ll_vaddr_to_laddr(uint32_t vaddr)
|
||||||
{
|
{
|
||||||
return vaddr & SOC_MMU_LINEAR_ADDR_MASK;
|
return vaddr & SOC_MMU_LINEAR_ADDR_MASK;
|
||||||
|
|||||||
@@ -39,6 +39,26 @@ config SOC_GPTIMER_SUPPORTED
|
|||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
|
|
||||||
|
config SOC_LCDCAM_SUPPORTED
|
||||||
|
bool
|
||||||
|
default y
|
||||||
|
|
||||||
|
config SOC_LCDCAM_I80_LCD_SUPPORTED
|
||||||
|
bool
|
||||||
|
default y
|
||||||
|
|
||||||
|
config SOC_LCDCAM_RGB_LCD_SUPPORTED
|
||||||
|
bool
|
||||||
|
default y
|
||||||
|
|
||||||
|
config SOC_LCD_I80_SUPPORTED
|
||||||
|
bool
|
||||||
|
default y
|
||||||
|
|
||||||
|
config SOC_LCD_RGB_SUPPORTED
|
||||||
|
bool
|
||||||
|
default y
|
||||||
|
|
||||||
config SOC_MCPWM_SUPPORTED
|
config SOC_MCPWM_SUPPORTED
|
||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
|
|||||||
@@ -161,6 +161,23 @@ typedef enum {
|
|||||||
SOC_MOD_CLK_INVALID, /*!< Indication of the end of the available module clock sources */
|
SOC_MOD_CLK_INVALID, /*!< Indication of the end of the available module clock sources */
|
||||||
} soc_module_clk_t;
|
} soc_module_clk_t;
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////LCD///////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Array initializer for all supported clock sources of LCD
|
||||||
|
*/
|
||||||
|
#define SOC_LCD_CLKS {SOC_MOD_CLK_PLL_F160M, SOC_MOD_CLK_XTAL, SOC_MOD_CLK_APLL}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Type of LCD clock source
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
LCD_CLK_SRC_PLL160M = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the source clock */
|
||||||
|
LCD_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */
|
||||||
|
LCD_CLK_SRC_APLL = SOC_MOD_CLK_APLL, /*!< Select APLL as the source clock */
|
||||||
|
LCD_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the default choice */
|
||||||
|
} soc_periph_lcd_clk_src_t;
|
||||||
|
|
||||||
//////////////////////////////////////////////////SYSTIMER//////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////SYSTIMER//////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ extern "C" {
|
|||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
/* HP peripherals */
|
/* HP peripherals */
|
||||||
|
PERIPH_LCD_CAM_MODULE,
|
||||||
PERIPH_TIMG0_MODULE,
|
PERIPH_TIMG0_MODULE,
|
||||||
PERIPH_TIMG1_MODULE,
|
PERIPH_TIMG1_MODULE,
|
||||||
PERIPH_UHCI0_MODULE,
|
PERIPH_UHCI0_MODULE,
|
||||||
|
|||||||
@@ -61,10 +61,9 @@ typedef enum periph_retention_module {
|
|||||||
SLEEP_RETENTION_MODULE_MCPWM1 = 36,
|
SLEEP_RETENTION_MODULE_MCPWM1 = 36,
|
||||||
SLEEP_RETENTION_MODULE_MCPWM2 = 37,
|
SLEEP_RETENTION_MODULE_MCPWM2 = 37,
|
||||||
SLEEP_RETENTION_MODULE_MCPWM3 = 38,
|
SLEEP_RETENTION_MODULE_MCPWM3 = 38,
|
||||||
SLEEP_RETENTION_MODULE_PCNT0 = 39,
|
SLEEP_RETENTION_MODULE_SDM0 = 39,
|
||||||
SLEEP_RETENTION_MODULE_PCNT1 = 40,
|
SLEEP_RETENTION_MODULE_LCDCAM = 40,
|
||||||
SLEEP_RETENTION_MODULE_SDM0 = 41,
|
SLEEP_RETENTION_MODULE_JPEG = 41,
|
||||||
SLEEP_RETENTION_MODULE_JPEG = 42,
|
|
||||||
|
|
||||||
/* Modem module, which includes WiFi, BLE and 802.15.4 */
|
/* Modem module, which includes WiFi, BLE and 802.15.4 */
|
||||||
SLEEP_RETENTION_MODULE_WIFI_MAC = 43,
|
SLEEP_RETENTION_MODULE_WIFI_MAC = 43,
|
||||||
|
|||||||
@@ -35,10 +35,12 @@
|
|||||||
#define SOC_DMA2D_SUPPORTED 1
|
#define SOC_DMA2D_SUPPORTED 1
|
||||||
#define SOC_GPTIMER_SUPPORTED 1
|
#define SOC_GPTIMER_SUPPORTED 1
|
||||||
// #define SOC_PCNT_SUPPORTED 1 // TODO: [ESP32S31] IDF-14699
|
// #define SOC_PCNT_SUPPORTED 1 // TODO: [ESP32S31] IDF-14699
|
||||||
// #define SOC_LCDCAM_SUPPORTED 1 // TODO: [ESP32S31] IDF-14722
|
#define SOC_LCDCAM_SUPPORTED 1
|
||||||
// #define SOC_LCDCAM_CAM_SUPPORTED 1 // TODO: [ESP32S31] IDF-14722
|
// #define SOC_LCDCAM_CAM_SUPPORTED 1 // TODO: [ESP32S31] IDF-14722
|
||||||
// #define SOC_LCDCAM_I80_LCD_SUPPORTED 1 // TODO: [ESP32S31] IDF-14722
|
#define SOC_LCDCAM_I80_LCD_SUPPORTED 1
|
||||||
// #define SOC_LCDCAM_RGB_LCD_SUPPORTED 1 // TODO: [ESP32S31] IDF-14722
|
#define SOC_LCDCAM_RGB_LCD_SUPPORTED 1
|
||||||
|
#define SOC_LCD_I80_SUPPORTED 1
|
||||||
|
#define SOC_LCD_RGB_SUPPORTED 1
|
||||||
#define SOC_MCPWM_SUPPORTED 1
|
#define SOC_MCPWM_SUPPORTED 1
|
||||||
#define SOC_TWAI_SUPPORTED 1
|
#define SOC_TWAI_SUPPORTED 1
|
||||||
#define SOC_TWAI_FD_SUPPORTED 1
|
#define SOC_TWAI_FD_SUPPORTED 1
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
*/
|
*/
|
||||||
@@ -953,7 +953,7 @@ typedef union {
|
|||||||
} lcdcam_lc_reg_date_reg_t;
|
} lcdcam_lc_reg_date_reg_t;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct lcd_cam_dev_t {
|
||||||
volatile lcdcam_lcd_clock_reg_t lcd_clock;
|
volatile lcdcam_lcd_clock_reg_t lcd_clock;
|
||||||
volatile lcdcam_cam_ctrl_reg_t cam_ctrl;
|
volatile lcdcam_cam_ctrl_reg_t cam_ctrl;
|
||||||
volatile lcdcam_cam_ctrl1_reg_t cam_ctrl1;
|
volatile lcdcam_cam_ctrl1_reg_t cam_ctrl1;
|
||||||
@@ -980,11 +980,12 @@ typedef struct {
|
|||||||
volatile lcdcam_lc_dma_int_clr_reg_t lc_dma_int_clr;
|
volatile lcdcam_lc_dma_int_clr_reg_t lc_dma_int_clr;
|
||||||
uint32_t reserved_074[34];
|
uint32_t reserved_074[34];
|
||||||
volatile lcdcam_lc_reg_date_reg_t lc_reg_date;
|
volatile lcdcam_lc_reg_date_reg_t lc_reg_date;
|
||||||
} lcdcam_dev_t;
|
} lcd_cam_dev_t;
|
||||||
|
|
||||||
|
extern lcd_cam_dev_t LCD_CAM;
|
||||||
|
|
||||||
#ifndef __cplusplus
|
#ifndef __cplusplus
|
||||||
_Static_assert(sizeof(lcdcam_dev_t) == 0x100, "Invalid size of lcdcam_dev_t structure");
|
_Static_assert(sizeof(lcd_cam_dev_t) == 0x100, "Invalid size of lcdcam_dev_t structure");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
#define DR_REG_SOC_ETM_BASE 0x20393000
|
#define DR_REG_SOC_ETM_BASE 0x20393000
|
||||||
#define DR_REG_TWAIFD0_BASE 0x20394000
|
#define DR_REG_TWAIFD0_BASE 0x20394000
|
||||||
#define DR_REG_TWAIFD1_BASE 0x20395000
|
#define DR_REG_TWAIFD1_BASE 0x20395000
|
||||||
#define DR_REG_LCD_CAM_BASE 0x20396000
|
#define DR_REG_LCDCAM_BASE 0x20396000
|
||||||
#define DR_REG_UHCI0_BASE 0x20398000
|
#define DR_REG_UHCI0_BASE 0x20398000
|
||||||
#define DR_REG_SYSTIMER_BASE 0x20399000
|
#define DR_REG_SYSTIMER_BASE 0x20399000
|
||||||
#define DR_REG_ZERO_DET_BASE 0x2039A000
|
#define DR_REG_ZERO_DET_BASE 0x2039A000
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
INPUT += \
|
INPUT += \
|
||||||
$(PROJECT_PATH)/components/esp_hal_dma/esp32s31/include/hal/bitscrambler_peri_select.h \
|
$(PROJECT_PATH)/components/esp_hal_dma/esp32s31/include/hal/bitscrambler_peri_select.h \
|
||||||
|
$(PROJECT_PATH)/components/esp_lcd/rgb/include/esp_lcd_panel_rgb.h \
|
||||||
$(PROJECT_PATH)/components/esp_driver_jpeg/include/driver/jpeg_decode.h \
|
$(PROJECT_PATH)/components/esp_driver_jpeg/include/driver/jpeg_decode.h \
|
||||||
$(PROJECT_PATH)/components/esp_driver_jpeg/include/driver/jpeg_encode.h \
|
$(PROJECT_PATH)/components/esp_driver_jpeg/include/driver/jpeg_encode.h \
|
||||||
$(PROJECT_PATH)/components/esp_driver_jpeg/include/driver/jpeg_types.h \
|
$(PROJECT_PATH)/components/esp_driver_jpeg/include/driver/jpeg_types.h \
|
||||||
|
|||||||
@@ -16,6 +16,49 @@ RGB LCD panel is created by :cpp:func:`esp_lcd_new_rgb_panel`, with various conf
|
|||||||
- :cpp:member:`esp_lcd_rgb_panel_config_t::num_fbs` specifies how many frame buffers the driver should allocate. For backward compatibility, setting this to ``0`` will allocate a single frame buffer. If you don't want to allocate any frame buffer, use :cpp:member:`esp_lcd_rgb_panel_config_t::no_fb` instead.
|
- :cpp:member:`esp_lcd_rgb_panel_config_t::num_fbs` specifies how many frame buffers the driver should allocate. For backward compatibility, setting this to ``0`` will allocate a single frame buffer. If you don't want to allocate any frame buffer, use :cpp:member:`esp_lcd_rgb_panel_config_t::no_fb` instead.
|
||||||
- :cpp:member:`esp_lcd_rgb_panel_config_t::no_fb` determines whether frame buffer will be allocated. When it is set, no frame buffer will be allocated. This is also called the :ref:`bounce_buffer_only` mode.
|
- :cpp:member:`esp_lcd_rgb_panel_config_t::no_fb` determines whether frame buffer will be allocated. When it is set, no frame buffer will be allocated. This is also called the :ref:`bounce_buffer_only` mode.
|
||||||
|
|
||||||
|
GPIO Matrix and IOMUX Pins
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
.. only:: esp32s31
|
||||||
|
|
||||||
|
On {IDF_TARGET_NAME}, the RGB LCD driver can use IOMUX automatically when all required signals are mapped to dedicated pins:
|
||||||
|
|
||||||
|
- If ``data_gpio_nums``, ``hsync_gpio_num``, ``vsync_gpio_num``, ``pclk_gpio_num``, and ``de_gpio_num`` all match their dedicated IOMUX pins, the driver bypasses the GPIO matrix automatically.
|
||||||
|
- If any one of these signals does not match the dedicated IOMUX pin, the driver falls back to GPIO matrix routing automatically.
|
||||||
|
|
||||||
|
For higher pixel clock configurations, using IOMUX pins is recommended for better timing robustness.
|
||||||
|
|
||||||
|
Dedicated RGB IOMUX pins on {IDF_TARGET_NAME} are listed below:
|
||||||
|
|
||||||
|
- When ``data_width = 8``, ``DATA[0:7]`` is used
|
||||||
|
- When ``data_width = 16``, ``DATA[0:15]`` is used
|
||||||
|
- When ``data_width = 24``, ``DATA[0:23]`` is used
|
||||||
|
|
||||||
|
.. list-table::
|
||||||
|
:widths: 35 65
|
||||||
|
:header-rows: 1
|
||||||
|
|
||||||
|
* - Signal
|
||||||
|
- GPIO
|
||||||
|
* - DATA[0:7]
|
||||||
|
- 8, 9, 10, 11, 12, 13, 14, 15
|
||||||
|
* - DATA[8:15]
|
||||||
|
- 16, 17, 18, 19, 33, 34, 35, 36
|
||||||
|
* - DATA[16:23]
|
||||||
|
- 37, 38, 39, 2, 3, 4, 5, 7
|
||||||
|
* - HSYNC
|
||||||
|
- 44
|
||||||
|
* - VSYNC
|
||||||
|
- 45
|
||||||
|
* - PCLK
|
||||||
|
- 40
|
||||||
|
* - DE
|
||||||
|
- 43
|
||||||
|
|
||||||
|
.. only:: not esp32s31
|
||||||
|
|
||||||
|
On {IDF_TARGET_NAME}, RGB signals are routed through the GPIO matrix.
|
||||||
|
|
||||||
RGB LCD Frame Buffer Operation Modes
|
RGB LCD Frame Buffer Operation Modes
|
||||||
------------------------------------
|
------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,49 @@ RGB LCD 面板的分配步骤只需一步,即调用函数 :cpp:func:`esp_lcd_n
|
|||||||
- :cpp:member:`esp_lcd_rgb_panel_config_t::num_fbs` 设置由驱动程序分配的 frame buffer 的数量。为了向后兼容,``0`` 表示分配 ``一个`` frame buffer。如果不想分配任何 frame buffer,请设置 :cpp:member:`esp_lcd_rgb_panel_config_t::no_fb`。
|
- :cpp:member:`esp_lcd_rgb_panel_config_t::num_fbs` 设置由驱动程序分配的 frame buffer 的数量。为了向后兼容,``0`` 表示分配 ``一个`` frame buffer。如果不想分配任何 frame buffer,请设置 :cpp:member:`esp_lcd_rgb_panel_config_t::no_fb`。
|
||||||
- :cpp:member:`esp_lcd_rgb_panel_config_t::no_fb` 可决定是否分配 frame buffer。设置该字段后将不分配 frame buffer。这也被称为 :ref:`bounce_buffer_only` 模式。
|
- :cpp:member:`esp_lcd_rgb_panel_config_t::no_fb` 可决定是否分配 frame buffer。设置该字段后将不分配 frame buffer。这也被称为 :ref:`bounce_buffer_only` 模式。
|
||||||
|
|
||||||
|
GPIO 矩阵与 IOMUX 管脚
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
.. only:: esp32s31
|
||||||
|
|
||||||
|
{IDF_TARGET_NAME} 上,RGB LCD 驱动支持在满足专用管脚条件时自动使用 IOMUX,无需额外配置开关:
|
||||||
|
|
||||||
|
- 当 ``data_gpio_nums``、``hsync_gpio_num``、``vsync_gpio_num``、``pclk_gpio_num`` 和 ``de_gpio_num`` 都配置为 RGB 外设的专用 IOMUX 管脚时,驱动会自动绕过 GPIO 矩阵。
|
||||||
|
- 只要上述任一信号未使用专用 IOMUX 管脚,驱动就会自动回退为 GPIO 矩阵路由。
|
||||||
|
|
||||||
|
在较高像素时钟下,建议优先使用 IOMUX 管脚以获得更稳定的时序表现。
|
||||||
|
|
||||||
|
{IDF_TARGET_NAME} 上 RGB 接口可用的专用 IOMUX 管脚如下:
|
||||||
|
|
||||||
|
- 当 ``data_width = 8`` 时,使用 ``DATA[0:7]``
|
||||||
|
- 当 ``data_width = 16`` 时,使用 ``DATA[0:15]``
|
||||||
|
- 当 ``data_width = 24`` 时,使用 ``DATA[0:23]``
|
||||||
|
|
||||||
|
.. list-table::
|
||||||
|
:widths: 35 65
|
||||||
|
:header-rows: 1
|
||||||
|
|
||||||
|
* - 信号
|
||||||
|
- GPIO
|
||||||
|
* - DATA[0:7]
|
||||||
|
- 8, 9, 10, 11, 12, 13, 14, 15
|
||||||
|
* - DATA[8:15]
|
||||||
|
- 16, 17, 18, 19, 33, 34, 35, 36
|
||||||
|
* - DATA[16:23]
|
||||||
|
- 37, 38, 39, 2, 3, 4, 5, 7
|
||||||
|
* - HSYNC
|
||||||
|
- 44
|
||||||
|
* - VSYNC
|
||||||
|
- 45
|
||||||
|
* - PCLK
|
||||||
|
- 40
|
||||||
|
* - DE
|
||||||
|
- 43
|
||||||
|
|
||||||
|
.. only:: not esp32s31
|
||||||
|
|
||||||
|
在 {IDF_TARGET_NAME} 上,RGB 信号通过 GPIO 矩阵路由。
|
||||||
|
|
||||||
RGB LCD frame buffer 操作模式
|
RGB LCD frame buffer 操作模式
|
||||||
------------------------------
|
------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
| Supported Targets | ESP32 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
|
| Supported Targets | ESP32 | ESP32-P4 | ESP32-S2 | ESP32-S3 | ESP32-S31 |
|
||||||
| ----------------- | ----- | -------- | -------- | -------- |
|
| ----------------- | ----- | -------- | -------- | -------- | --------- |
|
||||||
|
|
||||||
# i80 LCD LVGL porting example
|
# i80 LCD LVGL porting example
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
CONFIG_SPIRAM=y
|
||||||
|
CONFIG_SPIRAM_SPEED_250M=y
|
||||||
|
|
||||||
|
# Enabling the following configurations can help increase the PCLK frequency in the case when
|
||||||
|
# the Frame Buffer is allocated from the PSRAM and fetched by EDMA
|
||||||
|
CONFIG_SPIRAM_XIP_FROM_PSRAM=y
|
||||||
|
|
||||||
|
CONFIG_EXAMPLE_PIN_NUM_BK_LIGHT=1
|
||||||
|
CONFIG_EXAMPLE_PIN_NUM_RST=56
|
||||||
|
CONFIG_EXAMPLE_PIN_NUM_CS=2
|
||||||
|
CONFIG_EXAMPLE_PIN_NUM_DC=54
|
||||||
|
CONFIG_EXAMPLE_PIN_NUM_PCLK=5
|
||||||
|
CONFIG_EXAMPLE_PIN_NUM_DATA0=11
|
||||||
|
CONFIG_EXAMPLE_PIN_NUM_DATA1=52
|
||||||
|
CONFIG_EXAMPLE_PIN_NUM_DATA2=8
|
||||||
|
CONFIG_EXAMPLE_PIN_NUM_DATA3=50
|
||||||
|
CONFIG_EXAMPLE_PIN_NUM_DATA4=6
|
||||||
|
CONFIG_EXAMPLE_PIN_NUM_DATA5=48
|
||||||
|
CONFIG_EXAMPLE_PIN_NUM_DATA6=13
|
||||||
|
CONFIG_EXAMPLE_PIN_NUM_DATA7=46
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
| Supported Targets | ESP32-P4 | ESP32-S3 |
|
| Supported Targets | ESP32-P4 | ESP32-S3 | ESP32-S31 |
|
||||||
| ----------------- | -------- | -------- |
|
| ----------------- | -------- | -------- | --------- |
|
||||||
|
|
||||||
# RGB LCD Panel Example
|
# RGB LCD Panel Example
|
||||||
|
|
||||||
|
|||||||
@@ -37,8 +37,8 @@ def test_rgb_lcd_lvgl_esp32s3(dut: Dut) -> None:
|
|||||||
],
|
],
|
||||||
indirect=True,
|
indirect=True,
|
||||||
)
|
)
|
||||||
@idf_parametrize('target', ['esp32p4'], indirect=['target'])
|
@idf_parametrize('target', ['esp32p4', 'esp32s31'], indirect=['target'])
|
||||||
def test_rgb_lcd_lvgl_esp32p4(dut: Dut) -> None:
|
def test_rgb_lcd_lvgl(dut: Dut) -> None:
|
||||||
dut.expect_exact('example: Turn off LCD backlight')
|
dut.expect_exact('example: Turn off LCD backlight')
|
||||||
dut.expect_exact('example: Install RGB LCD panel driver')
|
dut.expect_exact('example: Install RGB LCD panel driver')
|
||||||
dut.expect_exact('example: Initialize RGB LCD panel')
|
dut.expect_exact('example: Initialize RGB LCD panel')
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
CONFIG_SPIRAM=y
|
||||||
|
CONFIG_SPIRAM_SPEED_250M=y
|
||||||
|
|
||||||
|
# LCD_CAM support 24 data lines at most
|
||||||
|
CONFIG_EXAMPLE_LCD_DATA_LINES_24=y
|
||||||
|
CONFIG_LV_COLOR_DEPTH_24=y
|
||||||
|
|
||||||
|
# Enabling the following configurations can help increase the PCLK frequency in the case when
|
||||||
|
# the Frame Buffer is allocated from the PSRAM and fetched by EDMA
|
||||||
|
CONFIG_SPIRAM_XIP_FROM_PSRAM=y
|
||||||
|
|
||||||
|
# Default GPIO assignment
|
||||||
|
CONFIG_EXAMPLE_LCD_VSYNC_GPIO=45
|
||||||
|
CONFIG_EXAMPLE_LCD_HSYNC_GPIO=44
|
||||||
|
CONFIG_EXAMPLE_LCD_DE_GPIO=43
|
||||||
|
CONFIG_EXAMPLE_LCD_PCLK_GPIO=40
|
||||||
|
|
||||||
|
# B0:B7 <=> DATA0:DATA7
|
||||||
|
CONFIG_EXAMPLE_LCD_DATA0_GPIO=8
|
||||||
|
CONFIG_EXAMPLE_LCD_DATA1_GPIO=9
|
||||||
|
CONFIG_EXAMPLE_LCD_DATA2_GPIO=10
|
||||||
|
CONFIG_EXAMPLE_LCD_DATA3_GPIO=11
|
||||||
|
CONFIG_EXAMPLE_LCD_DATA4_GPIO=12
|
||||||
|
CONFIG_EXAMPLE_LCD_DATA5_GPIO=13
|
||||||
|
CONFIG_EXAMPLE_LCD_DATA6_GPIO=14
|
||||||
|
CONFIG_EXAMPLE_LCD_DATA7_GPIO=15
|
||||||
|
|
||||||
|
# G0:G7 <=> DATA8:DATA15
|
||||||
|
CONFIG_EXAMPLE_LCD_DATA8_GPIO=16
|
||||||
|
CONFIG_EXAMPLE_LCD_DATA9_GPIO=17
|
||||||
|
CONFIG_EXAMPLE_LCD_DATA10_GPIO=18
|
||||||
|
CONFIG_EXAMPLE_LCD_DATA11_GPIO=19
|
||||||
|
CONFIG_EXAMPLE_LCD_DATA12_GPIO=33
|
||||||
|
CONFIG_EXAMPLE_LCD_DATA13_GPIO=34
|
||||||
|
CONFIG_EXAMPLE_LCD_DATA14_GPIO=35
|
||||||
|
CONFIG_EXAMPLE_LCD_DATA15_GPIO=36
|
||||||
|
|
||||||
|
# R0:R7 <=> DATA16:DATA23
|
||||||
|
CONFIG_EXAMPLE_LCD_DATA16_GPIO=37
|
||||||
|
CONFIG_EXAMPLE_LCD_DATA17_GPIO=38
|
||||||
|
CONFIG_EXAMPLE_LCD_DATA18_GPIO=39
|
||||||
|
CONFIG_EXAMPLE_LCD_DATA19_GPIO=2
|
||||||
|
CONFIG_EXAMPLE_LCD_DATA20_GPIO=3
|
||||||
|
CONFIG_EXAMPLE_LCD_DATA21_GPIO=4
|
||||||
|
CONFIG_EXAMPLE_LCD_DATA22_GPIO=5
|
||||||
|
CONFIG_EXAMPLE_LCD_DATA23_GPIO=7
|
||||||
Reference in New Issue
Block a user