ACwing FC firmware
STM32WB55: attitude IEKF, altitude Kalman filter, flight core, protocol v2
Loading...
Searching...
No Matches
vl53l1x.c
Go to the documentation of this file.
1
13#include "vl53l1x.h"
14
15#define REG_SOFT_RESET 0x0000u
16#define REG_VHV_TIMEOUT_LOOP_BOUND 0x0008u
17#define REG_VHV_START 0x000Bu
18#define REG_GPIO_HV_MUX_CTRL 0x0030u
19#define REG_GPIO_TIO_HV_STATUS 0x0031u
20#define REG_PHASECAL_TIMEOUT 0x004Bu
21#define REG_RANGE_TIMEOUT_A_HI 0x005Eu
22#define REG_RANGE_VCSEL_PERIOD_A 0x0060u
23#define REG_RANGE_TIMEOUT_B_HI 0x0061u
24#define REG_RANGE_VCSEL_PERIOD_B 0x0063u
25#define REG_RANGE_VALID_PHASE_HIGH 0x0069u
26#define REG_INTERMEASUREMENT 0x006Cu
27#define REG_SD_WOI_SD0 0x0078u
28#define REG_SD_INITIAL_PHASE_SD0 0x007Au
29#define REG_INTERRUPT_CLEAR 0x0086u
30#define REG_MODE_START 0x0087u
31#define REG_RESULT_RANGE_STATUS 0x0089u
32#define REG_RESULT_DISTANCE 0x0096u
33#define REG_OSC_CALIBRATE_VAL 0x00DEu
34#define REG_FIRMWARE_SYSTEM_STATUS 0x00E5u
35#define REG_MODEL_ID 0x010Fu
36
37/* ULD VL51L1X_DEFAULT_CONFIGURATION, registers 0x2D..0x87 */
38static const uint8_t k_default[0x87 - 0x2D + 1] = {
39 0x00, 0x01, 0x01, 0x01, 0x02, 0x00, 0x02, 0x08, 0x00, 0x08, 0x10, 0x01, 0x01, 0x00, 0x00, 0x00,
40 0x00, 0xff, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x0b, 0x00, 0x00, 0x02, 0x0a, 0x21,
41 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x38, 0xff, 0x01, 0x00, 0x08, 0x00,
42 0x00, 0x01, 0xdb, 0x0f, 0x01, 0xf1, 0x0d, 0x01, 0x68, 0x00, 0x80, 0x08, 0xb8, 0x00, 0x00, 0x00,
43 0x00, 0x0f, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x0d, 0x0e, 0x0e, 0x00,
44 0x00, 0x02, 0xc7, 0xff, 0x9B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00
45};
46
47static int32_t wr8(vl53_t *d, uint16_t reg, uint8_t v) { return d->bus.write(d->bus.handle, reg, &v, 1); }
48static int32_t wr16(vl53_t *d, uint16_t reg, uint16_t v)
49{
50 const uint8_t b[2] = { (uint8_t)(v >> 8), (uint8_t)v };
51 return d->bus.write(d->bus.handle, reg, b, 2);
52}
53static int32_t wr32(vl53_t *d, uint16_t reg, uint32_t v)
54{
55 const uint8_t b[4] = { (uint8_t)(v >> 24), (uint8_t)(v >> 16), (uint8_t)(v >> 8), (uint8_t)v };
56 return d->bus.write(d->bus.handle, reg, b, 4);
57}
58static int32_t rd8(vl53_t *d, uint16_t reg, uint8_t *v) { return d->bus.read(d->bus.handle, reg, v, 1); }
59static int32_t rd16(vl53_t *d, uint16_t reg, uint16_t *v)
60{
61 uint8_t b[2];
62 const int32_t r = d->bus.read(d->bus.handle, reg, b, 2);
63 *v = (uint16_t)(((uint16_t)b[0] << 8) | b[1]);
64 return r;
65}
66static void dly(vl53_t *d, uint32_t ms) { if (d->bus.delay_ms) d->bus.delay_ms(ms); }
67
68static int32_t data_ready(vl53_t *d, uint8_t *rdy)
69{
70 uint8_t t;
71 if (rd8(d, REG_GPIO_TIO_HV_STATUS, &t)) return -1;
72 *rdy = (uint8_t)((t & 1u) == d->int_pol);
73 return 0;
74}
75
76static uint8_t map_status(uint8_t s)
77{
78 switch (s & 0x1Fu) {
79 case 9: return 0; case 6: return 1; case 4: return 2; case 8: return 3;
80 case 5: return 4; case 3: return 5; case 19: return 6; case 7: return 7;
81 case 12: return 9; case 18: return 10; case 22: return 11; case 23: return 12;
82 case 13: return 13; default: return 255;
83 }
84}
85
86int32_t vl53_init(vl53_t *d, const vl53_bus_t *bus, uint16_t budget_ms)
87{
88 d->bus = *bus;
89 d->ok = 0;
90
91 /* boot: firmware ready (up to ~1.2 ms after XSHUT, allow 100 ms) */
92 uint8_t st = 0;
93 for (int i = 0; i < 100; ++i) {
94 if (rd8(d, REG_FIRMWARE_SYSTEM_STATUS, &st) == 0 && (st & 1u)) break;
95 dly(d, 1);
96 }
97 if (!(st & 1u)) return -1;
98 uint16_t id = 0;
99 if (rd16(d, REG_MODEL_ID, &id) || id != VL53L1X_MODEL_ID) return -2;
100
101 /* SensorInit */
102 if (d->bus.write(d->bus.handle, 0x2Du, k_default, sizeof k_default)) return -1;
103 uint8_t mux = 0;
104 if (rd8(d, REG_GPIO_HV_MUX_CTRL, &mux)) return -1;
105 d->int_pol = (uint8_t)!((mux & 0x10u) >> 4);
106 if (wr8(d, REG_INTERRUPT_CLEAR, 0x01) || wr8(d, REG_MODE_START, 0x40)) return -1;
107 uint8_t rdy = 0;
108 for (int i = 0; i < 150 && !rdy; ++i) { if (data_ready(d, &rdy)) return -1; if (!rdy) dly(d, 1); }
109 if (!rdy) return -3;
110 if (wr8(d, REG_INTERRUPT_CLEAR, 0x01) || wr8(d, REG_MODE_START, 0x00)) return -1;
111 if (wr8(d, REG_VHV_TIMEOUT_LOOP_BOUND, 0x09) || wr8(d, REG_VHV_START, 0x00)) return -1;
112
113 /* long distance mode (up to 4 m indoors) */
114 if (wr8(d, REG_PHASECAL_TIMEOUT, 0x0A) || wr8(d, REG_RANGE_VCSEL_PERIOD_A, 0x0F) ||
116 wr16(d, REG_SD_WOI_SD0, 0x0F0D) || wr16(d, REG_SD_INITIAL_PHASE_SD0, 0x0E0E)) return -1;
117 /* timing budget (long mode table of the ULD) */
118 uint16_t a, b;
119 switch (budget_ms) {
120 case 20: a = 0x001E; b = 0x0022; break;
121 case 50: a = 0x00AD; b = 0x00C6; break;
122 case 100: a = 0x01CC; b = 0x01EA; break;
123 default: a = 0x0060; b = 0x006E; budget_ms = 33; break;
124 }
125 if (wr16(d, REG_RANGE_TIMEOUT_A_HI, a) || wr16(d, REG_RANGE_TIMEOUT_B_HI, b)) return -1;
126 /* inter-measurement period = budget (continuous back-to-back ranging) */
127 uint16_t pll = 0;
128 if (rd16(d, REG_OSC_CALIBRATE_VAL, &pll)) return -1;
129 pll &= 0x3FFu;
130 if (wr32(d, REG_INTERMEASUREMENT, (uint32_t)((float)pll * (float)budget_ms * 1.075f))) return -1;
131
132 if (wr8(d, REG_INTERRUPT_CLEAR, 0x01) || wr8(d, REG_MODE_START, 0x40)) return -1;
133 d->ok = 1;
134 return 0;
135}
136
138{
139 if (!d->ok) return -1;
140 uint8_t rdy = 0;
141 if (data_ready(d, &rdy)) return -1;
142 if (!rdy) return 0;
143 /* RESULT__RANGE_STATUS (0x89) .. FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0 (0x96)
144 * .. PEAK_SIGNAL_COUNT_RATE (0x98): one burst */
145 uint8_t r[0x99 - 0x89 + 1];
146 if (d->bus.read(d->bus.handle, REG_RESULT_RANGE_STATUS, r, sizeof r)) return -1;
147 if (wr8(d, REG_INTERRUPT_CLEAR, 0x01)) return -1;
148 s->status = map_status(r[0]);
149 s->mm = (uint16_t)(((uint16_t)r[0x96 - 0x89] << 8) | r[0x97 - 0x89]);
150 s->signal_kcps = (uint16_t)((((uint32_t)r[0x98 - 0x89] << 8) | r[0x99 - 0x89]) * 8u);
151 return 1;
152}
static batt_state_t s
Definition battery.c:21
double b[6]
Definition calib_mgr.c:53
uint16_t ms
Definition log_task.c:42
void * handle
Definition vl53l1x.h:25
void(* delay_ms)(uint32_t ms)
Definition vl53l1x.h:24
int32_t(* read)(void *h, uint16_t reg, uint8_t *d, uint16_t len)
Definition vl53l1x.h:23
int32_t(* write)(void *h, uint16_t reg, const uint8_t *d, uint16_t len)
Definition vl53l1x.h:22
Range status after the ULD mapping: 0 valid, 1 sigma fail, 2 signal fail, 4 out of bounds,...
Definition vl53l1x.h:36
vl53_bus_t bus
Definition vl53l1x.h:29
uint8_t int_pol
data-ready level on GPIO__TIO_HV_STATUS bit 0
Definition vl53l1x.h:30
uint8_t ok
Definition vl53l1x.h:31
static USBD_StatusTypeDef st(HAL_StatusTypeDef h)
Definition usbd_conf.c:86
#define REG_GPIO_HV_MUX_CTRL
Definition vl53l1x.c:18
#define REG_INTERMEASUREMENT
Definition vl53l1x.c:26
#define REG_MODEL_ID
Definition vl53l1x.c:35
static int32_t wr16(vl53_t *d, uint16_t reg, uint16_t v)
Definition vl53l1x.c:48
#define REG_MODE_START
Definition vl53l1x.c:30
#define REG_GPIO_TIO_HV_STATUS
Definition vl53l1x.c:19
#define REG_RANGE_VALID_PHASE_HIGH
Definition vl53l1x.c:25
#define REG_RESULT_RANGE_STATUS
Definition vl53l1x.c:31
#define REG_RANGE_TIMEOUT_B_HI
Definition vl53l1x.c:23
static uint8_t map_status(uint8_t s)
Definition vl53l1x.c:76
static int32_t wr32(vl53_t *d, uint16_t reg, uint32_t v)
Definition vl53l1x.c:53
static void dly(vl53_t *d, uint32_t ms)
Definition vl53l1x.c:66
#define REG_VHV_TIMEOUT_LOOP_BOUND
Definition vl53l1x.c:16
#define REG_RANGE_TIMEOUT_A_HI
Definition vl53l1x.c:21
static int32_t rd8(vl53_t *d, uint16_t reg, uint8_t *v)
Definition vl53l1x.c:58
#define REG_FIRMWARE_SYSTEM_STATUS
Definition vl53l1x.c:34
#define REG_SD_WOI_SD0
Definition vl53l1x.c:27
#define REG_INTERRUPT_CLEAR
Definition vl53l1x.c:29
static int32_t wr8(vl53_t *d, uint16_t reg, uint8_t v)
Definition vl53l1x.c:47
#define REG_PHASECAL_TIMEOUT
Definition vl53l1x.c:20
static const uint8_t k_default[0x87 - 0x2D+1]
Definition vl53l1x.c:38
static int32_t rd16(vl53_t *d, uint16_t reg, uint16_t *v)
Definition vl53l1x.c:59
int32_t vl53_init(vl53_t *d, const vl53_bus_t *bus, uint16_t budget_ms)
0 = sensor found and ranging; < 0 = absent or error (the board works without it)
Definition vl53l1x.c:86
#define REG_RANGE_VCSEL_PERIOD_A
Definition vl53l1x.c:22
int32_t vl53_poll(vl53_t *d, vl53_sample_t *s)
1 = new sample in *s, 0 = none yet, < 0 = bus error
Definition vl53l1x.c:137
#define REG_RANGE_VCSEL_PERIOD_B
Definition vl53l1x.c:24
#define REG_VHV_START
Definition vl53l1x.c:17
#define REG_SD_INITIAL_PHASE_SD0
Definition vl53l1x.c:28
#define REG_OSC_CALIBRATE_VAL
Definition vl53l1x.c:33
static int32_t data_ready(vl53_t *d, uint8_t *rdy)
Definition vl53l1x.c:68
Minimal VL53L1X time-of-flight driver (ACwing Flow rev A, Qwiic 0x29).
#define VL53L1X_MODEL_ID
Definition vl53l1x.h:19