1
6
7
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
90
93
96
99
100
101
106
107
108
109
110
113
114
115
116
117
118
119
120
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
159
160
161
162
163
164
165
166
167
168
169
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
223
224
225
226
227
228
229
230
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
267
268
269
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
312
313
314
315
316
317
318
319
326
327
328
329
330
331
332
333
334
335
338
339
352
/* ... */
#include <stdint.h>
#include "esp_types.h"
#include "esp_err.h"
#include "esp_check.h"
#include "assert.h"
#include "hal/efuse_ll.h"
#include "hal/adc_types.h"
#include "driver/adc_types_legacy.h"
#include "esp_adc_cal_types_legacy.h"9 includes
#ifdef CONFIG_ADC_CAL_EFUSE_TP_ENABLE
#define EFUSE_TP_ENABLED 1
#else
#define EFUSE_TP_ENABLED 0
#endif
#ifdef CONFIG_ADC_CAL_EFUSE_VREF_ENABLE
#define EFUSE_VREF_ENABLED 1
#else
#define EFUSE_VREF_ENABLED 0
#endif
#ifdef CONFIG_ADC_CAL_LUT_ENABLE
#define LUT_ENABLED 1
#else
#define LUT_ENABLED 0
#endif
/* ... */
#define CHECK_BLK3_FLAG 1
#define VREF_FORMAT 0
#define VREF_MASK 0x1F
#define VREF_STEP_SIZE 7
#define VREF_OFFSET 1100
#define TP_LOW1_OFFSET 278
#define TP_LOW2_OFFSET 421
#define TP_LOW_MASK 0x7F
#define TP_LOW_VOLTAGE 150
#define TP_HIGH1_OFFSET 3265
#define TP_HIGH2_OFFSET 3406
#define TP_HIGH_MASK 0x1FF
#define TP_HIGH_VOLTAGE 850
#define TP_STEP_SIZE 4
------------------------------ eFuse Access
#define LIN_COEFF_A_SCALE 65536
#define LIN_COEFF_A_ROUND (LIN_COEFF_A_SCALE/2)
#define LUT_VREF_LOW 1000
#define LUT_VREF_HIGH 1200
#define LUT_ADC_STEP_SIZE 64
#define LUT_POINTS 20
#define LUT_LOW_THRESH 2880
#define LUT_HIGH_THRESH (LUT_LOW_THRESH + LUT_ADC_STEP_SIZE)
#define ADC_12_BIT_RES 409623 defines
static const uint32_t adc1_tp_atten_scale[4] = {65504, 86975, 120389, 224310};
static const uint32_t adc2_tp_atten_scale[4] = {65467, 86861, 120416, 224708};
static const uint32_t adc1_tp_atten_offset[4] = {0, 1, 27, 54};
static const uint32_t adc2_tp_atten_offset[4] = {0, 9, 26, 66};
static const uint32_t adc1_vref_atten_scale[4] = {57431, 76236, 105481, 196602};
static const uint32_t adc2_vref_atten_scale[4] = {57236, 76175, 105678, 197170};
static const uint32_t adc1_vref_atten_offset[4] = {75, 78, 107, 142};
static const uint32_t adc2_vref_atten_offset[4] = {63, 66, 89, 128};
static const uint32_t lut_adc1_low[LUT_POINTS] = {2240, 2297, 2352, 2405, 2457, 2512, 2564, 2616, 2664, 2709,
2754, 2795, 2832, 2868, 2903, 2937, 2969, 3000, 3030, 3060
}{...};
static const uint32_t lut_adc1_high[LUT_POINTS] = {2667, 2706, 2745, 2780, 2813, 2844, 2873, 2901, 2928, 2956,
2982, 3006, 3032, 3059, 3084, 3110, 3135, 3160, 3184, 3209
}{...};
static const uint32_t lut_adc2_low[LUT_POINTS] = {2238, 2293, 2347, 2399, 2451, 2507, 2561, 2613, 2662, 2710,
2754, 2792, 2831, 2869, 2904, 2937, 2968, 2999, 3029, 3059
}{...};
static const uint32_t lut_adc2_high[LUT_POINTS] = {2657, 2698, 2738, 2774, 2807, 2838, 2867, 2894, 2921, 2946,
2971, 2996, 3020, 3043, 3067, 3092, 3116, 3139, 3162, 3185
}{...};
------------------------ Characterization Constants
static bool check_efuse_vref(void)
{
return (efuse_ll_get_adc_vref() != 0) ? true : false;
}{ ... }
static bool check_efuse_tp(void)
{
if (CHECK_BLK3_FLAG && (efuse_ll_get_blk3_part_reserve() == 0)) {
return false;
}{...}
return efuse_ll_get_adc1_tp_low() &&
efuse_ll_get_adc2_tp_low() &&
efuse_ll_get_adc1_tp_high() &&
efuse_ll_get_adc2_tp_high();
}{ ... }
static inline int decode_bits(uint32_t bits, uint32_t mask, bool is_twos_compl)
{
int ret;
if (bits & (~(mask >> 1) & mask)) {
if (is_twos_compl) {
ret = -(((~bits) + 1) & (mask >> 1));
}{...} else {
ret = -(bits & (mask >> 1));
}{...}
}{...} else {
ret = bits & (mask >> 1);
}{...}
return ret;
}{ ... }
static uint32_t read_efuse_vref(void)
{
uint32_t ret = VREF_OFFSET;
uint32_t bits = efuse_ll_get_adc_vref();
ret += decode_bits(bits, VREF_MASK, VREF_FORMAT) * VREF_STEP_SIZE;
return ret;
}{ ... }
static uint32_t read_efuse_tp_low(adc_unit_t adc_num)
{
uint32_t ret;
uint32_t bits;
if (adc_num == ADC_UNIT_1) {
ret = TP_LOW1_OFFSET;
bits = efuse_ll_get_adc1_tp_low();
}{...} else {
ret = TP_LOW2_OFFSET;
bits = efuse_ll_get_adc2_tp_low();
}{...}
ret += decode_bits(bits, TP_LOW_MASK, true) * TP_STEP_SIZE;
return ret;
}{ ... }
static uint32_t read_efuse_tp_high(adc_unit_t adc_num)
{
uint32_t ret;
uint32_t bits;
if (adc_num == ADC_UNIT_1) {
ret = TP_HIGH1_OFFSET;
bits = efuse_ll_get_adc1_tp_high();
}{...} else {
ret = TP_HIGH2_OFFSET;
bits = efuse_ll_get_adc2_tp_high();
}{...}
ret += decode_bits(bits, TP_HIGH_MASK, true) * TP_STEP_SIZE;
return ret;
}{ ... }
----------------------- EFuse Access Functions
static void characterize_using_two_point(adc_unit_t adc_num,
adc_atten_t atten,
uint32_t high,
uint32_t low,
uint32_t *coeff_a,
uint32_t *coeff_b)
{
const uint32_t *atten_scales;
const uint32_t *atten_offsets;
if (adc_num == ADC_UNIT_1) {
atten_scales = adc1_tp_atten_scale;
atten_offsets = adc1_tp_atten_offset;
}{...} else {
atten_scales = adc2_tp_atten_scale;
atten_offsets = adc2_tp_atten_offset;
}{...}
uint32_t delta_x = high - low;
uint32_t delta_v = TP_HIGH_VOLTAGE - TP_LOW_VOLTAGE;
*coeff_a = (delta_v * atten_scales[atten] + (delta_x / 2)) / delta_x;
*coeff_b = TP_HIGH_VOLTAGE - ((delta_v * high + (delta_x / 2)) / delta_x) + atten_offsets[atten];
}{ ... }
static void characterize_using_vref(adc_unit_t adc_num,
adc_atten_t atten,
uint32_t vref,
uint32_t *coeff_a,
uint32_t *coeff_b)
{
const uint32_t *atten_scales;
const uint32_t *atten_offsets;
if (adc_num == ADC_UNIT_1) {
atten_scales = adc1_vref_atten_scale;
atten_offsets = adc1_vref_atten_offset;
}{...} else {
atten_scales = adc2_vref_atten_scale;
atten_offsets = adc2_vref_atten_offset;
}{...}
*coeff_a = (vref * atten_scales[atten]) / (ADC_12_BIT_RES);
*coeff_b = atten_offsets[atten];
}{ ... }
----------------------- Characterization Functions
static uint32_t calculate_voltage_linear(uint32_t adc_reading, uint32_t coeff_a, uint32_t coeff_b)
{
return (((coeff_a * adc_reading) + LIN_COEFF_A_ROUND) / LIN_COEFF_A_SCALE) + coeff_b;
}{ ... }
static uint32_t calculate_voltage_lut(uint32_t adc, uint32_t vref, const uint32_t *low_vref_curve, const uint32_t *high_vref_curve)
{
uint32_t i = (adc - LUT_LOW_THRESH) / LUT_ADC_STEP_SIZE;
int x2dist = LUT_VREF_HIGH - vref;
int x1dist = vref - LUT_VREF_LOW;
int y2dist = ((i + 1) * LUT_ADC_STEP_SIZE) + LUT_LOW_THRESH - adc;
int y1dist = adc - ((i * LUT_ADC_STEP_SIZE) + LUT_LOW_THRESH);
int q11 = low_vref_curve[i];
int q12 = low_vref_curve[i + 1];
int q21 = high_vref_curve[i];
int q22 = high_vref_curve[i + 1];
int voltage = (q11 * x2dist * y2dist) + (q21 * x1dist * y2dist) + (q12 * x2dist * y1dist) + (q22 * x1dist * y1dist);
voltage += ((LUT_VREF_HIGH - LUT_VREF_LOW) * LUT_ADC_STEP_SIZE) / 2;
voltage /= ((LUT_VREF_HIGH - LUT_VREF_LOW) * LUT_ADC_STEP_SIZE);
return (uint32_t)voltage;
}{ ... }
static inline uint32_t interpolate_two_points(uint32_t y1, uint32_t y2, uint32_t x_step, uint32_t x)
{
return ((y1 * x_step) + (y2 * x) - (y1 * x) + (x_step / 2)) / x_step;
}{ ... }
------------------------ Conversion Functions
esp_err_t esp_adc_cal_check_efuse(esp_adc_cal_value_t source)
{
if (source == ESP_ADC_CAL_VAL_EFUSE_TP) {
return (check_efuse_tp()) ? ESP_OK : ESP_ERR_NOT_SUPPORTED;
}{...} else if (source == ESP_ADC_CAL_VAL_EFUSE_VREF) {
return (check_efuse_vref()) ? ESP_OK : ESP_ERR_NOT_SUPPORTED;
}{...} else {
return ESP_ERR_INVALID_ARG;
}{...}
}{ ... }
esp_adc_cal_value_t 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)
{
assert((adc_num == ADC_UNIT_1) || (adc_num == ADC_UNIT_2));
assert(chars != NULL);
assert(bit_width < ADC_WIDTH_MAX);
bool efuse_tp_present = check_efuse_tp();
bool efuse_vref_present = check_efuse_vref();
esp_adc_cal_value_t ret;
if (efuse_tp_present && EFUSE_TP_ENABLED) {
uint32_t high = read_efuse_tp_high(adc_num);
uint32_t low = read_efuse_tp_low(adc_num);
characterize_using_two_point(adc_num, atten, high, low, &chars->coeff_a, &chars->coeff_b);
ret = ESP_ADC_CAL_VAL_EFUSE_TP;
}{...} else if (efuse_vref_present && EFUSE_VREF_ENABLED) {
uint32_t vref = read_efuse_vref();
characterize_using_vref(adc_num, atten, vref, &chars->coeff_a, &chars->coeff_b);
ret = ESP_ADC_CAL_VAL_EFUSE_VREF;
}{...} else {
characterize_using_vref(adc_num, atten, default_vref, &chars->coeff_a, &chars->coeff_b);
ret = ESP_ADC_CAL_VAL_DEFAULT_VREF;
}{...}
chars->adc_num = adc_num;
chars->atten = atten;
chars->bit_width = bit_width;
chars->vref = (EFUSE_VREF_ENABLED && efuse_vref_present) ? read_efuse_vref() : default_vref;
if (LUT_ENABLED && atten == ADC_ATTEN_DB_12) {
chars->low_curve = (adc_num == ADC_UNIT_1) ? lut_adc1_low : lut_adc2_low;
chars->high_curve = (adc_num == ADC_UNIT_1) ? lut_adc1_high : lut_adc2_high;
}{...} else {
chars->low_curve = NULL;
chars->high_curve = NULL;
}{...}
return ret;
}{ ... }
uint32_t esp_adc_cal_raw_to_voltage(uint32_t adc_reading, const esp_adc_cal_characteristics_t *chars)
{
assert(chars != NULL);
adc_reading = (adc_reading << (ADC_WIDTH_BIT_12 - chars->bit_width));
if (adc_reading > ADC_12_BIT_RES - 1) {
adc_reading = ADC_12_BIT_RES - 1;
}{...}
if (LUT_ENABLED && (chars->atten == ADC_ATTEN_DB_12) && (adc_reading >= LUT_LOW_THRESH)) {
uint32_t lut_voltage = calculate_voltage_lut(adc_reading, chars->vref, chars->low_curve, chars->high_curve);
if (adc_reading <= LUT_HIGH_THRESH) {
uint32_t linear_voltage = calculate_voltage_linear(adc_reading, chars->coeff_a, chars->coeff_b);
return interpolate_two_points(linear_voltage, lut_voltage, LUT_ADC_STEP_SIZE, (adc_reading - LUT_LOW_THRESH));
}{...} else {
return lut_voltage;
}{...}
}{...} else {
return calculate_voltage_linear(adc_reading, chars->coeff_a, chars->coeff_b);
}{...}
}{ ... }