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 3ad81cd956..52d18a433b 100644 --- a/components/esp_driver_cam/test_apps/dvp/main/CMakeLists.txt +++ b/components/esp_driver_cam/test_apps/dvp/main/CMakeLists.txt @@ -3,6 +3,9 @@ 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") +endif() set(priv_requires unity diff --git a/components/esp_driver_cam/test_apps/dvp/main/idf_component.yml b/components/esp_driver_cam/test_apps/dvp/main/idf_component.yml new file mode 100644 index 0000000000..4cd6897719 --- /dev/null +++ b/components/esp_driver_cam/test_apps/dvp/main/idf_component.yml @@ -0,0 +1,3 @@ +dependencies: + sensor_init: + path: ${IDF_PATH}/examples/peripherals/camera/common_components/sensor_init diff --git a/components/esp_driver_cam/test_apps/dvp/main/test_dvp_driver.c b/components/esp_driver_cam/test_apps/dvp/main/test_dvp_driver.c index b7e7e5ac2f..123297574c 100644 --- a/components/esp_driver_cam/test_apps/dvp/main/test_dvp_driver.c +++ b/components/esp_driver_cam/test_apps/dvp/main/test_dvp_driver.c @@ -167,7 +167,7 @@ TEST_CASE("TEST DVP driver intern/extern generate xclk", "[DVP]") dvp_config.external_xtal = false; TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_cam_new_dvp_ctlr(&dvp_config, &handle)); - pin_cfg.xclk_io = 20; + pin_cfg.xclk_io = 15; dvp_config.pin = &pin_cfg; TEST_ESP_OK(esp_cam_new_dvp_ctlr(&dvp_config, &handle)); TEST_ESP_OK(esp_cam_ctlr_del(handle)); @@ -175,11 +175,11 @@ TEST_CASE("TEST DVP driver intern/extern generate xclk", "[DVP]") TEST_CASE("TEST DVP driver only output xclk signal", "[DVP]") { - TEST_ESP_OK(esp_cam_ctlr_dvp_start_clock(0, 20, CAM_CLK_SRC_DEFAULT, 20000000)); + TEST_ESP_OK(esp_cam_ctlr_dvp_start_clock(0, 15, CAM_CLK_SRC_DEFAULT, 20000000)); TEST_ESP_OK(esp_cam_ctlr_dvp_deinit(0)); #if CONFIG_IDF_TARGET_ESP32S3 - TEST_ESP_OK(esp_cam_ctlr_dvp_start_clock(0, 20, CAM_CLK_SRC_PLL240M, 24000000)); + TEST_ESP_OK(esp_cam_ctlr_dvp_start_clock(0, 15, CAM_CLK_SRC_PLL240M, 24000000)); TEST_ESP_OK(esp_cam_ctlr_dvp_deinit(0)); #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 new file mode 100644 index 0000000000..c5f3f69e01 --- /dev/null +++ b/components/esp_driver_cam/test_apps/dvp/main/test_dvp_s3eye.c @@ -0,0 +1,165 @@ +/* + * 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, + .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 5ef42e0150..a88d69804a 100644 --- a/components/esp_driver_cam/test_apps/dvp/pytest_dvp.py +++ b/components/esp_driver_cam/test_apps/dvp/pytest_dvp.py @@ -23,5 +23,19 @@ def test_dvp(dut: Dut) -> None: indirect=True, ) @idf_parametrize('target', ['esp32s3'], indirect=['target']) -def test_dvp_octal(dut: Dut) -> None: +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) + + +@pytest.mark.esp32s3_eye +@pytest.mark.parametrize( + 'config', + ['esp32s3_eye'], + indirect=True, +) +@idf_parametrize('target', ['esp32s3'], indirect=['target']) +def test_dvp_s3eye(dut: Dut) -> None: dut.run_all_single_board_cases() 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 new file mode 100644 index 0000000000..41438fffb0 --- /dev/null +++ b/components/esp_driver_cam/test_apps/dvp/sdkconfig.ci.esp32s3_eye @@ -0,0 +1,7 @@ +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/pytest.ini b/pytest.ini index e12d1747bd..a46a8a6bd4 100644 --- a/pytest.ini +++ b/pytest.ini @@ -108,6 +108,7 @@ env_markers = es8311: Development board that carries es8311 codec camera: Runner with camera ov5647: Runner with camera ov5647 + esp32s3_eye: Runner for esp32s3_eye and camera ov2640 multi_dut_modbus_rs485: a pair of runners connected by RS485 bus ieee802154: ieee802154 related tests should run on ieee802154 runners. openthread_br: tests should be used for openthread border router.