1 /*
2  * SPDX-FileCopyrightText: 2020-2021 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 "esp_types.h"
10 #include "esp_err.h"
11 #include "esp_log.h"
12 #include "esp_check.h"
13 #include "driver/adc.h"
14 #include "hal/adc_types.h"
15 #include "esp_adc_cal.h"
16 #include "esp_adc_cal_internal.h"
17 
18 const static char *TAG = "ADC_CALI";
19 
esp_adc_cal_get_voltage(adc_channel_t channel,const esp_adc_cal_characteristics_t * chars,uint32_t * voltage)20 esp_err_t esp_adc_cal_get_voltage(adc_channel_t channel,
21                                   const esp_adc_cal_characteristics_t *chars,
22                                   uint32_t *voltage)
23 {
24     // Check parameters
25     ESP_RETURN_ON_FALSE(chars != NULL, ESP_ERR_INVALID_ARG, TAG, "No characteristic input");
26     ESP_RETURN_ON_FALSE(voltage != NULL, ESP_ERR_INVALID_ARG, TAG, "No output buffer");
27 
28     esp_err_t ret = ESP_OK;
29     int adc_reading;
30     if (chars->adc_num == ADC_UNIT_1) {
31         ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(0), ESP_ERR_INVALID_ARG, TAG, "Invalid channel");
32         adc_reading = adc1_get_raw(channel);
33     } else {
34         ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(1), ESP_ERR_INVALID_ARG, TAG, "Invalid channel");
35         ret = adc2_get_raw(channel, chars->bit_width, &adc_reading);
36     }
37     *voltage = esp_adc_cal_raw_to_voltage((uint32_t)adc_reading, chars);
38     return ret;
39 }
40 
41 #if ESP_ADC_CAL_CURVE_FITTING_SUPPORTED
42 /*------------------------------------------------------------------------------
43  * Private API
44  *----------------------------------------------------------------------------*/
esp_adc_cal_get_reading_error(const esp_adc_error_calc_param_t * param,uint8_t atten)45 int32_t esp_adc_cal_get_reading_error(const esp_adc_error_calc_param_t *param, uint8_t atten)
46 {
47     if (param->v_cali_input == 0) {
48         return 0;
49     }
50 
51     uint64_t v_cali_1 = param->v_cali_input;
52     uint8_t term_num = param->term_num;
53     int32_t error = 0;
54     uint64_t coeff = 0;
55     uint64_t variable[term_num];
56     uint64_t term[term_num];
57     memset(variable, 0, term_num * sizeof(uint64_t));
58     memset(term, 0, term_num * sizeof(uint64_t));
59 
60     /**
61      * For atten0 ~ 2:
62      * error = (K0 * X^0) + (K1 * X^1) + (K2 * X^2);
63      *
64      * For atten3:
65      * error = (K0 * X^0) + (K1 * X^1)  + (K2 * X^2) + (K3 * X^3) + (K4 * X^4);
66      */
67     variable[0] = 1;
68     coeff = (*param->coeff)[atten][0][0];
69     term[0] = variable[0] * coeff / (*param->coeff)[atten][0][1];
70     error = (int32_t)term[0] * (*param->sign)[atten][0];
71 
72     for (int i = 1; i < term_num; i++) {
73         variable[i] = variable[i-1] * v_cali_1;
74         coeff = (*param->coeff)[atten][i][0];
75         term[i] = variable[i] * coeff;
76         ESP_LOGV(TAG, "big coef is %llu, big term%d is %llu, coef_id is %d", coeff, i, term[i], i);
77 
78         term[i] = term[i] / (*param->coeff)[atten][i][1];
79         error += (int32_t)term[i] * (*param->sign)[atten][i];
80         ESP_LOGV(TAG, "term%d is %llu, error is %d", i, term[i], error);
81     }
82 
83     return error;
84 }
85 #endif  //#if ESP_ADC_CAL_CURVE_FITTING_SUPPORTED
86