Uses the APDS_9960 Digital Proximity, Ambient Light, RGB and Gesture Sensor library to play detected gesture sounds on a speaker from the SDcard
Dependencies: mbed SDFileSystem wave_player
Revision 7:0564c6faf8aa, committed 2015-03-06
- Comitter:
- kbhagat6
- Date:
- Fri Mar 06 19:35:24 2015 +0000
- Parent:
- 6:687dff16904e
- Child:
- 8:6fa15d4e31fb
- Commit message:
- added more functions and reorgnanized
Changed in this revision
glibr.cpp | Show annotated file Show diff for this revision Revisions of this file |
--- a/glibr.cpp Fri Mar 06 07:20:24 2015 +0000 +++ b/glibr.cpp Fri Mar 06 19:35:24 2015 +0000 @@ -125,7 +125,40 @@ return id; } +#if 0 + /* Gesture config register dump */ + uint8_t reg; + uint8_t val; + + for(reg = 0x80; reg <= 0xAF; reg++) { + if( (reg != 0x82) && \ + (reg != 0x8A) && \ + (reg != 0x91) && \ + (reg != 0xA8) && \ + (reg != 0xAC) && \ + (reg != 0xAD) ) + { + val= I2CreadByte(APDS9960_I2C_ADDR, reg); + if(val==ERROR){ + printf("ERROR"); + } + /* + print(reg, HEX); + print(": 0x"); + println(val, HEX);*/ + } + } + for(reg = 0xE4; reg <= 0xE7; reg++) { + val= I2CreadByte(APDS9960_I2C_ADDR, reg); + Serial.print(reg, HEX); + Serial.print(": 0x"); + Serial.println(val, HEX); + } +#endif + + return true; +} @@ -182,30 +215,7 @@ return val; } -bool glibr::setLEDDrive(uint8_t drive) -{ - uint8_t val; - - /* Read value from CONTROL register */ - val=I2CreadByte(APDS9960_I2C_ADDR,APDS9960_CONTROL); - if(val==ERROR){ - return false; - } - /* Set bits in register to given value */ - drive &= 0x03; - drive = drive << 6; - //val &= 0b00111111; - val &= 0x3F; - val |= drive; - - /* Write register value back into CONTROL register */ - if( I2CwriteByte(APDS9960_I2C_ADDR,APDS9960_CONTROL, val) ) { - return false; - } - - return true; -} bool glibr::enableLightSensor(bool interrupts) { @@ -716,6 +726,331 @@ gesture_motion_ = DIR_NONE; } +bool glibr::processGestureData() +{ + uint8_t u_first = 0; + uint8_t d_first = 0; + uint8_t l_first = 0; + uint8_t r_first = 0; + uint8_t u_last = 0; + uint8_t d_last = 0; + uint8_t l_last = 0; + uint8_t r_last = 0; + int ud_ratio_first; + int lr_ratio_first; + int ud_ratio_last; + int lr_ratio_last; + int ud_delta; + int lr_delta; + int i; + + /* If we have less than 4 total gestures, that's not enough */ + if( gesture_data_.total_gestures <= 4 ) { + return false; + } + + /* Check to make sure our data isn't out of bounds */ + if( (gesture_data_.total_gestures <= 32) && \ + (gesture_data_.total_gestures > 0) ) { + + /* Find the first value in U/D/L/R above the threshold */ + for( i = 0; i < gesture_data_.total_gestures; i++ ) { + if( (gesture_data_.u_data[i] > GESTURE_THRESHOLD_OUT) && + (gesture_data_.d_data[i] > GESTURE_THRESHOLD_OUT) && + (gesture_data_.l_data[i] > GESTURE_THRESHOLD_OUT) && + (gesture_data_.r_data[i] > GESTURE_THRESHOLD_OUT) ) { + + u_first = gesture_data_.u_data[i]; + d_first = gesture_data_.d_data[i]; + l_first = gesture_data_.l_data[i]; + r_first = gesture_data_.r_data[i]; + break; + } + } + + /* If one of the _first values is 0, then there is no good data */ + if( (u_first == 0) || (d_first == 0) || \ + (l_first == 0) || (r_first == 0) ) { + + return false; + } + /* Find the last value in U/D/L/R above the threshold */ + for( i = gesture_data_.total_gestures - 1; i >= 0; i-- ) { +/* #if DEBUG + Serial.print(F("Finding last: ")); + Serial.print(F("U:")); + Serial.print(gesture_data_.u_data[i]); + Serial.print(F(" D:")); + Serial.print(gesture_data_.d_data[i]); + Serial.print(F(" L:")); + Serial.print(gesture_data_.l_data[i]); + Serial.print(F(" R:")); + Serial.println(gesture_data_.r_data[i]); +#endif */ + if( (gesture_data_.u_data[i] > GESTURE_THRESHOLD_OUT) && + (gesture_data_.d_data[i] > GESTURE_THRESHOLD_OUT) && + (gesture_data_.l_data[i] > GESTURE_THRESHOLD_OUT) && + (gesture_data_.r_data[i] > GESTURE_THRESHOLD_OUT) ) { + + u_last = gesture_data_.u_data[i]; + d_last = gesture_data_.d_data[i]; + l_last = gesture_data_.l_data[i]; + r_last = gesture_data_.r_data[i]; + break; + } + } + } + + /* Calculate the first vs. last ratio of up/down and left/right */ + ud_ratio_first = ((u_first - d_first) * 100) / (u_first + d_first); + lr_ratio_first = ((l_first - r_first) * 100) / (l_first + r_first); + ud_ratio_last = ((u_last - d_last) * 100) / (u_last + d_last); + lr_ratio_last = ((l_last - r_last) * 100) / (l_last + r_last); + +/* #if DEBUG + Serial.print(F("Last Values: ")); + Serial.print(F("U:")); + Serial.print(u_last); + Serial.print(F(" D:")); + Serial.print(d_last); + Serial.print(F(" L:")); + Serial.print(l_last); + Serial.print(F(" R:")); + Serial.println(r_last); + + Serial.print(F("Ratios: ")); + Serial.print(F("UD Fi: ")); + Serial.print(ud_ratio_first); + Serial.print(F(" UD La: ")); + Serial.print(ud_ratio_last); + Serial.print(F(" LR Fi: ")); + Serial.print(lr_ratio_first); + Serial.print(F(" LR La: ")); + Serial.println(lr_ratio_last); +#endif */ + + /* Determine the difference between the first and last ratios */ + ud_delta = ud_ratio_last - ud_ratio_first; + lr_delta = lr_ratio_last - lr_ratio_first; + +/* #if DEBUG + Serial.print("Deltas: "); + Serial.print("UD: "); + Serial.print(ud_delta); + Serial.print(" LR: "); + Serial.println(lr_delta); +#endif */ + + /* Accumulate the UD and LR delta values */ + gesture_ud_delta_ += ud_delta; + gesture_lr_delta_ += lr_delta; + +/* #if DEBUG + Serial.print("Accumulations: "); + Serial.print("UD: "); + Serial.print(gesture_ud_delta_); + Serial.print(" LR: "); + Serial.println(gesture_lr_delta_); +#endif */ + + /* Determine U/D gesture */ + if( gesture_ud_delta_ >= GESTURE_SENSITIVITY_1 ) { + gesture_ud_count_ = 1; + } else if( gesture_ud_delta_ <= -GESTURE_SENSITIVITY_1 ) { + gesture_ud_count_ = -1; + } else { + gesture_ud_count_ = 0; + } + + /* Determine L/R gesture */ + if( gesture_lr_delta_ >= GESTURE_SENSITIVITY_1 ) { + gesture_lr_count_ = 1; + } else if( gesture_lr_delta_ <= -GESTURE_SENSITIVITY_1 ) { + gesture_lr_count_ = -1; + } else { + gesture_lr_count_ = 0; + } + + /* Determine Near/Far gesture */ + if( (gesture_ud_count_ == 0) && (gesture_lr_count_ == 0) ) { + if( (abs(ud_delta) < GESTURE_SENSITIVITY_2) && \ + (abs(lr_delta) < GESTURE_SENSITIVITY_2) ) { + + if( (ud_delta == 0) && (lr_delta == 0) ) { + gesture_near_count_++; + } else if( (ud_delta != 0) || (lr_delta != 0) ) { + gesture_far_count_++; + } + + if( (gesture_near_count_ >= 10) && (gesture_far_count_ >= 2) ) { + if( (ud_delta == 0) && (lr_delta == 0) ) { + gesture_state_ = NEAR_STATE; + } else if( (ud_delta != 0) && (lr_delta != 0) ) { + gesture_state_ = FAR_STATE; + } + return true; + } + } + } else { + if( (abs(ud_delta) < GESTURE_SENSITIVITY_2) && \ + (abs(lr_delta) < GESTURE_SENSITIVITY_2) ) { + + if( (ud_delta == 0) && (lr_delta == 0) ) { + gesture_near_count_++; + } + + if( gesture_near_count_ >= 10 ) { + gesture_ud_count_ = 0; + gesture_lr_count_ = 0; + gesture_ud_delta_ = 0; + gesture_lr_delta_ = 0; + } + } + } + +/* #if DEBUG + Serial.print("UD_CT: "); + Serial.print(gesture_ud_count_); + Serial.print(" LR_CT: "); + Serial.print(gesture_lr_count_); + Serial.print(" NEAR_CT: "); + Serial.print(gesture_near_count_); + Serial.print(" FAR_CT: "); + Serial.println(gesture_far_count_); + Serial.println("----------"); +#endif */ + + return false; +} + +/** + * @brief Determines swipe direction or near/far state + * + * @return True if near/far event. False otherwise. + */ +bool APDS9960::decodeGesture() +{ + /* Return if near or far event is detected */ + if( gesture_state_ == NEAR_STATE ) { + gesture_motion_ = DIR_NEAR; + return true; + } else if ( gesture_state_ == FAR_STATE ) { + gesture_motion_ = DIR_FAR; + return true; + } + + /* Determine swipe direction */ + if( (gesture_ud_count_ == -1) && (gesture_lr_count_ == 0) ) { + gesture_motion_ = DIR_UP; + } else if( (gesture_ud_count_ == 1) && (gesture_lr_count_ == 0) ) { + gesture_motion_ = DIR_DOWN; + } else if( (gesture_ud_count_ == 0) && (gesture_lr_count_ == 1) ) { + gesture_motion_ = DIR_RIGHT; + } else if( (gesture_ud_count_ == 0) && (gesture_lr_count_ == -1) ) { + gesture_motion_ = DIR_LEFT; + } else if( (gesture_ud_count_ == -1) && (gesture_lr_count_ == 1) ) { + if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) { + gesture_motion_ = DIR_UP; + } else { + gesture_motion_ = DIR_RIGHT; + } + } else if( (gesture_ud_count_ == 1) && (gesture_lr_count_ == -1) ) { + if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) { + gesture_motion_ = DIR_DOWN; + } else { + gesture_motion_ = DIR_LEFT; + } + } else if( (gesture_ud_count_ == -1) && (gesture_lr_count_ == -1) ) { + if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) { + gesture_motion_ = DIR_UP; + } else { + gesture_motion_ = DIR_LEFT; + } + } else if( (gesture_ud_count_ == 1) && (gesture_lr_count_ == 1) ) { + if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) { + gesture_motion_ = DIR_DOWN; + } else { + gesture_motion_ = DIR_RIGHT; + } + } else { + return false; + } + + return true; +} + +/******************************************************************************* + * Getters and setters for register values + ******************************************************************************/ + +/** + * @brief Returns the lower threshold for proximity detection + * + * @return lower threshold + */ + + uint8_t glibr::getProxIntLowThresh() +{ + uint8_t val; + + /* Read value from PILT register */ + /* if( !wireReadDataByte(APDS9960_PILT, val) ) { + val = 0; + }*/ + val=I2CreadByte(APDS9960_I2C_ADDR,APDS9960_PILT); + if(val==ERROR){ + val=0; + } + + return val; +} + + bool glibr::setProxIntLowThresh(uint8_t threshold) +{ + if( I2CwriteByte(APDS9960_I2C_ADDR,APDS9960_PILT, threshold) ) { + return false; + } + + return true; +} + +bool glibr::setProxIntHighThresh(uint8_t threshold) +{ + + if( I2CwriteByte(APDS9960_I2C_ADDR,APDS9960_PIHT, threshold) ) { + return false; + } + + return true; +} + + + +bool glibr::setLEDDrive(uint8_t drive) +{ + uint8_t val; + + /* Read value from CONTROL register */ + + val=I2CreadByte(APDS9960_I2C_ADDR,APDS9960_CONTROL); + if(val==ERROR){ + return false; + } + /* Set bits in register to given value */ + drive &= 0x03; + drive = drive << 6; + //val &= 0b00111111; + val &= 0x3F; + val |= drive; + + /* Write register value back into CONTROL register */ + if( I2CwriteByte(APDS9960_I2C_ADDR,APDS9960_CONTROL, val) ) { + return false; + } + + return true; +} + bool glibr::setProximityGain(uint8_t drive) @@ -770,26 +1105,6 @@ } -bool setProxIntLowThresh(uint8_t threshold) -{ - if( I2CwriteByte(APDS9960_I2C_ADDR,APDS9960_PILT, threshold) ) { - return false; - } - - return true; -} - -bool glibr::setProxIntHighThresh(uint8_t threshold) -{ - - if( I2CwriteByte(APDS9960_I2C_ADDR,APDS9960_PIHT, threshold) ) { - return false; - } - - return true; -} - -