mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
adc: support adc dma driver on all chips
This commit is contained in:
parent
5ddce053ea
commit
4dc0d6b2fe
@ -20,6 +20,12 @@ set(srcs
|
||||
|
||||
set(includes "include" "${target}/include" "deprecated")
|
||||
|
||||
if(CONFIG_SOC_ADC_SUPPORTED)
|
||||
list(APPEND srcs
|
||||
"adc_common.c"
|
||||
"adc.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SOC_MCPWM_SUPPORTED)
|
||||
list(APPEND srcs "mcpwm.c")
|
||||
endif()
|
||||
@ -30,8 +36,7 @@ endif()
|
||||
|
||||
if(${target} STREQUAL "esp32")
|
||||
# SDMMC and MCPWM are in ESP32 only.
|
||||
list(APPEND srcs "adc_common.c"
|
||||
"dac_common.c"
|
||||
list(APPEND srcs "dac_common.c"
|
||||
"sdio_slave.c"
|
||||
"sdmmc_host.c"
|
||||
"i2s.c"
|
||||
@ -41,13 +46,13 @@ if(${target} STREQUAL "esp32")
|
||||
"touch_sensor_common.c"
|
||||
"esp32/touch_sensor.c"
|
||||
"esp32/adc.c"
|
||||
"adc_deprecated.c"
|
||||
"esp32/dac.c"
|
||||
"twai.c")
|
||||
endif()
|
||||
|
||||
if(IDF_TARGET STREQUAL "esp32s2")
|
||||
list(APPEND srcs "adc_common.c"
|
||||
"dac_common.c"
|
||||
list(APPEND srcs "dac_common.c"
|
||||
"dedic_gpio.c"
|
||||
"spi_slave_hd.c"
|
||||
"touch_sensor_common.c"
|
||||
@ -58,13 +63,13 @@ if(IDF_TARGET STREQUAL "esp32s2")
|
||||
"esp32s2/rtc_tempsensor.c"
|
||||
"esp32s2/touch_sensor.c"
|
||||
"esp32s2/adc.c"
|
||||
"adc_deprecated.c"
|
||||
"esp32s2/adc2_init_cal.c"
|
||||
"esp32s2/dac.c")
|
||||
endif()
|
||||
|
||||
if(${target} STREQUAL "esp32s3")
|
||||
list(APPEND srcs "adc_common.c"
|
||||
"dedic_gpio.c"
|
||||
list(APPEND srcs "dedic_gpio.c"
|
||||
"sdmmc_host.c"
|
||||
"sdmmc_transaction.c"
|
||||
"rmt.c"
|
||||
@ -79,13 +84,11 @@ endif()
|
||||
|
||||
if(IDF_TARGET STREQUAL "esp32c3")
|
||||
list(APPEND srcs "spi_slave_hd.c"
|
||||
"adc_common.c"
|
||||
"dedic_gpio.c"
|
||||
"usb_serial_jtag.c"
|
||||
"i2s.c"
|
||||
"rmt.c"
|
||||
"sigmadelta.c"
|
||||
"esp32c3/adc.c"
|
||||
"esp32c3/adc2_init_cal.c"
|
||||
"esp32c3/rtc_tempsensor.c"
|
||||
"twai.c")
|
||||
@ -93,12 +96,10 @@ endif()
|
||||
|
||||
if(IDF_TARGET STREQUAL "esp32h2")
|
||||
list(APPEND srcs "spi_slave_hd.c"
|
||||
"adc_common.c"
|
||||
"dedic_gpio.c"
|
||||
"i2s.c"
|
||||
"rmt.c"
|
||||
"sigmadelta.c"
|
||||
"esp32h2/adc.c"
|
||||
"esp32h2/rtc_tempsensor.c"
|
||||
"twai.c")
|
||||
endif()
|
||||
|
@ -12,49 +12,48 @@
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_pm.h"
|
||||
#include "esp_check.h"
|
||||
#include "sys/lock.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/timers.h"
|
||||
#include "freertos/ringbuf.h"
|
||||
#include "esp32c3/rom/ets_sys.h"
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/adc.h"
|
||||
#include "hal/adc_types.h"
|
||||
#include "hal/adc_hal.h"
|
||||
#include "hal/dma_types.h"
|
||||
//For calibration
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp_efuse_rtc_table.h"
|
||||
#elif SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
#include "esp_efuse_rtc_calib.h"
|
||||
#endif
|
||||
//For DMA
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
#include "esp_private/gdma.h"
|
||||
|
||||
#define ADC_CHECK_RET(fun_ret) ({ \
|
||||
if (fun_ret != ESP_OK) { \
|
||||
ESP_LOGE(ADC_TAG,"%s(%d)",__FUNCTION__,__LINE__); \
|
||||
return ESP_FAIL; \
|
||||
} \
|
||||
})
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "hal/spi_types.h"
|
||||
#include "driver/spi_common_internal.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32
|
||||
#include "driver/i2s.h"
|
||||
#include "hal/i2s_types.h"
|
||||
#include "soc/i2s_periph.h"
|
||||
#include "esp_private/i2s_platform.h"
|
||||
#endif
|
||||
|
||||
static const char *ADC_TAG = "ADC";
|
||||
|
||||
#define ADC_CHECK(a, str, ret_val) ({ \
|
||||
if (!(a)) { \
|
||||
ESP_LOGE(ADC_TAG,"%s(%d) :%s", __FUNCTION__, __LINE__, str); \
|
||||
return (ret_val); \
|
||||
} \
|
||||
})
|
||||
|
||||
#define ADC_GET_IO_NUM(periph, channel) (adc_channel_io_map[periph][channel])
|
||||
|
||||
#define ADC_CHANNEL_CHECK(periph, channel) ADC_CHECK(channel < SOC_ADC_CHANNEL_NUM(periph), "ADC"#periph" channel error", ESP_ERR_INVALID_ARG)
|
||||
|
||||
extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished.
|
||||
#define ADC_ENTER_CRITICAL() portENTER_CRITICAL(&rtc_spinlock)
|
||||
#define ADC_EXIT_CRITICAL() portEXIT_CRITICAL(&rtc_spinlock)
|
||||
|
||||
/**
|
||||
* 1. sar_adc1_lock: this mutex lock is to protect the SARADC1 module.
|
||||
* 2. sar_adc2_lock: this mutex lock is to protect the SARADC2 module. On C3, it is controlled by the digital controller
|
||||
* and PWDET controller.
|
||||
* 2. sar_adc2_lock: this mutex lock is to protect the SARADC2 module.
|
||||
* 3. adc_reg_lock: this spin lock is to protect the shared registers used by ADC1 / ADC2 single read mode.
|
||||
*/
|
||||
static _lock_t sar_adc1_lock;
|
||||
@ -68,35 +67,55 @@ portMUX_TYPE adc_reg_lock = portMUX_INITIALIZER_UNLOCKED;
|
||||
#define ADC_REG_LOCK_EXIT() portEXIT_CRITICAL(&adc_reg_lock)
|
||||
|
||||
#define INTERNAL_BUF_NUM 5
|
||||
#define IN_SUC_EOF_BIT GDMA_LL_EVENT_RX_SUC_EOF
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Digital Controller Context
|
||||
---------------------------------------------------------------*/
|
||||
typedef struct adc_digi_context_t {
|
||||
uint8_t *rx_dma_buf; //dma buffer
|
||||
adc_hal_context_t hal; //hal context
|
||||
gdma_channel_handle_t rx_dma_channel; //dma rx channel handle
|
||||
RingbufHandle_t ringbuf_hdl; //RX ringbuffer handler
|
||||
intptr_t rx_eof_desc_addr; //eof descriptor address of RX channel
|
||||
bool ringbuf_overflow_flag; //1: ringbuffer overflow
|
||||
bool driver_start_flag; //1: driver is started; 0: driver is stoped
|
||||
bool use_adc1; //1: ADC unit1 will be used; 0: ADC unit1 won't be used.
|
||||
bool use_adc2; //1: ADC unit2 will be used; 0: ADC unit2 won't be used. This determines whether to acquire sar_adc2_mutex lock or not.
|
||||
adc_atten_t adc1_atten; //Attenuation for ADC1. On this chip each ADC can only support one attenuation.
|
||||
adc_atten_t adc2_atten; //Attenuation for ADC2. On this chip each ADC can only support one attenuation.
|
||||
adc_digi_config_t digi_controller_config; //Digital Controller Configuration
|
||||
esp_pm_lock_handle_t pm_lock; //For power management
|
||||
uint8_t *rx_dma_buf; //dma buffer
|
||||
adc_hal_context_t hal; //hal context
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
gdma_channel_handle_t rx_dma_channel; //dma rx channel handle
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
spi_host_device_t spi_host; //ADC uses this SPI DMA
|
||||
intr_handle_t intr_hdl; //Interrupt handler
|
||||
#elif CONFIG_IDF_TARGET_ESP32
|
||||
i2s_port_t i2s_host; //ADC uses this I2S DMA
|
||||
intr_handle_t intr_hdl; //Interrupt handler
|
||||
#endif
|
||||
RingbufHandle_t ringbuf_hdl; //RX ringbuffer handler
|
||||
intptr_t rx_eof_desc_addr; //eof descriptor address of RX channel
|
||||
bool ringbuf_overflow_flag; //1: ringbuffer overflow
|
||||
bool driver_start_flag; //1: driver is started; 0: driver is stoped
|
||||
bool use_adc1; //1: ADC unit1 will be used; 0: ADC unit1 won't be used.
|
||||
bool use_adc2; //1: ADC unit2 will be used; 0: ADC unit2 won't be used. This determines whether to acquire sar_adc2_mutex lock or not.
|
||||
adc_atten_t adc1_atten; //Attenuation for ADC1. On this chip each ADC can only support one attenuation.
|
||||
adc_atten_t adc2_atten; //Attenuation for ADC2. On this chip each ADC can only support one attenuation.
|
||||
adc_hal_digi_ctrlr_cfg_t hal_digi_ctrlr_cfg; //Hal digital controller configuration
|
||||
esp_pm_lock_handle_t pm_lock; //For power management
|
||||
} adc_digi_context_t;
|
||||
|
||||
static adc_digi_context_t *s_adc_digi_ctx = NULL;
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
//Only for deprecated API
|
||||
extern esp_pm_lock_handle_t adc_digi_arbiter_lock;
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
|
||||
static uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t chan, adc_atten_t atten);
|
||||
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t chan, adc_atten_t atten);
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
ADC Continuous Read Mode (via DMA)
|
||||
---------------------------------------------------------------*/
|
||||
//Function to address transaction
|
||||
static IRAM_ATTR bool s_adc_dma_intr(adc_digi_context_t *adc_digi_ctx);
|
||||
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
static IRAM_ATTR bool adc_dma_in_suc_eof_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data);
|
||||
#else
|
||||
static IRAM_ATTR void adc_dma_intr_handler(void *arg);
|
||||
#endif
|
||||
|
||||
static int8_t adc_digi_get_io_num(uint8_t adc_unit, uint8_t adc_channel)
|
||||
{
|
||||
@ -149,7 +168,7 @@ esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config)
|
||||
}
|
||||
|
||||
//malloc internal buffer used by DMA
|
||||
s_adc_digi_ctx->rx_dma_buf = heap_caps_calloc(1, init_config->conv_num_each_intr * INTERNAL_BUF_NUM, MALLOC_CAP_INTERNAL);
|
||||
s_adc_digi_ctx->rx_dma_buf = heap_caps_calloc(1, init_config->conv_num_each_intr * INTERNAL_BUF_NUM, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA);
|
||||
if (!s_adc_digi_ctx->rx_dma_buf) {
|
||||
ret = ESP_ERR_NO_MEM;
|
||||
goto cleanup;
|
||||
@ -163,8 +182,8 @@ esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config)
|
||||
}
|
||||
|
||||
//malloc pattern table
|
||||
s_adc_digi_ctx->digi_controller_config.adc_pattern = calloc(1, SOC_ADC_PATT_LEN_MAX * sizeof(adc_digi_pattern_table_t));
|
||||
if (!s_adc_digi_ctx->digi_controller_config.adc_pattern) {
|
||||
s_adc_digi_ctx->hal_digi_ctrlr_cfg.adc_pattern = calloc(1, SOC_ADC_PATT_LEN_MAX * sizeof(adc_digi_pattern_config_t));
|
||||
if (!s_adc_digi_ctx->hal_digi_ctrlr_cfg.adc_pattern) {
|
||||
ret = ESP_ERR_NO_MEM;
|
||||
goto cleanup;
|
||||
}
|
||||
@ -190,6 +209,7 @@ esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config)
|
||||
}
|
||||
}
|
||||
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
//alloc rx gdma channel
|
||||
gdma_channel_alloc_config_t rx_alloc_config = {
|
||||
.direction = GDMA_CHANNEL_DIRECTION_RX,
|
||||
@ -214,7 +234,50 @@ esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config)
|
||||
int dma_chan;
|
||||
gdma_get_channel_id(s_adc_digi_ctx->rx_dma_channel, &dma_chan);
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
//ADC utilises SPI3 DMA on ESP32S2
|
||||
bool spi_success = false;
|
||||
uint32_t dma_chan = 0;
|
||||
|
||||
spi_success = spicommon_periph_claim(SPI3_HOST, "adc");
|
||||
ret = spicommon_dma_chan_alloc(SPI3_HOST, SPI_DMA_CH_AUTO, &dma_chan, &dma_chan);
|
||||
if (ret == ESP_OK) {
|
||||
s_adc_digi_ctx->spi_host = SPI3_HOST;
|
||||
}
|
||||
if (!spi_success || (s_adc_digi_ctx->spi_host != SPI3_HOST)) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = esp_intr_alloc(spicommon_irqdma_source_for_host(s_adc_digi_ctx->spi_host), 0, adc_dma_intr_handler,
|
||||
(void *)s_adc_digi_ctx, &s_adc_digi_ctx->intr_hdl);
|
||||
if (ret != ESP_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32
|
||||
//ADC utilises I2S0 DMA on ESP32
|
||||
uint32_t dma_chan = 0;
|
||||
ret = i2s_priv_register_object(&s_adc_digi_ctx, I2S_NUM_0);
|
||||
if (ret != ESP_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
s_adc_digi_ctx->i2s_host = I2S_NUM_0;
|
||||
ret = esp_intr_alloc(i2s_periph_signal[s_adc_digi_ctx->i2s_host].irq, 0, adc_dma_intr_handler,
|
||||
(void *)s_adc_digi_ctx, &s_adc_digi_ctx->intr_hdl);
|
||||
if (ret != ESP_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
#endif
|
||||
|
||||
adc_hal_config_t config = {
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
.dev = (void *)GDMA_LL_GET_HW(0),
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
.dev = (void *)SPI_LL_GET_HW(s_adc_digi_ctx->spi_host),
|
||||
#elif CONFIG_IDF_TARGET_ESP32
|
||||
.dev = (void *)I2S_LL_GET_HW(s_adc_digi_ctx->i2s_host),
|
||||
#endif
|
||||
.desc_max_num = INTERNAL_BUF_NUM,
|
||||
.dma_chan = dma_chan,
|
||||
.eof_num = init_config->conv_num_each_intr / ADC_HAL_DATA_LEN_PER_CONV
|
||||
@ -224,28 +287,48 @@ esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config)
|
||||
//enable SARADC module clock
|
||||
periph_module_enable(PERIPH_SARADC_MODULE);
|
||||
|
||||
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
adc_hal_calibration_init(ADC_NUM_1);
|
||||
adc_hal_calibration_init(ADC_NUM_2);
|
||||
#endif //#if SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
|
||||
return ret;
|
||||
|
||||
cleanup:
|
||||
adc_digi_deinitialize();
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
static IRAM_ATTR bool adc_dma_intr(adc_digi_context_t *adc_digi_ctx);
|
||||
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
static IRAM_ATTR bool adc_dma_in_suc_eof_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data)
|
||||
{
|
||||
assert(event_data);
|
||||
adc_digi_context_t *adc_digi_ctx = (adc_digi_context_t *)user_data;
|
||||
adc_digi_ctx->rx_eof_desc_addr = event_data->rx_eof_desc_addr;
|
||||
return adc_dma_intr(adc_digi_ctx);
|
||||
s_adc_digi_ctx->rx_eof_desc_addr = event_data->rx_eof_desc_addr;
|
||||
return s_adc_dma_intr(user_data);
|
||||
}
|
||||
#else
|
||||
static IRAM_ATTR void adc_dma_intr_handler(void *arg)
|
||||
{
|
||||
adc_digi_context_t *ctx = (adc_digi_context_t *)arg;
|
||||
bool need_yield = false;
|
||||
|
||||
static IRAM_ATTR bool adc_dma_intr(adc_digi_context_t *adc_digi_ctx)
|
||||
bool conversion_finish = adc_hal_check_event(&ctx->hal, ADC_HAL_DMA_INTR_MASK);
|
||||
if (conversion_finish) {
|
||||
adc_hal_digi_clr_intr(&s_adc_digi_ctx->hal, ADC_HAL_DMA_INTR_MASK);
|
||||
|
||||
intptr_t desc_addr = adc_hal_get_desc_addr(&ctx->hal);
|
||||
|
||||
ctx->rx_eof_desc_addr = desc_addr;
|
||||
need_yield = s_adc_dma_intr(ctx);
|
||||
}
|
||||
|
||||
if (need_yield) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static IRAM_ATTR bool s_adc_dma_intr(adc_digi_context_t *adc_digi_ctx)
|
||||
{
|
||||
portBASE_TYPE taskAwoken = 0;
|
||||
BaseType_t ret;
|
||||
@ -267,7 +350,7 @@ static IRAM_ATTR bool adc_dma_intr(adc_digi_context_t *adc_digi_ctx)
|
||||
|
||||
if (status == ADC_HAL_DMA_DESC_NULL) {
|
||||
//start next turns of dma operation
|
||||
adc_hal_digi_rxdma_start(&adc_digi_ctx->hal, adc_digi_ctx->rx_dma_buf);
|
||||
adc_hal_digi_start(&adc_digi_ctx->hal, adc_digi_ctx->rx_dma_buf);
|
||||
}
|
||||
|
||||
return (taskAwoken == pdTRUE);
|
||||
@ -275,82 +358,117 @@ static IRAM_ATTR bool adc_dma_intr(adc_digi_context_t *adc_digi_ctx)
|
||||
|
||||
esp_err_t adc_digi_start(void)
|
||||
{
|
||||
if (s_adc_digi_ctx->driver_start_flag != 0) {
|
||||
ESP_LOGE(ADC_TAG, "The driver is already started");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
adc_power_acquire();
|
||||
//reset flags
|
||||
s_adc_digi_ctx->ringbuf_overflow_flag = 0;
|
||||
s_adc_digi_ctx->driver_start_flag = 1;
|
||||
if (s_adc_digi_ctx->use_adc1) {
|
||||
SAR_ADC1_LOCK_ACQUIRE();
|
||||
}
|
||||
if (s_adc_digi_ctx->use_adc2) {
|
||||
SAR_ADC2_LOCK_ACQUIRE();
|
||||
}
|
||||
if (s_adc_digi_ctx) {
|
||||
if (s_adc_digi_ctx->driver_start_flag != 0) {
|
||||
ESP_LOGE(ADC_TAG, "The driver is already started");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
adc_power_acquire();
|
||||
//reset flags
|
||||
s_adc_digi_ctx->ringbuf_overflow_flag = 0;
|
||||
s_adc_digi_ctx->driver_start_flag = 1;
|
||||
if (s_adc_digi_ctx->use_adc1) {
|
||||
SAR_ADC1_LOCK_ACQUIRE();
|
||||
}
|
||||
if (s_adc_digi_ctx->use_adc2) {
|
||||
SAR_ADC2_LOCK_ACQUIRE();
|
||||
}
|
||||
|
||||
#if CONFIG_PM_ENABLE
|
||||
// Lock APB frequency while ADC driver is in use
|
||||
esp_pm_lock_acquire(s_adc_digi_ctx->pm_lock);
|
||||
// Lock APB frequency while ADC driver is in use
|
||||
esp_pm_lock_acquire(s_adc_digi_ctx->pm_lock);
|
||||
#endif
|
||||
|
||||
adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT();
|
||||
if (s_adc_digi_ctx->use_adc1) {
|
||||
uint32_t cal_val = adc_get_calibration_offset(ADC_NUM_1, ADC_CHANNEL_MAX, s_adc_digi_ctx->adc1_atten);
|
||||
adc_hal_set_calibration_param(ADC_NUM_1, cal_val);
|
||||
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
if (s_adc_digi_ctx->use_adc1) {
|
||||
uint32_t cal_val = adc_get_calibration_offset(ADC_NUM_1, ADC_CHANNEL_MAX, s_adc_digi_ctx->adc1_atten);
|
||||
adc_hal_set_calibration_param(ADC_NUM_1, cal_val);
|
||||
}
|
||||
if (s_adc_digi_ctx->use_adc2) {
|
||||
uint32_t cal_val = adc_get_calibration_offset(ADC_NUM_2, ADC_CHANNEL_MAX, s_adc_digi_ctx->adc2_atten);
|
||||
adc_hal_set_calibration_param(ADC_NUM_2, cal_val);
|
||||
}
|
||||
#endif //#if SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
|
||||
adc_hal_init();
|
||||
#if SOC_ADC_ARBITER_SUPPORTED
|
||||
adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT();
|
||||
adc_hal_arbiter_config(&config);
|
||||
#endif //#if SOC_ADC_ARBITER_SUPPORTED
|
||||
|
||||
adc_hal_set_controller(ADC_NUM_1, ADC_HAL_CONTINUOUS_READ_MODE);
|
||||
adc_hal_set_controller(ADC_NUM_2, ADC_HAL_CONTINUOUS_READ_MODE);
|
||||
|
||||
adc_hal_digi_init(&s_adc_digi_ctx->hal);
|
||||
adc_hal_digi_controller_config(&s_adc_digi_ctx->hal, &s_adc_digi_ctx->hal_digi_ctrlr_cfg);
|
||||
|
||||
//start conversion
|
||||
adc_hal_digi_start(&s_adc_digi_ctx->hal, s_adc_digi_ctx->rx_dma_buf);
|
||||
|
||||
}
|
||||
if (s_adc_digi_ctx->use_adc2) {
|
||||
uint32_t cal_val = adc_get_calibration_offset(ADC_NUM_2, ADC_CHANNEL_MAX, s_adc_digi_ctx->adc2_atten);
|
||||
adc_hal_set_calibration_param(ADC_NUM_2, cal_val);
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
//For being compatible with the deprecated behaviour
|
||||
else {
|
||||
ESP_LOGE(ADC_TAG, "API used without driver initialization before. The following behaviour is deprecated!!");
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
ESP_RETURN_ON_FALSE((adc_digi_arbiter_lock), ESP_FAIL, ADC_TAG, "Should start after call `adc_digi_controller_config`");
|
||||
esp_pm_lock_acquire(adc_digi_arbiter_lock);
|
||||
#endif
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_ll_digi_dma_enable();
|
||||
adc_ll_digi_trigger_enable();
|
||||
ADC_EXIT_CRITICAL();
|
||||
}
|
||||
|
||||
adc_hal_init();
|
||||
adc_hal_arbiter_config(&config);
|
||||
adc_hal_digi_init(&s_adc_digi_ctx->hal);
|
||||
adc_hal_digi_controller_config(&s_adc_digi_ctx->digi_controller_config);
|
||||
|
||||
//reset ADC and DMA
|
||||
adc_hal_fifo_reset(&s_adc_digi_ctx->hal);
|
||||
//start DMA
|
||||
adc_hal_digi_rxdma_start(&s_adc_digi_ctx->hal, s_adc_digi_ctx->rx_dma_buf);
|
||||
//start ADC
|
||||
adc_hal_digi_start(&s_adc_digi_ctx->hal);
|
||||
|
||||
#endif //#if CONFIG_IDF_TARGET_ESP32S2
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_stop(void)
|
||||
{
|
||||
if (s_adc_digi_ctx->driver_start_flag != 1) {
|
||||
ESP_LOGE(ADC_TAG, "The driver is already stopped");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
s_adc_digi_ctx->driver_start_flag = 0;
|
||||
if (s_adc_digi_ctx) {
|
||||
if (s_adc_digi_ctx->driver_start_flag != 1) {
|
||||
ESP_LOGE(ADC_TAG, "The driver is already stopped");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
s_adc_digi_ctx->driver_start_flag = 0;
|
||||
|
||||
//disable the in suc eof intrrupt
|
||||
adc_hal_digi_dis_intr(&s_adc_digi_ctx->hal, IN_SUC_EOF_BIT);
|
||||
//clear the in suc eof interrupt
|
||||
adc_hal_digi_clr_intr(&s_adc_digi_ctx->hal, IN_SUC_EOF_BIT);
|
||||
//stop ADC
|
||||
adc_hal_digi_stop(&s_adc_digi_ctx->hal);
|
||||
//stop DMA
|
||||
adc_hal_digi_rxdma_stop(&s_adc_digi_ctx->hal);
|
||||
adc_hal_digi_deinit();
|
||||
//disable the in suc eof intrrupt
|
||||
adc_hal_digi_dis_intr(&s_adc_digi_ctx->hal, ADC_HAL_DMA_INTR_MASK);
|
||||
//clear the in suc eof interrupt
|
||||
adc_hal_digi_clr_intr(&s_adc_digi_ctx->hal, ADC_HAL_DMA_INTR_MASK);
|
||||
//stop ADC
|
||||
adc_hal_digi_stop(&s_adc_digi_ctx->hal);
|
||||
|
||||
adc_hal_digi_deinit(&s_adc_digi_ctx->hal);
|
||||
#if CONFIG_PM_ENABLE
|
||||
if (s_adc_digi_ctx->pm_lock) {
|
||||
esp_pm_lock_release(s_adc_digi_ctx->pm_lock);
|
||||
}
|
||||
if (s_adc_digi_ctx->pm_lock) {
|
||||
esp_pm_lock_release(s_adc_digi_ctx->pm_lock);
|
||||
}
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
|
||||
if (s_adc_digi_ctx->use_adc1) {
|
||||
SAR_ADC1_LOCK_RELEASE();
|
||||
if (s_adc_digi_ctx->use_adc1) {
|
||||
SAR_ADC1_LOCK_RELEASE();
|
||||
}
|
||||
if (s_adc_digi_ctx->use_adc2) {
|
||||
SAR_ADC2_LOCK_RELEASE();
|
||||
}
|
||||
adc_power_release();
|
||||
}
|
||||
if (s_adc_digi_ctx->use_adc2) {
|
||||
SAR_ADC2_LOCK_RELEASE();
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
else {
|
||||
//For being compatible with the deprecated behaviour
|
||||
ESP_LOGE(ADC_TAG, "API used without driver initialization before. The following behaviour is deprecated!!");
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
if (adc_digi_arbiter_lock) {
|
||||
esp_pm_lock_release(adc_digi_arbiter_lock);
|
||||
}
|
||||
#endif
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_ll_digi_trigger_disable();
|
||||
adc_ll_digi_dma_disable();
|
||||
ADC_EXIT_CRITICAL();
|
||||
}
|
||||
adc_power_release();
|
||||
|
||||
#endif //#if CONFIG_IDF_TARGET_ESP32S2
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -410,10 +528,18 @@ esp_err_t adc_digi_deinitialize(void)
|
||||
|
||||
free(s_adc_digi_ctx->rx_dma_buf);
|
||||
free(s_adc_digi_ctx->hal.rx_desc);
|
||||
free(s_adc_digi_ctx->digi_controller_config.adc_pattern);
|
||||
free(s_adc_digi_ctx->hal_digi_ctrlr_cfg.adc_pattern);
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
gdma_disconnect(s_adc_digi_ctx->rx_dma_channel);
|
||||
gdma_del_channel(s_adc_digi_ctx->rx_dma_channel);
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
esp_intr_free(s_adc_digi_ctx->intr_hdl);
|
||||
spicommon_dma_chan_free(s_adc_digi_ctx->spi_host);
|
||||
spicommon_periph_free(s_adc_digi_ctx->spi_host);
|
||||
#elif CONFIG_IDF_TARGET_ESP32
|
||||
esp_intr_free(s_adc_digi_ctx->intr_hdl);
|
||||
i2s_priv_deregister_object(s_adc_digi_ctx->i2s_host);
|
||||
#endif
|
||||
free(s_adc_digi_ctx);
|
||||
s_adc_digi_ctx = NULL;
|
||||
|
||||
@ -422,6 +548,83 @@ esp_err_t adc_digi_deinitialize(void)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Digital controller setting
|
||||
---------------------------------------------------------------*/
|
||||
esp_err_t adc_digi_controller_configure(const adc_digi_configuration_t *config)
|
||||
{
|
||||
if (!s_adc_digi_ctx) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
//Pattern related check
|
||||
ESP_RETURN_ON_FALSE(config->pattern_num <= SOC_ADC_PATT_LEN_MAX, ESP_ERR_INVALID_ARG, ADC_TAG, "Max pattern num is %d", SOC_ADC_PATT_LEN_MAX);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
for (int i = 0; i < config->pattern_num; i++) {
|
||||
ESP_RETURN_ON_FALSE((config->adc_pattern[i].bit_width >= SOC_ADC_DIGI_MIN_BITWIDTH && config->adc_pattern->bit_width <= SOC_ADC_DIGI_MAX_BITWIDTH), ESP_ERR_INVALID_ARG, ADC_TAG, "ADC bitwidth not supported");
|
||||
ESP_RETURN_ON_FALSE(config->adc_pattern[i].unit == 0, ESP_ERR_INVALID_ARG, ADC_TAG, "Only support using ADC1 DMA mode");
|
||||
}
|
||||
#else
|
||||
for (int i = 0; i < config->pattern_num; i++) {
|
||||
ESP_RETURN_ON_FALSE((config->adc_pattern[i].bit_width == SOC_ADC_DIGI_MAX_BITWIDTH), ESP_ERR_INVALID_ARG, ADC_TAG, "ADC bitwidth not supported");
|
||||
}
|
||||
#endif
|
||||
ESP_RETURN_ON_FALSE(config->sample_freq_hz <= SOC_ADC_SAMPLE_FREQ_THRES_HIGH && config->sample_freq_hz >= SOC_ADC_SAMPLE_FREQ_THRES_LOW, ESP_ERR_INVALID_ARG, ADC_TAG, "ADC sampling frequency out of range");
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
ESP_RETURN_ON_FALSE(config->conv_limit_en == 1, ESP_ERR_INVALID_ARG, ADC_TAG, "`conv_limit_en` should be set to 1");
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
ESP_RETURN_ON_FALSE(config->format == ADC_DIGI_OUTPUT_FORMAT_TYPE1, ESP_ERR_INVALID_ARG, ADC_TAG, "Please use type1");
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
if (config->conv_mode == ADC_CONV_BOTH_UNIT || config->conv_mode == ADC_CONV_ALTER_UNIT) {
|
||||
ESP_RETURN_ON_FALSE(config->format == ADC_DIGI_OUTPUT_FORMAT_TYPE2, ESP_ERR_INVALID_ARG, ADC_TAG, "Please use type2");
|
||||
} else if (config->conv_mode == ADC_CONV_SINGLE_UNIT_1 || config->conv_mode == ADC_CONV_SINGLE_UNIT_2) {
|
||||
ESP_RETURN_ON_FALSE(config->format == ADC_DIGI_OUTPUT_FORMAT_TYPE1, ESP_ERR_INVALID_ARG, ADC_TAG, "Please use type1");
|
||||
}
|
||||
#else
|
||||
ESP_RETURN_ON_FALSE(config->format == ADC_DIGI_OUTPUT_FORMAT_TYPE2, ESP_ERR_INVALID_ARG, ADC_TAG, "Please use type2");
|
||||
#endif
|
||||
|
||||
s_adc_digi_ctx->hal_digi_ctrlr_cfg.conv_limit_en = config->conv_limit_en;
|
||||
s_adc_digi_ctx->hal_digi_ctrlr_cfg.conv_limit_num = config->conv_limit_num;
|
||||
s_adc_digi_ctx->hal_digi_ctrlr_cfg.adc_pattern_len = config->pattern_num;
|
||||
s_adc_digi_ctx->hal_digi_ctrlr_cfg.sample_freq_hz = config->sample_freq_hz;
|
||||
s_adc_digi_ctx->hal_digi_ctrlr_cfg.conv_mode = config->conv_mode;
|
||||
memcpy(s_adc_digi_ctx->hal_digi_ctrlr_cfg.adc_pattern, config->adc_pattern, config->pattern_num * sizeof(adc_digi_pattern_config_t));
|
||||
|
||||
const int atten_uninitialized = 999;
|
||||
s_adc_digi_ctx->adc1_atten = atten_uninitialized;
|
||||
s_adc_digi_ctx->adc2_atten = atten_uninitialized;
|
||||
s_adc_digi_ctx->use_adc1 = 0;
|
||||
s_adc_digi_ctx->use_adc2 = 0;
|
||||
for (int i = 0; i < config->pattern_num; i++) {
|
||||
const adc_digi_pattern_config_t *pat = &config->adc_pattern[i];
|
||||
if (pat->unit == ADC_NUM_1) {
|
||||
s_adc_digi_ctx->use_adc1 = 1;
|
||||
|
||||
if (s_adc_digi_ctx->adc1_atten == atten_uninitialized) {
|
||||
s_adc_digi_ctx->adc1_atten = pat->atten;
|
||||
} else if (s_adc_digi_ctx->adc1_atten != pat->atten) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
} else if (pat->unit == ADC_NUM_2) {
|
||||
//See whether ADC2 will be used or not. If yes, the ``sar_adc2_mutex`` should be acquired in the continuous read driver
|
||||
s_adc_digi_ctx->use_adc2 = 1;
|
||||
|
||||
if (s_adc_digi_ctx->adc2_atten == atten_uninitialized) {
|
||||
s_adc_digi_ctx->adc2_atten = pat->atten;
|
||||
} else if (s_adc_digi_ctx->adc2_atten != pat->atten) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32C3
|
||||
/*---------------------------------------------------------------
|
||||
ADC Single Read Mode
|
||||
---------------------------------------------------------------*/
|
||||
@ -472,8 +675,8 @@ esp_err_t adc1_config_width(adc_bits_width_t width_bit)
|
||||
|
||||
esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten)
|
||||
{
|
||||
ADC_CHANNEL_CHECK(ADC_NUM_1, channel);
|
||||
ADC_CHECK(atten < ADC_ATTEN_MAX, "ADC Atten Err", ESP_ERR_INVALID_ARG);
|
||||
ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(ADC_NUM_1), ESP_ERR_INVALID_ARG, ADC_TAG, "ADC1 channel error");
|
||||
ESP_RETURN_ON_FALSE((atten < ADC_ATTEN_MAX), ESP_ERR_INVALID_ARG, ADC_TAG, "ADC Atten Err");
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
s_atten1_single[channel] = atten;
|
||||
@ -512,8 +715,8 @@ int adc1_get_raw(adc1_channel_t channel)
|
||||
|
||||
esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten)
|
||||
{
|
||||
ADC_CHANNEL_CHECK(ADC_NUM_2, channel);
|
||||
ADC_CHECK(atten <= ADC_ATTEN_11db, "ADC2 Atten Err", ESP_ERR_INVALID_ARG);
|
||||
ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(ADC_NUM_2), ESP_ERR_INVALID_ARG, ADC_TAG, "ADC2 channel error");
|
||||
ESP_RETURN_ON_FALSE((atten <= ADC_ATTEN_11db), ESP_ERR_INVALID_ARG, ADC_TAG, "ADC2 Atten Err");
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
s_atten2_single[channel] = atten;
|
||||
@ -558,53 +761,6 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Digital controller setting
|
||||
---------------------------------------------------------------*/
|
||||
esp_err_t adc_digi_controller_config(const adc_digi_config_t *config)
|
||||
{
|
||||
if (!s_adc_digi_ctx) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
ADC_CHECK(config->sample_freq_hz <= SOC_ADC_SAMPLE_FREQ_THRES_HIGH && config->sample_freq_hz >= SOC_ADC_SAMPLE_FREQ_THRES_LOW, "ADC sampling frequency out of range", ESP_ERR_INVALID_ARG);
|
||||
|
||||
s_adc_digi_ctx->digi_controller_config.conv_limit_en = config->conv_limit_en;
|
||||
s_adc_digi_ctx->digi_controller_config.conv_limit_num = config->conv_limit_num;
|
||||
s_adc_digi_ctx->digi_controller_config.adc_pattern_len = config->adc_pattern_len;
|
||||
s_adc_digi_ctx->digi_controller_config.sample_freq_hz = config->sample_freq_hz;
|
||||
memcpy(s_adc_digi_ctx->digi_controller_config.adc_pattern, config->adc_pattern, config->adc_pattern_len * sizeof(adc_digi_pattern_table_t));
|
||||
|
||||
const int atten_uninitialised = 999;
|
||||
s_adc_digi_ctx->adc1_atten = atten_uninitialised;
|
||||
s_adc_digi_ctx->adc2_atten = atten_uninitialised;
|
||||
s_adc_digi_ctx->use_adc1 = 0;
|
||||
s_adc_digi_ctx->use_adc2 = 0;
|
||||
for (int i = 0; i < config->adc_pattern_len; i++) {
|
||||
const adc_digi_pattern_table_t *pat = &config->adc_pattern[i];
|
||||
if (pat->unit == ADC_NUM_1) {
|
||||
s_adc_digi_ctx->use_adc1 = 1;
|
||||
|
||||
if (s_adc_digi_ctx->adc1_atten == atten_uninitialised) {
|
||||
s_adc_digi_ctx->adc1_atten = pat->atten;
|
||||
} else if (s_adc_digi_ctx->adc1_atten != pat->atten) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
} else if (pat->unit == ADC_NUM_2) {
|
||||
//See whether ADC2 will be used or not. If yes, the ``sar_adc2_mutex`` should be acquired in the continuous read driver
|
||||
s_adc_digi_ctx->use_adc2 = 1;
|
||||
|
||||
if (s_adc_digi_ctx->adc2_atten == atten_uninitialised) {
|
||||
s_adc_digi_ctx->adc2_atten = pat->atten;
|
||||
} else if (s_adc_digi_ctx->adc2_atten != pat->atten) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/*************************************/
|
||||
/* Digital controller filter setting */
|
||||
/*************************************/
|
||||
@ -661,10 +817,22 @@ esp_err_t adc_digi_monitor_enable(adc_digi_monitor_idx_t idx, bool enable)
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif //#if CONFIG_IDF_TARGET_ESP32C3
|
||||
|
||||
|
||||
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
/*---------------------------------------------------------------
|
||||
RTC controller setting
|
||||
Hardware Calibration Setting
|
||||
---------------------------------------------------------------*/
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
#define esp_efuse_rtc_calib_get_ver() esp_efuse_rtc_table_read_calib_version()
|
||||
|
||||
static inline uint32_t esp_efuse_rtc_calib_get_init_code(int version, uint32_t adc_unit, int atten)
|
||||
{
|
||||
int tag = esp_efuse_rtc_table_get_tag(version, adc_unit + 1, atten, RTCCALIB_V2_PARAM_VINIT);
|
||||
return esp_efuse_rtc_table_get_parsed_efuse_value(tag, false);
|
||||
}
|
||||
#endif
|
||||
|
||||
static uint16_t s_adc_cali_param[SOC_ADC_PERIPH_NUM][ADC_ATTEN_MAX] = {};
|
||||
|
||||
@ -672,39 +840,34 @@ static uint16_t s_adc_cali_param[SOC_ADC_PERIPH_NUM][ADC_ATTEN_MAX] = {};
|
||||
// 1. Semaphore when reading efuse
|
||||
// 2. Lock (Spinlock, or Mutex) if we actually do ADC calibration in the future
|
||||
//This function shoudn't be called inside critical section or ISR
|
||||
static uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten)
|
||||
uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten)
|
||||
{
|
||||
const bool no_cal = false;
|
||||
if (s_adc_cali_param[adc_n][atten]) {
|
||||
ESP_LOGV(ADC_TAG, "Use calibrated val ADC%d atten=%d: %04X", adc_n, atten, s_adc_cali_param[adc_n][atten]);
|
||||
return (uint32_t)s_adc_cali_param[adc_n][atten];
|
||||
}
|
||||
|
||||
if (no_cal) {
|
||||
return 0; //indicating failure
|
||||
}
|
||||
|
||||
// check if we can fetch the values from eFuse.
|
||||
int version = esp_efuse_rtc_calib_get_ver();
|
||||
|
||||
uint32_t init_code = 0;
|
||||
if (version == 1) {
|
||||
//for calibration v1, both ADC units use the same init code (calibrated by ADC1)
|
||||
init_code = esp_efuse_rtc_calib_get_init_code(version, atten);
|
||||
ESP_LOGD(ADC_TAG, "Calib(V%d) ADC0, 1 atten=%d: %04X", version, atten, init_code);
|
||||
s_adc_cali_param[0][atten] = init_code;
|
||||
s_adc_cali_param[1][atten] = init_code;
|
||||
|
||||
if (version == ESP_EFUSE_ADC_CALIB_VER) {
|
||||
init_code = esp_efuse_rtc_calib_get_init_code(version, adc_n, atten);
|
||||
|
||||
} else {
|
||||
ESP_LOGD(ADC_TAG, "Calibration eFuse is not configured, use self-calibration for ICode");
|
||||
adc_power_acquire();
|
||||
ADC_ENTER_CRITICAL();
|
||||
const bool internal_gnd = true;
|
||||
init_code = adc_hal_self_calibration(adc_n, channel, atten, internal_gnd);
|
||||
ADC_EXIT_CRITICAL();
|
||||
adc_power_release();
|
||||
|
||||
ESP_LOGD(ADC_TAG, "Calib(V%d) ADC%d atten=%d: %04X", version, adc_n, atten, init_code);
|
||||
s_adc_cali_param[adc_n][atten] = init_code;
|
||||
}
|
||||
|
||||
s_adc_cali_param[adc_n][atten] = init_code;
|
||||
ESP_LOGV(ADC_TAG, "Calib(V%d) ADC%d atten=%d: %04X", version, adc_n, atten, init_code);
|
||||
|
||||
return init_code;
|
||||
}
|
||||
|
||||
@ -718,3 +881,61 @@ esp_err_t adc_cal_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif //#if SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Deprecated API
|
||||
---------------------------------------------------------------*/
|
||||
#if CONFIG_IDF_TARGET_ESP32C3
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#include "deprecated/driver/adc_deprecated.h"
|
||||
#include "deprecated/driver/adc_types_deprecated.h"
|
||||
esp_err_t adc_digi_controller_config(const adc_digi_config_t *config)
|
||||
{
|
||||
if (!s_adc_digi_ctx) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
ESP_RETURN_ON_FALSE((config->sample_freq_hz <= SOC_ADC_SAMPLE_FREQ_THRES_HIGH && config->sample_freq_hz >= SOC_ADC_SAMPLE_FREQ_THRES_LOW), ESP_ERR_INVALID_ARG, ADC_TAG, "DC sampling frequency out of range");
|
||||
|
||||
s_adc_digi_ctx->hal_digi_ctrlr_cfg.conv_limit_en = config->conv_limit_en;
|
||||
s_adc_digi_ctx->hal_digi_ctrlr_cfg.conv_limit_num = config->conv_limit_num;
|
||||
s_adc_digi_ctx->hal_digi_ctrlr_cfg.adc_pattern_len = config->adc_pattern_len;
|
||||
s_adc_digi_ctx->hal_digi_ctrlr_cfg.sample_freq_hz = config->sample_freq_hz;
|
||||
|
||||
for (int i = 0; i < config->adc_pattern_len; i++) {
|
||||
s_adc_digi_ctx->hal_digi_ctrlr_cfg.adc_pattern[i].atten = config->adc_pattern[i].atten;
|
||||
s_adc_digi_ctx->hal_digi_ctrlr_cfg.adc_pattern[i].channel = config->adc_pattern[i].channel;
|
||||
s_adc_digi_ctx->hal_digi_ctrlr_cfg.adc_pattern[i].unit = config->adc_pattern[i].unit;
|
||||
}
|
||||
|
||||
|
||||
const int atten_uninitialized = 999;
|
||||
s_adc_digi_ctx->adc1_atten = atten_uninitialized;
|
||||
s_adc_digi_ctx->adc2_atten = atten_uninitialized;
|
||||
s_adc_digi_ctx->use_adc1 = 0;
|
||||
s_adc_digi_ctx->use_adc2 = 0;
|
||||
for (int i = 0; i < config->adc_pattern_len; i++) {
|
||||
const adc_digi_pattern_config_t *pat = &s_adc_digi_ctx->hal_digi_ctrlr_cfg.adc_pattern[i];
|
||||
if (pat->unit == ADC_NUM_1) {
|
||||
s_adc_digi_ctx->use_adc1 = 1;
|
||||
|
||||
if (s_adc_digi_ctx->adc1_atten == atten_uninitialized) {
|
||||
s_adc_digi_ctx->adc1_atten = pat->atten;
|
||||
} else if (s_adc_digi_ctx->adc1_atten != pat->atten) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
} else if (pat->unit == ADC_NUM_2) {
|
||||
//See whether ADC2 will be used or not. If yes, the ``sar_adc2_mutex`` should be acquired in the continuous read driver
|
||||
s_adc_digi_ctx->use_adc2 = 1;
|
||||
|
||||
if (s_adc_digi_ctx->adc2_atten == atten_uninitialized) {
|
||||
s_adc_digi_ctx->adc2_atten = pat->atten;
|
||||
} else if (s_adc_digi_ctx->adc2_atten != pat->atten) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif //#if CONFIG_IDF_TARGET_ESP32C3
|
@ -78,6 +78,7 @@ extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate posi
|
||||
#define FSM_ENTER() RTC_ENTER_CRITICAL()
|
||||
#define FSM_EXIT() RTC_EXIT_CRITICAL()
|
||||
|
||||
//TODO: IDF-3610
|
||||
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
//prevent ADC1 being used by I2S dma and other tasks at the same time.
|
||||
static _lock_t adc1_dma_lock;
|
||||
@ -85,6 +86,7 @@ static _lock_t adc1_dma_lock;
|
||||
#define SARADC1_RELEASE() _lock_release( &adc1_dma_lock )
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
In ADC2, there're two locks used for different cases:
|
||||
1. lock shared with app and Wi-Fi:
|
||||
@ -218,65 +220,23 @@ esp_err_t adc2_pad_get_io_num(adc2_channel_t channel, gpio_num_t *gpio_num)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------RTC Single Read----------------------------------------------//
|
||||
#if SOC_ADC_RTC_CTRL_SUPPORTED
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
ADC Calibration
|
||||
---------------------------------------------------------------*/
|
||||
#if CONFIG_IDF_TARGET_ESP32S3
|
||||
/**
|
||||
* Temporarily put this function here. These are about ADC calibration and will be moved driver/adc.c in !14278.
|
||||
* Reason for putting calibration functions in driver/adc.c:
|
||||
* adc_common.c is far too confusing. Before a refactor is applied to adc_common.c, will put definite code in driver/adc.c
|
||||
*/
|
||||
|
||||
static uint16_t s_adc_cali_param[SOC_ADC_PERIPH_NUM][ADC_ATTEN_MAX] = {};
|
||||
|
||||
uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten)
|
||||
{
|
||||
if (s_adc_cali_param[adc_n][atten]) {
|
||||
//These value won't exceed UINT16_MAX
|
||||
return s_adc_cali_param[adc_n][atten];
|
||||
}
|
||||
|
||||
//Get the calibration version
|
||||
int version = esp_efuse_rtc_calib_get_ver();
|
||||
|
||||
uint32_t init_code = 0;
|
||||
if (version == 1) {
|
||||
init_code = esp_efuse_rtc_calib_get_init_code(version, adc_n, atten);
|
||||
} else {
|
||||
ESP_LOGV(ADC_TAG, "Calibration eFuse is not configured, use self-calibration for ICode");
|
||||
adc_power_acquire();
|
||||
RTC_ENTER_CRITICAL();
|
||||
const bool internal_gnd = true;
|
||||
init_code = adc_hal_self_calibration(adc_n, channel, atten, internal_gnd);
|
||||
RTC_EXIT_CRITICAL();
|
||||
adc_power_release();
|
||||
}
|
||||
s_adc_cali_param[adc_n][atten] = init_code;
|
||||
return s_adc_cali_param[adc_n][atten];
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
//Temporarily extern this from s2/adc.c. Will be modified in !14278.
|
||||
extern uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten);
|
||||
#endif //CONFIG_IDF_TARGET_ESP32S3
|
||||
|
||||
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
static uint32_t get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t chan)
|
||||
{
|
||||
adc_atten_t atten = adc_hal_get_atten(adc_n, chan);
|
||||
adc_atten_t atten = adc_ll_get_atten(adc_n, chan);
|
||||
extern uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten);
|
||||
|
||||
return adc_get_calibration_offset(adc_n, chan, atten);
|
||||
}
|
||||
#endif //#if SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
#endif //SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
|
||||
esp_err_t adc_set_clk_div(uint8_t clk_div)
|
||||
{
|
||||
DIGI_CONTROLLER_ENTER();
|
||||
adc_hal_digi_set_clk_div(clk_div);
|
||||
adc_ll_digi_set_clk_div(clk_div);
|
||||
DIGI_CONTROLLER_EXIT();
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -290,20 +250,25 @@ static void adc_rtc_chan_init(adc_unit_t adc_unit)
|
||||
dac_hal_rtc_sync_by_adc(false);
|
||||
#endif
|
||||
adc_hal_rtc_output_invert(ADC_NUM_1, SOC_ADC1_DATA_INVERT_DEFAULT);
|
||||
adc_hal_set_sar_clk_div(ADC_NUM_1, SOC_ADC_SAR_CLK_DIV_DEFAULT(ADC_NUM_1));
|
||||
adc_ll_set_sar_clk_div(ADC_NUM_1, SOC_ADC_SAR_CLK_DIV_DEFAULT(ADC_NUM_1));
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
adc_hal_hall_disable(); //Disable other peripherals.
|
||||
adc_hal_amp_disable(); //Currently the LNA is not open, close it by default.
|
||||
adc_ll_hall_disable(); //Disable other peripherals.
|
||||
adc_ll_amp_disable(); //Currently the LNA is not open, close it by default.
|
||||
#endif
|
||||
}
|
||||
if (adc_unit & ADC_UNIT_2) {
|
||||
adc_hal_pwdet_set_cct(SOC_ADC_PWDET_CCT_DEFAULT);
|
||||
adc_hal_rtc_output_invert(ADC_NUM_2, SOC_ADC2_DATA_INVERT_DEFAULT);
|
||||
adc_hal_set_sar_clk_div(ADC_NUM_2, SOC_ADC_SAR_CLK_DIV_DEFAULT(ADC_NUM_2));
|
||||
adc_ll_set_sar_clk_div(ADC_NUM_2, SOC_ADC_SAR_CLK_DIV_DEFAULT(ADC_NUM_2));
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t adc_gpio_init(adc_unit_t adc_unit, adc_channel_t channel)
|
||||
/**
|
||||
* This function is NOT an API.
|
||||
* Now some to-be-deprecated APIs are using this function, so don't make it static for now.
|
||||
* Will make this static on v5.0
|
||||
*/
|
||||
esp_err_t adc_common_gpio_init(adc_unit_t adc_unit, adc_channel_t channel)
|
||||
{
|
||||
gpio_num_t gpio_num = 0;
|
||||
//If called with `ADC_UNIT_BOTH (ADC_UNIT_1 | ADC_UNIT_2)`, both if blocks will be run
|
||||
@ -343,22 +308,22 @@ esp_err_t adc_set_data_inv(adc_unit_t adc_unit, bool inv_en)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_set_data_width(adc_unit_t adc_unit, adc_bits_width_t bits)
|
||||
esp_err_t adc_set_data_width(adc_unit_t adc_unit, adc_bits_width_t width_bit)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
ADC_CHECK(bits < ADC_WIDTH_MAX, "WIDTH ERR: ESP32 support 9 ~ 12 bit width", ESP_ERR_INVALID_ARG);
|
||||
ADC_CHECK(width_bit < ADC_WIDTH_MAX, "WIDTH ERR: ESP32 support 9 ~ 12 bit width", ESP_ERR_INVALID_ARG);
|
||||
#else
|
||||
ADC_CHECK(bits == ADC_WIDTH_MAX - 1, "WIDTH ERR: see `adc_bits_width_t` for supported bit width", ESP_ERR_INVALID_ARG);
|
||||
ADC_CHECK(width_bit == ADC_WIDTH_MAX - 1, "WIDTH ERR: see `adc_bits_width_t` for supported bit width", ESP_ERR_INVALID_ARG);
|
||||
#endif
|
||||
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
SARADC1_ENTER();
|
||||
adc_hal_rtc_set_output_format(ADC_NUM_1, bits);
|
||||
adc_hal_rtc_set_output_format(ADC_NUM_1, width_bit);
|
||||
SARADC1_EXIT();
|
||||
}
|
||||
if (adc_unit & ADC_UNIT_2) {
|
||||
SARADC2_ENTER();
|
||||
adc_hal_rtc_set_output_format(ADC_NUM_2, bits);
|
||||
adc_hal_rtc_set_output_format(ADC_NUM_2, width_bit);
|
||||
SARADC2_EXIT();
|
||||
}
|
||||
|
||||
@ -389,7 +354,7 @@ esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten)
|
||||
ADC_CHANNEL_CHECK(ADC_NUM_1, channel);
|
||||
ADC_CHECK(atten < ADC_ATTEN_MAX, "ADC Atten Err", ESP_ERR_INVALID_ARG);
|
||||
|
||||
adc_gpio_init(ADC_UNIT_1, channel);
|
||||
adc_common_gpio_init(ADC_UNIT_1, channel);
|
||||
SARADC1_ENTER();
|
||||
adc_rtc_chan_init(ADC_UNIT_1);
|
||||
adc_hal_set_atten(ADC_NUM_1, channel, atten);
|
||||
@ -428,11 +393,7 @@ esp_err_t adc1_dma_mode_acquire(void)
|
||||
|
||||
SARADC1_ENTER();
|
||||
/* switch SARADC into DIG channel */
|
||||
#if CONFIG_IDF_TARGET_ESP32S3 // remove this macro. TODO: IDF-1776
|
||||
adc_hal_set_controller(ADC_NUM_1, ADC_LL_CTRL_DIG);
|
||||
#else
|
||||
adc_hal_set_controller(ADC_NUM_1, ADC_CTRL_DIG);
|
||||
#endif
|
||||
adc_ll_set_controller(ADC_NUM_1, ADC_LL_CTRL_DIG);
|
||||
SARADC1_EXIT();
|
||||
|
||||
return ESP_OK;
|
||||
@ -447,11 +408,7 @@ esp_err_t adc1_rtc_mode_acquire(void)
|
||||
|
||||
SARADC1_ENTER();
|
||||
/* switch SARADC into RTC channel. */
|
||||
#if CONFIG_IDF_TARGET_ESP32S3 // remove this macro. TODO: IDF-1776
|
||||
adc_hal_set_controller(ADC_NUM_1, ADC_LL_CTRL_RTC);
|
||||
#else
|
||||
adc_hal_set_controller(ADC_NUM_1, ADC_CTRL_RTC);
|
||||
#endif
|
||||
adc_ll_set_controller(ADC_NUM_1, ADC_LL_CTRL_RTC);
|
||||
SARADC1_EXIT();
|
||||
|
||||
return ESP_OK;
|
||||
@ -481,14 +438,10 @@ int adc1_get_raw(adc1_channel_t channel)
|
||||
|
||||
SARADC1_ENTER();
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
adc_hal_hall_disable(); //Disable other peripherals.
|
||||
adc_hal_amp_disable(); //Currently the LNA is not open, close it by default.
|
||||
#endif
|
||||
#if CONFIG_IDF_TARGET_ESP32S3 // remove this macro. TODO: IDF-1776
|
||||
adc_hal_set_controller(ADC_NUM_1, ADC_LL_CTRL_RTC); //Set controller
|
||||
#else
|
||||
adc_hal_set_controller(ADC_NUM_1, ADC_CTRL_RTC); //Set controller
|
||||
adc_ll_hall_disable(); //Disable other peripherals.
|
||||
adc_ll_amp_disable(); //Currently the LNA is not open, close it by default.
|
||||
#endif
|
||||
adc_ll_set_controller(ADC_NUM_1, ADC_LL_CTRL_RTC); //Set controller
|
||||
adc_hal_convert(ADC_NUM_1, channel, &adc_value); //Start conversion, For ADC1, the data always valid.
|
||||
#if !CONFIG_IDF_TARGET_ESP32
|
||||
adc_ll_rtc_reset(); //Reset FSM of rtc controller
|
||||
@ -510,17 +463,13 @@ void adc1_ulp_enable(void)
|
||||
adc_power_acquire();
|
||||
|
||||
SARADC1_ENTER();
|
||||
#if CONFIG_IDF_TARGET_ESP32S3 // remove this macro. TODO: IDF-1776
|
||||
adc_hal_set_controller(ADC_NUM_1, ADC_LL_CTRL_ULP);
|
||||
#else
|
||||
adc_hal_set_controller(ADC_NUM_1, ADC_CTRL_ULP); //Set controller
|
||||
#endif
|
||||
adc_ll_set_controller(ADC_NUM_1, ADC_LL_CTRL_ULP);
|
||||
/* since most users do not need LNA and HALL with uLP, we disable them here
|
||||
open them in the uLP if needed. */
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
/* disable other peripherals. */
|
||||
adc_hal_hall_disable();
|
||||
adc_hal_amp_disable();
|
||||
adc_ll_hall_disable();
|
||||
adc_ll_amp_disable();
|
||||
#endif
|
||||
SARADC1_EXIT();
|
||||
}
|
||||
@ -552,7 +501,7 @@ esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten)
|
||||
ADC_CHANNEL_CHECK(ADC_NUM_2, channel);
|
||||
ADC_CHECK(atten <= ADC_ATTEN_11db, "ADC2 Atten Err", ESP_ERR_INVALID_ARG);
|
||||
|
||||
adc_gpio_init(ADC_UNIT_2, channel);
|
||||
adc_common_gpio_init(ADC_UNIT_2, channel);
|
||||
|
||||
if ( SARADC2_TRY_ACQUIRE() == -1 ) {
|
||||
//try the lock, return if failed (wifi using).
|
||||
@ -649,10 +598,11 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *
|
||||
adc2_dac_disable(channel); //disable other peripherals
|
||||
#endif
|
||||
adc_hal_rtc_set_output_format(ADC_NUM_2, width_bit);
|
||||
#if CONFIG_IDF_TARGET_ESP32S3 // remove this macro. TODO: IDF-1776
|
||||
adc_hal_set_controller(ADC_NUM_2, ADC_LL_CTRL_ARB);// set controller
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
adc_ll_set_controller(ADC_NUM_2, ADC_LL_CTRL_RTC);// set controller
|
||||
#else
|
||||
adc_hal_set_controller(ADC_NUM_2, ADC_CTRL_RTC);
|
||||
adc_ll_set_controller(ADC_NUM_2, ADC_LL_CTRL_ARB);// set controller
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
@ -721,7 +671,7 @@ esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio)
|
||||
}
|
||||
|
||||
//Configure RTC gpio, Only ADC2's channels IO are supported to output reference voltage.
|
||||
adc_gpio_init(ADC_UNIT_2, ch);
|
||||
adc_common_gpio_init(ADC_UNIT_2, ch);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
626
components/driver/adc_deprecated.c
Normal file
626
components/driver/adc_deprecated.c
Normal file
@ -0,0 +1,626 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------------
|
||||
This file contains ESP32 and ESP32S2 Depricated ADC APIs and functions
|
||||
-----------------------------------------------------------------------------------*/
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_types.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "driver/rtc_io.h"
|
||||
#include "hal/adc_ll.h"
|
||||
#include "hal/adc_types.h"
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
#include "esp_pm.h"
|
||||
#endif
|
||||
#include "adc.h"
|
||||
#include "esp_private/adc_cali.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#include "deprecated/driver/adc_types_deprecated.h"
|
||||
|
||||
static const char *ADC_TAG = "ADC";
|
||||
|
||||
#define ADC_CHECK_RET(fun_ret) ({ \
|
||||
if (fun_ret != ESP_OK) { \
|
||||
ESP_LOGE(ADC_TAG,"%s:%d\n",__FUNCTION__,__LINE__); \
|
||||
return ESP_FAIL; \
|
||||
} \
|
||||
})
|
||||
|
||||
#define ADC_CHECK(a, str, ret_val) ({ \
|
||||
if (!(a)) { \
|
||||
ESP_LOGE(ADC_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \
|
||||
return (ret_val); \
|
||||
} \
|
||||
})
|
||||
|
||||
#define ADC_CHANNEL_CHECK(periph, channel) ADC_CHECK(channel < SOC_ADC_CHANNEL_NUM(periph), "ADC"#periph" channel error", ESP_ERR_INVALID_ARG)
|
||||
#define ADC_GET_IO_NUM(periph, channel) (adc_channel_io_map[periph][channel])
|
||||
|
||||
extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished.
|
||||
#define ADC_ENTER_CRITICAL() portENTER_CRITICAL(&rtc_spinlock)
|
||||
#define ADC_EXIT_CRITICAL() portEXIT_CRITICAL(&rtc_spinlock)
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
esp_pm_lock_handle_t adc_digi_arbiter_lock = NULL;
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/*---------------------------------------------------------------
|
||||
ESP32 Depricated ADC APIs and functions
|
||||
---------------------------------------------------------------*/
|
||||
#define ADC_MEAS_NUM_LIM_DEFAULT (1)
|
||||
#define ADC_MAX_MEAS_NUM_DEFAULT (255)
|
||||
#define DIG_ADC_OUTPUT_FORMAT_DEFUALT (ADC_DIGI_FORMAT_12BIT)
|
||||
#define DIG_ADC_ATTEN_DEFUALT (ADC_ATTEN_DB_11)
|
||||
#define DIG_ADC_BIT_WIDTH_DEFUALT (ADC_WIDTH_BIT_12)
|
||||
|
||||
esp_err_t adc_digi_init(void)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_init();
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_deinit(void)
|
||||
{
|
||||
adc_power_release();
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_digi_deinit(NULL);
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set adc output 16-bit-data format from digital controller.
|
||||
*
|
||||
* @param data_sel 1: [15] unit, [14:11] channel, [10:0] data, 11-bit-width at most. Only work under `ADC_LL_DIGI_CONV_BOTH_UNIT` or `ADC_LL_DIGI_CONV_ALTER_UNIT` mode.
|
||||
* 0: [15:12] channel, [11:0] data, 12-bit-width at most. Only work under `ADC_LL_DIGI_CONV_ONLY_ADC1` or `ADC_LL_DIGI_CONV_ONLY_ADC2` mode
|
||||
* @note see `adc_ll_digi_pattern_table_t` for more detail of data bit width
|
||||
*/
|
||||
static inline void adc_ll_digi_set_output_format(bool data_sel)
|
||||
{
|
||||
SYSCON.saradc_ctrl.data_sar_sel = data_sel;
|
||||
}
|
||||
|
||||
static inline void adc_ll_digi_prepare_pattern_table(adc_ll_num_t adc_n, uint32_t pattern_index, adc_digi_pattern_table_t pattern)
|
||||
{
|
||||
uint32_t tab;
|
||||
uint8_t index = pattern_index / 4;
|
||||
uint8_t offset = (pattern_index % 4) * 8;
|
||||
if (adc_n == ADC_NUM_1) {
|
||||
tab = SYSCON.saradc_sar1_patt_tab[index]; // Read old register value
|
||||
tab &= (~(0xFF000000 >> offset)); // clear old data
|
||||
tab |= ((uint32_t)pattern.val << 24) >> offset; // Fill in the new data
|
||||
SYSCON.saradc_sar1_patt_tab[index] = tab; // Write back
|
||||
} else { // adc_n == ADC_NUM_2
|
||||
tab = SYSCON.saradc_sar2_patt_tab[index]; // Read old register value
|
||||
tab &= (~(0xFF000000 >> offset)); // clear old data
|
||||
tab |= ((uint32_t)pattern.val << 24) >> offset; // Fill in the new data
|
||||
SYSCON.saradc_sar2_patt_tab[index] = tab; // Write back
|
||||
}
|
||||
}
|
||||
|
||||
void adc_digi_controller_reg_set(const adc_digi_config_t *cfg)
|
||||
{
|
||||
/* On ESP32, only support ADC1 */
|
||||
switch (cfg->conv_mode) {
|
||||
case ADC_CONV_SINGLE_UNIT_1:
|
||||
adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_ONLY_ADC1);
|
||||
break;
|
||||
case ADC_CONV_SINGLE_UNIT_2:
|
||||
adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_ONLY_ADC2);
|
||||
break;
|
||||
case ADC_CONV_BOTH_UNIT:
|
||||
adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_BOTH_UNIT);
|
||||
break;
|
||||
case ADC_CONV_ALTER_UNIT:
|
||||
adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_ALTER_UNIT);
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_1) {
|
||||
adc_ll_set_controller(ADC_NUM_1, ADC_LL_CTRL_DIG);
|
||||
if (cfg->adc1_pattern_len) {
|
||||
adc_ll_digi_clear_pattern_table(ADC_NUM_1);
|
||||
adc_ll_digi_set_pattern_table_len(ADC_NUM_1, cfg->adc1_pattern_len);
|
||||
for (uint32_t i = 0; i < cfg->adc1_pattern_len; i++) {
|
||||
adc_ll_digi_prepare_pattern_table(ADC_NUM_1, i, cfg->adc1_pattern[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_2) {
|
||||
adc_ll_set_controller(ADC_NUM_2, ADC_LL_CTRL_DIG);
|
||||
if (cfg->adc2_pattern_len) {
|
||||
adc_ll_digi_clear_pattern_table(ADC_NUM_2);
|
||||
adc_ll_digi_set_pattern_table_len(ADC_NUM_2, cfg->adc2_pattern_len);
|
||||
for (uint32_t i = 0; i < cfg->adc2_pattern_len; i++) {
|
||||
adc_ll_digi_prepare_pattern_table(ADC_NUM_2, i, cfg->adc2_pattern[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
adc_ll_digi_set_output_format(cfg->format);
|
||||
if (cfg->conv_limit_en) {
|
||||
adc_ll_digi_set_convert_limit_num(cfg->conv_limit_num);
|
||||
adc_ll_digi_convert_limit_enable();
|
||||
} else {
|
||||
adc_ll_digi_convert_limit_disable();
|
||||
}
|
||||
adc_ll_digi_set_data_source(ADC_I2S_DATA_SRC_ADC);
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_controller_config(const adc_digi_config_t *config)
|
||||
{
|
||||
adc_power_acquire();
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_digi_controller_reg_set(config);
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_set_i2s_data_source(adc_i2s_source_t src)
|
||||
{
|
||||
ADC_CHECK(src < ADC_I2S_DATA_SRC_MAX, "ADC i2s data source error", ESP_ERR_INVALID_ARG);
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_ll_digi_set_data_source(src);
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
extern esp_err_t adc_common_gpio_init(adc_unit_t adc_unit, adc_channel_t channel);
|
||||
esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel)
|
||||
{
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
ADC_CHECK((SOC_ADC_SUPPORT_DMA_MODE(ADC_NUM_1)), "ADC1 not support DMA for now.", ESP_ERR_INVALID_ARG);
|
||||
ADC_CHANNEL_CHECK(ADC_NUM_1, channel);
|
||||
}
|
||||
if (adc_unit & ADC_UNIT_2) {
|
||||
ADC_CHECK((SOC_ADC_SUPPORT_DMA_MODE(ADC_NUM_2)), "ADC2 not support DMA for now.", ESP_ERR_INVALID_ARG);
|
||||
ADC_CHANNEL_CHECK(ADC_NUM_2, channel);
|
||||
}
|
||||
|
||||
adc_digi_pattern_table_t adc1_pattern[1];
|
||||
adc_digi_pattern_table_t adc2_pattern[1];
|
||||
adc_digi_config_t dig_cfg = {
|
||||
.conv_limit_en = ADC_MEAS_NUM_LIM_DEFAULT,
|
||||
.conv_limit_num = ADC_MAX_MEAS_NUM_DEFAULT,
|
||||
.format = DIG_ADC_OUTPUT_FORMAT_DEFUALT,
|
||||
.conv_mode = (adc_digi_convert_mode_t)adc_unit,
|
||||
};
|
||||
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
adc1_pattern[0].atten = DIG_ADC_ATTEN_DEFUALT;
|
||||
adc1_pattern[0].bit_width = DIG_ADC_BIT_WIDTH_DEFUALT;
|
||||
adc1_pattern[0].channel = channel;
|
||||
dig_cfg.adc1_pattern_len = 1;
|
||||
dig_cfg.adc1_pattern = adc1_pattern;
|
||||
}
|
||||
if (adc_unit & ADC_UNIT_2) {
|
||||
adc2_pattern[0].atten = DIG_ADC_ATTEN_DEFUALT;
|
||||
adc2_pattern[0].bit_width = DIG_ADC_BIT_WIDTH_DEFUALT;
|
||||
adc2_pattern[0].channel = channel;
|
||||
dig_cfg.adc2_pattern_len = 1;
|
||||
dig_cfg.adc2_pattern = adc2_pattern;
|
||||
}
|
||||
adc_common_gpio_init(adc_unit, channel);
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_init();
|
||||
adc_digi_controller_reg_set(&dig_cfg);
|
||||
ADC_EXIT_CRITICAL();
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#endif //#if CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
/*---------------------------------------------------------------
|
||||
ESP32S2 Depricated ADC functions and APIs
|
||||
---------------------------------------------------------------*/
|
||||
esp_err_t adc_arbiter_config(adc_unit_t adc_unit, adc_arbiter_t *config)
|
||||
{
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_arbiter_config(config);
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable interrupt of adc digital controller by bitmask.
|
||||
*
|
||||
* @param adc_n ADC unit.
|
||||
* @param intr Interrupt bitmask.
|
||||
*/
|
||||
static inline void adc_ll_digi_intr_enable(adc_ll_num_t adc_n, adc_digi_intr_t intr)
|
||||
{
|
||||
if (adc_n == ADC_NUM_1) {
|
||||
if (intr & ADC_DIGI_INTR_MASK_MONITOR) {
|
||||
APB_SARADC.int_ena.adc1_thres = 1;
|
||||
}
|
||||
if (intr & ADC_DIGI_INTR_MASK_MEAS_DONE) {
|
||||
APB_SARADC.int_ena.adc1_done = 1;
|
||||
}
|
||||
} else { // adc_n == ADC_NUM_2
|
||||
if (intr & ADC_DIGI_INTR_MASK_MONITOR) {
|
||||
APB_SARADC.int_ena.adc2_thres = 1;
|
||||
}
|
||||
if (intr & ADC_DIGI_INTR_MASK_MEAS_DONE) {
|
||||
APB_SARADC.int_ena.adc2_done = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_intr_enable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
adc_ll_digi_intr_enable(ADC_NUM_1, intr_mask);
|
||||
}
|
||||
if (adc_unit & ADC_UNIT_2) {
|
||||
adc_ll_digi_intr_enable(ADC_NUM_2, intr_mask);
|
||||
}
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable interrupt of adc digital controller by bitmask.
|
||||
*
|
||||
* @param adc_n ADC unit.
|
||||
* @param intr Interrupt bitmask.
|
||||
*/
|
||||
static inline void adc_ll_digi_intr_disable(adc_ll_num_t adc_n, adc_digi_intr_t intr)
|
||||
{
|
||||
if (adc_n == ADC_NUM_1) {
|
||||
if (intr & ADC_DIGI_INTR_MASK_MONITOR) {
|
||||
APB_SARADC.int_ena.adc1_thres = 0;
|
||||
}
|
||||
if (intr & ADC_DIGI_INTR_MASK_MEAS_DONE) {
|
||||
APB_SARADC.int_ena.adc1_done = 0;
|
||||
}
|
||||
} else { // adc_n == ADC_NUM_2
|
||||
if (intr & ADC_DIGI_INTR_MASK_MONITOR) {
|
||||
APB_SARADC.int_ena.adc2_thres = 0;
|
||||
}
|
||||
if (intr & ADC_DIGI_INTR_MASK_MEAS_DONE) {
|
||||
APB_SARADC.int_ena.adc2_done = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_intr_disable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
adc_ll_digi_intr_disable(ADC_NUM_1, intr_mask);
|
||||
}
|
||||
if (adc_unit & ADC_UNIT_2) {
|
||||
adc_ll_digi_intr_disable(ADC_NUM_2, intr_mask);
|
||||
}
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear interrupt of adc digital controller by bitmask.
|
||||
*
|
||||
* @param adc_n ADC unit.
|
||||
* @param intr Interrupt bitmask.
|
||||
*/
|
||||
static inline void adc_ll_digi_intr_clear(adc_ll_num_t adc_n, adc_digi_intr_t intr)
|
||||
{
|
||||
if (adc_n == ADC_NUM_1) {
|
||||
if (intr & ADC_DIGI_INTR_MASK_MONITOR) {
|
||||
APB_SARADC.int_clr.adc1_thres = 1;
|
||||
}
|
||||
if (intr & ADC_DIGI_INTR_MASK_MEAS_DONE) {
|
||||
APB_SARADC.int_clr.adc1_done = 1;
|
||||
}
|
||||
} else { // adc_n == ADC_NUM_2
|
||||
if (intr & ADC_DIGI_INTR_MASK_MONITOR) {
|
||||
APB_SARADC.int_clr.adc2_thres = 1;
|
||||
}
|
||||
if (intr & ADC_DIGI_INTR_MASK_MEAS_DONE) {
|
||||
APB_SARADC.int_clr.adc2_done = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_intr_clear(adc_unit_t adc_unit, adc_digi_intr_t intr_mask)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
adc_ll_digi_intr_clear(ADC_NUM_1, intr_mask);
|
||||
}
|
||||
if (adc_unit & ADC_UNIT_2) {
|
||||
adc_ll_digi_intr_clear(ADC_NUM_2, intr_mask);
|
||||
}
|
||||
ADC_EXIT_CRITICAL();
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get interrupt status mask of adc digital controller.
|
||||
*
|
||||
* @param adc_n ADC unit.
|
||||
* @return
|
||||
* - intr Interrupt bitmask.
|
||||
*/
|
||||
static inline uint32_t adc_ll_digi_get_intr_status(adc_ll_num_t adc_n)
|
||||
{
|
||||
uint32_t int_st = APB_SARADC.int_st.val;
|
||||
uint32_t ret_msk = 0;
|
||||
|
||||
if (adc_n == ADC_NUM_1) {
|
||||
if (int_st & APB_SARADC_ADC1_DONE_INT_ST_M) {
|
||||
ret_msk |= ADC_DIGI_INTR_MASK_MEAS_DONE;
|
||||
}
|
||||
if (int_st & APB_SARADC_ADC1_THRES_INT_ST) {
|
||||
ret_msk |= ADC_DIGI_INTR_MASK_MONITOR;
|
||||
}
|
||||
} else { // adc_n == ADC_NUM_2
|
||||
if (int_st & APB_SARADC_ADC2_DONE_INT_ST_M) {
|
||||
ret_msk |= ADC_DIGI_INTR_MASK_MEAS_DONE;
|
||||
}
|
||||
if (int_st & APB_SARADC_ADC2_THRES_INT_ST_M) {
|
||||
ret_msk |= ADC_DIGI_INTR_MASK_MONITOR;
|
||||
}
|
||||
}
|
||||
|
||||
return ret_msk;
|
||||
}
|
||||
|
||||
uint32_t adc_digi_intr_get_status(adc_unit_t adc_unit)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
ADC_ENTER_CRITICAL();
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
ret = adc_ll_digi_get_intr_status(ADC_NUM_1);
|
||||
}
|
||||
if (adc_unit & ADC_UNIT_2) {
|
||||
ret = adc_ll_digi_get_intr_status(ADC_NUM_2);
|
||||
}
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint8_t s_isr_registered = 0;
|
||||
static intr_handle_t s_adc_isr_handle = NULL;
|
||||
|
||||
esp_err_t adc_digi_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags)
|
||||
{
|
||||
ADC_CHECK((fn != NULL), "Parameter error", ESP_ERR_INVALID_ARG);
|
||||
ADC_CHECK(s_isr_registered == 0, "ADC ISR have installed, can not install again", ESP_FAIL);
|
||||
|
||||
esp_err_t ret = esp_intr_alloc(ETS_APB_ADC_INTR_SOURCE, intr_alloc_flags, fn, arg, &s_adc_isr_handle);
|
||||
if (ret == ESP_OK) {
|
||||
s_isr_registered = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_isr_deregister(void)
|
||||
{
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
if (s_isr_registered) {
|
||||
ret = esp_intr_free(s_adc_isr_handle);
|
||||
if (ret == ESP_OK) {
|
||||
s_isr_registered = 0;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_init(void)
|
||||
{
|
||||
adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT();
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_init();
|
||||
adc_hal_arbiter_config(&config);
|
||||
ADC_EXIT_CRITICAL();
|
||||
|
||||
adc_hal_calibration_init(ADC_NUM_1);
|
||||
adc_hal_calibration_init(ADC_NUM_2);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_deinit(void)
|
||||
{
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
if (adc_digi_arbiter_lock) {
|
||||
esp_pm_lock_delete(adc_digi_arbiter_lock);
|
||||
adc_digi_arbiter_lock = NULL;
|
||||
}
|
||||
#endif
|
||||
adc_power_release();
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_digi_deinit(NULL);
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset FSM of adc digital controller.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_reset(void)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_ll_digi_reset();
|
||||
adc_ll_digi_clear_pattern_table(ADC_NUM_1);
|
||||
adc_ll_digi_clear_pattern_table(ADC_NUM_2);
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set adc output data format for digital controller.
|
||||
*
|
||||
* @param format Output data format.
|
||||
*/
|
||||
static inline void adc_ll_digi_set_output_format(adc_digi_output_format_t format)
|
||||
{
|
||||
APB_SARADC.ctrl.data_sar_sel = format;
|
||||
}
|
||||
|
||||
static inline void adc_ll_digi_prepare_pattern_table(adc_ll_num_t adc_n, uint32_t pattern_index, adc_digi_pattern_table_t pattern)
|
||||
{
|
||||
uint32_t tab;
|
||||
uint8_t index = pattern_index / 4;
|
||||
uint8_t offset = (pattern_index % 4) * 8;
|
||||
if (adc_n == ADC_NUM_1) {
|
||||
tab = APB_SARADC.sar1_patt_tab[index]; // Read old register value
|
||||
tab &= (~(0xFF000000 >> offset)); // clear old data
|
||||
tab |= ((uint32_t)pattern.val << 24) >> offset; // Fill in the new data
|
||||
APB_SARADC.sar1_patt_tab[index] = tab; // Write back
|
||||
} else { // adc_n == ADC_NUM_2
|
||||
tab = APB_SARADC.sar2_patt_tab[index]; // Read old register value
|
||||
tab &= (~(0xFF000000 >> offset)); // clear old data
|
||||
tab |= ((uint32_t)pattern.val << 24) >> offset; // Fill in the new data
|
||||
APB_SARADC.sar2_patt_tab[index] = tab; // Write back
|
||||
}
|
||||
}
|
||||
|
||||
static void adc_digi_controller_reg_set(const adc_digi_config_t *cfg)
|
||||
{
|
||||
/* Single channel mode or multi channel mode. */
|
||||
switch (cfg->conv_mode) {
|
||||
case ADC_CONV_SINGLE_UNIT_1:
|
||||
adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_ONLY_ADC1);
|
||||
break;
|
||||
case ADC_CONV_SINGLE_UNIT_2:
|
||||
adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_ONLY_ADC2);
|
||||
break;
|
||||
case ADC_CONV_BOTH_UNIT:
|
||||
adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_BOTH_UNIT);
|
||||
break;
|
||||
case ADC_CONV_ALTER_UNIT:
|
||||
adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_ALTER_UNIT);
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_1) {
|
||||
if (cfg->adc1_pattern_len) {
|
||||
adc_ll_digi_clear_pattern_table(ADC_NUM_1);
|
||||
adc_ll_digi_set_pattern_table_len(ADC_NUM_1, cfg->adc1_pattern_len);
|
||||
for (uint32_t i = 0; i < cfg->adc1_pattern_len; i++) {
|
||||
adc_ll_digi_prepare_pattern_table(ADC_NUM_1, i, cfg->adc1_pattern[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_2) {
|
||||
if (cfg->adc2_pattern_len) {
|
||||
adc_ll_digi_clear_pattern_table(ADC_NUM_2);
|
||||
adc_ll_digi_set_pattern_table_len(ADC_NUM_2, cfg->adc2_pattern_len);
|
||||
for (uint32_t i = 0; i < cfg->adc2_pattern_len; i++) {
|
||||
adc_ll_digi_prepare_pattern_table(ADC_NUM_2, i, cfg->adc2_pattern[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_1) {
|
||||
adc_ll_set_controller(ADC_NUM_1, ADC_LL_CTRL_DIG);
|
||||
}
|
||||
if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_2) {
|
||||
adc_ll_set_controller(ADC_NUM_2, ADC_LL_CTRL_ARB);
|
||||
}
|
||||
adc_ll_digi_set_output_format(cfg->format);
|
||||
if (cfg->conv_limit_en) {
|
||||
adc_ll_digi_set_convert_limit_num(cfg->conv_limit_num);
|
||||
adc_ll_digi_convert_limit_enable();
|
||||
} else {
|
||||
adc_ll_digi_convert_limit_disable();
|
||||
}
|
||||
|
||||
adc_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_dma_set_eof_num(cfg->dma_eof_num);
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_controller_config(const adc_digi_config_t *config)
|
||||
{
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
esp_err_t err;
|
||||
if (adc_digi_arbiter_lock == NULL) {
|
||||
if (config->dig_clk.use_apll) {
|
||||
err = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "adc_dma", &adc_digi_arbiter_lock);
|
||||
} else {
|
||||
err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "adc_dma", &adc_digi_arbiter_lock);
|
||||
}
|
||||
if (err != ESP_OK) {
|
||||
adc_digi_arbiter_lock = NULL;
|
||||
ESP_LOGE(ADC_TAG, "ADC-DMA pm lock error");
|
||||
return err;
|
||||
}
|
||||
}
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
|
||||
if (config->conv_mode & ADC_CONV_SINGLE_UNIT_1) {
|
||||
for (int i = 0; i < config->adc1_pattern_len; i++) {
|
||||
adc_cal_offset(ADC_NUM_1, config->adc1_pattern[i].channel, config->adc1_pattern[i].atten);
|
||||
}
|
||||
}
|
||||
if (config->conv_mode & ADC_CONV_SINGLE_UNIT_2) {
|
||||
for (int i = 0; i < config->adc2_pattern_len; i++) {
|
||||
adc_cal_offset(ADC_NUM_2, config->adc2_pattern[i].channel, config->adc2_pattern[i].atten);
|
||||
}
|
||||
}
|
||||
|
||||
/* If enable digtal controller, adc xpd should always on. */
|
||||
adc_power_acquire();
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_digi_controller_reg_set(config);
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif // #if CONFIG_IDF_TARGET_ESP32S2
|
||||
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
|
||||
/*---------------------------------------------------------------
|
||||
ESP32S2 Depricated ADC functions and APIs
|
||||
---------------------------------------------------------------*/
|
||||
esp_err_t adc_gpio_init(adc_unit_t adc_unit, adc_channel_t channel)
|
||||
{
|
||||
gpio_num_t gpio_num = 0;
|
||||
//If called with `ADC_UNIT_BOTH (ADC_UNIT_1 | ADC_UNIT_2)`, both if blocks will be run
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
ADC_CHANNEL_CHECK(ADC_NUM_1, channel);
|
||||
gpio_num = ADC_GET_IO_NUM(ADC_NUM_1, channel);
|
||||
ADC_CHECK_RET(rtc_gpio_init(gpio_num));
|
||||
ADC_CHECK_RET(rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_DISABLED));
|
||||
ADC_CHECK_RET(rtc_gpio_pulldown_dis(gpio_num));
|
||||
ADC_CHECK_RET(rtc_gpio_pullup_dis(gpio_num));
|
||||
}
|
||||
if (adc_unit & ADC_UNIT_2) {
|
||||
ADC_CHANNEL_CHECK(ADC_NUM_2, channel);
|
||||
gpio_num = ADC_GET_IO_NUM(ADC_NUM_2, channel);
|
||||
ADC_CHECK_RET(rtc_gpio_init(gpio_num));
|
||||
ADC_CHECK_RET(rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_DISABLED));
|
||||
ADC_CHECK_RET(rtc_gpio_pulldown_dis(gpio_num));
|
||||
ADC_CHECK_RET(rtc_gpio_pullup_dis(gpio_num));
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif //#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
|
163
components/driver/deprecated/driver/adc_deprecated.h
Normal file
163
components/driver/deprecated/driver/adc_deprecated.h
Normal file
@ -0,0 +1,163 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------------
|
||||
This file contains Deprecated ADC APIs
|
||||
-----------------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
#include "esp_err.h"
|
||||
#include "hal/adc_types.h"
|
||||
#include "driver/adc_types_deprecated.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
/*---------------------------------------------------------------
|
||||
ESP32S2 Deprecated ADC APIs
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Config ADC module arbiter.
|
||||
* The arbiter is to improve the use efficiency of ADC2. After the control right is robbed by the high priority,
|
||||
* the low priority controller will read the invalid ADC2 data, and the validity of the data can be judged by the flag bit in the data.
|
||||
*
|
||||
* @note Only ADC2 support arbiter.
|
||||
* @note Default priority: Wi-Fi > RTC > Digital;
|
||||
* @note In normal use, there is no need to call this interface to config arbiter.
|
||||
*
|
||||
* @param adc_unit ADC unit.
|
||||
* @param config Refer to `adc_arbiter_t`.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_NOT_SUPPORTED ADC unit not support arbiter.
|
||||
*/
|
||||
esp_err_t adc_arbiter_config(adc_unit_t adc_unit, adc_arbiter_t *config) __attribute__((deprecated));
|
||||
|
||||
/**
|
||||
* @brief Enable interrupt of adc digital controller by bitmask.
|
||||
*
|
||||
* @param adc_unit ADC unit.
|
||||
* @param intr_mask Interrupt bitmask. See ``adc_digi_intr_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_intr_enable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask) __attribute__((deprecated));
|
||||
|
||||
/**
|
||||
* @brief Disable interrupt of adc digital controller by bitmask.
|
||||
*
|
||||
* @param adc_unit ADC unit.
|
||||
* @param intr_mask Interrupt bitmask. See ``adc_digi_intr_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_intr_disable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask) __attribute__((deprecated));
|
||||
|
||||
/**
|
||||
* @brief Clear interrupt of adc digital controller by bitmask.
|
||||
*
|
||||
* @param adc_unit ADC unit.
|
||||
* @param intr_mask Interrupt bitmask. See ``adc_digi_intr_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_intr_clear(adc_unit_t adc_unit, adc_digi_intr_t intr_mask) __attribute__((deprecated));
|
||||
|
||||
/**
|
||||
* @brief Get interrupt status mask of adc digital controller.
|
||||
*
|
||||
* @param adc_unit ADC unit.
|
||||
* @return
|
||||
* - intr Interrupt bitmask, See ``adc_digi_intr_t``.
|
||||
*/
|
||||
uint32_t adc_digi_intr_get_status(adc_unit_t adc_unit) __attribute__((deprecated));
|
||||
|
||||
/**
|
||||
* @brief Register ADC interrupt handler, the handler is an ISR.
|
||||
* The handler will be attached to the same CPU core that this function is running on.
|
||||
*
|
||||
* @param fn Interrupt handler function.
|
||||
* @param arg Parameter for handler function
|
||||
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
|
||||
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_NOT_FOUND Can not find the interrupt that matches the flags.
|
||||
* - ESP_ERR_INVALID_ARG Function pointer error.
|
||||
*/
|
||||
esp_err_t adc_digi_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags) __attribute__((deprecated));
|
||||
|
||||
/**
|
||||
* @brief Deregister ADC interrupt handler, the handler is an ISR.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG hander error.
|
||||
* - ESP_FAIL ISR not be registered.
|
||||
*/
|
||||
esp_err_t adc_digi_isr_deregister(void) __attribute__((deprecated));
|
||||
#endif // #if CONFIG_IDF_TARGET_ESP32S2
|
||||
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
|
||||
/*---------------------------------------------------------------
|
||||
ESP32, ESP32S2 Deprecated ADC APIs
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief ADC digital controller initialization.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_init(void) __attribute__((deprecated));
|
||||
|
||||
/**
|
||||
* @brief ADC digital controller deinitialization.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_deinit(void) __attribute__((deprecated));
|
||||
#endif //#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
|
||||
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
|
||||
/*---------------------------------------------------------------
|
||||
ESP32, ESP32S2, ESP32C3 Deprecated ADC APIs
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Setting the digital controller.
|
||||
*
|
||||
* @param config Pointer to digital controller paramter. Refer to ``adc_digi_config_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_STATE Driver state is invalid.
|
||||
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
|
||||
* - ESP_OK On success
|
||||
*/
|
||||
esp_err_t adc_digi_controller_config(const adc_digi_config_t *config) __attribute__((deprecated));
|
||||
|
||||
/**
|
||||
* @brief Initialize ADC pad
|
||||
* @param adc_unit ADC unit index
|
||||
* @param channel ADC channel index
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t adc_gpio_init(adc_unit_t adc_unit, adc_channel_t channel) __attribute__((deprecated));;
|
||||
#endif //#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
203
components/driver/deprecated/driver/adc_types_deprecated.h
Normal file
203
components/driver/deprecated/driver/adc_types_deprecated.h
Normal file
@ -0,0 +1,203 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "esp_err.h"
|
||||
#include "hal/adc_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/*---------------------------------------------------------------
|
||||
ESP32 Deprecated Types
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief ADC digital controller (DMA mode) conversion rules setting.
|
||||
*/
|
||||
typedef struct {
|
||||
union {
|
||||
struct {
|
||||
uint8_t atten: 2; /*!< ADC sampling voltage attenuation configuration. Modification of attenuation affects the range of measurements.
|
||||
0: measurement range 0 - 800mV,
|
||||
1: measurement range 0 - 1100mV,
|
||||
2: measurement range 0 - 1350mV,
|
||||
3: measurement range 0 - 2600mV. */
|
||||
uint8_t bit_width: 2; /*!< ADC resolution.
|
||||
- 0: 9 bit;
|
||||
- 1: 10 bit;
|
||||
- 2: 11 bit;
|
||||
- 3: 12 bit. */
|
||||
int8_t channel: 4; /*!< ADC channel index. */
|
||||
};
|
||||
uint8_t val; /*!<Raw data value */
|
||||
};
|
||||
} adc_digi_pattern_table_t __attribute__((deprecated));
|
||||
|
||||
/**
|
||||
* Explanation of the relationship between `conv_limit_num`, `dma_eof_num` and the number of DMA outputs:
|
||||
*
|
||||
* +---------------------+--------+--------+--------+
|
||||
* | conv_mode | single | both | alter |
|
||||
* +---------------------+--------+--------+--------+
|
||||
* | trigger meas times | 1 | 1 | 1 |
|
||||
* +---------------------+--------+--------+--------+
|
||||
* | conv_limit_num | +1 | +1 | +1 |
|
||||
* | dma_eof_num | +1 | +2 | +1 |
|
||||
* | dma output (byte) | +2 | +4 | +2 |
|
||||
* +---------------------+--------+--------+--------+
|
||||
*/
|
||||
typedef struct {
|
||||
bool conv_limit_en; /*!<Enable the function of limiting ADC conversion times.
|
||||
If the number of ADC conversion trigger count is equal to the `limit_num`, the conversion is stopped. */
|
||||
uint32_t conv_limit_num; /*!<Set the upper limit of the number of ADC conversion triggers. Range: 1 ~ 255. */
|
||||
uint32_t adc1_pattern_len; /*!<Pattern table length for digital controller. Range: 0 ~ 16 (0: Don't change the pattern table setting).
|
||||
The pattern table that defines the conversion rules for each SAR ADC. Each table has 16 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 16 different rules before repeating itself. */
|
||||
uint32_t adc2_pattern_len; /*!<Refer to ``adc1_pattern_len`` */
|
||||
adc_digi_pattern_table_t *adc1_pattern; /*!<Pointer to pattern table for digital controller. The table size defined by `adc1_pattern_len`. */
|
||||
adc_digi_pattern_table_t *adc2_pattern; /*!<Refer to `adc1_pattern` */
|
||||
adc_digi_convert_mode_t conv_mode; /*!<ADC conversion mode for digital controller. See ``adc_digi_convert_mode_t``. */
|
||||
adc_digi_output_format_t format; /*!<ADC output data format for digital controller. See ``adc_digi_output_format_t``. */
|
||||
} adc_digi_config_t __attribute__((deprecated));
|
||||
#endif //#if CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
/*---------------------------------------------------------------
|
||||
ESP32S2 Deprecated Types
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief ADC digital controller (DMA mode) conversion rules setting.
|
||||
*/
|
||||
typedef struct {
|
||||
union {
|
||||
struct {
|
||||
uint8_t atten: 2; /*!< ADC sampling voltage attenuation configuration. Modification of attenuation affects the range of measurements.
|
||||
0: measurement range 0 - 800mV,
|
||||
1: measurement range 0 - 1100mV,
|
||||
2: measurement range 0 - 1350mV,
|
||||
3: measurement range 0 - 2600mV. */
|
||||
uint8_t reserved: 2; /*!< reserved0 */
|
||||
uint8_t channel: 4; /*!< ADC channel index. */
|
||||
};
|
||||
uint8_t val; /*!<Raw data value */
|
||||
};
|
||||
} adc_digi_pattern_table_t __attribute__((deprecated));
|
||||
|
||||
/**
|
||||
* @brief ADC digital controller (DMA mode) configuration parameters.
|
||||
*
|
||||
* Example setting: When using ADC1 channel0 to measure voltage, the sampling rate is required to be 1 kHz:
|
||||
*
|
||||
* +---------------------+--------+--------+--------+
|
||||
* | sample rate | 1 kHz | 1 kHz | 1 kHz |
|
||||
* +---------------------+--------+--------+--------+
|
||||
* | conv_mode | single | both | alter |
|
||||
* | adc1_pattern_len | 1 | 1 | 1 |
|
||||
* | dig_clk.use_apll | 0 | 0 | 0 |
|
||||
* | dig_clk.div_num | 99 | 99 | 99 |
|
||||
* | dig_clk.div_b | 0 | 0 | 0 |
|
||||
* | dig_clk.div_a | 0 | 0 | 0 |
|
||||
* | interval | 400 | 400 | 200 |
|
||||
* +---------------------+--------+--------+--------+
|
||||
* | `trigger_meas_freq` | 1 kHz | 1 kHz | 2 kHz |
|
||||
* +---------------------+--------+--------+--------+
|
||||
*
|
||||
* Explanation of the relationship between `conv_limit_num`, `dma_eof_num` and the number of DMA outputs:
|
||||
*
|
||||
* +---------------------+--------+--------+--------+
|
||||
* | conv_mode | single | both | alter |
|
||||
* +---------------------+--------+--------+--------+
|
||||
* | trigger meas times | 1 | 1 | 1 |
|
||||
* +---------------------+--------+--------+--------+
|
||||
* | conv_limit_num | +1 | +1 | +1 |
|
||||
* | dma_eof_num | +1 | +2 | +1 |
|
||||
* | dma output (byte) | +2 | +4 | +2 |
|
||||
* +---------------------+--------+--------+--------+
|
||||
*/
|
||||
typedef struct {
|
||||
bool conv_limit_en; /*!<Enable the function of limiting ADC conversion times.
|
||||
If the number of ADC conversion trigger count is equal to the `limit_num`, the conversion is stopped. */
|
||||
uint32_t conv_limit_num; /*!<Set the upper limit of the number of ADC conversion triggers. Range: 1 ~ 255. */
|
||||
uint32_t adc1_pattern_len; /*!<Pattern table length for digital controller. Range: 0 ~ 16 (0: Don't change the pattern table setting).
|
||||
The pattern table that defines the conversion rules for each SAR ADC. Each table has 16 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 16 different rules before repeating itself. */
|
||||
uint32_t adc2_pattern_len; /*!<Refer to ``adc1_pattern_len`` */
|
||||
adc_digi_pattern_table_t *adc1_pattern; /*!<Pointer to pattern table for digital controller. The table size defined by `adc1_pattern_len`. */
|
||||
adc_digi_pattern_table_t *adc2_pattern; /*!<Refer to `adc1_pattern` */
|
||||
adc_digi_convert_mode_t conv_mode; /*!<ADC conversion mode for digital controller. See ``adc_digi_convert_mode_t``. */
|
||||
adc_digi_output_format_t format; /*!<ADC output data format for digital controller. See ``adc_digi_output_format_t``. */
|
||||
uint32_t interval; /*!<The number of interval clock cycles for the digital controller to trigger the measurement.
|
||||
The unit is the divided clock. Range: 40 ~ 4095.
|
||||
Expression: `trigger_meas_freq` = `controller_clk` / 2 / interval. Refer to ``adc_digi_clk_t``.
|
||||
Note: The sampling rate of each channel is also related to the conversion mode (See ``adc_digi_convert_mode_t``) and pattern table settings. */
|
||||
adc_digi_clk_t dig_clk; /*!<ADC digital controller clock divider settings. Refer to ``adc_digi_clk_t``.
|
||||
Note: The clocks of the DAC digital controller use the ADC digital controller clock divider. */
|
||||
uint32_t dma_eof_num; /*!<DMA eof num of adc digital controller.
|
||||
If the number of measurements reaches `dma_eof_num`, then `dma_in_suc_eof` signal is generated in DMA.
|
||||
Note: The converted data in the DMA in link buffer will be multiple of two bytes. */
|
||||
} adc_digi_config_t __attribute__((deprecated));
|
||||
|
||||
/**
|
||||
* @brief ADC digital controller (DMA mode) interrupt type options.
|
||||
*/
|
||||
typedef enum {
|
||||
ADC_DIGI_INTR_MASK_MONITOR = 0x1,
|
||||
ADC_DIGI_INTR_MASK_MEAS_DONE = 0x2,
|
||||
ADC_DIGI_INTR_MASK_ALL = 0x3,
|
||||
} adc_digi_intr_t __attribute__((deprecated));
|
||||
FLAG_ATTR(adc_digi_intr_t)
|
||||
#endif //#if CONFIG_IDF_TARGET_ESP32S2
|
||||
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32C3
|
||||
/*---------------------------------------------------------------
|
||||
ESP32C3 Deprecated Types
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief ADC digital controller (DMA mode) conversion rules setting.
|
||||
*/
|
||||
typedef struct {
|
||||
union {
|
||||
struct {
|
||||
uint8_t atten: 2; /*!< ADC sampling voltage attenuation configuration. Modification of attenuation affects the range of measurements.
|
||||
0: measurement range 0 - 800mV,
|
||||
1: measurement range 0 - 1100mV,
|
||||
2: measurement range 0 - 1350mV,
|
||||
3: measurement range 0 - 2600mV. */
|
||||
uint8_t channel: 3; /*!< ADC channel index. */
|
||||
uint8_t unit: 1; /*!< ADC unit index. */
|
||||
uint8_t reserved: 2; /*!< reserved0 */
|
||||
};
|
||||
uint8_t val; /*!<Raw data value */
|
||||
};
|
||||
} adc_digi_pattern_table_t __attribute__((deprecated));
|
||||
|
||||
typedef struct {
|
||||
bool conv_limit_en; /*!<Enable the function of limiting ADC conversion times.
|
||||
If the number of ADC conversion trigger count is equal to the `limit_num`, the conversion is stopped. */
|
||||
uint32_t conv_limit_num; /*!<Set the upper limit of the number of ADC conversion triggers. Range: 1 ~ 255. */
|
||||
uint32_t adc_pattern_len; /*!<Pattern table length for digital controller. Range: 0 ~ 7 (0: Don't change the pattern table setting).
|
||||
The pattern table that defines the conversion rules for each SAR ADC. Each table has 7 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 16 different rules before repeating itself. */
|
||||
adc_digi_pattern_table_t *adc_pattern; /*!<Pointer to pattern table for digital controller. The table size defined by `adc_pattern_len`. */
|
||||
uint32_t sample_freq_hz; /*!< The expected ADC sampling frequency in Hz. Range: 611Hz ~ 83333Hz
|
||||
Fs = Fd / interval / 2
|
||||
Fs: sampling frequency;
|
||||
Fd: digital controller frequency, no larger than 5M for better performance
|
||||
interval: interval between 2 measurement trigger signal, the smallest interval should not be smaller than the ADC measurement period, the largest interval should not be larger than 4095 */
|
||||
} adc_digi_config_t __attribute__((deprecated));
|
||||
#endif //#if CONFIG_IDF_TARGET_ESP32C3
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -30,123 +30,14 @@
|
||||
#include "hal/adc_types.h"
|
||||
#include "hal/adc_hal.h"
|
||||
|
||||
#define ADC_MAX_MEAS_NUM_DEFAULT (255)
|
||||
#define ADC_MEAS_NUM_LIM_DEFAULT (1)
|
||||
|
||||
#define DIG_ADC_OUTPUT_FORMAT_DEFUALT (ADC_DIGI_FORMAT_12BIT)
|
||||
#define DIG_ADC_ATTEN_DEFUALT (ADC_ATTEN_DB_11)
|
||||
#define DIG_ADC_BIT_WIDTH_DEFUALT (ADC_WIDTH_BIT_12)
|
||||
|
||||
#define ADC_CHECK_RET(fun_ret) ({ \
|
||||
if (fun_ret != ESP_OK) { \
|
||||
ESP_LOGE(ADC_TAG,"%s:%d\n",__FUNCTION__,__LINE__); \
|
||||
return ESP_FAIL; \
|
||||
} \
|
||||
})
|
||||
|
||||
static const char *ADC_TAG = "ADC";
|
||||
|
||||
#define ADC_CHECK(a, str, ret_val) ({ \
|
||||
if (!(a)) { \
|
||||
ESP_LOGE(ADC_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \
|
||||
return (ret_val); \
|
||||
} \
|
||||
})
|
||||
|
||||
#define ADC_GET_IO_NUM(periph, channel) (adc_channel_io_map[periph][channel])
|
||||
|
||||
#define ADC_CHANNEL_CHECK(periph, channel) ADC_CHECK(channel < SOC_ADC_CHANNEL_NUM(periph), "ADC"#periph" channel error", ESP_ERR_INVALID_ARG)
|
||||
|
||||
extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished.
|
||||
#define ADC_ENTER_CRITICAL() portENTER_CRITICAL(&rtc_spinlock)
|
||||
#define ADC_EXIT_CRITICAL() portEXIT_CRITICAL(&rtc_spinlock)
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Digital controller setting
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
esp_err_t adc_set_i2s_data_source(adc_i2s_source_t src)
|
||||
{
|
||||
ADC_CHECK(src < ADC_I2S_DATA_SRC_MAX, "ADC i2s data source error", ESP_ERR_INVALID_ARG);
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_digi_set_data_source(src);
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel)
|
||||
{
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
ADC_CHECK((SOC_ADC_SUPPORT_DMA_MODE(ADC_NUM_1)), "ADC1 not support DMA for now.", ESP_ERR_INVALID_ARG);
|
||||
ADC_CHANNEL_CHECK(ADC_NUM_1, channel);
|
||||
}
|
||||
if (adc_unit & ADC_UNIT_2) {
|
||||
ADC_CHECK((SOC_ADC_SUPPORT_DMA_MODE(ADC_NUM_2)), "ADC2 not support DMA for now.", ESP_ERR_INVALID_ARG);
|
||||
ADC_CHANNEL_CHECK(ADC_NUM_2, channel);
|
||||
}
|
||||
|
||||
adc_digi_pattern_table_t adc1_pattern[1];
|
||||
adc_digi_pattern_table_t adc2_pattern[1];
|
||||
adc_digi_config_t dig_cfg = {
|
||||
.conv_limit_en = ADC_MEAS_NUM_LIM_DEFAULT,
|
||||
.conv_limit_num = ADC_MAX_MEAS_NUM_DEFAULT,
|
||||
.format = DIG_ADC_OUTPUT_FORMAT_DEFUALT,
|
||||
.conv_mode = (adc_digi_convert_mode_t)adc_unit,
|
||||
};
|
||||
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
adc1_pattern[0].atten = DIG_ADC_ATTEN_DEFUALT;
|
||||
adc1_pattern[0].bit_width = DIG_ADC_BIT_WIDTH_DEFUALT;
|
||||
adc1_pattern[0].channel = channel;
|
||||
dig_cfg.adc1_pattern_len = 1;
|
||||
dig_cfg.adc1_pattern = adc1_pattern;
|
||||
}
|
||||
if (adc_unit & ADC_UNIT_2) {
|
||||
adc2_pattern[0].atten = DIG_ADC_ATTEN_DEFUALT;
|
||||
adc2_pattern[0].bit_width = DIG_ADC_BIT_WIDTH_DEFUALT;
|
||||
adc2_pattern[0].channel = channel;
|
||||
dig_cfg.adc2_pattern_len = 1;
|
||||
dig_cfg.adc2_pattern = adc2_pattern;
|
||||
}
|
||||
adc_gpio_init(adc_unit, channel);
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_init();
|
||||
adc_hal_digi_controller_config(&dig_cfg);
|
||||
ADC_EXIT_CRITICAL();
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_init(void)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_init();
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_deinit(void)
|
||||
{
|
||||
adc_power_release();
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_digi_deinit();
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_controller_config(const adc_digi_config_t *config)
|
||||
{
|
||||
/* If enable digital controller, adc xpd should always on. */
|
||||
adc_power_acquire();
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_digi_controller_config(config);
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
RTC controller setting
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
HALL SENSOR
|
||||
@ -160,22 +51,26 @@ static int hall_sensor_get_value(void) //hall sensor without LNA
|
||||
|
||||
ADC_ENTER_CRITICAL();
|
||||
/* disable other peripherals. */
|
||||
adc_hal_amp_disable();
|
||||
adc_hal_hall_enable();
|
||||
adc_ll_amp_disable();
|
||||
adc_ll_hall_enable();
|
||||
// set controller
|
||||
adc_hal_set_controller( ADC_NUM_1, ADC_CTRL_RTC );
|
||||
adc_ll_set_controller( ADC_NUM_1, ADC_LL_CTRL_RTC );
|
||||
hall_value = adc_hal_hall_convert();
|
||||
adc_hal_hall_disable();
|
||||
adc_ll_hall_disable();
|
||||
ADC_EXIT_CRITICAL();
|
||||
|
||||
adc_power_release();
|
||||
return hall_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* To Be Deprecated
|
||||
*/
|
||||
extern esp_err_t adc_common_gpio_init(adc_unit_t adc_unit, adc_channel_t channel);
|
||||
int hall_sensor_read(void)
|
||||
{
|
||||
adc_gpio_init(ADC_UNIT_1, ADC1_CHANNEL_0);
|
||||
adc_gpio_init(ADC_UNIT_1, ADC1_CHANNEL_3);
|
||||
adc_common_gpio_init(ADC_UNIT_1, ADC1_CHANNEL_0);
|
||||
adc_common_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();
|
||||
|
@ -1,64 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "driver/adc_common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Digital controller setting
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Set I2S data source
|
||||
* @param src I2S DMA data source, I2S DMA can get data from digital signals or from ADC.
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
*/
|
||||
esp_err_t adc_set_i2s_data_source(adc_i2s_source_t src);
|
||||
|
||||
/**
|
||||
* @brief Initialize I2S ADC mode
|
||||
* @param adc_unit ADC unit index
|
||||
* @param channel ADC channel index
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel);
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
RTC controller setting
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Read Hall Sensor
|
||||
*
|
||||
* @note When the power switch of SARADC1, SARADC2, HALL sensor and AMP sensor is turned on,
|
||||
* the input of GPIO36 and GPIO39 will be pulled down for about 80ns.
|
||||
* When enabling power for any of these peripherals, ignore input from GPIO36 and GPIO39.
|
||||
* Please refer to section 3.11 of 'ECO_and_Workarounds_for_Bugs_in_ESP32' for the description of this issue.
|
||||
*
|
||||
* @note The Hall Sensor uses channels 0 and 3 of ADC1. Do not configure
|
||||
* these channels for use as ADC channels.
|
||||
*
|
||||
* @note The ADC1 module must be enabled by calling
|
||||
* adc1_config_width() before calling hall_sensor_read(). ADC1
|
||||
* should be configured for 12 bit readings, as the hall sensor
|
||||
* readings are low values and do not cover the full range of the
|
||||
* ADC.
|
||||
*
|
||||
* @return The hall sensor reading.
|
||||
*/
|
||||
int hall_sensor_read(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,93 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "driver/adc_common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Common setting
|
||||
---------------------------------------------------------------*/
|
||||
/*************************************/
|
||||
/* Digital controller filter setting */
|
||||
/*************************************/
|
||||
/**
|
||||
* @brief Reset adc digital controller filter.
|
||||
*
|
||||
* @param idx Filter index.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_filter_reset(adc_digi_filter_idx_t idx);
|
||||
|
||||
/**
|
||||
* @brief Set adc digital controller filter configuration.
|
||||
*
|
||||
* @param idx Filter index.
|
||||
* @param config See ``adc_digi_filter_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_filter_set_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config);
|
||||
|
||||
/**
|
||||
* @brief Get adc digital controller filter configuration.
|
||||
*
|
||||
* @param idx Filter index.
|
||||
* @param config See ``adc_digi_filter_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_filter_get_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config);
|
||||
|
||||
/**
|
||||
* @brief Enable/disable adc digital controller filter.
|
||||
* Filtering the ADC data to obtain smooth data at higher sampling rates.
|
||||
*
|
||||
* @param idx Filter index.
|
||||
* @param enable Enable/Disable filter.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_filter_enable(adc_digi_filter_idx_t idx, bool enable);
|
||||
|
||||
/**************************************/
|
||||
/* Digital controller monitor setting */
|
||||
/**************************************/
|
||||
|
||||
/**
|
||||
* @brief Config monitor of adc digital controller.
|
||||
*
|
||||
* @param idx Monitor index.
|
||||
* @param config See ``adc_digi_monitor_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_monitor_set_config(adc_digi_monitor_idx_t idx, adc_digi_monitor_t *config);
|
||||
|
||||
/**
|
||||
* @brief Enable/disable monitor of adc digital controller.
|
||||
*
|
||||
* @param idx Monitor index.
|
||||
* @param enable True or false enable monitor.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_monitor_enable(adc_digi_monitor_idx_t idx, bool enable);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,717 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <esp_types.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_pm.h"
|
||||
#include "sys/lock.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/timers.h"
|
||||
#include "freertos/ringbuf.h"
|
||||
#include "esp32h2/rom/ets_sys.h"
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/adc.h"
|
||||
#include "hal/adc_types.h"
|
||||
#include "hal/adc_hal.h"
|
||||
#include "hal/dma_types.h"
|
||||
#include "esp_efuse_rtc_calib.h"
|
||||
#include "esp_private/gdma.h"
|
||||
|
||||
#define ADC_CHECK_RET(fun_ret) ({ \
|
||||
if (fun_ret != ESP_OK) { \
|
||||
ESP_LOGE(ADC_TAG,"%s(%d)",__FUNCTION__,__LINE__); \
|
||||
return ESP_FAIL; \
|
||||
} \
|
||||
})
|
||||
|
||||
static const char *ADC_TAG = "ADC";
|
||||
|
||||
#define ADC_CHECK(a, str, ret_val) ({ \
|
||||
if (!(a)) { \
|
||||
ESP_LOGE(ADC_TAG,"%s(%d) :%s", __FUNCTION__, __LINE__, str); \
|
||||
return (ret_val); \
|
||||
} \
|
||||
})
|
||||
|
||||
#define ADC_GET_IO_NUM(periph, channel) (adc_channel_io_map[periph][channel])
|
||||
|
||||
#define ADC_CHANNEL_CHECK(periph, channel) ADC_CHECK(channel < SOC_ADC_CHANNEL_NUM(periph), "ADC"#periph" channel error", ESP_ERR_INVALID_ARG)
|
||||
|
||||
extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished.
|
||||
#define ADC_ENTER_CRITICAL() portENTER_CRITICAL(&rtc_spinlock)
|
||||
#define ADC_EXIT_CRITICAL() portEXIT_CRITICAL(&rtc_spinlock)
|
||||
|
||||
/**
|
||||
* 1. sar_adc1_lock: this mutex lock is to protect the SARADC1 module.
|
||||
* 2. sar_adc2_lock: this mutex lock is to protect the SARADC2 module. On H2, it is controlled by the digital controller
|
||||
* and PWDET controller.
|
||||
* 3. adc_reg_lock: this spin lock is to protect the shared registers used by ADC1 / ADC2 single read mode.
|
||||
*/
|
||||
static _lock_t sar_adc1_lock;
|
||||
#define SAR_ADC1_LOCK_ACQUIRE() _lock_acquire(&sar_adc1_lock)
|
||||
#define SAR_ADC1_LOCK_RELEASE() _lock_release(&sar_adc1_lock)
|
||||
static _lock_t sar_adc2_lock;
|
||||
#define SAR_ADC2_LOCK_ACQUIRE() _lock_acquire(&sar_adc2_lock)
|
||||
#define SAR_ADC2_LOCK_RELEASE() _lock_release(&sar_adc2_lock)
|
||||
portMUX_TYPE adc_reg_lock = portMUX_INITIALIZER_UNLOCKED;
|
||||
#define ADC_REG_LOCK_ENTER() portENTER_CRITICAL(&adc_reg_lock)
|
||||
#define ADC_REG_LOCK_EXIT() portEXIT_CRITICAL(&adc_reg_lock)
|
||||
|
||||
#define INTERNAL_BUF_NUM 5
|
||||
#define IN_SUC_EOF_BIT GDMA_LL_EVENT_RX_SUC_EOF
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Digital Controller Context
|
||||
---------------------------------------------------------------*/
|
||||
typedef struct adc_digi_context_t {
|
||||
uint8_t *rx_dma_buf; //dma buffer
|
||||
adc_hal_context_t hal; //hal context
|
||||
gdma_channel_handle_t rx_dma_channel; //dma rx channel handle
|
||||
RingbufHandle_t ringbuf_hdl; //RX ringbuffer handler
|
||||
intptr_t rx_eof_desc_addr; //eof descriptor address of RX channel
|
||||
bool ringbuf_overflow_flag; //1: ringbuffer overflow
|
||||
bool driver_start_flag; //1: driver is started; 0: driver is stoped
|
||||
bool use_adc1; //1: ADC unit1 will be used; 0: ADC unit1 won't be used.
|
||||
bool use_adc2; //1: ADC unit2 will be used; 0: ADC unit2 won't be used. This determines whether to acquire sar_adc2_mutex lock or not.
|
||||
adc_atten_t adc1_atten; //Attenuation for ADC1. On this chip each ADC can only support one attenuation.
|
||||
adc_atten_t adc2_atten; //Attenuation for ADC2. On this chip each ADC can only support one attenuation.
|
||||
adc_digi_config_t digi_controller_config; //Digital Controller Configuration
|
||||
esp_pm_lock_handle_t pm_lock; //For power management
|
||||
} adc_digi_context_t;
|
||||
|
||||
static adc_digi_context_t *s_adc_digi_ctx = NULL;
|
||||
|
||||
static uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t chan, adc_atten_t atten);
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
ADC Continuous Read Mode (via DMA)
|
||||
---------------------------------------------------------------*/
|
||||
static IRAM_ATTR bool adc_dma_in_suc_eof_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data);
|
||||
|
||||
static int8_t adc_digi_get_io_num(uint8_t adc_unit, uint8_t adc_channel)
|
||||
{
|
||||
return adc_channel_io_map[adc_unit][adc_channel];
|
||||
}
|
||||
|
||||
static esp_err_t adc_digi_gpio_init(adc_unit_t adc_unit, uint16_t channel_mask)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
uint64_t gpio_mask = 0;
|
||||
uint32_t n = 0;
|
||||
int8_t io = 0;
|
||||
|
||||
while (channel_mask) {
|
||||
if (channel_mask & 0x1) {
|
||||
io = adc_digi_get_io_num(adc_unit, n);
|
||||
if (io < 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
gpio_mask |= BIT64(io);
|
||||
}
|
||||
channel_mask = channel_mask >> 1;
|
||||
n++;
|
||||
}
|
||||
|
||||
gpio_config_t cfg = {
|
||||
.pin_bit_mask = gpio_mask,
|
||||
.mode = GPIO_MODE_DISABLE,
|
||||
};
|
||||
ret = gpio_config(&cfg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
s_adc_digi_ctx = calloc(1, sizeof(adc_digi_context_t));
|
||||
if (s_adc_digi_ctx == NULL) {
|
||||
ret = ESP_ERR_NO_MEM;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
//ringbuffer
|
||||
s_adc_digi_ctx->ringbuf_hdl = xRingbufferCreate(init_config->max_store_buf_size, RINGBUF_TYPE_BYTEBUF);
|
||||
if (!s_adc_digi_ctx->ringbuf_hdl) {
|
||||
ret = ESP_ERR_NO_MEM;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
//malloc internal buffer used by DMA
|
||||
s_adc_digi_ctx->rx_dma_buf = heap_caps_calloc(1, init_config->conv_num_each_intr * INTERNAL_BUF_NUM, MALLOC_CAP_INTERNAL);
|
||||
if (!s_adc_digi_ctx->rx_dma_buf) {
|
||||
ret = ESP_ERR_NO_MEM;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
//malloc dma descriptor
|
||||
s_adc_digi_ctx->hal.rx_desc = heap_caps_calloc(1, (sizeof(dma_descriptor_t)) * INTERNAL_BUF_NUM, MALLOC_CAP_DMA);
|
||||
if (!s_adc_digi_ctx->hal.rx_desc) {
|
||||
ret = ESP_ERR_NO_MEM;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
//malloc pattern table
|
||||
s_adc_digi_ctx->digi_controller_config.adc_pattern = calloc(1, SOC_ADC_PATT_LEN_MAX * sizeof(adc_digi_pattern_table_t));
|
||||
if (!s_adc_digi_ctx->digi_controller_config.adc_pattern) {
|
||||
ret = ESP_ERR_NO_MEM;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
#if CONFIG_PM_ENABLE
|
||||
ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "adc_dma", &s_adc_digi_ctx->pm_lock);
|
||||
if (ret != ESP_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
|
||||
//init gpio pins
|
||||
if (init_config->adc1_chan_mask) {
|
||||
ret = adc_digi_gpio_init(ADC_NUM_1, init_config->adc1_chan_mask);
|
||||
if (ret != ESP_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
if (init_config->adc2_chan_mask) {
|
||||
ret = adc_digi_gpio_init(ADC_NUM_2, init_config->adc2_chan_mask);
|
||||
if (ret != ESP_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
//alloc rx gdma channel
|
||||
gdma_channel_alloc_config_t rx_alloc_config = {
|
||||
.direction = GDMA_CHANNEL_DIRECTION_RX,
|
||||
};
|
||||
ret = gdma_new_channel(&rx_alloc_config, &s_adc_digi_ctx->rx_dma_channel);
|
||||
if (ret != ESP_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
gdma_connect(s_adc_digi_ctx->rx_dma_channel, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_ADC, 0));
|
||||
|
||||
gdma_strategy_config_t strategy_config = {
|
||||
.auto_update_desc = true,
|
||||
.owner_check = true
|
||||
};
|
||||
gdma_apply_strategy(s_adc_digi_ctx->rx_dma_channel, &strategy_config);
|
||||
|
||||
gdma_rx_event_callbacks_t cbs = {
|
||||
.on_recv_eof = adc_dma_in_suc_eof_callback
|
||||
};
|
||||
gdma_register_rx_event_callbacks(s_adc_digi_ctx->rx_dma_channel, &cbs, s_adc_digi_ctx);
|
||||
|
||||
int dma_chan;
|
||||
gdma_get_channel_id(s_adc_digi_ctx->rx_dma_channel, &dma_chan);
|
||||
|
||||
adc_hal_config_t config = {
|
||||
.desc_max_num = INTERNAL_BUF_NUM,
|
||||
.dma_chan = dma_chan,
|
||||
.eof_num = init_config->conv_num_each_intr / ADC_HAL_DATA_LEN_PER_CONV
|
||||
};
|
||||
adc_hal_context_config(&s_adc_digi_ctx->hal, &config);
|
||||
|
||||
//enable SARADC module clock
|
||||
periph_module_enable(PERIPH_SARADC_MODULE);
|
||||
|
||||
adc_hal_calibration_init(ADC_NUM_1);
|
||||
adc_hal_calibration_init(ADC_NUM_2);
|
||||
|
||||
return ret;
|
||||
|
||||
cleanup:
|
||||
adc_digi_deinitialize();
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
static IRAM_ATTR bool adc_dma_intr(adc_digi_context_t *adc_digi_ctx);
|
||||
|
||||
static IRAM_ATTR bool adc_dma_in_suc_eof_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data)
|
||||
{
|
||||
assert(event_data);
|
||||
adc_digi_context_t *adc_digi_ctx = (adc_digi_context_t *)user_data;
|
||||
adc_digi_ctx->rx_eof_desc_addr = event_data->rx_eof_desc_addr;
|
||||
return adc_dma_intr(adc_digi_ctx);
|
||||
}
|
||||
|
||||
static IRAM_ATTR bool adc_dma_intr(adc_digi_context_t *adc_digi_ctx)
|
||||
{
|
||||
portBASE_TYPE taskAwoken = 0;
|
||||
BaseType_t ret;
|
||||
adc_hal_dma_desc_status_t status = false;
|
||||
dma_descriptor_t *current_desc = NULL;
|
||||
|
||||
while (1) {
|
||||
status = adc_hal_get_reading_result(&adc_digi_ctx->hal, adc_digi_ctx->rx_eof_desc_addr, ¤t_desc);
|
||||
if (status != ADC_HAL_DMA_DESC_VALID) {
|
||||
break;
|
||||
}
|
||||
|
||||
ret = xRingbufferSendFromISR(adc_digi_ctx->ringbuf_hdl, current_desc->buffer, current_desc->dw0.length, &taskAwoken);
|
||||
if (ret == pdFALSE) {
|
||||
//ringbuffer overflow
|
||||
adc_digi_ctx->ringbuf_overflow_flag = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (status == ADC_HAL_DMA_DESC_NULL) {
|
||||
//start next turns of dma operation
|
||||
adc_hal_digi_rxdma_start(&adc_digi_ctx->hal, adc_digi_ctx->rx_dma_buf);
|
||||
}
|
||||
|
||||
return (taskAwoken == pdTRUE);
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_start(void)
|
||||
{
|
||||
if (s_adc_digi_ctx->driver_start_flag != 0) {
|
||||
ESP_LOGE(ADC_TAG, "The driver is already started");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
adc_power_acquire();
|
||||
//reset flags
|
||||
s_adc_digi_ctx->ringbuf_overflow_flag = 0;
|
||||
s_adc_digi_ctx->driver_start_flag = 1;
|
||||
if (s_adc_digi_ctx->use_adc1) {
|
||||
SAR_ADC1_LOCK_ACQUIRE();
|
||||
}
|
||||
if (s_adc_digi_ctx->use_adc2) {
|
||||
SAR_ADC2_LOCK_ACQUIRE();
|
||||
}
|
||||
|
||||
#if CONFIG_PM_ENABLE
|
||||
// Lock APB frequency while ADC driver is in use
|
||||
esp_pm_lock_acquire(s_adc_digi_ctx->pm_lock);
|
||||
#endif
|
||||
|
||||
adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT();
|
||||
if (s_adc_digi_ctx->use_adc1) {
|
||||
uint32_t cal_val = adc_get_calibration_offset(ADC_NUM_1, ADC_CHANNEL_MAX, s_adc_digi_ctx->adc1_atten);
|
||||
adc_hal_set_calibration_param(ADC_NUM_1, cal_val);
|
||||
}
|
||||
if (s_adc_digi_ctx->use_adc2) {
|
||||
uint32_t cal_val = adc_get_calibration_offset(ADC_NUM_2, ADC_CHANNEL_MAX, s_adc_digi_ctx->adc2_atten);
|
||||
adc_hal_set_calibration_param(ADC_NUM_2, cal_val);
|
||||
}
|
||||
|
||||
adc_hal_init();
|
||||
adc_hal_arbiter_config(&config);
|
||||
adc_hal_digi_init(&s_adc_digi_ctx->hal);
|
||||
adc_hal_digi_controller_config(&s_adc_digi_ctx->digi_controller_config);
|
||||
|
||||
//reset ADC and DMA
|
||||
adc_hal_fifo_reset(&s_adc_digi_ctx->hal);
|
||||
//start DMA
|
||||
adc_hal_digi_rxdma_start(&s_adc_digi_ctx->hal, s_adc_digi_ctx->rx_dma_buf);
|
||||
//start ADC
|
||||
adc_hal_digi_start(&s_adc_digi_ctx->hal);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_stop(void)
|
||||
{
|
||||
if (s_adc_digi_ctx->driver_start_flag != 1) {
|
||||
ESP_LOGE(ADC_TAG, "The driver is already stopped");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
s_adc_digi_ctx->driver_start_flag = 0;
|
||||
|
||||
//disable the in suc eof intrrupt
|
||||
adc_hal_digi_dis_intr(&s_adc_digi_ctx->hal, IN_SUC_EOF_BIT);
|
||||
//clear the in suc eof interrupt
|
||||
adc_hal_digi_clr_intr(&s_adc_digi_ctx->hal, IN_SUC_EOF_BIT);
|
||||
//stop ADC
|
||||
adc_hal_digi_stop(&s_adc_digi_ctx->hal);
|
||||
//stop DMA
|
||||
adc_hal_digi_rxdma_stop(&s_adc_digi_ctx->hal);
|
||||
adc_hal_digi_deinit();
|
||||
#if CONFIG_PM_ENABLE
|
||||
if (s_adc_digi_ctx->pm_lock) {
|
||||
esp_pm_lock_release(s_adc_digi_ctx->pm_lock);
|
||||
}
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
|
||||
if (s_adc_digi_ctx->use_adc1) {
|
||||
SAR_ADC1_LOCK_RELEASE();
|
||||
}
|
||||
if (s_adc_digi_ctx->use_adc2) {
|
||||
SAR_ADC2_LOCK_RELEASE();
|
||||
}
|
||||
adc_power_release();
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_read_bytes(uint8_t *buf, uint32_t length_max, uint32_t *out_length, uint32_t timeout_ms)
|
||||
{
|
||||
TickType_t ticks_to_wait;
|
||||
esp_err_t ret = ESP_OK;
|
||||
uint8_t *data = NULL;
|
||||
size_t size = 0;
|
||||
|
||||
ticks_to_wait = timeout_ms / portTICK_RATE_MS;
|
||||
if (timeout_ms == ADC_MAX_DELAY) {
|
||||
ticks_to_wait = portMAX_DELAY;
|
||||
}
|
||||
|
||||
data = xRingbufferReceiveUpTo(s_adc_digi_ctx->ringbuf_hdl, &size, ticks_to_wait, length_max);
|
||||
if (!data) {
|
||||
ESP_LOGV(ADC_TAG, "No data, increase timeout or reduce conv_num_each_intr");
|
||||
ret = ESP_ERR_TIMEOUT;
|
||||
*out_length = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
memcpy(buf, data, size);
|
||||
vRingbufferReturnItem(s_adc_digi_ctx->ringbuf_hdl, data);
|
||||
assert((size % 4) == 0);
|
||||
*out_length = size;
|
||||
|
||||
if (s_adc_digi_ctx->ringbuf_overflow_flag) {
|
||||
ret = ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_deinitialize(void)
|
||||
{
|
||||
if (!s_adc_digi_ctx) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (s_adc_digi_ctx->driver_start_flag != 0) {
|
||||
ESP_LOGE(ADC_TAG, "The driver is not stopped");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (s_adc_digi_ctx->ringbuf_hdl) {
|
||||
vRingbufferDelete(s_adc_digi_ctx->ringbuf_hdl);
|
||||
s_adc_digi_ctx->ringbuf_hdl = NULL;
|
||||
}
|
||||
|
||||
#if CONFIG_PM_ENABLE
|
||||
if (s_adc_digi_ctx->pm_lock) {
|
||||
esp_pm_lock_delete(s_adc_digi_ctx->pm_lock);
|
||||
}
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
|
||||
free(s_adc_digi_ctx->rx_dma_buf);
|
||||
free(s_adc_digi_ctx->hal.rx_desc);
|
||||
free(s_adc_digi_ctx->digi_controller_config.adc_pattern);
|
||||
gdma_disconnect(s_adc_digi_ctx->rx_dma_channel);
|
||||
gdma_del_channel(s_adc_digi_ctx->rx_dma_channel);
|
||||
|
||||
free(s_adc_digi_ctx);
|
||||
s_adc_digi_ctx = NULL;
|
||||
|
||||
periph_module_disable(PERIPH_SARADC_MODULE);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
ADC Single Read Mode
|
||||
---------------------------------------------------------------*/
|
||||
static adc_atten_t s_atten1_single[ADC1_CHANNEL_MAX]; //Array saving attenuate of each channel of ADC1, used by single read API
|
||||
static adc_atten_t s_atten2_single[ADC2_CHANNEL_MAX]; //Array saving attenuate of each channel of ADC2, used by single read API
|
||||
|
||||
esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio)
|
||||
{
|
||||
esp_err_t ret;
|
||||
uint32_t channel = ADC2_CHANNEL_MAX;
|
||||
if (adc_unit == ADC_UNIT_2) {
|
||||
for (int i = 0; i < ADC2_CHANNEL_MAX; i++) {
|
||||
if (gpio == ADC_GET_IO_NUM(ADC_NUM_2, i)) {
|
||||
channel = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (channel == ADC2_CHANNEL_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
adc_power_acquire();
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_vref_output(ADC_NUM_1, channel, true);
|
||||
ADC_EXIT_CRITICAL()
|
||||
} else if (adc_unit & ADC_UNIT_2) {
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_vref_output(ADC_NUM_2, channel, true);
|
||||
ADC_EXIT_CRITICAL()
|
||||
}
|
||||
|
||||
ret = adc_digi_gpio_init(ADC_NUM_2, BIT(channel));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t adc1_config_width(adc_bits_width_t width_bit)
|
||||
{
|
||||
//On ESP32H2, the data width is always 12-bits.
|
||||
if (width_bit != ADC_WIDTH_BIT_12) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten)
|
||||
{
|
||||
ADC_CHANNEL_CHECK(ADC_NUM_1, channel);
|
||||
ADC_CHECK(atten < ADC_ATTEN_MAX, "ADC Atten Err", ESP_ERR_INVALID_ARG);
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
s_atten1_single[channel] = atten;
|
||||
ret = adc_digi_gpio_init(ADC_NUM_1, BIT(channel));
|
||||
|
||||
adc_hal_calibration_init(ADC_NUM_1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int adc1_get_raw(adc1_channel_t channel)
|
||||
{
|
||||
int raw_out = 0;
|
||||
|
||||
periph_module_enable(PERIPH_SARADC_MODULE);
|
||||
adc_power_acquire();
|
||||
|
||||
SAR_ADC1_LOCK_ACQUIRE();
|
||||
|
||||
adc_atten_t atten = s_atten1_single[channel];
|
||||
uint32_t cal_val = adc_get_calibration_offset(ADC_NUM_1, channel, atten);
|
||||
adc_hal_set_calibration_param(ADC_NUM_1, cal_val);
|
||||
|
||||
ADC_REG_LOCK_ENTER();
|
||||
adc_hal_set_atten(ADC_NUM_2, channel, atten);
|
||||
adc_hal_convert(ADC_NUM_1, channel, &raw_out);
|
||||
ADC_REG_LOCK_EXIT();
|
||||
|
||||
SAR_ADC1_LOCK_RELEASE();
|
||||
|
||||
adc_power_release();
|
||||
periph_module_disable(PERIPH_SARADC_MODULE);
|
||||
|
||||
return raw_out;
|
||||
}
|
||||
|
||||
esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten)
|
||||
{
|
||||
ADC_CHANNEL_CHECK(ADC_NUM_2, channel);
|
||||
ADC_CHECK(atten <= ADC_ATTEN_11db, "ADC2 Atten Err", ESP_ERR_INVALID_ARG);
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
s_atten2_single[channel] = atten;
|
||||
ret = adc_digi_gpio_init(ADC_NUM_2, BIT(channel));
|
||||
|
||||
adc_hal_calibration_init(ADC_NUM_2);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *raw_out)
|
||||
{
|
||||
//On ESP32H2, the data width is always 12-bits.
|
||||
if (width_bit != ADC_WIDTH_BIT_12) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
periph_module_enable(PERIPH_SARADC_MODULE);
|
||||
adc_power_acquire();
|
||||
|
||||
SAR_ADC2_LOCK_ACQUIRE();
|
||||
|
||||
adc_atten_t atten = s_atten2_single[channel];
|
||||
uint32_t cal_val = adc_get_calibration_offset(ADC_NUM_2, channel, atten);
|
||||
adc_hal_set_calibration_param(ADC_NUM_2, cal_val);
|
||||
|
||||
ADC_REG_LOCK_ENTER();
|
||||
adc_hal_set_atten(ADC_NUM_2, channel, atten);
|
||||
ret = adc_hal_convert(ADC_NUM_2, channel, raw_out);
|
||||
ADC_REG_LOCK_EXIT();
|
||||
|
||||
SAR_ADC2_LOCK_RELEASE();
|
||||
|
||||
adc_power_release();
|
||||
periph_module_disable(PERIPH_SARADC_MODULE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Digital controller setting
|
||||
---------------------------------------------------------------*/
|
||||
esp_err_t adc_digi_controller_config(const adc_digi_config_t *config)
|
||||
{
|
||||
if (!s_adc_digi_ctx) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
ADC_CHECK(config->sample_freq_hz <= SOC_ADC_SAMPLE_FREQ_THRES_HIGH && config->sample_freq_hz >= SOC_ADC_SAMPLE_FREQ_THRES_LOW, "ADC sampling frequency out of range", ESP_ERR_INVALID_ARG);
|
||||
|
||||
s_adc_digi_ctx->digi_controller_config.conv_limit_en = config->conv_limit_en;
|
||||
s_adc_digi_ctx->digi_controller_config.conv_limit_num = config->conv_limit_num;
|
||||
s_adc_digi_ctx->digi_controller_config.adc_pattern_len = config->adc_pattern_len;
|
||||
s_adc_digi_ctx->digi_controller_config.sample_freq_hz = config->sample_freq_hz;
|
||||
memcpy(s_adc_digi_ctx->digi_controller_config.adc_pattern, config->adc_pattern, config->adc_pattern_len * sizeof(adc_digi_pattern_table_t));
|
||||
|
||||
const int atten_uninitialised = 999;
|
||||
s_adc_digi_ctx->adc1_atten = atten_uninitialised;
|
||||
s_adc_digi_ctx->adc2_atten = atten_uninitialised;
|
||||
s_adc_digi_ctx->use_adc1 = 0;
|
||||
s_adc_digi_ctx->use_adc2 = 0;
|
||||
for (int i = 0; i < config->adc_pattern_len; i++) {
|
||||
const adc_digi_pattern_table_t *pat = &config->adc_pattern[i];
|
||||
if (pat->unit == ADC_NUM_1) {
|
||||
s_adc_digi_ctx->use_adc1 = 1;
|
||||
|
||||
if (s_adc_digi_ctx->adc1_atten == atten_uninitialised) {
|
||||
s_adc_digi_ctx->adc1_atten = pat->atten;
|
||||
} else if (s_adc_digi_ctx->adc1_atten != pat->atten) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
} else if (pat->unit == ADC_NUM_2) {
|
||||
//See whether ADC2 will be used or not. If yes, the ``sar_adc2_mutex`` should be acquired in the continuous read driver
|
||||
s_adc_digi_ctx->use_adc2 = 1;
|
||||
|
||||
if (s_adc_digi_ctx->adc2_atten == atten_uninitialised) {
|
||||
s_adc_digi_ctx->adc2_atten = pat->atten;
|
||||
} else if (s_adc_digi_ctx->adc2_atten != pat->atten) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/*************************************/
|
||||
/* Digital controller filter setting */
|
||||
/*************************************/
|
||||
|
||||
esp_err_t adc_digi_filter_reset(adc_digi_filter_idx_t idx)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_digi_filter_reset(idx);
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_filter_set_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_digi_filter_set_factor(idx, config);
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_filter_get_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_digi_filter_get_factor(idx, config);
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_filter_enable(adc_digi_filter_idx_t idx, bool enable)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_digi_filter_enable(idx, enable);
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
/* Digital controller monitor setting */
|
||||
/**************************************/
|
||||
|
||||
esp_err_t adc_digi_monitor_set_config(adc_digi_monitor_idx_t idx, adc_digi_monitor_t *config)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_digi_monitor_config(idx, config);
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_monitor_enable(adc_digi_monitor_idx_t idx, bool enable)
|
||||
{
|
||||
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_digi_monitor_enable(idx, enable);
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
RTC controller setting
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
static uint16_t s_adc_cali_param[SOC_ADC_PERIPH_NUM][ADC_ATTEN_MAX] = {};
|
||||
|
||||
//NOTE: according to calibration version, different types of lock may be taken during the process:
|
||||
// 1. Semaphore when reading efuse
|
||||
// 2. Lock (Spinlock, or Mutex) if we actually do ADC calibration in the future
|
||||
//This function shoudn't be called inside critical section or ISR
|
||||
static uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten)
|
||||
{
|
||||
const bool no_cal = false;
|
||||
if (s_adc_cali_param[adc_n][atten]) {
|
||||
return (uint32_t)s_adc_cali_param[adc_n][atten];
|
||||
}
|
||||
|
||||
if (no_cal) {
|
||||
return 0; //indicating failure
|
||||
}
|
||||
|
||||
// check if we can fetch the values from eFuse.
|
||||
int version = esp_efuse_rtc_calib_get_ver();
|
||||
|
||||
uint32_t init_code = 0;
|
||||
if (version == 1) {
|
||||
//for calibration v1, both ADC units use the same init code (calibrated by ADC1)
|
||||
init_code = esp_efuse_rtc_calib_get_init_code(version, atten);
|
||||
ESP_LOGD(ADC_TAG, "Calib(V%d) ADC0, 1 atten=%d: %04X", version, atten, init_code);
|
||||
s_adc_cali_param[0][atten] = init_code;
|
||||
s_adc_cali_param[1][atten] = init_code;
|
||||
} else {
|
||||
adc_power_acquire();
|
||||
ADC_ENTER_CRITICAL();
|
||||
const bool internal_gnd = true;
|
||||
init_code = adc_hal_self_calibration(adc_n, channel, atten, internal_gnd);
|
||||
ADC_EXIT_CRITICAL();
|
||||
adc_power_release();
|
||||
|
||||
ESP_LOGD(ADC_TAG, "Calib(V%d) ADC%d atten=%d: %04X", version, adc_n, atten, init_code);
|
||||
s_adc_cali_param[adc_n][atten] = init_code;
|
||||
}
|
||||
|
||||
return init_code;
|
||||
}
|
||||
|
||||
// Internal function to calibrate PWDET for WiFi
|
||||
esp_err_t adc_cal_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten)
|
||||
{
|
||||
adc_hal_calibration_init(adc_n);
|
||||
uint32_t cal_val = adc_get_calibration_offset(adc_n, channel, atten);
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_set_calibration_param(adc_n, cal_val);
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* This file is used to get `adc2_init_code_calibration` executed before the APP when the ADC2 is used by Wi-Fi or other drivers.
|
||||
The linker will link constructor (adc2_init_code_calibration) only when any sections inside the same file (adc2_cal_include) is used.
|
||||
Don't put any other code into this file. */
|
||||
|
||||
#include "adc2_wifi_private.h"
|
||||
#include "hal/adc_hal.h"
|
||||
#include "esp_private/adc_cali.h"
|
||||
|
||||
/**
|
||||
* @brief Set initial code to ADC2 after calibration. ADC2 RTC and ADC2 PWDET controller share the initial code.
|
||||
* This API be called in before `app_main()`.
|
||||
*/
|
||||
static __attribute__((constructor)) void adc2_init_code_calibration(void)
|
||||
{
|
||||
const adc_ll_num_t adc_n = ADC_NUM_2;
|
||||
const adc_atten_t atten = ADC_ATTEN_DB_11;
|
||||
const adc_channel_t channel = 0;
|
||||
adc_cal_offset(adc_n, channel, atten);
|
||||
}
|
||||
|
||||
/** Don't call `adc2_cal_include` in user code. */
|
||||
void adc2_cal_include(void)
|
||||
{
|
||||
/* When this empty function is called, the `adc2_init_code_calibration` constructor will be linked and executed before the app.*/
|
||||
}
|
@ -1,93 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "driver/adc_common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Common setting
|
||||
---------------------------------------------------------------*/
|
||||
/*************************************/
|
||||
/* Digital controller filter setting */
|
||||
/*************************************/
|
||||
/**
|
||||
* @brief Reset adc digital controller filter.
|
||||
*
|
||||
* @param idx Filter index.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_filter_reset(adc_digi_filter_idx_t idx);
|
||||
|
||||
/**
|
||||
* @brief Set adc digital controller filter configuration.
|
||||
*
|
||||
* @param idx Filter index.
|
||||
* @param config See ``adc_digi_filter_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_filter_set_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config);
|
||||
|
||||
/**
|
||||
* @brief Get adc digital controller filter configuration.
|
||||
*
|
||||
* @param idx Filter index.
|
||||
* @param config See ``adc_digi_filter_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_filter_get_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config);
|
||||
|
||||
/**
|
||||
* @brief Enable/disable adc digital controller filter.
|
||||
* Filtering the ADC data to obtain smooth data at higher sampling rates.
|
||||
*
|
||||
* @param idx Filter index.
|
||||
* @param enable Enable/Disable filter.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_filter_enable(adc_digi_filter_idx_t idx, bool enable);
|
||||
|
||||
/**************************************/
|
||||
/* Digital controller monitor setting */
|
||||
/**************************************/
|
||||
|
||||
/**
|
||||
* @brief Config monitor of adc digital controller.
|
||||
*
|
||||
* @param idx Monitor index.
|
||||
* @param config See ``adc_digi_monitor_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_monitor_set_config(adc_digi_monitor_idx_t idx, adc_digi_monitor_t *config);
|
||||
|
||||
/**
|
||||
* @brief Enable/disable monitor of adc digital controller.
|
||||
*
|
||||
* @param idx Monitor index.
|
||||
* @param enable True or false enable monitor.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_monitor_enable(adc_digi_monitor_idx_t idx, bool enable);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -11,229 +11,24 @@
|
||||
#include "esp_log.h"
|
||||
#include "sys/lock.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/xtensa_api.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/timers.h"
|
||||
#include "esp_pm.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
#include "driver/rtc_io.h"
|
||||
#include "driver/rtc_cntl.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/adc.h"
|
||||
#include "esp_efuse_rtc_table.h"
|
||||
|
||||
#include "hal/adc_types.h"
|
||||
#include "hal/adc_hal.h"
|
||||
|
||||
#define ADC_CHECK_RET(fun_ret) ({ \
|
||||
if (fun_ret != ESP_OK) { \
|
||||
ESP_LOGE(ADC_TAG,"%s:%d\n",__FUNCTION__,__LINE__); \
|
||||
return ESP_FAIL; \
|
||||
} \
|
||||
})
|
||||
|
||||
static const char *ADC_TAG = "ADC";
|
||||
|
||||
#define ADC_CHECK(a, str, ret_val) ({ \
|
||||
if (!(a)) { \
|
||||
ESP_LOGE(ADC_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \
|
||||
return (ret_val); \
|
||||
} \
|
||||
})
|
||||
|
||||
#define ADC_GET_IO_NUM(periph, channel) (adc_channel_io_map[periph][channel])
|
||||
|
||||
#define ADC_CHANNEL_CHECK(periph, channel) ADC_CHECK(channel < SOC_ADC_CHANNEL_NUM(periph), "ADC"#periph" channel error", ESP_ERR_INVALID_ARG)
|
||||
#include "hal/adc_ll.h"
|
||||
|
||||
extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished.
|
||||
#define ADC_ENTER_CRITICAL() portENTER_CRITICAL(&rtc_spinlock)
|
||||
#define ADC_EXIT_CRITICAL() portEXIT_CRITICAL(&rtc_spinlock)
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
static esp_pm_lock_handle_t s_adc_digi_arbiter_lock = NULL;
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
|
||||
esp_err_t adc_cal_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten);
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Digital controller setting
|
||||
---------------------------------------------------------------*/
|
||||
esp_err_t adc_digi_init(void)
|
||||
{
|
||||
adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT();
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_init();
|
||||
adc_hal_arbiter_config(&config);
|
||||
ADC_EXIT_CRITICAL();
|
||||
|
||||
adc_hal_calibration_init(ADC_NUM_1);
|
||||
adc_hal_calibration_init(ADC_NUM_2);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_deinit(void)
|
||||
{
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
if (s_adc_digi_arbiter_lock) {
|
||||
esp_pm_lock_delete(s_adc_digi_arbiter_lock);
|
||||
s_adc_digi_arbiter_lock = NULL;
|
||||
}
|
||||
#endif
|
||||
adc_power_release();
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_digi_deinit();
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_controller_config(const adc_digi_config_t *config)
|
||||
{
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
esp_err_t err;
|
||||
if (s_adc_digi_arbiter_lock == NULL) {
|
||||
if (config->dig_clk.use_apll) {
|
||||
err = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "adc_dma", &s_adc_digi_arbiter_lock);
|
||||
} else {
|
||||
err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "adc_dma", &s_adc_digi_arbiter_lock);
|
||||
}
|
||||
if (err != ESP_OK) {
|
||||
s_adc_digi_arbiter_lock = NULL;
|
||||
ESP_LOGE(ADC_TAG, "ADC-DMA pm lock error");
|
||||
return err;
|
||||
}
|
||||
}
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
|
||||
if (config->conv_mode & ADC_CONV_SINGLE_UNIT_1) {
|
||||
for (int i = 0; i < config->adc1_pattern_len; i++) {
|
||||
adc_cal_offset(ADC_NUM_1, config->adc1_pattern[i].channel, config->adc1_pattern[i].atten);
|
||||
}
|
||||
}
|
||||
if (config->conv_mode & ADC_CONV_SINGLE_UNIT_2) {
|
||||
for (int i = 0; i < config->adc2_pattern_len; i++) {
|
||||
adc_cal_offset(ADC_NUM_2, config->adc2_pattern[i].channel, config->adc2_pattern[i].atten);
|
||||
}
|
||||
}
|
||||
|
||||
/* If enable digtal controller, adc xpd should always on. */
|
||||
adc_power_acquire();
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_digi_controller_config(config);
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_arbiter_config(adc_unit_t adc_unit, adc_arbiter_t *config)
|
||||
{
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_arbiter_config(config);
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set ADC module controller.
|
||||
* There are five SAR ADC controllers:
|
||||
* Two digital controller: Continuous conversion mode (DMA). High performance with multiple channel scan modes;
|
||||
* Two RTC controller: Single conversion modes (Polling). For low power purpose working during deep sleep;
|
||||
* the other is dedicated for Power detect (PWDET / PKDET), Only support ADC2.
|
||||
* Config monitor of adc digital controller.
|
||||
*
|
||||
* @note Only ADC2 support arbiter to switch controllers automatically. Access to the ADC is based on the priority of the controller.
|
||||
* @note For ADC1, Controller access is mutually exclusive.
|
||||
*
|
||||
* @param adc_unit ADC unit.
|
||||
* @param ctrl ADC controller, Refer to `adc_ll_controller_t`.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* @note The monitor will monitor all the enabled channel data of the each ADC unit at the same time.
|
||||
* @param adc_n ADC unit.
|
||||
* @param config Refer to ``adc_digi_monitor_t``.
|
||||
*/
|
||||
esp_err_t adc_set_controller(adc_unit_t adc_unit, adc_ll_controller_t ctrl)
|
||||
static void adc_digi_monitor_config(adc_ll_num_t adc_n, adc_digi_monitor_t *config)
|
||||
{
|
||||
adc_arbiter_t config = {0};
|
||||
adc_arbiter_t cfg = ADC_ARBITER_CONFIG_DEFAULT();
|
||||
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
adc_hal_set_controller(ADC_NUM_1, ctrl);
|
||||
}
|
||||
if (adc_unit & ADC_UNIT_2) {
|
||||
adc_hal_set_controller(ADC_NUM_2, ctrl);
|
||||
switch (ctrl) {
|
||||
case ADC2_CTRL_FORCE_PWDET:
|
||||
config.pwdet_pri = 2;
|
||||
config.mode = ADC_ARB_MODE_SHIELD;
|
||||
adc_hal_arbiter_config(&config);
|
||||
adc_hal_set_controller(ADC_NUM_2, ADC2_CTRL_PWDET);
|
||||
break;
|
||||
case ADC2_CTRL_FORCE_RTC:
|
||||
config.rtc_pri = 2;
|
||||
config.mode = ADC_ARB_MODE_SHIELD;
|
||||
adc_hal_arbiter_config(&config);
|
||||
adc_hal_set_controller(ADC_NUM_2, ADC_CTRL_RTC);
|
||||
break;
|
||||
case ADC2_CTRL_FORCE_ULP:
|
||||
config.rtc_pri = 2;
|
||||
config.mode = ADC_ARB_MODE_SHIELD;
|
||||
adc_hal_arbiter_config(&config);
|
||||
adc_hal_set_controller(ADC_NUM_2, ADC_CTRL_ULP);
|
||||
break;
|
||||
case ADC2_CTRL_FORCE_DIG:
|
||||
config.dig_pri = 2;
|
||||
config.mode = ADC_ARB_MODE_SHIELD;
|
||||
adc_hal_arbiter_config(&config);
|
||||
adc_hal_set_controller(ADC_NUM_2, ADC_CTRL_DIG);
|
||||
break;
|
||||
default:
|
||||
adc_hal_arbiter_config(&cfg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_start(void)
|
||||
{
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
ADC_CHECK((s_adc_digi_arbiter_lock), "Should start after call `adc_digi_controller_config`", ESP_FAIL);
|
||||
esp_pm_lock_acquire(s_adc_digi_arbiter_lock);
|
||||
#endif
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_digi_enable();
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_stop(void)
|
||||
{
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
if (s_adc_digi_arbiter_lock) {
|
||||
esp_pm_lock_release(s_adc_digi_arbiter_lock);
|
||||
}
|
||||
#endif
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_digi_disable();
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset FSM of adc digital controller.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_reset(void)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_digi_reset();
|
||||
adc_hal_digi_clear_pattern_table(ADC_NUM_1);
|
||||
adc_hal_digi_clear_pattern_table(ADC_NUM_2);
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
adc_ll_digi_monitor_set_mode(adc_n, config->mode);
|
||||
adc_ll_digi_monitor_set_thres(adc_n, config->threshold);
|
||||
}
|
||||
|
||||
/*************************************/
|
||||
@ -244,9 +39,9 @@ esp_err_t adc_digi_filter_reset(adc_digi_filter_idx_t idx)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
if (idx == ADC_DIGI_FILTER_IDX0) {
|
||||
adc_hal_digi_filter_reset(ADC_NUM_1);
|
||||
adc_ll_digi_filter_reset(ADC_NUM_1);
|
||||
} else if (idx == ADC_DIGI_FILTER_IDX1) {
|
||||
adc_hal_digi_filter_reset(ADC_NUM_2);
|
||||
adc_ll_digi_filter_reset(ADC_NUM_2);
|
||||
}
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
@ -256,9 +51,9 @@ esp_err_t adc_digi_filter_set_config(adc_digi_filter_idx_t idx, adc_digi_filter_
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
if (idx == ADC_DIGI_FILTER_IDX0) {
|
||||
adc_hal_digi_filter_set_factor(ADC_NUM_1, config->mode);
|
||||
adc_ll_digi_filter_set_factor(ADC_NUM_1, config->mode);
|
||||
} else if (idx == ADC_DIGI_FILTER_IDX1) {
|
||||
adc_hal_digi_filter_set_factor(ADC_NUM_2, config->mode);
|
||||
adc_ll_digi_filter_set_factor(ADC_NUM_2, config->mode);
|
||||
}
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
@ -270,11 +65,11 @@ esp_err_t adc_digi_filter_get_config(adc_digi_filter_idx_t idx, adc_digi_filter_
|
||||
if (idx == ADC_DIGI_FILTER_IDX0) {
|
||||
config->adc_unit = ADC_UNIT_1;
|
||||
config->channel = ADC_CHANNEL_MAX;
|
||||
adc_hal_digi_filter_get_factor(ADC_NUM_1, &config->mode);
|
||||
adc_ll_digi_filter_get_factor(ADC_NUM_1, &config->mode);
|
||||
} else if (idx == ADC_DIGI_FILTER_IDX1) {
|
||||
config->adc_unit = ADC_UNIT_2;
|
||||
config->channel = ADC_CHANNEL_MAX;
|
||||
adc_hal_digi_filter_get_factor(ADC_NUM_2, &config->mode);
|
||||
adc_ll_digi_filter_get_factor(ADC_NUM_2, &config->mode);
|
||||
}
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
@ -284,9 +79,9 @@ esp_err_t adc_digi_filter_enable(adc_digi_filter_idx_t idx, bool enable)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
if (idx == ADC_DIGI_FILTER_IDX0) {
|
||||
adc_hal_digi_filter_enable(ADC_NUM_1, enable);
|
||||
adc_ll_digi_filter_enable(ADC_NUM_1, enable);
|
||||
} else if (idx == ADC_DIGI_FILTER_IDX1) {
|
||||
adc_hal_digi_filter_enable(ADC_NUM_2, enable);
|
||||
adc_ll_digi_filter_enable(ADC_NUM_2, enable);
|
||||
}
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
@ -303,9 +98,9 @@ esp_err_t adc_digi_filter_enable(adc_digi_filter_idx_t idx, bool enable)
|
||||
int adc_digi_filter_read_data(adc_digi_filter_idx_t idx)
|
||||
{
|
||||
if (idx == ADC_DIGI_FILTER_IDX0) {
|
||||
return adc_hal_digi_filter_read_data(ADC_NUM_1);
|
||||
return adc_ll_digi_filter_read_data(ADC_NUM_1);
|
||||
} else if (idx == ADC_DIGI_FILTER_IDX1) {
|
||||
return adc_hal_digi_filter_read_data(ADC_NUM_2);
|
||||
return adc_ll_digi_filter_read_data(ADC_NUM_2);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
@ -319,9 +114,9 @@ esp_err_t adc_digi_monitor_set_config(adc_digi_monitor_idx_t idx, adc_digi_monit
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
if (idx == ADC_DIGI_MONITOR_IDX0) {
|
||||
adc_hal_digi_monitor_config(ADC_NUM_1, config);
|
||||
adc_digi_monitor_config(ADC_NUM_1, config);
|
||||
} else if (idx == ADC_DIGI_MONITOR_IDX1) {
|
||||
adc_hal_digi_monitor_config(ADC_NUM_2, config);
|
||||
adc_digi_monitor_config(ADC_NUM_2, config);
|
||||
}
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
@ -331,148 +126,10 @@ esp_err_t adc_digi_monitor_enable(adc_digi_monitor_idx_t idx, bool enable)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
if (idx == ADC_DIGI_MONITOR_IDX0) {
|
||||
adc_hal_digi_monitor_enable(ADC_NUM_1, enable);
|
||||
adc_ll_digi_monitor_enable(ADC_NUM_1, enable);
|
||||
} else if (idx == ADC_DIGI_MONITOR_IDX1) {
|
||||
adc_hal_digi_monitor_enable(ADC_NUM_2, enable);
|
||||
adc_ll_digi_monitor_enable(ADC_NUM_2, enable);
|
||||
}
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
/* Digital controller intr setting */
|
||||
/**************************************/
|
||||
|
||||
esp_err_t adc_digi_intr_enable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
adc_hal_digi_intr_enable(ADC_NUM_1, intr_mask);
|
||||
}
|
||||
if (adc_unit & ADC_UNIT_2) {
|
||||
adc_hal_digi_intr_enable(ADC_NUM_2, intr_mask);
|
||||
}
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_intr_disable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
adc_hal_digi_intr_disable(ADC_NUM_1, intr_mask);
|
||||
}
|
||||
if (adc_unit & ADC_UNIT_2) {
|
||||
adc_hal_digi_intr_disable(ADC_NUM_2, intr_mask);
|
||||
}
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_intr_clear(adc_unit_t adc_unit, adc_digi_intr_t intr_mask)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
adc_hal_digi_intr_clear(ADC_NUM_1, intr_mask);
|
||||
}
|
||||
if (adc_unit & ADC_UNIT_2) {
|
||||
adc_hal_digi_intr_clear(ADC_NUM_2, intr_mask);
|
||||
}
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
uint32_t adc_digi_intr_get_status(adc_unit_t adc_unit)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
ADC_ENTER_CRITICAL();
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
ret = adc_hal_digi_get_intr_status(ADC_NUM_1);
|
||||
}
|
||||
if (adc_unit & ADC_UNIT_2) {
|
||||
ret = adc_hal_digi_get_intr_status(ADC_NUM_2);
|
||||
}
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint8_t s_isr_registered = 0;
|
||||
static intr_handle_t s_adc_isr_handle = NULL;
|
||||
|
||||
esp_err_t adc_digi_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags)
|
||||
{
|
||||
ADC_CHECK((fn != NULL), "Parameter error", ESP_ERR_INVALID_ARG);
|
||||
ADC_CHECK(s_isr_registered == 0, "ADC ISR have installed, can not install again", ESP_FAIL);
|
||||
|
||||
esp_err_t ret = esp_intr_alloc(ETS_APB_ADC_INTR_SOURCE, intr_alloc_flags, fn, arg, &s_adc_isr_handle);
|
||||
if (ret == ESP_OK) {
|
||||
s_isr_registered = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_isr_deregister(void)
|
||||
{
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
if (s_isr_registered) {
|
||||
ret = esp_intr_free(s_adc_isr_handle);
|
||||
if (ret == ESP_OK) {
|
||||
s_isr_registered = 0;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
RTC controller setting
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Calibration
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
static uint16_t s_adc_cali_param[ADC_NUM_MAX][ADC_ATTEN_MAX] = { {0}, {0} };
|
||||
|
||||
//NOTE: according to calibration version, different types of lock may be taken during the process:
|
||||
// 1. Semaphore when reading efuse
|
||||
// 2. Spinlock when actually doing ADC calibration
|
||||
//This function shoudn't be called inside critical section or ISR
|
||||
uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten)
|
||||
{
|
||||
#ifdef CONFIG_IDF_ENV_FPGA
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
if (s_adc_cali_param[adc_n][atten]) {
|
||||
ESP_LOGV(ADC_TAG, "Use calibrated val ADC%d atten=%d: %04X", adc_n, atten, s_adc_cali_param[adc_n][atten]);
|
||||
return (uint32_t)s_adc_cali_param[adc_n][atten];
|
||||
}
|
||||
|
||||
uint32_t dout = 0;
|
||||
// check if we can fetch the values from eFuse.
|
||||
int version = esp_efuse_rtc_table_read_calib_version();
|
||||
if (version == 2) {
|
||||
int tag = esp_efuse_rtc_table_get_tag(version, adc_n + 1, atten, RTCCALIB_V2_PARAM_VINIT);
|
||||
dout = esp_efuse_rtc_table_get_parsed_efuse_value(tag, false);
|
||||
} else {
|
||||
adc_power_acquire();
|
||||
ADC_ENTER_CRITICAL();
|
||||
const bool internal_gnd = true;
|
||||
dout = adc_hal_self_calibration(adc_n, channel, atten, internal_gnd);
|
||||
ADC_EXIT_CRITICAL();
|
||||
adc_power_release();
|
||||
}
|
||||
ESP_LOGD(ADC_TAG, "Calib(V%d) ADC%d atten=%d: %04X", version, adc_n, atten, dout);
|
||||
s_adc_cali_param[adc_n][atten] = (uint16_t)dout;
|
||||
return dout;
|
||||
}
|
||||
|
||||
esp_err_t adc_cal_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten)
|
||||
{
|
||||
adc_hal_calibration_init(adc_n);
|
||||
uint32_t cal_val = adc_get_calibration_offset(adc_n, channel, atten);
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_set_calibration_param(adc_n, cal_val);
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
@ -1,247 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "driver/adc_common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Common setting
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Config ADC module arbiter.
|
||||
* The arbiter is to improve the use efficiency of ADC2. After the control right is robbed by the high priority,
|
||||
* the low priority controller will read the invalid ADC2 data, and the validity of the data can be judged by the flag bit in the data.
|
||||
*
|
||||
* @note Only ADC2 support arbiter.
|
||||
* @note Default priority: Wi-Fi > RTC > Digital;
|
||||
* @note In normal use, there is no need to call this interface to config arbiter.
|
||||
*
|
||||
* @param adc_unit ADC unit.
|
||||
* @param config Refer to `adc_arbiter_t`.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_NOT_SUPPORTED ADC unit not support arbiter.
|
||||
*/
|
||||
esp_err_t adc_arbiter_config(adc_unit_t adc_unit, adc_arbiter_t *config);
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Digital controller setting
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Enable digital controller to trigger the measurement.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_start(void);
|
||||
|
||||
/**
|
||||
* @brief Disable digital controller to trigger the measurement.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_stop(void);
|
||||
|
||||
/*************************************/
|
||||
/* Digital controller filter setting */
|
||||
/*************************************/
|
||||
/**
|
||||
* @brief Reset adc digital controller filter.
|
||||
*
|
||||
* @param idx Filter index.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_filter_reset(adc_digi_filter_idx_t idx);
|
||||
|
||||
/**
|
||||
* @brief Set adc digital controller filter configuration.
|
||||
*
|
||||
* @note For ESP32S2, Filter IDX0/IDX1 can only be used to filter all enabled channels of ADC1/ADC2 unit at the same time.
|
||||
*
|
||||
* @param idx Filter index.
|
||||
* @param config See ``adc_digi_filter_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_filter_set_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config);
|
||||
|
||||
/**
|
||||
* @brief Get adc digital controller filter configuration.
|
||||
*
|
||||
* @note For ESP32S2, Filter IDX0/IDX1 can only be used to filter all enabled channels of ADC1/ADC2 unit at the same time.
|
||||
*
|
||||
* @param idx Filter index.
|
||||
* @param config See ``adc_digi_filter_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_filter_get_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config);
|
||||
|
||||
/**
|
||||
* @brief Enable/disable adc digital controller filter.
|
||||
* Filtering the ADC data to obtain smooth data at higher sampling rates.
|
||||
*
|
||||
* @note For ESP32S2, Filter IDX0/IDX1 can only be used to filter all enabled channels of ADC1/ADC2 unit at the same time.
|
||||
*
|
||||
* @param idx Filter index.
|
||||
* @param enable Enable/Disable filter.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_filter_enable(adc_digi_filter_idx_t idx, bool enable);
|
||||
|
||||
/**************************************/
|
||||
/* Digital controller monitor setting */
|
||||
/**************************************/
|
||||
|
||||
/**
|
||||
* @brief Config monitor of adc digital controller.
|
||||
*
|
||||
* @note For ESP32S2, The monitor will monitor all the enabled channel data of the each ADC unit at the same time.
|
||||
*
|
||||
* @param idx Monitor index.
|
||||
* @param config See ``adc_digi_monitor_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_monitor_set_config(adc_digi_monitor_idx_t idx, adc_digi_monitor_t *config);
|
||||
|
||||
/**
|
||||
* @brief Enable/disable monitor of adc digital controller.
|
||||
*
|
||||
* @note For ESP32S2, The monitor will monitor all the enabled channel data of the each ADC unit at the same time.
|
||||
*
|
||||
* @param idx Monitor index.
|
||||
* @param enable True or false enable monitor.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_monitor_enable(adc_digi_monitor_idx_t idx, bool enable);
|
||||
|
||||
/**************************************/
|
||||
/* Digital controller intr setting */
|
||||
/**************************************/
|
||||
|
||||
/**
|
||||
* @brief Enable interrupt of adc digital controller by bitmask.
|
||||
*
|
||||
* @param adc_unit ADC unit.
|
||||
* @param intr_mask Interrupt bitmask. See ``adc_digi_intr_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_intr_enable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask);
|
||||
|
||||
/**
|
||||
* @brief Disable interrupt of adc digital controller by bitmask.
|
||||
*
|
||||
* @param adc_unit ADC unit.
|
||||
* @param intr_mask Interrupt bitmask. See ``adc_digi_intr_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_intr_disable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask);
|
||||
|
||||
/**
|
||||
* @brief Clear interrupt of adc digital controller by bitmask.
|
||||
*
|
||||
* @param adc_unit ADC unit.
|
||||
* @param intr_mask Interrupt bitmask. See ``adc_digi_intr_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_intr_clear(adc_unit_t adc_unit, adc_digi_intr_t intr_mask);
|
||||
|
||||
/**
|
||||
* @brief Get interrupt status mask of adc digital controller.
|
||||
*
|
||||
* @param adc_unit ADC unit.
|
||||
* @return
|
||||
* - intr Interrupt bitmask, See ``adc_digi_intr_t``.
|
||||
*/
|
||||
uint32_t adc_digi_intr_get_status(adc_unit_t adc_unit);
|
||||
|
||||
/**
|
||||
* @brief Register ADC interrupt handler, the handler is an ISR.
|
||||
* The handler will be attached to the same CPU core that this function is running on.
|
||||
*
|
||||
* @param fn Interrupt handler function.
|
||||
* @param arg Parameter for handler function
|
||||
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
|
||||
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_NOT_FOUND Can not find the interrupt that matches the flags.
|
||||
* - ESP_ERR_INVALID_ARG Function pointer error.
|
||||
*/
|
||||
esp_err_t adc_digi_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags);
|
||||
|
||||
/**
|
||||
* @brief Deregister ADC interrupt handler, the handler is an ISR.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG hander error.
|
||||
* - ESP_FAIL ISR not be registered.
|
||||
*/
|
||||
esp_err_t adc_digi_isr_deregister(void);
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
RTC controller setting
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Deprecated API
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Set I2S data source
|
||||
*
|
||||
* @param src I2S DMA data source, I2S DMA can get data from digital signals or from ADC.
|
||||
*
|
||||
* @deprecated The ESP32S2 don't use I2S DMA. Call ``adc_digi_controller_config`` instead.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
*/
|
||||
esp_err_t adc_set_i2s_data_source(adc_i2s_source_t src) __attribute__((deprecated));
|
||||
|
||||
/**
|
||||
* @brief Initialize I2S ADC mode
|
||||
*
|
||||
* @param adc_unit ADC unit index
|
||||
* @param channel ADC channel index
|
||||
*
|
||||
* @deprecated The ESP32S2 don't use I2S DMA. Call ``adc_digi_controller_config`` instead.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel) __attribute__((deprecated));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,10 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "driver/adc_common.h"
|
||||
// This file will be removed. TODO: IDF-1776
|
@ -1,93 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "driver/adc_common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Common setting
|
||||
---------------------------------------------------------------*/
|
||||
/*************************************/
|
||||
/* Digital controller filter setting */
|
||||
/*************************************/
|
||||
/**
|
||||
* @brief Reset adc digital controller filter.
|
||||
*
|
||||
* @param idx Filter index.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_filter_reset(adc_digi_filter_idx_t idx);
|
||||
|
||||
/**
|
||||
* @brief Set adc digital controller filter configuration.
|
||||
*
|
||||
* @param idx Filter index.
|
||||
* @param config See ``adc_digi_filter_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_filter_set_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config);
|
||||
|
||||
/**
|
||||
* @brief Get adc digital controller filter configuration.
|
||||
*
|
||||
* @param idx Filter index.
|
||||
* @param config See ``adc_digi_filter_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_filter_get_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config);
|
||||
|
||||
/**
|
||||
* @brief Enable/disable adc digital controller filter.
|
||||
* Filtering the ADC data to obtain smooth data at higher sampling rates.
|
||||
*
|
||||
* @param idx Filter index.
|
||||
* @param enable Enable/Disable filter.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_filter_enable(adc_digi_filter_idx_t idx, bool enable);
|
||||
|
||||
/**************************************/
|
||||
/* Digital controller monitor setting */
|
||||
/**************************************/
|
||||
|
||||
/**
|
||||
* @brief Config monitor of adc digital controller.
|
||||
*
|
||||
* @param idx Monitor index.
|
||||
* @param config See ``adc_digi_monitor_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_monitor_set_config(adc_digi_monitor_idx_t idx, adc_digi_monitor_t *config);
|
||||
|
||||
/**
|
||||
* @brief Enable/disable monitor of adc digital controller.
|
||||
*
|
||||
* @param idx Monitor index.
|
||||
* @param enable True or false enable monitor.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_monitor_enable(adc_digi_monitor_idx_t idx, bool enable);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -8,7 +8,6 @@
|
||||
#include <stdbool.h>
|
||||
#include <math.h>
|
||||
#include <esp_types.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
646
components/driver/include/driver/adc.h
Normal file
646
components/driver/include/driver/adc.h
Normal file
@ -0,0 +1,646 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "esp_err.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "hal/adc_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/**** `adc1_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/
|
||||
typedef enum {
|
||||
ADC1_CHANNEL_0 = 0, /*!< ADC1 channel 0 is GPIO36 */
|
||||
ADC1_CHANNEL_1, /*!< ADC1 channel 1 is GPIO37 */
|
||||
ADC1_CHANNEL_2, /*!< ADC1 channel 2 is GPIO38 */
|
||||
ADC1_CHANNEL_3, /*!< ADC1 channel 3 is GPIO39 */
|
||||
ADC1_CHANNEL_4, /*!< ADC1 channel 4 is GPIO32 */
|
||||
ADC1_CHANNEL_5, /*!< ADC1 channel 5 is GPIO33 */
|
||||
ADC1_CHANNEL_6, /*!< ADC1 channel 6 is GPIO34 */
|
||||
ADC1_CHANNEL_7, /*!< ADC1 channel 7 is GPIO35 */
|
||||
ADC1_CHANNEL_MAX,
|
||||
} adc1_channel_t;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 // TODO ESP32-S3 channels are wrong IDF-1776
|
||||
/**** `adc1_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/
|
||||
typedef enum {
|
||||
ADC1_CHANNEL_0 = 0, /*!< ADC1 channel 0 is GPIO1 */
|
||||
ADC1_CHANNEL_1, /*!< ADC1 channel 1 is GPIO2 */
|
||||
ADC1_CHANNEL_2, /*!< ADC1 channel 2 is GPIO3 */
|
||||
ADC1_CHANNEL_3, /*!< ADC1 channel 3 is GPIO4 */
|
||||
ADC1_CHANNEL_4, /*!< ADC1 channel 4 is GPIO5 */
|
||||
ADC1_CHANNEL_5, /*!< ADC1 channel 5 is GPIO6 */
|
||||
ADC1_CHANNEL_6, /*!< ADC1 channel 6 is GPIO7 */
|
||||
ADC1_CHANNEL_7, /*!< ADC1 channel 7 is GPIO8 */
|
||||
ADC1_CHANNEL_8, /*!< ADC1 channel 8 is GPIO9 */
|
||||
ADC1_CHANNEL_9, /*!< ADC1 channel 9 is GPIO10 */
|
||||
ADC1_CHANNEL_MAX,
|
||||
} adc1_channel_t;
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684
|
||||
/**** `adc1_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/
|
||||
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_MAX,
|
||||
} adc1_channel_t;
|
||||
#endif // CONFIG_IDF_TARGET_*
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 // TODO ESP32-S3 channels are wrong IDF-1776
|
||||
/**** `adc2_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/
|
||||
typedef enum {
|
||||
ADC2_CHANNEL_0 = 0, /*!< ADC2 channel 0 is GPIO4 (ESP32), GPIO11 (ESP32-S2) */
|
||||
ADC2_CHANNEL_1, /*!< ADC2 channel 1 is GPIO0 (ESP32), GPIO12 (ESP32-S2) */
|
||||
ADC2_CHANNEL_2, /*!< ADC2 channel 2 is GPIO2 (ESP32), GPIO13 (ESP32-S2) */
|
||||
ADC2_CHANNEL_3, /*!< ADC2 channel 3 is GPIO15 (ESP32), GPIO14 (ESP32-S2) */
|
||||
ADC2_CHANNEL_4, /*!< ADC2 channel 4 is GPIO13 (ESP32), GPIO15 (ESP32-S2) */
|
||||
ADC2_CHANNEL_5, /*!< ADC2 channel 5 is GPIO12 (ESP32), GPIO16 (ESP32-S2) */
|
||||
ADC2_CHANNEL_6, /*!< ADC2 channel 6 is GPIO14 (ESP32), GPIO17 (ESP32-S2) */
|
||||
ADC2_CHANNEL_7, /*!< ADC2 channel 7 is GPIO27 (ESP32), GPIO18 (ESP32-S2) */
|
||||
ADC2_CHANNEL_8, /*!< ADC2 channel 8 is GPIO25 (ESP32), GPIO19 (ESP32-S2) */
|
||||
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_ESP32H2 || CONFIG_IDF_TARGET_ESP8684
|
||||
/**** `adc2_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/
|
||||
typedef enum {
|
||||
ADC2_CHANNEL_0 = 0, /*!< ADC2 channel 0 is GPIO5 */
|
||||
ADC2_CHANNEL_MAX,
|
||||
} adc2_channel_t;
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @brief ADC rtc controller attenuation option.
|
||||
*
|
||||
* @note This definitions are only for being back-compatible
|
||||
*/
|
||||
#define ADC_ATTEN_0db ADC_ATTEN_DB_0
|
||||
#define ADC_ATTEN_2_5db ADC_ATTEN_DB_2_5
|
||||
#define ADC_ATTEN_6db ADC_ATTEN_DB_6
|
||||
#define ADC_ATTEN_11db ADC_ATTEN_DB_11
|
||||
|
||||
/**
|
||||
* The default (max) bit width of the ADC of current version. You can also get the maximum bitwidth
|
||||
* by `SOC_ADC_MAX_BITWIDTH` defined in soc_caps.h.
|
||||
*/
|
||||
#define ADC_WIDTH_BIT_DEFAULT (ADC_WIDTH_MAX-1)
|
||||
|
||||
//this definitions are only for being back-compatible
|
||||
#define ADC_WIDTH_9Bit ADC_WIDTH_BIT_9
|
||||
#define ADC_WIDTH_10Bit ADC_WIDTH_BIT_10
|
||||
#define ADC_WIDTH_11Bit ADC_WIDTH_BIT_11
|
||||
#define ADC_WIDTH_12Bit ADC_WIDTH_BIT_12
|
||||
|
||||
/**
|
||||
* @brief ADC digital controller encode option.
|
||||
*
|
||||
* @deprecated The ESP32-S2 doesn't use I2S DMA. Call ``adc_digi_output_format_t`` instead.
|
||||
*/
|
||||
typedef enum {
|
||||
ADC_ENCODE_12BIT, /*!< ADC to DMA data format, , [15:12]-channel [11:0]-12 bits ADC data */
|
||||
ADC_ENCODE_11BIT, /*!< ADC to DMA data format, [15]-unit, [14:11]-channel [10:0]-11 bits ADC data */
|
||||
ADC_ENCODE_MAX,
|
||||
} adc_i2s_encode_t;
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Common setting
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Enable ADC power
|
||||
* @deprecated Use adc_power_acquire and adc_power_release instead.
|
||||
*/
|
||||
void adc_power_on(void) __attribute__((deprecated));
|
||||
|
||||
/**
|
||||
* @brief Power off SAR ADC
|
||||
* @deprecated Use adc_power_acquire and adc_power_release instead.
|
||||
* This function will force power down for ADC.
|
||||
* This function is deprecated because forcing power ADC power off may
|
||||
* disrupt operation of other components which may be using the ADC.
|
||||
*/
|
||||
void adc_power_off(void) __attribute__((deprecated));
|
||||
|
||||
/**
|
||||
* @brief Increment the usage counter for ADC module.
|
||||
* ADC will stay powered on while the counter is greater than 0.
|
||||
* Call adc_power_release when done using the ADC.
|
||||
*/
|
||||
void adc_power_acquire(void);
|
||||
|
||||
/**
|
||||
* @brief Decrement the usage counter for ADC module.
|
||||
* ADC will stay powered on while the counter is greater than 0.
|
||||
* Call this function when done using the ADC.
|
||||
*/
|
||||
void adc_power_release(void);
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
ADC Single Read Setting
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Get the GPIO number of a specific ADC1 channel.
|
||||
*
|
||||
* @param channel Channel to get the GPIO number
|
||||
* @param gpio_num output buffer to hold the GPIO number
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if success
|
||||
* - ESP_ERR_INVALID_ARG if channel not valid
|
||||
*/
|
||||
esp_err_t adc1_pad_get_io_num(adc1_channel_t channel, gpio_num_t *gpio_num);
|
||||
|
||||
/**
|
||||
* @brief Set the attenuation of a particular channel on ADC1, and configure its associated GPIO pin mux.
|
||||
*
|
||||
* The default ADC voltage is for attenuation 0 dB and listed in the table below.
|
||||
* By setting higher attenuation it is possible to read higher voltages.
|
||||
*
|
||||
* Due to ADC characteristics, most accurate results are obtained within the "suggested range"
|
||||
* shown in the following table.
|
||||
*
|
||||
* +----------+-------------+-----------------+
|
||||
* | | attenuation | suggested range |
|
||||
* | SoC | (dB) | (mV) |
|
||||
* +==========+=============+=================+
|
||||
* | | 0 | 100 ~ 950 |
|
||||
* | +-------------+-----------------+
|
||||
* | | 2.5 | 100 ~ 1250 |
|
||||
* | ESP32 +-------------+-----------------+
|
||||
* | | 6 | 150 ~ 1750 |
|
||||
* | +-------------+-----------------+
|
||||
* | | 11 | 150 ~ 2450 |
|
||||
* +----------+-------------+-----------------+
|
||||
* | | 0 | 0 ~ 750 |
|
||||
* | +-------------+-----------------+
|
||||
* | | 2.5 | 0 ~ 1050 |
|
||||
* | ESP32-S2 +-------------+-----------------+
|
||||
* | | 6 | 0 ~ 1300 |
|
||||
* | +-------------+-----------------+
|
||||
* | | 11 | 0 ~ 2500 |
|
||||
* +----------+-------------+-----------------+
|
||||
*
|
||||
* For maximum accuracy, use the ADC calibration APIs and measure voltages within these recommended ranges.
|
||||
*
|
||||
* @note For any given channel, this function must be called before the first time ``adc1_get_raw()`` is called for that channel.
|
||||
*
|
||||
* @note This function can be called multiple times to configure multiple
|
||||
* ADC channels simultaneously. You may call ``adc1_get_raw()`` only after configuring a channel.
|
||||
*
|
||||
* @param channel ADC1 channel to configure
|
||||
* @param atten Attenuation level
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten);
|
||||
|
||||
/**
|
||||
* @brief Configure ADC1 capture width, meanwhile enable output invert for ADC1.
|
||||
* The configuration is for all channels of ADC1
|
||||
* @param width_bit Bit capture width for ADC1
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t adc1_config_width(adc_bits_width_t width_bit);
|
||||
|
||||
/**
|
||||
* @brief Take an ADC1 reading from a single channel.
|
||||
* @note ESP32:
|
||||
* When the power switch of SARADC1, SARADC2, HALL sensor and AMP sensor is turned on,
|
||||
* the input of GPIO36 and GPIO39 will be pulled down for about 80ns.
|
||||
* When enabling power for any of these peripherals, ignore input from GPIO36 and GPIO39.
|
||||
* Please refer to section 3.11 of 'ECO_and_Workarounds_for_Bugs_in_ESP32' for the description of this issue.
|
||||
* As a workaround, call adc_power_acquire() in the app. This will result in higher power consumption (by ~1mA),
|
||||
* but will remove the glitches on GPIO36 and GPIO39.
|
||||
*
|
||||
* @note Call ``adc1_config_width()`` before the first time this
|
||||
* function is called.
|
||||
*
|
||||
* @note For any given channel, adc1_config_channel_atten(channel)
|
||||
* must be called before the first time this function is called. Configuring
|
||||
* a new channel does not prevent a previously configured channel from being read.
|
||||
*
|
||||
* @param channel ADC1 channel to read
|
||||
*
|
||||
* @return
|
||||
* - -1: Parameter error
|
||||
* - Other: ADC1 channel reading.
|
||||
*/
|
||||
int adc1_get_raw(adc1_channel_t channel);
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
//TODO IDF-3610, replace these with proper caps
|
||||
/**
|
||||
* @brief Set ADC data invert
|
||||
* @param adc_unit ADC unit index
|
||||
* @param inv_en whether enable data invert
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t adc_set_data_inv(adc_unit_t adc_unit, bool inv_en);
|
||||
|
||||
/**
|
||||
* @brief Set ADC source clock
|
||||
* @param clk_div ADC clock divider, ADC clock is divided from APB clock
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
*/
|
||||
esp_err_t adc_set_clk_div(uint8_t clk_div);
|
||||
|
||||
/**
|
||||
* @brief Configure ADC capture width.
|
||||
*
|
||||
* @param adc_unit ADC unit index
|
||||
* @param width_bit Bit capture width for ADC unit.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t adc_set_data_width(adc_unit_t adc_unit, adc_bits_width_t width_bit);
|
||||
|
||||
/**
|
||||
* @brief Configure ADC1 to be usable by the ULP
|
||||
*
|
||||
* This function reconfigures ADC1 to be controlled by the ULP.
|
||||
* Effect of this function can be reverted using ``adc1_get_raw()`` function.
|
||||
*
|
||||
* Note that adc1_config_channel_atten, ``adc1_config_width()`` functions need
|
||||
* to be called to configure ADC1 channels, before ADC1 is used by the ULP.
|
||||
*/
|
||||
void adc1_ulp_enable(void);
|
||||
#endif //#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
|
||||
/**
|
||||
* @brief Get the GPIO number of a specific ADC2 channel.
|
||||
*
|
||||
* @param channel Channel to get the GPIO number
|
||||
*
|
||||
* @param gpio_num output buffer to hold the GPIO number
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if success
|
||||
* - ESP_ERR_INVALID_ARG if channel not valid
|
||||
*/
|
||||
esp_err_t adc2_pad_get_io_num(adc2_channel_t channel, gpio_num_t *gpio_num);
|
||||
|
||||
/**
|
||||
* @brief Configure the ADC2 channel, including setting attenuation.
|
||||
*
|
||||
* The default ADC voltage is for attenuation 0 dB and listed in the table below.
|
||||
* By setting higher attenuation it is possible to read higher voltages.
|
||||
*
|
||||
* Due to ADC characteristics, most accurate results are obtained within the "suggested range"
|
||||
* shown in the following table.
|
||||
*
|
||||
* +----------+-------------+-----------------+
|
||||
* | | attenuation | suggested range |
|
||||
* | SoC | (dB) | (mV) |
|
||||
* +==========+=============+=================+
|
||||
* | | 0 | 100 ~ 950 |
|
||||
* | +-------------+-----------------+
|
||||
* | | 2.5 | 100 ~ 1250 |
|
||||
* | ESP32 +-------------+-----------------+
|
||||
* | | 6 | 150 ~ 1750 |
|
||||
* | +-------------+-----------------+
|
||||
* | | 11 | 150 ~ 2450 |
|
||||
* +----------+-------------+-----------------+
|
||||
* | | 0 | 0 ~ 750 |
|
||||
* | +-------------+-----------------+
|
||||
* | | 2.5 | 0 ~ 1050 |
|
||||
* | ESP32-S2 +-------------+-----------------+
|
||||
* | | 6 | 0 ~ 1300 |
|
||||
* | +-------------+-----------------+
|
||||
* | | 11 | 0 ~ 2500 |
|
||||
* +----------+-------------+-----------------+
|
||||
*
|
||||
* For maximum accuracy, use the ADC calibration APIs and measure voltages within these recommended ranges.
|
||||
*
|
||||
* @note This function also configures the input GPIO pin mux to
|
||||
* connect it to the ADC2 channel. It must be called before calling
|
||||
* ``adc2_get_raw()`` for this channel.
|
||||
*
|
||||
* @note For any given channel, this function must be called before the first time ``adc2_get_raw()`` is called for that channel.
|
||||
*
|
||||
* @param channel ADC2 channel to configure
|
||||
* @param atten Attenuation level
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten);
|
||||
|
||||
/**
|
||||
* @brief Take an ADC2 reading on a single channel
|
||||
*
|
||||
* @note ESP32:
|
||||
* When the power switch of SARADC1, SARADC2, HALL sensor and AMP sensor is turned on,
|
||||
* the input of GPIO36 and GPIO39 will be pulled down for about 80ns.
|
||||
* When enabling power for any of these peripherals, ignore input from GPIO36 and GPIO39.
|
||||
* Please refer to section 3.11 of 'ECO_and_Workarounds_for_Bugs_in_ESP32' for the description of this issue.
|
||||
* As a workaround, call adc_power_acquire() in the app. This will result in higher power consumption (by ~1mA),
|
||||
* but will remove the glitches on GPIO36 and GPIO39.
|
||||
*
|
||||
*
|
||||
* @note ESP32:
|
||||
* For a given channel, ``adc2_config_channel_atten()``
|
||||
* must be called before the first time this function is called. If Wi-Fi is started via ``esp_wifi_start()``, this
|
||||
* function will always fail with ``ESP_ERR_TIMEOUT``.
|
||||
*
|
||||
* @note ESP32-S2:
|
||||
* ADC2 support hardware arbiter. The arbiter is to improve the use efficiency of ADC2. After the control right is robbed by the high priority,
|
||||
* the low priority controller will read the invalid ADC2 data. Default priority: Wi-Fi > RTC > Digital;
|
||||
*
|
||||
* @param channel ADC2 channel to read
|
||||
* @param width_bit Bit capture width for ADC2
|
||||
* @param raw_out the variable to hold the output data.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if success
|
||||
* - ESP_ERR_TIMEOUT ADC2 is being used by other controller and the request timed out.
|
||||
* - ESP_ERR_INVALID_STATE The controller status is invalid. Please try again.
|
||||
*/
|
||||
esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *raw_out);
|
||||
|
||||
/**
|
||||
* @brief Output ADC1 or ADC2's reference voltage to ``adc2_channe_t``'s IO.
|
||||
*
|
||||
* 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_unit ADC unit index
|
||||
* @param[in] gpio GPIO number (Only ADC2's channels IO are supported)
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: v_ref successfully routed to selected GPIO
|
||||
* - ESP_ERR_INVALID_ARG: Unsupported GPIO
|
||||
*/
|
||||
esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio);
|
||||
|
||||
/**
|
||||
* @brief Output ADC2 reference voltage to ``adc2_channe_t``'s IO.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @deprecated Use ``adc_vref_to_gpio`` instead.
|
||||
*
|
||||
* @param[in] gpio GPIO number (ADC2's channels are supported)
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: v_ref successfully routed to selected GPIO
|
||||
* - ESP_ERR_INVALID_ARG: Unsupported GPIO
|
||||
*/
|
||||
esp_err_t adc2_vref_to_gpio(gpio_num_t gpio) __attribute__((deprecated));
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
DMA setting
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Digital ADC DMA read max timeout value, it may make the ``adc_digi_read_bytes`` block forever if the OS supports
|
||||
*/
|
||||
#define ADC_MAX_DELAY UINT32_MAX
|
||||
|
||||
/**
|
||||
* @brief ADC DMA driver configuration
|
||||
*/
|
||||
typedef struct adc_digi_init_config_s {
|
||||
uint32_t max_store_buf_size; ///< Max length of the converted data that driver can store before they are processed.
|
||||
uint32_t conv_num_each_intr; ///< Bytes of data that can be converted in 1 interrupt.
|
||||
uint32_t adc1_chan_mask; ///< Channel list of ADC1 to be initialized.
|
||||
uint32_t adc2_chan_mask; ///< Channel list of ADC2 to be initialized.
|
||||
} adc_digi_init_config_t;
|
||||
|
||||
/**
|
||||
* @brief ADC digital controller settings
|
||||
*/
|
||||
typedef struct {
|
||||
bool conv_limit_en; ///< To limit ADC conversion times. Conversion stops after finishing `conv_limit_num` times conversion
|
||||
uint32_t conv_limit_num; ///< Set the upper limit of the number of ADC conversion triggers. Range: 1 ~ 255.
|
||||
uint32_t pattern_num; ///< Number of ADC channels that will be used
|
||||
adc_digi_pattern_config_t *adc_pattern; ///< List of configs for each ADC channel that will be used
|
||||
uint32_t sample_freq_hz; /*!< The expected ADC sampling frequency in Hz. Range: 611Hz ~ 83333Hz
|
||||
Fs = Fd / interval / 2
|
||||
Fs: sampling frequency;
|
||||
Fd: digital controller frequency, no larger than 5M for better performance
|
||||
interval: interval between 2 measurement trigger signal, the smallest interval should not be smaller than the ADC measurement period, the largest interval should not be larger than 4095 */
|
||||
adc_digi_convert_mode_t conv_mode; ///< ADC DMA conversion mode, see `adc_digi_convert_mode_t`.
|
||||
adc_digi_output_format_t format; ///< ADC DMA conversion output format, see `adc_digi_output_format_t`.
|
||||
} adc_digi_configuration_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize the Digital ADC.
|
||||
*
|
||||
* @param init_config Pointer to Digital ADC initilization config. Refer to ``adc_digi_init_config_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
|
||||
* - ESP_ERR_NOT_FOUND No free interrupt found with the specified flags
|
||||
* - ESP_ERR_NO_MEM If out of memory
|
||||
* - ESP_OK On success
|
||||
*/
|
||||
esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config);
|
||||
|
||||
/**
|
||||
* @brief Read bytes from Digital ADC through DMA.
|
||||
*
|
||||
* @param[out] buf Buffer to read from ADC.
|
||||
* @param[in] length_max Expected length of data read from the ADC.
|
||||
* @param[out] out_length Real length of data read from the ADC via this API.
|
||||
* @param[in] timeout_ms Time to wait for data via this API, in millisecond.
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_STATE Driver state is invalid. Usually it means the ADC sampling rate is faster than the task processing rate.
|
||||
* - ESP_ERR_TIMEOUT Operation timed out
|
||||
* - ESP_OK On success
|
||||
*/
|
||||
esp_err_t adc_digi_read_bytes(uint8_t *buf, uint32_t length_max, uint32_t *out_length, uint32_t timeout_ms);
|
||||
|
||||
/**
|
||||
* @brief Start the Digital ADC and DMA peripherals. After this, the hardware starts working.
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_STATE Driver state is invalid.
|
||||
* - ESP_OK On success
|
||||
*/
|
||||
esp_err_t adc_digi_start(void);
|
||||
|
||||
/**
|
||||
* @brief Stop the Digital ADC and DMA peripherals. After this, the hardware stops working.
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_STATE Driver state is invalid.
|
||||
* - ESP_OK On success
|
||||
*/
|
||||
esp_err_t adc_digi_stop(void);
|
||||
|
||||
/**
|
||||
* @brief Deinitialize the Digital ADC.
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_STATE Driver state is invalid.
|
||||
* - ESP_OK On success
|
||||
*/
|
||||
esp_err_t adc_digi_deinitialize(void);
|
||||
|
||||
/**
|
||||
* @brief Setting the digital controller.
|
||||
*
|
||||
* @param config Pointer to digital controller paramter. Refer to ``adc_digi_config_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_STATE Driver state is invalid.
|
||||
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
|
||||
* - ESP_OK On success
|
||||
*/
|
||||
esp_err_t adc_digi_controller_configure(const adc_digi_configuration_t *config);
|
||||
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
|
||||
//TODO IDF-3610
|
||||
/**
|
||||
* @brief Reset adc digital controller filter.
|
||||
*
|
||||
* @param idx Filter index.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_filter_reset(adc_digi_filter_idx_t idx);
|
||||
|
||||
/**
|
||||
* @brief Set adc digital controller filter configuration.
|
||||
*
|
||||
* @note For ESP32S2, Filter IDX0/IDX1 can only be used to filter all enabled channels of ADC1/ADC2 unit at the same time.
|
||||
*
|
||||
* @param idx Filter index.
|
||||
* @param config See ``adc_digi_filter_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_filter_set_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config);
|
||||
|
||||
/**
|
||||
* @brief Get adc digital controller filter configuration.
|
||||
*
|
||||
* @note For ESP32S2, Filter IDX0/IDX1 can only be used to filter all enabled channels of ADC1/ADC2 unit at the same time.
|
||||
*
|
||||
* @param idx Filter index.
|
||||
* @param config See ``adc_digi_filter_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_filter_get_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config);
|
||||
|
||||
/**
|
||||
* @brief Enable/disable adc digital controller filter.
|
||||
* Filtering the ADC data to obtain smooth data at higher sampling rates.
|
||||
*
|
||||
* @note For ESP32S2, Filter IDX0/IDX1 can only be used to filter all enabled channels of ADC1/ADC2 unit at the same time.
|
||||
*
|
||||
* @param idx Filter index.
|
||||
* @param enable Enable/Disable filter.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_filter_enable(adc_digi_filter_idx_t idx, bool enable);
|
||||
|
||||
/**
|
||||
* @brief Config monitor of adc digital controller.
|
||||
*
|
||||
* @note For ESP32S2, The monitor will monitor all the enabled channel data of the each ADC unit at the same time.
|
||||
*
|
||||
* @param idx Monitor index.
|
||||
* @param config See ``adc_digi_monitor_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_monitor_set_config(adc_digi_monitor_idx_t idx, adc_digi_monitor_t *config);
|
||||
|
||||
/**
|
||||
* @brief Enable/disable monitor of adc digital controller.
|
||||
*
|
||||
* @note For ESP32S2, The monitor will monitor all the enabled channel data of the each ADC unit at the same time.
|
||||
*
|
||||
* @param idx Monitor index.
|
||||
* @param enable True or false enable monitor.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_monitor_enable(adc_digi_monitor_idx_t idx, bool enable);
|
||||
#endif //#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
//TODO IDF-3610
|
||||
/**
|
||||
* @brief Read Hall Sensor
|
||||
*
|
||||
* @note When the power switch of SARADC1, SARADC2, HALL sensor and AMP sensor is turned on,
|
||||
* the input of GPIO36 and GPIO39 will be pulled down for about 80ns.
|
||||
* When enabling power for any of these peripherals, ignore input from GPIO36 and GPIO39.
|
||||
* Please refer to section 3.11 of 'ECO_and_Workarounds_for_Bugs_in_ESP32' for the description of this issue.
|
||||
*
|
||||
* @note The Hall Sensor uses channels 0 and 3 of ADC1. Do not configure
|
||||
* these channels for use as ADC channels.
|
||||
*
|
||||
* @note The ADC1 module must be enabled by calling
|
||||
* adc1_config_width() before calling hall_sensor_read(). ADC1
|
||||
* should be configured for 12 bit readings, as the hall sensor
|
||||
* readings are low values and do not cover the full range of the
|
||||
* ADC.
|
||||
*
|
||||
* @return The hall sensor reading.
|
||||
*/
|
||||
int hall_sensor_read(void);
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
To Be Deprecated TODO: IDF-3610
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Set I2S data source
|
||||
* @param src I2S DMA data source, I2S DMA can get data from digital signals or from ADC.
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
*/
|
||||
esp_err_t adc_set_i2s_data_source(adc_i2s_source_t src);
|
||||
|
||||
/**
|
||||
* @brief Initialize I2S ADC mode
|
||||
* @param adc_unit ADC unit index
|
||||
* @param channel ADC channel index
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,544 +1,11 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "esp_err.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "hal/adc_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/**** `adc1_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/
|
||||
typedef enum {
|
||||
ADC1_CHANNEL_0 = 0, /*!< ADC1 channel 0 is GPIO36 */
|
||||
ADC1_CHANNEL_1, /*!< ADC1 channel 1 is GPIO37 */
|
||||
ADC1_CHANNEL_2, /*!< ADC1 channel 2 is GPIO38 */
|
||||
ADC1_CHANNEL_3, /*!< ADC1 channel 3 is GPIO39 */
|
||||
ADC1_CHANNEL_4, /*!< ADC1 channel 4 is GPIO32 */
|
||||
ADC1_CHANNEL_5, /*!< ADC1 channel 5 is GPIO33 */
|
||||
ADC1_CHANNEL_6, /*!< ADC1 channel 6 is GPIO34 */
|
||||
ADC1_CHANNEL_7, /*!< ADC1 channel 7 is GPIO35 */
|
||||
ADC1_CHANNEL_MAX,
|
||||
} adc1_channel_t;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 // TODO ESP32-S3 channels are wrong IDF-1776
|
||||
/**** `adc1_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/
|
||||
typedef enum {
|
||||
ADC1_CHANNEL_0 = 0, /*!< ADC1 channel 0 is GPIO1 */
|
||||
ADC1_CHANNEL_1, /*!< ADC1 channel 1 is GPIO2 */
|
||||
ADC1_CHANNEL_2, /*!< ADC1 channel 2 is GPIO3 */
|
||||
ADC1_CHANNEL_3, /*!< ADC1 channel 3 is GPIO4 */
|
||||
ADC1_CHANNEL_4, /*!< ADC1 channel 4 is GPIO5 */
|
||||
ADC1_CHANNEL_5, /*!< ADC1 channel 5 is GPIO6 */
|
||||
ADC1_CHANNEL_6, /*!< ADC1 channel 6 is GPIO7 */
|
||||
ADC1_CHANNEL_7, /*!< ADC1 channel 7 is GPIO8 */
|
||||
ADC1_CHANNEL_8, /*!< ADC1 channel 8 is GPIO9 */
|
||||
ADC1_CHANNEL_9, /*!< ADC1 channel 9 is GPIO10 */
|
||||
ADC1_CHANNEL_MAX,
|
||||
} adc1_channel_t;
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684
|
||||
/**** `adc1_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/
|
||||
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_MAX,
|
||||
} adc1_channel_t;
|
||||
#endif // CONFIG_IDF_TARGET_*
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 // TODO ESP32-S3 channels are wrong IDF-1776
|
||||
/**** `adc2_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/
|
||||
typedef enum {
|
||||
ADC2_CHANNEL_0 = 0, /*!< ADC2 channel 0 is GPIO4 (ESP32), GPIO11 (ESP32-S2) */
|
||||
ADC2_CHANNEL_1, /*!< ADC2 channel 1 is GPIO0 (ESP32), GPIO12 (ESP32-S2) */
|
||||
ADC2_CHANNEL_2, /*!< ADC2 channel 2 is GPIO2 (ESP32), GPIO13 (ESP32-S2) */
|
||||
ADC2_CHANNEL_3, /*!< ADC2 channel 3 is GPIO15 (ESP32), GPIO14 (ESP32-S2) */
|
||||
ADC2_CHANNEL_4, /*!< ADC2 channel 4 is GPIO13 (ESP32), GPIO15 (ESP32-S2) */
|
||||
ADC2_CHANNEL_5, /*!< ADC2 channel 5 is GPIO12 (ESP32), GPIO16 (ESP32-S2) */
|
||||
ADC2_CHANNEL_6, /*!< ADC2 channel 6 is GPIO14 (ESP32), GPIO17 (ESP32-S2) */
|
||||
ADC2_CHANNEL_7, /*!< ADC2 channel 7 is GPIO27 (ESP32), GPIO18 (ESP32-S2) */
|
||||
ADC2_CHANNEL_8, /*!< ADC2 channel 8 is GPIO25 (ESP32), GPIO19 (ESP32-S2) */
|
||||
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_ESP32H2 || CONFIG_IDF_TARGET_ESP8684
|
||||
/**** `adc2_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/
|
||||
typedef enum {
|
||||
ADC2_CHANNEL_0 = 0, /*!< ADC2 channel 0 is GPIO5 */
|
||||
ADC2_CHANNEL_MAX,
|
||||
} adc2_channel_t;
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @brief ADC rtc controller attenuation option.
|
||||
*
|
||||
* @note This definitions are only for being back-compatible
|
||||
* This file is only a wrapper for `driver/adc.h` for back-compatability.
|
||||
*/
|
||||
#define ADC_ATTEN_0db ADC_ATTEN_DB_0
|
||||
#define ADC_ATTEN_2_5db ADC_ATTEN_DB_2_5
|
||||
#define ADC_ATTEN_6db ADC_ATTEN_DB_6
|
||||
#define ADC_ATTEN_11db ADC_ATTEN_DB_11
|
||||
|
||||
/**
|
||||
* The default (max) bit width of the ADC of current version. You can also get the maximum bitwidth
|
||||
* by `SOC_ADC_MAX_BITWIDTH` defined in soc_caps.h.
|
||||
*/
|
||||
#define ADC_WIDTH_BIT_DEFAULT (ADC_WIDTH_MAX-1)
|
||||
|
||||
//this definitions are only for being back-compatible
|
||||
#define ADC_WIDTH_9Bit ADC_WIDTH_BIT_9
|
||||
#define ADC_WIDTH_10Bit ADC_WIDTH_BIT_10
|
||||
#define ADC_WIDTH_11Bit ADC_WIDTH_BIT_11
|
||||
#define ADC_WIDTH_12Bit ADC_WIDTH_BIT_12
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684
|
||||
/**
|
||||
* @brief Digital ADC DMA read max timeout value, it may make the ``adc_digi_read_bytes`` block forever if the OS supports
|
||||
*/
|
||||
#define ADC_MAX_DELAY UINT32_MAX
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ADC digital controller encode option.
|
||||
*
|
||||
* @deprecated The ESP32-S2 doesn't use I2S DMA. Call ``adc_digi_output_format_t`` instead.
|
||||
*/
|
||||
typedef enum {
|
||||
ADC_ENCODE_12BIT, /*!< ADC to DMA data format, , [15:12]-channel [11:0]-12 bits ADC data */
|
||||
ADC_ENCODE_11BIT, /*!< ADC to DMA data format, [15]-unit, [14:11]-channel [10:0]-11 bits ADC data */
|
||||
ADC_ENCODE_MAX,
|
||||
} adc_i2s_encode_t;
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684
|
||||
//This feature is currently supported on ESP32C3, will be supported on other chips soon
|
||||
/**
|
||||
* @brief Digital ADC DMA configuration
|
||||
*/
|
||||
typedef struct adc_digi_init_config_s {
|
||||
uint32_t max_store_buf_size; ///< Max length of the converted data that driver can store before they are processed.
|
||||
uint32_t conv_num_each_intr; ///< Bytes of data that can be converted in 1 interrupt.
|
||||
uint32_t adc1_chan_mask; ///< Channel list of ADC1 to be initialized.
|
||||
uint32_t adc2_chan_mask; ///< Channel list of ADC2 to be initialized.
|
||||
} adc_digi_init_config_t;
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Common setting
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Enable ADC power
|
||||
* @deprecated Use adc_power_acquire and adc_power_release instead.
|
||||
*/
|
||||
void adc_power_on(void) __attribute__((deprecated));
|
||||
|
||||
/**
|
||||
* @brief Power off SAR ADC
|
||||
* @deprecated Use adc_power_acquire and adc_power_release instead.
|
||||
* This function will force power down for ADC.
|
||||
* This function is deprecated because forcing power ADC power off may
|
||||
* disrupt operation of other components which may be using the ADC.
|
||||
*/
|
||||
void adc_power_off(void) __attribute__((deprecated));
|
||||
|
||||
/**
|
||||
* @brief Increment the usage counter for ADC module.
|
||||
* ADC will stay powered on while the counter is greater than 0.
|
||||
* Call adc_power_release when done using the ADC.
|
||||
*/
|
||||
void adc_power_acquire(void);
|
||||
|
||||
/**
|
||||
* @brief Decrement the usage counter for ADC module.
|
||||
* ADC will stay powered on while the counter is greater than 0.
|
||||
* Call this function when done using the ADC.
|
||||
*/
|
||||
void adc_power_release(void);
|
||||
|
||||
#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP8684
|
||||
/**
|
||||
* @brief Initialize ADC pad
|
||||
* @param adc_unit ADC unit index
|
||||
* @param channel ADC channel index
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t adc_gpio_init(adc_unit_t adc_unit, adc_channel_t channel);
|
||||
#endif //#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP8684
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
ADC Single Read Setting
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Get the GPIO number of a specific ADC1 channel.
|
||||
*
|
||||
* @param channel Channel to get the GPIO number
|
||||
* @param gpio_num output buffer to hold the GPIO number
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if success
|
||||
* - ESP_ERR_INVALID_ARG if channel not valid
|
||||
*/
|
||||
esp_err_t adc1_pad_get_io_num(adc1_channel_t channel, gpio_num_t *gpio_num);
|
||||
|
||||
/**
|
||||
* @brief Set the attenuation of a particular channel on ADC1, and configure its associated GPIO pin mux.
|
||||
*
|
||||
* The default ADC voltage is for attenuation 0 dB and listed in the table below.
|
||||
* By setting higher attenuation it is possible to read higher voltages.
|
||||
*
|
||||
* Due to ADC characteristics, most accurate results are obtained within the "suggested range"
|
||||
* shown in the following table.
|
||||
*
|
||||
* +----------+-------------+-----------------+
|
||||
* | | attenuation | suggested range |
|
||||
* | SoC | (dB) | (mV) |
|
||||
* +==========+=============+=================+
|
||||
* | | 0 | 100 ~ 950 |
|
||||
* | +-------------+-----------------+
|
||||
* | | 2.5 | 100 ~ 1250 |
|
||||
* | ESP32 +-------------+-----------------+
|
||||
* | | 6 | 150 ~ 1750 |
|
||||
* | +-------------+-----------------+
|
||||
* | | 11 | 150 ~ 2450 |
|
||||
* +----------+-------------+-----------------+
|
||||
* | | 0 | 0 ~ 750 |
|
||||
* | +-------------+-----------------+
|
||||
* | | 2.5 | 0 ~ 1050 |
|
||||
* | ESP32-S2 +-------------+-----------------+
|
||||
* | | 6 | 0 ~ 1300 |
|
||||
* | +-------------+-----------------+
|
||||
* | | 11 | 0 ~ 2500 |
|
||||
* +----------+-------------+-----------------+
|
||||
*
|
||||
* For maximum accuracy, use the ADC calibration APIs and measure voltages within these recommended ranges.
|
||||
*
|
||||
* @note For any given channel, this function must be called before the first time ``adc1_get_raw()`` is called for that channel.
|
||||
*
|
||||
* @note This function can be called multiple times to configure multiple
|
||||
* ADC channels simultaneously. You may call ``adc1_get_raw()`` only after configuring a channel.
|
||||
*
|
||||
* @param channel ADC1 channel to configure
|
||||
* @param atten Attenuation level
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten);
|
||||
|
||||
/**
|
||||
* @brief Configure ADC1 capture width, meanwhile enable output invert for ADC1.
|
||||
* The configuration is for all channels of ADC1
|
||||
* @param width_bit Bit capture width for ADC1
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t adc1_config_width(adc_bits_width_t width_bit);
|
||||
|
||||
/**
|
||||
* @brief Take an ADC1 reading from a single channel.
|
||||
* @note ESP32:
|
||||
* When the power switch of SARADC1, SARADC2, HALL sensor and AMP sensor is turned on,
|
||||
* the input of GPIO36 and GPIO39 will be pulled down for about 80ns.
|
||||
* When enabling power for any of these peripherals, ignore input from GPIO36 and GPIO39.
|
||||
* Please refer to section 3.11 of 'ECO_and_Workarounds_for_Bugs_in_ESP32' for the description of this issue.
|
||||
* As a workaround, call adc_power_acquire() in the app. This will result in higher power consumption (by ~1mA),
|
||||
* but will remove the glitches on GPIO36 and GPIO39.
|
||||
*
|
||||
* @note Call ``adc1_config_width()`` before the first time this
|
||||
* function is called.
|
||||
*
|
||||
* @note For any given channel, adc1_config_channel_atten(channel)
|
||||
* must be called before the first time this function is called. Configuring
|
||||
* a new channel does not prevent a previously configured channel from being read.
|
||||
*
|
||||
* @param channel ADC1 channel to read
|
||||
*
|
||||
* @return
|
||||
* - -1: Parameter error
|
||||
* - Other: ADC1 channel reading.
|
||||
*/
|
||||
int adc1_get_raw(adc1_channel_t channel);
|
||||
|
||||
#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP8684
|
||||
/**
|
||||
* @brief Set ADC data invert
|
||||
* @param adc_unit ADC unit index
|
||||
* @param inv_en whether enable data invert
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t adc_set_data_inv(adc_unit_t adc_unit, bool inv_en);
|
||||
|
||||
/**
|
||||
* @brief Set ADC source clock
|
||||
* @param clk_div ADC clock divider, ADC clock is divided from APB clock
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
*/
|
||||
esp_err_t adc_set_clk_div(uint8_t clk_div);
|
||||
|
||||
/**
|
||||
* @brief Configure ADC capture width.
|
||||
*
|
||||
* @param adc_unit ADC unit index
|
||||
* @param width_bit Bit capture width for ADC unit.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t adc_set_data_width(adc_unit_t adc_unit, adc_bits_width_t width_bit);
|
||||
|
||||
/**
|
||||
* @brief Configure ADC1 to be usable by the ULP
|
||||
*
|
||||
* This function reconfigures ADC1 to be controlled by the ULP.
|
||||
* Effect of this function can be reverted using ``adc1_get_raw()`` function.
|
||||
*
|
||||
* Note that adc1_config_channel_atten, ``adc1_config_width()`` functions need
|
||||
* to be called to configure ADC1 channels, before ADC1 is used by the ULP.
|
||||
*/
|
||||
void adc1_ulp_enable(void);
|
||||
#endif //#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP8684
|
||||
|
||||
/**
|
||||
* @brief Get the GPIO number of a specific ADC2 channel.
|
||||
*
|
||||
* @param channel Channel to get the GPIO number
|
||||
*
|
||||
* @param gpio_num output buffer to hold the GPIO number
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if success
|
||||
* - ESP_ERR_INVALID_ARG if channel not valid
|
||||
*/
|
||||
esp_err_t adc2_pad_get_io_num(adc2_channel_t channel, gpio_num_t *gpio_num);
|
||||
|
||||
/**
|
||||
* @brief Configure the ADC2 channel, including setting attenuation.
|
||||
*
|
||||
* The default ADC voltage is for attenuation 0 dB and listed in the table below.
|
||||
* By setting higher attenuation it is possible to read higher voltages.
|
||||
*
|
||||
* Due to ADC characteristics, most accurate results are obtained within the "suggested range"
|
||||
* shown in the following table.
|
||||
*
|
||||
* +----------+-------------+-----------------+
|
||||
* | | attenuation | suggested range |
|
||||
* | SoC | (dB) | (mV) |
|
||||
* +==========+=============+=================+
|
||||
* | | 0 | 100 ~ 950 |
|
||||
* | +-------------+-----------------+
|
||||
* | | 2.5 | 100 ~ 1250 |
|
||||
* | ESP32 +-------------+-----------------+
|
||||
* | | 6 | 150 ~ 1750 |
|
||||
* | +-------------+-----------------+
|
||||
* | | 11 | 150 ~ 2450 |
|
||||
* +----------+-------------+-----------------+
|
||||
* | | 0 | 0 ~ 750 |
|
||||
* | +-------------+-----------------+
|
||||
* | | 2.5 | 0 ~ 1050 |
|
||||
* | ESP32-S2 +-------------+-----------------+
|
||||
* | | 6 | 0 ~ 1300 |
|
||||
* | +-------------+-----------------+
|
||||
* | | 11 | 0 ~ 2500 |
|
||||
* +----------+-------------+-----------------+
|
||||
*
|
||||
* For maximum accuracy, use the ADC calibration APIs and measure voltages within these recommended ranges.
|
||||
*
|
||||
* @note This function also configures the input GPIO pin mux to
|
||||
* connect it to the ADC2 channel. It must be called before calling
|
||||
* ``adc2_get_raw()`` for this channel.
|
||||
*
|
||||
* @note For any given channel, this function must be called before the first time ``adc2_get_raw()`` is called for that channel.
|
||||
*
|
||||
* @param channel ADC2 channel to configure
|
||||
* @param atten Attenuation level
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten);
|
||||
|
||||
/**
|
||||
* @brief Take an ADC2 reading on a single channel
|
||||
*
|
||||
* @note ESP32:
|
||||
* When the power switch of SARADC1, SARADC2, HALL sensor and AMP sensor is turned on,
|
||||
* the input of GPIO36 and GPIO39 will be pulled down for about 80ns.
|
||||
* When enabling power for any of these peripherals, ignore input from GPIO36 and GPIO39.
|
||||
* Please refer to section 3.11 of 'ECO_and_Workarounds_for_Bugs_in_ESP32' for the description of this issue.
|
||||
* As a workaround, call adc_power_acquire() in the app. This will result in higher power consumption (by ~1mA),
|
||||
* but will remove the glitches on GPIO36 and GPIO39.
|
||||
*
|
||||
*
|
||||
* @note ESP32:
|
||||
* For a given channel, ``adc2_config_channel_atten()``
|
||||
* must be called before the first time this function is called. If Wi-Fi is started via ``esp_wifi_start()``, this
|
||||
* function will always fail with ``ESP_ERR_TIMEOUT``.
|
||||
*
|
||||
* @note ESP32-S2:
|
||||
* ADC2 support hardware arbiter. The arbiter is to improve the use efficiency of ADC2. After the control right is robbed by the high priority,
|
||||
* the low priority controller will read the invalid ADC2 data. Default priority: Wi-Fi > RTC > Digital;
|
||||
*
|
||||
* @param channel ADC2 channel to read
|
||||
* @param width_bit Bit capture width for ADC2
|
||||
* @param raw_out the variable to hold the output data.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if success
|
||||
* - ESP_ERR_TIMEOUT ADC2 is being used by other controller and the request timed out.
|
||||
* - ESP_ERR_INVALID_STATE The controller status is invalid. Please try again.
|
||||
*/
|
||||
esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *raw_out);
|
||||
|
||||
/**
|
||||
* @brief Output ADC1 or ADC2's reference voltage to ``adc2_channe_t``'s IO.
|
||||
*
|
||||
* 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_unit ADC unit index
|
||||
* @param[in] gpio GPIO number (Only ADC2's channels IO are supported)
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: v_ref successfully routed to selected GPIO
|
||||
* - ESP_ERR_INVALID_ARG: Unsupported GPIO
|
||||
*/
|
||||
esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio);
|
||||
|
||||
/**
|
||||
* @brief Output ADC2 reference voltage to ``adc2_channe_t``'s IO.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @deprecated Use ``adc_vref_to_gpio`` instead.
|
||||
*
|
||||
* @param[in] gpio GPIO number (ADC2's channels are supported)
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: v_ref successfully routed to selected GPIO
|
||||
* - ESP_ERR_INVALID_ARG: Unsupported GPIO
|
||||
*/
|
||||
esp_err_t adc2_vref_to_gpio(gpio_num_t gpio) __attribute__((deprecated));
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Digital controller setting
|
||||
---------------------------------------------------------------*/
|
||||
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
|
||||
//These APIs are only supported on ESP32 and ESP32-S2. On ESP32-C3 and later chips, please use ``adc_digi_initialize`` and ``adc_digi_deinitialize``
|
||||
/**
|
||||
* @brief ADC digital controller initialization.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_init(void);
|
||||
|
||||
/**
|
||||
* @brief ADC digital controller deinitialization.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_deinit(void);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Setting the digital controller.
|
||||
*
|
||||
* @param config Pointer to digital controller paramter. Refer to ``adc_digi_config_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_STATE Driver state is invalid.
|
||||
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
|
||||
* - ESP_OK On success
|
||||
*/
|
||||
esp_err_t adc_digi_controller_config(const adc_digi_config_t *config);
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684
|
||||
//This feature is currently supported on ESP32C3, will be supported on other chips soon
|
||||
/*---------------------------------------------------------------
|
||||
DMA setting
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Initialize the Digital ADC.
|
||||
*
|
||||
* @param init_config Pointer to Digital ADC initilization config. Refer to ``adc_digi_init_config_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
|
||||
* - ESP_ERR_NOT_FOUND No free interrupt found with the specified flags
|
||||
* - ESP_ERR_NO_MEM If out of memory
|
||||
* - ESP_OK On success
|
||||
*/
|
||||
esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config);
|
||||
|
||||
/**
|
||||
* @brief Start the Digital ADC and DMA peripherals. After this, the hardware starts working.
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_STATE Driver state is invalid.
|
||||
* - ESP_OK On success
|
||||
*/
|
||||
esp_err_t adc_digi_start(void);
|
||||
|
||||
/**
|
||||
* @brief Stop the Digital ADC and DMA peripherals. After this, the hardware stops working.
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_STATE Driver state is invalid.
|
||||
* - ESP_OK On success
|
||||
*/
|
||||
esp_err_t adc_digi_stop(void);
|
||||
|
||||
/**
|
||||
* @brief Read bytes from Digital ADC through DMA.
|
||||
*
|
||||
* @param[out] buf Buffer to read from ADC.
|
||||
* @param[in] length_max Expected length of data read from the ADC.
|
||||
* @param[out] out_length Real length of data read from the ADC via this API.
|
||||
* @param[in] timeout_ms Time to wait for data via this API, in millisecond.
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_STATE Driver state is invalid. Usually it means the ADC sampling rate is faster than the task processing rate.
|
||||
* - ESP_ERR_TIMEOUT Operation timed out
|
||||
* - ESP_OK On success
|
||||
*/
|
||||
esp_err_t adc_digi_read_bytes(uint8_t *buf, uint32_t length_max, uint32_t *out_length, uint32_t timeout_ms);
|
||||
|
||||
/**
|
||||
* @brief Deinitialize the Digital ADC.
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_STATE Driver state is invalid.
|
||||
* - ESP_OK On success
|
||||
*/
|
||||
esp_err_t adc_digi_deinitialize(void);
|
||||
|
||||
#endif //#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#include "adc.h"
|
||||
|
@ -110,7 +110,7 @@ bool spicommon_periph_in_use(spi_host_device_t host);
|
||||
bool spicommon_periph_free(spi_host_device_t host);
|
||||
|
||||
/**
|
||||
* @brief Alloc DMA for SPI Slave
|
||||
* @brief Alloc DMA for SPI
|
||||
*
|
||||
* @param host_id SPI host ID
|
||||
* @param dma_chan DMA channel to be used
|
||||
@ -122,17 +122,17 @@ bool spicommon_periph_free(spi_host_device_t host);
|
||||
* - ESP_ERR_NO_MEM: No enough memory
|
||||
* - ESP_ERR_NOT_FOUND: There is no available DMA channel
|
||||
*/
|
||||
esp_err_t spicommon_slave_dma_chan_alloc(spi_host_device_t host_id, spi_dma_chan_t dma_chan, uint32_t *out_actual_tx_dma_chan, uint32_t *out_actual_rx_dma_chan);
|
||||
esp_err_t spicommon_dma_chan_alloc(spi_host_device_t host_id, spi_dma_chan_t dma_chan, uint32_t *out_actual_tx_dma_chan, uint32_t *out_actual_rx_dma_chan);
|
||||
|
||||
/**
|
||||
* @brief Free DMA for SPI Slave
|
||||
* @brief Free DMA for SPI
|
||||
*
|
||||
* @param host_id SPI host ID
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: On success
|
||||
*/
|
||||
esp_err_t spicommon_slave_free_dma(spi_host_device_t host_id);
|
||||
esp_err_t spicommon_dma_chan_free(spi_host_device_t host_id);
|
||||
|
||||
/**
|
||||
* @brief Connect a SPI peripheral to GPIO pins
|
||||
|
@ -158,7 +158,7 @@ static inline periph_module_t get_dma_periph(int dma_chan)
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool spicommon_dma_chan_claim(int dma_chan, uint32_t *out_actual_dma_chan)
|
||||
static bool claim_dma_chan(int dma_chan, uint32_t *out_actual_dma_chan)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
@ -175,7 +175,7 @@ static bool spicommon_dma_chan_claim(int dma_chan, uint32_t *out_actual_dma_chan
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void spicommon_connect_spi_and_dma(spi_host_device_t host, int dma_chan)
|
||||
static void connect_spi_and_dma(spi_host_device_t host, int dma_chan)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
DPORT_SET_PERI_REG_BITS(DPORT_SPI_DMA_CHAN_SEL_REG, 3, dma_chan, (host * 2));
|
||||
@ -184,7 +184,7 @@ static void spicommon_connect_spi_and_dma(spi_host_device_t host, int dma_chan)
|
||||
#endif
|
||||
}
|
||||
|
||||
static esp_err_t spicommon_dma_chan_alloc(spi_host_device_t host_id, spi_dma_chan_t dma_chan, uint32_t *out_actual_tx_dma_chan, uint32_t *out_actual_rx_dma_chan)
|
||||
static esp_err_t alloc_dma_chan(spi_host_device_t host_id, spi_dma_chan_t dma_chan, uint32_t *out_actual_tx_dma_chan, uint32_t *out_actual_rx_dma_chan)
|
||||
{
|
||||
assert(is_valid_host(host_id));
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
@ -200,17 +200,17 @@ static esp_err_t spicommon_dma_chan_alloc(spi_host_device_t host_id, spi_dma_cha
|
||||
if (dma_chan == SPI_DMA_CH_AUTO) {
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
for (int i = 1; i < SOC_SPI_DMA_CHAN_NUM+1; i++) {
|
||||
success = spicommon_dma_chan_claim(i, &actual_dma_chan);
|
||||
success = claim_dma_chan(i, &actual_dma_chan);
|
||||
if (success) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
//On ESP32S2, each SPI controller has its own DMA channel
|
||||
success = spicommon_dma_chan_claim(host_id, &actual_dma_chan);
|
||||
success = claim_dma_chan(host_id, &actual_dma_chan);
|
||||
#endif //#if CONFIG_IDF_TARGET_XXX
|
||||
} else {
|
||||
success = spicommon_dma_chan_claim((int)dma_chan, &actual_dma_chan);
|
||||
success = claim_dma_chan((int)dma_chan, &actual_dma_chan);
|
||||
}
|
||||
|
||||
//On ESP32 and ESP32S2, actual_tx_dma_chan and actual_rx_dma_chan are always same
|
||||
@ -221,13 +221,13 @@ static esp_err_t spicommon_dma_chan_alloc(spi_host_device_t host_id, spi_dma_cha
|
||||
SPI_CHECK(false, "no available dma channel", ESP_ERR_NOT_FOUND);
|
||||
}
|
||||
|
||||
spicommon_connect_spi_and_dma(host_id, *out_actual_tx_dma_chan);
|
||||
connect_spi_and_dma(host_id, *out_actual_tx_dma_chan);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else //SOC_GDMA_SUPPORTED
|
||||
static esp_err_t spicommon_dma_chan_alloc(spi_host_device_t host_id, spi_dma_chan_t dma_chan, uint32_t *out_actual_tx_dma_chan, uint32_t *out_actual_rx_dma_chan)
|
||||
static esp_err_t alloc_dma_chan(spi_host_device_t host_id, spi_dma_chan_t dma_chan, uint32_t *out_actual_tx_dma_chan, uint32_t *out_actual_rx_dma_chan)
|
||||
{
|
||||
assert(is_valid_host(host_id));
|
||||
assert(dma_chan == SPI_DMA_CH_AUTO);
|
||||
@ -272,7 +272,7 @@ static esp_err_t spicommon_dma_chan_alloc(spi_host_device_t host_id, spi_dma_cha
|
||||
}
|
||||
#endif //#if !SOC_GDMA_SUPPORTED
|
||||
|
||||
esp_err_t spicommon_slave_dma_chan_alloc(spi_host_device_t host_id, spi_dma_chan_t dma_chan, uint32_t *out_actual_tx_dma_chan, uint32_t *out_actual_rx_dma_chan)
|
||||
esp_err_t spicommon_dma_chan_alloc(spi_host_device_t host_id, spi_dma_chan_t dma_chan, uint32_t *out_actual_tx_dma_chan, uint32_t *out_actual_rx_dma_chan)
|
||||
{
|
||||
assert(is_valid_host(host_id));
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
@ -292,7 +292,7 @@ esp_err_t spicommon_slave_dma_chan_alloc(spi_host_device_t host_id, spi_dma_chan
|
||||
bus_ctx[host_id] = ctx;
|
||||
ctx->host_id = host_id;
|
||||
|
||||
ret = spicommon_dma_chan_alloc(host_id, dma_chan, &actual_tx_dma_chan, &actual_rx_dma_chan);
|
||||
ret = alloc_dma_chan(host_id, dma_chan, &actual_tx_dma_chan, &actual_rx_dma_chan);
|
||||
if (ret != ESP_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
@ -310,7 +310,7 @@ cleanup:
|
||||
}
|
||||
|
||||
//----------------------------------------------------------free dma periph-------------------------------------------------------//
|
||||
static esp_err_t spicommon_dma_chan_free(spi_host_device_t host_id)
|
||||
static esp_err_t dma_chan_free(spi_host_device_t host_id)
|
||||
{
|
||||
assert(is_valid_host(host_id));
|
||||
|
||||
@ -339,11 +339,11 @@ static esp_err_t spicommon_dma_chan_free(spi_host_device_t host_id)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t spicommon_slave_free_dma(spi_host_device_t host_id)
|
||||
esp_err_t spicommon_dma_chan_free(spi_host_device_t host_id)
|
||||
{
|
||||
assert(is_valid_host(host_id));
|
||||
|
||||
esp_err_t ret = spicommon_dma_chan_free(host_id);
|
||||
esp_err_t ret = dma_chan_free(host_id);
|
||||
free(bus_ctx[host_id]);
|
||||
bus_ctx[host_id] = NULL;
|
||||
|
||||
@ -783,7 +783,7 @@ esp_err_t spi_bus_initialize(spi_host_device_t host_id, const spi_bus_config_t *
|
||||
if (dma_chan != SPI_DMA_DISABLED) {
|
||||
bus_attr->dma_enabled = 1;
|
||||
|
||||
err = spicommon_dma_chan_alloc(host_id, dma_chan, &actual_tx_dma_chan, &actual_rx_dma_chan);
|
||||
err = alloc_dma_chan(host_id, dma_chan, &actual_tx_dma_chan, &actual_rx_dma_chan);
|
||||
if (err != ESP_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
@ -844,7 +844,7 @@ cleanup:
|
||||
bus_attr->dmadesc_tx = NULL;
|
||||
bus_attr->dmadesc_rx = NULL;
|
||||
if (bus_attr->dma_enabled) {
|
||||
spicommon_dma_chan_free(host_id);
|
||||
dma_chan_free(host_id);
|
||||
}
|
||||
}
|
||||
spicommon_periph_free(host_id);
|
||||
@ -881,7 +881,7 @@ esp_err_t spi_bus_free(spi_host_device_t host_id)
|
||||
bus_attr->dmadesc_tx = NULL;
|
||||
bus_attr->dmadesc_rx = NULL;
|
||||
if (bus_attr->dma_enabled > 0) {
|
||||
spicommon_dma_chan_free(host_id);
|
||||
dma_chan_free(host_id);
|
||||
}
|
||||
spicommon_periph_free(host_id);
|
||||
free(ctx);
|
||||
|
@ -140,7 +140,7 @@ esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *b
|
||||
bool use_dma = (dma_chan != SPI_DMA_DISABLED);
|
||||
spihost[host]->dma_enabled = use_dma;
|
||||
if (use_dma) {
|
||||
ret = spicommon_slave_dma_chan_alloc(host, dma_chan, &actual_tx_dma_chan, &actual_rx_dma_chan);
|
||||
ret = spicommon_dma_chan_alloc(host, dma_chan, &actual_tx_dma_chan, &actual_rx_dma_chan);
|
||||
if (ret != ESP_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
@ -240,7 +240,7 @@ cleanup:
|
||||
}
|
||||
spi_slave_hal_deinit(&spihost[host]->hal);
|
||||
if (spihost[host]->dma_enabled) {
|
||||
spicommon_slave_free_dma(host);
|
||||
spicommon_dma_chan_free(host);
|
||||
}
|
||||
|
||||
free(spihost[host]);
|
||||
@ -257,7 +257,7 @@ esp_err_t spi_slave_free(spi_host_device_t host)
|
||||
if (spihost[host]->trans_queue) vQueueDelete(spihost[host]->trans_queue);
|
||||
if (spihost[host]->ret_queue) vQueueDelete(spihost[host]->ret_queue);
|
||||
if (spihost[host]->dma_enabled) {
|
||||
spicommon_slave_free_dma(host);
|
||||
spicommon_dma_chan_free(host);
|
||||
}
|
||||
free(spihost[host]->hal.dmadesc_tx);
|
||||
free(spihost[host]->hal.dmadesc_rx);
|
||||
|
@ -89,7 +89,7 @@ esp_err_t spi_slave_hd_init(spi_host_device_t host_id, const spi_bus_config_t *b
|
||||
host->dma_enabled = (config->dma_chan != SPI_DMA_DISABLED);
|
||||
|
||||
if (host->dma_enabled) {
|
||||
ret = spicommon_slave_dma_chan_alloc(host_id, config->dma_chan, &actual_tx_dma_chan, &actual_rx_dma_chan);
|
||||
ret = spicommon_dma_chan_alloc(host_id, config->dma_chan, &actual_tx_dma_chan, &actual_rx_dma_chan);
|
||||
if (ret != ESP_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
@ -241,7 +241,7 @@ esp_err_t spi_slave_hd_deinit(spi_host_device_t host_id)
|
||||
|
||||
spicommon_periph_free(host_id);
|
||||
if (host->dma_enabled) {
|
||||
spicommon_slave_free_dma(host_id);
|
||||
spicommon_dma_chan_free(host_id);
|
||||
}
|
||||
free(host);
|
||||
spihost[host_id] = NULL;
|
||||
|
@ -8,6 +8,10 @@
|
||||
Tests for the adc device driver on ESP32-S2 only
|
||||
*/
|
||||
#include "sdkconfig.h"
|
||||
#include "unity.h"
|
||||
#include "test_utils.h"
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2) //TODO: IDF-3160
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
|
||||
|
||||
@ -37,6 +41,10 @@
|
||||
#include "soc/lldesc.h"
|
||||
#include "test/test_adc_dac_dma.h"
|
||||
|
||||
#include "driver/adc_deprecated.h"
|
||||
#include "hal/adc_ll.h"
|
||||
#include "esp_pm.h"
|
||||
|
||||
static const char *TAG = "test_adc";
|
||||
|
||||
#define PLATFORM_SELECT (1) //0: pxp; 1: chip
|
||||
@ -83,7 +91,6 @@ static adc_channel_t adc_list[SOC_ADC_PATT_LEN_MAX] = {
|
||||
/* For ESP32S2, it should use same atten, or, it will have error. */
|
||||
#define TEST_ADC_ATTEN_DEFAULT (ADC_ATTEN_11db)
|
||||
|
||||
extern esp_err_t adc_digi_reset(void);
|
||||
|
||||
/* Work mode.
|
||||
* single: eof_num;
|
||||
@ -109,6 +116,20 @@ static lldesc_t dma2 = {0};
|
||||
static QueueHandle_t que_adc = NULL;
|
||||
static adc_dma_event_t adc_evt;
|
||||
|
||||
/**
|
||||
* @brief Reset FSM of adc digital controller.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
static esp_err_t adc_digi_reset(void)
|
||||
{
|
||||
adc_ll_digi_reset();
|
||||
adc_ll_digi_clear_pattern_table(ADC_NUM_1);
|
||||
adc_ll_digi_clear_pattern_table(ADC_NUM_2);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/** ADC-DMA ISR handler. */
|
||||
static IRAM_ATTR void adc_dma_isr(void *arg)
|
||||
{
|
||||
@ -630,3 +651,4 @@ TEST_CASE("test_adc_digi_slope_debug", "[adc_dma][ignore]")
|
||||
}
|
||||
|
||||
#endif // CONFIG_IDF_TARGET_ESP32S2
|
||||
#endif //#if !DISABLED_FOR_TARGETS(ESP32S2)
|
||||
|
@ -12,14 +12,15 @@
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP8684)
|
||||
// TODO: Support ADC IDF-3908
|
||||
#include "esp_adc_cal.h"
|
||||
#include "driver/adc_common.h"
|
||||
#include "driver/adc.h"
|
||||
|
||||
static const char *TAG = "ADC";
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32, ESP32S2, ESP32S3)
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32, ESP32S2, ESP32S3, ESP32C3) //TODO: IDF-3160
|
||||
//API only supported for C3 now.
|
||||
|
||||
#include "driver/adc.h"
|
||||
#include "esp_adc_cal.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#define TEST_COUNT 4096
|
||||
|
@ -7,7 +7,6 @@
|
||||
Tests for the adc2 device driver
|
||||
*/
|
||||
#include "esp_system.h"
|
||||
#include "driver/adc.h"
|
||||
#include "unity.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_event.h"
|
||||
@ -16,6 +15,7 @@
|
||||
#include "nvs_flash.h"
|
||||
#include "test_utils.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/adc.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/gpio.h"
|
||||
|
@ -15,9 +15,10 @@ int esp_efuse_rtc_calib_get_ver(void)
|
||||
return result;
|
||||
}
|
||||
|
||||
uint16_t esp_efuse_rtc_calib_get_init_code(int version, int atten)
|
||||
uint32_t esp_efuse_rtc_calib_get_init_code(int version, uint32_t adc_unit, int atten)
|
||||
{
|
||||
assert(version == 1);
|
||||
(void) adc_unit;
|
||||
const esp_efuse_desc_t** init_code_efuse;
|
||||
assert(atten < 4);
|
||||
if (atten == 0) {
|
||||
|
@ -11,6 +11,9 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//This is the ADC calibration value version burnt in efuse
|
||||
#define ESP_EFUSE_ADC_CALIB_VER 1
|
||||
|
||||
/**
|
||||
* @brief Get the RTC calibration efuse version
|
||||
*
|
||||
@ -21,11 +24,12 @@ int esp_efuse_rtc_calib_get_ver(void);
|
||||
/**
|
||||
* @brief Get the init code in the efuse, for the corresponding attenuation.
|
||||
*
|
||||
* @param version Version of the stored efuse
|
||||
* @param atten Attenuation of the init code
|
||||
* @param version Version of the stored efuse
|
||||
* @param adc_unit ADC unit. Not used, for compatibility. On esp32c3, for calibration v1, both ADC units use the same init code (calibrated by ADC1)
|
||||
* @param atten Attenuation of the init code
|
||||
* @return The init code stored in efuse
|
||||
*/
|
||||
uint16_t esp_efuse_rtc_calib_get_init_code(int version, int atten);
|
||||
uint32_t esp_efuse_rtc_calib_get_init_code(int version, uint32_t adc_unit, int atten);
|
||||
|
||||
/**
|
||||
* @brief Get the calibration digits stored in the efuse, and the corresponding voltage.
|
||||
|
@ -15,6 +15,9 @@ extern "C" {
|
||||
#include "esp_err.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
//This is the ADC calibration value version burnt in efuse
|
||||
#define ESP_EFUSE_ADC_CALIB_VER 2
|
||||
|
||||
#define RTCCALIB_ESP32S2_ADCCOUNT 2
|
||||
#define RTCCALIB_ESP32S2_ATTENCOUNT 4
|
||||
|
||||
|
@ -30,7 +30,7 @@ int esp_efuse_rtc_calib_get_ver(void)
|
||||
return cali_version_v1;
|
||||
}
|
||||
|
||||
uint16_t esp_efuse_rtc_calib_get_init_code(int version, uint32_t adc_unit, int atten)
|
||||
uint32_t esp_efuse_rtc_calib_get_init_code(int version, uint32_t adc_unit, int atten)
|
||||
{
|
||||
assert(version == 1);
|
||||
assert(atten < 4);
|
||||
|
@ -11,6 +11,9 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//This is the ADC calibration value version burnt in efuse
|
||||
#define ESP_EFUSE_ADC_CALIB_VER 1
|
||||
|
||||
/**
|
||||
* @brief Get the RTC calibration efuse version
|
||||
*
|
||||
@ -26,7 +29,7 @@ int esp_efuse_rtc_calib_get_ver(void);
|
||||
* @param atten Attenuation of the init code
|
||||
* @return The init code stored in efuse
|
||||
*/
|
||||
uint16_t esp_efuse_rtc_calib_get_init_code(int version, uint32_t adc_unit, int atten);
|
||||
uint32_t esp_efuse_rtc_calib_get_init_code(int version, uint32_t adc_unit, int atten);
|
||||
|
||||
/**
|
||||
* @brief Get the calibration digits stored in the efuse, and the corresponding voltage.
|
||||
|
@ -1,130 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include "esp_types.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
#include "driver/adc.h"
|
||||
#include "hal/adc_ll.h"
|
||||
#include "esp_efuse_rtc_calib.h"
|
||||
#include "esp_adc_cal.h"
|
||||
|
||||
const static char LOG_TAG[] = "adc_calib";
|
||||
|
||||
|
||||
/* ------------------------ Characterization Constants ---------------------- */
|
||||
|
||||
// coeff_a and coeff_b are actually floats
|
||||
// they are scaled to put them into uint32_t so that the headers do not have to be changed
|
||||
static const int coeff_a_scaling = 65536;
|
||||
static const int coeff_b_scaling = 1024;
|
||||
/* -------------------- Characterization Helper Data Types ------------------ */
|
||||
typedef struct {
|
||||
uint32_t voltage;
|
||||
uint32_t digi;
|
||||
} adc_calib_data_ver1;
|
||||
|
||||
typedef struct {
|
||||
char version_num;
|
||||
adc_unit_t adc_num;
|
||||
adc_atten_t atten_level;
|
||||
union {
|
||||
adc_calib_data_ver1 ver1;
|
||||
} efuse_data;
|
||||
} adc_calib_parsed_info;
|
||||
|
||||
static esp_err_t prepare_calib_data_for(int version_num, adc_unit_t adc_num, adc_atten_t atten, adc_calib_parsed_info *parsed_data_storage)
|
||||
{
|
||||
assert(version_num == 1);
|
||||
esp_err_t ret;
|
||||
|
||||
parsed_data_storage->version_num = version_num;
|
||||
parsed_data_storage->adc_num = adc_num;
|
||||
parsed_data_storage->atten_level = atten;
|
||||
// V1 we don't have calibration data for ADC2, using the efuse data of ADC1
|
||||
uint32_t voltage, digi;
|
||||
ret = esp_efuse_rtc_calib_get_cal_voltage(version_num, atten, &digi, &voltage);
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
parsed_data_storage->efuse_data.ver1.voltage = voltage;
|
||||
parsed_data_storage->efuse_data.ver1.digi = digi;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* ----------------------- Characterization Functions ----------------------- */
|
||||
/*
|
||||
* Estimate the (assumed) linear relationship btwn the measured raw value and the voltage
|
||||
* with the previously done measurement when the chip was manufactured.
|
||||
*/
|
||||
static void calculate_characterization_coefficients(const adc_calib_parsed_info *parsed_data, esp_adc_cal_characteristics_t *chars)
|
||||
{
|
||||
ESP_LOGD(LOG_TAG, "Calib V1, Cal Voltage = %d, Digi out = %d\n", parsed_data->efuse_data.ver1.voltage, parsed_data->efuse_data.ver1.digi);
|
||||
|
||||
chars->coeff_a = coeff_a_scaling * parsed_data->efuse_data.ver1.voltage / parsed_data->efuse_data.ver1.digi;
|
||||
chars->coeff_b = 0;
|
||||
}
|
||||
|
||||
/* ------------------------- Public API ------------------------------------- */
|
||||
esp_err_t esp_adc_cal_check_efuse(esp_adc_cal_value_t source)
|
||||
{
|
||||
if (source != ESP_ADC_CAL_VAL_EFUSE_TP) {
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
uint8_t adc_encoding_version = esp_efuse_rtc_calib_get_ver();
|
||||
if (adc_encoding_version != 1) {
|
||||
// current version only accepts encoding ver 1.
|
||||
return ESP_ERR_INVALID_VERSION;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_adc_cal_value_t esp_adc_cal_characterize(adc_unit_t adc_num,
|
||||
adc_atten_t atten,
|
||||
adc_bits_width_t bit_width,
|
||||
uint32_t default_vref,
|
||||
esp_adc_cal_characteristics_t *chars)
|
||||
{
|
||||
esp_err_t ret;
|
||||
adc_calib_parsed_info efuse_parsed_data = {0};
|
||||
// Check parameters
|
||||
ESP_RETURN_ON_FALSE(adc_num == ADC_UNIT_1 || adc_num == ADC_UNIT_2, ESP_ADC_CAL_VAL_NOT_SUPPORTED, LOG_TAG, "Invalid unit num");
|
||||
ESP_RETURN_ON_FALSE(chars != NULL, ESP_ADC_CAL_VAL_NOT_SUPPORTED, LOG_TAG, "Ivalid characteristic");
|
||||
ESP_RETURN_ON_FALSE(bit_width == ADC_WIDTH_BIT_12, ESP_ADC_CAL_VAL_NOT_SUPPORTED, LOG_TAG, "Invalid bit_width");
|
||||
ESP_RETURN_ON_FALSE(atten < 4, ESP_ADC_CAL_VAL_NOT_SUPPORTED, LOG_TAG, "Invalid attenuation");
|
||||
|
||||
int version_num = esp_efuse_rtc_calib_get_ver();
|
||||
ESP_RETURN_ON_FALSE(version_num == 1, ESP_ADC_CAL_VAL_NOT_SUPPORTED, LOG_TAG, "No calibration efuse burnt");
|
||||
|
||||
memset(chars, 0, sizeof(esp_adc_cal_characteristics_t));
|
||||
|
||||
// make sure adc is calibrated.
|
||||
ret = prepare_calib_data_for(version_num, adc_num, atten, &efuse_parsed_data);
|
||||
if (ret != ESP_OK) {
|
||||
abort();
|
||||
}
|
||||
|
||||
calculate_characterization_coefficients(&efuse_parsed_data, chars);
|
||||
ESP_LOGD(LOG_TAG, "adc%d (atten leven %d) calibration done: A:%d B:%d\n", adc_num, atten, chars->coeff_a, chars->coeff_b);
|
||||
|
||||
// Initialize remaining fields
|
||||
chars->adc_num = adc_num;
|
||||
chars->atten = atten;
|
||||
chars->bit_width = bit_width;
|
||||
|
||||
// in esp32h2 we only use the two point method to calibrate the adc.
|
||||
return ESP_ADC_CAL_VAL_EFUSE_TP;
|
||||
}
|
||||
|
||||
uint32_t esp_adc_cal_raw_to_voltage(uint32_t adc_reading, const esp_adc_cal_characteristics_t *chars)
|
||||
{
|
||||
assert(chars != NULL);
|
||||
return adc_reading * chars->coeff_a / coeff_a_scaling + chars->coeff_b / coeff_b_scaling;
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
// Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
// NOTE: From the view of master
|
||||
#define CMD_HD_WRBUF_REG 0x01
|
||||
#define CMD_HD_RDBUF_REG 0x02
|
||||
#define CMD_HD_WRDMA_REG 0x03
|
||||
#define CMD_HD_RDDMA_REG 0x04
|
||||
|
||||
#define CMD_HD_ONEBIT_MODE 0x00
|
||||
#define CMD_HD_DOUT_MODE 0x10
|
||||
#define CMD_HD_QOUT_MODE 0x20
|
||||
#define CMD_HD_DIO_MODE 0x50
|
||||
#define CMD_HD_QIO_MODE 0xA0
|
||||
|
||||
#define CMD_HD_SEG_END_REG 0x05
|
||||
#define CMD_HD_EN_QPI_REG 0x06
|
||||
#define CMD_HD_WR_END_REG 0x07
|
||||
#define CMD_HD_INT0_REG 0x08
|
||||
#define CMD_HD_INT1_REG 0x09
|
||||
#define CMD_HD_INT2_REG 0x0A
|
||||
#define CMD_HD_EX_QPI_REG 0xDD
|
||||
|
||||
#define SPI_SLAVE_HD_BUFFER_SIZE 64
|
@ -139,7 +139,6 @@ if(NOT BOOTLOADER_BUILD)
|
||||
"twai_hal.c"
|
||||
"twai_hal_iram.c"
|
||||
"aes_hal.c"
|
||||
"esp32h2/adc_hal.c"
|
||||
"esp32h2/brownout_hal.c"
|
||||
"esp32h2/hmac_hal.c"
|
||||
"esp32h2/rtc_cntl_hal.c")
|
||||
@ -151,7 +150,6 @@ if(NOT BOOTLOADER_BUILD)
|
||||
"spi_flash_hal_gpspi.c"
|
||||
"spi_slave_hd_hal.c"
|
||||
"systimer_hal.c"
|
||||
"esp8684/adc_hal.c"
|
||||
"esp8684/brownout_hal.c"
|
||||
"esp8684/rtc_cntl_hal.c")
|
||||
endif()
|
||||
|
@ -5,25 +5,108 @@
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include "soc/soc_caps.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "hal/adc_hal.h"
|
||||
#include "hal/adc_hal_conf.h"
|
||||
#include "hal/assert.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/lldesc.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
//ADC utilises I2S0 DMA on ESP32
|
||||
#include "hal/i2s_ll.h"
|
||||
#include "hal/i2s_types.h"
|
||||
#include "soc/i2s_struct.h"
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684
|
||||
#include "soc/gdma_channel.h"
|
||||
#include "soc/soc.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
//ADC utilises SPI3 DMA on ESP32S2
|
||||
#include "hal/spi_ll.h"
|
||||
#include "soc/spi_struct.h"
|
||||
#endif
|
||||
|
||||
#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
|
||||
/*---------------------------------------------------------------
|
||||
Single Read
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* For chips without RTC controller, Digital controller is used to trigger an ADC single read.
|
||||
*/
|
||||
#include "esp_rom_sys.h"
|
||||
|
||||
typedef enum {
|
||||
ADC_EVENT_ADC1_DONE = BIT(0),
|
||||
ADC_EVENT_ADC2_DONE = BIT(1),
|
||||
} adc_hal_event_t;
|
||||
#endif //SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Define all ADC DMA required operations here
|
||||
---------------------------------------------------------------*/
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
#define adc_dma_ll_rx_clear_intr(dev, chan, mask) gdma_ll_rx_clear_interrupt_status(dev, chan, mask)
|
||||
#define adc_dma_ll_rx_enable_intr(dev, chan, mask) gdma_ll_rx_enable_interrupt(dev, chan, mask, true)
|
||||
#define adc_dma_ll_rx_disable_intr(dev, chan, mask) gdma_ll_rx_enable_interrupt(dev, chan, mask, false)
|
||||
#define adc_dma_ll_rx_reset_channel(dev, chan) gdma_ll_rx_reset_channel(dev, chan)
|
||||
#define adc_dma_ll_rx_stop(dev, chan) gdma_ll_rx_stop(dev, chan)
|
||||
#define adc_dma_ll_rx_start(dev, chan, addr) do { \
|
||||
gdma_ll_rx_set_desc_addr(dev, chan, (uint32_t)addr); \
|
||||
gdma_ll_rx_start(dev, chan); \
|
||||
} while (0)
|
||||
#define adc_ll_digi_dma_set_eof_num(dev, num) adc_ll_digi_dma_set_eof_num(num)
|
||||
#define adc_ll_digi_reset(dev) adc_ll_digi_reset()
|
||||
#define adc_ll_digi_trigger_enable(dev) adc_ll_digi_trigger_enable()
|
||||
#define adc_ll_digi_trigger_disable(dev) adc_ll_digi_trigger_disable()
|
||||
|
||||
//ADC utilises SPI3 DMA on ESP32S2
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#define adc_dma_ll_rx_get_intr(dev, mask) spi_ll_get_intr(dev, mask)
|
||||
#define adc_dma_ll_rx_clear_intr(dev, chan, mask) spi_ll_clear_intr(dev, mask)
|
||||
#define adc_dma_ll_rx_enable_intr(dev, chan, mask) spi_ll_enable_intr(dev, mask)
|
||||
#define adc_dma_ll_rx_disable_intr(dev, chan, mask) spi_ll_disable_intr(dev, mask)
|
||||
#define adc_dma_ll_rx_reset_channel(dev, chan) spi_dma_ll_rx_reset(dev, chan)
|
||||
#define adc_dma_ll_rx_stop(dev, chan) spi_dma_ll_rx_stop(dev, chan)
|
||||
#define adc_dma_ll_rx_start(dev, chan, addr) spi_dma_ll_rx_start(dev, chan, addr)
|
||||
#define adc_dma_ll_get_in_suc_eof_desc_addr(dev, chan) spi_dma_ll_get_in_suc_eof_desc_addr(dev, chan)
|
||||
#define adc_ll_digi_dma_set_eof_num(dev, num) adc_ll_digi_dma_set_eof_num(num)
|
||||
#define adc_ll_digi_reset(dev) adc_ll_digi_reset()
|
||||
#define adc_ll_digi_trigger_enable(dev) adc_ll_digi_trigger_enable()
|
||||
#define adc_ll_digi_trigger_disable(dev) adc_ll_digi_trigger_disable()
|
||||
|
||||
//ADC utilises I2S0 DMA on ESP32
|
||||
#else //CONFIG_IDF_TARGET_ESP32
|
||||
#define adc_dma_ll_rx_get_intr(dev, mask) ({i2s_ll_get_intr_status(dev) & mask;})
|
||||
#define adc_dma_ll_rx_clear_intr(dev, chan, mask) i2s_ll_clear_intr_status(dev, mask)
|
||||
#define adc_dma_ll_rx_enable_intr(dev, chan, mask) do {((i2s_dev_t *)(dev))->int_ena.val |= mask;} while (0)
|
||||
#define adc_dma_ll_rx_disable_intr(dev, chan, mask) do {((i2s_dev_t *)(dev))->int_ena.val &= ~mask;} while (0)
|
||||
#define adc_dma_ll_rx_reset_channel(dev, chan) i2s_ll_rx_reset_dma(dev)
|
||||
#define adc_dma_ll_rx_stop(dev, chan) i2s_ll_rx_stop_link(dev)
|
||||
#define adc_dma_ll_rx_start(dev, chan, address) do { \
|
||||
((i2s_dev_t *)(dev))->in_link.addr = (uint32_t)(address); \
|
||||
i2s_ll_enable_dma(dev, 1); \
|
||||
((i2s_dev_t *)(dev))->in_link.start = 1; \
|
||||
} while (0)
|
||||
#define adc_dma_ll_get_in_suc_eof_desc_addr(dev, chan) ({uint32_t addr; i2s_ll_rx_get_eof_des_addr(dev, &addr); addr;})
|
||||
#define adc_ll_digi_dma_set_eof_num(dev, num) do {((i2s_dev_t *)(dev))->rx_eof_num = num;} while (0)
|
||||
#define adc_ll_digi_reset(dev) do { \
|
||||
i2s_ll_rx_reset(dev); \
|
||||
i2s_ll_rx_reset_fifo(dev); \
|
||||
} while (0)
|
||||
#define adc_ll_digi_trigger_enable(dev) i2s_ll_rx_start(dev)
|
||||
#define adc_ll_digi_trigger_disable(dev) i2s_ll_rx_stop(dev)
|
||||
#define adc_ll_digi_dma_enable() adc_ll_digi_set_data_source(1) //Will this influence I2S0
|
||||
#define adc_ll_digi_dma_disable() adc_ll_digi_set_data_source(0)
|
||||
|
||||
//ESP32 ADC uses the DMA through I2S. The I2S needs to be configured.
|
||||
#define I2S_BASE_CLK (2*APB_CLK_FREQ)
|
||||
#define SAMPLE_BITS 16
|
||||
#define ADC_LL_CLKM_DIV_NUM_DEFAULT 2
|
||||
#define ADC_LL_CLKM_DIV_B_DEFAULT 0
|
||||
#define ADC_LL_CLKM_DIV_A_DEFAULT 1
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
void adc_hal_init(void)
|
||||
{
|
||||
// Set internal FSM wait time, fixed value.
|
||||
@ -42,7 +125,405 @@ void adc_hal_arbiter_config(adc_arbiter_t *config)
|
||||
adc_ll_set_arbiter_work_mode(config->mode);
|
||||
adc_ll_set_arbiter_priority(config->rtc_pri, config->dig_pri, config->pwdet_pri);
|
||||
}
|
||||
#endif // #if SOC_ADC_ARBITER_SUPPORTED
|
||||
|
||||
void adc_hal_digi_deinit(adc_hal_context_t *hal)
|
||||
{
|
||||
adc_ll_digi_trigger_disable(hal->dev);
|
||||
adc_ll_digi_dma_disable();
|
||||
adc_ll_digi_clear_pattern_table(ADC_NUM_1);
|
||||
adc_ll_digi_clear_pattern_table(ADC_NUM_2);
|
||||
adc_ll_digi_reset(hal->dev);
|
||||
adc_ll_digi_controller_clk_disable();
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Controller Setting
|
||||
---------------------------------------------------------------*/
|
||||
static adc_ll_controller_t get_controller(adc_ll_num_t unit, adc_hal_work_mode_t work_mode)
|
||||
{
|
||||
if (unit == ADC_NUM_1) {
|
||||
switch (work_mode) {
|
||||
#if SOC_ULP_SUPPORTED
|
||||
case ADC_HAL_ULP_MODE:
|
||||
return ADC_LL_CTRL_ULP;
|
||||
#endif
|
||||
case ADC_HAL_SINGLE_READ_MODE:
|
||||
#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
|
||||
return ADC_LL_CTRL_DIG;
|
||||
#elif SOC_ADC_RTC_CTRL_SUPPORTED
|
||||
return ADC_LL_CTRL_RTC;
|
||||
#endif
|
||||
case ADC_HAL_CONTINUOUS_READ_MODE:
|
||||
return ADC_LL_CTRL_DIG;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
} else {
|
||||
switch (work_mode) {
|
||||
#if SOC_ULP_SUPPORTED
|
||||
case ADC_HAL_ULP_MODE:
|
||||
return ADC_LL_CTRL_ULP;
|
||||
#endif
|
||||
#if !SOC_ADC_ARBITER_SUPPORTED //No ADC2 arbiter on ESP32
|
||||
case ADC_HAL_SINGLE_READ_MODE:
|
||||
return ADC_LL_CTRL_RTC;
|
||||
case ADC_HAL_CONTINUOUS_READ_MODE:
|
||||
return ADC_LL_CTRL_DIG;
|
||||
case ADC_HAL_PWDET_MODE:
|
||||
return ADC_LL_CTRL_PWDET;
|
||||
default:
|
||||
abort();
|
||||
#else
|
||||
default:
|
||||
return ADC_LL_CTRL_ARB;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void adc_hal_set_controller(adc_ll_num_t unit, adc_hal_work_mode_t work_mode)
|
||||
{
|
||||
adc_ll_controller_t ctrlr = get_controller(unit, work_mode);
|
||||
adc_ll_set_controller(unit, ctrlr);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
DMA read
|
||||
---------------------------------------------------------------*/
|
||||
static adc_ll_digi_convert_mode_t get_convert_mode(adc_digi_convert_mode_t convert_mode)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
return ADC_LL_DIGI_CONV_ONLY_ADC1;
|
||||
#endif
|
||||
#if (SOC_ADC_DIGI_CONTROLLER_NUM == 1)
|
||||
return ADC_LL_DIGI_CONV_ALTER_UNIT;
|
||||
#elif (SOC_ADC_DIGI_CONTROLLER_NUM >= 2)
|
||||
switch (convert_mode) {
|
||||
case ADC_CONV_SINGLE_UNIT_1:
|
||||
return ADC_LL_DIGI_CONV_ONLY_ADC1;
|
||||
case ADC_CONV_SINGLE_UNIT_2:
|
||||
return ADC_LL_DIGI_CONV_ONLY_ADC2;
|
||||
case ADC_CONV_BOTH_UNIT:
|
||||
return ADC_LL_DIGI_CONV_BOTH_UNIT;
|
||||
case ADC_CONV_ALTER_UNIT:
|
||||
return ADC_LL_DIGI_CONV_ALTER_UNIT;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* For esp32s2 and later chips
|
||||
* - Set ADC digital controller clock division factor. The clock is divided from `APLL` or `APB` clock.
|
||||
* Expression: controller_clk = APLL/APB * (div_num + div_a / div_b + 1).
|
||||
* - Enable clock and select clock source for ADC digital controller.
|
||||
* For esp32, use I2S clock
|
||||
*/
|
||||
static void adc_hal_digi_sample_freq_config(adc_hal_context_t *hal, uint32_t freq)
|
||||
{
|
||||
#if !CONFIG_IDF_TARGET_ESP32
|
||||
uint32_t interval = APB_CLK_FREQ / (ADC_LL_CLKM_DIV_NUM_DEFAULT + ADC_LL_CLKM_DIV_A_DEFAULT / ADC_LL_CLKM_DIV_B_DEFAULT + 1) / 2 / freq;
|
||||
//set sample interval
|
||||
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
|
||||
#else
|
||||
i2s_ll_rx_clk_set_src(hal->dev, I2S_CLK_D2CLK); /*!< Clock from PLL_D2_CLK(160M)*/
|
||||
uint32_t bck = I2S_BASE_CLK / (ADC_LL_CLKM_DIV_NUM_DEFAULT + ADC_LL_CLKM_DIV_B_DEFAULT / ADC_LL_CLKM_DIV_A_DEFAULT) / 2 / freq;
|
||||
i2s_ll_mclk_div_t clk = {
|
||||
.mclk_div = ADC_LL_CLKM_DIV_NUM_DEFAULT,
|
||||
.a = ADC_LL_CLKM_DIV_A_DEFAULT,
|
||||
.b = ADC_LL_CLKM_DIV_B_DEFAULT,
|
||||
};
|
||||
i2s_ll_rx_set_clk(hal->dev, &clk);
|
||||
i2s_ll_rx_set_bck_div_num(hal->dev, bck);
|
||||
#endif
|
||||
}
|
||||
|
||||
void adc_hal_digi_controller_config(adc_hal_context_t *hal, const adc_hal_digi_ctrlr_cfg_t *cfg)
|
||||
{
|
||||
#if (SOC_ADC_DIGI_CONTROLLER_NUM == 1)
|
||||
//Only one pattern table, this variable is for readability
|
||||
const int pattern_both = 0;
|
||||
|
||||
adc_ll_digi_clear_pattern_table(pattern_both);
|
||||
adc_ll_digi_set_pattern_table_len(pattern_both, cfg->adc_pattern_len);
|
||||
for (int i = 0; i < cfg->adc_pattern_len; i++) {
|
||||
adc_ll_digi_set_pattern_table(pattern_both, i, cfg->adc_pattern[i]);
|
||||
}
|
||||
|
||||
#elif (SOC_ADC_DIGI_CONTROLLER_NUM >= 2)
|
||||
uint32_t adc1_pattern_idx = 0;
|
||||
uint32_t adc2_pattern_idx = 0;
|
||||
|
||||
adc_ll_digi_clear_pattern_table(ADC_NUM_1);
|
||||
adc_ll_digi_clear_pattern_table(ADC_NUM_2);
|
||||
|
||||
for (int i = 0; i < cfg->adc_pattern_len; i++) {
|
||||
if (cfg->adc_pattern[i].unit == ADC_NUM_1) {
|
||||
adc_ll_digi_set_pattern_table(ADC_NUM_1, adc1_pattern_idx, cfg->adc_pattern[i]);
|
||||
adc1_pattern_idx++;
|
||||
} else if (cfg->adc_pattern[i].unit == ADC_NUM_2) {
|
||||
adc_ll_digi_set_pattern_table(ADC_NUM_2, adc2_pattern_idx, cfg->adc_pattern[i]);
|
||||
adc2_pattern_idx++;
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
adc_ll_digi_set_pattern_table_len(ADC_NUM_1, adc1_pattern_idx);
|
||||
adc_ll_digi_set_pattern_table_len(ADC_NUM_2, adc2_pattern_idx);
|
||||
|
||||
#endif
|
||||
|
||||
if (cfg->conv_limit_en) {
|
||||
adc_ll_digi_set_convert_limit_num(cfg->conv_limit_num);
|
||||
adc_ll_digi_convert_limit_enable();
|
||||
} else {
|
||||
adc_ll_digi_convert_limit_disable();
|
||||
}
|
||||
|
||||
adc_ll_digi_set_convert_mode(get_convert_mode(cfg->conv_mode));
|
||||
|
||||
//clock and sample frequency
|
||||
adc_hal_digi_sample_freq_config(hal, cfg->sample_freq_hz);
|
||||
}
|
||||
|
||||
void adc_hal_context_config(adc_hal_context_t *hal, const adc_hal_config_t *config)
|
||||
{
|
||||
hal->desc_dummy_head.next = hal->rx_desc;
|
||||
hal->dev = config->dev;
|
||||
hal->desc_max_num = config->desc_max_num;
|
||||
hal->dma_chan = config->dma_chan;
|
||||
hal->eof_num = config->eof_num;
|
||||
}
|
||||
|
||||
void adc_hal_digi_init(adc_hal_context_t *hal)
|
||||
{
|
||||
adc_dma_ll_rx_clear_intr(hal->dev, hal->dma_chan, ADC_HAL_DMA_INTR_MASK);
|
||||
adc_dma_ll_rx_enable_intr(hal->dev, hal->dma_chan, ADC_HAL_DMA_INTR_MASK);
|
||||
adc_ll_digi_dma_set_eof_num(hal->dev, hal->eof_num);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
i2s_ll_rx_set_sample_bit(hal->dev, SAMPLE_BITS, SAMPLE_BITS);
|
||||
i2s_ll_rx_enable_mono_mode(hal->dev, 1);
|
||||
i2s_ll_rx_force_enable_fifo_mod(hal->dev, 1);
|
||||
i2s_ll_enable_builtin_adc(hal->dev, 1);
|
||||
#endif
|
||||
#if CONFIG_IDF_TARGET_ESP32C3
|
||||
adc_ll_onetime_sample_enable(ADC_NUM_1, false);
|
||||
adc_ll_onetime_sample_enable(ADC_NUM_2, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void adc_hal_digi_dma_link_descriptors(dma_descriptor_t *desc, uint8_t *data_buf, uint32_t size, uint32_t num)
|
||||
{
|
||||
HAL_ASSERT(((uint32_t)data_buf % 4) == 0);
|
||||
HAL_ASSERT((size % 4) == 0);
|
||||
uint32_t n = 0;
|
||||
|
||||
while (num--) {
|
||||
desc[n] = (dma_descriptor_t) {
|
||||
.dw0.size = size,
|
||||
.dw0.length = 0,
|
||||
.dw0.suc_eof = 0,
|
||||
.dw0.owner = 1,
|
||||
.buffer = data_buf,
|
||||
.next = &desc[n+1]
|
||||
};
|
||||
data_buf += size;
|
||||
n++;
|
||||
}
|
||||
desc[n-1].next = NULL;
|
||||
}
|
||||
|
||||
void adc_hal_digi_start(adc_hal_context_t *hal, uint8_t *data_buf)
|
||||
{
|
||||
//stop peripheral and DMA
|
||||
adc_hal_digi_stop(hal);
|
||||
|
||||
//reset DMA
|
||||
adc_dma_ll_rx_reset_channel(hal->dev, hal->dma_chan);
|
||||
//reset peripheral
|
||||
adc_ll_digi_reset(hal->dev);
|
||||
|
||||
//reset the current descriptor address
|
||||
hal->cur_desc_ptr = &hal->desc_dummy_head;
|
||||
adc_hal_digi_dma_link_descriptors(hal->rx_desc, data_buf, hal->eof_num * ADC_HAL_DATA_LEN_PER_CONV, hal->desc_max_num);
|
||||
|
||||
//start DMA
|
||||
adc_dma_ll_rx_start(hal->dev, hal->dma_chan, (lldesc_t *)hal->rx_desc);
|
||||
//connect DMA and peripheral
|
||||
adc_ll_digi_dma_enable();
|
||||
//start ADC
|
||||
adc_ll_digi_trigger_enable(hal->dev);
|
||||
}
|
||||
|
||||
#if !SOC_GDMA_SUPPORTED
|
||||
intptr_t adc_hal_get_desc_addr(adc_hal_context_t *hal)
|
||||
{
|
||||
return adc_dma_ll_get_in_suc_eof_desc_addr(hal->dev, hal->dma_chan);
|
||||
}
|
||||
|
||||
bool adc_hal_check_event(adc_hal_context_t *hal, uint32_t mask)
|
||||
{
|
||||
return adc_dma_ll_rx_get_intr(hal->dev, mask);
|
||||
}
|
||||
#endif //#if !SOC_GDMA_SUPPORTED
|
||||
|
||||
adc_hal_dma_desc_status_t adc_hal_get_reading_result(adc_hal_context_t *hal, const intptr_t eof_desc_addr, dma_descriptor_t **cur_desc)
|
||||
{
|
||||
HAL_ASSERT(hal->cur_desc_ptr);
|
||||
if (!hal->cur_desc_ptr->next) {
|
||||
return ADC_HAL_DMA_DESC_NULL;
|
||||
}
|
||||
if ((intptr_t)hal->cur_desc_ptr == eof_desc_addr) {
|
||||
return ADC_HAL_DMA_DESC_WAITING;
|
||||
}
|
||||
|
||||
hal->cur_desc_ptr = hal->cur_desc_ptr->next;
|
||||
*cur_desc = hal->cur_desc_ptr;
|
||||
|
||||
return ADC_HAL_DMA_DESC_VALID;
|
||||
}
|
||||
|
||||
void adc_hal_digi_clr_intr(adc_hal_context_t *hal, uint32_t mask)
|
||||
{
|
||||
adc_dma_ll_rx_clear_intr(hal->dev, hal->dma_chan, mask);
|
||||
}
|
||||
|
||||
void adc_hal_digi_dis_intr(adc_hal_context_t *hal, uint32_t mask)
|
||||
{
|
||||
adc_dma_ll_rx_disable_intr(hal->dev, hal->dma_chan, mask);
|
||||
}
|
||||
|
||||
void adc_hal_digi_stop(adc_hal_context_t *hal)
|
||||
{
|
||||
//stop ADC
|
||||
adc_ll_digi_trigger_disable(hal->dev);
|
||||
//stop DMA
|
||||
adc_dma_ll_rx_stop(hal->dev, hal->dma_chan);
|
||||
//disconnect DMA and peripheral
|
||||
adc_ll_digi_dma_disable();
|
||||
}
|
||||
|
||||
#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
|
||||
/*---------------------------------------------------------------
|
||||
Single Read
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* For chips without RTC controller, Digital controller is used to trigger an ADC single read.
|
||||
*/
|
||||
|
||||
//--------------------INTR-------------------------------//
|
||||
static adc_ll_intr_t get_event_intr(adc_hal_event_t event)
|
||||
{
|
||||
adc_ll_intr_t intr_mask = 0;
|
||||
if (event & ADC_EVENT_ADC1_DONE) {
|
||||
intr_mask |= ADC_LL_INTR_ADC1_DONE;
|
||||
}
|
||||
if (event & ADC_EVENT_ADC2_DONE) {
|
||||
intr_mask |= ADC_LL_INTR_ADC2_DONE;
|
||||
}
|
||||
return intr_mask;
|
||||
}
|
||||
|
||||
static void adc_hal_intr_clear(adc_hal_event_t event)
|
||||
{
|
||||
adc_ll_intr_clear(get_event_intr(event));
|
||||
}
|
||||
|
||||
static bool adc_hal_intr_get_raw(adc_hal_event_t event)
|
||||
{
|
||||
return adc_ll_intr_get_raw(get_event_intr(event));
|
||||
}
|
||||
|
||||
|
||||
//--------------------Single Read-------------------------------//
|
||||
static void adc_hal_onetime_start(void)
|
||||
{
|
||||
/**
|
||||
* There is a hardware limitation. If the APB clock frequency is high, the step of this reg signal: ``onetime_start`` may not be captured by the
|
||||
* ADC digital controller (when its clock frequency is too slow). A rough estimate for this step should be at least 3 ADC digital controller
|
||||
* clock cycle.
|
||||
*
|
||||
* This limitation will be removed in hardware future versions.
|
||||
*
|
||||
*/
|
||||
uint32_t digi_clk = APB_CLK_FREQ / (ADC_LL_CLKM_DIV_NUM_DEFAULT + ADC_LL_CLKM_DIV_A_DEFAULT / ADC_LL_CLKM_DIV_B_DEFAULT + 1);
|
||||
//Convert frequency to time (us). Since decimals are removed by this division operation. Add 1 here in case of the fact that delay is not enough.
|
||||
uint32_t delay = (1000 * 1000) / digi_clk + 1;
|
||||
//3 ADC digital controller clock cycle
|
||||
delay = delay * 3;
|
||||
//This coefficient (8) is got from test. When digi_clk is not smaller than ``APB_CLK_FREQ/8``, no delay is needed.
|
||||
if (digi_clk >= APB_CLK_FREQ/8) {
|
||||
delay = 0;
|
||||
}
|
||||
|
||||
adc_ll_onetime_start(false);
|
||||
esp_rom_delay_us(delay);
|
||||
adc_ll_onetime_start(true);
|
||||
|
||||
//No need to delay here. Becuase if the start signal is not seen, there won't be a done intr.
|
||||
}
|
||||
|
||||
static esp_err_t adc_hal_single_read(adc_ll_num_t adc_n, int *out_raw)
|
||||
{
|
||||
if (adc_n == ADC_NUM_1) {
|
||||
*out_raw = adc_ll_adc1_read();
|
||||
} else if (adc_n == ADC_NUM_2) {
|
||||
*out_raw = adc_ll_adc2_read();
|
||||
if (adc_ll_analysis_raw_data(adc_n, *out_raw)) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_hal_convert(adc_ll_num_t adc_n, int channel, int *out_raw)
|
||||
{
|
||||
esp_err_t ret;
|
||||
adc_hal_event_t event;
|
||||
|
||||
if (adc_n == ADC_NUM_1) {
|
||||
event = ADC_EVENT_ADC1_DONE;
|
||||
} else {
|
||||
event = ADC_EVENT_ADC2_DONE;
|
||||
}
|
||||
|
||||
adc_hal_intr_clear(event);
|
||||
adc_ll_onetime_sample_enable(ADC_NUM_1, false);
|
||||
adc_ll_onetime_sample_enable(ADC_NUM_2, false);
|
||||
adc_ll_onetime_sample_enable(adc_n, true);
|
||||
adc_ll_onetime_set_channel(adc_n, channel);
|
||||
|
||||
//Trigger single read.
|
||||
adc_hal_onetime_start();
|
||||
while (!adc_hal_intr_get_raw(event));
|
||||
ret = adc_hal_single_read(adc_n, out_raw);
|
||||
//HW workaround: when enabling periph clock, this should be false
|
||||
adc_ll_onetime_sample_enable(adc_n, false);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else // #if SOC_ADC_RTC_CTRL_SUPPORTED
|
||||
esp_err_t adc_hal_convert(adc_ll_num_t adc_n, int channel, int *out_raw)
|
||||
{
|
||||
adc_ll_rtc_enable_channel(adc_n, channel);
|
||||
adc_ll_rtc_start_convert(adc_n, channel);
|
||||
while (adc_ll_rtc_convert_is_done(adc_n) != true);
|
||||
*out_raw = adc_ll_rtc_get_convert_value(adc_n);
|
||||
|
||||
if ((int)adc_ll_rtc_analysis_raw_data(adc_n, (uint16_t)(*out_raw))) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif //#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
|
||||
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
ADC calibration setting
|
||||
@ -63,14 +544,10 @@ void adc_hal_set_calibration_param(adc_ll_num_t adc_n, uint32_t param)
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
#if SOC_ADC_RTC_CTRL_SUPPORTED
|
||||
static void cal_setup(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten, bool internal_gnd)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
adc_hal_set_controller(adc_n, ADC_CTRL_RTC); //Set controller
|
||||
#else
|
||||
adc_hal_set_controller(adc_n, ADC_LL_CTRL_ARB); //Set controller
|
||||
#endif
|
||||
adc_hal_set_controller(adc_n, ADC_HAL_SINGLE_READ_MODE); //Set controller
|
||||
|
||||
/* Enable/disable internal connect GND (for calibration). */
|
||||
if (internal_gnd) {
|
||||
@ -89,14 +566,15 @@ static uint32_t read_cal_channel(adc_ll_num_t adc_n, int channel)
|
||||
return (uint32_t)adc_ll_rtc_get_convert_value(adc_n);
|
||||
}
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684
|
||||
#elif SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
|
||||
//For those RTC controller not supported chips, they use digital controller to do the single read. e.g.: esp32c3
|
||||
static void cal_setup(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten, bool internal_gnd)
|
||||
{
|
||||
adc_ll_onetime_sample_enable(ADC_NUM_1, false);
|
||||
adc_ll_onetime_sample_enable(ADC_NUM_2, false);
|
||||
/* Enable/disable internal connect GND (for calibration). */
|
||||
if (internal_gnd) {
|
||||
const int esp32c3_invalid_chan = (adc_n == ADC_NUM_1) ? 0xF : 0x1;
|
||||
const int esp32c3_invalid_chan = (adc_n == ADC_NUM_1)? 0xF: 0x1;
|
||||
adc_ll_onetime_set_channel(adc_n, esp32c3_invalid_chan);
|
||||
} else {
|
||||
adc_ll_onetime_set_channel(adc_n, channel);
|
||||
@ -112,7 +590,7 @@ static uint32_t read_cal_channel(adc_ll_num_t adc_n, int channel)
|
||||
esp_rom_delay_us(5);
|
||||
adc_ll_onetime_start(true);
|
||||
|
||||
while (!adc_ll_intr_get_raw(ADC_LL_INTR_ADC1_DONE | ADC_LL_INTR_ADC2_DONE));
|
||||
while(!adc_ll_intr_get_raw(ADC_LL_INTR_ADC1_DONE | ADC_LL_INTR_ADC2_DONE));
|
||||
|
||||
uint32_t read_val = -1;
|
||||
if (adc_n == ADC_NUM_1) {
|
||||
@ -125,7 +603,7 @@ static uint32_t read_cal_channel(adc_ll_num_t adc_n, int channel)
|
||||
}
|
||||
return read_val;
|
||||
}
|
||||
#endif //CONFIG_IDF_TARGET_*
|
||||
#endif //Do single read via DIGI controller or RTC controller
|
||||
|
||||
#define ADC_HAL_CAL_TIMES (10)
|
||||
#define ADC_HAL_CAL_OFFSET_RANGE (4096)
|
||||
@ -181,224 +659,10 @@ uint32_t adc_hal_self_calibration(adc_ll_num_t adc_n, adc_channel_t channel, adc
|
||||
|
||||
chk_code = code_h + code_l;
|
||||
uint32_t ret = ((code_sum - chk_code) % (ADC_HAL_CAL_TIMES - 2) < 4)
|
||||
? (code_sum - chk_code) / (ADC_HAL_CAL_TIMES - 2)
|
||||
: (code_sum - chk_code) / (ADC_HAL_CAL_TIMES - 2) + 1;
|
||||
? (code_sum - chk_code) / (ADC_HAL_CAL_TIMES - 2)
|
||||
: (code_sum - chk_code) / (ADC_HAL_CAL_TIMES - 2) + 1;
|
||||
|
||||
adc_ll_calibration_finish(adc_n);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif //SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684
|
||||
//This feature is currently supported on ESP32C3, will be supported on other chips soon
|
||||
/*---------------------------------------------------------------
|
||||
DMA setting
|
||||
---------------------------------------------------------------*/
|
||||
void adc_hal_context_config(adc_hal_context_t *hal, const adc_hal_config_t *config)
|
||||
{
|
||||
hal->dev = &GDMA;
|
||||
hal->desc_dummy_head.next = hal->rx_desc;
|
||||
hal->desc_max_num = config->desc_max_num;
|
||||
hal->dma_chan = config->dma_chan;
|
||||
hal->eof_num = config->eof_num;
|
||||
}
|
||||
|
||||
void adc_hal_digi_init(adc_hal_context_t *hal)
|
||||
{
|
||||
gdma_ll_rx_clear_interrupt_status(hal->dev, hal->dma_chan, UINT32_MAX);
|
||||
gdma_ll_rx_enable_interrupt(hal->dev, hal->dma_chan, GDMA_LL_EVENT_RX_SUC_EOF, true);
|
||||
adc_ll_digi_dma_set_eof_num(hal->eof_num);
|
||||
adc_ll_onetime_sample_enable(ADC_NUM_1, false);
|
||||
adc_ll_onetime_sample_enable(ADC_NUM_2, false);
|
||||
}
|
||||
|
||||
void adc_hal_fifo_reset(adc_hal_context_t *hal)
|
||||
{
|
||||
adc_ll_digi_reset();
|
||||
gdma_ll_rx_reset_channel(hal->dev, hal->dma_chan);
|
||||
}
|
||||
|
||||
static void adc_hal_digi_dma_link_descriptors(dma_descriptor_t *desc, uint8_t *data_buf, uint32_t size, uint32_t num)
|
||||
{
|
||||
HAL_ASSERT(((uint32_t)data_buf % 4) == 0);
|
||||
HAL_ASSERT((size % 4) == 0);
|
||||
uint32_t n = 0;
|
||||
|
||||
while (num--) {
|
||||
desc[n].dw0.size = size;
|
||||
desc[n].dw0.suc_eof = 0;
|
||||
desc[n].dw0.owner = 1;
|
||||
desc[n].buffer = data_buf;
|
||||
desc[n].next = &desc[n + 1];
|
||||
data_buf += size;
|
||||
n++;
|
||||
}
|
||||
desc[n - 1].next = NULL;
|
||||
}
|
||||
|
||||
void adc_hal_digi_rxdma_start(adc_hal_context_t *hal, uint8_t *data_buf)
|
||||
{
|
||||
//reset the current descriptor address
|
||||
hal->cur_desc_ptr = &hal->desc_dummy_head;
|
||||
adc_hal_digi_dma_link_descriptors(hal->rx_desc, data_buf, hal->eof_num * ADC_HAL_DATA_LEN_PER_CONV, hal->desc_max_num);
|
||||
gdma_ll_rx_set_desc_addr(hal->dev, hal->dma_chan, (uint32_t)hal->rx_desc);
|
||||
gdma_ll_rx_start(hal->dev, hal->dma_chan);
|
||||
}
|
||||
|
||||
void adc_hal_digi_start(adc_hal_context_t *hal)
|
||||
{
|
||||
//the ADC data will be sent to the DMA
|
||||
adc_ll_digi_dma_enable();
|
||||
//enable sar adc timer
|
||||
adc_ll_digi_trigger_enable();
|
||||
}
|
||||
|
||||
adc_hal_dma_desc_status_t adc_hal_get_reading_result(adc_hal_context_t *hal, const intptr_t eof_desc_addr, dma_descriptor_t **cur_desc)
|
||||
{
|
||||
HAL_ASSERT(hal->cur_desc_ptr);
|
||||
if (!hal->cur_desc_ptr->next) {
|
||||
return ADC_HAL_DMA_DESC_NULL;
|
||||
}
|
||||
if ((intptr_t)hal->cur_desc_ptr == eof_desc_addr) {
|
||||
return ADC_HAL_DMA_DESC_WAITING;
|
||||
}
|
||||
|
||||
hal->cur_desc_ptr = hal->cur_desc_ptr->next;
|
||||
*cur_desc = hal->cur_desc_ptr;
|
||||
|
||||
return ADC_HAL_DMA_DESC_VALID;
|
||||
}
|
||||
|
||||
void adc_hal_digi_rxdma_stop(adc_hal_context_t *hal)
|
||||
{
|
||||
gdma_ll_rx_stop(hal->dev, hal->dma_chan);
|
||||
}
|
||||
|
||||
void adc_hal_digi_clr_intr(adc_hal_context_t *hal, uint32_t mask)
|
||||
{
|
||||
gdma_ll_rx_clear_interrupt_status(hal->dev, hal->dma_chan, mask);
|
||||
}
|
||||
|
||||
void adc_hal_digi_dis_intr(adc_hal_context_t *hal, uint32_t mask)
|
||||
{
|
||||
gdma_ll_rx_enable_interrupt(hal->dev, hal->dma_chan, mask, false);
|
||||
}
|
||||
|
||||
void adc_hal_digi_stop(adc_hal_context_t *hal)
|
||||
{
|
||||
//Set to 0: the ADC data won't be sent to the DMA
|
||||
adc_ll_digi_dma_disable();
|
||||
//disable sar adc timer
|
||||
adc_ll_digi_trigger_disable();
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Single Read
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
//--------------------INTR-------------------------------//
|
||||
static adc_ll_intr_t get_event_intr(adc_hal_event_t event)
|
||||
{
|
||||
adc_ll_intr_t intr_mask = 0;
|
||||
if (event & ADC_EVENT_ADC1_DONE) {
|
||||
intr_mask |= ADC_LL_INTR_ADC1_DONE;
|
||||
}
|
||||
if (event & ADC_EVENT_ADC2_DONE) {
|
||||
intr_mask |= ADC_LL_INTR_ADC2_DONE;
|
||||
}
|
||||
return intr_mask;
|
||||
}
|
||||
|
||||
static void adc_hal_intr_clear(adc_hal_event_t event)
|
||||
{
|
||||
adc_ll_intr_clear(get_event_intr(event));
|
||||
}
|
||||
|
||||
static bool adc_hal_intr_get_raw(adc_hal_event_t event)
|
||||
{
|
||||
return adc_ll_intr_get_raw(get_event_intr(event));
|
||||
}
|
||||
|
||||
//--------------------Single Read-------------------------------//
|
||||
static void adc_hal_onetime_start(void)
|
||||
{
|
||||
/**
|
||||
* There is a hardware limitation. If the APB clock frequency is high, the step of this reg signal: ``onetime_start`` may not be captured by the
|
||||
* ADC digital controller (when its clock frequency is too slow). A rough estimate for this step should be at least 3 ADC digital controller
|
||||
* clock cycle.
|
||||
*
|
||||
* This limitation will be removed in hardware future versions.
|
||||
*
|
||||
*/
|
||||
uint32_t digi_clk = APB_CLK_FREQ / (ADC_LL_CLKM_DIV_NUM_DEFAULT + ADC_LL_CLKM_DIV_A_DEFAULT / ADC_LL_CLKM_DIV_B_DEFAULT + 1);
|
||||
//Convert frequency to time (us). Since decimals are removed by this division operation. Add 1 here in case of the fact that delay is not enough.
|
||||
uint32_t delay = (1000 * 1000) / digi_clk + 1;
|
||||
//3 ADC digital controller clock cycle
|
||||
delay = delay * 3;
|
||||
//This coefficient (8) is got from test. When digi_clk is not smaller than ``APB_CLK_FREQ/8``, no delay is needed.
|
||||
if (digi_clk >= APB_CLK_FREQ / 8) {
|
||||
delay = 0;
|
||||
}
|
||||
|
||||
adc_ll_onetime_start(false);
|
||||
esp_rom_delay_us(delay);
|
||||
adc_ll_onetime_start(true);
|
||||
|
||||
//No need to delay here. Becuase if the start signal is not seen, there won't be a done intr.
|
||||
}
|
||||
|
||||
static esp_err_t adc_hal_single_read(adc_ll_num_t adc_n, int *out_raw)
|
||||
{
|
||||
if (adc_n == ADC_NUM_1) {
|
||||
*out_raw = adc_ll_adc1_read();
|
||||
} else if (adc_n == ADC_NUM_2) {
|
||||
*out_raw = adc_ll_adc2_read();
|
||||
if (adc_ll_analysis_raw_data(adc_n, *out_raw)) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_hal_convert(adc_ll_num_t adc_n, int channel, int *out_raw)
|
||||
{
|
||||
esp_err_t ret;
|
||||
adc_hal_event_t event;
|
||||
|
||||
if (adc_n == ADC_NUM_1) {
|
||||
event = ADC_EVENT_ADC1_DONE;
|
||||
} else {
|
||||
event = ADC_EVENT_ADC2_DONE;
|
||||
}
|
||||
|
||||
adc_hal_intr_clear(event);
|
||||
adc_ll_onetime_sample_enable(ADC_NUM_1, false);
|
||||
adc_ll_onetime_sample_enable(ADC_NUM_2, false);
|
||||
adc_ll_onetime_sample_enable(adc_n, true);
|
||||
adc_ll_onetime_set_channel(adc_n, channel);
|
||||
|
||||
//Trigger single read.
|
||||
adc_hal_onetime_start();
|
||||
while (!adc_hal_intr_get_raw(event));
|
||||
ret = adc_hal_single_read(adc_n, out_raw);
|
||||
//HW workaround: when enabling periph clock, this should be false
|
||||
adc_ll_onetime_sample_enable(adc_n, false);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#else // !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684
|
||||
esp_err_t adc_hal_convert(adc_ll_num_t adc_n, int channel, int *out_raw)
|
||||
{
|
||||
adc_ll_rtc_enable_channel(adc_n, channel);
|
||||
adc_ll_rtc_start_convert(adc_n, channel);
|
||||
while (adc_ll_rtc_convert_is_done(adc_n) != true);
|
||||
*out_raw = adc_ll_rtc_get_convert_value(adc_n);
|
||||
|
||||
if ((int)adc_ll_rtc_analysis_raw_data(adc_n, (uint16_t)(*out_raw))) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif //#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP8684
|
||||
|
@ -1,16 +1,8 @@
|
||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// The HAL layer for ADC (common part)
|
||||
|
||||
@ -18,45 +10,6 @@
|
||||
#include "hal/adc_hal_conf.h"
|
||||
#include "hal/adc_types.h"
|
||||
|
||||
void adc_hal_digi_deinit(void)
|
||||
{
|
||||
adc_ll_digi_clear_pattern_table(ADC_NUM_1);
|
||||
adc_ll_digi_clear_pattern_table(ADC_NUM_2);
|
||||
}
|
||||
|
||||
void adc_hal_digi_controller_config(const adc_digi_config_t *cfg)
|
||||
{
|
||||
/* Single channel mode or multi channel mode. */
|
||||
adc_ll_digi_set_convert_mode(cfg->conv_mode);
|
||||
if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_1) {
|
||||
adc_ll_set_controller(ADC_NUM_1, ADC_CTRL_DIG);
|
||||
if (cfg->adc1_pattern_len) {
|
||||
adc_ll_digi_clear_pattern_table(ADC_NUM_1);
|
||||
adc_ll_digi_set_pattern_table_len(ADC_NUM_1, cfg->adc1_pattern_len);
|
||||
for (uint32_t i = 0; i < cfg->adc1_pattern_len; i++) {
|
||||
adc_ll_digi_set_pattern_table(ADC_NUM_1, i, cfg->adc1_pattern[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_2) {
|
||||
adc_ll_set_controller(ADC_NUM_2, ADC_CTRL_DIG);
|
||||
if (cfg->adc2_pattern_len) {
|
||||
adc_ll_digi_clear_pattern_table(ADC_NUM_2);
|
||||
adc_ll_digi_set_pattern_table_len(ADC_NUM_2, cfg->adc2_pattern_len);
|
||||
for (uint32_t i = 0; i < cfg->adc2_pattern_len; i++) {
|
||||
adc_ll_digi_set_pattern_table(ADC_NUM_2, i, cfg->adc2_pattern[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
adc_ll_digi_set_output_format(cfg->format);
|
||||
if (cfg->conv_limit_en) {
|
||||
adc_ll_digi_set_convert_limit_num(cfg->conv_limit_num);
|
||||
adc_ll_digi_convert_limit_enable();
|
||||
} else {
|
||||
adc_ll_digi_convert_limit_disable();
|
||||
}
|
||||
adc_ll_digi_set_data_source(ADC_I2S_DATA_SRC_ADC);
|
||||
}
|
||||
|
||||
int adc_hal_hall_convert(void)
|
||||
{
|
||||
|
@ -1,16 +1,8 @@
|
||||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* NOTICE
|
||||
@ -31,35 +23,9 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Digital controller setting
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Set I2S DMA data source for digital controller.
|
||||
*
|
||||
* @param src i2s data source.
|
||||
*/
|
||||
#define adc_hal_digi_set_data_source(src) adc_ll_digi_set_data_source(src)
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Common setting
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Hall sensor setting
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Enable hall sensor.
|
||||
*/
|
||||
#define adc_hal_hall_enable() adc_ll_hall_enable()
|
||||
|
||||
/**
|
||||
* Disable hall sensor.
|
||||
*/
|
||||
#define adc_hal_hall_disable() adc_ll_hall_disable()
|
||||
|
||||
/**
|
||||
* Start hall convert and return the hall value.
|
||||
*
|
||||
|
@ -1,3 +1,9 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "soc/adc_periph.h"
|
||||
@ -26,22 +32,50 @@ typedef enum {
|
||||
ADC_POWER_MAX, /*!< For parameter check. */
|
||||
} adc_ll_power_t;
|
||||
|
||||
typedef enum {
|
||||
ADC_RTC_DATA_OK = 0,
|
||||
} adc_ll_rtc_raw_data_t;
|
||||
|
||||
typedef enum {
|
||||
ADC_LL_CTRL_RTC = 0, ///< For ADC1 and ADC2. Select RTC controller.
|
||||
ADC_LL_CTRL_ULP = 1, ///< For ADC1 and ADC2. Select ULP controller.
|
||||
ADC_LL_CTRL_DIG = 2, ///< For ADC1 and ADC2. Select DIG controller.
|
||||
ADC_LL_CTRL_PWDET = 3, ///< For ADC2. Select PWDET controller.
|
||||
} adc_ll_controller_t;
|
||||
|
||||
/**
|
||||
* @brief ADC digital controller (DMA mode) work mode.
|
||||
*
|
||||
* @note The conversion mode affects the sampling frequency:
|
||||
* SINGLE_UNIT_1: When the measurement is triggered, only ADC1 is sampled once.
|
||||
* SINGLE_UNIT_2: When the measurement is triggered, only ADC2 is sampled once.
|
||||
* BOTH_UNIT : When the measurement is triggered, ADC1 and ADC2 are sampled at the same time.
|
||||
* ALTER_UNIT : When the measurement is triggered, ADC1 or ADC2 samples alternately.
|
||||
*/
|
||||
typedef enum {
|
||||
ADC_LL_DIGI_CONV_ONLY_ADC1 = 0, // Only use ADC1 for conversion
|
||||
ADC_LL_DIGI_CONV_ONLY_ADC2 = 1, // Only use ADC2 for conversion
|
||||
ADC_LL_DIGI_CONV_BOTH_UNIT = 2, // Use Both ADC1 and ADC2 for conversion simultaneously
|
||||
ADC_LL_DIGI_CONV_ALTER_UNIT = 3 // Use both ADC1 and ADC2 for conversion by turn. e.g. ADC1 -> ADC2 -> ADC1 -> ADC2 .....
|
||||
} adc_ll_digi_convert_mode_t;
|
||||
|
||||
//Need a unit test for bit_width
|
||||
typedef struct {
|
||||
union {
|
||||
struct {
|
||||
uint8_t atten: 2;
|
||||
uint8_t bit_width: 2; //ADC resolution. 0: 9 bit; 1: 10 bit; 2: 11 bit; 3: 12 bit
|
||||
uint8_t channel: 4;
|
||||
};
|
||||
uint8_t val;
|
||||
};
|
||||
} __attribute__((packed)) adc_ll_digi_pattern_table_t;
|
||||
|
||||
typedef enum {
|
||||
ADC_HALL_CTRL_ULP = 0x0,/*!< Hall sensor controlled by ULP */
|
||||
ADC_HALL_CTRL_RTC = 0x1 /*!< Hall sensor controlled by RTC */
|
||||
} adc_ll_hall_controller_t ;
|
||||
|
||||
typedef enum {
|
||||
ADC_CTRL_RTC = 0,
|
||||
ADC_CTRL_ULP = 1,
|
||||
ADC_CTRL_DIG = 2,
|
||||
ADC2_CTRL_PWDET = 3,
|
||||
} adc_hal_controller_t ;
|
||||
|
||||
typedef enum {
|
||||
ADC_RTC_DATA_OK = 0,
|
||||
} adc_ll_rtc_raw_data_t;
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Digital controller setting
|
||||
---------------------------------------------------------------*/
|
||||
@ -85,16 +119,6 @@ static inline void adc_ll_digi_set_clk_div(uint32_t div)
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(SYSCON.saradc_ctrl, sar_clk_div, div);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set adc output data format for digital controller.
|
||||
*
|
||||
* @param format Output data format, see ``adc_digi_output_format_t``.
|
||||
*/
|
||||
static inline void adc_ll_digi_set_output_format(adc_digi_output_format_t format)
|
||||
{
|
||||
SYSCON.saradc_ctrl.data_sar_sel = format;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set adc max conversion number for digital controller.
|
||||
* If the number of ADC conversion is equal to the maximum, the conversion is stopped.
|
||||
@ -128,21 +152,28 @@ static inline void adc_ll_digi_convert_limit_disable(void)
|
||||
* Set adc conversion mode for digital controller.
|
||||
*
|
||||
* @note ESP32 only support ADC1 single mode.
|
||||
* @note For `data_sar_sel` register:
|
||||
* 1: [15] unit, [14:11] channel, [10:0] data, 11-bit-width at most. Only work under `ADC_LL_DIGI_CONV_BOTH_UNIT` or `ADC_LL_DIGI_CONV_ALTER_UNIT` mode.
|
||||
* 0: [15:12] channel, [11:0] data, 12-bit-width at most. Only work under `ADC_LL_DIGI_CONV_ONLY_ADC1` or `ADC_LL_DIGI_CONV_ONLY_ADC2` mode
|
||||
*
|
||||
* @param mode Conversion mode select, see ``adc_digi_convert_mode_t``.
|
||||
* @param mode Conversion mode select.
|
||||
*/
|
||||
static inline void adc_ll_digi_set_convert_mode(adc_digi_convert_mode_t mode)
|
||||
static inline void adc_ll_digi_set_convert_mode(adc_ll_digi_convert_mode_t mode)
|
||||
{
|
||||
if (mode == ADC_CONV_SINGLE_UNIT_1) {
|
||||
if (mode == ADC_LL_DIGI_CONV_ONLY_ADC1) {
|
||||
SYSCON.saradc_ctrl.work_mode = 0;
|
||||
SYSCON.saradc_ctrl.sar_sel = 0;
|
||||
} else if (mode == ADC_CONV_SINGLE_UNIT_2) {
|
||||
SYSCON.saradc_ctrl.data_sar_sel = 0;
|
||||
} else if (mode == ADC_LL_DIGI_CONV_ONLY_ADC2) {
|
||||
SYSCON.saradc_ctrl.work_mode = 0;
|
||||
SYSCON.saradc_ctrl.sar_sel = 1;
|
||||
} else if (mode == ADC_CONV_BOTH_UNIT) {
|
||||
SYSCON.saradc_ctrl.data_sar_sel = 0;
|
||||
} else if (mode == ADC_LL_DIGI_CONV_BOTH_UNIT) {
|
||||
SYSCON.saradc_ctrl.work_mode = 1;
|
||||
} else if (mode == ADC_CONV_ALTER_UNIT) {
|
||||
SYSCON.saradc_ctrl.data_sar_sel = 1;
|
||||
} else if (mode == ADC_LL_DIGI_CONV_ALTER_UNIT) {
|
||||
SYSCON.saradc_ctrl.work_mode = 2;
|
||||
SYSCON.saradc_ctrl.data_sar_sel = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -163,11 +194,10 @@ static inline void adc_ll_digi_output_invert(adc_ll_num_t adc_n, bool inv_en)
|
||||
/**
|
||||
* Set I2S DMA data source for digital controller.
|
||||
*
|
||||
* @param src i2s data source, see ``adc_i2s_source_t``.
|
||||
* @param src 1: I2S input data is from SAR ADC (for DMA) 0: I2S input data is from GPIO matrix
|
||||
*/
|
||||
static inline void adc_ll_digi_set_data_source(adc_i2s_source_t src)
|
||||
static inline void adc_ll_digi_set_data_source(bool src)
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@ -199,12 +229,33 @@ static inline void adc_ll_digi_set_pattern_table_len(adc_ll_num_t adc_n, uint32_
|
||||
* @param pattern_index Items index. Range: 0 ~ 15.
|
||||
* @param pattern Stored conversion rules, see ``adc_digi_pattern_table_t``.
|
||||
*/
|
||||
static inline void adc_ll_digi_set_pattern_table(adc_ll_num_t adc_n, uint32_t pattern_index, adc_digi_pattern_table_t pattern)
|
||||
static inline void adc_ll_digi_set_pattern_table(adc_ll_num_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) * 8;
|
||||
if (adc_n == ADC_NUM_1) {
|
||||
adc_ll_digi_pattern_table_t pattern = {0};
|
||||
uint8_t bit_width;
|
||||
|
||||
switch (table.bit_width) {
|
||||
case 9:
|
||||
bit_width = 0x0;
|
||||
break;
|
||||
case 10:
|
||||
bit_width = 0x1;
|
||||
break;
|
||||
case 11:
|
||||
bit_width = 0x2;
|
||||
break;
|
||||
case 12:
|
||||
bit_width = 0x3;
|
||||
break;
|
||||
default:
|
||||
bit_width = 0x3;
|
||||
}
|
||||
pattern.val = (table.atten & 0x3) | ((bit_width) << 2) | ((table.channel & 0xF) << 4);
|
||||
|
||||
if (table.unit == ADC_NUM_1) {
|
||||
tab = SYSCON.saradc_sar1_patt_tab[index]; // Read old register value
|
||||
tab &= (~(0xFF000000 >> offset)); // clear old data
|
||||
tab |= ((uint32_t)pattern.val << 24) >> offset; // Fill in the new data
|
||||
@ -233,6 +284,15 @@ static inline void adc_ll_digi_clear_pattern_table(adc_ll_num_t adc_n)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable clock for ADC digital controller.
|
||||
* @note Not used for esp32
|
||||
*/
|
||||
static inline void adc_ll_digi_controller_clk_disable(void)
|
||||
{
|
||||
//Leave here for compatibility
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
PWDET(Power detect) controller setting
|
||||
---------------------------------------------------------------*/
|
||||
@ -263,6 +323,20 @@ static inline uint32_t adc_ll_pwdet_get_cct(void)
|
||||
/*---------------------------------------------------------------
|
||||
RTC controller setting
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* ADC SAR clock division factor setting. ADC SAR clock divided from `RTC_FAST_CLK`.
|
||||
*
|
||||
* @param div Division factor.
|
||||
*/
|
||||
static inline void adc_ll_set_sar_clk_div(adc_ll_num_t adc_n, uint32_t div)
|
||||
{
|
||||
if (adc_n == ADC_NUM_1) {
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_read_ctrl, sar1_clk_div, div);
|
||||
} else { // adc_n == ADC_NUM_2
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_read_ctrl2, sar2_clk_div, div);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set adc output data format for RTC controller.
|
||||
*
|
||||
@ -398,62 +472,6 @@ static inline adc_ll_rtc_raw_data_t adc_ll_rtc_analysis_raw_data(adc_ll_num_t ad
|
||||
return ADC_RTC_DATA_OK;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
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) {
|
||||
SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_PU;
|
||||
} else if (manage == ADC_POWER_BY_FSM) {
|
||||
SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_FSM;
|
||||
} else if (manage == ADC_POWER_SW_OFF) {
|
||||
SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_PD;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ADC module power management.
|
||||
*
|
||||
* @return
|
||||
* - ADC power status.
|
||||
*/
|
||||
static inline adc_ll_power_t adc_ll_get_power_manage(void)
|
||||
{
|
||||
/* Bit1 0:Fsm 1: SW mode
|
||||
Bit0 0:SW mode power down 1: SW mode power on */
|
||||
adc_ll_power_t manage;
|
||||
if (SENS.sar_meas_wait2.force_xpd_sar == SENS_FORCE_XPD_SAR_PU) {
|
||||
manage = ADC_POWER_SW_ON;
|
||||
} else if (SENS.sar_meas_wait2.force_xpd_sar == SENS_FORCE_XPD_SAR_PD) {
|
||||
manage = ADC_POWER_SW_OFF;
|
||||
} else {
|
||||
manage = ADC_POWER_BY_FSM;
|
||||
}
|
||||
return manage;
|
||||
}
|
||||
|
||||
/**
|
||||
* ADC SAR clock division factor setting. ADC SAR clock divided from `RTC_FAST_CLK`.
|
||||
*
|
||||
* @param div Division factor.
|
||||
*/
|
||||
static inline void adc_ll_set_sar_clk_div(adc_ll_num_t adc_n, uint32_t div)
|
||||
{
|
||||
if (adc_n == ADC_NUM_1) {
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_read_ctrl, sar1_clk_div, div);
|
||||
} else { // adc_n == ADC_NUM_2
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_read_ctrl2, sar2_clk_div, div);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the attenuation of a particular channel on ADCn.
|
||||
*/
|
||||
@ -482,6 +500,27 @@ static inline adc_atten_t adc_ll_get_atten(adc_ll_num_t adc_n, adc_channel_t cha
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
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) {
|
||||
SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_PU;
|
||||
} else if (manage == ADC_POWER_BY_FSM) {
|
||||
SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_FSM;
|
||||
} else if (manage == ADC_POWER_SW_OFF) {
|
||||
SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_PD;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set ADC module controller.
|
||||
* There are five SAR ADC controllers:
|
||||
@ -492,25 +531,25 @@ static inline adc_atten_t adc_ll_get_atten(adc_ll_num_t adc_n, adc_channel_t cha
|
||||
* @param adc_n ADC unit.
|
||||
* @param ctrl ADC controller.
|
||||
*/
|
||||
static inline void adc_ll_set_controller(adc_ll_num_t adc_n, adc_hal_controller_t ctrl)
|
||||
static inline void adc_ll_set_controller(adc_ll_num_t adc_n, adc_ll_controller_t ctrl)
|
||||
{
|
||||
if (adc_n == ADC_NUM_1) {
|
||||
switch ( ctrl ) {
|
||||
case ADC_CTRL_RTC:
|
||||
case ADC_LL_CTRL_RTC:
|
||||
SENS.sar_read_ctrl.sar1_dig_force = 0; // 1: Select digital control; 0: Select RTC control.
|
||||
SENS.sar_meas_start1.meas1_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start.
|
||||
SENS.sar_meas_start1.sar1_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map;
|
||||
SENS.sar_touch_ctrl1.xpd_hall_force = 1; // 1: SW control HALL power; 0: ULP FSM control HALL power.
|
||||
SENS.sar_touch_ctrl1.hall_phase_force = 1; // 1: SW control HALL phase; 0: ULP FSM control HALL phase.
|
||||
break;
|
||||
case ADC_CTRL_ULP:
|
||||
case ADC_LL_CTRL_ULP:
|
||||
SENS.sar_read_ctrl.sar1_dig_force = 0; // 1: Select digital control; 0: Select RTC control.
|
||||
SENS.sar_meas_start1.meas1_start_force = 0; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start.
|
||||
SENS.sar_meas_start1.sar1_en_pad_force = 0; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map;
|
||||
SENS.sar_touch_ctrl1.xpd_hall_force = 0; // 1: SW control HALL power; 0: ULP FSM control HALL power.
|
||||
SENS.sar_touch_ctrl1.hall_phase_force = 0; // 1: SW control HALL phase; 0: ULP FSM control HALL phase.
|
||||
break;
|
||||
case ADC_CTRL_DIG:
|
||||
case ADC_LL_CTRL_DIG:
|
||||
SENS.sar_read_ctrl.sar1_dig_force = 1; // 1: Select digital control; 0: Select RTC control.
|
||||
SENS.sar_meas_start1.meas1_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start.
|
||||
SENS.sar_meas_start1.sar1_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map;
|
||||
@ -522,28 +561,28 @@ static inline void adc_ll_set_controller(adc_ll_num_t adc_n, adc_hal_controller_
|
||||
}
|
||||
} else { // adc_n == ADC_NUM_2
|
||||
switch ( ctrl ) {
|
||||
case ADC_CTRL_RTC:
|
||||
case ADC_LL_CTRL_RTC:
|
||||
SENS.sar_meas_start2.meas2_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start.
|
||||
SENS.sar_meas_start2.sar2_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map;
|
||||
SENS.sar_read_ctrl2.sar2_dig_force = 0; // 1: Select digital control; 0: Select RTC control.
|
||||
SENS.sar_read_ctrl2.sar2_pwdet_force = 0; // 1: Select power detect control; 0: Select RTC control.
|
||||
SYSCON.saradc_ctrl.sar2_mux = 1; // 1: Select digital control; 0: Select power detect control.
|
||||
break;
|
||||
case ADC_CTRL_ULP:
|
||||
case ADC_LL_CTRL_ULP:
|
||||
SENS.sar_meas_start2.meas2_start_force = 0; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start.
|
||||
SENS.sar_meas_start2.sar2_en_pad_force = 0; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map;
|
||||
SENS.sar_read_ctrl2.sar2_dig_force = 0; // 1: Select digital control; 0: Select RTC control.
|
||||
SENS.sar_read_ctrl2.sar2_pwdet_force = 0; // 1: Select power detect control; 0: Select RTC control.
|
||||
SYSCON.saradc_ctrl.sar2_mux = 1; // 1: Select digital control; 0: Select power detect control.
|
||||
break;
|
||||
case ADC_CTRL_DIG:
|
||||
case ADC_LL_CTRL_DIG:
|
||||
SENS.sar_meas_start2.meas2_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start.
|
||||
SENS.sar_meas_start2.sar2_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map;
|
||||
SENS.sar_read_ctrl2.sar2_dig_force = 1; // 1: Select digital control; 0: Select RTC control.
|
||||
SENS.sar_read_ctrl2.sar2_pwdet_force = 0; // 1: Select power detect control; 0: Select RTC control.
|
||||
SYSCON.saradc_ctrl.sar2_mux = 1; // 1: Select digital control; 0: Select power detect control.
|
||||
break;
|
||||
case ADC2_CTRL_PWDET: // currently only used by Wi-Fi
|
||||
case ADC_LL_CTRL_PWDET: // currently only used by Wi-Fi
|
||||
SENS.sar_meas_start2.meas2_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start.
|
||||
SENS.sar_meas_start2.sar2_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map;
|
||||
SENS.sar_read_ctrl2.sar2_dig_force = 0; // 1: Select digital control; 0: Select RTC control.
|
||||
|
@ -1,16 +1,8 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// The HAL layer for ADC (ESP32-C3 specific part)
|
||||
|
||||
@ -32,56 +24,6 @@ static adc_digi_monitor_t s_monitor_config[SOC_ADC_DIGI_MONITOR_NUM] = {};
|
||||
/*---------------------------------------------------------------
|
||||
Digital controller setting
|
||||
---------------------------------------------------------------*/
|
||||
void adc_hal_digi_deinit(void)
|
||||
{
|
||||
adc_ll_digi_trigger_disable(); // boss
|
||||
adc_ll_digi_dma_disable();
|
||||
adc_ll_digi_clear_pattern_table(ADC_NUM_1);
|
||||
adc_ll_digi_clear_pattern_table(ADC_NUM_2);
|
||||
adc_ll_digi_filter_reset(ADC_NUM_1);
|
||||
adc_ll_digi_filter_reset(ADC_NUM_2);
|
||||
adc_ll_digi_reset();
|
||||
adc_ll_digi_controller_clk_disable();
|
||||
}
|
||||
|
||||
/**
|
||||
* - Set ADC digital controller clock division factor. The clock is divided from `APLL` or `APB` clock.
|
||||
* Expression: controller_clk = APLL/APB * (div_num + div_a / div_b + 1).
|
||||
* - Enable clock and select clock source for ADC digital controller.
|
||||
*/
|
||||
static void adc_hal_digi_clk_config(void)
|
||||
{
|
||||
//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_controller_clk_enable(0);
|
||||
}
|
||||
|
||||
void adc_hal_digi_controller_config(const adc_digi_config_t *cfg)
|
||||
{
|
||||
//only one pattern table is supported on C3, but LL still needs one argument.
|
||||
const int pattern_both = 0;
|
||||
|
||||
if (cfg->adc_pattern_len) {
|
||||
adc_ll_digi_clear_pattern_table(pattern_both);
|
||||
adc_ll_digi_set_pattern_table_len(pattern_both, cfg->adc_pattern_len);
|
||||
for (uint32_t i = 0; i < cfg->adc_pattern_len; i++) {
|
||||
adc_ll_digi_set_pattern_table(pattern_both, i, cfg->adc_pattern[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (cfg->conv_limit_en) {
|
||||
adc_ll_digi_set_convert_limit_num(cfg->conv_limit_num);
|
||||
adc_ll_digi_convert_limit_enable();
|
||||
} else {
|
||||
adc_ll_digi_convert_limit_disable();
|
||||
}
|
||||
|
||||
//clock
|
||||
uint32_t interval = APB_CLK_FREQ / (ADC_LL_CLKM_DIV_NUM_DEFAULT + ADC_LL_CLKM_DIV_A_DEFAULT / ADC_LL_CLKM_DIV_B_DEFAULT + 1) / 2 / cfg->sample_freq_hz;
|
||||
adc_ll_digi_set_trigger_interval(interval);
|
||||
adc_hal_digi_clk_config();
|
||||
}
|
||||
|
||||
static void filter_update(adc_digi_filter_idx_t idx)
|
||||
{
|
||||
//ESP32-C3 has no enable bit, the filter will be enabled when the filter channel is configured
|
||||
|
@ -1,16 +1,8 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* NOTICE
|
||||
@ -34,18 +26,6 @@ extern "C" {
|
||||
/*---------------------------------------------------------------
|
||||
Digital controller setting
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* Digital controller deinitialization.
|
||||
*/
|
||||
void adc_hal_digi_deinit(void);
|
||||
|
||||
/**
|
||||
* Setting the digital controller.
|
||||
*
|
||||
* @param cfg Pointer to digital controller paramter.
|
||||
*/
|
||||
void adc_hal_digi_controller_config(const adc_digi_config_t *cfg);
|
||||
|
||||
/**
|
||||
* Reset adc digital controller filter.
|
||||
*
|
||||
|
@ -1,30 +1,22 @@
|
||||
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include "hal/misc.h"
|
||||
#include "regi2c_ctrl.h"
|
||||
#include "esp_attr.h"
|
||||
|
||||
#include "soc/adc_periph.h"
|
||||
#include "hal/adc_types.h"
|
||||
#include "soc/apb_saradc_struct.h"
|
||||
#include "soc/apb_saradc_reg.h"
|
||||
#include "soc/rtc_cntl_struct.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "hal/misc.h"
|
||||
#include "hal/adc_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -54,6 +46,22 @@ typedef enum {
|
||||
ADC_RTC_DATA_FAIL = -1,
|
||||
} adc_ll_rtc_raw_data_t;
|
||||
|
||||
typedef enum {
|
||||
ADC_LL_CTRL_DIG = 0, ///< For ADC1. Select DIG controller.
|
||||
ADC_LL_CTRL_ARB = 1, ///< For ADC2. The controller is selected by the arbiter.
|
||||
} adc_ll_controller_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;
|
||||
|
||||
//These values should be set according to the HW
|
||||
typedef enum {
|
||||
ADC_LL_INTR_THRES1_LOW = BIT(26),
|
||||
@ -65,21 +73,17 @@ typedef enum {
|
||||
} adc_ll_intr_t;
|
||||
FLAG_ATTR(adc_ll_intr_t)
|
||||
|
||||
/**
|
||||
* @brief ADC controller type selection.
|
||||
*
|
||||
* @note For ADC2, use the force option with care. The system power consumption detection will use ADC2.
|
||||
* If it is forced to switch to another controller, it may cause the system to obtain incorrect values.
|
||||
* @note Normally, there is no need to switch the controller manually.
|
||||
*/
|
||||
typedef enum {
|
||||
ADC_CTRL_RTC = 0, /*!<For ADC1. Select RTC controller. For ADC2. The controller is selected by the arbiter. Arbiter in default mode. */
|
||||
ADC_CTRL_DIG = 2, /*!<For ADC1. Select DIG controller. For ADC2. The controller is selected by the arbiter. Arbiter in default mode. */
|
||||
ADC2_CTRL_PWDET = 3,/*!<For ADC2. The controller is selected by the arbiter. Arbiter in default mode. */
|
||||
ADC2_CTRL_FORCE_PWDET = 3, /*!<For ADC2. Arbiter in shield mode. Force select Wi-Fi controller work. */
|
||||
ADC2_CTRL_FORCE_RTC = 4, /*!<For ADC2. Arbiter in shield mode. Force select RTC controller work. */
|
||||
ADC2_CTRL_FORCE_DIG = 6, /*!<For ADC2. Arbiter in shield mode. Force select digital controller work. */
|
||||
} adc_ll_controller_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
|
||||
@ -157,6 +161,18 @@ static inline void adc_ll_digi_convert_limit_disable(void)
|
||||
APB_SARADC.ctrl2.meas_num_limit = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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,
|
||||
@ -181,16 +197,18 @@ static inline void adc_ll_digi_set_pattern_table_len(adc_ll_num_t adc_n, uint32_
|
||||
* @param pattern_index Items index. Range: 0 ~ 7.
|
||||
* @param pattern Stored conversion rules.
|
||||
*/
|
||||
static inline void adc_ll_digi_set_pattern_table(adc_ll_num_t adc_n, uint32_t pattern_index, adc_digi_pattern_table_t pattern)
|
||||
static inline void adc_ll_digi_set_pattern_table(adc_ll_num_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};
|
||||
|
||||
tab = APB_SARADC.sar_patt_tab[index].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.sar_patt_tab[index].sar_patt_tab1 = tab; // Write back
|
||||
pattern.val = (table.atten & 0x3) | ((table.channel & 0x7) << 2) | ((table.unit & 0x1) << 5);
|
||||
tab = APB_SARADC.sar_patt_tab[index].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.sar_patt_tab[index].sar_patt_tab1 = tab; // Write back
|
||||
}
|
||||
|
||||
/**
|
||||
@ -260,9 +278,9 @@ static inline void adc_ll_digi_trigger_disable(void)
|
||||
|
||||
/**
|
||||
* Set ADC digital controller clock division factor. The clock divided from `APLL` or `APB` clock.
|
||||
* Expression: controller_clk = APLL/APB * (div_num + div_b / div_a).
|
||||
* Expression: controller_clk = (APLL or APB) / (div_num + div_a / div_b + 1).
|
||||
*
|
||||
* @param div_num Division factor. Range: 1 ~ 255.
|
||||
* @param div_num Division factor. Range: 0 ~ 255.
|
||||
* @param div_b Division factor. Range: 1 ~ 63.
|
||||
* @param div_a Division factor. Range: 0 ~ 63.
|
||||
*/
|
||||
@ -278,7 +296,7 @@ static inline void adc_ll_digi_controller_clk_div(uint32_t div_num, uint32_t div
|
||||
*
|
||||
* @param use_apll true: use APLL clock; false: use APB clock.
|
||||
*/
|
||||
static inline void adc_ll_digi_controller_clk_enable(bool use_apll)
|
||||
static inline void adc_ll_digi_clk_sel(bool use_apll)
|
||||
{
|
||||
if (use_apll) {
|
||||
APB_SARADC.apb_adc_clkm_conf.clk_sel = 1; // APLL clock
|
||||
@ -494,8 +512,8 @@ static inline adc_ll_rtc_raw_data_t adc_ll_analysis_raw_data(adc_ll_num_t adc_n,
|
||||
*/
|
||||
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 */
|
||||
/* Bit1 0:Fsm 1: SW mode
|
||||
Bit0 0:SW mode power down 1: SW mode power on */
|
||||
if (manage == ADC_POWER_SW_ON) {
|
||||
APB_SARADC.ctrl.sar_clk_gated = 1;
|
||||
APB_SARADC.ctrl.xpd_sar_force = 3;
|
||||
@ -503,30 +521,14 @@ static inline void adc_ll_set_power_manage(adc_ll_power_t manage)
|
||||
APB_SARADC.ctrl.sar_clk_gated = 1;
|
||||
APB_SARADC.ctrl.xpd_sar_force = 0;
|
||||
} else if (manage == ADC_POWER_SW_OFF) {
|
||||
APB_SARADC.ctrl.xpd_sar_force = 2;
|
||||
APB_SARADC.ctrl.sar_clk_gated = 0;
|
||||
APB_SARADC.ctrl.xpd_sar_force = 2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ADC module power management.
|
||||
*
|
||||
* @return
|
||||
* - ADC power status.
|
||||
*/
|
||||
static inline adc_ll_power_t adc_ll_get_power_manage(void)
|
||||
static inline void adc_ll_set_controller(adc_ll_num_t adc_n, adc_ll_controller_t ctrl)
|
||||
{
|
||||
/* Bit1 0:Fsm 1: SW mode
|
||||
Bit0 0:SW mode power down 1: SW mode power on */
|
||||
adc_ll_power_t manage;
|
||||
if (APB_SARADC.ctrl.xpd_sar_force == 3) {
|
||||
manage = ADC_POWER_SW_ON;
|
||||
} else if (APB_SARADC.ctrl.xpd_sar_force == 2) {
|
||||
manage = ADC_POWER_SW_OFF;
|
||||
} else {
|
||||
manage = ADC_POWER_BY_FSM;
|
||||
}
|
||||
return manage;
|
||||
//Not used on ESP32C3
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,165 +0,0 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// The HAL layer for ADC (ESP32-H2 specific part)
|
||||
|
||||
#include <string.h>
|
||||
#include "soc/soc_caps.h"
|
||||
#include "hal/adc_hal.h"
|
||||
#include "hal/adc_types.h"
|
||||
#include "soc/soc.h"
|
||||
|
||||
//Currently we don't have context for the ADC HAL. So HAL variables are temporarily put here. But
|
||||
//please don't follow this code. Create a context for your own HAL!
|
||||
|
||||
static bool s_filter_enabled[SOC_ADC_DIGI_FILTER_NUM] = {};
|
||||
static adc_digi_filter_t s_filter[SOC_ADC_DIGI_FILTER_NUM] = {};
|
||||
|
||||
static bool s_monitor_enabled[SOC_ADC_DIGI_MONITOR_NUM] = {};
|
||||
static adc_digi_monitor_t s_monitor_config[SOC_ADC_DIGI_MONITOR_NUM] = {};
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Digital controller setting
|
||||
---------------------------------------------------------------*/
|
||||
void adc_hal_digi_deinit(void)
|
||||
{
|
||||
adc_ll_digi_trigger_disable(); // boss
|
||||
adc_ll_digi_dma_disable();
|
||||
adc_ll_digi_clear_pattern_table(ADC_NUM_1);
|
||||
adc_ll_digi_clear_pattern_table(ADC_NUM_2);
|
||||
adc_ll_digi_filter_reset(ADC_NUM_1);
|
||||
adc_ll_digi_filter_reset(ADC_NUM_2);
|
||||
adc_ll_digi_reset();
|
||||
adc_ll_digi_controller_clk_disable();
|
||||
}
|
||||
|
||||
/**
|
||||
* - Set ADC digital controller clock division factor. The clock is divided from `APLL` or `APB` clock.
|
||||
* Expression: controller_clk = APLL/APB * (div_num + div_a / div_b + 1).
|
||||
* - Enable clock and select clock source for ADC digital controller.
|
||||
*/
|
||||
static void adc_hal_digi_clk_config(void)
|
||||
{
|
||||
//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_controller_clk_enable(0);
|
||||
}
|
||||
|
||||
void adc_hal_digi_controller_config(const adc_digi_config_t *cfg)
|
||||
{
|
||||
//only one pattern table is supported on H2, but LL still needs one argument.
|
||||
const int pattern_both = 0;
|
||||
|
||||
if (cfg->adc_pattern_len) {
|
||||
adc_ll_digi_clear_pattern_table(pattern_both);
|
||||
adc_ll_digi_set_pattern_table_len(pattern_both, cfg->adc_pattern_len);
|
||||
for (uint32_t i = 0; i < cfg->adc_pattern_len; i++) {
|
||||
adc_ll_digi_set_pattern_table(pattern_both, i, cfg->adc_pattern[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (cfg->conv_limit_en) {
|
||||
adc_ll_digi_set_convert_limit_num(cfg->conv_limit_num);
|
||||
adc_ll_digi_convert_limit_enable();
|
||||
} else {
|
||||
adc_ll_digi_convert_limit_disable();
|
||||
}
|
||||
|
||||
//clock
|
||||
uint32_t interval = APB_CLK_FREQ / (ADC_LL_CLKM_DIV_NUM_DEFAULT + ADC_LL_CLKM_DIV_A_DEFAULT / ADC_LL_CLKM_DIV_B_DEFAULT + 1) / 2 / cfg->sample_freq_hz;
|
||||
adc_ll_digi_set_trigger_interval(interval);
|
||||
adc_hal_digi_clk_config();
|
||||
}
|
||||
|
||||
static void filter_update(adc_digi_filter_idx_t idx)
|
||||
{
|
||||
//ESP32-H2 has no enable bit, the filter will be enabled when the filter channel is configured
|
||||
if (s_filter_enabled[idx]) {
|
||||
adc_ll_digi_filter_set_factor(idx, &s_filter[idx]);
|
||||
} else {
|
||||
adc_ll_digi_filter_disable(idx);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set adc digital controller filter factor.
|
||||
*
|
||||
* @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).
|
||||
*/
|
||||
void adc_hal_digi_filter_set_factor(adc_digi_filter_idx_t idx, adc_digi_filter_t *filter)
|
||||
{
|
||||
s_filter[idx] = *filter;
|
||||
filter_update(idx);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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).
|
||||
*/
|
||||
void adc_hal_digi_filter_get_factor(adc_digi_filter_idx_t idx, adc_digi_filter_t *filter)
|
||||
{
|
||||
*filter = s_filter[idx];
|
||||
}
|
||||
|
||||
void adc_hal_digi_filter_enable(adc_digi_filter_idx_t filter_idx, bool enable)
|
||||
{
|
||||
s_filter_enabled[filter_idx] = enable;
|
||||
filter_update(filter_idx);
|
||||
}
|
||||
|
||||
static void update_monitor(adc_digi_monitor_idx_t idx)
|
||||
{
|
||||
//ESP32-H2 has no enable bit, the monitor will be enabled when the monitor channel is configured
|
||||
if (s_monitor_enabled[idx]) {
|
||||
adc_ll_digi_monitor_set_mode(idx, &s_monitor_config[idx]);
|
||||
} else {
|
||||
adc_ll_digi_monitor_disable(idx);
|
||||
}
|
||||
}
|
||||
|
||||
void adc_hal_digi_monitor_config(adc_digi_monitor_idx_t idx, adc_digi_monitor_t *config)
|
||||
{
|
||||
s_monitor_config[idx] = *config;
|
||||
update_monitor(idx);
|
||||
}
|
||||
|
||||
void adc_hal_digi_monitor_enable(adc_digi_monitor_idx_t mon_idx, bool enable)
|
||||
{
|
||||
s_monitor_enabled[mon_idx] = enable;
|
||||
update_monitor(mon_idx);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Common setting
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Config ADC2 module arbiter.
|
||||
* The arbiter is to improve the use efficiency of ADC2. After the control right is robbed by the high priority,
|
||||
* the low priority controller will read the invalid ADC2 data, and the validity of the data can be judged by the flag bit in the data.
|
||||
*
|
||||
* @note Only ADC2 support arbiter.
|
||||
* @note The arbiter's working clock is APB_CLK. When the APB_CLK clock drops below 8 MHz, the arbiter must be in shield mode.
|
||||
* @note Default priority: Wi-Fi > RTC > Digital;
|
||||
*
|
||||
* @param config Refer to `adc_arbiter_t`.
|
||||
*/
|
||||
void adc_hal_arbiter_config(adc_arbiter_t *config)
|
||||
{
|
||||
adc_ll_set_arbiter_work_mode(config->mode);
|
||||
adc_ll_set_arbiter_priority(config->rtc_pri, config->dig_pri, config->pwdet_pri);
|
||||
}
|
@ -1,119 +0,0 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/*******************************************************************************
|
||||
* NOTICE
|
||||
* The hal is not public api, don't use in application code.
|
||||
* See readme.md in soc/include/hal/readme.md
|
||||
******************************************************************************/
|
||||
|
||||
// The HAL layer for ADC (esp32s2 specific part)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hal/adc_ll.h"
|
||||
#include "hal/adc_types.h"
|
||||
|
||||
#include_next "hal/adc_hal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Digital controller setting
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* Digital controller deinitialization.
|
||||
*/
|
||||
void adc_hal_digi_deinit(void);
|
||||
|
||||
/**
|
||||
* Setting the digital controller.
|
||||
*
|
||||
* @param cfg Pointer to digital controller paramter.
|
||||
*/
|
||||
void adc_hal_digi_controller_config(const adc_digi_config_t *cfg);
|
||||
|
||||
/**
|
||||
* Reset adc digital controller filter.
|
||||
*
|
||||
* @param filter_idx ADC filter unit.
|
||||
*/
|
||||
#define adc_hal_digi_filter_reset(filter_idx) adc_ll_digi_filter_reset(filter_idx)
|
||||
|
||||
/**
|
||||
* Set adc digital controller filter factor.
|
||||
*
|
||||
* @param filter_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).
|
||||
*/
|
||||
void adc_hal_digi_filter_set_factor(adc_digi_filter_idx_t filter_idx, adc_digi_filter_t *filter);
|
||||
|
||||
/**
|
||||
* Get adc digital controller filter factor.
|
||||
*
|
||||
* @param filter_idx ADC filter unit.
|
||||
* @param factor Expression: filter_data = (k-1)/k * last_data + new_data / k. Set values: (2, 4, 8, 16, 64).
|
||||
*/
|
||||
void adc_hal_digi_filter_get_factor(adc_digi_filter_idx_t filter_idx, adc_digi_filter_t *filter);
|
||||
|
||||
/**
|
||||
* Enable/disable adc digital controller filter.
|
||||
* Filtering the ADC data to obtain smooth data at higher sampling rates.
|
||||
*
|
||||
* @note The filter will filter all the enabled channel data of the each ADC unit at the same time.
|
||||
* @param filter_idx ADC filter unit.
|
||||
* @param enable True to enable the filter, otherwise disable.
|
||||
*/
|
||||
void adc_hal_digi_filter_enable(adc_digi_filter_idx_t filter_idx, bool enable);
|
||||
|
||||
/**
|
||||
* Config monitor of adc digital controller.
|
||||
*
|
||||
* @note If the channel info is not supported, the monitor function will not be enabled.
|
||||
* @param mon_idx ADC monitor index.
|
||||
* @param config Refer to `adc_digi_monitor_t`.
|
||||
*/
|
||||
void adc_hal_digi_monitor_config(adc_digi_monitor_idx_t mon_idx, adc_digi_monitor_t *config);
|
||||
|
||||
/**
|
||||
* Enable/disable monitor of adc digital controller.
|
||||
*
|
||||
* @note The monitor will monitor all the enabled channel data of the each ADC unit at the same time.
|
||||
* @param mon_idx ADC monitor index.
|
||||
* @param enable True to enable the monitor, otherwise disable.
|
||||
*/
|
||||
void adc_hal_digi_monitor_enable(adc_digi_monitor_idx_t mon_idx, bool enable);
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Common setting
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Config ADC2 module arbiter.
|
||||
* The arbiter is to improve the use efficiency of ADC2. After the control right is robbed by the high priority,
|
||||
* the low priority controller will read the invalid ADC2 data, and the validity of the data can be judged by the flag bit in the data.
|
||||
*
|
||||
* @note Only ADC2 support arbiter.
|
||||
* @note The arbiter's working clock is APB_CLK. When the APB_CLK clock drops below 8 MHz, the arbiter must be in shield mode.
|
||||
* @note Default priority: Wi-Fi > RTC > Digital;
|
||||
*
|
||||
* @param config Refer to `adc_arbiter_t`.
|
||||
*/
|
||||
void adc_hal_arbiter_config(adc_arbiter_t *config);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,16 +1,8 @@
|
||||
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
@ -54,6 +46,22 @@ typedef enum {
|
||||
ADC_RTC_DATA_FAIL = -1,
|
||||
} adc_ll_rtc_raw_data_t;
|
||||
|
||||
typedef enum {
|
||||
ADC_LL_CTRL_DIG = 0, ///< For ADC1. Select DIG controller.
|
||||
ADC_LL_CTRL_ARB = 1, ///< For ADC2. The controller is selected by the arbiter.
|
||||
} adc_ll_controller_t;
|
||||
|
||||
/**
|
||||
* @brief ADC digital controller (DMA mode) work mode.
|
||||
*
|
||||
* @note The conversion mode affects the sampling frequency:
|
||||
* ESP32H2 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;
|
||||
|
||||
//These values should be set according to the HW
|
||||
typedef enum {
|
||||
ADC_LL_INTR_THRES1_LOW = BIT(26),
|
||||
@ -65,21 +73,17 @@ typedef enum {
|
||||
} adc_ll_intr_t;
|
||||
FLAG_ATTR(adc_ll_intr_t)
|
||||
|
||||
/**
|
||||
* @brief ADC controller type selection.
|
||||
*
|
||||
* @note For ADC2, use the force option with care. The system power consumption detection will use ADC2.
|
||||
* If it is forced to switch to another controller, it may cause the system to obtain incorrect values.
|
||||
* @note Normally, there is no need to switch the controller manually.
|
||||
*/
|
||||
typedef enum {
|
||||
ADC_CTRL_RTC = 0, /*!<For ADC1. Select RTC controller. For ADC2. The controller is selected by the arbiter. Arbiter in default mode. */
|
||||
ADC_CTRL_DIG = 2, /*!<For ADC1. Select DIG controller. For ADC2. The controller is selected by the arbiter. Arbiter in default mode. */
|
||||
ADC2_CTRL_PWDET = 3,/*!<For ADC2. The controller is selected by the arbiter. Arbiter in default mode. */
|
||||
ADC2_CTRL_FORCE_PWDET = 3, /*!<For ADC2. Arbiter in shield mode. Force select Wi-Fi controller work. */
|
||||
ADC2_CTRL_FORCE_RTC = 4, /*!<For ADC2. Arbiter in shield mode. Force select RTC controller work. */
|
||||
ADC2_CTRL_FORCE_DIG = 6, /*!<For ADC2. Arbiter in shield mode. Force select digital controller work. */
|
||||
} adc_ll_controller_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
|
||||
@ -157,6 +161,18 @@ static inline void adc_ll_digi_convert_limit_disable(void)
|
||||
APB_SARADC.ctrl2.meas_num_limit = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set adc conversion mode for digital controller.
|
||||
*
|
||||
* @note ESP32H2 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)
|
||||
{
|
||||
//ESP32H2 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,
|
||||
@ -181,16 +197,18 @@ static inline void adc_ll_digi_set_pattern_table_len(adc_ll_num_t adc_n, uint32_
|
||||
* @param pattern_index Items index. Range: 0 ~ 7.
|
||||
* @param pattern Stored conversion rules.
|
||||
*/
|
||||
static inline void adc_ll_digi_set_pattern_table(adc_ll_num_t adc_n, uint32_t pattern_index, adc_digi_pattern_table_t pattern)
|
||||
static inline void adc_ll_digi_set_pattern_table(adc_ll_num_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};
|
||||
|
||||
tab = APB_SARADC.sar_patt_tab[index].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.sar_patt_tab[index].sar_patt_tab1 = tab; // Write back
|
||||
pattern.val = (table.atten & 0x3) | ((table.channel & 0x7) << 2) | ((table.unit & 0x1) << 5);
|
||||
tab = APB_SARADC.sar_patt_tab[index].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.sar_patt_tab[index].sar_patt_tab1 = tab; // Write back
|
||||
}
|
||||
|
||||
/**
|
||||
@ -260,9 +278,9 @@ static inline void adc_ll_digi_trigger_disable(void)
|
||||
|
||||
/**
|
||||
* Set ADC digital controller clock division factor. The clock divided from `APLL` or `APB` clock.
|
||||
* Expression: controller_clk = APLL/APB * (div_num + div_b / div_a).
|
||||
* Expression: controller_clk = (APLL or APB) / (div_num + div_a / div_b + 1).
|
||||
*
|
||||
* @param div_num Division factor. Range: 1 ~ 255.
|
||||
* @param div_num Division factor. Range: 0 ~ 255.
|
||||
* @param div_b Division factor. Range: 1 ~ 63.
|
||||
* @param div_a Division factor. Range: 0 ~ 63.
|
||||
*/
|
||||
@ -278,7 +296,7 @@ static inline void adc_ll_digi_controller_clk_div(uint32_t div_num, uint32_t div
|
||||
*
|
||||
* @param use_apll true: use APLL clock; false: use APB clock.
|
||||
*/
|
||||
static inline void adc_ll_digi_controller_clk_enable(bool use_apll)
|
||||
static inline void adc_ll_digi_clk_sel(bool use_apll)
|
||||
{
|
||||
if (use_apll) {
|
||||
APB_SARADC.apb_adc_clkm_conf.clk_sel = 1; // APLL clock
|
||||
@ -445,8 +463,7 @@ static inline void adc_ll_digi_reset(void)
|
||||
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;
|
||||
abort(); // ESP32H2-TODO: IDF-3389
|
||||
abort();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -458,9 +475,7 @@ static inline void adc_ll_pwdet_set_cct(uint32_t cct)
|
||||
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;
|
||||
abort(); // ESP32H2-TODO: IDF-3389
|
||||
return 0;
|
||||
abort();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -497,8 +512,8 @@ static inline adc_ll_rtc_raw_data_t adc_ll_analysis_raw_data(adc_ll_num_t adc_n,
|
||||
*/
|
||||
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 */
|
||||
/* Bit1 0:Fsm 1: SW mode
|
||||
Bit0 0:SW mode power down 1: SW mode power on */
|
||||
if (manage == ADC_POWER_SW_ON) {
|
||||
APB_SARADC.ctrl.sar_clk_gated = 1;
|
||||
APB_SARADC.ctrl.xpd_sar_force = 3;
|
||||
@ -506,30 +521,14 @@ static inline void adc_ll_set_power_manage(adc_ll_power_t manage)
|
||||
APB_SARADC.ctrl.sar_clk_gated = 1;
|
||||
APB_SARADC.ctrl.xpd_sar_force = 0;
|
||||
} else if (manage == ADC_POWER_SW_OFF) {
|
||||
APB_SARADC.ctrl.xpd_sar_force = 2;
|
||||
APB_SARADC.ctrl.sar_clk_gated = 0;
|
||||
APB_SARADC.ctrl.xpd_sar_force = 2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ADC module power management.
|
||||
*
|
||||
* @return
|
||||
* - ADC power status.
|
||||
*/
|
||||
static inline adc_ll_power_t adc_ll_get_power_manage(void)
|
||||
static inline void adc_ll_set_controller(adc_ll_num_t adc_n, adc_ll_controller_t ctrl)
|
||||
{
|
||||
/* Bit1 0:Fsm 1: SW mode
|
||||
Bit0 0:SW mode power down 1: SW mode power on */
|
||||
adc_ll_power_t manage;
|
||||
if (APB_SARADC.ctrl.xpd_sar_force == 3) {
|
||||
manage = ADC_POWER_SW_ON;
|
||||
} else if (APB_SARADC.ctrl.xpd_sar_force == 2) {
|
||||
manage = ADC_POWER_SW_OFF;
|
||||
} else {
|
||||
manage = ADC_POWER_BY_FSM;
|
||||
}
|
||||
return manage;
|
||||
//Not used on ESP32H2
|
||||
}
|
||||
|
||||
/**
|
||||
@ -688,7 +687,7 @@ static inline void adc_ll_set_calibration_param(adc_ll_num_t adc_n, uint32_t par
|
||||
*/
|
||||
static inline void adc_ll_vref_output(adc_ll_num_t adc, adc_channel_t channel, bool en)
|
||||
{
|
||||
// ESP32H2-TODO: IDF-3389
|
||||
abort();
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
|
@ -1,123 +0,0 @@
|
||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// The HAL layer for ADC (ESP32-S2 specific part)
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "hal/adc_hal.h"
|
||||
#include "hal/adc_types.h"
|
||||
#include "hal/adc_hal_conf.h"
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Digital controller setting
|
||||
---------------------------------------------------------------*/
|
||||
void adc_hal_digi_deinit(void)
|
||||
{
|
||||
adc_ll_digi_trigger_disable(); // boss
|
||||
adc_ll_digi_dma_disable();
|
||||
adc_ll_digi_clear_pattern_table(ADC_NUM_1);
|
||||
adc_ll_digi_clear_pattern_table(ADC_NUM_2);
|
||||
adc_ll_digi_filter_reset(ADC_NUM_1);
|
||||
adc_ll_digi_filter_reset(ADC_NUM_2);
|
||||
adc_ll_digi_reset();
|
||||
adc_ll_digi_controller_clk_disable();
|
||||
}
|
||||
|
||||
void adc_hal_digi_controller_config(const adc_digi_config_t *cfg)
|
||||
{
|
||||
/* Single channel mode or multi channel mode. */
|
||||
adc_ll_digi_set_convert_mode(cfg->conv_mode);
|
||||
if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_1) {
|
||||
if (cfg->adc1_pattern_len) {
|
||||
adc_ll_digi_clear_pattern_table(ADC_NUM_1);
|
||||
adc_ll_digi_set_pattern_table_len(ADC_NUM_1, cfg->adc1_pattern_len);
|
||||
for (uint32_t i = 0; i < cfg->adc1_pattern_len; i++) {
|
||||
adc_ll_digi_set_pattern_table(ADC_NUM_1, i, cfg->adc1_pattern[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_2) {
|
||||
if (cfg->adc2_pattern_len) {
|
||||
adc_ll_digi_clear_pattern_table(ADC_NUM_2);
|
||||
adc_ll_digi_set_pattern_table_len(ADC_NUM_2, cfg->adc2_pattern_len);
|
||||
for (uint32_t i = 0; i < cfg->adc2_pattern_len; i++) {
|
||||
adc_ll_digi_set_pattern_table(ADC_NUM_2, i, cfg->adc2_pattern[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_1) {
|
||||
adc_ll_set_controller(ADC_NUM_1, ADC_CTRL_DIG);
|
||||
}
|
||||
if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_2) {
|
||||
adc_ll_set_controller(ADC_NUM_2, ADC_CTRL_DIG);
|
||||
}
|
||||
adc_ll_digi_set_output_format(cfg->format);
|
||||
if (cfg->conv_limit_en) {
|
||||
adc_ll_digi_set_convert_limit_num(cfg->conv_limit_num);
|
||||
adc_ll_digi_convert_limit_enable();
|
||||
} else {
|
||||
adc_ll_digi_convert_limit_disable();
|
||||
}
|
||||
|
||||
adc_ll_digi_set_trigger_interval(cfg->interval);
|
||||
adc_hal_digi_clk_config(&cfg->dig_clk);
|
||||
adc_ll_digi_dma_set_eof_num(cfg->dma_eof_num);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set ADC digital controller clock division factor. The clock divided from `APLL` or `APB` clock.
|
||||
* Enable clock and select clock source for ADC digital controller.
|
||||
* Expression: controller_clk = (`APLL` or `APB`) / (div_num + div_a / div_b + 1).
|
||||
*
|
||||
* @note ADC and DAC digital controller share the same frequency divider.
|
||||
* Please set a reasonable frequency division factor to meet the sampling frequency of the ADC and the output frequency of the DAC.
|
||||
*
|
||||
* @param clk Refer to ``adc_digi_clk_t``.
|
||||
*/
|
||||
void adc_hal_digi_clk_config(const adc_digi_clk_t *clk)
|
||||
{
|
||||
adc_ll_digi_controller_clk_div(clk->div_num, clk->div_b, clk->div_a);
|
||||
adc_ll_digi_controller_clk_enable(clk->use_apll);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable digital controller to trigger the measurement.
|
||||
*/
|
||||
void adc_hal_digi_enable(void)
|
||||
{
|
||||
adc_ll_digi_dma_enable();
|
||||
adc_ll_digi_trigger_enable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable digital controller to trigger the measurement.
|
||||
*/
|
||||
void adc_hal_digi_disable(void)
|
||||
{
|
||||
adc_ll_digi_trigger_disable();
|
||||
adc_ll_digi_dma_disable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Config monitor of adc digital controller.
|
||||
*
|
||||
* @note The monitor will monitor all the enabled channel data of the each ADC unit at the same time.
|
||||
* @param adc_n ADC unit.
|
||||
* @param config Refer to ``adc_digi_monitor_t``.
|
||||
*/
|
||||
void adc_hal_digi_monitor_config(adc_ll_num_t adc_n, adc_digi_monitor_t *config)
|
||||
{
|
||||
adc_ll_digi_monitor_set_mode(adc_n, config->mode);
|
||||
adc_ll_digi_monitor_set_thres(adc_n, config->threshold);
|
||||
}
|
@ -1,21 +1,13 @@
|
||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// The HAL layer for ADC (esp32s2 specific part)
|
||||
|
||||
#include "hal/dac_hal.h"
|
||||
#include "hal/adc_hal.h"
|
||||
#include "hal/adc_ll.h"
|
||||
#include "hal/dac_types.h"
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
@ -39,7 +31,8 @@ void dac_hal_digi_controller_config(const dac_digi_config_t *cfg)
|
||||
{
|
||||
dac_ll_digi_set_convert_mode(cfg->mode);
|
||||
dac_ll_digi_set_trigger_interval(cfg->interval);
|
||||
adc_hal_digi_clk_config(&cfg->dig_clk);
|
||||
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);
|
||||
}
|
||||
|
||||
void dac_hal_digi_start(void)
|
||||
|
@ -1,202 +0,0 @@
|
||||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/*******************************************************************************
|
||||
* NOTICE
|
||||
* The hal is not public api, don't use in application code.
|
||||
* See readme.md in hal/include/hal/readme.md
|
||||
******************************************************************************/
|
||||
|
||||
// The HAL layer for ADC (esp32s2 specific part)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hal/adc_ll.h"
|
||||
#include "hal/adc_types.h"
|
||||
|
||||
#include_next "hal/adc_hal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Digital controller setting
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* ADC Digital controller output data invert or not.
|
||||
*
|
||||
* @param adc_n ADC unit.
|
||||
* @param inv_en data invert or not.
|
||||
*/
|
||||
#define adc_hal_digi_output_invert(adc_n, inv_en) adc_ll_digi_output_invert(adc_n, inv_en)
|
||||
|
||||
/**
|
||||
* Sets the number of interval clock cycles for the digital controller to trigger the measurement.
|
||||
* Expression: `trigger_meas_freq` = `controller_clk` / 2 / interval. Refer to ``adc_digi_clk_t``.
|
||||
*
|
||||
* @note The trigger interval should not be less than the sampling time of the SAR ADC.
|
||||
* @param cycle The number of clock cycles for the trigger interval. The unit is the divided clock. Range: 40 ~ 4095.
|
||||
*/
|
||||
#define adc_hal_digi_set_trigger_interval(cycle) adc_ll_digi_set_trigger_interval(cycle)
|
||||
|
||||
/**
|
||||
* Enable digital controller to trigger the measurement.
|
||||
*/
|
||||
void adc_hal_digi_enable(void);
|
||||
|
||||
/**
|
||||
* Disable digital controller to trigger the measurement.
|
||||
*/
|
||||
void adc_hal_digi_disable(void);
|
||||
|
||||
/**
|
||||
* Set ADC digital controller clock division factor. The clock divided from `APLL` or `APB` clock.
|
||||
* Enable clock and select clock source for ADC digital controller.
|
||||
* Expression: controller_clk = (`APLL` or `APB`) / (div_num + div_a / div_b + 1).
|
||||
*
|
||||
* @note ADC and DAC digital controller share the same frequency divider.
|
||||
* Please set a reasonable frequency division factor to meet the sampling frequency of the ADC and the output frequency of the DAC.
|
||||
*
|
||||
* @param clk Refer to ``adc_digi_clk_t``.
|
||||
*/
|
||||
void adc_hal_digi_clk_config(const adc_digi_clk_t *clk);
|
||||
|
||||
/**
|
||||
* Reset adc digital controller filter.
|
||||
*
|
||||
* @param adc_n ADC unit.
|
||||
*/
|
||||
#define adc_hal_digi_filter_reset(adc_n) adc_ll_digi_filter_reset(adc_n)
|
||||
|
||||
/**
|
||||
* Set 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).
|
||||
*/
|
||||
#define adc_hal_digi_filter_set_factor(adc_n, factor) adc_ll_digi_filter_set_factor(adc_n, factor)
|
||||
|
||||
/**
|
||||
* 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).
|
||||
*/
|
||||
#define adc_hal_digi_filter_get_factor(adc_n, factor) adc_ll_digi_filter_get_factor(adc_n, factor)
|
||||
|
||||
/**
|
||||
* Enable/disable adc digital controller filter.
|
||||
* Filtering the ADC data to obtain smooth data at higher sampling rates.
|
||||
*
|
||||
* @note The filter will filter all the enabled channel data of the each ADC unit at the same time.
|
||||
* @param adc_n ADC unit.
|
||||
*/
|
||||
#define adc_hal_digi_filter_enable(adc_n, enable) adc_ll_digi_filter_enable(adc_n, enable)
|
||||
|
||||
/**
|
||||
* Get the filtered data of adc digital controller filter.
|
||||
* The data after each measurement and filtering is updated to the DMA by the digital controller. But it can also be obtained manually through this API.
|
||||
*
|
||||
* @note The filter will filter all the enabled channel data of the each ADC unit at the same time.
|
||||
* @param adc_n ADC unit.
|
||||
* @return Filtered data.
|
||||
*/
|
||||
#define adc_hal_digi_filter_read_data(adc_n) adc_ll_digi_filter_read_data(adc_n)
|
||||
|
||||
/**
|
||||
* Config monitor of adc digital controller.
|
||||
*
|
||||
* @note The monitor will monitor all the enabled channel data of the each ADC unit at the same time.
|
||||
* @param adc_n ADC unit.
|
||||
* @param config Refer to ``adc_digi_monitor_t``.
|
||||
*/
|
||||
void adc_hal_digi_monitor_config(adc_ll_num_t adc_n, adc_digi_monitor_t *config);
|
||||
|
||||
/**
|
||||
* Enable/disable monitor of adc digital controller.
|
||||
*
|
||||
* @note The monitor will monitor all the enabled channel data of the each ADC unit at the same time.
|
||||
* @param adc_n ADC unit.
|
||||
*/
|
||||
#define adc_hal_digi_monitor_enable(adc_n, enable) adc_ll_digi_monitor_enable(adc_n, enable)
|
||||
|
||||
/**
|
||||
* Enable interrupt of adc digital controller by bitmask.
|
||||
*
|
||||
* @param adc_n ADC unit.
|
||||
* @param intr Interrupt bitmask.
|
||||
*/
|
||||
#define adc_hal_digi_intr_enable(adc_n, intr) adc_ll_digi_intr_enable(adc_n, intr)
|
||||
|
||||
/**
|
||||
* Disable interrupt of adc digital controller by bitmask.
|
||||
*
|
||||
* @param adc_n ADC unit.
|
||||
* @param intr Interrupt bitmask.
|
||||
*/
|
||||
#define adc_hal_digi_intr_disable(adc_n, intr) adc_ll_digi_intr_disable(adc_n, intr)
|
||||
|
||||
/**
|
||||
* Clear interrupt of adc digital controller by bitmask.
|
||||
*
|
||||
* @param adc_n ADC unit.
|
||||
* @param intr Interrupt bitmask.
|
||||
*/
|
||||
#define adc_hal_digi_intr_clear(adc_n, intr) adc_ll_digi_intr_clear(adc_n, intr)
|
||||
|
||||
/**
|
||||
* Get interrupt status mask of adc digital controller.
|
||||
*
|
||||
* @param adc_n ADC unit.
|
||||
* @return
|
||||
* - intr Interrupt bitmask.
|
||||
*/
|
||||
#define adc_hal_digi_get_intr_status(adc_n) adc_ll_digi_get_intr_status(adc_n)
|
||||
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
#define adc_hal_digi_dma_set_eof_num(num) adc_ll_digi_dma_set_eof_num(num)
|
||||
|
||||
/**
|
||||
* Enable output data to DMA from adc digital controller.
|
||||
*/
|
||||
#define adc_hal_digi_dma_enable() adc_ll_digi_dma_enable()
|
||||
|
||||
/**
|
||||
* Disable output data to DMA from adc digital controller.
|
||||
*/
|
||||
#define adc_hal_digi_dma_disable() adc_ll_digi_dma_disable()
|
||||
|
||||
/**
|
||||
* Reset adc digital controller.
|
||||
*/
|
||||
#define adc_hal_digi_reset() adc_ll_digi_reset()
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
RTC controller setting
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* Reset RTC controller FSM.
|
||||
*/
|
||||
#define adc_hal_rtc_reset() adc_ll_rtc_reset()
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,3 +1,9 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
@ -15,6 +21,11 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//To be checked if ESP32S2 has the 5M freq limit
|
||||
#define ADC_LL_CLKM_DIV_NUM_DEFAULT 15
|
||||
#define ADC_LL_CLKM_DIV_B_DEFAULT 1
|
||||
#define ADC_LL_CLKM_DIV_A_DEFAULT 0
|
||||
|
||||
typedef enum {
|
||||
ADC_NUM_1 = 0, /*!< SAR ADC 1 */
|
||||
ADC_NUM_2 = 1, /*!< SAR ADC 2 */
|
||||
@ -35,6 +46,40 @@ typedef enum {
|
||||
ADC_RTC_DATA_FAIL = -1,
|
||||
} adc_ll_rtc_raw_data_t;
|
||||
|
||||
typedef enum {
|
||||
ADC_LL_CTRL_RTC = 0, ///< For ADC1. Select RTC controller.
|
||||
ADC_LL_CTRL_ULP = 1, ///< For ADC1 and ADC2. Select ULP controller.
|
||||
ADC_LL_CTRL_DIG = 2, ///< For ADC1. Select DIG controller.
|
||||
ADC_LL_CTRL_ARB = 3, ///< For ADC2. The controller is selected by the arbiter.
|
||||
} adc_ll_controller_t;
|
||||
|
||||
/**
|
||||
* @brief ADC digital controller (DMA mode) work mode.
|
||||
*
|
||||
* @note The conversion mode affects the sampling frequency:
|
||||
* SINGLE_UNIT_1: When the measurement is triggered, only ADC1 is sampled once.
|
||||
* SINGLE_UNIT_2: When the measurement is triggered, only ADC2 is sampled once.
|
||||
* BOTH_UNIT : When the measurement is triggered, ADC1 and ADC2 are sampled at the same time.
|
||||
* ALTER_UNIT : When the measurement is triggered, ADC1 or ADC2 samples alternately.
|
||||
*/
|
||||
typedef enum {
|
||||
ADC_LL_DIGI_CONV_ONLY_ADC1 = 0, // Only use ADC1 for conversion
|
||||
ADC_LL_DIGI_CONV_ONLY_ADC2 = 1, // Only use ADC2 for conversion
|
||||
ADC_LL_DIGI_CONV_BOTH_UNIT = 2, // Use Both ADC1 and ADC2 for conversion simultaneously
|
||||
ADC_LL_DIGI_CONV_ALTER_UNIT = 3 // 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 reserved: 2;
|
||||
uint8_t channel: 4;
|
||||
};
|
||||
uint8_t val;
|
||||
};
|
||||
} __attribute__((packed)) adc_ll_digi_pattern_table_t;
|
||||
|
||||
/**
|
||||
* @brief Analyze whether the obtained raw data is correct.
|
||||
* ADC2 use arbiter by default. The arbitration result can be judged by the flag bit in the original data.
|
||||
@ -53,24 +98,6 @@ typedef struct {
|
||||
};
|
||||
} adc_ll_rtc_output_data_t;
|
||||
|
||||
/**
|
||||
* @brief ADC controller type selection.
|
||||
*
|
||||
* @note For ADC2, use the force option with care. The system power consumption detection will use ADC2.
|
||||
* If it is forced to switch to another controller, it may cause the system to obtain incorrect values.
|
||||
* @note Normally, there is no need to switch the controller manually.
|
||||
*/
|
||||
typedef enum {
|
||||
ADC_CTRL_RTC = 0, /*!<For ADC1. Select RTC controller. For ADC2. The controller is selected by the arbiter. Arbiter in default mode. */
|
||||
ADC_CTRL_ULP = 1, /*!<For ADC1. Select ULP controller. For ADC2. The controller is selected by the arbiter. Arbiter in default mode. */
|
||||
ADC_CTRL_DIG = 2, /*!<For ADC1. Select DIG controller. For ADC2. The controller is selected by the arbiter. Arbiter in default mode. */
|
||||
ADC2_CTRL_PWDET = 3,/*!<For ADC2. The controller is selected by the arbiter. Arbiter in default mode. */
|
||||
ADC2_CTRL_FORCE_PWDET = 3, /*!<For ADC2. Arbiter in shield mode. Force select Wi-Fi controller work. */
|
||||
ADC2_CTRL_FORCE_RTC = 4, /*!<For ADC2. Arbiter in shield mode. Force select RTC controller work. */
|
||||
ADC2_CTRL_FORCE_ULP = 5, /*!<For ADC2. Arbiter in shield mode. Force select RTC controller work. */
|
||||
ADC2_CTRL_FORCE_DIG = 6, /*!<For ADC2. Arbiter in shield mode. Force select digital controller work. */
|
||||
} adc_ll_controller_t;
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Digital controller setting
|
||||
---------------------------------------------------------------*/
|
||||
@ -120,16 +147,6 @@ static inline void adc_ll_digi_set_clk_div(uint32_t div)
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.ctrl, sar_clk_div, div);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set adc output data format for digital controller.
|
||||
*
|
||||
* @param format Output data format.
|
||||
*/
|
||||
static inline void adc_ll_digi_set_output_format(adc_digi_output_format_t format)
|
||||
{
|
||||
APB_SARADC.ctrl.data_sar_sel = format;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set adc max conversion number for digital controller.
|
||||
* If the number of ADC conversion is equal to the maximum, the conversion is stopped.
|
||||
@ -162,22 +179,25 @@ static inline void adc_ll_digi_convert_limit_disable(void)
|
||||
/**
|
||||
* Set adc conversion mode for digital controller.
|
||||
*
|
||||
* @note ESP32 only support ADC1 single mode.
|
||||
*
|
||||
* @param mode Conversion mode select.
|
||||
* TODO IDF-3610
|
||||
*/
|
||||
static inline void adc_ll_digi_set_convert_mode(adc_digi_convert_mode_t mode)
|
||||
static inline void adc_ll_digi_set_convert_mode(adc_ll_digi_convert_mode_t mode)
|
||||
{
|
||||
if (mode == ADC_CONV_SINGLE_UNIT_1) {
|
||||
if (mode == ADC_LL_DIGI_CONV_ONLY_ADC1) {
|
||||
APB_SARADC.ctrl.work_mode = 0;
|
||||
APB_SARADC.ctrl.sar_sel = 0;
|
||||
} else if (mode == ADC_CONV_SINGLE_UNIT_2) {
|
||||
APB_SARADC.ctrl.data_sar_sel = 0;
|
||||
} else if (mode == ADC_LL_DIGI_CONV_ONLY_ADC2) {
|
||||
APB_SARADC.ctrl.work_mode = 0;
|
||||
APB_SARADC.ctrl.sar_sel = 1;
|
||||
} else if (mode == ADC_CONV_BOTH_UNIT) {
|
||||
APB_SARADC.ctrl.data_sar_sel = 0;
|
||||
} else if (mode == ADC_LL_DIGI_CONV_BOTH_UNIT) {
|
||||
APB_SARADC.ctrl.work_mode = 1;
|
||||
} else if (mode == ADC_CONV_ALTER_UNIT) {
|
||||
APB_SARADC.ctrl.data_sar_sel = 1;
|
||||
} else if (mode == ADC_LL_DIGI_CONV_ALTER_UNIT) {
|
||||
APB_SARADC.ctrl.work_mode = 2;
|
||||
APB_SARADC.ctrl.data_sar_sel = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -209,12 +229,15 @@ static inline void adc_ll_digi_set_pattern_table_len(adc_ll_num_t adc_n, uint32_
|
||||
* @param pattern_index Items index. Range: 0 ~ 15.
|
||||
* @param pattern Stored conversion rules.
|
||||
*/
|
||||
static inline void adc_ll_digi_set_pattern_table(adc_ll_num_t adc_n, uint32_t pattern_index, adc_digi_pattern_table_t pattern)
|
||||
static inline void adc_ll_digi_set_pattern_table(adc_ll_num_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) * 8;
|
||||
if (adc_n == ADC_NUM_1) {
|
||||
adc_ll_digi_pattern_table_t pattern = {0};
|
||||
|
||||
pattern.val = (table.atten & 0x3) | ((table.channel & 0xF) << 4);
|
||||
if (table.unit == ADC_NUM_1) {
|
||||
tab = APB_SARADC.sar1_patt_tab[index]; // Read old register value
|
||||
tab &= (~(0xFF000000 >> offset)); // clear old data
|
||||
tab |= ((uint32_t)pattern.val << 24) >> offset; // Fill in the new data
|
||||
@ -319,7 +342,7 @@ static inline void adc_ll_digi_controller_clk_div(uint32_t div_num, uint32_t div
|
||||
*
|
||||
* @param use_apll true: use APLL clock; false: use APB clock.
|
||||
*/
|
||||
static inline void adc_ll_digi_controller_clk_enable(bool use_apll)
|
||||
static inline void adc_ll_digi_clk_sel(bool use_apll)
|
||||
{
|
||||
if (use_apll) {
|
||||
APB_SARADC.apb_adc_clkm_conf.clk_sel = 1; // APLL clock
|
||||
@ -483,112 +506,6 @@ static inline void adc_ll_digi_monitor_enable(adc_ll_num_t adc_n, bool enable)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable interrupt of adc digital controller by bitmask.
|
||||
*
|
||||
* @param adc_n ADC unit.
|
||||
* @param intr Interrupt bitmask.
|
||||
*/
|
||||
static inline void adc_ll_digi_intr_enable(adc_ll_num_t adc_n, adc_digi_intr_t intr)
|
||||
{
|
||||
if (adc_n == ADC_NUM_1) {
|
||||
if (intr & ADC_DIGI_INTR_MASK_MONITOR) {
|
||||
APB_SARADC.int_ena.adc1_thres = 1;
|
||||
}
|
||||
if (intr & ADC_DIGI_INTR_MASK_MEAS_DONE) {
|
||||
APB_SARADC.int_ena.adc1_done = 1;
|
||||
}
|
||||
} else { // adc_n == ADC_NUM_2
|
||||
if (intr & ADC_DIGI_INTR_MASK_MONITOR) {
|
||||
APB_SARADC.int_ena.adc2_thres = 1;
|
||||
}
|
||||
if (intr & ADC_DIGI_INTR_MASK_MEAS_DONE) {
|
||||
APB_SARADC.int_ena.adc2_done = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable interrupt of adc digital controller by bitmask.
|
||||
*
|
||||
* @param adc_n ADC unit.
|
||||
* @param intr Interrupt bitmask.
|
||||
*/
|
||||
static inline void adc_ll_digi_intr_disable(adc_ll_num_t adc_n, adc_digi_intr_t intr)
|
||||
{
|
||||
if (adc_n == ADC_NUM_1) {
|
||||
if (intr & ADC_DIGI_INTR_MASK_MONITOR) {
|
||||
APB_SARADC.int_ena.adc1_thres = 0;
|
||||
}
|
||||
if (intr & ADC_DIGI_INTR_MASK_MEAS_DONE) {
|
||||
APB_SARADC.int_ena.adc1_done = 0;
|
||||
}
|
||||
} else { // adc_n == ADC_NUM_2
|
||||
if (intr & ADC_DIGI_INTR_MASK_MONITOR) {
|
||||
APB_SARADC.int_ena.adc2_thres = 0;
|
||||
}
|
||||
if (intr & ADC_DIGI_INTR_MASK_MEAS_DONE) {
|
||||
APB_SARADC.int_ena.adc2_done = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear interrupt of adc digital controller by bitmask.
|
||||
*
|
||||
* @param adc_n ADC unit.
|
||||
* @param intr Interrupt bitmask.
|
||||
*/
|
||||
static inline void adc_ll_digi_intr_clear(adc_ll_num_t adc_n, adc_digi_intr_t intr)
|
||||
{
|
||||
if (adc_n == ADC_NUM_1) {
|
||||
if (intr & ADC_DIGI_INTR_MASK_MONITOR) {
|
||||
APB_SARADC.int_clr.adc1_thres = 1;
|
||||
}
|
||||
if (intr & ADC_DIGI_INTR_MASK_MEAS_DONE) {
|
||||
APB_SARADC.int_clr.adc1_done = 1;
|
||||
}
|
||||
} else { // adc_n == ADC_NUM_2
|
||||
if (intr & ADC_DIGI_INTR_MASK_MONITOR) {
|
||||
APB_SARADC.int_clr.adc2_thres = 1;
|
||||
}
|
||||
if (intr & ADC_DIGI_INTR_MASK_MEAS_DONE) {
|
||||
APB_SARADC.int_clr.adc2_done = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get interrupt status mask of adc digital controller.
|
||||
*
|
||||
* @param adc_n ADC unit.
|
||||
* @return
|
||||
* - intr Interrupt bitmask.
|
||||
*/
|
||||
static inline uint32_t adc_ll_digi_get_intr_status(adc_ll_num_t adc_n)
|
||||
{
|
||||
uint32_t int_st = APB_SARADC.int_st.val;
|
||||
uint32_t ret_msk = 0;
|
||||
|
||||
if (adc_n == ADC_NUM_1) {
|
||||
if (int_st & APB_SARADC_ADC1_DONE_INT_ST_M) {
|
||||
ret_msk |= ADC_DIGI_INTR_MASK_MEAS_DONE;
|
||||
}
|
||||
if (int_st & APB_SARADC_ADC1_THRES_INT_ST) {
|
||||
ret_msk |= ADC_DIGI_INTR_MASK_MONITOR;
|
||||
}
|
||||
} else { // adc_n == ADC_NUM_2
|
||||
if (int_st & APB_SARADC_ADC2_DONE_INT_ST_M) {
|
||||
ret_msk |= ADC_DIGI_INTR_MASK_MEAS_DONE;
|
||||
}
|
||||
if (int_st & APB_SARADC_ADC2_THRES_INT_ST_M) {
|
||||
ret_msk |= ADC_DIGI_INTR_MASK_MONITOR;
|
||||
}
|
||||
}
|
||||
|
||||
return ret_msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@ -655,6 +572,20 @@ 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`.
|
||||
*
|
||||
* @param div Division factor.
|
||||
*/
|
||||
static inline void adc_ll_set_sar_clk_div(adc_ll_num_t adc_n, uint32_t div)
|
||||
{
|
||||
if (adc_n == ADC_NUM_1) {
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_reader1_ctrl, sar1_clk_div, div);
|
||||
} else { // adc_n == ADC_NUM_2
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_reader2_ctrl, sar2_clk_div, div);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set adc output data format for RTC controller.
|
||||
*
|
||||
@ -855,65 +786,6 @@ static inline adc_ll_rtc_raw_data_t adc_ll_rtc_analysis_raw_data(adc_ll_num_t ad
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
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) {
|
||||
SENS.sar_meas1_ctrl1.rtc_saradc_clkgate_en = 1;
|
||||
SENS.sar_power_xpd_sar.force_xpd_sar = SENS_FORCE_XPD_SAR_PU;
|
||||
} else if (manage == ADC_POWER_BY_FSM) {
|
||||
SENS.sar_meas1_ctrl1.rtc_saradc_clkgate_en = 1;
|
||||
SENS.sar_power_xpd_sar.force_xpd_sar = SENS_FORCE_XPD_SAR_FSM;
|
||||
} else if (manage == ADC_POWER_SW_OFF) {
|
||||
SENS.sar_power_xpd_sar.force_xpd_sar = SENS_FORCE_XPD_SAR_PD;
|
||||
SENS.sar_meas1_ctrl1.rtc_saradc_clkgate_en = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ADC module power management.
|
||||
*
|
||||
* @return
|
||||
* - ADC power status.
|
||||
*/
|
||||
static inline adc_ll_power_t adc_ll_get_power_manage(void)
|
||||
{
|
||||
/* Bit1 0:Fsm 1: SW mode
|
||||
Bit0 0:SW mode power down 1: SW mode power on */
|
||||
adc_ll_power_t manage;
|
||||
if (SENS.sar_power_xpd_sar.force_xpd_sar == SENS_FORCE_XPD_SAR_PU) {
|
||||
manage = ADC_POWER_SW_ON;
|
||||
} else if (SENS.sar_power_xpd_sar.force_xpd_sar == SENS_FORCE_XPD_SAR_PD) {
|
||||
manage = ADC_POWER_SW_OFF;
|
||||
} else {
|
||||
manage = ADC_POWER_BY_FSM;
|
||||
}
|
||||
return manage;
|
||||
}
|
||||
|
||||
/**
|
||||
* ADC SAR clock division factor setting. ADC SAR clock devided from `RTC_FAST_CLK`.
|
||||
*
|
||||
* @param div Division factor.
|
||||
*/
|
||||
static inline void adc_ll_set_sar_clk_div(adc_ll_num_t adc_n, uint32_t div)
|
||||
{
|
||||
if (adc_n == ADC_NUM_1) {
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_reader1_ctrl, sar1_clk_div, div);
|
||||
} else { // adc_n == ADC_NUM_2
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_reader2_ctrl, sar2_clk_div, div);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the attenuation of a particular channel on ADCn.
|
||||
*
|
||||
@ -972,6 +844,30 @@ static inline adc_atten_t adc_ll_get_atten(adc_ll_num_t adc_n, adc_channel_t cha
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
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) {
|
||||
SENS.sar_meas1_ctrl1.rtc_saradc_clkgate_en = 1;
|
||||
SENS.sar_power_xpd_sar.force_xpd_sar = SENS_FORCE_XPD_SAR_PU;
|
||||
} else if (manage == ADC_POWER_BY_FSM) {
|
||||
SENS.sar_meas1_ctrl1.rtc_saradc_clkgate_en = 1;
|
||||
SENS.sar_power_xpd_sar.force_xpd_sar = SENS_FORCE_XPD_SAR_FSM;
|
||||
} else if (manage == ADC_POWER_SW_OFF) {
|
||||
SENS.sar_power_xpd_sar.force_xpd_sar = SENS_FORCE_XPD_SAR_PD;
|
||||
SENS.sar_meas1_ctrl1.rtc_saradc_clkgate_en = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set ADC module controller.
|
||||
* There are five SAR ADC controllers:
|
||||
@ -985,18 +881,18 @@ static inline adc_atten_t adc_ll_get_atten(adc_ll_num_t adc_n, adc_channel_t cha
|
||||
static inline void adc_ll_set_controller(adc_ll_num_t adc_n, adc_ll_controller_t ctrl)
|
||||
{
|
||||
if (adc_n == ADC_NUM_1) {
|
||||
switch ( ctrl ) {
|
||||
case ADC_CTRL_RTC:
|
||||
switch (ctrl) {
|
||||
case ADC_LL_CTRL_RTC:
|
||||
SENS.sar_meas1_mux.sar1_dig_force = 0; // 1: Select digital control; 0: Select RTC control.
|
||||
SENS.sar_meas1_ctrl2.meas1_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start.
|
||||
SENS.sar_meas1_ctrl2.sar1_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map;
|
||||
break;
|
||||
case ADC_CTRL_ULP:
|
||||
case ADC_LL_CTRL_ULP:
|
||||
SENS.sar_meas1_mux.sar1_dig_force = 0; // 1: Select digital control; 0: Select RTC control.
|
||||
SENS.sar_meas1_ctrl2.meas1_start_force = 0; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start.
|
||||
SENS.sar_meas1_ctrl2.sar1_en_pad_force = 0; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map;
|
||||
break;
|
||||
case ADC_CTRL_DIG:
|
||||
case ADC_LL_CTRL_DIG:
|
||||
SENS.sar_meas1_mux.sar1_dig_force = 1; // 1: Select digital control; 0: Select RTC control.
|
||||
SENS.sar_meas1_ctrl2.meas1_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start.
|
||||
SENS.sar_meas1_ctrl2.sar1_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map;
|
||||
@ -1005,23 +901,16 @@ static inline void adc_ll_set_controller(adc_ll_num_t adc_n, adc_ll_controller_t
|
||||
break;
|
||||
}
|
||||
} else { // adc_n == ADC_NUM_2
|
||||
switch ( ctrl ) {
|
||||
case ADC_CTRL_RTC:
|
||||
switch (ctrl) {
|
||||
//If ADC2 is not controlled by ULP, the arbiter will decide which controller to use ADC2.
|
||||
case ADC_LL_CTRL_ARB:
|
||||
SENS.sar_meas2_ctrl2.meas2_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start.
|
||||
SENS.sar_meas2_ctrl2.sar2_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map;
|
||||
break;
|
||||
case ADC_CTRL_ULP:
|
||||
case ADC_LL_CTRL_ULP:
|
||||
SENS.sar_meas2_ctrl2.meas2_start_force = 0; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start.
|
||||
SENS.sar_meas2_ctrl2.sar2_en_pad_force = 0; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map;
|
||||
break;
|
||||
case ADC_CTRL_DIG:
|
||||
SENS.sar_meas2_ctrl2.meas2_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start.
|
||||
SENS.sar_meas2_ctrl2.sar2_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map;
|
||||
break;
|
||||
case ADC2_CTRL_PWDET: // currently only used by Wi-Fi
|
||||
SENS.sar_meas2_ctrl2.meas2_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start.
|
||||
SENS.sar_meas2_ctrl2.sar2_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1,16 +1,8 @@
|
||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* NOTICE
|
||||
@ -1089,10 +1081,6 @@ static inline uint32_t spi_ll_slave_hd_get_last_addr(spi_dev_t *hw)
|
||||
*/
|
||||
static inline void spi_dma_ll_rx_reset(spi_dma_dev_t *dma_in, uint32_t channel)
|
||||
{
|
||||
//Reset RX DMA peripheral
|
||||
dma_in->dma_in_link.dma_rx_ena = 0;
|
||||
HAL_ASSERT(dma_in->dma_in_link.dma_rx_ena == 0);
|
||||
|
||||
dma_in->dma_conf.in_rst = 1;
|
||||
dma_in->dma_conf.in_rst = 0;
|
||||
}
|
||||
@ -1110,6 +1098,17 @@ static inline void spi_dma_ll_rx_start(spi_dma_dev_t *dma_in, uint32_t channel,
|
||||
dma_in->dma_in_link.start = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop RX DMA.
|
||||
*
|
||||
* @param dma_in Beginning address of the DMA peripheral registers which stores the data received from a peripheral into RAM.
|
||||
* @param channel DMA channel, for chip version compatibility, not used.
|
||||
*/
|
||||
static inline void spi_dma_ll_rx_stop(spi_dma_dev_t *dma_in, uint32_t channel)
|
||||
{
|
||||
dma_in->dma_in_link.stop = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable DMA RX channel burst for data
|
||||
*
|
||||
@ -1173,6 +1172,17 @@ static inline void spi_dma_ll_tx_start(spi_dma_dev_t *dma_out, uint32_t channel,
|
||||
dma_out->dma_out_link.start = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop TX DMA.
|
||||
*
|
||||
* @param dma_out Beginning address of the DMA peripheral registers which transmits the data from RAM to a peripheral.
|
||||
* @param channel DMA channel, for chip version compatibility, not used.
|
||||
*/
|
||||
static inline void spi_dma_ll_tx_stop(spi_dma_dev_t *dma_out, uint32_t channel)
|
||||
{
|
||||
dma_out->dma_out_link.stop = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable DMA TX channel burst for data
|
||||
*
|
||||
@ -1251,7 +1261,6 @@ static inline void spi_dma_ll_rx_disable(spi_dma_dev_t *dma_in)
|
||||
static inline void spi_dma_ll_tx_disable(spi_dma_dev_t *dma_out)
|
||||
{
|
||||
dma_out->dma_out_link.dma_tx_ena = 0;
|
||||
dma_out->dma_out_link.stop = 1;
|
||||
}
|
||||
|
||||
static inline bool spi_ll_tx_get_empty_err(spi_dev_t *hw)
|
||||
|
@ -1,16 +1,8 @@
|
||||
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
@ -55,12 +47,28 @@ typedef enum {
|
||||
} adc_ll_rtc_raw_data_t;
|
||||
|
||||
typedef enum {
|
||||
ADC_LL_CTRL_RTC = 0, ///< For ADC1. Select RTC controller.
|
||||
ADC_LL_CTRL_ULP = 1, ///< For ADC1 and ADC2. Select ULP controller.
|
||||
ADC_LL_CTRL_DIG = 2, ///< For ADC1. Select DIG controller.
|
||||
ADC_LL_CTRL_ARB = 4, ///< For ADC2. The controller is selected by the arbiter.
|
||||
ADC_LL_CTRL_RTC = 0, ///< For ADC1. Select RTC controller.
|
||||
ADC_LL_CTRL_ULP = 1, ///< For ADC1 and ADC2. Select ULP controller.
|
||||
ADC_LL_CTRL_DIG = 2, ///< For ADC1. Select DIG controller.
|
||||
ADC_LL_CTRL_ARB = 3, ///< For ADC2. The controller is selected by the arbiter.
|
||||
} adc_ll_controller_t;
|
||||
|
||||
/**
|
||||
* @brief ADC digital controller (DMA mode) work mode.
|
||||
*
|
||||
* @note The conversion mode affects the sampling frequency:
|
||||
* SINGLE_UNIT_1: When the measurement is triggered, only ADC1 is sampled once.
|
||||
* SINGLE_UNIT_2: When the measurement is triggered, only ADC2 is sampled once.
|
||||
* BOTH_UNIT : When the measurement is triggered, ADC1 and ADC2 are sampled at the same time.
|
||||
* ALTER_UNIT : When the measurement is triggered, ADC1 or ADC2 samples alternately.
|
||||
*/
|
||||
typedef enum {
|
||||
ADC_LL_DIGI_CONV_ONLY_ADC1 = 0, // Only use ADC1 for conversion
|
||||
ADC_LL_DIGI_CONV_ONLY_ADC2 = 1, // Only use ADC2 for conversion
|
||||
ADC_LL_DIGI_CONV_BOTH_UNIT = 2, // Use Both ADC1 and ADC2 for conversion simultaneously
|
||||
ADC_LL_DIGI_CONV_ALTER_UNIT = 3 // 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 {
|
||||
@ -84,8 +92,8 @@ typedef struct {
|
||||
typedef struct {
|
||||
union {
|
||||
struct {
|
||||
uint16_t data: 12; /*!<ADC real output data info. Resolution: 13 bit. */
|
||||
uint16_t reserved: 2; /*!<reserved */
|
||||
uint16_t data: 13; /*!<ADC real output data info. Resolution: 13 bit. */
|
||||
uint16_t reserved: 1; /*!<reserved */
|
||||
uint16_t flag: 2; /*!<ADC data flag info.
|
||||
If (flag == 0), The data is valid.
|
||||
If (flag > 0), The data is invalid. */
|
||||
@ -181,21 +189,19 @@ static inline void adc_ll_digi_convert_limit_disable(void)
|
||||
/**
|
||||
* Set adc conversion mode for digital controller.
|
||||
*
|
||||
* @note ESP32 only support ADC1 single mode.
|
||||
*
|
||||
* @param mode Conversion mode select.
|
||||
*/
|
||||
static inline void adc_ll_digi_set_convert_mode(adc_digi_convert_mode_t mode)
|
||||
static inline void adc_ll_digi_set_convert_mode(adc_ll_digi_convert_mode_t mode)
|
||||
{
|
||||
if (mode == ADC_CONV_SINGLE_UNIT_1) {
|
||||
if (mode == ADC_LL_DIGI_CONV_ONLY_ADC1) {
|
||||
APB_SARADC.ctrl.work_mode = 0;
|
||||
APB_SARADC.ctrl.sar_sel = 0;
|
||||
} else if (mode == ADC_CONV_SINGLE_UNIT_2) {
|
||||
} else if (mode == ADC_LL_DIGI_CONV_ONLY_ADC2) {
|
||||
APB_SARADC.ctrl.work_mode = 0;
|
||||
APB_SARADC.ctrl.sar_sel = 1;
|
||||
} else if (mode == ADC_CONV_BOTH_UNIT) {
|
||||
} else if (mode == ADC_LL_DIGI_CONV_BOTH_UNIT) {
|
||||
APB_SARADC.ctrl.work_mode = 1;
|
||||
} else if (mode == ADC_CONV_ALTER_UNIT) {
|
||||
} else if (mode == ADC_LL_DIGI_CONV_ALTER_UNIT) {
|
||||
APB_SARADC.ctrl.work_mode = 2;
|
||||
}
|
||||
APB_SARADC.ctrl.data_sar_sel = 1;
|
||||
@ -229,9 +235,25 @@ static inline void adc_ll_digi_set_pattern_table_len(adc_ll_num_t adc_n, uint32_
|
||||
* @param pattern_index Items index. Range: 0 ~ 11.
|
||||
* @param pattern Stored conversion rules.
|
||||
*/
|
||||
static inline void adc_ll_digi_set_pattern_table(adc_ll_num_t adc_n, uint32_t pattern_index, adc_digi_pattern_table_t table)
|
||||
static inline void adc_ll_digi_set_pattern_table(adc_ll_num_t adc_n, uint32_t pattern_index, adc_digi_pattern_config_t table)
|
||||
{
|
||||
abort();
|
||||
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 & 0xF) << 2);
|
||||
if (table.unit == ADC_NUM_1){
|
||||
tab = APB_SARADC.sar1_patt_tab[index].sar1_patt_tab; //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.sar1_patt_tab[index].sar1_patt_tab = tab; //Write back
|
||||
} else {
|
||||
tab = APB_SARADC.sar2_patt_tab[index].sar2_patt_tab; //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.sar2_patt_tab[index].sar2_patt_tab = tab; //Write back
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -325,7 +347,7 @@ static inline void adc_ll_digi_controller_clk_div(uint32_t div_num, uint32_t div
|
||||
*
|
||||
* @param use_apll true: use APLL clock; false: use APB clock.
|
||||
*/
|
||||
static inline void adc_ll_digi_controller_clk_enable(bool use_apll)
|
||||
static inline void adc_ll_digi_clk_sel(bool use_apll)
|
||||
{
|
||||
if (use_apll) {
|
||||
APB_SARADC.apb_adc_clkm_conf.clk_sel = 1; // APLL clock
|
||||
@ -354,26 +376,13 @@ static inline void adc_ll_digi_filter_reset(adc_ll_num_t adc_n)
|
||||
abort();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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).
|
||||
* @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_set_factor(adc_digi_filter_idx_t idx, adc_digi_filter_t *filter)
|
||||
static inline void adc_ll_digi_filter_set_factor(adc_ll_num_t adc_n, adc_digi_filter_mode_t factor)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
@ -384,7 +393,19 @@ static inline void adc_ll_digi_filter_set_factor(adc_digi_filter_idx_t idx, adc_
|
||||
* @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)
|
||||
static inline void adc_ll_digi_filter_get_factor(adc_ll_num_t adc_n, adc_digi_filter_mode_t *factor)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/disable adc digital controller filter.
|
||||
* Filtering the ADC data to obtain smooth data at higher sampling rates.
|
||||
*
|
||||
* @note The filter will filter all the enabled channel data of the each ADC unit at the same time.
|
||||
* @param adc_n ADC unit.
|
||||
*/
|
||||
static inline void adc_ll_digi_filter_enable(adc_ll_num_t adc_n, bool enable)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
@ -410,23 +431,11 @@ static inline uint32_t adc_ll_digi_filter_read_data(adc_ll_num_t adc_n)
|
||||
* @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)
|
||||
static inline void adc_ll_digi_monitor_set_mode(adc_ll_num_t adc_n, bool is_larger)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set monitor threshold of adc digital controller.
|
||||
*
|
||||
@ -513,30 +522,6 @@ static inline uint32_t adc_ll_pwdet_get_cct(void)
|
||||
return SENS.sar_meas2_mux.sar2_pwdet_cct;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* - 0: The data is correct to use.
|
||||
* - -1: The data is invalid.
|
||||
*/
|
||||
static inline adc_ll_rtc_raw_data_t adc_ll_analysis_raw_data(adc_ll_num_t adc_n, int raw_data)
|
||||
{
|
||||
if (adc_n == ADC_NUM_1) {
|
||||
return ADC_RTC_DATA_OK;
|
||||
}
|
||||
|
||||
//The raw data API returns value without channel information. Read value directly from the register
|
||||
if (((APB_SARADC.apb_saradc2_data_status.adc2_data >> 12) & 0xF) > 9) {
|
||||
return ADC_RTC_DATA_FAIL;
|
||||
}
|
||||
|
||||
return ADC_RTC_DATA_OK;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Common setting
|
||||
---------------------------------------------------------------*/
|
||||
@ -547,21 +532,17 @@ static inline adc_ll_rtc_raw_data_t adc_ll_analysis_raw_data(adc_ll_num_t adc_n,
|
||||
*/
|
||||
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) {
|
||||
SENS.sar_peri_clk_gate_conf.saradc_clk_en = 1;
|
||||
SENS.sar_power_xpd_sar.force_xpd_sar = 3; //SENS_FORCE_XPD_SAR_PU;
|
||||
APB_SARADC.ctrl.sar_clk_gated = 1;
|
||||
APB_SARADC.ctrl.xpd_sar_force = 3;
|
||||
} else if (manage == ADC_POWER_BY_FSM) {
|
||||
SENS.sar_peri_clk_gate_conf.saradc_clk_en = 1;
|
||||
SENS.sar_power_xpd_sar.force_xpd_sar = 0; //SENS_FORCE_XPD_SAR_FSM;
|
||||
APB_SARADC.ctrl.sar_clk_gated = 1;
|
||||
APB_SARADC.ctrl.xpd_sar_force = 0;
|
||||
} else if (manage == ADC_POWER_SW_OFF) {
|
||||
SENS.sar_power_xpd_sar.force_xpd_sar = 2; //SENS_FORCE_XPD_SAR_PD;
|
||||
SENS.sar_peri_clk_gate_conf.saradc_clk_en = 0;
|
||||
APB_SARADC.ctrl.sar_clk_gated = 0;
|
||||
APB_SARADC.ctrl.xpd_sar_force = 2;
|
||||
}
|
||||
}
|
||||
|
||||
@ -579,37 +560,37 @@ static inline void adc_ll_set_controller(adc_ll_num_t adc_n, adc_ll_controller_t
|
||||
{
|
||||
if (adc_n == ADC_NUM_1) {
|
||||
switch (ctrl) {
|
||||
case ADC_LL_CTRL_RTC:
|
||||
SENS.sar_meas1_mux.sar1_dig_force = 0; // 1: Select digital control; 0: Select RTC control.
|
||||
SENS.sar_meas1_ctrl2.meas1_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start.
|
||||
SENS.sar_meas1_ctrl2.sar1_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map;
|
||||
break;
|
||||
case ADC_LL_CTRL_ULP:
|
||||
SENS.sar_meas1_mux.sar1_dig_force = 0; // 1: Select digital control; 0: Select RTC control.
|
||||
SENS.sar_meas1_ctrl2.meas1_start_force = 0; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start.
|
||||
SENS.sar_meas1_ctrl2.sar1_en_pad_force = 0; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map;
|
||||
break;
|
||||
case ADC_LL_CTRL_DIG:
|
||||
SENS.sar_meas1_mux.sar1_dig_force = 1; // 1: Select digital control; 0: Select RTC control.
|
||||
SENS.sar_meas1_ctrl2.meas1_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start.
|
||||
SENS.sar_meas1_ctrl2.sar1_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case ADC_LL_CTRL_RTC:
|
||||
SENS.sar_meas1_mux.sar1_dig_force = 0; // 1: Select digital control; 0: Select RTC control.
|
||||
SENS.sar_meas1_ctrl2.meas1_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start.
|
||||
SENS.sar_meas1_ctrl2.sar1_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map;
|
||||
break;
|
||||
case ADC_LL_CTRL_ULP:
|
||||
SENS.sar_meas1_mux.sar1_dig_force = 0; // 1: Select digital control; 0: Select RTC control.
|
||||
SENS.sar_meas1_ctrl2.meas1_start_force = 0; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start.
|
||||
SENS.sar_meas1_ctrl2.sar1_en_pad_force = 0; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map;
|
||||
break;
|
||||
case ADC_LL_CTRL_DIG:
|
||||
SENS.sar_meas1_mux.sar1_dig_force = 1; // 1: Select digital control; 0: Select RTC control.
|
||||
SENS.sar_meas1_ctrl2.meas1_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start.
|
||||
SENS.sar_meas1_ctrl2.sar1_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else { // adc_n == ADC_NUM_2
|
||||
//If ADC2 is not controlled by ULP, the arbiter will decide which controller to use ADC2.
|
||||
switch (ctrl) {
|
||||
case ADC_LL_CTRL_ARB:
|
||||
SENS.sar_meas2_ctrl2.meas2_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start.
|
||||
SENS.sar_meas2_ctrl2.sar2_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map;
|
||||
break;
|
||||
case ADC_LL_CTRL_ULP:
|
||||
SENS.sar_meas2_ctrl2.meas2_start_force = 0; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start.
|
||||
SENS.sar_meas2_ctrl2.sar2_en_pad_force = 0; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case ADC_LL_CTRL_ARB:
|
||||
SENS.sar_meas2_ctrl2.meas2_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start.
|
||||
SENS.sar_meas2_ctrl2.sar2_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map;
|
||||
break;
|
||||
case ADC_LL_CTRL_ULP:
|
||||
SENS.sar_meas2_ctrl2.meas2_start_force = 0; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start.
|
||||
SENS.sar_meas2_ctrl2.sar2_en_pad_force = 0; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -725,7 +706,7 @@ static inline void adc_ll_calibration_init(adc_ll_num_t adc_n)
|
||||
* Configure the registers for ADC calibration. You need to call the ``adc_ll_calibration_finish`` interface to resume after calibration.
|
||||
*
|
||||
* @param adc_n ADC index number.
|
||||
* @param channel Not used
|
||||
* @param channel Not used.
|
||||
* @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.
|
||||
*/
|
||||
|
@ -1,136 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// The HAL layer for ADC (ESP-8684 specific part)
|
||||
|
||||
#include <string.h>
|
||||
#include "soc/soc_caps.h"
|
||||
#include "hal/adc_hal.h"
|
||||
#include "hal/adc_types.h"
|
||||
#include "soc/soc.h"
|
||||
|
||||
//Currently we don't have context for the ADC HAL. So HAL variables are temporarily put here. But
|
||||
//please don't follow this code. Create a context for your own HAL!
|
||||
|
||||
static bool s_filter_enabled[SOC_ADC_DIGI_FILTER_NUM] = {};
|
||||
static adc_digi_filter_t s_filter[SOC_ADC_DIGI_FILTER_NUM] = {};
|
||||
|
||||
static bool s_monitor_enabled[SOC_ADC_DIGI_MONITOR_NUM] = {};
|
||||
static adc_digi_monitor_t s_monitor_config[SOC_ADC_DIGI_MONITOR_NUM] = {};
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Digital controller setting
|
||||
---------------------------------------------------------------*/
|
||||
void adc_hal_digi_deinit(void)
|
||||
{
|
||||
adc_ll_digi_trigger_disable(); // boss
|
||||
adc_ll_digi_dma_disable();
|
||||
adc_ll_digi_clear_pattern_table(ADC_NUM_1);
|
||||
adc_ll_digi_clear_pattern_table(ADC_NUM_2);
|
||||
adc_ll_digi_filter_reset(ADC_NUM_1);
|
||||
adc_ll_digi_filter_reset(ADC_NUM_2);
|
||||
adc_ll_digi_reset();
|
||||
adc_ll_digi_controller_clk_disable();
|
||||
}
|
||||
|
||||
/**
|
||||
* - Set ADC digital controller clock division factor. The clock is divided from `APLL` or `APB` clock.
|
||||
* Expression: controller_clk = APLL/APB * (div_num + div_a / div_b + 1).
|
||||
* - Enable clock and select clock source for ADC digital controller.
|
||||
*/
|
||||
static void adc_hal_digi_clk_config(void)
|
||||
{
|
||||
//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_controller_clk_enable(0);
|
||||
}
|
||||
|
||||
void adc_hal_digi_controller_config(const adc_digi_config_t *cfg)
|
||||
{
|
||||
//only one pattern table is supported on C3, but LL still needs one argument.
|
||||
const int pattern_both = 0;
|
||||
|
||||
if (cfg->adc_pattern_len) {
|
||||
adc_ll_digi_clear_pattern_table(pattern_both);
|
||||
adc_ll_digi_set_pattern_table_len(pattern_both, cfg->adc_pattern_len);
|
||||
for (uint32_t i = 0; i < cfg->adc_pattern_len; i++) {
|
||||
adc_ll_digi_set_pattern_table(pattern_both, i, cfg->adc_pattern[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (cfg->conv_limit_en) {
|
||||
adc_ll_digi_set_convert_limit_num(cfg->conv_limit_num);
|
||||
adc_ll_digi_convert_limit_enable();
|
||||
} else {
|
||||
adc_ll_digi_convert_limit_disable();
|
||||
}
|
||||
|
||||
//clock
|
||||
uint32_t interval = APB_CLK_FREQ / (ADC_LL_CLKM_DIV_NUM_DEFAULT + ADC_LL_CLKM_DIV_A_DEFAULT / ADC_LL_CLKM_DIV_B_DEFAULT + 1) / 2 / cfg->sample_freq_hz;
|
||||
adc_ll_digi_set_trigger_interval(interval);
|
||||
adc_hal_digi_clk_config();
|
||||
}
|
||||
|
||||
static void filter_update(adc_digi_filter_idx_t idx)
|
||||
{
|
||||
//ESP8684 has no enable bit, the filter will be enabled when the filter channel is configured
|
||||
if (s_filter_enabled[idx]) {
|
||||
adc_ll_digi_filter_set_factor(idx, &s_filter[idx]);
|
||||
} else {
|
||||
adc_ll_digi_filter_disable(idx);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set adc digital controller filter factor.
|
||||
*
|
||||
* @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).
|
||||
*/
|
||||
void adc_hal_digi_filter_set_factor(adc_digi_filter_idx_t idx, adc_digi_filter_t *filter)
|
||||
{
|
||||
s_filter[idx] = *filter;
|
||||
filter_update(idx);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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).
|
||||
*/
|
||||
void adc_hal_digi_filter_get_factor(adc_digi_filter_idx_t idx, adc_digi_filter_t *filter)
|
||||
{
|
||||
*filter = s_filter[idx];
|
||||
}
|
||||
|
||||
void adc_hal_digi_filter_enable(adc_digi_filter_idx_t filter_idx, bool enable)
|
||||
{
|
||||
s_filter_enabled[filter_idx] = enable;
|
||||
filter_update(filter_idx);
|
||||
}
|
||||
|
||||
static void update_monitor(adc_digi_monitor_idx_t idx)
|
||||
{
|
||||
//ESP8684 has no enable bit, the monitor will be enabled when the monitor channel is configured
|
||||
if (s_monitor_enabled[idx]) {
|
||||
adc_ll_digi_monitor_set_mode(idx, &s_monitor_config[idx]);
|
||||
} else {
|
||||
adc_ll_digi_monitor_disable(idx);
|
||||
}
|
||||
}
|
||||
|
||||
void adc_hal_digi_monitor_config(adc_digi_monitor_idx_t idx, adc_digi_monitor_t *config)
|
||||
{
|
||||
s_monitor_config[idx] = *config;
|
||||
update_monitor(idx);
|
||||
}
|
||||
|
||||
void adc_hal_digi_monitor_enable(adc_digi_monitor_idx_t mon_idx, bool enable)
|
||||
{
|
||||
s_monitor_enabled[mon_idx] = enable;
|
||||
update_monitor(mon_idx);
|
||||
}
|
@ -1,111 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* NOTICE
|
||||
* The hal is not public api, don't use in application code.
|
||||
* See readme.md in soc/include/hal/readme.md
|
||||
******************************************************************************/
|
||||
|
||||
// The HAL layer for ADC (esp32s2 specific part)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hal/adc_ll.h"
|
||||
#include "hal/adc_types.h"
|
||||
|
||||
#include_next "hal/adc_hal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Digital controller setting
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* Digital controller deinitialization.
|
||||
*/
|
||||
void adc_hal_digi_deinit(void);
|
||||
|
||||
/**
|
||||
* Setting the digital controller.
|
||||
*
|
||||
* @param cfg Pointer to digital controller paramter.
|
||||
*/
|
||||
void adc_hal_digi_controller_config(const adc_digi_config_t *cfg);
|
||||
|
||||
/**
|
||||
* Reset adc digital controller filter.
|
||||
*
|
||||
* @param filter_idx ADC filter unit.
|
||||
*/
|
||||
#define adc_hal_digi_filter_reset(filter_idx) adc_ll_digi_filter_reset(filter_idx)
|
||||
|
||||
/**
|
||||
* Set adc digital controller filter factor.
|
||||
*
|
||||
* @param filter_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).
|
||||
*/
|
||||
void adc_hal_digi_filter_set_factor(adc_digi_filter_idx_t filter_idx, adc_digi_filter_t *filter);
|
||||
|
||||
/**
|
||||
* Get adc digital controller filter factor.
|
||||
*
|
||||
* @param filter_idx ADC filter unit.
|
||||
* @param factor Expression: filter_data = (k-1)/k * last_data + new_data / k. Set values: (2, 4, 8, 16, 64).
|
||||
*/
|
||||
void adc_hal_digi_filter_get_factor(adc_digi_filter_idx_t filter_idx, adc_digi_filter_t *filter);
|
||||
|
||||
/**
|
||||
* Enable/disable adc digital controller filter.
|
||||
* Filtering the ADC data to obtain smooth data at higher sampling rates.
|
||||
*
|
||||
* @note The filter will filter all the enabled channel data of the each ADC unit at the same time.
|
||||
* @param filter_idx ADC filter unit.
|
||||
* @param enable True to enable the filter, otherwise disable.
|
||||
*/
|
||||
void adc_hal_digi_filter_enable(adc_digi_filter_idx_t filter_idx, bool enable);
|
||||
|
||||
/**
|
||||
* Config monitor of adc digital controller.
|
||||
*
|
||||
* @note If the channel info is not supported, the monitor function will not be enabled.
|
||||
* @param mon_idx ADC monitor index.
|
||||
* @param config Refer to `adc_digi_monitor_t`.
|
||||
*/
|
||||
void adc_hal_digi_monitor_config(adc_digi_monitor_idx_t mon_idx, adc_digi_monitor_t *config);
|
||||
|
||||
/**
|
||||
* Enable/disable monitor of adc digital controller.
|
||||
*
|
||||
* @note The monitor will monitor all the enabled channel data of the each ADC unit at the same time.
|
||||
* @param mon_idx ADC monitor index.
|
||||
* @param enable True to enable the monitor, otherwise disable.
|
||||
*/
|
||||
void adc_hal_digi_monitor_enable(adc_digi_monitor_idx_t mon_idx, bool enable);
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Common setting
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Config ADC2 module arbiter.
|
||||
* The arbiter is to improve the use efficiency of ADC2. After the control right is robbed by the high priority,
|
||||
* the low priority controller will read the invalid ADC2 data, and the validity of the data can be judged by the flag bit in the data.
|
||||
*
|
||||
* @note Only ADC2 support arbiter.
|
||||
* @note The arbiter's working clock is APB_CLK. When the APB_CLK clock drops below 8 MHz, the arbiter must be in shield mode.
|
||||
* @note Default priority: Wi-Fi > RTC > Digital;
|
||||
*
|
||||
* @param config Refer to `adc_arbiter_t`.
|
||||
*/
|
||||
void adc_hal_arbiter_config(adc_arbiter_t *config);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -11,11 +11,12 @@
|
||||
#include "esp_attr.h"
|
||||
|
||||
#include "soc/adc_periph.h"
|
||||
#include "hal/adc_types.h"
|
||||
#include "soc/apb_saradc_struct.h"
|
||||
#include "soc/apb_saradc_reg.h"
|
||||
#include "soc/rtc_cntl_struct.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "hal/misc.h"
|
||||
#include "hal/adc_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -45,6 +46,22 @@ typedef enum {
|
||||
ADC_RTC_DATA_FAIL = -1,
|
||||
} adc_ll_rtc_raw_data_t;
|
||||
|
||||
typedef enum {
|
||||
ADC_LL_CTRL_DIG = 0, ///< For ADC1. Select DIG controller.
|
||||
ADC_LL_CTRL_ARB = 1, ///< For ADC2. The controller is selected by the arbiter.
|
||||
} adc_ll_controller_t;
|
||||
|
||||
/**
|
||||
* @brief ADC digital controller (DMA mode) work mode.
|
||||
*
|
||||
* @note The conversion mode affects the sampling frequency:
|
||||
* ESP8684 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;
|
||||
|
||||
//These values should be set according to the HW
|
||||
typedef enum {
|
||||
ADC_LL_INTR_THRES1_LOW = BIT(26),
|
||||
@ -56,21 +73,17 @@ typedef enum {
|
||||
} adc_ll_intr_t;
|
||||
FLAG_ATTR(adc_ll_intr_t)
|
||||
|
||||
/**
|
||||
* @brief ADC controller type selection.
|
||||
*
|
||||
* @note For ADC2, use the force option with care. The system power consumption detection will use ADC2.
|
||||
* If it is forced to switch to another controller, it may cause the system to obtain incorrect values.
|
||||
* @note Normally, there is no need to switch the controller manually.
|
||||
*/
|
||||
typedef enum {
|
||||
ADC_CTRL_RTC = 0, /*!<For ADC1. Select RTC controller. For ADC2. The controller is selected by the arbiter. Arbiter in default mode. */
|
||||
ADC_CTRL_DIG = 2, /*!<For ADC1. Select DIG controller. For ADC2. The controller is selected by the arbiter. Arbiter in default mode. */
|
||||
ADC2_CTRL_PWDET = 3,/*!<For ADC2. The controller is selected by the arbiter. Arbiter in default mode. */
|
||||
ADC2_CTRL_FORCE_PWDET = 3, /*!<For ADC2. Arbiter in shield mode. Force select Wi-Fi controller work. */
|
||||
ADC2_CTRL_FORCE_RTC = 4, /*!<For ADC2. Arbiter in shield mode. Force select RTC controller work. */
|
||||
ADC2_CTRL_FORCE_DIG = 6, /*!<For ADC2. Arbiter in shield mode. Force select digital controller work. */
|
||||
} adc_ll_controller_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
|
||||
@ -85,7 +98,12 @@ typedef enum {
|
||||
*/
|
||||
static inline void adc_ll_digi_set_fsm_time(uint32_t rst_wait, uint32_t start_wait, uint32_t standby_wait)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
// Internal FSM reset wait time
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.fsm_wait, rstb_wait, rst_wait);
|
||||
// Internal FSM start wait time
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.fsm_wait, xpd_wait, start_wait);
|
||||
// Internal FSM standby wait time
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.fsm_wait, standby_wait, standby_wait);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -97,7 +115,9 @@ static inline void adc_ll_digi_set_fsm_time(uint32_t rst_wait, uint32_t start_wa
|
||||
*/
|
||||
static inline void adc_ll_set_sample_cycle(uint32_t sample_cycle)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
/* Should be called before writing I2C registers. */
|
||||
SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_PU);
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_SAMPLE_CYCLE_ADDR, sample_cycle);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -108,7 +128,8 @@ static inline void adc_ll_set_sample_cycle(uint32_t sample_cycle)
|
||||
*/
|
||||
static inline void adc_ll_digi_set_clk_div(uint32_t div)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
/* ADC clock devided from digital controller clock clk */
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.ctrl, sar_clk_div, div);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -119,7 +140,7 @@ static inline void adc_ll_digi_set_clk_div(uint32_t div)
|
||||
*/
|
||||
static inline void adc_ll_digi_set_convert_limit_num(uint32_t meas_num)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.ctrl2, max_meas_num, meas_num);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -128,7 +149,7 @@ static inline void adc_ll_digi_set_convert_limit_num(uint32_t meas_num)
|
||||
*/
|
||||
static inline void adc_ll_digi_convert_limit_enable(void)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
APB_SARADC.ctrl2.meas_num_limit = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -137,7 +158,19 @@ static inline void adc_ll_digi_convert_limit_enable(void)
|
||||
*/
|
||||
static inline void adc_ll_digi_convert_limit_disable(void)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
APB_SARADC.ctrl2.meas_num_limit = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set adc conversion mode for digital controller.
|
||||
*
|
||||
* @note ESP8684 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)
|
||||
{
|
||||
//ESP8684 only supports ADC_CONV_ALTER_UNIT mode
|
||||
}
|
||||
|
||||
/**
|
||||
@ -151,7 +184,7 @@ static inline void adc_ll_digi_convert_limit_disable(void)
|
||||
*/
|
||||
static inline void adc_ll_digi_set_pattern_table_len(adc_ll_num_t adc_n, uint32_t patt_len)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
APB_SARADC.ctrl.sar_patt_len = patt_len - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -164,9 +197,18 @@ static inline void adc_ll_digi_set_pattern_table_len(adc_ll_num_t adc_n, uint32_
|
||||
* @param pattern_index Items index. Range: 0 ~ 7.
|
||||
* @param pattern Stored conversion rules.
|
||||
*/
|
||||
static inline void adc_ll_digi_set_pattern_table(adc_ll_num_t adc_n, uint32_t pattern_index, adc_digi_pattern_table_t pattern)
|
||||
static inline void adc_ll_digi_set_pattern_table(adc_ll_num_t adc_n, uint32_t pattern_index, adc_digi_pattern_config_t table)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
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);
|
||||
tab = APB_SARADC.sar_patt_tab[index].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.sar_patt_tab[index].sar_patt_tab1 = tab; // Write back
|
||||
}
|
||||
|
||||
/**
|
||||
@ -176,7 +218,8 @@ static inline void adc_ll_digi_set_pattern_table(adc_ll_num_t adc_n, uint32_t pa
|
||||
*/
|
||||
static inline void adc_ll_digi_clear_pattern_table(adc_ll_num_t adc_n)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
APB_SARADC.ctrl.sar_patt_p_clear = 1;
|
||||
APB_SARADC.ctrl.sar_patt_p_clear = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -187,7 +230,7 @@ static inline void adc_ll_digi_clear_pattern_table(adc_ll_num_t adc_n)
|
||||
*/
|
||||
static inline void adc_ll_digi_set_arbiter_stable_cycle(uint32_t cycle)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
APB_SARADC.ctrl.wait_arb_cycle = cycle;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -198,7 +241,11 @@ static inline void adc_ll_digi_set_arbiter_stable_cycle(uint32_t cycle)
|
||||
*/
|
||||
static inline void adc_ll_digi_output_invert(adc_ll_num_t adc_n, bool inv_en)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
if (adc_n == ADC_NUM_1) {
|
||||
APB_SARADC.ctrl2.sar1_inv = inv_en; // Enable / Disable ADC data invert
|
||||
} else { // adc_n == ADC_NUM_2
|
||||
APB_SARADC.ctrl2.sar2_inv = inv_en; // Enable / Disable ADC data invert
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -210,7 +257,7 @@ static inline void adc_ll_digi_output_invert(adc_ll_num_t adc_n, bool inv_en)
|
||||
*/
|
||||
static inline void adc_ll_digi_set_trigger_interval(uint32_t cycle)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
APB_SARADC.ctrl2.timer_target = cycle;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -218,7 +265,7 @@ static inline void adc_ll_digi_set_trigger_interval(uint32_t cycle)
|
||||
*/
|
||||
static inline void adc_ll_digi_trigger_enable(void)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
APB_SARADC.ctrl2.timer_en = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -226,20 +273,22 @@ static inline void adc_ll_digi_trigger_enable(void)
|
||||
*/
|
||||
static inline void adc_ll_digi_trigger_disable(void)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
APB_SARADC.ctrl2.timer_en = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set ADC digital controller clock division factor. The clock divided from `APLL` or `APB` clock.
|
||||
* Expression: controller_clk = APLL/APB * (div_num + div_b / div_a).
|
||||
* Expression: controller_clk = (APLL or APB) / (div_num + div_a / div_b + 1).
|
||||
*
|
||||
* @param div_num Division factor. Range: 1 ~ 255.
|
||||
* @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)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.apb_adc_clkm_conf, clkm_div_num, div_num);
|
||||
APB_SARADC.apb_adc_clkm_conf.clkm_div_b = div_b;
|
||||
APB_SARADC.apb_adc_clkm_conf.clkm_div_a = div_a;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -247,9 +296,14 @@ static inline void adc_ll_digi_controller_clk_div(uint32_t div_num, uint32_t div
|
||||
*
|
||||
* @param use_apll true: use APLL clock; false: use APB clock.
|
||||
*/
|
||||
static inline void adc_ll_digi_controller_clk_enable(bool use_apll)
|
||||
static inline void adc_ll_digi_clk_sel(bool use_apll)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
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.ctrl.sar_clk_gated = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -257,7 +311,7 @@ static inline void adc_ll_digi_controller_clk_enable(bool use_apll)
|
||||
*/
|
||||
static inline void adc_ll_digi_controller_clk_disable(void)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
APB_SARADC.ctrl.sar_clk_gated = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -267,7 +321,7 @@ static inline void adc_ll_digi_controller_clk_disable(void)
|
||||
*/
|
||||
static inline void adc_ll_digi_filter_reset(adc_ll_num_t adc_n)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
APB_SARADC.filter_ctrl0.filter_reset = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -279,7 +333,13 @@ static inline void adc_ll_digi_filter_reset(adc_ll_num_t adc_n)
|
||||
*/
|
||||
static inline void adc_ll_digi_filter_set_factor(adc_digi_filter_idx_t idx, adc_digi_filter_t *filter)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
if (idx == ADC_DIGI_FILTER_IDX0) {
|
||||
APB_SARADC.filter_ctrl0.filter_channel0 = (filter->adc_unit << 3) | (filter->channel & 0x7);
|
||||
APB_SARADC.filter_ctrl1.filter_factor0 = filter->mode;
|
||||
} else if (idx == ADC_DIGI_FILTER_IDX1) {
|
||||
APB_SARADC.filter_ctrl0.filter_channel1 = (filter->adc_unit << 3) | (filter->channel & 0x7);
|
||||
APB_SARADC.filter_ctrl1.filter_factor1 = filter->mode;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -290,7 +350,15 @@ static inline void adc_ll_digi_filter_set_factor(adc_digi_filter_idx_t idx, adc_
|
||||
*/
|
||||
static inline void adc_ll_digi_filter_get_factor(adc_digi_filter_idx_t idx, adc_digi_filter_t *filter)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
if (idx == ADC_DIGI_FILTER_IDX0) {
|
||||
filter->adc_unit = (APB_SARADC.filter_ctrl0.filter_channel0 >> 3) & 0x1;
|
||||
filter->channel = APB_SARADC.filter_ctrl0.filter_channel0 & 0x7;
|
||||
filter->mode = APB_SARADC.filter_ctrl1.filter_factor0;
|
||||
} else if (idx == ADC_DIGI_FILTER_IDX1) {
|
||||
filter->adc_unit = (APB_SARADC.filter_ctrl0.filter_channel1 >> 3) & 0x1;
|
||||
filter->channel = APB_SARADC.filter_ctrl0.filter_channel1 & 0x7;
|
||||
filter->mode = APB_SARADC.filter_ctrl1.filter_factor1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -302,7 +370,13 @@ static inline void adc_ll_digi_filter_get_factor(adc_digi_filter_idx_t idx, adc_
|
||||
*/
|
||||
static inline void adc_ll_digi_filter_disable(adc_digi_filter_idx_t idx)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
if (idx == ADC_DIGI_FILTER_IDX0) {
|
||||
APB_SARADC.filter_ctrl0.filter_channel0 = 0xF;
|
||||
APB_SARADC.filter_ctrl1.filter_factor0 = 0;
|
||||
} else if (idx == ADC_DIGI_FILTER_IDX1) {
|
||||
APB_SARADC.filter_ctrl0.filter_channel1 = 0xF;
|
||||
APB_SARADC.filter_ctrl1.filter_factor1 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -315,7 +389,15 @@ static inline void adc_ll_digi_filter_disable(adc_digi_filter_idx_t idx)
|
||||
*/
|
||||
static inline void adc_ll_digi_monitor_set_mode(adc_digi_monitor_idx_t idx, adc_digi_monitor_t *cfg)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
if (idx == ADC_DIGI_MONITOR_IDX0) {
|
||||
APB_SARADC.thres0_ctrl.thres0_channel = (cfg->adc_unit << 3) | (cfg->channel & 0x7);
|
||||
APB_SARADC.thres0_ctrl.thres0_high = cfg->h_threshold;
|
||||
APB_SARADC.thres0_ctrl.thres0_low = cfg->l_threshold;
|
||||
} else { // ADC_DIGI_MONITOR_IDX1
|
||||
APB_SARADC.thres1_ctrl.thres1_channel = (cfg->adc_unit << 3) | (cfg->channel & 0x7);
|
||||
APB_SARADC.thres1_ctrl.thres1_high = cfg->h_threshold;
|
||||
APB_SARADC.thres1_ctrl.thres1_low = cfg->l_threshold;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -326,7 +408,11 @@ static inline void adc_ll_digi_monitor_set_mode(adc_digi_monitor_idx_t idx, adc_
|
||||
*/
|
||||
static inline void adc_ll_digi_monitor_disable(adc_digi_monitor_idx_t idx)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
if (idx == ADC_DIGI_MONITOR_IDX0) {
|
||||
APB_SARADC.thres0_ctrl.thres0_channel = 0xF;
|
||||
} else { // ADC_DIGI_MONITOR_IDX1
|
||||
APB_SARADC.thres1_ctrl.thres1_channel = 0xF;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -337,7 +423,7 @@ static inline void adc_ll_digi_monitor_disable(adc_digi_monitor_idx_t idx)
|
||||
*/
|
||||
static inline void adc_ll_digi_dma_set_eof_num(uint32_t num)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.dma_conf, apb_adc_eof_num, num);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -345,7 +431,7 @@ static inline void adc_ll_digi_dma_set_eof_num(uint32_t num)
|
||||
*/
|
||||
static inline void adc_ll_digi_dma_enable(void)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
APB_SARADC.dma_conf.apb_adc_trans = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -353,7 +439,7 @@ static inline void adc_ll_digi_dma_enable(void)
|
||||
*/
|
||||
static inline void adc_ll_digi_dma_disable(void)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
APB_SARADC.dma_conf.apb_adc_trans = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -361,7 +447,8 @@ static inline void adc_ll_digi_dma_disable(void)
|
||||
*/
|
||||
static inline void adc_ll_digi_reset(void)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
APB_SARADC.dma_conf.apb_adc_reset_fsm = 1;
|
||||
APB_SARADC.dma_conf.apb_adc_reset_fsm = 0;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
@ -375,7 +462,8 @@ static inline void adc_ll_digi_reset(void)
|
||||
*/
|
||||
static inline void adc_ll_pwdet_set_cct(uint32_t cct)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
/* Capacitor tuning of the PA power monitor. cct set to the same value with PHY. */
|
||||
RTCCNTL.sensor_ctrl.sar2_pwdet_cct = cct;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -386,8 +474,8 @@ static inline void adc_ll_pwdet_set_cct(uint32_t cct)
|
||||
*/
|
||||
static inline uint32_t adc_ll_pwdet_get_cct(void)
|
||||
{
|
||||
// TODO: IDF-3901.
|
||||
abort();
|
||||
/* Capacitor tuning of the PA power monitor. cct set to the same value with PHY. */
|
||||
return RTCCNTL.sensor_ctrl.sar2_pwdet_cct;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -402,8 +490,16 @@ static inline uint32_t adc_ll_pwdet_get_cct(void)
|
||||
*/
|
||||
static inline adc_ll_rtc_raw_data_t adc_ll_analysis_raw_data(adc_ll_num_t adc_n, int raw_data)
|
||||
{
|
||||
// TODO: IDF-3901.
|
||||
abort();
|
||||
if (adc_n == ADC_NUM_1) {
|
||||
return ADC_RTC_DATA_OK;
|
||||
}
|
||||
|
||||
//The raw data API returns value without channel information. Read value directly from the register
|
||||
if (((APB_SARADC.apb_saradc2_data_status.adc2_data >> 13) & 0xF) > 9) {
|
||||
return ADC_RTC_DATA_FAIL;
|
||||
}
|
||||
|
||||
return ADC_RTC_DATA_OK;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
@ -416,18 +512,23 @@ static inline adc_ll_rtc_raw_data_t adc_ll_analysis_raw_data(adc_ll_num_t adc_n,
|
||||
*/
|
||||
static inline void adc_ll_set_power_manage(adc_ll_power_t manage)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
/* Bit1 0:Fsm 1: SW mode
|
||||
Bit0 0:SW mode power down 1: SW mode power on */
|
||||
if (manage == ADC_POWER_SW_ON) {
|
||||
APB_SARADC.ctrl.sar_clk_gated = 1;
|
||||
APB_SARADC.ctrl.xpd_sar_force = 3;
|
||||
} else if (manage == ADC_POWER_BY_FSM) {
|
||||
APB_SARADC.ctrl.sar_clk_gated = 1;
|
||||
APB_SARADC.ctrl.xpd_sar_force = 0;
|
||||
} else if (manage == ADC_POWER_SW_OFF) {
|
||||
APB_SARADC.ctrl.sar_clk_gated = 0;
|
||||
APB_SARADC.ctrl.xpd_sar_force = 2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ADC module power management.
|
||||
*
|
||||
* @return
|
||||
* - ADC power status.
|
||||
*/
|
||||
static inline adc_ll_power_t adc_ll_get_power_manage(void)
|
||||
static inline void adc_ll_set_controller(adc_ll_num_t adc_n, adc_ll_controller_t ctrl)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
//Not used on ESP8684
|
||||
}
|
||||
|
||||
/**
|
||||
@ -442,7 +543,15 @@ static inline adc_ll_power_t adc_ll_get_power_manage(void)
|
||||
*/
|
||||
static inline void adc_ll_set_arbiter_work_mode(adc_arbiter_mode_t mode)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
if (mode == ADC_ARB_MODE_FIX) {
|
||||
APB_SARADC.apb_adc_arb_ctrl.adc_arb_grant_force = 0;
|
||||
APB_SARADC.apb_adc_arb_ctrl.adc_arb_fix_priority = 1;
|
||||
} else if (mode == ADC_ARB_MODE_LOOP) {
|
||||
APB_SARADC.apb_adc_arb_ctrl.adc_arb_grant_force = 0;
|
||||
APB_SARADC.apb_adc_arb_ctrl.adc_arb_fix_priority = 0;
|
||||
} else {
|
||||
APB_SARADC.apb_adc_arb_ctrl.adc_arb_grant_force = 1; // Shield arbiter.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -460,7 +569,33 @@ static inline void adc_ll_set_arbiter_work_mode(adc_arbiter_mode_t mode)
|
||||
*/
|
||||
static inline void adc_ll_set_arbiter_priority(uint8_t pri_rtc, uint8_t pri_dig, uint8_t pri_pwdet)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
if (pri_rtc != pri_dig && pri_rtc != pri_pwdet && pri_dig != pri_pwdet) {
|
||||
APB_SARADC.apb_adc_arb_ctrl.adc_arb_rtc_priority = pri_rtc;
|
||||
APB_SARADC.apb_adc_arb_ctrl.adc_arb_apb_priority = pri_dig;
|
||||
APB_SARADC.apb_adc_arb_ctrl.adc_arb_wifi_priority = pri_pwdet;
|
||||
}
|
||||
/* Should select highest priority controller. */
|
||||
if (pri_rtc > pri_dig) {
|
||||
if (pri_rtc > pri_pwdet) {
|
||||
APB_SARADC.apb_adc_arb_ctrl.adc_arb_apb_force = 0;
|
||||
APB_SARADC.apb_adc_arb_ctrl.adc_arb_rtc_force = 1;
|
||||
APB_SARADC.apb_adc_arb_ctrl.adc_arb_wifi_force = 0;
|
||||
} else {
|
||||
APB_SARADC.apb_adc_arb_ctrl.adc_arb_apb_force = 0;
|
||||
APB_SARADC.apb_adc_arb_ctrl.adc_arb_rtc_force = 0;
|
||||
APB_SARADC.apb_adc_arb_ctrl.adc_arb_wifi_force = 1;
|
||||
}
|
||||
} else {
|
||||
if (pri_dig > pri_pwdet) {
|
||||
APB_SARADC.apb_adc_arb_ctrl.adc_arb_apb_force = 1;
|
||||
APB_SARADC.apb_adc_arb_ctrl.adc_arb_rtc_force = 0;
|
||||
APB_SARADC.apb_adc_arb_ctrl.adc_arb_wifi_force = 0;
|
||||
} else {
|
||||
APB_SARADC.apb_adc_arb_ctrl.adc_arb_apb_force = 0;
|
||||
APB_SARADC.apb_adc_arb_ctrl.adc_arb_rtc_force = 0;
|
||||
APB_SARADC.apb_adc_arb_ctrl.adc_arb_wifi_force = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ADC calibration code. */
|
||||
@ -469,7 +604,11 @@ static inline void adc_ll_set_arbiter_priority(uint8_t pri_rtc, uint8_t pri_dig,
|
||||
*/
|
||||
static inline void adc_ll_calibration_init(adc_ll_num_t adc_n)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
if (adc_n == ADC_NUM_1) {
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_DREF_ADDR, 1);
|
||||
} else {
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_DREF_ADDR, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -484,7 +623,20 @@ static inline void adc_ll_calibration_init(adc_ll_num_t adc_n)
|
||||
*/
|
||||
static inline void adc_ll_calibration_prepare(adc_ll_num_t adc_n, adc_channel_t channel, bool internal_gnd)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
/* Enable/disable internal connect GND (for calibration). */
|
||||
if (adc_n == ADC_NUM_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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -494,7 +646,11 @@ static inline void adc_ll_calibration_prepare(adc_ll_num_t adc_n, adc_channel_t
|
||||
*/
|
||||
static inline void adc_ll_calibration_finish(adc_ll_num_t adc_n)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
if (adc_n == ADC_NUM_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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -506,7 +662,15 @@ static inline void adc_ll_calibration_finish(adc_ll_num_t adc_n)
|
||||
*/
|
||||
static inline void adc_ll_set_calibration_param(adc_ll_num_t adc_n, uint32_t param)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
uint8_t msb = param >> 8;
|
||||
uint8_t lsb = param & 0xFF;
|
||||
if (adc_n == ADC_NUM_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. */
|
||||
|
||||
@ -523,7 +687,45 @@ static inline void adc_ll_set_calibration_param(adc_ll_num_t adc_n, uint32_t par
|
||||
*/
|
||||
static inline void adc_ll_vref_output(adc_ll_num_t adc, adc_channel_t channel, bool en)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
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_NUM_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);
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
@ -538,57 +740,63 @@ static inline void adc_ll_vref_output(adc_ll_num_t adc, adc_channel_t channel, b
|
||||
*/
|
||||
static inline void adc_ll_onetime_start(bool val)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
APB_SARADC.onetime_sample.onetime_start = val;
|
||||
}
|
||||
|
||||
static inline void adc_ll_onetime_set_channel(adc_ll_num_t unit, adc_channel_t channel)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
APB_SARADC.onetime_sample.onetime_channel = ((unit << 3) | channel);
|
||||
}
|
||||
|
||||
static inline void adc_ll_onetime_set_atten(adc_atten_t atten)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
APB_SARADC.onetime_sample.onetime_atten = atten;
|
||||
}
|
||||
|
||||
static inline void adc_ll_intr_enable(adc_ll_intr_t mask)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
APB_SARADC.int_ena.val |= mask;
|
||||
}
|
||||
|
||||
static inline void adc_ll_intr_disable(adc_ll_intr_t mask)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
APB_SARADC.int_ena.val &= ~mask;
|
||||
}
|
||||
|
||||
static inline void adc_ll_intr_clear(adc_ll_intr_t mask)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
APB_SARADC.int_clr.val |= mask;
|
||||
}
|
||||
|
||||
static inline bool adc_ll_intr_get_raw(adc_ll_intr_t mask)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
return (APB_SARADC.int_raw.val & mask);
|
||||
}
|
||||
|
||||
static inline bool adc_ll_intr_get_status(adc_ll_intr_t mask)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
return (APB_SARADC.int_st.val & mask);
|
||||
}
|
||||
|
||||
static inline void adc_ll_onetime_sample_enable(adc_ll_num_t adc_n, bool enable)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
if (adc_n == ADC_NUM_1) {
|
||||
APB_SARADC.onetime_sample.adc1_onetime_sample = enable;
|
||||
} else {
|
||||
APB_SARADC.onetime_sample.adc2_onetime_sample = enable;
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32_t adc_ll_adc1_read(void)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
//On ESP8684, valid data width is 12-bit
|
||||
return (APB_SARADC.apb_saradc1_data_status.adc1_data & 0xfff);
|
||||
}
|
||||
|
||||
static inline uint32_t adc_ll_adc2_read(void)
|
||||
{
|
||||
abort();// TODO: IDF-3901.
|
||||
//On ESP8684, valid data width is 12-bit
|
||||
return (APB_SARADC.apb_saradc2_data_status.adc2_data & 0xfff);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -1,21 +1,51 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "hal/dma_types.h"
|
||||
#include "hal/adc_types.h"
|
||||
#include "hal/adc_ll.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
#include "soc/gdma_struct.h"
|
||||
#include "hal/gdma_ll.h"
|
||||
#include "hal/dma_types.h"
|
||||
#include "hal/adc_ll.h"
|
||||
#include "hal/dma_types.h"
|
||||
#include "esp_err.h"
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
//ADC utilises SPI3 DMA on ESP32S2
|
||||
#include "hal/spi_ll.h"
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
//ADC utilises I2S0 DMA on ESP32
|
||||
#include "hal/i2s_ll.h"
|
||||
#endif
|
||||
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
#define ADC_HAL_DMA_INTR_MASK GDMA_LL_EVENT_RX_SUC_EOF
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#define ADC_HAL_DMA_INTR_MASK SPI_LL_INTR_IN_SUC_EOF
|
||||
#else //CONFIG_IDF_TARGET_ESP32
|
||||
#define ADC_HAL_DMA_INTR_MASK BIT(9)
|
||||
#endif
|
||||
|
||||
//For ADC module, each conversion contains 4 bytes
|
||||
#define ADC_HAL_DATA_LEN_PER_CONV 4
|
||||
|
||||
typedef enum adc_hal_work_mode_t {
|
||||
ADC_HAL_ULP_MODE,
|
||||
ADC_HAL_SINGLE_READ_MODE,
|
||||
ADC_HAL_CONTINUOUS_READ_MODE,
|
||||
ADC_HAL_PWDET_MODE
|
||||
} adc_hal_work_mode_t;
|
||||
|
||||
/**
|
||||
* @brief Enum for DMA descriptor status
|
||||
*/
|
||||
@ -29,6 +59,7 @@ typedef enum adc_hal_dma_desc_status_t {
|
||||
* @brief Configuration of the HAL
|
||||
*/
|
||||
typedef struct adc_hal_config_t {
|
||||
void *dev; ///< DMA peripheral address
|
||||
uint32_t desc_max_num; ///< Number of the descriptors linked once
|
||||
uint32_t dma_chan; ///< DMA channel to be used
|
||||
uint32_t eof_num; ///< Bytes between 2 in_suc_eof interrupts
|
||||
@ -42,25 +73,30 @@ typedef struct adc_hal_context_t {
|
||||
dma_descriptor_t *rx_desc; ///< DMA descriptors
|
||||
|
||||
/**< these will be assigned by hal layer itself */
|
||||
gdma_dev_t *dev; ///< GDMA address
|
||||
dma_descriptor_t desc_dummy_head; ///< Dummy DMA descriptor for ``cur_desc_ptr`` to start
|
||||
dma_descriptor_t *cur_desc_ptr; ///< Pointer to the current descriptor
|
||||
|
||||
/**< these need to be configured by `adc_hal_config_t` via driver layer*/
|
||||
void *dev; ///< DMA address
|
||||
uint32_t desc_max_num; ///< Number of the descriptors linked once
|
||||
uint32_t dma_chan; ///< DMA channel to be used
|
||||
uint32_t eof_num; ///< Words between 2 in_suc_eof interrupts
|
||||
} adc_hal_context_t;
|
||||
#endif
|
||||
|
||||
typedef struct adc_hal_digi_ctrlr_cfg_t {
|
||||
bool conv_limit_en; //1: adc conversion will stop when `conv_limit_num` reaches. 0: won't stop. NOTE: esp32 should always be set to 1.
|
||||
uint32_t conv_limit_num; //see `conv_limit_en`
|
||||
uint32_t adc_pattern_len; //total pattern item number, including ADC1 and ADC2
|
||||
adc_digi_pattern_config_t *adc_pattern; //pattern item
|
||||
uint32_t sample_freq_hz; //ADC sample frequency
|
||||
adc_digi_convert_mode_t conv_mode; //controller work mode
|
||||
uint32_t bit_width; //output data width
|
||||
} adc_hal_digi_ctrlr_cfg_t;
|
||||
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Common setting
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* ADC module initialization.
|
||||
*/
|
||||
void adc_hal_init(void);
|
||||
|
||||
/**
|
||||
* Set ADC module power management.
|
||||
*
|
||||
@ -68,51 +104,7 @@ void adc_hal_init(void);
|
||||
*/
|
||||
#define adc_hal_set_power_manage(manage) adc_ll_set_power_manage(manage)
|
||||
|
||||
/**
|
||||
* ADC module clock division factor setting. ADC clock devided from APB clock.
|
||||
*
|
||||
* @prarm div Division factor.
|
||||
*/
|
||||
#define adc_hal_digi_set_clk_div(div) adc_ll_digi_set_clk_div(div)
|
||||
|
||||
#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP8684
|
||||
/**
|
||||
* ADC SAR clock division factor setting. ADC SAR clock devided from `RTC_FAST_CLK`.
|
||||
*
|
||||
* @prarm div Division factor.
|
||||
*/
|
||||
#define adc_hal_set_sar_clk_div(adc_n, div) adc_ll_set_sar_clk_div(adc_n, div)
|
||||
|
||||
/**
|
||||
* Set ADC module controller.
|
||||
* There are five SAR ADC controllers:
|
||||
* Two digital controller: Continuous conversion mode (DMA). High performance with multiple channel scan modes;
|
||||
* Two RTC controller: Single conversion modes (Polling). For low power purpose working during deep sleep;
|
||||
* the other is dedicated for Power detect (PWDET / PKDET), Only support ADC2.
|
||||
*
|
||||
* @prarm adc_n ADC unit.
|
||||
* @prarm ctrl ADC controller.
|
||||
*/
|
||||
#define adc_hal_set_controller(adc_n, ctrl) adc_ll_set_controller(adc_n, ctrl)
|
||||
#endif //#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP8684
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
/**
|
||||
* Get the attenuation of a particular channel on ADCn.
|
||||
*
|
||||
* @param adc_n ADC unit.
|
||||
* @param channel ADCn channel number.
|
||||
* @return atten The attenuation option.
|
||||
*/
|
||||
#define adc_hal_get_atten(adc_n, channel) adc_ll_get_atten(adc_n, channel)
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/**
|
||||
* Close ADC AMP module if don't use it for power save.
|
||||
*/
|
||||
#define adc_hal_amp_disable() adc_ll_amp_disable()
|
||||
#endif
|
||||
void adc_hal_set_controller(adc_ll_num_t unit, adc_hal_work_mode_t work_mode);
|
||||
|
||||
#if SOC_ADC_ARBITER_SUPPORTED
|
||||
//No ADC2 controller arbiter on ESP32
|
||||
@ -133,7 +125,6 @@ void adc_hal_arbiter_config(adc_arbiter_t *config);
|
||||
/*---------------------------------------------------------------
|
||||
PWDET(Power detect) controller setting
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Set adc cct for PWDET controller.
|
||||
*
|
||||
@ -150,26 +141,6 @@ void adc_hal_arbiter_config(adc_arbiter_t *config);
|
||||
*/
|
||||
#define adc_hal_pwdet_get_cct() adc_ll_pwdet_get_cct()
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
RTC controller setting
|
||||
---------------------------------------------------------------*/
|
||||
#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP8684
|
||||
/**
|
||||
* Set adc output data format for RTC controller.
|
||||
*
|
||||
* @prarm adc_n ADC unit.
|
||||
* @prarm bits Output data bits width option.
|
||||
*/
|
||||
#define adc_hal_rtc_set_output_format(adc_n, bits) adc_ll_rtc_set_output_format(adc_n, bits)
|
||||
|
||||
/**
|
||||
* ADC module output data invert or not.
|
||||
*
|
||||
* @prarm adc_n ADC unit.
|
||||
*/
|
||||
#define adc_hal_rtc_output_invert(adc_n, inv_en) adc_ll_rtc_output_invert(adc_n, inv_en)
|
||||
#endif //#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP8684
|
||||
|
||||
/**
|
||||
* Enable/disable the output of ADCn's internal reference voltage to one of ADC2's channels.
|
||||
*
|
||||
@ -188,28 +159,108 @@ void adc_hal_arbiter_config(adc_arbiter_t *config);
|
||||
Digital controller setting
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* Digital controller deinitialization.
|
||||
* ADC module initialization.
|
||||
*/
|
||||
void adc_hal_digi_deinit(void);
|
||||
void adc_hal_init(void);
|
||||
|
||||
/**
|
||||
* Digital controller deinitialization.
|
||||
*
|
||||
* @param hal Context of the HAL
|
||||
*/
|
||||
void adc_hal_digi_deinit(adc_hal_context_t *hal);
|
||||
|
||||
/**
|
||||
* @brief Initialize the hal context
|
||||
*
|
||||
* @param hal Context of the HAL
|
||||
* @param config Configuration of the HAL
|
||||
*/
|
||||
void adc_hal_context_config(adc_hal_context_t *hal, const adc_hal_config_t *config);
|
||||
|
||||
/**
|
||||
* @brief Initialize the HW
|
||||
*
|
||||
* @param hal Context of the HAL
|
||||
*/
|
||||
void adc_hal_digi_init(adc_hal_context_t *hal);
|
||||
|
||||
/**
|
||||
* Setting the digital controller.
|
||||
*
|
||||
* @param cfg Pointer to digital controller paramter.
|
||||
* @param hal Context of the HAL
|
||||
* @param cfg Pointer to digital controller paramter.
|
||||
*/
|
||||
void adc_hal_digi_controller_config(const adc_digi_config_t *cfg);
|
||||
void adc_hal_digi_controller_config(adc_hal_context_t *hal, const adc_hal_digi_ctrlr_cfg_t *cfg);
|
||||
|
||||
/**
|
||||
* Reset the pattern table pointer, then take the measurement rule from table header in next measurement.
|
||||
* @brief Start Conversion
|
||||
*
|
||||
* @param adc_n ADC unit.
|
||||
* @param hal Context of the HAL
|
||||
* @param data_buf Pointer to the data buffer, the length should be multiple of ``desc_max_num`` and ``eof_num`` in ``adc_hal_context_t``
|
||||
*/
|
||||
#define adc_hal_digi_clear_pattern_table(adc_n) adc_ll_digi_clear_pattern_table(adc_n)
|
||||
void adc_hal_digi_start(adc_hal_context_t *hal, uint8_t *data_buf);
|
||||
|
||||
#if !SOC_GDMA_SUPPORTED
|
||||
/**
|
||||
* @brief Get the DMA descriptor that Hardware has finished processing.
|
||||
*
|
||||
* @param hal Context of the HAL
|
||||
*
|
||||
* @return DMA descriptor address
|
||||
*/
|
||||
intptr_t adc_hal_get_desc_addr(adc_hal_context_t *hal);
|
||||
|
||||
/**
|
||||
* @brief Check the hardware interrupt event
|
||||
*
|
||||
* @param hal Context of the HAL
|
||||
* @param mask Event mask
|
||||
*
|
||||
* @return True: the event is triggered. False: the event is not triggered yet.
|
||||
*/
|
||||
bool adc_hal_check_event(adc_hal_context_t *hal, uint32_t mask);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Get the ADC reading result
|
||||
*
|
||||
* @param hal Context of the HAL
|
||||
* @param eof_desc_addr The last descriptor that is finished by HW. Should be got from DMA
|
||||
* @param[out] cur_desc The descriptor with ADC reading result (from the 1st one to the last one (``eof_desc_addr``))
|
||||
*
|
||||
* @return See ``adc_hal_dma_desc_status_t``
|
||||
*/
|
||||
adc_hal_dma_desc_status_t adc_hal_get_reading_result(adc_hal_context_t *hal, const intptr_t eof_desc_addr, dma_descriptor_t **cur_desc);
|
||||
|
||||
/**
|
||||
* @brief Clear interrupt
|
||||
*
|
||||
* @param hal Context of the HAL
|
||||
* @param mask mask of the interrupt
|
||||
*/
|
||||
void adc_hal_digi_clr_intr(adc_hal_context_t *hal, uint32_t mask);
|
||||
|
||||
/**
|
||||
* @brief Enable interrupt
|
||||
*
|
||||
* @param hal Context of the HAL
|
||||
* @param mask mask of the interrupt
|
||||
*/
|
||||
void adc_hal_digi_dis_intr(adc_hal_context_t *hal, uint32_t mask);
|
||||
|
||||
/**
|
||||
* @brief Stop conversion
|
||||
*
|
||||
* @param hal Context of the HAL
|
||||
*/
|
||||
void adc_hal_digi_stop(adc_hal_context_t *hal);
|
||||
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
ADC Single Read
|
||||
---------------------------------------------------------------*/
|
||||
#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP8684
|
||||
#if SOC_ADC_RTC_CTRL_SUPPORTED
|
||||
/**
|
||||
* Set the attenuation of a particular channel on ADCn.
|
||||
*
|
||||
@ -245,7 +296,7 @@ void adc_hal_digi_controller_config(const adc_digi_config_t *cfg);
|
||||
*/
|
||||
#define adc_hal_set_atten(adc_n, channel, atten) adc_ll_set_atten(adc_n, channel, atten)
|
||||
|
||||
#else // CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684
|
||||
#else // #if !SOC_ADC_RTC_CTRL_SUPPORTED
|
||||
/**
|
||||
* Set the attenuation for ADC to single read
|
||||
*
|
||||
@ -256,7 +307,7 @@ void adc_hal_digi_controller_config(const adc_digi_config_t *cfg);
|
||||
* @param atten ADC attenuation. See ``adc_atten_t``
|
||||
*/
|
||||
#define adc_hal_set_atten(adc_n, channel, atten) adc_ll_onetime_set_atten(atten)
|
||||
#endif
|
||||
#endif //#if SOC_ADC_RTC_CTRL_SUPPORTED
|
||||
|
||||
/**
|
||||
* Start an ADC conversion and get the converted value.
|
||||
@ -277,7 +328,6 @@ esp_err_t adc_hal_convert(adc_ll_num_t adc_n, int channel, int *out_raw);
|
||||
ADC calibration setting
|
||||
---------------------------------------------------------------*/
|
||||
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
// ESP32-S2, C3 and H2 support HW offset calibration.
|
||||
|
||||
/**
|
||||
* @brief Initialize default parameter for the calibration block.
|
||||
@ -314,86 +364,21 @@ uint32_t adc_hal_self_calibration(adc_ll_num_t adc_n, adc_channel_t channel, adc
|
||||
|
||||
#endif //SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
DMA setting
|
||||
RTC controller setting
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Initialize the hal context
|
||||
* Set adc output data format for RTC controller.
|
||||
*
|
||||
* @param hal Context of the HAL
|
||||
* @param config Configuration of the HAL
|
||||
* @prarm adc_n ADC unit.
|
||||
* @prarm bits Output data bits width option.
|
||||
*/
|
||||
void adc_hal_context_config(adc_hal_context_t *hal, const adc_hal_config_t *config);
|
||||
#define adc_hal_rtc_set_output_format(adc_n, bits) adc_ll_rtc_set_output_format(adc_n, bits)
|
||||
|
||||
/**
|
||||
* @brief Initialize the HW
|
||||
* ADC module output data invert or not.
|
||||
*
|
||||
* @param hal Context of the HAL
|
||||
* @prarm adc_n ADC unit.
|
||||
*/
|
||||
void adc_hal_digi_init(adc_hal_context_t *hal);
|
||||
|
||||
/**
|
||||
* @brief Reset ADC / DMA fifo
|
||||
*
|
||||
* @param hal Context of the HAL
|
||||
*/
|
||||
void adc_hal_fifo_reset(adc_hal_context_t *hal);
|
||||
|
||||
/**
|
||||
* @brief Start DMA
|
||||
*
|
||||
* @param hal Context of the HAL
|
||||
* @param data_buf Pointer to the data buffer, the length should be multiple of ``desc_max_num`` and ``eof_num`` in ``adc_hal_context_t``
|
||||
*/
|
||||
void adc_hal_digi_rxdma_start(adc_hal_context_t *hal, uint8_t *data_buf);
|
||||
|
||||
/**
|
||||
* @brief Start ADC
|
||||
*
|
||||
* @param hal Context of the HAL
|
||||
*/
|
||||
void adc_hal_digi_start(adc_hal_context_t *hal);
|
||||
|
||||
/**
|
||||
* @brief Get the ADC reading result
|
||||
*
|
||||
* @param hal Context of the HAL
|
||||
* @param eof_desc_addr The last descriptor that is finished by HW. Should be got from DMA
|
||||
* @param[out] cur_desc The descriptor with ADC reading result (from the 1st one to the last one (``eof_desc_addr``))
|
||||
*
|
||||
* @return See ``adc_hal_dma_desc_status_t``
|
||||
*/
|
||||
adc_hal_dma_desc_status_t adc_hal_get_reading_result(adc_hal_context_t *hal, const intptr_t eof_desc_addr, dma_descriptor_t **cur_desc);
|
||||
|
||||
/**
|
||||
* @brief Stop DMA
|
||||
*
|
||||
* @param hal Context of the HAL
|
||||
*/
|
||||
void adc_hal_digi_rxdma_stop(adc_hal_context_t *hal);
|
||||
|
||||
/**
|
||||
* @brief Clear interrupt
|
||||
*
|
||||
* @param hal Context of the HAL
|
||||
* @param mask mask of the interrupt
|
||||
*/
|
||||
void adc_hal_digi_clr_intr(adc_hal_context_t *hal, uint32_t mask);
|
||||
|
||||
/**
|
||||
* @brief Enable interrupt
|
||||
*
|
||||
* @param hal Context of the HAL
|
||||
* @param mask mask of the interrupt
|
||||
*/
|
||||
void adc_hal_digi_dis_intr(adc_hal_context_t *hal, uint32_t mask);
|
||||
|
||||
/**
|
||||
* @brief Stop ADC
|
||||
*
|
||||
* @param hal Context of the HAL
|
||||
*/
|
||||
void adc_hal_digi_stop(adc_hal_context_t *hal);
|
||||
|
||||
#endif //#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684
|
||||
#define adc_hal_rtc_output_invert(adc_n, inv_en) adc_ll_rtc_output_invert(adc_n, inv_en)
|
||||
|
@ -54,26 +54,9 @@ typedef enum {
|
||||
ADC_ATTEN_MAX,
|
||||
} adc_atten_t;
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
/**
|
||||
* @brief ESP32 ADC DMA source selection.
|
||||
*/
|
||||
#else
|
||||
/**
|
||||
* @brief ESP32 ADC DMA source selection.
|
||||
*
|
||||
* @deprecated Not applicable on ESP32-S2 because ESP32-S2 doesn't use I2S DMA.
|
||||
*/
|
||||
#endif
|
||||
typedef enum {
|
||||
ADC_I2S_DATA_SRC_IO_SIG = 0, /*!< I2S data from GPIO matrix signal */
|
||||
ADC_I2S_DATA_SRC_ADC = 1, /*!< I2S data from ADC */
|
||||
ADC_I2S_DATA_SRC_MAX,
|
||||
} adc_i2s_source_t;
|
||||
|
||||
/**
|
||||
* @brief ADC resolution setting option.
|
||||
*
|
||||
* @note Only used in single read mode
|
||||
*/
|
||||
typedef enum {
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
@ -89,82 +72,56 @@ typedef enum {
|
||||
ADC_WIDTH_MAX,
|
||||
} adc_bits_width_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief ADC digital controller (DMA mode) work mode.
|
||||
*
|
||||
* @note The conversion mode affects the sampling frequency:
|
||||
* SINGLE_UNIT_1: When the measurement is triggered, only ADC1 is sampled once.
|
||||
* SINGLE_UNIT_2: When the measurement is triggered, only ADC2 is sampled once.
|
||||
* BOTH_UNIT : When the measurement is triggered, ADC1 and ADC2 are sampled at the same time.
|
||||
* ALTER_UNIT : When the measurement is triggered, ADC1 or ADC2 samples alternately.
|
||||
*/
|
||||
typedef enum {
|
||||
ADC_CONV_SINGLE_UNIT_1 = 1, /*!< SAR ADC 1. */
|
||||
ADC_CONV_SINGLE_UNIT_2 = 2, /*!< SAR ADC 2. */
|
||||
ADC_CONV_BOTH_UNIT = 3, /*!< SAR ADC 1 and 2. */
|
||||
ADC_CONV_ALTER_UNIT = 7, /*!< SAR ADC 1 and 2 alternative mode. */
|
||||
ADC_CONV_SINGLE_UNIT_1 = 1, ///< Only use ADC1 for conversion
|
||||
ADC_CONV_SINGLE_UNIT_2 = 2, ///< Only use ADC2 for conversion
|
||||
ADC_CONV_BOTH_UNIT = 3, ///< Use Both ADC1 and ADC2 for conversion simultaneously
|
||||
ADC_CONV_ALTER_UNIT = 7, ///< Use both ADC1 and ADC2 for conversion by turn. e.g. ADC1 -> ADC2 -> ADC1 -> ADC2 .....
|
||||
ADC_CONV_UNIT_MAX,
|
||||
} adc_digi_convert_mode_t;
|
||||
|
||||
/**
|
||||
* @brief ADC digital controller (DMA mode) conversion rules setting.
|
||||
*/
|
||||
typedef struct {
|
||||
union {
|
||||
struct {
|
||||
uint8_t atten: 2; /*!< ADC sampling voltage attenuation configuration. Modification of attenuation affects the range of measurements.
|
||||
0: measurement range 0 - 800mV,
|
||||
1: measurement range 0 - 1100mV,
|
||||
2: measurement range 0 - 1350mV,
|
||||
3: measurement range 0 - 2600mV. */
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
uint8_t bit_width: 2; /*!< ADC resolution.
|
||||
- 0: 9 bit;
|
||||
- 1: 10 bit;
|
||||
- 2: 11 bit;
|
||||
- 3: 12 bit. */
|
||||
int8_t channel: 4; /*!< ADC channel index. */
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
uint8_t reserved: 2; /*!< reserved0 */
|
||||
uint8_t channel: 4; /*!< ADC channel index. */
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684
|
||||
uint8_t channel: 3; /*!< ADC channel index. */
|
||||
uint8_t unit: 1; /*!< ADC unit index. */
|
||||
uint8_t reserved: 2; /*!< reserved0 */
|
||||
#endif
|
||||
};
|
||||
uint8_t val; /*!<Raw data value */
|
||||
};
|
||||
} adc_digi_pattern_table_t;
|
||||
|
||||
/**
|
||||
* @brief ADC digital controller (DMA mode) output data format option.
|
||||
*/
|
||||
typedef enum {
|
||||
ADC_DIGI_FORMAT_12BIT, /*!<ADC to DMA data format, [15:12]-channel, [11: 0]-12 bits ADC data (`adc_digi_output_data_t`).
|
||||
Note: For single convert mode. */
|
||||
ADC_DIGI_FORMAT_11BIT, /*!<ADC to DMA data format, [15]-adc unit, [14:11]-channel, [10: 0]-11 bits ADC data (`adc_digi_output_data_t`).
|
||||
Note: For multi or alter convert mode. */
|
||||
ADC_DIGI_FORMAT_MAX,
|
||||
ADC_DIGI_FORMAT_12BIT __attribute__((deprecated)), /*!<ADC to DMA data format, [15:12]-channel, [11: 0]-12 bits ADC data (`adc_digi_output_data_t`). Note: For single convert mode. */
|
||||
ADC_DIGI_FORMAT_11BIT __attribute__((deprecated)), /*!<ADC to DMA data format, [15]-adc unit, [14:11]-channel, [10: 0]-11 bits ADC data (`adc_digi_output_data_t`). Note: For multi or alter convert mode. */
|
||||
ADC_DIGI_FORMAT_MAX __attribute__((deprecated)),
|
||||
|
||||
ADC_DIGI_OUTPUT_FORMAT_TYPE1, ///< See `adc_digi_output_data_t.type1`
|
||||
ADC_DIGI_OUTPUT_FORMAT_TYPE2, ///< See `adc_digi_output_data_t.type2`
|
||||
} adc_digi_output_format_t;
|
||||
|
||||
/**
|
||||
* @brief ADC digital controller pattern configuration
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t atten; ///< Attenuation of this ADC channel
|
||||
uint8_t channel; ///< ADC channel
|
||||
uint8_t unit; ///< ADC unit
|
||||
uint8_t bit_width; ///< ADC output bit width
|
||||
} adc_digi_pattern_config_t;
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Output Format
|
||||
---------------------------------------------------------------*/
|
||||
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
|
||||
/**
|
||||
* @brief ADC digital controller (DMA mode) output data format.
|
||||
* Used to analyze the acquired ADC (DMA) data.
|
||||
*
|
||||
* @note ESP32-S2:
|
||||
* Member `channel` can be used to judge the validity of the ADC data, because the role of the arbiter may get invalid ADC data.
|
||||
* @note ESP32: Only `type1` is valid. ADC2 does not support DMA mode.
|
||||
* @note ESP32-S2: Member `channel` can be used to judge the validity of the ADC data,
|
||||
* because the role of the arbiter may get invalid ADC data.
|
||||
*/
|
||||
typedef struct {
|
||||
union {
|
||||
struct {
|
||||
uint16_t data: 12; /*!<ADC real output data info. Resolution: 12 bit. */
|
||||
uint16_t channel: 4; /*!<ADC channel index info. For ESP32-S2:
|
||||
If (channel < ADC_CHANNEL_MAX), The data is valid.
|
||||
If (channel > ADC_CHANNEL_MAX), The data is invalid. */
|
||||
} type1; /*!<When the configured output format is 12bit. `ADC_DIGI_FORMAT_12BIT` */
|
||||
uint16_t channel: 4; /*!<ADC channel index info. */
|
||||
} type1;
|
||||
struct {
|
||||
uint16_t data: 11; /*!<ADC real output data info. Resolution: 11 bit. */
|
||||
uint16_t channel: 4; /*!<ADC channel index info. For ESP32-S2:
|
||||
@ -175,8 +132,8 @@ typedef struct {
|
||||
uint16_t val; /*!<Raw data value */
|
||||
};
|
||||
} adc_digi_output_data_t;
|
||||
#endif
|
||||
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684
|
||||
/**
|
||||
* @brief ADC digital controller (DMA mode) output data format.
|
||||
* Used to analyze the acquired ADC (DMA) data.
|
||||
@ -195,112 +152,32 @@ typedef struct {
|
||||
uint32_t val; /*!<Raw data value */
|
||||
};
|
||||
} adc_digi_output_data_t;
|
||||
#endif
|
||||
|
||||
#if !CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
/**
|
||||
* @brief ADC digital controller (DMA mode) clock system setting.
|
||||
* Calculation formula: controller_clk = (`APLL` or `APB`) / (div_num + div_a / div_b + 1).
|
||||
*
|
||||
* @note: The clocks of the DAC digital controller use the ADC digital controller clock divider.
|
||||
* @brief ADC digital controller (DMA mode) output data format.
|
||||
* Used to analyze the acquired ADC (DMA) data.
|
||||
*/
|
||||
typedef struct {
|
||||
bool use_apll; /*!<true: use APLL clock; false: use APB clock. */
|
||||
uint32_t div_num; /*!<Division factor. Range: 0 ~ 255.
|
||||
Note: When a higher frequency clock is used (the division factor is less than 9),
|
||||
the ADC reading value will be slightly offset. */
|
||||
uint32_t div_b; /*!<Division factor. Range: 1 ~ 63. */
|
||||
uint32_t div_a; /*!<Division factor. Range: 0 ~ 63. */
|
||||
} adc_digi_clk_t;
|
||||
|
||||
#endif //!CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
/**
|
||||
* @brief ADC digital controller (DMA mode) configuration parameters.
|
||||
*
|
||||
* Example setting: When using ADC1 channel0 to measure voltage, the sampling rate is required to be 1 kHz:
|
||||
*
|
||||
* +---------------------+--------+--------+--------+
|
||||
* | sample rate | 1 kHz | 1 kHz | 1 kHz |
|
||||
* +---------------------+--------+--------+--------+
|
||||
* | conv_mode | single | both | alter |
|
||||
* | adc1_pattern_len | 1 | 1 | 1 |
|
||||
* | dig_clk.use_apll | 0 | 0 | 0 |
|
||||
* | dig_clk.div_num | 99 | 99 | 99 |
|
||||
* | dig_clk.div_b | 0 | 0 | 0 |
|
||||
* | dig_clk.div_a | 0 | 0 | 0 |
|
||||
* | interval | 400 | 400 | 200 |
|
||||
* +---------------------+--------+--------+--------+
|
||||
* | `trigger_meas_freq` | 1 kHz | 1 kHz | 2 kHz |
|
||||
* +---------------------+--------+--------+--------+
|
||||
*
|
||||
* Explanation of the relationship between `conv_limit_num`, `dma_eof_num` and the number of DMA outputs:
|
||||
*
|
||||
* +---------------------+--------+--------+--------+
|
||||
* | conv_mode | single | both | alter |
|
||||
* +---------------------+--------+--------+--------+
|
||||
* | trigger meas times | 1 | 1 | 1 |
|
||||
* +---------------------+--------+--------+--------+
|
||||
* | conv_limit_num | +1 | +1 | +1 |
|
||||
* | dma_eof_num | +1 | +2 | +1 |
|
||||
* | dma output (byte) | +2 | +4 | +2 |
|
||||
* +---------------------+--------+--------+--------+
|
||||
*/
|
||||
typedef struct {
|
||||
bool conv_limit_en; /*!<Enable the function of limiting ADC conversion times.
|
||||
If the number of ADC conversion trigger count is equal to the `limit_num`, the conversion is stopped. */
|
||||
uint32_t conv_limit_num; /*!<Set the upper limit of the number of ADC conversion triggers. Range: 1 ~ 255. */
|
||||
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
|
||||
uint32_t adc1_pattern_len; /*!<Pattern table length for digital controller. Range: 0 ~ 16 (0: Don't change the pattern table setting).
|
||||
The pattern table that defines the conversion rules for each SAR ADC. Each table has 16 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 16 different rules before repeating itself. */
|
||||
uint32_t adc2_pattern_len; /*!<Refer to ``adc1_pattern_len`` */
|
||||
adc_digi_pattern_table_t *adc1_pattern; /*!<Pointer to pattern table for digital controller. The table size defined by `adc1_pattern_len`. */
|
||||
adc_digi_pattern_table_t *adc2_pattern; /*!<Refer to `adc1_pattern` */
|
||||
adc_digi_convert_mode_t conv_mode; /*!<ADC conversion mode for digital controller. See ``adc_digi_convert_mode_t``. */
|
||||
adc_digi_output_format_t format; /*!<ADC output data format for digital controller. See ``adc_digi_output_format_t``. */
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684
|
||||
uint32_t adc_pattern_len; /*!<Pattern table length for digital controller. Range: 0 ~ 7 (0: Don't change the pattern table setting).
|
||||
The pattern table that defines the conversion rules for each SAR ADC. Each table has 7 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 16 different rules before repeating itself. */
|
||||
adc_digi_pattern_table_t *adc_pattern; /*!<Pointer to pattern table for digital controller. The table size defined by `adc_pattern_len`. */
|
||||
#endif
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
uint32_t interval; /*!<The number of interval clock cycles for the digital controller to trigger the measurement.
|
||||
The unit is the divided clock. Range: 40 ~ 4095.
|
||||
Expression: `trigger_meas_freq` = `controller_clk` / 2 / interval. Refer to ``adc_digi_clk_t``.
|
||||
Note: The sampling rate of each channel is also related to the conversion mode (See ``adc_digi_convert_mode_t``) and pattern table settings. */
|
||||
adc_digi_clk_t dig_clk; /*!<ADC digital controller clock divider settings. Refer to ``adc_digi_clk_t``.
|
||||
Note: The clocks of the DAC digital controller use the ADC digital controller clock divider. */
|
||||
uint32_t dma_eof_num; /*!<DMA eof num of adc digital controller.
|
||||
If the number of measurements reaches `dma_eof_num`, then `dma_in_suc_eof` signal is generated in DMA.
|
||||
Note: The converted data in the DMA in link buffer will be multiple of two bytes. */
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684
|
||||
uint32_t sample_freq_hz; /*!< The expected ADC sampling frequency in Hz. Range: 611Hz ~ 83333Hz
|
||||
Fs = Fd / interval / 2
|
||||
Fs: sampling frequency;
|
||||
Fd: digital controller frequency, no larger than 5M for better performance
|
||||
interval: interval between 2 measurement trigger signal, the smallest interval should not be smaller than the ADC measurement period, the largest interval should not be larger than 4095 */
|
||||
#endif
|
||||
} adc_digi_config_t;
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
/**
|
||||
* @brief ADC digital controller (DMA mode) interrupt type options.
|
||||
*/
|
||||
typedef enum {
|
||||
ADC_DIGI_INTR_MASK_MONITOR = 0x1,
|
||||
ADC_DIGI_INTR_MASK_MEAS_DONE = 0x2,
|
||||
ADC_DIGI_INTR_MASK_ALL = 0x3,
|
||||
} adc_digi_intr_t;
|
||||
FLAG_ATTR(adc_digi_intr_t)
|
||||
union {
|
||||
struct {
|
||||
uint32_t data: 13; /*!<ADC real output data info. Resolution: 13 bit. */
|
||||
uint32_t channel: 4; /*!<ADC channel index info.
|
||||
If (channel < ADC_CHANNEL_MAX), The data is valid.
|
||||
If (channel > ADC_CHANNEL_MAX), The data is invalid. */
|
||||
uint32_t unit: 1; /*!<ADC unit index info. 0: ADC1; 1: ADC2. */
|
||||
uint32_t reserved17_31: 14; /*!<Reserved17. */
|
||||
} type2; /*!<When the configured output format is 12bit. `ADC_DIGI_FORMAT_11BIT` */
|
||||
uint32_t val; /*!<Raw data value */
|
||||
};
|
||||
} adc_digi_output_data_t;
|
||||
#endif
|
||||
|
||||
#if !CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
#if SOC_ADC_ARBITER_SUPPORTED
|
||||
/*---------------------------------------------------------------
|
||||
Arbiter
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief ADC arbiter work mode option.
|
||||
*
|
||||
@ -336,7 +213,12 @@ typedef struct {
|
||||
.dig_pri = 0, \
|
||||
.pwdet_pri = 2, \
|
||||
}
|
||||
#endif //#if SOC_ADC_ARBITER_SUPPORTED
|
||||
|
||||
#if SOC_ADC_FILTER_SUPPORTED
|
||||
/*---------------------------------------------------------------
|
||||
Filter
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief ADC digital controller (DMA mode) filter index options.
|
||||
*
|
||||
@ -379,7 +261,12 @@ typedef struct {
|
||||
For ESP32-S2, it's always `ADC_CHANNEL_MAX` */
|
||||
adc_digi_filter_mode_t mode;/*!<Set adc filter mode for filter. See ``adc_digi_filter_mode_t``. */
|
||||
} adc_digi_filter_t;
|
||||
#endif // #if SOC_ADC_FILTER_SUPPORTED
|
||||
|
||||
#if SOC_ADC_MONITOR_SUPPORTED
|
||||
/*---------------------------------------------------------------
|
||||
Monitor
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief ADC digital controller (DMA mode) monitor index options.
|
||||
*
|
||||
@ -429,5 +316,41 @@ typedef struct {
|
||||
uint32_t threshold; /*!<Set monitor threshold of adc digital controller. */
|
||||
#endif
|
||||
} adc_digi_monitor_t;
|
||||
#endif //#if SOC_ADC_MONITOR_SUPPORTED
|
||||
|
||||
#endif // CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
/*---------------------------------------------------------------
|
||||
To Be Deprecated TODO: IDF-3610
|
||||
---------------------------------------------------------------*/
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
/**
|
||||
* @brief ESP32 ADC DMA source selection.
|
||||
*/
|
||||
#else
|
||||
/**
|
||||
* @brief ESP32 ADC DMA source selection.
|
||||
*
|
||||
* @deprecated Not applicable on ESP32-S2 because ESP32-S2 doesn't use I2S DMA.
|
||||
*/
|
||||
#endif
|
||||
typedef enum {
|
||||
ADC_I2S_DATA_SRC_IO_SIG = 0, /*!< I2S data from GPIO matrix signal */
|
||||
ADC_I2S_DATA_SRC_ADC = 1, /*!< I2S data from ADC */
|
||||
ADC_I2S_DATA_SRC_MAX,
|
||||
} adc_i2s_source_t;
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
/**
|
||||
* @brief ADC digital controller (DMA mode) clock system setting.
|
||||
* Calculation formula: controller_clk = (`APLL` or `APB`) / (div_num + div_a / div_b + 1).
|
||||
*
|
||||
* @note: The clocks of the DAC digital controller use the ADC digital controller clock divider.
|
||||
*/
|
||||
typedef struct {
|
||||
bool use_apll; /*!<true: use APLL clock; false: use APB clock. */
|
||||
uint32_t div_num; /*!<Division factor. Range: 0 ~ 255.
|
||||
Note: When a higher frequency clock is used (the division factor is less than 9),
|
||||
the ADC reading value will be slightly offset. */
|
||||
uint32_t div_b; /*!<Division factor. Range: 1 ~ 63. */
|
||||
uint32_t div_a; /*!<Division factor. Range: 0 ~ 63. */
|
||||
} adc_digi_clk_t;
|
||||
#endif
|
||||
|
@ -15,6 +15,10 @@ config SOC_CAPS_ECO_VER_MAX
|
||||
int
|
||||
default 3
|
||||
|
||||
config SOC_ADC_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_DAC_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
@ -91,6 +95,10 @@ config SOC_ADC_RTC_CTRL_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_ADC_DIG_CTRL_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_ADC_PERIPH_NUM
|
||||
int
|
||||
default 2
|
||||
@ -117,11 +125,11 @@ config SOC_ADC_DIGI_MAX_BITWIDTH
|
||||
|
||||
config SOC_ADC_SAMPLE_FREQ_THRES_HIGH
|
||||
int
|
||||
default 83333
|
||||
default 2
|
||||
|
||||
config SOC_ADC_SAMPLE_FREQ_THRES_LOW
|
||||
int
|
||||
default 611
|
||||
default 2000
|
||||
|
||||
config SOC_ADC_MAX_BITWIDTH
|
||||
int
|
||||
|
@ -1,16 +1,8 @@
|
||||
// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef _SOC_PERIPH_DEFS_H_
|
||||
#define _SOC_PERIPH_DEFS_H_
|
||||
@ -54,6 +46,7 @@ typedef enum {
|
||||
PERIPH_AES_MODULE,
|
||||
PERIPH_SHA_MODULE,
|
||||
PERIPH_RSA_MODULE,
|
||||
PERIPH_SARADC_MODULE,
|
||||
PERIPH_MODULE_MAX
|
||||
} periph_module_t;
|
||||
|
||||
|
@ -63,6 +63,7 @@
|
||||
/*-------------------------- COMMON CAPS ---------------------------------------*/
|
||||
#define SOC_CAPS_ECO_VER_MAX 3
|
||||
|
||||
#define SOC_ADC_SUPPORTED 1
|
||||
#define SOC_DAC_SUPPORTED 1
|
||||
#define SOC_MCPWM_SUPPORTED 1
|
||||
#define SOC_SDMMC_HOST_SUPPORTED 1
|
||||
@ -85,7 +86,7 @@
|
||||
|
||||
/*-------------------------- ADC CAPS ----------------------------------------*/
|
||||
/**
|
||||
* TO BE REMOVED in !14278
|
||||
* TO BE REMOVED
|
||||
* Check if adc support digital controller (DMA) mode.
|
||||
* @value
|
||||
* - 1 : support;
|
||||
@ -95,6 +96,7 @@
|
||||
|
||||
/*!< SAR ADC Module*/
|
||||
#define SOC_ADC_RTC_CTRL_SUPPORTED 1
|
||||
#define SOC_ADC_DIG_CTRL_SUPPORTED 1
|
||||
#define SOC_ADC_PERIPH_NUM (2)
|
||||
#define SOC_ADC_CHANNEL_NUM(PERIPH_NUM) ((PERIPH_NUM==0)? 8: 10)
|
||||
#define SOC_ADC_MAX_CHANNEL_NUM (10)
|
||||
@ -105,8 +107,8 @@
|
||||
#define SOC_ADC_DIGI_MIN_BITWIDTH (9)
|
||||
#define SOC_ADC_DIGI_MAX_BITWIDTH (12)
|
||||
/*!< F_sample = F_digi_con / 2 / interval. F_digi_con = 5M for now. 30 <= interva <= 4095 */
|
||||
#define SOC_ADC_SAMPLE_FREQ_THRES_HIGH 83333
|
||||
#define SOC_ADC_SAMPLE_FREQ_THRES_LOW 611
|
||||
#define SOC_ADC_SAMPLE_FREQ_THRES_HIGH (2*1000*1000)
|
||||
#define SOC_ADC_SAMPLE_FREQ_THRES_LOW (2000)
|
||||
|
||||
/*!< RTC */
|
||||
#define SOC_ADC_MAX_BITWIDTH (12)
|
||||
|
@ -7,6 +7,10 @@ config SOC_CPU_CORES_NUM
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_ADC_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_DEDICATED_GPIO_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
@ -107,6 +111,10 @@ config SOC_AES_SUPPORT_AES_256
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_ADC_DIG_CTRL_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_ADC_ARBITER_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
@ -128,8 +136,8 @@ config SOC_ADC_MAX_CHANNEL_NUM
|
||||
default 5
|
||||
|
||||
config SOC_ADC_DIGI_CONTROLLER_NUM
|
||||
bool
|
||||
default y
|
||||
int
|
||||
default 1
|
||||
|
||||
config SOC_ADC_PATT_LEN_MAX
|
||||
int
|
||||
|
@ -1,3 +1,9 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// The long term plan is to have a single soc_caps.h for each peripheral.
|
||||
// During the refactoring and multichip support development process, we
|
||||
// seperate these information into periph_caps.h for each peripheral and
|
||||
@ -20,6 +26,7 @@
|
||||
|
||||
/*-------------------------- COMMON CAPS ---------------------------------------*/
|
||||
#define SOC_CPU_CORES_NUM 1
|
||||
#define SOC_ADC_SUPPORTED 1
|
||||
#define SOC_DEDICATED_GPIO_SUPPORTED 1
|
||||
#define SOC_GDMA_SUPPORTED 1
|
||||
#define SOC_TWAI_SUPPORTED 1
|
||||
@ -53,6 +60,7 @@
|
||||
|
||||
/*-------------------------- ADC CAPS -------------------------------*/
|
||||
/*!< SAR ADC Module*/
|
||||
#define SOC_ADC_DIG_CTRL_SUPPORTED 1
|
||||
#define SOC_ADC_ARBITER_SUPPORTED 1
|
||||
#define SOC_ADC_FILTER_SUPPORTED 1
|
||||
#define SOC_ADC_MONITOR_SUPPORTED 1
|
||||
@ -61,7 +69,7 @@
|
||||
#define SOC_ADC_MAX_CHANNEL_NUM (5)
|
||||
|
||||
/*!< Digital */
|
||||
#define SOC_ADC_DIGI_CONTROLLER_NUM (1)
|
||||
#define SOC_ADC_DIGI_CONTROLLER_NUM (1U)
|
||||
#define SOC_ADC_PATT_LEN_MAX (8) /*!< One pattern table, each contains 8 items. Each item takes 1 byte */
|
||||
#define SOC_ADC_DIGI_MAX_BITWIDTH (12)
|
||||
#define SOC_ADC_DIGI_FILTER_NUM (2)
|
||||
@ -76,7 +84,6 @@
|
||||
/*!< Calibration */
|
||||
#define SOC_ADC_CALIBRATION_V1_SUPPORTED (1) /*!< support HW offset calibration version 1*/
|
||||
|
||||
|
||||
/*-------------------------- APB BACKUP DMA CAPS -------------------------------*/
|
||||
#define SOC_APB_BACKUP_DMA (1)
|
||||
|
||||
|
@ -7,6 +7,10 @@ config SOC_CPU_CORES_NUM
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_ADC_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_DEDICATED_GPIO_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
@ -95,19 +99,39 @@ config SOC_AES_SUPPORT_AES_256
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_ADC_DIG_CTRL_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_ADC_ARBITER_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_ADC_FILTER_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_ADC_MONITOR_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_ADC_PERIPH_NUM
|
||||
int
|
||||
default 2
|
||||
|
||||
config SOC_ADC_PATT_LEN_MAX
|
||||
int
|
||||
default 16
|
||||
|
||||
config SOC_ADC_MAX_CHANNEL_NUM
|
||||
int
|
||||
default 5
|
||||
|
||||
config SOC_ADC_MAX_BITWIDTH
|
||||
config SOC_ADC_DIGI_CONTROLLER_NUM
|
||||
int
|
||||
default 1
|
||||
|
||||
config SOC_ADC_PATT_LEN_MAX
|
||||
int
|
||||
default 8
|
||||
|
||||
config SOC_ADC_DIGI_MAX_BITWIDTH
|
||||
int
|
||||
default 12
|
||||
|
||||
@ -119,10 +143,6 @@ config SOC_ADC_DIGI_MONITOR_NUM
|
||||
int
|
||||
default 2
|
||||
|
||||
config SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_ADC_SAMPLE_FREQ_THRES_HIGH
|
||||
int
|
||||
default 83333
|
||||
@ -131,6 +151,10 @@ config SOC_ADC_SAMPLE_FREQ_THRES_LOW
|
||||
int
|
||||
default 611
|
||||
|
||||
config SOC_ADC_MAX_BITWIDTH
|
||||
int
|
||||
default 12
|
||||
|
||||
config SOC_APB_BACKUP_DMA
|
||||
bool
|
||||
default y
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
/*-------------------------- COMMON CAPS ---------------------------------------*/
|
||||
#define SOC_CPU_CORES_NUM 1
|
||||
#define SOC_ADC_SUPPORTED 1
|
||||
#define SOC_DEDICATED_GPIO_SUPPORTED 1
|
||||
#define SOC_GDMA_SUPPORTED 1
|
||||
#define SOC_TWAI_SUPPORTED 1
|
||||
@ -55,19 +56,29 @@
|
||||
#define SOC_AES_SUPPORT_AES_256 (1)
|
||||
|
||||
/*-------------------------- ADC CAPS -------------------------------*/
|
||||
/*!< SAR ADC Module*/
|
||||
#define SOC_ADC_DIG_CTRL_SUPPORTED 1
|
||||
#define SOC_ADC_ARBITER_SUPPORTED 1
|
||||
#define SOC_ADC_FILTER_SUPPORTED 1
|
||||
#define SOC_ADC_MONITOR_SUPPORTED 1
|
||||
#define SOC_ADC_PERIPH_NUM (2)
|
||||
#define SOC_ADC_PATT_LEN_MAX (16)
|
||||
#define SOC_ADC_CHANNEL_NUM(PERIPH_NUM) ((PERIPH_NUM==0)? 5 : 1)
|
||||
#define SOC_ADC_MAX_CHANNEL_NUM (5)
|
||||
#define SOC_ADC_MAX_BITWIDTH (12)
|
||||
|
||||
/*!< Digital */
|
||||
#define SOC_ADC_DIGI_CONTROLLER_NUM (1U)
|
||||
#define SOC_ADC_PATT_LEN_MAX (8) /*!< One pattern table, each contains 8 items. Each item takes 1 byte */
|
||||
#define SOC_ADC_DIGI_MAX_BITWIDTH (12)
|
||||
#define SOC_ADC_DIGI_FILTER_NUM (2)
|
||||
#define SOC_ADC_DIGI_MONITOR_NUM (2)
|
||||
#define SOC_ADC_CALIBRATION_V1_SUPPORTED (1) /*!< support HW offset calibration version 1*/
|
||||
#define SOC_ADC_SUPPORT_DMA_MODE(PERIPH_NUM) 1
|
||||
//F_sample = F_digi_con / 2 / interval. F_digi_con = 5M for now. 30 <= interva <= 4095
|
||||
/*!< F_sample = F_digi_con / 2 / interval. F_digi_con = 5M for now. 30 <= interva <= 4095 */
|
||||
#define SOC_ADC_SAMPLE_FREQ_THRES_HIGH 83333
|
||||
#define SOC_ADC_SAMPLE_FREQ_THRES_LOW 611
|
||||
|
||||
/*!< RTC */
|
||||
#define SOC_ADC_MAX_BITWIDTH (12)
|
||||
|
||||
|
||||
/*-------------------------- APB BACKUP DMA CAPS -------------------------------*/
|
||||
#define SOC_APB_BACKUP_DMA (1)
|
||||
|
||||
@ -283,6 +294,7 @@
|
||||
#define SOC_MAC_BB_PD_MEM_SIZE (192*4)
|
||||
|
||||
/*-------------------------- Power Management CAPS ----------------------------*/
|
||||
|
||||
#define SOC_PM_SUPPORT_BT_WAKEUP (1)
|
||||
|
||||
#define SOC_PM_SUPPORT_CPU_PD (1)
|
||||
|
@ -3,6 +3,10 @@
|
||||
# using gen_soc_caps_kconfig.py, do not edit manually
|
||||
#####################################################
|
||||
|
||||
config SOC_ADC_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_DAC_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
@ -123,6 +127,10 @@ config SOC_ADC_RTC_CTRL_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_ADC_DIG_CTRL_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_ADC_ARBITER_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
@ -1,16 +1,8 @@
|
||||
// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef _SOC_PERIPH_DEFS_H_
|
||||
#define _SOC_PERIPH_DEFS_H_
|
||||
@ -50,6 +42,7 @@ typedef enum {
|
||||
PERIPH_AES_DMA_MODULE,
|
||||
PERIPH_SHA_DMA_MODULE,
|
||||
PERIPH_DEDIC_GPIO_MODULE,
|
||||
PERIPH_SARADC_MODULE,
|
||||
PERIPH_MODULE_MAX
|
||||
} periph_module_t;
|
||||
|
||||
|
@ -39,6 +39,7 @@
|
||||
#pragma once
|
||||
|
||||
/*-------------------------- COMMON CAPS ---------------------------------------*/
|
||||
#define SOC_ADC_SUPPORTED 1
|
||||
#define SOC_DAC_SUPPORTED 1
|
||||
#define SOC_TWAI_SUPPORTED 1
|
||||
#define SOC_CP_DMA_SUPPORTED 1
|
||||
@ -73,6 +74,7 @@
|
||||
/*-------------------------- ADC CAPS ----------------------------------------*/
|
||||
/*!< SAR ADC Module*/
|
||||
#define SOC_ADC_RTC_CTRL_SUPPORTED 1
|
||||
#define SOC_ADC_DIG_CTRL_SUPPORTED 1
|
||||
#define SOC_ADC_ARBITER_SUPPORTED 1
|
||||
#define SOC_ADC_FILTER_SUPPORTED 1
|
||||
#define SOC_ADC_MONITOR_SUPPORTED 1
|
||||
@ -94,7 +96,6 @@
|
||||
/*!< Calibration */
|
||||
#define SOC_ADC_CALIBRATION_V1_SUPPORTED (1) /*!< support HW offset calibration version 1*/
|
||||
|
||||
|
||||
/*-------------------------- BROWNOUT CAPS -----------------------------------*/
|
||||
#define SOC_BROWNOUT_RESET_SUPPORTED 1
|
||||
|
||||
|
@ -135,6 +135,10 @@ config SOC_RTCIO_WAKE_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_ADC_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PCNT_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
@ -263,6 +267,10 @@ config SOC_ADC_RTC_CTRL_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_ADC_DIG_CTRL_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_ADC_ARBITER_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
@ -1,16 +1,8 @@
|
||||
// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef _SOC_APB_SARADC_STRUCT_H_
|
||||
#define _SOC_APB_SARADC_STRUCT_H_
|
||||
|
||||
|
@ -1,16 +1,8 @@
|
||||
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
@ -58,6 +50,7 @@ typedef enum {
|
||||
PERIPH_SYSTIMER_MODULE,
|
||||
PERIPH_GDMA_MODULE,
|
||||
PERIPH_DEDIC_GPIO_MODULE,
|
||||
PERIPH_SARADC_MODULE,
|
||||
PERIPH_MODULE_MAX
|
||||
} periph_module_t;
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#pragma once
|
||||
|
||||
/*-------------------------- COMMON CAPS ---------------------------------------*/
|
||||
#define SOC_ADC_SUPPORTED 1
|
||||
#define SOC_PCNT_SUPPORTED 1
|
||||
#define SOC_TWAI_SUPPORTED 1
|
||||
#define SOC_GDMA_SUPPORTED 1
|
||||
@ -62,6 +63,7 @@
|
||||
/*-------------------------- ADC CAPS ----------------------------------------*/
|
||||
/*!< SAR ADC Module*/
|
||||
#define SOC_ADC_RTC_CTRL_SUPPORTED 1
|
||||
#define SOC_ADC_DIG_CTRL_SUPPORTED 1
|
||||
#define SOC_ADC_ARBITER_SUPPORTED 1
|
||||
#define SOC_ADC_FILTER_SUPPORTED 1
|
||||
#define SOC_ADC_MONITOR_SUPPORTED 1
|
||||
|
@ -7,6 +7,10 @@ config SOC_CPU_CORES_NUM
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_ADC_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_GDMA_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
@ -63,26 +67,42 @@ config SOC_AES_GDMA
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_ADC_DIG_CTRL_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_ADC_ARBITER_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_ADC_FILTER_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_ADC_MONITOR_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_ADC_PERIPH_NUM
|
||||
int
|
||||
default 2
|
||||
|
||||
config SOC_ADC_PATT_LEN_MAX
|
||||
int
|
||||
default 16
|
||||
|
||||
config SOC_ADC_MAX_CHANNEL_NUM
|
||||
int
|
||||
default 5
|
||||
|
||||
config SOC_ADC_MAX_BITWIDTH
|
||||
config SOC_ADC_DIGI_CONTROLLER_NUM
|
||||
int
|
||||
default 1
|
||||
|
||||
config SOC_ADC_PATT_LEN_MAX
|
||||
int
|
||||
default 8
|
||||
|
||||
config SOC_ADC_DIGI_MAX_BITWIDTH
|
||||
int
|
||||
default 12
|
||||
|
||||
config SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_ADC_DIGI_FILTER_NUM
|
||||
int
|
||||
default 2
|
||||
@ -91,10 +111,6 @@ config SOC_ADC_DIGI_MONITOR_NUM
|
||||
int
|
||||
default 2
|
||||
|
||||
config SOC_ADC_HW_CALIBRATION_V1
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_ADC_SAMPLE_FREQ_THRES_HIGH
|
||||
int
|
||||
default 83333
|
||||
@ -103,6 +119,10 @@ config SOC_ADC_SAMPLE_FREQ_THRES_LOW
|
||||
int
|
||||
default 611
|
||||
|
||||
config SOC_ADC_MAX_BITWIDTH
|
||||
int
|
||||
default 12
|
||||
|
||||
config SOC_APB_BACKUP_DMA
|
||||
bool
|
||||
default y
|
||||
|
@ -11,6 +11,7 @@
|
||||
#pragma once
|
||||
|
||||
#define SOC_CPU_CORES_NUM 1
|
||||
#define SOC_ADC_SUPPORTED 1
|
||||
#define SOC_GDMA_SUPPORTED 1
|
||||
#define SOC_BT_SUPPORTED 1
|
||||
#define SOC_DIG_SIGN_SUPPORTED 1
|
||||
@ -33,20 +34,28 @@
|
||||
#define SOC_AES_GDMA (1)
|
||||
|
||||
/*-------------------------- ADC CAPS -------------------------------*/
|
||||
/*!< SAR ADC Module*/
|
||||
#define SOC_ADC_DIG_CTRL_SUPPORTED 1
|
||||
#define SOC_ADC_ARBITER_SUPPORTED 1
|
||||
#define SOC_ADC_FILTER_SUPPORTED 1
|
||||
#define SOC_ADC_MONITOR_SUPPORTED 1
|
||||
#define SOC_ADC_PERIPH_NUM (2)
|
||||
#define SOC_ADC_PATT_LEN_MAX (16)
|
||||
#define SOC_ADC_CHANNEL_NUM(PERIPH_NUM) ((PERIPH_NUM==0)? 5 : 1)
|
||||
#define SOC_ADC_MAX_CHANNEL_NUM (5)
|
||||
#define SOC_ADC_MAX_BITWIDTH (12)
|
||||
#define SOC_ADC_CALIBRATION_V1_SUPPORTED (1) /*!< support HW offset calibration version 1*/
|
||||
|
||||
/*!< Digital */
|
||||
#define SOC_ADC_DIGI_CONTROLLER_NUM (1U)
|
||||
#define SOC_ADC_PATT_LEN_MAX (8) /*!< One pattern table, each contains 8 items. Each item takes 1 byte */
|
||||
#define SOC_ADC_DIGI_MAX_BITWIDTH (12)
|
||||
#define SOC_ADC_DIGI_FILTER_NUM (2)
|
||||
#define SOC_ADC_DIGI_MONITOR_NUM (2)
|
||||
#define SOC_ADC_HW_CALIBRATION_V1 (1) /*!< support HW offset calibration */
|
||||
#define SOC_ADC_SUPPORT_DMA_MODE(PERIPH_NUM) 1
|
||||
//F_sample = F_digi_con / 2 / interval. F_digi_con = 5M for now. 30 <= interva <= 4095
|
||||
/*!< F_sample = F_digi_con / 2 / interval. F_digi_con = 5M for now. 30 <= interva <= 4095 */
|
||||
#define SOC_ADC_SAMPLE_FREQ_THRES_HIGH 83333
|
||||
#define SOC_ADC_SAMPLE_FREQ_THRES_LOW 611
|
||||
|
||||
/*!< RTC */
|
||||
#define SOC_ADC_MAX_BITWIDTH (12)
|
||||
|
||||
/*-------------------------- APB BACKUP DMA CAPS -------------------------------*/
|
||||
#define SOC_APB_BACKUP_DMA (1)
|
||||
|
||||
|
@ -81,8 +81,7 @@ INPUT = \
|
||||
$(PROJECT_PATH)/components/hal/include/hal/lcd_types.h \
|
||||
$(PROJECT_PATH)/components/hal/include/hal/adc_types.h \
|
||||
$(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/adc_channel.h \
|
||||
$(PROJECT_PATH)/components/driver/include/driver/adc_common.h \
|
||||
$(PROJECT_PATH)/components/driver/$(IDF_TARGET)/include/driver/adc.h \
|
||||
$(PROJECT_PATH)/components/driver/include/driver/adc.h \
|
||||
$(PROJECT_PATH)/components/esp_adc_cal/include/esp_adc_cal.h \
|
||||
$(PROJECT_PATH)/components/hal/include/hal/dac_types.h \
|
||||
$(PROJECT_PATH)/components/driver/include/driver/dac_common.h \
|
||||
|
@ -161,7 +161,7 @@ Driver Usage
|
||||
|
||||
.. only:: esp32c3
|
||||
|
||||
The code example for using ADC continuous (DMA) read mode can be found in the :example:`peripherals/adc/esp32c3/adc` directory of ESP-IDF examples.
|
||||
The code example for using ADC continuous (DMA) read mode can be found in the :example:`peripherals/adc/dma_read` directory of ESP-IDF examples.
|
||||
|
||||
.. note:: See :ref:`adc_limitations` for the limitation of using ADC continuous (DMA) read mode.
|
||||
|
||||
@ -448,8 +448,6 @@ ADC driver
|
||||
|
||||
.. include-build-file:: inc/adc_types.inc
|
||||
|
||||
.. include-build-file:: inc/adc_common.inc
|
||||
|
||||
.. _adc-api-reference-adc-calibration:
|
||||
|
||||
ADC Calibration
|
||||
|
67
examples/peripherals/adc/dma_read/README.md
Normal file
67
examples/peripherals/adc/dma_read/README.md
Normal file
@ -0,0 +1,67 @@
|
||||
# ADC DMA Example
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
This example shows how to use ADC Continuous Read Mode (DMA Mode) to read from GPIO pins via on-chip ADC module(s).
|
||||
|
||||
## How to use example
|
||||
|
||||
### Hardware Required
|
||||
|
||||
* A development board with ESP32, ESP32-S and ESP32-C SoC
|
||||
* A USB cable for power supply and programming
|
||||
|
||||
Please refer to the `channel` array defined in `adc_dma_example_main.c`. These GPIOs should be connected to voltage sources (0 ~ 3.3V). If other ADC unit(s) / channel(s) are selected in your application,
|
||||
feel free to modify these definitions.
|
||||
|
||||
### Configure the project
|
||||
|
||||
```
|
||||
idf.py menuconfig
|
||||
```
|
||||
|
||||
### Build and Flash
|
||||
|
||||
Build the project and flash it to the board, then run monitor tool to view serial output:
|
||||
|
||||
```
|
||||
idf.py -p PORT flash monitor
|
||||
```
|
||||
|
||||
(To exit the serial monitor, type ``Ctrl-]``.)
|
||||
|
||||
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
|
||||
|
||||
## Example Output
|
||||
|
||||
Running this example, you will see the following log output on the serial monitor:
|
||||
```
|
||||
I (338) ADC DMA: adc_pattern[0].atten is :0
|
||||
I (348) ADC DMA: adc_pattern[0].channel is :2
|
||||
I (348) ADC DMA: adc_pattern[0].unit is :0
|
||||
I (358) ADC DMA: adc_pattern[1].atten is :0
|
||||
I (358) ADC DMA: adc_pattern[1].channel is :3
|
||||
I (368) ADC DMA: adc_pattern[1].unit is :0
|
||||
I (368) ADC DMA: adc_pattern[2].atten is :0
|
||||
I (378) ADC DMA: adc_pattern[2].channel is :0
|
||||
I (378) ADC DMA: adc_pattern[2].unit is :1
|
||||
I (388) TASK:: ret is 0, ret_num is 256
|
||||
I (388) ADC DMA: Unit: 1,_Channel: 2, Value: bec
|
||||
I (398) ADC DMA: Unit: 2,_Channel: 0, Value: 9cb
|
||||
I (398) ADC DMA: Unit: 1,_Channel: 3, Value: acb
|
||||
I (408) ADC DMA: Unit: 2,_Channel: 0, Value: 966
|
||||
I (408) ADC DMA: Unit: 1,_Channel: 2, Value: b63
|
||||
I (418) ADC DMA: Unit: 2,_Channel: 0, Value: 8ff
|
||||
I (418) ADC DMA: Unit: 1,_Channel: 3, Value: a6b
|
||||
I (428) ADC DMA: Unit: 2,_Channel: 0, Value: 8a2
|
||||
...
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
* program upload failure
|
||||
|
||||
* Hardware connection is not correct: run `idf.py -p PORT monitor`, and reboot your board to see if there are any output logs.
|
||||
* The baud rate for downloading is too high: lower your baud rate in the `menuconfig` menu, and try again.
|
||||
|
||||
For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon.
|
176
examples/peripherals/adc/dma_read/main/adc_dma_example_main.c
Normal file
176
examples/peripherals/adc/dma_read/main/adc_dma_example_main.c
Normal file
@ -0,0 +1,176 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "driver/adc.h"
|
||||
|
||||
#define TIMES 256
|
||||
#define GET_UNIT(x) ((x>>3) & 0x1)
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define ADC_RESULT_BYTE 2
|
||||
#define ADC_CONV_LIMIT_EN 1 //For ESP32, this should always be set to 1
|
||||
#define ADC_CONV_MODE ADC_CONV_SINGLE_UNIT_1 //ESP32 only supports ADC1 DMA mode
|
||||
#define ADC_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE1
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#define ADC_RESULT_BYTE 2
|
||||
#define ADC_CONV_LIMIT_EN 0
|
||||
#define ADC_CONV_MODE ADC_CONV_BOTH_UNIT
|
||||
#define ADC_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE2
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684
|
||||
#define ADC_RESULT_BYTE 4
|
||||
#define ADC_CONV_LIMIT_EN 0
|
||||
#define ADC_CONV_MODE ADC_CONV_ALTER_UNIT //ESP32C3 only supports alter mode
|
||||
#define ADC_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE2
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#define ADC_RESULT_BYTE 4
|
||||
#define ADC_CONV_LIMIT_EN 0
|
||||
#define ADC_CONV_MODE ADC_CONV_BOTH_UNIT
|
||||
#define ADC_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE2
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684
|
||||
static uint16_t adc1_chan_mask = BIT(2) | BIT(3);
|
||||
static uint16_t adc2_chan_mask = BIT(0);
|
||||
static adc_channel_t channel[3] = {ADC1_CHANNEL_2, ADC1_CHANNEL_3, (ADC2_CHANNEL_0 | 1 << 3)};
|
||||
#endif
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
static uint16_t adc1_chan_mask = BIT(2) | BIT(3);
|
||||
static uint16_t adc2_chan_mask = BIT(0);
|
||||
static adc_channel_t channel[3] = {ADC1_CHANNEL_2, ADC1_CHANNEL_3, (ADC2_CHANNEL_0 | 1 << 3)};
|
||||
#endif
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
static uint16_t adc1_chan_mask = BIT(7);
|
||||
static uint16_t adc2_chan_mask = 0;
|
||||
static adc_channel_t channel[1] = {ADC1_CHANNEL_7};
|
||||
#endif
|
||||
|
||||
static const char *TAG = "ADC DMA";
|
||||
|
||||
static void continuous_adc_init(uint16_t adc1_chan_mask, uint16_t adc2_chan_mask, adc_channel_t *channel, uint8_t channel_num)
|
||||
{
|
||||
adc_digi_init_config_t adc_dma_config = {
|
||||
.max_store_buf_size = 1024,
|
||||
.conv_num_each_intr = TIMES,
|
||||
.adc1_chan_mask = adc1_chan_mask,
|
||||
.adc2_chan_mask = adc2_chan_mask,
|
||||
};
|
||||
ESP_ERROR_CHECK(adc_digi_initialize(&adc_dma_config));
|
||||
|
||||
adc_digi_configuration_t dig_cfg = {
|
||||
.conv_limit_en = ADC_CONV_LIMIT_EN,
|
||||
.conv_limit_num = 250,
|
||||
.sample_freq_hz = 10 * 1000,
|
||||
.conv_mode = ADC_CONV_MODE,
|
||||
.format = ADC_OUTPUT_TYPE,
|
||||
};
|
||||
|
||||
adc_digi_pattern_config_t adc_pattern[SOC_ADC_PATT_LEN_MAX] = {0};
|
||||
dig_cfg.pattern_num = channel_num;
|
||||
for (int i = 0; i < channel_num; i++) {
|
||||
uint8_t unit = GET_UNIT(channel[i]);
|
||||
uint8_t ch = channel[i] & 0x7;
|
||||
adc_pattern[i].atten = ADC_ATTEN_DB_0;
|
||||
adc_pattern[i].channel = ch;
|
||||
adc_pattern[i].unit = unit;
|
||||
adc_pattern[i].bit_width = SOC_ADC_DIGI_MAX_BITWIDTH;
|
||||
|
||||
ESP_LOGI(TAG, "adc_pattern[%d].atten is :%x", i, adc_pattern[i].atten);
|
||||
ESP_LOGI(TAG, "adc_pattern[%d].channel is :%x", i, adc_pattern[i].channel);
|
||||
ESP_LOGI(TAG, "adc_pattern[%d].unit is :%x", i, adc_pattern[i].unit);
|
||||
}
|
||||
dig_cfg.adc_pattern = adc_pattern;
|
||||
ESP_ERROR_CHECK(adc_digi_controller_configure(&dig_cfg));
|
||||
}
|
||||
|
||||
#if !CONFIG_IDF_TARGET_ESP32
|
||||
static bool check_valid_data(const adc_digi_output_data_t *data)
|
||||
{
|
||||
const unsigned int unit = data->type2.unit;
|
||||
if (unit > 2) return false;
|
||||
if (data->type2.channel >= SOC_ADC_CHANNEL_NUM(unit)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
esp_err_t ret;
|
||||
uint32_t ret_num = 0;
|
||||
uint8_t result[TIMES] = {0};
|
||||
memset(result, 0xcc, TIMES);
|
||||
|
||||
continuous_adc_init(adc1_chan_mask, adc2_chan_mask, channel, sizeof(channel) / sizeof(adc_channel_t));
|
||||
adc_digi_start();
|
||||
|
||||
while(1) {
|
||||
ret = adc_digi_read_bytes(result, TIMES, &ret_num, ADC_MAX_DELAY);
|
||||
if (ret == ESP_OK || ret == ESP_ERR_INVALID_STATE) {
|
||||
if (ret == ESP_ERR_INVALID_STATE) {
|
||||
/**
|
||||
* @note 1
|
||||
* Issue:
|
||||
* As an example, we simply print the result out, which is super slow. Therefore the conversion is too
|
||||
* fast for the task to handle. In this condition, some conversion results lost.
|
||||
*
|
||||
* Reason:
|
||||
* When this error occurs, you will usually see the task watchdog timeout issue also.
|
||||
* Because the conversion is too fast, whereas the task calling `adc_digi_read_bytes` is slow.
|
||||
* So `adc_digi_read_bytes` will hardly block. Therefore Idle Task hardly has chance to run. In this
|
||||
* example, we add a `vTaskDelay(1)` below, to prevent the task watchdog timeout.
|
||||
*
|
||||
* Solution:
|
||||
* Either decrease the conversion speed, or increase the frequency you call `adc_digi_read_bytes`
|
||||
*/
|
||||
}
|
||||
|
||||
ESP_LOGI("TASK:", "ret is %x, ret_num is %d", ret, ret_num);
|
||||
for (int i = 0; i < ret_num; i += ADC_RESULT_BYTE) {
|
||||
adc_digi_output_data_t *p = (void*)&result[i];
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
ESP_LOGI(TAG, "Unit: %d, Channel: %d, Value: %x", 1, p->type1.channel, p->type1.data);
|
||||
#else
|
||||
if (ADC_CONV_MODE == ADC_CONV_BOTH_UNIT || ADC_CONV_MODE == ADC_CONV_ALTER_UNIT) {
|
||||
if (check_valid_data(p)) {
|
||||
ESP_LOGI(TAG, "Unit: %d,_Channel: %d, Value: %x", p->type2.unit+1, p->type2.channel, p->type2.data);
|
||||
} else {
|
||||
// abort();
|
||||
ESP_LOGI(TAG, "Invalid data [%d_%d_%x]", p->type2.unit+1, p->type2.channel, p->type2.data);
|
||||
}
|
||||
}
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
else if (ADC_CONV_MODE == ADC_CONV_SINGLE_UNIT_2) {
|
||||
ESP_LOGI(TAG, "Unit: %d, Channel: %d, Value: %x", 2, p->type1.channel, p->type1.data);
|
||||
} else if (ADC_CONV_MODE == ADC_CONV_SINGLE_UNIT_1) {
|
||||
ESP_LOGI(TAG, "Unit: %d, Channel: %d, Value: %x", 1, p->type1.channel, p->type1.data);
|
||||
}
|
||||
#endif //#if CONFIG_IDF_TARGET_ESP32S2
|
||||
#endif
|
||||
}
|
||||
//See `note 1`
|
||||
vTaskDelay(1);
|
||||
} else if (ret == ESP_ERR_TIMEOUT) {
|
||||
/**
|
||||
* ``ESP_ERR_TIMEOUT``: If ADC conversion is not finished until Timeout, you'll get this return error.
|
||||
* Here we set Timeout ``portMAX_DELAY``, so you'll never reach this branch.
|
||||
*/
|
||||
ESP_LOGW(TAG, "No data, increase timeout or reduce conv_num_each_intr");
|
||||
vTaskDelay(1000);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
adc_digi_stop();
|
||||
ret = adc_digi_deinitialize();
|
||||
assert(ret == ESP_OK);
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
| Supported Targets | ESP32-C3 |
|
||||
| ----------------- | -------- |
|
||||
|
||||
# ADC DMA Example
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
This example shows how to use DMA-Read-APIs and Single-Read-APIs to read voltage from GPIO pins via ADC controller.
|
||||
|
||||
## How to use example
|
||||
|
||||
### Hardware Required
|
||||
|
||||
* A development board with ESP32C3 SoC
|
||||
* A USB cable for power supply and programming
|
||||
|
||||
For `single_read` (Single-Read-APIs example), we use `ADC1_CHANNEL_2`, `ADC1_CHANNEL_3`, `ADC1_CHANNEL_4`, `ADC2_CHANNEL_0`. Hence we need to connect voltage sources (0 ~ 3.3V) to GPIO2, GPIO3, GPIO4, GPIO5 respectively.
|
||||
|
||||
For `continuous_read` (DMA-Read-APIs example), we use `ADC1_CHANNEL_0`, `ADC1_CHANNEL_1` and `ADC2_CHANNEL_0`. Therefore, GPIO0, GPIO1 and GPIO5 should be connected to voltage sources (0 ~ 3.3V).
|
||||
|
||||
If other ADC units/channels are selected in your application, you need to change the GPIO pin (please refer to the `ESP32C3 Technical Reference Manual`).
|
||||
|
||||
### Configure the project
|
||||
|
||||
```
|
||||
idf.py menuconfig
|
||||
```
|
||||
|
||||
### Build and Flash
|
||||
|
||||
Build the project and flash it to the board, then run monitor tool to view serial output:
|
||||
|
||||
```
|
||||
idf.py -p PORT flash monitor
|
||||
```
|
||||
|
||||
(To exit the serial monitor, type ``Ctrl-]``.)
|
||||
|
||||
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
|
||||
|
||||
## Example Output
|
||||
|
||||
Running this example, you will see the following log output on the serial monitor:
|
||||
```
|
||||
I (322) ADC1_CH2: 7c8
|
||||
I (322) ADC1_CH3: 278
|
||||
I (322) ADC1_CH4: d4b
|
||||
I (322) ADC2_CH0: 48
|
||||
```
|
||||
```
|
||||
ADC1_CH0: 61b
|
||||
ADC1_CH1: 39b
|
||||
ADC2_CH0: 4b
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
* program upload failure
|
||||
|
||||
* Hardware connection is not correct: run `idf.py -p PORT monitor`, and reboot your board to see if there are any output logs.
|
||||
* The baud rate for downloading is too high: lower your baud rate in the `menuconfig` menu, and try again.
|
||||
|
||||
For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon.
|
@ -1,124 +0,0 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/adc.h"
|
||||
|
||||
#define TIMES 256
|
||||
|
||||
static void continuous_adc_init(uint16_t adc1_chan_mask, uint16_t adc2_chan_mask, adc_channel_t *channel, uint8_t channel_num)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
assert(ret == ESP_OK);
|
||||
|
||||
adc_digi_init_config_t adc_dma_config = {
|
||||
.max_store_buf_size = 1024,
|
||||
.conv_num_each_intr = 256,
|
||||
.adc1_chan_mask = adc1_chan_mask,
|
||||
.adc2_chan_mask = adc2_chan_mask,
|
||||
};
|
||||
ret = adc_digi_initialize(&adc_dma_config);
|
||||
assert(ret == ESP_OK);
|
||||
|
||||
adc_digi_pattern_table_t adc_pattern[10] = {0};
|
||||
|
||||
//Do not set the sampling frequency out of the range between `SOC_ADC_SAMPLE_FREQ_THRES_LOW` and `SOC_ADC_SAMPLE_FREQ_THRES_HIGH`
|
||||
adc_digi_config_t dig_cfg = {
|
||||
.conv_limit_en = 0,
|
||||
.conv_limit_num = 250,
|
||||
.sample_freq_hz = 620,
|
||||
};
|
||||
|
||||
dig_cfg.adc_pattern_len = channel_num;
|
||||
for (int i = 0; i < channel_num; i++) {
|
||||
uint8_t unit = ((channel[i] >> 3) & 0x1);
|
||||
uint8_t ch = channel[i] & 0x7;
|
||||
adc_pattern[i].atten = ADC_ATTEN_DB_0;
|
||||
adc_pattern[i].channel = ch;
|
||||
adc_pattern[i].unit = unit;
|
||||
}
|
||||
dig_cfg.adc_pattern = adc_pattern;
|
||||
ret = adc_digi_controller_config(&dig_cfg);
|
||||
assert(ret == ESP_OK);
|
||||
}
|
||||
|
||||
static bool check_valid_data(const adc_digi_output_data_t *data)
|
||||
{
|
||||
const unsigned int unit = data->type2.unit;
|
||||
if (unit > 2) return false;
|
||||
if (data->type2.channel >= SOC_ADC_CHANNEL_NUM(unit)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void continuous_read(void *arg)
|
||||
{
|
||||
esp_err_t ret;
|
||||
uint32_t ret_num = 0;
|
||||
uint8_t result[TIMES] = {0};
|
||||
memset(result, 0xcc, TIMES);
|
||||
|
||||
uint16_t adc1_chan_mask = BIT(0) | BIT(1);
|
||||
uint16_t adc2_chan_mask = BIT(0);
|
||||
adc_channel_t channel[3] = {ADC1_CHANNEL_0, ADC1_CHANNEL_1, (ADC2_CHANNEL_0 | 1 << 3)};
|
||||
|
||||
continuous_adc_init(adc1_chan_mask, adc2_chan_mask, channel, sizeof(channel) / sizeof(adc_channel_t));
|
||||
adc_digi_start();
|
||||
|
||||
int n = 20;
|
||||
while(n--) {
|
||||
ret = adc_digi_read_bytes(result, TIMES, &ret_num, ADC_MAX_DELAY);
|
||||
for (int i = 0; i < ret_num; i+=4) {
|
||||
adc_digi_output_data_t *p = (void*)&result[i];
|
||||
if (check_valid_data(p)) {
|
||||
printf("ADC%d_CH%d: %x\n", p->type2.unit+1, p->type2.channel, p->type2.data);
|
||||
} else {
|
||||
printf("Invalid data [%d_%d_%x]\n", p->type2.unit+1, p->type2.channel, p->type2.data);
|
||||
}
|
||||
}
|
||||
// If you see task WDT in this task, it means the conversion is too fast for the task to handle
|
||||
}
|
||||
|
||||
adc_digi_stop();
|
||||
ret = adc_digi_deinitialize();
|
||||
assert(ret == ESP_OK);
|
||||
}
|
||||
|
||||
static void single_read(void *arg)
|
||||
{
|
||||
esp_err_t ret;
|
||||
int adc1_reading[3] = {0xcc};
|
||||
int adc2_reading[1] = {0xcc};
|
||||
|
||||
const char TAG_CH[][10] = {"ADC1_CH2", "ADC1_CH3","ADC1_CH4", "ADC2_CH0"};
|
||||
|
||||
adc1_config_width(ADC_WIDTH_BIT_DEFAULT);
|
||||
adc1_config_channel_atten(ADC1_CHANNEL_2, ADC_ATTEN_DB_0);
|
||||
adc1_config_channel_atten(ADC1_CHANNEL_3, ADC_ATTEN_DB_6);
|
||||
adc1_config_channel_atten(ADC1_CHANNEL_4, ADC_ATTEN_DB_0);
|
||||
adc2_config_channel_atten(ADC2_CHANNEL_0, ADC_ATTEN_DB_0);
|
||||
|
||||
int n = 20;
|
||||
while (n--) {
|
||||
|
||||
adc1_reading[0] = adc1_get_raw(ADC1_CHANNEL_2);
|
||||
adc1_reading[1] = adc1_get_raw(ADC1_CHANNEL_3);
|
||||
adc1_reading[2] = adc1_get_raw(ADC1_CHANNEL_4);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ESP_LOGI(TAG_CH[i], "%x", adc1_reading[i]);
|
||||
}
|
||||
|
||||
ret = adc2_get_raw(ADC2_CHANNEL_0, ADC_WIDTH_BIT_12, &adc2_reading[0]);
|
||||
assert(ret == ESP_OK);
|
||||
ESP_LOGI(TAG_CH[3], "%x", adc2_reading[0]);
|
||||
}
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
single_read(NULL);
|
||||
continuous_read(NULL);
|
||||
}
|
@ -1,3 +1,9 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* ADC1 Example
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
@ -11,7 +17,7 @@
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/adc_common.h"
|
||||
#include "driver/adc.h"
|
||||
#include "esp_adc_cal.h"
|
||||
|
||||
|
||||
|
@ -759,7 +759,6 @@ components/esp_serial_slave_link/include/esp_serial_slave_link/essl.h
|
||||
components/esp_serial_slave_link/include/esp_serial_slave_link/essl_sdio.h
|
||||
components/esp_serial_slave_link/include/esp_serial_slave_link/essl_spi.h
|
||||
components/esp_serial_slave_link/include/essl_spi/esp32c3_defs.h
|
||||
components/esp_serial_slave_link/include/essl_spi/esp32h2_defs.h
|
||||
components/esp_serial_slave_link/include/essl_spi/esp32s2_defs.h
|
||||
components/esp_serial_slave_link/include/essl_spi/esp32s3_defs.h
|
||||
components/esp_system/eh_frame_parser.c
|
||||
@ -973,12 +972,9 @@ components/hal/aes_hal.c
|
||||
components/hal/cpu_hal.c
|
||||
components/hal/dac_hal.c
|
||||
components/hal/ds_hal.c
|
||||
components/hal/esp32/adc_hal.c
|
||||
components/hal/esp32/brownout_hal.c
|
||||
components/hal/esp32/gpio_hal_workaround.c
|
||||
components/hal/esp32/include/hal/adc_hal.h
|
||||
components/hal/esp32/include/hal/adc_hal_conf.h
|
||||
components/hal/esp32/include/hal/adc_ll.h
|
||||
components/hal/esp32/include/hal/aes_ll.h
|
||||
components/hal/esp32/include/hal/can_hal.h
|
||||
components/hal/esp32/include/hal/can_ll.h
|
||||
@ -1009,12 +1005,9 @@ components/hal/esp32/include/hal/twai_ll.h
|
||||
components/hal/esp32/include/hal/uart_ll.h
|
||||
components/hal/esp32/interrupt_descriptor_table.c
|
||||
components/hal/esp32/touch_sensor_hal.c
|
||||
components/hal/esp32c3/adc_hal.c
|
||||
components/hal/esp32c3/brownout_hal.c
|
||||
components/hal/esp32c3/hmac_hal.c
|
||||
components/hal/esp32c3/include/hal/adc_hal.h
|
||||
components/hal/esp32c3/include/hal/adc_hal_conf.h
|
||||
components/hal/esp32c3/include/hal/adc_ll.h
|
||||
components/hal/esp32c3/include/hal/aes_ll.h
|
||||
components/hal/esp32c3/include/hal/clk_gate_ll.h
|
||||
components/hal/esp32c3/include/hal/ds_ll.h
|
||||
@ -1040,12 +1033,9 @@ components/hal/esp32c3/include/hal/uart_ll.h
|
||||
components/hal/esp32c3/include/hal/uhci_ll.h
|
||||
components/hal/esp32c3/include/hal/usb_serial_jtag_ll.h
|
||||
components/hal/esp32c3/rtc_cntl_hal.c
|
||||
components/hal/esp32h2/adc_hal.c
|
||||
components/hal/esp32h2/brownout_hal.c
|
||||
components/hal/esp32h2/hmac_hal.c
|
||||
components/hal/esp32h2/include/hal/adc_hal.h
|
||||
components/hal/esp32h2/include/hal/adc_hal_conf.h
|
||||
components/hal/esp32h2/include/hal/adc_ll.h
|
||||
components/hal/esp32h2/include/hal/aes_ll.h
|
||||
components/hal/esp32h2/include/hal/clk_gate_ll.h
|
||||
components/hal/esp32h2/include/hal/ds_ll.h
|
||||
@ -1068,13 +1058,9 @@ components/hal/esp32h2/include/hal/uhci_ll.h
|
||||
components/hal/esp32h2/include/hal/uhci_types.h
|
||||
components/hal/esp32h2/include/hal/usb_serial_jtag_ll.h
|
||||
components/hal/esp32h2/rtc_cntl_hal.c
|
||||
components/hal/esp32s2/adc_hal.c
|
||||
components/hal/esp32s2/brownout_hal.c
|
||||
components/hal/esp32s2/cp_dma_hal.c
|
||||
components/hal/esp32s2/dac_hal.c
|
||||
components/hal/esp32s2/include/hal/adc_hal.h
|
||||
components/hal/esp32s2/include/hal/adc_hal_conf.h
|
||||
components/hal/esp32s2/include/hal/adc_ll.h
|
||||
components/hal/esp32s2/include/hal/aes_ll.h
|
||||
components/hal/esp32s2/include/hal/clk_gate_ll.h
|
||||
components/hal/esp32s2/include/hal/cp_dma_hal.h
|
||||
@ -1100,7 +1086,6 @@ components/hal/esp32s2/include/hal/sigmadelta_ll.h
|
||||
components/hal/esp32s2/include/hal/soc_ll.h
|
||||
components/hal/esp32s2/include/hal/spi_flash_encrypted_ll.h
|
||||
components/hal/esp32s2/include/hal/spi_flash_ll.h
|
||||
components/hal/esp32s2/include/hal/spi_ll.h
|
||||
components/hal/esp32s2/include/hal/spimem_flash_ll.h
|
||||
components/hal/esp32s2/include/hal/systimer_ll.h
|
||||
components/hal/esp32s2/include/hal/touch_sensor_hal.h
|
||||
@ -1113,7 +1098,6 @@ components/hal/esp32s2/interrupt_descriptor_table.c
|
||||
components/hal/esp32s2/touch_sensor_hal.c
|
||||
components/hal/esp32s3/brownout_hal.c
|
||||
components/hal/esp32s3/include/hal/adc_hal_conf.h
|
||||
components/hal/esp32s3/include/hal/adc_ll.h
|
||||
components/hal/esp32s3/include/hal/aes_ll.h
|
||||
components/hal/esp32s3/include/hal/cpu_ll.h
|
||||
components/hal/esp32s3/include/hal/gpspi_flash_ll.h
|
||||
@ -1141,7 +1125,6 @@ components/hal/esp32s3/interrupt_descriptor_table.c
|
||||
components/hal/gpio_hal.c
|
||||
components/hal/i2c_hal.c
|
||||
components/hal/i2c_hal_iram.c
|
||||
components/hal/include/hal/adc_hal.h
|
||||
components/hal/include/hal/aes_hal.h
|
||||
components/hal/include/hal/aes_types.h
|
||||
components/hal/include/hal/brownout_hal.h
|
||||
@ -1649,7 +1632,6 @@ components/soc/esp32/include/soc/mmu.h
|
||||
components/soc/esp32/include/soc/nrx_reg.h
|
||||
components/soc/esp32/include/soc/pcnt_reg.h
|
||||
components/soc/esp32/include/soc/pcnt_struct.h
|
||||
components/soc/esp32/include/soc/periph_defs.h
|
||||
components/soc/esp32/include/soc/pid.h
|
||||
components/soc/esp32/include/soc/reset_reasons.h
|
||||
components/soc/esp32/include/soc/rmt_reg.h
|
||||
@ -1744,7 +1726,6 @@ components/soc/esp32c3/include/soc/rtc_i2c_reg.h
|
||||
components/soc/esp32c3/include/soc/rtc_i2c_struct.h
|
||||
components/soc/esp32c3/include/soc/sensitive_reg.h
|
||||
components/soc/esp32c3/include/soc/sensitive_struct.h
|
||||
components/soc/esp32c3/include/soc/soc_caps.h
|
||||
components/soc/esp32c3/include/soc/soc_pins.h
|
||||
components/soc/esp32c3/include/soc/spi_mem_reg.h
|
||||
components/soc/esp32c3/include/soc/spi_mem_struct.h
|
||||
@ -1875,7 +1856,6 @@ components/soc/esp32s2/include/soc/mmu.h
|
||||
components/soc/esp32s2/include/soc/nrx_reg.h
|
||||
components/soc/esp32s2/include/soc/pcnt_reg.h
|
||||
components/soc/esp32s2/include/soc/pcnt_struct.h
|
||||
components/soc/esp32s2/include/soc/periph_defs.h
|
||||
components/soc/esp32s2/include/soc/reset_reasons.h
|
||||
components/soc/esp32s2/include/soc/rmt_reg.h
|
||||
components/soc/esp32s2/include/soc/rmt_struct.h
|
||||
@ -1940,7 +1920,6 @@ components/soc/esp32s3/include/soc/adc_channel.h
|
||||
components/soc/esp32s3/include/soc/apb_ctrl_reg.h
|
||||
components/soc/esp32s3/include/soc/apb_ctrl_struct.h
|
||||
components/soc/esp32s3/include/soc/apb_saradc_reg.h
|
||||
components/soc/esp32s3/include/soc/apb_saradc_struct.h
|
||||
components/soc/esp32s3/include/soc/assist_debug_reg.h
|
||||
components/soc/esp32s3/include/soc/assist_debug_struct.h
|
||||
components/soc/esp32s3/include/soc/bb_reg.h
|
||||
@ -1986,7 +1965,6 @@ components/soc/esp32s3/include/soc/pcnt_reg.h
|
||||
components/soc/esp32s3/include/soc/pcnt_struct.h
|
||||
components/soc/esp32s3/include/soc/peri_backup_reg.h
|
||||
components/soc/esp32s3/include/soc/peri_backup_struct.h
|
||||
components/soc/esp32s3/include/soc/periph_defs.h
|
||||
components/soc/esp32s3/include/soc/reset_reasons.h
|
||||
components/soc/esp32s3/include/soc/rmt_reg.h
|
||||
components/soc/esp32s3/include/soc/rmt_struct.h
|
||||
@ -2721,10 +2699,8 @@ examples/network/simple_sniffer/components/pcap/pcap.h
|
||||
examples/network/simple_sniffer/main/cmd_sniffer.c
|
||||
examples/network/simple_sniffer/main/cmd_sniffer.h
|
||||
examples/network/simple_sniffer/main/simple_sniffer_example_main.c
|
||||
examples/peripherals/adc/esp32c3/adc/main/adc_dma_example_main.c
|
||||
examples/peripherals/adc/single_read/adc/main/adc1_example_main.c
|
||||
examples/peripherals/adc/single_read/adc2/main/adc2_example_main.c
|
||||
examples/peripherals/adc/single_read/single_read/main/single_read.c
|
||||
examples/peripherals/gpio/generic_gpio/example_test.py
|
||||
examples/peripherals/gpio/generic_gpio/main/gpio_example_main.c
|
||||
examples/peripherals/gpio/matrix_keyboard/components/matrix_keyboard/include/matrix_keyboard.h
|
||||
|
Loading…
Reference in New Issue
Block a user