Merge branch 'camera/add_dvp_example_v5.4' into 'release/v5.4'

P4 DVP example and bugfix (v5.4)

See merge request espressif/esp-idf!39909
This commit is contained in:
morris
2025-07-03 10:44:10 +08:00
32 changed files with 851 additions and 66 deletions

View File

@@ -43,10 +43,12 @@ typedef struct esp_cam_ctlr_dvp_config {
uint32_t bk_buffer_dis : 1; /*!< Disable backup buffer */ uint32_t bk_buffer_dis : 1; /*!< Disable backup buffer */
uint32_t pin_dont_init : 1; /*!< Don't initialize DVP pins if users have called "esp_cam_ctlr_dvp_init" before */ uint32_t pin_dont_init : 1; /*!< Don't initialize DVP pins if users have called "esp_cam_ctlr_dvp_init" before */
uint32_t pic_format_jpeg : 1; /*!< Input picture format is JPEG, if set this flag and "input_data_color_type" will be ignored */ uint32_t pic_format_jpeg : 1; /*!< Input picture format is JPEG, if set this flag and "input_data_color_type" will be ignored */
uint32_t external_xtal : 1; /*!< Using external XTAL, if set, xclk_io and dvp output clock will be ignored */
}; /*!< Boolean Flags */ }; /*!< Boolean Flags */
uint32_t dma_burst_size; /*!< DVP DMA burst transmission block size, set to 0 means to disable the data burst, uint32_t dma_burst_size; /*!< DVP DMA burst transmission block size, set to 0 means to disable the data burst,
other value must be power of 2, e.g., 4/8/16/32/64/128 */ other value must be power of 2, e.g., 4/8/16/32/64/128 */
uint32_t xclk_freq; /*!< DVP output clock frequency in HZ, only valid if `external_xtal` is set to true */
const esp_cam_ctlr_dvp_pin_config_t *pin; /*!< DVP pin configuration, this will be ignored by "esp_cam_new_dvp_ctlr" if "pin_dont_init" is set */ const esp_cam_ctlr_dvp_pin_config_t *pin; /*!< DVP pin configuration, this will be ignored by "esp_cam_new_dvp_ctlr" if "pin_dont_init" is set */
} esp_cam_ctlr_dvp_config_t; } esp_cam_ctlr_dvp_config_t;

View File

@@ -138,7 +138,7 @@ static esp_err_t esp_cam_ctlr_dvp_config_input_gpio(int pin, int signal, bool in
static IRAM_ATTR esp_err_t esp_cam_ctlr_dvp_start_trans(esp_cam_ctlr_dvp_cam_t *ctlr) static IRAM_ATTR esp_err_t esp_cam_ctlr_dvp_start_trans(esp_cam_ctlr_dvp_cam_t *ctlr)
{ {
bool buffer_ready = false; bool buffer_ready = false;
esp_cam_ctlr_trans_t trans; esp_cam_ctlr_trans_t trans = {0};
if (ctlr->cur_buf) { if (ctlr->cur_buf) {
ctlr->cur_buf = NULL; ctlr->cur_buf = NULL;
@@ -146,9 +146,14 @@ static IRAM_ATTR esp_err_t esp_cam_ctlr_dvp_start_trans(esp_cam_ctlr_dvp_cam_t *
ESP_RETURN_ON_ERROR_ISR(esp_cam_ctlr_dvp_dma_stop(&ctlr->dma), TAG, "failed to stop DMA"); ESP_RETURN_ON_ERROR_ISR(esp_cam_ctlr_dvp_dma_stop(&ctlr->dma), TAG, "failed to stop DMA");
} }
if (ctlr->cbs.on_get_new_trans && ctlr->cbs.on_get_new_trans(&(ctlr->base), &trans, ctlr->cbs_user_data)) { if (ctlr->cbs.on_get_new_trans) {
buffer_ready = true; ctlr->cbs.on_get_new_trans(&(ctlr->base), &trans, ctlr->cbs_user_data);
} else if (!ctlr->bk_buffer_dis) { if (trans.buffer) {
buffer_ready = true;
}
}
if (!buffer_ready && !ctlr->bk_buffer_dis) {
trans.buffer = ctlr->backup_buffer; trans.buffer = ctlr->backup_buffer;
trans.buflen = ctlr->fb_size_in_bytes; trans.buflen = ctlr->fb_size_in_bytes;
buffer_ready = true; buffer_ready = true;
@@ -687,6 +692,9 @@ esp_err_t esp_cam_new_dvp_ctlr(const esp_cam_ctlr_dvp_config_t *config, esp_cam_
ESP_RETURN_ON_FALSE(config && ret_handle, ESP_ERR_INVALID_ARG, TAG, "invalid argument: config or ret_handle is null"); ESP_RETURN_ON_FALSE(config && ret_handle, ESP_ERR_INVALID_ARG, TAG, "invalid argument: config or ret_handle is null");
ESP_RETURN_ON_FALSE(config->ctlr_id < CAP_DVP_PERIPH_NUM, ESP_ERR_INVALID_ARG, TAG, "invalid argument: ctlr_id >= %d", CAP_DVP_PERIPH_NUM); ESP_RETURN_ON_FALSE(config->ctlr_id < CAP_DVP_PERIPH_NUM, ESP_ERR_INVALID_ARG, TAG, "invalid argument: ctlr_id >= %d", CAP_DVP_PERIPH_NUM);
ESP_RETURN_ON_FALSE(config->pin_dont_init || config->pin, ESP_ERR_INVALID_ARG, TAG, "invalid argument: pin_dont_init is unset and pin is null"); ESP_RETURN_ON_FALSE(config->pin_dont_init || config->pin, ESP_ERR_INVALID_ARG, TAG, "invalid argument: pin_dont_init is unset and pin is null");
ESP_RETURN_ON_FALSE(config->external_xtal || config->pin_dont_init || config->pin->xclk_io != GPIO_NUM_NC, ESP_ERR_INVALID_ARG, TAG, "invalid argument: xclk_io is not set");
ESP_RETURN_ON_FALSE(config->external_xtal || config->xclk_freq, ESP_ERR_INVALID_ARG, TAG, "invalid argument: xclk_freq is not set");
ESP_RETURN_ON_ERROR(esp_cache_get_alignment(MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA, &alignment_size), TAG, "failed to get cache alignment"); ESP_RETURN_ON_ERROR(esp_cache_get_alignment(MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA, &alignment_size), TAG, "failed to get cache alignment");
ESP_RETURN_ON_ERROR(esp_cam_ctlr_dvp_cam_get_frame_size(config, &fb_size_in_bytes), TAG, "invalid argument: input frame pixel format is not supported"); ESP_RETURN_ON_ERROR(esp_cam_ctlr_dvp_cam_get_frame_size(config, &fb_size_in_bytes), TAG, "invalid argument: input frame pixel format is not supported");
ESP_RETURN_ON_ERROR(dvp_shared_ctrl_claim_io_signals(), TAG, "failed to claim io signals"); ESP_RETURN_ON_ERROR(dvp_shared_ctrl_claim_io_signals(), TAG, "failed to claim io signals");
@@ -719,13 +727,21 @@ esp_err_t esp_cam_new_dvp_ctlr(const esp_cam_ctlr_dvp_config_t *config, esp_cam_
.port = config->ctlr_id, .port = config->ctlr_id,
.byte_swap_en = config->byte_swap_en, .byte_swap_en = config->byte_swap_en,
}; };
cam_hal_init(&ctlr->hal, &cam_hal_config);
if (!config->pin_dont_init) { if (!config->pin_dont_init) {
// Initialzie DVP clock and GPIO internally
ESP_GOTO_ON_ERROR(esp_cam_ctlr_dvp_init(config->ctlr_id, config->clk_src, config->pin), ESP_GOTO_ON_ERROR(esp_cam_ctlr_dvp_init(config->ctlr_id, config->clk_src, config->pin),
fail5, TAG, "failed to initialize clock and GPIO"); fail5, TAG, "failed to initialize clock and GPIO");
} }
if (!config->external_xtal) {
// Generate DVP xtal clock internally
ESP_GOTO_ON_ERROR(esp_cam_ctlr_dvp_output_clock(config->ctlr_id, config->clk_src, config->xclk_freq),
fail5, TAG, "failed to generate xtal clock");
}
cam_hal_init(&ctlr->hal, &cam_hal_config);
ctlr->ctlr_id = config->ctlr_id; ctlr->ctlr_id = config->ctlr_id;
ctlr->fb_size_in_bytes = fb_size_in_bytes; ctlr->fb_size_in_bytes = fb_size_in_bytes;
ctlr->dvp_fsm = ESP_CAM_CTLR_DVP_CAM_FSM_INIT; ctlr->dvp_fsm = ESP_CAM_CTLR_DVP_CAM_FSM_INIT;

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -28,9 +28,9 @@ typedef struct {
int de_io; ///< ISP DVP de IO numbers int de_io; ///< ISP DVP de IO numbers
struct { struct {
uint32_t pclk_invert: 1; ///< The pclk is inverted uint32_t pclk_invert: 1; ///< The pclk is inverted
uint32_t hsync_invert: 1; ///< The hsync signal is inverted uint32_t hsync_invert: 1; ///< The hsync signal is inverted (i.e. active low)
uint32_t vsync_invert: 1; ///< The vsync signal is inverted uint32_t vsync_invert: 1; ///< The vsync signal is inverted (i.e. active high)
uint32_t de_invert: 1; ///< The de signal is inverted uint32_t de_invert: 1; ///< The de signal is inverted (i.e. active low)
} io_flags; ///< ISP DVP IO flags } io_flags; ///< ISP DVP IO flags
int queue_items; ///< Queue items int queue_items; ///< Queue items
struct { struct {

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -20,6 +20,7 @@ TEST_CASE("TEST DVP driver allocation", "[DVP]")
.dma_burst_size = 128, .dma_burst_size = 128,
.byte_swap_en = false, .byte_swap_en = false,
.pin_dont_init = true, .pin_dont_init = true,
.external_xtal = true,
}; };
esp_cam_ctlr_handle_t handle = NULL; esp_cam_ctlr_handle_t handle = NULL;
TEST_ESP_OK(esp_cam_new_dvp_ctlr(&dvp_config, &handle)); TEST_ESP_OK(esp_cam_new_dvp_ctlr(&dvp_config, &handle));
@@ -45,6 +46,7 @@ TEST_CASE("TEST DVP driver allocation with JPEG input", "[DVP]")
.byte_swap_en = false, .byte_swap_en = false,
.pin_dont_init = true, .pin_dont_init = true,
.pic_format_jpeg = true, .pic_format_jpeg = true,
.external_xtal = true,
}; };
esp_cam_ctlr_handle_t handle = NULL; esp_cam_ctlr_handle_t handle = NULL;
TEST_ESP_OK(esp_cam_new_dvp_ctlr(&dvp_config, &handle)); TEST_ESP_OK(esp_cam_new_dvp_ctlr(&dvp_config, &handle));
@@ -71,6 +73,7 @@ TEST_CASE("TEST DVP driver no backup buffer usage", "[DVP]")
.byte_swap_en = false, .byte_swap_en = false,
.bk_buffer_dis = true, .bk_buffer_dis = true,
.pin_dont_init = true, .pin_dont_init = true,
.external_xtal = true,
}; };
esp_cam_ctlr_handle_t handle = NULL; esp_cam_ctlr_handle_t handle = NULL;
TEST_ESP_OK(esp_cam_new_dvp_ctlr(&dvp_config, &handle)); TEST_ESP_OK(esp_cam_new_dvp_ctlr(&dvp_config, &handle));
@@ -84,3 +87,87 @@ TEST_CASE("TEST DVP driver no backup buffer usage", "[DVP]")
TEST_ASSERT_EQUAL((dvp_config.h_res * dvp_config.v_res * 2), bk_buffer_len); // out type RGB565 using 2 byte / pixel TEST_ASSERT_EQUAL((dvp_config.h_res * dvp_config.v_res * 2), bk_buffer_len); // out type RGB565 using 2 byte / pixel
TEST_ESP_OK(esp_cam_ctlr_del(handle)); TEST_ESP_OK(esp_cam_ctlr_del(handle));
} }
TEST_CASE("TEST DVP driver intern/extern init", "[DVP]")
{
esp_cam_ctlr_dvp_config_t dvp_config = {
.ctlr_id = 0,
.clk_src = CAM_CLK_SRC_DEFAULT,
.h_res = 800,
.v_res = 640,
.input_data_color_type = CAM_CTLR_COLOR_RGB565,
.dma_burst_size = 128,
.byte_swap_en = false,
.external_xtal = true,
};
esp_cam_ctlr_handle_t handle = NULL;
//Init externally, do not check pin
dvp_config.pin_dont_init = true;
TEST_ESP_OK(esp_cam_new_dvp_ctlr(&dvp_config, &handle));
TEST_ESP_OK(esp_cam_ctlr_del(handle));
//Init internally but not set pin
dvp_config.pin_dont_init = false;
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_cam_new_dvp_ctlr(&dvp_config, &handle));
//Init internally and set pin
esp_cam_ctlr_dvp_pin_config_t pin_cfg = {
.data_width = 8,
};
dvp_config.pin = &pin_cfg;
TEST_ESP_OK(esp_cam_new_dvp_ctlr(&dvp_config, &handle));
TEST_ESP_OK(esp_cam_ctlr_del(handle));
}
TEST_CASE("TEST DVP driver intern/extern generate xclk", "[DVP]")
{
esp_cam_ctlr_dvp_config_t dvp_config = {
.ctlr_id = 0,
.clk_src = CAM_CLK_SRC_DEFAULT,
.h_res = 800,
.v_res = 640,
.input_data_color_type = CAM_CTLR_COLOR_RGB565,
.dma_burst_size = 128,
.byte_swap_en = false,
.external_xtal = true,
};
esp_cam_ctlr_handle_t handle = NULL;
//Init externally, generate xclk externally, check nothing
dvp_config.pin_dont_init = true;
dvp_config.external_xtal = true;
TEST_ESP_OK(esp_cam_new_dvp_ctlr(&dvp_config, &handle));
TEST_ESP_OK(esp_cam_ctlr_del(handle));
//Init externally, generate xclk internally, do not check pin, check xclk_freq
dvp_config.pin_dont_init = true;
dvp_config.external_xtal = false;
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_cam_new_dvp_ctlr(&dvp_config, &handle));
dvp_config.xclk_freq = 20000000;
TEST_ESP_OK(esp_cam_new_dvp_ctlr(&dvp_config, &handle));
TEST_ESP_OK(esp_cam_ctlr_del(handle));
esp_cam_ctlr_dvp_pin_config_t pin_cfg = {
.data_width = 8,
.xclk_io = GPIO_NUM_NC,
};
//Init internally, generate xclk externally, check nothing
dvp_config.pin = &pin_cfg;
dvp_config.pin_dont_init = false;
dvp_config.external_xtal = true;
TEST_ESP_OK(esp_cam_new_dvp_ctlr(&dvp_config, &handle));
TEST_ESP_OK(esp_cam_ctlr_del(handle));
//Init internally, generate xclk internally, check xclk_io and xclk_freq
dvp_config.pin = &pin_cfg;
dvp_config.pin_dont_init = false;
dvp_config.external_xtal = false;
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_cam_new_dvp_ctlr(&dvp_config, &handle));
pin_cfg.xclk_io = 20;
dvp_config.pin = &pin_cfg;
TEST_ESP_OK(esp_cam_new_dvp_ctlr(&dvp_config, &handle));
TEST_ESP_OK(esp_cam_ctlr_del(handle));
}

