adc: update the monitor and filter in the HAL on C3

On C3 ADC has no enable bit for monitor and filter. However we can use context variables to implement one
This commit is contained in:
Michael (XIAO Xufeng) 2021-01-07 23:43:35 +08:00 committed by bot
parent 19fb11549b
commit 90fc3e7030
5 changed files with 85 additions and 46 deletions

View File

@ -663,11 +663,7 @@ esp_err_t adc_digi_reset(void)
esp_err_t adc_digi_filter_reset(adc_digi_filter_idx_t idx)
{
ADC_ENTER_CRITICAL();
if (idx == ADC_DIGI_FILTER_IDX0) {
adc_hal_digi_filter_reset(ADC_NUM_1);
} else if (idx == ADC_DIGI_FILTER_IDX1) {
adc_hal_digi_filter_reset(ADC_NUM_2);
}
adc_hal_digi_filter_reset(idx);
ADC_EXIT_CRITICAL();
return ESP_OK;
}
@ -690,21 +686,12 @@ esp_err_t adc_digi_filter_get_config(adc_digi_filter_idx_t idx, adc_digi_filter_
esp_err_t adc_digi_filter_enable(adc_digi_filter_idx_t idx, bool enable)
{
ADC_ENTER_CRITICAL();
adc_hal_digi_filter_enable(idx, enable);
ADC_EXIT_CRITICAL();
return ESP_OK;
}
/**
* @brief Get the filtered data of adc digital controller filter. For debug.
* 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.
*
* @param idx Filter index.
* @return Filtered data. if <0, the read data invalid.
*/
int adc_digi_filter_read_data(adc_digi_filter_idx_t idx)
{
return -1;
}
/**************************************/
/* Digital controller monitor setting */
/**************************************/
@ -719,6 +706,10 @@ esp_err_t adc_digi_monitor_set_config(adc_digi_monitor_idx_t idx, adc_digi_monit
esp_err_t adc_digi_monitor_enable(adc_digi_monitor_idx_t idx, bool enable)
{
ADC_ENTER_CRITICAL();
adc_hal_digi_monitor_enable(idx, enable);
ADC_EXIT_CRITICAL();
return ESP_OK;
}

View File

@ -14,9 +14,20 @@
// The HAL layer for ADC (ESP32-C3 specific part)
#include <string.h>
#include "soc/soc_caps.h"
#include "hal/adc_hal.h"
#include "hal/adc_types.h"
//Currently we don't have context for the ADC HAL. So HAL variables are temporarily put here. But
//please don't follow this code. Create a context for your own HAL!
static bool s_filter_enabled[SOC_ADC_DIGI_FILTER_NUM] = {};
static adc_digi_filter_t s_filter[SOC_ADC_DIGI_FILTER_NUM] = {};
static bool s_monitor_enabled[SOC_ADC_DIGI_MONITOR_NUM] = {};
static adc_digi_monitor_t s_monitor_config[SOC_ADC_DIGI_MONITOR_NUM] = {};
/*---------------------------------------------------------------
Digital controller setting
---------------------------------------------------------------*/
@ -94,6 +105,16 @@ void adc_hal_digi_disable(void)
adc_ll_digi_dma_disable();
}
static void filter_update(adc_digi_filter_idx_t idx)
{
//ESP32-C3 has no enable bit, the filter will be enabled when the filter channel is configured
if (s_filter_enabled[idx]) {
adc_ll_digi_filter_set_factor(idx, &s_filter[idx]);
} else {
adc_ll_digi_filter_disable(idx);
}
}
/**
* Set adc digital controller filter factor.
*
@ -102,11 +123,8 @@ void adc_hal_digi_disable(void)
*/
void adc_hal_digi_filter_set_factor(adc_digi_filter_idx_t idx, adc_digi_filter_t *filter)
{
if (filter->mode == ADC_DIGI_FILTER_DIS) {
adc_ll_digi_filter_disable(idx);
} else {
adc_ll_digi_filter_set_factor(idx, filter);
}
s_filter[idx] = *filter;
filter_update(idx);
}
/**
@ -117,26 +135,35 @@ void adc_hal_digi_filter_set_factor(adc_digi_filter_idx_t idx, adc_digi_filter_t
*/
void adc_hal_digi_filter_get_factor(adc_digi_filter_idx_t idx, adc_digi_filter_t *filter)
{
adc_ll_digi_filter_get_factor(idx, filter);
if (((filter->adc_unit << 3) | filter->channel) > 9) {
filter->mode = ADC_DIGI_FILTER_DIS;
*filter = s_filter[idx];
}
void adc_hal_digi_filter_enable(adc_digi_filter_idx_t filter_idx, bool enable)
{
s_filter_enabled[filter_idx] = enable;
filter_update(filter_idx);
}
static void update_monitor(adc_digi_monitor_idx_t idx)
{
//ESP32-C3 has no enable bit, the monitor will be enabled when the monitor channel is configured
if (s_monitor_enabled[idx]) {
adc_ll_digi_monitor_set_mode(idx, &s_monitor_config[idx]);
} else {
adc_ll_digi_monitor_disable(idx);
}
}
/**
* Config monitor of adc digital controller.
*
* @note If the channel info is not supported, the monitor function will not be enabled.
* @param idx ADC monitor index.
* @param config Refer to `adc_digi_monitor_t`.
*/
void adc_hal_digi_monitor_config(adc_digi_monitor_idx_t idx, adc_digi_monitor_t *config)
{
if (config->mode == ADC_DIGI_MONITOR_DIS) {
adc_ll_digi_monitor_disable(idx);
} else {
adc_ll_digi_monitor_set_mode(idx, config);
}
s_monitor_config[idx] = *config;
update_monitor(idx);
}
void adc_hal_digi_monitor_enable(adc_digi_monitor_idx_t mon_idx, bool enable)
{
s_monitor_enabled[mon_idx] = enable;
update_monitor(mon_idx);
}
/*---------------------------------------------------------------

View File

@ -84,34 +84,53 @@ void adc_hal_digi_clk_config(const adc_digi_clk_t *clk);
/**
* Reset adc digital controller filter.
*
* @param adc_n ADC unit.
* @param filter_idx ADC filter unit.
*/
#define adc_hal_digi_filter_reset(adc_n) adc_ll_digi_filter_reset(adc_n)
#define adc_hal_digi_filter_reset(filter_idx) adc_ll_digi_filter_reset(filter_idx)
/**
* Set adc digital controller filter factor.
*
* @param idx ADC filter unit.
* @param filter_idx ADC filter unit.
* @param filter Filter config. Expression: filter_data = (k-1)/k * last_data + new_data / k. Set values: (2, 4, 8, 16, 64).
*/
void adc_hal_digi_filter_set_factor(adc_digi_filter_idx_t idx, adc_digi_filter_t *filter);
void adc_hal_digi_filter_set_factor(adc_digi_filter_idx_t filter_idx, adc_digi_filter_t *filter);
/**
* Get adc digital controller filter factor.
*
* @param adc_n ADC unit.
* @param filter_idx ADC filter unit.
* @param factor Expression: filter_data = (k-1)/k * last_data + new_data / k. Set values: (2, 4, 8, 16, 64).
*/
void adc_hal_digi_filter_get_factor(adc_digi_filter_idx_t idx, adc_digi_filter_t *filter);
void adc_hal_digi_filter_get_factor(adc_digi_filter_idx_t filter_idx, adc_digi_filter_t *filter);
/**
* Enable/disable adc digital controller filter.
* Filtering the ADC data to obtain smooth data at higher sampling rates.
*
* @note The filter will filter all the enabled channel data of the each ADC unit at the same time.
* @param filter_idx ADC filter unit.
* @param enable True to enable the filter, otherwise disable.
*/
void adc_hal_digi_filter_enable(adc_digi_filter_idx_t filter_idx, bool enable);
/**
* Config monitor of adc digital controller.
*
* @note If the channel info is not supported, the monitor function will not be enabled.
* @param idx ADC monitor index.
* @param mon_idx ADC monitor index.
* @param config Refer to `adc_digi_monitor_t`.
*/
void adc_hal_digi_monitor_config(adc_digi_monitor_idx_t idx, adc_digi_monitor_t *config);
void adc_hal_digi_monitor_config(adc_digi_monitor_idx_t mon_idx, adc_digi_monitor_t *config);
/**
* Enable/disable monitor of adc digital controller.
*
* @note The monitor will monitor all the enabled channel data of the each ADC unit at the same time.
* @param mon_idx ADC monitor index.
* @param enable True to enable the monitor, otherwise disable.
*/
void adc_hal_digi_monitor_enable(adc_digi_monitor_idx_t mon_idx, bool enable);
/**
* Enable interrupt of adc digital controller by bitmask.

View File

@ -338,7 +338,7 @@ static inline void adc_ll_digi_filter_get_factor(adc_digi_filter_idx_t idx, adc_
/**
* Disable adc digital controller filter.
* Filtering the ADC data to obtain smooth data at higher sampling rates.
*
*
* @note If the channel info is not supported, the filter function will not be enabled.
* @param adc_n ADC unit.
*/

View File

@ -107,6 +107,8 @@
#define SOC_ADC_CHANNEL_NUM(PERIPH_NUM) ((PERIPH_NUM==0)? 5 : 1)
#define SOC_ADC_MAX_CHANNEL_NUM (10)
#define SOC_ADC_MAX_BITWIDTH (12)
#define SOC_ADC_DIGI_FILTER_NUM (2)
#define SOC_ADC_DIGI_MONITOR_NUM (2)
/**
* Check if adc support digital controller (DMA) mode.