touch_sw.c 5.6 KB

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