feat(isp_ae): support isp auto exposure

This commit is contained in:
gaoxu
2024-07-08 09:57:08 +08:00
parent dcb34c5ffa
commit 3c0fe579b6
16 changed files with 837 additions and 63 deletions

View File

@@ -12,7 +12,8 @@ if(CONFIG_SOC_ISP_SUPPORTED)
list(APPEND srcs "src/isp_core.c"
"src/isp_af.c"
"src/isp_ccm.c"
"src/isp_awb.c")
"src/isp_awb.c"
"src/isp_ae.c")
endif()
if(CONFIG_SOC_ISP_BF_SUPPORTED)

View File

@@ -16,3 +16,4 @@
#include "driver/isp_awb.h"
#include "driver/isp_bf.h"
#include "driver/isp_ccm.h"
#include "driver/isp_ae.h"

View File

@@ -0,0 +1,221 @@
/*
* 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"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief AE controller config
*/
typedef struct {
isp_ae_sample_point_t sample_point; ///< The input data source, ISP_AE_SAMPLE_POINT_AFTER_DEMOSAIC: AE input data after demosaic, ISP_AE_SAMPLE_POINT_AFTER_GAMMA: AE input data after gamma
isp_window_t window; ///< The sampling windows of AE
int intr_priority; ///< The interrupt priority, range 0~7, if set to 0, the driver will try to allocate an interrupt with a relative low priority (1,2,3) otherwise the larger the higher, 7 is NMI
} esp_isp_ae_config_t;
/**
* @brief New an ISP AE controller
*
* @param[in] isp_proc ISP Processor handle
* @param[in] ae_config Pointer to AE config. Refer to ``esp_isp_ae_config_t``.
* @param[out] ret_hdl AE controller handle
*
* @return
* - ESP_OK On success
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid
* - ESP_ERR_INVALID_STATE Invalid state
* - 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_ae_controller(isp_proc_handle_t isp_proc, const esp_isp_ae_config_t *ae_config, isp_ae_ctlr_t *ret_hdl);
/**
* @brief Delete an ISP AE controller
*
* @param[in] ae_ctlr AE controller handle
*
* @return
* - ESP_OK On success
* - 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_ae_controller(isp_ae_ctlr_t ae_ctlr);
/**
* @brief Enable an ISP AE controller
*
* @param[in] ae_ctlr AE controller handle
*
* @return
* - ESP_OK On success
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
* - ESP_ERR_INVALID_STATE Driver state is invalid.
*/
esp_err_t esp_isp_ae_controller_enable(isp_ae_ctlr_t ae_ctlr);
/**
* @brief Disable an ISP AE controller
*
* @param[in] ae_ctlr AE controller handle
*
* @return
* - ESP_OK On success
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
* - ESP_ERR_INVALID_STATE Driver state is invalid.
*/
esp_err_t esp_isp_ae_controller_disable(isp_ae_ctlr_t ae_ctlr);
/**
* @brief Trigger AE luminance statistics for one time and get the result
*
* @param[in] ae_ctlr AE controller handle
* @param[in] timeout_ms Timeout in millisecond
* - timeout_ms < 0: Won't return until finished
* - timeout_ms = 0: No timeout, trigger one time statistics and return immediately,
* in this case, the result won't be assigned in this function,
* but you can get the result in the callback `esp_isp_ae_env_detector_evt_cbs_t::on_env_statistics_done`
* - timeout_ms > 0: Wait for specified milliseconds, if not finished, then return timeout error
* @param[out] out_res AE luminance statistics result, can be NULL if `timeout_ms = 0`
*
* @return
* - ESP_OK On success
* - ESP_ERR_TIMEOUT If the waiting time exceeds the specified timeout.
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
* - ESP_ERR_INVALID_STATE Driver state is invalid.
*/
esp_err_t esp_isp_ae_controller_get_oneshot_statistics(isp_ae_ctlr_t ae_ctlr, int timeout_ms, isp_ae_result_t *out_res);
/**
* @brief Start AE continuous statistics of the luminance in the windows
* @note This function is an asynchronous and non-block function,
* it will start the continuous statistics and return immediately.
* You have to register the AE callback and get the result from the callback event data.
* When you call `esp_isp_ae_controller_get_oneshot_statistics` during continuous mode,
* continuous will be invalid, you need to restart continuous mode again.
* @param[in] ae_ctlr AE controller handle
* @return
* - ESP_OK On success
* - ESP_ERR_INVALID_ARG Null pointer
* - ESP_ERR_INVALID_STATE Driver state is invalid.
*/
esp_err_t esp_isp_ae_controller_start_continuous_statistics(isp_ae_ctlr_t ae_ctlr);
/**
* @brief Stop AE continuous statistics of the luminance in the windows
*
* @param[in] ae_ctlr AE controller handle
* @return
* - ESP_OK On success
* - ESP_ERR_INVALID_ARG Null pointer
* - ESP_ERR_INVALID_STATE Driver state is invalid.
*/
esp_err_t esp_isp_ae_controller_stop_continuous_statistics(isp_ae_ctlr_t ae_ctlr);
/*---------------------------------------------
AE env detector
----------------------------------------------*/
/**
* @brief AE environment detector config
*/
typedef struct {
int interval; /*!< Interval between environment detection, in frames.
* i.e., AE controller will trigger the statistic periodically to detect the environment change.
*/
} esp_isp_ae_env_config_t;
/**
* @brief AE environment detector config
*/
typedef struct {
int low_thresh; /*!< Low threshold for AE environment detector luminance */
int high_thresh; /*!< High threshold for AE environment detector luminance */
} esp_isp_ae_env_thresh_t;
/**
* @brief Set ISP AE environment detector
*
* @param[in] ae_ctlr AE controller handle
* @param[in] env_config AE Env detector configuration
*
* @return
* - ESP_OK On success
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
* - ESP_ERR_INVALID_STATE Driver state is invalid.
*/
esp_err_t esp_isp_ae_controller_set_env_detector(isp_ae_ctlr_t ae_ctlr, const esp_isp_ae_env_config_t *env_config);
/**
* @brief Set ISP AE environment detector detecting threshold
*
* @param[in] ae_ctlr AE controller handle
* @param[in] env_thresh Luminance thresholds for AE env detector
*
* @return
* - ESP_OK On success
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
* - ESP_ERR_INVALID_STATE Driver state is invalid.
*/
esp_err_t esp_isp_ae_controller_set_env_detector_threshold(isp_ae_ctlr_t ae_ctlr, const esp_isp_ae_env_thresh_t *env_thresh);
/**
* @brief Event data structure
*/
typedef struct {
isp_ae_result_t ae_result; /*!< The AE statistics result */
} esp_isp_ae_env_detector_evt_data_t;
/**
* @brief Prototype of ISP AE Env detector event callback
*
* @param[in] ae_ctlr ISP AE controller handle
* @param[in] edata ISP AE Env detector event data
* @param[in] user_data User registered context, registered when in `esp_isp_ae_env_detector_register_event_callbacks()`
*
* @return Whether a high priority task is woken up by this function
*/
typedef bool (*esp_isp_ae_env_detector_callback_t)(isp_ae_ctlr_t ae_ctlr, const esp_isp_ae_env_detector_evt_data_t *edata, void *user_data);
/**
* @brief Group of ISP AE env_detector
* @note These callbacks are all running in an ISR environment.
* @note When CONFIG_ISP_ISR_IRAM_SAEE is enabled, the callback itself and functions called by it should be placed in IRAM.
* Involved variables should be in internal RAM as well.
*/
typedef struct {
esp_isp_ae_env_detector_callback_t on_env_statistics_done; ///< Event callback, invoked when environment sample done.
esp_isp_ae_env_detector_callback_t on_env_change; ///< Event callback, invoked when environment change happens.
} esp_isp_ae_env_detector_evt_cbs_t;
/**
* @brief Register AE Env detector event callbacks
*
* @note User can deregister a previously registered callback by calling this function and setting the to-be-deregistered callback member in
* the `cbs` structure to NULL.
* @note When CONFIG_ISP_ISR_IRAM_SAEE is enabled, the callback itself and functions called by it should be placed in IRAM.
* Involved variables (including `user_data`) should be in internal RAM as well.
*
* @param[in] ae_ctlr AE controller handle
* @param[in] cbs Group of callback functions
* @param[in] user_data User data, which will be delivered to the callback functions directly
*
* @return
* - ESP_OK: On success
* - 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_ae_env_detector_register_event_callbacks(isp_ae_ctlr_t ae_ctlr, const esp_isp_ae_env_detector_evt_cbs_t *cbs, void *user_data);
#ifdef __cplusplus
}
#endif

View File

@@ -78,9 +78,6 @@ 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
* @note This function is a synchronous and block function,
* it only returns when AF luminance and definition statistics is done or timeout.
* It's a simple method to get the result directly for one time.
*
* @param[in] af_ctrlr AF controller handle
* @param[in] timeout_ms Timeout in millisecond
@@ -109,6 +106,7 @@ esp_err_t esp_isp_af_controller_get_oneshot_statistics(isp_af_ctlr_t af_ctrlr, i
* @note This function is an asynchronous and non-block function,
* it will start the continuous statistics and return immediately.
* You have to register the AF callback and get the result from the callback event data.
* @note When continuous mode start, AF environment detector will be invalid
*
* @param[in] af_ctrlr AF controller handle
* @return
@@ -130,7 +128,7 @@ esp_err_t esp_isp_af_controller_start_continuous_statistics(isp_af_ctlr_t af_ctr
esp_err_t esp_isp_af_controller_stop_continuous_statistics(isp_af_ctlr_t af_ctrlr);
/*---------------------------------------------
AF Env Monitor
AF Env Detector
----------------------------------------------*/
/**
* @brief AF environment detector config
@@ -147,6 +145,7 @@ typedef struct {
* @param[in] af_ctrlr AF controller handle
* @param[in] env_config AF Env detector configuration
*
* @note When continuous mode start, AF environment detector will be invalid
* @return
* - ESP_OK On success
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.

View File

@@ -121,9 +121,6 @@ esp_err_t esp_isp_awb_controller_disable(isp_awb_ctlr_t awb_ctlr);
/**
* @brief Trigger AWB white patch statistics for one time and get the result
* @note This function is a synchronous and block function,
* it only returns when AWB white patch statistics is done or timeout.
* It's a simple method to get the result directly for one time.
*
* @param[in] awb_ctlr AWB controller handle
* @param[in] timeout_ms Timeout in millisecond

View File

@@ -48,6 +48,13 @@ typedef struct {
uint32_t sum_b; ///< The sum of B channel of these white patches
} isp_awb_stat_result_t;
/**
* @brief ISP AE result
*/
typedef struct {
int luminance[ISP_AE_BLOCK_X_NUM][ISP_AE_BLOCK_Y_NUM]; ///< Luminance, it refers how luminant an image is
} isp_ae_result_t;
/**
* @brief Type of ISP processor handle
*/
@@ -63,6 +70,11 @@ typedef struct isp_af_controller_t *isp_af_ctlr_t;
*/
typedef struct isp_awb_controller_t *isp_awb_ctlr_t;
/**
* @brief Type of ISP AE controller handle
*/
typedef struct isp_ae_controller_t *isp_ae_ctlr_t;
#ifdef __cplusplus
}
#endif

