1
2 // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
3 /******************************************************************************
4 * Copyright (c) 2020, STMicroelectronics - All Rights Reserved
5
6 This file is part of VL53L1 and is dual licensed,
7 either GPL-2.0+
8 or 'BSD 3-clause "New" or "Revised" License' , at your option.
9 ******************************************************************************
10 */
11
12 #include "vl53l1_api.h"
13 #include "vl53l1_api_strings.h"
14 #include "vl53l1_register_settings.h"
15 #include "vl53l1_register_funcs.h"
16 #include "vl53l1_core.h"
17 #include "vl53l1_api_calibration.h"
18 #include "vl53l1_wait.h"
19 #include "vl53l1_preset_setup.h"
20 #include "vl53l1_api_debug.h"
21 #include "vl53l1_api_core.h"
22
23 /* Check for minimum user zone requested by Xtalk calibration */
24 /* no need for VL53L1_MAX_USER_ZONES check, set 5 to pass the test */
25 #define ZONE_CHECK 5
26
27 #if ZONE_CHECK < 5
28 #error Must define at least 5 zones in MAX_USER_ZONES constant
29 #endif
30
31 #define LOG_FUNCTION_START(fmt, ...) \
32 _LOG_FUNCTION_START(VL53L1_TRACE_MODULE_API, fmt, ##__VA_ARGS__)
33 #define LOG_FUNCTION_END(status, ...) \
34 _LOG_FUNCTION_END(VL53L1_TRACE_MODULE_API, status, ##__VA_ARGS__)
35 #define LOG_FUNCTION_END_FMT(status, fmt, ...) \
36 _LOG_FUNCTION_END_FMT(VL53L1_TRACE_MODULE_API, status, \
37 fmt, ##__VA_ARGS__)
38
39 #ifdef VL53L1_LOG_ENABLE
40 #define trace_print(level, ...) trace_print_module_function(\
41 VL53L1_TRACE_MODULE_API, level, VL53L1_TRACE_FUNCTION_NONE, \
42 ##__VA_ARGS__)
43 #endif
44
45 #ifndef MIN
46 #define MIN(v1, v2) ((v1) < (v2) ? (v1) : (v2))
47 #endif
48 #ifndef MAX
49 #define MAX(v1, v2) ((v1) < (v2) ? (v2) : (v1))
50 #endif
51
52 #define DMAX_REFLECTANCE_IDX 2
53 /* Use Dmax index 2 because it's the 50% reflectance case by default */
54
55 /* Following LOWPOWER_AUTO figures have been measured observing vcsel
56 * emissions on an actual device
57 */
58 #define LOWPOWER_AUTO_VHV_LOOP_DURATION_US 245
59 #define LOWPOWER_AUTO_OVERHEAD_BEFORE_A_RANGING 1448
60 #define LOWPOWER_AUTO_OVERHEAD_BETWEEN_A_B_RANGING 2100
61
62 #define FDA_MAX_TIMING_BUDGET_US 550000
63 /* Maximum timing budget allowed codex #456189*/
64
65
66 /* local static utilities functions */
67
68 /* Bare Driver Tuning parameter table indexed with VL53L1_Tuning_t */
69 static int32_t BDTable[VL53L1_TUNING_MAX_TUNABLE_KEY] = {
70 TUNING_VERSION,
71 TUNING_PROXY_MIN,
72 TUNING_SINGLE_TARGET_XTALK_TARGET_DISTANCE_MM,
73 TUNING_SINGLE_TARGET_XTALK_SAMPLE_NUMBER,
74 TUNING_MIN_AMBIENT_DMAX_VALID,
75 TUNING_MAX_SIMPLE_OFFSET_CALIBRATION_SAMPLE_NUMBER,
76 TUNING_XTALK_FULL_ROI_TARGET_DISTANCE_MM,
77 TUNING_SIMPLE_OFFSET_CALIBRATION_REPEAT,
78 TUNING_XTALK_FULL_ROI_BIN_SUM_MARGIN,
79 TUNING_XTALK_FULL_ROI_DEFAULT_OFFSET,
80 TUNING_ZERO_DISTANCE_OFFSET_NON_LINEAR_FACTOR_DEFAULT,
81 TUNING_PHASECAL_PATCH_POWER
82 };
83
84
85 static VL53L1_Error VL53L1_LoadPatch(VL53L1_DEV Dev);
86 static VL53L1_Error VL53L1_UnloadPatch(VL53L1_DEV Dev);
87
88 #define VL53L1_NVM_POWER_UP_DELAY_US 50
89 #define VL53L1_NVM_READ_TRIGGER_DELAY_US 5
90
VL53L1_nvm_enable(VL53L1_DEV Dev,uint16_t nvm_ctrl_pulse_width,int32_t nvm_power_up_delay_us)91 static VL53L1_Error VL53L1_nvm_enable(
92 VL53L1_DEV Dev,
93 uint16_t nvm_ctrl_pulse_width,
94 int32_t nvm_power_up_delay_us)
95 {
96 /*
97 * Sequence below enables NVM for reading
98 *
99 * - Enable power force
100 * - Disable firmware
101 * - Power up NVM
102 * - Wait for 50us while the NVM powers up
103 * - Configure for reading and set the pulse width (16-bit)
104 */
105
106 VL53L1_Error status = VL53L1_ERROR_NONE;
107
108 LOG_FUNCTION_START("");
109
110
111 /* Disable Firmware */
112
113 if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/
114 status = VL53L1_disable_firmware(Dev);
115
116
117 /* Enable Power Force */
118
119 if (status == VL53L1_ERROR_NONE)
120 status = VL53L1_enable_powerforce(Dev);
121
122 /* Wait the required time for the regulators, bandgap,
123 * oscillator to wake up and settle
124 */
125
126 if (status == VL53L1_ERROR_NONE)
127 status = VL53L1_WaitUs(Dev,
128 VL53L1_ENABLE_POWERFORCE_SETTLING_TIME_US);
129
130 /* Power up NVM */
131
132 if (status == VL53L1_ERROR_NONE)
133 status = VL53L1_WrByte(Dev, VL53L1_RANGING_CORE__NVM_CTRL__PDN,
134 0x01);
135
136 /* Enable NVM Clock */
137
138 if (status == VL53L1_ERROR_NONE)
139 status = VL53L1_WrByte(Dev, VL53L1_RANGING_CORE__CLK_CTRL1,
140 0x05);
141
142 /* Wait the required time for NVM to power up*/
143
144 if (status == VL53L1_ERROR_NONE)
145 status = VL53L1_WaitUs(Dev, nvm_power_up_delay_us);
146
147 /* Select read mode and set control pulse width */
148
149 if (status == VL53L1_ERROR_NONE)
150 status = VL53L1_WrByte(Dev, VL53L1_RANGING_CORE__NVM_CTRL__MODE,
151 0x01);
152
153 if (status == VL53L1_ERROR_NONE)
154 status = VL53L1_WrWord(Dev,
155 VL53L1_RANGING_CORE__NVM_CTRL__PULSE_WIDTH_MSB,
156 nvm_ctrl_pulse_width);
157
158 LOG_FUNCTION_END(status);
159
160 return status;
161
162 }
163
164
VL53L1_nvm_read(VL53L1_DEV Dev,uint8_t start_address,uint8_t count,uint8_t * pdata)165 static VL53L1_Error VL53L1_nvm_read(
166 VL53L1_DEV Dev,
167 uint8_t start_address,
168 uint8_t count,
169 uint8_t *pdata)
170 {
171 /*
172 * Sequence per 32-bit NVM read access:
173 *
174 * - Set up the 5-bit (0-127) NVM Address
175 * - Trigger the read of the NVM data by toggling NVM_CTRL__READN
176 * - Read the NVM data - 4 bytes wide read/write interface
177 * - Increment data byte pointer by 4 ready for the next loop
178 */
179
180 VL53L1_Error status = VL53L1_ERROR_NONE;
181 uint8_t nvm_addr = 0;
182 uint8_t start = start_address;
183 uint8_t end = start_address + count;
184
185 LOG_FUNCTION_START("");
186
187 for (nvm_addr = start; nvm_addr < end; nvm_addr++) {
188
189 /* Step 1 : set address */
190
191 if (status == VL53L1_ERROR_NONE)
192 status = VL53L1_WrByte(Dev,
193 VL53L1_RANGING_CORE__NVM_CTRL__ADDR,
194 nvm_addr);
195
196 /* Step 2 : trigger reading of data */
197
198 if (status == VL53L1_ERROR_NONE)
199 status = VL53L1_WrByte(Dev,
200 VL53L1_RANGING_CORE__NVM_CTRL__READN,
201 0x00);
202
203 /* Step 3 : wait the required time */
204
205 if (status == VL53L1_ERROR_NONE)
206 status = VL53L1_WaitUs(Dev,
207 VL53L1_NVM_READ_TRIGGER_DELAY_US);
208
209 if (status == VL53L1_ERROR_NONE)
210 status = VL53L1_WrByte(Dev,
211 VL53L1_RANGING_CORE__NVM_CTRL__READN,
212 0x01);
213
214 /* Step 3 : read 4-byte wide data register */
215 if (status == VL53L1_ERROR_NONE)
216 status = VL53L1_ReadMulti(Dev,
217 VL53L1_RANGING_CORE__NVM_CTRL__DATAOUT_MMM,
218 pdata, 4);
219
220 /* Step 4 : increment byte buffer pointer */
221 pdata = pdata + 4;
222
223 }
224
225 LOG_FUNCTION_END(status);
226
227 return status;
228 }
229
VL53L1_nvm_disable(VL53L1_DEV Dev)230 static VL53L1_Error VL53L1_nvm_disable(
231 VL53L1_DEV Dev)
232 {
233 /*
234 * Power down NVM (OTP) to extend lifetime
235 */
236
237 VL53L1_Error status = VL53L1_ERROR_NONE;
238
239 LOG_FUNCTION_START("");
240
241 if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/
242 status = VL53L1_WrByte(
243 Dev,
244 VL53L1_RANGING_CORE__NVM_CTRL__READN,
245 0x01);
246
247 /* Power down NVM */
248
249 if (status == VL53L1_ERROR_NONE)
250 status = VL53L1_WrByte(
251 Dev,
252 VL53L1_RANGING_CORE__NVM_CTRL__PDN,
253 0x00);
254
255 /* Keep power force enabled */
256
257 if (status == VL53L1_ERROR_NONE)
258 status = VL53L1_disable_powerforce(Dev);
259
260 /* (Re)Enable Firmware */
261
262 if (status == VL53L1_ERROR_NONE)
263 status = VL53L1_enable_firmware(Dev);
264
265 LOG_FUNCTION_END(status);
266
267 return status;
268
269 }
270
VL53L1_read_nvm_raw_data(VL53L1_DEV Dev,uint8_t start_address,uint8_t count,uint8_t * pnvm_raw_data)271 static VL53L1_Error VL53L1_read_nvm_raw_data(
272 VL53L1_DEV Dev,
273 uint8_t start_address,
274 uint8_t count,
275 uint8_t *pnvm_raw_data)
276 {
277
278 /*
279 * Reads ALL 512 bytes of NVM data
280 */
281
282 VL53L1_Error status = VL53L1_ERROR_NONE;
283
284 LOG_FUNCTION_START("");
285
286 /*
287 * Enable NVM and set control pulse width
288 */
289
290 if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/
291 status = VL53L1_nvm_enable(
292 Dev,
293 0x0004,
294 VL53L1_NVM_POWER_UP_DELAY_US);
295
296 /*
297 * Read the raw NVM data
298 * - currently all of 128 * 4 bytes = 512 bytes are read
299 */
300
301 if (status == VL53L1_ERROR_NONE)
302 status = VL53L1_nvm_read(
303 Dev,
304 start_address,
305 count,
306 pnvm_raw_data);
307
308 /*
309 * Disable NVM
310 */
311
312 if (status == VL53L1_ERROR_NONE)
313 status = VL53L1_nvm_disable(Dev);
314
315 LOG_FUNCTION_END(status);
316
317 return status;
318
319 }
320
SingleTargetXTalkCalibration(VL53L1_DEV Dev)321 static VL53L1_Error SingleTargetXTalkCalibration(VL53L1_DEV Dev)
322 {
323 VL53L1_Error Status = VL53L1_ERROR_NONE;
324
325 uint32_t sum_ranging = 0;
326 uint32_t sum_spads = 0;
327 FixPoint1616_t sum_signalRate = 0;
328 FixPoint1616_t total_count = 0;
329 uint8_t xtalk_meas = 0;
330 uint8_t xtalk_measmax =
331 BDTable[VL53L1_TUNING_SINGLE_TARGET_XTALK_SAMPLE_NUMBER];
332 VL53L1_RangingMeasurementData_t RMData;
333 FixPoint1616_t xTalkStoredMeanSignalRate;
334 FixPoint1616_t xTalkStoredMeanRange;
335 FixPoint1616_t xTalkStoredMeanRtnSpads;
336 uint32_t xTalkStoredMeanRtnSpadsAsInt;
337 uint32_t xTalkCalDistanceAsInt;
338 FixPoint1616_t XTalkCompensationRateMegaCps;
339 uint32_t signalXTalkTotalPerSpad;
340 VL53L1_PresetModes PresetMode;
341 VL53L1_CalibrationData_t CalibrationData;
342 VL53L1_CustomerNvmManaged_t *pC;
343
344
345 LOG_FUNCTION_START("");
346
347 /* check if the following are selected
348 * VL53L1_PRESETMODE_AUTONOMOUS,
349 * VL53L1_PRESETMODE_LOWPOWER_AUTONOMOUS
350 * VL53L1_PRESETMODE_LITE_RANGING
351 */
352 PresetMode = VL53L1DevDataGet(Dev, CurrentParameters.PresetMode);
353
354 if ((PresetMode != VL53L1_PRESETMODE_AUTONOMOUS) &&
355 (PresetMode != VL53L1_PRESETMODE_LOWPOWER_AUTONOMOUS) &&
356 (PresetMode != VL53L1_PRESETMODE_LITE_RANGING)) {
357 Status = VL53L1_ERROR_MODE_NOT_SUPPORTED;
358 goto ENDFUNC;
359 }
360
361 /* disable crosstalk calibration */
362 Status = VL53L1_disable_xtalk_compensation(Dev);
363
364 if (Status != VL53L1_ERROR_NONE)
365 goto ENDFUNC;
366
367 Status = VL53L1_StartMeasurement(Dev);
368
369 if (Status != VL53L1_ERROR_NONE)
370 goto ENDFUNC;
371
372 /* First measurement is never relevant */
373 VL53L1_WaitMeasurementDataReady(Dev);
374 VL53L1_GetRangingMeasurementData(Dev, &RMData);
375 VL53L1_ClearInterruptAndStartMeasurement(Dev);
376
377 sum_ranging = 0;
378 sum_spads = 0;
379 sum_signalRate = 0;
380 total_count = 0;
381 for (xtalk_meas = 0; xtalk_meas < xtalk_measmax; xtalk_meas++) {
382 VL53L1_WaitMeasurementDataReady(Dev);
383 VL53L1_GetRangingMeasurementData(Dev, &RMData);
384 VL53L1_ClearInterruptAndStartMeasurement(Dev);
385 if (RMData.RangeStatus == VL53L1_RANGESTATUS_RANGE_VALID) {
386 sum_ranging += RMData.RangeMilliMeter;
387 sum_signalRate += RMData.SignalRateRtnMegaCps;
388 sum_spads += RMData.EffectiveSpadRtnCount / 256;
389 total_count++;
390 }
391 }
392 Status = VL53L1_StopMeasurement(Dev);
393
394 if (total_count > 0) {
395 /* FixPoint1616_t / uint16_t = FixPoint1616_t */
396 xTalkStoredMeanSignalRate = sum_signalRate / total_count;
397 xTalkStoredMeanRange = (FixPoint1616_t)(sum_ranging << 16);
398 xTalkStoredMeanRange /= total_count;
399 xTalkStoredMeanRtnSpads = (FixPoint1616_t)(sum_spads << 16);
400 xTalkStoredMeanRtnSpads /= total_count;
401
402 /* Round Mean Spads to Whole Number.
403 * Typically the calculated mean SPAD count is a whole number
404 * or very close to a whole
405 * number, therefore any truncation will not result in a
406 * significant loss in accuracy.
407 * Also, for a grey target at a typical distance of around
408 * 400mm, around 220 SPADs will
409 * be enabled, therefore, any truncation will result in a loss
410 * of accuracy of less than
411 * 0.5%.
412 */
413 xTalkStoredMeanRtnSpadsAsInt = (xTalkStoredMeanRtnSpads +
414 0x8000) >> 16;
415
416 /* Round Cal Distance to Whole Number.
417 * Note that the cal distance is in mm, therefore no resolution
418 * is lost.
419 */
420 xTalkCalDistanceAsInt = ((uint32_t)BDTable[
421 VL53L1_TUNING_SINGLE_TARGET_XTALK_TARGET_DISTANCE_MM]);
422 if (xTalkStoredMeanRtnSpadsAsInt == 0 ||
423 xTalkCalDistanceAsInt == 0 ||
424 xTalkStoredMeanRange >= (xTalkCalDistanceAsInt << 16)) {
425 XTalkCompensationRateMegaCps = 0;
426 } else {
427 /* Apply division by mean spad count early in the
428 * calculation to keep the numbers small.
429 * This ensures we can maintain a 32bit calculation.
430 * Fixed1616 / int := Fixed1616
431 */
432 signalXTalkTotalPerSpad = (xTalkStoredMeanSignalRate) /
433 xTalkStoredMeanRtnSpadsAsInt;
434
435 /* Complete the calculation for total Signal XTalk per
436 * SPAD
437 * Fixed1616 * (Fixed1616 - Fixed1616/int) :=
438 * (2^16 * Fixed1616)
439 */
440 signalXTalkTotalPerSpad *= (((uint32_t)1 << 16) -
441 (xTalkStoredMeanRange / xTalkCalDistanceAsInt));
442
443 /* Round from 2^16 * Fixed1616, to Fixed1616. */
444 XTalkCompensationRateMegaCps = (signalXTalkTotalPerSpad
445 + 0x8000) >> 16;
446 }
447
448
449 Status = VL53L1_GetCalibrationData(Dev, &CalibrationData);
450
451 if (Status != VL53L1_ERROR_NONE)
452 goto ENDFUNC;
453
454 pC = &CalibrationData.customer;
455
456 pC->algo__crosstalk_compensation_plane_offset_kcps =
457 (uint32_t)(1000 * ((XTalkCompensationRateMegaCps +
458 ((uint32_t)1<<6)) >> (16-9)));
459
460 Status = VL53L1_SetCalibrationData(Dev, &CalibrationData);
461
462 if (Status != VL53L1_ERROR_NONE)
463 goto ENDFUNC;
464
465 Status = VL53L1_enable_xtalk_compensation(Dev);
466
467 } else
468 /* return error because no valid data found */
469 Status = VL53L1_ERROR_XTALK_EXTRACTION_NO_SAMPLE_FAIL;
470
471 ENDFUNC:
472 LOG_FUNCTION_END(Status);
473 return Status;
474
475 }
476
477 /* Check Rectangle in user's coordinate system:
478 * 15 TL(x,y) o-----*
479 * ^ | |
480 * | *-----o BR(x,y)
481 * 0------------------------- >15
482 * check Rectangle definition conforms to the (0,15,15) coordinate system
483 * with a minimum of 4x4 size
484 */
CheckValidRectRoi(VL53L1_UserRoi_t ROI)485 static VL53L1_Error CheckValidRectRoi(VL53L1_UserRoi_t ROI)
486 {
487 VL53L1_Error Status = VL53L1_ERROR_NONE;
488
489 LOG_FUNCTION_START("");
490
491 /* Negative check are not necessary because value is unsigned */
492 if ((ROI.TopLeftX > 15) || (ROI.TopLeftY > 15) ||
493 (ROI.BotRightX > 15) || (ROI.BotRightY > 15))
494 Status = VL53L1_ERROR_INVALID_PARAMS;
495
496 if ((ROI.TopLeftX > ROI.BotRightX) || (ROI.TopLeftY < ROI.BotRightY))
497 Status = VL53L1_ERROR_INVALID_PARAMS;
498
499 LOG_FUNCTION_END(Status);
500 return Status;
501 }
502
ConvertModeToLLD(VL53L1_Error * pStatus,VL53L1_ThresholdMode CrossMode)503 static VL53L1_GPIO_Interrupt_Mode ConvertModeToLLD(VL53L1_Error *pStatus,
504 VL53L1_ThresholdMode CrossMode)
505 {
506 VL53L1_GPIO_Interrupt_Mode Mode;
507
508 switch (CrossMode) {
509 case VL53L1_THRESHOLD_CROSSED_LOW:
510 Mode = VL53L1_GPIOINTMODE_LEVEL_LOW;
511 break;
512 case VL53L1_THRESHOLD_CROSSED_HIGH:
513 Mode = VL53L1_GPIOINTMODE_LEVEL_HIGH;
514 break;
515 case VL53L1_THRESHOLD_OUT_OF_WINDOW:
516 Mode = VL53L1_GPIOINTMODE_OUT_OF_WINDOW;
517 break;
518 case VL53L1_THRESHOLD_IN_WINDOW:
519 Mode = VL53L1_GPIOINTMODE_IN_WINDOW;
520 break;
521 default:
522 /* define Mode to avoid warning but actual value doesn't mind */
523 Mode = VL53L1_GPIOINTMODE_LEVEL_HIGH;
524 *pStatus = VL53L1_ERROR_INVALID_PARAMS;
525 }
526 return Mode;
527 }
528
ConvertModeFromLLD(VL53L1_Error * pStatus,VL53L1_GPIO_Interrupt_Mode CrossMode)529 static VL53L1_ThresholdMode ConvertModeFromLLD(VL53L1_Error *pStatus,
530 VL53L1_GPIO_Interrupt_Mode CrossMode)
531 {
532 VL53L1_ThresholdMode Mode;
533
534 switch (CrossMode) {
535 case VL53L1_GPIOINTMODE_LEVEL_LOW:
536 Mode = VL53L1_THRESHOLD_CROSSED_LOW;
537 break;
538 case VL53L1_GPIOINTMODE_LEVEL_HIGH:
539 Mode = VL53L1_THRESHOLD_CROSSED_HIGH;
540 break;
541 case VL53L1_GPIOINTMODE_OUT_OF_WINDOW:
542 Mode = VL53L1_THRESHOLD_OUT_OF_WINDOW;
543 break;
544 case VL53L1_GPIOINTMODE_IN_WINDOW:
545 Mode = VL53L1_THRESHOLD_IN_WINDOW;
546 break;
547 default:
548 /* define Mode to avoid warning but actual value doesn't mind */
549 Mode = VL53L1_THRESHOLD_CROSSED_HIGH;
550 *pStatus = VL53L1_ERROR_UNDEFINED;
551 }
552 return Mode;
553 }
554
555 /* Group PAL General Functions */
556
VL53L1_GetVersion(VL53L1_Version_t * pVersion)557 VL53L1_Error VL53L1_GetVersion(VL53L1_Version_t *pVersion)
558 {
559 VL53L1_Error Status = VL53L1_ERROR_NONE;
560
561 LOG_FUNCTION_START("");
562
563 pVersion->major = VL53L1_IMPLEMENTATION_VER_MAJOR;
564 pVersion->minor = VL53L1_IMPLEMENTATION_VER_MINOR;
565 pVersion->build = VL53L1_IMPLEMENTATION_VER_SUB;
566
567 pVersion->revision = VL53L1_IMPLEMENTATION_VER_REVISION;
568
569 LOG_FUNCTION_END(Status);
570 return Status;
571 }
572
VL53L1_GetProductRevision(VL53L1_DEV Dev,uint8_t * pProductRevisionMajor,uint8_t * pProductRevisionMinor)573 VL53L1_Error VL53L1_GetProductRevision(VL53L1_DEV Dev,
574 uint8_t *pProductRevisionMajor, uint8_t *pProductRevisionMinor)
575 {
576 VL53L1_Error Status = VL53L1_ERROR_NONE;
577 uint8_t revision_id;
578 VL53L1_LLDriverData_t *pLLData;
579
580 LOG_FUNCTION_START("");
581
582 pLLData = VL53L1DevStructGetLLDriverHandle(Dev);
583 revision_id = pLLData->nvm_copy_data.identification__revision_id;
584 *pProductRevisionMajor = 1;
585 *pProductRevisionMinor = (revision_id & 0xF0) >> 4;
586
587 LOG_FUNCTION_END(Status);
588 return Status;
589
590 }
591
VL53L1_GetDeviceInfo(VL53L1_DEV Dev,VL53L1_DeviceInfo_t * pVL53L1_DeviceInfo)592 VL53L1_Error VL53L1_GetDeviceInfo(VL53L1_DEV Dev,
593 VL53L1_DeviceInfo_t *pVL53L1_DeviceInfo)
594 {
595 VL53L1_Error Status = VL53L1_ERROR_NONE;
596 uint8_t revision_id;
597 VL53L1_LLDriverData_t *pLLData;
598
599 LOG_FUNCTION_START("");
600
601 pLLData = VL53L1DevStructGetLLDriverHandle(Dev);
602
603 strncpy(pVL53L1_DeviceInfo->ProductId, "",
604 VL53L1_DEVINFO_STRLEN-1);
605 pVL53L1_DeviceInfo->ProductType =
606 pLLData->nvm_copy_data.identification__module_type;
607
608 revision_id = pLLData->nvm_copy_data.identification__revision_id;
609 pVL53L1_DeviceInfo->ProductRevisionMajor = 1;
610 pVL53L1_DeviceInfo->ProductRevisionMinor = (revision_id & 0xF0) >> 4;
611
612 #ifndef VL53L1_USE_EMPTY_STRING
613 if (pVL53L1_DeviceInfo->ProductRevisionMinor == 0)
614 strncpy(pVL53L1_DeviceInfo->Name,
615 VL53L1_STRING_DEVICE_INFO_NAME0,
616 VL53L1_DEVINFO_STRLEN-1);
617 else
618 strncpy(pVL53L1_DeviceInfo->Name,
619 VL53L1_STRING_DEVICE_INFO_NAME1,
620 VL53L1_DEVINFO_STRLEN-1);
621 strncpy(pVL53L1_DeviceInfo->Type,
622 VL53L1_STRING_DEVICE_INFO_TYPE,
623 VL53L1_DEVINFO_STRLEN-1);
624 /* Is module_type (ProductType) "evo" aka VL53L3 instead of VL53L1 ? */
625 if (pVL53L1_DeviceInfo->ProductType == 0xAA) {
626 pVL53L1_DeviceInfo->Name[5] = '3';
627 pVL53L1_DeviceInfo->Type[5] = '3';
628 }
629 #else
630 pVL53L1_DeviceInfo->Name[0] = 0;
631 pVL53L1_DeviceInfo->Type[0] = 0;
632 #endif
633
634 LOG_FUNCTION_END(Status);
635 return Status;
636 }
637
VL53L1_GetUID(VL53L1_DEV Dev,uint64_t * pUid)638 VL53L1_Error VL53L1_GetUID(VL53L1_DEV Dev, uint64_t *pUid)
639 {
640 VL53L1_Error Status = VL53L1_ERROR_NONE;
641 uint8_t fmtdata[8];
642
643 LOG_FUNCTION_START("");
644
645 Status = VL53L1_read_nvm_raw_data(Dev,
646 (uint8_t)(0x1F8 >> 2),
647 (uint8_t)(8 >> 2),
648 fmtdata);
649 memcpy(pUid, fmtdata, sizeof(uint64_t));
650
651 LOG_FUNCTION_END(Status);
652 return Status;
653 }
654
VL53L1_GetRangeStatusString(uint8_t RangeStatus,char * pRangeStatusString)655 VL53L1_Error VL53L1_GetRangeStatusString(uint8_t RangeStatus,
656 char *pRangeStatusString)
657 {
658 VL53L1_Error Status = VL53L1_ERROR_NONE;
659
660 LOG_FUNCTION_START("");
661
662 Status = VL53L1_get_range_status_string(RangeStatus,
663 pRangeStatusString);
664
665 LOG_FUNCTION_END(Status);
666 return Status;
667 }
668
VL53L1_GetPalErrorString(VL53L1_Error PalErrorCode,char * pPalErrorString)669 VL53L1_Error VL53L1_GetPalErrorString(VL53L1_Error PalErrorCode,
670 char *pPalErrorString)
671 {
672 VL53L1_Error Status = VL53L1_ERROR_NONE;
673
674 LOG_FUNCTION_START("");
675
676 Status = VL53L1_get_pal_error_string(PalErrorCode, pPalErrorString);
677
678 LOG_FUNCTION_END(Status);
679 return Status;
680 }
681
VL53L1_GetPalStateString(VL53L1_State PalStateCode,char * pPalStateString)682 VL53L1_Error VL53L1_GetPalStateString(VL53L1_State PalStateCode,
683 char *pPalStateString)
684 {
685 VL53L1_Error Status = VL53L1_ERROR_NONE;
686
687 LOG_FUNCTION_START("");
688
689 Status = VL53L1_get_pal_state_string(PalStateCode, pPalStateString);
690
691 LOG_FUNCTION_END(Status);
692 return Status;
693 }
694
VL53L1_GetPalState(VL53L1_DEV Dev,VL53L1_State * pPalState)695 VL53L1_Error VL53L1_GetPalState(VL53L1_DEV Dev, VL53L1_State *pPalState)
696 {
697 VL53L1_Error Status = VL53L1_ERROR_NONE;
698
699 LOG_FUNCTION_START("");
700
701 *pPalState = VL53L1DevDataGet(Dev, PalState);
702
703 LOG_FUNCTION_END(Status);
704 return Status;
705 }
706
707 /* End Group PAL General Functions */
708
709 /* Group PAL Init Functions */
VL53L1_SetDeviceAddress(VL53L1_DEV Dev,uint8_t DeviceAddress)710 VL53L1_Error VL53L1_SetDeviceAddress(VL53L1_DEV Dev, uint8_t DeviceAddress)
711 {
712 VL53L1_Error Status = VL53L1_ERROR_NONE;
713 VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev);
714 VL53L1_static_nvm_managed_t *pdata = &(pdev->stat_nvm);
715
716 LOG_FUNCTION_START("");
717
718 Status = VL53L1_WrByte(Dev, VL53L1_I2C_SLAVE__DEVICE_ADDRESS,
719 DeviceAddress / 2);
720
721 pdata->i2c_slave__device_address = (DeviceAddress / 2) & 0x7F;
722
723 LOG_FUNCTION_END(Status);
724 return Status;
725 }
726
VL53L1_DataInit(VL53L1_DEV Dev)727 VL53L1_Error VL53L1_DataInit(VL53L1_DEV Dev)
728 {
729 VL53L1_Error Status = VL53L1_ERROR_NONE;
730 uint8_t i;
731
732 LOG_FUNCTION_START("");
733
734 /* 2V8 power mode selection codex 447463 */
735 #ifdef USE_I2C_2V8
736 Status = VL53L1_RdByte(Dev, VL53L1_PAD_I2C_HV__EXTSUP_CONFIG, &i);
737 if (Status == VL53L1_ERROR_NONE) {
738 i = (i & 0xfe) | 0x01;
739 Status = VL53L1_WrByte(Dev, VL53L1_PAD_I2C_HV__EXTSUP_CONFIG,
740 i);
741 }
742 #endif
743
744 if (Status == VL53L1_ERROR_NONE)
745 Status = VL53L1_data_init(Dev, 1);
746
747
748 if (Status == VL53L1_ERROR_NONE)
749 VL53L1DevDataSet(Dev, PalState, VL53L1_STATE_WAIT_STATICINIT);
750
751 /* Enable all check */
752 for (i = 0; i < VL53L1_CHECKENABLE_NUMBER_OF_CHECKS; i++) {
753 if (Status == VL53L1_ERROR_NONE)
754 Status |= VL53L1_SetLimitCheckEnable(Dev, i, 1);
755 else
756 break;
757
758 }
759
760
761 LOG_FUNCTION_END(Status);
762 return Status;
763 }
764
765
VL53L1_StaticInit(VL53L1_DEV Dev)766 VL53L1_Error VL53L1_StaticInit(VL53L1_DEV Dev)
767 {
768 VL53L1_Error Status = VL53L1_ERROR_NONE;
769 uint8_t measurement_mode;
770
771 LOG_FUNCTION_START("");
772
773 VL53L1DevDataSet(Dev, PalState, VL53L1_STATE_IDLE);
774
775 measurement_mode = VL53L1_DEVICEMEASUREMENTMODE_BACKTOBACK;
776 VL53L1DevDataSet(Dev, LLData.measurement_mode, measurement_mode);
777
778 /* ticket 472728 fix */
779 Status = VL53L1_SetPresetMode(Dev,
780 VL53L1_PRESETMODE_LOWPOWER_AUTONOMOUS);
781 VL53L1DevDataSet(Dev, CurrentParameters.PresetMode,
782 VL53L1_PRESETMODE_LOWPOWER_AUTONOMOUS);
783 /* end of ticket 472728 fix */
784
785 LOG_FUNCTION_END(Status);
786 return Status;
787 }
788
VL53L1_WaitDeviceBooted(VL53L1_DEV Dev)789 VL53L1_Error VL53L1_WaitDeviceBooted(VL53L1_DEV Dev)
790 {
791 VL53L1_Error Status = VL53L1_ERROR_NONE;
792
793 LOG_FUNCTION_START("");
794
795 Status = VL53L1_poll_for_boot_completion(Dev,
796 VL53L1_BOOT_COMPLETION_POLLING_TIMEOUT_MS);
797
798 LOG_FUNCTION_END(Status);
799 return Status;
800 }
801
802 /* End Group PAL Init Functions */
803
804 /* Group PAL Parameters Functions */
ComputeDevicePresetMode(VL53L1_PresetModes PresetMode,VL53L1_DistanceModes DistanceMode,VL53L1_DevicePresetModes * pDevicePresetMode)805 static VL53L1_Error ComputeDevicePresetMode(
806 VL53L1_PresetModes PresetMode,
807 VL53L1_DistanceModes DistanceMode,
808 VL53L1_DevicePresetModes *pDevicePresetMode)
809 {
810 VL53L1_Error Status = VL53L1_ERROR_NONE;
811
812 uint8_t DistIdx;
813 VL53L1_DevicePresetModes LightModes[3] = {
814 VL53L1_DEVICEPRESETMODE_STANDARD_RANGING_SHORT_RANGE,
815 VL53L1_DEVICEPRESETMODE_STANDARD_RANGING,
816 VL53L1_DEVICEPRESETMODE_STANDARD_RANGING_LONG_RANGE};
817
818
819 VL53L1_DevicePresetModes TimedModes[3] = {
820 VL53L1_DEVICEPRESETMODE_TIMED_RANGING_SHORT_RANGE,
821 VL53L1_DEVICEPRESETMODE_TIMED_RANGING,
822 VL53L1_DEVICEPRESETMODE_TIMED_RANGING_LONG_RANGE};
823
824 VL53L1_DevicePresetModes LowPowerTimedModes[3] = {
825 VL53L1_DEVICEPRESETMODE_LOWPOWERAUTO_SHORT_RANGE,
826 VL53L1_DEVICEPRESETMODE_LOWPOWERAUTO_MEDIUM_RANGE,
827 VL53L1_DEVICEPRESETMODE_LOWPOWERAUTO_LONG_RANGE};
828
829 *pDevicePresetMode = VL53L1_DEVICEPRESETMODE_STANDARD_RANGING;
830
831 switch (DistanceMode) {
832 case VL53L1_DISTANCEMODE_SHORT:
833 DistIdx = 0;
834 break;
835 case VL53L1_DISTANCEMODE_MEDIUM:
836 DistIdx = 1;
837 break;
838 default:
839 DistIdx = 2;
840 }
841
842 switch (PresetMode) {
843 case VL53L1_PRESETMODE_LITE_RANGING:
844 *pDevicePresetMode = LightModes[DistIdx];
845 break;
846
847
848 case VL53L1_PRESETMODE_AUTONOMOUS:
849 *pDevicePresetMode = TimedModes[DistIdx];
850 break;
851
852 case VL53L1_PRESETMODE_LOWPOWER_AUTONOMOUS:
853 *pDevicePresetMode = LowPowerTimedModes[DistIdx];
854 break;
855
856 default:
857 /* Unsupported mode */
858 Status = VL53L1_ERROR_MODE_NOT_SUPPORTED;
859 }
860
861 return Status;
862 }
863
SetPresetMode(VL53L1_DEV Dev,VL53L1_PresetModes PresetMode,VL53L1_DistanceModes DistanceMode,uint32_t inter_measurement_period_ms)864 static VL53L1_Error SetPresetMode(VL53L1_DEV Dev,
865 VL53L1_PresetModes PresetMode,
866 VL53L1_DistanceModes DistanceMode,
867 uint32_t inter_measurement_period_ms)
868 {
869 VL53L1_Error Status = VL53L1_ERROR_NONE;
870 VL53L1_DevicePresetModes device_preset_mode;
871 uint8_t measurement_mode;
872 uint16_t dss_config__target_total_rate_mcps = 0;
873 uint32_t phasecal_config_timeout_us = 0;
874 uint32_t mm_config_timeout_us = 0;
875 uint32_t lld_range_config_timeout_us = 0;
876
877 LOG_FUNCTION_START("%d", (int)PresetMode);
878
879 if ((PresetMode == VL53L1_PRESETMODE_AUTONOMOUS) ||
880 (PresetMode == VL53L1_PRESETMODE_LOWPOWER_AUTONOMOUS))
881 measurement_mode = VL53L1_DEVICEMEASUREMENTMODE_TIMED;
882 else
883 measurement_mode = VL53L1_DEVICEMEASUREMENTMODE_BACKTOBACK;
884
885
886 Status = ComputeDevicePresetMode(PresetMode, DistanceMode,
887 &device_preset_mode);
888
889 if (Status == VL53L1_ERROR_NONE)
890 Status = VL53L1_get_preset_mode_timing_cfg(Dev,
891 device_preset_mode,
892 &dss_config__target_total_rate_mcps,
893 &phasecal_config_timeout_us,
894 &mm_config_timeout_us,
895 &lld_range_config_timeout_us);
896
897 if (Status == VL53L1_ERROR_NONE)
898 Status = VL53L1_set_preset_mode(
899 Dev,
900 device_preset_mode,
901 dss_config__target_total_rate_mcps,
902 phasecal_config_timeout_us,
903 mm_config_timeout_us,
904 lld_range_config_timeout_us,
905 inter_measurement_period_ms);
906
907 if (Status == VL53L1_ERROR_NONE)
908 VL53L1DevDataSet(Dev, LLData.measurement_mode,
909 measurement_mode);
910
911 if (Status == VL53L1_ERROR_NONE)
912 VL53L1DevDataSet(Dev, CurrentParameters.PresetMode, PresetMode);
913
914 LOG_FUNCTION_END(Status);
915 return Status;
916 }
917
VL53L1_SetInterruptPolarity(VL53L1_DEV Dev,VL53L1_DeviceInterruptPolarity interrupt_polarity)918 VL53L1_Error VL53L1_SetInterruptPolarity(VL53L1_DEV Dev,
919 VL53L1_DeviceInterruptPolarity interrupt_polarity)
920 {
921 VL53L1_Error Status = VL53L1_ERROR_NONE;
922
923 LOG_FUNCTION_START("");
924
925 Status = VL53L1_set_interrupt_polarity(Dev, interrupt_polarity);
926
927 LOG_FUNCTION_END(Status);
928 return Status;
929 }
930
VL53L1_GetInterruptPolarity(VL53L1_DEV Dev,VL53L1_DeviceInterruptPolarity * pinterrupt_polarity)931 VL53L1_Error VL53L1_GetInterruptPolarity(VL53L1_DEV Dev,
932 VL53L1_DeviceInterruptPolarity *pinterrupt_polarity)
933 {
934 VL53L1_Error Status = VL53L1_ERROR_NONE;
935
936 LOG_FUNCTION_START("");
937
938 Status = VL53L1_get_interrupt_polarity(Dev, pinterrupt_polarity);
939
940 LOG_FUNCTION_END(Status);
941 return Status;
942 }
943
944
VL53L1_SetPresetMode(VL53L1_DEV Dev,VL53L1_PresetModes PresetMode)945 VL53L1_Error VL53L1_SetPresetMode(VL53L1_DEV Dev, VL53L1_PresetModes PresetMode)
946 {
947 VL53L1_Error Status = VL53L1_ERROR_NONE;
948 VL53L1_DistanceModes DistanceMode = VL53L1_DISTANCEMODE_LONG;
949
950 LOG_FUNCTION_START("%d", (int)PresetMode);
951
952 /* fix for bug 495690 */
953 Status = VL53L1_low_power_auto_data_init(Dev);
954
955 Status = SetPresetMode(Dev,
956 PresetMode,
957 DistanceMode,
958 1000);
959
960 if (Status == VL53L1_ERROR_NONE) {
961 if ((PresetMode == VL53L1_PRESETMODE_LITE_RANGING) ||
962 (PresetMode == VL53L1_PRESETMODE_AUTONOMOUS) ||
963 (PresetMode == VL53L1_PRESETMODE_LOWPOWER_AUTONOMOUS))
964 Status = VL53L1_SetMeasurementTimingBudgetMicroSeconds(
965 Dev, 41000);
966 else
967 /* Set default timing budget to 30Hz (33.33 ms)*/
968 Status = VL53L1_SetMeasurementTimingBudgetMicroSeconds(
969 Dev, 33333);
970 }
971
972 if (Status == VL53L1_ERROR_NONE) {
973 /* Set default intermeasurement period to 1000 ms */
974 Status = VL53L1_SetInterMeasurementPeriodMilliSeconds(Dev,
975 1000);
976 }
977
978 LOG_FUNCTION_END(Status);
979 return Status;
980 }
981
982
VL53L1_GetPresetMode(VL53L1_DEV Dev,VL53L1_PresetModes * pPresetMode)983 VL53L1_Error VL53L1_GetPresetMode(VL53L1_DEV Dev,
984 VL53L1_PresetModes *pPresetMode)
985 {
986 VL53L1_Error Status = VL53L1_ERROR_NONE;
987
988 LOG_FUNCTION_START("");
989
990 *pPresetMode = VL53L1DevDataGet(Dev, CurrentParameters.PresetMode);
991
992 LOG_FUNCTION_END(Status);
993 return Status;
994 }
995
VL53L1_SetDistanceMode(VL53L1_DEV Dev,VL53L1_DistanceModes DistanceMode)996 VL53L1_Error VL53L1_SetDistanceMode(VL53L1_DEV Dev,
997 VL53L1_DistanceModes DistanceMode)
998 {
999 VL53L1_Error Status = VL53L1_ERROR_NONE;
1000 VL53L1_PresetModes PresetMode;
1001 uint32_t inter_measurement_period_ms;
1002 uint32_t TimingBudget = 0;
1003 uint32_t MmTimeoutUs = 0;
1004 uint32_t PhaseCalTimeoutUs = 0;
1005 VL53L1_user_zone_t user_zone;
1006
1007 LOG_FUNCTION_START("%d", (int)DistanceMode);
1008
1009 PresetMode = VL53L1DevDataGet(Dev, CurrentParameters.PresetMode);
1010
1011 /* when the distance mode is valid:
1012 * Manual Mode: all modes
1013 * AUTO AUTO_LITE : LITE_RANGING, RANGING
1014 */
1015
1016 if ((DistanceMode != VL53L1_DISTANCEMODE_SHORT) &&
1017 (DistanceMode != VL53L1_DISTANCEMODE_MEDIUM) &&
1018 (DistanceMode != VL53L1_DISTANCEMODE_LONG))
1019 return VL53L1_ERROR_INVALID_PARAMS;
1020
1021 if (Status == VL53L1_ERROR_NONE)
1022 Status = VL53L1_get_user_zone(Dev, &user_zone);
1023
1024 inter_measurement_period_ms = VL53L1DevDataGet(Dev,
1025 LLData.inter_measurement_period_ms);
1026
1027 if (Status == VL53L1_ERROR_NONE)
1028 Status = VL53L1_get_timeouts_us(Dev, &PhaseCalTimeoutUs,
1029 &MmTimeoutUs, &TimingBudget);
1030
1031 if (Status == VL53L1_ERROR_NONE)
1032 Status = SetPresetMode(Dev,
1033 PresetMode,
1034 DistanceMode,
1035 inter_measurement_period_ms);
1036
1037 if (Status == VL53L1_ERROR_NONE) {
1038 VL53L1DevDataSet(Dev, CurrentParameters.DistanceMode,
1039 DistanceMode);
1040 }
1041
1042 if (Status == VL53L1_ERROR_NONE) {
1043 Status = VL53L1_set_timeouts_us(Dev, PhaseCalTimeoutUs,
1044 MmTimeoutUs, TimingBudget);
1045
1046 if (Status == VL53L1_ERROR_NONE)
1047 VL53L1DevDataSet(Dev, LLData.range_config_timeout_us,
1048 TimingBudget);
1049 }
1050
1051 if (Status == VL53L1_ERROR_NONE)
1052 Status = VL53L1_set_user_zone(Dev, &user_zone);
1053
1054 LOG_FUNCTION_END(Status);
1055 return Status;
1056 }
1057
VL53L1_GetDistanceMode(VL53L1_DEV Dev,VL53L1_DistanceModes * pDistanceMode)1058 VL53L1_Error VL53L1_GetDistanceMode(VL53L1_DEV Dev,
1059 VL53L1_DistanceModes *pDistanceMode)
1060 {
1061 VL53L1_Error Status = VL53L1_ERROR_NONE;
1062
1063 LOG_FUNCTION_START("");
1064
1065 *pDistanceMode = VL53L1DevDataGet(Dev, CurrentParameters.DistanceMode);
1066
1067 LOG_FUNCTION_END(Status);
1068 return Status;
1069 }
1070
1071
1072
1073
VL53L1_SetMeasurementTimingBudgetMicroSeconds(VL53L1_DEV Dev,uint32_t MeasurementTimingBudgetMicroSeconds)1074 VL53L1_Error VL53L1_SetMeasurementTimingBudgetMicroSeconds(VL53L1_DEV Dev,
1075 uint32_t MeasurementTimingBudgetMicroSeconds)
1076 {
1077 VL53L1_Error Status = VL53L1_ERROR_NONE;
1078 uint8_t Mm1Enabled = 0;
1079 uint8_t Mm2Enabled = 0;
1080 uint32_t TimingGuard;
1081 uint32_t divisor;
1082 uint32_t TimingBudget = 0;
1083 uint32_t MmTimeoutUs = 0;
1084 VL53L1_PresetModes PresetMode;
1085 uint32_t PhaseCalTimeoutUs = 0;
1086 uint32_t vhv;
1087 int32_t vhv_loops;
1088 uint32_t FDAMaxTimingBudgetUs = FDA_MAX_TIMING_BUDGET_US;
1089
1090 LOG_FUNCTION_START("");
1091
1092 /* Timing budget is limited to 10 seconds */
1093 if (MeasurementTimingBudgetMicroSeconds > 10000000)
1094 Status = VL53L1_ERROR_INVALID_PARAMS;
1095
1096 if (Status == VL53L1_ERROR_NONE) {
1097 Status = VL53L1_GetSequenceStepEnable(Dev,
1098 VL53L1_SEQUENCESTEP_MM1, &Mm1Enabled);
1099 }
1100
1101 if (Status == VL53L1_ERROR_NONE) {
1102 Status = VL53L1_GetSequenceStepEnable(Dev,
1103 VL53L1_SEQUENCESTEP_MM2, &Mm2Enabled);
1104 }
1105
1106 if (Status == VL53L1_ERROR_NONE)
1107 Status = VL53L1_get_timeouts_us(Dev,
1108 &PhaseCalTimeoutUs,
1109 &MmTimeoutUs,
1110 &TimingBudget);
1111
1112 if (Status == VL53L1_ERROR_NONE) {
1113 PresetMode = VL53L1DevDataGet(Dev,
1114 CurrentParameters.PresetMode);
1115
1116 TimingGuard = 0;
1117 divisor = 1;
1118 switch (PresetMode) {
1119 case VL53L1_PRESETMODE_LITE_RANGING:
1120 if ((Mm1Enabled == 1) || (Mm2Enabled == 1))
1121 TimingGuard = 5000;
1122 else
1123 TimingGuard = 1000;
1124 break;
1125
1126 case VL53L1_PRESETMODE_AUTONOMOUS:
1127 FDAMaxTimingBudgetUs *= 2;
1128 if ((Mm1Enabled == 1) || (Mm2Enabled == 1))
1129 TimingGuard = 26600;
1130 else
1131 TimingGuard = 21600;
1132 divisor = 2;
1133 break;
1134
1135 case VL53L1_PRESETMODE_LOWPOWER_AUTONOMOUS:
1136 FDAMaxTimingBudgetUs *= 2;
1137 vhv = LOWPOWER_AUTO_VHV_LOOP_DURATION_US;
1138 VL53L1_get_tuning_parm(Dev,
1139 VL53L1_TUNINGPARM_LOWPOWERAUTO_VHV_LOOP_BOUND,
1140 &vhv_loops);
1141 if (vhv_loops > 0) {
1142 vhv += vhv_loops *
1143 LOWPOWER_AUTO_VHV_LOOP_DURATION_US;
1144 }
1145 TimingGuard = LOWPOWER_AUTO_OVERHEAD_BEFORE_A_RANGING +
1146 LOWPOWER_AUTO_OVERHEAD_BETWEEN_A_B_RANGING +
1147 vhv;
1148 divisor = 2;
1149 break;
1150
1151 default:
1152 /* Unsupported mode */
1153 Status = VL53L1_ERROR_MODE_NOT_SUPPORTED;
1154 }
1155
1156 if (MeasurementTimingBudgetMicroSeconds <= TimingGuard)
1157 Status = VL53L1_ERROR_INVALID_PARAMS;
1158 else {
1159 TimingBudget = (MeasurementTimingBudgetMicroSeconds
1160 - TimingGuard);
1161 }
1162
1163 if (Status == VL53L1_ERROR_NONE) {
1164 if (TimingBudget > FDAMaxTimingBudgetUs)
1165 Status = VL53L1_ERROR_INVALID_PARAMS;
1166 else {
1167 TimingBudget /= divisor;
1168 Status = VL53L1_set_timeouts_us(
1169 Dev,
1170 PhaseCalTimeoutUs,
1171 MmTimeoutUs,
1172 TimingBudget);
1173 }
1174
1175 if (Status == VL53L1_ERROR_NONE)
1176 VL53L1DevDataSet(Dev,
1177 LLData.range_config_timeout_us,
1178 TimingBudget);
1179 }
1180 }
1181 if (Status == VL53L1_ERROR_NONE) {
1182 VL53L1DevDataSet(Dev,
1183 CurrentParameters.MeasurementTimingBudgetMicroSeconds,
1184 MeasurementTimingBudgetMicroSeconds);
1185 }
1186
1187 LOG_FUNCTION_END(Status);
1188 return Status;
1189 }
1190
1191
VL53L1_GetMeasurementTimingBudgetMicroSeconds(VL53L1_DEV Dev,uint32_t * pMeasurementTimingBudgetMicroSeconds)1192 VL53L1_Error VL53L1_GetMeasurementTimingBudgetMicroSeconds(VL53L1_DEV Dev,
1193 uint32_t *pMeasurementTimingBudgetMicroSeconds)
1194 {
1195 VL53L1_Error Status = VL53L1_ERROR_NONE;
1196 uint8_t Mm1Enabled = 0;
1197 uint8_t Mm2Enabled = 0;
1198 uint32_t MmTimeoutUs = 0;
1199 uint32_t RangeTimeoutUs = 0;
1200 uint32_t MeasTimingBdg = 0;
1201 uint32_t PhaseCalTimeoutUs = 0;
1202 VL53L1_PresetModes PresetMode;
1203 uint32_t TimingGuard;
1204 uint32_t vhv;
1205 int32_t vhv_loops;
1206
1207 LOG_FUNCTION_START("");
1208
1209 *pMeasurementTimingBudgetMicroSeconds = 0;
1210
1211 if (Status == VL53L1_ERROR_NONE)
1212 Status = VL53L1_GetSequenceStepEnable(Dev,
1213 VL53L1_SEQUENCESTEP_MM1, &Mm1Enabled);
1214
1215 if (Status == VL53L1_ERROR_NONE)
1216 Status = VL53L1_GetSequenceStepEnable(Dev,
1217 VL53L1_SEQUENCESTEP_MM2, &Mm2Enabled);
1218
1219 if (Status == VL53L1_ERROR_NONE)
1220 Status = VL53L1_get_timeouts_us(Dev,
1221 &PhaseCalTimeoutUs,
1222 &MmTimeoutUs,
1223 &RangeTimeoutUs);
1224
1225 if (Status == VL53L1_ERROR_NONE) {
1226 PresetMode = VL53L1DevDataGet(Dev,
1227 CurrentParameters.PresetMode);
1228
1229 switch (PresetMode) {
1230 case VL53L1_PRESETMODE_LITE_RANGING:
1231 if ((Mm1Enabled == 1) || (Mm2Enabled == 1))
1232 MeasTimingBdg = RangeTimeoutUs + 5000;
1233 else
1234 MeasTimingBdg = RangeTimeoutUs + 1000;
1235
1236 break;
1237
1238 case VL53L1_PRESETMODE_AUTONOMOUS:
1239 if ((Mm1Enabled == 1) || (Mm2Enabled == 1))
1240 MeasTimingBdg = 2 * RangeTimeoutUs + 26600;
1241 else
1242 MeasTimingBdg = 2 * RangeTimeoutUs + 21600;
1243
1244 break;
1245
1246 case VL53L1_PRESETMODE_LOWPOWER_AUTONOMOUS:
1247 vhv = LOWPOWER_AUTO_VHV_LOOP_DURATION_US;
1248 VL53L1_get_tuning_parm(Dev,
1249 VL53L1_TUNINGPARM_LOWPOWERAUTO_VHV_LOOP_BOUND,
1250 &vhv_loops);
1251 if (vhv_loops > 0) {
1252 vhv += vhv_loops *
1253 LOWPOWER_AUTO_VHV_LOOP_DURATION_US;
1254 }
1255 TimingGuard = LOWPOWER_AUTO_OVERHEAD_BEFORE_A_RANGING +
1256 LOWPOWER_AUTO_OVERHEAD_BETWEEN_A_B_RANGING +
1257 vhv;
1258 MeasTimingBdg = 2 * RangeTimeoutUs + TimingGuard;
1259 break;
1260
1261 default:
1262 /* Unsupported mode */
1263 Status = VL53L1_ERROR_MODE_NOT_SUPPORTED;
1264 }
1265 }
1266 if (Status == VL53L1_ERROR_NONE)
1267 *pMeasurementTimingBudgetMicroSeconds = MeasTimingBdg;
1268
1269 LOG_FUNCTION_END(Status);
1270 return Status;
1271 }
1272
1273
1274
VL53L1_SetInterMeasurementPeriodMilliSeconds(VL53L1_DEV Dev,uint32_t InterMeasurementPeriodMilliSeconds)1275 VL53L1_Error VL53L1_SetInterMeasurementPeriodMilliSeconds(VL53L1_DEV Dev,
1276 uint32_t InterMeasurementPeriodMilliSeconds)
1277 {
1278 VL53L1_Error Status = VL53L1_ERROR_NONE;
1279 uint32_t adjustedIMP;
1280
1281 LOG_FUNCTION_START("");
1282
1283 /* Fix for Ticket 468205 actual measurement period shorter than set */
1284 adjustedIMP = InterMeasurementPeriodMilliSeconds;
1285 adjustedIMP += (adjustedIMP * 64) / 1000;
1286 /* End of fix for Ticket 468205 */
1287 Status = VL53L1_set_inter_measurement_period_ms(Dev,
1288 adjustedIMP);
1289
1290 LOG_FUNCTION_END(Status);
1291 return Status;
1292 }
1293
VL53L1_GetInterMeasurementPeriodMilliSeconds(VL53L1_DEV Dev,uint32_t * pInterMeasurementPeriodMilliSeconds)1294 VL53L1_Error VL53L1_GetInterMeasurementPeriodMilliSeconds(VL53L1_DEV Dev,
1295 uint32_t *pInterMeasurementPeriodMilliSeconds)
1296 {
1297 VL53L1_Error Status = VL53L1_ERROR_NONE;
1298 uint32_t adjustedIMP;
1299
1300 LOG_FUNCTION_START("");
1301
1302 Status = VL53L1_get_inter_measurement_period_ms(Dev, &adjustedIMP);
1303 /* Fix for Ticket 468205 actual measurement period shorter than set */
1304 adjustedIMP -= (adjustedIMP * 64) / 1000;
1305 *pInterMeasurementPeriodMilliSeconds = adjustedIMP;
1306 /* End of fix for Ticket 468205 */
1307
1308 LOG_FUNCTION_END(Status);
1309 return Status;
1310 }
1311
1312
1313 /* End Group PAL Parameters Functions */
1314
1315
1316 /* Group Limit check Functions */
1317
VL53L1_GetNumberOfLimitCheck(uint16_t * pNumberOfLimitCheck)1318 VL53L1_Error VL53L1_GetNumberOfLimitCheck(uint16_t *pNumberOfLimitCheck)
1319 {
1320 VL53L1_Error Status = VL53L1_ERROR_NONE;
1321
1322 LOG_FUNCTION_START("");
1323
1324 *pNumberOfLimitCheck = VL53L1_CHECKENABLE_NUMBER_OF_CHECKS;
1325
1326 LOG_FUNCTION_END(Status);
1327 return Status;
1328 }
1329
VL53L1_GetLimitCheckInfo(uint16_t LimitCheckId,char * pLimitCheckString)1330 VL53L1_Error VL53L1_GetLimitCheckInfo(uint16_t LimitCheckId,
1331 char *pLimitCheckString)
1332 {
1333 VL53L1_Error Status = VL53L1_ERROR_NONE;
1334
1335 LOG_FUNCTION_START("");
1336
1337 Status = VL53L1_get_limit_check_info(LimitCheckId,
1338 pLimitCheckString);
1339
1340 LOG_FUNCTION_END(Status);
1341 return Status;
1342 }
1343
VL53L1_GetLimitCheckStatus(VL53L1_DEV Dev,uint16_t LimitCheckId,uint8_t * pLimitCheckStatus)1344 VL53L1_Error VL53L1_GetLimitCheckStatus(VL53L1_DEV Dev, uint16_t LimitCheckId,
1345 uint8_t *pLimitCheckStatus)
1346 {
1347 VL53L1_Error Status = VL53L1_ERROR_NONE;
1348 uint8_t Temp8;
1349
1350 LOG_FUNCTION_START("");
1351
1352 if (LimitCheckId >= VL53L1_CHECKENABLE_NUMBER_OF_CHECKS) {
1353 Status = VL53L1_ERROR_INVALID_PARAMS;
1354 } else {
1355 VL53L1_GETARRAYPARAMETERFIELD(Dev, LimitChecksStatus,
1356 LimitCheckId, Temp8);
1357 *pLimitCheckStatus = Temp8;
1358 }
1359
1360 LOG_FUNCTION_END(Status);
1361 return Status;
1362 }
1363
SetLimitValue(VL53L1_DEV Dev,uint16_t LimitCheckId,FixPoint1616_t value)1364 static VL53L1_Error SetLimitValue(VL53L1_DEV Dev, uint16_t LimitCheckId,
1365 FixPoint1616_t value)
1366 {
1367 VL53L1_Error Status = VL53L1_ERROR_NONE;
1368 uint16_t tmpuint16; /* temporary variable */
1369
1370 LOG_FUNCTION_START("");
1371
1372 switch (LimitCheckId) {
1373 case VL53L1_CHECKENABLE_SIGMA_FINAL_RANGE:
1374 tmpuint16 = VL53L1_FIXPOINT1616TOFIXPOINT142(value);
1375 VL53L1_set_lite_sigma_threshold(Dev, tmpuint16);
1376 break;
1377 case VL53L1_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE:
1378 tmpuint16 = VL53L1_FIXPOINT1616TOFIXPOINT97(value);
1379 VL53L1_set_lite_min_count_rate(Dev, tmpuint16);
1380 break;
1381 default:
1382 Status = VL53L1_ERROR_INVALID_PARAMS;
1383 }
1384
1385 LOG_FUNCTION_END(Status);
1386 return Status;
1387 }
1388
1389
VL53L1_SetLimitCheckEnable(VL53L1_DEV Dev,uint16_t LimitCheckId,uint8_t LimitCheckEnable)1390 VL53L1_Error VL53L1_SetLimitCheckEnable(VL53L1_DEV Dev, uint16_t LimitCheckId,
1391 uint8_t LimitCheckEnable)
1392 {
1393 VL53L1_Error Status = VL53L1_ERROR_NONE;
1394 FixPoint1616_t TempFix1616 = 0;
1395
1396 LOG_FUNCTION_START("");
1397
1398
1399 if (LimitCheckId >= VL53L1_CHECKENABLE_NUMBER_OF_CHECKS) {
1400 Status = VL53L1_ERROR_INVALID_PARAMS;
1401 } else {
1402 /* TempFix1616 contains either 0 or the limit value */
1403 if (LimitCheckEnable == 0)
1404 TempFix1616 = 0;
1405 else
1406 VL53L1_GETARRAYPARAMETERFIELD(Dev, LimitChecksValue,
1407 LimitCheckId, TempFix1616);
1408
1409 Status = SetLimitValue(Dev, LimitCheckId, TempFix1616);
1410 }
1411
1412 if (Status == VL53L1_ERROR_NONE)
1413 VL53L1_SETARRAYPARAMETERFIELD(Dev,
1414 LimitChecksEnable,
1415 LimitCheckId,
1416 ((LimitCheckEnable == 0) ? 0 : 1));
1417
1418
1419
1420 LOG_FUNCTION_END(Status);
1421 return Status;
1422 }
1423
VL53L1_GetLimitCheckEnable(VL53L1_DEV Dev,uint16_t LimitCheckId,uint8_t * pLimitCheckEnable)1424 VL53L1_Error VL53L1_GetLimitCheckEnable(VL53L1_DEV Dev, uint16_t LimitCheckId,
1425 uint8_t *pLimitCheckEnable)
1426 {
1427 VL53L1_Error Status = VL53L1_ERROR_NONE;
1428 uint8_t Temp8;
1429
1430 LOG_FUNCTION_START("");
1431
1432 if (LimitCheckId >= VL53L1_CHECKENABLE_NUMBER_OF_CHECKS) {
1433 Status = VL53L1_ERROR_INVALID_PARAMS;
1434 *pLimitCheckEnable = 0;
1435 } else {
1436 VL53L1_GETARRAYPARAMETERFIELD(Dev, LimitChecksEnable,
1437 LimitCheckId, Temp8);
1438 *pLimitCheckEnable = Temp8;
1439 }
1440
1441
1442 LOG_FUNCTION_END(Status);
1443 return Status;
1444 }
1445
VL53L1_SetLimitCheckValue(VL53L1_DEV Dev,uint16_t LimitCheckId,FixPoint1616_t LimitCheckValue)1446 VL53L1_Error VL53L1_SetLimitCheckValue(VL53L1_DEV Dev, uint16_t LimitCheckId,
1447 FixPoint1616_t LimitCheckValue)
1448 {
1449 VL53L1_Error Status = VL53L1_ERROR_NONE;
1450 uint8_t LimitChecksEnable;
1451
1452 LOG_FUNCTION_START("");
1453
1454 if (LimitCheckId >= VL53L1_CHECKENABLE_NUMBER_OF_CHECKS) {
1455 Status = VL53L1_ERROR_INVALID_PARAMS;
1456 } else {
1457
1458 VL53L1_GETARRAYPARAMETERFIELD(Dev, LimitChecksEnable,
1459 LimitCheckId,
1460 LimitChecksEnable);
1461
1462 if (LimitChecksEnable == 0) {
1463 /* disabled write only internal value */
1464 VL53L1_SETARRAYPARAMETERFIELD(Dev, LimitChecksValue,
1465 LimitCheckId, LimitCheckValue);
1466 } else {
1467
1468 Status = SetLimitValue(Dev, LimitCheckId,
1469 LimitCheckValue);
1470
1471 if (Status == VL53L1_ERROR_NONE) {
1472 VL53L1_SETARRAYPARAMETERFIELD(Dev,
1473 LimitChecksValue,
1474 LimitCheckId, LimitCheckValue);
1475 }
1476 }
1477 }
1478
1479 LOG_FUNCTION_END(Status);
1480 return Status;
1481 }
1482
VL53L1_GetLimitCheckValue(VL53L1_DEV Dev,uint16_t LimitCheckId,FixPoint1616_t * pLimitCheckValue)1483 VL53L1_Error VL53L1_GetLimitCheckValue(VL53L1_DEV Dev, uint16_t LimitCheckId,
1484 FixPoint1616_t *pLimitCheckValue)
1485 {
1486 VL53L1_Error Status = VL53L1_ERROR_NONE;
1487 uint16_t MinCountRate;
1488 FixPoint1616_t TempFix1616 = 0;
1489 uint16_t SigmaThresh;
1490
1491 LOG_FUNCTION_START("");
1492
1493 switch (LimitCheckId) {
1494 case VL53L1_CHECKENABLE_SIGMA_FINAL_RANGE:
1495 Status = VL53L1_get_lite_sigma_threshold(Dev, &SigmaThresh);
1496 TempFix1616 = VL53L1_FIXPOINT142TOFIXPOINT1616(SigmaThresh);
1497 break;
1498 case VL53L1_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE:
1499 Status = VL53L1_get_lite_min_count_rate(Dev, &MinCountRate);
1500 TempFix1616 = VL53L1_FIXPOINT97TOFIXPOINT1616(MinCountRate);
1501 break;
1502 default:
1503 Status = VL53L1_ERROR_INVALID_PARAMS;
1504 }
1505
1506 if (Status == VL53L1_ERROR_NONE) {
1507
1508 if (TempFix1616 == 0) {
1509 /* disabled: return value from memory */
1510 VL53L1_GETARRAYPARAMETERFIELD(Dev,
1511 LimitChecksValue, LimitCheckId,
1512 TempFix1616);
1513 *pLimitCheckValue = TempFix1616;
1514 VL53L1_SETARRAYPARAMETERFIELD(Dev,
1515 LimitChecksEnable, LimitCheckId, 0);
1516 } else {
1517 *pLimitCheckValue = TempFix1616;
1518 VL53L1_SETARRAYPARAMETERFIELD(Dev,
1519 LimitChecksValue, LimitCheckId,
1520 TempFix1616);
1521 VL53L1_SETARRAYPARAMETERFIELD(Dev,
1522 LimitChecksEnable, LimitCheckId, 1);
1523 }
1524 }
1525 LOG_FUNCTION_END(Status);
1526 return Status;
1527
1528 }
1529
VL53L1_GetLimitCheckCurrent(VL53L1_DEV Dev,uint16_t LimitCheckId,FixPoint1616_t * pLimitCheckCurrent)1530 VL53L1_Error VL53L1_GetLimitCheckCurrent(VL53L1_DEV Dev, uint16_t LimitCheckId,
1531 FixPoint1616_t *pLimitCheckCurrent)
1532 {
1533 VL53L1_Error Status = VL53L1_ERROR_NONE;
1534 FixPoint1616_t TempFix1616 = 0;
1535
1536 LOG_FUNCTION_START("");
1537
1538 if (LimitCheckId >= VL53L1_CHECKENABLE_NUMBER_OF_CHECKS) {
1539 Status = VL53L1_ERROR_INVALID_PARAMS;
1540 } else {
1541 VL53L1_GETARRAYPARAMETERFIELD(Dev, LimitChecksCurrent,
1542 LimitCheckId, TempFix1616);
1543 *pLimitCheckCurrent = TempFix1616;
1544 }
1545
1546 LOG_FUNCTION_END(Status);
1547 return Status;
1548
1549 }
1550
1551 /* End Group Limit check Functions */
1552
1553
1554
1555 /* Group ROI Functions */
1556
VL53L1_SetUserROI(VL53L1_DEV Dev,VL53L1_UserRoi_t * pRoi)1557 VL53L1_Error VL53L1_SetUserROI(VL53L1_DEV Dev,
1558 VL53L1_UserRoi_t *pRoi)
1559 {
1560 VL53L1_Error Status = VL53L1_ERROR_NONE;
1561 VL53L1_user_zone_t user_zone;
1562
1563 Status = CheckValidRectRoi(*pRoi);
1564 if (Status != VL53L1_ERROR_NONE)
1565 return VL53L1_ERROR_INVALID_PARAMS;
1566
1567 user_zone.x_centre = (pRoi->BotRightX + pRoi->TopLeftX + 1) / 2;
1568 user_zone.y_centre = (pRoi->TopLeftY + pRoi->BotRightY + 1) / 2;
1569 user_zone.width = (pRoi->BotRightX - pRoi->TopLeftX);
1570 user_zone.height = (pRoi->TopLeftY - pRoi->BotRightY);
1571 if ((user_zone.width < 3) || (user_zone.height < 3))
1572 Status = VL53L1_ERROR_INVALID_PARAMS;
1573 else
1574 Status = VL53L1_set_user_zone(Dev, &user_zone);
1575
1576 LOG_FUNCTION_END(Status);
1577 return Status;
1578 }
1579
VL53L1_GetUserROI(VL53L1_DEV Dev,VL53L1_UserRoi_t * pRoi)1580 VL53L1_Error VL53L1_GetUserROI(VL53L1_DEV Dev,
1581 VL53L1_UserRoi_t *pRoi)
1582 {
1583 VL53L1_Error Status = VL53L1_ERROR_NONE;
1584 VL53L1_user_zone_t user_zone;
1585
1586 Status = VL53L1_get_user_zone(Dev, &user_zone);
1587
1588 pRoi->TopLeftX = (2 * user_zone.x_centre - user_zone.width) >> 1;
1589 pRoi->TopLeftY = (2 * user_zone.y_centre + user_zone.height) >> 1;
1590 pRoi->BotRightX = (2 * user_zone.x_centre + user_zone.width) >> 1;
1591 pRoi->BotRightY = (2 * user_zone.y_centre - user_zone.height) >> 1;
1592
1593 LOG_FUNCTION_END(Status);
1594 return Status;
1595 }
1596
1597
1598
1599 /* End Group ROI Functions */
1600
1601
1602 /* Group Sequence Step Functions */
1603
VL53L1_GetNumberOfSequenceSteps(VL53L1_DEV Dev,uint8_t * pNumberOfSequenceSteps)1604 VL53L1_Error VL53L1_GetNumberOfSequenceSteps(VL53L1_DEV Dev,
1605 uint8_t *pNumberOfSequenceSteps)
1606 {
1607 VL53L1_Error Status = VL53L1_ERROR_NONE;
1608
1609 SUPPRESS_UNUSED_WARNING(Dev);
1610
1611 LOG_FUNCTION_START("");
1612
1613 *pNumberOfSequenceSteps = VL53L1_SEQUENCESTEP_NUMBER_OF_ITEMS;
1614
1615 LOG_FUNCTION_END(Status);
1616 return Status;
1617 }
1618
VL53L1_GetSequenceStepsInfo(VL53L1_SequenceStepId SequenceStepId,char * pSequenceStepsString)1619 VL53L1_Error VL53L1_GetSequenceStepsInfo(VL53L1_SequenceStepId SequenceStepId,
1620 char *pSequenceStepsString)
1621 {
1622 VL53L1_Error Status = VL53L1_ERROR_NONE;
1623
1624 LOG_FUNCTION_START("");
1625
1626 Status = VL53L1_get_sequence_steps_info(
1627 SequenceStepId,
1628 pSequenceStepsString);
1629
1630 LOG_FUNCTION_END(Status);
1631
1632 return Status;
1633 }
1634
VL53L1_SetSequenceStepEnable(VL53L1_DEV Dev,VL53L1_SequenceStepId SequenceStepId,uint8_t SequenceStepEnabled)1635 VL53L1_Error VL53L1_SetSequenceStepEnable(VL53L1_DEV Dev,
1636 VL53L1_SequenceStepId SequenceStepId, uint8_t SequenceStepEnabled)
1637 {
1638 VL53L1_Error Status = VL53L1_ERROR_NONE;
1639 uint32_t MeasurementTimingBudgetMicroSeconds;
1640
1641 LOG_FUNCTION_START("");
1642
1643 /* the VL53L1_SequenceStepId correspond to the LLD
1644 * VL53L1_DeviceSequenceConfig
1645 */
1646
1647 Status = VL53L1_set_sequence_config_bit(Dev,
1648 (VL53L1_DeviceSequenceConfig)SequenceStepId,
1649 SequenceStepEnabled);
1650
1651 /* Apply New Setting */
1652 if (Status == VL53L1_ERROR_NONE) {
1653
1654 /* Recalculate timing budget */
1655 MeasurementTimingBudgetMicroSeconds = VL53L1DevDataGet(Dev,
1656 CurrentParameters.MeasurementTimingBudgetMicroSeconds);
1657
1658 VL53L1_SetMeasurementTimingBudgetMicroSeconds(Dev,
1659 MeasurementTimingBudgetMicroSeconds);
1660 }
1661
1662 LOG_FUNCTION_END(Status);
1663
1664 return Status;
1665 }
1666
1667
VL53L1_GetSequenceStepEnable(VL53L1_DEV Dev,VL53L1_SequenceStepId SequenceStepId,uint8_t * pSequenceStepEnabled)1668 VL53L1_Error VL53L1_GetSequenceStepEnable(VL53L1_DEV Dev,
1669 VL53L1_SequenceStepId SequenceStepId, uint8_t *pSequenceStepEnabled)
1670 {
1671 VL53L1_Error Status = VL53L1_ERROR_NONE;
1672
1673 LOG_FUNCTION_START("");
1674
1675 Status = VL53L1_get_sequence_config_bit(Dev,
1676 (VL53L1_DeviceSequenceConfig)SequenceStepId,
1677 pSequenceStepEnabled);
1678
1679 LOG_FUNCTION_END(Status);
1680 return Status;
1681 }
1682
1683
1684 /* End Group Sequence Step Functions Functions */
1685
1686
1687
1688 /* Group PAL Measurement Functions */
1689
1690
1691
VL53L1_StartMeasurement(VL53L1_DEV Dev)1692 VL53L1_Error VL53L1_StartMeasurement(VL53L1_DEV Dev)
1693 {
1694 #define TIMED_MODE_TIMING_GUARD_MILLISECONDS 4
1695 VL53L1_Error Status = VL53L1_ERROR_NONE;
1696 uint8_t DeviceMeasurementMode;
1697 VL53L1_State CurrPalState;
1698 VL53L1_Error lStatus;
1699 uint32_t MTBus, IMPms;
1700
1701
1702 LOG_FUNCTION_START("");
1703
1704 DeviceMeasurementMode = VL53L1DevDataGet(Dev, LLData.measurement_mode);
1705 if (DeviceMeasurementMode != VL53L1_DEVICEMEASUREMENTMODE_TIMED)
1706 VL53L1_LoadPatch(Dev);
1707 CurrPalState = VL53L1DevDataGet(Dev, PalState);
1708 switch (CurrPalState) {
1709 case VL53L1_STATE_IDLE:
1710 Status = VL53L1_ERROR_NONE;
1711 break;
1712 case VL53L1_STATE_POWERDOWN:
1713 case VL53L1_STATE_WAIT_STATICINIT:
1714 case VL53L1_STATE_STANDBY:
1715 case VL53L1_STATE_RUNNING:
1716 case VL53L1_STATE_RESET:
1717 case VL53L1_STATE_UNKNOWN:
1718 case VL53L1_STATE_ERROR:
1719 Status = VL53L1_ERROR_INVALID_COMMAND;
1720 break;
1721 default:
1722 Status = VL53L1_ERROR_UNDEFINED;
1723 }
1724
1725 /* Check timing configuration between timing budget and
1726 * inter measurement period */
1727 if ((Status == VL53L1_ERROR_NONE) &&
1728 (DeviceMeasurementMode == VL53L1_DEVICEMEASUREMENTMODE_TIMED)) {
1729 lStatus = VL53L1_GetMeasurementTimingBudgetMicroSeconds(Dev,
1730 &MTBus);
1731 /* convert timing budget in ms */
1732 MTBus /= 1000;
1733 lStatus = VL53L1_GetInterMeasurementPeriodMilliSeconds(Dev,
1734 &IMPms);
1735 /* trick to get rid of compiler "set but not used" warning */
1736 SUPPRESS_UNUSED_WARNING(lStatus);
1737 if (IMPms < MTBus + TIMED_MODE_TIMING_GUARD_MILLISECONDS)
1738 Status = VL53L1_ERROR_INVALID_PARAMS;
1739 }
1740
1741 if (Status == VL53L1_ERROR_NONE)
1742 Status = VL53L1_init_and_start_range(
1743 Dev,
1744 DeviceMeasurementMode,
1745 VL53L1_DEVICECONFIGLEVEL_FULL);
1746
1747 /* Set PAL State to Running */
1748 if (Status == VL53L1_ERROR_NONE)
1749 VL53L1DevDataSet(Dev, PalState, VL53L1_STATE_RUNNING);
1750
1751
1752 LOG_FUNCTION_END(Status);
1753 return Status;
1754 }
1755
VL53L1_StopMeasurement(VL53L1_DEV Dev)1756 VL53L1_Error VL53L1_StopMeasurement(VL53L1_DEV Dev)
1757 {
1758 VL53L1_Error Status = VL53L1_ERROR_NONE;
1759 uint8_t DeviceMeasurementMode;
1760
1761 LOG_FUNCTION_START("");
1762
1763 Status = VL53L1_stop_range(Dev);
1764 DeviceMeasurementMode = VL53L1DevDataGet(Dev, LLData.measurement_mode);
1765 if (DeviceMeasurementMode != VL53L1_DEVICEMEASUREMENTMODE_TIMED)
1766 VL53L1_UnloadPatch(Dev);
1767 /* Set PAL State to Idle */
1768 if (Status == VL53L1_ERROR_NONE)
1769 VL53L1DevDataSet(Dev, PalState, VL53L1_STATE_IDLE);
1770
1771 LOG_FUNCTION_END(Status);
1772 return Status;
1773 }
1774
1775
VL53L1_ClearInterruptAndStartMeasurement(VL53L1_DEV Dev)1776 VL53L1_Error VL53L1_ClearInterruptAndStartMeasurement(VL53L1_DEV Dev)
1777 {
1778 VL53L1_Error Status = VL53L1_ERROR_NONE;
1779 uint8_t DeviceMeasurementMode;
1780
1781 LOG_FUNCTION_START("");
1782
1783 DeviceMeasurementMode = VL53L1DevDataGet(Dev, LLData.measurement_mode);
1784
1785 Status = VL53L1_clear_interrupt_and_enable_next_range(Dev,
1786 DeviceMeasurementMode);
1787
1788 LOG_FUNCTION_END(Status);
1789 return Status;
1790 }
1791
1792
VL53L1_GetMeasurementDataReady(VL53L1_DEV Dev,uint8_t * pMeasurementDataReady)1793 VL53L1_Error VL53L1_GetMeasurementDataReady(VL53L1_DEV Dev,
1794 uint8_t *pMeasurementDataReady)
1795 {
1796 VL53L1_Error Status = VL53L1_ERROR_NONE;
1797
1798 LOG_FUNCTION_START("");
1799
1800 Status = VL53L1_is_new_data_ready(Dev, pMeasurementDataReady);
1801
1802 LOG_FUNCTION_END(Status);
1803 return Status;
1804 }
1805
VL53L1_WaitMeasurementDataReady(VL53L1_DEV Dev)1806 VL53L1_Error VL53L1_WaitMeasurementDataReady(VL53L1_DEV Dev)
1807 {
1808 VL53L1_Error Status = VL53L1_ERROR_NONE;
1809
1810 LOG_FUNCTION_START("");
1811
1812 /* Note that the timeout is given by:
1813 * VL53L1_RANGE_COMPLETION_POLLING_TIMEOUT_MS defined in def.h
1814 */
1815
1816 Status = VL53L1_poll_for_range_completion(Dev,
1817 VL53L1_RANGE_COMPLETION_POLLING_TIMEOUT_MS);
1818
1819 LOG_FUNCTION_END(Status);
1820 return Status;
1821 }
1822
1823
1824
ComputeRQL(uint8_t active_results,uint8_t FilteredRangeStatus,VL53L1_range_data_t * presults_data)1825 static uint8_t ComputeRQL(uint8_t active_results,
1826 uint8_t FilteredRangeStatus,
1827 VL53L1_range_data_t *presults_data)
1828 {
1829 int16_t SRL = 300;
1830 uint16_t SRAS = 30;
1831 FixPoint1616_t RAS;
1832 FixPoint1616_t SRQL;
1833 FixPoint1616_t GI = 7713587; /* 117.7 * 65536 */
1834 FixPoint1616_t GGm = 3198157; /* 48.8 * 65536 */
1835 FixPoint1616_t LRAP = 6554; /* 0.1 * 65536 */
1836 FixPoint1616_t partial;
1837 uint8_t finalvalue;
1838 uint8_t returnvalue;
1839
1840 if (active_results == 0)
1841 returnvalue = 0;
1842 else if (FilteredRangeStatus == VL53L1_DEVICEERROR_PHASECONSISTENCY)
1843 returnvalue = 50;
1844 else {
1845 if (presults_data->median_range_mm < SRL)
1846 RAS = SRAS * 65536;
1847 else
1848 RAS = LRAP * presults_data->median_range_mm;
1849
1850 /* Fix1616 + (fix1616 * uint16_t / fix1616) * 65536 = fix1616 */
1851 if (RAS != 0) {
1852 partial = (GGm * presults_data->sigma_mm);
1853 partial = partial + (RAS >> 1);
1854 partial = partial / RAS;
1855 partial = partial * 65536;
1856 if (partial <= GI)
1857 SRQL = GI - partial;
1858 else
1859 SRQL = 50 * 65536;
1860 } else
1861 SRQL = 100 * 65536;
1862
1863 finalvalue = (uint8_t)(SRQL >> 16);
1864 returnvalue = MAX(50, MIN(100, finalvalue));
1865 }
1866
1867 return returnvalue;
1868 }
1869
1870
ConvertStatusLite(uint8_t FilteredRangeStatus)1871 static uint8_t ConvertStatusLite(uint8_t FilteredRangeStatus)
1872 {
1873 uint8_t RangeStatus;
1874
1875 switch (FilteredRangeStatus) {
1876 case VL53L1_DEVICEERROR_GPHSTREAMCOUNT0READY:
1877 RangeStatus = VL53L1_RANGESTATUS_SYNCRONISATION_INT;
1878 break;
1879 case VL53L1_DEVICEERROR_RANGECOMPLETE_NO_WRAP_CHECK:
1880 RangeStatus = VL53L1_RANGESTATUS_RANGE_VALID_NO_WRAP_CHECK_FAIL;
1881 break;
1882 case VL53L1_DEVICEERROR_RANGEPHASECHECK:
1883 RangeStatus = VL53L1_RANGESTATUS_OUTOFBOUNDS_FAIL;
1884 break;
1885 case VL53L1_DEVICEERROR_MSRCNOTARGET:
1886 RangeStatus = VL53L1_RANGESTATUS_SIGNAL_FAIL;
1887 break;
1888 case VL53L1_DEVICEERROR_SIGMATHRESHOLDCHECK:
1889 RangeStatus = VL53L1_RANGESTATUS_SIGMA_FAIL;
1890 break;
1891 case VL53L1_DEVICEERROR_PHASECONSISTENCY:
1892 RangeStatus = VL53L1_RANGESTATUS_WRAP_TARGET_FAIL;
1893 break;
1894 case VL53L1_DEVICEERROR_RANGEIGNORETHRESHOLD:
1895 RangeStatus = VL53L1_RANGESTATUS_XTALK_SIGNAL_FAIL;
1896 break;
1897 case VL53L1_DEVICEERROR_MINCLIP:
1898 RangeStatus = VL53L1_RANGESTATUS_RANGE_VALID_MIN_RANGE_CLIPPED;
1899 break;
1900 case VL53L1_DEVICEERROR_RANGECOMPLETE:
1901 RangeStatus = VL53L1_RANGESTATUS_RANGE_VALID;
1902 break;
1903 default:
1904 RangeStatus = VL53L1_RANGESTATUS_NONE;
1905 }
1906
1907 return RangeStatus;
1908 }
1909
1910
1911
SetSimpleData(VL53L1_DEV Dev,uint8_t active_results,uint8_t device_status,VL53L1_range_data_t * presults_data,VL53L1_RangingMeasurementData_t * pRangeData)1912 static VL53L1_Error SetSimpleData(VL53L1_DEV Dev,
1913 uint8_t active_results, uint8_t device_status,
1914 VL53L1_range_data_t *presults_data,
1915 VL53L1_RangingMeasurementData_t *pRangeData)
1916 {
1917 VL53L1_Error Status = VL53L1_ERROR_NONE;
1918 uint8_t FilteredRangeStatus;
1919 uint8_t SigmaLimitflag;
1920 uint8_t SignalLimitflag;
1921 uint8_t Temp8Enable;
1922 uint8_t Temp8;
1923 FixPoint1616_t AmbientRate;
1924 FixPoint1616_t SignalRate;
1925 FixPoint1616_t TempFix1616;
1926 FixPoint1616_t LimitCheckValue;
1927 int16_t Range;
1928
1929 pRangeData->TimeStamp = presults_data->time_stamp;
1930
1931 FilteredRangeStatus = presults_data->range_status & 0x1F;
1932
1933 pRangeData->RangeQualityLevel = ComputeRQL(active_results,
1934 FilteredRangeStatus,
1935 presults_data);
1936
1937 SignalRate = VL53L1_FIXPOINT97TOFIXPOINT1616(
1938 presults_data->peak_signal_count_rate_mcps);
1939 pRangeData->SignalRateRtnMegaCps
1940 = SignalRate;
1941
1942 AmbientRate = VL53L1_FIXPOINT97TOFIXPOINT1616(
1943 presults_data->ambient_count_rate_mcps);
1944 pRangeData->AmbientRateRtnMegaCps = AmbientRate;
1945
1946 pRangeData->EffectiveSpadRtnCount =
1947 presults_data->actual_effective_spads;
1948
1949 TempFix1616 = VL53L1_FIXPOINT97TOFIXPOINT1616(
1950 presults_data->sigma_mm);
1951
1952 pRangeData->SigmaMilliMeter = TempFix1616;
1953
1954 pRangeData->RangeMilliMeter = presults_data->median_range_mm;
1955
1956 pRangeData->RangeFractionalPart = 0;
1957
1958 /* Treat device error status first */
1959 switch (device_status) {
1960 case VL53L1_DEVICEERROR_MULTCLIPFAIL:
1961 case VL53L1_DEVICEERROR_VCSELWATCHDOGTESTFAILURE:
1962 case VL53L1_DEVICEERROR_VCSELCONTINUITYTESTFAILURE:
1963 case VL53L1_DEVICEERROR_NOVHVVALUEFOUND:
1964 pRangeData->RangeStatus = VL53L1_RANGESTATUS_HARDWARE_FAIL;
1965 break;
1966 case VL53L1_DEVICEERROR_USERROICLIP:
1967 pRangeData->RangeStatus = VL53L1_RANGESTATUS_MIN_RANGE_FAIL;
1968 break;
1969 default:
1970 pRangeData->RangeStatus = VL53L1_RANGESTATUS_RANGE_VALID;
1971 }
1972
1973 /* Now deal with range status according to the ranging preset */
1974 if (pRangeData->RangeStatus == VL53L1_RANGESTATUS_RANGE_VALID) {
1975 pRangeData->RangeStatus =
1976 ConvertStatusLite(FilteredRangeStatus);
1977 }
1978
1979 /* Update current Limit Check */
1980 TempFix1616 = VL53L1_FIXPOINT97TOFIXPOINT1616(
1981 presults_data->sigma_mm);
1982 VL53L1_SETARRAYPARAMETERFIELD(Dev,
1983 LimitChecksCurrent, VL53L1_CHECKENABLE_SIGMA_FINAL_RANGE,
1984 TempFix1616);
1985
1986 TempFix1616 = VL53L1_FIXPOINT97TOFIXPOINT1616(
1987 presults_data->peak_signal_count_rate_mcps);
1988 VL53L1_SETARRAYPARAMETERFIELD(Dev,
1989 LimitChecksCurrent, VL53L1_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE,
1990 TempFix1616);
1991
1992 /* Update Limit Check Status */
1993 /* Sigma */
1994 VL53L1_GetLimitCheckValue(Dev,
1995 VL53L1_CHECKENABLE_SIGMA_FINAL_RANGE,
1996 &LimitCheckValue);
1997
1998 SigmaLimitflag = (FilteredRangeStatus ==
1999 VL53L1_DEVICEERROR_SIGMATHRESHOLDCHECK)
2000 ? 1 : 0;
2001
2002 VL53L1_GetLimitCheckEnable(Dev,
2003 VL53L1_CHECKENABLE_SIGMA_FINAL_RANGE,
2004 &Temp8Enable);
2005
2006 Temp8 = ((Temp8Enable == 1) && (SigmaLimitflag == 1)) ? 1 : 0;
2007 VL53L1_SETARRAYPARAMETERFIELD(Dev, LimitChecksStatus,
2008 VL53L1_CHECKENABLE_SIGMA_FINAL_RANGE, Temp8);
2009
2010 /* Signal Rate */
2011 VL53L1_GetLimitCheckValue(Dev,
2012 VL53L1_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE,
2013 &LimitCheckValue);
2014
2015 SignalLimitflag = (FilteredRangeStatus ==
2016 VL53L1_DEVICEERROR_MSRCNOTARGET)
2017 ? 1 : 0;
2018
2019 VL53L1_GetLimitCheckEnable(Dev,
2020 VL53L1_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE,
2021 &Temp8Enable);
2022
2023 Temp8 = ((Temp8Enable == 1) && (SignalLimitflag == 1)) ? 1 : 0;
2024 VL53L1_SETARRAYPARAMETERFIELD(Dev, LimitChecksStatus,
2025 VL53L1_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE, Temp8);
2026
2027 Range = pRangeData->RangeMilliMeter;
2028 if ((pRangeData->RangeStatus == VL53L1_RANGESTATUS_RANGE_VALID) &&
2029 (Range < 0)) {
2030 if (Range < BDTable[VL53L1_TUNING_PROXY_MIN])
2031 pRangeData->RangeStatus =
2032 VL53L1_RANGESTATUS_RANGE_INVALID;
2033 else
2034 pRangeData->RangeMilliMeter = 0;
2035 }
2036
2037 return Status;
2038 }
2039
2040
2041
VL53L1_GetRangingMeasurementData(VL53L1_DEV Dev,VL53L1_RangingMeasurementData_t * pRangingMeasurementData)2042 VL53L1_Error VL53L1_GetRangingMeasurementData(VL53L1_DEV Dev,
2043 VL53L1_RangingMeasurementData_t *pRangingMeasurementData)
2044 {
2045 VL53L1_Error Status = VL53L1_ERROR_NONE;
2046 VL53L1_range_results_t results;
2047 VL53L1_range_results_t *presults = &results;
2048 VL53L1_range_data_t *presults_data;
2049
2050 LOG_FUNCTION_START("");
2051
2052
2053 /* Clear Ranging Data */
2054 memset(pRangingMeasurementData, 0xFF,
2055 sizeof(VL53L1_RangingMeasurementData_t));
2056
2057 /* Get Ranging Data */
2058 Status = VL53L1_get_device_results(
2059 Dev,
2060 VL53L1_DEVICERESULTSLEVEL_FULL,
2061 presults);
2062
2063 if (Status == VL53L1_ERROR_NONE) {
2064 pRangingMeasurementData->StreamCount = presults->stream_count;
2065
2066 /* in case of lite ranging or autonomous the following function
2067 * returns index = 0
2068 */
2069 presults_data = &(presults->data[0]);
2070 Status = SetSimpleData(Dev, 1,
2071 presults->device_status,
2072 presults_data,
2073 pRangingMeasurementData);
2074 }
2075
2076 LOG_FUNCTION_END(Status);
2077 return Status;
2078 }
2079
2080
2081
2082
2083
2084 /* End Group PAL Measurement Functions */
2085
2086
2087 /* Group Calibration functions */
VL53L1_SetTuningParameter(VL53L1_DEV Dev,uint16_t TuningParameterId,int32_t TuningParameterValue)2088 VL53L1_Error VL53L1_SetTuningParameter(VL53L1_DEV Dev,
2089 uint16_t TuningParameterId, int32_t TuningParameterValue)
2090 {
2091 VL53L1_Error Status = VL53L1_ERROR_NONE;
2092
2093 LOG_FUNCTION_START("");
2094 if (TuningParameterId >= 32768)
2095 Status = VL53L1_set_tuning_parm(Dev,
2096 TuningParameterId,
2097 TuningParameterValue);
2098 else {
2099 if (TuningParameterId < VL53L1_TUNING_MAX_TUNABLE_KEY)
2100 BDTable[TuningParameterId] = TuningParameterValue;
2101 else
2102 Status = VL53L1_ERROR_INVALID_PARAMS;
2103 }
2104
2105 LOG_FUNCTION_END(Status);
2106 return Status;
2107 }
2108
VL53L1_GetTuningParameter(VL53L1_DEV Dev,uint16_t TuningParameterId,int32_t * pTuningParameterValue)2109 VL53L1_Error VL53L1_GetTuningParameter(VL53L1_DEV Dev,
2110 uint16_t TuningParameterId, int32_t *pTuningParameterValue)
2111 {
2112 VL53L1_Error Status = VL53L1_ERROR_NONE;
2113
2114 LOG_FUNCTION_START("");
2115
2116 if (TuningParameterId >= 32768)
2117 Status = VL53L1_get_tuning_parm(Dev,
2118 TuningParameterId,
2119 pTuningParameterValue);
2120 else {
2121 if (TuningParameterId < VL53L1_TUNING_MAX_TUNABLE_KEY)
2122 *pTuningParameterValue = BDTable[TuningParameterId];
2123 else
2124 Status = VL53L1_ERROR_INVALID_PARAMS;
2125 }
2126
2127 LOG_FUNCTION_END(Status);
2128 return Status;
2129 }
2130
2131
VL53L1_PerformRefSpadManagement(VL53L1_DEV Dev)2132 VL53L1_Error VL53L1_PerformRefSpadManagement(VL53L1_DEV Dev)
2133 {
2134 #ifdef VL53L1_NOCALIB
2135 VL53L1_Error Status = VL53L1_ERROR_NOT_SUPPORTED;
2136
2137 SUPPRESS_UNUSED_WARNING(Dev);
2138
2139 LOG_FUNCTION_START("");
2140 #else
2141 VL53L1_Error Status = VL53L1_ERROR_NONE;
2142 VL53L1_Error RawStatus;
2143 uint8_t dcrbuffer[24];
2144 uint8_t *commbuf;
2145 uint8_t numloc[2] = {5, 3};
2146 VL53L1_LLDriverData_t *pdev;
2147 VL53L1_customer_nvm_managed_t *pc;
2148 VL53L1_PresetModes PresetMode;
2149
2150 LOG_FUNCTION_START("");
2151
2152 pdev = VL53L1DevStructGetLLDriverHandle(Dev);
2153 pc = &pdev->customer;
2154
2155 if (Status == VL53L1_ERROR_NONE) {
2156 PresetMode = VL53L1DevDataGet(Dev,
2157 CurrentParameters.PresetMode);
2158 Status = VL53L1_run_ref_spad_char(Dev, &RawStatus);
2159 /* We discovered RefSpad mngt badly breaks some preset mode
2160 * The WA is to apply again the current one
2161 */
2162 if (Status == VL53L1_ERROR_NONE)
2163 Status = VL53L1_SetPresetMode(Dev, PresetMode);
2164 }
2165
2166 if (Status == VL53L1_WARNING_REF_SPAD_CHAR_RATE_TOO_HIGH) {
2167 /* Fix ticket #466282 RefSpad management error/warning -29
2168 * force usage of location 3 and 5 refspads in registers
2169 */
2170 Status = VL53L1_read_nvm_raw_data(Dev,
2171 (uint8_t)(0xA0 >> 2),
2172 (uint8_t)(24 >> 2),
2173 dcrbuffer);
2174
2175 if (Status == VL53L1_ERROR_NONE)
2176 Status = VL53L1_WriteMulti(Dev,
2177 VL53L1_REF_SPAD_MAN__NUM_REQUESTED_REF_SPADS,
2178 numloc, 2);
2179
2180 if (Status == VL53L1_ERROR_NONE) {
2181 pc->ref_spad_man__num_requested_ref_spads = numloc[0];
2182 pc->ref_spad_man__ref_location = numloc[1];
2183 }
2184
2185 commbuf = &dcrbuffer[16];
2186 /*
2187 * update & copy reference SPAD enables to customer nvm managed
2188 */
2189 if (Status == VL53L1_ERROR_NONE)
2190 Status = VL53L1_WriteMulti(Dev,
2191 VL53L1_GLOBAL_CONFIG__SPAD_ENABLES_REF_0,
2192 commbuf, 6);
2193
2194 if (Status == VL53L1_ERROR_NONE) {
2195 pc->global_config__spad_enables_ref_0 = commbuf[0];
2196 pc->global_config__spad_enables_ref_1 = commbuf[1];
2197 pc->global_config__spad_enables_ref_2 = commbuf[2];
2198 pc->global_config__spad_enables_ref_3 = commbuf[3];
2199 pc->global_config__spad_enables_ref_4 = commbuf[4];
2200 pc->global_config__spad_enables_ref_5 = commbuf[5];
2201 }
2202 /* End of fix ticket #466282 */
2203 }
2204
2205 #endif
2206
2207 LOG_FUNCTION_END(Status);
2208 return Status;
2209 }
2210
2211
VL53L1_SetXTalkCompensationEnable(VL53L1_DEV Dev,uint8_t XTalkCompensationEnable)2212 VL53L1_Error VL53L1_SetXTalkCompensationEnable(VL53L1_DEV Dev,
2213 uint8_t XTalkCompensationEnable)
2214 {
2215 VL53L1_Error Status = VL53L1_ERROR_NONE;
2216
2217 LOG_FUNCTION_START("");
2218
2219 if (XTalkCompensationEnable == 0)
2220 Status = VL53L1_disable_xtalk_compensation(Dev);
2221 else
2222 Status = VL53L1_enable_xtalk_compensation(Dev);
2223
2224 LOG_FUNCTION_END(Status);
2225 return Status;
2226 }
2227
2228
VL53L1_GetXTalkCompensationEnable(VL53L1_DEV Dev,uint8_t * pXTalkCompensationEnable)2229 VL53L1_Error VL53L1_GetXTalkCompensationEnable(VL53L1_DEV Dev,
2230 uint8_t *pXTalkCompensationEnable)
2231 {
2232 VL53L1_Error Status = VL53L1_ERROR_NONE;
2233
2234 LOG_FUNCTION_START("");
2235
2236 VL53L1_get_xtalk_compensation_enable(
2237 Dev,
2238 pXTalkCompensationEnable);
2239
2240 LOG_FUNCTION_END(Status);
2241 return Status;
2242 }
2243
VL53L1_PerformSingleTargetXTalkCalibration(VL53L1_DEV Dev,int32_t CalDistanceMilliMeter)2244 VL53L1_Error VL53L1_PerformSingleTargetXTalkCalibration(VL53L1_DEV Dev,
2245 int32_t CalDistanceMilliMeter)
2246 {
2247 VL53L1_Error Status = VL53L1_ERROR_NONE;
2248
2249 LOG_FUNCTION_START("");
2250
2251 if (CalDistanceMilliMeter > 0) {
2252 BDTable[VL53L1_TUNING_SINGLE_TARGET_XTALK_TARGET_DISTANCE_MM] =
2253 CalDistanceMilliMeter;
2254 Status = SingleTargetXTalkCalibration(Dev);
2255 } else
2256 Status = VL53L1_ERROR_INVALID_PARAMS;
2257
2258 LOG_FUNCTION_END(Status);
2259 return Status;
2260 }
2261
2262
2263
2264
2265
VL53L1_PerformOffsetSimpleCalibration(VL53L1_DEV Dev,int32_t CalDistanceMilliMeter)2266 VL53L1_Error VL53L1_PerformOffsetSimpleCalibration(VL53L1_DEV Dev,
2267 int32_t CalDistanceMilliMeter)
2268 {
2269 VL53L1_Error Status = VL53L1_ERROR_NONE;
2270 int32_t sum_ranging;
2271 uint8_t offset_meas;
2272 int16_t Max, UnderMax, OverMax, Repeat;
2273 int32_t total_count, inloopcount;
2274 int32_t IncRounding;
2275 int16_t meanDistance_mm;
2276 int16_t offset;
2277 VL53L1_RangingMeasurementData_t RangingMeasurementData;
2278 VL53L1_LLDriverData_t *pdev;
2279 uint8_t goodmeas;
2280
2281 LOG_FUNCTION_START("");
2282
2283 pdev = VL53L1DevStructGetLLDriverHandle(Dev);
2284 /* Disable any offsets */
2285 pdev->customer.algo__part_to_part_range_offset_mm = 0;
2286 pdev->customer.mm_config__inner_offset_mm = 0;
2287 pdev->customer.mm_config__outer_offset_mm = 0;
2288 Repeat = BDTable[VL53L1_TUNING_SIMPLE_OFFSET_CALIBRATION_REPEAT];
2289 Max = BDTable[
2290 VL53L1_TUNING_MAX_SIMPLE_OFFSET_CALIBRATION_SAMPLE_NUMBER];
2291 UnderMax = 1 + (Max / 2);
2292 OverMax = Max + (Max / 2);
2293 sum_ranging = 0;
2294 total_count = 0;
2295
2296 while ((Repeat > 0) && (Status == VL53L1_ERROR_NONE)) {
2297 Status = VL53L1_StartMeasurement(Dev);
2298 /* Very first ranging completion interrupt must be ignored */
2299 if (Status == VL53L1_ERROR_NONE) {
2300 VL53L1_WaitMeasurementDataReady(Dev);
2301 VL53L1_GetRangingMeasurementData(Dev,
2302 &RangingMeasurementData);
2303 VL53L1_ClearInterruptAndStartMeasurement(Dev);
2304 }
2305 /* offset calibration main loop */
2306 inloopcount = 0;
2307 offset_meas = 0;
2308 while ((Status == VL53L1_ERROR_NONE) && (inloopcount < Max) &&
2309 (offset_meas < OverMax)) {
2310 Status = VL53L1_WaitMeasurementDataReady(Dev);
2311 if (Status == VL53L1_ERROR_NONE)
2312 Status = VL53L1_GetRangingMeasurementData(Dev,
2313 &RangingMeasurementData);
2314 goodmeas = (RangingMeasurementData.RangeStatus ==
2315 VL53L1_RANGESTATUS_RANGE_VALID);
2316 if ((Status == VL53L1_ERROR_NONE) && goodmeas) {
2317 sum_ranging = sum_ranging +
2318 RangingMeasurementData.RangeMilliMeter;
2319 inloopcount++;
2320 }
2321 Status = VL53L1_ClearInterruptAndStartMeasurement(Dev);
2322 offset_meas++;
2323 }
2324 total_count += inloopcount;
2325
2326 /* no enough valid values found */
2327 if (inloopcount < UnderMax)
2328 Status = VL53L1_ERROR_OFFSET_CAL_NO_SAMPLE_FAIL;
2329
2330 VL53L1_StopMeasurement(Dev);
2331
2332 Repeat--;
2333
2334 }
2335 /* check overflow (unlikely if target is near to the device) */
2336 if ((sum_ranging < 0) ||
2337 (sum_ranging > ((int32_t) total_count * 0xffff)))
2338 Status = VL53L1_WARNING_OFFSET_CAL_SIGMA_TOO_HIGH;
2339
2340 if ((Status == VL53L1_ERROR_NONE) && (total_count > 0)) {
2341 IncRounding = total_count / 2;
2342 meanDistance_mm = (int16_t)((sum_ranging + IncRounding)
2343 / total_count);
2344 offset = (int16_t)CalDistanceMilliMeter - meanDistance_mm;
2345 pdev->customer.algo__part_to_part_range_offset_mm = 0;
2346 pdev->customer.mm_config__inner_offset_mm = offset;
2347 pdev->customer.mm_config__outer_offset_mm = offset;
2348
2349 Status = VL53L1_set_customer_nvm_managed(Dev,
2350 &(pdev->customer));
2351 }
2352
2353 LOG_FUNCTION_END(Status);
2354 return Status;
2355 }
2356
VL53L1_PerformOffsetZeroDistanceCalibration(VL53L1_DEV Dev)2357 VL53L1_Error VL53L1_PerformOffsetZeroDistanceCalibration(VL53L1_DEV Dev)
2358 {
2359 #define START_OFFSET 50
2360 VL53L1_Error Status = VL53L1_ERROR_NONE;
2361 int32_t sum_ranging;
2362 uint8_t offset_meas;
2363 int16_t Max, UnderMax, OverMax, Repeat;
2364 int32_t total_count, inloopcount;
2365 int32_t IncRounding;
2366 int16_t meanDistance_mm;
2367 int16_t offset, ZeroDistanceOffset;
2368 VL53L1_RangingMeasurementData_t RangingMeasurementData;
2369 VL53L1_LLDriverData_t *pdev;
2370 uint8_t goodmeas;
2371
2372 LOG_FUNCTION_START("");
2373
2374 pdev = VL53L1DevStructGetLLDriverHandle(Dev);
2375 pdev->customer.algo__part_to_part_range_offset_mm = 0;
2376 pdev->customer.mm_config__inner_offset_mm = START_OFFSET;
2377 pdev->customer.mm_config__outer_offset_mm = START_OFFSET;
2378 ZeroDistanceOffset = BDTable[
2379 VL53L1_TUNING_ZERO_DISTANCE_OFFSET_NON_LINEAR_FACTOR];
2380 Repeat = BDTable[VL53L1_TUNING_SIMPLE_OFFSET_CALIBRATION_REPEAT];
2381 Max = BDTable[
2382 VL53L1_TUNING_MAX_SIMPLE_OFFSET_CALIBRATION_SAMPLE_NUMBER];
2383 UnderMax = 1 + (Max / 2);
2384 OverMax = Max + (Max / 2);
2385 sum_ranging = 0;
2386 total_count = 0;
2387
2388 while ((Repeat > 0) && (Status == VL53L1_ERROR_NONE)) {
2389 Status = VL53L1_StartMeasurement(Dev);
2390 if (Status == VL53L1_ERROR_NONE) {
2391 VL53L1_WaitMeasurementDataReady(Dev);
2392 VL53L1_GetRangingMeasurementData(Dev,
2393 &RangingMeasurementData);
2394 VL53L1_ClearInterruptAndStartMeasurement(Dev);
2395 }
2396 inloopcount = 0;
2397 offset_meas = 0;
2398 while ((Status == VL53L1_ERROR_NONE) && (inloopcount < Max) &&
2399 (offset_meas < OverMax)) {
2400 Status = VL53L1_WaitMeasurementDataReady(Dev);
2401 if (Status == VL53L1_ERROR_NONE)
2402 Status = VL53L1_GetRangingMeasurementData(Dev,
2403 &RangingMeasurementData);
2404 goodmeas = (RangingMeasurementData.RangeStatus ==
2405 VL53L1_RANGESTATUS_RANGE_VALID);
2406 if ((Status == VL53L1_ERROR_NONE) && goodmeas) {
2407 sum_ranging = sum_ranging +
2408 RangingMeasurementData.RangeMilliMeter;
2409 inloopcount++;
2410 }
2411 Status = VL53L1_ClearInterruptAndStartMeasurement(Dev);
2412 offset_meas++;
2413 }
2414 total_count += inloopcount;
2415 if (inloopcount < UnderMax)
2416 Status = VL53L1_ERROR_OFFSET_CAL_NO_SAMPLE_FAIL;
2417 VL53L1_StopMeasurement(Dev);
2418 Repeat--;
2419 }
2420 if ((sum_ranging < 0) ||
2421 (sum_ranging > ((int32_t) total_count * 0xffff)))
2422 Status = VL53L1_WARNING_OFFSET_CAL_SIGMA_TOO_HIGH;
2423
2424 if ((Status == VL53L1_ERROR_NONE) && (total_count > 0)) {
2425 IncRounding = total_count / 2;
2426 meanDistance_mm = (int16_t)
2427 ((sum_ranging + IncRounding) / total_count);
2428 offset = START_OFFSET - meanDistance_mm + ZeroDistanceOffset;
2429 pdev->customer.algo__part_to_part_range_offset_mm = 0;
2430 pdev->customer.mm_config__inner_offset_mm = offset;
2431 pdev->customer.mm_config__outer_offset_mm = offset;
2432 Status = VL53L1_set_customer_nvm_managed(Dev,
2433 &(pdev->customer));
2434 }
2435
2436 LOG_FUNCTION_END(Status);
2437 return Status;
2438 }
2439
VL53L1_SetCalibrationData(VL53L1_DEV Dev,VL53L1_CalibrationData_t * pCalibrationData)2440 VL53L1_Error VL53L1_SetCalibrationData(VL53L1_DEV Dev,
2441 VL53L1_CalibrationData_t *pCalibrationData)
2442 {
2443 VL53L1_Error Status = VL53L1_ERROR_NONE;
2444 VL53L1_CustomerNvmManaged_t *pC;
2445 VL53L1_calibration_data_t cal_data;
2446 uint32_t x, IncomeVersion, CurrentVersion;
2447
2448 LOG_FUNCTION_START("");
2449
2450 cal_data.struct_version = pCalibrationData->struct_version -
2451 VL53L1_ADDITIONAL_CALIBRATION_DATA_STRUCT_VERSION;
2452 /* adjust version for old calibration data */
2453 IncomeVersion = pCalibrationData->struct_version;
2454 CurrentVersion = VL53L1_LL_CALIBRATION_DATA_STRUCT_VERSION +
2455 VL53L1_ADDITIONAL_CALIBRATION_DATA_STRUCT_VERSION;
2456
2457 if ((IncomeVersion < CurrentVersion) &&
2458 ((IncomeVersion & 0xFFFFFF0F) ==
2459 (CurrentVersion & 0xFFFFFF0F))) {
2460 cal_data.struct_version =
2461 VL53L1_LL_CALIBRATION_DATA_STRUCT_VERSION;
2462 }
2463
2464
2465 /* memcpy(DEST, SRC, N) */
2466 memcpy(
2467 &(cal_data.add_off_cal_data),
2468 &(pCalibrationData->add_off_cal_data),
2469 sizeof(VL53L1_additional_offset_cal_data_t));
2470
2471 /* memcpy (DEST, SRC, N) */
2472 memcpy(
2473 &(cal_data.optical_centre),
2474 &(pCalibrationData->optical_centre),
2475 sizeof(VL53L1_optical_centre_t));
2476
2477 /* memcpy (DEST, SRC, N) */
2478 memcpy(
2479 &(cal_data.gain_cal),
2480 &(pCalibrationData->gain_cal),
2481 sizeof(VL53L1_gain_calibration_data_t));
2482
2483 /* memcpy (DEST, SRC, N) */
2484 memcpy(
2485 &(cal_data.cal_peak_rate_map),
2486 &(pCalibrationData->cal_peak_rate_map),
2487 sizeof(VL53L1_cal_peak_rate_map_t));
2488
2489
2490 pC = &pCalibrationData->customer;
2491 x = pC->algo__crosstalk_compensation_plane_offset_kcps;
2492 cal_data.customer.algo__crosstalk_compensation_plane_offset_kcps =
2493 (uint16_t)(x&0x0000FFFF);
2494
2495 cal_data.customer.global_config__spad_enables_ref_0 =
2496 pC->global_config__spad_enables_ref_0;
2497 cal_data.customer.global_config__spad_enables_ref_1 =
2498 pC->global_config__spad_enables_ref_1;
2499 cal_data.customer.global_config__spad_enables_ref_2 =
2500 pC->global_config__spad_enables_ref_2;
2501 cal_data.customer.global_config__spad_enables_ref_3 =
2502 pC->global_config__spad_enables_ref_3;
2503 cal_data.customer.global_config__spad_enables_ref_4 =
2504 pC->global_config__spad_enables_ref_4;
2505 cal_data.customer.global_config__spad_enables_ref_5 =
2506 pC->global_config__spad_enables_ref_5;
2507 cal_data.customer.global_config__ref_en_start_select =
2508 pC->global_config__ref_en_start_select;
2509 cal_data.customer.ref_spad_man__num_requested_ref_spads =
2510 pC->ref_spad_man__num_requested_ref_spads;
2511 cal_data.customer.ref_spad_man__ref_location =
2512 pC->ref_spad_man__ref_location;
2513 cal_data.customer.algo__crosstalk_compensation_x_plane_gradient_kcps =
2514 pC->algo__crosstalk_compensation_x_plane_gradient_kcps;
2515 cal_data.customer.algo__crosstalk_compensation_y_plane_gradient_kcps =
2516 pC->algo__crosstalk_compensation_y_plane_gradient_kcps;
2517 cal_data.customer.ref_spad_char__total_rate_target_mcps =
2518 pC->ref_spad_char__total_rate_target_mcps;
2519 cal_data.customer.algo__part_to_part_range_offset_mm =
2520 pC->algo__part_to_part_range_offset_mm;
2521 cal_data.customer.mm_config__inner_offset_mm =
2522 pC->mm_config__inner_offset_mm;
2523 cal_data.customer.mm_config__outer_offset_mm =
2524 pC->mm_config__outer_offset_mm;
2525
2526 Status = VL53L1_set_part_to_part_data(Dev, &cal_data);
2527 LOG_FUNCTION_END(Status);
2528 return Status;
2529
2530 }
2531
VL53L1_GetCalibrationData(VL53L1_DEV Dev,VL53L1_CalibrationData_t * pCalibrationData)2532 VL53L1_Error VL53L1_GetCalibrationData(VL53L1_DEV Dev,
2533 VL53L1_CalibrationData_t *pCalibrationData)
2534 {
2535 VL53L1_Error Status = VL53L1_ERROR_NONE;
2536 VL53L1_calibration_data_t cal_data;
2537 VL53L1_CustomerNvmManaged_t *pC;
2538 VL53L1_customer_nvm_managed_t *pC2;
2539
2540 LOG_FUNCTION_START("");
2541
2542 /* struct_version is filled inside get part to part function */
2543 Status = VL53L1_get_part_to_part_data(Dev, &cal_data);
2544
2545 pCalibrationData->struct_version = cal_data.struct_version +
2546 VL53L1_ADDITIONAL_CALIBRATION_DATA_STRUCT_VERSION;
2547
2548
2549 /* memcpy(DEST, SRC, N) */
2550 memcpy(
2551 &(pCalibrationData->add_off_cal_data),
2552 &(cal_data.add_off_cal_data),
2553 sizeof(VL53L1_additional_offset_cal_data_t));
2554
2555 /* memcpy (DEST, SRC, N) */
2556 memcpy(
2557 &(pCalibrationData->optical_centre),
2558 &(cal_data.optical_centre),
2559 sizeof(VL53L1_optical_centre_t));
2560
2561 /* memcpy (DEST, SRC, N) */
2562 memcpy(
2563 &(pCalibrationData->gain_cal),
2564 &(cal_data.gain_cal),
2565 sizeof(VL53L1_gain_calibration_data_t));
2566
2567 /* memcpy (DEST, SRC, N) */
2568 memcpy(
2569 &(pCalibrationData->cal_peak_rate_map),
2570 &(cal_data.cal_peak_rate_map),
2571 sizeof(VL53L1_cal_peak_rate_map_t));
2572
2573
2574 pC = &pCalibrationData->customer;
2575 pC2 = &cal_data.customer;
2576 pC->global_config__spad_enables_ref_0 =
2577 pC2->global_config__spad_enables_ref_0;
2578 pC->global_config__spad_enables_ref_1 =
2579 pC2->global_config__spad_enables_ref_1;
2580 pC->global_config__spad_enables_ref_2 =
2581 pC2->global_config__spad_enables_ref_2;
2582 pC->global_config__spad_enables_ref_3 =
2583 pC2->global_config__spad_enables_ref_3;
2584 pC->global_config__spad_enables_ref_4 =
2585 pC2->global_config__spad_enables_ref_4;
2586 pC->global_config__spad_enables_ref_5 =
2587 pC2->global_config__spad_enables_ref_5;
2588 pC->global_config__ref_en_start_select =
2589 pC2->global_config__ref_en_start_select;
2590 pC->ref_spad_man__num_requested_ref_spads =
2591 pC2->ref_spad_man__num_requested_ref_spads;
2592 pC->ref_spad_man__ref_location =
2593 pC2->ref_spad_man__ref_location;
2594 pC->algo__crosstalk_compensation_x_plane_gradient_kcps =
2595 pC2->algo__crosstalk_compensation_x_plane_gradient_kcps;
2596 pC->algo__crosstalk_compensation_y_plane_gradient_kcps =
2597 pC2->algo__crosstalk_compensation_y_plane_gradient_kcps;
2598 pC->ref_spad_char__total_rate_target_mcps =
2599 pC2->ref_spad_char__total_rate_target_mcps;
2600 pC->algo__part_to_part_range_offset_mm =
2601 pC2->algo__part_to_part_range_offset_mm;
2602 pC->mm_config__inner_offset_mm =
2603 pC2->mm_config__inner_offset_mm;
2604 pC->mm_config__outer_offset_mm =
2605 pC2->mm_config__outer_offset_mm;
2606
2607 pC->algo__crosstalk_compensation_plane_offset_kcps =
2608 (uint32_t)(
2609 pC2->algo__crosstalk_compensation_plane_offset_kcps);
2610 LOG_FUNCTION_END(Status);
2611 return Status;
2612 }
2613
2614
2615
VL53L1_GetOpticalCenter(VL53L1_DEV Dev,FixPoint1616_t * pOpticalCenterX,FixPoint1616_t * pOpticalCenterY)2616 VL53L1_Error VL53L1_GetOpticalCenter(VL53L1_DEV Dev,
2617 FixPoint1616_t *pOpticalCenterX,
2618 FixPoint1616_t *pOpticalCenterY)
2619 {
2620 VL53L1_Error Status = VL53L1_ERROR_NONE;
2621 VL53L1_calibration_data_t CalibrationData;
2622
2623 LOG_FUNCTION_START("");
2624
2625 *pOpticalCenterX = 0;
2626 *pOpticalCenterY = 0;
2627 Status = VL53L1_get_part_to_part_data(Dev, &CalibrationData);
2628 if (Status == VL53L1_ERROR_NONE) {
2629 *pOpticalCenterX = VL53L1_FIXPOINT44TOFIXPOINT1616(
2630 CalibrationData.optical_centre.x_centre);
2631 *pOpticalCenterY = VL53L1_FIXPOINT44TOFIXPOINT1616(
2632 CalibrationData.optical_centre.y_centre);
2633 }
2634
2635 LOG_FUNCTION_END(Status);
2636 return Status;
2637 }
2638
2639 /* END Group Calibration functions */
2640
2641
2642 /* Group PAL detection triggered events Functions */
2643
VL53L1_SetThresholdConfig(VL53L1_DEV Dev,VL53L1_DetectionConfig_t * pConfig)2644 VL53L1_Error VL53L1_SetThresholdConfig(VL53L1_DEV Dev,
2645 VL53L1_DetectionConfig_t *pConfig)
2646 {
2647 #define BADTHRESBOUNDS(T) \
2648 (((T.CrossMode == VL53L1_THRESHOLD_OUT_OF_WINDOW) || \
2649 (T.CrossMode == VL53L1_THRESHOLD_IN_WINDOW)) && (T.Low > T.High))
2650
2651 VL53L1_Error Status = VL53L1_ERROR_NONE;
2652 VL53L1_GPIO_interrupt_config_t Cfg;
2653 uint16_t g;
2654 FixPoint1616_t gain, high1616, low1616;
2655 VL53L1_LLDriverData_t *pdev;
2656
2657 LOG_FUNCTION_START("");
2658
2659 pdev = VL53L1DevStructGetLLDriverHandle(Dev);
2660
2661 Status = VL53L1_get_GPIO_interrupt_config(Dev, &Cfg);
2662 if (Status != VL53L1_ERROR_NONE)
2663 return Status;
2664
2665 if (pConfig->DetectionMode == VL53L1_DETECTION_NORMAL_RUN) {
2666 Cfg.intr_new_measure_ready = 1;
2667 Status = VL53L1_set_GPIO_interrupt_config_struct(Dev,
2668 Cfg);
2669 } else {
2670 if (BADTHRESBOUNDS(pConfig->Distance))
2671 Status = VL53L1_ERROR_INVALID_PARAMS;
2672 if ((Status == VL53L1_ERROR_NONE) &&
2673 (BADTHRESBOUNDS(pConfig->Rate)))
2674 Status = VL53L1_ERROR_INVALID_PARAMS;
2675 if (Status == VL53L1_ERROR_NONE) {
2676 Cfg.intr_new_measure_ready = 0;
2677 Cfg.intr_no_target = pConfig->IntrNoTarget;
2678 /* fix ticket 466238 Apply invert distance gain to thresholds */
2679 g = pdev->gain_cal.standard_ranging_gain_factor;
2680 if (g != 0) {
2681 /* gain is ufix 5.11, convert to 16.16 */
2682 gain = (FixPoint1616_t) ((uint32_t)g << 5);
2683 high1616 = (FixPoint1616_t) ((uint32_t)
2684 pConfig->Distance.High << 16);
2685 low1616 = (FixPoint1616_t) ((uint32_t)
2686 pConfig->Distance.Low << 16);
2687 /* +32768 to round the results*/
2688 high1616 = (high1616 + 32768) / gain;
2689 low1616 = (low1616 + 32768) / gain;
2690 Cfg.threshold_distance_high = (uint16_t)
2691 (high1616 & 0xFFFF);
2692 Cfg.threshold_distance_low = (uint16_t)
2693 (low1616 & 0xFFFF);
2694 } /* end fix ticket 466238 */
2695 Cfg.threshold_rate_high =
2696 VL53L1_FIXPOINT1616TOFIXPOINT97(
2697 pConfig->Rate.High);
2698 Cfg.threshold_rate_low =
2699 VL53L1_FIXPOINT1616TOFIXPOINT97(
2700 pConfig->Rate.Low);
2701
2702 Cfg.intr_mode_distance = ConvertModeToLLD(
2703 &Status,
2704 pConfig->Distance.CrossMode);
2705 if (Status == VL53L1_ERROR_NONE)
2706 Cfg.intr_mode_rate = ConvertModeToLLD(
2707 &Status,
2708 pConfig->Rate.CrossMode);
2709 }
2710
2711 /* Refine thresholds combination now */
2712 if (Status == VL53L1_ERROR_NONE) {
2713 Cfg.intr_combined_mode = 1;
2714 switch (pConfig->DetectionMode) {
2715 case VL53L1_DETECTION_DISTANCE_ONLY:
2716 Cfg.threshold_rate_high = 0;
2717 Cfg.threshold_rate_low = 0;
2718 break;
2719 case VL53L1_DETECTION_RATE_ONLY:
2720 Cfg.threshold_distance_high = 0;
2721 Cfg.threshold_distance_low = 0;
2722 break;
2723 case VL53L1_DETECTION_DISTANCE_OR_RATE:
2724 /* Nothing to do all is already in place */
2725 break;
2726 case VL53L1_DETECTION_DISTANCE_AND_RATE:
2727 Cfg.intr_combined_mode = 0;
2728 break;
2729 default:
2730 Status = VL53L1_ERROR_INVALID_PARAMS;
2731 }
2732 }
2733
2734 if (Status == VL53L1_ERROR_NONE)
2735 Status =
2736 VL53L1_set_GPIO_interrupt_config_struct(Dev, Cfg);
2737
2738 }
2739
2740 LOG_FUNCTION_END(Status);
2741 return Status;
2742 }
2743
2744
VL53L1_GetThresholdConfig(VL53L1_DEV Dev,VL53L1_DetectionConfig_t * pConfig)2745 VL53L1_Error VL53L1_GetThresholdConfig(VL53L1_DEV Dev,
2746 VL53L1_DetectionConfig_t *pConfig)
2747 {
2748 VL53L1_Error Status = VL53L1_ERROR_NONE;
2749 VL53L1_GPIO_interrupt_config_t Cfg;
2750
2751 LOG_FUNCTION_START("");
2752
2753 Status = VL53L1_get_GPIO_interrupt_config(Dev, &Cfg);
2754
2755 if (Status != VL53L1_ERROR_NONE) {
2756 LOG_FUNCTION_END(Status);
2757 return Status;
2758 }
2759
2760 pConfig->IntrNoTarget = Cfg.intr_no_target;
2761 pConfig->Distance.High = Cfg.threshold_distance_high;
2762 pConfig->Distance.Low = Cfg.threshold_distance_low;
2763 pConfig->Rate.High =
2764 VL53L1_FIXPOINT97TOFIXPOINT1616(
2765 Cfg.threshold_rate_high);
2766 pConfig->Rate.Low =
2767 VL53L1_FIXPOINT97TOFIXPOINT1616(Cfg.threshold_rate_low);
2768 pConfig->Distance.CrossMode =
2769 ConvertModeFromLLD(&Status, Cfg.intr_mode_distance);
2770 if (Status == VL53L1_ERROR_NONE)
2771 pConfig->Rate.CrossMode =
2772 ConvertModeFromLLD(&Status, Cfg.intr_mode_rate);
2773
2774 if (Cfg.intr_new_measure_ready == 1) {
2775 pConfig->DetectionMode = VL53L1_DETECTION_NORMAL_RUN;
2776 } else {
2777 /* Refine thresholds combination now */
2778 if (Status == VL53L1_ERROR_NONE) {
2779 if (Cfg.intr_combined_mode == 0)
2780 pConfig->DetectionMode =
2781 VL53L1_DETECTION_DISTANCE_AND_RATE;
2782 else {
2783 if ((Cfg.threshold_distance_high == 0) &&
2784 (Cfg.threshold_distance_low == 0))
2785 pConfig->DetectionMode =
2786 VL53L1_DETECTION_RATE_ONLY;
2787 else if ((Cfg.threshold_rate_high == 0) &&
2788 (Cfg.threshold_rate_low == 0))
2789 pConfig->DetectionMode =
2790 VL53L1_DETECTION_DISTANCE_ONLY;
2791 else
2792 pConfig->DetectionMode =
2793 VL53L1_DETECTION_DISTANCE_OR_RATE;
2794 }
2795 }
2796 }
2797
2798 LOG_FUNCTION_END(Status);
2799 return Status;
2800 }
2801
2802
2803 /* End Group PAL IRQ Triggered events Functions */
2804
2805
VL53L1_LoadPatch(VL53L1_DEV Dev)2806 static VL53L1_Error VL53L1_LoadPatch(VL53L1_DEV Dev)
2807 {
2808 VL53L1_Error status = VL53L1_ERROR_NONE;
2809 uint32_t patch_tuning = 0;
2810 uint8_t comms_buffer[256];
2811 uint32_t patch_power;
2812 LOG_FUNCTION_START("");
2813
2814 if (status == VL53L1_ERROR_NONE)
2815 status = VL53L1_WrByte(
2816 Dev,
2817 VL53L1_FIRMWARE__ENABLE,
2818 0x00);
2819 /* Force GO1 on */
2820 if (status == VL53L1_ERROR_NONE)
2821 VL53L1_enable_powerforce(Dev);
2822
2823 patch_tuning = BDTable[VL53L1_TUNING_PHASECAL_PATCH_POWER];
2824
2825 switch(patch_tuning) {
2826 case 0:
2827 patch_power = 0x00;
2828 break;
2829 case 1:
2830 patch_power = 0x10;
2831 break;
2832 case 2:
2833 patch_power = 0x20;
2834 break;
2835 case 3:
2836 patch_power = 0x40;
2837 break;
2838 default:
2839 patch_power = 0x00;
2840 }
2841 /* Set patch RAM offsets */
2842 if (status == VL53L1_ERROR_NONE) {
2843 /* Package up MultiByte transaction */
2844 comms_buffer[0] = 0x29;
2845 comms_buffer[1] = 0xC9;
2846 comms_buffer[2] = 0x0E;
2847 comms_buffer[3] = 0x40;
2848 comms_buffer[4] = 0x28;
2849 comms_buffer[5] = patch_power;
2850 /* 0x10 for 60ms, 0x20 for 240ms and 0x40 for 3580ms */
2851 status = VL53L1_WriteMulti(
2852 Dev,
2853 VL53L1_PATCH__OFFSET_0,
2854 comms_buffer,
2855 6);
2856 }
2857 /* Set patch breakpoints */
2858 if (status == VL53L1_ERROR_NONE) {
2859 comms_buffer[0] = 0x03;
2860 comms_buffer[1] = 0x6D;
2861 comms_buffer[2] = 0x03;
2862 comms_buffer[3] = 0x6F;
2863 comms_buffer[4] = 0x07;
2864 comms_buffer[5] = 0x29;
2865 status = VL53L1_WriteMulti(
2866 Dev,
2867 VL53L1_PATCH__ADDRESS_0,
2868 comms_buffer,
2869 6);
2870 }
2871 /* Enable patch JMP patches */
2872 if (status == VL53L1_ERROR_NONE) {
2873 comms_buffer[0] = 0x00;
2874 comms_buffer[1] = 0x07;
2875 status = VL53L1_WriteMulti(
2876 Dev,
2877 VL53L1_PATCH__JMP_ENABLES,
2878 comms_buffer,
2879 2);
2880 }
2881 /* Enable patch DATA patches */
2882 if (status == VL53L1_ERROR_NONE) {
2883 comms_buffer[0] = 0x00;
2884 comms_buffer[1] = 0x07;
2885 status = VL53L1_WriteMulti(
2886 Dev,
2887 VL53L1_PATCH__DATA_ENABLES,
2888 comms_buffer,
2889 2);
2890 }
2891 /* Enable firmware patching */
2892 if (status == VL53L1_ERROR_NONE)
2893 status = VL53L1_WrByte(
2894 Dev,
2895 VL53L1_PATCH__CTRL,
2896 0x01);
2897 /* Enable Firmware */
2898 if (status == VL53L1_ERROR_NONE)
2899 status = VL53L1_WrByte(
2900 Dev,
2901 VL53L1_FIRMWARE__ENABLE,
2902 0x01);
2903
2904 LOG_FUNCTION_END(status);
2905
2906 return status;
2907 }
2908
VL53L1_UnloadPatch(VL53L1_DEV Dev)2909 static VL53L1_Error VL53L1_UnloadPatch(VL53L1_DEV Dev)
2910 {
2911 VL53L1_Error status = VL53L1_ERROR_NONE;
2912 /* Disable Firmware (allow full write access) */
2913 if (status == VL53L1_ERROR_NONE)
2914 status = VL53L1_WrByte(
2915 Dev,
2916 VL53L1_FIRMWARE__ENABLE,
2917 0x00);
2918 /* Force GO1 off */
2919 if (status == VL53L1_ERROR_NONE)
2920 VL53L1_disable_powerforce(Dev);
2921 /* Disable firmware patching */
2922 if (status == VL53L1_ERROR_NONE)
2923 status = VL53L1_WrByte(
2924 Dev,
2925 VL53L1_PATCH__CTRL,
2926 0x00);
2927 /* Enable Firmware */
2928 if (status == VL53L1_ERROR_NONE)
2929 status = VL53L1_WrByte(
2930 Dev,
2931 VL53L1_FIRMWARE__ENABLE,
2932 0x01);
2933
2934 LOG_FUNCTION_END(status);
2935
2936 return status;
2937 }
2938