mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-01 18:50:34 +03:00
feat(cam): support dvp cam on ESP32-S31
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
| Supported Targets | ESP32-P4 | ESP32-S3 |
|
||||
| ----------------- | -------- | -------- |
|
||||
| Supported Targets | ESP32-P4 | ESP32-S3 | ESP32-S31 |
|
||||
| ----------------- | -------- | -------- | --------- |
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -1,166 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "esp_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;
|
||||
}
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,5 @@
|
||||
CONFIG_IDF_TARGET="esp32s31"
|
||||
|
||||
CONFIG_SPIRAM=y
|
||||
CONFIG_SPIRAM_SPEED_250M=y
|
||||
CONFIG_CAMERA_OV2640=y
|
||||
@@ -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
|
||||
@@ -0,0 +1 @@
|
||||
CONFIG_CAMERA_OV2640=y
|
||||
@@ -1,4 +1,6 @@
|
||||
CONFIG_IDF_TARGET="esp32s3"
|
||||
|
||||
CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y
|
||||
|
||||
CONFIG_SPIRAM=y
|
||||
CONFIG_SPIRAM_MODE_OCT=y
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
CONFIG_IDF_TARGET="esp32s31"
|
||||
|
||||
CONFIG_SPIRAM=y
|
||||
CONFIG_SPIRAM_SPEED_250M=y
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,583 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#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
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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//////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user