Merge branch 'feature/adc_filter' into 'master'

adc: supported adc digital filter

Closes IDF-2529, IDFGH-9113, and IDFGH-9279

See merge request espressif/esp-idf!22035
This commit is contained in:
Armando (Dou Yiwen)
2023-02-13 16:43:58 +08:00
41 changed files with 1056 additions and 402 deletions

View File

@@ -17,6 +17,10 @@ if(CONFIG_SOC_ADC_DMA_SUPPORTED)
list(APPEND srcs "adc_continuous.c")
endif()
if(CONFIG_SOC_ADC_DIG_IIR_FILTER_SUPPORTED)
list(APPEND srcs "adc_filter.c")
endif()
# line fitting scheme
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${target}/adc_cali_line_fitting.c")
list(APPEND srcs "${target}/adc_cali_line_fitting.c")

View File

@@ -28,6 +28,7 @@
#include "hal/adc_hal.h"
#include "hal/dma_types.h"
#include "esp_memory_utils.h"
#include "adc_continuous_internal.h"
//For DMA
#if SOC_GDMA_SUPPORTED
#include "esp_private/gdma.h"
@@ -51,40 +52,6 @@ extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate posi
#define INTERNAL_BUF_NUM 5
typedef enum {
ADC_FSM_INIT,
ADC_FSM_STARTED,
} adc_fsm_t;
/*---------------------------------------------------------------
Continuous Mode Driverr Context
---------------------------------------------------------------*/
typedef struct adc_continuous_ctx_t {
uint8_t *rx_dma_buf; //dma buffer
adc_hal_dma_ctx_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
#elif CONFIG_IDF_TARGET_ESP32
i2s_port_t i2s_host; //ADC uses this I2S DMA
#endif
intr_handle_t dma_intr_hdl; //DMA Interrupt handler
RingbufHandle_t ringbuf_hdl; //RX ringbuffer handler
void* ringbuf_storage; //Ringbuffer storage buffer
void* ringbuf_struct; //Ringbuffer structure buffer
intptr_t rx_eof_desc_addr; //eof descriptor address of RX channel
adc_fsm_t fsm; //ADC continuous mode driver internal states
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
adc_continuous_evt_cbs_t cbs; //Callbacks
void *user_data; //User context
esp_pm_lock_handle_t pm_lock; //For power management
} adc_continuous_ctx_t;
#ifdef CONFIG_PM_ENABLE
//Only for deprecated API
extern esp_pm_lock_handle_t adc_digi_arbiter_lock;

View File

@@ -0,0 +1,87 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "sdkconfig.h"
#include "esp_pm.h"
#include "freertos/FreeRTOS.h"
#include "freertos/ringbuf.h"
#include "hal/adc_types.h"
#include "hal/adc_hal.h"
//For DMA
#if SOC_GDMA_SUPPORTED
#include "esp_private/gdma.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "hal/spi_types.h"
#elif CONFIG_IDF_TARGET_ESP32
#include "driver/i2s_types.h"
#endif
#include "esp_adc/adc_filter.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
ADC_FSM_INIT,
ADC_FSM_STARTED,
} adc_fsm_t;
/*---------------------------------------------------------------
Driver Context
---------------------------------------------------------------*/
typedef struct adc_iir_filter_t adc_iir_filter_t;
typedef struct adc_continuous_ctx_t adc_continuous_ctx_t;
/**
* @brief ADC iir filter context
*/
struct adc_iir_filter_t {
adc_digi_iir_filter_t filter_id; // Filter ID
adc_continuous_iir_filter_config_t cfg; //filter configuration
adc_continuous_ctx_t *continuous_ctx; //ADC continuous driver context
};
/**
* @brief ADC continuous driver context
*/
struct adc_continuous_ctx_t {
uint8_t *rx_dma_buf; //dma buffer
adc_hal_dma_ctx_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
#elif CONFIG_IDF_TARGET_ESP32
i2s_port_t i2s_host; //ADC uses this I2S DMA
#endif
intr_handle_t dma_intr_hdl; //DMA Interrupt handler
RingbufHandle_t ringbuf_hdl; //RX ringbuffer handler
void* ringbuf_storage; //Ringbuffer storage buffer
void* ringbuf_struct; //Ringbuffer structure buffer
intptr_t rx_eof_desc_addr; //eof descriptor address of RX channel
adc_fsm_t fsm; //ADC continuous mode driver internal states
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
adc_continuous_evt_cbs_t cbs; //Callbacks
void *user_data; //User context
esp_pm_lock_handle_t pm_lock; //For power management
#if SOC_ADC_DIG_IIR_FILTER_SUPPORTED
adc_iir_filter_t *iir_filter[SOC_ADC_DIGI_IIR_FILTER_NUM]; //ADC IIR filter context
#endif
};
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,156 @@
/*
* SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdatomic.h>
#include "esp_types.h"
#include "sdkconfig.h"
#include "esp_log.h"
#include "esp_check.h"
#include "esp_heap_caps.h"
#include "freertos/FreeRTOS.h"
#include "hal/adc_types.h"
#include "hal/adc_hal.h"
#include "adc_continuous_internal.h"
#include "esp_adc/adc_filter.h"
static const char *TAG = "adc_filter";
static portMUX_TYPE s_filter_spinlock = portMUX_INITIALIZER_UNLOCKED;
#if SOC_ADC_DIG_IIR_FILTER_UNIT_BINDED
static atomic_bool s_adc_filter_claimed[SOC_ADC_PERIPH_NUM] = {ATOMIC_VAR_INIT(false),
#if (SOC_ADC_PERIPH_NUM >= 2)
ATOMIC_VAR_INIT(false)
#endif
};
static esp_err_t s_adc_filter_claim(adc_continuous_handle_t handle, adc_iir_filter_t *filter_ctx, adc_unit_t unit)
{
assert(handle && filter_ctx);
esp_err_t ret = ESP_ERR_NOT_FOUND;
bool false_var = false;
if (atomic_compare_exchange_strong(&s_adc_filter_claimed[unit], &false_var, true)) {
ret = ESP_OK;
filter_ctx->filter_id = unit;
handle->iir_filter[unit] = filter_ctx;
}
return ret;
}
static esp_err_t s_adc_filter_free(adc_iir_filter_t *filter_ctx)
{
assert(filter_ctx);
esp_err_t ret = ESP_ERR_NOT_FOUND;
bool true_var = true;
if (atomic_compare_exchange_strong(&s_adc_filter_claimed[filter_ctx->cfg.unit], &true_var, false)) {
ret = ESP_OK;
filter_ctx->continuous_ctx->iir_filter[filter_ctx->filter_id] = NULL;
}
return ret;
}
#else
static esp_err_t s_adc_filter_claim(adc_continuous_handle_t handle, adc_iir_filter_t *filter_ctx, adc_unit_t unit)
{
(void)unit;
assert(handle && filter_ctx);
for (int i = 0; i < SOC_ADC_DIGI_IIR_FILTER_NUM; i++) {
portENTER_CRITICAL(&s_filter_spinlock);
bool found = !handle->iir_filter[i];
handle->iir_filter[i] = filter_ctx;
filter_ctx->filter_id = i;
portEXIT_CRITICAL(&s_filter_spinlock);
if (found) {
return ESP_OK;
}
}
return ESP_ERR_NOT_FOUND;
}
static esp_err_t s_adc_filter_free(adc_iir_filter_t *filter_ctx)
{
assert(filter_ctx);
portENTER_CRITICAL(&s_filter_spinlock);
filter_ctx->continuous_ctx->iir_filter[filter_ctx->filter_id] = NULL;
portEXIT_CRITICAL(&s_filter_spinlock);
return ESP_OK;
}
#endif
esp_err_t adc_new_continuous_iir_filter(adc_continuous_handle_t handle, const adc_continuous_iir_filter_config_t *config, adc_iir_filter_handle_t *ret_hdl)
{
esp_err_t ret = ESP_FAIL;
ESP_RETURN_ON_FALSE(handle && config && ret_hdl, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
ESP_RETURN_ON_FALSE(handle->fsm == ADC_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "ADC continuous driver should be in init state");
ESP_RETURN_ON_FALSE(config->unit < SOC_ADC_PERIPH_NUM, ESP_ERR_INVALID_ARG, TAG, "invalid unit");
adc_iir_filter_t *filter_ctx = heap_caps_calloc(1, sizeof(adc_iir_filter_t), MALLOC_CAP_DEFAULT);
ESP_RETURN_ON_FALSE(filter_ctx, ESP_ERR_NO_MEM, TAG, "no mem");
//claim a filter
#if SOC_ADC_DIG_IIR_FILTER_UNIT_BINDED
ESP_GOTO_ON_ERROR(s_adc_filter_claim(handle, filter_ctx, config->unit), err, TAG, "filter already in use");
#else
ESP_GOTO_ON_ERROR(s_adc_filter_claim(handle, filter_ctx, config->unit), err, TAG, "no free filter");
#endif
filter_ctx->cfg.unit = config->unit;
filter_ctx->cfg.channel = config->channel;
filter_ctx->cfg.coeff = config->coeff;
filter_ctx->continuous_ctx = handle;
*ret_hdl = filter_ctx;
return ESP_OK;
err:
free(filter_ctx);
return ret;
}
esp_err_t adc_continuous_iir_filter_enable(adc_iir_filter_handle_t filter_hdl)
{
ESP_RETURN_ON_FALSE(filter_hdl, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
ESP_RETURN_ON_FALSE(filter_hdl->continuous_ctx->fsm == ADC_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "ADC continuous driver should be in init state");
portENTER_CRITICAL(&s_filter_spinlock);
adc_ll_digi_filter_reset(filter_hdl->filter_id, filter_hdl->cfg.unit);
adc_ll_digi_filter_set_factor(filter_hdl->filter_id, filter_hdl->cfg.unit, filter_hdl->cfg.channel, filter_hdl->cfg.coeff);
adc_ll_digi_filter_enable(filter_hdl->filter_id, filter_hdl->cfg.unit, true);
portEXIT_CRITICAL(&s_filter_spinlock);
return ESP_OK;
}
esp_err_t adc_continuous_iir_filter_disable(adc_iir_filter_handle_t filter_hdl)
{
ESP_RETURN_ON_FALSE(filter_hdl, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
ESP_RETURN_ON_FALSE(filter_hdl->continuous_ctx->fsm == ADC_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "ADC continuous driver should be in init state");
portENTER_CRITICAL(&s_filter_spinlock);
adc_ll_digi_filter_enable(filter_hdl->filter_id, filter_hdl->cfg.unit, false);
portEXIT_CRITICAL(&s_filter_spinlock);
return ESP_OK;
}
esp_err_t adc_del_continuous_iir_filter(adc_iir_filter_handle_t filter_hdl)
{
ESP_RETURN_ON_FALSE(filter_hdl, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
ESP_RETURN_ON_FALSE(filter_hdl->continuous_ctx->fsm == ADC_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "ADC continuous driver should be in init state");
ESP_RETURN_ON_ERROR(s_adc_filter_free(filter_hdl), TAG, "filter isn't in use");
free(filter_hdl);
return ESP_OK;
}

View File

@@ -16,7 +16,6 @@
extern "C" {
#endif
#if SOC_ADC_DMA_SUPPORTED
/**
* @brief Driver Backgrounds
@@ -130,7 +129,7 @@ esp_err_t adc_continuous_config(adc_continuous_handle_t handle, const adc_contin
/**
* @brief Register callbacks
*
* @note User can deregister a previously registered callback by calling this function and setting the to-be-deregistered callback member int
* @note User can deregister a previously registered callback by calling this function and setting the to-be-deregistered callback member in
* the `cbs` structure to NULL.
* @note When CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE is enabled, the callback itself and functions called by it should be placed in IRAM.
* Involved variables (including `user_data`) should be in internal RAM as well.
@@ -224,8 +223,6 @@ esp_err_t adc_continuous_io_to_channel(int io_num, adc_unit_t *unit_id, adc_chan
*/
esp_err_t adc_continuous_channel_to_io(adc_unit_t unit_id, adc_channel_t channel, int *io_num);
#endif // #if SOC_ADC_DMA_SUPPORTED
#ifdef __cplusplus
}

