Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
vl6180x_class.cpp
00001 /** 00002 ****************************************************************************** 00003 * @file vl6180x_class.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_class.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 00719 00720 int VL6180X::VL6180x_AlsSetThresholds(VL6180xDev_t dev, uint16_t low, uint16_t high) { 00721 int status; 00722 00723 LOG_FUNCTION_START("%d %d", (int )low, (int)high); 00724 00725 status = VL6180x_WrWord(dev, SYSALS_THRESH_LOW, low); 00726 if(!status ){ 00727 status = VL6180x_WrWord(dev, SYSALS_THRESH_HIGH, high); 00728 } 00729 00730 LOG_FUNCTION_END(status) ; 00731 return status; 00732 } 00733 00734 00735 int VL6180X::VL6180x_AlsSetAnalogueGain(VL6180xDev_t dev, uint8_t gain) { 00736 int status; 00737 uint8_t GainTotal; 00738 00739 LOG_FUNCTION_START("%d", (int )gain); 00740 gain&=~0x40; 00741 if (gain > 7) { 00742 gain = 7; 00743 } 00744 GainTotal = gain|0x40; 00745 00746 status = VL6180x_WrByte(dev, SYSALS_ANALOGUE_GAIN, GainTotal); 00747 if( !status){ 00748 VL6180xDevDataSet(dev, AlsGainCode , gain); 00749 } 00750 00751 LOG_FUNCTION_END_FMT(status, "%d %d", (int ) gain, (int )GainTotal); 00752 return status; 00753 } 00754 00755 int VL6180X::VL6180x_AlsSetInterMeasurementPeriod(VL6180xDev_t dev, uint16_t intermeasurement_period_ms) 00756 { 00757 int status; 00758 00759 LOG_FUNCTION_START("%d",(int)intermeasurement_period_ms); 00760 /* clipping: range is 0-2550ms */ 00761 if (intermeasurement_period_ms >= 255 *10) 00762 intermeasurement_period_ms = 255 *10; 00763 status=VL6180x_WrByte(dev, SYSALS_INTERMEASUREMENT_PERIOD, (uint8_t)(intermeasurement_period_ms/10)); 00764 00765 LOG_FUNCTION_END_FMT(status, "%d", (int) intermeasurement_period_ms); 00766 return status; 00767 } 00768 00769 00770 int VL6180X::VL6180x_AlsSetIntegrationPeriod(VL6180xDev_t dev, uint16_t period_ms) 00771 { 00772 int status; 00773 uint16_t SetIntegrationPeriod; 00774 00775 LOG_FUNCTION_START("%d", (int)period_ms); 00776 00777 if( period_ms>=1 ) 00778 SetIntegrationPeriod = period_ms - 1; 00779 else 00780 SetIntegrationPeriod = period_ms; 00781 00782 if (SetIntegrationPeriod > 464) { 00783 SetIntegrationPeriod = 464; 00784 } 00785 else if (SetIntegrationPeriod == 255) { 00786 SetIntegrationPeriod++; /* can't write 255 since this causes the device to lock out.*/ 00787 } 00788 00789 status =VL6180x_WrWord(dev, SYSALS_INTEGRATION_PERIOD, SetIntegrationPeriod); 00790 if( !status ){ 00791 VL6180xDevDataSet(dev, IntegrationPeriod , SetIntegrationPeriod) ; 00792 } 00793 LOG_FUNCTION_END_FMT(status, "%d", (int)SetIntegrationPeriod); 00794 return status; 00795 } 00796 00797 #endif /* HAVE_ALS_SUPPORT */ 00798 00799 00800 int VL6180X::VL6180x_RangePollMeasurement(VL6180xDev_t dev, VL6180x_RangeData_t *pRangeData) 00801 { 00802 int status; 00803 int ClrStatus; 00804 IntrStatus_t IntStatus; 00805 00806 LOG_FUNCTION_START(""); 00807 /* start single range measurement */ 00808 00809 00810 #if VL6180X_SAFE_POLLING_ENTER 00811 /* if device get stopped with left interrupt uncleared , it is required to clear them now or poll for new condition will never occur*/ 00812 status=VL6180x_RangeClearInterrupt(dev); 00813 if(status){ 00814 VL6180x_ErrLog("VL6180x_RangeClearInterrupt fail"); 00815 goto done; 00816 } 00817 #endif 00818 /* //![single_shot_snipet] */ 00819 status=VL6180x_RangeSetSystemMode(dev, MODE_START_STOP|MODE_SINGLESHOT); 00820 if( status ){ 00821 VL6180x_ErrLog("VL6180x_RangeSetSystemMode fail"); 00822 goto done; 00823 } 00824 00825 /* poll for new sample ready */ 00826 while(1 ){ 00827 status=VL6180x_RangeGetInterruptStatus(dev, &IntStatus.val ); 00828 if( status ){ 00829 break; 00830 } 00831 if( IntStatus.status .Error !=0 ){ 00832 VL6180x_ErrLog("GPIO int Error report %d",(int)IntStatus.val ); 00833 status = RANGE_ERROR; 00834 break; 00835 } 00836 else 00837 if( IntStatus.status .Range == RES_INT_STAT_GPIO_NEW_SAMPLE_READY){ 00838 break; 00839 } 00840 wait_ms(10); 00841 } 00842 /* //![single_shot_snipet] */ 00843 00844 if ( !status ){ 00845 status = VL6180x_RangeGetMeasurement(dev, pRangeData); 00846 } 00847 00848 /* clear range interrupt source */ 00849 ClrStatus = VL6180x_RangeClearInterrupt(dev); 00850 if( ClrStatus ){ 00851 VL6180x_ErrLog("VL6180x_RangeClearInterrupt fail"); 00852 /* leave initial status if already in error */ 00853 if( !status ){ 00854 status=ClrStatus; 00855 } 00856 } 00857 done: 00858 LOG_FUNCTION_END(status); 00859 return status; 00860 } 00861 00862 00863 00864 int VL6180X::VL6180x_RangeGetMeasurement(VL6180xDev_t dev, VL6180x_RangeData_t *pRangeData) 00865 { 00866 int status; 00867 uint16_t RawRate; 00868 uint8_t RawStatus; 00869 00870 LOG_FUNCTION_START(""); 00871 00872 status = VL6180x_RangeGetResult(dev, &pRangeData->range_mm ); 00873 if( !status ){ 00874 status = VL6180x_RdWord(dev,RESULT_RANGE_SIGNAL_RATE, &RawRate ); 00875 if( !status ){ 00876 pRangeData->signalRate_mcps = VL6180x_9to7Conv(RawRate); 00877 status = VL6180x_RdByte(dev, RESULT_RANGE_STATUS, &RawStatus); 00878 if( !status ){ 00879 pRangeData->errorStatus = RawStatus >>4; 00880 } 00881 else{ 00882 VL6180x_ErrLog("Rd RESULT_RANGE_STATUS fail"); 00883 } 00884 #if VL6180x_WRAP_AROUND_FILTER_SUPPORT || VL6180x_HAVE_DMAX_RANGING 00885 status = _GetRateResult(dev, pRangeData); 00886 if( status ) 00887 goto error; 00888 #endif 00889 #if VL6180x_WRAP_AROUND_FILTER_SUPPORT 00890 /* if enabled run filter */ 00891 if( _IsWrapArroundActive(dev) ){ 00892 status=_filter_GetResult(dev, pRangeData); 00893 if( !status){ 00894 /* patch the range status and measure if it is filtered */ 00895 if( pRangeData->range_mm != pRangeData->FilteredData .range_mm ) { 00896 pRangeData->errorStatus =RangingFiltered; 00897 pRangeData->range_mm = pRangeData->FilteredData .range_mm ; 00898 } 00899 } 00900 } 00901 #endif 00902 00903 #if VL6180x_HAVE_DMAX_RANGING 00904 if(_IsDMaxActive(dev) ){ 00905 _DMax_Compute(dev, pRangeData); 00906 } 00907 #endif 00908 } 00909 else{ 00910 VL6180x_ErrLog("Rd RESULT_RANGE_SIGNAL_RATE fail"); 00911 } 00912 } 00913 else{ 00914 VL6180x_ErrLog("VL6180x_GetRangeResult fail"); 00915 } 00916 error: 00917 LOG_FUNCTION_END_FMT(status, "%d %d %d", (int)pRangeData->range_mm , (int)pRangeData->signalRate_mcps , (int)pRangeData->errorStatus ) ; 00918 return status; 00919 } 00920 00921 00922 int VL6180X::VL6180x_RangeGetMeasurementIfReady(VL6180xDev_t dev, VL6180x_RangeData_t *pRangeData) 00923 { 00924 int status; 00925 IntrStatus_t IntStatus; 00926 00927 LOG_FUNCTION_START(); 00928 00929 status = VL6180x_RangeGetInterruptStatus(dev, &IntStatus.val ); 00930 if( status ==0 ){ 00931 if( IntStatus.status .Error !=0 ){ 00932 VL6180x_ErrLog("GPIO int Error report %d",(int)IntStatus.val ); 00933 status = RANGE_ERROR; 00934 } 00935 else 00936 if( IntStatus.status .Range == RES_INT_STAT_GPIO_NEW_SAMPLE_READY){ 00937 status = VL6180x_RangeGetMeasurement(dev,pRangeData ); 00938 if( status == 0){ 00939 /* clear range interrupt source */ 00940 status = VL6180x_RangeClearInterrupt(dev); 00941 if( status ){ 00942 VL6180x_ErrLog("VL6180x_RangeClearInterrupt fail"); 00943 } 00944 } 00945 } 00946 else{ 00947 status = NOT_READY; 00948 } 00949 } 00950 else{ 00951 VL6180x_ErrLog("fail to get interrupt status"); 00952 } 00953 LOG_FUNCTION_END(status) ; 00954 return status; 00955 } 00956 00957 int VL6180X::VL6180x_FilterSetState(VL6180xDev_t dev, int state){ 00958 int status; 00959 LOG_FUNCTION_START("%d", state); 00960 #if VL6180x_WRAP_AROUND_FILTER_SUPPORT 00961 VL6180xDevDataSet(dev,WrapAroundFilterActive , state); 00962 status = 0; 00963 #else 00964 status = NOT_SUPPORTED; 00965 #endif 00966 LOG_FUNCTION_END(status); 00967 return status; 00968 } 00969 00970 int VL6180X::VL6180x_FilterGetState(VL6180xDev_t dev){ 00971 int status; 00972 LOG_FUNCTION_START(""); 00973 #if VL6180x_WRAP_AROUND_FILTER_SUPPORT 00974 status = VL6180xDevDataGet(dev,WrapAroundFilterActive ); 00975 #else 00976 status = 0; 00977 #endif 00978 LOG_FUNCTION_END(status); 00979 return status; 00980 } 00981 00982 int VL6180X::VL6180x_RangeGetResult(VL6180xDev_t dev, uint32_t *pRange_mm) { 00983 int status; 00984 uint8_t RawRange; 00985 int32_t Upscale; 00986 00987 LOG_FUNCTION_START("%p",pRange_mm); 00988 00989 status = VL6180x_RdByte(dev, RESULT_RANGE_VAL, &RawRange); 00990 if( !status ){ 00991 Upscale = _GetUpscale(dev); 00992 *pRange_mm= Upscale*(int32_t)RawRange; 00993 } 00994 LOG_FUNCTION_END_FMT(status, "%d", (int)*pRange_mm); 00995 return status; 00996 } 00997 00998 int VL6180X::VL6180x_RangeSetRawThresholds(VL6180xDev_t dev, uint8_t low, uint8_t high) 00999 { 01000 int status; 01001 LOG_FUNCTION_START("%d %d", (int) low, (int)high); 01002 /* TODO we can optimize here grouping high/low in a word but that's cpu endianness dependent */ 01003 status=VL6180x_WrByte(dev, SYSRANGE_THRESH_HIGH,high); 01004 if( !status){ 01005 status=VL6180x_WrByte(dev, SYSRANGE_THRESH_LOW, low); 01006 } 01007 01008 LOG_FUNCTION_END(status); 01009 return status; 01010 } 01011 01012 int VL6180X::VL6180x_RangeSetThresholds(VL6180xDev_t dev, uint16_t low, uint16_t high, int UseSafeParamHold) 01013 { 01014 int status; 01015 int scale; 01016 LOG_FUNCTION_START("%d %d", (int) low, (int)high); 01017 scale=_GetUpscale(dev,UpscaleFactor ); 01018 if( low>scale*255 || high >scale*255){ 01019 status = INVALID_PARAMS; 01020 } 01021 else{ 01022 do{ 01023 if( UseSafeParamHold ){ 01024 status=VL6180x_SetGroupParamHold(dev, 1); 01025 if( status ) 01026 break; 01027 } 01028 status=VL6180x_RangeSetRawThresholds(dev, (uint8_t)(low/scale), (uint8_t)(high/scale)); 01029 if( status ){ 01030 VL6180x_ErrLog("VL6180x_RangeSetRawThresholds fail"); 01031 } 01032 if( UseSafeParamHold ){ 01033 int HoldStatus; 01034 /* tryt to unset param hold vene if previous fail */ 01035 HoldStatus=VL6180x_SetGroupParamHold(dev, 0); 01036 if( !status) 01037 status=HoldStatus; 01038 } 01039 } 01040 while(0); 01041 } 01042 01043 LOG_FUNCTION_END(status); 01044 return status; 01045 } 01046 01047 01048 int VL6180X::VL6180x_RangeGetThresholds(VL6180xDev_t dev, uint16_t *low, uint16_t *high) 01049 { 01050 int status; 01051 uint8_t RawLow, RawHigh; 01052 int scale; 01053 01054 LOG_FUNCTION_START("%p %p", low , high); 01055 01056 scale=_GetUpscale(dev,UpscaleFactor ); 01057 do{ 01058 if( high != NULL ){ 01059 status=VL6180x_RdByte(dev, SYSRANGE_THRESH_HIGH,&RawHigh); 01060 if( status ){ 01061 VL6180x_ErrLog("rd SYSRANGE_THRESH_HIGH fail"); 01062 break; 01063 } 01064 *high=(uint16_t)RawHigh*scale; 01065 } 01066 if( low != NULL ) { 01067 status=VL6180x_RdByte(dev, SYSRANGE_THRESH_LOW, &RawLow); 01068 if( status ){ 01069 VL6180x_ErrLog("rd SYSRANGE_THRESH_LOW fail"); 01070 break; 01071 } 01072 *low=(uint16_t)RawLow*scale; 01073 } 01074 } 01075 while(0); 01076 LOG_FUNCTION_END_FMT(status, "%d %d",(int)*low ,(int)*high); 01077 return status; 01078 } 01079 01080 01081 int VL6180X::VL6180x_RangeGetInterruptStatus(VL6180xDev_t dev, uint8_t *pIntStatus) { 01082 int status; 01083 uint8_t IntStatus; 01084 LOG_FUNCTION_START("%p", pIntStatus); 01085 /* FIXME we are grouping "error" with over status the user must check implicitly for it 01086 * not just new sample or over status , that will nevr show up in case of error*/ 01087 status = VL6180x_RdByte(dev, RESULT_INTERRUPT_STATUS_GPIO, &IntStatus); 01088 *pIntStatus= IntStatus&0xC7; 01089 01090 LOG_FUNCTION_END_FMT(status, "%d", (int)*pIntStatus); 01091 return status; 01092 } 01093 01094 01095 int VL6180X::VL6180x_GetInterruptStatus(VL6180xDev_t dev, uint8_t *IntStatus) 01096 { 01097 int status; 01098 LOG_FUNCTION_START("%p" , IntStatus); 01099 status = VL6180x_RdByte(dev, RESULT_INTERRUPT_STATUS_GPIO, IntStatus); 01100 LOG_FUNCTION_END_FMT(status, "%d", (int)*IntStatus); 01101 return status; 01102 } 01103 01104 int VL6180X::VL6180x_ClearInterrupt(VL6180xDev_t dev, uint8_t IntClear ) 01105 { 01106 int status; 01107 LOG_FUNCTION_START("%d" ,(int)IntClear); 01108 if( IntClear <= 7 ){ 01109 status=VL6180x_WrByte( dev, SYSTEM_INTERRUPT_CLEAR, IntClear); 01110 } 01111 else{ 01112 status = INVALID_PARAMS; 01113 } 01114 LOG_FUNCTION_END(status); 01115 return status; 01116 } 01117 01118 01119 int VL6180X::VL6180x_RangeStaticInit(VL6180xDev_t dev) 01120 { 01121 int status; 01122 LOG_FUNCTION_START(""); 01123 01124 /* REGISTER_TUNING_SR03_270514_CustomerView.txt */ 01125 VL6180x_WrByte( dev, 0x0207, 0x01); 01126 VL6180x_WrByte( dev, 0x0208, 0x01); 01127 VL6180x_WrByte( dev, 0x0096, 0x00); 01128 VL6180x_WrByte( dev, 0x0097, 0xfd); 01129 VL6180x_WrByte( dev, 0x00e3, 0x00); 01130 VL6180x_WrByte( dev, 0x00e4, 0x04); 01131 VL6180x_WrByte( dev, 0x00e5, 0x02); 01132 VL6180x_WrByte( dev, 0x00e6, 0x01); 01133 VL6180x_WrByte( dev, 0x00e7, 0x03); 01134 VL6180x_WrByte( dev, 0x00f5, 0x02); 01135 VL6180x_WrByte( dev, 0x00d9, 0x05); 01136 VL6180x_WrByte( dev, 0x00db, 0xce); 01137 VL6180x_WrByte( dev, 0x00dc, 0x03); 01138 VL6180x_WrByte( dev, 0x00dd, 0xf8); 01139 VL6180x_WrByte( dev, 0x009f, 0x00); 01140 VL6180x_WrByte( dev, 0x00a3, 0x3c); 01141 VL6180x_WrByte( dev, 0x00b7, 0x00); 01142 VL6180x_WrByte( dev, 0x00bb, 0x3c); 01143 VL6180x_WrByte( dev, 0x00b2, 0x09); 01144 VL6180x_WrByte( dev, 0x00ca, 0x09); 01145 VL6180x_WrByte( dev, 0x0198, 0x01); 01146 VL6180x_WrByte( dev, 0x01b0, 0x17); 01147 VL6180x_WrByte( dev, 0x01ad, 0x00); 01148 VL6180x_WrByte( dev, 0x00ff, 0x05); 01149 VL6180x_WrByte( dev, 0x0100, 0x05); 01150 VL6180x_WrByte( dev, 0x0199, 0x05); 01151 VL6180x_WrByte( dev, 0x01a6, 0x1b); 01152 VL6180x_WrByte( dev, 0x01ac, 0x3e); 01153 VL6180x_WrByte( dev, 0x01a7, 0x1f); 01154 VL6180x_WrByte( dev, 0x0030, 0x00); 01155 01156 /* Recommended : Public registers - See data sheet for more detail */ 01157 VL6180x_WrByte( dev, SYSTEM_MODE_GPIO1, 0x10); /* Enables polling for New Sample ready when measurement completes */ 01158 VL6180x_WrByte( dev, READOUT_AVERAGING_SAMPLE_PERIOD, 0x30); /* Set the averaging sample period (compromise between lower noise and increased execution time) */ 01159 VL6180x_WrByte( dev, SYSALS_ANALOGUE_GAIN, 0x46); /* Sets the light and dark gain (upper nibble). Dark gain should not be changed.*/ 01160 VL6180x_WrByte( dev, SYSRANGE_VHV_REPEAT_RATE, 0xFF); /* sets the # of range measurements after which auto calibration of system is performed */ 01161 VL6180x_WrByte( dev, SYSALS_INTEGRATION_PERIOD, 0x63); /* Set ALS integration time to 100ms */ 01162 VL6180x_WrByte( dev, SYSRANGE_VHV_RECALIBRATE, 0x01); /* perform a single temperature calibration of the ranging sensor */ 01163 01164 /* Optional: Public registers - See data sheet for more detail */ 01165 VL6180x_WrByte( dev, SYSRANGE_INTERMEASUREMENT_PERIOD, 0x09); /* Set default ranging inter-measurement period to 100ms */ 01166 VL6180x_WrByte( dev, SYSALS_INTERMEASUREMENT_PERIOD, 0x31); /* Set default ALS inter-measurement period to 500ms */ 01167 VL6180x_WrByte( dev, SYSTEM_INTERRUPT_CONFIG_GPIO, 0x24); /* Configures interrupt on New sample ready */ 01168 01169 01170 status=VL6180x_RangeSetMaxConvergenceTime(dev, 50); /* Calculate ece value on initialization (use max conv) */ 01171 LOG_FUNCTION_END(status); 01172 01173 return status; 01174 } 01175 01176 #if VL6180x_UPSCALE_SUPPORT != 1 01177 01178 int VL6180X::_UpscaleInitPatch0(VL6180xDev_t dev){ 01179 int status; 01180 uint32_t CalValue=0; 01181 CalValue= VL6180xDevDataGet(dev, Part2PartAmbNVM ); 01182 status=VL6180x_WrDWord( dev, 0xDA, CalValue); 01183 return status; 01184 } 01185 01186 /* only include up-scaling register setting when up-scale support is configured in */ 01187 int VL6180X::VL6180x_UpscaleRegInit(VL6180xDev_t dev) 01188 { 01189 /* apply REGISTER_TUNING_ER02_100614_CustomerView.txt */ 01190 VL6180x_WrByte( dev, 0x0207, 0x01); 01191 VL6180x_WrByte( dev, 0x0208, 0x01); 01192 VL6180x_WrByte( dev, 0x0096, 0x00); 01193 VL6180x_WrByte( dev, 0x0097, 0x54); 01194 VL6180x_WrByte( dev, 0x00e3, 0x00); 01195 VL6180x_WrByte( dev, 0x00e4, 0x04); 01196 VL6180x_WrByte( dev, 0x00e5, 0x02); 01197 VL6180x_WrByte( dev, 0x00e6, 0x01); 01198 VL6180x_WrByte( dev, 0x00e7, 0x03); 01199 VL6180x_WrByte( dev, 0x00f5, 0x02); 01200 VL6180x_WrByte( dev, 0x00d9, 0x05); 01201 01202 _UpscaleInitPatch0(dev); 01203 01204 VL6180x_WrByte( dev, 0x009f, 0x00); 01205 VL6180x_WrByte( dev, 0x00a3, 0x28); 01206 VL6180x_WrByte( dev, 0x00b7, 0x00); 01207 VL6180x_WrByte( dev, 0x00bb, 0x28); 01208 VL6180x_WrByte( dev, 0x00b2, 0x09); 01209 VL6180x_WrByte( dev, 0x00ca, 0x09); 01210 VL6180x_WrByte( dev, 0x0198, 0x01); 01211 VL6180x_WrByte( dev, 0x01b0, 0x17); 01212 VL6180x_WrByte( dev, 0x01ad, 0x00); 01213 VL6180x_WrByte( dev, 0x00ff, 0x05); 01214 VL6180x_WrByte( dev, 0x0100, 0x05); 01215 VL6180x_WrByte( dev, 0x0199, 0x05); 01216 VL6180x_WrByte( dev, 0x01a6, 0x1b); 01217 VL6180x_WrByte( dev, 0x01ac, 0x3e); 01218 VL6180x_WrByte( dev, 0x01a7, 0x1f); 01219 VL6180x_WrByte( dev, 0x0030, 0x00); 01220 VL6180x_WrByte( dev, SYSTEM_MODE_GPIO1, 0x10); 01221 VL6180x_WrByte( dev, READOUT_AVERAGING_SAMPLE_PERIOD, 0x30); 01222 VL6180x_WrByte( dev, SYSALS_ANALOGUE_GAIN, 0x46); 01223 VL6180x_WrByte( dev, SYSRANGE_VHV_REPEAT_RATE, 0xFF); 01224 VL6180x_WrByte( dev, SYSALS_INTEGRATION_PERIOD, 0x63); 01225 VL6180x_WrByte( dev, SYSRANGE_VHV_RECALIBRATE, 0x01); 01226 VL6180x_WrByte( dev, SYSRANGE_MAX_AMBIENT_LEVEL_MULT, 0xff); 01227 VL6180x_WrByte( dev, SYSRANGE_INTERMEASUREMENT_PERIOD, 0x09); 01228 VL6180x_WrByte( dev, SYSALS_INTERMEASUREMENT_PERIOD, 0x31); 01229 VL6180x_WrByte( dev, SYSTEM_INTERRUPT_CONFIG_GPIO, 0x24); 01230 #if VL6180x_EXTENDED_RANGE 01231 VL6180x_RangeSetMaxConvergenceTime(dev, 63); 01232 #else 01233 VL6180x_RangeSetMaxConvergenceTime(dev, 50); 01234 #endif 01235 return 0; 01236 } 01237 #else 01238 #define VL6180x_UpscaleRegInit(...) -1 01239 #endif 01240 01241 int VL6180X::VL6180x_UpscaleSetScaling(VL6180xDev_t dev, uint8_t scaling) 01242 { 01243 int status; 01244 uint16_t Scaler; 01245 int8_t Offset; 01246 01247 LOG_FUNCTION_START("%d",(int) scaling); 01248 01249 #ifdef VL6180x_HAVE_UPSCALE_DATA 01250 #define min_scaling 1 01251 #define max_scaling sizeof(ScalerLookUP)/sizeof(ScalerLookUP[0]) 01252 #else 01253 /* we are in fixed config so only allow configured factor */ 01254 #define min_scaling VL6180x_UPSCALE_SUPPORT 01255 #define max_scaling VL6180x_UPSCALE_SUPPORT 01256 #endif 01257 01258 if( scaling>=min_scaling && scaling<= max_scaling ){ 01259 01260 Scaler = ScalerLookUP[scaling-1]; 01261 status = VL6180x_WrWord(dev, RANGE_SCALER, Scaler); 01262 _SetUpscale(dev, scaling ); 01263 01264 /* Apply scaling on part-2-part offset */ 01265 Offset = VL6180xDevDataGet(dev, Part2PartOffsetNVM )/scaling; 01266 status = VL6180x_WrByte(dev, SYSRANGE_PART_TO_PART_RANGE_OFFSET, Offset); 01267 #if ! VL6180x_EXTENDED_RANGE 01268 if( status ==0 ){ 01269 status = VL6180x_RangeSetEceState(dev, scaling == 1); /* enable ece only at 1x scaling */ 01270 } 01271 if( status == 0 && !VL6180x_EXTENDED_RANGE && scaling!=1 ){ 01272 status = NOT_GUARANTEED ; 01273 } 01274 #endif 01275 } 01276 else{ 01277 status = INVALID_PARAMS; 01278 } 01279 #undef min_scaling 01280 #undef max_scaling 01281 LOG_FUNCTION_END(status); 01282 return status; 01283 } 01284 01285 01286 int VL6180X::VL6180x_UpscaleGetScaling(VL6180xDev_t dev) 01287 { 01288 int status; 01289 LOG_FUNCTION_START(""); 01290 status=_GetUpscale(dev ); 01291 LOG_FUNCTION_END(status); 01292 01293 return status; 01294 } 01295 01296 01297 int VL6180X::VL6180x_UpscaleStaticInit(VL6180xDev_t dev) 01298 { 01299 /* todo make these a fail macro in case only 1x is suppoted */ 01300 int status; 01301 01302 LOG_FUNCTION_START(""); 01303 do{ 01304 status=VL6180x_UpscaleRegInit(dev); 01305 if( status){ 01306 VL6180x_ErrLog("regInit fail"); 01307 break; 01308 } 01309 #if VL6180x_EXTENDED_RANGE 01310 status = VL6180x_RangeSetEceState(dev, 0); 01311 if( status){ 01312 VL6180x_ErrLog("VL6180x_RangeSetEceState fail"); 01313 break; 01314 } 01315 #endif 01316 } while(0); 01317 if( !status){ 01318 /* must write the scaler at least once to the device to ensure the scaler is in a known state. */ 01319 status=VL6180x_UpscaleSetScaling(dev, _GetUpscale(dev)); 01320 VL6180x_WrByte( dev, SYSTEM_FRESH_OUT_OF_RESET, 0x00); /* change fresh out of set status to 0 */ 01321 } 01322 LOG_FUNCTION_END(status); 01323 return status; 01324 } 01325 01326 01327 int VL6180X::VL6180x_SetGPIOxPolarity(VL6180xDev_t dev, int pin, int active_high) 01328 { 01329 int status; 01330 LOG_FUNCTION_START("%d %d",(int) pin, (int)active_high); 01331 01332 if( pin ==0 || pin ==1 ){ 01333 uint16_t RegIndex; 01334 uint8_t DataSet; 01335 if( pin==0 ) 01336 RegIndex= SYSTEM_MODE_GPIO0; 01337 else 01338 RegIndex= SYSTEM_MODE_GPIO1; 01339 01340 if (active_high ) 01341 DataSet = GPIOx_POLARITY_SELECT_MASK; 01342 else 01343 DataSet = 0; 01344 01345 status = VL6180x_UpdateByte(dev, RegIndex, (uint8_t)~GPIOx_POLARITY_SELECT_MASK, DataSet); 01346 } 01347 else{ 01348 VL6180x_ErrLog("Invalid pin param %d", (int)pin); 01349 status = INVALID_PARAMS; 01350 } 01351 01352 LOG_FUNCTION_END(status); 01353 01354 return status; 01355 } 01356 01357 int VL6180X::VL6180x_SetGPIOxFunctionality(VL6180xDev_t dev, int pin, uint8_t functionality) 01358 { 01359 int status; 01360 01361 LOG_FUNCTION_START("%d %d",(int) pin, (int)functionality); 01362 01363 if( ((pin ==0) || (pin ==1)) && IsValidGPIOFunction(functionality) ){ 01364 uint16_t RegIndex; 01365 01366 if( pin==0 ) 01367 RegIndex= SYSTEM_MODE_GPIO0; 01368 else 01369 RegIndex= SYSTEM_MODE_GPIO1; 01370 01371 status = VL6180x_UpdateByte(dev, RegIndex, (uint8_t)~GPIOx_FUNCTIONALITY_SELECT_MASK, functionality<<GPIOx_FUNCTIONALITY_SELECT_SHIFT); 01372 if( status){ 01373 VL6180x_ErrLog("Update SYSTEM_MODE_GPIO%d fail", (int)pin); 01374 } 01375 } 01376 else{ 01377 VL6180x_ErrLog("Invalid pin %d or function %d", (int)pin, (int) functionality); 01378 status = INVALID_PARAMS; 01379 } 01380 01381 LOG_FUNCTION_END(status); 01382 return status; 01383 } 01384 01385 01386 int VL6180X::VL6180x_SetupGPIOx(VL6180xDev_t dev, int pin, uint8_t IntFunction, int ActiveHigh) 01387 { 01388 int status; 01389 01390 LOG_FUNCTION_START("%d %d",(int) pin, (int)IntFunction); 01391 01392 if( ((pin ==0) || (pin ==1)) && IsValidGPIOFunction(IntFunction) ){ 01393 uint16_t RegIndex; 01394 uint8_t value=0; 01395 01396 if( pin==0 ) 01397 RegIndex= SYSTEM_MODE_GPIO0; 01398 else 01399 RegIndex= SYSTEM_MODE_GPIO1; 01400 01401 if( ActiveHigh ) 01402 value|=GPIOx_POLARITY_SELECT_MASK; 01403 01404 value |= IntFunction<<GPIOx_FUNCTIONALITY_SELECT_SHIFT; 01405 status = VL6180x_WrByte(dev, RegIndex, value); 01406 if( status ){ 01407 VL6180x_ErrLog("SYSTEM_MODE_GPIO%d wr fail", (int)pin-SYSTEM_MODE_GPIO0); 01408 } 01409 } 01410 else{ 01411 VL6180x_ErrLog("Invalid pin %d or function %d", (int)pin, (int) IntFunction); 01412 status = INVALID_PARAMS; 01413 } 01414 01415 LOG_FUNCTION_END(status); 01416 return status; 01417 } 01418 01419 01420 int VL6180X::VL6180x_DisableGPIOxOut(VL6180xDev_t dev, int pin) { 01421 int status; 01422 01423 LOG_FUNCTION_START("%d",(int)pin); 01424 01425 status=VL6180x_SetGPIOxFunctionality(dev, pin, GPIOx_SELECT_OFF); 01426 01427 LOG_FUNCTION_END(status); 01428 return status; 01429 } 01430 01431 01432 int VL6180X::VL6180x_SetupGPIO1(VL6180xDev_t dev, uint8_t IntFunction, int ActiveHigh) 01433 { 01434 int status; 01435 LOG_FUNCTION_START("%d %d",(int)IntFunction, (int)ActiveHigh ); 01436 status=VL6180x_SetupGPIOx(dev, 1 , IntFunction, ActiveHigh); 01437 LOG_FUNCTION_END(status); 01438 return status; 01439 } 01440 01441 int VL6180X::VL6180x_RangeConfigInterrupt(VL6180xDev_t dev, uint8_t ConfigGpioInt) 01442 { 01443 int status; 01444 01445 if( ConfigGpioInt<= CONFIG_GPIO_INTERRUPT_NEW_SAMPLE_READY){ 01446 status = VL6180x_UpdateByte(dev, SYSTEM_INTERRUPT_CONFIG_GPIO, (uint8_t)(~CONFIG_GPIO_RANGE_MASK), ConfigGpioInt); 01447 } 01448 else{ 01449 VL6180x_ErrLog("Invalid config mode param %d", (int)ConfigGpioInt); 01450 status = INVALID_PARAMS; 01451 } 01452 LOG_FUNCTION_END(status); 01453 return status; 01454 } 01455 01456 01457 int VL6180X::VL6180x_RangeSetEceFactor(VL6180xDev_t dev, uint16_t FactorM, uint16_t FactorD){ 01458 int status; 01459 uint8_t u8; 01460 01461 LOG_FUNCTION_START("%d %d", (int)FactorM, (int)FactorD ); 01462 do{ 01463 /* D cannot be 0 M must be <=D and >= 0 */ 01464 if( FactorM <= FactorD && FactorD> 0){ 01465 VL6180xDevDataSet(dev, EceFactorM , FactorM); 01466 VL6180xDevDataSet(dev, EceFactorD , FactorD); 01467 /* read and re-apply max conv time to get new ece factor set */ 01468 status = VL6180x_RdByte(dev, SYSRANGE_MAX_CONVERGENCE_TIME, &u8); 01469 if( status){ 01470 VL6180x_ErrLog("SYSRANGE_MAX_CONVERGENCE_TIME rd fail "); 01471 break; 01472 } 01473 status = VL6180x_RangeSetMaxConvergenceTime(dev, u8); 01474 if( status <0 ){ 01475 VL6180x_ErrLog("fail to apply time after ece m/d change"); 01476 break; 01477 } 01478 } 01479 else{ 01480 VL6180x_ErrLog("invalid factor %d/%d", (int)FactorM, (int)FactorD ); 01481 status = INVALID_PARAMS; 01482 } 01483 } 01484 while(0); 01485 LOG_FUNCTION_END(status); 01486 return status; 01487 } 01488 01489 int VL6180X::VL6180x_RangeSetEceState(VL6180xDev_t dev, int enable ){ 01490 int status; 01491 uint8_t or_mask; 01492 01493 LOG_FUNCTION_START("%d", (int)enable); 01494 if( enable ) 01495 or_mask = RANGE_CHECK_ECE_ENABLE_MASK; 01496 else 01497 or_mask = 0; 01498 01499 status =VL6180x_UpdateByte(dev, SYSRANGE_RANGE_CHECK_ENABLES, ~RANGE_CHECK_ECE_ENABLE_MASK, or_mask); 01500 LOG_FUNCTION_END(status); 01501 return status; 01502 } 01503 01504 01505 int VL6180X::VL6180x_RangeSetMaxConvergenceTime(VL6180xDev_t dev, uint8_t MaxConTime_msec) 01506 { 01507 int status = 0; 01508 LOG_FUNCTION_START("%d",(int)MaxConTime_msec); 01509 do{ 01510 status=VL6180x_WrByte(dev, SYSRANGE_MAX_CONVERGENCE_TIME, MaxConTime_msec); 01511 if( status ){ 01512 break; 01513 } 01514 status=VL6180x_RangeSetEarlyConvergenceEestimateThreshold(dev); 01515 if( status){ 01516 break; 01517 } 01518 status = _DMax_InitData(dev); 01519 } 01520 while(0); 01521 LOG_FUNCTION_END(status); 01522 return status; 01523 } 01524 01525 int VL6180X::VL6180x_RangeSetInterMeasPeriod(VL6180xDev_t dev, uint32_t InterMeasTime_msec){ 01526 uint8_t SetTime; 01527 int status; 01528 01529 LOG_FUNCTION_START("%d",(int)InterMeasTime_msec); 01530 do { 01531 if( InterMeasTime_msec > 2550 ){ 01532 status = INVALID_PARAMS; 01533 break; 01534 } 01535 /* doc in not 100% clear and confusing about the limit practically all value are OK but 0 01536 * that can hang device in continuous mode */ 01537 if( InterMeasTime_msec < 10 ) { 01538 InterMeasTime_msec=10; 01539 } 01540 SetTime=(uint8_t)(InterMeasTime_msec/10); 01541 status=VL6180x_WrByte(dev, SYSRANGE_INTERMEASUREMENT_PERIOD, SetTime); 01542 if( status ){ 01543 VL6180x_ErrLog("SYSRANGE_INTERMEASUREMENT_PERIOD wr fail"); 01544 } 01545 else 01546 if( SetTime != InterMeasTime_msec /10 ) { 01547 status = MIN_CLIPED; /* on success change status to clip if it did */ 01548 } 01549 }while(0); 01550 LOG_FUNCTION_END(status); 01551 return status; 01552 } 01553 01554 01555 int VL6180X::VL6180x_RangeGetDeviceReady(VL6180xDev_t dev, int * Ready){ 01556 int status; 01557 uint8_t u8; 01558 LOG_FUNCTION_START("%p", (int)Ready); 01559 status=VL6180x_RdByte(dev, RESULT_RANGE_STATUS, &u8); 01560 if( !status) 01561 *Ready = u8&RANGE_DEVICE_READY_MASK; 01562 LOG_FUNCTION_END_FMT(status,"%d", *Ready); 01563 return status; 01564 } 01565 01566 01567 int VL6180X::VL6180x_RangeWaitDeviceReady(VL6180xDev_t dev, int MaxLoop ){ 01568 int status; /* if user specify an invalid <=0 loop count we'll return error */ 01569 int n; 01570 uint8_t u8; 01571 LOG_FUNCTION_START("%d", (int)MaxLoop); 01572 if( MaxLoop<1){ 01573 status=INVALID_PARAMS; 01574 } 01575 else{ 01576 for( n=0; n < MaxLoop ; n++){ 01577 status=VL6180x_RdByte(dev, RESULT_RANGE_STATUS, &u8); 01578 if( status) 01579 break; 01580 u8 = u8 & RANGE_DEVICE_READY_MASK; 01581 if( u8 ) 01582 break; 01583 01584 } 01585 if( !status && !u8 ){ 01586 status = TIME_OUT; 01587 } 01588 } 01589 LOG_FUNCTION_END(status); 01590 return status; 01591 } 01592 01593 int VL6180X::VL6180x_RangeSetSystemMode(VL6180xDev_t dev, uint8_t mode) 01594 { 01595 int status; 01596 LOG_FUNCTION_START("%d", (int)mode); 01597 /* FIXME we are not checking device is ready via @a VL6180x_RangeWaitDeviceReady 01598 * so if called back to back real fast we are not checking 01599 * if previous mode "set" got absorbed => bit 0 must be 0 so that it work 01600 */ 01601 if( mode <= 3){ 01602 status=VL6180x_WrByte(dev, SYSRANGE_START, mode); 01603 if( status ){ 01604 VL6180x_ErrLog("SYSRANGE_START wr fail"); 01605 } 01606 } 01607 else{ 01608 status = INVALID_PARAMS; 01609 } 01610 LOG_FUNCTION_END(status); 01611 return status; 01612 } 01613 01614 01615 int VL6180X::VL6180x_RangeStartContinuousMode(VL6180xDev_t dev) 01616 { 01617 int status; 01618 LOG_FUNCTION_START(""); 01619 status= VL6180x_RangeSetSystemMode(dev, MODE_START_STOP | MODE_CONTINUOUS); 01620 LOG_FUNCTION_END(status); 01621 return status; 01622 } 01623 01624 int VL6180X::VL6180x_RangeStartSingleShot(VL6180xDev_t dev) { 01625 int status; 01626 LOG_FUNCTION_START(""); 01627 status = VL6180x_RangeSetSystemMode(dev, MODE_START_STOP|MODE_SINGLESHOT); 01628 LOG_FUNCTION_END(status); 01629 return status; 01630 } 01631 01632 01633 int VL6180X::VL6180x_RangeSetEarlyConvergenceEestimateThreshold(VL6180xDev_t dev) 01634 { 01635 int status; 01636 01637 const uint32_t cMicroSecPerMilliSec = 1000; 01638 const uint32_t cEceSampleTime_us = 500; 01639 uint32_t ece_factor_m = VL6180xDevDataGet(dev, EceFactorM ); 01640 uint32_t ece_factor_d = VL6180xDevDataGet(dev, EceFactorD ); 01641 uint32_t convergTime_us; 01642 uint32_t fineThresh; 01643 uint32_t eceThresh; 01644 uint8_t u8; 01645 uint32_t maxConv_ms; 01646 int32_t AveTime; 01647 01648 LOG_FUNCTION_START(""); 01649 01650 do{ 01651 status = VL6180x_RdByte(dev, SYSRANGE_MAX_CONVERGENCE_TIME, &u8); 01652 if( status ){ 01653 VL6180x_ErrLog("SYSRANGE_MAX_CONVERGENCE_TIME rd fail"); 01654 break; 01655 } 01656 maxConv_ms = u8; 01657 AveTime = _GetAveTotalTime(dev); 01658 if( AveTime <0 ){ 01659 status=-1; 01660 break; 01661 } 01662 01663 convergTime_us = maxConv_ms * cMicroSecPerMilliSec - AveTime; 01664 status = VL6180x_RdDWord(dev, 0xB8, &fineThresh); 01665 if( status ) { 01666 VL6180x_ErrLog("reg 0xB8 rd fail"); 01667 break; 01668 } 01669 fineThresh*=256; 01670 eceThresh = ece_factor_m * cEceSampleTime_us * fineThresh/(convergTime_us * ece_factor_d); 01671 01672 status=VL6180x_WrWord(dev, SYSRANGE_EARLY_CONVERGENCE_ESTIMATE, (uint16_t)eceThresh); 01673 } 01674 while(0); 01675 01676 LOG_FUNCTION_END(status); 01677 return status; 01678 } 01679 01680 /* 01681 * Return >0 = time 01682 * <0 1 if fail to get read data from device to compute time 01683 */ 01684 int32_t VL6180X::_GetAveTotalTime(VL6180xDev_t dev) { 01685 uint32_t cFwOverhead_us = 24; 01686 uint32_t cVcpSetupTime_us = 70; 01687 uint32_t cPLL2_StartupDelay_us = 200; 01688 uint8_t cMeasMask = 0x07; 01689 uint32_t Samples; 01690 uint32_t SamplePeriod; 01691 uint32_t SingleTime_us; 01692 int32_t TotalAveTime_us; 01693 uint8_t u8; 01694 int status; 01695 01696 LOG_FUNCTION_START(""); 01697 01698 status = VL6180x_RdByte(dev, 0x109, &u8); 01699 if (status) { 01700 VL6180x_ErrLog("rd 0x109 fail"); 01701 return -1; 01702 } 01703 Samples = u8 & cMeasMask; 01704 status = VL6180x_RdByte(dev, READOUT_AVERAGING_SAMPLE_PERIOD, &u8); 01705 if (status) { 01706 VL6180x_ErrLog("i2c READOUT_AVERAGING_SAMPLE_PERIOD fail"); 01707 return -1; 01708 } 01709 SamplePeriod = u8; 01710 SingleTime_us = cFwOverhead_us + cVcpSetupTime_us + (SamplePeriod * 10); 01711 TotalAveTime_us = (Samples + 1) * SingleTime_us + cPLL2_StartupDelay_us; 01712 01713 LOG_FUNCTION_END(TotalAveTime_us); 01714 return TotalAveTime_us; 01715 } 01716 01717 #if VL6180x_HAVE_DMAX_RANGING 01718 #define _GetDMaxDataRetSignalAt400mm(dev) VL6180xDevDataGet(dev, DMaxData.retSignalAt400mm) 01719 #else 01720 #define _GetDMaxDataRetSignalAt400mm(dev) 375 // Use a default high value 01721 #endif 01722 01723 01724 #if VL6180x_WRAP_AROUND_FILTER_SUPPORT 01725 01726 #define FILTER_STDDEV_SAMPLES 6 01727 #define MIN_FILTER_STDDEV_SAMPLES 3 01728 #define MIN_FILTER_VALID_STDDEV_SAMPLES 3 01729 #define FILTER_INVALID_DISTANCE 65535 01730 01731 #define _FilterData(field) VL6180xDevDataGet(dev, FilterData.field) 01732 /* 01733 * One time init 01734 */ 01735 static int _filter_Init( VL6180xDev_t dev) { 01736 int i; 01737 _FilterData(MeasurementIndex) = 0; 01738 01739 _FilterData(Default_ZeroVal) = 0; 01740 _FilterData(Default_VAVGVal) = 0; 01741 _FilterData(NoDelay_ZeroVal) = 0; 01742 _FilterData(NoDelay_VAVGVal) = 0; 01743 _FilterData(Previous_VAVGDiff) = 0; 01744 01745 _FilterData(StdFilteredReads) = 0; 01746 01747 for (i = 0; i < FILTER_NBOF_SAMPLES; i++) { 01748 _FilterData(LastTrueRange)[i] = FILTER_INVALID_DISTANCE; 01749 _FilterData(LastReturnRates)[i] = 0; 01750 } 01751 return 0; 01752 } 01753 01754 01755 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) { 01756 uint32_t newStdDev; 01757 uint16_t SNR; 01758 01759 if (AmbientRate > 0) 01760 SNR = (uint16_t) ((100 * SignalRate) / AmbientRate); 01761 else 01762 SNR = 9999; 01763 01764 if (SNR >= StdDevLimitLowLightSNR) { 01765 newStdDev = StdDevLimitLowLight; 01766 } else { 01767 if (SNR <= StdDevLimitHighLightSNR) 01768 newStdDev = StdDevLimitHighLight; 01769 else { 01770 newStdDev = (uint32_t) (StdDevLimitHighLight + (SNR - StdDevLimitHighLightSNR) * (int) (StdDevLimitLowLight - StdDevLimitHighLight) / (StdDevLimitLowLightSNR - StdDevLimitHighLightSNR)); 01771 } 01772 } 01773 01774 return newStdDev; 01775 } 01776 01777 01778 /* 01779 * Return <0 on error 01780 */ 01781 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) { 01782 int status; 01783 uint16_t m_newTrueRange_mm = 0; 01784 01785 uint16_t i; 01786 uint16_t bypassFilter = 0; 01787 01788 uint16_t registerValue; 01789 01790 uint32_t register32BitsValue1; 01791 uint32_t register32BitsValue2; 01792 01793 uint16_t ValidDistance = 0; 01794 01795 uint16_t WrapAroundFlag = 0; 01796 uint16_t NoWrapAroundFlag = 0; 01797 uint16_t NoWrapAroundHighConfidenceFlag = 0; 01798 01799 uint16_t FlushFilter = 0; 01800 uint32_t RateChange = 0; 01801 01802 uint16_t StdDevSamples = 0; 01803 uint32_t StdDevDistanceSum = 0; 01804 uint32_t StdDevDistanceMean = 0; 01805 uint32_t StdDevDistance = 0; 01806 uint32_t StdDevRateSum = 0; 01807 uint32_t StdDevRateMean = 0; 01808 uint32_t StdDevRate = 0; 01809 uint32_t StdDevLimitWithTargetMove = 0; 01810 01811 uint32_t VAVGDiff; 01812 uint32_t IdealVAVGDiff; 01813 uint32_t MinVAVGDiff; 01814 uint32_t MaxVAVGDiff; 01815 01816 /* Filter Parameters */ 01817 static const uint16_t ROMABLE_DATA WrapAroundLowRawRangeLimit = 60; 01818 static const uint32_t ROMABLE_DATA WrapAroundLowReturnRateLimit_ROM = 800; // Shall be adapted depending on crossTalk 01819 static const uint16_t ROMABLE_DATA WrapAroundLowRawRangeLimit2 = 165; 01820 static const uint32_t ROMABLE_DATA WrapAroundLowReturnRateLimit2_ROM = 180; // Shall be adapted depending on crossTalk and device sensitivity 01821 01822 static const uint32_t ROMABLE_DATA WrapAroundLowReturnRateFilterLimit_ROM = 850; // Shall be adapted depending on crossTalk and device sensitivity 01823 static const uint16_t ROMABLE_DATA WrapAroundHighRawRangeFilterLimit = 350; 01824 static const uint32_t ROMABLE_DATA WrapAroundHighReturnRateFilterLimit_ROM = 1400; // Shall be adapted depending on crossTalk and device sensitivity 01825 01826 static const uint32_t ROMABLE_DATA WrapAroundMaximumAmbientRateFilterLimit = 7500; 01827 01828 /* Temporal filter data and flush values */ 01829 static const uint32_t ROMABLE_DATA MinReturnRateFilterFlush = 75; 01830 static const uint32_t ROMABLE_DATA MaxReturnRateChangeFilterFlush = 50; 01831 01832 /* STDDEV values and damper values */ 01833 01834 static const uint32_t ROMABLE_DATA StdDevLimitLowLight = 300; 01835 static const uint32_t ROMABLE_DATA StdDevLimitLowLightSNR = 30; /* 0.3 */ 01836 static const uint32_t ROMABLE_DATA StdDevLimitHighLight = 2500; 01837 static const uint32_t ROMABLE_DATA StdDevLimitHighLightSNR = 5; /* 0.05 */ 01838 01839 static const uint32_t ROMABLE_DATA StdDevHighConfidenceSNRLimit = 8; 01840 01841 static const uint32_t ROMABLE_DATA StdDevMovingTargetStdDevLimit = 90000; 01842 01843 static const uint32_t ROMABLE_DATA StdDevMovingTargetReturnRateLimit = 3500; 01844 static const uint32_t ROMABLE_DATA StdDevMovingTargetStdDevForReturnRateLimit = 5000; 01845 01846 static const uint32_t ROMABLE_DATA MAX_VAVGDiff = 1800; 01847 01848 /* WrapAroundDetection variables */ 01849 static const uint16_t ROMABLE_DATA WrapAroundNoDelayCheckPeriod = 2; 01850 static const uint16_t ROMABLE_DATA StdFilteredReadsIncrement = 2; 01851 static const uint16_t ROMABLE_DATA StdMaxFilteredReads = 4; 01852 01853 uint32_t SignalRateDMax; 01854 uint32_t WrapAroundLowReturnRateLimit; 01855 uint32_t WrapAroundLowReturnRateLimit2; 01856 uint32_t WrapAroundLowReturnRateFilterLimit; 01857 uint32_t WrapAroundHighReturnRateFilterLimit; 01858 01859 uint8_t u8, u8_2; 01860 uint32_t XTalkCompRate_KCps; 01861 uint32_t StdDevLimit = 300; 01862 uint32_t MaxOrInvalidDistance = 255*_GetUpscale(dev); 01863 /* #define MaxOrInvalidDistance (uint16_t) (255 * 3) */ 01864 01865 /* Check if distance is Valid or not */ 01866 switch (errorCode) { 01867 case 0x0C: 01868 m_trueRange_mm = MaxOrInvalidDistance; 01869 ValidDistance = 0; 01870 break; 01871 case 0x0D: 01872 m_trueRange_mm = MaxOrInvalidDistance; 01873 ValidDistance = 1; 01874 break; 01875 case 0x0F: 01876 m_trueRange_mm = MaxOrInvalidDistance; 01877 ValidDistance = 1; 01878 break; 01879 default: 01880 if (m_rawRange_mm >= MaxOrInvalidDistance) { 01881 ValidDistance = 0; 01882 } else { 01883 ValidDistance = 1; 01884 } 01885 break; 01886 } 01887 m_newTrueRange_mm = m_trueRange_mm; 01888 01889 XTalkCompRate_KCps = VL6180xDevDataGet(dev, XTalkCompRate_KCps ); 01890 01891 01892 //Update signal rate limits depending on crosstalk 01893 SignalRateDMax = (uint32_t)_GetDMaxDataRetSignalAt400mm(dev) + XTalkCompRate_KCps; 01894 WrapAroundLowReturnRateLimit = WrapAroundLowReturnRateLimit_ROM + XTalkCompRate_KCps; 01895 WrapAroundLowReturnRateLimit2 = ((WrapAroundLowReturnRateLimit2_ROM * SignalRateDMax) / 312) + XTalkCompRate_KCps; 01896 WrapAroundLowReturnRateFilterLimit = ((WrapAroundLowReturnRateFilterLimit_ROM * SignalRateDMax) / 312) + XTalkCompRate_KCps; 01897 WrapAroundHighReturnRateFilterLimit = ((WrapAroundHighReturnRateFilterLimit_ROM * SignalRateDMax) / 312) + XTalkCompRate_KCps; 01898 01899 01900 /* Checks on low range data */ 01901 if ((m_rawRange_mm < WrapAroundLowRawRangeLimit) && (m_rtnSignalRate < WrapAroundLowReturnRateLimit)) { 01902 m_newTrueRange_mm = MaxOrInvalidDistance; 01903 bypassFilter = 1; 01904 } 01905 if ((m_rawRange_mm < WrapAroundLowRawRangeLimit2) && (m_rtnSignalRate < WrapAroundLowReturnRateLimit2)) { 01906 m_newTrueRange_mm = MaxOrInvalidDistance; 01907 bypassFilter = 1; 01908 } 01909 01910 /* Checks on Ambient rate level */ 01911 if (m_rtnAmbientRate > WrapAroundMaximumAmbientRateFilterLimit) { 01912 /* Too high ambient rate */ 01913 FlushFilter = 1; 01914 bypassFilter = 1; 01915 } 01916 /* Checks on Filter flush */ 01917 if (m_rtnSignalRate < MinReturnRateFilterFlush) { 01918 /* Completely lost target, so flush the filter */ 01919 FlushFilter = 1; 01920 bypassFilter = 1; 01921 } 01922 if (_FilterData(LastReturnRates)[0] != 0) { 01923 if (m_rtnSignalRate > _FilterData(LastReturnRates)[0]) 01924 RateChange = (100 * (m_rtnSignalRate - _FilterData(LastReturnRates)[0])) / _FilterData(LastReturnRates)[0]; 01925 else 01926 RateChange = (100 * (_FilterData(LastReturnRates)[0] - m_rtnSignalRate)) / _FilterData(LastReturnRates)[0]; 01927 } else 01928 RateChange = 0; 01929 if (RateChange > MaxReturnRateChangeFilterFlush) { 01930 FlushFilter = 1; 01931 } 01932 /* TODO optimize filter using circular buffer */ 01933 if (FlushFilter == 1) { 01934 _FilterData(MeasurementIndex) = 0; 01935 for (i = 0; i < FILTER_NBOF_SAMPLES; i++) { 01936 _FilterData(LastTrueRange)[i] = FILTER_INVALID_DISTANCE; 01937 _FilterData(LastReturnRates)[i] = 0; 01938 } 01939 } else { 01940 for (i = (uint16_t) (FILTER_NBOF_SAMPLES - 1); i > 0; i--) { 01941 _FilterData(LastTrueRange)[i] = _FilterData(LastTrueRange)[i - 1]; 01942 _FilterData(LastReturnRates)[i] = _FilterData(LastReturnRates)[i - 1]; 01943 } 01944 } 01945 if (ValidDistance == 1) 01946 _FilterData(LastTrueRange)[0] = m_trueRange_mm; 01947 else 01948 _FilterData(LastTrueRange)[0] = FILTER_INVALID_DISTANCE; 01949 _FilterData(LastReturnRates)[0] = m_rtnSignalRate; 01950 01951 /* Check if we need to go through the filter or not */ 01952 if (!(((m_rawRange_mm < WrapAroundHighRawRangeFilterLimit) && (m_rtnSignalRate < WrapAroundLowReturnRateFilterLimit)) || ((m_rawRange_mm >= WrapAroundHighRawRangeFilterLimit) && (m_rtnSignalRate < WrapAroundHighReturnRateFilterLimit)))) 01953 bypassFilter = 1; 01954 01955 /* Check which kind of measurement has been made */ 01956 status = VL6180x_RdByte(dev, 0x01AC, &u8 ); 01957 if( status ){ 01958 VL6180x_ErrLog("0x01AC rd fail"); 01959 goto done_err; 01960 } 01961 registerValue =u8; 01962 01963 /* Read data for filtering */ 01964 status = VL6180x_RdByte(dev, 0x10C, &u8 ); /* read only 8 lsb bits */ 01965 if( status ){ 01966 VL6180x_ErrLog("0x010C rd fail"); 01967 goto done_err; 01968 } 01969 register32BitsValue1=u8; 01970 status = VL6180x_RdByte(dev, 0x0110, &u8); /* read only 8 lsb bits */ 01971 if( status ){ 01972 VL6180x_ErrLog("0x0110 rd fail"); 01973 goto done_err; 01974 } 01975 register32BitsValue2 = u8; 01976 01977 if (registerValue == 0x3E) { 01978 _FilterData(Default_ZeroVal) = register32BitsValue1; 01979 _FilterData(Default_VAVGVal) = register32BitsValue2; 01980 } else { 01981 _FilterData(NoDelay_ZeroVal) = register32BitsValue1; 01982 _FilterData(NoDelay_VAVGVal) = register32BitsValue2; 01983 } 01984 01985 if (bypassFilter == 1) { 01986 /* Do not go through the filter */ 01987 if (registerValue != 0x3E) { 01988 status = VL6180x_WrByte(dev, 0x1AC, 0x3E); 01989 if( status ){ 01990 VL6180x_ErrLog("0x01AC bypass wr fail"); 01991 goto done_err; 01992 } 01993 status = VL6180x_WrByte(dev, 0x0F2, 0x01); 01994 if( status ){ 01995 VL6180x_ErrLog("0x0F2 bypass wr fail"); 01996 goto done_err; 01997 } 01998 } 01999 /* Set both Default and NoDelay To same value */ 02000 _FilterData(Default_ZeroVal) = register32BitsValue1; 02001 _FilterData(Default_VAVGVal) = register32BitsValue2; 02002 _FilterData(NoDelay_ZeroVal) = register32BitsValue1; 02003 _FilterData(NoDelay_VAVGVal) = register32BitsValue2; 02004 _FilterData(MeasurementIndex) = 0; 02005 02006 return m_newTrueRange_mm; 02007 } 02008 02009 if (_FilterData(MeasurementIndex) % WrapAroundNoDelayCheckPeriod == 0) { 02010 u8=0x3C; 02011 u8_2 = 0x05; 02012 } else { 02013 u8=0x3E; 02014 u8_2 = 0x01; 02015 } 02016 status = VL6180x_WrByte(dev, 0x01AC, u8); 02017 if( status ){ 02018 VL6180x_ErrLog("0x01AC wr fail"); 02019 goto done_err; 02020 } 02021 status = VL6180x_WrByte(dev, 0x0F2, u8_2); 02022 if( status ){ 02023 VL6180x_ErrLog("0x0F2 wr fail"); 02024 goto done_err; 02025 } 02026 02027 02028 _FilterData(MeasurementIndex)++; 02029 02030 /* Computes current VAVGDiff */ 02031 if (_FilterData(Default_VAVGVal) > _FilterData(NoDelay_VAVGVal)) 02032 VAVGDiff = _FilterData(Default_VAVGVal) - _FilterData(NoDelay_VAVGVal); 02033 else 02034 VAVGDiff = 0; 02035 _FilterData(Previous_VAVGDiff) = VAVGDiff; 02036 02037 /* Check the VAVGDiff */ 02038 if (_FilterData(Default_ZeroVal) > _FilterData(NoDelay_ZeroVal)) 02039 IdealVAVGDiff = _FilterData(Default_ZeroVal) - _FilterData(NoDelay_ZeroVal); 02040 else 02041 IdealVAVGDiff = _FilterData(NoDelay_ZeroVal) - _FilterData(Default_ZeroVal); 02042 if (IdealVAVGDiff > MAX_VAVGDiff) 02043 MinVAVGDiff = IdealVAVGDiff - MAX_VAVGDiff; 02044 else 02045 MinVAVGDiff = 0; 02046 MaxVAVGDiff = IdealVAVGDiff + MAX_VAVGDiff; 02047 if (VAVGDiff < MinVAVGDiff || VAVGDiff > MaxVAVGDiff) { 02048 WrapAroundFlag = 1; 02049 } else { 02050 /* Go through filtering check */ 02051 02052 /* StdDevLimit Damper on SNR */ 02053 StdDevLimit = _filter_StdDevDamper(m_rtnAmbientRate, m_rtnSignalRate, StdDevLimitLowLight, StdDevLimitLowLightSNR, StdDevLimitHighLight, StdDevLimitHighLightSNR); 02054 02055 /* Standard deviations computations */ 02056 StdDevSamples = 0; 02057 StdDevDistanceSum = 0; 02058 StdDevDistanceMean = 0; 02059 StdDevDistance = 0; 02060 StdDevRateSum = 0; 02061 StdDevRateMean = 0; 02062 StdDevRate = 0; 02063 for (i = 0; (i < FILTER_NBOF_SAMPLES) && (StdDevSamples < FILTER_STDDEV_SAMPLES); i++) { 02064 if (_FilterData(LastTrueRange)[i] != FILTER_INVALID_DISTANCE) { 02065 StdDevSamples = (uint16_t) (StdDevSamples + 1); 02066 StdDevDistanceSum = (uint32_t) (StdDevDistanceSum + _FilterData(LastTrueRange)[i]); 02067 StdDevRateSum = (uint32_t) (StdDevRateSum + _FilterData(LastReturnRates)[i]); 02068 } 02069 } 02070 if (StdDevSamples > 0) { 02071 StdDevDistanceMean = (uint32_t) (StdDevDistanceSum / StdDevSamples); 02072 StdDevRateMean = (uint32_t) (StdDevRateSum / StdDevSamples); 02073 } 02074 /* TODO optimize shorten Std dev in aisngle loop computation using sum of x2 - (sum of x)2 */ 02075 StdDevSamples = 0; 02076 StdDevDistanceSum = 0; 02077 StdDevRateSum = 0; 02078 for (i = 0; (i < FILTER_NBOF_SAMPLES) && (StdDevSamples < FILTER_STDDEV_SAMPLES); i++) { 02079 if (_FilterData(LastTrueRange)[i] != FILTER_INVALID_DISTANCE) { 02080 StdDevSamples = (uint16_t) (StdDevSamples + 1); 02081 StdDevDistanceSum = (uint32_t) (StdDevDistanceSum + (int) (_FilterData(LastTrueRange)[i] - StdDevDistanceMean) * (int) (_FilterData(LastTrueRange)[i] - StdDevDistanceMean)); 02082 StdDevRateSum = (uint32_t) (StdDevRateSum + (int) (_FilterData(LastReturnRates)[i] - StdDevRateMean) * (int) (_FilterData(LastReturnRates)[i] - StdDevRateMean)); 02083 } 02084 } 02085 if (StdDevSamples >= MIN_FILTER_STDDEV_SAMPLES) { 02086 StdDevDistance = (uint16_t) (StdDevDistanceSum / StdDevSamples); 02087 StdDevRate = (uint16_t) (StdDevRateSum / StdDevSamples); 02088 } else { 02089 StdDevDistance = 0; 02090 StdDevRate = 0; 02091 } 02092 02093 /* Check Return rate standard deviation */ 02094 if (StdDevRate < StdDevMovingTargetStdDevLimit) { 02095 if (StdDevSamples < MIN_FILTER_VALID_STDDEV_SAMPLES) { 02096 m_newTrueRange_mm = MaxOrInvalidDistance; 02097 } else { 02098 /* Check distance standard deviation */ 02099 if (StdDevRate < StdDevMovingTargetReturnRateLimit) 02100 StdDevLimitWithTargetMove = StdDevLimit + (((StdDevMovingTargetStdDevForReturnRateLimit - StdDevLimit) * StdDevRate) / StdDevMovingTargetReturnRateLimit); 02101 else 02102 StdDevLimitWithTargetMove = StdDevMovingTargetStdDevForReturnRateLimit; 02103 02104 if ((StdDevDistance * StdDevHighConfidenceSNRLimit) < StdDevLimitWithTargetMove) { 02105 NoWrapAroundHighConfidenceFlag = 1; 02106 } else { 02107 if (StdDevDistance < StdDevLimitWithTargetMove) { 02108 if (StdDevSamples >= MIN_FILTER_VALID_STDDEV_SAMPLES) { 02109 NoWrapAroundFlag = 1; 02110 } else { 02111 m_newTrueRange_mm = MaxOrInvalidDistance; 02112 } 02113 } else { 02114 WrapAroundFlag = 1; 02115 } 02116 } 02117 } 02118 } else { 02119 WrapAroundFlag = 1; 02120 } 02121 } 02122 02123 if (m_newTrueRange_mm == MaxOrInvalidDistance) { 02124 if (_FilterData(StdFilteredReads) > 0) 02125 _FilterData(StdFilteredReads) = (uint16_t) (_FilterData(StdFilteredReads) - 1); 02126 } else { 02127 if (WrapAroundFlag == 1) { 02128 m_newTrueRange_mm = MaxOrInvalidDistance; 02129 _FilterData(StdFilteredReads) = (uint16_t) (_FilterData(StdFilteredReads) + StdFilteredReadsIncrement); 02130 if (_FilterData(StdFilteredReads) > StdMaxFilteredReads) 02131 _FilterData(StdFilteredReads) = StdMaxFilteredReads; 02132 } else { 02133 if (NoWrapAroundFlag == 1) { 02134 if (_FilterData(StdFilteredReads) > 0) { 02135 m_newTrueRange_mm = MaxOrInvalidDistance; 02136 if (_FilterData(StdFilteredReads) > StdFilteredReadsIncrement) 02137 _FilterData(StdFilteredReads) = (uint16_t) (_FilterData(StdFilteredReads) - StdFilteredReadsIncrement); 02138 else 02139 _FilterData(StdFilteredReads) = 0; 02140 } 02141 } else { 02142 if (NoWrapAroundHighConfidenceFlag == 1) { 02143 _FilterData(StdFilteredReads) = 0; 02144 } 02145 } 02146 } 02147 } 02148 02149 return m_newTrueRange_mm; 02150 done_err: 02151 return -1; 02152 02153 #undef MaxOrInvalidDistance 02154 } 02155 02156 02157 int VL6180X::_filter_GetResult(VL6180xDev_t dev, VL6180x_RangeData_t *pRangeData) { 02158 uint32_t m_rawRange_mm = 0; 02159 int32_t FilteredRange; 02160 const uint8_t scaler = _GetUpscale(dev); 02161 uint8_t u8; 02162 int status; 02163 02164 do { 02165 status = VL6180x_RdByte(dev, RESULT_RANGE_RAW, &u8); 02166 if (status) { 02167 VL6180x_ErrLog("RESULT_RANGE_RAW rd fail"); 02168 break; 02169 } 02170 m_rawRange_mm = u8; 02171 02172 FilteredRange = _filter_Start(dev, pRangeData->range_mm , (m_rawRange_mm * scaler), pRangeData->rtnRate , pRangeData->rtnAmbRate , pRangeData->errorStatus ); 02173 if( FilteredRange<0 ){ 02174 status = -1; 02175 break; 02176 } 02177 pRangeData->FilteredData .range_mm = FilteredRange; 02178 pRangeData->FilteredData .rawRange_mm = m_rawRange_mm * scaler; 02179 } while (0); 02180 return status; 02181 } 02182 02183 #undef _FilterData 02184 #undef FILTER_STDDEV_SAMPLES 02185 #undef MIN_FILTER_STDDEV_SAMPLES 02186 #undef MIN_FILTER_VALID_STDDEV_SAMPLES 02187 #undef FILTER_INVALID_DISTANCE 02188 02189 #endif /* VL6180x_WRAP_AROUND_FILTER_SUPPORT */ 02190 02191 #ifdef VL6180x_HAVE_RATE_DATA 02192 02193 int VL6180X::_GetRateResult(VL6180xDev_t dev, VL6180x_RangeData_t *pRangeData) { 02194 uint32_t m_rtnConvTime = 0; 02195 uint32_t m_rtnSignalRate = 0; 02196 uint32_t m_rtnAmbientRate = 0; 02197 uint32_t m_rtnSignalCount = 0; 02198 uint32_t m_rtnAmbientCount = 0; 02199 uint32_t m_refConvTime = 0; 02200 uint32_t cRtnSignalCountMax = 0x7FFFFFFF; 02201 uint32_t cDllPeriods = 6; 02202 uint32_t calcConvTime = 0; 02203 02204 int status; 02205 02206 do { 02207 02208 status = VL6180x_RdDWord(dev, RESULT_RANGE_RETURN_SIGNAL_COUNT, &m_rtnSignalCount); 02209 if (status) { 02210 VL6180x_ErrLog("RESULT_RANGE_RETURN_SIGNAL_COUNT rd fail"); 02211 break; 02212 } 02213 if (m_rtnSignalCount > cRtnSignalCountMax) { 02214 m_rtnSignalCount = 0; 02215 } 02216 02217 status = VL6180x_RdDWord(dev, RESULT_RANGE_RETURN_AMB_COUNT, &m_rtnAmbientCount); 02218 if (status) { 02219 VL6180x_ErrLog("RESULT_RANGE_RETURN_AMB_COUNTrd fail"); 02220 break; 02221 } 02222 02223 02224 status = VL6180x_RdDWord(dev, RESULT_RANGE_RETURN_CONV_TIME, &m_rtnConvTime); 02225 if (status) { 02226 VL6180x_ErrLog("RESULT_RANGE_RETURN_CONV_TIME rd fail"); 02227 break; 02228 } 02229 02230 status = VL6180x_RdDWord(dev, RESULT_RANGE_REFERENCE_CONV_TIME, &m_refConvTime); 02231 if (status) { 02232 VL6180x_ErrLog("RESULT_RANGE_REFERENCE_CONV_TIME rd fail"); 02233 break; 02234 } 02235 02236 pRangeData->rtnConvTime = m_rtnConvTime; 02237 pRangeData->refConvTime = m_refConvTime; 02238 02239 calcConvTime = m_refConvTime; 02240 if (m_rtnConvTime > m_refConvTime) { 02241 calcConvTime = m_rtnConvTime; 02242 } 02243 if (calcConvTime == 0) 02244 calcConvTime = 63000; 02245 02246 m_rtnSignalRate = (m_rtnSignalCount * 1000) / calcConvTime; 02247 m_rtnAmbientRate = (m_rtnAmbientCount * cDllPeriods * 1000) / calcConvTime; 02248 02249 pRangeData->rtnRate = m_rtnSignalRate; 02250 pRangeData->rtnAmbRate = m_rtnAmbientRate; 02251 02252 02253 } while (0); 02254 return status; 02255 } 02256 #endif /* VL6180x_HAVE_RATE_DATA */ 02257 02258 02259 int VL6180X::VL6180x_DMaxSetState(VL6180xDev_t dev, int state){ 02260 int status; 02261 LOG_FUNCTION_START("%d", state); 02262 #if VL6180x_HAVE_DMAX_RANGING 02263 VL6180xDevDataSet(dev,DMaxEnable, state); 02264 if( state ){ 02265 status = _DMax_InitData(dev); 02266 } 02267 else { 02268 status = 0; 02269 } 02270 #else 02271 status = NOT_SUPPORTED; 02272 #endif 02273 LOG_FUNCTION_END(status); 02274 return status; 02275 } 02276 02277 int VL6180X::VL6180x_DMaxGetState(VL6180xDev_t dev){ 02278 int status; 02279 LOG_FUNCTION_START(""); 02280 #if VL6180x_HAVE_DMAX_RANGING 02281 status = VL6180xDevDataGet(dev,DMaxEnable); 02282 #else 02283 status = 0; 02284 #endif 02285 LOG_FUNCTION_END(status); 02286 return status; 02287 } 02288 02289 02290 #if VL6180x_HAVE_DMAX_RANGING 02291 02292 #define _DMaxData(field) VL6180xDevDataGet(dev, DMaxData.field) 02293 /* 02294 * Convert fix point x.7 to KCpount per sec 02295 */ 02296 02297 #ifndef VL6180x_PLATFORM_PROVIDE_SQRT 02298 02299 /* 02300 * 32 bit integer square root with not so bad precision (integer result) and is quite fast 02301 * see http://en.wikipedia.org/wiki/Methods_of_computing_square_roots 02302 */ 02303 uint32_t VL6180x_SqrtUint32(uint32_t num) { 02304 uint32_t res = 0; 02305 uint32_t bit = 1 << 30; /* The second-to-top bit is set: 1 << 30 for 32 bits */ 02306 02307 /* "bit" starts at the highest power of four <= the argument. */ 02308 while (bit > num) 02309 bit >>= 2; 02310 02311 while (bit != 0) { 02312 if (num >= res + bit) { 02313 num -= res + bit; 02314 res = (res >> 1) + bit; 02315 } 02316 else 02317 res >>= 1; 02318 bit >>= 2; 02319 } 02320 return res; 02321 } 02322 #endif 02323 02324 02325 /* DMax one time init */ 02326 void _DMax_OneTimeInit(VL6180xDev_t dev){ 02327 _DMaxData(ambTuningWindowFactor_K)=DEF_AMBIENT_TUNING; 02328 } 02329 02330 02331 static uint32_t _DMax_RawValueAtRateKCps(VL6180xDev_t dev, int32_t rate){ 02332 uint32_t snrLimit_K; 02333 int32_t DMaxSq; 02334 uint32_t RawDMax; 02335 DMaxFix_t retSignalAt400mm; 02336 uint32_t ambTuningWindowFactor_K; 02337 02338 02339 ambTuningWindowFactor_K = _DMaxData(ambTuningWindowFactor_K); 02340 snrLimit_K = _DMaxData(snrLimit_K); 02341 retSignalAt400mm = _DMaxData(retSignalAt400mm); /* 12 to 18 bits Kcps */ 02342 if( rate > 0 ){ 02343 DMaxSq = 400*400*1000 / rate -(400*400/330); /* K of (1/RtnAmb -1/330 )=> 30bit- (12-18)bit => 12-18 bits*/ 02344 if( DMaxSq<= 0){ 02345 RawDMax = 0; 02346 } 02347 else{ 02348 /* value can be more 32 bit so base on raneg apply *retSignalAt400mm before or after division to presevr accuracy */ 02349 if( DMaxSq< (2<<12) ){ 02350 DMaxSq = DMaxSq*retSignalAt400mm/(snrLimit_K+ambTuningWindowFactor_K); /* max 12 + 12 to 18 -10 => 12-26 bit */ 02351 }else{ 02352 DMaxSq = DMaxSq/(snrLimit_K+ambTuningWindowFactor_K)*retSignalAt400mm; /* 12 to 18 -10 + 12 to 18 *=> 12-26 bit */ 02353 } 02354 RawDMax=VL6180x_SqrtUint32(DMaxSq); 02355 } 02356 } 02357 else{ 02358 RawDMax = 0x7FFFFFFF; /* bigest possibmle 32bit signed value */ 02359 } 02360 return RawDMax; 02361 } 02362 02363 /* 02364 * fetch static data from register to avoid re-read 02365 * precompute all intermediate constant and cliipings 02366 * 02367 * to be re-used/call on changes of : 02368 * 0x2A 02369 * SYSRANGE_MAX_AMBIENT_LEVEL_MULT 02370 * Dev Data XtalkComRate_KCPs 02371 * SYSRANGE_MAX_CONVERGENCE_TIME 02372 * SYSRANGE_RANGE_CHECK_ENABLES mask RANGE_CHECK_RANGE_ENABLE_MASK 02373 * range 0xb8-0xbb (0xbb) 02374 */ 02375 int VL6180X::_DMax_InitData(VL6180xDev_t dev){ 02376 int status, warning; 02377 uint8_t u8; 02378 uint16_t u16; 02379 uint32_t u32; 02380 uint32_t Reg2A_KCps; 02381 uint32_t RegB8; 02382 uint8_t MaxConvTime; 02383 uint32_t XTalkCompRate_KCps; 02384 uint32_t RangeIgnoreThreshold; 02385 int32_t minSignalNeeded; 02386 uint8_t SysRangeCheckEn; 02387 uint8_t snrLimit; 02388 warning=0; 02389 02390 static const int ROMABLE_DATA MaxConvTimeAdjust=-4; 02391 02392 LOG_FUNCTION_START(""); 02393 do{ 02394 status = VL6180x_RdByte(dev, 0x02A ,&u8); 02395 if( status ){ 02396 VL6180x_ErrLog("Reg 0x02A rd fail"); 02397 break; 02398 } 02399 02400 if( u8 == 0 ) { 02401 warning = CALIBRATION_WARNING; 02402 u8 = 40; /* use a default average value */ 02403 } 02404 Reg2A_KCps = Fix7_2_KCPs(u8); /* convert to KCPs */ 02405 02406 status = VL6180x_RdByte(dev, SYSRANGE_RANGE_CHECK_ENABLES, &SysRangeCheckEn); 02407 if (status) { 02408 VL6180x_ErrLog("SYSRANGE_RANGE_CHECK_ENABLES rd fail "); 02409 break; 02410 } 02411 02412 status = VL6180x_RdByte(dev, SYSRANGE_MAX_CONVERGENCE_TIME, &MaxConvTime); 02413 if( status){ 02414 VL6180x_ErrLog("SYSRANGE_MAX_CONVERGENCE_TIME rd fail "); 02415 break; 02416 } 02417 02418 status = VL6180x_RdDWord(dev, 0x0B8, &RegB8); 02419 if( status ){ 02420 VL6180x_ErrLog("reg 0x0B8 rd fail "); 02421 break; 02422 } 02423 02424 status = VL6180x_RdByte(dev, SYSRANGE_MAX_AMBIENT_LEVEL_MULT, &snrLimit); 02425 if( status){ 02426 VL6180x_ErrLog("SYSRANGE_MAX_AMBIENT_LEVEL_MULT rd fail "); 02427 break; 02428 } 02429 _DMaxData(snrLimit_K) = (int32_t)16*1000/snrLimit; 02430 XTalkCompRate_KCps = VL6180xDevDataGet(dev, XTalkCompRate_KCps ); 02431 02432 if( Reg2A_KCps >= XTalkCompRate_KCps){ 02433 _DMaxData(retSignalAt400mm)=( Reg2A_KCps - XTalkCompRate_KCps); 02434 } 02435 else{ 02436 _DMaxData(retSignalAt400mm)=0; /* Reg2A_K - XTalkCompRate_KCp <0 is invalid */ 02437 } 02438 02439 /* if xtalk range check is off omit it in snr clipping */ 02440 if( SysRangeCheckEn&RANGE_CHECK_RANGE_ENABLE_MASK ){ 02441 status = VL6180x_RdWord(dev, SYSRANGE_RANGE_IGNORE_THRESHOLD, &u16); 02442 if( status){ 02443 VL6180x_ErrLog("SYSRANGE_RANGE_IGNORE_THRESHOLD rd fail "); 02444 break; 02445 } 02446 RangeIgnoreThreshold = Fix7_2_KCPs(u16); 02447 } 02448 else{ 02449 RangeIgnoreThreshold = 0; 02450 } 02451 02452 minSignalNeeded = (RegB8*256)/((int32_t)MaxConvTime+(int32_t)MaxConvTimeAdjust); /* KCps 8+8 bit -(1 to 6 bit) => 15-10 bit */ 02453 /* minSignalNeeded = max ( minSignalNeeded, RangeIgnoreThreshold - XTalkCompRate_KCps) */ 02454 if( minSignalNeeded <= RangeIgnoreThreshold - XTalkCompRate_KCps ) 02455 minSignalNeeded = RangeIgnoreThreshold - XTalkCompRate_KCps; 02456 02457 u32 = (minSignalNeeded*(uint32_t)snrLimit)/16; 02458 _DMaxData(ClipSnrLimit ) = _DMax_RawValueAtRateKCps(dev, u32 ); /* clip to dmax to min signal snr limit rate*/ 02459 } 02460 while(0); 02461 if( !status ) 02462 status = warning; 02463 LOG_FUNCTION_END(status); 02464 return status; 02465 } 02466 02467 static int _DMax_Compute(VL6180xDev_t dev, VL6180x_RangeData_t *pRange){ 02468 uint32_t rtnAmbRate; 02469 int32_t DMax; 02470 int scaling; 02471 uint16_t HwLimitAtScale; 02472 static const int ROMABLE_DATA rtnAmbLowLimit_KCps=330*1000; 02473 02474 rtnAmbRate = pRange->rtnAmbRate ; 02475 if( rtnAmbRate < rtnAmbLowLimit_KCps ){ 02476 DMax = _DMax_RawValueAtRateKCps( dev, rtnAmbRate); 02477 scaling = _GetUpscale(dev); 02478 HwLimitAtScale=UpperLimitLookUP[scaling - 1]; 02479 02480 if( DMax > _DMaxData(ClipSnrLimit) ){ 02481 DMax=_DMaxData(ClipSnrLimit); 02482 } 02483 if( DMax > HwLimitAtScale ){ 02484 DMax=HwLimitAtScale; 02485 } 02486 pRange->DMax =DMax; 02487 } 02488 else{ 02489 pRange->DMax = 0; 02490 } 02491 return 0; 02492 } 02493 02494 #undef _DMaxData 02495 #undef Fix7_2_KCPs 02496 02497 #endif /* VL6180x_HAVE_DMAX_RANGING */ 02498 02499 02500 /******************************************************************************/ 02501 /******************************************************************************/ 02502 02503 02504 02505 /****************** Write and read functions from I2C *************************/ 02506 02507 int VL6180X::VL6180x_WrByte(VL6180xDev_t dev, uint16_t index, uint8_t data) 02508 { 02509 int status; 02510 02511 status=VL6180x_I2CWrite(dev->I2cAddr, index, &data,(uint8_t)1); 02512 return status; 02513 } 02514 02515 int VL6180X::VL6180x_WrWord(VL6180xDev_t dev, uint16_t index, uint16_t data) 02516 { 02517 int status; 02518 02519 status=VL6180x_I2CWrite(dev->I2cAddr, index, (uint8_t *)&data,(uint8_t)2); 02520 return status; 02521 } 02522 02523 int VL6180X::VL6180x_WrDWord(VL6180xDev_t dev, uint16_t index, uint32_t data) 02524 { 02525 int status; 02526 02527 status=VL6180x_I2CWrite(dev->I2cAddr, index, (uint8_t *)&data,(uint8_t)4); 02528 return status; 02529 } 02530 02531 int VL6180X::VL6180x_RdByte(VL6180xDev_t dev, uint16_t index, uint8_t *data) 02532 { 02533 int status; 02534 02535 uint8_t buffer=0; 02536 status=VL6180x_I2CRead(dev->I2cAddr, index, &buffer,1); 02537 if(!status) 02538 { 02539 *data=buffer; 02540 } 02541 return status; 02542 } 02543 02544 int VL6180X::VL6180x_RdWord(VL6180xDev_t dev, uint16_t index, uint16_t *data) 02545 { 02546 int status; 02547 02548 uint8_t buffer[2]; 02549 buffer[0]=buffer[1]=0; 02550 status=VL6180x_I2CRead(dev->I2cAddr, index, buffer, 2); 02551 if(!status) 02552 { 02553 memcpy(data, buffer, 2); 02554 } 02555 return status; 02556 } 02557 02558 int VL6180X::VL6180x_RdDWord(VL6180xDev_t dev, uint16_t index, uint32_t *data) 02559 { 02560 int status; 02561 uint8_t buffer[4]; 02562 buffer[0]=buffer[1]=buffer[2]=buffer[3]=0; 02563 status=VL6180x_I2CRead(dev->I2cAddr, index, buffer,4); 02564 if(!status) 02565 { 02566 memcpy(data, buffer, 4); 02567 } 02568 return status; 02569 } 02570 02571 int VL6180X::VL6180x_UpdateByte(VL6180xDev_t dev, uint16_t index, uint8_t AndData, uint8_t OrData) 02572 { 02573 int status; 02574 uint8_t buffer=0; 02575 02576 status=VL6180x_I2CWrite(dev->I2cAddr, index, (uint8_t *)&buffer,(uint8_t)0); 02577 if(!status) 02578 { 02579 /* read data direct onto buffer */ 02580 status=VL6180x_I2CRead(dev->I2cAddr, index, &buffer,1); 02581 if(!status) 02582 { 02583 buffer=(buffer & AndData)|OrData; 02584 status=VL6180x_I2CWrite(dev->I2cAddr, index, &buffer, (uint8_t)1); 02585 } 02586 } 02587 return status; 02588 } 02589 02590 int VL6180X::VL6180x_I2CWrite(uint8_t DeviceAddr, uint16_t RegisterAddr, uint8_t* pBuffer, uint16_t NumByteToWrite) 02591 { 02592 int ret; 02593 int i; 02594 uint8_t tmp[TEMP_BUF_SIZE]; 02595 uint16_t myRegisterAddr = RegisterAddr; 02596 uint16_t WriteDeviceAddr=0; 02597 02598 /* First, prepare 8 bits device address in 7bits i2ci format */ 02599 WriteDeviceAddr=DeviceAddr*2; 02600 if(NumByteToWrite >= TEMP_BUF_SIZE) return -2; 02601 02602 /* then prepare 16 bits register address in BE format. Then, send data and STOP condition */ 02603 tmp[0] = *(((uint8_t*)&myRegisterAddr)+1); 02604 tmp[1] = (uint8_t)RegisterAddr; 02605 02606 if(NumByteToWrite>1) /* swap data endianess */ 02607 { 02608 for(i=0;i<NumByteToWrite;i++) 02609 { 02610 tmp[NumByteToWrite+sizeof(RegisterAddr)-1-i]=pBuffer[i]; 02611 } 02612 } 02613 else 02614 { 02615 memcpy(tmp+sizeof(RegisterAddr), pBuffer, NumByteToWrite); 02616 } 02617 ret = dev_i2c.write(WriteDeviceAddr, (const char*)tmp, NumByteToWrite+sizeof(RegisterAddr), false); 02618 02619 if(ret) 02620 return -1; 02621 return 0; 02622 } 02623 02624 int VL6180X::VL6180x_I2CRead(uint8_t DeviceAddr, uint16_t RegisterAddr, uint8_t* pBuffer, uint16_t NumByteToRead) 02625 { 02626 int ret,i; 02627 uint8_t tmp[TEMP_BUF_SIZE]; 02628 uint16_t myRegisterAddr = RegisterAddr; 02629 uint16_t myRegisterAddrBE; 02630 uint16_t ReadDeviceAddr=DeviceAddr; 02631 02632 ReadDeviceAddr=DeviceAddr*2; 02633 myRegisterAddrBE = *(((uint8_t*)&myRegisterAddr)+1); 02634 *(((uint8_t*)&myRegisterAddrBE)+1) = (uint8_t)myRegisterAddr; 02635 02636 /* Send 8 bits device address and 16 bits register address in BE format, with no STOP condition */ 02637 ret = dev_i2c.write(ReadDeviceAddr, (const char*)&myRegisterAddrBE, sizeof(RegisterAddr), true); 02638 if(!ret) 02639 { 02640 ReadDeviceAddr|=0x001; 02641 /* Read data, with STOP condition */ 02642 ret = dev_i2c.read(ReadDeviceAddr, (char*)tmp, NumByteToRead, false); 02643 } 02644 if(ret) 02645 return -1; 02646 02647 if(NumByteToRead>1) /* swap data endianess */ 02648 { 02649 for(i=0;i<NumByteToRead;i++) 02650 { 02651 pBuffer[i] = tmp[NumByteToRead-1-i]; 02652 } 02653 } 02654 else 02655 { 02656 memcpy(pBuffer, tmp, NumByteToRead); 02657 } 02658 return 0; 02659 } 02660 02661 /******************************************************************************/ 02662 02663 int VL6180X::AlsSetThresholds(uint16_t lux_threshold_low, uint16_t lux_threshold_high) 02664 { 02665 uint32_t AlsAnGain, IntPeriod, AlsScaler , GainFix, RawAlsHigh, RawAlsLow; 02666 uint16_t RawThreshLow, RawThreshHigh; 02667 const uint32_t LuxResxIntIme =(uint32_t)(0.56f* DEF_INT_PEFRIOD *(1<<LUXRES_FIX_PREC)); 02668 void *p_low; 02669 void *p_high; 02670 02671 AlsAnGain=VL6180xDevDataGet(Device, AlsGainCode ); 02672 IntPeriod=VL6180xDevDataGet(Device, IntegrationPeriod ); 02673 AlsScaler=VL6180xDevDataGet(Device, AlsScaler); 02674 GainFix=AlsGainLookUp[AlsAnGain]; 02675 IntPeriod++; 02676 RawAlsLow=lux_threshold_low*AlsScaler*GainFix; 02677 RawAlsLow=RawAlsLow*IntPeriod; 02678 RawAlsLow=RawAlsLow/LuxResxIntIme; 02679 RawAlsHigh=lux_threshold_high*(AlsScaler*GainFix); 02680 RawAlsHigh=RawAlsHigh*IntPeriod; 02681 RawAlsHigh=RawAlsHigh/LuxResxIntIme; 02682 p_low=&RawAlsLow; 02683 RawThreshLow=*(uint16_t*)p_low; 02684 p_high=&RawAlsHigh; 02685 RawThreshHigh=*(uint16_t*)p_high; 02686 return VL6180x_AlsSetThresholds(Device, RawThreshLow, RawThreshHigh); 02687 } 02688 02689 02690 int VL6180X::ReadID(uint8_t *id) 02691 { 02692 return VL6180x_RdByte(Device, IDENTIFICATION_MODEL_ID, id); 02693 } 02694 02695 02696 int VL6180X::StartMeasurement(OperatingMode operating_mode, void (*fptr)(void), uint16_t low, uint16_t high) 02697 { 02698 int status, r_status, l_status; 02699 02700 switch(operating_mode) 02701 { 02702 case(range_single_shot_polling): 02703 r_status=VL6180x_RangeConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_NEW_SAMPLE_READY); 02704 l_status=VL6180x_AlsConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_DISABLED); 02705 DisableGPIOxOut(1); 02706 if((!r_status)&&(!l_status)) 02707 return RangeMeasPollSingleShot(); 02708 else 02709 return (r_status|l_status); 02710 02711 case(als_single_shot_polling): 02712 r_status=VL6180x_AlsConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_NEW_SAMPLE_READY); 02713 l_status=VL6180x_RangeConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_DISABLED); 02714 DisableGPIOxOut(1); 02715 if((!r_status)&&(!l_status)) 02716 return AlsMeasPollSingleShot(); 02717 else 02718 return (r_status|l_status); 02719 02720 case(range_continuous_polling): 02721 r_status=VL6180x_RangeConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_NEW_SAMPLE_READY); 02722 l_status=VL6180x_AlsConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_DISABLED); 02723 if((!r_status)&&(!l_status)) 02724 return RangeMeasPollContinuousMode(); 02725 else 02726 return (r_status|l_status); 02727 02728 case(als_continuous_polling): 02729 r_status=VL6180x_AlsConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_NEW_SAMPLE_READY); 02730 l_status=VL6180x_RangeConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_DISABLED); 02731 if((!r_status)&&(!l_status)) 02732 return AlsMeasPollContinuousMode(); 02733 else 02734 return (r_status|l_status); 02735 02736 case(range_continuous_interrupt): 02737 if (gpio1Int==NULL) return 1; 02738 r_status=VL6180x_RangeConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_NEW_SAMPLE_READY); 02739 l_status=VL6180x_AlsConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_DISABLED); 02740 if((!r_status)&&(!l_status)) 02741 return RangeMeasIntContinuousMode(fptr); 02742 else 02743 return (r_status|l_status); 02744 02745 case(als_continuous_interrupt): 02746 if (gpio1Int==NULL) return 1; 02747 l_status=VL6180x_AlsConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_NEW_SAMPLE_READY); 02748 r_status=VL6180x_RangeConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_DISABLED); 02749 if((!r_status)&&(!l_status)) 02750 return AlsMeasIntContinuousMode(fptr); 02751 else 02752 return (r_status|l_status); 02753 02754 case(interleaved_mode_interrupt): 02755 if (gpio1Int==NULL) return 1; 02756 l_status=VL6180x_AlsConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_NEW_SAMPLE_READY); 02757 r_status=VL6180x_RangeConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_DISABLED); 02758 if((!r_status)&&(!l_status)) 02759 return InterleavedMode(fptr); 02760 else 02761 return (r_status|l_status); 02762 02763 case(range_continuous_polling_low_threshold): 02764 r_status=VL6180x_RangeConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_LEVEL_LOW); 02765 l_status=VL6180x_AlsConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_DISABLED); 02766 if((!r_status)&&(!l_status)) 02767 { 02768 status=RangeSetLowThreshold(low); 02769 if(!status) 02770 return RangeMeasPollContinuousMode(); 02771 else 02772 return status; 02773 } 02774 else 02775 return (r_status|l_status); 02776 02777 case(range_continuous_polling_high_threshold): 02778 r_status=VL6180x_RangeConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_LEVEL_HIGH); 02779 l_status=VL6180x_AlsConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_DISABLED); 02780 if((!r_status)&&(!l_status)) 02781 { 02782 status=RangeSetHighThreshold(high); 02783 if(!status) 02784 return RangeMeasPollContinuousMode(); 02785 else 02786 return status; 02787 } 02788 else 02789 return (r_status|l_status); 02790 02791 case(range_continuous_polling_out_of_window): 02792 r_status=VL6180x_RangeConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_OUT_OF_WINDOW); 02793 l_status=VL6180x_AlsConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_DISABLED); 02794 if((!r_status)&&(!l_status)) 02795 { 02796 status=VL6180x_RangeSetThresholds(Device,low,high,1); 02797 if(!status) 02798 return RangeMeasPollContinuousMode(); 02799 else 02800 return status; 02801 } 02802 else 02803 return (r_status|l_status); 02804 02805 case(als_continuous_polling_low_threshold): 02806 l_status=VL6180x_AlsConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_LEVEL_LOW); 02807 r_status=VL6180x_RangeConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_DISABLED); 02808 if((!r_status)&&(!l_status)) 02809 { 02810 status=AlsSetLowThreshold(low); 02811 if(!status) 02812 return AlsMeasPollContinuousMode(); 02813 else 02814 return status; 02815 } 02816 else 02817 return (r_status|l_status); 02818 02819 case(als_continuous_polling_high_threshold): 02820 l_status=VL6180x_AlsConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_LEVEL_HIGH); 02821 r_status=VL6180x_RangeConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_DISABLED); 02822 if((!r_status)&&(!l_status)) 02823 { 02824 status=AlsSetHighThreshold(high); 02825 if(!status) 02826 return AlsMeasPollContinuousMode(); 02827 else 02828 return status; 02829 } 02830 else 02831 return (r_status|l_status); 02832 02833 case(als_continuous_polling_out_of_window): 02834 l_status=VL6180x_AlsConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_OUT_OF_WINDOW); 02835 r_status=VL6180x_RangeConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_DISABLED); 02836 if((!r_status)&&(!l_status)) 02837 { 02838 status=VL6180x_AlsSetThresholds(Device,low,high); 02839 if(!status) 02840 return AlsMeasPollContinuousMode(); 02841 else 02842 return status; 02843 } 02844 else 02845 return (r_status|l_status); 02846 02847 case(range_continuous_interrupt_low_threshold): 02848 if (gpio1Int==NULL) return 1; 02849 r_status=VL6180x_RangeConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_LEVEL_LOW); 02850 l_status=VL6180x_AlsConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_DISABLED); 02851 if((!r_status)&&(!l_status)) 02852 { 02853 status=RangeSetLowThreshold(low); 02854 if(!status) 02855 return RangeMeasIntContinuousMode(fptr); 02856 else 02857 return status; 02858 } 02859 else 02860 return (r_status|l_status); 02861 02862 case(range_continuous_interrupt_high_threshold): 02863 if (gpio1Int==NULL) return 1; 02864 r_status=VL6180x_RangeConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_LEVEL_HIGH); 02865 l_status=VL6180x_AlsConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_DISABLED); 02866 if((!r_status)&&(!l_status)) 02867 { 02868 status=RangeSetHighThreshold(high); 02869 if(!status) 02870 return RangeMeasIntContinuousMode(fptr); 02871 else 02872 return status; 02873 } 02874 else 02875 return (r_status|l_status); 02876 02877 case(range_continuous_interrupt_out_of_window): 02878 if (gpio1Int==NULL) return 1; 02879 r_status=VL6180x_RangeConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_OUT_OF_WINDOW); 02880 l_status=VL6180x_AlsConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_DISABLED); 02881 if((!r_status)&&(!l_status)) 02882 { 02883 status=VL6180x_RangeSetThresholds(Device,low,high,1); 02884 if(!status) 02885 return RangeMeasIntContinuousMode(fptr); 02886 else 02887 return status; 02888 } 02889 else 02890 return (r_status|l_status); 02891 02892 case(als_continuous_interrupt_low_threshold): 02893 if (gpio1Int==NULL) return 1; 02894 l_status=VL6180x_AlsConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_LEVEL_LOW); 02895 r_status=VL6180x_RangeConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_DISABLED); 02896 if((!r_status)&&(!l_status)) 02897 { 02898 status=AlsSetLowThreshold(low); 02899 if(!status) 02900 return AlsMeasIntContinuousMode(fptr); 02901 else 02902 return status; 02903 } 02904 else 02905 return (r_status|l_status); 02906 02907 case(als_continuous_interrupt_high_threshold): 02908 if (gpio1Int==NULL) return 1; 02909 l_status=VL6180x_AlsConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_LEVEL_HIGH); 02910 r_status=VL6180x_RangeConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_DISABLED); 02911 if((!r_status)&&(!l_status)) 02912 { 02913 status=AlsSetHighThreshold(high); 02914 if(!status) 02915 return AlsMeasIntContinuousMode(fptr); 02916 else 02917 return status; 02918 } 02919 else 02920 return (r_status|l_status); 02921 02922 case(als_continuous_interrupt_out_of_window): 02923 if (gpio1Int==NULL) return 1; 02924 l_status=VL6180x_AlsConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_OUT_OF_WINDOW); 02925 r_status=VL6180x_RangeConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_DISABLED); 02926 if((!r_status)&&(!l_status)) 02927 { 02928 status=VL6180x_AlsSetThresholds(Device,low,high); 02929 if(!status) 02930 return AlsMeasIntContinuousMode(fptr); 02931 else 02932 return status; 02933 } 02934 else 02935 return (r_status|l_status); 02936 02937 default: 02938 return INVALID_PARAMS; 02939 } 02940 } 02941 02942 02943 int VL6180X::GetRangeError(MeasureData_t *Data, VL6180x_RangeData_t RangeData) 02944 { 02945 Data->range_error=RangeData.errorStatus ; 02946 if(Data->range_error!=0) 02947 { 02948 VL6180x_ErrLog("Range error %d",Data->range_error); 02949 return RANGE_ERROR; 02950 } 02951 return NoError_; 02952 } 02953 02954 02955 int VL6180X::GetAlsError(MeasureData_t *Data, VL6180x_AlsData_t AlsData) 02956 { 02957 Data->als_error=AlsData.errorStatus; 02958 if(Data->als_error!=0) 02959 { 02960 VL6180x_ErrLog("Light error %d",Data->light_error); 02961 return API_ERROR; 02962 } 02963 return NoError_; 02964 } 02965 02966 02967 int VL6180X::RangeMeasPollSingleShot() 02968 { 02969 int status; 02970 02971 status=VL6180x_RangeClearInterrupt(Device); 02972 if(status) 02973 { 02974 VL6180x_ErrLog("VL6180x_RangeClearInterrupt fail"); 02975 return status; 02976 } 02977 status=VL6180x_ClearErrorInterrupt(Device); 02978 if(status) 02979 { 02980 VL6180x_ErrLog("VL6180x_ClearErrorInterrupt fail"); 02981 return status; 02982 } 02983 return RangeStartSingleShot(); 02984 } 02985 02986 02987 int VL6180X::AlsMeasPollSingleShot() 02988 { 02989 int status; 02990 02991 status=VL6180x_AlsClearInterrupt(Device); 02992 if(status) 02993 { 02994 VL6180x_ErrLog("VL6180x_AlsClearInterrupt fail"); 02995 return status; 02996 } 02997 status=VL6180x_ClearErrorInterrupt(Device); 02998 if(status) 02999 { 03000 VL6180x_ErrLog("VL6180x_ClearErrorInterrupt fail"); 03001 return status; 03002 } 03003 return AlsStartSingleShot(); 03004 } 03005 03006 03007 int VL6180X::RangeMeasPollContinuousMode() 03008 { 03009 int status; 03010 03011 status=VL6180x_RangeClearInterrupt(Device); 03012 if(status) 03013 { 03014 VL6180x_ErrLog("VL6180x_RangeClearInterrupt fail"); 03015 return status; 03016 } 03017 status=VL6180x_ClearErrorInterrupt(Device); 03018 if(status) 03019 { 03020 VL6180x_ErrLog("VL6180x_ClearErrorInterrupt fail"); 03021 return status; 03022 } 03023 return RangeStartContinuousMode(); 03024 } 03025 03026 03027 int VL6180X::AlsMeasPollContinuousMode() 03028 { 03029 int status; 03030 03031 status=VL6180x_AlsClearInterrupt(Device); 03032 if(status) 03033 { 03034 VL6180x_ErrLog("VL6180x_AlsClearInterrupt fail"); 03035 return status; 03036 } 03037 status=VL6180x_ClearErrorInterrupt(Device); 03038 if(status) 03039 { 03040 VL6180x_ErrLog("VL6180x_ClearErrorInterrupt fail"); 03041 return status; 03042 } 03043 return AlsStartContinuousMode(); 03044 } 03045 03046 03047 int VL6180X::AlsGetMeasurementIfReady(VL6180xDev_t dev, VL6180x_AlsData_t *pAlsData) 03048 { 03049 int status; 03050 uint8_t IntStatus; 03051 03052 status=VL6180x_AlsGetInterruptStatus(dev, &IntStatus); 03053 if(!status) 03054 { 03055 if(IntStatus==RES_INT_STAT_GPIO_NEW_SAMPLE_READY) 03056 { 03057 status = VL6180x_AlsGetMeasurement(dev, pAlsData); 03058 if(!status) 03059 { 03060 status=VL6180x_AlsClearInterrupt(Device); 03061 if(status) 03062 VL6180x_ErrLog("VL6180x_AlsClearInterrupt fail"); 03063 } 03064 } 03065 else 03066 status=NOT_READY; 03067 } 03068 else 03069 VL6180x_ErrLog("Failed to get interrupt status"); 03070 return status; 03071 } 03072 03073 03074 int VL6180X::RangeMeasIntContinuousMode(void (*fptr)(void)) 03075 { 03076 int status, ClrStatus; 03077 03078 EnableInterruptMeasureDetectionIRQ(); 03079 AttachInterruptMeasureDetectionIRQ(fptr); 03080 status=SetupGPIO1(GPIOx_SELECT_GPIO_INTERRUPT_OUTPUT, 1); 03081 ClrStatus=VL6180x_ClearAllInterrupt(Device); 03082 if(ClrStatus) 03083 VL6180x_ErrLog("VL6180x_ClearErrorInterrupt fail"); 03084 if(!status) 03085 status=RangeStartContinuousMode(); 03086 return status; 03087 } 03088 03089 03090 int VL6180X::AlsMeasIntContinuousMode(void (*fptr)(void)) 03091 { 03092 int status, ClrStatus; 03093 03094 EnableInterruptMeasureDetectionIRQ(); 03095 AttachInterruptMeasureDetectionIRQ(fptr); 03096 status=SetupGPIO1(GPIOx_SELECT_GPIO_INTERRUPT_OUTPUT, 1); 03097 ClrStatus=VL6180x_ClearAllInterrupt(Device); 03098 if(ClrStatus) 03099 VL6180x_ErrLog("VL6180x_ClearErrorInterrupt fail"); 03100 if(!status) 03101 status=AlsStartContinuousMode(); 03102 return status; 03103 } 03104 03105 03106 int VL6180X::StartInterleavedMode() 03107 { 03108 int status; 03109 uint16_t integration_period, intermeasurement_period_ms; 03110 uint8_t max_convergence_time; 03111 uint8_t buf; 03112 03113 status=VL6180x_WrByte(Device, 0x2A3, 1); 03114 if(status) 03115 { 03116 VL6180x_ErrLog("Failed to write INTERLEAVED_MODE_ENABLE!\n\r"); 03117 return status; 03118 } 03119 status=VL6180x_RdByte(Device, SYSRANGE_MAX_CONVERGENCE_TIME, &max_convergence_time); 03120 if(status) 03121 { 03122 VL6180x_ErrLog("Failed to read SYSRANGE_MAX_CONVERGENCE_TIME!\n\r"); 03123 return status; 03124 } 03125 status=VL6180x_RdWord(Device, SYSALS_INTEGRATION_PERIOD, &integration_period); 03126 if(status) 03127 { 03128 VL6180x_ErrLog("Failed to read SYSALS_INTEGRATION_PERIOD!\n\r"); 03129 return status; 03130 } 03131 max_convergence_time&=0x3F; 03132 integration_period&=0x01FF; 03133 intermeasurement_period_ms=((max_convergence_time+5)+(integration_period*1.1)); 03134 intermeasurement_period_ms=(intermeasurement_period_ms/0.9)+10; 03135 intermeasurement_period_ms=200; 03136 status=VL6180x_AlsSetInterMeasurementPeriod(Device, intermeasurement_period_ms); 03137 VL6180x_RdByte(Device, 0x03E, &buf); 03138 if(status) 03139 { 03140 VL6180x_ErrLog("Failed to write SYSALS_INTERMEASUREMENT_PERIOD!\n\r"); 03141 return status; 03142 } 03143 return AlsStartContinuousMode(); 03144 } 03145 03146 03147 int VL6180X::InterleavedMode(void (*fptr)(void)) 03148 { 03149 int status, ClrStatus; 03150 03151 EnableInterruptMeasureDetectionIRQ(); 03152 AttachInterruptMeasureDetectionIRQ(fptr); 03153 status=SetupGPIO1(GPIOx_SELECT_GPIO_INTERRUPT_OUTPUT, 1); 03154 ClrStatus=VL6180x_ClearAllInterrupt(Device); 03155 if(ClrStatus) 03156 VL6180x_ErrLog("VL6180x_ClearErrorInterrupt fail"); 03157 if(!status) 03158 status=StartInterleavedMode(); 03159 return status; 03160 } 03161 03162 03163 int VL6180X::HandleIRQ(OperatingMode operating_mode, MeasureData_t *Data) 03164 { 03165 int status; 03166 03167 EnableInterruptMeasureDetectionIRQ(); 03168 status=GetMeasurement(operating_mode, Data); 03169 return status; 03170 } 03171 03172 03173 int VL6180X::RangeSetLowThreshold(uint16_t threshold) 03174 { 03175 int status; 03176 uint16_t low, high; 03177 03178 status=VL6180x_RangeGetThresholds(Device, &low, &high); 03179 if(!status) 03180 status=VL6180x_RangeSetThresholds(Device, threshold, high, 1); 03181 return status; 03182 } 03183 03184 03185 int VL6180X::RangeSetHighThreshold(uint16_t threshold) 03186 { 03187 int status; 03188 uint16_t low, high; 03189 03190 status=VL6180x_RangeGetThresholds(Device, &low, &high); 03191 if(!status) 03192 status=VL6180x_RangeSetThresholds(Device, low, threshold, 1); 03193 return status; 03194 } 03195 03196 03197 int VL6180X::AlsSetLowThreshold(uint16_t threshold) 03198 { 03199 int status; 03200 lux_t low, high; 03201 03202 status=AlsGetThresholds(Device, &low, &high); 03203 if(!status) 03204 status=VL6180x_AlsSetThresholds(Device, threshold, high); 03205 return status; 03206 } 03207 03208 03209 int VL6180X::AlsSetHighThreshold(uint16_t threshold) 03210 { 03211 int status; 03212 lux_t low, high; 03213 03214 status=AlsGetThresholds(Device, &low, &high); 03215 if(!status) 03216 status=VL6180x_AlsSetThresholds(Device, low, threshold); 03217 return status; 03218 } 03219 03220 03221 int VL6180X::AlsGetThresholds(VL6180xDev_t dev, lux_t *low, lux_t *high) 03222 { 03223 int status; 03224 uint16_t RawAlsLow, RawAlsHigh; 03225 uint32_t luxLowValue, luxHighValue, IntPeriod, AlsAnGain, GainFix, AlsScaler ; 03226 const uint32_t LuxResxIntIme =(uint32_t)(0.56f* DEF_INT_PEFRIOD *(1<<LUXRES_FIX_PREC)); 03227 03228 status=VL6180x_RdWord(dev, SYSALS_THRESH_LOW, &RawAlsLow); 03229 if(status) 03230 { 03231 VL6180x_ErrLog("rd SYSALS_THRESH_LOW fail"); 03232 return status; 03233 } 03234 status=VL6180x_RdWord(dev, SYSALS_THRESH_HIGH, &RawAlsHigh); 03235 if(status) 03236 { 03237 VL6180x_ErrLog("rd SYSALS_THRESH_HIGH fail"); 03238 return status; 03239 } 03240 AlsAnGain=VL6180xDevDataGet(dev, AlsGainCode ); 03241 IntPeriod=VL6180xDevDataGet(dev, IntegrationPeriod ); 03242 AlsScaler=VL6180xDevDataGet(dev, AlsScaler); 03243 GainFix=AlsGainLookUp[AlsAnGain]; 03244 IntPeriod++; 03245 luxLowValue=(uint32_t)RawAlsLow*LuxResxIntIme; 03246 luxLowValue=luxLowValue/IntPeriod; 03247 luxLowValue=luxLowValue/(AlsScaler*GainFix); 03248 luxHighValue=(uint32_t)RawAlsHigh*LuxResxIntIme; 03249 luxHighValue=luxHighValue/IntPeriod; 03250 luxHighValue=luxHighValue/(AlsScaler*GainFix); 03251 *low=luxLowValue; 03252 *high=luxHighValue; 03253 return status; 03254 } 03255 03256 03257 int VL6180X::GetMeasurement(OperatingMode operating_mode, MeasureData_t *Data) 03258 { 03259 switch(operating_mode) 03260 { 03261 case(range_single_shot_polling): 03262 case(range_continuous_polling): 03263 case(range_continuous_interrupt): 03264 case(range_continuous_polling_low_threshold): 03265 case(range_continuous_polling_high_threshold): 03266 case(range_continuous_polling_out_of_window): 03267 case(range_continuous_interrupt_low_threshold): 03268 case(range_continuous_interrupt_high_threshold): 03269 case(range_continuous_interrupt_out_of_window): 03270 return GetRangeMeas(operating_mode, Data); 03271 03272 case(als_single_shot_polling): 03273 case(als_continuous_polling): 03274 case(als_continuous_interrupt): 03275 case(als_continuous_polling_low_threshold): 03276 case(als_continuous_polling_high_threshold): 03277 case(als_continuous_polling_out_of_window): 03278 case(als_continuous_interrupt_low_threshold): 03279 case(als_continuous_interrupt_high_threshold): 03280 case(als_continuous_interrupt_out_of_window): 03281 return GetAlsMeas(operating_mode, Data); 03282 03283 case(interleaved_mode_interrupt): 03284 return GetRangeAlsMeas(Data); 03285 03286 default: 03287 return INVALID_PARAMS; 03288 } 03289 } 03290 03291 03292 int VL6180X::GetRangeMeas(OperatingMode operating_mode, MeasureData_t *Data) 03293 { 03294 VL6180x_RangeData_t RangeData; 03295 int status, ClrStatus; 03296 IntrStatus_t IntStatus; 03297 03298 status=VL6180x_RangeGetInterruptStatus(Device, &IntStatus.val ); 03299 if(!status) 03300 { 03301 Data->int_error=IntStatus.status .Error ; 03302 if(IntStatus.status .Error !=0) 03303 { 03304 VL6180x_ErrLog("GPIO int Error report %d",(int)IntStatus.val ); 03305 status=RANGE_ERROR; 03306 } 03307 } 03308 else 03309 { 03310 VL6180x_ErrLog("Failed to read RESULT_INTERRUPT_STATUS_GPIO"); 03311 } 03312 ClrStatus=VL6180x_RangeClearInterrupt(Device); 03313 if(ClrStatus) 03314 { 03315 VL6180x_ErrLog("VL6180x_RangeClearInterrupt fail"); 03316 } 03317 ClrStatus=VL6180x_ClearErrorInterrupt(Device); 03318 if(ClrStatus) 03319 { 03320 VL6180x_ErrLog("VL6180x_ClearErrorInterrupt fail"); 03321 } 03322 if(status) 03323 return status; 03324 if((operating_mode==range_single_shot_polling)||(operating_mode==range_continuous_polling)||(operating_mode==range_continuous_interrupt)) 03325 { 03326 if(IntStatus.status .Range ==RES_INT_STAT_GPIO_NEW_SAMPLE_READY) 03327 status=VL6180x_RangeGetMeasurement(Device, &RangeData); 03328 else 03329 return NOT_READY; 03330 } 03331 else if((operating_mode==range_continuous_polling_low_threshold)||(operating_mode==range_continuous_interrupt_low_threshold)) 03332 { 03333 if(IntStatus.status .Range ==RES_INT_STAT_GPIO_LOW_LEVEL_THRESHOLD) 03334 status=VL6180x_RangeGetMeasurement(Device, &RangeData); 03335 else 03336 return NOT_READY; 03337 } 03338 else if((operating_mode==range_continuous_polling_high_threshold)||(operating_mode==range_continuous_interrupt_high_threshold)) 03339 { 03340 if(IntStatus.status .Range ==RES_INT_STAT_GPIO_HIGH_LEVEL_THRESHOLD) 03341 status=VL6180x_RangeGetMeasurement(Device, &RangeData); 03342 else 03343 return NOT_READY; 03344 } 03345 else if((operating_mode==range_continuous_polling_out_of_window)||(operating_mode==range_continuous_interrupt_out_of_window)) 03346 { 03347 if(IntStatus.status .Range ==RES_INT_STAT_GPIO_OUT_OF_WINDOW) 03348 status=VL6180x_RangeGetMeasurement(Device, &RangeData); 03349 else 03350 return NOT_READY; 03351 } 03352 if(!status) 03353 { 03354 status=GetRangeError(Data, RangeData); 03355 if(!status) 03356 Data->range_mm=RangeData.range_mm ; 03357 else 03358 Data->range_mm=0xFFFFFFFF; 03359 } 03360 return status; 03361 } 03362 03363 03364 int VL6180X::GetAlsMeas(OperatingMode operating_mode, MeasureData_t *Data) 03365 { 03366 VL6180x_AlsData_t AlsData; 03367 int status, ClrStatus; 03368 uint8_t IntStatus; 03369 03370 status=VL6180x_AlsGetInterruptStatus(Device, &IntStatus); 03371 if(status) 03372 { 03373 VL6180x_ErrLog("Failed to read RESULT_INTERRUPT_STATUS_GPIO"); 03374 } 03375 ClrStatus=VL6180x_AlsClearInterrupt(Device); 03376 if(ClrStatus) 03377 { 03378 VL6180x_ErrLog("VL6180x_AlsClearInterrupt fail"); 03379 } 03380 ClrStatus=VL6180x_ClearErrorInterrupt(Device); 03381 if(ClrStatus) 03382 { 03383 VL6180x_ErrLog("VL6180x_ClearErrorInterrupt fail"); 03384 } 03385 if(status) 03386 return status; 03387 if((operating_mode==als_single_shot_polling)||(operating_mode==als_continuous_polling)||(operating_mode==als_continuous_interrupt)) 03388 { 03389 if(IntStatus==RES_INT_STAT_GPIO_NEW_SAMPLE_READY) 03390 status=VL6180x_AlsGetMeasurement(Device, &AlsData); 03391 else 03392 return NOT_READY; 03393 } 03394 else if((operating_mode==als_continuous_polling_low_threshold)||(operating_mode==als_continuous_interrupt_low_threshold)) 03395 { 03396 if(IntStatus==RES_INT_STAT_GPIO_LOW_LEVEL_THRESHOLD) 03397 status=VL6180x_AlsGetMeasurement(Device, &AlsData); 03398 else 03399 return NOT_READY; 03400 } 03401 else if((operating_mode==als_continuous_polling_high_threshold)||(operating_mode==als_continuous_interrupt_high_threshold)) 03402 { 03403 if(IntStatus==RES_INT_STAT_GPIO_HIGH_LEVEL_THRESHOLD) 03404 status=VL6180x_AlsGetMeasurement(Device, &AlsData); 03405 else 03406 return NOT_READY; 03407 } 03408 else if((operating_mode==als_continuous_polling_out_of_window)||(operating_mode==als_continuous_interrupt_out_of_window)) 03409 { 03410 if(IntStatus==RES_INT_STAT_GPIO_OUT_OF_WINDOW) 03411 status=VL6180x_AlsGetMeasurement(Device, &AlsData); 03412 else 03413 return NOT_READY; 03414 } 03415 if(!status) 03416 { 03417 status=GetAlsError(Data, AlsData); 03418 if(!status) 03419 Data->lux=AlsData.lux; 03420 else 03421 Data->lux=0xFFFFFFFF; 03422 } 03423 return status; 03424 } 03425 03426 03427 int VL6180X::GetRangeAlsMeas(MeasureData_t *Data) 03428 { 03429 int status, ClrStatus, r_status, l_status; 03430 IntrStatus_t IntStatus; 03431 VL6180x_RangeData_t RangeData; 03432 VL6180x_AlsData_t AlsData; 03433 03434 status=VL6180x_RdByte(Device, RESULT_INTERRUPT_STATUS_GPIO, &IntStatus.val ); 03435 if(!status) 03436 { 03437 Data->int_error=IntStatus.status .Error ; 03438 if(IntStatus.status .Error !=0) 03439 { 03440 VL6180x_ErrLog("GPIO int Error report %d",(int)IntStatus.val ); 03441 status=RANGE_ERROR; 03442 } 03443 } 03444 else 03445 { 03446 VL6180x_ErrLog("Failed to read RESULT_INTERRUPT_STATUS_GPIO"); 03447 } 03448 ClrStatus=VL6180x_ClearAllInterrupt(Device); 03449 if(ClrStatus) 03450 VL6180x_ErrLog("VL6180x_ClearAllInterrupt fail"); 03451 if(status) 03452 return status; 03453 03454 if(IntStatus.status .Als ==RES_INT_STAT_GPIO_NEW_SAMPLE_READY) 03455 { 03456 r_status=VL6180x_RangeGetMeasurement(Device, &RangeData); 03457 l_status=VL6180x_AlsGetMeasurement(Device, &AlsData); 03458 if((!r_status)&&(!l_status)) 03459 { 03460 r_status=GetRangeError(Data, RangeData); 03461 l_status=GetAlsError(Data, AlsData); 03462 if(!r_status) 03463 Data->range_mm=RangeData.range_mm ; 03464 else 03465 Data->range_mm=0xFFFFFFFF; 03466 if(!l_status) 03467 Data->lux=AlsData.lux; 03468 else 03469 Data->lux=0xFFFFFFFF; 03470 status=r_status|l_status; 03471 } 03472 else 03473 { 03474 status=r_status|l_status; 03475 } 03476 } 03477 else 03478 return NOT_READY; 03479 return status; 03480 } 03481 03482 03483 int VL6180X::StopMeasurement(OperatingMode operating_mode) 03484 { 03485 int status; 03486 03487 switch(operating_mode) 03488 { 03489 case(range_single_shot_polling): 03490 case(range_continuous_polling): 03491 case(range_continuous_interrupt): 03492 case(range_continuous_polling_low_threshold): 03493 case(range_continuous_polling_high_threshold): 03494 case(range_continuous_polling_out_of_window): 03495 case(range_continuous_interrupt_low_threshold): 03496 case(range_continuous_interrupt_high_threshold): 03497 case(range_continuous_interrupt_out_of_window): 03498 return StopRangeMeasurement(operating_mode); 03499 03500 case(als_single_shot_polling): 03501 case(als_continuous_polling): 03502 case(als_continuous_interrupt): 03503 case(als_continuous_polling_low_threshold): 03504 case(als_continuous_polling_high_threshold): 03505 case(als_continuous_polling_out_of_window): 03506 case(als_continuous_interrupt_low_threshold): 03507 case(als_continuous_interrupt_high_threshold): 03508 case(als_continuous_interrupt_out_of_window): 03509 return StopAlsMeasurement(operating_mode); 03510 03511 case(interleaved_mode_interrupt): 03512 status=StopRangeMeasurement(range_continuous_interrupt); 03513 if(!status) 03514 return StopAlsMeasurement(als_continuous_interrupt); 03515 else return status; 03516 03517 default: 03518 return INVALID_PARAMS; 03519 } 03520 } 03521 03522 03523 int VL6180X::IsPresent() 03524 { 03525 int status; uint8_t id; 03526 03527 status=ReadID(&id); 03528 if(status) 03529 VL6180x_ErrLog("Failed to read ID device. Device not present!\n\r"); 03530 return status; 03531 } 03532 03533 03534 int VL6180X::StopRangeMeasurement(OperatingMode operating_mode) 03535 { 03536 int status; 03537 03538 if(operating_mode==range_single_shot_polling) 03539 status=VL6180x_RangeSetSystemMode(Device, MODE_SINGLESHOT); 03540 else 03541 status=VL6180x_RangeSetSystemMode(Device, MODE_START_STOP|MODE_SINGLESHOT); 03542 if(status) 03543 return status; 03544 status=VL6180x_RangeConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_DISABLED); 03545 if(status) 03546 { 03547 VL6180x_ErrLog("VL6180x_RangeConfigInterrupt fail"\n\r); 03548 return status; 03549 } 03550 status=VL6180x_RangeClearInterrupt(Device); 03551 if(status) 03552 { 03553 VL6180x_ErrLog("VL6180x_RangeClearInterrupt fail"); 03554 return status; 03555 } 03556 status=VL6180x_ClearErrorInterrupt(Device); 03557 if(status) 03558 { 03559 VL6180x_ErrLog("VL6180x_ClearErrorInterrupt fail"); 03560 return status; 03561 } 03562 status=VL6180x_RangeSetRawThresholds(Device, 10, 200); 03563 if(status) 03564 VL6180x_ErrLog("VL6180x_RangeSetThresholds fail"); 03565 return status; 03566 } 03567 03568 03569 int VL6180X::StopAlsMeasurement(OperatingMode operating_mode) 03570 { 03571 int status; 03572 03573 if(operating_mode==als_single_shot_polling) 03574 status=VL6180x_AlsSetSystemMode(Device, MODE_SINGLESHOT); 03575 else 03576 status=VL6180x_AlsSetSystemMode(Device, MODE_START_STOP|MODE_SINGLESHOT); 03577 if(status) 03578 return status; 03579 status=VL6180x_AlsConfigInterrupt(Device, CONFIG_GPIO_INTERRUPT_DISABLED); 03580 if(status) 03581 { 03582 VL6180x_ErrLog("VL6180x_AlsConfigInterrupt fail"\n\r); 03583 return status; 03584 } 03585 status=VL6180x_AlsClearInterrupt(Device); 03586 if(status) 03587 { 03588 VL6180x_ErrLog("VL6180x_AlsClearInterrupt fail"); 03589 return status; 03590 } 03591 status=VL6180x_ClearErrorInterrupt(Device); 03592 if(status) 03593 { 03594 VL6180x_ErrLog("VL6180x_ClearErrorInterrupt fail"); 03595 return status; 03596 } 03597 status=VL6180x_AlsSetThresholds(Device, 0x0, 1800); 03598 if(status) 03599 VL6180x_ErrLog("VL6180x_AlsSetThresholds fail"); 03600 return status; 03601 } 03602 03603 03604 03605 03606 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Wed Jul 13 2022 22:31:06 by
1.7.2