eb46978a8d
connected to: https://github.com/espressif/arduino-esp32/issues/220 and https://github.com/espressif/arduino-esp32/issues/161
274 lines
11 KiB
C
274 lines
11 KiB
C
// Copyright 2015-2016 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 "esp32-hal-adc.h"
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
#include "rom/ets_sys.h"
|
|
#include "esp_attr.h"
|
|
#include "esp_intr.h"
|
|
#include "soc/rtc_io_reg.h"
|
|
#include "soc/rtc_cntl_reg.h"
|
|
#include "soc/sens_reg.h"
|
|
|
|
static uint8_t __analogAttenuation = 3;//11db
|
|
static uint8_t __analogWidth = 3;//12 bits
|
|
static uint8_t __analogCycles = 8;
|
|
static uint8_t __analogSamples = 0;//1 sample
|
|
static uint8_t __analogClockDiv = 1;
|
|
|
|
// Width of returned answer ()
|
|
static uint8_t __analogReturnedWidth = 12;
|
|
|
|
void __analogSetWidth(uint8_t bits){
|
|
if(bits < 9){
|
|
bits = 9;
|
|
} else if(bits > 12){
|
|
bits = 12;
|
|
}
|
|
__analogReturnedWidth = bits;
|
|
__analogWidth = bits - 9;
|
|
SET_PERI_REG_BITS(SENS_SAR_START_FORCE_REG, SENS_SAR1_BIT_WIDTH, __analogWidth, SENS_SAR1_BIT_WIDTH_S);
|
|
SET_PERI_REG_BITS(SENS_SAR_READ_CTRL_REG, SENS_SAR1_SAMPLE_BIT, __analogWidth, SENS_SAR1_SAMPLE_BIT_S);
|
|
|
|
SET_PERI_REG_BITS(SENS_SAR_START_FORCE_REG, SENS_SAR2_BIT_WIDTH, __analogWidth, SENS_SAR2_BIT_WIDTH_S);
|
|
SET_PERI_REG_BITS(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_SAMPLE_BIT, __analogWidth, SENS_SAR2_SAMPLE_BIT_S);
|
|
}
|
|
|
|
void __analogSetCycles(uint8_t cycles){
|
|
__analogCycles = cycles;
|
|
SET_PERI_REG_BITS(SENS_SAR_READ_CTRL_REG, SENS_SAR1_SAMPLE_CYCLE, __analogCycles, SENS_SAR1_SAMPLE_CYCLE_S);
|
|
SET_PERI_REG_BITS(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_SAMPLE_CYCLE, __analogCycles, SENS_SAR2_SAMPLE_CYCLE_S);
|
|
}
|
|
|
|
void __analogSetSamples(uint8_t samples){
|
|
if(!samples){
|
|
return;
|
|
}
|
|
__analogSamples = samples - 1;
|
|
SET_PERI_REG_BITS(SENS_SAR_READ_CTRL_REG, SENS_SAR1_SAMPLE_NUM, __analogSamples, SENS_SAR1_SAMPLE_NUM_S);
|
|
SET_PERI_REG_BITS(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_SAMPLE_NUM, __analogSamples, SENS_SAR2_SAMPLE_NUM_S);
|
|
}
|
|
|
|
void __analogSetClockDiv(uint8_t clockDiv){
|
|
if(!clockDiv){
|
|
return;
|
|
}
|
|
__analogClockDiv = clockDiv;
|
|
SET_PERI_REG_BITS(SENS_SAR_READ_CTRL_REG, SENS_SAR1_CLK_DIV, __analogClockDiv, SENS_SAR1_CLK_DIV_S);
|
|
SET_PERI_REG_BITS(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_CLK_DIV, __analogClockDiv, SENS_SAR2_CLK_DIV_S);
|
|
}
|
|
|
|
void __analogSetAttenuation(adc_attenuation_t attenuation)
|
|
{
|
|
__analogAttenuation = attenuation & 3;
|
|
uint32_t att_data = 0;
|
|
int i = 10;
|
|
while(i--){
|
|
att_data |= __analogAttenuation << (i * 2);
|
|
}
|
|
WRITE_PERI_REG(SENS_SAR_ATTEN1_REG, att_data & 0xFFFF);//ADC1 has 8 channels
|
|
WRITE_PERI_REG(SENS_SAR_ATTEN2_REG, att_data);
|
|
}
|
|
|
|
void IRAM_ATTR __analogInit(){
|
|
static bool initialized = false;
|
|
if(initialized){
|
|
return;
|
|
}
|
|
|
|
__analogSetAttenuation(__analogAttenuation);
|
|
__analogSetCycles(__analogCycles);
|
|
__analogSetSamples(__analogSamples + 1);//in samples
|
|
__analogSetClockDiv(__analogClockDiv);
|
|
__analogSetWidth(__analogWidth + 9);//in bits
|
|
|
|
SET_PERI_REG_MASK(SENS_SAR_READ_CTRL_REG, SENS_SAR1_DATA_INV);
|
|
SET_PERI_REG_MASK(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_DATA_INV);
|
|
|
|
SET_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_START_FORCE_M); //SAR ADC1 controller (in RTC) is started by SW
|
|
SET_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_SAR1_EN_PAD_FORCE_M); //SAR ADC1 pad enable bitmap is controlled by SW
|
|
SET_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_START_FORCE_M); //SAR ADC2 controller (in RTC) is started by SW
|
|
SET_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_SAR2_EN_PAD_FORCE_M); //SAR ADC2 pad enable bitmap is controlled by SW
|
|
|
|
CLEAR_PERI_REG_MASK(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR_M); //force XPD_SAR=0, use XPD_FSM
|
|
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_AMP, 0x2, SENS_FORCE_XPD_AMP_S); //force XPD_AMP=0
|
|
|
|
CLEAR_PERI_REG_MASK(SENS_SAR_MEAS_CTRL_REG, 0xfff << SENS_AMP_RST_FB_FSM_S); //clear FSM
|
|
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT1_REG, SENS_SAR_AMP_WAIT1, 0x1, SENS_SAR_AMP_WAIT1_S);
|
|
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT1_REG, SENS_SAR_AMP_WAIT2, 0x1, SENS_SAR_AMP_WAIT2_S);
|
|
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_SAR_AMP_WAIT3, 0x1, SENS_SAR_AMP_WAIT3_S);
|
|
while (GET_PERI_REG_BITS2(SENS_SAR_SLAVE_ADDR1_REG, 0x7, SENS_MEAS_STATUS_S) != 0); //wait det_fsm==
|
|
|
|
initialized = true;
|
|
}
|
|
|
|
void __analogSetPinAttenuation(uint8_t pin, adc_attenuation_t attenuation)
|
|
{
|
|
int8_t channel = digitalPinToAnalogChannel(pin);
|
|
if(channel < 0 || attenuation > 3){
|
|
return ;
|
|
}
|
|
__analogInit();
|
|
if(channel > 7){
|
|
SET_PERI_REG_BITS(SENS_SAR_ATTEN2_REG, 3, attenuation, ((channel - 10) * 2));
|
|
} else {
|
|
SET_PERI_REG_BITS(SENS_SAR_ATTEN1_REG, 3, attenuation, (channel * 2));
|
|
}
|
|
}
|
|
|
|
bool IRAM_ATTR __adcAttachPin(uint8_t pin){
|
|
|
|
int8_t channel = digitalPinToAnalogChannel(pin);
|
|
if(channel < 0){
|
|
return false;//not adc pin
|
|
}
|
|
|
|
int8_t pad = digitalPinToTouchChannel(pin);
|
|
if(pad >= 0){
|
|
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);
|
|
}
|
|
} else if(pin == 25){
|
|
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
|
|
}
|
|
|
|
pinMode(pin, ANALOG);
|
|
|
|
__analogInit();
|
|
return true;
|
|
}
|
|
|
|
bool IRAM_ATTR __adcStart(uint8_t pin){
|
|
|
|
int8_t channel = digitalPinToAnalogChannel(pin);
|
|
if(channel < 0){
|
|
return false;//not adc pin
|
|
}
|
|
|
|
if(channel > 9){
|
|
channel -= 10;
|
|
CLEAR_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_START_SAR_M);
|
|
SET_PERI_REG_BITS(SENS_SAR_MEAS_START2_REG, SENS_SAR2_EN_PAD, (1 << channel), SENS_SAR2_EN_PAD_S);
|
|
SET_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_START_SAR_M);
|
|
} else {
|
|
CLEAR_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_START_SAR_M);
|
|
SET_PERI_REG_BITS(SENS_SAR_MEAS_START1_REG, SENS_SAR1_EN_PAD, (1 << channel), SENS_SAR1_EN_PAD_S);
|
|
SET_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_START_SAR_M);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool IRAM_ATTR __adcBusy(uint8_t pin){
|
|
|
|
int8_t channel = digitalPinToAnalogChannel(pin);
|
|
if(channel < 0){
|
|
return false;//not adc pin
|
|
}
|
|
|
|
if(channel > 7){
|
|
return (GET_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_DONE_SAR) == 0);
|
|
}
|
|
return (GET_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_DONE_SAR) == 0);
|
|
}
|
|
|
|
uint16_t IRAM_ATTR __adcEnd(uint8_t pin)
|
|
{
|
|
|
|
uint16_t value = 0;
|
|
int8_t channel = digitalPinToAnalogChannel(pin);
|
|
if(channel < 0){
|
|
return 0;//not adc pin
|
|
}
|
|
if(channel > 7){
|
|
while (GET_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_DONE_SAR) == 0); //wait for conversion
|
|
value = GET_PERI_REG_BITS2(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_DATA_SAR, SENS_MEAS2_DATA_SAR_S);
|
|
} else {
|
|
while (GET_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_DONE_SAR) == 0); //wait for conversion
|
|
value = GET_PERI_REG_BITS2(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_DATA_SAR, SENS_MEAS1_DATA_SAR_S);
|
|
}
|
|
|
|
// Shift result if necessary
|
|
uint8_t from = __analogWidth + 9;
|
|
if (from == __analogReturnedWidth) {
|
|
return value;
|
|
}
|
|
if (from > __analogReturnedWidth) {
|
|
return value >> (from - __analogReturnedWidth);
|
|
}
|
|
return value << (__analogReturnedWidth - from);
|
|
}
|
|
|
|
uint16_t IRAM_ATTR __analogRead(uint8_t pin)
|
|
{
|
|
if(!__adcAttachPin(pin) || !__adcStart(pin)){
|
|
return 0;
|
|
}
|
|
return __adcEnd(pin);
|
|
}
|
|
|
|
void __analogReadResolution(uint8_t bits)
|
|
{
|
|
if(!bits || bits > 16){
|
|
return;
|
|
}
|
|
__analogSetWidth(bits); // hadware from 9 to 12
|
|
__analogReturnedWidth = bits; // software from 1 to 16
|
|
}
|
|
|
|
int __hallRead() //hall sensor without LNA
|
|
{
|
|
int Sens_Vp0;
|
|
int Sens_Vn0;
|
|
int Sens_Vp1;
|
|
int Sens_Vn1;
|
|
|
|
pinMode(36, ANALOG);
|
|
pinMode(39, ANALOG);
|
|
SET_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL1_REG, SENS_XPD_HALL_FORCE_M); // hall sens force enable
|
|
SET_PERI_REG_MASK(RTC_IO_HALL_SENS_REG, RTC_IO_XPD_HALL); // xpd hall
|
|
SET_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL1_REG, SENS_HALL_PHASE_FORCE_M); // phase force
|
|
CLEAR_PERI_REG_MASK(RTC_IO_HALL_SENS_REG, RTC_IO_HALL_PHASE); // hall phase
|
|
Sens_Vp0 = __analogRead(36);
|
|
Sens_Vn0 = __analogRead(39);
|
|
SET_PERI_REG_MASK(RTC_IO_HALL_SENS_REG, RTC_IO_HALL_PHASE);
|
|
Sens_Vp1 = __analogRead(36);
|
|
Sens_Vn1 = __analogRead(39);
|
|
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR, 0, SENS_FORCE_XPD_SAR_S);
|
|
CLEAR_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL1_REG, SENS_XPD_HALL_FORCE);
|
|
CLEAR_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL1_REG, SENS_HALL_PHASE_FORCE);
|
|
return (Sens_Vp1 - Sens_Vp0) - (Sens_Vn1 - Sens_Vn0);
|
|
}
|
|
|
|
extern uint16_t analogRead(uint8_t pin) __attribute__ ((weak, alias("__analogRead")));
|
|
extern void analogReadResolution(uint8_t bits) __attribute__ ((weak, alias("__analogReadResolution")));
|
|
extern void analogSetWidth(uint8_t bits) __attribute__ ((weak, alias("__analogSetWidth")));
|
|
extern void analogSetCycles(uint8_t cycles) __attribute__ ((weak, alias("__analogSetCycles")));
|
|
extern void analogSetSamples(uint8_t samples) __attribute__ ((weak, alias("__analogSetSamples")));
|
|
extern void analogSetClockDiv(uint8_t clockDiv) __attribute__ ((weak, alias("__analogSetClockDiv")));
|
|
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")));
|
|
extern int hallRead() __attribute__ ((weak, alias("__hallRead")));
|
|
|
|
extern bool adcAttachPin(uint8_t pin) __attribute__ ((weak, alias("__adcAttachPin")));
|
|
extern bool adcStart(uint8_t pin) __attribute__ ((weak, alias("__adcStart")));
|
|
extern bool adcBusy(uint8_t pin) __attribute__ ((weak, alias("__adcBusy")));
|
|
extern uint16_t adcEnd(uint8_t pin) __attribute__ ((weak, alias("__adcEnd")));
|