plcnt.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. #include "includes.h"
  2. #include "asm/plcnt.h"
  3. #include "asm/gpio.h"
  4. static u8 port_index_mapping_talbe[PLCNT_KEY_CH_MAX] = {0};
  5. static u32 touch_pre_value[PLCNT_KEY_CH_MAX] = {0};
  6. static u32 touch_normal_value[PLCNT_KEY_CH_MAX] = {0};
  7. #define TOUCH_VAL_CALIBRATE_CYCLE (200)//周期大约2秒
  8. static u32 touch_calibrate_cnt[PLCNT_KEY_CH_MAX] = {0};
  9. static u32 touch_calibrate_tmp_value[PLCNT_KEY_CH_MAX] = {0};
  10. static u8 touch_state = 0;
  11. static const struct touch_key_platform_data *user_data = NULL;
  12. static JL_PORT_FLASH_TypeDef *PLCNT_IO_PORTx = NULL;
  13. static u8 PLCNT_IO_xx;
  14. void plcnt_io_out(struct touch_key_port *key)
  15. {
  16. if (key->port > IO_MAX_NUM) {
  17. return;
  18. } else if ((key->port / 16) == 0) {
  19. PLCNT_IO_PORTx = JL_PORTA;
  20. } else if ((key->port / 16) == 1) {
  21. PLCNT_IO_PORTx = JL_PORTB;
  22. }
  23. PLCNT_IO_xx = key->port % 16;
  24. PLCNT_IO_PORTx->DIE |= BIT(PLCNT_IO_xx);
  25. PLCNT_IO_PORTx->PU &= ~BIT(PLCNT_IO_xx);
  26. PLCNT_IO_PORTx->PD |= BIT(PLCNT_IO_xx);
  27. PLCNT_IO_PORTx->OUT |= BIT(PLCNT_IO_xx);
  28. PLCNT_IO_PORTx->DIR &= ~BIT(PLCNT_IO_xx);
  29. }
  30. void plcnt_io_in(struct touch_key_port *key)
  31. {
  32. if (key->port > IO_MAX_NUM) {
  33. return;
  34. } else if ((key->port / 16) == 0) {
  35. PLCNT_IO_PORTx = JL_PORTA;
  36. } else if ((key->port / 16) == 1) {
  37. PLCNT_IO_PORTx = JL_PORTB;
  38. }
  39. PLCNT_IO_xx = key->port % 16;
  40. PLCNT_IO_PORTx->DIE |= BIT(PLCNT_IO_xx);
  41. PLCNT_IO_PORTx->PU &= ~BIT(PLCNT_IO_xx);
  42. PLCNT_IO_PORTx->PD |= BIT(PLCNT_IO_xx);
  43. PLCNT_IO_PORTx->OUT |= BIT(PLCNT_IO_xx);
  44. PLCNT_IO_PORTx->DIR |= BIT(PLCNT_IO_xx);
  45. }
  46. void plcnt_iomc(struct touch_key_port *key)
  47. {
  48. //放电计数引脚选择intputchannel2
  49. gpio_set_fun_input_port(key->port, PFI_GP_ICH6);
  50. SFR(JL_IOMAP->CON1, 8, 4, 6);
  51. }
  52. static u32 key_or = 0;
  53. void plcnt_flt(u32 cur_val, u32 ch)
  54. {
  55. /* printf("ch%d : %d\n", ch, cur_val); */
  56. //简单滤波
  57. if (touch_pre_value[ch] == 0) {
  58. touch_pre_value[ch] = cur_val;
  59. } else if (cur_val >= touch_pre_value[ch]) {
  60. touch_pre_value[ch] = touch_pre_value[ch] + (u32)((cur_val - touch_pre_value[ch]) * 0.2f);
  61. } else {
  62. touch_pre_value[ch] = touch_pre_value[ch] - (u32)((touch_pre_value[ch] - cur_val) * 0.2f);
  63. }
  64. //处理滤波之后的值
  65. if (touch_pre_value[ch] > (touch_normal_value[ch] + user_data->port_list[ch].press_delta)) {
  66. key_or |= BIT(ch);
  67. touch_calibrate_cnt[ch] = 0;
  68. } else {
  69. key_or &= ~BIT(ch);
  70. touch_calibrate_cnt[ch] ++;
  71. }
  72. //定期标定常态下的基准值
  73. if (touch_calibrate_cnt[ch] > TOUCH_VAL_CALIBRATE_CYCLE) {
  74. touch_normal_value[ch] = touch_calibrate_tmp_value[ch] / 10;
  75. touch_calibrate_tmp_value[ch] = 0;
  76. touch_calibrate_cnt[ch] = 0;
  77. } else if (touch_calibrate_cnt[ch] >= (TOUCH_VAL_CALIBRATE_CYCLE / 2)) {
  78. if (touch_calibrate_cnt[ch] < ((TOUCH_VAL_CALIBRATE_CYCLE / 2) + 10)) {
  79. touch_calibrate_tmp_value[ch] += touch_pre_value[ch];
  80. }
  81. } else {
  82. touch_calibrate_tmp_value[ch] = 0;
  83. }
  84. }
  85. void scan_capkey_async(void *priv)
  86. {
  87. if (!user_data) {
  88. return;
  89. }
  90. static u8 cur_ch = 0;
  91. static u32 new_val = 0;
  92. static u32 old_val = 0;
  93. u8 pre_ch = cur_ch - 1;
  94. u8 net_ch = cur_ch + 1;
  95. if (cur_ch == 0) {
  96. pre_ch = user_data->num - 1;
  97. }
  98. if (net_ch >= user_data->num) {
  99. net_ch = 0;
  100. }
  101. new_val = JL_PCNT->VAL;
  102. u32 delta_val = 0;
  103. if (new_val >= old_val) {
  104. delta_val = new_val - old_val;
  105. } else {
  106. delta_val = (u32) - new_val + old_val;
  107. }
  108. plcnt_flt(delta_val, pre_ch);
  109. old_val = JL_PCNT->VAL;
  110. plcnt_iomc(&(user_data->port_list[cur_ch]));
  111. plcnt_io_in(&(user_data->port_list[cur_ch]));
  112. if (net_ch != cur_ch) {
  113. plcnt_io_out(&(user_data->port_list[net_ch]));
  114. }
  115. cur_ch = net_ch;
  116. }
  117. void scan_capkey(void *priv)
  118. {
  119. if (!user_data) {
  120. return;
  121. }
  122. for (u8 ch = 0; ch < user_data->num; ch ++) {
  123. plcnt_io_out(&(user_data->port_list[ch]));
  124. plcnt_iomc(&(user_data->port_list[ch]));
  125. u32 tmp_val, start_val, end_val, delta_val = 0;
  126. for (u8 i = 0; i < 5; i ++) {
  127. delay(100);
  128. start_val = JL_PCNT->VAL;
  129. PLCNT_IO_PORTx->DIR |= BIT(PLCNT_IO_xx);
  130. __asm__ volatile("csync");
  131. while (PLCNT_IO_PORTx->IN & BIT(PLCNT_IO_xx));
  132. end_val = JL_PCNT->VAL;
  133. PLCNT_IO_PORTx->DIR &= ~BIT(PLCNT_IO_xx);
  134. if (end_val > start_val) {
  135. tmp_val = end_val - start_val;
  136. } else {
  137. tmp_val = (u32) - start_val + end_val;
  138. }
  139. delta_val += tmp_val;
  140. }
  141. delta_val = delta_val / 5;
  142. /* printf("%d: %d\n", ch, delta_val); */
  143. plcnt_flt(delta_val, ch);
  144. }
  145. }
  146. /*
  147. @brief 引脚放电计数模块初始化
  148. */
  149. int plcnt_init(void *_data)
  150. {
  151. if (_data == NULL) {
  152. return -1;
  153. }
  154. user_data = (const struct touch_key_platform_data *)_data;
  155. if (user_data->num > PLCNT_KEY_CH_MAX) {
  156. return -1;
  157. }
  158. for (u8 ch = 0; ch < user_data->num; ch ++) {
  159. touch_normal_value[ch] = 0 - (2 * user_data->port_list[ch].press_delta);
  160. }
  161. for (u8 ch = 0; ch < user_data->num; ch ++) {
  162. plcnt_iomc(&(user_data->port_list[ch]));
  163. plcnt_io_out(&(user_data->port_list[ch]));
  164. }
  165. JL_PCNT->CON = 0;
  166. JL_PCNT->CON |= (0b11 << 2); //选择PLL240M为时钟源
  167. JL_PCNT->CON |= BIT(1); //引脚放电计数使能
  168. /* sys_s_hi_timer_add(NULL, scan_capkey_async, 2); //2ms */
  169. sys_s_hi_timer_add(NULL, scan_capkey, 10); //10ms
  170. return 0;
  171. }
  172. static u8 key_filter(u8 key)
  173. {
  174. static u8 used_key = 0xff;
  175. static u8 old_key;
  176. static u8 key_counter;
  177. if (old_key != key) {
  178. key_counter = 0;
  179. old_key = key;
  180. } else {
  181. key_counter++;
  182. if (key_counter == 3) {
  183. used_key = key;
  184. }
  185. }
  186. return used_key;
  187. }
  188. u8 get_plcnt_value(void)
  189. {
  190. /* printf("%d %d %d\n", touch_pre_value[0], touch_pre_value[1], touch_pre_value[2]); */
  191. static u8 pre_i = 0;
  192. u8 key_num = 0xff;
  193. if (key_or) {
  194. if (key_or & BIT(pre_i)) {
  195. key_num = pre_i;
  196. } else {
  197. for (u8 ch = 0; ch < user_data->num; ch ++) {
  198. if (key_or & BIT(ch)) {
  199. key_num = ch;
  200. pre_i = ch;
  201. break;
  202. }
  203. }
  204. }
  205. /* printf("key_num : %d\n", key_num); */
  206. }
  207. return key_filter(key_num);
  208. }