Statistics
| Branch: | Tag: | Revision:

amiro-lld / include / VL53L0X / v1 / Api_vl53l0x / core / src / vl53l0x_api_core.c @ 6ebebd4d

History | View | Annotate | Download (73.463 KB)

1
/*******************************************************************************
2
 Copyright � 2016, STMicroelectronics International N.V.
3
 All rights reserved.
4

5
 Redistribution and use in source and binary forms, with or without
6
 modification, are permitted provided that the following conditions are met:
7
 * Redistributions of source code must retain the above copyright
8
 notice, this list of conditions and the following disclaimer.
9
 * Redistributions in binary form must reproduce the above copyright
10
 notice, this list of conditions and the following disclaimer in the
11
 documentation and/or other materials provided with the distribution.
12
 * Neither the name of STMicroelectronics nor the
13
 names of its contributors may be used to endorse or promote products
14
 derived from this software without specific prior written permission.
15

16
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
 WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
19
 NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
20
 IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY
21
 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 ******************************************************************************/
28

    
29
#include "vl53l0x_api.h"
30
#include "vl53l0x_api_core.h"
31
#include "vl53l0x_api_calibration.h"
32
//#include "periphAL.h"
33

    
34

    
35
#ifndef __KERNEL__
36
#include <stdlib.h>
37
#endif
38
#define LOG_FUNCTION_START(fmt, ...) \
39
    _LOG_FUNCTION_START(TRACE_MODULE_API, fmt, ##__VA_ARGS__)
40
#define LOG_FUNCTION_END(status, ...) \
41
    _LOG_FUNCTION_END(TRACE_MODULE_API, status, ##__VA_ARGS__)
42
#define LOG_FUNCTION_END_FMT(status, fmt, ...) \
43
    _LOG_FUNCTION_END_FMT(TRACE_MODULE_API, status, fmt, ##__VA_ARGS__)
44

    
45
VL53L0X_Error VL53L0X_reverse_bytes(uint8_t *data, uint32_t size)
46
{
47
    VL53L0X_Error Status = VL53L0X_ERROR_NONE;
48
    uint8_t tempData;
49
    uint32_t mirrorIndex;
50
    uint32_t middle = size/2;
51
    uint32_t index;
52

    
53
    for (index = 0; index < middle; index++) {
54
        mirrorIndex                 = size - index - 1;
55
        tempData                 = data[index];
56
        data[index]                 = data[mirrorIndex];
57
        data[mirrorIndex] = tempData;
58
    }
59
    return Status;
60
}
61

    
62
VL53L0X_Error VL53L0X_measurement_poll_for_completion(VL53L0X_DEV Dev)
63
{
64
    VL53L0X_Error Status = VL53L0X_ERROR_NONE;
65
    uint8_t NewDataReady = 0;
66
    uint32_t LoopNb;
67

    
68
    LOG_FUNCTION_START("");
69

    
70
    LoopNb = 0;
71

    
72
    do {
73
        Status = VL53L0X_GetMeasurementDataReady(Dev, &NewDataReady);
74
        if (Status != 0)
75
            break; /* the error is set */
76

    
77
        if (NewDataReady == 1)
78
            break; /* done note that status == 0 */
79

    
80
        LoopNb++;
81
        if (LoopNb >= VL53L0X_DEFAULT_MAX_LOOP) {
82
            Status = VL53L0X_ERROR_TIME_OUT;
83
            break;
84
        }
85

    
86
        // sleep for 1 millisec
87
        usleep(1000);
88

    
89
    } while (1);
90

    
91
    LOG_FUNCTION_END(Status);
92

    
93
    return Status;
94
}
95

    
96

    
97
uint8_t VL53L0X_decode_vcsel_period(uint8_t vcsel_period_reg)
98
{
99
    /*!
100
     * Converts the encoded VCSEL period register value into the real
101
     * period in PLL clocks
102
     */
103

    
104
    uint8_t vcsel_period_pclks = 0;
105

    
106
    vcsel_period_pclks = (vcsel_period_reg + 1) << 1;
107

    
108
    return vcsel_period_pclks;
109
}
110

    
111
uint8_t VL53L0X_encode_vcsel_period(uint8_t vcsel_period_pclks)
112
{
113
    /*!
114
     * Converts the encoded VCSEL period register value into the real period
115
     * in PLL clocks
116
     */
117

    
118
    uint8_t vcsel_period_reg = 0;
119

    
120
    vcsel_period_reg = (vcsel_period_pclks >> 1) - 1;
121

    
122
    return vcsel_period_reg;
123
}
124

    
125

    
126
uint32_t VL53L0X_isqrt(uint32_t num)
127
{
128
    /*
129
     * Implements an integer square root
130
     *
131
     * From: http://en.wikipedia.org/wiki/Methods_of_computing_square_roots
132
     */
133

    
134
    uint32_t  res = 0;
135
    uint32_t  bit = 1 << 30;
136
    /* The second-to-top bit is set:
137
     *        1 << 14 for 16-bits, 1 << 30 for 32 bits */
138

    
139
     /* "bit" starts at the highest power of four <= the argument. */
140
    while (bit > num)
141
        bit >>= 2;
142

    
143

    
144
    while (bit != 0) {
145
        if (num >= res + bit) {
146
            num -= res + bit;
147
            res = (res >> 1) + bit;
148
        } else
149
            res >>= 1;
150

    
151
        bit >>= 2;
152
    }
153

    
154
    return res;
155
}
156

    
157

    
158
uint32_t VL53L0X_quadrature_sum(uint32_t a, uint32_t b)
159
{
160
    /*
161
     * Implements a quadrature sum
162
     *
163
     * rea = sqrt(a^2 + b^2)
164
     *
165
     * Trap overflow case max input value is 65535 (16-bit value)
166
     * as internal calc are 32-bit wide
167
     *
168
     * If overflow then seta output to maximum
169
     */
170
    uint32_t  res = 0;
171

    
172
    if (a > 65535 || b > 65535)
173
        res = 65535;
174
    else
175
        res = VL53L0X_isqrt(a * a + b * b);
176

    
177
    return res;
178
}
179

    
180

    
181
VL53L0X_Error VL53L0X_device_read_strobe(VL53L0X_DEV Dev)
182
{
183
    VL53L0X_Error Status = VL53L0X_ERROR_NONE;
184
    uint8_t strobe;
185
    uint32_t LoopNb;
186
    LOG_FUNCTION_START("");
187

    
188
    Status |= VL53L0X_WrByte(Dev, 0x83, 0x00);
189

    
190
    /* polling
191
     * use timeout to avoid deadlock*/
192
    if (Status == VL53L0X_ERROR_NONE) {
193
        LoopNb = 0;
194
        do {
195
            Status = VL53L0X_RdByte(Dev, 0x83, &strobe);
196
            if ((strobe != 0x00) || Status != VL53L0X_ERROR_NONE)
197
                    break;
198

    
199
            LoopNb = LoopNb + 1;
200
        } while (LoopNb < VL53L0X_DEFAULT_MAX_LOOP);
201

    
202
        if (LoopNb >= VL53L0X_DEFAULT_MAX_LOOP)
203
            Status = VL53L0X_ERROR_TIME_OUT;
204

    
205
    }
206

    
207
    Status |= VL53L0X_WrByte(Dev, 0x83, 0x01);
208

    
209
    LOG_FUNCTION_END(Status);
210
    return Status;
211

    
212
}
213

    
214
VL53L0X_Error VL53L0X_get_info_from_device(VL53L0X_DEV Dev, uint8_t option)
215
{
216

    
217
    VL53L0X_Error Status = VL53L0X_ERROR_NONE;
218
    uint8_t byte;
219
    uint32_t TmpDWord;
220
    uint8_t ModuleId;
221
    uint8_t Revision;
222
    uint8_t ReferenceSpadCount = 0;
223
    uint8_t ReferenceSpadType = 0;
224
    uint32_t PartUIDUpper = 0;
225
    uint32_t PartUIDLower = 0;
226
    uint32_t OffsetFixed1104_mm = 0;
227
    int16_t OffsetMicroMeters = 0;
228
    uint32_t DistMeasTgtFixed1104_mm = 400 << 4;
229
    uint32_t DistMeasFixed1104_400_mm = 0;
230
    uint32_t SignalRateMeasFixed1104_400_mm = 0;
231
    char ProductId[19];
232
    char *ProductId_tmp;
233
    uint8_t ReadDataFromDeviceDone;
234
    FixPoint1616_t SignalRateMeasFixed400mmFix = 0;
235
    uint8_t NvmRefGoodSpadMap[VL53L0X_REF_SPAD_BUFFER_SIZE];
236
    int i;
237

    
238

    
239
    LOG_FUNCTION_START("");
240

    
241
    ReadDataFromDeviceDone = VL53L0X_GETDEVICESPECIFICPARAMETER(Dev,
242
            ReadDataFromDeviceDone);
243

    
244
    /* This access is done only once after that a GetDeviceInfo or
245
     * datainit is done*/
246
    if (ReadDataFromDeviceDone != 7) {
247

    
248
        Status |= VL53L0X_WrByte(Dev, 0x80, 0x01);
249
        Status |= VL53L0X_WrByte(Dev, 0xFF, 0x01);
250
        Status |= VL53L0X_WrByte(Dev, 0x00, 0x00);
251

    
252
        Status |= VL53L0X_WrByte(Dev, 0xFF, 0x06);
253
        Status |= VL53L0X_RdByte(Dev, 0x83, &byte);
254
        Status |= VL53L0X_WrByte(Dev, 0x83, byte|4);
255
        Status |= VL53L0X_WrByte(Dev, 0xFF, 0x07);
256
        Status |= VL53L0X_WrByte(Dev, 0x81, 0x01);
257

    
258
        //Status |= VL53L0X_PollingDelay(Dev); TODO NEED THIS ??
259

    
260
        Status |= VL53L0X_WrByte(Dev, 0x80, 0x01);
261

    
262
        if (((option & 1) == 1) &&
263
            ((ReadDataFromDeviceDone & 1) == 0)) {
264
            Status |= VL53L0X_WrByte(Dev, 0x94, 0x6b);
265
            Status |= VL53L0X_device_read_strobe(Dev);
266
            Status |= VL53L0X_RdDWord(Dev, 0x90, &TmpDWord);
267

    
268
            ReferenceSpadCount = (uint8_t)((TmpDWord >> 8) & 0x07f);
269
            ReferenceSpadType  = (uint8_t)((TmpDWord >> 15) & 0x01);
270

    
271
            Status |= VL53L0X_WrByte(Dev, 0x94, 0x24);
272
            Status |= VL53L0X_device_read_strobe(Dev);
273
            Status |= VL53L0X_RdDWord(Dev, 0x90, &TmpDWord);
274

    
275

    
276
            NvmRefGoodSpadMap[0] = (uint8_t)((TmpDWord >> 24)
277
                & 0xff);
278
            NvmRefGoodSpadMap[1] = (uint8_t)((TmpDWord >> 16)
279
                & 0xff);
280
            NvmRefGoodSpadMap[2] = (uint8_t)((TmpDWord >> 8)
281
                & 0xff);
282
            NvmRefGoodSpadMap[3] = (uint8_t)(TmpDWord & 0xff);
283

    
284
            Status |= VL53L0X_WrByte(Dev, 0x94, 0x25);
285
            Status |= VL53L0X_device_read_strobe(Dev);
286
            Status |= VL53L0X_RdDWord(Dev, 0x90, &TmpDWord);
287

    
288
            NvmRefGoodSpadMap[4] = (uint8_t)((TmpDWord >> 24)
289
                & 0xff);
290
            NvmRefGoodSpadMap[5] = (uint8_t)((TmpDWord >> 16)
291
                & 0xff);
292
        }
293

    
294
        if (((option & 2) == 2) &&
295
            ((ReadDataFromDeviceDone & 2) == 0)) {
296

    
297
            Status |= VL53L0X_WrByte(Dev, 0x94, 0x02);
298
            Status |= VL53L0X_device_read_strobe(Dev);
299
            Status |= VL53L0X_RdByte(Dev, 0x90, &ModuleId);
300

    
301
            Status |= VL53L0X_WrByte(Dev, 0x94, 0x7B);
302
            Status |= VL53L0X_device_read_strobe(Dev);
303
            Status |= VL53L0X_RdByte(Dev, 0x90, &Revision);
304

    
305
            Status |= VL53L0X_WrByte(Dev, 0x94, 0x77);
306
            Status |= VL53L0X_device_read_strobe(Dev);
307
            Status |= VL53L0X_RdDWord(Dev, 0x90, &TmpDWord);
308

    
309
            ProductId[0] = (char)((TmpDWord >> 25) & 0x07f);
310
            ProductId[1] = (char)((TmpDWord >> 18) & 0x07f);
311
            ProductId[2] = (char)((TmpDWord >> 11) & 0x07f);
312
            ProductId[3] = (char)((TmpDWord >> 4) & 0x07f);
313

    
314
            byte = (uint8_t)((TmpDWord & 0x00f) << 3);
315

    
316
            Status |= VL53L0X_WrByte(Dev, 0x94, 0x78);
317
            Status |= VL53L0X_device_read_strobe(Dev);
318
            Status |= VL53L0X_RdDWord(Dev, 0x90, &TmpDWord);
319

    
320
            ProductId[4] = (char)(byte +
321
                    ((TmpDWord >> 29) & 0x07f));
322
            ProductId[5] = (char)((TmpDWord >> 22) & 0x07f);
323
            ProductId[6] = (char)((TmpDWord >> 15) & 0x07f);
324
            ProductId[7] = (char)((TmpDWord >> 8) & 0x07f);
325
            ProductId[8] = (char)((TmpDWord >> 1) & 0x07f);
326

    
327
            byte = (uint8_t)((TmpDWord & 0x001) << 6);
328

    
329
            Status |= VL53L0X_WrByte(Dev, 0x94, 0x79);
330

    
331
            Status |= VL53L0X_device_read_strobe(Dev);
332

    
333
            Status |= VL53L0X_RdDWord(Dev, 0x90, &TmpDWord);
334

    
335
            ProductId[9] = (char)(byte +
336
                    ((TmpDWord >> 26) & 0x07f));
337
            ProductId[10] = (char)((TmpDWord >> 19) & 0x07f);
338
            ProductId[11] = (char)((TmpDWord >> 12) & 0x07f);
339
            ProductId[12] = (char)((TmpDWord >> 5) & 0x07f);
340

    
341
            byte = (uint8_t)((TmpDWord & 0x01f) << 2);
342

    
343
            Status |= VL53L0X_WrByte(Dev, 0x94, 0x7A);
344

    
345
            Status |= VL53L0X_device_read_strobe(Dev);
346

    
347
            Status |= VL53L0X_RdDWord(Dev, 0x90, &TmpDWord);
348

    
349
            ProductId[13] = (char)(byte +
350
                    ((TmpDWord >> 30) & 0x07f));
351
            ProductId[14] = (char)((TmpDWord >> 23) & 0x07f);
352
            ProductId[15] = (char)((TmpDWord >> 16) & 0x07f);
353
            ProductId[16] = (char)((TmpDWord >> 9) & 0x07f);
354
            ProductId[17] = (char)((TmpDWord >> 2) & 0x07f);
355
            ProductId[18] = '\0';
356

    
357
        }
358

    
359
        if (((option & 4) == 4) &&
360
            ((ReadDataFromDeviceDone & 4) == 0)) {
361

    
362
            Status |= VL53L0X_WrByte(Dev, 0x94, 0x7B);
363
            Status |= VL53L0X_device_read_strobe(Dev);
364
            Status |= VL53L0X_RdDWord(Dev, 0x90, &PartUIDUpper);
365

    
366
            Status |= VL53L0X_WrByte(Dev, 0x94, 0x7C);
367
            Status |= VL53L0X_device_read_strobe(Dev);
368
            Status |= VL53L0X_RdDWord(Dev, 0x90, &PartUIDLower);
369

    
370
            Status |= VL53L0X_WrByte(Dev, 0x94, 0x73);
371
            Status |= VL53L0X_device_read_strobe(Dev);
372
            Status |= VL53L0X_RdDWord(Dev, 0x90, &TmpDWord);
373

    
374
            SignalRateMeasFixed1104_400_mm = (TmpDWord &
375
                0x0000000ff) << 8;
376

    
377
            Status |= VL53L0X_WrByte(Dev, 0x94, 0x74);
378
            Status |= VL53L0X_device_read_strobe(Dev);
379
            Status |= VL53L0X_RdDWord(Dev, 0x90, &TmpDWord);
380

    
381
            SignalRateMeasFixed1104_400_mm |= ((TmpDWord &
382
                0xff000000) >> 24);
383

    
384
            Status |= VL53L0X_WrByte(Dev, 0x94, 0x75);
385
            Status |= VL53L0X_device_read_strobe(Dev);
386
            Status |= VL53L0X_RdDWord(Dev, 0x90, &TmpDWord);
387

    
388
            DistMeasFixed1104_400_mm = (TmpDWord & 0x0000000ff)
389
                            << 8;
390

    
391
            Status |= VL53L0X_WrByte(Dev, 0x94, 0x76);
392
            Status |= VL53L0X_device_read_strobe(Dev);
393
            Status |= VL53L0X_RdDWord(Dev, 0x90, &TmpDWord);
394

    
395
            DistMeasFixed1104_400_mm |= ((TmpDWord & 0xff000000)
396
                            >> 24);
397
        }
398

    
399
        Status |= VL53L0X_WrByte(Dev, 0x81, 0x00);
400
        Status |= VL53L0X_WrByte(Dev, 0xFF, 0x06);
401
        Status |= VL53L0X_RdByte(Dev, 0x83, &byte);
402
        Status |= VL53L0X_WrByte(Dev, 0x83, byte&0xfb);
403
        Status |= VL53L0X_WrByte(Dev, 0xFF, 0x01);
404
        Status |= VL53L0X_WrByte(Dev, 0x00, 0x01);
405

    
406
        Status |= VL53L0X_WrByte(Dev, 0xFF, 0x00);
407
        Status |= VL53L0X_WrByte(Dev, 0x80, 0x00);
408
    }
409

    
410
    if ((Status == VL53L0X_ERROR_NONE) &&
411
        (ReadDataFromDeviceDone != 7)) {
412
        /* Assign to variable if status is ok */
413
        if (((option & 1) == 1) &&
414
            ((ReadDataFromDeviceDone & 1) == 0)) {
415
            VL53L0X_SETDEVICESPECIFICPARAMETER(Dev,
416
                ReferenceSpadCount, ReferenceSpadCount);
417

    
418
            VL53L0X_SETDEVICESPECIFICPARAMETER(Dev,
419
                ReferenceSpadType, ReferenceSpadType);
420

    
421
            for (i = 0; i < VL53L0X_REF_SPAD_BUFFER_SIZE; i++) {
422
                Dev->Data.SpadData.RefGoodSpadMap[i] =
423
                    NvmRefGoodSpadMap[i];
424
            }
425
        }
426

    
427
        if (((option & 2) == 2) &&
428
            ((ReadDataFromDeviceDone & 2) == 0)) {
429
            VL53L0X_SETDEVICESPECIFICPARAMETER(Dev,
430
                    ModuleId, ModuleId);
431

    
432
            VL53L0X_SETDEVICESPECIFICPARAMETER(Dev,
433
                    Revision, Revision);
434

    
435
            ProductId_tmp = VL53L0X_GETDEVICESPECIFICPARAMETER(Dev,
436
                    ProductId);
437
            VL53L0X_COPYSTRING(ProductId_tmp, ProductId);
438

    
439
        }
440

    
441
        if (((option & 4) == 4) &&
442
            ((ReadDataFromDeviceDone & 4) == 0)) {
443
            VL53L0X_SETDEVICESPECIFICPARAMETER(Dev,
444
                        PartUIDUpper, PartUIDUpper);
445

    
446
            VL53L0X_SETDEVICESPECIFICPARAMETER(Dev,
447
                        PartUIDLower, PartUIDLower);
448

    
449
            SignalRateMeasFixed400mmFix =
450
                VL53L0X_FIXPOINT97TOFIXPOINT1616(
451
                    SignalRateMeasFixed1104_400_mm);
452

    
453
            VL53L0X_SETDEVICESPECIFICPARAMETER(Dev,
454
                SignalRateMeasFixed400mm,
455
                SignalRateMeasFixed400mmFix);
456

    
457
            OffsetMicroMeters = 0;
458
            if (DistMeasFixed1104_400_mm != 0) {
459
                    OffsetFixed1104_mm =
460
                        DistMeasFixed1104_400_mm -
461
                        DistMeasTgtFixed1104_mm;
462
                    OffsetMicroMeters = (OffsetFixed1104_mm
463
                        * 1000) >> 4;
464
                    OffsetMicroMeters *= -1;
465
            }
466

    
467
            PALDevDataSet(Dev,
468
                Part2PartOffsetAdjustmentNVMMicroMeter,
469
                OffsetMicroMeters);
470
        }
471
        byte = (uint8_t)(ReadDataFromDeviceDone|option);
472
        VL53L0X_SETDEVICESPECIFICPARAMETER(Dev, ReadDataFromDeviceDone,
473
                byte);
474
    }
475

    
476
    LOG_FUNCTION_END(Status);
477
    return Status;
478
}
479

    
480

    
481
uint32_t VL53L0X_calc_macro_period_ps(VL53L0X_DEV Dev, uint8_t vcsel_period_pclks)
482
{
483
    uint64_t PLL_period_ps;
484
    uint32_t macro_period_vclks;
485
    uint32_t macro_period_ps;
486

    
487
    LOG_FUNCTION_START("");
488

    
489
    /* The above calculation will produce rounding errors,
490
       therefore set fixed value
491
    */
492
    PLL_period_ps = 1655;
493

    
494
    macro_period_vclks = 2304;
495
    macro_period_ps = (uint32_t)(macro_period_vclks
496
            * vcsel_period_pclks * PLL_period_ps);
497

    
498
    LOG_FUNCTION_END("");
499
    return macro_period_ps;
500
}
501

    
502
uint16_t VL53L0X_encode_timeout(uint32_t timeout_macro_clks)
503
{
504
    /*!
505
     * Encode timeout in macro periods in (LSByte * 2^MSByte) + 1 format
506
     */
507

    
508
    uint16_t encoded_timeout = 0;
509
    uint32_t ls_byte = 0;
510
    uint16_t ms_byte = 0;
511

    
512
    if (timeout_macro_clks > 0) {
513
        ls_byte = timeout_macro_clks - 1;
514

    
515
        while ((ls_byte & 0xFFFFFF00) > 0) {
516
            ls_byte = ls_byte >> 1;
517
            ms_byte++;
518
        }
519

    
520
        encoded_timeout = (ms_byte << 8)
521
                + (uint16_t) (ls_byte & 0x000000FF);
522
    }
523

    
524
    return encoded_timeout;
525

    
526
}
527

    
528
uint32_t VL53L0X_decode_timeout(uint16_t encoded_timeout)
529
{
530
    /*!
531
     * Decode 16-bit timeout register value - format (LSByte * 2^MSByte) + 1
532
     */
533

    
534
    uint32_t timeout_macro_clks = 0;
535

    
536
    timeout_macro_clks = ((uint32_t) (encoded_timeout & 0x00FF)
537
            << (uint32_t) ((encoded_timeout & 0xFF00) >> 8)) + 1;
538

    
539
    return timeout_macro_clks;
540
}
541

    
542

    
543
/* To convert ms into register value */
544
uint32_t VL53L0X_calc_timeout_mclks(VL53L0X_DEV Dev,
545
        uint32_t timeout_period_us,
546
        uint8_t vcsel_period_pclks)
547
{
548
    uint32_t macro_period_ps;
549
    uint32_t macro_period_ns;
550
    uint32_t timeout_period_mclks = 0;
551

    
552
    macro_period_ps = VL53L0X_calc_macro_period_ps(Dev, vcsel_period_pclks);
553
    macro_period_ns = (macro_period_ps + 500) / 1000;
554

    
555
    timeout_period_mclks =
556
        (uint32_t) (((timeout_period_us * 1000)
557
        + (macro_period_ns / 2)) / macro_period_ns);
558

    
559
    return timeout_period_mclks;
560
}
561

    
562
/* To convert register value into us */
563
uint32_t VL53L0X_calc_timeout_us(VL53L0X_DEV Dev,
564
        uint16_t timeout_period_mclks,
565
        uint8_t vcsel_period_pclks)
566
{
567
    uint32_t macro_period_ps;
568
    uint32_t macro_period_ns;
569
    uint32_t actual_timeout_period_us = 0;
570

    
571
    macro_period_ps = VL53L0X_calc_macro_period_ps(Dev, vcsel_period_pclks);
572
    macro_period_ns = (macro_period_ps + 500) / 1000;
573

    
574
    actual_timeout_period_us =
575
        ((timeout_period_mclks * macro_period_ns) + 500) / 1000;
576

    
577
    return actual_timeout_period_us;
578
}
579

    
580

    
581
VL53L0X_Error get_sequence_step_timeout(VL53L0X_DEV Dev,
582
                VL53L0X_SequenceStepId SequenceStepId,
583
                uint32_t *pTimeOutMicroSecs)
584
{
585
    VL53L0X_Error Status = VL53L0X_ERROR_NONE;
586
    uint8_t CurrentVCSELPulsePeriodPClk;
587
    uint8_t EncodedTimeOutByte = 0;
588
    uint32_t TimeoutMicroSeconds = 0;
589
    uint16_t PreRangeEncodedTimeOut = 0;
590
    uint16_t MsrcTimeOutMClks;
591
    uint16_t PreRangeTimeOutMClks;
592
    uint16_t FinalRangeTimeOutMClks = 0;
593
    uint16_t FinalRangeEncodedTimeOut;
594
    VL53L0X_SchedulerSequenceSteps_t SchedulerSequenceSteps;
595

    
596
    if ((SequenceStepId == VL53L0X_SEQUENCESTEP_TCC)         ||
597
        (SequenceStepId == VL53L0X_SEQUENCESTEP_DSS)         ||
598
        (SequenceStepId == VL53L0X_SEQUENCESTEP_MSRC)) {
599

    
600
        Status = VL53L0X_GetVcselPulsePeriod(Dev,
601
                    VL53L0X_VCSEL_PERIOD_PRE_RANGE,
602
                    &CurrentVCSELPulsePeriodPClk);
603
        if (Status == VL53L0X_ERROR_NONE) {
604
            Status = VL53L0X_RdByte(Dev,
605
                    VL53L0X_REG_MSRC_CONFIG_TIMEOUT_MACROP,
606
                    &EncodedTimeOutByte);
607
        }
608
        MsrcTimeOutMClks = VL53L0X_decode_timeout(EncodedTimeOutByte);
609

    
610
        TimeoutMicroSeconds = VL53L0X_calc_timeout_us(Dev,
611
                        MsrcTimeOutMClks,
612
                        CurrentVCSELPulsePeriodPClk);
613
    } else if (SequenceStepId == VL53L0X_SEQUENCESTEP_PRE_RANGE) {
614
        /* Retrieve PRE-RANGE VCSEL Period */
615
        Status = VL53L0X_GetVcselPulsePeriod(Dev,
616
                        VL53L0X_VCSEL_PERIOD_PRE_RANGE,
617
                        &CurrentVCSELPulsePeriodPClk);
618

    
619
        /* Retrieve PRE-RANGE Timeout in Macro periods (MCLKS) */
620
        if (Status == VL53L0X_ERROR_NONE) {
621

    
622
            /* Retrieve PRE-RANGE VCSEL Period */
623
            Status = VL53L0X_GetVcselPulsePeriod(Dev,
624
                    VL53L0X_VCSEL_PERIOD_PRE_RANGE,
625
                    &CurrentVCSELPulsePeriodPClk);
626

    
627
            if (Status == VL53L0X_ERROR_NONE) {
628
                Status = VL53L0X_RdWord(Dev,
629
                VL53L0X_REG_PRE_RANGE_CONFIG_TIMEOUT_MACROP_HI,
630
                &PreRangeEncodedTimeOut);
631
            }
632

    
633
            PreRangeTimeOutMClks = VL53L0X_decode_timeout(
634
                    PreRangeEncodedTimeOut);
635

    
636
            TimeoutMicroSeconds = VL53L0X_calc_timeout_us(Dev,
637
                    PreRangeTimeOutMClks,
638
                    CurrentVCSELPulsePeriodPClk);
639
        }
640
    } else if (SequenceStepId == VL53L0X_SEQUENCESTEP_FINAL_RANGE) {
641

    
642
        VL53L0X_GetSequenceStepEnables(Dev, &SchedulerSequenceSteps);
643
        PreRangeTimeOutMClks = 0;
644

    
645
        if (SchedulerSequenceSteps.PreRangeOn) {
646
            /* Retrieve PRE-RANGE VCSEL Period */
647
            Status = VL53L0X_GetVcselPulsePeriod(Dev,
648
                VL53L0X_VCSEL_PERIOD_PRE_RANGE,
649
                &CurrentVCSELPulsePeriodPClk);
650

    
651
            /* Retrieve PRE-RANGE Timeout in Macro periods
652
             * (MCLKS) */
653
            if (Status == VL53L0X_ERROR_NONE) {
654
                Status = VL53L0X_RdWord(Dev,
655
                VL53L0X_REG_PRE_RANGE_CONFIG_TIMEOUT_MACROP_HI,
656
                &PreRangeEncodedTimeOut);
657
                PreRangeTimeOutMClks = VL53L0X_decode_timeout(
658
                        PreRangeEncodedTimeOut);
659
            }
660
        }
661

    
662
        if (Status == VL53L0X_ERROR_NONE) {
663
            /* Retrieve FINAL-RANGE VCSEL Period */
664
            Status = VL53L0X_GetVcselPulsePeriod(Dev,
665
                    VL53L0X_VCSEL_PERIOD_FINAL_RANGE,
666
                    &CurrentVCSELPulsePeriodPClk);
667
        }
668

    
669
        /* Retrieve FINAL-RANGE Timeout in Macro periods (MCLKS) */
670
        if (Status == VL53L0X_ERROR_NONE) {
671
            Status = VL53L0X_RdWord(Dev,
672
                VL53L0X_REG_FINAL_RANGE_CONFIG_TIMEOUT_MACROP_HI,
673
                &FinalRangeEncodedTimeOut);
674
            FinalRangeTimeOutMClks = VL53L0X_decode_timeout(
675
                    FinalRangeEncodedTimeOut);
676
        }
677

    
678
        FinalRangeTimeOutMClks -= PreRangeTimeOutMClks;
679
        TimeoutMicroSeconds = VL53L0X_calc_timeout_us(Dev,
680
                        FinalRangeTimeOutMClks,
681
                        CurrentVCSELPulsePeriodPClk);
682
    }
683

    
684
    *pTimeOutMicroSecs = TimeoutMicroSeconds;
685

    
686
    return Status;
687
}
688

    
689

    
690
VL53L0X_Error set_sequence_step_timeout(VL53L0X_DEV Dev,
691
                    VL53L0X_SequenceStepId SequenceStepId,
692
                    uint32_t TimeOutMicroSecs)
693
{
694
    VL53L0X_Error Status = VL53L0X_ERROR_NONE;
695
    uint8_t CurrentVCSELPulsePeriodPClk;
696
    uint8_t MsrcEncodedTimeOut;
697
    uint16_t PreRangeEncodedTimeOut;
698
    uint16_t PreRangeTimeOutMClks;
699
    uint16_t MsrcRangeTimeOutMClks;
700
    uint32_t FinalRangeTimeOutMClks;
701
    uint16_t FinalRangeEncodedTimeOut;
702
    VL53L0X_SchedulerSequenceSteps_t SchedulerSequenceSteps;
703

    
704
    if ((SequenceStepId == VL53L0X_SEQUENCESTEP_TCC)         ||
705
        (SequenceStepId == VL53L0X_SEQUENCESTEP_DSS)         ||
706
        (SequenceStepId == VL53L0X_SEQUENCESTEP_MSRC)) {
707

    
708
        Status = VL53L0X_GetVcselPulsePeriod(Dev,
709
                    VL53L0X_VCSEL_PERIOD_PRE_RANGE,
710
                    &CurrentVCSELPulsePeriodPClk);
711

    
712
        if (Status == VL53L0X_ERROR_NONE) {
713
            MsrcRangeTimeOutMClks = VL53L0X_calc_timeout_mclks(Dev,
714
                    TimeOutMicroSecs,
715
                    (uint8_t)CurrentVCSELPulsePeriodPClk);
716

    
717
            if (MsrcRangeTimeOutMClks > 256)
718
                MsrcEncodedTimeOut = 255;
719
            else
720
                MsrcEncodedTimeOut =
721
                    (uint8_t)MsrcRangeTimeOutMClks - 1;
722

    
723
            VL53L0X_SETDEVICESPECIFICPARAMETER(Dev,
724
                LastEncodedTimeout,
725
                MsrcEncodedTimeOut);
726
        }
727

    
728
        if (Status == VL53L0X_ERROR_NONE) {
729
            Status = VL53L0X_WrByte(Dev,
730
                VL53L0X_REG_MSRC_CONFIG_TIMEOUT_MACROP,
731
                MsrcEncodedTimeOut);
732
        }
733
    } else {
734

    
735
        if (SequenceStepId == VL53L0X_SEQUENCESTEP_PRE_RANGE) {
736

    
737
            if (Status == VL53L0X_ERROR_NONE) {
738
                Status = VL53L0X_GetVcselPulsePeriod(Dev,
739
                        VL53L0X_VCSEL_PERIOD_PRE_RANGE,
740
                        &CurrentVCSELPulsePeriodPClk);
741
                PreRangeTimeOutMClks =
742
                    VL53L0X_calc_timeout_mclks(Dev,
743
                    TimeOutMicroSecs,
744
                    (uint8_t)CurrentVCSELPulsePeriodPClk);
745
                PreRangeEncodedTimeOut = VL53L0X_encode_timeout(
746
                    PreRangeTimeOutMClks);
747

    
748
                VL53L0X_SETDEVICESPECIFICPARAMETER(Dev,
749
                    LastEncodedTimeout,
750
                    PreRangeEncodedTimeOut);
751
            }
752

    
753
            if (Status == VL53L0X_ERROR_NONE) {
754
                Status = VL53L0X_WrWord(Dev,
755
                VL53L0X_REG_PRE_RANGE_CONFIG_TIMEOUT_MACROP_HI,
756
                PreRangeEncodedTimeOut);
757
            }
758

    
759
            if (Status == VL53L0X_ERROR_NONE) {
760
                VL53L0X_SETDEVICESPECIFICPARAMETER(
761
                    Dev,
762
                    PreRangeTimeoutMicroSecs,
763
                    TimeOutMicroSecs);
764
            }
765
        } else if (SequenceStepId == VL53L0X_SEQUENCESTEP_FINAL_RANGE) {
766

    
767
            /* For the final range timeout, the pre-range timeout
768
             * must be added. To do this both final and pre-range
769
             * timeouts must be expressed in macro periods MClks
770
             * because they have different vcsel periods.
771
             */
772

    
773
            VL53L0X_GetSequenceStepEnables(Dev,
774
                    &SchedulerSequenceSteps);
775
            PreRangeTimeOutMClks = 0;
776
            if (SchedulerSequenceSteps.PreRangeOn) {
777

    
778
                /* Retrieve PRE-RANGE VCSEL Period */
779
                Status = VL53L0X_GetVcselPulsePeriod(Dev,
780
                    VL53L0X_VCSEL_PERIOD_PRE_RANGE,
781
                    &CurrentVCSELPulsePeriodPClk);
782

    
783
                /* Retrieve PRE-RANGE Timeout in Macro periods
784
                 * (MCLKS) */
785
                if (Status == VL53L0X_ERROR_NONE) {
786
                    Status = VL53L0X_RdWord(Dev, 0x51,
787
                        &PreRangeEncodedTimeOut);
788
                    PreRangeTimeOutMClks =
789
                        VL53L0X_decode_timeout(
790
                            PreRangeEncodedTimeOut);
791
                }
792
            }
793

    
794
            /* Calculate FINAL RANGE Timeout in Macro Periods
795
             * (MCLKS) and add PRE-RANGE value
796
             */
797
            if (Status == VL53L0X_ERROR_NONE) {
798

    
799
                Status = VL53L0X_GetVcselPulsePeriod(Dev,
800
                        VL53L0X_VCSEL_PERIOD_FINAL_RANGE,
801
                        &CurrentVCSELPulsePeriodPClk);
802
            }
803
            if (Status == VL53L0X_ERROR_NONE) {
804

    
805
                FinalRangeTimeOutMClks =
806
                    VL53L0X_calc_timeout_mclks(Dev,
807
                    TimeOutMicroSecs,
808
                    (uint8_t) CurrentVCSELPulsePeriodPClk);
809

    
810
                FinalRangeTimeOutMClks += PreRangeTimeOutMClks;
811

    
812
                FinalRangeEncodedTimeOut =
813
                VL53L0X_encode_timeout(FinalRangeTimeOutMClks);
814

    
815
                if (Status == VL53L0X_ERROR_NONE) {
816
                    Status = VL53L0X_WrWord(Dev, 0x71,
817
                    FinalRangeEncodedTimeOut);
818
                }
819

    
820
                if (Status == VL53L0X_ERROR_NONE) {
821
                    VL53L0X_SETDEVICESPECIFICPARAMETER(
822
                        Dev,
823
                        FinalRangeTimeoutMicroSecs,
824
                        TimeOutMicroSecs);
825
                }
826
            }
827
        } else
828
            Status = VL53L0X_ERROR_INVALID_PARAMS;
829

    
830
    }
831
    return Status;
832
}
833

    
834
VL53L0X_Error VL53L0X_set_vcsel_pulse_period(VL53L0X_DEV Dev,
835
    VL53L0X_VcselPeriod VcselPeriodType, uint8_t VCSELPulsePeriodPCLK)
836
{
837
    VL53L0X_Error Status = VL53L0X_ERROR_NONE;
838
    uint8_t vcsel_period_reg;
839
    uint8_t MinPreVcselPeriodPCLK = 12;
840
    uint8_t MaxPreVcselPeriodPCLK = 18;
841
    uint8_t MinFinalVcselPeriodPCLK = 8;
842
    uint8_t MaxFinalVcselPeriodPCLK = 14;
843
    uint32_t MeasurementTimingBudgetMicroSeconds;
844
    uint32_t FinalRangeTimeoutMicroSeconds;
845
    uint32_t PreRangeTimeoutMicroSeconds;
846
    uint32_t MsrcTimeoutMicroSeconds;
847
    uint8_t PhaseCalInt = 0;
848

    
849
    /* Check if valid clock period requested */
850

    
851
    if ((VCSELPulsePeriodPCLK % 2) != 0) {
852
        /* Value must be an even number */
853
        Status = VL53L0X_ERROR_INVALID_PARAMS;
854
    } else if (VcselPeriodType == VL53L0X_VCSEL_PERIOD_PRE_RANGE &&
855
        (VCSELPulsePeriodPCLK < MinPreVcselPeriodPCLK ||
856
        VCSELPulsePeriodPCLK > MaxPreVcselPeriodPCLK)) {
857
        Status = VL53L0X_ERROR_INVALID_PARAMS;
858
    } else if (VcselPeriodType == VL53L0X_VCSEL_PERIOD_FINAL_RANGE &&
859
        (VCSELPulsePeriodPCLK < MinFinalVcselPeriodPCLK ||
860
         VCSELPulsePeriodPCLK > MaxFinalVcselPeriodPCLK)) {
861

    
862
        Status = VL53L0X_ERROR_INVALID_PARAMS;
863
    }
864

    
865
    /* Apply specific settings for the requested clock period */
866

    
867
    if (Status != VL53L0X_ERROR_NONE)
868
        return Status;
869

    
870

    
871
    if (VcselPeriodType == VL53L0X_VCSEL_PERIOD_PRE_RANGE) {
872

    
873
        /* Set phase check limits */
874
        if (VCSELPulsePeriodPCLK == 12) {
875

    
876
            Status = VL53L0X_WrByte(Dev,
877
                VL53L0X_REG_PRE_RANGE_CONFIG_VALID_PHASE_HIGH,
878
                0x18);
879
            Status = VL53L0X_WrByte(Dev,
880
                VL53L0X_REG_PRE_RANGE_CONFIG_VALID_PHASE_LOW,
881
                0x08);
882
        } else if (VCSELPulsePeriodPCLK == 14) {
883

    
884
            Status = VL53L0X_WrByte(Dev,
885
                VL53L0X_REG_PRE_RANGE_CONFIG_VALID_PHASE_HIGH,
886
                0x30);
887
            Status = VL53L0X_WrByte(Dev,
888
                VL53L0X_REG_PRE_RANGE_CONFIG_VALID_PHASE_LOW,
889
                0x08);
890
        } else if (VCSELPulsePeriodPCLK == 16) {
891

    
892
            Status = VL53L0X_WrByte(Dev,
893
                VL53L0X_REG_PRE_RANGE_CONFIG_VALID_PHASE_HIGH,
894
                0x40);
895
            Status = VL53L0X_WrByte(Dev,
896
                VL53L0X_REG_PRE_RANGE_CONFIG_VALID_PHASE_LOW,
897
                0x08);
898
        } else if (VCSELPulsePeriodPCLK == 18) {
899

    
900
            Status = VL53L0X_WrByte(Dev,
901
                VL53L0X_REG_PRE_RANGE_CONFIG_VALID_PHASE_HIGH,
902
                0x50);
903
            Status = VL53L0X_WrByte(Dev,
904
                VL53L0X_REG_PRE_RANGE_CONFIG_VALID_PHASE_LOW,
905
                0x08);
906
        }
907
    } else if (VcselPeriodType == VL53L0X_VCSEL_PERIOD_FINAL_RANGE) {
908

    
909
        if (VCSELPulsePeriodPCLK == 8) {
910

    
911
            Status = VL53L0X_WrByte(Dev,
912
                VL53L0X_REG_FINAL_RANGE_CONFIG_VALID_PHASE_HIGH,
913
                0x10);
914
            Status = VL53L0X_WrByte(Dev,
915
                VL53L0X_REG_FINAL_RANGE_CONFIG_VALID_PHASE_LOW,
916
                0x08);
917

    
918
            Status |= VL53L0X_WrByte(Dev,
919
                VL53L0X_REG_GLOBAL_CONFIG_VCSEL_WIDTH, 0x02);
920
            Status |= VL53L0X_WrByte(Dev,
921
                VL53L0X_REG_ALGO_PHASECAL_CONFIG_TIMEOUT, 0x0C);
922

    
923
            Status |= VL53L0X_WrByte(Dev, 0xff, 0x01);
924
            Status |= VL53L0X_WrByte(Dev,
925
                VL53L0X_REG_ALGO_PHASECAL_LIM,
926
                0x30);
927
            Status |= VL53L0X_WrByte(Dev, 0xff, 0x00);
928
        } else if (VCSELPulsePeriodPCLK == 10) {
929

    
930
            Status = VL53L0X_WrByte(Dev,
931
                VL53L0X_REG_FINAL_RANGE_CONFIG_VALID_PHASE_HIGH,
932
                0x28);
933
            Status = VL53L0X_WrByte(Dev,
934
                VL53L0X_REG_FINAL_RANGE_CONFIG_VALID_PHASE_LOW,
935
                0x08);
936

    
937
            Status |= VL53L0X_WrByte(Dev,
938
                VL53L0X_REG_GLOBAL_CONFIG_VCSEL_WIDTH, 0x03);
939
            Status |= VL53L0X_WrByte(Dev,
940
                VL53L0X_REG_ALGO_PHASECAL_CONFIG_TIMEOUT, 0x09);
941

    
942
            Status |= VL53L0X_WrByte(Dev, 0xff, 0x01);
943
            Status |= VL53L0X_WrByte(Dev,
944
                VL53L0X_REG_ALGO_PHASECAL_LIM,
945
                0x20);
946
            Status |= VL53L0X_WrByte(Dev, 0xff, 0x00);
947
        } else if (VCSELPulsePeriodPCLK == 12) {
948

    
949
            Status = VL53L0X_WrByte(Dev,
950
                VL53L0X_REG_FINAL_RANGE_CONFIG_VALID_PHASE_HIGH,
951
                0x38);
952
            Status = VL53L0X_WrByte(Dev,
953
                VL53L0X_REG_FINAL_RANGE_CONFIG_VALID_PHASE_LOW,
954
                0x08);
955

    
956
            Status |= VL53L0X_WrByte(Dev,
957
                VL53L0X_REG_GLOBAL_CONFIG_VCSEL_WIDTH, 0x03);
958
            Status |= VL53L0X_WrByte(Dev,
959
                VL53L0X_REG_ALGO_PHASECAL_CONFIG_TIMEOUT, 0x08);
960

    
961
            Status |= VL53L0X_WrByte(Dev, 0xff, 0x01);
962
            Status |= VL53L0X_WrByte(Dev,
963
                VL53L0X_REG_ALGO_PHASECAL_LIM,
964
                0x20);
965
            Status |= VL53L0X_WrByte(Dev, 0xff, 0x00);
966
        } else if (VCSELPulsePeriodPCLK == 14) {
967

    
968
            Status = VL53L0X_WrByte(Dev,
969
                VL53L0X_REG_FINAL_RANGE_CONFIG_VALID_PHASE_HIGH,
970
                0x048);
971
            Status = VL53L0X_WrByte(Dev,
972
                VL53L0X_REG_FINAL_RANGE_CONFIG_VALID_PHASE_LOW,
973
                0x08);
974

    
975
            Status |= VL53L0X_WrByte(Dev,
976
                VL53L0X_REG_GLOBAL_CONFIG_VCSEL_WIDTH, 0x03);
977
            Status |= VL53L0X_WrByte(Dev,
978
                VL53L0X_REG_ALGO_PHASECAL_CONFIG_TIMEOUT, 0x07);
979

    
980
            Status |= VL53L0X_WrByte(Dev, 0xff, 0x01);
981
            Status |= VL53L0X_WrByte(Dev,
982
                VL53L0X_REG_ALGO_PHASECAL_LIM,
983
                0x20);
984
            Status |= VL53L0X_WrByte(Dev, 0xff, 0x00);
985
        }
986
    }
987

    
988

    
989
    /* Re-calculate and apply timeouts, in macro periods */
990

    
991
    if (Status == VL53L0X_ERROR_NONE) {
992
        vcsel_period_reg = VL53L0X_encode_vcsel_period((uint8_t)
993
            VCSELPulsePeriodPCLK);
994

    
995
        /* When the VCSEL period for the pre or final range is changed,
996
        * the corresponding timeout must be read from the device using
997
        * the current VCSEL period, then the new VCSEL period can be
998
        * applied. The timeout then must be written back to the device
999
        * using the new VCSEL period.
1000
        *
1001
        * For the MSRC timeout, the same applies - this timeout being
1002
        * dependant on the pre-range vcsel period.
1003
        */
1004
        switch (VcselPeriodType) {
1005
        case VL53L0X_VCSEL_PERIOD_PRE_RANGE:
1006
            Status = get_sequence_step_timeout(Dev,
1007
                VL53L0X_SEQUENCESTEP_PRE_RANGE,
1008
                &PreRangeTimeoutMicroSeconds);
1009

    
1010
            if (Status == VL53L0X_ERROR_NONE)
1011
                Status = get_sequence_step_timeout(Dev,
1012
                    VL53L0X_SEQUENCESTEP_MSRC,
1013
                    &MsrcTimeoutMicroSeconds);
1014

    
1015
            if (Status == VL53L0X_ERROR_NONE)
1016
                Status = VL53L0X_WrByte(Dev,
1017
                VL53L0X_REG_PRE_RANGE_CONFIG_VCSEL_PERIOD,
1018
                    vcsel_period_reg);
1019

    
1020

    
1021
            if (Status == VL53L0X_ERROR_NONE)
1022
                Status = set_sequence_step_timeout(Dev,
1023
                    VL53L0X_SEQUENCESTEP_PRE_RANGE,
1024
                    PreRangeTimeoutMicroSeconds);
1025

    
1026

    
1027
            if (Status == VL53L0X_ERROR_NONE)
1028
                Status = set_sequence_step_timeout(Dev,
1029
                    VL53L0X_SEQUENCESTEP_MSRC,
1030
                    MsrcTimeoutMicroSeconds);
1031

    
1032
            VL53L0X_SETDEVICESPECIFICPARAMETER(
1033
                Dev,
1034
                PreRangeVcselPulsePeriod,
1035
                VCSELPulsePeriodPCLK);
1036
            break;
1037
        case VL53L0X_VCSEL_PERIOD_FINAL_RANGE:
1038
            Status = get_sequence_step_timeout(Dev,
1039
                VL53L0X_SEQUENCESTEP_FINAL_RANGE,
1040
                &FinalRangeTimeoutMicroSeconds);
1041

    
1042
            if (Status == VL53L0X_ERROR_NONE)
1043
                Status = VL53L0X_WrByte(Dev,
1044
                VL53L0X_REG_FINAL_RANGE_CONFIG_VCSEL_PERIOD,
1045
                    vcsel_period_reg);
1046

    
1047

    
1048
            if (Status == VL53L0X_ERROR_NONE)
1049
                Status = set_sequence_step_timeout(Dev,
1050
                    VL53L0X_SEQUENCESTEP_FINAL_RANGE,
1051
                    FinalRangeTimeoutMicroSeconds);
1052

    
1053
            VL53L0X_SETDEVICESPECIFICPARAMETER(
1054
                Dev,
1055
                FinalRangeVcselPulsePeriod,
1056
                VCSELPulsePeriodPCLK);
1057
            break;
1058
        default:
1059
            Status = VL53L0X_ERROR_INVALID_PARAMS;
1060
        }
1061
    }
1062

    
1063
    /* Finally, the timing budget must be re-applied */
1064
    if (Status == VL53L0X_ERROR_NONE) {
1065
        VL53L0X_GETPARAMETERFIELD(Dev,
1066
            MeasurementTimingBudgetMicroSeconds,
1067
            MeasurementTimingBudgetMicroSeconds);
1068

    
1069
        Status = VL53L0X_SetMeasurementTimingBudgetMicroSeconds(Dev,
1070
                MeasurementTimingBudgetMicroSeconds);
1071
    }
1072

    
1073
    /* Perform the phase calibration. This is needed after changing on
1074
     * vcsel period.
1075
     * get_data_enable = 0, restore_config = 1 */
1076
    if (Status == VL53L0X_ERROR_NONE)
1077
        Status = VL53L0X_perform_phase_calibration(
1078
            Dev, &PhaseCalInt, 0, 1);
1079

    
1080
    return Status;
1081
}
1082

    
1083
VL53L0X_Error VL53L0X_get_vcsel_pulse_period(VL53L0X_DEV Dev,
1084
    VL53L0X_VcselPeriod VcselPeriodType, uint8_t *pVCSELPulsePeriodPCLK)
1085
{
1086
    VL53L0X_Error Status = VL53L0X_ERROR_NONE;
1087
    uint8_t vcsel_period_reg;
1088

    
1089
    switch (VcselPeriodType) {
1090
    case VL53L0X_VCSEL_PERIOD_PRE_RANGE:
1091
        Status = VL53L0X_RdByte(Dev,
1092
            VL53L0X_REG_PRE_RANGE_CONFIG_VCSEL_PERIOD,
1093
            &vcsel_period_reg);
1094
    break;
1095
    case VL53L0X_VCSEL_PERIOD_FINAL_RANGE:
1096
        Status = VL53L0X_RdByte(Dev,
1097
            VL53L0X_REG_FINAL_RANGE_CONFIG_VCSEL_PERIOD,
1098
            &vcsel_period_reg);
1099
    break;
1100
    default:
1101
        Status = VL53L0X_ERROR_INVALID_PARAMS;
1102
    }
1103

    
1104
    if (Status == VL53L0X_ERROR_NONE)
1105
        *pVCSELPulsePeriodPCLK =
1106
            VL53L0X_decode_vcsel_period(vcsel_period_reg);
1107

    
1108
    return Status;
1109
}
1110

    
1111

    
1112

    
1113
VL53L0X_Error VL53L0X_set_measurement_timing_budget_micro_seconds(VL53L0X_DEV Dev,
1114
        uint32_t MeasurementTimingBudgetMicroSeconds)
1115
{
1116
    VL53L0X_Error Status = VL53L0X_ERROR_NONE;
1117
    uint32_t FinalRangeTimingBudgetMicroSeconds;
1118
    VL53L0X_SchedulerSequenceSteps_t SchedulerSequenceSteps;
1119
    uint32_t MsrcDccTccTimeoutMicroSeconds        = 2000;
1120
    uint32_t StartOverheadMicroSeconds                = 1910;
1121
    uint32_t EndOverheadMicroSeconds                = 960;
1122
    uint32_t MsrcOverheadMicroSeconds                = 660;
1123
    uint32_t TccOverheadMicroSeconds                = 590;
1124
    uint32_t DssOverheadMicroSeconds                = 690;
1125
    uint32_t PreRangeOverheadMicroSeconds        = 660;
1126
    uint32_t FinalRangeOverheadMicroSeconds = 550;
1127
    uint32_t PreRangeTimeoutMicroSeconds        = 0;
1128
    uint32_t cMinTimingBudgetMicroSeconds        = 20000;
1129
    uint32_t SubTimeout = 0;
1130

    
1131
    LOG_FUNCTION_START("");
1132

    
1133
    if (MeasurementTimingBudgetMicroSeconds
1134
            < cMinTimingBudgetMicroSeconds) {
1135
        Status = VL53L0X_ERROR_INVALID_PARAMS;
1136
        return Status;
1137
    }
1138

    
1139
    FinalRangeTimingBudgetMicroSeconds =
1140
        MeasurementTimingBudgetMicroSeconds -
1141
        (StartOverheadMicroSeconds + EndOverheadMicroSeconds);
1142

    
1143
    Status = VL53L0X_GetSequenceStepEnables(Dev, &SchedulerSequenceSteps);
1144

    
1145
    if (Status == VL53L0X_ERROR_NONE &&
1146
        (SchedulerSequenceSteps.TccOn  ||
1147
        SchedulerSequenceSteps.MsrcOn ||
1148
        SchedulerSequenceSteps.DssOn)) {
1149

    
1150
        /* TCC, MSRC and DSS all share the same timeout */
1151
        Status = get_sequence_step_timeout(Dev,
1152
                    VL53L0X_SEQUENCESTEP_MSRC,
1153
                    &MsrcDccTccTimeoutMicroSeconds);
1154

    
1155
        /* Subtract the TCC, MSRC and DSS timeouts if they are
1156
         * enabled. */
1157

    
1158
        if (Status != VL53L0X_ERROR_NONE)
1159
            return Status;
1160

    
1161
        /* TCC */
1162
        if (SchedulerSequenceSteps.TccOn) {
1163

    
1164
            SubTimeout = MsrcDccTccTimeoutMicroSeconds
1165
                + TccOverheadMicroSeconds;
1166

    
1167
            if (SubTimeout <
1168
                FinalRangeTimingBudgetMicroSeconds) {
1169
                FinalRangeTimingBudgetMicroSeconds -=
1170
                            SubTimeout;
1171
            } else {
1172
                /* Requested timeout too big. */
1173
                Status = VL53L0X_ERROR_INVALID_PARAMS;
1174
            }
1175
        }
1176

    
1177
        if (Status != VL53L0X_ERROR_NONE) {
1178
            LOG_FUNCTION_END(Status);
1179
            return Status;
1180
        }
1181

    
1182
        /* DSS */
1183
        if (SchedulerSequenceSteps.DssOn) {
1184

    
1185
            SubTimeout = 2 * (MsrcDccTccTimeoutMicroSeconds +
1186
                DssOverheadMicroSeconds);
1187

    
1188
            if (SubTimeout < FinalRangeTimingBudgetMicroSeconds) {
1189
                FinalRangeTimingBudgetMicroSeconds
1190
                            -= SubTimeout;
1191
            } else {
1192
                /* Requested timeout too big. */
1193
                Status = VL53L0X_ERROR_INVALID_PARAMS;
1194
            }
1195
        } else if (SchedulerSequenceSteps.MsrcOn) {
1196
            /* MSRC */
1197
            SubTimeout = MsrcDccTccTimeoutMicroSeconds +
1198
                        MsrcOverheadMicroSeconds;
1199

    
1200
            if (SubTimeout < FinalRangeTimingBudgetMicroSeconds) {
1201
                FinalRangeTimingBudgetMicroSeconds
1202
                            -= SubTimeout;
1203
            } else {
1204
                /* Requested timeout too big. */
1205
                Status = VL53L0X_ERROR_INVALID_PARAMS;
1206
            }
1207
        }
1208

    
1209
    }
1210

    
1211
    if (Status != VL53L0X_ERROR_NONE) {
1212
        LOG_FUNCTION_END(Status);
1213
        return Status;
1214
    }
1215

    
1216
    if (SchedulerSequenceSteps.PreRangeOn) {
1217

    
1218
        /* Subtract the Pre-range timeout if enabled. */
1219

    
1220
        Status = get_sequence_step_timeout(Dev,
1221
                VL53L0X_SEQUENCESTEP_PRE_RANGE,
1222
                &PreRangeTimeoutMicroSeconds);
1223

    
1224
        SubTimeout = PreRangeTimeoutMicroSeconds +
1225
                PreRangeOverheadMicroSeconds;
1226

    
1227
        if (SubTimeout < FinalRangeTimingBudgetMicroSeconds) {
1228
            FinalRangeTimingBudgetMicroSeconds -= SubTimeout;
1229
        } else {
1230
            /* Requested timeout too big. */
1231
            Status = VL53L0X_ERROR_INVALID_PARAMS;
1232
        }
1233
    }
1234

    
1235

    
1236
    if (Status == VL53L0X_ERROR_NONE &&
1237
        SchedulerSequenceSteps.FinalRangeOn) {
1238

    
1239
        FinalRangeTimingBudgetMicroSeconds -=
1240
                FinalRangeOverheadMicroSeconds;
1241

    
1242
        /* Final Range Timeout
1243
         * Note that the final range timeout is determined by the timing
1244
         * budget and the sum of all other timeouts within the sequence.
1245
         * If there is no room for the final range timeout, then an error
1246
         * will be set. Otherwise the remaining time will be applied to
1247
         * the final range.
1248
         */
1249
        Status = set_sequence_step_timeout(Dev,
1250
            VL53L0X_SEQUENCESTEP_FINAL_RANGE,
1251
            FinalRangeTimingBudgetMicroSeconds);
1252

    
1253
        VL53L0X_SETPARAMETERFIELD(Dev,
1254
            MeasurementTimingBudgetMicroSeconds,
1255
            MeasurementTimingBudgetMicroSeconds);
1256
    }
1257

    
1258
    LOG_FUNCTION_END(Status);
1259

    
1260
    return Status;
1261
}
1262

    
1263
VL53L0X_Error VL53L0X_get_measurement_timing_budget_micro_seconds(VL53L0X_DEV Dev,
1264
        uint32_t *pMeasurementTimingBudgetMicroSeconds)
1265
{
1266
    VL53L0X_Error Status = VL53L0X_ERROR_NONE;
1267
    VL53L0X_SchedulerSequenceSteps_t SchedulerSequenceSteps;
1268
    uint32_t FinalRangeTimeoutMicroSeconds;
1269
    uint32_t MsrcDccTccTimeoutMicroSeconds        = 2000;
1270
    uint32_t StartOverheadMicroSeconds                = 1910;
1271
    uint32_t EndOverheadMicroSeconds                = 960;
1272
    uint32_t MsrcOverheadMicroSeconds                = 660;
1273
    uint32_t TccOverheadMicroSeconds                = 590;
1274
    uint32_t DssOverheadMicroSeconds                = 690;
1275
    uint32_t PreRangeOverheadMicroSeconds        = 660;
1276
    uint32_t FinalRangeOverheadMicroSeconds = 550;
1277
    uint32_t PreRangeTimeoutMicroSeconds        = 0;
1278

    
1279
    LOG_FUNCTION_START("");
1280

    
1281
    /* Start and end overhead times always present */
1282
    *pMeasurementTimingBudgetMicroSeconds
1283
        = StartOverheadMicroSeconds + EndOverheadMicroSeconds;
1284

    
1285
    Status = VL53L0X_GetSequenceStepEnables(Dev, &SchedulerSequenceSteps);
1286

    
1287
    if (Status != VL53L0X_ERROR_NONE) {
1288
        LOG_FUNCTION_END(Status);
1289
        return Status;
1290
    }
1291

    
1292

    
1293
    if (SchedulerSequenceSteps.TccOn  ||
1294
        SchedulerSequenceSteps.MsrcOn ||
1295
        SchedulerSequenceSteps.DssOn) {
1296

    
1297
        Status = get_sequence_step_timeout(Dev,
1298
                VL53L0X_SEQUENCESTEP_MSRC,
1299
                &MsrcDccTccTimeoutMicroSeconds);
1300

    
1301
        if (Status == VL53L0X_ERROR_NONE) {
1302
            if (SchedulerSequenceSteps.TccOn) {
1303
                *pMeasurementTimingBudgetMicroSeconds +=
1304
                    MsrcDccTccTimeoutMicroSeconds +
1305
                    TccOverheadMicroSeconds;
1306
            }
1307

    
1308
            if (SchedulerSequenceSteps.DssOn) {
1309
                *pMeasurementTimingBudgetMicroSeconds +=
1310
                2 * (MsrcDccTccTimeoutMicroSeconds +
1311
                    DssOverheadMicroSeconds);
1312
            } else if (SchedulerSequenceSteps.MsrcOn) {
1313
                *pMeasurementTimingBudgetMicroSeconds +=
1314
                    MsrcDccTccTimeoutMicroSeconds +
1315
                    MsrcOverheadMicroSeconds;
1316
            }
1317
        }
1318
    }
1319

    
1320
    if (Status == VL53L0X_ERROR_NONE) {
1321
        if (SchedulerSequenceSteps.PreRangeOn) {
1322
            Status = get_sequence_step_timeout(Dev,
1323
                VL53L0X_SEQUENCESTEP_PRE_RANGE,
1324
                &PreRangeTimeoutMicroSeconds);
1325
            *pMeasurementTimingBudgetMicroSeconds +=
1326
                PreRangeTimeoutMicroSeconds +
1327
                PreRangeOverheadMicroSeconds;
1328
        }
1329
    }
1330

    
1331
    if (Status == VL53L0X_ERROR_NONE) {
1332
        if (SchedulerSequenceSteps.FinalRangeOn) {
1333
            Status = get_sequence_step_timeout(Dev,
1334
                    VL53L0X_SEQUENCESTEP_FINAL_RANGE,
1335
                    &FinalRangeTimeoutMicroSeconds);
1336
            *pMeasurementTimingBudgetMicroSeconds +=
1337
                (FinalRangeTimeoutMicroSeconds +
1338
                FinalRangeOverheadMicroSeconds);
1339
        }
1340
    }
1341

    
1342
    if (Status == VL53L0X_ERROR_NONE) {
1343
        VL53L0X_SETPARAMETERFIELD(Dev,
1344
            MeasurementTimingBudgetMicroSeconds,
1345
            *pMeasurementTimingBudgetMicroSeconds);
1346
    }
1347

    
1348
    LOG_FUNCTION_END(Status);
1349
    return Status;
1350
}
1351

    
1352

    
1353

    
1354
VL53L0X_Error VL53L0X_load_tuning_settings(VL53L0X_DEV Dev,
1355
        uint8_t *pTuningSettingBuffer)
1356
{
1357
    VL53L0X_Error Status = VL53L0X_ERROR_NONE;
1358
    int i;
1359
    int Index;
1360
    uint8_t msb;
1361
    uint8_t lsb;
1362
    uint8_t SelectParam;
1363
    uint8_t NumberOfWrites;
1364
    uint8_t Address;
1365
    uint8_t localBuffer[4]; /* max */
1366
    uint16_t Temp16;
1367

    
1368
    LOG_FUNCTION_START("");
1369

    
1370
    Index = 0;
1371

    
1372
    while ((*(pTuningSettingBuffer + Index) != 0) &&
1373
            (Status == VL53L0X_ERROR_NONE)) {
1374
        NumberOfWrites = *(pTuningSettingBuffer + Index);
1375
        Index++;
1376
        if (NumberOfWrites == 0xFF) {
1377
            /* internal parameters */
1378
            SelectParam = *(pTuningSettingBuffer + Index);
1379
            Index++;
1380
            switch (SelectParam) {
1381
            case 0: /* uint16_t SigmaEstRefArray -> 2 bytes */
1382
                msb = *(pTuningSettingBuffer + Index);
1383
                Index++;
1384
                lsb = *(pTuningSettingBuffer + Index);
1385
                Index++;
1386
                Temp16 = VL53L0X_MAKEUINT16(lsb, msb);
1387
                PALDevDataSet(Dev, SigmaEstRefArray, Temp16);
1388
                break;
1389
            case 1: /* uint16_t SigmaEstEffPulseWidth -> 2 bytes */
1390
                msb = *(pTuningSettingBuffer + Index);
1391
                Index++;
1392
                lsb = *(pTuningSettingBuffer + Index);
1393
                Index++;
1394
                Temp16 = VL53L0X_MAKEUINT16(lsb, msb);
1395
                PALDevDataSet(Dev, SigmaEstEffPulseWidth,
1396
                    Temp16);
1397
                break;
1398
            case 2: /* uint16_t SigmaEstEffAmbWidth -> 2 bytes */
1399
                msb = *(pTuningSettingBuffer + Index);
1400
                Index++;
1401
                lsb = *(pTuningSettingBuffer + Index);
1402
                Index++;
1403
                Temp16 = VL53L0X_MAKEUINT16(lsb, msb);
1404
                PALDevDataSet(Dev, SigmaEstEffAmbWidth, Temp16);
1405
                break;
1406
            case 3: /* uint16_t targetRefRate -> 2 bytes */
1407
                msb = *(pTuningSettingBuffer + Index);
1408
                Index++;
1409
                lsb = *(pTuningSettingBuffer + Index);
1410
                Index++;
1411
                Temp16 = VL53L0X_MAKEUINT16(lsb, msb);
1412
                PALDevDataSet(Dev, targetRefRate, Temp16);
1413
                break;
1414
            default: /* invalid parameter */
1415
                Status = VL53L0X_ERROR_INVALID_PARAMS;
1416
            }
1417

    
1418
        } else if (NumberOfWrites <= 4) {
1419
            Address = *(pTuningSettingBuffer + Index);
1420
            Index++;
1421

    
1422
            for (i = 0; i < NumberOfWrites; i++) {
1423
                localBuffer[i] = *(pTuningSettingBuffer +
1424
                            Index);
1425
                Index++;
1426
            }
1427

    
1428
            Status = VL53L0X_WriteMulti(Dev, Address, localBuffer,
1429
                    NumberOfWrites);
1430

    
1431
        } else {
1432
            Status = VL53L0X_ERROR_INVALID_PARAMS;
1433
        }
1434
    }
1435

    
1436
    LOG_FUNCTION_END(Status);
1437
    return Status;
1438
}
1439

    
1440
VL53L0X_Error VL53L0X_get_total_xtalk_rate(VL53L0X_DEV Dev,
1441
    VL53L0X_RangingMeasurementData_t *pRangingMeasurementData,
1442
    FixPoint1616_t *ptotal_xtalk_rate_mcps)
1443
{
1444
    VL53L0X_Error Status = VL53L0X_ERROR_NONE;
1445

    
1446
    uint8_t xtalkCompEnable;
1447
    FixPoint1616_t totalXtalkMegaCps;
1448
    FixPoint1616_t xtalkPerSpadMegaCps;
1449

    
1450
    *ptotal_xtalk_rate_mcps = 0;
1451

    
1452
    Status = VL53L0X_GetXTalkCompensationEnable(Dev, &xtalkCompEnable);
1453
    if (Status == VL53L0X_ERROR_NONE) {
1454

    
1455
        if (xtalkCompEnable) {
1456

    
1457
            VL53L0X_GETPARAMETERFIELD(
1458
                Dev,
1459
                XTalkCompensationRateMegaCps,
1460
                xtalkPerSpadMegaCps);
1461

    
1462
            /* FixPoint1616 * FixPoint 8:8 = FixPoint0824 */
1463
            totalXtalkMegaCps =
1464
                pRangingMeasurementData->EffectiveSpadRtnCount *
1465
                xtalkPerSpadMegaCps;
1466

    
1467
            /* FixPoint0824 >> 8 = FixPoint1616 */
1468
            *ptotal_xtalk_rate_mcps =
1469
                (totalXtalkMegaCps + 0x80) >> 8;
1470
        }
1471
    }
1472

    
1473
    return Status;
1474
}
1475

    
1476
VL53L0X_Error VL53L0X_get_total_signal_rate(VL53L0X_DEV Dev,
1477
    VL53L0X_RangingMeasurementData_t *pRangingMeasurementData,
1478
    FixPoint1616_t *ptotal_signal_rate_mcps)
1479
{
1480
    VL53L0X_Error Status = VL53L0X_ERROR_NONE;
1481
    FixPoint1616_t totalXtalkMegaCps;
1482

    
1483
    LOG_FUNCTION_START("");
1484

    
1485
    *ptotal_signal_rate_mcps =
1486
        pRangingMeasurementData->SignalRateRtnMegaCps;
1487

    
1488
    Status = VL53L0X_get_total_xtalk_rate(
1489
        Dev, pRangingMeasurementData, &totalXtalkMegaCps);
1490

    
1491
    if (Status == VL53L0X_ERROR_NONE)
1492
        *ptotal_signal_rate_mcps += totalXtalkMegaCps;
1493

    
1494
    return Status;
1495
}
1496

    
1497
VL53L0X_Error VL53L0X_calc_dmax(
1498
    VL53L0X_DEV Dev,
1499
    FixPoint1616_t totalSignalRate_mcps,
1500
    FixPoint1616_t totalCorrSignalRate_mcps,
1501
    FixPoint1616_t pwMult,
1502
    uint32_t sigmaEstimateP1,
1503
    FixPoint1616_t sigmaEstimateP2,
1504
    uint32_t peakVcselDuration_us,
1505
    uint32_t *pdmax_mm)
1506
{
1507
    const uint32_t cSigmaLimit                = 18;
1508
    const FixPoint1616_t cSignalLimit        = 0x4000; /* 0.25 */
1509
    const FixPoint1616_t cSigmaEstRef        = 0x00000042; /* 0.001 */
1510
    const uint32_t cAmbEffWidthSigmaEst_ns = 6;
1511
    const uint32_t cAmbEffWidthDMax_ns           = 7;
1512
    uint32_t dmaxCalRange_mm;
1513
    FixPoint1616_t dmaxCalSignalRateRtn_mcps;
1514
    FixPoint1616_t minSignalNeeded;
1515
    FixPoint1616_t minSignalNeeded_p1;
1516
    FixPoint1616_t minSignalNeeded_p2;
1517
    FixPoint1616_t minSignalNeeded_p3;
1518
    FixPoint1616_t minSignalNeeded_p4;
1519
    FixPoint1616_t sigmaLimitTmp;
1520
    FixPoint1616_t sigmaEstSqTmp;
1521
    FixPoint1616_t signalLimitTmp;
1522
    FixPoint1616_t SignalAt0mm;
1523
    FixPoint1616_t dmaxDark;
1524
    FixPoint1616_t dmaxAmbient;
1525
    FixPoint1616_t dmaxDarkTmp;
1526
    FixPoint1616_t sigmaEstP2Tmp;
1527
    uint32_t signalRateTemp_mcps;
1528

    
1529
    VL53L0X_Error Status = VL53L0X_ERROR_NONE;
1530

    
1531
    LOG_FUNCTION_START("");
1532

    
1533
    dmaxCalRange_mm =
1534
        PALDevDataGet(Dev, DmaxCalRangeMilliMeter);
1535

    
1536
    dmaxCalSignalRateRtn_mcps =
1537
        PALDevDataGet(Dev, DmaxCalSignalRateRtnMegaCps);
1538

    
1539
    /* uint32 * FixPoint1616 = FixPoint1616 */
1540
    SignalAt0mm = dmaxCalRange_mm * dmaxCalSignalRateRtn_mcps;
1541

    
1542
    /* FixPoint1616 >> 8 = FixPoint2408 */
1543
    SignalAt0mm = (SignalAt0mm + 0x80) >> 8;
1544
    SignalAt0mm *= dmaxCalRange_mm;
1545

    
1546
    minSignalNeeded_p1 = 0;
1547
    if (totalCorrSignalRate_mcps > 0) {
1548

    
1549
        /* Shift by 10 bits to increase resolution prior to the
1550
         * division */
1551
        signalRateTemp_mcps = totalSignalRate_mcps << 10;
1552

    
1553
        /* Add rounding value prior to division */
1554
        minSignalNeeded_p1 = signalRateTemp_mcps +
1555
            (totalCorrSignalRate_mcps/2);
1556

    
1557
        /* FixPoint0626/FixPoint1616 = FixPoint2210 */
1558
        minSignalNeeded_p1 /= totalCorrSignalRate_mcps;
1559

    
1560
        /* Apply a factored version of the speed of light.
1561
         Correction to be applied at the end */
1562
        minSignalNeeded_p1 *= 3;
1563

    
1564
        /* FixPoint2210 * FixPoint2210 = FixPoint1220 */
1565
        minSignalNeeded_p1 *= minSignalNeeded_p1;
1566

    
1567
        /* FixPoint1220 >> 16 = FixPoint2804 */
1568
        minSignalNeeded_p1 = (minSignalNeeded_p1 + 0x8000) >> 16;
1569
    }
1570

    
1571
    minSignalNeeded_p2 = pwMult * sigmaEstimateP1;
1572

    
1573
    /* FixPoint1616 >> 16 =         uint32 */
1574
    minSignalNeeded_p2 = (minSignalNeeded_p2 + 0x8000) >> 16;
1575

    
1576
    /* uint32 * uint32        =  uint32 */
1577
    minSignalNeeded_p2 *= minSignalNeeded_p2;
1578

    
1579
    /* Check sigmaEstimateP2
1580
     * If this value is too high there is not enough signal rate
1581
     * to calculate dmax value so set a suitable value to ensure
1582
     * a very small dmax.
1583
     */
1584
    sigmaEstP2Tmp = (sigmaEstimateP2 + 0x8000) >> 16;
1585
    sigmaEstP2Tmp = (sigmaEstP2Tmp + cAmbEffWidthSigmaEst_ns/2)/
1586
        cAmbEffWidthSigmaEst_ns;
1587
    sigmaEstP2Tmp *= cAmbEffWidthDMax_ns;
1588

    
1589
    if (sigmaEstP2Tmp > 0xffff) {
1590
        minSignalNeeded_p3 = 0xfff00000;
1591
    } else {
1592

    
1593
        /* DMAX uses a different ambient width from sigma, so apply
1594
         * correction.
1595
         * Perform division before multiplication to prevent overflow.
1596
         */
1597
        sigmaEstimateP2 = (sigmaEstimateP2 + cAmbEffWidthSigmaEst_ns/2)/
1598
            cAmbEffWidthSigmaEst_ns;
1599
        sigmaEstimateP2 *= cAmbEffWidthDMax_ns;
1600

    
1601
        /* FixPoint1616 >> 16 = uint32 */
1602
        minSignalNeeded_p3 = (sigmaEstimateP2 + 0x8000) >> 16;
1603

    
1604
        minSignalNeeded_p3 *= minSignalNeeded_p3;
1605

    
1606
    }
1607

    
1608
    /* FixPoint1814 / uint32 = FixPoint1814 */
1609
    sigmaLimitTmp = ((cSigmaLimit << 14) + 500) / 1000;
1610

    
1611
    /* FixPoint1814 * FixPoint1814 = FixPoint3628 := FixPoint0428 */
1612
    sigmaLimitTmp *= sigmaLimitTmp;
1613

    
1614
    /* FixPoint1616 * FixPoint1616 = FixPoint3232 */
1615
    sigmaEstSqTmp = cSigmaEstRef * cSigmaEstRef;
1616

    
1617
    /* FixPoint3232 >> 4 = FixPoint0428 */
1618
    sigmaEstSqTmp = (sigmaEstSqTmp + 0x08) >> 4;
1619

    
1620
    /* FixPoint0428 - FixPoint0428        = FixPoint0428 */
1621
    sigmaLimitTmp -=  sigmaEstSqTmp;
1622

    
1623
    /* uint32_t * FixPoint0428 = FixPoint0428 */
1624
    minSignalNeeded_p4 = 4 * 12 * sigmaLimitTmp;
1625

    
1626
    /* FixPoint0428 >> 14 = FixPoint1814 */
1627
    minSignalNeeded_p4 = (minSignalNeeded_p4 + 0x2000) >> 14;
1628

    
1629
    /* uint32 + uint32 = uint32 */
1630
    minSignalNeeded = (minSignalNeeded_p2 + minSignalNeeded_p3);
1631

    
1632
    /* uint32 / uint32 = uint32 */
1633
    minSignalNeeded += (peakVcselDuration_us/2);
1634
    minSignalNeeded /= peakVcselDuration_us;
1635

    
1636
    /* uint32 << 14 = FixPoint1814 */
1637
    minSignalNeeded <<= 14;
1638

    
1639
    /* FixPoint1814 / FixPoint1814 = uint32 */
1640
    minSignalNeeded += (minSignalNeeded_p4/2);
1641
    minSignalNeeded /= minSignalNeeded_p4;
1642

    
1643
    /* FixPoint3200 * FixPoint2804 := FixPoint2804*/
1644
    minSignalNeeded *= minSignalNeeded_p1;
1645

    
1646
    /* Apply correction by dividing by 1000000.
1647
     * This assumes 10E16 on the numerator of the equation
1648
     * and 10E-22 on the denominator.
1649
     * We do this because 32bit fix point calculation can't
1650
     * handle the larger and smaller elements of this equation,
1651
     * i.e. speed of light and pulse widths.
1652
     */
1653
    minSignalNeeded = (minSignalNeeded + 500) / 1000;
1654
    minSignalNeeded <<= 4;
1655

    
1656
    minSignalNeeded = (minSignalNeeded + 500) / 1000;
1657

    
1658
    /* FixPoint1616 >> 8 = FixPoint2408 */
1659
    signalLimitTmp = (cSignalLimit + 0x80) >> 8;
1660

    
1661
    /* FixPoint2408/FixPoint2408 = uint32 */
1662
    if (signalLimitTmp != 0)
1663
        dmaxDarkTmp = (SignalAt0mm + (signalLimitTmp / 2))
1664
            / signalLimitTmp;
1665
    else
1666
        dmaxDarkTmp = 0;
1667

    
1668
    dmaxDark = VL53L0X_isqrt(dmaxDarkTmp);
1669

    
1670
    /* FixPoint2408/FixPoint2408 = uint32 */
1671
    if (minSignalNeeded != 0)
1672
        dmaxAmbient = (SignalAt0mm + minSignalNeeded/2)
1673
            / minSignalNeeded;
1674
    else
1675
        dmaxAmbient = 0;
1676

    
1677
    dmaxAmbient = VL53L0X_isqrt(dmaxAmbient);
1678

    
1679
    *pdmax_mm = dmaxDark;
1680
    if (dmaxDark > dmaxAmbient)
1681
        *pdmax_mm = dmaxAmbient;
1682

    
1683
    LOG_FUNCTION_END(Status);
1684

    
1685
    return Status;
1686
}
1687

    
1688

    
1689
VL53L0X_Error VL53L0X_calc_sigma_estimate(VL53L0X_DEV Dev,
1690
    VL53L0X_RangingMeasurementData_t *pRangingMeasurementData,
1691
    FixPoint1616_t *pSigmaEstimate,
1692
    uint32_t *pDmax_mm)
1693
{
1694
    /* Expressed in 100ths of a ns, i.e. centi-ns */
1695
    const uint32_t cPulseEffectiveWidth_centi_ns   = 800;
1696
    /* Expressed in 100ths of a ns, i.e. centi-ns */
1697
    const uint32_t cAmbientEffectiveWidth_centi_ns = 600;
1698
    const FixPoint1616_t cDfltFinalRangeIntegrationTimeMilliSecs        = 0x00190000; /* 25ms */
1699
    const uint32_t cVcselPulseWidth_ps        = 4700; /* pico secs */
1700
    const FixPoint1616_t cSigmaEstMax        = 0x028F87AE;
1701
    const FixPoint1616_t cSigmaEstRtnMax        = 0xF000;
1702
    const FixPoint1616_t cAmbToSignalRatioMax = 0xF0000000/
1703
        cAmbientEffectiveWidth_centi_ns;
1704
    /* Time Of Flight per mm (6.6 pico secs) */
1705
    const FixPoint1616_t cTOF_per_mm_ps                = 0x0006999A;
1706
    const uint32_t c16BitRoundingParam                = 0x00008000;
1707
    const FixPoint1616_t cMaxXTalk_kcps                = 0x00320000;
1708
    const uint32_t cPllPeriod_ps                        = 1655;
1709

    
1710
    uint32_t vcselTotalEventsRtn;
1711
    uint32_t finalRangeTimeoutMicroSecs;
1712
    uint32_t preRangeTimeoutMicroSecs;
1713
    uint32_t finalRangeIntegrationTimeMilliSecs;
1714
    FixPoint1616_t sigmaEstimateP1;
1715
    FixPoint1616_t sigmaEstimateP2;
1716
    FixPoint1616_t sigmaEstimateP3;
1717
    FixPoint1616_t deltaT_ps;
1718
    FixPoint1616_t pwMult;
1719
    FixPoint1616_t sigmaEstRtn;
1720
    FixPoint1616_t sigmaEstimate;
1721
    FixPoint1616_t xTalkCorrection;
1722
    FixPoint1616_t ambientRate_kcps;
1723
    FixPoint1616_t peakSignalRate_kcps;
1724
    FixPoint1616_t xTalkCompRate_mcps;
1725
    uint32_t xTalkCompRate_kcps;
1726
    VL53L0X_Error Status = VL53L0X_ERROR_NONE;
1727
    FixPoint1616_t diff1_mcps;
1728
    FixPoint1616_t diff2_mcps;
1729
    FixPoint1616_t sqr1;
1730
    FixPoint1616_t sqr2;
1731
    FixPoint1616_t sqrSum;
1732
    FixPoint1616_t sqrtResult_centi_ns;
1733
    FixPoint1616_t sqrtResult;
1734
    FixPoint1616_t totalSignalRate_mcps;
1735
    FixPoint1616_t correctedSignalRate_mcps;
1736
    FixPoint1616_t sigmaEstRef;
1737
    uint32_t vcselWidth;
1738
    uint32_t finalRangeMacroPCLKS;
1739
    uint32_t preRangeMacroPCLKS;
1740
    uint32_t peakVcselDuration_us;
1741
    uint8_t finalRangeVcselPCLKS;
1742
    uint8_t preRangeVcselPCLKS;
1743
    /*! \addtogroup calc_sigma_estimate
1744
     * @{
1745
     *
1746
     * Estimates the range sigma
1747
     */
1748

    
1749
    LOG_FUNCTION_START("");
1750

    
1751
    VL53L0X_GETPARAMETERFIELD(Dev, XTalkCompensationRateMegaCps,
1752
            xTalkCompRate_mcps);
1753

    
1754
    /*
1755
     * We work in kcps rather than mcps as this helps keep within the
1756
     * confines of the 32 Fix1616 type.
1757
     */
1758

    
1759
    ambientRate_kcps =
1760
        (pRangingMeasurementData->AmbientRateRtnMegaCps * 1000) >> 16;
1761

    
1762
    correctedSignalRate_mcps =
1763
        pRangingMeasurementData->SignalRateRtnMegaCps;
1764

    
1765

    
1766
    Status = VL53L0X_get_total_signal_rate(
1767
        Dev, pRangingMeasurementData, &totalSignalRate_mcps);
1768
    Status = VL53L0X_get_total_xtalk_rate(
1769
        Dev, pRangingMeasurementData, &xTalkCompRate_mcps);
1770

    
1771

    
1772
    /* Signal rate measurement provided by device is the
1773
     * peak signal rate, not average.
1774
     */
1775
    peakSignalRate_kcps = (totalSignalRate_mcps * 1000);
1776
    peakSignalRate_kcps = (peakSignalRate_kcps + 0x8000) >> 16;
1777

    
1778
    xTalkCompRate_kcps = xTalkCompRate_mcps * 1000;
1779

    
1780
    if (xTalkCompRate_kcps > cMaxXTalk_kcps)
1781
        xTalkCompRate_kcps = cMaxXTalk_kcps;
1782

    
1783
    if (Status == VL53L0X_ERROR_NONE) {
1784

    
1785
        /* Calculate final range macro periods */
1786
        finalRangeTimeoutMicroSecs = VL53L0X_GETDEVICESPECIFICPARAMETER(
1787
            Dev, FinalRangeTimeoutMicroSecs);
1788

    
1789
        finalRangeVcselPCLKS = VL53L0X_GETDEVICESPECIFICPARAMETER(
1790
            Dev, FinalRangeVcselPulsePeriod);
1791

    
1792
        finalRangeMacroPCLKS = VL53L0X_calc_timeout_mclks(
1793
            Dev, finalRangeTimeoutMicroSecs, finalRangeVcselPCLKS);
1794

    
1795
        /* Calculate pre-range macro periods */
1796
        preRangeTimeoutMicroSecs = VL53L0X_GETDEVICESPECIFICPARAMETER(
1797
            Dev, PreRangeTimeoutMicroSecs);
1798

    
1799
        preRangeVcselPCLKS = VL53L0X_GETDEVICESPECIFICPARAMETER(
1800
            Dev, PreRangeVcselPulsePeriod);
1801

    
1802
        preRangeMacroPCLKS = VL53L0X_calc_timeout_mclks(
1803
            Dev, preRangeTimeoutMicroSecs, preRangeVcselPCLKS);
1804

    
1805
        vcselWidth = 3;
1806
        if (finalRangeVcselPCLKS == 8)
1807
            vcselWidth = 2;
1808

    
1809

    
1810
        peakVcselDuration_us = vcselWidth * 2048 *
1811
            (preRangeMacroPCLKS + finalRangeMacroPCLKS);
1812
        peakVcselDuration_us = (peakVcselDuration_us + 500)/1000;
1813
        peakVcselDuration_us *= cPllPeriod_ps;
1814
        peakVcselDuration_us = (peakVcselDuration_us + 500)/1000;
1815

    
1816
        /* Fix1616 >> 8 = Fix2408 */
1817
        totalSignalRate_mcps = (totalSignalRate_mcps + 0x80) >> 8;
1818

    
1819
        /* Fix2408 * uint32 = Fix2408 */
1820
        vcselTotalEventsRtn = totalSignalRate_mcps *
1821
            peakVcselDuration_us;
1822

    
1823
        /* Fix2408 >> 8 = uint32 */
1824
        vcselTotalEventsRtn = (vcselTotalEventsRtn + 0x80) >> 8;
1825

    
1826
        /* Fix2408 << 8 = Fix1616 = */
1827
        totalSignalRate_mcps <<= 8;
1828
    }
1829

    
1830
    if (Status != VL53L0X_ERROR_NONE) {
1831
        LOG_FUNCTION_END(Status);
1832
        return Status;
1833
    }
1834

    
1835
    if (peakSignalRate_kcps == 0) {
1836
        *pSigmaEstimate = cSigmaEstMax;
1837
        PALDevDataSet(Dev, SigmaEstimate, cSigmaEstMax);
1838
        *pDmax_mm = 0;
1839
    } else {
1840
        if (vcselTotalEventsRtn < 1)
1841
            vcselTotalEventsRtn = 1;
1842

    
1843
        sigmaEstimateP1 = cPulseEffectiveWidth_centi_ns;
1844

    
1845
        /* ((FixPoint1616 << 16)* uint32)/uint32 = FixPoint1616 */
1846
        sigmaEstimateP2 = (ambientRate_kcps << 16)/peakSignalRate_kcps;
1847
        if (sigmaEstimateP2 > cAmbToSignalRatioMax) {
1848
            /* Clip to prevent overflow. Will ensure safe
1849
             * max result. */
1850
            sigmaEstimateP2 = cAmbToSignalRatioMax;
1851
        }
1852
        sigmaEstimateP2 *= cAmbientEffectiveWidth_centi_ns;
1853

    
1854
        sigmaEstimateP3 = 2 * VL53L0X_isqrt(vcselTotalEventsRtn * 12);
1855

    
1856
        /* uint32 * FixPoint1616 = FixPoint1616 */
1857
        deltaT_ps = pRangingMeasurementData->RangeMilliMeter *
1858
                    cTOF_per_mm_ps;
1859

    
1860
        /*
1861
         * vcselRate - xtalkCompRate
1862
         * (uint32 << 16) - FixPoint1616 = FixPoint1616.
1863
         * Divide result by 1000 to convert to mcps.
1864
         * 500 is added to ensure rounding when integer division
1865
         * truncates.
1866
         */
1867
        diff1_mcps = (((peakSignalRate_kcps << 16) -
1868
            2 * xTalkCompRate_kcps) + 500)/1000;
1869

    
1870
        /* vcselRate + xtalkCompRate */
1871
        diff2_mcps = ((peakSignalRate_kcps << 16) + 500)/1000;
1872

    
1873
        /* Shift by 8 bits to increase resolution prior to the
1874
         * division */
1875
        diff1_mcps <<= 8;
1876

    
1877
        /* FixPoint0824/FixPoint1616 = FixPoint2408 */
1878
        xTalkCorrection         = abs(diff1_mcps/diff2_mcps);
1879

    
1880
        /* FixPoint2408 << 8 = FixPoint1616 */
1881
        xTalkCorrection <<= 8;
1882

    
1883
        if(pRangingMeasurementData->RangeStatus != 0){
1884
            pwMult = 1 << 16;
1885
        } else {
1886
            /* FixPoint1616/uint32 = FixPoint1616 */
1887
            pwMult = deltaT_ps/cVcselPulseWidth_ps; /* smaller than 1.0f */
1888

    
1889
            /*
1890
             * FixPoint1616 * FixPoint1616 = FixPoint3232, however both
1891
             * values are small enough such that32 bits will not be
1892
             * exceeded.
1893
             */
1894
            pwMult *= ((1 << 16) - xTalkCorrection);
1895

    
1896
            /* (FixPoint3232 >> 16) = FixPoint1616 */
1897
            pwMult =  (pwMult + c16BitRoundingParam) >> 16;
1898

    
1899
            /* FixPoint1616 + FixPoint1616 = FixPoint1616 */
1900
            pwMult += (1 << 16);
1901

    
1902
            /*
1903
             * At this point the value will be 1.xx, therefore if we square
1904
             * the value this will exceed 32 bits. To address this perform
1905
             * a single shift to the right before the multiplication.
1906
             */
1907
            pwMult >>= 1;
1908
            /* FixPoint1715 * FixPoint1715 = FixPoint3430 */
1909
            pwMult = pwMult * pwMult;
1910

    
1911
            /* (FixPoint3430 >> 14) = Fix1616 */
1912
            pwMult >>= 14;
1913
        }
1914

    
1915
        /* FixPoint1616 * uint32 = FixPoint1616 */
1916
        sqr1 = pwMult * sigmaEstimateP1;
1917

    
1918
        /* (FixPoint1616 >> 16) = FixPoint3200 */
1919
        sqr1 = (sqr1 + 0x8000) >> 16;
1920

    
1921
        /* FixPoint3200 * FixPoint3200 = FixPoint6400 */
1922
        sqr1 *= sqr1;
1923

    
1924
        sqr2 = sigmaEstimateP2;
1925

    
1926
        /* (FixPoint1616 >> 16) = FixPoint3200 */
1927
        sqr2 = (sqr2 + 0x8000) >> 16;
1928

    
1929
        /* FixPoint3200 * FixPoint3200 = FixPoint6400 */
1930
        sqr2 *= sqr2;
1931

    
1932
        /* FixPoint64000 + FixPoint6400 = FixPoint6400 */
1933
        sqrSum = sqr1 + sqr2;
1934

    
1935
        /* SQRT(FixPoin6400) = FixPoint3200 */
1936
        sqrtResult_centi_ns = VL53L0X_isqrt(sqrSum);
1937

    
1938
        /* (FixPoint3200 << 16) = FixPoint1616 */
1939
        sqrtResult_centi_ns <<= 16;
1940

    
1941
        /*
1942
         * Note that the Speed Of Light is expressed in um per 1E-10
1943
         * seconds (2997) Therefore to get mm/ns we have to divide by
1944
         * 10000
1945
         */
1946
        sigmaEstRtn = (((sqrtResult_centi_ns+50)/100) /
1947
                sigmaEstimateP3);
1948
        sigmaEstRtn                 *= VL53L0X_SPEED_OF_LIGHT_IN_AIR;
1949

    
1950
        /* Add 5000 before dividing by 10000 to ensure rounding. */
1951
        sigmaEstRtn                 += 5000;
1952
        sigmaEstRtn                 /= 10000;
1953

    
1954
        if (sigmaEstRtn > cSigmaEstRtnMax) {
1955
            /* Clip to prevent overflow. Will ensure safe
1956
             * max result. */
1957
            sigmaEstRtn = cSigmaEstRtnMax;
1958
        }
1959
        finalRangeIntegrationTimeMilliSecs =
1960
            (finalRangeTimeoutMicroSecs + preRangeTimeoutMicroSecs + 500)/1000;
1961

    
1962
        /* sigmaEstRef = 1mm * 25ms/final range integration time (inc pre-range)
1963
         * sqrt(FixPoint1616/int) = FixPoint2408)
1964
         */
1965
        sigmaEstRef =
1966
            VL53L0X_isqrt((cDfltFinalRangeIntegrationTimeMilliSecs +
1967
                finalRangeIntegrationTimeMilliSecs/2)/
1968
                finalRangeIntegrationTimeMilliSecs);
1969

    
1970
        /* FixPoint2408 << 8 = FixPoint1616 */
1971
        sigmaEstRef <<= 8;
1972
        sigmaEstRef = (sigmaEstRef + 500)/1000;
1973

    
1974
        /* FixPoint1616 * FixPoint1616 = FixPoint3232 */
1975
        sqr1 = sigmaEstRtn * sigmaEstRtn;
1976
        /* FixPoint1616 * FixPoint1616 = FixPoint3232 */
1977
        sqr2 = sigmaEstRef * sigmaEstRef;
1978

    
1979
        /* sqrt(FixPoint3232) = FixPoint1616 */
1980
        sqrtResult = VL53L0X_isqrt((sqr1 + sqr2));
1981
        /*
1982
         * Note that the Shift by 4 bits increases resolution prior to
1983
         * the sqrt, therefore the result must be shifted by 2 bits to
1984
         * the right to revert back to the FixPoint1616 format.
1985
         */
1986

    
1987
        sigmaEstimate         = 1000 * sqrtResult;
1988

    
1989
        if ((peakSignalRate_kcps < 1) || (vcselTotalEventsRtn < 1) ||
1990
                (sigmaEstimate > cSigmaEstMax)) {
1991
                sigmaEstimate = cSigmaEstMax;
1992
        }
1993

    
1994
        *pSigmaEstimate = (uint32_t)(sigmaEstimate);
1995
        PALDevDataSet(Dev, SigmaEstimate, *pSigmaEstimate);
1996
        Status = VL53L0X_calc_dmax(
1997
            Dev,
1998
            totalSignalRate_mcps,
1999
            correctedSignalRate_mcps,
2000
            pwMult,
2001
            sigmaEstimateP1,
2002
            sigmaEstimateP2,
2003
            peakVcselDuration_us,
2004
            pDmax_mm);
2005
    }
2006

    
2007
    LOG_FUNCTION_END(Status);
2008
    return Status;
2009
}
2010

    
2011
VL53L0X_Error VL53L0X_get_pal_range_status(VL53L0X_DEV Dev,
2012
        uint8_t DeviceRangeStatus,
2013
        FixPoint1616_t SignalRate,
2014
        uint16_t EffectiveSpadRtnCount,
2015
        VL53L0X_RangingMeasurementData_t *pRangingMeasurementData,
2016
        uint8_t *pPalRangeStatus)
2017
{
2018
    VL53L0X_Error Status = VL53L0X_ERROR_NONE;
2019
    uint8_t NoneFlag;
2020
    uint8_t SigmaLimitflag = 0;
2021
    uint8_t SignalRefClipflag = 0;
2022
    uint8_t RangeIgnoreThresholdflag = 0;
2023
    uint8_t SigmaLimitCheckEnable = 0;
2024
    uint8_t SignalRateFinalRangeLimitCheckEnable = 0;
2025
    uint8_t SignalRefClipLimitCheckEnable = 0;
2026
    uint8_t RangeIgnoreThresholdLimitCheckEnable = 0;
2027
    FixPoint1616_t SigmaEstimate;
2028
    FixPoint1616_t SigmaLimitValue;
2029
    FixPoint1616_t SignalRefClipValue;
2030
    FixPoint1616_t RangeIgnoreThresholdValue;
2031
    FixPoint1616_t SignalRatePerSpad;
2032
    uint8_t DeviceRangeStatusInternal = 0;
2033
    uint16_t tmpWord = 0;
2034
    uint8_t Temp8;
2035
    uint32_t Dmax_mm = 0;
2036
    FixPoint1616_t LastSignalRefMcps;
2037

    
2038
    LOG_FUNCTION_START("");
2039

    
2040

    
2041
    /*
2042
     * VL53L0X has a good ranging when the value of the
2043
     * DeviceRangeStatus = 11. This function will replace the value 0 with
2044
     * the value 11 in the DeviceRangeStatus.
2045
     * In addition, the SigmaEstimator is not included in the VL53L0X
2046
     * DeviceRangeStatus, this will be added in the PalRangeStatus.
2047
     */
2048

    
2049
    DeviceRangeStatusInternal = ((DeviceRangeStatus & 0x78) >> 3);
2050

    
2051
    if (DeviceRangeStatusInternal == 0 ||
2052
        DeviceRangeStatusInternal == 5 ||
2053
        DeviceRangeStatusInternal == 7 ||
2054
        DeviceRangeStatusInternal == 12 ||
2055
        DeviceRangeStatusInternal == 13 ||
2056
        DeviceRangeStatusInternal == 14 ||
2057
        DeviceRangeStatusInternal == 15
2058
            ) {
2059
        NoneFlag = 1;
2060
    } else {
2061
        NoneFlag = 0;
2062
    }
2063

    
2064
    /*
2065
     * Check if Sigma limit is enabled, if yes then do comparison with limit
2066
     * value and put the result back into pPalRangeStatus.
2067
     */
2068
    if (Status == VL53L0X_ERROR_NONE)
2069
        Status =  VL53L0X_GetLimitCheckEnable(Dev,
2070
            VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE,
2071
            &SigmaLimitCheckEnable);
2072

    
2073
    if ((SigmaLimitCheckEnable != 0) && (Status == VL53L0X_ERROR_NONE)) {
2074
        /*
2075
        * compute the Sigma and check with limit
2076
        */
2077
        Status = VL53L0X_calc_sigma_estimate(
2078
            Dev,
2079
            pRangingMeasurementData,
2080
            &SigmaEstimate,
2081
            &Dmax_mm);
2082
        if (Status == VL53L0X_ERROR_NONE)
2083
            pRangingMeasurementData->RangeDMaxMilliMeter = Dmax_mm;
2084

    
2085
        if (Status == VL53L0X_ERROR_NONE) {
2086
            Status = VL53L0X_GetLimitCheckValue(Dev,
2087
                VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE,
2088
                &SigmaLimitValue);
2089

    
2090
            if ((SigmaLimitValue > 0) &&
2091
                (SigmaEstimate > SigmaLimitValue))
2092
                    /* Limit Fail */
2093
                    SigmaLimitflag = 1;
2094
        }
2095
    }
2096

    
2097
    /*
2098
     * Check if Signal ref clip limit is enabled, if yes then do comparison
2099
     * with limit value and put the result back into pPalRangeStatus.
2100
     */
2101
    if (Status == VL53L0X_ERROR_NONE)
2102
        Status =  VL53L0X_GetLimitCheckEnable(Dev,
2103
                VL53L0X_CHECKENABLE_SIGNAL_REF_CLIP,
2104
                &SignalRefClipLimitCheckEnable);
2105

    
2106
    if ((SignalRefClipLimitCheckEnable != 0) &&
2107
            (Status == VL53L0X_ERROR_NONE)) {
2108

    
2109
        Status = VL53L0X_GetLimitCheckValue(Dev,
2110
                VL53L0X_CHECKENABLE_SIGNAL_REF_CLIP,
2111
                &SignalRefClipValue);
2112

    
2113
        /* Read LastSignalRefMcps from device */
2114
        if (Status == VL53L0X_ERROR_NONE)
2115
            Status = VL53L0X_WrByte(Dev, 0xFF, 0x01);
2116

    
2117
        if (Status == VL53L0X_ERROR_NONE)
2118
            Status = VL53L0X_RdWord(Dev,
2119
                VL53L0X_REG_RESULT_PEAK_SIGNAL_RATE_REF,
2120
                &tmpWord);
2121

    
2122
        if (Status == VL53L0X_ERROR_NONE)
2123
            Status = VL53L0X_WrByte(Dev, 0xFF, 0x00);
2124

    
2125
        LastSignalRefMcps = VL53L0X_FIXPOINT97TOFIXPOINT1616(tmpWord);
2126
        PALDevDataSet(Dev, LastSignalRefMcps, LastSignalRefMcps);
2127

    
2128
        if ((SignalRefClipValue > 0) &&
2129
                (LastSignalRefMcps > SignalRefClipValue)) {
2130
            /* Limit Fail */
2131
            SignalRefClipflag = 1;
2132
        }
2133
    }
2134

    
2135
    /*
2136
     * Check if Signal ref clip limit is enabled, if yes then do comparison
2137
     * with limit value and put the result back into pPalRangeStatus.
2138
     * EffectiveSpadRtnCount has a format 8.8
2139
     * If (Return signal rate < (1.5 x Xtalk x number of Spads)) : FAIL
2140
     */
2141
    if (Status == VL53L0X_ERROR_NONE)
2142
        Status =  VL53L0X_GetLimitCheckEnable(Dev,
2143
                VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD,
2144
                &RangeIgnoreThresholdLimitCheckEnable);
2145

    
2146
    if ((RangeIgnoreThresholdLimitCheckEnable != 0) &&
2147
            (Status == VL53L0X_ERROR_NONE)) {
2148

    
2149
        /* Compute the signal rate per spad */
2150
        if (EffectiveSpadRtnCount == 0) {
2151
            SignalRatePerSpad = 0;
2152
        } else {
2153
            SignalRatePerSpad = (FixPoint1616_t)((256 * SignalRate)
2154
                / EffectiveSpadRtnCount);
2155
        }
2156

    
2157
        Status = VL53L0X_GetLimitCheckValue(Dev,
2158
                VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD,
2159
                &RangeIgnoreThresholdValue);
2160

    
2161
        if ((RangeIgnoreThresholdValue > 0) &&
2162
            (SignalRatePerSpad < RangeIgnoreThresholdValue)) {
2163
            /* Limit Fail add 2^6 to range status */
2164
            RangeIgnoreThresholdflag = 1;
2165
        }
2166
    }
2167

    
2168
    if (Status == VL53L0X_ERROR_NONE) {
2169
        if (NoneFlag == 1) {
2170
            *pPalRangeStatus = 255;         /* NONE */
2171
        } else if (DeviceRangeStatusInternal == 1 ||
2172
                    DeviceRangeStatusInternal == 2 ||
2173
                    DeviceRangeStatusInternal == 3) {
2174
            *pPalRangeStatus = 5; /* HW fail */
2175
        } else if (DeviceRangeStatusInternal == 6 ||
2176
                    DeviceRangeStatusInternal == 9) {
2177
            *pPalRangeStatus = 4;  /* Phase fail */
2178
        } else if (DeviceRangeStatusInternal == 8 ||
2179
                    DeviceRangeStatusInternal == 10 ||
2180
                    SignalRefClipflag == 1) {
2181
            *pPalRangeStatus = 3;  /* Min range */
2182
        } else if (DeviceRangeStatusInternal == 4 ||
2183
                    RangeIgnoreThresholdflag == 1) {
2184
            *pPalRangeStatus = 2;  /* Signal Fail */
2185
        } else if (SigmaLimitflag == 1) {
2186
            *pPalRangeStatus = 1;  /* Sigma         Fail */
2187
        } else {
2188
            *pPalRangeStatus = 0; /* Range Valid */
2189
        }
2190
    }
2191

    
2192
    /* DMAX only relevant during range error */
2193
    if (*pPalRangeStatus == 0)
2194
        pRangingMeasurementData->RangeDMaxMilliMeter = 0;
2195

    
2196
    /* fill the Limit Check Status */
2197

    
2198
    Status =  VL53L0X_GetLimitCheckEnable(Dev,
2199
            VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE,
2200
            &SignalRateFinalRangeLimitCheckEnable);
2201

    
2202
    if (Status == VL53L0X_ERROR_NONE) {
2203
        if ((SigmaLimitCheckEnable == 0) || (SigmaLimitflag == 1))
2204
            Temp8 = 1;
2205
        else
2206
            Temp8 = 0;
2207
        VL53L0X_SETARRAYPARAMETERFIELD(Dev, LimitChecksStatus,
2208
                VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE, Temp8);
2209

    
2210
        if ((DeviceRangeStatusInternal == 4) ||
2211
                (SignalRateFinalRangeLimitCheckEnable == 0))
2212
            Temp8 = 1;
2213
        else
2214
            Temp8 = 0;
2215
        VL53L0X_SETARRAYPARAMETERFIELD(Dev, LimitChecksStatus,
2216
                VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE,
2217
                Temp8);
2218

    
2219
        if ((SignalRefClipLimitCheckEnable == 0) ||
2220
                    (SignalRefClipflag == 1))
2221
            Temp8 = 1;
2222
        else
2223
            Temp8 = 0;
2224

    
2225
        VL53L0X_SETARRAYPARAMETERFIELD(Dev, LimitChecksStatus,
2226
                VL53L0X_CHECKENABLE_SIGNAL_REF_CLIP, Temp8);
2227

    
2228
        if ((RangeIgnoreThresholdLimitCheckEnable == 0) ||
2229
                (RangeIgnoreThresholdflag == 1))
2230
            Temp8 = 1;
2231
        else
2232
            Temp8 = 0;
2233

    
2234
        VL53L0X_SETARRAYPARAMETERFIELD(Dev, LimitChecksStatus,
2235
                VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD,
2236
                Temp8);
2237
    }
2238

    
2239
    LOG_FUNCTION_END(Status);
2240
    return Status;
2241

    
2242
}