mirror of
https://github.com/espressif/esp-idf.git
synced 2026-08-13 04:42:01 +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}
|
||||
|
||||
130
components/esp_driver_cam/test_apps/dvp/main/test_dvp_ov2640.c
Normal file
130
components/esp_driver_cam/test_apps/dvp/main/test_dvp_ov2640.c
Normal file
@@ -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
|
||||
40
components/esp_hal_cam/esp32s31/cam_periph.c
Normal file
40
components/esp_hal_cam/esp32s31/cam_periph.c
Normal file
@@ -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
|
||||
}
|
||||
}
|
||||
};
|
||||
583
components/esp_hal_cam/esp32s31/include/hal/cam_ll.h
Normal file
583
components/esp_hal_cam/esp32s31/include/hal/cam_ll.h
Normal file
@@ -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
|
||||
|
||||
@@ -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
|
||||
-------------
|
||||
|
||||
@@ -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 参考
|
||||
--------
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#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;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
dependencies:
|
||||
espressif/esp_cam_sensor: "^1.2.1"
|
||||
espressif/esp_cam_sensor: "^2.1.0"
|
||||
idf:
|
||||
version: ">=5.3.0"
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
```
|
||||
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
@@ -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 <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)
|
||||
@@ -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
|
||||
)
|
||||
@@ -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
|
||||
@@ -1,249 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -1,3 +0,0 @@
|
||||
dependencies:
|
||||
sensor_init:
|
||||
path: ${IDF_PATH}/examples/peripherals/camera/common_components/sensor_init
|
||||
@@ -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()')
|
||||
@@ -1,2 +0,0 @@
|
||||
CONFIG_CAMERA_OV2640=y
|
||||
CONFIG_CAM_CTRL_SPI_ENABLE=n
|
||||
@@ -1,2 +0,0 @@
|
||||
CONFIG_SPIRAM_SPEED_80M=y
|
||||
CONFIG_SPIRAM=y
|
||||
@@ -1,2 +0,0 @@
|
||||
CONFIG_SPIRAM=y
|
||||
CONFIG_SPIRAM_MODE_OCT=y
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user