Skip to content

Commit

Permalink
adc_calib: support calibration v2 on esp32c6
Browse files Browse the repository at this point in the history
  • Loading branch information
L-KAYA committed Jun 26, 2023
1 parent 6fc45d4 commit f949819
Show file tree
Hide file tree
Showing 17 changed files with 179 additions and 122 deletions.
8 changes: 5 additions & 3 deletions components/efuse/esp32c2/esp_efuse_rtc_calib.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand All @@ -26,7 +26,8 @@ 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);
assert((version >= ESP_EFUSE_ADC_CALIB_VER_MIN) &&
(version <= ESP_EFUSE_ADC_CALIB_VER_MAX));
assert(atten <= ADC_ATTEN_DB_11);
(void) adc_unit;

Expand Down Expand Up @@ -64,7 +65,8 @@ 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);
assert((version >= ESP_EFUSE_ADC_CALIB_VER_MIN) &&
(version <= ESP_EFUSE_ADC_CALIB_VER_MAX));
assert(atten <= ADC_ATTEN_DB_11);
(void) adc_unit;

Expand Down
4 changes: 3 additions & 1 deletion components/efuse/esp32c2/include/esp_efuse_rtc_calib.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ extern "C" {
#endif

//This is the ADC calibration value version burnt in efuse
#define ESP_EFUSE_ADC_CALIB_VER 1
#define ESP_EFUSE_ADC_CALIB_VER 1
#define ESP_EFUSE_ADC_CALIB_VER_MIN ESP_EFUSE_ADC_CALIB_VER
#define ESP_EFUSE_ADC_CALIB_VER_MAX ESP_EFUSE_ADC_CALIB_VER

/**
* @brief Get the RTC calibration efuse version
Expand Down
8 changes: 5 additions & 3 deletions components/efuse/esp32c3/esp_efuse_rtc_calib.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand All @@ -24,7 +24,8 @@ 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);
assert((version >= ESP_EFUSE_ADC_CALIB_VER_MIN) &&
(version <= ESP_EFUSE_ADC_CALIB_VER_MAX));
(void) adc_unit;
const esp_efuse_desc_t** init_code_efuse;
assert(atten < 4);
Expand All @@ -51,7 +52,8 @@ esp_err_t esp_efuse_rtc_calib_get_cal_voltage(int version, uint32_t adc_unit, in
(void)adc_unit; //On esp32c3, V1 we don't have calibration data for ADC2, using the efuse data of ADC1
const esp_efuse_desc_t** cal_vol_efuse;
uint32_t calib_vol_expected_mv;
if (version != ESP_EFUSE_ADC_CALIB_VER) {
if ((version < ESP_EFUSE_ADC_CALIB_VER_MIN) ||
(version > ESP_EFUSE_ADC_CALIB_VER_MAX)) {
return ESP_ERR_INVALID_ARG;
}
if (atten >= 4) {
Expand Down
4 changes: 3 additions & 1 deletion components/efuse/esp32c3/include/esp_efuse_rtc_calib.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ extern "C" {
#endif

//This is the ADC calibration value version burnt in efuse
#define ESP_EFUSE_ADC_CALIB_VER 1
#define ESP_EFUSE_ADC_CALIB_VER 1
#define ESP_EFUSE_ADC_CALIB_VER_MIN ESP_EFUSE_ADC_CALIB_VER
#define ESP_EFUSE_ADC_CALIB_VER_MAX ESP_EFUSE_ADC_CALIB_VER

/**
* @brief Get the RTC calibration efuse version
Expand Down
56 changes: 31 additions & 25 deletions components/efuse/esp32c6/esp_efuse_rtc_calib.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@
int esp_efuse_rtc_calib_get_ver(void)
{
uint32_t cali_version = 0;
if (efuse_hal_blk_version() >= 1) {
cali_version = ESP_EFUSE_ADC_CALIB_VER;
uint32_t blk_ver = efuse_hal_blk_version();
if (blk_ver == 1) {
cali_version = ESP_EFUSE_ADC_CALIB_VER1;
} else if (blk_ver >= 2) {
cali_version = ESP_EFUSE_ADC_CALIB_VER2;
} else {
ESP_LOGW("eFuse", "calibration efuse version does not match, set default version to 0");
}
Expand All @@ -31,7 +34,8 @@ 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);
assert((version >= ESP_EFUSE_ADC_CALIB_VER_MIN) &&
(version <= ESP_EFUSE_ADC_CALIB_VER_MAX));
assert(atten >=0 && atten < 4);
(void) adc_unit;

Expand All @@ -56,7 +60,8 @@ 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);
assert((version >= ESP_EFUSE_ADC_CALIB_VER_MIN) &&
(version <= ESP_EFUSE_ADC_CALIB_VER_MAX));
assert(atten < 4);
assert(adc_channel < SOC_ADC_CHANNEL_NUM(adc_unit));

Expand Down Expand Up @@ -95,34 +100,35 @@ int esp_efuse_rtc_calib_get_chan_compens(int version, uint32_t adc_unit, uint32_
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)
{
(void) adc_unit;
const esp_efuse_desc_t** cal_vol_efuse;
uint32_t calib_vol_expected_mv;
if (version != ESP_EFUSE_ADC_CALIB_VER) {
const esp_efuse_desc_t** cal_vol_efuse[4] = {
ESP_EFUSE_ADC1_CAL_VOL_ATTEN0,
ESP_EFUSE_ADC1_CAL_VOL_ATTEN1,
ESP_EFUSE_ADC1_CAL_VOL_ATTEN2,
ESP_EFUSE_ADC1_CAL_VOL_ATTEN3,
};
const uint32_t input_vout_mv[2][4] = {
{400, 550, 750, 1370}, // Calibration V1 coefficients
{750, 1000, 1500, 2800}, // Calibration V2 coefficients
};

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 == 0) {
cal_vol_efuse = ESP_EFUSE_ADC1_CAL_VOL_ATTEN0;
calib_vol_expected_mv = 400;
} else if (atten == 1) {
cal_vol_efuse = ESP_EFUSE_ADC1_CAL_VOL_ATTEN1;
calib_vol_expected_mv = 550;
} else if (atten == 2) {
cal_vol_efuse = ESP_EFUSE_ADC1_CAL_VOL_ATTEN2;
calib_vol_expected_mv = 750;
} else {
cal_vol_efuse = ESP_EFUSE_ADC1_CAL_VOL_ATTEN3;
calib_vol_expected_mv = 1370;
}
assert(cal_vol_efuse[0]->bit_count == 10);

uint32_t cal_vol = 0;
ESP_ERROR_CHECK(esp_efuse_read_field_blob(cal_vol_efuse, &cal_vol, cal_vol_efuse[0]->bit_count));
assert(cal_vol_efuse[atten][0]->bit_count == 10);

*out_digi = 1500 + RTC_CALIB_GET_SIGNED_VAL(cal_vol, 9);
*out_vol_mv = calib_vol_expected_mv;
uint32_t cal_vol = 0;
esp_err_t ret = esp_efuse_read_field_blob(cal_vol_efuse[atten], &cal_vol, cal_vol_efuse[atten][0]->bit_count);
if (ret != ESP_OK) {
return ret;
}
uint32_t chk_offset = (version == ESP_EFUSE_ADC_CALIB_VER1) ? 1500 : (atten == 2) ? 2900 : 2850;
*out_digi = chk_offset + RTC_CALIB_GET_SIGNED_VAL(cal_vol, 9);
*out_vol_mv = input_vout_mv[VER2IDX(version)][atten];
return ESP_OK;
}

Expand Down
7 changes: 5 additions & 2 deletions components/efuse/esp32c6/include/esp_efuse_rtc_calib.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@ extern "C" {
#endif

//This is the ADC calibration value version burnt in efuse
#define ESP_EFUSE_ADC_CALIB_VER 1

#define ESP_EFUSE_ADC_CALIB_VER1 1
#define ESP_EFUSE_ADC_CALIB_VER2 2
#define ESP_EFUSE_ADC_CALIB_VER_MIN ESP_EFUSE_ADC_CALIB_VER1
#define ESP_EFUSE_ADC_CALIB_VER_MAX ESP_EFUSE_ADC_CALIB_VER2
#define VER2IDX(ver) (ver - 1) // Version number to index number of the array
/**
* @brief Get the RTC calibration efuse version
*
Expand Down
4 changes: 3 additions & 1 deletion components/efuse/esp32h2/include/esp_efuse_rtc_calib.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ extern "C" {
#endif

//This is the ADC calibration value version burnt in efuse
#define ESP_EFUSE_ADC_CALIB_VER 1
#define ESP_EFUSE_ADC_CALIB_VER 1
#define ESP_EFUSE_ADC_CALIB_VER_MIN ESP_EFUSE_ADC_CALIB_VER
#define ESP_EFUSE_ADC_CALIB_VER_MAX ESP_EFUSE_ADC_CALIB_VER

/**
* @brief Get the RTC calibration efuse version
Expand Down
4 changes: 3 additions & 1 deletion components/efuse/esp32s2/include/esp_efuse_rtc_table.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ extern "C" {
#include "sdkconfig.h"

//This is the ADC calibration value version burnt in efuse
#define ESP_EFUSE_ADC_CALIB_VER 2
#define ESP_EFUSE_ADC_CALIB_VER 2
#define ESP_EFUSE_ADC_CALIB_VER_MIN ESP_EFUSE_ADC_CALIB_VER
#define ESP_EFUSE_ADC_CALIB_VER_MAX ESP_EFUSE_ADC_CALIB_VER

#define RTCCALIB_ESP32S2_ADCCOUNT 2
#define RTCCALIB_ESP32S2_ATTENCOUNT 4
Expand Down
8 changes: 5 additions & 3 deletions components/efuse/esp32s3/esp_efuse_rtc_calib.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand Down Expand Up @@ -27,7 +27,8 @@ 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);
assert((version >= ESP_EFUSE_ADC_CALIB_VER_MIN) &&
(version <= ESP_EFUSE_ADC_CALIB_VER_MAX));
assert(atten < 4);
assert(adc_unit <= ADC_UNIT_2);

Expand Down Expand Up @@ -62,7 +63,8 @@ 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);
assert((version >= ESP_EFUSE_ADC_CALIB_VER_MIN) &&
(version <= ESP_EFUSE_ADC_CALIB_VER_MAX));
assert(atten < 4);
assert(adc_unit <= ADC_UNIT_2);

Expand Down
4 changes: 3 additions & 1 deletion components/efuse/esp32s3/include/esp_efuse_rtc_calib.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ extern "C" {
#endif

//This is the ADC calibration value version burnt in efuse
#define ESP_EFUSE_ADC_CALIB_VER 1
#define ESP_EFUSE_ADC_CALIB_VER 1
#define ESP_EFUSE_ADC_CALIB_VER_MIN ESP_EFUSE_ADC_CALIB_VER
#define ESP_EFUSE_ADC_CALIB_VER_MAX ESP_EFUSE_ADC_CALIB_VER

/**
* @brief Get the RTC calibration efuse version
Expand Down
43 changes: 9 additions & 34 deletions components/esp_adc/adc_cali_curve_fitting.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand All @@ -15,11 +15,11 @@
#include "soc/soc_caps.h"
#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"
#include "curve_fitting_coefficients.h"

const __attribute__((unused)) static char *TAG = "adc_cali";

Expand Down Expand Up @@ -48,12 +48,6 @@ typedef struct {
uint32_t coeff_b; ///< Offset of ADC-Voltage curve
} cali_chars_first_step_t;

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
} cali_chars_second_step_t;

typedef struct {
adc_unit_t unit_id; ///< ADC unit
adc_channel_t chan; ///< ADC channel
Expand All @@ -65,7 +59,6 @@ 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 void calc_second_step_coefficients(const adc_cali_curve_fitting_config_t *config, cali_chars_curve_fitting_t *ctx);
static int32_t get_reading_error(uint64_t v_cali_1, const cali_chars_second_step_t *param, adc_atten_t atten);
static esp_err_t check_valid(const adc_cali_curve_fitting_config_t *config);

Expand All @@ -81,9 +74,10 @@ esp_err_t adc_cali_create_scheme_curve_fitting(const adc_cali_curve_fitting_conf
if (ret != ESP_OK) {
return ret;
}
// current version only accepts encoding version: `ESP_EFUSE_ADC_CALIB_VER`.
uint8_t adc_encoding_version = esp_efuse_rtc_calib_get_ver();
ESP_RETURN_ON_FALSE(adc_encoding_version == ESP_EFUSE_ADC_CALIB_VER, ESP_ERR_NOT_SUPPORTED, TAG, "Calibration required eFuse bits not burnt");
// current version only accepts encoding version: ESP_EFUSE_ADC_CALIB_VER_MIN <= adc_encoding_version <= ESP_EFUSE_ADC_CALIB_VER_MAX.
uint32_t adc_encoding_version = esp_efuse_rtc_calib_get_ver();
ESP_RETURN_ON_FALSE((adc_encoding_version >= ESP_EFUSE_ADC_CALIB_VER_MIN) &&
(adc_encoding_version <= ESP_EFUSE_ADC_CALIB_VER_MAX), ESP_ERR_NOT_SUPPORTED, TAG, "Calibration required eFuse bits not burnt");

adc_cali_scheme_t *scheme = (adc_cali_scheme_t *)heap_caps_calloc(1, sizeof(adc_cali_scheme_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
ESP_RETURN_ON_FALSE(scheme, ESP_ERR_NO_MEM, TAG, "no mem for adc calibration scheme");
Expand All @@ -100,7 +94,7 @@ esp_err_t adc_cali_create_scheme_curve_fitting(const adc_cali_curve_fitting_conf
get_first_step_reference_point(adc_encoding_version, config->unit_id, config->atten, &calib_info);
calc_first_step_coefficients(&calib_info, chars);
//Set second step calibration context
calc_second_step_coefficients(config, chars);
curve_fitting_get_second_step_coeff(config, &(chars->chars_second_step));
chars->unit_id = config->unit_id;
chars->chan = config->chan;
chars->atten = config->atten;
Expand Down Expand Up @@ -157,7 +151,8 @@ static esp_err_t cali_raw_to_voltage(void *arg, int raw, int *voltage)
//To get the reference point (Dout, Vin)
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)
{
assert(version_num == ESP_EFUSE_ADC_CALIB_VER);
assert((version_num >= ESP_EFUSE_ADC_CALIB_VER_MIN) &&
(version_num <= ESP_EFUSE_ADC_CALIB_VER_MAX));
esp_err_t ret;

calib_info->version_num = version_num;
Expand All @@ -183,19 +178,6 @@ static void calc_first_step_coefficients(const adc_calib_info_t *parsed_data, ca
ESP_LOGV(TAG, "Calib V1, Cal Voltage = %" PRId32 ", Digi out = %" PRId32 ", Coef_a = %" PRId32, parsed_data->ref_data.ver1.voltage, parsed_data->ref_data.ver1.digi, ctx->chars_first_step.coeff_a);
}

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 || 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
ctx->chars_second_step.coeff = (config->unit_id == ADC_UNIT_1) ? &adc1_error_coef_atten : &adc2_error_coef_atten;
ctx->chars_second_step.sign = (config->unit_id == ADC_UNIT_1) ? &adc1_error_sign : &adc2_error_sign;
#endif
}

static int32_t get_reading_error(uint64_t v_cali_1, const cali_chars_second_step_t *param, adc_atten_t atten)
{
Expand All @@ -211,13 +193,6 @@ 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));

/**
* 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);
*/
variable[0] = 1;
coeff = (*param->coeff)[atten][0][0];
term[0] = variable[0] * coeff / (*param->coeff)[atten][0][1];
Expand Down
Loading

0 comments on commit f949819

Please sign in to comment.