ST Expansion SW Team / VL53L3CX_mbed

Dependencies:   X_NUCLEO_COMMON ST_INTERFACES

Dependents:   VL53L3CX_NoShield_1Sensor_poll_Mb06x VL53L3_NoShield_1Sensor_polling_Mb63 X_NUCLEO_53L3A2 53L3A2_Ranging

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers vl53lx_api.c Source File

vl53lx_api.c

00001 
00002 // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
00003 /******************************************************************************
00004  * Copyright (c) 2020, STMicroelectronics - All Rights Reserved
00005 
00006  This file is part of VL53LX and is dual licensed,
00007  either GPL-2.0+
00008  or 'BSD 3-clause "New" or "Revised" License' , at your option.
00009  ******************************************************************************
00010  */
00011 
00012 
00013 
00014 
00015 
00016 
00017 #include "vl53lx_api.h"
00018 #include "vl53lx_register_settings.h"
00019 #include "vl53lx_register_funcs.h"
00020 #include "vl53lx_core.h"
00021 #include "vl53lx_api_calibration.h"
00022 #include "vl53lx_wait.h"
00023 #include "vl53lx_preset_setup.h"
00024 #include "vl53lx_api_debug.h"
00025 #include "vl53lx_api_core.h"
00026 #include "vl53lx_nvm.h"
00027 #include "spi_interface.h"
00028 
00029 
00030 
00031 #define ZONE_CHECK 5
00032 
00033 #define LOG_FUNCTION_START(fmt, ...) \
00034     _LOG_FUNCTION_START(VL53LX_TRACE_MODULE_API, fmt, ##__VA_ARGS__)
00035 #define LOG_FUNCTION_END(status, ...) \
00036     _LOG_FUNCTION_END(VL53LX_TRACE_MODULE_API, status, ##__VA_ARGS__)
00037 #define LOG_FUNCTION_END_FMT(status, fmt, ...) \
00038     _LOG_FUNCTION_END_FMT(VL53LX_TRACE_MODULE_API, status, \
00039             fmt, ##__VA_ARGS__)
00040 
00041 #ifdef VL53LX_LOG_ENABLE
00042 #define trace_print(level, ...) trace_print_module_function(\
00043         VL53LX_TRACE_MODULE_API, level, VL53LX_TRACE_FUNCTION_NONE, \
00044         ##__VA_ARGS__)
00045 #endif
00046 
00047 #ifndef MIN
00048 #define MIN(v1, v2) ((v1) < (v2) ? (v1) : (v2))
00049 #endif
00050 #ifndef MAX
00051 #define MAX(v1, v2) ((v1) < (v2) ? (v2) : (v1))
00052 #endif
00053 
00054 #define DMAX_REFLECTANCE_IDX 2
00055 
00056 
00057 
00058 #define LOWPOWER_AUTO_VHV_LOOP_DURATION_US 245
00059 #define LOWPOWER_AUTO_OVERHEAD_BEFORE_A_RANGING 1448
00060 #define LOWPOWER_AUTO_OVERHEAD_BETWEEN_A_B_RANGING 2100
00061 
00062 #define FDA_MAX_TIMING_BUDGET_US 550000
00063 #define L4_FDA_MAX_TIMING_BUDGET_US 200000
00064 
00065 
00066 
00067 
00068 static int32_t BDTable[VL53LX_TUNING_MAX_TUNABLE_KEY] = {
00069         TUNING_VERSION,
00070         TUNING_PROXY_MIN,
00071         TUNING_SINGLE_TARGET_XTALK_TARGET_DISTANCE_MM,
00072         TUNING_SINGLE_TARGET_XTALK_SAMPLE_NUMBER,
00073         TUNING_MIN_AMBIENT_DMAX_VALID,
00074         TUNING_MAX_SIMPLE_OFFSET_CALIBRATION_SAMPLE_NUMBER,
00075         TUNING_XTALK_FULL_ROI_TARGET_DISTANCE_MM,
00076         TUNING_SIMPLE_OFFSET_CALIBRATION_REPEAT,
00077         TUNING_XTALK_FULL_ROI_BIN_SUM_MARGIN,
00078         TUNING_XTALK_FULL_ROI_DEFAULT_OFFSET,
00079         TUNING_ZERO_DISTANCE_OFFSET_NON_LINEAR_FACTOR_DEFAULT
00080 };
00081 
00082 static VL53LX_Error SetInterMeasurementPeriodMilliSeconds(VL53LX_DEV Dev,
00083         uint32_t InterMeasurementPeriodMilliSeconds);
00084 
00085 static VL53LX_Error GetInterMeasurementPeriodMilliSeconds(VL53LX_DEV Dev,
00086     uint32_t *pInterMeasurementPeriodMilliSeconds);
00087 
00088 static VL53LX_Error ComputeDevicePresetMode(
00089         VL53LX_DistanceModes DistanceMode,
00090         VL53LX_DevicePresetModes *pDevicePresetMode);
00091 
00092 static VL53LX_Error SetPresetModeL3CX(VL53LX_DEV Dev,
00093         VL53LX_DistanceModes DistanceMode,
00094         uint32_t inter_measurement_period_ms);
00095 
00096 static int IsL4(VL53LX_DEV Dev);
00097 
00098 static VL53LX_Error CheckValidRectRoi(VL53LX_UserRoi_t ROI);
00099 
00100 
00101 VL53LX_Error VL53LX_GetVersion(VL53LX_Version_t *pVersion)
00102 {
00103     VL53LX_Error Status = VL53LX_ERROR_NONE;
00104 
00105     LOG_FUNCTION_START("");
00106 
00107     pVersion->major  = VL53LX_IMPLEMENTATION_VER_MAJOR;
00108     pVersion->minor  = VL53LX_IMPLEMENTATION_VER_MINOR;
00109     pVersion->build  = VL53LX_IMPLEMENTATION_VER_SUB;
00110 
00111     pVersion->revision  = VL53LX_IMPLEMENTATION_VER_REVISION;
00112 
00113     LOG_FUNCTION_END(Status);
00114     return Status;
00115 }
00116 
00117 VL53LX_Error VL53LX_GetProductRevision(VL53LX_DEV Dev,
00118     uint8_t *pProductRevisionMajor, uint8_t *pProductRevisionMinor)
00119 {
00120     VL53LX_Error Status = VL53LX_ERROR_NONE;
00121     uint8_t revision_id;
00122     VL53LX_LLDriverData_t   *pLLData;
00123 
00124     LOG_FUNCTION_START("");
00125 
00126     pLLData =  VL53LXDevStructGetLLDriverHandle(Dev);
00127     revision_id = pLLData->nvm_copy_data.identification__revision_id;
00128     *pProductRevisionMajor = 1;
00129     *pProductRevisionMinor = (revision_id & 0xF0) >> 4;
00130 
00131     LOG_FUNCTION_END(Status);
00132     return Status;
00133 
00134 }
00135 
00136 VL53LX_Error VL53LX_GetDeviceInfo(VL53LX_DEV Dev,
00137     VL53LX_DeviceInfo_t *pVL53LX_DeviceInfo)
00138 {
00139     VL53LX_Error Status = VL53LX_ERROR_NONE;
00140     uint8_t revision_id;
00141     VL53LX_LLDriverData_t   *pLLData;
00142 
00143     LOG_FUNCTION_START("");
00144 
00145     pLLData =  VL53LXDevStructGetLLDriverHandle(Dev);
00146 
00147     pVL53LX_DeviceInfo->ProductType  =
00148             pLLData->nvm_copy_data.identification__module_type;
00149 
00150     revision_id = pLLData->nvm_copy_data.identification__revision_id;
00151     pVL53LX_DeviceInfo->ProductRevisionMajor  = 1;
00152     pVL53LX_DeviceInfo->ProductRevisionMinor  = (revision_id & 0xF0) >> 4;
00153 
00154     LOG_FUNCTION_END(Status);
00155     return Status;
00156 }
00157 
00158 VL53LX_Error VL53LX_GetUID(VL53LX_DEV Dev, uint64_t *pUid)
00159 {
00160     VL53LX_Error Status = VL53LX_ERROR_NONE;
00161     uint8_t fmtdata[8];
00162 
00163     LOG_FUNCTION_START("");
00164 
00165     Status = VL53LX_read_nvm_raw_data(Dev,
00166             (uint8_t)(0x1F8 >> 2),
00167             (uint8_t)(8 >> 2),
00168             fmtdata);
00169     memcpy(pUid, fmtdata, sizeof(uint64_t));
00170 
00171     LOG_FUNCTION_END(Status);
00172     return Status;
00173 }
00174 
00175 
00176 
00177 VL53LX_Error VL53LX_SetDeviceAddress(VL53LX_DEV Dev, uint8_t DeviceAddress)
00178 {
00179 
00180     VL53LX_Error Status = VL53LX_ERROR_NONE;
00181     VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev);
00182     VL53LX_static_nvm_managed_t  *pdata = &(pdev->stat_nvm);
00183 
00184     LOG_FUNCTION_START("");
00185         printf("VL53LX_SetDeviceAddress VL53LX_WrByte from  %d  to %d\n",Dev->IO.Address,DeviceAddress);
00186 
00187     Status = VL53LX_WrByte(Dev, VL53LX_I2C_SLAVE__DEVICE_ADDRESS,
00188             DeviceAddress / 2);
00189         printf("VL53LX_SetDeviceAddress VL53LX_WrByte status %d\n",Status);
00190     pdata->i2c_slave__device_address = (DeviceAddress / 2) & 0x7F;
00191     Dev->IO.Address = DeviceAddress;
00192 
00193     LOG_FUNCTION_END(Status);
00194 
00195     return Status;
00196 }
00197 
00198 
00199 VL53LX_Error VL53LX_DataInit(VL53LX_DEV Dev)
00200 {
00201     VL53LX_Error Status = VL53LX_ERROR_NONE;
00202     VL53LX_LLDriverData_t *pdev;
00203     uint8_t  measurement_mode;
00204 
00205     LOG_FUNCTION_START("");
00206 
00207 
00208 #ifdef USE_I2C_2V8
00209     Status = VL53LX_RdByte(Dev, VL53LX_PAD_I2C_HV__EXTSUP_CONFIG, &i);
00210     if (Status == VL53LX_ERROR_NONE) {
00211         i = (i & 0xfe) | 0x01;
00212         Status = VL53LX_WrByte(Dev, VL53LX_PAD_I2C_HV__EXTSUP_CONFIG,
00213                 i);
00214     }
00215 #endif
00216 
00217     if (Status == VL53LX_ERROR_NONE)
00218         Status = VL53LX_data_init(Dev, 1);
00219 
00220     Status = SetPresetModeL3CX(Dev,
00221             VL53LX_DISTANCEMODE_MEDIUM,
00222             1000);
00223 
00224 
00225     if (Status == VL53LX_ERROR_NONE)
00226         Status = VL53LX_SetMeasurementTimingBudgetMicroSeconds(Dev,
00227                 33333);
00228 
00229     if (Status == VL53LX_ERROR_NONE)
00230         Status = SetInterMeasurementPeriodMilliSeconds(Dev, 1000);
00231 
00232     if (Status == VL53LX_ERROR_NONE) {
00233         pdev = VL53LXDevStructGetLLDriverHandle(Dev);
00234         memset(&pdev->per_vcsel_cal_data, 0,
00235                 sizeof(pdev->per_vcsel_cal_data));
00236     }
00237 
00238     if (Status == VL53LX_ERROR_NONE) {
00239         Status = VL53LX_set_dmax_mode(Dev,
00240             VL53LX_DEVICEDMAXMODE__CUST_CAL_DATA);
00241     }
00242 
00243 
00244     if (Status == VL53LX_ERROR_NONE)
00245         Status = VL53LX_SmudgeCorrectionEnable(Dev,
00246             VL53LX_SMUDGE_CORRECTION_NONE);
00247 
00248     measurement_mode  = VL53LX_DEVICEMEASUREMENTMODE_BACKTOBACK;
00249     VL53LXDevDataSet(Dev, LLData.measurement_mode, measurement_mode);
00250 
00251     VL53LXDevDataSet(Dev, CurrentParameters.DistanceMode,
00252             VL53LX_DISTANCEMODE_MEDIUM);
00253 
00254     LOG_FUNCTION_END(Status);
00255     return Status;
00256 }
00257 
00258 
00259 VL53LX_Error VL53LX_WaitDeviceBooted(VL53LX_DEV Dev)
00260 {
00261     VL53LX_Error Status = VL53LX_ERROR_NONE;
00262 
00263     LOG_FUNCTION_START("");
00264 
00265     Status = VL53LX_poll_for_boot_completion(Dev,
00266             VL53LX_BOOT_COMPLETION_POLLING_TIMEOUT_MS);
00267 
00268     LOG_FUNCTION_END(Status);
00269     return Status;
00270 }
00271 
00272 
00273 
00274 
00275 static VL53LX_Error ComputeDevicePresetMode(
00276         VL53LX_DistanceModes DistanceMode,
00277         VL53LX_DevicePresetModes *pDevicePresetMode)
00278 {
00279     VL53LX_Error Status = VL53LX_ERROR_NONE;
00280 
00281     uint8_t DistIdx;
00282     VL53LX_DevicePresetModes RangingModes[3] = {
00283         VL53LX_DEVICEPRESETMODE_HISTOGRAM_SHORT_RANGE,
00284         VL53LX_DEVICEPRESETMODE_HISTOGRAM_MEDIUM_RANGE,
00285         VL53LX_DEVICEPRESETMODE_HISTOGRAM_LONG_RANGE};
00286 
00287     switch (DistanceMode) {
00288     case VL53LX_DISTANCEMODE_SHORT:
00289         DistIdx = 0;
00290         break;
00291     case VL53LX_DISTANCEMODE_MEDIUM:
00292         DistIdx = 1;
00293         break;
00294     default:
00295         DistIdx = 2;
00296     }
00297 
00298     *pDevicePresetMode = RangingModes[DistIdx];
00299 
00300     return Status;
00301 }
00302 
00303 static VL53LX_Error SetPresetModeL3CX(VL53LX_DEV Dev,
00304         VL53LX_DistanceModes DistanceMode,
00305         uint32_t inter_measurement_period_ms)
00306 {
00307     VL53LX_Error Status = VL53LX_ERROR_NONE;
00308     VL53LX_DevicePresetModes   device_preset_mode;
00309     uint8_t measurement_mode;
00310     uint16_t dss_config__target_total_rate_mcps;
00311     uint32_t phasecal_config_timeout_us;
00312     uint32_t mm_config_timeout_us;
00313     uint32_t lld_range_config_timeout_us;
00314 
00315     LOG_FUNCTION_START("");
00316 
00317     measurement_mode  = VL53LX_DEVICEMEASUREMENTMODE_BACKTOBACK;
00318 
00319     Status = ComputeDevicePresetMode(DistanceMode,
00320             &device_preset_mode);
00321 
00322     if (Status == VL53LX_ERROR_NONE)
00323         Status =  VL53LX_get_preset_mode_timing_cfg(Dev,
00324                 device_preset_mode,
00325                 &dss_config__target_total_rate_mcps,
00326                 &phasecal_config_timeout_us,
00327                 &mm_config_timeout_us,
00328                 &lld_range_config_timeout_us);
00329 
00330     if (Status == VL53LX_ERROR_NONE)
00331         Status = VL53LX_set_preset_mode(
00332                 Dev,
00333                 device_preset_mode,
00334                 dss_config__target_total_rate_mcps,
00335                 phasecal_config_timeout_us,
00336                 mm_config_timeout_us,
00337                 lld_range_config_timeout_us,
00338                 inter_measurement_period_ms);
00339 
00340     if (Status == VL53LX_ERROR_NONE)
00341         VL53LXDevDataSet(Dev, LLData.measurement_mode,
00342                 measurement_mode);
00343 
00344     LOG_FUNCTION_END(Status);
00345     return Status;
00346 }
00347 
00348 static int IsL4(VL53LX_DEV Dev)
00349 {
00350     int devL4 = 0;
00351     VL53LX_LLDriverData_t *pDev;
00352     pDev = VL53LXDevStructGetLLDriverHandle(Dev);
00353 
00354     if ((pDev->nvm_copy_data.identification__module_type == 0xAA) &&
00355         (pDev->nvm_copy_data.identification__model_id == 0xEB))
00356         devL4 = 1;
00357     return devL4;
00358 }
00359 
00360 static VL53LX_Error CheckValidRectRoi(VL53LX_UserRoi_t ROI)
00361 {
00362     VL53LX_Error Status = VL53LX_ERROR_NONE;
00363 
00364     LOG_FUNCTION_START("");
00365 
00366 
00367     if ((ROI.TopLeftX  > 15) || (ROI.TopLeftY  > 15) ||
00368         (ROI.BotRightX  > 15) || (ROI.BotRightY  > 15))
00369         Status = VL53LX_ERROR_INVALID_PARAMS;
00370 
00371     if ((ROI.TopLeftX  > ROI.BotRightX ) || (ROI.TopLeftY  < ROI.BotRightY ))
00372         Status = VL53LX_ERROR_INVALID_PARAMS;
00373 
00374     LOG_FUNCTION_END(Status);
00375     return Status;
00376 }
00377 
00378 
00379 VL53LX_Error VL53LX_SetDistanceMode(VL53LX_DEV Dev,
00380         VL53LX_DistanceModes DistanceMode)
00381 {
00382     VL53LX_Error Status = VL53LX_ERROR_NONE;
00383     uint32_t inter_measurement_period_ms;
00384     uint32_t TimingBudget;
00385     uint32_t MmTimeoutUs;
00386     uint32_t PhaseCalTimeoutUs;
00387 
00388     LOG_FUNCTION_START("%d", (int)DistanceMode);
00389 
00390 
00391 
00392     if ((DistanceMode != VL53LX_DISTANCEMODE_SHORT) &&
00393         (DistanceMode != VL53LX_DISTANCEMODE_MEDIUM) &&
00394         (DistanceMode != VL53LX_DISTANCEMODE_LONG))
00395         return VL53LX_ERROR_INVALID_PARAMS;
00396 
00397     if (IsL4(Dev) && (DistanceMode == VL53LX_DISTANCEMODE_SHORT))
00398         return VL53LX_ERROR_INVALID_PARAMS;
00399 
00400     inter_measurement_period_ms =  VL53LXDevDataGet(Dev,
00401                 LLData.inter_measurement_period_ms);
00402 
00403     if (Status == VL53LX_ERROR_NONE)
00404         Status = VL53LX_get_timeouts_us(Dev, &PhaseCalTimeoutUs,
00405             &MmTimeoutUs, &TimingBudget);
00406 
00407     if (Status == VL53LX_ERROR_NONE)
00408         Status = SetPresetModeL3CX(Dev,
00409                 DistanceMode,
00410                 inter_measurement_period_ms);
00411 
00412     if (Status == VL53LX_ERROR_NONE) {
00413         VL53LXDevDataSet(Dev, CurrentParameters.DistanceMode,
00414                 DistanceMode);
00415     }
00416 
00417     if (Status == VL53LX_ERROR_NONE) {
00418         Status = VL53LX_set_timeouts_us(Dev, PhaseCalTimeoutUs,
00419             MmTimeoutUs, TimingBudget);
00420 
00421         if (Status == VL53LX_ERROR_NONE)
00422             VL53LXDevDataSet(Dev, LLData.range_config_timeout_us,
00423                 TimingBudget);
00424     }
00425 
00426     LOG_FUNCTION_END(Status);
00427     return Status;
00428 }
00429 
00430 VL53LX_Error VL53LX_GetDistanceMode(VL53LX_DEV Dev,
00431     VL53LX_DistanceModes *pDistanceMode)
00432 {
00433     VL53LX_Error Status = VL53LX_ERROR_NONE;
00434 
00435     LOG_FUNCTION_START("");
00436 
00437     *pDistanceMode = VL53LXDevDataGet(Dev, CurrentParameters.DistanceMode);
00438 
00439     LOG_FUNCTION_END(Status);
00440     return Status;
00441 }
00442 
00443 
00444 VL53LX_Error VL53LX_SetMeasurementTimingBudgetMicroSeconds(VL53LX_DEV Dev,
00445     uint32_t MeasurementTimingBudgetMicroSeconds)
00446 {
00447     VL53LX_Error Status = VL53LX_ERROR_NONE;
00448     uint32_t TimingGuard;
00449     uint32_t divisor;
00450     uint32_t TimingBudget;
00451     uint32_t MmTimeoutUs;
00452     uint32_t PhaseCalTimeoutUs;
00453     uint32_t FDAMaxTimingBudgetUs = FDA_MAX_TIMING_BUDGET_US;
00454 
00455     LOG_FUNCTION_START("");
00456 
00457 
00458     if (MeasurementTimingBudgetMicroSeconds > 10000000)
00459         Status = VL53LX_ERROR_INVALID_PARAMS;
00460 
00461     if (Status == VL53LX_ERROR_NONE)
00462         Status = VL53LX_get_timeouts_us(Dev,
00463             &PhaseCalTimeoutUs,
00464             &MmTimeoutUs,
00465             &TimingBudget);
00466 
00467     TimingGuard = 1700;
00468     divisor = 6;
00469 
00470     if (IsL4(Dev))
00471         FDAMaxTimingBudgetUs = L4_FDA_MAX_TIMING_BUDGET_US;
00472 
00473     if (MeasurementTimingBudgetMicroSeconds <= TimingGuard)
00474         Status = VL53LX_ERROR_INVALID_PARAMS;
00475     else {
00476         TimingBudget = (MeasurementTimingBudgetMicroSeconds
00477                 - TimingGuard);
00478     }
00479 
00480     if (Status == VL53LX_ERROR_NONE) {
00481         if (TimingBudget > FDAMaxTimingBudgetUs)
00482             Status = VL53LX_ERROR_INVALID_PARAMS;
00483         else {
00484             TimingBudget /= divisor;
00485             Status = VL53LX_set_timeouts_us(
00486                 Dev,
00487                 PhaseCalTimeoutUs,
00488                 MmTimeoutUs,
00489                 TimingBudget);
00490         }
00491 
00492         if (Status == VL53LX_ERROR_NONE)
00493             VL53LXDevDataSet(Dev,
00494                 LLData.range_config_timeout_us,
00495                 TimingBudget);
00496     }
00497 
00498     if (Status == VL53LX_ERROR_NONE) {
00499         VL53LXDevDataSet(Dev,
00500             CurrentParameters.MeasurementTimingBudgetMicroSeconds,
00501             MeasurementTimingBudgetMicroSeconds);
00502     }
00503 
00504     LOG_FUNCTION_END(Status);
00505     return Status;
00506 }
00507 
00508 
00509 VL53LX_Error VL53LX_GetMeasurementTimingBudgetMicroSeconds(VL53LX_DEV Dev,
00510     uint32_t *pMeasurementTimingBudgetMicroSeconds)
00511 {
00512     VL53LX_Error Status = VL53LX_ERROR_NONE;
00513     uint32_t MmTimeoutUs = 0;
00514     uint32_t RangeTimeoutUs = 0;
00515     uint32_t PhaseCalTimeoutUs = 0;
00516 
00517     LOG_FUNCTION_START("");
00518 
00519     *pMeasurementTimingBudgetMicroSeconds = 0;
00520 
00521     if (Status == VL53LX_ERROR_NONE)
00522         Status = VL53LX_get_timeouts_us(Dev,
00523             &PhaseCalTimeoutUs,
00524             &MmTimeoutUs,
00525             &RangeTimeoutUs);
00526 
00527     if (Status == VL53LX_ERROR_NONE)
00528         *pMeasurementTimingBudgetMicroSeconds = (6 * RangeTimeoutUs) +
00529         1700;
00530 
00531     LOG_FUNCTION_END(Status);
00532     return Status;
00533 }
00534 
00535 
00536 
00537 static VL53LX_Error SetInterMeasurementPeriodMilliSeconds(VL53LX_DEV Dev,
00538     uint32_t InterMeasurementPeriodMilliSeconds)
00539 {
00540     VL53LX_Error Status = VL53LX_ERROR_NONE;
00541     uint32_t adjustedIMP;
00542 
00543     LOG_FUNCTION_START("");
00544 
00545 
00546     adjustedIMP = InterMeasurementPeriodMilliSeconds;
00547     adjustedIMP += (adjustedIMP * 64) / 1000;
00548 
00549     Status = VL53LX_set_inter_measurement_period_ms(Dev,
00550             adjustedIMP);
00551 
00552     LOG_FUNCTION_END(Status);
00553     return Status;
00554 }
00555 
00556 static VL53LX_Error GetInterMeasurementPeriodMilliSeconds(VL53LX_DEV Dev,
00557     uint32_t *pInterMeasurementPeriodMilliSeconds)
00558 {
00559     VL53LX_Error Status = VL53LX_ERROR_NONE;
00560     uint32_t adjustedIMP;
00561 
00562     LOG_FUNCTION_START("");
00563 
00564     Status = VL53LX_get_inter_measurement_period_ms(Dev, &adjustedIMP);
00565 
00566     adjustedIMP -= (adjustedIMP * 64) / 1000;
00567     *pInterMeasurementPeriodMilliSeconds = adjustedIMP;
00568 
00569 
00570     LOG_FUNCTION_END(Status);
00571     return Status;
00572 }
00573 
00574 
00575 
00576 
00577 
00578 VL53LX_Error VL53LX_SetUserROI(VL53LX_DEV Dev,
00579         VL53LX_UserRoi_t *pRoi)
00580 {
00581     VL53LX_Error Status = VL53LX_ERROR_NONE;
00582     VL53LX_zone_config_t  zone_cfg;
00583     uint8_t x_centre, y_centre, width, height;
00584 
00585     Status = CheckValidRectRoi(*pRoi);
00586     if (Status != VL53LX_ERROR_NONE)
00587         return VL53LX_ERROR_INVALID_PARAMS;
00588 
00589     x_centre = (pRoi->BotRightX  + pRoi->TopLeftX   + 1) / 2;
00590     y_centre = (pRoi->TopLeftY   + pRoi->BotRightY  + 1) / 2;
00591     width =    (pRoi->BotRightX  - pRoi->TopLeftX );
00592     height =   (pRoi->TopLeftY   - pRoi->BotRightY );
00593     zone_cfg.max_zones = 1;
00594     zone_cfg.active_zones = 0;
00595     zone_cfg.user_zones[0].x_centre = x_centre;
00596     zone_cfg.user_zones[0].y_centre = y_centre;
00597     zone_cfg.user_zones[0].width = width;
00598     zone_cfg.user_zones[0].height = height;
00599     if ((width < 3) || (height < 3))
00600         Status = VL53LX_ERROR_INVALID_PARAMS;
00601     else
00602         Status =  VL53LX_set_zone_config(Dev, &zone_cfg);
00603 
00604     LOG_FUNCTION_END(Status);
00605     return Status;
00606 }
00607 
00608 VL53LX_Error VL53LX_GetUserROI(VL53LX_DEV Dev,
00609         VL53LX_UserRoi_t *pRoi)
00610 {
00611     VL53LX_Error Status = VL53LX_ERROR_NONE;
00612     VL53LX_zone_config_t zone_cfg;
00613     uint8_t  TopLeftX;
00614     uint8_t  TopLeftY;
00615     uint8_t  BotRightX;
00616     uint8_t  BotRightY;
00617 
00618     LOG_FUNCTION_START("");
00619 
00620     VL53LX_get_zone_config(Dev, &zone_cfg);
00621 
00622     TopLeftX = (2 * zone_cfg.user_zones[0].x_centre -
00623         zone_cfg.user_zones[0].width) >> 1;
00624     TopLeftY = (2 * zone_cfg.user_zones[0].y_centre +
00625         zone_cfg.user_zones[0].height) >> 1;
00626     BotRightX = (2 * zone_cfg.user_zones[0].x_centre +
00627         zone_cfg.user_zones[0].width) >> 1;
00628     BotRightY = (2 * zone_cfg.user_zones[0].y_centre -
00629         zone_cfg.user_zones[0].height) >> 1;
00630     pRoi->TopLeftX  = TopLeftX;
00631     pRoi->TopLeftY  = TopLeftY;
00632     pRoi->BotRightX  = BotRightX;
00633     pRoi->BotRightY  = BotRightY;
00634 
00635     LOG_FUNCTION_END(Status);
00636     return Status;
00637 }
00638 
00639 
00640 
00641 
00642 
00643 VL53LX_Error VL53LX_StartMeasurement(VL53LX_DEV Dev)
00644 {
00645 #define TIMED_MODE_TIMING_GUARD_MILLISECONDS 4
00646     VL53LX_Error Status = VL53LX_ERROR_NONE;
00647     uint8_t DeviceMeasurementMode;
00648     VL53LX_Error lStatus;
00649     uint32_t MTBus, IMPms;
00650     uint8_t i;
00651     VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev);
00652 
00653     LOG_FUNCTION_START("");
00654 
00655     VL53LX_load_patch(Dev);
00656     for (i = 0; i < VL53LX_MAX_RANGE_RESULTS; i++) {
00657         pdev->PreviousRangeMilliMeter[i] = 0;
00658         pdev->PreviousRangeStatus[i] = 255;
00659         pdev->PreviousExtendedRange[i] = 0;
00660     }
00661     pdev->PreviousStreamCount = 0;
00662 
00663     DeviceMeasurementMode = VL53LXDevDataGet(Dev, LLData.measurement_mode);
00664 
00665 
00666     if ((Status == VL53LX_ERROR_NONE) &&
00667         (DeviceMeasurementMode == VL53LX_DEVICEMEASUREMENTMODE_TIMED)) {
00668         lStatus = VL53LX_GetMeasurementTimingBudgetMicroSeconds(Dev,
00669                 &MTBus);
00670 
00671         MTBus /= 1000;
00672         lStatus = GetInterMeasurementPeriodMilliSeconds(Dev,
00673                 &IMPms);
00674 
00675         SUPPRESS_UNUSED_WARNING(lStatus);
00676         if (IMPms < MTBus + TIMED_MODE_TIMING_GUARD_MILLISECONDS)
00677             Status = VL53LX_ERROR_INVALID_PARAMS;
00678     }
00679 
00680     if (Status == VL53LX_ERROR_NONE)
00681         Status = VL53LX_init_and_start_range(
00682                 Dev,
00683                 DeviceMeasurementMode,
00684                 VL53LX_DEVICECONFIGLEVEL_FULL);
00685                 
00686     if ( Dev->EnableInterrupt == 1) 
00687     {
00688          enable_interrupt_measure_detection_irq();
00689          attach_interrupt_measure_detection_irq(Dev->Interrupt_Func );
00690     }
00691      
00692     LOG_FUNCTION_END(Status);
00693     return Status;
00694 }
00695 
00696 VL53LX_Error VL53LX_StopMeasurement(VL53LX_DEV Dev)
00697 {
00698     VL53LX_Error Status = VL53LX_ERROR_NONE;
00699 
00700     LOG_FUNCTION_START("");
00701                     
00702     if ( Dev->EnableInterrupt == 1) 
00703     {
00704          disable_interrupt_measure_detection_irq();
00705     }
00706 
00707     Status = VL53LX_stop_range(Dev);
00708 
00709     VL53LX_unload_patch(Dev);
00710 
00711     LOG_FUNCTION_END(Status);
00712     return Status;
00713 }
00714 
00715 
00716 VL53LX_Error VL53LX_ClearInterruptAndStartMeasurement(VL53LX_DEV Dev)
00717 {
00718     VL53LX_Error Status = VL53LX_ERROR_NONE;
00719     uint8_t DeviceMeasurementMode;
00720 
00721     LOG_FUNCTION_START("");
00722 
00723     DeviceMeasurementMode = VL53LXDevDataGet(Dev, LLData.measurement_mode);
00724 
00725     Status = VL53LX_clear_interrupt_and_enable_next_range(Dev,
00726             DeviceMeasurementMode);
00727 
00728     LOG_FUNCTION_END(Status);
00729     return Status;
00730 }
00731 
00732 
00733 VL53LX_Error VL53LX_GetMeasurementDataReady(VL53LX_DEV Dev,
00734     uint8_t *pMeasurementDataReady)
00735 {
00736     VL53LX_Error Status = VL53LX_ERROR_NONE;
00737 
00738     LOG_FUNCTION_START("");
00739 
00740     Status = VL53LX_is_new_data_ready(Dev, pMeasurementDataReady);
00741 
00742     LOG_FUNCTION_END(Status);
00743     return Status;
00744 }
00745 
00746 VL53LX_Error VL53LX_WaitMeasurementDataReady(VL53LX_DEV Dev)
00747 {
00748     VL53LX_Error Status = VL53LX_ERROR_NONE;
00749 
00750     LOG_FUNCTION_START("");
00751 
00752 
00753 
00754     Status = VL53LX_poll_for_range_completion(Dev,
00755             VL53LX_RANGE_COMPLETION_POLLING_TIMEOUT_MS);
00756 
00757     LOG_FUNCTION_END(Status);
00758     return Status;
00759 }
00760 
00761 static uint8_t ConvertStatusHisto(uint8_t FilteredRangeStatus)
00762 {
00763     uint8_t RangeStatus;
00764 
00765     switch (FilteredRangeStatus) {
00766     case VL53LX_DEVICEERROR_RANGEPHASECHECK:
00767         RangeStatus = VL53LX_RANGESTATUS_OUTOFBOUNDS_FAIL;
00768         break;
00769     case VL53LX_DEVICEERROR_SIGMATHRESHOLDCHECK:
00770         RangeStatus = VL53LX_RANGESTATUS_SIGMA_FAIL;
00771         break;
00772     case VL53LX_DEVICEERROR_RANGECOMPLETE_NO_WRAP_CHECK:
00773         RangeStatus =
00774             VL53LX_RANGESTATUS_RANGE_VALID_NO_WRAP_CHECK_FAIL;
00775         break;
00776     case VL53LX_DEVICEERROR_PHASECONSISTENCY:
00777         RangeStatus = VL53LX_RANGESTATUS_WRAP_TARGET_FAIL;
00778         break;
00779     case VL53LX_DEVICEERROR_PREV_RANGE_NO_TARGETS:
00780         RangeStatus = VL53LX_RANGESTATUS_TARGET_PRESENT_LACK_OF_SIGNAL;
00781         break;
00782     case VL53LX_DEVICEERROR_EVENTCONSISTENCY:
00783         RangeStatus = VL53LX_RANGESTATUS_WRAP_TARGET_FAIL;
00784         break;
00785     case VL53LX_DEVICEERROR_RANGECOMPLETE_MERGED_PULSE:
00786         RangeStatus = VL53LX_RANGESTATUS_RANGE_VALID_MERGED_PULSE;
00787         break;
00788     case VL53LX_DEVICEERROR_RANGECOMPLETE:
00789         RangeStatus = VL53LX_RANGESTATUS_RANGE_VALID;
00790         break;
00791     default:
00792         RangeStatus = VL53LX_RANGESTATUS_NONE;
00793     }
00794 
00795     return RangeStatus;
00796 }
00797 
00798 static VL53LX_Error SetTargetData(VL53LX_DEV Dev,
00799     uint8_t active_results, uint8_t streamcount, uint8_t iteration,
00800     uint8_t device_status, VL53LX_range_data_t *presults_data,
00801     VL53LX_TargetRangeData_t *pRangeData)
00802 {
00803     VL53LX_Error Status = VL53LX_ERROR_NONE;
00804     VL53LX_LLDriverData_t *pdev =
00805             VL53LXDevStructGetLLDriverHandle(Dev);
00806     VL53LX_tuning_parm_storage_t *tp =
00807             &(pdev->tuning_parms);
00808     uint8_t sequency;
00809     uint8_t FilteredRangeStatus;
00810     FixPoint1616_t AmbientRate;
00811     FixPoint1616_t SignalRate;
00812     FixPoint1616_t TempFix1616;
00813     int16_t Range, RangeDiff, RangeMillimeterInit;
00814     int32_t ExtendedRangeEnabled = 0;
00815     uint8_t uwr_status;
00816     int16_t AddOffset;
00817 
00818     SUPPRESS_UNUSED_WARNING(Dev);
00819 
00820     FilteredRangeStatus = presults_data->range_status & 0x1F;
00821 
00822     SignalRate = VL53LX_FIXPOINT97TOFIXPOINT1616(
00823         presults_data->peak_signal_count_rate_mcps);
00824     pRangeData->SignalRateRtnMegaCps 
00825         = SignalRate;
00826 
00827     AmbientRate = VL53LX_FIXPOINT97TOFIXPOINT1616(
00828         presults_data->ambient_count_rate_mcps);
00829     pRangeData->AmbientRateRtnMegaCps  = AmbientRate;
00830 
00831     TempFix1616 = VL53LX_FIXPOINT97TOFIXPOINT1616(
00832             presults_data->VL53LX_p_002);
00833 
00834     pRangeData->SigmaMilliMeter  = TempFix1616;
00835 
00836     pRangeData->RangeMilliMeter  = presults_data->median_range_mm;
00837     pRangeData->RangeMaxMilliMeter  = presults_data->max_range_mm;
00838     pRangeData->RangeMinMilliMeter  = presults_data->min_range_mm;
00839 
00840 
00841     switch (device_status) {
00842     case VL53LX_DEVICEERROR_MULTCLIPFAIL:
00843     case VL53LX_DEVICEERROR_VCSELWATCHDOGTESTFAILURE:
00844     case VL53LX_DEVICEERROR_VCSELCONTINUITYTESTFAILURE:
00845     case VL53LX_DEVICEERROR_NOVHVVALUEFOUND:
00846         pRangeData->RangeStatus  =  VL53LX_RANGESTATUS_HARDWARE_FAIL;
00847         break;
00848     case VL53LX_DEVICEERROR_USERROICLIP:
00849         pRangeData->RangeStatus  =  VL53LX_RANGESTATUS_MIN_RANGE_FAIL;
00850         break;
00851     default:
00852         pRangeData->RangeStatus  =  VL53LX_RANGESTATUS_RANGE_VALID;
00853     }
00854 
00855 
00856     if ((pRangeData->RangeStatus  ==  VL53LX_RANGESTATUS_RANGE_VALID) &&
00857         (active_results == 0)) {
00858         pRangeData->RangeStatus  =  VL53LX_RANGESTATUS_NONE;
00859         pRangeData->SignalRateRtnMegaCps  = 0;
00860         pRangeData->SigmaMilliMeter  = 0;
00861         pRangeData->RangeMilliMeter  = 8191;
00862         pRangeData->RangeMaxMilliMeter  = 8191;
00863         pRangeData->RangeMinMilliMeter  = 8191;
00864     }
00865 
00866 
00867     if (pRangeData->RangeStatus  ==  VL53LX_RANGESTATUS_RANGE_VALID)
00868         pRangeData->RangeStatus  =
00869             ConvertStatusHisto(FilteredRangeStatus);
00870 
00871 
00872 
00873     VL53LX_get_tuning_parm(Dev, VL53LX_TUNINGPARM_UWR_ENABLE,
00874             &ExtendedRangeEnabled);
00875 
00876     sequency = streamcount % 2;
00877     uwr_status = 1;
00878     RangeMillimeterInit = pRangeData->RangeMilliMeter ;
00879     AddOffset = 0;
00880 
00881     pRangeData->ExtendedRange  = 0;
00882 
00883     if (ExtendedRangeEnabled &&
00884         (pRangeData->RangeStatus  ==
00885             VL53LX_RANGESTATUS_WRAP_TARGET_FAIL ||
00886             pRangeData->RangeStatus  ==
00887             VL53LX_RANGESTATUS_OUTOFBOUNDS_FAIL)
00888         && (pdev->PreviousRangeStatus[iteration] ==
00889             VL53LX_RANGESTATUS_WRAP_TARGET_FAIL ||
00890             pdev->PreviousRangeStatus[iteration] ==
00891             VL53LX_RANGESTATUS_OUTOFBOUNDS_FAIL ||
00892             (pdev->PreviousRangeStatus[iteration] ==
00893             VL53LX_RANGESTATUS_RANGE_VALID &&
00894             pdev->PreviousExtendedRange[iteration] == 1)))
00895     {
00896         if (((pdev->PreviousStreamCount) ==
00897             (pdev->hist_data.result__stream_count - 1 ))
00898         || ((pdev->PreviousStreamCount) ==
00899             (pdev->hist_data.result__stream_count + 127)))
00900         {
00901         RangeDiff = pRangeData->RangeMilliMeter  -
00902             pdev->PreviousRangeMilliMeter[iteration];
00903 
00904         switch (pdev->preset_mode) {
00905             case VL53LX_DEVICEPRESETMODE_HISTOGRAM_SHORT_RANGE:
00906 
00907                 uwr_status = 0;
00908                 break;
00909 
00910             case VL53LX_DEVICEPRESETMODE_HISTOGRAM_MEDIUM_RANGE:
00911                 if (RangeDiff > tp->tp_uwr_med_z_1_min &&
00912                     RangeDiff < tp->tp_uwr_med_z_1_max &&
00913                     sequency == 1) {
00914                     AddOffset =
00915                     tp->tp_uwr_med_corr_z_1_rangeb;
00916                 }
00917                 else
00918                 if (RangeDiff < -tp->tp_uwr_med_z_1_min &&
00919                     RangeDiff > -tp->tp_uwr_med_z_1_max &&
00920                     sequency == 0) {
00921                     AddOffset =
00922                     tp->tp_uwr_med_corr_z_1_rangea;
00923                 }
00924                 else
00925                 if (RangeDiff > tp->tp_uwr_med_z_2_min &&
00926                     RangeDiff < tp->tp_uwr_med_z_2_max &&
00927                     sequency == 0) {
00928                     AddOffset =
00929                     tp->tp_uwr_med_corr_z_2_rangea;
00930                 }
00931                 else
00932                 if (RangeDiff < -tp->tp_uwr_med_z_2_min &&
00933                     RangeDiff > -tp->tp_uwr_med_z_2_max &&
00934                     sequency == 1) {
00935                     AddOffset =
00936                     tp->tp_uwr_med_corr_z_2_rangeb;
00937                 }
00938                 else
00939                 if (RangeDiff > tp->tp_uwr_med_z_3_min &&
00940                     RangeDiff < tp->tp_uwr_med_z_3_max &&
00941                     sequency == 1) {
00942                     AddOffset =
00943                     tp->tp_uwr_med_corr_z_3_rangeb;
00944                 }
00945                 else
00946                 if (RangeDiff < -tp->tp_uwr_med_z_3_min &&
00947                     RangeDiff > -tp->tp_uwr_med_z_3_max &&
00948                     sequency == 0) {
00949                     AddOffset =
00950                     tp->tp_uwr_med_corr_z_3_rangea;
00951                 }
00952                 else
00953                 if (RangeDiff > tp->tp_uwr_med_z_4_min &&
00954                     RangeDiff < tp->tp_uwr_med_z_4_max &&
00955                     sequency == 0) {
00956                     AddOffset =
00957                     tp->tp_uwr_med_corr_z_4_rangea;
00958                 }
00959                 else
00960                 if (RangeDiff < -tp->tp_uwr_med_z_4_min &&
00961                     RangeDiff > -tp->tp_uwr_med_z_4_max &&
00962                     sequency == 1) {
00963                     AddOffset =
00964                     tp->tp_uwr_med_corr_z_4_rangeb;
00965                 }
00966                 else
00967                 if (RangeDiff < tp->tp_uwr_med_z_5_max &&
00968                     RangeDiff > tp->tp_uwr_med_z_5_min) {
00969                     AddOffset =
00970                     tp->tp_uwr_med_corr_z_5_rangea;
00971                 } else
00972                     uwr_status = 0;
00973                 break;
00974 
00975             case VL53LX_DEVICEPRESETMODE_HISTOGRAM_LONG_RANGE:
00976                 if (RangeDiff > tp->tp_uwr_lng_z_1_min &&
00977                     RangeDiff < tp->tp_uwr_lng_z_1_max &&
00978                     sequency == 0) {
00979                     AddOffset =
00980                     tp->tp_uwr_lng_corr_z_1_rangea;
00981                 }
00982                 else
00983                 if (RangeDiff < -tp->tp_uwr_lng_z_1_min &&
00984                     RangeDiff > -tp->tp_uwr_lng_z_1_max &&
00985                     sequency == 1) {
00986                     AddOffset =
00987                     tp->tp_uwr_lng_corr_z_1_rangeb;
00988                 }
00989                 else
00990                 if (RangeDiff > tp->tp_uwr_lng_z_2_min &&
00991                     RangeDiff < tp->tp_uwr_lng_z_2_max &&
00992                     sequency == 1) {
00993                     AddOffset =
00994                     tp->tp_uwr_lng_corr_z_2_rangeb;
00995                 }
00996                 else
00997                 if (RangeDiff < -tp->tp_uwr_lng_z_2_min &&
00998                     RangeDiff > -tp->tp_uwr_lng_z_2_max &&
00999                     sequency == 0) {
01000                     AddOffset =
01001                     tp->tp_uwr_lng_corr_z_2_rangea;
01002                 }
01003                 else
01004                 if (RangeDiff < tp->tp_uwr_lng_z_3_max &&
01005                     RangeDiff > tp->tp_uwr_lng_z_3_min) {
01006                     AddOffset =
01007                     tp->tp_uwr_lng_corr_z_3_rangea;
01008                 }
01009                 else
01010                     uwr_status = 0;
01011                 break;
01012 
01013             default:
01014                 uwr_status = 0;
01015                 break;
01016             }
01017         }
01018 
01019         if (uwr_status) {
01020             pRangeData->RangeMilliMeter  += AddOffset;
01021             pRangeData->RangeMinMilliMeter  += AddOffset;
01022             pRangeData->RangeMaxMilliMeter  += AddOffset;
01023             pRangeData->ExtendedRange  = 1;
01024             pRangeData->RangeStatus  = 0;
01025         }
01026 
01027     }
01028 
01029     pdev->PreviousRangeMilliMeter[iteration] = RangeMillimeterInit;
01030     pdev->PreviousRangeStatus[iteration] = pRangeData->RangeStatus ;
01031     pdev->PreviousExtendedRange[iteration] = pRangeData->ExtendedRange ;
01032     pdev->PreviousStreamCount = pdev->hist_data.result__stream_count;
01033 
01034     Range = pRangeData->RangeMilliMeter ;
01035     if ((pRangeData->RangeStatus  ==  VL53LX_RANGESTATUS_RANGE_VALID) &&
01036         (Range < 0)) {
01037         if (Range < BDTable[VL53LX_TUNING_PROXY_MIN])
01038             pRangeData->RangeStatus  =
01039                      VL53LX_RANGESTATUS_RANGE_INVALID;
01040         else
01041             pRangeData->RangeMilliMeter  = 0;
01042     }
01043 
01044     return Status;
01045 }
01046 
01047 
01048 static VL53LX_Error SetMeasurementData(VL53LX_DEV Dev,
01049     VL53LX_range_results_t *presults,
01050     VL53LX_MultiRangingData_t *pMultiRangingData)
01051 {
01052     VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev);
01053     uint8_t i;
01054     uint8_t iteration;
01055     VL53LX_TargetRangeData_t *pRangeData;
01056     VL53LX_range_data_t *presults_data;
01057     VL53LX_Error Status = VL53LX_ERROR_NONE;
01058     uint8_t ActiveResults;
01059 
01060     pMultiRangingData->NumberOfObjectsFound  = presults->active_results;
01061     pMultiRangingData->HasXtalkValueChanged  =
01062             presults->smudge_corrector_data.new_xtalk_applied_flag;
01063 
01064 
01065     pMultiRangingData->TimeStamp  = 0;
01066 
01067     pMultiRangingData->StreamCount  = presults->stream_count;
01068 
01069     ActiveResults = presults->active_results;
01070     if (ActiveResults < 1)
01071 
01072         iteration = 1;
01073     else
01074         iteration = ActiveResults;
01075     for (i = 0; i < iteration; i++) {
01076         pRangeData = &(pMultiRangingData->RangeData [i]);
01077 
01078         presults_data = &(presults->VL53LX_p_003[i]);
01079         if (Status == VL53LX_ERROR_NONE)
01080             Status = SetTargetData(Dev, ActiveResults,
01081                     pMultiRangingData->StreamCount ,
01082                     i,
01083                     presults->device_status,
01084                     presults_data,
01085                     pRangeData);
01086 
01087         pMultiRangingData->EffectiveSpadRtnCount  =
01088                 presults_data->VL53LX_p_004;
01089 
01090     }
01091 
01092     for (i = iteration; i < VL53LX_MAX_RANGE_RESULTS; i++) {
01093         pdev->PreviousRangeMilliMeter[i] = 0;
01094         pdev->PreviousRangeStatus[i] = 255;
01095         pdev->PreviousExtendedRange[i] = 0;
01096     }
01097 
01098     return Status;
01099 }
01100 
01101 
01102 VL53LX_Error VL53LX_GetMultiRangingData(VL53LX_DEV Dev,
01103         VL53LX_MultiRangingData_t *pMultiRangingData)
01104 {
01105     VL53LX_Error Status = VL53LX_ERROR_NONE;
01106     VL53LX_LLDriverData_t *pdev =
01107             VL53LXDevStructGetLLDriverHandle(Dev);
01108     VL53LX_range_results_t *presults =
01109             (VL53LX_range_results_t *) pdev->wArea1;
01110 
01111     LOG_FUNCTION_START("");
01112 
01113 
01114     memset(pMultiRangingData, 0xFF,
01115         sizeof(VL53LX_MultiRangingData_t));
01116 
01117 
01118     Status = VL53LX_get_device_results(
01119                 Dev,
01120                 VL53LX_DEVICERESULTSLEVEL_FULL,
01121                 presults);
01122 
01123     Status = SetMeasurementData(Dev,
01124                     presults,
01125                     pMultiRangingData);
01126 
01127     LOG_FUNCTION_END(Status);
01128     return Status;
01129 }
01130 
01131 VL53LX_Error VL53LX_GetAdditionalData(VL53LX_DEV Dev,
01132         VL53LX_AdditionalData_t *pAdditionalData)
01133 {
01134     VL53LX_Error Status = VL53LX_ERROR_NONE;
01135 
01136     LOG_FUNCTION_START("");
01137 
01138     Status = VL53LX_get_additional_data(Dev, pAdditionalData);
01139 
01140     LOG_FUNCTION_END(Status);
01141     return Status;
01142 }
01143 
01144 
01145 
01146 
01147 
01148 
01149 VL53LX_Error VL53LX_SetTuningParameter(VL53LX_DEV Dev,
01150         uint16_t TuningParameterId, int32_t TuningParameterValue)
01151 {
01152     VL53LX_Error Status = VL53LX_ERROR_NONE;
01153 
01154     LOG_FUNCTION_START("");
01155 
01156     if (TuningParameterId ==
01157         VL53LX_TUNINGPARM_DYNXTALK_NODETECT_XTALK_OFFSET_KCPS)
01158         return VL53LX_ERROR_INVALID_PARAMS;
01159 
01160     if (TuningParameterId >= 32768)
01161         Status = VL53LX_set_tuning_parm(Dev,
01162             TuningParameterId,
01163             TuningParameterValue);
01164     else {
01165         if (TuningParameterId < VL53LX_TUNING_MAX_TUNABLE_KEY)
01166             BDTable[TuningParameterId] = TuningParameterValue;
01167         else
01168             Status = VL53LX_ERROR_INVALID_PARAMS;
01169     }
01170 
01171     LOG_FUNCTION_END(Status);
01172     return Status;
01173 }
01174 
01175 VL53LX_Error VL53LX_GetTuningParameter(VL53LX_DEV Dev,
01176         uint16_t TuningParameterId, int32_t *pTuningParameterValue)
01177 {
01178     VL53LX_Error Status = VL53LX_ERROR_NONE;
01179 
01180     LOG_FUNCTION_START("");
01181 
01182     if (TuningParameterId >= 32768)
01183         Status = VL53LX_get_tuning_parm(Dev,
01184             TuningParameterId,
01185             pTuningParameterValue);
01186     else {
01187         if (TuningParameterId < VL53LX_TUNING_MAX_TUNABLE_KEY)
01188             *pTuningParameterValue = BDTable[TuningParameterId];
01189         else
01190             Status = VL53LX_ERROR_INVALID_PARAMS;
01191     }
01192 
01193     LOG_FUNCTION_END(Status);
01194     return Status;
01195 }
01196 
01197 
01198 VL53LX_Error VL53LX_PerformRefSpadManagement(VL53LX_DEV Dev)
01199 {
01200     VL53LX_Error Status = VL53LX_ERROR_NONE;
01201     VL53LX_Error RawStatus;
01202     uint8_t dcrbuffer[24];
01203     uint8_t *commbuf;
01204     uint8_t numloc[2] = {5, 3};
01205     VL53LX_LLDriverData_t *pdev;
01206     VL53LX_customer_nvm_managed_t *pc;
01207     VL53LX_DistanceModes DistanceMode;
01208 
01209     LOG_FUNCTION_START("");
01210 
01211     pdev = VL53LXDevStructGetLLDriverHandle(Dev);
01212     pc = &pdev->customer;
01213 
01214     if (Status == VL53LX_ERROR_NONE) {
01215         DistanceMode = VL53LXDevDataGet(Dev,
01216                 CurrentParameters.DistanceMode);
01217         Status = VL53LX_run_ref_spad_char(Dev, &RawStatus);
01218 
01219         if (Status == VL53LX_ERROR_NONE)
01220             Status = VL53LX_SetDistanceMode(Dev, DistanceMode);
01221     }
01222 
01223     if (Status == VL53LX_WARNING_REF_SPAD_CHAR_RATE_TOO_HIGH) {
01224 
01225         Status = VL53LX_read_nvm_raw_data(Dev,
01226                 (uint8_t)(0xA0 >> 2),
01227                 (uint8_t)(24 >> 2),
01228                 dcrbuffer);
01229 
01230         if (Status == VL53LX_ERROR_NONE)
01231             Status = VL53LX_WriteMulti(Dev,
01232                 VL53LX_REF_SPAD_MAN__NUM_REQUESTED_REF_SPADS,
01233                 numloc, 2);
01234 
01235         if (Status == VL53LX_ERROR_NONE) {
01236             pc->ref_spad_man__num_requested_ref_spads = numloc[0];
01237             pc->ref_spad_man__ref_location = numloc[1];
01238         }
01239 
01240         if (Status == VL53LX_ERROR_NONE)
01241             commbuf = &dcrbuffer[16];
01242 
01243 
01244 
01245         if (Status == VL53LX_ERROR_NONE)
01246             Status = VL53LX_WriteMulti(Dev,
01247                 VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_REF_0,
01248                 commbuf, 6);
01249 
01250         if (Status == VL53LX_ERROR_NONE) {
01251             pc->global_config__spad_enables_ref_0 = commbuf[0];
01252             pc->global_config__spad_enables_ref_1 = commbuf[1];
01253             pc->global_config__spad_enables_ref_2 = commbuf[2];
01254             pc->global_config__spad_enables_ref_3 = commbuf[3];
01255             pc->global_config__spad_enables_ref_4 = commbuf[4];
01256             pc->global_config__spad_enables_ref_5 = commbuf[5];
01257         }
01258 
01259     }
01260 
01261     LOG_FUNCTION_END(Status);
01262     return Status;
01263 }
01264 
01265 
01266 VL53LX_Error VL53LX_SmudgeCorrectionEnable(VL53LX_DEV Dev,
01267         VL53LX_SmudgeCorrectionModes Mode)
01268 {
01269     VL53LX_Error Status = VL53LX_ERROR_NONE;
01270     VL53LX_Error s1 = VL53LX_ERROR_NONE;
01271     VL53LX_Error s2 = VL53LX_ERROR_NONE;
01272     VL53LX_Error s3 = VL53LX_ERROR_NONE;
01273 
01274     LOG_FUNCTION_START("");
01275 
01276     switch (Mode) {
01277     case VL53LX_SMUDGE_CORRECTION_NONE:
01278         s1 = VL53LX_dynamic_xtalk_correction_disable(Dev);
01279         s2 = VL53LX_dynamic_xtalk_correction_apply_disable(Dev);
01280         s3 = VL53LX_dynamic_xtalk_correction_single_apply_disable(Dev);
01281         break;
01282     case VL53LX_SMUDGE_CORRECTION_CONTINUOUS:
01283         s1 = VL53LX_dynamic_xtalk_correction_enable(Dev);
01284         s2 = VL53LX_dynamic_xtalk_correction_apply_enable(Dev);
01285         s3 = VL53LX_dynamic_xtalk_correction_single_apply_disable(Dev);
01286         break;
01287     case VL53LX_SMUDGE_CORRECTION_SINGLE:
01288         s1 = VL53LX_dynamic_xtalk_correction_enable(Dev);
01289         s2 = VL53LX_dynamic_xtalk_correction_apply_enable(Dev);
01290         s3 = VL53LX_dynamic_xtalk_correction_single_apply_enable(Dev);
01291         break;
01292     case VL53LX_SMUDGE_CORRECTION_DEBUG:
01293         s1 = VL53LX_dynamic_xtalk_correction_enable(Dev);
01294         s2 = VL53LX_dynamic_xtalk_correction_apply_disable(Dev);
01295         s3 = VL53LX_dynamic_xtalk_correction_single_apply_disable(Dev);
01296         break;
01297     default:
01298         Status = VL53LX_ERROR_INVALID_PARAMS;
01299         break;
01300     }
01301 
01302     if (Status == VL53LX_ERROR_NONE) {
01303         Status = s1;
01304         if (Status == VL53LX_ERROR_NONE)
01305             Status = s2;
01306         if (Status == VL53LX_ERROR_NONE)
01307             Status = s3;
01308     }
01309 
01310     LOG_FUNCTION_END(Status);
01311     return Status;
01312 }
01313 
01314 
01315 VL53LX_Error VL53LX_SetXTalkCompensationEnable(VL53LX_DEV Dev,
01316     uint8_t XTalkCompensationEnable)
01317 {
01318     VL53LX_Error Status = VL53LX_ERROR_NONE;
01319 
01320     LOG_FUNCTION_START("");
01321 
01322     if (XTalkCompensationEnable == 0)
01323         Status = VL53LX_disable_xtalk_compensation(Dev);
01324     else
01325         Status = VL53LX_enable_xtalk_compensation(Dev);
01326 
01327     LOG_FUNCTION_END(Status);
01328     return Status;
01329 }
01330 
01331 
01332 VL53LX_Error VL53LX_GetXTalkCompensationEnable(VL53LX_DEV Dev,
01333     uint8_t *pXTalkCompensationEnable)
01334 {
01335     VL53LX_Error Status = VL53LX_ERROR_NONE;
01336 
01337     LOG_FUNCTION_START("");
01338 
01339     VL53LX_get_xtalk_compensation_enable(
01340         Dev,
01341         pXTalkCompensationEnable);
01342 
01343     LOG_FUNCTION_END(Status);
01344     return Status;
01345 }
01346 
01347 VL53LX_Error VL53LX_PerformXTalkCalibration(VL53LX_DEV Dev)
01348 {
01349     VL53LX_Error Status = VL53LX_ERROR_NONE;
01350     VL53LX_Error UStatus;
01351     int16_t CalDistanceMm;
01352     VL53LX_xtalk_calibration_results_t xtalk;
01353 
01354     VL53LX_CalibrationData_t caldata;
01355     VL53LX_LLDriverData_t *pLLData;
01356     int i;
01357     uint32_t *pPlaneOffsetKcps;
01358     uint32_t Margin =
01359             BDTable[VL53LX_TUNING_XTALK_FULL_ROI_BIN_SUM_MARGIN];
01360     uint32_t DefaultOffset =
01361             BDTable[VL53LX_TUNING_XTALK_FULL_ROI_DEFAULT_OFFSET];
01362     uint32_t *pLLDataPlaneOffsetKcps;
01363     uint32_t sum = 0;
01364     uint8_t binok = 0;
01365 
01366     LOG_FUNCTION_START("");
01367 
01368     pPlaneOffsetKcps =
01369     &caldata.customer.algo__crosstalk_compensation_plane_offset_kcps;
01370     pLLData = VL53LXDevStructGetLLDriverHandle(Dev);
01371     pLLDataPlaneOffsetKcps =
01372     &pLLData->xtalk_cal.algo__crosstalk_compensation_plane_offset_kcps;
01373 
01374     CalDistanceMm = (int16_t)
01375     BDTable[VL53LX_TUNING_XTALK_FULL_ROI_TARGET_DISTANCE_MM];
01376     Status = VL53LX_run_hist_xtalk_extraction(Dev, CalDistanceMm,
01377             &UStatus);
01378 
01379     VL53LX_GetCalibrationData(Dev, &caldata);
01380     for (i = 0; i < VL53LX_XTALK_HISTO_BINS; i++) {
01381         sum += caldata.xtalkhisto.xtalk_shape.bin_data[i];
01382         if (caldata.xtalkhisto.xtalk_shape.bin_data[i] > 0)
01383             binok++;
01384     }
01385     if ((UStatus ==
01386         VL53LX_ERROR_XTALK_EXTRACTION_SIGMA_LIMIT_FAIL) ||
01387         (sum > (1024 + Margin)) || (sum < (1024 - Margin)) ||
01388         (binok < 3)) {
01389         *pPlaneOffsetKcps = DefaultOffset;
01390         *pLLDataPlaneOffsetKcps = DefaultOffset;
01391         caldata.xtalkhisto.xtalk_shape.bin_data[0] = 307;
01392         caldata.xtalkhisto.xtalk_shape.bin_data[1] = 410;
01393         caldata.xtalkhisto.xtalk_shape.bin_data[2] = 410;
01394         caldata.xtalkhisto.xtalk_shape.bin_data[3] = 307;
01395         for (i = 4; i < VL53LX_XTALK_HISTO_BINS; i++)
01396             caldata.xtalkhisto.xtalk_shape.bin_data[i] = 0;
01397         for (i = 0; i < VL53LX_BIN_REC_SIZE; i++)
01398             caldata.algo__xtalk_cpo_HistoMerge_kcps[i] =
01399                 DefaultOffset + DefaultOffset * i;
01400         VL53LX_SetCalibrationData(Dev, &caldata);
01401     }
01402 
01403     if (Status == VL53LX_ERROR_NONE) {
01404         Status = VL53LX_get_current_xtalk_settings(Dev, &xtalk);
01405         Status = VL53LX_set_tuning_parm(Dev,
01406             VL53LX_TUNINGPARM_DYNXTALK_NODETECT_XTALK_OFFSET_KCPS,
01407             xtalk.algo__crosstalk_compensation_plane_offset_kcps);
01408     }
01409 
01410     LOG_FUNCTION_END(Status);
01411     return Status;
01412 }
01413 
01414 
01415 VL53LX_Error VL53LX_SetOffsetCorrectionMode(VL53LX_DEV Dev,
01416         VL53LX_OffsetCorrectionModes OffsetCorrectionMode)
01417 {
01418     VL53LX_Error Status = VL53LX_ERROR_NONE;
01419     VL53LX_OffsetCorrectionMode   offset_cor_mode;
01420 
01421     LOG_FUNCTION_START("");
01422 
01423     if (OffsetCorrectionMode == VL53LX_OFFSETCORRECTIONMODE_STANDARD) {
01424         offset_cor_mode =
01425                 VL53LX_OFFSETCORRECTIONMODE__MM1_MM2_OFFSETS;
01426     } else if (OffsetCorrectionMode ==
01427             VL53LX_OFFSETCORRECTIONMODE_PERVCSEL) {
01428         offset_cor_mode =
01429                 VL53LX_OFFSETCORRECTIONMODE__PER_VCSEL_OFFSETS;
01430     } else {
01431         Status = VL53LX_ERROR_INVALID_PARAMS;
01432     }
01433 
01434     if (Status == VL53LX_ERROR_NONE)
01435         Status =  VL53LX_set_offset_correction_mode(Dev,
01436                 offset_cor_mode);
01437 
01438     LOG_FUNCTION_END(Status);
01439     return Status;
01440 }
01441 
01442 
01443 VL53LX_Error VL53LX_PerformOffsetSimpleCalibration(VL53LX_DEV Dev,
01444     int32_t CalDistanceMilliMeter)
01445 {
01446     VL53LX_Error Status = VL53LX_ERROR_NONE;
01447     int32_t sum_ranging;
01448     uint8_t offset_meas;
01449     int16_t Max, UnderMax, OverMax, Repeat;
01450     int32_t total_count, inloopcount;
01451     int32_t IncRounding;
01452     int16_t meanDistance_mm;
01453     int16_t offset;
01454     VL53LX_MultiRangingData_t RangingMeasurementData;
01455     VL53LX_LLDriverData_t *pdev;
01456     uint8_t goodmeas;
01457     VL53LX_Error SmudgeStatus = VL53LX_ERROR_NONE;
01458     uint8_t smudge_corr_en;
01459     VL53LX_TargetRangeData_t *pRange;
01460 
01461     LOG_FUNCTION_START("");
01462 
01463     pdev = VL53LXDevStructGetLLDriverHandle(Dev);
01464 
01465     smudge_corr_en = pdev->smudge_correct_config.smudge_corr_enabled;
01466     SmudgeStatus = VL53LX_dynamic_xtalk_correction_disable(Dev);
01467 
01468     pdev->customer.algo__part_to_part_range_offset_mm = 0;
01469     pdev->customer.mm_config__inner_offset_mm = 0;
01470     pdev->customer.mm_config__outer_offset_mm = 0;
01471     memset(&pdev->per_vcsel_cal_data, 0, sizeof(pdev->per_vcsel_cal_data));
01472     Repeat = BDTable[VL53LX_TUNING_SIMPLE_OFFSET_CALIBRATION_REPEAT];
01473     Max = BDTable[
01474         VL53LX_TUNING_MAX_SIMPLE_OFFSET_CALIBRATION_SAMPLE_NUMBER];
01475     UnderMax = 1 + (Max / 2);
01476     OverMax = Max + (Max / 2);
01477     sum_ranging = 0;
01478     total_count = 0;
01479 
01480     while ((Repeat > 0) && (Status == VL53LX_ERROR_NONE)) {
01481         Status = VL53LX_StartMeasurement(Dev);
01482 
01483         if (Status == VL53LX_ERROR_NONE) {
01484             VL53LX_WaitMeasurementDataReady(Dev);
01485             VL53LX_GetMultiRangingData(Dev,
01486                 &RangingMeasurementData);
01487             VL53LX_ClearInterruptAndStartMeasurement(Dev);
01488         }
01489 
01490         inloopcount = 0;
01491         offset_meas = 0;
01492         while ((Status == VL53LX_ERROR_NONE) && (inloopcount < Max) &&
01493                 (offset_meas < OverMax)) {
01494             Status = VL53LX_WaitMeasurementDataReady(Dev);
01495             if (Status == VL53LX_ERROR_NONE)
01496                 Status = VL53LX_GetMultiRangingData(Dev,
01497                         &RangingMeasurementData);
01498             pRange = &(RangingMeasurementData.RangeData [0]);
01499             goodmeas = (pRange->RangeStatus  ==
01500                 VL53LX_RANGESTATUS_RANGE_VALID);
01501             if ((Status == VL53LX_ERROR_NONE) && goodmeas) {
01502                 sum_ranging += pRange->RangeMilliMeter ;
01503                 inloopcount++;
01504             }
01505             Status = VL53LX_ClearInterruptAndStartMeasurement(Dev);
01506             offset_meas++;
01507         }
01508         total_count += inloopcount;
01509 
01510 
01511         if (inloopcount < UnderMax)
01512             Status = VL53LX_ERROR_OFFSET_CAL_NO_SAMPLE_FAIL;
01513 
01514         VL53LX_StopMeasurement(Dev);
01515 
01516         Repeat--;
01517 
01518     }
01519 
01520     if ((SmudgeStatus == VL53LX_ERROR_NONE) && (smudge_corr_en == 1))
01521         SmudgeStatus = VL53LX_dynamic_xtalk_correction_enable(Dev);
01522 
01523     if ((sum_ranging < 0) ||
01524         (sum_ranging > ((int32_t) total_count * 0xffff)))
01525         Status = VL53LX_WARNING_OFFSET_CAL_SIGMA_TOO_HIGH;
01526 
01527     if ((Status == VL53LX_ERROR_NONE) && (total_count > 0)) {
01528         IncRounding = total_count / 2;
01529         meanDistance_mm = (int16_t)((sum_ranging + IncRounding)
01530                 / total_count);
01531         offset = (int16_t)CalDistanceMilliMeter - meanDistance_mm;
01532         pdev->customer.algo__part_to_part_range_offset_mm = 0;
01533         pdev->customer.mm_config__inner_offset_mm = offset;
01534         pdev->customer.mm_config__outer_offset_mm = offset;
01535 
01536         Status = VL53LX_set_customer_nvm_managed(Dev,
01537                 &(pdev->customer));
01538     }
01539 
01540     LOG_FUNCTION_END(Status);
01541     return Status;
01542 }
01543 
01544 VL53LX_Error VL53LX_PerformOffsetZeroDistanceCalibration(VL53LX_DEV Dev)
01545 {
01546     #define START_OFFSET 50
01547     VL53LX_Error Status = VL53LX_ERROR_NONE;
01548     int32_t sum_ranging;
01549     uint8_t offset_meas;
01550     int16_t Max, UnderMax, OverMax, Repeat;
01551     int32_t total_count, inloopcount;
01552     int32_t IncRounding;
01553     int16_t meanDistance_mm;
01554     int16_t offset, ZeroDistanceOffset;
01555     VL53LX_MultiRangingData_t RangingMeasurementData;
01556     VL53LX_LLDriverData_t *pdev;
01557     uint8_t goodmeas;
01558     VL53LX_Error SmudgeStatus = VL53LX_ERROR_NONE;
01559     uint8_t smudge_corr_en;
01560     VL53LX_TargetRangeData_t *pRange;
01561 
01562     LOG_FUNCTION_START("");
01563 
01564     pdev = VL53LXDevStructGetLLDriverHandle(Dev);
01565     smudge_corr_en = pdev->smudge_correct_config.smudge_corr_enabled;
01566     SmudgeStatus = VL53LX_dynamic_xtalk_correction_disable(Dev);
01567     pdev->customer.algo__part_to_part_range_offset_mm = 0;
01568     pdev->customer.mm_config__inner_offset_mm = START_OFFSET;
01569     pdev->customer.mm_config__outer_offset_mm = START_OFFSET;
01570     memset(&pdev->per_vcsel_cal_data, 0, sizeof(pdev->per_vcsel_cal_data));
01571     ZeroDistanceOffset = BDTable[
01572         VL53LX_TUNING_ZERO_DISTANCE_OFFSET_NON_LINEAR_FACTOR];
01573     Repeat = BDTable[VL53LX_TUNING_SIMPLE_OFFSET_CALIBRATION_REPEAT];
01574     Max =
01575     BDTable[VL53LX_TUNING_MAX_SIMPLE_OFFSET_CALIBRATION_SAMPLE_NUMBER];
01576     UnderMax = 1 + (Max / 2);
01577     OverMax = Max + (Max / 2);
01578     sum_ranging = 0;
01579     total_count = 0;
01580 
01581     while ((Repeat > 0) && (Status == VL53LX_ERROR_NONE)) {
01582         Status = VL53LX_StartMeasurement(Dev);
01583         if (Status == VL53LX_ERROR_NONE) {
01584             VL53LX_WaitMeasurementDataReady(Dev);
01585             VL53LX_GetMultiRangingData(Dev,
01586                 &RangingMeasurementData);
01587             VL53LX_ClearInterruptAndStartMeasurement(Dev);
01588         }
01589         inloopcount = 0;
01590         offset_meas = 0;
01591         while ((Status == VL53LX_ERROR_NONE) && (inloopcount < Max) &&
01592                 (offset_meas < OverMax)) {
01593             Status = VL53LX_WaitMeasurementDataReady(Dev);
01594             if (Status == VL53LX_ERROR_NONE)
01595                 Status = VL53LX_GetMultiRangingData(Dev,
01596                         &RangingMeasurementData);
01597             pRange = &(RangingMeasurementData.RangeData [0]);
01598             goodmeas = (pRange->RangeStatus  ==
01599                 VL53LX_RANGESTATUS_RANGE_VALID);
01600             if ((Status == VL53LX_ERROR_NONE) && goodmeas) {
01601                 sum_ranging = sum_ranging +
01602                     pRange->RangeMilliMeter ;
01603                 inloopcount++;
01604             }
01605             Status = VL53LX_ClearInterruptAndStartMeasurement(Dev);
01606             offset_meas++;
01607         }
01608         total_count += inloopcount;
01609         if (inloopcount < UnderMax)
01610             Status = VL53LX_ERROR_OFFSET_CAL_NO_SAMPLE_FAIL;
01611         VL53LX_StopMeasurement(Dev);
01612         Repeat--;
01613     }
01614     if ((SmudgeStatus == VL53LX_ERROR_NONE) && (smudge_corr_en == 1))
01615         SmudgeStatus = VL53LX_dynamic_xtalk_correction_enable(Dev);
01616     if ((sum_ranging < 0) ||
01617         (sum_ranging > ((int32_t) total_count * 0xffff)))
01618         Status = VL53LX_WARNING_OFFSET_CAL_SIGMA_TOO_HIGH;
01619 
01620     if ((Status == VL53LX_ERROR_NONE) && (total_count > 0)) {
01621         IncRounding = total_count / 2;
01622         meanDistance_mm = (int16_t)
01623             ((sum_ranging + IncRounding) / total_count);
01624         offset = START_OFFSET - meanDistance_mm + ZeroDistanceOffset;
01625         pdev->customer.algo__part_to_part_range_offset_mm = 0;
01626         pdev->customer.mm_config__inner_offset_mm = offset;
01627         pdev->customer.mm_config__outer_offset_mm = offset;
01628         Status = VL53LX_set_customer_nvm_managed(Dev,
01629             &(pdev->customer));
01630     }
01631 
01632     LOG_FUNCTION_END(Status);
01633     return Status;
01634 }
01635 
01636 VL53LX_Error VL53LX_SetCalibrationData(VL53LX_DEV Dev,
01637         VL53LX_CalibrationData_t *pCalibrationData)
01638 {
01639     VL53LX_Error Status = VL53LX_ERROR_NONE;
01640     VL53LX_CustomerNvmManaged_t          *pC;
01641     VL53LX_calibration_data_t            cal_data;
01642     uint32_t x;
01643     VL53LX_xtalk_calibration_results_t xtalk;
01644 
01645     LOG_FUNCTION_START("");
01646 
01647     cal_data.struct_version = pCalibrationData->struct_version -
01648             VL53LX_ADDITIONAL_CALIBRATION_DATA_STRUCT_VERSION;
01649 
01650 
01651     memcpy(
01652         &(cal_data.add_off_cal_data),
01653         &(pCalibrationData->add_off_cal_data),
01654         sizeof(VL53LX_additional_offset_cal_data_t));
01655 
01656 
01657     memcpy(
01658         &(cal_data.optical_centre),
01659         &(pCalibrationData->optical_centre),
01660         sizeof(VL53LX_optical_centre_t));
01661 
01662 
01663     memcpy(
01664         &(cal_data.xtalkhisto),
01665         &(pCalibrationData->xtalkhisto),
01666         sizeof(VL53LX_xtalk_histogram_data_t));
01667 
01668 
01669     memcpy(
01670         &(cal_data.gain_cal),
01671         &(pCalibrationData->gain_cal),
01672         sizeof(VL53LX_gain_calibration_data_t));
01673 
01674 
01675     memcpy(
01676         &(cal_data.cal_peak_rate_map),
01677         &(pCalibrationData->cal_peak_rate_map),
01678         sizeof(VL53LX_cal_peak_rate_map_t));
01679 
01680 
01681     memcpy(
01682         &(cal_data.per_vcsel_cal_data),
01683         &(pCalibrationData->per_vcsel_cal_data),
01684         sizeof(VL53LX_per_vcsel_period_offset_cal_data_t));
01685 
01686     pC = &pCalibrationData->customer;
01687     x = pC->algo__crosstalk_compensation_plane_offset_kcps;
01688     cal_data.customer.algo__crosstalk_compensation_plane_offset_kcps =
01689         (uint16_t)(x&0x0000FFFF);
01690 
01691     cal_data.customer.global_config__spad_enables_ref_0 =
01692         pC->global_config__spad_enables_ref_0;
01693     cal_data.customer.global_config__spad_enables_ref_1 =
01694         pC->global_config__spad_enables_ref_1;
01695     cal_data.customer.global_config__spad_enables_ref_2 =
01696         pC->global_config__spad_enables_ref_2;
01697     cal_data.customer.global_config__spad_enables_ref_3 =
01698         pC->global_config__spad_enables_ref_3;
01699     cal_data.customer.global_config__spad_enables_ref_4 =
01700         pC->global_config__spad_enables_ref_4;
01701     cal_data.customer.global_config__spad_enables_ref_5 =
01702         pC->global_config__spad_enables_ref_5;
01703     cal_data.customer.global_config__ref_en_start_select =
01704         pC->global_config__ref_en_start_select;
01705     cal_data.customer.ref_spad_man__num_requested_ref_spads =
01706         pC->ref_spad_man__num_requested_ref_spads;
01707     cal_data.customer.ref_spad_man__ref_location =
01708         pC->ref_spad_man__ref_location;
01709     cal_data.customer.algo__crosstalk_compensation_x_plane_gradient_kcps =
01710         pC->algo__crosstalk_compensation_x_plane_gradient_kcps;
01711     cal_data.customer.algo__crosstalk_compensation_y_plane_gradient_kcps =
01712         pC->algo__crosstalk_compensation_y_plane_gradient_kcps;
01713     cal_data.customer.ref_spad_char__total_rate_target_mcps =
01714         pC->ref_spad_char__total_rate_target_mcps;
01715     cal_data.customer.algo__part_to_part_range_offset_mm =
01716         pC->algo__part_to_part_range_offset_mm;
01717     cal_data.customer.mm_config__inner_offset_mm =
01718         pC->mm_config__inner_offset_mm;
01719     cal_data.customer.mm_config__outer_offset_mm =
01720         pC->mm_config__outer_offset_mm;
01721 
01722     Status = VL53LX_set_part_to_part_data(Dev, &cal_data);
01723 
01724     if (Status != VL53LX_ERROR_NONE)
01725         goto ENDFUNC;
01726 
01727     Status = VL53LX_get_current_xtalk_settings(Dev, &xtalk);
01728 
01729     if (Status != VL53LX_ERROR_NONE)
01730         goto ENDFUNC;
01731 
01732     xtalk.algo__crosstalk_compensation_plane_offset_kcps = x;
01733 
01734     Status = VL53LX_set_tuning_parm(Dev,
01735             VL53LX_TUNINGPARM_DYNXTALK_NODETECT_XTALK_OFFSET_KCPS,
01736             x);
01737 
01738 
01739     memcpy(
01740         &(xtalk.algo__xtalk_cpo_HistoMerge_kcps[0]),
01741         &(pCalibrationData->algo__xtalk_cpo_HistoMerge_kcps[0]),
01742         sizeof(pCalibrationData->algo__xtalk_cpo_HistoMerge_kcps));
01743 
01744     Status = VL53LX_set_current_xtalk_settings(Dev, &xtalk);
01745 
01746 ENDFUNC:
01747     LOG_FUNCTION_END(Status);
01748     return Status;
01749 
01750 }
01751 
01752 VL53LX_Error VL53LX_GetCalibrationData(VL53LX_DEV Dev,
01753         VL53LX_CalibrationData_t  *pCalibrationData)
01754 {
01755     VL53LX_Error Status = VL53LX_ERROR_NONE;
01756     VL53LX_calibration_data_t      cal_data;
01757     VL53LX_CustomerNvmManaged_t         *pC;
01758     VL53LX_customer_nvm_managed_t       *pC2;
01759     VL53LX_xtalk_calibration_results_t xtalk;
01760     uint32_t                          tmp;
01761 
01762     LOG_FUNCTION_START("");
01763 
01764 
01765     Status = VL53LX_get_part_to_part_data(Dev, &cal_data);
01766 
01767     pCalibrationData->struct_version = cal_data.struct_version +
01768             VL53LX_ADDITIONAL_CALIBRATION_DATA_STRUCT_VERSION;
01769 
01770 
01771     memcpy(
01772         &(pCalibrationData->add_off_cal_data),
01773         &(cal_data.add_off_cal_data),
01774         sizeof(VL53LX_additional_offset_cal_data_t));
01775 
01776 
01777     memcpy(
01778         &(pCalibrationData->optical_centre),
01779         &(cal_data.optical_centre),
01780         sizeof(VL53LX_optical_centre_t));
01781 
01782 
01783     memcpy(
01784         &(pCalibrationData->xtalkhisto),
01785         &(cal_data.xtalkhisto),
01786         sizeof(VL53LX_xtalk_histogram_data_t));
01787 
01788     memcpy(
01789         &(pCalibrationData->gain_cal),
01790         &(cal_data.gain_cal),
01791         sizeof(VL53LX_gain_calibration_data_t));
01792 
01793 
01794     memcpy(
01795         &(pCalibrationData->cal_peak_rate_map),
01796         &(cal_data.cal_peak_rate_map),
01797         sizeof(VL53LX_cal_peak_rate_map_t));
01798 
01799 
01800     memcpy(
01801         &(pCalibrationData->per_vcsel_cal_data),
01802         &(cal_data.per_vcsel_cal_data),
01803         sizeof(VL53LX_per_vcsel_period_offset_cal_data_t));
01804 
01805     pC = &pCalibrationData->customer;
01806     pC2 = &cal_data.customer;
01807     pC->global_config__spad_enables_ref_0 =
01808         pC2->global_config__spad_enables_ref_0;
01809     pC->global_config__spad_enables_ref_1 =
01810         pC2->global_config__spad_enables_ref_1;
01811     pC->global_config__spad_enables_ref_2 =
01812         pC2->global_config__spad_enables_ref_2;
01813     pC->global_config__spad_enables_ref_3 =
01814         pC2->global_config__spad_enables_ref_3;
01815     pC->global_config__spad_enables_ref_4 =
01816         pC2->global_config__spad_enables_ref_4;
01817     pC->global_config__spad_enables_ref_5 =
01818         pC2->global_config__spad_enables_ref_5;
01819     pC->global_config__ref_en_start_select =
01820         pC2->global_config__ref_en_start_select;
01821     pC->ref_spad_man__num_requested_ref_spads =
01822         pC2->ref_spad_man__num_requested_ref_spads;
01823     pC->ref_spad_man__ref_location =
01824         pC2->ref_spad_man__ref_location;
01825     pC->algo__crosstalk_compensation_x_plane_gradient_kcps =
01826         pC2->algo__crosstalk_compensation_x_plane_gradient_kcps;
01827     pC->algo__crosstalk_compensation_y_plane_gradient_kcps =
01828         pC2->algo__crosstalk_compensation_y_plane_gradient_kcps;
01829     pC->ref_spad_char__total_rate_target_mcps =
01830         pC2->ref_spad_char__total_rate_target_mcps;
01831     pC->algo__part_to_part_range_offset_mm =
01832         pC2->algo__part_to_part_range_offset_mm;
01833     pC->mm_config__inner_offset_mm =
01834         pC2->mm_config__inner_offset_mm;
01835     pC->mm_config__outer_offset_mm =
01836         pC2->mm_config__outer_offset_mm;
01837 
01838     pC->algo__crosstalk_compensation_plane_offset_kcps =
01839         (uint32_t)(
01840             pC2->algo__crosstalk_compensation_plane_offset_kcps);
01841 
01842     Status = VL53LX_get_current_xtalk_settings(Dev, &xtalk);
01843 
01844     if (Status != VL53LX_ERROR_NONE)
01845         goto ENDFUNC;
01846 
01847     tmp = xtalk.algo__crosstalk_compensation_plane_offset_kcps;
01848     pC->algo__crosstalk_compensation_plane_offset_kcps = tmp;
01849     tmp = xtalk.algo__crosstalk_compensation_x_plane_gradient_kcps;
01850     pC->algo__crosstalk_compensation_x_plane_gradient_kcps = tmp;
01851     tmp = xtalk.algo__crosstalk_compensation_y_plane_gradient_kcps;
01852     pC->algo__crosstalk_compensation_y_plane_gradient_kcps = tmp;
01853 
01854     memcpy(&(pCalibrationData->algo__xtalk_cpo_HistoMerge_kcps[0]),
01855         &(xtalk.algo__xtalk_cpo_HistoMerge_kcps[0]),
01856         sizeof(pCalibrationData->algo__xtalk_cpo_HistoMerge_kcps));
01857 ENDFUNC:
01858     LOG_FUNCTION_END(Status);
01859     return Status;
01860 }
01861 
01862 
01863 
01864 VL53LX_Error VL53LX_PerformOffsetPerVcselCalibration(VL53LX_DEV Dev,
01865     int32_t CalDistanceMilliMeter)
01866 {
01867     VL53LX_Error Status = VL53LX_ERROR_NONE;
01868     int32_t sum_ranging_range_A, sum_ranging_range_B;
01869     uint8_t offset_meas_range_A, offset_meas_range_B;
01870     int16_t Max, UnderMax, OverMax, Repeat;
01871     int32_t inloopcount;
01872     int32_t IncRounding;
01873     int16_t meanDistance_mm;
01874     VL53LX_MultiRangingData_t RangingMeasurementData;
01875     VL53LX_LLDriverData_t *pdev;
01876     uint8_t goodmeas;
01877     VL53LX_DistanceModes currentDist;
01878     VL53LX_DistanceModes DistMode[3] = {VL53LX_DISTANCEMODE_SHORT,
01879             VL53LX_DISTANCEMODE_MEDIUM, VL53LX_DISTANCEMODE_LONG};
01880     int16_t offsetA[3] = {0, 0, 0};
01881     int16_t offsetB[3] = {0, 0, 0};
01882 
01883     VL53LX_Error SmudgeStatus = VL53LX_ERROR_NONE;
01884     uint8_t smudge_corr_en, ics;
01885     VL53LX_TargetRangeData_t *pRange;
01886 
01887     LOG_FUNCTION_START("");
01888 
01889     pdev = VL53LXDevStructGetLLDriverHandle(Dev);
01890 
01891     smudge_corr_en = pdev->smudge_correct_config.smudge_corr_enabled;
01892     SmudgeStatus = VL53LX_dynamic_xtalk_correction_disable(Dev);
01893 
01894     pdev->customer.algo__part_to_part_range_offset_mm = 0;
01895     pdev->customer.mm_config__inner_offset_mm = 0;
01896     pdev->customer.mm_config__outer_offset_mm = 0;
01897     pdev->customer.mm_config__outer_offset_mm = 0;
01898     memset(&pdev->per_vcsel_cal_data, 0, sizeof(pdev->per_vcsel_cal_data));
01899 
01900     Repeat = 0;
01901     if (IsL4(Dev))
01902         Repeat = 1;
01903     Max = 2 * BDTable[
01904         VL53LX_TUNING_MAX_SIMPLE_OFFSET_CALIBRATION_SAMPLE_NUMBER];
01905     UnderMax = 1 + (Max / 2);
01906     OverMax = Max + (Max / 2);
01907 
01908     Status = VL53LX_GetDistanceMode(Dev, &currentDist);
01909 
01910     while ((Repeat < 3) && (Status == VL53LX_ERROR_NONE)) {
01911         Status = VL53LX_SetDistanceMode(Dev, DistMode[Repeat]);
01912         Status = VL53LX_StartMeasurement(Dev);
01913 
01914         if (Status == VL53LX_ERROR_NONE) {
01915             VL53LX_WaitMeasurementDataReady(Dev);
01916             VL53LX_GetMultiRangingData(Dev,
01917                 &RangingMeasurementData);
01918             VL53LX_ClearInterruptAndStartMeasurement(Dev);
01919         }
01920 
01921         inloopcount = 0;
01922         offset_meas_range_A = 0;
01923         sum_ranging_range_A = 0;
01924         offset_meas_range_B = 0;
01925         sum_ranging_range_B = 0;
01926         while ((Status == VL53LX_ERROR_NONE) && (inloopcount < Max) &&
01927                 (inloopcount < OverMax)) {
01928             Status = VL53LX_WaitMeasurementDataReady(Dev);
01929             if (Status == VL53LX_ERROR_NONE)
01930                 Status = VL53LX_GetMultiRangingData(Dev,
01931                         &RangingMeasurementData);
01932             pRange = &(RangingMeasurementData.RangeData [0]);
01933             goodmeas = (pRange->RangeStatus  ==
01934                 VL53LX_RANGESTATUS_RANGE_VALID);
01935             ics = pdev->ll_state.cfg_internal_stream_count;
01936             if ((Status == VL53LX_ERROR_NONE) && goodmeas) {
01937                 if (ics & 0x01) {
01938                     sum_ranging_range_A +=
01939                         pRange->RangeMilliMeter ;
01940                     offset_meas_range_A++;
01941                 } else {
01942                     sum_ranging_range_B +=
01943                         pRange->RangeMilliMeter ;
01944                     offset_meas_range_B++;
01945                 }
01946                 inloopcount = offset_meas_range_A +
01947                     offset_meas_range_B;
01948             }
01949             Status = VL53LX_ClearInterruptAndStartMeasurement(Dev);
01950         }
01951 
01952 
01953         if (inloopcount < UnderMax)
01954             Status = VL53LX_ERROR_OFFSET_CAL_NO_SAMPLE_FAIL;
01955 
01956         VL53LX_StopMeasurement(Dev);
01957 
01958 
01959         if ((sum_ranging_range_A < 0) ||
01960             (sum_ranging_range_B < 0) ||
01961             (sum_ranging_range_A >
01962             ((int32_t) offset_meas_range_A * 0xffff)) ||
01963             (sum_ranging_range_B >
01964             ((int32_t) offset_meas_range_B * 0xffff))) {
01965             Status = VL53LX_WARNING_OFFSET_CAL_SIGMA_TOO_HIGH;
01966         }
01967 
01968         if ((Status == VL53LX_ERROR_NONE) &&
01969             (offset_meas_range_A > 0)) {
01970             IncRounding = offset_meas_range_A / 2;
01971             meanDistance_mm = (int16_t)
01972                 ((sum_ranging_range_A + IncRounding)
01973                 / offset_meas_range_A);
01974             offsetA[Repeat] = (int16_t)
01975                 CalDistanceMilliMeter - meanDistance_mm;
01976         }
01977 
01978         if ((Status == VL53LX_ERROR_NONE) &&
01979             (offset_meas_range_B > 0)) {
01980             IncRounding = offset_meas_range_B / 2;
01981             meanDistance_mm = (int16_t)
01982                 ((sum_ranging_range_B + IncRounding)
01983                 / offset_meas_range_B);
01984             offsetB[Repeat] = (int16_t)
01985                 CalDistanceMilliMeter - meanDistance_mm;
01986         }
01987         Repeat++;
01988     }
01989 
01990     if ((SmudgeStatus == VL53LX_ERROR_NONE) && (smudge_corr_en == 1))
01991         SmudgeStatus = VL53LX_dynamic_xtalk_correction_enable(Dev);
01992 
01993     if (Status == VL53LX_ERROR_NONE) {
01994         pdev->per_vcsel_cal_data.short_a_offset_mm  = offsetA[0];
01995         pdev->per_vcsel_cal_data.short_b_offset_mm  = offsetB[0];
01996         pdev->per_vcsel_cal_data.medium_a_offset_mm = offsetA[1];
01997         pdev->per_vcsel_cal_data.medium_b_offset_mm = offsetB[1];
01998         pdev->per_vcsel_cal_data.long_a_offset_mm   = offsetA[2];
01999         pdev->per_vcsel_cal_data.long_b_offset_mm   = offsetB[2];
02000     }
02001 
02002     VL53LX_SetDistanceMode(Dev, currentDist);
02003 
02004     LOG_FUNCTION_END(Status);
02005     return Status;
02006 }
02007 
02008 VL53LX_Error VL53LX_GetOpticalCenter(VL53LX_DEV Dev,
02009         FixPoint1616_t *pOpticalCenterX,
02010         FixPoint1616_t *pOpticalCenterY)
02011 {
02012     VL53LX_Error Status = VL53LX_ERROR_NONE;
02013     VL53LX_calibration_data_t  CalibrationData;
02014 
02015     LOG_FUNCTION_START("");
02016 
02017     *pOpticalCenterX = 0;
02018     *pOpticalCenterY = 0;
02019     Status = VL53LX_get_part_to_part_data(Dev, &CalibrationData);
02020     if (Status == VL53LX_ERROR_NONE) {
02021         *pOpticalCenterX = VL53LX_FIXPOINT44TOFIXPOINT1616(
02022                 CalibrationData.optical_centre.x_centre);
02023         *pOpticalCenterY = VL53LX_FIXPOINT44TOFIXPOINT1616(
02024                 CalibrationData.optical_centre.y_centre);
02025     }
02026 
02027     LOG_FUNCTION_END(Status);
02028     return Status;
02029 }
02030 
02031