├── .github └── workflows │ └── Continuous-integration.yml ├── LICENSE ├── README.md ├── examples ├── VL53L8CX_HelloWorld_I2C │ └── VL53L8CX_HelloWorld_I2C.ino ├── VL53L8CX_HelloWorld_SPI │ └── VL53L8CX_HelloWorld_SPI.ino └── VL53L8CX_ThresholdDetection │ └── VL53L8CX_ThresholdDetection.ino ├── keywords.txt ├── library.properties └── src ├── vl53l8cx.cpp ├── vl53l8cx.h ├── vl53l8cx_api.c ├── vl53l8cx_api.h ├── vl53l8cx_buffers.h ├── vl53l8cx_platform.c ├── vl53l8cx_platform.h ├── vl53l8cx_platform_config.h ├── vl53l8cx_platform_config_default.h ├── vl53l8cx_plugin_detection_thresholds.c ├── vl53l8cx_plugin_detection_thresholds.h ├── vl53l8cx_plugin_motion_indicator.c ├── vl53l8cx_plugin_motion_indicator.h ├── vl53l8cx_plugin_xtalk.c └── vl53l8cx_plugin_xtalk.h /.github/workflows/Continuous-integration.yml: -------------------------------------------------------------------------------- 1 | name: VL53L8CX Continuous Integration 2 | on: 3 | push: 4 | branches: 5 | - main 6 | paths-ignore: 7 | - '*' 8 | - '**.md' 9 | - '**.txt' 10 | pull_request: 11 | paths-ignore: 12 | - '*' 13 | - '**.md' 14 | - '**.txt' 15 | jobs: 16 | astyle_check: 17 | runs-on: ubuntu-latest 18 | name: AStyle check 19 | steps: 20 | # First of all, clone the repo using the checkout action. 21 | - name: Checkout 22 | uses: actions/checkout@main 23 | 24 | - name: Astyle check 25 | id: Astyle 26 | uses: stm32duino/actions/astyle-check@main 27 | 28 | # Use the output from the `Astyle` step 29 | - name: Astyle Errors 30 | if: failure() 31 | run: | 32 | cat ${{ steps.Astyle.outputs.astyle-result }} 33 | exit 1 34 | codespell: 35 | name: Check for spelling errors 36 | runs-on: ubuntu-latest 37 | steps: 38 | - name: Checkout 39 | uses: actions/checkout@main 40 | 41 | # See: https://github.com/codespell-project/actions-codespell/blob/master/README.md 42 | - name: Spell check 43 | uses: codespell-project/actions-codespell@master 44 | with: 45 | check_filenames: true 46 | check_hidden: true 47 | lib_build: 48 | runs-on: ubuntu-latest 49 | name: Library compilation 50 | steps: 51 | 52 | # First of all, clone the repo using the checkout action. 53 | - name: Checkout 54 | uses: actions/checkout@main 55 | 56 | - name: Compilation 57 | id: compile 58 | uses: stm32duino/actions/compile-examples@main 59 | with: 60 | board-pattern: "NUCLEO_L476RG" 61 | 62 | # Use the output from the `Compilation` step 63 | - name: Compilation Errors 64 | if: failure() 65 | run: | 66 | cat ${{ steps.compile.outputs.compile-result }} 67 | exit 1 68 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2024, STM32duino 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 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its 16 | contributors may be used to endorse or promote products derived from 17 | this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VL53L8CX 2 | Arduino library to support the VL53L8CX Time-of-Flight 8x8 multizone ranging sensor with wide field view. 3 | 4 | ## API 5 | 6 | This sensor uses I2C/SPI to communicate. And I2C/SPI instance is required to access to the sensor. 7 | The APIs provide simple distance measure and multizone detection in both polling and interrupt modes. 8 | The APIs derive from VL53L8CX ULD SDK v1.3.0. 9 | 10 | ## Examples 11 | 12 | The examples contained in this library are based on VL53L8CX-SATEL sensor board. 13 | 14 | You need to connect the VL53L8CX-SATEL sensor board directly to the Nucleo board with wires as explained below in the case of I2C communication: 15 | - pin 1 (SPI_I2C_n) of the VL53L8CX satellite connected to pin GND of the Nucleo board 16 | - pin 2 (LPn) of the VL53L8CX satellite connected to pin A3 of the Nucleo board 17 | - pin 3 (NCS) not connected 18 | - pin 4 (MISO) not connected 19 | - pin 5 (MOSI_SDA) of the VL53L8CX satellite connected to pin D14 (SDA) of the Nucleo board 20 | - pin 6 (MCLK_SCL) of the VL53L8CX satellite connected to pin D15 (SCL) of the Nucleo board 21 | - pin 7 (PWREN) of the VL53L8CX satellite connected to pin D11 of the Nucleo board 22 | - pin 8 (I0VDD) of the VL53L8CX satellite not connected 23 | - pin 9 (3V3) of the VL53L8CX satellite not connected 24 | - pin 10 (1V8) of the VL53L8CX satellite not connected 25 | - pin 11 (5V) of the VL53L8CX satellite connected to 5V of the Nucleo board 26 | - GPIO1 of VL53L8CX satellite connected to A2 pin of the Nucleo board (not used) 27 | - GND of the VL53L8CX satellite connected to GND of the Nucleo board 28 | 29 | You need to connect the VL53L8CX-SATEL sensor board directly to the Nucleo board with wires as explained below in the case of SPI communication: 30 | - pin 1 (SPI_I2C_n) of the VL53L8CX satellite connected to 3V3 of the Nucleo board 31 | - pin 2 (LPn) of the VL53L8CX satellite connected to 3V3 of the Nucleo board 32 | - pin 3 (NCS) of the VL53L8CX satellite connected to pin D10 of the Nucleo board 33 | - pin 4 (MISO) of the VL53L8CX satellite connected to pin D5 of the Nucleo board 34 | - pin 5 (MOSI_SDA) of the VL53L8CX satellite connected to pin D4 (MOSI) of the Nucleo board 35 | - pin 6 (MCLK_SCL) of the VL53L8CX satellite connected to pin D3 (MCLK_SCL) of the Nucleo board 36 | - pin 7 (PWREN) of the VL53L8CX satellite connected to pin D11 of the Nucleo board 37 | - pin 8 (I0VDD) of the VL53L8CX satellite not connected 38 | - pin 9 (3V3) of the VL53L8CX satellite not connected 39 | - pin 10 (1V8) of the VL53L8CX satellite not connected 40 | - pin 11 (5V) of the VL53L8CX satellite connected to 5V of the Nucleo board 41 | - GPIO1 of VL53L8CX satellite connected to A2 pin of the Nucleo board (not used) 42 | - GND of the VL53L8CX satellite connected to GND of the Nucleo board 43 | 44 | There are 3 examples with the VL53L8CX library: 45 | 46 | * VL53L8CX_Sat_HelloWorld_I2C: This example code is to show how to get multizone detection and proximity 47 | values of the VL53L8CX satellite sensor in polling mode using I2C communication. 48 | 49 | * VL53L8CX_Sat_HelloWorld_SPI: This example code is to show how to get multizone detection and proximity 50 | values of the VL53L8CX satellite sensor in polling mode using SPI communication. 51 | 52 | * VL53L8CX_ThresholdsDetection: This example code is to show how to configure the thresholds detection of the VL53L8CX satellite sensor. 53 | 54 | 55 | ## Documentation 56 | 57 | You can find the source files at 58 | https://github.com/stm32duino/VL53L8CX 59 | 60 | The VL53L8CX datasheet is available at 61 | https://www.st.com/en/imaging-and-photonics-solutions/VL53L8CX.html 62 | -------------------------------------------------------------------------------- /examples/VL53L8CX_HelloWorld_I2C/VL53L8CX_HelloWorld_I2C.ino: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file VL53L8CX_HelloWorld_I2C.ino 4 | * @author STMicroelectronics 5 | * @version V2.0.0 6 | * @date 27 June 2024 7 | * @brief Arduino test application for STMicroelectronics VL53L8CX 8 | * proximity sensor satellite based on FlightSense. 9 | * This application makes use of C++ classes obtained from the C 10 | * components' drivers. 11 | ****************************************************************************** 12 | * @attention 13 | * 14 | *

© COPYRIGHT(c) 2024 STMicroelectronics

15 | * 16 | * Redistribution and use in source and binary forms, with or without modification, 17 | * are permitted provided that the following conditions are met: 18 | * 1. Redistributions of source code must retain the above copyright notice, 19 | * this list of conditions and the following disclaimer. 20 | * 2. Redistributions in binary form must reproduce the above copyright notice, 21 | * this list of conditions and the following disclaimer in the documentation 22 | * and/or other materials provided with the distribution. 23 | * 3. Neither the name of STMicroelectronics nor the names of its contributors 24 | * may be used to endorse or promote products derived from this software 25 | * without specific prior written permission. 26 | * 27 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 28 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 30 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 31 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 33 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 34 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 35 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 | * 38 | ****************************************************************************** 39 | */ 40 | /* 41 | * To use these examples you need to connect the VL53L8CX satellite sensor directly to the Nucleo board with wires as explained below: 42 | * pin 1 (SPI_I2C_N) of the VL53L8CX satellite connected to pin GND of the Nucleo board 43 | * pin 2 (LPn) of the VL53L8CX satellite connected to pin A3 of the Nucleo board 44 | * pin 3 (NCS) not connected 45 | * pin 4 (MISO) not connected 46 | * pin 5 (MOSI_SDA) of the VL53L8CX satellite connected to pin D14 (SDA) of the Nucleo board 47 | * pin 6 (MCLK_SCL) of the VL53L8CX satellite connected to pin D15 (SCL) of the Nucleo board 48 | * pin 7 (PWREN) of the VL53L8CX satellite connected to pin D11 of the Nucleo board 49 | * pin 8 (I0VDD) of the VL53L8CX satellite not connected 50 | * pin 9 (3V3) of the VL53L8CX satellite not connected 51 | * pin 10 (1V8) of the VL53L8CX satellite not connected 52 | * pin 11 (5V) of the VL53L8CX satellite connected to 5V of the Nucleo board 53 | * GPIO1 of VL53L8CX satellite connected to A2 pin of the Nucleo board (not used) 54 | * GND of the VL53L8CX satellite connected to GND of the Nucleo board 55 | */ 56 | 57 | /* Includes ------------------------------------------------------------------*/ 58 | 59 | #include 60 | 61 | 62 | #ifdef ARDUINO_SAM_DUE 63 | #define DEV_I2C Wire1 64 | #else 65 | #define DEV_I2C Wire 66 | #endif 67 | #define SerialPort Serial 68 | 69 | #define LPN_PIN A3 70 | #define PWREN_PIN 11 71 | 72 | void print_result(VL53L8CX_ResultsData *Result); 73 | void clear_screen(void); 74 | void handle_cmd(uint8_t cmd); 75 | void display_commands_banner(void); 76 | 77 | // Components. 78 | VL53L8CX sensor_vl53l8cx_top(&DEV_I2C, LPN_PIN); 79 | 80 | bool EnableAmbient = false; 81 | bool EnableSignal = false; 82 | uint8_t res = VL53L8CX_RESOLUTION_4X4; 83 | char report[256]; 84 | uint8_t status; 85 | 86 | /* Setup ---------------------------------------------------------------------*/ 87 | void setup() 88 | { 89 | 90 | // Enable PWREN pin if present 91 | if (PWREN_PIN >= 0) { 92 | pinMode(PWREN_PIN, OUTPUT); 93 | digitalWrite(PWREN_PIN, HIGH); 94 | delay(10); 95 | } 96 | 97 | // Initialize serial for output. 98 | SerialPort.begin(460800); 99 | 100 | // Initialize I2C bus. 101 | DEV_I2C.begin(); 102 | 103 | // Configure VL53L8CX component. 104 | sensor_vl53l8cx_top.begin(); 105 | status = sensor_vl53l8cx_top.init(); 106 | 107 | // Start Measurements 108 | status = sensor_vl53l8cx_top.start_ranging(); 109 | } 110 | 111 | void loop() 112 | { 113 | VL53L8CX_ResultsData Results; 114 | uint8_t NewDataReady = 0; 115 | 116 | do { 117 | status = sensor_vl53l8cx_top.check_data_ready(&NewDataReady); 118 | } while (!NewDataReady); 119 | 120 | if ((!status) && (NewDataReady != 0)) { 121 | status = sensor_vl53l8cx_top.get_ranging_data(&Results); 122 | print_result(&Results); 123 | } 124 | 125 | if (Serial.available() > 0) { 126 | handle_cmd(Serial.read()); 127 | } 128 | delay(100); 129 | } 130 | 131 | void print_result(VL53L8CX_ResultsData *Result) 132 | { 133 | int8_t i, j, k; 134 | uint8_t l, zones_per_line; 135 | uint8_t number_of_zones = res; 136 | 137 | zones_per_line = (number_of_zones == 16) ? 4 : 8; 138 | 139 | display_commands_banner(); 140 | 141 | SerialPort.print("Cell Format :\n\n"); 142 | 143 | for (l = 0; l < VL53L8CX_NB_TARGET_PER_ZONE; l++) { 144 | snprintf(report, sizeof(report), " \033[38;5;10m%20s\033[0m : %20s\n", "Distance [mm]", "Status"); 145 | SerialPort.print(report); 146 | 147 | if (EnableAmbient || EnableSignal) { 148 | snprintf(report, sizeof(report), " %20s : %20s\n", "Signal [kcps/spad]", "Ambient [kcps/spad]"); 149 | SerialPort.print(report); 150 | } 151 | } 152 | 153 | SerialPort.print("\n\n"); 154 | 155 | for (j = 0; j < number_of_zones; j += zones_per_line) { 156 | for (i = 0; i < zones_per_line; i++) { 157 | SerialPort.print(" -----------------"); 158 | } 159 | SerialPort.print("\n"); 160 | 161 | for (i = 0; i < zones_per_line; i++) { 162 | SerialPort.print("| "); 163 | } 164 | SerialPort.print("|\n"); 165 | 166 | for (l = 0; l < VL53L8CX_NB_TARGET_PER_ZONE; l++) { 167 | // Print distance and status 168 | for (k = (zones_per_line - 1); k >= 0; k--) { 169 | if (Result->nb_target_detected[j + k] > 0) { 170 | snprintf(report, sizeof(report), "| \033[38;5;10m%5ld\033[0m : %5ld ", 171 | (long)Result->distance_mm[(VL53L8CX_NB_TARGET_PER_ZONE * (j + k)) + l], 172 | (long)Result->target_status[(VL53L8CX_NB_TARGET_PER_ZONE * (j + k)) + l]); 173 | SerialPort.print(report); 174 | } else { 175 | snprintf(report, sizeof(report), "| %5s : %5s ", "X", "X"); 176 | SerialPort.print(report); 177 | } 178 | } 179 | SerialPort.print("|\n"); 180 | 181 | if (EnableAmbient || EnableSignal) { 182 | // Print Signal and Ambient 183 | for (k = (zones_per_line - 1); k >= 0; k--) { 184 | if (Result->nb_target_detected[j + k] > 0) { 185 | if (EnableSignal) { 186 | snprintf(report, sizeof(report), "| %5ld : ", (long)Result->signal_per_spad[(VL53L8CX_NB_TARGET_PER_ZONE * (j + k)) + l]); 187 | SerialPort.print(report); 188 | } else { 189 | snprintf(report, sizeof(report), "| %5s : ", "X"); 190 | SerialPort.print(report); 191 | } 192 | if (EnableAmbient) { 193 | snprintf(report, sizeof(report), "%5ld ", (long)Result->ambient_per_spad[j + k]); 194 | SerialPort.print(report); 195 | } else { 196 | snprintf(report, sizeof(report), "%5s ", "X"); 197 | SerialPort.print(report); 198 | } 199 | } else { 200 | snprintf(report, sizeof(report), "| %5s : %5s ", "X", "X"); 201 | SerialPort.print(report); 202 | } 203 | } 204 | SerialPort.print("|\n"); 205 | } 206 | } 207 | } 208 | for (i = 0; i < zones_per_line; i++) { 209 | SerialPort.print(" -----------------"); 210 | } 211 | SerialPort.print("\n"); 212 | } 213 | 214 | void toggle_resolution(void) 215 | { 216 | status = sensor_vl53l8cx_top.stop_ranging(); 217 | 218 | switch (res) { 219 | case VL53L8CX_RESOLUTION_4X4: 220 | res = VL53L8CX_RESOLUTION_8X8; 221 | break; 222 | 223 | case VL53L8CX_RESOLUTION_8X8: 224 | res = VL53L8CX_RESOLUTION_4X4; 225 | break; 226 | 227 | default: 228 | break; 229 | } 230 | status = sensor_vl53l8cx_top.set_resolution(res); 231 | status = sensor_vl53l8cx_top.start_ranging(); 232 | } 233 | 234 | void toggle_signal_and_ambient(void) 235 | { 236 | EnableAmbient = (EnableAmbient) ? false : true; 237 | EnableSignal = (EnableSignal) ? false : true; 238 | } 239 | 240 | void clear_screen(void) 241 | { 242 | snprintf(report, sizeof(report), "%c[2J", 27); /* 27 is ESC command */ 243 | SerialPort.print(report); 244 | } 245 | 246 | void display_commands_banner(void) 247 | { 248 | snprintf(report, sizeof(report), "%c[2H", 27); /* 27 is ESC command */ 249 | SerialPort.print(report); 250 | 251 | Serial.print("53L8A1 Simple Ranging demo application\n"); 252 | Serial.print("--------------------------------------\n\n"); 253 | 254 | Serial.print("Use the following keys to control application\n"); 255 | Serial.print(" 'r' : change resolution\n"); 256 | Serial.print(" 's' : enable signal and ambient\n"); 257 | Serial.print(" 'c' : clear screen\n"); 258 | Serial.print("\n"); 259 | } 260 | 261 | void handle_cmd(uint8_t cmd) 262 | { 263 | switch (cmd) { 264 | case 'r': 265 | toggle_resolution(); 266 | clear_screen(); 267 | break; 268 | 269 | case 's': 270 | toggle_signal_and_ambient(); 271 | clear_screen(); 272 | break; 273 | 274 | case 'c': 275 | clear_screen(); 276 | break; 277 | 278 | default: 279 | break; 280 | } 281 | } 282 | -------------------------------------------------------------------------------- /examples/VL53L8CX_HelloWorld_SPI/VL53L8CX_HelloWorld_SPI.ino: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file VL53L8CX_HelloWorld_SPI.ino 4 | * @author STMicroelectronics 5 | * @version V2.0.0 6 | * @date 27 June 2024 7 | * @brief Arduino test application for the X-NUCLEO-53L8A1 based on VL53L8CX 8 | * proximity sensor. 9 | * This application makes use of C++ classes obtained from the C 10 | * components' drivers. 11 | ****************************************************************************** 12 | * @attention 13 | * 14 | *

© COPYRIGHT(c) 2024 STMicroelectronics

15 | * 16 | * Redistribution and use in source and binary forms, with or without modification, 17 | * are permitted provided that the following conditions are met: 18 | * 1. Redistributions of source code must retain the above copyright notice, 19 | * this list of conditions and the following disclaimer. 20 | * 2. Redistributions in binary form must reproduce the above copyright notice, 21 | * this list of conditions and the following disclaimer in the documentation 22 | * and/or other materials provided with the distribution. 23 | * 3. Neither the name of STMicroelectronics nor the names of its contributors 24 | * may be used to endorse or promote products derived from this software 25 | * without specific prior written permission. 26 | * 27 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 28 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 30 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 31 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 33 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 34 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 35 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 | * 38 | ****************************************************************************** 39 | */ 40 | /* 41 | * To use these examples you need to connect the VL53L8CX satellite sensor directly to the Nucleo board with wires as explained below: 42 | * pin 1 (SPI_I2C_n) of the VL53L8CX satellite connected to 3V3 of the Nucleo board 43 | * pin 2 (LPn) of the VL53L8CX satellite connected to 3V3 of the Nucleo board 44 | * pin 3 (NCS) of the VL53L8CX satellite connected to pin D10 of the Nucleo board 45 | * pin 4 (MISO) of the VL53L8CX satellite connected to pin D5 of the Nucleo board 46 | * pin 5 (MOSI_SDA) of the VL53L8CX satellite connected to pin D4 (MOSI) of the Nucleo board 47 | * pin 6 (MCLK_SCL) of the VL53L8CX satellite connected to pin D3 (MCLK_SCL) of the Nucleo board 48 | * pin 7 (PWREN) of the VL53L8CX satellite connected to pin D11 of the Nucleo board 49 | * pin 8 (I0VDD) of the VL53L8CX satellite not connected 50 | * pin 9 (3V3) of the VL53L8CX satellite not connected 51 | * pin 10 (1V8) of the VL53L8CX satellite not connected 52 | * pin 11 (5V) of the VL53L8CX satellite connected to 5V of the Nucleo board 53 | * GPIO1 of VL53L8CX satellite connected to A2 pin of the Nucleo board (not used) 54 | * GND of the VL53L8CX satellite connected to GND of the Nucleo board 55 | */ 56 | 57 | /* Includes ------------------------------------------------------------------*/ 58 | 59 | #include 60 | #include 61 | 62 | #define SerialPort Serial 63 | 64 | #define PWREN_PIN 11 65 | 66 | #define SPI_CLK_PIN 3 67 | #define SPI_MISO_PIN 5 68 | #define SPI_MOSI_PIN 4 69 | #define CS_PIN 10 70 | 71 | SPIClass DEV_SPI(SPI_MOSI_PIN, SPI_MISO_PIN, SPI_CLK_PIN); 72 | 73 | void print_result(VL53L8CX_ResultsData *Result); 74 | void clear_screen(void); 75 | void handle_cmd(uint8_t cmd); 76 | void display_commands_banner(void); 77 | 78 | VL53L8CX sensor_vl53l8cx_top(&DEV_SPI, CS_PIN); 79 | 80 | bool EnableAmbient = false; 81 | bool EnableSignal = false; 82 | uint8_t res = VL53L8CX_RESOLUTION_4X4; 83 | char report[256]; 84 | uint8_t status; 85 | /* Setup ---------------------------------------------------------------------*/ 86 | void setup() 87 | { 88 | // Enable PWREN pin if present 89 | if (PWREN_PIN >= 0) { 90 | pinMode(PWREN_PIN, OUTPUT); 91 | digitalWrite(PWREN_PIN, HIGH); 92 | delay(10); 93 | } 94 | 95 | // Initialize serial for output. 96 | SerialPort.begin(460800); 97 | 98 | // Initialize SPI bus. 99 | DEV_SPI.begin(); 100 | 101 | // Configure VL53L8CX component. 102 | sensor_vl53l8cx_top.begin(); 103 | status = sensor_vl53l8cx_top.init(); 104 | 105 | // Start Measurements 106 | status = sensor_vl53l8cx_top.start_ranging(); 107 | } 108 | 109 | void loop() 110 | { 111 | VL53L8CX_ResultsData Results; 112 | uint8_t NewDataReady = 0; 113 | do { 114 | status = sensor_vl53l8cx_top.check_data_ready(&NewDataReady); 115 | } while (!NewDataReady); 116 | 117 | if ((!status) && (NewDataReady != 0)) { 118 | status = sensor_vl53l8cx_top.get_ranging_data(&Results); 119 | print_result(&Results); 120 | } 121 | 122 | if (Serial.available() > 0) { 123 | handle_cmd(Serial.read()); 124 | } 125 | delay(50); 126 | } 127 | 128 | void print_result(VL53L8CX_ResultsData *Result) 129 | { 130 | int8_t i, j, k; 131 | uint8_t l, zones_per_line; 132 | uint8_t number_of_zones = res; 133 | 134 | zones_per_line = (number_of_zones == 16) ? 4 : 8; 135 | 136 | display_commands_banner(); 137 | 138 | SerialPort.print("Cell Format :\n\n"); 139 | 140 | for (l = 0; l < VL53L8CX_NB_TARGET_PER_ZONE; l++) { 141 | snprintf(report, sizeof(report), " \033[38;5;10m%20s\033[0m : %20s\n", "Distance [mm]", "Status"); 142 | SerialPort.print(report); 143 | 144 | if (EnableAmbient || EnableSignal) { 145 | snprintf(report, sizeof(report), " %20s : %20s\n", "Signal [kcps/spad]", "Ambient [kcps/spad]"); 146 | SerialPort.print(report); 147 | } 148 | } 149 | 150 | SerialPort.print("\n\n"); 151 | 152 | for (j = 0; j < number_of_zones; j += zones_per_line) { 153 | for (i = 0; i < zones_per_line; i++) { 154 | SerialPort.print(" -----------------"); 155 | } 156 | SerialPort.print("\n"); 157 | 158 | for (i = 0; i < zones_per_line; i++) { 159 | SerialPort.print("| "); 160 | } 161 | SerialPort.print("|\n"); 162 | 163 | for (l = 0; l < VL53L8CX_NB_TARGET_PER_ZONE; l++) { 164 | // Print distance and status 165 | for (k = (zones_per_line - 1); k >= 0; k--) { 166 | if (Result->nb_target_detected[j + k] > 0) { 167 | snprintf(report, sizeof(report), "| \033[38;5;10m%5ld\033[0m : %5ld ", 168 | (long)Result->distance_mm[(VL53L8CX_NB_TARGET_PER_ZONE * (j + k)) + l], 169 | (long)Result->target_status[(VL53L8CX_NB_TARGET_PER_ZONE * (j + k)) + l]); 170 | SerialPort.print(report); 171 | } else { 172 | snprintf(report, sizeof(report), "| %5s : %5s ", "X", "X"); 173 | SerialPort.print(report); 174 | } 175 | } 176 | SerialPort.print("|\n"); 177 | 178 | if (EnableAmbient || EnableSignal) { 179 | // Print Signal and Ambient 180 | for (k = (zones_per_line - 1); k >= 0; k--) { 181 | if (Result->nb_target_detected[j + k] > 0) { 182 | if (EnableSignal) { 183 | snprintf(report, sizeof(report), "| %5ld : ", (long)Result->signal_per_spad[(VL53L8CX_NB_TARGET_PER_ZONE * (j + k)) + l]); 184 | SerialPort.print(report); 185 | } else { 186 | snprintf(report, sizeof(report), "| %5s : ", "X"); 187 | SerialPort.print(report); 188 | } 189 | if (EnableAmbient) { 190 | snprintf(report, sizeof(report), "%5ld ", (long)Result->ambient_per_spad[j + k]); 191 | SerialPort.print(report); 192 | } else { 193 | snprintf(report, sizeof(report), "%5s ", "X"); 194 | SerialPort.print(report); 195 | } 196 | } else { 197 | snprintf(report, sizeof(report), "| %5s : %5s ", "X", "X"); 198 | SerialPort.print(report); 199 | } 200 | } 201 | SerialPort.print("|\n"); 202 | } 203 | } 204 | } 205 | for (i = 0; i < zones_per_line; i++) { 206 | SerialPort.print(" -----------------"); 207 | } 208 | SerialPort.print("\n"); 209 | } 210 | 211 | void toggle_resolution(void) 212 | { 213 | status = sensor_vl53l8cx_top.stop_ranging(); 214 | 215 | switch (res) { 216 | case VL53L8CX_RESOLUTION_4X4: 217 | res = VL53L8CX_RESOLUTION_8X8; 218 | break; 219 | 220 | case VL53L8CX_RESOLUTION_8X8: 221 | res = VL53L8CX_RESOLUTION_4X4; 222 | break; 223 | 224 | default: 225 | break; 226 | } 227 | status = sensor_vl53l8cx_top.set_resolution(res); 228 | status = sensor_vl53l8cx_top.start_ranging(); 229 | } 230 | 231 | void toggle_signal_and_ambient(void) 232 | { 233 | EnableAmbient = (EnableAmbient) ? false : true; 234 | EnableSignal = (EnableSignal) ? false : true; 235 | } 236 | 237 | void clear_screen(void) 238 | { 239 | snprintf(report, sizeof(report), "%c[2J", 27); /* 27 is ESC command */ 240 | SerialPort.print(report); 241 | } 242 | 243 | void display_commands_banner(void) 244 | { 245 | snprintf(report, sizeof(report), "%c[2H", 27); /* 27 is ESC command */ 246 | SerialPort.print(report); 247 | 248 | Serial.print("53L8A1 Simple Ranging demo application\n"); 249 | Serial.print("--------------------------------------\n\n"); 250 | 251 | Serial.print("Use the following keys to control application\n"); 252 | Serial.print(" 'r' : change resolution\n"); 253 | Serial.print(" 's' : enable signal and ambient\n"); 254 | Serial.print(" 'c' : clear screen\n"); 255 | Serial.print("\n"); 256 | } 257 | 258 | void handle_cmd(uint8_t cmd) 259 | { 260 | switch (cmd) { 261 | case 'r': 262 | toggle_resolution(); 263 | clear_screen(); 264 | break; 265 | 266 | case 's': 267 | toggle_signal_and_ambient(); 268 | clear_screen(); 269 | break; 270 | 271 | case 'c': 272 | clear_screen(); 273 | break; 274 | 275 | default: 276 | break; 277 | } 278 | } 279 | -------------------------------------------------------------------------------- /examples/VL53L8CX_ThresholdDetection/VL53L8CX_ThresholdDetection.ino: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file VL53L8CX_ThresholdDetection.ino 4 | * @author STMicroelectronics 5 | * @version V2.0.0 6 | * @date 27 June 2024 7 | * @brief Arduino test application for the STMicrolectronics VL53L8CX 8 | * proximity sensor satellite based on FlightSense. 9 | * This application makes use of C++ classes obtained from the C 10 | * components' drivers. 11 | ****************************************************************************** 12 | * @attention 13 | * 14 | *

© COPYRIGHT(c) 2024 STMicroelectronics

