00001
00016 #include "si114x_algorithm.h"
00017 #include "si114x_functions.h"
00018 #include "si1147_i2c.h"
00019
00020 #define LED1I 0xb
00021 #define LED2I 0xb
00022 #define LED3I 0xb
00023 #define UV_TASKLIST 0x80
00024 #define GESTURE_TASKLIST 0x7
00025 #define HOVER_TASKLIST 0x1
00026 #define UV_IRQ_EN IE_ALS_EVRYSAMPLE
00027 #define GESTURE_IRQ (IE_ALS_EVRYSAMPLE | IE_PS1_EVRYSAMPLE | IE_PS2_EVRYSAMPLE | IE_PS3_EVRYSAMPLE)
00028 #define MEASRATE_FAST 320
00029 #define MEASRATE_SLOW 32000
00030 #define PS_HOVER_THRESHOLD 295
00031 #define PS_THRESHOLD 275
00032 #define SI1147_DEVICE_ID 0x47
00033
00034
00035
00036
00037
00038
00039 static si114x_i2c_t si114x_i2c;
00040 static si114x_i2c_t *si114x_handle = &si114x_i2c;
00041
00042
00043
00044 static gesture_t ProcessSi1147Samples(Si114x_Sample_TypeDef *samples);
00045
00046
00056 int Si1147_Detect_Device(I2C_TypeDef *i2c, uint8_t addr)
00057 {
00058 uint8_t data;
00059 si114x_handle->addr = addr;
00060 si114x_handle->i2c = i2c;
00061 data = Si114xReadFromRegister(si114x_handle, 0);
00062
00063 if (data == SI1147_DEVICE_ID)
00064 {
00065 return 1;
00066 }
00067 return 0;
00068 }
00069
00070
00082 int Si1147_SetInterruptOutputEnable(I2C_TypeDef *i2c, uint8_t addr, int enable)
00083 {
00084 int retval;
00085 si114x_handle->addr = addr;
00086 si114x_handle->i2c = i2c;
00087 if (enable)
00088 {
00089 retval = Si114xWriteToRegister(si114x_handle, REG_INT_CFG, ICG_INTOE);
00090 }
00091 else
00092 {
00093 retval = Si114xWriteToRegister(si114x_handle, REG_INT_CFG, 0);
00094 }
00095 return retval;
00096 }
00097
00098
00111 int Si1147_GetInterruptOutputEnable(I2C_TypeDef *i2c, uint8_t addr, int *enable)
00112 {
00113 int retval = 0;
00114 si114x_handle->addr = addr;
00115 si114x_handle->i2c = i2c;
00116 *enable = Si114xReadFromRegister(si114x_handle, REG_INT_CFG);
00117 return retval;
00118 }
00119
00120
00137 int Si1147_MeasureUVAndObjectPresent(I2C_TypeDef *i2c, uint8_t addr, uint16_t *uvIndex, int *objectDetect)
00138 {
00139 uint16_t data;
00140 int retval = 0;
00141 int gestureMode;
00142 *objectDetect = 0;
00143 si114x_handle->addr = addr;
00144 si114x_handle->i2c = i2c;
00145 Si1147_GetInterruptOutputEnable(i2c,addr,&gestureMode);
00146 if ( !gestureMode )
00147 {
00148 Si114xPsAlsForce(si114x_handle);
00149 while ((Si114xReadFromRegister(si114x_handle, REG_IRQ_STATUS) & 1) == 0)
00150 ;
00151 }
00152 data = Si114xReadFromRegister(si114x_handle, REG_AUX_DATA0);
00153 data |= Si114xReadFromRegister(si114x_handle, REG_AUX_DATA1) << 8;
00154
00155 *uvIndex = data + 50;
00156 *uvIndex /= 100;
00157
00158 if ( !gestureMode )
00159 {
00160 data = Si114xReadFromRegister(si114x_handle, REG_PS1_DATA0);
00161 data |= Si114xReadFromRegister(si114x_handle, REG_PS1_DATA1) << 8;
00162 if (data > PS_HOVER_THRESHOLD)
00163 {
00164 *objectDetect = 1;
00165 }
00166 }
00167
00168 Si114xWriteToRegister(si114x_handle, REG_IRQ_STATUS, 0xff);
00169
00170 return retval;
00171 }
00172
00173
00181 static void readPSData(HANDLE si114x_handle, Si114x_Sample_TypeDef *sample)
00182 {
00183
00184 sample->ps1 = Si114xReadFromRegister(si114x_handle, REG_PS1_DATA0);
00185 sample->ps1 |= Si114xReadFromRegister(si114x_handle, REG_PS1_DATA1) << 8;
00186
00187 sample->ps2 = Si114xReadFromRegister(si114x_handle, REG_PS2_DATA0);
00188 sample->ps2 |= Si114xReadFromRegister(si114x_handle, REG_PS2_DATA1) << 8;
00189
00190 sample->ps3 = Si114xReadFromRegister(si114x_handle, REG_PS3_DATA0);
00191 sample->ps3 |= Si114xReadFromRegister(si114x_handle, REG_PS3_DATA1) << 8;
00192 }
00193
00194
00195
00208 gesture_t Si1147_NewSample(I2C_TypeDef *i2c, uint8_t addr, uint32_t timestamp)
00209 {
00210 Si114x_Sample_TypeDef sample;
00211 si114x_handle->addr = addr;
00212 si114x_handle->i2c = i2c;
00213 sample.timestamp = timestamp;
00214
00215 readPSData(si114x_handle, &sample);
00216
00217 Si114xWriteToRegister(si114x_handle, REG_IRQ_STATUS, Si114xReadFromRegister(si114x_handle, REG_IRQ_STATUS));
00218
00219 return ProcessSi1147Samples(&sample);
00220 }
00221
00222
00223
00233 static gesture_t ProcessSi1147Samples(Si114x_Sample_TypeDef *samples)
00234 {
00235 u16 ps[3];
00236
00237 static u32 ps_entry_time[3] = { 0, 0, 0 };
00238 static u32 ps_exit_time[3] = { 0, 0, 0 };
00239
00240 static u8 ps_state[3] = { 0, 0, 0 };
00241
00242 u8 array_counter;
00243 u32 diff_x ;
00244 u32 diff_y1 ;
00245 u32 diff_y2 ;
00246 u32 ps_time[3] ;
00247 u32 ps_avg;
00248 gesture_t ret = NONE;
00249
00250 ps[0] = samples->ps1;
00251 ps[1] = samples->ps2;
00252 ps[2] = samples->ps3;
00253
00254
00255 for (array_counter = 0; array_counter < 3; array_counter++)
00256 {
00257
00258
00259 if (ps[array_counter] >= PS_THRESHOLD)
00260 {
00261 if (ps_state[array_counter] == 0)
00262 {
00263 ps_state[array_counter] = 1;
00264 ps_entry_time[array_counter] = samples->timestamp;
00265 }
00266 }
00267 else
00268 {
00269 if (ps_state[array_counter] == 1)
00270 {
00271 ps_state[array_counter] = 0;
00272 ps_exit_time[array_counter] = samples->timestamp;
00273 }
00274 }
00275 }
00276
00277
00278 if ((ps[0] < PS_THRESHOLD) && (ps[1] < PS_THRESHOLD) && (ps[2] < PS_THRESHOLD))
00279 {
00280
00281
00282 if ((ps_entry_time[0] != 0) && (ps_entry_time[1] != 0) && (ps_entry_time[2] != 0)
00283 && (ps_exit_time[0] != 0) && (ps_exit_time[1] != 0) && (ps_exit_time[2] != 0))
00284 {
00285
00286 if ((ps_exit_time[0] > 0xFC000000L) || (ps_exit_time[1] > 0xFC000000L) || (ps_exit_time[2] > 0xFC000000L)
00287 || (ps_entry_time[0] > 0xFC000000L) || (ps_entry_time[1] > 0xFC000000L) || (ps_entry_time[2] > 0xFC000000L))
00288 {
00289 ps_exit_time[0] += 0x1FFFFFFFL;
00290 ps_exit_time[1] += 0x1FFFFFFFL;
00291 ps_exit_time[2] += 0x1FFFFFFFL;
00292
00293 ps_entry_time[0] += 0x1FFFFFFFL;
00294 ps_entry_time[1] += 0x1FFFFFFFL;
00295 ps_entry_time[2] += 0x1FFFFFFFL;
00296 }
00297
00298
00299
00300 ps_time[0] = (ps_exit_time[0] - ps_entry_time[0]) / 2;
00301 ps_time[0] = ps_time[0] + ps_entry_time[0];
00302
00303 ps_time[1] = (ps_exit_time[1] - ps_entry_time[1]) / 2;
00304 ps_time[1] = ps_time[1] + ps_entry_time[1];
00305
00306 ps_time[2] = (ps_exit_time[2] - ps_entry_time[2]) / 2;
00307 ps_time[2] = ps_time[2] + ps_entry_time[2];
00308
00309
00310
00311 if (ps_time[1] > ps_time[2])
00312 {
00313 diff_x = ps_time[1] - ps_time[2];
00314 }
00315 else
00316 {
00317 diff_x = ps_time[2] - ps_time[1];
00318 }
00319 if( ps_time[0] > ps_time[1] )
00320 {
00321 diff_y1 = ps_time[0] - ps_time[1];
00322 }
00323 else
00324 {
00325 diff_y1 = ps_time[1] - ps_time[0];
00326 }
00327
00328 if( ps_time[0] > ps_time[2] )
00329 {
00330 diff_y2 = ps_time[0] - ps_time[2];
00331 }
00332 else
00333 {
00334 diff_y2 = ps_time[2] - ps_time[0];
00335 }
00336
00337
00338
00339 ps_avg = (u32) ps_time[0] + (u32) ps_time[1] + (u32) ps_time[2];
00340 ps_avg = ps_avg / 3;
00341
00342 if ((ps_exit_time[0] - ps_entry_time[0]) > 10 || (ps_exit_time[1] - ps_entry_time[1]) > 10 || (ps_exit_time[2] - ps_entry_time[2]) > 10)
00343 {
00344 if( ( (ps_time[0] < ps_time[1]) && (diff_y1 > diff_x) ) || ( (ps_time[0] <= ps_time[2]) && (diff_y2 > diff_x) ) )
00345 {
00346 ret = UP;
00347 }
00348 else if ( ( (ps_time[0] < ps_time[1]) && (diff_y1 > diff_x) ) || ( (ps_time[0] > ps_time[2]) && (diff_y2 > diff_x) ) )
00349 {
00350 ret = DOWN;
00351 }
00352 else if((ps_time[0] < ps_time[1]) && (ps_time[2] < ps_time[1]) && (diff_x > ((diff_y1+diff_y2)/2)))
00353 {
00354 ret = LEFT;
00355 }
00356 else if( (ps_time[0] < ps_time[2]) && (ps_time[1] < ps_time[2]) && (diff_x > ((diff_y1+diff_y2)/2)))
00357 {
00358 ret = RIGHT;
00359 }
00360 }
00361 }
00362 for (array_counter = 0; array_counter < 3; array_counter++)
00363 {
00364 ps_exit_time[array_counter] = 0;
00365 ps_entry_time[array_counter] = 0;
00366 }
00367 }
00368
00369 return ret;
00370 }
00371
00372
00373
00386 int Si1147_ConfigureDetection(I2C_TypeDef *i2c, uint8_t addr, int lowpower)
00387 {
00388 s16 retval = 0;
00389 SI114X_CAL_S si114x_cal;
00390 si114x_handle->addr = addr;
00391 si114x_handle->i2c = i2c;
00392
00393
00394
00395
00396
00397
00398
00399
00400 retval += Si114xReset(si114x_handle);
00401
00402 retval += Si114xWriteToRegister(si114x_handle, REG_PS_LED21, (LED1I << 4) + LED2I);
00403 retval += Si114xWriteToRegister(si114x_handle, REG_PS_LED3, LED3I);
00404
00405
00406
00407
00408 si114x_get_calibration(si114x_handle, &si114x_cal, 0);
00409 si114x_set_ucoef(si114x_handle, 0, &si114x_cal);
00410
00411
00412
00413 retval += Si114xParamSet(si114x_handle, PARAM_CH_LIST, GESTURE_TASKLIST | UV_TASKLIST);
00414
00415 retval += Si114xWriteToRegister(si114x_handle, REG_IRQ_ENABLE, GESTURE_IRQ);
00416
00417 retval += Si114xParamSet(si114x_handle, PARAM_PS_ADC_MISC, 0x24);
00418 retval += Si114xParamSet(si114x_handle, PARAM_PS1_ADC_MUX, 0x00);
00419 retval += Si114xParamSet(si114x_handle, PARAM_PS2_ADC_MUX, 0x00);
00420 retval += Si114xParamSet(si114x_handle, PARAM_PS3_ADC_MUX, 0x00);
00421
00422
00423
00424 retval += Si114xParamSet(si114x_handle, PARAM_ALSIR_ADC_MISC, RANGE_EN);
00425 retval += Si114xParamSet(si114x_handle, PARAM_ALSVIS_ADC_MISC, RANGE_EN);
00426
00427 if (!lowpower)
00428 {
00429
00430 retval += Si114xWriteToRegister(si114x_handle, REG_MEAS_RATE_MSB, (MEASRATE_FAST & 0xff00) >> 8);
00431 retval += Si114xWriteToRegister(si114x_handle, REG_MEAS_RATE_LSB, MEASRATE_FAST & 0x00ff);
00432
00433 retval += Si114xPsAlsAuto(si114x_handle);
00434
00435 }
00436
00437
00438
00439
00440 return retval;
00441 }