feat(isp_ccm): support isp color correction matrix

This commit is contained in:
laokaiyao
2024-06-01 01:50:25 +08:00
parent 391aabf73f
commit 251fb331d2
15 changed files with 295 additions and 4 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"
@@ -178,7 +178,7 @@ typedef struct {
/**
* @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] user_data User registered context, registered when in `esp_isp_af_env_detector_register_event_callbacks()`
*
@@ -164,7 +164,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));
}