1 /*
2  * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef __ESP_ADC_CAL_H__
8 #define __ESP_ADC_CAL_H__
9 
10 #include <stdint.h>
11 #include "esp_err.h"
12 #include "driver/adc.h"
13 
14 #ifdef __cplusplus
15 extern "C" {
16 #endif
17 
18 /**
19  * @brief Type of calibration value used in characterization
20  */
21 typedef enum {
22     ESP_ADC_CAL_VAL_EFUSE_VREF = 0,         /**< Characterization based on reference voltage stored in eFuse*/
23     ESP_ADC_CAL_VAL_EFUSE_TP = 1,           /**< Characterization based on Two Point values stored in eFuse*/
24     ESP_ADC_CAL_VAL_DEFAULT_VREF = 2,       /**< Characterization based on default reference voltage*/
25     ESP_ADC_CAL_VAL_EFUSE_TP_FIT = 3,       /**< Characterization based on Two Point values and fitting curve coefficients stored in eFuse */
26     ESP_ADC_CAL_VAL_MAX,
27     ESP_ADC_CAL_VAL_NOT_SUPPORTED = ESP_ADC_CAL_VAL_MAX,
28 } esp_adc_cal_value_t;
29 
30 /**
31  * @brief Structure storing characteristics of an ADC
32  *
33  * @note Call esp_adc_cal_characterize() to initialize the structure
34  */
35 typedef struct {
36     adc_unit_t adc_num;                     /**< ADC number*/
37     adc_atten_t atten;                      /**< ADC attenuation*/
38     adc_bits_width_t bit_width;             /**< ADC bit width */
39     uint32_t coeff_a;                       /**< Gradient of ADC-Voltage curve*/
40     uint32_t coeff_b;                       /**< Offset of ADC-Voltage curve*/
41     uint32_t vref;                          /**< Vref used by lookup table*/
42     const uint32_t *low_curve;              /**< Pointer to low Vref curve of lookup table (NULL if unused)*/
43     const uint32_t *high_curve;             /**< Pointer to high Vref curve of lookup table (NULL if unused)*/
44     uint8_t version;                        /**< ADC Calibration */
45 } esp_adc_cal_characteristics_t;
46 
47 /**
48  * @brief Checks if ADC calibration values are burned into eFuse
49  *
50  * This function checks if ADC reference voltage or Two Point values have been
51  * burned to the eFuse of the current ESP32
52  *
53  * @param   value_type  Type of calibration value (ESP_ADC_CAL_VAL_EFUSE_VREF or ESP_ADC_CAL_VAL_EFUSE_TP)
54  * @note in ESP32S2, only ESP_ADC_CAL_VAL_EFUSE_TP is supported. Some old ESP32S2s do not support this, either.
55  * In which case you have to calibrate it manually, possibly by performing your own two-point calibration on the chip.
56  *
57  * @return
58  *      - ESP_OK: The calibration mode is supported in eFuse
59  *      - ESP_ERR_NOT_SUPPORTED: Error, eFuse values are not burned
60  *      - ESP_ERR_INVALID_ARG: Error, invalid argument (ESP_ADC_CAL_VAL_DEFAULT_VREF)
61  */
62 esp_err_t esp_adc_cal_check_efuse(esp_adc_cal_value_t value_type);
63 
64 /**
65  * @brief Characterize an ADC at a particular attenuation
66  *
67  * This function will characterize the ADC at a particular attenuation and generate
68  * the ADC-Voltage curve in the form of [y = coeff_a * x + coeff_b].
69  * Characterization can be based on Two Point values, eFuse Vref, or default Vref
70  * and the calibration values will be prioritized in that order.
71  *
72  * @note
73  * For ESP32, Two Point values and eFuse Vref calibration can be enabled/disabled using menuconfig.
74  * For ESP32s2, only Two Point values calibration and only ADC_WIDTH_BIT_13 is supported. The parameter default_vref is unused.
75  *
76  *
77  * @param[in]   adc_num         ADC to characterize (ADC_UNIT_1 or ADC_UNIT_2)
78  * @param[in]   atten           Attenuation to characterize
79  * @param[in]   bit_width       Bit width configuration of ADC
80  * @param[in]   default_vref    Default ADC reference voltage in mV (Only in ESP32, used if eFuse values is not available)
81  * @param[out]  chars           Pointer to empty structure used to store ADC characteristics
82  *
83  * @return
84  *      - ESP_ADC_CAL_VAL_EFUSE_VREF: eFuse Vref used for characterization
85  *      - ESP_ADC_CAL_VAL_EFUSE_TP: Two Point value used for characterization (only in Linear Mode)
86  *      - ESP_ADC_CAL_VAL_DEFAULT_VREF: Default Vref used for characterization
87  */
88 esp_adc_cal_value_t esp_adc_cal_characterize(adc_unit_t adc_num,
89                                              adc_atten_t atten,
90                                              adc_bits_width_t bit_width,
91                                              uint32_t default_vref,
92                                              esp_adc_cal_characteristics_t *chars);
93 
94 /**
95  * @brief   Convert an ADC reading to voltage in mV
96  *
97  * This function converts an ADC reading to a voltage in mV based on the ADC's
98  * characteristics.
99  *
100  * @note    Characteristics structure must be initialized before this function
101  *          is called (call esp_adc_cal_characterize())
102  *
103  * @param[in]   adc_reading     ADC reading
104  * @param[in]   chars           Pointer to initialized structure containing ADC characteristics
105  *
106  * @return      Voltage in mV
107  */
108 uint32_t esp_adc_cal_raw_to_voltage(uint32_t adc_reading, const esp_adc_cal_characteristics_t *chars);
109 
110 /**
111  * @brief   Reads an ADC and converts the reading to a voltage in mV
112  *
113  * This function reads an ADC then converts the raw reading to a voltage in mV
114  * based on the characteristics provided. The ADC that is read is also
115  * determined by the characteristics.
116  *
117  * @note    The Characteristics structure must be initialized before this
118  *          function is called (call esp_adc_cal_characterize())
119  *
120  * @param[in]   channel     ADC Channel to read
121  * @param[in]   chars       Pointer to initialized ADC characteristics structure
122  * @param[out]  voltage     Pointer to store converted voltage
123  *
124  * @return
125  *      - ESP_OK: ADC read and converted to mV
126  *      - ESP_ERR_INVALID_ARG: Error due to invalid arguments
127  *      - ESP_ERR_INVALID_STATE: Reading result is invalid. Try to read again.
128  */
129 esp_err_t esp_adc_cal_get_voltage(adc_channel_t channel, const esp_adc_cal_characteristics_t *chars, uint32_t *voltage);
130 
131 #ifdef __cplusplus
132 }
133 #endif
134 
135 #endif /* __ESP_ADC_CAL_H__ */
136