mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
feat(isp): added isp dvp driver
This commit is contained in:
parent
7425154472
commit
70d2ed5ee8
@ -1,21 +1,29 @@
|
||||
idf_build_get_property(target IDF_TARGET)
|
||||
|
||||
set(srcs "esp_cam_ctlr.c")
|
||||
set(srcs "esp_cam_ctlr.c" "dvp_share_ctrl.c")
|
||||
|
||||
set(include "include" "interface")
|
||||
set(includes "include" "interface")
|
||||
|
||||
set(requires "esp_driver_isp")
|
||||
|
||||
set(priv_requires "esp_driver_gpio")
|
||||
|
||||
if(CONFIG_SOC_MIPI_CSI_SUPPORTED)
|
||||
list(APPEND srcs "csi/src/esp_cam_ctlr_csi.c")
|
||||
list(APPEND include "csi/include")
|
||||
list(APPEND includes "csi/include")
|
||||
endif()
|
||||
|
||||
if(${target} STREQUAL "linux")
|
||||
set(priv_requires "")
|
||||
else()
|
||||
set(priv_requires esp_mm)
|
||||
if(CONFIG_SOC_ISP_DVP_SUPPORTED)
|
||||
list(APPEND srcs "isp_dvp/src/esp_cam_ctlr_isp_dvp.c")
|
||||
list(APPEND includes "isp_dvp/include")
|
||||
endif()
|
||||
|
||||
if(NOT ${target} STREQUAL "linux")
|
||||
list(APPEND requires esp_mm)
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS ${srcs}
|
||||
INCLUDE_DIRS ${include}
|
||||
PRIV_REQUIRES "${priv_requires}"
|
||||
INCLUDE_DIRS ${includes}
|
||||
REQUIRES ${requires}
|
||||
PRIV_REQUIRES ${priv_requires}
|
||||
)
|
||||
|
@ -1,11 +1,27 @@
|
||||
menu "ESP Camera Controller Configurations"
|
||||
menu "ESP-Driver:Camera Controller Configurations"
|
||||
|
||||
depends on SOC_MIPI_CSI_SUPPORTED
|
||||
|
||||
config MIPI_CSI_ISR_IRAM_SAFE
|
||||
config CAM_CTLR_MIPI_CSI_ISR_IRAM_SAFE
|
||||
bool "CSI ISR IRAM-Safe"
|
||||
default n
|
||||
select DW_GDMA_ISR_IRAM_SAFE
|
||||
select DW_GDMA_CTRL_FUNC_IN_IRAM
|
||||
select DW_GDMA_SETTER_FUNC_IN_IRAM
|
||||
select DW_GDMA_GETTER_FUNC_IN_IRAM
|
||||
help
|
||||
Ensure the CSI driver ISR is IRAM-Safe. When enabled, the ISR handler
|
||||
will be available when the cache is disabled.
|
||||
|
||||
config CAM_CTLR_ISP_DVP_ISR_IRAM_SAFE
|
||||
bool "ISP_DVP ISR IRAM-Safe"
|
||||
default n
|
||||
select DW_GDMA_ISR_IRAM_SAFE
|
||||
select DW_GDMA_CTRL_FUNC_IN_IRAM
|
||||
select DW_GDMA_SETTER_FUNC_IN_IRAM
|
||||
select DW_GDMA_GETTER_FUNC_IN_IRAM
|
||||
help
|
||||
Ensure the ISP_DVP driver ISR is IRAM-Safe. When enabled, the ISR handler
|
||||
will be available when the cache is disabled.
|
||||
|
||||
endmenu # ESP Camera Controller Configurations
|
||||
|
@ -15,11 +15,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ESP CAM controller max timeout value
|
||||
*/
|
||||
#define ESP_CAM_CTLR_MAX_DELAY UINT32_MAX
|
||||
|
||||
/**
|
||||
* @brief ESP CAM CSI controller configurations
|
||||
*/
|
||||
@ -30,8 +25,8 @@ typedef struct {
|
||||
uint32_t v_res; ///< Input vertical resolution, i.e. the number of lines in a frame
|
||||
uint8_t data_lane_num; ///< Data lane num
|
||||
int lane_bit_rate_mbps; ///< Lane bit rate in Mbps
|
||||
mipi_csi_color_t input_data_color_type; ///< Input color type
|
||||
mipi_csi_color_t output_data_color_type; ///< Output color type
|
||||
cam_ctlr_color_t input_data_color_type; ///< Input color type
|
||||
cam_ctlr_color_t output_data_color_type; ///< Output color type
|
||||
int queue_items; ///< Queue items
|
||||
struct {
|
||||
uint32_t byte_swap_en : 1; ///< Enable byte swap
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include "esp_private/esp_cache_private.h"
|
||||
#include "esp_cache.h"
|
||||
|
||||
#if CONFIG_MIPI_CSI_ISR_IRAM_SAFE
|
||||
#if CONFIG_CAM_CTLR_MIPI_CSI_ISR_IRAM_SAFE
|
||||
#define CSI_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
|
||||
#else
|
||||
#define CSI_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
|
||||
@ -66,7 +66,6 @@ static esp_err_t s_csi_claim_controller(csi_controller_t *controller)
|
||||
mipi_csi_ll_enable_host_bus_clock(i, 1);
|
||||
mipi_csi_ll_reset_host_clock(i);
|
||||
}
|
||||
_lock_release(&s_platform.mutex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -295,7 +294,7 @@ static esp_err_t s_csi_ctlr_get_buffer_length(esp_cam_ctlr_handle_t handle, size
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static bool csi_dma_trans_done_callback(dw_gdma_channel_handle_t chan, const dw_gdma_trans_done_event_data_t *event_data, void *user_data)
|
||||
IRAM_ATTR static bool csi_dma_trans_done_callback(dw_gdma_channel_handle_t chan, const dw_gdma_trans_done_event_data_t *event_data, void *user_data)
|
||||
{
|
||||
bool need_yield = false;
|
||||
BaseType_t high_task_woken = pdFALSE;
|
||||
@ -374,7 +373,7 @@ esp_err_t s_register_event_callbacks(esp_cam_ctlr_handle_t handle, const esp_cam
|
||||
csi_controller_t *ctlr = __containerof(handle, csi_controller_t, base);
|
||||
ESP_RETURN_ON_FALSE(ctlr->csi_fsm == CSI_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "driver starts already, not allow cbs register");
|
||||
|
||||
#if CONFIG_MIPI_CSI_ISR_IRAM_SAFE
|
||||
#if CONFIG_CAM_CTLR_MIPI_CSI_ISR_IRAM_SAFE
|
||||
if (cbs->on_get_new_trans) {
|
||||
ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_get_new_trans), ESP_ERR_INVALID_ARG, TAG, "on_get_new_trans callback not in IRAM");
|
||||
}
|
||||
|
36
components/esp_driver_cam/dvp_share_ctrl.c
Normal file
36
components/esp_driver_cam/dvp_share_ctrl.c
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <esp_types.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_err.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
|
||||
bool dvp_signal_used;
|
||||
static portMUX_TYPE s_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
esp_err_t dvp_shared_ctrl_claim_io_signals(void)
|
||||
{
|
||||
esp_err_t ret = ESP_ERR_NOT_FOUND;
|
||||
portENTER_CRITICAL(&s_spinlock);
|
||||
if (!dvp_signal_used) {
|
||||
dvp_signal_used = true;
|
||||
ret = ESP_OK;
|
||||
}
|
||||
portEXIT_CRITICAL(&s_spinlock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t dvp_shared_ctrl_declaim_io_signals(void)
|
||||
{
|
||||
portENTER_CRITICAL(&s_spinlock);
|
||||
dvp_signal_used = false;
|
||||
portEXIT_CRITICAL(&s_spinlock);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
28
components/esp_driver_cam/dvp_share_ctrl.h
Normal file
28
components/esp_driver_cam/dvp_share_ctrl.h
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <esp_types.h>
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Claim DVP IO signal usage
|
||||
*/
|
||||
esp_err_t dvp_shared_ctrl_claim_io_signals(void);
|
||||
|
||||
/**
|
||||
* @brief Declaim DVP IO signal usage
|
||||
*/
|
||||
esp_err_t dvp_shared_ctrl_declaim_io_signals(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -14,6 +14,11 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ESP CAM controller max timeout value
|
||||
*/
|
||||
#define ESP_CAM_CTLR_MAX_DELAY UINT32_MAX
|
||||
|
||||
/**
|
||||
* @brief ESP CAM controller handle
|
||||
*/
|
||||
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "esp_err.h"
|
||||
#include "driver/isp_types.h"
|
||||
#include "hal/cam_ctlr_types.h"
|
||||
#include "esp_cam_ctlr_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ESP CAM ISP DVP controller configurations
|
||||
*/
|
||||
typedef struct {
|
||||
cam_ctlr_data_width_t data_width; ///< Number of data lines
|
||||
int data_io[ISP_DVP_DATA_SIG_NUM]; ///< ISP DVP data-in IO numbers
|
||||
int pclk_io; ///< ISP DVP pclk IO numbers
|
||||
int hsync_io; ///< ISP DVP hsync IO numbers
|
||||
int vsync_io; ///< ISP DVP vsync IO numbers
|
||||
int de_io; ///< ISP DVP de IO numbers
|
||||
struct {
|
||||
uint32_t pclk_invert: 1; ///< The pclk is inverted
|
||||
uint32_t hsync_invert: 1; ///< The hsync signal is inverted
|
||||
uint32_t vsync_invert: 1; ///< The vsync signal is inverted
|
||||
uint32_t de_invert: 1; ///< The de signal is inverted
|
||||
} io_flags; ///< ISP DVP IO flags
|
||||
int queue_items; ///< Queue items
|
||||
struct {
|
||||
uint32_t byte_swap_en : 1; ///< Enable byte swap
|
||||
uint32_t bk_buffer_dis : 1; ///< Disable backup buffer
|
||||
};
|
||||
} esp_cam_ctlr_isp_dvp_cfg_t;
|
||||
|
||||
/**
|
||||
* @brief New ESP CAM ISP DVP controller
|
||||
*
|
||||
* @param[in] ctlr_config ISP DVP controller configurations
|
||||
* @param[out] ret_handle Returned ESP CAM controller handle
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK
|
||||
* - ESP_ERR_INVALID_ARG: Invalid argument
|
||||
* - ESP_ERR_NO_MEM: Out of memory
|
||||
* - ESP_ERR_NOT_SUPPORTED: Currently not support modes or types
|
||||
* - ESP_ERR_NOT_FOUND: ISP DVP is registered already
|
||||
*/
|
||||
esp_err_t esp_cam_new_isp_dvp_ctlr(isp_proc_handle_t isp_proc, const esp_cam_ctlr_isp_dvp_cfg_t *ctlr_config, esp_cam_ctlr_handle_t *ret_handle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
568
components/esp_driver_cam/isp_dvp/src/esp_cam_ctlr_isp_dvp.c
Normal file
568
components/esp_driver_cam/isp_dvp/src/esp_cam_ctlr_isp_dvp.c
Normal file
@ -0,0 +1,568 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <esp_types.h>
|
||||
#include <sys/lock.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/idf_additions.h"
|
||||
#include "driver/isp_types.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "hal/isp_hal.h"
|
||||
#include "hal/gpio_hal.h"
|
||||
#include "hal/isp_ll.h"
|
||||
#include "hal/mipi_csi_brg_ll.h"
|
||||
#include "hal/mipi_csi_ll.h"
|
||||
#include "hal/color_hal.h"
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
#include "esp_private/isp_private.h"
|
||||
#include "esp_private/esp_cache_private.h"
|
||||
#include "esp_private/mipi_csi_share_hw_ctrl.h"
|
||||
#include "esp_private/dw_gdma.h"
|
||||
#include "esp_cam_ctlr_types.h"
|
||||
#include "esp_cam_ctlr_interface.h"
|
||||
#include "esp_cache.h"
|
||||
#include "esp_cam_ctlr_isp_dvp.h"
|
||||
#include "../../dvp_share_ctrl.h"
|
||||
|
||||
#if CONFIG_CAM_CTLR_ISP_DVP_ISR_IRAM_SAFE
|
||||
#define ISP_DVP_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
|
||||
#else
|
||||
#define ISP_DVP_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
|
||||
#endif
|
||||
|
||||
typedef struct isp_dvp_controller_t {
|
||||
int id; //dvp id
|
||||
isp_fsm_t fsm; //finite state machine
|
||||
portMUX_TYPE spinlock; //spinlock
|
||||
isp_processor_t *isp_proc; //isp processor
|
||||
int in_bpp; //input data type, bit per pixel
|
||||
int out_bpp; //output data type, bit per pixel
|
||||
size_t fb_size_in_bytes; //Frame buffer size, in bytes
|
||||
esp_cam_ctlr_trans_t trans; //Saved done transaction to be given out to callers
|
||||
void *backup_buffer; //backup buffer to make csi bridge can work to avoid wrong state
|
||||
bool bk_buffer_exposed; //status of if back_buffer is exposed to users
|
||||
bool bk_buffer_dis; //allow to not malloc backup_buffer
|
||||
QueueHandle_t trans_que; //transaction queue
|
||||
esp_cam_ctlr_evt_cbs_t cbs; //user callbacks
|
||||
void *cbs_user_data; //callback userdata
|
||||
dw_gdma_channel_handle_t dma_chan; //dwgdma channel handle
|
||||
size_t dvp_transfer_size; //csi transfer size for dwgdma
|
||||
bool isr_installed; //is isr installed
|
||||
esp_cam_ctlr_t base;
|
||||
} isp_dvp_controller_t;
|
||||
|
||||
typedef struct isp_dvp_ctx_t {
|
||||
_lock_t mutex;
|
||||
isp_dvp_controller_t *dvp_ctlr[SOC_ISP_DVP_CTLR_NUMS];
|
||||
} isp_dvp_ctx_t;
|
||||
|
||||
static const char *TAG = "ISP_DVP";
|
||||
static isp_dvp_ctx_t s_ctx;
|
||||
|
||||
static esp_err_t s_isp_io_init(isp_dvp_controller_t *dvp_ctlr, const esp_cam_ctlr_isp_dvp_cfg_t *ctlr_config);
|
||||
static esp_err_t s_isp_claim_dvp_controller(isp_proc_handle_t isp_proc, isp_dvp_controller_t *dvp_ctlr);
|
||||
static esp_err_t s_isp_declaim_dvp_controller(isp_dvp_controller_t *dvp_ctlr);
|
||||
static esp_err_t s_isp_del_dvp_controller(esp_cam_ctlr_handle_t handle);
|
||||
static esp_err_t s_isp_dvp_get_frame_buffer(esp_cam_ctlr_handle_t handle, uint32_t fb_num, const void **fb0, ...);
|
||||
static esp_err_t s_isp_dvp_get_frame_buffer_length(esp_cam_ctlr_handle_t handle, size_t *ret_fb_len);
|
||||
static esp_err_t s_isp_dvp_register_event_callbacks(esp_cam_ctlr_handle_t handle, const esp_cam_ctlr_evt_cbs_t *cbs, void *user_data);
|
||||
static esp_err_t s_isp_dvp_enable(esp_cam_ctlr_handle_t handle);
|
||||
static esp_err_t s_isp_dvp_disable(esp_cam_ctlr_handle_t handle);
|
||||
static esp_err_t s_isp_dvp_start(esp_cam_ctlr_handle_t handle);
|
||||
static esp_err_t s_isp_dvp_stop(esp_cam_ctlr_handle_t handle);
|
||||
static esp_err_t s_isp_dvp_receive(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, uint32_t timeout_ms);
|
||||
static bool s_dvp_dma_trans_done_callback(dw_gdma_channel_handle_t chan, const dw_gdma_trans_done_event_data_t *event_data, void *user_data);
|
||||
|
||||
esp_err_t esp_cam_new_isp_dvp_ctlr(isp_proc_handle_t isp_proc, const esp_cam_ctlr_isp_dvp_cfg_t *ctlr_config, esp_cam_ctlr_handle_t *ret_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
ESP_RETURN_ON_FALSE(isp_proc && ctlr_config && ret_handle, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
||||
|
||||
isp_dvp_controller_t *dvp_ctlr = heap_caps_calloc(1, sizeof(isp_dvp_controller_t), ISP_DVP_MEM_ALLOC_CAPS);
|
||||
ESP_RETURN_ON_FALSE(dvp_ctlr, ESP_ERR_NO_MEM, TAG, "no mem for isp dvp controller");
|
||||
|
||||
dvp_ctlr->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
|
||||
dvp_ctlr->isp_proc = isp_proc;
|
||||
|
||||
#if SOC_ISP_SHARE_CSI_BRG
|
||||
ESP_GOTO_ON_ERROR(mipi_csi_brg_claim(MIPI_CSI_BRG_USER_ISP_DVP, &isp_proc->csi_brg_id), err, TAG, "csi bridge is in use already");
|
||||
#endif
|
||||
//claim an DVP controller
|
||||
ESP_GOTO_ON_ERROR(s_isp_claim_dvp_controller(isp_proc, dvp_ctlr), err, TAG, "no available controller");
|
||||
ESP_GOTO_ON_ERROR(dvp_shared_ctrl_claim_io_signals(), err, TAG, "failed to claim io signals");
|
||||
ESP_GOTO_ON_ERROR(s_isp_io_init(dvp_ctlr, ctlr_config), err, TAG, "io init fail");
|
||||
|
||||
dvp_ctlr->trans_que = xQueueCreateWithCaps(ctlr_config->queue_items, sizeof(esp_cam_ctlr_trans_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
ESP_GOTO_ON_FALSE(dvp_ctlr->trans_que, ESP_ERR_NO_MEM, err, TAG, "no memory for transaction queue");
|
||||
//in color type
|
||||
int in_bits_per_pixel = color_hal_pixel_format_get_bit_depth(isp_proc->in_color_format);
|
||||
dvp_ctlr->in_bpp = in_bits_per_pixel;
|
||||
ESP_LOGD(TAG, "dvp_ctlr->in_bpp: 0d %d", dvp_ctlr->in_bpp);
|
||||
|
||||
//out color type
|
||||
int out_bits_per_pixel = color_hal_pixel_format_get_bit_depth(isp_proc->out_color_format);
|
||||
dvp_ctlr->out_bpp = out_bits_per_pixel;
|
||||
ESP_LOGD(TAG, "dvp_ctlr->out_bpp: 0d %d", dvp_ctlr->out_bpp);
|
||||
|
||||
// Note: Width * Height * BitsPerPixel must be divisible by 8
|
||||
int fb_size_in_bits = isp_proc->v_res * isp_proc->h_res * out_bits_per_pixel;
|
||||
ESP_GOTO_ON_FALSE((fb_size_in_bits % 8 == 0), ESP_ERR_INVALID_ARG, err, TAG, "framesize not 8bit aligned");
|
||||
dvp_ctlr->fb_size_in_bytes = fb_size_in_bits / 8;
|
||||
ESP_LOGD(TAG, "dvp_ctlr->fb_size_in_bytes=%d", dvp_ctlr->fb_size_in_bytes);
|
||||
|
||||
dvp_ctlr->bk_buffer_dis = ctlr_config->bk_buffer_dis;
|
||||
if (!dvp_ctlr->bk_buffer_dis) {
|
||||
size_t dma_alignment = 4;
|
||||
size_t cache_alignment = 1;
|
||||
ESP_GOTO_ON_ERROR(esp_cache_get_alignment(MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA, &cache_alignment), err, TAG, "failed to get cache alignment");
|
||||
size_t alignment = MAX(cache_alignment, dma_alignment);
|
||||
ESP_LOGD(TAG, "alignment: 0x%x\n", alignment);
|
||||
|
||||
dvp_ctlr->backup_buffer = heap_caps_aligned_alloc(alignment, dvp_ctlr->fb_size_in_bytes, MALLOC_CAP_SPIRAM);
|
||||
ESP_GOTO_ON_FALSE(dvp_ctlr->backup_buffer, ESP_ERR_NO_MEM, err, TAG, "no mem for backup buffer");
|
||||
ESP_LOGD(TAG, "dvp_ctlr->backup_buffer: %p\n", dvp_ctlr->backup_buffer);
|
||||
esp_cache_msync((void *)(dvp_ctlr->backup_buffer), dvp_ctlr->fb_size_in_bytes, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
|
||||
}
|
||||
|
||||
bool valid_format = isp_ll_dvp_set_data_type(isp_proc->hal.hw, isp_proc->in_color_format);
|
||||
ESP_GOTO_ON_FALSE(valid_format, ESP_ERR_INVALID_ARG, err, TAG, "invalid dvp color space config");
|
||||
if (ctlr_config->io_flags.pclk_invert) {
|
||||
isp_ll_cam_enable_pclk_invert(isp_proc->hal.hw, true);
|
||||
}
|
||||
if (ctlr_config->io_flags.hsync_invert) {
|
||||
isp_ll_cam_enable_hsync_invert(isp_proc->hal.hw, true);
|
||||
}
|
||||
if (ctlr_config->io_flags.vsync_invert) {
|
||||
isp_ll_cam_enable_vsync_invert(isp_proc->hal.hw, true);
|
||||
}
|
||||
if (ctlr_config->io_flags.de_invert) {
|
||||
isp_ll_cam_enable_de_invert(isp_proc->hal.hw, true);
|
||||
}
|
||||
isp_ll_dvp_cam_reset(isp_proc->hal.hw);
|
||||
|
||||
// configure DW_GDMA for ISP DVP
|
||||
dw_gdma_channel_alloc_config_t dvp_dma_alloc_config = {
|
||||
.src = {
|
||||
.block_transfer_type = DW_GDMA_BLOCK_TRANSFER_CONTIGUOUS,
|
||||
#if SOC_ISP_SHARE_CSI_BRG
|
||||
.role = DW_GDMA_ROLE_PERIPH_CSI, //CSI bridge
|
||||
#endif
|
||||
.handshake_type = DW_GDMA_HANDSHAKE_HW,
|
||||
.num_outstanding_requests = 5,
|
||||
.status_fetch_addr = MIPI_CSI_BRG_MEM_BASE,
|
||||
},
|
||||
.dst = {
|
||||
.block_transfer_type = DW_GDMA_BLOCK_TRANSFER_CONTIGUOUS,
|
||||
.role = DW_GDMA_ROLE_MEM,
|
||||
.handshake_type = DW_GDMA_HANDSHAKE_HW,
|
||||
.num_outstanding_requests = 5,
|
||||
},
|
||||
.flow_controller = DW_GDMA_FLOW_CTRL_SRC,
|
||||
.chan_priority = 1,
|
||||
};
|
||||
ESP_ERROR_CHECK(dw_gdma_new_channel(&dvp_dma_alloc_config, &dvp_ctlr->dma_chan));
|
||||
|
||||
size_t dvp_transfer_size = isp_proc->h_res * isp_proc->v_res * dvp_ctlr->in_bpp / 64;
|
||||
dvp_ctlr->dvp_transfer_size = dvp_transfer_size;
|
||||
ESP_LOGD(TAG, "dvp_transfer_size: 0d %d", dvp_transfer_size);
|
||||
|
||||
dvp_ctlr->fsm = ISP_FSM_INIT;
|
||||
isp_proc->csi_brg_hw = MIPI_CSI_BRG_LL_GET_HW(isp_proc->csi_brg_id);
|
||||
mipi_csi_brg_ll_set_intput_data_h_pixel_num(isp_proc->csi_brg_hw, isp_proc->h_res);
|
||||
mipi_csi_brg_ll_set_intput_data_v_row_num(isp_proc->csi_brg_hw, isp_proc->v_res);
|
||||
mipi_csi_brg_ll_set_burst_len(isp_proc->csi_brg_hw, 512);
|
||||
|
||||
esp_cam_ctlr_t *cam_ctlr = &(dvp_ctlr->base);
|
||||
cam_ctlr->del = s_isp_del_dvp_controller;
|
||||
cam_ctlr->enable = s_isp_dvp_enable;
|
||||
cam_ctlr->start = s_isp_dvp_start;
|
||||
cam_ctlr->stop = s_isp_dvp_stop;
|
||||
cam_ctlr->disable = s_isp_dvp_disable;
|
||||
cam_ctlr->receive = s_isp_dvp_receive;
|
||||
cam_ctlr->register_event_callbacks = s_isp_dvp_register_event_callbacks;
|
||||
cam_ctlr->get_internal_buffer = s_isp_dvp_get_frame_buffer;
|
||||
cam_ctlr->get_buffer_len = s_isp_dvp_get_frame_buffer_length;
|
||||
*ret_handle = cam_ctlr;
|
||||
|
||||
return ESP_OK;
|
||||
|
||||
err:
|
||||
if (dvp_ctlr) {
|
||||
s_isp_del_dvp_controller(&(dvp_ctlr->base));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t s_isp_del_dvp_controller(esp_cam_ctlr_handle_t handle)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
||||
isp_dvp_controller_t *dvp_ctlr = __containerof(handle, isp_dvp_controller_t, base);
|
||||
|
||||
ESP_RETURN_ON_FALSE(dvp_ctlr->fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "controller isn't in init state");
|
||||
if (dvp_ctlr->dma_chan) {
|
||||
ESP_RETURN_ON_ERROR(dw_gdma_del_channel(dvp_ctlr->dma_chan), TAG, "failed to delete dwgdma channel");
|
||||
}
|
||||
#if SOC_ISP_SHARE_CSI_BRG
|
||||
ESP_RETURN_ON_ERROR(mipi_csi_brg_declaim(dvp_ctlr->isp_proc->csi_brg_id), TAG, "declaim csi bridge fail");
|
||||
#endif
|
||||
ESP_RETURN_ON_ERROR(s_isp_declaim_dvp_controller(dvp_ctlr), TAG, "controller isn't in use");
|
||||
ESP_RETURN_ON_ERROR(dvp_shared_ctrl_declaim_io_signals(), TAG, "failed to declaim io signals");
|
||||
if (!dvp_ctlr->bk_buffer_dis) {
|
||||
free(dvp_ctlr->backup_buffer);
|
||||
}
|
||||
if (dvp_ctlr->trans_que) {
|
||||
vQueueDeleteWithCaps(dvp_ctlr->trans_que);
|
||||
}
|
||||
free(dvp_ctlr);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t s_isp_dvp_get_frame_buffer(esp_cam_ctlr_handle_t handle, uint32_t fb_num, const void **fb0, ...)
|
||||
{
|
||||
isp_dvp_controller_t *dvp_ctlr = __containerof(handle, isp_dvp_controller_t, base);
|
||||
ESP_RETURN_ON_FALSE((dvp_ctlr->fsm >= ISP_FSM_INIT) && (dvp_ctlr->backup_buffer), ESP_ERR_INVALID_STATE, TAG, "driver isn't initialized or back_buffer isn't available");
|
||||
ESP_RETURN_ON_FALSE(fb_num && fb_num <= 1, ESP_ERR_INVALID_ARG, TAG, "invalid frame buffer number");
|
||||
|
||||
dvp_ctlr->bk_buffer_exposed = true;
|
||||
const void **fb_itor = fb0;
|
||||
va_list args;
|
||||
va_start(args, fb0);
|
||||
for (uint32_t i = 0; i < fb_num; i++) {
|
||||
if (fb_itor) {
|
||||
*fb_itor = dvp_ctlr->backup_buffer;
|
||||
fb_itor = va_arg(args, const void **);
|
||||
}
|
||||
}
|
||||
va_end(args);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t s_isp_dvp_get_frame_buffer_length(esp_cam_ctlr_handle_t handle, size_t *ret_fb_len)
|
||||
{
|
||||
isp_dvp_controller_t *dvp_ctlr = __containerof(handle, isp_dvp_controller_t, base);
|
||||
ESP_RETURN_ON_FALSE((dvp_ctlr->fsm >= ISP_FSM_INIT) && (dvp_ctlr->backup_buffer), ESP_ERR_INVALID_STATE, TAG, "driver isn't initialized or back_buffer isn't available");
|
||||
|
||||
*ret_fb_len = dvp_ctlr->fb_size_in_bytes;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t s_isp_dvp_register_event_callbacks(esp_cam_ctlr_handle_t handle, const esp_cam_ctlr_evt_cbs_t *cbs, void *user_data)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(handle && cbs, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
isp_dvp_controller_t *dvp_ctlr = __containerof(handle, isp_dvp_controller_t, base);
|
||||
ESP_RETURN_ON_FALSE(dvp_ctlr->fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "controller isn't in init state");
|
||||
|
||||
#if CONFIG_CAM_CTLR_MIPI_CSI_ISR_IRAM_SAFE
|
||||
if (cbs->on_get_new_trans) {
|
||||
ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_get_new_trans), ESP_ERR_INVALID_ARG, TAG, "on_get_new_trans callback not in IRAM");
|
||||
}
|
||||
if (cbs->on_trans_finished) {
|
||||
ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_trans_finished), ESP_ERR_INVALID_ARG, TAG, "on_trans_finished callback not in IRAM");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!dvp_ctlr->isr_installed) {
|
||||
dw_gdma_event_callbacks_t csi_dma_cbs = {
|
||||
.on_full_trans_done = s_dvp_dma_trans_done_callback,
|
||||
};
|
||||
ESP_RETURN_ON_ERROR(dw_gdma_channel_register_event_callbacks(dvp_ctlr->dma_chan, &csi_dma_cbs, dvp_ctlr), TAG, "failed to register dma callbacks");
|
||||
dvp_ctlr->isr_installed = true;
|
||||
}
|
||||
|
||||
dvp_ctlr->cbs.on_get_new_trans = cbs->on_get_new_trans;
|
||||
dvp_ctlr->cbs.on_trans_finished = cbs->on_trans_finished;
|
||||
dvp_ctlr->cbs_user_data = user_data;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t s_isp_dvp_enable(esp_cam_ctlr_handle_t handle)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
||||
isp_dvp_controller_t *dvp_ctlr = __containerof(handle, isp_dvp_controller_t, base);
|
||||
ESP_RETURN_ON_FALSE(dvp_ctlr->fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "controller isn't in init state");
|
||||
|
||||
portENTER_CRITICAL(&dvp_ctlr->spinlock);
|
||||
dvp_ctlr->fsm = ISP_FSM_ENABLE;
|
||||
portEXIT_CRITICAL(&dvp_ctlr->spinlock);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t s_isp_dvp_disable(esp_cam_ctlr_handle_t handle)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
||||
isp_dvp_controller_t *dvp_ctlr = __containerof(handle, isp_dvp_controller_t, base);
|
||||
ESP_RETURN_ON_FALSE(dvp_ctlr->fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "controller isn't in enable state");
|
||||
|
||||
portENTER_CRITICAL(&dvp_ctlr->spinlock);
|
||||
dvp_ctlr->fsm = ISP_FSM_INIT;
|
||||
portEXIT_CRITICAL(&dvp_ctlr->spinlock);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t s_isp_dvp_start(esp_cam_ctlr_handle_t handle)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
||||
isp_dvp_controller_t *dvp_ctlr = __containerof(handle, isp_dvp_controller_t, base);
|
||||
ESP_RETURN_ON_FALSE(dvp_ctlr->fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "controller isn't in enable state");
|
||||
ESP_RETURN_ON_FALSE(dvp_ctlr->isp_proc->isp_fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "ISP processor isn't in enable state");
|
||||
ESP_RETURN_ON_FALSE(dvp_ctlr->cbs.on_trans_finished, ESP_ERR_INVALID_STATE, TAG, "no on_trans_finished callback registered");
|
||||
|
||||
mipi_csi_brg_ll_enable(dvp_ctlr->isp_proc->csi_brg_hw, true);
|
||||
isp_ll_cam_enable(dvp_ctlr->isp_proc->hal.hw, true);
|
||||
|
||||
esp_cam_ctlr_trans_t trans = {};
|
||||
bool has_new_trans = false;
|
||||
|
||||
if (dvp_ctlr->cbs.on_get_new_trans) {
|
||||
dvp_ctlr->cbs.on_get_new_trans(handle, &trans, dvp_ctlr->cbs_user_data);
|
||||
if (trans.buffer) {
|
||||
has_new_trans = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_new_trans) {
|
||||
if (!dvp_ctlr->bk_buffer_dis) {
|
||||
trans.buffer = dvp_ctlr->backup_buffer;
|
||||
trans.buflen = dvp_ctlr->fb_size_in_bytes;
|
||||
} else {
|
||||
ESP_RETURN_ON_FALSE(false, ESP_ERR_INVALID_STATE, TAG, "no ready transaction, and no backup buffer");
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "trans.buffer: %p, trans.buflen: %d", trans.buffer, trans.buflen);
|
||||
dvp_ctlr->trans = trans;
|
||||
|
||||
portENTER_CRITICAL(&dvp_ctlr->spinlock);
|
||||
dvp_ctlr->fsm = ISP_FSM_START;
|
||||
portEXIT_CRITICAL(&dvp_ctlr->spinlock);
|
||||
|
||||
dw_gdma_block_transfer_config_t dvp_dma_transfer_config = {};
|
||||
dvp_dma_transfer_config = (dw_gdma_block_transfer_config_t) {
|
||||
.src = {
|
||||
.addr = MIPI_CSI_BRG_MEM_BASE,
|
||||
.burst_mode = DW_GDMA_BURST_MODE_FIXED,
|
||||
.burst_items = DW_GDMA_BURST_ITEMS_512,
|
||||
.burst_len = 16,
|
||||
.width = DW_GDMA_TRANS_WIDTH_64,
|
||||
},
|
||||
.dst = {
|
||||
.addr = (uint32_t)(trans.buffer),
|
||||
.burst_mode = DW_GDMA_BURST_MODE_INCREMENT,
|
||||
.burst_items = DW_GDMA_BURST_ITEMS_512,
|
||||
.burst_len = 16,
|
||||
.width = DW_GDMA_TRANS_WIDTH_64,
|
||||
},
|
||||
.size = dvp_ctlr->dvp_transfer_size,
|
||||
};
|
||||
ESP_RETURN_ON_ERROR(dw_gdma_channel_config_transfer(dvp_ctlr->dma_chan, &dvp_dma_transfer_config), TAG, "failed to configure dwgdma transfer");
|
||||
ESP_RETURN_ON_ERROR(dw_gdma_channel_enable_ctrl(dvp_ctlr->dma_chan, true), TAG, "failed to enable dwgdma");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t s_isp_dvp_stop(esp_cam_ctlr_handle_t handle)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
isp_dvp_controller_t *dvp_ctlr = __containerof(handle, isp_dvp_controller_t, base);
|
||||
ESP_RETURN_ON_FALSE(dvp_ctlr->fsm == ISP_FSM_START, ESP_ERR_INVALID_STATE, TAG, "driver isn't started");
|
||||
|
||||
isp_ll_cam_enable(dvp_ctlr->isp_proc->hal.hw, false);
|
||||
mipi_csi_brg_ll_enable(dvp_ctlr->isp_proc->csi_brg_hw, false);
|
||||
ESP_RETURN_ON_ERROR(dw_gdma_channel_enable_ctrl(dvp_ctlr->dma_chan, false), TAG, "failed to disable dwgdma");
|
||||
|
||||
portENTER_CRITICAL(&dvp_ctlr->spinlock);
|
||||
dvp_ctlr->fsm = ISP_FSM_INIT;
|
||||
portEXIT_CRITICAL(&dvp_ctlr->spinlock);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t s_isp_dvp_receive(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, uint32_t timeout_ms)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
isp_dvp_controller_t *dvp_ctlr = __containerof(handle, isp_dvp_controller_t, base);
|
||||
|
||||
ESP_RETURN_ON_FALSE(trans->buffer, ESP_ERR_INVALID_ARG, TAG, "invalid argument: no trans buffer");
|
||||
ESP_RETURN_ON_FALSE((trans->buflen >= dvp_ctlr->fb_size_in_bytes), ESP_ERR_INVALID_ARG, TAG, "invalid argument: trans buffer smaller than framebuffer size");
|
||||
|
||||
TickType_t ticks_to_wait = timeout_ms / portTICK_PERIOD_MS;
|
||||
if (timeout_ms == ESP_CAM_CTLR_MAX_DELAY) {
|
||||
ticks_to_wait = portMAX_DELAY;
|
||||
}
|
||||
|
||||
BaseType_t r = xQueueSend(dvp_ctlr->trans_que, trans, ticks_to_wait);
|
||||
if (r != pdTRUE) {
|
||||
ret = ESP_ERR_TIMEOUT;
|
||||
ESP_LOGW(TAG, "csi recv API, transaction queue is full, failed to send transaction to the queue");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
IRAM_ATTR static bool s_dvp_dma_trans_done_callback(dw_gdma_channel_handle_t chan, const dw_gdma_trans_done_event_data_t *event_data, void *user_data)
|
||||
{
|
||||
bool need_yield = false;
|
||||
BaseType_t high_task_woken = pdFALSE;
|
||||
isp_dvp_controller_t *dvp_ctlr = (isp_dvp_controller_t *)user_data;
|
||||
bool has_new_trans = false;
|
||||
|
||||
dw_gdma_block_transfer_config_t dvp_dma_transfer_config = {};
|
||||
dvp_dma_transfer_config = (dw_gdma_block_transfer_config_t) {
|
||||
.src = {
|
||||
.addr = MIPI_CSI_BRG_MEM_BASE,
|
||||
.burst_mode = DW_GDMA_BURST_MODE_FIXED,
|
||||
.burst_items = DW_GDMA_BURST_ITEMS_512,
|
||||
.burst_len = 16,
|
||||
.width = DW_GDMA_TRANS_WIDTH_64,
|
||||
},
|
||||
.dst = {
|
||||
.addr = 0,
|
||||
.burst_mode = DW_GDMA_BURST_MODE_INCREMENT,
|
||||
.burst_items = DW_GDMA_BURST_ITEMS_512,
|
||||
.burst_len = 16,
|
||||
.width = DW_GDMA_TRANS_WIDTH_64,
|
||||
},
|
||||
.size = dvp_ctlr->dvp_transfer_size,
|
||||
};
|
||||
esp_cam_ctlr_trans_t new_trans = {};
|
||||
|
||||
if (dvp_ctlr->cbs.on_get_new_trans) {
|
||||
need_yield = dvp_ctlr->cbs.on_get_new_trans(&(dvp_ctlr->base), &new_trans, dvp_ctlr->cbs_user_data);
|
||||
if (new_trans.buffer && new_trans.buflen >= dvp_ctlr->fb_size_in_bytes) {
|
||||
dvp_dma_transfer_config.dst.addr = (uint32_t)(new_trans.buffer);
|
||||
has_new_trans = true;
|
||||
}
|
||||
} else if (xQueueReceiveFromISR(dvp_ctlr->trans_que, &new_trans, &high_task_woken) == pdTRUE) {
|
||||
if (new_trans.buffer && new_trans.buflen >= dvp_ctlr->fb_size_in_bytes) {
|
||||
dvp_dma_transfer_config.dst.addr = (uint32_t)(new_trans.buffer);
|
||||
has_new_trans = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_new_trans) {
|
||||
if (!dvp_ctlr->bk_buffer_dis) {
|
||||
new_trans.buffer = dvp_ctlr->backup_buffer;
|
||||
new_trans.buflen = dvp_ctlr->fb_size_in_bytes;
|
||||
ESP_EARLY_LOGD(TAG, "no new buffer or no long enough new buffer, use driver internal buffer");
|
||||
dvp_dma_transfer_config.dst.addr = (uint32_t)dvp_ctlr->backup_buffer;
|
||||
} else {
|
||||
assert(false && "no new buffer, and no driver internal buffer");
|
||||
}
|
||||
}
|
||||
|
||||
ESP_EARLY_LOGD(TAG, "new_trans.buffer: %p, new_trans.buflen: %d", new_trans.buffer, new_trans.buflen);
|
||||
dw_gdma_channel_config_transfer(chan, &dvp_dma_transfer_config);
|
||||
dw_gdma_channel_enable_ctrl(chan, true);
|
||||
|
||||
if ((dvp_ctlr->trans.buffer != dvp_ctlr->backup_buffer) || dvp_ctlr->bk_buffer_exposed) {
|
||||
esp_err_t ret = esp_cache_msync((void *)(dvp_ctlr->trans.buffer), dvp_ctlr->trans.received_size, ESP_CACHE_MSYNC_FLAG_INVALIDATE);
|
||||
assert(ret == ESP_OK);
|
||||
assert(dvp_ctlr->cbs.on_trans_finished);
|
||||
if (dvp_ctlr->cbs.on_trans_finished) {
|
||||
dvp_ctlr->trans.received_size = dvp_ctlr->fb_size_in_bytes;
|
||||
need_yield |= dvp_ctlr->cbs.on_trans_finished(&(dvp_ctlr->base), &dvp_ctlr->trans, dvp_ctlr->cbs_user_data);
|
||||
}
|
||||
}
|
||||
|
||||
//dvp_ctlr->trans is the transaction saved before dma starts
|
||||
memset(&dvp_ctlr->trans, 0x0, sizeof(esp_cam_ctlr_trans_t));
|
||||
dvp_ctlr->trans = new_trans;
|
||||
|
||||
need_yield |= high_task_woken == pdTRUE;
|
||||
return need_yield;
|
||||
}
|
||||
|
||||
static esp_err_t s_isp_io_init(isp_dvp_controller_t *dvp_ctlr, const esp_cam_ctlr_isp_dvp_cfg_t *ctlr_config)
|
||||
{
|
||||
gpio_config_t gpio_conf = {
|
||||
.intr_type = GPIO_INTR_DISABLE,
|
||||
.mode = GPIO_MODE_INPUT,
|
||||
.pull_down_en = false,
|
||||
.pull_up_en = true,
|
||||
};
|
||||
|
||||
if (ctlr_config->pclk_io) {
|
||||
gpio_conf.pin_bit_mask = 1ULL << ctlr_config->pclk_io;
|
||||
ESP_RETURN_ON_ERROR(gpio_config(&gpio_conf), TAG, "failed to configure pclk gpio");
|
||||
ESP_LOGD(TAG, "pclk_io: %d, dvp_pclk_sig: %"PRId32, ctlr_config->pclk_io, isp_hw_info.dvp_ctlr[dvp_ctlr->id].dvp_pclk_sig);
|
||||
esp_rom_gpio_connect_in_signal(ctlr_config->pclk_io, isp_hw_info.dvp_ctlr[dvp_ctlr->id].dvp_pclk_sig, false);
|
||||
}
|
||||
|
||||
if (ctlr_config->hsync_io) {
|
||||
gpio_conf.pin_bit_mask = 1ULL << ctlr_config->hsync_io;
|
||||
ESP_RETURN_ON_ERROR(gpio_config(&gpio_conf), TAG, "failed to configure hsync gpio");
|
||||
ESP_LOGD(TAG, "hsync_io: %d, dvp_hsync_sig: %"PRId32, ctlr_config->hsync_io, isp_hw_info.dvp_ctlr[dvp_ctlr->id].dvp_hsync_sig);
|
||||
esp_rom_gpio_connect_in_signal(ctlr_config->hsync_io, isp_hw_info.dvp_ctlr[dvp_ctlr->id].dvp_hsync_sig, false);
|
||||
}
|
||||
|
||||
if (ctlr_config->vsync_io) {
|
||||
gpio_conf.pin_bit_mask = 1ULL << ctlr_config->vsync_io;
|
||||
ESP_RETURN_ON_ERROR(gpio_config(&gpio_conf), TAG, "failed to configure vsync gpio");
|
||||
ESP_LOGD(TAG, "vsync_io: %d, dvp_vsync_sig: %"PRId32, ctlr_config->vsync_io, isp_hw_info.dvp_ctlr[dvp_ctlr->id].dvp_vsync_sig);
|
||||
esp_rom_gpio_connect_in_signal(ctlr_config->vsync_io, isp_hw_info.dvp_ctlr[dvp_ctlr->id].dvp_vsync_sig, false);
|
||||
}
|
||||
|
||||
if (ctlr_config->de_io) {
|
||||
gpio_conf.pin_bit_mask = 1ULL << ctlr_config->de_io;
|
||||
ESP_RETURN_ON_ERROR(gpio_config(&gpio_conf), TAG, "failed to configure de gpio");
|
||||
ESP_LOGD(TAG, "de_io: %d, dvp_de_sig: %"PRId32, ctlr_config->de_io, isp_hw_info.dvp_ctlr[dvp_ctlr->id].dvp_de_sig);
|
||||
esp_rom_gpio_connect_in_signal(ctlr_config->de_io, isp_hw_info.dvp_ctlr[dvp_ctlr->id].dvp_de_sig, false);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < ctlr_config->data_width; i++) {
|
||||
gpio_conf.pin_bit_mask = 1ULL << ctlr_config->data_io[i];
|
||||
ESP_RETURN_ON_ERROR(gpio_config(&gpio_conf), TAG, "failed to configure data gpio");
|
||||
ESP_LOGD(TAG, "data_io: %d, dvp_data_sig: %"PRId32, ctlr_config->data_io[i], isp_hw_info.dvp_ctlr[dvp_ctlr->id].dvp_data_sig[i]);
|
||||
esp_rom_gpio_connect_in_signal(ctlr_config->data_io[i], isp_hw_info.dvp_ctlr[dvp_ctlr->id].dvp_data_sig[i], false);
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t s_isp_claim_dvp_controller(isp_proc_handle_t isp_proc, isp_dvp_controller_t *dvp_ctlr)
|
||||
{
|
||||
assert(isp_proc && dvp_ctlr);
|
||||
|
||||
_lock_acquire(&s_ctx.mutex);
|
||||
bool found = false;
|
||||
for (int i = 0; i < SOC_ISP_DVP_CTLR_NUMS; i++) {
|
||||
found = !s_ctx.dvp_ctlr[i];
|
||||
if (found) {
|
||||
s_ctx.dvp_ctlr[i] = dvp_ctlr;
|
||||
dvp_ctlr->id = i;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
_lock_release(&s_ctx.mutex);
|
||||
|
||||
if (!found) {
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t s_isp_declaim_dvp_controller(isp_dvp_controller_t *dvp_ctlr)
|
||||
{
|
||||
assert(dvp_ctlr);
|
||||
|
||||
_lock_acquire(&s_ctx.mutex);
|
||||
s_ctx.dvp_ctlr[dvp_ctlr->id] = NULL;
|
||||
_lock_release(&s_ctx.mutex);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
@ -16,8 +16,8 @@ TEST_CASE("TEST CSI driver allocation", "[csi]")
|
||||
.h_res = 800,
|
||||
.v_res = 640,
|
||||
.lane_bit_rate_mbps = 200,
|
||||
.input_data_color_type = MIPI_CSI_COLOR_RAW8,
|
||||
.output_data_color_type = MIPI_CSI_COLOR_RGB565,
|
||||
.input_data_color_type = CAM_CTLR_COLOR_RAW8,
|
||||
.output_data_color_type = CAM_CTLR_COLOR_RGB565,
|
||||
.data_lane_num = 2,
|
||||
.byte_swap_en = false,
|
||||
.queue_items = 1,
|
||||
@ -42,8 +42,8 @@ TEST_CASE("TEST CSI driver no backup buffer usage", "[csi]")
|
||||
.h_res = 800,
|
||||
.v_res = 640,
|
||||
.lane_bit_rate_mbps = 200,
|
||||
.input_data_color_type = MIPI_CSI_COLOR_RAW8,
|
||||
.output_data_color_type = MIPI_CSI_COLOR_RGB565,
|
||||
.input_data_color_type = CAM_CTLR_COLOR_RAW8,
|
||||
.output_data_color_type = CAM_CTLR_COLOR_RGB565,
|
||||
.data_lane_num = 2,
|
||||
.byte_swap_en = false,
|
||||
.queue_items = 1,
|
||||
|
@ -0,0 +1,6 @@
|
||||
CONFIG_FREERTOS_HZ=1000
|
||||
CONFIG_ESP_TASK_WDT_EN=n
|
||||
|
||||
CONFIG_SPIRAM=y
|
||||
CONFIG_IDF_EXPERIMENTAL_FEATURES=y
|
||||
CONFIG_SPIRAM_SPEED_200M=y
|
@ -1,7 +1,13 @@
|
||||
idf_build_get_property(target IDF_TARGET)
|
||||
|
||||
set(srcs)
|
||||
|
||||
set(public_include "include")
|
||||
|
||||
set(priv_requires "esp_driver_gpio")
|
||||
|
||||
set(requires)
|
||||
|
||||
if(CONFIG_SOC_ISP_SUPPORTED)
|
||||
list(APPEND srcs "src/isp_core.c"
|
||||
"src/isp_af.c")
|
||||
@ -11,7 +17,12 @@ if(CONFIG_SOC_ISP_BF_SUPPORTED)
|
||||
list(APPEND srcs "src/isp_bf.c")
|
||||
endif()
|
||||
|
||||
if(NOT ${target} STREQUAL "linux")
|
||||
list(APPEND requires esp_mm)
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS ${srcs}
|
||||
INCLUDE_DIRS ${public_include}
|
||||
PRIV_REQUIRES esp_driver_gpio
|
||||
REQUIRES ${requires}
|
||||
PRIV_REQUIRES ${priv_requires}
|
||||
)
|
||||
|
@ -38,7 +38,7 @@ typedef struct {
|
||||
* - ESP_ERR_NOT_FOUND No free interrupt found with the specified flags
|
||||
* - ESP_ERR_NO_MEM If out of memory
|
||||
*/
|
||||
esp_err_t esp_isp_new_af_controller(isp_proc_handle_t isp_proc, const esp_isp_af_config_t *af_config, isp_af_ctrlr_t *ret_hdl);
|
||||
esp_err_t esp_isp_new_af_controller(isp_proc_handle_t isp_proc, const esp_isp_af_config_t *af_config, isp_af_ctlr_t *ret_hdl);
|
||||
|
||||
/**
|
||||
* @brief Delete an ISP AF controller
|
||||
@ -50,7 +50,7 @@ esp_err_t esp_isp_new_af_controller(isp_proc_handle_t isp_proc, const esp_isp_af
|
||||
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
|
||||
* - ESP_ERR_INVALID_STATE Driver state is invalid.
|
||||
*/
|
||||
esp_err_t esp_isp_del_af_controller(isp_af_ctrlr_t af_ctrlr);
|
||||
esp_err_t esp_isp_del_af_controller(isp_af_ctlr_t af_ctrlr);
|
||||
|
||||
/**
|
||||
* @brief Enable an ISP AF controller
|
||||
@ -62,7 +62,7 @@ esp_err_t esp_isp_del_af_controller(isp_af_ctrlr_t af_ctrlr);
|
||||
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
|
||||
* - ESP_ERR_INVALID_STATE Driver state is invalid.
|
||||
*/
|
||||
esp_err_t esp_isp_af_controller_enable(isp_af_ctrlr_t af_ctrlr);
|
||||
esp_err_t esp_isp_af_controller_enable(isp_af_ctlr_t af_ctrlr);
|
||||
|
||||
/**
|
||||
* @brief Disable an ISP AF controller
|
||||
@ -74,7 +74,7 @@ esp_err_t esp_isp_af_controller_enable(isp_af_ctrlr_t af_ctrlr);
|
||||
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
|
||||
* - ESP_ERR_INVALID_STATE Driver state is invalid.
|
||||
*/
|
||||
esp_err_t esp_isp_af_controller_disable(isp_af_ctrlr_t af_ctrlr);
|
||||
esp_err_t esp_isp_af_controller_disable(isp_af_ctlr_t af_ctrlr);
|
||||
|
||||
/**
|
||||
* @brief Trigger AF luminance and definition statistics for one time and get the result
|
||||
@ -97,7 +97,7 @@ esp_err_t esp_isp_af_controller_disable(isp_af_ctrlr_t af_ctrlr);
|
||||
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
|
||||
* - ESP_ERR_INVALID_STATE Driver state is invalid.
|
||||
*/
|
||||
esp_err_t esp_isp_af_controller_get_oneshot_statistics(isp_af_ctrlr_t af_ctrlr, int timeout_ms, isp_af_result_t *out_res);
|
||||
esp_err_t esp_isp_af_controller_get_oneshot_statistics(isp_af_ctlr_t af_ctrlr, int timeout_ms, isp_af_result_t *out_res);
|
||||
|
||||
/** @cond */
|
||||
#define esp_isp_af_controller_get_oneshot_result(af_ctrlr, out_res) \
|
||||
@ -116,7 +116,7 @@ esp_err_t esp_isp_af_controller_get_oneshot_statistics(isp_af_ctrlr_t af_ctrlr,
|
||||
* - ESP_ERR_INVALID_ARG Null pointer
|
||||
* - ESP_ERR_INVALID_STATE Driver state is invalid.
|
||||
*/
|
||||
esp_err_t esp_isp_af_controller_start_continuous_statistics(isp_af_ctrlr_t af_ctrlr);
|
||||
esp_err_t esp_isp_af_controller_start_continuous_statistics(isp_af_ctlr_t af_ctrlr);
|
||||
|
||||
/**
|
||||
* @brief Stop AF continuous statistics of the luminance and definition in the windows
|
||||
@ -127,7 +127,7 @@ esp_err_t esp_isp_af_controller_start_continuous_statistics(isp_af_ctrlr_t af_ct
|
||||
* - ESP_ERR_INVALID_ARG Null pointer
|
||||
* - ESP_ERR_INVALID_STATE Driver state is invalid.
|
||||
*/
|
||||
esp_err_t esp_isp_af_controller_stop_continuous_statistics(isp_af_ctrlr_t af_ctrlr);
|
||||
esp_err_t esp_isp_af_controller_stop_continuous_statistics(isp_af_ctlr_t af_ctrlr);
|
||||
|
||||
/*---------------------------------------------
|
||||
AF Env Monitor
|
||||
@ -152,7 +152,7 @@ typedef struct {
|
||||
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
|
||||
* - ESP_ERR_INVALID_STATE Driver state is invalid.
|
||||
*/
|
||||
esp_err_t esp_isp_af_controller_set_env_detector(isp_af_ctrlr_t af_ctrlr, const esp_isp_af_env_config_t *env_config);
|
||||
esp_err_t esp_isp_af_controller_set_env_detector(isp_af_ctlr_t af_ctrlr, const esp_isp_af_env_config_t *env_config);
|
||||
|
||||
/**
|
||||
* @brief Set ISP AF environment detector detecting threshold
|
||||
@ -166,7 +166,7 @@ esp_err_t esp_isp_af_controller_set_env_detector(isp_af_ctrlr_t af_ctrlr, const
|
||||
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
|
||||
* - ESP_ERR_INVALID_STATE Driver state is invalid.
|
||||
*/
|
||||
esp_err_t esp_isp_af_controller_set_env_detector_threshold(isp_af_ctrlr_t af_ctrlr, int definition_thresh, int luminance_thresh);
|
||||
esp_err_t esp_isp_af_controller_set_env_detector_threshold(isp_af_ctlr_t af_ctrlr, int definition_thresh, int luminance_thresh);
|
||||
|
||||
/**
|
||||
* @brief Event data structure
|
||||
@ -184,7 +184,7 @@ typedef struct {
|
||||
*
|
||||
* @return Whether a high priority task is woken up by this function
|
||||
*/
|
||||
typedef bool (*esp_isp_af_env_detector_callback_t)(isp_af_ctrlr_t af_ctrlr, const esp_isp_af_env_detector_evt_data_t *edata, void *user_data);
|
||||
typedef bool (*esp_isp_af_env_detector_callback_t)(isp_af_ctlr_t af_ctrlr, const esp_isp_af_env_detector_evt_data_t *edata, void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Group of ISP AF Env detector callbacks
|
||||
@ -215,7 +215,7 @@ typedef struct {
|
||||
* - ESP_ERR_INVALID_ARG: Invalid arguments
|
||||
* - ESP_ERR_INVALID_STATE: Driver state is invalid, you shouldn't call this API at this moment
|
||||
*/
|
||||
esp_err_t esp_isp_af_env_detector_register_event_callbacks(isp_af_ctrlr_t af_ctrlr, const esp_isp_af_env_detector_evt_cbs_t *cbs, void *user_data);
|
||||
esp_err_t esp_isp_af_env_detector_register_event_callbacks(isp_af_ctlr_t af_ctrlr, const esp_isp_af_env_detector_evt_cbs_t *cbs, void *user_data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ typedef struct isp_processor_t *isp_proc_handle_t;
|
||||
/**
|
||||
* @brief Type of ISP AF controller handle
|
||||
*/
|
||||
typedef struct isp_af_controller_t *isp_af_ctrlr_t;
|
||||
typedef struct isp_af_controller_t *isp_af_ctlr_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -19,11 +19,13 @@
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/idf_additions.h"
|
||||
#include "driver/isp_types.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#if SOC_ISP_SUPPORTED
|
||||
#include "hal/isp_hal.h"
|
||||
#include "hal/isp_ll.h"
|
||||
#include "hal/isp_types.h"
|
||||
#include "soc/isp_periph.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -43,6 +45,7 @@ typedef enum {
|
||||
ISP_FSM_START,
|
||||
} isp_fsm_t;
|
||||
|
||||
#if SOC_ISP_SUPPORTED
|
||||
/*---------------------------------------------------------------
|
||||
Driver Context
|
||||
---------------------------------------------------------------*/
|
||||
@ -55,11 +58,15 @@ typedef struct isp_processor_t {
|
||||
#endif
|
||||
isp_fsm_t isp_fsm;
|
||||
portMUX_TYPE spinlock;
|
||||
|
||||
color_space_pixel_format_t in_color_format;
|
||||
color_space_pixel_format_t out_color_format;
|
||||
uint32_t h_res;
|
||||
uint32_t v_res;
|
||||
/* sub module contexts */
|
||||
isp_af_ctrlr_t af_ctlr[SOC_ISP_AF_CTLR_NUMS];
|
||||
isp_af_ctlr_t af_ctlr[SOC_ISP_AF_CTLR_NUMS];
|
||||
isp_fsm_t bf_fsm;
|
||||
} isp_processor_t;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
@ -12,7 +12,7 @@
|
||||
#include "esp_heap_caps.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "driver/isp_af.h"
|
||||
#include "isp_internal.h"
|
||||
#include "esp_private/isp_private.h"
|
||||
|
||||
static const char *TAG = "ISP_AF";
|
||||
|
||||
@ -33,7 +33,7 @@ static void s_isp_af_default_isr(void *arg);
|
||||
/*---------------------------------------------
|
||||
AF
|
||||
----------------------------------------------*/
|
||||
static esp_err_t s_isp_claim_af_controller(isp_proc_handle_t isp_proc, isp_af_ctrlr_t af_ctlr)
|
||||
static esp_err_t s_isp_claim_af_controller(isp_proc_handle_t isp_proc, isp_af_ctlr_t af_ctlr)
|
||||
{
|
||||
assert(isp_proc && af_ctlr);
|
||||
|
||||
@ -56,7 +56,7 @@ static esp_err_t s_isp_claim_af_controller(isp_proc_handle_t isp_proc, isp_af_ct
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void s_isp_declaim_af_controller(isp_af_ctrlr_t af_ctlr)
|
||||
static void s_isp_declaim_af_controller(isp_af_ctlr_t af_ctlr)
|
||||
{
|
||||
assert(af_ctlr && af_ctlr->isp_proc);
|
||||
|
||||
@ -65,7 +65,7 @@ static void s_isp_declaim_af_controller(isp_af_ctrlr_t af_ctlr)
|
||||
portEXIT_CRITICAL(&af_ctlr->isp_proc->spinlock);
|
||||
}
|
||||
|
||||
static void s_isp_af_free_controller(isp_af_ctrlr_t af_ctlr)
|
||||
static void s_isp_af_free_controller(isp_af_ctlr_t af_ctlr)
|
||||
{
|
||||
if (af_ctlr) {
|
||||
if (af_ctlr->intr_handle) {
|
||||
@ -78,7 +78,7 @@ static void s_isp_af_free_controller(isp_af_ctrlr_t af_ctlr)
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t esp_isp_new_af_controller(isp_proc_handle_t isp_proc, const esp_isp_af_config_t *af_config, isp_af_ctrlr_t *ret_hdl)
|
||||
esp_err_t esp_isp_new_af_controller(isp_proc_handle_t isp_proc, const esp_isp_af_config_t *af_config, isp_af_ctlr_t *ret_hdl)
|
||||
{
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
ESP_RETURN_ON_FALSE(isp_proc && af_config && ret_hdl, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
||||
@ -102,7 +102,7 @@ esp_err_t esp_isp_new_af_controller(isp_proc_handle_t isp_proc, const esp_isp_af
|
||||
}
|
||||
ESP_RETURN_ON_FALSE(af_config->edge_thresh > 0, ESP_ERR_INVALID_ARG, TAG, "edge threshold should be larger than 0");
|
||||
|
||||
isp_af_ctrlr_t af_ctlr = heap_caps_calloc(1, sizeof(isp_af_controller_t), ISP_MEM_ALLOC_CAPS);
|
||||
isp_af_ctlr_t af_ctlr = heap_caps_calloc(1, sizeof(isp_af_controller_t), ISP_MEM_ALLOC_CAPS);
|
||||
ESP_RETURN_ON_FALSE(af_ctlr, ESP_ERR_NO_MEM, TAG, "no mem");
|
||||
af_ctlr->evt_que = xQueueCreateWithCaps(1, sizeof(isp_af_result_t), ISP_MEM_ALLOC_CAPS);
|
||||
ESP_GOTO_ON_FALSE(af_ctlr->evt_que, ESP_ERR_NO_MEM, err1, TAG, "no mem for af event queue");
|
||||
@ -141,7 +141,7 @@ err1:
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_isp_del_af_controller(isp_af_ctrlr_t af_ctlr)
|
||||
esp_err_t esp_isp_del_af_controller(isp_af_ctlr_t af_ctlr)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(af_ctlr && af_ctlr->isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
||||
ESP_RETURN_ON_FALSE(af_ctlr->fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "controller isn't in init state");
|
||||
@ -159,7 +159,7 @@ esp_err_t esp_isp_del_af_controller(isp_af_ctrlr_t af_ctlr)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_isp_af_controller_enable(isp_af_ctrlr_t af_ctlr)
|
||||
esp_err_t esp_isp_af_controller_enable(isp_af_ctlr_t af_ctlr)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(af_ctlr && af_ctlr->isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
||||
ESP_RETURN_ON_FALSE(af_ctlr->fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "controller isn't in init state");
|
||||
@ -173,7 +173,7 @@ esp_err_t esp_isp_af_controller_enable(isp_af_ctrlr_t af_ctlr)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_isp_af_controller_disable(isp_af_ctrlr_t af_ctlr)
|
||||
esp_err_t esp_isp_af_controller_disable(isp_af_ctlr_t af_ctlr)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(af_ctlr && af_ctlr->isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
||||
ESP_RETURN_ON_FALSE(af_ctlr->fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "controller isn't in enable state");
|
||||
@ -187,7 +187,7 @@ esp_err_t esp_isp_af_controller_disable(isp_af_ctrlr_t af_ctlr)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_isp_af_controller_get_oneshot_statistics(isp_af_ctrlr_t af_ctrlr, int timeout_ms, isp_af_result_t *out_res)
|
||||
esp_err_t esp_isp_af_controller_get_oneshot_statistics(isp_af_ctlr_t af_ctrlr, int timeout_ms, isp_af_result_t *out_res)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE_ISR(af_ctrlr && (out_res || timeout_ms == 0), ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
||||
ESP_RETURN_ON_FALSE_ISR(af_ctrlr->fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "controller isn't enabled or continuous statistics has started");
|
||||
@ -206,7 +206,7 @@ esp_err_t esp_isp_af_controller_get_oneshot_statistics(isp_af_ctrlr_t af_ctrlr,
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_isp_af_controller_start_continuous_statistics(isp_af_ctrlr_t af_ctrlr)
|
||||
esp_err_t esp_isp_af_controller_start_continuous_statistics(isp_af_ctlr_t af_ctrlr)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE_ISR(af_ctrlr, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
||||
ESP_RETURN_ON_FALSE_ISR(af_ctrlr->fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "controller isn't in enable state");
|
||||
@ -217,7 +217,7 @@ esp_err_t esp_isp_af_controller_start_continuous_statistics(isp_af_ctrlr_t af_ct
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_isp_af_controller_stop_continuous_statistics(isp_af_ctrlr_t af_ctrlr)
|
||||
esp_err_t esp_isp_af_controller_stop_continuous_statistics(isp_af_ctlr_t af_ctrlr)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE_ISR(af_ctrlr, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
||||
ESP_RETURN_ON_FALSE_ISR(af_ctrlr->fsm == ISP_FSM_START, ESP_ERR_INVALID_STATE, TAG, "controller isn't in continuous state");
|
||||
@ -231,7 +231,7 @@ esp_err_t esp_isp_af_controller_stop_continuous_statistics(isp_af_ctrlr_t af_ctr
|
||||
/*---------------------------------------------
|
||||
AF Env Monitor
|
||||
----------------------------------------------*/
|
||||
esp_err_t esp_isp_af_controller_set_env_detector(isp_af_ctrlr_t af_ctrlr, const esp_isp_af_env_config_t *env_config)
|
||||
esp_err_t esp_isp_af_controller_set_env_detector(isp_af_ctlr_t af_ctrlr, const esp_isp_af_env_config_t *env_config)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(af_ctrlr && env_config, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
||||
ESP_RETURN_ON_FALSE(af_ctrlr->fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "invalid fsm, should be called when in init state");
|
||||
@ -248,7 +248,7 @@ esp_err_t esp_isp_af_controller_set_env_detector(isp_af_ctrlr_t af_ctrlr, const
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_isp_af_env_detector_register_event_callbacks(isp_af_ctrlr_t af_ctrlr, const esp_isp_af_env_detector_evt_cbs_t *cbs, void *user_data)
|
||||
esp_err_t esp_isp_af_env_detector_register_event_callbacks(isp_af_ctlr_t af_ctrlr, const esp_isp_af_env_detector_evt_cbs_t *cbs, void *user_data)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(af_ctrlr && cbs, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
ESP_RETURN_ON_FALSE(af_ctrlr->fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "detector isn't in the init state");
|
||||
@ -271,7 +271,7 @@ esp_err_t esp_isp_af_env_detector_register_event_callbacks(isp_af_ctrlr_t af_ctr
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_isp_af_controller_set_env_detector_threshold(isp_af_ctrlr_t af_ctrlr, int definition_thresh, int luminance_thresh)
|
||||
esp_err_t esp_isp_af_controller_set_env_detector_threshold(isp_af_ctlr_t af_ctrlr, int definition_thresh, int luminance_thresh)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE_ISR(af_ctrlr, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
ESP_RETURN_ON_FALSE_ISR(af_ctrlr->fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "detector isn't in enable state");
|
||||
@ -286,7 +286,7 @@ esp_err_t esp_isp_af_controller_set_env_detector_threshold(isp_af_ctrlr_t af_ctr
|
||||
---------------------------------------------------------------*/
|
||||
static void IRAM_ATTR s_isp_af_default_isr(void *arg)
|
||||
{
|
||||
isp_af_ctrlr_t af_ctrlr = (isp_af_ctrlr_t)arg;
|
||||
isp_af_ctlr_t af_ctrlr = (isp_af_ctlr_t)arg;
|
||||
isp_proc_handle_t proc = af_ctrlr->isp_proc;
|
||||
|
||||
uint32_t af_events = isp_hal_check_clear_intr_event(&proc->hal, ISP_LL_EVENT_AF_MASK);
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include "hal/hal_utils.h"
|
||||
#include "soc/mipi_csi_bridge_struct.h"
|
||||
#include "soc/isp_periph.h"
|
||||
#include "isp_internal.h"
|
||||
#include "esp_private/isp_private.h"
|
||||
|
||||
static const char *TAG = "ISP_BF";
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include "hal/hal_utils.h"
|
||||
#include "soc/mipi_csi_bridge_struct.h"
|
||||
#include "soc/isp_periph.h"
|
||||
#include "isp_internal.h"
|
||||
#include "esp_private/isp_private.h"
|
||||
|
||||
typedef struct isp_platform_t {
|
||||
_lock_t mutex;
|
||||
@ -73,7 +73,7 @@ esp_err_t esp_isp_new_processor(const esp_isp_processor_cfg_t *proc_config, isp_
|
||||
{
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
ESP_RETURN_ON_FALSE(proc_config && ret_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
||||
ESP_RETURN_ON_FALSE(proc_config->input_data_source == ISP_INPUT_DATA_SOURCE_CSI, ESP_ERR_NOT_SUPPORTED, TAG, "only support CSI as input source at this moment");
|
||||
ESP_RETURN_ON_FALSE(proc_config->input_data_source != ISP_INPUT_DATA_SOURCE_DWGDMA, ESP_ERR_NOT_SUPPORTED, TAG, "input source not supported yet");
|
||||
ESP_RETURN_ON_FALSE(proc_config->input_data_color_type == ISP_COLOR_RAW8, ESP_ERR_NOT_SUPPORTED, TAG, "input data type not supported");
|
||||
|
||||
isp_processor_t *proc = heap_caps_calloc(1, sizeof(isp_processor_t), ISP_MEM_ALLOC_CAPS);
|
||||
@ -143,6 +143,11 @@ esp_err_t esp_isp_new_processor(const esp_isp_processor_cfg_t *proc_config, isp_
|
||||
isp_ll_set_intput_data_h_pixel_num(proc->hal.hw, proc_config->h_res);
|
||||
isp_ll_set_intput_data_v_row_num(proc->hal.hw, proc_config->v_res);
|
||||
|
||||
proc->in_color_format = in_color_format;
|
||||
proc->out_color_format = out_color_format;
|
||||
proc->h_res = proc_config->h_res;
|
||||
proc->v_res = proc_config->v_res;
|
||||
|
||||
*ret_proc = proc;
|
||||
|
||||
return ESP_OK;
|
||||
|
@ -8,6 +8,7 @@ endif()
|
||||
set(priv_requires
|
||||
unity
|
||||
esp_driver_isp
|
||||
esp_psram
|
||||
)
|
||||
|
||||
idf_component_register(SRCS ${srcs}
|
||||
|
@ -7,8 +7,8 @@
|
||||
#include "sdkconfig.h"
|
||||
#include "unity.h"
|
||||
#include "driver/isp.h"
|
||||
|
||||
#include "esp_rom_sys.h"
|
||||
#include "esp_private/isp_dvp_private.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
TEST_CASE("ISP processor exhausted allocation", "[isp]")
|
||||
{
|
||||
@ -31,6 +31,45 @@ TEST_CASE("ISP processor exhausted allocation", "[isp]")
|
||||
}
|
||||
}
|
||||
|
||||
#if SOC_ISP_DVP_SUPPORTED
|
||||
TEST_CASE("ISP DVP controller exhausted allocation", "[isp]")
|
||||
{
|
||||
esp_isp_processor_cfg_t isp_config = {
|
||||
.clk_hz = 120 * 1000 * 1000,
|
||||
.input_data_source = ISP_INPUT_DATA_SOURCE_DVP,
|
||||
.input_data_color_type = ISP_COLOR_RAW8,
|
||||
.output_data_color_type = ISP_COLOR_RGB565,
|
||||
.has_line_start_packet = false,
|
||||
.has_line_end_packet = false,
|
||||
.h_res = 800,
|
||||
.v_res = 640,
|
||||
};
|
||||
isp_proc_handle_t isp_proc = NULL;
|
||||
TEST_ESP_OK(esp_isp_new_processor(&isp_config, &isp_proc));
|
||||
|
||||
esp_cam_ctlr_isp_dvp_cfg_t dvp_ctlr_config = {
|
||||
.data_width = 8,
|
||||
.data_io = {53, 54, 52, 0, 1, 45, 46, 47, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
.pclk_io = 21,
|
||||
.hsync_io = 5,
|
||||
.vsync_io = 23,
|
||||
.de_io = 22,
|
||||
.io_flags.vsync_invert = 1,
|
||||
};
|
||||
esp_cam_ctlr_handle_t dvp_ctrlr[SOC_ISP_DVP_CTLR_NUMS + 1] = {};
|
||||
for (int i = 0; i < SOC_ISP_DVP_CTLR_NUMS; i++) {
|
||||
TEST_ESP_OK(esp_isp_new_dvp_controller(isp_proc, &dvp_ctlr_config, &dvp_ctrlr[i]));
|
||||
}
|
||||
|
||||
TEST_ASSERT(esp_isp_new_dvp_controller(isp_proc, &dvp_ctlr_config, &dvp_ctrlr[SOC_ISP_DVP_CTLR_NUMS]) == ESP_ERR_NOT_FOUND);
|
||||
|
||||
for (int i = 0; i < SOC_ISP_DVP_CTLR_NUMS; i++) {
|
||||
TEST_ESP_OK(esp_isp_del_dvp_controller(dvp_ctrlr[i]));
|
||||
}
|
||||
TEST_ESP_OK(esp_isp_del_processor(isp_proc));
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_CASE("ISP AF controller exhausted allocation", "[isp]")
|
||||
{
|
||||
esp_isp_processor_cfg_t isp_config = {
|
||||
@ -45,7 +84,7 @@ TEST_CASE("ISP AF controller exhausted allocation", "[isp]")
|
||||
esp_isp_af_config_t af_config = {
|
||||
.edge_thresh = 128,
|
||||
};
|
||||
isp_af_ctrlr_t af_ctrlr[SOC_ISP_AF_CTLR_NUMS + 1] = {};
|
||||
isp_af_ctlr_t af_ctrlr[SOC_ISP_AF_CTLR_NUMS + 1] = {};
|
||||
for (int i = 0; i < SOC_ISP_AF_CTLR_NUMS; i++) {
|
||||
TEST_ESP_OK(esp_isp_new_af_controller(isp_proc, &af_config, &af_ctrlr[i]));
|
||||
}
|
||||
|
@ -1,2 +1,5 @@
|
||||
CONFIG_FREERTOS_HZ=1000
|
||||
CONFIG_ESP_TASK_WDT_EN=n
|
||||
CONFIG_SPIRAM=y
|
||||
CONFIG_IDF_EXPERIMENTAL_FEATURES=y
|
||||
CONFIG_SPIRAM_SPEED_200M=y
|
||||
|
@ -76,6 +76,13 @@ extern "C" {
|
||||
---------------------------------------------------------------*/
|
||||
#define ISP_LL_BF_DEFAULT_TEMPLATE_VAL 15
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
DVP
|
||||
---------------------------------------------------------------*/
|
||||
#define ISP_LL_DVP_DATA_TYPE_RAW8 0x2A
|
||||
#define ISP_LL_DVP_DATA_TYPE_RAW10 0x2B
|
||||
#define ISP_LL_DVP_DATA_TYPE_RAW12 0x2C
|
||||
|
||||
/**
|
||||
* @brief Env monitor mode
|
||||
*/
|
||||
@ -791,6 +798,130 @@ static inline void isp_ll_color_enable(isp_dev_t *hw, bool enable)
|
||||
hw->cntl.color_en = enable;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
DVP Camera
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Set dvp data color format
|
||||
*
|
||||
* @param[in] hw Hardware instance address
|
||||
* @param[in] format color format, see `color_space_pixel_format_t`
|
||||
*
|
||||
* @return true for valid format, false for invalid format
|
||||
*/
|
||||
static inline bool isp_ll_dvp_set_data_type(isp_dev_t *hw, color_space_pixel_format_t format)
|
||||
{
|
||||
bool valid = false;
|
||||
|
||||
if (format.color_space == COLOR_SPACE_RAW) {
|
||||
switch(format.pixel_format) {
|
||||
case COLOR_PIXEL_RAW8:
|
||||
hw->cam_conf.cam_data_type = ISP_LL_DVP_DATA_TYPE_RAW8;
|
||||
valid = true;
|
||||
break;
|
||||
case COLOR_PIXEL_RAW10:
|
||||
hw->cam_conf.cam_data_type = ISP_LL_DVP_DATA_TYPE_RAW10;
|
||||
valid = true;
|
||||
break;
|
||||
case COLOR_PIXEL_RAW12:
|
||||
hw->cam_conf.cam_data_type = ISP_LL_DVP_DATA_TYPE_RAW12;
|
||||
valid = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable / Disable 2B mode
|
||||
*
|
||||
* @param[in] hw Hardware instance address
|
||||
* @param[in] enable Enable / Disable
|
||||
*/
|
||||
static inline void isp_ll_dvp_enable_2byte_mode(isp_dev_t *hw, bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
HAL_ASSERT(hw->cam_conf.cam_data_type == ISP_LL_DVP_DATA_TYPE_RAW8);
|
||||
hw->cam_conf.cam_2byte_mode = 1;
|
||||
} else {
|
||||
hw->cam_conf.cam_2byte_mode = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset DVP CAM module
|
||||
*
|
||||
* @param[in] hw Hardware instance address
|
||||
*/
|
||||
static inline void isp_ll_dvp_cam_reset(isp_dev_t *hw)
|
||||
{
|
||||
hw->cam_cntl.cam_reset = 1;
|
||||
hw->cam_cntl.cam_reset = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable DVP CAM pclk invert
|
||||
*
|
||||
* @param[in] hw Hardware instance address
|
||||
* @param[in] enable Enable / Disable
|
||||
*/
|
||||
static inline void isp_ll_cam_enable_pclk_invert(isp_dev_t *hw, bool enable)
|
||||
{
|
||||
hw->cam_cntl.cam_clk_inv = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable DVP CAM de invert
|
||||
*
|
||||
* @param[in] hw Hardware instance address
|
||||
* @param[in] enable Enable / Disable
|
||||
*/
|
||||
static inline void isp_ll_cam_enable_de_invert(isp_dev_t *hw, bool enable)
|
||||
{
|
||||
hw->cam_conf.cam_de_inv = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable DVP CAM hsync invert
|
||||
*
|
||||
* @param[in] hw Hardware instance address
|
||||
* @param[in] enable Enable / Disable
|
||||
*/
|
||||
static inline void isp_ll_cam_enable_hsync_invert(isp_dev_t *hw, bool enable)
|
||||
{
|
||||
hw->cam_conf.cam_hsync_inv = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable DVP CAM vsync invert
|
||||
*
|
||||
* @param[in] hw Hardware instance address
|
||||
* @param[in] enable Enable / Disable
|
||||
*/
|
||||
static inline void isp_ll_cam_enable_vsync_invert(isp_dev_t *hw, bool enable)
|
||||
{
|
||||
hw->cam_conf.cam_vsync_inv = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable DVP CAM
|
||||
*
|
||||
* @param[in] hw Hardware instance address
|
||||
* @param[in] enable Enable / Disable
|
||||
*/
|
||||
static inline void isp_ll_cam_enable(isp_dev_t *hw, bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
hw->cam_cntl.cam_update_reg = 1;
|
||||
hw->cam_cntl.cam_en = 1;
|
||||
while (hw->cam_cntl.cam_update_reg);
|
||||
} else {
|
||||
hw->cam_cntl.cam_en = 0;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------
|
||||
INTR
|
||||
---------------------------------------------------------------*/
|
||||
|
42
components/hal/include/hal/cam_ctlr_types.h
Normal file
42
components/hal/include/hal/cam_ctlr_types.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
#include "hal/color_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Camera Controller Color Type
|
||||
*/
|
||||
typedef enum {
|
||||
CAM_CTLR_COLOR_RAW8 = COLOR_TYPE_ID(COLOR_SPACE_RAW, COLOR_PIXEL_RAW8), ///< RAW8
|
||||
CAM_CTLR_COLOR_RAW10 = COLOR_TYPE_ID(COLOR_SPACE_RAW, COLOR_PIXEL_RAW10), ///< RAW10
|
||||
CAM_CTLR_COLOR_RAW12 = COLOR_TYPE_ID(COLOR_SPACE_RAW, COLOR_PIXEL_RAW12), ///< RAW12
|
||||
CAM_CTLR_COLOR_RGB565 = COLOR_TYPE_ID(COLOR_SPACE_RGB, COLOR_PIXEL_RGB565), ///< RGB565
|
||||
CAM_CTLR_COLOR_RGB666 = COLOR_TYPE_ID(COLOR_SPACE_RGB, COLOR_PIXEL_RGB666), ///< RGB666
|
||||
CAM_CTLR_COLOR_RGB888 = COLOR_TYPE_ID(COLOR_SPACE_RGB, COLOR_PIXEL_RGB888), ///< RGB888
|
||||
CAM_CTLR_COLOR_YUV420 = COLOR_TYPE_ID(COLOR_SPACE_YUV, COLOR_PIXEL_YUV420), ///< YUV420
|
||||
CAM_CTLR_COLOR_YUV422 = COLOR_TYPE_ID(COLOR_SPACE_YUV, COLOR_PIXEL_YUV422), ///< YUV422
|
||||
} cam_ctlr_color_t;
|
||||
|
||||
/**
|
||||
* @brief Camera Controller Data Width
|
||||
*/
|
||||
typedef enum {
|
||||
CAM_CTLR_DATA_WIDTH_8 = 8, ///< 8-bit data width
|
||||
CAM_CTLR_DATA_WIDTH_10 = 10, ///< 10-bit data width
|
||||
CAM_CTLR_DATA_WIDTH_12 = 12, ////< 12-bit data width
|
||||
CAM_CTLR_DATA_WIDTH_16 = 16, ///< 16-bit data width
|
||||
} cam_ctlr_data_width_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -45,6 +45,15 @@ typedef enum {
|
||||
ISP_COLOR_YUV420 = COLOR_TYPE_ID(COLOR_SPACE_YUV, COLOR_PIXEL_YUV420), ///< YUV420
|
||||
} isp_color_t;
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
DVP
|
||||
---------------------------------------------------------------*/
|
||||
#if SOC_ISP_AF_WINDOW_NUMS
|
||||
#define ISP_DVP_DATA_SIG_NUM SOC_ISP_DVP_DATA_WIDTH_MAX // The ISP DVP data signal number
|
||||
#else
|
||||
#define ISP_DVP_DATA_SIG_NUM 0
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
AF
|
||||
---------------------------------------------------------------*/
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/clk_tree_defs.h"
|
||||
#include "hal/color_types.h"
|
||||
#include "hal/cam_ctlr_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -24,20 +25,6 @@ typedef soc_periph_mipi_csi_phy_clk_src_t mipi_csi_phy_clock_source_t;
|
||||
typedef int mipi_csi_phy_clock_source_t;
|
||||
#endif // SOC_MIPI_CSI_SUPPORTED
|
||||
|
||||
/**
|
||||
* @brief MIPI CSI Color Type
|
||||
*/
|
||||
typedef enum {
|
||||
MIPI_CSI_COLOR_RAW8 = COLOR_TYPE_ID(COLOR_SPACE_RAW, COLOR_PIXEL_RAW8), ///< RAW8
|
||||
MIPI_CSI_COLOR_RAW10 = COLOR_TYPE_ID(COLOR_SPACE_RAW, COLOR_PIXEL_RAW10), ///< RAW10
|
||||
MIPI_CSI_COLOR_RAW12 = COLOR_TYPE_ID(COLOR_SPACE_RAW, COLOR_PIXEL_RAW12), ///< RAW12
|
||||
MIPI_CSI_COLOR_RGB565 = COLOR_TYPE_ID(COLOR_SPACE_RGB, COLOR_PIXEL_RGB565), ///< RGB565
|
||||
MIPI_CSI_COLOR_RGB666 = COLOR_TYPE_ID(COLOR_SPACE_RGB, COLOR_PIXEL_RGB666), ///< RGB666
|
||||
MIPI_CSI_COLOR_RGB888 = COLOR_TYPE_ID(COLOR_SPACE_RGB, COLOR_PIXEL_RGB888), ///< RGB888
|
||||
MIPI_CSI_COLOR_YUV420 = COLOR_TYPE_ID(COLOR_SPACE_YUV, COLOR_PIXEL_YUV420), ///< YUV420
|
||||
MIPI_CSI_COLOR_YUV422 = COLOR_TYPE_ID(COLOR_SPACE_YUV, COLOR_PIXEL_YUV422), ///< YUV422
|
||||
} mipi_csi_color_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -763,10 +763,18 @@ config SOC_ISP_BF_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_ISP_DVP_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_ISP_NUMS
|
||||
int
|
||||
default 1
|
||||
|
||||
config SOC_ISP_DVP_CTLR_NUMS
|
||||
int
|
||||
default 1
|
||||
|
||||
config SOC_ISP_AF_CTLR_NUMS
|
||||
int
|
||||
default 1
|
||||
@ -787,6 +795,10 @@ config SOC_ISP_BF_TEMPLATE_Y_NUMS
|
||||
int
|
||||
default 3
|
||||
|
||||
config SOC_ISP_DVP_DATA_WIDTH_MAX
|
||||
int
|
||||
default 16
|
||||
|
||||
config SOC_LEDC_SUPPORT_PLL_DIV_CLOCK
|
||||
bool
|
||||
default y
|
||||
|
@ -313,13 +313,16 @@
|
||||
|
||||
/*-------------------------- ISP CAPS ----------------------------------------*/
|
||||
#define SOC_ISP_BF_SUPPORTED 1
|
||||
#define SOC_ISP_DVP_SUPPORTED 1
|
||||
|
||||
#define SOC_ISP_NUMS 1U
|
||||
#define SOC_ISP_DVP_CTLR_NUMS 1U
|
||||
#define SOC_ISP_AF_CTLR_NUMS 1U
|
||||
#define SOC_ISP_AF_WINDOW_NUMS 3
|
||||
#define SOC_ISP_SHARE_CSI_BRG 1
|
||||
#define SOC_ISP_BF_TEMPLATE_X_NUMS 3
|
||||
#define SOC_ISP_BF_TEMPLATE_Y_NUMS 3
|
||||
#define SOC_ISP_DVP_DATA_WIDTH_MAX 16
|
||||
|
||||
/*-------------------------- LEDC CAPS ---------------------------------------*/
|
||||
#define SOC_LEDC_SUPPORT_PLL_DIV_CLOCK (1)
|
||||
|
@ -16,6 +16,32 @@ const isp_info_t isp_hw_info = {
|
||||
[0] = {
|
||||
.irq = ETS_ISP_INTR_SOURCE,
|
||||
}
|
||||
},
|
||||
.dvp_ctlr = {
|
||||
[0] = {
|
||||
.dvp_pclk_sig = CAM_PCLK_PAD_IN_IDX,
|
||||
.dvp_hsync_sig = CAM_H_SYNC_PAD_IN_IDX,
|
||||
.dvp_vsync_sig = CAM_V_SYNC_PAD_IN_IDX,
|
||||
.dvp_de_sig = CAM_H_ENABLE_PAD_IN_IDX,
|
||||
.dvp_data_sig = {
|
||||
CAM_DATA_IN_PAD_IN0_IDX,
|
||||
CAM_DATA_IN_PAD_IN1_IDX,
|
||||
CAM_DATA_IN_PAD_IN2_IDX,
|
||||
CAM_DATA_IN_PAD_IN3_IDX,
|
||||
CAM_DATA_IN_PAD_IN4_IDX,
|
||||
CAM_DATA_IN_PAD_IN5_IDX,
|
||||
CAM_DATA_IN_PAD_IN6_IDX,
|
||||
CAM_DATA_IN_PAD_IN7_IDX,
|
||||
CAM_DATA_IN_PAD_IN8_IDX,
|
||||
CAM_DATA_IN_PAD_IN9_IDX,
|
||||
CAM_DATA_IN_PAD_IN10_IDX,
|
||||
CAM_DATA_IN_PAD_IN11_IDX,
|
||||
CAM_DATA_IN_PAD_IN12_IDX,
|
||||
CAM_DATA_IN_PAD_IN13_IDX,
|
||||
CAM_DATA_IN_PAD_IN14_IDX,
|
||||
CAM_DATA_IN_PAD_IN15_IDX
|
||||
},
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <stdint.h>
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/periph_defs.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -19,6 +20,13 @@ typedef struct {
|
||||
struct {
|
||||
const uint32_t irq;
|
||||
} instances[SOC_ISP_NUMS];
|
||||
struct {
|
||||
const uint32_t dvp_pclk_sig;
|
||||
const uint32_t dvp_hsync_sig;
|
||||
const uint32_t dvp_vsync_sig;
|
||||
const uint32_t dvp_de_sig;
|
||||
const uint32_t dvp_data_sig[SOC_ISP_DVP_DATA_WIDTH_MAX];
|
||||
} dvp_ctlr[SOC_ISP_DVP_CTLR_NUMS];
|
||||
} isp_info_t;
|
||||
|
||||
extern const isp_info_t isp_hw_info;
|
||||
|
@ -48,8 +48,8 @@ Resource Allocation
|
||||
.h_res = MIPI_CSI_DISP_HSIZE,
|
||||
.v_res = MIPI_CSI_DISP_VSIZE_640P,
|
||||
.lane_bit_rate_mbps = MIPI_CSI_LANE_BITRATE_MBPS,
|
||||
.input_data_color_type = MIPI_CSI_COLOR_RAW8,
|
||||
.output_data_color_type = MIPI_CSI_COLOR_RGB565,
|
||||
.input_data_color_type = CAM_CTLR_COLOR_RAW8,
|
||||
.output_data_color_type = CAM_CTLR_COLOR_RGB565,
|
||||
.data_lane_num = 2,
|
||||
.byte_swap_en = false,
|
||||
.queue_items = 1,
|
||||
@ -134,7 +134,7 @@ The factory function :cpp:func:`esp_cam_new_csi_ctlr` and :cpp:func:`esp_cam_ctl
|
||||
Kconfig Options
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
- :ref:`CONFIG_MIPI_CSI_ISR_IRAM_SAFE` controls whether the default ISR handler should be masked when the cache is disabled
|
||||
- :ref:`CONFIG_CAM_CTLR_MIPI_CSI_ISR_IRAM_SAFE` controls whether the default ISR handler should be masked when the cache is disabled
|
||||
|
||||
|
||||
.. _cam-iram-safe:
|
||||
@ -144,7 +144,7 @@ IRAM Safe
|
||||
|
||||
By default, the CSI interrupt will be deferred when the cache is disabled because of writing or erasing the flash.
|
||||
|
||||
There is a Kconfig option :ref:`CONFIG_MIPI_CSI_ISR_IRAM_SAFE` that:
|
||||
There is a Kconfig option :ref:`CONFIG_CAM_CTLR_MIPI_CSI_ISR_IRAM_SAFE` that:
|
||||
|
||||
- Enables the interrupt being serviced even when the cache is disabled
|
||||
- Places all functions that used by the ISR into IRAM
|
||||
|
@ -71,7 +71,7 @@ If the configurations in :cpp:type:`esp_isp_af_config_t` is specified, users can
|
||||
esp_isp_af_config_t af_config = {
|
||||
.edge_thresh = 128,
|
||||
};
|
||||
isp_af_ctrlr_t af_ctrlr = NULL;
|
||||
isp_af_ctlr_t af_ctrlr = NULL;
|
||||
ESP_ERROR_CHECK(esp_isp_new_af_controller(isp_proc, &af_config, &af_ctrlr));
|
||||
|
||||
You can use the created handle to do driver enable / disable the ISP AF driver and ISP AF Env module installation.
|
||||
@ -122,7 +122,7 @@ Calling :cpp:func:`esp_isp_af_controller_get_oneshot_statistics` to get oneshot
|
||||
esp_isp_af_config_t af_config = {
|
||||
.edge_thresh = 128,
|
||||
};
|
||||
isp_af_ctrlr_t af_ctrlr = NULL;
|
||||
isp_af_ctlr_t af_ctrlr = NULL;
|
||||
ESP_ERROR_CHECK(esp_isp_new_af_controller(isp_proc, &af_config, &af_ctrlr));
|
||||
ESP_ERROR_CHECK(esp_isp_af_controller_enable(af_ctrlr));
|
||||
isp_af_result_t result = {};
|
||||
@ -140,7 +140,7 @@ Note that if you want to use the continuous statistics, you need to register the
|
||||
|
||||
.. code:: c
|
||||
|
||||
isp_af_ctrlr_t af_ctrlr = NULL;
|
||||
isp_af_ctlr_t af_ctrlr = NULL;
|
||||
esp_isp_af_config_t af_config = {
|
||||
.edge_thresh = 128,
|
||||
};
|
||||
@ -171,7 +171,7 @@ Calling :cpp:func:`esp_isp_af_controller_set_env_detector` to set an ISP AF envi
|
||||
esp_isp_af_env_config_t env_config = {
|
||||
.interval = 10,
|
||||
};
|
||||
isp_af_ctrlr_t af_ctrlr = NULL;
|
||||
isp_af_ctlr_t af_ctrlr = NULL;
|
||||
ESP_ERROR_CHECK(esp_isp_new_af_controller(isp_proc, &af_config, &af_ctrlr));
|
||||
ESP_ERROR_CHECK(esp_isp_af_controller_set_env_detector(af_ctrlr, &env_config));
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
idf_component_register(SRCS "example_dsi_init.c"
|
||||
INCLUDE_DIRS "."
|
||||
INCLUDE_DIRS "include"
|
||||
REQUIRES esp_lcd
|
||||
)
|
@ -0,0 +1,25 @@
|
||||
menu "Example DSI Configuration"
|
||||
choice EXAMPLE_MIPI_DSI_DISP_HRES
|
||||
bool "Set MIPI CSI horizontal resolution"
|
||||
default EXAMPLE_MIPI_DSI_DISP_HRES_800
|
||||
|
||||
config EXAMPLE_MIPI_DSI_DISP_HRES_800
|
||||
bool "800"
|
||||
endchoice
|
||||
|
||||
config EXAMPLE_MIPI_DSI_DISP_HRES
|
||||
int
|
||||
default 800 if EXAMPLE_MIPI_DSI_DISP_HRES_800
|
||||
|
||||
choice EXAMPLE_MIPI_DSI_DISP_VRES
|
||||
bool "Set MIPI CSI vertical resolution"
|
||||
default EXAMPLE_MIPI_DSI_DISP_VRES_1280
|
||||
|
||||
config EXAMPLE_MIPI_DSI_DISP_VRES_1280
|
||||
bool "1280"
|
||||
endchoice
|
||||
|
||||
config EXAMPLE_MIPI_DSI_DISP_VRES
|
||||
int
|
||||
default 1280 if EXAMPLE_MIPI_DSI_DISP_VRES_1280
|
||||
endmenu
|
@ -10,6 +10,7 @@
|
||||
#include "esp_lcd_panel_ops.h"
|
||||
#include "esp_lcd_ili9881c.h"
|
||||
#include "example_dsi_init.h"
|
||||
#include "example_dsi_init_config.h"
|
||||
|
||||
void example_dsi_resource_alloc(esp_lcd_panel_handle_t *ili9881c_ctrl_panel, esp_lcd_panel_handle_t *mipi_dpi_panel, void **frame_buffer)
|
||||
{
|
||||
@ -45,8 +46,8 @@ void example_dsi_resource_alloc(esp_lcd_panel_handle_t *ili9881c_ctrl_panel, esp
|
||||
.virtual_channel = 0,
|
||||
.pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565,
|
||||
.video_timing = {
|
||||
.h_size = EXAMPLE_MIPI_DSI_IMAGE_HSIZE,
|
||||
.v_size = EXAMPLE_MIPI_DSI_IMAGE_VSIZE,
|
||||
.h_size = CONFIG_EXAMPLE_MIPI_DSI_DISP_HRES,
|
||||
.v_size = CONFIG_EXAMPLE_MIPI_DSI_DISP_VRES,
|
||||
.hsync_back_porch = EXAMPLE_MIPI_DSI_IMAGE_HBP,
|
||||
.hsync_pulse_width = EXAMPLE_MIPI_DSI_IMAGE_HSYNC,
|
||||
.hsync_front_porch = EXAMPLE_MIPI_DSI_IMAGE_HFP,
|
@ -1,4 +1,4 @@
|
||||
dependencies:
|
||||
espressif/esp_lcd_ili9881c: "^0.2.0"
|
||||
esp_lcd_ili9881c: ">=0.1.0"
|
||||
idf:
|
||||
version: ">=5.3.0"
|
@ -6,19 +6,14 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "esp_lcd_mipi_dsi.h"
|
||||
#include "esp_lcd_panel_ops.h"
|
||||
#include "esp_lcd_ili9881c.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define EXAMPLE_MIPI_DSI_IMAGE_HSIZE 800
|
||||
#define EXAMPLE_MIPI_DSI_IMAGE_VSIZE 1280
|
||||
#define EXAMPLE_MIPI_DSI_IMAGE_HSYNC 40
|
||||
#define EXAMPLE_MIPI_DSI_IMAGE_HBP 140
|
||||
#define EXAMPLE_MIPI_DSI_IMAGE_HFP 40
|
||||
#define EXAMPLE_MIPI_DSI_IMAGE_VSYNC 4
|
||||
#define EXAMPLE_MIPI_DSI_IMAGE_VBP 16
|
||||
#define EXAMPLE_MIPI_DSI_IMAGE_VFP 16
|
||||
|
||||
/**
|
||||
* @brief DSI init function
|
||||
*
|
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define EXAMPLE_MIPI_DSI_IMAGE_HSYNC 40
|
||||
#define EXAMPLE_MIPI_DSI_IMAGE_HBP 140
|
||||
#define EXAMPLE_MIPI_DSI_IMAGE_HFP 40
|
||||
#define EXAMPLE_MIPI_DSI_IMAGE_VSYNC 4
|
||||
#define EXAMPLE_MIPI_DSI_IMAGE_VBP 16
|
||||
#define EXAMPLE_MIPI_DSI_IMAGE_VFP 16
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,4 +1,4 @@
|
||||
idf_component_register(SRCS "camera_dsi_main.c"
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES esp_mm esp_driver_isp esp_driver_cam esp_driver_i2c esp_lcd dsi_init
|
||||
REQUIRES esp_mm esp_driver_isp esp_driver_cam esp_driver_i2c dsi_init
|
||||
)
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "esp_cam_sensor.h"
|
||||
#include "ov5647.h"
|
||||
#include "example_dsi_init.h"
|
||||
#include "example_dsi_init_config.h"
|
||||
#include "example_config.h"
|
||||
|
||||
static const char *TAG = "cam_dsi";
|
||||
@ -55,9 +56,9 @@ void app_main(void)
|
||||
example_dsi_resource_alloc(&ili9881c_ctrl_panel, &mipi_dpi_panel, &frame_buffer);
|
||||
|
||||
//---------------Necessary variable config------------------//
|
||||
frame_buffer_size = CONFIG_EXAMPLE_MIPI_CSI_DISP_HRES * EXAMPLE_MIPI_DSI_IMAGE_VSIZE * EXAMPLE_RGB565_BITS_PER_PIXEL / 8;
|
||||
frame_buffer_size = CONFIG_EXAMPLE_MIPI_CSI_DISP_HRES * CONFIG_EXAMPLE_MIPI_DSI_DISP_VRES * EXAMPLE_RGB565_BITS_PER_PIXEL / 8;
|
||||
|
||||
ESP_LOGD(TAG, "CONFIG_EXAMPLE_MIPI_CSI_DISP_HRES: %d, EXAMPLE_MIPI_DSI_IMAGE_VSIZE: %d, bits per pixel: %d", CONFIG_EXAMPLE_MIPI_CSI_DISP_HRES, EXAMPLE_MIPI_DSI_IMAGE_VSIZE, 8);
|
||||
ESP_LOGD(TAG, "CONFIG_EXAMPLE_MIPI_CSI_DISP_HRES: %d, CONFIG_EXAMPLE_MIPI_DSI_DISP_VRES: %d, bits per pixel: %d", CONFIG_EXAMPLE_MIPI_CSI_DISP_HRES, CONFIG_EXAMPLE_MIPI_DSI_DISP_VRES, 8);
|
||||
ESP_LOGD(TAG, "frame_buffer_size: %zu", frame_buffer_size);
|
||||
ESP_LOGD(TAG, "frame_buffer: %p", frame_buffer);
|
||||
|
||||
@ -92,8 +93,8 @@ void app_main(void)
|
||||
.h_res = CONFIG_EXAMPLE_MIPI_CSI_DISP_HRES,
|
||||
.v_res = CONFIG_EXAMPLE_MIPI_CSI_DISP_VRES,
|
||||
.lane_bit_rate_mbps = EXAMPLE_MIPI_CSI_LANE_BITRATE_MBPS,
|
||||
.input_data_color_type = MIPI_CSI_COLOR_RAW8,
|
||||
.output_data_color_type = MIPI_CSI_COLOR_RGB565,
|
||||
.input_data_color_type = CAM_CTLR_COLOR_RAW8,
|
||||
.output_data_color_type = CAM_CTLR_COLOR_RGB565,
|
||||
.data_lane_num = 2,
|
||||
.byte_swap_en = false,
|
||||
.queue_items = 1,
|
||||
|
@ -4,4 +4,4 @@ dependencies:
|
||||
idf:
|
||||
version: ">=5.3.0"
|
||||
dsi_init:
|
||||
path: ${IDF_PATH}/examples/peripherals/camera/components/dsi_init
|
||||
path: ${IDF_PATH}/examples/peripherals/camera/camera_dsi/components/dsi_init
|
||||
|
@ -52,7 +52,7 @@ typedef struct {
|
||||
* - ESP_ERR_INVALID_STATE Invalid state
|
||||
* - ESP_ERR_NO_MEM If out of memory
|
||||
*/
|
||||
esp_err_t isp_af_create_sa_scheme(isp_af_ctrlr_t af_ctrlr, const isp_af_sa_scheme_config_t *config, isp_af_scheme_handle_t *ret_scheme);
|
||||
esp_err_t isp_af_create_sa_scheme(isp_af_ctlr_t af_ctrlr, const isp_af_sa_scheme_config_t *config, isp_af_scheme_handle_t *ret_scheme);
|
||||
|
||||
/**
|
||||
* @brief Delete an AF step approximation scheme
|
||||
|
@ -21,7 +21,7 @@
|
||||
static const char *TAG = "AF_SCHEME";
|
||||
|
||||
typedef struct {
|
||||
isp_af_ctrlr_t af_ctlr;
|
||||
isp_af_ctlr_t af_ctlr;
|
||||
int first_step_val;
|
||||
int first_approx_cycles;
|
||||
int second_step_val;
|
||||
@ -36,7 +36,7 @@ typedef struct {
|
||||
static esp_err_t s_af_process(void *arg, int *out_definition_thresh, int *out_luminance_thresh);
|
||||
|
||||
/* ------------------------- Public API ------------------------------------- */
|
||||
esp_err_t isp_af_create_sa_scheme(isp_af_ctrlr_t af_ctlr, const isp_af_sa_scheme_config_t *config, isp_af_scheme_handle_t *ret_scheme)
|
||||
esp_err_t isp_af_create_sa_scheme(isp_af_ctlr_t af_ctlr, const isp_af_sa_scheme_config_t *config, isp_af_scheme_handle_t *ret_scheme)
|
||||
{
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
ESP_RETURN_ON_FALSE(af_ctlr && config && ret_scheme, ESP_ERR_INVALID_ARG, TAG, "invalid arg: null pointer");
|
||||
|
@ -6,4 +6,4 @@ dependencies:
|
||||
isp_af_schemes:
|
||||
path: ${IDF_PATH}/examples/peripherals/isp/auto_focus/components/isp_af_schemes
|
||||
dsi_init:
|
||||
path: ${IDF_PATH}/examples/peripherals/camera/components/dsi_init
|
||||
path: ${IDF_PATH}/examples/peripherals/camera/camera_dsi/components/dsi_init
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "esp_cam_sensor.h"
|
||||
#include "ov5647.h"
|
||||
#include "example_dsi_init.h"
|
||||
#include "example_dsi_init_config.h"
|
||||
#include "example_config.h"
|
||||
|
||||
static const char *TAG = "isp_dsi";
|
||||
@ -46,7 +47,7 @@ typedef union {
|
||||
uint16_t val;
|
||||
} dw9714_reg_t;
|
||||
|
||||
static bool IRAM_ATTR s_env_change_cb(isp_af_ctrlr_t af_ctrlr, const esp_isp_af_env_detector_evt_data_t *edata, void *user_data)
|
||||
static bool IRAM_ATTR s_env_change_cb(isp_af_ctlr_t af_ctrlr, const esp_isp_af_env_detector_evt_data_t *edata, void *user_data)
|
||||
{
|
||||
BaseType_t mustYield = pdFALSE;
|
||||
TaskHandle_t task_handle = (TaskHandle_t)user_data;
|
||||
@ -119,7 +120,7 @@ static void af_task(void *arg)
|
||||
.edge_thresh = 128,
|
||||
};
|
||||
|
||||
isp_af_ctrlr_t af_ctrlr = NULL;
|
||||
isp_af_ctlr_t af_ctrlr = NULL;
|
||||
ESP_ERROR_CHECK(esp_isp_new_af_controller(af_task_param.isp_proc, &af_config, &af_ctrlr));
|
||||
|
||||
esp_isp_af_env_config_t env_config = {
|
||||
@ -185,9 +186,9 @@ void app_main(void)
|
||||
example_dsi_resource_alloc(&ili9881c_ctrl_panel, &mipi_dpi_panel, &frame_buffer);
|
||||
|
||||
//---------------Necessary variable config------------------//
|
||||
frame_buffer_size = CONFIG_EXAMPLE_MIPI_CSI_DISP_HRES * EXAMPLE_MIPI_DSI_IMAGE_VSIZE * EXAMPLE_RGB565_BITS_PER_PIXEL / 8;
|
||||
frame_buffer_size = CONFIG_EXAMPLE_MIPI_CSI_DISP_HRES * CONFIG_EXAMPLE_MIPI_DSI_DISP_VRES * EXAMPLE_RGB565_BITS_PER_PIXEL / 8;
|
||||
|
||||
ESP_LOGD(TAG, "CONFIG_EXAMPLE_MIPI_CSI_DISP_HRES: %d, EXAMPLE_MIPI_DSI_IMAGE_VSIZE: %d, bits per pixel: %d", CONFIG_EXAMPLE_MIPI_CSI_DISP_HRES, EXAMPLE_MIPI_DSI_IMAGE_VSIZE, 8);
|
||||
ESP_LOGD(TAG, "CONFIG_EXAMPLE_MIPI_CSI_DISP_HRES: %d, CONFIG_EXAMPLE_MIPI_DSI_DISP_VRES: %d, bits per pixel: %d", CONFIG_EXAMPLE_MIPI_CSI_DISP_HRES, CONFIG_EXAMPLE_MIPI_DSI_DISP_VRES, 8);
|
||||
ESP_LOGD(TAG, "frame_buffer_size: %zu", frame_buffer_size);
|
||||
ESP_LOGD(TAG, "frame_buffer: %p", frame_buffer);
|
||||
|
||||
@ -226,8 +227,8 @@ void app_main(void)
|
||||
.h_res = CONFIG_EXAMPLE_MIPI_CSI_DISP_HRES,
|
||||
.v_res = CONFIG_EXAMPLE_MIPI_CSI_DISP_VRES,
|
||||
.lane_bit_rate_mbps = EXAMPLE_MIPI_CSI_LANE_BITRATE_MBPS,
|
||||
.input_data_color_type = MIPI_CSI_COLOR_RAW8,
|
||||
.output_data_color_type = MIPI_CSI_COLOR_RGB565,
|
||||
.input_data_color_type = CAM_CTLR_COLOR_RAW8,
|
||||
.output_data_color_type = CAM_CTLR_COLOR_RGB565,
|
||||
.data_lane_num = 2,
|
||||
.byte_swap_en = false,
|
||||
.queue_items = 1,
|
||||
|
Loading…
Reference in New Issue
Block a user