sc7a20.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. #include "include.h"
  2. #if SC7A20_EN
  3. #include "sc7a20.h"
  4. unsigned char interrupt_come = 0;
  5. bool sc7a20_online = false;
  6. void SL_MEMS_i2cWrite(u8 chip_id, u8 iic_addr, u8 iic_dat)
  7. {
  8. bsp_i2c_start();
  9. bsp_i2c_tx_byte(chip_id);
  10. bsp_i2c_rx_ack();
  11. bsp_i2c_tx_byte(iic_addr);
  12. bsp_i2c_rx_ack();
  13. bsp_i2c_tx_byte(iic_dat);
  14. bsp_i2c_rx_ack();
  15. bsp_i2c_stop();
  16. }
  17. void SL_MEMS_i2cRead(u8 chip_id, u8 iic_addr,u8 n,u8 *iic_dat)
  18. {
  19. bsp_i2c_start();
  20. bsp_i2c_tx_byte(chip_id);
  21. bsp_i2c_rx_ack();
  22. if (0xff != iic_addr) {
  23. bsp_i2c_tx_byte(iic_addr);
  24. bsp_i2c_rx_ack();
  25. }
  26. bsp_i2c_stop();
  27. delay_us(100);
  28. bsp_i2c_start();
  29. bsp_i2c_tx_byte(chip_id | 0x1);
  30. bsp_i2c_rx_ack();
  31. for (int i=0; i < n-1; i++) {
  32. *iic_dat++ = bsp_i2c_rx_byte();
  33. bsp_i2c_tx_ack();
  34. }
  35. *iic_dat++ = bsp_i2c_rx_byte();
  36. bsp_i2c_tx_nack();
  37. bsp_i2c_stop();
  38. }
  39. char SC7A20_Check()
  40. {
  41. unsigned char reg_value=0;
  42. SL_MEMS_i2cRead(SC7A20_ADDR_W, SC7A20_WHO_AM_I, 1, &reg_value);
  43. //printf("reg_value=%x\n", reg_value);
  44. if (reg_value == 0x11)
  45. {
  46. return 0x01;
  47. }
  48. else
  49. {
  50. return 0x00;
  51. }
  52. }
  53. AT(.com_text)
  54. const char test_str1[] = "SC7A20 interrupt coming\n";
  55. AT(.com_text.isr)
  56. void SC7A20_port_isr(void)
  57. {
  58. WDT_CLR();
  59. if ((WKUPEDG & (BIT(21) )) && (!(GPIOB & BIT(5)))) {
  60. WKUPCPND = (BIT(21)); //CLEAR PENDING
  61. interrupt_come = 1;
  62. //printf(test_str1, WKUPEDG >> 16);
  63. }
  64. }
  65. void SC7A20_Config_int(void) //sys_set_tmr_enable(1, 1);
  66. {
  67. #if 1
  68. GPIOBDE |= BIT(5);GPIOBDIR |= BIT(5);GPIOBFEN &= ~BIT(5);
  69. //GPIOBPU |= BIT(5);
  70. GPIOBPD |= BIT(5);
  71. //PORTINTEN |= BIT(12);
  72. //PORTINTEDG |= BIT(12); //falling edge;
  73. WKUPCPND = 0xff << 16;
  74. //WKUPEDG |= BIT(5); //falling edge
  75. WKUPEDG &= ~BIT(5); //raising edge
  76. WKUPCON = BIT(5) | BIT(16); //falling edge wake iput //wakeup int en
  77. #else
  78. GPIOBDE |= BIT(5);GPIOBDIR |= BIT(5);GPIOBFEN &= ~BIT(5);
  79. GPIOBPU |= BIT(5);
  80. //GPIOBPD |= BIT(5);
  81. //PORTINTEN |= BIT(12);
  82. //PORTINTEDG |= BIT(12); //falling edge;
  83. WKUPCPND = 0xff << 16;
  84. WKUPEDG |= BIT(5); //falling edge
  85. //WKUPEDG &= ~BIT(5); //raising edge
  86. WKUPCON = BIT(5) | BIT(16); //falling edge wake iput //wakeup int en
  87. #endif
  88. sys_irq_init(IRQ_PORT_VECTOR, 0, SC7A20_port_isr);
  89. }
  90. u8 SC7A20_Config(void)
  91. {
  92. u8 Check_Flag=0;
  93. u8 cnt;
  94. //unsigned char reg_value=0;
  95. //timer3_init();
  96. //printf("SC7A20_Config\n");
  97. sc7a20_online = false;
  98. SC7A20_Config_int();
  99. for (cnt = 0x0; cnt < 0x03; cnt++)
  100. {
  101. Check_Flag = SC7A20_Check();
  102. if (!Check_Flag)
  103. {
  104. printf("will retry check\n");
  105. }
  106. else
  107. {
  108. break;
  109. }
  110. }
  111. if (Check_Flag == 1)
  112. {
  113. SL_MEMS_i2cWrite(SC7A20_ADDR_W, SC7A20_CTRL_REG1, 0x7f);
  114. SL_MEMS_i2cWrite(SC7A20_ADDR_W, SC7A20_CTRL_REG2, 0x0C);
  115. //SL_MEMS_i2cWrite(SC7A20_ADDR_W, SC7A20_CTRL_REG3, 0x80);// click int1
  116. //SL_MEMS_i2cWrite(SC7A20_ADDR_W, SC7A20_CTRL_REG6, 0x80);// click int2
  117. SL_MEMS_i2cWrite(SC7A20_ADDR_W, SC7A20_CTRL_REG4, 0x90);
  118. SL_MEMS_i2cWrite(SC7A20_ADDR_W, SC7A20_CTRL_REG5, 0x40);
  119. SL_MEMS_i2cWrite(SC7A20_ADDR_W, SC7A20_FIFO_CTRL_REG, 0x80);
  120. SL_MEMS_i2cWrite(SC7A20_ADDR_W, SC7A20_CLICK_CFG, 0x15);
  121. SL_MEMS_i2cWrite(SC7A20_ADDR_W, SC7A20_CLICK_THS, 0x25);
  122. SL_MEMS_i2cWrite(SC7A20_ADDR_W, SC7A20_TIME_LIMIT, 0x05);
  123. SL_MEMS_i2cWrite(SC7A20_ADDR_W, SC7A20_TIME_LATENCY, 0x10);
  124. SL_MEMS_i2cWrite(SC7A20_ADDR_W, SC7A20_CTRL_REG6, 0x80);// click int2 low
  125. //SL_MEMS_i2cWrite(SC7A20_ADDR_W, SC7A20_CTRL_REG6, 0x82);// click int2 high
  126. sc7a20_online = true;
  127. return 1;
  128. }
  129. else
  130. {
  131. //printf("init sc7a20 fail\n");
  132. sc7a20_online = false;
  133. return 0;
  134. }
  135. }
  136. unsigned char sl_pp_num=0;
  137. unsigned char SL_Get_CLICK_PP_CNT(unsigned char fun_flag)
  138. {
  139. if (fun_flag == 0)
  140. sl_pp_num = 0;
  141. return sl_pp_num;
  142. }
  143. unsigned int SL_Click_Sqrt(unsigned int sqrt_data)
  144. {
  145. unsigned int SL_SQRT_LOW, SL_SQRT_UP, SL_SQRT_MID;
  146. unsigned char sl_sqrt_num = 0;
  147. SL_SQRT_LOW = 0;
  148. SL_SQRT_UP = sqrt_data;
  149. SL_SQRT_MID = (SL_SQRT_UP+SL_SQRT_LOW)/2;
  150. while (sl_sqrt_num < 200)
  151. {
  152. if (SL_SQRT_MID*SL_SQRT_MID > sqrt_data)
  153. {
  154. SL_SQRT_UP = SL_SQRT_MID;
  155. }
  156. else
  157. {
  158. SL_SQRT_LOW = SL_SQRT_MID;
  159. }
  160. if (SL_SQRT_UP-SL_SQRT_LOW == 1)
  161. {
  162. if ((SL_SQRT_UP*SL_SQRT_UP - sqrt_data) > (sqrt_data - SL_SQRT_LOW*SL_SQRT_LOW))
  163. {
  164. return SL_SQRT_LOW;
  165. }
  166. else
  167. {
  168. return SL_SQRT_UP;
  169. }
  170. }
  171. SL_SQRT_MID = (SL_SQRT_UP+SL_SQRT_LOW)/2;
  172. sl_sqrt_num++;
  173. }
  174. return 0;
  175. }
  176. char SC7A20_Click_Read(int TH1,int TH2)
  177. {
  178. unsigned char i = 0, j = 0, k = 0;
  179. unsigned char click_num = 0;
  180. unsigned char fifo_len;
  181. unsigned int sc7a20_data = 0;
  182. unsigned int fifo_data_xyz[32];
  183. unsigned char click_result = 0x00;
  184. unsigned int click_sum = 0;
  185. unsigned char data1[6];
  186. signed char data[6];
  187. SL_MEMS_i2cRead(SC7A20_ADDR_W, SC7A20_SRC_REG,1, &fifo_len);
  188. if ((fifo_len & 0x40) == 0x40)
  189. fifo_len = 32;
  190. else
  191. fifo_len = (fifo_len & 0x1f);
  192. for (i = 0; i < fifo_len; i++)
  193. {
  194. SL_MEMS_i2cRead(SC7A20_ADDR_W, 0xA8, 6, &data1[0]);
  195. data[1] = (signed char)data1[1];
  196. data[3] = (signed char)data1[3];
  197. data[5] = (signed char)data1[5];
  198. sc7a20_data = (data[1])*(data[1]) + (data[3])*(data[3]) + (data[5])*(data[5]);
  199. sc7a20_data = SL_Click_Sqrt(sc7a20_data);
  200. fifo_data_xyz[i] = sc7a20_data;
  201. }
  202. k = 0;
  203. for (i = 1;i < fifo_len - 1; i++)
  204. {
  205. if ((fifo_data_xyz[i+1] > TH1) && (fifo_data_xyz[i-1] < 30))
  206. {
  207. if (click_num == 0)
  208. {
  209. click_sum = 0;//first peak
  210. for (j = 0;j < i - 1; j++)
  211. {
  212. if (fifo_data_xyz[j] > fifo_data_xyz[j+1])
  213. {
  214. click_sum += fifo_data_xyz[j] - fifo_data_xyz[j+1];
  215. }
  216. else
  217. {
  218. click_sum += fifo_data_xyz[j+1] - fifo_data_xyz[j];
  219. }
  220. }
  221. if (click_sum > TH2)
  222. {
  223. sl_pp_num++;
  224. //printf("click_sum :%d > TH2 = %d sl_pp_num %d \n",click_sum, TH2, sl_pp_num);
  225. break;
  226. }
  227. k = i;
  228. }
  229. else
  230. {
  231. k = i;//sencond peak
  232. }
  233. }
  234. if (k != 0)
  235. {
  236. if ((fifo_data_xyz[i-1] - fifo_data_xyz[i+1]) > (TH1 - 10))
  237. {
  238. if ((i - k) < 5)
  239. {
  240. click_num = 1;
  241. break;
  242. }
  243. }
  244. }
  245. }
  246. if (click_num == 1)
  247. {
  248. click_result = 1;
  249. }
  250. else
  251. {
  252. click_result = 0;
  253. }
  254. //printf("click_result == %d\n",click_result);
  255. return click_result;
  256. }
  257. //Service function in Int Function
  258. //unsigned char sl_click_timer_en =0;
  259. unsigned char sl_click_status = 0;
  260. unsigned short click_timer_cnt = 0;
  261. unsigned short click_timer_total_cnt = 0;
  262. unsigned char click_click_final_cnt = 0;
  263. unsigned char volatile sl_click_timer_en = 0;
  264. u8 SC7A20_Click_Alog(void)
  265. {
  266. unsigned char click_status=0;
  267. //SL_MEMS_i2cWrite(SC7A20_ADDR_W, SC7A20_CTRL_REG6, 0x00);
  268. click_status = SC7A20_Click_Read(35, 55);
  269. if (click_status == 1)
  270. {
  271. if (sl_click_timer_en == 0)
  272. {
  273. //set click timer flag
  274. sl_click_timer_en = 1;
  275. //clear click timer cnt value
  276. click_timer_cnt = 0;
  277. click_timer_total_cnt = 0;
  278. click_click_final_cnt = 0;
  279. }
  280. sl_click_status = 1;
  281. }
  282. //printf("click_status : %d,sl_click_timer_en = %d\n",click_status,sl_click_timer_en);
  283. //SL_MEMS_i2cWrite(SC7A20_ADDR_W, SC7A20_CTRL_REG6, 0x82);
  284. return click_status;
  285. }
  286. #define click_pp_num (unsigned short)10 //10-0.5s
  287. #define click_max_num (unsigned short)55//55 //5s
  288. //This fuction is execute in 50ms timer when the timer is opened
  289. u8 SC7A20_click_status(void)
  290. {
  291. unsigned char click_e_cnt = 0;
  292. WDT_CLR();
  293. if (sl_click_timer_en == 1)
  294. {
  295. click_timer_cnt++;
  296. if ((click_timer_cnt < click_pp_num) && sl_click_status == 1)
  297. {
  298. //printf("status:%d\n", sl_click_status);
  299. //printf("fin_num:%d\n", click_click_final_cnt);
  300. sl_click_status = 0;
  301. click_timer_total_cnt = click_timer_total_cnt + click_timer_cnt;
  302. click_timer_cnt = 0;
  303. click_click_final_cnt++;
  304. }
  305. click_e_cnt = SL_Get_CLICK_PP_CNT(1);
  306. //printf("click_e_cnt = %d,click_timer_cnt = %d,click_timer_total_cnt =%d\n",click_e_cnt,click_timer_cnt,click_timer_total_cnt);
  307. if ((((click_timer_cnt >= click_pp_num) || (click_timer_total_cnt >= click_max_num)) && (click_e_cnt < 1)) ||
  308. ((click_timer_cnt >= click_pp_num) && (click_e_cnt > 0)))
  309. {
  310. //clear click timer flag
  311. sl_click_timer_en = 0;
  312. //clear click timer cnt value
  313. click_timer_cnt = 0;
  314. click_timer_total_cnt = 0;
  315. if (click_e_cnt > 0)
  316. {
  317. //printf("click_e_cnt %d SC7A20_click_status return 0\n", click_e_cnt);
  318. click_e_cnt = SL_Get_CLICK_PP_CNT(0);
  319. return 0;
  320. }
  321. else
  322. {
  323. //printf("click_e_cnt %d SC7A20_click_status return final_cnt %d\n", click_e_cnt, click_click_final_cnt);
  324. return click_click_final_cnt;
  325. }
  326. }
  327. }
  328. return 0;
  329. }
  330. void sc7a20_status_scan(void)
  331. {
  332. static u32 click_ticks = 0;
  333. u8 click_cnt = 0;
  334. u8 click_status = 0;
  335. if (sc7a20_online == true && interrupt_come) {
  336. interrupt_come = 0;
  337. click_status = SC7A20_Click_Alog();
  338. if (click_status == 1)
  339. SL_MEMS_i2cWrite(SC7A20_ADDR_W, SC7A20_CTRL_REG6, 0x00);//SC7A20用来保护超时时间段的数据。
  340. }
  341. //WDT_CLR();
  342. if (tick_check_expire(click_ticks, 50) && sl_click_timer_en){
  343. click_cnt = SC7A20_click_status();
  344. SL_MEMS_i2cWrite(SC7A20_ADDR_W, SC7A20_CTRL_REG6, 0x80);//SC7A20 low
  345. //SL_MEMS_i2cWrite(SC7A20_ADDR_W, SC7A20_CTRL_REG6, 0x82); //high
  346. switch(click_cnt)
  347. {
  348. case 1:
  349. msg_enqueue(KU_PLAY_USER_DEF);
  350. //printf("key:click\n");
  351. break;
  352. case 2:
  353. //printf("key:double click\n");
  354. msg_enqueue(KD_PLAY_PWR_USER_DEF);
  355. break;
  356. case 3:
  357. //printf("key:triple click\n");
  358. msg_enqueue(KTH_PLAY_PWR_USER_DEF);
  359. break;
  360. default:
  361. break;
  362. }
  363. click_ticks = tick_get();
  364. }
  365. }
  366. u8 sc7a20_enter_lowpow(void)
  367. {
  368. //printf("%s\n", __func__);
  369. SL_MEMS_i2cWrite(SC7A20_ADDR_W, SC7A20_CTRL_REG1, 0x8f);
  370. return 0;
  371. }
  372. #endif