Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: X_NUCLEO_COMMON ST_INTERFACES
Dependents: VL53L3CX_NoShield_1Sensor_poll_Mb06x VL53L3_NoShield_1Sensor_polling_Mb63 X_NUCLEO_53L3A2 53L3A2_Ranging
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, ¤tDist); 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
Generated on Mon Jul 18 2022 15:35:58 by
1.7.2