button_adc.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. /* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
  2. *
  3. * SPDX-License-Identifier: Apache-2.0
  4. */
  5. #include <string.h>
  6. #include <inttypes.h>
  7. #include "esp_log.h"
  8. #include "esp_timer.h"
  9. #include "esp_idf_version.h"
  10. #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
  11. #include "soc/soc_caps.h"
  12. #include "esp_adc/adc_oneshot.h"
  13. #include "esp_adc/adc_cali.h"
  14. #include "esp_adc/adc_cali_scheme.h"
  15. #else
  16. #include "driver/gpio.h"
  17. #include "driver/adc.h"
  18. #include "esp_adc_cal.h"
  19. #endif
  20. #include "button_adc.h"
  21. #include "hal/adc_hal.h"
  22. static const char *TAG = "adc button";
  23. #define ADC_BTN_CHECK(a, str, ret_val) \
  24. if (!(a)) \
  25. { \
  26. printf("%s(%d): %s", __FUNCTION__, __LINE__, str); \
  27. return (ret_val); \
  28. }
  29. #define DEFAULT_VREF 1100
  30. #define NO_OF_SAMPLES CONFIG_ADC_BUTTON_SAMPLE_TIMES //Multisampling
  31. #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
  32. #define ADC_BUTTON_WIDTH SOC_ADC_RTC_MAX_BITWIDTH
  33. #define ADC1_BUTTON_CHANNEL_MAX SOC_ADC_MAX_CHANNEL_NUM
  34. #define ADC_BUTTON_ATTEN ADC_ATTEN_DB_11
  35. #else
  36. #define ADC_BUTTON_WIDTH ADC_WIDTH_MAX-1
  37. #define ADC1_BUTTON_CHANNEL_MAX ADC1_CHANNEL_MAX
  38. #define ADC_BUTTON_ATTEN ADC_ATTEN_DB_11
  39. #endif
  40. #define ADC_BUTTON_ADC_UNIT ADC_UNIT_1
  41. #define ADC_BUTTON_MAX_CHANNEL CONFIG_ADC_BUTTON_MAX_CHANNEL
  42. #define ADC_BUTTON_MAX_BUTTON CONFIG_ADC_BUTTON_MAX_BUTTON_PER_CHANNEL
  43. typedef struct {
  44. uint16_t min;
  45. uint16_t max;
  46. } button_data_t;
  47. typedef struct {
  48. uint8_t channel;
  49. uint8_t is_init;
  50. button_data_t btns[ADC_BUTTON_MAX_BUTTON]; /* all button on the channel */
  51. uint64_t last_time; /* the last time of adc sample */
  52. } btn_adc_channel_t;
  53. typedef struct {
  54. bool is_configured;
  55. #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
  56. adc_cali_handle_t adc1_cali_handle;
  57. adc_oneshot_unit_handle_t adc1_handle;
  58. #else
  59. esp_adc_cal_characteristics_t adc_chars;
  60. #endif
  61. btn_adc_channel_t ch[ADC_BUTTON_MAX_CHANNEL];
  62. uint8_t ch_num;
  63. } adc_button_t;
  64. static adc_button_t g_button = {0};
  65. static int find_unused_channel(void)
  66. {
  67. for (size_t i = 0; i < ADC_BUTTON_MAX_CHANNEL; i++) {
  68. if (0 == g_button.ch[i].is_init) {
  69. return i;
  70. }
  71. }
  72. return -1;
  73. }
  74. static int find_channel(uint8_t channel)
  75. {
  76. for (size_t i = 0; i < ADC_BUTTON_MAX_CHANNEL; i++) {
  77. if (channel == g_button.ch[i].channel) {
  78. return i;
  79. }
  80. }
  81. return -1;
  82. }
  83. #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
  84. static esp_err_t adc_calibration_init(adc_unit_t unit, adc_atten_t atten, adc_cali_handle_t *out_handle)
  85. {
  86. adc_cali_handle_t handle = NULL;
  87. esp_err_t ret = ESP_FAIL;
  88. bool calibrated = false;
  89. #if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
  90. if (!calibrated) {
  91. ESP_LOGI(TAG, "calibration scheme version is %s", "Curve Fitting");
  92. adc_cali_curve_fitting_config_t cali_config = {
  93. .unit_id = unit,
  94. .atten = atten,
  95. .bitwidth = ADC_BUTTON_WIDTH,
  96. };
  97. ret = adc_cali_create_scheme_curve_fitting(&cali_config, &handle);
  98. if (ret == ESP_OK) {
  99. calibrated = true;
  100. }
  101. }
  102. #endif
  103. #if ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED
  104. if (!calibrated) {
  105. ESP_LOGI(TAG, "calibration scheme version is %s", "Line Fitting");
  106. adc_cali_line_fitting_config_t cali_config = {
  107. .unit_id = unit,
  108. .atten = atten,
  109. .bitwidth = ADC_BUTTON_WIDTH,
  110. };
  111. ret = adc_cali_create_scheme_line_fitting(&cali_config, &handle);
  112. if (ret == ESP_OK) {
  113. calibrated = true;
  114. }
  115. }
  116. #endif
  117. *out_handle = handle;
  118. if (ret == ESP_OK) {
  119. ESP_LOGI(TAG, "Calibration Success");
  120. } else if (ret == ESP_ERR_NOT_SUPPORTED || !calibrated) {
  121. ESP_LOGW(TAG, "eFuse not burnt, skip software calibration");
  122. } else {
  123. ESP_LOGE(TAG, "Invalid arg or no memory");
  124. }
  125. return calibrated?ESP_OK:ESP_FAIL;
  126. }
  127. #endif
  128. esp_err_t button_adc_init(const button_adc_config_t *config)
  129. {
  130. ADC_BTN_CHECK(NULL != config, "Pointer of config is invalid", ESP_ERR_INVALID_ARG);
  131. ADC_BTN_CHECK(config->adc_channel < ADC1_BUTTON_CHANNEL_MAX, "channel out of range", ESP_ERR_NOT_SUPPORTED);
  132. ADC_BTN_CHECK(config->button_index < ADC_BUTTON_MAX_BUTTON, "button_index out of range", ESP_ERR_NOT_SUPPORTED);
  133. ADC_BTN_CHECK(config->max > 0, "key max voltage invalid", ESP_ERR_INVALID_ARG);
  134. int ch_index = find_channel(config->adc_channel);
  135. if (ch_index >= 0) { /**< the channel has been initialized */
  136. ADC_BTN_CHECK(g_button.ch[ch_index].btns[config->button_index].max == 0, "The button_index has been used", ESP_ERR_INVALID_STATE);
  137. } else { /**< this is a new channel */
  138. int unused_ch_index = find_unused_channel();
  139. ADC_BTN_CHECK(unused_ch_index >= 0, "exceed max channel number, can't create a new channel", ESP_ERR_INVALID_STATE);
  140. ch_index = unused_ch_index;
  141. }
  142. /** initialize adc */
  143. if (0 == g_button.is_configured) {
  144. #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
  145. esp_err_t ret;
  146. if (NULL == config->adc_handle) {
  147. //ADC1 Init
  148. adc_oneshot_unit_init_cfg_t init_config = {
  149. .unit_id = ADC_UNIT_1,
  150. };
  151. ret = adc_oneshot_new_unit(&init_config, &g_button.adc1_handle);
  152. ADC_BTN_CHECK(ret == ESP_OK, "adc oneshot new unit fail!", ESP_FAIL);
  153. } else {
  154. g_button.adc1_handle = *config->adc_handle ;
  155. ESP_LOGI(TAG, "ADC1 has been initialized");
  156. }
  157. #else
  158. //Configure ADC
  159. adc1_config_width(ADC_BUTTON_WIDTH);
  160. //Characterize ADC
  161. esp_adc_cal_value_t val_type = esp_adc_cal_characterize(ADC_BUTTON_ADC_UNIT, ADC_BUTTON_ATTEN, ADC_BUTTON_WIDTH, DEFAULT_VREF, &g_button.adc_chars);
  162. if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) {
  163. ESP_LOGI(TAG, "Characterized using Two Point Value");
  164. } else if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) {
  165. ESP_LOGI(TAG, "Characterized using eFuse Vref");
  166. } else {
  167. ESP_LOGI(TAG, "Characterized using Default Vref");
  168. }
  169. #endif
  170. g_button.is_configured = 1;
  171. }
  172. /** initialize adc channel */
  173. if (0 == g_button.ch[ch_index].is_init) {
  174. #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
  175. //ADC1 Config
  176. adc_oneshot_chan_cfg_t oneshot_config = {
  177. .bitwidth = ADC_BUTTON_WIDTH,
  178. .atten = ADC_BUTTON_ATTEN,
  179. };
  180. esp_err_t ret = adc_oneshot_config_channel(g_button.adc1_handle, config->adc_channel, &oneshot_config);
  181. ADC_BTN_CHECK(ret == ESP_OK, "adc oneshot config channel fail!", ESP_FAIL);
  182. //-------------ADC1 Calibration Init---------------//
  183. ret = adc_calibration_init(ADC_BUTTON_ADC_UNIT, ADC_BUTTON_ATTEN, &g_button.adc1_cali_handle);
  184. ADC_BTN_CHECK(ret == ESP_OK, "ADC1 Calibration Init False", 0);
  185. #else
  186. adc1_config_channel_atten(config->adc_channel, ADC_BUTTON_ATTEN);
  187. #endif
  188. g_button.ch[ch_index].channel = config->adc_channel;
  189. g_button.ch[ch_index].is_init = 1;
  190. g_button.ch[ch_index].last_time = 0;
  191. }
  192. g_button.ch[ch_index].btns[config->button_index].max = config->max;
  193. g_button.ch[ch_index].btns[config->button_index].min = config->min;
  194. g_button.ch_num++;
  195. return ESP_OK;
  196. }
  197. esp_err_t button_adc_deinit(uint8_t channel, int button_index)
  198. {
  199. ADC_BTN_CHECK(channel < ADC1_BUTTON_CHANNEL_MAX, "channel out of range", ESP_ERR_INVALID_ARG);
  200. ADC_BTN_CHECK(button_index < ADC_BUTTON_MAX_BUTTON, "button_index out of range", ESP_ERR_INVALID_ARG);
  201. int ch_index = find_channel(channel);
  202. ADC_BTN_CHECK(ch_index >= 0, "can't find the channel", ESP_ERR_INVALID_ARG);
  203. g_button.ch[ch_index].btns[button_index].max = 0;
  204. g_button.ch[ch_index].btns[button_index].min = 0;
  205. /** check button usage on the channel*/
  206. uint8_t unused_button = 0;
  207. for (size_t i = 0; i < ADC_BUTTON_MAX_BUTTON; i++) {
  208. if (0 == g_button.ch[ch_index].btns[i].max) {
  209. unused_button++;
  210. }
  211. }
  212. if (unused_button == ADC_BUTTON_MAX_BUTTON && g_button.ch[ch_index].is_init) { /**< if all button is unused, deinit the channel */
  213. g_button.ch[ch_index].is_init = 0;
  214. g_button.ch[ch_index].channel = ADC1_BUTTON_CHANNEL_MAX;
  215. ESP_LOGD(TAG, "all button is unused on channel%d, deinit the channel", g_button.ch[ch_index].channel);
  216. }
  217. /** check channel usage on the adc*/
  218. uint8_t unused_ch = 0;
  219. for (size_t i = 0; i < ADC_BUTTON_MAX_CHANNEL; i++) {
  220. if (0 == g_button.ch[i].is_init) {
  221. unused_ch++;
  222. }
  223. }
  224. if (unused_ch == ADC_BUTTON_MAX_CHANNEL && g_button.is_configured) { /**< if all channel is unused, deinit the adc */
  225. g_button.is_configured = false;
  226. memset(&g_button, 0, sizeof(adc_button_t));
  227. ESP_LOGD(TAG, "all channel is unused, , deinit adc");
  228. }
  229. #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
  230. esp_err_t ret = adc_oneshot_del_unit(g_button.adc1_handle);
  231. ADC_BTN_CHECK(ret == ESP_OK, "adc oneshot deinit fail", ESP_FAIL);
  232. #endif
  233. return ESP_OK;
  234. }
  235. int i = 0;
  236. static uint32_t get_adc_volatge(uint8_t channel)
  237. {
  238. uint32_t adc_reading = 0;
  239. #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
  240. int adc_raw = 0;
  241. for (int i = 0; i < NO_OF_SAMPLES; i++) {
  242. //adc_ll_set_power_manage(ADC_POWER_BY_FSM);
  243. adc_oneshot_read(g_button.adc1_handle, channel, &adc_raw);
  244. //adc_ll_set_power_manage(ADC_POWER_SW_OFF);
  245. adc_reading += adc_raw;
  246. }
  247. adc_reading /= NO_OF_SAMPLES;
  248. //Convert adc_reading to voltage in mV
  249. int voltage = 0;
  250. adc_cali_raw_to_voltage(g_button.adc1_cali_handle, adc_reading, &voltage);
  251. // ESP_LOGV(TAG, "Raw: %"PRIu32"\tVoltage: %dmV", adc_reading, voltage);
  252. // printf("Raw: %"PRIu32"\tVoltage: %"PRIu32"mV\r\n", adc_reading, voltage);
  253. // i++;
  254. // if(i>100)
  255. // {
  256. // i = 0;
  257. // printf("Raw: %lu Voltage: %d mV\r\n", adc_reading, voltage);
  258. // }
  259. #else
  260. //Multisampling
  261. for (int i = 0; i < NO_OF_SAMPLES; i++) {
  262. adc_reading += adc1_get_raw(channel);
  263. }
  264. adc_reading /= NO_OF_SAMPLES;
  265. //Convert adc_reading to voltage in mV
  266. uint32_t voltage = esp_adc_cal_raw_to_voltage(adc_reading, &g_button.adc_chars);
  267. ESP_LOGV(TAG, "Raw: %"PRIu32"\tVoltage: %"PRIu32"mV", adc_reading, voltage);
  268. i++;
  269. if(i>10000)
  270. {
  271. i = 0;
  272. printf("Raw: %lu Voltage: %d mV\r\n", adc_reading, voltage);
  273. }
  274. #endif
  275. return voltage;
  276. }
  277. uint8_t button_adc_get_key_level(void *button_index)
  278. {
  279. static uint16_t vol = 0;
  280. uint32_t ch = ADC_BUTTON_SPLIT_CHANNEL(button_index);
  281. uint32_t index = ADC_BUTTON_SPLIT_INDEX(button_index);
  282. ADC_BTN_CHECK(ch < ADC1_BUTTON_CHANNEL_MAX, "channel out of range", 0);
  283. ADC_BTN_CHECK(index < ADC_BUTTON_MAX_BUTTON, "button_index out of range", 0);
  284. int ch_index = find_channel(ch);
  285. ADC_BTN_CHECK(ch_index >= 0, "The button_index is not init", 0);
  286. /** It starts only when the elapsed time is more than 1ms */
  287. if ((esp_timer_get_time() - g_button.ch[ch_index].last_time) > 1000) {
  288. vol = get_adc_volatge(ch);
  289. // i++;
  290. // if(i>100)
  291. // {
  292. // i = 0;
  293. // printf("adc vol = %d ch = %ld,index = %ld,ch_index = %d\r\n",vol,ch,index,ch_index);
  294. // }
  295. //printf("adc vol = %d\r\n",vol);
  296. g_button.ch[ch_index].last_time = esp_timer_get_time();
  297. }
  298. // printf("adc vol = %d ch = %ld,index = %ld,ch_index = %d\r\n",vol,ch,index,ch_index);
  299. // printf("adc vol = %d ch = %ld,index = %ld,ch_index = %d\r\n",vol,ch,index,ch_index);
  300. // printf("max = %d\r\n",g_button.ch[ch_index].btns[index].max);
  301. // printf("min = %d\r\n",g_button.ch[ch_index].btns[index].min);
  302. if (vol <= g_button.ch[ch_index].btns[index].max &&
  303. vol >= g_button.ch[ch_index].btns[index].min) {
  304. return 1;
  305. }
  306. return 0;
  307. }