/* ----------------------------------------------------------------------------* * * Function Name : setMode(uint8_t mode, uint8_t enable) * * Description :Reads and returns the contents of the ENABLE register * * Input : mode which feature to enable,enable ON (1) or OFF (0) * * Output : None * * Return : Contents of the ENABLE register. 0xFF if error. * ----------------------------------------------------------------------------* * Authors: Sarath S * Date: May 17, 2017 * ---------------------------------------------------------------------------*/ uint8_t getMode(void) { uint8_t enable_value; /* Read current ENABLE register */ if( !i2c1_read(APDS9960_ENABLE,&enable_value,1) ) { return ERROR; } return enable_value; }/* End of this function */
void task_telemetry(void){ OS_Stop(); user_debug_msg(STR_TELEMETRY_QA "Starting."); #if 1 OS_Delay(250); // structure that will contain the results typedef struct{ uint64_t passed; uint64_t failed; uint16_t test_num; // Last test number uint16_t failed_num; uint16_t failed_res; // Non-zero when/if test fails }selftest_res_t; selftest_res_t test; //unsigned char TestData[sizeof(selftest_res)+13]; supmcu_selftest_start(TRUE); OS_Delay(250); supmcu_selftest_tel(TRUE); i2c1_read(I2C_ADDR.g, &TEL_DATA[0], sizeof(test)+13); memcpy(&test.passed, &TEL_DATA[5],sizeof(uint64_t)); memcpy(&test.failed, &TEL_DATA[5+8],sizeof(uint64_t)); memcpy(&test.test_num, &TEL_DATA[5+8+8],sizeof(uint16_t)); memcpy(&test.failed_num, &TEL_DATA[5+8+8+2],sizeof(uint16_t)); memcpy(&test.failed_res, &TEL_DATA[5+8+8+2+2],sizeof(uint16_t)); //sprintf(strTmp,"pass %llu ; fail %llu; num %u; num_fail %u; res_fail %u",test.passed,test.failed, test.test_num, test.failed_num,test.failed_res); //user_debug_msg(strTmp); if(test.failed == 0){ sprintf(strTmp,"All selftests passed"); user_debug_msg(STR_TELEMETRY_QA "All selftests passed"); } else{ sprintf(strTmp,STR_TELEMETRY_QA "Failed %llu tests, last failed %u",test.failed,test.failed_num); user_debug_msg(strTmp); } while(1) { OS_Delay(250); } #endif }
// return: the read data int cs8556_i2c_read(int addr) { #ifdef CONFIG_KERNEL // return i2c_api_register_read(CS8556_ADDR, 2, addr); char buf = 0; vpp_i2c_read(CS8556_ID, CS8556_ADDR, addr, &buf, 1); return buf; #else uchar data = 0; i2c1_read(CS8556_ADDR, addr, 2, &data, 1); return data; #endif }
/* ----------------------------------------------------------------------------* * * Function Name : isGestureAvailable(void) * * Description :Determines if there is a gesture available for reading * * Input : None * * Output : None * * Return : True if gesture available. False otherwise. * ----------------------------------------------------------------------------* * Authors: Sarath S * Date: May 17, 2017 * ---------------------------------------------------------------------------*/ int isGestureAvailable(void) { uint8_t val; /* Read value from GSTATUS register */ if( !i2c1_read(APDS9960_GSTATUS, &val,1) ) { return ERROR; } /* Shift and mask out GVALID bit */ val &= APDS9960_GVALID; /* Return true/false based on GVALID bit */ if( val == 1) { return true; } else { return false; } }/* End of this function */
/* ----------------------------------------------------------------------------* * * Function Name : setGestureMode(uint8_t mode) * * Description :Tells the state machine to either enter or exit gesture state machine * * Input : mode 1 to enter gesture state machine, 0 to exit. * * Output : None * * Return : True if operation successful. False otherwise. * ----------------------------------------------------------------------------* * Authors: Sarath S * Date: May 17, 2017 * ---------------------------------------------------------------------------*/ int setGestureMode(uint8_t mode) { uint8_t val; /* Read value from GCONF4 register */ if( !i2c1_read(APDS9960_GCONF4, &val,1) ) { return false; } /* Set bits in register to given value */ mode &= 0x01; val &= 0xFE; val |= mode; /* Write register value back into GCONF4 register */ if( !i2c1_write(APDS9960_GCONF4, val) ) { return false; } return true; }/* End of this function */
/* ----------------------------------------------------------------------------* * * Function Name : setGestureWaitTime(uint8_t time) * * Description :Sets the time in low power mode between gesture detections * Value Wait time * 0 0 ms * 1 2.8 ms * 2 5.6 ms * 3 8.4 ms * 4 14.0 ms * 5 22.4 ms * 6 30.8 ms * 7 39.2 ms * Input : the value for the wait time * * Output : None * * Return : True if operation successful. False otherwise. * ----------------------------------------------------------------------------* * Authors: Sarath S * Date: May 17, 2017 * ---------------------------------------------------------------------------*/ int setGestureWaitTime(uint8_t time) { uint8_t val; /* Read value from GCONF2 register */ if( !i2c1_read(APDS9960_GCONF2, &val,1) ) { return false; } /* Set bits in register to given value */ time &= 0x07; val &= 0xF8; val |= time; /* Write register value back into GCONF2 register */ if( !i2c1_write(APDS9960_GCONF2, val) ) { return false; } return true; }/* End of this function */
/* ----------------------------------------------------------------------------* * * Function Name : setAmbientLightGain(uint8_t drive) * * Description :Sets the receiver gain for the ambient light sensor (ALS) * Value Gain * 0 1x * 1 4x * 2 16x * 3 64x * Input : drive the value (0-3) for the gain * * Output : None * * Return : True if operation successful. False otherwise. * ----------------------------------------------------------------------------* * Authors: Sarath S * Date: May 17, 2017 * ---------------------------------------------------------------------------*/ int setAmbientLightGain(uint8_t drive) { uint8_t val; /* Read value from CONTROL register */ if( !i2c1_read(APDS9960_CONTROL, &val,1) ) { return false; } /* Set bits in register to given value */ drive &= 0x03; val &= 0xFC; val |= drive; /* Write register value back into CONTROL register */ if( !i2c1_write(APDS9960_CONTROL, val) ) { return false; } return true; }/* End of this function */
/* ----------------------------------------------------------------------------* * * Function Name : setLEDBoost(uint8_t boost) * * Description :Sets the LED current boost value * Value Boost Current * 0 100% * 1 150% * 2 200% * 3 300% * Input : drive the value (0-3) for current boost (100-300%) * * Output : None * * Return : True if operation successful. False otherwise. * ----------------------------------------------------------------------------* * Authors: Sarath S * Date: May 17, 2017 * ---------------------------------------------------------------------------*/ int setLEDBoost(uint8_t boost) { uint8_t val; /* Read value from CONFIG2 register */ if( !i2c1_read(APDS9960_CONFIG2, &val,1) ) { return false; } /* Set bits in register to given value */ boost &= 0x03; boost = boost << 4; val &= 0xCF; val |= boost; /* Write register value back into CONFIG2 register */ if( !i2c1_write(APDS9960_CONFIG2, val) ) { return false; } return true; }/* End of this function */
/* ----------------------------------------------------------------------------* * * Function Name : setGestureGain(uint8_t gain) * * Description :Sets the gain of the photodiode during gesture mode * Value Gain * 0 1x * 1 2x * 2 4x * 3 8x * Input : gain the value for the photodiode gain * * Output : None * * Return : True if operation successful. False otherwise. * ----------------------------------------------------------------------------* * Authors: Sarath S * Date: May 17, 2017 * ---------------------------------------------------------------------------*/ int setGestureGain(uint8_t gain) { uint8_t val; /* Read value from GCONF2 register */ if( !i2c1_read(APDS9960_GCONF2, &val,1) ) { return false; } /* Set bits in register to given value */ gain &= 0x03; gain = gain << 5; val &= 0x9F; val |= gain; /* Write register value back into GCONF2 register */ if( !i2c1_write(APDS9960_GCONF2, val) ) { return false; } return true; }/* End of this function */
/* ----------------------------------------------------------------------------* * * Function Name : setGestureLEDDrive(uint8_t drive) * * Description :Sets the LED drive current during gesture mode * Value LED Current * 0 100 mA * 1 50 mA * 2 25 mA * 3 12.5 mA * * Input : drive the value for the LED drive current * * Output : None * * Return : True if operation successful. False otherwise. * ----------------------------------------------------------------------------* * Authors: Sarath S * Date: May 17, 2017 * ---------------------------------------------------------------------------*/ int setGestureLEDDrive(uint8_t drive) { uint8_t val; /* Read value from GCONF2 register */ if( !i2c1_read(APDS9960_GCONF2, &val,1) ) { return false; } /* Set bits in register to given value */ drive &= 0x03; drive = drive << 3; val &= 0xE7; val |= drive; /* Write register value back into GCONF2 register */ if( !i2c1_write(APDS9960_GCONF2, val) ) { return false; } return true; }/* End of this function */
/* ----------------------------------------------------------------------------* * * Function Name : setGestureIntEnable(uint8_t enable) * * Description :Turns gesture-related interrupts on or off * * Input : enable 1 to enable interrupts, 0 to turn them off * * Output : None * * Return : True if operation successful. False otherwise. * ----------------------------------------------------------------------------* * Authors: Sarath S * Date: May 17, 2017 * ---------------------------------------------------------------------------*/ int setGestureIntEnable(uint8_t enable) { uint8_t val; /* Read value from GCONF4 register */ if( !i2c1_read(APDS9960_GCONF4, &val,1) ) { return false; } /* Set bits in register to given value */ enable &= 0x01; enable = enable << 1; val &= 0xFD; val |= enable; /* Write register value back into GCONF4 register */ if( !i2c1_write(APDS9960_GCONF4, val) ) { return false; } return true; }/* End of this function */
/* ----------------------------------------------------------------------------* * * 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; } } }
/* ----------------------------------------------------------------------------* * * Function Name : apds9960init * * Description : Configures I2C communications and initializes registers to defaults * * Input : None * * Output : None * * Return : True if initialized successfully. False otherwise * ----------------------------------------------------------------------------* * Authors: Sarath S * Date: May 17, 2017 * ---------------------------------------------------------------------------*/ int apds9960init(void) { uint8_t id; //ledSetLeftLed(LED_ON); /* Initialize I2C */ I2C1_init(); delayms(700); /* Read ID register and check against known values for APDS-9960 */ if( !i2c1_read(APDS9960_ID, &id,1) ) { ledSetRightLed(LED_ON); return false; } ledSetLeftLed(LED_ON); if( !(id == APDS9960_ID_1 || id == APDS9960_ID_2) ) { return false; } /* Set ENABLE register to 0 (disable all features) */ if( !setMode(ALL, OFF) ) { return false; } /* Set default values for ambient light and proximity registers */ if( !i2c1_write(APDS9960_ATIME, DEFAULT_ATIME) ) { return false; } if( !i2c1_write(APDS9960_WTIME, DEFAULT_WTIME) ) { return false; } if( !i2c1_write(APDS9960_PPULSE, DEFAULT_PROX_PPULSE) ) { return false; } if( !i2c1_write(APDS9960_POFFSET_UR, DEFAULT_POFFSET_UR) ) { return false; } if( !i2c1_write(APDS9960_POFFSET_DL, DEFAULT_POFFSET_DL) ) { return false; } if( !i2c1_write(APDS9960_CONFIG1, DEFAULT_CONFIG1) ) { return false; } if( !setLEDDrive(DEFAULT_LDRIVE) ) { return false; } if( !setProximityGain(DEFAULT_PGAIN) ) { return false; } if( !setAmbientLightGain(DEFAULT_AGAIN) ) { return false; } if( !setProxIntLowThresh(DEFAULT_PILT) ) { return false; } if( !setProxIntHighThresh(DEFAULT_PIHT) ) { return false; } if( !setLightIntLowThreshold(DEFAULT_AILT) ) { return false; } if( !setLightIntHighThreshold(DEFAULT_AIHT) ) { return false; } if( !i2c1_write(APDS9960_PERS, DEFAULT_PERS) ) { return false; } if( !i2c1_write(APDS9960_CONFIG2, DEFAULT_CONFIG2) ) { return false; } if( !i2c1_write(APDS9960_CONFIG3, DEFAULT_CONFIG3) ) { return false; } /* Set default values for gesture sense registers */ if( !setGestureEnterThresh(DEFAULT_GPENTH) ) { return false; } if( !setGestureExitThresh(DEFAULT_GEXTH) ) { return false; } if( !i2c1_write(APDS9960_GCONF1, DEFAULT_GCONF1) ) { return false; } if( !setGestureGain(DEFAULT_GGAIN) ) { return false; } if( !setGestureLEDDrive(DEFAULT_GLDRIVE) ) { return false; } if( !setGestureWaitTime(DEFAULT_GWTIME) ) { return false; } if( !i2c1_write(APDS9960_GOFFSET_U, DEFAULT_GOFFSET) ) { return false; } if( !i2c1_write(APDS9960_GOFFSET_D, DEFAULT_GOFFSET) ) { return false; } if( !i2c1_write(APDS9960_GOFFSET_L, DEFAULT_GOFFSET) ) { return false; } if( !i2c1_write(APDS9960_GOFFSET_R, DEFAULT_GOFFSET) ) { return false; } if( !i2c1_write(APDS9960_GPULSE, DEFAULT_GPULSE) ) { return false; } if( !i2c1_write(APDS9960_GCONF3, DEFAULT_GCONF3) ) { return false; } if( !setGestureIntEnable(DEFAULT_GIEN) ) { return false; } #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) ) { i2c1_read(reg, val,1); //debugPutChar(reg); debugPutString(": 0x"); //debugPutChar(val); } } for(reg = 0xE4; reg <= 0xE7; reg++) { i2c1_read(reg, val,1); //debugPutChar(reg); debugPutString(": 0x"); //debugPutChar(val); } #endif return true; }/* End of this function */