1 /*
2 * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <stdint.h>
8 #include <string.h>
9 #include "inttypes.h"
10 #include "sdkconfig.h"
11
12 #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
13 #include "esp_types.h"
14 #include "esp_err.h"
15 #include "esp_log.h"
16 #include "esp_check.h"
17 #include "hal/adc_types.h"
18 #define CONFIG_ADC_SUPPRESS_DEPRECATE_WARN 1
19 #include "esp_adc_cal.h"
20 #include "esp_adc_cal_internal_legacy.h"
21 #include "driver/adc.h"
22
23 const __attribute__((unused)) static char *TAG = "ADC_CALI";
24
esp_adc_cal_get_voltage(adc_channel_t channel,const esp_adc_cal_characteristics_t * chars,uint32_t * voltage)25 esp_err_t esp_adc_cal_get_voltage(adc_channel_t channel,
26 const esp_adc_cal_characteristics_t *chars,
27 uint32_t *voltage)
28 {
29 // Check parameters
30 ESP_RETURN_ON_FALSE(chars != NULL, ESP_ERR_INVALID_ARG, TAG, "No characteristic input");
31 ESP_RETURN_ON_FALSE(voltage != NULL, ESP_ERR_INVALID_ARG, TAG, "No output buffer");
32
33 esp_err_t ret = ESP_OK;
34 int adc_reading;
35 if (chars->adc_num == ADC_UNIT_1) {
36 ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(0), ESP_ERR_INVALID_ARG, TAG, "Invalid channel");
37 adc_reading = adc1_get_raw(channel);
38 } else {
39 ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(1), ESP_ERR_INVALID_ARG, TAG, "Invalid channel");
40 ret = adc2_get_raw(channel, chars->bit_width, &adc_reading);
41 }
42
43 if (ret == ESP_OK) {
44 *voltage = esp_adc_cal_raw_to_voltage((uint32_t)adc_reading, chars);
45 }
46 return ret;
47 }
48
49
50 #if ESP_ADC_CAL_CURVE_FITTING_SUPPORTED
51 /*------------------------------------------------------------------------------
52 * Private API
53 *----------------------------------------------------------------------------*/
esp_adc_cal_get_reading_error(const esp_adc_error_calc_param_t * param,uint8_t atten)54 int32_t esp_adc_cal_get_reading_error(const esp_adc_error_calc_param_t *param, uint8_t atten)
55 {
56 if (param->v_cali_input == 0) {
57 return 0;
58 }
59
60 uint64_t v_cali_1 = param->v_cali_input;
61 uint8_t term_num = param->term_num;
62 int32_t error = 0;
63 uint64_t coeff = 0;
64 uint64_t *variable = (uint64_t *)malloc(term_num * sizeof(uint64_t));
65 uint64_t *term = (uint64_t *)malloc(term_num * sizeof(uint64_t));
66
67 if (variable == NULL || term == NULL) {
68 return ESP_ERR_NO_MEM;
69 }
70
71 memset(variable, 0, term_num * sizeof(uint64_t));
72 memset(term, 0, term_num * sizeof(uint64_t));
73
74 /**
75 * For atten0 ~ 2:
76 * error = (K0 * X^0) + (K1 * X^1) + (K2 * X^2);
77 *
78 * For atten3:
79 * error = (K0 * X^0) + (K1 * X^1) + (K2 * X^2) + (K3 * X^3) + (K4 * X^4);
80 */
81 variable[0] = 1;
82 coeff = (*param->coeff)[atten][0][0];
83 term[0] = variable[0] * coeff / (*param->coeff)[atten][0][1];
84 error = (int32_t)term[0] * (*param->sign)[atten][0];
85
86 for (int i = 1; i < term_num; i++) {
87 variable[i] = variable[i-1] * v_cali_1;
88 coeff = (*param->coeff)[atten][i][0];
89 term[i] = variable[i] * coeff;
90 ESP_LOGV(TAG, "big coef is %llu, big term%d is %llu, coef_id is %d", coeff, i, term[i], i);
91
92 term[i] = term[i] / (*param->coeff)[atten][i][1];
93 error += (int32_t)term[i] * (*param->sign)[atten][i];
94 ESP_LOGV(TAG, "term%d is %llu, error is %"PRId32, i, term[i], error);
95 }
96
97 return error;
98 }
99 #endif //#if ESP_ADC_CAL_CURVE_FITTING_SUPPORTED
100
101 #endif //#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
102