Merge branch 'bugfix/fix_adc_driver_for_esp32s2' into 'master'

Bugfix/fix adc driver for esp32s2

Closes IDF-1448, IDF-1449, IDF-1450, IDF-1451, and IDF-1458

See merge request espressif/esp-idf!7776
This commit is contained in:
Michael (XIAO Xufeng) 2020-04-02 11:02:21 +08:00
commit 15026d1b84
56 changed files with 9686 additions and 945 deletions

View file

@ -1,5 +1,5 @@
set(srcs
"adc.c"
"adc_common.c"
"can.c"
"dac.c"
"gpio.c"
@ -31,13 +31,15 @@ if(IDF_TARGET STREQUAL "esp32")
"sdio_slave.c"
"sdmmc_host.c"
"sdmmc_transaction.c"
"esp32/touch_sensor.c")
"esp32/touch_sensor.c"
"esp32/adc.c")
list(APPEND includes "esp32/include")
endif()
if(IDF_TARGET STREQUAL "esp32s2")
list(APPEND srcs "esp32s2/rtc_tempsensor.c"
"esp32s2/touch_sensor.c")
"esp32s2/touch_sensor.c"
"esp32s2/adc.c")
# currently only S2 beta has its own target-specific includes
list(APPEND includes "esp32s2/include")
endif()

View file

