Merge branch 'feature/support_isp_ae' into 'master'
feat(isp): Support ISP Auto Exposure (AE) Closes IDF-9592, IDF-10193, and IDF-10580 See merge request espressif/esp-idf!31671
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -16,3 +16,4 @@
|
||||
#include "driver/isp_awb.h"
|
||||
#include "driver/isp_bf.h"
|
||||
#include "driver/isp_ccm.h"
|
||||
#include "driver/isp_ae.h"
|
||||
|
||||
@@ -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~3, if set to 0, the driver will try to allocate an interrupt with a relative low priority (1,2,3)
|
||||
} 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.
|
||||
* @note When using oneshot statistics, the AE Environment Detector will be temporarily disabled
|
||||
* and will automatically recover once the oneshot is complete.
|
||||
* @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
|
||||
@@ -21,7 +21,7 @@ extern "C" {
|
||||
typedef struct {
|
||||
isp_window_t window[ISP_AF_WINDOW_NUM]; ///< The sampling windows of AF
|
||||
int edge_thresh; ///< Edge threshold, definition higher than this value will be counted as a valid pixel for calculating AF result
|
||||
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
|
||||
int intr_priority; ///< The interrupt priority, range 0~3, if set to 0, the driver will try to allocate an interrupt with a relative low priority (1,2,3)
|
||||
} esp_isp_af_config_t;
|
||||
|
||||
/**
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -28,6 +28,7 @@ typedef struct {
|
||||
bool has_line_end_packet; ///< Enable line end packet
|
||||
uint32_t h_res; ///< Input horizontal resolution, i.e. the number of pixels in a line
|
||||
uint32_t v_res; ///< Input vertical resolution, i.e. the number of lines in a frame
|
||||
int intr_priority; ///< The interrupt priority, range 0~3
|
||||
} esp_isp_processor_cfg_t;
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -32,17 +32,20 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#if CONFIG_ISP_ISR_IRAM_SAFE
|
||||
#define ISP_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_IRAM)
|
||||
#define ISP_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_IRAM)
|
||||
#define ISP_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
|
||||
#else
|
||||
#define ISP_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_INTRDISABLED)
|
||||
#define ISP_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_INTRDISABLED)
|
||||
#define ISP_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
ISP_FSM_INIT,
|
||||
ISP_FSM_ENABLE,
|
||||
ISP_FSM_START,
|
||||
ISP_FSM_INIT, // Controller is initialized, but not enabled
|
||||
ISP_FSM_ENABLE, // Controller is enabled, but is not running
|
||||
ISP_FSM_START, // Controller is in running
|
||||
|
||||
ISP_FSM_ONESHOT, // Controller is in oneshot sampling
|
||||
ISP_FSM_CONTINUOUS, // Controller is in continuous sampling
|
||||
} isp_fsm_t;
|
||||
|
||||
#if SOC_ISP_SUPPORTED
|
||||
@@ -66,9 +69,35 @@ 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;
|
||||
/* ISR */
|
||||
intr_handle_t intr_hdl;
|
||||
int intr_priority;
|
||||
int isr_ref_counts;
|
||||
struct {
|
||||
uint32_t af_isr_added: 1;
|
||||
uint32_t ae_isr_added: 1;
|
||||
uint32_t awb_isr_added: 1;
|
||||
} isr_users;
|
||||
|
||||
} isp_processor_t;
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
ISP_SUBMODULE_AF,
|
||||
ISP_SUBMODULE_AE,
|
||||
ISP_SUBMODULE_AWB,
|
||||
} isp_submodule_t;
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
INTR
|
||||
---------------------------------------------------------------*/
|
||||
esp_err_t esp_isp_register_isr(isp_proc_handle_t proc, isp_submodule_t submodule);
|
||||
esp_err_t esp_isp_deregister_isr(isp_proc_handle_t proc, isp_submodule_t submodule);
|
||||
bool esp_isp_af_isr(isp_proc_handle_t proc, uint32_t af_events);
|
||||
bool esp_isp_ae_isr(isp_proc_handle_t proc, uint32_t ae_events);
|
||||
bool esp_isp_awb_isr(isp_proc_handle_t proc, uint32_t awb_events);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,321 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <esp_types.h>
|
||||
#include <sys/lock.h>
|
||||
#include <stdatomic.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;
|
||||
_Atomic 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;
|
||||
int low_thresh;
|
||||
int high_thresh;
|
||||
esp_isp_ae_env_detector_evt_cbs_t cbs;
|
||||
void *user_data;
|
||||
} isp_ae_controller_t;
|
||||
|
||||
/*---------------------------------------------
|
||||
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) {
|
||||
vQueueDeleteWithCaps(ae_ctlr->evt_que);
|
||||
}
|
||||
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");
|
||||
|
||||
atomic_init(&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
|
||||
int intr_priority = (ae_config->intr_priority > 0 && ae_config->intr_priority <= 3) ? BIT(ae_config->intr_priority) : ESP_INTR_FLAG_LOWMED;
|
||||
ESP_GOTO_ON_ERROR(intr_priority != isp_proc->intr_priority, err2, TAG, "intr_priority error");
|
||||
ESP_GOTO_ON_ERROR(esp_isp_register_isr(ae_ctlr->isp_proc, ISP_SUBMODULE_AE), err2, TAG, "fail to register ISR");
|
||||
|
||||
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(atomic_load(&ae_ctlr->fsm) == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "controller not in init state");
|
||||
|
||||
// Deregister the AE ISR
|
||||
ESP_RETURN_ON_FALSE(esp_isp_deregister_isr(ae_ctlr->isp_proc, ISP_SUBMODULE_AE) == ESP_OK, ESP_FAIL, TAG, "fail to deregister ISR");
|
||||
|
||||
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");
|
||||
|
||||
isp_fsm_t expected_fsm = ISP_FSM_INIT;
|
||||
ESP_RETURN_ON_FALSE(atomic_compare_exchange_strong(&ae_ctlr->fsm, &expected_fsm, ISP_FSM_ENABLE),
|
||||
ESP_ERR_INVALID_STATE, TAG, "controller not in init state");
|
||||
|
||||
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);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
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");
|
||||
isp_fsm_t expected_fsm = ISP_FSM_ENABLE;
|
||||
ESP_RETURN_ON_FALSE(atomic_compare_exchange_strong(&ae_ctlr->fsm, &expected_fsm, ISP_FSM_INIT),
|
||||
ESP_ERR_INVALID_STATE, TAG, "controller not in enable state");
|
||||
|
||||
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);
|
||||
|
||||
isp_fsm_t expected_fsm = ISP_FSM_ENABLE;
|
||||
if (atomic_compare_exchange_strong(&ae_ctlr->fsm, &expected_fsm, ISP_FSM_ONESHOT)) {
|
||||
// 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);
|
||||
} else {
|
||||
ESP_RETURN_ON_FALSE_ISR(false, ESP_ERR_INVALID_STATE, TAG, "controller is not enabled yet");
|
||||
}
|
||||
|
||||
atomic_store(&ae_ctlr->fsm, ISP_FSM_ENABLE);
|
||||
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");
|
||||
|
||||
isp_fsm_t expected_fsm = ISP_FSM_ENABLE;
|
||||
if (atomic_compare_exchange_strong(&ae_ctlr->fsm, &expected_fsm, ISP_FSM_CONTINUOUS)) {
|
||||
isp_ll_ae_manual_update(ae_ctlr->isp_proc->hal.hw);
|
||||
} else {
|
||||
ESP_RETURN_ON_FALSE_ISR(false, ESP_ERR_INVALID_STATE, TAG, "controller is not enabled yet");
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
isp_fsm_t expected_fsm = ISP_FSM_CONTINUOUS;
|
||||
ESP_RETURN_ON_FALSE_ISR(atomic_compare_exchange_strong(&ae_ctlr->fsm, &expected_fsm, ISP_FSM_ENABLE),
|
||||
ESP_ERR_INVALID_STATE, TAG, "controller is not running");
|
||||
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(env_config->interval > 0, ESP_ERR_INVALID_STATE, TAG, "invalid interval, should be greater than 0");
|
||||
ESP_RETURN_ON_FALSE(atomic_load(&ae_ctlr->fsm) == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "controller not in init state");
|
||||
|
||||
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(atomic_load(&ae_ctlr->fsm) == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "controller not in 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((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");
|
||||
ESP_RETURN_ON_FALSE(atomic_load(&ae_ctlr->fsm) == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "controller not in enable state");
|
||||
|
||||
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
|
||||
---------------------------------------------------------------*/
|
||||
bool IRAM_ATTR esp_isp_ae_isr(isp_proc_handle_t proc, uint32_t ae_events)
|
||||
{
|
||||
isp_ae_ctlr_t ae_ctlr = proc->ae_ctlr;
|
||||
|
||||
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 (atomic_load(&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);
|
||||
}
|
||||
}
|
||||
return need_yield;
|
||||
}
|
||||
@@ -28,8 +28,6 @@ typedef struct isp_af_controller_t {
|
||||
void *user_data;
|
||||
} isp_af_controller_t;
|
||||
|
||||
static void s_isp_af_default_isr(void *arg);
|
||||
|
||||
/*---------------------------------------------
|
||||
AF
|
||||
----------------------------------------------*/
|
||||
@@ -72,7 +70,7 @@ static void s_isp_af_free_controller(isp_af_ctlr_t af_ctlr)
|
||||
esp_intr_free(af_ctlr->intr_handle);
|
||||
}
|
||||
if (af_ctlr->evt_que) {
|
||||
vQueueDelete(af_ctlr->evt_que);
|
||||
vQueueDeleteWithCaps(af_ctlr->evt_que);
|
||||
}
|
||||
free(af_ctlr);
|
||||
}
|
||||
@@ -114,10 +112,9 @@ esp_err_t esp_isp_new_af_controller(isp_proc_handle_t isp_proc, const esp_isp_af
|
||||
ESP_GOTO_ON_ERROR(s_isp_claim_af_controller(isp_proc, af_ctlr), err1, TAG, "no available controller");
|
||||
|
||||
// Register the AF ISR
|
||||
uint32_t intr_st_reg_addr = isp_ll_get_intr_status_reg_addr(isp_proc->hal.hw);
|
||||
int intr_priority = af_config->intr_priority > 0 && af_config->intr_priority <= 7 ? BIT(af_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_AF_MASK,
|
||||
s_isp_af_default_isr, af_ctlr, &af_ctlr->intr_handle), err2, TAG, "allocate interrupt failed");
|
||||
int intr_priority = (af_config->intr_priority > 0 && af_config->intr_priority <= 3) ? BIT(af_config->intr_priority) : ESP_INTR_FLAG_LOWMED;
|
||||
ESP_GOTO_ON_ERROR(intr_priority != isp_proc->intr_priority, err2, TAG, "intr_priority error");
|
||||
ESP_GOTO_ON_ERROR(esp_isp_register_isr(af_ctlr->isp_proc, ISP_SUBMODULE_AF), err2, TAG, "fail to register ISR");
|
||||
|
||||
isp_ll_af_enable_auto_update(isp_proc->hal.hw, false);
|
||||
isp_ll_af_enable(isp_proc->hal.hw, false);
|
||||
@@ -126,7 +123,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);
|
||||
|
||||
@@ -153,6 +150,10 @@ esp_err_t esp_isp_del_af_controller(isp_af_ctlr_t af_ctlr)
|
||||
}
|
||||
}
|
||||
ESP_RETURN_ON_FALSE(exist, ESP_ERR_INVALID_ARG, TAG, "controller isn't in use");
|
||||
|
||||
// Deregister the AF ISR
|
||||
ESP_RETURN_ON_FALSE(esp_isp_deregister_isr(af_ctlr->isp_proc, ISP_SUBMODULE_AF) == ESP_OK, ESP_FAIL, TAG, "fail to deregister ISR");
|
||||
|
||||
s_isp_declaim_af_controller(af_ctlr);
|
||||
s_isp_af_free_controller(af_ctlr);
|
||||
|
||||
@@ -164,7 +165,6 @@ 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");
|
||||
|
||||
esp_intr_enable(af_ctlr->intr_handle);
|
||||
isp_ll_af_clk_enable(af_ctlr->isp_proc->hal.hw, true);
|
||||
isp_ll_enable_intr(af_ctlr->isp_proc->hal.hw, ISP_LL_EVENT_AF_MASK, true);
|
||||
isp_ll_af_enable(af_ctlr->isp_proc->hal.hw, true);
|
||||
@@ -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;
|
||||
}
|
||||
@@ -284,12 +284,9 @@ esp_err_t esp_isp_af_controller_set_env_detector_threshold(isp_af_ctlr_t af_ctrl
|
||||
/*---------------------------------------------------------------
|
||||
INTR
|
||||
---------------------------------------------------------------*/
|
||||
static void IRAM_ATTR s_isp_af_default_isr(void *arg)
|
||||
bool IRAM_ATTR esp_isp_af_isr(isp_proc_handle_t proc, uint32_t af_events)
|
||||
{
|
||||
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);
|
||||
isp_af_ctlr_t af_ctrlr = proc->af_ctlr[0];
|
||||
|
||||
bool need_yield = false;
|
||||
esp_isp_af_env_detector_evt_data_t edata = {};
|
||||
@@ -323,8 +320,5 @@ static void IRAM_ATTR s_isp_af_default_isr(void *arg)
|
||||
need_yield |= af_ctrlr->cbs.on_env_change(af_ctrlr, &edata, af_ctrlr->user_data);
|
||||
}
|
||||
}
|
||||
|
||||
if (need_yield) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
return need_yield;
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ typedef struct isp_awb_controller_t {
|
||||
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;
|
||||
@@ -28,8 +27,6 @@ typedef struct isp_awb_controller_t {
|
||||
|
||||
static const char *TAG = "ISP_AWB";
|
||||
|
||||
static void s_isp_awb_default_isr(void *arg);
|
||||
|
||||
/*---------------------------------------------
|
||||
AWB
|
||||
----------------------------------------------*/
|
||||
@@ -64,10 +61,10 @@ static void s_isp_awb_free_controller(isp_awb_ctlr_t awb_ctlr)
|
||||
esp_intr_free(awb_ctlr->intr_handle);
|
||||
}
|
||||
if (awb_ctlr->evt_que) {
|
||||
vQueueDelete(awb_ctlr->evt_que);
|
||||
vQueueDeleteWithCaps(awb_ctlr->evt_que);
|
||||
}
|
||||
if (awb_ctlr->stat_lock) {
|
||||
vSemaphoreDelete(awb_ctlr->stat_lock);
|
||||
vSemaphoreDeleteWithCaps(awb_ctlr->stat_lock);
|
||||
}
|
||||
free(awb_ctlr);
|
||||
}
|
||||
@@ -109,11 +106,11 @@ esp_err_t esp_isp_new_awb_controller(isp_proc_handle_t isp_proc, const esp_isp_a
|
||||
|
||||
// Claim an AWB controller
|
||||
ESP_GOTO_ON_ERROR(s_isp_claim_awb_controller(isp_proc, awb_ctlr), err1, TAG, "no available controller");
|
||||
|
||||
// Register the AWB ISR
|
||||
uint32_t intr_st_reg_addr = isp_ll_get_intr_status_reg_addr(isp_proc->hal.hw);
|
||||
awb_ctlr->intr_priority = awb_cfg->intr_priority > 0 && awb_cfg->intr_priority <= 3 ? BIT(awb_cfg->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 | awb_ctlr->intr_priority, intr_st_reg_addr, ISP_LL_EVENT_AWB_MASK,
|
||||
s_isp_awb_default_isr, awb_ctlr, &awb_ctlr->intr_handle), err2, TAG, "allocate interrupt failed");
|
||||
int intr_priority = (awb_cfg->intr_priority > 0 && awb_cfg->intr_priority <= 3) ? BIT(awb_cfg->intr_priority) : ESP_INTR_FLAG_LOWMED;
|
||||
ESP_GOTO_ON_ERROR(intr_priority != isp_proc->intr_priority, err2, TAG, "intr_priority error");
|
||||
ESP_GOTO_ON_ERROR(esp_isp_register_isr(awb_ctlr->isp_proc, ISP_SUBMODULE_AWB), err2, TAG, "fail to register ISR");
|
||||
|
||||
// Configure the hardware
|
||||
isp_ll_awb_enable(isp_proc->hal.hw, false);
|
||||
@@ -137,6 +134,8 @@ esp_err_t esp_isp_del_awb_controller(isp_awb_ctlr_t awb_ctlr)
|
||||
ESP_RETURN_ON_FALSE(awb_ctlr && awb_ctlr->isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
||||
ESP_RETURN_ON_FALSE(awb_ctlr->isp_proc->awb_ctlr == awb_ctlr, ESP_ERR_INVALID_ARG, TAG, "controller isn't in use");
|
||||
ESP_RETURN_ON_FALSE(awb_ctlr->fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "controller isn't in init state");
|
||||
|
||||
ESP_RETURN_ON_FALSE(esp_isp_deregister_isr(awb_ctlr->isp_proc, ISP_SUBMODULE_AWB) == ESP_OK, ESP_FAIL, TAG, "fail to deregister ISR");
|
||||
s_isp_declaim_awb_controller(awb_ctlr);
|
||||
|
||||
isp_ll_awb_enable_algorithm_mode(awb_ctlr->isp_proc->hal.hw, false);
|
||||
@@ -148,9 +147,6 @@ esp_err_t esp_isp_del_awb_controller(isp_awb_ctlr_t awb_ctlr)
|
||||
esp_err_t esp_isp_awb_controller_reconfig(isp_awb_ctlr_t awb_ctlr, const esp_isp_awb_config_t *awb_cfg)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(awb_ctlr && awb_cfg, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
||||
int intr_priority = awb_cfg->intr_priority > 0 && awb_cfg->intr_priority <= 3 ? BIT(awb_cfg->intr_priority) : ESP_INTR_FLAG_LOWMED;
|
||||
ESP_RETURN_ON_FALSE(intr_priority == awb_ctlr->intr_priority, ESP_ERR_INVALID_ARG, TAG, "can't change interrupt priority after initialized");
|
||||
|
||||
return s_esp_isp_awb_config_hardware(awb_ctlr->isp_proc, awb_cfg);
|
||||
}
|
||||
|
||||
@@ -161,14 +157,10 @@ esp_err_t esp_isp_awb_controller_enable(isp_awb_ctlr_t awb_ctlr)
|
||||
awb_ctlr->fsm = ISP_FSM_ENABLE;
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
ESP_GOTO_ON_ERROR(esp_intr_enable(awb_ctlr->intr_handle), err, TAG, "failed to enable the AWB interrupt");
|
||||
isp_ll_awb_clk_enable(awb_ctlr->isp_proc->hal.hw, true);
|
||||
isp_ll_enable_intr(awb_ctlr->isp_proc->hal.hw, ISP_LL_EVENT_AWB_MASK, true);
|
||||
xSemaphoreGive(awb_ctlr->stat_lock);
|
||||
|
||||
return ret;
|
||||
err:
|
||||
awb_ctlr->fsm = ISP_FSM_INIT;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -245,13 +237,8 @@ esp_err_t esp_isp_awb_controller_stop_continuous_statistics(isp_awb_ctlr_t awb_c
|
||||
/*---------------------------------------------------------------
|
||||
INTR
|
||||
---------------------------------------------------------------*/
|
||||
static void IRAM_ATTR s_isp_awb_default_isr(void *arg)
|
||||
bool IRAM_ATTR esp_isp_awb_isr(isp_proc_handle_t proc, uint32_t awb_events)
|
||||
{
|
||||
isp_awb_ctlr_t awb_ctlr = (isp_awb_ctlr_t)arg;
|
||||
isp_proc_handle_t proc = awb_ctlr->isp_proc;
|
||||
|
||||
uint32_t awb_events = isp_hal_check_clear_intr_event(&proc->hal, ISP_LL_EVENT_AWB_MASK);
|
||||
|
||||
bool need_yield = false;
|
||||
|
||||
if (awb_events & ISP_LL_EVENT_AWB_FDONE) {
|
||||
@@ -279,10 +266,7 @@ static void IRAM_ATTR s_isp_awb_default_isr(void *arg)
|
||||
isp_ll_awb_enable(awb_ctlr->isp_proc->hal.hw, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (need_yield) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
return need_yield;
|
||||
}
|
||||
|
||||
esp_err_t esp_isp_awb_register_event_callbacks(isp_awb_ctlr_t awb_ctlr, const esp_isp_awb_cbs_t *cbs, void *user_data)
|
||||
|
||||
@@ -89,6 +89,8 @@ esp_err_t esp_isp_new_processor(const esp_isp_processor_cfg_t *proc_config, isp_
|
||||
ESP_GOTO_ON_ERROR(esp_clk_tree_src_get_freq_hz(clk_src, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &clk_src_freq_hz), err, TAG, "clock source setting fail");
|
||||
ESP_GOTO_ON_FALSE((proc_config->clk_hz > 0 && proc_config->clk_hz <= clk_src_freq_hz), ESP_ERR_INVALID_ARG, err, TAG, "clk hz not supported");
|
||||
|
||||
proc->intr_priority = (proc_config->intr_priority > 0 && proc_config->intr_priority <= 3) ? BIT(proc_config->intr_priority) : ESP_INTR_FLAG_LOWMED;
|
||||
|
||||
uint32_t out_clk_freq_hz = 0;
|
||||
hal_utils_clk_div_t clk_div = {};
|
||||
hal_utils_clk_info_t clk_info = {
|
||||
@@ -102,7 +104,7 @@ esp_err_t esp_isp_new_processor(const esp_isp_processor_cfg_t *proc_config, isp_
|
||||
if (out_clk_freq_hz != proc_config->clk_hz) {
|
||||
ESP_LOGW(TAG, "precision loss, real output frequency: %"PRIu32"Hz", out_clk_freq_hz);
|
||||
}
|
||||
|
||||
;
|
||||
isp_hal_init(&proc->hal, proc->proc_id);
|
||||
PERIPH_RCC_ATOMIC() {
|
||||
isp_ll_select_clk_source(proc->hal.hw, clk_src);
|
||||
@@ -186,3 +188,137 @@ esp_err_t esp_isp_disable(isp_proc_handle_t proc)
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
INTR
|
||||
---------------------------------------------------------------*/
|
||||
static void IRAM_ATTR s_isp_isr_dispatcher(void *arg)
|
||||
{
|
||||
isp_processor_t *proc = (isp_processor_t *)arg;
|
||||
bool need_yield = false;
|
||||
|
||||
//Check and clear hw events
|
||||
uint32_t af_events = isp_hal_check_clear_intr_event(&proc->hal, ISP_LL_EVENT_AF_MASK);
|
||||
uint32_t awb_events = isp_hal_check_clear_intr_event(&proc->hal, ISP_LL_EVENT_AWB_MASK);
|
||||
uint32_t ae_events = isp_hal_check_clear_intr_event(&proc->hal, ISP_LL_EVENT_AE_MASK);
|
||||
|
||||
bool do_dispatch = false;
|
||||
//Deal with hw events
|
||||
if (af_events) {
|
||||
portENTER_CRITICAL_ISR(&proc->spinlock);
|
||||
do_dispatch = proc->isr_users.af_isr_added;
|
||||
portEXIT_CRITICAL_ISR(&proc->spinlock);
|
||||
|
||||
if (do_dispatch) {
|
||||
need_yield |= esp_isp_af_isr(proc, af_events);
|
||||
}
|
||||
do_dispatch = false;
|
||||
}
|
||||
if (awb_events) {
|
||||
portENTER_CRITICAL_ISR(&proc->spinlock);
|
||||
do_dispatch = proc->isr_users.awb_isr_added;
|
||||
portEXIT_CRITICAL_ISR(&proc->spinlock);
|
||||
|
||||
if (do_dispatch) {
|
||||
need_yield |= esp_isp_awb_isr(proc, awb_events);
|
||||
}
|
||||
do_dispatch = false;
|
||||
}
|
||||
if (ae_events) {
|
||||
portENTER_CRITICAL_ISR(&proc->spinlock);
|
||||
do_dispatch = proc->isr_users.ae_isr_added;
|
||||
portEXIT_CRITICAL_ISR(&proc->spinlock);
|
||||
|
||||
if (do_dispatch) {
|
||||
need_yield |= esp_isp_ae_isr(proc, ae_events);
|
||||
}
|
||||
do_dispatch = false;
|
||||
}
|
||||
if (need_yield) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t esp_isp_register_isr(isp_proc_handle_t proc, isp_submodule_t submodule)
|
||||
{
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
ESP_RETURN_ON_FALSE(proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
||||
|
||||
bool do_alloc = false;
|
||||
portENTER_CRITICAL(&proc->spinlock);
|
||||
proc->isr_ref_counts++;
|
||||
if (proc->isr_ref_counts == 1) {
|
||||
assert(!proc->intr_hdl);
|
||||
do_alloc = true;
|
||||
}
|
||||
|
||||
switch (submodule) {
|
||||
case ISP_SUBMODULE_AF:
|
||||
proc->isr_users.af_isr_added = true;
|
||||
break;
|
||||
case ISP_SUBMODULE_AWB:
|
||||
proc->isr_users.awb_isr_added = true;
|
||||
break;
|
||||
case ISP_SUBMODULE_AE:
|
||||
proc->isr_users.ae_isr_added = true;
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
portEXIT_CRITICAL(&proc->spinlock);
|
||||
|
||||
if (do_alloc) {
|
||||
|
||||
uint32_t intr_st_reg_addr = isp_ll_get_intr_status_reg_addr(proc->hal.hw);
|
||||
uint32_t intr_st_mask = ISP_LL_EVENT_AF_MASK | ISP_LL_EVENT_AE_MASK | ISP_LL_EVENT_AWB_MASK;
|
||||
ret = esp_intr_alloc_intrstatus(isp_hw_info.instances[proc->proc_id].irq, ISP_INTR_ALLOC_FLAGS | proc->intr_priority, intr_st_reg_addr, intr_st_mask,
|
||||
s_isp_isr_dispatcher, (void *)proc, &proc->intr_hdl);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "no intr source");
|
||||
return ret;
|
||||
}
|
||||
esp_intr_enable(proc->intr_hdl);
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_isp_deregister_isr(isp_proc_handle_t proc, isp_submodule_t submodule)
|
||||
{
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
ESP_RETURN_ON_FALSE(proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
||||
|
||||
bool do_free = false;
|
||||
portENTER_CRITICAL(&proc->spinlock);
|
||||
proc->isr_ref_counts--;
|
||||
assert(proc->isr_ref_counts >= 0);
|
||||
if (proc->isr_ref_counts == 0) {
|
||||
assert(proc->intr_hdl);
|
||||
do_free = true;
|
||||
}
|
||||
|
||||
switch (submodule) {
|
||||
case ISP_SUBMODULE_AF:
|
||||
proc->isr_users.af_isr_added = false;
|
||||
break;
|
||||
case ISP_SUBMODULE_AWB:
|
||||
proc->isr_users.awb_isr_added = false;
|
||||
break;
|
||||
case ISP_SUBMODULE_AE:
|
||||
proc->isr_users.ae_isr_added = false;
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
portEXIT_CRITICAL(&proc->spinlock);
|
||||
|
||||
if (do_free) {
|
||||
esp_intr_disable(proc->intr_hdl);
|
||||
ret = esp_intr_free(proc->intr_hdl);
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -153,3 +153,94 @@ TEST_CASE("ISP CCM basic function", "[isp]")
|
||||
TEST_ESP_OK(esp_isp_disable(isp_proc));
|
||||
TEST_ESP_OK(esp_isp_del_processor(isp_proc));
|
||||
}
|
||||
|
||||
static bool test_isp_ae_default_on_statistics_done_cb(isp_ae_ctlr_t ae_ctlr, const esp_isp_ae_env_detector_evt_data_t *edata, void *user_data)
|
||||
{
|
||||
(void) ae_ctlr;
|
||||
(void) edata;
|
||||
(void) user_data;
|
||||
// Do nothing
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool test_isp_ae_default_on_continuous_done_cb(isp_ae_ctlr_t ae_ctlr, const esp_isp_ae_env_detector_evt_data_t *edata, void *user_data)
|
||||
{
|
||||
(void) ae_ctlr;
|
||||
(void) edata;
|
||||
(void) user_data;
|
||||
// Do nothing
|
||||
return false;
|
||||
}
|
||||
|
||||
TEST_CASE("ISP AE driver basic function", "[isp]")
|
||||
{
|
||||
esp_isp_processor_cfg_t isp_config = {
|
||||
.clk_hz = 80 * 1000 * 1000,
|
||||
.input_data_source = ISP_INPUT_DATA_SOURCE_CSI,
|
||||
.input_data_color_type = ISP_COLOR_RAW8,
|
||||
.output_data_color_type = ISP_COLOR_RGB565,
|
||||
};
|
||||
isp_proc_handle_t isp_proc = NULL;
|
||||
TEST_ESP_OK(esp_isp_new_processor(&isp_config, &isp_proc));
|
||||
TEST_ESP_OK(esp_isp_enable(isp_proc));
|
||||
|
||||
isp_ae_ctlr_t ae_ctlr = NULL;
|
||||
/* Default parameters from helper macro */
|
||||
esp_isp_ae_config_t ae_config = {
|
||||
.sample_point = ISP_AE_SAMPLE_POINT_AFTER_DEMOSAIC,
|
||||
};
|
||||
isp_ae_result_t ae_res = {};
|
||||
/* Create the ae controller */
|
||||
TEST_ESP_OK(esp_isp_new_ae_controller(isp_proc, &ae_config, &ae_ctlr));
|
||||
/* Register AE callback */
|
||||
esp_isp_ae_env_detector_evt_cbs_t ae_cb = {
|
||||
.on_env_statistics_done = test_isp_ae_default_on_statistics_done_cb,
|
||||
.on_env_change = test_isp_ae_default_on_continuous_done_cb,
|
||||
};
|
||||
TEST_ESP_OK(esp_isp_ae_env_detector_register_event_callbacks(ae_ctlr, &ae_cb, NULL));
|
||||
/* Enabled the ae controller */
|
||||
TEST_ESP_OK(esp_isp_ae_controller_enable(ae_ctlr));
|
||||
/* Start continuous AE statistics */
|
||||
TEST_ESP_OK(esp_isp_ae_controller_start_continuous_statistics(ae_ctlr));
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, esp_isp_ae_controller_get_oneshot_statistics(ae_ctlr, 0, &ae_res));
|
||||
|
||||
/* Stop continuous AE statistics */
|
||||
TEST_ESP_OK(esp_isp_ae_controller_stop_continuous_statistics(ae_ctlr));
|
||||
TEST_ESP_ERR(ESP_ERR_TIMEOUT, esp_isp_ae_controller_get_oneshot_statistics(ae_ctlr, 1, &ae_res));
|
||||
|
||||
/* Disable the ae controller */
|
||||
TEST_ESP_OK(esp_isp_ae_controller_disable(ae_ctlr));
|
||||
|
||||
/* Delete the ae controller and free the resources */
|
||||
TEST_ESP_OK(esp_isp_del_ae_controller(ae_ctlr));
|
||||
|
||||
TEST_ESP_OK(esp_isp_disable(isp_proc));
|
||||
TEST_ESP_OK(esp_isp_del_processor(isp_proc));
|
||||
}
|
||||
|
||||
TEST_CASE("ISP AE controller exhausted allocation", "[isp]")
|
||||
{
|
||||
esp_isp_processor_cfg_t isp_config = {
|
||||
.clk_hz = 80 * 1000 * 1000,
|
||||
.input_data_source = ISP_INPUT_DATA_SOURCE_CSI,
|
||||
.input_data_color_type = ISP_COLOR_RAW8,
|
||||
.output_data_color_type = ISP_COLOR_RGB565,
|
||||
};
|
||||
isp_proc_handle_t isp_proc = NULL;
|
||||
TEST_ESP_OK(esp_isp_new_processor(&isp_config, &isp_proc));
|
||||
|
||||
esp_isp_ae_config_t ae_config = {
|
||||
.sample_point = ISP_AE_SAMPLE_POINT_AFTER_DEMOSAIC,
|
||||
};
|
||||
isp_ae_ctlr_t ae_ctrlr[SOC_ISP_AE_CTLR_NUMS + 1] = {};
|
||||
for (int i = 0; i < SOC_ISP_AE_CTLR_NUMS; i++) {
|
||||
TEST_ESP_OK(esp_isp_new_ae_controller(isp_proc, &ae_config, &ae_ctrlr[i]));
|
||||
}
|
||||
|
||||
TEST_ASSERT(esp_isp_new_ae_controller(isp_proc, &ae_config, &ae_ctrlr[SOC_ISP_AE_CTLR_NUMS]) == ESP_ERR_NOT_FOUND);
|
||||
|
||||
for (int i = 0; i < SOC_ISP_AE_CTLR_NUMS; i++) {
|
||||
TEST_ESP_OK(esp_isp_del_ae_controller(ae_ctrlr[i]));
|
||||
}
|
||||
TEST_ESP_OK(esp_isp_del_processor(isp_proc));
|
||||
}
|
||||
|
||||
@@ -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
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
@@ -64,7 +64,18 @@ void isp_hal_init(isp_hal_context_t *hal, int isp_id);
|
||||
* @param[in] window_id Window ID
|
||||
* @param[in] window Window info, see `isp_window_t`
|
||||
*/
|
||||
void isp_hal_af_window_config(const isp_hal_context_t *hal, int window_id, const isp_window_t *window);
|
||||
void isp_hal_af_window_config(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(isp_hal_context_t *hal, const isp_window_t *window);
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
INTR
|
||||
@@ -75,7 +86,7 @@ void isp_hal_af_window_config(const isp_hal_context_t *hal, int window_id, const
|
||||
* @param[in] hal Context of the HAL layer
|
||||
* @param[in] mask HW event mask
|
||||
*/
|
||||
uint32_t isp_hal_check_clear_intr_event(const isp_hal_context_t *hal, uint32_t mask);
|
||||
uint32_t isp_hal_check_clear_intr_event(isp_hal_context_t *hal, uint32_t mask);
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
BF
|
||||
@@ -101,7 +112,7 @@ void isp_hal_bf_config(isp_hal_context_t *hal, isp_hal_bf_cfg_t *config);
|
||||
* - true Set success
|
||||
* - false Invalid argument
|
||||
*/
|
||||
bool isp_hal_ccm_set_matrix(const isp_hal_context_t *hal, bool saturation, const float flt_matrix[ISP_CCM_DIMENSION][ISP_CCM_DIMENSION]);
|
||||
bool isp_hal_ccm_set_matrix(isp_hal_context_t *hal, bool saturation, const float flt_matrix[ISP_CCM_DIMENSION][ISP_CCM_DIMENSION]);
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
AWB
|
||||
@@ -115,7 +126,7 @@ bool isp_hal_ccm_set_matrix(const isp_hal_context_t *hal, bool saturation, const
|
||||
* - true Set success
|
||||
* - false Invalid arg
|
||||
*/
|
||||
bool isp_hal_awb_set_window_range(const isp_hal_context_t *hal, const isp_window_t *win);
|
||||
bool isp_hal_awb_set_window_range(isp_hal_context_t *hal, const isp_window_t *win);
|
||||
|
||||
/**
|
||||
* @brief Set the luminance range of the white patch
|
||||
@@ -127,7 +138,7 @@ bool isp_hal_awb_set_window_range(const isp_hal_context_t *hal, const isp_window
|
||||
* - true Set success
|
||||
* - false Invalid arg
|
||||
*/
|
||||
bool isp_hal_awb_set_luminance_range(const isp_hal_context_t *hal, uint32_t lum_min, uint32_t lum_max);
|
||||
bool isp_hal_awb_set_luminance_range(isp_hal_context_t *hal, uint32_t lum_min, uint32_t lum_max);
|
||||
|
||||
/**
|
||||
* @brief Set the R/G ratio of the white patch
|
||||
@@ -138,7 +149,7 @@ bool isp_hal_awb_set_luminance_range(const isp_hal_context_t *hal, uint32_t lum_
|
||||
* - true Set success
|
||||
* - false Invalid arg
|
||||
*/
|
||||
bool isp_hal_awb_set_rg_ratio_range(const isp_hal_context_t *hal, float rg_min, float rg_max);
|
||||
bool isp_hal_awb_set_rg_ratio_range(isp_hal_context_t *hal, float rg_min, float rg_max);
|
||||
|
||||
/**
|
||||
* @brief Set the B/R ratio of the white patch
|
||||
@@ -149,7 +160,7 @@ bool isp_hal_awb_set_rg_ratio_range(const isp_hal_context_t *hal, float rg_min,
|
||||
* - true Set success
|
||||
* - false Invalid arg
|
||||
*/
|
||||
bool isp_hal_awb_set_bg_ratio_range(const isp_hal_context_t *hal, float bg_min, float bg_max);
|
||||
bool isp_hal_awb_set_bg_ratio_range(isp_hal_context_t *hal, float bg_min, float bg_max);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ void isp_hal_init(isp_hal_context_t *hal, int isp_id)
|
||||
/*---------------------------------------------------------------
|
||||
AF
|
||||
---------------------------------------------------------------*/
|
||||
void isp_hal_af_window_config(const isp_hal_context_t *hal, int window_id, const isp_window_t *window)
|
||||
void isp_hal_af_window_config(isp_hal_context_t *hal, int window_id, const isp_window_t *window)
|
||||
{
|
||||
isp_ll_af_set_window_range(hal->hw, window_id, window->top_left.x, window->top_left.y, window->btm_right.x, window->btm_right.y);
|
||||
}
|
||||
@@ -57,10 +57,28 @@ 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(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
|
||||
---------------------------------------------------------------*/
|
||||
uint32_t isp_hal_check_clear_intr_event(const isp_hal_context_t *hal, uint32_t mask)
|
||||
uint32_t isp_hal_check_clear_intr_event(isp_hal_context_t *hal, uint32_t mask)
|
||||
{
|
||||
uint32_t triggered_events = isp_ll_get_intr_status(hal->hw) & mask;
|
||||
|
||||
@@ -74,7 +92,7 @@ uint32_t isp_hal_check_clear_intr_event(const isp_hal_context_t *hal, uint32_t m
|
||||
/*---------------------------------------------------------------
|
||||
Color Correction Matrix
|
||||
---------------------------------------------------------------*/
|
||||
bool isp_hal_ccm_set_matrix(const isp_hal_context_t *hal, bool saturation, const float flt_matrix[ISP_CCM_DIMENSION][ISP_CCM_DIMENSION])
|
||||
bool isp_hal_ccm_set_matrix(isp_hal_context_t *hal, bool saturation, const float flt_matrix[ISP_CCM_DIMENSION][ISP_CCM_DIMENSION])
|
||||
{
|
||||
isp_ll_ccm_gain_t fp_matrix[ISP_CCM_DIMENSION][ISP_CCM_DIMENSION] = {};
|
||||
hal_utils_fixed_point_t fp_cfg = {
|
||||
@@ -98,7 +116,7 @@ bool isp_hal_ccm_set_matrix(const isp_hal_context_t *hal, bool saturation, const
|
||||
/*---------------------------------------------------------------
|
||||
AWB
|
||||
---------------------------------------------------------------*/
|
||||
bool isp_hal_awb_set_window_range(const isp_hal_context_t *hal, const isp_window_t *win)
|
||||
bool isp_hal_awb_set_window_range(isp_hal_context_t *hal, const isp_window_t *win)
|
||||
{
|
||||
if (win->top_left.x > win->btm_right.x ||
|
||||
win->top_left.y > win->btm_right.y ||
|
||||
@@ -111,7 +129,7 @@ bool isp_hal_awb_set_window_range(const isp_hal_context_t *hal, const isp_window
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isp_hal_awb_set_luminance_range(const isp_hal_context_t *hal, uint32_t lum_min, uint32_t lum_max)
|
||||
bool isp_hal_awb_set_luminance_range(isp_hal_context_t *hal, uint32_t lum_min, uint32_t lum_max)
|
||||
{
|
||||
if (lum_min > lum_max || lum_max > ISP_LL_AWB_LUM_MAX_RANGE) {
|
||||
return false;
|
||||
@@ -120,7 +138,7 @@ bool isp_hal_awb_set_luminance_range(const isp_hal_context_t *hal, uint32_t lum_
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isp_hal_awb_set_rg_ratio_range(const isp_hal_context_t *hal, float rg_min, float rg_max)
|
||||
bool isp_hal_awb_set_rg_ratio_range(isp_hal_context_t *hal, float rg_min, float rg_max)
|
||||
{
|
||||
// Convert to fixed point
|
||||
isp_ll_awb_rgb_ratio_t fp_rg_min = {};
|
||||
@@ -142,7 +160,7 @@ bool isp_hal_awb_set_rg_ratio_range(const isp_hal_context_t *hal, float rg_min,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isp_hal_awb_set_bg_ratio_range(const isp_hal_context_t *hal, float bg_min, float bg_max)
|
||||
bool isp_hal_awb_set_bg_ratio_range(isp_hal_context_t *hal, float bg_min, float bg_max)
|
||||
{
|
||||
// Convert to fixed point
|
||||
isp_ll_awb_rgb_ratio_t fp_bg_min = {};
|
||||
|
||||
@@ -843,6 +843,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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -334,6 +334,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
|
||||
|
||||
Reference in New Issue
Block a user