diff --git a/components/esp_adc/CMakeLists.txt b/components/esp_adc/CMakeLists.txt index fc17397748..2f53681010 100644 --- a/components/esp_adc/CMakeLists.txt +++ b/components/esp_adc/CMakeLists.txt @@ -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") diff --git a/components/esp_adc/adc_continuous.c b/components/esp_adc/adc_continuous.c index 7f21de5d68..b4bc9ab319 100644 --- a/components/esp_adc/adc_continuous.c +++ b/components/esp_adc/adc_continuous.c @@ -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; diff --git a/components/esp_adc/adc_continuous_internal.h b/components/esp_adc/adc_continuous_internal.h new file mode 100644 index 0000000000..e352c300e7 --- /dev/null +++ b/components/esp_adc/adc_continuous_internal.h @@ -0,0 +1,87 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#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 diff --git a/components/esp_adc/adc_filter.c b/components/esp_adc/adc_filter.c new file mode 100644 index 0000000000..f27216cd08 --- /dev/null +++ b/components/esp_adc/adc_filter.c @@ -0,0 +1,158 @@ +/* + * SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#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; +} diff --git a/components/esp_adc/include/esp_adc/adc_continuous.h b/components/esp_adc/include/esp_adc/adc_continuous.h index 8db0f53135..d4827669e9 100644 --- a/components/esp_adc/include/esp_adc/adc_continuous.h +++ b/components/esp_adc/include/esp_adc/adc_continuous.h @@ -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 } diff --git a/components/esp_adc/include/esp_adc/adc_filter.h b/components/esp_adc/include/esp_adc/adc_filter.h new file mode 100644 index 0000000000..de4a12074c --- /dev/null +++ b/components/esp_adc/include/esp_adc/adc_filter.h @@ -0,0 +1,88 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#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 a 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 diff --git a/components/esp_adc/test_apps/adc/main/test_adc_driver_iram.c b/components/esp_adc/test_apps/adc/main/test_adc_driver_iram.c index c48fc746a1..a258a5b743 100644 --- a/components/esp_adc/test_apps/adc/main/test_adc_driver_iram.c +++ b/components/esp_adc/test_apps/adc/main/test_adc_driver_iram.c @@ -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; diff --git a/components/esp_adc/test_apps/adc/main/test_adc_performance.c b/components/esp_adc/test_apps/adc/main/test_adc_performance.c index 314b59aef9..366c288bac 100644 --- a/components/esp_adc/test_apps/adc/main/test_adc_performance.c +++ b/components/esp_adc/test_apps/adc/main/test_adc_performance.c @@ -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<= 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); } diff --git a/components/esp_adc/test_apps/adc/main/test_common_adc.c b/components/esp_adc/test_apps/adc/main/test_common_adc.c index aff057286e..f9cc81ebf1 100644 --- a/components/esp_adc/test_apps/adc/main/test_common_adc.c +++ b/components/esp_adc/test_apps/adc/main/test_common_adc.c @@ -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 #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); +} diff --git a/components/esp_adc/test_apps/adc/main/test_common_adc.h b/components/esp_adc/test_apps/adc/main/test_common_adc.h index d822404a3f..d443d33235 100644 --- a/components/esp_adc/test_apps/adc/main/test_common_adc.h +++ b/components/esp_adc/test_apps/adc/main/test_common_adc.h @@ -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 diff --git a/components/hal/esp32c2/include/hal/adc_ll.h b/components/hal/esp32c2/include/hal/adc_ll.h index 15376463b2..a1d51689d7 100644 --- a/components/hal/esp32c2/include/hal/adc_ll.h +++ b/components/hal/esp32c2/include/hal/adc_ll.h @@ -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. } /** diff --git a/components/hal/esp32c3/include/hal/adc_ll.h b/components/hal/esp32c3/include/hal/adc_ll.h index 81966cb01c..c102b72abd 100644 --- a/components/hal/esp32c3/include/hal/adc_ll.h +++ b/components/hal/esp32c3/include/hal/adc_ll.h @@ -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. } /** diff --git a/components/hal/esp32c6/include/hal/adc_ll.h b/components/hal/esp32c6/include/hal/adc_ll.h index 9dd051b716..5ed2db486a 100644 --- a/components/hal/esp32c6/include/hal/adc_ll.h +++ b/components/hal/esp32c6/include/hal/adc_ll.h @@ -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. } /** diff --git a/components/hal/esp32h4/include/hal/adc_ll.h b/components/hal/esp32h4/include/hal/adc_ll.h index b131fda5fa..aa23ec8bb2 100644 --- a/components/hal/esp32h4/include/hal/adc_ll.h +++ b/components/hal/esp32h4/include/hal/adc_ll.h @@ -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. } /** diff --git a/components/hal/esp32s2/include/hal/adc_ll.h b/components/hal/esp32s2/include/hal/adc_ll.h index aacb604209..e09a07f54c 100644 --- a/components/hal/esp32s2/include/hal/adc_ll.h +++ b/components/hal/esp32s2/include/hal/adc_ll.h @@ -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 diff --git a/components/hal/esp32s3/include/hal/adc_ll.h b/components/hal/esp32s3/include/hal/adc_ll.h index c1526aebc6..19a5c9aea3 100644 --- a/components/hal/esp32s3/include/hal/adc_ll.h +++ b/components/hal/esp32s3/include/hal/adc_ll.h @@ -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. } /** diff --git a/components/hal/include/hal/adc_types.h b/components/hal/include/hal/adc_types.h index 8568c195c5..b8cc83b245 100644 --- a/components/hal/include/hal/adc_types.h +++ b/components/hal/include/hal/adc_types.h @@ -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 ---------------------------------------------------------------*/ diff --git a/components/hal/include/hal/adc_types_private.h b/components/hal/include/hal/adc_types_private.h index 63c210261b..aa65371465 100644 --- a/components/hal/include/hal/adc_types_private.h +++ b/components/hal/include/hal/adc_types_private.h @@ -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, /*!