driver_touch_key.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. /**
  2. ******************************************************************************************************************************
  3. *
  4. *@file driver_touch_key.c
  5. *
  6. *@brief Source file for Touch Key Driver
  7. *
  8. *@Create date: 2023-03-23
  9. *
  10. *
  11. *Copyright (c) 2023, BLUETRUM
  12. ******************************************************************************************************************************
  13. **/
  14. #include "driver_touch_key.h"
  15. #include "driver_gpio.h"
  16. #define TRACE_EN 0
  17. #if TRACE_EN
  18. #define TRACE(...) printf(__VA_ARGS__)
  19. #else
  20. #define TRACE(...)
  21. #endif
  22. void touch_key_dump(void)
  23. {
  24. TRACE ("\n");
  25. TRACE ("INPCON: %08X\n", INPCON );
  26. TRACE ("INPCPND: %08X\n", INPCPND);
  27. TRACE ("TKCON: %08X\n", TKCON);
  28. TRACE ("TKCON1: %08X\n", TKCON1);
  29. TRACE ("TKCON2: %08X\n", TKCON2);
  30. TRACE ("TKACON0: %08X\n", TKACON0);
  31. TRACE ("TKACON1: %08X\n", TKACON1);
  32. TRACE ("TKCNT: %08X\n", TKCNT);
  33. TRACE ("TKBCNT: %08X\n", TKBCNT);
  34. TRACE ("TKCDPR0: %08X\n",TKCDPR0);
  35. TRACE ("TKCDPR1: %08X\n",TKCDPR1);
  36. TRACE ("TKVARI: %08X\n", TKVARI);
  37. TRACE ("TKTMR: %08X\n", TKTMR);
  38. if (GETF_REG_TKCON_TK0_PND_EN() & GETF_REG_TKCON_TK0_EN()) {
  39. TRACE("touch key ch0 enable\n");
  40. }
  41. if (GETF_REG_TKCON_TK1_PND_EN() & GETF_REG_TKCON_TK1_EN()) {
  42. TRACE("touch key ch1 enable\n");
  43. }
  44. if (GETF_REG_TKCON_TK2_PND_EN() & GETF_REG_TKCON_TK2_EN()) {
  45. TRACE("touch key ch2 enable\r");
  46. }
  47. if (GETF_REG_TKCON_TK3_PND_EN() & GETF_REG_TKCON_TK3_EN()) {
  48. TRACE("touch key ch3 enable\r");
  49. }
  50. TRACE("touch key ch = 0x%02x\r\n", GET_REG_TKCON_TKSEL());
  51. }
  52. AT(.com_periph.touch.get_key)
  53. u8 touch_key_get_key(void)
  54. {
  55. if (!GETF_REG_TKCON_TKEN()) {
  56. return 0;
  57. }
  58. return 1;
  59. }
  60. #if 1 //Already been implemented internal
  61. AT(.com_periph.tkey.isr)
  62. u32 tkey_tcnt_variance_calc(tk_cb_t *s, u16 tkcnt)
  63. {
  64. u32 i;
  65. u32 sum = 0, dela, variance = 0;
  66. s->buf[s->cnt++] = tkcnt;
  67. if (s->cnt > 7) {
  68. s->cnt = 0;
  69. }
  70. for (i = 0; i < 8; i++) {
  71. sum += s->buf[i];
  72. }
  73. s->avg = sum >> 3;
  74. for (i = 0; i < 8; i++) {
  75. if (s->buf[i] > s->avg) {
  76. dela = s->buf[i] - s->avg;
  77. } else {
  78. dela = s->avg - s->buf[i];
  79. }
  80. variance += (dela * dela);
  81. }
  82. return variance;
  83. }
  84. //根据方差检测进行range exception校准
  85. AT(.com_periph.tkey.isr)
  86. void tkey_bcnt_range_exception(tk_cb_t *s, u16 tkcnt)
  87. {
  88. u16 bcnt;
  89. u32 variance = tkey_tcnt_variance_calc(s, tkcnt);
  90. if (variance < s->limit) {
  91. s->anov_cnt++;
  92. bcnt = s->bcnt_sfr[0] & 0xfff;
  93. if ((s->avg > (bcnt+3)) && (s->avg < (bcnt + s->range_thresh))) {
  94. s->stable_cnt++;
  95. if (s->stable_cnt > s->fil_except) {
  96. if (s->range_en) {
  97. s->bcnt_sfr[0] = bcnt + 3;
  98. }
  99. s->stable_cnt = 0;
  100. }
  101. } else if(s->avg < bcnt - 3) {
  102. s->bcnt_sfr[0] = bcnt - 3;
  103. } else {
  104. s->stable_cnt = 0;
  105. }
  106. } else {
  107. s->anov_cnt = 0;
  108. s->stable_cnt = 0;
  109. }
  110. }
  111. #endif
  112. AT(.com_periph.tkey.isr)
  113. void touch_key_isr(void)
  114. {
  115. u32 inpcon = INPCON;
  116. u32 tk_exp_pnd = (inpcon >> 21) & (inpcon >> 5) & 0xf;
  117. u32 tk_pto_pnd = (inpcon >> 29) & (inpcon >> 13) & 0x1;
  118. u32 tk_pnd = (inpcon >> 16) & (inpcon >> 0) & 0x1;
  119. tk_exp_pnd |= (tk_pto_pnd << 4); //bit0-smaller exception pending
  120. //bit1-larger exception pending
  121. //bit2-range exception pending
  122. //bit3-timeout exception pending
  123. //bit4-press timeout exception pending
  124. if (tk_exp_pnd) { //touch key exception pending
  125. INPCPND = BIT(21);
  126. }
  127. if (tk_pnd) { //touch key timer pending
  128. INPCPND = BIT(16);
  129. touch_key_range_isr(inpcon >> 30, TKCNT & 0xfff);
  130. }
  131. }
  132. /**
  133. * @brief Touch key interrup enable and isr registered.
  134. *
  135. * @params[in] touch_pin To makesure touch key pin data from APP is legal.
  136. *
  137. * @retval none
  138. */
  139. void touch_key_isr_init(u32 touch_pin)
  140. {
  141. u32 inpcon;
  142. sys_irq_init(IRQn_FREQUENCY_DET_TOUCH_KEY, 0, touch_key_isr);
  143. inpcon = BIT(0); //touch key pending interrupt enable
  144. if (touch_pin & 0x0f) {
  145. //inpcon |= BIT(4) //touch key bcnt valid pending interrupt enable
  146. inpcon |= (0xf << 5); //touch key exception pending interrupt enable
  147. inpcon |= BIT(13); //tkey press timeout interrupt enable
  148. //inpcon |= BIT(14); //touch key variance interrupt enable
  149. }
  150. INPCON = inpcon;
  151. }
  152. /**
  153. * @brief To reset touch key,so that we can change REGISTER value without power off.
  154. *
  155. * @retval none
  156. */
  157. void touch_key_sw_reset(void)
  158. {
  159. RTCCON0 |= BIT(4);
  160. INPCPND = BIT(0); //inpwr_swrst
  161. RTCCON0 &= ~BIT(19); //osc core disable
  162. }
  163. /**
  164. * @brief To init touch key clock.
  165. *
  166. * @params[in] touch_key_reg Touch Key Register Base Address
  167. * @params[in] clk_sel Touch Key Clock Select.
  168. * @params[in] tkclk_div2_enable CLK2M_TK to CLK2M_P divide
  169. *
  170. * @retval none
  171. */
  172. void touch_key_clk_init(touch_key_typedef *touch_key_reg, CLK_TOUCH_KEY_TYPEDEF clk_sel, uint8_t tkclk_div2_enable)
  173. {
  174. u32 clk_freq;
  175. clk_touch_key_clk_set(clk_sel);
  176. clk_freq = clk_touch_key_clk_get(CLK_VALUE_MODE_FREQ);
  177. INPCPND = BIT(0); //inpwr_swrst
  178. touch_key_reg->tkcon1 = 0;
  179. if (tkclk_div2_enable) {
  180. SETF_REG_TKCON1_DIV2SEL(); //CLK2M_TK to CLK2M_P divide
  181. SET_REG_TKCON1_TKCLK2MDIV((u32)(clk_freq / (125 * 2048))); //CLK2M to 32k divide
  182. } else {
  183. SET_REG_TKCON1_TKCLK2MDIV((u32)(clk_freq / (125 * 1024))); //CLK2M to 32k divide
  184. }
  185. SETF_REG_TKCON1_TKAEN(); //touch key analog enable
  186. SETF_REG_TKCON1_TKCEN(); //touch key clock enable
  187. SETF_REG_TKCON1_TKVCEN(); //touch key variance clock enable
  188. TRACE("%s: %x, %d\n", __func__, touch_key_reg->tkcon1, clk_freq);
  189. }
  190. /**
  191. * @brief To init touch key configuration,including clock and other registers.
  192. *
  193. * @params[in] touch_key_reg Touch Key Register Base Address
  194. * @params[in] tkey_cfg Touch Key Params From APP.
  195. * @params[in] first_pwron To Tell The Driver Whether Touch Key Is First Time Init Or Not.
  196. * @params[in] clk_sel Touch Key Clock Select.
  197. * @params[in] tkclk_div2_enable CLK2M_TK to CLK2M_P divide, typical value is 0.
  198. *
  199. * @retval -1: If failed
  200. 0: If success
  201. */
  202. int touch_key_init(touch_key_typedef *touch_key_reg, void *tkey_cfg, u32 first_pwron, CLK_TOUCH_KEY_TYPEDEF clk_sel, uint8_t tkclk_div2_enable)
  203. {
  204. int ret_code = 1;
  205. u32 touch_pin = 0;
  206. u16 tkbcnt;
  207. uint32_t tkcdpr0 = 0, tkcdpr1 = 0;
  208. if (tkey_cfg == NULL) {
  209. return -1;
  210. }
  211. tkey_cfg_t *p = (tkey_cfg_t *)tkey_cfg;
  212. INPCPND = BIT(0);
  213. // BGUV Reset TKSWRSTN disable
  214. RTCCON0 &= ~BIT(21);
  215. // Between Core Interface Enable, SNF_RC_EN
  216. RTCCON0 |= BIT(4) | BIT(19);
  217. if ((first_pwron) || (!(RTCCON0 & BIT(5)))) {
  218. //Touch Key Reset, or it will cause register write failure
  219. RTCCON0 |= BIT(5);
  220. touch_key_clk_init(touch_key_reg, clk_sel, tkclk_div2_enable);
  221. touch_key_reg->tkbcnt = 0xfff;
  222. touch_key_reg->tkcon = 0;
  223. ret_code = 0;
  224. }
  225. tkbcnt = touch_key_reg->tkbcnt & 0xfff;
  226. for (u8 i = 0; i < 4; i++) {
  227. tkey_ch_t *ch = (tkey_ch_t *)p->key[i];
  228. if (ch != NULL) {
  229. if (i == 0) {
  230. tkcdpr0 |= ((tkcdpr0 & (~BIT_REG_TKCDPR0_TKCDPR0)) | ((ch->cdpr) << POS_REG_TKCDPR0_TKCDPR0));
  231. SET_REG_TKACON0_CTRIM0(ch->ctrim);
  232. SET_REG_TKACON0_ITRIM0(ch->itrim);
  233. SETF_REG_TKCON_TK0_EN(); //touch key 0 enable
  234. SETF_REG_TKCON_TK0_PND_EN(); //touch key 0 pending enable
  235. RTCCON1 &= ~(1 << 4); //WK pull up disable, or may cause TKCNT error
  236. RTCCON1 |= BIT(8); //10s reset source 0:WKO 1 touch key
  237. if (ch->type) {
  238. SETF_REG_TKACON0_ENCHN0();
  239. }
  240. } else if (i == 1) {
  241. tkcdpr0 |= ((tkcdpr0 & (~BIT_REG_TKCDPR0_TKCDPR1)) | ((ch->cdpr) << POS_REG_TKCDPR0_TKCDPR1));
  242. SET_REG_TKACON0_CTRIM1(ch->ctrim);
  243. SET_REG_TKACON0_ITRIM1(ch->itrim);
  244. SETF_REG_TKCON_TK1_EN(); //touch key 1 enable
  245. SETF_REG_TKCON_TK1_PND_EN(); //touch key 1 pending enable
  246. if (ch->type) {
  247. SETF_REG_TKACON0_ENCHN1();
  248. }
  249. } else if (i == 2) {
  250. tkcdpr1 |= ((tkcdpr1 & (~BIT_REG_TKCDPR1_TKCDPR2)) | ((ch->cdpr) << POS_REG_TKCDPR1_TKCDPR2));
  251. SET_REG_TKACON1_CTRIM2(ch->ctrim);
  252. SET_REG_TKACON1_ITRIM2(ch->itrim);
  253. SETF_REG_TKCON_TK2_EN(); //touch key 2 enable
  254. SETF_REG_TKCON_TK2_PND_EN(); //touch key 2 pending enable
  255. if (ch->type) {
  256. SETF_REG_TKACON1_ENCHN2();
  257. }
  258. } else if (i == 3) {
  259. tkcdpr1 |= ((tkcdpr1 & (~BIT_REG_TKCDPR1_TKCDPR3)) | ((ch->cdpr) << POS_REG_TKCDPR1_TKCDPR3));
  260. SET_REG_TKACON1_CTRIM3(ch->ctrim);
  261. SET_REG_TKACON1_ITRIM3(ch->itrim);
  262. SETF_REG_TKCON_TK3_EN(); //touch key 3 enable
  263. SETF_REG_TKCON_TK3_PND_EN(); //touch key 3 pending enable
  264. if (ch->type) {
  265. SETF_REG_TKACON1_ENCHN3();
  266. }
  267. }
  268. if (ch->type == 1) {
  269. SET_REG_TKCON_TKSEL(0); //Select WKO for hardware wakeup
  270. // Touch Key Pin Select
  271. touch_pin |= BIT(i);
  272. }
  273. }
  274. }
  275. SET_REG_TKCON1_TKARTRIM(2);
  276. //touch key configure
  277. if (touch_pin & 0x0f) {
  278. touch_key_reg->tkbcnt = tkbcnt;
  279. touch_key_reg->tktmr = p->reg_tktmr;
  280. touch_key_reg->tkpthd = p->reg_tkpthd;
  281. touch_key_reg->tkethd = p->reg_tkethd;
  282. touch_key_reg->tkvari = p->reg_tkvari;
  283. touch_key_reg->tkvarithd = p->reg_tkvarithd;
  284. touch_key_reg->tkcon2 = p->reg_tkcon2;
  285. touch_key_reg->tkcdpr0 = tkcdpr0;
  286. touch_key_reg->tkcdpr1 = tkcdpr1;
  287. SETF_REG_TKCON_TKPTOUPDBEN(); //press timeout update base_cnt enable
  288. SETF_REG_TKCON_TKSTAWKEN(); //touch key wakeup enable
  289. SETF_REG_TKCON_TKSUPDBEN(); //small pending update base_cnt enable
  290. SETF_REG_TKCON_TKLUPDBEN(); //large pending update base_cnt enable
  291. SETF_REG_TKCON_TKRUPDBEN(); //range pending update base_cnt enable
  292. //SETF_REG_TKCON_TKTOUPDBEN(); //timerout pending update base_cnt enable
  293. SETF_REG_TKCON_TKBCNTVAL(); //touch key base_cnt valid enable
  294. }
  295. /*tkcon bit 4 5 is key channel*/
  296. TKCON &= ~(BIT(5) | BIT(4));
  297. // TKCON |= BIT(4);
  298. // TKCON |= BIT(5);
  299. // TKCON |= (BIT(5) | BIT(4));
  300. /*tkcon1 bit 14 15 is key along channel*/
  301. TKCON1 &= ~(BIT(14) | BIT(15));
  302. // TKCON1 |= BIT(14);
  303. // TKCON1 |= BIT(15);
  304. // TKCON1 |= (BIT(14) | BIT(15));
  305. /*small thmod*/
  306. TKCON |= BIT(1);
  307. /*range thmeod*/
  308. // TKCON &= ~BIT(25);
  309. SETF_REG_TKCON_TKEN(); //touch key enable
  310. SETF_REG_TKCON_TKAEN_ATSEL(); //touch key auto enable
  311. SETF_REG_TKCON_TK_MODE();
  312. delay_5ms(10);
  313. touch_key_isr_init(touch_pin);
  314. touch_key_dump();
  315. return ret_code;
  316. }