A library for the combined proximity, ambient light, RGB color and gesture sensor Avago APDS9960. Tested with corresponding breakout board from SparkFun.

Dependents:   mbed_blinky

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SparkFun_APDS9960.cpp Source File

SparkFun_APDS9960.cpp

00001 /**
00002  * @file    SparkFun_APDS-9960.cpp
00003  * @brief   Library for the SparkFun APDS-9960 breakout board
00004  * @author  Shawn Hymel (SparkFun Electronics)
00005  *
00006  * @copyright   This code is public domain but you buy me a beer if you use
00007  * this and we meet someday (Beerware license).
00008  *
00009  * Adapted for mbed by Nenad Milosevic (synvox.ch) in April 2015.
00010  *
00011  * This library interfaces the Avago APDS-9960 to mbed over I2C. The library
00012  * relies on the mbed I2C-library. To use the library, instantiate an
00013  * APDS9960 object, call init(), and call the appropriate functions.
00014  *
00015  * APDS-9960 current draw tests (default parameters):
00016  *   Off:                   1mA
00017  *   Waiting for gesture:   14mA
00018  *   Gesture in progress:   35mA
00019  */
00020  
00021  #include "mbed.h"
00022  
00023  #include "SparkFun_APDS9960.h"
00024  
00025 /**
00026  * @brief Constructor - Instantiates SparkFun_APDS9960 object
00027  */
00028 SparkFun_APDS9960::SparkFun_APDS9960(I2C &i2c) : apds_i2c(i2c)
00029 {
00030     gesture_ud_delta_ = 0;
00031     gesture_lr_delta_ = 0;
00032     
00033     gesture_ud_count_ = 0;
00034     gesture_lr_count_ = 0;
00035     
00036     gesture_near_count_ = 0;
00037     gesture_far_count_ = 0;
00038     
00039     gesture_state_ = 0;
00040     gesture_motion_ = DIR_NONE;
00041 }
00042  
00043 /**
00044  * @brief Destructor
00045  */
00046 SparkFun_APDS9960::~SparkFun_APDS9960()
00047 {
00048 
00049 }
00050 
00051 /**
00052  * @brief Configures I2C communications and initializes registers to defaults
00053  *
00054  * @return True if initialized successfully. False otherwise.
00055  */
00056 bool SparkFun_APDS9960::init(int apds_i2c_freq)
00057 {
00058     uint8_t id;
00059 
00060     /* Initialize I2C */
00061     apds_i2c.frequency(apds_i2c_freq);
00062      
00063     /* Read ID register and check against known values for APDS-9960 */
00064     if( !wireReadDataByte(APDS9960_ID, id) ) {
00065         return false;
00066     }
00067     if( !(id == APDS9960_ID_1 || id == APDS9960_ID_2) ) {
00068         return false;
00069     }
00070      
00071     /* Set ENABLE register to 0 (disable all features) */
00072     if( !setMode(ALL_MODES, OFF) ) {
00073         return false;
00074     }
00075     
00076     /* Set default values for ambient light and proximity registers */
00077     if( !wireWriteDataByte(APDS9960_ATIME, DEFAULT_ATIME) ) {
00078         return false;
00079     }
00080     if( !wireWriteDataByte(APDS9960_WTIME, DEFAULT_WTIME) ) {
00081         return false;
00082     }
00083     if( !wireWriteDataByte(APDS9960_PPULSE, DEFAULT_PROX_PPULSE) ) {
00084         return false;
00085     }
00086     if( !wireWriteDataByte(APDS9960_POFFSET_UR, DEFAULT_POFFSET_UR) ) {
00087         return false;
00088     }
00089     if( !wireWriteDataByte(APDS9960_POFFSET_DL, DEFAULT_POFFSET_DL) ) {
00090         return false;
00091     }
00092     if( !wireWriteDataByte(APDS9960_CONFIG1, DEFAULT_CONFIG1) ) {
00093         return false;
00094     }
00095     if( !setLEDDrive(DEFAULT_LDRIVE) ) {
00096         return false;
00097     }
00098     if( !setProximityGain(DEFAULT_PGAIN) ) {
00099         return false;
00100     }
00101     if( !setAmbientLightGain(DEFAULT_AGAIN) ) {
00102         return false;
00103     }
00104     if( !setProxIntLowThresh(DEFAULT_PILT) ) {
00105         return false;
00106     }
00107     if( !setProxIntHighThresh(DEFAULT_PIHT) ) {
00108         return false;
00109     }
00110     if( !setLightIntLowThreshold(DEFAULT_AILT) ) {
00111         return false;
00112     }
00113     if( !setLightIntHighThreshold(DEFAULT_AIHT) ) {
00114         return false;
00115     }
00116     if( !wireWriteDataByte(APDS9960_PERS, DEFAULT_PERS) ) {
00117         return false;
00118     }
00119     if( !wireWriteDataByte(APDS9960_CONFIG2, DEFAULT_CONFIG2) ) {
00120         return false;
00121     }
00122     if( !wireWriteDataByte(APDS9960_CONFIG3, DEFAULT_CONFIG3) ) {
00123         return false;
00124     }
00125     
00126     /* Set default values for gesture sense registers */
00127     if( !setGestureEnterThresh(DEFAULT_GPENTH) ) {
00128         return false;
00129     }
00130     if( !setGestureExitThresh(DEFAULT_GEXTH) ) {
00131         return false;
00132     }
00133     if( !wireWriteDataByte(APDS9960_GCONF1, DEFAULT_GCONF1) ) {
00134         return false;
00135     }
00136     if( !setGestureGain(DEFAULT_GGAIN) ) {
00137         return false;
00138     }
00139     if( !setGestureLEDDrive(DEFAULT_GLDRIVE) ) {
00140         return false;
00141     }
00142     if( !setGestureWaitTime(DEFAULT_GWTIME) ) {
00143         return false;
00144     }
00145     if( !wireWriteDataByte(APDS9960_GOFFSET_U, DEFAULT_GOFFSET) ) {
00146         return false;
00147     }
00148     if( !wireWriteDataByte(APDS9960_GOFFSET_D, DEFAULT_GOFFSET) ) {
00149         return false;
00150     }
00151     if( !wireWriteDataByte(APDS9960_GOFFSET_L, DEFAULT_GOFFSET) ) {
00152         return false;
00153     }
00154     if( !wireWriteDataByte(APDS9960_GOFFSET_R, DEFAULT_GOFFSET) ) {
00155         return false;
00156     }
00157     if( !wireWriteDataByte(APDS9960_GPULSE, DEFAULT_GPULSE) ) {
00158         return false;
00159     }
00160     if( !wireWriteDataByte(APDS9960_GCONF3, DEFAULT_GCONF3) ) {
00161         return false;
00162     }
00163     if( !setGestureIntEnable(DEFAULT_GIEN) ) {
00164         return false;
00165     }
00166 
00167     return true;
00168 }
00169 
00170 /*******************************************************************************
00171  * Public methods for controlling the APDS-9960
00172  ******************************************************************************/
00173 
00174 /**
00175  * @brief Reads and returns the contents of the ENABLE register
00176  *
00177  * @return Contents of the ENABLE register. 0xFF if error.
00178  */
00179 uint8_t SparkFun_APDS9960::getMode()
00180 {
00181     uint8_t enable_value;
00182     
00183     /* Read current ENABLE register */
00184     if( !wireReadDataByte(APDS9960_ENABLE, enable_value) ) {
00185         return ERROR;
00186     }
00187     
00188     return enable_value;
00189 }
00190 
00191 /**
00192  * @brief Enables or disables a feature in the APDS-9960
00193  *
00194  * @param[in] mode which feature to enable
00195  * @param[in] enable ON (1) or OFF (0)
00196  * @return True if operation success. False otherwise.
00197  */
00198 bool SparkFun_APDS9960::setMode(uint8_t mode, uint8_t enable)
00199 {
00200     uint8_t reg_val;
00201 
00202     /* Read current ENABLE register */
00203     reg_val = getMode();
00204     if( reg_val == ERROR ) {
00205         return false;
00206     }
00207     
00208     /* Change bit(s) in ENABLE register */
00209     enable = enable & 0x01;
00210     if( mode <= 6 ) {
00211         if (enable) {
00212             reg_val |= (1 << mode);
00213         } else {
00214             reg_val &= ~(1 << mode);
00215         }
00216     } else if( mode == ALL_MODES ) {
00217         if (enable) {
00218             reg_val = 0x7F;
00219         } else {
00220             reg_val = 0x00;
00221         }
00222     }
00223         
00224     /* Write value back to ENABLE register */
00225     if( !wireWriteDataByte(APDS9960_ENABLE, reg_val) ) {
00226         return false;
00227     }
00228         
00229     return true;
00230 }
00231 
00232 /**
00233  * @brief Starts the light (R/G/B/Ambient) sensor on the APDS-9960
00234  *
00235  * @param[in] interrupts true to enable hardware interrupt on high or low light
00236  * @return True if sensor enabled correctly. False on error.
00237  */
00238 bool SparkFun_APDS9960::enableLightSensor(bool interrupts)
00239 {
00240     
00241     /* Set default gain, interrupts, enable power, and enable sensor */
00242     if( !setAmbientLightGain(DEFAULT_AGAIN) ) {
00243         return false;
00244     }
00245     if( interrupts ) {
00246         if( !setAmbientLightIntEnable(1) ) {
00247             return false;
00248         }
00249     } else {
00250         if( !setAmbientLightIntEnable(0) ) {
00251             return false;
00252         }
00253     }
00254     if( !enablePower() ){
00255         return false;
00256     }
00257     if( !setMode(AMBIENT_LIGHT, 1) ) {
00258         return false;
00259     }
00260     
00261     return true;
00262 
00263 }
00264 
00265 /**
00266  * @brief Ends the light sensor on the APDS-9960
00267  *
00268  * @return True if sensor disabled correctly. False on error.
00269  */
00270 bool SparkFun_APDS9960::disableLightSensor()
00271 {
00272     if( !setAmbientLightIntEnable(0) ) {
00273         return false;
00274     }
00275     if( !setMode(AMBIENT_LIGHT, 0) ) {
00276         return false;
00277     }
00278     
00279     return true;
00280 }
00281 
00282 /**
00283  * @brief Starts the proximity sensor on the APDS-9960
00284  *
00285  * @param[in] interrupts true to enable hardware external interrupt on proximity
00286  * @return True if sensor enabled correctly. False on error.
00287  */
00288 bool SparkFun_APDS9960::enableProximitySensor(bool interrupts)
00289 {
00290     /* Set default gain, LED, interrupts, enable power, and enable sensor */
00291     if( !setProximityGain(DEFAULT_PGAIN) ) {
00292         return false;
00293     }
00294     if( !setLEDDrive(DEFAULT_LDRIVE) ) {
00295         return false;
00296     }
00297     if( interrupts ) {
00298         if( !setProximityIntEnable(1) ) {
00299             return false;
00300         }
00301     } else {
00302         if( !setProximityIntEnable(0) ) {
00303             return false;
00304         }
00305     }
00306     if( !enablePower() ){
00307         return false;
00308     }
00309     if( !setMode(PROXIMITY, 1) ) {
00310         return false;
00311     }
00312     
00313     return true;
00314 }
00315 
00316 /**
00317  * @brief Ends the proximity sensor on the APDS-9960
00318  *
00319  * @return True if sensor disabled correctly. False on error.
00320  */
00321 bool SparkFun_APDS9960::disableProximitySensor()
00322 {
00323     if( !setProximityIntEnable(0) ) {
00324         return false;
00325     }
00326     if( !setMode(PROXIMITY, 0) ) {
00327         return false;
00328     }
00329 
00330     return true;
00331 }
00332 
00333 /**
00334  * @brief Starts the gesture recognition engine on the APDS-9960
00335  *
00336  * @param[in] interrupts true to enable hardware external interrupt on gesture
00337  * @return True if engine enabled correctly. False on error.
00338  */
00339 bool SparkFun_APDS9960::enableGestureSensor(bool interrupts)
00340 {
00341     
00342     /* Enable gesture mode
00343        Set ENABLE to 0 (power off)
00344        Set WTIME to 0xFF
00345        Set AUX to LED_BOOST_300
00346        Enable PON, WEN, PEN, GEN in ENABLE 
00347     */
00348     resetGestureParameters();
00349     if( !wireWriteDataByte(APDS9960_WTIME, 0xFF) ) {
00350         return false;
00351     }
00352     if( !wireWriteDataByte(APDS9960_PPULSE, DEFAULT_GESTURE_PPULSE) ) {
00353         return false;
00354     }
00355     if( !setLEDBoost(LED_BOOST_300) ) {
00356         return false;
00357     }
00358     if( interrupts ) {
00359         if( !setGestureIntEnable(1) ) {
00360             return false;
00361         }
00362     } else {
00363         if( !setGestureIntEnable(0) ) {
00364             return false;
00365         }
00366     }
00367     if( !setGestureMode(1) ) {
00368         return false;
00369     }
00370     if( !enablePower() ){
00371         return false;
00372     }
00373     if( !setMode(WAIT, 1) ) {
00374         return false;
00375     }
00376     if( !setMode(PROXIMITY, 1) ) {
00377         return false;
00378     }
00379     if( !setMode(GESTURE, 1) ) {
00380         return false;
00381     }
00382     
00383     return true;
00384 }
00385 
00386 /**
00387  * @brief Ends the gesture recognition engine on the APDS-9960
00388  *
00389  * @return True if engine disabled correctly. False on error.
00390  */
00391 bool SparkFun_APDS9960::disableGestureSensor()
00392 {
00393     resetGestureParameters();
00394     if( !setGestureIntEnable(0) ) {
00395         return false;
00396     }
00397     if( !setGestureMode(0) ) {
00398         return false;
00399     }
00400     if( !setMode(GESTURE, 0) ) {
00401         return false;
00402     }
00403     
00404     return true;
00405 }
00406 
00407 /**
00408  * @brief Determines if there is a gesture available for reading
00409  *
00410  * @return True if gesture available. False otherwise.
00411  */
00412 bool SparkFun_APDS9960::isGestureAvailable()
00413 {
00414     uint8_t val;
00415     
00416     /* Read value from GSTATUS register */
00417     if( !wireReadDataByte(APDS9960_GSTATUS, val) ) {
00418         return ERROR;
00419     }
00420     
00421     /* Shift and mask out GVALID bit */
00422     val &= APDS9960_GVALID;
00423     
00424     /* Return true/false based on GVALID bit */
00425     if( val == 1) {
00426         return true;
00427     } else {
00428         return false;
00429     }
00430 }
00431 
00432 /**
00433  * @brief Processes a gesture event and returns best guessed gesture
00434  *
00435  * @return Number corresponding to gesture. -1 on error.
00436  */
00437 int SparkFun_APDS9960::readGesture()
00438 {
00439     uint8_t fifo_level = 0;
00440     int bytes_read = 0;
00441     uint8_t fifo_data[128];
00442     uint8_t gstatus;
00443     int motion;
00444     int i;
00445     
00446     /* Make sure that power and gesture is on and data is valid */
00447     if( !isGestureAvailable() || !(getMode() & 0x41) ) {
00448         return DIR_NONE;
00449     }
00450     
00451     /* Keep looping as long as gesture data is valid */
00452     while(1) {
00453     
00454         /* Wait some time to collect next batch of FIFO data */
00455         wait_ms(FIFO_PAUSE_TIME);
00456         
00457         /* Get the contents of the STATUS register. Is data still valid? */
00458         if( !wireReadDataByte(APDS9960_GSTATUS, gstatus) ) {
00459             return ERROR;
00460         }
00461         
00462         /* If we have valid data, read in FIFO */
00463         if( (gstatus & APDS9960_GVALID) == APDS9960_GVALID ) {
00464         
00465             /* Read the current FIFO level */
00466             if( !wireReadDataByte(APDS9960_GFLVL, fifo_level) ) {
00467                 return ERROR;
00468             }
00469 
00470             /* If there's stuff in the FIFO, read it into our data block */
00471             if( fifo_level > 0) {
00472                 bytes_read = wireReadDataBlock(  APDS9960_GFIFO_U, 
00473                                                 (uint8_t*)fifo_data, 
00474                                                 (fifo_level * 4) );
00475                 if( bytes_read == -1 ) {
00476                     return ERROR;
00477                 }
00478 
00479                 /* If at least 1 set of data, sort the data into U/D/L/R */
00480                 if( bytes_read >= 4 ) {
00481                     for( i = 0; i < bytes_read; i += 4 ) {
00482                         gesture_data_.u_data[gesture_data_.index] = \
00483                                                             fifo_data[i + 0];
00484                         gesture_data_.d_data[gesture_data_.index] = \
00485                                                             fifo_data[i + 1];
00486                         gesture_data_.l_data[gesture_data_.index] = \
00487                                                             fifo_data[i + 2];
00488                         gesture_data_.r_data[gesture_data_.index] = \
00489                                                             fifo_data[i + 3];
00490                         gesture_data_.index++;
00491                         gesture_data_.total_gestures++;
00492                     }
00493 
00494                     /* Filter and process gesture data. Decode near/far state */
00495                     if( processGestureData() ) {
00496                         if( decodeGesture() ) {
00497                             //***TODO: U-Turn Gestures
00498                         }
00499                     }
00500                     
00501                     /* Reset data */
00502                     gesture_data_.index = 0;
00503                     gesture_data_.total_gestures = 0;
00504                 }
00505             }
00506         } else {
00507     
00508             /* Determine best guessed gesture and clean up */
00509             wait_ms(FIFO_PAUSE_TIME);
00510             decodeGesture();
00511             motion = gesture_motion_;
00512             resetGestureParameters();
00513             return motion;
00514         }
00515     }
00516 }
00517 
00518 /**
00519  * Turn the APDS-9960 on
00520  *
00521  * @return True if operation successful. False otherwise.
00522  */
00523 bool SparkFun_APDS9960::enablePower()
00524 {
00525     if( !setMode(POWER, 1) ) {
00526         return false;
00527     }
00528     
00529     return true;
00530 }
00531 
00532 /**
00533  * Turn the APDS-9960 off
00534  *
00535  * @return True if operation successful. False otherwise.
00536  */
00537 bool SparkFun_APDS9960::disablePower()
00538 {
00539     if( !setMode(POWER, 0) ) {
00540         return false;
00541     }
00542     
00543     return true;
00544 }
00545 
00546 /*******************************************************************************
00547  * Ambient light and color sensor controls
00548  ******************************************************************************/
00549 
00550 /**
00551  * @brief Reads the ambient (clear) light level as a 16-bit value
00552  *
00553  * @param[out] val value of the light sensor.
00554  * @return True if operation successful. False otherwise.
00555  */
00556 bool SparkFun_APDS9960::readAmbientLight(uint16_t &val)
00557 {
00558     uint8_t val_byte;
00559     val = 0;
00560     
00561     /* Read value from clear channel, low byte register */
00562     if( !wireReadDataByte(APDS9960_CDATAL, val_byte) ) {
00563         return false;
00564     }
00565     val = val_byte;
00566     
00567     /* Read value from clear channel, high byte register */
00568     if( !wireReadDataByte(APDS9960_CDATAH, val_byte) ) {
00569         return false;
00570     }
00571     val = val + ((uint16_t)val_byte << 8);
00572     
00573     return true;
00574 }
00575 
00576 /**
00577  * @brief Reads the red light level as a 16-bit value
00578  *
00579  * @param[out] val value of the light sensor.
00580  * @return True if operation successful. False otherwise.
00581  */
00582 bool SparkFun_APDS9960::readRedLight(uint16_t &val)
00583 {
00584     uint8_t val_byte;
00585     val = 0;
00586     
00587     /* Read value from clear channel, low byte register */
00588     if( !wireReadDataByte(APDS9960_RDATAL, val_byte) ) {
00589         return false;
00590     }
00591     val = val_byte;
00592     
00593     /* Read value from clear channel, high byte register */
00594     if( !wireReadDataByte(APDS9960_RDATAH, val_byte) ) {
00595         return false;
00596     }
00597     val = val + ((uint16_t)val_byte << 8);
00598     
00599     return true;
00600 }
00601  
00602 /**
00603  * @brief Reads the green light level as a 16-bit value
00604  *
00605  * @param[out] val value of the light sensor.
00606  * @return True if operation successful. False otherwise.
00607  */
00608 bool SparkFun_APDS9960::readGreenLight(uint16_t &val)
00609 {
00610     uint8_t val_byte;
00611     val = 0;
00612     
00613     /* Read value from clear channel, low byte register */
00614     if( !wireReadDataByte(APDS9960_GDATAL, val_byte) ) {
00615         return false;
00616     }
00617     val = val_byte;
00618     
00619     /* Read value from clear channel, high byte register */
00620     if( !wireReadDataByte(APDS9960_GDATAH, val_byte) ) {
00621         return false;
00622     }
00623     val = val + ((uint16_t)val_byte << 8);
00624     
00625     return true;
00626 }
00627 
00628 /**
00629  * @brief Reads the red light level as a 16-bit value
00630  *
00631  * @param[out] val value of the light sensor.
00632  * @return True if operation successful. False otherwise.
00633  */
00634 bool SparkFun_APDS9960::readBlueLight(uint16_t &val)
00635 {
00636     uint8_t val_byte;
00637     val = 0;
00638     
00639     /* Read value from clear channel, low byte register */
00640     if( !wireReadDataByte(APDS9960_BDATAL, val_byte) ) {
00641         return false;
00642     }
00643     val = val_byte;
00644     
00645     /* Read value from clear channel, high byte register */
00646     if( !wireReadDataByte(APDS9960_BDATAH, val_byte) ) {
00647         return false;
00648     }
00649     val = val + ((uint16_t)val_byte << 8);
00650     
00651     return true;
00652 }
00653 
00654 /*******************************************************************************
00655  * Proximity sensor controls
00656  ******************************************************************************/
00657 
00658 /**
00659  * @brief Reads the proximity level as an 8-bit value
00660  *
00661  * @param[out] val value of the proximity sensor.
00662  * @return True if operation successful. False otherwise.
00663  */
00664 bool SparkFun_APDS9960::readProximity(uint8_t &val)
00665 {
00666     val = 0;
00667     
00668     /* Read value from proximity data register */
00669     if( !wireReadDataByte(APDS9960_PDATA, val) ) {
00670         return false;
00671     }
00672     
00673     return true;
00674 }
00675 
00676 /*******************************************************************************
00677  * High-level gesture controls
00678  ******************************************************************************/
00679 
00680 /**
00681  * @brief Resets all the parameters in the gesture data member
00682  */
00683 void SparkFun_APDS9960::resetGestureParameters()
00684 {
00685     gesture_data_.index = 0;
00686     gesture_data_.total_gestures = 0;
00687     
00688     gesture_ud_delta_ = 0;
00689     gesture_lr_delta_ = 0;
00690     
00691     gesture_ud_count_ = 0;
00692     gesture_lr_count_ = 0;
00693     
00694     gesture_near_count_ = 0;
00695     gesture_far_count_ = 0;
00696     
00697     gesture_state_ = 0;
00698     gesture_motion_ = DIR_NONE;
00699 }
00700 
00701 /**
00702  * @brief Processes the raw gesture data to determine swipe direction
00703  *
00704  * @return True if near or far state seen. False otherwise.
00705  */
00706 bool SparkFun_APDS9960::processGestureData()
00707 {
00708     uint8_t u_first = 0;
00709     uint8_t d_first = 0;
00710     uint8_t l_first = 0;
00711     uint8_t r_first = 0;
00712     uint8_t u_last = 0;
00713     uint8_t d_last = 0;
00714     uint8_t l_last = 0;
00715     uint8_t r_last = 0;
00716     int ud_ratio_first;
00717     int lr_ratio_first;
00718     int ud_ratio_last;
00719     int lr_ratio_last;
00720     int ud_delta;
00721     int lr_delta;
00722     int i;
00723 
00724     /* If we have less than 4 total gestures, that's not enough */
00725     if( gesture_data_.total_gestures <= 4 ) {
00726         return false;
00727     }
00728     
00729     /* Check to make sure our data isn't out of bounds */
00730     if( (gesture_data_.total_gestures <= 32) && \
00731         (gesture_data_.total_gestures > 0) ) {
00732         
00733         /* Find the first value in U/D/L/R above the threshold */
00734         for( i = 0; i < gesture_data_.total_gestures; i++ ) {
00735             if( (gesture_data_.u_data[i] > GESTURE_THRESHOLD_OUT) &&
00736                 (gesture_data_.d_data[i] > GESTURE_THRESHOLD_OUT) &&
00737                 (gesture_data_.l_data[i] > GESTURE_THRESHOLD_OUT) &&
00738                 (gesture_data_.r_data[i] > GESTURE_THRESHOLD_OUT) ) {
00739                 
00740                 u_first = gesture_data_.u_data[i];
00741                 d_first = gesture_data_.d_data[i];
00742                 l_first = gesture_data_.l_data[i];
00743                 r_first = gesture_data_.r_data[i];
00744                 break;
00745             }
00746         }
00747         
00748         /* If one of the _first values is 0, then there is no good data */
00749         if( (u_first == 0) || (d_first == 0) || \
00750             (l_first == 0) || (r_first == 0) ) {
00751             
00752             return false;
00753         }
00754         /* Find the last value in U/D/L/R above the threshold */
00755         for( i = gesture_data_.total_gestures - 1; i >= 0; i-- ) {
00756             if( (gesture_data_.u_data[i] > GESTURE_THRESHOLD_OUT) &&
00757                 (gesture_data_.d_data[i] > GESTURE_THRESHOLD_OUT) &&
00758                 (gesture_data_.l_data[i] > GESTURE_THRESHOLD_OUT) &&
00759                 (gesture_data_.r_data[i] > GESTURE_THRESHOLD_OUT) ) {
00760                 
00761                 u_last = gesture_data_.u_data[i];
00762                 d_last = gesture_data_.d_data[i];
00763                 l_last = gesture_data_.l_data[i];
00764                 r_last = gesture_data_.r_data[i];
00765                 break;
00766             }
00767         }
00768     }
00769     
00770     /* Calculate the first vs. last ratio of up/down and left/right */
00771     ud_ratio_first = ((u_first - d_first) * 100) / (u_first + d_first);
00772     lr_ratio_first = ((l_first - r_first) * 100) / (l_first + r_first);
00773     ud_ratio_last = ((u_last - d_last) * 100) / (u_last + d_last);
00774     lr_ratio_last = ((l_last - r_last) * 100) / (l_last + r_last);
00775        
00776     /* Determine the difference between the first and last ratios */
00777     ud_delta = ud_ratio_last - ud_ratio_first;
00778     lr_delta = lr_ratio_last - lr_ratio_first;
00779 
00780     /* Accumulate the UD and LR delta values */
00781     gesture_ud_delta_ += ud_delta;
00782     gesture_lr_delta_ += lr_delta;
00783     
00784     /* Determine U/D gesture */
00785     if( gesture_ud_delta_ >= GESTURE_SENSITIVITY_1 ) {
00786         gesture_ud_count_ = 1;
00787     } else if( gesture_ud_delta_ <= -GESTURE_SENSITIVITY_1 ) {
00788         gesture_ud_count_ = -1;
00789     } else {
00790         gesture_ud_count_ = 0;
00791     }
00792     
00793     /* Determine L/R gesture */
00794     if( gesture_lr_delta_ >= GESTURE_SENSITIVITY_1 ) {
00795         gesture_lr_count_ = 1;
00796     } else if( gesture_lr_delta_ <= -GESTURE_SENSITIVITY_1 ) {
00797         gesture_lr_count_ = -1;
00798     } else {
00799         gesture_lr_count_ = 0;
00800     }
00801     
00802     /* Determine Near/Far gesture */
00803     if( (gesture_ud_count_ == 0) && (gesture_lr_count_ == 0) ) {
00804         if( (abs(ud_delta) < GESTURE_SENSITIVITY_2) && \
00805             (abs(lr_delta) < GESTURE_SENSITIVITY_2) ) {
00806             
00807             if( (ud_delta == 0) && (lr_delta == 0) ) {
00808                 gesture_near_count_++;
00809             } else if( (ud_delta != 0) || (lr_delta != 0) ) {
00810                 gesture_far_count_++;
00811             }
00812             
00813             if( (gesture_near_count_ >= 10) && (gesture_far_count_ >= 2) ) {
00814                 if( (ud_delta == 0) && (lr_delta == 0) ) {
00815                     gesture_state_ = NEAR_STATE;
00816                 } else if( (ud_delta != 0) && (lr_delta != 0) ) {
00817                     gesture_state_ = FAR_STATE;
00818                 }
00819                 return true;
00820             }
00821         }
00822     } else {
00823         if( (abs(ud_delta) < GESTURE_SENSITIVITY_2) && \
00824             (abs(lr_delta) < GESTURE_SENSITIVITY_2) ) {
00825                 
00826             if( (ud_delta == 0) && (lr_delta == 0) ) {
00827                 gesture_near_count_++;
00828             }
00829             
00830             if( gesture_near_count_ >= 10 ) {
00831                 gesture_ud_count_ = 0;
00832                 gesture_lr_count_ = 0;
00833                 gesture_ud_delta_ = 0;
00834                 gesture_lr_delta_ = 0;
00835             }
00836         }
00837     }
00838     
00839     return false;
00840 }
00841 
00842 /**
00843  * @brief Determines swipe direction or near/far state
00844  *
00845  * @return True if near/far event. False otherwise.
00846  */
00847 bool SparkFun_APDS9960::decodeGesture()
00848 {
00849     /* Return if near or far event is detected */
00850     if( gesture_state_ == NEAR_STATE ) {
00851         gesture_motion_ = DIR_NEAR;
00852         return true;
00853     } else if ( gesture_state_ == FAR_STATE ) {
00854         gesture_motion_ = DIR_FAR;
00855         return true;
00856     }
00857     
00858     /* Determine swipe direction */
00859     if( (gesture_ud_count_ == -1) && (gesture_lr_count_ == 0) ) {
00860         gesture_motion_ = DIR_UP;
00861     } else if( (gesture_ud_count_ == 1) && (gesture_lr_count_ == 0) ) {
00862         gesture_motion_ = DIR_DOWN;
00863     } else if( (gesture_ud_count_ == 0) && (gesture_lr_count_ == 1) ) {
00864         gesture_motion_ = DIR_RIGHT;
00865     } else if( (gesture_ud_count_ == 0) && (gesture_lr_count_ == -1) ) {
00866         gesture_motion_ = DIR_LEFT;
00867     } else if( (gesture_ud_count_ == -1) && (gesture_lr_count_ == 1) ) {
00868         if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) {
00869             gesture_motion_ = DIR_UP;
00870         } else {
00871             gesture_motion_ = DIR_RIGHT;
00872         }
00873     } else if( (gesture_ud_count_ == 1) && (gesture_lr_count_ == -1) ) {
00874         if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) {
00875             gesture_motion_ = DIR_DOWN;
00876         } else {
00877             gesture_motion_ = DIR_LEFT;
00878         }
00879     } else if( (gesture_ud_count_ == -1) && (gesture_lr_count_ == -1) ) {
00880         if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) {
00881             gesture_motion_ = DIR_UP;
00882         } else {
00883             gesture_motion_ = DIR_LEFT;
00884         }
00885     } else if( (gesture_ud_count_ == 1) && (gesture_lr_count_ == 1) ) {
00886         if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) {
00887             gesture_motion_ = DIR_DOWN;
00888         } else {
00889             gesture_motion_ = DIR_RIGHT;
00890         }
00891     } else {
00892         return false;
00893     }
00894     
00895     return true;
00896 }
00897 
00898 /*******************************************************************************
00899  * Getters and setters for register values
00900  ******************************************************************************/
00901 
00902 /**
00903  * @brief Returns the lower threshold for proximity detection
00904  *
00905  * @return lower threshold
00906  */
00907 uint8_t SparkFun_APDS9960::getProxIntLowThresh()
00908 {
00909     uint8_t val;
00910     
00911     /* Read value from PILT register */
00912     if( !wireReadDataByte(APDS9960_PILT, val) ) {
00913         val = 0;
00914     }
00915     
00916     return val;
00917 }
00918 
00919 /**
00920  * @brief Sets the lower threshold for proximity detection
00921  *
00922  * @param[in] threshold the lower proximity threshold
00923  * @return True if operation successful. False otherwise.
00924  */
00925 bool SparkFun_APDS9960::setProxIntLowThresh(uint8_t threshold)
00926 {
00927     if( !wireWriteDataByte(APDS9960_PILT, threshold) ) {
00928         return false;
00929     }
00930     
00931     return true;
00932 }
00933 
00934 /**
00935  * @brief Returns the high threshold for proximity detection
00936  *
00937  * @return high threshold
00938  */
00939 uint8_t SparkFun_APDS9960::getProxIntHighThresh()
00940 {
00941     uint8_t val;
00942     
00943     /* Read value from PIHT register */
00944     if( !wireReadDataByte(APDS9960_PIHT, val) ) {
00945         val = 0;
00946     }
00947     
00948     return val;
00949 }
00950 
00951 /**
00952  * @brief Sets the high threshold for proximity detection
00953  *
00954  * @param[in] threshold the high proximity threshold
00955  * @return True if operation successful. False otherwise.
00956  */
00957 bool SparkFun_APDS9960::setProxIntHighThresh(uint8_t threshold)
00958 {
00959     if( !wireWriteDataByte(APDS9960_PIHT, threshold) ) {
00960         return false;
00961     }
00962     
00963     return true;
00964 }
00965 
00966 /**
00967  * @brief Returns LED drive strength for proximity and ALS
00968  *
00969  * Value    LED Current
00970  *   0        100 mA
00971  *   1         50 mA
00972  *   2         25 mA
00973  *   3         12.5 mA
00974  *
00975  * @return the value of the LED drive strength. 0xFF on failure.
00976  */
00977 uint8_t SparkFun_APDS9960::getLEDDrive()
00978 {
00979     uint8_t val;
00980     
00981     /* Read value from CONTROL register */
00982     if( !wireReadDataByte(APDS9960_CONTROL, val) ) {
00983         return ERROR;
00984     }
00985     
00986     /* Shift and mask out LED drive bits */
00987     val = (val >> 6) & 0x03;
00988     
00989     return val;
00990 }
00991 
00992 /**
00993  * @brief Sets the LED drive strength for proximity and ALS
00994  *
00995  * Value    LED Current
00996  *   0        100 mA
00997  *   1         50 mA
00998  *   2         25 mA
00999  *   3         12.5 mA
01000  *
01001  * @param[in] drive the value (0-3) for the LED drive strength
01002  * @return True if operation successful. False otherwise.
01003  */
01004 bool SparkFun_APDS9960::setLEDDrive(uint8_t drive)
01005 {
01006     uint8_t val;
01007     
01008     /* Read value from CONTROL register */
01009     if( !wireReadDataByte(APDS9960_CONTROL, val) ) {
01010         return false;
01011     }
01012     
01013     /* Set bits in register to given value */
01014     drive &= 0x03;
01015     drive = drive << 6;
01016     val &= 0x3F;
01017     val |= drive;
01018     
01019     /* Write register value back into CONTROL register */
01020     if( !wireWriteDataByte(APDS9960_CONTROL, val) ) {
01021         return false;
01022     }
01023     
01024     return true;
01025 }
01026 
01027 /**
01028  * @brief Returns receiver gain for proximity detection
01029  *
01030  * Value    Gain
01031  *   0       1x
01032  *   1       2x
01033  *   2       4x
01034  *   3       8x
01035  *
01036  * @return the value of the proximity gain. 0xFF on failure.
01037  */
01038 uint8_t SparkFun_APDS9960::getProximityGain()
01039 {
01040     uint8_t val;
01041     
01042     /* Read value from CONTROL register */
01043     if( !wireReadDataByte(APDS9960_CONTROL, val) ) {
01044         return ERROR;
01045     }
01046     
01047     /* Shift and mask out PDRIVE bits */
01048     val = (val >> 2) & 0x03;
01049     
01050     return val;
01051 }
01052 
01053 /**
01054  * @brief Sets the receiver gain for proximity detection
01055  *
01056  * Value    Gain
01057  *   0       1x
01058  *   1       2x
01059  *   2       4x
01060  *   3       8x
01061  *
01062  * @param[in] drive the value (0-3) for the gain
01063  * @return True if operation successful. False otherwise.
01064  */
01065 bool SparkFun_APDS9960::setProximityGain(uint8_t drive)
01066 {
01067     uint8_t val;
01068     
01069     /* Read value from CONTROL register */
01070     if( !wireReadDataByte(APDS9960_CONTROL, val) ) {
01071         return false;
01072     }
01073     
01074     /* Set bits in register to given value */
01075     drive &= 0x03;
01076     drive = drive << 2;
01077     val &= 0xF3;
01078     val |= drive;
01079     
01080     /* Write register value back into CONTROL register */
01081     if( !wireWriteDataByte(APDS9960_CONTROL, val) ) {
01082         return false;
01083     }
01084     
01085     return true;
01086 }
01087 
01088 /**
01089  * @brief Returns receiver gain for the ambient light sensor (ALS)
01090  *
01091  * Value    Gain
01092  *   0        1x
01093  *   1        4x
01094  *   2       16x
01095  *   3       64x
01096  *
01097  * @return the value of the ALS gain. 0xFF on failure.
01098  */
01099 uint8_t SparkFun_APDS9960::getAmbientLightGain()
01100 {
01101     uint8_t val;
01102     
01103     /* Read value from CONTROL register */
01104     if( !wireReadDataByte(APDS9960_CONTROL, val) ) {
01105         return ERROR;
01106     }
01107     
01108     /* Shift and mask out ADRIVE bits */
01109     val &= 0x03;
01110     
01111     return val;
01112 }
01113 
01114 /**
01115  * @brief Sets the receiver gain for the ambient light sensor (ALS)
01116  *
01117  * Value    Gain
01118  *   0        1x
01119  *   1        4x
01120  *   2       16x
01121  *   3       64x
01122  *
01123  * @param[in] drive the value (0-3) for the gain
01124  * @return True if operation successful. False otherwise.
01125  */
01126 bool SparkFun_APDS9960::setAmbientLightGain(uint8_t drive)
01127 {
01128     uint8_t val;
01129     
01130     /* Read value from CONTROL register */
01131     if( !wireReadDataByte(APDS9960_CONTROL, val) ) {
01132         return false;
01133     }
01134     
01135     /* Set bits in register to given value */
01136     drive &= 0x03;
01137     val &= 0xFC;
01138     val |= drive;
01139     
01140     /* Write register value back into CONTROL register */
01141     if( !wireWriteDataByte(APDS9960_CONTROL, val) ) {
01142         return false;
01143     }
01144     
01145     return true;
01146 }
01147 
01148 /**
01149  * @brief Get the current LED boost value
01150  * 
01151  * Value  Boost Current
01152  *   0        100%
01153  *   1        150%
01154  *   2        200%
01155  *   3        300%
01156  *
01157  * @return The LED boost value. 0xFF on failure.
01158  */
01159 uint8_t SparkFun_APDS9960::getLEDBoost()
01160 {
01161     uint8_t val;
01162     
01163     /* Read value from CONFIG2 register */
01164     if( !wireReadDataByte(APDS9960_CONFIG2, val) ) {
01165         return ERROR;
01166     }
01167     
01168     /* Shift and mask out LED_BOOST bits */
01169     val = (val >> 4) & 0x03;
01170     
01171     return val;
01172 }
01173 
01174 /**
01175  * @brief Sets the LED current boost value
01176  *
01177  * Value  Boost Current
01178  *   0        100%
01179  *   1        150%
01180  *   2        200%
01181  *   3        300%
01182  *
01183  * @param[in] drive the value (0-3) for current boost (100-300%)
01184  * @return True if operation successful. False otherwise.
01185  */
01186 bool SparkFun_APDS9960::setLEDBoost(uint8_t boost)
01187 {
01188     uint8_t val;
01189     
01190     /* Read value from CONFIG2 register */
01191     if( !wireReadDataByte(APDS9960_CONFIG2, val) ) {
01192         return false;
01193     }
01194     
01195     /* Set bits in register to given value */
01196     boost &= 0x03;
01197     boost = boost << 4;
01198     val &= 0xCF;
01199     val |= boost;
01200     
01201     /* Write register value back into CONFIG2 register */
01202     if( !wireWriteDataByte(APDS9960_CONFIG2, val) ) {
01203         return false;
01204     }
01205     
01206     return true;
01207 }    
01208    
01209 /**
01210  * @brief Gets proximity gain compensation enable
01211  *
01212  * @return 1 if compensation is enabled. 0 if not. 0xFF on error.
01213  */
01214 uint8_t SparkFun_APDS9960::getProxGainCompEnable()
01215 {
01216     uint8_t val;
01217     
01218     /* Read value from CONFIG3 register */
01219     if( !wireReadDataByte(APDS9960_CONFIG3, val) ) {
01220         return ERROR;
01221     }
01222     
01223     /* Shift and mask out PCMP bits */
01224     val = (val >> 5) & 0x01;
01225     
01226     return val;
01227 }
01228 
01229 /**
01230  * @brief Sets the proximity gain compensation enable
01231  *
01232  * @param[in] enable 1 to enable compensation. 0 to disable compensation.
01233  * @return True if operation successful. False otherwise.
01234  */
01235  bool SparkFun_APDS9960::setProxGainCompEnable(uint8_t enable)
01236 {
01237     uint8_t val;
01238     
01239     /* Read value from CONFIG3 register */
01240     if( !wireReadDataByte(APDS9960_CONFIG3, val) ) {
01241         return false;
01242     }
01243     
01244     /* Set bits in register to given value */
01245     enable &= 0x01;
01246     enable = enable << 5;
01247     val &= 0xDF;
01248     val |= enable;
01249     
01250     /* Write register value back into CONFIG3 register */
01251     if( !wireWriteDataByte(APDS9960_CONFIG3, val) ) {
01252         return false;
01253     }
01254     
01255     return true;
01256 }
01257 
01258 /**
01259  * @brief Gets the current mask for enabled/disabled proximity photodiodes
01260  *
01261  * 1 = disabled, 0 = enabled
01262  * Bit    Photodiode
01263  *  3       UP
01264  *  2       DOWN
01265  *  1       LEFT
01266  *  0       RIGHT
01267  *
01268  * @return Current proximity mask for photodiodes. 0xFF on error.
01269  */
01270 uint8_t SparkFun_APDS9960::getProxPhotoMask()
01271 {
01272     uint8_t val;
01273     
01274     /* Read value from CONFIG3 register */
01275     if( !wireReadDataByte(APDS9960_CONFIG3, val) ) {
01276         return ERROR;
01277     }
01278     
01279     /* Mask out photodiode enable mask bits */
01280     val &= 0x0F;
01281     
01282     return val;
01283 }
01284 
01285 /**
01286  * @brief Sets the mask for enabling/disabling proximity photodiodes
01287  *
01288  * 1 = disabled, 0 = enabled
01289  * Bit    Photodiode
01290  *  3       UP
01291  *  2       DOWN
01292  *  1       LEFT
01293  *  0       RIGHT
01294  *
01295  * @param[in] mask 4-bit mask value
01296  * @return True if operation successful. False otherwise.
01297  */
01298 bool SparkFun_APDS9960::setProxPhotoMask(uint8_t mask)
01299 {
01300     uint8_t val;
01301     
01302     /* Read value from CONFIG3 register */
01303     if( !wireReadDataByte(APDS9960_CONFIG3, val) ) {
01304         return false;
01305     }
01306     
01307     /* Set bits in register to given value */
01308     mask &= 0x0F;
01309     val &= 0xF0;
01310     val |= mask;
01311     
01312     /* Write register value back into CONFIG3 register */
01313     if( !wireWriteDataByte(APDS9960_CONFIG3, val) ) {
01314         return false;
01315     }
01316     
01317     return true;
01318 }
01319 
01320 /**
01321  * @brief Gets the entry proximity threshold for gesture sensing
01322  *
01323  * @return Current entry proximity threshold.
01324  */
01325 uint8_t SparkFun_APDS9960::getGestureEnterThresh()
01326 {
01327     uint8_t val;
01328     
01329     /* Read value from GPENTH register */
01330     if( !wireReadDataByte(APDS9960_GPENTH, val) ) {
01331         val = 0;
01332     }
01333     
01334     return val;
01335 }
01336 
01337 /**
01338  * @brief Sets the entry proximity threshold for gesture sensing
01339  *
01340  * @param[in] threshold proximity value needed to start gesture mode
01341  * @return True if operation successful. False otherwise.
01342  */
01343 bool SparkFun_APDS9960::setGestureEnterThresh(uint8_t threshold)
01344 {
01345     if( !wireWriteDataByte(APDS9960_GPENTH, threshold) ) {
01346         return false;
01347     }
01348     
01349     return true;
01350 }
01351 
01352 /**
01353  * @brief Gets the exit proximity threshold for gesture sensing
01354  *
01355  * @return Current exit proximity threshold.
01356  */
01357 uint8_t SparkFun_APDS9960::getGestureExitThresh()
01358 {
01359     uint8_t val;
01360     
01361     /* Read value from GEXTH register */
01362     if( !wireReadDataByte(APDS9960_GEXTH, val) ) {
01363         val = 0;
01364     }
01365     
01366     return val;
01367 }
01368 
01369 /**
01370  * @brief Sets the exit proximity threshold for gesture sensing
01371  *
01372  * @param[in] threshold proximity value needed to end gesture mode
01373  * @return True if operation successful. False otherwise.
01374  */
01375 bool SparkFun_APDS9960::setGestureExitThresh(uint8_t threshold)
01376 {
01377     if( !wireWriteDataByte(APDS9960_GEXTH, threshold) ) {
01378         return false;
01379     }
01380     
01381     return true;
01382 }
01383 
01384 /**
01385  * @brief Gets the gain of the photodiode during gesture mode
01386  *
01387  * Value    Gain
01388  *   0       1x
01389  *   1       2x
01390  *   2       4x
01391  *   3       8x
01392  *
01393  * @return the current photodiode gain. 0xFF on error.
01394  */
01395 uint8_t SparkFun_APDS9960::getGestureGain()
01396 {
01397     uint8_t val;
01398     
01399     /* Read value from GCONF2 register */
01400     if( !wireReadDataByte(APDS9960_GCONF2, val) ) {
01401         return ERROR;
01402     }
01403     
01404     /* Shift and mask out GGAIN bits */
01405     val = (val >> 5) & 0x03;
01406     
01407     return val;
01408 }
01409 
01410 /**
01411  * @brief Sets the gain of the photodiode during gesture mode
01412  *
01413  * Value    Gain
01414  *   0       1x
01415  *   1       2x
01416  *   2       4x
01417  *   3       8x
01418  *
01419  * @param[in] gain the value for the photodiode gain
01420  * @return True if operation successful. False otherwise.
01421  */
01422 bool SparkFun_APDS9960::setGestureGain(uint8_t gain)
01423 {
01424     uint8_t val;
01425     
01426     /* Read value from GCONF2 register */
01427     if( !wireReadDataByte(APDS9960_GCONF2, val) ) {
01428         return false;
01429     }
01430     
01431     /* Set bits in register to given value */
01432     gain &= 0x03;
01433     gain = gain << 5;
01434     val &= 0x9F;
01435     val |= gain;
01436     
01437     /* Write register value back into GCONF2 register */
01438     if( !wireWriteDataByte(APDS9960_GCONF2, val) ) {
01439         return false;
01440     }
01441     
01442     return true;
01443 }
01444 
01445 /**
01446  * @brief Gets the drive current of the LED during gesture mode
01447  *
01448  * Value    LED Current
01449  *   0        100 mA
01450  *   1         50 mA
01451  *   2         25 mA
01452  *   3         12.5 mA
01453  *
01454  * @return the LED drive current value. 0xFF on error.
01455  */
01456 uint8_t SparkFun_APDS9960::getGestureLEDDrive()
01457 {
01458     uint8_t val;
01459     
01460     /* Read value from GCONF2 register */
01461     if( !wireReadDataByte(APDS9960_GCONF2, val) ) {
01462         return ERROR;
01463     }
01464     
01465     /* Shift and mask out GLDRIVE bits */
01466     val = (val >> 3) & 0x03;
01467     
01468     return val;
01469 }
01470 
01471 /**
01472  * @brief Sets the LED drive current during gesture mode
01473  *
01474  * Value    LED Current
01475  *   0        100 mA
01476  *   1         50 mA
01477  *   2         25 mA
01478  *   3         12.5 mA
01479  *
01480  * @param[in] drive the value for the LED drive current
01481  * @return True if operation successful. False otherwise.
01482  */
01483 bool SparkFun_APDS9960::setGestureLEDDrive(uint8_t drive)
01484 {
01485     uint8_t val;
01486     
01487     /* Read value from GCONF2 register */
01488     if( !wireReadDataByte(APDS9960_GCONF2, val) ) {
01489         return false;
01490     }
01491     
01492     /* Set bits in register to given value */
01493     drive &= 0x03;
01494     drive = drive << 3;
01495     val &= 0xE7;
01496     val |= drive;
01497     
01498     /* Write register value back into GCONF2 register */
01499     if( !wireWriteDataByte(APDS9960_GCONF2, val) ) {
01500         return false;
01501     }
01502     
01503     return true;
01504 }
01505 
01506 /**
01507  * @brief Gets the time in low power mode between gesture detections
01508  *
01509  * Value    Wait time
01510  *   0          0 ms
01511  *   1          2.8 ms
01512  *   2          5.6 ms
01513  *   3          8.4 ms
01514  *   4         14.0 ms
01515  *   5         22.4 ms
01516  *   6         30.8 ms
01517  *   7         39.2 ms
01518  *
01519  * @return the current wait time between gestures. 0xFF on error.
01520  */
01521 uint8_t SparkFun_APDS9960::getGestureWaitTime()
01522 {
01523     uint8_t val;
01524     
01525     /* Read value from GCONF2 register */
01526     if( !wireReadDataByte(APDS9960_GCONF2, val) ) {
01527         return ERROR;
01528     }
01529     
01530     /* Mask out GWTIME bits */
01531     val &= 0x07;
01532     
01533     return val;
01534 }
01535 
01536 /**
01537  * @brief Sets the time in low power mode between gesture detections
01538  *
01539  * Value    Wait time
01540  *   0          0 ms
01541  *   1          2.8 ms
01542  *   2          5.6 ms
01543  *   3          8.4 ms
01544  *   4         14.0 ms
01545  *   5         22.4 ms
01546  *   6         30.8 ms
01547  *   7         39.2 ms
01548  *
01549  * @param[in] the value for the wait time
01550  * @return True if operation successful. False otherwise.
01551  */
01552 bool SparkFun_APDS9960::setGestureWaitTime(uint8_t time)
01553 {
01554     uint8_t val;
01555     
01556     /* Read value from GCONF2 register */
01557     if( !wireReadDataByte(APDS9960_GCONF2, val) ) {
01558         return false;
01559     }
01560     
01561     /* Set bits in register to given value */
01562     time &= 0x07;
01563     val &= 0xF8;
01564     val |= time;
01565     
01566     /* Write register value back into GCONF2 register */
01567     if( !wireWriteDataByte(APDS9960_GCONF2, val) ) {
01568         return false;
01569     }
01570     
01571     return true;
01572 }
01573 
01574 /**
01575  * @brief Gets the low threshold for ambient light interrupts
01576  *
01577  * @param[out] threshold current low threshold stored on the APDS-9960
01578  * @return True if operation successful. False otherwise.
01579  */
01580 bool SparkFun_APDS9960::getLightIntLowThreshold(uint16_t &threshold)
01581 {
01582     uint8_t val_byte;
01583     threshold = 0;
01584     
01585     /* Read value from ambient light low threshold, low byte register */
01586     if( !wireReadDataByte(APDS9960_AILTL, val_byte) ) {
01587         return false;
01588     }
01589     threshold = val_byte;
01590     
01591     /* Read value from ambient light low threshold, high byte register */
01592     if( !wireReadDataByte(APDS9960_AILTH, val_byte) ) {
01593         return false;
01594     }
01595     threshold = threshold + ((uint16_t)val_byte << 8);
01596     
01597     return true;
01598 }
01599 
01600 /**
01601  * @brief Sets the low threshold for ambient light interrupts
01602  *
01603  * @param[in] threshold low threshold value for interrupt to trigger
01604  * @return True if operation successful. False otherwise.
01605  */
01606 bool SparkFun_APDS9960::setLightIntLowThreshold(uint16_t threshold)
01607 {
01608     uint8_t val_low;
01609     uint8_t val_high;
01610     
01611     /* Break 16-bit threshold into 2 8-bit values */
01612     val_low = threshold & 0x00FF;
01613     val_high = (threshold & 0xFF00) >> 8;
01614     
01615     /* Write low byte */
01616     if( !wireWriteDataByte(APDS9960_AILTL, val_low) ) {
01617         return false;
01618     }
01619     
01620     /* Write high byte */
01621     if( !wireWriteDataByte(APDS9960_AILTH, val_high) ) {
01622         return false;
01623     }
01624     
01625     return true;
01626 }
01627 
01628 /**
01629  * @brief Gets the high threshold for ambient light interrupts
01630  *
01631  * @param[out] threshold current low threshold stored on the APDS-9960
01632  * @return True if operation successful. False otherwise.
01633  */
01634 bool SparkFun_APDS9960::getLightIntHighThreshold(uint16_t &threshold)
01635 {
01636     uint8_t val_byte;
01637     threshold = 0;
01638     
01639     /* Read value from ambient light high threshold, low byte register */
01640     if( !wireReadDataByte(APDS9960_AIHTL, val_byte) ) {
01641         return false;
01642     }
01643     threshold = val_byte;
01644     
01645     /* Read value from ambient light high threshold, high byte register */
01646     if( !wireReadDataByte(APDS9960_AIHTH, val_byte) ) {
01647         return false;
01648     }
01649     threshold = threshold + ((uint16_t)val_byte << 8);
01650     
01651     return true;
01652 }
01653 
01654 /**
01655  * @brief Sets the high threshold for ambient light interrupts
01656  *
01657  * @param[in] threshold high threshold value for interrupt to trigger
01658  * @return True if operation successful. False otherwise.
01659  */
01660 bool SparkFun_APDS9960::setLightIntHighThreshold(uint16_t threshold)
01661 {
01662     uint8_t val_low;
01663     uint8_t val_high;
01664     
01665     /* Break 16-bit threshold into 2 8-bit values */
01666     val_low = threshold & 0x00FF;
01667     val_high = (threshold & 0xFF00) >> 8;
01668     
01669     /* Write low byte */
01670     if( !wireWriteDataByte(APDS9960_AIHTL, val_low) ) {
01671         return false;
01672     }
01673     
01674     /* Write high byte */
01675     if( !wireWriteDataByte(APDS9960_AIHTH, val_high) ) {
01676         return false;
01677     }
01678     
01679     return true;
01680 }
01681 
01682 /**
01683  * @brief Gets the low threshold for proximity interrupts
01684  *
01685  * @param[out] threshold current low threshold stored on the APDS-9960
01686  * @return True if operation successful. False otherwise.
01687  */
01688 bool SparkFun_APDS9960::getProximityIntLowThreshold(uint8_t &threshold)
01689 {
01690     threshold = 0;
01691     
01692     /* Read value from proximity low threshold register */
01693     if( !wireReadDataByte(APDS9960_PILT, threshold) ) {
01694         return false;
01695     }
01696     
01697     return true;
01698 }
01699 
01700 /**
01701  * @brief Sets the low threshold for proximity interrupts
01702  *
01703  * @param[in] threshold low threshold value for interrupt to trigger
01704  * @return True if operation successful. False otherwise.
01705  */
01706 bool SparkFun_APDS9960::setProximityIntLowThreshold(uint8_t threshold)
01707 {
01708     
01709     /* Write threshold value to register */
01710     if( !wireWriteDataByte(APDS9960_PILT, threshold) ) {
01711         return false;
01712     }
01713     
01714     return true;
01715 }
01716     
01717 /**
01718  * @brief Gets the high threshold for proximity interrupts
01719  *
01720  * @param[out] threshold current low threshold stored on the APDS-9960
01721  * @return True if operation successful. False otherwise.
01722  */
01723 bool SparkFun_APDS9960::getProximityIntHighThreshold(uint8_t &threshold)
01724 {
01725     threshold = 0;
01726     
01727     /* Read value from proximity low threshold register */
01728     if( !wireReadDataByte(APDS9960_PIHT, threshold) ) {
01729         return false;
01730     }
01731     
01732     return true;
01733 }
01734 
01735 /**
01736  * @brief Sets the high threshold for proximity interrupts
01737  *
01738  * @param[in] threshold high threshold value for interrupt to trigger
01739  * @return True if operation successful. False otherwise.
01740  */
01741 bool SparkFun_APDS9960::setProximityIntHighThreshold(uint8_t threshold)
01742 {
01743     
01744     /* Write threshold value to register */
01745     if( !wireWriteDataByte(APDS9960_PIHT, threshold) ) {
01746         return false;
01747     }
01748     
01749     return true;
01750 }
01751 
01752 /**
01753  * @brief Gets if ambient light interrupts are enabled or not
01754  *
01755  * @return 1 if interrupts are enabled, 0 if not. 0xFF on error.
01756  */
01757 uint8_t SparkFun_APDS9960::getAmbientLightIntEnable()
01758 {
01759     uint8_t val;
01760     
01761     /* Read value from ENABLE register */
01762     if( !wireReadDataByte(APDS9960_ENABLE, val) ) {
01763         return ERROR;
01764     }
01765     
01766     /* Shift and mask out AIEN bit */
01767     val = (val >> 4) & 0x01;
01768     
01769     return val;
01770 }
01771 
01772 /**
01773  * @brief Turns ambient light interrupts on or off
01774  *
01775  * @param[in] enable 1 to enable interrupts, 0 to turn them off
01776  * @return True if operation successful. False otherwise.
01777  */
01778 bool SparkFun_APDS9960::setAmbientLightIntEnable(uint8_t enable)
01779 {
01780     uint8_t val;
01781     
01782     /* Read value from ENABLE register */
01783     if( !wireReadDataByte(APDS9960_ENABLE, val) ) {
01784         return false;
01785     }
01786     
01787     /* Set bits in register to given value */
01788     enable &= 0x01;
01789     enable = enable << 4;
01790     val &= 0xEF;
01791     val |= enable;
01792     
01793     /* Write register value back into ENABLE register */
01794     if( !wireWriteDataByte(APDS9960_ENABLE, val) ) {
01795         return false;
01796     }
01797     
01798     return true;
01799 }
01800 
01801 /**
01802  * @brief Gets if proximity interrupts are enabled or not
01803  *
01804  * @return 1 if interrupts are enabled, 0 if not. 0xFF on error.
01805  */
01806 uint8_t SparkFun_APDS9960::getProximityIntEnable()
01807 {
01808     uint8_t val;
01809     
01810     /* Read value from ENABLE register */
01811     if( !wireReadDataByte(APDS9960_ENABLE, val) ) {
01812         return ERROR;
01813     }
01814     
01815     /* Shift and mask out PIEN bit */
01816     val = (val >> 5) & 0x01;
01817     
01818     return val;
01819 }
01820 
01821 /**
01822  * @brief Turns proximity interrupts on or off
01823  *
01824  * @param[in] enable 1 to enable interrupts, 0 to turn them off
01825  * @return True if operation successful. False otherwise.
01826  */
01827 bool SparkFun_APDS9960::setProximityIntEnable(uint8_t enable)
01828 {
01829     uint8_t val;
01830     
01831     /* Read value from ENABLE register */
01832     if( !wireReadDataByte(APDS9960_ENABLE, val) ) {
01833         return false;
01834     }
01835     
01836     /* Set bits in register to given value */
01837     enable &= 0x01;
01838     enable = enable << 5;
01839     val &= 0xDF;
01840     val |= enable;
01841     
01842     /* Write register value back into ENABLE register */
01843     if( !wireWriteDataByte(APDS9960_ENABLE, val) ) {
01844         return false;
01845     }
01846     
01847     return true;
01848 }
01849 
01850 /**
01851  * @brief Gets if gesture interrupts are enabled or not
01852  *
01853  * @return 1 if interrupts are enabled, 0 if not. 0xFF on error.
01854  */
01855 uint8_t SparkFun_APDS9960::getGestureIntEnable()
01856 {
01857     uint8_t val;
01858     
01859     /* Read value from GCONF4 register */
01860     if( !wireReadDataByte(APDS9960_GCONF4, val) ) {
01861         return ERROR;
01862     }
01863     
01864     /* Shift and mask out GIEN bit */
01865     val = (val >> 1) & 0x01;
01866     
01867     return val;
01868 }
01869 
01870 /**
01871  * @brief Turns gesture-related interrupts on or off
01872  *
01873  * @param[in] enable 1 to enable interrupts, 0 to turn them off
01874  * @return True if operation successful. False otherwise.
01875  */
01876 bool SparkFun_APDS9960::setGestureIntEnable(uint8_t enable)
01877 {
01878     uint8_t val;
01879     
01880     /* Read value from GCONF4 register */
01881     if( !wireReadDataByte(APDS9960_GCONF4, val) ) {
01882         return false;
01883     }
01884     
01885     /* Set bits in register to given value */
01886     enable &= 0x01;
01887     enable = enable << 1;
01888     val &= 0xFD;
01889     val |= enable;
01890     
01891     /* Write register value back into GCONF4 register */
01892     if( !wireWriteDataByte(APDS9960_GCONF4, val) ) {
01893         return false;
01894     }
01895     
01896     return true;
01897 }
01898 
01899 /**
01900  * @brief Clears the ambient light interrupt
01901  *
01902  * @return True if operation completed successfully. False otherwise.
01903  */
01904 bool SparkFun_APDS9960::clearAmbientLightInt()
01905 {
01906     uint8_t throwaway;
01907     if( !wireReadDataByte(APDS9960_AICLEAR, throwaway) ) {
01908         return false;
01909     }
01910     
01911     return true;
01912 }
01913 
01914 /**
01915  * @brief Clears the proximity interrupt
01916  *
01917  * @return True if operation completed successfully. False otherwise.
01918  */
01919 bool SparkFun_APDS9960::clearProximityInt()
01920 {
01921     uint8_t throwaway;
01922     if( !wireReadDataByte(APDS9960_PICLEAR, throwaway) ) {
01923         return false;
01924     }
01925     
01926     return true;
01927 }
01928 
01929 /**
01930  * @brief Tells if the gesture state machine is currently running
01931  *
01932  * @return 1 if gesture state machine is running, 0 if not. 0xFF on error.
01933  */
01934 uint8_t SparkFun_APDS9960::getGestureMode()
01935 {
01936     uint8_t val;
01937     
01938     /* Read value from GCONF4 register */
01939     if( !wireReadDataByte(APDS9960_GCONF4, val) ) {
01940         return ERROR;
01941     }
01942     
01943     /* Mask out GMODE bit */
01944     val &= 0x01;
01945     
01946     return val;
01947 }
01948 
01949 /**
01950  * @brief Tells the state machine to either enter or exit gesture state machine
01951  *
01952  * @param[in] mode 1 to enter gesture state machine, 0 to exit.
01953  * @return True if operation successful. False otherwise.
01954  */
01955 bool SparkFun_APDS9960::setGestureMode(uint8_t mode)
01956 {
01957     uint8_t val;
01958     
01959     /* Read value from GCONF4 register */
01960     if( !wireReadDataByte(APDS9960_GCONF4, val) ) {
01961         return false;
01962     }
01963     
01964     /* Set bits in register to given value */
01965     mode &= 0x01;
01966     val &= 0xFE;
01967     val |= mode;
01968     
01969     /* Write register value back into GCONF4 register */
01970     if( !wireWriteDataByte(APDS9960_GCONF4, val) ) {
01971         return false;
01972     }
01973     
01974     return true;
01975 }
01976 
01977 /*******************************************************************************
01978  * Raw I2C Reads and Writes
01979  ******************************************************************************/
01980 
01981 /**
01982  * @brief Writes a single byte to the I2C device (no register)
01983  *
01984  * @param[in] val the 1-byte value to write to the I2C device
01985  * @return True if successful write operation. False otherwise.
01986  */
01987 bool SparkFun_APDS9960::wireWriteByte(uint8_t val)
01988 {
01989     //char wr_data[1];
01990     //wr_data[0] = (char)val;
01991     if (apds_i2c.write(APDS9960_I2C_ADDR8, (char *)&val, 1) != 0) return false;
01992     return true;
01993 }
01994 
01995 /**
01996  * @brief Writes a single byte to the I2C device and specified register
01997  *
01998  * @param[in] reg the register in the I2C device to write to
01999  * @param[in] val the 1-byte value to write to the I2C device
02000  * @return True if successful write operation. False otherwise.
02001  */
02002 bool SparkFun_APDS9960::wireWriteDataByte(uint8_t reg, uint8_t val)
02003 {
02004     char wr_data[2];
02005     wr_data[0] = (char)reg;
02006     wr_data[1] = (char)val;
02007     if (apds_i2c.write(APDS9960_I2C_ADDR8, wr_data, 2) != 0) return false;
02008     return true;
02009 }
02010 
02011 /**
02012  * @brief Reads a single byte from the I2C device and specified register
02013  *
02014  * @param[in] reg the register to read from
02015  * @param[out] the value returned from the register
02016  * @return True if successful read operation. False otherwise.
02017  */
02018 bool SparkFun_APDS9960::wireReadDataByte(uint8_t reg, uint8_t &val)
02019 {
02020     
02021     /* Indicate which register we want to read from */
02022     if (apds_i2c.write(APDS9960_I2C_ADDR8, (char *)&reg, 1, true) != 0) return false;
02023     
02024     /* Read from register */
02025     if (apds_i2c.read(APDS9960_I2C_ADDR8, (char *)&val, 1) != 0) return false;
02026     return true;
02027 }
02028 
02029 /**
02030  * @brief Reads a block (array) of bytes from the I2C device and register
02031  *
02032  * @param[in] reg the register to read from
02033  * @param[out] val pointer to the beginning of the data
02034  * @param[in] len number of bytes to read
02035  * @return Number of bytes read. -1 on read error.
02036  */
02037 int SparkFun_APDS9960::wireReadDataBlock(   uint8_t reg, 
02038                                         uint8_t *val, 
02039                                         unsigned int len)
02040 {
02041     //unsigned char i = 0;
02042     
02043     /* Indicate which register we want to read from */
02044     if (apds_i2c.write(APDS9960_I2C_ADDR8, (char *)&reg, 1, true) != 0) return -1;
02045     
02046     /* Read block data */
02047     if (apds_i2c.read(APDS9960_I2C_ADDR8, (char *)val, len) != 0) return -1;
02048 
02049     return len;
02050 }