/**************************************************************************//** * @brief * Initializes and configures the Si1147 sensor. * @param[in] i2c * The I2C peripheral to use (not used). * @param[in] addr * The I2C address of the sensor. * @param[in] lowpower * Set to 1 to initialize without autonomous mode (low power) or set to 0 * to enable autonomous mode. * @return * Returns 0 on success. *****************************************************************************/ int Si1147_ConfigureDetection(I2C_TypeDef *i2c, uint8_t addr, int lowpower) { s16 retval = 0; SI114X_CAL_S si114x_cal; si114x_handle->addr = addr; si114x_handle->i2c = i2c; /* Note that the Si114xReset() actually performs the following functions: */ /* 1. Pauses all prior measurements */ /* 2. Clear i2c registers that need to be cleared */ /* 3. Clears irq status to make sure INT* is negated */ /* 4. Delays 10 ms */ /* 5. Sends HW Key */ retval += Si114xReset(si114x_handle); retval += Si114xWriteToRegister(si114x_handle, REG_PS_LED21, (LED1I << 4) + LED2I); retval += Si114xWriteToRegister(si114x_handle, REG_PS_LED3, LED3I); /* UV Coefficients */ si114x_get_calibration(si114x_handle, &si114x_cal, 1); si114x_set_ucoef(si114x_handle, 0, &si114x_cal); retval += Si114xParamSet(si114x_handle, PARAM_CH_LIST, GESTURE_TASKLIST | UV_TASKLIST); retval += Si114xWriteToRegister(si114x_handle, REG_IRQ_ENABLE, GESTURE_IRQ); retval += Si114xParamSet(si114x_handle, PARAM_PS_ADC_MISC, 0x24); /* PS_ADC_MISC to high signal range */ retval += Si114xParamSet(si114x_handle, PARAM_PS1_ADC_MUX, 0x00); /* PS1_ADCMUX, PS2_ADCMUX, PS3_ADCMUX to small photodiode */ retval += Si114xParamSet(si114x_handle, PARAM_PS2_ADC_MUX, 0x00); retval += Si114xParamSet(si114x_handle, PARAM_PS3_ADC_MUX, 0x00); /* Configure the ALS IR channel for the same settings as PS */ retval += Si114xParamSet(si114x_handle, PARAM_ALSIR_ADC_MISC, RANGE_EN); retval += Si114xParamSet(si114x_handle, PARAM_ALSVIS_ADC_MISC, RANGE_EN); if (!lowpower) { /* Set up how often the device wakes up to make measurements (10ms) */ retval += Si114xWriteToRegister(si114x_handle, REG_MEAS_RATE_MSB, (MEASRATE_FAST & 0xff00) >> 8); retval += Si114xWriteToRegister(si114x_handle, REG_MEAS_RATE_LSB, MEASRATE_FAST & 0x00ff); /* Enable Autonomous Operation */ retval += Si114xPsAlsAuto(si114x_handle); }
/**************************************************************************//** * @brief * Enables or disables the Si1147 interrupt pin * @param[in] i2c * The I2C peripheral to use (not used). * @param[in] addr * The I2C address of the sensor. * @param[in] enable * Set to 1 to enable the interrupt output pin or set to 0 to disable the pin. * @return * Returns error codes based on the I2CDRV. *****************************************************************************/ int Si1147_SetInterruptOutputEnable(I2C_TypeDef *i2c, uint8_t addr, int enable) { int retval; si114x_handle->addr = addr; si114x_handle->i2c = i2c; if (enable) { retval = Si114xWriteToRegister(si114x_handle, REG_INT_CFG, ICG_INTOE); } else { retval = Si114xWriteToRegister(si114x_handle, REG_INT_CFG, 0); } return retval; }
int Si1147_MeasureUVAndObjectPresent(I2C_TypeDef *i2c, uint8_t addr, uint16_t *uvIndex, int *objectDetect) { uint16_t data; int retval = 0; int gestureMode; *objectDetect = 0; si114x_handle->addr = addr; si114x_handle->i2c = i2c; Si1147_GetInterruptOutputEnable(i2c,addr,&gestureMode); if ( !gestureMode ) /* Force only if not already running swipe detection. */ { Si114xPsAlsForce(si114x_handle); while ((Si114xReadFromRegister(si114x_handle, REG_IRQ_STATUS) & 1) == 0) ; /*wait for measurement data */ } data = Si114xReadFromRegister(si114x_handle, REG_AUX_DATA0); /*read sample data from si114x */ data |= Si114xReadFromRegister(si114x_handle, REG_AUX_DATA1) << 8; /*round to nearest*/ *uvIndex = data + 50; *uvIndex /= 100; if ( !gestureMode ) /* Check for object only if not already running swipe detection. */ { data = Si114xReadFromRegister(si114x_handle, REG_PS1_DATA0); /*read sample data from si114x */ data |= Si114xReadFromRegister(si114x_handle, REG_PS1_DATA1) << 8; if (data > PS_HOVER_THRESHOLD) { *objectDetect = 1; } } /*clear irq*/ Si114xWriteToRegister(si114x_handle, REG_IRQ_STATUS, 0xff); return retval; }
/**************************************************************************//** * @brief Stop HRM Processing and interrupts *****************************************************************************/ static void stopHRM () { HANDLE si114xHandle; si114xhrm_GetLowLevelHandle(hrmHandle, &si114xHandle); si114xhrm_Pause(hrmHandle); displayHeartRateValue = 0; displaySpo2Value = 0; Si114xWriteToRegister( si114xHandle, REG_PS_LED21, currentHRMConfig->ledCurrent & 0xff ); Si114xWriteToRegister( si114xHandle, REG_PS_LED3, currentHRMConfig->ledCurrent >> 8 ); }
/**************************************************************************//** * @brief * Reads new measurement data and processes a new sample. This function * should be called every time an interrupt for a new sample is received. * @param[in] i2c * The I2C peripheral to use (not used). * @param[in] addr * The I2C address of the sensor. * @param[in] timestamp * The timestamp for when the sample interrupt was received. * @return * Returns the type of gesture detected (as defined by gesture_t). *****************************************************************************/ gesture_t Si1147_NewSample(I2C_TypeDef *i2c, uint8_t addr, uint32_t timestamp) { Si114x_Sample_TypeDef sample; si114x_handle->addr = addr; si114x_handle->i2c = i2c; sample.timestamp = timestamp; /*read sample data from si114x */ readPSData(si114x_handle, &sample); /*clear irq*/ Si114xWriteToRegister(si114x_handle, REG_IRQ_STATUS, Si114xReadFromRegister(si114x_handle, REG_IRQ_STATUS)); /*look for gestures */ return ProcessSi1147Samples(&sample); }
/**************************************************************************//** * @brief * Reads the UV index measurement data from the * Si114x. * @param[out] uvIndex * The UV index read from the sensor * @return * Returns 0. *****************************************************************************/ int Si114x_MeasureUVIndex(u16 *uvIndex) { u16 data; volatile u8 regval; int retval = 0; Si114xPsAlsForce(si114x_handle); regval = Si114xReadFromRegister(si114x_handle, REG_AUX_DATA0); /*read sample data from si114x */ data = regval; regval = Si114xReadFromRegister(si114x_handle, REG_AUX_DATA1); data |= regval << 8; //check for saturation after the forced measurement and clear it if found //otherwise the next si114x cmd will not be performed. Also this must be //done after reading the AUX_DATA register regval = Si114xReadFromRegister(si114x_handle, REG_RESPONSE); while((regval & 0x80) != 0) //response == 0x8x means saturation occured { // Send the NOP Command to clear the error...we cannot use Si114xNop() // because it first checks if REG_RESPONSE < 0 and if so it does not // perform the cmd. Since we have a saturation REG_RESPONSE will be <0 Si114xWriteToRegister(si114x_handle, REG_COMMAND, 0x00); regval = Si114xReadFromRegister(si114x_handle, REG_RESPONSE); } /*round to nearest*/ *uvIndex = data + 50; *uvIndex /= 100; /*clear irq*/ if(*uvIndex > 10) *uvIndex = data + 50; Si114xWriteToRegister(si114x_handle, REG_IRQ_STATUS, 0xff); return retval; }
/**************************************************************************//** * @brief * Initializes and configures the Si1146 sensor for UV index measurements. * @param[in] fullInit * The I2C peripheral to use (not used). * @param[in] handle * The si114x handle for programmer's toolkit * @return * Returns 0 on success. *****************************************************************************/ int Si114x_ConfigureUV(int fullInit, HANDLE *handle) { s16 retval = 0; SI114X_CAL_S si114x_cal; /* Set handle */ si114x_handle = *handle; /* Note that the Si114xReset() actually performs the following functions: */ /* 1. Pauses all prior measurements */ /* 2. Clear i2c registers that need to be cleared */ /* 3. Clears irq status to make sure INT* is negated */ /* 4. Delays 10 ms */ /* 5. Sends HW Key */ if (fullInit) retval += Si114xReset(si114x_handle); /* UV Coefficients */ si114x_get_calibration(si114x_handle, &si114x_cal, 0); si114x_set_ucoef(si114x_handle, 0, &si114x_cal); if (fullInit) { retval += Si114xParamSet(si114x_handle, PARAM_CH_LIST, UV_TASKLIST); retval += Si114xWriteToRegister(si114x_handle, REG_IRQ_ENABLE, IE_ALS_EVRYSAMPLE); retval += Si114xParamSet(si114x_handle, PARAM_PS_ADC_MISC, 0x24); /* PS_ADC_MISC to high signal range */ retval += Si114xParamSet(si114x_handle, PARAM_PS1_ADC_MUX, 0x00); /* PS1_ADCMUX, PS2_ADCMUX, PS3_ADCMUX to small photodiode */ retval += Si114xParamSet(si114x_handle, PARAM_PS2_ADC_MUX, 0x00); retval += Si114xParamSet(si114x_handle, PARAM_PS3_ADC_MUX, 0x00); } /* Configure the ALS IR channel for the same settings as PS */ retval += Si114xParamSet(si114x_handle, PARAM_ALSIR_ADC_MISC, RANGE_EN); retval += Si114xParamSet(si114x_handle, PARAM_ALSVIS_ADC_MISC, RANGE_EN); /* If nothing went wrong after all of this time, the value */ /* returned will be 0. Otherwise, it will be some negative */ /* number */ return retval; }
int main() { // variable declarations int usr_sel; int s16_current = 0x0bbb; int s16_tasklist = -1; int s16_measrate = 0x84; int gest_cnt = 0; s16 SI114x_ret_val = -1; u8 SI114x_write_val; u8 SI114x_ret_val_array[8]; u8* SI114x_ptr = &SI114x_ret_val_array; // data structure declarations SI114X_IRQ_SAMPLE samples; gesture_t gest = NONE; HANDLE si114x_handle; si114x_handle = 0; // main program printf("\nGesture Sensor program starting... Please wait...\n\n"); // initializing the I2C bus @ addr = I2C_OPENCORES_0_BASE printf("Initializing I2C bus...\n"); I2C_init(I2C_OPENCORES_0_BASE, (alt_32) 50000000, (alt_32) 200000); // reset the Si1143 Gesture IC printf("Resetting Si1143 Gesture Sensor...\n"); SI114x_ret_val = Si114xReset(si114x_handle); if ( SI114x_ret_val != 0 ) // if reset is successful... { printf("Si1143 Reset completed successfully!\n"); // set IR LED current values to a default level printf("Setting LED current values...\n"); u8 i21, i3; i21 = 0xbb; // current = LEDI_202; i3 = 0x0b; SI114x_ret_val+=Si114xWriteToRegister(si114x_handle, REG_PS_LED21, i21); SI114x_ret_val+=Si114xWriteToRegister(si114x_handle, REG_PS_LED3 , i3); } else // if reset fails, exit { printf("Si1143 Reset failed... Exiting...\n"); return -1; } // gesture recognition loop printf("Entering main loop...\n Loop exits after 32 gestures are recognized.\n"); // have Si1143 measure all three proximity channels, the visual channel, and the IR channel s16_tasklist = PS1_TASK + PS2_TASK + PS3_TASK + ALS_VIS_TASK + ALS_IR_TASK; SI114x_ret_val+=Si114xParamSet(si114x_handle, PARAM_CH_LIST, s16_tasklist); while ( gest_cnt <= 32 ){ // make measurement SI114x_ret_val = Si114xPsAlsForce(si114x_handle); //usleep(10000); // uncomment if you need a pause in measurements if ( SI114x_ret_val > 0 ){ // if measurement is successful... // retrieve data from sensor and put it in struct "samples" DECA_si1143_irq_pop(si114x_handle, &samples); // process data in gesture algorithm gest = ProcessSi1143Samples(&samples); // report the gesture and increment counter if ( gest != NONE ) gest_cnt++; if ( gest == UP ) printf("UP swipe detected!\n"); if ( gest == DOWN ) printf("DOWN swipe detected!\n"); if ( gest == LEFT ) printf("LEFT swipe detected!\n"); if ( gest == RIGHT ) printf("RIGHT swipe detected!\n"); if ( gest == TAP ) printf("TAP detected!\n"); } else printf("Unable to force measurement...\n"); } return 0; }