From 90fc3e7030cc44e5a54854e2332d7c35c59cb9ef Mon Sep 17 00:00:00 2001 From: "Michael (XIAO Xufeng)" Date: Thu, 7 Jan 2021 23:43:35 +0800 Subject: [PATCH] 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 --- components/driver/esp32c3/adc.c | 25 +++---- components/hal/esp32c3/adc_hal.c | 67 +++++++++++++------ components/hal/esp32c3/include/hal/adc_hal.h | 35 +++++++--- components/hal/esp32c3/include/hal/adc_ll.h | 2 +- components/soc/esp32c3/include/soc/soc_caps.h | 2 + 5 files changed, 85 insertions(+), 46 deletions(-) diff --git a/components/driver/esp32c3/adc.c b/components/driver/esp32c3/adc.c index 3123ed4a72..9fbcc3d720 100644 --- a/components/driver/esp32c3/adc.c +++ b/components/driver/esp32c3/adc.c @@ -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; } diff --git a/components/hal/esp32c3/adc_hal.c b/components/hal/esp32c3/adc_hal.c index cb41e2b39e..8f7b2678fd 100644 --- a/components/hal/esp32c3/adc_hal.c +++ b/components/hal/esp32c3/adc_hal.c @@ -14,9 +14,20 @@ // The HAL layer for ADC (ESP32-C3 specific part) +#include +#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); } /*--------------------------------------------------------------- diff --git a/components/hal/esp32c3/include/hal/adc_hal.h b/components/hal/esp32c3/include/hal/adc_hal.h index fc6a618796..0b53e44f54 100644 --- a/components/hal/esp32c3/include/hal/adc_hal.h +++ b/components/hal/esp32c3/include/hal/adc_hal.h @@ -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. diff --git a/components/hal/esp32c3/include/hal/adc_ll.h b/components/hal/esp32c3/include/hal/adc_ll.h index 59bab42995..7149f88171 100644 --- a/components/hal/esp32c3/include/hal/adc_ll.h +++ b/components/hal/esp32c3/include/hal/adc_ll.h @@ -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. */ diff --git a/components/soc/esp32c3/include/soc/soc_caps.h b/components/soc/esp32c3/include/soc/soc_caps.h index fae89b8a41..fc323730e0 100644 --- a/components/soc/esp32c3/include/soc/soc_caps.h +++ b/components/soc/esp32c3/include/soc/soc_caps.h @@ -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.