15 | * 16 | * Redistribution and use in source and binary forms, with or without modification, 17 | * are permitted provided that the following conditions are met: 18 | * 1. Redistributions of source code must retain the above copyright notice, 19 | * this list of conditions and the following disclaimer. 20 | * 2. Redistributions in binary form must reproduce the above copyright notice, 21 | * this list of conditions and the following disclaimer in the documentation 22 | * and/or other materials provided with the distribution. 23 | * 3. Neither the name of STMicroelectronics nor the names of its contributors 24 | * may be used to endorse or promote products derived from this software 25 | * without specific prior written permission. 26 | * 27 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 28 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 30 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 31 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 33 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 34 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 35 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 | * 38 | ****************************************************************************** 39 | */ 40 | /* 41 | * To use these examples you need to connect the VL53L8CX satellite sensor directly to the Nucleo board with wires as explained below: 42 | * pin 1 (SPI_I2C_n) of the VL53L8CX satellite connected to pin GND of the Nucleo board 43 | * pin 2 (LPn) of the VL53L8CX satellite connected to pin A3 of the Nucleo board 44 | * pin 3 (NCS) not connected 45 | * pin 4 (MISO) not connected 46 | * pin 5 (MOSI_SDA) of the VL53L8CX satellite connected to pin D14 (SDA) of the Nucleo board 47 | * pin 6 (MCLK_SCL) of the VL53L8CX satellite connected to pin D15 (SCL) of the Nucleo board 48 | * pin 7 (PWREN) of the VL53L8CX satellite connected to pin D11 of the Nucleo board 49 | * pin 8 (I0VDD) of the VL53L8CX satellite not connected 50 | * pin 9 (3V3) of the VL53L8CX satellite not connected 51 | * pin 10 (1V8) of the VL53L8CX satellite not connected 52 | * pin 11 (5V) of the VL53L8CX satellite connected to 5V of the Nucleo board 53 | * GPIO1 of VL53L8CX satellite connected to A2 pin of the Nucleo board (not used) 54 | * GND of the VL53L8CX satellite connected to GND of the Nucleo board 55 | */ 56 | 57 | /* Includes ------------------------------------------------------------------*/ 58 | 59 | #include 60 | 61 | #ifdef ARDUINO_SAM_DUE 62 | #define DEV_I2C Wire1 63 | #else 64 | #define DEV_I2C Wire 65 | #endif 66 | #define SerialPort Serial 67 | 68 | #define LPN_PIN A3 69 | #define PWREN_PIN 11 70 | #define INT_PIN A2 71 | 72 | void measure(void); 73 | void print_result(VL53L8CX_ResultsData *Result); 74 | 75 | // Component. 76 | VL53L8CX sensor_VL53L8CX_top(&DEV_I2C, LPN_PIN); 77 | 78 | bool EnableAmbient = false; 79 | bool EnableSignal = false; 80 | uint8_t res = VL53L8CX_RESOLUTION_4X4; 81 | char report[256]; 82 | volatile int interruptCount = 0; 83 | uint8_t i; 84 | uint8_t status; 85 | 86 | /* Setup ---------------------------------------------------------------------*/ 87 | 88 | void setup() 89 | { 90 | 91 | VL53L8CX_DetectionThresholds thresholds[VL53L8CX_NB_THRESHOLDS]; 92 | 93 | // Enable PWREN pin if present 94 | if (PWREN_PIN >= 0) { 95 | pinMode(PWREN_PIN, OUTPUT); 96 | digitalWrite(PWREN_PIN, HIGH); 97 | delay(10); 98 | } 99 | 100 | // Initialize serial for output. 101 | SerialPort.begin(460800); 102 | 103 | // Initialize I2C bus. 104 | DEV_I2C.begin(); 105 | 106 | // Set interrupt pin 107 | pinMode(INT_PIN, INPUT_PULLUP); 108 | attachInterrupt(INT_PIN, measure, FALLING); 109 | 110 | // Configure VL53L8CX component. 111 | sensor_VL53L8CX_top.begin(); 112 | status = sensor_VL53L8CX_top.init(); 113 | 114 | // Disable thresholds detection. 115 | status = sensor_VL53L8CX_top.set_detection_thresholds_enable(0U); 116 | 117 | // Set all values to 0. 118 | memset(&thresholds, 0, sizeof(thresholds)); 119 | 120 | // Configure thresholds on each active zone 121 | for (i = 0; i < res; i++) { 122 | thresholds[i].zone_num = i; 123 | thresholds[i].measurement = VL53L8CX_DISTANCE_MM; 124 | thresholds[i].type = VL53L8CX_IN_WINDOW; 125 | thresholds[i].mathematic_operation = VL53L8CX_OPERATION_NONE; 126 | thresholds[i].param_low_thresh = 200; 127 | thresholds[i].param_high_thresh = 600; 128 | } 129 | 130 | // Last threshold must be clearly indicated. 131 | thresholds[i].zone_num |= VL53L8CX_LAST_THRESHOLD; 132 | 133 | // Send array of thresholds to the sensor. 134 | status = sensor_VL53L8CX_top.set_detection_thresholds(thresholds); 135 | 136 | // Enable thresholds detection. 137 | status = sensor_VL53L8CX_top.set_detection_thresholds_enable(1U); 138 | 139 | // Start Measurements. 140 | status = sensor_VL53L8CX_top.start_ranging(); 141 | } 142 | 143 | void loop() 144 | { 145 | VL53L8CX_ResultsData Results; 146 | uint8_t NewDataReady = 0; 147 | do { 148 | status = sensor_VL53L8CX_top.check_data_ready(&NewDataReady); 149 | } while (!NewDataReady); 150 | 151 | if ((!status) && (NewDataReady != 0) && interruptCount) { 152 | interruptCount = 0; 153 | status = sensor_VL53L8CX_top.get_ranging_data(&Results); 154 | print_result(&Results); 155 | } 156 | 157 | } 158 | 159 | void print_result(VL53L8CX_ResultsData *Result) 160 | { 161 | int8_t i, j, k; 162 | uint8_t l, zones_per_line; 163 | uint8_t number_of_zones = res; 164 | 165 | zones_per_line = (number_of_zones == 16) ? 4 : 8; 166 | 167 | snprintf(report, sizeof(report), "%c[2H", 27); /* 27 is ESC command */ 168 | SerialPort.print(report); 169 | SerialPort.print("53L8A1 Threshold Detection demo application\n"); 170 | SerialPort.print("-------------------------------------------\n\n"); 171 | SerialPort.print("Cell Format :\n\n"); 172 | 173 | for (l = 0; l < VL53L8CX_NB_TARGET_PER_ZONE; l++) { 174 | snprintf(report, sizeof(report), " \033[38;5;10m%20s\033[0m : %20s\n", "Distance [mm]", "Status"); 175 | SerialPort.print(report); 176 | 177 | if (EnableAmbient || EnableSignal) { 178 | snprintf(report, sizeof(report), " %20s : %20s\n", "Signal [kcps/spad]", "Ambient [kcps/spad]"); 179 | SerialPort.print(report); 180 | } 181 | } 182 | 183 | SerialPort.print("\n\n"); 184 | 185 | for (j = 0; j < number_of_zones; j += zones_per_line) { 186 | for (i = 0; i < zones_per_line; i++) { 187 | SerialPort.print(" -----------------"); 188 | } 189 | SerialPort.print("\n"); 190 | 191 | for (i = 0; i < zones_per_line; i++) { 192 | SerialPort.print("| "); 193 | } 194 | SerialPort.print("|\n"); 195 | 196 | for (l = 0; l < VL53L8CX_NB_TARGET_PER_ZONE; l++) { 197 | // Print distance and status. 198 | for (k = (zones_per_line - 1); k >= 0; k--) { 199 | if (Result->nb_target_detected[j + k] > 0) { 200 | snprintf(report, sizeof(report), "| \033[38;5;10m%5ld\033[0m : %5ld ", 201 | (long)Result->distance_mm[(VL53L8CX_NB_TARGET_PER_ZONE * (j + k)) + l], 202 | (long)Result->target_status[(VL53L8CX_NB_TARGET_PER_ZONE * (j + k)) + l]); 203 | SerialPort.print(report); 204 | } else { 205 | snprintf(report, sizeof(report), "| %5s : %5s ", "X", "X"); 206 | SerialPort.print(report); 207 | } 208 | } 209 | SerialPort.print("|\n"); 210 | 211 | if (EnableAmbient || EnableSignal) { 212 | // Print Signal and Ambient. 213 | for (k = (zones_per_line - 1); k >= 0; k--) { 214 | if (Result->nb_target_detected[j + k] > 0) { 215 | if (EnableSignal) { 216 | snprintf(report, sizeof(report), "| %5ld : ", (long)Result->signal_per_spad[(VL53L8CX_NB_TARGET_PER_ZONE * (j + k)) + l]); 217 | SerialPort.print(report); 218 | } else { 219 | snprintf(report, sizeof(report), "| %5s : ", "X"); 220 | SerialPort.print(report); 221 | } 222 | if (EnableAmbient) { 223 | snprintf(report, sizeof(report), "%5ld ", (long)Result->ambient_per_spad[j + k]); 224 | SerialPort.print(report); 225 | } else { 226 | snprintf(report, sizeof(report), "%5s ", "X"); 227 | SerialPort.print(report); 228 | } 229 | } else { 230 | snprintf(report, sizeof(report), "| %5s : %5s ", "X", "X"); 231 | SerialPort.print(report); 232 | } 233 | } 234 | SerialPort.print("|\n"); 235 | } 236 | } 237 | } 238 | for (i = 0; i < zones_per_line; i++) { 239 | SerialPort.print(" -----------------"); 240 | } 241 | SerialPort.print("\n"); 242 | } 243 | 244 | void measure(void) 245 | { 246 | interruptCount = 1; 247 | } 248 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For VL53L8CX 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | VL53L8CX KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | 15 | begin KEYWORD2 16 | end KEYWORD2 17 | on KEYWORD2 18 | off KEYWORD2 19 | is_alive KEYWORD2 20 | init KEYWORD2 21 | set_i2c_address KEYWORD2 22 | get_power_mode KEYWORD2 23 | set_power_mode KEYWORD2 24 | start_ranging KEYWORD2 25 | stop_ranging KEYWORD2 26 | check_data_ready KEYWORD2 27 | get_ranging_data KEYWORD2 28 | get_resolution KEYWORD2 29 | set_resolution KEYWORD2 30 | get_ranging_frequency_hz KEYWORD2 31 | set_ranging_frequency_hz KEYWORD2 32 | get_integration_time_ms KEYWORD2 33 | set_integration_time_ms KEYWORD2 34 | get_sharpener_percent KEYWORD2 35 | set_sharpener_percent KEYWORD2 36 | get_target_order KEYWORD2 37 | set_target_order KEYWORD2 38 | get_ranging_mode KEYWORD2 39 | set_ranging_mode KEYWORD2 40 | get_external_sync_pin_enable KEYWORD2 41 | set_external_sync_pin_enable KEYWORD2 42 | get_VHV_repeat_count KEYWORD2 43 | set_VHV_repeat_count KEYWORD2 44 | dci_read_data KEYWORD2 45 | dci_write_data KEYWORD2 46 | dci_replace_data KEYWORD2 47 | get_detection_thresholds_enable KEYWORD2 48 | set_detection_thresholds_enable KEYWORD2 49 | get_detection_thresholds KEYWORD2 50 | set_detection_thresholds KEYWORD2 51 | get_detection_thresholds_auto_stop KEYWORD2 52 | set_detection_thresholds_auto_stop 53 | motion_indicator_init KEYWORD2 KEYWORD2 54 | motion_indicator_set_distance_motion KEYWORD2 55 | motion_indicator_set_resolution KEYWORD2 56 | calibrate_xtalk KEYWORD2 57 | get_caldata_xtalk KEYWORD2 58 | set_caldata_xtalk KEYWORD2 59 | get_xtalk_margin KEYWORD2 60 | set_xtalk_margin KEYWORD2 61 | SwapBuffer KEYWORD2 62 | get_stream_count KEYWORD2 63 | 64 | ####################################### 65 | # Constants (LITERAL1) 66 | ####################################### 67 | 68 | DEFAULT_I2C_BUFFER_LEN LITERAL1 69 | VL53L8CX_NB_TARGET_PER_ZONE LITERAL1 70 | VL53L8CX_API_REVISION LITERAL1 71 | VL53L8CX_DEFAULT_I2C_ADDRESS LITERAL1 72 | VL53L8CX_RESOLUTION_4X4 LITERAL1 73 | VL53L8CX_RESOLUTION_8X8 LITERAL1 74 | VL53L8CX_TARGET_ORDER_CLOSEST LITERAL1 75 | VL53L8CX_TARGET_ORDER_STRONGEST LITERAL1 76 | VL53L8CX_RANGING_MODE_CONTINUOUS LITERAL1 77 | VL53L8CX_RANGING_MODE_AUTONOMOUS LITERAL1 78 | VL53L8CX_POWER_MODE_SLEEP LITERAL1 79 | VL53L8CX_POWER_MODE_WAKEUP LITERAL1 80 | VL53L8CX_STATUS_OK LITERAL1 81 | VL53L8CX_MCU_ERROR LITERAL1 82 | VL53L8CX_STATUS_INVALID_PARAM LITERAL1 83 | VL53L8CX_STATUS_ERROR LITERAL1 84 | VL53L8CX_START_BH LITERAL1 85 | VL53L8CX_METADATA_BH LITERAL1 86 | VL53L8CX_COMMONDATA_BH LITERAL1 87 | VL53L8CX_AMBIENT_RATE_BH LITERAL1 88 | VL53L8CX_SPAD_COUNT_BH LITERAL1 89 | VL53L8CX_NB_TARGET_DETECTED_BH LITERAL1 90 | VL53L8CX_SIGNAL_RATE_BH LITERAL1 91 | VL53L8CX_RANGE_SIGMA_MM_BH LITERAL1 92 | VL53L8CX_DISTANCE_BH LITERAL1 93 | VL53L8CX_REFLECTANCE_BH LITERAL1 94 | VL53L8CX_TARGET_STATUS_BH LITERAL1 95 | VL53L8CX_MOTION_DETECT_BH LITERAL1 96 | VL53L8CX_METADATA_IDX LITERAL1 97 | VL53L8CX_SPAD_COUNT_IDX LITERAL1 98 | VL53L8CX_AMBIENT_RATE_IDX LITERAL1 99 | VL53L8CX_NB_TARGET_DETECTED_IDX LITERAL1 100 | VL53L8CX_SIGNAL_RATE_IDX LITERAL1 101 | VL53L8CX_RANGE_SIGMA_MM_IDX LITERAL1 102 | VL53L8CX_DISTANCE_IDX LITERAL1 103 | VL53L8CX_REFLECTANCE_EST_PC_IDX LITERAL1 104 | VL53L8CX_TARGET_STATUS_IDX LITERAL1 105 | VL53L8CX_MOTION_DETEC_IDX LITERAL1 106 | VL53L8CX_NVM_DATA_SIZE LITERAL1 107 | VL53L8CX_CONFIGURATION_SIZE LITERAL1 108 | VL53L8CX_OFFSET_BUFFER_SIZE LITERAL1 109 | VL53L8CX_XTALK_BUFFER_SIZE LITERAL1 110 | VL53L8CX_DCI_ZONE_CONFIG LITERAL1 111 | VL53L8CX_DCI_FREQ_HZ LITERAL1 112 | VL53L8CX_DCI_INT_TIME LITERAL1 113 | VL53L8CX_DCI_FW_NB_TARGET LITERAL1 114 | VL53L8CX_DCI_RANGING_MODE LITERAL1 115 | VL53L8CX_DCI_DSS_CONFIG LITERAL1 116 | VL53L8CX_DCI_TARGET_ORDER LITERAL1 117 | VL53L8CX_DCI_SHARPENER LITERAL1 118 | VL53L8CX_DCI_MOTION_DETECTOR_CFG LITERAL1 119 | VL53L8CX_DCI_SINGLE_RANGE LITERAL1 120 | VL53L8CX_DCI_OUTPUT_CONFIG LITERAL1 121 | VL53L8CX_DCI_OUTPUT_ENABLES LITERAL1 122 | VL53L8CX_DCI_OUTPUT_LIST LITERAL1 123 | VL53L8CX_DCI_PIPE_CONTROL LITERAL1 124 | VL53L8CX_UI_CMD_STATUS LITERAL1 125 | VL53L8CX_UI_CMD_START LITERAL1 126 | VL53L8CX_UI_CMD_END LITERAL1 127 | L5CX_AMB_SIZE LITERAL1 128 | L5CX_SPAD_SIZE LITERAL1 129 | L5CX_NTAR_SIZE LITERAL1 130 | L5CX_SPS_SIZE LITERAL1 131 | L5CX_SIGR_SIZE LITERAL1 132 | L5CX_DIST_SIZE LITERAL1 133 | L5CX_RFLEST_SIZE LITERAL1 134 | L5CX_STA_SIZE LITERAL1 135 | L5CX_MOT_SIZE LITERAL1 136 | VL53L8CX_MAX_RESULTS_SIZE LITERAL1 137 | VL53L8CX_TEMPORARY_BUFFER_SIZE LITERAL1 138 | VL53L8CX_FW_NBTAR_RANGING LITERAL1 139 | VL53L8CX_NB_THRESHOLDS LITERAL1 140 | VL53L8CX_DCI_DET_THRESH_CONFIG LITERAL1 141 | VL53L8CX_DCI_DET_THRESH_GLOBAL_CONFIG LITERAL1 142 | VL53L8CX_DCI_DET_THRESH_START LITERAL1 143 | VL53L8CX_DCI_DET_THRESH_VALID_STATUS LITERAL1 144 | VL53L8CX_LAST_THRESHOLD LITERAL1 145 | VL53L8CX_DISTANCE_MM LITERAL1 146 | VL53L8CX_SIGNAL_PER_SPAD_KCPS LITERAL1 147 | VL53L8CX_RANGE_SIGMA_MM LITERAL1 148 | VL53L8CX_AMBIENT_PER_SPAD_KCPS LITERAL1 149 | VL53L8CX_NB_TARGET_DETECTED LITERAL1 150 | VL53L8CX_TARGET_STATUS LITERAL1 151 | VL53L8CX_NB_SPADS_ENABLED LITERAL1 152 | VL53L8CX_MOTION_INDICATOR LITERAL1 153 | VL53L8CX_IN_WINDOW LITERAL1 154 | VL53L8CX_OUT_OF_WINDOW LITERAL1 155 | VL53L8CX_LESS_THAN_EQUAL_MIN_CHECKER LITERAL1 156 | VL53L8CX_GREATER_THAN_MAX_CHECKER LITERAL1 157 | VL53L8CX_EQUAL_MIN_CHECKER LITERAL1 158 | VL53L8CX_NOT_EQUAL_MIN_CHECKER LITERAL1 159 | VL53L8CX_OPERATION_NONE LITERAL1 160 | VL53L8CX_OPERATION_OR LITERAL1 161 | VL53L8CX_OPERATION_AND LITERAL1 162 | VL53L8CX_FW_NBTAR_XTALK LITERAL1 163 | VL53L8CX_DCI_CAL_CFG LITERAL1 164 | VL53L8CX_DCI_XTALK_CFG LITERAL1 165 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=STM32duino VL53L8CX 2 | version=2.0.3 3 | author=STMicroelectronics 4 | maintainer=stm32duino 5 | sentence=Allows controlling the VL53L8CX (Time-of-Flight 8x8 multizone ranging sensor with wide field view) 6 | paragraph= This library provides simple measure distance in mm 7 | category=Device Control 8 | url= https://github.com/stm32duino/VL53L8CX 9 | architectures=* 10 | -------------------------------------------------------------------------------- /src/vl53l8cx.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file vl53l8cx.cpp 4 | * @author STMicroelectronics 5 | * @version V2.0.0 6 | * @date 27 June 2024 7 | * @brief Implementation of of a VL53L8CX Time of Flight(TOF) sensor. 8 | ****************************************************************************** 9 | * @attention 10 | * 11 | *

© COPYRIGHT(c) 2024 STMicroelectronics

12 | * 13 | * Redistribution and use in source and binary forms, with or without modification, 14 | * are permitted provided that the following conditions are met: 15 | * 1. Redistributions of source code must retain the above copyright notice, 16 | * this list of conditions and the following disclaimer. 17 | * 2. Redistributions in binary form must reproduce the above copyright notice, 18 | * this list of conditions and the following disclaimer in the documentation 19 | * and/or other materials provided with the distribution. 20 | * 3. Neither the name of STMicroelectronics nor the names of its contributors 21 | * may be used to endorse or promote products derived from this software 22 | * without specific prior written permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 | * DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 30 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 31 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 32 | * OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 33 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | * 35 | ****************************************************************************** 36 | */ 37 | 38 | 39 | /* Includes ------------------------------------------------------------------*/ 40 | #include "vl53l8cx.h" 41 | 42 | 43 | /** Constructor 44 | * @param i2c device I2C to be used for communication 45 | * @param _lpn_pin pin to be used as component LPn 46 | * @param _i2c_rst_pin pin to be used as component I2C_RST 47 | */ 48 | VL53L8CX::VL53L8CX(TwoWire *i2c, int _lpn_pin, int _i2c_rst_pin): dev_i2c(i2c), lpn_pin(_lpn_pin), i2c_rst_pin(_i2c_rst_pin) 49 | { 50 | memset((void *)&_dev, 0x0, sizeof(VL53L8CX_Configuration)); 51 | dev_spi = NULL; 52 | _dev.platform.address = VL53L8CX_DEFAULT_I2C_ADDRESS; 53 | _dev.platform.Write = VL53L8CX_io_write; 54 | _dev.platform.Read = VL53L8CX_io_read; 55 | _dev.platform.Wait = VL53L8CX_io_wait; 56 | _dev.platform.handle = (void *)this; 57 | p_dev = &_dev; 58 | } 59 | /** Constructor 60 | * @param spi object of an helper class which handles the SPI peripheral 61 | * @param _cs_pin the chip select pin 62 | * @param _lpn_pin pin to be used as component LPn 63 | * @param _i2c_rst_pin pin to be used as component I2C_RST 64 | * @param _spi_speed the SPI speed in Hz 65 | */ 66 | VL53L8CX::VL53L8CX(SPIClass *spi, int _cs_pin, int _lpn_pin, int _i2c_rst_pin, uint32_t _spi_speed) : dev_spi(spi), cs_pin(_cs_pin), lpn_pin(_lpn_pin), i2c_rst_pin(_i2c_rst_pin), spi_speed(_spi_speed) 67 | { 68 | memset((void *)&_dev, 0x0, sizeof(VL53L8CX_Configuration)); 69 | dev_i2c = NULL; 70 | _dev.platform.address = VL53L8CX_DEFAULT_I2C_ADDRESS; 71 | _dev.platform.Write = VL53L8CX_io_write; 72 | _dev.platform.Read = VL53L8CX_io_read; 73 | _dev.platform.Wait = VL53L8CX_io_wait; 74 | _dev.platform.handle = (void *)this; 75 | p_dev = &_dev; 76 | } 77 | 78 | /** Destructor 79 | */ 80 | VL53L8CX::~VL53L8CX() {} 81 | 82 | /** 83 | * @brief Initialize the pins of the sensor 84 | * @return Status 0 if check is OK. 85 | */ 86 | int VL53L8CX::begin() 87 | { 88 | if (lpn_pin >= 0) { 89 | pinMode(lpn_pin, OUTPUT); 90 | digitalWrite(lpn_pin, LOW); 91 | delay(10); 92 | digitalWrite(lpn_pin, HIGH); 93 | } 94 | if (i2c_rst_pin >= 0) { 95 | pinMode(i2c_rst_pin, OUTPUT); 96 | if (dev_i2c) { 97 | digitalWrite(i2c_rst_pin, LOW); 98 | } 99 | if (dev_spi) { 100 | digitalWrite(i2c_rst_pin, HIGH); 101 | } 102 | } 103 | if (dev_spi) { 104 | // Configure CS pin 105 | pinMode(cs_pin, OUTPUT); 106 | digitalWrite(cs_pin, HIGH); 107 | } 108 | return 0; 109 | } 110 | 111 | /** 112 | * @brief Deinitialize the pins of the sensor 113 | * @return Status 0 if check is OK. 114 | */ 115 | int VL53L8CX::end() 116 | { 117 | if (lpn_pin >= 0) { 118 | pinMode(lpn_pin, INPUT); 119 | } 120 | if (i2c_rst_pin >= 0) { 121 | pinMode(i2c_rst_pin, INPUT); 122 | } 123 | /* Reset CS configuration */ 124 | if (dev_spi) { 125 | // Configure CS pin 126 | pinMode(cs_pin, INPUT); 127 | } 128 | return 0; 129 | } 130 | 131 | /** 132 | * @brief PowerOn the sensor 133 | * @return void 134 | */ 135 | void VL53L8CX::on(void) 136 | { 137 | if (lpn_pin >= 0) { 138 | digitalWrite(lpn_pin, HIGH); 139 | } 140 | delay(10); 141 | } 142 | 143 | /** 144 | * @brief PowerOff the sensor 145 | * @return void 146 | */ 147 | void VL53L8CX::off(void) 148 | { 149 | if (lpn_pin >= 0) { 150 | digitalWrite(lpn_pin, LOW); 151 | } 152 | delay(10); 153 | } 154 | 155 | /** 156 | * @brief Reset I2C peripheral of the sensor 157 | * @return void 158 | */ 159 | void VL53L8CX::i2c_reset(void) 160 | { 161 | if (dev_i2c && i2c_rst_pin >= 0) { 162 | digitalWrite(i2c_rst_pin, LOW); 163 | delay(10); 164 | digitalWrite(i2c_rst_pin, HIGH); 165 | delay(10); 166 | digitalWrite(i2c_rst_pin, LOW); 167 | delay(10); 168 | } 169 | } 170 | 171 | /** 172 | * @brief Check if the VL53L8CX sensor is alive(responding to I2C communication). 173 | * @param p_is_alive Pointer to the variable that will be set to indicate if the sensor is alive. 174 | * @return Status 0 if check is OK. 175 | */ 176 | uint8_t VL53L8CX::is_alive(uint8_t *p_is_alive) 177 | { 178 | return vl53l8cx_is_alive(p_dev, p_is_alive); 179 | } 180 | 181 | /** 182 | * @brief Initialize the VL53L8CX sensor. 183 | * @return Status 0 if initialization is OK. 184 | */ 185 | uint8_t VL53L8CX::init(void) 186 | { 187 | return vl53l8cx_init(p_dev); 188 | } 189 | 190 | /** 191 | * @brief Set the I2C address of the VL53L8CX sensor. 192 | * @param i2c_address The new I2C address to be set for the sensor. 193 | * @return Status 0 if the address is set correctly. 194 | */ 195 | uint8_t VL53L8CX::set_i2c_address(uint16_t i2c_address) 196 | { 197 | return vl53l8cx_set_i2c_address(p_dev, i2c_address); 198 | } 199 | 200 | /** 201 | * @brief Get the current power mode of the VL53L8CX sensor. 202 | * @param p_power_mode Pointer to the variable that will be set to the current power mode. 203 | * @return Status 0 if the power mode is retrieved successfully. 204 | */ 205 | uint8_t VL53L8CX::get_power_mode(uint8_t *p_power_mode) 206 | { 207 | return vl53l8cx_get_power_mode(p_dev, p_power_mode); 208 | } 209 | 210 | /** 211 | * @brief Set the power mode of the VL53L8CX sensor. 212 | * @param power_mode The power mode to be set(e.g., sleep or wakeup). 213 | * @return Status 0 if the power mode is set successfully, or 127 if the requested power mode is not valid. 214 | */ 215 | uint8_t VL53L8CX::set_power_mode(uint8_t power_mode) 216 | { 217 | return vl53l8cx_set_power_mode(p_dev, power_mode); 218 | } 219 | 220 | /** 221 | * @brief Start a ranging session with the VL53L8CX sensor. 222 | * @return Status 0 if the ranging session starts successfully. 223 | */ 224 | uint8_t VL53L8CX::start_ranging(void) 225 | { 226 | return vl53l8cx_start_ranging(p_dev); 227 | } 228 | 229 | /** 230 | * @brief Stop the current ranging session with the VL53L8CX sensor. 231 | * @return Status 0 if the ranging session stops successfully. 232 | */ 233 | uint8_t VL53L8CX::stop_ranging(void) 234 | { 235 | return vl53l8cx_stop_ranging(p_dev); 236 | } 237 | 238 | /** 239 | * @brief Check if new ranging data is ready. 240 | * @param p_isReady Pointer to the variable that will be updated to indicate if new data is ready. 241 | * @return Status 0 if the data ready check is successful. 242 | */ 243 | uint8_t VL53L8CX::check_data_ready(uint8_t *p_isReady) 244 | { 245 | return vl53l8cx_check_data_ready(p_dev, p_isReady); 246 | } 247 | 248 | /** 249 | * @brief Get the ranging data from the VL53L8CX sensor. 250 | * @param p_results Pointer to the results data structure where the ranging data will be stored. 251 | * @return Status 0 if the data is retrieved successfully. 252 | */ 253 | uint8_t VL53L8CX::get_ranging_data(VL53L8CX_ResultsData *p_results) 254 | { 255 | return vl53l8cx_get_ranging_data(p_dev, p_results); 256 | } 257 | 258 | /** 259 | * @brief Get the current resolution of the VL53L8CX sensor. 260 | * @param p_resolution Pointer to the variable that will be set to the current resolution. 261 | * @return Status 0 if the resolution is retrieved successfully. 262 | */ 263 | uint8_t VL53L8CX::get_resolution(uint8_t *p_resolution) 264 | { 265 | return vl53l8cx_get_resolution(p_dev, p_resolution); 266 | } 267 | 268 | /** 269 | * @brief Set a new resolution for the VL53L8CX sensor. 270 | * @param resolution The new resolution to be set. 271 | * @return Status 0 if the resolution is set successfully. 272 | */ 273 | uint8_t VL53L8CX::set_resolution(uint8_t resolution) 274 | { 275 | return vl53l8cx_set_resolution(p_dev, resolution); 276 | } 277 | 278 | /** 279 | * @brief Get the current ranging frequency of the VL53L8CX sensor in Hz. 280 | * @param p_frequency_hz Pointer to the variable that will be set to the current ranging frequency. 281 | * @return Status 0 if the ranging frequency is retrieved successfully. 282 | */ 283 | uint8_t VL53L8CX::get_ranging_frequency_hz(uint8_t *p_frequency_hz) 284 | { 285 | return vl53l8cx_get_ranging_frequency_hz(p_dev, p_frequency_hz); 286 | } 287 | 288 | /** 289 | * @brief Set a new ranging frequency for the VL53L8CX sensor in Hz. 290 | * @param frequency_hz The new ranging frequency to be set. 291 | * @return Status 0 if the ranging frequency is set successfully, or 127 if the value is not correct. 292 | */ 293 | uint8_t VL53L8CX::set_ranging_frequency_hz(uint8_t frequency_hz) 294 | { 295 | return vl53l8cx_set_ranging_frequency_hz(p_dev, frequency_hz); 296 | } 297 | 298 | /** 299 | * @brief Get the current integration time of the VL53L8CX sensor in ms. 300 | * @param p_time_ms Pointer to the variable that will be set to the current integration time. 301 | * @return Status 0 if the integration time is retrieved successfully. 302 | */ 303 | uint8_t VL53L8CX::get_integration_time_ms(uint32_t *p_time_ms) 304 | { 305 | return vl53l8cx_get_integration_time_ms(p_dev, p_time_ms); 306 | } 307 | 308 | /** 309 | * @brief Set a new integration time for the VL53L8CX sensor in ms. 310 | * @param integration_time_ms The new integration time to be set. 311 | * @return Status 0 if the integration time is set successfully. 312 | */ 313 | uint8_t VL53L8CX::set_integration_time_ms(uint32_t integration_time_ms) 314 | { 315 | return vl53l8cx_set_integration_time_ms(p_dev, integration_time_ms); 316 | } 317 | 318 | /** 319 | * @brief Get the current sharpener percentage of the VL53L8CX sensor. 320 | * @param p_sharpener_percent Pointer to the variable that will be set to the current sharpener percentage. 321 | * @return Status 0 if the sharpener percentage is retrieved successfully. 322 | */ 323 | uint8_t VL53L8CX::get_sharpener_percent(uint8_t *p_sharpener_percent) 324 | { 325 | return vl53l8cx_get_sharpener_percent(p_dev, p_sharpener_percent); 326 | } 327 | 328 | /** 329 | * @brief Set a new sharpener percentage for the VL53L8CX sensor. 330 | * @param sharpener_percent The new sharpener percentage to be set. 331 | * @return Status 0 if the sharpener percentage is set successfully. 332 | */ 333 | uint8_t VL53L8CX::set_sharpener_percent(uint8_t sharpener_percent) 334 | { 335 | return vl53l8cx_set_sharpener_percent(p_dev, sharpener_percent); 336 | } 337 | /** 338 | * @brief Get the current target order of the VL53L8CX sensor(closest or strongest). 339 | * @param p_target_order Pointer to the variable that will be set to the current target order. 340 | * @return Status 0 if the target order is retrieved successfully. 341 | */ 342 | uint8_t VL53L8CX::get_target_order(uint8_t *p_target_order) 343 | { 344 | return vl53l8cx_get_target_order(p_dev, p_target_order); 345 | } 346 | 347 | /** 348 | * @brief Set a new target order for the VL53L8CX sensor. 349 | * @param target_order The new target order to be set. 350 | * @return Status 0 if the target order is set successfully, or 127 if the target order is unknown. 351 | */ 352 | uint8_t VL53L8CX::set_target_order(uint8_t target_order) 353 | { 354 | return vl53l8cx_set_target_order(p_dev, target_order); 355 | } 356 | 357 | /** 358 | * @brief Get the current ranging mode of the VL53L8CX sensor. 359 | * @param p_ranging_mode Pointer to the variable that will be set to the current ranging mode. 360 | * @return Status 0 if the ranging mode is retrieved successfully. 361 | */ 362 | uint8_t VL53L8CX::get_ranging_mode(uint8_t *p_ranging_mode) 363 | { 364 | return vl53l8cx_get_ranging_mode(p_dev, p_ranging_mode); 365 | } 366 | 367 | /** 368 | * @brief Set the ranging mode of the VL53L8CX sensor. 369 | * @param ranging_mode The new ranging mode to be set. 370 | * @return Status 0 if the ranging mode is set successfully. 371 | */ 372 | uint8_t VL53L8CX::set_ranging_mode(uint8_t ranging_mode) 373 | { 374 | return vl53l8cx_set_ranging_mode(p_dev, ranging_mode); 375 | } 376 | 377 | /** 378 | * @brief Check if the synchronization pin of the VL53L8CX sensor is enabled. 379 | * @param p_is_sync_pin_enabled Pointer to the variable that will be updated to indicate if the sync pin is enabled. 380 | * @return Status 0 if the sync pin status is retrieved successfully. 381 | */ 382 | uint8_t VL53L8CX::get_external_sync_pin_enable(uint8_t *p_is_sync_pin_enabled) 383 | { 384 | return vl53l8cx_get_external_sync_pin_enable(p_dev, p_is_sync_pin_enabled); 385 | } 386 | 387 | /** 388 | * @brief Enable or disable the synchronization pin of the VL53L8CX sensor. 389 | * @param enable_sync_pin Set to 1 to enable the sync pin, or 0 to disable it. 390 | * @return Status 0 if the sync pin is set successfully. 391 | */ 392 | uint8_t VL53L8CX::set_external_sync_pin_enable(uint8_t enable_sync_pin) 393 | { 394 | return vl53l8cx_set_external_sync_pin_enable(p_dev, enable_sync_pin); 395 | } 396 | 397 | /** 398 | * @brief Get the number of frames between two temperature compensations for the VL53L8CX sensor. 399 | * @param p_repeat_count Pointer to the variable that will be set to the number of frames before the next temperature compensation. 400 | * @return Status 0 if the repeat count is retrieved successfully. 401 | */ 402 | uint8_t VL53L8CX::get_VHV_repeat_count(uint32_t *p_repeat_count) 403 | { 404 | return vl53l8cx_get_VHV_repeat_count(p_dev, p_repeat_count); 405 | } 406 | 407 | 408 | /** 409 | * @brief Set the number of frames between two temperature compensations for the VL53L8CX sensor. 410 | * @param repeat_count The number of frames between temperature compensations to be set. 411 | * @return Status 0 if the repeat count is set successfully. 412 | */ 413 | uint8_t VL53L8CX::set_VHV_repeat_count(uint32_t repeat_count) 414 | { 415 | return vl53l8cx_set_VHV_repeat_count(p_dev, repeat_count); 416 | } 417 | 418 | /** 419 | * @brief Read 'extra data' from the VL53L8CX sensor using DCI(Device Configuration Interface). 420 | * @param data Pointer to the data array or casted structure where the read data will be stored. 421 | * @param index Index of the required value to be read. 422 | * @param data_size Size of the data array or casted structure(use sizeof() function). 423 | * @return Status 0 if the read operation is successful. 424 | */ 425 | uint8_t VL53L8CX::dci_read_data(uint8_t *data, uint32_t index, uint16_t data_size) 426 | { 427 | return vl53l8cx_dci_read_data(p_dev, data, index, data_size); 428 | } 429 | 430 | /** 431 | * @brief Write 'extra data' to the VL53L8CX sensor using DCI(Device Configuration Interface). 432 | * @param data Pointer to the data array or casted structure containing the data to be written. 433 | * @param index Index of the required value to be written. 434 | * @param data_size Size of the data array or casted structure(use sizeof() function). 435 | * @return Status 0 if the write operation is successful. 436 | */ 437 | uint8_t VL53L8CX::dci_write_data(uint8_t *data, uint32_t index, uint16_t data_size) 438 | { 439 | return vl53l8cx_dci_write_data(p_dev, data, index, data_size); 440 | } 441 | 442 | /** 443 | * @brief Replace 'extra data' in the VL53L8CX sensor using DCI(Device Configuration Interface). 444 | * @param data Pointer to the data array or casted structure where the current data is stored. 445 | * @param index Index of the required value to be replaced. 446 | * @param data_size Size of the data array or casted structure(use sizeof() function). 447 | * @param new_data Pointer to the new data array containing the fields to be replaced. 448 | * @param new_data_size Size of the new data array. 449 | * @param new_data_pos Position of the new data in the buffer. 450 | * @return Status 0 if the replace operation is successful. 451 | */ 452 | uint8_t VL53L8CX::dci_replace_data(uint8_t *data, uint32_t index, uint16_t data_size, uint8_t *new_data, uint16_t new_data_size, uint16_t new_data_pos) 453 | { 454 | return vl53l8cx_dci_replace_data(p_dev, 455 | data, 456 | index, 457 | data_size, 458 | new_data, 459 | new_data_size, 460 | new_data_pos); 461 | } 462 | 463 | 464 | /** 465 | * @brief Check if the detection thresholds are enabled on the VL53L8CX sensor. 466 | * @param p_enabled Pointer to the variable that will be set to 1 if thresholds are enabled, or 0 if disabled. 467 | * @return Status 0 if the check is successful. 468 | */ 469 | uint8_t VL53L8CX::get_detection_thresholds_enable(uint8_t *p_enabled) 470 | { 471 | return vl53l8cx_get_detection_thresholds_enable(p_dev, p_enabled); 472 | } 473 | 474 | /** 475 | * @brief Enable or disable the detection thresholds on the VL53L8CX sensor. 476 | * @param enabled Set to 1 to enable thresholds, or 0 to disable them. 477 | * @return Status 0 if the thresholds are set successfully. 478 | */ 479 | uint8_t VL53L8CX::set_detection_thresholds_enable(uint8_t enabled) 480 | { 481 | return vl53l8cx_set_detection_thresholds_enable(p_dev, enabled); 482 | } 483 | 484 | /** 485 | * @brief Get the detection thresholds from the VL53L8CX sensor. 486 | * @param p_thresholds Pointer to the array where the detection thresholds will be stored. 487 | * @return Status 0 if the thresholds are retrieved successfully. 488 | */ 489 | uint8_t VL53L8CX::get_detection_thresholds(VL53L8CX_DetectionThresholds *p_thresholds) 490 | { 491 | return vl53l8cx_get_detection_thresholds(p_dev, p_thresholds); 492 | } 493 | 494 | /** 495 | * @brief Set the detection thresholds on the VL53L8CX sensor. 496 | * @param p_thresholds Pointer to the array containing the new detection thresholds. 497 | * @return Status 0 if the thresholds are programmed successfully. 498 | */ 499 | uint8_t VL53L8CX::set_detection_thresholds(VL53L8CX_DetectionThresholds *p_thresholds) 500 | { 501 | return vl53l8cx_set_detection_thresholds(p_dev, p_thresholds); 502 | } 503 | 504 | /** 505 | * @brief Get the status of the auto-stop feature on the VL53L8CX sensor when using detection thresholds. 506 | * @param p_auto_stop Pointer to the variable that will be set to 1 if auto-stop is enabled, or 0 if disabled. 507 | * @return Status 0 if the auto-stop status is retrieved successfully. 508 | */ 509 | uint8_t VL53L8CX::get_detection_thresholds_auto_stop(uint8_t *p_auto_stop) 510 | { 511 | return vl53l8cx_get_detection_thresholds_auto_stop(p_dev, p_auto_stop); 512 | } 513 | 514 | /** 515 | * @brief Enable or disable the auto-stop feature on the VL53L8CX sensor when using detection thresholds. 516 | * @param auto_stop Set to 1 to enable auto-stop, or 0 to disable it. 517 | * @return Status 0 if the auto-stop feature is set successfully. 518 | */ 519 | uint8_t VL53L8CX::set_detection_thresholds_auto_stop(uint8_t auto_stop) 520 | { 521 | return vl53l8cx_set_detection_thresholds_auto_stop(p_dev, auto_stop); 522 | } 523 | 524 | 525 | /** 526 | * @brief Initialize the motion indicator with the default monitoring range. 527 | * @param p_motion_config Pointer to the structure containing the initialized motion configuration. 528 | * @param resolution The desired resolution, defined by macros VL53L8CX_RESOLUTION_4X4 or VL53L8CX_RESOLUTION_8X8. 529 | * @return Status 0 if initialization is successful, or 127 if the resolution is unknown. 530 | */ 531 | uint8_t VL53L8CX::motion_indicator_init(VL53L8CX_Motion_Configuration *p_motion_config, uint8_t resolution) 532 | { 533 | return vl53l8cx_motion_indicator_init(p_dev, p_motion_config, resolution); 534 | } 535 | 536 | /** 537 | * @brief Change the working distance range of the motion indicator. 538 | * @param p_motion_config Pointer to the structure containing the motion configuration. 539 | * @param distance_min_mm Minimum distance for the motion indicator(minimum value 400mm, maximum 4000mm). 540 | * @param distance_max_mm Maximum distance for the motion indicator(minimum value 400mm, maximum 4000mm). 541 | * @return Status 0 if the configuration is successful, or 127 if an argument is invalid. 542 | */ 543 | uint8_t VL53L8CX::motion_indicator_set_distance_motion(VL53L8CX_Motion_Configuration *p_motion_config, uint16_t distance_min_mm, uint16_t distance_max_mm) 544 | { 545 | return vl53l8cx_motion_indicator_set_distance_motion(p_dev, p_motion_config, distance_min_mm, distance_max_mm); 546 | } 547 | 548 | /** 549 | * @brief Update the internal motion indicator map to a new resolution. 550 | * @param p_motion_config Pointer to the structure containing the motion configuration. 551 | * @param resolution The desired SCI resolution, defined by macros VL53L8CX_RESOLUTION_4X4 or VL53L8CX_RESOLUTION_8X8. 552 | * @return Status 0 if the update is successful, or 127 if the resolution is unknown. 553 | */ 554 | uint8_t VL53L8CX::motion_indicator_set_resolution(VL53L8CX_Motion_Configuration *p_motion_config, uint8_t resolution) 555 | { 556 | return vl53l8cx_motion_indicator_set_resolution(p_dev, p_motion_config, resolution); 557 | } 558 | 559 | /** 560 | * @brief Start the VL53L8CX sensor to calibrate Xtalk, recommended for use with a coverglass. 561 | * @param reflectance_percent Target reflectance in percent, between 1 and 99%. ST recommends a 3% target reflectance for better efficiency. 562 | * @param nb_samples Number of samples used for calibration. More samples increase accuracy but also calibration time. Minimum is 1, maximum is 16. 563 | * @param distance_mm Target distance in mm for calibration. Minimum allowed is 600mm, maximum is 3000mm. The target must stay in Full FOV. 564 | * @return Status 0 if calibration is successful, 127 if an argument has an incorrect value, or 255 if something failed. 565 | */ 566 | uint8_t VL53L8CX::calibrate_xtalk(uint16_t reflectance_percent, uint8_t nb_samples, uint16_t distance_mm) 567 | { 568 | return vl53l8cx_calibrate_xtalk(p_dev, reflectance_percent, nb_samples, distance_mm); 569 | } 570 | 571 | /** 572 | * @brief Get the Xtalk calibration data buffer, available after using vl53l8cx_calibrate_xtalk(). 573 | * @param p_xtalk_data Buffer to store Xtalk data, size defined by VL53L8CX_XTALK_SIZE macro. 574 | * @return Status 0 if buffer reading is successful. 575 | */ 576 | uint8_t VL53L8CX::get_caldata_xtalk(uint8_t *p_xtalk_data) 577 | { 578 | return vl53l8cx_get_caldata_xtalk(p_dev, p_xtalk_data); 579 | } 580 | 581 | /** 582 | * @brief Set the Xtalk calibration data buffer, can be used to override the default Xtalk buffer. 583 | * @param p_xtalk_data Buffer containing Xtalk data, size defined by VL53L8CX_XTALK_SIZE macro. 584 | * @return Status 0 if buffer is set successfully. 585 | */ 586 | uint8_t VL53L8CX::set_caldata_xtalk(uint8_t *p_xtalk_data) 587 | { 588 | return vl53l8cx_set_caldata_xtalk(p_dev, p_xtalk_data); 589 | } 590 | 591 | /** 592 | * @brief Get the Xtalk margin, used to increase the Xtalk threshold and avoid false positives after calibration. 593 | * @param p_xtalk_margin Pointer to store the current Xtalk margin in kcps/spads. 594 | * @return Status 0 if reading is successful. 595 | */ 596 | uint8_t VL53L8CX::get_xtalk_margin(uint32_t *p_xtalk_margin) 597 | { 598 | return vl53l8cx_get_xtalk_margin(p_dev, p_xtalk_margin); 599 | } 600 | 601 | /** 602 | * @brief Set the Xtalk margin, used to increase the Xtalk threshold and avoid false positives after calibration. 603 | * @param xtalk_margin New Xtalk margin in kcps/spads. Minimum value is 0, maximum is 10,000 kcps/spads. 604 | * @return Status 0 if the new margin is set successfully, or 127 if the margin is invalid. 605 | */ 606 | uint8_t VL53L8CX::set_xtalk_margin(uint32_t xtalk_margin) 607 | { 608 | return vl53l8cx_set_xtalk_margin(p_dev, xtalk_margin); 609 | } 610 | 611 | uint8_t VL53L8CX_io_write(void *handle, uint16_t RegisterAddress, uint8_t *p_values, uint32_t size) 612 | { 613 | return ((VL53L8CX *)handle)->IO_Write(RegisterAddress, p_values, size); 614 | } 615 | 616 | uint8_t VL53L8CX_io_read(void *handle, uint16_t RegisterAddress, uint8_t *p_values, uint32_t size) 617 | { 618 | return ((VL53L8CX *)handle)->IO_Read(RegisterAddress, p_values, size); 619 | } 620 | 621 | uint8_t VL53L8CX_io_wait(void *handle, uint32_t ms) 622 | { 623 | return ((VL53L8CX *)handle)->IO_Wait(ms); 624 | } 625 | -------------------------------------------------------------------------------- /src/vl53l8cx.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file vl53l8cx.h 4 | * @author STMicroelectronics 5 | * @version V2.0.0 6 | * @date 27 June 2024 7 | * @brief Abstract class of a VL53L8CX Time of Flight(TOF) sensor. 8 | ****************************************************************************** 9 | * @attention 10 | * 11 | *

