I recently bought an Esp32 which I want to integrate into a low power project. I'd like it to use as little power as possible, so utilising the ULP coprocessor is a no-brainer for me. The analog measurements should be stored in an array, so I can later evaluate the data on the Esp32's main processors. Heres my code (I started off by copying the adc example):
adc_ulp.S
Code: Select all
/* ADC1 channel 6, GPIO34 */
.set adc_channel_1, 6
/* ADC1 channel 7, GPIO36 */
.set adc_channel_2, 0
/* Configure the number of ADC samples to average on each measurement.
For convenience, make it a power of 2. */
.set adc_oversampling_factor_log, 2
.set adc_oversampling_factor, (1 << adc_oversampling_factor_log)
.set max_sample_seconds, 10
.set sample_frequency, 5
.set max_samples, max_sample_seconds * sample_frequency
.set max_samples_bytes, max_samples * 4
/* Define variables, which go into .bss section (zero-initialized data) */
.bss
.global adc_channel_1_threshold
adc_channel_1_threshold:
.long 0
.global adc_channel_2_threshold
adc_channel_2_threshold:
.long 0
/* Counter of measurements done */
.global sample_counter
sample_counter:
.long 0
.global channel_1_measurements
channel_1_measurements:
.fill max_samples_bytes
.global channel_2_measurements
channel_2_measurements:
.fill max_samples_bytes
/* Code goes into .text section */
.text
.global entry
entry:
/* increment sample counter */
//move r1, sample_counter
//ld r0, r1, 0
//add r0, r0, 1
//st r0, r1, 0
// r0 holds the loop count, r1 can be used again
//r1 will hold the first channel measurement, r2 will hold the second
// initialize the loop counter, reset r1 and r2
move r1, 0
move r2, 0
stage_rst
measure:
// store temporary measurements in r3
// measure first channel
adc r3, 0, adc_channel_1 + 1
add r1, r1, r3
// measure second channel
adc r3, 0, adc_channel_2 + 1
add r2, r2, r3
// repeat if we haven't measure enough samples for oversampling
stage_inc 1
jumps measure, adc_oversampling_factor, lt
// r3 can be used again
// divide by oversampling factor. Since its a power of two, we can >> ^^
rsh r1, r1, adc_oversampling_factor_log
rsh r2, r2, adc_oversampling_factor_log
// load sample counter into r0
move r3, sample_counter
ld r0, r3, 0
// store measurements in respective arrays
move r3, channel_1_measurements // load its address
add r3, r3, r0 // offset by loop-counter (zero based)
st r3, r1, 0 // and store the value
move r3, channel_2_measurements // load its address
add r3, r3, r0 // offset by loop-counter (zero based)
st r3, r1, 0 // and store the value
// increment our sample counter and store the value
move r3, sample_counter
add r0, r0, 1
st r0, r3, 0
jumpr wake_up, max_samples, ge // wake up when we stored enough values (compares max_samples with r0)
/* compare with high_thr; wake up if value > high_thr */
move r3, adc_channel_1_threshold
ld r3, r3, 0
sub r3, r3, r1
jump wake_up, ov
move r3, adc_channel_2_threshold
ld r3, r3, 0
sub r3, r3, r2
jump wake_up, ov
halt
wake_up:
wake
halt