|
|
@@ -41,7 +41,6 @@
|
|
|
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
|
|
#include "esp32s2beta/rom/ets_sys.h"
|
|
|
#endif
|
|
|
-#include "hal/dac_hal.h"
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
// Enable built-in checks in queue.h in debug builds
|
|
|
@@ -49,67 +48,14 @@
|
|
|
#endif
|
|
|
#include "sys/queue.h"
|
|
|
|
|
|
-#define ADC_FSM_RSTB_WAIT_DEFAULT (8)
|
|
|
-#define ADC_FSM_START_WAIT_DEFAULT (5)
|
|
|
-#define ADC_FSM_STANDBY_WAIT_DEFAULT (100)
|
|
|
-#define ADC_FSM_TIME_KEEP (-1)
|
|
|
-#define ADC_MAX_MEAS_NUM_DEFAULT (255)
|
|
|
-#define ADC_MEAS_NUM_LIM_DEFAULT (1)
|
|
|
-#define SAR_ADC_CLK_DIV_DEFAULT (2)
|
|
|
-#define ADC_PATT_LEN_MAX (16)
|
|
|
#define TOUCH_PAD_FILTER_FACTOR_DEFAULT (4) // IIR filter coefficient.
|
|
|
#define TOUCH_PAD_SHIFT_DEFAULT (4) // Increase computing accuracy.
|
|
|
#define TOUCH_PAD_SHIFT_ROUND_DEFAULT (8) // ROUND = 2^(n-1); rounding off for fractional.
|
|
|
|
|
|
-static const char *RTC_MODULE_TAG = "RTC_MODULE";
|
|
|
-
|
|
|
-#define RTC_MODULE_CHECK(a, str, ret_val) if (!(a)) { \
|
|
|
- ESP_LOGE(RTC_MODULE_TAG,"%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str); \
|
|
|
- return (ret_val); \
|
|
|
-}
|
|
|
-
|
|
|
-#define RTC_RES_CHECK(res, ret_val) if ( (a) != ESP_OK) { \
|
|
|
- ESP_LOGE(RTC_MODULE_TAG,"%s:%d (%s)", __FILE__, __LINE__, __FUNCTION__); \
|
|
|
- return (ret_val); \
|
|
|
-}
|
|
|
-
|
|
|
-#define ADC_CHECK_UNIT(unit) RTC_MODULE_CHECK(adc_unit < ADC_UNIT_2, "ADC unit error, only support ADC1 for now", ESP_ERR_INVALID_ARG)
|
|
|
-
|
|
|
-#define ADC1_CHECK_FUNCTION_RET(fun_ret) if(fun_ret!=ESP_OK){\
|
|
|
- ESP_LOGE(RTC_MODULE_TAG,"%s:%d\n",__FUNCTION__,__LINE__);\
|
|
|
- return ESP_FAIL;\
|
|
|
-}
|
|
|
-
|
|
|
-#define ADC2_CHECK_FUNCTION_RET(fun_ret) do { if(fun_ret!=ESP_OK){\
|
|
|
- ESP_LOGE(RTC_MODULE_TAG,"%s:%d\n",__FUNCTION__,__LINE__);\
|
|
|
- return ESP_FAIL;\
|
|
|
-} }while (0)
|
|
|
-
|
|
|
portMUX_TYPE rtc_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
|
|
#if CONFIG_IDF_TARGET_ESP32
|
|
|
static SemaphoreHandle_t rtc_touch_mux = NULL;
|
|
|
#endif
|
|
|
-/*
|
|
|
-In ADC2, there're two locks used for different cases:
|
|
|
-1. lock shared with app and WIFI:
|
|
|
- when wifi using the ADC2, we assume it will never stop,
|
|
|
- so app checks the lock and returns immediately if failed.
|
|
|
-
|
|
|
-2. lock shared between tasks:
|
|
|
- when several tasks sharing the ADC2, we want to guarantee
|
|
|
- all the requests will be handled.
|
|
|
- Since conversions are short (about 31us), app returns the lock very soon,
|
|
|
- we use a spinlock to stand there waiting to do conversions one by one.
|
|
|
-
|
|
|
-adc2_spinlock should be acquired first, then adc2_wifi_lock or rtc_spinlock.
|
|
|
-*/
|
|
|
-//prevent ADC2 being used by wifi and other tasks at the same time.
|
|
|
-static _lock_t adc2_wifi_lock;
|
|
|
-//prevent ADC2 being used by tasks (regardless of WIFI)
|
|
|
-portMUX_TYPE adc2_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
|
|
-
|
|
|
-//prevent ADC1 being used by I2S dma and other tasks at the same time.
|
|
|
-static _lock_t adc1_i2s_lock;
|
|
|
|
|
|
#if CONFIG_IDF_TARGET_ESP32
|
|
|
typedef struct {
|
|
|
@@ -126,18 +72,20 @@ static uint16_t s_touch_pad_init_bit = 0x0000;
|
|
|
static filter_cb_t s_filter_cb = NULL;
|
|
|
#endif
|
|
|
|
|
|
-typedef enum {
|
|
|
- ADC_CTRL_RTC = 0,
|
|
|
- ADC_CTRL_ULP = 1,
|
|
|
- ADC_CTRL_DIG = 2,
|
|
|
- ADC2_CTRL_PWDET = 3,
|
|
|
-} adc_controller_t ;
|
|
|
+#if CONFIG_IDF_TARGET_ESP32
|
|
|
|
|
|
-static const char TAG[] = "adc";
|
|
|
+static const char *RTC_MODULE_TAG = "RTC_MODULE";
|
|
|
|
|
|
-static inline void adc1_hall_enable(bool enable);
|
|
|
+#define RTC_MODULE_CHECK(a, str, ret_val) if (!(a)) { \
|
|
|
+ ESP_LOGE(RTC_MODULE_TAG,"%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str); \
|
|
|
+ return (ret_val); \
|
|
|
+}
|
|
|
+
|
|
|
+#define RTC_RES_CHECK(res, ret_val) if ( (a) != ESP_OK) { \
|
|
|
+ ESP_LOGE(RTC_MODULE_TAG,"%s:%d (%s)", __FILE__, __LINE__, __FUNCTION__); \
|
|
|
+ return (ret_val); \
|
|
|
+}
|
|
|
|
|
|
-#if CONFIG_IDF_TARGET_ESP32
|
|
|
/*---------------------------------------------------------------
|
|
|
Touch Pad
|
|
|
---------------------------------------------------------------*/
|
|
|
@@ -788,955 +736,6 @@ esp_err_t touch_pad_get_wakeup_status(touch_pad_t *pad_num)
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
-/*---------------------------------------------------------------
|
|
|
- ADC Common
|
|
|
----------------------------------------------------------------*/
|
|
|
-#if CONFIG_IDF_TARGET_ESP32S2BETA
|
|
|
-#define SENS_FORCE_XPD_AMP_FSM 0 // Use FSM to control power down
|
|
|
-#define SENS_FORCE_XPD_AMP_PD 2 // Force power down
|
|
|
-#define SENS_FORCE_XPD_AMP_PU 3 // Force power up
|
|
|
-
|
|
|
-#define SENS_SAR1_ATTEN_VAL_MASK 0x3
|
|
|
-#define SENS_SAR2_ATTEN_VAL_MASK 0x3
|
|
|
-
|
|
|
-#define SENS_FORCE_XPD_SAR_SW_M (BIT(1))
|
|
|
-#define SENS_FORCE_XPD_SAR_FSM 0 // Use FSM to control power down
|
|
|
-#define SENS_FORCE_XPD_SAR_PD 2 // Force power down
|
|
|
-#define SENS_FORCE_XPD_SAR_PU 3 // Force power up
|
|
|
-#endif
|
|
|
-
|
|
|
-static esp_err_t adc_set_fsm_time(int rst_wait, int start_wait, int standby_wait, int sample_cycle)
|
|
|
-{
|
|
|
- portENTER_CRITICAL(&rtc_spinlock);
|
|
|
-#if CONFIG_IDF_TARGET_ESP32
|
|
|
- // Internal FSM reset wait time
|
|
|
- if (rst_wait >= 0) {
|
|
|
- SYSCON.saradc_fsm.rstb_wait = rst_wait;
|
|
|
- }
|
|
|
- // Internal FSM start wait time
|
|
|
- if (start_wait >= 0) {
|
|
|
- SYSCON.saradc_fsm.start_wait = start_wait;
|
|
|
- }
|
|
|
- // Internal FSM standby wait time
|
|
|
- if (standby_wait >= 0) {
|
|
|
- SYSCON.saradc_fsm.standby_wait = standby_wait;
|
|
|
- }
|
|
|
-#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
|
|
- // Internal FSM reset wait time
|
|
|
- if (rst_wait >= 0) {
|
|
|
- SYSCON.saradc_fsm_wait.rstb_wait = rst_wait;
|
|
|
- }
|
|
|
- // Internal FSM start wait time
|
|
|
- if (start_wait >= 0) {
|
|
|
- SYSCON.saradc_fsm_wait.xpd_wait = start_wait;
|
|
|
- }
|
|
|
- // Internal FSM standby wait time
|
|
|
- if (standby_wait >= 0) {
|
|
|
- SYSCON.saradc_fsm_wait.standby_wait = standby_wait;
|
|
|
- }
|
|
|
-#endif
|
|
|
- // Internal FSM standby sample cycle
|
|
|
- if (sample_cycle >= 0) {
|
|
|
- SYSCON.saradc_fsm.sample_cycle = sample_cycle;
|
|
|
- }
|
|
|
- portEXIT_CRITICAL(&rtc_spinlock);
|
|
|
- return ESP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-static esp_err_t adc_set_data_format(adc_i2s_encode_t mode)
|
|
|
-{
|
|
|
- portENTER_CRITICAL(&rtc_spinlock);
|
|
|
- //data format:
|
|
|
- //0: ADC_ENCODE_12BIT [15:12]-channel [11:0]-12 bits ADC data
|
|
|
- //1: ADC_ENCODE_11BIT [15]-1 [14:11]-channel [10:0]-11 bits ADC data, the resolution should not be larger than 11 bits in this case.
|
|
|
- SYSCON.saradc_ctrl.data_sar_sel = mode;
|
|
|
- portEXIT_CRITICAL(&rtc_spinlock);
|
|
|
- return ESP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-static esp_err_t adc_set_measure_limit(uint8_t meas_num, bool lim_en)
|
|
|
-{
|
|
|
- portENTER_CRITICAL(&rtc_spinlock);
|
|
|
- // Set max measure number
|
|
|
- SYSCON.saradc_ctrl2.max_meas_num = meas_num;
|
|
|
- // Enable max measure number limit
|
|
|
- SYSCON.saradc_ctrl2.meas_num_limit = lim_en;
|
|
|
- portEXIT_CRITICAL(&rtc_spinlock);
|
|
|
- return ESP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-static esp_err_t adc_set_work_mode(adc_unit_t adc_unit)
|
|
|
-{
|
|
|
- portENTER_CRITICAL(&rtc_spinlock);
|
|
|
- if (adc_unit == ADC_UNIT_1) {
|
|
|
- // saradc mode sel : 0--single saradc; 1--double saradc; 2--alternative saradc
|
|
|
- SYSCON.saradc_ctrl.work_mode = 0;
|
|
|
- //ENABLE ADC 0: ADC1 1: ADC2, only work for single SAR mode
|
|
|
- SYSCON.saradc_ctrl.sar_sel = 0;
|
|
|
- } else if (adc_unit == ADC_UNIT_2) {
|
|
|
- // saradc mode sel : 0--single saradc; 1--double saradc; 2--alternative saradc
|
|
|
- SYSCON.saradc_ctrl.work_mode = 0;
|
|
|
- //ENABLE ADC1 0: SAR1 1: SAR2 only work for single SAR mode
|
|
|
- SYSCON.saradc_ctrl.sar_sel = 1;
|
|
|
- } else if (adc_unit == ADC_UNIT_BOTH) {
|
|
|
- // saradc mode sel : 0--single saradc; 1--double saradc; 2--alternative saradc
|
|
|
- SYSCON.saradc_ctrl.work_mode = 1;
|
|
|
- } else if (adc_unit == ADC_UNIT_ALTER) {
|
|
|
- // saradc mode sel : 0--single saradc; 1--double saradc; 2--alternative saradc
|
|
|
- SYSCON.saradc_ctrl.work_mode = 2;
|
|
|
- }
|
|
|
- portEXIT_CRITICAL(&rtc_spinlock);
|
|
|
- return ESP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-static esp_err_t adc_set_atten(adc_unit_t adc_unit, adc_channel_t channel, adc_atten_t atten)
|
|
|
-{
|
|
|
- ADC_CHECK_UNIT(adc_unit);
|
|
|
- if (adc_unit & ADC_UNIT_1) {
|
|
|
- RTC_MODULE_CHECK((adc1_channel_t)channel < ADC1_CHANNEL_MAX, "ADC Channel Err", ESP_ERR_INVALID_ARG);
|
|
|
- }
|
|
|
- RTC_MODULE_CHECK(atten < ADC_ATTEN_MAX, "ADC Atten Err", ESP_ERR_INVALID_ARG);
|
|
|
-
|
|
|
- portENTER_CRITICAL(&rtc_spinlock);
|
|
|
- if (adc_unit & ADC_UNIT_1) {
|
|
|
- //SAR1_atten
|
|
|
- SET_PERI_REG_BITS(SENS_SAR_ATTEN1_REG, SENS_SAR1_ATTEN_VAL_MASK, atten, (channel * 2));
|
|
|
- }
|
|
|
- if (adc_unit & ADC_UNIT_2) {
|
|
|
- //SAR2_atten
|
|
|
- SET_PERI_REG_BITS(SENS_SAR_ATTEN2_REG, SENS_SAR2_ATTEN_VAL_MASK, atten, (channel * 2));
|
|
|
- }
|
|
|
- portEXIT_CRITICAL(&rtc_spinlock);
|
|
|
- return ESP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-void adc_power_always_on(void)
|
|
|
-{
|
|
|
- portENTER_CRITICAL(&rtc_spinlock);
|
|
|
-#if CONFIG_IDF_TARGET_ESP32
|
|
|
- SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_PU;
|
|
|
-#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
|
|
- SENS.sar_power_xpd_sar.force_xpd_sar = SENS_FORCE_XPD_SAR_PU;
|
|
|
-#endif
|
|
|
- portEXIT_CRITICAL(&rtc_spinlock);
|
|
|
-}
|
|
|
-
|
|
|
-void adc_power_on(void)
|
|
|
-{
|
|
|
- portENTER_CRITICAL(&rtc_spinlock);
|
|
|
-#if CONFIG_IDF_TARGET_ESP32
|
|
|
- //The power FSM controlled mode saves more power, while the ADC noise may get increased.
|
|
|
-#ifndef CONFIG_ADC_FORCE_XPD_FSM
|
|
|
- //Set the power always on to increase precision.
|
|
|
- SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_PU;
|
|
|
-#else
|
|
|
- //Use the FSM to turn off the power while not used to save power.
|
|
|
- if (SENS.sar_meas_wait2.force_xpd_sar & SENS_FORCE_XPD_SAR_SW_M) {
|
|
|
- SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_PU;
|
|
|
- } else {
|
|
|
- SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_FSM;
|
|
|
- }
|
|
|
-#endif
|
|
|
-#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
|
|
- //The power FSM controlled mode saves more power, while the ADC noise may get increased.
|
|
|
-#ifndef CONFIG_ADC_FORCE_XPD_FSM
|
|
|
- //Set the power always on to increase precision.
|
|
|
- SENS.sar_power_xpd_sar.force_xpd_sar = SENS_FORCE_XPD_SAR_PU;
|
|
|
-#else
|
|
|
- //Use the FSM to turn off the power while not used to save power.
|
|
|
- if (SENS.sar_power_xpd_sar.force_xpd_sar & SENS_FORCE_XPD_SAR_SW_M) {
|
|
|
- SENS.sar_power_xpd_sar.force_xpd_sar = SENS_FORCE_XPD_SAR_PU;
|
|
|
- } else {
|
|
|
- SENS.sar_power_xpd_sar.force_xpd_sar = SENS_FORCE_XPD_SAR_FSM;
|
|
|
- }
|
|
|
-#endif
|
|
|
-#endif
|
|
|
- portEXIT_CRITICAL(&rtc_spinlock);
|
|
|
-}
|
|
|
-
|
|
|
-void adc_power_off(void)
|
|
|
-{
|
|
|
- portENTER_CRITICAL(&rtc_spinlock);
|
|
|
-#if CONFIG_IDF_TARGET_ESP32
|
|
|
- //Bit1 0:Fsm 1: SW mode
|
|
|
- //Bit0 0:SW mode power down 1: SW mode power on
|
|
|
- SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_PD;
|
|
|
-#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
|
|
- SENS.sar_power_xpd_sar.force_xpd_sar = SENS_FORCE_XPD_SAR_PD;
|
|
|
-#endif
|
|
|
-
|
|
|
- portEXIT_CRITICAL(&rtc_spinlock);
|
|
|
-}
|
|
|
-
|
|
|
-esp_err_t adc_set_clk_div(uint8_t clk_div)
|
|
|
-{
|
|
|
- portENTER_CRITICAL(&rtc_spinlock);
|
|
|
- // ADC clock divided from APB clk, 80 / 2 = 40Mhz,
|
|
|
- SYSCON.saradc_ctrl.sar_clk_div = clk_div;
|
|
|
- portEXIT_CRITICAL(&rtc_spinlock);
|
|
|
- return ESP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-esp_err_t adc_set_i2s_data_source(adc_i2s_source_t src)
|
|
|
-{
|
|
|
- RTC_MODULE_CHECK(src < ADC_I2S_DATA_SRC_MAX, "ADC i2s data source error", ESP_ERR_INVALID_ARG);
|
|
|
- portENTER_CRITICAL(&rtc_spinlock);
|
|
|
- // 1: I2S input data is from SAR ADC (for DMA) 0: I2S input data is from GPIO matrix
|
|
|
- SYSCON.saradc_ctrl.data_to_i2s = src;
|
|
|
- portEXIT_CRITICAL(&rtc_spinlock);
|
|
|
- return ESP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-esp_err_t adc_gpio_init(adc_unit_t adc_unit, adc_channel_t channel)
|
|
|
-{
|
|
|
- ADC_CHECK_UNIT(adc_unit);
|
|
|
- gpio_num_t gpio_num = 0;
|
|
|
- if (adc_unit & ADC_UNIT_1) {
|
|
|
- RTC_MODULE_CHECK((adc1_channel_t) channel < ADC1_CHANNEL_MAX, "ADC1 channel error", ESP_ERR_INVALID_ARG);
|
|
|
- ADC1_CHECK_FUNCTION_RET(adc1_pad_get_io_num((adc1_channel_t) channel, &gpio_num));
|
|
|
- ADC1_CHECK_FUNCTION_RET(rtc_gpio_init(gpio_num));
|
|
|
- ADC1_CHECK_FUNCTION_RET(rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_DISABLED));
|
|
|
- ADC1_CHECK_FUNCTION_RET(gpio_set_pull_mode(gpio_num, GPIO_FLOATING));
|
|
|
- }
|
|
|
- return ESP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-esp_err_t adc_set_data_inv(adc_unit_t adc_unit, bool inv_en)
|
|
|
-{
|
|
|
- portENTER_CRITICAL(&rtc_spinlock);
|
|
|
-#if CONFIG_IDF_TARGET_ESP32
|
|
|
- if (adc_unit & ADC_UNIT_1) {
|
|
|
- // Enable ADC data invert
|
|
|
- SENS.sar_read_ctrl.sar1_data_inv = inv_en;
|
|
|
- }
|
|
|
- if (adc_unit & ADC_UNIT_2) {
|
|
|
- // Enable ADC data invert
|
|
|
- SENS.sar_read_ctrl2.sar2_data_inv = inv_en;
|
|
|
- }
|
|
|
-#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
|
|
- if (adc_unit & ADC_UNIT_1) {
|
|
|
- // Enable ADC data invert
|
|
|
- SENS.sar_reader1_ctrl.sar1_data_inv = inv_en;
|
|
|
- }
|
|
|
- if (adc_unit & ADC_UNIT_2) {
|
|
|
- // Enable ADC data invert
|
|
|
- SENS.sar_reader2_ctrl.sar2_data_inv = inv_en;
|
|
|
- }
|
|
|
-#endif
|
|
|
- portEXIT_CRITICAL(&rtc_spinlock);
|
|
|
- return ESP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-esp_err_t adc_set_data_width(adc_unit_t adc_unit, adc_bits_width_t bits)
|
|
|
-{
|
|
|
- ADC_CHECK_UNIT(adc_unit);
|
|
|
- RTC_MODULE_CHECK(bits < ADC_WIDTH_MAX, "ADC bit width error", ESP_ERR_INVALID_ARG);
|
|
|
- portENTER_CRITICAL(&rtc_spinlock);
|
|
|
-#if CONFIG_IDF_TARGET_ESP32
|
|
|
- if (adc_unit & ADC_UNIT_1) {
|
|
|
- SENS.sar_start_force.sar1_bit_width = bits;
|
|
|
- SENS.sar_read_ctrl.sar1_sample_bit = bits;
|
|
|
- }
|
|
|
- if (adc_unit & ADC_UNIT_2) {
|
|
|
- SENS.sar_start_force.sar2_bit_width = bits;
|
|
|
- SENS.sar_read_ctrl2.sar2_sample_bit = bits;
|
|
|
- }
|
|
|
-#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
|
|
- if (adc_unit & ADC_UNIT_1) {
|
|
|
- SENS.sar_meas1_ctrl1.sar1_bit_width = bits;
|
|
|
- SENS.sar_reader1_ctrl.sar1_sample_bit = bits;
|
|
|
- }
|
|
|
- if (adc_unit & ADC_UNIT_2) {
|
|
|
- SENS.sar_meas2_ctrl1.sar2_bit_width = bits;
|
|
|
- SENS.sar_reader2_ctrl.sar2_sample_bit = bits;
|
|
|
- }
|
|
|
-#endif
|
|
|
- portEXIT_CRITICAL(&rtc_spinlock);
|
|
|
- return ESP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-// this function should be called in the critical section
|
|
|
-static void adc_set_controller(adc_unit_t unit, adc_controller_t ctrl )
|
|
|
-{
|
|
|
-#if CONFIG_IDF_TARGET_ESP32
|
|
|
- if ( unit == ADC_UNIT_1 ) {
|
|
|
- switch( ctrl ) {
|
|
|
- case ADC_CTRL_RTC:
|
|
|
- SENS.sar_read_ctrl.sar1_dig_force = false; //RTC controller controls the ADC, not digital controller
|
|
|
- SENS.sar_meas_start1.meas1_start_force = true; //RTC controller controls the ADC,not ulp coprocessor
|
|
|
- SENS.sar_meas_start1.sar1_en_pad_force = true; //RTC controller controls the data port, not ulp coprocessor
|
|
|
- SENS.sar_touch_ctrl1.xpd_hall_force = true; // RTC controller controls the hall sensor power,not ulp coprocessor
|
|
|
- SENS.sar_touch_ctrl1.hall_phase_force = true; // RTC controller controls the hall sensor phase,not ulp coprocessor
|
|
|
- break;
|
|
|
- case ADC_CTRL_ULP:
|
|
|
- SENS.sar_read_ctrl.sar1_dig_force = false;
|
|
|
- SENS.sar_meas_start1.meas1_start_force = false;
|
|
|
- SENS.sar_meas_start1.sar1_en_pad_force = false;
|
|
|
- SENS.sar_touch_ctrl1.xpd_hall_force = false;
|
|
|
- SENS.sar_touch_ctrl1.hall_phase_force = false;
|
|
|
- break;
|
|
|
- case ADC_CTRL_DIG:
|
|
|
- SENS.sar_read_ctrl.sar1_dig_force = true;
|
|
|
- SENS.sar_meas_start1.meas1_start_force = true;
|
|
|
- SENS.sar_meas_start1.sar1_en_pad_force = true;
|
|
|
- SENS.sar_touch_ctrl1.xpd_hall_force = true;
|
|
|
- SENS.sar_touch_ctrl1.hall_phase_force = true;
|
|
|
- break;
|
|
|
- default:
|
|
|
- ESP_LOGE(TAG, "adc1 selects invalid controller");
|
|
|
- break;
|
|
|
- }
|
|
|
- } else if ( unit == ADC_UNIT_2) {
|
|
|
- switch( ctrl ) {
|
|
|
- case ADC_CTRL_RTC:
|
|
|
- SENS.sar_meas_start2.meas2_start_force = true; //RTC controller controls the ADC,not ulp coprocessor
|
|
|
- SENS.sar_meas_start2.sar2_en_pad_force = true; //RTC controller controls the data port, not ulp coprocessor
|
|
|
- SENS.sar_read_ctrl2.sar2_dig_force = false; //RTC controller controls the ADC, not digital controller
|
|
|
- SENS.sar_read_ctrl2.sar2_pwdet_force = false; //RTC controller controls the ADC, not PWDET
|
|
|
- SYSCON.saradc_ctrl.sar2_mux = true; //RTC controller controls the ADC, not PWDET
|
|
|
- break;
|
|
|
- case ADC_CTRL_ULP:
|
|
|
- SENS.sar_meas_start2.meas2_start_force = false;
|
|
|
- SENS.sar_meas_start2.sar2_en_pad_force = false;
|
|
|
- SENS.sar_read_ctrl2.sar2_dig_force = false;
|
|
|
- SENS.sar_read_ctrl2.sar2_pwdet_force = false;
|
|
|
- SYSCON.saradc_ctrl.sar2_mux = true;
|
|
|
- break;
|
|
|
- case ADC_CTRL_DIG:
|
|
|
- SENS.sar_meas_start2.meas2_start_force = true;
|
|
|
- SENS.sar_meas_start2.sar2_en_pad_force = true;
|
|
|
- SENS.sar_read_ctrl2.sar2_dig_force = true;
|
|
|
- SENS.sar_read_ctrl2.sar2_pwdet_force = false;
|
|
|
- SYSCON.saradc_ctrl.sar2_mux = true;
|
|
|
- break;
|
|
|
- case ADC2_CTRL_PWDET:
|
|
|
- //currently only used by Wi-Fi
|
|
|
- SENS.sar_meas_start2.meas2_start_force = true;
|
|
|
- SENS.sar_meas_start2.sar2_en_pad_force = true;
|
|
|
- SENS.sar_read_ctrl2.sar2_dig_force = false;
|
|
|
- SENS.sar_read_ctrl2.sar2_pwdet_force = true;
|
|
|
- SYSCON.saradc_ctrl.sar2_mux = false;
|
|
|
- break;
|
|
|
- default:
|
|
|
- ESP_LOGE(TAG, "adc2 selects invalid controller");
|
|
|
- break;
|
|
|
- }
|
|
|
- } else {
|
|
|
- ESP_LOGE(TAG, "invalid adc unit");
|
|
|
- assert(0);
|
|
|
- }
|
|
|
-#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
|
|
- if ( unit == ADC_UNIT_1 ) {
|
|
|
- switch( ctrl ) {
|
|
|
- case ADC_CTRL_RTC:
|
|
|
- SENS.sar_meas1_mux.sar1_dig_force = false; //RTC controller controls the ADC, not digital controller
|
|
|
- SENS.sar_meas1_ctrl2.meas1_start_force = true; //RTC controller controls the ADC,not ulp coprocessor
|
|
|
- SENS.sar_meas1_ctrl2.sar1_en_pad_force = true; //RTC controller controls the data port, not ulp coprocessor
|
|
|
- SENS.sar_hall_ctrl.xpd_hall_force = true; // RTC controller controls the hall sensor power,not ulp coprocessor
|
|
|
- SENS.sar_hall_ctrl.hall_phase_force = true; // RTC controller controls the hall sensor phase,not ulp coprocessor
|
|
|
- break;
|
|
|
- case ADC_CTRL_ULP:
|
|
|
- SENS.sar_meas1_mux.sar1_dig_force = false;
|
|
|
- SENS.sar_meas1_ctrl2.meas1_start_force = false;
|
|
|
- SENS.sar_meas1_ctrl2.sar1_en_pad_force = false;
|
|
|
- SENS.sar_hall_ctrl.xpd_hall_force = false;
|
|
|
- SENS.sar_hall_ctrl.hall_phase_force = false;
|
|
|
- break;
|
|
|
- case ADC_CTRL_DIG:
|
|
|
- SENS.sar_meas1_mux.sar1_dig_force = true;
|
|
|
- SENS.sar_meas1_ctrl2.meas1_start_force = true;
|
|
|
- SENS.sar_meas1_ctrl2.sar1_en_pad_force = true;
|
|
|
- SENS.sar_hall_ctrl.xpd_hall_force = true;
|
|
|
- SENS.sar_hall_ctrl.hall_phase_force = true;
|
|
|
- break;
|
|
|
- default:
|
|
|
- ESP_LOGE(TAG, "adc1 selects invalid controller");
|
|
|
- break;
|
|
|
- }
|
|
|
- } else if ( unit == ADC_UNIT_2) {
|
|
|
- switch( ctrl ) {
|
|
|
- case ADC_CTRL_RTC:
|
|
|
- SENS.sar_meas2_ctrl2.meas2_start_force = true; //RTC controller controls the ADC,not ulp coprocessor
|
|
|
- SENS.sar_meas2_ctrl2.sar2_en_pad_force = true; //RTC controller controls the data port, not ulp coprocessor
|
|
|
- break;
|
|
|
- case ADC_CTRL_ULP:
|
|
|
- SENS.sar_meas2_ctrl2.meas2_start_force = false;
|
|
|
- SENS.sar_meas2_ctrl2.sar2_en_pad_force = false;
|
|
|
- break;
|
|
|
- case ADC_CTRL_DIG:
|
|
|
- SENS.sar_meas2_ctrl2.meas2_start_force = true;
|
|
|
- SENS.sar_meas2_ctrl2.sar2_en_pad_force = true;
|
|
|
- break;
|
|
|
- case ADC2_CTRL_PWDET:
|
|
|
- //currently only used by Wi-Fi
|
|
|
- SENS.sar_meas2_ctrl2.meas2_start_force = true;
|
|
|
- SENS.sar_meas2_ctrl2.sar2_en_pad_force = true;
|
|
|
- break;
|
|
|
- default:
|
|
|
- ESP_LOGE(TAG, "adc2 selects invalid controller");
|
|
|
- break;
|
|
|
- }
|
|
|
- } else {
|
|
|
- ESP_LOGE(TAG, "invalid adc unit");
|
|
|
- assert(0);
|
|
|
- }
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
-// this function should be called in the critical section
|
|
|
-static int adc_convert( adc_unit_t unit, int channel)
|
|
|
-{
|
|
|
- uint16_t adc_value = 0;
|
|
|
-#if CONFIG_IDF_TARGET_ESP32
|
|
|
- if ( unit == ADC_UNIT_1 ) {
|
|
|
- SENS.sar_meas_start1.sar1_en_pad = (1 << channel); //only one channel is selected.
|
|
|
- while (SENS.sar_slave_addr1.meas_status != 0);
|
|
|
- SENS.sar_meas_start1.meas1_start_sar = 0;
|
|
|
- SENS.sar_meas_start1.meas1_start_sar = 1;
|
|
|
- while (SENS.sar_meas_start1.meas1_done_sar == 0);
|
|
|
- adc_value = SENS.sar_meas_start1.meas1_data_sar;
|
|
|
- } else if ( unit == ADC_UNIT_2 ) {
|
|
|
- SENS.sar_meas_start2.sar2_en_pad = (1 << channel); //only one channel is selected.
|
|
|
-
|
|
|
- SENS.sar_meas_start2.meas2_start_sar = 0; //start force 0
|
|
|
- SENS.sar_meas_start2.meas2_start_sar = 1; //start force 1
|
|
|
- while (SENS.sar_meas_start2.meas2_done_sar == 0) {}; //read done
|
|
|
- adc_value = SENS.sar_meas_start2.meas2_data_sar;
|
|
|
- } else {
|
|
|
- ESP_LOGE(TAG, "invalid adc unit");
|
|
|
- return ESP_ERR_INVALID_ARG;
|
|
|
- }
|
|
|
-#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
|
|
- if ( unit == ADC_UNIT_1 ) {
|
|
|
- SENS.sar_meas1_ctrl2.sar1_en_pad = (1 << channel); //only one channel is selected.
|
|
|
- while (SENS.sar_slave_addr1.meas_status != 0);
|
|
|
- SENS.sar_meas1_ctrl2.meas1_start_sar = 0;
|
|
|
- SENS.sar_meas1_ctrl2.meas1_start_sar = 1;
|
|
|
- while (SENS.sar_meas1_ctrl2.meas1_done_sar == 0);
|
|
|
- adc_value = SENS.sar_meas1_ctrl2.meas1_data_sar;
|
|
|
- } else if ( unit == ADC_UNIT_2 ) {
|
|
|
- SENS.sar_meas2_ctrl2.sar2_en_pad = (1 << channel); //only one channel is selected.
|
|
|
-
|
|
|
- SENS.sar_meas2_ctrl2.meas2_start_sar = 0; //start force 0
|
|
|
- SENS.sar_meas2_ctrl2.meas2_start_sar = 1; //start force 1
|
|
|
- while (SENS.sar_meas2_ctrl2.meas2_done_sar == 0) {}; //read done
|
|
|
- adc_value = SENS.sar_meas2_ctrl2.meas2_data_sar;
|
|
|
- } else {
|
|
|
- ESP_LOGE(TAG, "invalid adc unit");
|
|
|
- return ESP_ERR_INVALID_ARG;
|
|
|
- }
|
|
|
-#endif
|
|
|
- return adc_value;
|
|
|
-}
|
|
|
-
|
|
|
-/*-------------------------------------------------------------------------------------
|
|
|
- * ADC I2S
|
|
|
- *------------------------------------------------------------------------------------*/
|
|
|
-static esp_err_t adc_set_i2s_data_len(adc_unit_t adc_unit, int patt_len)
|
|
|
-{
|
|
|
- ADC_CHECK_UNIT(adc_unit);
|
|
|
- RTC_MODULE_CHECK((patt_len < ADC_PATT_LEN_MAX) && (patt_len > 0), "ADC pattern length error", ESP_ERR_INVALID_ARG);
|
|
|
- portENTER_CRITICAL(&rtc_spinlock);
|
|
|
- if(adc_unit & ADC_UNIT_1) {
|
|
|
- SYSCON.saradc_ctrl.sar1_patt_len = patt_len - 1;
|
|
|
- }
|
|
|
- if(adc_unit & ADC_UNIT_2) {
|
|
|
- SYSCON.saradc_ctrl.sar2_patt_len = patt_len - 1;
|
|
|
- }
|
|
|
- portEXIT_CRITICAL(&rtc_spinlock);
|
|
|
- return ESP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-static esp_err_t adc_set_i2s_data_pattern(adc_unit_t adc_unit, int seq_num, adc_channel_t channel, adc_bits_width_t bits, adc_atten_t atten)
|
|
|
-{
|
|
|
- ADC_CHECK_UNIT(adc_unit);
|
|
|
- if (adc_unit & ADC_UNIT_1) {
|
|
|
- RTC_MODULE_CHECK((adc1_channel_t) channel < ADC1_CHANNEL_MAX, "ADC1 channel error", ESP_ERR_INVALID_ARG);
|
|
|
- }
|
|
|
- RTC_MODULE_CHECK(bits < ADC_WIDTH_MAX, "ADC bit width error", ESP_ERR_INVALID_ARG);
|
|
|
- RTC_MODULE_CHECK(atten < ADC_ATTEN_MAX, "ADC Atten Err", ESP_ERR_INVALID_ARG);
|
|
|
-
|
|
|
- portENTER_CRITICAL(&rtc_spinlock);
|
|
|
- //Configure pattern table, each 8 bit defines one channel
|
|
|
- //[7:4]-channel [3:2]-bit width [1:0]- attenuation
|
|
|
- //BIT WIDTH: 3: 12BIT 2: 11BIT 1: 10BIT 0: 9BIT
|
|
|
- //ATTEN: 3: ATTEN = 11dB 2: 6dB 1: 2.5dB 0: 0dB
|
|
|
- uint8_t val = (channel << 4) | (bits << 2) | (atten << 0);
|
|
|
- if (adc_unit & ADC_UNIT_1) {
|
|
|
- SYSCON.saradc_sar1_patt_tab[seq_num / 4] &= (~(0xff << ((3 - (seq_num % 4)) * 8)));
|
|
|
- SYSCON.saradc_sar1_patt_tab[seq_num / 4] |= (val << ((3 - (seq_num % 4)) * 8));
|
|
|
- }
|
|
|
- if (adc_unit & ADC_UNIT_2) {
|
|
|
- SYSCON.saradc_sar2_patt_tab[seq_num / 4] &= (~(0xff << ((3 - (seq_num % 4)) * 8)));
|
|
|
- SYSCON.saradc_sar2_patt_tab[seq_num / 4] |= (val << ((3 - (seq_num % 4)) * 8));
|
|
|
- }
|
|
|
- portEXIT_CRITICAL(&rtc_spinlock);
|
|
|
- return ESP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel)
|
|
|
-{
|
|
|
- ADC_CHECK_UNIT(adc_unit);
|
|
|
- if (adc_unit & ADC_UNIT_1) {
|
|
|
- RTC_MODULE_CHECK((adc1_channel_t) channel < ADC1_CHANNEL_MAX, "ADC1 channel error", ESP_ERR_INVALID_ARG);
|
|
|
- }
|
|
|
-
|
|
|
- uint8_t table_len = 1;
|
|
|
- //POWER ON SAR
|
|
|
- adc_power_always_on();
|
|
|
- adc_gpio_init(adc_unit, channel);
|
|
|
- adc_set_i2s_data_len(adc_unit, table_len);
|
|
|
- adc_set_i2s_data_pattern(adc_unit, 0, channel, ADC_WIDTH_BIT_12, ADC_ATTEN_DB_11);
|
|
|
- portENTER_CRITICAL(&rtc_spinlock);
|
|
|
- if (adc_unit & ADC_UNIT_1) {
|
|
|
- adc_set_controller( ADC_UNIT_1, ADC_CTRL_DIG );
|
|
|
- }
|
|
|
- if (adc_unit & ADC_UNIT_2) {
|
|
|
- adc_set_controller( ADC_UNIT_2, ADC_CTRL_DIG );
|
|
|
- }
|
|
|
- portEXIT_CRITICAL(&rtc_spinlock);
|
|
|
- adc_set_i2s_data_source(ADC_I2S_DATA_SRC_ADC);
|
|
|
- adc_set_clk_div(SAR_ADC_CLK_DIV_DEFAULT);
|
|
|
- // Set internal FSM wait time.
|
|
|
- adc_set_fsm_time(ADC_FSM_RSTB_WAIT_DEFAULT, ADC_FSM_START_WAIT_DEFAULT, ADC_FSM_STANDBY_WAIT_DEFAULT,
|
|
|
- ADC_FSM_TIME_KEEP);
|
|
|
- adc_set_work_mode(adc_unit);
|
|
|
- adc_set_data_format(ADC_ENCODE_12BIT);
|
|
|
- adc_set_measure_limit(ADC_MAX_MEAS_NUM_DEFAULT, ADC_MEAS_NUM_LIM_DEFAULT);
|
|
|
- //Invert The Level, Invert SAR ADC1 data
|
|
|
- adc_set_data_inv(adc_unit, true);
|
|
|
- return ESP_OK;
|
|
|
- }
|
|
|
-
|
|
|
-/*-------------------------------------------------------------------------------------
|
|
|
- * ADC1
|
|
|
- *------------------------------------------------------------------------------------*/
|
|
|
-esp_err_t adc1_pad_get_io_num(adc1_channel_t channel, gpio_num_t *gpio_num)
|
|
|
-{
|
|
|
- RTC_MODULE_CHECK(channel < ADC1_CHANNEL_MAX, "ADC1 Channel Err", ESP_ERR_INVALID_ARG);
|
|
|
-
|
|
|
- switch (channel) {
|
|
|
- case ADC1_CHANNEL_0:
|
|
|
- *gpio_num = ADC1_CHANNEL_0_GPIO_NUM;
|
|
|
- break;
|
|
|
- case ADC1_CHANNEL_1:
|
|
|
- *gpio_num = ADC1_CHANNEL_1_GPIO_NUM;
|
|
|
- break;
|
|
|
- case ADC1_CHANNEL_2:
|
|
|
- *gpio_num = ADC1_CHANNEL_2_GPIO_NUM;
|
|
|
- break;
|
|
|
- case ADC1_CHANNEL_3:
|
|
|
- *gpio_num = ADC1_CHANNEL_3_GPIO_NUM;
|
|
|
- break;
|
|
|
- case ADC1_CHANNEL_4:
|
|
|
- *gpio_num = ADC1_CHANNEL_4_GPIO_NUM;
|
|
|
- break;
|
|
|
- case ADC1_CHANNEL_5:
|
|
|
- *gpio_num = ADC1_CHANNEL_5_GPIO_NUM;
|
|
|
- break;
|
|
|
- case ADC1_CHANNEL_6:
|
|
|
- *gpio_num = ADC1_CHANNEL_6_GPIO_NUM;
|
|
|
- break;
|
|
|
- case ADC1_CHANNEL_7:
|
|
|
- *gpio_num = ADC1_CHANNEL_7_GPIO_NUM;
|
|
|
- break;
|
|
|
- default:
|
|
|
- return ESP_ERR_INVALID_ARG;
|
|
|
- }
|
|
|
-
|
|
|
- return ESP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten)
|
|
|
-{
|
|
|
- RTC_MODULE_CHECK(channel < ADC1_CHANNEL_MAX, "ADC Channel Err", ESP_ERR_INVALID_ARG);
|
|
|
- RTC_MODULE_CHECK(atten < ADC_ATTEN_MAX, "ADC Atten Err", ESP_ERR_INVALID_ARG);
|
|
|
- adc_gpio_init(ADC_UNIT_1, channel);
|
|
|
- adc_set_atten(ADC_UNIT_1, channel, atten);
|
|
|
- return ESP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-esp_err_t adc1_config_width(adc_bits_width_t width_bit)
|
|
|
-{
|
|
|
- RTC_MODULE_CHECK(width_bit < ADC_WIDTH_MAX, "ADC bit width error", ESP_ERR_INVALID_ARG);
|
|
|
- adc_set_data_width(ADC_UNIT_1, width_bit);
|
|
|
- adc_set_data_inv(ADC_UNIT_1, true);
|
|
|
- return ESP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-static inline void adc1_fsm_disable(void)
|
|
|
-{
|
|
|
-#if CONFIG_IDF_TARGET_ESP32
|
|
|
- //channel is set in the convert function
|
|
|
- SENS.sar_meas_wait2.force_xpd_amp = SENS_FORCE_XPD_AMP_PD;
|
|
|
- //disable FSM, it's only used by the LNA.
|
|
|
- SENS.sar_meas_ctrl.amp_rst_fb_fsm = 0;
|
|
|
- SENS.sar_meas_ctrl.amp_short_ref_fsm = 0;
|
|
|
- SENS.sar_meas_ctrl.amp_short_ref_gnd_fsm = 0;
|
|
|
- SENS.sar_meas_wait1.sar_amp_wait1 = 1;
|
|
|
- SENS.sar_meas_wait1.sar_amp_wait2 = 1;
|
|
|
- SENS.sar_meas_wait2.sar_amp_wait3 = 1;
|
|
|
-#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
|
|
- //channel is set in the convert function
|
|
|
- SENS.sar_meas1_ctrl1.force_xpd_amp = SENS_FORCE_XPD_AMP_PD;
|
|
|
- //disable FSM, it's only used by the LNA.
|
|
|
- SENS.sar_amp_ctrl3.amp_rst_fb_fsm = 0;
|
|
|
- SENS.sar_amp_ctrl3.amp_short_ref_fsm = 0;
|
|
|
- SENS.sar_amp_ctrl3.amp_short_ref_gnd_fsm = 0;
|
|
|
- SENS.sar_amp_ctrl1.sar_amp_wait1 = 1;
|
|
|
- SENS.sar_amp_ctrl1.sar_amp_wait2 = 1;
|
|
|
- SENS.sar_amp_ctrl2.sar_amp_wait3 = 1;
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
-esp_err_t adc1_i2s_mode_acquire(void)
|
|
|
-{
|
|
|
- //lazy initialization
|
|
|
- //for i2s, block until acquire the lock
|
|
|
- _lock_acquire( &adc1_i2s_lock );
|
|
|
- ESP_LOGD( RTC_MODULE_TAG, "i2s mode takes adc1 lock." );
|
|
|
- portENTER_CRITICAL(&rtc_spinlock);
|
|
|
-#if CONFIG_IDF_TARGET_ESP32
|
|
|
- SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_PU;
|
|
|
- //switch SARADC into DIG channel
|
|
|
- SENS.sar_read_ctrl.sar1_dig_force = 1;
|
|
|
-#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
|
|
- SENS.sar_power_xpd_sar.force_xpd_sar = SENS_FORCE_XPD_SAR_PU;
|
|
|
- //switch SARADC into DIG channel
|
|
|
- SENS.sar_meas1_mux.sar1_dig_force = 1;
|
|
|
-#endif
|
|
|
- portEXIT_CRITICAL(&rtc_spinlock);
|
|
|
- return ESP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-esp_err_t adc1_adc_mode_acquire(void)
|
|
|
-{
|
|
|
- //lazy initialization
|
|
|
- //for adc1, block until acquire the lock
|
|
|
- _lock_acquire( &adc1_i2s_lock );
|
|
|
- ESP_LOGD( RTC_MODULE_TAG, "adc mode takes adc1 lock." );
|
|
|
- portENTER_CRITICAL(&rtc_spinlock);
|
|
|
- // for now the WiFi would use ADC2 and set xpd_sar force on.
|
|
|
- // so we can not reset xpd_sar to fsm mode directly.
|
|
|
- // We should handle this after the synchronization mechanism is established.
|
|
|
-
|
|
|
- //switch SARADC into RTC channel
|
|
|
-#if CONFIG_IDF_TARGET_ESP32
|
|
|
- SENS.sar_read_ctrl.sar1_dig_force = 0;
|
|
|
-#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
|
|
- SENS.sar_meas1_mux.sar1_dig_force = 0;
|
|
|
-#endif
|
|
|
- portEXIT_CRITICAL(&rtc_spinlock);
|
|
|
- return ESP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-esp_err_t adc1_lock_release(void)
|
|
|
-{
|
|
|
- RTC_MODULE_CHECK((uint32_t*)adc1_i2s_lock != NULL, "adc1 lock release called before acquire", ESP_ERR_INVALID_STATE );
|
|
|
- // for now the WiFi would use ADC2 and set xpd_sar force on.
|
|
|
- // so we can not reset xpd_sar to fsm mode directly.
|
|
|
- // We should handle this after the synchronization mechanism is established.
|
|
|
-
|
|
|
- _lock_release( &adc1_i2s_lock );
|
|
|
- return ESP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-int adc1_get_raw(adc1_channel_t channel)
|
|
|
-{
|
|
|
- uint16_t adc_value;
|
|
|
- RTC_MODULE_CHECK(channel < ADC1_CHANNEL_MAX, "ADC Channel Err", ESP_ERR_INVALID_ARG);
|
|
|
- adc1_adc_mode_acquire();
|
|
|
- adc_power_on();
|
|
|
-
|
|
|
- portENTER_CRITICAL(&rtc_spinlock);
|
|
|
- //disable other peripherals
|
|
|
- adc1_hall_enable(false);
|
|
|
- adc1_fsm_disable(); //currently the LNA is not open, close it by default
|
|
|
- //set controller
|
|
|
- adc_set_controller( ADC_UNIT_1, ADC_CTRL_RTC );
|
|
|
- //start conversion
|
|
|
- adc_value = adc_convert( ADC_UNIT_1, channel );
|
|
|
- portEXIT_CRITICAL(&rtc_spinlock);
|
|
|
- adc1_lock_release();
|
|
|
- return adc_value;
|
|
|
-}
|
|
|
-
|
|
|
-void adc1_ulp_enable(void)
|
|
|
-{
|
|
|
- adc_power_on();
|
|
|
-
|
|
|
- portENTER_CRITICAL(&rtc_spinlock);
|
|
|
- adc_set_controller( ADC_UNIT_1, ADC_CTRL_ULP );
|
|
|
- // since most users do not need LNA and HALL with uLP, we disable them here
|
|
|
- // open them in the uLP if needed.
|
|
|
- adc1_fsm_disable();
|
|
|
- adc1_hall_enable(false);
|
|
|
- portEXIT_CRITICAL(&rtc_spinlock);
|
|
|
-}
|
|
|
-
|
|
|
-/*---------------------------------------------------------------
|
|
|
- ADC2
|
|
|
----------------------------------------------------------------*/
|
|
|
-esp_err_t adc2_pad_get_io_num(adc2_channel_t channel, gpio_num_t *gpio_num)
|
|
|
-{
|
|
|
- RTC_MODULE_CHECK(channel < ADC2_CHANNEL_MAX, "ADC2 Channel Err", ESP_ERR_INVALID_ARG);
|
|
|
-
|
|
|
- switch (channel) {
|
|
|
- case ADC2_CHANNEL_0:
|
|
|
- *gpio_num = ADC2_CHANNEL_0_GPIO_NUM;
|
|
|
- break;
|
|
|
- case ADC2_CHANNEL_1:
|
|
|
- *gpio_num = ADC2_CHANNEL_1_GPIO_NUM;
|
|
|
- break;
|
|
|
- case ADC2_CHANNEL_2:
|
|
|
- *gpio_num = ADC2_CHANNEL_2_GPIO_NUM;
|
|
|
- break;
|
|
|
- case ADC2_CHANNEL_3:
|
|
|
- *gpio_num = ADC2_CHANNEL_3_GPIO_NUM;
|
|
|
- break;
|
|
|
- case ADC2_CHANNEL_4:
|
|
|
- *gpio_num = ADC2_CHANNEL_4_GPIO_NUM;
|
|
|
- break;
|
|
|
- case ADC2_CHANNEL_5:
|
|
|
- *gpio_num = ADC2_CHANNEL_5_GPIO_NUM;
|
|
|
- break;
|
|
|
- case ADC2_CHANNEL_6:
|
|
|
- *gpio_num = ADC2_CHANNEL_6_GPIO_NUM;
|
|
|
- break;
|
|
|
- case ADC2_CHANNEL_7:
|
|
|
- *gpio_num = ADC2_CHANNEL_7_GPIO_NUM;
|
|
|
- break;
|
|
|
- case ADC2_CHANNEL_8:
|
|
|
- *gpio_num = ADC2_CHANNEL_8_GPIO_NUM;
|
|
|
- break;
|
|
|
- case ADC2_CHANNEL_9:
|
|
|
- *gpio_num = ADC2_CHANNEL_9_GPIO_NUM;
|
|
|
- break;
|
|
|
- default:
|
|
|
- return ESP_ERR_INVALID_ARG;
|
|
|
- }
|
|
|
-
|
|
|
- return ESP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-esp_err_t adc2_wifi_acquire(void)
|
|
|
-{
|
|
|
- //lazy initialization
|
|
|
- //for wifi, block until acquire the lock
|
|
|
- _lock_acquire( &adc2_wifi_lock );
|
|
|
- ESP_LOGD( RTC_MODULE_TAG, "Wi-Fi takes adc2 lock." );
|
|
|
- return ESP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-esp_err_t adc2_wifi_release(void)
|
|
|
-{
|
|
|
- RTC_MODULE_CHECK((uint32_t*)adc2_wifi_lock != NULL, "wifi release called before acquire", ESP_ERR_INVALID_STATE );
|
|
|
-
|
|
|
- _lock_release( &adc2_wifi_lock );
|
|
|
- ESP_LOGD( RTC_MODULE_TAG, "Wi-Fi returns adc2 lock." );
|
|
|
- return ESP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-static esp_err_t adc2_pad_init(adc2_channel_t channel)
|
|
|
-{
|
|
|
- gpio_num_t gpio_num = 0;
|
|
|
- ADC2_CHECK_FUNCTION_RET(adc2_pad_get_io_num(channel, &gpio_num));
|
|
|
- ADC2_CHECK_FUNCTION_RET(rtc_gpio_init(gpio_num));
|
|
|
- ADC1_CHECK_FUNCTION_RET(rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_DISABLED));
|
|
|
- ADC2_CHECK_FUNCTION_RET(gpio_set_pull_mode(gpio_num, GPIO_FLOATING));
|
|
|
- return ESP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten)
|
|
|
-{
|
|
|
- RTC_MODULE_CHECK(channel < ADC2_CHANNEL_MAX, "ADC2 Channel Err", ESP_ERR_INVALID_ARG);
|
|
|
- RTC_MODULE_CHECK(atten <= ADC_ATTEN_11db, "ADC2 Atten Err", ESP_ERR_INVALID_ARG);
|
|
|
-
|
|
|
- adc2_pad_init(channel);
|
|
|
- portENTER_CRITICAL( &adc2_spinlock );
|
|
|
-
|
|
|
- //lazy initialization
|
|
|
- //avoid collision with other tasks
|
|
|
- if ( _lock_try_acquire( &adc2_wifi_lock ) == -1 ) {
|
|
|
- //try the lock, return if failed (wifi using).
|
|
|
- portEXIT_CRITICAL( &adc2_spinlock );
|
|
|
- return ESP_ERR_TIMEOUT;
|
|
|
- }
|
|
|
- SENS.sar_atten2 = ( SENS.sar_atten2 & ~(3<<(channel*2)) ) | ((atten&3) << (channel*2));
|
|
|
- _lock_release( &adc2_wifi_lock );
|
|
|
-
|
|
|
- portEXIT_CRITICAL( &adc2_spinlock );
|
|
|
- return ESP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-static inline void adc2_config_width(adc_bits_width_t width_bit)
|
|
|
-{
|
|
|
- portENTER_CRITICAL(&rtc_spinlock);
|
|
|
-#if CONFIG_IDF_TARGET_ESP32
|
|
|
- //sar_start_force shared with ADC1
|
|
|
- SENS.sar_start_force.sar2_bit_width = width_bit;
|
|
|
- //cct set to the same value with PHY
|
|
|
- SENS.sar_start_force.sar2_pwdet_cct = 4;
|
|
|
- portEXIT_CRITICAL(&rtc_spinlock);
|
|
|
-
|
|
|
- //Invert the adc value,the Output value is invert
|
|
|
- SENS.sar_read_ctrl2.sar2_data_inv = 1;
|
|
|
- //Set The adc sample width,invert adc value,must digital sar2_bit_width[1:0]=3
|
|
|
- SENS.sar_read_ctrl2.sar2_sample_bit = width_bit;
|
|
|
-#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
|
|
- //sar_start_force shared with ADC1
|
|
|
- SENS.sar_meas2_ctrl1.sar2_bit_width = width_bit;
|
|
|
- //cct set to the same value with PHY
|
|
|
- SENS.sar_meas2_mux.sar2_pwdet_cct = 4;
|
|
|
- portEXIT_CRITICAL(&rtc_spinlock);
|
|
|
- //Invert the adc value,the Output value is invert
|
|
|
- SENS.sar_reader2_ctrl.sar2_data_inv = 1;
|
|
|
- //Set The adc sample width,invert adc value,must digital sar2_bit_width[1:0]=3
|
|
|
- SENS.sar_reader2_ctrl.sar2_sample_bit = width_bit;
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
-static inline void adc2_dac_disable( adc2_channel_t channel)
|
|
|
-{
|
|
|
-#if CONFIG_IDF_TARGET_ESP32
|
|
|
- if ( channel == ADC2_CHANNEL_8 ) { // the same as DAC channel 1
|
|
|
- dac_ll_power_down( DAC_CHANNEL_1 );
|
|
|
- } else if ( channel == ADC2_CHANNEL_9 ) {
|
|
|
- dac_ll_power_down( DAC_CHANNEL_2 );
|
|
|
- }
|
|
|
-#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
|
|
- if ( channel == ADC2_CHANNEL_6 ) { // the same as DAC channel 1
|
|
|
- dac_ll_power_down( DAC_CHANNEL_1 );
|
|
|
- } else if ( channel == ADC2_CHANNEL_7 ) {
|
|
|
- dac_ll_power_down( DAC_CHANNEL_2 );
|
|
|
- }
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
-//registers in critical section with adc1:
|
|
|
-//SENS_SAR_START_FORCE_REG,
|
|
|
-esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int* raw_out)
|
|
|
-{
|
|
|
- uint16_t adc_value = 0;
|
|
|
- RTC_MODULE_CHECK(channel < ADC2_CHANNEL_MAX, "ADC Channel Err", ESP_ERR_INVALID_ARG);
|
|
|
-
|
|
|
- //in critical section with whole rtc module
|
|
|
- adc_power_on();
|
|
|
-
|
|
|
- //avoid collision with other tasks
|
|
|
- portENTER_CRITICAL(&adc2_spinlock);
|
|
|
- //lazy initialization
|
|
|
- //try the lock, return if failed (wifi using).
|
|
|
- if ( _lock_try_acquire( &adc2_wifi_lock ) == -1 ) {
|
|
|
- portEXIT_CRITICAL( &adc2_spinlock );
|
|
|
- return ESP_ERR_TIMEOUT;
|
|
|
- }
|
|
|
-
|
|
|
- //disable other peripherals
|
|
|
-#ifdef CONFIG_ADC_DISABLE_DAC
|
|
|
- adc2_dac_disable( channel );
|
|
|
-#endif
|
|
|
- // set controller
|
|
|
- // in critical section with whole rtc module
|
|
|
- // because the PWDET use the same registers, place it here.
|
|
|
- adc2_config_width( width_bit );
|
|
|
- adc_set_controller( ADC_UNIT_2, ADC_CTRL_RTC );
|
|
|
- //start converting
|
|
|
- adc_value = adc_convert( ADC_UNIT_2, channel );
|
|
|
- _lock_release( &adc2_wifi_lock );
|
|
|
- portEXIT_CRITICAL(&adc2_spinlock);
|
|
|
-
|
|
|
- *raw_out = (int)adc_value;
|
|
|
- return ESP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-esp_err_t adc2_vref_to_gpio(gpio_num_t gpio)
|
|
|
-{
|
|
|
-#if CONFIG_IDF_TARGET_ESP32
|
|
|
- int channel;
|
|
|
- if(gpio == GPIO_NUM_25){
|
|
|
- channel = 8; //Channel 8 bit
|
|
|
- }else if (gpio == GPIO_NUM_26){
|
|
|
- channel = 9; //Channel 9 bit
|
|
|
- }else if (gpio == GPIO_NUM_27){
|
|
|
- channel = 7; //Channel 7 bit
|
|
|
- }else{
|
|
|
- return ESP_ERR_INVALID_ARG;
|
|
|
- }
|
|
|
-
|
|
|
- //Configure RTC gpio
|
|
|
- rtc_gpio_init(gpio);
|
|
|
- rtc_gpio_set_direction(gpio, RTC_GPIO_MODE_DISABLED);
|
|
|
- rtc_gpio_pullup_dis(gpio);
|
|
|
- rtc_gpio_pulldown_dis(gpio);
|
|
|
- //force fsm
|
|
|
- adc_power_always_on(); //Select power source of ADC
|
|
|
-
|
|
|
- RTCCNTL.bias_conf.dbg_atten = 0; //Check DBG effect outside sleep mode
|
|
|
- //set dtest (MUX_SEL : 0 -> RTC; 1-> vdd_sar2)
|
|
|
- RTCCNTL.test_mux.dtest_rtc = 1; //Config test mux to route v_ref to ADC2 Channels
|
|
|
- //set ent
|
|
|
- RTCCNTL.test_mux.ent_rtc = 1;
|
|
|
- //set sar2_en_test
|
|
|
- SENS.sar_start_force.sar2_en_test = 1;
|
|
|
- //set sar2 en force
|
|
|
- SENS.sar_meas_start2.sar2_en_pad_force = 1; //Pad bitmap controlled by SW
|
|
|
- //set en_pad for channels 7,8,9 (bits 0x380)
|
|
|
- SENS.sar_meas_start2.sar2_en_pad = 1<<channel;
|
|
|
-#endif
|
|
|
- return ESP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-/*---------------------------------------------------------------
|
|
|
- HALL SENSOR
|
|
|
----------------------------------------------------------------*/
|
|
|
-
|
|
|
-static inline void adc1_hall_enable(bool enable)
|
|
|
-{
|
|
|
-#if CONFIG_IDF_TARGET_ESP32
|
|
|
- RTCIO.hall_sens.xpd_hall = enable;
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
-static int hall_sensor_get_value(void) //hall sensor without LNA
|
|
|
-{
|
|
|
- int hall_value = 0;
|
|
|
-
|
|
|
- adc_power_on();
|
|
|
-
|
|
|
-#if CONFIG_IDF_TARGET_ESP32
|
|
|
- int Sens_Vp0;
|
|
|
- int Sens_Vn0;
|
|
|
- int Sens_Vp1;
|
|
|
- int Sens_Vn1;
|
|
|
- portENTER_CRITICAL(&rtc_spinlock);
|
|
|
- //disable other peripherals
|
|
|
- adc1_fsm_disable();//currently the LNA is not open, close it by default
|
|
|
- adc1_hall_enable(true);
|
|
|
- // set controller
|
|
|
- adc_set_controller( ADC_UNIT_1, ADC_CTRL_RTC );
|
|
|
- // convert for 4 times with different phase and outputs
|
|
|
- RTCIO.hall_sens.hall_phase = 0; // hall phase
|
|
|
- Sens_Vp0 = adc_convert( ADC_UNIT_1, ADC1_CHANNEL_0 );
|
|
|
- Sens_Vn0 = adc_convert( ADC_UNIT_1, ADC1_CHANNEL_3 );
|
|
|
- RTCIO.hall_sens.hall_phase = 1;
|
|
|
- Sens_Vp1 = adc_convert( ADC_UNIT_1, ADC1_CHANNEL_0 );
|
|
|
- Sens_Vn1 = adc_convert( ADC_UNIT_1, ADC1_CHANNEL_3 );
|
|
|
- portEXIT_CRITICAL(&rtc_spinlock);
|
|
|
- hall_value = (Sens_Vp1 - Sens_Vp0) - (Sens_Vn1 - Sens_Vn0);
|
|
|
-#endif
|
|
|
- return hall_value;
|
|
|
-}
|
|
|
-
|
|
|
-int hall_sensor_read(void)
|
|
|
-{
|
|
|
- adc_gpio_init(ADC_UNIT_1, ADC1_CHANNEL_0);
|
|
|
- adc_gpio_init(ADC_UNIT_1, ADC1_CHANNEL_3);
|
|
|
- adc1_config_channel_atten(ADC1_CHANNEL_0, ADC_ATTEN_DB_0);
|
|
|
- adc1_config_channel_atten(ADC1_CHANNEL_3, ADC_ATTEN_DB_0);
|
|
|
- return hall_sensor_get_value();
|
|
|
-}
|
|
|
-
|
|
|
/*---------------------------------------------------------------
|
|
|
INTERRUPT HANDLER
|
|
|
---------------------------------------------------------------*/
|