2022-07-15 00:52:44 -04:00
/*
* SPDX - FileCopyrightText : 2016 - 2021 Espressif Systems ( Shanghai ) CO LTD
*
* SPDX - License - Identifier : Apache - 2.0
*/
/*----------------------------------------------------------------------------------
This file contains ESP32 and ESP32S2 Depricated ADC APIs and functions
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
# include "sdkconfig.h"
# include "esp_types.h"
# include "esp_log.h"
# include "esp_intr_alloc.h"
# include "driver/rtc_io.h"
# include "hal/adc_hal.h"
# include "hal/adc_ll.h"
# include "hal/adc_types.h"
# ifdef CONFIG_PM_ENABLE
# include "esp_pm.h"
# endif
# include "freertos/FreeRTOS.h"
# include "driver/adc_i2s_legacy.h"
# include "driver/adc_types_legacy.h"
static __attribute__ ( ( unused ) ) const char * ADC_TAG = " ADC " ;
# define ADC_CHECK_RET(fun_ret) ({ \
if ( fun_ret ! = ESP_OK ) { \
2023-06-08 14:56:11 -04:00
ESP_LOGE ( ADC_TAG , " %s:%d " , __FUNCTION__ , __LINE__ ) ; \
2022-07-15 00:52:44 -04:00
return ESP_FAIL ; \
} \
} )
# define ADC_CHECK(a, str, ret_val) ({ \
if ( ! ( a ) ) { \
ESP_LOGE ( ADC_TAG , " %s(%d): %s " , __FUNCTION__ , __LINE__ , str ) ; \
return ( ret_val ) ; \
} \
} )
# define ADC_CHANNEL_CHECK(periph, channel) ADC_CHECK(channel < SOC_ADC_CHANNEL_NUM(periph), "ADC"#periph" channel error", ESP_ERR_INVALID_ARG)
# define ADC_GET_IO_NUM(periph, channel) (adc_channel_io_map[periph][channel])
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)
# ifdef CONFIG_PM_ENABLE
esp_pm_lock_handle_t adc_digi_arbiter_lock = NULL ;
# endif //CONFIG_PM_ENABLE
# if CONFIG_IDF_TARGET_ESP32
/*---------------------------------------------------------------
ESP32 Depricated ADC APIs and functions
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
# 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 (3) //3 for ADC_WIDTH_BIT_12
/**
* @ brief ADC digital controller ( DMA mode ) conversion rules setting .
*/
typedef struct {
union {
struct {
uint8_t atten : 2 ; /*!< ADC sampling voltage attenuation configuration. Modification of attenuation affects the range of measurements.
0 : measurement range 0 - 800 mV ,
1 : measurement range 0 - 1100 mV ,
2 : measurement range 0 - 1350 mV ,
3 : measurement range 0 - 2600 mV . */
uint8_t bit_width : 2 ; /*!< ADC resolution.
- 0 : 9 bit ;
- 1 : 10 bit ;
- 2 : 11 bit ;
- 3 : 12 bit . */
int8_t channel : 4 ; /*!< ADC channel index. */
} ;
uint8_t val ; /*!<Raw data value */
} ;
} adc_digi_pattern_table_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: For 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: For multi or alter convert mode. */
ADC_DIGI_FORMAT_MAX ,
} adc_digi_format_t ;
/**
* Explanation of the relationship between ` conv_limit_num ` , ` dma_eof_num ` and the number of DMA outputs :
*
* + - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - + - - - - - - - - + - - - - - - - - +
* | conv_mode | single | both | alter |
* + - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - + - - - - - - - - + - - - - - - - - +
* | trigger meas times | 1 | 1 | 1 |
* + - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - + - - - - - - - - + - - - - - - - - +
* | conv_limit_num | + 1 | + 1 | + 1 |
* | dma_eof_num | + 1 | + 2 | + 1 |
* | dma output ( byte ) | + 2 | + 4 | + 2 |
* + - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - + - - - - - - - - + - - - - - - - - +
*/
typedef struct {
uint32_t adc1_pattern_len ; /*!<Pattern table length for digital controller. Range: 0 ~ 16 (0: Don't change the pattern table setting).
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. See ``adc_digi_convert_mode_t``. */
adc_digi_format_t format ; /*!<ADC output data format for digital controller. See ``adc_digi_format_t``. */
} adc_digi_config_t ;
/**
* Set adc output 16 - bit - data format from digital controller .
*
* @ param data_sel 1 : [ 15 ] unit , [ 14 : 11 ] channel , [ 10 : 0 ] data , 11 - bit - width at most . Only work under ` ADC_LL_DIGI_CONV_BOTH_UNIT ` or ` ADC_LL_DIGI_CONV_ALTER_UNIT ` mode .
* 0 : [ 15 : 12 ] channel , [ 11 : 0 ] data , 12 - bit - width at most . Only work under ` ADC_LL_DIGI_CONV_ONLY_ADC1 ` or ` ADC_LL_DIGI_CONV_ONLY_ADC2 ` mode
* @ note see ` adc_ll_digi_pattern_table_t ` for more detail of data bit width
*/
static inline void adc_ll_digi_set_output_format ( bool data_sel )
{
SYSCON . saradc_ctrl . data_sar_sel = data_sel ;
}
static inline void adc_ll_digi_prepare_pattern_table ( adc_unit_t adc_n , uint32_t pattern_index , adc_digi_pattern_table_t pattern )
{
uint32_t tab ;
uint8_t index = pattern_index / 4 ;
uint8_t offset = ( pattern_index % 4 ) * 8 ;
if ( adc_n = = ADC_UNIT_1 ) {
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_UNIT_2
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
}
}
static void adc_digi_controller_reg_set ( const adc_digi_config_t * cfg )
{
/* On ESP32, only support ADC1 */
switch ( cfg - > conv_mode ) {
case ADC_CONV_SINGLE_UNIT_1 :
adc_ll_digi_set_convert_mode ( ADC_LL_DIGI_CONV_ONLY_ADC1 ) ;
break ;
case ADC_CONV_SINGLE_UNIT_2 :
adc_ll_digi_set_convert_mode ( ADC_LL_DIGI_CONV_ONLY_ADC2 ) ;
break ;
case ADC_CONV_BOTH_UNIT :
adc_ll_digi_set_convert_mode ( ADC_LL_DIGI_CONV_BOTH_UNIT ) ;
break ;
case ADC_CONV_ALTER_UNIT :
adc_ll_digi_set_convert_mode ( ADC_LL_DIGI_CONV_ALTER_UNIT ) ;
break ;
default :
abort ( ) ;
}
if ( cfg - > conv_mode & ADC_CONV_SINGLE_UNIT_1 ) {
adc_ll_set_controller ( ADC_UNIT_1 , ADC_LL_CTRL_DIG ) ;
if ( cfg - > adc1_pattern_len ) {
adc_ll_digi_clear_pattern_table ( ADC_UNIT_1 ) ;
adc_ll_digi_set_pattern_table_len ( ADC_UNIT_1 , cfg - > adc1_pattern_len ) ;
for ( uint32_t i = 0 ; i < cfg - > adc1_pattern_len ; i + + ) {
adc_ll_digi_prepare_pattern_table ( ADC_UNIT_1 , i , cfg - > adc1_pattern [ i ] ) ;
}
}
}
if ( cfg - > conv_mode & ADC_CONV_SINGLE_UNIT_2 ) {
adc_ll_set_controller ( ADC_UNIT_2 , ADC_LL_CTRL_DIG ) ;
if ( cfg - > adc2_pattern_len ) {
adc_ll_digi_clear_pattern_table ( ADC_UNIT_2 ) ;
adc_ll_digi_set_pattern_table_len ( ADC_UNIT_2 , cfg - > adc2_pattern_len ) ;
for ( uint32_t i = 0 ; i < cfg - > adc2_pattern_len ; i + + ) {
adc_ll_digi_prepare_pattern_table ( ADC_UNIT_2 , i , cfg - > adc2_pattern [ i ] ) ;
}
}
}
adc_ll_digi_set_output_format ( cfg - > format ) ;
adc_ll_digi_convert_limit_enable ( ADC_LL_DEFAULT_CONV_LIMIT_EN ) ;
adc_ll_digi_set_convert_limit_num ( ADC_LL_DEFAULT_CONV_LIMIT_NUM ) ;
adc_ll_digi_set_data_source ( ADC_I2S_DATA_SRC_ADC ) ;
}
esp_err_t adc_set_i2s_data_source ( adc_i2s_source_t src )
{
ADC_CHECK ( ( src = = ADC_I2S_DATA_SRC_IO_SIG | | src = = ADC_I2S_DATA_SRC_ADC ) , " ADC i2s data source error " , ESP_ERR_INVALID_ARG ) ;
ADC_ENTER_CRITICAL ( ) ;
adc_ll_digi_set_data_source ( src ) ;
ADC_EXIT_CRITICAL ( ) ;
return ESP_OK ;
}
extern esp_err_t adc_common_gpio_init ( adc_unit_t adc_unit , adc_channel_t channel ) ;
esp_err_t adc_i2s_mode_init ( adc_unit_t adc_unit , adc_channel_t channel )
{
if ( adc_unit = = ADC_UNIT_1 ) {
ADC_CHANNEL_CHECK ( ADC_UNIT_1 , channel ) ;
} else if ( adc_unit = = ADC_UNIT_2 ) {
//ADC2 does not support DMA mode
ADC_CHECK ( false , " ADC2 not support DMA for now. " , ESP_ERR_INVALID_ARG ) ;
ADC_CHANNEL_CHECK ( ADC_UNIT_2 , channel ) ;
}
adc_digi_pattern_table_t adc1_pattern [ 1 ] ;
adc_digi_pattern_table_t adc2_pattern [ 1 ] ;
adc_digi_config_t dig_cfg = {
. format = DIG_ADC_OUTPUT_FORMAT_DEFUALT ,
. conv_mode = ADC_CONV_SINGLE_UNIT_1 ,
} ;
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 ;
} else 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_common_gpio_init ( adc_unit , channel ) ;
ADC_ENTER_CRITICAL ( ) ;
2023-02-13 02:53:31 -05:00
adc_ll_digi_set_fsm_time ( ADC_LL_FSM_RSTB_WAIT_DEFAULT , ADC_LL_FSM_START_WAIT_DEFAULT ,
ADC_LL_FSM_STANDBY_WAIT_DEFAULT ) ;
adc_ll_set_sample_cycle ( ADC_LL_SAMPLE_CYCLE_DEFAULT ) ;
adc_hal_pwdet_set_cct ( ADC_LL_PWDET_CCT_DEFAULT ) ;
adc_ll_digi_output_invert ( ADC_UNIT_1 , ADC_LL_DIGI_DATA_INVERT_DEFAULT ( ADC_UNIT_1 ) ) ;
adc_ll_digi_output_invert ( ADC_UNIT_2 , ADC_LL_DIGI_DATA_INVERT_DEFAULT ( ADC_UNIT_2 ) ) ;
adc_ll_digi_set_clk_div ( ADC_LL_DIGI_SAR_CLK_DIV_DEFAULT ) ;
2022-07-15 00:52:44 -04:00
adc_digi_controller_reg_set ( & dig_cfg ) ;
ADC_EXIT_CRITICAL ( ) ;
return ESP_OK ;
}
# endif //#if CONFIG_IDF_TARGET_ESP32