Skip to content

Commit

Permalink
Merge branch 'feature/support_isp_awb' into 'master'
Browse files Browse the repository at this point in the history
feat(isp): Support ISP Auto White Balance (AWB)

Closes IDF-9593

See merge request espressif/esp-idf!30137
  • Loading branch information
L-KAYA committed Jun 4, 2024
2 parents 82af825 + 846287b commit ad57a47
Show file tree
Hide file tree
Showing 18 changed files with 1,294 additions and 59 deletions.
3 changes: 2 additions & 1 deletion components/esp_driver_isp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ set(requires)

if(CONFIG_SOC_ISP_SUPPORTED)
list(APPEND srcs "src/isp_core.c"
"src/isp_af.c")
"src/isp_af.c"
"src/isp_awb.c")
endif()

if(CONFIG_SOC_ISP_BF_SUPPORTED)
Expand Down
1 change: 1 addition & 0 deletions components/esp_driver_isp/include/driver/isp.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@

#include "driver/isp_core.h"
#include "driver/isp_af.h"
#include "driver/isp_awb.h"
#include "driver/isp_bf.h"
2 changes: 1 addition & 1 deletion components/esp_driver_isp/include/driver/isp_af.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ typedef struct {
/**
* @brief Prototype of ISP AF Env detector event callback
*
* @param[in] handle ISP AF controller handle
* @param[in] af_ctrlr ISP AF controller handle
* @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()`
*
Expand Down
207 changes: 207 additions & 0 deletions components/esp_driver_isp/include/driver/isp_awb.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
/*
* 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 AWB controller config
*/
typedef struct {
isp_awb_sample_point_t sample_point; /*!< AWB sample point of the ISP pipeline.
* ISP_AWB_SAMPLE_POINT_BEFORE_CCM: sample before Color Correction Matrix(CCM).
* ISP_AWB_SAMPLE_POINT_AFTER_CCM: sample after Color Correction Matrix(CCM).
* If your camera support to set the manual gain to the RGB channels,
* then you can choose to sample before CCM, and set the gain to the camera registers.
* If your camera doesn't support the manual gain or don't want to change the camera configuration,
* then you can choose to sample after CCM, and set the calculated gain to the CCM
*/
isp_window_t window; /*!< Statistic window of AWB.
* Suggest to set it at the middle of the image and a little smaller than the whole image.
* It will be more reliable because the edges of image are easily to be overexposure,
* the overexposure pixels are almost at maximum luminance,
* which are not good references to calculate the gain for white balance.
*/
struct {
isp_u32_range_t luminance; /*!< Luminance range of the white patch. Range [0, 255 * 3]
* Not suggest to set the max value to 255 * 3,
* because these pixels are too bright, very possible to be overexposure.
* So the pixels that too bright should not be the reference of the white balance.
* And the minimum value better to be 0 to allow the white balance work under low luminance environment.
*/
isp_float_range_t red_green_ratio; /*!< Red to green ratio of the white patch. Range [0, 4.0).
* The ratio could be as wider as possible,
* so that all the distorted pixels will be counted for the reference of white balance.
*/
isp_float_range_t blue_green_ratio; /*!< Blue to green ratio of the white patch. Range [0, 4.0)
* The ratio could be as wider as possible,
* so that all the distorted pixels will be counted for the reference of white balance.
*/
} white_patch; /*!< white patch configuration */
int intr_priority; /*!< The interrupt priority, range 0~7, if set to 0, the driver will try to allocate an interrupt with
* a relative low priority (1,2,3) otherwise the larger the higher, 7 is NMI.
*/
} esp_isp_awb_config_t;

/**
* @brief New an ISP AWB controller
*
* @param[in] isp_proc ISP Processor handle
* @param[in] awb_cfg Pointer to AWB config. Refer to ``esp_isp_awb_config_t``.
* @param[out] ret_hdl AWB 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_awb_controller(isp_proc_handle_t isp_proc, const esp_isp_awb_config_t *awb_cfg, isp_awb_ctlr_t *ret_hdl);

/**
* @brief Delete an ISP AWB controller
*
* @param[in] awb_ctlr AWB 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_awb_controller(isp_awb_ctlr_t awb_ctlr);

/**
* @brief Enable an ISP AWB controller
*
* @param[in] awb_ctlr AWB 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_awb_controller_enable(isp_awb_ctlr_t awb_ctlr);

/**
* @brief Disable an ISP AWB controller
*
* @param[in] awb_ctlr AWB 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_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
* - 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_awb_cbs_t::on_statistics_done`
* - timeout_ms > 0: Wait for specified milliseconds, if not finished, then return timeout error
* @param[out] out_res AWB white patch statistics result
*
* @return
* - ESP_OK On success
* - ESP_ERR_TIMEOUT Wait for the result 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_awb_controller_get_oneshot_statistics(isp_awb_ctlr_t awb_ctlr, int timeout_ms, isp_awb_stat_result_t *out_res);

/**
* @brief Start AWB continuous statistics of the white patch in the window
* @note This function is an asynchronous and non-block function,
* it will start the continuous statistics and return immediately.
* You have to register the AWB callback and get the result from the callback event data.
*
* @param[in] awb_ctlr AWB 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_awb_controller_start_continuous_statistics(isp_awb_ctlr_t awb_ctlr);

/**
* @brief Stop AWB continuous statistics of the white patch in the window
*
* @param[in] awb_ctlr AWB 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_awb_controller_stop_continuous_statistics(isp_awb_ctlr_t awb_ctlr);

/**
* @brief Event data of callbacks
*/
typedef struct {
isp_awb_stat_result_t awb_result; /*!< The AWB white patch statistics result */
} esp_isp_awb_evt_data_t;

/**
* @brief Prototype of ISP AWB event callback
*
* @param[in] handle ISP AWB controller handle
* @param[in] edata ISP AWB event data
* @param[in] user_data User registered context, registered when in `esp_isp_awb_env_detector_register_event_callbacks()`
*
* @return Whether a high priority task is woken up by this function
*/
typedef bool (*esp_isp_awb_callback_t)(isp_awb_ctlr_t awb_ctlr, const esp_isp_awb_evt_data_t *edata, void *user_data);

/**
* @brief Group of ISP AWB callbacks
*
* @note These callbacks are all running in an ISR environment.
* @note When CONFIG_ISP_ISR_IRAM_SAFE 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_awb_callback_t on_statistics_done; ///< Event callback, invoked when white patches statistic done.
} esp_isp_awb_cbs_t;

/**
* @brief Register AWB 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_SAFE 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] awb_ctlr AWB 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_awb_register_event_callbacks(isp_awb_ctlr_t awb_ctlr, const esp_isp_awb_cbs_t *cbs, void *user_data);

#ifdef __cplusplus
}
#endif
41 changes: 41 additions & 0 deletions components/esp_driver_isp/include/driver/isp_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,42 @@
extern "C" {
#endif

/**
* @brief ISP unsigned integer range type
* @note Whether the edge value are included depends on the variable itself
*/
typedef struct {
uint32_t min; ///< Minimum unsigned int value
uint32_t max; ///< Maximum unsigned int value
} isp_u32_range_t;

/**
* @brief ISP float range type
* @note Whether the edge value are included depends on the variable itself
*/
typedef struct {
float min; ///< Minimum float value
float max; ///< Maximum float value
} 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
*/
typedef struct {
uint32_t white_patch_num; ///< white patch number that counted by AWB in the window
uint32_t sum_r; ///< The sum of R channel of these white patches
uint32_t sum_g; ///< The sum of G channel of these white patches
uint32_t sum_b; ///< The sum of B channel of these white patches
} isp_awb_stat_result_t;

/**
* @brief Type of ISP processor handle
*/
Expand All @@ -22,6 +58,11 @@ typedef struct isp_processor_t *isp_proc_handle_t;
*/
typedef struct isp_af_controller_t *isp_af_ctlr_t;

/**
* @brief Type of ISP AWB controller handle
*/
typedef struct isp_awb_controller_t *isp_awb_ctlr_t;

#ifdef __cplusplus
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ typedef struct isp_processor_t {
uint32_t v_res;
/* sub module contexts */
isp_af_ctlr_t af_ctlr[SOC_ISP_AF_CTLR_NUMS];
isp_awb_ctlr_t awb_ctlr;
isp_fsm_t bf_fsm;
} isp_processor_t;
#endif
Expand Down
Loading

0 comments on commit ad57a47

Please sign in to comment.