esp_adc: added adc digital filter feature

This commit is contained in:
Armando 2023-02-07 16:01:26 +08:00 committed by Armando (Dou Yiwen)
parent 648b1a41c6
commit 3afa671069
38 changed files with 1032 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,158 @@
/*
* 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 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

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