View File

@@ -66,6 +66,7 @@ typedef struct isp_processor_t {
isp_af_ctlr_t af_ctlr[SOC_ISP_AF_CTLR_NUMS];
isp_awb_ctlr_t awb_ctlr;
isp_fsm_t bf_fsm;
isp_ae_ctlr_t ae_ctlr;
} isp_processor_t;
#endif

View File

@@ -0,0 +1,350 @@
/*
* SPDX-FileCopyrightText: 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 "driver/isp_ae.h"
#include "esp_private/isp_private.h"
static const char *TAG = "ISP_AE";
typedef struct isp_ae_controller_t {
int id;
isp_fsm_t fsm;
portMUX_TYPE spinlock;
intr_handle_t intr_handle;
int intr_priority;
isp_proc_handle_t isp_proc;
QueueHandle_t evt_que;
SemaphoreHandle_t stat_lock;
int low_thresh;
int high_thresh;
esp_isp_ae_env_detector_evt_cbs_t cbs;
void *user_data;
} isp_ae_controller_t;
extern portMUX_TYPE fsm_spinlock;
static void s_isp_ae_default_isr(void *arg);
/*---------------------------------------------
AE
----------------------------------------------*/
static esp_err_t s_isp_claim_ae_controller(isp_proc_handle_t isp_proc, isp_ae_ctlr_t ae_ctlr)
{
assert(isp_proc && ae_ctlr);
esp_err_t ret = ESP_ERR_NOT_FOUND;
portENTER_CRITICAL(&isp_proc->spinlock);
if (!isp_proc->ae_ctlr) {
isp_proc->ae_ctlr = ae_ctlr;
ret = ESP_OK;
}
portEXIT_CRITICAL(&isp_proc->spinlock);
return ret;
}
static void s_isp_declaim_ae_controller(isp_ae_ctlr_t ae_ctlr)
{
if (ae_ctlr && ae_ctlr->isp_proc) {
portENTER_CRITICAL(&ae_ctlr->isp_proc->spinlock);
ae_ctlr->isp_proc->ae_ctlr = NULL;
portEXIT_CRITICAL(&ae_ctlr->isp_proc->spinlock);
}
}
static void s_isp_ae_free_controller(isp_ae_ctlr_t ae_ctlr)
{
if (ae_ctlr) {
if (ae_ctlr->intr_handle) {
esp_intr_free(ae_ctlr->intr_handle);
}
if (ae_ctlr->evt_que) {
vQueueDelete(ae_ctlr->evt_que);
}
if (ae_ctlr->stat_lock) {
vSemaphoreDelete(ae_ctlr->stat_lock);
}
free(ae_ctlr);
}
}
esp_err_t esp_isp_new_ae_controller(isp_proc_handle_t isp_proc, const esp_isp_ae_config_t *ae_config, isp_ae_ctlr_t *ret_hdl)
{
esp_err_t ret = ESP_FAIL;
ESP_RETURN_ON_FALSE(isp_proc && ae_config && ret_hdl, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
ESP_RETURN_ON_FALSE(((ae_config->window.top_left.x < ISP_LL_AE_WINDOW_MAX_RANGE) &&
(ae_config->window.btm_right.x >= ae_config->window.top_left.x) &&
(ae_config->window.btm_right.x < ISP_LL_AE_WINDOW_MAX_RANGE) &&
(ae_config->window.top_left.y < ISP_LL_AE_WINDOW_MAX_RANGE) &&
(ae_config->window.btm_right.y >= ae_config->window.top_left.y) &&
(ae_config->window.btm_right.y < ISP_LL_AE_WINDOW_MAX_RANGE)), ESP_ERR_INVALID_ARG, TAG, "invalid window");
isp_ae_ctlr_t ae_ctlr = heap_caps_calloc(1, sizeof(isp_ae_controller_t), ISP_MEM_ALLOC_CAPS);
ESP_RETURN_ON_FALSE(ae_ctlr, ESP_ERR_NO_MEM, TAG, "no mem");
ae_ctlr->evt_que = xQueueCreateWithCaps(1, sizeof(isp_ae_result_t), ISP_MEM_ALLOC_CAPS);
ESP_GOTO_ON_FALSE(ae_ctlr->evt_que, ESP_ERR_NO_MEM, err1, TAG, "no mem for ae event queue");
ae_ctlr->stat_lock = xSemaphoreCreateBinaryWithCaps(ISP_MEM_ALLOC_CAPS);
ESP_GOTO_ON_FALSE(ae_ctlr->stat_lock, ESP_ERR_NO_MEM, err1, TAG, "no mem for ae semaphore");
ae_ctlr->fsm = ISP_FSM_INIT;
ae_ctlr->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
ae_ctlr->isp_proc = isp_proc;
//claim an AE controller
ESP_GOTO_ON_ERROR(s_isp_claim_ae_controller(isp_proc, ae_ctlr), err1, TAG, "no available controller");
// Register the AE ISR
uint32_t intr_st_reg_addr = isp_ll_get_intr_status_reg_addr(isp_proc->hal.hw);
int intr_priority = ae_config->intr_priority > 0 && ae_config->intr_priority <= 7 ? BIT(ae_config->intr_priority) : ESP_INTR_FLAG_LOWMED;
ESP_GOTO_ON_ERROR(esp_intr_alloc_intrstatus(isp_hw_info.instances[isp_proc->proc_id].irq, ISP_INTR_ALLOC_FLAGS | intr_priority, intr_st_reg_addr, ISP_LL_EVENT_AE_MASK,
s_isp_ae_default_isr, ae_ctlr, &ae_ctlr->intr_handle), err2, TAG, "allocate interrupt failed");
isp_ll_ae_set_sample_point(isp_proc->hal.hw, ae_config->sample_point);
isp_ll_ae_enable(isp_proc->hal.hw, false);
isp_hal_ae_window_config(&isp_proc->hal, &ae_config->window);
isp_ll_clear_intr(isp_proc->hal.hw, ISP_LL_EVENT_AE_MASK);
*ret_hdl = ae_ctlr;
return ESP_OK;
err2:
s_isp_declaim_ae_controller(ae_ctlr);
err1:
s_isp_ae_free_controller(ae_ctlr);
return ret;
}
esp_err_t esp_isp_del_ae_controller(isp_ae_ctlr_t ae_ctlr)
{
ESP_RETURN_ON_FALSE(ae_ctlr && ae_ctlr->isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
ESP_RETURN_ON_FALSE(ae_ctlr->isp_proc->ae_ctlr == ae_ctlr, ESP_ERR_INVALID_ARG, TAG, "controller isn't in use");
ESP_RETURN_ON_FALSE(ae_ctlr->fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "controller isn't in init state");
s_isp_declaim_ae_controller(ae_ctlr);
s_isp_ae_free_controller(ae_ctlr);
return ESP_OK;
}
esp_err_t esp_isp_ae_controller_enable(isp_ae_ctlr_t ae_ctlr)
{
ESP_RETURN_ON_FALSE(ae_ctlr && ae_ctlr->isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
ESP_RETURN_ON_FALSE(ae_ctlr->fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "controller isn't in init state");
esp_err_t ret = ESP_OK;
ESP_GOTO_ON_ERROR(esp_intr_enable(ae_ctlr->intr_handle), err, TAG, "failed to enable the AE interrupt");
isp_ll_ae_clk_enable(ae_ctlr->isp_proc->hal.hw, true);
isp_ll_enable_intr(ae_ctlr->isp_proc->hal.hw, ISP_LL_EVENT_AE_MASK, true);
isp_ll_ae_enable(ae_ctlr->isp_proc->hal.hw, true);
xSemaphoreGive(ae_ctlr->stat_lock);
return ret;
err:
ae_ctlr->fsm = ISP_FSM_INIT;
return ret;
}
esp_err_t esp_isp_ae_controller_disable(isp_ae_ctlr_t ae_ctlr)
{
ESP_RETURN_ON_FALSE(ae_ctlr && ae_ctlr->isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
ESP_RETURN_ON_FALSE(ae_ctlr->fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "controller isn't in enable state");
xSemaphoreTake(ae_ctlr->stat_lock, 0);
ae_ctlr->fsm = ISP_FSM_INIT;
isp_ll_ae_clk_enable(ae_ctlr->isp_proc->hal.hw, false);
isp_ll_enable_intr(ae_ctlr->isp_proc->hal.hw, ISP_LL_EVENT_AE_MASK, false);
isp_ll_ae_enable(ae_ctlr->isp_proc->hal.hw, false);
esp_intr_disable(ae_ctlr->intr_handle);
return ESP_OK;
}
esp_err_t esp_isp_ae_controller_get_oneshot_statistics(isp_ae_ctlr_t ae_ctlr, int timeout_ms, isp_ae_result_t *out_res)
{
ESP_RETURN_ON_FALSE_ISR(ae_ctlr && (out_res || timeout_ms == 0), ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
esp_err_t ret = ESP_OK;
TickType_t ticks = timeout_ms < 0 ? portMAX_DELAY : pdMS_TO_TICKS(timeout_ms);
xSemaphoreTake(ae_ctlr->stat_lock, ticks);
ESP_GOTO_ON_FALSE(ae_ctlr->fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, err, TAG, "controller isn't in enable state");
// Reset the queue in case receiving the legacy data in the queue
xQueueReset(ae_ctlr->evt_que);
// Disable the env detector when manual statistics.
// Otherwise, the env detector results may overwrite the manual statistics results when the statistics results are not read out in time
isp_ll_ae_env_detector_set_thresh(ae_ctlr->isp_proc->hal.hw, 0, 0);
// Trigger the AE statistics manually
isp_ll_ae_manual_update(ae_ctlr->isp_proc->hal.hw);
// Wait the statistics to finish and receive the result from the queue
if ((ticks > 0) && xQueueReceive(ae_ctlr->evt_que, out_res, ticks) != pdTRUE) {
ret = ESP_ERR_TIMEOUT;
}
// Re-enable the env detector after manual statistics.
isp_ll_ae_env_detector_set_thresh(ae_ctlr->isp_proc->hal.hw, ae_ctlr->low_thresh, ae_ctlr->high_thresh);
portENTER_CRITICAL(&fsm_spinlock);
ae_ctlr->fsm = ISP_FSM_ENABLE;
portEXIT_CRITICAL(&fsm_spinlock);
err:
xSemaphoreGive(ae_ctlr->stat_lock);
return ret;
}
esp_err_t esp_isp_ae_controller_start_continuous_statistics(isp_ae_ctlr_t ae_ctlr)
{
ESP_RETURN_ON_FALSE_ISR(ae_ctlr, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
ESP_RETURN_ON_FALSE_ISR(ae_ctlr->fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "controller isn't in enable state");
esp_err_t ret = ESP_OK;
if (xSemaphoreTake(ae_ctlr->stat_lock, 0) == pdFALSE) {
ESP_LOGW(TAG, "statistics lock is not acquired, controller is busy");
return ESP_ERR_INVALID_STATE;
}
ESP_GOTO_ON_FALSE(ae_ctlr->fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, err, TAG, "controller isn't in enable state");
portENTER_CRITICAL(&fsm_spinlock);
ae_ctlr->fsm = ISP_FSM_START;
portEXIT_CRITICAL(&fsm_spinlock);
isp_ll_ae_manual_update(ae_ctlr->isp_proc->hal.hw);
err:
xSemaphoreGive(ae_ctlr->stat_lock);
return ret;
}
esp_err_t esp_isp_ae_controller_stop_continuous_statistics(isp_ae_ctlr_t ae_ctlr)
{
ESP_RETURN_ON_FALSE_ISR(ae_ctlr, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
ESP_RETURN_ON_FALSE_ISR(ae_ctlr->fsm == ISP_FSM_START, ESP_ERR_INVALID_STATE, TAG, "controller isn't in continuous state");
isp_ll_ae_env_detector_set_thresh(ae_ctlr->isp_proc->hal.hw, ae_ctlr->low_thresh, ae_ctlr->high_thresh);
portENTER_CRITICAL(&fsm_spinlock);
ae_ctlr->fsm = ISP_FSM_ENABLE;
portEXIT_CRITICAL(&fsm_spinlock);
xSemaphoreGive(ae_ctlr->stat_lock);
return ESP_OK;
}
/*---------------------------------------------
AE Env Detector
----------------------------------------------*/
esp_err_t esp_isp_ae_controller_set_env_detector(isp_ae_ctlr_t ae_ctlr, const esp_isp_ae_env_config_t *env_config)
{
ESP_RETURN_ON_FALSE(ae_ctlr && env_config, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
ESP_RETURN_ON_FALSE(ae_ctlr->fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "invalid fsm, should be called when in init state");
ESP_RETURN_ON_FALSE(env_config->interval > 0, ESP_ERR_INVALID_STATE, TAG, "invalid interval, should be greater than 0");
isp_ll_clear_intr(ae_ctlr->isp_proc->hal.hw, ISP_LL_EVENT_AE_ENV);
isp_ll_ae_env_detector_set_period(ae_ctlr->isp_proc->hal.hw, env_config->interval);
isp_ll_enable_intr(ae_ctlr->isp_proc->hal.hw, ISP_LL_EVENT_AE_ENV, true);
return ESP_OK;
}
esp_err_t esp_isp_ae_env_detector_register_event_callbacks(isp_ae_ctlr_t ae_ctlr, const esp_isp_ae_env_detector_evt_cbs_t *cbs, void *user_data)
{
ESP_RETURN_ON_FALSE(ae_ctlr && cbs, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
ESP_RETURN_ON_FALSE(ae_ctlr->fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "detector isn't in the init state");
#if CONFIG_ISP_ISR_IRAM_SAEE
if (cbs->on_env_statistics_done) {
ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_env_statistics_done), ESP_ERR_INVALID_ARG, TAG, "on_env_statistics_done callback not in IRAM");
}
if (cbs->on_env_change) {
ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_env_change), ESP_ERR_INVALID_ARG, TAG, "on_env_change callback not in IRAM");
}
if (user_data) {
ESP_RETURN_ON_FALSE(esp_ptr_internal(user_data), ESP_ERR_INVALID_ARG, TAG, "user context not in internal RAM");
}
#endif
ae_ctlr->cbs.on_env_statistics_done = cbs->on_env_statistics_done;
ae_ctlr->cbs.on_env_change = cbs->on_env_change;
ae_ctlr->user_data = user_data;
return ESP_OK;
}
esp_err_t esp_isp_ae_controller_set_env_detector_threshold(isp_ae_ctlr_t ae_ctlr, const esp_isp_ae_env_thresh_t *env_thresh)
{
ESP_RETURN_ON_FALSE_ISR(ae_ctlr, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
ESP_RETURN_ON_FALSE_ISR(ae_ctlr->fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "AE env detector isn't in enable state");
ESP_RETURN_ON_FALSE_ISR((env_thresh->low_thresh != 0 && env_thresh->high_thresh != 0) && (env_thresh->low_thresh <= env_thresh->high_thresh), ESP_ERR_INVALID_STATE, TAG, "invalid AE env detector thresh");
ae_ctlr->low_thresh = env_thresh->low_thresh;
ae_ctlr->high_thresh = env_thresh->high_thresh;
isp_ll_ae_env_detector_set_thresh(ae_ctlr->isp_proc->hal.hw, ae_ctlr->low_thresh, ae_ctlr->high_thresh);
return ESP_OK;
}
/*---------------------------------------------------------------
INTR
---------------------------------------------------------------*/
static void IRAM_ATTR s_isp_ae_default_isr(void *arg)
{
isp_ae_ctlr_t ae_ctlr = (isp_ae_ctlr_t)arg;
isp_proc_handle_t proc = ae_ctlr->isp_proc;
uint32_t ae_events = isp_hal_check_clear_intr_event(&proc->hal, ISP_LL_EVENT_AE_MASK);
bool need_yield = false;
esp_isp_ae_env_detector_evt_data_t edata = {};
if (ae_events) {
// Get the statistics result
int block_id = 0;
for (int i = 0; i < SOC_ISP_AE_BLOCK_X_NUMS; i++) {
for (int j = 0; j < SOC_ISP_AE_BLOCK_Y_NUMS; j++) {
edata.ae_result.luminance[i][j] = isp_ll_ae_get_block_mean_lum(proc->hal.hw, block_id);
block_id++;
}
}
BaseType_t high_task_awake = false;
// Send the event data to the queue, overwrite the legacy one if exist
xQueueOverwriteFromISR(ae_ctlr->evt_que, &edata.ae_result, &high_task_awake);
// Invoke the callback if the callback is registered
need_yield |= high_task_awake == pdTRUE;
/* If started continuous sampling, then trigger the next AE sample */
if (ae_ctlr->fsm == ISP_FSM_START) {
isp_ll_ae_manual_update(ae_ctlr->isp_proc->hal.hw);
}
}
/**
* Deal with the interrupts.
* Now only one detector.
* Should decide a detector instance according to the hw event.
*/
if (ae_events & ISP_LL_EVENT_AE_FDONE) {
if (ae_ctlr->cbs.on_env_statistics_done) {
need_yield |= ae_ctlr->cbs.on_env_statistics_done(ae_ctlr, &edata, ae_ctlr->user_data);
}
}
if (ae_events & ISP_LL_EVENT_AE_ENV) {
if (ae_ctlr->cbs.on_env_change) {
need_yield |= ae_ctlr->cbs.on_env_change(ae_ctlr, &edata, ae_ctlr->user_data);
}
}
if (need_yield) {
portYIELD_FROM_ISR();
}
}

View File

@@ -126,7 +126,7 @@ esp_err_t esp_isp_new_af_controller(isp_proc_handle_t isp_proc, const esp_isp_af
isp_hal_af_window_config(&isp_proc->hal, i, &af_config->window[i]);
}
isp_ll_af_set_edge_thresh_mode(isp_proc->hal.hw, ISP_LL_AF_EDGE_MONITOR_MODE_MANUAL);
isp_ll_af_set_edge_thresh_mode(isp_proc->hal.hw, ISP_LL_AF_EDGE_DETECTOR_MODE_MANUAL);
isp_ll_af_set_edge_thresh(isp_proc->hal.hw, af_config->edge_thresh);
isp_ll_clear_intr(isp_proc->hal.hw, ISP_LL_EVENT_AF_MASK);
@@ -229,7 +229,7 @@ esp_err_t esp_isp_af_controller_stop_continuous_statistics(isp_af_ctlr_t af_ctrl
}
/*---------------------------------------------
AF Env Monitor
AF Env Detector
----------------------------------------------*/
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)
{
@@ -238,11 +238,11 @@ esp_err_t esp_isp_af_controller_set_env_detector(isp_af_ctlr_t af_ctrlr, const e
af_ctrlr->config.interval = env_config->interval;
isp_ll_af_env_monitor_set_period(af_ctrlr->isp_proc->hal.hw, 0);
isp_ll_af_env_detector_set_period(af_ctrlr->isp_proc->hal.hw, 0);
isp_ll_clear_intr(af_ctrlr->isp_proc->hal.hw, ISP_LL_EVENT_AF_ENV);
isp_ll_af_env_monitor_set_mode(af_ctrlr->isp_proc->hal.hw, ISP_LL_AF_ENV_MONITOR_MODE_ABS);
isp_ll_af_env_monitor_set_period(af_ctrlr->isp_proc->hal.hw, af_ctrlr->config.interval);
isp_ll_af_env_detector_set_mode(af_ctrlr->isp_proc->hal.hw, ISP_LL_AF_ENV_DETECTOR_MODE_ABS);
isp_ll_af_env_detector_set_period(af_ctrlr->isp_proc->hal.hw, af_ctrlr->config.interval);
isp_ll_enable_intr(af_ctrlr->isp_proc->hal.hw, ISP_LL_EVENT_AF_ENV, true);
return ESP_OK;
@@ -276,7 +276,7 @@ esp_err_t esp_isp_af_controller_set_env_detector_threshold(isp_af_ctlr_t af_ctrl
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");
isp_ll_af_env_monitor_set_thresh(af_ctrlr->isp_proc->hal.hw, definition_thresh, luminance_thresh);
isp_ll_af_env_detector_set_thresh(af_ctrlr->isp_proc->hal.hw, definition_thresh, luminance_thresh);
return ESP_OK;
}

View File

@@ -41,8 +41,8 @@ extern "C" {
#define ISP_LL_EVENT_MIPI_HNUM_UNMATCH (1<<5)
#define ISP_LL_EVENT_DPC_CHECK_DONE (1<<6)
#define ISP_LL_EVENT_GAMMA_XCOORD_ERR (1<<7)
#define ISP_LL_EVENT_AE_MONITOR (1<<8)
#define ISP_LL_EVENT_AE_FRAME_DONE (1<<9)
#define ISP_LL_EVENT_AE_ENV (1<<8)
#define ISP_LL_EVENT_AE_FDONE (1<<9)
#define ISP_LL_EVENT_AF_FDONE (1<<10)
#define ISP_LL_EVENT_AF_ENV (1<<11)
#define ISP_LL_EVENT_AWB_FDONE (1<<12)
@@ -65,6 +65,7 @@ extern "C" {
#define ISP_LL_EVENT_ALL_MASK (0x1FFFFFFF)
#define ISP_LL_EVENT_AF_MASK (ISP_LL_EVENT_AF_FDONE | ISP_LL_EVENT_AF_ENV)
#define ISP_LL_EVENT_AE_MASK (ISP_LL_EVENT_AE_FDONE | ISP_LL_EVENT_AE_ENV)
#define ISP_LL_EVENT_AWB_MASK (ISP_LL_EVENT_AWB_FDONE)
/*---------------------------------------------------------------
@@ -72,6 +73,11 @@ extern "C" {
---------------------------------------------------------------*/
#define ISP_LL_AF_WINDOW_MAX_RANGE ((1<<12) - 1)
/*---------------------------------------------------------------
AE
---------------------------------------------------------------*/
#define ISP_LL_AE_WINDOW_MAX_RANGE ((1<<12) - 1)
/*---------------------------------------------------------------
BF
---------------------------------------------------------------*/
@@ -117,20 +123,20 @@ typedef union {
} isp_ll_ccm_gain_t;
/**
* @brief Env monitor mode
* @brief Env detector mode
*/
typedef enum {
ISP_LL_AF_ENV_MONITOR_MODE_ABS, ///< Use absolute val for threshold
ISP_LL_AF_ENV_MONITOR_MODE_RATIO, ///< Use ratio val for threshold
} isp_ll_af_env_monitor_mode_t;
ISP_LL_AF_ENV_DETECTOR_MODE_ABS, ///< Use absolute val for threshold
ISP_LL_AF_ENV_DETECTOR_MODE_RATIO, ///< Use ratio val for threshold
} isp_ll_af_env_detector_mode_t;
/**
* @brief Edge monitor mode
* @brief Edge detector mode
*/
typedef enum {
ISP_LL_AF_EDGE_MONITOR_MODE_AUTO, ///< Auto set threshold
ISP_LL_AF_EDGE_MONITOR_MODE_MANUAL, ///< Manual set threshold
} isp_ll_af_edge_monitor_mode_t;
ISP_LL_AF_EDGE_DETECTOR_MODE_AUTO, ///< Auto set threshold
ISP_LL_AF_EDGE_DETECTOR_MODE_MANUAL, ///< Manual set threshold
} isp_ll_af_edge_detector_mode_t;
/*---------------------------------------------------------------
@@ -496,11 +502,11 @@ static inline void isp_ll_af_manual_update(isp_dev_t *hw)
* @brief Set edge thresh mode
*
* @param[in] hw Hardware instance address
* @param[in] mode See `isp_ll_af_edge_monitor_mode_t`
* @param[in] mode See `isp_ll_af_edge_detector_mode_t`
*/
static inline void isp_ll_af_set_edge_thresh_mode(isp_dev_t *hw, isp_ll_af_edge_monitor_mode_t mode)
static inline void isp_ll_af_set_edge_thresh_mode(isp_dev_t *hw, isp_ll_af_edge_detector_mode_t mode)
{
if (mode == ISP_LL_AF_EDGE_MONITOR_MODE_AUTO) {
if (mode == ISP_LL_AF_EDGE_DETECTOR_MODE_AUTO) {
hw->af_threshold.af_threshold = 0;
}
}
@@ -622,43 +628,43 @@ static inline uint32_t isp_ll_af_get_window_lum(isp_dev_t *hw, uint32_t window_i
}
/*---------------------------------------------
AF Env Monitor
AF Env detector
----------------------------------------------*/
/**
* @brief Set env monitor period
* @brief Set env detector period
*
* @param[in] hw Hardware instance address
* @param[in] period period of the env monitor, in frames
* @param[in] period period of the env detector, in frames
*/
static inline void isp_ll_af_env_monitor_set_period(isp_dev_t *hw, uint32_t period)
static inline void isp_ll_af_env_detector_set_period(isp_dev_t *hw, uint32_t period)
{
hw->af_ctrl0.af_env_period = period;
}
/**
* @brief Set env monitor mode
* @brief Set env detector mode
*
* @param[in] hw Hardware instance address
* @param[in] mode See `isp_ll_af_env_monitor_mode_t`
* @param[in] mode See `isp_ll_af_env_detector_mode_t`
*/
static inline void isp_ll_af_env_monitor_set_mode(isp_dev_t *hw, isp_ll_af_env_monitor_mode_t mode)
static inline void isp_ll_af_env_detector_set_mode(isp_dev_t *hw, isp_ll_af_env_detector_mode_t mode)
{
if (mode == ISP_LL_AF_ENV_MONITOR_MODE_RATIO) {
if (mode == ISP_LL_AF_ENV_DETECTOR_MODE_RATIO) {
hw->af_env_user_th_sum.af_env_user_threshold_sum = 0x0;
hw->af_env_user_th_lum.af_env_user_threshold_lum = 0x0;
}
//nothing to do to if using abs mode, it'll be enabled after `isp_ll_af_env_monitor_set_thresh()`
//nothing to do to if using abs mode, it'll be enabled after `isp_ll_af_env_detector_set_thresh()`
}
/**
* @brief Set env monitor threshold
* @brief Set env detector threshold
*
* @param[in] hw Hardware instance address
* @param[in] sum_thresh Threshold for definition
* @param[in] lum_thresh Threshold for luminance
*/
static inline void isp_ll_af_env_monitor_set_thresh(isp_dev_t *hw, uint32_t sum_thresh, uint32_t lum_thresh)
static inline void isp_ll_af_env_detector_set_thresh(isp_dev_t *hw, uint32_t sum_thresh, uint32_t lum_thresh)
{
HAL_ASSERT(sum_thresh != 0 || lum_thresh != 0);
@@ -667,12 +673,12 @@ static inline void isp_ll_af_env_monitor_set_thresh(isp_dev_t *hw, uint32_t sum_
}
/**
* @brief Set env monitor ratio
* @brief Set env detector ratio
*
* @param[in] hw Hardware instance address
* @param[in] ratio_val Threshold for ratio
*/
static inline void isp_ll_af_env_monitor_set_ratio(isp_dev_t *hw, uint32_t ratio_val)
static inline void isp_ll_af_env_detector_set_ratio(isp_dev_t *hw, uint32_t ratio_val)
{
HAL_ASSERT(hw->af_env_user_th_sum.af_env_user_threshold_sum == 0 &&
hw->af_env_user_th_lum.af_env_user_threshold_lum == 0);
@@ -974,6 +980,122 @@ static inline void isp_ll_cam_enable(isp_dev_t *hw, bool enable)
hw->cam_cntl.cam_en = 0;
}
}
/*---------------------------------------------------------------
AE
---------------------------------------------------------------*/
/**
* @brief Enable / Disable AE clock
*
* @param[in] hw Hardware instance address
* @param[in] enable Enable / Disable
*/
static inline void isp_ll_ae_clk_enable(isp_dev_t *hw, bool enable)
{
hw->clk_en.clk_ae_force_on = enable;
}
/**
* @brief Enable / Disable AE
*
* @param[in] hw Hardware instance address
* @param[in] enable Enable / Disable
*/
static inline void isp_ll_ae_enable(isp_dev_t *hw, bool enable)
{
hw->cntl.ae_en = enable;
}
/**
* @brief Manual aupdate AF once
*
* @param[in] hw Hardware instance address
*/
static inline void isp_ll_ae_manual_update(isp_dev_t *hw)
{
hw->ae_ctrl.ae_update = 1;
}
/**
* @brief Select AE input data source
*
* @param[in] hw Hardware instance address
* @param[in] sample_point 0: AE input data after demosaic, 1: AE input data after gamma
*/
static inline void isp_ll_ae_set_sample_point(isp_dev_t *hw, isp_ae_sample_point_t sample_point)
{
hw->ae_ctrl.ae_select = sample_point;
}
/**
* @brief Set AE window range
*
* @param[in] hw Hardware instance address
* @param[in] x_start Top left pixel x axis value
* @param[in] x_bsize Block size on x axis
* @param[in] y_start Top left pixel y axis value
* @param[in] y_bsize Block size on y axis
*/
static inline void isp_ll_ae_set_window_range(isp_dev_t *hw, int x_start, int x_bsize, int y_start, int y_bsize)
{
hw->ae_bx.ae_x_start = x_start;
hw->ae_bx.ae_x_bsize = x_bsize;
hw->ae_by.ae_y_start = y_start;
hw->ae_by.ae_y_bsize = y_bsize;
}
/**
* @brief Get block mean luminance
*
* @param[in] hw Hardware instance address
* @param[in] block_id
*
* @return Mean luminance
*/
static inline int isp_ll_ae_get_block_mean_lum(isp_dev_t *hw, int block_id)
{
HAL_ASSERT(block_id >=0 && block_id < (SOC_ISP_AE_BLOCK_X_NUMS * SOC_ISP_AE_BLOCK_Y_NUMS));
return hw->ae_block_mean[block_id / 4].ae_b_mean[3 - (block_id % 4)];
}
/**
* @brief AE set the pixel number of each subwin, and set the reciprocal of each subwin_pixnum, 20bit fraction
*
* @param[in] hw Hardware instance address
* @param[in] subwin_pixnum Pixel number
*/
static inline void isp_ll_ae_set_subwin_pixnum_recip(isp_dev_t *hw, int subwin_pixnum)
{
hw->ae_winpixnum.ae_subwin_pixnum = subwin_pixnum;
int subwin_recip = (1 << 20) / subwin_pixnum;
hw->ae_win_reciprocal.ae_subwin_recip = subwin_recip;
}
/**
* @brief Set AE env detector threshold
*
* @param[in] hw Hardware instance address
* @param[in] low_thresh Lower lum threshold
* @param[in] high_thresh Higher lum threshold
*/
static inline void isp_ll_ae_env_detector_set_thresh(isp_dev_t *hw, uint32_t low_thresh, uint32_t high_thresh)
{
hw->ae_monitor.ae_monitor_tl = low_thresh;
hw->ae_monitor.ae_monitor_th = high_thresh;
}
/**
* @brief Set AE env detector period
*
* @param[in] hw Hardware instance address
* @param[in] period period of the AE env detector, in frames
*/
static inline void isp_ll_ae_env_detector_set_period(isp_dev_t *hw, uint32_t period)
{
hw->ae_monitor.ae_monitor_period = period;
}
/*---------------------------------------------------------------
INTR
---------------------------------------------------------------*/

View File

@@ -66,6 +66,17 @@ void isp_hal_init(isp_hal_context_t *hal, int isp_id);
*/
void isp_hal_af_window_config(const isp_hal_context_t *hal, int window_id, const isp_window_t *window);
/*---------------------------------------------------------------
AE
---------------------------------------------------------------*/
/**
* @brief Configure AE window
*
* @param[in] hal Context of the HAL layer
* @param[in] window Window info, see `isp_window_t`
*/
void isp_hal_ae_window_config(const isp_hal_context_t *hal, const isp_window_t *window);
/*---------------------------------------------------------------
INTR
---------------------------------------------------------------*/

View File

@@ -122,6 +122,26 @@ typedef enum {
ISP_AWB_SAMPLE_POINT_AFTER_CCM, ///< Sample AWB data after CCM (Color Correction Matrix)
} isp_awb_sample_point_t;
/*---------------------------------------------------------------
AE
---------------------------------------------------------------*/
#if (SOC_ISP_AE_BLOCK_X_NUMS && SOC_ISP_AE_BLOCK_Y_NUMS)
#define ISP_AE_BLOCK_X_NUM SOC_ISP_AE_BLOCK_X_NUMS // The AF window number for sampling
#define ISP_AE_BLOCK_Y_NUM SOC_ISP_AE_BLOCK_Y_NUMS // The AF window number for sampling
#else
#define ISP_AE_BLOCK_X_NUM 0
#define ISP_AE_BLOCK_Y_NUM 0
#endif
/**
* @brief ISP AE input data source
*
*/
typedef enum {
ISP_AE_SAMPLE_POINT_AFTER_DEMOSAIC, ///< AE input data after demosaic
ISP_AE_SAMPLE_POINT_AFTER_GAMMA, ///< AE input data after gamma
} isp_ae_sample_point_t;
#ifdef __cplusplus
}

View File

@@ -57,6 +57,24 @@ void isp_hal_bf_config(isp_hal_context_t *hal, isp_hal_bf_cfg_t *config)
isp_ll_bf_set_template(hal->hw, default_template);
}
}
/*---------------------------------------------------------------
AE
---------------------------------------------------------------*/
void isp_hal_ae_window_config(const isp_hal_context_t *hal, const isp_window_t *window)
{
uint32_t ae_x_start = window->top_left.x;
uint32_t ae_x_bsize = (window->btm_right.x - window-> top_left.x) / SOC_ISP_AE_BLOCK_X_NUMS;
uint32_t ae_y_start = window->top_left.y;
uint32_t ae_y_bsize = (window->btm_right.y - window->top_left.y) / SOC_ISP_AE_BLOCK_Y_NUMS;
isp_ll_ae_set_window_range(hal->hw, ae_x_start, ae_x_bsize, ae_y_start, ae_y_bsize);
int ae_subwin_pixnum = ae_x_bsize * ae_y_bsize;
isp_ll_ae_set_subwin_pixnum_recip(hal->hw, ae_subwin_pixnum);
}
/*---------------------------------------------------------------
INTR, put in iram
---------------------------------------------------------------*/

View File

@@ -827,6 +827,18 @@ config SOC_ISP_AF_WINDOW_NUMS
int
default 3
config SOC_ISP_AE_CTLR_NUMS
int
default 1
config SOC_ISP_AE_BLOCK_X_NUMS
int
default 5
config SOC_ISP_AE_BLOCK_Y_NUMS
int
default 5
config SOC_ISP_SHARE_CSI_BRG
bool
default y

View File

@@ -1,5 +1,5 @@
/**
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -398,35 +398,35 @@ typedef union {
typedef union {
struct {
/** gau_template21 : R/W; bitpos: [3:0]; default: 15;
* this field configures index 21 of gausian template
* this field configures index 21 of gaussian template
*/
uint32_t gau_template21:4;
/** gau_template20 : R/W; bitpos: [7:4]; default: 15;
* this field configures index 20 of gausian template
* this field configures index 20 of gaussian template
*/
uint32_t gau_template20:4;
/** gau_template12 : R/W; bitpos: [11:8]; default: 15;
* this field configures index 12 of gausian template
* this field configures index 12 of gaussian template
*/
uint32_t gau_template12:4;
/** gau_template11 : R/W; bitpos: [15:12]; default: 15;
* this field configures index 11 of gausian template
* this field configures index 11 of gaussian template
*/
uint32_t gau_template11:4;
/** gau_template10 : R/W; bitpos: [19:16]; default: 15;
* this field configures index 10 of gausian template
* this field configures index 10 of gaussian template
*/
uint32_t gau_template10:4;
/** gau_template02 : R/W; bitpos: [23:20]; default: 15;
* this field configures index 02 of gausian template
* this field configures index 02 of gaussian template
*/
uint32_t gau_template02:4;
/** gau_template01 : R/W; bitpos: [27:24]; default: 15;
* this field configures index 01 of gausian template
* this field configures index 01 of gaussian template
*/
uint32_t gau_template01:4;
/** gau_template00 : R/W; bitpos: [31:28]; default: 15;
* this field configures index 00 of gausian template
* this field configures index 00 of gaussian template
*/
uint32_t gau_template00:4;
};
@@ -439,7 +439,7 @@ typedef union {
typedef union {
struct {
/** gau_template22 : R/W; bitpos: [3:0]; default: 15;
* this field configures index 22 of gausian template
* this field configures index 22 of gaussian template
*/
uint32_t gau_template22:4;
uint32_t reserved_4:28;
@@ -1321,7 +1321,7 @@ typedef union {
*/
uint32_t ae_monitor_th:8;
/** ae_monitor_period : R/W; bitpos: [21:16]; default: 0;
* this field cnfigures ae monitor frame period
* this field configures ae monitor frame period
*/
uint32_t ae_monitor_period:6;
uint32_t reserved_22:10;
@@ -1536,7 +1536,7 @@ typedef union {
typedef union {
struct {
/** dma_en : WT; bitpos: [0]; default: 0;
* write 1 to triger dma to get 1 frame
* write 1 to trigger dma to get 1 frame
*/
uint32_t dma_en:1;
/** dma_update_reg : R/W; bitpos: [1]; default: 0;
@@ -1584,7 +1584,7 @@ typedef union {
typedef union {
struct {
/** cam_en : R/W; bitpos: [0]; default: 0;
* write 1 to start recive camera data, write 0 to disable
* write 1 to start receive camera data, write 0 to disable
*/
uint32_t cam_en:1;
/** cam_update_reg : R/W; bitpos: [1]; default: 0;
@@ -1596,7 +1596,7 @@ typedef union {
*/
uint32_t cam_reset:1;
/** cam_clk_inv : R/W; bitpos: [3]; default: 0;
* this bit configures the invertion of cam clk from pad. 0: not invert cam clk, 1:
* this bit configures the inversion of cam clk from pad. 0: not invert cam clk, 1:
* invert cam clk
*/
uint32_t cam_clk_inv:1;
@@ -1880,7 +1880,7 @@ typedef union {
typedef union {
struct {
/** awb_mode : R/W; bitpos: [1:0]; default: 3;
* this field configures awb algo sel. 00: none sellected. 01: sel algo0. 10: sel
* this field configures awb algo sel. 00: none selected. 01: sel algo0. 10: sel
* algo1. 11: sel both algo0 and algo1
*/
uint32_t awb_mode:2;
@@ -2627,6 +2627,19 @@ typedef union {
uint32_t val;
} isp_lut_rdata_reg_t;
/** Type of ae_block_mean register
* ae statistic result
*/
typedef union {
struct {
/** ae_lum : RO; bitpos: [31:0]; default: 0;
* this field represents the result of AE block
*/
uint8_t ae_b_mean[4];
};
uint32_t val;
} isp_ae_block_mean_reg_t;
/** Type of ae_block_mean_0 register
* ae statistic result register 0
*/
@@ -2790,7 +2803,6 @@ typedef union {
};
uint32_t val;
} isp_ae_block_mean_6_reg_t;
/** Type of af_sum_a register
* result of sum of af window a
*/
@@ -3764,13 +3776,7 @@ typedef struct {
volatile isp_ae_by_reg_t ae_by;
volatile isp_ae_winpixnum_reg_t ae_winpixnum;
volatile isp_ae_win_reciprocal_reg_t ae_win_reciprocal;
volatile isp_ae_block_mean_0_reg_t ae_block_mean_0;
volatile isp_ae_block_mean_1_reg_t ae_block_mean_1;
volatile isp_ae_block_mean_2_reg_t ae_block_mean_2;
volatile isp_ae_block_mean_3_reg_t ae_block_mean_3;
volatile isp_ae_block_mean_4_reg_t ae_block_mean_4;
volatile isp_ae_block_mean_5_reg_t ae_block_mean_5;
volatile isp_ae_block_mean_6_reg_t ae_block_mean_6;
volatile isp_ae_block_mean_reg_t ae_block_mean[7];
volatile isp_sharp_ctrl0_reg_t sharp_ctrl0;
volatile isp_sharp_filter0_reg_t sharp_filter0;
volatile isp_sharp_filter1_reg_t sharp_filter1;

View File

@@ -328,6 +328,9 @@
#define SOC_ISP_DVP_CTLR_NUMS 1U
#define SOC_ISP_AF_CTLR_NUMS 1U
#define SOC_ISP_AF_WINDOW_NUMS 3
#define SOC_ISP_AE_CTLR_NUMS 1U
#define SOC_ISP_AE_BLOCK_X_NUMS 5
#define SOC_ISP_AE_BLOCK_Y_NUMS 5
#define SOC_ISP_SHARE_CSI_BRG 1
#define SOC_ISP_BF_TEMPLATE_X_NUMS 3
#define SOC_ISP_BF_TEMPLATE_Y_NUMS 3