Skip to content

Commit af2ef7f

Browse files
author
blue-2357
committed
Add Arduino SAM compatible analogReadResolution and Non-Blocking ADC api
connected to: espressif/arduino-esp32#220 and espressif/arduino-esp32#161
1 parent 85ff99d commit af2ef7f

File tree

2 files changed

+125
-15
lines changed

2 files changed

+125
-15
lines changed

Diff for: cores/esp32/esp32-hal-adc.c

+86-14
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,16 @@ static uint8_t __analogCycles = 8;
2828
static uint8_t __analogSamples = 0;//1 sample
2929
static uint8_t __analogClockDiv = 1;
3030

31+
// Width of returned answer ()
32+
static uint8_t __analogReturnedWidth = 12;
33+
3134
void __analogSetWidth(uint8_t bits){
3235
if(bits < 9){
3336
bits = 9;
3437
} else if(bits > 12){
3538
bits = 12;
3639
}
40+
__analogReturnedWidth = bits;
3741
__analogWidth = bits - 9;
3842
SET_PERI_REG_BITS(SENS_SAR_START_FORCE_REG, SENS_SAR1_BIT_WIDTH, __analogWidth, SENS_SAR1_BIT_WIDTH_S);
3943
SET_PERI_REG_BITS(SENS_SAR_READ_CTRL_REG, SENS_SAR1_SAMPLE_BIT, __analogWidth, SENS_SAR1_SAMPLE_BIT_S);
@@ -124,14 +128,14 @@ void __analogSetPinAttenuation(uint8_t pin, adc_attenuation_t attenuation)
124128
}
125129
}
126130

127-
uint16_t IRAM_ATTR __analogRead(uint8_t pin)
128-
{
131+
bool IRAM_ATTR __adcAttachPin(uint8_t pin){
132+
129133
int8_t channel = digitalPinToAnalogChannel(pin);
130134
if(channel < 0){
131-
return 0;//not adc pin
135+
return false;//not adc pin
132136
}
133-
int8_t pad = digitalPinToTouchChannel(pin);
134137

138+
int8_t pad = digitalPinToTouchChannel(pin);
135139
if(pad >= 0){
136140
uint32_t touch = READ_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG);
137141
if(touch & (1 << pad)){
@@ -149,22 +153,84 @@ uint16_t IRAM_ATTR __analogRead(uint8_t pin)
149153
pinMode(pin, ANALOG);
150154

151155
__analogInit();
156+
return true;
157+
}
152158

153-
if(channel > 7){
154-
channel -= 10;
159+
bool IRAM_ATTR __adcStart(uint8_t pin){
155160

156-
SET_PERI_REG_BITS(SENS_SAR_MEAS_START2_REG, SENS_SAR2_EN_PAD, (1 << channel), SENS_SAR2_EN_PAD_S);
161+
int8_t channel = digitalPinToAnalogChannel(pin);
162+
if(channel < 0){
163+
return false;//not adc pin
164+
}
165+
166+
if(channel > 9){
167+
channel -= 10;
157168
CLEAR_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_START_SAR_M);
169+
SET_PERI_REG_BITS(SENS_SAR_MEAS_START2_REG, SENS_SAR2_EN_PAD, (1 << channel), SENS_SAR2_EN_PAD_S);
158170
SET_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_START_SAR_M);
159-
while (GET_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_DONE_SAR) == 0) {}; //read done
160-
return GET_PERI_REG_BITS2(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_DATA_SAR, SENS_MEAS2_DATA_SAR_S);
171+
} else {
172+
CLEAR_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_START_SAR_M);
173+
SET_PERI_REG_BITS(SENS_SAR_MEAS_START1_REG, SENS_SAR1_EN_PAD, (1 << channel), SENS_SAR1_EN_PAD_S);
174+
SET_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_START_SAR_M);
161175
}
176+
return true;
177+
}
178+
179+
bool IRAM_ATTR __adcBusy(uint8_t pin){
162180

163-
SET_PERI_REG_BITS(SENS_SAR_MEAS_START1_REG, SENS_SAR1_EN_PAD, (1 << channel), SENS_SAR1_EN_PAD_S);
164-
CLEAR_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_START_SAR_M);
165-
SET_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_START_SAR_M);
166-
while (GET_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_DONE_SAR) == 0) {}; //read done
167-
return GET_PERI_REG_BITS2(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_DATA_SAR, SENS_MEAS1_DATA_SAR_S);
181+
int8_t channel = digitalPinToAnalogChannel(pin);
182+
if(channel < 0){
183+
return false;//not adc pin
184+
}
185+
186+
if(channel > 7){
187+
return (GET_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_DONE_SAR) == 0);
188+
}
189+
return (GET_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_DONE_SAR) == 0);
190+
}
191+
192+
uint16_t IRAM_ATTR __adcEnd(uint8_t pin)
193+
{
194+
195+
uint16_t value = 0;
196+
int8_t channel = digitalPinToAnalogChannel(pin);
197+
if(channel < 0){
198+
return 0;//not adc pin
199+
}
200+
if(channel > 7){
201+
while (GET_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_DONE_SAR) == 0); //wait for conversion
202+
value = GET_PERI_REG_BITS2(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_DATA_SAR, SENS_MEAS2_DATA_SAR_S);
203+
} else {
204+
while (GET_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_DONE_SAR) == 0); //wait for conversion
205+
value = GET_PERI_REG_BITS2(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_DATA_SAR, SENS_MEAS1_DATA_SAR_S);
206+
}
207+
208+
// Shift result if necessary
209+
uint8_t from = __analogWidth + 9;
210+
if (from == __analogReturnedWidth) {
211+
return value;
212+
}
213+
if (from > __analogReturnedWidth) {
214+
return value >> (from - __analogReturnedWidth);
215+
}
216+
return value << (__analogReturnedWidth - from);
217+
}
218+
219+
uint16_t IRAM_ATTR __analogRead(uint8_t pin)
220+
{
221+
if(!__adcAttachPin(pin) || !__adcStart(pin)){
222+
return 0;
223+
}
224+
return __adcEnd(pin);
225+
}
226+
227+
void __analogReadResolution(uint8_t bits)
228+
{
229+
if(!bits || bits > 16){
230+
return;
231+
}
232+
__analogSetWidth(bits); // hadware from 9 to 12
233+
__analogReturnedWidth = bits; // software from 1 to 16
168234
}
169235

