diff --git a/components/esp_driver_isp/CMakeLists.txt b/components/esp_driver_isp/CMakeLists.txt index ab7761edb6..57728bf667 100644 --- a/components/esp_driver_isp/CMakeLists.txt +++ b/components/esp_driver_isp/CMakeLists.txt @@ -22,6 +22,10 @@ if(CONFIG_SOC_ISP_BF_SUPPORTED) list(APPEND srcs "src/isp_bf.c") endif() +if(CONFIG_SOC_ISP_BLC_SUPPORTED) + list(APPEND srcs "src/isp_blc.c") +endif() + if(CONFIG_SOC_ISP_DEMOSAIC_SUPPORTED) list(APPEND srcs "src/isp_demosaic.c") endif() diff --git a/components/esp_driver_isp/include/driver/isp.h b/components/esp_driver_isp/include/driver/isp.h index 235aca350e..73f6fbd465 100644 --- a/components/esp_driver_isp/include/driver/isp.h +++ b/components/esp_driver_isp/include/driver/isp.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -16,10 +16,11 @@ #include "driver/isp_af.h" #include "driver/isp_awb.h" #include "driver/isp_bf.h" +#include "driver/isp_blc.h" #include "driver/isp_ccm.h" +#include "driver/isp_color.h" #include "driver/isp_demosaic.h" #include "driver/isp_gamma.h" #include "driver/isp_hist.h" -#include "driver/isp_sharpen.h" -#include "driver/isp_color.h" #include "driver/isp_lsc.h" +#include "driver/isp_sharpen.h" diff --git a/components/esp_driver_isp/include/driver/isp_blc.h b/components/esp_driver_isp/include/driver/isp_blc.h new file mode 100644 index 0000000000..d4a9bd8120 --- /dev/null +++ b/components/esp_driver_isp/include/driver/isp_blc.h @@ -0,0 +1,112 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "esp_err.h" +#include "driver/isp_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*--------------------------------------------------------------- + BLC (Black Level Correction) +---------------------------------------------------------------*/ +/** + * @brief ISP BLC threshold configurations + */ +typedef struct { + uint8_t top_left_chan_thresh; ///< Black level threshold for top left channel of the raw Bayer image + uint8_t top_right_chan_thresh; ///< Black level threshold for top right channel of the raw Bayer image + uint8_t bottom_left_chan_thresh; ///< Black level threshold for bottom left channel of the raw Bayer image + uint8_t bottom_right_chan_thresh; ///< Black level threshold for bottom right channel of the raw Bayer image +} esp_isp_blc_thresh_t; + +/** + * @brief ISP BLC stretch configurations + * + * Enable this can stretch the pixel value to 0~255 after black level correction + */ +typedef struct { + bool top_left_chan_stretch_en; ///< Enable stretch for top left channel of the raw Bayer image + bool top_right_chan_stretch_en; ///< Enable stretch for top right channel of the raw Bayer image + bool bottom_left_chan_stretch_en; ///< Enable stretch for bottom left channel of the raw Bayer image + bool bottom_right_chan_stretch_en; ///< Enable stretch for bottom right channel of the raw Bayer image +} esp_isp_blc_stretch_t; + +/** + * @brief ISP BLC configurations + */ +typedef struct { + isp_window_t window; ///< The sampling windows of BLC, only pixels within the window will be sampled + esp_isp_blc_thresh_t filter_threshold; ///< Black level threshold for each channel of the raw Bayer image + bool filter_enable; ///< Enable filter for BLC, if enabled, only pixels within the threshold will be sampled + esp_isp_blc_stretch_t stretch; ///< Stretch configurations for each channel of the raw Bayer image +} esp_isp_blc_config_t; + +/** + * @brief ISP BLC correction offset + */ +typedef struct { + uint32_t top_left_chan_offset; ///< Correction offset for top left channel of the raw Bayer image + uint32_t top_right_chan_offset; ///< Correction offset for top right channel of the raw Bayer image + uint32_t bottom_left_chan_offset; ///< Correction offset for bottom left channel of the raw Bayer image + uint32_t bottom_right_chan_offset; ///< Correction offset for bottom right channel of the raw Bayer image +} esp_isp_blc_offset_t; + +/** + * @brief ISP BLC configuration + * + * @note After calling this API, BLC doesn't take into effect until `esp_isp_blc_enable` is called + * + * @param[in] isp_proc Processor handle + * @param[in] config BLC configurations + * + * @return + * - ESP_OK On success + * - ESP_ERR_INVALID_STATE Not allowed to be called under current state + * - ESP_ERR_INVALID_ARG If the combination of arguments is invalid + * - ESP_ERR_NOT_SUPPORTED Not supported + */ +esp_err_t esp_isp_blc_configure(isp_proc_handle_t isp_proc, const esp_isp_blc_config_t *config); + +/** + * @brief Enable ISP BLC function + * + * @param[in] isp_proc Processor 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_blc_enable(isp_proc_handle_t isp_proc); + +/** + * @brief Set the correction offset of ISP BLC function + * + * @param[in] isp_proc Processor handle + * @param[in] offset Correction offset + */ +esp_err_t esp_isp_blc_set_correction_offset(isp_proc_handle_t isp_proc, esp_isp_blc_offset_t *offset); + +/** + * @brief Disable ISP BLC function + * + * @param[in] isp_proc Processor 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_blc_disable(isp_proc_handle_t isp_proc); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_driver_isp/include/driver/isp_lsc.h b/components/esp_driver_isp/include/driver/isp_lsc.h index 68ef165955..693145eaa8 100644 --- a/components/esp_driver_isp/include/driver/isp_lsc.h +++ b/components/esp_driver_isp/include/driver/isp_lsc.h @@ -14,6 +14,10 @@ extern "C" { #endif +/*--------------------------------------------------------------- + LSC (Lens Shading Correction) +---------------------------------------------------------------*/ + /** * @brief LSC Gain array */ diff --git a/components/esp_driver_isp/include/esp_private/isp_private.h b/components/esp_driver_isp/include/esp_private/isp_private.h index 7bcb151c1d..452d3c2323 100644 --- a/components/esp_driver_isp/include/esp_private/isp_private.h +++ b/components/esp_driver_isp/include/esp_private/isp_private.h @@ -77,6 +77,7 @@ typedef struct isp_processor_t { isp_fsm_t sharpen_fsm; isp_fsm_t color_fsm; isp_fsm_t lsc_fsm; + isp_fsm_t blc_fsm; esp_isp_evt_cbs_t cbs; void *user_data; diff --git a/components/esp_driver_isp/src/isp_blc.c b/components/esp_driver_isp/src/isp_blc.c new file mode 100644 index 0000000000..bad515da5e --- /dev/null +++ b/components/esp_driver_isp/src/isp_blc.c @@ -0,0 +1,103 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include +#include "sdkconfig.h" +#include "esp_log.h" +#include "esp_check.h" +#include "freertos/FreeRTOS.h" +#include "driver/isp_core.h" +#include "driver/isp_blc.h" +#include "esp_private/isp_private.h" +#include "hal/efuse_hal.h" +#include "soc/chip_revision.h" + +/*--------------------------------------------------------------- + BLC +---------------------------------------------------------------*/ + +static const char *TAG = "ISP_BLC"; + +esp_err_t esp_isp_blc_configure(isp_proc_handle_t isp_proc, const esp_isp_blc_config_t *config) +{ +#if CONFIG_IDF_TARGET_ESP32P4 + unsigned chip_version = efuse_hal_chip_revision(); + if (!ESP_CHIP_REV_ABOVE(chip_version, 300)) { + ESP_RETURN_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, TAG, "BLC is not supported on ESP32P4 chips prior than v3.0"); + } +#endif + + ESP_RETURN_ON_FALSE(isp_proc && config, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); + ESP_RETURN_ON_FALSE(isp_proc->blc_fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "blc is enabled already"); + ESP_RETURN_ON_FALSE(config->window.top_left.x < config->window.btm_right.x, ESP_ERR_INVALID_ARG, TAG, "invalid window x coordinates"); + ESP_RETURN_ON_FALSE(config->window.top_left.y < config->window.btm_right.y, ESP_ERR_INVALID_ARG, TAG, "invalid window y coordinates"); + ESP_RETURN_ON_FALSE(config->window.btm_right.x <= isp_proc->h_res, ESP_ERR_INVALID_ARG, TAG, "window exceeds horizontal resolution"); + ESP_RETURN_ON_FALSE(config->window.btm_right.y <= isp_proc->v_res, ESP_ERR_INVALID_ARG, TAG, "window exceeds vertical resolution"); + + // Configure clock control mode + isp_ll_blc_set_clk_ctrl_mode(isp_proc->hal.hw, ISP_LL_PIPELINE_CLK_CTRL_AUTO); + + // Configure sampling window + isp_ll_blc_set_window(isp_proc->hal.hw, + config->window.top_left.x, config->window.top_left.y, + config->window.btm_right.x, config->window.btm_right.y); + + if (config->filter_enable) { + // Configure threshold values for each channel + isp_ll_blc_set_filter_threshold(isp_proc->hal.hw, config->filter_threshold.top_left_chan_thresh, config->filter_threshold.top_right_chan_thresh, config->filter_threshold.bottom_left_chan_thresh, config->filter_threshold.bottom_right_chan_thresh); + isp_ll_blc_enable_filter(isp_proc->hal.hw, true); + } else { + isp_ll_blc_enable_filter(isp_proc->hal.hw, false); + } + + // Configure stretch enable for each channel + isp_ll_blc_enable_stretch(isp_proc->hal.hw, config->stretch.top_left_chan_stretch_en, config->stretch.top_right_chan_stretch_en, config->stretch.bottom_left_chan_stretch_en, config->stretch.bottom_right_chan_stretch_en); + + return ESP_OK; +} + +esp_err_t esp_isp_blc_enable(isp_proc_handle_t isp_proc) +{ + ESP_RETURN_ON_FALSE(isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); + ESP_RETURN_ON_FALSE(isp_proc->blc_fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "blc is enabled already"); + + // Enable BLC module + isp_ll_blc_enable(isp_proc->hal.hw, true); + isp_proc->blc_fsm = ISP_FSM_ENABLE; + + ESP_LOGD(TAG, "BLC enabled"); + return ESP_OK; +} + +esp_err_t esp_isp_blc_set_correction_offset(isp_proc_handle_t isp_proc, esp_isp_blc_offset_t *offset) +{ + ESP_RETURN_ON_FALSE(isp_proc && offset, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); + ESP_RETURN_ON_FALSE(isp_proc->blc_fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "blc isn't enabled yet"); + + // Set correction offset for each channel + isp_ll_blc_set_correction_offset(isp_proc->hal.hw, offset->top_left_chan_offset, offset->top_right_chan_offset, offset->bottom_left_chan_offset, offset->bottom_right_chan_offset); + + ESP_LOGD(TAG, "BLC correction offset set: TL=%"PRIu32", TR=%"PRIu32", BL=%"PRIu32", BR=%"PRIu32, + offset->top_left_chan_offset, offset->top_right_chan_offset, + offset->bottom_left_chan_offset, offset->bottom_right_chan_offset); + + return ESP_OK; +} + +esp_err_t esp_isp_blc_disable(isp_proc_handle_t isp_proc) +{ + ESP_RETURN_ON_FALSE(isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); + ESP_RETURN_ON_FALSE(isp_proc->blc_fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "blc isn't enabled yet"); + + // Disable BLC module + isp_ll_blc_enable(isp_proc->hal.hw, false); + isp_proc->blc_fsm = ISP_FSM_INIT; + + ESP_LOGD(TAG, "BLC disabled"); + return ESP_OK; +} diff --git a/components/esp_driver_isp/src/isp_lsc.c b/components/esp_driver_isp/src/isp_lsc.c index 8ebd459555..0d11a963d9 100644 --- a/components/esp_driver_isp/src/isp_lsc.c +++ b/components/esp_driver_isp/src/isp_lsc.c @@ -27,7 +27,7 @@ static const char *TAG = "ISP_LSC"; esp_err_t esp_isp_lsc_allocate_gain_array(isp_proc_handle_t isp_proc, esp_isp_lsc_gain_array_t *gain_array, size_t *out_array_size_per_channel) { - ESP_RETURN_ON_FALSE(isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); + ESP_RETURN_ON_FALSE(isp_proc && gain_array && out_array_size_per_channel, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); ESP_RETURN_ON_FALSE(isp_proc->lsc_fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "lsc is enabled already"); int num_grids_x_max = ISP_LSC_GET_GRIDS(ISP_LL_HSIZE_MAX); diff --git a/components/hal/esp32p4/include/hal/isp_ll.h b/components/hal/esp32p4/include/hal/isp_ll.h index 4c07d91fe1..b32ea0fb4a 100644 --- a/components/hal/esp32p4/include/hal/isp_ll.h +++ b/components/hal/esp32p4/include/hal/isp_ll.h @@ -859,6 +859,110 @@ static inline void isp_ll_bf_set_template(isp_dev_t *hw, uint8_t template_arr[SO hw->bf_gau1.gau_template22 = template_arr[2][2]; } +/*--------------------------------------------------------------- + BLC +---------------------------------------------------------------*/ +/** + * @brief Set BLC clock control mode + * + * @param[in] hw Hardware instance address + * @param[in] mode 'isp_ll_pipeline_clk_ctrl_t` + */ +static inline void isp_ll_blc_set_clk_ctrl_mode(isp_dev_t *hw, isp_ll_pipeline_clk_ctrl_t mode) +{ + hw->clk_en.clk_blc_force_on = mode; +} + +/** + * @brief Enable / Disable BLC + * + * @param[in] hw Hardware instance address + * @param[in] enable Enable / Disable + */ +static inline void isp_ll_blc_enable(isp_dev_t *hw, bool enable) +{ + hw->cntl.blc_en = enable; +} + +/** + * @brief Set BLC correction offset + * + * @param[in] hw Hardware instance address + * @param[in] top_left_chan_offset Correction offset for top left channel of the raw Bayer image + * @param[in] top_right_chan_offset Correction offset for top right channel of the raw Bayer image + * @param[in] bottom_left_chan_offset Correction offset for bottom left channel of the raw Bayer image + * @param[in] bottom_right_chan_offset Correction offset for bottom right channel of the raw Bayer image + */ +static inline void isp_ll_blc_set_correction_offset(isp_dev_t *hw, uint32_t top_left_chan_offset, uint32_t top_right_chan_offset, uint32_t bottom_left_chan_offset, uint32_t bottom_right_chan_offset) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->blc_value, blc_r0_value, top_left_chan_offset); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->blc_value, blc_r1_value, top_right_chan_offset); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->blc_value, blc_r2_value, bottom_left_chan_offset); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->blc_value, blc_r3_value, bottom_right_chan_offset); +} + +/** + * @brief Enable / Disable BLC stretch + * + * @param[in] hw Hardware instance address + * @param[in] top_left_chan_stretch_en Enable / Disable stretch for top left channel of the raw Bayer image + * @param[in] top_right_chan_stretch_en Enable / Disable stretch for top right channel of the raw Bayer image + * @param[in] bottom_left_chan_stretch_en Enable / Disable stretch for bottom left channel of the raw Bayer image + * @param[in] bottom_right_chan_stretch_en Enable / Disable stretch for bottom right channel of the raw Bayer image + */ +static inline void isp_ll_blc_enable_stretch(isp_dev_t *hw, bool top_left_chan_stretch_en, bool top_right_chan_stretch_en, bool bottom_left_chan_stretch_en, bool bottom_right_chan_stretch_en) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->blc_ctrl0, blc_r0_stretch, top_left_chan_stretch_en); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->blc_ctrl0, blc_r1_stretch, top_right_chan_stretch_en); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->blc_ctrl0, blc_r2_stretch, bottom_left_chan_stretch_en); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->blc_ctrl0, blc_r3_stretch, bottom_right_chan_stretch_en); +} + +/** + * @brief Set BLC window + * + * @param[in] hw Hardware instance address + * @param[in] x_start X start position + * @param[in] y_start Y start position + * @param[in] x_size X size + * @param[in] y_size Y size + */ +static inline void isp_ll_blc_set_window(isp_dev_t *hw, uint32_t x_start, uint32_t y_start, uint32_t x_size, uint32_t y_size) +{ + hw->blc_ctrl1.blc_window_top = y_start; + hw->blc_ctrl1.blc_window_left = x_start; + hw->blc_ctrl1.blc_window_vnum = y_size; + hw->blc_ctrl1.blc_window_hnum = x_size; +} + +/** + * @brief Set BLC filter threshold + * + * @param[in] hw Hardware instance address + * @param[in] top_left_chan_thresh Filter threshold for top left channel of the raw Bayer image + * @param[in] top_right_chan_thresh Filter threshold for top right channel of the raw Bayer image + * @param[in] bottom_left_chan_thresh Filter threshold for bottom left channel of the raw Bayer image + * @param[in] bottom_right_chan_thresh Filter threshold for bottom right channel of the raw Bayer image + */ +static inline void isp_ll_blc_set_filter_threshold(isp_dev_t *hw, uint32_t top_left_chan_thresh, uint32_t top_right_chan_thresh, uint32_t bottom_left_chan_thresh, uint32_t bottom_right_chan_thresh) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->blc_ctrl2, blc_r0_th, top_left_chan_thresh); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->blc_ctrl2, blc_r1_th, top_right_chan_thresh); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->blc_ctrl2, blc_r2_th, bottom_left_chan_thresh); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->blc_ctrl2, blc_r3_th, bottom_right_chan_thresh); +} + +/** + * @brief Enable / Disable BLC filter + * + * @param[in] hw Hardware instance address + * @param[in] enable Enable / Disable + */ +static inline void isp_ll_blc_enable_filter(isp_dev_t *hw, bool enable) +{ + hw->blc_ctrl1.blc_filter_en = enable; +} + /*--------------------------------------------------------------- CCM ---------------------------------------------------------------*/ diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index 3ca4fdf4d7..b197f27a26 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -915,10 +915,18 @@ config SOC_ISP_BF_SUPPORTED bool default y +config SOC_ISP_BLC_SUPPORTED + bool + default y + config SOC_ISP_CCM_SUPPORTED bool default y +config SOC_ISP_COLOR_SUPPORTED + bool + default y + config SOC_ISP_DEMOSAIC_SUPPORTED bool default y @@ -927,18 +935,14 @@ config SOC_ISP_DVP_SUPPORTED bool default y -config SOC_ISP_SHARPEN_SUPPORTED - bool - default y - -config SOC_ISP_COLOR_SUPPORTED - bool - default y - config SOC_ISP_LSC_SUPPORTED bool default y +config SOC_ISP_SHARPEN_SUPPORTED + bool + default y + config SOC_ISP_SHARE_CSI_BRG bool default y diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index e916122d65..beedc922a6 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -353,12 +353,13 @@ /*-------------------------- ISP CAPS ----------------------------------------*/ #define SOC_ISP_BF_SUPPORTED 1 +#define SOC_ISP_BLC_SUPPORTED 1 #define SOC_ISP_CCM_SUPPORTED 1 +#define SOC_ISP_COLOR_SUPPORTED 1 #define SOC_ISP_DEMOSAIC_SUPPORTED 1 #define SOC_ISP_DVP_SUPPORTED 1 -#define SOC_ISP_SHARPEN_SUPPORTED 1 -#define SOC_ISP_COLOR_SUPPORTED 1 #define SOC_ISP_LSC_SUPPORTED 1 +#define SOC_ISP_SHARPEN_SUPPORTED 1 #define SOC_ISP_SHARE_CSI_BRG 1 #define SOC_ISP_NUMS 1U diff --git a/docs/doxygen/Doxyfile_esp32p4 b/docs/doxygen/Doxyfile_esp32p4 index 3d50cda7fa..bf64bf8cb7 100644 --- a/docs/doxygen/Doxyfile_esp32p4 +++ b/docs/doxygen/Doxyfile_esp32p4 @@ -37,6 +37,7 @@ INPUT += \ $(PROJECT_PATH)/components/esp_driver_isp/include/driver/isp_awb.h \ $(PROJECT_PATH)/components/esp_driver_isp/include/driver/isp_ccm.h \ $(PROJECT_PATH)/components/esp_driver_isp/include/driver/isp_bf.h \ + $(PROJECT_PATH)/components/esp_driver_isp/include/driver/isp_blc.h \ $(PROJECT_PATH)/components/esp_driver_isp/include/driver/isp_lsc.h \ $(PROJECT_PATH)/components/esp_driver_isp/include/driver/isp_demosaic.h \ $(PROJECT_PATH)/components/esp_driver_isp/include/driver/isp_sharpen.h \ diff --git a/docs/en/api-reference/peripherals/isp.rst b/docs/en/api-reference/peripherals/isp.rst index 80ec3d5cce..34914a6c1f 100644 --- a/docs/en/api-reference/peripherals/isp.rst +++ b/docs/en/api-reference/peripherals/isp.rst @@ -23,6 +23,7 @@ Terminology - AE: Auto exposure - HIST: Histogram - BF: Bayer noise filter + - BLC: Black Level Correction - LSC: Lens Shading Correction - CCM: Color correction matrix @@ -46,7 +47,7 @@ ISP Pipeline isp_chs [label = "Contrast &\n Hue & Saturation", width = 150, height = 70]; isp_yuv [label = "YUV Limit\n YUB2RGB", width = 120, height = 70]; - isp_header -> BF -> LSC -> Demosaic -> CCM -> Gamma -> RGB2YUV -> SHARP -> isp_chs -> isp_yuv -> isp_tail; + isp_header -> BLC -> BF -> LSC -> Demosaic -> CCM -> Gamma -> RGB2YUV -> SHARP -> isp_chs -> isp_yuv -> isp_tail; LSC -> HIST Demosaic -> AWB @@ -70,6 +71,7 @@ The ISP driver offers following services: - :ref:`isp-ae-statistics` - covers how to get AE statistics one-shot or continuously. - :ref:`isp-hist-statistics` - covers how to get histogram statistics one-shot or continuously. - :ref:`isp-bf` - covers how to enable and configure BF function. +- :ref:`isp-blc` - covers how to enable and configure BLC function. - :ref:`isp-lsc` - covers how to enable and configure LSC function. - :ref:`isp-ccm-config` - covers how to configure the CCM. - :ref:`isp-demosaic` - covers how to configure the Demosaic function. @@ -516,6 +518,63 @@ After calling :cpp:func:`esp_isp_bf_configure`, you need to enable the ISP BF co Calling :cpp:func:`esp_isp_bf_disable` does the opposite, that is, put the driver back to the **init** state. +.. _isp-blc: + +ISP BLC Controller +^^^^^^^^^^^^^^^^^^ + +Black Level Correction (BLC) aims for the issues caused by the uneven black level of the image. + +Calling :cpp:func:`esp_isp_blc_configure` to configure the BLC module to do the correction. + +.. code-block:: c + + esp_isp_blc_config_t blc_config = { + .window = { + .top_left = { + .x = 0, + .y = 0, + }, + .btm_right = { + .x = CONFIG_EXAMPLE_MIPI_CSI_DISP_HRES, + .y = CONFIG_EXAMPLE_MIPI_CSI_DISP_VRES, + }, + }, + .filter_enable = true, + .filter_threshold = { + .top_left_chan_thresh = 128, + .top_right_chan_thresh = 128, + .bottom_left_chan_thresh = 128, + .bottom_right_chan_thresh = 128, + }, + .stretch = { + .top_left_chan_stretch_en = true, + .top_right_chan_stretch_en = true, + .bottom_left_chan_stretch_en = true, + .bottom_right_chan_stretch_en = true, + }, + }; + ESP_ERROR_CHECK(esp_isp_blc_configure(isp_proc, &blc_config)); + ESP_ERROR_CHECK(esp_isp_blc_enable(isp_proc)); + +After calling :cpp:func:`esp_isp_blc_configure`, you need to enable the ISP BLC controller by calling :cpp:func:`esp_isp_blc_enable`. This function: + +* Switches the driver state from **init** to **enable**. + +Calling :cpp:func:`esp_isp_blc_disable` does the opposite, that is, put the driver back to the **init** state. + +Calling :cpp:func:`esp_isp_blc_set_correction_offset` to set the BLC correction offset. + +.. code-block:: c + + esp_isp_blc_offset_t blc_offset = { + .top_left_chan_offset = 20, + .top_right_chan_offset = 20, + .bottom_left_chan_offset = 20, + .bottom_right_chan_offset = 20, + }; + ESP_ERROR_CHECK(esp_isp_blc_set_correction_offset(isp_proc, &blc_offset)); + .. _isp-lsc: @@ -861,6 +920,7 @@ API Reference .. include-build-file:: inc/isp_ae.inc .. include-build-file:: inc/isp_awb.inc .. include-build-file:: inc/isp_bf.inc +.. include-build-file:: inc/isp_blc.inc .. include-build-file:: inc/isp_lsc.inc .. include-build-file:: inc/isp_ccm.inc .. include-build-file:: inc/isp_demosaic.inc diff --git a/docs/zh_CN/api-reference/peripherals/isp.rst b/docs/zh_CN/api-reference/peripherals/isp.rst index 78b1f0b83c..b90aae512f 100644 --- a/docs/zh_CN/api-reference/peripherals/isp.rst +++ b/docs/zh_CN/api-reference/peripherals/isp.rst @@ -23,6 +23,7 @@ - AE:自动曝光 - HIST:直方图 - BF:拜耳域降噪 + - BLC:黑电平校正 - LSC:镜头阴影校正 - CCM:色彩校正矩阵 @@ -46,7 +47,7 @@ ISP 流水线 isp_chs [label = "对比度 &\n 色调 & 饱和度", width = 150, height = 70]; isp_yuv [label = "YUV 限制\n YUB2RGB", width = 120, height = 70]; - isp_header -> BF -> LSC -> 去马赛克 -> CCM -> gamma 校正 -> RGB 转 YUV -> 锐化 -> isp_chs -> isp_yuv -> isp_tail; + isp_header -> BLC -> BF -> LSC -> 去马赛克 -> CCM -> gamma 校正 -> RGB 转 YUV -> 锐化 -> isp_chs -> isp_yuv -> isp_tail; LSC -> HIST 去马赛克 -> AWB @@ -70,6 +71,7 @@ ISP 驱动程序提供以下服务: - :ref:`isp-ae-statistics` - 涵盖如何单次或连续获取 AE 统计信息。 - :ref:`isp-hist-statistics` - 涵盖如何单次或连续获取直方图统计信息。 - :ref:`isp-bf` - 涵盖如何启用和配置 BF 功能。 +- :ref:`isp-blc` - 涵盖如何启用和配置 BLC 功能。 - :ref:`isp-lsc` - 涵盖如何启用和配置 LSC 功能。 - :ref:`isp-ccm-config` - 涵盖如何配置 CCM。 - :ref:`isp-demosaic` - 涵盖如何配置去马赛克功能。 @@ -517,6 +519,64 @@ ISP BF 控制器 调用 :cpp:func:`esp_isp_bf_disable` 函数会执行相反的操作,即将驱动程序恢复到 **init** 状态。 +.. _isp-blc: + +ISP BLC 控制器 +~~~~~~~~~~~~~~ + +黑电平校正 (BLC) 旨在解决因相机传感器中光线折射不均而引起的问题。 + +可调用 :cpp:func:`esp_isp_blc_configure` 函数配置 BLC 模块以进行校正。 + +.. code-block:: c + + esp_isp_blc_config_t blc_config = { + .window = { + .top_left = { + .x = 0, + .y = 0, + }, + .btm_right = { + .x = CONFIG_EXAMPLE_MIPI_CSI_DISP_HRES, + .y = CONFIG_EXAMPLE_MIPI_CSI_DISP_VRES, + }, + }, + .filter_enable = true, + .filter_threshold = { + .top_left_chan_thresh = 128, + .top_right_chan_thresh = 128, + .bottom_left_chan_thresh = 128, + .bottom_right_chan_thresh = 128, + }, + .stretch = { + .top_left_chan_stretch_en = true, + .top_right_chan_stretch_en = true, + .bottom_left_chan_stretch_en = true, + .bottom_right_chan_stretch_en = true, + }, + }; + ESP_ERROR_CHECK(esp_isp_blc_configure(isp_proc, &blc_config)); + ESP_ERROR_CHECK(esp_isp_blc_enable(isp_proc)); + +调用 :cpp:func:`esp_isp_blc_configure` 后,需要通过调用 :cpp:func:`esp_isp_blc_enable` 来启用 ISP BLC 控制器。此函数: + +* 将驱动程序状态从 **init** 切换到 **enable**。 + +调用 :cpp:func:`esp_isp_blc_disable` 函数会执行相反的操作,即将驱动程序恢复到 **init** 状态。 + +调用 :cpp:func:`esp_isp_blc_set_correction_offset` 函数来设置 BLC 校正偏移量。 + +.. code-block:: c + + esp_isp_blc_offset_t blc_offset = { + .top_left_chan_offset = 20, + .top_right_chan_offset = 20, + .bottom_left_chan_offset = 20, + .bottom_right_chan_offset = 20, + }; + ESP_ERROR_CHECK(esp_isp_blc_set_correction_offset(isp_proc, &blc_offset)); + + .. _isp-lsc: ISP LSC 控制器 @@ -861,6 +921,7 @@ API 参考 .. include-build-file:: inc/isp_ae.inc .. include-build-file:: inc/isp_awb.inc .. include-build-file:: inc/isp_bf.inc +.. include-build-file:: inc/isp_blc.inc .. include-build-file:: inc/isp_lsc.inc .. include-build-file:: inc/isp_ccm.inc .. include-build-file:: inc/isp_demosaic.inc diff --git a/examples/peripherals/isp/multi_pipelines/README.md b/examples/peripherals/isp/multi_pipelines/README.md index 16682631b5..719e29dac5 100644 --- a/examples/peripherals/isp/multi_pipelines/README.md +++ b/examples/peripherals/isp/multi_pipelines/README.md @@ -10,6 +10,7 @@ This example demonstrates how to use the ISP (image signal processor) to work wi - ISP AF (auto-focus) feature - ISP BF (bayer denoise) feature +- ISP BLC (black level correction) feature - ISP Sharpen feature - ISP Demosaic feature - ISP GAMMA feature diff --git a/examples/peripherals/isp/multi_pipelines/main/isp_dsi_main.c b/examples/peripherals/isp/multi_pipelines/main/isp_dsi_main.c index 018f522d61..79ac257074 100644 --- a/examples/peripherals/isp/multi_pipelines/main/isp_dsi_main.c +++ b/examples/peripherals/isp/multi_pipelines/main/isp_dsi_main.c @@ -303,6 +303,49 @@ void app_main(void) ESP_ERROR_CHECK(esp_isp_bf_configure(isp_proc, &bf_config)); ESP_ERROR_CHECK(esp_isp_bf_enable(isp_proc)); +#if CONFIG_ESP32P4_REV_MIN_FULL >= 300 + /** + * This piece of BLC code is to show how to use the BLC related APIs. + * Suggested way to calibrate the BLC is by covering the lens and record the raw data. + * Then, use the recorded data to calibrate the BLC. + */ + esp_isp_blc_config_t blc_config = { + .window = { + .top_left = { + .x = 0, + .y = 0, + }, + .btm_right = { + .x = CONFIG_EXAMPLE_MIPI_CSI_DISP_HRES, + .y = CONFIG_EXAMPLE_MIPI_CSI_DISP_VRES, + }, + }, + .filter_enable = true, + .filter_threshold = { + .top_left_chan_thresh = 128, + .top_right_chan_thresh = 128, + .bottom_left_chan_thresh = 128, + .bottom_right_chan_thresh = 128, + }, + .stretch = { + .top_left_chan_stretch_en = true, + .top_right_chan_stretch_en = true, + .bottom_left_chan_stretch_en = true, + .bottom_right_chan_stretch_en = true, + }, + }; + ESP_ERROR_CHECK(esp_isp_blc_configure(isp_proc, &blc_config)); + ESP_ERROR_CHECK(esp_isp_blc_enable(isp_proc)); + + esp_isp_blc_offset_t blc_offset = { + .top_left_chan_offset = 20, + .top_right_chan_offset = 20, + .bottom_left_chan_offset = 20, + .bottom_right_chan_offset = 20, + }; + ESP_ERROR_CHECK(esp_isp_blc_set_correction_offset(isp_proc, &blc_offset)); +#endif + esp_isp_demosaic_config_t demosaic_config = { .grad_ratio = { .integer = 2,