© COPYRIGHT(c) 2024 STMicroelectronics

12 | * 13 | * Redistribution and use in source and binary forms, with or without modification, 14 | * are permitted provided that the following conditions are met: 15 | * 1. Redistributions of source code must retain the above copyright notice, 16 | * this list of conditions and the following disclaimer. 17 | * 2. Redistributions in binary form must reproduce the above copyright notice, 18 | * this list of conditions and the following disclaimer in the documentation 19 | * and/or other materials provided with the distribution. 20 | * 3. Neither the name of STMicroelectronics nor the names of its contributors 21 | * may be used to endorse or promote products derived from this software 22 | * without specific prior written permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 | * DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 30 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 31 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 32 | * OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 33 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | * 35 | ****************************************************************************** 36 | */ 37 | 38 | /* Prevent recursive inclusion -----------------------------------------------*/ 39 | #ifndef __VL53L8CX_H 40 | #define __VL53L8CX_H 41 | 42 | /* Includes ------------------------------------------------------------------*/ 43 | #include "Arduino.h" 44 | #include "Wire.h" 45 | #include "SPI.h" 46 | #include "vl53l8cx_platform.h" 47 | #include "vl53l8cx_api.h" 48 | #include "vl53l8cx_plugin_detection_thresholds.h" 49 | #include "vl53l8cx_plugin_motion_indicator.h" 50 | #include "vl53l8cx_plugin_xtalk.h" 51 | 52 | /* Class Declaration ---------------------------------------------------------*/ 53 | class VL53L8CX { 54 | public: 55 | VL53L8CX(TwoWire *i2c, int lpn_pin, int i2c_rst_pin = -1); 56 | VL53L8CX(SPIClass *spi, int cs_pin, int lpn_pin = -1, int i2c_rst_pin = -1, uint32_t spi_speed = 5000000); 57 | virtual ~VL53L8CX(void); 58 | virtual int begin(void); 59 | virtual int end(void); 60 | virtual void on(void); 61 | virtual void off(void); 62 | virtual void i2c_reset(void); 63 | uint8_t is_alive(uint8_t *p_is_alive); 64 | uint8_t init(void); 65 | uint8_t set_i2c_address(uint16_t i2c_address); 66 | uint8_t get_power_mode(uint8_t *p_power_mode); 67 | uint8_t set_power_mode(uint8_t power_mode); 68 | uint8_t start_ranging(void); 69 | uint8_t stop_ranging(void); 70 | uint8_t check_data_ready(uint8_t *p_isReady); 71 | uint8_t get_ranging_data(VL53L8CX_ResultsData *p_results); 72 | uint8_t get_resolution(uint8_t *p_resolution); 73 | uint8_t set_resolution(uint8_t resolution); 74 | uint8_t get_ranging_frequency_hz(uint8_t *p_frequency_hz); 75 | uint8_t set_ranging_frequency_hz(uint8_t frequency_hz); 76 | uint8_t get_integration_time_ms(uint32_t *p_time_ms); 77 | uint8_t set_integration_time_ms(uint32_t integration_time_ms); 78 | uint8_t get_sharpener_percent(uint8_t *p_sharpener_percent); 79 | uint8_t set_sharpener_percent(uint8_t sharpener_percent); 80 | uint8_t get_target_order(uint8_t *p_target_order); 81 | uint8_t set_target_order(uint8_t target_order); 82 | uint8_t get_ranging_mode(uint8_t *p_ranging_mode); 83 | uint8_t set_ranging_mode(uint8_t ranging_mode); 84 | uint8_t get_external_sync_pin_enable(uint8_t *p_is_sync_pin_enabled); 85 | uint8_t set_external_sync_pin_enable(uint8_t enable_sync_pin); 86 | uint8_t get_VHV_repeat_count(uint32_t *p_repeat_count); 87 | uint8_t set_VHV_repeat_count(uint32_t repeat_count); 88 | uint8_t dci_read_data(uint8_t *data, uint32_t index, uint16_t data_size); 89 | uint8_t dci_write_data(uint8_t *data, uint32_t index, uint16_t data_size); 90 | uint8_t dci_replace_data(uint8_t *data, uint32_t index, uint16_t data_size, uint8_t *new_data, uint16_t new_data_size, uint16_t new_data_pos); 91 | uint8_t get_detection_thresholds_enable(uint8_t *p_enabled); 92 | uint8_t set_detection_thresholds_enable(uint8_t enabled); 93 | uint8_t get_detection_thresholds(VL53L8CX_DetectionThresholds *p_thresholds); 94 | uint8_t set_detection_thresholds(VL53L8CX_DetectionThresholds *p_thresholds); 95 | uint8_t get_detection_thresholds_auto_stop(uint8_t *p_auto_stop); 96 | uint8_t set_detection_thresholds_auto_stop(uint8_t auto_stop); 97 | uint8_t motion_indicator_init(VL53L8CX_Motion_Configuration *p_motion_config, uint8_t resolution); 98 | uint8_t motion_indicator_set_distance_motion(VL53L8CX_Motion_Configuration *p_motion_config, uint16_t distance_min_mm, uint16_t distance_max_mm); 99 | uint8_t motion_indicator_set_resolution(VL53L8CX_Motion_Configuration *p_motion_config, uint8_t resolution); 100 | uint8_t calibrate_xtalk(uint16_t reflectance_percent, uint8_t nb_samples, uint16_t distance_mm); 101 | uint8_t get_caldata_xtalk(uint8_t *p_xtalk_data); 102 | uint8_t set_caldata_xtalk(uint8_t *p_xtalk_data); 103 | uint8_t get_xtalk_margin(uint32_t *p_xtalk_margin); 104 | uint8_t set_xtalk_margin(uint32_t xtalk_margin); 105 | 106 | /** 107 | * @brief Utility function to read data. 108 | * @param RegisterAddr: specifies internal address register to be read. 109 | * @param p_values: pointer to data to be read. 110 | * @param size: number of bytes to be read. 111 | * @retval 0 if ok, an error code otherwise. 112 | */ 113 | uint8_t IO_Read(uint16_t RegisterAddress, uint8_t *p_values, uint32_t size) 114 | { 115 | if (dev_i2c) { 116 | int status = 0; 117 | uint8_t buffer[2]; 118 | // Loop until the port is transmitted correctly 119 | do { 120 | dev_i2c->beginTransmission((uint8_t)((_dev.platform.address >> 1) & 0x7F)); 121 | // Target register address for transfer 122 | buffer[0] = (uint8_t)(RegisterAddress >> 8); 123 | buffer[1] = (uint8_t)(RegisterAddress & 0xFF); 124 | dev_i2c->write(buffer, 2); 125 | status = dev_i2c->endTransmission(false); 126 | // Fix for some STM32 boards 127 | // Reinitialize the i2c bus with the default parameters 128 | #ifdef ARDUINO_ARCH_STM32 129 | if (status) { 130 | dev_i2c->end(); 131 | dev_i2c->begin(); 132 | } 133 | #endif 134 | // End of fix 135 | } while (status != 0); 136 | uint32_t i = 0; 137 | if (size > DEFAULT_I2C_BUFFER_LEN) { 138 | while (i < size) { 139 | // If still more than DEFAULT_I2C_BUFFER_LEN bytes to go, DEFAULT_I2C_BUFFER_LEN, 140 | // else the remaining number of bytes 141 | uint8_t current_read_size = (size - i > DEFAULT_I2C_BUFFER_LEN ? DEFAULT_I2C_BUFFER_LEN : size - i); 142 | dev_i2c->requestFrom(((uint8_t)((_dev.platform.address >> 1) & 0x7F)), current_read_size); 143 | while (dev_i2c->available()) { 144 | p_values[i] = dev_i2c->read(); 145 | i++; 146 | } 147 | } 148 | } else { 149 | dev_i2c->requestFrom(((uint8_t)((_dev.platform.address >> 1) & 0x7F)), size); 150 | while (dev_i2c->available()) { 151 | p_values[i] = dev_i2c->read(); 152 | i++; 153 | } 154 | } 155 | return i != size; 156 | } 157 | if (dev_spi) { 158 | uint32_t position = 0; 159 | uint32_t data_size = 0; 160 | uint16_t temp; 161 | uint8_t data_write[VL53L8CX_COMMS_CHUNK_SIZE + 2]; 162 | for (position = 0; position < size; position += VL53L8CX_COMMS_CHUNK_SIZE) { 163 | if (size > VL53L8CX_COMMS_CHUNK_SIZE) { 164 | if ((position + VL53L8CX_COMMS_CHUNK_SIZE) > size) { 165 | data_size = size - position; 166 | } else { 167 | data_size = VL53L8CX_COMMS_CHUNK_SIZE; 168 | } 169 | } else { 170 | data_size = size; 171 | } 172 | temp = RegisterAddress + position; 173 | data_write[0] = SPI_READ_MASK(temp) >> 8; 174 | data_write[1] = SPI_READ_MASK(temp) & 0xFF; 175 | dev_spi->beginTransaction(SPISettings(spi_speed, MSBFIRST, SPI_MODE3)); 176 | digitalWrite(cs_pin, LOW); 177 | dev_spi->transfer(&data_write, 2); 178 | for (uint16_t i = 0; i < data_size; i++) { 179 | *(p_values + i + position) = dev_spi->transfer(0x00); 180 | } 181 | digitalWrite(cs_pin, HIGH); 182 | } 183 | return 0; 184 | } 185 | return 1; 186 | } 187 | 188 | /** 189 | * @brief Utility function to write data. 190 | * @param RegisterAddr: specifies internal address register to be written. 191 | * @param p_values: pointer to data to be written. 192 | * @param size: number of bytes to be written. 193 | * @retval 0 if ok, an error code otherwise. 194 | */ 195 | uint8_t IO_Write(uint16_t RegisterAddress, uint8_t *p_values, uint32_t size) 196 | { 197 | if (dev_i2c) { 198 | uint32_t i = 0; 199 | uint8_t buffer[2]; 200 | while (i < size) { 201 | // If still more than DEFAULT_I2C_BUFFER_LEN bytes to go, DEFAULT_I2C_BUFFER_LEN, 202 | // else the remaining number of bytes 203 | size_t current_write_size = (size - i > DEFAULT_I2C_BUFFER_LEN ? DEFAULT_I2C_BUFFER_LEN : size - i); 204 | dev_i2c->beginTransmission((uint8_t)((_dev.platform.address >> 1) & 0x7F)); 205 | // Target register address for transfer 206 | buffer[0] = (uint8_t)((RegisterAddress + i) >> 8); 207 | buffer[1] = (uint8_t)((RegisterAddress + i) & 0xFF); 208 | dev_i2c->write(buffer, 2); 209 | if (dev_i2c->write(p_values + i, current_write_size) == 0) { 210 | return 1; 211 | } else { 212 | i += current_write_size; 213 | if (size - i) { 214 | // Flush buffer and send stop bit so we have compatibility also with ESP32 platforms 215 | dev_i2c->endTransmission(true); 216 | } 217 | } 218 | } 219 | return dev_i2c->endTransmission(true); 220 | } 221 | 222 | if (dev_spi) { 223 | 224 | uint8_t status = 0; 225 | uint32_t i = 0; 226 | uint32_t position = 0; 227 | uint32_t data_size = 0; 228 | uint16_t temp; 229 | uint8_t data_write[VL53L8CX_COMMS_CHUNK_SIZE + 2]; 230 | for (position = 0; position < size; position += VL53L8CX_COMMS_CHUNK_SIZE) { 231 | if (size > VL53L8CX_COMMS_CHUNK_SIZE) { 232 | if ((position + VL53L8CX_COMMS_CHUNK_SIZE) > size) { 233 | data_size = size - position; 234 | } else { 235 | data_size = VL53L8CX_COMMS_CHUNK_SIZE; 236 | } 237 | } else { 238 | data_size = size; 239 | } 240 | temp = RegisterAddress + position; 241 | data_write[0] = SPI_WRITE_MASK(temp) >> 8; 242 | data_write[1] = SPI_WRITE_MASK(temp) & 0xFF; 243 | for (i = 0; i < data_size; i++) { 244 | data_write[i + 2] = p_values[position + i]; 245 | } 246 | data_size += 2; 247 | dev_spi->beginTransaction(SPISettings(spi_speed, MSBFIRST, SPI_MODE3)); 248 | digitalWrite(cs_pin, LOW); 249 | dev_spi->transfer(&data_write, data_size); 250 | digitalWrite(cs_pin, HIGH); 251 | } 252 | return status; 253 | } 254 | return 1; 255 | } 256 | 257 | /** 258 | * @brief Utility function to wait. 259 | * @param ms: milliseconds to wait. 260 | * @retval 0 261 | */ 262 | uint8_t IO_Wait(uint32_t ms) 263 | { 264 | delay(ms); 265 | return 0; 266 | } 267 | 268 | private: 269 | 270 | /* Helper classes. */ 271 | TwoWire *dev_i2c; 272 | SPIClass *dev_spi; 273 | 274 | /* Configuration */ 275 | int cs_pin; 276 | int lpn_pin; 277 | int i2c_rst_pin; 278 | uint32_t spi_speed; 279 | 280 | VL53L8CX_Configuration _dev; 281 | VL53L8CX_Configuration *p_dev; 282 | }; 283 | 284 | 285 | #ifdef __cplusplus 286 | extern "C" { 287 | #endif 288 | 289 | uint8_t VL53L8CX_io_write(void *handle, uint16_t RegisterAddress, uint8_t *p_values, uint32_t size); 290 | uint8_t VL53L8CX_io_read(void *handle, uint16_t RegisterAddress, uint8_t *p_values, uint32_t size); 291 | uint8_t VL53L8CX_io_wait(void *handle, uint32_t ms); 292 | 293 | #ifdef __cplusplus 294 | } 295 | #endif 296 | 297 | #endif /* __VL53L8CX_H */ 298 | -------------------------------------------------------------------------------- /src/vl53l8cx_api.c: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Copyright (c) 2021 STMicroelectronics. 4 | * All rights reserved. 5 | * 6 | * This software is licensed under terms that can be found in the LICENSE file 7 | * in the root directory of this software component. 8 | * If no LICENSE file comes with this software, it is provided AS-IS. 9 | * 10 | ****************************************************************************** 11 | */ 12 | 13 | #include 14 | #include 15 | #include "vl53l8cx_api.h" 16 | #include "vl53l8cx_buffers.h" 17 | 18 | /** 19 | * @brief Inner function, not available outside this file. This function is used 20 | * to wait for an answer from VL53L8CX sensor. 21 | */ 22 | 23 | static uint8_t _vl53l8cx_poll_for_answer( 24 | VL53L8CX_Configuration *p_dev, 25 | uint8_t size, 26 | uint8_t pos, 27 | uint16_t address, 28 | uint8_t mask, 29 | uint8_t expected_value) 30 | { 31 | uint8_t status = VL53L8CX_STATUS_OK; 32 | uint8_t timeout = 0; 33 | 34 | do { 35 | status |= VL53L8CX_RdMulti(&(p_dev->platform), address, 36 | p_dev->temp_buffer, size); 37 | status |= VL53L8CX_WaitMs(&(p_dev->platform), 10); 38 | 39 | if (timeout >= (uint8_t)200) { /* 2s timeout */ 40 | status |= (uint8_t)VL53L8CX_STATUS_TIMEOUT_ERROR; 41 | break; 42 | } else if ((size >= (uint8_t)4) 43 | && (p_dev->temp_buffer[2] >= (uint8_t)0x7f)) { 44 | status |= VL53L8CX_MCU_ERROR; 45 | break; 46 | } else { 47 | timeout++; 48 | } 49 | } while ((p_dev->temp_buffer[pos] & mask) != expected_value); 50 | 51 | return status; 52 | } 53 | 54 | /* 55 | * Inner function, not available outside this file. This function is used to 56 | * wait for the MCU to boot. 57 | */ 58 | static uint8_t _vl53l8cx_poll_for_mcu_boot( 59 | VL53L8CX_Configuration *p_dev) 60 | { 61 | uint8_t go2_status0, go2_status1, status = VL53L8CX_STATUS_OK; 62 | uint16_t timeout = 0; 63 | 64 | do { 65 | status |= VL53L8CX_RdByte(&(p_dev->platform), 0x06, &go2_status0); 66 | if ((go2_status0 & (uint8_t)0x80) != (uint8_t)0) { 67 | status |= VL53L8CX_RdByte(&(p_dev->platform), 0x07, &go2_status1); 68 | if (go2_status1 & (uint8_t)0x01) { 69 | status |= VL53L8CX_STATUS_OK; 70 | break; 71 | } 72 | } 73 | (void)VL53L8CX_WaitMs(&(p_dev->platform), 1); 74 | timeout++; 75 | 76 | if ((go2_status0 & (uint8_t)0x1) != (uint8_t)0) { 77 | break; 78 | } 79 | } while (timeout < (uint16_t)500); 80 | 81 | return status; 82 | } 83 | 84 | /** 85 | * @brief Inner function, not available outside this file. This function is used 86 | * to set the offset data gathered from NVM. 87 | */ 88 | 89 | static uint8_t _vl53l8cx_send_offset_data( 90 | VL53L8CX_Configuration *p_dev, 91 | uint8_t resolution) 92 | { 93 | uint8_t status = VL53L8CX_STATUS_OK; 94 | uint32_t signal_grid[64]; 95 | int16_t range_grid[64]; 96 | uint8_t dss_4x4[] = {0x0F, 0x04, 0x04, 0x00, 0x08, 0x10, 0x10, 0x07}; 97 | uint8_t footer[] = {0x00, 0x00, 0x00, 0x0F, 0x03, 0x01, 0x01, 0xE4}; 98 | int8_t i, j; 99 | uint16_t k; 100 | 101 | (void)memcpy(p_dev->temp_buffer, 102 | p_dev->offset_data, VL53L8CX_OFFSET_BUFFER_SIZE); 103 | 104 | /* Data extrapolation is required for 4X4 offset */ 105 | if (resolution == (uint8_t)VL53L8CX_RESOLUTION_4X4) { 106 | (void)memcpy(&(p_dev->temp_buffer[0x10]), dss_4x4, sizeof(dss_4x4)); 107 | VL53L8CX_SwapBuffer(p_dev->temp_buffer, VL53L8CX_OFFSET_BUFFER_SIZE); 108 | (void)memcpy(signal_grid, &(p_dev->temp_buffer[0x3C]), 109 | sizeof(signal_grid)); 110 | (void)memcpy(range_grid, &(p_dev->temp_buffer[0x140]), 111 | sizeof(range_grid)); 112 | 113 | for (j = 0; j < (int8_t)4; j++) { 114 | for (i = 0; i < (int8_t)4 ; i++) { 115 | signal_grid[i + (4 * j)] = 116 | (signal_grid[(2 * i) + (16 * j) + (int8_t)0] 117 | + signal_grid[(2 * i) + (16 * j) + (int8_t)1] 118 | + signal_grid[(2 * i) + (16 * j) + (int8_t)8] 119 | + signal_grid[(2 * i) + (16 * j) + (int8_t)9]) 120 | / (uint32_t)4; 121 | range_grid[i + (4 * j)] = 122 | (range_grid[(2 * i) + (16 * j)] 123 | + range_grid[(2 * i) + (16 * j) + 1] 124 | + range_grid[(2 * i) + (16 * j) + 8] 125 | + range_grid[(2 * i) + (16 * j) + 9]) 126 | / (int16_t)4; 127 | } 128 | } 129 | (void)memset(&range_grid[0x10], 0, (uint16_t)96); 130 | (void)memset(&signal_grid[0x10], 0, (uint16_t)192); 131 | (void)memcpy(&(p_dev->temp_buffer[0x3C]), 132 | signal_grid, sizeof(signal_grid)); 133 | (void)memcpy(&(p_dev->temp_buffer[0x140]), 134 | range_grid, sizeof(range_grid)); 135 | VL53L8CX_SwapBuffer(p_dev->temp_buffer, VL53L8CX_OFFSET_BUFFER_SIZE); 136 | } 137 | 138 | for (k = 0; k < (VL53L8CX_OFFSET_BUFFER_SIZE - (uint16_t)4); k++) { 139 | p_dev->temp_buffer[k] = p_dev->temp_buffer[k + (uint16_t)8]; 140 | } 141 | 142 | (void)memcpy(&(p_dev->temp_buffer[0x1E0]), footer, 8); 143 | status |= VL53L8CX_WrMulti(&(p_dev->platform), 0x2e18, p_dev->temp_buffer, 144 | VL53L8CX_OFFSET_BUFFER_SIZE); 145 | status |= _vl53l8cx_poll_for_answer(p_dev, 4, 1, 146 | VL53L8CX_UI_CMD_STATUS, 0xff, 0x03); 147 | 148 | return status; 149 | } 150 | 151 | /** 152 | * @brief Inner function, not available outside this file. This function is used 153 | * to set the Xtalk data from generic configuration, or user's calibration. 154 | */ 155 | 156 | static uint8_t _vl53l8cx_send_xtalk_data( 157 | VL53L8CX_Configuration *p_dev, 158 | uint8_t resolution) 159 | { 160 | uint8_t status = VL53L8CX_STATUS_OK; 161 | uint8_t res4x4[] = {0x0F, 0x04, 0x04, 0x17, 0x08, 0x10, 0x10, 0x07}; 162 | uint8_t dss_4x4[] = {0x00, 0x78, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08}; 163 | uint8_t profile_4x4[] = {0xA0, 0xFC, 0x01, 0x00}; 164 | uint32_t signal_grid[64]; 165 | int8_t i, j; 166 | 167 | (void)memcpy(p_dev->temp_buffer, &(p_dev->xtalk_data[0]), 168 | VL53L8CX_XTALK_BUFFER_SIZE); 169 | 170 | /* Data extrapolation is required for 4X4 Xtalk */ 171 | if (resolution == (uint8_t)VL53L8CX_RESOLUTION_4X4) { 172 | (void)memcpy(&(p_dev->temp_buffer[0x8]), 173 | res4x4, sizeof(res4x4)); 174 | (void)memcpy(&(p_dev->temp_buffer[0x020]), 175 | dss_4x4, sizeof(dss_4x4)); 176 | 177 | VL53L8CX_SwapBuffer(p_dev->temp_buffer, VL53L8CX_XTALK_BUFFER_SIZE); 178 | (void)memcpy(signal_grid, &(p_dev->temp_buffer[0x34]), 179 | sizeof(signal_grid)); 180 | 181 | for (j = 0; j < (int8_t)4; j++) { 182 | for (i = 0; i < (int8_t)4 ; i++) { 183 | signal_grid[i + (4 * j)] = 184 | (signal_grid[(2 * i) + (16 * j) + 0] 185 | + signal_grid[(2 * i) + (16 * j) + 1] 186 | + signal_grid[(2 * i) + (16 * j) + 8] 187 | + signal_grid[(2 * i) + (16 * j) + 9]) / (uint32_t)4; 188 | } 189 | } 190 | (void)memset(&signal_grid[0x10], 0, (uint32_t)192); 191 | (void)memcpy(&(p_dev->temp_buffer[0x34]), 192 | signal_grid, sizeof(signal_grid)); 193 | VL53L8CX_SwapBuffer(p_dev->temp_buffer, VL53L8CX_XTALK_BUFFER_SIZE); 194 | (void)memcpy(&(p_dev->temp_buffer[0x134]), 195 | profile_4x4, sizeof(profile_4x4)); 196 | (void)memset(&(p_dev->temp_buffer[0x078]), 0, 197 | (uint32_t)4 * sizeof(uint8_t)); 198 | } 199 | 200 | status |= VL53L8CX_WrMulti(&(p_dev->platform), 0x2cf8, 201 | p_dev->temp_buffer, VL53L8CX_XTALK_BUFFER_SIZE); 202 | status |= _vl53l8cx_poll_for_answer(p_dev, 4, 1, 203 | VL53L8CX_UI_CMD_STATUS, 0xff, 0x03); 204 | 205 | return status; 206 | } 207 | 208 | uint8_t vl53l8cx_is_alive( 209 | VL53L8CX_Configuration *p_dev, 210 | uint8_t *p_is_alive) 211 | { 212 | uint8_t status = VL53L8CX_STATUS_OK; 213 | uint8_t device_id, revision_id; 214 | 215 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x7fff, 0x00); 216 | status |= VL53L8CX_RdByte(&(p_dev->platform), 0, &device_id); 217 | status |= VL53L8CX_RdByte(&(p_dev->platform), 1, &revision_id); 218 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x7fff, 0x02); 219 | 220 | 221 | if ((device_id == (uint8_t)0xF0) && (revision_id == (uint8_t)0x0C)) { 222 | *p_is_alive = 1; 223 | } else { 224 | *p_is_alive = 0; 225 | } 226 | 227 | 228 | return status; 229 | } 230 | 231 | uint8_t vl53l8cx_init( 232 | VL53L8CX_Configuration *p_dev) 233 | { 234 | uint8_t tmp, status = VL53L8CX_STATUS_OK; 235 | uint8_t pipe_ctrl[] = {VL53L8CX_NB_TARGET_PER_ZONE, 0x00, 0x01, 0x00}; 236 | uint32_t single_range = 0x01; 237 | uint32_t crc_checksum = 0x00; 238 | p_dev->default_xtalk = (uint8_t *)VL53L8CX_DEFAULT_XTALK; 239 | p_dev->default_configuration = (uint8_t *)VL53L8CX_DEFAULT_CONFIGURATION; 240 | p_dev->is_auto_stop_enabled = (uint8_t)0x0; 241 | 242 | /* SW reboot sequence */ 243 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x7fff, 0x00); 244 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x0009, 0x04); 245 | 246 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x000F, 0x40); 247 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x000A, 0x03); 248 | status |= VL53L8CX_RdByte(&(p_dev->platform), 0x7FFF, &tmp); 249 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x000C, 0x01); 250 | 251 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x0101, 0x00); 252 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x0102, 0x00); 253 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x010A, 0x01); 254 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x4002, 0x01); 255 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x4002, 0x00); 256 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x010A, 0x03); 257 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x0103, 0x01); 258 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x000C, 0x00); 259 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x000F, 0x43); 260 | status |= VL53L8CX_WaitMs(&(p_dev->platform), 1); 261 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x000F, 0x40); 262 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x000A, 0x01); 263 | 264 | status |= VL53L8CX_WaitMs(&(p_dev->platform), 100); 265 | /* Wait for sensor booted (several ms required to get sensor ready ) */ 266 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x7fff, 0x00); 267 | status |= _vl53l8cx_poll_for_answer(p_dev, 1, 0, 0x06, 0xff, 1); 268 | if (status != (uint8_t)0) { 269 | goto exit; 270 | } 271 | 272 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x000E, 0x01); 273 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x7fff, 0x02); 274 | 275 | /* Enable FW access */ 276 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x7fff, 0x01); 277 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x06, 0x01); 278 | status |= _vl53l8cx_poll_for_answer(p_dev, 1, 0, 0x21, 0xFF, 0x4); 279 | 280 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x7fff, 0x00); 281 | 282 | /* Enable host access to GO1 */ 283 | status |= VL53L8CX_RdByte(&(p_dev->platform), 0x7fff, &tmp); 284 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x0C, 0x01); 285 | 286 | /* Power ON status */ 287 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x7fff, 0x00); 288 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x101, 0x00); 289 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x102, 0x00); 290 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x010A, 0x01); 291 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x4002, 0x01); 292 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x4002, 0x00); 293 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x010A, 0x03); 294 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x103, 0x01); 295 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x400F, 0x00); 296 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x21A, 0x43); 297 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x21A, 0x03); 298 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x21A, 0x01); 299 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x21A, 0x00); 300 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x219, 0x00); 301 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x21B, 0x00); 302 | 303 | /* Wake up MCU */ 304 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x7fff, 0x00); 305 | status |= VL53L8CX_RdByte(&(p_dev->platform), 0x7fff, &tmp); 306 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x7fff, 0x01); 307 | 308 | /* Download FW into VL53L8CX */ 309 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x7fff, 0x09); 310 | status |= VL53L8CX_WrMulti(&(p_dev->platform), 0, 311 | (uint8_t *)&VL53L8CX_FIRMWARE[0], 0x8000); 312 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x7fff, 0x0a); 313 | status |= VL53L8CX_WrMulti(&(p_dev->platform), 0, 314 | (uint8_t *)&VL53L8CX_FIRMWARE[0x8000], 0x8000); 315 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x7fff, 0x0b); 316 | status |= VL53L8CX_WrMulti(&(p_dev->platform), 0, 317 | (uint8_t *)&VL53L8CX_FIRMWARE[0x10000], 0x5000); 318 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x7fff, 0x01); 319 | 320 | /* Check if FW correctly downloaded */ 321 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x7fff, 0x01); 322 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x06, 0x03); 323 | 324 | status |= VL53L8CX_WaitMs(&(p_dev->platform), 5); 325 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x7fff, 0x00); 326 | status |= VL53L8CX_RdByte(&(p_dev->platform), 0x7fff, &tmp); 327 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x0C, 0x01); 328 | 329 | /* Reset MCU and wait boot */ 330 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x7FFF, 0x00); 331 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x114, 0x00); 332 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x115, 0x00); 333 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x116, 0x42); 334 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x117, 0x00); 335 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x0B, 0x00); 336 | status |= VL53L8CX_RdByte(&(p_dev->platform), 0x7fff, &tmp); 337 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x0C, 0x00); 338 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x0B, 0x01); 339 | 340 | status |= _vl53l8cx_poll_for_mcu_boot(p_dev); 341 | if (status != (uint8_t)0) { 342 | goto exit; 343 | } 344 | 345 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x7fff, 0x02); 346 | 347 | /* Firmware checksum */ 348 | status |= VL53L8CX_RdMulti(&(p_dev->platform), (uint16_t)(0x812FFC & 0xFFFF), 349 | p_dev->temp_buffer, 4); 350 | VL53L8CX_SwapBuffer(p_dev->temp_buffer, 4); 351 | memcpy((uint8_t *)&crc_checksum, &(p_dev->temp_buffer[0]), 4); 352 | if (crc_checksum != (uint32_t)0xc0b6c9e) { 353 | status |= VL53L8CX_STATUS_FW_CHECKSUM_FAIL; 354 | goto exit; 355 | } 356 | 357 | /* Get offset NVM data and store them into the offset buffer */ 358 | status |= VL53L8CX_WrMulti(&(p_dev->platform), 0x2fd8, 359 | (uint8_t *)VL53L8CX_GET_NVM_CMD, sizeof(VL53L8CX_GET_NVM_CMD)); 360 | status |= _vl53l8cx_poll_for_answer(p_dev, 4, 0, 361 | VL53L8CX_UI_CMD_STATUS, 0xff, 2); 362 | status |= VL53L8CX_RdMulti(&(p_dev->platform), VL53L8CX_UI_CMD_START, 363 | p_dev->temp_buffer, VL53L8CX_NVM_DATA_SIZE); 364 | (void)memcpy(p_dev->offset_data, p_dev->temp_buffer, 365 | VL53L8CX_OFFSET_BUFFER_SIZE); 366 | status |= _vl53l8cx_send_offset_data(p_dev, VL53L8CX_RESOLUTION_4X4); 367 | 368 | /* Set default Xtalk shape. Send Xtalk to sensor */ 369 | (void)memcpy(p_dev->xtalk_data, (uint8_t *)VL53L8CX_DEFAULT_XTALK, 370 | VL53L8CX_XTALK_BUFFER_SIZE); 371 | status |= _vl53l8cx_send_xtalk_data(p_dev, VL53L8CX_RESOLUTION_4X4); 372 | 373 | /* Send default configuration to VL53L8CX firmware */ 374 | status |= VL53L8CX_WrMulti(&(p_dev->platform), 0x2c34, 375 | p_dev->default_configuration, 376 | sizeof(VL53L8CX_DEFAULT_CONFIGURATION)); 377 | status |= _vl53l8cx_poll_for_answer(p_dev, 4, 1, 378 | VL53L8CX_UI_CMD_STATUS, 0xff, 0x03); 379 | 380 | status |= vl53l8cx_dci_write_data(p_dev, (uint8_t *)&pipe_ctrl, 381 | VL53L8CX_DCI_PIPE_CONTROL, (uint16_t)sizeof(pipe_ctrl)); 382 | #if VL53L8CX_NB_TARGET_PER_ZONE != 1 383 | tmp = VL53L8CX_NB_TARGET_PER_ZONE; 384 | status |= vl53l8cx_dci_replace_data(p_dev, p_dev->temp_buffer, 385 | VL53L8CX_DCI_FW_NB_TARGET, 16, 386 | (uint8_t *)&tmp, 1, 0x0C); 387 | #endif 388 | 389 | status |= vl53l8cx_dci_write_data(p_dev, (uint8_t *)&single_range, 390 | VL53L8CX_DCI_SINGLE_RANGE, 391 | (uint16_t)sizeof(single_range)); 392 | 393 | exit: 394 | return status; 395 | } 396 | 397 | uint8_t vl53l8cx_set_i2c_address( 398 | VL53L8CX_Configuration *p_dev, 399 | uint16_t i2c_address) 400 | { 401 | uint8_t status = VL53L8CX_STATUS_OK; 402 | 403 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x7fff, 0x00); 404 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x4, (uint8_t)(i2c_address >> 1)); 405 | p_dev->platform.address = i2c_address; 406 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x7fff, 0x02); 407 | 408 | return status; 409 | } 410 | 411 | uint8_t vl53l8cx_get_power_mode( 412 | VL53L8CX_Configuration *p_dev, 413 | uint8_t *p_power_mode) 414 | { 415 | uint8_t tmp, status = VL53L8CX_STATUS_OK; 416 | 417 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x7FFF, 0x00); 418 | status |= VL53L8CX_RdByte(&(p_dev->platform), 0x009, &tmp); 419 | 420 | switch (tmp) { 421 | case 0x4: 422 | *p_power_mode = VL53L8CX_POWER_MODE_WAKEUP; 423 | break; 424 | case 0x2: 425 | status |= VL53L8CX_RdByte(&(p_dev->platform), 0x000F, &tmp); 426 | if (tmp == 0x43) { 427 | *p_power_mode = VL53L8CX_POWER_MODE_DEEP_SLEEP; 428 | } else { 429 | *p_power_mode = VL53L8CX_POWER_MODE_SLEEP; 430 | } 431 | 432 | break; 433 | default: 434 | *p_power_mode = 0; 435 | status = VL53L8CX_STATUS_ERROR; 436 | break; 437 | } 438 | 439 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x7FFF, 0x02); 440 | 441 | return status; 442 | } 443 | 444 | uint8_t vl53l8cx_set_power_mode( 445 | VL53L8CX_Configuration *p_dev, 446 | uint8_t power_mode) 447 | { 448 | uint8_t current_power_mode, stored_mode, status = VL53L8CX_STATUS_OK; 449 | 450 | status |= vl53l8cx_get_power_mode(p_dev, ¤t_power_mode); 451 | if (power_mode != current_power_mode) { 452 | switch (power_mode) { 453 | case VL53L8CX_POWER_MODE_WAKEUP: 454 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x7FFF, 0x00); 455 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x09, 0x04); 456 | status |= VL53L8CX_RdByte(&(p_dev->platform), 0x000F, &stored_mode); 457 | if (stored_mode == 0x43) { /* Only for deep sleep mode */ 458 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x000F, 0x40); 459 | } 460 | status |= _vl53l8cx_poll_for_answer( 461 | p_dev, 1, 0, 0x06, 0x01, 1); 462 | if (stored_mode == 0x43) { /* Only for deep sleep mode */ 463 | status |= vl53l8cx_init(p_dev); 464 | } 465 | break; 466 | 467 | case VL53L8CX_POWER_MODE_SLEEP: 468 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x7FFF, 0x00); 469 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x09, 0x02); 470 | status |= _vl53l8cx_poll_for_answer( 471 | p_dev, 1, 0, 0x06, 0x01, 0); 472 | break; 473 | 474 | case VL53L8CX_POWER_MODE_DEEP_SLEEP: 475 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x7FFF, 0x00); 476 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x09, 0x02); 477 | status |= _vl53l8cx_poll_for_answer( 478 | p_dev, 1, 0, 0x06, 0x01, 0); 479 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x000F, 0x43); 480 | break; 481 | 482 | default: 483 | status = VL53L8CX_STATUS_ERROR; 484 | break; 485 | } 486 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x7FFF, 0x02); 487 | } 488 | 489 | return status; 490 | } 491 | 492 | uint8_t vl53l8cx_start_ranging( 493 | VL53L8CX_Configuration *p_dev) 494 | { 495 | uint8_t resolution, status = VL53L8CX_STATUS_OK; 496 | uint16_t tmp; 497 | uint32_t i; 498 | uint32_t header_config[2] = {0, 0}; 499 | 500 | union Block_header *bh_ptr; 501 | uint8_t cmd[] = {0x00, 0x03, 0x00, 0x00}; 502 | 503 | status |= vl53l8cx_get_resolution(p_dev, &resolution); 504 | p_dev->data_read_size = 0; 505 | p_dev->streamcount = 255; 506 | 507 | /* Enable mandatory output (meta and common data) */ 508 | uint32_t output_bh_enable[] = { 509 | 0x00000007U, 510 | 0x00000000U, 511 | 0x00000000U, 512 | 0xC0000000U 513 | }; 514 | 515 | /* Send addresses of possible output */ 516 | uint32_t output[] = {VL53L8CX_START_BH, 517 | VL53L8CX_METADATA_BH, 518 | VL53L8CX_COMMONDATA_BH, 519 | VL53L8CX_AMBIENT_RATE_BH, 520 | VL53L8CX_SPAD_COUNT_BH, 521 | VL53L8CX_NB_TARGET_DETECTED_BH, 522 | VL53L8CX_SIGNAL_RATE_BH, 523 | VL53L8CX_RANGE_SIGMA_MM_BH, 524 | VL53L8CX_DISTANCE_BH, 525 | VL53L8CX_REFLECTANCE_BH, 526 | VL53L8CX_TARGET_STATUS_BH, 527 | VL53L8CX_MOTION_DETECT_BH 528 | }; 529 | 530 | /* Enable selected outputs in the 'platform.h' file */ 531 | #ifndef VL53L8CX_DISABLE_AMBIENT_PER_SPAD 532 | output_bh_enable[0] += (uint32_t)8; 533 | #endif 534 | #ifndef VL53L8CX_DISABLE_NB_SPADS_ENABLED 535 | output_bh_enable[0] += (uint32_t)16; 536 | #endif 537 | #ifndef VL53L8CX_DISABLE_NB_TARGET_DETECTED 538 | output_bh_enable[0] += (uint32_t)32; 539 | #endif 540 | #ifndef VL53L8CX_DISABLE_SIGNAL_PER_SPAD 541 | output_bh_enable[0] += (uint32_t)64; 542 | #endif 543 | #ifndef VL53L8CX_DISABLE_RANGE_SIGMA_MM 544 | output_bh_enable[0] += (uint32_t)128; 545 | #endif 546 | #ifndef VL53L8CX_DISABLE_DISTANCE_MM 547 | output_bh_enable[0] += (uint32_t)256; 548 | #endif 549 | #ifndef VL53L8CX_DISABLE_REFLECTANCE_PERCENT 550 | output_bh_enable[0] += (uint32_t)512; 551 | #endif 552 | #ifndef VL53L8CX_DISABLE_TARGET_STATUS 553 | output_bh_enable[0] += (uint32_t)1024; 554 | #endif 555 | #ifndef VL53L8CX_DISABLE_MOTION_INDICATOR 556 | output_bh_enable[0] += (uint32_t)2048; 557 | #endif 558 | 559 | /* Update data size */ 560 | for (i = 0; i < (uint32_t)(sizeof(output) / sizeof(uint32_t)); i++) { 561 | if ((output[i] == (uint8_t)0) 562 | || ((output_bh_enable[i / (uint32_t)32] 563 | & ((uint32_t)1 << (i % (uint32_t)32))) == (uint32_t)0)) { 564 | continue; 565 | } 566 | 567 | bh_ptr = (union Block_header *) & (output[i]); 568 | if (((uint8_t)bh_ptr->type >= (uint8_t)0x1) 569 | && ((uint8_t)bh_ptr->type < (uint8_t)0x0d)) { 570 | if ((bh_ptr->idx >= (uint16_t)0x54d0) 571 | && (bh_ptr->idx < (uint16_t)(0x54d0 + 960))) { 572 | bh_ptr->size = resolution; 573 | } else { 574 | bh_ptr->size = (uint16_t)((uint16_t)resolution 575 | * (uint16_t)VL53L8CX_NB_TARGET_PER_ZONE); 576 | } 577 | p_dev->data_read_size += bh_ptr->type * bh_ptr->size; 578 | } else { 579 | p_dev->data_read_size += bh_ptr->size; 580 | } 581 | p_dev->data_read_size += (uint32_t)4; 582 | } 583 | p_dev->data_read_size += (uint32_t)24; 584 | 585 | status |= vl53l8cx_dci_write_data(p_dev, 586 | (uint8_t *) & (output), VL53L8CX_DCI_OUTPUT_LIST, 587 | (uint16_t)sizeof(output)); 588 | 589 | header_config[0] = p_dev->data_read_size; 590 | header_config[1] = i + (uint32_t)1; 591 | 592 | status |= vl53l8cx_dci_write_data(p_dev, 593 | (uint8_t *) & (header_config), VL53L8CX_DCI_OUTPUT_CONFIG, 594 | (uint16_t)sizeof(header_config)); 595 | 596 | status |= vl53l8cx_dci_write_data(p_dev, 597 | (uint8_t *) & (output_bh_enable), VL53L8CX_DCI_OUTPUT_ENABLES, 598 | (uint16_t)sizeof(output_bh_enable)); 599 | 600 | /* Start xshut bypass (interrupt mode) */ 601 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x7fff, 0x00); 602 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x09, 0x05); 603 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x7fff, 0x02); 604 | 605 | /* Start ranging session */ 606 | status |= VL53L8CX_WrMulti(&(p_dev->platform), VL53L8CX_UI_CMD_END - 607 | (uint16_t)(4 - 1), (uint8_t *)cmd, sizeof(cmd)); 608 | status |= _vl53l8cx_poll_for_answer(p_dev, 4, 1, 609 | VL53L8CX_UI_CMD_STATUS, 0xff, 0x03); 610 | 611 | /* Read ui range data content and compare if data size is the correct one */ 612 | status |= vl53l8cx_dci_read_data(p_dev, 613 | (uint8_t *)p_dev->temp_buffer, 0x5440, 12); 614 | (void)memcpy(&tmp, &(p_dev->temp_buffer[0x8]), sizeof(tmp)); 615 | if (tmp != p_dev->data_read_size) { 616 | status |= VL53L8CX_STATUS_ERROR; 617 | } 618 | 619 | /* Ensure that there is no laser safety fault */ 620 | status |= vl53l8cx_dci_read_data(p_dev, 621 | (uint8_t *)p_dev->temp_buffer, 0xE0C4, 8); 622 | if ((uint8_t)p_dev->temp_buffer[0x6] != (uint8_t)0) { 623 | status |= VL53L8CX_STATUS_LASER_SAFETY; 624 | } 625 | 626 | return status; 627 | } 628 | 629 | uint8_t vl53l8cx_stop_ranging( 630 | VL53L8CX_Configuration *p_dev) 631 | { 632 | uint8_t tmp = 0, status = VL53L8CX_STATUS_OK; 633 | uint16_t timeout = 0; 634 | uint32_t auto_stop_flag = 0; 635 | 636 | status |= VL53L8CX_RdMulti(&(p_dev->platform), 637 | 0x2FFC, (uint8_t *)&auto_stop_flag, 4); 638 | if ((auto_stop_flag != (uint32_t)0x4FF) 639 | && (p_dev->is_auto_stop_enabled == (uint8_t)0)) { 640 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x7fff, 0x00); 641 | 642 | /* Provoke MCU stop */ 643 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x15, 0x16); 644 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x14, 0x01); 645 | 646 | /* Poll for G02 status 0 MCU stop */ 647 | while (((tmp & (uint8_t)0x80) >> 7) == (uint8_t)0x00) { 648 | status |= VL53L8CX_RdByte(&(p_dev->platform), 0x6, &tmp); 649 | status |= VL53L8CX_WaitMs(&(p_dev->platform), 10); 650 | timeout++; /* Timeout reached after 5 seconds */ 651 | 652 | if (timeout > (uint16_t)500) { 653 | status |= tmp; 654 | break; 655 | } 656 | } 657 | } 658 | 659 | /* Check GO2 status 1 if status is still OK */ 660 | status |= VL53L8CX_RdByte(&(p_dev->platform), 0x6, &tmp); 661 | if ((tmp & (uint8_t)0x80) != (uint8_t)0) { 662 | status |= VL53L8CX_RdByte(&(p_dev->platform), 0x7, &tmp); 663 | if ((tmp != (uint8_t)0x84) && (tmp != (uint8_t)0x85)) { 664 | status |= tmp; 665 | } 666 | } 667 | 668 | /* Undo MCU stop */ 669 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x7fff, 0x00); 670 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x14, 0x00); 671 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x15, 0x00); 672 | 673 | /* Stop xshut bypass */ 674 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x09, 0x04); 675 | status |= VL53L8CX_WrByte(&(p_dev->platform), 0x7fff, 0x02); 676 | 677 | return status; 678 | } 679 | 680 | uint8_t vl53l8cx_check_data_ready( 681 | VL53L8CX_Configuration *p_dev, 682 | uint8_t *p_isReady) 683 | { 684 | uint8_t status = VL53L8CX_STATUS_OK; 685 | 686 | status |= VL53L8CX_RdMulti(&(p_dev->platform), 0x0, p_dev->temp_buffer, 4); 687 | 688 | if ((p_dev->temp_buffer[0] != p_dev->streamcount) 689 | && (p_dev->temp_buffer[0] != (uint8_t)255) 690 | && (p_dev->temp_buffer[1] == (uint8_t)0x5) 691 | && ((p_dev->temp_buffer[2] & (uint8_t)0x5) == (uint8_t)0x5) 692 | && ((p_dev->temp_buffer[3] & (uint8_t)0x10) == (uint8_t)0x10) 693 | ) { 694 | *p_isReady = (uint8_t)1; 695 | p_dev->streamcount = p_dev->temp_buffer[0]; 696 | } else { 697 | if ((p_dev->temp_buffer[3] & (uint8_t)0x80) != (uint8_t)0) { 698 | status |= p_dev->temp_buffer[2]; /* Return GO2 error status */ 699 | } 700 | 701 | *p_isReady = 0; 702 | } 703 | 704 | return status; 705 | } 706 | 707 | uint8_t vl53l8cx_get_ranging_data( 708 | VL53L8CX_Configuration *p_dev, 709 | VL53L8CX_ResultsData *p_results) 710 | { 711 | uint8_t status = VL53L8CX_STATUS_OK; 712 | uint16_t header_id, footer_id; 713 | union Block_header *bh_ptr; 714 | uint32_t i, j, msize; 715 | status |= VL53L8CX_RdMulti(&(p_dev->platform), 0x0, 716 | p_dev->temp_buffer, p_dev->data_read_size); 717 | p_dev->streamcount = p_dev->temp_buffer[0]; 718 | VL53L8CX_SwapBuffer(p_dev->temp_buffer, (uint16_t)p_dev->data_read_size); 719 | 720 | /* Start conversion at position 16 to avoid headers */ 721 | for (i = (uint32_t)16; i 722 | < (uint32_t)p_dev->data_read_size; i += (uint32_t)4) { 723 | bh_ptr = (union Block_header *) & (p_dev->temp_buffer[i]); 724 | if ((bh_ptr->type > (uint32_t)0x1) 725 | && (bh_ptr->type < (uint32_t)0xd)) { 726 | msize = bh_ptr->type * bh_ptr->size; 727 | } else { 728 | msize = bh_ptr->size; 729 | } 730 | 731 | switch (bh_ptr->idx) { 732 | case VL53L8CX_METADATA_IDX: 733 | p_results->silicon_temp_degc = 734 | (int8_t)p_dev->temp_buffer[i + (uint32_t)12]; 735 | break; 736 | 737 | #ifndef VL53L8CX_DISABLE_AMBIENT_PER_SPAD 738 | case VL53L8CX_AMBIENT_RATE_IDX: 739 | (void)memcpy(p_results->ambient_per_spad, 740 | &(p_dev->temp_buffer[i + (uint32_t)4]), msize); 741 | break; 742 | #endif 743 | #ifndef VL53L8CX_DISABLE_NB_SPADS_ENABLED 744 | case VL53L8CX_SPAD_COUNT_IDX: 745 | (void)memcpy(p_results->nb_spads_enabled, 746 | &(p_dev->temp_buffer[i + (uint32_t)4]), msize); 747 | break; 748 | #endif 749 | #ifndef VL53L8CX_DISABLE_NB_TARGET_DETECTED 750 | case VL53L8CX_NB_TARGET_DETECTED_IDX: 751 | (void)memcpy(p_results->nb_target_detected, 752 | &(p_dev->temp_buffer[i + (uint32_t)4]), msize); 753 | break; 754 | #endif 755 | #ifndef VL53L8CX_DISABLE_SIGNAL_PER_SPAD 756 | case VL53L8CX_SIGNAL_RATE_IDX: 757 | (void)memcpy(p_results->signal_per_spad, 758 | &(p_dev->temp_buffer[i + (uint32_t)4]), msize); 759 | break; 760 | #endif 761 | #ifndef VL53L8CX_DISABLE_RANGE_SIGMA_MM 762 | case VL53L8CX_RANGE_SIGMA_MM_IDX: 763 | (void)memcpy(p_results->range_sigma_mm, 764 | &(p_dev->temp_buffer[i + (uint32_t)4]), msize); 765 | break; 766 | #endif 767 | #ifndef VL53L8CX_DISABLE_DISTANCE_MM 768 | case VL53L8CX_DISTANCE_IDX: 769 | (void)memcpy(p_results->distance_mm, 770 | &(p_dev->temp_buffer[i + (uint32_t)4]), msize); 771 | break; 772 | #endif 773 | #ifndef VL53L8CX_DISABLE_REFLECTANCE_PERCENT 774 | case VL53L8CX_REFLECTANCE_EST_PC_IDX: 775 | (void)memcpy(p_results->reflectance, 776 | &(p_dev->temp_buffer[i + (uint32_t)4]), msize); 777 | break; 778 | #endif 779 | #ifndef VL53L8CX_DISABLE_TARGET_STATUS 780 | case VL53L8CX_TARGET_STATUS_IDX: 781 | (void)memcpy(p_results->target_status, 782 | &(p_dev->temp_buffer[i + (uint32_t)4]), msize); 783 | break; 784 | #endif 785 | #ifndef VL53L8CX_DISABLE_MOTION_INDICATOR 786 | case VL53L8CX_MOTION_DETEC_IDX: 787 | (void)memcpy(&p_results->motion_indicator, 788 | &(p_dev->temp_buffer[i + (uint32_t)4]), msize); 789 | break; 790 | #endif 791 | default: 792 | break; 793 | } 794 | i += msize; 795 | } 796 | 797 | #ifndef VL53L8CX_USE_RAW_FORMAT 798 | 799 | /* Convert data into their real format */ 800 | #ifndef VL53L8CX_DISABLE_AMBIENT_PER_SPAD 801 | for (i = 0; i < (uint32_t)VL53L8CX_RESOLUTION_8X8; i++) { 802 | p_results->ambient_per_spad[i] /= (uint32_t)2048; 803 | } 804 | #endif 805 | 806 | for (i = 0; i < (uint32_t)(VL53L8CX_RESOLUTION_8X8 807 | *VL53L8CX_NB_TARGET_PER_ZONE); i++) { 808 | #ifndef VL53L8CX_DISABLE_DISTANCE_MM 809 | p_results->distance_mm[i] /= 4; 810 | #endif 811 | #ifndef VL53L8CX_DISABLE_REFLECTANCE_PERCENT 812 | p_results->reflectance[i] /= (uint8_t)2; 813 | #endif 814 | #ifndef VL53L8CX_DISABLE_RANGE_SIGMA_MM 815 | p_results->range_sigma_mm[i] /= (uint16_t)128; 816 | #endif 817 | #ifndef VL53L8CX_DISABLE_SIGNAL_PER_SPAD 818 | p_results->signal_per_spad[i] /= (uint32_t)2048; 819 | #endif 820 | } 821 | 822 | /* Set target status to 255 if no target is detected for this zone */ 823 | #ifndef VL53L8CX_DISABLE_NB_TARGET_DETECTED 824 | for (i = 0; i < (uint32_t)VL53L8CX_RESOLUTION_8X8; i++) { 825 | if (p_results->nb_target_detected[i] == (uint8_t)0) { 826 | for (j = 0; j < (uint32_t) 827 | VL53L8CX_NB_TARGET_PER_ZONE; j++) { 828 | #ifndef VL53L8CX_DISABLE_TARGET_STATUS 829 | p_results->target_status 830 | [((uint32_t)VL53L8CX_NB_TARGET_PER_ZONE 831 | * (uint32_t)i) + j] = (uint8_t)255; 832 | #endif 833 | } 834 | } 835 | } 836 | #endif 837 | 838 | #ifndef VL53L8CX_DISABLE_MOTION_INDICATOR 839 | for (i = 0; i < (uint32_t)32; i++) { 840 | p_results->motion_indicator.motion[i] /= (uint32_t)65535; 841 | } 842 | #endif 843 | 844 | #endif 845 | 846 | /* Check if footer id and header id are matching. This allows to detect 847 | * corrupted frames */ 848 | header_id = ((uint16_t)(p_dev->temp_buffer[0x8]) << 8) & 0xFF00U; 849 | header_id |= ((uint16_t)(p_dev->temp_buffer[0x9])) & 0x00FFU; 850 | 851 | footer_id = ((uint16_t)(p_dev->temp_buffer[p_dev->data_read_size 852 | - (uint32_t)4]) << 8) & 0xFF00U; 853 | footer_id |= ((uint16_t)(p_dev->temp_buffer[p_dev->data_read_size 854 | - (uint32_t)3])) & 0xFFU; 855 | 856 | if (header_id != footer_id) { 857 | status |= VL53L8CX_STATUS_CORRUPTED_FRAME; 858 | } 859 | 860 | return status; 861 | } 862 | 863 | uint8_t vl53l8cx_get_resolution( 864 | VL53L8CX_Configuration *p_dev, 865 | uint8_t *p_resolution) 866 | { 867 | uint8_t status = VL53L8CX_STATUS_OK; 868 | 869 | status |= vl53l8cx_dci_read_data(p_dev, p_dev->temp_buffer, 870 | VL53L8CX_DCI_ZONE_CONFIG, 8); 871 | *p_resolution = p_dev->temp_buffer[0x00] * p_dev->temp_buffer[0x01]; 872 | 873 | return status; 874 | } 875 | 876 | 877 | 878 | uint8_t vl53l8cx_set_resolution( 879 | VL53L8CX_Configuration *p_dev, 880 | uint8_t resolution) 881 | { 882 | uint8_t status = VL53L8CX_STATUS_OK; 883 | 884 | switch (resolution) { 885 | case VL53L8CX_RESOLUTION_4X4: 886 | status |= vl53l8cx_dci_read_data(p_dev, 887 | p_dev->temp_buffer, 888 | VL53L8CX_DCI_DSS_CONFIG, 16); 889 | p_dev->temp_buffer[0x04] = 64; 890 | p_dev->temp_buffer[0x06] = 64; 891 | p_dev->temp_buffer[0x09] = 4; 892 | status |= vl53l8cx_dci_write_data(p_dev, 893 | p_dev->temp_buffer, 894 | VL53L8CX_DCI_DSS_CONFIG, 16); 895 | 896 | status |= vl53l8cx_dci_read_data(p_dev, 897 | p_dev->temp_buffer, 898 | VL53L8CX_DCI_ZONE_CONFIG, 8); 899 | p_dev->temp_buffer[0x00] = 4; 900 | p_dev->temp_buffer[0x01] = 4; 901 | p_dev->temp_buffer[0x04] = 8; 902 | p_dev->temp_buffer[0x05] = 8; 903 | status |= vl53l8cx_dci_write_data(p_dev, 904 | p_dev->temp_buffer, 905 | VL53L8CX_DCI_ZONE_CONFIG, 8); 906 | break; 907 | 908 | case VL53L8CX_RESOLUTION_8X8: 909 | status |= vl53l8cx_dci_read_data(p_dev, 910 | p_dev->temp_buffer, 911 | VL53L8CX_DCI_DSS_CONFIG, 16); 912 | p_dev->temp_buffer[0x04] = 16; 913 | p_dev->temp_buffer[0x06] = 16; 914 | p_dev->temp_buffer[0x09] = 1; 915 | status |= vl53l8cx_dci_write_data(p_dev, 916 | p_dev->temp_buffer, 917 | VL53L8CX_DCI_DSS_CONFIG, 16); 918 | 919 | status |= vl53l8cx_dci_read_data(p_dev, 920 | p_dev->temp_buffer, 921 | VL53L8CX_DCI_ZONE_CONFIG, 8); 922 | p_dev->temp_buffer[0x00] = 8; 923 | p_dev->temp_buffer[0x01] = 8; 924 | p_dev->temp_buffer[0x04] = 4; 925 | p_dev->temp_buffer[0x05] = 4; 926 | status |= vl53l8cx_dci_write_data(p_dev, 927 | p_dev->temp_buffer, 928 | VL53L8CX_DCI_ZONE_CONFIG, 8); 929 | 930 | break; 931 | 932 | default: 933 | status = VL53L8CX_STATUS_INVALID_PARAM; 934 | break; 935 | } 936 | 937 | status |= _vl53l8cx_send_offset_data(p_dev, resolution); 938 | status |= _vl53l8cx_send_xtalk_data(p_dev, resolution); 939 | 940 | return status; 941 | } 942 | 943 | uint8_t vl53l8cx_get_ranging_frequency_hz( 944 | VL53L8CX_Configuration *p_dev, 945 | uint8_t *p_frequency_hz) 946 | { 947 | uint8_t status = VL53L8CX_STATUS_OK; 948 | 949 | status |= vl53l8cx_dci_read_data(p_dev, (uint8_t *)p_dev->temp_buffer, 950 | VL53L8CX_DCI_FREQ_HZ, 4); 951 | *p_frequency_hz = p_dev->temp_buffer[0x01]; 952 | 953 | return status; 954 | } 955 | 956 | uint8_t vl53l8cx_set_ranging_frequency_hz( 957 | VL53L8CX_Configuration *p_dev, 958 | uint8_t frequency_hz) 959 | { 960 | uint8_t status = VL53L8CX_STATUS_OK; 961 | 962 | status |= vl53l8cx_dci_replace_data(p_dev, p_dev->temp_buffer, 963 | VL53L8CX_DCI_FREQ_HZ, 4, 964 | (uint8_t *)&frequency_hz, 1, 0x01); 965 | 966 | return status; 967 | } 968 | 969 | uint8_t vl53l8cx_get_integration_time_ms( 970 | VL53L8CX_Configuration *p_dev, 971 | uint32_t *p_time_ms) 972 | { 973 | uint8_t status = VL53L8CX_STATUS_OK; 974 | 975 | status |= vl53l8cx_dci_read_data(p_dev, (uint8_t *)p_dev->temp_buffer, 976 | VL53L8CX_DCI_INT_TIME, 20); 977 | 978 | (void)memcpy(p_time_ms, &(p_dev->temp_buffer[0x0]), 4); 979 | *p_time_ms /= (uint32_t)1000; 980 | 981 | return status; 982 | } 983 | 984 | uint8_t vl53l8cx_set_integration_time_ms( 985 | VL53L8CX_Configuration *p_dev, 986 | uint32_t integration_time_ms) 987 | { 988 | uint8_t status = VL53L8CX_STATUS_OK; 989 | uint32_t integration = integration_time_ms; 990 | 991 | /* Integration time must be between 2ms and 1000ms */ 992 | if ((integration < (uint32_t)2) 993 | || (integration > (uint32_t)1000)) { 994 | status |= VL53L8CX_STATUS_INVALID_PARAM; 995 | } else { 996 | integration *= (uint32_t)1000; 997 | 998 | status |= vl53l8cx_dci_replace_data(p_dev, p_dev->temp_buffer, 999 | VL53L8CX_DCI_INT_TIME, 20, 1000 | (uint8_t *)&integration, 4, 0x00); 1001 | } 1002 | 1003 | return status; 1004 | } 1005 | 1006 | uint8_t vl53l8cx_get_sharpener_percent( 1007 | VL53L8CX_Configuration *p_dev, 1008 | uint8_t *p_sharpener_percent) 1009 | { 1010 | uint8_t status = VL53L8CX_STATUS_OK; 1011 | 1012 | status |= vl53l8cx_dci_read_data(p_dev, p_dev->temp_buffer, 1013 | VL53L8CX_DCI_SHARPENER, 16); 1014 | 1015 | *p_sharpener_percent = (p_dev->temp_buffer[0xD] 1016 | * (uint8_t)100) / (uint8_t)255; 1017 | 1018 | return status; 1019 | } 1020 | 1021 | uint8_t vl53l8cx_set_sharpener_percent( 1022 | VL53L8CX_Configuration *p_dev, 1023 | uint8_t sharpener_percent) 1024 | { 1025 | uint8_t status = VL53L8CX_STATUS_OK; 1026 | uint8_t sharpener; 1027 | 1028 | if (sharpener_percent >= (uint8_t)100) { 1029 | status |= VL53L8CX_STATUS_INVALID_PARAM; 1030 | } else { 1031 | sharpener = (sharpener_percent * (uint8_t)255) / (uint8_t)100; 1032 | status |= vl53l8cx_dci_replace_data(p_dev, p_dev->temp_buffer, 1033 | VL53L8CX_DCI_SHARPENER, 16, 1034 | (uint8_t *)&sharpener, 1, 0xD); 1035 | } 1036 | 1037 | return status; 1038 | } 1039 | 1040 | uint8_t vl53l8cx_get_target_order( 1041 | VL53L8CX_Configuration *p_dev, 1042 | uint8_t *p_target_order) 1043 | { 1044 | uint8_t status = VL53L8CX_STATUS_OK; 1045 | 1046 | status |= vl53l8cx_dci_read_data(p_dev, (uint8_t *)p_dev->temp_buffer, 1047 | VL53L8CX_DCI_TARGET_ORDER, 4); 1048 | *p_target_order = (uint8_t)p_dev->temp_buffer[0x0]; 1049 | 1050 | return status; 1051 | } 1052 | 1053 | uint8_t vl53l8cx_set_target_order( 1054 | VL53L8CX_Configuration *p_dev, 1055 | uint8_t target_order) 1056 | { 1057 | uint8_t status = VL53L8CX_STATUS_OK; 1058 | 1059 | if ((target_order == (uint8_t)VL53L8CX_TARGET_ORDER_CLOSEST) 1060 | || (target_order == (uint8_t)VL53L8CX_TARGET_ORDER_STRONGEST)) { 1061 | status |= vl53l8cx_dci_replace_data(p_dev, p_dev->temp_buffer, 1062 | VL53L8CX_DCI_TARGET_ORDER, 4, 1063 | (uint8_t *)&target_order, 1, 0x0); 1064 | } else { 1065 | status |= VL53L8CX_STATUS_INVALID_PARAM; 1066 | } 1067 | 1068 | return status; 1069 | } 1070 | 1071 | uint8_t vl53l8cx_get_ranging_mode( 1072 | VL53L8CX_Configuration *p_dev, 1073 | uint8_t *p_ranging_mode) 1074 | { 1075 | uint8_t status = VL53L8CX_STATUS_OK; 1076 | 1077 | status |= vl53l8cx_dci_read_data(p_dev, p_dev->temp_buffer, 1078 | VL53L8CX_DCI_RANGING_MODE, 8); 1079 | 1080 | if (p_dev->temp_buffer[0x01] == (uint8_t)0x1) { 1081 | *p_ranging_mode = VL53L8CX_RANGING_MODE_CONTINUOUS; 1082 | } else { 1083 | *p_ranging_mode = VL53L8CX_RANGING_MODE_AUTONOMOUS; 1084 | } 1085 | 1086 | return status; 1087 | } 1088 | 1089 | uint8_t vl53l8cx_set_ranging_mode( 1090 | VL53L8CX_Configuration *p_dev, 1091 | uint8_t ranging_mode) 1092 | { 1093 | uint8_t status = VL53L8CX_STATUS_OK; 1094 | uint32_t single_range = 0x00; 1095 | 1096 | status |= vl53l8cx_dci_read_data(p_dev, p_dev->temp_buffer, 1097 | VL53L8CX_DCI_RANGING_MODE, 8); 1098 | 1099 | switch (ranging_mode) { 1100 | case VL53L8CX_RANGING_MODE_CONTINUOUS: 1101 | p_dev->temp_buffer[0x01] = 0x1; 1102 | p_dev->temp_buffer[0x03] = 0x3; 1103 | single_range = 0x00; 1104 | break; 1105 | 1106 | case VL53L8CX_RANGING_MODE_AUTONOMOUS: 1107 | p_dev->temp_buffer[0x01] = 0x3; 1108 | p_dev->temp_buffer[0x03] = 0x2; 1109 | single_range = 0x01; 1110 | break; 1111 | 1112 | default: 1113 | status = VL53L8CX_STATUS_INVALID_PARAM; 1114 | break; 1115 | } 1116 | 1117 | status |= vl53l8cx_dci_write_data(p_dev, p_dev->temp_buffer, 1118 | VL53L8CX_DCI_RANGING_MODE, (uint16_t)8); 1119 | 1120 | status |= vl53l8cx_dci_write_data(p_dev, (uint8_t *)&single_range, 1121 | VL53L8CX_DCI_SINGLE_RANGE, 1122 | (uint16_t)sizeof(single_range)); 1123 | 1124 | return status; 1125 | } 1126 | 1127 | uint8_t vl53l8cx_get_external_sync_pin_enable( 1128 | VL53L8CX_Configuration *p_dev, 1129 | uint8_t *p_is_sync_pin_enabled) 1130 | { 1131 | uint8_t status = VL53L8CX_STATUS_OK; 1132 | 1133 | status |= vl53l8cx_dci_read_data(p_dev, p_dev->temp_buffer, 1134 | VL53L8CX_DCI_SYNC_PIN, 4); 1135 | 1136 | /* Check bit 1 value (get sync pause bit) */ 1137 | if ((p_dev->temp_buffer[3] & (uint8_t)0x2) != (uint8_t)0) { 1138 | *p_is_sync_pin_enabled = (uint8_t)1; 1139 | } else { 1140 | *p_is_sync_pin_enabled = (uint8_t)0; 1141 | } 1142 | 1143 | return status; 1144 | } 1145 | 1146 | uint8_t vl53l8cx_set_external_sync_pin_enable( 1147 | VL53L8CX_Configuration *p_dev, 1148 | uint8_t enable_sync_pin) 1149 | { 1150 | uint8_t status = VL53L8CX_STATUS_OK; 1151 | uint32_t tmp; 1152 | 1153 | status |= vl53l8cx_dci_read_data(p_dev, p_dev->temp_buffer, 1154 | VL53L8CX_DCI_SYNC_PIN, 4); 1155 | tmp = (uint32_t)p_dev->temp_buffer[3]; 1156 | 1157 | /* Update bit 1 with mask (set sync pause bit) */ 1158 | if (enable_sync_pin == (uint8_t)0) { 1159 | tmp &= ~(1UL << 1); 1160 | 1161 | } else { 1162 | tmp |= 1UL << 1; 1163 | } 1164 | 1165 | p_dev->temp_buffer[3] = (uint8_t)tmp; 1166 | status |= vl53l8cx_dci_write_data(p_dev, p_dev->temp_buffer, 1167 | VL53L8CX_DCI_SYNC_PIN, 4); 1168 | 1169 | return status; 1170 | } 1171 | 1172 | uint8_t vl53l8cx_get_VHV_repeat_count( 1173 | VL53L8CX_Configuration *p_dev, 1174 | uint32_t *p_repeat_count) 1175 | { 1176 | uint8_t status = VL53L8CX_STATUS_OK; 1177 | status |= vl53l8cx_dci_read_data(p_dev, (uint8_t *)p_dev->temp_buffer, 1178 | VL53L8CX_DCI_VHV_CONFIG, 16); 1179 | 1180 | *p_repeat_count = ((uint32_t)p_dev->temp_buffer[7] << 24) 1181 | | ((uint32_t)p_dev->temp_buffer[6] << 16) 1182 | | ((uint32_t)p_dev->temp_buffer[5] << 8) 1183 | | (uint32_t)p_dev->temp_buffer[4]; 1184 | 1185 | return status; 1186 | } 1187 | 1188 | uint8_t vl53l8cx_set_VHV_repeat_count( 1189 | VL53L8CX_Configuration *p_dev, 1190 | uint32_t repeat_count) 1191 | { 1192 | uint8_t status = VL53L8CX_STATUS_OK; 1193 | status |= vl53l8cx_dci_replace_data(p_dev, p_dev->temp_buffer, 1194 | VL53L8CX_DCI_VHV_CONFIG, 16, (uint8_t *)&repeat_count, 4, 0x4); 1195 | return status; 1196 | } 1197 | 1198 | uint8_t vl53l8cx_dci_read_data( 1199 | VL53L8CX_Configuration *p_dev, 1200 | uint8_t *data, 1201 | uint32_t index, 1202 | uint16_t data_size) 1203 | { 1204 | int16_t i; 1205 | uint8_t status = VL53L8CX_STATUS_OK; 1206 | uint32_t rd_size = (uint32_t) data_size + (uint32_t)12; 1207 | uint8_t cmd[] = {0x00, 0x00, 0x00, 0x00, 1208 | 0x00, 0x00, 0x00, 0x0f, 1209 | 0x00, 0x02, 0x00, 0x08 1210 | }; 1211 | 1212 | /* Check if tmp buffer is large enough */ 1213 | if ((data_size + (uint16_t)12) > (uint16_t)VL53L8CX_TEMPORARY_BUFFER_SIZE) { 1214 | status |= VL53L8CX_STATUS_ERROR; 1215 | } else { 1216 | cmd[0] = (uint8_t)(index >> 8); 1217 | cmd[1] = (uint8_t)(index & (uint32_t)0xff); 1218 | cmd[2] = (uint8_t)((data_size & (uint16_t)0xff0) >> 4); 1219 | cmd[3] = (uint8_t)((data_size & (uint16_t)0xf) << 4); 1220 | 1221 | /* Request data reading from FW */ 1222 | status |= VL53L8CX_WrMulti(&(p_dev->platform), 1223 | (VL53L8CX_UI_CMD_END - (uint16_t)11), cmd, sizeof(cmd)); 1224 | status |= _vl53l8cx_poll_for_answer(p_dev, 4, 1, 1225 | VL53L8CX_UI_CMD_STATUS, 1226 | 0xff, 0x03); 1227 | 1228 | /* Read new data sent (4 bytes header + data_size + 8 bytes footer) */ 1229 | status |= VL53L8CX_RdMulti(&(p_dev->platform), VL53L8CX_UI_CMD_START, 1230 | p_dev->temp_buffer, rd_size); 1231 | VL53L8CX_SwapBuffer(p_dev->temp_buffer, data_size + (uint16_t)12); 1232 | 1233 | /* Copy data from FW into input structure (-4 bytes to remove header) */ 1234 | for (i = 0 ; i < (int16_t)data_size; i++) { 1235 | data[i] = p_dev->temp_buffer[i + 4]; 1236 | } 1237 | } 1238 | 1239 | return status; 1240 | } 1241 | 1242 | uint8_t vl53l8cx_dci_write_data( 1243 | VL53L8CX_Configuration *p_dev, 1244 | uint8_t *data, 1245 | uint32_t index, 1246 | uint16_t data_size) 1247 | { 1248 | uint8_t status = VL53L8CX_STATUS_OK; 1249 | int16_t i; 1250 | 1251 | uint8_t headers[] = {0x00, 0x00, 0x00, 0x00}; 1252 | uint8_t footer[] = {0x00, 0x00, 0x00, 0x0f, 0x05, 0x01, 1253 | (uint8_t)((data_size + (uint16_t)8) >> 8), 1254 | (uint8_t)((data_size + (uint16_t)8) & (uint8_t)0xFF) 1255 | }; 1256 | 1257 | uint16_t address = (uint16_t)VL53L8CX_UI_CMD_END - 1258 | (data_size + (uint16_t)12) + (uint16_t)1; 1259 | 1260 | /* Check if cmd buffer is large enough */ 1261 | if ((data_size + (uint16_t)12) 1262 | > (uint16_t)VL53L8CX_TEMPORARY_BUFFER_SIZE) { 1263 | status |= VL53L8CX_STATUS_ERROR; 1264 | } else { 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 | VL53L8CX_SwapBuffer(data, data_size); 1272 | for (i = (int16_t)data_size - (int16_t)1 ; i >= 0; i--) { 1273 | p_dev->temp_buffer[i + 4] = data[i]; 1274 | } 1275 | 1276 | /* Add headers and footer */ 1277 | (void)memcpy(&p_dev->temp_buffer[0], headers, sizeof(headers)); 1278 | (void)memcpy(&p_dev->temp_buffer[data_size + (uint16_t)4], 1279 | footer, sizeof(footer)); 1280 | 1281 | /* Send data to FW */ 1282 | status |= VL53L8CX_WrMulti(&(p_dev->platform), address, 1283 | p_dev->temp_buffer, 1284 | (uint32_t)((uint32_t)data_size + (uint32_t)12)); 1285 | status |= _vl53l8cx_poll_for_answer(p_dev, 4, 1, 1286 | VL53L8CX_UI_CMD_STATUS, 0xff, 0x03); 1287 | 1288 | VL53L8CX_SwapBuffer(data, data_size); 1289 | } 1290 | 1291 | return status; 1292 | } 1293 | 1294 | uint8_t vl53l8cx_dci_replace_data( 1295 | VL53L8CX_Configuration *p_dev, 1296 | uint8_t *data, 1297 | uint32_t index, 1298 | uint16_t data_size, 1299 | uint8_t *new_data, 1300 | uint16_t new_data_size, 1301 | uint16_t new_data_pos) 1302 | { 1303 | uint8_t status = VL53L8CX_STATUS_OK; 1304 | 1305 | status |= vl53l8cx_dci_read_data(p_dev, data, index, data_size); 1306 | (void)memcpy(&(data[new_data_pos]), new_data, new_data_size); 1307 | status |= vl53l8cx_dci_write_data(p_dev, data, index, data_size); 1308 | 1309 | return status; 1310 | } 1311 | -------------------------------------------------------------------------------- /src/vl53l8cx_api.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Copyright (c) 2021 STMicroelectronics. 4 | * All rights reserved. 5 | * 6 | * This software is licensed under terms that can be found in the LICENSE file 7 | * in the root directory of this software component. 8 | * If no LICENSE file comes with this software, it is provided AS-IS. 9 | * 10 | ****************************************************************************** 11 | */ 12 | 13 | #ifndef VL53L8CX_API_H_ 14 | #define VL53L8CX_API_H_ 15 | 16 | #ifdef __cplusplus 17 | extern "C" { 18 | #endif 19 | 20 | #if defined (__ARMCC_VERSION) && (__ARMCC_VERSION < 6010050) 21 | #pragma anon_unions 22 | #endif 23 | 24 | 25 | 26 | #include "vl53l8cx_platform.h" 27 | 28 | /** 29 | * @brief Current driver version. 30 | */ 31 | 32 | #define VL53L8CX_API_REVISION "VL53L8CX_1.3.0" 33 | 34 | /** 35 | * @brief Default I2C address of VL53L8CX sensor. Can be changed using function 36 | * vl53l8cx_set_i2c_address() function is called. 37 | */ 38 | 39 | #define VL53L8CX_DEFAULT_I2C_ADDRESS ((uint16_t)0x52) 40 | 41 | /** 42 | * @brief Macro VL53L8CX_RESOLUTION_4X4 or VL53L8CX_RESOLUTION_8X8 allows 43 | * setting sensor in 4x4 mode or 8x8 mode, using function 44 | * vl53l8cx_set_resolution(). 45 | */ 46 | 47 | #define VL53L8CX_RESOLUTION_4X4 ((uint8_t) 16U) 48 | #define VL53L8CX_RESOLUTION_8X8 ((uint8_t) 64U) 49 | 50 | 51 | /** 52 | * @brief Macro VL53L8CX_TARGET_ORDER_STRONGEST or VL53L8CX_TARGET_ORDER_CLOSEST 53 | * are used to select the target order for data output. 54 | */ 55 | 56 | #define VL53L8CX_TARGET_ORDER_CLOSEST ((uint8_t) 1U) 57 | #define VL53L8CX_TARGET_ORDER_STRONGEST ((uint8_t) 2U) 58 | 59 | /** 60 | * @brief Macro VL53L8CX_RANGING_MODE_CONTINUOUS and 61 | * VL53L8CX_RANGING_MODE_AUTONOMOUS are used to change the ranging mode. 62 | * Autonomous mode can be used to set a precise integration time, whereas 63 | * continuous is always maximum. 64 | */ 65 | 66 | #define VL53L8CX_RANGING_MODE_CONTINUOUS ((uint8_t) 1U) 67 | #define VL53L8CX_RANGING_MODE_AUTONOMOUS ((uint8_t) 3U) 68 | 69 | /** 70 | * @brief The default power mode is VL53L8CX_POWER_MODE_WAKEUP. User can choose two 71 | * different modes to save power consumption when is the device 72 | * is not used: 73 | * - VL53L8CX_POWER_MODE_SLEEP: This mode retains the firmware and the configuration. It 74 | * is recommended when the device needs to quickly wake-up. 75 | * - VL53L8CX_POWER_MODE_DEEP_SLEEP: This mode clears all memory, by consequence the firmware, 76 | * the configuration and the calibration are lost. It is recommended when the device sleeps during 77 | * a long time as it consumes a very low current consumption. 78 | * Both modes can be changed using function vl53l8cx_set_power_mode(). 79 | */ 80 | 81 | #define VL53L8CX_POWER_MODE_SLEEP ((uint8_t) 0U) 82 | #define VL53L8CX_POWER_MODE_WAKEUP ((uint8_t) 1U) 83 | #define VL53L8CX_POWER_MODE_DEEP_SLEEP ((uint8_t) 2U) 84 | 85 | /** 86 | * @brief Macro VL53L8CX_STATUS_OK indicates that VL53L5 sensor has no error. 87 | * Macro VL53L8CX_STATUS_ERROR indicates that something is wrong (value, 88 | * I2C access, ...). Macro VL53L8CX_MCU_ERROR is used to indicate a MCU issue. 89 | */ 90 | 91 | #define VL53L8CX_STATUS_OK ((uint8_t) 0U) 92 | #define VL53L8CX_STATUS_TIMEOUT_ERROR ((uint8_t) 1U) 93 | #define VL53L8CX_STATUS_CORRUPTED_FRAME ((uint8_t) 2U) 94 | #define VL53L8CX_STATUS_LASER_SAFETY ((uint8_t) 3U) 95 | #define VL53L8CX_STATUS_XTALK_FAILED ((uint8_t) 4U) 96 | #define VL53L8CX_STATUS_FW_CHECKSUM_FAIL ((uint8_t) 5U) 97 | #define VL53L8CX_MCU_ERROR ((uint8_t) 66U) 98 | #define VL53L8CX_STATUS_INVALID_PARAM ((uint8_t) 127U) 99 | #define VL53L8CX_STATUS_ERROR ((uint8_t) 255U) 100 | 101 | /** 102 | * @brief Definitions for Range results block headers 103 | */ 104 | 105 | #if VL53L8CX_NB_TARGET_PER_ZONE == 1 106 | 107 | #define VL53L8CX_START_BH ((uint32_t)0x0000000DU) 108 | #define VL53L8CX_METADATA_BH ((uint32_t)0x54B400C0U) 109 | #define VL53L8CX_COMMONDATA_BH ((uint32_t)0x54C00040U) 110 | #define VL53L8CX_AMBIENT_RATE_BH ((uint32_t)0x54D00104U) 111 | #define VL53L8CX_SPAD_COUNT_BH ((uint32_t)0x55D00404U) 112 | #define VL53L8CX_NB_TARGET_DETECTED_BH ((uint32_t)0xDB840401U) 113 | #define VL53L8CX_SIGNAL_RATE_BH ((uint32_t)0xDBC40404U) 114 | #define VL53L8CX_RANGE_SIGMA_MM_BH ((uint32_t)0xDEC40402U) 115 | #define VL53L8CX_DISTANCE_BH ((uint32_t)0xDF440402U) 116 | #define VL53L8CX_REFLECTANCE_BH ((uint32_t)0xE0440401U) 117 | #define VL53L8CX_TARGET_STATUS_BH ((uint32_t)0xE0840401U) 118 | #define VL53L8CX_MOTION_DETECT_BH ((uint32_t)0xD85808C0U) 119 | 120 | #define VL53L8CX_METADATA_IDX ((uint16_t)0x54B4U) 121 | #define VL53L8CX_SPAD_COUNT_IDX ((uint16_t)0x55D0U) 122 | #define VL53L8CX_AMBIENT_RATE_IDX ((uint16_t)0x54D0U) 123 | #define VL53L8CX_NB_TARGET_DETECTED_IDX ((uint16_t)0xDB84U) 124 | #define VL53L8CX_SIGNAL_RATE_IDX ((uint16_t)0xDBC4U) 125 | #define VL53L8CX_RANGE_SIGMA_MM_IDX ((uint16_t)0xDEC4U) 126 | #define VL53L8CX_DISTANCE_IDX ((uint16_t)0xDF44U) 127 | #define VL53L8CX_REFLECTANCE_EST_PC_IDX ((uint16_t)0xE044U) 128 | #define VL53L8CX_TARGET_STATUS_IDX ((uint16_t)0xE084U) 129 | #define VL53L8CX_MOTION_DETEC_IDX ((uint16_t)0xD858U) 130 | 131 | #else 132 | #define VL53L8CX_START_BH ((uint32_t)0x0000000DU) 133 | #define VL53L8CX_METADATA_BH ((uint32_t)0x54B400C0U) 134 | #define VL53L8CX_COMMONDATA_BH ((uint32_t)0x54C00040U) 135 | #define VL53L8CX_AMBIENT_RATE_BH ((uint32_t)0x54D00104U) 136 | #define VL53L8CX_NB_TARGET_DETECTED_BH ((uint32_t)0x57D00401U) 137 | #define VL53L8CX_SPAD_COUNT_BH ((uint32_t)0x55D00404U) 138 | #define VL53L8CX_SIGNAL_RATE_BH ((uint32_t)0x58900404U) 139 | #define VL53L8CX_RANGE_SIGMA_MM_BH ((uint32_t)0x64900402U) 140 | #define VL53L8CX_DISTANCE_BH ((uint32_t)0x66900402U) 141 | #define VL53L8CX_REFLECTANCE_BH ((uint32_t)0x6A900401U) 142 | #define VL53L8CX_TARGET_STATUS_BH ((uint32_t)0x6B900401U) 143 | #define VL53L8CX_MOTION_DETECT_BH ((uint32_t)0xCC5008C0U) 144 | 145 | #define VL53L8CX_METADATA_IDX ((uint16_t)0x54B4U) 146 | #define VL53L8CX_SPAD_COUNT_IDX ((uint16_t)0x55D0U) 147 | #define VL53L8CX_AMBIENT_RATE_IDX ((uint16_t)0x54D0U) 148 | #define VL53L8CX_NB_TARGET_DETECTED_IDX ((uint16_t)0x57D0U) 149 | #define VL53L8CX_SIGNAL_RATE_IDX ((uint16_t)0x5890U) 150 | #define VL53L8CX_RANGE_SIGMA_MM_IDX ((uint16_t)0x6490U) 151 | #define VL53L8CX_DISTANCE_IDX ((uint16_t)0x6690U) 152 | #define VL53L8CX_REFLECTANCE_EST_PC_IDX ((uint16_t)0x6A90U) 153 | #define VL53L8CX_TARGET_STATUS_IDX ((uint16_t)0x6B90U) 154 | #define VL53L8CX_MOTION_DETEC_IDX ((uint16_t)0xCC50U) 155 | #endif 156 | 157 | 158 | /** 159 | * @brief Inner Macro for API. Not for user, only for development. 160 | */ 161 | 162 | #define VL53L8CX_NVM_DATA_SIZE ((uint16_t)492U) 163 | #define VL53L8CX_CONFIGURATION_SIZE ((uint16_t)972U) 164 | #define VL53L8CX_OFFSET_BUFFER_SIZE ((uint16_t)488U) 165 | #define VL53L8CX_XTALK_BUFFER_SIZE ((uint16_t)776U) 166 | 167 | #define VL53L8CX_DCI_ZONE_CONFIG ((uint16_t)0x5450U) 168 | #define VL53L8CX_DCI_FREQ_HZ ((uint16_t)0x5458U) 169 | #define VL53L8CX_DCI_INT_TIME ((uint16_t)0x545CU) 170 | #define VL53L8CX_DCI_FW_NB_TARGET ((uint16_t)0x5478) 171 | #define VL53L8CX_DCI_RANGING_MODE ((uint16_t)0xAD30U) 172 | #define VL53L8CX_DCI_DSS_CONFIG ((uint16_t)0xAD38U) 173 | #define VL53L8CX_DCI_VHV_CONFIG ((uint16_t)0xAD60U) 174 | #define VL53L8CX_DCI_TARGET_ORDER ((uint16_t)0xAE64U) 175 | #define VL53L8CX_DCI_SHARPENER ((uint16_t)0xAED8U) 176 | #define VL53L8CX_DCI_INTERNAL_CP ((uint16_t)0xB39CU) 177 | #define VL53L8CX_DCI_SYNC_PIN ((uint16_t)0xB5F0U) 178 | #define VL53L8CX_DCI_MOTION_DETECTOR_CFG ((uint16_t)0xBFACU) 179 | #define VL53L8CX_DCI_SINGLE_RANGE ((uint16_t)0xD964U) 180 | #define VL53L8CX_DCI_OUTPUT_CONFIG ((uint16_t)0xD968U) 181 | #define VL53L8CX_DCI_OUTPUT_ENABLES ((uint16_t)0xD970U) 182 | #define VL53L8CX_DCI_OUTPUT_LIST ((uint16_t)0xD980U) 183 | #define VL53L8CX_DCI_PIPE_CONTROL ((uint16_t)0xDB80U) 184 | 185 | #define VL53L8CX_UI_CMD_STATUS ((uint16_t)0x2C00U) 186 | #define VL53L8CX_UI_CMD_START ((uint16_t)0x2C04U) 187 | #define VL53L8CX_UI_CMD_END ((uint16_t)0x2FFFU) 188 | 189 | /** 190 | * @brief Inner values for API. Max buffer size depends of the selected output. 191 | */ 192 | 193 | #ifndef VL53L8CX_DISABLE_AMBIENT_PER_SPAD 194 | #define L5CX_AMB_SIZE 260U 195 | #else 196 | #define L5CX_AMB_SIZE 0U 197 | #endif 198 | 199 | #ifndef VL53L8CX_DISABLE_NB_SPADS_ENABLED 200 | #define L5CX_SPAD_SIZE 260U 201 | #else 202 | #define L5CX_SPAD_SIZE 0U 203 | #endif 204 | 205 | #ifndef VL53L8CX_DISABLE_NB_TARGET_DETECTED 206 | #define L5CX_NTAR_SIZE 68U 207 | #else 208 | #define L5CX_NTAR_SIZE 0U 209 | #endif 210 | 211 | #ifndef VL53L8CX_DISABLE_SIGNAL_PER_SPAD 212 | #define L5CX_SPS_SIZE ((256U * VL53L8CX_NB_TARGET_PER_ZONE) + 4U) 213 | #else 214 | #define L5CX_SPS_SIZE 0U 215 | #endif 216 | 217 | #ifndef VL53L8CX_DISABLE_RANGE_SIGMA_MM 218 | #define L5CX_SIGR_SIZE ((128U * VL53L8CX_NB_TARGET_PER_ZONE) + 4U) 219 | #else 220 | #define L5CX_SIGR_SIZE 0U 221 | #endif 222 | 223 | #ifndef VL53L8CX_DISABLE_DISTANCE_MM 224 | #define L5CX_DIST_SIZE ((128U * VL53L8CX_NB_TARGET_PER_ZONE) + 4U) 225 | #else 226 | #define L5CX_DIST_SIZE 0U 227 | #endif 228 | 229 | #ifndef VL53L8CX_DISABLE_REFLECTANCE_PERCENT 230 | #define L5CX_RFLEST_SIZE ((64U *VL53L8CX_NB_TARGET_PER_ZONE) + 4U) 231 | #else 232 | #define L5CX_RFLEST_SIZE 0U 233 | #endif 234 | 235 | #ifndef VL53L8CX_DISABLE_TARGET_STATUS 236 | #define L5CX_STA_SIZE ((64U *VL53L8CX_NB_TARGET_PER_ZONE) + 4U) 237 | #else 238 | #define L5CX_STA_SIZE 0U 239 | #endif 240 | 241 | #ifndef VL53L8CX_DISABLE_MOTION_INDICATOR 242 | #define L5CX_MOT_SIZE 144U 243 | #else 244 | #define L5CX_MOT_SIZE 0U 245 | #endif 246 | 247 | /** 248 | * @brief Macro VL53L8CX_MAX_RESULTS_SIZE indicates the maximum size used by 249 | * output through I2C. Value 40 corresponds to headers + meta-data + common-data 250 | * and 20 corresponds to the footer. 251 | */ 252 | 253 | #define VL53L8CX_MAX_RESULTS_SIZE ( 40U \ 254 | + L5CX_AMB_SIZE + L5CX_SPAD_SIZE + L5CX_NTAR_SIZE + L5CX_SPS_SIZE \ 255 | + L5CX_SIGR_SIZE + L5CX_DIST_SIZE + L5CX_RFLEST_SIZE + L5CX_STA_SIZE \ 256 | + L5CX_MOT_SIZE + 20U) 257 | 258 | /** 259 | * @brief Macro VL53L8CX_TEMPORARY_BUFFER_SIZE can be used to know the size of 260 | * the temporary buffer. The minimum size is 1024, and the maximum depends of 261 | * the output configuration. 262 | */ 263 | 264 | #if VL53L8CX_MAX_RESULTS_SIZE < 1024U 265 | #define VL53L8CX_TEMPORARY_BUFFER_SIZE ((uint32_t) 1024U) 266 | #else 267 | #define VL53L8CX_TEMPORARY_BUFFER_SIZE ((uint32_t) VL53L8CX_MAX_RESULTS_SIZE) 268 | #endif 269 | 270 | 271 | /** 272 | * @brief Structure VL53L8CX_Configuration contains the sensor configuration. 273 | * User MUST not manually change these field, except for the sensor address. 274 | */ 275 | 276 | typedef struct { 277 | /* Platform, filled by customer into the 'vl53l8cx_platform.h' file */ 278 | VL53L8CX_Platform platform; 279 | /* Results streamcount, value auto-incremented at each range */ 280 | uint8_t streamcount; 281 | /* Size of data read though I2C */ 282 | uint32_t data_read_size; 283 | /* Address of default configuration buffer */ 284 | uint8_t *default_configuration; 285 | /* Address of default Xtalk buffer */ 286 | uint8_t *default_xtalk; 287 | /* Offset buffer */ 288 | uint8_t offset_data[VL53L8CX_OFFSET_BUFFER_SIZE]; 289 | /* Xtalk buffer */ 290 | uint8_t xtalk_data[VL53L8CX_XTALK_BUFFER_SIZE]; 291 | /* Temporary buffer used for internal driver processing */ 292 | uint8_t temp_buffer[VL53L8CX_TEMPORARY_BUFFER_SIZE]; 293 | /* Auto-stop flag for stopping the sensor */ 294 | uint8_t is_auto_stop_enabled; 295 | } VL53L8CX_Configuration; 296 | 297 | 298 | /** 299 | * @brief Structure VL53L8CX_ResultsData contains the ranging results of 300 | * VL53L8CX. If user wants more than 1 target per zone, the results can be split 301 | * into 2 sub-groups : 302 | * - Per zone results. These results are common to all targets (ambient_per_spad 303 | * , nb_target_detected and nb_spads_enabled). 304 | * - Per target results : These results are different relative to the detected 305 | * target (signal_per_spad, range_sigma_mm, distance_mm, reflectance, 306 | * target_status). 307 | */ 308 | 309 | typedef struct { 310 | /* Internal sensor silicon temperature */ 311 | int8_t silicon_temp_degc; 312 | 313 | /* Ambient noise in kcps/spads */ 314 | #ifndef VL53L8CX_DISABLE_AMBIENT_PER_SPAD 315 | uint32_t ambient_per_spad[VL53L8CX_RESOLUTION_8X8]; 316 | #endif 317 | 318 | /* Number of valid target detected for 1 zone */ 319 | #ifndef VL53L8CX_DISABLE_NB_TARGET_DETECTED 320 | uint8_t nb_target_detected[VL53L8CX_RESOLUTION_8X8]; 321 | #endif 322 | 323 | /* Number of spads enabled for this ranging */ 324 | #ifndef VL53L8CX_DISABLE_NB_SPADS_ENABLED 325 | uint32_t nb_spads_enabled[VL53L8CX_RESOLUTION_8X8]; 326 | #endif 327 | 328 | /* Signal returned to the sensor in kcps/spads */ 329 | #ifndef VL53L8CX_DISABLE_SIGNAL_PER_SPAD 330 | uint32_t signal_per_spad[(VL53L8CX_RESOLUTION_8X8 331 | *VL53L8CX_NB_TARGET_PER_ZONE)]; 332 | #endif 333 | 334 | /* Sigma of the current distance in mm */ 335 | #ifndef VL53L8CX_DISABLE_RANGE_SIGMA_MM 336 | uint16_t range_sigma_mm[(VL53L8CX_RESOLUTION_8X8 337 | *VL53L8CX_NB_TARGET_PER_ZONE)]; 338 | #endif 339 | 340 | /* Measured distance in mm */ 341 | #ifndef VL53L8CX_DISABLE_DISTANCE_MM 342 | int16_t distance_mm[(VL53L8CX_RESOLUTION_8X8 343 | *VL53L8CX_NB_TARGET_PER_ZONE)]; 344 | #endif 345 | 346 | /* Estimated reflectance in percent */ 347 | #ifndef VL53L8CX_DISABLE_REFLECTANCE_PERCENT 348 | uint8_t reflectance[(VL53L8CX_RESOLUTION_8X8 349 | *VL53L8CX_NB_TARGET_PER_ZONE)]; 350 | #endif 351 | 352 | /* Status indicating the measurement validity (5 & 9 means ranging OK)*/ 353 | #ifndef VL53L8CX_DISABLE_TARGET_STATUS 354 | uint8_t target_status[(VL53L8CX_RESOLUTION_8X8 355 | *VL53L8CX_NB_TARGET_PER_ZONE)]; 356 | #endif 357 | 358 | /* Motion detector results */ 359 | #ifndef VL53L8CX_DISABLE_MOTION_INDICATOR 360 | struct { 361 | uint32_t global_indicator_1; 362 | uint32_t global_indicator_2; 363 | uint8_t status; 364 | uint8_t nb_of_detected_aggregates; 365 | uint8_t nb_of_aggregates; 366 | uint8_t spare; 367 | uint32_t motion[32]; 368 | } motion_indicator; 369 | #endif 370 | 371 | } VL53L8CX_ResultsData; 372 | 373 | #ifndef BLOCK_HEADER 374 | #define BLOCK_HEADER 375 | union Block_header { 376 | uint32_t bytes; 377 | struct { 378 | uint32_t type : 4; 379 | uint32_t size : 12; 380 | uint32_t idx : 16; 381 | }; 382 | }; 383 | #endif 384 | 385 | uint8_t vl53l8cx_is_alive( 386 | VL53L8CX_Configuration *p_dev, 387 | uint8_t *p_is_alive); 388 | 389 | /** 390 | * @brief Mandatory function used to initialize the sensor. This function must 391 | * be called after a power on, to load the firmware into the VL53L8CX. It takes 392 | * a few hundred milliseconds. 393 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 394 | * @return (uint8_t) status : 0 if initialization is OK. 395 | */ 396 | 397 | uint8_t vl53l8cx_init( 398 | VL53L8CX_Configuration *p_dev); 399 | 400 | /** 401 | * @brief This function is used to change the I2C address of the sensor. If 402 | * multiple VL53L5 sensors are connected to the same I2C line, all other LPn 403 | * pins needs to be set to Low. The default sensor address is 0x52. 404 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 405 | * @param (uint16_t) i2c_address : New I2C address. 406 | * @return (uint8_t) status : 0 if new address is OK 407 | */ 408 | 409 | uint8_t vl53l8cx_set_i2c_address( 410 | VL53L8CX_Configuration *p_dev, 411 | uint16_t i2c_address); 412 | 413 | /** 414 | * @brief This function is used to get the current sensor power mode. 415 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 416 | * @param (uint8_t) *p_power_mode : Current power mode. The value of this 417 | * pointer is equal to 0 if the sensor is in low power, 418 | * (VL53L8CX_POWER_MODE_SLEEP), or 1 if sensor is in standard mode 419 | * (VL53L8CX_POWER_MODE_WAKEUP). 420 | * @return (uint8_t) status : 0 if power mode is OK 421 | */ 422 | 423 | uint8_t vl53l8cx_get_power_mode( 424 | VL53L8CX_Configuration *p_dev, 425 | uint8_t *p_power_mode); 426 | 427 | /** 428 | * @brief This function is used to set the sensor in Low Power mode, for 429 | * example if the sensor is not used during a long time. The macro 430 | * VL53L8CX_POWER_MODE_SLEEP can be used to enable the low power mode. When user 431 | * want to restart the sensor, he can use macro VL53L8CX_POWER_MODE_WAKEUP. 432 | * Please ensure that the device is not streaming before calling the function. 433 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 434 | * @param (uint8_t) power_mode : Selected power mode (VL53L8CX_POWER_MODE_SLEEP 435 | * or VL53L8CX_POWER_MODE_WAKEUP) 436 | * @return (uint8_t) status : 0 if power mode is OK, or 127 if power mode 437 | * requested by user is not valid. 438 | */ 439 | 440 | uint8_t vl53l8cx_set_power_mode( 441 | VL53L8CX_Configuration *p_dev, 442 | uint8_t power_mode); 443 | 444 | /** 445 | * @brief This function starts a ranging session. When the sensor streams, host 446 | * cannot change settings 'on-the-fly'. 447 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 448 | * @return (uint8_t) status : 0 if start is OK. 449 | */ 450 | 451 | uint8_t vl53l8cx_start_ranging( 452 | VL53L8CX_Configuration *p_dev); 453 | 454 | /** 455 | * @brief This function stops the ranging session. It must be used when the 456 | * sensor streams, after calling vl53l8cx_start_ranging(). 457 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 458 | * @return (uint8_t) status : 0 if stop is OK 459 | */ 460 | 461 | uint8_t vl53l8cx_stop_ranging( 462 | VL53L8CX_Configuration *p_dev); 463 | 464 | /** 465 | * @brief This function checks if a new data is ready by polling I2C. If a new 466 | * data is ready, a flag will be raised. 467 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 468 | * @param (uint8_t) *p_isReady : Value of this pointer be updated to 0 if data 469 | * is not ready, or 1 if a new data is ready. 470 | * @return (uint8_t) status : 0 if I2C reading is OK 471 | */ 472 | 473 | uint8_t vl53l8cx_check_data_ready( 474 | VL53L8CX_Configuration *p_dev, 475 | uint8_t *p_isReady); 476 | 477 | /** 478 | * @brief This function gets the ranging data, using the selected output and the 479 | * resolution. 480 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 481 | * @param (VL53L8CX_ResultsData) *p_results : VL53L5 results structure. 482 | * @return (uint8_t) status : 0 data are successfully get. 483 | */ 484 | 485 | uint8_t vl53l8cx_get_ranging_data( 486 | VL53L8CX_Configuration *p_dev, 487 | VL53L8CX_ResultsData *p_results); 488 | 489 | /** 490 | * @brief This function gets the current resolution (4x4 or 8x8). 491 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 492 | * @param (uint8_t) *p_resolution : Value of this pointer will be equal to 16 493 | * for 4x4 mode, and 64 for 8x8 mode. 494 | * @return (uint8_t) status : 0 if resolution is OK. 495 | */ 496 | 497 | uint8_t vl53l8cx_get_resolution( 498 | VL53L8CX_Configuration *p_dev, 499 | uint8_t *p_resolution); 500 | 501 | /** 502 | * @brief This function sets a new resolution (4x4 or 8x8). 503 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 504 | * @param (uint8_t) resolution : Use macro VL53L8CX_RESOLUTION_4X4 or 505 | * VL53L8CX_RESOLUTION_8X8 to set the resolution. 506 | * @return (uint8_t) status : 0 if set resolution is OK. 507 | */ 508 | 509 | uint8_t vl53l8cx_set_resolution( 510 | VL53L8CX_Configuration *p_dev, 511 | uint8_t resolution); 512 | 513 | /** 514 | * @brief This function gets the current ranging frequency in Hz. Ranging 515 | * frequency corresponds to the time between each measurement. 516 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 517 | * @param (uint8_t) *p_frequency_hz: Contains the ranging frequency in Hz. 518 | * @return (uint8_t) status : 0 if ranging frequency is OK. 519 | */ 520 | 521 | uint8_t vl53l8cx_get_ranging_frequency_hz( 522 | VL53L8CX_Configuration *p_dev, 523 | uint8_t *p_frequency_hz); 524 | 525 | /** 526 | * @brief This function sets a new ranging frequency in Hz. Ranging frequency 527 | * corresponds to the measurements frequency. This setting depends of 528 | * the resolution, so please select your resolution before using this function. 529 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 530 | * @param (uint8_t) frequency_hz : Contains the ranging frequency in Hz. 531 | * - For 4x4, min and max allowed values are : [1;60] 532 | * - For 8x8, min and max allowed values are : [1;15] 533 | * @return (uint8_t) status : 0 if ranging frequency is OK, or 127 if the value 534 | * is not correct. 535 | */ 536 | 537 | uint8_t vl53l8cx_set_ranging_frequency_hz( 538 | VL53L8CX_Configuration *p_dev, 539 | uint8_t frequency_hz); 540 | 541 | /** 542 | * @brief This function gets the current integration time in ms. 543 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 544 | * @param (uint32_t) *p_time_ms: Contains integration time in ms. 545 | * @return (uint8_t) status : 0 if integration time is OK. 546 | */ 547 | 548 | uint8_t vl53l8cx_get_integration_time_ms( 549 | VL53L8CX_Configuration *p_dev, 550 | uint32_t *p_time_ms); 551 | 552 | /** 553 | * @brief This function sets a new integration time in ms. Integration time must 554 | * be computed to be lower than the ranging period, for a selected resolution. 555 | * Please note that this function has no impact on ranging mode continuous. 556 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 557 | * @param (uint32_t) time_ms : Contains the integration time in ms. For all 558 | * resolutions and frequency, the minimum value is 2ms, and the maximum is 559 | * 1000ms. 560 | * @return (uint8_t) status : 0 if set integration time is OK. 561 | */ 562 | 563 | uint8_t vl53l8cx_set_integration_time_ms( 564 | VL53L8CX_Configuration *p_dev, 565 | uint32_t integration_time_ms); 566 | 567 | /** 568 | * @brief This function gets the current sharpener in percent. Sharpener can be 569 | * changed to blur more or less zones depending of the application. 570 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 571 | * @param (uint32_t) *p_sharpener_percent: Contains the sharpener in percent. 572 | * @return (uint8_t) status : 0 if get sharpener is OK. 573 | */ 574 | 575 | uint8_t vl53l8cx_get_sharpener_percent( 576 | VL53L8CX_Configuration *p_dev, 577 | uint8_t *p_sharpener_percent); 578 | 579 | /** 580 | * @brief This function sets a new sharpener value in percent. Sharpener can be 581 | * changed to blur more or less zones depending of the application. Min value is 582 | * 0 (disabled), and max is 99. 583 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 584 | * @param (uint32_t) sharpener_percent : Value between 0 (disabled) and 99%. 585 | * @return (uint8_t) status : 0 if set sharpener is OK. 586 | */ 587 | 588 | uint8_t vl53l8cx_set_sharpener_percent( 589 | VL53L8CX_Configuration *p_dev, 590 | uint8_t sharpener_percent); 591 | 592 | /** 593 | * @brief This function gets the current target order (closest or strongest). 594 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 595 | * @param (uint8_t) *p_target_order: Contains the target order. 596 | * @return (uint8_t) status : 0 if get target order is OK. 597 | */ 598 | 599 | uint8_t vl53l8cx_get_target_order( 600 | VL53L8CX_Configuration *p_dev, 601 | uint8_t *p_target_order); 602 | 603 | /** 604 | * @brief This function sets a new target order. Please use macros 605 | * VL53L8CX_TARGET_ORDER_STRONGEST and VL53L8CX_TARGET_ORDER_CLOSEST to define 606 | * the new output order. By default, the sensor is configured with the strongest 607 | * output. 608 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 609 | * @param (uint8_t) target_order : Required target order. 610 | * @return (uint8_t) status : 0 if set target order is OK, or 127 if target 611 | * order is unknown. 612 | */ 613 | 614 | uint8_t vl53l8cx_set_target_order( 615 | VL53L8CX_Configuration *p_dev, 616 | uint8_t target_order); 617 | 618 | /** 619 | * @brief This function is used to get the ranging mode. Two modes are 620 | * available using ULD : Continuous and autonomous. The default 621 | * mode is Autonomous. 622 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 623 | * @param (uint8_t) *p_ranging_mode : current ranging mode 624 | * @return (uint8_t) status : 0 if get ranging mode is OK. 625 | */ 626 | 627 | uint8_t vl53l8cx_get_ranging_mode( 628 | VL53L8CX_Configuration *p_dev, 629 | uint8_t *p_ranging_mode); 630 | 631 | /** 632 | * @brief This function is used to set the ranging mode. Two modes are 633 | * available using ULD : Continuous and autonomous. The default 634 | * mode is Autonomous. 635 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 636 | * @param (uint8_t) ranging_mode : Use macros VL53L8CX_RANGING_MODE_CONTINUOUS, 637 | * VL53L8CX_RANGING_MODE_CONTINUOUS. 638 | * @return (uint8_t) status : 0 if set ranging mode is OK. 639 | */ 640 | 641 | uint8_t vl53l8cx_set_ranging_mode( 642 | VL53L8CX_Configuration *p_dev, 643 | uint8_t ranging_mode); 644 | 645 | /** 646 | * @brief This function is used to check if the synchronization pin is enabled 647 | * or disabled. When it is enabled, the sensor waits an interrupt on B1 pin 648 | * to start the next measurement. It is useful for multi-devices 649 | * synchronization. By default the sync pin is disabled. 650 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 651 | * @param (uint8_t*) p_is_sync_pin_enabled : Pointer of sync pin status. Value 652 | * overridden to 0 if the pin is disabled, or 1 if the pin is enabled. 653 | * @return (uint8_t) status : 0 if get sync pin OK. 654 | */ 655 | uint8_t vl53l8cx_get_external_sync_pin_enable( 656 | VL53L8CX_Configuration *p_dev, 657 | uint8_t *p_is_sync_pin_enabled); 658 | 659 | 660 | /** 661 | * @brief This function is used to enable or disable the synchronization pin. When 662 | * it is enabled, the sensor waits an interrupt on B1 pin to start the next 663 | * measurement. It is useful for multi-devices synchronization. By default the sync 664 | * pin is disabled. 665 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 666 | * @param (uint8_t) enable_sync_pin : Ste the value to 1 to enable the sync 667 | * pin, or 0 to disable it. 668 | * @return (uint8_t) status : 0 if set sync pin OK. 669 | */ 670 | uint8_t vl53l8cx_set_external_sync_pin_enable( 671 | VL53L8CX_Configuration *p_dev, 672 | uint8_t enable_sync_pin); 673 | 674 | /** 675 | * @brief This function is used to get the number of frames between 2 temperature 676 | * compensation. 677 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 678 | * @param (uint32_t) *p_repeat_count : Number of frames before next temperature 679 | * compensation. Set to 0 to disable the feature (default configuration). 680 | */ 681 | uint8_t vl53l8cx_get_VHV_repeat_count( 682 | VL53L8CX_Configuration *p_dev, 683 | uint32_t *p_repeat_count); 684 | 685 | /** 686 | * @brief This function is used to set a periodic temperature compensation. By 687 | * setting a repeat count different to 0 the firmware automatically runs a 688 | * temperature calibration every N frames. 689 | * default the repeat count is set to 0 690 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 691 | * @param (uint32_t) repeat_count : Number of frames between temperature 692 | * compensation. Set to 0 to disable the feature (default configuration). 693 | */ 694 | uint8_t vl53l8cx_set_VHV_repeat_count( 695 | VL53L8CX_Configuration *p_dev, 696 | uint32_t repeat_count); 697 | 698 | /** 699 | * @brief This function can be used to read 'extra data' from DCI. Using a known 700 | * index, the function fills the casted structure passed in argument. 701 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 702 | * @param (uint8_t) *data : This field can be a casted structure, or a simple 703 | * array. Please note that the FW only accept data of 32 bits. So field data can 704 | * only have a size of 32, 64, 96, 128, bits .... 705 | * @param (uint32_t) index : Index of required value. 706 | * @param (uint16_t)*data_size : This field must be the structure or array size 707 | * (using sizeof() function). 708 | * @return (uint8_t) status : 0 if OK 709 | */ 710 | 711 | uint8_t vl53l8cx_dci_read_data( 712 | VL53L8CX_Configuration *p_dev, 713 | uint8_t *data, 714 | uint32_t index, 715 | uint16_t data_size); 716 | 717 | /** 718 | * @brief This function can be used to write 'extra data' to DCI. The data can 719 | * be simple data, or casted structure. 720 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 721 | * @param (uint8_t) *data : This field can be a casted structure, or a simple 722 | * array. Please note that the FW only accept data of 32 bits. So field data can 723 | * only have a size of 32, 64, 96, 128, bits .. 724 | * @param (uint32_t) index : Index of required value. 725 | * @param (uint16_t)*data_size : This field must be the structure or array size 726 | * (using sizeof() function). 727 | * @return (uint8_t) status : 0 if OK 728 | */ 729 | 730 | uint8_t vl53l8cx_dci_write_data( 731 | VL53L8CX_Configuration *p_dev, 732 | uint8_t *data, 733 | uint32_t index, 734 | uint16_t data_size); 735 | 736 | /** 737 | * @brief This function can be used to replace 'extra data' in DCI. The data can 738 | * be simple data, or casted structure. 739 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 740 | * @param (uint8_t) *data : This field can be a casted structure, or a simple 741 | * array. Please note that the FW only accept data of 32 bits. So field data can 742 | * only have a size of 32, 64, 96, 128, bits .. 743 | * @param (uint32_t) index : Index of required value. 744 | * @param (uint16_t)*data_size : This field must be the structure or array size 745 | * (using sizeof() function). 746 | * @param (uint8_t) *new_data : Contains the new fields. 747 | * @param (uint16_t) new_data_size : New data size. 748 | * @param (uint16_t) new_data_pos : New data position into the buffer. 749 | * @return (uint8_t) status : 0 if OK 750 | */ 751 | 752 | uint8_t vl53l8cx_dci_replace_data( 753 | VL53L8CX_Configuration *p_dev, 754 | uint8_t *data, 755 | uint32_t index, 756 | uint16_t data_size, 757 | uint8_t *new_data, 758 | uint16_t new_data_size, 759 | uint16_t new_data_pos); 760 | 761 | #ifdef __cplusplus 762 | } 763 | #endif 764 | 765 | #endif //VL53L8CX_API_H_ 766 | -------------------------------------------------------------------------------- /src/vl53l8cx_platform.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file vl53l8cx_platform.cpp 4 | * @author STMicroelectronics 5 | * @version V1.0.0 6 | * @date 11 November 2021 7 | * @brief Implementation of the platform dependent APIs. 8 | ****************************************************************************** 9 | * @attention 10 | * 11 | *