170236
int __hallRead() //hall sensor without LNA
@@ -192,10 +258,16 @@ int __hallRead() //hall sensor without LNA
192258
}
193259

194260
extern uint16_t analogRead(uint8_t pin) __attribute__ ((weak, alias("__analogRead")));
261+
extern void analogReadResolution(uint8_t bits) __attribute__ ((weak, alias("__analogReadResolution")));
195262
extern void analogSetWidth(uint8_t bits) __attribute__ ((weak, alias("__analogSetWidth")));
196263
extern void analogSetCycles(uint8_t cycles) __attribute__ ((weak, alias("__analogSetCycles")));
197264
extern void analogSetSamples(uint8_t samples) __attribute__ ((weak, alias("__analogSetSamples")));
198265
extern void analogSetClockDiv(uint8_t clockDiv) __attribute__ ((weak, alias("__analogSetClockDiv")));
199266
extern void analogSetAttenuation(adc_attenuation_t attenuation) __attribute__ ((weak, alias("__analogSetAttenuation")));
200267
extern void analogSetPinAttenuation(uint8_t pin, adc_attenuation_t attenuation) __attribute__ ((weak, alias("__analogSetPinAttenuation")));
201268
extern int hallRead() __attribute__ ((weak, alias("__hallRead")));
269+
270+
extern bool adcAttachPin(uint8_t pin) __attribute__ ((weak, alias("__adcAttachPin")));
271+
extern bool adcStart(uint8_t pin) __attribute__ ((weak, alias("__adcStart")));
272+
extern bool adcBusy(uint8_t pin) __attribute__ ((weak, alias("__adcBusy")));
273+
extern uint16_t adcEnd(uint8_t pin) __attribute__ ((weak, alias("__adcEnd")));

Diff for: cores/esp32/esp32-hal-adc.h

+39-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,16 @@ typedef enum {
3939
uint16_t analogRead(uint8_t pin);
4040

4141
/*
42-
* Sets the sample bits
42+
* Set the resolution of analogRead return values. Default is 12 bits (range from 0 to 4096).
43+
* If between 9 and 12, it will equal the set hardware resolution, else value will be shifted.
44+
* Range is 1 - 16
45+
*
46+
* Note: compatibility with Arduino SAM
47+
*/
48+
void analogReadResolution(uint8_t bits);
49+
50+
/*
51+
* Sets the sample bits and read resolution
4352
* Default is 12bit (0 - 4095)
4453
* Range is 9 - 12
4554
* */
@@ -88,6 +97,35 @@ void analogSetPinAttenuation(uint8_t pin, adc_attenuation_t attenuation);
8897
* */
8998
int hallRead();
9099

100+
/*
101+
* Non-Blocking API (almost)
102+
*
103+
* Note: ADC conversion can run only for single pin at a time.
104+
* That means that if you want to run ADC on two pins on the same bus,
105+
* you need to run them one after another. Probably the best use would be
106+
* to start conversion on both buses in parallel.
107+
* */
108+
109+
/*
110+
* Attach pin to ADC (will also clear any other analog mode that could be on)
111+
* */
112+
bool adcAttachPin(uint8_t pin);
113+
114+
/*
115+
* Start ADC conversion on attached pin's bus
116+
* */
117+
bool adcStart(uint8_t pin);
118+
119+
/*
120+
* Check if conversion on the pin's ADC bus is currently running
121+
* */
122+
bool adcBusy(uint8_t pin);
123+
124+
/*
125+
* Get the result of the conversion (will wait if it have not finished)
126+
* */
127+
uint16_t adcEnd(uint8_t pin);
128+
91129
#ifdef __cplusplus
92130
}
93131
#endif

0 commit comments

Comments
 (0)