From 4e3751b32eb8d8855755fe7184610dcd3650e71d Mon Sep 17 00:00:00 2001 From: gaoxu Date: Thu, 14 May 2026 17:09:49 +0800 Subject: [PATCH] feat(cam): support dvp cam on ESP32-S31 --- .../dvp/src/esp_cam_ctlr_dvp_cam.c | 4 + .../test_apps/csi/main/test_csi_ov5647.c | 3 + .../test_apps/csi/sdkconfig.defaults.esp32p4 | 1 + .../esp_driver_cam/test_apps/dvp/README.md | 4 +- .../test_apps/dvp/main/CMakeLists.txt | 8 +- .../test_apps/dvp/main/test_dvp_ov2640.c | 130 ++++ .../dvp/main/test_dvp_ov2640_board.h | 134 ++++ .../test_apps/dvp/main/test_dvp_s3eye.c | 166 ----- .../test_apps/dvp/pytest_dvp.py | 33 +- .../test_apps/dvp/sdkconfig.ci.esp32p4_ov2640 | 6 + .../dvp/sdkconfig.ci.esp32s31_ov2640 | 5 + .../test_apps/dvp/sdkconfig.ci.esp32s3_eye | 7 - .../test_apps/dvp/sdkconfig.ci.esp32s3_ov2640 | 1 + .../test_apps/dvp/sdkconfig.defaults.esp32s3 | 2 + .../test_apps/dvp/sdkconfig.defaults.esp32s31 | 4 + components/esp_hal_cam/esp32s31/cam_periph.c | 40 ++ .../esp_hal_cam/esp32s31/include/hal/cam_ll.h | 583 ++++++++++++++++++ .../esp32s31/include/hal/clk_gate_ll.h | 24 + .../esp_hal_lcd/esp32s31/include/hal/lcd_ll.h | 3 +- components/esp_system/port/soc/esp32s31/clk.c | 3 + .../esp32s31/include/soc/Kconfig.soc_caps.in | 8 + .../soc/esp32s31/include/soc/clk_tree_defs.h | 17 + .../soc/esp32s31/include/soc/soc_caps.h | 6 +- .../peripherals/camera_driver.rst | 1 + .../peripherals/camera_driver.rst | 1 + examples/peripherals/.build-test-rules.yml | 13 - .../sensor_init/example_sensor_init.c | 12 +- .../sensor_init/idf_component.yml | 2 +- .../sensor_init/include/example_sensor_init.h | 3 + examples/peripherals/camera/dvp_dsi/README.md | 17 +- .../camera/dvp_dsi/main/dvp_dsi_main.c | 3 + .../camera/dvp_dsi/main/example_config.h | 4 +- .../camera/dvp_dsi/sdkconfig.defaults | 2 + .../peripherals/camera/dvp_isp_dsi/README.md | 15 +- .../dvp_isp_dsi/main/dvp_isp_dsi_main.c | 3 + .../camera/dvp_isp_dsi/sdkconfig.defaults | 4 + .../camera/dvp_spi_lcd/CMakeLists.txt | 8 - .../peripherals/camera/dvp_spi_lcd/README.md | 137 ---- .../camera/dvp_spi_lcd/main/CMakeLists.txt | 5 - .../camera/dvp_spi_lcd/main/Kconfig.projbuild | 44 -- .../dvp_spi_lcd/main/dvp_spi_lcd_main.c | 249 -------- .../camera/dvp_spi_lcd/main/example_config.h | 76 --- .../camera/dvp_spi_lcd/main/idf_component.yml | 3 - .../camera/dvp_spi_lcd/pytest_dvp_spi_lcd.py | 11 - .../camera/dvp_spi_lcd/sdkconfig.defaults | 2 - .../dvp_spi_lcd/sdkconfig.defaults.esp32p4 | 2 - .../dvp_spi_lcd/sdkconfig.defaults.esp32s3 | 2 - .../mipi_isp_dsi/main/mipi_isp_dsi_main.c | 3 + .../camera/mipi_isp_dsi/sdkconfig.defaults | 4 + .../isp/multi_pipelines/main/isp_dsi_main.c | 3 + .../isp/multi_pipelines/sdkconfig.defaults | 3 + tools/ci/check_examples_documented.py | 2 - 52 files changed, 1040 insertions(+), 786 deletions(-) create mode 100644 components/esp_driver_cam/test_apps/dvp/main/test_dvp_ov2640.c create mode 100644 components/esp_driver_cam/test_apps/dvp/main/test_dvp_ov2640_board.h delete mode 100644 components/esp_driver_cam/test_apps/dvp/main/test_dvp_s3eye.c create mode 100644 components/esp_driver_cam/test_apps/dvp/sdkconfig.ci.esp32p4_ov2640 create mode 100644 components/esp_driver_cam/test_apps/dvp/sdkconfig.ci.esp32s31_ov2640 delete mode 100644 components/esp_driver_cam/test_apps/dvp/sdkconfig.ci.esp32s3_eye create mode 100644 components/esp_driver_cam/test_apps/dvp/sdkconfig.ci.esp32s3_ov2640 create mode 100644 components/esp_driver_cam/test_apps/dvp/sdkconfig.defaults.esp32s31 create mode 100644 components/esp_hal_cam/esp32s31/cam_periph.c create mode 100644 components/esp_hal_cam/esp32s31/include/hal/cam_ll.h delete mode 100644 examples/peripherals/camera/dvp_spi_lcd/CMakeLists.txt delete mode 100644 examples/peripherals/camera/dvp_spi_lcd/README.md delete mode 100644 examples/peripherals/camera/dvp_spi_lcd/main/CMakeLists.txt delete mode 100644 examples/peripherals/camera/dvp_spi_lcd/main/Kconfig.projbuild delete mode 100644 examples/peripherals/camera/dvp_spi_lcd/main/dvp_spi_lcd_main.c delete mode 100644 examples/peripherals/camera/dvp_spi_lcd/main/example_config.h delete mode 100644 examples/peripherals/camera/dvp_spi_lcd/main/idf_component.yml delete mode 100644 examples/peripherals/camera/dvp_spi_lcd/pytest_dvp_spi_lcd.py delete mode 100644 examples/peripherals/camera/dvp_spi_lcd/sdkconfig.defaults delete mode 100644 examples/peripherals/camera/dvp_spi_lcd/sdkconfig.defaults.esp32p4 delete mode 100644 examples/peripherals/camera/dvp_spi_lcd/sdkconfig.defaults.esp32s3 diff --git a/components/esp_driver_cam/dvp/src/esp_cam_ctlr_dvp_cam.c b/components/esp_driver_cam/dvp/src/esp_cam_ctlr_dvp_cam.c index 5e2567a79ee..a64df57d63e 100644 --- a/components/esp_driver_cam/dvp/src/esp_cam_ctlr_dvp_cam.c +++ b/components/esp_driver_cam/dvp/src/esp_cam_ctlr_dvp_cam.c @@ -810,6 +810,9 @@ esp_err_t esp_cam_ctlr_dvp_format_conversion(esp_cam_ctlr_handle_t cam_handle, return ESP_OK; } +#if !SOC_LCDCAM_CAM_SUPPORT_RGB_YUV_CONV + return ESP_ERR_NOT_SUPPORTED; +#else #if !CONFIG_ESP32P4_SELECTS_REV_LESS_V3 if (config->src_format == CAM_CTLR_COLOR_YUV420) { ESP_LOGE(TAG, "YUV420 is not allowed for source format"); @@ -820,6 +823,7 @@ esp_err_t esp_cam_ctlr_dvp_format_conversion(esp_cam_ctlr_handle_t cam_handle, cam_hal_color_format_convert(&ctlr->hal, config); return ESP_OK; +#endif } /** diff --git a/components/esp_driver_cam/test_apps/csi/main/test_csi_ov5647.c b/components/esp_driver_cam/test_apps/csi/main/test_csi_ov5647.c index b2e6027ba40..d263239c697 100644 --- a/components/esp_driver_cam/test_apps/csi/main/test_csi_ov5647.c +++ b/components/esp_driver_cam/test_apps/csi/main/test_csi_ov5647.c @@ -85,6 +85,9 @@ TEST_CASE("TEST esp_cam on ov5647", "[csi][camera][ov5647]") .i2c_port_num = I2C_NUM_0, .i2c_sda_io_num = TEST_MIPI_CSI_CAM_SCCB_SDA_IO, .i2c_scl_io_num = TEST_MIPI_CSI_CAM_SCCB_SCL_IO, + .reset_pin = -1, + .pwdn_pin = -1, + .xclk_pin = -1, .port = ESP_CAM_SENSOR_MIPI_CSI, .format_name = TEST_CAM_FORMAT, }; diff --git a/components/esp_driver_cam/test_apps/csi/sdkconfig.defaults.esp32p4 b/components/esp_driver_cam/test_apps/csi/sdkconfig.defaults.esp32p4 index ca90c75b74f..3452c71fa07 100644 --- a/components/esp_driver_cam/test_apps/csi/sdkconfig.defaults.esp32p4 +++ b/components/esp_driver_cam/test_apps/csi/sdkconfig.defaults.esp32p4 @@ -5,3 +5,4 @@ CONFIG_IDF_EXPERIMENTAL_FEATURES=y CONFIG_SPIRAM_SPEED_200M=y CONFIG_CAMERA_OV5647=y +CONFIG_CAMERA_OV5647_MIPI_RAW8_800X640_50FPS=y diff --git a/components/esp_driver_cam/test_apps/dvp/README.md b/components/esp_driver_cam/test_apps/dvp/README.md index 25fbbd517f0..d96e2372ecc 100644 --- a/components/esp_driver_cam/test_apps/dvp/README.md +++ b/components/esp_driver_cam/test_apps/dvp/README.md @@ -1,2 +1,2 @@ -| Supported Targets | ESP32-P4 | ESP32-S3 | -| ----------------- | -------- | -------- | +| Supported Targets | ESP32-P4 | ESP32-S3 | ESP32-S31 | +| ----------------- | -------- | -------- | --------- | diff --git a/components/esp_driver_cam/test_apps/dvp/main/CMakeLists.txt b/components/esp_driver_cam/test_apps/dvp/main/CMakeLists.txt index 69ed5c35072..4c8b39cd047 100644 --- a/components/esp_driver_cam/test_apps/dvp/main/CMakeLists.txt +++ b/components/esp_driver_cam/test_apps/dvp/main/CMakeLists.txt @@ -3,8 +3,8 @@ set(srcs "test_app_main.c") if(CONFIG_SOC_LCDCAM_CAM_SUPPORTED) list(APPEND srcs "test_dvp_driver.c") endif() -if(CONFIG_IDF_TARGET_ESP32S3) - list(APPEND srcs "test_dvp_s3eye.c") +if(CONFIG_CAMERA_OV2640 AND CONFIG_SOC_LCDCAM_CAM_SUPPORTED) + list(APPEND srcs "test_dvp_ov2640.c") endif() set(priv_requires @@ -14,6 +14,10 @@ set(priv_requires esp_driver_ledc ) +if(CONFIG_CAMERA_OV2640 AND CONFIG_SOC_LCDCAM_CAM_SUPPORTED) + list(APPEND priv_requires sensor_init) +endif() + idf_component_register(SRCS ${srcs} INCLUDE_DIRS "." PRIV_REQUIRES ${priv_requires} diff --git a/components/esp_driver_cam/test_apps/dvp/main/test_dvp_ov2640.c b/components/esp_driver_cam/test_apps/dvp/main/test_dvp_ov2640.c new file mode 100644 index 00000000000..d6a4f0d475c --- /dev/null +++ b/components/esp_driver_cam/test_apps/dvp/main/test_dvp_ov2640.c @@ -0,0 +1,130 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "sdkconfig.h" +#include "freertos/FreeRTOS.h" +#include "unity.h" +#include "driver/i2c_master.h" +#include "esp_attr.h" +#include "esp_heap_caps.h" +#include "esp_cam_ctlr.h" +#include "esp_cam_ctlr_dvp.h" +#include "example_sensor_init.h" +#include "test_dvp_ov2640_board.h" + +static int s_new_trans_count; +static int s_trans_finished_count; + +static bool IRAM_ATTR camera_get_new_buffer(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data) +{ + (void)handle; + esp_cam_ctlr_trans_t *new_trans = (esp_cam_ctlr_trans_t *)user_data; + trans->buffer = new_trans->buffer; + trans->buflen = new_trans->buflen; + s_new_trans_count++; + return false; +} + +static bool IRAM_ATTR camera_trans_finished(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data) +{ + (void)handle; + (void)trans; + (void)user_data; + s_trans_finished_count++; + return false; +} + +TEST_CASE("TEST esp_cam DVP on ov2640", "[dvp][camera][ov2640]") +{ + s_new_trans_count = 0; + s_trans_finished_count = 0; + + esp_cam_ctlr_dvp_pin_config_t pin_cfg = { + .data_width = TEST_DVP_CAM_DATA_WIDTH, + .data_io = { + TEST_DVP_CAM_D0_IO, + TEST_DVP_CAM_D1_IO, + TEST_DVP_CAM_D2_IO, + TEST_DVP_CAM_D3_IO, + TEST_DVP_CAM_D4_IO, + TEST_DVP_CAM_D5_IO, + TEST_DVP_CAM_D6_IO, + TEST_DVP_CAM_D7_IO, + }, + .vsync_io = TEST_DVP_CAM_VSYNC_IO, + .de_io = TEST_DVP_CAM_DE_IO, + .pclk_io = TEST_DVP_CAM_PCLK_IO, + .xclk_io = TEST_DVP_CAM_XCLK_IO, + }; + + esp_cam_ctlr_dvp_config_t dvp_config = { + .ctlr_id = 0, + .clk_src = CAM_CLK_SRC_DEFAULT, + .h_res = TEST_DVP_CAM_FRAME_WIDTH, + .v_res = TEST_DVP_CAM_FRAME_HEIGHT, + .input_data_color_type = TEST_DVP_CAM_INPUT_COLOR_TYPE, + .output_data_color_type = TEST_DVP_CAM_OUTPUT_COLOR_TYPE, + .dma_burst_size = 64, + .pin = &pin_cfg, + .bk_buffer_dis = 1, + .xclk_freq = TEST_DVP_CAM_XCLK_FREQ_HZ, + .cam_data_width = TEST_DVP_CAM_DATA_WIDTH, + .byte_swap_en = false, + .bit_swap_en = false, + }; + esp_cam_ctlr_handle_t cam_handle = NULL; + TEST_ESP_OK(esp_cam_new_dvp_ctlr(&dvp_config, &cam_handle)); + + size_t frame_buffer_size = TEST_DVP_CAM_FRAME_SIZE_BYTES; + void *frame_buffer = esp_cam_ctlr_alloc_buffer(cam_handle, frame_buffer_size, TEST_DVP_CAM_BUF_ALLOC_CAPS); + TEST_ASSERT_NOT_NULL(frame_buffer); + + esp_cam_ctlr_trans_t trans_data = { + .buffer = frame_buffer, + .buflen = frame_buffer_size, + }; + + example_sensor_handle_t sensor_handle = { + .sccb_handle = NULL, + .i2c_bus_handle = NULL, + }; + example_sensor_config_t sensor_config = { + .i2c_port_num = I2C_NUM_0, + .i2c_sda_io_num = TEST_DVP_CAM_SCCB_SDA_IO, + .i2c_scl_io_num = TEST_DVP_CAM_SCCB_SCL_IO, + .reset_pin = TEST_DVP_CAM_RESET_IO, + .pwdn_pin = TEST_DVP_CAM_PWDN_IO, + .xclk_pin = TEST_DVP_CAM_XCLK_IO, + .port = ESP_CAM_SENSOR_DVP, + .format_name = TEST_DVP_CAM_FORMAT_NAME, + }; + example_sensor_init(&sensor_config, &sensor_handle); + if (sensor_handle.sccb_handle == NULL || sensor_handle.i2c_bus_handle == NULL) { + TEST_ESP_OK(esp_cam_ctlr_del(cam_handle)); + heap_caps_free(frame_buffer); + TEST_FAIL_MESSAGE("failed to detect or initialize ov2640 sensor"); + } + + esp_cam_ctlr_evt_cbs_t cbs = { + .on_get_new_trans = camera_get_new_buffer, + .on_trans_finished = camera_trans_finished, + }; + TEST_ESP_OK(esp_cam_ctlr_register_event_callbacks(cam_handle, &cbs, &trans_data)); + + TEST_ESP_OK(esp_cam_ctlr_enable(cam_handle)); + TEST_ESP_OK(esp_cam_ctlr_start(cam_handle)); + vTaskDelay(pdMS_TO_TICKS(1000)); + TEST_ESP_OK(esp_cam_ctlr_stop(cam_handle)); + + // Roughly one transfer per frame is expected for the selected OV2640 format. + TEST_ASSERT_GREATER_OR_EQUAL(TEST_DVP_CAM_EXPECTED_NEW_TRANS_MIN, s_new_trans_count); + TEST_ASSERT_GREATER_OR_EQUAL(TEST_DVP_CAM_EXPECTED_FINISHED_MIN, s_trans_finished_count); + + TEST_ESP_OK(esp_cam_ctlr_disable(cam_handle)); + TEST_ESP_OK(esp_cam_ctlr_del(cam_handle)); + + example_sensor_deinit(sensor_handle); + heap_caps_free(frame_buffer); +} diff --git a/components/esp_driver_cam/test_apps/dvp/main/test_dvp_ov2640_board.h b/components/esp_driver_cam/test_apps/dvp/main/test_dvp_ov2640_board.h new file mode 100644 index 00000000000..99618dbac57 --- /dev/null +++ b/components/esp_driver_cam/test_apps/dvp/main/test_dvp_ov2640_board.h @@ -0,0 +1,134 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include "sdkconfig.h" +#include "hal/cam_ctlr_types.h" +#include "esp_heap_caps.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define TEST_DVP_CAM_FRAME_BITS_PER_PIXEL 16 +#define TEST_DVP_CAM_EXPECTED_NEW_TRANS_MIN 6 +#define TEST_DVP_CAM_EXPECTED_FINISHED_MIN 5 +#define TEST_DVP_CAM_XCLK_FREQ_HZ 20000000 +#define TEST_DVP_CAM_DATA_WIDTH 8 + +#if CONFIG_IDF_TARGET_ESP32S3 +#define TEST_DVP_CAM_FRAME_WIDTH 640 +#define TEST_DVP_CAM_FRAME_HEIGHT 480 +#define TEST_DVP_CAM_FORMAT_NAME "DVP_8bit_20Minput_YUV422_YUYV_640x480_6fps" +#define TEST_DVP_CAM_INPUT_COLOR_TYPE CAM_CTLR_COLOR_YUV422_YUYV +#define TEST_DVP_CAM_OUTPUT_COLOR_TYPE CAM_CTLR_COLOR_YUV422_YUYV + +#define TEST_DVP_CAM_PWDN_IO (-1) +#define TEST_DVP_CAM_RESET_IO (-1) +#define TEST_DVP_CAM_SCCB_SCL_IO 5 +#define TEST_DVP_CAM_SCCB_SDA_IO 4 + +#define TEST_DVP_CAM_D0_IO 11 +#define TEST_DVP_CAM_D1_IO 9 +#define TEST_DVP_CAM_D2_IO 8 +#define TEST_DVP_CAM_D3_IO 10 +#define TEST_DVP_CAM_D4_IO 12 +#define TEST_DVP_CAM_D5_IO 18 +#define TEST_DVP_CAM_D6_IO 17 +#define TEST_DVP_CAM_D7_IO 16 + +#define TEST_DVP_CAM_XCLK_IO 15 +#define TEST_DVP_CAM_PCLK_IO 13 +#define TEST_DVP_CAM_DE_IO 7 +#define TEST_DVP_CAM_VSYNC_IO 6 + +#elif CONFIG_IDF_TARGET_ESP32P4 +#define TEST_DVP_CAM_FRAME_WIDTH 640 +#define TEST_DVP_CAM_FRAME_HEIGHT 480 +#define TEST_DVP_CAM_FORMAT_NAME "DVP_8bit_20Minput_YUV422_UYVY_640x480_6fps" +#define TEST_DVP_CAM_INPUT_COLOR_TYPE CAM_CTLR_COLOR_YUV422_UYVY +#define TEST_DVP_CAM_OUTPUT_COLOR_TYPE CAM_CTLR_COLOR_YUV422_UYVY + +#define TEST_DVP_CAM_PWDN_IO (-1) +#define TEST_DVP_CAM_RESET_IO (-1) + +#if !CONFIG_ESP32P4_SELECTS_REV_LESS_V3 +#define TEST_DVP_CAM_SCCB_SCL_IO 8 +#define TEST_DVP_CAM_SCCB_SDA_IO 7 + +#define TEST_DVP_CAM_D0_IO 2 +#define TEST_DVP_CAM_D1_IO 32 +#define TEST_DVP_CAM_D2_IO 33 +#define TEST_DVP_CAM_D3_IO 23 +#define TEST_DVP_CAM_D4_IO 3 +#define TEST_DVP_CAM_D5_IO 6 +#define TEST_DVP_CAM_D6_IO 5 +#define TEST_DVP_CAM_D7_IO 21 + +#define TEST_DVP_CAM_XCLK_IO 20 +#define TEST_DVP_CAM_PCLK_IO 4 +#define TEST_DVP_CAM_DE_IO 22 +#define TEST_DVP_CAM_VSYNC_IO 37 +#else +#define TEST_DVP_CAM_SCCB_SCL_IO 33 +#define TEST_DVP_CAM_SCCB_SDA_IO 32 + +#define TEST_DVP_CAM_D0_IO 53 +#define TEST_DVP_CAM_D1_IO 54 +#define TEST_DVP_CAM_D2_IO 26 +#define TEST_DVP_CAM_D3_IO 1 +#define TEST_DVP_CAM_D4_IO 0 +#define TEST_DVP_CAM_D5_IO 45 +#define TEST_DVP_CAM_D6_IO 46 +#define TEST_DVP_CAM_D7_IO 47 + +#define TEST_DVP_CAM_XCLK_IO 20 +#define TEST_DVP_CAM_PCLK_IO 21 +#define TEST_DVP_CAM_DE_IO 22 +#define TEST_DVP_CAM_VSYNC_IO 23 +#endif + +#elif CONFIG_IDF_TARGET_ESP32S31 + +#define TEST_DVP_CAM_FRAME_WIDTH 640 +#define TEST_DVP_CAM_FRAME_HEIGHT 480 +#define TEST_DVP_CAM_FORMAT_NAME "DVP_8bit_20Minput_YUV422_YUYV_640x480_6fps" +#define TEST_DVP_CAM_INPUT_COLOR_TYPE CAM_CTLR_COLOR_YUV422_YUYV +#define TEST_DVP_CAM_OUTPUT_COLOR_TYPE CAM_CTLR_COLOR_YUV422_YUYV + +#define TEST_DVP_CAM_PWDN_IO 61 +#define TEST_DVP_CAM_RESET_IO 60 +#define TEST_DVP_CAM_SCCB_SCL_IO 1 +#define TEST_DVP_CAM_SCCB_SDA_IO 0 + +#define TEST_DVP_CAM_D0_IO 46 +#define TEST_DVP_CAM_D1_IO 47 +#define TEST_DVP_CAM_D2_IO 48 +#define TEST_DVP_CAM_D3_IO 49 +#define TEST_DVP_CAM_D4_IO 50 +#define TEST_DVP_CAM_D5_IO 51 +#define TEST_DVP_CAM_D6_IO 52 +#define TEST_DVP_CAM_D7_IO 53 + +#define TEST_DVP_CAM_XCLK_IO 55 +#define TEST_DVP_CAM_PCLK_IO 54 +#define TEST_DVP_CAM_DE_IO 57 +#define TEST_DVP_CAM_VSYNC_IO 56 + +#endif + +#define TEST_DVP_CAM_FRAME_SIZE_BYTES \ + (TEST_DVP_CAM_FRAME_WIDTH * TEST_DVP_CAM_FRAME_HEIGHT * TEST_DVP_CAM_FRAME_BITS_PER_PIXEL / 8) + +#if CONFIG_SPIRAM +#define TEST_DVP_CAM_BUF_ALLOC_CAPS (MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA) +#else +#define TEST_DVP_CAM_BUF_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA) +#endif + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_driver_cam/test_apps/dvp/main/test_dvp_s3eye.c b/components/esp_driver_cam/test_apps/dvp/main/test_dvp_s3eye.c deleted file mode 100644 index d86a0325bae..00000000000 --- a/components/esp_driver_cam/test_apps/dvp/main/test_dvp_s3eye.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2025 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_cache.h" -#include "driver/i2c_master.h" -#include "esp_cam_ctlr.h" -#include "esp_cam_ctlr_dvp.h" -#include "driver/ledc.h" -#include "example_sensor_init.h" -#include "unity.h" - -//----------CAM Config------------// -#define TEST_RGB565_BITS_PER_PIXEL 16 - -#define TEST_DVP_CAM_SCCB_SCL_IO (5) -#define TEST_DVP_CAM_SCCB_SDA_IO (4) -#define TEST_DVP_CAM_XCLK_FREQ_HZ (20000000) -#define TEST_DVP_CAM_DATA_WIDTH (8) - -#define TEST_DVP_CAM_D0_IO (11) -#define TEST_DVP_CAM_D1_IO (9) -#define TEST_DVP_CAM_D2_IO (8) -#define TEST_DVP_CAM_D3_IO (10) -#define TEST_DVP_CAM_D4_IO (12) -#define TEST_DVP_CAM_D5_IO (18) -#define TEST_DVP_CAM_D6_IO (17) -#define TEST_DVP_CAM_D7_IO (16) - -#define TEST_DVP_CAM_XCLK_IO (15) -#define TEST_DVP_CAM_PCLK_IO (13) -#define TEST_DVP_CAM_DE_IO (7) -#define TEST_DVP_CAM_VSYNC_IO (6) -#define TEST_DVP_CAM_HSYNC_IO (-1) - -#define TEST_DVP_CAM_BUF_ALLOC_CAPS (MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA) - -#define TEST_DVP_CAM_H_RES 240 -#define TEST_DVP_CAM_V_RES 240 -#define TEST_CAM_FORMAT "DVP_8bit_20Minput_RGB565_240x240_25fps" - -#define BUFFER_SIZE (TEST_DVP_CAM_H_RES * TEST_DVP_CAM_V_RES * TEST_RGB565_BITS_PER_PIXEL / 8) - -typedef struct { - // esp_lcd_panel_handle_t panel_hdl; - esp_cam_ctlr_trans_t cam_trans; -} example_cam_context_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); - -int count_new_vb = 0; -int count_finished_trans = 0; - -TEST_CASE("TEST DVP camera on esp32s3_eye", "[dvp][camera][esp32s3_eye]") -{ - //----------CAM Controller Init------------// - esp_cam_ctlr_handle_t cam_handle = NULL; - esp_cam_ctlr_dvp_pin_config_t pin_cfg = { - .data_width = TEST_DVP_CAM_DATA_WIDTH, - .data_io = { - TEST_DVP_CAM_D0_IO, - TEST_DVP_CAM_D1_IO, - TEST_DVP_CAM_D2_IO, - TEST_DVP_CAM_D3_IO, - TEST_DVP_CAM_D4_IO, - TEST_DVP_CAM_D5_IO, - TEST_DVP_CAM_D6_IO, - TEST_DVP_CAM_D7_IO, - }, - .vsync_io = TEST_DVP_CAM_VSYNC_IO, - .de_io = TEST_DVP_CAM_DE_IO, - .pclk_io = TEST_DVP_CAM_PCLK_IO, - .xclk_io = TEST_DVP_CAM_XCLK_IO, - }; - - esp_cam_ctlr_dvp_config_t dvp_config = { - .ctlr_id = 0, - .clk_src = CAM_CLK_SRC_DEFAULT, - .h_res = TEST_DVP_CAM_H_RES, - .v_res = TEST_DVP_CAM_V_RES, - .input_data_color_type = CAM_CTLR_COLOR_RGB565, - .output_data_color_type = CAM_CTLR_COLOR_RGB565, - .dma_burst_size = 64, - .pin = &pin_cfg, - .bk_buffer_dis = 1, - .xclk_freq = TEST_DVP_CAM_XCLK_FREQ_HZ, - }; - - TEST_ESP_OK(esp_cam_new_dvp_ctlr(&dvp_config, &cam_handle)); - - //--------Allocate Camera Buffer----------// - size_t cam_buffer_size = TEST_DVP_CAM_H_RES * TEST_DVP_CAM_V_RES * TEST_RGB565_BITS_PER_PIXEL / 8; - void *cam_buffer = NULL; - - cam_buffer = esp_cam_ctlr_alloc_buffer(cam_handle, cam_buffer_size, TEST_DVP_CAM_BUF_ALLOC_CAPS); - - //--------Camera Sensor and SCCB Init-----------// - example_sensor_config_t cam_sensor_config = { - .i2c_port_num = I2C_NUM_0, - .i2c_sda_io_num = TEST_DVP_CAM_SCCB_SDA_IO, - .i2c_scl_io_num = TEST_DVP_CAM_SCCB_SCL_IO, - .port = ESP_CAM_SENSOR_DVP, - .format_name = TEST_CAM_FORMAT, - }; - example_sensor_handle_t sensor_handle = { - .sccb_handle = NULL, - .i2c_bus_handle = NULL, - }; - example_sensor_init(&cam_sensor_config, &sensor_handle); - - //--------Register Camera Callbacks----------// - example_cam_context_t cam_ctx = { - // .panel_hdl = lcd_panel_hdl, - .cam_trans = { - .buffer = cam_buffer, - .buflen = cam_buffer_size, - } - }; - - esp_cam_ctlr_evt_cbs_t cbs = { - .on_get_new_trans = s_camera_get_new_vb, - .on_trans_finished = s_camera_get_finished_trans, - }; - TEST_ESP_OK(esp_cam_ctlr_register_event_callbacks(cam_handle, &cbs, &cam_ctx)); - - TEST_ESP_OK(esp_cam_ctlr_enable(cam_handle)); - TEST_ESP_OK(esp_cam_ctlr_start(cam_handle)); - - vTaskDelay(1000 / portTICK_PERIOD_MS); - - //For this format"DVP_8bit_20Minput_RGB565_240x240_25fps", the FPS is 25 - TEST_ASSERT_GREATER_OR_EQUAL(25, count_new_vb); - TEST_ASSERT_GREATER_OR_EQUAL(24, count_finished_trans); - - TEST_ESP_OK(esp_cam_ctlr_stop(cam_handle)); - TEST_ESP_OK(esp_cam_ctlr_disable(cam_handle)); - TEST_ESP_OK(esp_cam_ctlr_del(cam_handle)); - - example_sensor_deinit(sensor_handle); - heap_caps_free(cam_buffer); -} - -static bool s_camera_get_new_vb(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data) -{ - example_cam_context_t *ctx = (example_cam_context_t *)user_data; - *trans = ctx->cam_trans; - - count_new_vb++; - - return false; -} - -static bool s_camera_get_finished_trans(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data) -{ - count_finished_trans++; - return false; -} diff --git a/components/esp_driver_cam/test_apps/dvp/pytest_dvp.py b/components/esp_driver_cam/test_apps/dvp/pytest_dvp.py index a88d69804a4..b810db326bc 100644 --- a/components/esp_driver_cam/test_apps/dvp/pytest_dvp.py +++ b/components/esp_driver_cam/test_apps/dvp/pytest_dvp.py @@ -1,41 +1,34 @@ -# SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut from pytest_embedded_idf.utils import idf_parametrize +def _skip_board_specific_cases(case_tester) -> None: # type: ignore + for case in case_tester.test_menu: + if 'TEST esp_cam DVP on ov2640' in case.name: + continue + case_tester.run_normal_case(case=case, reset=True) + + @pytest.mark.generic @pytest.mark.parametrize( 'config', ['cache_safe', 'release', 'pm_enable'], indirect=True, ) -@idf_parametrize('target', ['esp32p4'], indirect=['target']) -def test_dvp(dut: Dut) -> None: - dut.run_all_single_board_cases() - - -@pytest.mark.octal_psram -@pytest.mark.parametrize( - 'config', - ['cache_safe', 'release', 'pm_enable'], - indirect=True, -) -@idf_parametrize('target', ['esp32s3'], indirect=['target']) -def test_dvp_driver(case_tester) -> None: # type: ignore - for case in case_tester.test_menu: - if 'TEST DVP camera on esp32s3_eye' in case.name: - continue - case_tester.run_normal_case(case=case, reset=True) +@idf_parametrize('target', ['esp32p4', 'esp32s31'], indirect=['target']) +def test_dvp(case_tester) -> None: # type: ignore + _skip_board_specific_cases(case_tester) @pytest.mark.esp32s3_eye @pytest.mark.parametrize( 'config', - ['esp32s3_eye'], + ['cache_safe', 'release', 'pm_enable', 'esp32s3_ov2640'], indirect=True, ) @idf_parametrize('target', ['esp32s3'], indirect=['target']) -def test_dvp_s3eye(dut: Dut) -> None: +def test_dvp_esp32s3(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_driver_cam/test_apps/dvp/sdkconfig.ci.esp32p4_ov2640 b/components/esp_driver_cam/test_apps/dvp/sdkconfig.ci.esp32p4_ov2640 new file mode 100644 index 00000000000..1d5186333be --- /dev/null +++ b/components/esp_driver_cam/test_apps/dvp/sdkconfig.ci.esp32p4_ov2640 @@ -0,0 +1,6 @@ +CONFIG_IDF_TARGET="esp32p4" + +CONFIG_SPIRAM=y +CONFIG_SPIRAM_SPEED_200M=y +CONFIG_IDF_EXPERIMENTAL_FEATURES=y +CONFIG_CAMERA_OV2640=y diff --git a/components/esp_driver_cam/test_apps/dvp/sdkconfig.ci.esp32s31_ov2640 b/components/esp_driver_cam/test_apps/dvp/sdkconfig.ci.esp32s31_ov2640 new file mode 100644 index 00000000000..b2d4c6694bb --- /dev/null +++ b/components/esp_driver_cam/test_apps/dvp/sdkconfig.ci.esp32s31_ov2640 @@ -0,0 +1,5 @@ +CONFIG_IDF_TARGET="esp32s31" + +CONFIG_SPIRAM=y +CONFIG_SPIRAM_SPEED_250M=y +CONFIG_CAMERA_OV2640=y diff --git a/components/esp_driver_cam/test_apps/dvp/sdkconfig.ci.esp32s3_eye b/components/esp_driver_cam/test_apps/dvp/sdkconfig.ci.esp32s3_eye deleted file mode 100644 index 41438fffb07..00000000000 --- a/components/esp_driver_cam/test_apps/dvp/sdkconfig.ci.esp32s3_eye +++ /dev/null @@ -1,7 +0,0 @@ -CONFIG_IDF_TARGET="esp32s3" - -CONFIG_SPIRAM=y -CONFIG_SPIRAM_MODE_OCT=y - -CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y -CONFIG_CAMERA_OV2640=y diff --git a/components/esp_driver_cam/test_apps/dvp/sdkconfig.ci.esp32s3_ov2640 b/components/esp_driver_cam/test_apps/dvp/sdkconfig.ci.esp32s3_ov2640 new file mode 100644 index 00000000000..dc0f8f7a839 --- /dev/null +++ b/components/esp_driver_cam/test_apps/dvp/sdkconfig.ci.esp32s3_ov2640 @@ -0,0 +1 @@ +CONFIG_CAMERA_OV2640=y diff --git a/components/esp_driver_cam/test_apps/dvp/sdkconfig.defaults.esp32s3 b/components/esp_driver_cam/test_apps/dvp/sdkconfig.defaults.esp32s3 index 15ecad20b0a..263ed93757d 100644 --- a/components/esp_driver_cam/test_apps/dvp/sdkconfig.defaults.esp32s3 +++ b/components/esp_driver_cam/test_apps/dvp/sdkconfig.defaults.esp32s3 @@ -1,4 +1,6 @@ CONFIG_IDF_TARGET="esp32s3" +CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y + CONFIG_SPIRAM=y CONFIG_SPIRAM_MODE_OCT=y diff --git a/components/esp_driver_cam/test_apps/dvp/sdkconfig.defaults.esp32s31 b/components/esp_driver_cam/test_apps/dvp/sdkconfig.defaults.esp32s31 new file mode 100644 index 00000000000..8d758072515 --- /dev/null +++ b/components/esp_driver_cam/test_apps/dvp/sdkconfig.defaults.esp32s31 @@ -0,0 +1,4 @@ +CONFIG_IDF_TARGET="esp32s31" + +CONFIG_SPIRAM=y +CONFIG_SPIRAM_SPEED_250M=y diff --git a/components/esp_hal_cam/esp32s31/cam_periph.c b/components/esp_hal_cam/esp32s31/cam_periph.c new file mode 100644 index 00000000000..7509fc71c95 --- /dev/null +++ b/components/esp_hal_cam/esp32s31/cam_periph.c @@ -0,0 +1,40 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "hal/cam_periph.h" +#include "soc/gpio_sig_map.h" + +const cam_signal_conn_t cam_periph_signals = { + .buses = { + [0] = { + .module = PERIPH_LCD_CAM_MODULE, + .irq_id = ETS_LCD_CAM_INTR_SOURCE, + .data_sigs = { + CAM_DATA0_IN_PAD_IN_IDX, + CAM_DATA1_IN_PAD_IN_IDX, + CAM_DATA2_IN_PAD_IN_IDX, + CAM_DATA3_IN_PAD_IN_IDX, + CAM_DATA4_IN_PAD_IN_IDX, + CAM_DATA5_IN_PAD_IN_IDX, + CAM_DATA6_IN_PAD_IN_IDX, + CAM_DATA7_IN_PAD_IN_IDX, + CAM_DATA8_IN_PAD_IN_IDX, + CAM_DATA9_IN_PAD_IN_IDX, + CAM_DATA10_IN_PAD_IN_IDX, + CAM_DATA11_IN_PAD_IN_IDX, + CAM_DATA12_IN_PAD_IN_IDX, + CAM_DATA13_IN_PAD_IN_IDX, + CAM_DATA14_IN_PAD_IN_IDX, + CAM_DATA15_IN_PAD_IN_IDX, + }, + .hsync_sig = CAM_H_SYNC_PAD_IN_IDX, + .vsync_sig = CAM_V_SYNC_PAD_IN_IDX, + .pclk_sig = CAM_PCLK_PAD_IN_IDX, + .de_sig = CAM_H_ENABLE_PAD_IN_IDX, + .clk_sig = CAM_CLK_PAD_OUT_IDX + } + } +}; diff --git a/components/esp_hal_cam/esp32s31/include/hal/cam_ll.h b/components/esp_hal_cam/esp32s31/include/hal/cam_ll.h new file mode 100644 index 00000000000..2bb647532f4 --- /dev/null +++ b/components/esp_hal_cam/esp32s31/include/hal/cam_ll.h @@ -0,0 +1,583 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include "hal/assert.h" +#include "hal/cam_types.h" +#include "hal/misc.h" +#include "soc/hp_sys_clkrst_struct.h" +#include "soc/lcd_cam_struct.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define CAM_LL_GET_HW(id) (((id) == 0) ? (&LCD_CAM) : NULL) + +#define CAM_LL_CLK_FRAC_DIV_N_MAX 256 // CAM_CLK = CAM_CLK_S / (N + b/a), the N register is 8 bit-width +#define CAM_LL_CLK_FRAC_DIV_AB_MAX 256 // CAM_CLK = CAM_CLK_S / (N + b/a), the a/b register is 8 bit-width +#define CAM_LL_PERIPH_NUM (1U) +#define CAM_LL_DATA_WIDTH_MAX (16U) + +/** + * @brief Enable the bus clock for CAM module + * + * @param group_id Group ID + * @param enable true to enable, false to disable + */ +static inline void cam_ll_enable_bus_clock(int group_id, bool en) +{ + (void)group_id; + // the core clock is a shared clock for both LCD and CAM + HP_SYS_CLKRST.lcdcam_lcdcam_ctrl0.reg_lcdcam_clk_en = en; + HP_SYS_CLKRST.lcdcam_ctrl0.reg_lcdcam_apb_clk_en = en; + HP_SYS_CLKRST.lcdcam_ctrl0.reg_lcdcam_sys_clk_en = en; +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance +#define cam_ll_enable_bus_clock(...) do { \ + (void)__DECLARE_RCC_RC_ATOMIC_ENV; \ + cam_ll_enable_bus_clock(__VA_ARGS__); \ + } while(0) + +/** + * @brief Reset the CAM module + * + * @param group_id Group ID + */ +static inline void cam_ll_reset_register(int group_id) +{ + (void)group_id; + HP_SYS_CLKRST.lcdcam_ctrl0.reg_lcdcam_apb_rst_en = 1; + HP_SYS_CLKRST.lcdcam_ctrl0.reg_lcdcam_apb_rst_en = 0; + HP_SYS_CLKRST.lcdcam_ctrl0.reg_lcdcam_rst_en = 1; + HP_SYS_CLKRST.lcdcam_ctrl0.reg_lcdcam_rst_en = 0; +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance +#define cam_ll_reset_register(...) do { \ + (void)__DECLARE_RCC_RC_ATOMIC_ENV; \ + cam_ll_reset_register(__VA_ARGS__); \ + } while(0) + +/** + * @brief Enable clock gating + * + * @param group_id Group ID + * @param en True to enable, False to disable + */ +static inline void cam_ll_enable_clk(int group_id, bool en) +{ + (void)group_id; + HP_SYS_CLKRST.lcdcam_cam_ctrl0.reg_cam_clk_en = en; +} + +/** + * @brief Select clock source for CAM peripheral + * + * @param group_id Group ID + * @param src Clock source + */ +static inline void cam_ll_select_clk_src(int group_id, cam_clock_source_t src) +{ + (void)group_id; + switch (src) { + case CAM_CLK_SRC_XTAL: + HP_SYS_CLKRST.lcdcam_cam_ctrl0.reg_cam_clk_src_sel = 0; + break; + case CAM_CLK_SRC_PLL160M: + HP_SYS_CLKRST.lcdcam_cam_ctrl0.reg_cam_clk_src_sel = 1; + break; + case CAM_CLK_SRC_APLL: + HP_SYS_CLKRST.lcdcam_cam_ctrl0.reg_cam_clk_src_sel = 2; + break; + default: + HP_SYS_CLKRST.lcdcam_cam_ctrl0.reg_cam_clk_src_sel = 3; + HAL_ASSERT(false); + break; + } +} + +/** + * @brief Get the CAM source clock type + * + * @param dev CAM register base address + * @param src The pointer to accept the CAM source clock type + */ +static inline void cam_ll_get_clk_src(lcd_cam_dev_t *dev, cam_clock_source_t *src) +{ + (void)dev; + switch (HP_SYS_CLKRST.lcdcam_cam_ctrl0.reg_cam_clk_src_sel) { + case 0: + *src = CAM_CLK_SRC_XTAL; + break; + case 1: + *src = CAM_CLK_SRC_PLL160M; + break; + case 2: + *src = CAM_CLK_SRC_APLL; + break; + default: + HAL_ASSERT(false); + break; + } +} + +/** + * @brief Set clock coefficient of CAM peripheral + * + * @param group_id Group ID + * @param div_num Integer part of the divider + * @param div_a denominator of the divider + * @param div_b numerator of the divider + */ +__attribute__((always_inline)) +static inline void cam_ll_set_group_clock_coeff(int group_id, int div_num, int div_a, int div_b) +{ + (void)group_id; + HAL_ASSERT(div_num > 0 && div_num <= CAM_LL_CLK_FRAC_DIV_N_MAX); + HAL_ASSERT(div_a >= 0 && div_a < CAM_LL_CLK_FRAC_DIV_AB_MAX); + HAL_ASSERT(div_b >= 0 && div_b < CAM_LL_CLK_FRAC_DIV_AB_MAX); + + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.lcdcam_cam_ctrl0, reg_cam_clk_div_num, div_num - 1); + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.lcdcam_cam_ctrl0, reg_cam_clk_div_denominator, div_a); + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.lcdcam_cam_ctrl0, reg_cam_clk_div_numerator, div_b); +} + +/** + * @brief Enable stop signal for CAM peripheral + * + * @param dev CAM register base address + * @param en True to stop when GDMA Rx FIFO is full, False to not stop + */ +static inline void cam_ll_enable_stop_signal(lcd_cam_dev_t *dev, bool en) +{ + dev->cam_ctrl.cam_stop_en = en; +} + +/** + * @brief Set vsync filter threshold value + * + * @param dev CAM register base address + * @param value Filter threshold value for CAM_VSYNC_SIGNAL, range [0, 7] + */ +static inline void cam_ll_set_vsync_filter_thres(lcd_cam_dev_t *dev, uint32_t value) +{ + dev->cam_ctrl.cam_vsync_filter_thres = value; +} + +/** + * @brief Enable to generate LCD_CAM_CAM_HS_INT + * + * @param dev CAM register base address + * @param en True to enable to generate LCD_CAM_CAM_HS_INT, False to disable + */ +static inline void cam_ll_enable_hs_line_int(lcd_cam_dev_t *dev, bool en) +{ + dev->cam_ctrl.cam_line_int_en = en; +} + +/** + * @brief Enable CAM_VSYNC to generate in_suc_eof + * + * @param dev CAM register base address + * @param en True to enable CAM_VSYNC to generate in_suc_eof, False to use LCD_CAM_CAM_REC_DATA_BYTELEN to control in_suc_eof + */ +static inline void cam_ll_enable_vsync_generate_eof(lcd_cam_dev_t *dev, bool en) +{ + dev->cam_ctrl.cam_vs_eof_en = en; +} + +/** + * @brief Enable to swap every two 8-bit input data + * + * @param dev CAM register base address + * @param en True to enable invert, False to disable invert + */ +static inline void cam_ll_enable_8bits_data_invert(lcd_cam_dev_t *dev, bool en) +{ + dev->cam_rgb_yuv.cam_conv_8bits_data_inv = en; +} + +/** + * @brief Enable YUV-RGB converter + * + * @param dev CAM register base address + * @param en True to enable converter, False to disable converter + */ +static inline void cam_ll_enable_rgb_yuv_convert(lcd_cam_dev_t *dev, bool en) +{ + dev->cam_rgb_yuv.cam_conv_enable = en; +} + +/** + * @brief Set convert data line width + * + * @param dev CAM register base address + * @param width data line width (8 or 16) + */ +static inline void cam_ll_set_convert_data_width(lcd_cam_dev_t *dev, uint32_t width) +{ + HAL_ASSERT(width == 8 || width == 16); + dev->cam_rgb_yuv.cam_conv_mode_8bits_on = (width == 8) ? 1 : 0; +} + +/** + * @brief Set the color range of input data + * + * @param dev CAM register base address + * @param range Color range + */ +static inline void cam_ll_set_input_color_range(lcd_cam_dev_t *dev, color_range_t range) +{ + if (range == COLOR_RANGE_LIMIT) { + dev->cam_rgb_yuv.cam_conv_data_in_mode = 0; + } else if (range == COLOR_RANGE_FULL) { + dev->cam_rgb_yuv.cam_conv_data_in_mode = 1; + } +} + +/** + * @brief Set the color range of output data + * + * @param dev CAM register base address + * @param range Color range + */ +static inline void cam_ll_set_output_color_range(lcd_cam_dev_t *dev, color_range_t range) +{ + if (range == COLOR_RANGE_LIMIT) { + dev->cam_rgb_yuv.cam_conv_data_out_mode = 0; + } else if (range == COLOR_RANGE_FULL) { + dev->cam_rgb_yuv.cam_conv_data_out_mode = 1; + } +} + +/** + * @brief Set YUV conversion standard + * + * @param dev CAM register base address + * @param std YUV conversion standard + */ +static inline void cam_ll_set_yuv_convert_std(lcd_cam_dev_t *dev, color_conv_std_rgb_yuv_t std) +{ + if (std == COLOR_CONV_STD_RGB_YUV_BT601) { + dev->cam_rgb_yuv.cam_conv_protocol_mode = 0; + } else if (std == COLOR_CONV_STD_RGB_YUV_BT709) { + dev->cam_rgb_yuv.cam_conv_protocol_mode = 1; + } +} + +/** + * @brief Set converter mode + * + * @param dev CAM register base address + * @param src_fourcc Source format FourCC + * @param dst_fourcc Destination format FourCC + */ +static inline void cam_ll_set_convert_mode(lcd_cam_dev_t *dev, uint32_t src_fourcc, uint32_t dst_fourcc) +{ + bool src_is_yuv = (src_fourcc == ESP_COLOR_FOURCC_OUYY_EVYY || + src_fourcc == ESP_COLOR_FOURCC_YVYU || + src_fourcc == ESP_COLOR_FOURCC_YUYV || + src_fourcc == ESP_COLOR_FOURCC_UYVY || + src_fourcc == ESP_COLOR_FOURCC_VYUY || + src_fourcc == ESP_COLOR_FOURCC_YUV); + bool dst_is_yuv = (dst_fourcc == ESP_COLOR_FOURCC_OUYY_EVYY || + dst_fourcc == ESP_COLOR_FOURCC_YVYU || + dst_fourcc == ESP_COLOR_FOURCC_YUYV || + dst_fourcc == ESP_COLOR_FOURCC_UYVY || + dst_fourcc == ESP_COLOR_FOURCC_VYUY || + dst_fourcc == ESP_COLOR_FOURCC_YUV); + + if (src_is_yuv && dst_is_yuv) { + HAL_ASSERT(src_fourcc != dst_fourcc); + dev->cam_rgb_yuv.cam_conv_trans_mode = 1; + dev->cam_rgb_yuv.cam_conv_yuv_mode = (src_fourcc == ESP_COLOR_FOURCC_OUYY_EVYY) ? 1 : 0; + dev->cam_rgb_yuv.cam_conv_yuv2yuv_mode = (dst_fourcc == ESP_COLOR_FOURCC_OUYY_EVYY) ? 1 : 0; + } else if (src_is_yuv) { + dev->cam_rgb_yuv.cam_conv_trans_mode = 0; + dev->cam_rgb_yuv.cam_conv_yuv2yuv_mode = 3; + dev->cam_rgb_yuv.cam_conv_yuv_mode = (src_fourcc == ESP_COLOR_FOURCC_OUYY_EVYY) ? 1 : 0; + } else if (dst_is_yuv) { + dev->cam_rgb_yuv.cam_conv_trans_mode = 1; + dev->cam_rgb_yuv.cam_conv_yuv2yuv_mode = 3; + dev->cam_rgb_yuv.cam_conv_yuv_mode = (dst_fourcc == ESP_COLOR_FOURCC_OUYY_EVYY) ? 1 : 0; + } +} + +/** + * @brief Set camera received data byte length + * + * @param dev CAM register base address + * @param length received data byte length, range [0, 0xFFFF] + */ +static inline void cam_ll_set_recv_data_bytelen(lcd_cam_dev_t *dev, uint32_t length) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->cam_ctrl1, cam_rec_data_bytelen, length); +} + +/** + * @brief Set line number to trigger interrupt + * + * @param dev CAM register base address + * @param number line number to trigger hs interrupt, range [0, 0x3F] + */ +static inline void cam_ll_set_line_int_num(lcd_cam_dev_t *dev, uint32_t number) +{ + dev->cam_ctrl1.cam_line_int_num = number; +} + +/** + * @brief Whether to invert the input signal CAM_PCLK + * + * @param dev CAM register base address + * @param en True to invert, False to not invert + */ +static inline void cam_ll_enable_invert_pclk(lcd_cam_dev_t *dev, bool en) +{ + dev->cam_ctrl1.cam_clk_inv = en; +} + +/** + * @brief Enable CAM_VSYNC filter function + * + * @param dev CAM register base address + * @param en True to enable, False to bypass + */ +static inline void cam_ll_enable_vsync_filter(lcd_cam_dev_t *dev, bool en) +{ + dev->cam_ctrl1.cam_vsync_filter_en = en; +} + +/** + * @brief Set CAM input data width + * + * @param dev CAM register base address + * @param stride 16: The bit number of input data is 9~16. 8: The bit number of input data is 0~8. + */ +static inline void cam_ll_set_input_data_width(lcd_cam_dev_t *dev, uint32_t stride) +{ + switch (stride) { + case 8: + dev->cam_ctrl1.cam_2byte_en = 0; + break; + case 16: + dev->cam_ctrl1.cam_2byte_en = 1; + break; + default: + HAL_ASSERT(false); + break; + } +} + +/** + * @brief Whether to invert CAM_DE + * + * @param dev CAM register base address + * @param en True to invert, False to not invert + */ +static inline void cam_ll_enable_invert_de(lcd_cam_dev_t *dev, bool en) +{ + dev->cam_ctrl1.cam_de_inv = en; +} + +/** + * @brief Whether to invert CAM_HSYNC + * + * @param dev CAM register base address + * @param en True to invert, False to not invert + */ +static inline void cam_ll_enable_invert_hsync(lcd_cam_dev_t *dev, bool en) +{ + dev->cam_ctrl1.cam_hsync_inv = en; +} + +/** + * @brief Whether to invert CAM_VSYNC + * + * @param dev CAM register base address + * @param en True to invert, False to not invert + */ +static inline void cam_ll_enable_invert_vsync(lcd_cam_dev_t *dev, bool en) +{ + dev->cam_ctrl1.cam_vsync_inv = en; +} + +/** + * @brief Enable the mode to control the input control signals + * + * @param dev CAM register base address + * @param mode 1: Input control signals are CAM_DE, CAM_HSYNC and CAM_VSYNC; + * 0: Input control signals are CAM_DE and CAM_VSYNC. CAM_HSYNC and CAM_DE are all 1 the the same time. + */ +static inline void cam_ll_set_vh_de_mode(lcd_cam_dev_t *dev, bool enable) +{ + dev->cam_ctrl1.cam_vh_de_mode_en = enable; +} + +/** + * @brief Get the mode of input control signals + * + * @param dev CAM register base address + * @param en The pointer to accept the vh_de mode status. 1: Input control signals are CAM_DE, CAM_HSYNC and CAM_VSYNC; + * 0: Input control signals are CAM_DE and CAM_VSYNC. CAM_HSYNC and CAM_DE are all 1 the the same time. + */ +static inline void cam_ll_get_vh_de_mode(lcd_cam_dev_t *dev, bool *en) +{ + *en = dev->cam_ctrl1.cam_vh_de_mode_en; +} + +/** + * @brief Set the wire width of CAM output + * + * @param dev CAM register base address + * @param width CAM output wire width + */ +static inline void cam_ll_set_data_wire_width(lcd_cam_dev_t *dev, uint32_t width) +{ + (void)dev; + (void)width; + // data line width is same as data stride that set in `cam_ll_set_input_data_width` +} + +/** + * @brief Start the CAM transaction + * + * @param dev CAM register base address + */ +__attribute__((always_inline)) +static inline void cam_ll_start(lcd_cam_dev_t *dev) +{ + dev->cam_ctrl.cam_update_reg = 1; + dev->cam_ctrl1.cam_start = 1; +} + +/** + * @brief Stop the CAM transaction + * + * @param dev CAM register base address + */ +__attribute__((always_inline)) +static inline void cam_ll_stop(lcd_cam_dev_t *dev) +{ + dev->cam_ctrl1.cam_start = 0; + dev->cam_ctrl.cam_update_reg = 1; // self clear +} + +/** + * @brief Whether to reverse the data bit order + * + * @note It acts before the YUV-RGB converter + * + * @param dev CAM register base address + * @param en True to reverse, False to not reverse + */ +__attribute__((always_inline)) +static inline void cam_ll_reverse_dma_data_bit_order(lcd_cam_dev_t *dev, bool en) +{ + dev->cam_ctrl.cam_bit_order = en; +} + +/** + * @brief Whether to swap adjacent two bytes + * + * @note This acts before the YUV-RGB converter, mainly to change the data endian. + * {B1,B0},{B3,B2} => {B0,B1}{B2,B3} + * + * @param dev CAM register base address + * @param en True to swap the byte order, False to not swap + */ +__attribute__((always_inline)) +static inline void cam_ll_swap_dma_data_byte_order(lcd_cam_dev_t *dev, bool en) +{ + dev->cam_ctrl.cam_byte_order = en; +} + +/** + * @brief Reset camera module + * + * @param dev CAM register base address + */ +__attribute__((always_inline)) +static inline void cam_ll_reset(lcd_cam_dev_t *dev) +{ + dev->cam_ctrl1.cam_reset = 1; // self clear +} + +/** + * @brief Reset Async RX FIFO + * + * @param dev CAM register base address + */ +__attribute__((always_inline)) +static inline void cam_ll_fifo_reset(lcd_cam_dev_t *dev) +{ + dev->cam_ctrl1.cam_afifo_reset = 1; // self clear +} + +/** + * @brief Enable/disable interrupt by mask + * + * @param dev CAM register base address + * @param mask Interrupt mask + * @param en True to enable interrupt, False to disable interrupt + */ +static inline void cam_ll_enable_interrupt(lcd_cam_dev_t *dev, uint32_t mask, bool en) +{ + if (en) { + dev->lc_dma_int_ena.val |= mask & 0x2c; + } else { + dev->lc_dma_int_ena.val &= ~(mask & 0x2c); + } +} +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define cam_ll_enable_interrupt(...) do { \ + (void)__DECLARE_RCC_ATOMIC_ENV; \ + cam_ll_enable_interrupt(__VA_ARGS__); \ + } while(0) + +/** + * @brief Get interrupt status value + * + * @param dev CAM register base address + * @return Interrupt status value + */ +__attribute__((always_inline)) +static inline uint32_t cam_ll_get_interrupt_status(lcd_cam_dev_t *dev) +{ + return dev->lc_dma_int_st.val & 0x2c; +} + +/** + * @brief Clear interrupt status by mask + * + * @param dev CAM register base address + * @param mask Interrupt status mask + */ +__attribute__((always_inline)) +static inline void cam_ll_clear_interrupt_status(lcd_cam_dev_t *dev, uint32_t mask) +{ + dev->lc_dma_int_clr.val = mask & 0x2c; +} + +/** + * @brief Get address of interrupt status register address + * + * @param dev CAM register base address + * @return Interrupt status register address + */ +static inline volatile void *cam_ll_get_interrupt_status_reg(lcd_cam_dev_t *dev) +{ + return &dev->lc_dma_int_st; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hal_clock/esp32s31/include/hal/clk_gate_ll.h b/components/esp_hal_clock/esp32s31/include/hal/clk_gate_ll.h index 60942aaf86e..42ac40569b7 100644 --- a/components/esp_hal_clock/esp32s31/include/hal/clk_gate_ll.h +++ b/components/esp_hal_clock/esp32s31/include/hal/clk_gate_ll.h @@ -11,6 +11,7 @@ #include "esp_attr.h" #include "soc/soc.h" #include "soc/reset_reasons.h" +#include "soc/hp_sys_clkrst_struct.h" #include "soc/lp_clkrst_struct.h" #include "soc/lp_clkrst_reg.h" @@ -33,6 +34,29 @@ FORCE_INLINE_ATTR void _clk_gate_ll_rtc_fast_to_lp_periph_en(bool enable) _clk_gate_ll_rtc_fast_to_lp_periph_en(__VA_ARGS__); \ } while(0) +/** + * @brief Set the default clock gate configuration + */ +static inline void periph_ll_clk_gate_set_default(soc_reset_reason_t rst_reason) +{ + if ((rst_reason == RESET_REASON_CHIP_POWER_ON) || (rst_reason == RESET_REASON_CORE_PMU_PWR_DOWN) || + (rst_reason == RESET_REASON_SYS_BROWN_OUT) || (rst_reason == RESET_REASON_SYS_RWDT) || + (rst_reason == RESET_REASON_SYS_SUPER_WDT) || (rst_reason == RESET_REASON_CORE_SW) || + (rst_reason == RESET_REASON_CORE_MWDT0) || (rst_reason == RESET_REASON_CORE_MWDT1) || + (rst_reason == RESET_REASON_CORE_RWDT) || (rst_reason == RESET_REASON_CORE_PWR_GLITCH) || + (rst_reason == RESET_REASON_CORE_EFUSE_CRC) || (rst_reason == RESET_REASON_CORE_USB_JTAG) || + (rst_reason == RESET_REASON_CORE_USB_UART) + ) { + /* + * Default lcdcam_lcdcam_ctrl0: + * reg_lcdcam_clk_src_sel: 1 (BBPLL 120 MHz path, shared by LCD and CAM) + * reg_lcdcam_clk_div_num: 1 (divide by 2 → 60 MHz) + */ + HP_SYS_CLKRST.lcdcam_lcdcam_ctrl0.reg_lcdcam_clk_src_sel = 1; + HP_SYS_CLKRST.lcdcam_lcdcam_ctrl0.reg_lcdcam_clk_div_num = 1; + } +} + #ifdef __cplusplus } #endif diff --git a/components/esp_hal_lcd/esp32s31/include/hal/lcd_ll.h b/components/esp_hal_lcd/esp32s31/include/hal/lcd_ll.h index 653ac8da2e7..7fc969ce91c 100644 --- a/components/esp_hal_lcd/esp32s31/include/hal/lcd_ll.h +++ b/components/esp_hal_lcd/esp32s31/include/hal/lcd_ll.h @@ -71,6 +71,8 @@ typedef enum { static inline void lcd_ll_enable_bus_clock(int group_id, bool enable) { (void)group_id; + // the core clock is a shared clock for both LCD and CAM + HP_SYS_CLKRST.lcdcam_lcdcam_ctrl0.reg_lcdcam_clk_en = enable; HP_SYS_CLKRST.lcdcam_ctrl0.reg_lcdcam_apb_clk_en = enable; HP_SYS_CLKRST.lcdcam_ctrl0.reg_lcdcam_sys_clk_en = enable; } @@ -112,7 +114,6 @@ static inline void _lcd_ll_reset_register(int group_id) static inline void lcd_ll_enable_clock(lcd_cam_dev_t *dev, bool en) { (void)dev; - HP_SYS_CLKRST.lcdcam_lcdcam_ctrl0.reg_lcdcam_clk_en = en; HP_SYS_CLKRST.lcdcam_lcd_ctrl0.reg_lcd_clk_en = en; } diff --git a/components/esp_system/port/soc/esp32s31/clk.c b/components/esp_system/port/soc/esp32s31/clk.c index 468c4ccd0fd..dc14844cfa3 100644 --- a/components/esp_system/port/soc/esp32s31/clk.c +++ b/components/esp_system/port/soc/esp32s31/clk.c @@ -25,6 +25,7 @@ #include "esp_private/esp_sleep_internal.h" #include "esp_private/esp_modem_clock.h" #include "esp_private/periph_ctrl.h" +#include "hal/clk_gate_ll.h" #include "esp_private/esp_clk.h" #include "esp_private/esp_pmu.h" #include "esp_rom_serial_output.h" @@ -194,4 +195,6 @@ __attribute__((weak)) void esp_perip_clk_init(void) : MODEM_CLOCK_LPCLK_SRC_RC_SLOW); modem_clock_select_lp_clock_source(PERIPH_WIFI_MODULE, modem_lpclk_src, 0); #endif + + periph_ll_clk_gate_set_default(esp_rom_get_reset_reason(0)); } diff --git a/components/soc/esp32s31/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s31/include/soc/Kconfig.soc_caps.in index 1b84974ca90..3aab9b38bfe 100644 --- a/components/soc/esp32s31/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s31/include/soc/Kconfig.soc_caps.in @@ -47,6 +47,10 @@ config SOC_LCDCAM_SUPPORTED bool default y +config SOC_LCDCAM_CAM_SUPPORTED + bool + default y + config SOC_LCDCAM_I80_LCD_SUPPORTED bool default y @@ -911,6 +915,10 @@ config SOC_KEY_MANAGER_ECDSA_KEY_DEPLOY bool default y +config SOC_LCDCAM_CAM_SUPPORT_RGB_YUV_CONV + bool + default y + config SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS int default 3 diff --git a/components/soc/esp32s31/include/soc/clk_tree_defs.h b/components/soc/esp32s31/include/soc/clk_tree_defs.h index 32258c171a2..cdfc7916a6c 100644 --- a/components/soc/esp32s31/include/soc/clk_tree_defs.h +++ b/components/soc/esp32s31/include/soc/clk_tree_defs.h @@ -179,6 +179,23 @@ typedef enum { LCD_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the default choice */ } soc_periph_lcd_clk_src_t; +//////////////////////////////////////////////////CAM/////////////////////////////////////////////////////////////////// + +/** + * @brief Array initializer for all supported clock sources of CAM + */ +#define SOC_CAM_CLKS {SOC_MOD_CLK_PLL_F160M, SOC_MOD_CLK_XTAL, SOC_MOD_CLK_APLL} + +/** + * @brief Type of CAM clock source + */ +typedef enum { + CAM_CLK_SRC_PLL160M = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the source clock */ + CAM_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ + CAM_CLK_SRC_APLL = SOC_MOD_CLK_APLL, /*!< Select APLL as the source clock */ + CAM_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the default choice */ +} soc_periph_cam_clk_src_t; + //////////////////////////////////////////////////SYSTIMER////////////////////////////////////////////////////////////// /** diff --git a/components/soc/esp32s31/include/soc/soc_caps.h b/components/soc/esp32s31/include/soc/soc_caps.h index 93a8db92bb6..89c3c9a895b 100644 --- a/components/soc/esp32s31/include/soc/soc_caps.h +++ b/components/soc/esp32s31/include/soc/soc_caps.h @@ -35,7 +35,7 @@ #define SOC_DMA2D_SUPPORTED 1 #define SOC_GPTIMER_SUPPORTED 1 #define SOC_LCDCAM_SUPPORTED 1 -// #define SOC_LCDCAM_CAM_SUPPORTED 1 // TODO: [ESP32S31] IDF-14722 +#define SOC_LCDCAM_CAM_SUPPORTED 1 #define SOC_LCDCAM_I80_LCD_SUPPORTED 1 #define SOC_LCDCAM_RGB_LCD_SUPPORTED 1 #define SOC_LCD_I80_SUPPORTED 1 @@ -365,6 +365,10 @@ // TODO: [ESP32S31] IDF-14626 #define SOC_KEY_MANAGER_ECDSA_KEY_DEPLOY 1 /*!< Key manager responsible to deploy ECDSA key */ // #define SOC_KEY_MANAGER_FE_KEY_DEPLOY 1 /*!< Key manager responsible to deploy Flash Encryption key */ + +/*--------------------------- CAM ---------------------------------*/ +#define SOC_LCDCAM_CAM_SUPPORT_RGB_YUV_CONV (1) + /*-------------------------- Secure Boot CAPS----------------------------*/ // TODO: [ESP32S31] IDF-14629 #define SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS 3 diff --git a/docs/en/api-reference/peripherals/camera_driver.rst b/docs/en/api-reference/peripherals/camera_driver.rst index 0784ecad238..b76fb20a4a2 100644 --- a/docs/en/api-reference/peripherals/camera_driver.rst +++ b/docs/en/api-reference/peripherals/camera_driver.rst @@ -343,6 +343,7 @@ 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 them on an 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 them on an LCD screen via a DSI interface. +* :example:`peripherals/camera/dvp_dsi` – Demonstrates how to use the ``esp_driver_cam`` component to capture DVP camera sensor data and display it on a MIPI DSI LCD. API Reference ------------- diff --git a/docs/zh_CN/api-reference/peripherals/camera_driver.rst b/docs/zh_CN/api-reference/peripherals/camera_driver.rst index 38a9212cead..df87b537205 100644 --- a/docs/zh_CN/api-reference/peripherals/camera_driver.rst +++ b/docs/zh_CN/api-reference/peripherals/camera_driver.rst @@ -343,6 +343,7 @@ IRAM 安全 * :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 屏幕上。 +* :example:`peripherals/camera/dvp_dsi` 演示了如何使用 ``esp_driver_cam`` 组件通过 DVP 接口采集摄像头传感器数据,并在 MIPI DSI LCD 上显示。 API 参考 -------- diff --git a/examples/peripherals/.build-test-rules.yml b/examples/peripherals/.build-test-rules.yml index 423e37d3508..19141db7929 100644 --- a/examples/peripherals/.build-test-rules.yml +++ b/examples/peripherals/.build-test-rules.yml @@ -73,19 +73,6 @@ examples/peripherals/camera/dvp_isp_dsi: - esp_driver_dma - soc -examples/peripherals/camera/dvp_spi_lcd: - disable: - - if: SOC_LCDCAM_CAM_SUPPORTED != 1 - disable_test: - - if: IDF_TARGET == "esp32s3" - temporary: true - reason: lack of runners - depends_components: - - esp_lcd - - esp_driver_cam - - esp_driver_dma - - soc - examples/peripherals/camera/mipi_isp_dsi: disable: - if: SOC_MIPI_CSI_SUPPORTED != 1 or SOC_MIPI_DSI_SUPPORTED != 1 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 c5a0688d656..fd10524296b 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 @@ -1,12 +1,12 @@ /* - * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ -#include -#include #include #include "sdkconfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" #include "esp_attr.h" #include "esp_log.h" #include "esp_err.h" @@ -36,9 +36,9 @@ void example_sensor_init(example_sensor_config_t *sensor_config, example_sensor_ //---------------SCCB Init------------------// esp_cam_sensor_config_t cam_config = { - .reset_pin = -1, - .pwdn_pin = -1, - .xclk_pin = -1, + .reset_pin = sensor_config->reset_pin, + .pwdn_pin = sensor_config->pwdn_pin, + .xclk_pin = sensor_config->xclk_pin, }; esp_cam_sensor_device_t *cam = NULL; diff --git a/examples/peripherals/camera/common_components/sensor_init/idf_component.yml b/examples/peripherals/camera/common_components/sensor_init/idf_component.yml index 59b5f0ae183..8d6cb4bf49b 100644 --- a/examples/peripherals/camera/common_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: "^1.2.1" + espressif/esp_cam_sensor: "^2.1.0" 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 index 745a99caa39..5f181a73fc6 100644 --- 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 @@ -28,6 +28,9 @@ 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 */ + int reset_pin; /* Sensor: reset GPIO number, -1 if unused */ + int pwdn_pin; /* Sensor: power-down GPIO number, -1 if unused */ + int xclk_pin; /* Sensor: XCLK GPIO number, -1 if unused */ 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; diff --git a/examples/peripherals/camera/dvp_dsi/README.md b/examples/peripherals/camera/dvp_dsi/README.md index d2bdbcd1f63..0db7fe544b6 100644 --- a/examples/peripherals/camera/dvp_dsi/README.md +++ b/examples/peripherals/camera/dvp_dsi/README.md @@ -132,19 +132,10 @@ If you see the following console output, your example should be running correctl I (1481) main_task: Calling app_main() I (1481) ek79007: version: 1.0.2 I (1701) ov2640: Detected Camera sensor PID=0x26 -I (1701) sensor_init: fmt[0].name:DVP_8bit_20Minput_RGB565_640x480_6fps -I (1701) sensor_init: fmt[1].name:DVP_8bit_20Minput_YUV422_640x480_6fps -I (1711) sensor_init: fmt[2].name:DVP_8bit_20Minput_JPEG_640x480_25fps -I (1711) sensor_init: fmt[3].name:DVP_8bit_20Minput_RGB565_240x240_25fps -I (1721) sensor_init: fmt[4].name:DVP_8bit_20Minput_YUV422_240x240_25fps -I (1721) sensor_init: fmt[5].name:DVP_8bit_20Minput_JPEG_320x240_50fps -I (1731) sensor_init: fmt[6].name:DVP_8bit_20Minput_JPEG_1280x720_12fps -I (1741) sensor_init: fmt[7].name:DVP_8bit_20Minput_JPEG_1600x1200_12fps -I (1741) sensor_init: fmt[8].name:DVP_8bit_20Minput_RAW8_800x640_30fps -I (1751) sensor_init: fmt[9].name:DVP_8bit_20Minput_RAW8_800x640_15fps -I (1761) sensor_init: fmt[10].name:DVP_8bit_20Minput_RAW8_800x800_15fps -I (1761) sensor_init: fmt[11].name:DVP_8bit_20Minput_RAW8_1024x600_15fps -I (8291) sensor_init: Format in use:DVP_8bit_20Minput_RGB565_640x480_6fps +I (1701) sensor_init: fmt[0].name:DVP_8bit_20Minput_RGB565_LE_640x480_6fps +I (1701) sensor_init: fmt[1].name:DVP_8bit_20Minput_YUV422_UYVY_640x480_6fps +I (1711) sensor_init: fmt[2].name:DVP_8bit_20Minput_RGB565_LE_240x240_25fps +I (8291) sensor_init: Format in use:DVP_8bit_20Minput_RGB565_LE_640x480_6fps ``` diff --git a/examples/peripherals/camera/dvp_dsi/main/dvp_dsi_main.c b/examples/peripherals/camera/dvp_dsi/main/dvp_dsi_main.c index f2bbce28956..a9b2033d6e3 100644 --- a/examples/peripherals/camera/dvp_dsi/main/dvp_dsi_main.c +++ b/examples/peripherals/camera/dvp_dsi/main/dvp_dsi_main.c @@ -125,6 +125,9 @@ void app_main(void) .i2c_port_num = I2C_NUM_0, .i2c_sda_io_num = EXAMPLE_DVP_CAM_SCCB_SDA_IO, .i2c_scl_io_num = EXAMPLE_DVP_CAM_SCCB_SCL_IO, + .reset_pin = -1, + .pwdn_pin = -1, + .xclk_pin = EXAMPLE_DVP_CAM_XCLK_IO, .port = ESP_CAM_SENSOR_DVP, .format_name = EXAMPLE_CAM_FORMAT, }; diff --git a/examples/peripherals/camera/dvp_dsi/main/example_config.h b/examples/peripherals/camera/dvp_dsi/main/example_config.h index eb76ca211f4..4c97fec2c8e 100644 --- a/examples/peripherals/camera/dvp_dsi/main/example_config.h +++ b/examples/peripherals/camera/dvp_dsi/main/example_config.h @@ -61,13 +61,13 @@ extern "C" { #if CONFIG_EXAMPLE_CAM_HRES_640 #if CONFIG_EXAMPLE_CAM_VRES_480 -#define EXAMPLE_CAM_FORMAT "DVP_8bit_20Minput_RGB565_640x480_6fps" +#define EXAMPLE_CAM_FORMAT "DVP_8bit_20Minput_RGB565_LE_640x480_6fps" #endif #elif CONFIG_EXAMPLE_CAM_HRES_240 #if CONFIG_EXAMPLE_CAM_VRES_240 -#define EXAMPLE_CAM_FORMAT "DVP_8bit_20Minput_RGB565_240x240_25fps" +#define EXAMPLE_CAM_FORMAT "DVP_8bit_20Minput_RGB565_LE_240x240_25fps" #endif #endif diff --git a/examples/peripherals/camera/dvp_dsi/sdkconfig.defaults b/examples/peripherals/camera/dvp_dsi/sdkconfig.defaults index bc0080e2fe6..ece719cbe6b 100644 --- a/examples/peripherals/camera/dvp_dsi/sdkconfig.defaults +++ b/examples/peripherals/camera/dvp_dsi/sdkconfig.defaults @@ -1,2 +1,4 @@ CONFIG_CAMERA_OV2640=y +CONFIG_CAMERA_OV2640_DVP_RGB565_640X480_6FPS=y +CONFIG_CAMERA_OV2640_DVP_RGB565_240X240_25FPS=y CONFIG_CAM_CTRL_SPI_ENABLE=n diff --git a/examples/peripherals/camera/dvp_isp_dsi/README.md b/examples/peripherals/camera/dvp_isp_dsi/README.md index aafc38da838..15340a210ca 100644 --- a/examples/peripherals/camera/dvp_isp_dsi/README.md +++ b/examples/peripherals/camera/dvp_isp_dsi/README.md @@ -134,17 +134,10 @@ If you see the following console output, your example should be running correctl 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 (1549) sensor_init: fmt[0].name:DVP_8bit_20Minput_YUV422_UYVY_640x480_6fps +I (1559) sensor_init: fmt[1].name:DVP_8bit_20Minput_RAW8_800x640_15fps +I (1569) sensor_init: fmt[2].name:DVP_8bit_20Minput_RAW8_800x800_15fps +I (1579) sensor_init: fmt[3].name:DVP_8bit_20Minput_RAW8_1024x600_15fps I (2609) sensor_init: Format in use:DVP_8bit_20Minput_RAW8_1024x600_15fps ``` 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 6bd754312e8..63c7d4ab618 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 @@ -105,6 +105,9 @@ void app_main(void) .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, + .reset_pin = -1, + .pwdn_pin = -1, + .xclk_pin = EXAMPLE_ISP_DVP_CAM_XCLK_IO, .port = ESP_CAM_SENSOR_DVP, .format_name = EXAMPLE_CAM_FORMAT, }; diff --git a/examples/peripherals/camera/dvp_isp_dsi/sdkconfig.defaults b/examples/peripherals/camera/dvp_isp_dsi/sdkconfig.defaults index 9bb229096cb..aa4d08b0797 100644 --- a/examples/peripherals/camera/dvp_isp_dsi/sdkconfig.defaults +++ b/examples/peripherals/camera/dvp_isp_dsi/sdkconfig.defaults @@ -1,4 +1,8 @@ CONFIG_CAMERA_OV2640=y CONFIG_CAMERA_SC030IOT=y +CONFIG_CAMERA_SC030IOT_DVP_RAW8_640X480_26FPS=y +CONFIG_CAMERA_OV2640_DVP_RAW8_800X640_15FPS=y +CONFIG_CAMERA_OV2640_DVP_RAW8_800X800_15FPS=y +CONFIG_CAMERA_OV2640_DVP_RAW8_1024X600_15FPS=y CONFIG_EXAMPLE_MIPI_DSI_DISP_USE_DMA2D=y CONFIG_CAM_CTRL_SPI_ENABLE=n diff --git a/examples/peripherals/camera/dvp_spi_lcd/CMakeLists.txt b/examples/peripherals/camera/dvp_spi_lcd/CMakeLists.txt deleted file mode 100644 index 1beccf8b5e9..00000000000 --- a/examples/peripherals/camera/dvp_spi_lcd/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# 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.22) - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -# "Trim" the build. Include the minimal set of components, main, and anything it depends on. -idf_build_set_property(MINIMAL_BUILD ON) -project(dvp_spi_lcd) diff --git a/examples/peripherals/camera/dvp_spi_lcd/README.md b/examples/peripherals/camera/dvp_spi_lcd/README.md deleted file mode 100644 index 8c28c8e3656..00000000000 --- a/examples/peripherals/camera/dvp_spi_lcd/README.md +++ /dev/null @@ -1,137 +0,0 @@ -| Supported Targets | ESP32-P4 | ESP32-S3 | -| ----------------- | -------- | -------- | - - -# DVP Camera display via LCD example - -## Overview - -This example demonstrates how to use the esp_driver_cam component to capture DVP camera sensor signals and display it via LCD 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 LCD 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 - -- ESP32S3 devkit with OV2640 camera sensor and ST7789 LCD screen -- or an ESP32S3-EYE dev-kit - -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 - ┌────────────────────────────────────────────────┐ ┌─────────────────────────────────────────────────────────┐ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ ┌───────────────┴─────────────┴──────────────────┐ │ - │ │ │ ┌──────────┴───────────┐ - │ │ │ LCD MOSI │ │ - │ │ ├───────────────────────────┤ │ - ┌───────────┴─────────┐ │ │ │ │ - │ │ │ │ LCD CLK │ │ - │ │ │ ├───────────────────────────┤ │ - │ │ XCLK │ ESP_CHIP │ │ │ - │ DVP Camera ├──────────────────────┤ │ LCD CS │ LCD Screen │ - │ │ │ ├───────────────────────────┤ │ - │ │ D0~7 │ │ │ │ - │ ├──────────────────────┤ │ LCD DC │ │ - │ │ │ ├───────────────────────────┤ │ - │ │ PCLK │ │ │ │ - │ ├──────────────────────┤ │ LCD BACKLIGHT │ │ - │ │ │ ├───────────────────────────┤ │ - │ │ VSYNC │ │ │ │ - │ ├──────────────────────┤ │ │ │ - │ │ │ │ │ │ - │ │ 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-S3 as the chip target, run: - -``` -idf.py set-target esp32s3 -``` - - -### 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 -``` - -Available options for the camera sensor output horizontal/vertical resolution can be seen in ``menuconfig`` > ``Example Configuration``. - - -### Build and Flash - -Execute the following command to build the project, flash it to your development board, and run the monitor tool to view the serial output: - -``` -idf.py build flash monitor -``` - -This command can be reduced to `idf.py flash monitor`. - -If the above command fails, check the log on the serial monitor which usually provides information on the possible cause of the issue. - -To exit the serial monitor, use `Ctrl` + `]`. - - -## Example Output - -If you see the following console output, your example should be running correctly: - -``` -I (1481) main_task: Calling app_main() -I (278) dvp_spi_lcd: Init SPI bus -I (278) dvp_spi_lcd: New panel IO SPI -I (278) dvp_spi_lcd: New ST7789 panel -I (278) dvp_spi_lcd: Reset and init panel -I (408) dvp_spi_lcd: Turn on display -I (408) dvp_spi_lcd: Screen lit up now! - -``` - - -## Reference - -- [ESP-IDF: Camera Controller Driver](https://docs.espressif.com/projects/esp-idf/en/latest/esp32p4/api-reference/peripherals/camera_driver.html) diff --git a/examples/peripherals/camera/dvp_spi_lcd/main/CMakeLists.txt b/examples/peripherals/camera/dvp_spi_lcd/main/CMakeLists.txt deleted file mode 100644 index 526570d89ce..00000000000 --- a/examples/peripherals/camera/dvp_spi_lcd/main/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register(SRCS "dvp_spi_lcd_main.c" - INCLUDE_DIRS "." - REQUIRES esp_mm esp_driver_cam esp_driver_i2c esp_lcd - PRIV_REQUIRES esp_driver_ledc - ) diff --git a/examples/peripherals/camera/dvp_spi_lcd/main/Kconfig.projbuild b/examples/peripherals/camera/dvp_spi_lcd/main/Kconfig.projbuild deleted file mode 100644 index de1d53bbbea..00000000000 --- a/examples/peripherals/camera/dvp_spi_lcd/main/Kconfig.projbuild +++ /dev/null @@ -1,44 +0,0 @@ -menu "Example Configuration" - - choice EXAMPLE_CAM_HRES - bool "Set camera horizontal resolution" - default EXAMPLE_CAM_HRES_240 - - config EXAMPLE_CAM_HRES_640 - bool "640" - config EXAMPLE_CAM_HRES_240 - bool "240" - endchoice - - config EXAMPLE_CAM_HRES - int - default 640 if EXAMPLE_CAM_HRES_640 - default 240 if EXAMPLE_CAM_HRES_240 - - choice EXAMPLE_CAM_VRES - bool "Set camera vertical resolution" - default EXAMPLE_CAM_VRES_480 if EXAMPLE_CAM_HRES_640 - default EXAMPLE_CAM_VRES_240 if EXAMPLE_CAM_HRES_240 - - config EXAMPLE_CAM_VRES_480 - bool "480" - config EXAMPLE_CAM_VRES_240 - bool "240" - endchoice - - config EXAMPLE_CAM_VRES - int - default 480 if EXAMPLE_CAM_VRES_480 - default 240 if EXAMPLE_CAM_VRES_240 - - choice EXAMPLE_CAM_INPUT_FORMAT - bool "Set camera input format" - default EXAMPLE_CAM_INPUT_FORMAT_YUV422 - - config EXAMPLE_CAM_INPUT_FORMAT_RGB565 - bool "RGB565" - config EXAMPLE_CAM_INPUT_FORMAT_YUV422 - bool "YUV422" - endchoice - -endmenu diff --git a/examples/peripherals/camera/dvp_spi_lcd/main/dvp_spi_lcd_main.c b/examples/peripherals/camera/dvp_spi_lcd/main/dvp_spi_lcd_main.c deleted file mode 100644 index 7270992ae84..00000000000 --- a/examples/peripherals/camera/dvp_spi_lcd/main/dvp_spi_lcd_main.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include -#include -#include -#include "hal/cam_ctlr_types.h" -#include "sdkconfig.h" -#include "esp_attr.h" -#include "esp_log.h" -#include "freertos/FreeRTOS.h" -#include "esp_lcd_panel_ops.h" -#include "esp_cache.h" -#include "driver/i2c_master.h" -#include "esp_cam_ctlr.h" -#include "esp_cam_ctlr_dvp.h" -#include "example_config.h" -#include "driver/ledc.h" -#include "esp_lcd_panel_io.h" -#include "esp_lcd_panel_vendor.h" -#include "esp_lcd_panel_ops.h" -#include "example_sensor_init.h" - -static const char *TAG = "dvp_spi_lcd"; - -#define BUFFER_SIZE (CONFIG_EXAMPLE_CAM_HRES * CONFIG_EXAMPLE_CAM_VRES * EXAMPLE_RGB565_BYTES_PER_PIXEL) - -typedef struct { - esp_lcd_panel_handle_t panel_hdl; - esp_cam_ctlr_trans_t cam_trans; -} example_cam_context_t; - -static bool s_camera_get_new_vb(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data); -static bool s_camera_get_finished_trans(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data); - -static void lcd_display_init(esp_lcd_panel_handle_t *lcd_panel_hdl, esp_lcd_panel_io_handle_t lcd_io_hdl) -{ - esp_lcd_panel_handle_t panel_handle = NULL; - //----------LEDC initialization------------// - const ledc_timer_config_t lcd_timer = { - .speed_mode = LEDC_LOW_SPEED_MODE, - .duty_resolution = LEDC_TIMER_10_BIT, - .timer_num = EXAMPLE_LEDC_LCD_BACKLIGHT, - .freq_hz = 5000, - .clk_cfg = LEDC_AUTO_CLK - }; - ESP_ERROR_CHECK(ledc_timer_config(&lcd_timer)); - const ledc_channel_config_t lcd_channel = { - .gpio_num = EXAMPLE_LCD_BACKLIGHT, - .speed_mode = LEDC_LOW_SPEED_MODE, - .channel = LEDC_CHANNEL_0, - .timer_sel = EXAMPLE_LEDC_LCD_BACKLIGHT, - .intr_type = LEDC_INTR_DISABLE, - .duty = 0, - .hpoint = 0, - .flags.output_invert = true, - }; - ESP_ERROR_CHECK(ledc_channel_config(&lcd_channel)); - - //----------SPI initialization------------// - ESP_LOGI(TAG, "Init SPI bus"); - const spi_bus_config_t bus_cfg = { - .sclk_io_num = EXAMPLE_LCD_SPI_CLK, - .mosi_io_num = EXAMPLE_LCD_SPI_MOSI, - .miso_io_num = GPIO_NUM_NC, - .quadwp_io_num = GPIO_NUM_NC, - .quadhd_io_num = GPIO_NUM_NC, - .max_transfer_sz = BUFFER_SIZE, - }; - ESP_ERROR_CHECK(spi_bus_initialize(EXAMPLE_LCD_SPI_NUM, &bus_cfg, SPI_DMA_CH_AUTO)); - - //----------Panel IO initialization------------// - ESP_LOGI(TAG, "New panel IO SPI"); - const esp_lcd_panel_io_spi_config_t io_cfg = { - .dc_gpio_num = EXAMPLE_LCD_DC, - .cs_gpio_num = EXAMPLE_LCD_SPI_CS, - .pclk_hz = EXAMPLE_LCD_PIXEL_CLOCK_HZ, - .lcd_cmd_bits = EXAMPLE_LCD_CMD_BITS, - .lcd_param_bits = EXAMPLE_LCD_PARAM_BITS, - .spi_mode = 2, - .trans_queue_depth = 10, - }; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi( - (esp_lcd_spi_bus_handle_t)EXAMPLE_LCD_SPI_NUM, - &io_cfg, - &lcd_io_hdl - )); - - //----------ST7789 Panel initialization------------// - ESP_LOGI(TAG, "New ST7789 panel"); - const esp_lcd_panel_dev_config_t panel_dev_cfg = { - .reset_gpio_num = EXAMPLE_LCD_RST, - .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, - .bits_per_pixel = EXAMPLE_RGB565_BITS_PER_PIXEL, - }; - ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(lcd_io_hdl, &panel_dev_cfg, &panel_handle)); - - ESP_LOGI(TAG, "Reset and init panel"); - esp_lcd_panel_reset(panel_handle); - esp_lcd_panel_init(panel_handle); - esp_lcd_panel_invert_color(panel_handle, true); - - ESP_LOGI(TAG, "Turn on display"); - esp_lcd_panel_disp_on_off(panel_handle, true); - - const int brightness = 100; - uint32_t duty = (1023 * brightness) / 100; - ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, duty)); - ESP_ERROR_CHECK(ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0)); - - *lcd_panel_hdl = panel_handle; -} - -void app_main(void) -{ - esp_err_t ret = ESP_FAIL; - - esp_lcd_panel_handle_t lcd_panel_hdl = NULL; - esp_lcd_panel_io_handle_t lcd_io_hdl = NULL; - - lcd_display_init(&lcd_panel_hdl, lcd_io_hdl); - - //----------CAM Controller Init------------// - esp_cam_ctlr_handle_t cam_handle = NULL; - esp_cam_ctlr_dvp_pin_config_t pin_cfg = { - .data_width = EXAMPLE_DVP_CAM_DATA_WIDTH, - .data_io = { - EXAMPLE_DVP_CAM_D0_IO, - EXAMPLE_DVP_CAM_D1_IO, - EXAMPLE_DVP_CAM_D2_IO, - EXAMPLE_DVP_CAM_D3_IO, - EXAMPLE_DVP_CAM_D4_IO, - EXAMPLE_DVP_CAM_D5_IO, - EXAMPLE_DVP_CAM_D6_IO, - EXAMPLE_DVP_CAM_D7_IO, - }, - .vsync_io = EXAMPLE_DVP_CAM_VSYNC_IO, - .de_io = EXAMPLE_DVP_CAM_DE_IO, - .pclk_io = EXAMPLE_DVP_CAM_PCLK_IO, - .xclk_io = EXAMPLE_DVP_CAM_XCLK_IO, - }; - - esp_cam_ctlr_dvp_config_t dvp_config = { - .ctlr_id = 0, - .clk_src = CAM_CLK_SRC_DEFAULT, - .h_res = CONFIG_EXAMPLE_CAM_HRES, - .v_res = CONFIG_EXAMPLE_CAM_VRES, -#if CONFIG_EXAMPLE_CAM_INPUT_FORMAT_YUV422 - .input_data_color_type = CAM_CTLR_COLOR_YUV422_UYVY, - .output_data_color_type = CAM_CTLR_COLOR_RGB565, -#else - .input_data_color_type = CAM_CTLR_COLOR_RGB565, - .output_data_color_type = CAM_CTLR_COLOR_RGB565, -#endif - .conv_std = COLOR_CONV_STD_RGB_YUV_BT601, - .input_range = COLOR_RANGE_LIMIT, - .output_range = COLOR_RANGE_LIMIT, - .dma_burst_size = 64, - .pin = &pin_cfg, - .bk_buffer_dis = 1, - .xclk_freq = EXAMPLE_DVP_CAM_XCLK_FREQ_HZ, - }; - - ret = esp_cam_new_dvp_ctlr(&dvp_config, &cam_handle); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "dvp init fail[%d]", ret); - return; - } - - //--------Allocate Camera Buffer----------// - size_t cam_buffer_size = CONFIG_EXAMPLE_CAM_HRES * CONFIG_EXAMPLE_CAM_VRES * EXAMPLE_RGB565_BYTES_PER_PIXEL; - void *cam_buffer = NULL; - - cam_buffer = esp_cam_ctlr_alloc_buffer(cam_handle, cam_buffer_size, EXAMPLE_DVP_CAM_BUF_ALLOC_CAPS); - - //--------Camera Sensor and SCCB Init-----------// - example_sensor_config_t cam_sensor_config = { - .i2c_port_num = I2C_NUM_0, - .i2c_sda_io_num = EXAMPLE_DVP_CAM_SCCB_SDA_IO, - .i2c_scl_io_num = EXAMPLE_DVP_CAM_SCCB_SCL_IO, - .port = ESP_CAM_SENSOR_DVP, - .format_name = EXAMPLE_CAM_FORMAT, - }; - example_sensor_handle_t sensor_handle = { - .sccb_handle = NULL, - .i2c_bus_handle = NULL, - }; - example_sensor_init(&cam_sensor_config, &sensor_handle); - - //--------Register Camera Callbacks----------// - example_cam_context_t cam_ctx = { - .panel_hdl = lcd_panel_hdl, - .cam_trans = { - .buffer = cam_buffer, - .buflen = cam_buffer_size, - } - }; - - 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_ctx) != ESP_OK) { - ESP_LOGE(TAG, "ops register fail"); - return; - } - - //--------Enable and start Camera Controller----------// - ESP_ERROR_CHECK(esp_cam_ctlr_enable(cam_handle)); - -#if CONFIG_EXAMPLE_CAM_INPUT_FORMAT_YUV422 - ESP_LOGI(TAG, "Configure format conversion: YUV422 -> RGB565"); - // Configure format conversion - const cam_ctlr_format_conv_config_t conv_cfg = { - .src_format = CAM_CTLR_COLOR_YUV422_UYVY, // Source format: YUV422 - .dst_format = CAM_CTLR_COLOR_RGB565, // Destination format: RGB565 - .conv_std = COLOR_CONV_STD_RGB_YUV_BT601, - .data_width = 8, - .input_range = COLOR_RANGE_LIMIT, - .output_range = COLOR_RANGE_LIMIT, - }; - ESP_ERROR_CHECK(esp_cam_ctlr_format_conversion(cam_handle, &conv_cfg)); -#endif - - if (esp_cam_ctlr_start(cam_handle) != ESP_OK) { - ESP_LOGE(TAG, "Driver start fail"); - return; - } - - while (1) { - vTaskDelay(1000 / portTICK_PERIOD_MS); - } -} - -static bool s_camera_get_new_vb(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data) -{ - example_cam_context_t *ctx = (example_cam_context_t *)user_data; - *trans = ctx->cam_trans; - return false; -} - -static bool s_camera_get_finished_trans(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data) -{ - example_cam_context_t *ctx = (example_cam_context_t *)user_data; - esp_lcd_panel_draw_bitmap(ctx->panel_hdl, 0, 0, CONFIG_EXAMPLE_CAM_HRES, CONFIG_EXAMPLE_CAM_VRES, trans->buffer); - return false; -} diff --git a/examples/peripherals/camera/dvp_spi_lcd/main/example_config.h b/examples/peripherals/camera/dvp_spi_lcd/main/example_config.h deleted file mode 100644 index 95d178d4689..00000000000 --- a/examples/peripherals/camera/dvp_spi_lcd/main/example_config.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#include "sdkconfig.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//----------CAM Config------------// -#define EXAMPLE_RGB565_BITS_PER_PIXEL 16 -#define EXAMPLE_RGB565_BYTES_PER_PIXEL (EXAMPLE_RGB565_BITS_PER_PIXEL / 8) - -#define EXAMPLE_DVP_CAM_SCCB_SCL_IO (5) -#define EXAMPLE_DVP_CAM_SCCB_SDA_IO (4) - -#define EXAMPLE_DVP_CAM_XCLK_FREQ_HZ (20000000) - -#define EXAMPLE_DVP_CAM_DATA_WIDTH (8) - -#define EXAMPLE_DVP_CAM_D0_IO (11) -#define EXAMPLE_DVP_CAM_D1_IO (9) -#define EXAMPLE_DVP_CAM_D2_IO (8) -#define EXAMPLE_DVP_CAM_D3_IO (10) -#define EXAMPLE_DVP_CAM_D4_IO (12) -#define EXAMPLE_DVP_CAM_D5_IO (18) -#define EXAMPLE_DVP_CAM_D6_IO (17) -#define EXAMPLE_DVP_CAM_D7_IO (16) - -#define EXAMPLE_DVP_CAM_XCLK_IO (15) -#define EXAMPLE_DVP_CAM_PCLK_IO (13) -#define EXAMPLE_DVP_CAM_DE_IO (7) -#define EXAMPLE_DVP_CAM_VSYNC_IO (6) -#define EXAMPLE_DVP_CAM_HSYNC_IO (-1) - -#if CONFIG_SPIRAM -#define EXAMPLE_DVP_CAM_BUF_ALLOC_CAPS (MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA) -#else -#define EXAMPLE_DVP_CAM_BUF_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA) -#endif - -#if CONFIG_EXAMPLE_CAM_INPUT_FORMAT_YUV422 -#define EXAMPLE_CAM_FORMAT "DVP_8bit_20Minput_YUV422_240x240_25fps" // ov2640 -#elif CONFIG_EXAMPLE_CAM_INPUT_FORMAT_RGB565 -#define EXAMPLE_CAM_FORMAT "DVP_8bit_20Minput_RGB565_240x240_25fps" // ov2640 -#endif - -#ifndef EXAMPLE_CAM_FORMAT -#error "Unsupported camera format! Please adjust EXAMPLE_CAM_HRES and EXAMPLE_CAM_VRES in menuconfig" -#endif - -//----------LCD Config------------// -#define EXAMPLE_LEDC_DVP_XCLK (LEDC_TIMER_0) -#define EXAMPLE_LEDC_LCD_BACKLIGHT (LEDC_TIMER_1) -#define EXAMPLE_LCD_SPI_NUM (SPI3_HOST) -#define EXAMPLE_LCD_CMD_BITS (8) -#define EXAMPLE_LCD_PARAM_BITS (8) - -/* LCD Display */ -#define EXAMPLE_LCD_SPI_MOSI (GPIO_NUM_47) -#define EXAMPLE_LCD_SPI_CLK (GPIO_NUM_21) -#define EXAMPLE_LCD_SPI_CS (GPIO_NUM_44) -#define EXAMPLE_LCD_DC (GPIO_NUM_43) -#define EXAMPLE_LCD_RST (GPIO_NUM_NC) -#define EXAMPLE_LCD_BACKLIGHT (GPIO_NUM_48) - -#define EXAMPLE_LCD_PIXEL_CLOCK_HZ (80 * 1000 * 1000) - -#ifdef __cplusplus -} -#endif diff --git a/examples/peripherals/camera/dvp_spi_lcd/main/idf_component.yml b/examples/peripherals/camera/dvp_spi_lcd/main/idf_component.yml deleted file mode 100644 index 4cd68977191..00000000000 --- a/examples/peripherals/camera/dvp_spi_lcd/main/idf_component.yml +++ /dev/null @@ -1,3 +0,0 @@ -dependencies: - sensor_init: - path: ${IDF_PATH}/examples/peripherals/camera/common_components/sensor_init diff --git a/examples/peripherals/camera/dvp_spi_lcd/pytest_dvp_spi_lcd.py b/examples/peripherals/camera/dvp_spi_lcd/pytest_dvp_spi_lcd.py deleted file mode 100644 index 7dfd614f40b..00000000000 --- a/examples/peripherals/camera/dvp_spi_lcd/pytest_dvp_spi_lcd.py +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD -# SPDX-License-Identifier: CC0-1.0 -import pytest -from pytest_embedded import Dut -from pytest_embedded_idf.utils import idf_parametrize - - -@pytest.mark.generic -@idf_parametrize('target', ['esp32p4'], indirect=['target']) -def test_dvp_spi_lcd_p4(dut: Dut) -> None: - dut.expect_exact('Calling app_main()') diff --git a/examples/peripherals/camera/dvp_spi_lcd/sdkconfig.defaults b/examples/peripherals/camera/dvp_spi_lcd/sdkconfig.defaults deleted file mode 100644 index bc0080e2fe6..00000000000 --- a/examples/peripherals/camera/dvp_spi_lcd/sdkconfig.defaults +++ /dev/null @@ -1,2 +0,0 @@ -CONFIG_CAMERA_OV2640=y -CONFIG_CAM_CTRL_SPI_ENABLE=n diff --git a/examples/peripherals/camera/dvp_spi_lcd/sdkconfig.defaults.esp32p4 b/examples/peripherals/camera/dvp_spi_lcd/sdkconfig.defaults.esp32p4 deleted file mode 100644 index b0354270024..00000000000 --- a/examples/peripherals/camera/dvp_spi_lcd/sdkconfig.defaults.esp32p4 +++ /dev/null @@ -1,2 +0,0 @@ -CONFIG_SPIRAM_SPEED_80M=y -CONFIG_SPIRAM=y diff --git a/examples/peripherals/camera/dvp_spi_lcd/sdkconfig.defaults.esp32s3 b/examples/peripherals/camera/dvp_spi_lcd/sdkconfig.defaults.esp32s3 deleted file mode 100644 index 38bbb5933ed..00000000000 --- a/examples/peripherals/camera/dvp_spi_lcd/sdkconfig.defaults.esp32s3 +++ /dev/null @@ -1,2 +0,0 @@ -CONFIG_SPIRAM=y -CONFIG_SPIRAM_MODE_OCT=y diff --git a/examples/peripherals/camera/mipi_isp_dsi/main/mipi_isp_dsi_main.c b/examples/peripherals/camera/mipi_isp_dsi/main/mipi_isp_dsi_main.c index da5329845c7..10ec9a533d2 100644 --- a/examples/peripherals/camera/mipi_isp_dsi/main/mipi_isp_dsi_main.c +++ b/examples/peripherals/camera/mipi_isp_dsi/main/mipi_isp_dsi_main.c @@ -74,6 +74,9 @@ void app_main(void) .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, + .reset_pin = -1, + .pwdn_pin = -1, + .xclk_pin = -1, .port = ESP_CAM_SENSOR_MIPI_CSI, .format_name = EXAMPLE_CAM_FORMAT, }; diff --git a/examples/peripherals/camera/mipi_isp_dsi/sdkconfig.defaults b/examples/peripherals/camera/mipi_isp_dsi/sdkconfig.defaults index ca810641071..ff158141a4c 100644 --- a/examples/peripherals/camera/mipi_isp_dsi/sdkconfig.defaults +++ b/examples/peripherals/camera/mipi_isp_dsi/sdkconfig.defaults @@ -1,3 +1,7 @@ CONFIG_CAMERA_SC2336=y CONFIG_CAMERA_OV5647=y +CONFIG_CAMERA_OV5647_MIPI_RAW8_800X640_50FPS=y +CONFIG_CAMERA_OV5647_MIPI_RAW8_800X800_50FPS=y +CONFIG_CAMERA_OV5647_MIPI_RAW8_800X1280_50FPS=y +CONFIG_CAMERA_SC2336_MIPI_RAW8_1024X600_30FPS=y CONFIG_CAM_CTRL_SPI_ENABLE=n diff --git a/examples/peripherals/isp/multi_pipelines/main/isp_dsi_main.c b/examples/peripherals/isp/multi_pipelines/main/isp_dsi_main.c index cc46659d162..539cdaab4d6 100644 --- a/examples/peripherals/isp/multi_pipelines/main/isp_dsi_main.c +++ b/examples/peripherals/isp/multi_pipelines/main/isp_dsi_main.c @@ -153,6 +153,9 @@ void app_main(void) .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, + .reset_pin = -1, + .pwdn_pin = -1, + .xclk_pin = -1, .port = ESP_CAM_SENSOR_MIPI_CSI, .format_name = EXAMPLE_CAM_FORMAT, }; diff --git a/examples/peripherals/isp/multi_pipelines/sdkconfig.defaults b/examples/peripherals/isp/multi_pipelines/sdkconfig.defaults index cad614b043f..ff54aa6eaa7 100644 --- a/examples/peripherals/isp/multi_pipelines/sdkconfig.defaults +++ b/examples/peripherals/isp/multi_pipelines/sdkconfig.defaults @@ -3,5 +3,8 @@ CONFIG_IDF_EXPERIMENTAL_FEATURES=y CONFIG_SPIRAM_SPEED_200M=y CONFIG_CAMERA_SC2336=y CONFIG_CAMERA_OV5647=y +CONFIG_CAMERA_OV5647_MIPI_RAW8_800X640_50FPS=y +CONFIG_CAMERA_OV5647_MIPI_RAW8_800X1280_50FPS=y +CONFIG_CAMERA_SC2336_MIPI_RAW8_1024X600_30FPS=y CONFIG_CAMERA_OV5647_ENABLE_MOTOR_BY_GPIO0=y CONFIG_CAM_CTRL_SPI_ENABLE=n diff --git a/tools/ci/check_examples_documented.py b/tools/ci/check_examples_documented.py index 3a80f09b11d..a7606957b4a 100644 --- a/tools/ci/check_examples_documented.py +++ b/tools/ci/check_examples_documented.py @@ -137,8 +137,6 @@ KNOWN_MISSING = { 'system/ulp/ulp_riscv/gpio_pulse_counter', 'system/unit_test/test', # TODO IDF-15382: add :example: references for peripherals examples - 'peripherals/camera/dvp_dsi', - 'peripherals/camera/dvp_spi_lcd', 'peripherals/h264', 'peripherals/i2s/i2s_advance/i2s_usb', 'peripherals/spi_slave/receiver',