Merge branch 'feature/support_isp_ccm_v5.3' into 'release/v5.3'

feat(isp_ccm): support isp color correction matrix (v5.3)

See merge request espressif/esp-idf!31608
This commit is contained in:
morris
2024-07-31 18:59:44 +08:00
14 changed files with 292 additions and 1 deletions
+1
View File
@@ -11,6 +11,7 @@ set(requires)
if(CONFIG_SOC_ISP_SUPPORTED)
list(APPEND srcs "src/isp_core.c"
"src/isp_af.c"
"src/isp_ccm.c"
"src/isp_awb.c")
endif()
@@ -15,3 +15,4 @@
#include "driver/isp_af.h"
#include "driver/isp_awb.h"
#include "driver/isp_bf.h"
#include "driver/isp_ccm.h"
@@ -177,7 +177,7 @@ typedef struct {
/**
* @brief Prototype of ISP AWB event callback
*
* @param[in] handle ISP AWB controller handle
* @param[in] awb_ctlr 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()`
*
@@ -0,0 +1,70 @@
/*
* 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 Color Correction Matrix configurations
*
*/
typedef struct {
float matrix[ISP_CCM_DIMENSION][ISP_CCM_DIMENSION]; /*!< The color correction matrix in float, range (-4.0, 4.0) */
bool saturation; /*!< Whether to use saturation when the float data in the matrix is out of the range,
* For example, if one of the matrix data is 5.0,
* When saturation is true, and final value will be limited to 4.0, and won't rise error
* When saturation is false, `esp_isp_ccm_configure` will rise ESP_ERR_INVALID_ARG error
*/
} esp_isp_ccm_config_t;
/**
* @brief ISP Color Correction Matrix (CCM) configuration
*
* @note This function is allowed to be called before or after `esp_isp_ccm_enable`,
* but it only takes effect until `esp_isp_ccm_enable` is called
*
* @param[in] proc Processor handle
* @param[in] ccm_cfg CCM configurations, set NULL to de-configure the ISP CCM
*
* @return
* - ESP_OK On success
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid
*/
esp_err_t esp_isp_ccm_configure(isp_proc_handle_t proc, const esp_isp_ccm_config_t *ccm_cfg);
/**
* @brief Enable ISP CCM function
*
* @param[in] proc Processor handle
*
* @return
* - ESP_OK On success
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
*/
esp_err_t esp_isp_ccm_enable(isp_proc_handle_t proc);
/**
* @brief Disable ISP CCM function
*
* @param[in] proc Processor handle
*
* @return
* - ESP_OK On success
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
*/
esp_err_t esp_isp_ccm_disable(isp_proc_handle_t proc);
#ifdef __cplusplus
}
#endif
+55
View File
@@ -0,0 +1,55 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <esp_types.h>
#include "esp_log.h"
#include "esp_check.h"
#include "freertos/FreeRTOS.h"
#include "driver/isp_core.h"
#include "driver/isp_ccm.h"
#include "esp_private/isp_private.h"
static const char *TAG = "ISP_CCM";
/*---------------------------------------------------------------
CCM
---------------------------------------------------------------*/
esp_err_t esp_isp_ccm_configure(isp_proc_handle_t proc, const esp_isp_ccm_config_t *ccm_cfg)
{
ESP_RETURN_ON_FALSE(proc && ccm_cfg, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
bool ret = true;
portENTER_CRITICAL(&proc->spinlock);
ret = isp_hal_ccm_set_matrix(&proc->hal, ccm_cfg->saturation, ccm_cfg->matrix);
portEXIT_CRITICAL(&proc->spinlock);
ESP_RETURN_ON_FALSE(ret, ESP_ERR_INVALID_ARG, TAG, "invalid argument: ccm matrix contain NaN or out of range");
return ESP_OK;
}
esp_err_t esp_isp_ccm_enable(isp_proc_handle_t proc)
{
ESP_RETURN_ON_FALSE(proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
portENTER_CRITICAL(&proc->spinlock);
isp_ll_ccm_clk_enable(proc->hal.hw, true);
isp_ll_ccm_enable(proc->hal.hw, true);
portEXIT_CRITICAL(&proc->spinlock);
return ESP_OK;
}
esp_err_t esp_isp_ccm_disable(isp_proc_handle_t proc)
{
ESP_RETURN_ON_FALSE(proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
portENTER_CRITICAL(&proc->spinlock);
isp_ll_ccm_enable(proc->hal.hw, false);
isp_ll_ccm_clk_enable(proc->hal.hw, false);
portEXIT_CRITICAL(&proc->spinlock);
return ESP_OK;
}
@@ -118,3 +118,38 @@ TEST_CASE("ISP AWB driver basic function", "[isp]")
TEST_ESP_OK(esp_isp_disable(isp_proc));
TEST_ESP_OK(esp_isp_del_processor(isp_proc));
}
TEST_CASE("ISP CCM 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));
esp_isp_ccm_config_t ccm_cfg = {
.matrix = {
{5.0, 0.0, 0.0},
{0.0, 1.0, 0.0},
{0.0, 0.0, 1.0}
},
.saturation = false,
};
// Out of range case
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_isp_ccm_configure(isp_proc, &ccm_cfg));
// saturation case
ccm_cfg.saturation = true;
TEST_ESP_OK(esp_isp_ccm_configure(isp_proc, &ccm_cfg));
TEST_ESP_OK(esp_isp_ccm_enable(isp_proc));
// Allow to be called after enabled
ccm_cfg.matrix[0][0] = -1.1;
TEST_ESP_OK(esp_isp_ccm_configure(isp_proc, &ccm_cfg));
TEST_ESP_OK(esp_isp_ccm_disable(isp_proc));
TEST_ESP_OK(esp_isp_disable(isp_proc));
TEST_ESP_OK(esp_isp_del_processor(isp_proc));
}
@@ -100,6 +100,22 @@ typedef union {
uint32_t val;
} isp_ll_awb_rgb_ratio_t;
/*---------------------------------------------------------------
CCM
---------------------------------------------------------------*/
#define ISP_LL_CCM_MATRIX_INT_BITS (2)
#define ISP_LL_CCM_MATRIX_FRAC_BITS (10)
#define ISP_LL_CCM_MATRIX_TOT_BITS (ISP_LL_CCM_MATRIX_INT_BITS + ISP_LL_CCM_MATRIX_FRAC_BITS + 1) // including one sign bit
typedef union {
struct {
uint32_t fraction: ISP_LL_AWB_RGB_RATIO_FRAC_BITS;
uint32_t integer: ISP_LL_AWB_RGB_RATIO_INT_BITS;
uint32_t sign: 1;
};
uint32_t val;
} isp_ll_ccm_gain_t;
/**
* @brief Env monitor mode
*/
@@ -790,6 +806,25 @@ static inline void isp_ll_ccm_enable(isp_dev_t *hw, bool enable)
hw->cntl.ccm_en = enable;
}
/**
* @brief Set the Color Correction Matrix
*
* @param[in] hw Hardware instance address
* @param[in] fixed_point_matrix Color Correction Matrix in fixed-point format
*/
static inline void isp_ll_ccm_set_matrix(isp_dev_t *hw, isp_ll_ccm_gain_t fixed_point_matrix[ISP_CCM_DIMENSION][ISP_CCM_DIMENSION])
{
hw->ccm_coef0.ccm_rr = fixed_point_matrix[0][0].val;
hw->ccm_coef0.ccm_rg = fixed_point_matrix[0][1].val;
hw->ccm_coef1.ccm_rb = fixed_point_matrix[0][2].val;
hw->ccm_coef1.ccm_gr = fixed_point_matrix[1][0].val;
hw->ccm_coef3.ccm_gg = fixed_point_matrix[1][1].val;
hw->ccm_coef3.ccm_gb = fixed_point_matrix[1][2].val;
hw->ccm_coef4.ccm_br = fixed_point_matrix[2][0].val;
hw->ccm_coef4.ccm_bg = fixed_point_matrix[2][1].val;
hw->ccm_coef5.ccm_bb = fixed_point_matrix[2][2].val;
}
/*---------------------------------------------------------------
Color
---------------------------------------------------------------*/
+15
View File
@@ -88,6 +88,21 @@ 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);
/*---------------------------------------------------------------
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 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]);
/*---------------------------------------------------------------
AWB
---------------------------------------------------------------*/
+9
View File
@@ -100,6 +100,15 @@ typedef enum {
ISP_BF_EDGE_PADDING_MODE_CUSTOM_DATA, ///< Fill BF edge padding data with custom pixel data
} isp_bf_edge_padding_mode_t;
/*---------------------------------------------------------------
CCM
---------------------------------------------------------------*/
#if SOC_ISP_CCM_SUPPORTED
#define ISP_CCM_DIMENSION SOC_ISP_CCM_DIMENSION ///< ISP Color Correction Matrix dimension
#else
#define ISP_CCM_DIMENSION 0 ///< Not support CCM
#endif
/*---------------------------------------------------------------
AWB
---------------------------------------------------------------*/
+25
View File
@@ -70,6 +70,31 @@ uint32_t isp_hal_check_clear_intr_event(const isp_hal_context_t *hal, uint32_t m
return triggered_events;
}
/*---------------------------------------------------------------
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])
{
isp_ll_ccm_gain_t fp_matrix[ISP_CCM_DIMENSION][ISP_CCM_DIMENSION] = {};
hal_utils_fixed_point_t fp_cfg = {
.int_bit = ISP_LL_CCM_MATRIX_INT_BITS,
.frac_bit = ISP_LL_CCM_MATRIX_FRAC_BITS,
.saturation = saturation,
};
int err_level = saturation ? -1 : 0;
/* Transfer the float type to fixed point */
for (int i = 0; i < ISP_CCM_DIMENSION; i++) {
for (int j = 0; j < ISP_CCM_DIMENSION; j++) {
if (hal_utils_float_to_fixed_point_32b(flt_matrix[i][j], &fp_cfg, &fp_matrix[i][j].val) < err_level) {
return false;
}
}
}
isp_ll_ccm_set_matrix(hal->hw, fp_matrix);
return true;
}
/*---------------------------------------------------------------
AWB
---------------------------------------------------------------*/
@@ -803,6 +803,10 @@ config SOC_ISP_BF_SUPPORTED
bool
default y
config SOC_ISP_CCM_SUPPORTED
bool
default y
config SOC_ISP_DVP_SUPPORTED
bool
default y
@@ -835,6 +839,10 @@ config SOC_ISP_BF_TEMPLATE_Y_NUMS
int
default 3
config SOC_ISP_CCM_DIMENSION
int
default 3
config SOC_ISP_DVP_DATA_WIDTH_MAX
int
default 16
@@ -321,6 +321,7 @@
/*-------------------------- ISP CAPS ----------------------------------------*/
#define SOC_ISP_BF_SUPPORTED 1
#define SOC_ISP_CCM_SUPPORTED 1
#define SOC_ISP_DVP_SUPPORTED 1
#define SOC_ISP_NUMS 1U
@@ -330,6 +331,7 @@
#define SOC_ISP_SHARE_CSI_BRG 1
#define SOC_ISP_BF_TEMPLATE_X_NUMS 3
#define SOC_ISP_BF_TEMPLATE_Y_NUMS 3
#define SOC_ISP_CCM_DIMENSION 3
#define SOC_ISP_DVP_DATA_WIDTH_MAX 16
/*-------------------------- LEDC CAPS ---------------------------------------*/