© COPYRIGHT(c) 2021 STMicroelectronics

12 | * 13 | * Redistribution and use in source and binary forms, with or without modification, 14 | * are permitted provided that the following conditions are met: 15 | * 1. Redistributions of source code must retain the above copyright notice, 16 | * this list of conditions and the following disclaimer. 17 | * 2. Redistributions in binary form must reproduce the above copyright notice, 18 | * this list of conditions and the following disclaimer in the documentation 19 | * and/or other materials provided with the distribution. 20 | * 3. Neither the name of STMicroelectronics nor the names of its contributors 21 | * may be used to endorse or promote products derived from this software 22 | * without specific prior written permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 30 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 31 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 32 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 33 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | * 35 | ****************************************************************************** 36 | */ 37 | 38 | 39 | #include "vl53l8cx_platform.h" 40 | 41 | 42 | uint8_t VL53L8CX_RdByte( 43 | VL53L8CX_Platform *p_platform, 44 | uint16_t RegisterAdress, 45 | uint8_t *p_value) 46 | { 47 | return p_platform->Read(p_platform->handle, RegisterAdress, p_value, 1U); 48 | } 49 | 50 | uint8_t VL53L8CX_WrByte( 51 | VL53L8CX_Platform *p_platform, 52 | uint16_t RegisterAdress, 53 | uint8_t value) 54 | { 55 | return p_platform->Write(p_platform->handle, RegisterAdress, &value, 1U); 56 | } 57 | 58 | uint8_t VL53L8CX_WrMulti( 59 | VL53L8CX_Platform *p_platform, 60 | uint16_t RegisterAdress, 61 | uint8_t *p_values, 62 | uint32_t size) 63 | { 64 | return p_platform->Write(p_platform->handle, RegisterAdress, p_values, size); 65 | } 66 | 67 | uint8_t VL53L8CX_RdMulti( 68 | VL53L8CX_Platform *p_platform, 69 | uint16_t RegisterAdress, 70 | uint8_t *p_values, 71 | uint32_t size) 72 | { 73 | return p_platform->Read(p_platform->handle, RegisterAdress, p_values, size); 74 | } 75 | 76 | void VL53L8CX_SwapBuffer( 77 | uint8_t *buffer, 78 | uint16_t size) 79 | { 80 | uint32_t i, tmp; 81 | 82 | /* Example of possible implementation using */ 83 | for (i = 0; i < size; i = i + 4) { 84 | tmp = ( 85 | buffer[i] << 24) 86 | | (buffer[i + 1] << 16) 87 | | (buffer[i + 2] << 8) 88 | | (buffer[i + 3]); 89 | 90 | memcpy(&(buffer[i]), &tmp, 4); 91 | } 92 | } 93 | 94 | uint8_t VL53L8CX_WaitMs( 95 | VL53L8CX_Platform *p_platform, 96 | uint32_t TimeMs) 97 | { 98 | return p_platform->Wait(p_platform->handle, TimeMs); 99 | } 100 | -------------------------------------------------------------------------------- /src/vl53l8cx_platform.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file vl53l8cx_platform.h 4 | * @author STMicroelectronics 5 | * @version V1.0.0 6 | * @date 11 November 2021 7 | * @brief Header file of the platform dependent structures. 8 | ****************************************************************************** 9 | * @attention 10 | * 11 | *

