Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
vl53l5cx_api.c
Go to the documentation of this file.
1
17#include <stdlib.h>
18#include <string.h>
19#include "vl53l5cx_api.h"
20#include "vl53l5cx_buffers.h"
21
29 uint8_t size,
30 uint8_t pos,
31 uint16_t address,
32 uint8_t mask,
34{
36 uint8_t timeout = 0;
37
38 do {
39 status |= RdMulti(&(p_dev->platform), address,
40 p_dev->temp_buffer, size);
41 status |= WaitMs(&(p_dev->platform), 10);
42
43 if(timeout >= (uint8_t)200) /* 2s timeout */
44 {
46 break;
47 }else if((size >= (uint8_t)4)
48 && (p_dev->temp_buffer[2] >= (uint8_t)0x7f))
49 {
51 break;
52 }
53 else
54 {
55 timeout++;
56 }
57 }while ((p_dev->temp_buffer[pos] & mask) != expected_value);
58
59 return status;
60}
61
62/*
63 * Inner function, not available outside this file. This function is used to
64 * wait for the MCU to boot.
65 */
68{
70 uint16_t timeout = 0;
71
72 do {
73 status |= RdByte(&(p_dev->platform), 0x06, &go2_status0);
74 if((go2_status0 & (uint8_t)0x80) != (uint8_t)0){
75 status |= RdByte(&(p_dev->platform), 0x07, &go2_status1);
77 break;
78 }
79 (void)WaitMs(&(p_dev->platform), 1);
80 timeout++;
81
82 if((go2_status0 & (uint8_t)0x1) != (uint8_t)0){
83 break;
84 }
85
86 }while (timeout < (uint16_t)500);
87
88 return status;
89}
90
98 uint8_t resolution)
99{
103 uint8_t dss_4x4[] = {0x0F, 0x04, 0x04, 0x00, 0x08, 0x10, 0x10, 0x07};
104 uint8_t footer[] = {0x00, 0x00, 0x00, 0x0F, 0x03, 0x01, 0x01, 0xE4};
105 int8_t i, j;
106 uint16_t k;
107
108 (void)memcpy(p_dev->temp_buffer,
109 p_dev->offset_data, VL53L5CX_OFFSET_BUFFER_SIZE);
110
111 /* Data extrapolation is required for 4X4 offset */
112 if(resolution == (uint8_t)VL53L5CX_RESOLUTION_4X4){
113 (void)memcpy(&(p_dev->temp_buffer[0x10]), dss_4x4, sizeof(dss_4x4));
115 (void)memcpy(signal_grid,&(p_dev->temp_buffer[0x3C]),
116 sizeof(signal_grid));
117 (void)memcpy(range_grid,&(p_dev->temp_buffer[0x140]),
118 sizeof(range_grid));
119
120 for (j = 0; j < (int8_t)4; j++)
121 {
122 for (i = 0; i < (int8_t)4 ; i++)
123 {
124 signal_grid[i+(4*j)] =
125 (signal_grid[(2*i)+(16*j)+ (int8_t)0]
126 + signal_grid[(2*i)+(16*j)+(int8_t)1]
127 + signal_grid[(2*i)+(16*j)+(int8_t)8]
128 + signal_grid[(2*i)+(16*j)+(int8_t)9])
129 /(uint32_t)4;
130 range_grid[i+(4*j)] =
131 (range_grid[(2*i)+(16*j)]
132 + range_grid[(2*i)+(16*j)+1]
133 + range_grid[(2*i)+(16*j)+8]
134 + range_grid[(2*i)+(16*j)+9])
135 /(int16_t)4;
136 }
137 }
138 (void)memset(&range_grid[0x10], 0, (uint16_t)96);
139 (void)memset(&signal_grid[0x10], 0, (uint16_t)192);
140 (void)memcpy(&(p_dev->temp_buffer[0x3C]),
141 signal_grid, sizeof(signal_grid));
142 (void)memcpy(&(p_dev->temp_buffer[0x140]),
143 range_grid, sizeof(range_grid));
145 }
146
147 for(k = 0; k < (VL53L5CX_OFFSET_BUFFER_SIZE - (uint16_t)4); k++)
148 {
149 p_dev->temp_buffer[k] = p_dev->temp_buffer[k + (uint16_t)8];
150 }
151
152 (void)memcpy(&(p_dev->temp_buffer[0x1E0]), footer, 8);
153 status |= WrMulti(&(p_dev->platform), 0x2e18, p_dev->temp_buffer,
156 VL53L5CX_UI_CMD_STATUS, 0xff, 0x03);
157
158 return status;
159}
160
168 uint8_t resolution)
169{
171 uint8_t res4x4[] = {0x0F, 0x04, 0x04, 0x17, 0x08, 0x10, 0x10, 0x07};
172 uint8_t dss_4x4[] = {0x00, 0x78, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08};
173 uint8_t profile_4x4[] = {0xA0, 0xFC, 0x01, 0x00};
175 int8_t i, j;
176
177 (void)memcpy(p_dev->temp_buffer, &(p_dev->xtalk_data[0]),
179
180 /* Data extrapolation is required for 4X4 Xtalk */
181 if(resolution == (uint8_t)VL53L5CX_RESOLUTION_4X4)
182 {
183 (void)memcpy(&(p_dev->temp_buffer[0x8]),
184 res4x4, sizeof(res4x4));
185 (void)memcpy(&(p_dev->temp_buffer[0x020]),
186 dss_4x4, sizeof(dss_4x4));
187
189 (void)memcpy(signal_grid, &(p_dev->temp_buffer[0x34]),
190 sizeof(signal_grid));
191
192 for (j = 0; j < (int8_t)4; j++)
193 {
194 for (i = 0; i < (int8_t)4 ; i++)
195 {
196 signal_grid[i+(4*j)] =
197 (signal_grid[(2*i)+(16*j)+0]
198 + signal_grid[(2*i)+(16*j)+1]
199 + signal_grid[(2*i)+(16*j)+8]
200 + signal_grid[(2*i)+(16*j)+9])/(uint32_t)4;
201 }
202 }
203 (void)memset(&signal_grid[0x10], 0, (uint32_t)192);
204 (void)memcpy(&(p_dev->temp_buffer[0x34]),
205 signal_grid, sizeof(signal_grid));
207 (void)memcpy(&(p_dev->temp_buffer[0x134]),
208 profile_4x4, sizeof(profile_4x4));
209 (void)memset(&(p_dev->temp_buffer[0x078]),0 ,
210 (uint32_t)4*sizeof(uint8_t));
211 }
212
213 status |= WrMulti(&(p_dev->platform), 0x2cf8,
214 p_dev->temp_buffer, VL53L5CX_XTALK_BUFFER_SIZE);
216 VL53L5CX_UI_CMD_STATUS, 0xff, 0x03);
217
218 return status;
219}
220
224{
227
228 status |= WrByte(&(p_dev->platform), 0x7fff, 0x00);
229 status |= RdByte(&(p_dev->platform), 0, &device_id);
230 status |= RdByte(&(p_dev->platform), 1, &revision_id);
231 status |= WrByte(&(p_dev->platform), 0x7fff, 0x02);
232
233 if((device_id == (uint8_t)0xF0) && (revision_id == (uint8_t)0x02))
234 {
235 *p_is_alive = 1;
236 }
237 else
238 {
239 *p_is_alive = 0;
240 }
241
242 return status;
243}
244
247{
249 uint8_t pipe_ctrl[] = {VL53L5CX_NB_TARGET_PER_ZONE, 0x00, 0x01, 0x00};
250 uint32_t single_range = 0x01;
251
252 p_dev->default_xtalk = (uint8_t*)VL53L5CX_DEFAULT_XTALK;
253 p_dev->default_configuration = (uint8_t*)VL53L5CX_DEFAULT_CONFIGURATION;
254 p_dev->is_auto_stop_enabled = (uint8_t)0x0;
255
256 /* SW reboot sequence */
257 status |= WrByte(&(p_dev->platform), 0x7fff, 0x00);
258 status |= WrByte(&(p_dev->platform), 0x0009, 0x04);
259 status |= WrByte(&(p_dev->platform), 0x000F, 0x40);
260 status |= WrByte(&(p_dev->platform), 0x000A, 0x03);
261 status |= RdByte(&(p_dev->platform), 0x7FFF, &tmp);
262 status |= WrByte(&(p_dev->platform), 0x000C, 0x01);
263
264 status |= WrByte(&(p_dev->platform), 0x0101, 0x00);
265 status |= WrByte(&(p_dev->platform), 0x0102, 0x00);
266 status |= WrByte(&(p_dev->platform), 0x010A, 0x01);
267 status |= WrByte(&(p_dev->platform), 0x4002, 0x01);
268 status |= WrByte(&(p_dev->platform), 0x4002, 0x00);
269 status |= WrByte(&(p_dev->platform), 0x010A, 0x03);
270 status |= WrByte(&(p_dev->platform), 0x0103, 0x01);
271 status |= WrByte(&(p_dev->platform), 0x000C, 0x00);
272 status |= WrByte(&(p_dev->platform), 0x000F, 0x43);
273 status |= WaitMs(&(p_dev->platform), 1);
274
275 status |= WrByte(&(p_dev->platform), 0x000F, 0x40);
276 status |= WrByte(&(p_dev->platform), 0x000A, 0x01);
277 status |= WaitMs(&(p_dev->platform), 100);
278
279 /* Wait for sensor booted (several ms required to get sensor ready ) */
280 status |= WrByte(&(p_dev->platform), 0x7fff, 0x00);
281 status |= _vl53l5cx_poll_for_answer(p_dev, 1, 0, 0x06, 0xff, 1);
282 if(status != (uint8_t)0){
283 goto exit;
284 }
285
286 status |= WrByte(&(p_dev->platform), 0x000E, 0x01);
287 status |= WrByte(&(p_dev->platform), 0x7fff, 0x02);
288
289 /* Enable FW access */
290 status |= WrByte(&(p_dev->platform), 0x03, 0x0D);
291 status |= WrByte(&(p_dev->platform), 0x7fff, 0x01);
292 status |= _vl53l5cx_poll_for_answer(p_dev, 1, 0, 0x21, 0x10, 0x10);
293 status |= WrByte(&(p_dev->platform), 0x7fff, 0x00);
294
295 /* Enable host access to GO1 */
296 status |= RdByte(&(p_dev->platform), 0x7fff, &tmp);
297 status |= WrByte(&(p_dev->platform), 0x0C, 0x01);
298
299 /* Power ON status */
300 status |= WrByte(&(p_dev->platform), 0x7fff, 0x00);
301 status |= WrByte(&(p_dev->platform), 0x101, 0x00);
302 status |= WrByte(&(p_dev->platform), 0x102, 0x00);
303 status |= WrByte(&(p_dev->platform), 0x010A, 0x01);
304 status |= WrByte(&(p_dev->platform), 0x4002, 0x01);
305 status |= WrByte(&(p_dev->platform), 0x4002, 0x00);
306 status |= WrByte(&(p_dev->platform), 0x010A, 0x03);
307 status |= WrByte(&(p_dev->platform), 0x103, 0x01);
308 status |= WrByte(&(p_dev->platform), 0x400F, 0x00);
309 status |= WrByte(&(p_dev->platform), 0x21A, 0x43);
310 status |= WrByte(&(p_dev->platform), 0x21A, 0x03);
311 status |= WrByte(&(p_dev->platform), 0x21A, 0x01);
312 status |= WrByte(&(p_dev->platform), 0x21A, 0x00);
313 status |= WrByte(&(p_dev->platform), 0x219, 0x00);
314 status |= WrByte(&(p_dev->platform), 0x21B, 0x00);
315
316 /* Wake up MCU */
317 status |= WrByte(&(p_dev->platform), 0x7fff, 0x00);
318 status |= RdByte(&(p_dev->platform), 0x7fff, &tmp);
319 status |= WrByte(&(p_dev->platform), 0x0C, 0x00);
320 status |= WrByte(&(p_dev->platform), 0x7fff, 0x01);
321 status |= WrByte(&(p_dev->platform), 0x20, 0x07);
322 status |= WrByte(&(p_dev->platform), 0x20, 0x06);
323
324 /* Download FW into VL53L5 */
325 status |= WrByte(&(p_dev->platform), 0x7fff, 0x09);
326 status |= WrMulti(&(p_dev->platform),0,
327 (uint8_t*)&VL53L5CX_FIRMWARE[0],0x8000);
328 status |= WrByte(&(p_dev->platform), 0x7fff, 0x0a);
329 status |= WrMulti(&(p_dev->platform),0,
330 (uint8_t*)&VL53L5CX_FIRMWARE[0x8000],0x8000);
331 status |= WrByte(&(p_dev->platform), 0x7fff, 0x0b);
332 status |= WrMulti(&(p_dev->platform),0,
333 (uint8_t*)&VL53L5CX_FIRMWARE[0x10000],0x5000);
334 status |= WrByte(&(p_dev->platform), 0x7fff, 0x01);
335
336 /* Check if FW correctly downloaded */
337 status |= WrByte(&(p_dev->platform), 0x7fff, 0x02);
338 status |= WrByte(&(p_dev->platform), 0x03, 0x0D);
339 status |= WrByte(&(p_dev->platform), 0x7fff, 0x01);
340 status |= _vl53l5cx_poll_for_answer(p_dev, 1, 0, 0x21, 0x10, 0x10);
341 if(status != (uint8_t)0){
342 goto exit;
343 }
344
345 status |= WrByte(&(p_dev->platform), 0x7fff, 0x00);
346 status |= RdByte(&(p_dev->platform), 0x7fff, &tmp);
347 status |= WrByte(&(p_dev->platform), 0x0C, 0x01);
348
349 /* Reset MCU and wait boot */
350 status |= WrByte(&(p_dev->platform), 0x7FFF, 0x00);
351 status |= WrByte(&(p_dev->platform), 0x114, 0x00);
352 status |= WrByte(&(p_dev->platform), 0x115, 0x00);
353 status |= WrByte(&(p_dev->platform), 0x116, 0x42);
354 status |= WrByte(&(p_dev->platform), 0x117, 0x00);
355 status |= WrByte(&(p_dev->platform), 0x0B, 0x00);
356 status |= RdByte(&(p_dev->platform), 0x7fff, &tmp);
357 status |= WrByte(&(p_dev->platform), 0x0C, 0x00);
358 status |= WrByte(&(p_dev->platform), 0x0B, 0x01);
360 if(status != (uint8_t)0){
361 goto exit;
362 }
363
364 status |= WrByte(&(p_dev->platform), 0x7fff, 0x02);
365
366 /* Get offset NVM data and store them into the offset buffer */
367 status |= WrMulti(&(p_dev->platform), 0x2fd8,
370 VL53L5CX_UI_CMD_STATUS, 0xff, 2);
371 status |= RdMulti(&(p_dev->platform), VL53L5CX_UI_CMD_START,
372 p_dev->temp_buffer, VL53L5CX_NVM_DATA_SIZE);
373 (void)memcpy(p_dev->offset_data, p_dev->temp_buffer,
376
377 /* Set default Xtalk shape. Send Xtalk to sensor */
381
382 /* Send default configuration to VL53L5CX firmware */
383 status |= WrMulti(&(p_dev->platform), 0x2c34,
384 p_dev->default_configuration,
387 VL53L5CX_UI_CMD_STATUS, 0xff, 0x03);
388
391#if VL53L5CX_NB_TARGET_PER_ZONE != 1
395 (uint8_t*)&tmp, 1, 0x0C);
396#endif
397
400 (uint16_t)sizeof(single_range));
401
402 tmp = (uint8_t)1;
404 VL53L5CX_GLARE_FILTER, 40, (uint8_t*)&tmp, 1, 0x26);
406 VL53L5CX_GLARE_FILTER, 40, (uint8_t*)&tmp, 1, 0x25);
407
408exit:
409 return status;
410}
411
415{
417
418 status |= WrByte(&(p_dev->platform), 0x7fff, 0x00);
419 status |= WrByte(&(p_dev->platform), 0x4, (uint8_t)(i2c_address >> 1));
420 p_dev->platform.address = i2c_address;
421 status |= WrByte(&(p_dev->platform), 0x7fff, 0x02);
422
423 return status;
424}
425
429{
431
432 status |= WrByte(&(p_dev->platform), 0x7FFF, 0x00);
433 status |= RdByte(&(p_dev->platform), 0x009, &tmp);
434
435 switch(tmp)
436 {
437 case 0x4:
439 break;
440 case 0x2:
442
443 break;
444 default:
445 *p_power_mode = 0;
447 break;
448 }
449
450 status |= WrByte(&(p_dev->platform), 0x7FFF, 0x02);
451
452 return status;
453}
454
458{
460
463 {
464 switch(power_mode)
465 {
467 status |= WrByte(&(p_dev->platform), 0x7FFF, 0x00);
468 status |= WrByte(&(p_dev->platform), 0x09, 0x04);
470 p_dev, 1, 0, 0x06, 0x01, 1);
471 break;
472
474 status |= WrByte(&(p_dev->platform), 0x7FFF, 0x00);
475 status |= WrByte(&(p_dev->platform), 0x09, 0x02);
477 p_dev, 1, 0, 0x06, 0x01, 0);
478 break;
479
480 default:
482 break;
483 }
484 status |= WrByte(&(p_dev->platform), 0x7FFF, 0x02);
485 }
486
487 return status;
488}
489
492{
493 uint8_t resolution, status = VL53L5CX_STATUS_OK;
495 uint32_t i;
496 uint32_t header_config[2] = {0, 0};
497
498 union Block_header *bh_ptr;
499 uint8_t cmd[] = {0x00, 0x03, 0x00, 0x00};
500
501 status |= vl53l5cx_get_resolution(p_dev, &resolution);
502 p_dev->data_read_size = 0;
503 p_dev->streamcount = 255;
504
505 /* Enable mandatory output (meta and common data) */
507 0x00000007U,
508 0x00000000U,
509 0x00000000U,
510 0xC0000000U};
511
512 /* Send addresses of possible output */
525
526 /* Enable selected outputs in the 'platform.h' file */
527#ifndef VL53L5CX_DISABLE_AMBIENT_PER_SPAD
528 output_bh_enable[0] += (uint32_t)8;
529#endif
530#ifndef VL53L5CX_DISABLE_NB_SPADS_ENABLED
531 output_bh_enable[0] += (uint32_t)16;
532#endif
533#ifndef VL53L5CX_DISABLE_NB_TARGET_DETECTED
534 output_bh_enable[0] += (uint32_t)32;
535#endif
536#ifndef VL53L5CX_DISABLE_SIGNAL_PER_SPAD
537 output_bh_enable[0] += (uint32_t)64;
538#endif
539#ifndef VL53L5CX_DISABLE_RANGE_SIGMA_MM
540 output_bh_enable[0] += (uint32_t)128;
541#endif
542#ifndef VL53L5CX_DISABLE_DISTANCE_MM
543 output_bh_enable[0] += (uint32_t)256;
544#endif
545#ifndef VL53L5CX_DISABLE_REFLECTANCE_PERCENT
546 output_bh_enable[0] += (uint32_t)512;
547#endif
548#ifndef VL53L5CX_DISABLE_TARGET_STATUS
549 output_bh_enable[0] += (uint32_t)1024;
550#endif
551#ifndef VL53L5CX_DISABLE_MOTION_INDICATOR
552 output_bh_enable[0] += (uint32_t)2048;
553#endif
554
555 /* Update data size */
556 for (i = 0; i < (uint32_t)(sizeof(output)/sizeof(uint32_t)); i++)
557 {
558 if ((output[i] == (uint8_t)0)
559 || ((output_bh_enable[i/(uint32_t)32]
560 &((uint32_t)1 << (i%(uint32_t)32))) == (uint32_t)0))
561 {
562 continue;
563 }
564
565 bh_ptr = (union Block_header *)&(output[i]);
566 if (((uint8_t)bh_ptr->type >= (uint8_t)0x1)
567 && ((uint8_t)bh_ptr->type < (uint8_t)0x0d))
568 {
569 if ((bh_ptr->idx >= (uint16_t)0x54d0)
570 && (bh_ptr->idx < (uint16_t)(0x54d0 + 960)))
571 {
572 bh_ptr->size = resolution;
573 }
574 else
575 {
576 bh_ptr->size = (uint16_t)((uint16_t)resolution
578 }
579 p_dev->data_read_size += bh_ptr->type * bh_ptr->size;
580 }
581 else
582 {
583 p_dev->data_read_size += bh_ptr->size;
584 }
585 p_dev->data_read_size += (uint32_t)4;
586 }
587 p_dev->data_read_size += (uint32_t)24;
588
591 (uint16_t)sizeof(output));
592
593 header_config[0] = p_dev->data_read_size;
594 header_config[1] = i + (uint32_t)1;
595
598 (uint16_t)sizeof(header_config));
599
602 (uint16_t)sizeof(output_bh_enable));
603
604 /* Start xshut bypass (interrupt mode) */
605 status |= WrByte(&(p_dev->platform), 0x7fff, 0x00);
606 status |= WrByte(&(p_dev->platform), 0x09, 0x05);
607 status |= WrByte(&(p_dev->platform), 0x7fff, 0x02);
608
609 /* Start ranging session */
610 status |= WrMulti(&(p_dev->platform), VL53L5CX_UI_CMD_END -
611 (uint16_t)(4 - 1), (uint8_t*)cmd, sizeof(cmd));
613 VL53L5CX_UI_CMD_STATUS, 0xff, 0x03);
614
615 /* Read ui range data content and compare if data size is the correct one */
617 (uint8_t*)p_dev->temp_buffer, 0x5440, 12);
618 (void)memcpy(&tmp, &(p_dev->temp_buffer[0x8]), sizeof(tmp));
619 if(tmp != p_dev->data_read_size)
620 {
622 }
623
624 return status;
625}
626
629{
631 uint16_t timeout = 0;
633
634 status |= RdMulti(&(p_dev->platform),
635 0x2FFC, (uint8_t*)&auto_stop_flag, 4);
636 if((auto_stop_flag != (uint32_t)0x4FF)
637 && (p_dev->is_auto_stop_enabled == (uint8_t)0))
638 {
639 status |= WrByte(&(p_dev->platform), 0x7fff, 0x00);
640
641 /* Provoke MCU stop */
642 status |= WrByte(&(p_dev->platform), 0x15, 0x16);
643 status |= WrByte(&(p_dev->platform), 0x14, 0x01);
644
645 /* Poll for G02 status 0 MCU stop */
646 while(((tmp & (uint8_t)0x80) >> 7) == (uint8_t)0x00)
647 {
648 status |= RdByte(&(p_dev->platform), 0x6, &tmp);
649 status |= WaitMs(&(p_dev->platform), 10);
650 timeout++; /* Timeout reached after 5 seconds */
651
652 if(timeout > (uint16_t)500)
653 {
654 status |= tmp;
655 break;
656 }
657 }
658 }
659
660 /* Check GO2 status 1 if status is still OK */
661 status |= RdByte(&(p_dev->platform), 0x6, &tmp);
662 if((tmp & (uint8_t)0x80) != (uint8_t)0){
663 status |= RdByte(&(p_dev->platform), 0x7, &tmp);
664 if((tmp != (uint8_t)0x84) && (tmp != (uint8_t)0x85)){
665 status |= tmp;
666 }
667 }
668
669 /* Undo MCU stop */
670 status |= WrByte(&(p_dev->platform), 0x7fff, 0x00);
671 status |= WrByte(&(p_dev->platform), 0x14, 0x00);
672 status |= WrByte(&(p_dev->platform), 0x15, 0x00);
673
674 /* Stop xshut bypass */
675 status |= WrByte(&(p_dev->platform), 0x09, 0x04);
676 status |= WrByte(&(p_dev->platform), 0x7fff, 0x02);
677
678 return status;
679}
680
684{
686
687 status |= RdMulti(&(p_dev->platform), 0x0, p_dev->temp_buffer, 4);
688
689 if((p_dev->temp_buffer[0] != p_dev->streamcount)
690 && (p_dev->temp_buffer[0] != (uint8_t)255)
691 && (p_dev->temp_buffer[1] == (uint8_t)0x5)
692 && ((p_dev->temp_buffer[2] & (uint8_t)0x5) == (uint8_t)0x5)
693 && ((p_dev->temp_buffer[3] & (uint8_t)0x10) ==(uint8_t)0x10)
694 )
695 {
696 *p_isReady = (uint8_t)1;
697 p_dev->streamcount = p_dev->temp_buffer[0];
698 }
699 else
700 {
701 if ((p_dev->temp_buffer[3] & (uint8_t)0x80) != (uint8_t)0)
702 {
703 status |= p_dev->temp_buffer[2]; /* Return GO2 error status */
704 }
705
706 *p_isReady = 0;
707 }
708
709 return status;
710}
711
715{
717 union Block_header *bh_ptr;
719 uint32_t i, j, msize;
720
721 status |= RdMulti(&(p_dev->platform), 0x0,
722 p_dev->temp_buffer, p_dev->data_read_size);
723 p_dev->streamcount = p_dev->temp_buffer[0];
724 SwapBuffer(p_dev->temp_buffer, (uint16_t)p_dev->data_read_size);
725
726 /* Start conversion at position 16 to avoid headers */
727 for (i = (uint32_t)16; i
728 < (uint32_t)p_dev->data_read_size; i+=(uint32_t)4)
729 {
730 bh_ptr = (union Block_header *)&(p_dev->temp_buffer[i]);
731 if ((bh_ptr->type > (uint32_t)0x1)
732 && (bh_ptr->type < (uint32_t)0xd))
733 {
734 msize = bh_ptr->type * bh_ptr->size;
735 }
736 else
737 {
738 msize = bh_ptr->size;
739 }
740
741 switch(bh_ptr->idx){
743 p_results->silicon_temp_degc =
744 (int8_t)p_dev->temp_buffer[i + (uint32_t)12];
745 break;
746
747#ifndef VL53L5CX_DISABLE_AMBIENT_PER_SPAD
749 (void)memcpy(p_results->ambient_per_spad,
750 &(p_dev->temp_buffer[i + (uint32_t)4]), msize);
751 break;
752#endif
753#ifndef VL53L5CX_DISABLE_NB_SPADS_ENABLED
755 (void)memcpy(p_results->nb_spads_enabled,
756 &(p_dev->temp_buffer[i + (uint32_t)4]), msize);
757 break;
758#endif
759#ifndef VL53L5CX_DISABLE_NB_TARGET_DETECTED
761 (void)memcpy(p_results->nb_target_detected,
762 &(p_dev->temp_buffer[i + (uint32_t)4]), msize);
763 break;
764#endif
765#ifndef VL53L5CX_DISABLE_SIGNAL_PER_SPAD
767 (void)memcpy(p_results->signal_per_spad,
768 &(p_dev->temp_buffer[i + (uint32_t)4]), msize);
769 break;
770#endif
771#ifndef VL53L5CX_DISABLE_RANGE_SIGMA_MM
773 (void)memcpy(p_results->range_sigma_mm,
774 &(p_dev->temp_buffer[i + (uint32_t)4]), msize);
775 break;
776#endif
777#ifndef VL53L5CX_DISABLE_DISTANCE_MM
779 (void)memcpy(p_results->distance_mm,
780 &(p_dev->temp_buffer[i + (uint32_t)4]), msize);
781 break;
782#endif
783#ifndef VL53L5CX_DISABLE_REFLECTANCE_PERCENT
785 (void)memcpy(p_results->reflectance,
786 &(p_dev->temp_buffer[i + (uint32_t)4]), msize);
787 break;
788#endif
789#ifndef VL53L5CX_DISABLE_TARGET_STATUS
791 (void)memcpy(p_results->target_status,
792 &(p_dev->temp_buffer[i + (uint32_t)4]), msize);
793 break;
794#endif
795#ifndef VL53L5CX_DISABLE_MOTION_INDICATOR
797 (void)memcpy(&p_results->motion_indicator,
798 &(p_dev->temp_buffer[i + (uint32_t)4]), msize);
799 break;
800#endif
801 default:
802 break;
803 }
804 i += msize;
805 }
806
807#ifndef VL53L5CX_USE_RAW_FORMAT
808
809 /* Convert data into their real format */
810#ifndef VL53L5CX_DISABLE_AMBIENT_PER_SPAD
811 for(i = 0; i < (uint32_t)VL53L5CX_RESOLUTION_8X8; i++)
812 {
813 p_results->ambient_per_spad[i] /= (uint32_t)2048;
814 }
815#endif
816
817 for(i = 0; i < (uint32_t)(VL53L5CX_RESOLUTION_8X8
819 {
820#ifndef VL53L5CX_DISABLE_DISTANCE_MM
821 p_results->distance_mm[i] /= 4;
822 if(p_results->distance_mm[i] < 0)
823 {
824 p_results->distance_mm[i] = 0;
825 }
826#endif
827#ifndef VL53L5CX_DISABLE_REFLECTANCE_PERCENT
828 p_results->reflectance[i] /= (uint8_t)2;
829#endif
830#ifndef VL53L5CX_DISABLE_RANGE_SIGMA_MM
831 p_results->range_sigma_mm[i] /= (uint16_t)128;
832#endif
833#ifndef VL53L5CX_DISABLE_SIGNAL_PER_SPAD
834 p_results->signal_per_spad[i] /= (uint32_t)2048;
835#endif
836 }
837
838 /* Set target status to 255 if no target is detected for this zone */
839#ifndef VL53L5CX_DISABLE_NB_TARGET_DETECTED
840 for(i = 0; i < (uint32_t)VL53L5CX_RESOLUTION_8X8; i++)
841 {
842 if(p_results->nb_target_detected[i] == (uint8_t)0){
843 for(j = 0; j < (uint32_t)
845 {
846#ifndef VL53L5CX_DISABLE_TARGET_STATUS
847 p_results->target_status
849 *(uint32_t)i) + j]=(uint8_t)255;
850#endif
851 }
852 }
853 }
854#endif
855
856#ifndef VL53L5CX_DISABLE_MOTION_INDICATOR
857 for(i = 0; i < (uint32_t)32; i++)
858 {
859 p_results->motion_indicator.motion[i] /= (uint32_t)65535;
860 }
861#endif
862
863#endif
864
865 /* Check if footer id and header id are matching. This allows to detect
866 * corrupted frames */
867 header_id = ((uint16_t)(p_dev->temp_buffer[0x8])<<8) & 0xFF00U;
868 header_id |= ((uint16_t)(p_dev->temp_buffer[0x9])) & 0x00FFU;
869
870 footer_id = ((uint16_t)(p_dev->temp_buffer[p_dev->data_read_size
871 - (uint32_t)4]) << 8) & 0xFF00U;
872 footer_id |= ((uint16_t)(p_dev->temp_buffer[p_dev->data_read_size
873 - (uint32_t)3])) & 0xFFU;
874
875 if(header_id != footer_id)
876 {
878 }
879
880 return status;
881}
882
886{
888
889 status |= vl53l5cx_dci_read_data(p_dev, p_dev->temp_buffer,
891 *p_resolution = p_dev->temp_buffer[0x00]*p_dev->temp_buffer[0x01];
892
893 return status;
894}
895
896
897
900 uint8_t resolution)
901{
903
904 switch(resolution){
907 p_dev->temp_buffer,
909 p_dev->temp_buffer[0x04] = 64;
910 p_dev->temp_buffer[0x06] = 64;
911 p_dev->temp_buffer[0x09] = 4;
913 p_dev->temp_buffer,
915
917 p_dev->temp_buffer,
919 p_dev->temp_buffer[0x00] = 4;
920 p_dev->temp_buffer[0x01] = 4;
921 p_dev->temp_buffer[0x04] = 8;
922 p_dev->temp_buffer[0x05] = 8;
924 p_dev->temp_buffer,
926 break;
927
930 p_dev->temp_buffer,
932 p_dev->temp_buffer[0x04] = 16;
933 p_dev->temp_buffer[0x06] = 16;
934 p_dev->temp_buffer[0x09] = 1;
936 p_dev->temp_buffer,
938
940 p_dev->temp_buffer,
942 p_dev->temp_buffer[0x00] = 8;
943 p_dev->temp_buffer[0x01] = 8;
944 p_dev->temp_buffer[0x04] = 4;
945 p_dev->temp_buffer[0x05] = 4;
947 p_dev->temp_buffer,
949
950 break;
951
952 default:
954 break;
955 }
956
958 status |= _vl53l5cx_send_xtalk_data(p_dev, resolution);
959
960 return status;
961}
962
975
978 uint8_t frequency_hz)
979{
981
984 (uint8_t*)&frequency_hz, 1, 0x01);
985
986 return status;
987}
988
992{
994
997
998 (void)memcpy(p_time_ms, &(p_dev->temp_buffer[0x0]), 4);
999 *p_time_ms /= (uint32_t)1000;
1000
1001 return status;
1002}
1003
1007{
1010
1011 /* Integration time must be between 2ms and 1000ms */
1012 if((integration < (uint32_t)2)
1013 || (integration > (uint32_t)1000))
1014 {
1016 }else
1017 {
1018 integration *= (uint32_t)1000;
1019
1022 (uint8_t*)&integration, 4, 0x00);
1023 }
1024
1025 return status;
1026}
1027
1031{
1033
1034 status |= vl53l5cx_dci_read_data(p_dev,p_dev->temp_buffer,
1036
1037 *p_sharpener_percent = (p_dev->temp_buffer[0xD]
1038 *(uint8_t)100)/(uint8_t)255;
1039
1040 return status;
1041}
1042
1046{
1049
1050 if(sharpener_percent >= (uint8_t)100)
1051 {
1053 }
1054 else
1055 {
1059 (uint8_t*)&sharpener, 1, 0xD);
1060 }
1061
1062 return status;
1063}
1064
1077
1097
1101{
1103
1104 status |= vl53l5cx_dci_read_data(p_dev, p_dev->temp_buffer,
1106
1107 if(p_dev->temp_buffer[0x01] == (uint8_t)0x1)
1108 {
1110 }
1111 else
1112 {
1114 }
1115
1116 return status;
1117}
1118
1122{
1124 uint32_t single_range = 0x00;
1125
1126 status |= vl53l5cx_dci_read_data(p_dev, p_dev->temp_buffer,
1128
1129 switch(ranging_mode)
1130 {
1132 p_dev->temp_buffer[0x01] = 0x1;
1133 p_dev->temp_buffer[0x03] = 0x3;
1134 single_range = 0x00;
1135 break;
1136
1138 p_dev->temp_buffer[0x01] = 0x3;
1139 p_dev->temp_buffer[0x03] = 0x2;
1140 single_range = 0x01;
1141 break;
1142
1143 default:
1145 break;
1146 }
1147
1148 status |= vl53l5cx_dci_write_data(p_dev, p_dev->temp_buffer,
1150
1153 (uint16_t)sizeof(single_range));
1154
1155 return status;
1156}
1157
1175
1193
1196 uint8_t *data,
1197 uint32_t index,
1199{
1200 int16_t i;
1203 uint8_t cmd[] = {0x00, 0x00, 0x00, 0x00,
1204 0x00, 0x00, 0x00, 0x0f,
1205 0x00, 0x02, 0x00, 0x08};
1206
1207 /* Check if tmp buffer is large enough */
1209 {
1211 }
1212 else
1213 {
1214 cmd[0] = (uint8_t)(index >> 8);
1215 cmd[1] = (uint8_t)(index & (uint32_t)0xff);
1216 cmd[2] = (uint8_t)((data_size & (uint16_t)0xff0) >> 4);
1217 cmd[3] = (uint8_t)((data_size & (uint16_t)0xf) << 4);
1218
1219 /* Request data reading from FW */
1220 status |= WrMulti(&(p_dev->platform),
1221 (VL53L5CX_UI_CMD_END-(uint16_t)11),cmd, sizeof(cmd));
1224 0xff, 0x03);
1225
1226 /* Read new data sent (4 bytes header + data_size + 8 bytes footer) */
1227 status |= RdMulti(&(p_dev->platform), VL53L5CX_UI_CMD_START,
1228 p_dev->temp_buffer, rd_size);
1229 SwapBuffer(p_dev->temp_buffer, data_size + (uint16_t)12);
1230
1231 /* Copy data from FW into input structure (-4 bytes to remove header) */
1232 for(i = 0 ; i < (int16_t)data_size;i++){
1233 data[i] = p_dev->temp_buffer[i + 4];
1234 }
1235 }
1236
1237 return status;
1238}
1239
1242 uint8_t *data,
1243 uint32_t index,
1245{
1247 int16_t i;
1248
1249 uint8_t headers[] = {0x00, 0x00, 0x00, 0x00};
1250 uint8_t footer[] = {0x00, 0x00, 0x00, 0x0f, 0x05, 0x01,
1251 (uint8_t)((data_size + (uint16_t)8) >> 8),
1252 (uint8_t)((data_size + (uint16_t)8) & (uint8_t)0xFF)};
1253
1255 (data_size + (uint16_t)12) + (uint16_t)1;
1256
1257 /* Check if cmd buffer is large enough */
1258 if((data_size + (uint16_t)12)
1260 {
1262 }
1263 else
1264 {
1265 headers[0] = (uint8_t)(index >> 8);
1266 headers[1] = (uint8_t)(index & (uint32_t)0xff);
1267 headers[2] = (uint8_t)(((data_size & (uint16_t)0xff0) >> 4));
1268 headers[3] = (uint8_t)((data_size & (uint16_t)0xf) << 4);
1269
1270 /* Copy data from structure to FW format (+4 bytes to add header) */
1271 SwapBuffer(data, data_size);
1272 for(i = (int16_t)data_size - (int16_t)1 ; i >= 0; i--)
1273 {
1274 p_dev->temp_buffer[i + 4] = data[i];
1275 }
1276
1277 /* Add headers and footer */
1278 (void)memcpy(&p_dev->temp_buffer[0], headers, sizeof(headers));
1279 (void)memcpy(&p_dev->temp_buffer[data_size + (uint16_t)4],
1280 footer, sizeof(footer));
1281
1282 /* Send data to FW */
1283 status |= WrMulti(&(p_dev->platform),address,
1284 p_dev->temp_buffer,
1287 VL53L5CX_UI_CMD_STATUS, 0xff, 0x03);
1288
1289 SwapBuffer(data, data_size);
1290 }
1291
1292 return status;
1293}
1294
static uint8_t status
uint16_t foo
Definition main_demo5.c:58
static float timeout
unsigned short uint16_t
Typedef defining 16 bit unsigned short type.
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
short int16_t
Typedef defining 16 bit short type.
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.
signed char int8_t
Typedef defining 8 bit char type.
uint8_t vl53l5cx_get_power_mode(VL53L5CX_Configuration *p_dev, uint8_t *p_power_mode)
This function is used to get the current sensor power mode.
uint8_t vl53l5cx_dci_read_data(VL53L5CX_Configuration *p_dev, uint8_t *data, uint32_t index, uint16_t data_size)
This function can be used to read 'extra data' from DCI.
uint8_t vl53l5cx_set_i2c_address(VL53L5CX_Configuration *p_dev, uint16_t i2c_address)
This function is used to change the I2C address of the sensor.
uint8_t vl53l5cx_disable_internal_cp(VL53L5CX_Configuration *p_dev)
This function is used to disable the VCSEL charge pump This optimizes the power consumption of the de...
uint8_t vl53l5cx_set_ranging_frequency_hz(VL53L5CX_Configuration *p_dev, uint8_t frequency_hz)
This function sets a new ranging frequency in Hz.
uint8_t vl53l5cx_get_ranging_mode(VL53L5CX_Configuration *p_dev, uint8_t *p_ranging_mode)
This function is used to get the ranging mode.
uint8_t vl53l5cx_get_sharpener_percent(VL53L5CX_Configuration *p_dev, uint8_t *p_sharpener_percent)
This function gets the current sharpener in percent.
uint8_t vl53l5cx_is_alive(VL53L5CX_Configuration *p_dev, uint8_t *p_is_alive)
uint8_t vl53l5cx_set_power_mode(VL53L5CX_Configuration *p_dev, uint8_t power_mode)
This function is used to set the sensor in Low Power mode, for example if the sensor is not used duri...
uint8_t vl53l5cx_set_integration_time_ms(VL53L5CX_Configuration *p_dev, uint32_t integration_time_ms)
This function sets a new integration time in ms.
static uint8_t _vl53l5cx_send_offset_data(VL53L5CX_Configuration *p_dev, uint8_t resolution)
Inner function, not available outside this file.
uint8_t vl53l5cx_dci_replace_data(VL53L5CX_Configuration *p_dev, uint8_t *data, uint32_t index, uint16_t data_size, uint8_t *new_data, uint16_t new_data_size, uint16_t new_data_pos)
This function can be used to replace 'extra data' in DCI.
uint8_t vl53l5cx_get_integration_time_ms(VL53L5CX_Configuration *p_dev, uint32_t *p_time_ms)
This function gets the current integration time in ms.
uint8_t vl53l5cx_get_ranging_data(VL53L5CX_Configuration *p_dev, VL53L5CX_ResultsData *p_results)
This function gets the ranging data, using the selected output and the resolution.
static uint8_t _vl53l5cx_send_xtalk_data(VL53L5CX_Configuration *p_dev, uint8_t resolution)
Inner function, not available outside this file.
static uint8_t _vl53l5cx_poll_for_answer(VL53L5CX_Configuration *p_dev, uint8_t size, uint8_t pos, uint16_t address, uint8_t mask, uint8_t expected_value)
Copyright (c) 2021 STMicroelectronics.
uint8_t vl53l5cx_init(VL53L5CX_Configuration *p_dev)
Mandatory function used to initialize the sensor.
static uint8_t _vl53l5cx_poll_for_mcu_boot(VL53L5CX_Configuration *p_dev)
uint8_t vl53l5cx_start_ranging(VL53L5CX_Configuration *p_dev)
This function starts a ranging session.
uint8_t vl53l5cx_check_data_ready(VL53L5CX_Configuration *p_dev, uint8_t *p_isReady)
This function checks if a new data is ready by polling I2C.
uint8_t vl53l5cx_set_target_order(VL53L5CX_Configuration *p_dev, uint8_t target_order)
This function sets a new target order.
uint8_t vl53l5cx_set_ranging_mode(VL53L5CX_Configuration *p_dev, uint8_t ranging_mode)
This function is used to set the ranging mode.
uint8_t vl53l5cx_get_ranging_frequency_hz(VL53L5CX_Configuration *p_dev, uint8_t *p_frequency_hz)
This function gets the current ranging frequency in Hz.
uint8_t vl53l5cx_get_resolution(VL53L5CX_Configuration *p_dev, uint8_t *p_resolution)
This function gets the current resolution (4x4 or 8x8).
uint8_t vl53l5cx_dci_write_data(VL53L5CX_Configuration *p_dev, uint8_t *data, uint32_t index, uint16_t data_size)
This function can be used to write 'extra data' to DCI.
uint8_t vl53l5cx_set_resolution(VL53L5CX_Configuration *p_dev, uint8_t resolution)
This function sets a new resolution (4x4 or 8x8).
uint8_t vl53l5cx_stop_ranging(VL53L5CX_Configuration *p_dev)
This function stops the ranging session.
uint8_t vl53l5cx_set_sharpener_percent(VL53L5CX_Configuration *p_dev, uint8_t sharpener_percent)
This function sets a new sharpener value in percent.
uint8_t vl53l5cx_enable_internal_cp(VL53L5CX_Configuration *p_dev)
This function is used to disable the VCSEL charge pump This optimizes the power consumption of the de...
uint8_t vl53l5cx_get_target_order(VL53L5CX_Configuration *p_dev, uint8_t *p_target_order)
This function gets the current target order (closest or strongest).
#define VL53L5CX_DCI_INT_TIME
#define VL53L5CX_MOTION_DETEC_IDX
#define VL53L5CX_SPAD_COUNT_IDX
#define VL53L5CX_DISTANCE_BH
#define VL53L5CX_STATUS_INVALID_PARAM
#define VL53L5CX_MCU_ERROR
#define VL53L5CX_AMBIENT_RATE_BH
#define VL53L5CX_XTALK_BUFFER_SIZE
#define VL53L5CX_STATUS_CORRUPTED_FRAME
#define VL53L5CX_DCI_ZONE_CONFIG
#define VL53L5CX_DCI_RANGING_MODE
#define VL53L5CX_DISTANCE_IDX
#define VL53L5CX_DCI_OUTPUT_LIST
#define VL53L5CX_POWER_MODE_WAKEUP
#define VL53L5CX_STATUS_OK
Macro VL53L5CX_STATUS_OK indicates that VL53L5 sensor has no error.
#define VL53L5CX_DCI_SHARPENER
#define VL53L5CX_METADATA_BH
#define VL53L5CX_TEMPORARY_BUFFER_SIZE
Macro VL53L5CX_TEMPORARY_BUFFER_SIZE can be used to know the size of the temporary buffer.
#define VL53L5CX_TARGET_STATUS_IDX
#define VL53L5CX_DCI_FREQ_HZ
#define VL53L5CX_RANGE_SIGMA_MM_BH
#define VL53L5CX_POWER_MODE_SLEEP
The default power mode is VL53L5CX_POWER_MODE_WAKEUP.
#define VL53L5CX_SIGNAL_RATE_IDX
#define VL53L5CX_RANGE_SIGMA_MM_IDX
#define VL53L5CX_DCI_FW_NB_TARGET
#define VL53L5CX_TARGET_ORDER_CLOSEST
Macro VL53L5CX_TARGET_ORDER_STRONGEST or VL53L5CX_TARGET_ORDER_CLOSEST are used to select the target ...
#define VL53L5CX_DCI_SINGLE_RANGE
#define VL53L5CX_DCI_DSS_CONFIG
#define VL53L5CX_REFLECTANCE_BH
#define VL53L5CX_MOTION_DETECT_BH
#define VL53L5CX_METADATA_IDX
#define VL53L5CX_DCI_OUTPUT_CONFIG
#define VL53L5CX_RESOLUTION_4X4
Macro VL53L5CX_RESOLUTION_4X4 or VL53L5CX_RESOLUTION_8X8 allows setting sensor in 4x4 mode or 8x8 mod...
#define VL53L5CX_NB_TARGET_DETECTED_BH
#define VL53L5CX_START_BH
Definitions for Range results block headers.
#define VL53L5CX_RESOLUTION_8X8
#define VL53L5CX_NB_TARGET_DETECTED_IDX
#define VL53L5CX_RANGING_MODE_CONTINUOUS
Macro VL53L5CX_RANGING_MODE_CONTINUOUS and VL53L5CX_RANGING_MODE_AUTONOMOUS are used to change the ra...
#define VL53L5CX_COMMONDATA_BH
#define VL53L5CX_UI_CMD_START
#define VL53L5CX_DCI_TARGET_ORDER
#define VL53L5CX_DCI_PIPE_CONTROL
#define VL53L5CX_SPAD_COUNT_BH
#define VL53L5CX_UI_CMD_STATUS
#define VL53L5CX_STATUS_ERROR
#define VL53L5CX_NVM_DATA_SIZE
Inner Macro for API.
#define VL53L5CX_TARGET_STATUS_BH
#define VL53L5CX_GLARE_FILTER
#define VL53L5CX_DCI_OUTPUT_ENABLES
#define VL53L5CX_AMBIENT_RATE_IDX
#define VL53L5CX_SIGNAL_RATE_BH
#define VL53L5CX_DCI_INTERNAL_CP
#define VL53L5CX_REFLECTANCE_EST_PC_IDX
#define VL53L5CX_UI_CMD_END
#define VL53L5CX_OFFSET_BUFFER_SIZE
#define VL53L5CX_RANGING_MODE_AUTONOMOUS
#define VL53L5CX_TARGET_ORDER_STRONGEST
#define VL53L5CX_STATUS_TIMEOUT_ERROR
Structure VL53L5CX_Configuration contains the sensor configuration.
Structure VL53L5CX_ResultsData contains the ranging results of VL53L5CX.
const uint8_t VL53L5CX_DEFAULT_CONFIGURATION[]
This buffer contains the VL53L5CX default configuration.
const uint8_t VL53L5CX_FIRMWARE[]
This buffer contains the VL53L5CX firmware (MM1.5)
const uint8_t VL53L5CX_DEFAULT_XTALK[]
This buffer contains the VL53L5CX default Xtalk data.
const uint8_t VL53L5CX_GET_NVM_CMD[]
This buffer is used to get NVM data.
uint8_t RdByte(VL53L5CX_Platform *dev, uint16_t index, uint8_t *p_data)
uint8_t WaitMs(VL53L5CX_Platform *p_platform, uint32_t TimeMs)
Mandatory function, used to wait during an amount of time.
uint8_t WrMulti(VL53L5CX_Platform *dev, uint16_t index, uint8_t *pdata, uint32_t count)
Mandatory function used to write multiples bytes.
void SwapBuffer(uint8_t *buffer, uint16_t size)
Optional function, only used to perform an hardware reset of the sensor.
uint8_t RdMulti(VL53L5CX_Platform *dev, uint16_t index, uint8_t *pdata, uint32_t count)
Mandatory function used to read multiples bytes.
uint8_t WrByte(VL53L5CX_Platform *dev, uint16_t index, uint8_t data)
Mandatory function used to write one single byte.
#define VL53L5CX_NB_TARGET_PER_ZONE