2017-08-07 13:33:01 +00:00
|
|
|
// 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 <stdint.h>
|
|
|
|
#include "driver/adc.h"
|
|
|
|
|
|
|
|
#include "esp_adc_cal.h"
|
|
|
|
|
|
|
|
static const esp_adc_cal_lookup_table_t *table_ptrs[4] = {&esp_adc_cal_table_atten_0,
|
|
|
|
&esp_adc_cal_table_atten_1,
|
|
|
|
&esp_adc_cal_table_atten_2,
|
|
|
|
&esp_adc_cal_table_atten_3};
|
|
|
|
|
|
|
|
uint32_t get_adc_vref_from_efuse()
|
|
|
|
{
|
|
|
|
//TODO: Replaced with read to eFuse once ATE confirms location of 5 bits
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void esp_adc_cal_get_characteristics(uint32_t v_ref,
|
|
|
|
adc_atten_t atten,
|
|
|
|
adc_bits_width_t bit_width,
|
|
|
|
esp_adc_cal_characteristics_t *chars)
|
|
|
|
{
|
|
|
|
chars->v_ref = v_ref;
|
|
|
|
chars->table = table_ptrs[atten];
|
|
|
|
chars->bit_width = bit_width;
|
|
|
|
if (v_ref >= ADC_CAL_LOW_V_REF) {
|
|
|
|
chars->gain = ((chars->v_ref - ADC_CAL_LOW_V_REF)
|
|
|
|
* chars->table->gain_m)
|
|
|
|
+ chars->table->gain_c;
|
|
|
|
chars->offset = (((chars->v_ref - ADC_CAL_LOW_V_REF)
|
|
|
|
* chars->table->offset_m)
|
|
|
|
+ chars->table->offset_c
|
|
|
|
+ ((1 << ADC_CAL_OFFSET_SCALE) / 2))
|
|
|
|
>> ADC_CAL_OFFSET_SCALE; //Bit shift to cancel 2^10 multiplier
|
|
|
|
chars->ideal_offset = (((ADC_CAL_IDEAL_V_REF - ADC_CAL_LOW_V_REF)
|
|
|
|
* chars->table->offset_m)
|
|
|
|
+ chars->table->offset_c
|
|
|
|
+ ((1 << ADC_CAL_OFFSET_SCALE) / 2)) //Rounding
|
|
|
|
>> ADC_CAL_OFFSET_SCALE;
|
|
|
|
} else { //For case where v_ref is smaller than low bound resulting in negative
|
|
|
|
chars->gain = chars->table->gain_c
|
|
|
|
- ((ADC_CAL_LOW_V_REF - chars->v_ref)
|
|
|
|
* chars->table->gain_m);
|
|
|
|
chars->offset = (chars->table->offset_c
|
|
|
|
- ((chars->v_ref - ADC_CAL_LOW_V_REF)
|
|
|
|
* chars->table->offset_m)
|
|
|
|
+ ((1 << ADC_CAL_OFFSET_SCALE) / 2)) //Rounding
|
|
|
|
>> ADC_CAL_OFFSET_SCALE; //Bit shift to cancel 2^10 multiplier
|
|
|
|
chars->ideal_offset = (chars->table->offset_c
|
|
|
|
- ((ADC_CAL_IDEAL_V_REF - ADC_CAL_LOW_V_REF)
|
|
|
|
* chars->table->offset_m)
|
|
|
|
+ ((1 << ADC_CAL_OFFSET_SCALE) / 2)) //Rounding
|
|
|
|
>> ADC_CAL_OFFSET_SCALE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint32_t esp_adc_cal_interpolate_round(uint32_t lower, uint32_t upper,
|
|
|
|
uint32_t step, uint32_t point)
|
|
|
|
{
|
|
|
|
//Interpolate 'point' between 'lower' and 'upper' seperated by 'step'
|
|
|
|
return ((lower * step) - (lower * point) + (upper * point) + (step / 2)) / step;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t esp_adc_cal_raw_to_voltage(uint32_t adc,
|
|
|
|
const esp_adc_cal_characteristics_t *chars)
|
|
|
|
{
|
|
|
|
//Scale ADC to 12 bit width (0 to 4095)
|
2017-08-23 15:12:56 +00:00
|
|
|
adc <<= (ADC_WIDTH_BIT_12 - chars->bit_width);
|
2017-08-07 13:33:01 +00:00
|
|
|
uint32_t i = (adc >> chars->table->bit_shift); //find index for lut voltages
|
|
|
|
//Refernce LUT to obtain voltage using index
|
|
|
|
uint32_t voltage = esp_adc_cal_interpolate_round(chars->table->voltage[i],
|
|
|
|
chars->table->voltage[i + 1],
|
|
|
|
(1 << chars->table->bit_shift),
|
|
|
|
adc - (i << chars->table->bit_shift));
|
|
|
|
/*
|
|
|
|
* Apply Gain, scaling(bit shift) and offset to interpolated voltage
|
|
|
|
* v_true = (((v_id - off_id)*gain)*scaling) + off_true
|
|
|
|
*/
|
|
|
|
if (voltage > chars->ideal_offset) {
|
|
|
|
voltage = (voltage - chars->ideal_offset) * chars->gain;
|
|
|
|
voltage += (1 << ADC_CAL_GAIN_SCALE) / 2; //For rounding when scaled
|
|
|
|
voltage >>= ADC_CAL_GAIN_SCALE;
|
|
|
|
voltage += chars->offset;
|
|
|
|
} else { //For case where voltage is less than ideal offset leading to negative value
|
|
|
|
voltage = ((chars->ideal_offset - voltage) * chars->gain);
|
|
|
|
voltage += (1 << ADC_CAL_GAIN_SCALE) / 2; //For rounding when scaled
|
|
|
|
voltage >>= ADC_CAL_GAIN_SCALE;
|
|
|
|
voltage = chars->offset - voltage;
|
|
|
|
}
|
|
|
|
|
|
|
|
return voltage;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t adc1_to_voltage(adc1_channel_t channel, const esp_adc_cal_characteristics_t *chars)
|
|
|
|
{
|
|
|
|
return esp_adc_cal_raw_to_voltage((uint32_t)adc1_get_raw(channel), chars);
|
|
|
|
}
|
|
|
|
|