From 8b4d46aa4675cc57bed29c6377d3b6807165c60b Mon Sep 17 00:00:00 2001 From: Song Ruo Jing Date: Thu, 17 Apr 2025 19:20:54 +0800 Subject: [PATCH] feat(isp_dvp): add SC030IOT camera support to dvp_isp_dsi example --- .../isp_dvp/include/esp_cam_ctlr_isp_dvp.h | 8 ++-- .../dsi_init/Kconfig.projbuild | 7 ++++ .../dsi_init/example_dsi_init.c | 6 ++- .../sensor_init/example_sensor_init.c | 4 ++ .../peripherals/camera/dvp_isp_dsi/README.md | 4 +- .../camera/dvp_isp_dsi/main/Kconfig.projbuild | 26 ++++++++---- .../dvp_isp_dsi/main/dvp_isp_dsi_main.c | 41 ++++++++++++++++--- .../camera/dvp_isp_dsi/main/example_config.h | 32 ++++++++++----- .../camera/dvp_isp_dsi/sdkconfig.defaults | 5 +-- .../dvp_isp_dsi/sdkconfig.defaults.esp32p4 | 3 ++ .../camera/mipi_isp_dsi/sdkconfig.defaults | 3 -- .../mipi_isp_dsi/sdkconfig.defaults.esp32p4 | 3 ++ 12 files changed, 103 insertions(+), 39 deletions(-) create mode 100644 examples/peripherals/camera/dvp_isp_dsi/sdkconfig.defaults.esp32p4 create mode 100644 examples/peripherals/camera/mipi_isp_dsi/sdkconfig.defaults.esp32p4 diff --git a/components/esp_driver_cam/isp_dvp/include/esp_cam_ctlr_isp_dvp.h b/components/esp_driver_cam/isp_dvp/include/esp_cam_ctlr_isp_dvp.h index 10861262fa..6921ed0f23 100644 --- a/components/esp_driver_cam/isp_dvp/include/esp_cam_ctlr_isp_dvp.h +++ b/components/esp_driver_cam/isp_dvp/include/esp_cam_ctlr_isp_dvp.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -28,9 +28,9 @@ typedef struct { int de_io; ///< ISP DVP de IO numbers struct { uint32_t pclk_invert: 1; ///< The pclk is inverted - uint32_t hsync_invert: 1; ///< The hsync signal is inverted - uint32_t vsync_invert: 1; ///< The vsync signal is inverted - uint32_t de_invert: 1; ///< The de signal is inverted + uint32_t hsync_invert: 1; ///< The hsync signal is inverted (i.e. active low) + uint32_t vsync_invert: 1; ///< The vsync signal is inverted (i.e. active high) + uint32_t de_invert: 1; ///< The de signal is inverted (i.e. active low) } io_flags; ///< ISP DVP IO flags int queue_items; ///< Queue items struct { diff --git a/examples/peripherals/camera/common_components/dsi_init/Kconfig.projbuild b/examples/peripherals/camera/common_components/dsi_init/Kconfig.projbuild index e433698706..9397e0196f 100644 --- a/examples/peripherals/camera/common_components/dsi_init/Kconfig.projbuild +++ b/examples/peripherals/camera/common_components/dsi_init/Kconfig.projbuild @@ -45,4 +45,11 @@ menu "Example DSI Configuration" int default 600 if EXAMPLE_MIPI_DSI_DISP_VRES_600 default 1280 if EXAMPLE_MIPI_DSI_DISP_VRES_1280 + + config EXAMPLE_MIPI_DSI_DISP_USE_DMA2D + bool "Use DMA2D to copy data to frame buffer" + default n + help + Enable this option, DMA2D will be used to copy data to the target frame buffer. + This can save some CPU time and improve the performance. endmenu diff --git a/examples/peripherals/camera/common_components/dsi_init/example_dsi_init.c b/examples/peripherals/camera/common_components/dsi_init/example_dsi_init.c index 955f45d794..3cd506cfc0 100644 --- a/examples/peripherals/camera/common_components/dsi_init/example_dsi_init.c +++ b/examples/peripherals/camera/common_components/dsi_init/example_dsi_init.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,6 +13,7 @@ #include "esp_lcd_ek79007.h" #include "example_dsi_init.h" #include "example_dsi_init_config.h" +#include "sdkconfig.h" void example_dsi_resource_alloc(esp_lcd_dsi_bus_handle_t *mipi_dsi_bus, esp_lcd_panel_io_handle_t *mipi_dbi_io, esp_lcd_panel_handle_t *mipi_dpi_panel, void **frame_buffer) { @@ -47,6 +48,9 @@ void example_dsi_resource_alloc(esp_lcd_dsi_bus_handle_t *mipi_dsi_bus, esp_lcd_ .vsync_pulse_width = EXAMPLE_MIPI_DSI_IMAGE_VSYNC, .vsync_front_porch = EXAMPLE_MIPI_DSI_IMAGE_VFP, }, +#if CONFIG_EXAMPLE_MIPI_DSI_DISP_USE_DMA2D + .flags.use_dma2d = true, +#endif }; #if CONFIG_EXAMPLE_LCD_PATTERN_ILI9881C diff --git a/examples/peripherals/camera/common_components/sensor_init/example_sensor_init.c b/examples/peripherals/camera/common_components/sensor_init/example_sensor_init.c index 77a6f6636c..671c92e399 100644 --- a/examples/peripherals/camera/common_components/sensor_init/example_sensor_init.c +++ b/examples/peripherals/camera/common_components/sensor_init/example_sensor_init.c @@ -81,6 +81,10 @@ void example_sensor_init(example_sensor_config_t *sensor_config, i2c_master_bus_ cam_cur_fmt = (esp_cam_sensor_format_t *) & (parray[i]); } } + if (!cam_cur_fmt) { + ESP_LOGE(TAG, "Unsupported format"); + ESP_ERROR_CHECK(ESP_ERR_INVALID_ARG); + } ret = esp_cam_sensor_set_format(cam, (const esp_cam_sensor_format_t *) cam_cur_fmt); if (ret != ESP_OK) { diff --git a/examples/peripherals/camera/dvp_isp_dsi/README.md b/examples/peripherals/camera/dvp_isp_dsi/README.md index dda9ad49a5..ca481049f9 100644 --- a/examples/peripherals/camera/dvp_isp_dsi/README.md +++ b/examples/peripherals/camera/dvp_isp_dsi/README.md @@ -15,7 +15,7 @@ The subsections below give only absolutely necessary information. For full steps ### Hardware Required -- OV2640 camera sensor, or other camera sensors with DVP port that can output raw format color data +- OV2640 / SC030IOT camera sensor, or other camera sensors with DVP port that can output raw format color data - EK79007 or ILI9881C LCD screen - ESP32P4 devkit @@ -106,7 +106,7 @@ Set CONFIG_CAMERA_OV2640 to y Remember to select the LCD screen model and set corresponding correct horizontal/vertical resolution in ``menuconfig`` > ``Example DSI Configuration``. -Available options for the camera sensor output horizontal/vertical resolution can be seen in ``menuconfig`` > ``Example Configuration``. Note that the horizontal resolution for the camera should be the same as the LCD screen horizontal resolution. +Available options for the camera sensor output horizontal/vertical resolution can be seen in ``menuconfig`` > ``Example Configuration``. ### Build and Flash diff --git a/examples/peripherals/camera/dvp_isp_dsi/main/Kconfig.projbuild b/examples/peripherals/camera/dvp_isp_dsi/main/Kconfig.projbuild index 9366f21f79..dec207d165 100644 --- a/examples/peripherals/camera/dvp_isp_dsi/main/Kconfig.projbuild +++ b/examples/peripherals/camera/dvp_isp_dsi/main/Kconfig.projbuild @@ -18,40 +18,48 @@ menu "Example Configuration" 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 + default EXAMPLE_CAM_HRES_640 config EXAMPLE_CAM_HRES_1024 - depends on EXAMPLE_MIPI_DSI_DISP_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 + depends on EXAMPLE_MIPI_DSI_DISP_HRES >= 800 bool "800" + config EXAMPLE_CAM_HRES_640 + depends on EXAMPLE_MIPI_DSI_DISP_HRES >= 640 + bool "640" endchoice config EXAMPLE_CAM_HRES int default 1024 if EXAMPLE_CAM_HRES_1024 default 800 if EXAMPLE_CAM_HRES_800 + default 640 if EXAMPLE_CAM_HRES_640 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 + default EXAMPLE_CAM_VRES_600 if EXAMPLE_CAM_HRES_1024 + default EXAMPLE_CAM_VRES_640 if EXAMPLE_CAM_HRES_800 + default EXAMPLE_CAM_VRES_480 if EXAMPLE_CAM_HRES_640 + config EXAMPLE_CAM_VRES_480 + depends on EXAMPLE_MIPI_DSI_DISP_VRES >= 480 + bool "480" config EXAMPLE_CAM_VRES_600 - depends on EXAMPLE_MIPI_DSI_DISP_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 + depends on EXAMPLE_MIPI_DSI_DISP_VRES >= 640 bool "640" config EXAMPLE_CAM_VRES_800 - depends on EXAMPLE_MIPI_DSI_DISP_VRES_1280 + depends on EXAMPLE_MIPI_DSI_DISP_VRES >= 800 bool "800" endchoice config EXAMPLE_CAM_VRES int + default 480 if EXAMPLE_CAM_VRES_480 default 600 if EXAMPLE_CAM_VRES_600 default 640 if EXAMPLE_CAM_VRES_640 default 800 if EXAMPLE_CAM_VRES_800 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 index 144be169e6..3527eb2fbe 100644 --- 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 @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -26,6 +26,11 @@ static const char *TAG = "dvp_isp_dsi"; +typedef struct { + esp_lcd_panel_handle_t panel_hdl; + void *cam_buf; +} display_update_param_t; + static bool s_camera_get_new_vb(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data); static bool s_camera_get_finished_trans(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data); @@ -54,6 +59,13 @@ static void s_ledc_generate_dvp_xclk(void) ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel)); } +static bool example_display_update_ready(esp_lcd_panel_handle_t panel, esp_lcd_dpi_panel_event_data_t *edata, void *user_ctx) +{ + display_update_param_t *param = (display_update_param_t *)user_ctx; + esp_lcd_panel_draw_bitmap(param->panel_hdl, 0, 0, CONFIG_EXAMPLE_CAM_HRES, CONFIG_EXAMPLE_CAM_VRES, param->cam_buf); + return false; +} + void app_main(void) { esp_err_t ret = ESP_FAIL; @@ -80,15 +92,21 @@ void app_main(void) 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; + frame_buffer_size = CONFIG_EXAMPLE_MIPI_DSI_DISP_HRES * CONFIG_EXAMPLE_MIPI_DSI_DISP_VRES * EXAMPLE_RGB565_BITS_PER_PIXEL / 8; - ESP_LOGD(TAG, "CONFIG_EXAMPLE_CAM_HRES: %d, CONFIG_EXAMPLE_MIPI_DSI_DISP_VRES: %d, bits per pixel: %d", CONFIG_EXAMPLE_CAM_HRES, CONFIG_EXAMPLE_MIPI_DSI_DISP_VRES, EXAMPLE_RGB565_BITS_PER_PIXEL); + ESP_LOGD(TAG, "CONFIG_EXAMPLE_MIPI_DSI_DISP_HRES: %d, CONFIG_EXAMPLE_MIPI_DSI_DISP_VRES: %d, bits per pixel: %d", CONFIG_EXAMPLE_MIPI_DSI_DISP_HRES, CONFIG_EXAMPLE_MIPI_DSI_DISP_VRES, EXAMPLE_RGB565_BITS_PER_PIXEL); ESP_LOGD(TAG, "frame_buffer_size: %zu", frame_buffer_size); ESP_LOGD(TAG, "frame_buffer: %p", frame_buffer); + size_t cam_buffer_size = CONFIG_EXAMPLE_CAM_HRES * CONFIG_EXAMPLE_CAM_VRES * EXAMPLE_RGB565_BITS_PER_PIXEL / 8; + void *cam_buffer = heap_caps_calloc(1, cam_buffer_size, MALLOC_CAP_DMA | MALLOC_CAP_SPIRAM); + if (!cam_buffer) { + ESP_LOGE(TAG, "no mem for cam_buffer"); + return; + } esp_cam_ctlr_trans_t cam_trans = { - .buffer = frame_buffer, - .buflen = frame_buffer_size, + .buffer = cam_buffer, + .buflen = cam_buffer_size, }; //--------Camera Sensor and SCCB Init-----------// @@ -137,7 +155,7 @@ void app_main(void) .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, + .io_flags.vsync_invert = 1, // active high .queue_items = 10, }; ret = esp_cam_new_isp_dvp_ctlr(isp_proc, &dvp_config, &cam_handle); @@ -171,6 +189,17 @@ void app_main(void) return; } + // Register DPI panel event callback for display update ready notification + display_update_param_t display_update_param = { + .panel_hdl = mipi_dpi_panel, + .cam_buf = cam_buffer, + }; + esp_lcd_dpi_panel_event_callbacks_t dpi_cbs = { + .on_color_trans_done = example_display_update_ready, + }; + ESP_ERROR_CHECK(esp_lcd_dpi_panel_register_event_callbacks(mipi_dpi_panel, &dpi_cbs, &display_update_param)); + esp_lcd_panel_draw_bitmap(mipi_dpi_panel, 0, 0, CONFIG_EXAMPLE_CAM_HRES, CONFIG_EXAMPLE_CAM_VRES, cam_buffer); + while (1) { ESP_ERROR_CHECK(esp_cam_ctlr_receive(cam_handle, &cam_trans, ESP_CAM_CTLR_MAX_DELAY)); } diff --git a/examples/peripherals/camera/dvp_isp_dsi/main/example_config.h b/examples/peripherals/camera/dvp_isp_dsi/main/example_config.h index 0bf8bd5941..81b3188c62 100644 --- a/examples/peripherals/camera/dvp_isp_dsi/main/example_config.h +++ b/examples/peripherals/camera/dvp_isp_dsi/main/example_config.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -20,36 +20,46 @@ extern "C" { #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_D0_IO (53) +#define EXAMPLE_ISP_DVP_CAM_D1_IO (54) +#define EXAMPLE_ISP_DVP_CAM_D2_IO (26) +#define EXAMPLE_ISP_DVP_CAM_D3_IO (1) +#define EXAMPLE_ISP_DVP_CAM_D4_IO (0) #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_DE_IO (22) #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_HRES_640 + +#if CONFIG_EXAMPLE_CAM_VRES_480 +#define EXAMPLE_CAM_FORMAT "DVP_8bit_20Minput_RAW8_640x480_26fps" // sc030iot +#endif + +#elif CONFIG_EXAMPLE_CAM_HRES_800 #if CONFIG_EXAMPLE_CAM_VRES_640 -#define EXAMPLE_CAM_FORMAT "DVP_8bit_20Minput_RAW8_800x640_15fps" +#define EXAMPLE_CAM_FORMAT "DVP_8bit_20Minput_RAW8_800x640_15fps" // ov2640 #elif CONFIG_EXAMPLE_CAM_VRES_800 -#define EXAMPLE_CAM_FORMAT "DVP_8bit_20Minput_RAW8_800x800_15fps" +#define EXAMPLE_CAM_FORMAT "DVP_8bit_20Minput_RAW8_800x800_15fps" // ov2640 #endif #elif CONFIG_EXAMPLE_CAM_HRES_1024 #if CONFIG_EXAMPLE_CAM_VRES_600 -#define EXAMPLE_CAM_FORMAT "DVP_8bit_20Minput_RAW8_1024x600_15fps" +#define EXAMPLE_CAM_FORMAT "DVP_8bit_20Minput_RAW8_1024x600_15fps" // ov2640 #endif #endif +#ifndef EXAMPLE_CAM_FORMAT +#error "Unsupported camera format! Please adjust EXAMPLE_CAM_HRES and EXAMPLE_CAM_VRES in menuconfig" +#endif + #ifdef __cplusplus } #endif diff --git a/examples/peripherals/camera/dvp_isp_dsi/sdkconfig.defaults b/examples/peripherals/camera/dvp_isp_dsi/sdkconfig.defaults index 3e05d2e5e6..0204a38fcf 100644 --- a/examples/peripherals/camera/dvp_isp_dsi/sdkconfig.defaults +++ b/examples/peripherals/camera/dvp_isp_dsi/sdkconfig.defaults @@ -1,4 +1,3 @@ -CONFIG_SPIRAM=y -CONFIG_IDF_EXPERIMENTAL_FEATURES=y -CONFIG_SPIRAM_SPEED_200M=y CONFIG_CAMERA_OV2640=y +CONFIG_CAMERA_SC030IOT=y +CONFIG_EXAMPLE_MIPI_DSI_DISP_USE_DMA2D=y diff --git a/examples/peripherals/camera/dvp_isp_dsi/sdkconfig.defaults.esp32p4 b/examples/peripherals/camera/dvp_isp_dsi/sdkconfig.defaults.esp32p4 new file mode 100644 index 0000000000..2c02a3b7ee --- /dev/null +++ b/examples/peripherals/camera/dvp_isp_dsi/sdkconfig.defaults.esp32p4 @@ -0,0 +1,3 @@ +CONFIG_IDF_EXPERIMENTAL_FEATURES=y +CONFIG_SPIRAM=y +CONFIG_SPIRAM_SPEED_200M=y diff --git a/examples/peripherals/camera/mipi_isp_dsi/sdkconfig.defaults b/examples/peripherals/camera/mipi_isp_dsi/sdkconfig.defaults index 6192f176b4..2a44a906d8 100644 --- a/examples/peripherals/camera/mipi_isp_dsi/sdkconfig.defaults +++ b/examples/peripherals/camera/mipi_isp_dsi/sdkconfig.defaults @@ -1,5 +1,2 @@ -CONFIG_SPIRAM=y -CONFIG_IDF_EXPERIMENTAL_FEATURES=y -CONFIG_SPIRAM_SPEED_200M=y CONFIG_CAMERA_SC2336=y CONFIG_CAMERA_OV5647=y diff --git a/examples/peripherals/camera/mipi_isp_dsi/sdkconfig.defaults.esp32p4 b/examples/peripherals/camera/mipi_isp_dsi/sdkconfig.defaults.esp32p4 new file mode 100644 index 0000000000..2c02a3b7ee --- /dev/null +++ b/examples/peripherals/camera/mipi_isp_dsi/sdkconfig.defaults.esp32p4 @@ -0,0 +1,3 @@ +CONFIG_IDF_EXPERIMENTAL_FEATURES=y +CONFIG_SPIRAM=y +CONFIG_SPIRAM_SPEED_200M=y