2021-03-11 11:11:53 +01:00
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
2016-12-08 22:43:41 +01:00
//
// 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 "esp32-hal-adc.h"
# include "freertos/FreeRTOS.h"
# include "freertos/task.h"
# include "esp_attr.h"
# include "soc/rtc_cntl_reg.h"
2020-01-20 14:18:56 +01:00
# include "driver/adc.h"
2021-04-05 13:23:58 +02:00
# include "esp_system.h"
# ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
# if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
# include "esp_adc_cal.h"
2021-04-14 17:10:05 +02:00
# include "soc/sens_reg.h"
# include "soc/rtc_io_reg.h"
2021-04-05 13:23:58 +02:00
# include "esp32/rom/ets_sys.h"
# include "esp_intr_alloc.h"
2020-01-20 14:18:56 +01:00
# define DEFAULT_VREF 1100
static esp_adc_cal_characteristics_t * __analogCharacteristics [ 2 ] = { NULL , NULL } ;
static uint16_t __analogVRef = 0 ;
static uint8_t __analogVRefPin = 0 ;
2021-04-05 13:23:58 +02:00
# elif CONFIG_IDF_TARGET_ESP32S2
# include "esp32s2/rom/ets_sys.h"
2021-04-14 17:10:05 +02:00
# include "soc/sens_reg.h"
# include "soc/rtc_io_reg.h"
# elif CONFIG_IDF_TARGET_ESP32C3
# include "esp32c3/rom/ets_sys.h"
2021-04-05 13:23:58 +02:00
# else
# error Target CONFIG_IDF_TARGET is not supported
# endif
# else // ESP32 Before IDF 4.0
# include "rom/ets_sys.h"
# include "esp_intr.h"
# endif
2017-03-03 14:53:20 +01:00
2021-04-05 13:23:58 +02:00
static uint8_t __analogAttenuation = 3 ; //11db
static uint8_t __analogWidth = 3 ; //12 bits
static uint8_t __analogClockDiv = 1 ;
2016-12-08 22:43:41 +01:00
void __analogSetClockDiv ( uint8_t clockDiv ) {
if ( ! clockDiv ) {
2020-01-20 14:18:56 +01:00
clockDiv = 1 ;
2016-12-08 22:43:41 +01:00
}
__analogClockDiv = clockDiv ;
2021-04-14 17:10:05 +02:00
# if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
2020-01-20 14:18:56 +01:00
adc_set_clk_div ( __analogClockDiv ) ;
2021-04-14 17:10:05 +02:00
# endif
2016-12-08 22:43:41 +01:00
}
2016-12-14 01:29:51 +01:00
void __analogSetAttenuation ( adc_attenuation_t attenuation )
{
2016-12-08 22:43:41 +01:00
__analogAttenuation = attenuation & 3 ;
}
2021-04-05 13:23:58 +02:00
# if CONFIG_IDF_TARGET_ESP32
void __analogSetWidth ( uint8_t bits ) {
if ( bits < 9 ) {
bits = 9 ;
} else if ( bits > 12 ) {
bits = 12 ;
}
__analogWidth = bits - 9 ;
adc1_config_width ( __analogWidth ) ;
}
# endif
2020-01-20 14:18:56 +01:00
void __analogInit ( ) {
2016-12-08 22:43:41 +01:00
static bool initialized = false ;
if ( initialized ) {
return ;
}
2020-01-20 14:18:56 +01:00
initialized = true ;
2016-12-08 22:43:41 +01:00
__analogSetClockDiv ( __analogClockDiv ) ;
2021-04-05 13:23:58 +02:00
# if CONFIG_IDF_TARGET_ESP32
2016-12-08 22:43:41 +01:00
__analogSetWidth ( __analogWidth + 9 ) ; //in bits
2021-04-05 13:23:58 +02:00
# endif
2016-12-08 22:43:41 +01:00
}
2016-12-14 01:29:51 +01:00
void __analogSetPinAttenuation ( uint8_t pin , adc_attenuation_t attenuation )
{
int8_t channel = digitalPinToAnalogChannel ( pin ) ;
if ( channel < 0 | | attenuation > 3 ) {
return ;
}
2020-01-20 14:18:56 +01:00
if ( channel > 9 ) {
adc2_config_channel_atten ( channel - 10 , attenuation ) ;
2016-12-14 01:29:51 +01:00
} else {
2020-01-20 14:18:56 +01:00
adc1_config_channel_atten ( channel , attenuation ) ;
2016-12-14 01:29:51 +01:00
}
2020-01-20 14:18:56 +01:00
__analogInit ( ) ;
2016-12-14 01:29:51 +01:00
}
2020-01-20 14:18:56 +01:00
bool __adcAttachPin ( uint8_t pin ) {
2016-12-08 22:43:41 +01:00
int8_t channel = digitalPinToAnalogChannel ( pin ) ;
if ( channel < 0 ) {
2020-01-20 14:18:56 +01:00
log_e ( " Pin %u is not ADC pin! " , pin ) ;
return false ;
2016-12-08 22:43:41 +01:00
}
2017-03-03 14:53:20 +01:00
int8_t pad = digitalPinToTouchChannel ( pin ) ;
2016-12-08 22:43:41 +01:00
if ( pad > = 0 ) {
2021-04-05 13:23:58 +02:00
# if CONFIG_IDF_TARGET_ESP32
2016-12-08 22:43:41 +01:00
uint32_t touch = READ_PERI_REG ( SENS_SAR_TOUCH_ENABLE_REG ) ;
if ( touch & ( 1 < < pad ) ) {
touch & = ~ ( ( 1 < < ( pad + SENS_TOUCH_PAD_OUTEN2_S ) )
| ( 1 < < ( pad + SENS_TOUCH_PAD_OUTEN1_S ) )
| ( 1 < < ( pad + SENS_TOUCH_PAD_WORKEN_S ) ) ) ;
WRITE_PERI_REG ( SENS_SAR_TOUCH_ENABLE_REG , touch ) ;
}
2021-04-05 13:23:58 +02:00
# endif
2021-04-14 17:10:05 +02:00
}
# if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
else if ( pin = = 25 ) {
2016-12-08 22:43:41 +01:00
CLEAR_PERI_REG_MASK ( RTC_IO_PAD_DAC1_REG , RTC_IO_PDAC1_XPD_DAC | RTC_IO_PDAC1_DAC_XPD_FORCE ) ; //stop dac1
} else if ( pin = = 26 ) {
CLEAR_PERI_REG_MASK ( RTC_IO_PAD_DAC2_REG , RTC_IO_PDAC2_XPD_DAC | RTC_IO_PDAC2_DAC_XPD_FORCE ) ; //stop dac2
}
2021-04-14 17:10:05 +02:00
# endif
2016-12-08 22:43:41 +01:00
pinMode ( pin , ANALOG ) ;
2020-01-20 14:18:56 +01:00
__analogSetPinAttenuation ( pin , __analogAttenuation ) ;
2017-03-03 14:53:20 +01:00
return true ;
}
2016-12-08 22:43:41 +01:00
2020-01-20 14:18:56 +01:00
void __analogReadResolution ( uint8_t bits )
{
if ( ! bits | | bits > 16 ) {
return ;
}
2021-04-05 13:23:58 +02:00
# if CONFIG_IDF_TARGET_ESP32
2020-01-20 14:18:56 +01:00
__analogSetWidth ( bits ) ; // hadware from 9 to 12
2021-04-05 13:23:58 +02:00
# endif
2020-01-20 14:18:56 +01:00
}
2016-12-08 22:43:41 +01:00
2020-01-20 14:18:56 +01:00
uint16_t __analogRead ( uint8_t pin )
{
2017-03-03 14:53:20 +01:00
int8_t channel = digitalPinToAnalogChannel ( pin ) ;
2020-01-20 14:18:56 +01:00
int value = 0 ;
esp_err_t r = ESP_OK ;
2017-03-03 14:53:20 +01:00
if ( channel < 0 ) {
2020-01-20 14:18:56 +01:00
log_e ( " Pin %u is not ADC pin! " , pin ) ;
return value ;
2017-03-03 14:53:20 +01:00
}
2020-01-20 14:18:56 +01:00
__adcAttachPin ( pin ) ;
2017-03-03 14:53:20 +01:00
if ( channel > 9 ) {
channel - = 10 ;
2020-01-20 14:18:56 +01:00
r = adc2_get_raw ( channel , __analogWidth , & value ) ;
if ( r = = ESP_OK ) {
return value ;
} else if ( r = = ESP_ERR_INVALID_STATE ) {
log_e ( " GPIO%u: %s: ADC2 not initialized yet. " , pin , esp_err_to_name ( r ) ) ;
} else if ( r = = ESP_ERR_TIMEOUT ) {
2021-07-08 12:58:17 +02:00
log_e ( " GPIO%u: %s: ADC2 is in use by Wi-Fi. Please see https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/adc.html#adc-limitations for more info " , pin , esp_err_to_name ( r ) ) ;
2020-01-20 14:18:56 +01:00
} else {
log_e ( " GPIO%u: %s " , pin , esp_err_to_name ( r ) ) ;
}
2017-03-03 14:53:20 +01:00
} else {
2020-01-20 14:18:56 +01:00
return adc1_get_raw ( channel ) ;
2016-12-08 22:43:41 +01:00
}
2020-01-20 14:18:56 +01:00
return value ;
2017-03-03 14:53:20 +01:00
}
2020-01-20 14:18:56 +01:00
uint32_t __analogReadMilliVolts ( uint8_t pin ) {
2017-03-03 14:53:20 +01:00
int8_t channel = digitalPinToAnalogChannel ( pin ) ;
if ( channel < 0 ) {
2020-01-20 14:18:56 +01:00
log_e ( " Pin %u is not ADC pin! " , pin ) ;
return 0 ;
2017-03-03 14:53:20 +01:00
}
2021-04-05 13:23:58 +02:00
# if CONFIG_IDF_TARGET_ESP32
2020-01-20 14:18:56 +01:00
if ( ! __analogVRef ) {
if ( esp_adc_cal_check_efuse ( ESP_ADC_CAL_VAL_EFUSE_TP ) = = ESP_OK ) {
log_d ( " eFuse Two Point: Supported " ) ;
__analogVRef = DEFAULT_VREF ;
}
if ( esp_adc_cal_check_efuse ( ESP_ADC_CAL_VAL_EFUSE_VREF ) = = ESP_OK ) {
log_d ( " eFuse Vref: Supported " ) ;
__analogVRef = DEFAULT_VREF ;
}
if ( ! __analogVRef ) {
__analogVRef = DEFAULT_VREF ;
if ( __analogVRefPin ) {
esp_adc_cal_characteristics_t chars ;
2021-04-05 13:23:58 +02:00
if ( adc_vref_to_gpio ( ADC_UNIT_2 , __analogVRefPin ) = = ESP_OK ) {
2020-01-20 14:18:56 +01:00
__analogVRef = __analogRead ( __analogVRefPin ) ;
esp_adc_cal_characterize ( 1 , __analogAttenuation , __analogWidth , DEFAULT_VREF , & chars ) ;
__analogVRef = esp_adc_cal_raw_to_voltage ( __analogVRef , & chars ) ;
log_d ( " Vref to GPIO%u: %u " , __analogVRefPin , __analogVRef ) ;
}
}
}
2017-03-03 14:53:20 +01:00
}
2020-01-20 14:18:56 +01:00
uint8_t unit = 1 ;
if ( channel > 9 ) {
unit = 2 ;
2017-03-03 14:53:20 +01:00
}
2020-01-20 14:18:56 +01:00
uint16_t adc_reading = __analogRead ( pin ) ;
if ( __analogCharacteristics [ unit - 1 ] = = NULL ) {
__analogCharacteristics [ unit - 1 ] = calloc ( 1 , sizeof ( esp_adc_cal_characteristics_t ) ) ;
if ( __analogCharacteristics [ unit - 1 ] = = NULL ) {
return 0 ;
}
esp_adc_cal_value_t val_type = esp_adc_cal_characterize ( unit , __analogAttenuation , __analogWidth , __analogVRef , __analogCharacteristics [ unit - 1 ] ) ;
if ( val_type = = ESP_ADC_CAL_VAL_EFUSE_TP ) {
log_i ( " ADC%u: Characterized using Two Point Value: %u \n " , unit , __analogCharacteristics [ unit - 1 ] - > vref ) ;
} else if ( val_type = = ESP_ADC_CAL_VAL_EFUSE_VREF ) {
log_i ( " ADC%u: Characterized using eFuse Vref: %u \n " , unit , __analogCharacteristics [ unit - 1 ] - > vref ) ;
} else if ( __analogVRef ! = DEFAULT_VREF ) {
log_i ( " ADC%u: Characterized using Vref to GPIO%u: %u \n " , unit , __analogVRefPin , __analogCharacteristics [ unit - 1 ] - > vref ) ;
} else {
log_i ( " ADC%u: Characterized using Default Vref: %u \n " , unit , __analogCharacteristics [ unit - 1 ] - > vref ) ;
}
2017-03-03 14:53:20 +01:00
}
2020-01-20 14:18:56 +01:00
return esp_adc_cal_raw_to_voltage ( adc_reading , __analogCharacteristics [ unit - 1 ] ) ;
2021-04-05 13:23:58 +02:00
# else
uint16_t adc_reading = __analogRead ( pin ) ;
uint16_t max_reading = 8191 ;
uint16_t max_mv = 1100 ;
switch ( __analogAttenuation ) {
case 3 : max_mv = 3900 ; break ;
case 2 : max_mv = 2200 ; break ;
case 1 : max_mv = 1500 ; break ;
default : break ;
}
return ( adc_reading * max_mv ) / max_reading ;
# endif
}
# if CONFIG_IDF_TARGET_ESP32
void __analogSetVRefPin ( uint8_t pin ) {
if ( pin < 25 | | pin > 27 ) {
pin = 0 ;
}
__analogVRefPin = pin ;
2016-12-08 22:43:41 +01:00
}
2016-12-14 01:29:51 +01:00
2021-06-10 10:58:08 +02:00
int __hallRead ( ) //hall sensor using idf read
2016-12-08 22:43:41 +01:00
{
pinMode ( 36 , ANALOG ) ;
pinMode ( 39 , ANALOG ) ;
2021-06-10 10:58:08 +02:00
__analogSetWidth ( 12 ) ;
return hall_sensor_read ( ) ;
2016-12-08 22:43:41 +01:00
}
2021-04-05 13:23:58 +02:00
# endif
2016-12-08 22:43:41 +01:00
extern uint16_t analogRead ( uint8_t pin ) __attribute__ ( ( weak , alias ( " __analogRead " ) ) ) ;
2021-04-05 13:23:58 +02:00
extern uint32_t analogReadMilliVolts ( uint8_t pin ) __attribute__ ( ( weak , alias ( " __analogReadMilliVolts " ) ) ) ;
2017-03-03 14:53:20 +01:00
extern void analogReadResolution ( uint8_t bits ) __attribute__ ( ( weak , alias ( " __analogReadResolution " ) ) ) ;
2016-12-08 22:43:41 +01:00
extern void analogSetClockDiv ( uint8_t clockDiv ) __attribute__ ( ( weak , alias ( " __analogSetClockDiv " ) ) ) ;
2016-12-14 01:29:51 +01:00
extern void analogSetAttenuation ( adc_attenuation_t attenuation ) __attribute__ ( ( weak , alias ( " __analogSetAttenuation " ) ) ) ;
extern void analogSetPinAttenuation ( uint8_t pin , adc_attenuation_t attenuation ) __attribute__ ( ( weak , alias ( " __analogSetPinAttenuation " ) ) ) ;
2017-03-03 14:53:20 +01:00
extern bool adcAttachPin ( uint8_t pin ) __attribute__ ( ( weak , alias ( " __adcAttachPin " ) ) ) ;
2020-01-20 14:18:56 +01:00
2021-04-05 13:23:58 +02:00
# if CONFIG_IDF_TARGET_ESP32
2020-01-20 14:18:56 +01:00
extern void analogSetVRefPin ( uint8_t pin ) __attribute__ ( ( weak , alias ( " __analogSetVRefPin " ) ) ) ;
2021-04-05 13:23:58 +02:00
extern void analogSetWidth ( uint8_t bits ) __attribute__ ( ( weak , alias ( " __analogSetWidth " ) ) ) ;
extern int hallRead ( ) __attribute__ ( ( weak , alias ( " __hallRead " ) ) ) ;
# endif