/* ----------------------------------------------------------------------------*
 *
 *  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;
        }
    }
}
Example #2
0
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 */