use VL6180XA1 chip wothout X-NUCLEO-6180XA1 Board. Simple way to use the chip.
Dependents: Check_VL6180XA1_ToF
Fork of X_NUCLEO_6180XA1 by
VL6180X.cpp
- Committer:
- kenjiArai
- Date:
- 2018-02-01
- Revision:
- 60:972b4898a007
- Parent:
- 59:81afbb75311d
File content as of revision 60:972b4898a007:
/** ****************************************************************************** * @file VL6180X.cpp * @author AST / EST * @version V0.0.1 * @date 14-April-2015 * @brief Implementation file for the HTS221 driver class ****************************************************************************** * @attention * * <h2><center>© COPYRIGHT(c) 2015 STMicroelectronics</center></h2> * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of STMicroelectronics nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************** */ //------- Feburary 1st, 2018 by JH1PJL / K.Arai -------------------------------- // Change X_NUCLEO_6180XA1 library to 6180XA1_simplest library // modified -> all related files //------------------------------------------------------------------------------ /* Includes */ #include "VL6180X.h" #define VL6180X_DEV_DATA_ATTR #define ROMABLE_DATA //-------- NOT USE FOLLOING FUNCTIONS ------------- //void OnErrLog(void); #define LOG_FUNCTION_START(...) (void)0 #define LOG_FUNCTION_END(...) (void)0 #define LOG_FUNCTION_END_FMT(...) (void)0 #define VL6180X_ErrLog(... ) //OnErrLog() //(void)0 #define VL6180XDevDataGet(dev, field) (dev->Data.field) #define VL6180XDevDataSet(dev, field, data) (dev->Data.field)=(data) /** @defgroup api_init Init functions * @brief API init functions * @ingroup api_hl * @{ */ /****************** define for i2c configuration *******************************/ #define TEMP_BUF_SIZE 32 /******************************************************************************/ /******************************* file api.c ***********************************/ #define VL6180X_9to7Conv(x) (x) /* TODO when set all "cached" value with "default init" are updated after init from register read back */ #define REFRESH_CACHED_DATA_AFTER_INIT 1 /** default value ECE factor Molecular */ #define DEF_ECE_FACTOR_M 85 /** default value ECE factor Denominator */ #define DEF_ECE_FACTOR_D 100 /** default value ALS integration time */ #define DEF_INT_PEFRIOD 100 /** default value ALS gain */ #define DEF_ALS_GAIN 1 /** default value ALS scaler */ #define DEF_ALS_SCALER 1 /** default value for DMAX Enbale */ #define DEF_DMAX_ENABLE 1 /** default ambient tuning factor %x1000 */ #define DEF_AMBIENT_TUNING 80 #define LUXRES_FIX_PREC 8 #define GAIN_FIX_PREC 8 /* ! if not sme as LUX_PREC then :( adjust GetLux */ #define AN_GAIN_MULT (1<<GAIN_FIX_PREC) /** * Als Code gain to fix point gain lookup */ static const uint16_t AlsGainLookUp[8] ROMABLE_DATA = { (uint16_t)(20.0f * AN_GAIN_MULT), (uint16_t)(10.0f * AN_GAIN_MULT), (uint16_t)(5.0f * AN_GAIN_MULT), (uint16_t)(2.5f * AN_GAIN_MULT), (uint16_t)(1.67f * AN_GAIN_MULT), (uint16_t)(1.25f * AN_GAIN_MULT), (uint16_t)(1.0f * AN_GAIN_MULT), (uint16_t)(40.0f * AN_GAIN_MULT), }; #if VL6180X_UPSCALE_SUPPORT == 1 #define _GetUpscale(dev, ... ) 1 #define _SetUpscale(...) -1 #define DEF_UPSCALE 1 #elif VL6180X_UPSCALE_SUPPORT == 2 #define _GetUpscale(dev, ... ) 2 #define _SetUpscale(...) #define DEF_UPSCALE 2 #elif VL6180X_UPSCALE_SUPPORT == 3 #define _GetUpscale(dev, ... ) 3 #define _SetUpscale(...) #define DEF_UPSCALE 3 #else #define DEF_UPSCALE (-(VL6180X_UPSCALE_SUPPORT)) #define _GetUpscale(dev, ... ) VL6180XDevDataGet(dev, UpscaleFactor) #define _SetUpscale(dev, Scaling ) VL6180XDevDataSet(dev, UpscaleFactor, Scaling) #endif #define Fix7_2_KCPs(x) ((((uint32_t)(x))*1000)>>7) int VL6180X::VL6180X_WaitDeviceBooted(VL6180XDev_t dev) { uint8_t FreshOutReset=0; int status; LOG_FUNCTION_START(""); do { status = VL6180X_RdByte(dev,SYSTEM_FRESH_OUT_OF_RESET, &FreshOutReset); } while( FreshOutReset!=1 && status==0); LOG_FUNCTION_END(status); return status; } int VL6180X::VL6180X_InitData(VL6180XDev_t dev) { int status, dmax_status ; int8_t offset; uint8_t FreshOutReset; uint32_t CalValue; uint16_t u16; uint32_t XTalkCompRate_KCps; LOG_FUNCTION_START(""); VL6180XDevDataSet(dev, EceFactorM , DEF_ECE_FACTOR_M); VL6180XDevDataSet(dev, EceFactorD , DEF_ECE_FACTOR_D); #ifdef VL6180X_HAVE_UPSCALE_DATA VL6180XDevDataSet(dev, UpscaleFactor , DEF_UPSCALE); #endif #ifdef VL6180X_HAVE_ALS_DATA VL6180XDevDataSet(dev, IntegrationPeriod, DEF_INT_PEFRIOD); VL6180XDevDataSet(dev, AlsGainCode, DEF_ALS_GAIN); VL6180XDevDataSet(dev, AlsScaler, DEF_ALS_SCALER); #endif do { /* backup offset initial value from nvm these must be done prior any over call that use offset */ status = VL6180X::VL6180X_RdByte(dev,SYSRANGE_PART_TO_PART_RANGE_OFFSET, (uint8_t*)&offset); if( status ) { VL6180X_ErrLog("SYSRANGE_PART_TO_PART_RANGE_OFFSET rd fail"); break; } VL6180XDevDataSet(dev, Part2PartOffsetNVM, offset); status=VL6180X_RdDWord( dev, SYSRANGE_RANGE_IGNORE_THRESHOLD, &CalValue); if( status ) { VL6180X_ErrLog("Part2PartAmbNVM rd fail"); break; } if( (CalValue&0xFFFF0000) == 0 ) { CalValue=0x00CE03F8; } VL6180XDevDataSet(dev, Part2PartAmbNVM, CalValue); status = VL6180X_RdWord(dev, SYSRANGE_CROSSTALK_COMPENSATION_RATE ,&u16); if( status) { VL6180X_ErrLog("SYSRANGE_CROSSTALK_COMPENSATION_RATE rd fail "); break; } XTalkCompRate_KCps = Fix7_2_KCPs(u16); VL6180XDevDataSet(dev, XTalkCompRate_KCps , XTalkCompRate_KCps ); /* Read or wait for fresh out of reset */ status = VL6180X_RdByte(dev,SYSTEM_FRESH_OUT_OF_RESET, &FreshOutReset); if( status ) { VL6180X_ErrLog("SYSTEM_FRESH_OUT_OF_RESET rd fail"); break; } if( FreshOutReset!= 1 || dmax_status ) status = CALIBRATION_WARNING; } while(0); LOG_FUNCTION_END(status); return status; } int VL6180X::VL6180X_StaticInit(VL6180XDev_t dev) { int status=0, init_status; LOG_FUNCTION_START(""); if( _GetUpscale(dev) == 1 ) init_status=VL6180X_RangeStaticInit(dev); if( init_status <0 ) { VL6180X_ErrLog("StaticInit fail"); goto error; } else if(init_status > 0) { VL6180X_ErrLog("StaticInit warning"); } #if REFRESH_CACHED_DATA_AFTER_INIT /* update cached value after tuning applied */ do { #ifdef VL6180X_HAVE_ALS_DATA uint8_t data; status= VL6180X_RdByte(dev, FW_ALS_RESULT_SCALER, &data); if( status ) break; VL6180XDevDataSet(dev, AlsScaler, data); status= VL6180X_RdByte(dev, SYSALS_ANALOGUE_GAIN, &data); if( status ) break; VL6180X_AlsSetAnalogueGain(dev, data); #endif } while(0); #endif /* REFRESH_CACHED_DATA_AFTER_INIT */ if( status < 0 ) { VL6180X_ErrLog("StaticInit fail"); } if( !status && init_status) { status = init_status; } error: LOG_FUNCTION_END(status); return status; } #if 1 int VL6180X::VL6180X_SetGroupParamHold(VL6180XDev_t dev, int Hold) { int status; uint8_t value; LOG_FUNCTION_START("%d", Hold); if( Hold ) value = 1; else value = 0; status = VL6180X_WrByte(dev, SYSTEM_GROUPED_PARAMETER_HOLD, value); LOG_FUNCTION_END(status); return status; } #endif int VL6180X::VL6180X_Prepare(VL6180XDev_t dev) { int status; LOG_FUNCTION_START(""); do { status=VL6180X_StaticInit(dev); if( status<0) break; /* set default threshold */ status=VL6180X_RangeSetRawThresholds(dev, 10, 200); if( status ) { VL6180X_ErrLog("VL6180X_RangeSetRawThresholds fail"); break; } #if VL6180X_ALS_SUPPORT status =VL6180X_AlsSetIntegrationPeriod(dev, 100); if( status ) break; status = VL6180X_AlsSetInterMeasurementPeriod(dev, 200); if( status ) break; status = VL6180X_AlsSetAnalogueGain(dev, 0); if( status ) break; status = VL6180X_AlsSetThresholds(dev, 0, 0xFFFF); if( status ) break; #endif } while(0); LOG_FUNCTION_END(status); return status; } #if VL6180X_ALS_SUPPORT int VL6180X::VL6180X_AlsGetLux(VL6180XDev_t dev, lux_t *pLux) { int status; uint16_t RawAls; uint32_t luxValue = 0; uint32_t IntPeriod; uint32_t AlsAnGain; uint32_t GainFix; uint32_t AlsScaler; #if LUXRES_FIX_PREC != GAIN_FIX_PREC #error "LUXRES_FIX_PREC != GAIN_FIX_PREC review these code to be correct" #endif const uint32_t LuxResxIntIme =(uint32_t)(0.56f* DEF_INT_PEFRIOD *(1<<LUXRES_FIX_PREC)); LOG_FUNCTION_START("%p", pLux); status = VL6180X_RdWord( dev, RESULT_ALS_VAL, &RawAls); if( !status) { /* wer are yet here at no fix point */ IntPeriod=VL6180XDevDataGet(dev, IntegrationPeriod); AlsScaler=VL6180XDevDataGet(dev, AlsScaler); IntPeriod++; /* what stored is real time ms -1 and it can be 0 for or 0 or 1ms */ luxValue = (uint32_t)RawAls * LuxResxIntIme; /* max # 16+8bits + 6bit (0.56*100) */ luxValue /= IntPeriod; /* max # 16+8bits + 6bit 16+8+1 to 9 bit */ /* between 29 - 21 bit */ AlsAnGain = VL6180XDevDataGet(dev, AlsGainCode); GainFix = AlsGainLookUp[AlsAnGain]; luxValue = luxValue / (AlsScaler * GainFix); *pLux=luxValue; } LOG_FUNCTION_END_FMT(status, "%x",(int)*pLux); return status; } int VL6180X::VL6180X_AlsWaitDeviceReady(VL6180XDev_t dev, int MaxLoop ) { int status; int n; uint8_t u8; LOG_FUNCTION_START("%d", (int)MaxLoop); if( MaxLoop<1) { status=INVALID_PARAMS; } else { for( n=0; n < MaxLoop ; n++) { status=VL6180X_RdByte(dev, RESULT_ALS_STATUS, &u8); if( status) break; u8 = u8 & ALS_DEVICE_READY_MASK; if( u8 ) break; } if( !status && !u8 ) { status = TIME_OUT; } } LOG_FUNCTION_END(status); return status; } int VL6180X::VL6180X_AlsSetSystemMode(VL6180XDev_t dev, uint8_t mode) { int status; LOG_FUNCTION_START("%d", (int)mode); /* FIXME if we are called back to back real fast we are not checking * if previous mode "set" got absorbed => bit 0 must be 0 so that wr 1 work */ if( mode <= 3) { status=VL6180X_WrByte(dev, SYSALS_START, mode); } else { status = INVALID_PARAMS; } LOG_FUNCTION_END(status); return status; } int VL6180X::VL6180X_AlsSetThresholds(VL6180XDev_t dev, uint16_t low, uint16_t high) { int status; LOG_FUNCTION_START("%d %d", (int )low, (int)high); status = VL6180X_WrWord(dev, SYSALS_THRESH_LOW, low); if(!status ) { status = VL6180X_WrWord(dev, SYSALS_THRESH_HIGH, high); } LOG_FUNCTION_END(status) ; return status; } int VL6180X::VL6180X_AlsSetAnalogueGain(VL6180XDev_t dev, uint8_t gain) { int status; uint8_t GainTotal; LOG_FUNCTION_START("%d", (int )gain); gain&=~0x40; if (gain > 7) { gain = 7; } GainTotal = gain|0x40; status = VL6180X_WrByte(dev, SYSALS_ANALOGUE_GAIN, GainTotal); if( !status) { VL6180XDevDataSet(dev, AlsGainCode, gain); } LOG_FUNCTION_END_FMT(status, "%d %d", (int ) gain, (int )GainTotal); return status; } int VL6180X::VL6180X_AlsSetInterMeasurementPeriod(VL6180XDev_t dev, uint16_t intermeasurement_period_ms) { int status; LOG_FUNCTION_START("%d",(int)intermeasurement_period_ms); /* clipping: range is 0-2550ms */ if (intermeasurement_period_ms >= 255 *10) intermeasurement_period_ms = 255 *10; status=VL6180X_WrByte(dev, SYSALS_INTERMEASUREMENT_PERIOD, (uint8_t)(intermeasurement_period_ms/10)); LOG_FUNCTION_END_FMT(status, "%d", (int) intermeasurement_period_ms); return status; } int VL6180X::VL6180X_AlsSetIntegrationPeriod(VL6180XDev_t dev, uint16_t period_ms) { int status; uint16_t SetIntegrationPeriod; LOG_FUNCTION_START("%d", (int)period_ms); if( period_ms>=1 ) SetIntegrationPeriod = period_ms - 1; else SetIntegrationPeriod = period_ms; if (SetIntegrationPeriod > 464) { SetIntegrationPeriod = 464; } else if (SetIntegrationPeriod == 255) { SetIntegrationPeriod++; /* can't write 255 since this causes the device to lock out.*/ } status =VL6180X_WrWord(dev, SYSALS_INTEGRATION_PERIOD, SetIntegrationPeriod); if( !status ) { VL6180XDevDataSet(dev, IntegrationPeriod, SetIntegrationPeriod) ; } LOG_FUNCTION_END_FMT(status, "%d", (int)SetIntegrationPeriod); return status; } #endif /* HAVE_ALS_SUPPORT */ int VL6180X::VL6180X_RangeGetResult(VL6180XDev_t dev, uint32_t *pRange_mm) { int status; uint8_t RawRange; int32_t Upscale; LOG_FUNCTION_START("%p",pRange_mm); status = VL6180X_RdByte(dev, RESULT_RANGE_VAL, &RawRange); if( !status ) { Upscale = _GetUpscale(dev); *pRange_mm= Upscale*(int32_t)RawRange; } LOG_FUNCTION_END_FMT(status, "%d", (int)*pRange_mm); return status; } int VL6180X::VL6180X_RangeSetRawThresholds(VL6180XDev_t dev, uint8_t low, uint8_t high) { int status; LOG_FUNCTION_START("%d %d", (int) low, (int)high); /* TODO we can optimize here grouping high/low in a word but that's cpu endianness dependent */ status=VL6180X_WrByte(dev, SYSRANGE_THRESH_HIGH,high); if( !status) { status=VL6180X_WrByte(dev, SYSRANGE_THRESH_LOW, low); } LOG_FUNCTION_END(status); return status; } int VL6180X::VL6180X_RangeStaticInit(VL6180XDev_t dev) { int status; LOG_FUNCTION_START(""); /* REGISTER_TUNING_SR03_270514_CustomerView.txt */ VL6180X_WrByte( dev, 0x0207, 0x01); VL6180X_WrByte( dev, 0x0208, 0x01); VL6180X_WrByte( dev, 0x0096, 0x00); VL6180X_WrByte( dev, 0x0097, 0xfd); VL6180X_WrByte( dev, 0x00e3, 0x00); VL6180X_WrByte( dev, 0x00e4, 0x04); VL6180X_WrByte( dev, 0x00e5, 0x02); VL6180X_WrByte( dev, 0x00e6, 0x01); VL6180X_WrByte( dev, 0x00e7, 0x03); VL6180X_WrByte( dev, 0x00f5, 0x02); VL6180X_WrByte( dev, 0x00d9, 0x05); VL6180X_WrByte( dev, 0x00db, 0xce); VL6180X_WrByte( dev, 0x00dc, 0x03); VL6180X_WrByte( dev, 0x00dd, 0xf8); VL6180X_WrByte( dev, 0x009f, 0x00); VL6180X_WrByte( dev, 0x00a3, 0x3c); VL6180X_WrByte( dev, 0x00b7, 0x00); VL6180X_WrByte( dev, 0x00bb, 0x3c); VL6180X_WrByte( dev, 0x00b2, 0x09); VL6180X_WrByte( dev, 0x00ca, 0x09); VL6180X_WrByte( dev, 0x0198, 0x01); VL6180X_WrByte( dev, 0x01b0, 0x17); VL6180X_WrByte( dev, 0x01ad, 0x00); VL6180X_WrByte( dev, 0x00ff, 0x05); VL6180X_WrByte( dev, 0x0100, 0x05); VL6180X_WrByte( dev, 0x0199, 0x05); VL6180X_WrByte( dev, 0x01a6, 0x1b); VL6180X_WrByte( dev, 0x01ac, 0x3e); VL6180X_WrByte( dev, 0x01a7, 0x1f); VL6180X_WrByte( dev, 0x0030, 0x00); /* Recommended : Public registers - See data sheet for more detail */ VL6180X_WrByte( dev, SYSTEM_MODE_GPIO1, 0x10); /* Enables polling for New Sample ready when measurement completes */ VL6180X_WrByte( dev, READOUT_AVERAGING_SAMPLE_PERIOD, 0x30); /* Set the averaging sample period (compromise between lower noise and increased execution time) */ VL6180X_WrByte( dev, SYSALS_ANALOGUE_GAIN, 0x46); /* Sets the light and dark gain (upper nibble). Dark gain should not be changed.*/ VL6180X_WrByte( dev, SYSRANGE_VHV_REPEAT_RATE, 0xFF); /* sets the # of range measurements after which auto calibration of system is performed */ VL6180X_WrByte( dev, SYSALS_INTEGRATION_PERIOD, 0x63); /* Set ALS integration time to 100ms */ VL6180X_WrByte( dev, SYSRANGE_VHV_RECALIBRATE, 0x01); /* perform a single temperature calibration of the ranging sensor */ /* Optional: Public registers - See data sheet for more detail */ VL6180X_WrByte( dev, SYSRANGE_INTERMEASUREMENT_PERIOD, 0x09); /* Set default ranging inter-measurement period to 100ms */ VL6180X_WrByte( dev, SYSALS_INTERMEASUREMENT_PERIOD, 0x31); /* Set default ALS inter-measurement period to 500ms */ VL6180X_WrByte( dev, SYSTEM_INTERRUPT_CONFIG_GPIO, 0x24); /* Configures interrupt on New sample ready */ status=VL6180X_RangeSetMaxConvergenceTime(dev, 50); /* Calculate ece value on initialization (use max conv) */ LOG_FUNCTION_END(status); return status; } #if VL6180X_UPSCALE_SUPPORT != 1 #else #define VL6180X_UpscaleRegInit(...) -1 #endif int VL6180X::VL6180X_RangeSetMaxConvergenceTime(VL6180XDev_t dev, uint8_t MaxConTime_msec) { int status = 0; LOG_FUNCTION_START("%d",(int)MaxConTime_msec); do { status=VL6180X_WrByte(dev, SYSRANGE_MAX_CONVERGENCE_TIME, MaxConTime_msec); if( status ) { break; } status=VL6180X_RangeSetEarlyConvergenceEestimateThreshold(dev); if( status) { break; } } while(0); LOG_FUNCTION_END(status); return status; } int VL6180X::VL6180X_RangeWaitDeviceReady(VL6180XDev_t dev, int MaxLoop ) { int status; /* if user specify an invalid <=0 loop count we'll return error */ int n; uint8_t u8; LOG_FUNCTION_START("%d", (int)MaxLoop); if( MaxLoop<1) { status=INVALID_PARAMS; } else { for( n=0; n < MaxLoop ; n++) { status=VL6180X_RdByte(dev, RESULT_RANGE_STATUS, &u8); if( status) break; u8 = u8 & RANGE_DEVICE_READY_MASK; if( u8 ) break; } if( !status && !u8 ) { status = TIME_OUT; } } LOG_FUNCTION_END(status); return status; } int VL6180X::VL6180X_RangeSetSystemMode(VL6180XDev_t dev, uint8_t mode) { int status; LOG_FUNCTION_START("%d", (int)mode); /* FIXME we are not checking device is ready via @a VL6180X_RangeWaitDeviceReady * so if called back to back real fast we are not checking * if previous mode "set" got absorbed => bit 0 must be 0 so that it work */ if( mode <= 3) { status=VL6180X_WrByte(dev, SYSRANGE_START, mode); if( status ) { VL6180X_ErrLog("SYSRANGE_START wr fail"); } } else { status = INVALID_PARAMS; } LOG_FUNCTION_END(status); return status; } int VL6180X::VL6180X_RangeSetEarlyConvergenceEestimateThreshold(VL6180XDev_t dev) { int status; const uint32_t cMicroSecPerMilliSec = 1000; const uint32_t cEceSampleTime_us = 500; uint32_t ece_factor_m = VL6180XDevDataGet(dev, EceFactorM); uint32_t ece_factor_d = VL6180XDevDataGet(dev, EceFactorD); uint32_t convergTime_us; uint32_t fineThresh; uint32_t eceThresh; uint8_t u8; uint32_t maxConv_ms; int32_t AveTime; LOG_FUNCTION_START(""); do { status = VL6180X_RdByte(dev, SYSRANGE_MAX_CONVERGENCE_TIME, &u8); if( status ) { VL6180X_ErrLog("SYSRANGE_MAX_CONVERGENCE_TIME rd fail"); break; } maxConv_ms = u8; AveTime = _GetAveTotalTime(dev); if( AveTime <0 ) { status=-1; break; } convergTime_us = maxConv_ms * cMicroSecPerMilliSec - AveTime; status = VL6180X_RdDWord(dev, 0xB8, &fineThresh); if( status ) { VL6180X_ErrLog("reg 0xB8 rd fail"); break; } fineThresh*=256; eceThresh = ece_factor_m * cEceSampleTime_us * fineThresh/(convergTime_us * ece_factor_d); status=VL6180X_WrWord(dev, SYSRANGE_EARLY_CONVERGENCE_ESTIMATE, (uint16_t)eceThresh); } while(0); LOG_FUNCTION_END(status); return status; } /* * Return >0 = time * <0 1 if fail to get read data from device to compute time */ int32_t VL6180X::_GetAveTotalTime(VL6180XDev_t dev) { uint32_t cFwOverhead_us = 24; uint32_t cVcpSetupTime_us = 70; uint32_t cPLL2_StartupDelay_us = 200; uint8_t cMeasMask = 0x07; uint32_t Samples; uint32_t SamplePeriod; uint32_t SingleTime_us; int32_t TotalAveTime_us; uint8_t u8; int status; LOG_FUNCTION_START(""); status = VL6180X_RdByte(dev, 0x109, &u8); if (status) { VL6180X_ErrLog("rd 0x109 fail"); return -1; } Samples = u8 & cMeasMask; status = VL6180X_RdByte(dev, READOUT_AVERAGING_SAMPLE_PERIOD, &u8); if (status) { VL6180X_ErrLog("i2c READOUT_AVERAGING_SAMPLE_PERIOD fail"); return -1; } SamplePeriod = u8; SingleTime_us = cFwOverhead_us + cVcpSetupTime_us + (SamplePeriod * 10); TotalAveTime_us = (Samples + 1) * SingleTime_us + cPLL2_StartupDelay_us; LOG_FUNCTION_END(TotalAveTime_us); return TotalAveTime_us; } #ifdef VL6180X_HAVE_RATE_DATA int VL6180X::_GetRateResult(VL6180XDev_t dev, VL6180X_RangeData_t *pRangeData) { uint32_t m_rtnConvTime = 0; uint32_t m_rtnSignalRate = 0; uint32_t m_rtnAmbientRate = 0; uint32_t m_rtnSignalCount = 0; uint32_t m_rtnAmbientCount = 0; uint32_t m_refConvTime = 0; uint32_t cRtnSignalCountMax = 0x7FFFFFFF; uint32_t cDllPeriods = 6; uint32_t calcConvTime = 0; int status; do { status = VL6180X_RdDWord(dev, RESULT_RANGE_RETURN_SIGNAL_COUNT, &m_rtnSignalCount); if (status) { VL6180X_ErrLog("RESULT_RANGE_RETURN_SIGNAL_COUNT rd fail"); break; } if (m_rtnSignalCount > cRtnSignalCountMax) { m_rtnSignalCount = 0; } status = VL6180X_RdDWord(dev, RESULT_RANGE_RETURN_AMB_COUNT, &m_rtnAmbientCount); if (status) { VL6180X_ErrLog("RESULT_RANGE_RETURN_AMB_COUNTrd fail"); break; } status = VL6180X_RdDWord(dev, RESULT_RANGE_RETURN_CONV_TIME, &m_rtnConvTime); if (status) { VL6180X_ErrLog("RESULT_RANGE_RETURN_CONV_TIME rd fail"); break; } status = VL6180X_RdDWord(dev, RESULT_RANGE_REFERENCE_CONV_TIME, &m_refConvTime); if (status) { VL6180X_ErrLog("RESULT_RANGE_REFERENCE_CONV_TIME rd fail"); break; } pRangeData->rtnConvTime = m_rtnConvTime; pRangeData->refConvTime = m_refConvTime; calcConvTime = m_refConvTime; if (m_rtnConvTime > m_refConvTime) { calcConvTime = m_rtnConvTime; } if (calcConvTime == 0) calcConvTime = 63000; m_rtnSignalRate = (m_rtnSignalCount * 1000) / calcConvTime; m_rtnAmbientRate = (m_rtnAmbientCount * cDllPeriods * 1000) / calcConvTime; pRangeData->rtnRate = m_rtnSignalRate; pRangeData->rtnAmbRate = m_rtnAmbientRate; } while (0); return status; } #endif /* VL6180X_HAVE_RATE_DATA */ /******************************************************************************/ /******************************************************************************/ /****************** Write and read functions from I2C *************************/ int VL6180X::VL6180X_WrByte(VL6180XDev_t dev, uint16_t index, uint8_t data) { int status; status=VL6180X_I2CWrite(dev->I2cAddr, index, &data,(uint8_t)1); return status; } int VL6180X::VL6180X_WrWord(VL6180XDev_t dev, uint16_t index, uint16_t data) { int status; status=VL6180X_I2CWrite(dev->I2cAddr, index, (uint8_t *)&data,(uint8_t)2); return status; } int VL6180X::VL6180X_WrDWord(VL6180XDev_t dev, uint16_t index, uint32_t data) { int status; status=VL6180X_I2CWrite(dev->I2cAddr, index, (uint8_t *)&data,(uint8_t)4); return status; } int VL6180X::VL6180X_RdByte(VL6180XDev_t dev, uint16_t index, uint8_t *data) { int status; uint8_t buffer=0; status=VL6180X_I2CRead(dev->I2cAddr, index, &buffer,1); if(!status) { *data=buffer; } return status; } int VL6180X::VL6180X_RdWord(VL6180XDev_t dev, uint16_t index, uint16_t *data) { int status; uint8_t buffer[2]; buffer[0]=buffer[1]=0; status=VL6180X_I2CRead(dev->I2cAddr, index, buffer, 2); if(!status) { memcpy(data, buffer, 2); } return status; } int VL6180X::VL6180X_RdDWord(VL6180XDev_t dev, uint16_t index, uint32_t *data) { int status; uint8_t buffer[4]; buffer[0]=buffer[1]=buffer[2]=buffer[3]=0; status=VL6180X_I2CRead(dev->I2cAddr, index, buffer,4); if(!status) { memcpy(data, buffer, 4); } return status; } int VL6180X::VL6180X_UpdateByte(VL6180XDev_t dev, uint16_t index, uint8_t AndData, uint8_t OrData) { int status; uint8_t buffer=0; status=VL6180X_I2CWrite(dev->I2cAddr, index, (uint8_t *)&buffer,(uint8_t)0); if(!status) { /* read data direct onto buffer */ status=VL6180X_I2CRead(dev->I2cAddr, index, &buffer,1); if(!status) { buffer=(buffer & AndData)|OrData; status=VL6180X_I2CWrite(dev->I2cAddr, index, &buffer, (uint8_t)1); } } return status; } int VL6180X::VL6180X_I2CWrite(uint8_t DeviceAddr, uint16_t RegisterAddr, uint8_t* pBuffer, uint16_t NumByteToWrite) { int ret; int i; uint8_t tmp[TEMP_BUF_SIZE]; uint16_t myRegisterAddr = RegisterAddr; uint16_t WriteDeviceAddr=0; /* First, prepare 8 bits device address in 7bits i2ci format */ WriteDeviceAddr=DeviceAddr*2; if(NumByteToWrite >= TEMP_BUF_SIZE) return -2; /* then prepare 16 bits register address in BE format. Then, send data and STOP condition */ tmp[0] = *(((uint8_t*)&myRegisterAddr)+1); tmp[1] = (uint8_t)RegisterAddr; if(NumByteToWrite>1) { /* swap data endianess */ for(i=0; i<NumByteToWrite; i++) { tmp[NumByteToWrite+sizeof(RegisterAddr)-1-i]=pBuffer[i]; } } else { memcpy(tmp+sizeof(RegisterAddr), pBuffer, NumByteToWrite); } ret = _i2c.write(WriteDeviceAddr, (const char*)tmp, NumByteToWrite+sizeof(RegisterAddr), false); if(ret) return -1; return 0; } int VL6180X::VL6180X_I2CRead(uint8_t DeviceAddr, uint16_t RegisterAddr, uint8_t* pBuffer, uint16_t NumByteToRead) { int ret,i; uint8_t tmp[TEMP_BUF_SIZE]; uint16_t myRegisterAddr = RegisterAddr; uint16_t myRegisterAddrBE; uint16_t ReadDeviceAddr=DeviceAddr; ReadDeviceAddr=DeviceAddr*2; myRegisterAddrBE = *(((uint8_t*)&myRegisterAddr)+1); *(((uint8_t*)&myRegisterAddrBE)+1) = (uint8_t)myRegisterAddr; /* Send 8 bits device address and 16 bits register address in BE format, with no STOP condition */ ret = _i2c.write(ReadDeviceAddr, (const char*)&myRegisterAddrBE, sizeof(RegisterAddr), true); if(!ret) { ReadDeviceAddr|=0x001; /* Read data, with STOP condition */ ret = _i2c.read(ReadDeviceAddr, (char*)tmp, NumByteToRead, false); } if(ret) return -1; if(NumByteToRead>1) { /* swap data endianess */ for(i=0; i<NumByteToRead; i++) { pBuffer[i] = tmp[NumByteToRead-1-i]; } } else { memcpy(pBuffer, tmp, NumByteToRead); } return 0; } /******************************************************************************/ int VL6180X::read_id(uint8_t *id) { return VL6180X_RdByte(_device, IDENTIFICATION_MODEL_ID, id); } int VL6180X::start_measurement(operating_mode_t operating_mode) { switch (operating_mode) { case(range_single_shot_polling): return VL6180X_WrByte(_device, SYSRANGE_START, MODE_START_STOP|MODE_SINGLESHOT); case(als_single_shot_polling): return VL6180X_WrByte(_device, SYSALS_START, MODE_START_STOP|MODE_SINGLESHOT); default: return INVALID_PARAMS; } } int VL6180X::stop_measurement(operating_mode_t operating_mode) { switch(operating_mode) { case(range_single_shot_polling): return VL6180X_RangeSetSystemMode(_device, MODE_SINGLESHOT); case(als_single_shot_polling): return VL6180X_AlsSetSystemMode(_device, MODE_SINGLESHOT); default: return INVALID_PARAMS; } } int VL6180X::IsPresent() { int status; uint8_t id; status=read_id(&id); if(status) VL6180X_ErrLog("Failed to read ID device. _device not present!\n\r"); return status; } /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/