touch_sw.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. /**************************************************************************//**
  2. * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2022-02-22 Wayne First version
  9. *
  10. ******************************************************************************/
  11. #include <rtthread.h>
  12. #if defined(NU_PKG_USING_ADC_TOUCH_SW)
  13. #include "rtdevice.h"
  14. #include "touch_sw.h"
  15. /* Private define ---------------------------------------------------------------*/
  16. #define DEF_ADC_TOUCH_SMPL_TICK 40
  17. #define TOUCH_MQ_LENGTH 32
  18. /* Private Typedef --------------------------------------------------------------*/
  19. static rt_timer_t g_psRtTouchMenuTimer;
  20. static rt_mq_t g_pmqTouchXYZ;
  21. static S_TOUCH_SW *g_psTouchSW = RT_NULL;
  22. static rt_bool_t bDoSmpling = RT_FALSE;
  23. struct nu_adc_touch_data
  24. {
  25. uint32_t u32X;
  26. uint32_t u32Y;
  27. uint32_t u32Z0;
  28. uint32_t u32Z1;
  29. };
  30. typedef struct nu_adc_touch_data *nu_adc_touch_data_t;
  31. static rt_uint32_t Get_X(S_TOUCH_SW *psTouchSW)
  32. {
  33. /*=== Get X from ADC input ===*/
  34. rt_pin_mode(psTouchSW->pin[evXR], PIN_MODE_OUTPUT);
  35. rt_pin_mode(psTouchSW->pin[evYD], PIN_MODE_INPUT);
  36. rt_pin_mode(psTouchSW->pin[evXL], PIN_MODE_OUTPUT);
  37. rt_pin_write(psTouchSW->pin[evXR], PIN_HIGH);
  38. rt_pin_write(psTouchSW->pin[evXL], PIN_LOW);
  39. psTouchSW->switch_to_digital(psTouchSW->pin[evXR]);
  40. psTouchSW->switch_to_digital(psTouchSW->pin[evYD]);
  41. psTouchSW->switch_to_digital(psTouchSW->pin[evXL]);
  42. /* Disable the digital input path to avoid the leakage current. */
  43. /* Configure the ADC analog input pins. */
  44. psTouchSW->switch_to_analog(psTouchSW->pin[evYU]);
  45. return rt_adc_read((rt_adc_device_t)psTouchSW->adc, psTouchSW->i32ADCChnYU) & 0x0FFF;
  46. }
  47. static rt_uint32_t Get_Y(S_TOUCH_SW *psTouchSW)
  48. {
  49. /*=== Get Y from ADC input ===*/
  50. rt_pin_mode(psTouchSW->pin[evYU], PIN_MODE_OUTPUT);
  51. rt_pin_mode(psTouchSW->pin[evYD], PIN_MODE_OUTPUT);
  52. rt_pin_mode(psTouchSW->pin[evXL], PIN_MODE_INPUT);
  53. rt_pin_write(psTouchSW->pin[evYU], PIN_HIGH);
  54. rt_pin_write(psTouchSW->pin[evYD], PIN_LOW);
  55. psTouchSW->switch_to_digital(psTouchSW->pin[evYU]);
  56. psTouchSW->switch_to_digital(psTouchSW->pin[evYD]);
  57. psTouchSW->switch_to_digital(psTouchSW->pin[evXL]);
  58. /* Disable the digital input path to avoid the leakage current. */
  59. /* Configure the ADC analog input pins. */
  60. psTouchSW->switch_to_analog(psTouchSW->pin[evXR]);
  61. return rt_adc_read((rt_adc_device_t)psTouchSW->adc, psTouchSW->i32ADCChnXR) & 0x0FFF;
  62. }
  63. static void nu_adc_touch_smpl(void *p)
  64. {
  65. static rt_bool_t bDrop = RT_FALSE;
  66. static uint32_t u32LastZ0 = 0xffffu;
  67. struct nu_adc_touch_data point;
  68. S_TOUCH_SW *psTouchSW;
  69. if (!bDoSmpling)
  70. return ;
  71. psTouchSW = (S_TOUCH_SW *)p;
  72. rt_memset(&point, 0, sizeof(struct nu_adc_touch_data));
  73. /* Get X, Y ADC converting data */
  74. point.u32X = Get_X(psTouchSW);
  75. point.u32Y = Get_Y(psTouchSW);
  76. if ((point.u32X < 4000) && (point.u32Y < 4000))
  77. {
  78. point.u32Z0 = point.u32Z1 = 1;
  79. bDrop = RT_FALSE;
  80. }
  81. else
  82. {
  83. bDrop = RT_TRUE;
  84. }
  85. // rt_kprintf("%04x %04x %d %d\n", point.u32X, point.u32Y, point.u32Z0, bDrop);
  86. if ((!bDrop || (u32LastZ0 != 0)) && (rt_mq_send(g_pmqTouchXYZ, (const void *)&point, sizeof(struct nu_adc_touch_data)) == RT_EOK))
  87. {
  88. if (psTouchSW->psRtTouch != RT_NULL)
  89. rt_hw_touch_isr(psTouchSW->psRtTouch);
  90. }
  91. u32LastZ0 = point.u32Z0;
  92. }
  93. int32_t nu_adc_touch_read_xyz(uint32_t *bufX, uint32_t *bufY, uint32_t *bufZ0, uint32_t *bufZ1, int32_t dataCnt)
  94. {
  95. int i;
  96. struct nu_adc_touch_data value;
  97. for (i = 0 ; i < dataCnt; i++)
  98. {
  99. if (rt_mq_recv(g_pmqTouchXYZ, (void *)&value, sizeof(struct nu_adc_touch_data), 0) == -RT_ETIMEOUT)
  100. break;
  101. bufX[i] = value.u32X;
  102. bufY[i] = value.u32Y;
  103. bufZ0[i] = value.u32Z0;
  104. bufZ1[i] = value.u32Z1;
  105. }
  106. return i;
  107. }
  108. void nu_adc_touch_detect(rt_bool_t bStartDetect)
  109. {
  110. }
  111. rt_err_t nu_adc_touch_enable(rt_touch_t psRtTouch)
  112. {
  113. if (g_psTouchSW->adc)
  114. {
  115. g_psTouchSW->psRtTouch = psRtTouch;
  116. rt_adc_enable((rt_adc_device_t)g_psTouchSW->adc, g_psTouchSW->i32ADCChnXR);
  117. rt_adc_enable((rt_adc_device_t)g_psTouchSW->adc, g_psTouchSW->i32ADCChnYU);
  118. bDoSmpling = RT_TRUE;
  119. /* Start sampling procedure. */
  120. rt_timer_start(g_psRtTouchMenuTimer);
  121. return RT_EOK;
  122. }
  123. return -RT_ERROR;
  124. }
  125. rt_err_t nu_adc_touch_disable(void)
  126. {
  127. if (g_psTouchSW->adc)
  128. {
  129. /* Stop sampling procedure. */
  130. rt_timer_stop(g_psRtTouchMenuTimer);
  131. bDoSmpling = RT_FALSE;
  132. rt_adc_disable((rt_adc_device_t)g_psTouchSW->adc, g_psTouchSW->i32ADCChnXR);
  133. rt_adc_disable((rt_adc_device_t)g_psTouchSW->adc, g_psTouchSW->i32ADCChnYU);
  134. g_psTouchSW->psRtTouch = RT_NULL;
  135. return RT_EOK;
  136. }
  137. return -RT_ERROR;
  138. }
  139. rt_err_t nu_adc_touch_sw_register(S_TOUCH_SW *psTouchSW)
  140. {
  141. RT_ASSERT(psTouchSW);
  142. psTouchSW->adc = rt_device_find(psTouchSW->adc_name);
  143. RT_ASSERT(psTouchSW->adc);
  144. g_pmqTouchXYZ = rt_mq_create("ADC_TOUCH_SW", sizeof(struct nu_adc_touch_data), TOUCH_MQ_LENGTH, RT_IPC_FLAG_FIFO);
  145. RT_ASSERT(g_pmqTouchXYZ);
  146. g_psRtTouchMenuTimer = rt_timer_create("TOUCH_SMPL_TIMER", nu_adc_touch_smpl, (void *)psTouchSW, DEF_ADC_TOUCH_SMPL_TICK, RT_TIMER_FLAG_PERIODIC);
  147. RT_ASSERT(g_psRtTouchMenuTimer);
  148. g_psTouchSW = psTouchSW;
  149. return RT_EOK;
  150. }
  151. #endif //#if defined(NU_PKG_USING_ADC_TOUCH_SW)