APDS-9960传感器具有先进的手势检测、接近检测、数字环境光感(ALS)和色感(RGBC)。

APDS_9960.c

  1. 1 /**
  2. 2 * @file APDS_9960.c
  3. 3 * @brief APDS-9960传感器的源文件
  4. 4 * @version 0.1
  5. 5 * @date 2019-07-02
  6. 6 *
  7. 7 * @copyright Copyright (c) 2019 Chipintelli Technology Co., Ltd.
  8. 8 *
  9. 9 */
  10. 10 /*-----------------------------------------------------------------------------
  11. 11 header
  12. 12 -----------------------------------------------------------------------------*/
  13. 13 #include "string.h"
  14. 14 #include "APDS_9960.h"
  15. 15 #include "ci110x_i2c.h"
  16. 16 #include "ci110x_gpio.h"
  17. 17 #include "ci110x_scu.h"
  18. 18 #include "ci_misc.h"
  19. 19 #include "ci_log.h"
  20. 20
  21. 21 /*-----------------------------------------------------------------------------
  22. 22 define
  23. 23 -----------------------------------------------------------------------------*/
  24. 24 #define DEBUG 0
  25. 25
  26. 26 /* APDS-9960 I2C address */
  27. 27 #define APDS9960_I2C_ADDR 0x39/*!< APDS-9960传感器IIC总线地址 */
  28. 28
  29. 29 /* Gesture parameters */
  30. 30 #define GESTURE_THRESHOLD_OUT 10
  31. 31 #define GESTURE_SENSITIVITY_1 50
  32. 32 #define GESTURE_SENSITIVITY_2 20
  33. 33
  34. 34 /* Error code for returned values */
  35. 35 #define ERROR 0xFF
  36. 36
  37. 37 /* Acceptable device IDs */
  38. 38 #define APDS9960_ID_1 0xAB
  39. 39 #define APDS9960_ID_2 0x9C
  40. 40
  41. 41 /* Misc parameters */
  42. 42 #define FIFO_PAUSE_TIME 30 /*!< Wait period (ms) between FIFO reads */
  43. 43
  44. 44 /* APDS-9960 register addresses */
  45. 45 #define APDS9960_ENABLE 0x80
  46. 46 #define APDS9960_ATIME 0x81
  47. 47 #define APDS9960_WTIME 0x83
  48. 48 #define APDS9960_AILTL 0x84
  49. 49 #define APDS9960_AILTH 0x85
  50. 50 #define APDS9960_AIHTL 0x86
  51. 51 #define APDS9960_AIHTH 0x87
  52. 52 #define APDS9960_PILT 0x89
  53. 53 #define APDS9960_PIHT 0x8B
  54. 54 #define APDS9960_PERS 0x8C
  55. 55 #define APDS9960_CONFIG1 0x8D
  56. 56 #define APDS9960_PPULSE 0x8E
  57. 57 #define APDS9960_CONTROL 0x8F
  58. 58 #define APDS9960_CONFIG2 0x90
  59. 59 #define APDS9960_ID 0x92
  60. 60 #define APDS9960_STATUS 0x93
  61. 61 #define APDS9960_CDATAL 0x94
  62. 62 #define APDS9960_CDATAH 0x95
  63. 63 #define APDS9960_RDATAL 0x96
  64. 64 #define APDS9960_RDATAH 0x97
  65. 65 #define APDS9960_GDATAL 0x98
  66. 66 #define APDS9960_GDATAH 0x99
  67. 67 #define APDS9960_BDATAL 0x9A
  68. 68 #define APDS9960_BDATAH 0x9B
  69. 69 #define APDS9960_PDATA 0x9C
  70. 70 #define APDS9960_POFFSET_UR 0x9D
  71. 71 #define APDS9960_POFFSET_DL 0x9E
  72. 72 #define APDS9960_CONFIG3 0x9F
  73. 73 #define APDS9960_GPENTH 0xA0
  74. 74 #define APDS9960_GEXTH 0xA1
  75. 75 #define APDS9960_GCONF1 0xA2
  76. 76 #define APDS9960_GCONF2 0xA3
  77. 77 #define APDS9960_GOFFSET_U 0xA4
  78. 78 #define APDS9960_GOFFSET_D 0xA5
  79. 79 #define APDS9960_GOFFSET_L 0xA7
  80. 80 #define APDS9960_GOFFSET_R 0xA9
  81. 81 #define APDS9960_GPULSE 0xA6
  82. 82 #define APDS9960_GCONF3 0xAA
  83. 83 #define APDS9960_GCONF4 0xAB
  84. 84 #define APDS9960_GFLVL 0xAE
  85. 85 #define APDS9960_GSTATUS 0xAF
  86. 86 #define APDS9960_IFORCE 0xE4
  87. 87 #define APDS9960_PICLEAR 0xE5
  88. 88 #define APDS9960_CICLEAR 0xE6
  89. 89 #define APDS9960_AICLEAR 0xE7
  90. 90 #define APDS9960_GFIFO_U 0xFC
  91. 91 #define APDS9960_GFIFO_D 0xFD
  92. 92 #define APDS9960_GFIFO_L 0xFE
  93. 93 #define APDS9960_GFIFO_R 0xFF
  94. 94
  95. 95 /* Bit fields */
  96. 96 #define APDS9960_PON 0x01
  97. 97 #define APDS9960_AEN 0x02
  98. 98 #define APDS9960_PEN 0x04
  99. 99 #define APDS9960_WEN 0x08
  100. 100 #define APSD9960_AIEN 0x10
  101. 101 #define APDS9960_PIEN 0x20
  102. 102 #define APDS9960_GEN 0x40
  103. 103 #define APDS9960_GVALID 0x01
  104. 104
  105. 105 /* On/Off definitions */
  106. 106 #define OFF 0
  107. 107 #define ON 1
  108. 108
  109. 109 /* Acceptable parameters for set_mode */
  110. 110 #define POWER 0
  111. 111 #define AMBIENT_LIGHT 1
  112. 112 #define PROXIMITY 2
  113. 113 #define WAIT 3
  114. 114 #define AMBIENT_LIGHT_INT 4
  115. 115 #define PROXIMITY_INT 5
  116. 116 #define GESTURE 6
  117. 117 #define ALL 7
  118. 118
  119. 119 /* LED Drive values */
  120. 120 #define LED_DRIVE_100MA 0
  121. 121 #define LED_DRIVE_50MA 1
  122. 122 #define LED_DRIVE_25MA 2
  123. 123 #define LED_DRIVE_12_5MA 3
  124. 124
  125. 125 /* Proximity Gain (PGAIN) values */
  126. 126 #define PGAIN_1X 0
  127. 127 #define PGAIN_2X 1
  128. 128 #define PGAIN_4X 2
  129. 129 #define PGAIN_8X 3
  130. 130
  131. 131 /* ALS Gain (AGAIN) values */
  132. 132 #define AGAIN_1X 0
  133. 133 #define AGAIN_4X 1
  134. 134 #define AGAIN_16X 2
  135. 135 #define AGAIN_64X 3
  136. 136
  137. 137 /* Gesture Gain (GGAIN) values */
  138. 138 #define GGAIN_1X 0
  139. 139 #define GGAIN_2X 1
  140. 140 #define GGAIN_4X 2
  141. 141 #define GGAIN_8X 3
  142. 142
  143. 143 /* LED Boost values */
  144. 144 #define LED_BOOST_100 0
  145. 145 #define LED_BOOST_150 1
  146. 146 #define LED_BOOST_200 2
  147. 147 #define LED_BOOST_300 3
  148. 148
  149. 149 /* Gesture wait time values */
  150. 150 #define GWTIME_0MS 0
  151. 151 #define GWTIME_2_8MS 1
  152. 152 #define GWTIME_5_6MS 2
  153. 153 #define GWTIME_8_4MS 3
  154. 154 #define GWTIME_14_0MS 4
  155. 155 #define GWTIME_22_4MS 5
  156. 156 #define GWTIME_30_8MS 6
  157. 157 #define GWTIME_39_2MS 7
  158. 158
  159. 159 /* Default values */
  160. 160 #define DEFAULT_ATIME 219 // 103ms
  161. 161 #define DEFAULT_WTIME 246 // 27ms
  162. 162 #define DEFAULT_PROX_PPULSE 0x87 // 16us, 8 pulses
  163. 163 #define DEFAULT_GESTURE_PPULSE 0x89 // 16us, 10 pulses
  164. 164 #define DEFAULT_POFFSET_UR 0 // 0 offset
  165. 165 #define DEFAULT_POFFSET_DL 0 // 0 offset
  166. 166 #define DEFAULT_CONFIG1 0x60 // No 12x wait (WTIME) factor
  167. 167 #define DEFAULT_LDRIVE LED_DRIVE_100MA
  168. 168 #define DEFAULT_PGAIN PGAIN_4X
  169. 169 #define DEFAULT_AGAIN AGAIN_4X
  170. 170 #define DEFAULT_PILT 0 // Low proximity threshold
  171. 171 #define DEFAULT_PIHT 50 // High proximity threshold
  172. 172 #define DEFAULT_AILT 0xFFFF // Force interrupt for calibration
  173. 173 #define DEFAULT_AIHT 0
  174. 174 #define DEFAULT_PERS 0x11 // 2 consecutive prox or ALS for int.
  175. 175 #define DEFAULT_CONFIG2 0x01 // No saturation interrupts or LED boost
  176. 176 #define DEFAULT_CONFIG3 0 // Enable all photodiodes, no SAI
  177. 177 #define DEFAULT_GPENTH 40 // Threshold for entering gesture mode
  178. 178 #define DEFAULT_GEXTH 30 // Threshold for exiting gesture mode
  179. 179 #define DEFAULT_GCONF1 0x40 // 4 gesture events for int., 1 for exit
  180. 180 #define DEFAULT_GGAIN GGAIN_4X
  181. 181 #define DEFAULT_GLDRIVE LED_DRIVE_100MA
  182. 182 #define DEFAULT_GWTIME GWTIME_2_8MS
  183. 183 #define DEFAULT_GOFFSET 0 // No offset scaling for gesture mode
  184. 184 #define DEFAULT_GPULSE 0xC9 // 32us, 10 pulses
  185. 185 #define DEFAULT_GCONF3 0 // All photodiodes active during gesture
  186. 186 #define DEFAULT_GIEN 0 // Disable gesture interrupts
  187. 187
  188. 188 /*-----------------------------------------------------------------------------
  189. 189 extern
  190. 190 -----------------------------------------------------------------------------*/
  191. 191
  192. 192 /*-----------------------------------------------------------------------------
  193. 193 struct / enum / union
  194. 194 -----------------------------------------------------------------------------*/
  195. 195 /* Direction definitions */
  196. 196 enum
  197. 197 {
  198. 198 DIR_NONE,
  199. 199 DIR_LEFT,
  200. 200 DIR_RIGHT,
  201. 201 DIR_UP,
  202. 202 DIR_DOWN,
  203. 203 DIR_NEAR,
  204. 204 DIR_FAR,
  205. 205 DIR_ALL
  206. 206 };
  207. 207
  208. 208 /* State definitions */
  209. 209 enum
  210. 210 {
  211. 211 NA_STATE,
  212. 212 NEAR_STATE,
  213. 213 FAR_STATE,
  214. 214 ALL_STATE
  215. 215 };
  216. 216 /* Container for gesture data */
  217. 217 typedef struct
  218. 218 {
  219. 219 uint8_t u_data[32];
  220. 220 uint8_t d_data[32];
  221. 221 uint8_t l_data[32];
  222. 222 uint8_t r_data[32];
  223. 223 uint8_t index;
  224. 224 uint8_t total_gestures;
  225. 225 uint8_t in_threshold;
  226. 226 uint8_t out_threshold;
  227. 227 }gesture_data_type;
  228. 228
  229. 229 /*-----------------------------------------------------------------------------
  230. 230 global
  231. 231 -----------------------------------------------------------------------------*/
  232. 232 /* Members */
  233. 233 gesture_data_type gesture_data_;
  234. 234
  235. 235 int gesture_ud_delta_;
  236. 236 int gesture_lr_delta_;
  237. 237 int gesture_ud_count_;
  238. 238 int gesture_lr_count_;
  239. 239 int gesture_near_count_;
  240. 240 int gesture_far_count_;
  241. 241 int gesture_state_;
  242. 242 int gesture_motion_;
  243. 243
  244. 244 void (*apds_callback)(void);
  245. 245
  246. 246 /*-----------------------------------------------------------------------------
  247. 247 declare
  248. 248 -----------------------------------------------------------------------------*/
  249. 249
  250. 250 /*-----------------------------------------------------------------------------
  251. 251 function
  252. 252 -----------------------------------------------------------------------------*/
  253. 253 static void delay_ms(int ms)
  254. 254 {
  255. 255 int i=0;
  256. 256 while(ms--)
  257. 257 {
  258. 258 for(i=0;i<0x1A80;i++);
  259. 259 }
  260. 260 }
  261. 261
  262. 262 /**
  263. 263 * @brief Constructor - Instantiates sparkfun_apds9960 object
  264. 264 */
  265. 265 void sparkfun_apds9960(void)
  266. 266 {
  267. 267 gesture_ud_delta_ = 0;
  268. 268 gesture_lr_delta_ = 0;
  269. 269 gesture_ud_count_ = 0;
  270. 270 gesture_lr_count_ = 0;
  271. 271 gesture_near_count_ = 0;
  272. 272 gesture_far_count_ = 0;
  273. 273 gesture_state_ = 0;
  274. 274 gesture_motion_ = DIR_NONE;
  275. 275 }
  276. 276
  277. 277 /**
  278. 278 * @brief IIC 读取一个byte
  279. 279 *
  280. 280 * @param reg
  281. 281 * @param val
  282. 282 * @return true
  283. 283 * @return false
  284. 284 */
  285. 285 int8_t wire_read_data_byte(uint8_t reg,uint8_t *val)
  286. 286 {
  287. 287 char buf[256] = {0};
  288. 288 struct i2c_client client = {0};
  289. 289 client.flags = 1;
  290. 290 client.addr = APDS9960_I2C_ADDR;
  291. 291 strcpy(client.name,"apds9960");
  292. 292 buf[0] = reg;
  293. 293 i2c_master_recv(IIC1,&client,buf,2);
  294. 294 *val = buf[0];
  295. 295 delay_ms(5);
  296. 296 return RETURN_OK;
  297. 297 }
  298. 298
  299. 299 /**
  300. 300 * @brief IIC 写入一个byte
  301. 301 *
  302. 302 * @param reg
  303. 303 * @param val
  304. 304 * @return true
  305. 305 * @return false
  306. 306 */
  307. 307 int8_t wire_write_data_byte(uint8_t reg,uint8_t val)
  308. 308 {
  309. 309 char buf[256] = {0};
  310. 310 struct i2c_client client = {0};
  311. 311 client.flags = 0;
  312. 312 client.addr = APDS9960_I2C_ADDR;
  313. 313 strcpy(client.name,"apds9960");
  314. 314 buf[0] = reg;
  315. 315 buf[1] = val;
  316. 316 i2c_master_send(IIC1,&client,buf,2);
  317. 317 delay_ms(5);
  318. 318 return RETURN_OK;
  319. 319 }
  320. 320
  321. 321 /**
  322. 322 * @brief IIC 读取多个byte
  323. 323 *
  324. 324 * @param reg
  325. 325 * @param data
  326. 326 * @param len
  327. 327 * @return int8_t
  328. 328 */
  329. 329 int8_t wire_read_data_block(uint8_t reg,uint8_t *data,uint32_t len)
  330. 330 {
  331. 331 char buf[256] = {0};
  332. 332 struct i2c_client client = {0};
  333. 333 client.flags = 1;
  334. 334 client.addr = APDS9960_I2C_ADDR;
  335. 335 strcpy(client.name,"apds9960");
  336. 336 buf[0] = reg;
  337. 337 i2c_master_recv(IIC1,&client,buf,len + 1);
  338. 338 memcpy(data,buf,len);
  339. 339 delay_ms(5);
  340. 340 return len;
  341. 341 }
  342. 342
  343. 343 /**
  344. 344 * @brief IIC 写入多个byte
  345. 345 *
  346. 346 * @param reg
  347. 347 * @param data
  348. 348 * @param len
  349. 349 * @return int8_t
  350. 350 */
  351. 351 int8_t wire_write_data_block(uint8_t reg,uint8_t *data,uint32_t len)
  352. 352 {
  353. 353 char buf[256] = {0};
  354. 354 struct i2c_client client = {0};
  355. 355 client.flags = 0;
  356. 356 client.addr = APDS9960_I2C_ADDR;
  357. 357 strcpy(client.name,"apds9960");
  358. 358 buf[0] = reg;
  359. 359 strncpy(&buf[1],(char const*)data,len);
  360. 360 i2c_master_send(IIC1,&client,buf,len + 1);
  361. 361 delay_ms(5);
  362. 362 return len;
  363. 363 }
  364. 364
  365. 365 /**
  366. 366 * @brief Reads and returns the contents of the ENABLE register
  367. 367 *
  368. 368 * @return Contents of the ENABLE register. 0xFF if error.
  369. 369 */
  370. 370 uint8_t get_mode(void)
  371. 371 {
  372. 372 uint8_t enable_value;
  373. 373
  374. 374 /* Read current ENABLE register */
  375. 375 if( !wire_read_data_byte(APDS9960_ENABLE, &enable_value) )
  376. 376 {
  377. 377 return ERROR;
  378. 378 }
  379. 379
  380. 380 return enable_value;
  381. 381 }
  382. 382
  383. 383 /**
  384. 384 * @brief Enables or disables a feature in the APDS-9960
  385. 385 *
  386. 386 #define POWER 0
  387. 387 #define AMBIENT_LIGHT 1
  388. 388 #define PROXIMITY 2
  389. 389 #define WAIT 3
  390. 390 #define AMBIENT_LIGHT_INT 4
  391. 391 #define PROXIMITY_INT 5
  392. 392 #define GESTURE 6
  393. 393 #define ALL 7
  394. 394 * @param[in] mode which feature to enable
  395. 395 * @param[in] enable ON (1) or OFF (0)
  396. 396 * @return True if operation success. False otherwise.
  397. 397 mode = ALL 7 enable = OFF 0
  398. 398 */
  399. 399 int8_t set_mode(int8_t mode, uint8_t enable)
  400. 400 {
  401. 401 uint8_t reg_val;
  402. 402
  403. 403 /* Read current ENABLE register */
  404. 404 reg_val = get_mode();
  405. 405 mprintf("First_setMode_regval = %.2x\n",reg_val);//打印读取到的使能寄存器的值 0x80 = 0x4d
  406. 406 if( reg_val == ERROR ) {//如果读取到的值为0xFF,则错误
  407. 407 return RETURN_ERR;
  408. 408 }
  409. 409
  410. 410 /* Change bit(s) in ENABLE register */
  411. 411 enable = enable & 0x01;
  412. 412 if((mode >= 0) && (mode <= 6)) //使能或失能某个位
  413. 413 {
  414. 414 if(enable) //使能
  415. 415 {
  416. 416 reg_val |= (1 << mode);
  417. 417 }
  418. 418 else //失能
  419. 419 {
  420. 420 reg_val &= ~(1 << mode);
  421. 421 }
  422. 422 }
  423. 423 else if( mode == ALL ) //使能全部
  424. 424 {
  425. 425 if (enable)
  426. 426 {
  427. 427 reg_val = 0x7F;//0x80=0x7F 全部使能
  428. 428 }
  429. 429 else //全部使能
  430. 430 {
  431. 431 reg_val = 0x00;//0x80=0x00
  432. 432 mprintf("0x80 = 0x00 all disable\n");
  433. 433 }
  434. 434 }
  435. 435
  436. 436 mprintf("Last_setMode_regval = %.2x\n",reg_val);//打印读取到的使能寄存器的值 0x80 = 0x4d
  437. 437 /* Write value back to ENABLE register */
  438. 438 if( !wire_write_data_byte(APDS9960_ENABLE, reg_val) )
  439. 439 {
  440. 440 return RETURN_ERR;
  441. 441 }
  442. 442
  443. 443 return RETURN_OK;
  444. 444 }
  445. 445
  446. 446 /**
  447. 447 * @brief Determines if there is a gesture available for reading
  448. 448 * 确定是否有用于阅读的手势
  449. 449 * @return True if gesture available. False otherwise.
  450. 450 */
  451. 451 int8_t is_gesture_available(void)
  452. 452 {
  453. 453 uint8_t val;
  454. 454
  455. 455 /*读0xAF*/
  456. 456 if( !wire_read_data_byte(APDS9960_GSTATUS, &val) )
  457. 457 {
  458. 458 return ERROR;
  459. 459 }
  460. 460 mprintf("AF_val = 0x%.2x\n",val);
  461. 461 /* Shift and mask out GVALID bit */
  462. 462 val &= APDS9960_GVALID;//判断0xAF最低位GVALID是否为1
  463. 463
  464. 464 /* Return RETURN_OK/RETURN_ERR based on GVALID bit */
  465. 465 if( val == 1)
  466. 466 {
  467. 467 return RETURN_OK;
  468. 468 }
  469. 469 else
  470. 470 {
  471. 471 return RETURN_ERR;
  472. 472 }
  473. 473 }
  474. 474
  475. 475 /**
  476. 476 * 处理原始手势数据确定滑动方向
  477. 477 *
  478. 478 * @return True if near or far state seen. False otherwise.
  479. 479 */
  480. 480 int8_t process_gesture_data(void)
  481. 481 {
  482. 482 uint8_t u_first = 0;
  483. 483 uint8_t d_first = 0;
  484. 484 uint8_t l_first = 0;
  485. 485 uint8_t r_first = 0;
  486. 486 uint8_t u_last = 0;
  487. 487 uint8_t d_last = 0;
  488. 488 uint8_t l_last = 0;
  489. 489 uint8_t r_last = 0;
  490. 490 int ud_ratio_first;
  491. 491 int lr_ratio_first;
  492. 492 int ud_ratio_last;
  493. 493 int lr_ratio_last;
  494. 494 int ud_delta;
  495. 495 int lr_delta;
  496. 496 int i;
  497. 497
  498. 498 /* If we have less than 4 total gestures, that\'s not enough */
  499. 499 if( gesture_data_.total_gestures <= 4 )
  500. 500 {
  501. 501 return RETURN_ERR;
  502. 502 }
  503. 503
  504. 504 /* Check to make sure our data isn\'t out of bounds */
  505. 505 if( (gesture_data_.total_gestures <= 32) && \
  506. 506 (gesture_data_.total_gestures > 0) )
  507. 507 {
  508. 508
  509. 509 /* Find the first value in U/D/L/R above the threshold */
  510. 510 for( i = 0; i < gesture_data_.total_gestures; i++ )
  511. 511 {
  512. 512 if( (gesture_data_.u_data[i] > GESTURE_THRESHOLD_OUT) &&
  513. 513 (gesture_data_.d_data[i] > GESTURE_THRESHOLD_OUT) &&
  514. 514 (gesture_data_.l_data[i] > GESTURE_THRESHOLD_OUT) &&
  515. 515 (gesture_data_.r_data[i] > GESTURE_THRESHOLD_OUT) )
  516. 516 {
  517. 517
  518. 518 u_first = gesture_data_.u_data[i];
  519. 519 d_first = gesture_data_.d_data[i];
  520. 520 l_first = gesture_data_.l_data[i];
  521. 521 r_first = gesture_data_.r_data[i];
  522. 522 #if DEBUG
  523. 523 mprintf("*********************************************\n");
  524. 524 mprintf("Finding first:\n");
  525. 525 mprintf("u_first = %d\n",u_first);
  526. 526 mprintf("d_first = %d\n",d_first);
  527. 527 mprintf("l_first = %d\n",l_first);
  528. 528 mprintf("r_first = %d\n",r_first);
  529. 529 mprintf("First i = %d\n",i);
  530. 530 mprintf("*********************************************\n");
  531. 531 #endif
  532. 532 break;
  533. 533 }
  534. 534 }
  535. 535 /* If one of the _first values is 0, then there is no good data */
  536. 536 if( (u_first == 0) || (d_first == 0) || \
  537. 537 (l_first == 0) || (r_first == 0) )
  538. 538 {
  539. 539
  540. 540 return RETURN_ERR;
  541. 541 }
  542. 542 /* Find the last value in U/D/L/R above the threshold */
  543. 543 for( i = gesture_data_.total_gestures - 1; i >= 0; i-- )
  544. 544 {
  545. 545 if( (gesture_data_.u_data[i] > GESTURE_THRESHOLD_OUT) &&
  546. 546 (gesture_data_.d_data[i] > GESTURE_THRESHOLD_OUT) &&
  547. 547 (gesture_data_.l_data[i] > GESTURE_THRESHOLD_OUT) &&
  548. 548 (gesture_data_.r_data[i] > GESTURE_THRESHOLD_OUT) )
  549. 549 {
  550. 550
  551. 551 u_last = gesture_data_.u_data[i];
  552. 552 d_last = gesture_data_.d_data[i];
  553. 553 l_last = gesture_data_.l_data[i];
  554. 554 r_last = gesture_data_.r_data[i];
  555. 555 #if DEBUG
  556. 556 mprintf("*********************************************\n");
  557. 557 mprintf("Finding last:\n");
  558. 558 mprintf("u_last = %d\n",u_last);
  559. 559 mprintf("d_last = %d\n",d_last);
  560. 560 mprintf("l_last = %d\n",l_last);
  561. 561 mprintf("r_last = %d\n",r_last);
  562. 562 mprintf("Last i = %d\n",i);
  563. 563 mprintf("*********************************************\n");
  564. 564 #endif
  565. 565 break;
  566. 566 }
  567. 567 }
  568. 568 }
  569. 569
  570. 570 /* Calculate the first vs. last ratio of up/down and left/right */
  571. 571 ud_ratio_first = ((u_first - d_first) * 100) / (u_first + d_first);
  572. 572 lr_ratio_first = ((l_first - r_first) * 100) / (l_first + r_first);
  573. 573 ud_ratio_last = ((u_last - d_last) * 100) / (u_last + d_last);
  574. 574 lr_ratio_last = ((l_last - r_last) * 100) / (l_last + r_last);
  575. 575
  576. 576 #if DEBUG
  577. 577 mprintf("===============================================\n");
  578. 578 mprintf("first vs last ratio :\n");
  579. 579 mprintf("ud_ratio_first = %d\n",ud_ratio_first);
  580. 580 mprintf("lr_ratio_first = %d\n",lr_ratio_first);
  581. 581 mprintf("ud_ratio_last = %d\n",ud_ratio_last);
  582. 582 mprintf("lr_ratio_last = %d\n",lr_ratio_last);
  583. 583 mprintf("===============================================\n");
  584. 584 #endif
  585. 585 /* Determine the difference between the first and last ratios */
  586. 586 ud_delta = ud_ratio_last - ud_ratio_first;
  587. 587 lr_delta = lr_ratio_last - lr_ratio_first;
  588. 588 #if DEBUG
  589. 589
  590. 590 mprintf("===============================================\n");
  591. 591 mprintf("Delta:\n");
  592. 592 mprintf("ud_delta = %d\n",ud_delta);
  593. 593 mprintf("lr_delta = %d\n",lr_delta);
  594. 594 mprintf("===============================================\n");
  595. 595 #endif
  596. 596
  597. 597 /* Accumulate the UD and LR delta values */
  598. 598 gesture_ud_delta_ += ud_delta;
  599. 599 gesture_lr_delta_ += lr_delta;
  600. 600
  601. 601 #if DEBUG
  602. 602 mprintf("===============================================\n");
  603. 603 mprintf("Accumulate Delta:\n");
  604. 604 mprintf("gesture_ud_delta_ = %d\n",gesture_ud_delta_);
  605. 605 mprintf("gesture_lr_delta_ = %d\n",gesture_lr_delta_);
  606. 606 mprintf("===============================================\n");
  607. 607 #endif
  608. 608 /* Determine U/D gesture */
  609. 609 if( gesture_ud_delta_ >= GESTURE_SENSITIVITY_1 ) //50
  610. 610 {
  611. 611 gesture_ud_count_ = 1;//U-->D
  612. 612 mprintf("U--->D\n");
  613. 613 }
  614. 614 else if( gesture_ud_delta_ <= -GESTURE_SENSITIVITY_1 )
  615. 615 {
  616. 616 gesture_ud_count_ = -1;
  617. 617 mprintf("D--->U\n");
  618. 618 }
  619. 619 else
  620. 620 {
  621. 621 gesture_ud_count_ = 0;
  622. 622 }
  623. 623
  624. 624 /* Determine L/R gesture */
  625. 625 if( gesture_lr_delta_ >= GESTURE_SENSITIVITY_1 )
  626. 626 {
  627. 627 gesture_lr_count_ = 1;
  628. 628 mprintf("L--->R\n");
  629. 629 }
  630. 630 else if( gesture_lr_delta_ <= -GESTURE_SENSITIVITY_1 )
  631. 631 {
  632. 632 gesture_lr_count_ = -1;
  633. 633 mprintf("R--->L\n");
  634. 634 }
  635. 635 else
  636. 636 {
  637. 637 gesture_lr_count_ = 0;
  638. 638 }
  639. 639 /* Determine Near/Far gesture */
  640. 640 if( (gesture_ud_count_ == 0) && (gesture_lr_count_ == 0) )
  641. 641 {
  642. 642 if( (abs(ud_delta) < GESTURE_SENSITIVITY_2) && (abs(lr_delta) < GESTURE_SENSITIVITY_2) ) //20
  643. 643 {
  644. 644 if( (ud_delta == 0) && (lr_delta == 0) )
  645. 645 {
  646. 646 gesture_near_count_++;
  647. 647 }
  648. 648 else if( (ud_delta != 0) || (lr_delta != 0) )
  649. 649 {
  650. 650 gesture_far_count_++;
  651. 651 }
  652. 652
  653. 653 if( (gesture_near_count_ >= 10) && (gesture_far_count_ >= 2) )
  654. 654 {
  655. 655 if( (ud_delta == 0) && (lr_delta == 0) )
  656. 656 {
  657. 657 gesture_state_ = NEAR_STATE;
  658. 658 }
  659. 659 else if( (ud_delta != 0) && (lr_delta != 0) )
  660. 660 {
  661. 661 gesture_state_ = FAR_STATE;
  662. 662 }
  663. 663 return RETURN_OK;
  664. 664 }
  665. 665 }
  666. 666 }
  667. 667 else
  668. 668 {
  669. 669 if( (abs((int)ud_delta) < GESTURE_SENSITIVITY_2) && (abs((int)lr_delta) < GESTURE_SENSITIVITY_2) )
  670. 670 {
  671. 671
  672. 672 if( (ud_delta == 0) && (lr_delta == 0) )
  673. 673 {
  674. 674 gesture_near_count_++;
  675. 675 }
  676. 676
  677. 677 if( gesture_near_count_ >= 10 )
  678. 678 {
  679. 679 gesture_ud_count_ = 0;
  680. 680 gesture_lr_count_ = 0;
  681. 681 gesture_ud_delta_ = 0;
  682. 682 gesture_lr_delta_ = 0;
  683. 683 }
  684. 684 }
  685. 685 }
  686. 686 #if DEBUG
  687. 687 mprintf("===============================================\n");
  688. 688 mprintf("UD_CT = %d\n",gesture_ud_count_);
  689. 689 mprintf("LR_CT = %d\n",gesture_lr_count_);
  690. 690 mprintf("NEAR_CT = %d\n",gesture_near_count_);
  691. 691 mprintf("FAR_CT = %d\n",gesture_far_count_);
  692. 692 mprintf("===============================================\n");
  693. 693 #endif
  694. 694 return RETURN_ERR;
  695. 695 }
  696. 696
  697. 697 /**
  698. 698 * 确定滑动方向、远近状态
  699. 699 *
  700. 700 * @return True if near/far event. False otherwise.
  701. 701 */
  702. 702 int8_t decode_gesture(void)
  703. 703 {
  704. 704 /* Return if near or far event is detected */
  705. 705 if( gesture_state_ == NEAR_STATE ) //手势状态 = 进距离
  706. 706 {
  707. 707 gesture_motion_ = DIR_NEAR;
  708. 708 return RETURN_OK;
  709. 709 }
  710. 710 else if ( gesture_state_ == FAR_STATE ) //手势状态 = 远距离
  711. 711 {
  712. 712 gesture_motion_ = DIR_FAR;
  713. 713 return RETURN_OK;
  714. 714 }
  715. 715
  716. 716 /* Determine swipe direction 确定滑动方向 */
  717. 717 if( (gesture_ud_count_ == -1) && (gesture_lr_count_ == 0) )
  718. 718 {
  719. 719 gesture_motion_ = DIR_UP;
  720. 720 }
  721. 721 else if( (gesture_ud_count_ == 1) && (gesture_lr_count_ == 0) )
  722. 722 {
  723. 723 gesture_motion_ = DIR_DOWN;
  724. 724 }
  725. 725 else if( (gesture_ud_count_ == 0) && (gesture_lr_count_ == 1) )
  726. 726 {
  727. 727 gesture_motion_ = DIR_RIGHT;
  728. 728 }
  729. 729 else if( (gesture_ud_count_ == 0) && (gesture_lr_count_ == -1) )
  730. 730 {
  731. 731 gesture_motion_ = DIR_LEFT;
  732. 732 }
  733. 733 else if( (gesture_ud_count_ == -1) && (gesture_lr_count_ == 1) )
  734. 734 {
  735. 735 if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) )
  736. 736 {
  737. 737 gesture_motion_ = DIR_UP;
  738. 738 }
  739. 739 else
  740. 740 {
  741. 741 gesture_motion_ = DIR_RIGHT;
  742. 742 }
  743. 743 }
  744. 744 else if( (gesture_ud_count_ == 1) && (gesture_lr_count_ == -1) )
  745. 745 {
  746. 746 if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) )
  747. 747 {
  748. 748 gesture_motion_ = DIR_DOWN;
  749. 749 }
  750. 750 else
  751. 751 {
  752. 752 gesture_motion_ = DIR_LEFT;
  753. 753 }
  754. 754 }
  755. 755 else if( (gesture_ud_count_ == -1) && (gesture_lr_count_ == -1) )
  756. 756 {
  757. 757 if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) )
  758. 758 {
  759. 759 gesture_motion_ = DIR_UP;
  760. 760 }
  761. 761 else
  762. 762 {
  763. 763 gesture_motion_ = DIR_LEFT;
  764. 764 }
  765. 765 }
  766. 766 else if( (gesture_ud_count_ == 1) && (gesture_lr_count_ == 1) )
  767. 767 {
  768. 768 if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) )
  769. 769 {
  770. 770 gesture_motion_ = DIR_DOWN;
  771. 771 }
  772. 772 else
  773. 773 {
  774. 774 gesture_motion_ = DIR_RIGHT;
  775. 775 }
  776. 776 }
  777. 777 else
  778. 778 {
  779. 779 return RETURN_ERR;
  780. 780 }
  781. 781 return RETURN_OK;
  782. 782 }
  783. 783
  784. 784 /*******************************************************************************
  785. 785 * High-level gesture controls
  786. 786 ******************************************************************************/
  787. 787
  788. 788 /**
  789. 789 * @brief Resets all the parameters in the gesture data member
  790. 790 */
  791. 791 void reset_gesture_parameters(void)
  792. 792 {
  793. 793 gesture_data_.index = 0;
  794. 794 gesture_data_.total_gestures = 0;
  795. 795
  796. 796 gesture_ud_delta_ = 0;
  797. 797 gesture_lr_delta_ = 0;
  798. 798
  799. 799 gesture_ud_count_ = 0;
  800. 800 gesture_lr_count_ = 0;
  801. 801
  802. 802 gesture_near_count_ = 0;
  803. 803 gesture_far_count_ = 0;
  804. 804
  805. 805 gesture_state_ = 0;
  806. 806 gesture_motion_ = DIR_NONE;
  807. 807 }
  808. 808
  809. 809 /**
  810. 810 * @brief Processes a gesture event and returns best guessed gesture
  811. 811 * 处理一个手势事件并返回最佳猜测手势
  812. 812 * @return Number corresponding to gesture. -1 on error.
  813. 813 */
  814. 814 int read_gesture(void)
  815. 815 {
  816. 816 uint8_t fifo_level = 0;
  817. 817 int8_t bytes_read = 0;
  818. 818 uint8_t fifo_data[128];
  819. 819 uint8_t gstatus;
  820. 820 int motion;
  821. 821 int i;
  822. 822
  823. 823 /* Get the contents of the STATUS register. Is data still valid? */
  824. 824 if( !wire_read_data_byte(APDS9960_GSTATUS, &gstatus) )
  825. 825 {
  826. 826 return ERROR;
  827. 827 }
  828. 828 /* Make sure that power and gesture is on and data is valid */
  829. 829 if(!is_gesture_available()||!(get_mode() & 0x41) )
  830. 830 {
  831. 831 return DIR_NONE;
  832. 832 }
  833. 833
  834. 834 /* Keep looping as long as gesture data is valid */
  835. 835 while(1)
  836. 836 {
  837. 837 /* Wait some time to collect next batch of FIFO data */
  838. 838 delay_ms(FIFO_PAUSE_TIME);
  839. 839
  840. 840 /* Get the contents of the STATUS register. Is data still valid? */
  841. 841 if( !wire_read_data_byte(APDS9960_GSTATUS, &gstatus) )
  842. 842 {
  843. 843 return ERROR;
  844. 844 }
  845. 845 mprintf("gstatus = %.2x\n",gstatus);
  846. 846
  847. 847 /* If we have valid data, read in FIFO */
  848. 848 if((gstatus & APDS9960_GVALID) == APDS9960_GVALID)
  849. 849 {
  850. 850
  851. 851 /* Read the current FIFO level */
  852. 852 if( !wire_read_data_byte(APDS9960_GFLVL, &fifo_level) )
  853. 853 {
  854. 854 return ERROR;
  855. 855 }
  856. 856 /* If there\'s stuff in the FIFO, read it into our data block */
  857. 857 if( fifo_level > 0)
  858. 858 {
  859. 859 bytes_read = wire_read_data_block( APDS9960_GFIFO_U,
  860. 860 (uint8_t*)fifo_data,
  861. 861 (fifo_level * 4) );
  862. 862
  863. 863 #if DEBUG
  864. 864 for(i = 0;i < fifo_level * 4;i = i + 4)
  865. 865 {
  866. 866 mprintf("=========================\n");
  867. 867 mprintf("%d fifo_level data\n",i/4);
  868. 868 mprintf("U = 0x%.2x ",fifo_data[i+0]);
  869. 869 mprintf("D = 0x%.2x ",fifo_data[i+1]);
  870. 870 mprintf("L = 0x%.2x ",fifo_data[i+2]);
  871. 871 mprintf("R = 0x%.2x \n",fifo_data[i+3]);
  872. 872 mprintf("=========================\n");
  873. 873 }
  874. 874 mprintf("fifo_level = %d\n",fifo_level);
  875. 875 mprintf("bytes_read = %d\n",bytes_read);
  876. 876 #endif
  877. 877 if(bytes_read == -1)
  878. 878 {
  879. 879 return ERROR;
  880. 880 }
  881. 881
  882. 882 /* If at least 1 set of data, sort the data into U/D/L/R */
  883. 883 if( bytes_read >= 4 )
  884. 884 {
  885. 885 for( i = 0; i < bytes_read; i += 4 )
  886. 886 {
  887. 887 gesture_data_.u_data[gesture_data_.index] = \
  888. 888 fifo_data[i + 0];
  889. 889 gesture_data_.d_data[gesture_data_.index] = \
  890. 890 fifo_data[i + 1];
  891. 891 gesture_data_.l_data[gesture_data_.index] = \
  892. 892 fifo_data[i + 2];
  893. 893 gesture_data_.r_data[gesture_data_.index] = \
  894. 894 fifo_data[i + 3];
  895. 895 gesture_data_.index++;
  896. 896 gesture_data_.total_gestures++;
  897. 897 }
  898. 898 mprintf("gesture_data_.index = %d\n",gesture_data_.index);
  899. 899 mprintf("gesture_data_.total_gestures = %d\n",gesture_data_.total_gestures);
  900. 900
  901. 901 /* Filter and process gesture data. Decode near/far state */
  902. 902 if(process_gesture_data() )
  903. 903 {
  904. 904 if(decode_gesture() )
  905. 905 {
  906. 906 mprintf("gesture_motion_ = %d\n",gesture_motion_);
  907. 907 }
  908. 908 }
  909. 909
  910. 910 /* Reset data */
  911. 911 gesture_data_.index = 0;
  912. 912 gesture_data_.total_gestures = 0;
  913. 913 }
  914. 914 }
  915. 915 }
  916. 916 else
  917. 917 {
  918. 918 /* Determine best guessed gesture and clean up */
  919. 919 delay_ms(FIFO_PAUSE_TIME);
  920. 920 decode_gesture();
  921. 921 motion = gesture_motion_;
  922. 922 reset_gesture_parameters();
  923. 923 return motion;
  924. 924 }
  925. 925 }
  926. 926 }
  927. 927
  928. 928 /**
  929. 929 * Turn the APDS-9960 on
  930. 930 *
  931. 931 * @return True if operation successful. False otherwise.
  932. 932 */
  933. 933 int8_t enable_power(void)
  934. 934 {
  935. 935 if( !set_mode(POWER, 1) )
  936. 936 {
  937. 937 return RETURN_ERR;
  938. 938 }
  939. 939
  940. 940 return RETURN_OK;
  941. 941 }
  942. 942
  943. 943 /**
  944. 944 * Turn the APDS-9960 off
  945. 945 *
  946. 946 * @return True if operation successful. False otherwise.
  947. 947 */
  948. 948 int8_t disable_power(void)
  949. 949 {
  950. 950 if( !set_mode(POWER, 0) )
  951. 951 {
  952. 952 return RETURN_ERR;
  953. 953 }
  954. 954
  955. 955 return RETURN_OK;
  956. 956 }
  957. 957
  958. 958 /**
  959. 959 * @brief Sets the LED current boost value
  960. 960 * 设置LED当前的升压值
  961. 961 * Value Boost Current
  962. 962 * 0 100%
  963. 963 * 1 150%
  964. 964 * 2 200%
  965. 965 * 3 300%
  966. 966 *
  967. 967 * @param[in] drive the value (0-3) for current boost (100-300%)
  968. 968 * @return True if operation successful. False otherwise.
  969. 969 */
  970. 970 int8_t set_led_boost(uint8_t boost)
  971. 971 {
  972. 972 uint8_t val;
  973. 973
  974. 974 /* Read value from CONFIG2 register */
  975. 975 if( !wire_read_data_byte(APDS9960_CONFIG2, &val) ) {
  976. 976 return RETURN_ERR;
  977. 977 }
  978. 978
  979. 979 /* Set bits in register to given value */
  980. 980 boost &= 0x03;
  981. 981 boost = boost << 4;
  982. 982 val &= 0xCF;
  983. 983 val |= boost;
  984. 984
  985. 985 /* Write register value back into CONFIG2 register */
  986. 986 if( !wire_write_data_byte(APDS9960_CONFIG2, val) ) {
  987. 987 return RETURN_ERR;
  988. 988 }
  989. 989
  990. 990 return RETURN_OK;
  991. 991 }
  992. 992
  993. 993
  994. 994
  995. 995
  996. 996
  997. 997 /***********************************************************************************
  998. 998 设置手势接近进入阀值
  999. 999 APDS9960_GPENTH = threshold = 40
  1000. 1000 0xA0 = 40
  1001. 1001 0xA0的bit4必须设为0
  1002. 1002 手势接近阀值会与接近数据PDATA进行比较并决定是否进入手势状态机
  1003. 1003 ***********************************************************************************/
  1004. 1004 int8_t set_gesture_enter_thresh(uint8_t threshold)
  1005. 1005 {
  1006. 1006 if( !wire_write_data_byte(APDS9960_GPENTH, threshold) )
  1007. 1007 {
  1008. 1008 return RETURN_ERR;
  1009. 1009 }
  1010. 1010
  1011. 1011 return RETURN_OK;
  1012. 1012 }
  1013. 1013
  1014. 1014
  1015. 1015 /***********************************************************************************
  1016. 1016 设置手势接近退出阀值
  1017. 1017 APDS9960_GEXTH = threshold = 30
  1018. 1018 0xA1 = 30
  1019. 1019 此寄存器设置阀值决定手势结束,同时退出手势状态机.
  1020. 1020 设置GTHR_OUT为0x00会防止手势退出直到GMODE被设为0
  1021. 1021 ***********************************************************************************/
  1022. 1022 int8_t set_gesture_exit_thresh(uint8_t threshold)
  1023. 1023 {
  1024. 1024 if( !wire_write_data_byte(APDS9960_GEXTH, threshold) ) {
  1025. 1025 return RETURN_ERR;
  1026. 1026 }
  1027. 1027
  1028. 1028 return RETURN_OK;
  1029. 1029 }
  1030. 1030
  1031. 1031
  1032. 1032
  1033. 1033 /**
  1034. 1034 * @brief Sets the gain of the photodiode during gesture mode
  1035. 1035 gain = 2
  1036. 1036 保留 7 写0
  1037. 1037 GGAIN 6:5 手势增益控制,设定一个增益手势接收在手势模式下
  1038. 1038 0 1x
  1039. 1039 1 2x
  1040. 1040 2 4x
  1041. 1041 3 8x
  1042. 1042 GLDRIVE 4:3 手势LED驱动强度
  1043. 1043 0 100ma
  1044. 1044 1 50ma
  1045. 1045 2 25ma
  1046. 1046 3 12.5ma
  1047. 1047 GWTIME 2:0 手势等待时间
  1048. 1048 0 0ms
  1049. 1049 1 2.8ms
  1050. 1050 2 5.6ms
  1051. 1051 3 8.4ms
  1052. 1052 4 14.0ms
  1053. 1053 5 22.4ms
  1054. 1054 6 30.8ms
  1055. 1055 7 39.2ms
  1056. 1056 */
  1057. 1057 int8_t set_gesture_gain(uint8_t gain)
  1058. 1058 {
  1059. 1059 uint8_t val;
  1060. 1060
  1061. 1061 /* Read value from GCONF2 register */
  1062. 1062 if( !wire_read_data_byte(APDS9960_GCONF2, &val) )
  1063. 1063 {
  1064. 1064 return RETURN_ERR;
  1065. 1065 }
  1066. 1066 /* Set bits in register to given value */
  1067. 1067 gain &= 0x03;//取gain最低两位
  1068. 1068 gain = gain << 5;//移动到6:5
  1069. 1069 val &= 0x9F;//将6:5位清零
  1070. 1070 val |= gain;//将gain的6:5位赋值给val
  1071. 1071 /* 然后在将val写入配置寄存器2设置增益(即用gain给其设置增益)*/
  1072. 1072 if( !wire_write_data_byte(APDS9960_GCONF2, val) )
  1073. 1073 {
  1074. 1074 return RETURN_ERR;
  1075. 1075 }
  1076. 1076
  1077. 1077 return RETURN_OK;
  1078. 1078 }
  1079. 1079
  1080. 1080
  1081. 1081
  1082. 1082 /**
  1083. 1083 * @brief Sets the LED drive current during gesture mode
  1084. 1084 *
  1085. 1085 * Value LED Current
  1086. 1086 * 0 100 mA
  1087. 1087 * 1 50 mA
  1088. 1088 * 2 25 mA
  1089. 1089 * 3 12.5 mA
  1090. 1090 *
  1091. 1091 * @param[in] drive the value for the LED drive current
  1092. 1092 * @return True if operation successful. False otherwise.
  1093. 1093 */
  1094. 1094 int8_t set_gesture_led_drive(uint8_t drive)
  1095. 1095 {
  1096. 1096 uint8_t val;
  1097. 1097
  1098. 1098 /* Read value from GCONF2 register */
  1099. 1099 if( !wire_read_data_byte(APDS9960_GCONF2, &val) )
  1100. 1100 {
  1101. 1101 return RETURN_ERR;
  1102. 1102 }
  1103. 1103 /* Set bits in register to given value */
  1104. 1104 drive &= 0x03;
  1105. 1105 drive = drive << 3;//bit 4:3
  1106. 1106 val &= 0xE7;
  1107. 1107 val |= drive;
  1108. 1108 /* Write register value back into GCONF2 register */
  1109. 1109 if( !wire_write_data_byte(APDS9960_GCONF2, val) )
  1110. 1110 {
  1111. 1111 return RETURN_ERR;
  1112. 1112 }
  1113. 1113
  1114. 1114 return RETURN_OK;
  1115. 1115 }
  1116. 1116
  1117. 1117
  1118. 1118
  1119. 1119 /**
  1120. 1120 * @brief Sets the time in low power mode between gesture detections
  1121. 1121 *
  1122. 1122 * Value Wait time
  1123. 1123 * 0 0 ms
  1124. 1124 * 1 2.8 ms
  1125. 1125 * 2 5.6 ms
  1126. 1126 * 3 8.4 ms
  1127. 1127 * 4 14.0 ms
  1128. 1128 * 5 22.4 ms
  1129. 1129 * 6 30.8 ms
  1130. 1130 * 7 39.2 ms
  1131. 1131 *
  1132. 1132 * @param[in] the value for the wait time
  1133. 1133 * @return True if operation successful. False otherwise.
  1134. 1134 */
  1135. 1135 int8_t set_gesture_wait_time(uint8_t time)
  1136. 1136 {
  1137. 1137 uint8_t val;
  1138. 1138
  1139. 1139 /* Read value from GCONF2 register */
  1140. 1140 if( !wire_read_data_byte(APDS9960_GCONF2, &val))
  1141. 1141 {
  1142. 1142 return RETURN_ERR;
  1143. 1143 }
  1144. 1144 mprintf("First_WaitTime__0xA3 = %.2x\n",val);
  1145. 1145
  1146. 1146 /* Set bits in register to given value */
  1147. 1147 time &= 0x07;
  1148. 1148 val &= 0xF8;
  1149. 1149 val |= time;
  1150. 1150
  1151. 1151 /* Write register value back into GCONF2 register */
  1152. 1152 if( !wire_write_data_byte(APDS9960_GCONF2, val) )
  1153. 1153 {
  1154. 1154 return RETURN_ERR;
  1155. 1155 }
  1156. 1156 mprintf("Last_WaitTime__0xA3 = %.2x\n",val);
  1157. 1157 return RETURN_OK;
  1158. 1158 }
  1159. 1159
  1160. 1160
  1161. 1161
  1162. 1162
  1163. 1163 /**
  1164. 1164 * @brief Turns gesture-related interrupts on or off
  1165. 1165 *
  1166. 1166 * @param[in] enable 1 to enable interrupts, 0 to turn them off
  1167. 1167 * @return True if operation successful. False otherwise.
  1168. 1168 */
  1169. 1169 int8_t set_gesture_int_enable(uint8_t enable)
  1170. 1170 {
  1171. 1171 uint8_t val;
  1172. 1172
  1173. 1173 /* Read value from GCONF4 register */
  1174. 1174 if( !wire_read_data_byte(APDS9960_GCONF4, &val) )
  1175. 1175 {
  1176. 1176 return RETURN_ERR;
  1177. 1177 }
  1178. 1178 mprintf("First_GIEN__0xAB = %.2x\n",val);
  1179. 1179 /* Set bits in register to given value */
  1180. 1180 enable &= 0x01;
  1181. 1181 enable = enable << 1;
  1182. 1182 val &= 0xFD;
  1183. 1183 val |= enable;
  1184. 1184 mprintf("Last_GIEN__0xAB = %.2x\n",val);
  1185. 1185 /* Write register value back into GCONF4 register */
  1186. 1186 if( !wire_write_data_byte(APDS9960_GCONF4, val) )
  1187. 1187 {
  1188. 1188 return RETURN_ERR;
  1189. 1189 }
  1190. 1190
  1191. 1191 return RETURN_OK;
  1192. 1192 }
  1193. 1193
  1194. 1194
  1195. 1195
  1196. 1196
  1197. 1197 /**
  1198. 1198 * @brief Tells the state machine to either enter or exit gesture state machine
  1199. 1199 *
  1200. 1200 * @param[in] mode 1 to enter gesture state machine, 0 to exit.
  1201. 1201 * @return True if operation successful. False otherwise.
  1202. 1202 */
  1203. 1203 int8_t set_gesture_mode(uint8_t mode)
  1204. 1204 {
  1205. 1205 uint8_t val;
  1206. 1206
  1207. 1207 /* Read value from GCONF4 register */
  1208. 1208 if( !wire_read_data_byte(APDS9960_GCONF4, &val) )
  1209. 1209 {
  1210. 1210 return RETURN_ERR;
  1211. 1211 }
  1212. 1212
  1213. 1213 /* Set bits in register to given value */
  1214. 1214 mode &= 0x01;
  1215. 1215 val &= 0xFE;
  1216. 1216 val |= mode;
  1217. 1217
  1218. 1218 /* Write register value back into GCONF4 register */
  1219. 1219 if( !wire_write_data_byte(APDS9960_GCONF4, val) ) {
  1220. 1220 return RETURN_ERR;
  1221. 1221 }
  1222. 1222
  1223. 1223 return RETURN_OK;
  1224. 1224 }
  1225. 1225
  1226. 1226 /**
  1227. 1227 * @brief Configures I2C communications and initializes registers to defaults
  1228. 1228 *
  1229. 1229 * @return True if initialized successfully. False otherwise.
  1230. 1230 */
  1231. 1231 int8_t spark_fun_apds9960_init(void)
  1232. 1232 {
  1233. 1233 uint8_t id,pid;
  1234. 1234
  1235. 1235 /* 读取器件ID 0x92 = 0xAB */
  1236. 1236 if( !wire_read_data_byte(APDS9960_ID,&pid) )
  1237. 1237 {
  1238. 1238 return RETURN_ERR;
  1239. 1239 }
  1240. 1240 id = pid;
  1241. 1241 mprintf("ID:0x%x\n",id);
  1242. 1242 if( !((id == APDS9960_ID_1 || id == APDS9960_ID_2)) )
  1243. 1243 {
  1244. 1244 return RETURN_ERR;
  1245. 1245 }
  1246. 1246 /* 失能失能寄存器0x80 = 0x00 */
  1247. 1247 if( !set_mode(ALL, OFF) ) //(7,0)
  1248. 1248 {
  1249. 1249 return RETURN_ERR;
  1250. 1250 }
  1251. 1251 //设置手势接近进入(手势状态机)阀值为0xA0 = 40
  1252. 1252 /* 设置手势传感器寄存器默认值 */
  1253. 1253 if( !set_gesture_enter_thresh(DEFAULT_GPENTH) )
  1254. 1254 {
  1255. 1255 return RETURN_ERR;
  1256. 1256 }
  1257. 1257 //设置手势接近退出(手势状态机)阀值为0xA1 = 30
  1258. 1258 if( !set_gesture_exit_thresh(DEFAULT_GEXTH) )
  1259. 1259 {
  1260. 1260 return RETURN_ERR;
  1261. 1261 }
  1262. 1262 //设置配置寄存器1 0xA2 = 0x40
  1263. 1263 //1.在4个数据集被添加到FIFO里后产生中断
  1264. 1264 //2.All UDLR 探测数据被包含到集合中
  1265. 1265 //3.手势退出持久性.当连续的手势结束发生称为比GEXPERS大于或等于的值时,
  1266. 1266 // 手势状态机退出(第1个手势结束发生导致手势状态机退出)
  1267. 1267 if( !wire_write_data_byte(APDS9960_GCONF1, DEFAULT_GCONF1) )
  1268. 1268 {
  1269. 1269 return RETURN_ERR;
  1270. 1270 }
  1271. 1271 //设置配置寄存器2 0xA3 的 bit 6:5 = 10 4x增益
  1272. 1272 if( !set_gesture_gain(DEFAULT_GGAIN) )
  1273. 1273 {
  1274. 1274 return RETURN_ERR;
  1275. 1275 }
  1276. 1276 //设置配置寄存器2 0xA3 的 bit 4:3 = 00 100ma
  1277. 1277 if( !set_gesture_led_drive(DEFAULT_GLDRIVE) )
  1278. 1278 {
  1279. 1279 return RETURN_ERR;
  1280. 1280 }
  1281. 1281 //设定配置寄存器2 0xA3 的 bit 2:0=001 2.8ms
  1282. 1282 if( !set_gesture_wait_time(DEFAULT_GWTIME) )
  1283. 1283 {
  1284. 1284 return RETURN_ERR;
  1285. 1285 }
  1286. 1286 //设置手势UP偏移寄存器 0xA4 = 0 没有偏移
  1287. 1287 if( !wire_write_data_byte(APDS9960_GOFFSET_U, DEFAULT_GOFFSET) )
  1288. 1288 {
  1289. 1289 return RETURN_ERR;
  1290. 1290 }
  1291. 1291 //设置手势DOWN偏移寄存器 0xA5 = 0 没有偏移
  1292. 1292 if( !wire_write_data_byte(APDS9960_GOFFSET_D, DEFAULT_GOFFSET) )
  1293. 1293 {
  1294. 1294 return RETURN_ERR;
  1295. 1295 }
  1296. 1296 //设置手势LEFT偏移寄存器 0xA7 = 0 没有偏移
  1297. 1297 if( !wire_write_data_byte(APDS9960_GOFFSET_L, DEFAULT_GOFFSET) )
  1298. 1298 {
  1299. 1299 return RETURN_ERR;
  1300. 1300 }
  1301. 1301 //设置手势RIGHT偏移寄存器 0xA9 = 0 没有偏移
  1302. 1302 if( !wire_write_data_byte(APDS9960_GOFFSET_R, DEFAULT_GOFFSET) )
  1303. 1303 {
  1304. 1304 return RETURN_ERR;
  1305. 1305 }
  1306. 1306 //设置收势脉冲数和脉宽寄存器0xA6 = 0xC9 32us, 10 pulses
  1307. 1307 if( !wire_write_data_byte(APDS9960_GPULSE, DEFAULT_GPULSE) )
  1308. 1308 {
  1309. 1309 return RETURN_ERR;
  1310. 1310 }
  1311. 1311 //设置配置寄存器3 0xAA 的bit 1:0 = 00 所有光电二极管在手势期间均有效
  1312. 1312 if( !wire_write_data_byte(APDS9960_GCONF3, DEFAULT_GCONF3) )
  1313. 1313 {
  1314. 1314 return RETURN_ERR;
  1315. 1315 }
  1316. 1316 //设置配置寄存器4 0xAB 的bit1 = 0 关闭手势中断 GIEN=0
  1317. 1317 if( !set_gesture_int_enable(DEFAULT_GIEN) )
  1318. 1318 {
  1319. 1319 return RETURN_ERR;
  1320. 1320 }
  1321. 1321 return RETURN_OK;
  1322. 1322 }
  1323. 1323
  1324. 1324 /**
  1325. 1325 * @brief Starts the gesture recognition engine on the APDS-9960
  1326. 1326 * 在ap9960上启动手势识别引擎
  1327. 1327 * @param[in] interrupts RETURN_OK to enable hardware external interrupt on gesture
  1328. 1328 * @return True if engine enabled correctly. False on error.
  1329. 1329 */
  1330. 1330 int8_t enable_gesture_sensor(int8_t interrupts)
  1331. 1331 {
  1332. 1332 /* Enable gesture mode
  1333. 1333 Set ENABLE to 0 (power off)
  1334. 1334 Set WTIME to 0xFF
  1335. 1335 Set AUX to LED_BOOST_300
  1336. 1336 Enable PON, WEN, PEN, GEN in ENABLE
  1337. 1337 */
  1338. 1338 //interrupts = RETURN_OK;
  1339. 1339
  1340. 1340 reset_gesture_parameters();//复位手势变量=0
  1341. 1341
  1342. 1342 //设置等待时间寄存器0x83 = 0xFF (WLONG=1 0.03s) (WLONG=0 2.78ms)
  1343. 1343 if( !wire_write_data_byte(APDS9960_WTIME, 0xFF) ) //
  1344. 1344 {
  1345. 1345 return RETURN_ERR;
  1346. 1346 }
  1347. 1347
  1348. 1348 //设置接近脉冲计数寄存器 0x8E = 0x89 16us, 10 pulses
  1349. 1349 if( !wire_write_data_byte(APDS9960_PPULSE, DEFAULT_GESTURE_PPULSE) )
  1350. 1350 {
  1351. 1351 return RETURN_ERR;
  1352. 1352 }
  1353. 1353
  1354. 1354 //设置配置寄存器2 0x90的bit5:4=11 %300 LED驱动电流
  1355. 1355 if( !set_led_boost(LED_BOOST_300) )
  1356. 1356 {
  1357. 1357 return RETURN_ERR;
  1358. 1358 }
  1359. 1359
  1360. 1360 //是否开启手势中断配置寄存器4 0xAB
  1361. 1361 if( interrupts )
  1362. 1362 {
  1363. 1363 if( !set_gesture_int_enable(1) )
  1364. 1364 {
  1365. 1365 return RETURN_ERR;
  1366. 1366 }
  1367. 1367 }
  1368. 1368 else
  1369. 1369 {
  1370. 1370 if( !set_gesture_int_enable(0) )
  1371. 1371 {
  1372. 1372 return RETURN_ERR;
  1373. 1373 }
  1374. 1374 }
  1375. 1375
  1376. 1376 //设置手势模式GMODE = 1
  1377. 1377 if( !set_gesture_mode(1) )
  1378. 1378 {
  1379. 1379 return RETURN_ERR;
  1380. 1380 }
  1381. 1381
  1382. 1382 //PON = 1 0x80 的 bit0 = 1
  1383. 1383 if( !enable_power() )
  1384. 1384 {
  1385. 1385 return RETURN_ERR;
  1386. 1386 }
  1387. 1387
  1388. 1388 //WEN = 1 0x80 的 bit3 = 1
  1389. 1389 if( !set_mode(WAIT, 1) )
  1390. 1390 {
  1391. 1391 return RETURN_ERR;
  1392. 1392 }
  1393. 1393
  1394. 1394 //PEN=1 0x80 的 bit2 = 1
  1395. 1395 if( !set_mode(PROXIMITY, 1) )
  1396. 1396 {
  1397. 1397 return RETURN_ERR;
  1398. 1398 }
  1399. 1399
  1400. 1400 //PIEN=1 0x80 的 bit6 = 1
  1401. 1401 if( !set_mode(GESTURE, 1) )
  1402. 1402 {
  1403. 1403 return RETURN_ERR;
  1404. 1404 }
  1405. 1405
  1406. 1406 return RETURN_OK;
  1407. 1407 }
  1408. 1408
  1409. 1409 /**
  1410. 1410 * @brief APDS-9960 init
  1411. 1411 *
  1412. 1412 */
  1413. 1413 int32_t apds9960_open(void)
  1414. 1414 {
  1415. 1415 Scu_SetIOReuse(UART1_TX_PAD,FIRST_FUNCTION);
  1416. 1416 Scu_SetDeviceGate((unsigned int)GPIO0,ENABLE);
  1417. 1417 Scu_Setdevice_Reset((unsigned int)GPIO0);
  1418. 1418 Scu_Setdevice_ResetRelease((unsigned int)GPIO0);
  1419. 1419 NVIC_EnableIRQ(GPIO0_IRQn);
  1420. 1420 gpio_irq_trigger_config(GPIO0,gpio_pin_1,both_edges_trigger);
  1421. 1421
  1422. 1422 NVIC_EnableIRQ(IIC1_IRQn);
  1423. 1423 Scu_SetDeviceGate((unsigned int)IIC1,ENABLE);
  1424. 1424 Scu_Setdevice_Reset((unsigned int)IIC1);
  1425. 1425 Scu_Setdevice_ResetRelease((unsigned int)IIC1);
  1426. 1426 Scu_SetIOReuse(I2C1_SCL_PAD,FIRST_FUNCTION);
  1427. 1427 Scu_SetIOReuse(I2C1_SDA_PAD,FIRST_FUNCTION);
  1428. 1428
  1429. 1429 I2C_InitStruct InitStruct = {0};
  1430. 1430 InitStruct.I2C_IO_BASE = (unsigned int)IIC1;
  1431. 1431 InitStruct.I2C_CLOCK_SPEED = 400;
  1432. 1432 InitStruct.I2C_INPUT_CLK = 50000000;
  1433. 1433 InitStruct.TIMEOUT = 0X5FFFFF;
  1434. 1434 i2c_init(IIC1,&InitStruct);
  1435. 1435 /* 模块初始化,官方示例代码引用 */
  1436. 1436 sparkfun_apds9960();
  1437. 1437
  1438. 1438 if(!spark_fun_apds9960_init())
  1439. 1439 {
  1440. 1440 return RETURN_ERR;
  1441. 1441 }
  1442. 1442 if(!enable_gesture_sensor(RETURN_OK))
  1443. 1443 {
  1444. 1444 return RETURN_ERR;
  1445. 1445 }
  1446. 1446
  1447. 1447 return RETURN_OK;
  1448. 1448 }
  1449. 1449
  1450. 1450 /**
  1451. 1451 * @brief 中断回调函数
  1452. 1452 *
  1453. 1453 */
  1454. 1454 void apds9960_callback(void)
  1455. 1455 {
  1456. 1456 sensor_irq_inform(SENSOR_TYPE_GESTURE);
  1457. 1457 }
  1458. 1458
  1459. 1459 /**
  1460. 1460 * @brief 手势解析
  1461. 1461 *
  1462. 1462 */
  1463. 1463 void gesture_manage(void)
  1464. 1464 {
  1465. 1465 if(is_gesture_available())
  1466. 1466 {
  1467. 1467 switch (read_gesture())
  1468. 1468 {
  1469. 1469 case DIR_UP:
  1470. 1470 mprintf("Gesture-UP\n");
  1471. 1471 break;
  1472. 1472 case DIR_DOWN:
  1473. 1473 mprintf("Gesture-DOWN\n");
  1474. 1474 break;
  1475. 1475 case DIR_LEFT:
  1476. 1476 mprintf("Gesture-LEFT\n");
  1477. 1477 break;
  1478. 1478 case DIR_RIGHT:
  1479. 1479 mprintf("Gesture-RIGHT\n");
  1480. 1480 break;
  1481. 1481 case DIR_NEAR:
  1482. 1482 mprintf("Gesture-NEAR\n");
  1483. 1483 break;
  1484. 1484 case DIR_FAR:
  1485. 1485 mprintf("Gesture-FAR\n");
  1486. 1486 break;
  1487. 1487 default:
  1488. 1488 mprintf("Gesture-NONE\n");
  1489. 1489 }
  1490. 1490 }
  1491. 1491 }
  1492. 1492
  1493. 1493 /**
  1494. 1494 * @brief apds9960 ops
  1495. 1495 *
  1496. 1496 */
  1497. 1497 sensor_ops_t apds9960_ops =
  1498. 1498 {
  1499. 1499 apds9960_open,
  1500. 1500 };

