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