1 /*
2  * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stdint.h>
8 #include <stdbool.h>
9 #include <string.h>
10 #include "esp_types.h"
11 #include "esp_err.h"
12 #include "esp_log.h"
13 #include "driver/adc.h"
14 #include "hal/adc_ll.h"
15 #include "esp_efuse_rtc_calib.h"
16 #include "esp_adc_cal.h"
17 #include "esp_adc_cal_internal.h"
18 
19 
20 #include <zephyr/logging/log.h>
21 LOG_MODULE_REGISTER(adc_cal, CONFIG_ADC_LOG_LEVEL);
22 
23 //const static char LOG_TAG[] = "ADC_CALI";
24 
25 
26 /* ------------------------ Characterization Constants ---------------------- */
27 
28 // coeff_a is actually a float number
29 // it is scaled to put them into uint32_t so that the headers do not have to be changed
30 static const int coeff_a_scaling = 65536;
31 
32 /**
33  * @note Error Calculation
34  * Coefficients for calculating the reading voltage error.
35  * Four sets of coefficients for atten0 ~ atten3 respectively.
36  *
37  * For each item, first element is the Coefficient, second element is the Multiple. (Coefficient / Multiple) is the real coefficient.
38  *
39  * @note {0,0} stands for unused item
40  * @note In case of the overflow, these coeffcients are recorded as Absolute Value
41  * @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);
42  * @note Above formula is rewritten from the original documentation, please note that the coefficients are re-ordered.
43  * @note ADC1 and ADC2 use same coeffients
44  */
45 const static uint64_t adc_error_coef_atten[4][5][2] = {
46      {{225966470500043, 1e15}, {7265418501948, 1e16}, {109410402681, 1e16}, {0, 0}, {0, 0}},                         //atten0
47      {{4229623392600516, 1e16}, {731527490903, 1e16}, {88166562521, 1e16}, {0, 0}, {0, 0}},                          //atten1
48      {{1017859239236435, 1e15}, {97159265299153, 1e16}, {149794028038, 1e16}, {0, 0}, {0, 0}},                       //atten2
49      {{14912262772850453, 1e16}, {228549975564099, 1e16}, {356391935717, 1e16}, {179964582, 1e16}, {42046, 1e16}}    //atten3
50     };
51 /**
52  * Term sign
53  * @note ADC1 and ADC2 use same coeffients
54  */
55 const static int32_t adc_error_sign[4][5] = {
56        {-1, -1, 1,  0,  0}, //atten0
57        { 1, -1, 1,  0,  0}, //atten1
58        {-1, -1, 1,  0,  0}, //atten2
59        {-1, -1, 1, -1,  1}  //atten3
60     };
61 
62 /* -------------------- Characterization Helper Data Types ------------------ */
63 typedef struct {
64     uint32_t voltage;
65     uint32_t digi;
66 } adc_calib_data_ver1;
67 
68 typedef struct {
69     char version_num;
70     adc_unit_t adc_num;
71     adc_atten_t atten_level;
72     union {
73         adc_calib_data_ver1 ver1;
74     } efuse_data;
75 } adc_calib_parsed_info_t;
76 
prepare_calib_data_for(int version_num,adc_unit_t adc_num,adc_atten_t atten,adc_calib_parsed_info_t * parsed_data_storage)77 static esp_err_t prepare_calib_data_for(int version_num, adc_unit_t adc_num, adc_atten_t atten, adc_calib_parsed_info_t *parsed_data_storage)
78 {
79     assert(version_num == 1);
80     esp_err_t ret;
81 
82     parsed_data_storage->version_num = version_num;
83     parsed_data_storage->adc_num = adc_num;
84     parsed_data_storage->atten_level = atten;
85     // V1 we don't have calibration data for ADC2, using the efuse data of ADC1
86     uint32_t voltage, digi;
87     ret = esp_efuse_rtc_calib_get_cal_voltage(version_num, atten, &digi, &voltage);
88     if (ret != ESP_OK) {
89         return ret;
90     }
91     parsed_data_storage->efuse_data.ver1.voltage = voltage;
92     parsed_data_storage->efuse_data.ver1.digi = digi;
93     return ret;
94 }
95 
96 /* ----------------------- Characterization Functions ----------------------- */
97 /*
98  * Estimate the (assumed) linear relationship btwn the measured raw value and the voltage
99  * with the previously done measurement when the chip was manufactured.
100  */
calculate_characterization_coefficients(const adc_calib_parsed_info_t * parsed_data,esp_adc_cal_characteristics_t * chars)101 static void calculate_characterization_coefficients(const adc_calib_parsed_info_t *parsed_data, esp_adc_cal_characteristics_t *chars)
102 {
103     LOG_DBG("Calib V1, Cal Voltage = %d, Digi out = %d\n", parsed_data->efuse_data.ver1.voltage, parsed_data->efuse_data.ver1.digi);
104 
105     chars->coeff_a = coeff_a_scaling * parsed_data->efuse_data.ver1.voltage / parsed_data->efuse_data.ver1.digi;
106     chars->coeff_b = 0;
107 }
108 
109 /* ------------------------- Public API ------------------------------------- */
esp_adc_cal_check_efuse(esp_adc_cal_value_t source)110 esp_err_t esp_adc_cal_check_efuse(esp_adc_cal_value_t source)
111 {
112     if (source != ESP_ADC_CAL_VAL_EFUSE_TP) {
113         return ESP_ERR_NOT_SUPPORTED;
114     }
115     uint8_t adc_encoding_version = esp_efuse_rtc_calib_get_ver();
116     if (adc_encoding_version != 1) {
117         // current version only accepts encoding ver 1.
118         return ESP_ERR_INVALID_VERSION;
119     }
120 
121     return ESP_OK;
122 }
123 
esp_adc_cal_characterize(adc_unit_t adc_num,adc_atten_t atten,adc_bits_width_t bit_width,uint32_t default_vref,esp_adc_cal_characteristics_t * chars)124 esp_adc_cal_value_t esp_adc_cal_characterize(adc_unit_t adc_num,
125         adc_atten_t atten,
126         adc_bits_width_t bit_width,
127         uint32_t default_vref,
128         esp_adc_cal_characteristics_t *chars)
129 {
130     esp_err_t ret;
131     adc_calib_parsed_info_t efuse_parsed_data = {0};
132     // Check parameters
133     if (adc_num != ADC_UNIT_1 && adc_num != ADC_UNIT_2) {
134         return ESP_ADC_CAL_VAL_NOT_SUPPORTED;
135 	}
136     if (!chars) {
137         return ESP_ADC_CAL_VAL_NOT_SUPPORTED;
138 	}
139     if (bit_width != ADC_WIDTH_BIT_12) {
140         return ESP_ADC_CAL_VAL_NOT_SUPPORTED;
141 	}
142     if (atten >= ADC_ATTEN_MAX) {
143         return ESP_ADC_CAL_VAL_NOT_SUPPORTED;
144 	}
145 
146     int version_num = esp_efuse_rtc_calib_get_ver();
147     if (version_num != 1) {
148         return ESP_ADC_CAL_VAL_NOT_SUPPORTED;
149 	}
150 
151     memset(chars, 0, sizeof(esp_adc_cal_characteristics_t));
152 
153     // make sure adc is calibrated.
154     ret = prepare_calib_data_for(version_num, adc_num, atten, &efuse_parsed_data);
155     if (ret != ESP_OK) {
156         abort();
157     }
158 
159     calculate_characterization_coefficients(&efuse_parsed_data, chars);
160 
161     // Initialize remaining fields
162     chars->adc_num = adc_num;
163     chars->atten = atten;
164     chars->bit_width = bit_width;
165 
166     // in esp32c3 we only use the two point method to calibrate the adc.
167     return ESP_ADC_CAL_VAL_EFUSE_TP;
168 }
169 
esp_adc_cal_raw_to_voltage(uint32_t adc_reading,const esp_adc_cal_characteristics_t * chars)170 uint32_t esp_adc_cal_raw_to_voltage(uint32_t adc_reading, const esp_adc_cal_characteristics_t *chars)
171 {
172     assert(chars != NULL);
173 
174     int32_t error = 0;
175     uint64_t v_cali_1 = adc_reading * chars->coeff_a / coeff_a_scaling;
176     esp_adc_error_calc_param_t param = {
177         .v_cali_input = v_cali_1,
178         .term_num = (chars->atten == 3) ? 5 : 3,
179         .coeff = &adc_error_coef_atten,
180         .sign = &adc_error_sign,
181     };
182     error = esp_adc_cal_get_reading_error(&param, chars->atten);
183 
184     return (int32_t)v_cali_1 - error;
185 }
186