© COPYRIGHT(c) 2021 STMicroelectronics

12 | * 13 | * Redistribution and use in source and binary forms, with or without modification, 14 | * are permitted provided that the following conditions are met: 15 | * 1. Redistributions of source code must retain the above copyright notice, 16 | * this list of conditions and the following disclaimer. 17 | * 2. Redistributions in binary form must reproduce the above copyright notice, 18 | * this list of conditions and the following disclaimer in the documentation 19 | * and/or other materials provided with the distribution. 20 | * 3. Neither the name of STMicroelectronics nor the names of its contributors 21 | * may be used to endorse or promote products derived from this software 22 | * without specific prior written permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 30 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 31 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 32 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 33 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | * 35 | ****************************************************************************** 36 | */ 37 | 38 | #ifndef _VL53L8CX_PLATFORM_H_ 39 | #define _VL53L8CX_PLATFORM_H_ 40 | 41 | #ifdef __cplusplus 42 | extern "C" { 43 | #endif 44 | 45 | 46 | #pragma once 47 | 48 | #include 49 | #include 50 | #include "vl53l8cx_platform_config.h" 51 | 52 | #define VL53L8CX_COMMS_CHUNK_SIZE 4096 53 | #define SPI_WRITE_MASK(x) (uint16_t)(x | 0x8000) 54 | #define SPI_READ_MASK(x) (uint16_t)(x & ~0x8000) 55 | 56 | typedef uint8_t (*VL53L8CX_wait_Func)(void *, uint32_t); 57 | typedef uint8_t (*VL53L8CX_write_Func)(void *, uint16_t, uint8_t *, uint32_t); 58 | typedef uint8_t (*VL53L8CX_read_Func)(void *, uint16_t, uint8_t *, uint32_t); 59 | 60 | #ifndef DEFAULT_I2C_BUFFER_LEN 61 | #ifdef ARDUINO_SAM_DUE 62 | /* FIXME: It seems that an I2C buffer of BUFFER_LENGTH does not work on Arduino DUE. So, we need to decrease the size */ 63 | #define DEFAULT_I2C_BUFFER_LEN (BUFFER_LENGTH - 2) 64 | #else 65 | #ifdef BUFFER_LENGTH 66 | #define DEFAULT_I2C_BUFFER_LEN BUFFER_LENGTH 67 | #else 68 | #define DEFAULT_I2C_BUFFER_LEN 32 69 | #endif 70 | #endif 71 | #endif 72 | typedef struct { 73 | uint16_t address; 74 | VL53L8CX_write_Func Write; 75 | VL53L8CX_read_Func Read; 76 | VL53L8CX_wait_Func Wait; 77 | void *handle; 78 | } VL53L8CX_Platform; 79 | 80 | 81 | uint8_t VL53L8CX_RdByte( 82 | VL53L8CX_Platform *p_platform, 83 | uint16_t RegisterAddress, 84 | uint8_t *p_value); 85 | 86 | uint8_t VL53L8CX_WrByte( 87 | VL53L8CX_Platform *p_platform, 88 | uint16_t RegisterAddress, 89 | uint8_t value); 90 | 91 | uint8_t VL53L8CX_WrMulti( 92 | VL53L8CX_Platform *p_platform, 93 | uint16_t RegisterAddress, 94 | uint8_t *p_values, 95 | uint32_t size); 96 | 97 | uint8_t VL53L8CX_RdMulti( 98 | VL53L8CX_Platform *p_platform, 99 | uint16_t RegisterAddress, 100 | uint8_t *p_values, 101 | uint32_t size); 102 | 103 | uint8_t VL53L8CX_WaitMs( 104 | VL53L8CX_Platform *p_platform, 105 | uint32_t TimeMs); 106 | void VL53L8CX_SwapBuffer( 107 | uint8_t *buffer, 108 | uint16_t size); 109 | 110 | #ifdef __cplusplus 111 | } 112 | #endif 113 | 114 | #endif // _VL53L8CX_PLATFORM_H_ 115 | -------------------------------------------------------------------------------- /src/vl53l8cx_platform_config.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file vl53l8cx_platform_config.h 4 | * @author STMicroelectronics 5 | * @version V1.0.0 6 | * @date 11 November 2021 7 | * @brief Header file for the platform settings. 8 | ****************************************************************************** 9 | * @attention 10 | * 11 | *

