esp_adc_cal_esp32.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. // http://www.apache.org/licenses/LICENSE-2.0
  7. //
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. #include <stdint.h>
  14. #include "esp_types.h"
  15. #include "driver/adc.h"
  16. #include "soc/efuse_periph.h"
  17. #include "esp_err.h"
  18. #include "assert.h"
  19. #include "esp_adc_cal.h"
  20. /* ----------------------------- Configuration ------------------------------ */
  21. #ifdef CONFIG_ADC_CAL_EFUSE_TP_ENABLE
  22. #define EFUSE_TP_ENABLED 1
  23. #else
  24. #define EFUSE_TP_ENABLED 0
  25. #endif
  26. #ifdef CONFIG_ADC_CAL_EFUSE_VREF_ENABLE
  27. #define EFUSE_VREF_ENABLED 1
  28. #else
  29. #define EFUSE_VREF_ENABLED 0
  30. #endif
  31. #ifdef CONFIG_ADC_CAL_LUT_ENABLE
  32. #define LUT_ENABLED 1
  33. #else
  34. #define LUT_ENABLED 0
  35. #endif
  36. /* ESP32s with both Two Point Values and Vref burned into eFuse are required to
  37. * also also burn the EFUSE_BLK3_PART_RESERVE flag. A limited set of ESP32s
  38. * (not available through regular sales channel) DO NOT have the
  39. * EFUSE_BLK3_PART_RESERVE burned. Moreover, this set of ESP32s represents Vref
  40. * in Two's Complement format. If this is the case, modify the preprocessor
  41. * definitions below as follows...
  42. * #define CHECK_BLK3_FLAG 0 //Do not check BLK3 flag as it is not burned
  43. * #define VREF_FORMAT 1 //eFuse Vref is in Two's Complement format
  44. */
  45. #define CHECK_BLK3_FLAG 1
  46. #define VREF_FORMAT 0
  47. /* ------------------------------ eFuse Access ----------------------------- */
  48. #define BLK3_RESERVED_REG EFUSE_BLK0_RDATA3_REG
  49. #define VREF_REG EFUSE_BLK0_RDATA4_REG
  50. #define VREF_MASK 0x1F
  51. #define VREF_STEP_SIZE 7
  52. #define VREF_OFFSET 1100
  53. #define TP_REG EFUSE_BLK3_RDATA3_REG
  54. #define TP_LOW1_OFFSET 278
  55. #define TP_LOW2_OFFSET 421
  56. #define TP_LOW_MASK 0x7F
  57. #define TP_LOW_VOLTAGE 150
  58. #define TP_HIGH1_OFFSET 3265
  59. #define TP_HIGH2_OFFSET 3406
  60. #define TP_HIGH_MASK 0x1FF
  61. #define TP_HIGH_VOLTAGE 850
  62. #define TP_STEP_SIZE 4
  63. /* ----------------------- Raw to Voltage Constants ------------------------- */
  64. #define LIN_COEFF_A_SCALE 65536
  65. #define LIN_COEFF_A_ROUND (LIN_COEFF_A_SCALE/2)
  66. #define LUT_VREF_LOW 1000
  67. #define LUT_VREF_HIGH 1200
  68. #define LUT_ADC_STEP_SIZE 64
  69. #define LUT_POINTS 20
  70. #define LUT_LOW_THRESH 2880
  71. #define LUT_HIGH_THRESH (LUT_LOW_THRESH + LUT_ADC_STEP_SIZE)
  72. #define ADC_12_BIT_RES 4096
  73. #define ADC_CAL_CHECK(cond, ret) ({ \
  74. if(!(cond)){ \
  75. return ret; \
  76. } \
  77. })
  78. /* ------------------------ Characterization Constants ---------------------- */
  79. static const uint32_t adc1_tp_atten_scale[4] = {65504, 86975, 120389, 224310};
  80. static const uint32_t adc2_tp_atten_scale[4] = {65467, 86861, 120416, 224708};
  81. static const uint32_t adc1_tp_atten_offset[4] = {0, 1, 27, 54};
  82. static const uint32_t adc2_tp_atten_offset[4] = {0, 9, 26, 66};
  83. static const uint32_t adc1_vref_atten_scale[4] = {57431, 76236, 105481, 196602};
  84. static const uint32_t adc2_vref_atten_scale[4] = {57236, 76175, 105678, 197170};
  85. static const uint32_t adc1_vref_atten_offset[4] = {75, 78, 107, 142};
  86. static const uint32_t adc2_vref_atten_offset[4] = {63, 66, 89, 128};
  87. //20 Point lookup tables, covering ADC readings from 2880 to 4096, step size of 64
  88. static const uint32_t lut_adc1_low[LUT_POINTS] = {2240, 2297, 2352, 2405, 2457, 2512, 2564, 2616, 2664, 2709,
  89. 2754, 2795, 2832, 2868, 2903, 2937, 2969, 3000, 3030, 3060};
  90. static const uint32_t lut_adc1_high[LUT_POINTS] = {2667, 2706, 2745, 2780, 2813, 2844, 2873, 2901, 2928, 2956,
  91. 2982, 3006, 3032, 3059, 3084, 3110, 3135, 3160, 3184, 3209};
  92. static const uint32_t lut_adc2_low[LUT_POINTS] = {2238, 2293, 2347, 2399, 2451, 2507, 2561, 2613, 2662, 2710,
  93. 2754, 2792, 2831, 2869, 2904, 2937, 2968, 2999, 3029, 3059};
  94. static const uint32_t lut_adc2_high[LUT_POINTS] = {2657, 2698, 2738, 2774, 2807, 2838, 2867, 2894, 2921, 2946,
  95. 2971, 2996, 3020, 3043, 3067, 3092, 3116, 3139, 3162, 3185};
  96. /* ----------------------- EFuse Access Functions --------------------------- */
  97. static bool check_efuse_vref(void)
  98. {
  99. //Check if Vref is burned in eFuse
  100. return (REG_GET_FIELD(VREF_REG, EFUSE_RD_ADC_VREF) != 0) ? true : false;
  101. }
  102. static bool check_efuse_tp(void)
  103. {
  104. //Check if Two Point values are burned in eFuse
  105. if (CHECK_BLK3_FLAG && (REG_GET_FIELD(BLK3_RESERVED_REG, EFUSE_RD_BLK3_PART_RESERVE) == 0)) {
  106. return false;
  107. }
  108. //All TP cal values must be non zero
  109. if ((REG_GET_FIELD(TP_REG, EFUSE_RD_ADC1_TP_LOW) != 0) &&
  110. (REG_GET_FIELD(TP_REG, EFUSE_RD_ADC2_TP_LOW) != 0) &&
  111. (REG_GET_FIELD(TP_REG, EFUSE_RD_ADC1_TP_HIGH) != 0) &&
  112. (REG_GET_FIELD(TP_REG, EFUSE_RD_ADC2_TP_HIGH) != 0)) {
  113. return true;
  114. } else {
  115. return false;
  116. }
  117. }
  118. static inline int decode_bits(uint32_t bits, uint32_t mask, bool is_twos_compl)
  119. {
  120. int ret;
  121. if (bits & (~(mask >> 1) & mask)) { //Check sign bit (MSB of mask)
  122. //Negative
  123. if (is_twos_compl) {
  124. ret = -(((~bits) + 1) & (mask >> 1)); //2's complement
  125. } else {
  126. ret = -(bits & (mask >> 1)); //Sign-magnitude
  127. }
  128. } else {
  129. //Positive
  130. ret = bits & (mask >> 1);
  131. }
  132. return ret;
  133. }
  134. static uint32_t read_efuse_vref(void)
  135. {
  136. //eFuse stores deviation from ideal reference voltage
  137. uint32_t ret = VREF_OFFSET; //Ideal vref
  138. uint32_t bits = REG_GET_FIELD(VREF_REG, EFUSE_ADC_VREF);
  139. ret += decode_bits(bits, VREF_MASK, VREF_FORMAT) * VREF_STEP_SIZE;
  140. return ret; //ADC Vref in mV
  141. }
  142. static uint32_t read_efuse_tp_low(adc_unit_t adc_num)
  143. {
  144. //ADC reading at 150mV stored in two's complement format
  145. uint32_t ret;
  146. uint32_t bits;
  147. if (adc_num == ADC_UNIT_1) {
  148. ret = TP_LOW1_OFFSET;
  149. bits = REG_GET_FIELD(TP_REG, EFUSE_RD_ADC1_TP_LOW);
  150. } else {
  151. ret = TP_LOW2_OFFSET;
  152. bits = REG_GET_FIELD(TP_REG, EFUSE_RD_ADC2_TP_LOW);
  153. }
  154. ret += decode_bits(bits, TP_LOW_MASK, true) * TP_STEP_SIZE;
  155. return ret; //Reading of ADC at 150mV
  156. }
  157. static uint32_t read_efuse_tp_high(adc_unit_t adc_num)
  158. {
  159. //ADC reading at 850mV stored in two's complement format
  160. uint32_t ret;
  161. uint32_t bits;
  162. if (adc_num == ADC_UNIT_1) {
  163. ret = TP_HIGH1_OFFSET;
  164. bits = REG_GET_FIELD(TP_REG, EFUSE_RD_ADC1_TP_HIGH);
  165. } else {
  166. ret = TP_HIGH2_OFFSET;
  167. bits = REG_GET_FIELD(TP_REG, EFUSE_RD_ADC2_TP_HIGH);
  168. }
  169. ret += decode_bits(bits, TP_HIGH_MASK, true) * TP_STEP_SIZE;
  170. return ret; //Reading of ADC at 850mV
  171. }
  172. /* ----------------------- Characterization Functions ----------------------- */
  173. static void characterize_using_two_point(adc_unit_t adc_num,
  174. adc_atten_t atten,
  175. uint32_t high,
  176. uint32_t low,
  177. uint32_t *coeff_a,
  178. uint32_t *coeff_b)
  179. {
  180. const uint32_t *atten_scales;
  181. const uint32_t *atten_offsets;
  182. if (adc_num == ADC_UNIT_1) { //Using ADC 1
  183. atten_scales = adc1_tp_atten_scale;
  184. atten_offsets = adc1_tp_atten_offset;
  185. } else { //Using ADC 2
  186. atten_scales = adc2_tp_atten_scale;
  187. atten_offsets = adc2_tp_atten_offset;
  188. }
  189. //Characterize ADC-Voltage curve as y = (coeff_a * x) + coeff_b
  190. uint32_t delta_x = high - low;
  191. uint32_t delta_v = TP_HIGH_VOLTAGE - TP_LOW_VOLTAGE;
  192. //Where coeff_a = (delta_v/delta_x) * atten_scale
  193. *coeff_a = (delta_v * atten_scales[atten] + (delta_x / 2)) / delta_x; //+(delta_x/2) for rounding
  194. //Where coeff_b = high_v - ((delta_v/delta_x) * high_x) + atten_offset
  195. *coeff_b = TP_HIGH_VOLTAGE - ((delta_v * high + (delta_x / 2)) / delta_x) + atten_offsets[atten];
  196. }
  197. static void characterize_using_vref(adc_unit_t adc_num,
  198. adc_atten_t atten,
  199. uint32_t vref,
  200. uint32_t *coeff_a,
  201. uint32_t *coeff_b)
  202. {
  203. const uint32_t *atten_scales;
  204. const uint32_t *atten_offsets;
  205. if (adc_num == ADC_UNIT_1) { //Using ADC 1
  206. atten_scales = adc1_vref_atten_scale;
  207. atten_offsets = adc1_vref_atten_offset;
  208. } else { //Using ADC 2
  209. atten_scales = adc2_vref_atten_scale;
  210. atten_offsets = adc2_vref_atten_offset;
  211. }
  212. //Characterize ADC-Voltage curve as y = (coeff_a * x) + coeff_b
  213. //Where coeff_a = (vref/4096) * atten_scale
  214. *coeff_a = (vref * atten_scales[atten]) / (ADC_12_BIT_RES);
  215. *coeff_b = atten_offsets[atten];
  216. }
  217. /* ------------------------ Conversion Functions --------------------------- */
  218. static uint32_t calculate_voltage_linear(uint32_t adc_reading, uint32_t coeff_a, uint32_t coeff_b)
  219. {
  220. //Where voltage = coeff_a * adc_reading + coeff_b
  221. return (((coeff_a * adc_reading) + LIN_COEFF_A_ROUND) / LIN_COEFF_A_SCALE) + coeff_b;
  222. }
  223. //Only call when ADC reading is above threshold
  224. static uint32_t calculate_voltage_lut(uint32_t adc, uint32_t vref, const uint32_t *low_vref_curve, const uint32_t *high_vref_curve)
  225. {
  226. //Get index of lower bound points of LUT
  227. uint32_t i = (adc - LUT_LOW_THRESH) / LUT_ADC_STEP_SIZE;
  228. //Let the X Axis be Vref, Y axis be ADC reading, and Z be voltage
  229. int x2dist = LUT_VREF_HIGH - vref; //(x2 - x)
  230. int x1dist = vref - LUT_VREF_LOW; //(x - x1)
  231. int y2dist = ((i + 1) * LUT_ADC_STEP_SIZE) + LUT_LOW_THRESH - adc; //(y2 - y)
  232. int y1dist = adc - ((i * LUT_ADC_STEP_SIZE) + LUT_LOW_THRESH); //(y - y1)
  233. //For points for bilinear interpolation
  234. int q11 = low_vref_curve[i]; //Lower bound point of low_vref_curve
  235. int q12 = low_vref_curve[i + 1]; //Upper bound point of low_vref_curve
  236. int q21 = high_vref_curve[i]; //Lower bound point of high_vref_curve
  237. int q22 = high_vref_curve[i + 1]; //Upper bound point of high_vref_curve
  238. //Bilinear interpolation
  239. //Where z = 1/((x2-x1)*(y2-y1)) * ( (q11*x2dist*y2dist) + (q21*x1dist*y2dist) + (q12*x2dist*y1dist) + (q22*x1dist*y1dist) )
  240. int voltage = (q11 * x2dist * y2dist) + (q21 * x1dist * y2dist) + (q12 * x2dist * y1dist) + (q22 * x1dist * y1dist);
  241. voltage += ((LUT_VREF_HIGH - LUT_VREF_LOW) * LUT_ADC_STEP_SIZE) / 2; //Integer division rounding
  242. voltage /= ((LUT_VREF_HIGH - LUT_VREF_LOW) * LUT_ADC_STEP_SIZE); //Divide by ((x2-x1)*(y2-y1))
  243. return (uint32_t)voltage;
  244. }
  245. static inline uint32_t interpolate_two_points(uint32_t y1, uint32_t y2, uint32_t x_step, uint32_t x)
  246. {
  247. //Interpolate between two points (x1,y1) (x2,y2) between 'lower' and 'upper' separated by 'step'
  248. return ((y1 * x_step) + (y2 * x) - (y1 * x) + (x_step / 2)) / x_step;
  249. }
  250. /* ------------------------- Public API ------------------------------------- */
  251. esp_err_t esp_adc_cal_check_efuse(esp_adc_cal_value_t source)
  252. {
  253. if (source == ESP_ADC_CAL_VAL_EFUSE_TP) {
  254. return (check_efuse_tp()) ? ESP_OK : ESP_ERR_NOT_SUPPORTED;
  255. } else if (source == ESP_ADC_CAL_VAL_EFUSE_VREF) {
  256. return (check_efuse_vref()) ? ESP_OK : ESP_ERR_NOT_SUPPORTED;
  257. } else {
  258. return ESP_ERR_INVALID_ARG;
  259. }
  260. }
  261. esp_adc_cal_value_t esp_adc_cal_characterize(adc_unit_t adc_num,
  262. adc_atten_t atten,
  263. adc_bits_width_t bit_width,
  264. uint32_t default_vref,
  265. esp_adc_cal_characteristics_t *chars)
  266. {
  267. //Check parameters
  268. assert((adc_num == ADC_UNIT_1) || (adc_num == ADC_UNIT_2));
  269. assert(chars != NULL);
  270. assert(bit_width < ADC_WIDTH_MAX);
  271. //Check eFuse if enabled to do so
  272. bool efuse_tp_present = check_efuse_tp();
  273. bool efuse_vref_present = check_efuse_vref();
  274. esp_adc_cal_value_t ret;
  275. if (efuse_tp_present && EFUSE_TP_ENABLED) {
  276. //Characterize based on Two Point values
  277. uint32_t high = read_efuse_tp_high(adc_num);
  278. uint32_t low = read_efuse_tp_low(adc_num);
  279. characterize_using_two_point(adc_num, atten, high, low, &chars->coeff_a, &chars->coeff_b);
  280. ret = ESP_ADC_CAL_VAL_EFUSE_TP;
  281. } else if (efuse_vref_present && EFUSE_VREF_ENABLED) {
  282. //Characterize based on eFuse Vref
  283. uint32_t vref = read_efuse_vref();
  284. characterize_using_vref(adc_num, atten, vref, &chars->coeff_a, &chars->coeff_b);
  285. ret = ESP_ADC_CAL_VAL_EFUSE_VREF;
  286. } else {
  287. //Characterized based on default Vref
  288. characterize_using_vref(adc_num, atten, default_vref, &chars->coeff_a, &chars->coeff_b);
  289. ret = ESP_ADC_CAL_VAL_DEFAULT_VREF;
  290. }
  291. //Initialized remaining fields
  292. chars->adc_num = adc_num;
  293. chars->atten = atten;
  294. chars->bit_width = bit_width;
  295. chars->vref = (EFUSE_VREF_ENABLED && efuse_vref_present) ? read_efuse_vref() : default_vref;
  296. //Initialize fields for lookup table if necessary
  297. if (LUT_ENABLED && atten == ADC_ATTEN_DB_11) {
  298. chars->low_curve = (adc_num == ADC_UNIT_1) ? lut_adc1_low : lut_adc2_low;
  299. chars->high_curve = (adc_num == ADC_UNIT_1) ? lut_adc1_high : lut_adc2_high;
  300. } else {
  301. chars->low_curve = NULL;
  302. chars->high_curve = NULL;
  303. }
  304. return ret;
  305. }
  306. uint32_t esp_adc_cal_raw_to_voltage(uint32_t adc_reading, const esp_adc_cal_characteristics_t *chars)
  307. {
  308. assert(chars != NULL);
  309. //Scale adc_rading if not 12 bits wide
  310. adc_reading = (adc_reading << (ADC_WIDTH_BIT_12 - chars->bit_width));
  311. if (adc_reading > ADC_12_BIT_RES - 1) {
  312. adc_reading = ADC_12_BIT_RES - 1; //Set to 12bit res max
  313. }
  314. if (LUT_ENABLED && (chars->atten == ADC_ATTEN_DB_11) && (adc_reading >= LUT_LOW_THRESH)) { //Check if in non-linear region
  315. //Use lookup table to get voltage in non linear portion of ADC_ATTEN_DB_11
  316. uint32_t lut_voltage = calculate_voltage_lut(adc_reading, chars->vref, chars->low_curve, chars->high_curve);
  317. if (adc_reading <= LUT_HIGH_THRESH) { //If ADC is transitioning from linear region to non-linear region
  318. //Linearly interpolate between linear voltage and lut voltage
  319. uint32_t linear_voltage = calculate_voltage_linear(adc_reading, chars->coeff_a, chars->coeff_b);
  320. return interpolate_two_points(linear_voltage, lut_voltage, LUT_ADC_STEP_SIZE, (adc_reading - LUT_LOW_THRESH));
  321. } else {
  322. return lut_voltage;
  323. }
  324. } else {
  325. return calculate_voltage_linear(adc_reading, chars->coeff_a, chars->coeff_b);
  326. }
  327. }
  328. esp_err_t esp_adc_cal_get_voltage(adc_channel_t channel,
  329. const esp_adc_cal_characteristics_t *chars,
  330. uint32_t *voltage)
  331. {
  332. //Check parameters
  333. ADC_CAL_CHECK(chars != NULL, ESP_ERR_INVALID_ARG);
  334. ADC_CAL_CHECK(voltage != NULL, ESP_ERR_INVALID_ARG);
  335. int adc_reading;
  336. if (chars->adc_num == ADC_UNIT_1) {
  337. //Check channel is valid on ADC1
  338. ADC_CAL_CHECK((adc1_channel_t)channel < ADC1_CHANNEL_MAX, ESP_ERR_INVALID_ARG);
  339. adc_reading = adc1_get_raw(channel);
  340. } else {
  341. //Check channel is valid on ADC2
  342. ADC_CAL_CHECK((adc2_channel_t)channel < ADC2_CHANNEL_MAX, ESP_ERR_INVALID_ARG);
  343. if (adc2_get_raw(channel, chars->bit_width, &adc_reading) != ESP_OK) {
  344. return ESP_ERR_TIMEOUT; //Timed out waiting for ADC2
  345. }
  346. }
  347. *voltage = esp_adc_cal_raw_to_voltage((uint32_t)adc_reading, chars);
  348. return ESP_OK;
  349. }