mirror of
https://github.com/espressif/esp-idf.git
synced 2025-09-30 19:19:21 +00:00
adc_cali: supported channel compensation of adc calibration on esp32c6
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
#include "esp_adc/adc_cali_scheme.h"
|
||||
#include "adc_cali_interface.h"
|
||||
#include "curve_fitting_coefficients.h"
|
||||
#include "esp_private/adc_share_hw_ctrl.h"
|
||||
|
||||
#if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
|
||||
#include "esp_efuse_rtc_calib.h"
|
||||
@@ -55,6 +56,7 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
adc_unit_t unit_id; ///< ADC unit
|
||||
adc_channel_t chan; ///< ADC channel
|
||||
adc_atten_t atten; ///< ADC attenuation
|
||||
cali_chars_first_step_t chars_first_step; ///< Calibration first step characteristics
|
||||
cali_chars_second_step_t chars_second_step; ///< Calibration second step characteristics
|
||||
@@ -100,6 +102,7 @@ esp_err_t adc_cali_create_scheme_curve_fitting(const adc_cali_curve_fitting_conf
|
||||
//Set second step calibration context
|
||||
calc_second_step_coefficients(config, chars);
|
||||
chars->unit_id = config->unit_id;
|
||||
chars->chan = config->chan;
|
||||
chars->atten = config->atten;
|
||||
|
||||
*ret_handle = scheme;
|
||||
@@ -132,6 +135,16 @@ static esp_err_t cali_raw_to_voltage(void *arg, int raw, int *voltage)
|
||||
//pointers are checked in the upper layer
|
||||
|
||||
cali_chars_curve_fitting_t *ctx = arg;
|
||||
|
||||
#if SOC_ADC_CALIB_CHAN_COMPENS_SUPPORTED
|
||||
int chan_compensation = adc_get_hw_calibration_chan_compens(ctx->unit_id, ctx->chan, ctx->atten);
|
||||
raw -= chan_compensation;
|
||||
/* Limit the range */
|
||||
int max_val = (1L << SOC_ADC_RTC_MAX_BITWIDTH) - 1;
|
||||
raw = raw <= 0 ? 0 :
|
||||
raw > max_val ? max_val : raw;
|
||||
#endif // SOC_ADC_CALIB_CHAN_COMPENS_SUPPORTED
|
||||
|
||||
uint64_t v_cali_1 = (uint64_t)raw * ctx->chars_first_step.coeff_a / coeff_a_scaling + ctx->chars_first_step.coeff_b;
|
||||
int32_t error = get_reading_error(v_cali_1, &(ctx->chars_second_step), ctx->atten);
|
||||
|
||||
@@ -173,8 +186,9 @@ static void calc_first_step_coefficients(const adc_calib_info_t *parsed_data, ca
|
||||
static void calc_second_step_coefficients(const adc_cali_curve_fitting_config_t *config, cali_chars_curve_fitting_t *ctx)
|
||||
{
|
||||
ctx->chars_second_step.term_num = (config->atten == 3) ? 5 : 3;
|
||||
#if CONFIG_IDF_TARGET_ESP32C3
|
||||
//On esp32c3, ADC1 and ADC2 share the second step coefficients
|
||||
#if CONFIG_IDF_TARGET_ESP32C3 || SOC_ADC_PERIPH_NUM == 1
|
||||
// On esp32c3, ADC1 and ADC2 share the second step coefficients
|
||||
// And if the target only has 1 ADC peripheral, just use the ADC1 directly
|
||||
ctx->chars_second_step.coeff = &adc1_error_coef_atten;
|
||||
ctx->chars_second_step.sign = &adc1_error_sign;
|
||||
#else
|
||||
|
@@ -102,6 +102,12 @@ static __attribute__((constructor)) void adc_hw_calibration(void)
|
||||
* update this when bringing up the calibration on that chip
|
||||
*/
|
||||
adc_calc_hw_calibration_code(i, j);
|
||||
#if SOC_ADC_CALIB_CHAN_COMPENS_SUPPORTED
|
||||
/* Load the channel compensation from efuse */
|
||||
for (int k = 0; k < SOC_ADC_CHANNEL_NUM(i); k++) {
|
||||
adc_load_hw_calibration_chan_compens(i, k, j);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -173,7 +173,7 @@ esp_err_t adc_oneshot_read(adc_oneshot_unit_handle_t handle, adc_channel_t chan,
|
||||
adc_atten_t atten = adc_ll_get_atten(handle->unit_id, chan);
|
||||
adc_hal_calibration_init(handle->unit_id);
|
||||
adc_set_hw_calibration_code(handle->unit_id, atten);
|
||||
#endif
|
||||
#endif // SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
bool valid = false;
|
||||
valid = adc_oneshot_hal_convert(&(handle->hal), out_raw);
|
||||
sar_periph_ctrl_adc_oneshot_power_release();
|
||||
|
@@ -14,10 +14,9 @@
|
||||
* For each item, first element is the Coefficient, second element is the Multiple. (Coefficient / Multiple) is the real coefficient.
|
||||
*
|
||||
* @note {0,0} stands for unused item
|
||||
* @note In case of the overflow, these coeffcients are recorded as Absolute Value
|
||||
* @note In case of the overflow, these coefficients are recorded as Absolute Value
|
||||
* @note For atten0 ~ 2, error = (K0 * X^0) + (K1 * X^1) + (K2 * X^2); For atten3, error = (K0 * X^0) + (K1 * X^1) + (K2 * X^2) + (K3 * X^3) + (K4 * X^4);
|
||||
* @note Above formula is rewritten from the original documentation, please note that the coefficients are re-ordered.
|
||||
* @note ADC1 and ADC2 use same coeffients
|
||||
*/
|
||||
const uint64_t adc1_error_coef_atten[4][5][2] = {
|
||||
{{487166399931449, 1e16}, {6436483033201, 1e16}, {30410131806, 1e16}, {0, 0}, {0, 0}}, //atten0
|
||||
|
@@ -22,6 +22,7 @@ extern "C" {
|
||||
---------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
adc_unit_t unit_id; ///< ADC unit
|
||||
adc_channel_t chan; ///< ADC channel, for chips with SOC_ADC_CALIB_CHAN_COMPENS_SUPPORTED, calibration can be per channel
|
||||
adc_atten_t atten; ///< ADC attenuation
|
||||
adc_bitwidth_t bitwidth; ///< ADC raw output bitwidth
|
||||
} adc_cali_curve_fitting_config_t;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -149,7 +149,7 @@ static void s_adc_oneshot_with_sleep(adc_unit_t unit_id, adc_channel_t channel)
|
||||
bool do_calibration = false;
|
||||
adc_cali_handle_t cali_handle[TEST_ATTEN_NUMS] = {};
|
||||
for (int i = 0; i < TEST_ATTEN_NUMS; i++) {
|
||||
do_calibration = test_adc_calibration_init(unit_id, g_test_atten[i], SOC_ADC_RTC_MAX_BITWIDTH, &cali_handle[i]);
|
||||
do_calibration = test_adc_calibration_init(unit_id, channel, g_test_atten[i], SOC_ADC_RTC_MAX_BITWIDTH, &cali_handle[i]);
|
||||
}
|
||||
if (!do_calibration) {
|
||||
ESP_LOGW(TAG, "No efuse bits burnt, only test the regi2c analog register values");
|
||||
|
@@ -324,7 +324,7 @@ static float test_adc_oneshot_std(adc_atten_t atten, bool is_performance_test)
|
||||
//-------------ADC Calibration Init---------------//
|
||||
bool do_calibration = false;
|
||||
adc_cali_handle_t cali_handle = NULL;
|
||||
do_calibration = test_adc_calibration_init(ADC_UNIT_1, atten, ADC_BITWIDTH_DEFAULT, &cali_handle);
|
||||
do_calibration = test_adc_calibration_init(ADC_UNIT_1, channel, atten, ADC_BITWIDTH_DEFAULT, &cali_handle);
|
||||
if (!do_calibration) {
|
||||
ESP_LOGW(TAG, "calibration fail, jump calibration\n");
|
||||
}
|
||||
@@ -420,7 +420,7 @@ static void s_adc_cali_speed(adc_unit_t unit_id, adc_channel_t channel)
|
||||
bool do_calibration = false;
|
||||
adc_cali_handle_t cali_handle[TEST_ATTEN_NUMS] = {};
|
||||
for (int i = 0; i < TEST_ATTEN_NUMS; i++) {
|
||||
do_calibration = test_adc_calibration_init(unit_id, g_test_atten[i], SOC_ADC_RTC_MAX_BITWIDTH, &cali_handle[i]);
|
||||
do_calibration = test_adc_calibration_init(unit_id, channel, g_test_atten[i], SOC_ADC_RTC_MAX_BITWIDTH, &cali_handle[i]);
|
||||
}
|
||||
|
||||
if (!do_calibration) {
|
||||
|
@@ -39,7 +39,7 @@ adc_digi_iir_filter_coeff_t g_test_filter_coeff[TEST_FILTER_COEFF_NUMS] = {
|
||||
/*---------------------------------------------------------------
|
||||
ADC Calibration
|
||||
---------------------------------------------------------------*/
|
||||
bool test_adc_calibration_init(adc_unit_t unit, adc_atten_t atten, adc_bitwidth_t bitwidth, adc_cali_handle_t *out_handle)
|
||||
bool test_adc_calibration_init(adc_unit_t unit, adc_channel_t channel, adc_atten_t atten, adc_bitwidth_t bitwidth, adc_cali_handle_t *out_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
adc_cali_handle_t handle = NULL;
|
||||
@@ -49,6 +49,7 @@ bool test_adc_calibration_init(adc_unit_t unit, adc_atten_t atten, adc_bitwidth_
|
||||
ESP_LOGI(TAG, "calibration scheme version is %s", "Curve Fitting");
|
||||
adc_cali_curve_fitting_config_t cali_config = {
|
||||
.unit_id = unit,
|
||||
.chan = channel,
|
||||
.atten = atten,
|
||||
.bitwidth = bitwidth,
|
||||
};
|
||||
|
@@ -71,11 +71,11 @@ extern "C" {
|
||||
#define ADC_TEST_HIGH_VAL 3400
|
||||
#define ADC_TEST_HIGH_THRESH 200
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32C6 // TODO: IDF-5312
|
||||
#define ADC_TEST_LOW_VAL 2144
|
||||
#define ADC_TEST_LOW_THRESH 200
|
||||
#elif CONFIG_IDF_TARGET_ESP32C6
|
||||
#define ADC_TEST_LOW_VAL 0
|
||||
#define ADC_TEST_LOW_THRESH 15
|
||||
|
||||
#define ADC_TEST_HIGH_VAL 4081
|
||||
#define ADC_TEST_HIGH_VAL 3350
|
||||
#define ADC_TEST_HIGH_VAL_DMA 4081
|
||||
#define ADC_TEST_HIGH_THRESH 200
|
||||
|
||||
@@ -114,13 +114,17 @@ extern adc_digi_iir_filter_coeff_t g_test_filter_coeff[TEST_FILTER_COEFF_NUMS];
|
||||
/**
|
||||
* @brief Initialise ADC Calibration
|
||||
*
|
||||
* @param[out] out_handle ADC calibration handle
|
||||
* @param[in] unit ADC unit
|
||||
* @param[in] channel ADC channel
|
||||
* @param[in] atten ADC attenuation
|
||||
* @param[in] bitwidth ADC bit width
|
||||
* @param[out] out_handle ADC calibration handle
|
||||
*
|
||||
* @return
|
||||
* - True Calibration success
|
||||
* - False Calibration fail
|
||||
*/
|
||||
bool test_adc_calibration_init(adc_unit_t unit, adc_atten_t atten, adc_bitwidth_t bitwidth, adc_cali_handle_t *out_handle);
|
||||
bool test_adc_calibration_init(adc_unit_t unit, adc_channel_t channel, adc_atten_t atten, adc_bitwidth_t bitwidth, adc_cali_handle_t *out_handle);
|
||||
|
||||
/**
|
||||
* @brief De-initialise ADC Calibration
|
||||
|
Reference in New Issue
Block a user