/* ----------------------------------------------------------------------------* * * Function Name : readGesture(void) * * Description :Processes a gesture event and returns best guessed gesture * * Input : None * * Output : None * * Return : Number corresponding to gesture. -1 on error. * ----------------------------------------------------------------------------* * Authors: Sarath S * Date: May 17, 2017 * ---------------------------------------------------------------------------*/ int readGesture(void) { uint8_t fifo_level = 0; int bytes_read = 0; uint8_t fifo_data[128]; uint8_t gstatus; int motion; int i; /* Make sure that power and gesture is on and data is valid */ if( !isGestureAvailable() || !(getMode() & 0x41) ) { return DIR_NONE; } /* Keep looping as long as gesture data is valid */ while(1) { /* Wait some time to collect next batch of FIFO data */ delayms(FIFO_PAUSE_TIME); /* Get the contents of the STATUS register. Is data still valid? */ if( !i2c1_read(APDS9960_GSTATUS, &gstatus,1) ) { return ERROR; } /* If we have valid data, read in FIFO */ if( (gstatus & APDS9960_GVALID) == APDS9960_GVALID ) { /* Read the current FIFO level */ if( !i2c1_read(APDS9960_GFLVL, &fifo_level,1) ) { return ERROR; } #if DEBUGPRINT debugPutString("FIFO Level: "); debugPutChar(fifo_level); #endif /* If there's stuff in the FIFO, read it into our data block */ if( fifo_level > 0) { bytes_read = i2c1_read(APDS9960_GFIFO_U, fifo_data, (fifo_level * 4) ); if( bytes_read == -1 ) { return ERROR; } #if DEBUGPRINT debugPutString("FIFO Dump: "); for ( i = 0; i < bytes_read; i++ ) { debugPutChar(fifo_data[i]); debugPutString(" "); } debugPutString("\r\n"); #endif /* If at least 1 set of data, sort the data into U/D/L/R */ if( bytes_read >= 4 ) { for( i = 0; i < bytes_read; i += 4 ) { gesture_data_.u_data[gesture_data_.index] = \ fifo_data[i + 0]; gesture_data_.d_data[gesture_data_.index] = \ fifo_data[i + 1]; gesture_data_.l_data[gesture_data_.index] = \ fifo_data[i + 2]; gesture_data_.r_data[gesture_data_.index] = \ fifo_data[i + 3]; gesture_data_.index++; gesture_data_.total_gestures++; } #if DEBUGPRINT debugPutString("Up Data: "); for ( i = 0; i < gesture_data_.total_gestures; i++ ) { debugPutChar(gesture_data_.u_data[i]); debugPutString(" "); } debugPutString("\r\n"); #endif /* Filter and process gesture data. Decode near/far state */ if( processGestureData() ) { if( decodeGesture() ) { //***TODO: U-Turn Gestures #if DEBUGPRINT debugPutChar(gesture_motion_); #endif } } /* Reset data */ gesture_data_.index = 0; gesture_data_.total_gestures = 0; } } } else { /* Determine best guessed gesture and clean up */ delayms(FIFO_PAUSE_TIME); decodeGesture(); motion = gesture_motion_; #if DEBUGPRINT debugPutString("END: "); debugPutChar(gesture_motion_); #endif resetGestureParameters(); return motion; } } }
void debugSendString(char *s) { while (*s) { debugPutChar(*s++); } }
/* ----------------------------------------------------------------------------* * * Function Name : processGestureData(void) * * Description :Processes the raw gesture data to determine swipe direction * * Input : None * * Output : None * * Return : True if near or far state seen. False otherwise. * ----------------------------------------------------------------------------* * Authors: Sarath S * Date: May 17, 2017 * ---------------------------------------------------------------------------*/ int processGestureData(void) { 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 DEBUGPRINT debugPutString("Finding last: "); debugPutString("U:"); debugPutChar(gesture_data_.u_data[i]); debugPutString(" D:"); debugPutChar(gesture_data_.d_data[i]); debugPutString(" L:"); debugPutChar(gesture_data_.l_data[i]); debugPutString(" R:"); debugPutChar(gesture_data_.r_data[i]); debugPutString("\r\n"); #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 DEBUGPRINT debugPutString("Last Values: "); debugPutString("U:"); debugPutChar(u_last); debugPutString(" D:"); debugPutChar(d_last); debugPutString(" L:"); debugPutChar(l_last); debugPutString(" R:"); debugPutChar(r_last); debugPutString("\r\n"); debugPutString("Ratios: "); debugPutString("UD Fi: "); debugPutChar(ud_ratio_first); debugPutString(" UD La: "); debugPutChar(ud_ratio_last); debugPutString(" LR Fi: "); debugPutChar(lr_ratio_first); debugPutString(" LR La: "); debugPutChar(lr_ratio_last); debugPutString("\r\n"); #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 DEBUGPRINT debugPutString("Deltas: "); debugPutString("UD: "); debugPutChar(ud_delta); debugPutString(" LR: "); debugPutChar(lr_delta); debugPutString("\r\n"); #endif /* Accumulate the UD and LR delta values */ gesture_ud_delta_ += ud_delta; gesture_lr_delta_ += lr_delta; #if DEBUGPRINT debugPutString("Accumulations: "); debugPutString("UD: "); debugPutChar(gesture_ud_delta_); debugPutString(" LR: "); debugPutChar(gesture_lr_delta_); debugPutString("\r\n"); #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 DEBUGPRINT debugPutString("UD_CT: "); debugPutChar(gesture_ud_count_); debugPutString(" LR_CT: "); debugPutChar(gesture_lr_count_); debugPutString(" NEAR_CT: "); debugPutChar(gesture_near_count_); debugPutString(" FAR_CT: "); debugPutChar(gesture_far_count_); debugPutString("----------"); #endif return false; }/* End of this function */