test_touch_button.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <time.h>
  5. #include "freertos/FreeRTOS.h"
  6. #include "freertos/task.h"
  7. #include "freertos/queue.h"
  8. #include "freertos/semphr.h"
  9. #include "unity.h"
  10. #include "touch_element/touch_element_private.h"
  11. #include "touch_element/touch_button.h"
  12. static portMUX_TYPE test_button_spinlock = portMUX_INITIALIZER_UNLOCKED;
  13. #define TEST_BUTTON_ENTER_CRITICAL() portENTER_CRITICAL(&test_button_spinlock)
  14. #define TEST_BUTTON_EXIT_CRITICAL() portEXIT_CRITICAL(&test_button_spinlock)
  15. static const touch_pad_t button_channel_array[14] = {
  16. TOUCH_PAD_NUM1,
  17. TOUCH_PAD_NUM2,
  18. TOUCH_PAD_NUM3,
  19. TOUCH_PAD_NUM4,
  20. TOUCH_PAD_NUM5,
  21. TOUCH_PAD_NUM6,
  22. TOUCH_PAD_NUM7,
  23. TOUCH_PAD_NUM8,
  24. TOUCH_PAD_NUM9,
  25. TOUCH_PAD_NUM10,
  26. TOUCH_PAD_NUM11,
  27. TOUCH_PAD_NUM12,
  28. TOUCH_PAD_NUM13,
  29. TOUCH_PAD_NUM14,
  30. };
  31. const uint8_t BUTTON_CHANNEL_NUM = sizeof(button_channel_array) / sizeof(touch_pad_t);
  32. typedef struct {
  33. QueueHandle_t valid_msg_handle;
  34. SemaphoreHandle_t response_sig_handle;
  35. } test_monitor_t;
  36. typedef struct {
  37. QueueHandle_t valid_msg_handle;
  38. SemaphoreHandle_t response_sig_handle;
  39. touch_button_handle_t button_handle;
  40. } test_concurrent_monitor_t;
  41. /* ------------------------------------------------------------------------------------------------------------------ */
  42. void test_button_event_simulator(touch_button_handle_t button_handle, touch_button_event_t button_event);
  43. void test_button_event_check(touch_elem_message_t *valid_message, touch_elem_message_t *current_message);
  44. static void test_button_callback_check(touch_button_handle_t current_handle, touch_button_message_t *current_message, touch_elem_message_t *valid_message);
  45. void test_button_event_trigger_and_check(touch_button_handle_t handle, touch_button_event_t button_event);
  46. void test_button_callback_trigger_and_check(touch_button_handle_t handle, touch_button_event_t button_event, bool should_trigger, test_monitor_t *monitor);
  47. /* ------------------------------------------------ Dispatch method test -------------------------------------------- */
  48. static void test_button_disp_event(void);
  49. static void test_button_disp_callback(void);
  50. void test_button_handler(touch_button_handle_t handle, touch_button_message_t *message, void *arg);
  51. /* ------------------------------------------------ Run-time test --------------------------------------------------- */
  52. static void test_button_event_change_lp(void);
  53. static void test_button_callback_change_lp(void);
  54. static void test_button_change_lp_handler(touch_button_handle_t handle, touch_button_message_t *message, void *arg);
  55. /* ------------------------------------------------ Concurrent test ------------------------------------------------- */
  56. static void test_button_event_concurrent(void);
  57. static void test_button_random_trigger_concurrent(void);
  58. void test_random_trigger_concurrent_task(void *arg);
  59. static void random_trigger_concurrent_handler(touch_button_handle_t handle, touch_button_message_t *message, void *arg);
  60. /* ------------------------------------------------------------------------------------------------------------------ */
  61. TEST_CASE("Touch button dispatch methods test", "[button][touch_element]")
  62. {
  63. touch_elem_global_config_t global_config = TOUCH_ELEM_GLOBAL_DEFAULT_CONFIG();
  64. TEST_ESP_OK(touch_element_install(&global_config));
  65. test_button_disp_event();
  66. test_button_disp_callback();
  67. touch_element_uninstall();
  68. }
  69. TEST_CASE("Touch button run-time test", "[button][touch_element]")
  70. {
  71. touch_elem_global_config_t global_config = TOUCH_ELEM_GLOBAL_DEFAULT_CONFIG();
  72. TEST_ESP_OK(touch_element_install(&global_config));
  73. test_button_event_change_lp();
  74. test_button_callback_change_lp();
  75. touch_element_uninstall();
  76. }
  77. TEST_CASE("Touch button concurrent test", "[button][touch_element]")
  78. {
  79. touch_elem_global_config_t global_config = TOUCH_ELEM_GLOBAL_DEFAULT_CONFIG();
  80. TEST_ESP_OK(touch_element_install(&global_config));
  81. test_button_event_concurrent();
  82. test_button_random_trigger_concurrent();
  83. touch_element_uninstall();
  84. }
  85. void test_button_event_simulator(touch_button_handle_t button_handle, touch_button_event_t button_event)
  86. {
  87. te_button_handle_t te_button = (te_button_handle_t) button_handle;
  88. touch_pad_t channel = te_button->device->channel;
  89. if (button_event == TOUCH_BUTTON_EVT_ON_PRESS) {
  90. touch_pad_set_cnt_mode(channel, TOUCH_PAD_SLOPE_3, TOUCH_PAD_TIE_OPT_DEFAULT);
  91. } else if (button_event == TOUCH_BUTTON_EVT_ON_RELEASE) {
  92. touch_pad_set_cnt_mode(channel, TOUCH_PAD_SLOPE_7, TOUCH_PAD_TIE_OPT_DEFAULT);
  93. } else {
  94. touch_pad_set_cnt_mode(channel, TOUCH_PAD_SLOPE_3, TOUCH_PAD_TIE_OPT_DEFAULT); //LongPress
  95. }
  96. }
  97. void test_button_event_check(touch_elem_message_t *valid_message, touch_elem_message_t *current_message)
  98. {
  99. TEST_ASSERT_MESSAGE(current_message->handle == valid_message->handle, "check handle failed");
  100. TEST_ASSERT_MESSAGE(current_message->element_type == valid_message->element_type, "check element type failed");
  101. const touch_button_message_t *valid_button_message = touch_button_get_message(valid_message);
  102. const touch_button_message_t *current_button_message = touch_button_get_message(current_message);
  103. TEST_ASSERT_MESSAGE(current_button_message->event == valid_button_message->event, "check event failed");
  104. }
  105. static void test_button_callback_check(touch_button_handle_t current_handle, touch_button_message_t *current_message, touch_elem_message_t *valid_message)
  106. {
  107. const touch_button_message_t *valid_button_message = touch_button_get_message(valid_message);
  108. TEST_ASSERT_MESSAGE(valid_message->handle == current_handle, "check handle failed");
  109. TEST_ASSERT_MESSAGE(valid_message->element_type == TOUCH_ELEM_TYPE_BUTTON, "check element type failed");
  110. TEST_ASSERT_MESSAGE(valid_button_message->event == current_message->event, "check event failed");
  111. }
  112. void test_button_event_trigger_and_check(touch_button_handle_t handle, touch_button_event_t button_event)
  113. {//TODO: refactor this with a constructor
  114. touch_elem_message_t valid_message = {
  115. .handle = handle,
  116. .element_type = TOUCH_ELEM_TYPE_BUTTON,
  117. .arg = NULL,
  118. };
  119. touch_button_message_t button_message = {
  120. .event = button_event
  121. };
  122. memcpy(valid_message.child_msg, &button_message, sizeof(touch_button_message_t)); //Construct valid_message
  123. test_button_event_simulator(handle, button_event); //Trigger signal
  124. touch_elem_message_t current_message;
  125. te_button_handle_t te_button = handle;
  126. esp_err_t ret = touch_element_message_receive(&current_message, pdMS_TO_TICKS(2 * te_button->trigger_thr * 10));
  127. TEST_ASSERT_MESSAGE(ret == ESP_OK, "button event receive timeout");
  128. test_button_event_check(&valid_message, &current_message); //Verification
  129. }
  130. void test_button_callback_trigger_and_check(touch_button_handle_t handle, touch_button_event_t button_event, bool should_trigger, test_monitor_t *monitor)
  131. {
  132. if (should_trigger) {
  133. touch_elem_message_t valid_message = {
  134. .handle = handle,
  135. .element_type = TOUCH_ELEM_TYPE_BUTTON,
  136. .arg = NULL
  137. };
  138. touch_button_message_t button_message = {
  139. .event = button_event
  140. };
  141. memcpy(valid_message.child_msg, &button_message, sizeof(touch_button_message_t)); //Construct valid_message
  142. xQueueSend(monitor->valid_msg_handle, &valid_message, portMAX_DELAY);
  143. }
  144. test_button_event_simulator(handle, button_event); //Trigger signal
  145. te_button_handle_t te_button = handle;
  146. if (should_trigger) { //Verification
  147. BaseType_t os_ret = xSemaphoreTake(monitor->response_sig_handle, pdMS_TO_TICKS(2 * te_button->trigger_thr * 10));
  148. TEST_ASSERT_MESSAGE(os_ret == pdPASS, "Button queue timeout");
  149. } else {
  150. BaseType_t os_ret = xSemaphoreTake(monitor->response_sig_handle, pdMS_TO_TICKS(500));
  151. TEST_ASSERT_MESSAGE(os_ret == pdFALSE, "Button invalid trigger");
  152. }
  153. }
  154. static void test_button_disp_event(void)
  155. {
  156. touch_button_handle_t button_handle[BUTTON_CHANNEL_NUM];
  157. touch_button_global_config_t global_config = TOUCH_BUTTON_GLOBAL_DEFAULT_CONFIG();
  158. TEST_ESP_OK(touch_button_install(&global_config));
  159. for (int i = 0; i < BUTTON_CHANNEL_NUM; i++) {
  160. touch_button_config_t button_config = {
  161. .channel_num = button_channel_array[i],
  162. .channel_sens = 0.1F
  163. };
  164. TEST_ESP_OK(touch_button_create(&button_config, &button_handle[i]));
  165. TEST_ESP_OK(touch_button_subscribe_event(button_handle[i],
  166. TOUCH_ELEM_EVENT_ON_PRESS | TOUCH_ELEM_EVENT_ON_RELEASE | TOUCH_ELEM_EVENT_ON_LONGPRESS,
  167. (void *) button_channel_array[i]));
  168. TEST_ESP_OK(touch_button_set_longpress(button_handle[i], 300));
  169. TEST_ESP_OK(touch_button_set_dispatch_method(button_handle[i], TOUCH_ELEM_DISP_EVENT));
  170. }
  171. TEST_ESP_OK(touch_element_start());
  172. vTaskDelay(pdMS_TO_TICKS(500)); //Mention in README, code-block-1
  173. srandom((unsigned int)time(NULL));
  174. //10 times random press/longpress/release test
  175. printf("Touch button event test start\n");
  176. for (int i = 0; i < 10; i++) {
  177. printf("Touch button event test... (%d/10)\n", i + 1);
  178. touch_button_handle_t current_handle = button_handle[random() % 14];
  179. test_button_event_trigger_and_check(current_handle, TOUCH_BUTTON_EVT_ON_PRESS);
  180. test_button_event_trigger_and_check(current_handle, TOUCH_BUTTON_EVT_ON_LONGPRESS);
  181. test_button_event_trigger_and_check(current_handle, TOUCH_BUTTON_EVT_ON_RELEASE);
  182. }
  183. printf("Touch button event test finish\n");
  184. TEST_ESP_OK(touch_element_stop());
  185. for (int i = 0; i < BUTTON_CHANNEL_NUM; i++) {
  186. TEST_ESP_OK(touch_button_delete(button_handle[i]));
  187. }
  188. touch_button_uninstall();
  189. }
  190. static void test_button_disp_callback(void)
  191. {
  192. test_monitor_t monitor;
  193. touch_button_handle_t button_handle[BUTTON_CHANNEL_NUM];
  194. monitor.valid_msg_handle = xQueueCreate(10, sizeof(touch_elem_message_t));
  195. monitor.response_sig_handle = xSemaphoreCreateBinary();
  196. TEST_ASSERT(monitor.valid_msg_handle != NULL || monitor.response_sig_handle != NULL);
  197. touch_button_global_config_t button_init = TOUCH_BUTTON_GLOBAL_DEFAULT_CONFIG();
  198. TEST_ESP_OK(touch_button_install(&button_init));
  199. for (int i = 0; i < BUTTON_CHANNEL_NUM; i++) {
  200. touch_button_config_t button_config = {
  201. .channel_num = button_channel_array[i],
  202. .channel_sens = 0.1F
  203. };
  204. TEST_ESP_OK(touch_button_create(&button_config, &button_handle[i]));
  205. TEST_ESP_OK(touch_button_subscribe_event(button_handle[i],
  206. TOUCH_ELEM_EVENT_ON_PRESS | TOUCH_ELEM_EVENT_ON_RELEASE | TOUCH_ELEM_EVENT_ON_LONGPRESS,
  207. (void *) &monitor));
  208. TEST_ESP_OK(touch_button_set_dispatch_method(button_handle[i], TOUCH_ELEM_DISP_CALLBACK));
  209. TEST_ESP_OK(touch_button_set_callback(button_handle[i], &test_button_handler));
  210. TEST_ESP_OK(touch_button_set_longpress(button_handle[i], 300));
  211. }
  212. TEST_ESP_OK(touch_element_start());
  213. srandom((unsigned int)time(NULL));
  214. vTaskDelay(pdMS_TO_TICKS(500)); //Mention in README, code-block-1
  215. //10 times random press/longpress/release test
  216. printf("Touch button callback test start\n");
  217. for (int i = 0; i < 10; i++) {
  218. printf("Touch button callback test... (%d/10)\n", i + 1);
  219. touch_button_handle_t current_handle = button_handle[random() % 14];
  220. test_button_callback_trigger_and_check(current_handle, TOUCH_BUTTON_EVT_ON_PRESS, true, &monitor);
  221. test_button_callback_trigger_and_check(current_handle, TOUCH_BUTTON_EVT_ON_LONGPRESS, true, &monitor);
  222. test_button_callback_trigger_and_check(current_handle, TOUCH_BUTTON_EVT_ON_RELEASE, true, &monitor);
  223. }
  224. printf("Touch button callback test finish\n");
  225. TEST_ESP_OK(touch_element_stop());
  226. for (int i = 0; i < BUTTON_CHANNEL_NUM; i++) {
  227. TEST_ESP_OK(touch_button_delete(button_handle[i]));
  228. }
  229. touch_button_uninstall();
  230. vQueueDelete(monitor.valid_msg_handle);
  231. vSemaphoreDelete(monitor.response_sig_handle);
  232. }
  233. void test_button_handler(touch_button_handle_t handle, touch_button_message_t *message, void *arg)
  234. {
  235. test_monitor_t *monitor = (test_monitor_t *)arg;
  236. touch_elem_message_t valid_message;
  237. BaseType_t os_ret = xQueueReceive(monitor->valid_msg_handle, &valid_message, pdMS_TO_TICKS(200)); //Get the valid message for the verification, 500ms timeout
  238. TEST_ASSERT_MESSAGE(os_ret == pdPASS, "test_button_handler: queue timeout");
  239. test_button_callback_check(handle, message, &valid_message);
  240. xSemaphoreGive(monitor->response_sig_handle);
  241. }
  242. static void test_button_event_change_lp(void)
  243. {
  244. touch_button_handle_t button_handle[BUTTON_CHANNEL_NUM];
  245. touch_button_global_config_t global_config = TOUCH_BUTTON_GLOBAL_DEFAULT_CONFIG();
  246. TEST_ESP_OK(touch_button_install(&global_config));
  247. for (int i = 0; i < BUTTON_CHANNEL_NUM; i++) {
  248. touch_button_config_t button_config = {
  249. .channel_num = button_channel_array[i],
  250. .channel_sens = 0.1F
  251. };
  252. TEST_ESP_OK(touch_button_create(&button_config, &button_handle[i]));
  253. TEST_ESP_OK(touch_button_subscribe_event(button_handle[i], TOUCH_ELEM_EVENT_ON_LONGPRESS, NULL));
  254. TEST_ESP_OK(touch_button_set_dispatch_method(button_handle[i], TOUCH_ELEM_DISP_EVENT));
  255. }
  256. TEST_ESP_OK(touch_element_start());
  257. vTaskDelay(pdMS_TO_TICKS(500)); //Mention in README, code-block-1
  258. srandom((unsigned int)time(NULL));
  259. //10 times random press/longpress/release test
  260. printf("Touch button event change longtime test start\n");
  261. for (int i = 0; i < 10; i++) {
  262. printf("Touch button event change longtime test... (%d/10)\n", i + 1);
  263. esp_err_t ret;
  264. uint8_t channel_index = random() % BUTTON_CHANNEL_NUM;
  265. touch_elem_message_t valid_message = {
  266. .handle = button_handle[channel_index],
  267. .element_type = TOUCH_ELEM_TYPE_BUTTON,
  268. .arg = NULL
  269. };
  270. touch_button_message_t button_message = {
  271. .event = TOUCH_BUTTON_EVT_ON_LONGPRESS
  272. };
  273. memcpy(valid_message.child_msg, &button_message, sizeof(touch_button_message_t)); //Construct valid_message
  274. TEST_ESP_OK(touch_button_set_longpress(valid_message.handle, 200 + (i + 1) * 50));
  275. test_button_event_simulator(valid_message.handle, button_message.event); //Trigger signal
  276. touch_elem_message_t current_message;
  277. ret = touch_element_message_receive(&current_message, pdMS_TO_TICKS(10 * 1000));
  278. TEST_ASSERT_MESSAGE(ret == ESP_OK, "button event LongPress timeout");
  279. test_button_event_check(&valid_message, &current_message); //Verification
  280. test_button_event_simulator(valid_message.handle, TOUCH_BUTTON_EVT_ON_RELEASE); //Release the button.
  281. }
  282. printf("Touch button event change longtime test finish\n");
  283. TEST_ESP_OK(touch_element_stop());
  284. for (int i = 0; i < BUTTON_CHANNEL_NUM; i++) {
  285. TEST_ESP_OK(touch_button_delete(button_handle[i]));
  286. }
  287. touch_button_uninstall();
  288. }
  289. static void test_button_callback_change_lp(void)
  290. {
  291. test_monitor_t monitor;
  292. touch_button_handle_t button_handle[BUTTON_CHANNEL_NUM];
  293. monitor.valid_msg_handle = xQueueCreate(10, sizeof(touch_elem_message_t));
  294. monitor.response_sig_handle = xSemaphoreCreateBinary();
  295. TEST_ASSERT(monitor.valid_msg_handle != NULL || monitor.response_sig_handle != NULL);
  296. touch_button_global_config_t global_config = TOUCH_BUTTON_GLOBAL_DEFAULT_CONFIG();
  297. TEST_ESP_OK(touch_button_install(&global_config));
  298. for (int i = 0; i < BUTTON_CHANNEL_NUM; i++) {
  299. touch_button_config_t button_config = {
  300. .channel_num = button_channel_array[i],
  301. .channel_sens = 0.1F
  302. };
  303. TEST_ESP_OK(touch_button_create(&button_config, &button_handle[i]));
  304. TEST_ESP_OK(touch_button_subscribe_event(button_handle[i], TOUCH_ELEM_EVENT_ON_LONGPRESS, (void *)&monitor));
  305. TEST_ESP_OK(touch_button_set_dispatch_method(button_handle[i], TOUCH_ELEM_DISP_CALLBACK));
  306. TEST_ESP_OK(touch_button_set_callback(button_handle[i], &test_button_change_lp_handler));
  307. }
  308. TEST_ESP_OK(touch_element_start());
  309. vTaskDelay(pdMS_TO_TICKS(500)); //Mention in README, code-block-1
  310. //10 times random press/longpress/release test
  311. printf("Touch button event change longtime test start\n");
  312. for (int i = 0; i < 10; i++) {
  313. printf("Touch button event change longtime test... (%d/10)\n", i + 1);
  314. uint8_t channel_index = 5; //Always this channel
  315. touch_elem_message_t valid_message = {
  316. .handle = button_handle[channel_index],
  317. .element_type = TOUCH_ELEM_TYPE_BUTTON,
  318. .arg = NULL,
  319. };
  320. touch_button_message_t button_message = {
  321. .event = TOUCH_BUTTON_EVT_ON_LONGPRESS
  322. };
  323. memcpy(valid_message.child_msg, &button_message, sizeof(touch_button_message_t)); //Construct valid_message
  324. xQueueSend(monitor.valid_msg_handle, &valid_message, portMAX_DELAY);
  325. test_button_event_simulator(button_handle[channel_index], button_message.event);
  326. BaseType_t os_ret = xSemaphoreTake(monitor.response_sig_handle, pdMS_TO_TICKS(10 * 1000)); //100ms timeout
  327. TEST_ASSERT_MESSAGE(os_ret == pdPASS, "Button LongPress queue timeout");
  328. test_button_event_simulator(valid_message.handle, TOUCH_BUTTON_EVT_ON_RELEASE); //Reset hardware
  329. }
  330. printf("Touch button event change longtime test finish\n");
  331. TEST_ESP_OK(touch_element_stop());
  332. for (int i = 0; i < BUTTON_CHANNEL_NUM; i++) {
  333. TEST_ESP_OK(touch_button_delete(button_handle[i]));
  334. }
  335. touch_button_uninstall();
  336. }
  337. static void test_button_change_lp_handler(touch_button_handle_t handle, touch_button_message_t *message, void *arg)
  338. {
  339. test_monitor_t *monitor = (test_monitor_t *)arg;
  340. touch_elem_message_t valid_message;
  341. BaseType_t os_ret = xQueueReceive(monitor->valid_msg_handle, &valid_message, pdMS_TO_TICKS(200)); //Get the valid message for the verification, 500ms timeout
  342. TEST_ASSERT_MESSAGE(os_ret == pdPASS, "test_button_handler: queue timeout");
  343. test_button_callback_check(handle, message, &valid_message);
  344. xSemaphoreGive(monitor->response_sig_handle);
  345. TEST_ESP_OK(touch_button_set_longpress(valid_message.handle, 300)); // Always 300ms
  346. }
  347. static void test_button_event_concurrent(void)
  348. {
  349. touch_button_handle_t button_handle[BUTTON_CHANNEL_NUM];
  350. touch_button_global_config_t global_config = TOUCH_BUTTON_GLOBAL_DEFAULT_CONFIG();
  351. TEST_ESP_OK(touch_button_install(&global_config));
  352. for (int i = 0; i < BUTTON_CHANNEL_NUM; i++) {
  353. touch_button_config_t button_config = {
  354. .channel_num = button_channel_array[i],
  355. .channel_sens = 0.1F
  356. };
  357. TEST_ESP_OK(touch_button_create(&button_config, &button_handle[i]));
  358. TEST_ESP_OK(touch_button_subscribe_event(button_handle[i], TOUCH_ELEM_EVENT_ON_PRESS | TOUCH_ELEM_EVENT_ON_RELEASE, NULL));
  359. TEST_ESP_OK(touch_button_set_dispatch_method(button_handle[i], TOUCH_ELEM_DISP_EVENT));
  360. }
  361. TEST_ESP_OK(touch_element_start());
  362. vTaskDelay(pdMS_TO_TICKS(500)); //Mention in README, code-block-1
  363. //10 times random press/longpress/release test
  364. printf("Touch button event concurrent test start\n");
  365. for (int i = 0; i < 10; i++) {
  366. printf("Touch button event concurrent test... (%d/10)\n", i + 1);
  367. esp_err_t ret;
  368. uint32_t message_count = 0;
  369. touch_elem_message_t current_message;
  370. TEST_BUTTON_ENTER_CRITICAL();
  371. for (int idx = 0; idx < BUTTON_CHANNEL_NUM; idx++) {
  372. test_button_event_simulator(button_handle[idx], TOUCH_BUTTON_EVT_ON_PRESS); //All channels trigger
  373. }
  374. TEST_BUTTON_EXIT_CRITICAL();
  375. message_count = 0;
  376. do {
  377. ret = touch_element_message_receive(&current_message, pdMS_TO_TICKS(500));
  378. if (ret == ESP_OK) {
  379. message_count++;
  380. }
  381. } while (ret == ESP_OK);
  382. TEST_ASSERT_MESSAGE(message_count == BUTTON_CHANNEL_NUM, "button concurrent Press failed");
  383. TEST_BUTTON_ENTER_CRITICAL();
  384. for (int idx = 0; idx < BUTTON_CHANNEL_NUM; idx++) {
  385. test_button_event_simulator(button_handle[idx], TOUCH_BUTTON_EVT_ON_RELEASE); //All channels trigger
  386. }
  387. TEST_BUTTON_EXIT_CRITICAL();
  388. message_count = 0;
  389. do {
  390. ret = touch_element_message_receive(&current_message, pdMS_TO_TICKS(500));
  391. if (ret == ESP_OK) {
  392. message_count++;
  393. }
  394. } while (ret == ESP_OK);
  395. TEST_ASSERT_MESSAGE(message_count == BUTTON_CHANNEL_NUM, "button concurrent Release failed");
  396. }
  397. printf("Touch button event concurrent test finish\n");
  398. TEST_ESP_OK(touch_element_stop());
  399. for (int i = 0; i < BUTTON_CHANNEL_NUM; i++) {
  400. TEST_ESP_OK(touch_button_delete(button_handle[i]));
  401. }
  402. touch_button_uninstall();
  403. }
  404. static void test_button_random_trigger_concurrent(void)
  405. {
  406. uint64_t sem_and_monitor[BUTTON_CHANNEL_NUM];
  407. printf("Touch button random trigger concurrent test start\n");
  408. test_concurrent_monitor_t monitor[BUTTON_CHANNEL_NUM];
  409. SemaphoreHandle_t count_sem = xSemaphoreCreateCounting(BUTTON_CHANNEL_NUM, 0);
  410. touch_button_global_config_t global_config = TOUCH_BUTTON_GLOBAL_DEFAULT_CONFIG();
  411. TEST_ESP_OK(touch_button_install(&global_config));
  412. for (uint32_t i = 0; i < BUTTON_CHANNEL_NUM; i++) {
  413. touch_button_config_t button_config = {
  414. .channel_num = button_channel_array[i],
  415. .channel_sens = 0.1F
  416. };
  417. monitor[i].response_sig_handle = xSemaphoreCreateBinary();
  418. monitor[i].valid_msg_handle = xQueueCreate(BUTTON_CHANNEL_NUM, sizeof(touch_elem_message_t));
  419. TEST_ASSERT(monitor[i].valid_msg_handle != NULL && monitor[i].response_sig_handle != NULL);
  420. uintptr_t temp_count_sem = (uint32_t)count_sem;
  421. uintptr_t temp_monitor = (uint32_t)&monitor[i]; //Prevent compiler warning
  422. sem_and_monitor[i] = (uint64_t)(((uint64_t)temp_count_sem << 32) | (uint64_t) temp_monitor);
  423. TEST_ESP_OK(touch_button_create(&button_config, &monitor[i].button_handle));
  424. TEST_ESP_OK(touch_button_subscribe_event(monitor[i].button_handle, TOUCH_ELEM_EVENT_ON_PRESS | TOUCH_ELEM_EVENT_ON_LONGPRESS | TOUCH_ELEM_EVENT_ON_RELEASE, (void *)&sem_and_monitor[i]));
  425. TEST_ESP_OK(touch_button_set_longpress(monitor[i].button_handle, 500));
  426. TEST_ESP_OK(touch_button_set_dispatch_method(monitor[i].button_handle, TOUCH_ELEM_DISP_CALLBACK));
  427. TEST_ESP_OK(touch_button_set_callback(monitor[i].button_handle, &random_trigger_concurrent_handler));
  428. }
  429. TEST_ESP_OK(touch_element_start());
  430. vTaskDelay(pdMS_TO_TICKS(500)); //Mention in README, code-block-1
  431. for (uint32_t i = 0; i < BUTTON_CHANNEL_NUM; i++) {
  432. BaseType_t os_ret = xTaskCreate(test_random_trigger_concurrent_task, "test_random_trigger_concurrent_task", 1024 * 4, (void *)&sem_and_monitor[i], 10, NULL);
  433. TEST_ASSERT(os_ret == pdPASS);
  434. }
  435. uint32_t run_count = 0;
  436. while (1) {
  437. if (run_count++ % 1000 == 0) {
  438. printf("Touch button random trigger concurrent test running... (1/1)\n");
  439. }
  440. uint8_t count = uxSemaphoreGetCount(count_sem);
  441. if (count == BUTTON_CHANNEL_NUM) {
  442. vTaskDelay(1); //Let IDLE task running and get tasks cleanup
  443. break;
  444. }
  445. vTaskDelay(1);
  446. }
  447. TEST_ESP_OK(touch_element_stop());
  448. for (int i = 0; i < BUTTON_CHANNEL_NUM; i++) {
  449. vQueueDelete(monitor[i].valid_msg_handle);
  450. vSemaphoreDelete(monitor[i].response_sig_handle);
  451. TEST_ESP_OK(touch_button_delete(monitor[i].button_handle));
  452. }
  453. touch_button_uninstall();
  454. printf("Touch button random trigger concurrent test stop\n");
  455. }
  456. void test_random_trigger_concurrent_task(void *arg)
  457. {
  458. uintptr_t temp_monitor = *((uint32_t *) arg);
  459. uintptr_t temp_count_sem = (*((uint64_t *) arg) >> 32); //Prevent compiler warning
  460. test_concurrent_monitor_t *monitor = (test_concurrent_monitor_t *)temp_monitor;
  461. SemaphoreHandle_t count_sem = (SemaphoreHandle_t) temp_count_sem;
  462. uint32_t start_delay_time = (esp_random() % 100) * 10;
  463. vTaskDelay(pdMS_TO_TICKS(start_delay_time));
  464. touch_elem_message_t valid_message = {
  465. .handle = monitor->button_handle,
  466. .element_type = TOUCH_ELEM_TYPE_BUTTON,
  467. .arg = NULL,
  468. };
  469. touch_button_message_t button_message;
  470. button_message.event = TOUCH_BUTTON_EVT_ON_PRESS;
  471. memcpy(valid_message.child_msg, &button_message, sizeof(touch_button_message_t)); //Construct valid_message
  472. xQueueSend(monitor->valid_msg_handle, &valid_message, portMAX_DELAY);
  473. test_button_event_simulator(valid_message.handle, button_message.event); //Trigger signal
  474. BaseType_t res_sem_ret = xSemaphoreTake(monitor->response_sig_handle, pdMS_TO_TICKS(1000));
  475. TEST_ASSERT_MESSAGE(res_sem_ret == pdPASS, "Response timeout");
  476. uint32_t hold_state_time_ms = (esp_random() % 100) * 10 + 100;
  477. te_button_handle_t te_button = (te_button_handle_t) valid_message.handle;
  478. if ((int)(hold_state_time_ms - te_button->trigger_thr * 10) > 50) { //should raise longpress event
  479. button_message.event = TOUCH_BUTTON_EVT_ON_LONGPRESS;
  480. memcpy(valid_message.child_msg, &button_message, sizeof(touch_button_message_t)); //Construct valid_message
  481. xQueueSend(monitor->valid_msg_handle, &valid_message, portMAX_DELAY);
  482. test_button_event_simulator(valid_message.handle, button_message.event); //Trigger signal
  483. res_sem_ret = xSemaphoreTake(monitor->response_sig_handle, pdMS_TO_TICKS(1000)); //+100 make sure it will really raise longpress event
  484. TEST_ASSERT_MESSAGE(res_sem_ret == pdPASS, "Response timeout");
  485. } else { //should not raise longpress event
  486. //Do nothing
  487. }
  488. button_message.event = TOUCH_BUTTON_EVT_ON_RELEASE;
  489. memcpy(valid_message.child_msg, &button_message, sizeof(touch_button_message_t)); //Construct valid_message
  490. xQueueSend(monitor->valid_msg_handle, &valid_message, portMAX_DELAY);
  491. test_button_event_simulator(valid_message.handle, button_message.event); //Trigger signal
  492. res_sem_ret = xSemaphoreTake(monitor->response_sig_handle, pdMS_TO_TICKS(1000));
  493. TEST_ASSERT_MESSAGE(res_sem_ret == pdPASS, "Response timeout");
  494. xSemaphoreGive(count_sem);
  495. vTaskDelete(NULL);
  496. }
  497. static void random_trigger_concurrent_handler(touch_button_handle_t handle, touch_button_message_t *message, void *arg)
  498. {
  499. uintptr_t temp_monitor = *((uint32_t *) arg); //Prevent compiler warning
  500. test_concurrent_monitor_t *monitor = (test_concurrent_monitor_t *) temp_monitor;
  501. touch_elem_message_t valid_message;
  502. BaseType_t os_ret = xQueueReceive(monitor->valid_msg_handle, &valid_message, pdMS_TO_TICKS(1000));
  503. TEST_ASSERT_MESSAGE(os_ret == pdPASS, "valid message timeout");
  504. const touch_button_message_t *button_message = touch_button_get_message(&valid_message);
  505. if (button_message->event == TOUCH_BUTTON_EVT_ON_LONGPRESS) {
  506. touch_button_set_longpress(handle, portMAX_DELAY); //Prevent button triggers LongPress event again
  507. }
  508. TEST_ASSERT_MESSAGE(handle == valid_message.handle, "check handle failed");
  509. TEST_ASSERT_MESSAGE(valid_message.element_type == TOUCH_ELEM_TYPE_BUTTON, "check element type failed");
  510. TEST_ASSERT_MESSAGE(message->event == button_message->event, "check event failed");
  511. xSemaphoreGive(monitor->response_sig_handle);
  512. }