View File

@@ -10,8 +10,9 @@ Introduction
.. list:: .. list::
: SOC_MIPI_CSI_SUPPORTED : - MIPI Camera Serial Interface (CSI) : SOC_MIPI_CSI_SUPPORTED : - MIPI Camera Serial Interface (MIPI CSI)
: SOC_ISP_DVP_SUPPORTED : - ISP Digital Video Port (ISP DVP) : SOC_ISP_DVP_SUPPORTED : - Digital Video Port through ISP module (ISP DVP)
: SOC_LCDCAM_CAM_SUPPORTED : - Digital Video Port through LCD_CAM module(LCD_CAM DVP)
The camera controller driver is designed for this hardware peripheral. The camera controller driver is designed for this hardware peripheral.
@@ -38,6 +39,14 @@ Resource Allocation
Install Camera Controller Driver Install Camera Controller Driver
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Camera controller driver can be implemented in one of following ways:
.. list::
: SOC_MIPI_CSI_SUPPORTED : - :cpp:func:`esp_cam_new_csi_ctlr`
: SOC_ISP_DVP_SUPPORTED : - :cpp:func:`esp_cam_new_isp_dvp_ctlr`
: SOC_LCDCAM_CAM_SUPPORTED : - :cpp:func:`esp_cam_new_lcd_cam_ctlr`
.. only:: SOC_MIPI_CSI_SUPPORTED .. only:: SOC_MIPI_CSI_SUPPORTED
A camera controller driver can be implemented by the CSI peripheral, which requires the configuration that specified by :cpp:type:`esp_cam_ctlr_csi_config_t`. A camera controller driver can be implemented by the CSI peripheral, which requires the configuration that specified by :cpp:type:`esp_cam_ctlr_csi_config_t`.
@@ -95,6 +104,48 @@ Install Camera Controller Driver
}; };
ESP_ERROR_CHECK(esp_cam_new_isp_dvp_ctlr(isp_proc, &dvp_ctlr_config, &cam_handle)); ESP_ERROR_CHECK(esp_cam_new_isp_dvp_ctlr(isp_proc, &dvp_ctlr_config, &cam_handle));
.. only:: SOC_LCDCAM_CAM_SUPPORTED
A camera controller driver can be implemented by the DVP port of LCD_CAM, which requires the configuration that specified by :cpp:type:`esp_cam_ctlr_dvp_config_t`.
:cpp:member:`esp_cam_ctlr_dvp_config_t::exexternal_xtal`: set this to use externally generated xclk, otherwise the camera driver will generate it internally.
If :cpp:type:`esp_cam_ctlr_lcd_cam_cfg_t` is specified, users can call :cpp:func:`esp_cam_new_lcd_cam_ctlr` to allocate and initialize a DVP camera controller handle. This function will return an DVP camera controller handle if it runs correctly. You can take following code as reference.
.. code:: c
esp_cam_ctlr_handle_t cam_handle = NULL;
esp_cam_ctlr_dvp_pin_config_t pin_cfg = {
.data_width = EXAMPLE_DVP_CAM_DATA_WIDTH,
.data_io = {
EXAMPLE_DVP_CAM_D0_IO,
EXAMPLE_DVP_CAM_D1_IO,
EXAMPLE_DVP_CAM_D2_IO,
EXAMPLE_DVP_CAM_D3_IO,
EXAMPLE_DVP_CAM_D4_IO,
EXAMPLE_DVP_CAM_D5_IO,
EXAMPLE_DVP_CAM_D6_IO,
EXAMPLE_DVP_CAM_D7_IO,
},
.vsync_io = EXAMPLE_DVP_CAM_VSYNC_IO,
.de_io = EXAMPLE_DVP_CAM_DE_IO,
.pclk_io = EXAMPLE_DVP_CAM_PCLK_IO,
.xclk_io = EXAMPLE_DVP_CAM_XCLK_IO, // Set XCLK pin to generate XCLK signal
};
esp_cam_ctlr_dvp_config_t dvp_config = {
.ctlr_id = 0,
.clk_src = CAM_CLK_SRC_DEFAULT,
.h_res = CONFIG_EXAMPLE_CAM_HRES,
.v_res = CONFIG_EXAMPLE_CAM_VRES,
.input_data_color_type = CAM_CTLR_COLOR_RGB565,
.dma_burst_size = 128,
.pin = &pin_cfg,
.bk_buffer_dis = 1,
.xclk_freq = EXAMPLE_DVP_CAM_XCLK_FREQ_HZ,
};
ESP_ERROR_CHECK(esp_cam_new_dvp_ctlr(&dvp_config, &cam_handle));
Uninstall Camera Controller Driver Uninstall Camera Controller Driver
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@@ -10,8 +10,9 @@
.. list:: .. list::
: SOC_MIPI_CSI_SUPPORTED : - MIPI 摄像头串行接口 (CSI) : SOC_MIPI_CSI_SUPPORTED : - MIPI 摄像头串行接口 (MIPI CSI)
: SOC_ISP_DVP_SUPPORTED : - ISP 数字视频端口 (ISP DVP) : SOC_ISP_DVP_SUPPORTED : - ISP的DVP端口 (ISP DVP)
: SOC_LCDCAM_CAM_SUPPORTED : - LCD_CAM的DVP端口 (LCD_CAM DVP)
摄像头控制器驱动程序是为上述硬件外设而设计的。 摄像头控制器驱动程序是为上述硬件外设而设计的。
@@ -38,6 +39,14 @@
安装摄像头控制器驱动程序 安装摄像头控制器驱动程序
~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~
摄像头控制器驱动程序可以通过以下方式之一安装:
.. list::
: SOC_MIPI_CSI_SUPPORTED : - :cpp:func:`esp_cam_new_csi_ctlr`
: SOC_ISP_DVP_SUPPORTED : - :cpp:func:`esp_cam_new_isp_dvp_ctlr`
: SOC_LCDCAM_CAM_SUPPORTED : - :cpp:func:`esp_cam_new_lcd_cam_ctlr`
.. only:: SOC_MIPI_CSI_SUPPORTED .. only:: SOC_MIPI_CSI_SUPPORTED
摄像头控制器驱动程序可以通过 CSI 外设实现,需要应用 :cpp:type:`esp_cam_ctlr_csi_config_t` 指定的配置。 摄像头控制器驱动程序可以通过 CSI 外设实现,需要应用 :cpp:type:`esp_cam_ctlr_csi_config_t` 指定的配置。
@@ -95,6 +104,48 @@
}; };
ESP_ERROR_CHECK(esp_cam_new_isp_dvp_ctlr(isp_proc, &dvp_ctlr_config, &cam_handle)); ESP_ERROR_CHECK(esp_cam_new_isp_dvp_ctlr(isp_proc, &dvp_ctlr_config, &cam_handle));
.. only:: SOC_LCDCAM_CAM_SUPPORTED
摄像头控制器驱动程序可以通过 LCD_CAM外设实现需要应用 :cpp:type:`esp_cam_ctlr_dvp_config_t`:cpp:type:`esp_cam_ctlr_dvp_pin_config_t` 指定的配置。
:cpp:member:`esp_cam_ctlr_dvp_config_t::exexternal_xtal`:使用外部生成的 xclk或者使用驱动内部内部生成的 xclk。
如果指定了 :cpp:type:`esp_cam_ctlr_dvp_config_t` 中的配置,就可以调用 :cpp:func:`esp_cam_new_dvp_ctlr` 来分配和初始化 DVP 摄像头控制器句柄。如果函数运行正确,将返回一个 DVP 摄像头控制器句柄。请参考以下代码。
.. code:: c
esp_cam_ctlr_handle_t cam_handle = NULL;
esp_cam_ctlr_dvp_pin_config_t pin_cfg = {
.data_width = EXAMPLE_DVP_CAM_DATA_WIDTH,
.data_io = {
EXAMPLE_DVP_CAM_D0_IO,
EXAMPLE_DVP_CAM_D1_IO,
EXAMPLE_DVP_CAM_D2_IO,
EXAMPLE_DVP_CAM_D3_IO,
EXAMPLE_DVP_CAM_D4_IO,
EXAMPLE_DVP_CAM_D5_IO,
EXAMPLE_DVP_CAM_D6_IO,
EXAMPLE_DVP_CAM_D7_IO,
},
.vsync_io = EXAMPLE_DVP_CAM_VSYNC_IO,
.de_io = EXAMPLE_DVP_CAM_DE_IO,
.pclk_io = EXAMPLE_DVP_CAM_PCLK_IO,
.xclk_io = EXAMPLE_DVP_CAM_XCLK_IO, // Set XCLK pin to generate XCLK signal
};
esp_cam_ctlr_dvp_config_t dvp_config = {
.ctlr_id = 0,
.clk_src = CAM_CLK_SRC_DEFAULT,
.h_res = CONFIG_EXAMPLE_CAM_HRES,
.v_res = CONFIG_EXAMPLE_CAM_VRES,
.input_data_color_type = CAM_CTLR_COLOR_RGB565,
.dma_burst_size = 128,
.pin = &pin_cfg,
.bk_buffer_dis = 1,
.xclk_freq = EXAMPLE_DVP_CAM_XCLK_FREQ_HZ,
};
ESP_ERROR_CHECK(esp_cam_new_dvp_ctlr(&dvp_config, &cam_handle));
卸载摄像头控制器驱动程序 卸载摄像头控制器驱动程序
~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~

