diff --git a/components/driver/dac/esp32s2/dac_dma.c b/components/driver/dac/esp32s2/dac_dma.c index cc65730ba5..25d9ceaf40 100644 --- a/components/driver/dac/esp32s2/dac_dma.c +++ b/components/driver/dac/esp32s2/dac_dma.c @@ -129,7 +129,7 @@ finish: dac_ll_digi_clk_inv(true); dac_ll_digi_set_trigger_interval(interval); // secondary clock division adc_ll_digi_controller_clk_div(clk_div - 1, b, a); - adc_ll_digi_clk_sel(is_apll); + adc_ll_digi_clk_sel(is_apll ? ADC_DIGI_CLK_SRC_APLL : ADC_DIGI_CLK_SRC_DEFAULT); return ESP_OK; } diff --git a/components/driver/deprecated/adc_legacy.c b/components/driver/deprecated/adc_legacy.c index 11c2906756..2a864463cb 100644 --- a/components/driver/deprecated/adc_legacy.c +++ b/components/driver/deprecated/adc_legacy.c @@ -617,11 +617,11 @@ esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio) adc_power_acquire(); if (adc_unit == ADC_UNIT_1) { VREF_ENTER(1); - adc_hal_vref_output(ADC_UNIT_1, ch, true); + adc_ll_vref_output(ADC_UNIT_1, ch, true); VREF_EXIT(1); } else if (adc_unit == ADC_UNIT_2) { VREF_ENTER(2); - adc_hal_vref_output(ADC_UNIT_2, ch, true); + adc_ll_vref_output(ADC_UNIT_2, ch, true); VREF_EXIT(2); } @@ -706,11 +706,11 @@ esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio) adc_power_acquire(); if (adc_unit == ADC_UNIT_1) { RTC_ENTER_CRITICAL(); - adc_hal_vref_output(ADC_UNIT_1, channel, true); + adc_ll_vref_output(ADC_UNIT_1, channel, true); RTC_EXIT_CRITICAL(); } else { //ADC_UNIT_2 RTC_ENTER_CRITICAL(); - adc_hal_vref_output(ADC_UNIT_2, channel, true); + adc_ll_vref_output(ADC_UNIT_2, channel, true); RTC_EXIT_CRITICAL(); } @@ -756,7 +756,7 @@ int adc1_get_raw(adc1_channel_t channel) periph_module_enable(PERIPH_SARADC_MODULE); adc_power_acquire(); - adc_ll_digi_clk_sel(0); + adc_ll_digi_clk_sel(ADC_DIGI_CLK_SRC_DEFAULT); adc_atten_t atten = s_atten1_single[channel]; #if SOC_ADC_CALIBRATION_V1_SUPPORTED @@ -807,7 +807,7 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int * periph_module_enable(PERIPH_SARADC_MODULE); adc_power_acquire(); - adc_ll_digi_clk_sel(0); + adc_ll_digi_clk_sel(ADC_DIGI_CLK_SRC_DEFAULT); adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT(); adc_hal_arbiter_config(&config); diff --git a/components/driver/deprecated/driver/adc_types_legacy.h b/components/driver/deprecated/driver/adc_types_legacy.h index 1a2b2a4d55..117d469600 100644 --- a/components/driver/deprecated/driver/adc_types_legacy.h +++ b/components/driver/deprecated/driver/adc_types_legacy.h @@ -61,7 +61,7 @@ typedef enum { ADC1_CHANNEL_9, /*!< ADC1 channel 9 is GPIO10 */ ADC1_CHANNEL_MAX, } adc1_channel_t; -#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32H4 || CONFIG_IDF_TARGET_ESP32C6 // TODO: IDF-5310 +#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32H4 typedef enum { ADC1_CHANNEL_0 = 0, /*!< ADC1 channel 0 is GPIO0 */ ADC1_CHANNEL_1, /*!< ADC1 channel 1 is GPIO1 */ @@ -70,6 +70,17 @@ typedef enum { ADC1_CHANNEL_4, /*!< ADC1 channel 4 is GPIO4 */ ADC1_CHANNEL_MAX, } adc1_channel_t; +#elif CONFIG_IDF_TARGET_ESP32C6 +typedef enum { + ADC1_CHANNEL_0 = 0, /*!< ADC1 channel 0 is GPIO0 */ + ADC1_CHANNEL_1, /*!< ADC1 channel 1 is GPIO1 */ + ADC1_CHANNEL_2, /*!< ADC1 channel 2 is GPIO2 */ + ADC1_CHANNEL_3, /*!< ADC1 channel 3 is GPIO3 */ + ADC1_CHANNEL_4, /*!< ADC1 channel 4 is GPIO4 */ + ADC1_CHANNEL_5, /*!< ADC1 channel 5 is GPIO5 */ + ADC1_CHANNEL_6, /*!< ADC1 channel 6 is GPIO6 */ + ADC1_CHANNEL_MAX, +} adc1_channel_t; #endif // CONFIG_IDF_TARGET_* #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 @@ -86,7 +97,8 @@ typedef enum { ADC2_CHANNEL_9, /*!< ADC2 channel 9 is GPIO26 (ESP32), GPIO20 (ESP32-S2) */ ADC2_CHANNEL_MAX, } adc2_channel_t; -#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32H4 || CONFIG_IDF_TARGET_ESP32C6 // TODO: IDF-5310 +#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32H4 +// ESP32C6 has no ADC2 typedef enum { ADC2_CHANNEL_0 = 0, /*!< ADC2 channel 0 is GPIO5 */ ADC2_CHANNEL_MAX, diff --git a/components/driver/deprecated/esp32s2/dac_legacy.c b/components/driver/deprecated/esp32s2/dac_legacy.c index 3e09d4c869..6f92bce6d0 100644 --- a/components/driver/deprecated/esp32s2/dac_legacy.c +++ b/components/driver/deprecated/esp32s2/dac_legacy.c @@ -82,7 +82,7 @@ esp_err_t dac_digi_controller_config(const dac_digi_config_t *cfg) dac_ll_digi_set_convert_mode(cfg->mode == DAC_CONV_ALTER); dac_ll_digi_set_trigger_interval(cfg->interval); adc_ll_digi_controller_clk_div(cfg->dig_clk.div_num, cfg->dig_clk.div_b, cfg->dig_clk.div_a); - adc_ll_digi_clk_sel(cfg->dig_clk.use_apll); + adc_ll_digi_clk_sel(cfg->dig_clk.use_apll ? ADC_DIGI_CLK_SRC_APLL : ADC_DIGI_CLK_SRC_DEFAULT); DAC_EXIT_CRITICAL(); return ESP_OK; diff --git a/components/hal/adc_hal.c b/components/hal/adc_hal.c index bc974e706c..eafc2fcf10 100644 --- a/components/hal/adc_hal.c +++ b/components/hal/adc_hal.c @@ -177,7 +177,7 @@ static void adc_hal_digi_sample_freq_config(adc_hal_dma_ctx_t *hal, uint32_t fre adc_ll_digi_set_trigger_interval(interval); //Here we set the clock divider factor to make the digital clock to 5M Hz adc_ll_digi_controller_clk_div(ADC_LL_CLKM_DIV_NUM_DEFAULT, ADC_LL_CLKM_DIV_B_DEFAULT, ADC_LL_CLKM_DIV_A_DEFAULT); - adc_ll_digi_clk_sel(0); //use APB + adc_ll_digi_clk_sel(ADC_DIGI_CLK_SRC_DEFAULT); // use default clock source for ADC digital controller #else i2s_ll_rx_clk_set_src(hal->dev, I2S_CLK_SRC_DEFAULT); /*!< Clock from PLL_D2_CLK(160M)*/ uint32_t bclk_div = 16; diff --git a/components/hal/adc_oneshot_hal.c b/components/hal/adc_oneshot_hal.c index 27ee5283a2..3b1c7f3bfa 100644 --- a/components/hal/adc_oneshot_hal.c +++ b/components/hal/adc_oneshot_hal.c @@ -57,7 +57,7 @@ void adc_oneshot_hal_setup(adc_oneshot_hal_ctx_t *hal, adc_channel_t chan) #endif #if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED - adc_ll_digi_clk_sel(0); + adc_ll_digi_clk_sel(ADC_DIGI_CLK_SRC_DEFAULT); #else adc_ll_set_sar_clk_div(unit, ADC_HAL_SAR_CLK_DIV_DEFAULT(unit)); if (unit == ADC_UNIT_2) { diff --git a/components/hal/esp32/include/hal/adc_ll.h b/components/hal/esp32/include/hal/adc_ll.h index d4dd029acf..dff4e6d3a7 100644 --- a/components/hal/esp32/include/hal/adc_ll.h +++ b/components/hal/esp32/include/hal/adc_ll.h @@ -15,6 +15,7 @@ #include "soc/sens_struct.h" #include "soc/syscon_struct.h" #include "soc/rtc_cntl_struct.h" +#include "soc/clk_tree_defs.h" #ifdef __cplusplus extern "C" { @@ -45,6 +46,12 @@ typedef enum { ADC_LL_CTRL_PWDET = 3, ///< For ADC2. Select PWDET controller. } adc_ll_controller_t; +/** + * @brief Clock source of ADC digital controller + * @note Not public as it always uses a default value for now + */ +typedef soc_periph_adc_digi_clk_src_t adc_ll_digi_clk_src_t; + /** * @brief ADC digital controller (DMA mode) work mode. * diff --git a/components/hal/esp32c2/include/hal/adc_ll.h b/components/hal/esp32c2/include/hal/adc_ll.h index e9d51a288e..89a6a986f1 100644 --- a/components/hal/esp32c2/include/hal/adc_ll.h +++ b/components/hal/esp32c2/include/hal/adc_ll.h @@ -14,6 +14,7 @@ #include "soc/apb_saradc_reg.h" #include "soc/rtc_cntl_struct.h" #include "soc/rtc_cntl_reg.h" +#include "soc/clk_tree_defs.h" #include "hal/misc.h" #include "hal/assert.h" #include "hal/adc_types.h" @@ -33,9 +34,9 @@ extern "C" { #define ADC_LL_EVENT_ADC2_ONESHOT_DONE BIT(30) typedef enum { - ADC_POWER_BY_FSM, /*!< ADC XPD controled by FSM. Used for polling mode */ - ADC_POWER_SW_ON, /*!< ADC XPD controled by SW. power on. Used for DMA mode */ - ADC_POWER_SW_OFF, /*!< ADC XPD controled by SW. power off. */ + ADC_POWER_BY_FSM, /*!< ADC XPD controlled by FSM. Used for polling mode */ + ADC_POWER_SW_ON, /*!< ADC XPD controlled by SW. power on. Used for DMA mode */ + ADC_POWER_SW_OFF, /*!< ADC XPD controlled by SW. power off. */ ADC_POWER_MAX, /*!< For parameter check. */ } adc_ll_power_t; @@ -50,6 +51,12 @@ typedef enum { ADC_LL_CTRL_DIG = 0, ///< For ADC1. Select DIG controller. } adc_ll_controller_t; +/** + * @brief Clock source of ADC digital controller + * @note Not public as it always uses a default value for now + */ +typedef soc_periph_adc_digi_clk_src_t adc_ll_digi_clk_src_t; + /*--------------------------------------------------------------- Digital controller setting ---------------------------------------------------------------*/ @@ -93,7 +100,7 @@ static inline void adc_ll_set_sample_cycle(uint32_t sample_cycle) */ static inline void adc_ll_digi_set_clk_div(uint32_t div) { - /* ADC clock devided from digital controller clock clk */ + /* ADC clock divided from digital controller clock clk */ HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.saradc_ctrl, saradc_saradc_sar_clk_div, div); } @@ -141,15 +148,11 @@ static inline void adc_ll_digi_controller_clk_div(uint32_t div_num, uint32_t div /** * Enable clock and select clock source for ADC digital controller. * - * @param use_apll true: use APLL clock; false: use APB clock. + * @param clk_src clock source for ADC digital controller. */ -static inline void adc_ll_digi_clk_sel(bool use_apll) +static inline void adc_ll_digi_clk_sel(adc_ll_digi_clk_src_t clk_src) { - if (use_apll) { - APB_SARADC.saradc_apb_adc_clkm_conf.saradc_reg_clk_sel = 1; // APLL clock - } else { - APB_SARADC.saradc_apb_adc_clkm_conf.saradc_reg_clk_sel = 2; // APB clock - } + APB_SARADC.saradc_apb_adc_clkm_conf.saradc_reg_clk_sel = (clk_src == ADC_DIGI_CLK_SRC_XTAL); APB_SARADC.saradc_ctrl.saradc_saradc_sar_clk_gated = 1; } diff --git a/components/hal/esp32c3/include/hal/adc_ll.h b/components/hal/esp32c3/include/hal/adc_ll.h index 399044390d..117e43dbe5 100644 --- a/components/hal/esp32c3/include/hal/adc_ll.h +++ b/components/hal/esp32c3/include/hal/adc_ll.h @@ -14,6 +14,7 @@ #include "soc/apb_saradc_reg.h" #include "soc/rtc_cntl_struct.h" #include "soc/rtc_cntl_reg.h" +#include "soc/clk_tree_defs.h" #include "hal/misc.h" #include "hal/assert.h" #include "hal/adc_types.h" @@ -40,9 +41,9 @@ extern "C" { #define ADC_LL_EVENT_THRES1_LOW BIT(26) typedef enum { - ADC_POWER_BY_FSM, /*!< ADC XPD controled by FSM. Used for polling mode */ - ADC_POWER_SW_ON, /*!< ADC XPD controled by SW. power on. Used for DMA mode */ - ADC_POWER_SW_OFF, /*!< ADC XPD controled by SW. power off. */ + ADC_POWER_BY_FSM, /*!< ADC XPD controlled by FSM. Used for polling mode */ + ADC_POWER_SW_ON, /*!< ADC XPD controlled by SW. power on. Used for DMA mode */ + ADC_POWER_SW_OFF, /*!< ADC XPD controlled by SW. power off. */ ADC_POWER_MAX, /*!< For parameter check. */ } adc_ll_power_t; @@ -58,6 +59,12 @@ typedef enum { ADC_LL_CTRL_ARB = 1, ///< For ADC2. The controller is selected by the arbiter. } adc_ll_controller_t; +/** + * @brief Clock source of ADC digital controller + * @note Not public as it always uses a default value for now + */ +typedef soc_periph_adc_digi_clk_src_t adc_ll_digi_clk_src_t; + /** * @brief ADC digital controller (DMA mode) work mode. * @@ -124,7 +131,7 @@ static inline void adc_ll_set_sample_cycle(uint32_t sample_cycle) */ static inline void adc_ll_digi_set_clk_div(uint32_t div) { - /* ADC clock devided from digital controller clock clk */ + /* ADC clock divided from digital controller clock clk */ HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.ctrl, sar_clk_div, div); } @@ -283,15 +290,12 @@ static inline void adc_ll_digi_controller_clk_div(uint32_t div_num, uint32_t div /** * Enable clock and select clock source for ADC digital controller. * - * @param use_apll true: use APLL clock; false: use APB clock. + * @param clk_src clock source for ADC digital controller. */ -static inline void adc_ll_digi_clk_sel(bool use_apll) +static inline void adc_ll_digi_clk_sel(adc_ll_digi_clk_src_t clk_src) { - if (use_apll) { - APB_SARADC.apb_adc_clkm_conf.clk_sel = 1; // APLL clock - } else { - APB_SARADC.apb_adc_clkm_conf.clk_sel = 2; // APB clock - } + // Only support APB clock, should always set to 0 + APB_SARADC.apb_adc_clkm_conf.clk_sel = 0; APB_SARADC.ctrl.sar_clk_gated = 1; } @@ -643,60 +647,6 @@ static inline void adc_ll_set_calibration_param(adc_unit_t adc_n, uint32_t param } /* Temp code end. */ -/** - * Output ADCn inter reference voltage to ADC2 channels. - * - * This function routes the internal reference voltage of ADCn to one of - * ADC1's channels. This reference voltage can then be manually measured - * for calibration purposes. - * - * @param[in] adc ADC unit select - * @param[in] channel ADC1 channel number - * @param[in] en Enable/disable the reference voltage output - */ -static inline void adc_ll_vref_output(adc_unit_t adc, adc_channel_t channel, bool en) -{ - if (en) { - REG_SET_FIELD(RTC_CNTL_SENSOR_CTRL_REG, RTC_CNTL_FORCE_XPD_SAR, 3); - SET_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU); - - REG_SET_FIELD(APB_SARADC_APB_ADC_CLKM_CONF_REG, APB_SARADC_CLK_SEL, 2); - SET_PERI_REG_MASK(APB_SARADC_APB_ADC_CLKM_CONF_REG, APB_SARADC_CLK_EN); - SET_PERI_REG_MASK(APB_SARADC_APB_ADC_ARB_CTRL_REG, APB_SARADC_ADC_ARB_GRANT_FORCE); - SET_PERI_REG_MASK(APB_SARADC_APB_ADC_ARB_CTRL_REG, APB_SARADC_ADC_ARB_APB_FORCE); - APB_SARADC.sar_patt_tab[0].sar_patt_tab1 = 0xFFFFFF; - APB_SARADC.sar_patt_tab[1].sar_patt_tab1 = 0xFFFFFF; - APB_SARADC.onetime_sample.adc1_onetime_sample = 1; - APB_SARADC.onetime_sample.onetime_channel = channel; - SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_PU); - if (adc == ADC_UNIT_1) { - /* Config test mux to route v_ref to ADC1 Channels */ - REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC1_ENCAL_REF_ADDR, 1); - REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_DTEST_RTC_ADDR, 1); - REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_TSENS_ADDR, 0); - REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_RTC_ADDR, 1); - } else { - /* Config test mux to route v_ref to ADC2 Channels */ - REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC2_ENCAL_REF_ADDR, 1); - REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_DTEST_RTC_ADDR, 0); - REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_TSENS_ADDR, 0); - REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_RTC_ADDR, 0); - } - } else { - REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC2_ENCAL_REF_ADDR, 0); - REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC1_ENCAL_REF_ADDR, 0); - REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_DTEST_RTC_ADDR, 0); - REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_RTC_ADDR, 0); - APB_SARADC.onetime_sample.adc1_onetime_sample = 0; - APB_SARADC.onetime_sample.onetime_channel = 0xf; - REG_SET_FIELD(RTC_CNTL_SENSOR_CTRL_REG, RTC_CNTL_FORCE_XPD_SAR, 0); - REG_SET_FIELD(APB_SARADC_APB_ADC_CLKM_CONF_REG, APB_SARADC_CLK_SEL, 0); - CLEAR_PERI_REG_MASK(APB_SARADC_APB_ADC_CLKM_CONF_REG, APB_SARADC_CLK_EN); - CLEAR_PERI_REG_MASK(APB_SARADC_APB_ADC_ARB_CTRL_REG, APB_SARADC_ADC_ARB_GRANT_FORCE); - CLEAR_PERI_REG_MASK(APB_SARADC_APB_ADC_ARB_CTRL_REG, APB_SARADC_ADC_ARB_APB_FORCE); - } -} - /*--------------------------------------------------------------- Oneshot Read ---------------------------------------------------------------*/ diff --git a/components/hal/esp32c6/include/hal/adc_hal_conf.h b/components/hal/esp32c6/include/hal/adc_hal_conf.h new file mode 100644 index 0000000000..55e742d388 --- /dev/null +++ b/components/hal/esp32c6/include/hal/adc_hal_conf.h @@ -0,0 +1,28 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +/*--------------------------------------------------------------- + Single Read +---------------------------------------------------------------*/ +#define ADC_HAL_DATA_INVERT_DEFAULT(PERIPH_NUM) (0) +#define ADC_HAL_SAR_CLK_DIV_DEFAULT(PERIPH_NUM) ((PERIPH_NUM==0)? 2 : 1) + +/*--------------------------------------------------------------- + DMA Read +---------------------------------------------------------------*/ +#define ADC_HAL_DIGI_DATA_INVERT_DEFAULT(PERIPH_NUM) (0) +#define ADC_HAL_FSM_RSTB_WAIT_DEFAULT (8) +#define ADC_HAL_FSM_START_WAIT_DEFAULT (5) +#define ADC_HAL_FSM_STANDBY_WAIT_DEFAULT (100) +#define ADC_HAL_SAMPLE_CYCLE_DEFAULT (2) +#define ADC_HAL_DIGI_SAR_CLK_DIV_DEFAULT (1) + +/*--------------------------------------------------------------- + PWDET (Power Detect) +---------------------------------------------------------------*/ +#define ADC_HAL_PWDET_CCT_DEFAULT (4) diff --git a/components/hal/esp32c6/include/hal/adc_ll.h b/components/hal/esp32c6/include/hal/adc_ll.h new file mode 100644 index 0000000000..fca4c7909f --- /dev/null +++ b/components/hal/esp32c6/include/hal/adc_ll.h @@ -0,0 +1,802 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include +#include "esp_attr.h" + +#include "soc/adc_periph.h" +#include "soc/apb_saradc_struct.h" +#include "soc/apb_saradc_reg.h" +#include "soc/pmu_reg.h" +#include "soc/clk_tree_defs.h" +#include "soc/pcr_struct.h" +#include "hal/misc.h" +#include "hal/assert.h" +#include "hal/adc_types.h" +#include "hal/adc_types_private.h" +#include "hal/regi2c_ctrl.h" + +#include "soc/regi2c_saradc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ADC_LL_CLKM_DIV_NUM_DEFAULT 15 +#define ADC_LL_CLKM_DIV_B_DEFAULT 1 +#define ADC_LL_CLKM_DIV_A_DEFAULT 0 +#define ADC_LL_DEFAULT_CONV_LIMIT_EN 0 +#define ADC_LL_DEFAULT_CONV_LIMIT_NUM 10 + +#define ADC_LL_EVENT_ADC1_ONESHOT_DONE BIT(31) +#define ADC_LL_EVENT_ADC2_ONESHOT_DONE BIT(30) +#define ADC_LL_EVENT_THRES0_HIGH BIT(29) +#define ADC_LL_event_THRES1_HIGH BIT(28) +#define ADC_LL_event_THRES0_LOW BIT(27) +#define ADC_LL_EVENT_THRES1_LOW BIT(26) + +typedef enum { + ADC_POWER_BY_FSM, /*!< ADC XPD controlled by FSM. Used for polling mode */ + ADC_POWER_SW_ON, /*!< ADC XPD controlled by SW. power on. Used for DMA mode */ + ADC_POWER_SW_OFF, /*!< ADC XPD controlled by SW. power off. */ + ADC_POWER_MAX, /*!< For parameter check. */ +} adc_ll_power_t; + +typedef enum { + ADC_RTC_DATA_OK = 0, + ADC_RTC_CTRL_UNSELECTED = 1, + ADC_RTC_CTRL_BREAK = 2, + ADC_RTC_DATA_FAIL = -1, +} adc_ll_rtc_raw_data_t; + +typedef enum { + ADC_LL_CTRL_DIG = 0, ///< Only support ADC1, i.e. only digital controller available. +} adc_ll_controller_t; + +/** + * @brief Clock source of ADC digital controller + * @note Not public as it always uses a default value for now + */ +typedef soc_periph_adc_digi_clk_src_t adc_ll_digi_clk_src_t; + +/** + * @brief Clock source of ADC digital controller + * @note Not public as it always uses a default value for now + */ +typedef soc_periph_adc_digi_clk_src_t adc_ll_digi_clk_src_t; + +/** + * @brief ADC digital controller (DMA mode) work mode. + * + * @note The conversion mode affects the sampling frequency: + * ESP32C3 only support ALTER_UNIT mode + * ALTER_UNIT : When the measurement is triggered, ADC1 or ADC2 samples alternately. + */ +typedef enum { + ADC_LL_DIGI_CONV_ALTER_UNIT = 0, // Use both ADC1 and ADC2 for conversion by turn. e.g. ADC1 -> ADC2 -> ADC1 -> ADC2 ..... +} adc_ll_digi_convert_mode_t; + +typedef struct { + union { + struct { + uint8_t atten: 2; + uint8_t channel: 3; + uint8_t unit: 1; + uint8_t reserved: 2; + }; + uint8_t val; + }; +} __attribute__((packed)) adc_ll_digi_pattern_table_t; + +/*--------------------------------------------------------------- + Digital controller setting +---------------------------------------------------------------*/ + +/** + * Set adc fsm interval parameter for digital controller. These values are fixed for same platforms. + * + * @param rst_wait cycles between DIG ADC controller reset ADC sensor and start ADC sensor. + * @param start_wait Delay time after open xpd. + * @param standby_wait Delay time to close xpd. + */ +static inline void adc_ll_digi_set_fsm_time(uint32_t rst_wait, uint32_t start_wait, uint32_t standby_wait) +{ + // Internal FSM reset wait time + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.saradc_fsm_wait, saradc_saradc_rstb_wait, rst_wait); + // Internal FSM start wait time + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.saradc_fsm_wait, saradc_saradc_xpd_wait, start_wait); + // Internal FSM standby wait time + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.saradc_fsm_wait, saradc_saradc_standby_wait, standby_wait); +} + +/** + * Set adc sample cycle for digital controller. + * + * @note Normally, please use default value. + * @param sample_cycle Cycles between DIG ADC controller start ADC sensor and beginning to receive data from sensor. + * Range: 2 ~ 0xFF. + */ +static inline void adc_ll_set_sample_cycle(uint32_t sample_cycle) +{ + // TODO: [adc_c6] Maybe this REG I2C for peripheral needs a reference lock + /* Should be called before writing I2C registers. */ + SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_PERIF_I2C); + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_SAMPLE_CYCLE_ADDR, sample_cycle); +} + +/** + * Set SAR ADC module clock division factor. + * SAR ADC clock divided from digital controller clock. + * + * @param div Division factor. + */ +static inline void adc_ll_digi_set_clk_div(uint32_t div) +{ + /* ADC clock devided from digital controller clock clk */ + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.saradc_ctrl, saradc_saradc_sar_clk_div, div); +} + +/** + * Set adc max conversion number for digital controller. + * If the number of ADC conversion is equal to the maximum, the conversion is stopped. + * + * @param meas_num Max conversion number. Range: 0 ~ 255. + */ +static inline void adc_ll_digi_set_convert_limit_num(uint32_t meas_num) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.saradc_ctrl2, saradc_saradc_max_meas_num, meas_num); +} + +/** + * Enable max conversion number detection for digital controller. + * If the number of ADC conversion is equal to the maximum, the conversion is stopped. + * + * @param enable true: enable; false: disable + */ +static inline void adc_ll_digi_convert_limit_enable(bool enable) +{ + APB_SARADC.saradc_ctrl2.saradc_saradc_meas_num_limit = enable; +} + +/** + * Set adc conversion mode for digital controller. + * + * @note ESP32C3 only support ADC1 single mode. + * + * @param mode Conversion mode select. + */ +static inline void adc_ll_digi_set_convert_mode(adc_ll_digi_convert_mode_t mode) +{ + //ESP32C3 only supports ADC_CONV_ALTER_UNIT mode +} + +/** + * Set pattern table length for digital controller. + * The pattern table that defines the conversion rules for each SAR ADC. Each table has 8 items, in which channel selection, + * and attenuation are stored. When the conversion is started, the controller reads conversion rules from the + * pattern table one by one. For each controller the scan sequence has at most 8 different rules before repeating itself. + * + * @param adc_n ADC unit. + * @param patt_len Items range: 1 ~ 8. + */ +static inline void adc_ll_digi_set_pattern_table_len(adc_unit_t adc_n, uint32_t patt_len) +{ + APB_SARADC.saradc_ctrl.saradc_saradc_sar_patt_len = patt_len - 1; +} + +/** + * Set pattern table for digital controller. + * The pattern table that defines the conversion rules for each SAR ADC. Each table has 8 items, in which channel selection, + * resolution and attenuation are stored. When the conversion is started, the controller reads conversion rules from the + * pattern table one by one. For each controller the scan sequence has at most 8 different rules before repeating itself. + * + * @param adc_n ADC unit. + * @param pattern_index Items index. Range: 0 ~ 7. + * @param pattern Stored conversion rules. + */ +static inline void adc_ll_digi_set_pattern_table(adc_unit_t adc_n, uint32_t pattern_index, adc_digi_pattern_config_t table) +{ + uint32_t tab; + uint8_t index = pattern_index / 4; + uint8_t offset = (pattern_index % 4) * 6; + adc_ll_digi_pattern_table_t pattern = {0}; + + pattern.val = (table.atten & 0x3) | ((table.channel & 0x7) << 2) | ((table.unit & 0x1) << 5); + if (index == 0) { + tab = APB_SARADC.saradc_sar_patt_tab1.saradc_saradc_sar_patt_tab1; // Read old register value + tab &= (~(0xFC0000 >> offset)); // Clear old data + tab |= ((uint32_t)(pattern.val & 0x3F) << 18) >> offset; // Fill in the new data + APB_SARADC.saradc_sar_patt_tab1.saradc_saradc_sar_patt_tab1 = tab; // Write back + } else { + tab = APB_SARADC.saradc_sar_patt_tab2.saradc_saradc_sar_patt_tab2; // Read old register value + tab &= (~(0xFC0000 >> offset)); // Clear old data + tab |= ((uint32_t)(pattern.val & 0x3F) << 18) >> offset; // Fill in the new data + APB_SARADC.saradc_sar_patt_tab2.saradc_saradc_sar_patt_tab2 = tab; // Write back + } +} + +/** + * Reset the pattern table pointer, then take the measurement rule from table header in next measurement. + * + * @param adc_n ADC unit. + */ +static inline void adc_ll_digi_clear_pattern_table(adc_unit_t adc_n) +{ + APB_SARADC.saradc_ctrl.saradc_saradc_sar_patt_p_clear = 1; + APB_SARADC.saradc_ctrl.saradc_saradc_sar_patt_p_clear = 0; +} + +/** + * Sets the number of cycles required for the conversion to complete and wait for the arbiter to stabilize. + * + * @note Only ADC2 have arbiter function. + * @param cycle range: 0 ~ 4. + */ +static inline void adc_ll_digi_set_arbiter_stable_cycle(uint32_t cycle) +{ + APB_SARADC.saradc_ctrl.saradc_saradc_wait_arb_cycle = cycle; +} + +/** + * ADC Digital controller output data invert or not. + * + * @param adc_n ADC unit. + * @param inv_en data invert or not. + */ +static inline void adc_ll_digi_output_invert(adc_unit_t adc_n, bool inv_en) +{ + if (adc_n == ADC_UNIT_1) { + APB_SARADC.saradc_ctrl2.saradc_saradc_sar1_inv = inv_en; // Enable / Disable ADC data invert + } else { // adc_n == ADC_UNIT_2 + APB_SARADC.saradc_ctrl2.saradc_saradc_sar2_inv = inv_en; // Enable / Disable ADC data invert + } +} + +/** + * Set the interval clock cycle for the digital controller to trigger the measurement. + * Expression: `trigger_meas_freq` = `controller_clk` / 2 / interval. + * + * @note The trigger interval should not be smaller than the sampling time of the SAR ADC. + * @param cycle The clock cycle (trigger interval) of the measurement. Range: 30 ~ 4095. + */ +static inline void adc_ll_digi_set_trigger_interval(uint32_t cycle) +{ + APB_SARADC.saradc_ctrl2.saradc_saradc_timer_target = cycle; +} + +/** + * Enable digital controller timer to trigger the measurement. + */ +static inline void adc_ll_digi_trigger_enable(void) +{ + APB_SARADC.saradc_ctrl2.saradc_saradc_timer_en = 1; +} + +/** + * Disable digital controller timer to trigger the measurement. + */ +static inline void adc_ll_digi_trigger_disable(void) +{ + APB_SARADC.saradc_ctrl2.saradc_saradc_timer_en = 0; +} + +/** + * Set ADC digital controller clock division factor. The clock divided from `APLL` or `APB` clock. + * Expression: controller_clk = (APLL or APB) / (div_num + div_a / div_b + 1). + * + * @param div_num Division factor. Range: 0 ~ 255. + * @param div_b Division factor. Range: 1 ~ 63. + * @param div_a Division factor. Range: 0 ~ 63. + */ +static inline void adc_ll_digi_controller_clk_div(uint32_t div_num, uint32_t div_b, uint32_t div_a) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.saradc_clkm_conf, saradc_clkm_div_num, div_num); + PCR.saradc_clkm_conf.saradc_clkm_div_b = div_b; + PCR.saradc_clkm_conf.saradc_clkm_div_a = div_a; +} + +/** + * Enable clock and select clock source for ADC digital controller. + * + * @param clk_src clock source for ADC digital controller. + */ +static inline void adc_ll_digi_clk_sel(adc_ll_digi_clk_src_t clk_src) +{ + switch (clk_src) { + case ADC_DIGI_CLK_SRC_XTAL: + PCR.saradc_clkm_conf.saradc_clkm_sel = 0; + break; + case ADC_DIGI_CLK_SRC_PLL_F80M: + PCR.saradc_clkm_conf.saradc_clkm_sel = 1; + break; + case ADC_DIGI_CLK_SRC_RC_FAST: + PCR.saradc_clkm_conf.saradc_clkm_sel = 2; + break; + default: + PCR.saradc_clkm_conf.saradc_clkm_sel = 1; + } + // Enable ADC_CTRL_CLK (i.e. digital domain clock) + PCR.saradc_clkm_conf.saradc_clkm_en = 1; +} + +/** + * Disable clock for ADC digital controller. + */ +static inline void adc_ll_digi_controller_clk_disable(void) +{ + PCR.saradc_clkm_conf.saradc_clkm_en = 0; +} + +/** + * Reset adc digital controller filter. + * + * @param adc_n ADC unit. + */ +static inline void adc_ll_digi_filter_reset(adc_unit_t adc_n) +{ + APB_SARADC.saradc_filter_ctrl0.saradc_apb_saradc_filter_reset = 1; +} + +/** + * Set adc digital controller filter factor. + * + * @note If the channel info is not supported, the filter function will not be enabled. + * @param idx ADC filter unit. + * @param filter Filter config. Expression: filter_data = (k-1)/k * last_data + new_data / k. Set values: (2, 4, 8, 16, 64). + */ +static inline void adc_ll_digi_filter_set_factor(adc_digi_filter_idx_t idx, adc_digi_filter_t *filter) +{ + if (idx == ADC_DIGI_FILTER_IDX0) { + APB_SARADC.saradc_filter_ctrl0.saradc_apb_saradc_filter_channel0 = (filter->adc_unit << 3) | (filter->channel & 0x7); + APB_SARADC.saradc_filter_ctrl1.saradc_apb_saradc_filter_factor0 = filter->mode; + } else if (idx == ADC_DIGI_FILTER_IDX1) { + APB_SARADC.saradc_filter_ctrl0.saradc_apb_saradc_filter_channel1 = (filter->adc_unit << 3) | (filter->channel & 0x7); + APB_SARADC.saradc_filter_ctrl1.saradc_apb_saradc_filter_factor1 = filter->mode; + } +} + +/** + * Get adc digital controller filter factor. + * + * @param adc_n ADC unit. + * @param factor Expression: filter_data = (k-1)/k * last_data + new_data / k. Set values: (2, 4, 8, 16, 64). + */ +static inline void adc_ll_digi_filter_get_factor(adc_digi_filter_idx_t idx, adc_digi_filter_t *filter) +{ + if (idx == ADC_DIGI_FILTER_IDX0) { + filter->adc_unit = (APB_SARADC.saradc_filter_ctrl0.saradc_apb_saradc_filter_channel0 >> 3) & 0x1; + filter->channel = APB_SARADC.saradc_filter_ctrl0.saradc_apb_saradc_filter_channel0 & 0x7; + filter->mode = APB_SARADC.saradc_filter_ctrl1.saradc_apb_saradc_filter_factor0; + } else if (idx == ADC_DIGI_FILTER_IDX1) { + filter->adc_unit = (APB_SARADC.saradc_filter_ctrl0.saradc_apb_saradc_filter_channel1 >> 3) & 0x1; + filter->channel = APB_SARADC.saradc_filter_ctrl0.saradc_apb_saradc_filter_channel1 & 0x7; + filter->mode = APB_SARADC.saradc_filter_ctrl1.saradc_apb_saradc_filter_factor1; + } +} + +/** + * Disable adc digital controller filter. + * Filtering the ADC data to obtain smooth data at higher sampling rates. + * + * @note If the channel info is not supported, the filter function will not be enabled. + * @param adc_n ADC unit. + */ +static inline void adc_ll_digi_filter_disable(adc_digi_filter_idx_t idx) +{ + if (idx == ADC_DIGI_FILTER_IDX0) { + APB_SARADC.saradc_filter_ctrl0.saradc_apb_saradc_filter_channel0 = 0xF; + APB_SARADC.saradc_filter_ctrl1.saradc_apb_saradc_filter_factor0 = 0; + } else if (idx == ADC_DIGI_FILTER_IDX1) { + APB_SARADC.saradc_filter_ctrl0.saradc_apb_saradc_filter_channel1 = 0xF; + APB_SARADC.saradc_filter_ctrl1.saradc_apb_saradc_filter_factor1 = 0; + } +} + +/** + * Set monitor mode of adc digital controller. + * + * @note If the channel info is not supported, the monitor function will not be enabled. + * @param adc_n ADC unit. + * @param is_larger true: If ADC_OUT > threshold, Generates monitor interrupt. + * false: If ADC_OUT < threshold, Generates monitor interrupt. + */ +static inline void adc_ll_digi_monitor_set_mode(adc_digi_monitor_idx_t idx, adc_digi_monitor_t *cfg) +{ + if (idx == ADC_DIGI_MONITOR_IDX0) { + APB_SARADC.saradc_thres0_ctrl.saradc_apb_saradc_thres0_channel = (cfg->adc_unit << 3) | (cfg->channel & 0x7); + APB_SARADC.saradc_thres0_ctrl.saradc_apb_saradc_thres0_high = cfg->h_threshold; + APB_SARADC.saradc_thres0_ctrl.saradc_apb_saradc_thres0_low = cfg->l_threshold; + } else { // ADC_DIGI_MONITOR_IDX1 + APB_SARADC.saradc_thres1_ctrl.saradc_apb_saradc_thres1_channel = (cfg->adc_unit << 3) | (cfg->channel & 0x7); + APB_SARADC.saradc_thres1_ctrl.saradc_apb_saradc_thres1_low = cfg->h_threshold; + APB_SARADC.saradc_thres1_ctrl.saradc_apb_saradc_thres1_low = cfg->l_threshold; + } +} + +/** + * Enable/disable monitor of adc digital controller. + * + * @note If the channel info is not supported, the monitor function will not be enabled. + * @param adc_n ADC unit. + */ +static inline void adc_ll_digi_monitor_disable(adc_digi_monitor_idx_t idx) +{ + if (idx == ADC_DIGI_MONITOR_IDX0) { + APB_SARADC.saradc_thres0_ctrl.saradc_apb_saradc_thres0_channel = 0xF; + } else { // ADC_DIGI_MONITOR_IDX1 + APB_SARADC.saradc_thres1_ctrl.saradc_apb_saradc_thres1_channel = 0xF; + } +} + +/** + * Set DMA eof num of adc digital controller. + * If the number of measurements reaches `dma_eof_num`, then `dma_in_suc_eof` signal is generated. + * + * @param num eof num of DMA. + */ +static inline void adc_ll_digi_dma_set_eof_num(uint32_t num) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.saradc_dma_conf, saradc_apb_adc_eof_num, num); +} + +/** + * Enable output data to DMA from adc digital controller. + */ +static inline void adc_ll_digi_dma_enable(void) +{ + APB_SARADC.saradc_dma_conf.saradc_apb_adc_trans = 1; +} + +/** + * Disable output data to DMA from adc digital controller. + */ +static inline void adc_ll_digi_dma_disable(void) +{ + APB_SARADC.saradc_dma_conf.saradc_apb_adc_trans = 0; +} + +/** + * Reset adc digital controller. + */ +static inline void adc_ll_digi_reset(void) +{ + APB_SARADC.saradc_dma_conf.saradc_apb_adc_reset_fsm = 1; + APB_SARADC.saradc_dma_conf.saradc_apb_adc_reset_fsm = 0; +} + +/*--------------------------------------------------------------- + PWDET(Power detect) controller setting +---------------------------------------------------------------*/ +/** + * Set adc cct for PWDET controller. + * + * @note Capacitor tuning of the PA power monitor. cct set to the same value with PHY. + * @param cct Range: 0 ~ 7. + */ +static inline void adc_ll_pwdet_set_cct(uint32_t cct) +{ + /* Capacitor tuning of the PA power monitor. cct set to the same value with PHY. */ + // RTCCNTL.sensor_ctrl.sar2_pwdet_cct = cct; + // TODO: [adc_c6] check cct validation on C6 +} + +/** + * Get adc cct for PWDET controller. + * + * @note Capacitor tuning of the PA power monitor. cct set to the same value with PHY. + * @return cct Range: 0 ~ 7. + */ +static inline uint32_t adc_ll_pwdet_get_cct(void) +{ + /* Capacitor tuning of the PA power monitor. cct set to the same value with PHY. */ + // return RTCCNTL.sensor_ctrl.sar2_pwdet_cct; + // TODO: [adc_c6] check cct validation on C6 + return 0; +} + +/*--------------------------------------------------------------- + Common setting +---------------------------------------------------------------*/ +/** + * Set ADC module power management. + * + * @param manage Set ADC power status. + */ +static inline void adc_ll_set_power_manage(adc_ll_power_t manage) +{ + /* Bit1 0:Fsm 1: SW mode + Bit0 0:SW mode power down 1: SW mode power on */ + if (manage == ADC_POWER_SW_ON) { + PCR.saradc_clkm_conf.saradc_clkm_en = 1; + APB_SARADC.saradc_ctrl.saradc_saradc_xpd_sar_force = 3; + } else if (manage == ADC_POWER_BY_FSM) { + PCR.saradc_clkm_conf.saradc_clkm_en = 1; + APB_SARADC.saradc_ctrl.saradc_saradc_xpd_sar_force = 0; + } else if (manage == ADC_POWER_SW_OFF) { + PCR.saradc_clkm_conf.saradc_clkm_en = 0; + APB_SARADC.saradc_ctrl.saradc_saradc_xpd_sar_force = 2; + } +} + +__attribute__((always_inline)) +static inline void adc_ll_set_controller(adc_unit_t adc_n, adc_ll_controller_t ctrl) +{ + //Not used on ESP32C6 +} + +/* ADC calibration code. */ +/** + * @brief Set common calibration configuration. Should be shared with other parts (PWDET). + */ +__attribute__((always_inline)) +static inline void adc_ll_calibration_init(adc_unit_t adc_n) +{ + if (adc_n == ADC_UNIT_1) { + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_DREF_ADDR, 1); + } else { + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_DREF_ADDR, 1); + } +} + +/** + * Configure the registers for ADC calibration. You need to call the ``adc_ll_calibration_finish`` interface to resume after calibration. + * + * @note Different ADC units and different attenuation options use different calibration data (initial data). + * + * @param adc_n ADC index number. + * @param internal_gnd true: Disconnect from the IO port and use the internal GND as the calibration voltage. + * false: Use IO external voltage as calibration voltage. + */ +static inline void adc_ll_calibration_prepare(adc_unit_t adc_n, bool internal_gnd) +{ + /* Enable/disable internal connect GND (for calibration). */ + if (adc_n == ADC_UNIT_1) { + if (internal_gnd) { + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_ENCAL_GND_ADDR, 1); + } else { + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_ENCAL_GND_ADDR, 0); + } + } else { + if (internal_gnd) { + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_ENCAL_GND_ADDR, 1); + } else { + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_ENCAL_GND_ADDR, 0); + } + } +} + +/** + * Resume register status after calibration. + * + * @param adc_n ADC index number. + */ +static inline void adc_ll_calibration_finish(adc_unit_t adc_n) +{ + if (adc_n == ADC_UNIT_1) { + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_ENCAL_GND_ADDR, 0); + } else { + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_ENCAL_GND_ADDR, 0); + } +} + +/** + * Set the calibration result to ADC. + * + * @note Different ADC units and different attenuation options use different calibration data (initial data). + * + * @param adc_n ADC index number. + */ +__attribute__((always_inline)) +static inline void adc_ll_set_calibration_param(adc_unit_t adc_n, uint32_t param) +{ + uint8_t msb = param >> 8; + uint8_t lsb = param & 0xFF; + if (adc_n == ADC_UNIT_1) { + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_INITIAL_CODE_HIGH_ADDR, msb); + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_INITIAL_CODE_LOW_ADDR, lsb); + } else { + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_INITIAL_CODE_HIGH_ADDR, msb); + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_INITIAL_CODE_LOW_ADDR, lsb); + } +} +/* Temp code end. */ + +/*--------------------------------------------------------------- + Oneshot Read +---------------------------------------------------------------*/ +/** + * Set adc output data format for oneshot mode + * + * @note ESP32C3 Oneshot mode only supports 12bit. + * @param adc_n ADC unit. + * @param bits Output data bits width option. + */ +static inline void adc_oneshot_ll_set_output_bits(adc_unit_t adc_n, adc_bitwidth_t bits) +{ + //ESP32C3 only supports 12bit, leave here for compatibility + HAL_ASSERT(bits == ADC_BITWIDTH_12 || bits == ADC_BITWIDTH_DEFAULT); +} + +/** + * Enable adc channel to start convert. + * + * @note Only one channel can be selected for measurement. + * + * @param adc_n ADC unit. + * @param channel ADC channel number for each ADCn. + */ +static inline void adc_oneshot_ll_set_channel(adc_unit_t adc_n, adc_channel_t channel) +{ + APB_SARADC.saradc_onetime_sample.saradc_saradc_onetime_channel = ((adc_n << 3) | channel); +} + +/** + * Disable adc channel to start convert. + * + * @note Only one channel can be selected in once measurement. + * + * @param adc_n ADC unit. + */ +static inline void adc_oneshot_ll_disable_channel(adc_unit_t adc_n) +{ + if (adc_n == ADC_UNIT_1) { + APB_SARADC.saradc_onetime_sample.saradc_saradc_onetime_channel = ((adc_n << 3) | 0xF); + } else { // adc_n == ADC_UNIT_2 + APB_SARADC.saradc_onetime_sample.saradc_saradc_onetime_channel = ((adc_n << 3) | 0x1); + } +} + +/** + * Start oneshot conversion by software + * + * @param val Usage: set to 1 to start the ADC conversion. The step signal should at least keep 3 ADC digital controller clock cycle, + * otherwise the step signal may not be captured by the ADC digital controller when its frequency is slow. + * This hardware limitation will be removed in future versions. + */ +static inline void adc_oneshot_ll_start(bool val) +{ + APB_SARADC.saradc_onetime_sample.saradc_saradc_onetime_start = val; +} + +/** + * Clear the event for each ADCn for Oneshot mode + * + * @param event ADC event + */ +static inline void adc_oneshot_ll_clear_event(uint32_t event_mask) +{ + APB_SARADC.saradc_int_clr.val |= event_mask; +} + +/** + * Check the event for each ADCn for Oneshot mode + * + * @param event ADC event + * + * @return + * -true : The conversion process is finish. + * -false : The conversion process is not finish. + */ +static inline bool adc_oneshot_ll_get_event(uint32_t event_mask) +{ + return (APB_SARADC.saradc_int_raw.val & event_mask); +} + +/** + * Get the converted value for each ADCn for RTC controller. + * + * @param adc_n ADC unit. + * @return + * - Converted value. + */ +static inline uint32_t adc_oneshot_ll_get_raw_result(adc_unit_t adc_n) +{ + uint32_t ret_val = 0; + if (adc_n == ADC_UNIT_1) { + ret_val = APB_SARADC.saradc_sar1data_status.saradc_apb_saradc1_data & 0xfff; + } else { // adc_n == ADC_UNIT_2 + ret_val = APB_SARADC.saradc_sar2data_status.saradc_apb_saradc2_data & 0xfff; + } + return ret_val; +} + +/** + * Analyze whether the obtained raw data is correct. + * ADC2 can use arbiter. The arbitration result is stored in the channel information of the returned data. + * + * @param adc_n ADC unit. + * @param raw_data ADC raw data input (convert value). + * @return + * - 1: The data is correct to use. + * - 0: The data is invalid. + */ +static inline bool adc_oneshot_ll_raw_check_valid(adc_unit_t adc_n, uint32_t raw_data) +{ + if (adc_n == ADC_UNIT_1) { + return true; + } + + //The raw data API returns value without channel information. Read value directly from the register + if (((APB_SARADC.saradc_sar2data_status.saradc_apb_saradc2_data >> 13) & 0xF) > 9) { + return false; + } + + return true; +} + +/** + * ADC module RTC output data invert or not. + * + * @param adc_n ADC unit. + * @param inv_en data invert or not. + */ +static inline void adc_oneshot_ll_output_invert(adc_unit_t adc_n, bool inv_en) +{ + (void)adc_n; + (void)inv_en; + //For compatibility +} + +/** + * Enable oneshot conversion trigger + * + * @param adc_n ADC unit + */ +static inline void adc_oneshot_ll_enable(adc_unit_t adc_n) +{ + if (adc_n == ADC_UNIT_1) { + APB_SARADC.saradc_onetime_sample.saradc_saradc1_onetime_sample = 1; + } else { + APB_SARADC.saradc_onetime_sample.saradc_saradc2_onetime_sample = 1; + } +} + +/** + * Disable oneshot conversion trigger for all the ADC units + */ +static inline void adc_oneshot_ll_disable_all_unit(void) +{ + APB_SARADC.saradc_onetime_sample.saradc_saradc1_onetime_sample = 0; + APB_SARADC.saradc_onetime_sample.saradc_saradc2_onetime_sample = 0; +} + +/** + * Set attenuation + * + * @note Attenuation is for all channels + * + * @param adc_n ADC unit + * @param channel ADC channel + * @param atten ADC attenuation + */ +static inline void adc_oneshot_ll_set_atten(adc_unit_t adc_n, adc_channel_t channel, adc_atten_t atten) +{ + (void)adc_n; + (void)channel; + // Attenuation is for all channels, unit and channel are for compatibility + APB_SARADC.saradc_onetime_sample.saradc_saradc_onetime_atten = atten; +} + +/** + * Get the attenuation of a particular channel on ADCn. + * + * @param adc_n ADC unit. + * @param channel ADCn channel number. + * @return atten The attenuation option. + */ +__attribute__((always_inline)) +static inline adc_atten_t adc_ll_get_atten(adc_unit_t adc_n, adc_channel_t channel) +{ + (void)adc_n; + (void)channel; + return (adc_atten_t)APB_SARADC.saradc_onetime_sample.saradc_saradc_onetime_atten; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32h4/include/hal/adc_ll.h b/components/hal/esp32h4/include/hal/adc_ll.h index 6db694fc37..5510fd98fc 100644 --- a/components/hal/esp32h4/include/hal/adc_ll.h +++ b/components/hal/esp32h4/include/hal/adc_ll.h @@ -16,6 +16,7 @@ #include "soc/apb_saradc_reg.h" #include "soc/rtc_cntl_struct.h" #include "soc/rtc_cntl_reg.h" +#include "soc/clk_tree_defs.h" #include "hal/misc.h" #include "hal/regi2c_ctrl.h" @@ -35,9 +36,9 @@ extern "C" { #define ADC_LL_EVENT_ADC2_ONESHOT_DONE BIT(30) typedef enum { - ADC_POWER_BY_FSM, /*!< ADC XPD controled by FSM. Used for polling mode */ - ADC_POWER_SW_ON, /*!< ADC XPD controled by SW. power on. Used for DMA mode */ - ADC_POWER_SW_OFF, /*!< ADC XPD controled by SW. power off. */ + ADC_POWER_BY_FSM, /*!< ADC XPD controlled by FSM. Used for polling mode */ + ADC_POWER_SW_ON, /*!< ADC XPD controlled by SW. power on. Used for DMA mode */ + ADC_POWER_SW_OFF, /*!< ADC XPD controlled by SW. power off. */ ADC_POWER_MAX, /*!< For parameter check. */ } adc_ll_power_t; @@ -53,6 +54,12 @@ typedef enum { ADC_LL_CTRL_ARB = 1, ///< For ADC2. The controller is selected by the arbiter. } adc_ll_controller_t; +/** + * @brief Clock source of ADC digital controller + * @note Not public as it always uses a default value for now + */ +typedef soc_periph_adc_digi_clk_src_t adc_ll_digi_clk_src_t; + /** * @brief ADC digital controller (DMA mode) work mode. * @@ -130,7 +137,7 @@ static inline void adc_ll_set_sample_cycle(uint32_t sample_cycle) */ static inline void adc_ll_digi_set_clk_div(uint32_t div) { - /* ADC clock devided from digital controller clock clk */ + /* ADC clock divided from digital controller clock clk */ HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.ctrl, sar_clk_div, div); } @@ -289,15 +296,12 @@ static inline void adc_ll_digi_controller_clk_div(uint32_t div_num, uint32_t div /** * Enable clock and select clock source for ADC digital controller. * - * @param use_apll true: use APLL clock; false: use APB clock. + * @param clk_src clock source for ADC digital controller. */ -static inline void adc_ll_digi_clk_sel(bool use_apll) +static inline void adc_ll_digi_clk_sel(adc_ll_digi_clk_src_t clk_src) { - if (use_apll) { - APB_SARADC.apb_adc_clkm_conf.clk_sel = 1; // APLL clock - } else { - APB_SARADC.apb_adc_clkm_conf.clk_sel = 2; // APB clock - } + // TODO: temporary support + APB_SARADC.apb_adc_clkm_conf.clk_sel = 0; APB_SARADC.ctrl.sar_clk_gated = 1; } @@ -674,22 +678,6 @@ static inline void adc_ll_set_calibration_param(adc_unit_t adc_n, uint32_t param } /* Temp code end. */ -/** - * Output ADCn inter reference voltage to ADC2 channels. - * - * This function routes the internal reference voltage of ADCn to one of - * ADC1's channels. This reference voltage can then be manually measured - * for calibration purposes. - * - * @param[in] adc ADC unit select - * @param[in] channel ADC1 channel number - * @param[in] en Enable/disable the reference voltage output - */ -static inline void adc_ll_vref_output(adc_unit_t adc, adc_channel_t channel, bool en) -{ - abort(); -} - /*--------------------------------------------------------------- Single Read ---------------------------------------------------------------*/ diff --git a/components/hal/esp32s2/include/hal/adc_ll.h b/components/hal/esp32s2/include/hal/adc_ll.h index 0120e427e0..edf7f040d0 100644 --- a/components/hal/esp32s2/include/hal/adc_ll.h +++ b/components/hal/esp32s2/include/hal/adc_ll.h @@ -18,6 +18,7 @@ #include "soc/rtc_cntl_struct.h" #include "soc/rtc_cntl_reg.h" #include "soc/regi2c_defs.h" +#include "soc/clk_tree_defs.h" #include "hal/regi2c_ctrl.h" #include "soc/regi2c_saradc.h" @@ -35,9 +36,9 @@ extern "C" { #define ADC_LL_EVENT_ADC2_ONESHOT_DONE (1 << 1) typedef enum { - ADC_POWER_BY_FSM, /*!< ADC XPD controled by FSM. Used for polling mode */ - ADC_POWER_SW_ON, /*!< ADC XPD controled by SW. power on. Used for DMA mode */ - ADC_POWER_SW_OFF, /*!< ADC XPD controled by SW. power off. */ + ADC_POWER_BY_FSM, /*!< ADC XPD controlled by FSM. Used for polling mode */ + ADC_POWER_SW_ON, /*!< ADC XPD controlled by SW. power on. Used for DMA mode */ + ADC_POWER_SW_OFF, /*!< ADC XPD controlled by SW. power off. */ ADC_POWER_MAX, /*!< For parameter check. */ } adc_ll_power_t; @@ -55,6 +56,12 @@ typedef enum { ADC_LL_CTRL_ARB = 3, ///< For ADC2. The controller is selected by the arbiter. } adc_ll_controller_t; +/** + * @brief Clock source of ADC digital controller + * @note Not public as it always uses a default value for now + */ +typedef soc_periph_adc_digi_clk_src_t adc_ll_digi_clk_src_t; + /** * @brief ADC digital controller (DMA mode) work mode. * @@ -145,7 +152,7 @@ static inline void adc_ll_set_sample_cycle(uint32_t sample_cycle) */ static inline void adc_ll_digi_set_clk_div(uint32_t div) { - /* ADC clock devided from digital controller clock clk */ + /* ADC clock divided from digital controller clock clk */ HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.ctrl, sar_clk_div, div); } @@ -335,15 +342,11 @@ static inline void adc_ll_digi_controller_clk_div(uint32_t div_num, uint32_t div /** * Enable clock and select clock source for ADC digital controller. * - * @param use_apll true: use APLL clock; false: use APB clock. + * @param clk_src clock source for ADC digital controller. */ -static inline void adc_ll_digi_clk_sel(bool use_apll) +static inline void adc_ll_digi_clk_sel(adc_ll_digi_clk_src_t clk_src) { - if (use_apll) { - APB_SARADC.apb_adc_clkm_conf.clk_sel = 1; // APLL clock - } else { - APB_SARADC.apb_adc_clkm_conf.clk_sel = 2; // APB clock - } + APB_SARADC.apb_adc_clkm_conf.clk_sel = (clk_src == ADC_DIGI_CLK_SRC_APLL) ? 1 : 2; APB_SARADC.ctrl.sar_clk_gated = 1; } @@ -568,7 +571,7 @@ static inline uint32_t adc_ll_pwdet_get_cct(void) RTC controller setting ---------------------------------------------------------------*/ /** - * ADC SAR clock division factor setting. ADC SAR clock devided from `RTC_FAST_CLK`. + * ADC SAR clock division factor setting. ADC SAR clock divided from `RTC_FAST_CLK`. * * @param div Division factor. */ @@ -798,7 +801,7 @@ static inline void adc_ll_rtc_set_arbiter_stable_cycle(uint32_t cycle) * * When VDD_A is 3.3V: * - * - 0dB attenuaton (ADC_ATTEN_DB_0) gives full-scale voltage 1.1V + * - 0dB attenuation (ADC_ATTEN_DB_0) gives full-scale voltage 1.1V * - 2.5dB attenuation (ADC_ATTEN_DB_2_5) gives full-scale voltage 1.5V * - 6dB attenuation (ADC_ATTEN_DB_6) gives full-scale voltage 2.2V * - 11dB attenuation (ADC_ATTEN_DB_11) gives full-scale voltage 3.9V (see note below) @@ -810,7 +813,7 @@ static inline void adc_ll_rtc_set_arbiter_stable_cycle(uint32_t cycle) * * Due to ADC characteristics, most accurate results are obtained within the following approximate voltage ranges: * - * - 0dB attenuaton (ADC_ATTEN_DB_0) between 100 and 950mV + * - 0dB attenuation (ADC_ATTEN_DB_0) between 100 and 950mV * - 2.5dB attenuation (ADC_ATTEN_DB_2_5) between 100 and 1250mV * - 6dB attenuation (ADC_ATTEN_DB_6) between 150 to 1750mV * - 11dB attenuation (ADC_ATTEN_DB_11) between 150 to 2450mV diff --git a/components/hal/esp32s3/include/hal/adc_ll.h b/components/hal/esp32s3/include/hal/adc_ll.h index 7dbd63f665..3793660e59 100644 --- a/components/hal/esp32s3/include/hal/adc_ll.h +++ b/components/hal/esp32s3/include/hal/adc_ll.h @@ -19,6 +19,7 @@ #include "soc/rtc_cntl_struct.h" #include "soc/rtc_cntl_reg.h" #include "soc/regi2c_defs.h" +#include "soc/clk_tree_defs.h" #include "hal/regi2c_ctrl.h" #include "soc/regi2c_saradc.h" @@ -36,9 +37,9 @@ extern "C" { #define ADC_LL_EVENT_ADC2_ONESHOT_DONE (1 << 1) typedef enum { - ADC_POWER_BY_FSM, /*!< ADC XPD controled by FSM. Used for polling mode */ - ADC_POWER_SW_ON, /*!< ADC XPD controled by SW. power on. Used for DMA mode */ - ADC_POWER_SW_OFF, /*!< ADC XPD controled by SW. power off. */ + ADC_POWER_BY_FSM, /*!< ADC XPD controlled by FSM. Used for polling mode */ + ADC_POWER_SW_ON, /*!< ADC XPD controlled by SW. power on. Used for DMA mode */ + ADC_POWER_SW_OFF, /*!< ADC XPD controlled by SW. power off. */ ADC_POWER_MAX, /*!< For parameter check. */ } adc_ll_power_t; @@ -56,6 +57,12 @@ typedef enum { ADC_LL_CTRL_ARB = 3, ///< For ADC2. The controller is selected by the arbiter. } adc_ll_controller_t; +/** + * @brief Clock source of ADC digital controller + * @note Not public as it always uses a default value for now + */ +typedef soc_periph_adc_digi_clk_src_t adc_ll_digi_clk_src_t; + /** * @brief ADC digital controller (DMA mode) work mode. * @@ -341,15 +348,11 @@ static inline void adc_ll_digi_controller_clk_div(uint32_t div_num, uint32_t div /** * Enable clock and select clock source for ADC digital controller. * - * @param use_apll true: use APLL clock; false: use APB clock. + * @param clk_src clock source for ADC digital controller. */ -static inline void adc_ll_digi_clk_sel(bool use_apll) +static inline void adc_ll_digi_clk_sel(adc_ll_digi_clk_src_t clk_src) { - if (use_apll) { - APB_SARADC.apb_adc_clkm_conf.clk_sel = 1; // APLL clock - } else { - APB_SARADC.apb_adc_clkm_conf.clk_sel = 2; // APB clock - } + APB_SARADC.apb_adc_clkm_conf.clk_sel = (clk_src == ADC_DIGI_CLK_SRC_APB) ? 2 : 1; APB_SARADC.ctrl.sar_clk_gated = 1; } @@ -787,7 +790,7 @@ static inline void adc_ll_vref_output(adc_unit_t adc, adc_channel_t channel, boo RTC controller setting ---------------------------------------------------------------*/ /** - * ADC SAR clock division factor setting. ADC SAR clock devided from `RTC_FAST_CLK`. + * ADC SAR clock division factor setting. ADC SAR clock divided from `RTC_FAST_CLK`. * * @param div Division factor. */ @@ -1017,7 +1020,7 @@ static inline void adc_ll_rtc_set_arbiter_stable_cycle(uint32_t cycle) * * When VDD_A is 3.3V: * - * - 0dB attenuaton (ADC_ATTEN_DB_0) gives full-scale voltage 1.1V + * - 0dB attenuation (ADC_ATTEN_DB_0) gives full-scale voltage 1.1V * - 2.5dB attenuation (ADC_ATTEN_DB_2_5) gives full-scale voltage 1.5V * - 6dB attenuation (ADC_ATTEN_DB_6) gives full-scale voltage 2.2V * - 11dB attenuation (ADC_ATTEN_DB_11) gives full-scale voltage 3.9V (see note below) @@ -1029,7 +1032,7 @@ static inline void adc_ll_rtc_set_arbiter_stable_cycle(uint32_t cycle) * * Due to ADC characteristics, most accurate results are obtained within the following approximate voltage ranges: * - * - 0dB attenuaton (ADC_ATTEN_DB_0) between 100 and 950mV + * - 0dB attenuation (ADC_ATTEN_DB_0) between 100 and 950mV * - 2.5dB attenuation (ADC_ATTEN_DB_2_5) between 100 and 1250mV * - 6dB attenuation (ADC_ATTEN_DB_6) between 150 to 1750mV * - 11dB attenuation (ADC_ATTEN_DB_11) between 150 to 2450mV diff --git a/components/hal/include/hal/adc_hal.h b/components/hal/include/hal/adc_hal.h index a88b1e7669..0bb33574b7 100644 --- a/components/hal/include/hal/adc_hal.h +++ b/components/hal/include/hal/adc_hal.h @@ -116,20 +116,6 @@ typedef struct adc_hal_digi_ctrlr_cfg_t { */ #define adc_hal_pwdet_get_cct() adc_ll_pwdet_get_cct() -/** - * Enable/disable the output of ADCn's internal reference voltage to one of ADC2's channels. - * - * This function routes the internal reference voltage of ADCn to one of - * ADC2's channels. This reference voltage can then be manually measured - * for calibration purposes. - * - * @note ESP32 only supports output of ADC2's internal reference voltage. - * @param[in] adc ADC unit select - * @param[in] channel ADC2 channel number - * @param[in] en Enable/disable the reference voltage output - */ -#define adc_hal_vref_output(adc, channel, en) adc_ll_vref_output(adc, channel, en) - /*--------------------------------------------------------------- Digital controller setting ---------------------------------------------------------------*/ diff --git a/components/hal/include/hal/adc_types_private.h b/components/hal/include/hal/adc_types_private.h index be5b83af58..da007ab7dc 100644 --- a/components/hal/include/hal/adc_types_private.h +++ b/components/hal/include/hal/adc_types_private.h @@ -142,7 +142,7 @@ typedef struct { adc_channel_t channel; /*!