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

Files at this revision

API Documentation at this revision

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