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