APDS_9960.h

 1 /**
 2  * @file APDS_9960.h
 3  * @brief APDS-9960传感器的头文件
 4  * @version 0.1
 5  * @date 2019-07-02
 6  *
 7  * @copyright Copyright (c) 2019  Chipintelli Technology Co., Ltd.
 8  *
 9  */
10 
11 #ifndef __APDS_9960_H__
12 #define __APDS_9960_H__
13 
14 /**
15  * @ingroup third_device_driver
16  * @defgroup APDS9960
17  * @brief APDS9960传感器驱动
18  * @{
19  */
20 
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24 
25 /*-----------------------------------------------------------------------------
26                             include
27 -----------------------------------------------------------------------------*/
28 #include "ci_sensor.h"
29 
30 /*-----------------------------------------------------------------------------
31                             define
32 -----------------------------------------------------------------------------*/
33 
34 /*-----------------------------------------------------------------------------
35                             extern
36 -----------------------------------------------------------------------------*/
37 extern int abs(int __x);
38 extern sensor_ops_t apds9960_ops;
39 /*-----------------------------------------------------------------------------
40                         struct / enum / union
41 -----------------------------------------------------------------------------*/
42 
43 /*-----------------------------------------------------------------------------
44                             global
45 -----------------------------------------------------------------------------*/
46 
47 /*-----------------------------------------------------------------------------
48                         function declare
49 -----------------------------------------------------------------------------*/
50 void gesture_manage(void);
51 
52 #ifdef __cplusplus
53 }
54 #endif
55 
56 /**
57  * @}
58  */
59 
60 #endif
61 
62 /*-----------------------------------------------------------------------------
63                             end of the file
64 -----------------------------------------------------------------------------*/

版权声明:本文为wangyanwen原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/wangyanwen/p/11451573.html