From ff0f9cd6490d37a19b9a079e463a0f0709e8e1fa Mon Sep 17 00:00:00 2001 From: Song Ruo Jing Date: Tue, 26 Nov 2024 15:23:20 +0800 Subject: [PATCH 1/2] feat(dvp_isp_dsi_example): add an example shows DVP-ISP-DSI combination --- .../isp_dvp/src/esp_cam_ctlr_isp_dvp.c | 8 +- components/hal/esp32p4/include/hal/isp_ll.h | 8 +- .../peripherals/camera_driver.rst | 6 + examples/peripherals/.build-test-rules.yml | 9 +- .../sensor_init/include/example_sensor_init.h | 25 --- .../camera/camera_dsi/main/idf_component.yml | 7 - .../dsi_init/CMakeLists.txt | 0 .../dsi_init/Kconfig.projbuild | 0 .../dsi_init/example_dsi_init.c | 0 .../dsi_init/idf_component.yml | 0 .../dsi_init/include/example_dsi_init.h | 0 .../include/example_dsi_init_config.h | 0 .../sensor_init/CMakeLists.txt | 1 + .../sensor_init/example_sensor_init.c | 20 +- .../sensor_init/idf_component.yml | 2 +- .../sensor_init/include/example_sensor_init.h | 37 ++++ .../include/example_sensor_init_config.h} | 4 +- .../CMakeLists.txt | 2 +- .../peripherals/camera/dvp_isp_dsi/README.md | 154 ++++++++++++++ .../main/CMakeLists.txt | 2 +- .../camera/dvp_isp_dsi/main/Kconfig.projbuild | 58 ++++++ .../dvp_isp_dsi/main/dvp_isp_dsi_main.c | 191 ++++++++++++++++++ .../camera/dvp_isp_dsi/main/example_config.h | 55 +++++ .../camera/dvp_isp_dsi/main/idf_component.yml | 7 + .../pytest_dvp_isp_dsi.py} | 2 +- .../camera/dvp_isp_dsi/sdkconfig.defaults | 4 + .../camera/mipi_isp_dsi/CMakeLists.txt | 6 + .../{camera_dsi => mipi_isp_dsi}/README.md | 18 +- .../camera/mipi_isp_dsi/main/CMakeLists.txt | 4 + .../main/Kconfig.projbuild | 7 + .../main/example_config.h} | 21 +- .../mipi_isp_dsi/main/idf_component.yml | 7 + .../main/mipi_isp_dsi_main.c} | 13 +- .../mipi_isp_dsi/pytest_mipi_isp_dsi.py | 10 + .../sdkconfig.defaults | 0 examples/peripherals/isp/auto_focus/README.md | 4 + .../isp/auto_focus/main/example_config.h | 20 ++ .../isp/auto_focus/main/idf_component.yml | 6 +- .../isp/auto_focus/main/isp_af_dsi_main.c | 9 +- 39 files changed, 648 insertions(+), 79 deletions(-) delete mode 100644 examples/peripherals/camera/camera_dsi/components/sensor_init/include/example_sensor_init.h delete mode 100644 examples/peripherals/camera/camera_dsi/main/idf_component.yml rename examples/peripherals/camera/{camera_dsi/components => common_components}/dsi_init/CMakeLists.txt (100%) rename examples/peripherals/camera/{camera_dsi/components => common_components}/dsi_init/Kconfig.projbuild (100%) rename examples/peripherals/camera/{camera_dsi/components => common_components}/dsi_init/example_dsi_init.c (100%) rename examples/peripherals/camera/{camera_dsi/components => common_components}/dsi_init/idf_component.yml (100%) rename examples/peripherals/camera/{camera_dsi/components => common_components}/dsi_init/include/example_dsi_init.h (100%) rename examples/peripherals/camera/{camera_dsi/components => common_components}/dsi_init/include/example_dsi_init_config.h (100%) rename examples/peripherals/camera/{camera_dsi/components => common_components}/sensor_init/CMakeLists.txt (72%) rename examples/peripherals/camera/{camera_dsi/components => common_components}/sensor_init/example_sensor_init.c (85%) rename examples/peripherals/camera/{camera_dsi/components => common_components}/sensor_init/idf_component.yml (54%) create mode 100644 examples/peripherals/camera/common_components/sensor_init/include/example_sensor_init.h rename examples/peripherals/camera/{camera_dsi/main/example_config.h => common_components/sensor_init/include/example_sensor_init_config.h} (52%) rename examples/peripherals/camera/{camera_dsi => dvp_isp_dsi}/CMakeLists.txt (91%) create mode 100644 examples/peripherals/camera/dvp_isp_dsi/README.md rename examples/peripherals/camera/{camera_dsi => dvp_isp_dsi}/main/CMakeLists.txt (77%) create mode 100644 examples/peripherals/camera/dvp_isp_dsi/main/Kconfig.projbuild create mode 100644 examples/peripherals/camera/dvp_isp_dsi/main/dvp_isp_dsi_main.c create mode 100644 examples/peripherals/camera/dvp_isp_dsi/main/example_config.h create mode 100644 examples/peripherals/camera/dvp_isp_dsi/main/idf_component.yml rename examples/peripherals/camera/{camera_dsi/pytest_camera_dsi.py => dvp_isp_dsi/pytest_dvp_isp_dsi.py} (85%) create mode 100644 examples/peripherals/camera/dvp_isp_dsi/sdkconfig.defaults create mode 100644 examples/peripherals/camera/mipi_isp_dsi/CMakeLists.txt rename examples/peripherals/camera/{camera_dsi => mipi_isp_dsi}/README.md (90%) create mode 100644 examples/peripherals/camera/mipi_isp_dsi/main/CMakeLists.txt rename examples/peripherals/camera/{camera_dsi => mipi_isp_dsi}/main/Kconfig.projbuild (88%) rename examples/peripherals/camera/{camera_dsi/components/sensor_init/include/example_sensor_init_config.h => mipi_isp_dsi/main/example_config.h} (52%) create mode 100644 examples/peripherals/camera/mipi_isp_dsi/main/idf_component.yml rename examples/peripherals/camera/{camera_dsi/main/camera_dsi_main.c => mipi_isp_dsi/main/mipi_isp_dsi_main.c} (91%) create mode 100644 examples/peripherals/camera/mipi_isp_dsi/pytest_mipi_isp_dsi.py rename examples/peripherals/camera/{camera_dsi => mipi_isp_dsi}/sdkconfig.defaults (100%) diff --git a/components/esp_driver_cam/isp_dvp/src/esp_cam_ctlr_isp_dvp.c b/components/esp_driver_cam/isp_dvp/src/esp_cam_ctlr_isp_dvp.c index 10446d3749..dc41abbb2c 100644 --- a/components/esp_driver_cam/isp_dvp/src/esp_cam_ctlr_isp_dvp.c +++ b/components/esp_driver_cam/isp_dvp/src/esp_cam_ctlr_isp_dvp.c @@ -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); diff --git a/components/hal/esp32p4/include/hal/isp_ll.h b/components/hal/esp32p4/include/hal/isp_ll.h index 8792659fcb..29a722612d 100644 --- a/components/hal/esp32p4/include/hal/isp_ll.h +++ b/components/hal/esp32p4/include/hal/isp_ll.h @@ -361,15 +361,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: diff --git a/docs/en/api-reference/peripherals/camera_driver.rst b/docs/en/api-reference/peripherals/camera_driver.rst index bc9bec1c57..2474a25129 100644 --- a/docs/en/api-reference/peripherals/camera_driver.rst +++ b/docs/en/api-reference/peripherals/camera_driver.rst @@ -152,6 +152,12 @@ There is a Kconfig option :ref:`CONFIG_CAM_CTLR_MIPI_CSI_ISR_IRAM_SAFE` that: This allows the interrupt to run while the cache is disabled, but comes at the cost of increased IRAM consumption. So user callbacks need to notice that the code and data inside (the callback) should be IRAM-safe or DRAM-safe, when cache is disabled. +Application Examples +-------------------- + +* :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 ------------- diff --git a/examples/peripherals/.build-test-rules.yml b/examples/peripherals/.build-test-rules.yml index 90f7b2c6a1..37aead171f 100644 --- a/examples/peripherals/.build-test-rules.yml +++ b/examples/peripherals/.build-test-rules.yml @@ -32,7 +32,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: diff --git a/examples/peripherals/camera/camera_dsi/components/sensor_init/include/example_sensor_init.h b/examples/peripherals/camera/camera_dsi/components/sensor_init/include/example_sensor_init.h deleted file mode 100644 index c2e1db3d31..0000000000 --- a/examples/peripherals/camera/camera_dsi/components/sensor_init/include/example_sensor_init.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#include "driver/i2c_master.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief SCCB Interface and Sensor Init - * - * @param[in] i2c_port I2C port - * @param[out] out_i2c_bus_handle I2C bus handle - */ -void example_sensor_init(int i2c_port, i2c_master_bus_handle_t *out_i2c_bus_handle); - -#ifdef __cplusplus -} -#endif diff --git a/examples/peripherals/camera/camera_dsi/main/idf_component.yml b/examples/peripherals/camera/camera_dsi/main/idf_component.yml deleted file mode 100644 index 363caa48c9..0000000000 --- a/examples/peripherals/camera/camera_dsi/main/idf_component.yml +++ /dev/null @@ -1,7 +0,0 @@ -dependencies: - idf: - version: ">=5.3.0" - dsi_init: - path: ${IDF_PATH}/examples/peripherals/camera/camera_dsi/components/dsi_init - sensor_init: - path: ${IDF_PATH}/examples/peripherals/camera/camera_dsi/components/sensor_init diff --git a/examples/peripherals/camera/camera_dsi/components/dsi_init/CMakeLists.txt b/examples/peripherals/camera/common_components/dsi_init/CMakeLists.txt similarity index 100% rename from examples/peripherals/camera/camera_dsi/components/dsi_init/CMakeLists.txt rename to examples/peripherals/camera/common_components/dsi_init/CMakeLists.txt diff --git a/examples/peripherals/camera/camera_dsi/components/dsi_init/Kconfig.projbuild b/examples/peripherals/camera/common_components/dsi_init/Kconfig.projbuild similarity index 100% rename from examples/peripherals/camera/camera_dsi/components/dsi_init/Kconfig.projbuild rename to examples/peripherals/camera/common_components/dsi_init/Kconfig.projbuild diff --git a/examples/peripherals/camera/camera_dsi/components/dsi_init/example_dsi_init.c b/examples/peripherals/camera/common_components/dsi_init/example_dsi_init.c similarity index 100% rename from examples/peripherals/camera/camera_dsi/components/dsi_init/example_dsi_init.c rename to examples/peripherals/camera/common_components/dsi_init/example_dsi_init.c diff --git a/examples/peripherals/camera/camera_dsi/components/dsi_init/idf_component.yml b/examples/peripherals/camera/common_components/dsi_init/idf_component.yml similarity index 100% rename from examples/peripherals/camera/camera_dsi/components/dsi_init/idf_component.yml rename to examples/peripherals/camera/common_components/dsi_init/idf_component.yml diff --git a/examples/peripherals/camera/camera_dsi/components/dsi_init/include/example_dsi_init.h b/examples/peripherals/camera/common_components/dsi_init/include/example_dsi_init.h similarity index 100% rename from examples/peripherals/camera/camera_dsi/components/dsi_init/include/example_dsi_init.h rename to examples/peripherals/camera/common_components/dsi_init/include/example_dsi_init.h diff --git a/examples/peripherals/camera/camera_dsi/components/dsi_init/include/example_dsi_init_config.h b/examples/peripherals/camera/common_components/dsi_init/include/example_dsi_init_config.h similarity index 100% rename from examples/peripherals/camera/camera_dsi/components/dsi_init/include/example_dsi_init_config.h rename to examples/peripherals/camera/common_components/dsi_init/include/example_dsi_init_config.h diff --git a/examples/peripherals/camera/camera_dsi/components/sensor_init/CMakeLists.txt b/examples/peripherals/camera/common_components/sensor_init/CMakeLists.txt similarity index 72% rename from examples/peripherals/camera/camera_dsi/components/sensor_init/CMakeLists.txt rename to examples/peripherals/camera/common_components/sensor_init/CMakeLists.txt index 6fb9927a89..474d6f8187 100644 --- a/examples/peripherals/camera/camera_dsi/components/sensor_init/CMakeLists.txt +++ b/examples/peripherals/camera/common_components/sensor_init/CMakeLists.txt @@ -1,3 +1,4 @@ idf_component_register(SRCS "example_sensor_init.c" INCLUDE_DIRS "include" + REQUIRES esp_cam_sensor ) diff --git a/examples/peripherals/camera/camera_dsi/components/sensor_init/example_sensor_init.c b/examples/peripherals/camera/common_components/sensor_init/example_sensor_init.c similarity index 85% rename from examples/peripherals/camera/camera_dsi/components/sensor_init/example_sensor_init.c rename to examples/peripherals/camera/common_components/sensor_init/example_sensor_init.c index 89346eee92..77a6f6636c 100644 --- a/examples/peripherals/camera/camera_dsi/components/sensor_init/example_sensor_init.c +++ b/examples/peripherals/camera/common_components/sensor_init/example_sensor_init.c @@ -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]); } } diff --git a/examples/peripherals/camera/camera_dsi/components/sensor_init/idf_component.yml b/examples/peripherals/camera/common_components/sensor_init/idf_component.yml similarity index 54% rename from examples/peripherals/camera/camera_dsi/components/sensor_init/idf_component.yml rename to examples/peripherals/camera/common_components/sensor_init/idf_component.yml index fbd8f4b028..1881aa5e99 100644 --- a/examples/peripherals/camera/camera_dsi/components/sensor_init/idf_component.yml +++ b/examples/peripherals/camera/common_components/sensor_init/idf_component.yml @@ -1,4 +1,4 @@ dependencies: - espressif/esp_cam_sensor: "^0.5.1" + espressif/esp_cam_sensor: "^0.6.1" idf: version: ">=5.3.0" diff --git a/examples/peripherals/camera/common_components/sensor_init/include/example_sensor_init.h b/examples/peripherals/camera/common_components/sensor_init/include/example_sensor_init.h new file mode 100644 index 0000000000..866cb3dd95 --- /dev/null +++ b/examples/peripherals/camera/common_components/sensor_init/include/example_sensor_init.h @@ -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 diff --git a/examples/peripherals/camera/camera_dsi/main/example_config.h b/examples/peripherals/camera/common_components/sensor_init/include/example_sensor_init_config.h similarity index 52% rename from examples/peripherals/camera/camera_dsi/main/example_config.h rename to examples/peripherals/camera/common_components/sensor_init/include/example_sensor_init_config.h index 8e5ad61cdf..dd3acc4720 100644 --- a/examples/peripherals/camera/camera_dsi/main/example_config.h +++ b/examples/peripherals/camera/common_components/sensor_init/include/example_sensor_init_config.h @@ -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 } diff --git a/examples/peripherals/camera/camera_dsi/CMakeLists.txt b/examples/peripherals/camera/dvp_isp_dsi/CMakeLists.txt similarity index 91% rename from examples/peripherals/camera/camera_dsi/CMakeLists.txt rename to examples/peripherals/camera/dvp_isp_dsi/CMakeLists.txt index 69a158b554..1b4e474205 100644 --- a/examples/peripherals/camera/camera_dsi/CMakeLists.txt +++ b/examples/peripherals/camera/dvp_isp_dsi/CMakeLists.txt @@ -3,4 +3,4 @@ cmake_minimum_required(VERSION 3.16) include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(camera_dsi) +project(dvp_isp_dsi) diff --git a/examples/peripherals/camera/dvp_isp_dsi/README.md b/examples/peripherals/camera/dvp_isp_dsi/README.md new file mode 100644 index 0000000000..dda9ad49a5 --- /dev/null +++ b/examples/peripherals/camera/dvp_isp_dsi/README.md @@ -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 +``` + +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) diff --git a/examples/peripherals/camera/camera_dsi/main/CMakeLists.txt b/examples/peripherals/camera/dvp_isp_dsi/main/CMakeLists.txt similarity index 77% rename from examples/peripherals/camera/camera_dsi/main/CMakeLists.txt rename to examples/peripherals/camera/dvp_isp_dsi/main/CMakeLists.txt index 545dc327d2..fa1f8c83b6 100644 --- a/examples/peripherals/camera/camera_dsi/main/CMakeLists.txt +++ b/examples/peripherals/camera/dvp_isp_dsi/main/CMakeLists.txt @@ -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 ) diff --git a/examples/peripherals/camera/dvp_isp_dsi/main/Kconfig.projbuild b/examples/peripherals/camera/dvp_isp_dsi/main/Kconfig.projbuild new file mode 100644 index 0000000000..9366f21f79 --- /dev/null +++ b/examples/peripherals/camera/dvp_isp_dsi/main/Kconfig.projbuild @@ -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 diff --git a/examples/peripherals/camera/dvp_isp_dsi/main/dvp_isp_dsi_main.c b/examples/peripherals/camera/dvp_isp_dsi/main/dvp_isp_dsi_main.c new file mode 100644 index 0000000000..144be169e6 --- /dev/null +++ b/examples/peripherals/camera/dvp_isp_dsi/main/dvp_isp_dsi_main.c @@ -0,0 +1,191 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#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; +} diff --git a/examples/peripherals/camera/dvp_isp_dsi/main/example_config.h b/examples/peripherals/camera/dvp_isp_dsi/main/example_config.h new file mode 100644 index 0000000000..0bf8bd5941 --- /dev/null +++ b/examples/peripherals/camera/dvp_isp_dsi/main/example_config.h @@ -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 diff --git a/examples/peripherals/camera/dvp_isp_dsi/main/idf_component.yml b/examples/peripherals/camera/dvp_isp_dsi/main/idf_component.yml new file mode 100644 index 0000000000..5aeb9ac3f5 --- /dev/null +++ b/examples/peripherals/camera/dvp_isp_dsi/main/idf_component.yml @@ -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 diff --git a/examples/peripherals/camera/camera_dsi/pytest_camera_dsi.py b/examples/peripherals/camera/dvp_isp_dsi/pytest_dvp_isp_dsi.py similarity index 85% rename from examples/peripherals/camera/camera_dsi/pytest_camera_dsi.py rename to examples/peripherals/camera/dvp_isp_dsi/pytest_dvp_isp_dsi.py index 9c234e6217..7eb81af001 100644 --- a/examples/peripherals/camera/camera_dsi/pytest_camera_dsi.py +++ b/examples/peripherals/camera/dvp_isp_dsi/pytest_dvp_isp_dsi.py @@ -6,5 +6,5 @@ from pytest_embedded import Dut @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()') diff --git a/examples/peripherals/camera/dvp_isp_dsi/sdkconfig.defaults b/examples/peripherals/camera/dvp_isp_dsi/sdkconfig.defaults new file mode 100644 index 0000000000..3e05d2e5e6 --- /dev/null +++ b/examples/peripherals/camera/dvp_isp_dsi/sdkconfig.defaults @@ -0,0 +1,4 @@ +CONFIG_SPIRAM=y +CONFIG_IDF_EXPERIMENTAL_FEATURES=y +CONFIG_SPIRAM_SPEED_200M=y +CONFIG_CAMERA_OV2640=y diff --git a/examples/peripherals/camera/mipi_isp_dsi/CMakeLists.txt b/examples/peripherals/camera/mipi_isp_dsi/CMakeLists.txt new file mode 100644 index 0000000000..fe1f36f8df --- /dev/null +++ b/examples/peripherals/camera/mipi_isp_dsi/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(mipi_isp_dsi) diff --git a/examples/peripherals/camera/camera_dsi/README.md b/examples/peripherals/camera/mipi_isp_dsi/README.md similarity index 90% rename from examples/peripherals/camera/camera_dsi/README.md rename to examples/peripherals/camera/mipi_isp_dsi/README.md index 60a3d9d2b4..d8394550fb 100644 --- a/examples/peripherals/camera/camera_dsi/README.md +++ b/examples/peripherals/camera/mipi_isp_dsi/README.md @@ -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 ``` diff --git a/examples/peripherals/camera/mipi_isp_dsi/main/CMakeLists.txt b/examples/peripherals/camera/mipi_isp_dsi/main/CMakeLists.txt new file mode 100644 index 0000000000..f0896c32b3 --- /dev/null +++ b/examples/peripherals/camera/mipi_isp_dsi/main/CMakeLists.txt @@ -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 + ) diff --git a/examples/peripherals/camera/camera_dsi/main/Kconfig.projbuild b/examples/peripherals/camera/mipi_isp_dsi/main/Kconfig.projbuild similarity index 88% rename from examples/peripherals/camera/camera_dsi/main/Kconfig.projbuild rename to examples/peripherals/camera/mipi_isp_dsi/main/Kconfig.projbuild index 98a42e128a..d2d601b230 100644 --- a/examples/peripherals/camera/camera_dsi/main/Kconfig.projbuild +++ b/examples/peripherals/camera/mipi_isp_dsi/main/Kconfig.projbuild @@ -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 diff --git a/examples/peripherals/camera/camera_dsi/components/sensor_init/include/example_sensor_init_config.h b/examples/peripherals/camera/mipi_isp_dsi/main/example_config.h similarity index 52% rename from examples/peripherals/camera/camera_dsi/components/sensor_init/include/example_sensor_init_config.h rename to examples/peripherals/camera/mipi_isp_dsi/main/example_config.h index 889122dbe1..570ebdc866 100644 --- a/examples/peripherals/camera/camera_dsi/components/sensor_init/include/example_sensor_init_config.h +++ b/examples/peripherals/camera/mipi_isp_dsi/main/example_config.h @@ -12,20 +12,29 @@ 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 + +#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 -#if CONFIG_EXAMPLE_MIPI_CSI_HRES_1024 -#define EXAMPLE_CAM_FORMAT "MIPI_2lane_24Minput_RAW8_1024x600_30fps" #endif #ifdef __cplusplus diff --git a/examples/peripherals/camera/mipi_isp_dsi/main/idf_component.yml b/examples/peripherals/camera/mipi_isp_dsi/main/idf_component.yml new file mode 100644 index 0000000000..5aeb9ac3f5 --- /dev/null +++ b/examples/peripherals/camera/mipi_isp_dsi/main/idf_component.yml @@ -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 diff --git a/examples/peripherals/camera/camera_dsi/main/camera_dsi_main.c b/examples/peripherals/camera/mipi_isp_dsi/main/mipi_isp_dsi_main.c similarity index 91% rename from examples/peripherals/camera/camera_dsi/main/camera_dsi_main.c rename to examples/peripherals/camera/mipi_isp_dsi/main/mipi_isp_dsi_main.c index ae8f0e2443..34ef7368e0 100644 --- a/examples/peripherals/camera/camera_dsi/main/camera_dsi_main.c +++ b/examples/peripherals/camera/mipi_isp_dsi/main/mipi_isp_dsi_main.c @@ -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 = { diff --git a/examples/peripherals/camera/mipi_isp_dsi/pytest_mipi_isp_dsi.py b/examples/peripherals/camera/mipi_isp_dsi/pytest_mipi_isp_dsi.py new file mode 100644 index 0000000000..44da4af5ef --- /dev/null +++ b/examples/peripherals/camera/mipi_isp_dsi/pytest_mipi_isp_dsi.py @@ -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()') diff --git a/examples/peripherals/camera/camera_dsi/sdkconfig.defaults b/examples/peripherals/camera/mipi_isp_dsi/sdkconfig.defaults similarity index 100% rename from examples/peripherals/camera/camera_dsi/sdkconfig.defaults rename to examples/peripherals/camera/mipi_isp_dsi/sdkconfig.defaults diff --git a/examples/peripherals/isp/auto_focus/README.md b/examples/peripherals/isp/auto_focus/README.md index 19d7e82965..242efee4d6 100644 --- a/examples/peripherals/isp/auto_focus/README.md +++ b/examples/peripherals/isp/auto_focus/README.md @@ -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 diff --git a/examples/peripherals/isp/auto_focus/main/example_config.h b/examples/peripherals/isp/auto_focus/main/example_config.h index 00775fd4c4..9c5482fe39 100644 --- a/examples/peripherals/isp/auto_focus/main/example_config.h +++ b/examples/peripherals/isp/auto_focus/main/example_config.h @@ -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 } diff --git a/examples/peripherals/isp/auto_focus/main/idf_component.yml b/examples/peripherals/isp/auto_focus/main/idf_component.yml index f67336dee2..3c5afe53fd 100644 --- a/examples/peripherals/isp/auto_focus/main/idf_component.yml +++ b/examples/peripherals/isp/auto_focus/main/idf_component.yml @@ -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/auto_focus/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 diff --git a/examples/peripherals/isp/auto_focus/main/isp_af_dsi_main.c b/examples/peripherals/isp/auto_focus/main/isp_af_dsi_main.c index 0ea053802c..a9ed397f8a 100644 --- a/examples/peripherals/isp/auto_focus/main/isp_af_dsi_main.c +++ b/examples/peripherals/isp/auto_focus/main/isp_af_dsi_main.c @@ -215,7 +215,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; From ce22a85cebba7d2550802cf7a6a78b9abad342b6 Mon Sep 17 00:00:00 2001 From: Song Ruo Jing Date: Tue, 10 Dec 2024 14:39:47 +0800 Subject: [PATCH 2/2] fix(isp): isp_dvp raw->rgb needs a workaround --- components/esp_driver_isp/src/isp_core.c | 4 ++++ components/hal/esp32p4/include/hal/isp_ll.h | 8 ++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/components/esp_driver_isp/src/isp_core.c b/components/esp_driver_isp/src/isp_core.c index 8fbf9e5f66..b69419f26d 100644 --- a/components/esp_driver_isp/src/isp_core.c +++ b/components/esp_driver_isp/src/isp_core.c @@ -135,6 +135,10 @@ esp_err_t esp_isp_new_processor(const esp_isp_processor_cfg_t *proc_config, isp_ isp_ll_set_intput_data_h_pixel_num(proc->hal.hw, proc_config->h_res); isp_ll_set_intput_data_v_row_num(proc->hal.hw, proc_config->v_res); + if (out_color_format.color_space == COLOR_SPACE_RGB && proc_config->input_data_source == ISP_INPUT_DATA_SOURCE_DVP) { + isp_ll_color_enable(proc->hal.hw, true); // workaround for DIG-474 + } + proc->in_color_format = in_color_format; proc->out_color_format = out_color_format; proc->h_res = proc_config->h_res; diff --git a/components/hal/esp32p4/include/hal/isp_ll.h b/components/hal/esp32p4/include/hal/isp_ll.h index 29a722612d..8792659fcb 100644 --- a/components/hal/esp32p4/include/hal/isp_ll.h +++ b/components/hal/esp32p4/include/hal/isp_ll.h @@ -361,15 +361,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 = 0; - hw->cntl.yuv2rgb_en = 0; + hw->cntl.rgb2yuv_en = 1; + hw->cntl.yuv2rgb_en = 1; valid = true; break; case COLOR_PIXEL_RGB565: hw->cntl.isp_out_type = 4; hw->cntl.demosaic_en = 1; - hw->cntl.rgb2yuv_en = 0; - hw->cntl.yuv2rgb_en = 0; + hw->cntl.rgb2yuv_en = 1; + hw->cntl.yuv2rgb_en = 1; valid = true; break; default: