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


    传感器简介

    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
    ",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
    ");
     433         }
     434     }
     435 
     436     mprintf("Last_setMode_regval = %.2x
    ",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
    ",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("*********************************************
    ");
     524                 mprintf("Finding first:
    ");
     525                 mprintf("u_first = %d
    ",u_first);
     526                 mprintf("d_first = %d
    ",d_first);
     527                 mprintf("l_first = %d
    ",l_first);
     528                 mprintf("r_first = %d
    ",r_first);
     529                 mprintf("First i = %d
    ",i);
     530                 mprintf("*********************************************
    ");
     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("*********************************************
    ");
     557                 mprintf("Finding last:
    ");
     558                 mprintf("u_last = %d
    ",u_last);
     559                 mprintf("d_last = %d
    ",d_last);
     560                 mprintf("l_last = %d
    ",l_last);
     561                 mprintf("r_last = %d
    ",r_last);
     562                 mprintf("Last i = %d
    ",i);
     563                 mprintf("*********************************************
    ");
     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("===============================================
    ");
     578     mprintf("first vs last ratio :
    ");
     579     mprintf("ud_ratio_first = %d
    ",ud_ratio_first);
     580     mprintf("lr_ratio_first = %d
    ",lr_ratio_first);
     581     mprintf("ud_ratio_last = %d
    ",ud_ratio_last);
     582     mprintf("lr_ratio_last = %d
    ",lr_ratio_last);
     583     mprintf("===============================================
    ");
     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("===============================================
    ");
     591     mprintf("Delta:
    ");
     592     mprintf("ud_delta = %d
    ",ud_delta);
     593     mprintf("lr_delta = %d
    ",lr_delta);
     594     mprintf("===============================================
    ");
     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("===============================================
    ");
     603     mprintf("Accumulate Delta:
    ");
     604     mprintf("gesture_ud_delta_ = %d
    ",gesture_ud_delta_);
     605     mprintf("gesture_lr_delta_ = %d
    ",gesture_lr_delta_);
     606     mprintf("===============================================
    ");
     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
    ");
     613     }
     614     else if( gesture_ud_delta_ <= -GESTURE_SENSITIVITY_1 )
     615     {
     616         gesture_ud_count_ = -1;
     617         mprintf("D--->U
    ");
     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
    ");
     629     }
     630     else if( gesture_lr_delta_ <= -GESTURE_SENSITIVITY_1 )
     631     {
     632         gesture_lr_count_ = -1;
     633         mprintf("R--->L
    ");
     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("===============================================
    ");
     688     mprintf("UD_CT = %d
    ",gesture_ud_count_);
     689     mprintf("LR_CT = %d
    ",gesture_lr_count_);
     690     mprintf("NEAR_CT = %d
    ",gesture_near_count_);
     691     mprintf("FAR_CT = %d
    ",gesture_far_count_);
     692     mprintf("===============================================
    ");
     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
    ",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("=========================
    ");
     867                     mprintf("%d fifo_level data
    ",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  
    ",fifo_data[i+3]);
     872                     mprintf("=========================
    ");
     873                 }
     874                 mprintf("fifo_level = %d
    ",fifo_level);
     875                 mprintf("bytes_read = %d
    ",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
    ",gesture_data_.index);
     899                     mprintf("gesture_data_.total_gestures = %d
    ",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
    ",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
    ",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
    ",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
    ",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
    ",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
    ",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
    ");
    1471             break;
    1472         case DIR_DOWN:
    1473             mprintf("Gesture-DOWN
    ");
    1474             break;
    1475         case DIR_LEFT:
    1476             mprintf("Gesture-LEFT
    ");
    1477             break;
    1478         case DIR_RIGHT:
    1479             mprintf("Gesture-RIGHT
    ");
    1480             break;
    1481         case DIR_NEAR:
    1482             mprintf("Gesture-NEAR
    ");
    1483             break;
    1484         case DIR_FAR:
    1485             mprintf("Gesture-FAR
    ");
    1486             break;
    1487         default:
    1488             mprintf("Gesture-NONE
    ");
    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 -----------------------------------------------------------------------------*/
  • 相关阅读:
    系统调用(转)
    linux 特殊符号(转)
    对物权法第十二章建设用地使用权解读(转载)
    地籍管理信息化总体设计纲要
    行业管理架构初探
    基础框架平台——基础管理框架——GUI实现设计(一)
    通过类库来实现多窗体windows程序遇到了些问题,请大家有空帮忙看一下,谢谢
    基础框架平台——基础管理框架——GUI抽象设计(布局管理器)
    基础框架平台——基础管理框架——GUI抽象设计(工作台)
    当窗体最大化后,系统提示"集合在窗体变化时发生了修改",请问是什么缘故啊?
  • 原文地址:https://www.cnblogs.com/wangyanwen/p/11451573.html
Copyright © 2020-2023  润新知