Librairie adaptée au laboratoire 2

Dependencies:   ST_INTERFACES X_NUCLEO_COMMON

Fork of X_NUCLEO_6180XA1 by ST

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers VL6180X.cpp Source File

VL6180X.cpp

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