Kenji Arai / 6180XA1_simple

Dependents:   Check_VL6180XA1_ToF

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 //------- Feburary 1st, 2018 by JH1PJL / K.Arai --------------------------------
00039 // Change X_NUCLEO_6180XA1 library to 6180XA1_simplest library
00040 //    modified -> all related files
00041 //------------------------------------------------------------------------------
00042 
00043 /* Includes */
00044 #include "VL6180X.h"
00045 
00046 #define VL6180X_DEV_DATA_ATTR
00047 #define ROMABLE_DATA
00048 
00049 //-------- NOT USE FOLLOING FUNCTIONS -------------
00050 //void OnErrLog(void);
00051 #define LOG_FUNCTION_START(...) (void)0
00052 #define LOG_FUNCTION_END(...) (void)0
00053 #define LOG_FUNCTION_END_FMT(...) (void)0
00054 #define VL6180X_ErrLog(... ) //OnErrLog() //(void)0
00055 
00056 #define VL6180XDevDataGet(dev, field) (dev->Data.field)
00057 #define VL6180XDevDataSet(dev, field, data) (dev->Data.field)=(data)
00058 
00059 /** @defgroup api_init Init functions
00060  *  @brief    API init functions
00061  *  @ingroup api_hl
00062  *  @{
00063  */
00064 
00065 
00066 /****************** define for i2c configuration *******************************/
00067 #define TEMP_BUF_SIZE   32
00068 
00069 /******************************************************************************/
00070 /******************************* file api.c ***********************************/
00071 
00072 #define VL6180X_9to7Conv(x) (x)
00073 
00074 /* TODO when set all "cached" value with "default init" are updated after init from register read back */
00075 #define REFRESH_CACHED_DATA_AFTER_INIT  1
00076 
00077 /** default value ECE factor Molecular */
00078 #define DEF_ECE_FACTOR_M    85
00079 /** default value ECE factor Denominator */
00080 #define DEF_ECE_FACTOR_D    100
00081 /** default value ALS integration time */
00082 #define DEF_INT_PEFRIOD     100
00083 /** default value ALS gain */
00084 #define DEF_ALS_GAIN        1
00085 /** default value ALS scaler */
00086 #define DEF_ALS_SCALER      1
00087 /** default value for DMAX Enbale */
00088 #define DEF_DMAX_ENABLE     1
00089 /** default ambient tuning factor %x1000 */
00090 #define DEF_AMBIENT_TUNING  80
00091 
00092 #define LUXRES_FIX_PREC 8
00093 #define GAIN_FIX_PREC    8  /* ! if not sme as LUX_PREC then :( adjust GetLux */
00094 #define AN_GAIN_MULT    (1<<GAIN_FIX_PREC)
00095 
00096 /**
00097  * Als Code gain to fix point gain lookup
00098  */
00099 static const uint16_t AlsGainLookUp[8]    ROMABLE_DATA = {
00100     (uint16_t)(20.0f * AN_GAIN_MULT),
00101     (uint16_t)(10.0f * AN_GAIN_MULT),
00102     (uint16_t)(5.0f  * AN_GAIN_MULT),
00103     (uint16_t)(2.5f  * AN_GAIN_MULT),
00104     (uint16_t)(1.67f * AN_GAIN_MULT),
00105     (uint16_t)(1.25f * AN_GAIN_MULT),
00106     (uint16_t)(1.0f  * AN_GAIN_MULT),
00107     (uint16_t)(40.0f * AN_GAIN_MULT),
00108 };
00109 
00110 #if VL6180X_UPSCALE_SUPPORT == 1
00111 #define _GetUpscale(dev, ... )  1
00112 #define _SetUpscale(...) -1
00113 #define DEF_UPSCALE 1
00114 #elif VL6180X_UPSCALE_SUPPORT == 2
00115 #define _GetUpscale(dev, ... )  2
00116 #define _SetUpscale(...)
00117 #define DEF_UPSCALE 2
00118 #elif  VL6180X_UPSCALE_SUPPORT == 3
00119 #define _GetUpscale(dev, ... )  3
00120 #define _SetUpscale(...)
00121 #define DEF_UPSCALE 3
00122 #else
00123 #define DEF_UPSCALE (-(VL6180X_UPSCALE_SUPPORT))
00124 #define _GetUpscale(dev, ... ) VL6180XDevDataGet(dev, UpscaleFactor)
00125 #define _SetUpscale(dev, Scaling ) VL6180XDevDataSet(dev, UpscaleFactor, Scaling)
00126 #endif
00127 
00128 #define Fix7_2_KCPs(x) ((((uint32_t)(x))*1000)>>7)
00129 
00130 int VL6180X::VL6180X_WaitDeviceBooted(VL6180XDev_t dev)
00131 {
00132     uint8_t FreshOutReset=0;
00133     int status;
00134     LOG_FUNCTION_START("");
00135     do {
00136         status = VL6180X_RdByte(dev,SYSTEM_FRESH_OUT_OF_RESET, &FreshOutReset);
00137     } while( FreshOutReset!=1 && status==0);
00138     LOG_FUNCTION_END(status);
00139     return status;
00140 }
00141 
00142 int VL6180X::VL6180X_InitData(VL6180XDev_t dev)
00143 {
00144     int status, dmax_status ;
00145     int8_t offset;
00146     uint8_t FreshOutReset;
00147     uint32_t CalValue;
00148     uint16_t u16;
00149     uint32_t XTalkCompRate_KCps;
00150 
00151     LOG_FUNCTION_START("");
00152 
00153     VL6180XDevDataSet(dev, EceFactorM , DEF_ECE_FACTOR_M);
00154     VL6180XDevDataSet(dev, EceFactorD , DEF_ECE_FACTOR_D);
00155 
00156 #ifdef VL6180X_HAVE_UPSCALE_DATA
00157     VL6180XDevDataSet(dev, UpscaleFactor ,  DEF_UPSCALE);
00158 #endif
00159 
00160 #ifdef VL6180X_HAVE_ALS_DATA
00161     VL6180XDevDataSet(dev, IntegrationPeriod, DEF_INT_PEFRIOD);
00162     VL6180XDevDataSet(dev, AlsGainCode, DEF_ALS_GAIN);
00163     VL6180XDevDataSet(dev, AlsScaler, DEF_ALS_SCALER);
00164 #endif
00165     do {
00166 
00167         /* backup offset initial value from nvm these must be done prior any over call that use offset */
00168         status = VL6180X::VL6180X_RdByte(dev,SYSRANGE_PART_TO_PART_RANGE_OFFSET, (uint8_t*)&offset);
00169         if( status ) {
00170             VL6180X_ErrLog("SYSRANGE_PART_TO_PART_RANGE_OFFSET rd fail");
00171             break;
00172         }
00173         VL6180XDevDataSet(dev, Part2PartOffsetNVM, offset);
00174 
00175         status=VL6180X_RdDWord( dev, SYSRANGE_RANGE_IGNORE_THRESHOLD, &CalValue);
00176         if( status ) {
00177             VL6180X_ErrLog("Part2PartAmbNVM rd fail");
00178             break;
00179         }
00180         if( (CalValue&0xFFFF0000) == 0 ) {
00181             CalValue=0x00CE03F8;
00182         }
00183         VL6180XDevDataSet(dev, Part2PartAmbNVM, CalValue);
00184 
00185         status = VL6180X_RdWord(dev, SYSRANGE_CROSSTALK_COMPENSATION_RATE ,&u16);
00186         if( status) {
00187             VL6180X_ErrLog("SYSRANGE_CROSSTALK_COMPENSATION_RATE rd fail ");
00188             break;
00189         }
00190         XTalkCompRate_KCps = Fix7_2_KCPs(u16);
00191         VL6180XDevDataSet(dev, XTalkCompRate_KCps , XTalkCompRate_KCps );
00192         /* Read or wait for fresh out of reset  */
00193         status = VL6180X_RdByte(dev,SYSTEM_FRESH_OUT_OF_RESET, &FreshOutReset);
00194         if( status )  {
00195             VL6180X_ErrLog("SYSTEM_FRESH_OUT_OF_RESET rd fail");
00196             break;
00197         }
00198         if( FreshOutReset!= 1 || dmax_status )
00199             status = CALIBRATION_WARNING;
00200 
00201     } while(0);
00202 
00203     LOG_FUNCTION_END(status);
00204     return status;
00205 }
00206 
00207 int VL6180X::VL6180X_StaticInit(VL6180XDev_t dev)
00208 {
00209     int status=0, init_status;
00210     LOG_FUNCTION_START("");
00211 
00212     if( _GetUpscale(dev) == 1 )
00213         init_status=VL6180X_RangeStaticInit(dev);
00214 
00215     if( init_status <0 ) {
00216         VL6180X_ErrLog("StaticInit fail");
00217         goto error;
00218     } else if(init_status > 0) {
00219         VL6180X_ErrLog("StaticInit warning");
00220     }
00221 
00222 #if REFRESH_CACHED_DATA_AFTER_INIT
00223     /* update cached value after tuning applied */
00224     do {
00225 #ifdef  VL6180X_HAVE_ALS_DATA
00226         uint8_t data;
00227         status=  VL6180X_RdByte(dev, FW_ALS_RESULT_SCALER, &data);
00228         if( status ) break;
00229         VL6180XDevDataSet(dev, AlsScaler, data);
00230 
00231         status=  VL6180X_RdByte(dev, SYSALS_ANALOGUE_GAIN, &data);
00232         if( status ) break;
00233         VL6180X_AlsSetAnalogueGain(dev, data);
00234 #endif
00235     } while(0);
00236 #endif /* REFRESH_CACHED_DATA_AFTER_INIT */
00237     if( status < 0 ) {
00238         VL6180X_ErrLog("StaticInit fail");
00239     }
00240     if( !status && init_status) {
00241         status = init_status;
00242     }
00243 error:
00244     LOG_FUNCTION_END(status);
00245     return status;
00246 }
00247 #if 1
00248 int VL6180X::VL6180X_SetGroupParamHold(VL6180XDev_t dev, int Hold)
00249 {
00250     int status;
00251     uint8_t value;
00252 
00253     LOG_FUNCTION_START("%d", Hold);
00254     if( Hold )
00255         value = 1;
00256     else
00257         value = 0;
00258     status = VL6180X_WrByte(dev, SYSTEM_GROUPED_PARAMETER_HOLD, value);
00259 
00260     LOG_FUNCTION_END(status);
00261     return status;
00262 
00263 }
00264 #endif
00265 int VL6180X::VL6180X_Prepare(VL6180XDev_t dev)
00266 {
00267     int status;
00268     LOG_FUNCTION_START("");
00269 
00270     do {
00271         status=VL6180X_StaticInit(dev);
00272         if( status<0) break;
00273 
00274         /* set default threshold */
00275         status=VL6180X_RangeSetRawThresholds(dev, 10, 200);
00276         if( status ) {
00277             VL6180X_ErrLog("VL6180X_RangeSetRawThresholds fail");
00278             break;
00279         }
00280 #if VL6180X_ALS_SUPPORT
00281         status =VL6180X_AlsSetIntegrationPeriod(dev, 100);
00282         if( status ) break;
00283         status = VL6180X_AlsSetInterMeasurementPeriod(dev,  200);
00284         if( status ) break;
00285         status = VL6180X_AlsSetAnalogueGain(dev,  0);
00286         if( status ) break;
00287         status = VL6180X_AlsSetThresholds(dev, 0, 0xFFFF);
00288         if( status ) break;
00289 #endif
00290     } while(0);
00291     LOG_FUNCTION_END(status);
00292 
00293     return status;
00294 }
00295 
00296 #if VL6180X_ALS_SUPPORT
00297 int VL6180X::VL6180X_AlsGetLux(VL6180XDev_t dev, lux_t *pLux)
00298 {
00299     int status;
00300     uint16_t RawAls;
00301     uint32_t luxValue = 0;
00302     uint32_t IntPeriod;
00303     uint32_t AlsAnGain;
00304     uint32_t GainFix;
00305     uint32_t AlsScaler;
00306 
00307 #if LUXRES_FIX_PREC !=  GAIN_FIX_PREC
00308 #error "LUXRES_FIX_PREC != GAIN_FIX_PREC  review these code to be correct"
00309 #endif
00310     const uint32_t LuxResxIntIme =(uint32_t)(0.56f* DEF_INT_PEFRIOD *(1<<LUXRES_FIX_PREC));
00311 
00312     LOG_FUNCTION_START("%p", pLux);
00313 
00314     status = VL6180X_RdWord( dev, RESULT_ALS_VAL, &RawAls);
00315     if( !status) {
00316         /* wer are yet here at no fix point */
00317         IntPeriod=VL6180XDevDataGet(dev, IntegrationPeriod);
00318         AlsScaler=VL6180XDevDataGet(dev, AlsScaler);
00319         IntPeriod++; /* what stored is real time  ms -1 and it can be 0 for or 0 or 1ms */
00320         luxValue = (uint32_t)RawAls * LuxResxIntIme; /* max # 16+8bits + 6bit (0.56*100)  */
00321         luxValue /= IntPeriod;                         /* max # 16+8bits + 6bit 16+8+1 to 9 bit */
00322         /* between  29 - 21 bit */
00323         AlsAnGain = VL6180XDevDataGet(dev, AlsGainCode);
00324         GainFix = AlsGainLookUp[AlsAnGain];
00325         luxValue = luxValue / (AlsScaler * GainFix);
00326         *pLux=luxValue;
00327     }
00328 
00329     LOG_FUNCTION_END_FMT(status, "%x",(int)*pLux);
00330     return status;
00331 }
00332 
00333 int VL6180X::VL6180X_AlsWaitDeviceReady(VL6180XDev_t dev, int MaxLoop )
00334 {
00335     int status;
00336     int  n;
00337     uint8_t u8;
00338     LOG_FUNCTION_START("%d", (int)MaxLoop);
00339     if( MaxLoop<1) {
00340         status=INVALID_PARAMS;
00341     } else {
00342         for( n=0; n < MaxLoop ; n++) {
00343             status=VL6180X_RdByte(dev, RESULT_ALS_STATUS, &u8);
00344             if( status)
00345                 break;
00346             u8 = u8 & ALS_DEVICE_READY_MASK;
00347             if( u8 )
00348                 break;
00349 
00350         }
00351         if( !status && !u8 ) {
00352             status = TIME_OUT;
00353         }
00354     }
00355     LOG_FUNCTION_END(status);
00356     return status;
00357 }
00358 
00359 int VL6180X::VL6180X_AlsSetSystemMode(VL6180XDev_t dev, uint8_t mode)
00360 {
00361     int status;
00362     LOG_FUNCTION_START("%d", (int)mode);
00363     /* FIXME if we are called back to back real fast we are not checking
00364      * if previous mode "set" got absorbed => bit 0 must be 0 so that wr 1 work */
00365     if( mode <= 3) {
00366         status=VL6180X_WrByte(dev, SYSALS_START, mode);
00367     } else {
00368         status = INVALID_PARAMS;
00369     }
00370     LOG_FUNCTION_END(status);
00371     return status;
00372 }
00373 
00374 int VL6180X::VL6180X_AlsSetThresholds(VL6180XDev_t dev, uint16_t low, uint16_t high)
00375 {
00376     int status;
00377 
00378     LOG_FUNCTION_START("%d %d", (int )low, (int)high);
00379 
00380     status = VL6180X_WrWord(dev, SYSALS_THRESH_LOW, low);
00381     if(!status ) {
00382         status = VL6180X_WrWord(dev, SYSALS_THRESH_HIGH, high);
00383     }
00384 
00385     LOG_FUNCTION_END(status) ;
00386     return status;
00387 }
00388 
00389 int VL6180X::VL6180X_AlsSetAnalogueGain(VL6180XDev_t dev, uint8_t gain)
00390 {
00391     int status;
00392     uint8_t GainTotal;
00393 
00394     LOG_FUNCTION_START("%d", (int )gain);
00395     gain&=~0x40;
00396     if (gain > 7) {
00397         gain = 7;
00398     }
00399     GainTotal = gain|0x40;
00400 
00401     status = VL6180X_WrByte(dev, SYSALS_ANALOGUE_GAIN, GainTotal);
00402     if( !status) {
00403         VL6180XDevDataSet(dev, AlsGainCode, gain);
00404     }
00405 
00406     LOG_FUNCTION_END_FMT(status, "%d %d", (int ) gain, (int )GainTotal);
00407     return status;
00408 }
00409 
00410 int VL6180X::VL6180X_AlsSetInterMeasurementPeriod(VL6180XDev_t dev,  uint16_t intermeasurement_period_ms)
00411 {
00412     int status;
00413 
00414     LOG_FUNCTION_START("%d",(int)intermeasurement_period_ms);
00415     /* clipping: range is 0-2550ms */
00416     if (intermeasurement_period_ms >= 255 *10)
00417         intermeasurement_period_ms = 255 *10;
00418     status=VL6180X_WrByte(dev, SYSALS_INTERMEASUREMENT_PERIOD, (uint8_t)(intermeasurement_period_ms/10));
00419 
00420     LOG_FUNCTION_END_FMT(status, "%d", (int) intermeasurement_period_ms);
00421     return status;
00422 }
00423 
00424 int VL6180X::VL6180X_AlsSetIntegrationPeriod(VL6180XDev_t dev, uint16_t period_ms)
00425 {
00426     int status;
00427     uint16_t SetIntegrationPeriod;
00428 
00429     LOG_FUNCTION_START("%d", (int)period_ms);
00430 
00431     if( period_ms>=1 )
00432         SetIntegrationPeriod = period_ms - 1;
00433     else
00434         SetIntegrationPeriod = period_ms;
00435 
00436     if (SetIntegrationPeriod > 464) {
00437         SetIntegrationPeriod = 464;
00438     } else if (SetIntegrationPeriod == 255)   {
00439         SetIntegrationPeriod++; /* can't write 255 since this causes the device to lock out.*/
00440     }
00441 
00442     status =VL6180X_WrWord(dev, SYSALS_INTEGRATION_PERIOD, SetIntegrationPeriod);
00443     if( !status ) {
00444         VL6180XDevDataSet(dev, IntegrationPeriod, SetIntegrationPeriod) ;
00445     }
00446     LOG_FUNCTION_END_FMT(status, "%d", (int)SetIntegrationPeriod);
00447     return status;
00448 }
00449 
00450 #endif /* HAVE_ALS_SUPPORT */
00451 
00452 int VL6180X::VL6180X_RangeGetResult(VL6180XDev_t dev, uint32_t *pRange_mm)
00453 {
00454     int status;
00455     uint8_t RawRange;
00456     int32_t Upscale;
00457 
00458     LOG_FUNCTION_START("%p",pRange_mm);
00459 
00460     status = VL6180X_RdByte(dev, RESULT_RANGE_VAL, &RawRange);
00461     if( !status ) {
00462         Upscale = _GetUpscale(dev);
00463         *pRange_mm= Upscale*(int32_t)RawRange;
00464     }
00465     LOG_FUNCTION_END_FMT(status, "%d", (int)*pRange_mm);
00466     return status;
00467 }
00468 
00469 int VL6180X::VL6180X_RangeSetRawThresholds(VL6180XDev_t dev, uint8_t low, uint8_t high)
00470 {
00471     int status;
00472     LOG_FUNCTION_START("%d %d", (int) low, (int)high);
00473     /* TODO we can optimize here grouping high/low in a word but that's cpu endianness dependent */
00474     status=VL6180X_WrByte(dev, SYSRANGE_THRESH_HIGH,high);
00475     if( !status) {
00476         status=VL6180X_WrByte(dev, SYSRANGE_THRESH_LOW, low);
00477     }
00478 
00479     LOG_FUNCTION_END(status);
00480     return status;
00481 }
00482 
00483 int VL6180X::VL6180X_RangeStaticInit(VL6180XDev_t dev)
00484 {
00485     int status;
00486     LOG_FUNCTION_START("");
00487 
00488     /* REGISTER_TUNING_SR03_270514_CustomerView.txt */
00489     VL6180X_WrByte( dev, 0x0207, 0x01);
00490     VL6180X_WrByte( dev, 0x0208, 0x01);
00491     VL6180X_WrByte( dev, 0x0096, 0x00);
00492     VL6180X_WrByte( dev, 0x0097, 0xfd);
00493     VL6180X_WrByte( dev, 0x00e3, 0x00);
00494     VL6180X_WrByte( dev, 0x00e4, 0x04);
00495     VL6180X_WrByte( dev, 0x00e5, 0x02);
00496     VL6180X_WrByte( dev, 0x00e6, 0x01);
00497     VL6180X_WrByte( dev, 0x00e7, 0x03);
00498     VL6180X_WrByte( dev, 0x00f5, 0x02);
00499     VL6180X_WrByte( dev, 0x00d9, 0x05);
00500     VL6180X_WrByte( dev, 0x00db, 0xce);
00501     VL6180X_WrByte( dev, 0x00dc, 0x03);
00502     VL6180X_WrByte( dev, 0x00dd, 0xf8);
00503     VL6180X_WrByte( dev, 0x009f, 0x00);
00504     VL6180X_WrByte( dev, 0x00a3, 0x3c);
00505     VL6180X_WrByte( dev, 0x00b7, 0x00);
00506     VL6180X_WrByte( dev, 0x00bb, 0x3c);
00507     VL6180X_WrByte( dev, 0x00b2, 0x09);
00508     VL6180X_WrByte( dev, 0x00ca, 0x09);
00509     VL6180X_WrByte( dev, 0x0198, 0x01);
00510     VL6180X_WrByte( dev, 0x01b0, 0x17);
00511     VL6180X_WrByte( dev, 0x01ad, 0x00);
00512     VL6180X_WrByte( dev, 0x00ff, 0x05);
00513     VL6180X_WrByte( dev, 0x0100, 0x05);
00514     VL6180X_WrByte( dev, 0x0199, 0x05);
00515     VL6180X_WrByte( dev, 0x01a6, 0x1b);
00516     VL6180X_WrByte( dev, 0x01ac, 0x3e);
00517     VL6180X_WrByte( dev, 0x01a7, 0x1f);
00518     VL6180X_WrByte( dev, 0x0030, 0x00);
00519 
00520     /* Recommended : Public registers - See data sheet for more detail */
00521     VL6180X_WrByte( dev, SYSTEM_MODE_GPIO1, 0x10); /* Enables polling for New Sample ready when measurement completes */
00522     VL6180X_WrByte( dev, READOUT_AVERAGING_SAMPLE_PERIOD, 0x30); /* Set the averaging sample period (compromise between lower noise and increased execution time) */
00523     VL6180X_WrByte( dev, SYSALS_ANALOGUE_GAIN, 0x46); /* Sets the light and dark gain (upper nibble). Dark gain should not be changed.*/
00524     VL6180X_WrByte( dev, SYSRANGE_VHV_REPEAT_RATE, 0xFF); /* sets the # of range measurements after which auto calibration of system is performed */
00525     VL6180X_WrByte( dev, SYSALS_INTEGRATION_PERIOD, 0x63); /* Set ALS integration time to 100ms */
00526     VL6180X_WrByte( dev, SYSRANGE_VHV_RECALIBRATE, 0x01); /* perform a single temperature calibration of the ranging sensor */
00527 
00528     /* Optional: Public registers - See data sheet for more detail */
00529     VL6180X_WrByte( dev, SYSRANGE_INTERMEASUREMENT_PERIOD, 0x09); /* Set default ranging inter-measurement period to 100ms */
00530     VL6180X_WrByte( dev, SYSALS_INTERMEASUREMENT_PERIOD, 0x31); /* Set default ALS inter-measurement period to 500ms */
00531     VL6180X_WrByte( dev, SYSTEM_INTERRUPT_CONFIG_GPIO, 0x24); /* Configures interrupt on New sample ready */
00532 
00533 
00534     status=VL6180X_RangeSetMaxConvergenceTime(dev, 50); /*  Calculate ece value on initialization (use max conv) */
00535     LOG_FUNCTION_END(status);
00536 
00537     return status;
00538 }
00539 
00540 #if VL6180X_UPSCALE_SUPPORT != 1
00541 
00542 #else
00543 #define VL6180X_UpscaleRegInit(...) -1
00544 #endif
00545 
00546 int VL6180X::VL6180X_RangeSetMaxConvergenceTime(VL6180XDev_t dev, uint8_t  MaxConTime_msec)
00547 {
00548     int status = 0;
00549     LOG_FUNCTION_START("%d",(int)MaxConTime_msec);
00550     do {
00551         status=VL6180X_WrByte(dev, SYSRANGE_MAX_CONVERGENCE_TIME, MaxConTime_msec);
00552         if( status ) {
00553             break;
00554         }
00555         status=VL6180X_RangeSetEarlyConvergenceEestimateThreshold(dev);
00556         if( status) {
00557             break;
00558         }
00559     } while(0);
00560     LOG_FUNCTION_END(status);
00561     return status;
00562 }
00563 
00564 int VL6180X::VL6180X_RangeWaitDeviceReady(VL6180XDev_t dev, int MaxLoop )
00565 {
00566     int status; /* if user specify an invalid <=0 loop count we'll return error */
00567     int  n;
00568     uint8_t u8;
00569     LOG_FUNCTION_START("%d", (int)MaxLoop);
00570     if( MaxLoop<1) {
00571         status=INVALID_PARAMS;
00572     } else {
00573         for( n=0; n < MaxLoop ; n++) {
00574             status=VL6180X_RdByte(dev, RESULT_RANGE_STATUS, &u8);
00575             if( status)
00576                 break;
00577             u8 = u8 & RANGE_DEVICE_READY_MASK;
00578             if( u8 )
00579                 break;
00580 
00581         }
00582         if( !status && !u8 ) {
00583             status = TIME_OUT;
00584         }
00585     }
00586     LOG_FUNCTION_END(status);
00587     return status;
00588 }
00589 
00590 int VL6180X::VL6180X_RangeSetSystemMode(VL6180XDev_t dev, uint8_t  mode)
00591 {
00592     int status;
00593     LOG_FUNCTION_START("%d", (int)mode);
00594     /* FIXME we are not checking device is ready via @a VL6180X_RangeWaitDeviceReady
00595      * so if called back to back real fast we are not checking
00596      * if previous mode "set" got absorbed => bit 0 must be 0 so that it work
00597      */
00598     if( mode <= 3) {
00599         status=VL6180X_WrByte(dev, SYSRANGE_START, mode);
00600         if( status ) {
00601             VL6180X_ErrLog("SYSRANGE_START wr fail");
00602         }
00603     } else {
00604         status = INVALID_PARAMS;
00605     }
00606     LOG_FUNCTION_END(status);
00607     return status;
00608 }
00609 
00610 int VL6180X::VL6180X_RangeSetEarlyConvergenceEestimateThreshold(VL6180XDev_t dev)
00611 {
00612     int status;
00613 
00614     const uint32_t cMicroSecPerMilliSec  = 1000;
00615     const uint32_t cEceSampleTime_us     = 500;
00616     uint32_t ece_factor_m          = VL6180XDevDataGet(dev, EceFactorM);
00617     uint32_t ece_factor_d          = VL6180XDevDataGet(dev, EceFactorD);
00618     uint32_t convergTime_us;
00619     uint32_t fineThresh;
00620     uint32_t eceThresh;
00621     uint8_t  u8;
00622     uint32_t maxConv_ms;
00623     int32_t AveTime;
00624 
00625     LOG_FUNCTION_START("");
00626 
00627     do {
00628         status = VL6180X_RdByte(dev, SYSRANGE_MAX_CONVERGENCE_TIME, &u8);
00629         if( status ) {
00630             VL6180X_ErrLog("SYSRANGE_MAX_CONVERGENCE_TIME rd fail");
00631             break;
00632         }
00633         maxConv_ms = u8;
00634         AveTime = _GetAveTotalTime(dev);
00635         if( AveTime <0 ) {
00636             status=-1;
00637             break;
00638         }
00639 
00640         convergTime_us = maxConv_ms * cMicroSecPerMilliSec - AveTime;
00641         status = VL6180X_RdDWord(dev, 0xB8, &fineThresh);
00642         if( status ) {
00643             VL6180X_ErrLog("reg 0xB8 rd fail");
00644             break;
00645         }
00646         fineThresh*=256;
00647         eceThresh      = ece_factor_m * cEceSampleTime_us * fineThresh/(convergTime_us * ece_factor_d);
00648 
00649         status=VL6180X_WrWord(dev, SYSRANGE_EARLY_CONVERGENCE_ESTIMATE, (uint16_t)eceThresh);
00650     } while(0);
00651 
00652     LOG_FUNCTION_END(status);
00653     return status;
00654 }
00655 
00656 /*
00657  * Return >0 = time
00658  *       <0 1 if fail to get read data from device to compute time
00659  */
00660 int32_t VL6180X::_GetAveTotalTime(VL6180XDev_t dev)
00661 {
00662     uint32_t cFwOverhead_us = 24;
00663     uint32_t cVcpSetupTime_us = 70;
00664     uint32_t cPLL2_StartupDelay_us = 200;
00665     uint8_t cMeasMask = 0x07;
00666     uint32_t Samples;
00667     uint32_t SamplePeriod;
00668     uint32_t SingleTime_us;
00669     int32_t TotalAveTime_us;
00670     uint8_t u8;
00671     int status;
00672 
00673     LOG_FUNCTION_START("");
00674 
00675     status = VL6180X_RdByte(dev, 0x109, &u8);
00676     if (status) {
00677         VL6180X_ErrLog("rd 0x109 fail");
00678         return -1;
00679     }
00680     Samples = u8 & cMeasMask;
00681     status = VL6180X_RdByte(dev, READOUT_AVERAGING_SAMPLE_PERIOD, &u8);
00682     if (status) {
00683         VL6180X_ErrLog("i2c READOUT_AVERAGING_SAMPLE_PERIOD fail");
00684         return -1;
00685     }
00686     SamplePeriod = u8;
00687     SingleTime_us = cFwOverhead_us + cVcpSetupTime_us + (SamplePeriod * 10);
00688     TotalAveTime_us = (Samples + 1) * SingleTime_us + cPLL2_StartupDelay_us;
00689 
00690     LOG_FUNCTION_END(TotalAveTime_us);
00691     return TotalAveTime_us;
00692 }
00693 
00694 
00695 #ifdef VL6180X_HAVE_RATE_DATA
00696 
00697 int VL6180X::_GetRateResult(VL6180XDev_t dev, VL6180X_RangeData_t *pRangeData)
00698 {
00699     uint32_t m_rtnConvTime = 0;
00700     uint32_t m_rtnSignalRate = 0;
00701     uint32_t m_rtnAmbientRate = 0;
00702     uint32_t m_rtnSignalCount = 0;
00703     uint32_t m_rtnAmbientCount = 0;
00704     uint32_t m_refConvTime = 0;
00705     uint32_t cRtnSignalCountMax = 0x7FFFFFFF;
00706     uint32_t cDllPeriods = 6;
00707     uint32_t calcConvTime = 0;
00708 
00709     int status;
00710 
00711     do {
00712 
00713         status = VL6180X_RdDWord(dev, RESULT_RANGE_RETURN_SIGNAL_COUNT, &m_rtnSignalCount);
00714         if (status) {
00715             VL6180X_ErrLog("RESULT_RANGE_RETURN_SIGNAL_COUNT rd fail");
00716             break;
00717         }
00718         if (m_rtnSignalCount > cRtnSignalCountMax) {
00719             m_rtnSignalCount = 0;
00720         }
00721 
00722         status = VL6180X_RdDWord(dev, RESULT_RANGE_RETURN_AMB_COUNT, &m_rtnAmbientCount);
00723         if (status) {
00724             VL6180X_ErrLog("RESULT_RANGE_RETURN_AMB_COUNTrd fail");
00725             break;
00726         }
00727 
00728 
00729         status = VL6180X_RdDWord(dev, RESULT_RANGE_RETURN_CONV_TIME, &m_rtnConvTime);
00730         if (status) {
00731             VL6180X_ErrLog("RESULT_RANGE_RETURN_CONV_TIME rd fail");
00732             break;
00733         }
00734 
00735         status = VL6180X_RdDWord(dev, RESULT_RANGE_REFERENCE_CONV_TIME, &m_refConvTime);
00736         if (status) {
00737             VL6180X_ErrLog("RESULT_RANGE_REFERENCE_CONV_TIME rd fail");
00738             break;
00739         }
00740 
00741         pRangeData->rtnConvTime  = m_rtnConvTime;
00742         pRangeData->refConvTime  = m_refConvTime;
00743 
00744         calcConvTime = m_refConvTime;
00745         if (m_rtnConvTime > m_refConvTime) {
00746             calcConvTime = m_rtnConvTime;
00747         }
00748         if (calcConvTime == 0)
00749             calcConvTime = 63000;
00750 
00751         m_rtnSignalRate = (m_rtnSignalCount * 1000) / calcConvTime;
00752         m_rtnAmbientRate = (m_rtnAmbientCount * cDllPeriods * 1000) / calcConvTime;
00753 
00754         pRangeData->rtnRate  = m_rtnSignalRate;
00755         pRangeData->rtnAmbRate  = m_rtnAmbientRate;
00756 
00757 
00758     } while (0);
00759     return status;
00760 }
00761 #endif /* VL6180X_HAVE_RATE_DATA */
00762 
00763 /******************************************************************************/
00764 /******************************************************************************/
00765 
00766 /****************** Write and read functions from I2C *************************/
00767 
00768 int VL6180X::VL6180X_WrByte(VL6180XDev_t dev, uint16_t index, uint8_t data)
00769 {
00770     int  status;
00771 
00772     status=VL6180X_I2CWrite(dev->I2cAddr, index, &data,(uint8_t)1);
00773     return status;
00774 }
00775 
00776 int VL6180X::VL6180X_WrWord(VL6180XDev_t dev, uint16_t index, uint16_t data)
00777 {
00778     int  status;
00779 
00780     status=VL6180X_I2CWrite(dev->I2cAddr, index, (uint8_t *)&data,(uint8_t)2);
00781     return status;
00782 }
00783 
00784 int VL6180X::VL6180X_WrDWord(VL6180XDev_t dev, uint16_t index, uint32_t data)
00785 {
00786     int  status;
00787 
00788     status=VL6180X_I2CWrite(dev->I2cAddr, index, (uint8_t *)&data,(uint8_t)4);
00789     return status;
00790 }
00791 
00792 int VL6180X::VL6180X_RdByte(VL6180XDev_t dev, uint16_t index, uint8_t *data)
00793 {
00794     int  status;
00795 
00796     uint8_t buffer=0;
00797     status=VL6180X_I2CRead(dev->I2cAddr, index, &buffer,1);
00798     if(!status) {
00799         *data=buffer;
00800     }
00801     return status;
00802 }
00803 
00804 int VL6180X::VL6180X_RdWord(VL6180XDev_t dev, uint16_t index, uint16_t *data)
00805 {
00806     int  status;
00807 
00808     uint8_t buffer[2];
00809     buffer[0]=buffer[1]=0;
00810     status=VL6180X_I2CRead(dev->I2cAddr, index, buffer, 2);
00811     if(!status) {
00812         memcpy(data, buffer, 2);
00813     }
00814     return status;
00815 }
00816 
00817 int VL6180X::VL6180X_RdDWord(VL6180XDev_t dev, uint16_t index, uint32_t *data)
00818 {
00819     int status;
00820     uint8_t buffer[4];
00821     buffer[0]=buffer[1]=buffer[2]=buffer[3]=0;
00822     status=VL6180X_I2CRead(dev->I2cAddr, index, buffer,4);
00823     if(!status) {
00824         memcpy(data, buffer, 4);
00825     }
00826     return status;
00827 }
00828 
00829 int VL6180X::VL6180X_UpdateByte(VL6180XDev_t dev, uint16_t index, uint8_t AndData, uint8_t OrData)
00830 {
00831     int  status;
00832     uint8_t buffer=0;
00833 
00834     status=VL6180X_I2CWrite(dev->I2cAddr, index, (uint8_t *)&buffer,(uint8_t)0);
00835     if(!status) {
00836         /* read data direct onto buffer */
00837         status=VL6180X_I2CRead(dev->I2cAddr, index, &buffer,1);
00838         if(!status) {
00839             buffer=(buffer & AndData)|OrData;
00840             status=VL6180X_I2CWrite(dev->I2cAddr, index, &buffer, (uint8_t)1);
00841         }
00842     }
00843     return status;
00844 }
00845 
00846 int VL6180X::VL6180X_I2CWrite(uint8_t DeviceAddr, uint16_t RegisterAddr, uint8_t* pBuffer, uint16_t NumByteToWrite)
00847 {
00848     int ret;
00849     int i;
00850     uint8_t tmp[TEMP_BUF_SIZE];
00851     uint16_t myRegisterAddr = RegisterAddr;
00852     uint16_t WriteDeviceAddr=0;
00853 
00854     /* First, prepare 8 bits device address in 7bits i2ci format */
00855     WriteDeviceAddr=DeviceAddr*2;
00856     if(NumByteToWrite >= TEMP_BUF_SIZE) return -2;
00857 
00858     /* then prepare 16 bits register address in BE format. Then, send data and STOP condition */
00859     tmp[0] = *(((uint8_t*)&myRegisterAddr)+1);
00860     tmp[1] = (uint8_t)RegisterAddr;
00861 
00862     if(NumByteToWrite>1) { /* swap data endianess */
00863         for(i=0; i<NumByteToWrite; i++) {
00864             tmp[NumByteToWrite+sizeof(RegisterAddr)-1-i]=pBuffer[i];
00865         }
00866     } else {
00867         memcpy(tmp+sizeof(RegisterAddr), pBuffer, NumByteToWrite);
00868     }
00869     ret = _i2c.write(WriteDeviceAddr, (const char*)tmp, NumByteToWrite+sizeof(RegisterAddr), false);
00870     if(ret)
00871         return -1;
00872     return 0;
00873 }
00874 
00875 int VL6180X::VL6180X_I2CRead(uint8_t DeviceAddr, uint16_t RegisterAddr, uint8_t* pBuffer, uint16_t NumByteToRead)
00876 {
00877     int ret,i;
00878     uint8_t tmp[TEMP_BUF_SIZE];
00879     uint16_t myRegisterAddr = RegisterAddr;
00880     uint16_t myRegisterAddrBE;
00881     uint16_t ReadDeviceAddr=DeviceAddr;
00882 
00883     ReadDeviceAddr=DeviceAddr*2;
00884     myRegisterAddrBE = *(((uint8_t*)&myRegisterAddr)+1);
00885     *(((uint8_t*)&myRegisterAddrBE)+1) = (uint8_t)myRegisterAddr;
00886 
00887     /* Send 8 bits device address and 16 bits register address in BE format, with no STOP condition */
00888     ret = _i2c.write(ReadDeviceAddr, (const char*)&myRegisterAddrBE, sizeof(RegisterAddr), true);
00889     if(!ret) {
00890         ReadDeviceAddr|=0x001;
00891         /* Read data, with STOP condition  */
00892         ret = _i2c.read(ReadDeviceAddr, (char*)tmp, NumByteToRead, false);
00893     }
00894     if(ret)
00895         return -1;
00896 
00897     if(NumByteToRead>1) { /* swap data endianess */
00898         for(i=0; i<NumByteToRead; i++) {
00899             pBuffer[i] = tmp[NumByteToRead-1-i];
00900         }
00901     } else {
00902         memcpy(pBuffer, tmp, NumByteToRead);
00903     }
00904     return 0;
00905 }
00906 
00907 /******************************************************************************/
00908 int VL6180X::read_id(uint8_t *id)
00909 {
00910     return VL6180X_RdByte(_device, IDENTIFICATION_MODEL_ID, id);
00911 }
00912 
00913 int VL6180X::start_measurement(operating_mode_t operating_mode)
00914 {
00915 
00916     switch (operating_mode) {
00917         case(range_single_shot_polling):
00918             return VL6180X_WrByte(_device, SYSRANGE_START, MODE_START_STOP|MODE_SINGLESHOT);
00919         case(als_single_shot_polling):
00920             return VL6180X_WrByte(_device, SYSALS_START, MODE_START_STOP|MODE_SINGLESHOT);
00921         default:
00922             return INVALID_PARAMS;
00923     }
00924 }
00925 
00926 int VL6180X::stop_measurement(operating_mode_t operating_mode)
00927 {
00928     switch(operating_mode) {
00929         case(range_single_shot_polling):
00930             return VL6180X_RangeSetSystemMode(_device, MODE_SINGLESHOT);
00931         case(als_single_shot_polling):
00932             return VL6180X_AlsSetSystemMode(_device, MODE_SINGLESHOT);
00933         default:
00934             return INVALID_PARAMS;
00935     }
00936 }
00937 
00938 int VL6180X::IsPresent()
00939 {
00940     int status;
00941     uint8_t id;
00942 
00943     status=read_id(&id);
00944     if(status)
00945         VL6180X_ErrLog("Failed to read ID device. _device not present!\n\r");
00946     return status;
00947 }
00948 
00949 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/