feat(isp): added isp dvp driver

This commit is contained in:
Armando 2024-05-15 18:53:04 +08:00
parent 7425154472
commit 70d2ed5ee8
45 changed files with 1172 additions and 123 deletions

View File

@ -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}
)

View File

@ -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

View File

@ -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

View File

@ -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");
}

View 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;
}

View 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

View File

@ -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
*/

View File

@ -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

View 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;
}

View File

@ -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,

View File

@ -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

View File

@ -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}
)

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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);

View File

@ -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";

View File

@ -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;

View File

@ -8,6 +8,7 @@ endif()
set(priv_requires
unity
esp_driver_isp
esp_psram
)
idf_component_register(SRCS ${srcs}

View File

@ -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]));
}

View File

@ -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

View File

@ -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
---------------------------------------------------------------*/

View 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

View File

@ -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
---------------------------------------------------------------*/

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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
},
},
}
};

View File

@ -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;

View File

@ -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

View File

@ -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));

View File

@ -1,4 +1,4 @@
idf_component_register(SRCS "example_dsi_init.c"
INCLUDE_DIRS "."
INCLUDE_DIRS "include"
REQUIRES esp_lcd
)

View File

@ -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

View File

@ -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,

View File

@ -1,4 +1,4 @@
dependencies:
espressif/esp_lcd_ili9881c: "^0.2.0"
esp_lcd_ili9881c: ">=0.1.0"
idf:
version: ">=5.3.0"

View File

@ -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
*

View File

@ -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

View File

@ -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
)

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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");

View File

@ -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

View File

@ -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,