View File

@@ -0,0 +1,88 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include "sdkconfig.h"
#include "esp_err.h"
#include "esp_adc/adc_continuous.h"
#include "hal/adc_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Type of adc iir filter handle
*/
typedef struct adc_iir_filter_t *adc_iir_filter_handle_t;
/**
* @brief Filter Configuration
*/
typedef struct {
adc_unit_t unit; ///< ADC unit
adc_channel_t channel; ///< An ADC channel to be filtered. Note for ESP32S2, you should only set only one channel in pattern table, per ADC unit. See programming guide for more details.
adc_digi_iir_filter_coeff_t coeff; ///< ADC filter coefficient
} adc_continuous_iir_filter_config_t;
/**
* @brief New an ADC continuous mode IIR filter
*
* @param[in] handle ADC continuous mode driver handle
* @param[in] config Filter configuration
* @param[out] ret_hdl Returned IIR filter handle
*
* @return
* - ESP_OK
* - ESP_ERR_INVALID_ARG: Invalid argument
* - ESP_ERR_INVALID_STATE: Invalid state
* - ESP_ERR_NO_MEM: No memory
*/
esp_err_t adc_new_continuous_iir_filter(adc_continuous_handle_t handle, const adc_continuous_iir_filter_config_t *config, adc_iir_filter_handle_t *ret_hdl);
/**
* @brief Enable an IIR filter
*
* @param[in] filter_hdl ADC IIR filter handle
*
* @return
* - ESP_OK
* - ESP_ERR_INVALID_ARG: Invalid argument
* - ESP_ERR_INVALID_STATE: Invalid state
*/
esp_err_t adc_continuous_iir_filter_enable(adc_iir_filter_handle_t filter_hdl);
/**
* @brief Disable an IIR filter
*
* @param[in] filter_hdl ADC IIR filter handle
*
* @return
* - ESP_OK
* - ESP_ERR_INVALID_ARG: Invalid argument
* - ESP_ERR_INVALID_STATE: Invalid state
*/
esp_err_t adc_continuous_iir_filter_disable(adc_iir_filter_handle_t filter_hdl);
/**
* @brief Delete the IIR filter
*
* @param[in] filter_hdl ADC IIR filter handle
*
* @return
* - ESP_OK
* - ESP_ERR_INVALID_ARG: Invalid argument
* - ESP_ERR_INVALID_STATE: Invalid state
*/
esp_err_t adc_del_continuous_iir_filter(adc_iir_filter_handle_t filter_hdl);
#ifdef __cplusplus
}
#endif

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -156,7 +156,7 @@ TEST_CASE("ADC oneshot fast work with ISR and Flash", "[adc_oneshot]")
#endif
#define ADC_TEST_FREQ_HZ (50 * 1000)
#define ADC_TEST_PKG_SIZE 100
#define ADC_TEST_PKG_SIZE 512
static bool IRAM_ATTR NOINLINE_ATTR s_conv_done_cb(adc_continuous_handle_t handle, const adc_continuous_evt_data_t *edata, void *user_data)
{
test_adc_iram_ctx_t *test_ctx = (test_adc_iram_ctx_t *)user_data;

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -15,19 +15,21 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_adc/adc_oneshot.h"
#include "esp_adc/adc_continuous.h"
#include "esp_adc/adc_filter.h"
#include "test_common_adc.h"
#if CONFIG_IDF_TARGET_ESP32 || SOC_ADC_CALIBRATION_V1_SUPPORTED
#include "idf_performance.h"
__attribute__((unused)) static const char *TAG = "TEST_ADC";
/*---------------------------------------------------------------
ADC Oneshot Average / STD_Deviation Test
---------------------------------------------------------------*/
#define TEST_COUNT (1<<SOC_ADC_RTC_MAX_BITWIDTH)
#define MAX_ARRAY_SIZE (1<<SOC_ADC_RTC_MAX_BITWIDTH)
#if CONFIG_IDF_TARGET_ESP32
#define TEST_STD_ADC1_CHANNEL0 ADC_CHANNEL_5
#else
#define TEST_STD_ADC1_CHANNEL0 ADC_CHANNEL_2
#endif
static int s_adc_count[MAX_ARRAY_SIZE]={};
static int s_adc_count_size;
static int *s_p_adc_count;
static int s_adc_offset = -1;
static int s_insert_point(uint32_t value)
@@ -36,40 +38,50 @@ static int s_insert_point(uint32_t value)
if (s_adc_offset < 0) {
if (fixed_size) {
TEST_ASSERT_GREATER_OR_EQUAL(4096, MAX_ARRAY_SIZE);
TEST_ASSERT_GREATER_OR_EQUAL(4096, s_adc_count_size);
s_adc_offset = 0; //Fixed to 0 because the array can hold all the data in 12 bits
} else {
s_adc_offset = MAX((int)value - MAX_ARRAY_SIZE/2, 0);
s_adc_offset = MAX((int)value - s_adc_count_size/2, 0);
}
}
if (!fixed_size && (value < s_adc_offset || value >= s_adc_offset + MAX_ARRAY_SIZE)) {
if (!fixed_size && (value < s_adc_offset || value >= s_adc_offset + s_adc_count_size)) {
TEST_ASSERT_GREATER_OR_EQUAL(s_adc_offset, value);
TEST_ASSERT_LESS_THAN(s_adc_offset + MAX_ARRAY_SIZE, value);
TEST_ASSERT_LESS_THAN(s_adc_offset + s_adc_count_size, value);
}
s_adc_count[value - s_adc_offset] ++;
s_p_adc_count[value - s_adc_offset] ++;
return value - s_adc_offset;
}
static void s_reset_array(void)
static void s_reset_array(int array_size)
{
memset(s_adc_count, 0, sizeof(s_adc_count));
s_adc_count_size = array_size;
s_p_adc_count = (int *)heap_caps_calloc(1, s_adc_count_size * sizeof(int), MALLOC_CAP_INTERNAL);
TEST_ASSERT(s_p_adc_count);
s_adc_offset = -1;
}
static void s_destroy_array(void)
{
free(s_p_adc_count);
s_p_adc_count = NULL;
s_adc_count_size = 0;
}
__attribute__((unused))
static uint32_t s_get_average(void)
{
uint32_t sum = 0;
int count = 0;
for (int i = 0; i < MAX_ARRAY_SIZE; i++) {
sum += s_adc_count[i] * (s_adc_offset+i);
count += s_adc_count[i];
for (int i = 0; i < s_adc_count_size; i++) {
sum += s_p_adc_count[i] * (s_adc_offset+i);
count += s_p_adc_count[i];
}
return sum/count;
}
static void s_print_summary(bool figure)
static float s_print_summary(bool figure)
{
const int MAX_WIDTH=20;
int max_count = 0;
@@ -77,53 +89,220 @@ static void s_print_summary(bool figure)
int end = -1;
uint32_t sum = 0;
int count = 0;
for (int i = 0; i < MAX_ARRAY_SIZE; i++) {
if (s_adc_count[i] > max_count) {
max_count = s_adc_count[i];
for (int i = 0; i < s_adc_count_size; i++) {
if (s_p_adc_count[i] > max_count) {
max_count = s_p_adc_count[i];
}
if (s_adc_count[i] > 0 && start < 0) {
if (s_p_adc_count[i] > 0 && start < 0) {
start = i;
}
if (s_adc_count[i] > 0) {
if (s_p_adc_count[i] > 0) {
end = i;
}
count += s_adc_count[i];
sum += s_adc_count[i] * (s_adc_offset+i);
count += s_p_adc_count[i];
sum += s_p_adc_count[i] * (s_adc_offset+i);
}
if (figure) {
for (int i = start; i <= end; i++) {
printf("%4d ", i+s_adc_offset);
int count = s_adc_count[i] * MAX_WIDTH / max_count;
int count = s_p_adc_count[i] * MAX_WIDTH / max_count;
for (int j = 0; j < count; j++) {
putchar('|');
}
printf(" %d\n", s_adc_count[i]);
printf(" %d\n", s_p_adc_count[i]);
}
}
float average = (float)sum/count;
float variation_square = 0;
for (int i = start; i <= end; i ++) {
if (s_adc_count[i] == 0) {
if (s_p_adc_count[i] == 0) {
continue;
}
float delta = i + s_adc_offset - average;
variation_square += (delta * delta) * s_adc_count[i];
variation_square += (delta * delta) * s_p_adc_count[i];
}
printf("%d points.\n", count);
printf("average: %.1f\n", (float)sum/count);
printf("std: %.2f\n", sqrt(variation_square/count));
return sqrt(variation_square/count);
}
#if CONFIG_IDF_TARGET_ESP32
#define TEST_STD_ADC1_CHANNEL0 ADC_CHANNEL_6
#if SOC_ADC_DMA_SUPPORTED
/*---------------------------------------------------------------
ADC Continuous Average / STD_Deviation Test
---------------------------------------------------------------*/
#if (SOC_ADC_DIGI_RESULT_BYTES == 2)
#define ADC_TEST_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE1
#define EXAMPLE_ADC_GET_CHANNEL(result) ((result).type1.channel)
#define EXAMPLE_ADC_GET_DATA(result) ((result).type1.data)
#else
#define TEST_STD_ADC1_CHANNEL0 ADC_CHANNEL_2
#define ADC_TEST_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE2
#define EXAMPLE_ADC_GET_CHANNEL(result) ((result).type2.channel)
#define EXAMPLE_ADC_GET_DATA(result) ((result).type2.data)
#endif
#define ADC_TEST_FREQ_HZ (50 * 1000)
#define ADC_TEST_PKG_SIZE 512
#define ADC_TEST_CNT 4096
static bool IRAM_ATTR s_conv_done_cb(adc_continuous_handle_t handle, const adc_continuous_evt_data_t *edata, void *user_data)
{
BaseType_t mustYield = pdFALSE;
TaskHandle_t task_handle = *(TaskHandle_t *)(user_data);
//Notify that ADC continuous driver has done enough number of conversions
vTaskNotifyGiveFromISR(task_handle, &mustYield);
return (mustYield == pdTRUE);
}
static float test_adc_continuous_std(adc_atten_t atten, bool filter_en, int filter_coeff, bool is_performance_test)
{
uint8_t *result = heap_caps_calloc(1, ADC_TEST_CNT * SOC_ADC_DIGI_RESULT_BYTES, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT | MALLOC_CAP_32BIT);
TEST_ASSERT(result);
bool print_figure = false;
TaskHandle_t task_handle = xTaskGetCurrentTaskHandle();
//-------------ADC Init---------------//
adc_continuous_handle_t handle = NULL;
adc_continuous_handle_cfg_t adc_config = {
.max_store_buf_size = 4096,
.conv_frame_size = ADC_TEST_PKG_SIZE,
};
TEST_ESP_OK(adc_continuous_new_handle(&adc_config, &handle));
adc_continuous_evt_cbs_t cbs = {
.on_conv_done = s_conv_done_cb,
};
TEST_ESP_OK(adc_continuous_register_event_callbacks(handle, &cbs, &task_handle));
//-------------ADC Config---------------//
adc_continuous_config_t dig_cfg = {
.sample_freq_hz = ADC_TEST_FREQ_HZ,
.conv_mode = ADC_CONV_SINGLE_UNIT_1,
.format = ADC_TEST_OUTPUT_TYPE,
};
adc_digi_pattern_config_t adc_pattern[SOC_ADC_PATT_LEN_MAX] = {0};
adc_pattern[0].atten = atten;
adc_pattern[0].channel = TEST_STD_ADC1_CHANNEL0;
adc_pattern[0].unit = ADC_UNIT_1;
adc_pattern[0].bit_width = SOC_ADC_DIGI_MAX_BITWIDTH;
dig_cfg.adc_pattern = adc_pattern;
dig_cfg.pattern_num = 1;
TEST_ESP_OK(adc_continuous_config(handle, &dig_cfg));
#if SOC_ADC_DIG_IIR_FILTER_SUPPORTED
adc_iir_filter_handle_t filter_hdl = NULL;
if (filter_en) {
adc_continuous_iir_filter_config_t filter_config = {
.unit = ADC_UNIT_1,
.channel = TEST_STD_ADC1_CHANNEL0,
.coeff = filter_coeff,
};
TEST_ESP_OK(adc_new_continuous_iir_filter(handle, &filter_config, &filter_hdl));
TEST_ESP_OK(adc_continuous_iir_filter_enable(filter_hdl));
}
#endif
TEST_CASE("ADC1 oneshot raw average / std_deviation", "[adc_oneshot][ignore][manual]")
if (is_performance_test) {
test_adc_set_io_middle(ADC_UNIT_1, TEST_STD_ADC1_CHANNEL0);
}
if (filter_en) {
ESP_LOGI("TEST_ADC", "Test with atten: %d, filter coeff: %d", atten, filter_coeff);
} else {
ESP_LOGI("TEST_ADC", "Test with atten: %d, no filter", atten);
}
s_reset_array((1 << SOC_ADC_DIGI_MAX_BITWIDTH));
TEST_ESP_OK(adc_continuous_start(handle));
int remain_count = ADC_TEST_CNT;
while (remain_count) {
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
int already_got = ADC_TEST_CNT - remain_count;
uint32_t ret_num = 0;
TEST_ESP_OK(adc_continuous_read(handle, result + already_got * SOC_ADC_DIGI_RESULT_BYTES, ADC_TEST_PKG_SIZE, &ret_num, 0));
remain_count -= ret_num / SOC_ADC_DIGI_RESULT_BYTES;
}
adc_digi_output_data_t *p = (void*)result;
for (int i = 0; i < ADC_TEST_CNT; i++) {
TEST_ASSERT_EQUAL(TEST_STD_ADC1_CHANNEL0, EXAMPLE_ADC_GET_CHANNEL(p[i]));
s_insert_point(EXAMPLE_ADC_GET_DATA(p[i]));
}
float std = s_print_summary(print_figure);
TEST_ESP_OK(adc_continuous_stop(handle));
#if SOC_ADC_DIG_IIR_FILTER_SUPPORTED
if (filter_en) {
TEST_ESP_OK(adc_continuous_iir_filter_disable(filter_hdl));
TEST_ESP_OK(adc_del_continuous_iir_filter(filter_hdl));
}
#endif
TEST_ESP_OK(adc_continuous_deinit(handle));
ulTaskNotifyTake(pdTRUE, 0);
s_destroy_array();
free(result);
return std;
}
TEST_CASE("ADC1 continuous raw average and std_deviation", "[adc_continuous][manual]")
{
for (int i = 0; i < TEST_ATTEN_NUMS; i ++) {
#if SOC_ADC_DIG_IIR_FILTER_SUPPORTED
//filter disabled
test_adc_continuous_std(g_test_atten[i], false, 0, false);
//filter with different coeffs
for (int j = 0; j < TEST_FILTER_COEFF_NUMS; j ++) {
test_adc_continuous_std(g_test_atten[i], true, g_test_filter_coeff[j], false);
}
#else
//filter disabled
test_adc_continuous_std(g_test_atten[i], false, 0, false);
#endif
}
}
TEST_CASE("ADC1 continuous std deviation performance, no filter", "[adc_continuous][performance]")
{
float std = test_adc_continuous_std(ADC_ATTEN_DB_11, false, 0, true);
TEST_PERFORMANCE_LESS_THAN(ADC_CONTINUOUS_STD_ATTEN3_NO_FILTER, "%.2f", std);
}
#if SOC_ADC_DIG_IIR_FILTER_SUPPORTED
TEST_CASE("ADC1 continuous std deviation performance, with filter", "[adc_continuous][performance]")
{
float std = test_adc_continuous_std(ADC_ATTEN_DB_11, false, 0, true);
TEST_PERFORMANCE_LESS_THAN(ADC_CONTINUOUS_STD_ATTEN3_NO_FILTER, "%.2f", std);
std = test_adc_continuous_std(ADC_ATTEN_DB_11, true, ADC_DIGI_IIR_FILTER_COEFF_2, true);
TEST_PERFORMANCE_LESS_THAN(ADC_CONTINUOUS_STD_ATTEN3_FILTER_2, "%.2f", std);
std = test_adc_continuous_std(ADC_ATTEN_DB_11, true, ADC_DIGI_IIR_FILTER_COEFF_4, true);
TEST_PERFORMANCE_LESS_THAN(ADC_CONTINUOUS_STD_ATTEN3_FILTER_4, "%.2f", std);
std = test_adc_continuous_std(ADC_ATTEN_DB_11, true, ADC_DIGI_IIR_FILTER_COEFF_8, true);
TEST_PERFORMANCE_LESS_THAN(ADC_CONTINUOUS_STD_ATTEN3_FILTER_8, "%.2f", std);
std = test_adc_continuous_std(ADC_ATTEN_DB_11, true, ADC_DIGI_IIR_FILTER_COEFF_16, true);
TEST_PERFORMANCE_LESS_THAN(ADC_CONTINUOUS_STD_ATTEN3_FILTER_16, "%.2f", std);
std = test_adc_continuous_std(ADC_ATTEN_DB_11, true, ADC_DIGI_IIR_FILTER_COEFF_64, true);
TEST_PERFORMANCE_LESS_THAN(ADC_CONTINUOUS_STD_ATTEN3_FILTER_64, "%.2f", std);
}
#endif //#if SOC_ADC_DIG_IIR_FILTER_SUPPORTED
#endif //#if SOC_ADC_DMA_SUPPORTED
#if CONFIG_IDF_TARGET_ESP32 || SOC_ADC_CALIBRATION_V1_SUPPORTED
/*---------------------------------------------------------------
ADC Oneshot Average / STD_Deviation Test
---------------------------------------------------------------*/
static float test_adc_oneshot_std(adc_atten_t atten, bool is_performance_test)
{
adc_channel_t channel = TEST_STD_ADC1_CHANNEL0;
int raw = 0;
@@ -144,50 +323,62 @@ TEST_CASE("ADC1 oneshot raw average / std_deviation", "[adc_oneshot][ignore][man
//-------------ADC Calibration Init---------------//
bool do_calibration = false;
adc_cali_handle_t cali_handle[TEST_ATTEN_NUMS] = {};
for (int i = 0; i < TEST_ATTEN_NUMS; i++) {
do_calibration = test_adc_calibration_init(ADC_UNIT_1, g_test_atten[i], ADC_BITWIDTH_DEFAULT, &cali_handle[i]);
}
adc_cali_handle_t cali_handle = NULL;
do_calibration = test_adc_calibration_init(ADC_UNIT_1, atten, ADC_BITWIDTH_DEFAULT, &cali_handle);
if (!do_calibration) {
ESP_LOGW(TAG, "calibration fail, jump calibration\n");
}
for (int i = 0; i < TEST_ATTEN_NUMS; i++) {
//-------------ADC1 Channel Config---------------//
config.atten = atten;
TEST_ESP_OK(adc_oneshot_config_channel(adc1_handle, channel, &config));
ESP_LOGI("TEST_ADC", "Test with atten: %d", atten);
//-------------ADC1 Channel Config---------------//
config.atten = g_test_atten[i];
TEST_ESP_OK(adc_oneshot_config_channel(adc1_handle, channel, &config));
ESP_LOGI("TEST_ADC", "Test with atten: %d", g_test_atten[i]);
s_reset_array((1 << SOC_ADC_RTC_MAX_BITWIDTH));
while (1) {
s_reset_array();
for (int i = 0; i < TEST_COUNT; i++) {
TEST_ESP_OK(adc_oneshot_read(adc1_handle, channel, &raw));
s_insert_point(raw);
}
s_print_summary(print_figure);
break;
}
if (do_calibration) {
uint32_t raw = s_get_average();
int voltage_mv = 0;
TEST_ESP_OK(adc_cali_raw_to_voltage(cali_handle[i], raw, &voltage_mv));
printf("Voltage = %d mV\n", voltage_mv);
}
if (is_performance_test) {
test_adc_set_io_middle(ADC_UNIT_1, TEST_STD_ADC1_CHANNEL0);
}
TEST_ESP_OK(adc_oneshot_del_unit(adc1_handle));
for (int i = 0; i < TEST_ATTEN_NUMS; i++) {
if (cali_handle[i]) {
test_adc_calibration_deinit(cali_handle[i]);
float std;
while (1) {
for (int i = 0; i < s_adc_count_size; i++) {
TEST_ESP_OK(adc_oneshot_read(adc1_handle, channel, &raw));
s_insert_point(raw);
}
std = s_print_summary(print_figure);
break;
}
if (do_calibration) {
uint32_t raw = s_get_average();
int voltage_mv = 0;
TEST_ESP_OK(adc_cali_raw_to_voltage(cali_handle, raw, &voltage_mv));
printf("Voltage = %d mV\n", voltage_mv);
}
s_destroy_array();
TEST_ESP_OK(adc_oneshot_del_unit(adc1_handle));
if (cali_handle) {
test_adc_calibration_deinit(cali_handle);
}
return std;
}
TEST_CASE("ADC1 oneshot raw average and std_deviation", "[adc_oneshot][manual]")
{
for (int i = 0; i < TEST_ATTEN_NUMS; i++) {
test_adc_oneshot_std(g_test_atten[i], false);
}
}
TEST_CASE("ADC1 oneshot std_deviation performance", "[adc_oneshot][performance]")
{
float std = test_adc_oneshot_std(ADC_ATTEN_DB_11, true);
TEST_PERFORMANCE_LESS_THAN(ADC_ONESHOT_STD_ATTEN3, "%.2f", std);
}
/*---------------------------------------------------------------
ADC Calibration Speed
---------------------------------------------------------------*/
@@ -277,14 +468,14 @@ static void s_adc_cali_speed(adc_unit_t unit_id, adc_channel_t channel)
}
}
TEST_CASE("ADC1 Calibration Speed", "[adc][ignore][manual]")
TEST_CASE("ADC1 Calibration Speed", "[adc][manual]")
{
s_adc_cali_speed(ADC_UNIT_1, ADC1_CALI_SPEED_TEST_CHAN0);
}
#if (SOC_ADC_PERIPH_NUM >= 2) && !CONFIG_IDF_TARGET_ESP32C3
//ESP32C3 ADC2 oneshot mode is not supported anymore
TEST_CASE("ADC2 Calibration Speed", "[adc][ignore][manual]")
TEST_CASE("ADC2 Calibration Speed", "[adc][manual]")
{
s_adc_cali_speed(ADC_UNIT_2, ADC2_CALI_SPEED_TEST_CHAN0);
}

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@@ -7,6 +7,8 @@
#include <stdlib.h>
#include "unity.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "driver/rtc_io.h"
#include "soc/adc_periph.h"
@@ -23,6 +25,16 @@ adc_atten_t g_test_atten[TEST_ATTEN_NUMS] = {ADC_ATTEN_DB_0, ADC_ATTEN_DB_11};
adc_atten_t g_test_atten[TEST_ATTEN_NUMS] = {ADC_ATTEN_DB_0, ADC_ATTEN_DB_2_5, ADC_ATTEN_DB_6, ADC_ATTEN_DB_11};
#endif
#if SOC_ADC_DIG_IIR_FILTER_SUPPORTED
adc_digi_iir_filter_coeff_t g_test_filter_coeff[TEST_FILTER_COEFF_NUMS] = {
ADC_DIGI_IIR_FILTER_COEFF_2,
ADC_DIGI_IIR_FILTER_COEFF_4,
ADC_DIGI_IIR_FILTER_COEFF_8,
ADC_DIGI_IIR_FILTER_COEFF_16,
ADC_DIGI_IIR_FILTER_COEFF_64,
};
#endif
/*---------------------------------------------------------------
ADC Calibration
@@ -102,3 +114,21 @@ void test_adc_set_io_level(adc_unit_t unit, adc_channel_t channel, bool level)
TEST_ESP_OK(gpio_set_pull_mode(io_num, (level ? GPIO_PULLUP_ONLY: GPIO_PULLDOWN_ONLY)));
#endif
}
void test_adc_set_io_middle(adc_unit_t unit, adc_channel_t channel)
{
TEST_ASSERT(channel < SOC_ADC_CHANNEL_NUM(unit) && "invalid channel");
uint32_t io_num = ADC_GET_IO_NUM(unit, channel);
#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
TEST_ESP_OK(gpio_set_pull_mode(io_num, GPIO_PULLUP_PULLDOWN));
#else
TEST_ESP_OK(rtc_gpio_init(io_num));
TEST_ESP_OK(rtc_gpio_pullup_en(io_num));
TEST_ESP_OK(rtc_gpio_pulldown_en(io_num));
TEST_ESP_OK(rtc_gpio_set_direction(io_num, RTC_GPIO_MODE_DISABLED));
#endif
vTaskDelay(10 / portTICK_PERIOD_MS);
}

View File

@@ -92,6 +92,13 @@ extern adc_atten_t g_test_atten[TEST_ATTEN_NUMS];
extern adc_atten_t g_test_atten[TEST_ATTEN_NUMS];
#endif
/*---------------------------------------------------------------
ADC Filter
---------------------------------------------------------------*/
#if SOC_ADC_DIG_IIR_FILTER_SUPPORTED
#define TEST_FILTER_COEFF_NUMS 5
extern adc_digi_iir_filter_coeff_t g_test_filter_coeff[TEST_FILTER_COEFF_NUMS];
#endif
/*---------------------------------------------------------------
ADC Calibration
@@ -127,6 +134,17 @@ void test_adc_calibration_deinit(adc_cali_handle_t handle);
*/
void test_adc_set_io_level(adc_unit_t unit, adc_channel_t channel, bool level);
/**
* @brief Set ADC IO to a middle level
*
* @note We don't expect this IO to have a fixed level among different chips.
* We just need the IO to be stable at a certain level, which is neither 0 nor overflow.
*
* @param[in] unit ADC unit
* @param[in] channel ADC channel
*/
void test_adc_set_io_middle(adc_unit_t unit, adc_channel_t channel);
#ifdef __cplusplus
}
#endif

View File

@@ -161,46 +161,77 @@ static inline void adc_ll_digi_controller_clk_disable(void)
/**
* Reset adc digital controller filter.
*
* @param idx Filter index
* @param adc_n ADC unit.
*/
static inline void adc_ll_digi_filter_reset(adc_unit_t adc_n)
static inline void adc_ll_digi_filter_reset(adc_digi_iir_filter_t idx, adc_unit_t adc_n)
{
(void)adc_n;
APB_SARADC.saradc_filter_ctrl0.saradc_filter_reset = 1;
APB_SARADC.saradc_filter_ctrl0.saradc_filter_reset = 0;
}
/**
* Set adc digital controller filter factor.
* Set adc digital controller filter coeff.
*
* @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 idx filter index
* @param adc_n adc unit
* @param channel adc channel
* @param coeff filter coeff
*/
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_digi_iir_filter_t idx, adc_unit_t adc_n, adc_channel_t channel, adc_digi_iir_filter_coeff_t coeff)
{
abort();
uint32_t factor_reg_val = 0;
switch (coeff) {
case ADC_DIGI_IIR_FILTER_COEFF_2:
factor_reg_val = 1;
break;
case ADC_DIGI_IIR_FILTER_COEFF_4:
factor_reg_val = 2;
break;
case ADC_DIGI_IIR_FILTER_COEFF_8:
factor_reg_val = 3;
break;
case ADC_DIGI_IIR_FILTER_COEFF_16:
factor_reg_val = 4;
break;
case ADC_DIGI_IIR_FILTER_COEFF_64:
factor_reg_val = 6;
break;
default:
HAL_ASSERT(false);
}
if (idx == ADC_DIGI_IIR_FILTER_0) {
APB_SARADC.saradc_filter_ctrl0.saradc_filter_channel0 = ((adc_n + 1) << 3) | (channel & 0x7);
APB_SARADC.saradc_filter_ctrl1.saradc_filter_factor0 = factor_reg_val;
} else if (idx == ADC_DIGI_IIR_FILTER_1) {
APB_SARADC.saradc_filter_ctrl0.saradc_filter_channel1 = ((adc_n + 1) << 3) | (channel & 0x7);
APB_SARADC.saradc_filter_ctrl1.saradc_filter_factor1 = factor_reg_val;
}
}
/**
* Get adc digital controller filter factor.
*
* @param adc_n ADC unit.
* @param factor Expression: filter_data = (k-1)/k * last_data + new_data / k. Set values: (2, 4, 8, 16, 64).
*/
static inline void adc_ll_digi_filter_get_factor(adc_digi_filter_idx_t idx, adc_digi_filter_t *filter)
{
abort();
}
/**
* Disable adc digital controller filter.
* Enable 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.
* @param idx filter index
* @param adc_n ADC unit
* @param enable Enable / Disable
*/
static inline void adc_ll_digi_filter_disable(adc_digi_filter_idx_t idx)
static inline void adc_ll_digi_filter_enable(adc_digi_iir_filter_t idx, adc_unit_t adc_n, bool enable)
{
abort();
(void)adc_n;
if (!enable) {
if (idx == ADC_DIGI_IIR_FILTER_0) {
APB_SARADC.saradc_filter_ctrl0.saradc_filter_channel0 = 0xF;
APB_SARADC.saradc_filter_ctrl1.saradc_filter_factor0 = 0;
} else if (idx == ADC_DIGI_IIR_FILTER_1) {
APB_SARADC.saradc_filter_ctrl0.saradc_filter_channel1 = 0xF;
APB_SARADC.saradc_filter_ctrl1.saradc_filter_factor1 = 0;
}
}
//nothing to do to enable, after adc_ll_digi_filter_set_factor, it's enabled.
}
/**

View File

@@ -304,66 +304,77 @@ static inline void adc_ll_digi_controller_clk_disable(void)
/**
* Reset adc digital controller filter.
*
* @param idx Filter index
* @param adc_n ADC unit.
*/
static inline void adc_ll_digi_filter_reset(adc_unit_t adc_n)
static inline void adc_ll_digi_filter_reset(adc_digi_iir_filter_t idx, adc_unit_t adc_n)
{
(void)adc_n;
APB_SARADC.filter_ctrl0.filter_reset = 1;
APB_SARADC.filter_ctrl0.filter_reset = 0;
}
/**
* Set adc digital controller filter factor.
* Set adc digital controller filter coeff.
*
* @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 idx filter index
* @param adc_n adc unit
* @param channel adc channel
* @param coeff filter coeff
*/
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_digi_iir_filter_t idx, adc_unit_t adc_n, adc_channel_t channel, adc_digi_iir_filter_coeff_t coeff)
{
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;
uint32_t factor_reg_val = 0;
switch (coeff) {
case ADC_DIGI_IIR_FILTER_COEFF_2:
factor_reg_val = 1;
break;
case ADC_DIGI_IIR_FILTER_COEFF_4:
factor_reg_val = 2;
break;
case ADC_DIGI_IIR_FILTER_COEFF_8:
factor_reg_val = 3;
break;
case ADC_DIGI_IIR_FILTER_COEFF_16:
factor_reg_val = 4;
break;
case ADC_DIGI_IIR_FILTER_COEFF_64:
factor_reg_val = 6;
break;
default:
HAL_ASSERT(false);
}
if (idx == ADC_DIGI_IIR_FILTER_0) {
APB_SARADC.filter_ctrl0.filter_channel0 = ((adc_n + 1) << 3) | (channel & 0x7);
APB_SARADC.filter_ctrl1.filter_factor0 = factor_reg_val;
} else if (idx == ADC_DIGI_IIR_FILTER_1) {
APB_SARADC.filter_ctrl0.filter_channel1 = ((adc_n + 1) << 3) | (channel & 0x7);
APB_SARADC.filter_ctrl1.filter_factor1 = factor_reg_val;
}
}
/**
* Get adc digital controller filter factor.
*
* @param adc_n ADC unit.
* @param factor Expression: filter_data = (k-1)/k * last_data + new_data / k. Set values: (2, 4, 8, 16, 64).
*/
static inline void adc_ll_digi_filter_get_factor(adc_digi_filter_idx_t idx, adc_digi_filter_t *filter)
{
if (idx == ADC_DIGI_FILTER_IDX0) {
filter->adc_unit = (APB_SARADC.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;
}
}
/**
* Disable adc digital controller filter.
* Enable 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.
* @param idx filter index
* @param adc_n ADC unit
* @param enable Enable / Disable
*/
static inline void adc_ll_digi_filter_disable(adc_digi_filter_idx_t idx)
static inline void adc_ll_digi_filter_enable(adc_digi_iir_filter_t idx, adc_unit_t adc_n, bool enable)
{
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;
(void)adc_n;
if (!enable) {
if (idx == ADC_DIGI_IIR_FILTER_0) {
APB_SARADC.filter_ctrl0.filter_channel0 = 0xF;
APB_SARADC.filter_ctrl1.filter_factor0 = 0;
} else if (idx == ADC_DIGI_IIR_FILTER_1) {
APB_SARADC.filter_ctrl0.filter_channel1 = 0xF;
APB_SARADC.filter_ctrl1.filter_factor1 = 0;
}
}
//nothing to do to enable, after adc_ll_digi_filter_set_factor, it's enabled.
}
/**

View File

@@ -313,66 +313,77 @@ static inline void adc_ll_digi_controller_clk_disable(void)
/**
* Reset adc digital controller filter.
*
* @param idx Filter index
* @param adc_n ADC unit.
*/
static inline void adc_ll_digi_filter_reset(adc_unit_t adc_n)
static inline void adc_ll_digi_filter_reset(adc_digi_iir_filter_t idx, adc_unit_t adc_n)
{
(void)adc_n;
APB_SARADC.saradc_filter_ctrl0.saradc_apb_saradc_filter_reset = 1;
APB_SARADC.saradc_filter_ctrl0.saradc_apb_saradc_filter_reset = 0;
}
/**
* Set adc digital controller filter factor.
* Set adc digital controller filter coeff.
*
* @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 idx filter index
* @param adc_n adc unit
* @param channel adc channel
* @param coeff filter coeff
*/
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_digi_iir_filter_t idx, adc_unit_t adc_n, adc_channel_t channel, adc_digi_iir_filter_coeff_t coeff)
{
if (idx == ADC_DIGI_FILTER_IDX0) {
APB_SARADC.saradc_filter_ctrl0.saradc_apb_saradc_filter_channel0 = (filter->adc_unit << 3) | (filter->channel & 0x7);
APB_SARADC.saradc_filter_ctrl1.saradc_apb_saradc_filter_factor0 = filter->mode;
} else if (idx == ADC_DIGI_FILTER_IDX1) {
APB_SARADC.saradc_filter_ctrl0.saradc_apb_saradc_filter_channel1 = (filter->adc_unit << 3) | (filter->channel & 0x7);
APB_SARADC.saradc_filter_ctrl1.saradc_apb_saradc_filter_factor1 = filter->mode;
uint32_t factor_reg_val = 0;
switch (coeff) {
case ADC_DIGI_IIR_FILTER_COEFF_2:
factor_reg_val = 1;
break;
case ADC_DIGI_IIR_FILTER_COEFF_4:
factor_reg_val = 2;
break;
case ADC_DIGI_IIR_FILTER_COEFF_8:
factor_reg_val = 3;
break;
case ADC_DIGI_IIR_FILTER_COEFF_16:
factor_reg_val = 4;
break;
case ADC_DIGI_IIR_FILTER_COEFF_64:
factor_reg_val = 6;
break;
default:
HAL_ASSERT(false);
}
if (idx == ADC_DIGI_IIR_FILTER_0) {
APB_SARADC.saradc_filter_ctrl0.saradc_apb_saradc_filter_channel0 = ((adc_n + 1) << 3) | (channel & 0x7);
APB_SARADC.saradc_filter_ctrl1.saradc_apb_saradc_filter_factor0 = factor_reg_val;
} else if (idx == ADC_DIGI_IIR_FILTER_1) {
APB_SARADC.saradc_filter_ctrl0.saradc_apb_saradc_filter_channel1 = ((adc_n + 1) << 3) | (channel & 0x7);
APB_SARADC.saradc_filter_ctrl1.saradc_apb_saradc_filter_factor1 = factor_reg_val;
}
}
/**
* Get adc digital controller filter factor.
*
* @param adc_n ADC unit.
* @param factor Expression: filter_data = (k-1)/k * last_data + new_data / k. Set values: (2, 4, 8, 16, 64).
*/
static inline void adc_ll_digi_filter_get_factor(adc_digi_filter_idx_t idx, adc_digi_filter_t *filter)
{
if (idx == ADC_DIGI_FILTER_IDX0) {
filter->adc_unit = (APB_SARADC.saradc_filter_ctrl0.saradc_apb_saradc_filter_channel0 >> 3) & 0x1;
filter->channel = APB_SARADC.saradc_filter_ctrl0.saradc_apb_saradc_filter_channel0 & 0x7;
filter->mode = APB_SARADC.saradc_filter_ctrl1.saradc_apb_saradc_filter_factor0;
} else if (idx == ADC_DIGI_FILTER_IDX1) {
filter->adc_unit = (APB_SARADC.saradc_filter_ctrl0.saradc_apb_saradc_filter_channel1 >> 3) & 0x1;
filter->channel = APB_SARADC.saradc_filter_ctrl0.saradc_apb_saradc_filter_channel1 & 0x7;
filter->mode = APB_SARADC.saradc_filter_ctrl1.saradc_apb_saradc_filter_factor1;
}
}
/**
* Disable adc digital controller filter.
* Enable 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.
* @param idx filter index
* @param adc_n ADC unit
* @param enable Enable / Disable
*/
static inline void adc_ll_digi_filter_disable(adc_digi_filter_idx_t idx)
static inline void adc_ll_digi_filter_enable(adc_digi_iir_filter_t idx, adc_unit_t adc_n, bool enable)
{
if (idx == ADC_DIGI_FILTER_IDX0) {
APB_SARADC.saradc_filter_ctrl0.saradc_apb_saradc_filter_channel0 = 0xF;
APB_SARADC.saradc_filter_ctrl1.saradc_apb_saradc_filter_factor0 = 0;
} else if (idx == ADC_DIGI_FILTER_IDX1) {
APB_SARADC.saradc_filter_ctrl0.saradc_apb_saradc_filter_channel1 = 0xF;
APB_SARADC.saradc_filter_ctrl1.saradc_apb_saradc_filter_factor1 = 0;
(void)adc_n;
if (!enable) {
if (idx == ADC_DIGI_IIR_FILTER_0) {
APB_SARADC.saradc_filter_ctrl0.saradc_apb_saradc_filter_channel0 = 0xF;
APB_SARADC.saradc_filter_ctrl1.saradc_apb_saradc_filter_factor0 = 0;
} else if (idx == ADC_DIGI_IIR_FILTER_1) {
APB_SARADC.saradc_filter_ctrl0.saradc_apb_saradc_filter_channel1 = 0xF;
APB_SARADC.saradc_filter_ctrl1.saradc_apb_saradc_filter_factor1 = 0;
}
}
//nothing to do to enable, after adc_ll_digi_filter_set_factor, it's enabled.
}
/**

View File

@@ -18,6 +18,7 @@
#include "soc/rtc_cntl_reg.h"
#include "soc/clk_tree_defs.h"
#include "hal/misc.h"
#include "hal/assert.h"
#include "hal/regi2c_ctrl.h"
#include "soc/regi2c_saradc.h"
@@ -310,66 +311,77 @@ static inline void adc_ll_digi_controller_clk_disable(void)
/**
* Reset adc digital controller filter.
*
* @param idx Filter index
* @param adc_n ADC unit.
*/
static inline void adc_ll_digi_filter_reset(adc_unit_t adc_n)
static inline void adc_ll_digi_filter_reset(adc_digi_iir_filter_t idx, adc_unit_t adc_n)
{
(void)adc_n;
APB_SARADC.filter_ctrl0.filter_reset = 1;
APB_SARADC.filter_ctrl0.filter_reset = 0;
}
/**
* Set adc digital controller filter factor.
* Set adc digital controller filter coeff.
*
* @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 idx filter index
* @param adc_n adc unit
* @param channel adc channel
* @param coeff filter coeff
*/
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_digi_iir_filter_t idx, adc_unit_t adc_n, adc_channel_t channel, adc_digi_iir_filter_coeff_t coeff)
{
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;
uint32_t factor_reg_val = 0;
switch (coeff) {
case ADC_DIGI_IIR_FILTER_COEFF_2:
factor_reg_val = 1;
break;
case ADC_DIGI_IIR_FILTER_COEFF_4:
factor_reg_val = 2;
break;
case ADC_DIGI_IIR_FILTER_COEFF_8:
factor_reg_val = 3;
break;
case ADC_DIGI_IIR_FILTER_COEFF_16:
factor_reg_val = 4;
break;
case ADC_DIGI_IIR_FILTER_COEFF_64:
factor_reg_val = 6;
break;
default:
HAL_ASSERT(false);
}
if (idx == ADC_DIGI_IIR_FILTER_0) {
APB_SARADC.filter_ctrl0.filter_channel0 = ((adc_n + 1) << 3) | (channel & 0x7);
APB_SARADC.filter_ctrl1.filter_factor0 = factor_reg_val;
} else if (idx == ADC_DIGI_IIR_FILTER_1) {
APB_SARADC.filter_ctrl0.filter_channel1 = ((adc_n + 1) << 3) | (channel & 0x7);
APB_SARADC.filter_ctrl1.filter_factor1 = factor_reg_val;
}
}
/**
* Get adc digital controller filter factor.
*
* @param adc_n ADC unit.
* @param factor Expression: filter_data = (k-1)/k * last_data + new_data / k. Set values: (2, 4, 8, 16, 64).
*/
static inline void adc_ll_digi_filter_get_factor(adc_digi_filter_idx_t idx, adc_digi_filter_t *filter)
{
if (idx == ADC_DIGI_FILTER_IDX0) {
filter->adc_unit = (APB_SARADC.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;
}
}
/**
* Disable adc digital controller filter.
* Enable 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.
* @param idx filter index
* @param adc_n ADC unit
* @param enable Enable / Disable
*/
static inline void adc_ll_digi_filter_disable(adc_digi_filter_idx_t idx)
static inline void adc_ll_digi_filter_enable(adc_digi_iir_filter_t idx, adc_unit_t adc_n, bool enable)
{
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;
(void)adc_n;
if (!enable) {
if (idx == ADC_DIGI_IIR_FILTER_0) {
APB_SARADC.filter_ctrl0.filter_channel0 = 0xF;
APB_SARADC.filter_ctrl1.filter_factor0 = 0;
} else if (idx == ADC_DIGI_IIR_FILTER_1) {
APB_SARADC.filter_ctrl0.filter_channel1 = 0xF;
APB_SARADC.filter_ctrl1.filter_factor1 = 0;
}
}
//nothing to do to enable, after adc_ll_digi_filter_set_factor, it's enabled.
}
/**

View File

@@ -357,10 +357,12 @@ static inline void adc_ll_digi_controller_clk_disable(void)
/**
* Reset adc digital controller filter.
*
* @param idx Filter index
* @param adc_n ADC unit.
*/
static inline void adc_ll_digi_filter_reset(adc_unit_t adc_n)
static inline void adc_ll_digi_filter_reset(adc_digi_iir_filter_t idx, adc_unit_t adc_n)
{
(void)idx;
if (adc_n == ADC_UNIT_1) {
APB_SARADC.filter_ctrl.adc1_filter_reset = 1;
APB_SARADC.filter_ctrl.adc1_filter_reset = 0;
@@ -371,20 +373,24 @@ static inline void adc_ll_digi_filter_reset(adc_unit_t adc_n)
}
/**
* Set adc digital controller filter factor.
* Set adc digital controller filter coeff.
*
* @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).
* @param idx filter index
* @param adc_n adc unit
* @param channel adc channel
* @param coeff filter coeff
*/
static inline void adc_ll_digi_filter_set_factor(adc_unit_t adc_n, adc_digi_filter_mode_t factor)
static inline void adc_ll_digi_filter_set_factor(adc_digi_iir_filter_t idx, adc_unit_t adc_n, adc_channel_t channel, adc_digi_iir_filter_coeff_t coeff)
{
(void)idx;
(void)channel;
int mode = 0;
switch (factor) {
case ADC_DIGI_FILTER_IIR_2: mode = 2; break;
case ADC_DIGI_FILTER_IIR_4: mode = 4; break;
case ADC_DIGI_FILTER_IIR_8: mode = 8; break;
case ADC_DIGI_FILTER_IIR_16: mode = 16; break;
case ADC_DIGI_FILTER_IIR_64: mode = 64; break;
switch (coeff) {
case ADC_DIGI_IIR_FILTER_COEFF_2: mode = 2; break;
case ADC_DIGI_IIR_FILTER_COEFF_4: mode = 4; break;
case ADC_DIGI_IIR_FILTER_COEFF_8: mode = 8; break;
case ADC_DIGI_IIR_FILTER_COEFF_16: mode = 16; break;
case ADC_DIGI_IIR_FILTER_COEFF_64: mode = 64; break;
default: mode = 8; break;
}
if (adc_n == ADC_UNIT_1) {
@@ -394,39 +400,18 @@ static inline void adc_ll_digi_filter_set_factor(adc_unit_t adc_n, adc_digi_filt
}
}
/**
* Get adc digital controller filter factor.
*
* @param adc_n ADC unit.
* @param factor Expression: filter_data = (k-1)/k * last_data + new_data / k. Set values: (2, 4, 8, 16, 64).
*/
static inline void adc_ll_digi_filter_get_factor(adc_unit_t adc_n, adc_digi_filter_mode_t *factor)
{
int mode = 0;
if (adc_n == ADC_UNIT_1) {
mode = APB_SARADC.filter_ctrl.adc1_filter_factor;
} else { // adc_n == ADC_UNIT_2
mode = APB_SARADC.filter_ctrl.adc2_filter_factor;
}
switch (mode) {
case 2: *factor = ADC_DIGI_FILTER_IIR_2; break;
case 4: *factor = ADC_DIGI_FILTER_IIR_4; break;
case 8: *factor = ADC_DIGI_FILTER_IIR_8; break;
case 16: *factor = ADC_DIGI_FILTER_IIR_16; break;
case 64: *factor = ADC_DIGI_FILTER_IIR_64; break;
default: *factor = ADC_DIGI_FILTER_IIR_MAX; break;
}
}
/**
* 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.
* @param idx Filter index
* @param adc_n ADC unit
* @param enable Enable / Disable
*/
static inline void adc_ll_digi_filter_enable(adc_unit_t adc_n, bool enable)
static inline void adc_ll_digi_filter_enable(adc_digi_iir_filter_t idx, adc_unit_t adc_n, bool enable)
{
(void)idx;
if (adc_n == ADC_UNIT_1) {
APB_SARADC.filter_ctrl.adc1_filter_en = enable;
} else { // adc_n == ADC_UNIT_2

View File

@@ -362,58 +362,77 @@ static inline void adc_ll_digi_controller_clk_disable(void)
/**
* Reset adc digital controller filter.
*
* @param idx Filter index
* @param adc_n ADC unit.
*/
static inline void adc_ll_digi_filter_reset(adc_unit_t adc_n)
static inline void adc_ll_digi_filter_reset(adc_digi_iir_filter_t idx, adc_unit_t adc_n)
{
abort();
(void)adc_n;
APB_SARADC.filter_ctrl0.filter_reset = 1;
APB_SARADC.filter_ctrl0.filter_reset = 0;
}
/**
* Set adc digital controller filter factor.
* Set adc digital controller filter coeff.
*
* @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).
* @param idx filter index
* @param adc_n adc unit
* @param channel adc channel
* @param coeff filter coeff
*/
static inline void adc_ll_digi_filter_set_factor(adc_unit_t adc_n, adc_digi_filter_mode_t factor)
static inline void adc_ll_digi_filter_set_factor(adc_digi_iir_filter_t idx, adc_unit_t adc_n, adc_channel_t channel, adc_digi_iir_filter_coeff_t coeff)
{
abort();
uint32_t factor_reg_val = 0;
switch (coeff) {
case ADC_DIGI_IIR_FILTER_COEFF_2:
factor_reg_val = 1;
break;
case ADC_DIGI_IIR_FILTER_COEFF_4:
factor_reg_val = 2;
break;
case ADC_DIGI_IIR_FILTER_COEFF_8:
factor_reg_val = 3;
break;
case ADC_DIGI_IIR_FILTER_COEFF_16:
factor_reg_val = 4;
break;
case ADC_DIGI_IIR_FILTER_COEFF_64:
factor_reg_val = 6;
break;
default:
HAL_ASSERT(false);
}
if (idx == ADC_DIGI_IIR_FILTER_0) {
APB_SARADC.filter_ctrl0.filter_channel0 = ((adc_n + 1) << 3) | (channel & 0x7);
APB_SARADC.filter_ctrl1.filter_factor0 = factor_reg_val;
} else if (idx == ADC_DIGI_IIR_FILTER_1) {
APB_SARADC.filter_ctrl0.filter_channel1 = ((adc_n + 1) << 3) | (channel & 0x7);
APB_SARADC.filter_ctrl1.filter_factor1 = factor_reg_val;
}
}
/**
* Get adc digital controller filter factor.
*
* @param adc_n ADC unit.
* @param factor Expression: filter_data = (k-1)/k * last_data + new_data / k. Set values: (2, 4, 8, 16, 64).
*/
static inline void adc_ll_digi_filter_get_factor(adc_unit_t adc_n, adc_digi_filter_mode_t *factor)
{
abort();
}
/**
* Enable/disable adc digital controller filter.
* Enable 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.
* @param idx filter index
* @param adc_n ADC unit
* @param enable Enable / Disable
*/
static inline void adc_ll_digi_filter_enable(adc_unit_t adc_n, bool enable)
static inline void adc_ll_digi_filter_enable(adc_digi_iir_filter_t idx, adc_unit_t adc_n, bool enable)
{
abort();
}
/**
* 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.
*/
static inline uint32_t adc_ll_digi_filter_read_data(adc_unit_t adc_n)
{
abort();
(void)adc_n;
if (!enable) {
if (idx == ADC_DIGI_IIR_FILTER_0) {
APB_SARADC.filter_ctrl0.filter_channel0 = 0xF;
APB_SARADC.filter_ctrl1.filter_factor0 = 0;
} else if (idx == ADC_DIGI_IIR_FILTER_1) {
APB_SARADC.filter_ctrl0.filter_channel1 = 0xF;
APB_SARADC.filter_ctrl1.filter_factor1 = 0;
}
}
//nothing to do to enable, after adc_ll_digi_filter_set_factor, it's enabled.
}
/**

View File

@@ -97,6 +97,25 @@ typedef struct {
uint8_t bit_width; ///< ADC output bit width
} adc_digi_pattern_config_t;
/**
* @brief ADC IIR Filter ID
*/
typedef enum {
ADC_DIGI_IIR_FILTER_0, ///< Filter 0
ADC_DIGI_IIR_FILTER_1, ///< Filter 1
} adc_digi_iir_filter_t;
/**
* @brief IIR Filter Coefficient
*/
typedef enum {
ADC_DIGI_IIR_FILTER_COEFF_2, ///< The filter coefficient is 2
ADC_DIGI_IIR_FILTER_COEFF_4, ///< The filter coefficient is 4
ADC_DIGI_IIR_FILTER_COEFF_8, ///< The filter coefficient is 8
ADC_DIGI_IIR_FILTER_COEFF_16, ///< The filter coefficient is 16
ADC_DIGI_IIR_FILTER_COEFF_64, ///< The filter coefficient is 64
} adc_digi_iir_filter_coeff_t;
/*---------------------------------------------------------------
Output Format
---------------------------------------------------------------*/

View File

@@ -47,55 +47,6 @@ typedef struct {
}
#endif //#if SOC_ADC_ARBITER_SUPPORTED
#if SOC_ADC_FILTER_SUPPORTED
/*---------------------------------------------------------------
Filter
---------------------------------------------------------------*/
/**
* @brief ADC digital controller (DMA mode) filter index options.
*
* @note For ESP32-S2, The filter object of the ADC is fixed.
*/
typedef enum {
ADC_DIGI_FILTER_IDX0 = 0, /*!<The filter index 0.
For ESP32-S2, It can only be used to filter all enabled channels of ADC1 unit at the same time. */
ADC_DIGI_FILTER_IDX1, /*!<The filter index 1.
For ESP32-S2, It can only be used to filter all enabled channels of ADC2 unit at the same time. */
ADC_DIGI_FILTER_IDX_MAX
} adc_digi_filter_idx_t;
/**
* @brief ADC digital controller (DMA mode) filter type options.
* Expression: filter_data = (k-1)/k * last_data + new_data / k.
*/
typedef enum {
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H4 || CONFIG_IDF_TARGET_ESP32C2
ADC_DIGI_FILTER_DIS = -1, /*!< Disable filter */
#endif
ADC_DIGI_FILTER_IIR_2 = 0, /*!<The filter mode is first-order IIR filter. The coefficient is 2. */
ADC_DIGI_FILTER_IIR_4, /*!<The filter mode is first-order IIR filter. The coefficient is 4. */
ADC_DIGI_FILTER_IIR_8, /*!<The filter mode is first-order IIR filter. The coefficient is 8. */
ADC_DIGI_FILTER_IIR_16, /*!<The filter mode is first-order IIR filter. The coefficient is 16. */
ADC_DIGI_FILTER_IIR_64, /*!<The filter mode is first-order IIR filter. The coefficient is 64. */
ADC_DIGI_FILTER_IIR_MAX
} adc_digi_filter_mode_t;
/**
* @brief ADC digital controller (DMA mode) filter configuration.
*
* @note For ESP32-S2, The filter object of the ADC is fixed.
* @note For ESP32-S2, The filter object is always all enabled channels.
*/
typedef struct {
adc_unit_t adc_unit; /*!<Set adc unit number for filter.
For ESP32-S2, Filter IDX0/IDX1 can only be used to filter all enabled channels of ADC1/ADC2 unit at the same time. */
adc_channel_t channel; /*!<Set adc channel number for filter.
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

View File

@@ -41,3 +41,6 @@
// floating point instructions per divide and per sqrt (configured for worst-case with PSRAM workaround)
#define IDF_PERFORMANCE_MAX_CYCLES_PER_DIV 70
#define IDF_PERFORMANCE_MAX_CYCLES_PER_SQRT 140
#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_NO_FILTER 3
#define IDF_PERFORMANCE_MAX_ADC_ONESHOT_STD_ATTEN3 3

View File

@@ -35,3 +35,5 @@
// floating point instructions per divide and per sqrt (configured for worst-case with PSRAM workaround)
#define IDF_PERFORMANCE_MAX_CYCLES_PER_DIV 70
#define IDF_PERFORMANCE_MAX_CYCLES_PER_SQRT 140
#define IDF_PERFORMANCE_MAX_ADC_ONESHOT_STD_ATTEN3 3

View File

@@ -39,3 +39,11 @@
// floating point instructions per divide and per sqrt (configured for worst-case with PSRAM workaround)
#define IDF_PERFORMANCE_MAX_CYCLES_PER_DIV 70
#define IDF_PERFORMANCE_MAX_CYCLES_PER_SQRT 140
#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_NO_FILTER 5
#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_2 5
#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_4 5
#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_8 5
#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_16 5
#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_64 5
#define IDF_PERFORMANCE_MAX_ADC_ONESHOT_STD_ATTEN3 5

View File

@@ -19,3 +19,10 @@
#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING 17
#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING_NO_DMA 32
#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING_NO_DMA 15
#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_NO_FILTER 6
#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_2 5
#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_4 5
#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_8 5
#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_16 5
#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_64 5

View File

@@ -27,3 +27,11 @@
#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING_NO_DMA 15
#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING 32
#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING_NO_DMA 30
#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_NO_FILTER 3
#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_2 3
#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_4 3
#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_8 3
#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_16 3
#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_64 3
#define IDF_PERFORMANCE_MAX_ADC_ONESHOT_STD_ATTEN3 6

View File

@@ -29,3 +29,11 @@
// floating point instructions per divide and per sqrt (configured for worst-case with PSRAM workaround)
#define IDF_PERFORMANCE_MAX_CYCLES_PER_DIV 70
#define IDF_PERFORMANCE_MAX_CYCLES_PER_SQRT 140
#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_NO_FILTER 4
#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_2 4
#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_4 4
#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_8 4
#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_16 4
#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_64 4
#define IDF_PERFORMANCE_MAX_ADC_ONESHOT_STD_ATTEN3 4

View File

@@ -99,7 +99,7 @@ config SOC_ADC_DIG_CTRL_SUPPORTED
bool
default y
config SOC_ADC_FILTER_SUPPORTED
config SOC_ADC_DIG_IIR_FILTER_SUPPORTED
bool
default y
@@ -135,7 +135,7 @@ config SOC_ADC_DIGI_MAX_BITWIDTH
int
default 12
config SOC_ADC_DIGI_FILTER_NUM
config SOC_ADC_DIGI_IIR_FILTER_NUM
int
default 2

View File

@@ -54,7 +54,7 @@
/*-------------------------- ADC CAPS -------------------------------*/
/*!< SAR ADC Module*/
#define SOC_ADC_DIG_CTRL_SUPPORTED 1
#define SOC_ADC_FILTER_SUPPORTED 1
#define SOC_ADC_DIG_IIR_FILTER_SUPPORTED 1
#define SOC_ADC_MONITOR_SUPPORTED 1
#define SOC_ADC_DIG_SUPPORTED_UNIT(UNIT) 1 //Digital controller supported ADC unit
#define SOC_ADC_PERIPH_NUM (1U)
@@ -67,7 +67,7 @@
#define SOC_ADC_PATT_LEN_MAX (8) /*!< One pattern table, each contains 8 items. Each item takes 1 byte */
#define SOC_ADC_DIGI_MIN_BITWIDTH (12)
#define SOC_ADC_DIGI_MAX_BITWIDTH (12)
#define SOC_ADC_DIGI_FILTER_NUM (2)
#define SOC_ADC_DIGI_IIR_FILTER_NUM (2)
#define SOC_ADC_DIGI_MONITOR_NUM (2)
/*!< F_sample = F_digi_con / 2 / interval. F_digi_con = 5M for now. 30 <= interval<= 4095 */
#define SOC_ADC_SAMPLE_FREQ_THRES_HIGH 83333

View File

@@ -167,7 +167,7 @@ config SOC_ADC_ARBITER_SUPPORTED
bool
default y
config SOC_ADC_FILTER_SUPPORTED
config SOC_ADC_DIG_IIR_FILTER_SUPPORTED
bool
default y
@@ -215,7 +215,7 @@ config SOC_ADC_DIGI_DATA_BYTES_PER_CONV
int
default 4
config SOC_ADC_DIGI_FILTER_NUM
config SOC_ADC_DIGI_IIR_FILTER_NUM
int
default 2

View File

@@ -79,7 +79,7 @@
/*!< 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_DIG_IIR_FILTER_SUPPORTED 1
#define SOC_ADC_MONITOR_SUPPORTED 1
#define SOC_ADC_DMA_SUPPORTED 1
#define SOC_ADC_DIG_SUPPORTED_UNIT(UNIT) ((UNIT == 0) ? 1 : 0) //Digital controller supported ADC unit
@@ -95,7 +95,7 @@
#define SOC_ADC_DIGI_MAX_BITWIDTH (12)
#define SOC_ADC_DIGI_RESULT_BYTES (4)
#define SOC_ADC_DIGI_DATA_BYTES_PER_CONV (4)
#define SOC_ADC_DIGI_FILTER_NUM (2)
#define SOC_ADC_DIGI_IIR_FILTER_NUM (2)
#define SOC_ADC_DIGI_MONITOR_NUM (2)
/*!< F_sample = F_digi_con / 2 / interval. F_digi_con = 5M for now. 30 <= interval <= 4095 */
#define SOC_ADC_SAMPLE_FREQ_THRES_HIGH 83333

View File

@@ -187,7 +187,7 @@ config SOC_ADC_DIG_CTRL_SUPPORTED
bool
default y
config SOC_ADC_FILTER_SUPPORTED
config SOC_ADC_DIG_IIR_FILTER_SUPPORTED
bool
default y
@@ -227,7 +227,7 @@ config SOC_ADC_DIGI_MIN_BITWIDTH
int
default 12
config SOC_ADC_DIGI_FILTER_NUM
config SOC_ADC_DIGI_IIR_FILTER_NUM
int
default 2

View File

@@ -82,7 +82,7 @@
/*-------------------------- ADC CAPS -------------------------------*/
/*!< SAR ADC Module*/
#define SOC_ADC_DIG_CTRL_SUPPORTED 1
#define SOC_ADC_FILTER_SUPPORTED 1
#define SOC_ADC_DIG_IIR_FILTER_SUPPORTED 1
#define SOC_ADC_MONITOR_SUPPORTED 1
#define SOC_ADC_DIG_SUPPORTED_UNIT(UNIT) 1 //Digital controller supported ADC unit
#define SOC_ADC_DMA_SUPPORTED 1
@@ -96,7 +96,7 @@
#define SOC_ADC_PATT_LEN_MAX (8) /*!< Two pattern tables, each contains 4 items. Each item takes 1 byte */
#define SOC_ADC_DIGI_MAX_BITWIDTH (12)
#define SOC_ADC_DIGI_MIN_BITWIDTH (12)
#define SOC_ADC_DIGI_FILTER_NUM (2)
#define SOC_ADC_DIGI_IIR_FILTER_NUM (2)
#define SOC_ADC_DIGI_MONITOR_NUM (2)
#define SOC_ADC_DIGI_RESULT_BYTES (4)
#define SOC_ADC_DIGI_DATA_BYTES_PER_CONV (4)

View File

@@ -127,7 +127,7 @@ config SOC_ADC_ARBITER_SUPPORTED
bool
default y
config SOC_ADC_FILTER_SUPPORTED
config SOC_ADC_DIG_IIR_FILTER_SUPPORTED
bool
default y
@@ -159,7 +159,7 @@ config SOC_ADC_DIGI_MAX_BITWIDTH
int
default 12
config SOC_ADC_DIGI_FILTER_NUM
config SOC_ADC_DIGI_IIR_FILTER_NUM
int
default 2

View File

@@ -81,7 +81,7 @@
/*!< 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_DIG_IIR_FILTER_SUPPORTED 1
#define SOC_ADC_MONITOR_SUPPORTED 1
#define SOC_ADC_PERIPH_NUM (1U)
#define SOC_ADC_CHANNEL_NUM(PERIPH_NUM) ((PERIPH_NUM==0)? 5 : 1)
@@ -92,7 +92,7 @@
#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_IIR_FILTER_NUM (2)
#define SOC_ADC_DIGI_MONITOR_NUM (2)
/*!< F_sample = F_digi_con / 2 / interval. F_digi_con = 5M for now. 30 <= interval<= 4095 */
#define SOC_ADC_SAMPLE_FREQ_THRES_HIGH 83333

View File

@@ -151,7 +151,7 @@ config SOC_ADC_ARBITER_SUPPORTED
bool
default y
config SOC_ADC_FILTER_SUPPORTED
config SOC_ADC_DIG_IIR_FILTER_SUPPORTED
bool
default y
@@ -199,7 +199,7 @@ config SOC_ADC_DIGI_DATA_BYTES_PER_CONV
int
default 4
config SOC_ADC_DIGI_FILTER_NUM
config SOC_ADC_DIGI_IIR_FILTER_NUM
int
default 2

View File

@@ -80,7 +80,7 @@
/*!< 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_DIG_IIR_FILTER_SUPPORTED 1
#define SOC_ADC_MONITOR_SUPPORTED 1
#define SOC_ADC_DMA_SUPPORTED 1
#define SOC_ADC_DIG_SUPPORTED_UNIT(UNIT) ((UNIT == 0) ? 1 : 0) //Digital controller supported ADC unit
@@ -96,7 +96,7 @@
#define SOC_ADC_DIGI_MAX_BITWIDTH (12)
#define SOC_ADC_DIGI_RESULT_BYTES (4)
#define SOC_ADC_DIGI_DATA_BYTES_PER_CONV (4)
#define SOC_ADC_DIGI_FILTER_NUM (2)
#define SOC_ADC_DIGI_IIR_FILTER_NUM (2)
#define SOC_ADC_DIGI_MONITOR_NUM (2)
/*!< F_sample = F_digi_con / 2 / interval. F_digi_con = 5M for now. 30 <= interval<= 4095 */
#define SOC_ADC_SAMPLE_FREQ_THRES_HIGH 83333

View File

@@ -183,7 +183,11 @@ config SOC_ADC_ARBITER_SUPPORTED
bool
default y
config SOC_ADC_FILTER_SUPPORTED
config SOC_ADC_DIG_IIR_FILTER_SUPPORTED
bool
default y
config SOC_ADC_DIG_IIR_FILTER_UNIT_BINDED
bool
default y
@@ -223,6 +227,10 @@ config SOC_ADC_DIGI_MAX_BITWIDTH
int
default 12
config SOC_ADC_DIGI_IIR_FILTER_NUM
int
default 2
config SOC_ADC_DIGI_RESULT_BYTES
int
default 2

View File

@@ -89,7 +89,8 @@
#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_DIG_IIR_FILTER_SUPPORTED 1
#define SOC_ADC_DIG_IIR_FILTER_UNIT_BINDED 1 //ADC filter is binded with the ADC unit
#define SOC_ADC_MONITOR_SUPPORTED 1
#define SOC_ADC_DMA_SUPPORTED 1
#define SOC_ADC_DIG_SUPPORTED_UNIT(UNIT) 1 //Digital controller supported ADC unit
@@ -103,6 +104,7 @@
#define SOC_ADC_PATT_LEN_MAX (32) /*!< Two pattern table, each contains 16 items. Each item takes 1 byte */
#define SOC_ADC_DIGI_MIN_BITWIDTH (12)
#define SOC_ADC_DIGI_MAX_BITWIDTH (12)
#define SOC_ADC_DIGI_IIR_FILTER_NUM (2)
#define SOC_ADC_DIGI_RESULT_BYTES (2)
#define SOC_ADC_DIGI_DATA_BYTES_PER_CONV (2)
/*!< F_sample = F_digi_con / 2 / interval. F_digi_con = 5M for now. 30 <= interval<= 4095 */

View File

@@ -223,7 +223,7 @@ config SOC_ADC_ARBITER_SUPPORTED
bool
default y
config SOC_ADC_FILTER_SUPPORTED
config SOC_ADC_DIG_IIR_FILTER_SUPPORTED
bool
default y
@@ -271,6 +271,10 @@ config SOC_ADC_DIGI_DATA_BYTES_PER_CONV
int
default 4
config SOC_ADC_DIGI_IIR_FILTER_NUM
int
default 2
config SOC_ADC_SAMPLE_FREQ_THRES_HIGH
int
default 83333

View File

@@ -82,7 +82,7 @@
#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_DIG_IIR_FILTER_SUPPORTED 1
#define SOC_ADC_MONITOR_SUPPORTED 1
#define SOC_ADC_DMA_SUPPORTED 1
#define SOC_ADC_DIG_SUPPORTED_UNIT(UNIT) ((UNIT == 0) ? 1 : 0) //Digital controller supported ADC unit
@@ -98,6 +98,7 @@
#define SOC_ADC_DIGI_MAX_BITWIDTH (12)
#define SOC_ADC_DIGI_RESULT_BYTES (4)
#define SOC_ADC_DIGI_DATA_BYTES_PER_CONV (4)
#define SOC_ADC_DIGI_IIR_FILTER_NUM (2)
/*!< F_sample = F_digi_con / 2 / interval. F_digi_con = 5M for now. 30 <= interval<= 4095 */
#define SOC_ADC_SAMPLE_FREQ_THRES_HIGH 83333
#define SOC_ADC_SAMPLE_FREQ_THRES_LOW 611

View File

@@ -71,6 +71,26 @@ After setting up above configurations for the ADC, call :cpp:func:`adc_continuou
If the ADC continuous mode driver is no longer used, you should deinitialize the driver by calling :cpp:func:`adc_continuous_deinit`.
.. only:: SOC_ADC_DIG_IIR_FILTER_SUPPORTED
Two IIR filters are available when ADC is working under continuous mode. To create an ADC IIR filter, you should set up the :cpp:type:`adc_continuous_iir_filter_config_t`, and call :cpp:func:`adc_new_continuous_iir_filter`.
- :cpp:member:`adc_digi_filter_config_t::unit`, ADC unit.
- :cpp:member:`adc_digi_filter_config_t::channel`, ADC channel to be filtered.
- :cpp:member:`adc_digi_filter_config_t::coeff`, filter coefficient.
.. only:: SOC_ADC_DIG_IIR_FILTER_UNIT_BINDED
On ESP32S2, the filter is per ADC unit. Once a filter is enabled, all the enabled ADC channels in this ADC unit will be filtered. However, we suggest only enabling one ADC channel per unit, when using the filter feature. Because the filtered results depend on the previous filtered result. So you should not enable multiple ADC channels, to avoid mixing the filtered results.
To recycle a filter, you should call :cpp:func:`adc_del_continuous_iir_filter`.
.. only:: not SOC_ADC_DIG_IIR_FILTER_UNIT_BINDED
.. note::
If you use both the filters on a same ADC channel, then only the first one will take effect.
Initialize the ADC Continuous Mode Driver
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -120,6 +140,10 @@ This API may fail due to reasons like :c:macro:`ESP_ERR_INVALID_ARG`. When it re
See ADC continuous mode example :example:`peripherals/adc/continuous_read` to see configuration codes.
.. only:: SOC_ADC_DIG_IIR_FILTER_SUPPORTED
To enable / disable the ADC IIR filter, you should call :cpp:func:`adc_continuous_iir_filter_enable` / :cpp:func:`adc_continuous_iir_filter_disable`.
ADC Control
^^^^^^^^^^^

View File

@@ -70,6 +70,7 @@ API Changes
- API ``hall_sensor_read`` on ESP32 has been removed. Hall sensor is no longer supported on ESP32.
- API ``adc_set_i2s_data_source`` and ``adc_i2s_mode_init`` have been deprecated. Related enum ``adc_i2s_source_t`` has been deprecated. Please migrate to use ``esp_adc/adc_continuous.h``.
- API ``adc_digi_filter_reset``, ``adc_digi_filter_set_config``, ``adc_digi_filter_get_config`` and ``adc_digi_filter_enable`` have been removed. These APIs behaviours are not guaranteed. Enum ``adc_digi_filter_idx_t``, ``adc_digi_filter_mode_t`` and structure ``adc_digi_iir_filter_t`` have been removed as well.
GPIO
----

View File

@@ -70,6 +70,7 @@ API 更新
- ESP32 中的 API ``hall_sensor_read`` 已被删除,因此 ESP32 不再支持霍尔传感器。
- API ``adc_set_i2s_data_source````adc_i2s_mode_init`` 已被弃用,相关的枚举 ``adc_i2s_source_t`` 也已被弃用,请使用 ``esp_adc/adc_continuous.h`` 进行迁移。
- API ``adc_digi_filter_reset`` ``adc_digi_filter_set_config`` ``adc_digi_filter_get_config````adc_digi_filter_enable`` 已被移除. 这些接口的行为不被保证。 枚举 ``adc_digi_filter_idx_t`` ``adc_digi_filter_mode_t`` 和结构体 ``adc_digi_iir_filter_t`` 已被移除。
GPIO
----------