@ -12,8 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _DRIVER_ADC1_I2S_PRIVATE_H_
#define _DRIVER_ADC1_I2S_PRIVATE_H_
#pragma once
#ifdef __cplusplus
extern "C" {
@ -34,26 +33,26 @@ void adc_power_always_on(void);
/**
* @brief For I2S dma to claim the usage of ADC1.
*
* Other tasks will be forbidden to use ADC1 between ``adc1_i2s_mode_acquire`` and ``adc1_i2s_release``.
* Other tasks will be forbidden to use ADC1 between ``adc1_dma_mode_acquire`` and ``adc1_i2s_release``.
* The I2S module may have to wait for a short time for the current conversion (if exist) to finish.
*
* @return
* - ESP_OK success
* - ESP_ERR_TIMEOUT reserved for future use. Currently the function will wait until success.
*/
esp_err_t adc1_i2s_mode_acquire(void);
esp_err_t adc1_dma_mode_acquire(void);
/**
* @brief For ADC1 to claim the usage of ADC1.
*
* Other tasks will be forbidden to use ADC1 between ``adc1_adc_mode_acquire`` and ``adc1_i2s_release``.
* Other tasks will be forbidden to use ADC1 between ``adc1_rtc_mode_acquire`` and ``adc1_i2s_release``.
* The ADC1 may have to wait for some time for the I2S read operation to finish.
*
* @return
* - ESP_OK success
* - ESP_ERR_TIMEOUT reserved for future use. Currently the function will wait until success.
*/
esp_err_t adc1_adc_mode_acquire(void);
esp_err_t adc1_rtc_mode_acquire(void);
/**
* @brief to let other tasks use the ADC1 when I2S is not work.
@ -69,5 +68,3 @@ esp_err_t adc1_lock_release(void);
}
#endif
#endif /*_DRIVER_ADC1_I2S_PRIVATE_H_*/

View file

@ -12,8 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _DRIVER_ADC2_INTERNAL_H_
#define _DRIVER_ADC2_INTERNAL_H_
#pragma once
#ifdef __cplusplus
extern "C" {
@ -48,5 +47,3 @@ esp_err_t adc2_wifi_release(void);
}
#endif
#endif /*_DRIVER_ADC2_INTERNAL_H_*/

View file

@ -20,25 +20,18 @@
#include "freertos/semphr.h"
#include "freertos/timers.h"
#include "esp_log.h"
#include "esp_pm.h"
#include "soc/rtc.h"
#include "rtc_io.h"
#include "adc.h"
#include "dac.h"
#include "driver/dac.h"
#include "sys/lock.h"
#include "driver/gpio.h"
#include "adc1_i2s_private.h"
#include "driver/adc.h"
#include "adc1_private.h"
#include "hal/adc_types.h"
#include "hal/adc_hal.h"
#define ADC_MAX_MEAS_NUM_DEFAULT (255)
#define ADC_MEAS_NUM_LIM_DEFAULT (1)
#define SAR_ADC_CLK_DIV_DEFUALT (2)
#define DIG_ADC_OUTPUT_FORMAT_DEFUALT (ADC_DIG_FORMAT_12BIT)
#define DIG_ADC_ATTEN_DEFUALT (ADC_ATTEN_DB_11)
#define DIG_ADC_BIT_WIDTH_DEFUALT (ADC_WIDTH_BIT_12)
#define ADC_CHECK_RET(fun_ret) ({ \
if (fun_ret != ESP_OK) { \
ESP_LOGE(ADC_TAG,"%s:%d\n",__FUNCTION__,__LINE__); \
@ -65,9 +58,11 @@ extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate posi
/*
In ADC2, there're two locks used for different cases:
1. lock shared with app and WIFI:
when wifi using the ADC2, we assume it will never stop,
so app checks the lock and returns immediately if failed.
1. lock shared with app and Wi-Fi:
ESP32:
When Wi-Fi using the ADC2, we assume it will never stop, so app checks the lock and returns immediately if failed.
ESP32S2:
The controller's control over the ADC is determined by the arbiter. There is no need to control by lock.
2. lock shared between tasks:
when several tasks sharing the ADC2, we want to guarantee
@ -77,13 +72,40 @@ In ADC2, there're two locks used for different cases:
adc2_spinlock should be acquired first, then adc2_wifi_lock or rtc_spinlock.
*/
#ifdef CONFIG_IDF_TARGET_ESP32
//prevent ADC2 being used by wifi and other tasks at the same time.
static _lock_t adc2_wifi_lock;
/** For ESP32S2 the ADC2 The right to use ADC2 is controlled by the arbiter, and there is no need to set a lock. */
#define ADC2_WIFI_LOCK_ACQUIRE() _lock_acquire( &adc2_wifi_lock )
#define ADC2_WIFI_LOCK_RELEASE() _lock_release( &adc2_wifi_lock )
#define ADC2_WIFI_LOCK_TRY_ACQUIRE() _lock_try_acquire( &adc2_wifi_lock )
#define ADC2_WIFI_LOCK_CHECK() ((uint32_t *)adc2_wifi_lock != NULL)
#elif defined CONFIG_IDF_TARGET_ESP32S2
#define ADC2_WIFI_LOCK_ACQUIRE()
#define ADC2_WIFI_LOCK_RELEASE()
#define ADC2_WIFI_LOCK_TRY_ACQUIRE() (0) //WIFI controller and rtc controller have independent parameter configuration.
#define ADC2_WIFI_LOCK_CHECK() (true)
#endif
//prevent ADC2 being used by tasks (regardless of WIFI)
static portMUX_TYPE adc2_spinlock = portMUX_INITIALIZER_UNLOCKED;
#define ADC2_ENTER_CRITICAL() portENTER_CRITICAL( &adc2_spinlock )
#define ADC2_EXIT_CRITICAL() portEXIT_CRITICAL( &adc2_spinlock )
//prevent ADC1 being used by I2S dma and other tasks at the same time.
static _lock_t adc1_i2s_lock;
static _lock_t adc1_dma_lock;
#define ADC1_DMA_LOCK_ACQUIRE() _lock_acquire( &adc1_dma_lock )
#define ADC1_DMA_LOCK_RELEASE() _lock_release( &adc1_dma_lock )
#ifdef CONFIG_IDF_TARGET_ESP32S2
#ifdef CONFIG_PM_ENABLE
static esp_pm_lock_handle_t s_adc2_arbiter_lock;
#endif //CONFIG_PM_ENABLE
#endif //CONFIG_IDF_TARGET_ESP32S2
/*---------------------------------------------------------------
ADC Common
---------------------------------------------------------------*/
@ -121,16 +143,7 @@ void adc_power_off(void)
esp_err_t adc_set_clk_div(uint8_t clk_div)
{
ADC_ENTER_CRITICAL();
adc_hal_set_clk_div(clk_div);
ADC_EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t adc_set_i2s_data_source(adc_i2s_source_t src)
{
ADC_CHECK(src < ADC_I2S_DATA_SRC_MAX, "ADC i2s data source error", ESP_ERR_INVALID_ARG);
ADC_ENTER_CRITICAL();
adc_hal_dig_set_data_source(src);
adc_hal_digi_set_clk_div(clk_div);
ADC_EXIT_CRITICAL();
return ESP_OK;
}
@ -141,18 +154,14 @@ esp_err_t adc_gpio_init(adc_unit_t adc_unit, adc_channel_t channel)
if (adc_unit & ADC_UNIT_1) {
ADC_CHANNEL_CHECK(ADC_NUM_1, channel);
gpio_num = ADC_GET_IO_NUM(ADC_NUM_1, channel);
ADC_CHECK_RET(rtc_gpio_init(gpio_num));
ADC_CHECK_RET(rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_DISABLED));
ADC_CHECK_RET(gpio_set_pull_mode(gpio_num, GPIO_FLOATING));
}
if (adc_unit & ADC_UNIT_2) {
ADC_CHANNEL_CHECK(ADC_NUM_2, channel);
gpio_num = ADC_GET_IO_NUM(ADC_NUM_2, channel);
ADC_CHECK_RET(rtc_gpio_init(gpio_num));
ADC_CHECK_RET(rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_DISABLED));
ADC_CHECK_RET(gpio_set_pull_mode(gpio_num, GPIO_FLOATING));
}
ADC_CHECK_RET(rtc_gpio_init(gpio_num));
ADC_CHECK_RET(rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_DISABLED));
ADC_CHECK_RET(gpio_set_pull_mode(gpio_num, GPIO_FLOATING));
return ESP_OK;
}
@ -160,18 +169,24 @@ esp_err_t adc_set_data_inv(adc_unit_t adc_unit, bool inv_en)
{
ADC_ENTER_CRITICAL();
if (adc_unit & ADC_UNIT_1) {
adc_hal_output_invert(ADC_NUM_1, inv_en);
adc_hal_rtc_output_invert(ADC_NUM_1, inv_en);
}
if (adc_unit & ADC_UNIT_2) {
adc_hal_output_invert(ADC_NUM_1, inv_en);
adc_hal_rtc_output_invert(ADC_NUM_1, inv_en);
}
ADC_EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t adc_set_data_width(adc_unit_t adc_unit, adc_bits_width_t bits)
{
ADC_CHECK(bits < ADC_WIDTH_MAX, "ADC bit width error", ESP_ERR_INVALID_ARG);
#ifdef CONFIG_IDF_TARGET_ESP32
ADC_CHECK(bits < ADC_WIDTH_MAX, "WIDTH ERR: ESP32 support 9 ~ 12 bit width", ESP_ERR_INVALID_ARG);
#elif defined CONFIG_IDF_TARGET_ESP32S2
ADC_CHECK(bits == ADC_WIDTH_BIT_13, "WIDTH ERR: ESP32S2 support 13 bit width", ESP_ERR_INVALID_ARG);
#endif
ADC_ENTER_CRITICAL();
if (adc_unit & ADC_UNIT_1) {
adc_hal_rtc_set_output_format(ADC_NUM_1, bits);
@ -181,68 +196,41 @@ esp_err_t adc_set_data_width(adc_unit_t adc_unit, adc_bits_width_t bits)
adc_hal_pwdet_set_cct(SOC_ADC_PWDET_CCT_DEFAULT);
}
ADC_EXIT_CRITICAL();
return ESP_OK;
}
/* this function should be called in the critical section. */
static int adc_convert(adc_ll_num_t adc_n, int channel)
/**
* @brief Reset RTC controller FSM.
*
* @return
* - ESP_OK Success
*/
#ifdef CONFIG_IDF_TARGET_ESP32S2
esp_err_t adc_rtc_reset(void)
{
return adc_hal_convert(adc_n, channel);
}
/*-------------------------------------------------------------------------------------
* ADC I2S
*------------------------------------------------------------------------------------*/
esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel)
{
if (adc_unit & ADC_UNIT_1) {
ADC_CHECK((SOC_ADC_SUPPORT_DMA_MODE(ADC_NUM_1)), "ADC1 not support DMA for now.", ESP_ERR_INVALID_ARG);
ADC_CHANNEL_CHECK(ADC_NUM_1, channel);
}
if (adc_unit & ADC_UNIT_2) {
ADC_CHECK((SOC_ADC_SUPPORT_DMA_MODE(ADC_NUM_2)), "ADC2 not support DMA for now.", ESP_ERR_INVALID_ARG);
ADC_CHANNEL_CHECK(ADC_NUM_2, channel);
}
adc_ll_pattern_table_t adc1_pattern[1];
adc_ll_pattern_table_t adc2_pattern[1];
adc_hal_dig_config_t dig_cfg = {
.conv_limit_en = ADC_MEAS_NUM_LIM_DEFAULT,
.conv_limit_num = ADC_MAX_MEAS_NUM_DEFAULT,
.clk_div = SAR_ADC_CLK_DIV_DEFUALT,
.format = DIG_ADC_OUTPUT_FORMAT_DEFUALT,
.conv_mode = (adc_ll_convert_mode_t)adc_unit,
};
if (adc_unit & ADC_UNIT_1) {
adc1_pattern[0].atten = DIG_ADC_ATTEN_DEFUALT;
adc1_pattern[0].bit_width = DIG_ADC_BIT_WIDTH_DEFUALT;
adc1_pattern[0].channel = channel;
dig_cfg.adc1_pattern_len = 1;
dig_cfg.adc1_pattern = adc1_pattern;
}
if (adc_unit & ADC_UNIT_2) {
adc2_pattern[0].atten = DIG_ADC_ATTEN_DEFUALT;
adc2_pattern[0].bit_width = DIG_ADC_BIT_WIDTH_DEFUALT;
adc2_pattern[0].channel = channel;
dig_cfg.adc2_pattern_len = 1;
dig_cfg.adc2_pattern = adc2_pattern;
}
ADC_ENTER_CRITICAL();
adc_hal_init();
adc_hal_dig_controller_config(&dig_cfg);
adc_hal_rtc_reset();
ADC_EXIT_CRITICAL();
return ESP_OK;
}
static inline void adc_set_init_code(adc_ll_num_t adc_n, adc_channel_t channel)
{
adc_atten_t atten = adc_hal_get_atten(adc_n, channel);
uint32_t cal_val = adc_hal_calibration(adc_n, channel, atten, true, false);
adc_hal_set_calibration_param(adc_n, cal_val);
ESP_LOGD(ADC_TAG, "Set cal adc %d\n", cal_val);
}
#endif
/*-------------------------------------------------------------------------------------
* ADC1
*------------------------------------------------------------------------------------*/
esp_err_t adc1_pad_get_io_num(adc1_channel_t channel, gpio_num_t *gpio_num)
{
ADC_CHANNEL_CHECK(ADC_NUM_1, channel);
int io = ADC_GET_IO_NUM(ADC_NUM_1, channel);
if (io < 0) {
return ESP_ERR_INVALID_ARG;
@ -257,71 +245,91 @@ esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten)
{
ADC_CHANNEL_CHECK(ADC_NUM_1, channel);
ADC_CHECK(atten < ADC_ATTEN_MAX, "ADC Atten Err", ESP_ERR_INVALID_ARG);
adc_gpio_init(ADC_UNIT_1, channel);
ADC_ENTER_CRITICAL();
adc_hal_set_atten(ADC_NUM_1, channel, atten);
ADC_EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t adc1_config_width(adc_bits_width_t width_bit)
{
ADC_CHECK(width_bit < ADC_WIDTH_MAX, "ADC bit width error", ESP_ERR_INVALID_ARG);
#ifdef CONFIG_IDF_TARGET_ESP32
ADC_CHECK(width_bit < ADC_WIDTH_MAX, "WIDTH ERR: ESP32 support 9 ~ 12 bit width", ESP_ERR_INVALID_ARG);
#elif defined CONFIG_IDF_TARGET_ESP32S2
ADC_CHECK(width_bit == ADC_WIDTH_BIT_13, "WIDTH ERR: ESP32S2 support 13 bit width", ESP_ERR_INVALID_ARG);
#endif
ADC_ENTER_CRITICAL();
adc_hal_rtc_set_output_format(ADC_NUM_1, width_bit);
adc_hal_output_invert(ADC_NUM_1, true);
adc_hal_rtc_output_invert(ADC_NUM_1, SOC_ADC1_DATA_INVERT_DEFAULT);
adc_hal_set_sar_clk_div(ADC_NUM_1, SOC_ADC_SAR_CLK_DIV_DEFAULT(ADC_NUM_1));
ADC_EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t adc1_i2s_mode_acquire(void)
esp_err_t adc1_dma_mode_acquire(void)
{
/* Use locks to avoid digtal and RTC controller conflicts.
for adc1, block until acquire the lock. */
_lock_acquire( &adc1_i2s_lock );
ESP_LOGD( ADC_TAG, "i2s mode takes adc1 lock." );
ADC1_DMA_LOCK_ACQUIRE();
ESP_LOGD( ADC_TAG, "dma mode takes adc1 lock." );
ADC_ENTER_CRITICAL();
adc_hal_set_power_manage(ADC_POWER_SW_ON);
/* switch SARADC into DIG channel */
adc_hal_set_controller(ADC_NUM_1, ADC_CTRL_DIG);
ADC_EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t adc1_adc_mode_acquire(void)
esp_err_t adc1_rtc_mode_acquire(void)
{
/* Use locks to avoid digtal and RTC controller conflicts.
for adc1, block until acquire the lock. */
_lock_acquire( &adc1_i2s_lock );
ADC1_DMA_LOCK_ACQUIRE();
ADC_ENTER_CRITICAL();
/* switch SARADC into RTC channel. */
adc_hal_set_controller(ADC_NUM_1, ADC_CTRL_RTC);
ADC_EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t adc1_lock_release(void)
{
ADC_CHECK((uint32_t *)adc1_i2s_lock != NULL, "adc1 lock release called before acquire", ESP_ERR_INVALID_STATE );
/* Use locks to avoid digtal and RTC controller conflicts.
for adc1, block until acquire the lock. */
_lock_release( &adc1_i2s_lock );
ADC_CHECK((uint32_t *)adc1_dma_lock != NULL, "adc1 lock release called before acquire", ESP_ERR_INVALID_STATE );
/* Use locks to avoid digtal and RTC controller conflicts. for adc1, block until acquire the lock. */
ADC1_DMA_LOCK_RELEASE();
return ESP_OK;
}
int adc1_get_raw(adc1_channel_t channel)
{
uint16_t adc_value;
int adc_value;
ADC_CHANNEL_CHECK(ADC_NUM_1, channel);
adc1_adc_mode_acquire();
adc1_rtc_mode_acquire();
adc_power_on();
ADC_ENTER_CRITICAL();
/* disable other peripherals. */
adc_hal_hall_disable();
/* currently the LNA is not open, close it by default. */
adc_hal_amp_disable();
/* set controller */
adc_hal_set_controller(ADC_NUM_1, ADC_CTRL_RTC);
/* start conversion */
adc_value = adc_convert(ADC_NUM_1, channel);
#ifdef CONFIG_IDF_TARGET_ESP32
adc_hal_hall_disable(); //Disable other peripherals.
adc_hal_amp_disable(); //Currently the LNA is not open, close it by default.
#endif
#ifdef CONFIG_IDF_TARGET_ESP32S2
adc_set_init_code(ADC_NUM_1, channel); // calibration for adc
#endif
adc_hal_set_controller(ADC_NUM_1, ADC_CTRL_RTC); //Set controller
adc_hal_convert(ADC_NUM_1, channel, &adc_value); //Start conversion, For ADC1, the data always valid.
ADC_EXIT_CRITICAL();
#ifdef CONFIG_IDF_TARGET_ESP32S2
adc_hal_rtc_reset(); //Reset FSM of rtc controller
#endif
adc1_lock_release();
return adc_value;
@ -340,9 +348,11 @@ void adc1_ulp_enable(void)
adc_hal_set_controller(ADC_NUM_1, ADC_CTRL_ULP);
/* since most users do not need LNA and HALL with uLP, we disable them here
open them in the uLP if needed. */
#ifdef CONFIG_IDF_TARGET_ESP32
/* disable other peripherals. */
adc_hal_hall_disable();
adc_hal_amp_disable();
#endif
ADC_EXIT_CRITICAL();
}
@ -352,6 +362,7 @@ void adc1_ulp_enable(void)
esp_err_t adc2_pad_get_io_num(adc2_channel_t channel, gpio_num_t *gpio_num)
{
ADC_CHANNEL_CHECK(ADC_NUM_2, channel);
int io = ADC_GET_IO_NUM(ADC_NUM_2, channel);
if (io < 0) {
return ESP_ERR_INVALID_ARG;
@ -362,20 +373,21 @@ esp_err_t adc2_pad_get_io_num(adc2_channel_t channel, gpio_num_t *gpio_num)
return ESP_OK;
}
/** For ESP32S2 the ADC2 The right to use ADC2 is controlled by the arbiter, and there is no need to set a lock.*/
esp_err_t adc2_wifi_acquire(void)
{
/* Wi-Fi module will use adc2. Use locks to avoid conflicts. */
_lock_acquire( &adc2_wifi_lock );
ADC2_WIFI_LOCK_ACQUIRE();
ESP_LOGD( ADC_TAG, "Wi-Fi takes adc2 lock." );
return ESP_OK;
}
esp_err_t adc2_wifi_release(void)
{
ADC_CHECK((uint32_t *)adc2_wifi_lock != NULL, "wifi release called before acquire", ESP_ERR_INVALID_STATE );
_lock_release( &adc2_wifi_lock );
ADC_CHECK(ADC2_WIFI_LOCK_CHECK(), "wifi release called before acquire", ESP_ERR_INVALID_STATE );
ADC2_WIFI_LOCK_RELEASE();
ESP_LOGD( ADC_TAG, "Wi-Fi returns adc2 lock." );
return ESP_OK;
}
@ -395,119 +407,123 @@ esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten)
ADC_CHECK(atten <= ADC_ATTEN_11db, "ADC2 Atten Err", ESP_ERR_INVALID_ARG);
adc2_pad_init(channel);
portENTER_CRITICAL( &adc2_spinlock );
//lazy initialization
ADC2_ENTER_CRITICAL();
//avoid collision with other tasks
if ( _lock_try_acquire( &adc2_wifi_lock ) == -1 ) {
if ( ADC2_WIFI_LOCK_TRY_ACQUIRE() == -1 ) {
//try the lock, return if failed (wifi using).
portEXIT_CRITICAL( &adc2_spinlock );
ADC2_EXIT_CRITICAL();
return ESP_ERR_TIMEOUT;
}
adc_hal_set_atten(ADC_NUM_2, channel, atten);
_lock_release( &adc2_wifi_lock );
ADC2_WIFI_LOCK_RELEASE();
ADC2_EXIT_CRITICAL();
portEXIT_CRITICAL( &adc2_spinlock );
return ESP_OK;
}
static inline void adc2_config_width(adc_bits_width_t width_bit)
{
#ifdef CONFIG_IDF_TARGET_ESP32S2
#ifdef CONFIG_PM_ENABLE
/* Lock APB clock. */
if (s_adc2_arbiter_lock == NULL) {
esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "adc2", &s_adc2_arbiter_lock);
}
#endif //CONFIG_PM_ENABLE
#endif //CONFIG_IDF_TARGET_ESP32S2
ADC_ENTER_CRITICAL();
adc_hal_rtc_set_output_format(ADC_NUM_2, width_bit);
adc_hal_pwdet_set_cct(SOC_ADC_PWDET_CCT_DEFAULT);
adc_hal_output_invert(ADC_NUM_2, true);
adc_hal_rtc_output_invert(ADC_NUM_2, SOC_ADC2_DATA_INVERT_DEFAULT);
adc_hal_set_sar_clk_div(ADC_NUM_2, SOC_ADC_SAR_CLK_DIV_DEFAULT(ADC_NUM_2));
ADC_EXIT_CRITICAL();
}
static inline void adc2_dac_disable( adc2_channel_t channel)
{
#ifdef CONFIG_IDF_TARGET_ESP32
if ( channel == ADC2_CHANNEL_8 ) { // the same as DAC channel 1
dac_output_disable(DAC_CHANNEL_1);
} else if ( channel == ADC2_CHANNEL_9 ) {
dac_output_disable(DAC_CHANNEL_2);
}
#elif defined CONFIG_IDF_TARGET_ESP32S2
if ( channel == ADC2_CHANNEL_6 ) { // the same as DAC channel 1
dac_output_disable(DAC_CHANNEL_1);
} else if ( channel == ADC2_CHANNEL_7 ) {
dac_output_disable(DAC_CHANNEL_2);
}
#endif
}
//registers in critical section with adc1:
//SENS_SAR_START_FORCE_REG,
/**
* @note For ESP32S2:
* The arbiter's working clock is APB_CLK. When the APB_CLK clock drops below 8 MHz, the arbiter must be in shield mode.
* Or, the RTC controller will fail when get raw data.
* This issue does not occur on digital controllers (DMA mode), and the hardware guarantees that there will be no errors.
*/
esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *raw_out)
{
uint16_t adc_value = 0;
int adc_value = 0;
ADC_CHECK(raw_out != NULL, "ADC out value err", ESP_ERR_INVALID_ARG);
ADC_CHECK(channel < ADC2_CHANNEL_MAX, "ADC Channel Err", ESP_ERR_INVALID_ARG);
#ifdef CONFIG_IDF_TARGET_ESP32
ADC_CHECK(width_bit < ADC_WIDTH_MAX, "WIDTH ERR: ESP32 support 9 ~ 12 bit width", ESP_ERR_INVALID_ARG);
#elif defined CONFIG_IDF_TARGET_ESP32S2
ADC_CHECK(width_bit == ADC_WIDTH_BIT_13, "WIDTH ERR: ESP32S2 support 13 bit width", ESP_ERR_INVALID_ARG);
#endif
//in critical section with whole rtc module
adc_power_on();
adc_power_on(); //in critical section with whole rtc module
//avoid collision with other tasks
portENTER_CRITICAL(&adc2_spinlock);
//lazy initialization
//try the lock, return if failed (wifi using).
if ( _lock_try_acquire( &adc2_wifi_lock ) == -1 ) {
portEXIT_CRITICAL( &adc2_spinlock );
ADC2_ENTER_CRITICAL(); //avoid collision with other tasks
if ( ADC2_WIFI_LOCK_TRY_ACQUIRE() == -1 ) { //try the lock, return if failed (wifi using).
ADC2_EXIT_CRITICAL();
return ESP_ERR_TIMEOUT;
}
//disable other peripherals
#ifdef CONFIG_ADC_DISABLE_DAC
adc2_dac_disable(channel);
adc2_dac_disable(channel); //disable other peripherals
#endif
// set controller
// in critical section with whole rtc module
// because the PWDET use the same registers, place it here.
adc2_config_width(width_bit);
adc_hal_set_controller(ADC_NUM_2, ADC_CTRL_RTC);
//start converting
adc_value = adc_convert(ADC_NUM_2, channel);
_lock_release( &adc2_wifi_lock );
portEXIT_CRITICAL(&adc2_spinlock);
adc2_config_width(width_bit); // in critical section with whole rtc module. because the PWDET use the same registers, place it here.
#ifdef CONFIG_IDF_TARGET_ESP32S2
adc_set_init_code(ADC_NUM_2, channel); // calibration for adc
#endif
adc_hal_set_controller(ADC_NUM_2, ADC_CTRL_RTC);// set controller
*raw_out = (int)adc_value;
#ifdef CONFIG_IDF_TARGET_ESP32S2
#ifdef CONFIG_PM_ENABLE
if (s_adc2_arbiter_lock) {
esp_pm_lock_acquire(s_adc2_arbiter_lock);
}
#endif //CONFIG_PM_ENABLE
#endif //CONFIG_IDF_TARGET_ESP32
if (adc_hal_convert(ADC_NUM_2, channel, &adc_value)) {
adc_value = -1;
}
#ifdef CONFIG_IDF_TARGET_ESP32S2
#ifdef CONFIG_PM_ENABLE
/* Release APB clock. */
if (s_adc2_arbiter_lock) {
esp_pm_lock_release(s_adc2_arbiter_lock);
}
#endif //CONFIG_PM_ENABLE
#endif //CONFIG_IDF_TARGET_ESP32
ADC2_WIFI_LOCK_RELEASE();
ADC2_EXIT_CRITICAL();
#ifdef CONFIG_IDF_TARGET_ESP32S2
adc_rtc_reset();
#endif
if (adc_value < 0) {
ESP_LOGD( ADC_TAG, "ADC2 ARB: Return data is invalid." );
return ESP_ERR_INVALID_STATE;
}
*raw_out = adc_value;
return ESP_OK;
}
esp_err_t adc2_vref_to_gpio(gpio_num_t gpio)
{
adc_power_always_on(); //Select power source of ADC
if (adc_hal_vref_output(gpio) != true) {
return ESP_ERR_INVALID_ARG;
} else {
//Configure RTC gpio
rtc_gpio_init(gpio);
rtc_gpio_set_direction(gpio, RTC_GPIO_MODE_DISABLED);
rtc_gpio_pullup_dis(gpio);
rtc_gpio_pulldown_dis(gpio);
return ESP_OK;
}
}
/*---------------------------------------------------------------
HALL SENSOR
---------------------------------------------------------------*/
static int hall_sensor_get_value(void) //hall sensor without LNA
{
int hall_value;
adc_power_on();
ADC_ENTER_CRITICAL();
/* disable other peripherals. */
adc_hal_amp_disable();
adc_hal_hall_enable();
// set controller
adc_hal_set_controller( ADC_NUM_1, ADC_CTRL_RTC );
hall_value = adc_hal_hall_convert();
ADC_EXIT_CRITICAL();
return hall_value;
}
int hall_sensor_read(void)
{
adc_gpio_init(ADC_NUM_1, ADC1_CHANNEL_0);
adc_gpio_init(ADC_NUM_1, ADC1_CHANNEL_3);
adc1_config_channel_atten(ADC1_CHANNEL_0, ADC_ATTEN_DB_0);
adc1_config_channel_atten(ADC1_CHANNEL_3, ADC_ATTEN_DB_0);
return hall_sensor_get_value();
}

View file

@ -3,7 +3,7 @@
#
COMPONENT_SRCDIRS := . $(IDF_TARGET)
COMPONENT_ADD_INCLUDEDIRS := include $(IDF_TARGET)/include
COMPONENT_ADD_INCLUDEDIRS := include $(IDF_TARGET)/include $(IDF_TARGET)/include/driver
COMPONENT_PRIV_INCLUDEDIRS := include/driver

View file

@ -0,0 +1,181 @@
// Copyright 2016-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <esp_types.h>
#include <stdlib.h>
#include <ctype.h>
#include "esp_log.h"
#include "sys/lock.h"
#include "soc/rtc.h"
#include "soc/periph_defs.h"
#include "freertos/FreeRTOS.h"
#include "freertos/xtensa_api.h"
#include "freertos/semphr.h"
#include "freertos/timers.h"
#include "esp_intr_alloc.h"
#include "driver/rtc_io.h"
#include "driver/rtc_cntl.h"
#include "driver/gpio.h"
#include "driver/adc.h"
#include "sdkconfig.h"
#include "esp32/rom/ets_sys.h"
#ifndef NDEBUG
// Enable built-in checks in queue.h in debug builds
#define INVARIANTS
#endif
#include "sys/queue.h"
#include "hal/adc_types.h"
#include "hal/adc_hal.h"
#define ADC_MAX_MEAS_NUM_DEFAULT (255)
#define ADC_MEAS_NUM_LIM_DEFAULT (1)
#define SAR_ADC_CLK_DIV_DEFUALT (2)
#define DIG_ADC_OUTPUT_FORMAT_DEFUALT (ADC_DIGI_FORMAT_12BIT)
#define DIG_ADC_ATTEN_DEFUALT (ADC_ATTEN_DB_11)
#define DIG_ADC_BIT_WIDTH_DEFUALT (ADC_WIDTH_BIT_12)
#define ADC_CHECK_RET(fun_ret) ({ \
if (fun_ret != ESP_OK) { \
ESP_LOGE(ADC_TAG,"%s:%d\n",__FUNCTION__,__LINE__); \
return ESP_FAIL; \
} \
})
static const char *ADC_TAG = "ADC";
#define ADC_CHECK(a, str, ret_val) ({ \
if (!(a)) { \
ESP_LOGE(ADC_TAG,"%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str); \
return (ret_val); \
} \
})
#define ADC_GET_IO_NUM(periph, channel) (adc_channel_io_map[periph][channel])
#define ADC_CHANNEL_CHECK(periph, channel) ADC_CHECK(channel < SOC_ADC_CHANNEL_NUM(periph), "ADC"#periph" channel error", ESP_ERR_INVALID_ARG)
extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished.
#define ADC_ENTER_CRITICAL() portENTER_CRITICAL(&rtc_spinlock)
#define ADC_EXIT_CRITICAL() portEXIT_CRITICAL(&rtc_spinlock)
/*---------------------------------------------------------------
Digital controller setting
---------------------------------------------------------------*/
esp_err_t adc_set_i2s_data_source(adc_i2s_source_t src)
{
ADC_CHECK(src < ADC_I2S_DATA_SRC_MAX, "ADC i2s data source error", ESP_ERR_INVALID_ARG);
ADC_ENTER_CRITICAL();
adc_hal_digi_set_data_source(src);
ADC_EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel)
{
if (adc_unit & ADC_UNIT_1) {
ADC_CHECK((SOC_ADC_SUPPORT_DMA_MODE(ADC_NUM_1)), "ADC1 not support DMA for now.", ESP_ERR_INVALID_ARG);
ADC_CHANNEL_CHECK(ADC_NUM_1, channel);
}
if (adc_unit & ADC_UNIT_2) {
ADC_CHECK((SOC_ADC_SUPPORT_DMA_MODE(ADC_NUM_2)), "ADC2 not support DMA for now.", ESP_ERR_INVALID_ARG);
ADC_CHANNEL_CHECK(ADC_NUM_2, channel);
}
adc_hal_digi_pattern_table_t adc1_pattern[1];
adc_hal_digi_pattern_table_t adc2_pattern[1];
adc_hal_digi_config_t dig_cfg = {
.conv_limit_en = ADC_MEAS_NUM_LIM_DEFAULT,
.conv_limit_num = ADC_MAX_MEAS_NUM_DEFAULT,
.clk_div = SAR_ADC_CLK_DIV_DEFUALT,
.format = DIG_ADC_OUTPUT_FORMAT_DEFUALT,
.conv_mode = (adc_hal_digi_convert_mode_t)adc_unit,
};
if (adc_unit & ADC_UNIT_1) {
adc1_pattern[0].atten = DIG_ADC_ATTEN_DEFUALT;
adc1_pattern[0].bit_width = DIG_ADC_BIT_WIDTH_DEFUALT;
adc1_pattern[0].channel = channel;
dig_cfg.adc1_pattern_len = 1;
dig_cfg.adc1_pattern = adc1_pattern;
}
if (adc_unit & ADC_UNIT_2) {
adc2_pattern[0].atten = DIG_ADC_ATTEN_DEFUALT;
adc2_pattern[0].bit_width = DIG_ADC_BIT_WIDTH_DEFUALT;
adc2_pattern[0].channel = channel;
dig_cfg.adc2_pattern_len = 1;
dig_cfg.adc2_pattern = adc2_pattern;
}
ADC_ENTER_CRITICAL();
adc_hal_digi_init();
adc_hal_digi_controller_config(&dig_cfg);
ADC_EXIT_CRITICAL();
return ESP_OK;
}
/*---------------------------------------------------------------
RTC controller setting
---------------------------------------------------------------*/
esp_err_t adc2_vref_to_gpio(gpio_num_t gpio)
{
ADC_ENTER_CRITICAL();
adc_hal_set_power_manage(ADC_POWER_SW_ON);
ADC_EXIT_CRITICAL();
if (adc_hal_vref_output(gpio) != true) {
return ESP_ERR_INVALID_ARG;
}
//Configure RTC gpio
rtc_gpio_init(gpio);
rtc_gpio_set_direction(gpio, RTC_GPIO_MODE_DISABLED);
rtc_gpio_pullup_dis(gpio);
rtc_gpio_pulldown_dis(gpio);
return ESP_OK;
}
/*---------------------------------------------------------------
HALL SENSOR
---------------------------------------------------------------*/
static int hall_sensor_get_value(void) //hall sensor without LNA
{
int hall_value;
adc_power_on();
ADC_ENTER_CRITICAL();
/* disable other peripherals. */
adc_hal_amp_disable();
adc_hal_hall_enable();
// set controller
adc_hal_set_controller( ADC_NUM_1, ADC_CTRL_RTC );
hall_value = adc_hal_hall_convert();
ADC_EXIT_CRITICAL();
return hall_value;
}
int hall_sensor_read(void)
{
adc_gpio_init(ADC_UNIT_1, ADC1_CHANNEL_0);
adc_gpio_init(ADC_UNIT_1, ADC1_CHANNEL_3);
adc1_config_channel_atten(ADC1_CHANNEL_0, ADC_ATTEN_DB_0);
adc1_config_channel_atten(ADC1_CHANNEL_3, ADC_ATTEN_DB_0);
return hall_sensor_get_value();
}

View file

@ -0,0 +1,88 @@
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include "driver/adc_common.h"
#ifdef __cplusplus
extern "C" {
#endif
/*---------------------------------------------------------------
Digital controller setting
---------------------------------------------------------------*/
/**
* @brief Set I2S data source
* @param src I2S DMA data source, I2S DMA can get data from digital signals or from ADC.
* @return
* - ESP_OK success
*/
esp_err_t adc_set_i2s_data_source(adc_i2s_source_t src);
/**
* @brief Initialize I2S ADC mode
* @param adc_unit ADC unit index
* @param channel ADC channel index
* @return
* - ESP_OK success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel);
/*---------------------------------------------------------------
RTC controller setting
---------------------------------------------------------------*/
/**
* @brief Output ADC2 reference voltage to GPIO 25 or 26 or 27
*
* This function utilizes the testing mux exclusive to ADC 2 to route the
* reference voltage one of ADC2's channels. Supported GPIOs are GPIOs
* 25, 26, and 27. This refernce voltage can be manually read from the pin
* and used in the esp_adc_cal component.
*
* @param[in] gpio GPIO number (GPIOs 25, 26 and 27 are supported)
*
* @return
* - ESP_OK: v_ref successfully routed to selected GPIO
* - ESP_ERR_INVALID_ARG: Unsupported GPIO
*/
esp_err_t adc2_vref_to_gpio(gpio_num_t gpio);
/**
* @brief Read Hall Sensor
*
* @note When the power switch of SARADC1, SARADC2, HALL sensor and AMP sensor is turned on,
* the input of GPIO36 and GPIO39 will be pulled down for about 80ns.
* When enabling power for any of these peripherals, ignore input from GPIO36 and GPIO39.
* Please refer to section 3.11 of 'ECO_and_Workarounds_for_Bugs_in_ESP32' for the description of this issue.
*
* @note The Hall Sensor uses channels 0 and 3 of ADC1. Do not configure
* these channels for use as ADC channels.
*
* @note The ADC1 module must be enabled by calling
* adc1_config_width() before calling hall_sensor_read(). ADC1
* should be configured for 12 bit readings, as the hall sensor
* readings are low values and do not cover the full range of the
* ADC.
*
* @return The hall sensor reading.
*/
int hall_sensor_read(void);
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,380 @@
// Copyright 2016-2018 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <esp_types.h>
#include <stdlib.h>
#include <ctype.h>
#include "esp_log.h"
#include "sys/lock.h"
#include "freertos/FreeRTOS.h"
#include "freertos/xtensa_api.h"
#include "freertos/semphr.h"
#include "freertos/timers.h"
#include "esp_intr_alloc.h"
#include "driver/periph_ctrl.h"
#include "driver/rtc_io.h"
#include "driver/rtc_cntl.h"
#include "driver/gpio.h"
#include "driver/adc.h"
#include "sdkconfig.h"
#include "esp32s2/rom/ets_sys.h"
#include "hal/adc_types.h"
#include "hal/adc_hal.h"
#define ADC_CHECK_RET(fun_ret) ({ \
if (fun_ret != ESP_OK) { \
ESP_LOGE(ADC_TAG,"%s:%d\n",__FUNCTION__,__LINE__); \
return ESP_FAIL; \
} \
})
static const char *ADC_TAG = "ADC";
#define ADC_CHECK(a, str, ret_val) ({ \
if (!(a)) { \
ESP_LOGE(ADC_TAG,"%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str); \
return (ret_val); \
} \
})
#define ADC_GET_IO_NUM(periph, channel) (adc_channel_io_map[periph][channel])
#define ADC_CHANNEL_CHECK(periph, channel) ADC_CHECK(channel < SOC_ADC_CHANNEL_NUM(periph), "ADC"#periph" channel error", ESP_ERR_INVALID_ARG)
extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished.
#define ADC_ENTER_CRITICAL() portENTER_CRITICAL(&rtc_spinlock)
#define ADC_EXIT_CRITICAL() portEXIT_CRITICAL(&rtc_spinlock)
/*---------------------------------------------------------------
Digital controller setting
---------------------------------------------------------------*/
esp_err_t adc_digi_init(void)
{
adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT();
ADC_ENTER_CRITICAL();
adc_hal_digi_init();
adc_hal_arbiter_config(&config);
ADC_EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t adc_digi_deinit(void)
{
ADC_ENTER_CRITICAL();
adc_hal_digi_init();
ADC_EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t adc_digi_controller_config(const adc_digi_config_t *config)
{
ADC_ENTER_CRITICAL();
adc_hal_digi_controller_config(config);
ADC_EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t adc_arbiter_config(adc_unit_t adc_unit, adc_arbiter_t *config)
{
if (adc_unit & ADC_UNIT_1) {
return ESP_ERR_NOT_SUPPORTED;
}
ADC_ENTER_CRITICAL();
adc_hal_arbiter_config(config);
ADC_EXIT_CRITICAL();
return ESP_OK;
}
/**
* @brief Set ADC module controller.
* There are five SAR ADC controllers:
* Two digital controller: Continuous conversion mode (DMA). High performance with multiple channel scan modes;
* Two RTC controller: Single conversion modes (Polling). For low power purpose working during deep sleep;
* the other is dedicated for Power detect (PWDET / PKDET), Only support ADC2.
*
* @note Only ADC2 support arbiter to switch controllers automatically. Access to the ADC is based on the priority of the controller.
* @note For ADC1, Controller access is mutually exclusive.
*
* @param adc_unit ADC unit.
* @param ctrl ADC controller, Refer to `adc_controller_t`.
*
* @return
* - ESP_OK Success
*/
esp_err_t adc_set_controller(adc_unit_t adc_unit, adc_controller_t ctrl)
{
adc_arbiter_t config = {0};
adc_arbiter_t cfg = ADC_ARBITER_CONFIG_DEFAULT();
if (adc_unit & ADC_UNIT_1) {
adc_hal_set_controller(ADC_NUM_1, ctrl);
}
if (adc_unit & ADC_UNIT_2) {
adc_hal_set_controller(ADC_NUM_2, ctrl);
switch (ctrl) {
case ADC2_CTRL_FORCE_PWDET:
config.pwdet_pri = 2;
config.mode = ADC_ARB_MODE_SHIELD;
adc_hal_arbiter_config(&config);
adc_hal_set_controller(ADC_NUM_2, ADC2_CTRL_PWDET);
break;
case ADC2_CTRL_FORCE_RTC:
config.rtc_pri = 2;
config.mode = ADC_ARB_MODE_SHIELD;
adc_hal_arbiter_config(&config);
adc_hal_set_controller(ADC_NUM_2, ADC_CTRL_RTC);
break;
case ADC2_CTRL_FORCE_ULP:
config.rtc_pri = 2;
config.mode = ADC_ARB_MODE_SHIELD;
adc_hal_arbiter_config(&config);
adc_hal_set_controller(ADC_NUM_2, ADC_CTRL_ULP);
break;
case ADC2_CTRL_FORCE_DIG:
config.dig_pri = 2;
config.mode = ADC_ARB_MODE_SHIELD;
adc_hal_arbiter_config(&config);
adc_hal_set_controller(ADC_NUM_2, ADC_CTRL_DIG);
break;
default:
adc_hal_arbiter_config(&cfg);
break;
}
}
return ESP_OK;
}
esp_err_t adc_digi_start(void)
{
ADC_ENTER_CRITICAL();
adc_hal_digi_enable();
ADC_EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t adc_digi_stop(void)
{
ADC_ENTER_CRITICAL();
adc_hal_digi_disable();
ADC_EXIT_CRITICAL();
return ESP_OK;
}
/**
* @brief Reset FSM of adc digital controller.
*
* @return
* - ESP_OK Success
*/
esp_err_t adc_digi_reset(void)
{
ADC_ENTER_CRITICAL();
adc_hal_digi_reset();
adc_hal_digi_clear_pattern_table(ADC_NUM_1);
adc_hal_digi_clear_pattern_table(ADC_NUM_2);
ADC_EXIT_CRITICAL();
return ESP_OK;
}
/*************************************/
/* Digital controller filter setting */
/*************************************/
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_EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t adc_digi_filter_set_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config)
{
ADC_ENTER_CRITICAL();
if (idx == ADC_DIGI_FILTER_IDX0) {
adc_hal_digi_filter_set_factor(ADC_NUM_1, config->mode);
} else if (idx == ADC_DIGI_FILTER_IDX1) {
adc_hal_digi_filter_set_factor(ADC_NUM_2, config->mode);
}
ADC_EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t adc_digi_filter_get_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config)
{
ADC_ENTER_CRITICAL();
if (idx == ADC_DIGI_FILTER_IDX0) {
config->adc_unit = ADC_UNIT_1;
config->channel = ADC_CHANNEL_MAX;
adc_hal_digi_filter_get_factor(ADC_NUM_1, &config->mode);
} else if (idx == ADC_DIGI_FILTER_IDX1) {
config->adc_unit = ADC_UNIT_2;
config->channel = ADC_CHANNEL_MAX;
adc_hal_digi_filter_get_factor(ADC_NUM_2, &config->mode);
}
ADC_EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t adc_digi_filter_enable(adc_digi_filter_idx_t idx, bool enable)
{
ADC_ENTER_CRITICAL();
if (idx == ADC_DIGI_FILTER_IDX0) {
adc_hal_digi_filter_enable(ADC_NUM_1, enable);
} else if (idx == ADC_DIGI_FILTER_IDX1) {
adc_hal_digi_filter_enable(ADC_NUM_2, 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.
*
* @note For ESP32S2, The filter will filter all the enabled channel data of the each ADC unit at the same time.
* @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)
{
if (idx == ADC_DIGI_FILTER_IDX0) {
return adc_hal_digi_filter_read_data(ADC_NUM_1);
} else if (idx == ADC_DIGI_FILTER_IDX1) {
return adc_hal_digi_filter_read_data(ADC_NUM_2);
} else {
return -1;
}
}
/**************************************/
/* Digital controller monitor setting */
/**************************************/
esp_err_t adc_digi_monitor_set_config(adc_digi_monitor_idx_t idx, adc_digi_monitor_t *config)
{
ADC_ENTER_CRITICAL();
if (idx == ADC_DIGI_MONITOR_IDX0) {
adc_hal_digi_monitor_config(ADC_NUM_1, config);
} else if (idx == ADC_DIGI_MONITOR_IDX1) {
adc_hal_digi_monitor_config(ADC_NUM_2, config);
}
ADC_EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t adc_digi_monitor_enable(adc_digi_monitor_idx_t idx, bool enable)
{
ADC_ENTER_CRITICAL();
if (idx == ADC_DIGI_MONITOR_IDX0) {
adc_hal_digi_monitor_enable(ADC_NUM_1, enable);
} else if (idx == ADC_DIGI_MONITOR_IDX1) {
adc_hal_digi_monitor_enable(ADC_NUM_2, enable);
}
ADC_EXIT_CRITICAL();
return ESP_OK;
}
/**************************************/
/* Digital controller intr setting */
/**************************************/
esp_err_t adc_digi_intr_enable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask)
{
ADC_ENTER_CRITICAL();
if (adc_unit & ADC_UNIT_1) {
adc_hal_digi_intr_enable(ADC_NUM_1, intr_mask);
}
if (adc_unit & ADC_UNIT_2) {
adc_hal_digi_intr_enable(ADC_NUM_2, intr_mask);
}
ADC_EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t adc_digi_intr_disable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask)
{
ADC_ENTER_CRITICAL();
if (adc_unit & ADC_UNIT_1) {
adc_hal_digi_intr_disable(ADC_NUM_1, intr_mask);
}
if (adc_unit & ADC_UNIT_2) {
adc_hal_digi_intr_disable(ADC_NUM_2, intr_mask);
}
ADC_EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t adc_digi_intr_clear(adc_unit_t adc_unit, adc_digi_intr_t intr_mask)
{
ADC_ENTER_CRITICAL();
if (adc_unit & ADC_UNIT_1) {
adc_hal_digi_intr_clear(ADC_NUM_1, intr_mask);
}
if (adc_unit & ADC_UNIT_2) {
adc_hal_digi_intr_clear(ADC_NUM_2, intr_mask);
}
ADC_EXIT_CRITICAL();
return ESP_OK;
}
uint32_t adc_digi_intr_get_status(adc_unit_t adc_unit)
{
uint32_t ret = 0;
ADC_ENTER_CRITICAL();
if (adc_unit & ADC_UNIT_1) {
ret = adc_hal_digi_get_intr_status(ADC_NUM_1);
}
if (adc_unit & ADC_UNIT_2) {
ret = adc_hal_digi_get_intr_status(ADC_NUM_2);
}
ADC_EXIT_CRITICAL();
return ret;
}
static uint8_t s_isr_registered = 0;
static intr_handle_t s_adc_isr_handle = NULL;
esp_err_t adc_digi_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags)
{
ADC_CHECK((fn != NULL), "Parameter error", ESP_ERR_INVALID_ARG);
ADC_CHECK(s_isr_registered == 0, "ADC ISR have installed, can not install again", ESP_FAIL);
esp_err_t ret = esp_intr_alloc(ETS_APB_ADC_INTR_SOURCE, intr_alloc_flags, fn, arg, &s_adc_isr_handle);
if (ret == ESP_OK) {
s_isr_registered = 1;
}
return ret;
}
esp_err_t adc_digi_isr_deregister(void)
{
esp_err_t ret = ESP_FAIL;
if (s_isr_registered) {
ret = esp_intr_free(s_adc_isr_handle);
if (ret == ESP_OK) {
s_isr_registered = 0;
}
}
return ret;
}
/*---------------------------------------------------------------
RTC controller setting
---------------------------------------------------------------*/

View file

@ -0,0 +1,277 @@
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include "driver/adc_common.h"
#ifdef __cplusplus
extern "C" {
#endif
/*---------------------------------------------------------------
Common setting
---------------------------------------------------------------*/
/**
* @brief Config ADC module arbiter.
* The arbiter is to improve the use efficiency of ADC2. After the control right is robbed by the high priority,
* the low priority controller will read the invalid ADC2 data, and the validity of the data can be judged by the flag bit in the data.
*
* @note Only ADC2 support arbiter.
* @note Default priority: Wi-Fi > RTC > Digital;
* @note In normal use, there is no need to call this interface to config arbiter.
*
* @param adc_unit ADC unit.
* @param config Refer to `adc_arbiter_t`.
*
* @return
* - ESP_OK Success
* - ESP_ERR_NOT_SUPPORTED ADC unit not support arbiter.
*/
esp_err_t adc_arbiter_config(adc_unit_t adc_unit, adc_arbiter_t *config);
/*---------------------------------------------------------------
Digital controller setting
---------------------------------------------------------------*/
/**
* @brief ADC digital controller initialization.
* @return
* - ESP_OK Success
*/
esp_err_t adc_digi_init(void);
/**
* @brief ADC digital controller deinitialization.
* @return
* - ESP_OK Success
*/
esp_err_t adc_digi_deinit(void);
/**
* @brief Setting the digital controller.
*
* @param config Pointer to digital controller paramter. Refer to `adc_digi_config_t`.
*
* @return
* - ESP_OK Success
*/
esp_err_t adc_digi_controller_config(const adc_digi_config_t *config);
/**
* @brief Enable digital controller to trigger the measurement.
*
* @return
* - ESP_OK Success
*/
esp_err_t adc_digi_start(void);
/**
* @brief Disable digital controller to trigger the measurement.
*
* @return
* - ESP_OK Success
*/
esp_err_t adc_digi_stop(void);
/*************************************/
/* Digital controller filter setting */
/*************************************/
/**
* @brief Reset adc digital controller filter.
*
* @param idx Filter index.
*
* @return
* - ESP_OK Success
*/
esp_err_t adc_digi_filter_reset(adc_digi_filter_idx_t idx);
/**
* @brief Set adc digital controller filter configuration.
*
* @note For ESP32S2, Filter IDX0/IDX1 can only be used to filter all enabled channels of ADC1/ADC2 unit at the same time.
*
* @param idx Filter index.
* @param config See ``adc_digi_filter_t``.
*
* @return
* - ESP_OK Success
*/
esp_err_t adc_digi_filter_set_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config);
/**
* @brief Get adc digital controller filter configuration.
*
* @note For ESP32S2, Filter IDX0/IDX1 can only be used to filter all enabled channels of ADC1/ADC2 unit at the same time.
*
* @param idx Filter index.
* @param config See ``adc_digi_filter_t``.
*
* @return
* - ESP_OK Success
*/
esp_err_t adc_digi_filter_get_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config);
/**
* @brief Enable/disable adc digital controller filter.
* Filtering the ADC data to obtain smooth data at higher sampling rates.
*
* @note For ESP32S2, Filter IDX0/IDX1 can only be used to filter all enabled channels of ADC1/ADC2 unit at the same time.
*
* @param idx Filter index.
* @param enable Enable/Disable filter.
*
* @return
* - ESP_OK Success
*/
esp_err_t adc_digi_filter_enable(adc_digi_filter_idx_t idx, bool enable);
/**************************************/
/* Digital controller monitor setting */
/**************************************/
/**
* @brief Config monitor of adc digital controller.
*
* @note For ESP32S2, The monitor will monitor all the enabled channel data of the each ADC unit at the same time.
*
* @param idx Monitor index.
* @param config See ``adc_digi_monitor_t``.
*
* @return
* - ESP_OK Success
*/
esp_err_t adc_digi_monitor_set_config(adc_digi_monitor_idx_t idx, adc_digi_monitor_t *config);
/**
* @brief Enable/disable monitor of adc digital controller.
*
* @note For ESP32S2, The monitor will monitor all the enabled channel data of the each ADC unit at the same time.
*
* @param idx Monitor index.
* @param enable True or false enable monitor.
*
* @return
* - ESP_OK Success
*/
esp_err_t adc_digi_monitor_enable(adc_digi_monitor_idx_t idx, bool enable);
/**************************************/
/* Digital controller intr setting */
/**************************************/
/**
* @brief Enable interrupt of adc digital controller by bitmask.
*
* @param adc_unit ADC unit.
* @param intr_mask Interrupt bitmask. See ``adc_digi_intr_t``.
*
* @return
* - ESP_OK Success
*/
esp_err_t adc_digi_intr_enable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask);
/**
* @brief Disable interrupt of adc digital controller by bitmask.
*
* @param adc_unit ADC unit.
* @param intr_mask Interrupt bitmask. See ``adc_digi_intr_t``.
*
* @return
* - ESP_OK Success
*/
esp_err_t adc_digi_intr_disable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask);
/**
* @brief Clear interrupt of adc digital controller by bitmask.
*
* @param adc_unit ADC unit.
* @param intr_mask Interrupt bitmask. See ``adc_digi_intr_t``.
*
* @return
* - ESP_OK Success
*/
esp_err_t adc_digi_intr_clear(adc_unit_t adc_unit, adc_digi_intr_t intr_mask);
/**
* @brief Get interrupt status mask of adc digital controller.
*
* @param adc_unit ADC unit.
* @return
* - intr Interrupt bitmask, See ``adc_digi_intr_t``.
*/
uint32_t adc_digi_intr_get_status(adc_unit_t adc_unit);
/**
* @brief Register ADC interrupt handler, the handler is an ISR.
* The handler will be attached to the same CPU core that this function is running on.
*
* @param fn Interrupt handler function.
* @param arg Parameter for handler function
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
*
* @return
* - ESP_OK Success
* - ESP_ERR_NOT_FOUND Can not find the interrupt that matches the flags.
* - ESP_ERR_INVALID_ARG Function pointer error.
*/
esp_err_t adc_digi_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags);
/**
* @brief Deregister ADC interrupt handler, the handler is an ISR.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG hander error.
* - ESP_FAIL ISR not be registered.
*/
esp_err_t adc_digi_isr_deregister(void);
/*---------------------------------------------------------------
RTC controller setting
---------------------------------------------------------------*/
/*---------------------------------------------------------------
Deprecated API
---------------------------------------------------------------*/
/**
* @brief Set I2S data source
*
* @param src I2S DMA data source, I2S DMA can get data from digital signals or from ADC.
*
* @deprecated The ESP32S2 don't use I2S DMA. Call ``adc_digi_controller_config`` instead.
*
* @return
* - ESP_OK success
*/
esp_err_t adc_set_i2s_data_source(adc_i2s_source_t src) __attribute__((deprecated));
/**
* @brief Initialize I2S ADC mode
*
* @param adc_unit ADC unit index
* @param channel ADC channel index
*
* @deprecated The ESP32S2 don't use I2S DMA. Call ``adc_digi_controller_config`` instead.
*
* @return
* - ESP_OK success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel) __attribute__((deprecated));
#ifdef __cplusplus
}
#endif

View file

@ -21,6 +21,9 @@
extern "C" {
#endif
/**
* @brief temperature sensor range option.
*/
typedef enum {
TSENS_DAC_L0 = 0, /*!< offset = -2, measure range: 50℃ ~ 125℃, error < 3℃. */
TSENS_DAC_L1, /*!< offset = -1, measure range: 20℃ ~ 100℃, error < 2℃. */
@ -39,6 +42,9 @@ typedef struct {
uint8_t clk_div; /*!< Default: 6 */
} temp_sensor_config_t;
/**
* @brief temperature sensor default setting.
*/
#define TSENS_CONFIG_DEFAULT() {.dac_offset = TSENS_DAC_L2, \
.clk_div = 6}
@ -74,7 +80,7 @@ esp_err_t temp_sensor_start(void);
esp_err_t temp_sensor_stop(void);
/**
* @brief Read temperature sensor raw data.
* @brief Read temperature sensor raw data.
* @param tsens_out Pointer to raw data, Range: 0 ~ 255
* @return
* - ESP_OK Success

View file

@ -233,7 +233,7 @@ esp_err_t touch_pad_isr_register(intr_handler_t fn, void *arg, touch_pad_intr_ma
*
* @param enable true(default): Enable the timeout check; false: Disable the timeout check.
* @param threshold For all channels, the maximum value that will not be exceeded during normal operation.
*
*
* @return
* - ESP_OK Success
*/
@ -244,7 +244,7 @@ esp_err_t touch_pad_timeout_set(bool enable, uint32_t threshold);
* If this API is not called, the touch FSM will stop the measurement after timeout interrupt.
*
* @note Call this API after finishes the exception handling by user.
*
*
* @return
* - ESP_OK Success
*/
@ -491,7 +491,7 @@ esp_err_t touch_pad_sleep_channel_get_info(touch_pad_sleep_channel_t *slp_config
* e.g. The user should uses `touch_pad_sleep_channel_read_data` instead of `touch_pad_read_raw_data` to obtain the sleep channel reading.
*
* @param pad_num Set touch channel number for sleep pad. Only one touch sensor channel is supported in deep sleep mode.
* @param enable true: enable sleep pad for touch sensor; false: disable sleep pad for touch sensor;
* @param enable true: enable sleep pad for touch sensor; false: disable sleep pad for touch sensor;
* @return
* - ESP_OK Success
*/
@ -502,9 +502,9 @@ esp_err_t touch_pad_sleep_channel_enable(touch_pad_t pad_num, bool enable);
* The touch sensor can works in sleep mode to wake up sleep.
*
* @note ESP32S2 only support one sleep channel.
*
*
* @param pad_num Set touch channel number for sleep pad. Only one touch sensor channel is supported in deep sleep mode.
* @param enable true: enable proximity for sleep channel; false: disable proximity for sleep channel;
* @param enable true: enable proximity for sleep channel; false: disable proximity for sleep channel;
* @return
* - ESP_OK Success
*/
@ -515,7 +515,7 @@ esp_err_t touch_pad_sleep_channel_enable_proximity(touch_pad_t pad_num, bool ena
* The threshold determines the sensitivity of the touch sensor.
*
* @note In general, the touch threshold during sleep can use the threshold parameter parameters before sleep.
*
*
* @param pad_num Set touch channel number for sleep pad. Only one touch sensor channel is supported in deep sleep mode.
* @param touch_thres touch sleep pad threshold
* @return
@ -528,7 +528,7 @@ esp_err_t touch_pad_sleep_set_threshold(touch_pad_t pad_num, uint32_t touch_thre
* The threshold determines the sensitivity of the touch sensor.
*
* @note In general, the touch threshold during sleep can use the threshold parameter parameters before sleep.
*
*
* @param pad_num Set touch channel number for sleep pad. Only one touch sensor channel is supported in deep sleep mode.
* @param touch_thres touch sleep pad threshold
* @return

View file

@ -18,11 +18,12 @@
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "esp_log.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/rtc_io_reg.h"
#include "soc/rtc_io_struct.h"
#include "soc/sens_reg.h"
#include "soc/sens_struct.h"
#include "temp_sensor.h"
#include "driver/temp_sensor.h"
#include "esp32s2/rom/ets_sys.h"
static const char *TAG = "tsens";
@ -38,6 +39,18 @@ static const char *TAG = "tsens";
#define TSENS_DAC_FACTOR (27.88)
#define TSENS_SYS_OFFSET (20.52)
#include "i2c_rtc_clk.h"
#define ANA_CONFIG2_REG 0x6000E048
#define ANA_CONFIG2_M (BIT(18))
#define I2C_ADC 0X69
#define I2C_ADC_HOSTID 1
#define I2C_SARADC_TSENS_DAC 6
#define I2C_SARADC_TSENS_DAC_MSB 3
#define I2C_SARADC_TSENS_DAC_LSB 0
typedef struct {
int index;
int offset;
@ -60,7 +73,11 @@ static SemaphoreHandle_t rtc_tsens_mux = NULL;
esp_err_t temp_sensor_set_config(temp_sensor_config_t tsens)
{
// SENS.sar_tctrl.tsens_dac = dac_offset[tsens.dac_offset].set_val; // TODO: others MR resolve it.
CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_FORCE_PD_M);
SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_FORCE_PU_M);
CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, BIT(18));
SET_PERI_REG_MASK(ANA_CONFIG2_REG, BIT(16));
I2C_WRITEREG_MASK_RTC(I2C_ADC, I2C_SARADC_TSENS_DAC, dac_offset[tsens.dac_offset].set_val);
SENS.sar_tctrl.tsens_clk_div = tsens.clk_div;
SENS.sar_tctrl.tsens_power_up_force = 1;
SENS.sar_tctrl2.tsens_xpd_wait = TSENS_XPD_WAIT_DEFAULT;
@ -77,9 +94,13 @@ esp_err_t temp_sensor_set_config(temp_sensor_config_t tsens)
esp_err_t temp_sensor_get_config(temp_sensor_config_t *tsens)
{
TSENS_CHECK(tsens != NULL, ESP_ERR_INVALID_ARG);
// tsens->dac_offset = SENS.sar_tctrl.tsens_dac; // TODO: others MR resolve it.
for(int i=TSENS_DAC_L0; i<TSENS_DAC_MAX; i++) {
if(tsens->dac_offset == dac_offset[i].set_val) {
CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_FORCE_PD_M);
SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_FORCE_PU_M);
CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, BIT(18));
SET_PERI_REG_MASK(ANA_CONFIG2_REG, BIT(16));
tsens->dac_offset = I2C_READREG_MASK_RTC(I2C_ADC, I2C_SARADC_TSENS_DAC);
for (int i = TSENS_DAC_L0; i < TSENS_DAC_MAX; i++) {
if (tsens->dac_offset == dac_offset[i].set_val) {
tsens->dac_offset = dac_offset[i].index;
break;
}

View file

@ -28,7 +28,7 @@
#if SOC_I2S_SUPPORTS_ADC_DAC
#include "driver/dac.h"
#include "hal/i2s_hal.h"
#include "adc1_i2s_private.h"
#include "adc1_private.h"
#endif
#include "esp_intr_alloc.h"
@ -1061,7 +1061,7 @@ esp_err_t i2s_adc_enable(i2s_port_t i2s_num)
I2S_CHECK((p_i2s_obj[i2s_num] != NULL), "Not initialized yet", ESP_ERR_INVALID_STATE);
I2S_CHECK((p_i2s_obj[i2s_num]->mode & I2S_MODE_ADC_BUILT_IN), "i2s built-in adc not enabled", ESP_ERR_INVALID_STATE);
adc1_i2s_mode_acquire();
adc1_dma_mode_acquire();
_i2s_adc_mode_recover();
i2s_hal_start_rx(&(p_i2s_obj[i2s_num]->hal));
i2s_hal_reset(&(p_i2s_obj[i2s_num]->hal));

View file

@ -12,30 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _DRIVER_ADC_H_
#define _DRIVER_ADC_H_
#ifdef __cplusplus
extern "C" {
#endif
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "esp_err.h"
#include "driver/gpio.h"
#include "soc/adc_periph.h"
#include "hal/adc_types.h"
//this definitions are only for being back-compatible
#define ADC_ATTEN_0db ADC_ATTEN_DB_0
#define ADC_ATTEN_2_5db ADC_ATTEN_DB_2_5
#define ADC_ATTEN_6db ADC_ATTEN_DB_6
#define ADC_ATTEN_11db ADC_ATTEN_DB_11
//this definitions are only for being back-compatible
#define ADC_WIDTH_9Bit ADC_WIDTH_BIT_9
#define ADC_WIDTH_10Bit ADC_WIDTH_BIT_10
#define ADC_WIDTH_11Bit ADC_WIDTH_BIT_11
#define ADC_WIDTH_12Bit ADC_WIDTH_BIT_12
#ifdef __cplusplus
extern "C" {
#endif
/**** `adc1_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/
typedef enum {
@ -71,17 +58,29 @@ typedef enum {
ADC2_CHANNEL_MAX,
} adc2_channel_t;
typedef enum {
ADC_UNIT_1 = 1, /*!< SAR ADC 1*/
ADC_UNIT_2 = 2, /*!< SAR ADC 2, not supported yet*/
ADC_UNIT_BOTH = 3, /*!< SAR ADC 1 and 2, not supported yet */
ADC_UNIT_ALTER = 7, /*!< SAR ADC 1 and 2 alternative mode, not supported yet */
ADC_UNIT_MAX,
} adc_unit_t;
/**
* @brief ADC rtc controller attenuation option.
*
* @note This definitions are only for being back-compatible
*/
#define ADC_ATTEN_0db ADC_ATTEN_DB_0
#define ADC_ATTEN_2_5db ADC_ATTEN_DB_2_5
#define ADC_ATTEN_6db ADC_ATTEN_DB_6
#define ADC_ATTEN_11db ADC_ATTEN_DB_11
//this definitions are only for being back-compatible
#define ADC_WIDTH_9Bit ADC_WIDTH_BIT_9
#define ADC_WIDTH_10Bit ADC_WIDTH_BIT_10
#define ADC_WIDTH_11Bit ADC_WIDTH_BIT_11
#define ADC_WIDTH_12Bit ADC_WIDTH_BIT_12
/**
* @brief ADC digital controller encode option.
*
* @deprecated The ESP32S2 don't use I2S DMA. Call ``adc_digi_output_format_t`` instead.
*/
typedef enum {
ADC_ENCODE_12BIT, /*!< ADC to I2S data format, [15:12]-channel [11:0]-12 bits ADC data */
ADC_ENCODE_11BIT, /*!< ADC to I2S data format, [15]-1 [14:11]-channel [10:0]-11 bits ADC data */
ADC_ENCODE_12BIT, /*!< ADC to DMA data format, , [15:12]-channel [11:0]-12 bits ADC data */
ADC_ENCODE_11BIT, /*!< ADC to DMA data format, [15]-unit, [14:11]-channel [10:0]-11 bits ADC data */
ADC_ENCODE_MAX,
} adc_i2s_encode_t;
@ -89,7 +88,6 @@ typedef enum {
* @brief Get the GPIO number of a specific ADC1 channel.
*
* @param channel Channel to get the GPIO number
*
* @param gpio_num output buffer to hold the GPIO number
*
* @return
@ -99,60 +97,38 @@ typedef enum {
esp_err_t adc1_pad_get_io_num(adc1_channel_t channel, gpio_num_t *gpio_num);
/**
* @brief Configure ADC1 capture width, meanwhile enable output invert for ADC1.
* The configuration is for all channels of ADC1
* @param width_bit Bit capture width for ADC1
* @brief Set the attenuation of a particular channel on ADC1, and configure its associated GPIO pin mux.
*
* @return
* - ESP_OK success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t adc1_config_width(adc_bits_width_t width_bit);
/**
* @brief Configure ADC capture width.
* @param adc_unit ADC unit index
* @param width_bit Bit capture width for ADC unit.
* @return
* - ESP_OK success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t adc_set_data_width(adc_unit_t adc_unit, adc_bits_width_t width_bit);
/**
* @brief Set the attenuation of a particular channel on ADC1, and configure its
* associated GPIO pin mux.
* The default ADC full-scale voltage is 1.1 V. To read higher voltages (up to the pin maximum voltage,
* usually 3.3 V) requires setting >0 dB signal attenuation for that ADC channel.
*
* @note For any given channel, this function must be called before the first time
* adc1_get_raw() is called for that channel.
* When VDD_A is 3.3 V:
*
* @note This function can be called multiple times to configure multiple
* ADC channels simultaneously. adc1_get_raw() can then be called for any configured
* channel.
* - 0 dB attenuation (ADC_ATTEN_DB_0) gives full-scale voltage 1.1 V
* - 2.5 dB attenuation (ADC_ATTEN_DB_2_5) gives full-scale voltage 1.5 V
* - 6 dB attenuation (ADC_ATTEN_DB_6) gives full-scale voltage 2.2 V
* - 11 dB attenuation (ADC_ATTEN_DB_11) gives full-scale voltage 3.9 V (see note below)
*
* The default ADC full-scale voltage is 1.1 V. To read higher voltages (up to the pin maximum voltage,
* usually 3.3 V) requires setting >0 dB signal attenuation for that ADC channel.
*
* When VDD_A is 3.3 V:
*
* - 0 dB attenuation (ADC_ATTEN_DB_0) gives full-scale voltage 1.1 V
* - 2.5 dB attenuation (ADC_ATTEN_DB_2_5) gives full-scale voltage 1.5 V
* - 6 dB attenuation (ADC_ATTEN_DB_6) gives full-scale voltage 2.2 V
* - 11 dB attenuation (ADC_ATTEN_DB_11) gives full-scale voltage 3.9 V (see note below)
*
* @note The full-scale voltage is the voltage corresponding to a maximum reading (depending on ADC1 configured
* bit width, this value is: 4095 for 12-bits, 2047 for 11-bits, 1023 for 10-bits, 511 for 9 bits.)
* @note The full-scale voltage is the voltage corresponding to a maximum reading (depending on ADC1 configured bit width,
* this value in ESP32 is: 4095 for 12-bits, 2047 for 11-bits, 1023 for 10-bits, 511 for 9 bits.
* this value in ESP32S2 is: 8191 for 13-bits.)
*
* @note At 11 dB attenuation the maximum voltage is limited by VDD_A, not the full scale voltage.
*
* Due to ADC characteristics, most accurate results are obtained within the following approximate voltage ranges:
* @note For ESP32:
* Due to ADC characteristics, most accurate results are obtained within the following approximate voltage ranges:
*
* - 0 dB attenuation (ADC_ATTEN_DB_0) between 100 and 950 mV
* - 2.5 dB attenuation (ADC_ATTEN_DB_2_5) between 100 and 1250 mV
* - 6 dB attenuation (ADC_ATTEN_DB_6) between 150 to 1750 mV
* - 11 dB attenuation (ADC_ATTEN_DB_11) between 150 to 2450 mV
* - 0 dB attenuation (ADC_ATTEN_DB_0) between 100 and 950 mV
* - 2.5 dB attenuation (ADC_ATTEN_DB_2_5) between 100 and 1250 mV
* - 6 dB attenuation (ADC_ATTEN_DB_6) between 150 to 1750 mV
* - 11 dB attenuation (ADC_ATTEN_DB_11) between 150 to 2450 mV
*
* For maximum accuracy, use the ADC calibration APIs and measure voltages within these recommended ranges.
* For maximum accuracy, use the ADC calibration APIs and measure voltages within these recommended ranges.
*
* @note For any given channel, this function must be called before the first time ``adc1_get_raw()`` is called for that channel.
*
* @note This function can be called multiple times to configure multiple
* ADC channels simultaneously. ``adc1_get_raw()`` can then be called for any configured channel.
*
* @param channel ADC1 channel to configure
* @param atten Attenuation level
@ -163,19 +139,31 @@ esp_err_t adc_set_data_width(adc_unit_t adc_unit, adc_bits_width_t width_bit);
*/
esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten);
/**
* @brief Configure ADC1 capture width, meanwhile enable output invert for ADC1.
* The configuration is for all channels of ADC1
* @param width_bit Bit capture width for ADC1
*
* @return
* - ESP_OK success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t adc1_config_width(adc_bits_width_t width_bit);
/**
* @brief Take an ADC1 reading from a single channel.
* @note When the power switch of SARADC1, SARADC2, HALL sensor and AMP sensor is turned on,
* @note ESP32:
* When the power switch of SARADC1, SARADC2, HALL sensor and AMP sensor is turned on,
* the input of GPIO36 and GPIO39 will be pulled down for about 80ns.
* When enabling power for any of these peripherals, ignore input from GPIO36 and GPIO39.
* Please refer to section 3.11 of 'ECO_and_Workarounds_for_Bugs_in_ESP32' for the description of this issue.
*
* @note Call adc1_config_width() before the first time this
* function is called.
* function is called.
*
* @note For any given channel, adc1_config_channel_atten(channel)
* must be called before the first time this function is called. Configuring
* a new channel does not prevent a previously configured channel from being read.
* must be called before the first time this function is called. Configuring
* a new channel does not prevent a previously configured channel from being read.
*
* @param channel ADC1 channel to read
*
@ -225,22 +213,18 @@ esp_err_t adc_set_data_inv(adc_unit_t adc_unit, bool inv_en);
esp_err_t adc_set_clk_div(uint8_t clk_div);
/**
* @brief Set I2S data source
* @param src I2S DMA data source, I2S DMA can get data from digital signals or from ADC.
* @return
* - ESP_OK success
*/
esp_err_t adc_set_i2s_data_source(adc_i2s_source_t src);
/**
* @brief Initialize I2S ADC mode
* @brief Configure ADC capture width.
*
* @note For ESP32S2, only support ``ADC_WIDTH_BIT_13``.
*
* @param adc_unit ADC unit index
* @param channel ADC channel index
* @param width_bit Bit capture width for ADC unit. For ESP32S2, only support ``ADC_WIDTH_BIT_13``.
*
* @return
* - ESP_OK success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel);
esp_err_t adc_set_data_width(adc_unit_t adc_unit, adc_bits_width_t width_bit);
/**
* @brief Configure ADC1 to be usable by the ULP
@ -253,27 +237,6 @@ esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel);
*/
void adc1_ulp_enable(void);
/**
* @brief Read Hall Sensor
*
* @note When the power switch of SARADC1, SARADC2, HALL sensor and AMP sensor is turned on,
* the input of GPIO36 and GPIO39 will be pulled down for about 80ns.
* When enabling power for any of these peripherals, ignore input from GPIO36 and GPIO39.
* Please refer to section 3.11 of 'ECO_and_Workarounds_for_Bugs_in_ESP32' for the description of this issue.
*
* @note The Hall Sensor uses channels 0 and 3 of ADC1. Do not configure
* these channels for use as ADC channels.
*
* @note The ADC1 module must be enabled by calling
* adc1_config_width() before calling hall_sensor_read(). ADC1
* should be configured for 12 bit readings, as the hall sensor
* readings are low values and do not cover the full range of the
* ADC.
*
* @return The hall sensor reading.
*/
int hall_sensor_read(void);
/**
* @brief Get the GPIO number of a specific ADC2 channel.
*
@ -290,23 +253,24 @@ esp_err_t adc2_pad_get_io_num(adc2_channel_t channel, gpio_num_t *gpio_num);
/**
* @brief Configure the ADC2 channel, including setting attenuation.
*
* The default ADC full-scale voltage is 1.1 V. To read higher voltages (up to the pin maximum voltage,
* usually 3.3 V) requires setting >0 dB signal attenuation for that ADC channel.
*
* When VDD_A is 3.3 V:
*
* - 0 dB attenuation (ADC_ATTEN_0db) gives full-scale voltage 1.1 V
* - 2.5 dB attenuation (ADC_ATTEN_2_5db) gives full-scale voltage 1.5 V
* - 6 dB attenuation (ADC_ATTEN_6db) gives full-scale voltage 2.2 V
* - 11 dB attenuation (ADC_ATTEN_11db) gives full-scale voltage 3.9 V (see note below)
*
* @note This function also configures the input GPIO pin mux to
* connect it to the ADC2 channel. It must be called before calling
* ``adc2_get_raw()`` for this channel.
*
* The default ADC full-scale voltage is 1.1 V. To read higher voltages (up to the pin maximum voltage,
* usually 3.3 V) requires setting >0 dB signal attenuation for that ADC channel.
*
* When VDD_A is 3.3 V:
*
* - 0 dB attenuation (ADC_ATTEN_0db) gives full-scale voltage 1.1 V
* - 2.5 dB attenuation (ADC_ATTEN_2_5db) gives full-scale voltage 1.5 V
* - 6 dB attenuation (ADC_ATTEN_6db) gives full-scale voltage 2.2 V
* - 11 dB attenuation (ADC_ATTEN_11db) gives full-scale voltage 3.9 V (see note below)
* connect it to the ADC2 channel. It must be called before calling
* ``adc2_get_raw()`` for this channel.
*
* @note The full-scale voltage is the voltage corresponding to a maximum reading
* (depending on ADC2 configured bit width, this value is: 4095 for 12-bits, 2047
* for 11-bits, 1023 for 10-bits, 511 for 9 bits.)
* (depending on ADC2 configured bit width,
* this value of ESP32 is: 4095 for 12-bits, 2047 for 11-bits, 1023 for 10-bits, 511 for 9 bits.
* this value of ESP32S2 is: 8191 for 13-bits.)
*
* @note At 11 dB attenuation the maximum voltage is limited by VDD_A, not the full scale voltage.
*
@ -322,46 +286,32 @@ esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten);
/**
* @brief Take an ADC2 reading on a single channel
*
* @note When the power switch of SARADC1, SARADC2, HALL sensor and AMP sensor is turned on,
* @note ESP32:
* When the power switch of SARADC1, SARADC2, HALL sensor and AMP sensor is turned on,
* the input of GPIO36 and GPIO39 will be pulled down for about 80ns.
* When enabling power for any of these peripherals, ignore input from GPIO36 and GPIO39.
* Please refer to section 3.11 of 'ECO_and_Workarounds_for_Bugs_in_ESP32' for the description of this issue.
*
* @note For a given channel, ``adc2_config_channel_atten()``
* must be called before the first time this function is called. If Wi-Fi is started via ``esp_wifi_start()``, this
* function will always fail with ``ESP_ERR_TIMEOUT``.
* @note ESP32:
* For a given channel, ``adc2_config_channel_atten()``
* must be called before the first time this function is called. If Wi-Fi is started via ``esp_wifi_start()``, this
* function will always fail with ``ESP_ERR_TIMEOUT``.
*
* @param channel ADC2 channel to read
*
* @param width_bit Bit capture width for ADC2
* @note ESP32S2:
* ADC2 support hardware arbiter. The arbiter is to improve the use efficiency of ADC2. After the control right is robbed by the high priority,
* the low priority controller will read the invalid ADC2 data. Default priority: Wi-Fi > RTC > Digital;
*
* @param channel ADC2 channel to read
* @param width_bit Bit capture width for ADC2. For ESP32S2, only support ``ADC_WIDTH_BIT_13``.
* @param raw_out the variable to hold the output data.
*
* @return
* - ESP_OK if success
* - ESP_ERR_TIMEOUT the WIFI is started, using the ADC2
* - ESP_ERR_TIMEOUT ADC2 is being used by other controller and the request timed out.
* - ESP_ERR_INVALID_STATE The controller status is invalid. Please try again.
*/
esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *raw_out);
/**
* @brief Output ADC2 reference voltage to GPIO 25 or 26 or 27
*
* This function utilizes the testing mux exclusive to ADC 2 to route the
* reference voltage one of ADC2's channels. Supported GPIOs are GPIOs
* 25, 26, and 27. This refernce voltage can be manually read from the pin
* and used in the esp_adc_cal component.
*
* @param[in] gpio GPIO number (GPIOs 25, 26 and 27 are supported)
*
* @return
* - ESP_OK: v_ref successfully routed to selected GPIO
* - ESP_ERR_INVALID_ARG: Unsupported GPIO
*/
esp_err_t adc2_vref_to_gpio(gpio_num_t gpio);
#ifdef __cplusplus
}
#endif
#endif /*_DRIVER_ADC_H_*/

View file

@ -24,7 +24,7 @@ extern "C" {
#include "hal/dac_types.h"
/**
* @brief Get the gpio number of a specific DAC channel.
* @brief Get the GPIO number of a specific DAC channel.
*
* @param channel Channel to get the gpio number
* @param gpio_num output buffer to hold the gpio number

View file

@ -14,4 +14,4 @@
#pragma once
#include "touch_sensor.h"
#include "driver/touch_sensor.h"

View file

@ -1,3 +1,3 @@
idf_component_register(SRC_DIRS . param_test touch_sensor_test
idf_component_register(SRC_DIRS . param_test touch_sensor_test adc_dma_test dac_dma_test
PRIV_INCLUDE_DIRS include param_test/include
PRIV_REQUIRES unity test_utils driver nvs_flash esp_serial_slave_link infrared_tools)
PRIV_REQUIRES unity test_utils driver nvs_flash esp_serial_slave_link infrared_tools)

View file

@ -0,0 +1,142 @@
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*
Tests for the adc device driver
*/
#include "esp_system.h"
#include "driver/adc.h"
#include "driver/dac.h"
#include "driver/rtc_io.h"
#include "driver/gpio.h"
#include "unity.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_wifi.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "test_utils.h"
#if !DISABLED_FOR_TARGETS(ESP8266, ESP32S2) // This testcase for ESP32
/*
* ADC DMA testcase
*/
#include "driver/i2s.h"
//i2s number
#define EXAMPLE_I2S_NUM (0)
//i2s sample rate
#define EXAMPLE_I2S_SAMPLE_RATE (16000)
//i2s data bits
#define EXAMPLE_I2S_SAMPLE_BITS (16)
//enable display buffer for debug
#define EXAMPLE_I2S_BUF_DEBUG (0)
//I2S read buffer length
#define EXAMPLE_I2S_READ_LEN (16 * 1024)
//I2S data format
#define EXAMPLE_I2S_FORMAT (I2S_CHANNEL_FMT_RIGHT_LEFT)
//I2S channel number
#define EXAMPLE_I2S_CHANNEL_NUM ((EXAMPLE_I2S_FORMAT < I2S_CHANNEL_FMT_ONLY_RIGHT) ? (2) : (1))
//I2S built-in ADC unit
#define I2S_ADC_UNIT ADC_UNIT_1
//I2S built-in ADC channel
//#define I2S_ADC_CHANNEL //adc1_ch[0]
//flash record size, for recording 5 seconds' data
#define FLASH_RECORD_SIZE (EXAMPLE_I2S_CHANNEL_NUM * EXAMPLE_I2S_SAMPLE_RATE * EXAMPLE_I2S_SAMPLE_BITS / 8 * 5)
#define FLASH_ERASE_SIZE (FLASH_RECORD_SIZE % FLASH_SECTOR_SIZE == 0) ? FLASH_RECORD_SIZE : FLASH_RECORD_SIZE + (FLASH_SECTOR_SIZE - FLASH_RECORD_SIZE % FLASH_SECTOR_SIZE)
//sector size of flash
#define FLASH_SECTOR_SIZE (0x1000)
#define ADC1_TEST_CHANNEL_NUM 3
#define ADC2_TEST_CHANNEL_NUM 3
static const int adc1_ch[ADC1_TEST_CHANNEL_NUM] = {
ADC1_CHANNEL_2,
ADC1_CHANNEL_3,
ADC1_CHANNEL_4,
};
/**
* @brief I2S ADC/DAC mode init.
*/
static void example_i2s_init(void)
{
int i2s_num = EXAMPLE_I2S_NUM;
i2s_config_t i2s_config = {
.mode = I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN,
.sample_rate = EXAMPLE_I2S_SAMPLE_RATE,
.bits_per_sample = EXAMPLE_I2S_SAMPLE_BITS,
.communication_format = I2S_COMM_FORMAT_PCM,
.channel_format = EXAMPLE_I2S_FORMAT,
.intr_alloc_flags = 0,
.dma_buf_count = 2,
.dma_buf_len = 1024,
.use_apll = 1,
};
//install and start i2s driver
TEST_ESP_OK( i2s_driver_install(i2s_num, &i2s_config, 0, NULL) );
//init ADC pad
TEST_ESP_OK( i2s_set_adc_mode(I2S_ADC_UNIT, adc1_ch[0]) );
}
static void example_i2s_deinit(void)
{
TEST_ESP_OK( i2s_driver_uninstall(EXAMPLE_I2S_NUM) );
}
/**
* @brief debug buffer data
*/
static void example_disp_buf(uint8_t *buf, int length)
{
printf("======\n");
for (int i = 0; i < length; i++) {
printf("%02x ", buf[i]);
if ((i + 1) % 8 == 0) {
printf("\n");
}
}
printf("======\n");
}
TEST_CASE("ADC DMA read", "[adc dma]")
{
example_i2s_init();
int i2s_read_len = EXAMPLE_I2S_READ_LEN;
int flash_wr_size = 0;
size_t bytes_read;
char *i2s_read_buff = (char *) calloc(i2s_read_len, sizeof(char));
TEST_ESP_OK( i2s_adc_enable(EXAMPLE_I2S_NUM) );
while (flash_wr_size < FLASH_RECORD_SIZE) {
//read data from I2S bus, in this case, from ADC.
TEST_ESP_OK( i2s_read(EXAMPLE_I2S_NUM, (void *) i2s_read_buff, i2s_read_len, &bytes_read, portMAX_DELAY) );
example_disp_buf((uint8_t *) i2s_read_buff, 64);
//save original data from I2S(ADC) into flash.
flash_wr_size += i2s_read_len;
ets_printf("Sound recording %u%%\n", flash_wr_size * 100 / FLASH_RECORD_SIZE);
}
TEST_ESP_OK( i2s_adc_disable(EXAMPLE_I2S_NUM) );
if (i2s_read_buff) {
free(i2s_read_buff);
i2s_read_buff = NULL;
}
example_i2s_deinit();
}
#endif // !DISABLED_FOR_TARGETS(ESP8266, ESP32S2)

View file

@ -0,0 +1,494 @@
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*
Tests for the adc device driver
*/
#include "esp_system.h"
#include "driver/adc.h"
#include "driver/dac.h"
#include "driver/rtc_io.h"
#include "driver/gpio.h"
#include "unity.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_wifi.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "test_utils.h"
#include "soc/spi_reg.h"
#include "soc/adc_periph.h"
#if !DISABLED_FOR_TARGETS(ESP8266, ESP32) // This testcase for ESP32S2
#include "soc/system_reg.h"
static const char *TAG = "test_adc";
#define PLATFORM_SELECT (1) //0: pxp; 1: chip
#if (PLATFORM_SELECT == 0) //PXP platform
#include "soc/apb_ctrl_reg.h"
#define SET_BREAK_POINT(flag) REG_WRITE(APB_CTRL_DATE_REG, flag)
//PXP clk is slower.
#define SYS_DELAY_TIME_MOM (1/40)
#define RTC_SLOW_CLK_FLAG 1 // Slow clock is 32KHz.
static void test_pxp_deinit_io(void)
{
for (int i = 0; i < 22; i++) {
rtc_gpio_init(i);
}
}
#else
//PXP clk is slower.
#define SET_BREAK_POINT(flag)
#define SYS_DELAY_TIME_MOM (1)
#define RTC_SLOW_CLK_FLAG 0 // Slow clock is 32KHz.
#endif
#define ADC_REG_BASE_TEST() ({ \
TEST_ASSERT_EQUAL_UINT32(REG_GET_FIELD(APB_SARADC_APB_CTRL_DATE_REG, APB_SARADC_APB_CTRL_DATE), APB_SARADC.apb_ctrl_date); \
TEST_ASSERT_EQUAL_UINT32(REG_GET_FIELD(SENS_SARDATE_REG, SENS_SAR_DATE), SENS.sardate.sar_date); \
TEST_ASSERT_EQUAL_UINT32(REG_GET_FIELD(RTC_IO_DATE_REG, RTC_IO_IO_DATE), RTCIO.date.date); \
})
#define TEST_ADC_TRIGGER_INTERVAL_DEFAULT (40)
#define TEST_ADC_COUNT_NUM (10)
#define TEST_ADC_CHANNEL (10)
static adc_channel_t adc_list[TEST_ADC_CHANNEL] = {
ADC_CHANNEL_0,
ADC_CHANNEL_1,
ADC_CHANNEL_2,
ADC_CHANNEL_3,
ADC_CHANNEL_4,
ADC_CHANNEL_5,
ADC_CHANNEL_6,
ADC_CHANNEL_7,
ADC_CHANNEL_8,
ADC_CHANNEL_9,
};
/* For ESP32S2, it should use same atten, or, it will have error. */
// #define TEST_ADC_ATTEN_DEFAULT (ADC_ATTEN_11db)
static adc_atten_t adc_atten[ADC_ATTEN_MAX] = {
ADC_ATTEN_DB_0,
ADC_ATTEN_DB_2_5,
ADC_ATTEN_DB_6,
ADC_ATTEN_DB_11
};
/*******************************************/
/** SPI DMA INIT CODE */
/*******************************************/
extern esp_err_t adc_digi_reset(void);
typedef struct dma_link {
struct {
uint32_t size : 12; //the size of buf, must be able to be divisible by 4
uint32_t length: 12; //in link,
uint32_t reversed: 6; //reversed
uint32_t eof: 1; //if this dma link is the last one, you shoule set this bit 1.
uint32_t owner: 1; //the owner of buf, bit 1 : DMA, bit 0 : CPU.
} des;
uint8_t *buf; //the pointer of buf
struct dma_link *pnext; //point to the next dma linker, if this link is the last one, set it NULL.
} dma_link_t;
/* Work mode.
* sigle: eof_num;
* double: SAR_EOF_NUMBER/2;
* alter: eof_num;
* */
#define SAR_SIMPLE_NUM 64
#define SAR_DMA_DATA_SIZE(unit, sample_num) (SAR_EOF_NUMBER(unit, sample_num) * 2) // 1 adc -> 2 byte
#define SAR_EOF_NUMBER(unit, sample_num) ((sample_num) * (unit))
#define SAR_MEAS_LIMIT_NUM(unit, sample_num) (SAR_EOF_NUMBER(unit, sample_num) / unit)
static uint8_t link_buf[2][SAR_DMA_DATA_SIZE(2, SAR_SIMPLE_NUM)] = {0};
static dma_link_t dma1;
static dma_link_t dma2;
static void dma_linker_init(adc_unit_t adc, bool is_loop)
{
dma1.des.eof = 0;
dma1.des.owner = 1;
dma1.pnext = &dma2;
dma1.des.size = SAR_DMA_DATA_SIZE((adc > 2) ? 2 : 1, SAR_SIMPLE_NUM);
dma1.des.length = 0; //For input buffer, this field is no use.
dma1.buf = &link_buf[0][0];
dma2.des.eof = 1;
dma2.des.owner = 1;
if (is_loop) {
dma2.pnext = &dma1;
} else {
dma2.pnext = NULL;
}
dma2.des.size = SAR_DMA_DATA_SIZE((adc > 2) ? 2 : 1, SAR_SIMPLE_NUM);
dma2.des.length = 0; //For input buffer, this field is no use.
dma2.buf = &link_buf[1][0];
REG_SET_BIT(DPORT_PERIP_CLK_EN_REG, DPORT_APB_SARADC_CLK_EN_M);
REG_SET_BIT(DPORT_PERIP_CLK_EN_REG, DPORT_SPI3_DMA_CLK_EN_M);
REG_SET_BIT(DPORT_PERIP_CLK_EN_REG, DPORT_SPI3_CLK_EN);
REG_CLR_BIT(DPORT_PERIP_RST_EN_REG, DPORT_SPI3_DMA_RST_M);
REG_CLR_BIT(DPORT_PERIP_RST_EN_REG, DPORT_SPI3_RST_M);
uint32_t dma_pointer = (uint32_t)&dma1;
SET_PERI_REG_BITS(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_ADDR, dma_pointer, 0);
REG_SET_BIT(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_START);
REG_CLR_BIT(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_STOP);
REG_SET_BIT(SPI_DMA_INT_ENA_REG(3), SPI_IN_SUC_EOF_INT_ENA);
printf("reg addr 0x%08x 0x%08x \n", SPI_DMA_IN_LINK_REG(3), dma_pointer);
}
static void dma_linker_restart(void)
{
REG_SET_BIT(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_STOP);
REG_CLR_BIT(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_START);
REG_SET_BIT(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_RESTART_M);
REG_CLR_BIT(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_RESTART_M);
REG_SET_BIT(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_START);
REG_CLR_BIT(SPI_DMA_IN_LINK_REG(3), SPI_INLINK_STOP);
adc_digi_reset();
}
/*******************************************/
/** SPI DMA INIT CODE END */
/*******************************************/
/**
* TEST TOOLS
* Note: internal pullup/pulldown is weak energy. if enabled WiFi, it should be need outside pullup/pulldown.
*/
#define ADC_GET_IO_NUM(periph, channel) (adc_channel_io_map[periph][channel])
static void adc_fake_tie_middle(adc_unit_t adc)
{
if (adc & ADC_UNIT_1) {
for (int i = 0; i < TEST_ADC_CHANNEL; i++) {
adc_gpio_init(ADC_UNIT_1, adc_list[i]);
TEST_ESP_OK(rtc_gpio_pullup_en(ADC_GET_IO_NUM(0, adc_list[i])));
TEST_ESP_OK(rtc_gpio_pulldown_en(ADC_GET_IO_NUM(0, adc_list[i])));
}
}
if (adc & ADC_UNIT_2) {
for (int i = 0; i < TEST_ADC_CHANNEL; i++) {
adc_gpio_init(ADC_UNIT_2, adc_list[i]);
TEST_ESP_OK(rtc_gpio_pullup_en(ADC_GET_IO_NUM(1, adc_list[i])));
TEST_ESP_OK(rtc_gpio_pulldown_en(ADC_GET_IO_NUM(1, adc_list[i])));
}
}
vTaskDelay(10 / portTICK_RATE_MS); // To wait stable of IO.
}
static void adc_fake_tie_high(adc_unit_t adc)
{
if (adc & ADC_UNIT_1) {
for (int i = 0; i < TEST_ADC_CHANNEL; i++) {
adc_gpio_init(ADC_UNIT_1, adc_list[i]);
TEST_ESP_OK(rtc_gpio_pullup_en(ADC_GET_IO_NUM(0, adc_list[i])));
TEST_ESP_OK(rtc_gpio_pulldown_dis(ADC_GET_IO_NUM(0, adc_list[i])));
}
}
if (adc & ADC_UNIT_2) {
for (int i = 0; i < TEST_ADC_CHANNEL; i++) {
adc_gpio_init(ADC_UNIT_2, adc_list[i]);
TEST_ESP_OK(rtc_gpio_pullup_en(ADC_GET_IO_NUM(1, adc_list[i])));
TEST_ESP_OK(rtc_gpio_pulldown_dis(ADC_GET_IO_NUM(1, adc_list[i])));
}
}
vTaskDelay(10 / portTICK_RATE_MS); // To wait stable of IO.
}
static void adc_fake_tie_low(adc_unit_t adc)
{
if (adc & ADC_UNIT_1) {
for (int i = 0; i < TEST_ADC_CHANNEL; i++) {
adc_gpio_init(ADC_UNIT_1, adc_list[i]);
TEST_ESP_OK(rtc_gpio_pullup_dis(ADC_GET_IO_NUM(0, adc_list[i])));
TEST_ESP_OK(rtc_gpio_pulldown_en(ADC_GET_IO_NUM(0, adc_list[i])));
}
}
if (adc & ADC_UNIT_2) {
for (int i = 0; i < TEST_ADC_CHANNEL; i++) {
adc_gpio_init(ADC_UNIT_2, adc_list[i]);
TEST_ESP_OK(rtc_gpio_pullup_dis(ADC_GET_IO_NUM(1, adc_list[i])));
TEST_ESP_OK(rtc_gpio_pulldown_en(ADC_GET_IO_NUM(1, adc_list[i])));
}
}
vTaskDelay(10 / portTICK_RATE_MS); // To wait stable of IO.
}
static void adc_io_normal(adc_unit_t adc)
{
if (adc & ADC_UNIT_1) {
for (int i = 0; i < TEST_ADC_CHANNEL; i++) {
adc_gpio_init(ADC_UNIT_1, adc_list[i]);
}
}
if (adc & ADC_UNIT_2) {
for (int i = 0; i < TEST_ADC_CHANNEL; i++) {
adc_gpio_init(ADC_UNIT_2, adc_list[i]);
}
}
vTaskDelay(10 / portTICK_RATE_MS); // To wait stable of IO.
}
#define DEBUG_CHECK_ENABLE 0
#define DEBUG_PRINT_ENABLE 1
#define DEBUG_CHECK_ERROR 100
static esp_err_t adc_dma_data_check(adc_unit_t adc, int ideal_level)
{
#if DEBUG_CHECK_ENABLE
int unit_old = 1;
int ch_cnt = 0;
#endif
for (int cnt = 0; cnt < 2; cnt++) {
ets_printf("\n[%s] link_buf[%d]: \n", __func__, cnt % 2);
for (int i = 0; i < SAR_DMA_DATA_SIZE((adc > 2) ? 2 : 1, SAR_SIMPLE_NUM); i++, i++) {
uint16_t h = link_buf[cnt % 2][i + 1], l = link_buf[cnt % 2][i];
uint16_t temp = (h << 8 | l);
adc_digi_output_data_t *data = (adc_digi_output_data_t *)&temp;
if (adc > ADC_UNIT_2) { //ADC_ENCODE_11BIT
#if DEBUG_PRINT_ENABLE
if (i % 16 == 0) {
ets_printf("\n");
}
ets_printf("[%d_%d_%04x] ", data->type2.unit, data->type2.channel, data->type2.data);
#endif
#if DEBUG_CHECK_ENABLE
TEST_ASSERT_NOT_EQUAL(unit_old, data->type2.unit);
unit_old = data->type2.unit;
if (data->type2.channel > ADC_CHANNEL_MAX) {
printf("Data invalid [%d]\n", data->type2.channel);
continue;
}
int cur_ch = ((ch_cnt++ / 2) % TEST_ADC_CHANNEL);
TEST_ASSERT_EQUAL( data->type2.channel, adc_list[cur_ch] );
/*Check data channel unit*/
if (ideal_level == 1) {
TEST_ASSERT_INT_WITHIN( DEBUG_CHECK_ERROR, 0x7FF, data->type2.data );
} else if (ideal_level == 0) {
TEST_ASSERT_INT_WITHIN( DEBUG_CHECK_ERROR, 0, data->type2.data );
} else {
// middle vol
}
#endif
} else { //ADC_ENCODE_12BIT
#if DEBUG_PRINT_ENABLE
if (i % 16 == 0) {
ets_printf("\n");
}
ets_printf("[%d_%04x] ", data->type1.channel, data->type1.data);
#endif
#if DEBUG_CHECK_ENABLE
/*Check data channel */
if (ideal_level == 1) {
if (data->type1.data != 0XFFF) {
return ESP_FAIL;
}
} else if (ideal_level == 0) {
if (data->type1.data != 0) {
return ESP_FAIL;
}
} else {
if (data->type1.data == 0 || data->type1.data == 0XFFF) {
return ESP_FAIL;
}
}
int cur_ch = ((i / 2) % TEST_ADC_CHANNEL);
if (data->type1.channel != adc_list[cur_ch] ) {
return ESP_FAIL;
}
#endif
}
link_buf[cnt % 2][i] = 0;
link_buf[cnt % 2][i + 1] = 0;
}
ets_printf("\n");
}
return ESP_OK;
}
static esp_err_t adc_dma_data_multi_st_check(adc_unit_t adc)
{
ESP_LOGI(TAG, "adc IO fake tie low, test ...");
adc_fake_tie_low(adc);
TEST_ESP_OK( adc_digi_stop() );
dma_linker_restart();
REG_SET_BIT(SPI_DMA_INT_CLR_REG(3), SPI_IN_SUC_EOF_INT_CLR);
TEST_ESP_OK( adc_digi_start() );
while (0 == REG_GET_BIT(SPI_DMA_INT_ST_REG(3), SPI_IN_SUC_EOF_INT_ST)) {};
REG_SET_BIT(SPI_DMA_INT_CLR_REG(3), SPI_IN_SUC_EOF_INT_CLR);
if ( ESP_OK != adc_dma_data_check(adc, 0)) {
return ESP_FAIL;
}
ESP_LOGI(TAG, "adc IO fake tie high, test ...");
adc_fake_tie_high(adc);
TEST_ESP_OK( adc_digi_stop() );
dma_linker_restart();
REG_SET_BIT(SPI_DMA_INT_CLR_REG(3), SPI_IN_SUC_EOF_INT_CLR);
TEST_ESP_OK( adc_digi_start() );
while (0 == REG_GET_BIT(SPI_DMA_INT_ST_REG(3), SPI_IN_SUC_EOF_INT_ST)) {};
REG_SET_BIT(SPI_DMA_INT_CLR_REG(3), SPI_IN_SUC_EOF_INT_CLR);
if ( ESP_OK != adc_dma_data_check(adc, 1)) {
return ESP_FAIL;
}
ESP_LOGI(TAG, "adc IO fake tie middle, test ...");
adc_fake_tie_middle(adc);
TEST_ESP_OK( adc_digi_stop() );
dma_linker_restart();
REG_SET_BIT(SPI_DMA_INT_CLR_REG(3), SPI_IN_SUC_EOF_INT_CLR);
TEST_ESP_OK( adc_digi_start() );
while (0 == REG_GET_BIT(SPI_DMA_INT_ST_REG(3), SPI_IN_SUC_EOF_INT_ST)) {};
REG_SET_BIT(SPI_DMA_INT_CLR_REG(3), SPI_IN_SUC_EOF_INT_CLR);
if ( ESP_OK != adc_dma_data_check(adc, 2)) {
return ESP_FAIL;
}
TEST_ESP_OK( adc_digi_stop() );
adc_io_normal(adc);
return ESP_OK;
}
#include "soc/apb_saradc_struct.h"
/**
* @brief Test the partten table setting. It's easy wrong.
*
* @param adc_n ADC unit.
* @param in_partten_len The length of partten be set.
* @param in_partten_len The channel number of the last message.
*/
static esp_err_t adc_check_patt_table(adc_unit_t adc, uint32_t in_partten_len, adc_channel_t in_last_ch)
{
esp_err_t ret = ESP_FAIL;
uint8_t index = (in_partten_len - 1) / 4;
uint8_t offset = 24 - ((in_partten_len - 1) % 4) * 8;
uint32_t temp = 0, len;
if (adc & ADC_UNIT_1) {
len = APB_SARADC.ctrl.sar1_patt_len + 1;
temp = APB_SARADC.sar1_patt_tab[index];
printf("patt1 len %d\n", len);
printf("patt1 0x%08x\n", APB_SARADC.sar1_patt_tab[0]);
printf("patt1 0x%08x\n", APB_SARADC.sar1_patt_tab[1]);
printf("patt1 0x%08x\n", APB_SARADC.sar1_patt_tab[2]);
printf("patt1 0x%08x\n", APB_SARADC.sar1_patt_tab[3]);
if (in_partten_len == len) {
if (in_last_ch == (((temp >> (offset + 4))) & 0xf)) {
ret = ESP_OK;
}
}
}
if (adc & ADC_UNIT_2) {
len = APB_SARADC.ctrl.sar2_patt_len + 1;
temp = APB_SARADC.sar2_patt_tab[index];
printf("patt2 len %d\n", len);
printf("patt2 0x%08x\n", APB_SARADC.sar2_patt_tab[0]);
printf("patt2 0x%08x\n", APB_SARADC.sar2_patt_tab[1]);
printf("patt2 0x%08x\n", APB_SARADC.sar2_patt_tab[2]);
printf("patt2 0x%08x\n", APB_SARADC.sar2_patt_tab[3]);
if (in_partten_len == len) {
if (in_last_ch == (((temp >> (offset + 4))) & 0xf)) {
ret = ESP_OK;
}
}
}
return ret;
}
int test_adc_dig_dma_single_unit(adc_unit_t adc)
{
ESP_LOGI(TAG, " >> %s << ", __func__);
ESP_LOGI(TAG, " >> adc unit: %x << ", adc);
TEST_ESP_OK( adc_digi_init() );
/* arbiter config */
adc_arbiter_t arb_cfg = {
.mode = ADC_ARB_MODE_FIX,
.dig_pri = 0,
.pwdet_pri = 2,
.rtc_pri = 1,
};
TEST_ESP_OK( adc_arbiter_config(ADC_UNIT_2, &arb_cfg) ); // If you want use force
adc_digi_config_t config = {
.conv_limit_en = false,
.conv_limit_num = 0,
.interval = TEST_ADC_TRIGGER_INTERVAL_DEFAULT,
.dig_clk.use_apll = 0, // APB clk
.dig_clk.div_num = 2, // 80 MHz / 160 = 500 KHz
.dig_clk.div_b = 1,
.dig_clk.div_a = 1,
.dma_eof_num = SAR_EOF_NUMBER((adc > 2) ? 2 : 1, SAR_SIMPLE_NUM),
};
/* Config pattern table */
adc_digi_pattern_table_t adc1_patt[TEST_ADC_CHANNEL] = {0};
adc_digi_pattern_table_t adc2_patt[TEST_ADC_CHANNEL] = {0};
if (adc & ADC_UNIT_1) {
config.adc1_pattern_len = TEST_ADC_CHANNEL;
config.adc1_pattern = adc1_patt;
for (int i = 0; i < TEST_ADC_CHANNEL; i++) {
adc1_patt[i].atten = adc_atten[i%ADC_ATTEN_MAX];
adc1_patt[i].channel = adc_list[i];
adc_gpio_init(ADC_UNIT_1, adc_list[i]);
}
}
if (adc & ADC_UNIT_2) {
config.adc2_pattern_len = TEST_ADC_CHANNEL;
config.adc2_pattern = adc2_patt;
for (int i = 0; i < TEST_ADC_CHANNEL; i++) {
adc2_patt[i].atten = adc_atten[i%ADC_ATTEN_MAX];
adc2_patt[i].channel = adc_list[i];
adc_gpio_init(ADC_UNIT_2, adc_list[i]);
}
}
if (adc == ADC_UNIT_1) {
config.conv_mode = ADC_CONV_SINGLE_UNIT_1;
config.format = ADC_DIGI_FORMAT_12BIT;
} else if (adc == ADC_UNIT_2) {
config.conv_mode = ADC_CONV_SINGLE_UNIT_2;
config.format = ADC_DIGI_FORMAT_12BIT;
} else if (adc == ADC_UNIT_BOTH) {
config.conv_mode = ADC_CONV_BOTH_UNIT;
config.format = ADC_DIGI_FORMAT_11BIT;
} else if (adc == ADC_UNIT_ALTER) {
config.conv_mode = ADC_CONV_ALTER_UNIT;
config.format = ADC_DIGI_FORMAT_11BIT;
}
TEST_ESP_OK( adc_digi_controller_config(&config) );
dma_linker_init(adc, false);
TEST_ESP_OK( adc_check_patt_table(adc, TEST_ADC_CHANNEL, adc_list[TEST_ADC_CHANNEL - 1]) );
TEST_ESP_OK( adc_digi_start() );
adc_dma_data_multi_st_check(adc);
return 0;
}
TEST_CASE("ADC DMA single read", "[ADC]")
{
test_adc_dig_dma_single_unit(ADC_UNIT_BOTH);
test_adc_dig_dma_single_unit(ADC_UNIT_ALTER);
test_adc_dig_dma_single_unit(ADC_UNIT_1);
test_adc_dig_dma_single_unit(ADC_UNIT_2);
}
#endif // !DISABLED_FOR_TARGETS(ESP8266, ESP32)

View file

@ -2,7 +2,7 @@
#Component Makefile
#
COMPONENT_SRCDIRS += param_test
COMPONENT_SRCDIRS += param_test touch_sensor_test adc_test
COMPONENT_PRIV_INCLUDEDIRS += param_test/include
COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,176 @@
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*
Tests for the dac device driver
Hardware connection:
- ESP32: GPIO25 <---> GPIO26
- ESP32S2: GPIO17 <---> GPIO18
*/
#include "esp_system.h"
#include "driver/adc.h"
#include "driver/dac.h"
#include "unity.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_wifi.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "test_utils.h"
#include "test_dac_audio_file.h"
#include "driver/i2s.h"
#if !DISABLED_FOR_TARGETS(ESP8266, ESP32S2) // This testcase for ESP32
/*
* DAC DMA config.
*/
//enable record sound and save in flash
#define RECORD_IN_FLASH_EN (1)
//enable replay recorded sound in flash
#define REPLAY_FROM_FLASH_EN (1)
//i2s number
#define EXAMPLE_I2S_NUM (0)
//i2s sample rate
#define EXAMPLE_I2S_SAMPLE_RATE (16000)
//i2s data bits
#define EXAMPLE_I2S_SAMPLE_BITS (16)
//enable display buffer for debug
#define EXAMPLE_I2S_BUF_DEBUG (0)
//I2S read buffer length
#define EXAMPLE_I2S_READ_LEN (16 * 1024)
//I2S data format
#define EXAMPLE_I2S_FORMAT (I2S_CHANNEL_FMT_RIGHT_LEFT)
//I2S channel number
#define EXAMPLE_I2S_CHANNEL_NUM ((EXAMPLE_I2S_FORMAT < I2S_CHANNEL_FMT_ONLY_RIGHT) ? (2) : (1))
//flash record size, for recording 5 seconds' data
#define FLASH_RECORD_SIZE (EXAMPLE_I2S_CHANNEL_NUM * EXAMPLE_I2S_SAMPLE_RATE * EXAMPLE_I2S_SAMPLE_BITS / 8 * 5)
#define FLASH_ERASE_SIZE (FLASH_RECORD_SIZE % FLASH_SECTOR_SIZE == 0) ? FLASH_RECORD_SIZE : FLASH_RECORD_SIZE + (FLASH_SECTOR_SIZE - FLASH_RECORD_SIZE % FLASH_SECTOR_SIZE)
//sector size of flash
#define FLASH_SECTOR_SIZE (0x1000)
//flash read / write address
#define FLASH_ADDR (0x200000)
/**
* @brief I2S ADC/DAC mode init.
*/
static void example_i2s_init(void)
{
int i2s_num = EXAMPLE_I2S_NUM;
i2s_config_t i2s_config = {
.mode = I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN,
.sample_rate = EXAMPLE_I2S_SAMPLE_RATE,
.bits_per_sample = EXAMPLE_I2S_SAMPLE_BITS,
.communication_format = I2S_COMM_FORMAT_PCM,
.channel_format = EXAMPLE_I2S_FORMAT,
.intr_alloc_flags = 0,
.dma_buf_count = 2,
.dma_buf_len = 1024,
.use_apll = 1,
};
//install and start i2s driver
TEST_ESP_OK( i2s_driver_install(i2s_num, &i2s_config, 0, NULL) );
//init DAC pad
TEST_ESP_OK( i2s_set_dac_mode(I2S_DAC_CHANNEL_RIGHT_EN) );
}
static void example_i2s_deinit(void)
{
TEST_ESP_OK( i2s_driver_uninstall(EXAMPLE_I2S_NUM) );
}
/**
* @brief Set i2s clock for example audio file
*/
static void example_set_file_play_mode(void)
{
TEST_ESP_OK( i2s_set_clk(EXAMPLE_I2S_NUM, 16000, EXAMPLE_I2S_SAMPLE_BITS, 1) );
}
/**
* @brief Scale data to 16bit/32bit for I2S DMA output.
* DAC can only output 8bit data value.
* I2S DMA will still send 16 bit or 32bit data, the highest 8bit contains DAC data.
*/
static int example_i2s_dac_data_scale(uint8_t *d_buff, uint8_t *s_buff, uint32_t len)
{
uint32_t j = 0;
#if (EXAMPLE_I2S_SAMPLE_BITS == 16)
for (int i = 0; i < len; i++) {
d_buff[j++] = 0;
d_buff[j++] = s_buff[i];
}
return (len * 2);
#else
for (int i = 0; i < len; i++) {
d_buff[j++] = 0;
d_buff[j++] = 0;
d_buff[j++] = 0;
d_buff[j++] = s_buff[i];
}
return (len * 4);
#endif
}
/**
* @brief debug buffer data
*/
static void example_disp_buf(uint8_t *buf, int length)
{
printf("======\n");
for (int i = 0; i < length; i++) {
printf("%02x ", buf[i]);
if ((i + 1) % 8 == 0) {
printf("\n");
}
}
printf("======\n");
}
/**
* @brief Reset i2s clock and mode
*/
static void example_reset_play_mode(void)
{
TEST_ESP_OK( i2s_set_clk(EXAMPLE_I2S_NUM, EXAMPLE_I2S_SAMPLE_RATE, EXAMPLE_I2S_SAMPLE_BITS, EXAMPLE_I2S_CHANNEL_NUM) );
}
TEST_CASE("DAC DMA output", "[dac]")
{
example_i2s_init();
size_t bytes_written;
int i2s_read_len = EXAMPLE_I2S_READ_LEN;
uint8_t *i2s_write_buff = (uint8_t *) calloc(i2s_read_len, sizeof(char));
printf("Playing file example: \n");
int offset = 0;
int tot_size = sizeof(audio_table);
example_set_file_play_mode();
while (offset < tot_size) {
int play_len = ((tot_size - offset) > (4 * 1024)) ? (4 * 1024) : (tot_size - offset);
int i2s_wr_len = example_i2s_dac_data_scale(i2s_write_buff, (uint8_t *)(audio_table + offset), play_len);
i2s_write(EXAMPLE_I2S_NUM, i2s_write_buff, i2s_wr_len, &bytes_written, portMAX_DELAY);
offset += play_len;
example_disp_buf((uint8_t *) i2s_write_buff, 32);
}
vTaskDelay(100 / portTICK_PERIOD_MS);
example_reset_play_mode();
free(i2s_write_buff);
example_i2s_deinit();
}
#endif // !DISABLED_FOR_TARGETS(ESP8266, ESP32S2)

View file

@ -12,10 +12,23 @@
#include "nvs_flash.h"
#include "test_utils.h"
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2)
static const char* TAG = "test_adc2";
#ifdef CONFIG_IDF_TARGET_ESP32
#define ADC_TEST_WIDTH ADC_WIDTH_BIT_12
#define ADC_TEST_RESOLUTION (4096)
#define ADC_TEST_DAC_RANGE (256)
#define ADC_TEST_CH1 ADC2_CHANNEL_8
#define ADC_TEST_CH2 ADC2_CHANNEL_9
#define ADC_TEST_ERROR (600)
#elif defined CONFIG_IDF_TARGET_ESP32S2
#define ADC_TEST_WIDTH ADC_WIDTH_BIT_13 //ESP32S2 only support 13 bit width
#define ADC_TEST_RESOLUTION (8192)
#define ADC_TEST_DAC_RANGE (210)
#define ADC_TEST_CH1 ADC2_CHANNEL_6
#define ADC_TEST_CH2 ADC2_CHANNEL_7
#define ADC_TEST_ERROR (1500)
#endif
#define DEFAULT_SSID "TEST_SSID"
#define DEFAULT_PWD "TEST_PASS"
@ -84,9 +97,8 @@ TEST_CASE("adc2 work with wifi","[adc]")
TEST_ESP_OK( dac_output_enable( DAC_CHANNEL_2 ));
TEST_ESP_OK( dac_output_voltage( DAC_CHANNEL_1, 30 ));
TEST_ESP_OK( dac_output_voltage( DAC_CHANNEL_2, 60 ));
TEST_ESP_OK( adc2_config_channel_atten( ADC2_CHANNEL_8, ADC_ATTEN_0db ));
TEST_ESP_OK( adc2_config_channel_atten( ADC2_CHANNEL_9, ADC_ATTEN_0db ));
TEST_ESP_OK( adc2_config_channel_atten( ADC_TEST_CH1, ADC_ATTEN_0db ));
TEST_ESP_OK( adc2_config_channel_atten( ADC_TEST_CH2, ADC_ATTEN_0db ));
//init wifi
printf("nvs init\n");
esp_err_t r = nvs_flash_init();
@ -112,23 +124,26 @@ TEST_CASE("adc2 work with wifi","[adc]")
TEST_ESP_OK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
//test read value
TEST_ESP_OK( adc2_get_raw( ADC2_CHANNEL_8, ADC_WIDTH_12Bit, &read_raw ));
target_value = 30*4096*3/256; //3 = 3.3/1.1
TEST_ESP_OK( adc2_get_raw( ADC_TEST_CH1, ADC_TEST_WIDTH, &read_raw ));
target_value = 30*ADC_TEST_RESOLUTION*3/ADC_TEST_DAC_RANGE; //3 = 3.3/1.1
printf("dac set: %d, adc read: %d (target_value: %d)\n", 30, read_raw, target_value );
TEST_ASSERT_INT_WITHIN( 600, target_value, read_raw );
TEST_ESP_OK( adc2_get_raw( ADC2_CHANNEL_9, ADC_WIDTH_12Bit, &read_raw ));
target_value = 60*4096*3/256;
TEST_ASSERT_INT_WITHIN( ADC_TEST_ERROR, target_value, read_raw );
TEST_ESP_OK( adc2_get_raw( ADC_TEST_CH2, ADC_TEST_WIDTH, &read_raw ));
target_value = 60*ADC_TEST_RESOLUTION*3/ADC_TEST_DAC_RANGE;
printf("dac set: %d, adc read: %d (target_value: %d)\n", 60, read_raw, target_value );
TEST_ASSERT_INT_WITHIN( 600, target_value, read_raw );
TEST_ASSERT_INT_WITHIN( ADC_TEST_ERROR, target_value, read_raw );
//now start wifi
printf("wifi start...\n");
TEST_ESP_OK(esp_wifi_start());
//test reading during wifi on
TEST_ASSERT_EQUAL( adc2_get_raw( ADC2_CHANNEL_8, ADC_WIDTH_12Bit, &read_raw ), ESP_ERR_TIMEOUT );
TEST_ASSERT_EQUAL( adc2_get_raw( ADC2_CHANNEL_9, ADC_WIDTH_12Bit, &read_raw ), ESP_ERR_TIMEOUT );
#ifdef CONFIG_IDF_TARGET_ESP32
TEST_ASSERT_EQUAL( adc2_get_raw( ADC_TEST_CH1, ADC_TEST_WIDTH, &read_raw ), ESP_ERR_TIMEOUT );
TEST_ASSERT_EQUAL( adc2_get_raw( ADC_TEST_CH2, ADC_TEST_WIDTH, &read_raw ), ESP_ERR_TIMEOUT );
#elif defined CONFIG_IDF_TARGET_ESP32S2
TEST_ASSERT_EQUAL( adc2_get_raw( ADC_TEST_CH1, ADC_TEST_WIDTH, &read_raw ), ESP_OK );
TEST_ASSERT_EQUAL( adc2_get_raw( ADC_TEST_CH2, ADC_TEST_WIDTH, &read_raw ), ESP_OK );
#endif
//wifi stop again
printf("wifi stop...\n");
TEST_ESP_OK( esp_wifi_stop() );
@ -137,18 +152,16 @@ TEST_CASE("adc2 work with wifi","[adc]")
nvs_flash_deinit();
//test read value
TEST_ESP_OK( adc2_get_raw( ADC2_CHANNEL_8, ADC_WIDTH_12Bit, &read_raw ));
target_value = 30*4096*3/256; //3 = 3.3/1.1
TEST_ESP_OK( adc2_get_raw( ADC_TEST_CH1, ADC_TEST_WIDTH, &read_raw ));
target_value = 30*ADC_TEST_RESOLUTION*3/ADC_TEST_DAC_RANGE; //3 = 3.3/1.1
printf("dac set: %d, adc read: %d (target_value: %d)\n", 30, read_raw, target_value );
TEST_ASSERT_INT_WITHIN( 600, target_value, read_raw );
TEST_ESP_OK( adc2_get_raw( ADC2_CHANNEL_9, ADC_WIDTH_12Bit, &read_raw ));
target_value = 60*4096*3/256;
TEST_ASSERT_INT_WITHIN( ADC_TEST_ERROR, target_value, read_raw );
TEST_ESP_OK( adc2_get_raw( ADC_TEST_CH2, ADC_TEST_WIDTH, &read_raw ));
target_value = 60*ADC_TEST_RESOLUTION*3/ADC_TEST_DAC_RANGE;
printf("dac set: %d, adc read: %d (target_value: %d)\n", 60, read_raw, target_value );
TEST_ASSERT_INT_WITHIN( 600, target_value, read_raw );
TEST_ASSERT_INT_WITHIN( ADC_TEST_ERROR, target_value, read_raw );
printf("test passed...\n");
TEST_IGNORE_MESSAGE("this test case is ignored due to the critical memory leak of esp_netif and event_loop.");
}
#endif

View file

@ -0,0 +1,266 @@
/*
Tests for the adc device driver
*/
#include "esp_system.h"
#include "driver/adc.h"
#include "driver/dac.h"
#include "driver/rtc_io.h"
#include "driver/gpio.h"
#include "unity.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_wifi.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "test_utils.h"
#include "soc/adc_periph.h"
static const char *TAG = "test_adc";
#ifdef CONFIG_IDF_TARGET_ESP32
#define ADC1_TEST_WIDTH ADC_WIDTH_BIT_12
#define ADC2_TEST_WIDTH ADC_WIDTH_BIT_12
#elif defined CONFIG_IDF_TARGET_ESP32S2
#define ADC1_TEST_WIDTH ADC_WIDTH_BIT_13 //ESP32S2 only support 13 bit width
#define ADC2_TEST_WIDTH ADC_WIDTH_BIT_13 //ESP32S2 only support 13 bit width
#endif
#define ADC1_TEST_ATTEN ADC_ATTEN_DB_11
#define ADC2_TEST_ATTEN ADC_ATTEN_DB_11
#define ADC1_TEST_CHANNEL_NUM 8
#define ADC2_TEST_CHANNEL_NUM 6
static const int adc1_ch[ADC1_TEST_CHANNEL_NUM] = {
ADC1_CHANNEL_0,
ADC1_CHANNEL_1,
ADC1_CHANNEL_2,
ADC1_CHANNEL_3,
ADC1_CHANNEL_4,
ADC1_CHANNEL_5,
ADC1_CHANNEL_6,
ADC1_CHANNEL_7,
};
static const int adc2_ch[ADC2_TEST_CHANNEL_NUM] = {
ADC2_CHANNEL_0,
ADC2_CHANNEL_1,
ADC2_CHANNEL_2,
ADC2_CHANNEL_3,
ADC2_CHANNEL_4,
ADC2_CHANNEL_5,
};
#define ADC_GET_IO_NUM(periph, channel) (adc_channel_io_map[periph][channel])
static void adc_fake_tie_middle(adc_unit_t adc_unit, adc_channel_t channel)
{
gpio_num_t gpio_num = 0;
if (adc_unit & ADC_UNIT_1) {
gpio_num = ADC_GET_IO_NUM(0, channel);
}
if (adc_unit & ADC_UNIT_2) {
gpio_num = ADC_GET_IO_NUM(1, channel);
}
TEST_ESP_OK(rtc_gpio_pullup_en(gpio_num));
TEST_ESP_OK(rtc_gpio_pulldown_en(gpio_num));
TEST_ESP_OK(gpio_set_pull_mode(gpio_num, GPIO_PULLUP_PULLDOWN));
}
static void adc_fake_tie_high(adc_unit_t adc_unit, adc_channel_t channel)
{
gpio_num_t gpio_num = 0;
if (adc_unit & ADC_UNIT_1) {
gpio_num = ADC_GET_IO_NUM(0, channel);
}
if (adc_unit & ADC_UNIT_2) {
gpio_num = ADC_GET_IO_NUM(1, channel);
}
TEST_ESP_OK(rtc_gpio_pullup_en(gpio_num));
TEST_ESP_OK(rtc_gpio_pulldown_dis(gpio_num));
TEST_ESP_OK(gpio_set_pull_mode(gpio_num, GPIO_PULLUP_ONLY));
}
static void adc_fake_tie_low(adc_unit_t adc_unit, adc_channel_t channel)
{
gpio_num_t gpio_num = 0;
if (adc_unit & ADC_UNIT_1) {
gpio_num = ADC_GET_IO_NUM(0, channel);
}
if (adc_unit & ADC_UNIT_2) {
gpio_num = ADC_GET_IO_NUM(1, channel);
}
TEST_ESP_OK(rtc_gpio_pullup_dis(gpio_num));
TEST_ESP_OK(rtc_gpio_pulldown_en(gpio_num));
TEST_ESP_OK(gpio_set_pull_mode(gpio_num, GPIO_PULLDOWN_ONLY));
}
static void adc_io_normal(adc_unit_t adc_unit, adc_channel_t channel)
{
gpio_num_t gpio_num = 0;
if (adc_unit & ADC_UNIT_1) {
gpio_num = ADC_GET_IO_NUM(0, channel);
}
if (adc_unit & ADC_UNIT_2) {
gpio_num = ADC_GET_IO_NUM(1, channel);
}
TEST_ESP_OK(rtc_gpio_pullup_dis(gpio_num));
TEST_ESP_OK(rtc_gpio_pulldown_dis(gpio_num));
TEST_ESP_OK(gpio_set_pull_mode(gpio_num, GPIO_FLOATING));
}
TEST_CASE("ADC1 rtc read", "[adc1]")
{
int adc1_val[ADC1_TEST_CHANNEL_NUM] = {0};
/* adc1 Configure */
adc1_config_width(ADC1_TEST_WIDTH);
ESP_LOGI(TAG, "ADC1 [CH - GPIO]:");
for (int i = 0; i < ADC1_TEST_CHANNEL_NUM; i++) {
TEST_ESP_OK( adc1_config_channel_atten(adc1_ch[i], ADC1_TEST_ATTEN) );
ESP_LOGI(TAG, "[CH%d - IO%d]:", adc1_ch[i], ADC_GET_IO_NUM(0, adc1_ch[i]));
}
printf("ADC tie normal read: ");
vTaskDelay(10 / portTICK_RATE_MS);
/* adc Read */
printf("ADC1: ");
for (int i = 0; i < ADC1_TEST_CHANNEL_NUM; i++) {
adc1_val[i] = adc1_get_raw((adc1_channel_t)adc1_ch[i]);
printf("CH%d-%d ", adc1_ch[i], adc1_val[i]);
}
printf("\n");
/* tie high */
for (int i = 0; i < ADC1_TEST_CHANNEL_NUM; i++) {
adc_fake_tie_high(ADC_UNIT_1, adc1_ch[i]);
}
printf("ADC tie high read: ");
vTaskDelay(50 / portTICK_RATE_MS);
/* adc Read */
printf("ADC1: ");
for (int i = 0; i < ADC1_TEST_CHANNEL_NUM; i++) {
adc1_val[i] = adc1_get_raw((adc1_channel_t)adc1_ch[i]);
printf("CH%d-%d ", adc1_ch[i], adc1_val[i]);
#ifdef CONFIG_IDF_TARGET_ESP32S2
TEST_ASSERT_EQUAL( adc1_val[i], 0x1fff );
#endif
}
printf("\n");
/* tie low */
for (int i = 0; i < ADC1_TEST_CHANNEL_NUM; i++) {
adc_fake_tie_low(ADC_UNIT_1, adc1_ch[i]);
}
printf("ADC tie low read: ");
vTaskDelay(50 / portTICK_RATE_MS);
/* adc Read */
printf("ADC1: ");
for (int i = 0; i < ADC1_TEST_CHANNEL_NUM; i++) {
adc1_val[i] = adc1_get_raw((adc1_channel_t)adc1_ch[i]);
printf("CH%d-%d ", adc1_ch[i], adc1_val[i]);
#ifdef CONFIG_IDF_TARGET_ESP32S2
TEST_ASSERT_INT_WITHIN( 100, 0, adc1_val[i] );
#endif
}
printf("\n");
/* tie midedle */
for (int i = 0; i < ADC1_TEST_CHANNEL_NUM; i++) {
adc_fake_tie_middle(ADC_UNIT_1, adc1_ch[i]);
}
printf("ADC tie mid read: ");
vTaskDelay(50 / portTICK_RATE_MS);
/* adc Read */
printf("ADC1: ");
for (int i = 0; i < ADC1_TEST_CHANNEL_NUM; i++) {
adc1_val[i] = adc1_get_raw((adc1_channel_t)adc1_ch[i]);
printf("CH%d-%d ", adc1_ch[i], adc1_val[i]);
#ifdef CONFIG_IDF_TARGET_ESP32S2
TEST_ASSERT_NOT_EQUAL( adc1_val[i], 0 );
#endif
}
printf("\n");
for (int i = 0; i < ADC1_TEST_CHANNEL_NUM; i++) {
adc_io_normal(ADC_UNIT_1, adc1_ch[i]);
}
}
TEST_CASE("ADC2 rtc read", "[adc2]")
{
int adc2_val[ADC2_TEST_CHANNEL_NUM] = {0};
/* adc2 Configure */
ESP_LOGI(TAG, "ADC2 [CH - GPIO]:");
for (int i = 0; i < ADC2_TEST_CHANNEL_NUM; i++) {
TEST_ESP_OK( adc2_config_channel_atten(adc2_ch[i], ADC2_TEST_ATTEN) );
ESP_LOGI(TAG, "[CH%d - IO%d]:", adc2_ch[i], ADC_GET_IO_NUM(1, adc2_ch[i]));
}
printf("ADC float read: ");
vTaskDelay(10 / portTICK_RATE_MS);
/* adc Read */
printf("ADC2: ");
for (int i = 0; i < ADC2_TEST_CHANNEL_NUM; i++) {
TEST_ESP_OK( adc2_get_raw((adc2_channel_t)adc2_ch[i], ADC2_TEST_WIDTH, &adc2_val[i]) );
printf("CH%d-%d ", adc2_ch[i], adc2_val[i]);
}
printf("\n");
/* tie high */
for (int i = 0; i < ADC2_TEST_CHANNEL_NUM; i++) {
adc_fake_tie_high(ADC_UNIT_2, adc2_ch[i]);
}
printf("ADC tie high read: ");
vTaskDelay(10 / portTICK_RATE_MS);
/* adc Read */
printf("ADC2: ");
for (int i = 0; i < ADC2_TEST_CHANNEL_NUM; i++) {
TEST_ESP_OK( adc2_get_raw((adc2_channel_t)adc2_ch[i], ADC2_TEST_WIDTH, &adc2_val[i]) );
printf("CH%d-%d ", adc2_ch[i], adc2_val[i]);
#ifdef CONFIG_IDF_TARGET_ESP32S2
TEST_ASSERT_EQUAL( adc2_val[i], 0x1fff );
#endif
}
printf("\n");
/* tie low */
for (int i = 0; i < ADC2_TEST_CHANNEL_NUM; i++) {
adc_fake_tie_low(ADC_UNIT_2, adc2_ch[i]);
}
printf("ADC tie low read: ");
vTaskDelay(10 / portTICK_RATE_MS);
/* adc Read */
printf("ADC2: ");
for (int i = 0; i < ADC2_TEST_CHANNEL_NUM; i++) {
TEST_ESP_OK( adc2_get_raw((adc2_channel_t)adc2_ch[i], ADC2_TEST_WIDTH, &adc2_val[i]) );
printf("CH%d-%d ", adc2_ch[i], adc2_val[i]);
#ifdef CONFIG_IDF_TARGET_ESP32S2
TEST_ASSERT_INT_WITHIN( 100, 0, adc2_val[i] );
#endif
}
printf("\n");
/* tie midedle */
for (int i = 0; i < ADC2_TEST_CHANNEL_NUM; i++) {
adc_fake_tie_middle(ADC_UNIT_2, adc2_ch[i]);
}
printf("ADC tie middle read: ");
vTaskDelay(10 / portTICK_RATE_MS);
/* adc Read */
printf("ADC2: ");
for (int i = 0; i < ADC2_TEST_CHANNEL_NUM; i++) {
TEST_ESP_OK( adc2_get_raw((adc2_channel_t)adc2_ch[i], ADC2_TEST_WIDTH, &adc2_val[i]) );
printf("CH%d-%d ", adc2_ch[i], adc2_val[i]);
#ifdef CONFIG_IDF_TARGET_ESP32S2
TEST_ASSERT_NOT_EQUAL( 0, adc2_val[i] );
TEST_ASSERT_NOT_EQUAL( 0x1fff, adc2_val[i] );
#endif
}
printf("\n");
for (int i = 0; i < ADC1_TEST_CHANNEL_NUM; i++) {
adc_io_normal(ADC_UNIT_1, adc1_ch[i]);
}
}

View file

@ -0,0 +1,120 @@
/*
Tests for the dac device driver
*/
#include "esp_system.h"
#include "driver/adc.h"
#include "driver/dac.h"
#include "unity.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_wifi.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "test_utils.h"
#include "driver/i2s.h"
static const char *TAG = "test_dac";
#ifdef CONFIG_IDF_TARGET_ESP32
#define ADC_TEST_WIDTH ADC_WIDTH_BIT_12
#elif defined CONFIG_IDF_TARGET_ESP32S2
#define ADC_TEST_WIDTH ADC_WIDTH_BIT_13 //ESP32S2 only support 13 bit width
#endif
#define ADC_TEST_ATTEN ADC_ATTEN_DB_11
#if CONFIG_IDF_TARGET_ESP32
#define ADC_TEST_CHANNEL_NUM ADC2_CHANNEL_8 // GPIO25
#define DAC_TEST_CHANNEL_NUM DAC_CHANNEL_1 // GPIO25
#elif CONFIG_IDF_TARGET_ESP32S2
#define ADC_TEST_CHANNEL_NUM ADC2_CHANNEL_6 // GPIO17
#define DAC_TEST_CHANNEL_NUM DAC_CHANNEL_1 // GPIO17
#endif
#define DAC_OUT_MAX (200)
#define DAC_OUT_TIMES (10)
#define DAC_OUT_STEP (DAC_OUT_MAX / DAC_OUT_TIMES)
#define DAC_TEST_TIMES (100)
TEST_CASE("DAC output (RTC) check by adc", "[dac]")
{
gpio_num_t adc_gpio_num, dac_gpio_num;
TEST_ESP_OK( adc2_pad_get_io_num( ADC_TEST_CHANNEL_NUM, &adc_gpio_num ) );
TEST_ESP_OK( dac_pad_get_io_num( DAC_TEST_CHANNEL_NUM, &dac_gpio_num ) );
printf("Please connect ADC2 CH%d-GPIO%d <--> DAC CH%d-GPIO%d.\n", ADC_TEST_CHANNEL_NUM, adc_gpio_num,
DAC_TEST_CHANNEL_NUM + 1, dac_gpio_num );
TEST_ESP_OK( dac_output_enable( DAC_TEST_CHANNEL_NUM ) );
//be sure to do the init before using adc2.
printf("adc2_init...\n");
TEST_ESP_OK( adc2_config_channel_atten( ADC_TEST_CHANNEL_NUM, ADC_TEST_ATTEN ) );
vTaskDelay(2 * portTICK_RATE_MS);
printf("start conversion.\n");
int output_data = 0;
int read_raw = 0, read_old = 0;
for (int i = 0; i < DAC_OUT_TIMES; i++) {
TEST_ESP_OK( dac_output_voltage( DAC_TEST_CHANNEL_NUM, output_data ) );
output_data += DAC_OUT_STEP;
vTaskDelay(2 * portTICK_RATE_MS);
TEST_ESP_OK( adc2_get_raw( ADC_TEST_CHANNEL_NUM, ADC_TEST_WIDTH, &read_raw) );
ESP_LOGI(TAG, "DAC%d - ADC%d", output_data, read_raw);
if (read_old != 0) {
TEST_ASSERT_GREATER_THAN(read_old, read_raw);
}
read_old = read_raw;
}
TEST_ESP_OK( dac_output_disable( DAC_TEST_CHANNEL_NUM ) );
}
TEST_CASE("DAC cw generator output (RTC) check by adc", "[dac]")
{
gpio_num_t adc_gpio_num, dac_gpio_num;
TEST_ESP_OK( adc2_pad_get_io_num( ADC_TEST_CHANNEL_NUM, &adc_gpio_num ) );
TEST_ESP_OK( dac_pad_get_io_num( DAC_TEST_CHANNEL_NUM, &dac_gpio_num ) );
printf("Please connect ADC2 CH%d-GPIO%d <--> DAC CH%d-GPIO%d.\n", ADC_TEST_CHANNEL_NUM, adc_gpio_num,
DAC_TEST_CHANNEL_NUM + 1, dac_gpio_num );
dac_cw_config_t cw = {
.en_ch = DAC_TEST_CHANNEL_NUM,
.scale = DAC_CW_SCALE_2,
.phase = DAC_CW_PHASE_0,
.freq = 1000,
#if CONFIG_IDF_TARGET_ESP32
.offset = 64,
#elif CONFIG_IDF_TARGET_ESP32S2
.offset = 16,
#endif
};
TEST_ESP_OK( dac_cw_generator_config(&cw) );
TEST_ESP_OK( dac_cw_generator_enable() );
TEST_ESP_OK( dac_output_enable( DAC_TEST_CHANNEL_NUM ) );
//be sure to do the init before using adc2.
printf("adc2_init...\n");
TEST_ESP_OK( adc2_config_channel_atten( ADC_TEST_CHANNEL_NUM, ADC_TEST_ATTEN ) );
vTaskDelay(2 * portTICK_RATE_MS);
printf("start conversion.\n");
int read_raw[3] = {0};
for (int i = 0; i < DAC_TEST_TIMES; i++) {
vTaskDelay(10 * portTICK_RATE_MS);
TEST_ESP_OK( adc2_get_raw( ADC_TEST_CHANNEL_NUM, ADC_TEST_WIDTH, &read_raw[0]) );
ESP_LOGI(TAG, "ADC: %d", read_raw[0]);
if (read_raw[0] == read_raw[1]) {
TEST_ASSERT_NOT_EQUAL(read_raw[1], read_raw[2]);
}
read_raw[2] = read_raw[1];
read_raw[1] = read_raw[0];
}
TEST_ESP_OK( dac_cw_generator_disable() );
TEST_ESP_OK( dac_output_disable( DAC_TEST_CHANNEL_NUM ) );
}

View file

@ -205,7 +205,7 @@ TEST_CASE("I2S Loopback test(master tx and rx)", "[i2s]")
#if !DISABLED_FOR_TARGETS(ESP32S2)
/* ESP32S2 has only single I2S port and hence following test cases are not applicable */
TEST_CASE("I2S adc test", "[i2s]")
TEST_CASE("I2S adc test", "[i2s][ignore]")
{
// init I2S ADC
i2s_config_t i2s_config = {

View file

@ -3,18 +3,6 @@
#include "hal/adc_types.h"
#include "hal/adc_ll.h"
typedef struct {
bool conv_limit_en;
uint32_t conv_limit_num;
uint32_t clk_div;
uint32_t adc1_pattern_len;
uint32_t adc2_pattern_len;
adc_ll_pattern_table_t *adc1_pattern;
adc_ll_pattern_table_t *adc2_pattern;
adc_ll_convert_mode_t conv_mode;
adc_ll_dig_output_format_t format;
} adc_hal_dig_config_t;
/*---------------------------------------------------------------
Common setting
---------------------------------------------------------------*/
@ -23,6 +11,11 @@ typedef struct {
*/
void adc_hal_init(void);
/**
* ADC module deinitialization.
*/
void adc_hal_deinit(void);
/**
* Set adc sample cycle for digital controller.
*
@ -30,7 +23,7 @@ void adc_hal_init(void);
* @param sample_cycle Cycles between DIG ADC controller start ADC sensor and beginning to receive data from sensor.
* Range: 2 ~ 0xFF.
*/
#define adc_hal_dig_set_sample_cycle(sample_cycle) adc_ll_dig_set_sample_cycle(sample_cycle)
#define adc_hal_digi_set_sample_cycle(sample_cycle) adc_ll_digi_set_sample_cycle(sample_cycle)
/**
* Set ADC module power management.
@ -52,14 +45,14 @@ void adc_hal_init(void);
*
* @prarm div Division factor.
*/
#define adc_hal_set_clk_div(div) adc_ll_set_clk_div(div)
#define adc_hal_digi_set_clk_div(div) adc_ll_digi_set_clk_div(div)
/**
* ADC module output data invert or not.
* ADC SAR clock division factor setting. ADC SAR clock devided from `RTC_FAST_CLK`.
*
* @prarm adc_n ADC unit.
* @prarm div Division factor.
*/
void adc_hal_output_invert(adc_ll_num_t adc_n, bool inv_en);
#define adc_hal_set_sar_clk_div(adc_n, div) adc_ll_set_sar_clk_div(adc_n, div)
/**
* Set ADC module controller.
@ -108,6 +101,15 @@ void adc_hal_output_invert(adc_ll_num_t adc_n, bool inv_en);
*/
#define adc_hal_set_atten(adc_n, channel, atten) adc_ll_set_atten(adc_n, channel, atten)
/**
* Get the attenuation of a particular channel on ADCn.
*
* @param adc_n ADC unit.
* @param channel ADCn channel number.
* @return atten The attenuation option.
*/
#define adc_hal_get_atten(adc_n, channel) adc_ll_get_atten(adc_n, channel)
/**
* Close ADC AMP module if don't use it for power save.
*/
@ -137,6 +139,21 @@ void adc_hal_output_invert(adc_ll_num_t adc_n, bool inv_en);
RTC controller setting
---------------------------------------------------------------*/
/**
* Get the converted value for each ADCn for RTC controller.
*
* @note It may be block to wait conversion finish.
*
* @prarm adc_n ADC unit.
* @param channel adc channel number.
* @param value Pointer for touch value.
*
* @return
* - 0: The value is valid.
* - ~0: The value is invalid.
*/
int adc_hal_convert(adc_ll_num_t adc_n, int channel, int *value);
/**
* Set adc output data format for RTC controller.
*
@ -146,62 +163,19 @@ void adc_hal_output_invert(adc_ll_num_t adc_n, bool inv_en);
#define adc_hal_rtc_set_output_format(adc_n, bits) adc_ll_rtc_set_output_format(adc_n, bits)
/**
* Get the converted value for each ADCn for RTC controller.
* ADC module output data invert or not.
*
* @note It may be block to wait conversion finish.
* @prarm adc_n ADC unit.
* @return
* - Converted value.
*/
int adc_hal_convert(adc_ll_num_t adc_n, int channel);
#define adc_hal_rtc_output_invert(adc_n, inv_en) adc_ll_rtc_output_invert(adc_n, inv_en)
/*---------------------------------------------------------------
Digital controller setting
---------------------------------------------------------------*/
/**
* Setting the digital controller.
* Reset the pattern table pointer, then take the measurement rule from table header in next measurement.
*
* @prarm adc_hal_dig_config_t cfg Pointer to digital controller paramter.
* @param adc_n ADC unit.
*/
void adc_hal_dig_controller_config(const adc_hal_dig_config_t *cfg);
/**
* Set I2S DMA data source for digital controller.
*
* @param src i2s data source.
*/
#define adc_hal_dig_set_data_source(src) adc_ll_dig_set_data_source(src)
/*---------------------------------------------------------------
Hall sensor setting
---------------------------------------------------------------*/
/**
* Enable hall sensor.
*/
#define adc_hal_hall_enable() adc_ll_hall_enable()
/**
* Disable hall sensor.
*/
#define adc_hal_hall_disable() adc_ll_hall_disable()
/**
* Start hall convert and return the hall value.
*
* @return Hall value.
*/
int adc_hal_hall_convert(void);
/**
* @brief Output ADC2 reference voltage to gpio
*
* This function utilizes the testing mux exclusive to ADC2 to route the
* reference voltage one of ADC2's channels.
*
* @param[in] io GPIO number
* @return
* - true: v_ref successfully routed to selected gpio
* - false: Unsupported gpio
*/
#define adc_hal_vref_output(io) adc_ll_vref_output(io)
#define adc_hal_digi_clear_pattern_table(adc_n) adc_ll_digi_clear_pattern_table(adc_n)

View file

@ -1,5 +1,27 @@
#pragma once
#include "soc/adc_caps.h"
#include "sdkconfig.h"
#include <stdbool.h>
/**
* @brief ADC units selected handle.
*
* @note For ADC digital controller(DMA mode), ESP32 don't support `ADC_UNIT_2`, `ADC_UNIT_BOTH`, `ADC_UNIT_ALTER`.
*/
typedef enum {
ADC_UNIT_1 = 1, /*!< SAR ADC 1. */
ADC_UNIT_2 = 2, /*!< SAR ADC 2. */
ADC_UNIT_BOTH = 3, /*!< SAR ADC 1 and 2. */
ADC_UNIT_ALTER = 7, /*!< SAR ADC 1 and 2 alternative mode, not supported yet */
ADC_UNIT_MAX,
} adc_unit_t;
/**
* @brief ADC channels handle. See ``adc1_channel_t``, ``adc2_channel_t``.
*
* @note For ESP32 ADC1, don't support `ADC_CHANNEL_8`, `ADC_CHANNEL_9`. See ``adc1_channel_t``.
*/
typedef enum {
ADC_CHANNEL_0 = 0, /*!< ADC channel */
ADC_CHANNEL_1, /*!< ADC channel */
@ -14,6 +36,9 @@ typedef enum {
ADC_CHANNEL_MAX,
} adc_channel_t;
/**
* @brief ADC attenuation parameter. Different parameters determine the range of the ADC. See ``adc1_config_channel_atten``.
*/
typedef enum {
ADC_ATTEN_DB_0 = 0, /*!<The input voltage of ADC will be reduced to about 1/1 */
ADC_ATTEN_DB_2_5 = 1, /*!<The input voltage of ADC will be reduced to about 1/1.34 */
@ -22,16 +47,278 @@ typedef enum {
ADC_ATTEN_MAX,
} adc_atten_t;
/**
* @brief ESP32 ADC DMA source selection.
*
* @note It's be deprecated in ESP32S2. Beacause ESP32S2 don't use I2S DMA.
*/
typedef enum {
ADC_I2S_DATA_SRC_IO_SIG = 0, /*!< I2S data from GPIO matrix signal */
ADC_I2S_DATA_SRC_ADC = 1, /*!< I2S data from ADC */
ADC_I2S_DATA_SRC_MAX,
} adc_i2s_source_t;
/**
* @brief ADC resolution setting option.
*
* @note For ESP32S2. Only support 13 bit resolution.
* For ESP32. Don't support 13 bit resolution.
*/
typedef enum {
ADC_WIDTH_BIT_9 = 0, /*!< ADC capture width is 9Bit*/
ADC_WIDTH_BIT_10 = 1, /*!< ADC capture width is 10Bit*/
ADC_WIDTH_BIT_11 = 2, /*!< ADC capture width is 11Bit*/
ADC_WIDTH_BIT_12 = 3, /*!< ADC capture width is 12Bit*/
ADC_WIDTH_BIT_9 = 0, /*!< ADC capture width is 9Bit. Only ESP32 is supported. */
ADC_WIDTH_BIT_10 = 1, /*!< ADC capture width is 10Bit. Only ESP32 is supported. */
ADC_WIDTH_BIT_11 = 2, /*!< ADC capture width is 11Bit. Only ESP32 is supported. */
ADC_WIDTH_BIT_12 = 3, /*!< ADC capture width is 12Bit. Only ESP32 is supported. */
#ifdef CONFIG_IDF_TARGET_ESP32S2
ADC_WIDTH_BIT_13 = 4, /*!< ADC capture width is 13Bit. Only ESP32S2 is supported. */
#endif
ADC_WIDTH_MAX,
} adc_bits_width_t;
#ifdef CONFIG_IDF_TARGET_ESP32S2
/**
* @brief ADC digital controller (DMA mode) clock system setting.
* Expression: controller_clk = (`APLL` or `APB`) * (div_num + div_b / div_a).
*/
typedef struct {
bool use_apll; /*!<true: use APLL clock; false: use APB clock. */
uint32_t div_num; /*!<Division factor. Range: 1 ~ 255. */
uint32_t div_b; /*!<Division factor. Range: 1 ~ 63. */
uint32_t div_a; /*!<Division factor. Range: 1 ~ 63. */
} adc_digi_clk_t;
/**
* @brief ADC digital controller (DMA mode) clock system default setting.
*/
#define ADC_DIGITAL_CLK_DEFAULT() { \
.use_apll = 0, \
.div_num = 40, \
.div_b = 1, \
.div_a = 1, \
}
/**
* @brief ADC arbiter work mode option.
*
* @note ESP32S2: Only ADC2 support arbiter.
*/
typedef enum {
ADC_ARB_MODE_SHIELD,/*!<Force shield arbiter, Select the highest priority controller to work. */
ADC_ARB_MODE_FIX, /*!<Fixed priority switch controller mode. */
ADC_ARB_MODE_LOOP, /*!<Loop priority switch controller mode. Each controller has the same priority,
and the arbiter will switch to the next controller after the measurement is completed. */
} adc_arbiter_mode_t;
/**
* @brief ADC arbiter work mode and priority setting.
*
* @note ESP32S2: Only ADC2 support arbiter.
*/
typedef struct {
adc_arbiter_mode_t mode; /*!<Refer to `adc_arbiter_mode_t`. Note: only support ADC2. */
uint8_t rtc_pri; /*!<RTC controller priority. Range: 0 ~ 2. */
uint8_t dig_pri; /*!<Digital controller priority. Range: 0 ~ 2. */
uint8_t pwdet_pri; /*!<Wi-Fi controller priority. Range: 0 ~ 2. */
} adc_arbiter_t;
/**
* @brief ADC arbiter default configuration.
*
* @note ESP32S2: Only ADC2 support arbiter.
*/
#define ADC_ARBITER_CONFIG_DEFAULT() { \
.mode = ADC_ARB_MODE_FIX, \
.rtc_pri = 1, \
.dig_pri = 0, \
.pwdet_pri = 2, \
}
/**
* @brief ADC digital controller (DMA mode) work mode.
*
* @note Member `channel` can be used to judge the validity of the ADC data, because the role of the arbiter may get invalid ADC data.
*/
typedef enum {
ADC_CONV_SINGLE_UNIT_1 = 1, /*!< SAR ADC 1. */
ADC_CONV_SINGLE_UNIT_2 = 2, /*!< SAR ADC 2. */
ADC_CONV_BOTH_UNIT = 3, /*!< SAR ADC 1 and 2. */
ADC_CONV_ALTER_UNIT = 7, /*!< SAR ADC 1 and 2 alternative mode. */
ADC_CONV_UNIT_MAX,
} adc_digi_convert_mode_t;
/**
* @brief ADC digital controller (DMA mode) output data format option.
*/
typedef enum {
ADC_DIGI_FORMAT_12BIT, /*!<ADC to DMA data format, [15:12]-channel, [11: 0]-12 bits ADC data (`adc_digi_output_data_t`).
Note: In single convert mode. */
ADC_DIGI_FORMAT_11BIT, /*!<ADC to DMA data format, [15]-adc unit, [14:11]-channel, [10: 0]-11 bits ADC data (`adc_digi_output_data_t`).
Note: In multi or alter convert mode. */
ADC_DIGI_FORMAT_MAX,
} adc_digi_output_format_t;
#ifdef _MSC_VER
#pragma pack(push, 1)
#endif /* _MSC_VER */
/**
* @brief ADC digital controller (DMA mode) output data format.
* Used to analyze the acquired ADC (DMA) data.
*
* @note Member `channel` can be used to judge the validity of the ADC data, because the role of the arbiter may get invalid ADC data.
*/
typedef struct {
union {
struct {
uint16_t data: 12; /*!<ADC real output data info. Resolution: 12 bit. */
uint16_t channel: 4; /*!<ADC channel index info.
If (channel < ADC_CHANNEL_MAX), The data is valid.
If (channel > ADC_CHANNEL_MAX), The data is invalid. */
} type1; /*!<When the configured output format is 12bit. `ADC_DIGI_FORMAT_12BIT` */
struct {
uint16_t data: 11; /*!<ADC real output data info. Resolution: 11 bit. */
uint16_t channel: 4; /*!<ADC channel index info.
If (channel < ADC_CHANNEL_MAX), The data is valid.
If (channel > ADC_CHANNEL_MAX), The data is invalid. */
uint16_t unit: 1; /*!<ADC unit index info. 0: ADC1; 1: ADC2. */
} type2; /*!<When the configured output format is 11bit. `ADC_DIGI_FORMAT_11BIT` */
uint16_t val;
};
} adc_digi_output_data_t;
/**
* @brief ADC digital controller (DMA mode) conversion rules setting.
*/
typedef struct {
union {
struct {
uint8_t atten: 2; /*!< ADC sampling voltage attenuation configuration.
0: input voltage * 1;
1: input voltage * 1/1.34;
2: input voltage * 1/2;
3: input voltage * 1/3.6. */
uint8_t reserved: 2; /*!< reserved0 */
uint8_t channel: 4; /*!< ADC channel index. */
};
uint8_t val;
};
} adc_digi_pattern_table_t;
#ifdef _MSC_VER
#pragma pack(pop)
#endif /* _MSC_VER */
/**
* @brief ADC digital controller (DMA mode) interrupt type options.
*/
typedef enum {
ADC_DIGI_INTR_MASK_MONITOR = 0x1,
ADC_DIGI_INTR_MASK_MEAS_DONE = 0x2,
ADC_DIGI_INTR_MASK_ALL = 0x3,
} adc_digi_intr_t;
/**
* @brief ADC digital controller (DMA mode) configuration parameters.
*/
typedef struct {
bool conv_limit_en; /*!<Enable max conversion number detection for digital controller.
If the number of ADC conversion is equal to the `limit_num`, the conversion is stopped. */
uint32_t conv_limit_num; /*!<ADC max conversion number for digital controller. */
uint32_t adc1_pattern_len; /*!<Pattern table length for digital controller. Range: 0 ~ 16.
The pattern table that defines the conversion rules for each SAR ADC. Each table has 16 items, in which channel selection,
resolution and attenuation are stored. When the conversion is started, the controller reads conversion rules from the
pattern table one by one. For each controller the scan sequence has at most 16 different rules before repeating itself. */
uint32_t adc2_pattern_len; /*!<Refer to `adc1_pattern_len` */
adc_digi_pattern_table_t *adc1_pattern; /*!<Pointer to pattern table for digital controller. The table size defined by `adc1_pattern_len`. */
adc_digi_pattern_table_t *adc2_pattern; /*!<Refer to `adc1_pattern` */
adc_digi_convert_mode_t conv_mode; /*!<ADC conversion mode for digital controller. */
adc_digi_output_format_t format; /*!<ADC output data format for digital controller. */
uint32_t interval; /*!<The number of interval clock cycles for the digital controller to trigger the measurement.
The unit is the divided clock. Range: 40 ~ 4095. */
adc_digi_clk_t dig_clk; /*!<Refer to `adc_digi_clk_t` */
uint32_t dma_eof_num; /*!<DMA eof num of adc digital controller.
If the number of measurements reaches `dma_eof_num`,
then `dma_in_suc_eof` signal is generated. */
} adc_digi_config_t;
/**
* @brief ADC digital controller (DMA mode) filter index options.
*
* @note For ESP32S2, The filter object of the ADC is fixed.
*/
typedef enum {
ADC_DIGI_FILTER_IDX0 = 0, /*!<The filter index 0.
For ESP32S2, 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 ESP32S2, 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 {
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 ESP32S2, The filter object of the ADC is fixed.
* @note For ESP32S2, The filter object is always all enabled channels.
*/
typedef struct {
adc_unit_t adc_unit; /*!<Set adc unit number for filter.
For ESP32S2, 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 ESP32S2, 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;
/**
* @brief ADC digital controller (DMA mode) monitor index options.
*
* @note For ESP32S2, The monitor object of the ADC is fixed.
*/
typedef enum {
ADC_DIGI_MONITOR_IDX0 = 0, /*!<The monitor index 0.
For ESP32S2, It can only be used to monitor all enabled channels of ADC1 unit at the same time. */
ADC_DIGI_MONITOR_IDX1, /*!<The monitor index 1.
For ESP32S2, It can only be used to monitor all enabled channels of ADC2 unit at the same time. */
ADC_DIGI_MONITOR_IDX_MAX
} adc_digi_monitor_idx_t;
/**
* @brief Set monitor mode of adc digital controller.
* MONITOR_HIGH:If ADC_OUT > threshold, Generates monitor interrupt.
* MONITOR_LOW: If ADC_OUT < threshold, Generates monitor interrupt.
*/
typedef enum {
ADC_DIGI_MONITOR_HIGH = 0, /*!<If ADC_OUT > threshold, Generates monitor interrupt. */
ADC_DIGI_MONITOR_LOW, /*!<If ADC_OUT < threshold, Generates monitor interrupt. */
ADC_DIGI_MONITOR_MAX
} adc_digi_monitor_mode_t;
/**
* @brief ADC digital controller (DMA mode) monitor configuration.
*
* @note For ESP32S2, The monitor object of the ADC is fixed.
* @note For ESP32S2, The monitor object is always all enabled channels.
*/
typedef struct {
adc_unit_t adc_unit; /*!<Set adc unit number for monitor.
For ESP32S2, monitor IDX0/IDX1 can only be used to monitor all enabled channels of ADC1/ADC2 unit at the same time. */
adc_channel_t channel; /*!<Set adc channel number for monitor.
For ESP32S2, it's always `ADC_CHANNEL_MAX` */
adc_digi_monitor_mode_t mode; /*!<Set adc monitor mode. See ``adc_digi_monitor_mode_t``. */
uint32_t threshold; /*!<Set monitor threshold of adc digital controller. */
} adc_digi_monitor_t;
#endif // CONFIG_IDF_TARGET_ESP32S2

View file

@ -10,7 +10,7 @@ typedef enum {
} dac_channel_t;
/**
* The multiple of the amplitude of the cosine wave generator. The max amplitude is VDD3P3_RTC.
* @brief The multiple of the amplitude of the cosine wave generator. The max amplitude is VDD3P3_RTC.
*/
typedef enum {
DAC_CW_SCALE_1 = 0x0, /*!< 1/1. Default. */
@ -20,7 +20,7 @@ typedef enum {
} dac_cw_scale_t;
/**
* Set the phase of the cosine wave generator output.
* @brief Set the phase of the cosine wave generator output.
*/
typedef enum {
DAC_CW_PHASE_0 = 0x2, /*!< Phase shift +0° */
@ -28,13 +28,13 @@ typedef enum {
} dac_cw_phase_t;
/**
* Config the cosine wave generator function in DAC module.
* @brief Config the cosine wave generator function in DAC module.
*/
typedef struct {
dac_channel_t en_ch; /*!< Enable the cosine wave generator of DAC channel. */
dac_cw_scale_t scale; /*!< Set the amplitude of the cosine wave generator output. */
dac_cw_phase_t phase; /*!< Set the phase of the cosine wave generator output. */
uint32_t freq; /*!< Set frequency of cosine wave generator output. Range: 130(130Hz) ~ 55000(100KHz). */
int8_t offset; /*!< Set the voltage value of the DC component of the cosine wave generator output.
int8_t offset; /*!< Set the voltage value of the DC component of the cosine wave generator output.
Note: Unreasonable settings can cause waveform to be oversaturated. Range: -128 ~ 127. */
} dac_cw_config_t;

View file

@ -290,7 +290,8 @@ typedef struct touch_filter_config {
/** Touch sensor channel sleep configuration */
typedef struct {
touch_pad_t touch_num; /*!<Set touch channel number for sleep pad.
Only one touch sensor channel is supported in deep sleep mode. */
Only one touch sensor channel is supported in deep sleep mode.
If clear the sleep channel, point this pad to `TOUCH_PAD_NUM0` */
bool en_proximity; /*!<enable proximity function for sleep pad */
} touch_pad_sleep_channel_t;

View file

@ -7,7 +7,7 @@
#define SOC_ADC_MAX_CHANNEL_NUM (10)
#define SOC_ADC1_DATA_INVERT_DEFAULT (1)
#define SOC_ADC2_DATA_INVERT_DEFAULT (0)
#define SOC_ADC2_DATA_INVERT_DEFAULT (1)
#define SOC_ADC_FSM_RSTB_WAIT_DEFAULT (8)
#define SOC_ADC_FSM_START_WAIT_DEFAULT (5)
@ -22,4 +22,6 @@
*/
#define SOC_ADC_SUPPORT_DMA_MODE(PERIPH_NUM) ((PERIPH_NUM==0)? 1: 0)
#define SOC_ADC_PWDET_CCT_DEFAULT (4)
#define SOC_ADC_PWDET_CCT_DEFAULT (4)
#define SOC_ADC_SAR_CLK_DIV_DEFAULT(PERIPH_NUM) (2)

View file

@ -6,8 +6,10 @@
#define SOC_ADC_CHANNEL_NUM(PERIPH_NUM) (10)
#define SOC_ADC_MAX_CHANNEL_NUM (10)
#define SOC_ADC1_DATA_INVERT_DEFAULT (1)
#define SOC_ADC2_DATA_INVERT_DEFAULT (1)
#define SOC_ADC1_DATA_INVERT_DEFAULT (0)
#define SOC_ADC2_DATA_INVERT_DEFAULT (0)
#define SOC_ADC_DIGI_DATA_INVERT_DEFAULT(PERIPH_NUM) (0)
#define SOC_ADC_FSM_RSTB_WAIT_DEFAULT (8)
#define SOC_ADC_FSM_START_WAIT_DEFAULT (5)
@ -20,6 +22,10 @@
* - 1 : support;
* - 0 : not support;
*/
#define SOC_ADC_SUPPORT_DMA_MODE(PERIPH_NUM) ((PERIPH_NUM==0)? 1: 0)
#define SOC_ADC_SUPPORT_DMA_MODE(PERIPH_NUM) ((PERIPH_NUM==0)? 1: 1)
#define SOC_ADC_PWDET_CCT_DEFAULT (4)
#define SOC_ADC_PWDET_CCT_DEFAULT (4)
#define SOC_ADC_SAR_CLK_DIV_DEFAULT(PERIPH_NUM) ((PERIPH_NUM==0)? 2 : 1)
#define SOC_ADC_DIGI_SAR_CLK_DIV_DEFAULT (1)

View file

@ -39,81 +39,6 @@ typedef volatile struct {
};
uint32_t val;
} tick_conf;
union {
struct {
uint32_t start_force: 1;
uint32_t start: 1;
uint32_t reserved2: 1;
uint32_t work_mode: 2; /*0: single mode 1: double mode 2: alternate mode*/
uint32_t sar_sel: 1; /*0: SAR1 1: SAR2 only work for single SAR mode*/
uint32_t sar_clk_gated: 1;
uint32_t sar_clk_div: 8; /*SAR clock divider*/
uint32_t sar1_patt_len: 4; /*0 ~ 15 means length 1 ~ 16*/
uint32_t sar2_patt_len: 4; /*0 ~ 15 means length 1 ~ 16*/
uint32_t sar1_patt_p_clear: 1; /*clear the pointer of pattern table for DIG ADC1 CTRL*/
uint32_t sar2_patt_p_clear: 1; /*clear the pointer of pattern table for DIG ADC2 CTRL*/
uint32_t data_sar_sel: 1; /*1: sar_sel will be coded by the MSB of the 16-bit output data in this case the resolution should not be larger than 11 bits.*/
uint32_t data_to_i2s: 1; /*1: I2S input data is from SAR ADC (for DMA) 0: I2S input data is from GPIO matrix*/
uint32_t xpd_sar_force: 2; /*force option to xpd sar blocks*/
uint32_t reserved29: 3;
};
uint32_t val;
} saradc_ctrl;
union {
struct {
uint32_t meas_num_limit: 1;
uint32_t max_meas_num: 8; /*max conversion number*/
uint32_t sar1_inv: 1; /*1: data to DIG ADC1 CTRL is inverted otherwise not*/
uint32_t sar2_inv: 1; /*1: data to DIG ADC2 CTRL is inverted otherwise not*/
uint32_t timer_sel: 1; /*1: select saradc timer 0: i2s_ws trigger*/
uint32_t timer_target: 8; /*to set saradc timer target*/
uint32_t timer_en: 1; /*to enable saradc timer trigger*/
uint32_t reserved21: 11;
};
uint32_t val;
} saradc_ctrl2;
union {
struct {
uint32_t reserved0: 16;
uint32_t sample_num: 8; /*sample number*/
uint32_t sample_cycle: 8; /*sample cycles*/
};
uint32_t val;
} saradc_fsm;
union {
struct {
uint32_t xpd_wait: 8;
uint32_t rstb_wait: 8;
uint32_t standby_wait: 8;
uint32_t reserved24: 8;
};
uint32_t val;
} saradc_fsm_wait;
uint32_t saradc_sar1_status; /**/
uint32_t saradc_sar2_status; /**/
uint32_t saradc_sar1_patt_tab1; /*item 0 ~ 3 for pattern table 1 (each item one byte)*/
uint32_t saradc_sar1_patt_tab2; /*Item 4 ~ 7 for pattern table 1 (each item one byte)*/
uint32_t saradc_sar1_patt_tab3; /*Item 8 ~ 11 for pattern table 1 (each item one byte)*/
uint32_t saradc_sar1_patt_tab4; /*Item 12 ~ 15 for pattern table 1 (each item one byte)*/
uint32_t saradc_sar2_patt_tab1; /*item 0 ~ 3 for pattern table 2 (each item one byte)*/
uint32_t saradc_sar2_patt_tab2; /*Item 4 ~ 7 for pattern table 2 (each item one byte)*/
uint32_t saradc_sar2_patt_tab3; /*Item 8 ~ 11 for pattern table 2 (each item one byte)*/
uint32_t saradc_sar2_patt_tab4; /*Item 12 ~ 15 for pattern table 2 (each item one byte)*/
union {
struct {
uint32_t reserved0: 2;
uint32_t adc_arb_apb_force: 1; /*adc2 arbiter force to enableapb controller*/
uint32_t adc_arb_rtc_force: 1; /*adc2 arbiter force to enable rtc controller*/
uint32_t adc_arb_wifi_force: 1; /*adc2 arbiter force to enable wifi controller*/
uint32_t adc_arb_grant_force: 1; /*adc2 arbiter force grant*/
uint32_t adc_arb_apb_priority: 2; /*Set adc2 arbiterapb priority*/
uint32_t adc_arb_rtc_priority: 2; /*Set adc2 arbiter rtc priority*/
uint32_t adc_arb_wifi_priority: 2; /*Set adc2 arbiter wifi priority*/
uint32_t adc_arb_fix_priority: 1; /*adc2 arbiter uses fixed priority*/
uint32_t reserved13: 19;
};
uint32_t val;
} adc_arb_ctrl;
union {
struct {
uint32_t clk20_oen: 1;
@ -134,11 +59,7 @@ typedef volatile struct {
union {
struct {
uint32_t peri_io_swap: 8;
uint32_t spi0_hold: 1;
uint32_t spi1_hold: 1;
uint32_t reserved10: 3;
uint32_t spi_prior: 1;
uint32_t reserved14: 18;
uint32_t reserved8: 24;
};
uint32_t val;
} host_inf_sel;
@ -177,10 +98,10 @@ typedef volatile struct {
};
uint32_t val;
} flash_ace3_attr;
uint32_t flash_ace0_addr; /**/
uint32_t flash_ace1_addr; /**/
uint32_t flash_ace2_addr; /**/
uint32_t flash_ace3_addr; /**/
uint32_t flash_ace0_addr; /**/
uint32_t flash_ace1_addr; /**/
uint32_t flash_ace2_addr; /**/
uint32_t flash_ace3_addr; /**/
union {
struct {
uint32_t flash_ace0_size:16;
@ -237,10 +158,10 @@ typedef volatile struct {
};
uint32_t val;
} sram_ace3_attr;
uint32_t sram_ace0_addr; /**/
uint32_t sram_ace1_addr; /**/
uint32_t sram_ace2_addr; /**/
uint32_t sram_ace3_addr; /**/
uint32_t sram_ace0_addr; /**/
uint32_t sram_ace1_addr; /**/
uint32_t sram_ace2_addr; /**/
uint32_t sram_ace3_addr; /**/
union {
struct {
uint32_t sram_ace0_size:16;
@ -271,24 +192,14 @@ typedef volatile struct {
} sram_ace3_size;
union {
struct {
uint32_t spi0_reject_int: 1;
uint32_t spi0_reject_clr: 1;
uint32_t spi0_reject_cde: 5;
uint32_t reserved7: 25;
uint32_t spi_mem_reject_int: 1;
uint32_t spi_mem_reject_clr: 1;
uint32_t spi_mem_reject_cde: 5;
uint32_t reserved7: 25;
};
uint32_t val;
} spi0_pms_ctrl;
uint32_t spi0_reject_addr; /**/
union {
struct {
uint32_t spi1_reject_int: 1;
uint32_t spi1_reject_clr: 1;
uint32_t spi1_reject_cde: 5;
uint32_t reserved7: 25;
};
uint32_t val;
} spi1_pms_ctrl;
uint32_t spi1_reject_addr; /**/
} spi_mem_pms_ctrl;
uint32_t spi_mem_reject_addr; /**/
union {
struct {
uint32_t sdio_win_access_en: 1;
@ -310,10 +221,10 @@ typedef volatile struct {
};
uint32_t val;
} redcy_sig1;
uint32_t wifi_bb_cfg; /**/
uint32_t wifi_bb_cfg_2; /**/
uint32_t wifi_clk_en; /**/
uint32_t wifi_rst_en; /**/
uint32_t wifi_bb_cfg; /**/
uint32_t wifi_bb_cfg_2; /**/
uint32_t wifi_clk_en; /**/
uint32_t wifi_rst_en; /**/
union {
struct {
uint32_t agc_mem_force_pu: 1;
@ -326,6 +237,23 @@ typedef volatile struct {
};
uint32_t val;
} front_end_mem_pd;
uint32_t reserved_9c;
uint32_t reserved_a0;
uint32_t reserved_a4;
uint32_t reserved_a8;
uint32_t reserved_ac;
uint32_t reserved_b0;
uint32_t reserved_b4;
uint32_t reserved_b8;
uint32_t reserved_bc;
uint32_t reserved_c0;
uint32_t reserved_c4;
uint32_t reserved_c8;
uint32_t reserved_cc;
uint32_t reserved_d0;
uint32_t reserved_d4;
uint32_t reserved_d8;
uint32_t reserved_dc;
uint32_t reserved_e0;
uint32_t reserved_e4;
uint32_t reserved_e8;
@ -525,7 +453,7 @@ typedef volatile struct {
uint32_t reserved_3f0;
uint32_t reserved_3f4;
uint32_t reserved_3f8;
uint32_t date; /**/
uint32_t date; /**/
} apb_ctrl_dev_t;
extern apb_ctrl_dev_t APB_CTRL;
#ifdef __cplusplus

View file

@ -73,13 +73,6 @@ typedef volatile struct {
uint32_t sar2_status; /**/
uint32_t sar1_patt_tab[4]; /*item 0 ~ 3 for pattern table 1 (each item one byte)*/
uint32_t sar2_patt_tab[4];
// uint32_t sar1_patt_tab2; /*Item 4 ~ 7 for pattern table 1 (each item one byte)*/
// uint32_t sar1_patt_tab3; /*Item 8 ~ 11 for pattern table 1 (each item one byte)*/
// uint32_t sar1_patt_tab4; /*Item 12 ~ 15 for pattern table 1 (each item one byte)*/
// uint32_t sar2_patt_tab1; /*item 0 ~ 3 for pattern table 2 (each item one byte)*/
// uint32_t sar2_patt_tab2; /*Item 4 ~ 7 for pattern table 2 (each item one byte)*/
// uint32_t sar2_patt_tab3; /*Item 8 ~ 11 for pattern table 2 (each item one byte)*/
// uint32_t sar2_patt_tab4; /*Item 12 ~ 15 for pattern table 2 (each item one byte)*/
union {
struct {
uint32_t reserved0: 2;

View file

@ -172,11 +172,7 @@ typedef volatile struct {
} fifo_data;
union {
struct {
uint32_t byte_num: 8; /*Byte_num represent the number of data need to be send or data need to be received.*/
uint32_t ack_en: 1; /*ack_check_en ack_exp and ack value are used to control the ack bit.*/
uint32_t ack_exp: 1; /*ack_check_en ack_exp and ack value are used to control the ack bit.*/
uint32_t ack_val: 1; /*ack_check_en ack_exp and ack value are used to control the ack bit.*/
uint32_t op_code: 3; /*op_code is the command 0RSTART 1WRITE 2READ 3STOP . 4:END.*/
uint32_t command0: 14; /*command0*/
uint32_t reserved14: 17;
uint32_t done: 1; /*command0_done*/
};

View file

@ -1,4 +1,5 @@
set(srcs "brownout_hal.c"
set(srcs "adc_hal.c"
"brownout_hal.c"
"rtc_clk.c"
"rtc_clk_init.c"
"rtc_init.c"

View file

@ -0,0 +1,87 @@
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// The HAL layer for ADC (common part)
#include "hal/adc_hal.h"
#include "hal/adc_types.h"
void adc_hal_digi_init(void)
{
adc_hal_init();
adc_hal_set_sar_clk_div(ADC_NUM_1, SOC_ADC_SAR_CLK_DIV_DEFAULT(ADC_NUM_1));
adc_hal_set_sar_clk_div(ADC_NUM_2, SOC_ADC_SAR_CLK_DIV_DEFAULT(ADC_NUM_2));
}
void adc_hal_digi_deinit(void)
{
adc_ll_digi_clear_pattern_table(ADC_NUM_1);
adc_ll_digi_clear_pattern_table(ADC_NUM_2);
adc_hal_deinit();
}
void adc_hal_digi_controller_config(const adc_hal_digi_config_t *cfg)
{
/* If enable digital controller, adc xpd should always on. */
adc_ll_set_power_manage(ADC_POWER_SW_ON);
adc_ll_digi_set_clk_div(cfg->clk_div);
/* Single channel mode or multi channel mode. */
adc_ll_digi_set_convert_mode(cfg->conv_mode);
if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_1) {
adc_ll_set_controller(ADC_NUM_1, ADC_CTRL_DIG);
if (cfg->adc1_pattern_len) {
adc_ll_digi_clear_pattern_table(ADC_NUM_1);
adc_ll_digi_set_pattern_table_len(ADC_NUM_1, cfg->adc1_pattern_len);
for (int i = 0; i < cfg->adc1_pattern_len; i++) {
adc_ll_digi_set_pattern_table(ADC_NUM_1, i, cfg->adc1_pattern[i]);
}
}
}
if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_2) {
adc_ll_set_controller(ADC_NUM_2, ADC_CTRL_DIG);
if (cfg->adc2_pattern_len) {
adc_ll_digi_clear_pattern_table(ADC_NUM_2);
adc_ll_digi_set_pattern_table_len(ADC_NUM_2, cfg->adc2_pattern_len);
for (int i = 0; i < cfg->adc2_pattern_len; i++) {
adc_ll_digi_set_pattern_table(ADC_NUM_2, i, cfg->adc2_pattern[i]);
}
}
}
adc_ll_digi_set_output_format(cfg->format);
if (cfg->conv_limit_en) {
adc_ll_digi_set_convert_limit_num(cfg->conv_limit_num);
adc_ll_digi_convert_limit_enable();
} else {
adc_ll_digi_convert_limit_disable();
}
adc_ll_digi_set_data_source(ADC_I2S_DATA_SRC_ADC);
}
int adc_hal_hall_convert(void)
{
int Sens_Vp0;
int Sens_Vn0;
int Sens_Vp1;
int Sens_Vn1;
int hall_value;
// convert for 4 times with different phase and outputs
adc_ll_hall_phase_disable(); // hall phase
adc_hal_convert( ADC_NUM_1, ADC_CHANNEL_0, &Sens_Vp0 );
adc_hal_convert( ADC_NUM_1, ADC_CHANNEL_3, &Sens_Vn0 );
adc_ll_hall_phase_enable();
adc_hal_convert( ADC_NUM_1, ADC_CHANNEL_0, &Sens_Vp1 );
adc_hal_convert( ADC_NUM_1, ADC_CHANNEL_3, &Sens_Vn1 );
hall_value = (Sens_Vp1 - Sens_Vp0) - (Sens_Vn1 - Sens_Vn0);
return hall_value;
}

View file

@ -0,0 +1,118 @@
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*******************************************************************************
* NOTICE
* The hal is not public api, don't use in application code.
* See readme.md in soc/include/hal/readme.md
******************************************************************************/
// The HAL layer for ADC (esp32 specific part)
#pragma once
#include "hal/adc_ll.h"
#include "hal/adc_types.h"
#include_next "hal/adc_hal.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
bool conv_limit_en; /*!<Enable max conversion number detection for digital controller.
If the number of ADC conversion is equal to the `limit_num`, the conversion is stopped. */
uint32_t conv_limit_num; /*!<ADC max conversion number for digital controller. */
uint32_t adc1_pattern_len; /*!<Pattern table length for digital controller. Range: 0 ~ 16.
The pattern table that defines the conversion rules for each SAR ADC. Each table has 16 items, in which channel selection,
resolution and attenuation are stored. When the conversion is started, the controller reads conversion rules from the
pattern table one by one. For each controller the scan sequence has at most 16 different rules before repeating itself. */
uint32_t adc2_pattern_len; /*!<Refer to `adc1_pattern_len` */
adc_hal_digi_pattern_table_t *adc1_pattern; /*!<Pointer to pattern table for digital controller. The table size defined by `adc1_pattern_len`. */
adc_hal_digi_pattern_table_t *adc2_pattern; /*!<Refer to `adc1_pattern` */
adc_hal_digi_convert_mode_t conv_mode; /*!<ADC conversion mode for digital controller. ESP32 only support ADC1 single mode. */
adc_hal_digi_output_format_t format; /*!<ADC output data format for digital controller. */
uint32_t clk_div; /*!< ADC module clock division factor. ADC clock divided from APB clock.*/
} adc_hal_digi_config_t;
/*---------------------------------------------------------------
Digital controller setting
---------------------------------------------------------------*/
/**
* Set I2S DMA data source for digital controller.
*
* @param src i2s data source.
*/
#define adc_hal_digi_set_data_source(src) adc_ll_digi_set_data_source(src)
/**
* Setting the digital controller.
*
* @prarm adc_digi_config_t cfg Pointer to digital controller paramter.
*/
void adc_hal_digi_controller_config(const adc_hal_digi_config_t *cfg);
/*---------------------------------------------------------------
Common setting
---------------------------------------------------------------*/
/**
* @brief ADC digital controller initialization.
*/
void adc_hal_digi_init(void);
/**
* @brief ADC digital controller deinitialization.
*/
void adc_hal_digi_deinit(void);
/*---------------------------------------------------------------
Hall sensor setting
---------------------------------------------------------------*/
/**
* Enable hall sensor.
*/
#define adc_hal_hall_enable() adc_ll_hall_enable()
/**
* Disable hall sensor.
*/
#define adc_hal_hall_disable() adc_ll_hall_disable()
/**
* Start hall convert and return the hall value.
*
* @return Hall value.
*/
int adc_hal_hall_convert(void);
/**
* @brief Output ADC2 reference voltage to gpio
*
* This function utilizes the testing mux exclusive to ADC2 to route the
* reference voltage one of ADC2's channels.
*
* @param[in] io GPIO number
* @return
* - true: v_ref successfully routed to selected gpio
* - false: Unsupported gpio
*/
#define adc_hal_vref_output(io) adc_ll_vref_output(io)
#ifdef __cplusplus
}
#endif

View file

@ -9,12 +9,12 @@ extern "C" {
#endif
typedef enum {
ADC_DIG_FORMAT_12BIT, /*!< ADC to I2S data format, [15:12]-channel [11:0]-12 bits ADC data.
ADC_DIGI_FORMAT_12BIT, /*!< ADC to I2S data format, [15:12]-channel [11:0]-12 bits ADC data.
Note: In single convert mode. */
ADC_DIG_FORMAT_11BIT, /*!< ADC to I2S data format, [15]-1 [14:11]-channel [10:0]-11 bits ADC data.
ADC_DIGI_FORMAT_11BIT, /*!< ADC to I2S data format, [15]-adc unit [14:11]-channel [10:0]-11 bits ADC data.
Note: In multi convert mode. */
ADC_DIG_FORMAT_MAX,
} adc_ll_dig_output_format_t;
ADC_DIGI_FORMAT_MAX,
} adc_hal_digi_output_format_t;
typedef enum {
ADC_CONV_SINGLE_UNIT_1 = 1, /*!< SAR ADC 1*/
@ -22,7 +22,7 @@ typedef enum {
ADC_CONV_BOTH_UNIT = 3, /*!< SAR ADC 1 and 2, not supported yet */
ADC_CONV_ALTER_UNIT = 7, /*!< SAR ADC 1 and 2 alternative mode, not supported yet */
ADC_CONV_UNIT_MAX,
} adc_ll_convert_mode_t;
} adc_hal_digi_convert_mode_t;
typedef enum {
ADC_NUM_1 = 0, /*!< SAR ADC 1 */
@ -47,18 +47,18 @@ typedef struct {
};
uint8_t val;
};
} adc_ll_pattern_table_t;
} adc_hal_digi_pattern_table_t;
typedef enum {
ADC_POWER_BY_FSM, /*!< ADC XPD controled by FSM. Used for polling mode */
ADC_POWER_SW_ON, /*!< ADC XPD controled by SW. power on. Used for DMA mode */
ADC_POWER_SW_OFF, /*!< ADC XPD controled by SW. power off. */
ADC_POWER_BY_FSM, /*!< ADC XPD controlled by FSM. Used for polling mode */
ADC_POWER_SW_ON, /*!< ADC XPD controlled by SW. power on. Used for DMA mode */
ADC_POWER_SW_OFF, /*!< ADC XPD controlled by SW. power off. */
ADC_POWER_MAX, /*!< For parameter check. */
} adc_ll_power_t;
typedef enum {
ADC_HALL_CTRL_ULP = 0x0,/*!< Hall sensor controled by ULP */
ADC_HALL_CTRL_RTC = 0x1 /*!< Hall sensor controled by RTC */
ADC_HALL_CTRL_ULP = 0x0,/*!< Hall sensor controlled by ULP */
ADC_HALL_CTRL_RTC = 0x1 /*!< Hall sensor controlled by RTC */
} adc_ll_hall_controller_t ;
typedef enum {
@ -66,7 +66,11 @@ typedef enum {
ADC_CTRL_ULP = 1,
ADC_CTRL_DIG = 2,
ADC2_CTRL_PWDET = 3,
} adc_ll_controller_t ;
} adc_hal_controller_t ;
typedef enum {
ADC_RTC_DATA_OK = 0,
} adc_ll_rtc_raw_data_t;
/*---------------------------------------------------------------
Digital controller setting
@ -79,7 +83,7 @@ typedef enum {
* @param start_wait Delay time after open xpd.
* @param standby_wait Delay time to close xpd.
*/
static inline void adc_ll_dig_set_fsm_time(uint32_t rst_wait, uint32_t start_wait, uint32_t standby_wait)
static inline void adc_ll_digi_set_fsm_time(uint32_t rst_wait, uint32_t start_wait, uint32_t standby_wait)
{
// Internal FSM reset wait time
SYSCON.saradc_fsm.rstb_wait = rst_wait;
@ -96,17 +100,28 @@ static inline void adc_ll_dig_set_fsm_time(uint32_t rst_wait, uint32_t start_wai
* @param sample_cycle Cycles between DIG ADC controller start ADC sensor and beginning to receive data from sensor.
* Range: 2 ~ 0xFF.
*/
static inline void adc_ll_dig_set_sample_cycle(uint32_t sample_cycle)
static inline void adc_ll_digi_set_sample_cycle(uint32_t sample_cycle)
{
SYSCON.saradc_fsm.sample_cycle = sample_cycle;
}
/**
* ADC module clock division factor setting. ADC clock divided from APB clock.
*
* @param div Division factor.
*/
static inline void adc_ll_digi_set_clk_div(uint32_t div)
{
/* ADC clock divided from APB clk, e.g. 80 / 2 = 40Mhz, */
SYSCON.saradc_ctrl.sar_clk_div = div;
}
/**
* Set adc output data format for digital controller.
*
* @param format Output data format.
* @param format Output data format, see ``adc_hal_digi_output_format_t``.
*/
static inline void adc_ll_dig_set_output_format(adc_ll_dig_output_format_t format)
static inline void adc_ll_digi_set_output_format(adc_hal_digi_output_format_t format)
{
SYSCON.saradc_ctrl.data_sar_sel = format;
}
@ -117,7 +132,7 @@ static inline void adc_ll_dig_set_output_format(adc_ll_dig_output_format_t forma
*
* @param meas_num Max conversion number. Range: 0 ~ 255.
*/
static inline void adc_ll_dig_set_convert_limit_num(uint32_t meas_num)
static inline void adc_ll_digi_set_convert_limit_num(uint32_t meas_num)
{
SYSCON.saradc_ctrl2.max_meas_num = meas_num;
}
@ -126,7 +141,7 @@ static inline void adc_ll_dig_set_convert_limit_num(uint32_t meas_num)
* Enable max conversion number detection for digital controller.
* If the number of ADC conversion is equal to the maximum, the conversion is stopped.
*/
static inline void adc_ll_dig_convert_limit_enable(void)
static inline void adc_ll_digi_convert_limit_enable(void)
{
SYSCON.saradc_ctrl2.meas_num_limit = 1;
}
@ -135,7 +150,7 @@ static inline void adc_ll_dig_convert_limit_enable(void)
* Disable max conversion number detection for digital controller.
* If the number of ADC conversion is equal to the maximum, the conversion is stopped.
*/
static inline void adc_ll_dig_convert_limit_disable(void)
static inline void adc_ll_digi_convert_limit_disable(void)
{
SYSCON.saradc_ctrl2.meas_num_limit = 0;
}
@ -145,9 +160,9 @@ static inline void adc_ll_dig_convert_limit_disable(void)
*
* @note ESP32 only support ADC1 single mode.
*
* @param mode Conversion mode select.
* @param mode Conversion mode select, see ``adc_hal_digi_convert_mode_t``.
*/
static inline void adc_ll_dig_set_convert_mode(adc_ll_convert_mode_t mode)
static inline void adc_ll_digi_set_convert_mode(adc_hal_digi_convert_mode_t mode)
{
if (mode == ADC_CONV_SINGLE_UNIT_1) {
SYSCON.saradc_ctrl.work_mode = 0;
@ -162,27 +177,41 @@ static inline void adc_ll_dig_set_convert_mode(adc_ll_convert_mode_t mode)
}
}
/**
* ADC module Digital output data invert or not.
*
* @prarm adc_n ADC unit.
*/
static inline void adc_ll_digi_output_invert(adc_ll_num_t adc_n, bool inv_en)
{
if (adc_n == ADC_NUM_1) {
SYSCON.saradc_ctrl2.sar1_inv = inv_en; // Enable / Disable ADC data invert
} else { // adc_n == ADC_NUM_2
SYSCON.saradc_ctrl2.sar2_inv = inv_en; // Enable / Disable ADC data invert
}
}
/**
* Set I2S DMA data source for digital controller.
*
* @param src i2s data source.
* @param src i2s data source, see ``adc_i2s_source_t``.
*/
static inline void adc_ll_dig_set_data_source(adc_i2s_source_t src)
static inline void adc_ll_digi_set_data_source(adc_i2s_source_t src)
{
/* 1: I2S input data is from SAR ADC (for DMA) 0: I2S input data is from GPIO matrix */
SYSCON.saradc_ctrl.data_to_i2s = src;
}
/**
* Set pattern table lenth for digital controller.
* Set pattern table length for digital controller.
* The pattern table that defines the conversion rules for each SAR ADC. Each table has 16 items, in which channel selection,
* resolution and attenuation are stored. When the conversion is started, the controller reads conversion rules from the
* pattern table one by one. For each controller the scan sequence has at most 16 different rules before repeating itself.
*
* @prarm adc_n ADC unit.
* @param adc_n ADC unit.
* @param patt_len Items range: 1 ~ 16.
*/
static inline void adc_ll_set_pattern_table_len(adc_ll_num_t adc_n, uint32_t patt_len)
static inline void adc_ll_digi_set_pattern_table_len(adc_ll_num_t adc_n, uint32_t patt_len)
{
if (adc_n == ADC_NUM_1) {
SYSCON.saradc_ctrl.sar1_patt_len = patt_len - 1;
@ -197,22 +226,41 @@ static inline void adc_ll_set_pattern_table_len(adc_ll_num_t adc_n, uint32_t pat
* resolution and attenuation are stored. When the conversion is started, the controller reads conversion rules from the
* pattern table one by one. For each controller the scan sequence has at most 16 different rules before repeating itself.
*
* @prarm adc_n ADC unit.
* @param pattern_index Items index. Range: 1 ~ 16.
* @param pattern Stored conversion rules.
* @param adc_n ADC unit.
* @param pattern_index Items index. Range: 0 ~ 15.
* @param pattern Stored conversion rules, see ``adc_hal_digi_pattern_table_t``.
*/
static inline void adc_ll_set_pattern_table(adc_ll_num_t adc_n, uint32_t pattern_index, adc_ll_pattern_table_t pattern)
static inline void adc_ll_digi_set_pattern_table(adc_ll_num_t adc_n, uint32_t pattern_index, adc_hal_digi_pattern_table_t pattern)
{
const uint32_t patt_tab_idx = pattern_index / 4;
const uint32_t patt_shift = (3 - (pattern_index % 4)) * 8;
const uint32_t patt_mask = 0xFF << patt_shift;
uint32_t tab;
uint8_t index = pattern_index / 4;
uint8_t offset = (pattern_index % 4) * 8;
if (adc_n == ADC_NUM_1) {
SYSCON.saradc_sar1_patt_tab[patt_tab_idx] &= ~patt_mask;
SYSCON.saradc_sar1_patt_tab[patt_tab_idx] |= pattern.val << patt_shift;
tab = SYSCON.saradc_sar1_patt_tab[index]; // Read old register value
tab &= (~(0xFF000000 >> offset)); // clear old data
tab |= ((uint32_t)pattern.val << 24) >> offset; // Fill in the new data
SYSCON.saradc_sar1_patt_tab[index] = tab; // Write back
} else { // adc_n == ADC_NUM_2
SYSCON.saradc_sar2_patt_tab[patt_tab_idx] &= ~patt_mask;
SYSCON.saradc_sar2_patt_tab[patt_tab_idx] |= pattern.val << patt_shift;
tab = SYSCON.saradc_sar2_patt_tab[index]; // Read old register value
tab &= (~(0xFF000000 >> offset)); // clear old data
tab |= ((uint32_t)pattern.val << 24) >> offset; // Fill in the new data
SYSCON.saradc_sar2_patt_tab[index] = tab; // Write back
}
}
/**
* Reset the pattern table pointer, then take the measurement rule from table header in next measurement.
*
* @param adc_n ADC unit.
*/
static inline void adc_ll_digi_clear_pattern_table(adc_ll_num_t adc_n)
{
if (adc_n == ADC_NUM_1) {
SYSCON.saradc_ctrl.sar1_patt_p_clear = 1;
SYSCON.saradc_ctrl.sar1_patt_p_clear = 0;
} else { // adc_n == ADC_NUM_2
SYSCON.saradc_ctrl.sar2_patt_p_clear = 1;
SYSCON.saradc_ctrl.sar2_patt_p_clear = 0;
}
}
@ -223,7 +271,7 @@ static inline void adc_ll_set_pattern_table(adc_ll_num_t adc_n, uint32_t pattern
* Set adc cct for PWDET controller.
*
* @note Capacitor tuning of the PA power monitor. cct set to the same value with PHY.
* @prarm cct Range: 0 ~ 7.
* @param cct Range: 0 ~ 7.
*/
static inline void adc_ll_pwdet_set_cct(uint32_t cct)
{
@ -249,8 +297,8 @@ static inline uint32_t adc_ll_pwdet_get_cct(void)
/**
* Set adc output data format for RTC controller.
*
* @prarm adc_n ADC unit.
* @prarm bits Output data bits width option.
* @param adc_n ADC unit.
* @param bits Output data bits width option, see ``adc_bits_width_t``.
*/
static inline void adc_ll_rtc_set_output_format(adc_ll_num_t adc_n, adc_bits_width_t bits)
{
@ -266,9 +314,9 @@ static inline void adc_ll_rtc_set_output_format(adc_ll_num_t adc_n, adc_bits_wid
/**
* Enable adc channel to start convert.
*
* @note Only one channel can be selected for once measurement.
* @note Only one channel can be selected in once measurement.
*
* @prarm adc_n ADC unit.
* @param adc_n ADC unit.
* @param channel ADC channel number for each ADCn.
*/
static inline void adc_ll_rtc_enable_channel(adc_ll_num_t adc_n, int channel)
@ -280,12 +328,29 @@ static inline void adc_ll_rtc_enable_channel(adc_ll_num_t adc_n, int channel)
}
}
/**
* Disable adc channel to start convert.
*
* @note Only one channel can be selected in once measurement.
*
* @param adc_n ADC unit.
* @param channel ADC channel number for each ADCn.
*/
static inline void adc_ll_rtc_disable_channel(adc_ll_num_t adc_n, int channel)
{
if (adc_n == ADC_NUM_1) {
SENS.sar_meas_start1.sar1_en_pad = 0; //only one channel is selected.
} else { // adc_n == ADC_NUM_2
SENS.sar_meas_start2.sar2_en_pad = 0; //only one channel is selected.
}
}
/**
* Start conversion once by software for RTC controller.
*
* @note It may be block to wait conversion idle for ADC1.
*
* @prarm adc_n ADC unit.
* @param adc_n ADC unit.
* @param channel ADC channel number for each ADCn.
*/
static inline void adc_ll_rtc_start_convert(adc_ll_num_t adc_n, int channel)
@ -303,7 +368,7 @@ static inline void adc_ll_rtc_start_convert(adc_ll_num_t adc_n, int channel)
/**
* Check the conversion done flag for each ADCn for RTC controller.
*
* @prarm adc_n ADC unit.
* @param adc_n ADC unit.
* @return
* -true : The conversion process is finish.
* -false : The conversion process is not finish.
@ -322,7 +387,7 @@ static inline bool adc_ll_rtc_convert_is_done(adc_ll_num_t adc_n)
/**
* Get the converted value for each ADCn for RTC controller.
*
* @prarm adc_n ADC unit.
* @param adc_n ADC unit.
* @return
* - Converted value.
*/
@ -337,13 +402,41 @@ static inline int adc_ll_rtc_get_convert_value(adc_ll_num_t adc_n)
return ret_val;
}
/**
* ADC module RTC output data invert or not.
*
* @param adc_n ADC unit.
*/
static inline void adc_ll_rtc_output_invert(adc_ll_num_t adc_n, bool inv_en)
{
if (adc_n == ADC_NUM_1) {
SENS.sar_read_ctrl.sar1_data_inv = inv_en; // Enable / Disable ADC data invert
} else { // adc_n == ADC_NUM_2
SENS.sar_read_ctrl2.sar2_data_inv = inv_en; // Enable / Disable ADC data invert
}
}
/**
* Analyze whether the obtained raw data is correct.
*
* @param adc_n ADC unit.
* @param raw_data ADC raw data input (convert value).
* @return
* - 0: The data is correct to use.
*/
static inline adc_ll_rtc_raw_data_t adc_ll_rtc_analysis_raw_data(adc_ll_num_t adc_n, uint16_t raw_data)
{
/* ADC1 don't need check data */
return ADC_RTC_DATA_OK;
}
/*---------------------------------------------------------------
Common setting
---------------------------------------------------------------*/
/**
* Set ADC module power management.
*
* @prarm manage Set ADC power status.
* @param manage Set ADC power status.
*/
static inline void adc_ll_set_power_manage(adc_ll_power_t manage)
{
@ -380,14 +473,17 @@ static inline adc_ll_power_t adc_ll_get_power_manage(void)
}
/**
* ADC module clock division factor setting. ADC clock devided from APB clock.
* ADC SAR clock division factor setting. ADC SAR clock divided from `RTC_FAST_CLK`.
*
* @prarm div Division factor.
* @param div Division factor.
*/
static inline void adc_ll_set_clk_div(uint32_t div)
static inline void adc_ll_set_sar_clk_div(adc_ll_num_t adc_n, uint32_t div)
{
/* ADC clock devided from APB clk, e.g. 80 / 2 = 40Mhz, */
SYSCON.saradc_ctrl.sar_clk_div = div;
if (adc_n == ADC_NUM_1) {
SENS.sar_read_ctrl.sar1_clk_div = div;
} else { // adc_n == ADC_NUM_2
SENS.sar_read_ctrl2.sar2_clk_div = div;
}
}
/**
@ -400,7 +496,7 @@ static inline void adc_ll_set_clk_div(uint32_t div)
*
* When VDD_A is 3.3V:
*
* - 0dB attenuaton (ADC_ATTEN_DB_0) gives full-scale voltage 1.1V
* - 0dB attenuation (ADC_ATTEN_DB_0) gives full-scale voltage 1.1V
* - 2.5dB attenuation (ADC_ATTEN_DB_2_5) gives full-scale voltage 1.5V
* - 6dB attenuation (ADC_ATTEN_DB_6) gives full-scale voltage 2.2V
* - 11dB attenuation (ADC_ATTEN_DB_11) gives full-scale voltage 3.9V (see note below)
@ -412,16 +508,16 @@ static inline void adc_ll_set_clk_div(uint32_t div)
*
* Due to ADC characteristics, most accurate results are obtained within the following approximate voltage ranges:
*
* - 0dB attenuaton (ADC_ATTEN_DB_0) between 100 and 950mV
* - 0dB attenuation (ADC_ATTEN_DB_0) between 100 and 950mV
* - 2.5dB attenuation (ADC_ATTEN_DB_2_5) between 100 and 1250mV
* - 6dB attenuation (ADC_ATTEN_DB_6) between 150 to 1750mV
* - 11dB attenuation (ADC_ATTEN_DB_11) between 150 to 2450mV
*
* For maximum accuracy, use the ADC calibration APIs and measure voltages within these recommended ranges.
*
* @prarm adc_n ADC unit.
* @prarm channel ADCn channel number.
* @prarm atten The attenuation option.
* @param adc_n ADC unit.
* @param channel ADCn channel number.
* @param atten The attenuation option.
*/
static inline void adc_ll_set_atten(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten)
{
@ -433,30 +529,18 @@ static inline void adc_ll_set_atten(adc_ll_num_t adc_n, adc_channel_t channel, a
}
/**
* ADC module RTC output data invert or not.
* Get the attenuation of a particular channel on ADCn.
*
* @prarm adc_n ADC unit.
* @param adc_n ADC unit.
* @param channel ADCn channel number.
* @return atten The attenuation option.
*/
static inline void adc_ll_rtc_output_invert(adc_ll_num_t adc_n, bool inv_en)
static inline adc_atten_t adc_ll_get_atten(adc_ll_num_t adc_n, adc_channel_t channel)
{
if (adc_n == ADC_NUM_1) {
SENS.sar_read_ctrl.sar1_data_inv = inv_en; // Enable / Disable ADC data invert
} else { // adc_n == ADC_NUM_2
SENS.sar_read_ctrl2.sar2_data_inv = inv_en; // Enable / Disable ADC data invert
}
}
/**
* ADC module Digital output data invert or not.
*
* @prarm adc_n ADC unit.
*/
static inline void adc_ll_dig_output_invert(adc_ll_num_t adc_n, bool inv_en)
{
if (adc_n == ADC_NUM_1) {
SYSCON.saradc_ctrl2.sar1_inv = inv_en; // Enable / Disable ADC data invert
} else { // adc_n == ADC_NUM_2
SYSCON.saradc_ctrl2.sar2_inv = inv_en; // Enable / Disable ADC data invert
return (adc_atten_t)((SENS.sar_atten1 >> (channel * 2)) & 0x3);
} else {
return (adc_atten_t)((SENS.sar_atten2 >> (channel * 2)) & 0x3);
}
}
@ -467,10 +551,10 @@ static inline void adc_ll_dig_output_invert(adc_ll_num_t adc_n, bool inv_en)
* Two RTC controller: Single conversion modes (Polling). For low power purpose working during deep sleep;
* the other is dedicated for Power detect (PWDET / PKDET), Only support ADC2.
*
* @prarm adc_n ADC unit.
* @prarm ctrl ADC controller.
* @param adc_n ADC unit.
* @param ctrl ADC controller.
*/
static inline void adc_ll_set_controller(adc_ll_num_t adc_n, adc_ll_controller_t ctrl)
static inline void adc_ll_set_controller(adc_ll_num_t adc_n, adc_hal_controller_t ctrl)
{
if (adc_n == ADC_NUM_1) {
switch ( ctrl ) {

View file

@ -178,6 +178,7 @@ static inline void dac_ll_cw_set_dc_offset(dac_channel_t channel, int8_t offset)
static inline void dac_ll_dma_enable(void)
{
SENS.sar_dac_ctrl1.dac_dig_force = 1;
SENS.sar_dac_ctrl1.dac_clk_inv = 1;
}
/**
@ -186,6 +187,7 @@ static inline void dac_ll_dma_enable(void)
static inline void dac_ll_dma_disable(void)
{
SENS.sar_dac_ctrl1.dac_dig_force = 0;
SENS.sar_dac_ctrl1.dac_clk_inv = 0;
}

View file

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// The HAL layer for SPI (common part)
// The HAL layer for Touch sensor (common part)
#include "hal/touch_sensor_hal.h"
#include "hal/touch_sensor_types.h"

View file

@ -1,4 +1,5 @@
set(srcs "brownout_hal.c"
set(srcs "adc_hal.c"
"brownout_hal.c"
"rtc_clk.c"
"rtc_clk_init.c"
"rtc_init.c"

View file

@ -0,0 +1,252 @@
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// The HAL layer for ADC (esp32s2 specific part)
#include "hal/adc_hal.h"
#include "hal/adc_types.h"
#include "esp_log.h"
/*---------------------------------------------------------------
Digital controller setting
---------------------------------------------------------------*/
void adc_hal_digi_init(void)
{
adc_hal_init();
adc_ll_digi_set_clk_div(SOC_ADC_DIGI_SAR_CLK_DIV_DEFAULT);
adc_ll_digi_output_invert(ADC_NUM_1, SOC_ADC_DIGI_DATA_INVERT_DEFAULT(ADC_NUM_1));
adc_ll_digi_output_invert(ADC_NUM_2, SOC_ADC_DIGI_DATA_INVERT_DEFAULT(ADC_NUM_2));
}
void adc_hal_digi_deinit(void)
{
adc_ll_digi_trigger_disable(); // boss
adc_ll_digi_dma_disable();
adc_ll_digi_clear_pattern_table(ADC_NUM_1);
adc_ll_digi_clear_pattern_table(ADC_NUM_2);
adc_ll_digi_filter_reset(ADC_NUM_1);
adc_ll_digi_filter_reset(ADC_NUM_2);
adc_ll_digi_reset();
adc_ll_digi_controller_clk_disable();
adc_hal_deinit();
}
static inline void adc_set_init_code(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten)
{
uint32_t cal_val = adc_hal_calibration(adc_n, channel, atten, true, false);
adc_hal_set_calibration_param(adc_n, cal_val);
}
void adc_hal_digi_controller_config(const adc_digi_config_t *cfg)
{
/* If enable digtal controller, adc xpd should always on. */
adc_ll_set_power_manage(ADC_POWER_SW_ON);
/* Single channel mode or multi channel mode. */
adc_ll_digi_set_convert_mode(cfg->conv_mode);
if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_1) {
if (cfg->adc1_pattern_len) {
adc_ll_digi_clear_pattern_table(ADC_NUM_1);
adc_ll_digi_set_pattern_table_len(ADC_NUM_1, cfg->adc1_pattern_len);
for (int i = 0; i < cfg->adc1_pattern_len; i++) {
adc_ll_digi_set_pattern_table(ADC_NUM_1, i, cfg->adc1_pattern[i]);
adc_set_init_code(ADC_NUM_1, cfg->adc1_pattern[i].channel, cfg->adc1_pattern[i].atten);
}
}
}
if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_2) {
if (cfg->adc2_pattern_len) {
adc_ll_digi_clear_pattern_table(ADC_NUM_2);
adc_ll_digi_set_pattern_table_len(ADC_NUM_2, cfg->adc2_pattern_len);
for (int i = 0; i < cfg->adc2_pattern_len; i++) {
adc_ll_digi_set_pattern_table(ADC_NUM_2, i, cfg->adc2_pattern[i]);
adc_set_init_code(ADC_NUM_2, cfg->adc2_pattern[i].channel, cfg->adc2_pattern[i].atten);
}
}
}
if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_1) {
adc_ll_set_controller(ADC_NUM_1, ADC_CTRL_DIG);
}
if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_2) {
adc_ll_set_controller(ADC_NUM_2, ADC_CTRL_DIG);
}
adc_ll_digi_set_output_format(cfg->format);
if (cfg->conv_limit_en) {
adc_ll_digi_set_convert_limit_num(cfg->conv_limit_num);
adc_ll_digi_convert_limit_enable();
} else {
adc_ll_digi_convert_limit_disable();
}
adc_ll_digi_set_trigger_interval(cfg->interval);
adc_hal_digi_clk_config(&cfg->dig_clk);
adc_ll_digi_dma_set_eof_num(cfg->dma_eof_num);
}
/**
* Set ADC digital controller clock division factor. The clock divided from `APLL` or `APB` clock.
* Enable clock and select clock source for ADC digital controller.
* Expression: controller_clk = APLL/APB * (div_num + div_b / div_a).
*
* @param clk Refer to `adc_digi_clk_t`.
*/
void adc_hal_digi_clk_config(const adc_digi_clk_t *clk)
{
adc_ll_digi_controller_clk_div(clk->div_num, clk->div_b, clk->div_a);
adc_ll_digi_controller_clk_enable(clk->use_apll);
}
/**
* Enable digital controller to trigger the measurement.
*/
void adc_hal_digi_enable(void)
{
adc_ll_digi_dma_enable();
adc_ll_digi_trigger_enable();
}
/**
* Disable digital controller to trigger the measurement.
*/
void adc_hal_digi_disable(void)
{
adc_ll_digi_trigger_disable();
adc_ll_digi_dma_disable();
}
/**
* Config 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 adc_n ADC unit.
* @param config Refer to `adc_digi_monitor_t`.
*/
void adc_hal_digi_monitor_config(adc_ll_num_t adc_n, adc_digi_monitor_t *config)
{
adc_ll_digi_monitor_set_mode(adc_n, config->mode);
adc_ll_digi_monitor_set_thres(adc_n, config->threshold);
}
/*---------------------------------------------------------------
Common setting
---------------------------------------------------------------*/
/**
* Config ADC2 module arbiter.
* The arbiter is to improve the use efficiency of ADC2. After the control right is robbed by the high priority,
* the low priority controller will read the invalid ADC2 data, and the validity of the data can be judged by the flag bit in the data.
*
* @note Only ADC2 support arbiter.
* @note The arbiter's working clock is APB_CLK. When the APB_CLK clock drops below 8 MHz, the arbiter must be in shield mode.
* @note Default priority: Wi-Fi > RTC > Digital;
*
* @param config Refer to `adc_arbiter_t`.
*/
void adc_hal_arbiter_config(adc_arbiter_t *config)
{
adc_ll_set_arbiter_work_mode(config->mode);
adc_ll_set_arbiter_priority(config->rtc_pri, config->dig_pri, config->pwdet_pri);
}
/*---------------------------------------------------------------
ADC calibration setting
---------------------------------------------------------------*/
static uint16_t s_adc_cali_param[ADC_NUM_MAX][ADC_ATTEN_MAX] = { {0}, {0} };
static uint32_t adc_hal_read_self_cal(adc_ll_num_t adc_n, int channel)
{
adc_ll_rtc_start_convert(adc_n, channel);
while (adc_ll_rtc_convert_is_done(adc_n) != true);
return (uint32_t)adc_ll_rtc_get_convert_value(adc_n);
}
uint32_t adc_hal_calibration(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten, bool internal_gnd, bool force_cal)
{
if (!force_cal) {
if (s_adc_cali_param[adc_n][atten]) {
return (uint32_t)s_adc_cali_param[adc_n][atten];
}
}
uint32_t code_list[ADC_HAL_CAL_TIMES] = {0};
uint32_t code_sum = 0;
uint32_t code_h = 0;
uint32_t code_l = 0;
uint32_t chk_code = 0;
uint32_t dout = 0;
adc_hal_set_power_manage(ADC_POWER_SW_ON);
if (adc_n == ADC_NUM_2) {
adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT();
adc_hal_arbiter_config(&config);
}
adc_hal_set_controller(adc_n, ADC_CTRL_RTC); //Set controller
// adc_hal_arbiter_config(adc_arbiter_t *config)
adc_ll_calibration_prepare(adc_n, channel, internal_gnd);
/* Enable/disable internal connect GND (for calibration). */
if (internal_gnd) {
adc_ll_rtc_disable_channel(adc_n, channel);
adc_ll_set_atten(adc_n, 0, atten); // Note: when disable all channel, HW auto select channel0 atten param.
} else {
adc_ll_rtc_enable_channel(adc_n, channel);
adc_ll_set_atten(adc_n, channel, atten);
}
for (uint8_t rpt = 0 ; rpt < ADC_HAL_CAL_TIMES ; rpt ++) {
code_h = ADC_HAL_CAL_OFFSET_RANGE;
code_l = 0;
chk_code = (code_h + code_l) / 2;
adc_ll_set_calibration_param(adc_n, chk_code);
dout = adc_hal_read_self_cal(adc_n, channel);
while (code_h - code_l > 1) {
if (dout == 0) {
code_h = chk_code;
} else {
code_l = chk_code;
}
chk_code = (code_h + code_l) / 2;
adc_ll_set_calibration_param(adc_n, chk_code);
dout = adc_hal_read_self_cal(adc_n, channel);
if ((code_h - code_l == 1)) {
chk_code += 1;
adc_ll_set_calibration_param(adc_n, chk_code);
dout = adc_hal_read_self_cal(adc_n, channel);
}
}
code_list[rpt] = chk_code;
code_sum += chk_code;
}
code_l = code_list[0];
code_h = code_list[0];
for (uint8_t i = 0 ; i < ADC_HAL_CAL_TIMES ; i++) {
if (code_l > code_list[i]) {
code_l = code_list[i];
}
if (code_h < code_list[i]) {
code_h = code_list[i];
}
}
chk_code = code_h + code_l;
dout = ((code_sum - chk_code) % (ADC_HAL_CAL_TIMES - 2) < 4)
? (code_sum - chk_code) / (ADC_HAL_CAL_TIMES - 2)
: (code_sum - chk_code) / (ADC_HAL_CAL_TIMES - 2) + 1;
adc_ll_set_calibration_param(adc_n, dout);
adc_ll_calibration_finish(adc_n);
s_adc_cali_param[adc_n][atten] = (uint16_t)dout;
return dout;
}

View file

@ -0,0 +1,262 @@
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*******************************************************************************
* NOTICE
* The hal is not public api, don't use in application code.
* See readme.md in soc/include/hal/readme.md
******************************************************************************/
// The HAL layer for ADC (esp32s2 specific part)
#pragma once
#include "hal/adc_ll.h"
#include "hal/adc_types.h"
#include_next "hal/adc_hal.h"
#ifdef __cplusplus
extern "C" {
#endif
/*---------------------------------------------------------------
Digital controller setting
---------------------------------------------------------------*/
/**
* Digital controller initialization.
*/
void adc_hal_digi_init(void);
/**
* Digital controller deinitialization.
*/
void adc_hal_digi_deinit(void);
/**
* Setting the digital controller.
*
* @param cfg Pointer to digital controller paramter.
*/
void adc_hal_digi_controller_config(const adc_digi_config_t *cfg);
/**
* ADC Digital controller output data invert or not.
*
* @param adc_n ADC unit.
* @param inv_en data invert or not.
*/
#define adc_hal_digi_output_invert(adc_n, inv_en) adc_ll_digi_output_invert(adc_n, inv_en)
/**
* Sets the number of interval clock cycles for the digital controller to trigger the measurement.
*
* @note The trigger interval should not be less than the sampling time of the SAR ADC.
* @param cycle The number of clock cycles for the trigger interval. The unit is the divided clock. Range: 40 ~ 4095.
*/
#define adc_hal_digi_set_trigger_interval(cycle) adc_ll_digi_set_trigger_interval(cycle)
/**
* Enable digital controller to trigger the measurement.
*/
void adc_hal_digi_enable(void);
/**
* Disable digital controller to trigger the measurement.
*/
void adc_hal_digi_disable(void);
/**
* Set ADC digital controller clock division factor. The clock divided from `APLL` or `APB` clock.
* Enable clock and select clock source for ADC digital controller.
* Expression: controller_clk = APLL/APB * (div_num + div_b / div_a).
*
* @param clk Refer to `adc_digi_clk_t`.
*/
void adc_hal_digi_clk_config(const adc_digi_clk_t *clk);
/**
* Reset adc digital controller filter.
*
* @param adc_n ADC unit.
*/
#define adc_hal_digi_filter_reset(adc_n) adc_ll_digi_filter_reset(adc_n)
/**
* Set 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).
*/
#define adc_hal_digi_filter_set_factor(adc_n, factor) adc_ll_digi_filter_set_factor(adc_n, factor)
/**
* 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).
*/
#define adc_hal_digi_filter_get_factor(adc_n, factor) adc_ll_digi_filter_get_factor(adc_n, factor)
/**
* 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.
*/
#define adc_hal_digi_filter_enable(adc_n, enable) adc_ll_digi_filter_enable(adc_n, enable)
/**
* 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.
*/
#define adc_hal_digi_filter_read_data(adc_n) adc_ll_digi_filter_read_data(adc_n)
/**
* Config 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 adc_n ADC unit.
* @param config Refer to `adc_digi_monitor_t`.
*/
void adc_hal_digi_monitor_config(adc_ll_num_t adc_n, 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 adc_n ADC unit.
*/
#define adc_hal_digi_monitor_enable(adc_n, enable) adc_ll_digi_monitor_enable(adc_n, enable)
/**
* Enable interrupt of adc digital controller by bitmask.
*
* @param adc_n ADC unit.
* @param intr Interrupt bitmask.
*/
#define adc_hal_digi_intr_enable(adc_n, intr) adc_ll_digi_intr_enable(adc_n, intr)
/**
* Disable interrupt of adc digital controller by bitmask.
*
* @param adc_n ADC unit.
* @param intr Interrupt bitmask.
*/
#define adc_hal_digi_intr_disable(adc_n, intr) adc_ll_digi_intr_disable(adc_n, intr)
/**
* Clear interrupt of adc digital controller by bitmask.
*
* @param adc_n ADC unit.
* @param intr Interrupt bitmask.
*/
#define adc_hal_digi_intr_clear(adc_n, intr) adc_ll_digi_intr_clear(adc_n, intr)
/**
* Get interrupt status mask of adc digital controller.
*
* @param adc_n ADC unit.
* @return
* - intr Interrupt bitmask.
*/
#define adc_hal_digi_get_intr_status(adc_n) adc_ll_digi_get_intr_status(adc_n)
/**
* Set DMA eof num of adc digital controller.
* If the number of measurements reaches `dma_eof_num`, then `dma_in_suc_eof` signal is generated.
*
* @param num eof num of DMA.
*/
#define adc_hal_digi_dma_set_eof_num(num) adc_ll_digi_dma_set_eof_num(num)
/**
* Enable output data to DMA from adc digital controller.
*/
#define adc_hal_digi_dma_enable() adc_ll_digi_dma_enable()
/**
* Disable output data to DMA from adc digital controller.
*/
#define adc_hal_digi_dma_disable() adc_ll_digi_dma_disable()
/**
* Reset adc digital controller.
*/
#define adc_hal_digi_reset() adc_ll_digi_reset()
/*---------------------------------------------------------------
RTC controller setting
---------------------------------------------------------------*/
/**
* Reset RTC controller FSM.
*/
#define adc_hal_rtc_reset() adc_ll_rtc_reset()
/*---------------------------------------------------------------
Common setting
---------------------------------------------------------------*/
/**
* Config ADC2 module arbiter.
* The arbiter is to improve the use efficiency of ADC2. After the control right is robbed by the high priority,
* the low priority controller will read the invalid ADC2 data, and the validity of the data can be judged by the flag bit in the data.
*
* @note Only ADC2 support arbiter.
* @note The arbiter's working clock is APB_CLK. When the APB_CLK clock drops below 8 MHz, the arbiter must be in shield mode.
* @note Default priority: Wi-Fi > RTC > Digital;
*
* @param config Refer to `adc_arbiter_t`.
*/
void adc_hal_arbiter_config(adc_arbiter_t *config);
/*---------------------------------------------------------------
ADC calibration setting
---------------------------------------------------------------*/
/**
* Calibrate the ADC according to the parameters.
*
* @note Different ADC units and different attenuation options use different calibration data (initial data).
*
* @param adc_n ADC index number.
* @param channel adc channel number.
* @param internal_gnd true: Disconnect from the IO port and use the internal GND as the calibration voltage.
* false: Use IO external voltage as calibration voltage.
* @param force_cal true: Do not use the results that have already been verified, and perform the verification again. It will take a long time.
* false: Use the result of the last calibration.
*
* @return
* - The calibration result (initial data) to ADC, use `adc_hal_set_calibration_param` to set.
*/
uint32_t adc_hal_calibration(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten, bool internal_gnd, bool force_cal);
/**
* Set the calibration result (initial data) to ADC.
*
* @note Different ADC units and different attenuation options use different calibration data (initial data).
*
* @param adc_n ADC index number.
*/
#define adc_hal_set_calibration_param(adc_n, param) adc_ll_set_calibration_param(adc_n, param);
#ifdef __cplusplus
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -28,6 +28,10 @@
extern "C" {
#endif
/*---------------------------------------------------------------
RTC controller setting
---------------------------------------------------------------*/
/**
* Power on dac module and start output voltage.
*
@ -36,6 +40,7 @@ extern "C" {
*/
static inline void dac_ll_power_on(dac_channel_t channel)
{
SENS.sar_dac_ctrl1.dac_clkgate_en = 1;
RTCIO.pad_dac[channel].dac_xpd_force = 1;
RTCIO.pad_dac[channel].xpd_dac = 1;
}
@ -49,6 +54,9 @@ static inline void dac_ll_power_down(dac_channel_t channel)
{
RTCIO.pad_dac[channel].dac_xpd_force = 0;
RTCIO.pad_dac[channel].xpd_dac = 0;
if (RTCIO.pad_dac[0].xpd_dac == 0 && RTCIO.pad_dac[1].xpd_dac == 0) {
SENS.sar_dac_ctrl1.dac_clkgate_en = 0;
}
}
/**
@ -69,6 +77,15 @@ static inline void dac_ll_update_output_value(dac_channel_t channel, uint8_t val
}
}
/**
* Reset dac by software.
*/
static inline void dac_ll_rtc_reset(void)
{
SENS.sar_dac_ctrl1.dac_reset = 1;
SENS.sar_dac_ctrl1.dac_reset = 0;
}
/************************************/
/* DAC cosine wave generator API's */
/************************************/
@ -168,6 +185,10 @@ static inline void dac_ll_cw_set_dc_offset(dac_channel_t channel, int8_t offset)
}
}
/*---------------------------------------------------------------
Digital controller setting
---------------------------------------------------------------*/
/************************************/
/* DAC DMA API's */
/************************************/
@ -178,6 +199,7 @@ static inline void dac_ll_cw_set_dc_offset(dac_channel_t channel, int8_t offset)
static inline void dac_ll_dma_enable(void)
{
SENS.sar_dac_ctrl1.dac_dig_force = 1;
SENS.sar_dac_ctrl1.dac_clk_inv = 1;
}
/**
@ -186,6 +208,7 @@ static inline void dac_ll_dma_enable(void)
static inline void dac_ll_dma_disable(void)
{
SENS.sar_dac_ctrl1.dac_dig_force = 0;
SENS.sar_dac_ctrl1.dac_clk_inv = 0;
}
#ifdef __cplusplus

View file

@ -17,72 +17,22 @@
void adc_hal_init(void)
{
// Set internal FSM wait time, fixed value.
adc_ll_dig_set_fsm_time(SOC_ADC_FSM_RSTB_WAIT_DEFAULT, SOC_ADC_FSM_START_WAIT_DEFAULT,
SOC_ADC_FSM_STANDBY_WAIT_DEFAULT);
adc_ll_dig_set_sample_cycle(ADC_FSM_SAMPLE_CYCLE_DEFAULT);
adc_hal_output_invert(ADC_NUM_1, SOC_ADC1_DATA_INVERT_DEFAULT);
adc_hal_output_invert(ADC_NUM_2, SOC_ADC2_DATA_INVERT_DEFAULT);
adc_ll_digi_set_fsm_time(SOC_ADC_FSM_RSTB_WAIT_DEFAULT, SOC_ADC_FSM_START_WAIT_DEFAULT,
SOC_ADC_FSM_STANDBY_WAIT_DEFAULT);
adc_ll_digi_set_sample_cycle(ADC_FSM_SAMPLE_CYCLE_DEFAULT);
adc_hal_pwdet_set_cct(SOC_ADC_PWDET_CCT_DEFAULT);
}
void adc_hal_dig_controller_config(const adc_hal_dig_config_t *cfg)
void adc_hal_deinit(void)
{
/* If enable digtal controller, adc xpd should always on. */
adc_ll_set_power_manage(ADC_POWER_SW_ON);
adc_ll_set_clk_div(cfg->clk_div);
/* Single channel mode or multi channel mode. */
adc_ll_dig_set_convert_mode(cfg->conv_mode);
if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_1) {
adc_ll_set_controller(ADC_NUM_1, ADC_CTRL_DIG);
adc_ll_set_pattern_table_len(ADC_NUM_1, cfg->adc1_pattern_len);
for (int i = 0; i < cfg->adc1_pattern_len; i++) {
adc_ll_set_pattern_table(ADC_NUM_1, i, cfg->adc1_pattern[i]);
}
}
if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_2) {
adc_ll_set_controller(ADC_NUM_2, ADC_CTRL_DIG);
adc_ll_set_pattern_table_len(ADC_NUM_2, cfg->adc2_pattern_len);
for (int i = 0; i < cfg->adc2_pattern_len; i++) {
adc_ll_set_pattern_table(ADC_NUM_2, i, cfg->adc2_pattern[i]);
}
}
adc_ll_dig_set_output_format(cfg->format);
if (cfg->conv_limit_en) {
adc_ll_dig_set_convert_limit_num(cfg->conv_limit_num);
adc_ll_dig_convert_limit_enable();
} else {
adc_ll_dig_convert_limit_disable();
}
adc_ll_dig_set_data_source(ADC_I2S_DATA_SRC_ADC);
adc_ll_set_power_manage(ADC_POWER_SW_OFF);
}
int adc_hal_convert(adc_ll_num_t adc_n, int channel)
int adc_hal_convert(adc_ll_num_t adc_n, int channel, int *value)
{
adc_ll_rtc_enable_channel(adc_n, channel);
adc_ll_rtc_start_convert(adc_n, channel);
while (adc_ll_rtc_convert_is_done(adc_n) != true);
return adc_ll_rtc_get_convert_value(adc_n);
*value = adc_ll_rtc_get_convert_value(adc_n);
return (int)adc_ll_rtc_analysis_raw_data(adc_n, (uint16_t)(*value));
}
int adc_hal_hall_convert(void)
{
int Sens_Vp0;
int Sens_Vn0;
int Sens_Vp1;
int Sens_Vn1;
int hall_value;
// convert for 4 times with different phase and outputs
adc_ll_hall_phase_disable(); // hall phase
Sens_Vp0 = adc_hal_convert( ADC_NUM_1, ADC_CHANNEL_0 );
Sens_Vn0 = adc_hal_convert( ADC_NUM_1, ADC_CHANNEL_3 );
adc_ll_hall_phase_enable();
Sens_Vp1 = adc_hal_convert( ADC_NUM_1, ADC_CHANNEL_0 );
Sens_Vn1 = adc_hal_convert( ADC_NUM_1, ADC_CHANNEL_3 );
hall_value = (Sens_Vp1 - Sens_Vp0) - (Sens_Vn1 - Sens_Vn0);
return hall_value;
}
void adc_hal_output_invert(adc_ll_num_t adc_n, bool inv_en)
{
adc_ll_rtc_output_invert(adc_n, inv_en);
adc_ll_dig_output_invert(adc_n, inv_en);
}

View file

@ -86,7 +86,6 @@ INPUT = \
##
## Peripherals - API Reference
##
$(IDF_PATH)/components/driver/include/driver/adc.h \
$(IDF_PATH)/components/driver/include/driver/can.h \
$(IDF_PATH)/components/soc/include/hal/can_types.h \
$(IDF_PATH)/components/driver/include/driver/dac.h \
@ -103,10 +102,12 @@ INPUT = \
$(IDF_PATH)/components/driver/include/driver/spi_common.h \
$(IDF_PATH)/components/driver/include/driver/spi_master.h \
$(IDF_PATH)/components/driver/include/driver/spi_slave.h \
$(IDF_PATH)/components/driver/$(IDF_TARGET)/include/touch_sensor.h \
$(IDF_PATH)/components/driver/esp32s2/include/temp_sensor.h \
$(IDF_PATH)/components/driver/$(IDF_TARGET)/include/driver/adc.h \
$(IDF_PATH)/components/driver/$(IDF_TARGET)/include/driver/touch_sensor.h \
$(IDF_PATH)/components/driver/esp32s2/include/driver/temp_sensor.h \
$(IDF_PATH)/components/driver/include/driver/timer.h \
$(IDF_PATH)/components/driver/include/driver/touch_sensor_common.h \
$(IDF_PATH)/components/driver/include/driver/adc_common.h \
$(IDF_PATH)/components/driver/include/driver/uart.h \
$(IDF_PATH)/components/esp_adc_cal/include/esp_adc_cal.h \
$(IDF_PATH)/components/soc/include/hal/rmt_types.h \

View file

@ -22,8 +22,10 @@
#if CONFIG_IDF_TARGET_ESP32
static esp_adc_cal_characteristics_t *adc_chars;
static const adc_channel_t channel = ADC_CHANNEL_6; //GPIO34 if ADC1, GPIO14 if ADC2
static const adc_bits_width_t width = ADC_WIDTH_BIT_12;
#elif CONFIG_IDF_TARGET_ESP32S2
static const adc_channel_t channel = ADC_CHANNEL_6; // GPIO7 if ADC1, GPIO17 if ADC2
static const adc_bits_width_t width = ADC_WIDTH_BIT_13;
#endif
static const adc_atten_t atten = ADC_ATTEN_DB_0;
static const adc_unit_t unit = ADC_UNIT_1;
@ -67,7 +69,7 @@ void app_main(void)
//Configure ADC
if (unit == ADC_UNIT_1) {
adc1_config_width(ADC_WIDTH_BIT_12);
adc1_config_width(width);
adc1_config_channel_atten(channel, atten);
} else {
adc2_config_channel_atten((adc2_channel_t)channel, atten);
@ -76,7 +78,7 @@ void app_main(void)
#if CONFIG_IDF_TARGET_ESP32
//Characterize ADC
adc_chars = calloc(1, sizeof(esp_adc_cal_characteristics_t));
esp_adc_cal_value_t val_type = esp_adc_cal_characterize(unit, atten, ADC_WIDTH_BIT_12, DEFAULT_VREF, adc_chars);
esp_adc_cal_value_t val_type = esp_adc_cal_characterize(unit, atten, width, DEFAULT_VREF, adc_chars);
print_char_val_type(val_type);
#endif
@ -89,7 +91,7 @@ void app_main(void)
adc_reading += adc1_get_raw((adc1_channel_t)channel);
} else {
int raw;
adc2_get_raw((adc2_channel_t)channel, ADC_WIDTH_BIT_12, &raw);
adc2_get_raw((adc2_channel_t)channel, width, &raw);
adc_reading += raw;
}
}

View file

@ -19,6 +19,12 @@
#define DAC_EXAMPLE_CHANNEL CONFIG_EXAMPLE_DAC_CHANNEL
#define ADC2_EXAMPLE_CHANNEL CONFIG_EXAMPLE_ADC2_CHANNEL
#if CONFIG_IDF_TARGET_ESP32
static const adc_bits_width_t width = ADC_WIDTH_BIT_12;
#elif CONFIG_IDF_TARGET_ESP32S2
static const adc_bits_width_t width = ADC_WIDTH_BIT_13;
#endif
void app_main(void)
{
uint8_t output_data=0;
@ -46,7 +52,7 @@ void app_main(void)
printf("start conversion.\n");
while(1) {
dac_output_voltage( DAC_EXAMPLE_CHANNEL, output_data++ );
r = adc2_get_raw( ADC2_EXAMPLE_CHANNEL, ADC_WIDTH_12Bit, &read_raw);
r = adc2_get_raw( ADC2_EXAMPLE_CHANNEL, width, &read_raw);
if ( r == ESP_OK ) {
printf("%d: %d\n", output_data, read_raw );
} else if ( r == ESP_ERR_INVALID_STATE ) {

View file

@ -11,6 +11,8 @@
#include "audio_example_file.h"
#include "esp_adc_cal.h"
#if CONFIG_IDF_TARGET_ESP32
static const char* TAG = "ad/da";
#define V_REF 1100
#define ADC1_TEST_CHANNEL (ADC1_CHANNEL_7)
@ -288,5 +290,4 @@ esp_err_t app_main(void)
xTaskCreate(adc_read_task, "ADC read task", 2048, NULL, 5, NULL);
return ESP_OK;
}
#endif

View file

@ -15,7 +15,7 @@
/* Note: ESP32 don't support temperature sensor */
#if CONFIG_IDF_TARGET_ESP32S2
#include "temp_sensor.h"
#include "driver/temp_sensor.h"
static const char *TAG = "TempSensor";

View file

@ -88,7 +88,11 @@ static int adc1_sample_and_show(int sampling_period)
void app_main(void)
{
ESP_LOGI(TAG, "Enabling ADC1 on channel 6 / GPIO34.");
#if CONFIG_IDF_TARGET_ESP32
adc1_config_width(ADC_WIDTH_BIT_12);
#elif CONFIG_IDF_TARGET_ESP32S2
adc1_config_width(ADC_WIDTH_BIT_13);
#endif
adc1_config_channel_atten(ADC1_TEST_CHANNEL, ADC_ATTEN_DB_11);
ESP_LOGI(TAG, "Enabling CW generator on DAC channel 1 / GPIO25.");

View file

@ -64,7 +64,11 @@ static void init_ulp_program(void)
/* Note: when changing channel here, also change 'adc_channel' constant
in adc.S */
adc1_config_channel_atten(ADC1_CHANNEL_6, ADC_ATTEN_DB_11);
#if CONFIG_IDF_TARGET_ESP32
adc1_config_width(ADC_WIDTH_BIT_12);
#elif CONFIG_IDF_TARGET_ESP32S2
adc1_config_width(ADC_WIDTH_BIT_13);
#endif
adc1_ulp_enable();
/* Set low and high thresholds, approx. 1.35V - 1.75V*/

View file

@ -336,7 +336,7 @@ example_test_012:
UT_001:
extends: .unit_test_template
parallel: 36
parallel: 37
tags:
- ESP32_IDF
- UT_T1_1