© COPYRIGHT(c) 2021 STMicroelectronics

12 | * 13 | * Redistribution and use in source and binary forms, with or without modification, 14 | * are permitted provided that the following conditions are met: 15 | * 1. Redistributions of source code must retain the above copyright notice, 16 | * this list of conditions and the following disclaimer. 17 | * 2. Redistributions in binary form must reproduce the above copyright notice, 18 | * this list of conditions and the following disclaimer in the documentation 19 | * and/or other materials provided with the distribution. 20 | * 3. Neither the name of STMicroelectronics nor the names of its contributors 21 | * may be used to endorse or promote products derived from this software 22 | * without specific prior written permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 30 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 31 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 32 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 33 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | * 35 | ****************************************************************************** 36 | */ 37 | 38 | #ifndef _VL53L8CX_PLATFORM_CONFIG_H_ 39 | #define _VL53L8CX_PLATFORM_CONFIG_H_ 40 | 41 | #if __has_include("vl53l8cx_platform_config_custom.h") 42 | #include "vl53l8cx_platform_config_custom.h" 43 | #else 44 | #include "vl53l8cx_platform_config_default.h" 45 | #endif 46 | 47 | #endif // _VL53L8CX_PLATFORM_CONFIG_H_ 48 | -------------------------------------------------------------------------------- /src/vl53l8cx_platform_config_default.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file vl53l8cx_platform_config_default.h 4 | * @author STMicroelectronics 5 | * @version V1.0.0 6 | * @date 11 November 2021 7 | * @brief Header file with the default platform settings. 8 | ****************************************************************************** 9 | * @attention 10 | * 11 | *

© COPYRIGHT(c) 2021 STMicroelectronics

