1 /*
2 * Copyright (c) 2017, STMicroelectronics - All Rights Reserved
3 *
4 * This file is part of VL53L1 Core and is dual licensed,
5 * either 'STMicroelectronics
6 * Proprietary license'
7 * or 'BSD 3-clause "New" or "Revised" License' , at your option.
8 *
9 ********************************************************************************
10 *
11 * 'STMicroelectronics Proprietary license'
12 *
13 ********************************************************************************
14 *
15 * License terms: STMicroelectronics Proprietary in accordance with licensing
16 * terms at www.st.com/sla0081
17 *
18 * STMicroelectronics confidential
19 * Reproduction and Communication of this document is strictly prohibited unless
20 * specifically authorized in writing by STMicroelectronics.
21 *
22 *
23 ********************************************************************************
24 *
25 * Alternatively, VL53L1 Core may be distributed under the terms of
26 * 'BSD 3-clause "New" or "Revised" License', in which case the following
27 * provisions apply instead of the ones mentioned above :
28 *
29 ********************************************************************************
30 *
31 * License terms: BSD 3-clause "New" or "Revised" License.
32 *
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions are met:
35 *
36 * 1. Redistributions of source code must retain the above copyright notice, this
37 * list of conditions and the following disclaimer.
38 *
39 * 2. Redistributions in binary form must reproduce the above copyright notice,
40 * this list of conditions and the following disclaimer in the documentation
41 * and/or other materials provided with the distribution.
42 *
43 * 3. Neither the name of the copyright holder nor the names of its contributors
44 * may be used to endorse or promote products derived from this software
45 * without specific prior written permission.
46 *
47 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
48 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
50 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
53 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
54 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
55 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
56 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
57 *
58 *
59 ********************************************************************************
60 *
61 */
62 
63 /**
64  * @file  vl53l1_core.c
65  *
66  * @brief EwokPlus25 core function definition
67  */
68 
69 #include "vl53l1_ll_def.h"
70 #include "vl53l1_ll_device.h"
71 #include "vl53l1_platform.h"
72 #include "vl53l1_register_map.h"
73 #include "vl53l1_register_funcs.h"
74 #include "vl53l1_register_settings.h"
75 #include "vl53l1_api_preset_modes.h"
76 #include "vl53l1_core.h"
77 #include "vl53l1_tuning_parm_defaults.h"
78 
79 #ifdef VL53L1_LOGGING
80 #include "vl53l1_api_debug.h"
81 #include "vl53l1_debug.h"
82 #include "vl53l1_register_debug.h"
83 #endif
84 
85 #define LOG_FUNCTION_START(fmt, ...) \
86 	_LOG_FUNCTION_START(VL53L1_TRACE_MODULE_CORE, fmt, ##__VA_ARGS__)
87 #define LOG_FUNCTION_END(status, ...) \
88 	_LOG_FUNCTION_END(VL53L1_TRACE_MODULE_CORE, status, ##__VA_ARGS__)
89 #define LOG_FUNCTION_END_FMT(status, fmt, ...) \
90 	_LOG_FUNCTION_END_FMT(VL53L1_TRACE_MODULE_CORE, \
91 		status, fmt, ##__VA_ARGS__)
92 
93 #define trace_print(level, ...) \
94 	_LOG_TRACE_PRINT(VL53L1_TRACE_MODULE_CORE, \
95 	level, VL53L1_TRACE_FUNCTION_NONE, ##__VA_ARGS__)
96 
97 
VL53L1_init_version(VL53L1_DEV Dev)98 void  VL53L1_init_version(
99 	VL53L1_DEV        Dev)
100 {
101 	/**
102 	 * Initialise version structure
103 	 */
104 
105 	VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev);
106 
107 	pdev->version.ll_major    = VL53L1_LL_API_IMPLEMENTATION_VER_MAJOR;
108 	pdev->version.ll_minor    = VL53L1_LL_API_IMPLEMENTATION_VER_MINOR;
109 	pdev->version.ll_build    = VL53L1_LL_API_IMPLEMENTATION_VER_SUB;
110 	pdev->version.ll_revision = VL53L1_LL_API_IMPLEMENTATION_VER_REVISION;
111 }
112 
113 
VL53L1_init_ll_driver_state(VL53L1_DEV Dev,VL53L1_DeviceState device_state)114 void  VL53L1_init_ll_driver_state(
115 	VL53L1_DEV         Dev,
116 	VL53L1_DeviceState device_state)
117 {
118 	/**
119 	 * Initialise LL Driver state variables
120 	 */
121 
122 	VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev);
123 	VL53L1_ll_driver_state_t *pstate = &(pdev->ll_state);
124 
125 	pstate->cfg_device_state  = device_state;
126 	pstate->cfg_stream_count  = 0;
127 	pstate->cfg_gph_id        = VL53L1_GROUPEDPARAMETERHOLD_ID_MASK;
128 	pstate->cfg_timing_status = 0;
129 
130 	pstate->rd_device_state   = device_state;
131 	pstate->rd_stream_count   = 0;
132 	pstate->rd_gph_id         = VL53L1_GROUPEDPARAMETERHOLD_ID_MASK;
133 	pstate->rd_timing_status  = 0;
134 
135 }
136 
137 
VL53L1_update_ll_driver_rd_state(VL53L1_DEV Dev)138 VL53L1_Error  VL53L1_update_ll_driver_rd_state(
139 	VL53L1_DEV         Dev)
140 {
141 	/**
142 	 * State machine for read device state
143 	 *
144 	 * VL53L1_DEVICESTATE_SW_STANDBY
145 	 * VL53L1_DEVICESTATE_RANGING_WAIT_GPH_SYNC
146 	 * VL53L1_DEVICESTATE_RANGING_GATHER_DATA
147 	 * VL53L1_DEVICESTATE_RANGING_OUTPUT_DATA
148 	 */
149 
150 	VL53L1_Error        status  = VL53L1_ERROR_NONE;
151 	VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev);
152 	VL53L1_ll_driver_state_t *pstate = &(pdev->ll_state);
153 
154 	/* if top bits of mode start reset are zero then in standby state */
155 
156 	LOG_FUNCTION_START("");
157 
158 #ifdef VL53L1_LOGGING
159 	VL53L1_print_ll_driver_state(pstate);
160 #endif
161 
162 	if ((pdev->sys_ctrl.system__mode_start &
163 		VL53L1_DEVICEMEASUREMENTMODE_MODE_MASK) == 0x00) {
164 
165 		pstate->rd_device_state  = VL53L1_DEVICESTATE_SW_STANDBY;
166 		pstate->rd_stream_count  = 0;
167 		pstate->rd_gph_id = VL53L1_GROUPEDPARAMETERHOLD_ID_MASK;
168 		pstate->rd_timing_status = 0;
169 
170 	} else {
171 
172 		/*
173 		 * implement read stream count
174 		 */
175 
176 		if (pstate->rd_stream_count == 0xFF) {
177 			pstate->rd_stream_count = 0x80;
178 		} else {
179 			pstate->rd_stream_count++;
180 		}
181 
182 
183 		/*
184 		 * Toggle grouped parameter hold ID
185 		 */
186 
187 		pstate->rd_gph_id ^= VL53L1_GROUPEDPARAMETERHOLD_ID_MASK;
188 
189 		/* Ok now ranging  */
190 
191 		switch (pstate->rd_device_state) {
192 
193 		case VL53L1_DEVICESTATE_SW_STANDBY:
194 
195 			if ((pdev->dyn_cfg.system__grouped_parameter_hold &
196 				VL53L1_GROUPEDPARAMETERHOLD_ID_MASK) > 0) {
197 				pstate->rd_device_state =
198 					VL53L1_DEVICESTATE_RANGING_WAIT_GPH_SYNC;
199 			} else {
200 				pstate->rd_device_state =
201 					VL53L1_DEVICESTATE_RANGING_OUTPUT_DATA;
202 			}
203 
204 			pstate->rd_stream_count  = 0;
205 			pstate->rd_timing_status = 0;
206 
207 		break;
208 
209 		case VL53L1_DEVICESTATE_RANGING_WAIT_GPH_SYNC:
210 
211 			pstate->rd_stream_count = 0;
212 			pstate->rd_device_state =
213 				VL53L1_DEVICESTATE_RANGING_OUTPUT_DATA;
214 
215 		break;
216 
217 		case VL53L1_DEVICESTATE_RANGING_GATHER_DATA:
218 
219 			pstate->rd_device_state =
220 				VL53L1_DEVICESTATE_RANGING_OUTPUT_DATA;
221 
222 		break;
223 
224 		case VL53L1_DEVICESTATE_RANGING_OUTPUT_DATA:
225 
226 			pstate->rd_timing_status ^= 0x01;
227 
228 			pstate->rd_device_state =
229 				VL53L1_DEVICESTATE_RANGING_OUTPUT_DATA;
230 
231 		break;
232 
233 		default:
234 
235 			pstate->rd_device_state  =
236 				VL53L1_DEVICESTATE_SW_STANDBY;
237 			pstate->rd_stream_count  = 0;
238 			pstate->rd_gph_id = VL53L1_GROUPEDPARAMETERHOLD_ID_MASK;
239 			pstate->rd_timing_status = 0;
240 
241 		break;
242 		}
243 	}
244 
245 #ifdef VL53L1_LOGGING
246 	VL53L1_print_ll_driver_state(pstate);
247 #endif
248 
249 	LOG_FUNCTION_END(status);
250 
251 	return status;
252 }
253 
254 
VL53L1_check_ll_driver_rd_state(VL53L1_DEV Dev)255 VL53L1_Error VL53L1_check_ll_driver_rd_state(
256 	VL53L1_DEV         Dev)
257 {
258 	/*
259 	 * Checks if the LL Driver Read state and expected stream count
260 	 * matches the state and stream count received from the device
261 	 *
262 	 * Check is only use in back to back mode
263 	 */
264 
265 	VL53L1_Error         status = VL53L1_ERROR_NONE;
266 	VL53L1_LLDriverData_t  *pdev =
267 			VL53L1DevStructGetLLDriverHandle(Dev);
268 
269 	VL53L1_ll_driver_state_t  *pstate       = &(pdev->ll_state);
270 	VL53L1_system_results_t   *psys_results = &(pdev->sys_results);
271 
272 	uint8_t   device_range_status   = 0;
273 	uint8_t   device_stream_count   = 0;
274 	uint8_t   device_gph_id         = 0;
275 
276 	LOG_FUNCTION_START("");
277 
278 #ifdef VL53L1_LOGGING
279 	VL53L1_print_ll_driver_state(pstate);
280 #endif
281 
282 	device_range_status =
283 			psys_results->result__range_status &
284 			VL53L1_RANGE_STATUS__RANGE_STATUS_MASK;
285 
286 	device_stream_count = psys_results->result__stream_count;
287 
288 	/* load the correct GPH ID */
289 	device_gph_id = (psys_results->result__interrupt_status &
290 		VL53L1_INTERRUPT_STATUS__GPH_ID_INT_STATUS_MASK) >> 4;
291 
292 	/* only apply checks in back to back mode */
293 
294 	if ((pdev->sys_ctrl.system__mode_start &
295 		VL53L1_DEVICEMEASUREMENTMODE_BACKTOBACK) ==
296 		VL53L1_DEVICEMEASUREMENTMODE_BACKTOBACK) {
297 
298 		/* if read state is wait for GPH sync interrupt then check the
299 		 * device returns a GPH range status value otherwise check that
300 		 * the stream count matches
301 		 *
302 		 * In theory the stream count should zero for the GPH interrupt
303 		 * but that is not the case after at abort ....
304 		 */
305 
306 		if (pstate->rd_device_state ==
307 			VL53L1_DEVICESTATE_RANGING_WAIT_GPH_SYNC) {
308 
309 			if (device_range_status !=
310 				VL53L1_DEVICEERROR_GPHSTREAMCOUNT0READY) {
311 				status = VL53L1_ERROR_GPH_SYNC_CHECK_FAIL;
312 			}
313 		} else {
314 			if (pstate->rd_stream_count != device_stream_count) {
315 				status = VL53L1_ERROR_STREAM_COUNT_CHECK_FAIL;
316 			}
317 
318 		/*
319 		 * Check Read state GPH ID
320 		 */
321 
322 		if (pstate->rd_gph_id != device_gph_id) {
323 			status = VL53L1_ERROR_GPH_ID_CHECK_FAIL;
324 #ifdef VL53L1_LOGGING
325 				trace_print(VL53L1_TRACE_LEVEL_ALL,
326 					"    RDSTATECHECK: Check failed: rd_gph_id: %d, device_gph_id: %d\n",
327 					pstate->rd_gph_id,
328 					device_gph_id);
329 #endif
330 			} else {
331 #ifdef VL53L1_LOGGING
332 				trace_print(VL53L1_TRACE_LEVEL_ALL,
333 					"    RDSTATECHECK: Check passed: rd_gph_id: %d, device_gph_id: %d\n",
334 					pstate->rd_gph_id,
335 					device_gph_id);
336 #endif
337 			}
338 
339 		} /* else (not in WAIT_GPH_SYNC) */
340 
341 	} /* if back to back */
342 
343 	LOG_FUNCTION_END(status);
344 
345 	return status;
346 }
347 
348 
VL53L1_update_ll_driver_cfg_state(VL53L1_DEV Dev)349 VL53L1_Error  VL53L1_update_ll_driver_cfg_state(
350 	VL53L1_DEV         Dev)
351 {
352 	/**
353 	 * State machine for configuration device state
354 	 */
355 
356 	VL53L1_Error         status = VL53L1_ERROR_NONE;
357 	VL53L1_LLDriverData_t  *pdev =
358 			VL53L1DevStructGetLLDriverHandle(Dev);
359 
360 	VL53L1_ll_driver_state_t *pstate = &(pdev->ll_state);
361 
362 	LOG_FUNCTION_START("");
363 
364 #ifdef VL53L1_LOGGING
365 	VL53L1_print_ll_driver_state(pstate);
366 #endif
367 
368 	/* if top bits of mode start reset are zero then in standby state */
369 
370 	if ((pdev->sys_ctrl.system__mode_start &
371 		VL53L1_DEVICEMEASUREMENTMODE_MODE_MASK) == 0x00) {
372 
373 		pstate->cfg_device_state  = VL53L1_DEVICESTATE_SW_STANDBY;
374 		pstate->cfg_stream_count  = 0;
375 		pstate->cfg_gph_id = VL53L1_GROUPEDPARAMETERHOLD_ID_MASK;
376 		pstate->cfg_timing_status = 0;
377 
378 	} else {
379 
380 		/*
381 		 * implement configuration stream count
382 		 */
383 
384 		if (pstate->cfg_stream_count == 0xFF) {
385 			pstate->cfg_stream_count = 0x80;
386 		} else {
387 			pstate->cfg_stream_count++;
388 		}
389 
390 		/*
391 		 * Toggle grouped parameter hold ID
392 		 */
393 
394 		pstate->cfg_gph_id ^= VL53L1_GROUPEDPARAMETERHOLD_ID_MASK;
395 
396 		/*
397 		 * Implement configuration state machine
398 		 */
399 
400 		switch (pstate->cfg_device_state) {
401 
402 		case VL53L1_DEVICESTATE_SW_STANDBY:
403 
404 			pstate->cfg_timing_status ^= 0x01;
405 			pstate->cfg_stream_count = 1;
406 
407 			pstate->cfg_device_state = VL53L1_DEVICESTATE_RANGING_DSS_AUTO;
408 		break;
409 
410 		case VL53L1_DEVICESTATE_RANGING_DSS_AUTO:
411 
412 			pstate->cfg_timing_status ^= 0x01;
413 
414 		break;
415 
416 		default:
417 
418 			pstate->cfg_device_state = VL53L1_DEVICESTATE_SW_STANDBY;
419 			pstate->cfg_stream_count = 0;
420 			pstate->cfg_gph_id = VL53L1_GROUPEDPARAMETERHOLD_ID_MASK;
421 			pstate->cfg_timing_status = 0;
422 
423 		break;
424 		}
425 	}
426 
427 #ifdef VL53L1_LOGGING
428 	VL53L1_print_ll_driver_state(pstate);
429 #endif
430 
431 	LOG_FUNCTION_END(status);
432 
433 	return status;
434 }
435 
436 
VL53L1_copy_rtn_good_spads_to_buffer(VL53L1_nvm_copy_data_t * pdata,uint8_t * pbuffer)437 void VL53L1_copy_rtn_good_spads_to_buffer(
438 	VL53L1_nvm_copy_data_t  *pdata,
439 	uint8_t                 *pbuffer)
440 {
441 	/*
442 	 * Convenience function to copy return SPAD enables to buffer
443 	 */
444 
445 	*(pbuffer +  0) = pdata->global_config__spad_enables_rtn_0;
446 	*(pbuffer +  1) = pdata->global_config__spad_enables_rtn_1;
447 	*(pbuffer +  2) = pdata->global_config__spad_enables_rtn_2;
448 	*(pbuffer +  3) = pdata->global_config__spad_enables_rtn_3;
449 	*(pbuffer +  4) = pdata->global_config__spad_enables_rtn_4;
450 	*(pbuffer +  5) = pdata->global_config__spad_enables_rtn_5;
451 	*(pbuffer +  6) = pdata->global_config__spad_enables_rtn_6;
452 	*(pbuffer +  7) = pdata->global_config__spad_enables_rtn_7;
453 	*(pbuffer +  8) = pdata->global_config__spad_enables_rtn_8;
454 	*(pbuffer +  9) = pdata->global_config__spad_enables_rtn_9;
455 	*(pbuffer + 10) = pdata->global_config__spad_enables_rtn_10;
456 	*(pbuffer + 11) = pdata->global_config__spad_enables_rtn_11;
457 	*(pbuffer + 12) = pdata->global_config__spad_enables_rtn_12;
458 	*(pbuffer + 13) = pdata->global_config__spad_enables_rtn_13;
459 	*(pbuffer + 14) = pdata->global_config__spad_enables_rtn_14;
460 	*(pbuffer + 15) = pdata->global_config__spad_enables_rtn_15;
461 	*(pbuffer + 16) = pdata->global_config__spad_enables_rtn_16;
462 	*(pbuffer + 17) = pdata->global_config__spad_enables_rtn_17;
463 	*(pbuffer + 18) = pdata->global_config__spad_enables_rtn_18;
464 	*(pbuffer + 19) = pdata->global_config__spad_enables_rtn_19;
465 	*(pbuffer + 20) = pdata->global_config__spad_enables_rtn_20;
466 	*(pbuffer + 21) = pdata->global_config__spad_enables_rtn_21;
467 	*(pbuffer + 22) = pdata->global_config__spad_enables_rtn_22;
468 	*(pbuffer + 23) = pdata->global_config__spad_enables_rtn_23;
469 	*(pbuffer + 24) = pdata->global_config__spad_enables_rtn_24;
470 	*(pbuffer + 25) = pdata->global_config__spad_enables_rtn_25;
471 	*(pbuffer + 26) = pdata->global_config__spad_enables_rtn_26;
472 	*(pbuffer + 27) = pdata->global_config__spad_enables_rtn_27;
473 	*(pbuffer + 28) = pdata->global_config__spad_enables_rtn_28;
474 	*(pbuffer + 29) = pdata->global_config__spad_enables_rtn_29;
475 	*(pbuffer + 30) = pdata->global_config__spad_enables_rtn_30;
476 	*(pbuffer + 31) = pdata->global_config__spad_enables_rtn_31;
477 }
478 
479 
VL53L1_init_system_results(VL53L1_system_results_t * pdata)480 void VL53L1_init_system_results(
481 		VL53L1_system_results_t  *pdata)
482 {
483 	/*
484 	 * Initialises the system results to all 0xFF just like the
485 	 * device firmware does a the start of a range
486 	 */
487 
488 	pdata->result__interrupt_status                       = 0xFF;
489 	pdata->result__range_status                           = 0xFF;
490 	pdata->result__report_status                          = 0xFF;
491 	pdata->result__stream_count                           = 0xFF;
492 
493 	pdata->result__dss_actual_effective_spads_sd0         = 0xFFFF;
494 	pdata->result__peak_signal_count_rate_mcps_sd0        = 0xFFFF;
495 	pdata->result__ambient_count_rate_mcps_sd0            = 0xFFFF;
496 	pdata->result__sigma_sd0                              = 0xFFFF;
497 	pdata->result__phase_sd0                              = 0xFFFF;
498 	pdata->result__final_crosstalk_corrected_range_mm_sd0 = 0xFFFF;
499 	pdata->result__peak_signal_count_rate_crosstalk_corrected_mcps_sd0 =
500 			0xFFFF;
501 	pdata->result__mm_inner_actual_effective_spads_sd0    = 0xFFFF;
502 	pdata->result__mm_outer_actual_effective_spads_sd0    = 0xFFFF;
503 	pdata->result__avg_signal_count_rate_mcps_sd0         = 0xFFFF;
504 
505 	pdata->result__dss_actual_effective_spads_sd1         = 0xFFFF;
506 	pdata->result__peak_signal_count_rate_mcps_sd1        = 0xFFFF;
507 	pdata->result__ambient_count_rate_mcps_sd1            = 0xFFFF;
508 	pdata->result__sigma_sd1                              = 0xFFFF;
509 	pdata->result__phase_sd1                              = 0xFFFF;
510 	pdata->result__final_crosstalk_corrected_range_mm_sd1 = 0xFFFF;
511 	pdata->result__spare_0_sd1                            = 0xFFFF;
512 	pdata->result__spare_1_sd1                            = 0xFFFF;
513 	pdata->result__spare_2_sd1                            = 0xFFFF;
514 	pdata->result__spare_3_sd1                            = 0xFF;
515 
516 }
517 
518 
VL53L1_i2c_encode_uint16_t(uint16_t ip_value,uint16_t count,uint8_t * pbuffer)519 void VL53L1_i2c_encode_uint16_t(
520 	uint16_t    ip_value,
521 	uint16_t    count,
522 	uint8_t    *pbuffer)
523 {
524 	/*
525 	 * Encodes a uint16_t register value into an I2C write buffer
526 	 * MS byte first order (as per I2C register map.
527 	 */
528 
529 	uint16_t   i    = 0;
530 	uint16_t   data = 0;
531 
532 	data =  ip_value;
533 
534 	for (i = 0; i < count ; i++) {
535 		pbuffer[count-i-1] = (uint8_t)(data & 0x00FF);
536 		data = data >> 8;
537 	}
538 }
539 
VL53L1_i2c_decode_uint16_t(uint16_t count,uint8_t * pbuffer)540 uint16_t VL53L1_i2c_decode_uint16_t(
541 	uint16_t    count,
542 	uint8_t    *pbuffer)
543 {
544 	/*
545 	 * Decodes a uint16_t from the input I2C read buffer
546 	 * (MS byte first order)
547 	 */
548 
549 	uint16_t   value = 0x00;
550 
551 	while (count-- > 0) {
552 		value = (value << 8) | (uint16_t)*pbuffer++;
553 	}
554 
555 	return value;
556 }
557 
558 
VL53L1_i2c_encode_int16_t(int16_t ip_value,uint16_t count,uint8_t * pbuffer)559 void VL53L1_i2c_encode_int16_t(
560 	int16_t     ip_value,
561 	uint16_t    count,
562 	uint8_t    *pbuffer)
563 {
564 	/*
565 	 * Encodes a int16_t register value into an I2C write buffer
566 	 * MS byte first order (as per I2C register map.
567 	 */
568 
569 	uint16_t   i    = 0;
570 	int16_t    data = 0;
571 
572 	data =  ip_value;
573 
574 	for (i = 0; i < count ; i++) {
575 		pbuffer[count-i-1] = (uint8_t)(data & 0x00FF);
576 		data = data >> 8;
577 	}
578 }
579 
VL53L1_i2c_decode_int16_t(uint16_t count,uint8_t * pbuffer)580 int16_t VL53L1_i2c_decode_int16_t(
581 	uint16_t    count,
582 	uint8_t    *pbuffer)
583 {
584 	/*
585 	 * Decodes a int16_t from the input I2C read buffer
586 	 * (MS byte first order)
587 	 */
588 
589 	int16_t    value = 0x00;
590 
591 	/* implement sign extension */
592 	if (*pbuffer >= 0x80) {
593 		value = 0xFFFF;
594 	}
595 
596 	while (count-- > 0) {
597 		value = (value << 8) | (int16_t)*pbuffer++;
598 	}
599 
600 	return value;
601 }
602 
VL53L1_i2c_encode_uint32_t(uint32_t ip_value,uint16_t count,uint8_t * pbuffer)603 void VL53L1_i2c_encode_uint32_t(
604 	uint32_t    ip_value,
605 	uint16_t    count,
606 	uint8_t    *pbuffer)
607 {
608 	/*
609 	 * Encodes a uint32_t register value into an I2C write buffer
610 	 * MS byte first order (as per I2C register map.
611 	 */
612 
613 	uint16_t   i    = 0;
614 	uint32_t   data = 0;
615 
616 	data =  ip_value;
617 
618 	for (i = 0; i < count ; i++) {
619 		pbuffer[count-i-1] = (uint8_t)(data & 0x00FF);
620 		data = data >> 8;
621 	}
622 }
623 
VL53L1_i2c_decode_uint32_t(uint16_t count,uint8_t * pbuffer)624 uint32_t VL53L1_i2c_decode_uint32_t(
625 	uint16_t    count,
626 	uint8_t    *pbuffer)
627 {
628 	/*
629 	 * Decodes a uint32_t from the input I2C read buffer
630 	 * (MS byte first order)
631 	 */
632 
633 	uint32_t   value = 0x00;
634 
635 	while (count-- > 0) {
636 		value = (value << 8) | (uint32_t)*pbuffer++;
637 	}
638 
639 	return value;
640 }
641 
642 
VL53L1_i2c_decode_with_mask(uint16_t count,uint8_t * pbuffer,uint32_t bit_mask,uint32_t down_shift,uint32_t offset)643 uint32_t VL53L1_i2c_decode_with_mask(
644 	uint16_t    count,
645 	uint8_t    *pbuffer,
646 	uint32_t    bit_mask,
647 	uint32_t    down_shift,
648 	uint32_t    offset)
649 {
650 	/*
651 	 * Decodes an integer from the input I2C read buffer
652 	 * (MS byte first order)
653 	 */
654 
655 	uint32_t   value = 0x00;
656 
657 	/* extract from buffer */
658 	while (count-- > 0) {
659 		value = (value << 8) | (uint32_t)*pbuffer++;
660 	}
661 
662 	/* Apply bit mask and down shift */
663 	value =  value & bit_mask;
664 	if (down_shift > 0) {
665 		value = value >> down_shift;
666 	}
667 
668 	/* add offset */
669 	value = value + offset;
670 
671 	return value;
672 }
673 
674 
VL53L1_i2c_encode_int32_t(int32_t ip_value,uint16_t count,uint8_t * pbuffer)675 void VL53L1_i2c_encode_int32_t(
676 	int32_t     ip_value,
677 	uint16_t    count,
678 	uint8_t    *pbuffer)
679 {
680 	/*
681 	 * Encodes a int32_t register value into an I2C write buffer
682 	 * MS byte first order (as per I2C register map.
683 	 */
684 
685 	uint16_t   i    = 0;
686 	int32_t    data = 0;
687 
688 	data =  ip_value;
689 
690 	for (i = 0; i < count ; i++) {
691 		pbuffer[count-i-1] = (uint8_t)(data & 0x00FF);
692 		data = data >> 8;
693 	}
694 }
695 
VL53L1_i2c_decode_int32_t(uint16_t count,uint8_t * pbuffer)696 int32_t VL53L1_i2c_decode_int32_t(
697 	uint16_t    count,
698 	uint8_t    *pbuffer)
699 {
700 	/*
701 	 * Decodes a int32_t from the input I2C read buffer
702 	 * (MS byte first order)
703 	 */
704 
705 	int32_t    value = 0x00;
706 
707 	/* implement sign extension */
708 	if (*pbuffer >= 0x80) {
709 		value = 0xFFFFFFFF;
710 	}
711 
712 	while (count-- > 0) {
713 		value = (value << 8) | (int32_t)*pbuffer++;
714 	}
715 
716 	return value;
717 }
718 
719 
720 #ifndef VL53L1_NOCALIB
VL53L1_start_test(VL53L1_DEV Dev,uint8_t test_mode__ctrl)721 VL53L1_Error VL53L1_start_test(
722 	VL53L1_DEV    Dev,
723 	uint8_t       test_mode__ctrl)
724 {
725 	/*
726 	 * Triggers the start of a test mode
727 	 */
728 
729 	VL53L1_Error status = VL53L1_ERROR_NONE;
730 
731 	LOG_FUNCTION_START("");
732 
733 	if (status == VL53L1_ERROR_NONE) { /*lint !e774 always true*/
734 		status = VL53L1_WrByte(
735 					Dev,
736 					VL53L1_TEST_MODE__CTRL,
737 					test_mode__ctrl);
738 	}
739 
740 	LOG_FUNCTION_END(status);
741 
742 	return status;
743 }
744 #endif
745 
746 
VL53L1_set_firmware_enable_register(VL53L1_DEV Dev,uint8_t value)747 VL53L1_Error VL53L1_set_firmware_enable_register(
748 	VL53L1_DEV    Dev,
749 	uint8_t       value)
750 {
751 	/*
752 	 * Set FIRMWARE__ENABLE register
753 	 */
754 
755 	VL53L1_Error status         = VL53L1_ERROR_NONE;
756 	VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev);
757 
758 	pdev->sys_ctrl.firmware__enable = value;
759 
760 	status = VL53L1_WrByte(
761 				Dev,
762 				VL53L1_FIRMWARE__ENABLE,
763 				pdev->sys_ctrl.firmware__enable);
764 
765 	return status;
766 }
767 
VL53L1_enable_firmware(VL53L1_DEV Dev)768 VL53L1_Error VL53L1_enable_firmware(
769 	VL53L1_DEV    Dev)
770 {
771 	/*
772 	 * Enable firmware
773 	 */
774 
775 	VL53L1_Error status       = VL53L1_ERROR_NONE;
776 
777 	LOG_FUNCTION_START("");
778 
779 	status = VL53L1_set_firmware_enable_register(Dev, 0x01);
780 
781 	LOG_FUNCTION_END(status);
782 
783 	return status;
784 }
785 
786 
VL53L1_disable_firmware(VL53L1_DEV Dev)787 VL53L1_Error VL53L1_disable_firmware(
788 	VL53L1_DEV    Dev)
789 {
790 	/*
791 	 * Disable firmware
792 	 */
793 
794 	VL53L1_Error status       = VL53L1_ERROR_NONE;
795 
796 	LOG_FUNCTION_START("");
797 
798 	status = VL53L1_set_firmware_enable_register(Dev, 0x00);
799 
800 	LOG_FUNCTION_END(status);
801 
802 	return status;
803 }
804 
805 
VL53L1_set_powerforce_register(VL53L1_DEV Dev,uint8_t value)806 VL53L1_Error VL53L1_set_powerforce_register(
807 	VL53L1_DEV    Dev,
808 	uint8_t       value)
809 {
810 	/*
811 	 * Set power force register
812 	 */
813 
814 	VL53L1_Error status       = VL53L1_ERROR_NONE;
815 	VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev);
816 
817 	pdev->sys_ctrl.power_management__go1_power_force = value;
818 
819 	status = VL53L1_WrByte(
820 			Dev,
821 			VL53L1_POWER_MANAGEMENT__GO1_POWER_FORCE,
822 			pdev->sys_ctrl.power_management__go1_power_force);
823 
824 	return status;
825 }
826 
827 
VL53L1_enable_powerforce(VL53L1_DEV Dev)828 VL53L1_Error VL53L1_enable_powerforce(
829 	VL53L1_DEV    Dev)
830 {
831 	/*
832 	 * Enable power force
833 	 */
834 
835 	VL53L1_Error status       = VL53L1_ERROR_NONE;
836 
837 	LOG_FUNCTION_START("");
838 
839 	status = VL53L1_set_powerforce_register(Dev, 0x01);
840 
841 	LOG_FUNCTION_END(status);
842 
843 	return status;
844 }
845 
846 
VL53L1_disable_powerforce(VL53L1_DEV Dev)847 VL53L1_Error VL53L1_disable_powerforce(
848 	VL53L1_DEV    Dev)
849 {
850 	/*
851 	 * Disable power force
852 	 */
853 
854 	VL53L1_Error status       = VL53L1_ERROR_NONE;
855 
856 	LOG_FUNCTION_START("");
857 
858 	status = VL53L1_set_powerforce_register(Dev, 0x00);
859 
860 	LOG_FUNCTION_END(status);
861 
862 	return status;
863 }
864 
865 
VL53L1_clear_interrupt(VL53L1_DEV Dev)866 VL53L1_Error VL53L1_clear_interrupt(
867 	VL53L1_DEV    Dev)
868 {
869 	/*
870 	 * Clear Ranging interrupt by writing to
871 	 */
872 
873 	VL53L1_Error status       = VL53L1_ERROR_NONE;
874 	VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev);
875 
876 	LOG_FUNCTION_START("");
877 
878 	pdev->sys_ctrl.system__interrupt_clear = VL53L1_CLEAR_RANGE_INT;
879 
880 	status = VL53L1_WrByte(
881 					Dev,
882 					VL53L1_SYSTEM__INTERRUPT_CLEAR,
883 					pdev->sys_ctrl.system__interrupt_clear);
884 
885 	LOG_FUNCTION_END(status);
886 
887 	return status;
888 }
889 
890 
891 #ifdef VL53L1_DEBUG
VL53L1_force_shadow_stream_count_to_zero(VL53L1_DEV Dev)892 VL53L1_Error VL53L1_force_shadow_stream_count_to_zero(
893 	VL53L1_DEV    Dev)
894 {
895 	/*
896 	 * Forces shadow stream count to zero
897 	 */
898 
899 	VL53L1_Error status       = VL53L1_ERROR_NONE;
900 
901 	if (status == VL53L1_ERROR_NONE) { /*lint !e774 always true*/
902 		status = VL53L1_disable_firmware(Dev);
903 	}
904 
905 	if (status == VL53L1_ERROR_NONE) {
906 		status = VL53L1_WrByte(
907 				Dev,
908 				VL53L1_SHADOW_RESULT__STREAM_COUNT,
909 				0x00);
910 	}
911 
912 	if (status == VL53L1_ERROR_NONE) {
913 		status = VL53L1_enable_firmware(Dev);
914 	}
915 
916 	return status;
917 }
918 #endif
919 
VL53L1_calc_macro_period_us(uint16_t fast_osc_frequency,uint8_t vcsel_period)920 uint32_t VL53L1_calc_macro_period_us(
921 	uint16_t  fast_osc_frequency,
922 	uint8_t   vcsel_period)
923 {
924 	/* Calculates macro period in [us] from the input fast oscillator
925 	 * frequency and VCSEL period
926 	 *
927 	 * Macro period fixed point format = unsigned 12.12
928 	 * Maximum supported macro period  = 4095.9999 us
929 	 */
930 
931 	uint32_t  pll_period_us        = 0;
932 	uint8_t   vcsel_period_pclks   = 0;
933 	uint32_t  macro_period_us      = 0;
934 
935 	LOG_FUNCTION_START("");
936 
937 	/*  Calculate PLL period in [us] from the  fast_osc_frequency
938 	 *  Fast osc frequency fixed point format = unsigned 4.12
939 	 */
940 
941 	pll_period_us = VL53L1_calc_pll_period_us(fast_osc_frequency);
942 
943 	/*  VCSEL period
944 	 *  - the real VCSEL period in PLL clocks = 2*(VCSEL_PERIOD+1)
945 	 */
946 
947 	vcsel_period_pclks = VL53L1_decode_vcsel_period(vcsel_period);
948 
949 	/*  Macro period
950 	 *  - PLL period [us]      = 0.24 format
951 	 *      - for 1.0 MHz fast oscillator freq
952 	 *      - max PLL period = 1/64 (6-bits)
953 	 *      - i.e only the lower 18-bits of PLL Period value are used
954 	 *  - Macro period [vclks] = 2304 (12-bits)
955 	 *
956 	 *  Max bits (24 - 6) + 12 = 30-bits usage
957 	 *
958 	 *  Downshift by 6 before multiplying by the VCSEL Period
959 	 */
960 
961 	macro_period_us =
962 			(uint32_t)VL53L1_MACRO_PERIOD_VCSEL_PERIODS *
963 			pll_period_us;
964 	macro_period_us = macro_period_us >> 6;
965 
966 	macro_period_us = macro_period_us * (uint32_t)vcsel_period_pclks;
967 	macro_period_us = macro_period_us >> 6;
968 
969 #ifdef VL53L1_LOGGING
970 	trace_print(VL53L1_TRACE_LEVEL_DEBUG,
971 			"    %-48s : %10u\n", "pll_period_us",
972 			pll_period_us);
973 	trace_print(VL53L1_TRACE_LEVEL_DEBUG,
974 			"    %-48s : %10u\n", "vcsel_period_pclks",
975 			vcsel_period_pclks);
976 	trace_print(VL53L1_TRACE_LEVEL_DEBUG,
977 			"    %-48s : %10u\n", "macro_period_us",
978 			macro_period_us);
979 #endif
980 
981 	LOG_FUNCTION_END(0);
982 
983 	return macro_period_us;
984 }
985 
986 
VL53L1_calc_range_ignore_threshold(uint32_t central_rate,int16_t x_gradient,int16_t y_gradient,uint8_t rate_mult)987 uint16_t VL53L1_calc_range_ignore_threshold(
988 	uint32_t central_rate,
989 	int16_t  x_gradient,
990 	int16_t  y_gradient,
991 	uint8_t  rate_mult)
992 {
993 	/* Calculates Range Ignore Threshold rate per spad
994 	 * in Mcps - 3.13 format
995 	 *
996 	 * Calculates worst case xtalk rate per spad in array corner
997 	 * based on input central xtalk and x and y gradients
998 	 *
999 	 * Worst case rate = central rate + (8*(magnitude(xgrad)) +
1000 	 * (8*(magnitude(ygrad)))
1001 	 *
1002 	 * Range ignore threshold rate is then multiplied by user input
1003 	 * rate_mult (in 3.5 fractional format)
1004 	 *
1005 	 */
1006 
1007 	int32_t    range_ignore_thresh_int  = 0;
1008 	uint16_t   range_ignore_thresh_kcps = 0;
1009 	int32_t    central_rate_int         = 0;
1010 	int16_t    x_gradient_int           = 0;
1011 	int16_t    y_gradient_int           = 0;
1012 
1013 	LOG_FUNCTION_START("");
1014 
1015 	/* Shift central_rate to .13 fractional for simple addition */
1016 
1017 	central_rate_int = ((int32_t)central_rate * (1 << 4)) / (1000);
1018 
1019 	if (x_gradient < 0) {
1020 		x_gradient_int = x_gradient * -1;
1021 	}
1022 
1023 	if (y_gradient < 0) {
1024 		y_gradient_int = y_gradient * -1;
1025 	}
1026 
1027 	/* Calculate full rate per spad - worst case from measured xtalk */
1028 	/* Generated here from .11 fractional kcps */
1029 	/* Additional factor of 4 applied to bring fractional precision to .13 */
1030 
1031 	range_ignore_thresh_int = (8 * x_gradient_int * 4) + (8 * y_gradient_int * 4);
1032 
1033 	/* Convert Kcps to Mcps */
1034 
1035 	range_ignore_thresh_int = range_ignore_thresh_int / 1000;
1036 
1037 	/* Combine with Central Rate - Mcps .13 format*/
1038 
1039 	range_ignore_thresh_int = range_ignore_thresh_int + central_rate_int;
1040 
1041 	/* Mult by user input */
1042 
1043 	range_ignore_thresh_int = (int32_t)rate_mult * range_ignore_thresh_int;
1044 
1045 	range_ignore_thresh_int = (range_ignore_thresh_int + (1<<4)) / (1<<5);
1046 
1047 	/* Finally clip and output in correct format */
1048 
1049 	if (range_ignore_thresh_int > 0xFFFF) {
1050 		range_ignore_thresh_kcps = 0xFFFF;
1051 	} else {
1052 		range_ignore_thresh_kcps = (uint16_t)range_ignore_thresh_int;
1053 	}
1054 
1055 #ifdef VL53L1_LOGGING
1056 	trace_print(VL53L1_TRACE_LEVEL_DEBUG,
1057 			"    %-48s : %10u\n", "range_ignore_thresh_kcps",
1058 			range_ignore_thresh_kcps);
1059 #endif
1060 
1061 	LOG_FUNCTION_END(0);
1062 
1063 	return range_ignore_thresh_kcps;
1064 }
1065 
1066 
VL53L1_calc_timeout_mclks(uint32_t timeout_us,uint32_t macro_period_us)1067 uint32_t VL53L1_calc_timeout_mclks(
1068 	uint32_t timeout_us,
1069 	uint32_t macro_period_us)
1070 {
1071 	/*  Calculates the timeout value in macro periods based on the input
1072 	 *  timeout period in milliseconds and the macro period in [us]
1073 	 *
1074 	 *  Max timeout supported is 1000000 us (1 sec) -> 20-bits
1075 	 *  Max timeout in 20.12 format = 32-bits
1076 	 *
1077 	 *  Macro period [us] = 12.12 format
1078 	 */
1079 
1080 	uint32_t timeout_mclks   = 0;
1081 
1082 	LOG_FUNCTION_START("");
1083 
1084 	timeout_mclks   =
1085 			((timeout_us << 12) + (macro_period_us>>1)) /
1086 			macro_period_us;
1087 
1088 	LOG_FUNCTION_END(0);
1089 
1090 	return timeout_mclks;
1091 }
1092 
1093 
VL53L1_calc_encoded_timeout(uint32_t timeout_us,uint32_t macro_period_us)1094 uint16_t VL53L1_calc_encoded_timeout(
1095 	uint32_t timeout_us,
1096 	uint32_t macro_period_us)
1097 {
1098 	/*  Calculates the encoded timeout register value based on the input
1099 	 *  timeout period in milliseconds and the macro period in [us]
1100 	 *
1101 	 *  Max timeout supported is 1000000 us (1 sec) -> 20-bits
1102 	 *  Max timeout in 20.12 format = 32-bits
1103 	 *
1104 	 *  Macro period [us] = 12.12 format
1105 	 */
1106 
1107 	uint32_t timeout_mclks   = 0;
1108 	uint16_t timeout_encoded = 0;
1109 
1110 	LOG_FUNCTION_START("");
1111 
1112 	timeout_mclks   =
1113 		VL53L1_calc_timeout_mclks(timeout_us, macro_period_us);
1114 
1115 	timeout_encoded =
1116 		VL53L1_encode_timeout(timeout_mclks);
1117 
1118 #ifdef VL53L1_LOGGING
1119 	trace_print(VL53L1_TRACE_LEVEL_DEBUG,
1120 			"    %-48s : %10u  (0x%04X)\n", "timeout_mclks",
1121 			timeout_mclks, timeout_mclks);
1122 	trace_print(VL53L1_TRACE_LEVEL_DEBUG,
1123 			"    %-48s : %10u  (0x%04X)\n", "timeout_encoded",
1124 			timeout_encoded, timeout_encoded);
1125 #endif
1126 
1127 	LOG_FUNCTION_END(0);
1128 
1129 	return timeout_encoded;
1130 }
1131 
1132 
VL53L1_calc_timeout_us(uint32_t timeout_mclks,uint32_t macro_period_us)1133 uint32_t VL53L1_calc_timeout_us(
1134 	uint32_t timeout_mclks,
1135 	uint32_t macro_period_us)
1136 {
1137 	/*  Calculates the  timeout in [us] based on the input
1138 	 *  encoded timeout and the macro period in [us]
1139 	 *
1140 	 *  Max timeout supported is 1000000 us (1 sec) -> 20-bits
1141 	 *  Max timeout in 20.12 format = 32-bits
1142 	 *
1143 	 *  Macro period [us] = 12.12 format
1144 	 */
1145 
1146 	uint32_t timeout_us     = 0;
1147 	uint64_t tmp            = 0;
1148 
1149 	LOG_FUNCTION_START("");
1150 
1151 	tmp  = (uint64_t)timeout_mclks * (uint64_t)macro_period_us;
1152 	tmp += 0x00800;
1153 	tmp  = tmp >> 12;
1154 
1155 	timeout_us = (uint32_t)tmp;
1156 
1157 #ifdef VL53L1_LOGGING
1158 	trace_print(VL53L1_TRACE_LEVEL_DEBUG,
1159 			"    %-48s : %10u  (0x%04X)\n", "timeout_mclks",
1160 			timeout_mclks, timeout_mclks);
1161 
1162 	trace_print(VL53L1_TRACE_LEVEL_DEBUG,
1163 			"    %-48s : %10u us\n", "timeout_us",
1164 			timeout_us, timeout_us);
1165 #endif
1166 
1167 	LOG_FUNCTION_END(0);
1168 
1169 	return timeout_us;
1170 }
1171 
VL53L1_calc_crosstalk_plane_offset_with_margin(uint32_t plane_offset_kcps,int16_t margin_offset_kcps)1172 uint32_t VL53L1_calc_crosstalk_plane_offset_with_margin(
1173 		uint32_t     plane_offset_kcps,
1174 		int16_t      margin_offset_kcps)
1175 {
1176 	uint32_t plane_offset_with_margin = 0;
1177 	int32_t  plane_offset_kcps_temp   = 0;
1178 
1179 	LOG_FUNCTION_START("");
1180 
1181 	plane_offset_kcps_temp =
1182 		(int32_t)plane_offset_kcps +
1183 		(int32_t)margin_offset_kcps;
1184 
1185 	if (plane_offset_kcps_temp < 0) {
1186 		plane_offset_kcps_temp = 0;
1187 	} else {
1188 		if (plane_offset_kcps_temp > 0x3FFFF) {
1189 			plane_offset_kcps_temp = 0x3FFFF;
1190 		}
1191 	}
1192 
1193 	plane_offset_with_margin = (uint32_t) plane_offset_kcps_temp;
1194 
1195 	LOG_FUNCTION_END(0);
1196 
1197 	return plane_offset_with_margin;
1198 
1199 }
1200 
VL53L1_calc_decoded_timeout_us(uint16_t timeout_encoded,uint32_t macro_period_us)1201 uint32_t VL53L1_calc_decoded_timeout_us(
1202 	uint16_t timeout_encoded,
1203 	uint32_t macro_period_us)
1204 {
1205 	/*  Calculates the  timeout in [us] based on the input
1206 	 *  encoded timeout and the macro period in [us]
1207 	 *
1208 	 *  Max timeout supported is 1000000 us (1 sec) -> 20-bits
1209 	 *  Max timeout in 20.12 format = 32-bits
1210 	 *
1211 	 *  Macro period [us] = 12.12 format
1212 	 */
1213 
1214 	uint32_t timeout_mclks  = 0;
1215 	uint32_t timeout_us     = 0;
1216 
1217 	LOG_FUNCTION_START("");
1218 
1219 	timeout_mclks =
1220 		VL53L1_decode_timeout(timeout_encoded);
1221 
1222 	timeout_us    =
1223 		VL53L1_calc_timeout_us(timeout_mclks, macro_period_us);
1224 
1225 	LOG_FUNCTION_END(0);
1226 
1227 	return timeout_us;
1228 }
1229 
1230 
VL53L1_encode_timeout(uint32_t timeout_mclks)1231 uint16_t VL53L1_encode_timeout(uint32_t timeout_mclks)
1232 {
1233 	/*
1234 	 * Encode timeout in macro periods in (LSByte * 2^MSByte) + 1 format
1235 	 */
1236 
1237 	uint16_t encoded_timeout = 0;
1238 	uint32_t ls_byte = 0;
1239 	uint16_t ms_byte = 0;
1240 
1241 	if (timeout_mclks > 0) {
1242 		ls_byte = timeout_mclks - 1;
1243 
1244 		while ((ls_byte & 0xFFFFFF00) > 0) {
1245 			ls_byte = ls_byte >> 1;
1246 			ms_byte++;
1247 		}
1248 
1249 		encoded_timeout = (ms_byte << 8)
1250 				+ (uint16_t) (ls_byte & 0x000000FF);
1251 	}
1252 
1253 	return encoded_timeout;
1254 }
1255 
1256 
VL53L1_decode_timeout(uint16_t encoded_timeout)1257 uint32_t VL53L1_decode_timeout(uint16_t encoded_timeout)
1258 {
1259 	/*
1260 	 * Decode 16-bit timeout register value
1261 	 * format (LSByte * 2^MSByte) + 1
1262 	 */
1263 
1264 	uint32_t timeout_macro_clks = 0;
1265 
1266 	timeout_macro_clks = ((uint32_t) (encoded_timeout & 0x00FF)
1267 			<< (uint32_t) ((encoded_timeout & 0xFF00) >> 8)) + 1;
1268 
1269 	return timeout_macro_clks;
1270 }
1271 
1272 
VL53L1_calc_timeout_register_values(uint32_t phasecal_config_timeout_us,uint32_t mm_config_timeout_us,uint32_t range_config_timeout_us,uint16_t fast_osc_frequency,VL53L1_general_config_t * pgeneral,VL53L1_timing_config_t * ptiming)1273 VL53L1_Error VL53L1_calc_timeout_register_values(
1274 	uint32_t                 phasecal_config_timeout_us,
1275 	uint32_t                 mm_config_timeout_us,
1276 	uint32_t                 range_config_timeout_us,
1277 	uint16_t                 fast_osc_frequency,
1278 	VL53L1_general_config_t *pgeneral,
1279 	VL53L1_timing_config_t  *ptiming)
1280 {
1281 	/*
1282 	 * Converts the input MM and range timeouts in [us]
1283 	 * into the appropriate register values
1284 	 *
1285 	 * Must also be run after the VCSEL period settings are changed
1286 	 */
1287 
1288 	VL53L1_Error status = VL53L1_ERROR_NONE;
1289 
1290 	uint32_t macro_period_us    = 0;
1291 	uint32_t timeout_mclks      = 0;
1292 	uint16_t timeout_encoded    = 0;
1293 
1294 	LOG_FUNCTION_START("");
1295 
1296 	if (fast_osc_frequency == 0) {
1297 		status = VL53L1_ERROR_DIVISION_BY_ZERO;
1298 	} else {
1299 		/* Update Macro Period for Range A VCSEL Period */
1300 		macro_period_us =
1301 				VL53L1_calc_macro_period_us(
1302 					fast_osc_frequency,
1303 					ptiming->range_config__vcsel_period_a);
1304 
1305 		/*  Update Phase timeout - uses Timing A */
1306 		timeout_mclks =
1307 			VL53L1_calc_timeout_mclks(
1308 				phasecal_config_timeout_us,
1309 				macro_period_us);
1310 
1311 		/* clip as the phase cal timeout register is only 8-bits */
1312 		if (timeout_mclks > 0xFF)
1313 			timeout_mclks = 0xFF;
1314 
1315 		pgeneral->phasecal_config__timeout_macrop =
1316 				(uint8_t)timeout_mclks;
1317 
1318 		/*  Update MM Timing A timeout */
1319 		timeout_encoded =
1320 			VL53L1_calc_encoded_timeout(
1321 				mm_config_timeout_us,
1322 				macro_period_us);
1323 
1324 		ptiming->mm_config__timeout_macrop_a_hi =
1325 				(uint8_t)((timeout_encoded & 0xFF00) >> 8);
1326 		ptiming->mm_config__timeout_macrop_a_lo =
1327 				(uint8_t) (timeout_encoded & 0x00FF);
1328 
1329 		/* Update Range Timing A timeout */
1330 		timeout_encoded =
1331 			VL53L1_calc_encoded_timeout(
1332 				range_config_timeout_us,
1333 				macro_period_us);
1334 
1335 		ptiming->range_config__timeout_macrop_a_hi =
1336 				(uint8_t)((timeout_encoded & 0xFF00) >> 8);
1337 		ptiming->range_config__timeout_macrop_a_lo =
1338 				(uint8_t) (timeout_encoded & 0x00FF);
1339 
1340 		/* Update Macro Period for Range B VCSEL Period */
1341 		macro_period_us =
1342 				VL53L1_calc_macro_period_us(
1343 					fast_osc_frequency,
1344 					ptiming->range_config__vcsel_period_b);
1345 
1346 		/* Update MM Timing B timeout */
1347 		timeout_encoded =
1348 				VL53L1_calc_encoded_timeout(
1349 					mm_config_timeout_us,
1350 					macro_period_us);
1351 
1352 		ptiming->mm_config__timeout_macrop_b_hi =
1353 				(uint8_t)((timeout_encoded & 0xFF00) >> 8);
1354 		ptiming->mm_config__timeout_macrop_b_lo =
1355 				(uint8_t) (timeout_encoded & 0x00FF);
1356 
1357 		/* Update Range Timing B timeout */
1358 		timeout_encoded = VL53L1_calc_encoded_timeout(
1359 							range_config_timeout_us,
1360 							macro_period_us);
1361 
1362 		ptiming->range_config__timeout_macrop_b_hi =
1363 				(uint8_t)((timeout_encoded & 0xFF00) >> 8);
1364 		ptiming->range_config__timeout_macrop_b_lo =
1365 				(uint8_t) (timeout_encoded & 0x00FF);
1366 	}
1367 
1368 	LOG_FUNCTION_END(0);
1369 
1370 	return status;
1371 
1372 }
1373 
1374 
VL53L1_encode_vcsel_period(uint8_t vcsel_period_pclks)1375 uint8_t VL53L1_encode_vcsel_period(uint8_t vcsel_period_pclks)
1376 {
1377 	/*
1378 	 * Converts the encoded VCSEL period register value into
1379 	 * the real period in PLL clocks
1380 	 */
1381 
1382 	uint8_t vcsel_period_reg = 0;
1383 
1384 	vcsel_period_reg = (vcsel_period_pclks >> 1) - 1;
1385 
1386 	return vcsel_period_reg;
1387 }
1388 
1389 
VL53L1_decode_unsigned_integer(uint8_t * pbuffer,uint8_t no_of_bytes)1390 uint32_t VL53L1_decode_unsigned_integer(
1391 	uint8_t  *pbuffer,
1392 	uint8_t   no_of_bytes)
1393 {
1394 	/*
1395 	 * Decodes a integer number from the buffer
1396 	 */
1397 
1398 	uint8_t   i = 0;
1399 	uint32_t  decoded_value = 0;
1400 
1401 	for (i = 0 ; i < no_of_bytes ; i++) {
1402 		decoded_value = (decoded_value << 8) + (uint32_t)pbuffer[i];
1403 	}
1404 
1405 	return decoded_value;
1406 }
1407 
1408 
VL53L1_encode_unsigned_integer(uint32_t ip_value,uint8_t no_of_bytes,uint8_t * pbuffer)1409 void VL53L1_encode_unsigned_integer(
1410 	uint32_t  ip_value,
1411 	uint8_t   no_of_bytes,
1412 	uint8_t  *pbuffer)
1413 {
1414 	/*
1415 	 * Encodes an integer number into the buffer
1416 	 */
1417 
1418 	uint8_t   i    = 0;
1419 	uint32_t  data = 0;
1420 
1421 	data = ip_value;
1422 	for (i = 0; i < no_of_bytes ; i++) {
1423 		pbuffer[no_of_bytes-i-1] = data & 0x00FF;
1424 		data = data >> 8;
1425 	}
1426 }
1427 
1428 
VL53L1_spad_number_to_byte_bit_index(uint8_t spad_number,uint8_t * pbyte_index,uint8_t * pbit_index,uint8_t * pbit_mask)1429 void VL53L1_spad_number_to_byte_bit_index(
1430 	uint8_t  spad_number,
1431 	uint8_t *pbyte_index,
1432 	uint8_t *pbit_index,
1433 	uint8_t *pbit_mask)
1434 {
1435 
1436     /**
1437      *  Converts the input SPAD number into the SPAD Enable byte index, bit index and bit mask
1438      *
1439      *  byte_index = (spad_no >> 3)
1440      *  bit_index  =  spad_no & 0x07
1441      *  bit_mask   =  0x01 << bit_index
1442      */
1443 
1444     *pbyte_index  = spad_number >> 3;
1445     *pbit_index   = spad_number & 0x07;
1446     *pbit_mask    = 0x01 << *pbit_index;
1447 
1448 }
1449 
1450 
VL53L1_encode_row_col(uint8_t row,uint8_t col,uint8_t * pspad_number)1451 void VL53L1_encode_row_col(
1452 	uint8_t  row,
1453 	uint8_t  col,
1454 	uint8_t *pspad_number)
1455 {
1456 	/**
1457 	 *  Encodes the input array(row,col) location as SPAD number.
1458 	 */
1459 
1460 	if (row > 7) {
1461 		*pspad_number = 128 + (col << 3) + (15-row);
1462 	} else {
1463 		*pspad_number = ((15-col) << 3) + row;
1464 	}
1465 }
1466 
1467 
VL53L1_decode_zone_size(uint8_t encoded_xy_size,uint8_t * pwidth,uint8_t * pheight)1468 void VL53L1_decode_zone_size(
1469 	uint8_t  encoded_xy_size,
1470 	uint8_t  *pwidth,
1471 	uint8_t  *pheight)
1472 {
1473 
1474 	/* extract x and y sizes
1475 	 *
1476 	 * Important: the sense of the device width and height is swapped
1477 	 * versus the API sense
1478 	 *
1479 	 * MS Nibble = height
1480 	 * LS Nibble = width
1481 	 */
1482 
1483 	*pheight = encoded_xy_size >> 4;
1484 	*pwidth  = encoded_xy_size & 0x0F;
1485 
1486 }
1487 
1488 
VL53L1_encode_zone_size(uint8_t width,uint8_t height,uint8_t * pencoded_xy_size)1489 void VL53L1_encode_zone_size(
1490 	uint8_t  width,
1491 	uint8_t  height,
1492 	uint8_t *pencoded_xy_size)
1493 {
1494 	/* merge x and y sizes
1495 	 *
1496 	 * Important: the sense of the device width and height is swapped
1497 	 * versus the API sense
1498 	 *
1499 	 * MS Nibble = height
1500 	 * LS Nibble = width
1501 	 */
1502 
1503 	*pencoded_xy_size = (height << 4) + width;
1504 
1505 }
1506 
1507 
VL53L1_decode_zone_limits(uint8_t encoded_xy_centre,uint8_t encoded_xy_size,int16_t * px_ll,int16_t * py_ll,int16_t * px_ur,int16_t * py_ur)1508 void VL53L1_decode_zone_limits(
1509 	uint8_t   encoded_xy_centre,
1510 	uint8_t   encoded_xy_size,
1511 	int16_t  *px_ll,
1512 	int16_t  *py_ll,
1513 	int16_t  *px_ur,
1514 	int16_t  *py_ur)
1515 {
1516 
1517 	/*
1518 	 * compute zone lower left and upper right limits
1519 	 *
1520 	 * centre (8,8) width = 16, height = 16  -> (0,0) -> (15,15)
1521      * centre (8,8) width = 14, height = 16  -> (1,0) -> (14,15)
1522 	 */
1523 
1524 	uint8_t x_centre = 0;
1525 	uint8_t y_centre = 0;
1526 	uint8_t width    = 0;
1527 	uint8_t height   = 0;
1528 
1529 	/* decode zone centre and size information */
1530 
1531 	VL53L1_decode_row_col(
1532 		encoded_xy_centre,
1533 		&y_centre,
1534 		&x_centre);
1535 
1536 	VL53L1_decode_zone_size(
1537 		encoded_xy_size,
1538 		&width,
1539 		&height);
1540 
1541 	/* compute bounds and clip */
1542 
1543 	*px_ll = (int16_t)x_centre - ((int16_t)width + 1) / 2;
1544 	if (*px_ll < 0)
1545 		*px_ll = 0;
1546 
1547 	*px_ur = *px_ll + (int16_t)width;
1548 	if (*px_ur > (VL53L1_SPAD_ARRAY_WIDTH-1))
1549 		*px_ur = VL53L1_SPAD_ARRAY_WIDTH-1;
1550 
1551 	*py_ll = (int16_t)y_centre - ((int16_t)height + 1) / 2;
1552 	if (*py_ll < 0)
1553 		*py_ll = 0;
1554 
1555 	*py_ur = *py_ll + (int16_t)height;
1556 	if (*py_ur > (VL53L1_SPAD_ARRAY_HEIGHT-1))
1557 		*py_ur = VL53L1_SPAD_ARRAY_HEIGHT-1;
1558 }
1559 
1560 
VL53L1_is_aperture_location(uint8_t row,uint8_t col)1561 uint8_t VL53L1_is_aperture_location(
1562 	uint8_t row,
1563 	uint8_t col)
1564 {
1565 	/*
1566 	 * Returns > 0 if input (row,col) location  is an aperture
1567 	 */
1568 
1569 	uint8_t is_aperture = 0;
1570 	uint8_t mod_row     = row % 4;
1571 	uint8_t mod_col     = col % 4;
1572 
1573 	if (mod_row == 0 && mod_col == 2)
1574 		is_aperture = 1;
1575 
1576 	if (mod_row == 2 && mod_col == 0)
1577 		is_aperture = 1;
1578 
1579 	return is_aperture;
1580 }
1581 
1582 
VL53L1_calc_mm_effective_spads(uint8_t encoded_mm_roi_centre,uint8_t encoded_mm_roi_size,uint8_t encoded_zone_centre,uint8_t encoded_zone_size,uint8_t * pgood_spads,uint16_t aperture_attenuation,uint16_t * pmm_inner_effective_spads,uint16_t * pmm_outer_effective_spads)1583 void VL53L1_calc_mm_effective_spads(
1584 	uint8_t     encoded_mm_roi_centre,
1585 	uint8_t     encoded_mm_roi_size,
1586 	uint8_t     encoded_zone_centre,
1587 	uint8_t     encoded_zone_size,
1588 	uint8_t    *pgood_spads,
1589 	uint16_t    aperture_attenuation,
1590 	uint16_t   *pmm_inner_effective_spads,
1591 	uint16_t   *pmm_outer_effective_spads)
1592 {
1593 
1594 	/* Calculates the effective SPAD counts for the MM inner and outer
1595 	 * regions based on the input MM ROI, Zone info and return good
1596 	 * SPAD map
1597 	 */
1598 
1599 	int16_t   x         = 0;
1600 	int16_t   y         = 0;
1601 
1602 	int16_t   mm_x_ll   = 0;
1603 	int16_t   mm_y_ll   = 0;
1604 	int16_t   mm_x_ur   = 0;
1605 	int16_t   mm_y_ur   = 0;
1606 
1607 	int16_t   zone_x_ll = 0;
1608 	int16_t   zone_y_ll = 0;
1609 	int16_t   zone_x_ur = 0;
1610 	int16_t   zone_y_ur = 0;
1611 
1612 	uint8_t   spad_number = 0;
1613 	uint8_t   byte_index  = 0;
1614 	uint8_t   bit_index   = 0;
1615 	uint8_t   bit_mask    = 0;
1616 
1617 	uint8_t   is_aperture = 0;
1618 	uint16_t  spad_attenuation = 0;
1619 
1620 	/* decode the MM ROI and Zone limits */
1621 
1622 	VL53L1_decode_zone_limits(
1623 		encoded_mm_roi_centre,
1624 		encoded_mm_roi_size,
1625 		&mm_x_ll,
1626 		&mm_y_ll,
1627 		&mm_x_ur,
1628 		&mm_y_ur);
1629 
1630 	VL53L1_decode_zone_limits(
1631 		encoded_zone_centre,
1632 		encoded_zone_size,
1633 		&zone_x_ll,
1634 		&zone_y_ll,
1635 		&zone_x_ur,
1636 		&zone_y_ur);
1637 
1638 	/*
1639 	 * Loop though all SPAD within the zone. Check if it is
1640 	 * a good SPAD then add the  transmission value to either
1641 	 * the inner or outer effective SPAD count dependent if
1642 	 * the SPAD lies within the MM ROI.
1643 	 */
1644 
1645 	*pmm_inner_effective_spads = 0;
1646 	*pmm_outer_effective_spads = 0;
1647 
1648 	for (y = zone_y_ll ; y <= zone_y_ur ; y++) {
1649 		for (x = zone_x_ll ; x <= zone_x_ur ; x++) {
1650 
1651 			/* Convert location into SPAD number */
1652 
1653 			VL53L1_encode_row_col(
1654 				(uint8_t)y,
1655 				(uint8_t)x,
1656 				&spad_number);
1657 
1658 			/* Convert spad number into byte and bit index
1659 			 * this is required to look up the appropriate
1660 			 * SPAD enable bit with the 32-byte good SPAD
1661 			 * enable buffer
1662 			 */
1663 
1664 			VL53L1_spad_number_to_byte_bit_index(
1665 				spad_number,
1666 				&byte_index,
1667 				&bit_index,
1668 				&bit_mask);
1669 
1670 			/* If spad is good then add it */
1671 
1672 			if ((pgood_spads[byte_index] & bit_mask) > 0) {
1673 				/* determine if apertured SPAD or not */
1674 
1675 				is_aperture = VL53L1_is_aperture_location(
1676 					(uint8_t)y,
1677 					(uint8_t)x);
1678 
1679 				if (is_aperture > 0)
1680 					spad_attenuation = aperture_attenuation;
1681 				else
1682 					spad_attenuation = 0x0100;
1683 
1684 				/*
1685 				 * if inside MM roi add to inner effective SPAD count
1686 				 * otherwise add to outer effective SPAD Count
1687 				 */
1688 
1689 				if (x >= mm_x_ll && x <= mm_x_ur &&
1690 					y >= mm_y_ll && y <= mm_y_ur)
1691 					*pmm_inner_effective_spads +=
1692 						spad_attenuation;
1693 				else
1694 					*pmm_outer_effective_spads +=
1695 						spad_attenuation;
1696 			}
1697 		}
1698 	}
1699 }
1700 
1701 
1702 /*
1703  * Encodes VL53L1_GPIO_interrupt_config_t structure to FW register format
1704  */
1705 
VL53L1_encode_GPIO_interrupt_config(VL53L1_GPIO_interrupt_config_t * pintconf)1706 uint8_t	VL53L1_encode_GPIO_interrupt_config(
1707 	VL53L1_GPIO_interrupt_config_t	*pintconf)
1708 {
1709 	uint8_t system__interrupt_config;
1710 
1711 	system__interrupt_config = pintconf->intr_mode_distance;
1712 	system__interrupt_config |= ((pintconf->intr_mode_rate) << 2);
1713 	system__interrupt_config |= ((pintconf->intr_new_measure_ready) << 5);
1714 	system__interrupt_config |= ((pintconf->intr_no_target) << 6);
1715 	system__interrupt_config |= ((pintconf->intr_combined_mode) << 7);
1716 
1717 	return system__interrupt_config;
1718 }
1719 
1720 /*
1721  * Decodes FW register to VL53L1_GPIO_interrupt_config_t structure
1722  */
1723 
VL53L1_decode_GPIO_interrupt_config(uint8_t system__interrupt_config)1724 VL53L1_GPIO_interrupt_config_t VL53L1_decode_GPIO_interrupt_config(
1725 	uint8_t		system__interrupt_config)
1726 {
1727 	VL53L1_GPIO_interrupt_config_t	intconf;
1728 
1729 	intconf.intr_mode_distance = system__interrupt_config & 0x03;
1730 	intconf.intr_mode_rate = (system__interrupt_config >> 2) & 0x03;
1731 	intconf.intr_new_measure_ready = (system__interrupt_config >> 5) & 0x01;
1732 	intconf.intr_no_target = (system__interrupt_config >> 6) & 0x01;
1733 	intconf.intr_combined_mode = (system__interrupt_config >> 7) & 0x01;
1734 
1735 	/* set some default values */
1736 	intconf.threshold_rate_low = 0;
1737 	intconf.threshold_rate_high = 0;
1738 	intconf.threshold_distance_low = 0;
1739 	intconf.threshold_distance_high = 0;
1740 
1741 	return intconf;
1742 }
1743 
1744 /*
1745  * Set GPIO distance threshold
1746  */
1747 
VL53L1_set_GPIO_distance_threshold(VL53L1_DEV Dev,uint16_t threshold_high,uint16_t threshold_low)1748 VL53L1_Error VL53L1_set_GPIO_distance_threshold(
1749 	VL53L1_DEV                      Dev,
1750 	uint16_t			threshold_high,
1751 	uint16_t			threshold_low)
1752 {
1753 	VL53L1_Error  status = VL53L1_ERROR_NONE;
1754 
1755 	VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev);
1756 
1757 	LOG_FUNCTION_START("");
1758 
1759 	pdev->dyn_cfg.system__thresh_high = threshold_high;
1760 	pdev->dyn_cfg.system__thresh_low = threshold_low;
1761 
1762 	LOG_FUNCTION_END(status);
1763 	return status;
1764 }
1765 
1766 /*
1767  * Set GPIO rate threshold
1768  */
1769 
VL53L1_set_GPIO_rate_threshold(VL53L1_DEV Dev,uint16_t threshold_high,uint16_t threshold_low)1770 VL53L1_Error VL53L1_set_GPIO_rate_threshold(
1771 	VL53L1_DEV                      Dev,
1772 	uint16_t			threshold_high,
1773 	uint16_t			threshold_low)
1774 {
1775 	VL53L1_Error  status = VL53L1_ERROR_NONE;
1776 
1777 	VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev);
1778 
1779 	LOG_FUNCTION_START("");
1780 
1781 	pdev->gen_cfg.system__thresh_rate_high = threshold_high;
1782 	pdev->gen_cfg.system__thresh_rate_low = threshold_low;
1783 
1784 	LOG_FUNCTION_END(status);
1785 	return status;
1786 }
1787 
1788 /*
1789  * Set GPIO thresholds from structure
1790  */
1791 
VL53L1_set_GPIO_thresholds_from_struct(VL53L1_DEV Dev,VL53L1_GPIO_interrupt_config_t * pintconf)1792 VL53L1_Error VL53L1_set_GPIO_thresholds_from_struct(
1793 	VL53L1_DEV                      Dev,
1794 	VL53L1_GPIO_interrupt_config_t *pintconf)
1795 {
1796 	VL53L1_Error  status = VL53L1_ERROR_NONE;
1797 
1798 	LOG_FUNCTION_START("");
1799 
1800 	status = VL53L1_set_GPIO_distance_threshold(
1801 			Dev,
1802 			pintconf->threshold_distance_high,
1803 			pintconf->threshold_distance_low);
1804 
1805 	if (status == VL53L1_ERROR_NONE) {
1806 		status =
1807 			VL53L1_set_GPIO_rate_threshold(
1808 				Dev,
1809 				pintconf->threshold_rate_high,
1810 				pintconf->threshold_rate_low);
1811 	}
1812 
1813 	LOG_FUNCTION_END(status);
1814 	return status;
1815 }
1816 
1817 
1818 #ifndef VL53L1_NOCALIB
VL53L1_set_ref_spad_char_config(VL53L1_DEV Dev,uint8_t vcsel_period_a,uint32_t phasecal_timeout_us,uint16_t total_rate_target_mcps,uint16_t max_count_rate_rtn_limit_mcps,uint16_t min_count_rate_rtn_limit_mcps,uint16_t fast_osc_frequency)1819 VL53L1_Error VL53L1_set_ref_spad_char_config(
1820 	VL53L1_DEV    Dev,
1821 	uint8_t       vcsel_period_a,
1822 	uint32_t      phasecal_timeout_us,
1823 	uint16_t      total_rate_target_mcps,
1824 	uint16_t      max_count_rate_rtn_limit_mcps,
1825 	uint16_t      min_count_rate_rtn_limit_mcps,
1826 	uint16_t      fast_osc_frequency)
1827 {
1828 	/*
1829 	 * Initialises the VCSEL period A and phasecal timeout registers
1830 	 * for the Reference SPAD Characterisation test
1831 	 */
1832 
1833 	VL53L1_Error status = VL53L1_ERROR_NONE;
1834 	VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev);
1835 
1836 	uint8_t buffer[2];
1837 
1838 	uint32_t macro_period_us = 0;
1839 	uint32_t timeout_mclks   = 0;
1840 
1841 	LOG_FUNCTION_START("");
1842 
1843 	/*
1844 	 * Update Macro Period for Range A VCSEL Period
1845 	 */
1846 	macro_period_us =
1847 		VL53L1_calc_macro_period_us(
1848 			fast_osc_frequency,
1849 			vcsel_period_a);
1850 
1851 	/*
1852 	 *  Calculate PhaseCal timeout and clip to max of 255 macro periods
1853 	 */
1854 
1855 	timeout_mclks = phasecal_timeout_us << 12;
1856 	timeout_mclks = timeout_mclks + (macro_period_us>>1);
1857 	timeout_mclks = timeout_mclks / macro_period_us;
1858 
1859 	if (timeout_mclks > 0xFF)
1860 		pdev->gen_cfg.phasecal_config__timeout_macrop = 0xFF;
1861 	else
1862 		pdev->gen_cfg.phasecal_config__timeout_macrop =
1863 				(uint8_t)timeout_mclks;
1864 
1865 	pdev->tim_cfg.range_config__vcsel_period_a = vcsel_period_a;
1866 
1867 	/*
1868 	 * Update device settings
1869 	 */
1870 
1871 	if (status == VL53L1_ERROR_NONE) /*lint !e774 always true*/
1872 		status =
1873 			VL53L1_WrByte(
1874 				Dev,
1875 				VL53L1_PHASECAL_CONFIG__TIMEOUT_MACROP,
1876 				pdev->gen_cfg.phasecal_config__timeout_macrop);
1877 
1878 	if (status == VL53L1_ERROR_NONE)
1879 		status =
1880 			VL53L1_WrByte(
1881 				Dev,
1882 				VL53L1_RANGE_CONFIG__VCSEL_PERIOD_A,
1883 				pdev->tim_cfg.range_config__vcsel_period_a);
1884 
1885 	/*
1886 	 * Copy vcsel register value to the WOI registers to ensure that
1887 	 * it is correctly set for the specified VCSEL period
1888 	 */
1889 
1890 	buffer[0] = pdev->tim_cfg.range_config__vcsel_period_a;
1891 	buffer[1] = pdev->tim_cfg.range_config__vcsel_period_a;
1892 
1893 	if (status == VL53L1_ERROR_NONE)
1894 		status =
1895 			VL53L1_WriteMulti(
1896 				Dev,
1897 				VL53L1_SD_CONFIG__WOI_SD0,
1898 				buffer,
1899 				2); /* It should be be replaced with a define */
1900 
1901 	/*
1902 	 * Set min, target and max rate limits
1903 	 */
1904 
1905 	pdev->customer.ref_spad_char__total_rate_target_mcps =
1906 			total_rate_target_mcps;
1907 
1908 	if (status == VL53L1_ERROR_NONE)
1909 		status =
1910 			VL53L1_WrWord(
1911 				Dev,
1912 				VL53L1_REF_SPAD_CHAR__TOTAL_RATE_TARGET_MCPS,
1913 				total_rate_target_mcps);  /* 9.7 format */
1914 
1915 	if (status == VL53L1_ERROR_NONE)
1916 		status =
1917 			VL53L1_WrWord(
1918 				Dev,
1919 				VL53L1_RANGE_CONFIG__SIGMA_THRESH,
1920 				max_count_rate_rtn_limit_mcps);
1921 
1922 	if (status == VL53L1_ERROR_NONE)
1923 		status =
1924 			VL53L1_WrWord(
1925 				Dev,
1926 				VL53L1_RANGE_CONFIG__MIN_COUNT_RATE_RTN_LIMIT_MCPS,
1927 				min_count_rate_rtn_limit_mcps);
1928 
1929 	LOG_FUNCTION_END(status);
1930 
1931 	return status;
1932 }
1933 
1934 
VL53L1_set_ssc_config(VL53L1_DEV Dev,VL53L1_ssc_config_t * pssc_cfg,uint16_t fast_osc_frequency)1935 VL53L1_Error VL53L1_set_ssc_config(
1936 	VL53L1_DEV            Dev,
1937 	VL53L1_ssc_config_t  *pssc_cfg,
1938 	uint16_t              fast_osc_frequency)
1939 {
1940 	/**
1941 	 * Builds and sends a single I2C multiple byte transaction to
1942 	 * initialize the device for SSC.
1943 	 *
1944 	 * The function also sets the WOI registers based on the input
1945 	 * vcsel period register value.
1946 	 */
1947 
1948 	VL53L1_Error status = VL53L1_ERROR_NONE;
1949 	uint8_t buffer[5];
1950 
1951 	uint32_t macro_period_us = 0;
1952 	uint16_t timeout_encoded = 0;
1953 
1954 	LOG_FUNCTION_START("");
1955 
1956 	/*
1957 	 * Update Macro Period for Range A VCSEL Period
1958 	 */
1959 	macro_period_us =
1960 		VL53L1_calc_macro_period_us(
1961 			fast_osc_frequency,
1962 			pssc_cfg->vcsel_period);
1963 
1964 	/*
1965 	 *  Update MM Timing A timeout
1966 	 */
1967 	timeout_encoded =
1968 		VL53L1_calc_encoded_timeout(
1969 			pssc_cfg->timeout_us,
1970 			macro_period_us);
1971 
1972 	/* update VCSEL timings */
1973 
1974 	if (status == VL53L1_ERROR_NONE)
1975 		status =
1976 			VL53L1_WrByte(
1977 				Dev,
1978 				VL53L1_CAL_CONFIG__VCSEL_START,
1979 				pssc_cfg->vcsel_start);
1980 
1981 	if (status == VL53L1_ERROR_NONE)
1982 		status =
1983 			VL53L1_WrByte(
1984 				Dev,
1985 				VL53L1_GLOBAL_CONFIG__VCSEL_WIDTH,
1986 				pssc_cfg->vcsel_width);
1987 
1988 	/* build buffer for timeouts, period and rate limit */
1989 
1990     buffer[0] = (uint8_t)((timeout_encoded &  0x0000FF00) >> 8);
1991     buffer[1] = (uint8_t) (timeout_encoded &  0x000000FF);
1992     buffer[2] = pssc_cfg->vcsel_period;
1993     buffer[3] = (uint8_t)((pssc_cfg->rate_limit_mcps &  0x0000FF00) >> 8);
1994     buffer[4] = (uint8_t) (pssc_cfg->rate_limit_mcps &  0x000000FF);
1995 
1996 	if (status == VL53L1_ERROR_NONE)
1997 		status =
1998 			VL53L1_WriteMulti(
1999 				Dev,
2000 				VL53L1_RANGE_CONFIG__TIMEOUT_MACROP_B_HI,
2001 				buffer,
2002 				5);
2003 
2004 	/*
2005 	 * Copy vcsel register value to the WOI registers to ensure that
2006 	 * it is correctly set for the specified VCSEL period
2007 	 */
2008 
2009     buffer[0] = pssc_cfg->vcsel_period;
2010     buffer[1] = pssc_cfg->vcsel_period;
2011 
2012 	if (status == VL53L1_ERROR_NONE)
2013 		status =
2014 			VL53L1_WriteMulti(
2015 				Dev,
2016 				VL53L1_SD_CONFIG__WOI_SD0,
2017 				buffer,
2018 				2);
2019 
2020 	/*
2021 	 * Write zero to NVM_BIST_CTRL to send RTN CountRate to Patch RAM
2022 	 * or 1 to write REF CountRate to Patch RAM
2023 	 */
2024 	if (status == VL53L1_ERROR_NONE)
2025 		status =
2026 			VL53L1_WrByte(
2027 				Dev,
2028 				VL53L1_NVM_BIST__CTRL,
2029 				pssc_cfg->array_select);
2030 
2031 	LOG_FUNCTION_END(status);
2032 
2033 	return status;
2034 }
2035 #endif
2036 
2037 
2038 #ifndef VL53L1_NOCALIB
VL53L1_get_spad_rate_data(VL53L1_DEV Dev,VL53L1_spad_rate_data_t * pspad_rates)2039 VL53L1_Error VL53L1_get_spad_rate_data(
2040 	VL53L1_DEV                Dev,
2041 	VL53L1_spad_rate_data_t  *pspad_rates)
2042 {
2043 
2044     /**
2045      *  Gets the SSC rate map output
2046      */
2047 
2048 	VL53L1_Error status = VL53L1_ERROR_NONE;
2049     int               i = 0;
2050 
2051     uint8_t  data[512];
2052     uint8_t *pdata = &data[0];
2053 
2054 	LOG_FUNCTION_START("");
2055 
2056 	/* Disable Firmware to Read Patch Ram */
2057 
2058 	if (status == VL53L1_ERROR_NONE)
2059 		status = VL53L1_disable_firmware(Dev);
2060 
2061     /*
2062      * Read Return SPADs Rates from patch RAM.
2063      * Note : platform layer  splits the I2C comms into smaller chunks
2064      */
2065 
2066 	if (status == VL53L1_ERROR_NONE)
2067 		status =
2068 			VL53L1_ReadMulti(
2069 				Dev,
2070 				VL53L1_PRIVATE__PATCH_BASE_ADDR_RSLV,
2071 				pdata,
2072 				512);
2073 
2074     /* now convert into 16-bit number */
2075     pdata = &data[0];
2076     for (i = 0 ; i < VL53L1_NO_OF_SPAD_ENABLES ; i++) {
2077 		pspad_rates->rate_data[i] =
2078 			(uint16_t)VL53L1_decode_unsigned_integer(pdata, 2);
2079 		pdata += 2;
2080     }
2081 
2082     /* Initialise structure info */
2083 
2084     pspad_rates->buffer_size     = VL53L1_NO_OF_SPAD_ENABLES;
2085     pspad_rates->no_of_values    = VL53L1_NO_OF_SPAD_ENABLES;
2086     pspad_rates->fractional_bits = 15;
2087 
2088 	/* Re-enable Firmware */
2089 
2090 	if (status == VL53L1_ERROR_NONE)
2091 		status = VL53L1_enable_firmware(Dev);
2092 
2093 	LOG_FUNCTION_END(status);
2094 
2095 	return status;
2096 }
2097 #endif
2098 
2099 /* Start Patch_LowPowerAutoMode */
2100 
VL53L1_low_power_auto_data_init(VL53L1_DEV Dev)2101 VL53L1_Error VL53L1_low_power_auto_data_init(
2102 	VL53L1_DEV                          Dev
2103 	)
2104 {
2105 
2106 	/*
2107 	 * Initializes internal data structures for low power auto mode
2108 	 */
2109 
2110 	/* don't really use this here */
2111 	VL53L1_Error  status = VL53L1_ERROR_NONE;
2112 
2113 	VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev);
2114 
2115 	LOG_FUNCTION_START("");
2116 
2117 	pdev->low_power_auto_data.vhv_loop_bound =
2118 		VL53L1_TUNINGPARM_LOWPOWERAUTO_VHV_LOOP_BOUND_DEFAULT;
2119 	pdev->low_power_auto_data.is_low_power_auto_mode = 0;
2120 	pdev->low_power_auto_data.low_power_auto_range_count = 0;
2121 	pdev->low_power_auto_data.saved_interrupt_config = 0;
2122 	pdev->low_power_auto_data.saved_vhv_init = 0;
2123 	pdev->low_power_auto_data.saved_vhv_timeout = 0;
2124 	pdev->low_power_auto_data.first_run_phasecal_result = 0;
2125 	pdev->low_power_auto_data.dss__total_rate_per_spad_mcps = 0;
2126 	pdev->low_power_auto_data.dss__required_spads = 0;
2127 
2128 	LOG_FUNCTION_END(status);
2129 
2130 	return status;
2131 }
2132 
VL53L1_low_power_auto_data_stop_range(VL53L1_DEV Dev)2133 VL53L1_Error VL53L1_low_power_auto_data_stop_range(
2134 	VL53L1_DEV                          Dev
2135 	)
2136 {
2137 
2138 	/*
2139 	 * Range has been paused but may continue later
2140 	 */
2141 
2142 	/* don't really use this here */
2143 	VL53L1_Error  status = VL53L1_ERROR_NONE;
2144 
2145 	VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev);
2146 
2147 	LOG_FUNCTION_START("");
2148 
2149 	/* doing this ensures stop_range followed by a get_device_results does
2150 	 * not mess up the counters */
2151 
2152 	pdev->low_power_auto_data.low_power_auto_range_count = 0xFF;
2153 
2154 	pdev->low_power_auto_data.first_run_phasecal_result = 0;
2155 	pdev->low_power_auto_data.dss__total_rate_per_spad_mcps = 0;
2156 	pdev->low_power_auto_data.dss__required_spads = 0;
2157 
2158 	/* restore vhv configs */
2159 	if (pdev->low_power_auto_data.saved_vhv_init != 0)
2160 		pdev->stat_nvm.vhv_config__init =
2161 			pdev->low_power_auto_data.saved_vhv_init;
2162 	if (pdev->low_power_auto_data.saved_vhv_timeout != 0)
2163 		pdev->stat_nvm.vhv_config__timeout_macrop_loop_bound =
2164 			pdev->low_power_auto_data.saved_vhv_timeout;
2165 
2166 	/* remove phasecal override */
2167 	pdev->gen_cfg.phasecal_config__override = 0x00;
2168 
2169 	LOG_FUNCTION_END(status);
2170 
2171 	return status;
2172 }
2173 
VL53L1_config_low_power_auto_mode(VL53L1_general_config_t * pgeneral,VL53L1_dynamic_config_t * pdynamic,VL53L1_low_power_auto_data_t * plpadata)2174 VL53L1_Error VL53L1_config_low_power_auto_mode(
2175 	VL53L1_general_config_t   *pgeneral,
2176 	VL53L1_dynamic_config_t   *pdynamic,
2177 	VL53L1_low_power_auto_data_t *plpadata
2178 	)
2179 {
2180 
2181 	/*
2182 	 * Initializes configs for when low power auto presets are selected
2183 	 */
2184 
2185 	/* don't really use this here */
2186 	VL53L1_Error  status = VL53L1_ERROR_NONE;
2187 
2188 	SUPPRESS_UNUSED_WARNING(pgeneral);
2189 
2190 	LOG_FUNCTION_START("");
2191 
2192 	/* set low power auto mode */
2193 	plpadata->is_low_power_auto_mode = 1;
2194 
2195 	/* set low power range count to 0 */
2196 	plpadata->low_power_auto_range_count = 0;
2197 
2198 	/* Turn off MM1/MM2 and DSS2 */
2199 	pdynamic->system__sequence_config = \
2200 			VL53L1_SEQUENCE_VHV_EN | \
2201 			VL53L1_SEQUENCE_PHASECAL_EN | \
2202 			VL53L1_SEQUENCE_DSS1_EN | \
2203 			VL53L1_SEQUENCE_DSS2_EN | \
2204 			/* VL53L1_SEQUENCE_MM1_EN | \*/
2205 			/* VL53L1_SEQUENCE_MM2_EN | \*/
2206 			VL53L1_SEQUENCE_RANGE_EN;
2207 
2208 	LOG_FUNCTION_END(status);
2209 
2210 	return status;
2211 }
2212 
VL53L1_low_power_auto_setup_manual_calibration(VL53L1_DEV Dev)2213 VL53L1_Error VL53L1_low_power_auto_setup_manual_calibration(
2214 	VL53L1_DEV        Dev)
2215 {
2216 
2217 	/*
2218 	 * Setup ranges after the first one in low power auto mode by turning
2219 	 * off FW calibration steps and programming static values
2220 	 */
2221 
2222 	VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev);
2223 
2224 	/* don't really use this here */
2225 	VL53L1_Error  status = VL53L1_ERROR_NONE;
2226 
2227 	LOG_FUNCTION_START("");
2228 
2229 	/* save original vhv configs */
2230 	pdev->low_power_auto_data.saved_vhv_init =
2231 		pdev->stat_nvm.vhv_config__init;
2232 	pdev->low_power_auto_data.saved_vhv_timeout =
2233 		pdev->stat_nvm.vhv_config__timeout_macrop_loop_bound;
2234 
2235 	/* disable VHV init */
2236 	pdev->stat_nvm.vhv_config__init &= 0x7F;
2237 	/* set loop bound to tuning param */
2238 	pdev->stat_nvm.vhv_config__timeout_macrop_loop_bound =
2239 		(pdev->stat_nvm.vhv_config__timeout_macrop_loop_bound & 0x03) +
2240 		(pdev->low_power_auto_data.vhv_loop_bound << 2);
2241 	/* override phasecal */
2242 	pdev->gen_cfg.phasecal_config__override = 0x01;
2243 	pdev->low_power_auto_data.first_run_phasecal_result =
2244 		pdev->dbg_results.phasecal_result__vcsel_start;
2245 	pdev->gen_cfg.cal_config__vcsel_start =
2246 		pdev->low_power_auto_data.first_run_phasecal_result;
2247 
2248 	LOG_FUNCTION_END(status);
2249 
2250 	return status;
2251 }
2252 
VL53L1_low_power_auto_update_DSS(VL53L1_DEV Dev)2253 VL53L1_Error VL53L1_low_power_auto_update_DSS(
2254 	VL53L1_DEV        Dev)
2255 {
2256 
2257 	/*
2258 	 * Do a DSS calculation and update manual config
2259 	 */
2260 
2261 	VL53L1_LLDriverData_t *pdev = VL53L1DevStructGetLLDriverHandle(Dev);
2262 
2263 	/* don't really use this here */
2264 	VL53L1_Error  status = VL53L1_ERROR_NONE;
2265 
2266 	uint32_t utemp32a;
2267 
2268 	LOG_FUNCTION_START("");
2269 
2270 	/* Calc total rate per spad */
2271 
2272 	/* 9.7 format */
2273 	utemp32a = pdev->sys_results.result__peak_signal_count_rate_crosstalk_corrected_mcps_sd0 +
2274 		pdev->sys_results.result__ambient_count_rate_mcps_sd0;
2275 
2276 	/* clip to 16 bits */
2277 	if (utemp32a > 0xFFFF)
2278 		utemp32a = 0xFFFF;
2279 
2280 	/* shift up to take advantage of 32 bits */
2281 	/* 9.23 format */
2282 	utemp32a = utemp32a << 16;
2283 
2284 	/* check SPAD count */
2285 	if (pdev->sys_results.result__dss_actual_effective_spads_sd0 == 0)
2286 		status = VL53L1_ERROR_DIVISION_BY_ZERO;
2287 	else {
2288 		/* format 17.15 */
2289 		utemp32a = utemp32a /
2290 			pdev->sys_results.result__dss_actual_effective_spads_sd0;
2291 		/* save intermediate result */
2292 		pdev->low_power_auto_data.dss__total_rate_per_spad_mcps =
2293 			utemp32a;
2294 
2295 		/* get the target rate and shift up by 16
2296 		 * format 9.23 */
2297 		utemp32a = pdev->stat_cfg.dss_config__target_total_rate_mcps;
2298 		utemp32a = utemp32a << 16;
2299 
2300 		/* check for divide by zero */
2301 		if (pdev->low_power_auto_data.dss__total_rate_per_spad_mcps == 0)
2302 			status = VL53L1_ERROR_DIVISION_BY_ZERO;
2303 		else {
2304 			/* divide by rate per spad
2305 			 * format 24.8 */
2306 			utemp32a = utemp32a /
2307 				pdev->low_power_auto_data.dss__total_rate_per_spad_mcps;
2308 
2309 			/* clip to 16 bit */
2310 			if (utemp32a > 0xFFFF)
2311 				utemp32a = 0xFFFF;
2312 
2313 			/* save result in low power auto data */
2314 			pdev->low_power_auto_data.dss__required_spads =
2315 				(uint16_t)utemp32a;
2316 
2317 			/* override DSS config */
2318 			pdev->gen_cfg.dss_config__manual_effective_spads_select =
2319 				pdev->low_power_auto_data.dss__required_spads;
2320 			pdev->gen_cfg.dss_config__roi_mode_control =
2321 				VL53L1_DEVICEDSSMODE__REQUESTED_EFFFECTIVE_SPADS;
2322 		}
2323 
2324 	}
2325 
2326 	if (status == VL53L1_ERROR_DIVISION_BY_ZERO) {
2327 		/* We want to gracefully set a spad target, not just exit with
2328 		* an error */
2329 
2330 		/* set target to mid point */
2331 		pdev->low_power_auto_data.dss__required_spads = 0x8000;
2332 
2333 		/* override DSS config */
2334 		pdev->gen_cfg.dss_config__manual_effective_spads_select =
2335 		pdev->low_power_auto_data.dss__required_spads;
2336 		pdev->gen_cfg.dss_config__roi_mode_control =
2337 		VL53L1_DEVICEDSSMODE__REQUESTED_EFFFECTIVE_SPADS;
2338 
2339 		/* reset error */
2340 		status = VL53L1_ERROR_NONE;
2341 	}
2342 
2343 	LOG_FUNCTION_END(status);
2344 
2345 	return status;
2346 }
2347 
2348 
2349 /* End Patch_LowPowerAutoMode */
2350