Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: Check_VL6180XA1_ToF
Fork of X_NUCLEO_6180XA1 by
VL6180X.cpp
00001 /** 00002 ****************************************************************************** 00003 * @file VL6180X.cpp 00004 * @author AST / EST 00005 * @version V0.0.1 00006 * @date 14-April-2015 00007 * @brief Implementation file for the HTS221 driver class 00008 ****************************************************************************** 00009 * @attention 00010 * 00011 * <h2><center>© COPYRIGHT(c) 2015 STMicroelectronics</center></h2> 00012 * 00013 * Redistribution and use in source and binary forms, with or without modification, 00014 * are permitted provided that the following conditions are met: 00015 * 1. Redistributions of source code must retain the above copyright notice, 00016 * this list of conditions and the following disclaimer. 00017 * 2. Redistributions in binary form must reproduce the above copyright notice, 00018 * this list of conditions and the following disclaimer in the documentation 00019 * and/or other materials provided with the distribution. 00020 * 3. Neither the name of STMicroelectronics nor the names of its contributors 00021 * may be used to endorse or promote products derived from this software 00022 * without specific prior written permission. 00023 * 00024 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00025 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00026 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00027 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 00028 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00029 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00030 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00031 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00032 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00033 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00034 * 00035 ****************************************************************************** 00036 */ 00037 00038 //------- 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****/
Generated on Tue Jul 12 2022 22:24:22 by
1.7.2