12 | * 13 | * Redistribution and use in source and binary forms, with or without modification, 14 | * are permitted provided that the following conditions are met: 15 | * 1. Redistributions of source code must retain the above copyright notice, 16 | * this list of conditions and the following disclaimer. 17 | * 2. Redistributions in binary form must reproduce the above copyright notice, 18 | * this list of conditions and the following disclaimer in the documentation 19 | * and/or other materials provided with the distribution. 20 | * 3. Neither the name of STMicroelectronics nor the names of its contributors 21 | * may be used to endorse or promote products derived from this software 22 | * without specific prior written permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 30 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 31 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 32 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 33 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | * 35 | ****************************************************************************** 36 | */ 37 | 38 | #ifndef _VL53L8CX_PLATFORM_CONFIG_DEFAULT_H_ 39 | #define _VL53L8CX_PLATFORM_CONFIG_DEFAULT_H_ 40 | 41 | /* 42 | * @brief If you want to customize these defines you can add in the application 43 | * code the file platform_config_custom.h file where you can override some of 44 | * these defines. 45 | */ 46 | 47 | /* 48 | * @brief The macro below is used to define the number of target per zone sent 49 | * through I2C. This value can be changed by user, in order to tune I2C 50 | * transaction, and also the total memory size (a lower number of target per 51 | * zone means a lower RAM). The value must be between 1 and 4. 52 | */ 53 | 54 | #ifndef VL53L8CX_NB_TARGET_PER_ZONE 55 | #define VL53L8CX_NB_TARGET_PER_ZONE 1U 56 | #endif 57 | 58 | /* 59 | * @brief The macro below can be used to avoid data conversion into the driver. 60 | * By default there is a conversion between firmware and user data. Using this macro 61 | * allows to use the firmware format instead of user format. The firmware format allows 62 | * an increased precision. 63 | */ 64 | 65 | // #define VL53L8CX_USE_RAW_FORMAT 66 | 67 | /* 68 | * @brief All macro below are used to configure the sensor output. User can 69 | * define some macros if he wants to disable selected output, in order to reduce 70 | * I2C access. 71 | */ 72 | 73 | // #define VL53L8CX_DISABLE_AMBIENT_PER_SPAD 74 | // #define VL53L8CX_DISABLE_NB_SPADS_ENABLED 75 | // #define VL53L8CX_DISABLE_NB_TARGET_DETECTED 76 | // #define VL53L8CX_DISABLE_SIGNAL_PER_SPAD 77 | // #define VL53L8CX_DISABLE_RANGE_SIGMA_MM 78 | // #define VL53L8CX_DISABLE_DISTANCE_MM 79 | // #define VL53L8CX_DISABLE_REFLECTANCE_PERCENT 80 | // #define VL53L8CX_DISABLE_TARGET_STATUS 81 | // #define VL53L8CX_DISABLE_MOTION_INDICATOR 82 | 83 | #endif // _VL53L8CX_PLATFORM_CONFIG_DEFAULT_H_ 84 | -------------------------------------------------------------------------------- /src/vl53l8cx_plugin_detection_thresholds.c: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Copyright (c) 2021 STMicroelectronics. 4 | * All rights reserved. 5 | * 6 | * This software is licensed under terms that can be found in the LICENSE file 7 | * in the root directory of this software component. 8 | * If no LICENSE file comes with this software, it is provided AS-IS. 9 | * 10 | ****************************************************************************** 11 | */ 12 | 13 | #include "vl53l8cx_plugin_detection_thresholds.h" 14 | 15 | uint8_t vl53l8cx_get_detection_thresholds_enable( 16 | VL53L8CX_Configuration *p_dev, 17 | uint8_t *p_enabled) 18 | { 19 | uint8_t status = VL53L8CX_STATUS_OK; 20 | 21 | status |= vl53l8cx_dci_read_data(p_dev, (uint8_t *)p_dev->temp_buffer, 22 | VL53L8CX_DCI_DET_THRESH_GLOBAL_CONFIG, 8); 23 | *p_enabled = p_dev->temp_buffer[0x1]; 24 | 25 | return status; 26 | } 27 | 28 | uint8_t vl53l8cx_set_detection_thresholds_enable( 29 | VL53L8CX_Configuration *p_dev, 30 | uint8_t enabled) 31 | { 32 | uint8_t tmp, status = VL53L8CX_STATUS_OK; 33 | uint8_t grp_global_config[] = {0x01, 0x00, 0x01, 0x00}; 34 | 35 | if (enabled == (uint8_t)1) { 36 | grp_global_config[0x01] = 0x01; 37 | tmp = 0x04; 38 | } else { 39 | grp_global_config[0x01] = 0x00; 40 | tmp = 0x0C; 41 | } 42 | 43 | /* Set global interrupt config */ 44 | status |= vl53l8cx_dci_replace_data(p_dev, p_dev->temp_buffer, 45 | VL53L8CX_DCI_DET_THRESH_GLOBAL_CONFIG, 8, 46 | (uint8_t *)&grp_global_config, 4, 0x00); 47 | 48 | /* Update interrupt config */ 49 | status |= vl53l8cx_dci_replace_data(p_dev, p_dev->temp_buffer, 50 | VL53L8CX_DCI_DET_THRESH_CONFIG, 20, 51 | (uint8_t *)&tmp, 1, 0x11); 52 | 53 | return status; 54 | } 55 | 56 | uint8_t vl53l8cx_get_detection_thresholds( 57 | VL53L8CX_Configuration *p_dev, 58 | VL53L8CX_DetectionThresholds *p_thresholds) 59 | { 60 | uint8_t i, status = VL53L8CX_STATUS_OK; 61 | 62 | /* Get thresholds configuration */ 63 | status |= vl53l8cx_dci_read_data(p_dev, (uint8_t *)p_thresholds, 64 | VL53L8CX_DCI_DET_THRESH_START, 65 | (uint16_t)VL53L8CX_NB_THRESHOLDS 66 | * (uint16_t)sizeof(VL53L8CX_DetectionThresholds)); 67 | 68 | for (i = 0; i < (uint8_t)VL53L8CX_NB_THRESHOLDS; i++) { 69 | switch (p_thresholds[i].measurement) { 70 | case VL53L8CX_DISTANCE_MM: 71 | p_thresholds[i].param_low_thresh /= 4; 72 | p_thresholds[i].param_high_thresh /= 4; 73 | break; 74 | case VL53L8CX_SIGNAL_PER_SPAD_KCPS: 75 | p_thresholds[i].param_low_thresh /= 2048; 76 | p_thresholds[i].param_high_thresh /= 2048; 77 | break; 78 | case VL53L8CX_RANGE_SIGMA_MM: 79 | p_thresholds[i].param_low_thresh /= 128; 80 | p_thresholds[i].param_high_thresh /= 128; 81 | break; 82 | case VL53L8CX_AMBIENT_PER_SPAD_KCPS: 83 | p_thresholds[i].param_low_thresh /= 2048; 84 | p_thresholds[i].param_high_thresh /= 2048; 85 | break; 86 | case VL53L8CX_NB_SPADS_ENABLED: 87 | p_thresholds[i].param_low_thresh /= 256; 88 | p_thresholds[i].param_high_thresh /= 256; 89 | break; 90 | case VL53L8CX_MOTION_INDICATOR: 91 | p_thresholds[i].param_low_thresh /= 65535; 92 | p_thresholds[i].param_high_thresh /= 65535; 93 | break; 94 | default: 95 | break; 96 | } 97 | } 98 | 99 | return status; 100 | } 101 | 102 | uint8_t vl53l8cx_set_detection_thresholds( 103 | VL53L8CX_Configuration *p_dev, 104 | VL53L8CX_DetectionThresholds *p_thresholds) 105 | { 106 | uint8_t i, status = VL53L8CX_STATUS_OK; 107 | uint8_t grp_valid_target_cfg[] = {0x05, 0x05, 0x05, 0x05, 108 | 0x05, 0x05, 0x05, 0x05 109 | }; 110 | 111 | for (i = 0; i < (uint8_t) VL53L8CX_NB_THRESHOLDS; i++) { 112 | switch (p_thresholds->measurement) { 113 | case VL53L8CX_DISTANCE_MM: 114 | p_thresholds[i].param_low_thresh *= 4; 115 | p_thresholds[i].param_high_thresh *= 4; 116 | break; 117 | case VL53L8CX_SIGNAL_PER_SPAD_KCPS: 118 | p_thresholds[i].param_low_thresh *= 2048; 119 | p_thresholds[i].param_high_thresh *= 2048; 120 | break; 121 | case VL53L8CX_RANGE_SIGMA_MM: 122 | p_thresholds[i].param_low_thresh *= 128; 123 | p_thresholds[i].param_high_thresh *= 128; 124 | break; 125 | case VL53L8CX_AMBIENT_PER_SPAD_KCPS: 126 | p_thresholds[i].param_low_thresh *= 2048; 127 | p_thresholds[i].param_high_thresh *= 2048; 128 | break; 129 | case VL53L8CX_NB_SPADS_ENABLED: 130 | p_thresholds[i].param_low_thresh *= 256; 131 | p_thresholds[i].param_high_thresh *= 256; 132 | break; 133 | case VL53L8CX_MOTION_INDICATOR: 134 | p_thresholds[i].param_low_thresh *= 65535; 135 | p_thresholds[i].param_high_thresh *= 65535; 136 | break; 137 | default: 138 | break; 139 | } 140 | } 141 | 142 | /* Set valid target list */ 143 | status |= vl53l8cx_dci_write_data(p_dev, (uint8_t *)grp_valid_target_cfg, 144 | VL53L8CX_DCI_DET_THRESH_VALID_STATUS, 145 | (uint16_t)sizeof(grp_valid_target_cfg)); 146 | 147 | /* Set thresholds configuration */ 148 | status |= vl53l8cx_dci_write_data(p_dev, (uint8_t *)p_thresholds, 149 | VL53L8CX_DCI_DET_THRESH_START, 150 | (uint16_t)(VL53L8CX_NB_THRESHOLDS 151 | * sizeof(VL53L8CX_DetectionThresholds))); 152 | 153 | return status; 154 | } 155 | 156 | uint8_t vl53l8cx_get_detection_thresholds_auto_stop( 157 | VL53L8CX_Configuration *p_dev, 158 | uint8_t *p_auto_stop) 159 | { 160 | uint8_t status = VL53L8CX_STATUS_OK; 161 | 162 | status |= vl53l8cx_dci_read_data(p_dev, (uint8_t *)p_dev->temp_buffer, 163 | VL53L8CX_DCI_PIPE_CONTROL, 4); 164 | *p_auto_stop = p_dev->temp_buffer[0x3]; 165 | 166 | return status; 167 | } 168 | 169 | uint8_t vl53l8cx_set_detection_thresholds_auto_stop( 170 | VL53L8CX_Configuration *p_dev, 171 | uint8_t auto_stop) 172 | { 173 | uint8_t status = VL53L8CX_STATUS_OK; 174 | 175 | status |= vl53l8cx_dci_replace_data(p_dev, p_dev->temp_buffer, 176 | VL53L8CX_DCI_PIPE_CONTROL, 4, 177 | (uint8_t *)&auto_stop, 1, 0x03); 178 | p_dev->is_auto_stop_enabled = (uint8_t)auto_stop; 179 | 180 | return status; 181 | } 182 | -------------------------------------------------------------------------------- /src/vl53l8cx_plugin_detection_thresholds.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Copyright (c) 2021 STMicroelectronics. 4 | * All rights reserved. 5 | * 6 | * This software is licensed under terms that can be found in the LICENSE file 7 | * in the root directory of this software component. 8 | * If no LICENSE file comes with this software, it is provided AS-IS. 9 | * 10 | ****************************************************************************** 11 | */ 12 | 13 | #ifndef VL53L8CX_PLUGIN_DETECTION_THRESHOLDS_H_ 14 | #define VL53L8CX_PLUGIN_DETECTION_THRESHOLDS_H_ 15 | 16 | #ifdef __cplusplus 17 | extern "C" { 18 | #endif 19 | 20 | #include "vl53l8cx_api.h" 21 | 22 | /** 23 | * @brief Macro VL53L8CX_NB_THRESHOLDS indicates the number of checkers. This 24 | * value cannot be changed. 25 | */ 26 | 27 | #define VL53L8CX_NB_THRESHOLDS ((uint8_t)64U) 28 | 29 | /** 30 | * @brief Inner Macro for API. Not for user, only for development. 31 | */ 32 | 33 | #define VL53L8CX_DCI_DET_THRESH_CONFIG ((uint16_t)0x5488U) 34 | #define VL53L8CX_DCI_DET_THRESH_GLOBAL_CONFIG ((uint16_t)0xB6E0U) 35 | #define VL53L8CX_DCI_DET_THRESH_START ((uint16_t)0xB6E8U) 36 | #define VL53L8CX_DCI_DET_THRESH_VALID_STATUS ((uint16_t)0xB9F0U) 37 | 38 | /** 39 | * @brief Macro VL53L8CX_LAST_THRESHOLD is used to indicate the end of checkers 40 | * programming. 41 | */ 42 | 43 | #define VL53L8CX_LAST_THRESHOLD ((uint8_t)128U) 44 | 45 | /** 46 | * @brief The following macro are used to define the 'param_type' of a checker. 47 | * They indicate what is the measurement to catch. 48 | */ 49 | 50 | #define VL53L8CX_DISTANCE_MM ((uint8_t)1U) 51 | #define VL53L8CX_SIGNAL_PER_SPAD_KCPS ((uint8_t)2U) 52 | #define VL53L8CX_RANGE_SIGMA_MM ((uint8_t)4U) 53 | #define VL53L8CX_AMBIENT_PER_SPAD_KCPS ((uint8_t)8U) 54 | #define VL53L8CX_NB_TARGET_DETECTED ((uint8_t)9U) 55 | #define VL53L8CX_TARGET_STATUS ((uint8_t)12U) 56 | #define VL53L8CX_NB_SPADS_ENABLED ((uint8_t)13U) 57 | #define VL53L8CX_MOTION_INDICATOR ((uint8_t)19U) 58 | 59 | /** 60 | * @brief The following macro are used to define the 'type' of a checker. 61 | * They indicate the window of measurements, defined by low and a high 62 | * thresholds. 63 | */ 64 | 65 | #define VL53L8CX_IN_WINDOW ((uint8_t)0U) 66 | #define VL53L8CX_OUT_OF_WINDOW ((uint8_t)1U) 67 | #define VL53L8CX_LESS_THAN_EQUAL_MIN_CHECKER ((uint8_t)2U) 68 | #define VL53L8CX_GREATER_THAN_MAX_CHECKER ((uint8_t)3U) 69 | #define VL53L8CX_EQUAL_MIN_CHECKER ((uint8_t)4U) 70 | #define VL53L8CX_NOT_EQUAL_MIN_CHECKER ((uint8_t)5U) 71 | 72 | /** 73 | * @brief The following macro are used to define multiple checkers in the same 74 | * zone, using operators. Please note that the first checker MUST always be a OR 75 | * operation. 76 | */ 77 | 78 | #define VL53L8CX_OPERATION_NONE ((uint8_t)0U) 79 | #define VL53L8CX_OPERATION_OR ((uint8_t)0U) 80 | #define VL53L8CX_OPERATION_AND ((uint8_t)2U) 81 | 82 | /** 83 | * @brief Structure VL53L8CX_DetectionThresholds contains a single threshold. 84 | * This structure is never used alone, it must be used as an array of 64 85 | * thresholds (defined by macro VL53L8CX_NB_THRESHOLDS). 86 | */ 87 | 88 | typedef struct { 89 | 90 | /* Low threshold */ 91 | int32_t param_low_thresh; 92 | /* High threshold */ 93 | int32_t param_high_thresh; 94 | /* Measurement to catch (VL53L8CX_MEDIAN_RANGE_MM,...)*/ 95 | uint8_t measurement; 96 | /* Windows type (VL53L8CX_IN_WINDOW, VL53L8CX_OUT_WINDOW, ...) */ 97 | uint8_t type; 98 | /* Zone id. Please read VL53L5 user manual to find the zone id.Set macro 99 | * VL53L8CX_LAST_THRESHOLD to indicates the end of checkers */ 100 | uint8_t zone_num; 101 | /* Mathematics operation (AND/OR). The first threshold is always OR.*/ 102 | uint8_t mathematic_operation; 103 | } VL53L8CX_DetectionThresholds; 104 | 105 | /** 106 | * @brief This function allows indicating if the detection thresholds are 107 | * enabled. 108 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 109 | * @param (uint8_t) *p_enabled : Set to 1 if enabled, or 0 if disable. 110 | * @return (uint8_t) status : 0 if OK 111 | */ 112 | 113 | uint8_t vl53l8cx_get_detection_thresholds_enable( 114 | VL53L8CX_Configuration *p_dev, 115 | uint8_t *p_enabled); 116 | 117 | /** 118 | * @brief This function allows enable the detection thresholds. 119 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 120 | * @param (uint8_t) enabled : Set to 1 to enable, or 0 to disable thresholds. 121 | * @return (uint8_t) status : 0 if programming is OK 122 | */ 123 | 124 | uint8_t vl53l8cx_set_detection_thresholds_enable( 125 | VL53L8CX_Configuration *p_dev, 126 | uint8_t enabled); 127 | 128 | /** 129 | * @brief This function allows getting the detection thresholds. 130 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 131 | * @param (VL53L8CX_DetectionThresholds) *p_thresholds : Array of 64 thresholds. 132 | * @return (uint8_t) status : 0 if programming is OK 133 | */ 134 | 135 | uint8_t vl53l8cx_get_detection_thresholds( 136 | VL53L8CX_Configuration *p_dev, 137 | VL53L8CX_DetectionThresholds *p_thresholds); 138 | 139 | /** 140 | * @brief This function allows programming the detection thresholds. 141 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 142 | * @param (VL53L8CX_DetectionThresholds) *p_thresholds : Array of 64 thresholds. 143 | * @return (uint8_t) status : 0 if programming is OK 144 | */ 145 | 146 | uint8_t vl53l8cx_set_detection_thresholds( 147 | VL53L8CX_Configuration *p_dev, 148 | VL53L8CX_DetectionThresholds *p_thresholds); 149 | 150 | /** 151 | * @brief This function is used to enable or disable the auto-stop feature. 152 | * When ToF runs in autonomous mode with detection threshold, the sensor 153 | * only emits an interrupt (INT pin) when a threshold is reached. Interrupt 154 | * is raised when the measurement is completed. It is possible to abort the ranging 155 | * without waiting for end of measurement completed by enabling the auto-stop. The 156 | * sensor emits an interrupt and quickly aborts the measurements in progress. Please 157 | * note that vl53l8cx_stop_ranging() function needs to be used after interrupt raised 158 | * for a clean stop. 159 | * This function is used to get the auto_stop flag. 160 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 161 | * @param (uint8_t) *p_auto_stop : Pointer of auto-stop feature, 0 disabled 162 | * (default) or 1 enabled. 163 | * @return (uint8_t) status : 0 if programming is OK 164 | */ 165 | 166 | uint8_t vl53l8cx_get_detection_thresholds_auto_stop( 167 | VL53L8CX_Configuration *p_dev, 168 | uint8_t *p_auto_stop); 169 | 170 | /** 171 | * @brief This function is used to enable or disable the auto-stop feature. 172 | * When ToF runs in autonomous mode with detection threshold, the sensor 173 | * only emits an interrupt (INT pin) when a threshold is reached. Interrupt 174 | * is raised when the measurement is completed. It is possible to abort the ranging 175 | * without waiting for end of measurement completed by enabling the auto-stop. The 176 | * sensor emits an interrupt and quickly aborts the measurements in progress. Please 177 | * note that vl53l8cx_stop_ranging() function needs to be used after interrupt raised 178 | * for a clean stop. 179 | * This function is used to set the auto_stop flag. 180 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 181 | * @param (uint8_t) *p_auto_stop : Pointer of auto-stop feature, 0 disabled 182 | * (default) or 1 enabled. 183 | * @return (uint8_t) status : 0 if programming is OK 184 | */ 185 | 186 | uint8_t vl53l8cx_set_detection_thresholds_auto_stop( 187 | VL53L8CX_Configuration *p_dev, 188 | uint8_t auto_stop); 189 | 190 | 191 | #ifdef __cplusplus 192 | } 193 | #endif 194 | 195 | #endif /* VL53L8CX_PLUGIN_DETECTION_THRESHOLDS_H_ */ 196 | -------------------------------------------------------------------------------- /src/vl53l8cx_plugin_motion_indicator.c: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Copyright (c) 2021 STMicroelectronics. 4 | * All rights reserved. 5 | * 6 | * This software is licensed under terms that can be found in the LICENSE file 7 | * in the root directory of this software component. 8 | * If no LICENSE file comes with this software, it is provided AS-IS. 9 | * 10 | ****************************************************************************** 11 | */ 12 | 13 | #include 14 | #include "vl53l8cx_plugin_motion_indicator.h" 15 | 16 | uint8_t vl53l8cx_motion_indicator_init( 17 | VL53L8CX_Configuration *p_dev, 18 | VL53L8CX_Motion_Configuration *p_motion_config, 19 | uint8_t resolution) 20 | { 21 | uint8_t status = VL53L8CX_STATUS_OK; 22 | 23 | (void)memset(p_motion_config, 0, sizeof(VL53L8CX_Motion_Configuration)); 24 | 25 | p_motion_config->ref_bin_offset = 13633; 26 | p_motion_config->detection_threshold = 2883584; 27 | p_motion_config->extra_noise_sigma = 0; 28 | p_motion_config->null_den_clip_value = 0; 29 | p_motion_config->mem_update_mode = 6; 30 | p_motion_config->mem_update_choice = 2; 31 | p_motion_config->sum_span = 4; 32 | p_motion_config->feature_length = 9; 33 | p_motion_config->nb_of_aggregates = 16; 34 | p_motion_config->nb_of_temporal_accumulations = 16; 35 | p_motion_config->min_nb_for_global_detection = 1; 36 | p_motion_config->global_indicator_format_1 = 8; 37 | p_motion_config->global_indicator_format_2 = 0; 38 | p_motion_config->spare_1 = 0; 39 | p_motion_config->spare_2 = 0; 40 | p_motion_config->spare_3 = 0; 41 | 42 | status |= vl53l8cx_motion_indicator_set_resolution(p_dev, 43 | p_motion_config, resolution); 44 | 45 | return status; 46 | } 47 | 48 | uint8_t vl53l8cx_motion_indicator_set_distance_motion( 49 | VL53L8CX_Configuration *p_dev, 50 | VL53L8CX_Motion_Configuration *p_motion_config, 51 | uint16_t distance_min_mm, 52 | uint16_t distance_max_mm) 53 | { 54 | uint8_t status = VL53L8CX_STATUS_OK; 55 | float_t tmp; 56 | 57 | if (((distance_max_mm - distance_min_mm) > (uint16_t)1500) 58 | || (distance_min_mm < (uint16_t)400) 59 | || (distance_max_mm > (uint16_t)4000)) { 60 | status |= VL53L8CX_STATUS_INVALID_PARAM; 61 | } else { 62 | tmp = (float_t)((((float_t)distance_min_mm / (float_t)37.5348) 63 | - (float_t)4.0) * (float_t)2048.5); 64 | p_motion_config->ref_bin_offset = (int32_t)tmp; 65 | 66 | tmp = (float_t)((((((float_t)distance_max_mm - 67 | (float_t)distance_min_mm) / (float_t)10.0) + (float_t)30.02784) 68 | / ((float_t)15.01392)) + (float_t)0.5); 69 | p_motion_config->feature_length = (uint8_t)tmp; 70 | 71 | status |= vl53l8cx_dci_write_data(p_dev, 72 | (uint8_t *)(p_motion_config), 73 | VL53L8CX_DCI_MOTION_DETECTOR_CFG, 74 | (uint16_t)sizeof(*p_motion_config)); 75 | } 76 | 77 | return status; 78 | } 79 | 80 | uint8_t vl53l8cx_motion_indicator_set_resolution( 81 | VL53L8CX_Configuration *p_dev, 82 | VL53L8CX_Motion_Configuration *p_motion_config, 83 | uint8_t resolution) 84 | { 85 | uint8_t i, status = VL53L8CX_STATUS_OK; 86 | 87 | switch (resolution) { 88 | case VL53L8CX_RESOLUTION_4X4: 89 | for (i = 0; i < (uint8_t)VL53L8CX_RESOLUTION_4X4; i++) { 90 | p_motion_config->map_id[i] = (int8_t)i; 91 | } 92 | (void)memset(p_motion_config->map_id + 16, -1, 48); 93 | break; 94 | 95 | case VL53L8CX_RESOLUTION_8X8: 96 | for (i = 0; i < (uint8_t)VL53L8CX_RESOLUTION_8X8; i++) { 97 | p_motion_config->map_id[i] = (int8_t)((((int8_t) 98 | i % 8) / 2) + (4 * ((int8_t)i / 16))); 99 | } 100 | break; 101 | 102 | default: 103 | status |= VL53L8CX_STATUS_ERROR; 104 | break; 105 | } 106 | 107 | if (status == VL53L8CX_STATUS_OK) { 108 | status |= vl53l8cx_dci_write_data(p_dev, 109 | (uint8_t *)(p_motion_config), 110 | VL53L8CX_DCI_MOTION_DETECTOR_CFG, 111 | (uint16_t)sizeof(*p_motion_config)); 112 | } 113 | 114 | return status; 115 | } 116 | -------------------------------------------------------------------------------- /src/vl53l8cx_plugin_motion_indicator.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Copyright (c) 2021 STMicroelectronics. 4 | * All rights reserved. 5 | * 6 | * This software is licensed under terms that can be found in the LICENSE file 7 | * in the root directory of this software component. 8 | * If no LICENSE file comes with this software, it is provided AS-IS. 9 | * 10 | ****************************************************************************** 11 | */ 12 | 13 | #ifndef VL53L8CX_PLUGIN_MOTION_INDICATOR_H_ 14 | #define VL53L8CX_PLUGIN_MOTION_INDICATOR_H_ 15 | 16 | #ifdef __cplusplus 17 | extern "C" { 18 | #endif 19 | 20 | #include "vl53l8cx_api.h" 21 | 22 | /** 23 | * @brief Motion indicator internal configuration structure. 24 | */ 25 | 26 | typedef struct { 27 | int32_t ref_bin_offset; 28 | uint32_t detection_threshold; 29 | uint32_t extra_noise_sigma; 30 | uint32_t null_den_clip_value; 31 | uint8_t mem_update_mode; 32 | uint8_t mem_update_choice; 33 | uint8_t sum_span; 34 | uint8_t feature_length; 35 | uint8_t nb_of_aggregates; 36 | uint8_t nb_of_temporal_accumulations; 37 | uint8_t min_nb_for_global_detection; 38 | uint8_t global_indicator_format_1; 39 | uint8_t global_indicator_format_2; 40 | uint8_t spare_1; 41 | uint8_t spare_2; 42 | uint8_t spare_3; 43 | int8_t map_id[64]; 44 | uint8_t indicator_format_1[32]; 45 | uint8_t indicator_format_2[32]; 46 | } VL53L8CX_Motion_Configuration; 47 | 48 | /** 49 | * @brief This function is used to initialized the motion indicator. By default, 50 | * indicator is programmed to monitor movements between 400mm and 1500mm. 51 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 52 | * @param (VL53L8CX_Motion_Configuration) *p_motion_config : Structure 53 | * containing the initialized motion configuration. 54 | * @param (uint8_t) resolution : Wanted resolution, defined by macros 55 | * VL53L8CX_RESOLUTION_4X4 or VL53L8CX_RESOLUTION_8X8. 56 | * @return (uint8_t) status : 0 if OK, or 127 is the resolution is unknown. 57 | */ 58 | 59 | uint8_t vl53l8cx_motion_indicator_init( 60 | VL53L8CX_Configuration *p_dev, 61 | VL53L8CX_Motion_Configuration *p_motion_config, 62 | uint8_t resolution); 63 | 64 | /** 65 | * @brief This function can be used to change the working distance of motion 66 | * indicator. By default, indicator is programmed to monitor movements between 67 | * 400mm and 1500mm. 68 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 69 | * @param (VL53L8CX_Motion_Configuration) *p_motion_config : Structure 70 | * containing the initialized motion configuration. 71 | * @param (uint16_t) distance_min_mm : Minimum distance for indicator (min value 72 | * 400mm, max 4000mm). 73 | * @param (uint16_t) distance_max_mm : Maximum distance for indicator (min value 74 | * 400mm, max 4000mm). 75 | * VL53L8CX_RESOLUTION_4X4 or VL53L8CX_RESOLUTION_8X8. 76 | * @return (uint8_t) status : 0 if OK, or 127 if an argument is invalid. 77 | */ 78 | 79 | uint8_t vl53l8cx_motion_indicator_set_distance_motion( 80 | VL53L8CX_Configuration *p_dev, 81 | VL53L8CX_Motion_Configuration *p_motion_config, 82 | uint16_t distance_min_mm, 83 | uint16_t distance_max_mm); 84 | 85 | /** 86 | * @brief This function is used to update the internal motion indicator map. 87 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 88 | * @param (VL53L8CX_Motion_Configuration) *p_motion_config : Structure 89 | * containing the initialized motion configuration. 90 | * @param (uint8_t) resolution : Wanted SCI resolution, defined by macros 91 | * VL53L8CX_RESOLUTION_4X4 or VL53L8CX_RESOLUTION_8X8. 92 | * @return (uint8_t) status : 0 if OK, or 127 is the resolution is unknown. 93 | */ 94 | 95 | uint8_t vl53l8cx_motion_indicator_set_resolution( 96 | VL53L8CX_Configuration *p_dev, 97 | VL53L8CX_Motion_Configuration *p_motion_config, 98 | uint8_t resolution); 99 | 100 | #ifdef __cplusplus 101 | } 102 | #endif 103 | 104 | #endif /* VL53L8CX_PLUGIN_MOTION_INDICATOR_H_ */ 105 | -------------------------------------------------------------------------------- /src/vl53l8cx_plugin_xtalk.c: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Copyright (c) 2021 STMicroelectronics. 4 | * All rights reserved. 5 | * 6 | * This software is licensed under terms that can be found in the LICENSE file 7 | * in the root directory of this software component. 8 | * If no LICENSE file comes with this software, it is provided AS-IS. 9 | * 10 | ****************************************************************************** 11 | */ 12 | 13 | #include "vl53l8cx_plugin_xtalk.h" 14 | 15 | /* 16 | * Inner function, not available outside this file. This function is used to 17 | * wait for an answer from VL53L5 sensor. 18 | */ 19 | 20 | static uint8_t _vl53l8cx_poll_for_answer( 21 | VL53L8CX_Configuration *p_dev, 22 | uint16_t address, 23 | uint8_t expected_value) 24 | { 25 | uint8_t status = VL53L8CX_STATUS_OK; 26 | uint8_t timeout = 0; 27 | 28 | do { 29 | status |= VL53L8CX_RdMulti(&(p_dev->platform), 30 | address, p_dev->temp_buffer, 4); 31 | status |= VL53L8CX_WaitMs(&(p_dev->platform), 10); 32 | 33 | /* 2s timeout or FW error*/ 34 | if ((timeout >= (uint8_t)200) 35 | || (p_dev->temp_buffer[2] >= (uint8_t) 0x7f)) { 36 | status |= VL53L8CX_MCU_ERROR; 37 | break; 38 | } else { 39 | timeout++; 40 | } 41 | } while ((p_dev->temp_buffer[0x1]) != expected_value); 42 | 43 | return status; 44 | } 45 | 46 | /* 47 | * Inner function, not available outside this file. This function is used to 48 | * program the output using the macro defined into the 'vl53l8cx_platform.h' file. 49 | */ 50 | 51 | static uint8_t _vl53l8cx_program_output_config( 52 | VL53L8CX_Configuration *p_dev) 53 | { 54 | uint8_t resolution, status = VL53L8CX_STATUS_OK; 55 | uint32_t i; 56 | uint32_t header_config[2] = {0, 0}; 57 | union Block_header *bh_ptr; 58 | 59 | status |= vl53l8cx_get_resolution(p_dev, &resolution); 60 | p_dev->data_read_size = 0; 61 | 62 | /* Enable mandatory output (meta and common data) */ 63 | uint32_t output_bh_enable[] = { 64 | 0x0001FFFFU, 65 | 0x00000000U, 66 | 0x00000000U, 67 | 0xC0000000U 68 | }; 69 | 70 | /* Send addresses of possible output */ 71 | uint32_t output[] = { 72 | 0x0000000DU, 73 | 0x54000040U, 74 | 0x9FD800C0U, 75 | 0x9FE40140U, 76 | 0x9FF80040U, 77 | 0x9FFC0404U, 78 | 0xA0FC0100U, 79 | 0xA10C0100U, 80 | 0xA11C00C0U, 81 | 0xA1280902U, 82 | 0xA2480040U, 83 | 0xA24C0081U, 84 | 0xA2540081U, 85 | 0xA25C0081U, 86 | 0xA2640081U, 87 | 0xA26C0084U, 88 | 0xA28C0082U 89 | }; 90 | 91 | /* Update data size */ 92 | for (i = 0; i < (uint32_t)(sizeof(output) / sizeof(uint32_t)); i++) { 93 | if ((output[i] == (uint8_t)0) 94 | || ((output_bh_enable[i / (uint32_t)32] 95 | & ((uint32_t)1 << (i % (uint32_t)32))) == (uint32_t)0)) { 96 | continue; 97 | } 98 | 99 | bh_ptr = (union Block_header *) & (output[i]); 100 | if (((uint8_t)bh_ptr->type >= (uint8_t)0x1) 101 | && ((uint8_t)bh_ptr->type < (uint8_t)0x0d)) { 102 | if ((bh_ptr->idx >= (uint16_t)0x54d0) 103 | && (bh_ptr->idx < (uint16_t)(0x54d0 + 960))) { 104 | bh_ptr->size = resolution; 105 | } else { 106 | bh_ptr->size = (uint8_t)(resolution 107 | * (uint8_t)VL53L8CX_NB_TARGET_PER_ZONE); 108 | } 109 | 110 | 111 | p_dev->data_read_size += bh_ptr->type * bh_ptr->size; 112 | } else { 113 | p_dev->data_read_size += bh_ptr->size; 114 | } 115 | 116 | p_dev->data_read_size += (uint32_t)4; 117 | } 118 | p_dev->data_read_size += (uint32_t)24; 119 | 120 | status |= vl53l8cx_dci_write_data(p_dev, 121 | (uint8_t *) & (output), 122 | VL53L8CX_DCI_OUTPUT_LIST, (uint16_t)sizeof(output)); 123 | 124 | header_config[0] = p_dev->data_read_size; 125 | header_config[1] = i + (uint32_t)1; 126 | 127 | status |= vl53l8cx_dci_write_data(p_dev, (uint8_t *) & (header_config), 128 | VL53L8CX_DCI_OUTPUT_CONFIG, 129 | (uint16_t)sizeof(header_config)); 130 | status |= vl53l8cx_dci_write_data(p_dev, (uint8_t *) & (output_bh_enable), 131 | VL53L8CX_DCI_OUTPUT_ENABLES, 132 | (uint16_t)sizeof(output_bh_enable)); 133 | 134 | return status; 135 | } 136 | 137 | uint8_t vl53l8cx_calibrate_xtalk( 138 | VL53L8CX_Configuration *p_dev, 139 | uint16_t reflectance_percent, 140 | uint8_t nb_samples, 141 | uint16_t distance_mm) 142 | { 143 | uint16_t timeout = 0; 144 | uint8_t cmd[] = {0x00, 0x03, 0x00, 0x00}; 145 | uint8_t footer[] = {0x00, 0x00, 0x00, 0x0F, 0x00, 0x01, 0x03, 0x04}; 146 | uint8_t continue_loop = 1, status = VL53L8CX_STATUS_OK; 147 | 148 | uint8_t resolution, frequency, target_order, sharp_prct, ranging_mode; 149 | uint32_t integration_time_ms, xtalk_margin; 150 | 151 | uint16_t reflectance = reflectance_percent; 152 | uint8_t samples = nb_samples; 153 | uint16_t distance = distance_mm; 154 | uint8_t *default_xtalk_ptr; 155 | 156 | /* Get initial configuration */ 157 | status |= vl53l8cx_get_resolution(p_dev, &resolution); 158 | status |= vl53l8cx_get_ranging_frequency_hz(p_dev, &frequency); 159 | status |= vl53l8cx_get_integration_time_ms(p_dev, &integration_time_ms); 160 | status |= vl53l8cx_get_sharpener_percent(p_dev, &sharp_prct); 161 | status |= vl53l8cx_get_target_order(p_dev, &target_order); 162 | status |= vl53l8cx_get_xtalk_margin(p_dev, &xtalk_margin); 163 | status |= vl53l8cx_get_ranging_mode(p_dev, &ranging_mode); 164 | 165 | /* Check input arguments validity */ 166 | if (((reflectance < (uint16_t)1) || (reflectance > (uint16_t)99)) 167 | || ((distance < (uint16_t)600) || (distance > (uint16_t)3000)) 168 | || ((samples < (uint8_t)1) || (samples > (uint8_t)16))) { 169 | status |= VL53L8CX_STATUS_INVALID_PARAM; 170 | } else { 171 | status |= vl53l8cx_set_resolution(p_dev, 172 | VL53L8CX_RESOLUTION_8X8); 173 | 174 | /* Send Xtalk calibration buffer */ 175 | (void)memcpy(p_dev->temp_buffer, VL53L8CX_CALIBRATE_XTALK, 176 | sizeof(VL53L8CX_CALIBRATE_XTALK)); 177 | status |= VL53L8CX_WrMulti(&(p_dev->platform), 0x2c28, 178 | p_dev->temp_buffer, 179 | (uint16_t)sizeof(VL53L8CX_CALIBRATE_XTALK)); 180 | status |= _vl53l8cx_poll_for_answer(p_dev, 181 | VL53L8CX_UI_CMD_STATUS, 0x3); 182 | 183 | /* Format input argument */ 184 | reflectance = reflectance * (uint16_t)16; 185 | distance = distance * (uint16_t)4; 186 | 187 | /* Update required fields */ 188 | status |= vl53l8cx_dci_replace_data(p_dev, p_dev->temp_buffer, 189 | VL53L8CX_DCI_CAL_CFG, 8, 190 | (uint8_t *)&distance, 2, 0x00); 191 | 192 | status |= vl53l8cx_dci_replace_data(p_dev, p_dev->temp_buffer, 193 | VL53L8CX_DCI_CAL_CFG, 8, 194 | (uint8_t *)&reflectance, 2, 0x02); 195 | 196 | status |= vl53l8cx_dci_replace_data(p_dev, p_dev->temp_buffer, 197 | VL53L8CX_DCI_CAL_CFG, 8, 198 | (uint8_t *)&samples, 1, 0x04); 199 | 200 | /* Program output for Xtalk calibration */ 201 | status |= _vl53l8cx_program_output_config(p_dev); 202 | 203 | /* Start ranging session */ 204 | status |= VL53L8CX_WrMulti(&(p_dev->platform), 205 | VL53L8CX_UI_CMD_END - (uint16_t)(4 - 1), 206 | (uint8_t *)cmd, sizeof(cmd)); 207 | status |= _vl53l8cx_poll_for_answer(p_dev, 208 | VL53L8CX_UI_CMD_STATUS, 0x3); 209 | 210 | /* Wait for end of calibration */ 211 | do { 212 | status |= VL53L8CX_RdMulti(&(p_dev->platform), 213 | 0x0, p_dev->temp_buffer, 4); 214 | if (p_dev->temp_buffer[0] != VL53L8CX_STATUS_ERROR) { 215 | /* Coverglass too good for Xtalk calibration */ 216 | if ((p_dev->temp_buffer[2] >= (uint8_t)0x7f) && 217 | (((uint16_t)(p_dev->temp_buffer[3] & 218 | (uint16_t)0x80) >> 7) == (uint16_t)1)) { 219 | default_xtalk_ptr = p_dev->default_xtalk; 220 | (void)memcpy(p_dev->xtalk_data, 221 | default_xtalk_ptr, 222 | sizeof(p_dev->xtalk_data)); 223 | status |= VL53L8CX_STATUS_XTALK_FAILED; 224 | } 225 | continue_loop = (uint8_t)0; 226 | } else if (timeout >= (uint16_t)400) { 227 | status |= VL53L8CX_STATUS_ERROR; 228 | continue_loop = (uint8_t)0; 229 | } else { 230 | timeout++; 231 | status |= VL53L8CX_WaitMs(&(p_dev->platform), 50); 232 | } 233 | 234 | } while (continue_loop == (uint8_t)1); 235 | } 236 | 237 | /* Save Xtalk data into the Xtalk buffer */ 238 | (void)memcpy(p_dev->temp_buffer, VL53L8CX_GET_XTALK_CMD, 239 | sizeof(VL53L8CX_GET_XTALK_CMD)); 240 | status |= VL53L8CX_WrMulti(&(p_dev->platform), 0x2fb8, 241 | p_dev->temp_buffer, 242 | (uint16_t)sizeof(VL53L8CX_GET_XTALK_CMD)); 243 | status |= _vl53l8cx_poll_for_answer(p_dev, VL53L8CX_UI_CMD_STATUS, 0x03); 244 | status |= VL53L8CX_RdMulti(&(p_dev->platform), VL53L8CX_UI_CMD_START, 245 | p_dev->temp_buffer, 246 | VL53L8CX_XTALK_BUFFER_SIZE + (uint16_t)4); 247 | 248 | (void)memcpy(&(p_dev->xtalk_data[0]), &(p_dev->temp_buffer[8]), 249 | VL53L8CX_XTALK_BUFFER_SIZE - (uint16_t)8); 250 | (void)memcpy(&(p_dev->xtalk_data[VL53L8CX_XTALK_BUFFER_SIZE 251 | - (uint16_t)8]), footer, sizeof(footer)); 252 | 253 | /* Reset default buffer */ 254 | status |= VL53L8CX_WrMulti(&(p_dev->platform), 0x2c34, 255 | p_dev->default_configuration, 256 | VL53L8CX_CONFIGURATION_SIZE); 257 | status |= _vl53l8cx_poll_for_answer(p_dev, VL53L8CX_UI_CMD_STATUS, 0x03); 258 | 259 | /* Reset initial configuration */ 260 | status |= vl53l8cx_set_resolution(p_dev, resolution); 261 | status |= vl53l8cx_set_ranging_frequency_hz(p_dev, frequency); 262 | status |= vl53l8cx_set_integration_time_ms(p_dev, integration_time_ms); 263 | status |= vl53l8cx_set_sharpener_percent(p_dev, sharp_prct); 264 | status |= vl53l8cx_set_target_order(p_dev, target_order); 265 | status |= vl53l8cx_set_xtalk_margin(p_dev, xtalk_margin); 266 | status |= vl53l8cx_set_ranging_mode(p_dev, ranging_mode); 267 | 268 | return status; 269 | } 270 | 271 | uint8_t vl53l8cx_get_caldata_xtalk( 272 | VL53L8CX_Configuration *p_dev, 273 | uint8_t *p_xtalk_data) 274 | { 275 | uint8_t status = VL53L8CX_STATUS_OK, resolution; 276 | uint8_t footer[] = {0x00, 0x00, 0x00, 0x0F, 0x00, 0x01, 0x03, 0x04}; 277 | 278 | status |= vl53l8cx_get_resolution(p_dev, &resolution); 279 | status |= vl53l8cx_set_resolution(p_dev, VL53L8CX_RESOLUTION_8X8); 280 | 281 | (void)memcpy(p_dev->temp_buffer, VL53L8CX_GET_XTALK_CMD, 282 | sizeof(VL53L8CX_GET_XTALK_CMD)); 283 | status |= VL53L8CX_WrMulti(&(p_dev->platform), 0x2fb8, 284 | p_dev->temp_buffer, sizeof(VL53L8CX_GET_XTALK_CMD)); 285 | status |= _vl53l8cx_poll_for_answer(p_dev, VL53L8CX_UI_CMD_STATUS, 0x03); 286 | status |= VL53L8CX_RdMulti(&(p_dev->platform), VL53L8CX_UI_CMD_START, 287 | p_dev->temp_buffer, 288 | VL53L8CX_XTALK_BUFFER_SIZE + (uint16_t)4); 289 | 290 | (void)memcpy(&(p_xtalk_data[0]), &(p_dev->temp_buffer[8]), 291 | VL53L8CX_XTALK_BUFFER_SIZE - (uint16_t)8); 292 | (void)memcpy(&(p_xtalk_data[VL53L8CX_XTALK_BUFFER_SIZE - (uint16_t)8]), 293 | footer, sizeof(footer)); 294 | 295 | status |= vl53l8cx_set_resolution(p_dev, resolution); 296 | 297 | return status; 298 | } 299 | 300 | uint8_t vl53l8cx_set_caldata_xtalk( 301 | VL53L8CX_Configuration *p_dev, 302 | uint8_t *p_xtalk_data) 303 | { 304 | uint8_t resolution, status = VL53L8CX_STATUS_OK; 305 | 306 | status |= vl53l8cx_get_resolution(p_dev, &resolution); 307 | (void)memcpy(p_dev->xtalk_data, p_xtalk_data, VL53L8CX_XTALK_BUFFER_SIZE); 308 | status |= vl53l8cx_set_resolution(p_dev, resolution); 309 | 310 | return status; 311 | } 312 | 313 | uint8_t vl53l8cx_get_xtalk_margin( 314 | VL53L8CX_Configuration *p_dev, 315 | uint32_t *p_xtalk_margin) 316 | { 317 | uint8_t status = VL53L8CX_STATUS_OK; 318 | 319 | status |= vl53l8cx_dci_read_data(p_dev, (uint8_t *)p_dev->temp_buffer, 320 | VL53L8CX_DCI_XTALK_CFG, 16); 321 | 322 | (void)memcpy(p_xtalk_margin, p_dev->temp_buffer, 4); 323 | *p_xtalk_margin = *p_xtalk_margin / (uint32_t)2048; 324 | 325 | return status; 326 | } 327 | 328 | uint8_t vl53l8cx_set_xtalk_margin( 329 | VL53L8CX_Configuration *p_dev, 330 | uint32_t xtalk_margin) 331 | { 332 | uint8_t status = VL53L8CX_STATUS_OK; 333 | uint32_t margin_kcps = xtalk_margin; 334 | 335 | if (margin_kcps > (uint32_t)10000) { 336 | status |= VL53L8CX_STATUS_INVALID_PARAM; 337 | } else { 338 | margin_kcps = margin_kcps * (uint32_t)2048; 339 | status |= vl53l8cx_dci_replace_data(p_dev, p_dev->temp_buffer, 340 | VL53L8CX_DCI_XTALK_CFG, 16, 341 | (uint8_t *)&margin_kcps, 4, 0x00); 342 | } 343 | 344 | return status; 345 | } 346 | -------------------------------------------------------------------------------- /src/vl53l8cx_plugin_xtalk.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Copyright (c) 2021 STMicroelectronics. 4 | * All rights reserved. 5 | * 6 | * This software is licensed under terms that can be found in the LICENSE file 7 | * in the root directory of this software component. 8 | * If no LICENSE file comes with this software, it is provided AS-IS. 9 | * 10 | ****************************************************************************** 11 | */ 12 | 13 | #ifndef VL53L8CX_PLUGIN_XTALK_H_ 14 | #define VL53L8CX_PLUGIN_XTALK_H_ 15 | 16 | #ifdef __cplusplus 17 | extern "C" { 18 | #endif 19 | 20 | 21 | #include "vl53l8cx_api.h" 22 | 23 | /** 24 | * @brief Inner internal number of targets. 25 | */ 26 | 27 | #if VL53L8CX_NB_TARGET_PER_ZONE == 1 28 | #define VL53L8CX_FW_NBTAR_XTALK 2 29 | #else 30 | #define VL53L8CX_FW_NBTAR_XTALK VL53L8CX_NB_TARGET_PER_ZONE 31 | #endif 32 | 33 | /** 34 | * @brief Inner Macro for plugin. Not for user, only for development. 35 | */ 36 | 37 | #define VL53L8CX_DCI_CAL_CFG ((uint16_t)0x5470U) 38 | #define VL53L8CX_DCI_XTALK_CFG ((uint16_t)0xAD94U) 39 | 40 | 41 | /** 42 | * @brief This function starts the VL53L8CX sensor in order to calibrate Xtalk. 43 | * This calibration is recommended is user wants to use a coverglass. 44 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 45 | * @param (uint16_t) reflectance_percent : Target reflectance in percent. This 46 | * value is include between 1 and 99%. For a better efficiency, ST recommends a 47 | * 3% target reflectance. 48 | * @param (uint8_t) nb_samples : Nb of samples used for calibration. A higher 49 | * number of samples means a higher accuracy, but it increases the calibration 50 | * time. Minimum is 1 and maximum is 16. 51 | * @param (uint16_t) distance_mm : Target distance in mm. The minimum allowed 52 | * distance is 600mm, and maximum is 3000mm. The target must stay in Full FOV, 53 | * so short distance are easier for calibration. 54 | * @return (uint8_t) status : 0 if calibration OK, 127 if an argument has an 55 | * incorrect value, or 255 is something failed. 56 | */ 57 | 58 | uint8_t vl53l8cx_calibrate_xtalk( 59 | VL53L8CX_Configuration *p_dev, 60 | uint16_t reflectance_percent, 61 | uint8_t nb_samples, 62 | uint16_t distance_mm); 63 | 64 | /** 65 | * @brief This function gets the Xtalk buffer. The buffer is available after 66 | * using the function vl53l8cx_calibrate_xtalk(). 67 | * @param (VL53L8CX_Configuration) *p_dev : VL53L5 configuration structure. 68 | * @param (uint8_t) *p_xtalk_data : Buffer with a size defined by 69 | * macro VL53L8CX_XTALK_SIZE. 70 | * @return (uint8_t) status : 0 if buffer reading OK 71 | */ 72 | 73 | uint8_t vl53l8cx_get_caldata_xtalk( 74 | VL53L8CX_Configuration *p_dev, 75 | uint8_t *p_xtalk_data); 76 | 77 | /** 78 | * @brief This function sets the Xtalk buffer. This function can be used to 79 | * override default Xtalk buffer. 80 | * @param (VL53L8CX_Configuration) *p_dev : VL53L5 configuration structure. 81 | * @param (uint8_t) *p_xtalk_data : Buffer with a size defined by 82 | * macro VL53L8CX_XTALK_SIZE. 83 | * @return (uint8_t) status : 0 if buffer OK 84 | */ 85 | 86 | uint8_t vl53l8cx_set_caldata_xtalk( 87 | VL53L8CX_Configuration *p_dev, 88 | uint8_t *p_xtalk_data); 89 | 90 | /** 91 | * @brief This function gets the Xtalk margin. This margin is used to increase 92 | * the Xtalk threshold. It can also be used to avoid false positives after the 93 | * Xtalk calibration. The default value is 50 kcps/spads. 94 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 95 | * @param (uint32_t) *p_xtalk_margin : Xtalk margin in kcps/spads. 96 | * @return (uint8_t) status : 0 if reading OK 97 | */ 98 | 99 | uint8_t vl53l8cx_get_xtalk_margin( 100 | VL53L8CX_Configuration *p_dev, 101 | uint32_t *p_xtalk_margin); 102 | 103 | /** 104 | * @brief This function sets the Xtalk margin. This margin is used to increase 105 | * the Xtalk threshold. It can also be used to avoid false positives after the 106 | * Xtalk calibration. The default value is 50 kcps/spads. 107 | * @param (VL53L8CX_Configuration) *p_dev : VL53L8CX configuration structure. 108 | * @param (uint32_t) xtalk_margin : New Xtalk margin in kcps/spads. Min value is 109 | * 0 kcps/spads, and max is 10.000 kcps/spads 110 | * @return (uint8_t) status : 0 if set margin is OK, or 127 is the margin is 111 | * invalid. 112 | */ 113 | 114 | uint8_t vl53l8cx_set_xtalk_margin( 115 | VL53L8CX_Configuration *p_dev, 116 | uint32_t xtalk_margin); 117 | 118 | /** 119 | * @brief Command used to get Xtalk calibration data 120 | */ 121 | 122 | static const uint8_t VL53L8CX_GET_XTALK_CMD[] = { 123 | 0x54, 0x00, 0x00, 0x40, 124 | 0x9F, 0xD8, 0x00, 0xC0, 125 | 0x9F, 0xE4, 0x01, 0x40, 126 | 0x9F, 0xF8, 0x00, 0x40, 127 | 0x9F, 0xFC, 0x04, 0x04, 128 | 0xA0, 0xFC, 0x01, 0x00, 129 | 0xA1, 0x0C, 0x01, 0x00, 130 | 0xA1, 0x1C, 0x00, 0xC0, 131 | 0xA1, 0x28, 0x09, 0x02, 132 | 0xA2, 0x48, 0x00, 0x40, 133 | 0xA2, 0x4C, 0x00, 0x81, 134 | 0xA2, 0x54, 0x00, 0x81, 135 | 0xA2, 0x5C, 0x00, 0x81, 136 | 0xA2, 0x64, 0x00, 0x81, 137 | 0xA2, 0x6C, 0x00, 0x84, 138 | 0xA2, 0x8C, 0x00, 0x82, 139 | 0x00, 0x00, 0x00, 0x0F, 140 | 0x07, 0x02, 0x00, 0x44 141 | }; 142 | 143 | /** 144 | * @brief Command used to get run Xtalk calibration 145 | */ 146 | 147 | static const uint8_t VL53L8CX_CALIBRATE_XTALK[] = { 148 | 0x54, 0x50, 0x00, 0x80, 149 | 0x00, 0x04, 0x08, 0x08, 150 | 0x00, 0x00, 0x04, 0x04, 151 | 0xAD, 0x30, 0x00, 0x80, 152 | 0x03, 0x01, 0x06, 0x03, 153 | 0x00, 0x00, 0x01, 0x00, 154 | 0xAD, 0x38, 0x01, 0x00, 155 | 0x01, 0xE0, 0x01, 0x40, 156 | 0x00, 0x10, 0x00, 0x10, 157 | 0x01, 0x00, 0x01, 0x00, 158 | 0x00, 0x00, 0x00, 0x01, 159 | 0x54, 0x58, 0x00, 0x40, 160 | 0x04, 0x1A, 0x02, 0x00, 161 | 0x54, 0x5C, 0x01, 0x40, 162 | 0x00, 0x01, 0x00, 0x51, 163 | 0x00, 0x00, 0x0F, 0xA0, 164 | 0x0F, 0xA0, 0x03, 0xE8, 165 | 0x02, 0x80, 0x1F, 0x40, 166 | 0x00, 0x00, 0x05, 0x00, 167 | 0x54, 0x70, 0x00, 0x80, 168 | 0x03, 0x20, 0x03, 0x20, 169 | 0x00, 0x00, 0x00, 0x08, 170 | 0x54, 0x78, 0x01, 0x00, 171 | 0x01, 0x1B, 0x00, 0x21, 172 | 0x00, 0x33, 0x00, 0x00, 173 | 0x02, 0x00, 0x00, 0x01, 174 | 0x04, 0x01, 0x08, VL53L8CX_FW_NBTAR_XTALK, 175 | 0x54, 0x88, 0x01, 0x40, 176 | 0x00, 0x00, 0x00, 0x00, 177 | 0x00, 0x00, 0x00, 0x00, 178 | 0x00, 0x00, 0x00, 0x00, 179 | 0x00, 0x00, 0x00, 0x00, 180 | 0x00, 0x00, 0x08, 0x00, 181 | 0xAD, 0x48, 0x01, 0x00, 182 | 0x01, 0xF4, 0x00, 0x00, 183 | 0x03, 0x06, 0x00, 0x10, 184 | 0x08, 0x08, 0x08, 0x08, 185 | 0x00, 0x00, 0x00, 0x08, 186 | 0xAD, 0x60, 0x01, 0x00, 187 | 0x00, 0x00, 0x00, 0x80, 188 | 0x00, 0x00, 0x00, 0x00, 189 | 0x20, 0x1F, 0x01, 0xF4, 190 | 0x00, 0x00, 0x1D, 0x0A, 191 | 0xAD, 0x70, 0x00, 0x80, 192 | 0x08, 0x00, 0x1F, 0x40, 193 | 0x00, 0x00, 0x00, 0x01, 194 | 0xAD, 0x78, 0x00, 0x80, 195 | 0x00, 0xA0, 0x03, 0x20, 196 | 0x00, 0x01, 0x01, 0x90, 197 | 0xAD, 0x80, 0x00, 0x40, 198 | 0x00, 0x00, 0x28, 0x00, 199 | 0xAD, 0x84, 0x00, 0x80, 200 | 0x00, 0x00, 0x32, 0x00, 201 | 0x03, 0x20, 0x00, 0x00, 202 | 0xAD, 0x8C, 0x00, 0x80, 203 | 0x02, 0x58, 0xFF, 0x38, 204 | 0x00, 0x00, 0x00, 0x0C, 205 | 0xAD, 0x94, 0x01, 0x00, 206 | 0x00, 0x01, 0x90, 0x00, 207 | 0xFF, 0xFF, 0xFC, 0x00, 208 | 0x00, 0x00, 0x04, 0x00, 209 | 0x00, 0x00, 0x01, 0x00, 210 | 0xAD, 0xA4, 0x00, 0xC0, 211 | 0x04, 0x80, 0x06, 0x1A, 212 | 0x00, 0x80, 0x05, 0x80, 213 | 0x00, 0x00, 0x01, 0x06, 214 | 0xAD, 0xB0, 0x00, 0xC0, 215 | 0x04, 0x80, 0x06, 0x1A, 216 | 0x19, 0x00, 0x05, 0x80, 217 | 0x00, 0x00, 0x01, 0x90, 218 | 0xAD, 0xBC, 0x04, 0x40, 219 | 0x00, 0x00, 0x00, 0x00, 220 | 0x00, 0x00, 0x00, 0x00, 221 | 0x00, 0x12, 0x00, 0x25, 222 | 0x00, 0x00, 0x00, 0x06, 223 | 0x00, 0x00, 0x00, 0x05, 224 | 0x00, 0x00, 0x00, 0x05, 225 | 0x00, 0x00, 0x00, 0x06, 226 | 0x00, 0x00, 0x00, 0x04, 227 | 0x00, 0x00, 0x00, 0x0F, 228 | 0x00, 0x00, 0x00, 0x5A, 229 | 0x00, 0x00, 0x00, 0x00, 230 | 0x00, 0x00, 0x00, 0x09, 231 | 0x0B, 0x0C, 0x0B, 0x0B, 232 | 0x03, 0x03, 0x11, 0x05, 233 | 0x01, 0x01, 0x01, 0x01, 234 | 0x00, 0x00, 0x00, 0x00, 235 | 0x00, 0x0D, 0x00, 0x00, 236 | 0xAE, 0x00, 0x01, 0x04, 237 | 0x00, 0x00, 0x00, 0x04, 238 | 0x00, 0x00, 0x00, 0x08, 239 | 0x00, 0x00, 0x00, 0x0A, 240 | 0x00, 0x00, 0x00, 0x0C, 241 | 0x00, 0x00, 0x00, 0x0D, 242 | 0x00, 0x00, 0x00, 0x0E, 243 | 0x00, 0x00, 0x00, 0x08, 244 | 0x00, 0x00, 0x00, 0x08, 245 | 0x00, 0x00, 0x00, 0x10, 246 | 0x00, 0x00, 0x00, 0x10, 247 | 0x00, 0x00, 0x00, 0x20, 248 | 0x00, 0x00, 0x00, 0x20, 249 | 0x00, 0x00, 0x00, 0x06, 250 | 0x00, 0x00, 0x05, 0x0A, 251 | 0x02, 0x00, 0x0C, 0x08, 252 | 0x00, 0x00, 0x00, 0x00, 253 | 0xAE, 0x40, 0x00, 0x40, 254 | 0x00, 0x00, 0x00, 0xFF, 255 | 0xAE, 0x44, 0x00, 0x40, 256 | 0x00, 0x10, 0x04, 0x01, 257 | 0xAE, 0x48, 0x00, 0x40, 258 | 0x00, 0x00, 0x10, 0x00, 259 | 0xAE, 0x4C, 0x00, 0x40, 260 | 0x00, 0x00, 0x00, 0x01, 261 | 0xAE, 0x50, 0x01, 0x40, 262 | 0x00, 0x00, 0x00, 0x14, 263 | 0x04, 0x00, 0x28, 0x00, 264 | 0x03, 0x20, 0x6C, 0x00, 265 | 0x00, 0x00, 0x00, 0x00, 266 | 0x00, 0x00, 0x00, 0x00, 267 | 0xAE, 0x64, 0x00, 0x40, 268 | 0x00, 0x00, 0x00, 0x01, 269 | 0xAE, 0xD8, 0x01, 0x00, 270 | 0x00, 0xC8, 0x05, 0xDC, 271 | 0x00, 0x00, 0x0C, 0xCD, 272 | 0x01, 0x04, 0x00, 0x00, 273 | 0x00, 0x01, 0x26, 0x01, 274 | 0xB5, 0x50, 0x02, 0x82, 275 | 0xA3, 0xE8, 0xA3, 0xB8, 276 | 0xA4, 0x38, 0xA4, 0x28, 277 | 0xA6, 0x48, 0xA4, 0x48, 278 | 0xA7, 0x88, 0xA7, 0x48, 279 | 0xAC, 0x10, 0xA7, 0x90, 280 | 0x99, 0xBC, 0x99, 0xB4, 281 | 0x9A, 0xFC, 0x9A, 0xBC, 282 | 0x00, 0x00, 0x00, 0x00, 283 | 0x00, 0x00, 0x00, 0x00, 284 | 0x00, 0x00, 0x00, 0x00, 285 | 0x00, 0x00, 0x00, 0x00, 286 | 0x00, 0x00, 0x00, 0x00, 287 | 0x00, 0x00, 0x00, 0x00, 288 | 0x00, 0x00, 0x00, 0x00, 289 | 0x00, 0x00, 0x00, 0x00, 290 | 0x00, 0x00, 0x00, 0x00, 291 | 0x00, 0x00, 0x00, 0x00, 292 | 0x00, 0x00, 0x00, 0x00, 293 | 0x00, 0x00, 0x00, 0x00, 294 | 0x00, 0x00, 0x00, 0x00, 295 | 0xB5, 0xA0, 0x02, 0x82, 296 | 0x00, 0x88, 0x03, 0x00, 297 | 0x00, 0x82, 0x00, 0x82, 298 | 0x04, 0x04, 0x04, 0x08, 299 | 0x00, 0x80, 0x04, 0x01, 300 | 0x09, 0x02, 0x09, 0x08, 301 | 0x04, 0x04, 0x00, 0x80, 302 | 0x04, 0x01, 0x04, 0x01, 303 | 0x00, 0x00, 0x00, 0x00, 304 | 0x00, 0x00, 0x00, 0x00, 305 | 0x00, 0x00, 0x00, 0x00, 306 | 0x00, 0x00, 0x00, 0x00, 307 | 0x00, 0x00, 0x00, 0x00, 308 | 0x00, 0x00, 0x00, 0x00, 309 | 0x00, 0x00, 0x00, 0x00, 310 | 0x00, 0x00, 0x00, 0x00, 311 | 0x00, 0x00, 0x00, 0x00, 312 | 0x00, 0x00, 0x00, 0x00, 313 | 0x00, 0x00, 0x00, 0x00, 314 | 0x00, 0x00, 0x00, 0x00, 315 | 0x00, 0x00, 0x00, 0x00, 316 | 0xB5, 0xF0, 0x00, 0x40, 317 | 0x00, 0x04, 0x00, 0x00, 318 | 0xB3, 0x9C, 0x01, 0x00, 319 | 0x40, 0x00, 0x05, 0x1E, 320 | 0x02, 0x1B, 0x08, 0x7C, 321 | 0x80, 0x00, 0x12, 0x01, 322 | 0x00, 0x01, 0x08, 0x00, 323 | 0xB6, 0xC0, 0x00, 0xC0, 324 | 0x00, 0x00, 0x60, 0x00, 325 | 0x00, 0x00, 0x20, 0x00, 326 | 0x00, 0x00, 0x00, 0x00, 327 | 0xAE, 0xA8, 0x00, 0x40, 328 | 0x00, 0x00, 0x04, 0x05, 329 | 0xAE, 0xAC, 0x00, 0x80, 330 | 0x01, 0x00, 0x01, 0x00, 331 | 0x00, 0x02, 0x00, 0x00, 332 | 0xAE, 0xB4, 0x00, 0x40, 333 | 0x00, 0x00, 0x00, 0x00, 334 | 0xAE, 0xB8, 0x00, 0x81, 335 | 0x00, 0x00, 0x00, 0x00, 336 | 0x00, 0x00, 0x00, 0x00, 337 | 0xAE, 0xC0, 0x00, 0x81, 338 | 0x00, 0x00, 0x00, 0x00, 339 | 0x00, 0x00, 0x00, 0x00, 340 | 0xAE, 0xC8, 0x00, 0x81, 341 | 0x08, 0x01, 0x01, 0x08, 342 | 0x00, 0x00, 0x00, 0x08, 343 | 0xAE, 0xD0, 0x00, 0x81, 344 | 0x01, 0x08, 0x08, 0x08, 345 | 0x00, 0x00, 0x00, 0x01, 346 | 0xB5, 0xF4, 0x00, 0x80, 347 | 0x00, 0x00, 0x00, 0x00, 348 | 0x00, 0x00, 0x00, 0x00, 349 | 0xB5, 0xFC, 0x00, 0x80, 350 | 0x00, 0x00, 0x00, 0x00, 351 | 0x00, 0x00, 0x00, 0x00, 352 | 0xB6, 0x04, 0x00, 0x40, 353 | 0x00, 0x00, 0x00, 0x00, 354 | 0xB6, 0x08, 0x00, 0x44, 355 | 0x00, 0x00, 0x00, 0x00, 356 | 0x00, 0x00, 0x00, 0x00, 357 | 0x00, 0x00, 0x00, 0x00, 358 | 0x00, 0x00, 0x00, 0x00, 359 | 0xB6, 0x18, 0x00, 0x44, 360 | 0x00, 0x00, 0x00, 0x00, 361 | 0x00, 0x00, 0x00, 0x00, 362 | 0x00, 0x00, 0x00, 0x00, 363 | 0x00, 0x00, 0x00, 0x00, 364 | 0xB6, 0x28, 0x00, 0x44, 365 | 0x00, 0x00, 0x00, 0x00, 366 | 0x00, 0x00, 0x00, 0x00, 367 | 0x00, 0x00, 0x00, 0x00, 368 | 0x00, 0x00, 0x00, 0x00, 369 | 0xB6, 0x38, 0x00, 0x44, 370 | 0x00, 0x00, 0x00, 0x00, 371 | 0x00, 0x00, 0x00, 0x00, 372 | 0x00, 0x00, 0x00, 0x00, 373 | 0x00, 0x00, 0x00, 0x00, 374 | 0xB6, 0x48, 0x01, 0x00, 375 | 0x00, 0x00, 0x00, 0x00, 376 | 0x00, 0x00, 0x00, 0x00, 377 | 0x00, 0x00, 0x00, 0x00, 378 | 0x00, 0x00, 0x00, 0x00, 379 | 0xB6, 0x58, 0x01, 0x00, 380 | 0x00, 0x00, 0x00, 0x00, 381 | 0x00, 0x00, 0x00, 0x00, 382 | 0x00, 0x00, 0x00, 0x00, 383 | 0x00, 0x00, 0x00, 0x00, 384 | 0xB6, 0x68, 0x01, 0x00, 385 | 0x00, 0x00, 0x00, 0x00, 386 | 0x00, 0x00, 0x00, 0x00, 387 | 0x00, 0x00, 0x00, 0x00, 388 | 0x00, 0x00, 0x00, 0x00, 389 | 0x54, 0x70, 0x00, 0x80, 390 | 0x00, 0x00, 0x00, 0x00, 391 | 0x00, 0x00, 0x00, 0x02, 392 | 0x00, 0x00, 0x00, 0x0F, 393 | 0x00, 0x01, 0x03, 0xD4 394 | }; 395 | 396 | #ifdef __cplusplus 397 | } 398 | #endif 399 | 400 | #endif /* VL53L8CX_PLUGIN_XTALK_H_ */ 401 | --------------------------------------------------------------------------------