传感器简介

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

APDS_9960.c

   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 };

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 -----------------------------------------------------------------------------*/

转载于:https://www.cnblogs.com/wangyanwen/p/11451573.html

APDS-9960手势检测、接近检测、数字环境光感(ALS)和色感(RGBC)传感器驱动(基于传感器管理组件)...相关推荐

  1. 评价对象检测模型的数字度量:F1分数以及它们如何帮助评估模型的表现

    来源:DeepHub IBMA本文约2000字,建议阅读7分钟 本文为你介绍评价对象检测模型的数字度量. 介绍 使用精度和召回率评估目标检测模型可以为模型在不同置信度下的表现提供有价值的见解.类似地, ...

  2. 物联网技术新品之一款可以检测噪声的数字噪声传感器

    物联网技术新品之一款可以检测噪声的数字噪声传感器 之所以称之为数字型噪声传感器是因为输出信号为标准modbus RS485信号输出 ,直接为数字信号,一般软件跟根据协议进行读取数据.   HB-NS5 ...

  3. 基于深度学习的病毒检测技术无需沙箱环境,直接将样本文件转换为二维图片,进而应用改造后的卷积神经网络 Inception V4 进行训练和检测...

    话题 3: 基于深度学习的二进制恶意样本检测 分享主题:全球正在经历一场由科技驱动的数字化转型,传统技术已经不能适应病毒数量飞速增长的发展态势.而基于沙箱的检测方案无法满足 APT 攻击的检测需求,也 ...

  4. 树莓派4B爽上流安装python3的OpenCV(人脸检测识别—门禁“环境搭建篇”)

    树莓派4B安装OpenCV3.4.0人脸检测识别-门禁"环境搭建篇" 前言 一.准备工作 PC端软件 二.搭建树莓派环境 拓展TF内存卡 Tips:换源(python软件源) 修改 ...

  5. 【AI实战】微小目标检测模型MMDet-RFLA--训练环境从零开始搭建

    [AI实战]微小目标检测模型MMDet-RFLA--训练环境搭建 RFLA介绍 环境搭建 安装依赖 参考 RFLA介绍 官方连接 https://github.com/Chasel-Tsui/mmde ...

  6. 静默活体检测+人脸检测+人脸识别结合在NCNN模型下的推理(Windows下的VS环境)

     前言: 涉及到三个模型  静默活体检测模型<2M,人脸检测模型<2M  ,人脸识别<5M(模型大小) 至于NCNN不必多说,全C++实现,不依赖第三方库实现,在第三方移动端CPU运 ...

  7. K210图像检测(1~8)数字卡片识别

    前言   第一次使用该平台.想先找一个简单的识别,来走走流程.就想到了,前几年的送药小车的数字卡片识别.花了半天收集标记图片.在运行时要注意摄像头与数字卡片的高度.不过也有些不足,可能是收集某个数字的 ...

  8. Kinect+OpenNI学习笔记之12(简单手势所表示的数字的识别)

    引自:http://www.cnblogs.com/tornadomeet/archive/2012/11/04/2753185.html 前言 这篇文章是本人玩kinect时做的一个小实验,即不采用 ...

  9. 行人检测/人体检测综述

    行人检测/人体检测综述 更详细的资料整理到了个人的github上,地址为 https://github.com/whitenightwu/11-Algorithm_and_Data\11-Paper ...

最新文章

  1. maven中打包项目为war包的pom.xml配置
  2. python网上编程课程-程序设计入门—Python
  3. delphi acropdf打印多个pdf_将多个PDF文件整合成一个文件
  4. en55032最新标准下载_关于欧盟新版EMC标准EN55032的解析
  5. 想自学HCIE,有什么好的书籍推荐吗?
  6. 过往记忆大数据 USDP 实测搭建,可替代CDH的免费大数据套件平台
  7. Matlab 动画及Gif生成
  8. Python3.7.4入门-0/1To Begin/数据类型与结构
  9. xorl %eax, %eax
  10. python 高德地图交通态势爬取(存入mysql)
  11. 060616信用证点滴简结(三)--D/P即期跟单托收
  12. Android 源码分享之小米文件管理器
  13. Python程序设计——邮件处理
  14. C语言:优先级与运算符的介绍
  15. 小散量化炒股记|基于多任务爬虫技术, 实现A股实时行情Level1采样
  16. mysql安装包msi_win10系统,mysql-installer-community-5.7.19.0.msi安装
  17. gradle引入本地jar
  18. 抗体偶联药物 (ADC)——抗肿瘤细胞
  19. 联合循环—25(了解PID原理图1)
  20. java的递归详细讲解

热门文章

  1. 怎样对平面中的点进行顺时针或者逆时针排序
  2. 深入讲解VsCode各场景高级调试与使用技巧
  3. (Ubuntu)下载及安装Genymosion模拟器并配置Android Studio
  4. 【Hadoop】Build and Execute
  5. 你不知道的javascript读书记录
  6. python 矢量数据融合代码_在ArcGIS下基于Python的矢量数据处理方法
  7. 极限与连续知识点总结_知识点一(极限与连续).doc
  8. windows注册表:开机启动的程序
  9. 第一次在我的P200上自己用rviz展现激光雷达数据
  10. 在Chrome中打印CSDN博客内容