1 /*
2  * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <esp_types.h>
8 #include "sdkconfig.h"
9 #include "esp_log.h"
10 #include "esp_check.h"
11 #include "freertos/FreeRTOS.h"
12 #include "esp_private/periph_ctrl.h"
13 #include "esp_private/adc_private.h"
14 #include "esp_private/adc_share_hw_ctrl.h"
15 #include "driver/gpio.h"
16 #include "hal/adc_hal.h"
17 #include "hal/adc_hal_common.h"
18 #include "soc/adc_periph.h"
19 
20 
21 static const char *TAG = "adc_common";
22 static portMUX_TYPE s_spinlock = portMUX_INITIALIZER_UNLOCKED;
23 extern portMUX_TYPE rtc_spinlock;
24 
25 /*------------------------------------------------------------------------------
26 * For those who use APB_SARADC periph
27 *----------------------------------------------------------------------------*/
28 static int s_adc_digi_ctrlr_cnt;
29 
adc_apb_periph_claim(void)30 void adc_apb_periph_claim(void)
31 {
32     portENTER_CRITICAL(&s_spinlock);
33     s_adc_digi_ctrlr_cnt++;
34     if (s_adc_digi_ctrlr_cnt == 1) {
35         //enable ADC digital part
36         periph_module_enable(PERIPH_SARADC_MODULE);
37         //reset ADC digital part
38         periph_module_reset(PERIPH_SARADC_MODULE);
39     }
40 
41     portEXIT_CRITICAL(&s_spinlock);
42 }
43 
adc_apb_periph_free(void)44 void adc_apb_periph_free(void)
45 {
46     portENTER_CRITICAL(&s_spinlock);
47     s_adc_digi_ctrlr_cnt--;
48     if (s_adc_digi_ctrlr_cnt == 0) {
49         periph_module_disable(PERIPH_SARADC_MODULE);
50     } else if (s_adc_digi_ctrlr_cnt < 0) {
51         portEXIT_CRITICAL(&s_spinlock);
52         ESP_LOGE(TAG, "%s called, but `s_adc_digi_ctrlr_cnt == 0`", __func__);
53         abort();
54     }
55 
56     portEXIT_CRITICAL(&s_spinlock);
57 }
58 
59 /*---------------------------------------------------------------
60             ADC IOs
61 ---------------------------------------------------------------*/
adc_io_to_channel(int io_num,adc_unit_t * unit_id,adc_channel_t * channel)62 esp_err_t adc_io_to_channel(int io_num, adc_unit_t *unit_id, adc_channel_t *channel)
63 {
64     ESP_RETURN_ON_FALSE(GPIO_IS_VALID_GPIO(io_num), ESP_ERR_INVALID_ARG, TAG, "invalid gpio number");
65     ESP_RETURN_ON_FALSE(unit_id && channel, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
66 
67     bool found = false;
68     for (int i = 0; i < SOC_ADC_PERIPH_NUM; i++) {
69         for (int j = 0; j < SOC_ADC_MAX_CHANNEL_NUM; j++) {
70             if (adc_channel_io_map[i][j] == io_num) {
71                 *channel = j;
72                 *unit_id = i;
73                 found = true;
74             }
75         }
76     }
77     return (found) ? ESP_OK : ESP_ERR_NOT_FOUND;
78 }
79 
adc_channel_to_io(adc_unit_t unit_id,adc_channel_t channel,int * io_num)80 esp_err_t adc_channel_to_io(adc_unit_t unit_id, adc_channel_t channel, int *io_num)
81 {
82     ESP_RETURN_ON_FALSE(unit_id < SOC_ADC_PERIPH_NUM, ESP_ERR_INVALID_ARG, TAG, "invalid unit");
83     ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(unit_id), ESP_ERR_INVALID_ARG, TAG, "invalid channel");
84     ESP_RETURN_ON_FALSE(io_num, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
85 
86     *io_num = adc_channel_io_map[unit_id][channel];
87     return ESP_OK;
88 }
89 
90 #if SOC_ADC_CALIBRATION_V1_SUPPORTED
91 /*---------------------------------------------------------------
92             ADC Hardware Calibration
93 ---------------------------------------------------------------*/
adc_hw_calibration(void)94 static void adc_hw_calibration(void)
95 {
96     //Calculate all ICode
97     for (int i = 0; i < SOC_ADC_PERIPH_NUM; i++) {
98         adc_hal_calibration_init(i);
99         for (int j = 0; j < SOC_ADC_ATTEN_NUM; j++) {
100             /**
101              * This may get wrong when attenuations are NOT consecutive on some chips,
102              * update this when bringing up the calibration on that chip
103              */
104             adc_calc_hw_calibration_code(i, j);
105 #if SOC_ADC_CALIB_CHAN_COMPENS_SUPPORTED
106             /* Load the channel compensation from efuse */
107             for (int k = 0; k < SOC_ADC_CHANNEL_NUM(i); k++) {
108                 adc_load_hw_calibration_chan_compens(i, k, j);
109             }
110 #endif
111         }
112     }
113 }
114 #endif //#if SOC_ADC_CALIBRATION_V1_SUPPORTED
115