Library to handle the X-NUCLEO-6180XA1 Proximity and ambient light sensor expansion board based on VL6180X.
Dependencies: X_NUCLEO_COMMON ST_INTERFACES
Dependents: HelloWorld_6180XA1 SunTracker_BLE Servo_6180XA1 BLE_HR_Light ... more
Fork of X_NUCLEO_6180XA1 by
VL6180X.cpp
00001 /** 00002 ****************************************************************************** 00003 * @file VL6180X.cpp 00004 * @author AST / EST 00005 * @version V0.0.1 00006 * @date 14-April-2015 00007 * @brief Implementation file for the HTS221 driver class 00008 ****************************************************************************** 00009 * @attention 00010 * 00011 * <h2><center>© COPYRIGHT(c) 2015 STMicroelectronics</center></h2> 00012 * 00013 * Redistribution and use in source and binary forms, with or without modification, 00014 * are permitted provided that the following conditions are met: 00015 * 1. Redistributions of source code must retain the above copyright notice, 00016 * this list of conditions and the following disclaimer. 00017 * 2. Redistributions in binary form must reproduce the above copyright notice, 00018 * this list of conditions and the following disclaimer in the documentation 00019 * and/or other materials provided with the distribution. 00020 * 3. Neither the name of STMicroelectronics nor the names of its contributors 00021 * may be used to endorse or promote products derived from this software 00022 * without specific prior written permission. 00023 * 00024 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00025 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00026 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00027 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 00028 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00029 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00030 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00031 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00032 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00033 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00034 * 00035 ****************************************************************************** 00036 */ 00037 00038 /* Includes */ 00039 #include "VL6180X.h" 00040 00041 00042 #ifndef VL6180X_RANGE_STATUS_ERRSTRING 00043 #warning "VL6180X_RANGE_STATUS_ERRSTRING not defined ?" 00044 /* TODO you may remove or comment these #warning and keep the default below to keep compatibility 00045 or update your vl6180x_platform.h file */ 00046 /** 00047 * force VL6180X_RANGE_STATUS_ERRSTRING to not supported when not part of any cfg file 00048 */ 00049 #define VL6180X_RANGE_STATUS_ERRSTRING 0 00050 #endif 00051 00052 #ifndef VL6180X_SAFE_POLLING_ENTER 00053 #warning "VL6180X_SAFE_POLLING_ENTER not defined, likely old vl6180x_cfg.h file ?" 00054 /* TODO you may remove or comment these #warning and keep the default below to keep compatibility 00055 or update your vl6180x_platform.h file */ 00056 /** 00057 * force VL6180X_SAFE_POLLING_ENTER to off when not in cfg file 00058 */ 00059 #define VL6180X_SAFE_POLLING_ENTER 0 /* off by default as in api 2.0 */ 00060 #endif 00061 00062 #ifndef VL6180X_LOG_ENABLE 00063 /** 00064 * Force VL6180X_LOG_ENABLE to none as default 00065 */ 00066 #define VL6180X_LOG_ENABLE 0 00067 #endif 00068 00069 #ifdef MY_LOG 00070 Serial pc(USBTX, USBRX); 00071 #endif 00072 00073 #if VL6180X_RANGE_STATUS_ERRSTRING 00074 /**@def VL6180X_HAVE_RANGE_STATUS_ERRSTRING 00075 * @brief is defined when @a #VL6180X_RANGE_STATUS_ERRSTRING is enable 00076 */ 00077 #define VL6180X_HAVE_RANGE_STATUS_ERRSTRING 00078 #endif 00079 00080 00081 /** @brief Get API version as "hex integer" 0xMMnnss 00082 */ 00083 #define VL6180X_ApiRevInt ((VL6180X_API_REV_MAJOR<<24)+(VL6180X_API_REV_MINOR<<16)+VL6180X_API_REV_SUB) 00084 00085 /** Get API version as string for exe "2.1.12" " 00086 */ 00087 #define VL6180X_ApiRevStr VL6180X_STR(VL6180X_API_REV_MAJOR) "." VL6180X_STR(VL6180X_API_REV_MINOR) "." VL6180X_STR(VL6180X_API_REV_SUB) 00088 00089 /** @defgroup api_init Init functions 00090 * @brief API init functions 00091 * @ingroup api_hl 00092 * @{ 00093 */ 00094 00095 00096 /****************** define for i2c configuration *******************************/ 00097 00098 #define TEMP_BUF_SIZE 32 00099 00100 #define IsValidGPIOFunction(x) ((x)==GPIOx_SELECT_GPIO_INTERRUPT_OUTPUT || (x)==GPIOx_SELECT_OFF) 00101 /** 00102 * @brief Clear All interrupt causes (als+range+error) 00103 * 00104 * @param dev The device 00105 * @return 0 On success 00106 */ 00107 #define VL6180X_ClearAllInterrupt(dev) VL6180X_ClearInterrupt(dev, INTERRUPT_CLEAR_ERROR|INTERRUPT_CLEAR_RANGING|INTERRUPT_CLEAR_ALS) 00108 /** 00109 * @brief Clear ALS interrupt 00110 * 00111 * @param dev The device 00112 * @return 0 On success 00113 */ 00114 #define VL6180X_AlsClearInterrupt(dev) VL6180X_ClearInterrupt(dev, INTERRUPT_CLEAR_ALS) 00115 /** 00116 * @brief Clear range interrupt 00117 * 00118 * @param dev The device 00119 * @return 0 On success 00120 */ 00121 #define VL6180X_RangeClearInterrupt(dev) VL6180X_ClearInterrupt(dev, INTERRUPT_CLEAR_RANGING) 00122 00123 /******************************************************************************/ 00124 /******************************* file api.c ***********************************/ 00125 00126 #define VL6180X_9to7Conv(x) (x) 00127 00128 /* TODO when set all "cached" value with "default init" are updated after init from register read back */ 00129 #define REFRESH_CACHED_DATA_AFTER_INIT 1 00130 00131 00132 #define IsValidGPIOFunction(x) ((x)==GPIOx_SELECT_GPIO_INTERRUPT_OUTPUT || (x)==GPIOx_SELECT_OFF) 00133 00134 00135 /** default value ECE factor Molecular */ 00136 #define DEF_ECE_FACTOR_M 85 00137 /** default value ECE factor Denominator */ 00138 #define DEF_ECE_FACTOR_D 100 00139 /** default value ALS integration time */ 00140 #define DEF_INT_PEFRIOD 100 00141 /** default value ALS gain */ 00142 #define DEF_ALS_GAIN 1 00143 /** default value ALS scaler */ 00144 #define DEF_ALS_SCALER 1 00145 /** default value for DMAX Enbale */ 00146 #define DEF_DMAX_ENABLE 1 00147 /** default ambient tuning factor %x1000 */ 00148 #define DEF_AMBIENT_TUNING 80 00149 00150 #if VL6180X_SINGLE_DEVICE_DRIVER 00151 extern struct VL6180XDevData_t SingleVL6180XDevData; 00152 #define VL6180XDevDataGet(dev, field) (SingleVL6180XDevData.field) 00153 #define VL6180XDevDataSet(dev, field, data) SingleVL6180XDevData.field=(data) 00154 #endif 00155 00156 #define LUXRES_FIX_PREC 8 00157 #define GAIN_FIX_PREC 8 /* ! if not sme as LUX_PREC then :( adjust GetLux */ 00158 #define AN_GAIN_MULT (1<<GAIN_FIX_PREC) 00159 00160 00161 //int32_t _GetAveTotalTime(VL6180XDev_t dev); 00162 //int VL6180X_RangeSetEarlyConvergenceEestimateThreshold(VL6180XDev_t dev); 00163 00164 /** 00165 * ScalerLookUP scaling factor-1 to register #RANGE_SCALER lookup 00166 */ 00167 static const uint16_t ScalerLookUP[] ROMABLE_DATA ={ 253, 127, 84}; /* lookup table for scaling->scalar 1x2x 3x */ 00168 /** 00169 * scaling factor to Upper limit look up 00170 */ 00171 static const uint16_t UpperLimitLookUP[] ROMABLE_DATA ={ 185, 370, 580}; /* lookup table for scaling->limit 1x2x3x */ 00172 /** 00173 * Als Code gain to fix point gain lookup 00174 */ 00175 static const uint16_t AlsGainLookUp[8] ROMABLE_DATA = { 00176 (uint16_t)(20.0f * AN_GAIN_MULT), 00177 (uint16_t)(10.0f * AN_GAIN_MULT), 00178 (uint16_t)(5.0f * AN_GAIN_MULT), 00179 (uint16_t)(2.5f * AN_GAIN_MULT), 00180 (uint16_t)(1.67f * AN_GAIN_MULT), 00181 (uint16_t)(1.25f * AN_GAIN_MULT), 00182 (uint16_t)(1.0f * AN_GAIN_MULT), 00183 (uint16_t)(40.0f * AN_GAIN_MULT), 00184 }; 00185 00186 00187 #if VL6180X_RANGE_STATUS_ERRSTRING 00188 const char * ROMABLE_DATA VL6180X_RangeStatusErrString[]={ 00189 "No Error", 00190 "VCSEL Continuity Test", 00191 "VCSEL Watchdog Test", 00192 "VCSEL Watchdog", 00193 "PLL1 Lock", 00194 "PLL2 Lock", 00195 "Early Convergence Estimate", 00196 "Max Convergence", 00197 "No Target Ignore", 00198 "Not used 9", 00199 "Not used 10", 00200 "Max Signal To Noise Ratio", 00201 "Raw Ranging Algo Underflow", 00202 "Raw Ranging Algo Overflow", 00203 "Ranging Algo Underflow", 00204 "Ranging Algo Overflow", 00205 00206 "Filtered by post processing" 00207 }; 00208 00209 const char * VL6180X_RangeGetStatusErrString(uint8_t RangeErrCode){ 00210 if( RangeErrCode > sizeof(VL6180X_RangeStatusErrString)/sizeof(VL6180X_RangeStatusErrString[0]) ) 00211 return NULL; 00212 return VL6180X_RangeStatusErrString[RangeErrCode]; 00213 } 00214 #endif 00215 00216 #if VL6180X_UPSCALE_SUPPORT == 1 00217 #define _GetUpscale(dev, ... ) 1 00218 #define _SetUpscale(...) -1 00219 #define DEF_UPSCALE 1 00220 #elif VL6180X_UPSCALE_SUPPORT == 2 00221 #define _GetUpscale(dev, ... ) 2 00222 #define _SetUpscale(...) 00223 #define DEF_UPSCALE 2 00224 #elif VL6180X_UPSCALE_SUPPORT == 3 00225 #define _GetUpscale(dev, ... ) 3 00226 #define _SetUpscale(...) 00227 #define DEF_UPSCALE 3 00228 #else 00229 #define DEF_UPSCALE (-(VL6180X_UPSCALE_SUPPORT)) 00230 #define _GetUpscale(dev, ... ) VL6180XDevDataGet(dev, UpscaleFactor) 00231 #define _SetUpscale(dev, Scaling ) VL6180XDevDataSet(dev, UpscaleFactor, Scaling) 00232 #endif 00233 00234 00235 #if VL6180X_SINGLE_DEVICE_DRIVER 00236 /** 00237 * the unique driver data When single device driver is active 00238 */ 00239 struct VL6180XDevData_t VL6180X_DEV_DATA_ATTR SingleVL6180XDevData={ 00240 .EceFactorM = DEF_ECE_FACTOR_M, 00241 .EceFactorD = DEF_ECE_FACTOR_D, 00242 #ifdef VL6180X_HAVE_UPSCALE_DATA 00243 .UpscaleFactor = DEF_UPSCALE, 00244 #endif 00245 #ifdef VL6180X_HAVE_ALS_DATA 00246 .IntegrationPeriod = DEF_INT_PEFRIOD, 00247 .AlsGainCode = DEF_ALS_GAIN, 00248 .AlsScaler = DEF_ALS_SCALER, 00249 #endif 00250 #ifdef VL6180X_HAVE_DMAX_RANGING 00251 .DMaxEnable = DEF_DMAX_ENABLE, 00252 #endif 00253 }; 00254 #endif /* VL6180X_SINGLE_DEVICE_DRIVER */ 00255 00256 #define Fix7_2_KCPs(x) ((((uint32_t)(x))*1000)>>7) 00257 00258 #if VL6180X_WRAP_AROUND_FILTER_SUPPORT 00259 static int _filter_Init(VL6180XDev_t dev); 00260 #define _IsWrapArroundActive(dev) VL6180XDevDataGet(dev,WrapAroundFilterActive) 00261 #else 00262 #define _IsWrapArroundActive(dev) 0 00263 #endif 00264 00265 00266 #if VL6180X_HAVE_DMAX_RANGING 00267 void _DMax_OneTimeInit(VL6180XDev_t dev); 00268 // static int _DMax_InitData(VL6180XDev_t dev); 00269 static int _DMax_Compute(VL6180XDev_t dev, VL6180X_RangeData_t *pRange); 00270 #define _IsDMaxActive(dev) VL6180XDevDataGet(dev,DMaxEnable) 00271 #else 00272 #define _DMax_InitData(...) 0 /* success */ 00273 #define _DMax_OneTimeInit(...) (void)0 00274 #define _IsDMaxActive(...) 0 00275 #endif 00276 00277 //static int VL6180X_RangeStaticInit(VL6180XDev_t dev); 00278 //static int VL6180X_UpscaleStaticInit(VL6180XDev_t dev); 00279 00280 int VL6180X::VL6180X_WaitDeviceBooted(VL6180XDev_t dev){ 00281 uint8_t FreshOutReset=0; 00282 int status; 00283 LOG_FUNCTION_START(""); 00284 do{ 00285 status = VL6180X_RdByte(dev,SYSTEM_FRESH_OUT_OF_RESET, &FreshOutReset); 00286 } 00287 while( FreshOutReset!=1 && status==0); 00288 LOG_FUNCTION_END(status); 00289 return status; 00290 } 00291 00292 int VL6180X::VL6180X_InitData(VL6180XDev_t dev){ 00293 int status, dmax_status ; 00294 int8_t offset; 00295 uint8_t FreshOutReset; 00296 uint32_t CalValue; 00297 uint16_t u16; 00298 uint32_t XTalkCompRate_KCps; 00299 00300 LOG_FUNCTION_START(""); 00301 00302 VL6180XDevDataSet(dev, EceFactorM , DEF_ECE_FACTOR_M); 00303 VL6180XDevDataSet(dev, EceFactorD , DEF_ECE_FACTOR_D); 00304 00305 #ifdef VL6180X_HAVE_UPSCALE_DATA 00306 VL6180XDevDataSet(dev, UpscaleFactor , DEF_UPSCALE); 00307 #endif 00308 00309 #ifdef VL6180X_HAVE_ALS_DATA 00310 VL6180XDevDataSet(dev, IntegrationPeriod , DEF_INT_PEFRIOD); 00311 VL6180XDevDataSet(dev, AlsGainCode , DEF_ALS_GAIN); 00312 VL6180XDevDataSet(dev, AlsScaler , DEF_ALS_SCALER); 00313 #endif 00314 00315 #ifdef VL6180X_HAVE_WRAP_AROUND_DATA 00316 VL6180XDevDataSet(dev, WrapAroundFilterActive , (VL6180X_WRAP_AROUND_FILTER_SUPPORT >0)); 00317 VL6180XDevDataSet(dev, DMaxEnable, DEF_DMAX_ENABLE); 00318 #endif 00319 00320 _DMax_OneTimeInit(dev); 00321 do{ 00322 00323 /* backup offset initial value from nvm these must be done prior any over call that use offset */ 00324 status = VL6180X::VL6180X_RdByte(dev,SYSRANGE_PART_TO_PART_RANGE_OFFSET, (uint8_t*)&offset); 00325 if( status ){ 00326 VL6180X_ErrLog("SYSRANGE_PART_TO_PART_RANGE_OFFSET rd fail"); 00327 break; 00328 } 00329 VL6180XDevDataSet(dev, Part2PartOffsetNVM , offset); 00330 00331 status=VL6180X_RdDWord( dev, SYSRANGE_RANGE_IGNORE_THRESHOLD, &CalValue); 00332 if( status ){ 00333 VL6180X_ErrLog("Part2PartAmbNVM rd fail"); 00334 break; 00335 } 00336 if( (CalValue&0xFFFF0000) == 0 ){ 00337 CalValue=0x00CE03F8; 00338 } 00339 VL6180XDevDataSet(dev, Part2PartAmbNVM , CalValue); 00340 00341 status = VL6180X_RdWord(dev, SYSRANGE_CROSSTALK_COMPENSATION_RATE ,&u16); 00342 if( status){ 00343 VL6180X_ErrLog("SYSRANGE_CROSSTALK_COMPENSATION_RATE rd fail "); 00344 break; 00345 } 00346 XTalkCompRate_KCps = Fix7_2_KCPs(u16); 00347 VL6180XDevDataSet(dev, XTalkCompRate_KCps , XTalkCompRate_KCps ); 00348 00349 dmax_status = _DMax_InitData(dev); 00350 if( dmax_status < 0 ){ 00351 VL6180X_ErrLog("DMax init failure"); 00352 break; 00353 } 00354 00355 /* Read or wait for fresh out of reset */ 00356 status = VL6180X_RdByte(dev,SYSTEM_FRESH_OUT_OF_RESET, &FreshOutReset); 00357 if( status ) { 00358 VL6180X_ErrLog("SYSTEM_FRESH_OUT_OF_RESET rd fail"); 00359 break; 00360 } 00361 if( FreshOutReset!= 1 || dmax_status ) 00362 status = CALIBRATION_WARNING; 00363 00364 } 00365 while(0); 00366 00367 LOG_FUNCTION_END(status); 00368 return status; 00369 } 00370 00371 int8_t VL6180X::VL6180X_GetOffsetCalibrationData(VL6180XDev_t dev) 00372 { 00373 int8_t offset; 00374 LOG_FUNCTION_START(""); 00375 offset = VL6180XDevDataGet(dev, Part2PartOffsetNVM ); 00376 LOG_FUNCTION_END( offset ); 00377 return offset; 00378 } 00379 00380 void VL6180X::VL6180X_SetOffsetCalibrationData(VL6180XDev_t dev, int8_t offset) 00381 { 00382 LOG_FUNCTION_START("%d", offset); 00383 VL6180XDevDataSet(dev, Part2PartOffsetNVM , offset); 00384 LOG_FUNCTION_END(0); 00385 } 00386 00387 int VL6180X::VL6180X_SetXTalkCompensationRate(VL6180XDev_t dev, FixPoint97_t Rate) 00388 { 00389 int status; 00390 LOG_FUNCTION_START("%d", Rate); 00391 status = VL6180X_WrWord(dev, SYSRANGE_CROSSTALK_COMPENSATION_RATE, Rate); 00392 if( status ==0 ){ 00393 uint32_t XTalkCompRate_KCps; 00394 XTalkCompRate_KCps = Fix7_2_KCPs(Rate); 00395 VL6180XDevDataSet(dev, XTalkCompRate_KCps , XTalkCompRate_KCps ); 00396 /* update dmax whenever xtalk rate changes */ 00397 status = _DMax_InitData(dev); 00398 } 00399 LOG_FUNCTION_END(status); 00400 return status; 00401 } 00402 00403 int VL6180X::VL6180X_SetI2CAddress(VL6180XDev_t dev, uint8_t NewAddress){ 00404 int status; 00405 LOG_FUNCTION_START(""); 00406 00407 status = VL6180X_WrByte(dev, I2C_SLAVE_DEVICE_ADDRESS, NewAddress); 00408 if( status ){ 00409 VL6180X_ErrLog("new i2c addr Wr fail"); 00410 } 00411 LOG_FUNCTION_END(status); 00412 return status; 00413 } 00414 00415 00416 uint16_t VL6180X::VL6180X_GetUpperLimit(VL6180XDev_t dev) { 00417 uint16_t limit; 00418 int scaling; 00419 00420 LOG_FUNCTION_START(""); 00421 00422 scaling = _GetUpscale(dev); 00423 /* FIXME we do assume here _GetUpscale is valid if user call us prior to init we may overflow the LUT mem area */ 00424 limit = UpperLimitLookUP[scaling - 1]; 00425 00426 LOG_FUNCTION_END((int )limit); 00427 return limit; 00428 } 00429 00430 00431 00432 int VL6180X::VL6180X_StaticInit(VL6180XDev_t dev){ 00433 int status=0, init_status; 00434 LOG_FUNCTION_START(""); 00435 00436 /* TODO doc When using configurable scaling but using 1x as start condition 00437 * load tunning upscale or not ??? */ 00438 if( _GetUpscale(dev) == 1 && !(VL6180X_UPSCALE_SUPPORT<0)) 00439 init_status=VL6180X_RangeStaticInit(dev); 00440 else 00441 init_status=VL6180X_UpscaleStaticInit(dev); 00442 00443 if( init_status <0 ){ 00444 VL6180X_ErrLog("StaticInit fail"); 00445 goto error; 00446 } 00447 else if(init_status > 0){ 00448 VL6180X_ErrLog("StaticInit warning"); 00449 } 00450 00451 #if REFRESH_CACHED_DATA_AFTER_INIT 00452 /* update cached value after tuning applied */ 00453 do{ 00454 #ifdef VL6180X_HAVE_ALS_DATA 00455 uint8_t data; 00456 status= VL6180X_RdByte(dev, FW_ALS_RESULT_SCALER, &data); 00457 if( status ) break; 00458 VL6180XDevDataSet(dev, AlsScaler , data); 00459 00460 status= VL6180X_RdByte(dev, SYSALS_ANALOGUE_GAIN, &data); 00461 if( status ) break; 00462 VL6180X_AlsSetAnalogueGain(dev, data); 00463 #endif 00464 } 00465 while(0); 00466 #endif /* REFRESH_CACHED_DATA_AFTER_INIT */ 00467 if( status < 0 ){ 00468 VL6180X_ErrLog("StaticInit fail"); 00469 } 00470 if( !status && init_status){ 00471 status = init_status; 00472 } 00473 error: 00474 LOG_FUNCTION_END(status); 00475 return status; 00476 } 00477 00478 00479 int VL6180X::VL6180X_SetGroupParamHold(VL6180XDev_t dev, int Hold) 00480 { 00481 int status; 00482 uint8_t value; 00483 00484 LOG_FUNCTION_START("%d", Hold); 00485 if( Hold ) 00486 value = 1; 00487 else 00488 value = 0; 00489 status = VL6180X_WrByte(dev, SYSTEM_GROUPED_PARAMETER_HOLD, value); 00490 00491 LOG_FUNCTION_END(status); 00492 return status; 00493 00494 } 00495 00496 int VL6180X::VL6180X_Prepare(VL6180XDev_t dev) 00497 { 00498 int status; 00499 LOG_FUNCTION_START(""); 00500 00501 do{ 00502 status=VL6180X_StaticInit(dev); 00503 if( status<0) break; 00504 00505 /* set range InterruptMode to new sample */ 00506 status=VL6180X_RangeConfigInterrupt(dev, CONFIG_GPIO_INTERRUPT_DISABLED ); 00507 if( status) 00508 break; 00509 00510 /* set default threshold */ 00511 status=VL6180X_RangeSetRawThresholds(dev, 10, 200); 00512 if( status ){ 00513 VL6180X_ErrLog("VL6180X_RangeSetRawThresholds fail"); 00514 break; 00515 } 00516 #if VL6180X_ALS_SUPPORT 00517 status =VL6180X_AlsSetIntegrationPeriod(dev, 100); 00518 if( status ) break; 00519 status = VL6180X_AlsSetInterMeasurementPeriod(dev, 200); 00520 if( status ) break; 00521 status = VL6180X_AlsSetAnalogueGain(dev, 0); 00522 if( status ) break; 00523 status = VL6180X_AlsSetThresholds(dev, 0, 0xFFFF); 00524 if( status ) break; 00525 /* set Als InterruptMode to new sample */ 00526 status=VL6180X_AlsConfigInterrupt(dev, CONFIG_GPIO_INTERRUPT_DISABLED); 00527 if( status ) { 00528 VL6180X_ErrLog("VL6180X_AlsConfigInterrupt fail"); 00529 break; 00530 } 00531 #endif 00532 #if VL6180X_WRAP_AROUND_FILTER_SUPPORT 00533 _filter_Init(dev); 00534 #endif 00535 /* make sure to reset any left previous condition that can hangs first poll */ 00536 status=VL6180X_ClearAllInterrupt(dev); 00537 } 00538 while(0); 00539 LOG_FUNCTION_END(status); 00540 00541 return status; 00542 } 00543 00544 #if VL6180X_ALS_SUPPORT 00545 int VL6180X::VL6180X_AlsGetLux(VL6180XDev_t dev, lux_t *pLux) 00546 { 00547 int status; 00548 uint16_t RawAls; 00549 uint32_t luxValue = 0; 00550 uint32_t IntPeriod; 00551 uint32_t AlsAnGain; 00552 uint32_t GainFix; 00553 uint32_t AlsScaler ; 00554 00555 #if LUXRES_FIX_PREC != GAIN_FIX_PREC 00556 #error "LUXRES_FIX_PREC != GAIN_FIX_PREC review these code to be correct" 00557 #endif 00558 const uint32_t LuxResxIntIme =(uint32_t)(0.56f* DEF_INT_PEFRIOD *(1<<LUXRES_FIX_PREC)); 00559 00560 LOG_FUNCTION_START("%p", pLux); 00561 00562 status = VL6180X_RdWord( dev, RESULT_ALS_VAL, &RawAls); 00563 if( !status){ 00564 /* wer are yet here at no fix point */ 00565 IntPeriod=VL6180XDevDataGet(dev, IntegrationPeriod ); 00566 AlsScaler=VL6180XDevDataGet(dev, AlsScaler); 00567 IntPeriod++; /* what stored is real time ms -1 and it can be 0 for or 0 or 1ms */ 00568 luxValue = (uint32_t)RawAls * LuxResxIntIme; /* max # 16+8bits + 6bit (0.56*100) */ 00569 luxValue /= IntPeriod; /* max # 16+8bits + 6bit 16+8+1 to 9 bit */ 00570 /* between 29 - 21 bit */ 00571 AlsAnGain = VL6180XDevDataGet(dev, AlsGainCode ); 00572 GainFix = AlsGainLookUp[AlsAnGain]; 00573 luxValue = luxValue / (AlsScaler * GainFix); 00574 *pLux=luxValue; 00575 } 00576 00577 LOG_FUNCTION_END_FMT(status, "%x",(int)*pLux); 00578 return status; 00579 } 00580 00581 int VL6180X::VL6180X_AlsGetMeasurement(VL6180XDev_t dev, VL6180X_AlsData_t *pAlsData) 00582 { 00583 int status; 00584 uint8_t ErrStatus; 00585 00586 LOG_FUNCTION_START("%p", pAlsData); 00587 00588 status = VL6180X_AlsGetLux(dev, &pAlsData->lux); 00589 if( !status ){ 00590 status = VL6180X_RdByte(dev, RESULT_ALS_STATUS, & ErrStatus); 00591 pAlsData->errorStatus = ErrStatus>>4; 00592 } 00593 LOG_FUNCTION_END_FMT(status,"%d %d", (int)pAlsData->lux, (int)pAlsData->errorStatus); 00594 00595 return status; 00596 } 00597 00598 00599 int VL6180X::VL6180X_AlsPollMeasurement(VL6180XDev_t dev, VL6180X_AlsData_t *pAlsData) { 00600 int status; 00601 int ClrStatus; 00602 uint8_t IntStatus; 00603 00604 LOG_FUNCTION_START("%p", pAlsData); 00605 #if VL6180X_SAFE_POLLING_ENTER 00606 /* if device get stopped with left interrupt uncleared , it is required to clear them now or poll for new condition will never occur*/ 00607 status=VL6180X_AlsClearInterrupt(dev); 00608 if(status){ 00609 VL6180X_ErrLog("VL6180X_AlsClearInterrupt fail"); 00610 goto over; 00611 } 00612 #endif 00613 00614 status=VL6180X_AlsSetSystemMode(dev, MODE_START_STOP|MODE_SINGLESHOT); 00615 if( status){ 00616 VL6180X_ErrLog("VL6180X_AlsSetSystemMode fail"); 00617 goto over; 00618 } 00619 00620 /* poll for new sample ready */ 00621 while (1 ) { 00622 status = VL6180X_AlsGetInterruptStatus(dev, &IntStatus); 00623 if (status) { 00624 break; 00625 } 00626 if (IntStatus == RES_INT_STAT_GPIO_NEW_SAMPLE_READY) { 00627 break; /* break on new data (status is 0) */ 00628 } 00629 wait_ms(10); 00630 }; 00631 00632 if (!status) { 00633 status = VL6180X_AlsGetMeasurement(dev, pAlsData); 00634 } 00635 00636 ClrStatus = VL6180X_AlsClearInterrupt(dev); 00637 if (ClrStatus) { 00638 VL6180X_ErrLog("VL6180X_AlsClearInterrupt fail"); 00639 if (!status) { 00640 status = ClrStatus; /* leave previous if already on error */ 00641 } 00642 } 00643 over: 00644 LOG_FUNCTION_END(status); 00645 00646 return status; 00647 } 00648 00649 int VL6180X::VL6180X_AlsGetInterruptStatus(VL6180XDev_t dev, uint8_t *pIntStatus) { 00650 int status; 00651 uint8_t IntStatus; 00652 LOG_FUNCTION_START("%p", pIntStatus); 00653 00654 status = VL6180X_RdByte(dev, RESULT_INTERRUPT_STATUS_GPIO, &IntStatus); 00655 *pIntStatus= (IntStatus>>3)&0x07; 00656 00657 LOG_FUNCTION_END_FMT(status, "%d", (int)*pIntStatus); 00658 return status; 00659 } 00660 00661 int VL6180X::VL6180X_AlsWaitDeviceReady(VL6180XDev_t dev, int MaxLoop ){ 00662 int status; 00663 int n; 00664 uint8_t u8; 00665 LOG_FUNCTION_START("%d", (int)MaxLoop); 00666 if( MaxLoop<1){ 00667 status=INVALID_PARAMS; 00668 } 00669 else{ 00670 for( n=0; n < MaxLoop ; n++){ 00671 status=VL6180X_RdByte(dev, RESULT_ALS_STATUS, &u8); 00672 if( status) 00673 break; 00674 u8 = u8 & ALS_DEVICE_READY_MASK; 00675 if( u8 ) 00676 break; 00677 00678 } 00679 if( !status && !u8 ){ 00680 status = TIME_OUT; 00681 } 00682 } 00683 LOG_FUNCTION_END(status); 00684 return status; 00685 } 00686 00687 int VL6180X::VL6180X_AlsSetSystemMode(VL6180XDev_t dev, uint8_t mode) 00688 { 00689 int status; 00690 LOG_FUNCTION_START("%d", (int)mode); 00691 /* FIXME if we are called back to back real fast we are not checking 00692 * if previous mode "set" got absorbed => bit 0 must be 0 so that wr 1 work */ 00693 if( mode <= 3){ 00694 status=VL6180X_WrByte(dev, SYSALS_START, mode); 00695 } 00696 else{ 00697 status = INVALID_PARAMS; 00698 } 00699 LOG_FUNCTION_END(status); 00700 return status; 00701 } 00702 00703 int VL6180X::VL6180X_AlsConfigInterrupt(VL6180XDev_t dev, uint8_t ConfigGpioInt) 00704 { 00705 int status; 00706 00707 if( ConfigGpioInt<= CONFIG_GPIO_INTERRUPT_NEW_SAMPLE_READY){ 00708 status = VL6180X_UpdateByte(dev, SYSTEM_INTERRUPT_CONFIG_GPIO, (uint8_t)(~CONFIG_GPIO_ALS_MASK), (ConfigGpioInt<<3)); 00709 } 00710 else{ 00711 VL6180X_ErrLog("Invalid config mode param %d", (int)ConfigGpioInt); 00712 status = INVALID_PARAMS; 00713 } 00714 LOG_FUNCTION_END(status); 00715 return status; 00716 } 00717 00718 int VL6180X::VL6180X_AlsSetThresholds(VL6180XDev_t dev, uint16_t low, uint16_t high) { 00719 int status; 00720 00721 LOG_FUNCTION_START("%d %d", (int )low, (int)high); 00722 00723 status = VL6180X_WrWord(dev, SYSALS_THRESH_LOW, low); 00724 if(!status ){ 00725 status = VL6180X_WrWord(dev, SYSALS_THRESH_HIGH, high); 00726 } 00727 00728 LOG_FUNCTION_END(status) ; 00729 return status; 00730 } 00731 00732 int VL6180X::VL6180X_AlsSetAnalogueGain(VL6180XDev_t dev, uint8_t gain) { 00733 int status; 00734 uint8_t GainTotal; 00735 00736 LOG_FUNCTION_START("%d", (int )gain); 00737 gain&=~0x40; 00738 if (gain > 7) { 00739 gain = 7; 00740 } 00741 GainTotal = gain|0x40; 00742 00743 status = VL6180X_WrByte(dev, SYSALS_ANALOGUE_GAIN, GainTotal); 00744 if( !status){ 00745 VL6180XDevDataSet(dev, AlsGainCode , gain); 00746 } 00747 00748 LOG_FUNCTION_END_FMT(status, "%d %d", (int ) gain, (int )GainTotal); 00749 return status; 00750 } 00751 00752 int VL6180X::VL6180X_AlsSetInterMeasurementPeriod(VL6180XDev_t dev, uint16_t intermeasurement_period_ms) 00753 { 00754 int status; 00755 00756 LOG_FUNCTION_START("%d",(int)intermeasurement_period_ms); 00757 /* clipping: range is 0-2550ms */ 00758 if (intermeasurement_period_ms >= 255 *10) 00759 intermeasurement_period_ms = 255 *10; 00760 status=VL6180X_WrByte(dev, SYSALS_INTERMEASUREMENT_PERIOD, (uint8_t)(intermeasurement_period_ms/10)); 00761 00762 LOG_FUNCTION_END_FMT(status, "%d", (int) intermeasurement_period_ms); 00763 return status; 00764 } 00765 00766 00767 int VL6180X::VL6180X_AlsSetIntegrationPeriod(VL6180XDev_t dev, uint16_t period_ms) 00768 { 00769 int status; 00770 uint16_t SetIntegrationPeriod; 00771 00772 LOG_FUNCTION_START("%d", (int)period_ms); 00773 00774 if( period_ms>=1 ) 00775 SetIntegrationPeriod = period_ms - 1; 00776 else 00777 SetIntegrationPeriod = period_ms; 00778 00779 if (SetIntegrationPeriod > 464) { 00780 SetIntegrationPeriod = 464; 00781 } 00782 else if (SetIntegrationPeriod == 255) { 00783 SetIntegrationPeriod++; /* can't write 255 since this causes the device to lock out.*/ 00784 } 00785 00786 status =VL6180X_WrWord(dev, SYSALS_INTEGRATION_PERIOD, SetIntegrationPeriod); 00787 if( !status ){ 00788 VL6180XDevDataSet(dev, IntegrationPeriod , SetIntegrationPeriod) ; 00789 } 00790 LOG_FUNCTION_END_FMT(status, "%d", (int)SetIntegrationPeriod); 00791 return status; 00792 } 00793 00794 #endif /* HAVE_ALS_SUPPORT */ 00795 00796 00797 int VL6180X::VL6180X_RangePollMeasurement(VL6180XDev_t dev, VL6180X_RangeData_t *pRangeData) 00798 { 00799 int status; 00800 int ClrStatus; 00801 IntrStatus_t IntStatus; 00802 00803 LOG_FUNCTION_START(""); 00804 /* start single range measurement */ 00805 00806 00807 #if VL6180X_SAFE_POLLING_ENTER 00808 /* if device get stopped with left interrupt uncleared , it is required to clear them now or poll for new condition will never occur*/ 00809 status=VL6180X_RangeClearInterrupt(dev); 00810 if(status){ 00811 VL6180X_ErrLog("VL6180X_RangeClearInterrupt fail"); 00812 goto done; 00813 } 00814 #endif 00815 /* //![single_shot_snipet] */ 00816 status=VL6180X_RangeSetSystemMode(dev, MODE_START_STOP|MODE_SINGLESHOT); 00817 if( status ){ 00818 VL6180X_ErrLog("VL6180X_RangeSetSystemMode fail"); 00819 goto done; 00820 } 00821 00822 /* poll for new sample ready */ 00823 while(1 ){ 00824 status=VL6180X_RangeGetInterruptStatus(dev, &IntStatus.val ); 00825 if( status ){ 00826 break; 00827 } 00828 if( IntStatus.status .Error !=0 ){ 00829 VL6180X_ErrLog("GPIO int Error report %d",(int)IntStatus.val ); 00830 status = RANGE_ERROR; 00831 break; 00832 } 00833 else 00834 if( IntStatus.status .Range == RES_INT_STAT_GPIO_NEW_SAMPLE_READY){ 00835 break; 00836 } 00837 wait_ms(10); 00838 } 00839 /* //![single_shot_snipet] */ 00840 00841 if ( !status ){ 00842 status = VL6180X_RangeGetMeasurement(dev, pRangeData); 00843 } 00844 00845 /* clear range interrupt source */ 00846 ClrStatus = VL6180X_RangeClearInterrupt(dev); 00847 if( ClrStatus ){ 00848 VL6180X_ErrLog("VL6180X_RangeClearInterrupt fail"); 00849 /* leave initial status if already in error */ 00850 if( !status ){ 00851 status=ClrStatus; 00852 } 00853 } 00854 done: 00855 LOG_FUNCTION_END(status); 00856 return status; 00857 } 00858 00859 00860 00861 int VL6180X::VL6180X_RangeGetMeasurement(VL6180XDev_t dev, VL6180X_RangeData_t *pRangeData) 00862 { 00863 int status; 00864 uint16_t RawRate; 00865 uint8_t RawStatus; 00866 00867 LOG_FUNCTION_START(""); 00868 00869 status = VL6180X_RangeGetResult(dev, &pRangeData->range_mm ); 00870 if( !status ){ 00871 status = VL6180X_RdWord(dev,RESULT_RANGE_SIGNAL_RATE, &RawRate ); 00872 if( !status ){ 00873 pRangeData->signalRate_mcps = VL6180X_9to7Conv(RawRate); 00874 status = VL6180X_RdByte(dev, RESULT_RANGE_STATUS, &RawStatus); 00875 if( !status ){ 00876 pRangeData->errorStatus = RawStatus >>4; 00877 } 00878 else{ 00879 VL6180X_ErrLog("Rd RESULT_RANGE_STATUS fail"); 00880 } 00881 #if VL6180X_WRAP_AROUND_FILTER_SUPPORT || VL6180X_HAVE_DMAX_RANGING 00882 status = _GetRateResult(dev, pRangeData); 00883 if( status ) 00884 goto error; 00885 #endif 00886 #if VL6180X_WRAP_AROUND_FILTER_SUPPORT 00887 /* if enabled run filter */ 00888 if( _IsWrapArroundActive(dev) ){ 00889 status=_filter_GetResult(dev, pRangeData); 00890 if( !status){ 00891 /* patch the range status and measure if it is filtered */ 00892 if( pRangeData->range_mm != pRangeData->FilteredData .range_mm ) { 00893 pRangeData->errorStatus =RangingFiltered; 00894 pRangeData->range_mm = pRangeData->FilteredData .range_mm ; 00895 } 00896 } 00897 } 00898 #endif 00899 00900 #if VL6180X_HAVE_DMAX_RANGING 00901 if(_IsDMaxActive(dev) ){ 00902 _DMax_Compute(dev, pRangeData); 00903 } 00904 #endif 00905 } 00906 else{ 00907 VL6180X_ErrLog("Rd RESULT_RANGE_SIGNAL_RATE fail"); 00908 } 00909 } 00910 else{ 00911 VL6180X_ErrLog("VL6180X_GetRangeResult fail"); 00912 } 00913 error: 00914 LOG_FUNCTION_END_FMT(status, "%d %d %d", (int)pRangeData->range_mm , (int)pRangeData->signalRate_mcps , (int)pRangeData->errorStatus ) ; 00915 return status; 00916 } 00917 00918 00919 int VL6180X::VL6180X_RangeGetMeasurementIfReady(VL6180XDev_t dev, VL6180X_RangeData_t *pRangeData) 00920 { 00921 int status; 00922 IntrStatus_t IntStatus; 00923 00924 LOG_FUNCTION_START(); 00925 00926 status = VL6180X_RangeGetInterruptStatus(dev, &IntStatus.val ); 00927 if( status ==0 ){ 00928 if( IntStatus.status .Error !=0 ){ 00929 VL6180X_ErrLog("GPIO int Error report %d",(int)IntStatus.val ); 00930 status = RANGE_ERROR; 00931 } 00932 else 00933 if( IntStatus.status .Range == RES_INT_STAT_GPIO_NEW_SAMPLE_READY){ 00934 status = VL6180X_RangeGetMeasurement(dev,pRangeData ); 00935 if( status == 0){ 00936 /* clear range interrupt source */ 00937 status = VL6180X_RangeClearInterrupt(dev); 00938 if( status ){ 00939 VL6180X_ErrLog("VL6180X_RangeClearInterrupt fail"); 00940 } 00941 } 00942 } 00943 else{ 00944 status = NOT_READY; 00945 } 00946 } 00947 else{ 00948 VL6180X_ErrLog("fail to get interrupt status"); 00949 } 00950 LOG_FUNCTION_END(status) ; 00951 return status; 00952 } 00953 00954 int VL6180X::VL6180X_FilterSetState(VL6180XDev_t dev, int state){ 00955 int status; 00956 LOG_FUNCTION_START("%d", state); 00957 #if VL6180X_WRAP_AROUND_FILTER_SUPPORT 00958 VL6180XDevDataSet(dev,WrapAroundFilterActive , state); 00959 status = 0; 00960 #else 00961 status = NOT_SUPPORTED; 00962 #endif 00963 LOG_FUNCTION_END(status); 00964 return status; 00965 } 00966 00967 int VL6180X::VL6180X_FilterGetState(VL6180XDev_t dev){ 00968 int status; 00969 LOG_FUNCTION_START(""); 00970 #if VL6180X_WRAP_AROUND_FILTER_SUPPORT 00971 status = VL6180XDevDataGet(dev,WrapAroundFilterActive ); 00972 #else 00973 status = 0; 00974 #endif 00975 LOG_FUNCTION_END(status); 00976 return status; 00977 } 00978 00979 int VL6180X::VL6180X_RangeGetResult(VL6180XDev_t dev, uint32_t *pRange_mm) { 00980 int status; 00981 uint8_t RawRange; 00982 int32_t Upscale; 00983 00984 LOG_FUNCTION_START("%p",pRange_mm); 00985 00986 status = VL6180X_RdByte(dev, RESULT_RANGE_VAL, &RawRange); 00987 if( !status ){ 00988 Upscale = _GetUpscale(dev); 00989 *pRange_mm= Upscale*(int32_t)RawRange; 00990 } 00991 LOG_FUNCTION_END_FMT(status, "%d", (int)*pRange_mm); 00992 return status; 00993 } 00994 00995 int VL6180X::VL6180X_RangeSetRawThresholds(VL6180XDev_t dev, uint8_t low, uint8_t high) 00996 { 00997 int status; 00998 LOG_FUNCTION_START("%d %d", (int) low, (int)high); 00999 /* TODO we can optimize here grouping high/low in a word but that's cpu endianness dependent */ 01000 status=VL6180X_WrByte(dev, SYSRANGE_THRESH_HIGH,high); 01001 if( !status){ 01002 status=VL6180X_WrByte(dev, SYSRANGE_THRESH_LOW, low); 01003 } 01004 01005 LOG_FUNCTION_END(status); 01006 return status; 01007 } 01008 01009 int VL6180X::VL6180X_RangeSetThresholds(VL6180XDev_t dev, uint16_t low, uint16_t high, int UseSafeParamHold) 01010 { 01011 int status; 01012 int scale; 01013 LOG_FUNCTION_START("%d %d", (int) low, (int)high); 01014 scale=_GetUpscale(dev,UpscaleFactor ); 01015 if( low>scale*255 || high >scale*255){ 01016 status = INVALID_PARAMS; 01017 } 01018 else{ 01019 do{ 01020 if( UseSafeParamHold ){ 01021 status=VL6180X_SetGroupParamHold(dev, 1); 01022 if( status ) 01023 break; 01024 } 01025 status=VL6180X_RangeSetRawThresholds(dev, (uint8_t)(low/scale), (uint8_t)(high/scale)); 01026 if( status ){ 01027 VL6180X_ErrLog("VL6180X_RangeSetRawThresholds fail"); 01028 } 01029 if( UseSafeParamHold ){ 01030 int HoldStatus; 01031 /* tryt to unset param hold vene if previous fail */ 01032 HoldStatus=VL6180X_SetGroupParamHold(dev, 0); 01033 if( !status) 01034 status=HoldStatus; 01035 } 01036 } 01037 while(0); 01038 } 01039 01040 LOG_FUNCTION_END(status); 01041 return status; 01042 } 01043 01044 01045 int VL6180X::VL6180X_RangeGetThresholds(VL6180XDev_t dev, uint16_t *low, uint16_t *high) 01046 { 01047 int status; 01048 uint8_t RawLow, RawHigh; 01049 int scale; 01050 01051 LOG_FUNCTION_START("%p %p", low , high); 01052 01053 scale=_GetUpscale(dev,UpscaleFactor ); 01054 do{ 01055 if( high != NULL ){ 01056 status=VL6180X_RdByte(dev, SYSRANGE_THRESH_HIGH,&RawHigh); 01057 if( status ){ 01058 VL6180X_ErrLog("rd SYSRANGE_THRESH_HIGH fail"); 01059 break; 01060 } 01061 *high=(uint16_t)RawHigh*scale; 01062 } 01063 if( low != NULL ) { 01064 status=VL6180X_RdByte(dev, SYSRANGE_THRESH_LOW, &RawLow); 01065 if( status ){ 01066 VL6180X_ErrLog("rd SYSRANGE_THRESH_LOW fail"); 01067 break; 01068 } 01069 *low=(uint16_t)RawLow*scale; 01070 } 01071 } 01072 while(0); 01073 LOG_FUNCTION_END_FMT(status, "%d %d",(int)*low ,(int)*high); 01074 return status; 01075 } 01076 01077 01078 int VL6180X::VL6180X_RangeGetInterruptStatus(VL6180XDev_t dev, uint8_t *pIntStatus) { 01079 int status; 01080 uint8_t IntStatus; 01081 LOG_FUNCTION_START("%p", pIntStatus); 01082 /* FIXME we are grouping "error" with over status the user must check implicitly for it 01083 * not just new sample or over status , that will nevr show up in case of error*/ 01084 status = VL6180X_RdByte(dev, RESULT_INTERRUPT_STATUS_GPIO, &IntStatus); 01085 *pIntStatus= IntStatus&0xC7; 01086 01087 LOG_FUNCTION_END_FMT(status, "%d", (int)*pIntStatus); 01088 return status; 01089 } 01090 01091 01092 int VL6180X::VL6180X_GetInterruptStatus(VL6180XDev_t dev, uint8_t *IntStatus) 01093 { 01094 int status; 01095 LOG_FUNCTION_START("%p" , IntStatus); 01096 status = VL6180X_RdByte(dev, RESULT_INTERRUPT_STATUS_GPIO, IntStatus); 01097 LOG_FUNCTION_END_FMT(status, "%d", (int)*IntStatus); 01098 return status; 01099 } 01100 01101 int VL6180X::VL6180X_ClearInterrupt(VL6180XDev_t dev, uint8_t IntClear ) 01102 { 01103 int status; 01104 LOG_FUNCTION_START("%d" ,(int)IntClear); 01105 if( IntClear <= 7 ){ 01106 status=VL6180X_WrByte( dev, SYSTEM_INTERRUPT_CLEAR, IntClear); 01107 } 01108 else{ 01109 status = INVALID_PARAMS; 01110 } 01111 LOG_FUNCTION_END(status); 01112 return status; 01113 } 01114 01115 01116 int VL6180X::VL6180X_RangeStaticInit(VL6180XDev_t dev) 01117 { 01118 int status; 01119 LOG_FUNCTION_START(""); 01120 01121 /* REGISTER_TUNING_SR03_270514_CustomerView.txt */ 01122 VL6180X_WrByte( dev, 0x0207, 0x01); 01123 VL6180X_WrByte( dev, 0x0208, 0x01); 01124 VL6180X_WrByte( dev, 0x0096, 0x00); 01125 VL6180X_WrByte( dev, 0x0097, 0xfd); 01126 VL6180X_WrByte( dev, 0x00e3, 0x00); 01127 VL6180X_WrByte( dev, 0x00e4, 0x04); 01128 VL6180X_WrByte( dev, 0x00e5, 0x02); 01129 VL6180X_WrByte( dev, 0x00e6, 0x01); 01130 VL6180X_WrByte( dev, 0x00e7, 0x03); 01131 VL6180X_WrByte( dev, 0x00f5, 0x02); 01132 VL6180X_WrByte( dev, 0x00d9, 0x05); 01133 VL6180X_WrByte( dev, 0x00db, 0xce); 01134 VL6180X_WrByte( dev, 0x00dc, 0x03); 01135 VL6180X_WrByte( dev, 0x00dd, 0xf8); 01136 VL6180X_WrByte( dev, 0x009f, 0x00); 01137 VL6180X_WrByte( dev, 0x00a3, 0x3c); 01138 VL6180X_WrByte( dev, 0x00b7, 0x00); 01139 VL6180X_WrByte( dev, 0x00bb, 0x3c); 01140 VL6180X_WrByte( dev, 0x00b2, 0x09); 01141 VL6180X_WrByte( dev, 0x00ca, 0x09); 01142 VL6180X_WrByte( dev, 0x0198, 0x01); 01143 VL6180X_WrByte( dev, 0x01b0, 0x17); 01144 VL6180X_WrByte( dev, 0x01ad, 0x00); 01145 VL6180X_WrByte( dev, 0x00ff, 0x05); 01146 VL6180X_WrByte( dev, 0x0100, 0x05); 01147 VL6180X_WrByte( dev, 0x0199, 0x05); 01148 VL6180X_WrByte( dev, 0x01a6, 0x1b); 01149 VL6180X_WrByte( dev, 0x01ac, 0x3e); 01150 VL6180X_WrByte( dev, 0x01a7, 0x1f); 01151 VL6180X_WrByte( dev, 0x0030, 0x00); 01152 01153 /* Recommended : Public registers - See data sheet for more detail */ 01154 VL6180X_WrByte( dev, SYSTEM_MODE_GPIO1, 0x10); /* Enables polling for New Sample ready when measurement completes */ 01155 VL6180X_WrByte( dev, READOUT_AVERAGING_SAMPLE_PERIOD, 0x30); /* Set the averaging sample period (compromise between lower noise and increased execution time) */ 01156 VL6180X_WrByte( dev, SYSALS_ANALOGUE_GAIN, 0x46); /* Sets the light and dark gain (upper nibble). Dark gain should not be changed.*/ 01157 VL6180X_WrByte( dev, SYSRANGE_VHV_REPEAT_RATE, 0xFF); /* sets the # of range measurements after which auto calibration of system is performed */ 01158 VL6180X_WrByte( dev, SYSALS_INTEGRATION_PERIOD, 0x63); /* Set ALS integration time to 100ms */ 01159 VL6180X_WrByte( dev, SYSRANGE_VHV_RECALIBRATE, 0x01); /* perform a single temperature calibration of the ranging sensor */ 01160 01161 /* Optional: Public registers - See data sheet for more detail */ 01162 VL6180X_WrByte( dev, SYSRANGE_INTERMEASUREMENT_PERIOD, 0x09); /* Set default ranging inter-measurement period to 100ms */ 01163 VL6180X_WrByte( dev, SYSALS_INTERMEASUREMENT_PERIOD, 0x31); /* Set default ALS inter-measurement period to 500ms */ 01164 VL6180X_WrByte( dev, SYSTEM_INTERRUPT_CONFIG_GPIO, 0x24); /* Configures interrupt on New sample ready */ 01165 01166 01167 status=VL6180X_RangeSetMaxConvergenceTime(dev, 50); /* Calculate ece value on initialization (use max conv) */ 01168 LOG_FUNCTION_END(status); 01169 01170 return status; 01171 } 01172 01173 #if VL6180X_UPSCALE_SUPPORT != 1 01174 01175 int VL6180X::_UpscaleInitPatch0(VL6180XDev_t dev){ 01176 int status; 01177 uint32_t CalValue=0; 01178 CalValue= VL6180XDevDataGet(dev, Part2PartAmbNVM ); 01179 status=VL6180X_WrDWord( dev, 0xDA, CalValue); 01180 return status; 01181 } 01182 01183 /* only include up-scaling register setting when up-scale support is configured in */ 01184 int VL6180X::VL6180X_UpscaleRegInit(VL6180XDev_t dev) 01185 { 01186 /* apply REGISTER_TUNING_ER02_100614_CustomerView.txt */ 01187 VL6180X_WrByte( dev, 0x0207, 0x01); 01188 VL6180X_WrByte( dev, 0x0208, 0x01); 01189 VL6180X_WrByte( dev, 0x0096, 0x00); 01190 VL6180X_WrByte( dev, 0x0097, 0x54); 01191 VL6180X_WrByte( dev, 0x00e3, 0x00); 01192 VL6180X_WrByte( dev, 0x00e4, 0x04); 01193 VL6180X_WrByte( dev, 0x00e5, 0x02); 01194 VL6180X_WrByte( dev, 0x00e6, 0x01); 01195 VL6180X_WrByte( dev, 0x00e7, 0x03); 01196 VL6180X_WrByte( dev, 0x00f5, 0x02); 01197 VL6180X_WrByte( dev, 0x00d9, 0x05); 01198 01199 _UpscaleInitPatch0(dev); 01200 01201 VL6180X_WrByte( dev, 0x009f, 0x00); 01202 VL6180X_WrByte( dev, 0x00a3, 0x28); 01203 VL6180X_WrByte( dev, 0x00b7, 0x00); 01204 VL6180X_WrByte( dev, 0x00bb, 0x28); 01205 VL6180X_WrByte( dev, 0x00b2, 0x09); 01206 VL6180X_WrByte( dev, 0x00ca, 0x09); 01207 VL6180X_WrByte( dev, 0x0198, 0x01); 01208 VL6180X_WrByte( dev, 0x01b0, 0x17); 01209 VL6180X_WrByte( dev, 0x01ad, 0x00); 01210 VL6180X_WrByte( dev, 0x00ff, 0x05); 01211 VL6180X_WrByte( dev, 0x0100, 0x05); 01212 VL6180X_WrByte( dev, 0x0199, 0x05); 01213 VL6180X_WrByte( dev, 0x01a6, 0x1b); 01214 VL6180X_WrByte( dev, 0x01ac, 0x3e); 01215 VL6180X_WrByte( dev, 0x01a7, 0x1f); 01216 VL6180X_WrByte( dev, 0x0030, 0x00); 01217 VL6180X_WrByte( dev, SYSTEM_MODE_GPIO1, 0x10); 01218 VL6180X_WrByte( dev, READOUT_AVERAGING_SAMPLE_PERIOD, 0x30); 01219 VL6180X_WrByte( dev, SYSALS_ANALOGUE_GAIN, 0x46); 01220 VL6180X_WrByte( dev, SYSRANGE_VHV_REPEAT_RATE, 0xFF); 01221 VL6180X_WrByte( dev, SYSALS_INTEGRATION_PERIOD, 0x63); 01222 VL6180X_WrByte( dev, SYSRANGE_VHV_RECALIBRATE, 0x01); 01223 VL6180X_WrByte( dev, SYSRANGE_MAX_AMBIENT_LEVEL_MULT, 0xff); 01224 VL6180X_WrByte( dev, SYSRANGE_INTERMEASUREMENT_PERIOD, 0x09); 01225 VL6180X_WrByte( dev, SYSALS_INTERMEASUREMENT_PERIOD, 0x31); 01226 VL6180X_WrByte( dev, SYSTEM_INTERRUPT_CONFIG_GPIO, 0x24); 01227 #if VL6180X_EXTENDED_RANGE 01228 VL6180X_RangeSetMaxConvergenceTime(dev, 63); 01229 #else 01230 VL6180X_RangeSetMaxConvergenceTime(dev, 50); 01231 #endif 01232 return 0; 01233 } 01234 #else 01235 #define VL6180X_UpscaleRegInit(...) -1 01236 #endif 01237 01238 int VL6180X::VL6180X_UpscaleSetScaling(VL6180XDev_t dev, uint8_t scaling) 01239 { 01240 int status; 01241 uint16_t Scaler; 01242 int8_t Offset; 01243 01244 LOG_FUNCTION_START("%d",(int) scaling); 01245 01246 #ifdef VL6180X_HAVE_UPSCALE_DATA 01247 #define min_scaling 1 01248 #define max_scaling sizeof(ScalerLookUP)/sizeof(ScalerLookUP[0]) 01249 #else 01250 /* we are in fixed config so only allow configured factor */ 01251 #define min_scaling VL6180X_UPSCALE_SUPPORT 01252 #define max_scaling VL6180X_UPSCALE_SUPPORT 01253 #endif 01254 01255 if( scaling>=min_scaling && scaling<= max_scaling ){ 01256 01257 Scaler = ScalerLookUP[scaling-1]; 01258 status = VL6180X_WrWord(dev, RANGE_SCALER, Scaler); 01259 _SetUpscale(dev, scaling ); 01260 01261 /* Apply scaling on part-2-part offset */ 01262 Offset = VL6180XDevDataGet(dev, Part2PartOffsetNVM )/scaling; 01263 status = VL6180X_WrByte(dev, SYSRANGE_PART_TO_PART_RANGE_OFFSET, Offset); 01264 #if ! VL6180X_EXTENDED_RANGE 01265 if( status ==0 ){ 01266 status = VL6180X_RangeSetEceState(dev, scaling == 1); /* enable ece only at 1x scaling */ 01267 } 01268 if( status == 0 && !VL6180X_EXTENDED_RANGE && scaling!=1 ){ 01269 status = NOT_GUARANTEED ; 01270 } 01271 #endif 01272 } 01273 else{ 01274 status = INVALID_PARAMS; 01275 } 01276 #undef min_scaling 01277 #undef max_scaling 01278 LOG_FUNCTION_END(status); 01279 return status; 01280 } 01281 01282 01283 int VL6180X::VL6180X_UpscaleGetScaling(VL6180XDev_t dev) 01284 { 01285 int status; 01286 LOG_FUNCTION_START(""); 01287 status=_GetUpscale(dev ); 01288 LOG_FUNCTION_END(status); 01289 01290 return status; 01291 } 01292 01293 01294 int VL6180X::VL6180X_UpscaleStaticInit(VL6180XDev_t dev) 01295 { 01296 /* todo make these a fail macro in case only 1x is suppoted */ 01297 int status; 01298 01299 LOG_FUNCTION_START(""); 01300 do{ 01301 status=VL6180X_UpscaleRegInit(dev); 01302 if( status){ 01303 VL6180X_ErrLog("regInit fail"); 01304 break; 01305 } 01306 #if VL6180X_EXTENDED_RANGE 01307 status = VL6180X_RangeSetEceState(dev, 0); 01308 if( status){ 01309 VL6180X_ErrLog("VL6180X_RangeSetEceState fail"); 01310 break; 01311 } 01312 #endif 01313 } while(0); 01314 if( !status){ 01315 /* must write the scaler at least once to the device to ensure the scaler is in a known state. */ 01316 status=VL6180X_UpscaleSetScaling(dev, _GetUpscale(dev)); 01317 VL6180X_WrByte( dev, SYSTEM_FRESH_OUT_OF_RESET, 0x00); /* change fresh out of set status to 0 */ 01318 } 01319 LOG_FUNCTION_END(status); 01320 return status; 01321 } 01322 01323 01324 int VL6180X::VL6180X_SetGPIOxPolarity(VL6180XDev_t dev, int pin, int active_high) 01325 { 01326 int status; 01327 LOG_FUNCTION_START("%d %d",(int) pin, (int)active_high); 01328 01329 if( pin ==0 || pin ==1 ){ 01330 uint16_t RegIndex; 01331 uint8_t DataSet; 01332 if( pin==0 ) 01333 RegIndex= SYSTEM_MODE_GPIO0; 01334 else 01335 RegIndex= SYSTEM_MODE_GPIO1; 01336 01337 if (active_high ) 01338 DataSet = GPIOx_POLARITY_SELECT_MASK; 01339 else 01340 DataSet = 0; 01341 01342 status = VL6180X_UpdateByte(dev, RegIndex, (uint8_t)~GPIOx_POLARITY_SELECT_MASK, DataSet); 01343 } 01344 else{ 01345 VL6180X_ErrLog("Invalid pin param %d", (int)pin); 01346 status = INVALID_PARAMS; 01347 } 01348 01349 LOG_FUNCTION_END(status); 01350 01351 return status; 01352 } 01353 01354 int VL6180X::VL6180X_SetGPIOxFunctionality(VL6180XDev_t dev, int pin, uint8_t functionality) 01355 { 01356 int status; 01357 01358 LOG_FUNCTION_START("%d %d",(int) pin, (int)functionality); 01359 01360 if( ((pin ==0) || (pin ==1)) && IsValidGPIOFunction(functionality) ){ 01361 uint16_t RegIndex; 01362 01363 if( pin==0 ) 01364 RegIndex= SYSTEM_MODE_GPIO0; 01365 else 01366 RegIndex= SYSTEM_MODE_GPIO1; 01367 01368 status = VL6180X_UpdateByte(dev, RegIndex, (uint8_t)~GPIOx_FUNCTIONALITY_SELECT_MASK, functionality<<GPIOx_FUNCTIONALITY_SELECT_SHIFT); 01369 if( status){ 01370 VL6180X_ErrLog("Update SYSTEM_MODE_GPIO%d fail", (int)pin); 01371 } 01372 } 01373 else{ 01374 VL6180X_ErrLog("Invalid pin %d or function %d", (int)pin, (int) functionality); 01375 status = INVALID_PARAMS; 01376 } 01377 01378 LOG_FUNCTION_END(status); 01379 return status; 01380 } 01381 01382 01383 int VL6180X::VL6180X_SetupGPIOx(VL6180XDev_t dev, int pin, uint8_t IntFunction, int ActiveHigh) 01384 { 01385 int status; 01386 01387 LOG_FUNCTION_START("%d %d",(int) pin, (int)IntFunction); 01388 01389 if( ((pin ==0) || (pin ==1)) && IsValidGPIOFunction(IntFunction) ){ 01390 uint16_t RegIndex; 01391 uint8_t value=0; 01392 01393 if( pin==0 ) 01394 RegIndex= SYSTEM_MODE_GPIO0; 01395 else 01396 RegIndex= SYSTEM_MODE_GPIO1; 01397 01398 if( ActiveHigh ) 01399 value|=GPIOx_POLARITY_SELECT_MASK; 01400 01401 value |= IntFunction<<GPIOx_FUNCTIONALITY_SELECT_SHIFT; 01402 status = VL6180X_WrByte(dev, RegIndex, value); 01403 if( status ){ 01404 VL6180X_ErrLog("SYSTEM_MODE_GPIO%d wr fail", (int)pin-SYSTEM_MODE_GPIO0); 01405 } 01406 } 01407 else{ 01408 VL6180X_ErrLog("Invalid pin %d or function %d", (int)pin, (int) IntFunction); 01409 status = INVALID_PARAMS; 01410 } 01411 01412 LOG_FUNCTION_END(status); 01413 return status; 01414 } 01415 01416 01417 int VL6180X::VL6180X_DisableGPIOxOut(VL6180XDev_t dev, int pin) { 01418 int status; 01419 01420 LOG_FUNCTION_START("%d",(int)pin); 01421 01422 status=VL6180X_SetGPIOxFunctionality(dev, pin, GPIOx_SELECT_OFF); 01423 01424 LOG_FUNCTION_END(status); 01425 return status; 01426 } 01427 01428 01429 int VL6180X::VL6180X_SetupGPIO1(VL6180XDev_t dev, uint8_t IntFunction, int ActiveHigh) 01430 { 01431 int status; 01432 LOG_FUNCTION_START("%d %d",(int)IntFunction, (int)ActiveHigh ); 01433 status=VL6180X_SetupGPIOx(dev, 1 , IntFunction, ActiveHigh); 01434 LOG_FUNCTION_END(status); 01435 return status; 01436 } 01437 01438 int VL6180X::VL6180X_RangeConfigInterrupt(VL6180XDev_t dev, uint8_t ConfigGpioInt) 01439 { 01440 int status; 01441 01442 if( ConfigGpioInt<= CONFIG_GPIO_INTERRUPT_NEW_SAMPLE_READY){ 01443 status = VL6180X_UpdateByte(dev, SYSTEM_INTERRUPT_CONFIG_GPIO, (uint8_t)(~CONFIG_GPIO_RANGE_MASK), ConfigGpioInt); 01444 } 01445 else{ 01446 VL6180X_ErrLog("Invalid config mode param %d", (int)ConfigGpioInt); 01447 status = INVALID_PARAMS; 01448 } 01449 LOG_FUNCTION_END(status); 01450 return status; 01451 } 01452 01453 01454 int VL6180X::VL6180X_RangeSetEceFactor(VL6180XDev_t dev, uint16_t FactorM, uint16_t FactorD){ 01455 int status; 01456 uint8_t u8; 01457 01458 LOG_FUNCTION_START("%d %d", (int)FactorM, (int)FactorD ); 01459 do{ 01460 /* D cannot be 0 M must be <=D and >= 0 */ 01461 if( FactorM <= FactorD && FactorD> 0){ 01462 VL6180XDevDataSet(dev, EceFactorM , FactorM); 01463 VL6180XDevDataSet(dev, EceFactorD , FactorD); 01464 /* read and re-apply max conv time to get new ece factor set */ 01465 status = VL6180X_RdByte(dev, SYSRANGE_MAX_CONVERGENCE_TIME, &u8); 01466 if( status){ 01467 VL6180X_ErrLog("SYSRANGE_MAX_CONVERGENCE_TIME rd fail "); 01468 break; 01469 } 01470 status = VL6180X_RangeSetMaxConvergenceTime(dev, u8); 01471 if( status <0 ){ 01472 VL6180X_ErrLog("fail to apply time after ece m/d change"); 01473 break; 01474 } 01475 } 01476 else{ 01477 VL6180X_ErrLog("invalid factor %d/%d", (int)FactorM, (int)FactorD ); 01478 status = INVALID_PARAMS; 01479 } 01480 } 01481 while(0); 01482 LOG_FUNCTION_END(status); 01483 return status; 01484 } 01485 01486 int VL6180X::VL6180X_RangeSetEceState(VL6180XDev_t dev, int enable ){ 01487 int status; 01488 uint8_t or_mask; 01489 01490 LOG_FUNCTION_START("%d", (int)enable); 01491 if( enable ) 01492 or_mask = RANGE_CHECK_ECE_ENABLE_MASK; 01493 else 01494 or_mask = 0; 01495 01496 status =VL6180X_UpdateByte(dev, SYSRANGE_RANGE_CHECK_ENABLES, ~RANGE_CHECK_ECE_ENABLE_MASK, or_mask); 01497 LOG_FUNCTION_END(status); 01498 return status; 01499 } 01500 01501 01502 int VL6180X::VL6180X_RangeSetMaxConvergenceTime(VL6180XDev_t dev, uint8_t MaxConTime_msec) 01503 { 01504 int status = 0; 01505 LOG_FUNCTION_START("%d",(int)MaxConTime_msec); 01506 do{ 01507 status=VL6180X_WrByte(dev, SYSRANGE_MAX_CONVERGENCE_TIME, MaxConTime_msec); 01508 if( status ){ 01509 break; 01510 } 01511 status=VL6180X_RangeSetEarlyConvergenceEestimateThreshold(dev); 01512 if( status){ 01513 break; 01514 } 01515 status = _DMax_InitData(dev); 01516 } 01517 while(0); 01518 LOG_FUNCTION_END(status); 01519 return status; 01520 } 01521 01522 int VL6180X::VL6180X_RangeSetInterMeasPeriod(VL6180XDev_t dev, uint32_t InterMeasTime_msec){ 01523 uint8_t SetTime; 01524 int status; 01525 01526 LOG_FUNCTION_START("%d",(int)InterMeasTime_msec); 01527 do { 01528 if( InterMeasTime_msec > 2550 ){ 01529 status = INVALID_PARAMS; 01530 break; 01531 } 01532 /* doc in not 100% clear and confusing about the limit practically all value are OK but 0 01533 * that can hang device in continuous mode */ 01534 if( InterMeasTime_msec < 10 ) { 01535 InterMeasTime_msec=10; 01536 } 01537 SetTime=(uint8_t)(InterMeasTime_msec/10); 01538 status=VL6180X_WrByte(dev, SYSRANGE_INTERMEASUREMENT_PERIOD, SetTime); 01539 if( status ){ 01540 VL6180X_ErrLog("SYSRANGE_INTERMEASUREMENT_PERIOD wr fail"); 01541 } 01542 else 01543 if( SetTime != InterMeasTime_msec /10 ) { 01544 status = MIN_CLIPED; /* on success change status to clip if it did */ 01545 } 01546 }while(0); 01547 LOG_FUNCTION_END(status); 01548 return status; 01549 } 01550 01551 01552 int VL6180X::VL6180X_RangeGetDeviceReady(VL6180XDev_t dev, int * Ready){ 01553 int status; 01554 uint8_t u8; 01555 LOG_FUNCTION_START("%p", (int)Ready); 01556 status=VL6180X_RdByte(dev, RESULT_RANGE_STATUS, &u8); 01557 if( !status) 01558 *Ready = u8&RANGE_DEVICE_READY_MASK; 01559 LOG_FUNCTION_END_FMT(status,"%d", *Ready); 01560 return status; 01561 } 01562 01563 01564 int VL6180X::VL6180X_RangeWaitDeviceReady(VL6180XDev_t dev, int MaxLoop ){ 01565 int status; /* if user specify an invalid <=0 loop count we'll return error */ 01566 int n; 01567 uint8_t u8; 01568 LOG_FUNCTION_START("%d", (int)MaxLoop); 01569 if( MaxLoop<1){ 01570 status=INVALID_PARAMS; 01571 } 01572 else{ 01573 for( n=0; n < MaxLoop ; n++){ 01574 status=VL6180X_RdByte(dev, RESULT_RANGE_STATUS, &u8); 01575 if( status) 01576 break; 01577 u8 = u8 & RANGE_DEVICE_READY_MASK; 01578 if( u8 ) 01579 break; 01580 01581 } 01582 if( !status && !u8 ){ 01583 status = TIME_OUT; 01584 } 01585 } 01586 LOG_FUNCTION_END(status); 01587 return status; 01588 } 01589 01590 int VL6180X::VL6180X_RangeSetSystemMode(VL6180XDev_t dev, uint8_t mode) 01591 { 01592 int status; 01593 LOG_FUNCTION_START("%d", (int)mode); 01594 /* FIXME we are not checking device is ready via @a VL6180X_RangeWaitDeviceReady 01595 * so if called back to back real fast we are not checking 01596 * if previous mode "set" got absorbed => bit 0 must be 0 so that it work 01597 */ 01598 if( mode <= 3){ 01599 status=VL6180X_WrByte(dev, SYSRANGE_START, mode); 01600 if( status ){ 01601 VL6180X_ErrLog("SYSRANGE_START wr fail"); 01602 } 01603 } 01604 else{ 01605 status = INVALID_PARAMS; 01606 } 01607 LOG_FUNCTION_END(status); 01608 return status; 01609 } 01610 01611 01612 int VL6180X::VL6180X_RangeStartContinuousMode(VL6180XDev_t dev) 01613 { 01614 int status; 01615 LOG_FUNCTION_START(""); 01616 status= VL6180X_RangeSetSystemMode(dev, MODE_START_STOP | MODE_CONTINUOUS); 01617 LOG_FUNCTION_END(status); 01618 return status; 01619 } 01620 01621 int VL6180X::VL6180X_RangeStartSingleShot(VL6180XDev_t dev) { 01622 int status; 01623 LOG_FUNCTION_START(""); 01624 status = VL6180X_RangeSetSystemMode(dev, MODE_START_STOP|MODE_SINGLESHOT); 01625 LOG_FUNCTION_END(status); 01626 return status; 01627 } 01628 01629 01630 int VL6180X::VL6180X_RangeSetEarlyConvergenceEestimateThreshold(VL6180XDev_t dev) 01631 { 01632 int status; 01633 01634 const uint32_t cMicroSecPerMilliSec = 1000; 01635 const uint32_t cEceSampleTime_us = 500; 01636 uint32_t ece_factor_m = VL6180XDevDataGet(dev, EceFactorM ); 01637 uint32_t ece_factor_d = VL6180XDevDataGet(dev, EceFactorD ); 01638 uint32_t convergTime_us; 01639 uint32_t fineThresh; 01640 uint32_t eceThresh; 01641 uint8_t u8; 01642 uint32_t maxConv_ms; 01643 int32_t AveTime; 01644 01645 LOG_FUNCTION_START(""); 01646 01647 do{ 01648 status = VL6180X_RdByte(dev, SYSRANGE_MAX_CONVERGENCE_TIME, &u8); 01649 if( status ){ 01650 VL6180X_ErrLog("SYSRANGE_MAX_CONVERGENCE_TIME rd fail"); 01651 break; 01652 } 01653 maxConv_ms = u8; 01654 AveTime = _GetAveTotalTime(dev); 01655 if( AveTime <0 ){ 01656 status=-1; 01657 break; 01658 } 01659 01660 convergTime_us = maxConv_ms * cMicroSecPerMilliSec - AveTime; 01661 status = VL6180X_RdDWord(dev, 0xB8, &fineThresh); 01662 if( status ) { 01663 VL6180X_ErrLog("reg 0xB8 rd fail"); 01664 break; 01665 } 01666 fineThresh*=256; 01667 eceThresh = ece_factor_m * cEceSampleTime_us * fineThresh/(convergTime_us * ece_factor_d); 01668 01669 status=VL6180X_WrWord(dev, SYSRANGE_EARLY_CONVERGENCE_ESTIMATE, (uint16_t)eceThresh); 01670 } 01671 while(0); 01672 01673 LOG_FUNCTION_END(status); 01674 return status; 01675 } 01676 01677 /* 01678 * Return >0 = time 01679 * <0 1 if fail to get read data from device to compute time 01680 */ 01681 int32_t VL6180X::_GetAveTotalTime(VL6180XDev_t dev) { 01682 uint32_t cFwOverhead_us = 24; 01683 uint32_t cVcpSetupTime_us = 70; 01684 uint32_t cPLL2_StartupDelay_us = 200; 01685 uint8_t cMeasMask = 0x07; 01686 uint32_t Samples; 01687 uint32_t SamplePeriod; 01688 uint32_t SingleTime_us; 01689 int32_t TotalAveTime_us; 01690 uint8_t u8; 01691 int status; 01692 01693 LOG_FUNCTION_START(""); 01694 01695 status = VL6180X_RdByte(dev, 0x109, &u8); 01696 if (status) { 01697 VL6180X_ErrLog("rd 0x109 fail"); 01698 return -1; 01699 } 01700 Samples = u8 & cMeasMask; 01701 status = VL6180X_RdByte(dev, READOUT_AVERAGING_SAMPLE_PERIOD, &u8); 01702 if (status) { 01703 VL6180X_ErrLog("i2c READOUT_AVERAGING_SAMPLE_PERIOD fail"); 01704 return -1; 01705 } 01706 SamplePeriod = u8; 01707 SingleTime_us = cFwOverhead_us + cVcpSetupTime_us + (SamplePeriod * 10); 01708 TotalAveTime_us = (Samples + 1) * SingleTime_us + cPLL2_StartupDelay_us; 01709 01710 LOG_FUNCTION_END(TotalAveTime_us); 01711 return TotalAveTime_us; 01712 } 01713 01714 #if VL6180X_HAVE_DMAX_RANGING 01715 #define _GetDMaxDataRetSignalAt400mm(dev) VL6180XDevDataGet(dev, DMaxData.retSignalAt400mm) 01716 #else 01717 #define _GetDMaxDataRetSignalAt400mm(dev) 375 // Use a default high value 01718 #endif 01719 01720 01721 #if VL6180X_WRAP_AROUND_FILTER_SUPPORT 01722 01723 #define FILTER_STDDEV_SAMPLES 6 01724 #define MIN_FILTER_STDDEV_SAMPLES 3 01725 #define MIN_FILTER_VALID_STDDEV_SAMPLES 3 01726 #define FILTER_INVALID_DISTANCE 65535 01727 01728 #define _FilterData(field) VL6180XDevDataGet(dev, FilterData.field) 01729 /* 01730 * One time init 01731 */ 01732 static int _filter_Init( VL6180XDev_t dev) { 01733 int i; 01734 _FilterData(MeasurementIndex) = 0; 01735 01736 _FilterData(Default_ZeroVal) = 0; 01737 _FilterData(Default_VAVGVal) = 0; 01738 _FilterData(NoDelay_ZeroVal) = 0; 01739 _FilterData(NoDelay_VAVGVal) = 0; 01740 _FilterData(Previous_VAVGDiff) = 0; 01741 01742 _FilterData(StdFilteredReads) = 0; 01743 01744 for (i = 0; i < FILTER_NBOF_SAMPLES; i++) { 01745 _FilterData(LastTrueRange)[i] = FILTER_INVALID_DISTANCE; 01746 _FilterData(LastReturnRates)[i] = 0; 01747 } 01748 return 0; 01749 } 01750 01751 01752 static uint32_t _filter_StdDevDamper(uint32_t AmbientRate, uint32_t SignalRate, const uint32_t StdDevLimitLowLight, const uint32_t StdDevLimitLowLightSNR, const uint32_t StdDevLimitHighLight, const uint32_t StdDevLimitHighLightSNR) { 01753 uint32_t newStdDev; 01754 uint16_t SNR; 01755 01756 if (AmbientRate > 0) 01757 SNR = (uint16_t) ((100 * SignalRate) / AmbientRate); 01758 else 01759 SNR = 9999; 01760 01761 if (SNR >= StdDevLimitLowLightSNR) { 01762 newStdDev = StdDevLimitLowLight; 01763 } else { 01764 if (SNR <= StdDevLimitHighLightSNR) 01765 newStdDev = StdDevLimitHighLight; 01766 else { 01767 newStdDev = (uint32_t) (StdDevLimitHighLight + (SNR - StdDevLimitHighLightSNR) * (int) (StdDevLimitLowLight - StdDevLimitHighLight) / (StdDevLimitLowLightSNR - StdDevLimitHighLightSNR)); 01768 } 01769 } 01770 01771 return newStdDev; 01772 } 01773 01774 01775 /* 01776 * Return <0 on error 01777 */ 01778 int32_t VL6180X::_filter_Start(VL6180XDev_t dev, uint16_t m_trueRange_mm, uint16_t m_rawRange_mm, uint32_t m_rtnSignalRate, uint32_t m_rtnAmbientRate, uint16_t errorCode) { 01779 int status; 01780 uint16_t m_newTrueRange_mm = 0; 01781 01782 uint16_t i; 01783 uint16_t bypassFilter = 0; 01784 01785 uint16_t registerValue; 01786 01787 uint32_t register32BitsValue1; 01788 uint32_t register32BitsValue2; 01789 01790 uint16_t ValidDistance = 0; 01791 01792 uint16_t WrapAroundFlag = 0; 01793 uint16_t NoWrapAroundFlag = 0; 01794 uint16_t NoWrapAroundHighConfidenceFlag = 0; 01795 01796 uint16_t FlushFilter = 0; 01797 uint32_t RateChange = 0; 01798 01799 uint16_t StdDevSamples = 0; 01800 uint32_t StdDevDistanceSum = 0; 01801 uint32_t StdDevDistanceMean = 0; 01802 uint32_t StdDevDistance = 0; 01803 uint32_t StdDevRateSum = 0; 01804 uint32_t StdDevRateMean = 0; 01805 uint32_t StdDevRate = 0; 01806 uint32_t StdDevLimitWithTargetMove = 0; 01807 01808 uint32_t VAVGDiff; 01809 uint32_t IdealVAVGDiff; 01810 uint32_t MinVAVGDiff; 01811 uint32_t MaxVAVGDiff; 01812 01813 /* Filter Parameters */ 01814 static const uint16_t ROMABLE_DATA WrapAroundLowRawRangeLimit = 60; 01815 static const uint32_t ROMABLE_DATA WrapAroundLowReturnRateLimit_ROM = 800; // Shall be adapted depending on crossTalk 01816 static const uint16_t ROMABLE_DATA WrapAroundLowRawRangeLimit2 = 165; 01817 static const uint32_t ROMABLE_DATA WrapAroundLowReturnRateLimit2_ROM = 180; // Shall be adapted depending on crossTalk and device sensitivity 01818 01819 static const uint32_t ROMABLE_DATA WrapAroundLowReturnRateFilterLimit_ROM = 850; // Shall be adapted depending on crossTalk and device sensitivity 01820 static const uint16_t ROMABLE_DATA WrapAroundHighRawRangeFilterLimit = 350; 01821 static const uint32_t ROMABLE_DATA WrapAroundHighReturnRateFilterLimit_ROM = 1400; // Shall be adapted depending on crossTalk and device sensitivity 01822 01823 static const uint32_t ROMABLE_DATA WrapAroundMaximumAmbientRateFilterLimit = 7500; 01824 01825 /* Temporal filter data and flush values */ 01826 static const uint32_t ROMABLE_DATA MinReturnRateFilterFlush = 75; 01827 static const uint32_t ROMABLE_DATA MaxReturnRateChangeFilterFlush = 50; 01828 01829 /* STDDEV values and damper values */ 01830 01831 static const uint32_t ROMABLE_DATA StdDevLimitLowLight = 300; 01832 static const uint32_t ROMABLE_DATA StdDevLimitLowLightSNR = 30; /* 0.3 */ 01833 static const uint32_t ROMABLE_DATA StdDevLimitHighLight = 2500; 01834 static const uint32_t ROMABLE_DATA StdDevLimitHighLightSNR = 5; /* 0.05 */ 01835 01836 static const uint32_t ROMABLE_DATA StdDevHighConfidenceSNRLimit = 8; 01837 01838 static const uint32_t ROMABLE_DATA StdDevMovingTargetStdDevLimit = 90000; 01839 01840 static const uint32_t ROMABLE_DATA StdDevMovingTargetReturnRateLimit = 3500; 01841 static const uint32_t ROMABLE_DATA StdDevMovingTargetStdDevForReturnRateLimit = 5000; 01842 01843 static const uint32_t ROMABLE_DATA MAX_VAVGDiff = 1800; 01844 01845 /* WrapAroundDetection variables */ 01846 static const uint16_t ROMABLE_DATA WrapAroundNoDelayCheckPeriod = 2; 01847 static const uint16_t ROMABLE_DATA StdFilteredReadsIncrement = 2; 01848 static const uint16_t ROMABLE_DATA StdMaxFilteredReads = 4; 01849 01850 uint32_t SignalRateDMax; 01851 uint32_t WrapAroundLowReturnRateLimit; 01852 uint32_t WrapAroundLowReturnRateLimit2; 01853 uint32_t WrapAroundLowReturnRateFilterLimit; 01854 uint32_t WrapAroundHighReturnRateFilterLimit; 01855 01856 uint8_t u8, u8_2; 01857 uint32_t XTalkCompRate_KCps; 01858 uint32_t StdDevLimit = 300; 01859 uint32_t MaxOrInvalidDistance = 255*_GetUpscale(dev); 01860 /* #define MaxOrInvalidDistance (uint16_t) (255 * 3) */ 01861 01862 /* Check if distance is Valid or not */ 01863 switch (errorCode) { 01864 case 0x0C: 01865 m_trueRange_mm = MaxOrInvalidDistance; 01866 ValidDistance = 0; 01867 break; 01868 case 0x0D: 01869 m_trueRange_mm = MaxOrInvalidDistance; 01870 ValidDistance = 1; 01871 break; 01872 case 0x0F: 01873 m_trueRange_mm = MaxOrInvalidDistance; 01874 ValidDistance = 1; 01875 break; 01876 default: 01877 if (m_rawRange_mm >= MaxOrInvalidDistance) { 01878 ValidDistance = 0; 01879 } else { 01880 ValidDistance = 1; 01881 } 01882 break; 01883 } 01884 m_newTrueRange_mm = m_trueRange_mm; 01885 01886 XTalkCompRate_KCps = VL6180XDevDataGet(dev, XTalkCompRate_KCps ); 01887 01888 01889 //Update signal rate limits depending on crosstalk 01890 SignalRateDMax = (uint32_t)_GetDMaxDataRetSignalAt400mm(dev) + XTalkCompRate_KCps; 01891 WrapAroundLowReturnRateLimit = WrapAroundLowReturnRateLimit_ROM + XTalkCompRate_KCps; 01892 WrapAroundLowReturnRateLimit2 = ((WrapAroundLowReturnRateLimit2_ROM * SignalRateDMax) / 312) + XTalkCompRate_KCps; 01893 WrapAroundLowReturnRateFilterLimit = ((WrapAroundLowReturnRateFilterLimit_ROM * SignalRateDMax) / 312) + XTalkCompRate_KCps; 01894 WrapAroundHighReturnRateFilterLimit = ((WrapAroundHighReturnRateFilterLimit_ROM * SignalRateDMax) / 312) + XTalkCompRate_KCps; 01895 01896 01897 /* Checks on low range data */ 01898 if ((m_rawRange_mm < WrapAroundLowRawRangeLimit) && (m_rtnSignalRate < WrapAroundLowReturnRateLimit)) { 01899 m_newTrueRange_mm = MaxOrInvalidDistance; 01900 bypassFilter = 1; 01901 } 01902 if ((m_rawRange_mm < WrapAroundLowRawRangeLimit2) && (m_rtnSignalRate < WrapAroundLowReturnRateLimit2)) { 01903 m_newTrueRange_mm = MaxOrInvalidDistance; 01904 bypassFilter = 1; 01905 } 01906 01907 /* Checks on Ambient rate level */ 01908 if (m_rtnAmbientRate > WrapAroundMaximumAmbientRateFilterLimit) { 01909 /* Too high ambient rate */ 01910 FlushFilter = 1; 01911 bypassFilter = 1; 01912 } 01913 /* Checks on Filter flush */ 01914 if (m_rtnSignalRate < MinReturnRateFilterFlush) { 01915 /* Completely lost target, so flush the filter */ 01916 FlushFilter = 1; 01917 bypassFilter = 1; 01918 } 01919 if (_FilterData(LastReturnRates)[0] != 0) { 01920 if (m_rtnSignalRate > _FilterData(LastReturnRates)[0]) 01921 RateChange = (100 * (m_rtnSignalRate - _FilterData(LastReturnRates)[0])) / _FilterData(LastReturnRates)[0]; 01922 else 01923 RateChange = (100 * (_FilterData(LastReturnRates)[0] - m_rtnSignalRate)) / _FilterData(LastReturnRates)[0]; 01924 } else 01925 RateChange = 0; 01926 if (RateChange > MaxReturnRateChangeFilterFlush) { 01927 FlushFilter = 1; 01928 } 01929 /* TODO optimize filter using circular buffer */ 01930 if (FlushFilter == 1) { 01931 _FilterData(MeasurementIndex) = 0; 01932 for (i = 0; i < FILTER_NBOF_SAMPLES; i++) { 01933 _FilterData(LastTrueRange)[i] = FILTER_INVALID_DISTANCE; 01934 _FilterData(LastReturnRates)[i] = 0; 01935 } 01936 } else { 01937 for (i = (uint16_t) (FILTER_NBOF_SAMPLES - 1); i > 0; i--) { 01938 _FilterData(LastTrueRange)[i] = _FilterData(LastTrueRange)[i - 1]; 01939 _FilterData(LastReturnRates)[i] = _FilterData(LastReturnRates)[i - 1]; 01940 } 01941 } 01942 if (ValidDistance == 1) 01943 _FilterData(LastTrueRange)[0] = m_trueRange_mm; 01944 else 01945 _FilterData(LastTrueRange)[0] = FILTER_INVALID_DISTANCE; 01946 _FilterData(LastReturnRates)[0] = m_rtnSignalRate; 01947 01948 /* Check if we need to go through the filter or not */ 01949 if (!(((m_rawRange_mm < WrapAroundHighRawRangeFilterLimit) && (m_rtnSignalRate < WrapAroundLowReturnRateFilterLimit)) || ((m_rawRange_mm >= WrapAroundHighRawRangeFilterLimit) && (m_rtnSignalRate < WrapAroundHighReturnRateFilterLimit)))) 01950 bypassFilter = 1; 01951 01952 /* Check which kind of measurement has been made */ 01953 status = VL6180X_RdByte(dev, 0x01AC, &u8 ); 01954 if( status ){ 01955 VL6180X_ErrLog("0x01AC rd fail"); 01956 goto done_err; 01957 } 01958 registerValue =u8; 01959 01960 /* Read data for filtering */ 01961 status = VL6180X_RdByte(dev, 0x10C, &u8 ); /* read only 8 lsb bits */ 01962 if( status ){ 01963 VL6180X_ErrLog("0x010C rd fail"); 01964 goto done_err; 01965 } 01966 register32BitsValue1=u8; 01967 status = VL6180X_RdByte(dev, 0x0110, &u8); /* read only 8 lsb bits */ 01968 if( status ){ 01969 VL6180X_ErrLog("0x0110 rd fail"); 01970 goto done_err; 01971 } 01972 register32BitsValue2 = u8; 01973 01974 if (registerValue == 0x3E) { 01975 _FilterData(Default_ZeroVal) = register32BitsValue1; 01976 _FilterData(Default_VAVGVal) = register32BitsValue2; 01977 } else { 01978 _FilterData(NoDelay_ZeroVal) = register32BitsValue1; 01979 _FilterData(NoDelay_VAVGVal) = register32BitsValue2; 01980 } 01981 01982 if (bypassFilter == 1) { 01983 /* Do not go through the filter */ 01984 if (registerValue != 0x3E) { 01985 status = VL6180X_WrByte(dev, 0x1AC, 0x3E); 01986 if( status ){ 01987 VL6180X_ErrLog("0x01AC bypass wr fail"); 01988 goto done_err; 01989 } 01990 status = VL6180X_WrByte(dev, 0x0F2, 0x01); 01991 if( status ){ 01992 VL6180X_ErrLog("0x0F2 bypass wr fail"); 01993 goto done_err; 01994 } 01995 } 01996 /* Set both Default and NoDelay To same value */ 01997 _FilterData(Default_ZeroVal) = register32BitsValue1; 01998 _FilterData(Default_VAVGVal) = register32BitsValue2; 01999 _FilterData(NoDelay_ZeroVal) = register32BitsValue1; 02000 _FilterData(NoDelay_VAVGVal) = register32BitsValue2; 02001 _FilterData(MeasurementIndex) = 0; 02002 02003 return m_newTrueRange_mm; 02004 } 02005 02006 if (_FilterData(MeasurementIndex) % WrapAroundNoDelayCheckPeriod == 0) { 02007 u8=0x3C; 02008 u8_2 = 0x05; 02009 } else { 02010 u8=0x3E; 02011 u8_2 = 0x01; 02012 } 02013 status = VL6180X_WrByte(dev, 0x01AC, u8); 02014 if( status ){ 02015 VL6180X_ErrLog("0x01AC wr fail"); 02016 goto done_err; 02017 } 02018 status = VL6180X_WrByte(dev, 0x0F2, u8_2); 02019 if( status ){ 02020 VL6180X_ErrLog("0x0F2 wr fail"); 02021 goto done_err; 02022 } 02023 02024 02025 _FilterData(MeasurementIndex)++; 02026 02027 /* Computes current VAVGDiff */ 02028 if (_FilterData(Default_VAVGVal) > _FilterData(NoDelay_VAVGVal)) 02029 VAVGDiff = _FilterData(Default_VAVGVal) - _FilterData(NoDelay_VAVGVal); 02030 else 02031 VAVGDiff = 0; 02032 _FilterData(Previous_VAVGDiff) = VAVGDiff; 02033 02034 /* Check the VAVGDiff */ 02035 if (_FilterData(Default_ZeroVal) > _FilterData(NoDelay_ZeroVal)) 02036 IdealVAVGDiff = _FilterData(Default_ZeroVal) - _FilterData(NoDelay_ZeroVal); 02037 else 02038 IdealVAVGDiff = _FilterData(NoDelay_ZeroVal) - _FilterData(Default_ZeroVal); 02039 if (IdealVAVGDiff > MAX_VAVGDiff) 02040 MinVAVGDiff = IdealVAVGDiff - MAX_VAVGDiff; 02041 else 02042 MinVAVGDiff = 0; 02043 MaxVAVGDiff = IdealVAVGDiff + MAX_VAVGDiff; 02044 if (VAVGDiff < MinVAVGDiff || VAVGDiff > MaxVAVGDiff) { 02045 WrapAroundFlag = 1; 02046 } else { 02047 /* Go through filtering check */ 02048 02049 /* StdDevLimit Damper on SNR */ 02050 StdDevLimit = _filter_StdDevDamper(m_rtnAmbientRate, m_rtnSignalRate, StdDevLimitLowLight, StdDevLimitLowLightSNR, StdDevLimitHighLight, StdDevLimitHighLightSNR); 02051 02052 /* Standard deviations computations */ 02053 StdDevSamples = 0; 02054 StdDevDistanceSum = 0; 02055 StdDevDistanceMean = 0; 02056 StdDevDistance = 0; 02057 StdDevRateSum = 0; 02058 StdDevRateMean = 0; 02059 StdDevRate = 0; 02060 for (i = 0; (i < FILTER_NBOF_SAMPLES) && (StdDevSamples < FILTER_STDDEV_SAMPLES); i++) { 02061 if (_FilterData(LastTrueRange)[i] != FILTER_INVALID_DISTANCE) { 02062 StdDevSamples = (uint16_t) (StdDevSamples + 1); 02063 StdDevDistanceSum = (uint32_t) (StdDevDistanceSum + _FilterData(LastTrueRange)[i]); 02064 StdDevRateSum = (uint32_t) (StdDevRateSum + _FilterData(LastReturnRates)[i]); 02065 } 02066 } 02067 if (StdDevSamples > 0) { 02068 StdDevDistanceMean = (uint32_t) (StdDevDistanceSum / StdDevSamples); 02069 StdDevRateMean = (uint32_t) (StdDevRateSum / StdDevSamples); 02070 } 02071 /* TODO optimize shorten Std dev in aisngle loop computation using sum of x2 - (sum of x)2 */ 02072 StdDevSamples = 0; 02073 StdDevDistanceSum = 0; 02074 StdDevRateSum = 0; 02075 for (i = 0; (i < FILTER_NBOF_SAMPLES) && (StdDevSamples < FILTER_STDDEV_SAMPLES); i++) { 02076 if (_FilterData(LastTrueRange)[i] != FILTER_INVALID_DISTANCE) { 02077 StdDevSamples = (uint16_t) (StdDevSamples + 1); 02078 StdDevDistanceSum = (uint32_t) (StdDevDistanceSum + (int) (_FilterData(LastTrueRange)[i] - StdDevDistanceMean) * (int) (_FilterData(LastTrueRange)[i] - StdDevDistanceMean)); 02079 StdDevRateSum = (uint32_t) (StdDevRateSum + (int) (_FilterData(LastReturnRates)[i] - StdDevRateMean) * (int) (_FilterData(LastReturnRates)[i] - StdDevRateMean)); 02080 } 02081 } 02082 if (StdDevSamples >= MIN_FILTER_STDDEV_SAMPLES) { 02083 StdDevDistance = (uint16_t) (StdDevDistanceSum / StdDevSamples); 02084 StdDevRate = (uint16_t) (StdDevRateSum / StdDevSamples); 02085 } else { 02086 StdDevDistance = 0; 02087 StdDevRate = 0; 02088 } 02089 02090 /* Check Return rate standard deviation */ 02091 if (StdDevRate < StdDevMovingTargetStdDevLimit) { 02092 if (StdDevSamples < MIN_FILTER_VALID_STDDEV_SAMPLES) { 02093 m_newTrueRange_mm = MaxOrInvalidDistance; 02094 } else { 02095 /* Check distance standard deviation */ 02096 if (StdDevRate < StdDevMovingTargetReturnRateLimit) 02097 StdDevLimitWithTargetMove = StdDevLimit + (((StdDevMovingTargetStdDevForReturnRateLimit - StdDevLimit) * StdDevRate) / StdDevMovingTargetReturnRateLimit); 02098 else 02099 StdDevLimitWithTargetMove = StdDevMovingTargetStdDevForReturnRateLimit; 02100 02101 if ((StdDevDistance * StdDevHighConfidenceSNRLimit) < StdDevLimitWithTargetMove) { 02102 NoWrapAroundHighConfidenceFlag = 1; 02103 } else { 02104 if (StdDevDistance < StdDevLimitWithTargetMove) { 02105 if (StdDevSamples >= MIN_FILTER_VALID_STDDEV_SAMPLES) { 02106 NoWrapAroundFlag = 1; 02107 } else { 02108 m_newTrueRange_mm = MaxOrInvalidDistance; 02109 } 02110 } else { 02111 WrapAroundFlag = 1; 02112 } 02113 } 02114 } 02115 } else { 02116 WrapAroundFlag = 1; 02117 } 02118 } 02119 02120 if (m_newTrueRange_mm == MaxOrInvalidDistance) { 02121 if (_FilterData(StdFilteredReads) > 0) 02122 _FilterData(StdFilteredReads) = (uint16_t) (_FilterData(StdFilteredReads) - 1); 02123 } else { 02124 if (WrapAroundFlag == 1) { 02125 m_newTrueRange_mm = MaxOrInvalidDistance; 02126 _FilterData(StdFilteredReads) = (uint16_t) (_FilterData(StdFilteredReads) + StdFilteredReadsIncrement); 02127 if (_FilterData(StdFilteredReads) > StdMaxFilteredReads) 02128 _FilterData(StdFilteredReads) = StdMaxFilteredReads; 02129 } else { 02130 if (NoWrapAroundFlag == 1) { 02131 if (_FilterData(StdFilteredReads) > 0) { 02132 m_newTrueRange_mm = MaxOrInvalidDistance; 02133 if (_FilterData(StdFilteredReads) > StdFilteredReadsIncrement) 02134 _FilterData(StdFilteredReads) = (uint16_t) (_FilterData(StdFilteredReads) - StdFilteredReadsIncrement); 02135 else 02136 _FilterData(StdFilteredReads) = 0; 02137 } 02138 } else { 02139 if (NoWrapAroundHighConfidenceFlag == 1) { 02140 _FilterData(StdFilteredReads) = 0; 02141 } 02142 } 02143 } 02144 } 02145 02146 return m_newTrueRange_mm; 02147 done_err: 02148 return -1; 02149 02150 #undef MaxOrInvalidDistance 02151 } 02152 02153 02154 int VL6180X::_filter_GetResult(VL6180XDev_t dev, VL6180X_RangeData_t *pRangeData) { 02155 uint32_t m_rawRange_mm = 0; 02156 int32_t FilteredRange; 02157 const uint8_t scaler = _GetUpscale(dev); 02158 uint8_t u8; 02159 int status; 02160 02161 do { 02162 status = VL6180X_RdByte(dev, RESULT_RANGE_RAW, &u8); 02163 if (status) { 02164 VL6180X_ErrLog("RESULT_RANGE_RAW rd fail"); 02165 break; 02166 } 02167 m_rawRange_mm = u8; 02168 02169 FilteredRange = _filter_Start(dev, pRangeData->range_mm , (m_rawRange_mm * scaler), pRangeData->rtnRate , pRangeData->rtnAmbRate , pRangeData->errorStatus ); 02170 if( FilteredRange<0 ){ 02171 status = -1; 02172 break; 02173 } 02174 pRangeData->FilteredData .range_mm = FilteredRange; 02175 pRangeData->FilteredData .rawRange_mm = m_rawRange_mm * scaler; 02176 } while (0); 02177 return status; 02178 } 02179 02180 #undef _FilterData 02181 #undef FILTER_STDDEV_SAMPLES 02182 #undef MIN_FILTER_STDDEV_SAMPLES 02183 #undef MIN_FILTER_VALID_STDDEV_SAMPLES 02184 #undef FILTER_INVALID_DISTANCE 02185 02186 #endif /* VL6180X_WRAP_AROUND_FILTER_SUPPORT */ 02187 02188 #ifdef VL6180X_HAVE_RATE_DATA 02189 02190 int VL6180X::_GetRateResult(VL6180XDev_t dev, VL6180X_RangeData_t *pRangeData) { 02191 uint32_t m_rtnConvTime = 0; 02192 uint32_t m_rtnSignalRate = 0; 02193 uint32_t m_rtnAmbientRate = 0; 02194 uint32_t m_rtnSignalCount = 0; 02195 uint32_t m_rtnAmbientCount = 0; 02196 uint32_t m_refConvTime = 0; 02197 uint32_t cRtnSignalCountMax = 0x7FFFFFFF; 02198 uint32_t cDllPeriods = 6; 02199 uint32_t calcConvTime = 0; 02200 02201 int status; 02202 02203 do { 02204 02205 status = VL6180X_RdDWord(dev, RESULT_RANGE_RETURN_SIGNAL_COUNT, &m_rtnSignalCount); 02206 if (status) { 02207 VL6180X_ErrLog("RESULT_RANGE_RETURN_SIGNAL_COUNT rd fail"); 02208 break; 02209 } 02210 if (m_rtnSignalCount > cRtnSignalCountMax) { 02211 m_rtnSignalCount = 0; 02212 } 02213 02214 status = VL6180X_RdDWord(dev, RESULT_RANGE_RETURN_AMB_COUNT, &m_rtnAmbientCount); 02215 if (status) { 02216 VL6180X_ErrLog("RESULT_RANGE_RETURN_AMB_COUNTrd fail"); 02217 break; 02218 } 02219 02220 02221 status = VL6180X_RdDWord(dev, RESULT_RANGE_RETURN_CONV_TIME, &m_rtnConvTime); 02222 if (status) { 02223 VL6180X_ErrLog("RESULT_RANGE_RETURN_CONV_TIME rd fail"); 02224 break; 02225 } 02226 02227 status = VL6180X_RdDWord(dev, RESULT_RANGE_REFERENCE_CONV_TIME, &m_refConvTime); 02228 if (status) { 02229 VL6180X_ErrLog("RESULT_RANGE_REFERENCE_CONV_TIME rd fail"); 02230 break; 02231 } 02232 02233 pRangeData->rtnConvTime = m_rtnConvTime; 02234 pRangeData->refConvTime = m_refConvTime; 02235 02236 calcConvTime = m_refConvTime; 02237 if (m_rtnConvTime > m_refConvTime) { 02238 calcConvTime = m_rtnConvTime; 02239 } 02240 if (calcConvTime == 0) 02241 calcConvTime = 63000; 02242 02243 m_rtnSignalRate = (m_rtnSignalCount * 1000) / calcConvTime; 02244 m_rtnAmbientRate = (m_rtnAmbientCount * cDllPeriods * 1000) / calcConvTime; 02245 02246 pRangeData->rtnRate = m_rtnSignalRate; 02247 pRangeData->rtnAmbRate = m_rtnAmbientRate; 02248 02249 02250 } while (0); 02251 return status; 02252 } 02253 #endif /* VL6180X_HAVE_RATE_DATA */ 02254 02255 02256 int VL6180X::VL6180X_DMaxSetState(VL6180XDev_t dev, int state){ 02257 int status; 02258 LOG_FUNCTION_START("%d", state); 02259 #if VL6180X_HAVE_DMAX_RANGING 02260 VL6180XDevDataSet(dev,DMaxEnable, state); 02261 if( state ){ 02262 status = _DMax_InitData(dev); 02263 } 02264 else { 02265 status = 0; 02266 } 02267 #else 02268 status = NOT_SUPPORTED; 02269 #endif 02270 LOG_FUNCTION_END(status); 02271 return status; 02272 } 02273 02274 int VL6180X::VL6180X_DMaxGetState(VL6180XDev_t dev){ 02275 int status; 02276 LOG_FUNCTION_START(""); 02277 #if VL6180X_HAVE_DMAX_RANGING 02278 status = VL6180XDevDataGet(dev,DMaxEnable); 02279 #else 02280 status = 0; 02281 #endif 02282 LOG_FUNCTION_END(status); 02283 return status; 02284 } 02285 02286 02287 #if VL6180X_HAVE_DMAX_RANGING 02288 02289 #define _DMaxData(field) VL6180XDevDataGet(dev, DMaxData.field) 02290 /* 02291 * Convert fix point x.7 to KCpount per sec 02292 */ 02293 02294 #ifndef VL6180X_PLATFORM_PROVIDE_SQRT 02295 02296 /* 02297 * 32 bit integer square root with not so bad precision (integer result) and is quite fast 02298 * see http://en.wikipedia.org/wiki/Methods_of_computing_square_roots 02299 */ 02300 uint32_t VL6180X_SqrtUint32(uint32_t num) { 02301 uint32_t res = 0; 02302 uint32_t bit = 1 << 30; /* The second-to-top bit is set: 1 << 30 for 32 bits */ 02303 02304 /* "bit" starts at the highest power of four <= the argument. */ 02305 while (bit > num) 02306 bit >>= 2; 02307 02308 while (bit != 0) { 02309 if (num >= res + bit) { 02310 num -= res + bit; 02311 res = (res >> 1) + bit; 02312 } 02313 else 02314 res >>= 1; 02315 bit >>= 2; 02316 } 02317 return res; 02318 } 02319 #endif 02320 02321 02322 /* DMax one time init */ 02323 void _DMax_OneTimeInit(VL6180XDev_t dev){ 02324 _DMaxData(ambTuningWindowFactor_K)=DEF_AMBIENT_TUNING; 02325 } 02326 02327 02328 static uint32_t _DMax_RawValueAtRateKCps(VL6180XDev_t dev, int32_t rate){ 02329 uint32_t snrLimit_K; 02330 int32_t DMaxSq; 02331 uint32_t RawDMax; 02332 DMaxFix_t retSignalAt400mm; 02333 uint32_t ambTuningWindowFactor_K; 02334 02335 02336 ambTuningWindowFactor_K = _DMaxData(ambTuningWindowFactor_K); 02337 snrLimit_K = _DMaxData(snrLimit_K); 02338 retSignalAt400mm = _DMaxData(retSignalAt400mm); /* 12 to 18 bits Kcps */ 02339 if( rate > 0 ){ 02340 DMaxSq = 400*400*1000 / rate -(400*400/330); /* K of (1/RtnAmb -1/330 )=> 30bit- (12-18)bit => 12-18 bits*/ 02341 if( DMaxSq<= 0){ 02342 RawDMax = 0; 02343 } 02344 else{ 02345 /* value can be more 32 bit so base on raneg apply *retSignalAt400mm before or after division to presevr accuracy */ 02346 if( DMaxSq< (2<<12) ){ 02347 DMaxSq = DMaxSq*retSignalAt400mm/(snrLimit_K+ambTuningWindowFactor_K); /* max 12 + 12 to 18 -10 => 12-26 bit */ 02348 }else{ 02349 DMaxSq = DMaxSq/(snrLimit_K+ambTuningWindowFactor_K)*retSignalAt400mm; /* 12 to 18 -10 + 12 to 18 *=> 12-26 bit */ 02350 } 02351 RawDMax=VL6180X_SqrtUint32(DMaxSq); 02352 } 02353 } 02354 else{ 02355 RawDMax = 0x7FFFFFFF; /* bigest possibmle 32bit signed value */ 02356 } 02357 return RawDMax; 02358 } 02359 02360 /* 02361 * fetch static data from register to avoid re-read 02362 * precompute all intermediate constant and cliipings 02363 * 02364 * to be re-used/call on changes of : 02365 * 0x2A 02366 * SYSRANGE_MAX_AMBIENT_LEVEL_MULT 02367 * Dev Data XtalkComRate_KCPs 02368 * SYSRANGE_MAX_CONVERGENCE_TIME 02369 * SYSRANGE_RANGE_CHECK_ENABLES mask RANGE_CHECK_RANGE_ENABLE_MASK 02370 * range 0xb8-0xbb (0xbb) 02371 */ 02372 int VL6180X::_DMax_InitData(VL6180XDev_t dev){ 02373 int status, warning; 02374 uint8_t u8; 02375 uint16_t u16; 02376 uint32_t u32; 02377 uint32_t Reg2A_KCps; 02378 uint32_t RegB8; 02379 uint8_t MaxConvTime; 02380 uint32_t XTalkCompRate_KCps; 02381 uint32_t RangeIgnoreThreshold; 02382 int32_t minSignalNeeded; 02383 uint8_t SysRangeCheckEn; 02384 uint8_t snrLimit; 02385 warning=0; 02386 02387 static const int ROMABLE_DATA MaxConvTimeAdjust=-4; 02388 02389 LOG_FUNCTION_START(""); 02390 do{ 02391 status = VL6180X_RdByte(dev, 0x02A ,&u8); 02392 if( status ){ 02393 VL6180X_ErrLog("Reg 0x02A rd fail"); 02394 break; 02395 } 02396 02397 if( u8 == 0 ) { 02398 warning = CALIBRATION_WARNING; 02399 u8 = 40; /* use a default average value */ 02400 } 02401 Reg2A_KCps = Fix7_2_KCPs(u8); /* convert to KCPs */ 02402 02403 status = VL6180X_RdByte(dev, SYSRANGE_RANGE_CHECK_ENABLES, &SysRangeCheckEn); 02404 if (status) { 02405 VL6180X_ErrLog("SYSRANGE_RANGE_CHECK_ENABLES rd fail "); 02406 break; 02407 } 02408 02409 status = VL6180X_RdByte(dev, SYSRANGE_MAX_CONVERGENCE_TIME, &MaxConvTime); 02410 if( status){ 02411 VL6180X_ErrLog("SYSRANGE_MAX_CONVERGENCE_TIME rd fail "); 02412 break; 02413 } 02414 02415 status = VL6180X_RdDWord(dev, 0x0B8, &RegB8); 02416 if( status ){ 02417 VL6180X_ErrLog("reg 0x0B8 rd fail "); 02418 break; 02419 } 02420 02421 status = VL6180X_RdByte(dev, SYSRANGE_MAX_AMBIENT_LEVEL_MULT, &snrLimit); 02422 if( status){ 02423 VL6180X_ErrLog("SYSRANGE_MAX_AMBIENT_LEVEL_MULT rd fail "); 02424 break; 02425 } 02426 _DMaxData(snrLimit_K) = (int32_t)16*1000/snrLimit; 02427 XTalkCompRate_KCps = VL6180XDevDataGet(dev, XTalkCompRate_KCps ); 02428 02429 if( Reg2A_KCps >= XTalkCompRate_KCps){ 02430 _DMaxData(retSignalAt400mm)=( Reg2A_KCps - XTalkCompRate_KCps); 02431 } 02432 else{ 02433 _DMaxData(retSignalAt400mm)=0; /* Reg2A_K - XTalkCompRate_KCp <0 is invalid */ 02434 } 02435 02436 /* if xtalk range check is off omit it in snr clipping */ 02437 if( SysRangeCheckEn&RANGE_CHECK_RANGE_ENABLE_MASK ){ 02438 status = VL6180X_RdWord(dev, SYSRANGE_RANGE_IGNORE_THRESHOLD, &u16); 02439 if( status){ 02440 VL6180X_ErrLog("SYSRANGE_RANGE_IGNORE_THRESHOLD rd fail "); 02441 break; 02442 } 02443 RangeIgnoreThreshold = Fix7_2_KCPs(u16); 02444 } 02445 else{ 02446 RangeIgnoreThreshold = 0; 02447 } 02448 02449 minSignalNeeded = (RegB8*256)/((int32_t)MaxConvTime+(int32_t)MaxConvTimeAdjust); /* KCps 8+8 bit -(1 to 6 bit) => 15-10 bit */ 02450 /* minSignalNeeded = max ( minSignalNeeded, RangeIgnoreThreshold - XTalkCompRate_KCps) */ 02451 if( minSignalNeeded <= RangeIgnoreThreshold - XTalkCompRate_KCps ) 02452 minSignalNeeded = RangeIgnoreThreshold - XTalkCompRate_KCps; 02453 02454 u32 = (minSignalNeeded*(uint32_t)snrLimit)/16; 02455 _DMaxData(ClipSnrLimit ) = _DMax_RawValueAtRateKCps(dev, u32 ); /* clip to dmax to min signal snr limit rate*/ 02456 } 02457 while(0); 02458 if( !status ) 02459 status = warning; 02460 LOG_FUNCTION_END(status); 02461 return status; 02462 } 02463 02464 static int _DMax_Compute(VL6180XDev_t dev, VL6180X_RangeData_t *pRange){ 02465 uint32_t rtnAmbRate; 02466 int32_t DMax; 02467 int scaling; 02468 uint16_t HwLimitAtScale; 02469 static const int ROMABLE_DATA rtnAmbLowLimit_KCps=330*1000; 02470 02471 rtnAmbRate = pRange->rtnAmbRate ; 02472 if( rtnAmbRate < rtnAmbLowLimit_KCps ){ 02473 DMax = _DMax_RawValueAtRateKCps( dev, rtnAmbRate); 02474 scaling = _GetUpscale(dev); 02475 HwLimitAtScale=UpperLimitLookUP[scaling - 1]; 02476 02477 if( DMax > _DMaxData(ClipSnrLimit) ){ 02478 DMax=_DMaxData(ClipSnrLimit); 02479 } 02480 if( DMax > HwLimitAtScale ){ 02481 DMax=HwLimitAtScale; 02482 } 02483 pRange->DMax =DMax; 02484 } 02485 else{ 02486 pRange->DMax = 0; 02487 } 02488 return 0; 02489 } 02490 02491 #undef _DMaxData 02492 #undef Fix7_2_KCPs 02493 02494 #endif /* VL6180X_HAVE_DMAX_RANGING */ 02495 02496 02497 /******************************************************************************/ 02498 /******************************************************************************/ 02499 02500 02501 02502 /****************** Write and read functions from I2C *************************/ 02503 02504 int VL6180X::VL6180X_WrByte(VL6180XDev_t dev, uint16_t index, uint8_t data) 02505 { 02506 int status; 02507 02508 status=VL6180X_I2CWrite(dev->I2cAddr, index, &data,(uint8_t)1); 02509 return status; 02510 } 02511 02512 int VL6180X::VL6180X_WrWord(VL6180XDev_t dev, uint16_t index, uint16_t data) 02513 { 02514 int status; 02515 02516 status=VL6180X_I2CWrite(dev->I2cAddr, index, (uint8_t *)&data,(uint8_t)2); 02517 return status; 02518 } 02519 02520 int VL6180X::VL6180X_WrDWord(VL6180XDev_t dev, uint16_t index, uint32_t data) 02521 { 02522 int status; 02523 02524 status=VL6180X_I2CWrite(dev->I2cAddr, index, (uint8_t *)&data,(uint8_t)4); 02525 return status; 02526 } 02527 02528 int VL6180X::VL6180X_RdByte(VL6180XDev_t dev, uint16_t index, uint8_t *data) 02529 { 02530 int status; 02531 02532 uint8_t buffer=0; 02533 status=VL6180X_I2CRead(dev->I2cAddr, index, &buffer,1); 02534 if(!status) 02535 { 02536 *data=buffer; 02537 } 02538 return status; 02539 } 02540 02541 int VL6180X::VL6180X_RdWord(VL6180XDev_t dev, uint16_t index, uint16_t *data) 02542 { 02543 int status; 02544 02545 uint8_t buffer[2]; 02546 buffer[0]=buffer[1]=0; 02547 status=VL6180X_I2CRead(dev->I2cAddr, index, buffer, 2); 02548 if(!status) 02549 { 02550 memcpy(data, buffer, 2); 02551 } 02552 return status; 02553 } 02554 02555 int VL6180X::VL6180X_RdDWord(VL6180XDev_t dev, uint16_t index, uint32_t *data) 02556 { 02557 int status; 02558 uint8_t buffer[4]; 02559 buffer[0]=buffer[1]=buffer[2]=buffer[3]=0; 02560 status=VL6180X_I2CRead(dev->I2cAddr, index, buffer,4); 02561 if(!status) 02562 { 02563 memcpy(data, buffer, 4); 02564 } 02565 return status; 02566 } 02567 02568 int VL6180X::VL6180X_UpdateByte(VL6180XDev_t dev, uint16_t index, uint8_t AndData, uint8_t OrData) 02569 { 02570 int status; 02571 uint8_t buffer=0; 02572 02573 status=VL6180X_I2CWrite(dev->I2cAddr, index, (uint8_t *)&buffer,(uint8_t)0); 02574 if(!status) 02575 { 02576 /* read data direct onto buffer */ 02577 status=VL6180X_I2CRead(dev->I2cAddr, index, &buffer,1); 02578 if(!status) 02579 { 02580 buffer=(buffer & AndData)|OrData; 02581 status=VL6180X_I2CWrite(dev->I2cAddr, index, &buffer, (uint8_t)1); 02582 } 02583 } 02584 return status; 02585 } 02586 02587 int VL6180X::VL6180X_I2CWrite(uint8_t DeviceAddr, uint16_t RegisterAddr, uint8_t* pBuffer, uint16_t NumByteToWrite) 02588 { 02589 int ret; 02590 int i; 02591 uint8_t tmp[TEMP_BUF_SIZE]; 02592 uint16_t myRegisterAddr = RegisterAddr; 02593 uint16_t WriteDeviceAddr=0; 02594 02595 /* First, prepare 8 bits device address in 7bits i2ci format */ 02596 WriteDeviceAddr=DeviceAddr*2; 02597 if(NumByteToWrite >= TEMP_BUF_SIZE) return -2; 02598 02599 /* then prepare 16 bits register address in BE format. Then, send data and STOP condition */ 02600 tmp[0] = *(((uint8_t*)&myRegisterAddr)+1); 02601 tmp[1] = (uint8_t)RegisterAddr; 02602 02603 if(NumByteToWrite>1) /* swap data endianess */ 02604 { 02605 for(i=0;i<NumByteToWrite;i++) 02606 { 02607 tmp[NumByteToWrite+sizeof(RegisterAddr)-1-i]=pBuffer[i]; 02608 } 02609 } 02610 else 02611 { 02612 memcpy(tmp+sizeof(RegisterAddr), pBuffer, NumByteToWrite); 02613 } 02614 ret = _dev_i2c->write(WriteDeviceAddr, (const char*)tmp, NumByteToWrite+sizeof(RegisterAddr), false); 02615 02616 if(ret) 02617 return -1; 02618 return 0; 02619 } 02620 02621 int VL6180X::VL6180X_I2CRead(uint8_t DeviceAddr, uint16_t RegisterAddr, uint8_t* pBuffer, uint16_t NumByteToRead) 02622 { 02623 int ret,i; 02624 uint8_t tmp[TEMP_BUF_SIZE]; 02625 uint16_t myRegisterAddr = RegisterAddr; 02626 uint16_t myRegisterAddrBE; 02627 uint16_t ReadDeviceAddr=DeviceAddr; 02628 02629 ReadDeviceAddr=DeviceAddr*2; 02630 myRegisterAddrBE = *(((uint8_t*)&myRegisterAddr)+1); 02631 *(((uint8_t*)&myRegisterAddrBE)+1) = (uint8_t)myRegisterAddr; 02632 02633 /* Send 8 bits device address and 16 bits register address in BE format, with no STOP condition */ 02634 ret = _dev_i2c->write(ReadDeviceAddr, (const char*)&myRegisterAddrBE, sizeof(RegisterAddr), true); 02635 if(!ret) 02636 { 02637 ReadDeviceAddr|=0x001; 02638 /* Read data, with STOP condition */ 02639 ret = _dev_i2c->read(ReadDeviceAddr, (char*)tmp, NumByteToRead, false); 02640 } 02641 if(ret) 02642 return -1; 02643 02644 if(NumByteToRead>1) /* swap data endianess */ 02645 { 02646 for(i=0;i<NumByteToRead;i++) 02647 { 02648 pBuffer[i] = tmp[NumByteToRead-1-i]; 02649 } 02650 } 02651 else 02652 { 02653 memcpy(pBuffer, tmp, NumByteToRead); 02654 } 02655 return 0; 02656 } 02657 02658 /******************************************************************************/ 02659 02660 int VL6180X::als_set_thresholds(uint16_t lux_threshold_low, uint16_t lux_threshold_high) 02661 { 02662 uint32_t AlsAnGain, IntPeriod, AlsScaler , GainFix, RawAlsHigh, RawAlsLow; 02663 uint16_t RawThreshLow, RawThreshHigh; 02664 const uint32_t LuxResxIntIme =(uint32_t)(0.56f* DEF_INT_PEFRIOD *(1<<LUXRES_FIX_PREC)); 02665 void *p_low; 02666 void *p_high; 02667 02668 AlsAnGain=VL6180XDevDataGet(_device, AlsGainCode ); 02669 IntPeriod=VL6180XDevDataGet(_device, IntegrationPeriod ); 02670 AlsScaler=VL6180XDevDataGet(_device, AlsScaler); 02671 GainFix=AlsGainLookUp[AlsAnGain]; 02672 IntPeriod++; 02673 RawAlsLow=lux_threshold_low*AlsScaler*GainFix; 02674 RawAlsLow=RawAlsLow*IntPeriod; 02675 RawAlsLow=RawAlsLow/LuxResxIntIme; 02676 RawAlsHigh=lux_threshold_high*(AlsScaler*GainFix); 02677 RawAlsHigh=RawAlsHigh*IntPeriod; 02678 RawAlsHigh=RawAlsHigh/LuxResxIntIme; 02679 p_low=&RawAlsLow; 02680 RawThreshLow=*(uint16_t*)p_low; 02681 p_high=&RawAlsHigh; 02682 RawThreshHigh=*(uint16_t*)p_high; 02683 return VL6180X_AlsSetThresholds(_device, RawThreshLow, RawThreshHigh); 02684 } 02685 02686 int VL6180X::read_id(uint8_t *id) 02687 { 02688 return VL6180X_RdByte(_device, IDENTIFICATION_MODEL_ID, id); 02689 } 02690 02691 02692 int VL6180X::start_measurement(operating_mode_t operating_mode, void (*fptr)(void), uint16_t low, uint16_t high) 02693 { 02694 int status, r_status, l_status; 02695 02696 switch (operating_mode) { 02697 case(range_single_shot_polling): 02698 r_status=VL6180X_RangeConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_NEW_SAMPLE_READY); 02699 l_status=VL6180X_AlsConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_DISABLED); 02700 disable_gpio_x_out(1); 02701 if((!r_status)&&(!l_status)) 02702 return RangeMeasPollSingleShot(); 02703 else 02704 return (r_status|l_status); 02705 02706 case(als_single_shot_polling): 02707 r_status=VL6180X_AlsConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_NEW_SAMPLE_READY); 02708 l_status=VL6180X_RangeConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_DISABLED); 02709 disable_gpio_x_out(1); 02710 if((!r_status)&&(!l_status)) 02711 return AlsMeasPollSingleShot(); 02712 else 02713 return (r_status|l_status); 02714 02715 case(range_continuous_polling): 02716 r_status=VL6180X_RangeConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_NEW_SAMPLE_READY); 02717 l_status=VL6180X_AlsConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_DISABLED); 02718 if((!r_status)&&(!l_status)) 02719 return RangeMeasPollContinuousMode(); 02720 else 02721 return (r_status|l_status); 02722 02723 case(als_continuous_polling): 02724 r_status=VL6180X_AlsConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_NEW_SAMPLE_READY); 02725 l_status=VL6180X_RangeConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_DISABLED); 02726 if((!r_status)&&(!l_status)) 02727 return AlsMeasPollContinuousMode(); 02728 else 02729 return (r_status|l_status); 02730 02731 case(range_continuous_interrupt): 02732 if (_gpio1Int==NULL) return 1; 02733 r_status=VL6180X_RangeConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_NEW_SAMPLE_READY); 02734 l_status=VL6180X_AlsConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_DISABLED); 02735 if((!r_status)&&(!l_status)) 02736 return RangeMeasIntContinuousMode(fptr); 02737 else 02738 return (r_status|l_status); 02739 02740 case(als_continuous_interrupt): 02741 if (_gpio1Int==NULL) return 1; 02742 l_status=VL6180X_AlsConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_NEW_SAMPLE_READY); 02743 r_status=VL6180X_RangeConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_DISABLED); 02744 if((!r_status)&&(!l_status)) 02745 return AlsMeasIntContinuousMode(fptr); 02746 else 02747 return (r_status|l_status); 02748 02749 case(interleaved_mode_interrupt): 02750 if (_gpio1Int==NULL) return 1; 02751 l_status=VL6180X_AlsConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_NEW_SAMPLE_READY); 02752 r_status=VL6180X_RangeConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_DISABLED); 02753 if((!r_status)&&(!l_status)) 02754 return InterleavedMode(fptr); 02755 else 02756 return (r_status|l_status); 02757 02758 case(range_continuous_polling_low_threshold): 02759 r_status=VL6180X_RangeConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_LEVEL_LOW); 02760 l_status=VL6180X_AlsConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_DISABLED); 02761 if((!r_status)&&(!l_status)) 02762 { 02763 status=RangeSetLowThreshold(low); 02764 if(!status) 02765 return RangeMeasPollContinuousMode(); 02766 else 02767 return status; 02768 } 02769 else 02770 return (r_status|l_status); 02771 02772 case(range_continuous_polling_high_threshold): 02773 r_status=VL6180X_RangeConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_LEVEL_HIGH); 02774 l_status=VL6180X_AlsConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_DISABLED); 02775 if((!r_status)&&(!l_status)) 02776 { 02777 status=RangeSetHighThreshold(high); 02778 if(!status) 02779 return RangeMeasPollContinuousMode(); 02780 else 02781 return status; 02782 } 02783 else 02784 return (r_status|l_status); 02785 02786 case(range_continuous_polling_out_of_window): 02787 r_status=VL6180X_RangeConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_OUT_OF_WINDOW); 02788 l_status=VL6180X_AlsConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_DISABLED); 02789 if((!r_status)&&(!l_status)) 02790 { 02791 status=VL6180X_RangeSetThresholds(_device,low,high,1); 02792 if(!status) 02793 return RangeMeasPollContinuousMode(); 02794 else 02795 return status; 02796 } 02797 else 02798 return (r_status|l_status); 02799 02800 case(als_continuous_polling_low_threshold): 02801 l_status=VL6180X_AlsConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_LEVEL_LOW); 02802 r_status=VL6180X_RangeConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_DISABLED); 02803 if((!r_status)&&(!l_status)) 02804 { 02805 status=AlsSetLowThreshold(low); 02806 if(!status) 02807 return AlsMeasPollContinuousMode(); 02808 else 02809 return status; 02810 } 02811 else 02812 return (r_status|l_status); 02813 02814 case(als_continuous_polling_high_threshold): 02815 l_status=VL6180X_AlsConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_LEVEL_HIGH); 02816 r_status=VL6180X_RangeConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_DISABLED); 02817 if((!r_status)&&(!l_status)) 02818 { 02819 status=AlsSetHighThreshold(high); 02820 if(!status) 02821 return AlsMeasPollContinuousMode(); 02822 else 02823 return status; 02824 } 02825 else 02826 return (r_status|l_status); 02827 02828 case(als_continuous_polling_out_of_window): 02829 l_status=VL6180X_AlsConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_OUT_OF_WINDOW); 02830 r_status=VL6180X_RangeConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_DISABLED); 02831 if((!r_status)&&(!l_status)) 02832 { 02833 status=VL6180X_AlsSetThresholds(_device,low,high); 02834 if(!status) 02835 return AlsMeasPollContinuousMode(); 02836 else 02837 return status; 02838 } 02839 else 02840 return (r_status|l_status); 02841 02842 case(range_continuous_interrupt_low_threshold): 02843 if (_gpio1Int==NULL) return 1; 02844 r_status=VL6180X_RangeConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_LEVEL_LOW); 02845 l_status=VL6180X_AlsConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_DISABLED); 02846 if((!r_status)&&(!l_status)) 02847 { 02848 status=RangeSetLowThreshold(low); 02849 if(!status) 02850 return RangeMeasIntContinuousMode(fptr); 02851 else 02852 return status; 02853 } 02854 else 02855 return (r_status|l_status); 02856 02857 case(range_continuous_interrupt_high_threshold): 02858 if (_gpio1Int==NULL) return 1; 02859 r_status=VL6180X_RangeConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_LEVEL_HIGH); 02860 l_status=VL6180X_AlsConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_DISABLED); 02861 if((!r_status)&&(!l_status)) 02862 { 02863 status=RangeSetHighThreshold(high); 02864 if(!status) 02865 return RangeMeasIntContinuousMode(fptr); 02866 else 02867 return status; 02868 } 02869 else 02870 return (r_status|l_status); 02871 02872 case(range_continuous_interrupt_out_of_window): 02873 if (_gpio1Int==NULL) return 1; 02874 r_status=VL6180X_RangeConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_OUT_OF_WINDOW); 02875 l_status=VL6180X_AlsConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_DISABLED); 02876 if((!r_status)&&(!l_status)) 02877 { 02878 status=VL6180X_RangeSetThresholds(_device,low,high,1); 02879 if(!status) 02880 return RangeMeasIntContinuousMode(fptr); 02881 else 02882 return status; 02883 } 02884 else 02885 return (r_status|l_status); 02886 02887 case(als_continuous_interrupt_low_threshold): 02888 if (_gpio1Int==NULL) return 1; 02889 l_status=VL6180X_AlsConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_LEVEL_LOW); 02890 r_status=VL6180X_RangeConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_DISABLED); 02891 if((!r_status)&&(!l_status)) 02892 { 02893 status=AlsSetLowThreshold(low); 02894 if(!status) 02895 return AlsMeasIntContinuousMode(fptr); 02896 else 02897 return status; 02898 } 02899 else 02900 return (r_status|l_status); 02901 02902 case(als_continuous_interrupt_high_threshold): 02903 if (_gpio1Int==NULL) return 1; 02904 l_status=VL6180X_AlsConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_LEVEL_HIGH); 02905 r_status=VL6180X_RangeConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_DISABLED); 02906 if((!r_status)&&(!l_status)) 02907 { 02908 status=AlsSetHighThreshold(high); 02909 if(!status) 02910 return AlsMeasIntContinuousMode(fptr); 02911 else 02912 return status; 02913 } 02914 else 02915 return (r_status|l_status); 02916 02917 case(als_continuous_interrupt_out_of_window): 02918 if (_gpio1Int==NULL) return 1; 02919 l_status=VL6180X_AlsConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_OUT_OF_WINDOW); 02920 r_status=VL6180X_RangeConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_DISABLED); 02921 if((!r_status)&&(!l_status)) 02922 { 02923 status=VL6180X_AlsSetThresholds(_device,low,high); 02924 if(!status) 02925 return AlsMeasIntContinuousMode(fptr); 02926 else 02927 return status; 02928 } 02929 else 02930 return (r_status|l_status); 02931 02932 default: 02933 return INVALID_PARAMS; 02934 } 02935 } 02936 02937 int VL6180X::GetRangeError(measure_data_t *Data, VL6180X_RangeData_t RangeData) 02938 { 02939 Data->range_error=RangeData.errorStatus ; 02940 if(Data->range_error!=0) 02941 { 02942 VL6180X_ErrLog("Range error %d",Data->range_error); 02943 return RANGE_ERROR; 02944 } 02945 return NoError_; 02946 } 02947 02948 int VL6180X::GetAlsError(measure_data_t *Data, VL6180X_AlsData_t AlsData) 02949 { 02950 Data->als_error=AlsData.errorStatus; 02951 if(Data->als_error!=0) 02952 { 02953 VL6180X_ErrLog("Light error %d",Data->light_error); 02954 return API_ERROR; 02955 } 02956 return NoError_; 02957 } 02958 02959 int VL6180X::RangeMeasPollSingleShot() 02960 { 02961 int status; 02962 02963 status=VL6180X_RangeClearInterrupt(_device); 02964 if(status) 02965 { 02966 VL6180X_ErrLog("VL6180X_RangeClearInterrupt fail"); 02967 return status; 02968 } 02969 status=VL6180X_ClearErrorInterrupt(_device); 02970 if(status) 02971 { 02972 VL6180X_ErrLog("VL6180X_ClearErrorInterrupt fail"); 02973 return status; 02974 } 02975 return range_start_single_shot(); 02976 } 02977 02978 02979 int VL6180X::AlsMeasPollSingleShot() 02980 { 02981 int status; 02982 02983 status=VL6180X_AlsClearInterrupt(_device); 02984 if(status) 02985 { 02986 VL6180X_ErrLog("VL6180X_AlsClearInterrupt fail"); 02987 return status; 02988 } 02989 status=VL6180X_ClearErrorInterrupt(_device); 02990 if(status) 02991 { 02992 VL6180X_ErrLog("VL6180X_ClearErrorInterrupt fail"); 02993 return status; 02994 } 02995 return als_start_single_shot(); 02996 } 02997 02998 02999 int VL6180X::RangeMeasPollContinuousMode() 03000 { 03001 int status; 03002 03003 status=VL6180X_RangeClearInterrupt(_device); 03004 if(status) 03005 { 03006 VL6180X_ErrLog("VL6180X_RangeClearInterrupt fail"); 03007 return status; 03008 } 03009 status=VL6180X_ClearErrorInterrupt(_device); 03010 if(status) 03011 { 03012 VL6180X_ErrLog("VL6180X_ClearErrorInterrupt fail"); 03013 return status; 03014 } 03015 return range_start_continuous_mode(); 03016 } 03017 03018 03019 int VL6180X::AlsMeasPollContinuousMode() 03020 { 03021 int status; 03022 03023 status=VL6180X_AlsClearInterrupt(_device); 03024 if(status) 03025 { 03026 VL6180X_ErrLog("VL6180X_AlsClearInterrupt fail"); 03027 return status; 03028 } 03029 status=VL6180X_ClearErrorInterrupt(_device); 03030 if(status) 03031 { 03032 VL6180X_ErrLog("VL6180X_ClearErrorInterrupt fail"); 03033 return status; 03034 } 03035 return als_start_continuous_mode(); 03036 } 03037 03038 03039 int VL6180X::AlsGetMeasurementIfReady(VL6180XDev_t dev, VL6180X_AlsData_t *pAlsData) 03040 { 03041 int status; 03042 uint8_t IntStatus; 03043 03044 status=VL6180X_AlsGetInterruptStatus(dev, &IntStatus); 03045 if(!status) 03046 { 03047 if(IntStatus==RES_INT_STAT_GPIO_NEW_SAMPLE_READY) 03048 { 03049 status = VL6180X_AlsGetMeasurement(dev, pAlsData); 03050 if(!status) 03051 { 03052 status=VL6180X_AlsClearInterrupt(_device); 03053 if(status) 03054 VL6180X_ErrLog("VL6180X_AlsClearInterrupt fail"); 03055 } 03056 } 03057 else 03058 status=NOT_READY; 03059 } 03060 else 03061 VL6180X_ErrLog("Failed to get interrupt status"); 03062 return status; 03063 } 03064 03065 03066 int VL6180X::RangeMeasIntContinuousMode(void (*fptr)(void)) 03067 { 03068 int status, ClrStatus; 03069 03070 enable_interrupt_measure_detection_irq(); 03071 attach_interrupt_measure_detection_irq(fptr); 03072 status=setup_gpio_1(GPIOx_SELECT_GPIO_INTERRUPT_OUTPUT, 1); 03073 ClrStatus=VL6180X_ClearAllInterrupt(_device); 03074 if(ClrStatus) 03075 VL6180X_ErrLog("VL6180X_ClearErrorInterrupt fail"); 03076 if(!status) 03077 status=range_start_continuous_mode(); 03078 return status; 03079 } 03080 03081 03082 int VL6180X::AlsMeasIntContinuousMode(void (*fptr)(void)) 03083 { 03084 int status, ClrStatus; 03085 03086 enable_interrupt_measure_detection_irq(); 03087 attach_interrupt_measure_detection_irq(fptr); 03088 status=setup_gpio_1(GPIOx_SELECT_GPIO_INTERRUPT_OUTPUT, 1); 03089 ClrStatus=VL6180X_ClearAllInterrupt(_device); 03090 if(ClrStatus) 03091 VL6180X_ErrLog("VL6180X_ClearErrorInterrupt fail"); 03092 if(!status) 03093 status=als_start_continuous_mode(); 03094 return status; 03095 } 03096 03097 03098 int VL6180X::StartInterleavedMode() 03099 { 03100 int status; 03101 uint16_t integration_period, intermeasurement_period_ms; 03102 uint8_t max_convergence_time; 03103 uint8_t buf; 03104 03105 status=VL6180X_WrByte(_device, 0x2A3, 1); 03106 if(status) 03107 { 03108 VL6180X_ErrLog("Failed to write INTERLEAVED_MODE_ENABLE!\n\r"); 03109 return status; 03110 } 03111 status=VL6180X_RdByte(_device, SYSRANGE_MAX_CONVERGENCE_TIME, &max_convergence_time); 03112 if(status) 03113 { 03114 VL6180X_ErrLog("Failed to read SYSRANGE_MAX_CONVERGENCE_TIME!\n\r"); 03115 return status; 03116 } 03117 status=VL6180X_RdWord(_device, SYSALS_INTEGRATION_PERIOD, &integration_period); 03118 if(status) 03119 { 03120 VL6180X_ErrLog("Failed to read SYSALS_INTEGRATION_PERIOD!\n\r"); 03121 return status; 03122 } 03123 max_convergence_time&=0x3F; 03124 integration_period&=0x01FF; 03125 intermeasurement_period_ms=((max_convergence_time+5)+(integration_period*1.1)); 03126 intermeasurement_period_ms=(intermeasurement_period_ms/0.9)+10; 03127 intermeasurement_period_ms=200; 03128 status=VL6180X_AlsSetInterMeasurementPeriod(_device, intermeasurement_period_ms); 03129 VL6180X_RdByte(_device, 0x03E, &buf); 03130 if(status) 03131 { 03132 VL6180X_ErrLog("Failed to write SYSALS_INTERMEASUREMENT_PERIOD!\n\r"); 03133 return status; 03134 } 03135 return als_start_continuous_mode(); 03136 } 03137 03138 03139 int VL6180X::InterleavedMode(void (*fptr)(void)) 03140 { 03141 int status, ClrStatus; 03142 03143 enable_interrupt_measure_detection_irq(); 03144 attach_interrupt_measure_detection_irq(fptr); 03145 status=setup_gpio_1(GPIOx_SELECT_GPIO_INTERRUPT_OUTPUT, 1); 03146 ClrStatus=VL6180X_ClearAllInterrupt(_device); 03147 if(ClrStatus) 03148 VL6180X_ErrLog("VL6180X_ClearErrorInterrupt fail"); 03149 if(!status) 03150 status=StartInterleavedMode(); 03151 return status; 03152 } 03153 03154 03155 int VL6180X::handle_irq(operating_mode_t operating_mode, measure_data_t *Data) 03156 { 03157 int status; 03158 enable_interrupt_measure_detection_irq(); 03159 status=get_measurement(operating_mode, Data); 03160 return status; 03161 } 03162 03163 03164 int VL6180X::RangeSetLowThreshold(uint16_t threshold) 03165 { 03166 int status; 03167 uint16_t low, high; 03168 03169 status=VL6180X_RangeGetThresholds(_device, &low, &high); 03170 if(!status) 03171 status=VL6180X_RangeSetThresholds(_device, threshold, high, 1); 03172 return status; 03173 } 03174 03175 03176 int VL6180X::RangeSetHighThreshold(uint16_t threshold) 03177 { 03178 int status; 03179 uint16_t low, high; 03180 03181 status=VL6180X_RangeGetThresholds(_device, &low, &high); 03182 if(!status) 03183 status=VL6180X_RangeSetThresholds(_device, low, threshold, 1); 03184 return status; 03185 } 03186 03187 03188 int VL6180X::AlsSetLowThreshold(uint16_t threshold) 03189 { 03190 int status; 03191 lux_t low, high; 03192 03193 status=AlsGetThresholds(_device, &low, &high); 03194 if(!status) 03195 status=VL6180X_AlsSetThresholds(_device, threshold, high); 03196 return status; 03197 } 03198 03199 03200 int VL6180X::AlsSetHighThreshold(uint16_t threshold) 03201 { 03202 int status; 03203 lux_t low, high; 03204 03205 status=AlsGetThresholds(_device, &low, &high); 03206 if(!status) 03207 status=VL6180X_AlsSetThresholds(_device, low, threshold); 03208 return status; 03209 } 03210 03211 03212 int VL6180X::AlsGetThresholds(VL6180XDev_t dev, lux_t *low, lux_t *high) 03213 { 03214 int status; 03215 uint16_t RawAlsLow, RawAlsHigh; 03216 uint32_t luxLowValue, luxHighValue, IntPeriod, AlsAnGain, GainFix, AlsScaler ; 03217 const uint32_t LuxResxIntIme =(uint32_t)(0.56f* DEF_INT_PEFRIOD *(1<<LUXRES_FIX_PREC)); 03218 03219 status=VL6180X_RdWord(dev, SYSALS_THRESH_LOW, &RawAlsLow); 03220 if(status) 03221 { 03222 VL6180X_ErrLog("rd SYSALS_THRESH_LOW fail"); 03223 return status; 03224 } 03225 status=VL6180X_RdWord(dev, SYSALS_THRESH_HIGH, &RawAlsHigh); 03226 if(status) 03227 { 03228 VL6180X_ErrLog("rd SYSALS_THRESH_HIGH fail"); 03229 return status; 03230 } 03231 AlsAnGain=VL6180XDevDataGet(dev, AlsGainCode ); 03232 IntPeriod=VL6180XDevDataGet(dev, IntegrationPeriod ); 03233 AlsScaler=VL6180XDevDataGet(dev, AlsScaler); 03234 GainFix=AlsGainLookUp[AlsAnGain]; 03235 IntPeriod++; 03236 luxLowValue=(uint32_t)RawAlsLow*LuxResxIntIme; 03237 luxLowValue=luxLowValue/IntPeriod; 03238 luxLowValue=luxLowValue/(AlsScaler*GainFix); 03239 luxHighValue=(uint32_t)RawAlsHigh*LuxResxIntIme; 03240 luxHighValue=luxHighValue/IntPeriod; 03241 luxHighValue=luxHighValue/(AlsScaler*GainFix); 03242 *low=luxLowValue; 03243 *high=luxHighValue; 03244 return status; 03245 } 03246 03247 03248 int VL6180X::get_measurement(operating_mode_t operating_mode, measure_data_t *Data) 03249 { 03250 switch(operating_mode) 03251 { 03252 case(range_single_shot_polling): 03253 case(range_continuous_polling): 03254 case(range_continuous_interrupt): 03255 case(range_continuous_polling_low_threshold): 03256 case(range_continuous_polling_high_threshold): 03257 case(range_continuous_polling_out_of_window): 03258 case(range_continuous_interrupt_low_threshold): 03259 case(range_continuous_interrupt_high_threshold): 03260 case(range_continuous_interrupt_out_of_window): 03261 return GetRangeMeas(operating_mode, Data); 03262 03263 case(als_single_shot_polling): 03264 case(als_continuous_polling): 03265 case(als_continuous_interrupt): 03266 case(als_continuous_polling_low_threshold): 03267 case(als_continuous_polling_high_threshold): 03268 case(als_continuous_polling_out_of_window): 03269 case(als_continuous_interrupt_low_threshold): 03270 case(als_continuous_interrupt_high_threshold): 03271 case(als_continuous_interrupt_out_of_window): 03272 return GetAlsMeas(operating_mode, Data); 03273 03274 case(interleaved_mode_interrupt): 03275 return GetRangeAlsMeas(Data); 03276 03277 default: 03278 return INVALID_PARAMS; 03279 } 03280 } 03281 03282 03283 int VL6180X::GetRangeMeas(operating_mode_t operating_mode, measure_data_t *Data) 03284 { 03285 VL6180X_RangeData_t RangeData; 03286 int status, ClrStatus; 03287 IntrStatus_t IntStatus; 03288 03289 status=VL6180X_RangeGetInterruptStatus(_device, &IntStatus.val ); 03290 if(!status) 03291 { 03292 Data->int_error=IntStatus.status .Error ; 03293 if(IntStatus.status .Error !=0) 03294 { 03295 VL6180X_ErrLog("GPIO int Error report %d",(int)IntStatus.val ); 03296 status=RANGE_ERROR; 03297 } 03298 } 03299 else 03300 { 03301 VL6180X_ErrLog("Failed to read RESULT_INTERRUPT_STATUS_GPIO"); 03302 } 03303 ClrStatus=VL6180X_RangeClearInterrupt(_device); 03304 if(ClrStatus) 03305 { 03306 VL6180X_ErrLog("VL6180X_RangeClearInterrupt fail"); 03307 } 03308 ClrStatus=VL6180X_ClearErrorInterrupt(_device); 03309 if(ClrStatus) 03310 { 03311 VL6180X_ErrLog("VL6180X_ClearErrorInterrupt fail"); 03312 } 03313 if(status) 03314 return status; 03315 if((operating_mode==range_single_shot_polling)||(operating_mode==range_continuous_polling)||(operating_mode==range_continuous_interrupt)) 03316 { 03317 if(IntStatus.status .Range ==RES_INT_STAT_GPIO_NEW_SAMPLE_READY) 03318 status=VL6180X_RangeGetMeasurement(_device, &RangeData); 03319 else 03320 return NOT_READY; 03321 } 03322 else if((operating_mode==range_continuous_polling_low_threshold)||(operating_mode==range_continuous_interrupt_low_threshold)) 03323 { 03324 if(IntStatus.status .Range ==RES_INT_STAT_GPIO_LOW_LEVEL_THRESHOLD) 03325 status=VL6180X_RangeGetMeasurement(_device, &RangeData); 03326 else 03327 return NOT_READY; 03328 } 03329 else if((operating_mode==range_continuous_polling_high_threshold)||(operating_mode==range_continuous_interrupt_high_threshold)) 03330 { 03331 if(IntStatus.status .Range ==RES_INT_STAT_GPIO_HIGH_LEVEL_THRESHOLD) 03332 status=VL6180X_RangeGetMeasurement(_device, &RangeData); 03333 else 03334 return NOT_READY; 03335 } 03336 else if((operating_mode==range_continuous_polling_out_of_window)||(operating_mode==range_continuous_interrupt_out_of_window)) 03337 { 03338 if(IntStatus.status .Range ==RES_INT_STAT_GPIO_OUT_OF_WINDOW) 03339 status=VL6180X_RangeGetMeasurement(_device, &RangeData); 03340 else 03341 return NOT_READY; 03342 } 03343 if(!status) 03344 { 03345 status=GetRangeError(Data, RangeData); 03346 if(!status) 03347 Data->range_mm=RangeData.range_mm ; 03348 else 03349 Data->range_mm=0xFFFFFFFF; 03350 } 03351 return status; 03352 } 03353 03354 03355 int VL6180X::GetAlsMeas(operating_mode_t operating_mode, measure_data_t *Data) 03356 { 03357 VL6180X_AlsData_t AlsData; 03358 int status, ClrStatus; 03359 uint8_t IntStatus; 03360 03361 status=VL6180X_AlsGetInterruptStatus(_device, &IntStatus); 03362 if(status) 03363 { 03364 VL6180X_ErrLog("Failed to read RESULT_INTERRUPT_STATUS_GPIO"); 03365 } 03366 ClrStatus=VL6180X_AlsClearInterrupt(_device); 03367 if(ClrStatus) 03368 { 03369 VL6180X_ErrLog("VL6180X_AlsClearInterrupt fail"); 03370 } 03371 ClrStatus=VL6180X_ClearErrorInterrupt(_device); 03372 if(ClrStatus) 03373 { 03374 VL6180X_ErrLog("VL6180X_ClearErrorInterrupt fail"); 03375 } 03376 if(status) 03377 return status; 03378 if((operating_mode==als_single_shot_polling)||(operating_mode==als_continuous_polling)||(operating_mode==als_continuous_interrupt)) 03379 { 03380 if(IntStatus==RES_INT_STAT_GPIO_NEW_SAMPLE_READY) 03381 status=VL6180X_AlsGetMeasurement(_device, &AlsData); 03382 else 03383 return NOT_READY; 03384 } 03385 else if((operating_mode==als_continuous_polling_low_threshold)||(operating_mode==als_continuous_interrupt_low_threshold)) 03386 { 03387 if(IntStatus==RES_INT_STAT_GPIO_LOW_LEVEL_THRESHOLD) 03388 status=VL6180X_AlsGetMeasurement(_device, &AlsData); 03389 else 03390 return NOT_READY; 03391 } 03392 else if((operating_mode==als_continuous_polling_high_threshold)||(operating_mode==als_continuous_interrupt_high_threshold)) 03393 { 03394 if(IntStatus==RES_INT_STAT_GPIO_HIGH_LEVEL_THRESHOLD) 03395 status=VL6180X_AlsGetMeasurement(_device, &AlsData); 03396 else 03397 return NOT_READY; 03398 } 03399 else if((operating_mode==als_continuous_polling_out_of_window)||(operating_mode==als_continuous_interrupt_out_of_window)) 03400 { 03401 if(IntStatus==RES_INT_STAT_GPIO_OUT_OF_WINDOW) 03402 status=VL6180X_AlsGetMeasurement(_device, &AlsData); 03403 else 03404 return NOT_READY; 03405 } 03406 if(!status) 03407 { 03408 status=GetAlsError(Data, AlsData); 03409 if(!status) 03410 Data->lux=AlsData.lux; 03411 else 03412 Data->lux=0xFFFFFFFF; 03413 } 03414 return status; 03415 } 03416 03417 03418 int VL6180X::GetRangeAlsMeas(measure_data_t *Data) 03419 { 03420 int status, ClrStatus, r_status, l_status; 03421 IntrStatus_t IntStatus; 03422 VL6180X_RangeData_t RangeData; 03423 VL6180X_AlsData_t AlsData; 03424 03425 status=VL6180X_RdByte(_device, RESULT_INTERRUPT_STATUS_GPIO, &IntStatus.val ); 03426 if(!status) 03427 { 03428 Data->int_error=IntStatus.status .Error ; 03429 if(IntStatus.status .Error !=0) 03430 { 03431 VL6180X_ErrLog("GPIO int Error report %d",(int)IntStatus.val ); 03432 status=RANGE_ERROR; 03433 } 03434 } 03435 else 03436 { 03437 VL6180X_ErrLog("Failed to read RESULT_INTERRUPT_STATUS_GPIO"); 03438 } 03439 ClrStatus=VL6180X_ClearAllInterrupt(_device); 03440 if(ClrStatus) 03441 VL6180X_ErrLog("VL6180X_ClearAllInterrupt fail"); 03442 if(status) 03443 return status; 03444 03445 if(IntStatus.status .Als ==RES_INT_STAT_GPIO_NEW_SAMPLE_READY) 03446 { 03447 r_status=VL6180X_RangeGetMeasurement(_device, &RangeData); 03448 l_status=VL6180X_AlsGetMeasurement(_device, &AlsData); 03449 if((!r_status)&&(!l_status)) 03450 { 03451 r_status=GetRangeError(Data, RangeData); 03452 l_status=GetAlsError(Data, AlsData); 03453 if(!r_status) 03454 Data->range_mm=RangeData.range_mm ; 03455 else 03456 Data->range_mm=0xFFFFFFFF; 03457 if(!l_status) 03458 Data->lux=AlsData.lux; 03459 else 03460 Data->lux=0xFFFFFFFF; 03461 status=r_status|l_status; 03462 } 03463 else 03464 { 03465 status=r_status|l_status; 03466 } 03467 } 03468 else 03469 return NOT_READY; 03470 return status; 03471 } 03472 03473 03474 int VL6180X::stop_measurement(operating_mode_t operating_mode) 03475 { 03476 int status; 03477 03478 switch(operating_mode) 03479 { 03480 case(range_single_shot_polling): 03481 case(range_continuous_polling): 03482 case(range_continuous_interrupt): 03483 case(range_continuous_polling_low_threshold): 03484 case(range_continuous_polling_high_threshold): 03485 case(range_continuous_polling_out_of_window): 03486 case(range_continuous_interrupt_low_threshold): 03487 case(range_continuous_interrupt_high_threshold): 03488 case(range_continuous_interrupt_out_of_window): 03489 return StopRangeMeasurement(operating_mode); 03490 03491 case(als_single_shot_polling): 03492 case(als_continuous_polling): 03493 case(als_continuous_interrupt): 03494 case(als_continuous_polling_low_threshold): 03495 case(als_continuous_polling_high_threshold): 03496 case(als_continuous_polling_out_of_window): 03497 case(als_continuous_interrupt_low_threshold): 03498 case(als_continuous_interrupt_high_threshold): 03499 case(als_continuous_interrupt_out_of_window): 03500 return StopAlsMeasurement(operating_mode); 03501 03502 case(interleaved_mode_interrupt): 03503 status=StopRangeMeasurement(range_continuous_interrupt); 03504 if(!status) 03505 return StopAlsMeasurement(als_continuous_interrupt); 03506 else return status; 03507 03508 default: 03509 return INVALID_PARAMS; 03510 } 03511 } 03512 03513 03514 int VL6180X::IsPresent() 03515 { 03516 int status; uint8_t id; 03517 03518 status=read_id(&id); 03519 if(status) 03520 VL6180X_ErrLog("Failed to read ID device. _device not present!\n\r"); 03521 return status; 03522 } 03523 03524 03525 int VL6180X::StopRangeMeasurement(operating_mode_t operating_mode) 03526 { 03527 int status; 03528 03529 if(operating_mode==range_single_shot_polling) 03530 status=VL6180X_RangeSetSystemMode(_device, MODE_SINGLESHOT); 03531 else 03532 status=VL6180X_RangeSetSystemMode(_device, MODE_START_STOP|MODE_SINGLESHOT); 03533 if(status) 03534 return status; 03535 status=VL6180X_RangeConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_DISABLED); 03536 if(status) 03537 { 03538 VL6180X_ErrLog("VL6180X_RangeConfigInterrupt fail"\n\r); 03539 return status; 03540 } 03541 status=VL6180X_RangeClearInterrupt(_device); 03542 if(status) 03543 { 03544 VL6180X_ErrLog("VL6180X_RangeClearInterrupt fail"); 03545 return status; 03546 } 03547 status=VL6180X_ClearErrorInterrupt(_device); 03548 if(status) 03549 { 03550 VL6180X_ErrLog("VL6180X_ClearErrorInterrupt fail"); 03551 return status; 03552 } 03553 status=VL6180X_RangeSetRawThresholds(_device, 10, 200); 03554 if(status) 03555 VL6180X_ErrLog("VL6180X_RangeSetThresholds fail"); 03556 return status; 03557 } 03558 03559 03560 int VL6180X::StopAlsMeasurement(operating_mode_t operating_mode) 03561 { 03562 int status; 03563 03564 if(operating_mode==als_single_shot_polling) 03565 status=VL6180X_AlsSetSystemMode(_device, MODE_SINGLESHOT); 03566 else 03567 status=VL6180X_AlsSetSystemMode(_device, MODE_START_STOP|MODE_SINGLESHOT); 03568 if(status) 03569 return status; 03570 status=VL6180X_AlsConfigInterrupt(_device, CONFIG_GPIO_INTERRUPT_DISABLED); 03571 if(status) 03572 { 03573 VL6180X_ErrLog("VL6180X_AlsConfigInterrupt fail"\n\r); 03574 return status; 03575 } 03576 status=VL6180X_AlsClearInterrupt(_device); 03577 if(status) 03578 { 03579 VL6180X_ErrLog("VL6180X_AlsClearInterrupt fail"); 03580 return status; 03581 } 03582 status=VL6180X_ClearErrorInterrupt(_device); 03583 if(status) 03584 { 03585 VL6180X_ErrLog("VL6180X_ClearErrorInterrupt fail"); 03586 return status; 03587 } 03588 status=VL6180X_AlsSetThresholds(_device, 0x0, 1800); 03589 if(status) 03590 VL6180X_ErrLog("VL6180X_AlsSetThresholds fail"); 03591 return status; 03592 } 03593 03594 03595 03596 03597 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Wed Jul 13 2022 23:03:14 by 1.7.2