View File

@@ -32,6 +32,13 @@ examples/peripherals/analog_comparator:
- esp_driver_gpio - esp_driver_gpio
- esp_driver_ana_cmpr - esp_driver_ana_cmpr
examples/peripherals/camera/dvp_dsi:
disable:
- if: SOC_LCDCAM_CAM_SUPPORTED != 1 or SOC_MIPI_DSI_SUPPORTED != 1
depends_components:
- esp_lcd
- esp_driver_cam
examples/peripherals/camera/dvp_isp_dsi: examples/peripherals/camera/dvp_isp_dsi:
disable: disable:
- if: SOC_ISP_DVP_SUPPORTED != 1 or SOC_MIPI_DSI_SUPPORTED != 1 - if: SOC_ISP_DVP_SUPPORTED != 1 or SOC_MIPI_DSI_SUPPORTED != 1

View File

@@ -45,4 +45,11 @@ menu "Example DSI Configuration"
int int
default 600 if EXAMPLE_MIPI_DSI_DISP_VRES_600 default 600 if EXAMPLE_MIPI_DSI_DISP_VRES_600
default 1280 if EXAMPLE_MIPI_DSI_DISP_VRES_1280 default 1280 if EXAMPLE_MIPI_DSI_DISP_VRES_1280
config EXAMPLE_MIPI_DSI_DISP_USE_DMA2D
bool "Use DMA2D to copy data to frame buffer"
default n
help
Enable this option, DMA2D will be used to copy data to the target frame buffer.
This can save some CPU time and improve the performance.
endmenu endmenu

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -13,6 +13,7 @@
#include "esp_lcd_ek79007.h" #include "esp_lcd_ek79007.h"
#include "example_dsi_init.h" #include "example_dsi_init.h"
#include "example_dsi_init_config.h" #include "example_dsi_init_config.h"
#include "sdkconfig.h"
void example_dsi_resource_alloc(esp_lcd_dsi_bus_handle_t *mipi_dsi_bus, esp_lcd_panel_io_handle_t *mipi_dbi_io, esp_lcd_panel_handle_t *mipi_dpi_panel, void **frame_buffer) void example_dsi_resource_alloc(esp_lcd_dsi_bus_handle_t *mipi_dsi_bus, esp_lcd_panel_io_handle_t *mipi_dbi_io, esp_lcd_panel_handle_t *mipi_dpi_panel, void **frame_buffer)
{ {
@@ -47,6 +48,9 @@ void example_dsi_resource_alloc(esp_lcd_dsi_bus_handle_t *mipi_dsi_bus, esp_lcd_
.vsync_pulse_width = EXAMPLE_MIPI_DSI_IMAGE_VSYNC, .vsync_pulse_width = EXAMPLE_MIPI_DSI_IMAGE_VSYNC,
.vsync_front_porch = EXAMPLE_MIPI_DSI_IMAGE_VFP, .vsync_front_porch = EXAMPLE_MIPI_DSI_IMAGE_VFP,
}, },
#if CONFIG_EXAMPLE_MIPI_DSI_DISP_USE_DMA2D
.flags.use_dma2d = true,
#endif
}; };
#if CONFIG_EXAMPLE_LCD_PATTERN_ILI9881C #if CONFIG_EXAMPLE_LCD_PATTERN_ILI9881C

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -19,7 +19,7 @@
static const char *TAG = "sensor_init"; static const char *TAG = "sensor_init";
void example_sensor_init(example_sensor_config_t *sensor_config, i2c_master_bus_handle_t *out_i2c_bus_handle) void example_sensor_init(example_sensor_config_t *sensor_config, example_sensor_handle_t *out_sensor_handle)
{ {
esp_err_t ret = ESP_FAIL; esp_err_t ret = ESP_FAIL;
@@ -81,6 +81,10 @@ void example_sensor_init(example_sensor_config_t *sensor_config, i2c_master_bus_
cam_cur_fmt = (esp_cam_sensor_format_t *) & (parray[i]); cam_cur_fmt = (esp_cam_sensor_format_t *) & (parray[i]);
} }
} }
if (!cam_cur_fmt) {
ESP_LOGE(TAG, "Unsupported format");
ESP_ERROR_CHECK(ESP_ERR_INVALID_ARG);
}
ret = esp_cam_sensor_set_format(cam, (const esp_cam_sensor_format_t *) cam_cur_fmt); ret = esp_cam_sensor_set_format(cam, (const esp_cam_sensor_format_t *) cam_cur_fmt);
if (ret != ESP_OK) { if (ret != ESP_OK) {
@@ -95,6 +99,12 @@ void example_sensor_init(example_sensor_config_t *sensor_config, i2c_master_bus_
ESP_LOGE(TAG, "Start stream fail"); ESP_LOGE(TAG, "Start stream fail");
} }
ESP_ERROR_CHECK(ret); ESP_ERROR_CHECK(ret);
out_sensor_handle->i2c_bus_handle = i2c_bus_handle;
*out_i2c_bus_handle = i2c_bus_handle; out_sensor_handle->sccb_handle = cam_config.sccb_handle;
}
void example_sensor_deinit(example_sensor_handle_t sensor_handle)
{
ESP_ERROR_CHECK(esp_sccb_del_i2c_io(sensor_handle.sccb_handle));
ESP_ERROR_CHECK(i2c_del_master_bus(sensor_handle.i2c_bus_handle));
} }

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -13,6 +13,14 @@
extern "C" { extern "C" {
#endif #endif
/**
* @brief Handle of SCCB interface and sensor
*/
typedef struct {
esp_sccb_io_handle_t sccb_handle; /*!< SCCB io handle that created by `sccb_new_i2c_io` */
i2c_master_bus_handle_t i2c_bus_handle; /*!< I2C bus handle that created by `i2c_new_master_bus` */
} example_sensor_handle_t;
/** /**
* @brief Configuration of SCCB interface and sensor * @brief Configuration of SCCB interface and sensor
*/ */
@@ -28,9 +36,16 @@ typedef struct {
* @brief SCCB Interface and Sensor Init * @brief SCCB Interface and Sensor Init
* *
* @param[in] sensor_config Camera sensor configuration * @param[in] sensor_config Camera sensor configuration
* @param[out] out_i2c_bus_handle I2C bus handle * @param[out] out_sensor_handle Camera sensor handle
*/ */
void example_sensor_init(example_sensor_config_t *sensor_config, i2c_master_bus_handle_t *out_i2c_bus_handle); void example_sensor_init(example_sensor_config_t *sensor_config, example_sensor_handle_t *out_sensor_handle);
/**
* @brief SCCB Interface and Sensor Deinit
*
* @param[in] out_sensor_handle Camera sensor handle
*/
void example_sensor_deinit(example_sensor_handle_t sensor_handle);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -10,7 +10,7 @@
extern "C" { extern "C" {
#endif #endif
#define EXAMPLE_CAM_SCCB_FREQ (100000) #define EXAMPLE_CAM_SCCB_FREQ (10 * 1000)
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -0,0 +1,8 @@
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
# "Trim" the build. Include the minimal set of components, main, and anything it depends on.
idf_build_set_property(MINIMAL_BUILD ON)
project(dvp_dsi)

View File

@@ -0,0 +1,156 @@
| Supported Targets | ESP32-P4 |
| ----------------- | -------- |
# DVP Camera display via DSI example
## Overview
This example demonstrates how to use the esp_driver_cam component to capture DVP camera sensor signals and display it via DSI interface. This example will auto-detect camera sensors via [ESP camera sensor driver](https://components.espressif.com/components/espressif/esp_cam_sensor) and capture camera sensor signals via DVP interface and display it via DSI interface.
## Usage
The subsections below give only absolutely necessary information. For full steps to configure ESP-IDF and use it to build and run projects, see [ESP-IDF Getting Started](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html#get-started).
### Hardware Required
- OV2640 camera sensor, or other camera sensors with DVP port that can output RGB565 format color data
- EK79007 LCD screen
- ESP32P4 devkit
**Note:** For EK79007 you will need to connect following pins:
- 5V - 5V
- GND - GND
- RST_LCD - 3V3
You can also connect camera sensors and LCD screens from other vendors to the ESP chip, you can find corresponding camera or LCD drivers from [ESP Component Registry](https://components.espressif.com), or design your own customized drivers.
GND GND
┌────────────────────────────────────────────────┐ ┌─────────────────────────────────────────────────────────┐
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
│ ┌───────────────┴─────────────┴──────────────────┐ │
│ │ │ ┌──────────┴───────────┐
│ │ │ DSI DATA 1P │ │
│ │ ├───────────────────────────┤ │
┌───────────┴─────────┐ │ │ │ │
│ │ │ │ DSI DATA 1N │ │
│ │ │ ├───────────────────────────┤ │
│ │ XCLK │ ESP32-P4 │ │ │
│ DVP Camera ├──────────────────────┤ │ DSI CLK N │ LCD Screen │
│ │ │ ├───────────────────────────┤ │
│ │ D0~7 │ │ │ │
│ ├──────────────────────┤ │ DSI CLK P │ │
│ │ │ ├───────────────────────────┤ │
│ │ PCLK │ │ │ │
│ ├──────────────────────┤ │ DSI DATA 0P │ │
│ │ │ ├───────────────────────────┤ │
│ │ VSYNC │ │ │ │
│ ├──────────────────────┤ │ DSI DATA 0N │ │
│ │ │ ├───────────────────────────┤ │
│ │ DE (HREF) │ │ │ │
│ ├──────────────────────┤ │ └──────────────────────┘
│ │ │ │
└───────┬──┬──────────┘ │ │
│ │ I2C SCL │ │
│ └─────────────────────────────────┤ │
│ I2C SDA │ │
└────────────────────────────────────┤ │
└────────────────────────────────────────────────┘
### Set Chip Target
First of all, your target must be supported by both:
- **By your ESP-IDF version**: For the full list of supported targets, run:
```
idf.py --list-targets
```
- **By this example**: For the full list of supported targets, refer to the supported targets table at the top of this README.
After you make sure that your target is supported, go to your example project directory and [set the chip target](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/tools/idf-py.html#select-the-target-chip-set-target):
```
idf.py set-target <target>
```
For example, to set esp32-P4 as the chip target, run:
```
idf.py set-target esp32p4
```
### Configure the Project
For information about Kconfig options, see [Project Configuration](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/kconfig.html) > _Name of relevant section(s)_.
To conveniently check or modify Kconfig options for this example in a project configuration menu, run:
```
idf.py menuconfig
```
```
Set CONFIG_CAMERA_OV2640 to y
```
Remember to select the LCD screen model and set corresponding correct horizontal/vertical resolution in ``menuconfig`` > ``Example DSI Configuration``.
Available options for the camera sensor output horizontal/vertical resolution can be seen in ``menuconfig`` > ``Example Configuration``.
### Build and Flash
Execute the following command to build the project, flash it to your development board, and run the monitor tool to view the serial output:
```
idf.py build flash monitor
```
This command can be reduced to `idf.py flash monitor`.
If the above command fails, check the log on the serial monitor which usually provides information on the possible cause of the issue.
To exit the serial monitor, use `Ctrl` + `]`.
## Example Output
If you see the following console output, your example should be running correctly:
```
I (1481) main_task: Calling app_main()
I (1481) ek79007: version: 1.0.2
I (1701) ov2640: Detected Camera sensor PID=0x26
I (1701) sensor_init: fmt[0].name:DVP_8bit_20Minput_RGB565_640x480_6fps
I (1701) sensor_init: fmt[1].name:DVP_8bit_20Minput_YUV422_640x480_6fps
I (1711) sensor_init: fmt[2].name:DVP_8bit_20Minput_JPEG_640x480_25fps
I (1711) sensor_init: fmt[3].name:DVP_8bit_20Minput_RGB565_240x240_25fps
I (1721) sensor_init: fmt[4].name:DVP_8bit_20Minput_YUV422_240x240_25fps
I (1721) sensor_init: fmt[5].name:DVP_8bit_20Minput_JPEG_320x240_50fps
I (1731) sensor_init: fmt[6].name:DVP_8bit_20Minput_JPEG_1280x720_12fps
I (1741) sensor_init: fmt[7].name:DVP_8bit_20Minput_JPEG_1600x1200_12fps
I (1741) sensor_init: fmt[8].name:DVP_8bit_20Minput_RAW8_800x640_30fps
I (1751) sensor_init: fmt[9].name:DVP_8bit_20Minput_RAW8_800x640_15fps
I (1761) sensor_init: fmt[10].name:DVP_8bit_20Minput_RAW8_800x800_15fps
I (1761) sensor_init: fmt[11].name:DVP_8bit_20Minput_RAW8_1024x600_15fps
I (8291) sensor_init: Format in use:DVP_8bit_20Minput_RGB565_640x480_6fps
```
## Reference
- Link to the ESP-IDF feature's API reference, for example [ESP-IDF: Camera Controller Driver](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/camera_driver.html)
- [ESP-IDF Getting Started](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html#get-started)
- [Project Configuration](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/kconfig.html) (Kconfig Options)

View File

@@ -0,0 +1,4 @@
idf_component_register(SRCS "dvp_dsi_main.c"
INCLUDE_DIRS "."
REQUIRES esp_mm esp_driver_cam esp_driver_i2c dsi_init sensor_init
)

View File

@@ -0,0 +1,45 @@
menu "Example Configuration"
config EXAMPLE_USED_LDO_CHAN_ID
int "Occupied channel ID of the LDO to power on the MIPI DSI PHY"
default 3
help
Example used LDO channel ID, you may check datasheet to know more details.
config EXAMPLE_USED_LDO_VOLTAGE_MV
int "Occupied LDO voltage in mV"
default 2500
range 0 3300
help
Example used LDO voltage, in mV
choice EXAMPLE_CAM_HRES
bool "Set camera horizontal resolution"
default EXAMPLE_CAM_HRES_640
config EXAMPLE_CAM_HRES_640
bool "640"
config EXAMPLE_CAM_HRES_240
bool "240"
endchoice
config EXAMPLE_CAM_HRES
int
default 640 if EXAMPLE_CAM_HRES_640
default 240 if EXAMPLE_CAM_HRES_240
choice EXAMPLE_CAM_VRES
bool "Set camera vertical resolution"
default EXAMPLE_CAM_VRES_480 if EXAMPLE_CAM_HRES_640
default EXAMPLE_CAM_VRES_240 if EXAMPLE_CAM_HRES_240
config EXAMPLE_CAM_VRES_480
bool "480"
config EXAMPLE_CAM_VRES_240
bool "240"
endchoice
config EXAMPLE_CAM_VRES
int
default 480 if EXAMPLE_CAM_VRES_480
default 240 if EXAMPLE_CAM_VRES_240
endmenu

View File

@@ -0,0 +1,184 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sdkconfig.h"
#include "esp_attr.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "esp_lcd_mipi_dsi.h"
#include "esp_lcd_panel_ops.h"
#include "esp_ldo_regulator.h"
#include "esp_cache.h"
#include "driver/i2c_master.h"
#include "esp_cam_ctlr.h"
#include "esp_cam_ctlr_dvp.h"
#include "example_dsi_init.h"
#include "example_dsi_init_config.h"
#include "example_sensor_init.h"
#include "example_config.h"
static const char *TAG = "dvp_dsi";
typedef struct {
esp_lcd_panel_handle_t panel_hdl;
void *cam_buf;
} display_update_param_t;
static bool s_camera_get_new_vb(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data);
static bool s_camera_get_finished_trans(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data);
static bool example_display_update_ready(esp_lcd_panel_handle_t panel, esp_lcd_dpi_panel_event_data_t *edata, void *user_ctx)
{
display_update_param_t *param = (display_update_param_t *)user_ctx;
esp_lcd_panel_draw_bitmap(param->panel_hdl, 0, 0, CONFIG_EXAMPLE_CAM_HRES, CONFIG_EXAMPLE_CAM_VRES, param->cam_buf);
return false;
}
void app_main(void)
{
esp_err_t ret = ESP_FAIL;
esp_lcd_dsi_bus_handle_t mipi_dsi_bus = NULL;
esp_lcd_panel_io_handle_t mipi_dbi_io = NULL;
esp_lcd_panel_handle_t mipi_dpi_panel = NULL;
void *frame_buffer = NULL;
size_t frame_buffer_size = 0;
//mipi ldo
esp_ldo_channel_handle_t ldo_mipi_phy = NULL;
esp_ldo_channel_config_t ldo_mipi_phy_config = {
.chan_id = CONFIG_EXAMPLE_USED_LDO_CHAN_ID,
.voltage_mv = CONFIG_EXAMPLE_USED_LDO_VOLTAGE_MV,
};
ESP_ERROR_CHECK(esp_ldo_acquire_channel(&ldo_mipi_phy_config, &ldo_mipi_phy));
//---------------DSI Init------------------//
example_dsi_resource_alloc(&mipi_dsi_bus, &mipi_dbi_io, &mipi_dpi_panel, &frame_buffer);
//---------------Necessary variable config------------------//
frame_buffer_size = CONFIG_EXAMPLE_MIPI_DSI_DISP_HRES * CONFIG_EXAMPLE_MIPI_DSI_DISP_VRES * EXAMPLE_RGB565_BITS_PER_PIXEL / 8;
ESP_LOGD(TAG, "CONFIG_EXAMPLE_MIPI_DSI_DISP_HRES: %d, CONFIG_EXAMPLE_MIPI_DSI_DISP_VRES: %d, bits per pixel: %d", CONFIG_EXAMPLE_MIPI_DSI_DISP_HRES, CONFIG_EXAMPLE_MIPI_DSI_DISP_VRES, EXAMPLE_RGB565_BITS_PER_PIXEL);
ESP_LOGD(TAG, "frame_buffer_size: %zu", frame_buffer_size);
ESP_LOGD(TAG, "frame_buffer: %p", frame_buffer);
size_t cam_buffer_size = CONFIG_EXAMPLE_CAM_HRES * CONFIG_EXAMPLE_CAM_VRES * EXAMPLE_RGB565_BITS_PER_PIXEL / 8;
void *cam_buffer = heap_caps_calloc(1, cam_buffer_size, MALLOC_CAP_DMA | MALLOC_CAP_SPIRAM);
if (!cam_buffer) {
ESP_LOGE(TAG, "no mem for cam_buffer");
return;
}
esp_cam_ctlr_trans_t cam_trans = {
.buffer = cam_buffer,
.buflen = cam_buffer_size,
};
//----------CAM Controller Init------------//
esp_cam_ctlr_handle_t cam_handle = NULL;
esp_cam_ctlr_dvp_pin_config_t pin_cfg = {
.data_width = EXAMPLE_DVP_CAM_DATA_WIDTH,
.data_io = {
EXAMPLE_DVP_CAM_D0_IO,
EXAMPLE_DVP_CAM_D1_IO,
EXAMPLE_DVP_CAM_D2_IO,
EXAMPLE_DVP_CAM_D3_IO,
EXAMPLE_DVP_CAM_D4_IO,
EXAMPLE_DVP_CAM_D5_IO,
EXAMPLE_DVP_CAM_D6_IO,
EXAMPLE_DVP_CAM_D7_IO,
},
.vsync_io = EXAMPLE_DVP_CAM_VSYNC_IO,
.de_io = EXAMPLE_DVP_CAM_DE_IO,
.pclk_io = EXAMPLE_DVP_CAM_PCLK_IO,
.xclk_io = EXAMPLE_DVP_CAM_XCLK_IO, // Set XCLK pin to generate XCLK signal
};
esp_cam_ctlr_dvp_config_t dvp_config = {
.ctlr_id = 0,
.clk_src = CAM_CLK_SRC_DEFAULT,
.h_res = CONFIG_EXAMPLE_CAM_HRES,
.v_res = CONFIG_EXAMPLE_CAM_VRES,
.input_data_color_type = CAM_CTLR_COLOR_RGB565,
.dma_burst_size = 128,
.pin = &pin_cfg,
.bk_buffer_dis = 1,
.xclk_freq = EXAMPLE_DVP_CAM_XCLK_FREQ_HZ,
};
ret = esp_cam_new_dvp_ctlr(&dvp_config, &cam_handle);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "dvp init fail[%d]", ret);
return;
}
//--------Camera Sensor and SCCB Init-----------//
example_sensor_config_t cam_sensor_config = {
.i2c_port_num = I2C_NUM_0,
.i2c_sda_io_num = EXAMPLE_DVP_CAM_SCCB_SDA_IO,
.i2c_scl_io_num = EXAMPLE_DVP_CAM_SCCB_SCL_IO,
.port = ESP_CAM_SENSOR_DVP,
.format_name = EXAMPLE_CAM_FORMAT,
};
example_sensor_handle_t sensor_handle = {
.sccb_handle = NULL,
.i2c_bus_handle = NULL,
};
example_sensor_init(&cam_sensor_config, &sensor_handle);
esp_cam_ctlr_evt_cbs_t cbs = {
.on_get_new_trans = s_camera_get_new_vb,
.on_trans_finished = s_camera_get_finished_trans,
};
if (esp_cam_ctlr_register_event_callbacks(cam_handle, &cbs, &cam_trans) != ESP_OK) {
ESP_LOGE(TAG, "ops register fail");
return;
}
ESP_ERROR_CHECK(esp_cam_ctlr_enable(cam_handle));
//---------------DPI Reset------------------//
example_dpi_panel_reset(mipi_dpi_panel);
//init to all white
memset(frame_buffer, 0xFF, frame_buffer_size);
esp_cache_msync((void *)frame_buffer, frame_buffer_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
example_dpi_panel_init(mipi_dpi_panel);
if (esp_cam_ctlr_start(cam_handle) != ESP_OK) {
ESP_LOGE(TAG, "Driver start fail");
return;
}
// Register DPI panel event callback for display update ready notification
display_update_param_t display_update_param = {
.panel_hdl = mipi_dpi_panel,
.cam_buf = cam_buffer,
};
esp_lcd_dpi_panel_event_callbacks_t dpi_cbs = {
.on_color_trans_done = example_display_update_ready,
};
ESP_ERROR_CHECK(esp_lcd_dpi_panel_register_event_callbacks(mipi_dpi_panel, &dpi_cbs, &display_update_param));
esp_lcd_panel_draw_bitmap(mipi_dpi_panel, 0, 0, CONFIG_EXAMPLE_CAM_HRES, CONFIG_EXAMPLE_CAM_VRES, cam_buffer);
while (1) {
vTaskDelay(100 / portTICK_PERIOD_MS);
}
}
static bool s_camera_get_new_vb(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data)
{
esp_cam_ctlr_trans_t cam_trans = *(esp_cam_ctlr_trans_t *)user_data;
trans->buffer = cam_trans.buffer;
trans->buflen = cam_trans.buflen;
return false;
}
static bool s_camera_get_finished_trans(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data)
{
return false;
}

View File

@@ -0,0 +1,57 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "sdkconfig.h"
#ifdef __cplusplus
extern "C" {
#endif
#define EXAMPLE_RGB565_BITS_PER_PIXEL (16)
#define EXAMPLE_DVP_CAM_SCCB_SCL_IO (33)
#define EXAMPLE_DVP_CAM_SCCB_SDA_IO (32)
#define EXAMPLE_DVP_CAM_XCLK_FREQ_HZ (20000000)
#define EXAMPLE_DVP_CAM_DATA_WIDTH (8)
#define EXAMPLE_DVP_CAM_D0_IO (53)
#define EXAMPLE_DVP_CAM_D1_IO (54)
#define EXAMPLE_DVP_CAM_D2_IO (26)
#define EXAMPLE_DVP_CAM_D3_IO (1)
#define EXAMPLE_DVP_CAM_D4_IO (0)
#define EXAMPLE_DVP_CAM_D5_IO (45)
#define EXAMPLE_DVP_CAM_D6_IO (46)
#define EXAMPLE_DVP_CAM_D7_IO (47)
#define EXAMPLE_DVP_CAM_XCLK_IO (20)
#define EXAMPLE_DVP_CAM_PCLK_IO (21)
#define EXAMPLE_DVP_CAM_DE_IO (22)
#define EXAMPLE_DVP_CAM_VSYNC_IO (23)
#define EXAMPLE_DVP_CAM_HSYNC_IO (-1)
#if CONFIG_EXAMPLE_CAM_HRES_640
#if CONFIG_EXAMPLE_CAM_VRES_480
#define EXAMPLE_CAM_FORMAT "DVP_8bit_20Minput_RGB565_640x480_6fps"
#endif
#elif CONFIG_EXAMPLE_CAM_HRES_240
#if CONFIG_EXAMPLE_CAM_VRES_240
#define EXAMPLE_CAM_FORMAT "DVP_8bit_20Minput_RGB565_240x240_25fps"
#endif
#endif
#ifndef EXAMPLE_CAM_FORMAT
#error "Unsupported camera format! Please adjust EXAMPLE_CAM_HRES and EXAMPLE_CAM_VRES in menuconfig"
#endif
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,7 @@
dependencies:
idf:
version: ">=5.3.0"
dsi_init:
path: ${IDF_PATH}/examples/peripherals/camera/common_components/dsi_init
sensor_init:
path: ${IDF_PATH}/examples/peripherals/camera/common_components/sensor_init

View File

@@ -0,0 +1,11 @@
# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import pytest
from pytest_embedded import Dut
from pytest_embedded_idf.utils import idf_parametrize
@pytest.mark.generic
@idf_parametrize('target', ['esp32p4'], indirect=['target'])
def test_dvp_dsi(dut: Dut) -> None:
dut.expect_exact('Calling app_main()')

View File

@@ -0,0 +1 @@
CONFIG_CAMERA_OV2640=y

View File

@@ -0,0 +1,4 @@
CONFIG_IDF_EXPERIMENTAL_FEATURES=y
CONFIG_SPIRAM=y
CONFIG_SPIRAM_SPEED_200M=y
CONFIG_EXAMPLE_MIPI_DSI_DISP_USE_DMA2D=y

View File

@@ -15,7 +15,7 @@ The subsections below give only absolutely necessary information. For full steps
### Hardware Required ### Hardware Required
- OV2640 camera sensor, or other camera sensors with DVP port that can output raw format color data - OV2640 / SC030IOT camera sensor, or other camera sensors with DVP port that can output raw format color data
- EK79007 or ILI9881C LCD screen - EK79007 or ILI9881C LCD screen
- ESP32P4 devkit - ESP32P4 devkit
@@ -106,7 +106,7 @@ Set CONFIG_CAMERA_OV2640 to y
Remember to select the LCD screen model and set corresponding correct horizontal/vertical resolution in ``menuconfig`` > ``Example DSI Configuration``. Remember to select the LCD screen model and set corresponding correct horizontal/vertical resolution in ``menuconfig`` > ``Example DSI Configuration``.
Available options for the camera sensor output horizontal/vertical resolution can be seen in ``menuconfig`` > ``Example Configuration``. Note that the horizontal resolution for the camera should be the same as the LCD screen horizontal resolution. Available options for the camera sensor output horizontal/vertical resolution can be seen in ``menuconfig`` > ``Example Configuration``.
### Build and Flash ### Build and Flash

View File

@@ -18,40 +18,48 @@ menu "Example Configuration"
choice EXAMPLE_CAM_HRES choice EXAMPLE_CAM_HRES
bool "Set camera horizontal resolution" bool "Set camera horizontal resolution"
default EXAMPLE_CAM_HRES_1024 if EXAMPLE_MIPI_DSI_DISP_HRES_1024 default EXAMPLE_CAM_HRES_640
default EXAMPLE_CAM_HRES_800 if EXAMPLE_MIPI_DSI_DISP_HRES_800
config EXAMPLE_CAM_HRES_1024 config EXAMPLE_CAM_HRES_1024
depends on EXAMPLE_MIPI_DSI_DISP_HRES_1024 depends on EXAMPLE_MIPI_DSI_DISP_HRES >= 1024
bool "1024" bool "1024"
config EXAMPLE_CAM_HRES_800 config EXAMPLE_CAM_HRES_800
depends on EXAMPLE_MIPI_DSI_DISP_HRES_800 depends on EXAMPLE_MIPI_DSI_DISP_HRES >= 800
bool "800" bool "800"
config EXAMPLE_CAM_HRES_640
depends on EXAMPLE_MIPI_DSI_DISP_HRES >= 640
bool "640"
endchoice endchoice
config EXAMPLE_CAM_HRES config EXAMPLE_CAM_HRES
int int
default 1024 if EXAMPLE_CAM_HRES_1024 default 1024 if EXAMPLE_CAM_HRES_1024
default 800 if EXAMPLE_CAM_HRES_800 default 800 if EXAMPLE_CAM_HRES_800
default 640 if EXAMPLE_CAM_HRES_640
choice EXAMPLE_CAM_VRES choice EXAMPLE_CAM_VRES
bool "Set camera vertical resolution" bool "Set camera vertical resolution"
default EXAMPLE_CAM_VRES_600 if EXAMPLE_MIPI_DSI_DISP_VRES_600 default EXAMPLE_CAM_VRES_600 if EXAMPLE_CAM_HRES_1024
default EXAMPLE_CAM_VRES_640 if EXAMPLE_MIPI_DSI_DISP_VRES_1280 default EXAMPLE_CAM_VRES_640 if EXAMPLE_CAM_HRES_800
default EXAMPLE_CAM_VRES_480 if EXAMPLE_CAM_HRES_640
config EXAMPLE_CAM_VRES_480
depends on EXAMPLE_MIPI_DSI_DISP_VRES >= 480
bool "480"
config EXAMPLE_CAM_VRES_600 config EXAMPLE_CAM_VRES_600
depends on EXAMPLE_MIPI_DSI_DISP_VRES_600 depends on EXAMPLE_MIPI_DSI_DISP_VRES >= 600
bool "600" bool "600"
config EXAMPLE_CAM_VRES_640 config EXAMPLE_CAM_VRES_640
depends on EXAMPLE_MIPI_DSI_DISP_VRES_1280 depends on EXAMPLE_MIPI_DSI_DISP_VRES >= 640
bool "640" bool "640"
config EXAMPLE_CAM_VRES_800 config EXAMPLE_CAM_VRES_800
depends on EXAMPLE_MIPI_DSI_DISP_VRES_1280 depends on EXAMPLE_MIPI_DSI_DISP_VRES >= 800
bool "800" bool "800"
endchoice endchoice
config EXAMPLE_CAM_VRES config EXAMPLE_CAM_VRES
int int
default 480 if EXAMPLE_CAM_VRES_480
default 600 if EXAMPLE_CAM_VRES_600 default 600 if EXAMPLE_CAM_VRES_600
default 640 if EXAMPLE_CAM_VRES_640 default 640 if EXAMPLE_CAM_VRES_640
default 800 if EXAMPLE_CAM_VRES_800 default 800 if EXAMPLE_CAM_VRES_800

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -26,6 +26,11 @@
static const char *TAG = "dvp_isp_dsi"; static const char *TAG = "dvp_isp_dsi";
typedef struct {
esp_lcd_panel_handle_t panel_hdl;
void *cam_buf;
} display_update_param_t;
static bool s_camera_get_new_vb(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data); static bool s_camera_get_new_vb(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data);
static bool s_camera_get_finished_trans(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data); static bool s_camera_get_finished_trans(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data);
@@ -54,6 +59,13 @@ static void s_ledc_generate_dvp_xclk(void)
ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel)); ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel));
} }
static bool example_display_update_ready(esp_lcd_panel_handle_t panel, esp_lcd_dpi_panel_event_data_t *edata, void *user_ctx)
{
display_update_param_t *param = (display_update_param_t *)user_ctx;
esp_lcd_panel_draw_bitmap(param->panel_hdl, 0, 0, CONFIG_EXAMPLE_CAM_HRES, CONFIG_EXAMPLE_CAM_VRES, param->cam_buf);
return false;
}
void app_main(void) void app_main(void)
{ {
esp_err_t ret = ESP_FAIL; esp_err_t ret = ESP_FAIL;
@@ -80,15 +92,21 @@ void app_main(void)
example_dsi_resource_alloc(&mipi_dsi_bus, &mipi_dbi_io, &mipi_dpi_panel, &frame_buffer); example_dsi_resource_alloc(&mipi_dsi_bus, &mipi_dbi_io, &mipi_dpi_panel, &frame_buffer);
//---------------Necessary variable config------------------// //---------------Necessary variable config------------------//
frame_buffer_size = CONFIG_EXAMPLE_CAM_HRES * CONFIG_EXAMPLE_MIPI_DSI_DISP_VRES * EXAMPLE_RGB565_BITS_PER_PIXEL / 8; frame_buffer_size = CONFIG_EXAMPLE_MIPI_DSI_DISP_HRES * CONFIG_EXAMPLE_MIPI_DSI_DISP_VRES * EXAMPLE_RGB565_BITS_PER_PIXEL / 8;
ESP_LOGD(TAG, "CONFIG_EXAMPLE_CAM_HRES: %d, CONFIG_EXAMPLE_MIPI_DSI_DISP_VRES: %d, bits per pixel: %d", CONFIG_EXAMPLE_CAM_HRES, CONFIG_EXAMPLE_MIPI_DSI_DISP_VRES, EXAMPLE_RGB565_BITS_PER_PIXEL); ESP_LOGD(TAG, "CONFIG_EXAMPLE_MIPI_DSI_DISP_HRES: %d, CONFIG_EXAMPLE_MIPI_DSI_DISP_VRES: %d, bits per pixel: %d", CONFIG_EXAMPLE_MIPI_DSI_DISP_HRES, CONFIG_EXAMPLE_MIPI_DSI_DISP_VRES, EXAMPLE_RGB565_BITS_PER_PIXEL);
ESP_LOGD(TAG, "frame_buffer_size: %zu", frame_buffer_size); ESP_LOGD(TAG, "frame_buffer_size: %zu", frame_buffer_size);
ESP_LOGD(TAG, "frame_buffer: %p", frame_buffer); ESP_LOGD(TAG, "frame_buffer: %p", frame_buffer);
size_t cam_buffer_size = CONFIG_EXAMPLE_CAM_HRES * CONFIG_EXAMPLE_CAM_VRES * EXAMPLE_RGB565_BITS_PER_PIXEL / 8;
void *cam_buffer = heap_caps_calloc(1, cam_buffer_size, MALLOC_CAP_DMA | MALLOC_CAP_SPIRAM);
if (!cam_buffer) {
ESP_LOGE(TAG, "no mem for cam_buffer");
return;
}
esp_cam_ctlr_trans_t cam_trans = { esp_cam_ctlr_trans_t cam_trans = {
.buffer = frame_buffer, .buffer = cam_buffer,
.buflen = frame_buffer_size, .buflen = cam_buffer_size,
}; };
//--------Camera Sensor and SCCB Init-----------// //--------Camera Sensor and SCCB Init-----------//
@@ -101,8 +119,11 @@ void app_main(void)
.port = ESP_CAM_SENSOR_DVP, .port = ESP_CAM_SENSOR_DVP,
.format_name = EXAMPLE_CAM_FORMAT, .format_name = EXAMPLE_CAM_FORMAT,
}; };
i2c_master_bus_handle_t i2c_bus_handle = NULL; example_sensor_handle_t sensor_handle = {
example_sensor_init(&cam_sensor_config, &i2c_bus_handle); .sccb_handle = NULL,
.i2c_bus_handle = NULL,
};
example_sensor_init(&cam_sensor_config, &sensor_handle);
//---------------ISP Init------------------// //---------------ISP Init------------------//
isp_proc_handle_t isp_proc = NULL; isp_proc_handle_t isp_proc = NULL;
@@ -137,7 +158,7 @@ void app_main(void)
.hsync_io = EXAMPLE_ISP_DVP_CAM_HSYNC_IO, .hsync_io = EXAMPLE_ISP_DVP_CAM_HSYNC_IO,
.vsync_io = EXAMPLE_ISP_DVP_CAM_VSYNC_IO, .vsync_io = EXAMPLE_ISP_DVP_CAM_VSYNC_IO,
.de_io = EXAMPLE_ISP_DVP_CAM_DE_IO, .de_io = EXAMPLE_ISP_DVP_CAM_DE_IO,
.io_flags.vsync_invert = 1, .io_flags.vsync_invert = 1, // active high
.queue_items = 10, .queue_items = 10,
}; };
ret = esp_cam_new_isp_dvp_ctlr(isp_proc, &dvp_config, &cam_handle); ret = esp_cam_new_isp_dvp_ctlr(isp_proc, &dvp_config, &cam_handle);
@@ -171,6 +192,17 @@ void app_main(void)
return; return;
} }
// Register DPI panel event callback for display update ready notification
display_update_param_t display_update_param = {
.panel_hdl = mipi_dpi_panel,
.cam_buf = cam_buffer,
};
esp_lcd_dpi_panel_event_callbacks_t dpi_cbs = {
.on_color_trans_done = example_display_update_ready,
};
ESP_ERROR_CHECK(esp_lcd_dpi_panel_register_event_callbacks(mipi_dpi_panel, &dpi_cbs, &display_update_param));
esp_lcd_panel_draw_bitmap(mipi_dpi_panel, 0, 0, CONFIG_EXAMPLE_CAM_HRES, CONFIG_EXAMPLE_CAM_VRES, cam_buffer);
while (1) { while (1) {
ESP_ERROR_CHECK(esp_cam_ctlr_receive(cam_handle, &cam_trans, ESP_CAM_CTLR_MAX_DELAY)); ESP_ERROR_CHECK(esp_cam_ctlr_receive(cam_handle, &cam_trans, ESP_CAM_CTLR_MAX_DELAY));
} }

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -20,36 +20,46 @@ extern "C" {
#define EXAMPLE_ISP_DVP_CAM_XCLK_FREQ_HZ (20000000) #define EXAMPLE_ISP_DVP_CAM_XCLK_FREQ_HZ (20000000)
#define EXAMPLE_ISP_DVP_CAM_DATA_WIDTH (8) #define EXAMPLE_ISP_DVP_CAM_DATA_WIDTH (8)
#define EXAMPLE_ISP_DVP_CAM_D0_IO (8) #define EXAMPLE_ISP_DVP_CAM_D0_IO (53)
#define EXAMPLE_ISP_DVP_CAM_D1_IO (9) #define EXAMPLE_ISP_DVP_CAM_D1_IO (54)
#define EXAMPLE_ISP_DVP_CAM_D2_IO (10) #define EXAMPLE_ISP_DVP_CAM_D2_IO (26)
#define EXAMPLE_ISP_DVP_CAM_D3_IO (4) #define EXAMPLE_ISP_DVP_CAM_D3_IO (1)
#define EXAMPLE_ISP_DVP_CAM_D4_IO (5) #define EXAMPLE_ISP_DVP_CAM_D4_IO (0)
#define EXAMPLE_ISP_DVP_CAM_D5_IO (45) #define EXAMPLE_ISP_DVP_CAM_D5_IO (45)
#define EXAMPLE_ISP_DVP_CAM_D6_IO (46) #define EXAMPLE_ISP_DVP_CAM_D6_IO (46)
#define EXAMPLE_ISP_DVP_CAM_D7_IO (47) #define EXAMPLE_ISP_DVP_CAM_D7_IO (47)
#define EXAMPLE_ISP_DVP_CAM_XCLK_IO (20) #define EXAMPLE_ISP_DVP_CAM_XCLK_IO (20)
#define EXAMPLE_ISP_DVP_CAM_PCLK_IO (21) #define EXAMPLE_ISP_DVP_CAM_PCLK_IO (21)
#define EXAMPLE_ISP_DVP_CAM_DE_IO (2) #define EXAMPLE_ISP_DVP_CAM_DE_IO (22)
#define EXAMPLE_ISP_DVP_CAM_VSYNC_IO (23) #define EXAMPLE_ISP_DVP_CAM_VSYNC_IO (23)
#define EXAMPLE_ISP_DVP_CAM_HSYNC_IO (-1) #define EXAMPLE_ISP_DVP_CAM_HSYNC_IO (-1)
#if CONFIG_EXAMPLE_CAM_HRES_800 #if CONFIG_EXAMPLE_CAM_HRES_640
#if CONFIG_EXAMPLE_CAM_VRES_480
#define EXAMPLE_CAM_FORMAT "DVP_8bit_20Minput_RAW8_640x480_26fps" // sc030iot
#endif
#elif CONFIG_EXAMPLE_CAM_HRES_800
#if CONFIG_EXAMPLE_CAM_VRES_640 #if CONFIG_EXAMPLE_CAM_VRES_640
#define EXAMPLE_CAM_FORMAT "DVP_8bit_20Minput_RAW8_800x640_15fps" #define EXAMPLE_CAM_FORMAT "DVP_8bit_20Minput_RAW8_800x640_15fps" // ov2640
#elif CONFIG_EXAMPLE_CAM_VRES_800 #elif CONFIG_EXAMPLE_CAM_VRES_800
#define EXAMPLE_CAM_FORMAT "DVP_8bit_20Minput_RAW8_800x800_15fps" #define EXAMPLE_CAM_FORMAT "DVP_8bit_20Minput_RAW8_800x800_15fps" // ov2640
#endif #endif
#elif CONFIG_EXAMPLE_CAM_HRES_1024 #elif CONFIG_EXAMPLE_CAM_HRES_1024
#if CONFIG_EXAMPLE_CAM_VRES_600 #if CONFIG_EXAMPLE_CAM_VRES_600
#define EXAMPLE_CAM_FORMAT "DVP_8bit_20Minput_RAW8_1024x600_15fps" #define EXAMPLE_CAM_FORMAT "DVP_8bit_20Minput_RAW8_1024x600_15fps" // ov2640
#endif #endif
#endif #endif
#ifndef EXAMPLE_CAM_FORMAT
#error "Unsupported camera format! Please adjust EXAMPLE_CAM_HRES and EXAMPLE_CAM_VRES in menuconfig"
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -1,4 +1,3 @@
CONFIG_SPIRAM=y
CONFIG_IDF_EXPERIMENTAL_FEATURES=y
CONFIG_SPIRAM_SPEED_200M=y
CONFIG_CAMERA_OV2640=y CONFIG_CAMERA_OV2640=y
CONFIG_CAMERA_SC030IOT=y
CONFIG_EXAMPLE_MIPI_DSI_DISP_USE_DMA2D=y

View File

@@ -0,0 +1,3 @@
CONFIG_IDF_EXPERIMENTAL_FEATURES=y
CONFIG_SPIRAM=y
CONFIG_SPIRAM_SPEED_200M=y

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -66,7 +66,10 @@ void app_main(void)
}; };
//--------Camera Sensor and SCCB Init-----------// //--------Camera Sensor and SCCB Init-----------//
i2c_master_bus_handle_t i2c_bus_handle = NULL; example_sensor_handle_t sensor_handle = {
.sccb_handle = NULL,
.i2c_bus_handle = NULL,
};
example_sensor_config_t cam_sensor_config = { example_sensor_config_t cam_sensor_config = {
.i2c_port_num = I2C_NUM_0, .i2c_port_num = I2C_NUM_0,
.i2c_sda_io_num = EXAMPLE_MIPI_CSI_CAM_SCCB_SDA_IO, .i2c_sda_io_num = EXAMPLE_MIPI_CSI_CAM_SCCB_SDA_IO,
@@ -74,7 +77,7 @@ void app_main(void)
.port = ESP_CAM_SENSOR_MIPI_CSI, .port = ESP_CAM_SENSOR_MIPI_CSI,
.format_name = EXAMPLE_CAM_FORMAT, .format_name = EXAMPLE_CAM_FORMAT,
}; };
example_sensor_init(&cam_sensor_config, &i2c_bus_handle); example_sensor_init(&cam_sensor_config, &sensor_handle);
//---------------CSI Init------------------// //---------------CSI Init------------------//
esp_cam_ctlr_csi_config_t csi_config = { esp_cam_ctlr_csi_config_t csi_config = {

View File

@@ -1,5 +1,2 @@
CONFIG_SPIRAM=y
CONFIG_IDF_EXPERIMENTAL_FEATURES=y
CONFIG_SPIRAM_SPEED_200M=y
CONFIG_CAMERA_SC2336=y CONFIG_CAMERA_SC2336=y
CONFIG_CAMERA_OV5647=y CONFIG_CAMERA_OV5647=y

View File

@@ -0,0 +1,3 @@
CONFIG_IDF_EXPERIMENTAL_FEATURES=y
CONFIG_SPIRAM=y
CONFIG_SPIRAM_SPEED_200M=y

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -223,7 +223,10 @@ void app_main(void)
}; };
//--------Camera Sensor and SCCB Init-----------// //--------Camera Sensor and SCCB Init-----------//
i2c_master_bus_handle_t i2c_bus_handle = NULL; example_sensor_handle_t sensor_handle = {
.sccb_handle = NULL,
.i2c_bus_handle = NULL,
};
example_sensor_config_t cam_sensor_config = { example_sensor_config_t cam_sensor_config = {
.i2c_port_num = I2C_NUM_0, .i2c_port_num = I2C_NUM_0,
.i2c_sda_io_num = EXAMPLE_MIPI_CSI_CAM_SCCB_SDA_IO, .i2c_sda_io_num = EXAMPLE_MIPI_CSI_CAM_SCCB_SDA_IO,
@@ -231,7 +234,7 @@ void app_main(void)
.port = ESP_CAM_SENSOR_MIPI_CSI, .port = ESP_CAM_SENSOR_MIPI_CSI,
.format_name = EXAMPLE_CAM_FORMAT, .format_name = EXAMPLE_CAM_FORMAT,
}; };
example_sensor_init(&cam_sensor_config, &i2c_bus_handle); example_sensor_init(&cam_sensor_config, &sensor_handle);
//---------------VCM SCCB Init------------------// //---------------VCM SCCB Init------------------//
esp_sccb_io_handle_t dw9714_io_handle = NULL; esp_sccb_io_handle_t dw9714_io_handle = NULL;
@@ -240,7 +243,7 @@ void app_main(void)
.device_address = EXAMPLE_DW9714_DEV_ADDR, .device_address = EXAMPLE_DW9714_DEV_ADDR,
.dev_addr_length = I2C_ADDR_BIT_LEN_7, .dev_addr_length = I2C_ADDR_BIT_LEN_7,
}; };
ESP_ERROR_CHECK(sccb_new_i2c_io(i2c_bus_handle, &i2c_config, &dw9714_io_handle)); ESP_ERROR_CHECK(sccb_new_i2c_io(sensor_handle.i2c_bus_handle, &i2c_config, &dw9714_io_handle));
//---------------CSI Init------------------// //---------------CSI Init------------------//
esp_cam_ctlr_csi_config_t csi_config = { esp_cam_ctlr_csi_config_t csi_config = {