mirror of
https://github.com/espressif/esp-idf.git
synced 2025-07-31 19:24:33 +02:00
docs(isp_awb): add isp awb programming guide
This commit is contained in:
committed by
Kevin (Lao Kaiyao)
parent
8c225c0200
commit
4b3e014076
@@ -178,7 +178,7 @@ typedef struct {
|
|||||||
/**
|
/**
|
||||||
* @brief Prototype of ISP AF Env detector event callback
|
* @brief Prototype of ISP AF Env detector event callback
|
||||||
*
|
*
|
||||||
* @param[in] af_ctrlr ISP AF controller handle
|
* @param[in] af_ctrlr ISP AF controller handle
|
||||||
* @param[in] edata ISP AF Env detector event data
|
* @param[in] edata ISP AF Env detector event data
|
||||||
* @param[in] user_data User registered context, registered when in `esp_isp_af_env_detector_register_event_callbacks()`
|
* @param[in] user_data User registered context, registered when in `esp_isp_af_env_detector_register_event_callbacks()`
|
||||||
*
|
*
|
||||||
|
@@ -30,6 +30,14 @@ typedef struct {
|
|||||||
float max; ///< Maximum float value
|
float max; ///< Maximum float value
|
||||||
} isp_float_range_t;
|
} isp_float_range_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief ISP AF result
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
int definition[ISP_AF_WINDOW_NUM]; ///< Definition, it refers how clear and sharp an image is
|
||||||
|
int luminance[ISP_AF_WINDOW_NUM]; ///< Luminance, it refers how luminant an image is
|
||||||
|
} isp_af_result_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief ISP AWB result
|
* @brief ISP AWB result
|
||||||
*/
|
*/
|
||||||
|
@@ -12,7 +12,7 @@
|
|||||||
#include "esp_check.h"
|
#include "esp_check.h"
|
||||||
#include "esp_heap_caps.h"
|
#include "esp_heap_caps.h"
|
||||||
#include "driver/isp_awb.h"
|
#include "driver/isp_awb.h"
|
||||||
#include "isp_internal.h"
|
#include "esp_private/isp_private.h"
|
||||||
|
|
||||||
typedef struct isp_awb_controller_t {
|
typedef struct isp_awb_controller_t {
|
||||||
isp_fsm_t fsm;
|
isp_fsm_t fsm;
|
||||||
@@ -142,40 +142,43 @@ esp_err_t esp_isp_awb_controller_enable(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 && awb_ctlr->isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
||||||
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(awb_ctlr->fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "controller isn't in init state");
|
||||||
|
awb_ctlr->fsm = ISP_FSM_ENABLE;
|
||||||
|
|
||||||
esp_intr_enable(awb_ctlr->intr_handle);
|
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_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);
|
isp_ll_enable_intr(awb_ctlr->isp_proc->hal.hw, ISP_LL_EVENT_AWB_MASK, true);
|
||||||
xSemaphoreGive(awb_ctlr->stat_lock);
|
xSemaphoreGive(awb_ctlr->stat_lock);
|
||||||
awb_ctlr->fsm = ISP_FSM_ENABLE;
|
|
||||||
|
|
||||||
return ESP_OK;
|
return ret;
|
||||||
|
err:
|
||||||
|
awb_ctlr->fsm = ISP_FSM_INIT;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t esp_isp_awb_controller_disable(isp_awb_ctlr_t awb_ctlr)
|
esp_err_t esp_isp_awb_controller_disable(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 && awb_ctlr->isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
||||||
ESP_RETURN_ON_FALSE(awb_ctlr->fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "controller isn't in enable state");
|
ESP_RETURN_ON_FALSE(awb_ctlr->fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "controller isn't in enable state");
|
||||||
|
xSemaphoreTake(awb_ctlr->stat_lock, 0);
|
||||||
|
awb_ctlr->fsm = ISP_FSM_INIT;
|
||||||
|
|
||||||
isp_ll_enable_intr(awb_ctlr->isp_proc->hal.hw, ISP_LL_EVENT_AWB_MASK, false);
|
isp_ll_enable_intr(awb_ctlr->isp_proc->hal.hw, ISP_LL_EVENT_AWB_MASK, false);
|
||||||
isp_ll_awb_clk_enable(awb_ctlr->isp_proc->hal.hw, false);
|
isp_ll_awb_clk_enable(awb_ctlr->isp_proc->hal.hw, false);
|
||||||
esp_intr_disable(awb_ctlr->intr_handle);
|
esp_intr_disable(awb_ctlr->intr_handle);
|
||||||
awb_ctlr->fsm = ISP_FSM_INIT;
|
|
||||||
xSemaphoreTake(awb_ctlr->stat_lock, 0);
|
|
||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t esp_isp_awb_controller_get_oneshot_statistics(isp_awb_ctlr_t awb_ctlr, int timeout_ms, isp_awb_stat_result_t *out_res)
|
esp_err_t esp_isp_awb_controller_get_oneshot_statistics(isp_awb_ctlr_t awb_ctlr, int timeout_ms, isp_awb_stat_result_t *out_res)
|
||||||
{
|
{
|
||||||
ESP_RETURN_ON_FALSE_ISR(awb_ctlr && (out_res || timeout_ms == 0), ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
ESP_RETURN_ON_FALSE(awb_ctlr && (out_res || timeout_ms == 0), ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
||||||
ESP_RETURN_ON_FALSE_ISR(awb_ctlr->fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "controller isn't in enable state");
|
esp_err_t ret = ESP_OK;
|
||||||
TickType_t ticks = timeout_ms < 0 ? portMAX_DELAY : pdMS_TO_TICKS(timeout_ms);
|
TickType_t ticks = timeout_ms < 0 ? portMAX_DELAY : pdMS_TO_TICKS(timeout_ms);
|
||||||
|
|
||||||
xSemaphoreTake(awb_ctlr->stat_lock, ticks);
|
xSemaphoreTake(awb_ctlr->stat_lock, ticks);
|
||||||
|
ESP_GOTO_ON_FALSE(awb_ctlr->fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, err, TAG, "controller isn't in enable state");
|
||||||
// Update state to avoid race condition
|
// Update state to avoid race condition
|
||||||
awb_ctlr->fsm = ISP_FSM_START;
|
awb_ctlr->fsm = ISP_FSM_START;
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
// Reset the queue in case receiving the legacy data in the queue
|
// Reset the queue in case receiving the legacy data in the queue
|
||||||
xQueueReset(awb_ctlr->evt_que);
|
xQueueReset(awb_ctlr->evt_que);
|
||||||
// Start the AWB white patch statistics and waiting it done
|
// Start the AWB white patch statistics and waiting it done
|
||||||
@@ -187,30 +190,34 @@ esp_err_t esp_isp_awb_controller_get_oneshot_statistics(isp_awb_ctlr_t awb_ctlr,
|
|||||||
// Stop the AWB white patch statistics
|
// Stop the AWB white patch statistics
|
||||||
isp_ll_awb_enable(awb_ctlr->isp_proc->hal.hw, false);
|
isp_ll_awb_enable(awb_ctlr->isp_proc->hal.hw, false);
|
||||||
awb_ctlr->fsm = ISP_FSM_ENABLE;
|
awb_ctlr->fsm = ISP_FSM_ENABLE;
|
||||||
|
err:
|
||||||
xSemaphoreGive(awb_ctlr->stat_lock);
|
xSemaphoreGive(awb_ctlr->stat_lock);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t esp_isp_awb_controller_start_continuous_statistics(isp_awb_ctlr_t awb_ctlr)
|
esp_err_t esp_isp_awb_controller_start_continuous_statistics(isp_awb_ctlr_t awb_ctlr)
|
||||||
{
|
{
|
||||||
ESP_RETURN_ON_FALSE_ISR(awb_ctlr, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
ESP_RETURN_ON_FALSE(awb_ctlr, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
||||||
ESP_RETURN_ON_FALSE_ISR(awb_ctlr->fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "controller isn't in enable state");
|
ESP_RETURN_ON_FALSE(awb_ctlr->cbs.on_statistics_done, ESP_ERR_INVALID_STATE, TAG, "invalid state: on_statistics_done callback not registered");
|
||||||
|
esp_err_t ret = ESP_OK;
|
||||||
if (xSemaphoreTake(awb_ctlr->stat_lock, 0) == pdFALSE) {
|
if (xSemaphoreTake(awb_ctlr->stat_lock, 0) == pdFALSE) {
|
||||||
ESP_LOGW(TAG, "statistics lock is not acquired, controller is busy");
|
ESP_LOGW(TAG, "statistics lock is not acquired, controller is busy");
|
||||||
return ESP_ERR_INVALID_STATE;
|
return ESP_ERR_INVALID_STATE;
|
||||||
}
|
}
|
||||||
|
ESP_GOTO_ON_FALSE(awb_ctlr->fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, err, TAG, "controller isn't in enable state");
|
||||||
awb_ctlr->fsm = ISP_FSM_START;
|
awb_ctlr->fsm = ISP_FSM_START;
|
||||||
isp_ll_awb_enable(awb_ctlr->isp_proc->hal.hw, true);
|
isp_ll_awb_enable(awb_ctlr->isp_proc->hal.hw, true);
|
||||||
|
|
||||||
return ESP_OK;
|
return ret;
|
||||||
|
err:
|
||||||
|
xSemaphoreGive(awb_ctlr->stat_lock);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t esp_isp_awb_controller_stop_continuous_statistics(isp_awb_ctlr_t awb_ctlr)
|
esp_err_t esp_isp_awb_controller_stop_continuous_statistics(isp_awb_ctlr_t awb_ctlr)
|
||||||
{
|
{
|
||||||
ESP_RETURN_ON_FALSE_ISR(awb_ctlr, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
ESP_RETURN_ON_FALSE(awb_ctlr, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
||||||
ESP_RETURN_ON_FALSE_ISR(awb_ctlr->fsm == ISP_FSM_START, ESP_ERR_INVALID_STATE, TAG, "controller isn't in continuous state");
|
ESP_RETURN_ON_FALSE(awb_ctlr->fsm == ISP_FSM_START, ESP_ERR_INVALID_STATE, TAG, "controller isn't in continuous state");
|
||||||
|
|
||||||
isp_ll_awb_enable(awb_ctlr->isp_proc->hal.hw, false);
|
isp_ll_awb_enable(awb_ctlr->isp_proc->hal.hw, false);
|
||||||
awb_ctlr->fsm = ISP_FSM_ENABLE;
|
awb_ctlr->fsm = ISP_FSM_ENABLE;
|
||||||
@@ -236,7 +243,7 @@ static void IRAM_ATTR s_isp_awb_default_isr(void *arg)
|
|||||||
// Get the statistics result
|
// Get the statistics result
|
||||||
esp_isp_awb_evt_data_t edata = {
|
esp_isp_awb_evt_data_t edata = {
|
||||||
.awb_result = {
|
.awb_result = {
|
||||||
.white_patch_num = isp_ll_awb_get_white_patcherence_cnt(proc->hal.hw),
|
.white_patch_num = isp_ll_awb_get_white_patch_cnt(proc->hal.hw),
|
||||||
.sum_r = isp_ll_awb_get_accumulated_r_value(proc->hal.hw),
|
.sum_r = isp_ll_awb_get_accumulated_r_value(proc->hal.hw),
|
||||||
.sum_g = isp_ll_awb_get_accumulated_g_value(proc->hal.hw),
|
.sum_g = isp_ll_awb_get_accumulated_g_value(proc->hal.hw),
|
||||||
.sum_b = isp_ll_awb_get_accumulated_b_value(proc->hal.hw),
|
.sum_b = isp_ll_awb_get_accumulated_b_value(proc->hal.hw),
|
||||||
|
@@ -57,6 +57,15 @@ TEST_CASE("ISP AF controller exhausted allocation", "[isp]")
|
|||||||
TEST_ESP_OK(esp_isp_del_processor(isp_proc));
|
TEST_ESP_OK(esp_isp_del_processor(isp_proc));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool test_isp_awb_default_on_statistics_done_cb(isp_awb_ctlr_t awb_ctlr, const esp_isp_awb_evt_data_t *edata, void *user_data)
|
||||||
|
{
|
||||||
|
(void) awb_ctlr;
|
||||||
|
(void) edata;
|
||||||
|
(void) user_data;
|
||||||
|
// Do nothing
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("ISP AWB driver basic function", "[isp]")
|
TEST_CASE("ISP AWB driver basic function", "[isp]")
|
||||||
{
|
{
|
||||||
esp_isp_processor_cfg_t isp_config = {
|
esp_isp_processor_cfg_t isp_config = {
|
||||||
@@ -88,6 +97,11 @@ TEST_CASE("ISP AWB driver basic function", "[isp]")
|
|||||||
isp_awb_stat_result_t stat_res = {};
|
isp_awb_stat_result_t stat_res = {};
|
||||||
/* Create the awb controller */
|
/* Create the awb controller */
|
||||||
TEST_ESP_OK(esp_isp_new_awb_controller(isp_proc, &awb_config, &awb_ctlr));
|
TEST_ESP_OK(esp_isp_new_awb_controller(isp_proc, &awb_config, &awb_ctlr));
|
||||||
|
/* Register AWB callback */
|
||||||
|
esp_isp_awb_cbs_t awb_cb = {
|
||||||
|
.on_statistics_done = test_isp_awb_default_on_statistics_done_cb,
|
||||||
|
};
|
||||||
|
TEST_ESP_OK(esp_isp_awb_register_event_callbacks(awb_ctlr, &awb_cb, NULL));
|
||||||
/* Enabled the awb controller */
|
/* Enabled the awb controller */
|
||||||
TEST_ESP_OK(esp_isp_awb_controller_enable(awb_ctlr));
|
TEST_ESP_OK(esp_isp_awb_controller_enable(awb_ctlr));
|
||||||
/* Start continuous AWB statistics */
|
/* Start continuous AWB statistics */
|
||||||
|
@@ -1123,7 +1123,7 @@ static inline void isp_ll_awb_set_bg_ratio_range(isp_dev_t *hw, isp_ll_awb_rgb_r
|
|||||||
* - white patch count
|
* - white patch count
|
||||||
*/
|
*/
|
||||||
__attribute__((always_inline))
|
__attribute__((always_inline))
|
||||||
static inline uint32_t isp_ll_awb_get_white_patcherence_cnt(isp_dev_t *hw)
|
static inline uint32_t isp_ll_awb_get_white_patch_cnt(isp_dev_t *hw)
|
||||||
{
|
{
|
||||||
return hw->awb0_white_cnt.awb0_white_cnt;
|
return hw->awb0_white_cnt.awb0_white_cnt;
|
||||||
}
|
}
|
||||||
|
@@ -88,21 +88,6 @@ uint32_t isp_hal_check_clear_intr_event(const isp_hal_context_t *hal, uint32_t m
|
|||||||
*/
|
*/
|
||||||
void isp_hal_bf_config(isp_hal_context_t *hal, isp_hal_bf_cfg_t *config);
|
void isp_hal_bf_config(isp_hal_context_t *hal, isp_hal_bf_cfg_t *config);
|
||||||
|
|
||||||
/*---------------------------------------------------------------
|
|
||||||
Color Correction Matrix
|
|
||||||
---------------------------------------------------------------*/
|
|
||||||
/**
|
|
||||||
* @brief Set Color Correction Matrix
|
|
||||||
*
|
|
||||||
* @param[in] hal Context of the HAL layer
|
|
||||||
* @param[in] saturation Whether to enable saturation when float data overflow
|
|
||||||
* @param[in] flt_matrix 3x3 RGB correction matrix
|
|
||||||
* @return
|
|
||||||
* - true Set success
|
|
||||||
* - false Invalid are
|
|
||||||
*/
|
|
||||||
bool isp_hal_ccm_set_matrix(const isp_hal_context_t *hal, bool saturation, const float flt_matrix[3][3]);
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------
|
/*---------------------------------------------------------------
|
||||||
AWB
|
AWB
|
||||||
---------------------------------------------------------------*/
|
---------------------------------------------------------------*/
|
||||||
|
@@ -82,12 +82,14 @@ typedef enum {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief ISP AF result
|
* @brief ISP AF window
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int definition[ISP_AF_WINDOW_NUM]; ///< Definition, it refers how clear and sharp an image is
|
uint32_t top_left_x; ///< Top left x axis value
|
||||||
int luminance[ISP_AF_WINDOW_NUM]; ///< Luminance, it refers how luminant an image is
|
uint32_t top_left_y; ///< Top left y axis value
|
||||||
} isp_af_result_t;
|
uint32_t bottom_right_x; ///< Bottom right x axis value
|
||||||
|
uint32_t bottom_right_y; ///< Bottom right y axis value
|
||||||
|
} isp_af_window_t;
|
||||||
|
|
||||||
/*---------------------------------------------------------------
|
/*---------------------------------------------------------------
|
||||||
BF
|
BF
|
||||||
|
@@ -16,8 +16,6 @@
|
|||||||
#include "hal/isp_types.h"
|
#include "hal/isp_types.h"
|
||||||
#include "hal/hal_utils.h"
|
#include "hal/hal_utils.h"
|
||||||
|
|
||||||
#include "esp_rom_sys.h"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ISP HAL layer
|
* ISP HAL layer
|
||||||
*/
|
*/
|
||||||
|
@@ -4,7 +4,7 @@ Image Signal Processor
|
|||||||
Introduction
|
Introduction
|
||||||
------------
|
------------
|
||||||
|
|
||||||
{IDF_TARGET_NAME} includes an image signal processor (ISP), which is a feature pipeline that consists of many image processing algorithms. ISP receives image data from the DVP camera or MIPI-CSI camera, or system memory, and writes the processed image data to the system memory through DMA. ISP shall work with other modules to read and write data, it can not work alone.
|
{IDF_TARGET_NAME} includes an Image Signal Processor (ISP), which is a feature pipeline that consists of many image processing algorithms. ISP receives image data from the DVP camera or MIPI-CSI camera, or system memory, and writes the processed image data to the system memory through DMA. ISP shall work with other modules to read and write data, it can not work alone.
|
||||||
|
|
||||||
Terminology
|
Terminology
|
||||||
-----------
|
-----------
|
||||||
@@ -16,6 +16,39 @@ Terminology
|
|||||||
- RGB: Colored image format composed of red, green, and blue colors classified into RGB888, RGB565, etc., based on the bit width of each color
|
- RGB: Colored image format composed of red, green, and blue colors classified into RGB888, RGB565, etc., based on the bit width of each color
|
||||||
- YUV: Colored image format composed of luminance and chrominance classified into YUV444, YUV422, YUV420, etc., based on the data arrangement
|
- YUV: Colored image format composed of luminance and chrominance classified into YUV444, YUV422, YUV420, etc., based on the data arrangement
|
||||||
- AF: Auto-focus
|
- AF: Auto-focus
|
||||||
|
- AWB: Auto-white balance
|
||||||
|
|
||||||
|
ISP Pipeline
|
||||||
|
------------
|
||||||
|
|
||||||
|
.. blockdiag::
|
||||||
|
:scale: 100%
|
||||||
|
:caption: ISP Pipeline
|
||||||
|
:align: center
|
||||||
|
|
||||||
|
blockdiag isp_pipeline {
|
||||||
|
orientation = portrait;
|
||||||
|
node_height = 30;
|
||||||
|
node_width = 120;
|
||||||
|
span_width = 100;
|
||||||
|
default_fontsize = 16;
|
||||||
|
|
||||||
|
isp_header [label = "ISP Header"];
|
||||||
|
isp_tail [label = "ISP Tail"];
|
||||||
|
isp_chs [label = "Contrast &\n Hue & Saturation", width = 150, height = 70];
|
||||||
|
isp_yuv [label = "YUV Limit\nYUB2RGB", width = 120, height = 70];
|
||||||
|
|
||||||
|
isp_header -> BF -> Demosaic -> CCM -> RGB2YUV -> isp_chs -> isp_yuv -> isp_tail;
|
||||||
|
|
||||||
|
BF -> HIST
|
||||||
|
Demosaic -> AWB
|
||||||
|
Demosaic -> AE
|
||||||
|
Demosaic -> HIST
|
||||||
|
CCM -> AWB
|
||||||
|
CCM -> AE
|
||||||
|
RGB2YUV -> HIST
|
||||||
|
RGB2YUV -> AF
|
||||||
|
}
|
||||||
|
|
||||||
Functional Overview
|
Functional Overview
|
||||||
-------------------
|
-------------------
|
||||||
@@ -24,8 +57,8 @@ The ISP driver offers following services:
|
|||||||
|
|
||||||
- `Resource Allocation <#isp-resource-allocation>`__ - covers how to allocate ISP resources with properly set of configurations. It also covers how to recycle the resources when they finished working.
|
- `Resource Allocation <#isp-resource-allocation>`__ - covers how to allocate ISP resources with properly set of configurations. It also covers how to recycle the resources when they finished working.
|
||||||
- `Enable and disable ISP processor <#isp-enable-disable>`__ - covers how to enable and disable an ISP processor.
|
- `Enable and disable ISP processor <#isp-enable-disable>`__ - covers how to enable and disable an ISP processor.
|
||||||
- `Get AF oneshot result <#isp-af-get-oneshot-result>`__ - covers how to get AF oneshot result.
|
- `Get AF statistics in one shot or continuous way <#isp-af-statistics>`__ - covers how to get AF statistics one-shot or continuously.
|
||||||
- `Start AF statistics continuously <#isp-af-start-conti-stat>`__ - covers how to start the continuous AF statistics.
|
- `Get AWB statistics in one shot or continuous way <#isp-awb-statistics>`__ - covers how to get AWB white patches statistics one-shot or continuously.
|
||||||
- `Register callback <#isp-callback>`__ - covers how to hook user specific code to ISP driver event callback function.
|
- `Register callback <#isp-callback>`__ - covers how to hook user specific code to ISP driver event callback function.
|
||||||
- `Thread Safety <#isp-thread-safety>`__ - lists which APIs are guaranteed to be thread safe by the driver.
|
- `Thread Safety <#isp-thread-safety>`__ - lists which APIs are guaranteed to be thread safe by the driver.
|
||||||
- `Kconfig Options <#isp-kconfig-options>`__ - lists the supported Kconfig options that can bring different effects to the driver.
|
- `Kconfig Options <#isp-kconfig-options>`__ - lists the supported Kconfig options that can bring different effects to the driver.
|
||||||
@@ -36,8 +69,8 @@ The ISP driver offers following services:
|
|||||||
Resource Allocation
|
Resource Allocation
|
||||||
^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Install Image Signal Processor (ISP) Driver
|
Install ISP Driver
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
ISP driver requires the configuration that specified by :cpp:type:`esp_isp_processor_cfg_t`.
|
ISP driver requires the configuration that specified by :cpp:type:`esp_isp_processor_cfg_t`.
|
||||||
|
|
||||||
@@ -59,8 +92,8 @@ If the configurations in :cpp:type:`esp_isp_processor_cfg_t` is specified, users
|
|||||||
You can use the created handle to do driver enable / disable the ISP driver and do other ISP module installation.
|
You can use the created handle to do driver enable / disable the ISP driver and do other ISP module installation.
|
||||||
|
|
||||||
|
|
||||||
Install Image Signal Processor (ISP) Auto-Focus (AF) Driver
|
Install ISP Auto-Focus (AF) Driver
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
ISP auto-focus (AF) driver requires the configuration that specified by :cpp:type:`esp_isp_af_config_t`.
|
ISP auto-focus (AF) driver requires the configuration that specified by :cpp:type:`esp_isp_af_config_t`.
|
||||||
|
|
||||||
@@ -76,33 +109,66 @@ If the configurations in :cpp:type:`esp_isp_af_config_t` is specified, users can
|
|||||||
|
|
||||||
You can use the created handle to do driver enable / disable the ISP AF driver and ISP AF Env module installation.
|
You can use the created handle to do driver enable / disable the ISP AF driver and ISP AF Env module installation.
|
||||||
|
|
||||||
Uninstall Image Signal Processor (ISP) Driver
|
Install ISP Auto-White-Balance (AWB) Driver
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
ISP auto-white-balance (AWB) driver requires the configuration specified by :cpp:type:`esp_isp_awb_config_t`.
|
||||||
|
|
||||||
|
If an :cpp:type:`esp_isp_awb_config_t` configuration is specified, you can call :cpp:func:`esp_isp_new_awb_controller` to allocate and initialize an ISP AWB processor. This function will return an ISP AWB processor handle on success. You can take following code as reference.
|
||||||
|
|
||||||
|
.. code:: c
|
||||||
|
|
||||||
|
isp_awb_ctlr_t awb_ctlr = NULL;
|
||||||
|
uint32_t image_width = 800;
|
||||||
|
uint32_t image_height = 600;
|
||||||
|
/* The AWB configuration, please refer to the API comment for how to tune these parameters */
|
||||||
|
esp_isp_awb_config_t awb_config = {
|
||||||
|
.sample_point = ISP_AWB_SAMPLE_POINT_AFTER_CCM,
|
||||||
|
.window = {
|
||||||
|
.top_left = {.x = image_width * 0.2, .y = image_height * 0.2},
|
||||||
|
.btm_right = {.x = image_width * 0.8, .y = image_height * 0.8},
|
||||||
|
},
|
||||||
|
.white_patch = {
|
||||||
|
.luminance = {.min = 0, .max = 220 * 3},
|
||||||
|
.red_green_ratio = {.min = 0.0f, .max = 3.999f},
|
||||||
|
.blue_green_ratio = {.min = 0.0f, .max = 3.999f},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
ESP_ERROR_CHECK(esp_isp_new_awb_controller(isp_proc, &awb_config, &awb_ctlr));
|
||||||
|
|
||||||
|
The AWB handle created in this step is required by other AWB APIs and AWB scheme.
|
||||||
|
|
||||||
|
Uninstall ISP Driver
|
||||||
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
If a previously installed ISP processor is no longer needed, it's recommended to recycle the resource by calling :cpp:func:`esp_isp_del_processor`, so that to release the underlying hardware.
|
If a previously installed ISP processor is no longer needed, it's recommended to recycle the resource by calling :cpp:func:`esp_isp_del_processor`, so that to release the underlying hardware.
|
||||||
|
|
||||||
UnInstall Image Signal Processor (ISP) Auto-Focus (AF) Driver
|
UnInstall ISP AF Driver
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
If a previously installed ISP AF processor is no longer needed, it's recommended to recycle the resource by calling :cpp:func:`esp_isp_del_af_controller`, so that to release the underlying hardware.
|
If a previously installed ISP AF processor is no longer needed, it's recommended to recycle the resource by calling :cpp:func:`esp_isp_del_af_controller`, so that to release the underlying hardware.
|
||||||
|
|
||||||
|
UnInstall ISP AWB Driver
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
If a previously installed ISP AWB processor is no longer needed, it's recommended to free the resource by calling :cpp:func:`esp_isp_del_awb_controller`, it will also release the underlying hardware.
|
||||||
|
|
||||||
|
|
||||||
.. _isp-enable-disable:
|
.. _isp-enable-disable:
|
||||||
|
|
||||||
Enable and Disable Image Signal Processor (ISP)
|
Enable and Disable ISP
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Image Signal Processor (ISP)
|
|
||||||
----------------------------
|
|
||||||
|
|
||||||
|
ISP
|
||||||
|
---------
|
||||||
Before doing ISP pipeline, you need to enable the ISP processor first, by calling :cpp:func:`esp_isp_enable`. This function:
|
Before doing ISP pipeline, you need to enable the ISP processor first, by calling :cpp:func:`esp_isp_enable`. This function:
|
||||||
|
|
||||||
* Switches the driver state from **init** to **enable**.
|
* Switches the driver state from **init** to **enable**.
|
||||||
|
|
||||||
Calling :cpp:func:`esp_isp_disable` does the opposite, that is, put the driver back to the **init** state.
|
Calling :cpp:func:`esp_isp_disable` does the opposite, that is, put the driver back to the **init** state.
|
||||||
|
|
||||||
Image Signal Processor (ISP) Auto-Focus (AF) Processor
|
ISP AF Processor
|
||||||
------------------------------------------------------
|
----------------
|
||||||
|
|
||||||
Before doing ISP AF, you need to enable the ISP AF processor first, by calling :cpp:func:`esp_isp_af_controller_enable`. This function:
|
Before doing ISP AF, you need to enable the ISP AF processor first, by calling :cpp:func:`esp_isp_af_controller_enable`. This function:
|
||||||
|
|
||||||
@@ -110,13 +176,17 @@ Before doing ISP AF, you need to enable the ISP AF processor first, by calling :
|
|||||||
|
|
||||||
Calling :cpp:func:`esp_isp_af_controller_disable` does the opposite, that is, put the driver back to the **init** state.
|
Calling :cpp:func:`esp_isp_af_controller_disable` does the opposite, that is, put the driver back to the **init** state.
|
||||||
|
|
||||||
.. _isp-af-get-oneshot-result:
|
.. _isp-af-statistics:
|
||||||
|
|
||||||
Get Auto-Focus (AF) Oneshot Result
|
AF One-shot and Continuous Statistics
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Calling :cpp:func:`esp_isp_af_controller_get_oneshot_statistics` to get oneshot AF statistics result. You can take following code as reference.
|
Calling :cpp:func:`esp_isp_af_controller_get_oneshot_statistics` to get oneshot AF statistics result. You can take following code as reference.
|
||||||
|
|
||||||
|
Aside from the above oneshot API, the ISP AF driver also provides a way to start AF statistics continuously. Calling :cpp:func:`esp_isp_af_controller_start_continuous_statistics` to start the continuous statistics and :cpp:func:`esp_isp_af_controller_stop_continuous_statistics` to stop it.
|
||||||
|
|
||||||
|
Note that if you want to use the continuous statistics, you need to register the :cpp:member:`esp_isp_af_env_detector_evt_cbs_t::on_env_statistics_done` or :cpp:member:`esp_isp_af_env_detector_evt_cbs_t::on_env_change` callback to get the statistics result. See how to register in `Register Event Callbacks <#isp-callback>`__
|
||||||
|
|
||||||
.. code:: c
|
.. code:: c
|
||||||
|
|
||||||
esp_isp_af_config_t af_config = {
|
esp_isp_af_config_t af_config = {
|
||||||
@@ -129,26 +199,6 @@ Calling :cpp:func:`esp_isp_af_controller_get_oneshot_statistics` to get oneshot
|
|||||||
/* Trigger the AF statistics and get its result for one time with timeout value 2000ms. */
|
/* Trigger the AF statistics and get its result for one time with timeout value 2000ms. */
|
||||||
ESP_ERROR_CHECK(esp_isp_af_controller_get_oneshot_statistics(af_ctrlr, 2000, &result));
|
ESP_ERROR_CHECK(esp_isp_af_controller_get_oneshot_statistics(af_ctrlr, 2000, &result));
|
||||||
|
|
||||||
.. _isp-af-start-conti-stat:
|
|
||||||
|
|
||||||
Start Auto-Focus (AF) Statistics Continuously
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
Aside from the above oneshot API, the ISP AF driver also provides a way to start AF statistics continuously. Calling :cpp:func:`esp_isp_af_controller_start_continuous_statistics` to start the continuous statistics and :cpp:func:`esp_isp_af_controller_stop_continuous_statistics` to stop it.
|
|
||||||
|
|
||||||
Note that if you want to use the continuous statistics, you need to register the :cpp:member:`esp_isp_af_env_detector_evt_cbs_t::on_env_statistics_done` or :cpp:member:`esp_isp_af_env_detector_evt_cbs_t::on_env_change` callback to get the statistics result. See how to register in `Register Event Callbacks <#isp-callback>`__
|
|
||||||
|
|
||||||
.. code:: c
|
|
||||||
|
|
||||||
isp_af_ctlr_t af_ctrlr = NULL;
|
|
||||||
esp_isp_af_config_t af_config = {
|
|
||||||
.edge_thresh = 128,
|
|
||||||
};
|
|
||||||
isp_af_result_t stat_res = {};
|
|
||||||
/* Create the af controller */
|
|
||||||
ESP_ERROR_CHECK(esp_isp_new_af_controller(isp_proc, &af_config, &af_ctrlr));
|
|
||||||
/* Enabled the af controller */
|
|
||||||
ESP_ERROR_CHECK(esp_isp_af_controller_enable(af_ctrlr));
|
|
||||||
/* Start continuous AF statistics */
|
/* Start continuous AF statistics */
|
||||||
ESP_ERROR_CHECK(esp_isp_af_controller_start_continuous_statistics(af_ctrlr));
|
ESP_ERROR_CHECK(esp_isp_af_controller_start_continuous_statistics(af_ctrlr));
|
||||||
// You can do other stuffs here, the statistics result can be obtained in the callback
|
// You can do other stuffs here, the statistics result can be obtained in the callback
|
||||||
@@ -156,13 +206,14 @@ Note that if you want to use the continuous statistics, you need to register the
|
|||||||
// vTaskDelay(pdMS_TO_TICKS(1000));
|
// vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
/* Stop continuous AF statistics */
|
/* Stop continuous AF statistics */
|
||||||
ESP_ERROR_CHECK(esp_isp_af_controller_stop_continuous_statistics(af_ctrlr));
|
ESP_ERROR_CHECK(esp_isp_af_controller_stop_continuous_statistics(af_ctrlr));
|
||||||
|
|
||||||
/* Disable the af controller */
|
/* Disable the af controller */
|
||||||
ESP_ERROR_CHECK(esp_isp_af_controller_disable(af_ctrlr));
|
ESP_ERROR_CHECK(esp_isp_af_controller_disable(af_ctrlr));
|
||||||
/* Delete the af controller and free the resources */
|
/* Delete the af controller and free the resources */
|
||||||
ESP_ERROR_CHECK(esp_isp_del_af_controller(af_ctrlr));
|
ESP_ERROR_CHECK(esp_isp_del_af_controller(af_ctrlr));
|
||||||
|
|
||||||
Set Auto-Focus (AF) Environment Detector
|
Set AF Environment Detector
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Calling :cpp:func:`esp_isp_af_controller_set_env_detector` to set an ISP AF environment detector. You can take following code as reference.
|
Calling :cpp:func:`esp_isp_af_controller_set_env_detector` to set an ISP AF environment detector. You can take following code as reference.
|
||||||
|
|
||||||
@@ -175,8 +226,8 @@ Calling :cpp:func:`esp_isp_af_controller_set_env_detector` to set an ISP AF envi
|
|||||||
ESP_ERROR_CHECK(esp_isp_new_af_controller(isp_proc, &af_config, &af_ctrlr));
|
ESP_ERROR_CHECK(esp_isp_new_af_controller(isp_proc, &af_config, &af_ctrlr));
|
||||||
ESP_ERROR_CHECK(esp_isp_af_controller_set_env_detector(af_ctrlr, &env_config));
|
ESP_ERROR_CHECK(esp_isp_af_controller_set_env_detector(af_ctrlr, &env_config));
|
||||||
|
|
||||||
Set Auto-Focus (AF) Environment Detector Threshold
|
Set AF Environment Detector Threshold
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Calling :cpp:func:`esp_isp_af_env_detector_set_threshold` to set the threshold of an ISP AF environment detector.
|
Calling :cpp:func:`esp_isp_af_env_detector_set_threshold` to set the threshold of an ISP AF environment detector.
|
||||||
|
|
||||||
@@ -186,13 +237,80 @@ Calling :cpp:func:`esp_isp_af_env_detector_set_threshold` to set the threshold o
|
|||||||
int luminance_thresh = 0;
|
int luminance_thresh = 0;
|
||||||
ESP_ERROR_CHECK(esp_isp_af_env_detector_set_threshold(env_detector, definition_thresh, luminance_thresh));
|
ESP_ERROR_CHECK(esp_isp_af_env_detector_set_threshold(env_detector, definition_thresh, luminance_thresh));
|
||||||
|
|
||||||
|
ISP AWB Processor
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Before doing ISP AWB, you need to enable the ISP AWB processor first, by calling :cpp:func:`esp_isp_awb_controller_enable`. This function:
|
||||||
|
|
||||||
|
* Switches the driver state from **init** to **enable**.
|
||||||
|
|
||||||
|
Calling :cpp:func:`esp_isp_awb_controller_disable` does the opposite, that is, put the driver back to the **init** state.
|
||||||
|
|
||||||
|
.. _isp-awb-statistics:
|
||||||
|
|
||||||
|
AWB One-shot and Continuous Statistics
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Calling :cpp:func:`esp_isp_awb_controller_get_oneshot_result` to get oneshot AWB statistics result of white patches. You can take following code as reference.
|
||||||
|
|
||||||
|
Aside from the above oneshot API, the ISP AWB driver also provides a way to start AWB statistics continuously. Calling :cpp:func:`esp_isp_awb_controller_start_continuous_statistics` starts the continuous statistics and :cpp:func:`esp_isp_awb_controller_stop_continuous_statistics` stops it.
|
||||||
|
|
||||||
|
Note that if you want to use the continuous statistics, you need to register the :cpp:member:`esp_isp_awb_cbs_t::on_statistics_done` callback to get the statistics result. See how to register it in `Register Event Callbacks <#isp-callback>`__
|
||||||
|
|
||||||
|
.. code:: c
|
||||||
|
|
||||||
|
bool example_isp_awb_on_statistics_done_cb(isp_awb_ctlr_t awb_ctlr, const esp_isp_awb_evt_data_t *edata, void *user_data);
|
||||||
|
// ...
|
||||||
|
isp_awb_ctlr_t awb_ctlr = NULL;
|
||||||
|
uint32_t image_width = 800;
|
||||||
|
uint32_t image_height = 600;
|
||||||
|
/* The AWB configuration, please refer to the API comment for how to tune these parameters */
|
||||||
|
esp_isp_awb_config_t awb_config = {
|
||||||
|
.sample_point = ISP_AWB_SAMPLE_POINT_AFTER_CCM,
|
||||||
|
.window = {
|
||||||
|
.top_left = {.x = image_width * 0.2, .y = image_height * 0.2},
|
||||||
|
.btm_right = {.x = image_width * 0.8, .y = image_height * 0.8},
|
||||||
|
},
|
||||||
|
.white_patch = {
|
||||||
|
.luminance = {.min = 0, .max = 220 * 3},
|
||||||
|
.red_green_ratio = {.min = 0.0f, .max = 3.999f},
|
||||||
|
.blue_green_ratio = {.min = 0.0f, .max = 3.999f},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
isp_awb_stat_result_t stat_res = {};
|
||||||
|
/* Create the awb controller */
|
||||||
|
ESP_ERROR_CHECK(esp_isp_new_awb_controller(isp_proc, &awb_config, &awb_ctlr));
|
||||||
|
/* Register AWB callback */
|
||||||
|
esp_isp_awb_cbs_t awb_cb = {
|
||||||
|
.on_statistics_done = example_isp_awb_on_statistics_done_cb,
|
||||||
|
};
|
||||||
|
ESP_ERROR_CHECK(esp_isp_awb_register_event_callbacks(awb_ctlr, &awb_cb, NULL));
|
||||||
|
/* Enabled the awb controller */
|
||||||
|
ESP_ERROR_CHECK(esp_isp_awb_controller_enable(awb_ctlr));
|
||||||
|
|
||||||
|
/* Get oneshot AWB statistics result */
|
||||||
|
ESP_ERROR_CHECK(esp_isp_awb_controller_get_oneshot_statistics(awb_ctlr, -1, &stat_res));
|
||||||
|
|
||||||
|
/* Start continuous AWB statistics, note that continuous statistics requires `on_statistics_done` callback */
|
||||||
|
ESP_ERROR_CHECK(esp_isp_awb_controller_start_continuous_statistics(awb_ctlr));
|
||||||
|
// You can do other stuffs here, the statistics result can be obtained in the callback
|
||||||
|
// ......
|
||||||
|
// vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
|
/* Stop continuous AWB statistics */
|
||||||
|
ESP_ERROR_CHECK(esp_isp_awb_controller_stop_continuous_statistics(awb_ctlr));
|
||||||
|
|
||||||
|
/* Disable the awb controller */
|
||||||
|
ESP_ERROR_CHECK(esp_isp_awb_controller_disable(awb_ctlr));
|
||||||
|
/* Delete the awb controller and free the resources */
|
||||||
|
ESP_ERROR_CHECK(esp_isp_del_awb_controller(awb_ctlr));
|
||||||
|
|
||||||
.. _isp-callback:
|
.. _isp-callback:
|
||||||
|
|
||||||
Register Event Callbacks
|
Register Event Callbacks
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Register Image Signal Processor (ISP) Auto-Focus (AF) Environment Detector Event Callbacks
|
Register ISP AF Environment Detector Event Callbacks
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
After the ISP AF environment detector starts up, it can generate a specific event dynamically. If you have some functions that should be called when the event happens, please hook your function to the interrupt service routine by calling :cpp:func:`esp_isp_af_env_detector_register_event_callbacks`. All supported event callbacks are listed in :cpp:type:`esp_isp_af_env_detector_evt_cbs_t`:
|
After the ISP AF environment detector starts up, it can generate a specific event dynamically. If you have some functions that should be called when the event happens, please hook your function to the interrupt service routine by calling :cpp:func:`esp_isp_af_env_detector_register_event_callbacks`. All supported event callbacks are listed in :cpp:type:`esp_isp_af_env_detector_evt_cbs_t`:
|
||||||
|
|
||||||
@@ -201,6 +319,15 @@ After the ISP AF environment detector starts up, it can generate a specific even
|
|||||||
|
|
||||||
You can save your own context to :cpp:func:`esp_isp_af_env_detector_register_event_callbacks` as well, via the parameter ``user_data``. The user data will be directly passed to the callback function.
|
You can save your own context to :cpp:func:`esp_isp_af_env_detector_register_event_callbacks` as well, via the parameter ``user_data``. The user data will be directly passed to the callback function.
|
||||||
|
|
||||||
|
Register ISP AWB Statistics Done Event Callbacks
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
After the ISP AWB controller finished statistics of white patches, it can generate a specific event dynamically. If you want to be informed when the statistics done event takes place, please hook your function to the interrupt service routine by calling :cpp:func:`esp_isp_awb_register_event_callbacks`. All supported event callbacks are listed in :cpp:type:`esp_isp_awb_cbs_t`:
|
||||||
|
|
||||||
|
- :cpp:member:`esp_isp_awb_cbs_t::on_statistics_done` sets a callback function when finished statistics of the white patches. As this function is called within the ISR context, you must ensure that the function does not attempt to block (e.g., by making sure that only FreeRTOS APIs with ``ISR`` suffix are called from within the function). The function prototype is declared in :cpp:type:`esp_isp_awb_callback_t`.
|
||||||
|
|
||||||
|
You can save your own context via the parameter ``user_data`` of :cpp:func:`esp_isp_awb_register_event_callbacks`. The user data will be directly passed to the callback function.
|
||||||
|
|
||||||
.. _isp-thread-safety:
|
.. _isp-thread-safety:
|
||||||
|
|
||||||
Thread Safety
|
Thread Safety
|
||||||
|
Reference in New Issue
Block a user