Skip to content

Commit

Permalink
Merge branch 'feature/isp_dvp_example' into 'master'
Browse files Browse the repository at this point in the history
feat(dvp_isp_dsi_example): add new option to connect a DVP camera sensor (ov2640) through ISP_DVP

Closes IDF-10032

See merge request espressif/esp-idf!31796
songruo committed Dec 9, 2024
2 parents 874ce4e + e4a4497 commit 0d68aa8
Showing 46 changed files with 704 additions and 82 deletions.
8 changes: 4 additions & 4 deletions components/esp_driver_cam/isp_dvp/src/esp_cam_ctlr_isp_dvp.c
Original file line number Diff line number Diff line change
@@ -495,28 +495,28 @@ static esp_err_t s_isp_io_init(isp_dvp_controller_t *dvp_ctlr, const esp_cam_ctl
.pull_up_en = true,
};

if (ctlr_config->pclk_io) {
if (ctlr_config->pclk_io >= 0) {
gpio_conf.pin_bit_mask = 1ULL << ctlr_config->pclk_io;
ESP_RETURN_ON_ERROR(gpio_config(&gpio_conf), TAG, "failed to configure pclk gpio");
ESP_LOGD(TAG, "pclk_io: %d, dvp_pclk_sig: %"PRId32, ctlr_config->pclk_io, isp_hw_info.dvp_ctlr[dvp_ctlr->id].dvp_pclk_sig);
esp_rom_gpio_connect_in_signal(ctlr_config->pclk_io, isp_hw_info.dvp_ctlr[dvp_ctlr->id].dvp_pclk_sig, false);
}

if (ctlr_config->hsync_io) {
if (ctlr_config->hsync_io >= 0) {
gpio_conf.pin_bit_mask = 1ULL << ctlr_config->hsync_io;
ESP_RETURN_ON_ERROR(gpio_config(&gpio_conf), TAG, "failed to configure hsync gpio");
ESP_LOGD(TAG, "hsync_io: %d, dvp_hsync_sig: %"PRId32, ctlr_config->hsync_io, isp_hw_info.dvp_ctlr[dvp_ctlr->id].dvp_hsync_sig);
esp_rom_gpio_connect_in_signal(ctlr_config->hsync_io, isp_hw_info.dvp_ctlr[dvp_ctlr->id].dvp_hsync_sig, false);
}

if (ctlr_config->vsync_io) {
if (ctlr_config->vsync_io >= 0) {
gpio_conf.pin_bit_mask = 1ULL << ctlr_config->vsync_io;
ESP_RETURN_ON_ERROR(gpio_config(&gpio_conf), TAG, "failed to configure vsync gpio");
ESP_LOGD(TAG, "vsync_io: %d, dvp_vsync_sig: %"PRId32, ctlr_config->vsync_io, isp_hw_info.dvp_ctlr[dvp_ctlr->id].dvp_vsync_sig);
esp_rom_gpio_connect_in_signal(ctlr_config->vsync_io, isp_hw_info.dvp_ctlr[dvp_ctlr->id].dvp_vsync_sig, false);
}

if (ctlr_config->de_io) {
if (ctlr_config->de_io >= 0) {
gpio_conf.pin_bit_mask = 1ULL << ctlr_config->de_io;
ESP_RETURN_ON_ERROR(gpio_config(&gpio_conf), TAG, "failed to configure de gpio");
ESP_LOGD(TAG, "de_io: %d, dvp_de_sig: %"PRId32, ctlr_config->de_io, isp_hw_info.dvp_ctlr[dvp_ctlr->id].dvp_de_sig);
Original file line number Diff line number Diff line change
@@ -111,6 +111,7 @@ bool esp_isp_ae_isr(isp_proc_handle_t proc, uint32_t ae_events);
bool esp_isp_awb_isr(isp_proc_handle_t proc, uint32_t awb_events);
bool esp_isp_sharpen_isr(isp_proc_handle_t proc, uint32_t sharp_events);
bool esp_isp_hist_isr(isp_proc_handle_t proc, uint32_t hist_events);
esp_err_t esp_isp_enable_yuv_submodules(isp_proc_handle_t proc, bool en);

#ifdef __cplusplus
}
2 changes: 2 additions & 0 deletions components/esp_driver_isp/src/isp_af.c
Original file line number Diff line number Diff line change
@@ -81,6 +81,7 @@ esp_err_t esp_isp_new_af_controller(isp_proc_handle_t isp_proc, const esp_isp_af
{
esp_err_t ret = ESP_FAIL;
ESP_RETURN_ON_FALSE(isp_proc && af_config && ret_hdl, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
ESP_RETURN_ON_ERROR(esp_isp_enable_yuv_submodules(isp_proc, true), TAG, "failed to enable YUV submodules");

bool rgb2yuv_en = isp_ll_is_rgb2yuv_enabled(isp_proc->hal.hw);
bool demosaic_en = isp_ll_is_demosaic_enabled(isp_proc->hal.hw);
@@ -154,6 +155,7 @@ esp_err_t esp_isp_del_af_controller(isp_af_ctlr_t af_ctlr)

// Deregister the AF ISR
ESP_RETURN_ON_FALSE(esp_isp_deregister_isr(af_ctlr->isp_proc, ISP_SUBMODULE_AF) == ESP_OK, ESP_FAIL, TAG, "fail to deregister ISR");
ESP_RETURN_ON_ERROR(esp_isp_enable_yuv_submodules(af_ctlr->isp_proc, false), TAG, "failed to disable YUV submodules");

s_isp_declaim_af_controller(af_ctlr);
s_isp_af_free_controller(af_ctlr);
2 changes: 2 additions & 0 deletions components/esp_driver_isp/src/isp_color.c
Original file line number Diff line number Diff line change
@@ -49,6 +49,7 @@ esp_err_t esp_isp_color_enable(isp_proc_handle_t proc)
{
ESP_RETURN_ON_FALSE(proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
ESP_RETURN_ON_FALSE(proc->color_fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "color is enabled already");
ESP_RETURN_ON_ERROR(esp_isp_enable_yuv_submodules(proc, true), TAG, "failed to enable YUV submodules");

isp_ll_color_clk_enable(proc->hal.hw, true);
isp_ll_color_enable(proc->hal.hw, true);
@@ -61,6 +62,7 @@ esp_err_t esp_isp_color_disable(isp_proc_handle_t proc)
{
ESP_RETURN_ON_FALSE(proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
ESP_RETURN_ON_FALSE(proc->color_fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "color isn't enabled yet");
ESP_RETURN_ON_ERROR(esp_isp_enable_yuv_submodules(proc, false), TAG, "failed to disable YUV submodules");

isp_ll_color_enable(proc->hal.hw, false);
isp_ll_color_clk_enable(proc->hal.hw, false);
26 changes: 26 additions & 0 deletions components/esp_driver_isp/src/isp_core.c
Original file line number Diff line number Diff line change
@@ -390,3 +390,29 @@ esp_err_t esp_isp_deregister_isr(isp_proc_handle_t proc, isp_submodule_t submodu

return ESP_OK;
}

esp_err_t esp_isp_enable_yuv_submodules(isp_proc_handle_t proc, bool en)
{
ESP_RETURN_ON_FALSE(proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");

bool rgb2yuv = false;
bool yuv2rgb = false;

if (proc->out_color_format.color_space == COLOR_SPACE_RGB) {
rgb2yuv = true;
yuv2rgb = true;
} else if (proc->out_color_format.color_space == COLOR_SPACE_YUV) {
rgb2yuv = true;
}

portENTER_CRITICAL(&proc->spinlock);
if (rgb2yuv) {
isp_ll_enable_rgb2yuv(proc->hal.hw, en);
}
if (yuv2rgb) {
isp_ll_enable_yuv2rgb(proc->hal.hw, en);
}
portEXIT_CRITICAL(&proc->spinlock);

return ESP_OK;
}
2 changes: 2 additions & 0 deletions components/esp_driver_isp/src/isp_sharpen.c
Original file line number Diff line number Diff line change
@@ -51,6 +51,7 @@ esp_err_t esp_isp_sharpen_enable(isp_proc_handle_t proc)
{
ESP_RETURN_ON_FALSE(proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
ESP_RETURN_ON_FALSE(proc->sharpen_fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "sharpen is enabled already");
ESP_RETURN_ON_ERROR(esp_isp_enable_yuv_submodules(proc, true), TAG, "failed to enable YUV submodules");

isp_ll_sharp_clk_enable(proc->hal.hw, true);
isp_ll_enable_intr(proc->hal.hw, ISP_LL_EVENT_SHARP_FRAME, true);
@@ -64,6 +65,7 @@ esp_err_t esp_isp_sharpen_disable(isp_proc_handle_t proc)
{
ESP_RETURN_ON_FALSE(proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
ESP_RETURN_ON_FALSE(proc->sharpen_fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "sharpen isn't enabled yet");
ESP_RETURN_ON_ERROR(esp_isp_enable_yuv_submodules(proc, false), TAG, "failed to disable YUV submodules");

isp_ll_sharp_enable(proc->hal.hw, false);
isp_ll_enable_intr(proc->hal.hw, ISP_LL_EVENT_SHARP_FRAME, false);
30 changes: 26 additions & 4 deletions components/hal/esp32p4/include/hal/isp_ll.h
Original file line number Diff line number Diff line change
@@ -396,15 +396,15 @@ static inline bool isp_ll_set_output_data_color_format(isp_dev_t *hw, color_spac
case COLOR_PIXEL_RGB888:
hw->cntl.isp_out_type = 2;
hw->cntl.demosaic_en = 1;
hw->cntl.rgb2yuv_en = 1;
hw->cntl.yuv2rgb_en = 1;
hw->cntl.rgb2yuv_en = 0;
hw->cntl.yuv2rgb_en = 0;
valid = true;
break;
case COLOR_PIXEL_RGB565:
hw->cntl.isp_out_type = 4;
hw->cntl.demosaic_en = 1;
hw->cntl.rgb2yuv_en = 1;
hw->cntl.yuv2rgb_en = 1;
hw->cntl.rgb2yuv_en = 0;
hw->cntl.yuv2rgb_en = 0;
valid = true;
break;
default:
@@ -456,6 +456,28 @@ static inline void isp_ll_enable_line_end_packet_exist(isp_dev_t *hw, bool en)
hw->frame_cfg.hsync_end_exist = en;
}

/**
* @brief Enable rgb2yuv
*
* @param[in] hw Hardware instance address
* @param[in] en Enable / Disable
*/
static inline void isp_ll_enable_rgb2yuv(isp_dev_t *hw, bool en)
{
hw->cntl.rgb2yuv_en = en;
}

/**
* @brief Enable yuv2rgb
*
* @param[in] hw Hardware instance address
* @param[in] en Enable / Disable
*/
static inline void isp_ll_enable_yuv2rgb(isp_dev_t *hw, bool en)
{
hw->cntl.yuv2rgb_en = en;
}

/**
* @brief Get if demosaic is enabled
*
3 changes: 2 additions & 1 deletion docs/en/api-reference/peripherals/camera_driver.rst
Original file line number Diff line number Diff line change
@@ -212,7 +212,8 @@ This allows the interrupt to run while the cache is disabled, but comes at the c
Application Examples
--------------------

* :example:`peripherals/camera/camera_dsi` demonstrates how to use the ``esp_driver_cam`` component to capture signals from a camera sensor and display it on an ILI9881C LCD screen via a DSI interface.
* :example:`peripherals/camera/mipi_isp_dsi` demonstrates how to use the ``esp_driver_cam`` component to capture signals from a MIPI CSI camera sensor via the ISP module and display it on a LCD screen via a DSI interface.
* :example:`peripherals/camera/dvp_isp_dsi` demonstrates how to use the ``esp_driver_cam`` component to capture signals from a DVP camera sensor via the ISP module and display it on a LCD screen via a DSI interface.

API Reference
-------------
3 changes: 2 additions & 1 deletion docs/zh_CN/api-reference/peripherals/camera_driver.rst
Original file line number Diff line number Diff line change
@@ -212,7 +212,8 @@ IRAM 安全
应用示例
--------

* :example:`peripherals/camera/camera_dsi` 演示了如何使用 ``esp_driver_cam`` 组件从摄像头传感器捕获信号,并通过 DSI 接口将其显示在 ILI9881C LCD 屏幕上。
* :example:`peripherals/camera/mipi_isp_dsi` 演示了如何使用 ``esp_driver_cam`` 组件从 MIPI CSI 摄像头传感器捕获信号,传入 ISP 模块,并通过 DSI 接口将其显示在 LCD 屏幕上。
* :example:`peripherals/camera/dvp_isp_dsi` 演示了如何使用 ``esp_driver_cam`` 组件从 DVP 摄像头传感器捕获信号,传入 ISP 模块,并通过 DSI 接口将其显示在 LCD 屏幕上。

API 参考
--------
9 changes: 8 additions & 1 deletion examples/peripherals/.build-test-rules.yml
Original file line number Diff line number Diff line change
@@ -38,7 +38,14 @@ examples/peripherals/analog_comparator:
- esp_driver_gpio
- esp_driver_ana_cmpr

examples/peripherals/camera/camera_dsi:
examples/peripherals/camera/dvp_isp_dsi:
disable:
- if: SOC_ISP_DVP_SUPPORTED != 1 or SOC_MIPI_DSI_SUPPORTED != 1
depends_components:
- esp_lcd
- esp_driver_cam

examples/peripherals/camera/mipi_isp_dsi:
disable:
- if: SOC_MIPI_CSI_SUPPORTED != 1 or SOC_MIPI_DSI_SUPPORTED != 1
depends_components:

This file was deleted.

7 changes: 0 additions & 7 deletions examples/peripherals/camera/camera_dsi/main/idf_component.yml

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
idf_component_register(SRCS "example_sensor_init.c"
INCLUDE_DIRS "include"
REQUIRES esp_cam_sensor
)
Original file line number Diff line number Diff line change
@@ -13,36 +13,32 @@
#include "driver/i2c_master.h"
#include "esp_sccb_intf.h"
#include "esp_sccb_i2c.h"
#include "esp_cam_sensor.h"
#include "esp_cam_sensor_detect.h"
#include "example_sensor_init.h"
#include "example_sensor_init_config.h"

static const char *TAG = "sensor_init";

void example_sensor_init(int i2c_port, i2c_master_bus_handle_t *out_i2c_bus_handle)
void example_sensor_init(example_sensor_config_t *sensor_config, i2c_master_bus_handle_t *out_i2c_bus_handle)
{
esp_err_t ret = ESP_FAIL;

//---------------I2C Init------------------//
i2c_master_bus_config_t i2c_bus_conf = {
.clk_source = I2C_CLK_SRC_DEFAULT,
.sda_io_num = EXAMPLE_CAM_SCCB_SDA_IO,
.scl_io_num = EXAMPLE_CAM_SCCB_SCL_IO,
.i2c_port = i2c_port,
.sda_io_num = sensor_config->i2c_sda_io_num,
.scl_io_num = sensor_config->i2c_scl_io_num,
.i2c_port = sensor_config->i2c_port_num,
.flags.enable_internal_pullup = true,
};
i2c_master_bus_handle_t i2c_bus_handle = NULL;
ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_conf, &i2c_bus_handle));

//---------------SCCB Init------------------//
esp_sccb_io_handle_t sccb_io_handle = NULL;
esp_cam_sensor_config_t cam_config = {
.sccb_handle = sccb_io_handle,
.reset_pin = -1,
.pwdn_pin = -1,
.xclk_pin = -1,
.sensor_port = ESP_CAM_SENSOR_MIPI_CSI,
};

esp_cam_sensor_device_t *cam = NULL;
@@ -54,9 +50,11 @@ void example_sensor_init(int i2c_port, i2c_master_bus_handle_t *out_i2c_bus_hand
};
ESP_ERROR_CHECK(sccb_new_i2c_io(i2c_bus_handle, &i2c_config, &cam_config.sccb_handle));

cam_config.sensor_port = p->port;

cam = (*(p->detect))(&cam_config);
if (cam) {
if (p->port != ESP_CAM_SENSOR_MIPI_CSI) {
if (p->port != sensor_config->port) {
ESP_LOGE(TAG, "detect a camera sensor with mismatched interface");
return;
}
@@ -79,8 +77,8 @@ void example_sensor_init(int i2c_port, i2c_master_bus_handle_t *out_i2c_bus_hand

esp_cam_sensor_format_t *cam_cur_fmt = NULL;
for (int i = 0; i < cam_fmt_array.count; i++) {
if (!strcmp(parray[i].name, EXAMPLE_CAM_FORMAT)) {
cam_cur_fmt = (esp_cam_sensor_format_t *) & (parray[i].name);
if (!strcmp(parray[i].name, sensor_config->format_name)) {
cam_cur_fmt = (esp_cam_sensor_format_t *) & (parray[i]);
}
}

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
dependencies:
espressif/esp_cam_sensor: "^0.5.1"
espressif/esp_cam_sensor: "^0.6.1"
idf:
version: ">=5.3.0"
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

#include "driver/i2c_master.h"
#include "esp_cam_sensor.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
* @brief Configuration of SCCB interface and sensor
*/
typedef struct {
int i2c_port_num; /* SCCB: i2c port */
int i2c_sda_io_num; /* SCCB: i2c SDA IO number */
int i2c_scl_io_num; /* SCCB: i2c SCL IO number */
esp_cam_sensor_port_t port; /* Sensor: interface of the camera sensor */
const char *format_name; /* Sensor: format to be set for the camera sensor */
} example_sensor_config_t;

/**
* @brief SCCB Interface and Sensor Init
*
* @param[in] sensor_config Camera sensor configuration
* @param[out] out_i2c_bus_handle I2C bus handle
*/
void example_sensor_init(example_sensor_config_t *sensor_config, i2c_master_bus_handle_t *out_i2c_bus_handle);

#ifdef __cplusplus
}
#endif
Original file line number Diff line number Diff line change
@@ -10,9 +10,7 @@
extern "C" {
#endif

#define EXAMPLE_RGB565_BITS_PER_PIXEL 16
#define EXAMPLE_MIPI_IDI_CLOCK_RATE (50000000)
#define EXAMPLE_MIPI_CSI_LANE_BITRATE_MBPS 200 //line_rate = pclk * 4
#define EXAMPLE_CAM_SCCB_FREQ (100000)

#ifdef __cplusplus
}
Original file line number Diff line number Diff line change
@@ -5,4 +5,4 @@ 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(camera_dsi)
project(dvp_isp_dsi)
154 changes: 154 additions & 0 deletions examples/peripherals/camera/dvp_isp_dsi/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
| 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 raw format color data
- EK79007 or ILI9881C 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``. Note that the horizontal resolution for the camera should be the same as the LCD screen horizontal resolution.


### 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 (1509) main_task: Calling app_main()
I (1509) ek79007: version: 1.0.1
I (1549) ov2640: Detected Camera sensor PID=0x26
I (1549) sensor_init: fmt[0].name:DVP_8bit_20Minput_RGB565_640x480_6fps
I (1549) sensor_init: fmt[1].name:DVP_8bit_20Minput_YUV422_640x480_6fps
I (1549) sensor_init: fmt[2].name:DVP_8bit_20Minput_JPEG_640x480_25fps
I (1559) sensor_init: fmt[3].name:DVP_8bit_20Minput_RGB565_240x240_25fps
I (1569) sensor_init: fmt[4].name:DVP_8bit_20Minput_YUV422_240x240_25fps
I (1569) sensor_init: fmt[5].name:DVP_8bit_20Minput_JPEG_320x240_50fps
I (1579) sensor_init: fmt[6].name:DVP_8bit_20Minput_JPEG_1280x720_12fps
I (1589) sensor_init: fmt[7].name:DVP_8bit_20Minput_JPEG_1600x1200_12fps
I (1589) sensor_init: fmt[8].name:DVP_8bit_20Minput_RAW8_800x640_15fps
I (1599) sensor_init: fmt[9].name:DVP_8bit_20Minput_RAW8_800x800_15fps
I (1609) sensor_init: fmt[10].name:DVP_8bit_20Minput_RAW8_1024x600_15fps
I (2609) sensor_init: Format in use:DVP_8bit_20Minput_RAW8_1024x600_15fps
```


## 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)
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
idf_component_register(SRCS "camera_dsi_main.c"
idf_component_register(SRCS "dvp_isp_dsi_main.c"
INCLUDE_DIRS "."
REQUIRES esp_mm esp_driver_isp esp_driver_cam esp_driver_i2c dsi_init sensor_init
)
58 changes: 58 additions & 0 deletions examples/peripherals/camera/dvp_isp_dsi/main/Kconfig.projbuild
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
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

config EXAMPLE_CAM_PORT_ISP_DVP
bool
default y

choice EXAMPLE_CAM_HRES
bool "Set camera horizontal resolution"
default EXAMPLE_CAM_HRES_1024 if EXAMPLE_MIPI_DSI_DISP_HRES_1024
default EXAMPLE_CAM_HRES_800 if EXAMPLE_MIPI_DSI_DISP_HRES_800

config EXAMPLE_CAM_HRES_1024
depends on EXAMPLE_MIPI_DSI_DISP_HRES_1024
bool "1024"
config EXAMPLE_CAM_HRES_800
depends on EXAMPLE_MIPI_DSI_DISP_HRES_800
bool "800"
endchoice

config EXAMPLE_CAM_HRES
int
default 1024 if EXAMPLE_CAM_HRES_1024
default 800 if EXAMPLE_CAM_HRES_800

choice EXAMPLE_CAM_VRES
bool "Set camera vertical resolution"
default EXAMPLE_CAM_VRES_600 if EXAMPLE_MIPI_DSI_DISP_VRES_600
default EXAMPLE_CAM_VRES_640 if EXAMPLE_MIPI_DSI_DISP_VRES_1280

config EXAMPLE_CAM_VRES_600
depends on EXAMPLE_MIPI_DSI_DISP_VRES_600
bool "600"
config EXAMPLE_CAM_VRES_640
depends on EXAMPLE_MIPI_DSI_DISP_VRES_1280
bool "640"
config EXAMPLE_CAM_VRES_800
depends on EXAMPLE_MIPI_DSI_DISP_VRES_1280
bool "800"
endchoice

config EXAMPLE_CAM_VRES
int
default 600 if EXAMPLE_CAM_VRES_600
default 640 if EXAMPLE_CAM_VRES_640
default 800 if EXAMPLE_CAM_VRES_800
endmenu
191 changes: 191 additions & 0 deletions examples/peripherals/camera/dvp_isp_dsi/main/dvp_isp_dsi_main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
/*
* SPDX-FileCopyrightText: 2024 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 "driver/isp.h"
#include "esp_cam_ctlr_isp_dvp.h"
#include "esp_cam_ctlr.h"
#include "example_dsi_init.h"
#include "example_dsi_init_config.h"
#include "example_sensor_init.h"
#include "example_config.h"
#include "driver/ledc.h"

static const char *TAG = "dvp_isp_dsi";

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);

// Generate a 20MHz clock for DVP XCLK
static void s_ledc_generate_dvp_xclk(void)
{
ledc_timer_config_t ledc_timer = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.duty_resolution = LEDC_TIMER_1_BIT,
.timer_num = LEDC_TIMER_0,
.freq_hz = EXAMPLE_ISP_DVP_CAM_XCLK_FREQ_HZ, // Set output frequency at 20 MHz
.clk_cfg = LEDC_AUTO_CLK
};
ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));

// Prepare and then apply the LEDC PWM channel configuration
ledc_channel_config_t ledc_channel = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.channel = LEDC_CHANNEL_0,
.timer_sel = LEDC_TIMER_0,
.intr_type = LEDC_INTR_DISABLE,
.gpio_num = EXAMPLE_ISP_DVP_CAM_XCLK_IO,
.duty = 1, // Set duty to 50%
.hpoint = 0
};
ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel));
}

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));

/**
* @background
* Sensor use RAW8
* ISP convert to RGB565
*/
//---------------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_CAM_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, "frame_buffer_size: %zu", frame_buffer_size);
ESP_LOGD(TAG, "frame_buffer: %p", frame_buffer);

esp_cam_ctlr_trans_t cam_trans = {
.buffer = frame_buffer,
.buflen = frame_buffer_size,
};

//--------Camera Sensor and SCCB Init-----------//
s_ledc_generate_dvp_xclk();

example_sensor_config_t cam_sensor_config = {
.i2c_port_num = I2C_NUM_0,
.i2c_sda_io_num = EXAMPLE_ISP_DVP_CAM_SCCB_SDA_IO,
.i2c_scl_io_num = EXAMPLE_ISP_DVP_CAM_SCCB_SCL_IO,
.port = ESP_CAM_SENSOR_DVP,
.format_name = EXAMPLE_CAM_FORMAT,
};
i2c_master_bus_handle_t i2c_bus_handle = NULL;
example_sensor_init(&cam_sensor_config, &i2c_bus_handle);

//---------------ISP Init------------------//
isp_proc_handle_t isp_proc = NULL;
esp_isp_processor_cfg_t isp_config = {
.clk_hz = 80 * 1000 * 1000,
.input_data_source = ISP_INPUT_DATA_SOURCE_DVP,
.input_data_color_type = ISP_COLOR_RAW8,
.output_data_color_type = ISP_COLOR_RGB565,
.has_line_start_packet = false,
.has_line_end_packet = false,
.h_res = CONFIG_EXAMPLE_CAM_HRES,
.v_res = CONFIG_EXAMPLE_CAM_VRES,
};
ESP_ERROR_CHECK(esp_isp_new_processor(&isp_config, &isp_proc));
ESP_ERROR_CHECK(esp_isp_enable(isp_proc));

//----------CAM Controller Init------------//
esp_cam_ctlr_handle_t cam_handle = NULL;
esp_cam_ctlr_isp_dvp_cfg_t dvp_config = {
.data_width = EXAMPLE_ISP_DVP_CAM_DATA_WIDTH,
.data_io = {
EXAMPLE_ISP_DVP_CAM_D0_IO,
EXAMPLE_ISP_DVP_CAM_D1_IO,
EXAMPLE_ISP_DVP_CAM_D2_IO,
EXAMPLE_ISP_DVP_CAM_D3_IO,
EXAMPLE_ISP_DVP_CAM_D4_IO,
EXAMPLE_ISP_DVP_CAM_D5_IO,
EXAMPLE_ISP_DVP_CAM_D6_IO,
EXAMPLE_ISP_DVP_CAM_D7_IO,
},
.pclk_io = EXAMPLE_ISP_DVP_CAM_PCLK_IO,
.hsync_io = EXAMPLE_ISP_DVP_CAM_HSYNC_IO,
.vsync_io = EXAMPLE_ISP_DVP_CAM_VSYNC_IO,
.de_io = EXAMPLE_ISP_DVP_CAM_DE_IO,
.io_flags.vsync_invert = 1,
.queue_items = 10,
};
ret = esp_cam_new_isp_dvp_ctlr(isp_proc, &dvp_config, &cam_handle);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "isp dvp init fail[%d]", ret);
return;
}

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;
}

while (1) {
ESP_ERROR_CHECK(esp_cam_ctlr_receive(cam_handle, &cam_trans, ESP_CAM_CTLR_MAX_DELAY));
}
}

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;
}
55 changes: 55 additions & 0 deletions examples/peripherals/camera/dvp_isp_dsi/main/example_config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* SPDX-FileCopyrightText: 2024 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_ISP_DVP_CAM_SCCB_SCL_IO (33)
#define EXAMPLE_ISP_DVP_CAM_SCCB_SDA_IO (32)

#define EXAMPLE_ISP_DVP_CAM_XCLK_FREQ_HZ (20000000)

#define EXAMPLE_ISP_DVP_CAM_DATA_WIDTH (8)
#define EXAMPLE_ISP_DVP_CAM_D0_IO (8)
#define EXAMPLE_ISP_DVP_CAM_D1_IO (9)
#define EXAMPLE_ISP_DVP_CAM_D2_IO (10)
#define EXAMPLE_ISP_DVP_CAM_D3_IO (4)
#define EXAMPLE_ISP_DVP_CAM_D4_IO (5)
#define EXAMPLE_ISP_DVP_CAM_D5_IO (45)
#define EXAMPLE_ISP_DVP_CAM_D6_IO (46)
#define EXAMPLE_ISP_DVP_CAM_D7_IO (47)
#define EXAMPLE_ISP_DVP_CAM_XCLK_IO (20)
#define EXAMPLE_ISP_DVP_CAM_PCLK_IO (21)
#define EXAMPLE_ISP_DVP_CAM_DE_IO (2)
#define EXAMPLE_ISP_DVP_CAM_VSYNC_IO (23)
#define EXAMPLE_ISP_DVP_CAM_HSYNC_IO (-1)

#if CONFIG_EXAMPLE_CAM_HRES_800

#if CONFIG_EXAMPLE_CAM_VRES_640
#define EXAMPLE_CAM_FORMAT "DVP_8bit_20Minput_RAW8_800x640_15fps"
#elif CONFIG_EXAMPLE_CAM_VRES_800
#define EXAMPLE_CAM_FORMAT "DVP_8bit_20Minput_RAW8_800x800_15fps"
#endif

#elif CONFIG_EXAMPLE_CAM_HRES_1024

#if CONFIG_EXAMPLE_CAM_VRES_600
#define EXAMPLE_CAM_FORMAT "DVP_8bit_20Minput_RAW8_1024x600_15fps"
#endif

#endif

#ifdef __cplusplus
}
#endif
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -6,5 +6,5 @@

@pytest.mark.esp32p4
@pytest.mark.generic
def test_camera_dsi(dut: Dut) -> None:
def test_dvp_isp_dsi(dut: Dut) -> None:
dut.expect_exact('Calling app_main()')
4 changes: 4 additions & 0 deletions examples/peripherals/camera/dvp_isp_dsi/sdkconfig.defaults
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
CONFIG_SPIRAM=y
CONFIG_IDF_EXPERIMENTAL_FEATURES=y
CONFIG_SPIRAM_SPEED_200M=y
CONFIG_CAMERA_OV2640=y
8 changes: 8 additions & 0 deletions examples/peripherals/camera/mipi_isp_dsi/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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(mipi_isp_dsi)
Original file line number Diff line number Diff line change
@@ -2,11 +2,11 @@
| ----------------- | -------- |


# Camera display via DSI example
# MIPI Camera display via DSI example

## Overview

This example demonstrates how to use the esp_driver_cam component to capture 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/versions/0.5.3) and capture camera sensor signals via CSI interface and display it via DSI interface.
This example demonstrates how to use the esp_driver_cam component to capture MIPI-CSI 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/versions/0.5.3) and capture camera sensor signals via CSI interface and display it via DSI interface.

## Usage

@@ -15,7 +15,7 @@ The subsections below give only absolutely necessary information. For full steps

### Hardware Required

- OV5647 or SC2336 camera sensor, or other camera sensors
- OV5647 or SC2336 camera sensor, or other camera sensors with MIPI-CSI port
- EK79007 or ILI9881C LCD screen
- ESP32P4 devkit

@@ -107,6 +107,10 @@ Set CONFIG_CAMERA_OV5647 to y
Set CONFIG_CAMERA_SC2336 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``. Note that the horizontal resolution for the camera should be the same as the LCD screen horizontal resolution.


### Build and Flash

@@ -133,10 +137,10 @@ I (1095) ili9881c: ID1: 0x98, ID2: 0x81, ID3: 0x5c
I (1125) gpio: GPIO[31]| InputEn: 1| OutputEn: 1| OpenDrain: 1| Pullup: 1| Pulldown: 0| Intr:0
I (1125) gpio: GPIO[34]| InputEn: 1| OutputEn: 1| OpenDrain: 1| Pullup: 1| Pulldown: 0| Intr:0
I (1295) ov5647: Detected Camera sensor PID=0x5647 with index 0
I (1305) cam_dsi: fmt[0].name:MIPI_2lane_24Minput_RAW8_800x1280_50fps
I (1305) cam_dsi: fmt[1].name:MIPI_2lane_24Minput_RAW8_800x640_50fps
I (1315) cam_dsi: fmt[2].name:MIPI_2lane_24Minput_RAW8_800x800_50fps
I (1355) cam_dsi: Format in use:MIPI_2lane_24Minput_RAW8_800x640_50fps
I (1305) sensor_init: fmt[0].name:MIPI_2lane_24Minput_RAW8_800x1280_50fps
I (1305) sensor_init: fmt[1].name:MIPI_2lane_24Minput_RAW8_800x640_50fps
I (1315) sensor_init: fmt[2].name:MIPI_2lane_24Minput_RAW8_800x800_50fps
I (1355) sensor_init: Format in use:MIPI_2lane_24Minput_RAW8_800x640_50fps
```


4 changes: 4 additions & 0 deletions examples/peripherals/camera/mipi_isp_dsi/main/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
idf_component_register(SRCS "mipi_isp_dsi_main.c"
INCLUDE_DIRS "."
REQUIRES esp_mm esp_driver_isp esp_driver_cam esp_driver_i2c dsi_init sensor_init
)
Original file line number Diff line number Diff line change
@@ -12,6 +12,10 @@ menu "Example Configuration"
help
Example used LDO voltage, in mV

config EXAMPLE_CAM_PORT_ISP_MIPI
bool
default y

choice EXAMPLE_MIPI_CSI_DISP_HRES
bool "Set MIPI CSI horizontal resolution"
default EXAMPLE_MIPI_CSI_HRES_1024
@@ -35,6 +39,8 @@ menu "Example Configuration"
bool "600"
config EXAMPLE_MIPI_CSI_VRES_640
bool "640"
config EXAMPLE_MIPI_CSI_VRES_800
bool "800"
config EXAMPLE_MIPI_CSI_VRES_1280
bool "1280"
endchoice
@@ -43,5 +49,6 @@ menu "Example Configuration"
int
default 600 if EXAMPLE_MIPI_CSI_VRES_600
default 640 if EXAMPLE_MIPI_CSI_VRES_640
default 800 if EXAMPLE_MIPI_CSI_VRES_800
default 1280 if EXAMPLE_MIPI_CSI_VRES_1280
endmenu
Original file line number Diff line number Diff line change
@@ -12,22 +12,31 @@
extern "C" {
#endif

#define EXAMPLE_CAM_SCCB_FREQ (100000)
#define EXAMPLE_CAM_SCCB_SCL_IO (8)
#define EXAMPLE_CAM_SCCB_SDA_IO (7)
#define EXAMPLE_RGB565_BITS_PER_PIXEL 16
#define EXAMPLE_MIPI_IDI_CLOCK_RATE (50000000)
#define EXAMPLE_MIPI_CSI_LANE_BITRATE_MBPS 200 //line_rate = pclk * 4

#define EXAMPLE_MIPI_CSI_CAM_SCCB_SCL_IO (8)
#define EXAMPLE_MIPI_CSI_CAM_SCCB_SDA_IO (7)

#if CONFIG_EXAMPLE_MIPI_CSI_HRES_800

#if CONFIG_EXAMPLE_MIPI_CSI_VRES_640
#define EXAMPLE_CAM_FORMAT "MIPI_2lane_24Minput_RAW8_800x640_50fps"
#else
#elif CONFIG_EXAMPLE_MIPI_CSI_VRES_800
#define EXAMPLE_CAM_FORMAT "MIPI_2lane_24Minput_RAW8_800x800_50fps"
#elif CONFIG_EXAMPLE_MIPI_CSI_VRES_1280
#define EXAMPLE_CAM_FORMAT "MIPI_2lane_24Minput_RAW8_800x1280_50fps"
#endif
#endif

#if CONFIG_EXAMPLE_MIPI_CSI_HRES_1024
#elif CONFIG_EXAMPLE_MIPI_CSI_HRES_1024

#if CONFIG_EXAMPLE_MIPI_CSI_VRES_600
#define EXAMPLE_CAM_FORMAT "MIPI_2lane_24Minput_RAW8_1024x600_30fps"
#endif

#endif

#ifdef __cplusplus
}
#endif
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -23,7 +23,7 @@
#include "example_sensor_init.h"
#include "example_config.h"

static const char *TAG = "cam_dsi";
static const char *TAG = "mipi_isp_dsi";

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);
@@ -56,7 +56,7 @@ void app_main(void)
//---------------Necessary variable config------------------//
frame_buffer_size = CONFIG_EXAMPLE_MIPI_CSI_DISP_HRES * CONFIG_EXAMPLE_MIPI_DSI_DISP_VRES * EXAMPLE_RGB565_BITS_PER_PIXEL / 8;

ESP_LOGD(TAG, "CONFIG_EXAMPLE_MIPI_CSI_DISP_HRES: %d, CONFIG_EXAMPLE_MIPI_DSI_DISP_VRES: %d, bits per pixel: %d", CONFIG_EXAMPLE_MIPI_CSI_DISP_HRES, CONFIG_EXAMPLE_MIPI_DSI_DISP_VRES, 8);
ESP_LOGD(TAG, "CONFIG_EXAMPLE_MIPI_CSI_DISP_HRES: %d, CONFIG_EXAMPLE_MIPI_DSI_DISP_VRES: %d, bits per pixel: %d", CONFIG_EXAMPLE_MIPI_CSI_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);

@@ -67,7 +67,14 @@ void app_main(void)

//--------Camera Sensor and SCCB Init-----------//
i2c_master_bus_handle_t i2c_bus_handle = NULL;
example_sensor_init(I2C_NUM_0, &i2c_bus_handle);
example_sensor_config_t cam_sensor_config = {
.i2c_port_num = I2C_NUM_0,
.i2c_sda_io_num = EXAMPLE_MIPI_CSI_CAM_SCCB_SDA_IO,
.i2c_scl_io_num = EXAMPLE_MIPI_CSI_CAM_SCCB_SCL_IO,
.port = ESP_CAM_SENSOR_MIPI_CSI,
.format_name = EXAMPLE_CAM_FORMAT,
};
example_sensor_init(&cam_sensor_config, &i2c_bus_handle);

//---------------CSI Init------------------//
esp_cam_ctlr_csi_config_t csi_config = {
10 changes: 10 additions & 0 deletions examples/peripherals/camera/mipi_isp_dsi/pytest_mipi_isp_dsi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import pytest
from pytest_embedded import Dut


@pytest.mark.esp32p4
@pytest.mark.generic
def test_mipi_isp_dsi(dut: Dut) -> None:
dut.expect_exact('Calling app_main()')
4 changes: 4 additions & 0 deletions examples/peripherals/isp/multi_pipelines/README.md
Original file line number Diff line number Diff line change
@@ -116,6 +116,10 @@ Set CONFIG_CAMERA_OV5647 to y
Set CONFIG_CAMERA_SC2336 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``. Note that the horizontal resolution for the camera should be the same as the LCD screen horizontal resolution.


### Build and Flash

20 changes: 20 additions & 0 deletions examples/peripherals/isp/multi_pipelines/main/example_config.h
Original file line number Diff line number Diff line change
@@ -14,6 +14,26 @@ extern "C" {
#define EXAMPLE_MIPI_SCCB_FREQ (100000)
#define EXAMPLE_MIPI_CSI_LANE_BITRATE_MBPS 200 //line_rate = pclk * 4

#define EXAMPLE_MIPI_CSI_CAM_SCCB_SCL_IO (8)
#define EXAMPLE_MIPI_CSI_CAM_SCCB_SDA_IO (7)

#if CONFIG_EXAMPLE_MIPI_CSI_HRES_800

#if CONFIG_EXAMPLE_MIPI_CSI_VRES_640
#define EXAMPLE_CAM_FORMAT "MIPI_2lane_24Minput_RAW8_800x640_50fps"
#elif CONFIG_EXAMPLE_MIPI_CSI_VRES_800
#define EXAMPLE_CAM_FORMAT "MIPI_2lane_24Minput_RAW8_800x800_50fps"
#elif CONFIG_EXAMPLE_MIPI_CSI_VRES_1280
#define EXAMPLE_CAM_FORMAT "MIPI_2lane_24Minput_RAW8_800x1280_50fps"
#endif

#elif CONFIG_EXAMPLE_MIPI_CSI_HRES_1024

#if CONFIG_EXAMPLE_MIPI_CSI_VRES_600
#define EXAMPLE_CAM_FORMAT "MIPI_2lane_24Minput_RAW8_1024x600_30fps"
#endif

#endif
#define EXAMPLE_DW9714_DEV_ADDR 0xC
#ifdef __cplusplus
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
dependencies:
espressif/esp_cam_sensor: "^0.5.*"
espressif/esp_cam_sensor: ">=0.5.*"
idf:
version: ">=5.3.0"
isp_af_schemes:
path: ${IDF_PATH}/examples/peripherals/isp/multi_pipelines/components/isp_af_schemes
dsi_init:
path: ${IDF_PATH}/examples/peripherals/camera/camera_dsi/components/dsi_init
path: ${IDF_PATH}/examples/peripherals/camera/common_components/dsi_init
sensor_init:
path: ${IDF_PATH}/examples/peripherals/camera/camera_dsi/components/sensor_init
path: ${IDF_PATH}/examples/peripherals/camera/common_components/sensor_init
9 changes: 8 additions & 1 deletion examples/peripherals/isp/multi_pipelines/main/isp_dsi_main.c
Original file line number Diff line number Diff line change
@@ -224,7 +224,14 @@ void app_main(void)

//--------Camera Sensor and SCCB Init-----------//
i2c_master_bus_handle_t i2c_bus_handle = NULL;
example_sensor_init(I2C_NUM_0, &i2c_bus_handle);
example_sensor_config_t cam_sensor_config = {
.i2c_port_num = I2C_NUM_0,
.i2c_sda_io_num = EXAMPLE_MIPI_CSI_CAM_SCCB_SDA_IO,
.i2c_scl_io_num = EXAMPLE_MIPI_CSI_CAM_SCCB_SCL_IO,
.port = ESP_CAM_SENSOR_MIPI_CSI,
.format_name = EXAMPLE_CAM_FORMAT,
};
example_sensor_init(&cam_sensor_config, &i2c_bus_handle);

//---------------VCM SCCB Init------------------//
esp_sccb_io_handle_t dw9714_io_handle = NULL;
2 changes: 1 addition & 1 deletion examples/peripherals/ppa/ppa_dsi/main/idf_component.yml
Original file line number Diff line number Diff line change
@@ -2,5 +2,5 @@ dependencies:
idf:
version: ">=5.3.0"
dsi_init:
path: ${IDF_PATH}/examples/peripherals/camera/camera_dsi/components/dsi_init
path: ${IDF_PATH}/examples/peripherals/camera/common_components/dsi_init
esp_jpeg: ">=1.0.2"

0 comments on commit 0d68aa8

Please sign in to comment.