test_adc_dma.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. // Copyright 2020 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. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include <sys/param.h>
  15. #include <string.h>
  16. #include "test_utils.h"
  17. #if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32, ESP32S2, ESP32S3)
  18. //API only supported for C3 now.
  19. #include "driver/adc.h"
  20. #include "esp_adc_cal.h"
  21. #include "esp_log.h"
  22. #define TEST_COUNT 4096
  23. #define MAX_ARRAY_SIZE 4096
  24. #define TEST_ATTEN ADC_ATTEN_MAX //Set to ADC_ATTEN_*db to test a single attenuation only
  25. static int s_adc_count[MAX_ARRAY_SIZE]={};
  26. static int s_adc_offset = -1;
  27. static int insert_point(uint32_t value)
  28. {
  29. const bool fixed_size = true;
  30. if (s_adc_offset < 0) {
  31. if (fixed_size) {
  32. TEST_ASSERT_GREATER_OR_EQUAL(4096, MAX_ARRAY_SIZE);
  33. s_adc_offset = 0; //Fixed to 0 because the array can hold all the data in 12 bits
  34. } else {
  35. s_adc_offset = MAX((int)value - MAX_ARRAY_SIZE/2, 0);
  36. }
  37. }
  38. if (!fixed_size && (value < s_adc_offset || value >= s_adc_offset + MAX_ARRAY_SIZE)) {
  39. TEST_ASSERT_GREATER_OR_EQUAL(s_adc_offset, value);
  40. TEST_ASSERT_LESS_THAN(s_adc_offset + MAX_ARRAY_SIZE, value);
  41. }
  42. s_adc_count[value - s_adc_offset] ++;
  43. return value - s_adc_offset;
  44. }
  45. static void reset_array(void)
  46. {
  47. memset(s_adc_count, 0, sizeof(s_adc_count));
  48. s_adc_offset = -1;
  49. }
  50. static uint32_t get_average(void)
  51. {
  52. uint32_t sum = 0;
  53. int count = 0;
  54. for (int i = 0; i < MAX_ARRAY_SIZE; i++) {
  55. sum += s_adc_count[i] * (s_adc_offset+i);
  56. count += s_adc_count[i];
  57. }
  58. return sum/count;
  59. }
  60. static void print_summary(bool figure)
  61. {
  62. const int MAX_WIDTH=20;
  63. int max_count = 0;
  64. int start = -1;
  65. int end = -1;
  66. uint32_t sum = 0;
  67. int count = 0;
  68. for (int i = 0; i < MAX_ARRAY_SIZE; i++) {
  69. if (s_adc_count[i] > max_count) {
  70. max_count = s_adc_count[i];
  71. }
  72. if (s_adc_count[i] > 0 && start < 0) {
  73. start = i;
  74. }
  75. if (s_adc_count[i] > 0) {
  76. end = i;
  77. }
  78. count += s_adc_count[i];
  79. sum += s_adc_count[i] * (s_adc_offset+i);
  80. }
  81. if (figure) {
  82. for (int i = start; i <= end; i++) {
  83. printf("%4d ", i+s_adc_offset);
  84. int count = s_adc_count[i] * MAX_WIDTH / max_count;
  85. for (int j = 0; j < count; j++) {
  86. putchar('|');
  87. }
  88. printf(" %d\n", s_adc_count[i]);
  89. }
  90. }
  91. float average = (float)sum/count;
  92. float variation_square = 0;
  93. for (int i = start; i <= end; i ++) {
  94. if (s_adc_count[i] == 0) {
  95. continue;
  96. }
  97. float delta = i + s_adc_offset - average;
  98. variation_square += (delta * delta) * s_adc_count[i];
  99. }
  100. printf("%d points.\n", count);
  101. printf("average: %.1f\n", (float)sum/count);
  102. printf("std: %.2f\n", sqrt(variation_square/count));
  103. }
  104. static void continuous_adc_init(uint16_t adc1_chan_mask, uint16_t adc2_chan_mask, adc_channel_t *channel, uint8_t channel_num, adc_atten_t atten)
  105. {
  106. adc_digi_init_config_t adc_dma_config = {
  107. .max_store_buf_size = TEST_COUNT*2,
  108. .conv_num_each_intr = 128,
  109. .adc1_chan_mask = adc1_chan_mask,
  110. .adc2_chan_mask = adc2_chan_mask,
  111. };
  112. TEST_ESP_OK(adc_digi_initialize(&adc_dma_config));
  113. adc_digi_pattern_table_t adc_pattern[10] = {0};
  114. adc_digi_config_t dig_cfg = {
  115. .conv_limit_en = 0,
  116. .conv_limit_num = 250,
  117. .sample_freq_hz = 83333,
  118. };
  119. dig_cfg.adc_pattern_len = channel_num;
  120. for (int i = 0; i < channel_num; i++) {
  121. uint8_t unit = ((channel[i] >> 3) & 0x1);
  122. uint8_t ch = channel[i] & 0x7;
  123. adc_pattern[i].atten = atten;
  124. adc_pattern[i].channel = ch;
  125. adc_pattern[i].unit = unit;
  126. }
  127. dig_cfg.adc_pattern = adc_pattern;
  128. TEST_ESP_OK(adc_digi_controller_config(&dig_cfg));
  129. }
  130. TEST_CASE("test_adc_dma", "[adc][ignore][manual]")
  131. {
  132. uint16_t adc1_chan_mask = BIT(2);
  133. uint16_t adc2_chan_mask = 0;
  134. adc_channel_t channel[1] = {ADC1_CHANNEL_2};
  135. adc_atten_t target_atten = TEST_ATTEN;
  136. const int output_data_size = sizeof(adc_digi_output_data_t);
  137. int buffer_size = TEST_COUNT*output_data_size;
  138. uint8_t* read_buf = malloc(buffer_size);
  139. TEST_ASSERT_NOT_NULL(read_buf);
  140. adc_atten_t atten;
  141. bool print_figure;
  142. if (target_atten == ADC_ATTEN_MAX) {
  143. atten = ADC_ATTEN_DB_0;
  144. target_atten = ADC_ATTEN_DB_11;
  145. print_figure = false;
  146. } else {
  147. atten = target_atten;
  148. print_figure = true;
  149. }
  150. while (1) {
  151. ESP_LOGI("TEST_ADC", "Test with atten: %d", atten);
  152. memset(read_buf, 0xce, buffer_size);
  153. bool do_calibration = false;
  154. esp_adc_cal_characteristics_t chan1_char = {};
  155. esp_adc_cal_value_t cal_ret = esp_adc_cal_characterize(ADC_UNIT_1, atten, ADC_WIDTH_12Bit, 0, &chan1_char);
  156. if (cal_ret == ESP_ADC_CAL_VAL_EFUSE_TP) {
  157. do_calibration = true;
  158. }
  159. continuous_adc_init(adc1_chan_mask, adc2_chan_mask, channel, sizeof(channel) / sizeof(adc_channel_t), atten);
  160. adc_digi_start();
  161. int remain_count = TEST_COUNT;
  162. while (remain_count) {
  163. int already_got = TEST_COUNT - remain_count;
  164. uint32_t ret_num;
  165. TEST_ESP_OK(adc_digi_read_bytes(read_buf + already_got*output_data_size,
  166. remain_count*output_data_size, &ret_num, ADC_MAX_DELAY));
  167. TEST_ASSERT((ret_num % output_data_size) == 0);
  168. remain_count -= ret_num / output_data_size;
  169. }
  170. adc_digi_output_data_t *p = (void*)read_buf;
  171. reset_array();
  172. for (int i = 0; i < TEST_COUNT; i++) {
  173. insert_point(p[i].type2.data);
  174. }
  175. print_summary(print_figure);
  176. if (do_calibration) {
  177. uint32_t raw = get_average();
  178. uint32_t voltage_mv = esp_adc_cal_raw_to_voltage(raw, &chan1_char);
  179. printf("Voltage = %d mV\n", voltage_mv);
  180. }
  181. adc_digi_stop();
  182. TEST_ESP_OK(adc_digi_deinitialize());
  183. if (atten == target_atten) {
  184. break;
  185. }
  186. atten++;
  187. }
  188. free(read_buf);
  189. }
  190. TEST_CASE("test_adc_single", "[adc][ignore][manual]")
  191. {
  192. adc_atten_t target_atten = TEST_ATTEN;
  193. adc_atten_t atten;
  194. bool print_figure;
  195. if (target_atten == ADC_ATTEN_MAX) {
  196. atten = ADC_ATTEN_DB_0;
  197. target_atten = ADC_ATTEN_DB_11;
  198. print_figure = false;
  199. } else {
  200. atten = target_atten;
  201. print_figure = true;
  202. }
  203. adc1_config_width(ADC_WIDTH_BIT_12);
  204. while (1) {
  205. ESP_LOGI("TEST_ADC", "Test with atten: %d", atten);
  206. adc1_config_channel_atten(ADC1_CHANNEL_2, atten);
  207. bool do_calibration = false;
  208. esp_adc_cal_characteristics_t chan1_char = {};
  209. esp_adc_cal_value_t cal_ret = esp_adc_cal_characterize(ADC_UNIT_1, atten, ADC_WIDTH_12Bit, 0, &chan1_char);
  210. if (cal_ret == ESP_ADC_CAL_VAL_EFUSE_TP) {
  211. do_calibration = true;
  212. }
  213. const int test_count = TEST_COUNT;
  214. adc1_channel_t channel = ADC1_CHANNEL_2;
  215. while (1) {
  216. reset_array();
  217. for (int i = 0; i < test_count; i++) {
  218. uint32_t raw = adc1_get_raw(channel);
  219. insert_point(raw);
  220. }
  221. print_summary(print_figure);
  222. break;
  223. }
  224. if (do_calibration) {
  225. uint32_t raw = get_average();
  226. uint32_t voltage_mv = esp_adc_cal_raw_to_voltage(raw, &chan1_char);
  227. printf("Voltage = %d mV\n", voltage_mv);
  228. }
  229. if (atten == target_atten) {
  230. break;
  231. }
  232. atten++;
  233. }
  234. }
  235. #endif