tkey.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. #include "include.h"
  2. #include "api.h"
  3. typedef struct {
  4. u32 anov_thres;
  5. u8 sta;
  6. u8 stable_cnt;
  7. u16 cnt;
  8. } te_cali_cb_t;
  9. tk_cb_t tk_cb;
  10. tk_cb_t tk1_cb;
  11. tk_cb_t te_cb;
  12. te_cali_cb_t te_cali_cb;
  13. u16 tkcnt_tmr[6]; //每个通路的实时TKCNT
  14. u8 tk_ch_temp;
  15. #if USER_TKEY_DEBUG_EN
  16. typedef struct {
  17. u16 tk_buf[16];
  18. u16 te_buf[16];
  19. char spp_buf[160];
  20. u8 tk_idx;
  21. u8 ch;
  22. volatile u8 tk_print_sta;
  23. u32 ticks;
  24. } spp_tkcb_t;
  25. spp_tkcb_t spp_tkcb AT(.tkey_buf.debug);
  26. AT(.rodata.tkey)
  27. const char tkcnt_str[] = "[TK] State(%01x), TKBCNT(%03x):\n";
  28. AT(.rodata.tkey)
  29. const char tecnt_str[] = "[TE] State(%01x), TEBCNT(%03x):\n";
  30. AT(.rodata.tkey)
  31. const char tkbcnt_str[] = "TKBCNT: %x\n";
  32. AT(.rodata.tkey)
  33. const char tkpend_str[] = "TK ERR: %x\n";
  34. AT(.rodata.tkey)
  35. const char tebcnt_str[] = "TEBCNT: %x\n";
  36. AT(.rodata.tkey)
  37. const char tepend_str[] = "TE ERR: %x\n";
  38. void spp_inpcon_tx(void)
  39. {
  40. int c_len = 0;
  41. if (tk_pnd_cb.flag & BIT(0)) {
  42. tk_pnd_cb.flag &= ~BIT(0);
  43. c_len += sprintf(spp_tkcb.spp_buf+c_len, tepend_str, tk_pnd_cb.te_exp);
  44. }
  45. if (tk_pnd_cb.flag & BIT(1)) {
  46. tk_pnd_cb.flag &= ~BIT(1);
  47. c_len += sprintf(spp_tkcb.spp_buf+c_len, tebcnt_str, tk_pnd_cb.tebcnt);
  48. }
  49. if (tk_pnd_cb.flag & BIT(2)) {
  50. tk_pnd_cb.flag &= ~BIT(2);
  51. c_len += sprintf(spp_tkcb.spp_buf+c_len, tkpend_str, tk_pnd_cb.tk_exp);
  52. }
  53. if (tk_pnd_cb.flag & BIT(3)) {
  54. tk_pnd_cb.flag &= ~BIT(3);
  55. c_len += sprintf(spp_tkcb.spp_buf+c_len, tkbcnt_str, tk_pnd_cb.tkbcnt);
  56. }
  57. if (c_len) {
  58. bt_spp_tx(SPP_SERVICE_CH0, (uint8_t *)spp_tkcb.spp_buf, c_len);
  59. }
  60. }
  61. //通过蓝牙SPP打印输出, 避免UART飞线干扰
  62. void spp_tkcnt_tx(void)
  63. {
  64. u16 tk_buf[8], te_buf[8];
  65. int c_len = 0, i;
  66. if (spp_tkcb.tk_print_sta) {
  67. memset(spp_tkcb.spp_buf, 0, sizeof(spp_tkcb.spp_buf));
  68. memcpy(tk_buf, &spp_tkcb.tk_buf[(spp_tkcb.tk_print_sta - 1)*8], 16);
  69. memcpy(te_buf, &spp_tkcb.te_buf[(spp_tkcb.tk_print_sta - 1)*8], 16);
  70. spp_tkcb.tk_print_sta = 0;
  71. if (tk_cb.ch != 0xff) {
  72. c_len += sprintf(spp_tkcb.spp_buf + c_len, tkcnt_str, tkey_get_key(), (u16)(TKBCNT & 0xffff));
  73. for (i = 0; i < 8; i++) {
  74. c_len += sprintf(spp_tkcb.spp_buf + c_len, "%04x ", tk_buf[i] & 0xffff);
  75. }
  76. c_len += sprintf(spp_tkcb.spp_buf + c_len, "\n");
  77. }
  78. #if USER_TKEY_INEAR
  79. if (te_cb.ch != 0xff) {
  80. c_len += sprintf(spp_tkcb.spp_buf + c_len, tecnt_str, tkey_is_inear(), (u16)(TEBCNT & 0xffff));
  81. for (i = 0; i < 8; i++) {
  82. c_len += sprintf(spp_tkcb.spp_buf + c_len, "%04x ", te_buf[i] & 0xffff);
  83. }
  84. c_len += sprintf(spp_tkcb.spp_buf + c_len, "\n");
  85. }
  86. #endif
  87. //printf((char *)spp_tkcb.spp_buf);
  88. bt_spp_tx(SPP_SERVICE_CH0, (uint8_t *)spp_tkcb.spp_buf, c_len);
  89. }
  90. }
  91. void bsp_tkey_spp_tx(void)
  92. {
  93. spp_tkcnt_tx(); //输出TKCNT
  94. // if (tick_check_expire(spp_tkcb.ticks, 100)) {
  95. // spp_tkcb.ticks = tick_get();
  96. // spp_inpcon_tx(); //输出一些状态
  97. // }
  98. }
  99. #endif // USER_TKEY_DEBUG_EN
  100. #if USER_TKEY
  101. void tkey_timeout_calibration(tk_cb_t *s, u16 tkcnt);
  102. //中断调用
  103. AT(.com_text.tkey.isr)
  104. void tkey_tkcnt_isr(u32 tk_ch, u16 tkcnt)
  105. {
  106. tkcnt_tmr[tk_ch] = tkcnt;
  107. if (tk_ch == te_cb.ch) {
  108. tkey_bcnt_range_exception(&te_cb, NULL, tkcnt);
  109. #if USER_TKEY_DEBUG_EN
  110. spp_tkcb.te_buf[spp_tkcb.tk_idx] = tkcnt;
  111. #endif
  112. } else if (tk_ch == tk_cb.ch) {
  113. tkey_bcnt_range_exception(&tk_cb, &tk1_cb, tkcnt);
  114. tkey_timeout_calibration(&tk_cb,tkcnt);
  115. #if USER_TKEY_DEBUG_EN
  116. spp_tkcb.tk_buf[spp_tkcb.tk_idx] = tkcnt;
  117. #endif
  118. }
  119. #if USER_TKEY_SLIDE
  120. else if (tk_ch == tk1_cb.ch) {
  121. tkey_bcnt_range_exception(&tk1_cb, &tk_cb, tkcnt);
  122. tkey_timeout_calibration(&tk1_cb,tkcnt);
  123. }
  124. #endif
  125. #if USER_TKEY_TEMP_EN
  126. else if (tk_ch == 5) { //温度通道
  127. }
  128. #endif
  129. #if USER_TKEY_DEBUG_EN
  130. if (tk_ch == spp_tkcb.ch) {
  131. spp_tkcb.tk_idx++;
  132. if (spp_tkcb.tk_idx == 8) {
  133. spp_tkcb.tk_print_sta = 1;
  134. } else if (spp_tkcb.tk_idx >= 16) {
  135. spp_tkcb.tk_print_sta = 2;
  136. spp_tkcb.tk_idx = 0;
  137. }
  138. }
  139. #endif
  140. }
  141. /*****************************************************************************
  142. * 1. 函数功能:充电时校准触摸的基准值BCNT
  143. * 2. 确保无触摸情况下调用(入仓且合盖可以确保未触摸),min_avg_cnt可以用小值。
  144. * 3. 不能确保有无触摸时被调用,min_avg_cnt * 8ms需要超过10秒以上。
  145. * 4. 此函数不需要频繁调用,建议10秒以上间隔。
  146. ******************************************************************************/
  147. AT(.text.bsp.tkey)
  148. void bsp_charge_bcnt_calibration(u32 min_avg_cnt)
  149. {
  150. #if USER_TKEY_INEAR
  151. if (te_cb.ch != 0xff) {
  152. // printf("calibration: %d, %d\n", te_cb.anov_cnt, min_avg_cnt);
  153. if (te_cb.anov_cnt > 100) {
  154. if ((!te_cali_cb.sta) && (te_cali_cb.stable_cnt < 3)) {
  155. RTCCON8 |= BIT(1); //RI_CHSTOPS = 1, 延时400ms校准
  156. te_cali_cb.cnt = 120;
  157. te_cali_cb.anov_thres = 50; //与延时时间长短有关
  158. te_cali_cb.sta = 1;
  159. }
  160. }
  161. }
  162. #endif
  163. if (tk_cb.ch != 0xff) {
  164. if (tk_cb.anov_cnt > min_avg_cnt) { //tkcnt是否稳定?
  165. u16 tkbcnt = TKBCNT & 0xffff;
  166. if (s_abs((s16)tkbcnt - (s16)tk_cb.avg) > 2) {
  167. TKBCNT = tk_cb.avg;
  168. }
  169. }
  170. }
  171. }
  172. AT(.text.bsp.charge)
  173. void tkey_proc_calibration_in_charge(void)
  174. {
  175. u16 cali_val;
  176. u16 cur_tebcnt = TEBCNT & 0xffff;
  177. if (te_cali_cb.sta) {
  178. if (te_cali_cb.cnt) {
  179. te_cali_cb.cnt--;
  180. } else {
  181. cali_val = te_cb.avg;
  182. RTCCON8 &= ~BIT(1); //RI_CHSTOPS = 0;
  183. te_cali_cb.sta = 0;
  184. if (te_cb.anov_cnt > te_cali_cb.anov_thres) {
  185. if (s_abs((s16)cur_tebcnt - (s16)cali_val) > 2) {
  186. if (tk_ch_temp != 0xff) {
  187. te_cb.temp_tkcnt = tkcnt_tmr[tk_ch_temp];
  188. }
  189. TEBCNT = cali_val;
  190. // printf("tebcnt calibration: %x\n", cali_val);
  191. } else {
  192. te_cali_cb.stable_cnt++;
  193. }
  194. } else {
  195. te_cali_cb.stable_cnt = 0;
  196. }
  197. }
  198. }
  199. }
  200. AT(.text.bsp.tkey)
  201. void tkey_stop_calibration_in_charge(void)
  202. {
  203. if (te_cb.ch != 0xff) {
  204. if (te_cali_cb.sta) {
  205. RTCCON8 &= ~BIT(1); //RI_CHSTOPS = 0;
  206. }
  207. memset(&te_cali_cb, 0, sizeof(te_cali_cb));
  208. bsp_tebcnt_temp_calibration_stop();
  209. }
  210. }
  211. AT(.text.bsp.tkey)
  212. void bsp_tebcnt_temp_calibration_start(void)
  213. {
  214. if ((te_cb.ch != 0xff) && (tk_ch_temp != 0xff)){
  215. te_cb.range_en = 0;
  216. TKCON &= ~BIT(29);
  217. te_cb.temp_tkcnt = tkcnt_tmr[tk_ch_temp];
  218. te_cb.tick = tick_get();
  219. // printf("calibration start\n");
  220. }
  221. }
  222. AT(.text.bsp.tkey)
  223. void bsp_tebcnt_temp_calibration(void)
  224. {
  225. if ((te_cb.ch != 0xff) && (tk_ch_temp != 0xff)) {
  226. u16 cur_tkcnt = tkcnt_tmr[tk_ch_temp];
  227. te_cb.tick = tick_get();
  228. if (te_temp_bcnt_calibration(cur_tkcnt, te_cb.temp_tkcnt)) {
  229. te_cb.temp_tkcnt = cur_tkcnt;
  230. }
  231. }
  232. }
  233. AT(.text.bsp.tkey)
  234. void bsp_tebcnt_temp_calibration_stop(void)
  235. {
  236. if ((te_cb.ch != 0xff) && (tk_ch_temp != 0xff)) {
  237. bsp_tebcnt_temp_calibration();
  238. delay_5ms(2);
  239. TKCON |= BIT(29);
  240. te_cb.range_en = 1;
  241. // printf("calibration stop: %x\n", TEBCNT & 0xffff);
  242. }
  243. }
  244. void bsp_tkey_channel_set(void)
  245. {
  246. int i;
  247. for (i = 0; i < 5; i++) {
  248. tkey_ch_t *ch = (tkey_ch_t *)tkey_cfg.key[i];
  249. if (ch) {
  250. if (ch->type == 2) {
  251. te_cb.ch = i;
  252. } else if (ch->type == 1) {
  253. if (tk_cb.ch == 0xff) {
  254. tk_cb.ch = i;
  255. } else if (tk1_cb.ch == 0xff) {
  256. tk1_cb.ch = i;
  257. }
  258. }
  259. #if USER_TKEY_DEBUG_EN
  260. spp_tkcb.ch = i;
  261. #endif
  262. }
  263. }
  264. #if USER_TKEY_TEMP_EN
  265. tk_ch_temp = 5; //temp ch5
  266. #endif
  267. }
  268. AT(.com_text.tkey)
  269. bool tkey_is_pressed(void)
  270. {
  271. if (tk_cb.ch == 0xff) {
  272. return false;
  273. }
  274. if (!tkey_get_key()) {
  275. return false;
  276. }
  277. #if USER_TKEY_SLIDE
  278. if (tk1_cb.ch != 0xff) {
  279. if (tk1_cb.tkey_sta || tk_cb.tkey_sta) {
  280. return false;
  281. }
  282. if (tk1_cb.slide || tk_cb.slide) {
  283. return false;
  284. }
  285. }
  286. #endif
  287. return true;
  288. }
  289. #if USER_TKEY_SLIDE
  290. AT(.com_text.tkey)
  291. void tkey_slide_msg(u8 silde_up)
  292. {
  293. if (silde_up == 0) {
  294. msg_enqueue(KU_VOL_UP);
  295. } else {
  296. msg_enqueue(KU_VOL_DOWN);
  297. }
  298. }
  299. #endif
  300. AT(.com_text.tkey)
  301. u8 bsp_tkey_scan(void)
  302. {
  303. u8 key = NO_KEY;
  304. if (tkey_is_pressed()) {
  305. key = (USER_TKEY_SOFT_PWR_EN) ? KEY_PLAY_PWR_USER_DEF : KEY_PLAY_USER_DEF;
  306. }
  307. return key;
  308. }
  309. #endif // USER_TKEY
  310. void tkey_press_timeout_clr(void)
  311. {
  312. tk_pnd_cb.flag = 0;
  313. tk_pnd_cb.tk_exp = 0;
  314. }
  315. void tkey_press_timeout_process(void)
  316. {
  317. if ((tk_pnd_cb.flag & BIT(2)) && (tk_pnd_cb.tk_exp & BIT(4))) {
  318. TKBCNT = tkcnt_tmr[tk_cb.ch];
  319. }
  320. }
  321. void bsp_tkey_var_init(void)
  322. {
  323. memset(&tk_cb, 0, sizeof(tk_cb));
  324. memset(&tk1_cb, 0, sizeof(tk_cb));
  325. memset(&te_cb, 0, sizeof(te_cb));
  326. memset(&te_cali_cb, 0, sizeof(te_cali_cb));
  327. #if USER_TKEY_DEBUG_EN
  328. memset(&spp_tkcb, 0, sizeof(spp_tkcb));
  329. spp_tkcb.ch = 0xff;
  330. #endif
  331. tk_cb.limit = 28;
  332. tk_cb.range_thresh = TKRTHRESH;
  333. tk_cb.ch = 0xff;
  334. tk_cb.fil_except = FIL_EXCEPT;
  335. tk_cb.bcnt_sfr = (psfr_t)(&TKBCNT);
  336. tk_cb.range_en = 0; //软件range校准是否使能
  337. tk_cb.to_cnt = TO_EXCEPT; //10秒
  338. tk_cb.slide_interval_min = 10;
  339. tk_cb.slide_interval_max = 250;
  340. memcpy(&tk1_cb, &tk_cb, sizeof(tk_cb_t));
  341. te_cb.te_flag = 1;
  342. te_cb.limit = 30;
  343. te_cb.range_thresh = TERTHRESH - 2;
  344. te_cb.ch = 0xff;
  345. te_cb.bcnt_sfr = (psfr_t)(&TEBCNT);
  346. te_cb.fil_except = EAR_FIL_EXCEPT;
  347. te_cb.range_en = 1; //软件range校准是否使能
  348. tk_ch_temp = 0xff;
  349. }
  350. void bsp_tkey_init(void)
  351. {
  352. bsp_tkey_var_init();
  353. #if USER_TKEY
  354. int res;
  355. tkey_cfg_t tkey_cfg_v;
  356. memcpy(&tkey_cfg_v, &tkey_cfg, sizeof(tkey_cfg_t));
  357. bsp_tkey_channel_set();
  358. #if USER_TKEY_TEMP_EN
  359. if (tk_ch_temp != 0xff) {
  360. tkey_cfg_v.key[tk_ch_temp] = &tkey_temp_cali_ch;
  361. }
  362. #endif
  363. { ///重新TK TIMEOUT的配置值
  364. u32 i, dlypr = 0, to_exp, pto_exp;
  365. u32 pr_us;
  366. for (i = 0; i < 6; i++) {
  367. tkey_ch_t *ch = (tkey_ch_t *)tkey_cfg_v.key[i];
  368. if (ch != NULL) {
  369. dlypr += ch->dlypr;
  370. }
  371. }
  372. pr_us = (1000000 * 2048) / sys_get_rc2m_rtc_clk();
  373. to_exp = TO_EXCEPT*8*1000 / (pr_us*dlypr); //根据所有通道PR计算timeout exception的配置值
  374. pto_exp = ((PTO_EXCEPT << 8)*8*1000 / (pr_us*dlypr)) >> 8; //根据所有通道PR计算按下timerout的配置值
  375. if (pto_exp > 15) {
  376. pto_exp = 15;
  377. }
  378. tkey_cfg_v.pto_except = pto_exp;
  379. tkey_cfg_v.to_except = to_exp;
  380. tk_cb.to_cnt = to_exp;
  381. //printf("tkdlypr: %d, %d, %d\n", dlypr, to_exp, pto_exp);
  382. }
  383. res = tkey_init((void *)&tkey_cfg_v, sys_cb.rtc_first_pwron);
  384. if (tk_cb.ch != 0xff) {
  385. if (!res || sys_cb.inbox_wken_flag || (RTCCON9 & BIT(4)) || (!(RTCCON9 & BIT(6)))) {
  386. delay_5ms(5);
  387. TKBCNT = tkcnt_tmr[tk_cb.ch];
  388. }
  389. }
  390. if (te_cb.ch != 0xff) {
  391. delay_5ms(4);
  392. TEBCNT = tkcnt_tmr[te_cb.ch];
  393. }
  394. #else
  395. tkey_sw_reset();
  396. #endif // USER_TKEY
  397. }
  398. bool bsp_tkey_wakeup_en(void)
  399. {
  400. #if USER_TKEY
  401. if (tkey_cfg.key[0] != NULL) { //ch0跟wko同一个io
  402. return true;
  403. } else
  404. #endif
  405. {
  406. return false;
  407. }
  408. }