From edc1abc8ea22185821d780d023b3e4ebf17335bb Mon Sep 17 00:00:00 2001 From: laokaiyao Date: Mon, 26 Jun 2023 11:52:25 +0800 Subject: [PATCH] refactor(adc_calib): Simplify 2nd step coefficient calculation - remove unnecessary variables and calculations - improve readability of code --- .../efuse/esp32c2/esp_efuse_rtc_calib.c | 10 ++-- .../efuse/esp32c6/esp_efuse_rtc_calib.c | 6 +-- .../efuse/esp32s3/esp_efuse_rtc_calib.c | 10 ++-- components/esp_adc/adc_cali_curve_fitting.c | 24 ++++++---- .../esp_adc/curve_fitting_coefficients.h | 7 +-- .../esp32c3/curve_fitting_coefficients.c | 7 ++- .../esp32c6/curve_fitting_coefficients.c | 47 +++++++++++-------- .../esp32s3/curve_fitting_coefficients.c | 12 ++++- components/esp_hw_support/adc_share_hw_ctrl.c | 10 +++- 9 files changed, 82 insertions(+), 51 deletions(-) diff --git a/components/efuse/esp32c2/esp_efuse_rtc_calib.c b/components/efuse/esp32c2/esp_efuse_rtc_calib.c index 0e36070959..c63dae5d2e 100644 --- a/components/efuse/esp32c2/esp_efuse_rtc_calib.c +++ b/components/efuse/esp32c2/esp_efuse_rtc_calib.c @@ -65,10 +65,14 @@ uint32_t esp_efuse_rtc_calib_get_init_code(int version, uint32_t adc_unit, int a esp_err_t esp_efuse_rtc_calib_get_cal_voltage(int version, uint32_t adc_unit, int atten, uint32_t *out_digi, uint32_t *out_vol_mv) { - assert((version >= ESP_EFUSE_ADC_CALIB_VER_MIN) && - (version <= ESP_EFUSE_ADC_CALIB_VER_MAX)); - assert(atten <= ADC_ATTEN_DB_11); (void) adc_unit; + if ((version < ESP_EFUSE_ADC_CALIB_VER_MIN) || + (version > ESP_EFUSE_ADC_CALIB_VER_MAX)) { + return ESP_ERR_INVALID_ARG; + } + if (atten >= 4 || atten < 0) { + return ESP_ERR_INVALID_ARG; + } if (atten == ADC_ATTEN_DB_2_5 || atten == ADC_ATTEN_DB_6) { /** diff --git a/components/efuse/esp32c6/esp_efuse_rtc_calib.c b/components/efuse/esp32c6/esp_efuse_rtc_calib.c index aa0f2a14c5..5477b095a4 100644 --- a/components/efuse/esp32c6/esp_efuse_rtc_calib.c +++ b/components/efuse/esp32c6/esp_efuse_rtc_calib.c @@ -34,8 +34,7 @@ int esp_efuse_rtc_calib_get_ver(void) uint32_t esp_efuse_rtc_calib_get_init_code(int version, uint32_t adc_unit, int atten) { - assert((version >= ESP_EFUSE_ADC_CALIB_VER_MIN) && - (version <= ESP_EFUSE_ADC_CALIB_VER_MAX)); + /* Version validation should be guaranteed in the caller */ assert(atten >=0 && atten < 4); (void) adc_unit; @@ -60,8 +59,7 @@ uint32_t esp_efuse_rtc_calib_get_init_code(int version, uint32_t adc_unit, int a int esp_efuse_rtc_calib_get_chan_compens(int version, uint32_t adc_unit, uint32_t adc_channel, int atten) { - assert((version >= ESP_EFUSE_ADC_CALIB_VER_MIN) && - (version <= ESP_EFUSE_ADC_CALIB_VER_MAX)); + /* Version validation should be guaranteed in the caller */ assert(atten < 4); assert(adc_channel < SOC_ADC_CHANNEL_NUM(adc_unit)); diff --git a/components/efuse/esp32s3/esp_efuse_rtc_calib.c b/components/efuse/esp32s3/esp_efuse_rtc_calib.c index 540fd9afc0..2ede5610ba 100644 --- a/components/efuse/esp32s3/esp_efuse_rtc_calib.c +++ b/components/efuse/esp32s3/esp_efuse_rtc_calib.c @@ -63,9 +63,13 @@ uint32_t esp_efuse_rtc_calib_get_init_code(int version, uint32_t adc_unit, int a esp_err_t esp_efuse_rtc_calib_get_cal_voltage(int version, uint32_t adc_unit, int atten, uint32_t *out_digi, uint32_t *out_vol_mv) { - assert((version >= ESP_EFUSE_ADC_CALIB_VER_MIN) && - (version <= ESP_EFUSE_ADC_CALIB_VER_MAX)); - assert(atten < 4); + if ((version < ESP_EFUSE_ADC_CALIB_VER_MIN) || + (version > ESP_EFUSE_ADC_CALIB_VER_MAX)) { + return ESP_ERR_INVALID_ARG; + } + if (atten >= 4 || atten < 0) { + return ESP_ERR_INVALID_ARG; + } assert(adc_unit <= ADC_UNIT_2); int efuse_vol_bits = 0; diff --git a/components/esp_adc/adc_cali_curve_fitting.c b/components/esp_adc/adc_cali_curve_fitting.c index cafe1ac4e8..dbdfab4783 100644 --- a/components/esp_adc/adc_cali_curve_fitting.c +++ b/components/esp_adc/adc_cali_curve_fitting.c @@ -59,7 +59,7 @@ typedef struct { /* ----------------------- Characterization Functions ----------------------- */ static void get_first_step_reference_point(int version_num, adc_unit_t unit_id, adc_atten_t atten, adc_calib_info_t *calib_info); static void calc_first_step_coefficients(const adc_calib_info_t *parsed_data, cali_chars_curve_fitting_t *chars); -static int32_t get_reading_error(uint64_t v_cali_1, const cali_chars_second_step_t *param, adc_atten_t atten); +static int32_t get_reading_error(uint64_t v_cali_1, const cali_chars_second_step_t *param); static esp_err_t check_valid(const adc_cali_curve_fitting_config_t *config); /* ------------------------ Interface Functions --------------------------- */ @@ -140,7 +140,7 @@ static esp_err_t cali_raw_to_voltage(void *arg, int raw, int *voltage) #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); + int32_t error = get_reading_error(v_cali_1, &(ctx->chars_second_step)); *voltage = (int32_t)v_cali_1 - error; @@ -179,9 +179,9 @@ static void calc_first_step_coefficients(const adc_calib_info_t *parsed_data, ca } -static int32_t get_reading_error(uint64_t v_cali_1, const cali_chars_second_step_t *param, adc_atten_t atten) +static int32_t get_reading_error(uint64_t v_cali_1, const cali_chars_second_step_t *param) { - if (v_cali_1 == 0) { + if (v_cali_1 == 0 || param->term_num == 0) { return 0; } @@ -193,19 +193,23 @@ static int32_t get_reading_error(uint64_t v_cali_1, const cali_chars_second_step memset(variable, 0, term_num * sizeof(uint64_t)); memset(term, 0, term_num * sizeof(uint64_t)); + /** + * The scheme formula is: + * error = (K0 * X^0) + (K1 * X^1) + (K2 * X^2) + (K3 * X^3) + ... + (Kn * X^n); + */ variable[0] = 1; - coeff = (*param->coeff)[atten][0][0]; - term[0] = variable[0] * coeff / (*param->coeff)[atten][0][1]; - error = (int32_t)term[0] * (*param->sign)[atten][0]; + coeff = (param->coeff)[0][0]; + term[0] = variable[0] * coeff / (param->coeff)[0][1]; + error = (int32_t)term[0] * (param->sign)[0]; for (int i = 1; i < term_num; i++) { variable[i] = variable[i - 1] * v_cali_1; - coeff = (*param->coeff)[atten][i][0]; + coeff = (param->coeff)[i][0]; term[i] = variable[i] * coeff; ESP_LOGV(TAG, "big coef is %llu, big term%d is %llu, coef_id is %d", coeff, i, term[i], i); - term[i] = term[i] / (*param->coeff)[atten][i][1]; - error += (int32_t)term[i] * (*param->sign)[atten][i]; + term[i] = term[i] / (param->coeff)[i][1]; + error += (int32_t)term[i] * (param->sign)[i]; ESP_LOGV(TAG, "term%d is %llu, error is %"PRId32, i, term[i], error); } diff --git a/components/esp_adc/curve_fitting_coefficients.h b/components/esp_adc/curve_fitting_coefficients.h index 79f08dc7bf..9c35d724b5 100644 --- a/components/esp_adc/curve_fitting_coefficients.h +++ b/components/esp_adc/curve_fitting_coefficients.h @@ -12,13 +12,10 @@ extern "C" { #endif -#define COEFF_GROUP_NUM 4 -#define TERM_MAX 5 - typedef struct { uint8_t term_num; ///< Term number of the algorithm formula - const uint64_t (*coeff)[COEFF_GROUP_NUM][TERM_MAX][2]; ///< Coeff of each term. See `adc_error_coef_atten` for details (and the magic number 2) - const int32_t (*sign)[COEFF_GROUP_NUM][TERM_MAX]; ///< Sign of each term + const uint64_t (*coeff)[2]; ///< Coeff of each term. See `adc_error_coef_atten` for details (and the magic number 2) + const int32_t (*sign); ///< Sign of each term } cali_chars_second_step_t; /** diff --git a/components/esp_adc/esp32c3/curve_fitting_coefficients.c b/components/esp_adc/esp32c3/curve_fitting_coefficients.c index 47a4b4eec7..9d8bda65ed 100644 --- a/components/esp_adc/esp32c3/curve_fitting_coefficients.c +++ b/components/esp_adc/esp32c3/curve_fitting_coefficients.c @@ -7,6 +7,9 @@ #include #include "../curve_fitting_coefficients.h" +#define COEFF_GROUP_NUM 4 +#define TERM_MAX 5 + /** * @note Error Calculation * Coefficients for calculating the reading voltage error. @@ -41,6 +44,6 @@ void curve_fitting_get_second_step_coeff(const adc_cali_curve_fitting_config_t * ctx->term_num = (config->atten == 3) ? 5 : 3; // 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->coeff = &adc1_error_coef_atten; - ctx->sign = &adc1_error_sign; + ctx->coeff = adc1_error_coef_atten[config->atten]; + ctx->sign = adc1_error_sign[config->atten]; } diff --git a/components/esp_adc/esp32c6/curve_fitting_coefficients.c b/components/esp_adc/esp32c6/curve_fitting_coefficients.c index cabc8d501d..588c318b96 100644 --- a/components/esp_adc/esp32c6/curve_fitting_coefficients.c +++ b/components/esp_adc/esp32c6/curve_fitting_coefficients.c @@ -10,6 +10,8 @@ #include "../curve_fitting_coefficients.h" #define COEFF_VERSION_NUM 2 // Currently C6 has two versions of curve calibration schemes +#define COEFF_GROUP_NUM 4 +#define TERM_MAX 3 /** * @note Error Calculation @@ -26,17 +28,17 @@ const static uint64_t adc1_error_coef_atten[COEFF_VERSION_NUM][COEFF_GROUP_NUM][TERM_MAX][2] = { /* Coefficients of calibration version 1 */ { - {{487166399931449, 1e15}, {6436483033201, 1e16}, {30410131806, 1e16}, {0, 0}, {0, 0}}, //atten0 - {{8665498165817785, 1e16}, {15239070452946, 1e16}, {13818878844, 1e16}, {0, 0}, {0, 0}}, //atten1 - {{12277821756674387, 1e16}, {22275554717885, 1e16}, {5924302667, 1e16}, {0, 0}, {0, 0}}, //atten2 - {{3801417550380255, 1e16}, {6020352420772, 1e16}, {12442478488, 1e16}, {0, 0}, {0, 0}}, //atten3 + {{487166399931449, 1e15}, {6436483033201, 1e16}, {30410131806, 1e16}}, //atten0 + {{8665498165817785, 1e16}, {15239070452946, 1e16}, {13818878844, 1e16}}, //atten1 + {{12277821756674387, 1e16}, {22275554717885, 1e16}, {5924302667, 1e16}}, //atten2 + {{3801417550380255, 1e16}, {6020352420772, 1e16}, {12442478488, 1e16}}, //atten3 }, /* Coefficients of calibration version 2 */ { - {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, //atten0 - {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, //atten1 - {{12217864764388775, 1e16}, {1954123107752, 1e16}, {6409679727, 1e16}, {0, 0}, {0, 0}}, //atten2 - {{3915910437042445 , 1e16}, {31536470857564, 1e16}, {12493873014, 1e16}, {0, 0}, {0, 0}}, //atten3 + {{0, 0}, {0, 0}, {0, 0}}, //atten0 + {{0, 0}, {0, 0}, {0, 0}}, //atten1 + {{12217864764388775, 1e16}, {1954123107752, 1e16}, {6409679727, 1e16}}, //atten2 + {{3915910437042445 , 1e16}, {31536470857564, 1e16}, {12493873014, 1e16}}, //atten3 }, }; @@ -46,17 +48,17 @@ const static uint64_t adc1_error_coef_atten[COEFF_VERSION_NUM][COEFF_GROUP_NUM][ const static int32_t adc1_error_sign[COEFF_VERSION_NUM][COEFF_GROUP_NUM][TERM_MAX] = { /* Coefficient sign of calibration version 1 */ { - {-1, 1, 1, 0, 0}, //atten0 - {-1, 1, 1, 0, 0}, //atten1 - {-1, 1, 1, 0, 0}, //atten2 - {-1, -1, 1, 0, 0}, //atten3 + {-1, 1, 1}, //atten0 + {-1, 1, 1}, //atten1 + {-1, 1, 1}, //atten2 + {-1, -1, 1}, //atten3 }, /* Coefficient sign of calibration version 2 */ { - { 0, 0, 0, 0, 0}, //atten0 - { 0, 0, 0, 0, 0}, //atten1 - {-1, -1, 1, 0, 0}, //atten2 - {-1, -1, 1, 0, 0}, //atten3 + { 0, 0, 0}, //atten0 + { 0, 0, 0}, //atten1 + {-1, -1, 1}, //atten2 + {-1, -1, 1}, //atten3 }, }; @@ -66,8 +68,13 @@ void curve_fitting_get_second_step_coeff(const adc_cali_curve_fitting_config_t * uint32_t adc_calib_ver = esp_efuse_rtc_calib_get_ver(); assert((adc_calib_ver >= ESP_EFUSE_ADC_CALIB_VER_MIN) && (adc_calib_ver <= ESP_EFUSE_ADC_CALIB_VER_MAX)); - ctx->term_num = 3; - printf("ver %lu index %lu\n", adc_calib_ver, VER2IDX(adc_calib_ver)); - ctx->coeff = &adc1_error_coef_atten[VER2IDX(adc_calib_ver)]; - ctx->sign = &adc1_error_sign[VER2IDX(adc_calib_ver)]; + if (adc_calib_ver == ESP_EFUSE_ADC_CALIB_VER2 && config->atten < 2) { + ctx->term_num = 0; + ctx->coeff = NULL; + ctx->sign = NULL; + } else { + ctx->term_num = 3; + ctx->coeff = adc1_error_coef_atten[VER2IDX(adc_calib_ver)][config->atten]; + ctx->sign = adc1_error_sign[VER2IDX(adc_calib_ver)][config->atten]; + } } diff --git a/components/esp_adc/esp32s3/curve_fitting_coefficients.c b/components/esp_adc/esp32s3/curve_fitting_coefficients.c index 6020130f30..74a500da31 100644 --- a/components/esp_adc/esp32s3/curve_fitting_coefficients.c +++ b/components/esp_adc/esp32s3/curve_fitting_coefficients.c @@ -5,8 +5,12 @@ */ #include +#include "hal/adc_types.h" #include "../curve_fitting_coefficients.h" +#define COEFF_GROUP_NUM 4 +#define TERM_MAX 5 + /** * @note Error Calculation * Coefficients for calculating the reading voltage error. @@ -50,6 +54,10 @@ const static int32_t adc2_error_sign[COEFF_GROUP_NUM][TERM_MAX] = { void curve_fitting_get_second_step_coeff(const adc_cali_curve_fitting_config_t *config, cali_chars_second_step_t *ctx) { ctx->term_num = (config->atten == 3) ? 5 : 3; - ctx->coeff = (config->unit_id == ADC_UNIT_1) ? &adc1_error_coef_atten : &adc2_error_coef_atten; - ctx->sign = (config->unit_id == ADC_UNIT_1) ? &adc1_error_sign : &adc2_error_sign; + ctx->coeff = config->unit_id == ADC_UNIT_1 ? + adc1_error_coef_atten[config->atten] : + adc2_error_coef_atten[config->atten]; + ctx->sign = config->unit_id == ADC_UNIT_1 ? + adc1_error_sign[config->atten] : + adc2_error_sign[config->atten]; } diff --git a/components/esp_hw_support/adc_share_hw_ctrl.c b/components/esp_hw_support/adc_share_hw_ctrl.c index 489cf311d9..57325e8aad 100644 --- a/components/esp_hw_support/adc_share_hw_ctrl.c +++ b/components/esp_hw_support/adc_share_hw_ctrl.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -70,6 +70,7 @@ void adc_calc_hw_calibration_code(adc_unit_t adc_n, adc_atten_t atten) if ((version >= ESP_EFUSE_ADC_CALIB_VER_MIN) && (version <= ESP_EFUSE_ADC_CALIB_VER_MAX)) { + // Guarantee the calibration version before calling efuse function init_code = esp_efuse_rtc_calib_get_init_code(version, adc_n, atten); } #if SOC_ADC_SELF_HW_CALI_SUPPORTED @@ -103,7 +104,12 @@ static int s_adc_cali_chan_compens[SOC_ADC_MAX_CHANNEL_NUM][SOC_ADC_ATTEN_NUM] = void adc_load_hw_calibration_chan_compens(adc_unit_t adc_n, adc_channel_t chan, adc_atten_t atten) { int version = esp_efuse_rtc_calib_get_ver(); - s_adc_cali_chan_compens[chan][atten] = esp_efuse_rtc_calib_get_chan_compens(version, adc_n, chan, atten); + if ((version >= ESP_EFUSE_ADC_CALIB_VER_MIN) && + (version <= ESP_EFUSE_ADC_CALIB_VER_MAX)) { + // Guarantee the calibration version before calling efuse function + s_adc_cali_chan_compens[chan][atten] = esp_efuse_rtc_calib_get_chan_compens(version, adc_n, chan, atten); + } + // No warning when version doesn't match because should has warned in adc_calc_hw_calibration_code } int IRAM_ATTR adc_get_hw_calibration_chan_compens(adc_unit_t adc_n, adc_channel_t chan, adc_atten_t atten)