├── .github ├── ISSUE_TEMPLATE │ ├── bug-report-or-feature-request.md │ └── config.yml └── workflows │ └── ci.yaml ├── .gitignore ├── .gitlab-ci.yml ├── LICENSE.txt ├── README.md ├── VL53L1X.cpp ├── VL53L1X.h ├── examples ├── Continuous │ └── Continuous.ino ├── ContinuousMultipleSensors │ └── ContinuousMultipleSensors.ino └── ContinuousWithDetails │ └── ContinuousWithDetails.ino ├── keywords.txt └── library.properties /.github/ISSUE_TEMPLATE/bug-report-or-feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report or feature request 3 | about: Did you find a specific bug in the code for this project? Do you want to request 4 | a new feature? Please open an issue! 5 | title: '' 6 | labels: '' 7 | assignees: '' 8 | 9 | --- 10 | 11 | 12 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Pololu Forum 4 | url: https://forum.pololu.com/ 5 | about: Do you need help getting started? Can't get this code to work at all? Having problems with electronics? Please post on our forum! 6 | -------------------------------------------------------------------------------- /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | name: "CI" 2 | on: 3 | pull_request: 4 | push: 5 | jobs: 6 | ci: 7 | runs-on: ubuntu-20.04 8 | steps: 9 | - name: Checkout this repository 10 | uses: actions/checkout@v2.3.4 11 | - name: Cache for arduino-ci 12 | uses: actions/cache@v2.1.3 13 | with: 14 | path: | 15 | ~/.arduino15 16 | key: ${{ runner.os }}-arduino 17 | - name: Install nix 18 | uses: cachix/install-nix-action@v12 19 | - run: nix-shell -I nixpkgs=channel:nixpkgs-unstable -p arduino-ci --run "arduino-ci" 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /docs/ 2 | /out/ 3 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | image: $CI_REGISTRY_IMAGE/nixos/nix:2.3.6 2 | 3 | stages: 4 | - ci 5 | 6 | ci: 7 | stage: ci 8 | tags: 9 | - nix 10 | script: 11 | - nix-shell -I nixpkgs=channel:nixpkgs-unstable -p arduino-ci --run "arduino-ci" 12 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Most of the functionality of this library is based on the VL53L1X API provided 2 | provided by ST (STSW-IMG007), and some of the explanatory comments are quoted 3 | or paraphrased from the API source code, API user manual (UM2356), and VL53L1X 4 | datasheet. Therefore, the license terms for the API source code (BSD 3-clause 5 | "New" or "Revised" License) also apply to this derivative work, as specified 6 | below. 7 | 8 | For more information, see 9 | 10 | https://www.pololu.com/ 11 | https://forum.pololu.com/ 12 | 13 | -------------------------------------------------------------------------------- 14 | 15 | Copyright (c) 2017, STMicroelectronics 16 | Copyright (c) 2018-2022, Pololu Corporation 17 | All Rights Reserved 18 | 19 | Redistribution and use in source and binary forms, with or without 20 | modification, are permitted provided that the following conditions are met: 21 | 22 | 1. Redistributions of source code must retain the above copyright notice, this 23 | list of conditions and the following disclaimer. 24 | 25 | 2. Redistributions in binary form must reproduce the above copyright notice, 26 | this list of conditions and the following disclaimer in the documentation 27 | and/or other materials provided with the distribution. 28 | 29 | 3. Neither the name of the copyright holder nor the names of its contributors 30 | may be used to endorse or promote products derived from this software 31 | without specific prior written permission. 32 | 33 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 34 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 35 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 36 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 37 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 38 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 39 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 40 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 41 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 42 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VL53L1X library for Arduino 2 | [www.pololu.com](https://www.pololu.com/) 3 | 4 | ## Summary 5 | 6 | This is a library for the Arduino IDE that helps interface with ST's [VL53L1X time-of-flight distance sensor](https://www.pololu.com/product/3415). The library makes it simple to configure the sensor and read range data from it via I²C. 7 | 8 | ## Supported platforms 9 | 10 | This library is designed to work with the Arduino IDE versions 1.6.x or later; we have not tested it with earlier versions. This library should support any Arduino-compatible board, including the [Pololu A-Star controllers](https://www.pololu.com/category/149/a-star-programmable-controllers). 11 | 12 | ## Getting started 13 | 14 | ### Hardware 15 | 16 | A [VL53L1X carrier](https://www.pololu.com/product/3415) can be purchased from Pololu's website. Before continuing, careful reading of the [product page](https://www.pololu.com/product/3415) as well as the VL53L1X datasheet is recommended. 17 | 18 | Make the following connections between the Arduino and the VL53L1X board: 19 | 20 | #### 5V Arduino boards 21 | 22 | (including Arduino Uno, Leonardo, Mega; Pololu A-Star 32U4) 23 | 24 | Arduino VL53L1X board 25 | ------- ------------- 26 | 5V - VIN 27 | GND - GND 28 | SDA - SDA 29 | SCL - SCL 30 | 31 | #### 3.3V Arduino boards 32 | 33 | (including Arduino Due) 34 | 35 | Arduino VL53L1X board 36 | ------- ------------- 37 | 3V3 - VIN 38 | GND - GND 39 | SDA - SDA 40 | SCL - SCL 41 | 42 | ### Software 43 | 44 | If you are using version 1.6.2 or later of the [Arduino software (IDE)](http://www.arduino.cc/en/Main/Software), you can use the Library Manager to install this library: 45 | 46 | 1. In the Arduino IDE, open the "Sketch" menu, select "Include Library", then "Manage Libraries...". 47 | 2. Search for "VL53L1X". 48 | 3. Click the VL53L1X entry in the list. 49 | 4. Click "Install". 50 | 51 | If this does not work, you can manually install the library: 52 | 53 | 1. Download the [latest release archive from GitHub](https://github.com/pololu/vl53l1x-arduino/releases) and decompress it. 54 | 2. Rename the folder "vl53l1x-arduino-master" to "VL53L1X". 55 | 3. Move the "VL53L1X" folder into the "libraries" directory inside your Arduino sketchbook directory. You can view your sketchbook location by opening the "File" menu and selecting "Preferences" in the Arduino IDE. If there is not already a "libraries" folder in that location, you should make the folder yourself. 56 | 4. After installing the library, restart the Arduino IDE. 57 | 58 | ## Examples 59 | 60 | Several example sketches are available that show how to use the library. You can access them from the Arduino IDE by opening the "File" menu, selecting "Examples", and then selecting "VL53L1X". If you cannot find these examples, the library was probably installed incorrectly and you should retry the installation instructions above. 61 | 62 | ## ST's VL53L1X API and this library 63 | 64 | Most of the functionality of this library is based on the [VL53L1X API](http://www.st.com/content/st_com/en/products/embedded-software/proximity-sensors-software/stsw-img007.html) provided by ST (STSW-IMG007), and some of the explanatory comments in the code are quoted or paraphrased from the API source code, API user manual (UM2356), and the VL53L1X datasheet. For more explanation about the library code and how it was derived from the API, see the comments in VL53L1X.cpp. 65 | 66 | This library is intended to provide a quicker and easier way to get started using the VL53L1X with an Arduino-compatible controller, in contrast to using ST's API on the Arduino. The library has a more streamlined interface, as well as smaller storage and memory footprints. However, it does not currently implement some of the more advanced functionality available in the API (for example, calibrating the sensor to work well under a cover glass or selecting a smaller region of interest (ROI)), and it has less robust error checking. For advanced applications, especially when storage and memory are less of an issue, consider using the VL53L1X API directly. We have an [implementation of ST's VL53L1X API for Arduino](https://github.com/pololu/vl53l1x-st-api-arduino) available. 67 | 68 | ## Library reference 69 | 70 | * `RangingData ranging_data`
71 | This struct contains information about the last ranging measurement. Its members are: 72 | * `uint16_t range_mm`
73 | Range reading from the last measurement, in millimeters. (This reading can also be obtained as the return value of `read()`.) 74 | * `RangeStatus range_status`
75 | Status of the last measurement; see the definition of the `RangeStatus` enumeration type in VL53L1X.h (or the API user manual and source code) for descriptions of the possible statuses. A status of `VL53L1X::RangeValid` means there were no problems with the measurement. 76 | * `float peak_signal_count_rate_MCPS`
77 | Peak signal count rate of the last measurement, in units of mega counts per second. 78 | * `float ambient_count_rate_MCPS`
79 | Ambient count rate of the last measurement, in units of mega counts per second. 80 | 81 | * `uint8_t last_status`
82 | The status of the last I²C write transmission. See the [`Wire.endTransmission()` documentation](http://arduino.cc/en/Reference/WireEndTransmission) for return values. 83 | 84 | * `VL53L1X()`
85 | Constructor. 86 | 87 | * `void setBus(TwoWire * bus)`
88 | Configures this object to use the specified I²C bus. `bus` should be a pointer to a `TwoWire` object; the default bus is `Wire`, which is typically the first or only I²C bus on an Arduino. If your Arduino has more than one I²C bus and you have the VL53L0X connected to the second bus, which is typically called `Wire1`, you can call `sensor.setBus(&Wire1);`. 89 | 90 | * `TwoWire * getBus()`
91 | Returns a pointer to the I²C bus this object is using. 92 | 93 | * `void setAddress(uint8_t new_addr)`
94 | Changes the I²C slave device address of the VL53L1X to the given value (7-bit). 95 | 96 | * `uint8_t getAddress()`
97 | Returns the current I²C address. 98 | 99 | * `bool init(bool io_2v8 = true)`
100 | Iniitializes and configures the sensor. If the optional argument `io_2v8` is true (the default if not specified), the sensor is configured for 2V8 mode (2.8 V I/O); if false, the sensor is left in 1V8 mode. The return value is a boolean indicating whether the initialization completed successfully. 101 | 102 | * `void writeReg(uint16_t reg, uint8_t value)`
103 | Writes an 8-bit sensor register with the given value. 104 | 105 | Register address constants are defined by the `regAddr` enumeration type in VL53L1X.h.
106 | Example use: `sensor.writeReg(VL53L1X::SOFT_RESET, 0x00);` 107 | 108 | * `void writeReg16Bit(uint16_t reg, uint16_t value)`
109 | Writes a 16-bit sensor register with the given value. 110 | 111 | * `void writeReg32Bit(uint16_t reg, uint32_t value)`
112 | Writes a 32-bit sensor register with the given value. 113 | 114 | * `uint8_t readReg(uint16_t reg)`
115 | Reads an 8-bit sensor register and returns the value read. 116 | 117 | * `uint16_t readReg16Bit(uint16_t reg)`
118 | Reads a 16-bit sensor register and returns the value read. 119 | 120 | * `uint32_t readReg32Bit(uint16_t reg)`
121 | Reads a 32-bit sensor register and returns the value read. 122 | 123 | * `bool setDistanceMode(DistanceMode mode)`
124 | Sets the distance mode of the sensor (`VL53L1X::Short`, `VL53L1X::Medium`, or `VL53L1X::Long`). Shorter distance modes are less affected by ambient light but have lower maximum ranges. See the datasheet for more information. The return value is a boolean indicating whether the requested mode was valid. 125 | 126 | * `DistanceMode getDistanceMode()`
127 | Returns the previously set distance mode. 128 | 129 | * `bool setMeasurementTimingBudget(uint32_t budget_us)`
130 | Sets the measurement timing budget to the given value in microseconds. This is the time allowed for one range measurement; a longer timing budget allows for more accurate measurements. The minimum budget is 20 ms (20000 us) in short distance mode and 33 ms for medium and long distance modes. See the VL53L1X datasheet for more information on range and timing limits. The return value is a boolean indicating whether the requested budget was valid. 131 | 132 | * `uint32_t getMeasurementTimingBudget()`
133 | Returns the current measurement timing budget in microseconds. 134 | 135 | * `void setROISize(uint8_t width, uint8_t height)`
136 | Changes the size of the sensor's region of interest (ROI), allowing a smaller field of view (FoV) to be configured at the cost of losing some sensitivity. The default and maximum ROI is 16x16, which covers the VL53L1X's full array of sensing elements (single-photon avalanche diodes, or SPADs). The minimum ROI is 4x4. See the datasheet and ST user manual [UM2555](https://www.st.com/resource/en/user_manual/dm00600212-vl53l1x-ultra-lite-driver-multiple-zone-implementation-stmicroelectronics.pdf) for more information. 137 | 138 | * `void getROISize(uint8_t * width, uint8_t * height)`
139 | Retrieves the size of the sensor's currently configured ROI. This function takes pointers to two `uint8_t`s and copies the width and height values to those locations. 140 | 141 | * `void setROICenter(uint8_t spadNum)`
142 | Sets the center of the sensor's ROI, allowing the sensor's FoV to be shifted off-center when a smaller FoV is configured. `spadNum` is the number of the selected center SPAD; information on selecting a SPAD number are in vl53l1x.cpp and [UM2555](https://www.st.com/resource/en/user_manual/dm00600212-vl53l1x-ultra-lite-driver-multiple-zone-implementation-stmicroelectronics.pdf). The default center SPAD is 199, which centers the sensor's FoV. 143 | 144 | * `uint8_t getROICenter()`
145 | Returns the number of the currently configured center SPAD, which determines the center of the sensor's ROI. 146 | 147 | * `void startContinuous(uint32_t period_ms)`
148 | Starts continuous ranging measurements. The specified inter-measurement period in milliseconds determines how often the sensor takes a measurement; if it is shorter than the timing budget, the sensor will start a new measurement as soon as the previous one finishes. 149 | 150 | * `void stopContinuous()`
151 | Stops continuous mode. 152 | 153 | * `uint16_t read(bool blocking = true)`
154 | After continuous ranging measurements have been started, calling this function returns a range reading in millimeters and updates the `ranging_data` struct with details about the last measurement. If the optional argument `blocking` is true (the default if not specified), this function will wait until data from a new measurement is available before returning. 155 | 156 | If you do not want this function to block, you can use the `dataReady()` function to check if new data is available before calling `read(false)`. Calling `read(false)` before new data is available results in undefined behavior. 157 | 158 | * `uint16_t readRangeContinuousMillimeters(bool blocking = true)`
159 | Alias of `read()` for convenience. 160 | 161 | * `uint16_t readSingle(bool blocking = true)`
162 | Starts a single-shot ranging measurement. If the optional argument `blocking` is true (the default if not specified), this function will wait until data from the measurement is available before returning and updating `ranging_data`. Otherwise, this function returns 0 immediately. 163 | 164 | To perform a single non-blocking read, you can call `readSingle(false)` to start the measurement, use `dataReady()` to wait until data is available, and finally call `read(false)` to get the data. 165 | 166 | * `uint16_t readRangeSingleMillimeters(bool blocking = true)`
167 | Alias of `readSingle()` for convenience. 168 | 169 | * `bool dataReady()`
170 | Returns a boolean indicating whether data from a new measurement is available from the sensor. 171 | 172 | * `static const char * rangeStatusToString(RangeStatus status)`
173 | Converts a `RangeStatus` into a readable string describing that status. 174 | 175 | Note that on an AVR, the strings in this function are stored in RAM (dynamic memory), which makes working with them easier but uses up 200+ bytes of RAM (many AVR-based Arduinos only have about 2000 bytes of RAM). You can avoid this memory usage if you do not call this function in your sketch. 176 | 177 | * `void setTimeout(uint16_t timeout)`
178 | Sets a timeout period in milliseconds after which read operations will abort if the sensor is not ready. A value of 0 disables the timeout. 179 | 180 | * `uint16_t getTimeout()`
181 | Returns the current timeout period setting. 182 | 183 | * `bool timeoutOccurred()`
184 | Indicates whether a read timeout has occurred since the last call to `timeoutOccurred()`. 185 | 186 | ## Version history 187 | 188 | * 1.3.1 (2022-02-18): Explicitly cast `Wire.write()` arguments to `uint8_t` (thanks giulcioffi). Added multiple sensors example. 189 | * 1.3.0 (2021-04-16): Added functions to configure and retrieve a custom region of interest (ROI) for the VL53L1X. 190 | * 1.2.1 (2020-11-23): Fixed compile error on platforms where `TwoWire` isn't a class. 191 | * 1.2.0 (2020-11-13): Added support for alternative I²C buses (thanks mampfes). 192 | * 1.1.0 (2020-09-21): 193 | * Added support for single-shot range measurements. 194 | * Changed timeout behavior on blocking reads to not clear `ranging_data`. 195 | * Fixed an incorrect error status returned by `getRangingData()`. (thanks rejnok93) 196 | * 1.0.1 (2018-09-19): Fixed Arduino 101 hanging in init(). 197 | * 1.0.0 (2018-05-31): Original release. 198 | -------------------------------------------------------------------------------- /VL53L1X.cpp: -------------------------------------------------------------------------------- 1 | // Most of the functionality of this library is based on the VL53L1X API 2 | // provided by ST (STSW-IMG007), and some of the explanatory comments are quoted 3 | // or paraphrased from the API source code, API user manual (UM2356), and 4 | // VL53L1X datasheet. 5 | 6 | #include "VL53L1X.h" 7 | 8 | // Constructors //////////////////////////////////////////////////////////////// 9 | 10 | VL53L1X::VL53L1X() 11 | #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_TWOWIRE) 12 | : bus(&Wire) 13 | #else 14 | : bus(nullptr) 15 | #endif 16 | , address(AddressDefault) 17 | , io_timeout(0) // no timeout 18 | , did_timeout(false) 19 | , calibrated(false) 20 | , saved_vhv_init(0) 21 | , saved_vhv_timeout(0) 22 | , distance_mode(Unknown) 23 | { 24 | } 25 | 26 | // Public Methods ////////////////////////////////////////////////////////////// 27 | 28 | void VL53L1X::setAddress(uint8_t new_addr) 29 | { 30 | writeReg(I2C_SLAVE__DEVICE_ADDRESS, new_addr & 0x7F); 31 | address = new_addr; 32 | } 33 | 34 | // Initialize sensor using settings taken mostly from VL53L1_DataInit() and 35 | // VL53L1_StaticInit(). 36 | // If io_2v8 (optional) is true or not given, the sensor is configured for 2V8 37 | // mode. 38 | bool VL53L1X::init(bool io_2v8) 39 | { 40 | // check model ID and module type registers (values specified in datasheet) 41 | if (readReg16Bit(IDENTIFICATION__MODEL_ID) != 0xEACC) { return false; } 42 | 43 | // VL53L1_software_reset() begin 44 | 45 | writeReg(SOFT_RESET, 0x00); 46 | delayMicroseconds(100); 47 | writeReg(SOFT_RESET, 0x01); 48 | 49 | // give it some time to boot; otherwise the sensor NACKs during the readReg() 50 | // call below and the Arduino 101 doesn't seem to handle that well 51 | delay(1); 52 | 53 | // VL53L1_poll_for_boot_completion() begin 54 | 55 | startTimeout(); 56 | 57 | // check last_status in case we still get a NACK to try to deal with it correctly 58 | while ((readReg(FIRMWARE__SYSTEM_STATUS) & 0x01) == 0 || last_status != 0) 59 | { 60 | if (checkTimeoutExpired()) 61 | { 62 | did_timeout = true; 63 | return false; 64 | } 65 | } 66 | // VL53L1_poll_for_boot_completion() end 67 | 68 | // VL53L1_software_reset() end 69 | 70 | // VL53L1_DataInit() begin 71 | 72 | // sensor uses 1V8 mode for I/O by default; switch to 2V8 mode if necessary 73 | if (io_2v8) 74 | { 75 | writeReg(PAD_I2C_HV__EXTSUP_CONFIG, 76 | readReg(PAD_I2C_HV__EXTSUP_CONFIG) | 0x01); 77 | } 78 | 79 | // store oscillator info for later use 80 | fast_osc_frequency = readReg16Bit(OSC_MEASURED__FAST_OSC__FREQUENCY); 81 | osc_calibrate_val = readReg16Bit(RESULT__OSC_CALIBRATE_VAL); 82 | 83 | // VL53L1_DataInit() end 84 | 85 | // VL53L1_StaticInit() begin 86 | 87 | // Note that the API does not actually apply the configuration settings below 88 | // when VL53L1_StaticInit() is called: it keeps a copy of the sensor's 89 | // register contents in memory and doesn't actually write them until a 90 | // measurement is started. Writing the configuration here means we don't have 91 | // to keep it all in memory and avoids a lot of redundant writes later. 92 | 93 | // the API sets the preset mode to LOWPOWER_AUTONOMOUS here: 94 | // VL53L1_set_preset_mode() begin 95 | 96 | // VL53L1_preset_mode_standard_ranging() begin 97 | 98 | // values labeled "tuning parm default" are from vl53l1_tuning_parm_defaults.h 99 | // (API uses these in VL53L1_init_tuning_parm_storage_struct()) 100 | 101 | // static config 102 | // API resets PAD_I2C_HV__EXTSUP_CONFIG here, but maybe we don't want to do 103 | // that? (seems like it would disable 2V8 mode) 104 | writeReg16Bit(DSS_CONFIG__TARGET_TOTAL_RATE_MCPS, TargetRate); // should already be this value after reset 105 | writeReg(GPIO__TIO_HV_STATUS, 0x02); 106 | writeReg(SIGMA_ESTIMATOR__EFFECTIVE_PULSE_WIDTH_NS, 8); // tuning parm default 107 | writeReg(SIGMA_ESTIMATOR__EFFECTIVE_AMBIENT_WIDTH_NS, 16); // tuning parm default 108 | writeReg(ALGO__CROSSTALK_COMPENSATION_VALID_HEIGHT_MM, 0x01); 109 | writeReg(ALGO__RANGE_IGNORE_VALID_HEIGHT_MM, 0xFF); 110 | writeReg(ALGO__RANGE_MIN_CLIP, 0); // tuning parm default 111 | writeReg(ALGO__CONSISTENCY_CHECK__TOLERANCE, 2); // tuning parm default 112 | 113 | // general config 114 | writeReg16Bit(SYSTEM__THRESH_RATE_HIGH, 0x0000); 115 | writeReg16Bit(SYSTEM__THRESH_RATE_LOW, 0x0000); 116 | writeReg(DSS_CONFIG__APERTURE_ATTENUATION, 0x38); 117 | 118 | // timing config 119 | // most of these settings will be determined later by distance and timing 120 | // budget configuration 121 | writeReg16Bit(RANGE_CONFIG__SIGMA_THRESH, 360); // tuning parm default 122 | writeReg16Bit(RANGE_CONFIG__MIN_COUNT_RATE_RTN_LIMIT_MCPS, 192); // tuning parm default 123 | 124 | // dynamic config 125 | 126 | writeReg(SYSTEM__GROUPED_PARAMETER_HOLD_0, 0x01); 127 | writeReg(SYSTEM__GROUPED_PARAMETER_HOLD_1, 0x01); 128 | writeReg(SD_CONFIG__QUANTIFIER, 2); // tuning parm default 129 | 130 | // VL53L1_preset_mode_standard_ranging() end 131 | 132 | // from VL53L1_preset_mode_timed_ranging_* 133 | // GPH is 0 after reset, but writing GPH0 and GPH1 above seem to set GPH to 1, 134 | // and things don't seem to work if we don't set GPH back to 0 (which the API 135 | // does here). 136 | writeReg(SYSTEM__GROUPED_PARAMETER_HOLD, 0x00); 137 | writeReg(SYSTEM__SEED_CONFIG, 1); // tuning parm default 138 | 139 | // from VL53L1_config_low_power_auto_mode 140 | writeReg(SYSTEM__SEQUENCE_CONFIG, 0x8B); // VHV, PHASECAL, DSS1, RANGE 141 | writeReg16Bit(DSS_CONFIG__MANUAL_EFFECTIVE_SPADS_SELECT, 200 << 8); 142 | writeReg(DSS_CONFIG__ROI_MODE_CONTROL, 2); // REQUESTED_EFFFECTIVE_SPADS 143 | 144 | // VL53L1_set_preset_mode() end 145 | 146 | // default to long range, 50 ms timing budget 147 | // note that this is different than what the API defaults to 148 | setDistanceMode(Long); 149 | setMeasurementTimingBudget(50000); 150 | 151 | // VL53L1_StaticInit() end 152 | 153 | // the API triggers this change in VL53L1_init_and_start_range() once a 154 | // measurement is started; assumes MM1 and MM2 are disabled 155 | writeReg16Bit(ALGO__PART_TO_PART_RANGE_OFFSET_MM, 156 | readReg16Bit(MM_CONFIG__OUTER_OFFSET_MM) * 4); 157 | 158 | return true; 159 | } 160 | 161 | // Write an 8-bit register 162 | void VL53L1X::writeReg(uint16_t reg, uint8_t value) 163 | { 164 | bus->beginTransmission(address); 165 | bus->write((uint8_t)(reg >> 8)); // reg high byte 166 | bus->write((uint8_t)(reg)); // reg low byte 167 | bus->write(value); 168 | last_status = bus->endTransmission(); 169 | } 170 | 171 | // Write a 16-bit register 172 | void VL53L1X::writeReg16Bit(uint16_t reg, uint16_t value) 173 | { 174 | bus->beginTransmission(address); 175 | bus->write((uint8_t)(reg >> 8)); // reg high byte 176 | bus->write((uint8_t)(reg)); // reg low byte 177 | bus->write((uint8_t)(value >> 8)); // value high byte 178 | bus->write((uint8_t)(value)); // value low byte 179 | last_status = bus->endTransmission(); 180 | } 181 | 182 | // Write a 32-bit register 183 | void VL53L1X::writeReg32Bit(uint16_t reg, uint32_t value) 184 | { 185 | bus->beginTransmission(address); 186 | bus->write((uint8_t)(reg >> 8)); // reg high byte 187 | bus->write((uint8_t)(reg)); // reg low byte 188 | bus->write((uint8_t)(value >> 24)); // value highest byte 189 | bus->write((uint8_t)(value >> 16)); 190 | bus->write((uint8_t)(value >> 8)); 191 | bus->write((uint8_t)(value)); // value lowest byte 192 | last_status = bus->endTransmission(); 193 | } 194 | 195 | // Read an 8-bit register 196 | uint8_t VL53L1X::readReg(regAddr reg) 197 | { 198 | uint8_t value; 199 | 200 | bus->beginTransmission(address); 201 | bus->write((uint8_t)(reg >> 8)); // reg high byte 202 | bus->write((uint8_t)(reg)); // reg low byte 203 | last_status = bus->endTransmission(); 204 | 205 | bus->requestFrom(address, (uint8_t)1); 206 | value = bus->read(); 207 | 208 | return value; 209 | } 210 | 211 | // Read a 16-bit register 212 | uint16_t VL53L1X::readReg16Bit(uint16_t reg) 213 | { 214 | uint16_t value; 215 | 216 | bus->beginTransmission(address); 217 | bus->write((uint8_t)(reg >> 8)); // reg high byte 218 | bus->write((uint8_t)(reg)); // reg low byte 219 | last_status = bus->endTransmission(); 220 | 221 | bus->requestFrom(address, (uint8_t)2); 222 | value = (uint16_t)bus->read() << 8; // value high byte 223 | value |= bus->read(); // value low byte 224 | 225 | return value; 226 | } 227 | 228 | // Read a 32-bit register 229 | uint32_t VL53L1X::readReg32Bit(uint16_t reg) 230 | { 231 | uint32_t value; 232 | 233 | bus->beginTransmission(address); 234 | bus->write((uint8_t)(reg >> 8)); // reg high byte 235 | bus->write((uint8_t)(reg)); // reg low byte 236 | last_status = bus->endTransmission(); 237 | 238 | bus->requestFrom(address, (uint8_t)4); 239 | value = (uint32_t)bus->read() << 24; // value highest byte 240 | value |= (uint32_t)bus->read() << 16; 241 | value |= (uint16_t)bus->read() << 8; 242 | value |= bus->read(); // value lowest byte 243 | 244 | return value; 245 | } 246 | 247 | // set distance mode to Short, Medium, or Long 248 | // based on VL53L1_SetDistanceMode() 249 | bool VL53L1X::setDistanceMode(DistanceMode mode) 250 | { 251 | // save existing timing budget 252 | uint32_t budget_us = getMeasurementTimingBudget(); 253 | 254 | switch (mode) 255 | { 256 | case Short: 257 | // from VL53L1_preset_mode_standard_ranging_short_range() 258 | 259 | // timing config 260 | writeReg(RANGE_CONFIG__VCSEL_PERIOD_A, 0x07); 261 | writeReg(RANGE_CONFIG__VCSEL_PERIOD_B, 0x05); 262 | writeReg(RANGE_CONFIG__VALID_PHASE_HIGH, 0x38); 263 | 264 | // dynamic config 265 | writeReg(SD_CONFIG__WOI_SD0, 0x07); 266 | writeReg(SD_CONFIG__WOI_SD1, 0x05); 267 | writeReg(SD_CONFIG__INITIAL_PHASE_SD0, 6); // tuning parm default 268 | writeReg(SD_CONFIG__INITIAL_PHASE_SD1, 6); // tuning parm default 269 | 270 | break; 271 | 272 | case Medium: 273 | // from VL53L1_preset_mode_standard_ranging() 274 | 275 | // timing config 276 | writeReg(RANGE_CONFIG__VCSEL_PERIOD_A, 0x0B); 277 | writeReg(RANGE_CONFIG__VCSEL_PERIOD_B, 0x09); 278 | writeReg(RANGE_CONFIG__VALID_PHASE_HIGH, 0x78); 279 | 280 | // dynamic config 281 | writeReg(SD_CONFIG__WOI_SD0, 0x0B); 282 | writeReg(SD_CONFIG__WOI_SD1, 0x09); 283 | writeReg(SD_CONFIG__INITIAL_PHASE_SD0, 10); // tuning parm default 284 | writeReg(SD_CONFIG__INITIAL_PHASE_SD1, 10); // tuning parm default 285 | 286 | break; 287 | 288 | case Long: // long 289 | // from VL53L1_preset_mode_standard_ranging_long_range() 290 | 291 | // timing config 292 | writeReg(RANGE_CONFIG__VCSEL_PERIOD_A, 0x0F); 293 | writeReg(RANGE_CONFIG__VCSEL_PERIOD_B, 0x0D); 294 | writeReg(RANGE_CONFIG__VALID_PHASE_HIGH, 0xB8); 295 | 296 | // dynamic config 297 | writeReg(SD_CONFIG__WOI_SD0, 0x0F); 298 | writeReg(SD_CONFIG__WOI_SD1, 0x0D); 299 | writeReg(SD_CONFIG__INITIAL_PHASE_SD0, 14); // tuning parm default 300 | writeReg(SD_CONFIG__INITIAL_PHASE_SD1, 14); // tuning parm default 301 | 302 | break; 303 | 304 | default: 305 | // unrecognized mode - do nothing 306 | return false; 307 | } 308 | 309 | // reapply timing budget 310 | setMeasurementTimingBudget(budget_us); 311 | 312 | // save mode so it can be returned by getDistanceMode() 313 | distance_mode = mode; 314 | 315 | return true; 316 | } 317 | 318 | // Set the measurement timing budget in microseconds, which is the time allowed 319 | // for one measurement. A longer timing budget allows for more accurate 320 | // measurements. 321 | // based on VL53L1_SetMeasurementTimingBudgetMicroSeconds() 322 | bool VL53L1X::setMeasurementTimingBudget(uint32_t budget_us) 323 | { 324 | // assumes PresetMode is LOWPOWER_AUTONOMOUS 325 | 326 | if (budget_us <= TimingGuard) { return false; } 327 | 328 | uint32_t range_config_timeout_us = budget_us -= TimingGuard; 329 | if (range_config_timeout_us > 1100000) { return false; } // FDA_MAX_TIMING_BUDGET_US * 2 330 | 331 | range_config_timeout_us /= 2; 332 | 333 | // VL53L1_calc_timeout_register_values() begin 334 | 335 | uint32_t macro_period_us; 336 | 337 | // "Update Macro Period for Range A VCSEL Period" 338 | macro_period_us = calcMacroPeriod(readReg(RANGE_CONFIG__VCSEL_PERIOD_A)); 339 | 340 | // "Update Phase timeout - uses Timing A" 341 | // Timeout of 1000 is tuning parm default (TIMED_PHASECAL_CONFIG_TIMEOUT_US_DEFAULT) 342 | // via VL53L1_get_preset_mode_timing_cfg(). 343 | uint32_t phasecal_timeout_mclks = timeoutMicrosecondsToMclks(1000, macro_period_us); 344 | if (phasecal_timeout_mclks > 0xFF) { phasecal_timeout_mclks = 0xFF; } 345 | writeReg(PHASECAL_CONFIG__TIMEOUT_MACROP, phasecal_timeout_mclks); 346 | 347 | // "Update MM Timing A timeout" 348 | // Timeout of 1 is tuning parm default (LOWPOWERAUTO_MM_CONFIG_TIMEOUT_US_DEFAULT) 349 | // via VL53L1_get_preset_mode_timing_cfg(). With the API, the register 350 | // actually ends up with a slightly different value because it gets assigned, 351 | // retrieved, recalculated with a different macro period, and reassigned, 352 | // but it probably doesn't matter because it seems like the MM ("mode 353 | // mitigation"?) sequence steps are disabled in low power auto mode anyway. 354 | writeReg16Bit(MM_CONFIG__TIMEOUT_MACROP_A, encodeTimeout( 355 | timeoutMicrosecondsToMclks(1, macro_period_us))); 356 | 357 | // "Update Range Timing A timeout" 358 | writeReg16Bit(RANGE_CONFIG__TIMEOUT_MACROP_A, encodeTimeout( 359 | timeoutMicrosecondsToMclks(range_config_timeout_us, macro_period_us))); 360 | 361 | // "Update Macro Period for Range B VCSEL Period" 362 | macro_period_us = calcMacroPeriod(readReg(RANGE_CONFIG__VCSEL_PERIOD_B)); 363 | 364 | // "Update MM Timing B timeout" 365 | // (See earlier comment about MM Timing A timeout.) 366 | writeReg16Bit(MM_CONFIG__TIMEOUT_MACROP_B, encodeTimeout( 367 | timeoutMicrosecondsToMclks(1, macro_period_us))); 368 | 369 | // "Update Range Timing B timeout" 370 | writeReg16Bit(RANGE_CONFIG__TIMEOUT_MACROP_B, encodeTimeout( 371 | timeoutMicrosecondsToMclks(range_config_timeout_us, macro_period_us))); 372 | 373 | // VL53L1_calc_timeout_register_values() end 374 | 375 | return true; 376 | } 377 | 378 | // Get the measurement timing budget in microseconds 379 | // based on VL53L1_SetMeasurementTimingBudgetMicroSeconds() 380 | uint32_t VL53L1X::getMeasurementTimingBudget() 381 | { 382 | // assumes PresetMode is LOWPOWER_AUTONOMOUS and these sequence steps are 383 | // enabled: VHV, PHASECAL, DSS1, RANGE 384 | 385 | // VL53L1_get_timeouts_us() begin 386 | 387 | // "Update Macro Period for Range A VCSEL Period" 388 | uint32_t macro_period_us = calcMacroPeriod(readReg(RANGE_CONFIG__VCSEL_PERIOD_A)); 389 | 390 | // "Get Range Timing A timeout" 391 | 392 | uint32_t range_config_timeout_us = timeoutMclksToMicroseconds(decodeTimeout( 393 | readReg16Bit(RANGE_CONFIG__TIMEOUT_MACROP_A)), macro_period_us); 394 | 395 | // VL53L1_get_timeouts_us() end 396 | 397 | return 2 * range_config_timeout_us + TimingGuard; 398 | } 399 | 400 | // Set the width and height of the region of interest 401 | // based on VL53L1X_SetROI() from STSW-IMG009 Ultra Lite Driver 402 | // 403 | // ST user manual UM2555 explains ROI selection in detail, so we recommend 404 | // reading that document carefully. 405 | void VL53L1X::setROISize(uint8_t width, uint8_t height) 406 | { 407 | if ( width > 16) { width = 16; } 408 | if (height > 16) { height = 16; } 409 | 410 | // Force ROI to be centered if width or height > 10, matching what the ULD API 411 | // does. (This can probably be overridden by calling setROICenter() 412 | // afterwards.) 413 | if (width > 10 || height > 10) 414 | { 415 | writeReg(ROI_CONFIG__USER_ROI_CENTRE_SPAD, 199); 416 | } 417 | 418 | writeReg(ROI_CONFIG__USER_ROI_REQUESTED_GLOBAL_XY_SIZE, 419 | (height - 1) << 4 | (width - 1)); 420 | } 421 | 422 | // Get the width and height of the region of interest (ROI) 423 | // based on VL53L1X_GetROI_XY() from STSW-IMG009 Ultra Lite Driver 424 | void VL53L1X::getROISize(uint8_t * width, uint8_t * height) 425 | { 426 | uint8_t reg_val = readReg(ROI_CONFIG__USER_ROI_REQUESTED_GLOBAL_XY_SIZE); 427 | *width = (reg_val & 0xF) + 1; 428 | *height = (reg_val >> 4) + 1; 429 | } 430 | 431 | // Set the center SPAD of the region of interest (ROI) 432 | // based on VL53L1X_SetROICenter() from STSW-IMG009 Ultra Lite Driver 433 | // 434 | // ST user manual UM2555 explains ROI selection in detail, so we recommend 435 | // reading that document carefully. Here is a table of SPAD locations from 436 | // UM2555 (199 is the default/center): 437 | // 438 | // 128,136,144,152,160,168,176,184, 192,200,208,216,224,232,240,248 439 | // 129,137,145,153,161,169,177,185, 193,201,209,217,225,233,241,249 440 | // 130,138,146,154,162,170,178,186, 194,202,210,218,226,234,242,250 441 | // 131,139,147,155,163,171,179,187, 195,203,211,219,227,235,243,251 442 | // 132,140,148,156,164,172,180,188, 196,204,212,220,228,236,244,252 443 | // 133,141,149,157,165,173,181,189, 197,205,213,221,229,237,245,253 444 | // 134,142,150,158,166,174,182,190, 198,206,214,222,230,238,246,254 445 | // 135,143,151,159,167,175,183,191, 199,207,215,223,231,239,247,255 446 | // 447 | // 127,119,111,103, 95, 87, 79, 71, 63, 55, 47, 39, 31, 23, 15, 7 448 | // 126,118,110,102, 94, 86, 78, 70, 62, 54, 46, 38, 30, 22, 14, 6 449 | // 125,117,109,101, 93, 85, 77, 69, 61, 53, 45, 37, 29, 21, 13, 5 450 | // 124,116,108,100, 92, 84, 76, 68, 60, 52, 44, 36, 28, 20, 12, 4 451 | // 123,115,107, 99, 91, 83, 75, 67, 59, 51, 43, 35, 27, 19, 11, 3 452 | // 122,114,106, 98, 90, 82, 74, 66, 58, 50, 42, 34, 26, 18, 10, 2 453 | // 121,113,105, 97, 89, 81, 73, 65, 57, 49, 41, 33, 25, 17, 9, 1 454 | // 120,112,104, 96, 88, 80, 72, 64, 56, 48, 40, 32, 24, 16, 8, 0 <- Pin 1 455 | // 456 | // This table is oriented as if looking into the front of the sensor (or top of 457 | // the chip). SPAD 0 is closest to pin 1 of the VL53L1X, which is the corner 458 | // closest to the VDD pin on the Pololu VL53L1X carrier board: 459 | // 460 | // +--------------+ 461 | // | O| GPIO1 462 | // | | 463 | // | O| 464 | // | 128 248 | 465 | // |+----------+ O| 466 | // ||+--+ +--+| | 467 | // ||| | | || O| 468 | // ||+--+ +--+| | 469 | // |+----------+ O| 470 | // | 120 0 | 471 | // | O| 472 | // | | 473 | // | O| VDD 474 | // +--------------+ 475 | // 476 | // However, note that the lens inside the VL53L1X inverts the image it sees 477 | // (like the way a camera works). So for example, to shift the sensor's FOV to 478 | // sense objects toward the upper left, you should pick a center SPAD in the 479 | // lower right. 480 | void VL53L1X::setROICenter(uint8_t spadNumber) 481 | { 482 | writeReg(ROI_CONFIG__USER_ROI_CENTRE_SPAD, spadNumber); 483 | } 484 | 485 | // Get the center SPAD of the region of interest 486 | // based on VL53L1X_GetROICenter() from STSW-IMG009 Ultra Lite Driver 487 | uint8_t VL53L1X::getROICenter() 488 | { 489 | return readReg(ROI_CONFIG__USER_ROI_CENTRE_SPAD); 490 | } 491 | 492 | // Start continuous ranging measurements, with the given inter-measurement 493 | // period in milliseconds determining how often the sensor takes a measurement. 494 | void VL53L1X::startContinuous(uint32_t period_ms) 495 | { 496 | // from VL53L1_set_inter_measurement_period_ms() 497 | writeReg32Bit(SYSTEM__INTERMEASUREMENT_PERIOD, period_ms * osc_calibrate_val); 498 | 499 | writeReg(SYSTEM__INTERRUPT_CLEAR, 0x01); // sys_interrupt_clear_range 500 | writeReg(SYSTEM__MODE_START, 0x40); // mode_range__timed 501 | } 502 | 503 | // Stop continuous measurements 504 | // based on VL53L1_stop_range() 505 | void VL53L1X::stopContinuous() 506 | { 507 | writeReg(SYSTEM__MODE_START, 0x80); // mode_range__abort 508 | 509 | // VL53L1_low_power_auto_data_stop_range() begin 510 | 511 | calibrated = false; 512 | 513 | // "restore vhv configs" 514 | if (saved_vhv_init != 0) 515 | { 516 | writeReg(VHV_CONFIG__INIT, saved_vhv_init); 517 | } 518 | if (saved_vhv_timeout != 0) 519 | { 520 | writeReg(VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND, saved_vhv_timeout); 521 | } 522 | 523 | // "remove phasecal override" 524 | writeReg(PHASECAL_CONFIG__OVERRIDE, 0x00); 525 | 526 | // VL53L1_low_power_auto_data_stop_range() end 527 | } 528 | 529 | // Returns a range reading in millimeters when continuous mode is active. If 530 | // blocking is true (the default), this function waits for a new measurement to 531 | // be available. If blocking is false, it will try to return data immediately. 532 | // (readSingle() also calls this function after starting a single-shot range 533 | // measurement) 534 | uint16_t VL53L1X::read(bool blocking) 535 | { 536 | if (blocking) 537 | { 538 | startTimeout(); 539 | while (!dataReady()) 540 | { 541 | if (checkTimeoutExpired()) 542 | { 543 | did_timeout = true; 544 | return 0; 545 | } 546 | } 547 | } 548 | 549 | readResults(); 550 | 551 | if (!calibrated) 552 | { 553 | setupManualCalibration(); 554 | calibrated = true; 555 | } 556 | 557 | updateDSS(); 558 | 559 | getRangingData(); 560 | 561 | writeReg(SYSTEM__INTERRUPT_CLEAR, 0x01); // sys_interrupt_clear_range 562 | 563 | return ranging_data.range_mm; 564 | } 565 | 566 | // Starts a single-shot range measurement. If blocking is true (the default), 567 | // this function waits for the measurement to finish and returns the reading. 568 | // Otherwise, it returns 0 immediately. 569 | uint16_t VL53L1X::readSingle(bool blocking) 570 | { 571 | writeReg(SYSTEM__INTERRUPT_CLEAR, 0x01); // sys_interrupt_clear_range 572 | writeReg(SYSTEM__MODE_START, 0x10); // mode_range__single_shot 573 | 574 | if (blocking) 575 | { 576 | return read(true); 577 | } 578 | else 579 | { 580 | return 0; 581 | } 582 | } 583 | 584 | // convert a RangeStatus to a readable string 585 | // Note that on an AVR, these strings are stored in RAM (dynamic memory), which 586 | // makes working with them easier but uses up 200+ bytes of RAM (many AVR-based 587 | // Arduinos only have about 2000 bytes of RAM). You can avoid this memory usage 588 | // if you do not call this function in your sketch. 589 | const char * VL53L1X::rangeStatusToString(RangeStatus status) 590 | { 591 | switch (status) 592 | { 593 | case RangeValid: 594 | return "range valid"; 595 | 596 | case SigmaFail: 597 | return "sigma fail"; 598 | 599 | case SignalFail: 600 | return "signal fail"; 601 | 602 | case RangeValidMinRangeClipped: 603 | return "range valid, min range clipped"; 604 | 605 | case OutOfBoundsFail: 606 | return "out of bounds fail"; 607 | 608 | case HardwareFail: 609 | return "hardware fail"; 610 | 611 | case RangeValidNoWrapCheckFail: 612 | return "range valid, no wrap check fail"; 613 | 614 | case WrapTargetFail: 615 | return "wrap target fail"; 616 | 617 | case XtalkSignalFail: 618 | return "xtalk signal fail"; 619 | 620 | case SynchronizationInt: 621 | return "synchronization int"; 622 | 623 | case MinRangeFail: 624 | return "min range fail"; 625 | 626 | case None: 627 | return "no update"; 628 | 629 | default: 630 | return "unknown status"; 631 | } 632 | } 633 | 634 | // Did a timeout occur in one of the read functions since the last call to 635 | // timeoutOccurred()? 636 | bool VL53L1X::timeoutOccurred() 637 | { 638 | bool tmp = did_timeout; 639 | did_timeout = false; 640 | return tmp; 641 | } 642 | 643 | // Private Methods ///////////////////////////////////////////////////////////// 644 | 645 | // "Setup ranges after the first one in low power auto mode by turning off 646 | // FW calibration steps and programming static values" 647 | // based on VL53L1_low_power_auto_setup_manual_calibration() 648 | void VL53L1X::setupManualCalibration() 649 | { 650 | // "save original vhv configs" 651 | saved_vhv_init = readReg(VHV_CONFIG__INIT); 652 | saved_vhv_timeout = readReg(VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND); 653 | 654 | // "disable VHV init" 655 | writeReg(VHV_CONFIG__INIT, saved_vhv_init & 0x7F); 656 | 657 | // "set loop bound to tuning param" 658 | writeReg(VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND, 659 | (saved_vhv_timeout & 0x03) + (3 << 2)); // tuning parm default (LOWPOWERAUTO_VHV_LOOP_BOUND_DEFAULT) 660 | 661 | // "override phasecal" 662 | writeReg(PHASECAL_CONFIG__OVERRIDE, 0x01); 663 | writeReg(CAL_CONFIG__VCSEL_START, readReg(PHASECAL_RESULT__VCSEL_START)); 664 | } 665 | 666 | // read measurement results into buffer 667 | void VL53L1X::readResults() 668 | { 669 | bus->beginTransmission(address); 670 | bus->write((uint8_t)(RESULT__RANGE_STATUS >> 8)); // reg high byte 671 | bus->write((uint8_t)(RESULT__RANGE_STATUS)); // reg low byte 672 | last_status = bus->endTransmission(); 673 | 674 | bus->requestFrom(address, (uint8_t)17); 675 | 676 | results.range_status = bus->read(); 677 | 678 | bus->read(); // report_status: not used 679 | 680 | results.stream_count = bus->read(); 681 | 682 | results.dss_actual_effective_spads_sd0 = (uint16_t)bus->read() << 8; // high byte 683 | results.dss_actual_effective_spads_sd0 |= bus->read(); // low byte 684 | 685 | bus->read(); // peak_signal_count_rate_mcps_sd0: not used 686 | bus->read(); 687 | 688 | results.ambient_count_rate_mcps_sd0 = (uint16_t)bus->read() << 8; // high byte 689 | results.ambient_count_rate_mcps_sd0 |= bus->read(); // low byte 690 | 691 | bus->read(); // sigma_sd0: not used 692 | bus->read(); 693 | 694 | bus->read(); // phase_sd0: not used 695 | bus->read(); 696 | 697 | results.final_crosstalk_corrected_range_mm_sd0 = (uint16_t)bus->read() << 8; // high byte 698 | results.final_crosstalk_corrected_range_mm_sd0 |= bus->read(); // low byte 699 | 700 | results.peak_signal_count_rate_crosstalk_corrected_mcps_sd0 = (uint16_t)bus->read() << 8; // high byte 701 | results.peak_signal_count_rate_crosstalk_corrected_mcps_sd0 |= bus->read(); // low byte 702 | } 703 | 704 | // perform Dynamic SPAD Selection calculation/update 705 | // based on VL53L1_low_power_auto_update_DSS() 706 | void VL53L1X::updateDSS() 707 | { 708 | uint16_t spadCount = results.dss_actual_effective_spads_sd0; 709 | 710 | if (spadCount != 0) 711 | { 712 | // "Calc total rate per spad" 713 | 714 | uint32_t totalRatePerSpad = 715 | (uint32_t)results.peak_signal_count_rate_crosstalk_corrected_mcps_sd0 + 716 | results.ambient_count_rate_mcps_sd0; 717 | 718 | // "clip to 16 bits" 719 | if (totalRatePerSpad > 0xFFFF) { totalRatePerSpad = 0xFFFF; } 720 | 721 | // "shift up to take advantage of 32 bits" 722 | totalRatePerSpad <<= 16; 723 | 724 | totalRatePerSpad /= spadCount; 725 | 726 | if (totalRatePerSpad != 0) 727 | { 728 | // "get the target rate and shift up by 16" 729 | uint32_t requiredSpads = ((uint32_t)TargetRate << 16) / totalRatePerSpad; 730 | 731 | // "clip to 16 bit" 732 | if (requiredSpads > 0xFFFF) { requiredSpads = 0xFFFF; } 733 | 734 | // "override DSS config" 735 | writeReg16Bit(DSS_CONFIG__MANUAL_EFFECTIVE_SPADS_SELECT, requiredSpads); 736 | // DSS_CONFIG__ROI_MODE_CONTROL should already be set to REQUESTED_EFFFECTIVE_SPADS 737 | 738 | return; 739 | } 740 | } 741 | 742 | // If we reached this point, it means something above would have resulted in a 743 | // divide by zero. 744 | // "We want to gracefully set a spad target, not just exit with an error" 745 | 746 | // "set target to mid point" 747 | writeReg16Bit(DSS_CONFIG__MANUAL_EFFECTIVE_SPADS_SELECT, 0x8000); 748 | } 749 | 750 | // get range, status, rates from results buffer 751 | // based on VL53L1_GetRangingMeasurementData() 752 | void VL53L1X::getRangingData() 753 | { 754 | // VL53L1_copy_sys_and_core_results_to_range_results() begin 755 | 756 | uint16_t range = results.final_crosstalk_corrected_range_mm_sd0; 757 | 758 | // "apply correction gain" 759 | // gain factor of 2011 is tuning parm default (VL53L1_TUNINGPARM_LITE_RANGING_GAIN_FACTOR_DEFAULT) 760 | // Basically, this appears to scale the result by 2011/2048, or about 98% 761 | // (with the 1024 added for proper rounding). 762 | ranging_data.range_mm = ((uint32_t)range * 2011 + 0x0400) / 0x0800; 763 | 764 | // VL53L1_copy_sys_and_core_results_to_range_results() end 765 | 766 | // set range_status in ranging_data based on value of RESULT__RANGE_STATUS register 767 | // mostly based on ConvertStatusLite() 768 | switch(results.range_status) 769 | { 770 | case 17: // MULTCLIPFAIL 771 | case 2: // VCSELWATCHDOGTESTFAILURE 772 | case 1: // VCSELCONTINUITYTESTFAILURE 773 | case 3: // NOVHVVALUEFOUND 774 | // from SetSimpleData() 775 | ranging_data.range_status = HardwareFail; 776 | break; 777 | 778 | case 13: // USERROICLIP 779 | // from SetSimpleData() 780 | ranging_data.range_status = MinRangeFail; 781 | break; 782 | 783 | case 18: // GPHSTREAMCOUNT0READY 784 | ranging_data.range_status = SynchronizationInt; 785 | break; 786 | 787 | case 5: // RANGEPHASECHECK 788 | ranging_data.range_status = OutOfBoundsFail; 789 | break; 790 | 791 | case 4: // MSRCNOTARGET 792 | ranging_data.range_status = SignalFail; 793 | break; 794 | 795 | case 6: // SIGMATHRESHOLDCHECK 796 | ranging_data.range_status = SigmaFail; 797 | break; 798 | 799 | case 7: // PHASECONSISTENCY 800 | ranging_data.range_status = WrapTargetFail; 801 | break; 802 | 803 | case 12: // RANGEIGNORETHRESHOLD 804 | ranging_data.range_status = XtalkSignalFail; 805 | break; 806 | 807 | case 8: // MINCLIP 808 | ranging_data.range_status = RangeValidMinRangeClipped; 809 | break; 810 | 811 | case 9: // RANGECOMPLETE 812 | // from VL53L1_copy_sys_and_core_results_to_range_results() 813 | if (results.stream_count == 0) 814 | { 815 | ranging_data.range_status = RangeValidNoWrapCheckFail; 816 | } 817 | else 818 | { 819 | ranging_data.range_status = RangeValid; 820 | } 821 | break; 822 | 823 | default: 824 | ranging_data.range_status = None; 825 | } 826 | 827 | // from SetSimpleData() 828 | ranging_data.peak_signal_count_rate_MCPS = 829 | countRateFixedToFloat(results.peak_signal_count_rate_crosstalk_corrected_mcps_sd0); 830 | ranging_data.ambient_count_rate_MCPS = 831 | countRateFixedToFloat(results.ambient_count_rate_mcps_sd0); 832 | } 833 | 834 | // Decode sequence step timeout in MCLKs from register value 835 | // based on VL53L1_decode_timeout() 836 | uint32_t VL53L1X::decodeTimeout(uint16_t reg_val) 837 | { 838 | return ((uint32_t)(reg_val & 0xFF) << (reg_val >> 8)) + 1; 839 | } 840 | 841 | // Encode sequence step timeout register value from timeout in MCLKs 842 | // based on VL53L1_encode_timeout() 843 | uint16_t VL53L1X::encodeTimeout(uint32_t timeout_mclks) 844 | { 845 | // encoded format: "(LSByte * 2^MSByte) + 1" 846 | 847 | uint32_t ls_byte = 0; 848 | uint16_t ms_byte = 0; 849 | 850 | if (timeout_mclks > 0) 851 | { 852 | ls_byte = timeout_mclks - 1; 853 | 854 | while ((ls_byte & 0xFFFFFF00) > 0) 855 | { 856 | ls_byte >>= 1; 857 | ms_byte++; 858 | } 859 | 860 | return (ms_byte << 8) | (ls_byte & 0xFF); 861 | } 862 | else { return 0; } 863 | } 864 | 865 | // Convert sequence step timeout from macro periods to microseconds with given 866 | // macro period in microseconds (12.12 format) 867 | // based on VL53L1_calc_timeout_us() 868 | uint32_t VL53L1X::timeoutMclksToMicroseconds(uint32_t timeout_mclks, uint32_t macro_period_us) 869 | { 870 | return ((uint64_t)timeout_mclks * macro_period_us + 0x800) >> 12; 871 | } 872 | 873 | // Convert sequence step timeout from microseconds to macro periods with given 874 | // macro period in microseconds (12.12 format) 875 | // based on VL53L1_calc_timeout_mclks() 876 | uint32_t VL53L1X::timeoutMicrosecondsToMclks(uint32_t timeout_us, uint32_t macro_period_us) 877 | { 878 | return (((uint32_t)timeout_us << 12) + (macro_period_us >> 1)) / macro_period_us; 879 | } 880 | 881 | // Calculate macro period in microseconds (12.12 format) with given VCSEL period 882 | // assumes fast_osc_frequency has been read and stored 883 | // based on VL53L1_calc_macro_period_us() 884 | uint32_t VL53L1X::calcMacroPeriod(uint8_t vcsel_period) 885 | { 886 | // from VL53L1_calc_pll_period_us() 887 | // fast osc frequency in 4.12 format; PLL period in 0.24 format 888 | uint32_t pll_period_us = ((uint32_t)0x01 << 30) / fast_osc_frequency; 889 | 890 | // from VL53L1_decode_vcsel_period() 891 | uint8_t vcsel_period_pclks = (vcsel_period + 1) << 1; 892 | 893 | // VL53L1_MACRO_PERIOD_VCSEL_PERIODS = 2304 894 | uint32_t macro_period_us = (uint32_t)2304 * pll_period_us; 895 | macro_period_us >>= 6; 896 | macro_period_us *= vcsel_period_pclks; 897 | macro_period_us >>= 6; 898 | 899 | return macro_period_us; 900 | } 901 | -------------------------------------------------------------------------------- /VL53L1X.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | class VL53L1X 7 | { 8 | public: 9 | 10 | // register addresses from API vl53l1x_register_map.h 11 | enum regAddr : uint16_t 12 | { 13 | SOFT_RESET = 0x0000, 14 | I2C_SLAVE__DEVICE_ADDRESS = 0x0001, 15 | ANA_CONFIG__VHV_REF_SEL_VDDPIX = 0x0002, 16 | ANA_CONFIG__VHV_REF_SEL_VQUENCH = 0x0003, 17 | ANA_CONFIG__REG_AVDD1V2_SEL = 0x0004, 18 | ANA_CONFIG__FAST_OSC__TRIM = 0x0005, 19 | OSC_MEASURED__FAST_OSC__FREQUENCY = 0x0006, 20 | OSC_MEASURED__FAST_OSC__FREQUENCY_HI = 0x0006, 21 | OSC_MEASURED__FAST_OSC__FREQUENCY_LO = 0x0007, 22 | VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND = 0x0008, 23 | VHV_CONFIG__COUNT_THRESH = 0x0009, 24 | VHV_CONFIG__OFFSET = 0x000A, 25 | VHV_CONFIG__INIT = 0x000B, 26 | GLOBAL_CONFIG__SPAD_ENABLES_REF_0 = 0x000D, 27 | GLOBAL_CONFIG__SPAD_ENABLES_REF_1 = 0x000E, 28 | GLOBAL_CONFIG__SPAD_ENABLES_REF_2 = 0x000F, 29 | GLOBAL_CONFIG__SPAD_ENABLES_REF_3 = 0x0010, 30 | GLOBAL_CONFIG__SPAD_ENABLES_REF_4 = 0x0011, 31 | GLOBAL_CONFIG__SPAD_ENABLES_REF_5 = 0x0012, 32 | GLOBAL_CONFIG__REF_EN_START_SELECT = 0x0013, 33 | REF_SPAD_MAN__NUM_REQUESTED_REF_SPADS = 0x0014, 34 | REF_SPAD_MAN__REF_LOCATION = 0x0015, 35 | ALGO__CROSSTALK_COMPENSATION_PLANE_OFFSET_KCPS = 0x0016, 36 | ALGO__CROSSTALK_COMPENSATION_PLANE_OFFSET_KCPS_HI = 0x0016, 37 | ALGO__CROSSTALK_COMPENSATION_PLANE_OFFSET_KCPS_LO = 0x0017, 38 | ALGO__CROSSTALK_COMPENSATION_X_PLANE_GRADIENT_KCPS = 0x0018, 39 | ALGO__CROSSTALK_COMPENSATION_X_PLANE_GRADIENT_KCPS_HI = 0x0018, 40 | ALGO__CROSSTALK_COMPENSATION_X_PLANE_GRADIENT_KCPS_LO = 0x0019, 41 | ALGO__CROSSTALK_COMPENSATION_Y_PLANE_GRADIENT_KCPS = 0x001A, 42 | ALGO__CROSSTALK_COMPENSATION_Y_PLANE_GRADIENT_KCPS_HI = 0x001A, 43 | ALGO__CROSSTALK_COMPENSATION_Y_PLANE_GRADIENT_KCPS_LO = 0x001B, 44 | REF_SPAD_CHAR__TOTAL_RATE_TARGET_MCPS = 0x001C, 45 | REF_SPAD_CHAR__TOTAL_RATE_TARGET_MCPS_HI = 0x001C, 46 | REF_SPAD_CHAR__TOTAL_RATE_TARGET_MCPS_LO = 0x001D, 47 | ALGO__PART_TO_PART_RANGE_OFFSET_MM = 0x001E, 48 | ALGO__PART_TO_PART_RANGE_OFFSET_MM_HI = 0x001E, 49 | ALGO__PART_TO_PART_RANGE_OFFSET_MM_LO = 0x001F, 50 | MM_CONFIG__INNER_OFFSET_MM = 0x0020, 51 | MM_CONFIG__INNER_OFFSET_MM_HI = 0x0020, 52 | MM_CONFIG__INNER_OFFSET_MM_LO = 0x0021, 53 | MM_CONFIG__OUTER_OFFSET_MM = 0x0022, 54 | MM_CONFIG__OUTER_OFFSET_MM_HI = 0x0022, 55 | MM_CONFIG__OUTER_OFFSET_MM_LO = 0x0023, 56 | DSS_CONFIG__TARGET_TOTAL_RATE_MCPS = 0x0024, 57 | DSS_CONFIG__TARGET_TOTAL_RATE_MCPS_HI = 0x0024, 58 | DSS_CONFIG__TARGET_TOTAL_RATE_MCPS_LO = 0x0025, 59 | DEBUG__CTRL = 0x0026, 60 | TEST_MODE__CTRL = 0x0027, 61 | CLK_GATING__CTRL = 0x0028, 62 | NVM_BIST__CTRL = 0x0029, 63 | NVM_BIST__NUM_NVM_WORDS = 0x002A, 64 | NVM_BIST__START_ADDRESS = 0x002B, 65 | HOST_IF__STATUS = 0x002C, 66 | PAD_I2C_HV__CONFIG = 0x002D, 67 | PAD_I2C_HV__EXTSUP_CONFIG = 0x002E, 68 | GPIO_HV_PAD__CTRL = 0x002F, 69 | GPIO_HV_MUX__CTRL = 0x0030, 70 | GPIO__TIO_HV_STATUS = 0x0031, 71 | GPIO__FIO_HV_STATUS = 0x0032, 72 | ANA_CONFIG__SPAD_SEL_PSWIDTH = 0x0033, 73 | ANA_CONFIG__VCSEL_PULSE_WIDTH_OFFSET = 0x0034, 74 | ANA_CONFIG__FAST_OSC__CONFIG_CTRL = 0x0035, 75 | SIGMA_ESTIMATOR__EFFECTIVE_PULSE_WIDTH_NS = 0x0036, 76 | SIGMA_ESTIMATOR__EFFECTIVE_AMBIENT_WIDTH_NS = 0x0037, 77 | SIGMA_ESTIMATOR__SIGMA_REF_MM = 0x0038, 78 | ALGO__CROSSTALK_COMPENSATION_VALID_HEIGHT_MM = 0x0039, 79 | SPARE_HOST_CONFIG__STATIC_CONFIG_SPARE_0 = 0x003A, 80 | SPARE_HOST_CONFIG__STATIC_CONFIG_SPARE_1 = 0x003B, 81 | ALGO__RANGE_IGNORE_THRESHOLD_MCPS = 0x003C, 82 | ALGO__RANGE_IGNORE_THRESHOLD_MCPS_HI = 0x003C, 83 | ALGO__RANGE_IGNORE_THRESHOLD_MCPS_LO = 0x003D, 84 | ALGO__RANGE_IGNORE_VALID_HEIGHT_MM = 0x003E, 85 | ALGO__RANGE_MIN_CLIP = 0x003F, 86 | ALGO__CONSISTENCY_CHECK__TOLERANCE = 0x0040, 87 | SPARE_HOST_CONFIG__STATIC_CONFIG_SPARE_2 = 0x0041, 88 | SD_CONFIG__RESET_STAGES_MSB = 0x0042, 89 | SD_CONFIG__RESET_STAGES_LSB = 0x0043, 90 | GPH_CONFIG__STREAM_COUNT_UPDATE_VALUE = 0x0044, 91 | GLOBAL_CONFIG__STREAM_DIVIDER = 0x0045, 92 | SYSTEM__INTERRUPT_CONFIG_GPIO = 0x0046, 93 | CAL_CONFIG__VCSEL_START = 0x0047, 94 | CAL_CONFIG__REPEAT_RATE = 0x0048, 95 | CAL_CONFIG__REPEAT_RATE_HI = 0x0048, 96 | CAL_CONFIG__REPEAT_RATE_LO = 0x0049, 97 | GLOBAL_CONFIG__VCSEL_WIDTH = 0x004A, 98 | PHASECAL_CONFIG__TIMEOUT_MACROP = 0x004B, 99 | PHASECAL_CONFIG__TARGET = 0x004C, 100 | PHASECAL_CONFIG__OVERRIDE = 0x004D, 101 | DSS_CONFIG__ROI_MODE_CONTROL = 0x004F, 102 | SYSTEM__THRESH_RATE_HIGH = 0x0050, 103 | SYSTEM__THRESH_RATE_HIGH_HI = 0x0050, 104 | SYSTEM__THRESH_RATE_HIGH_LO = 0x0051, 105 | SYSTEM__THRESH_RATE_LOW = 0x0052, 106 | SYSTEM__THRESH_RATE_LOW_HI = 0x0052, 107 | SYSTEM__THRESH_RATE_LOW_LO = 0x0053, 108 | DSS_CONFIG__MANUAL_EFFECTIVE_SPADS_SELECT = 0x0054, 109 | DSS_CONFIG__MANUAL_EFFECTIVE_SPADS_SELECT_HI = 0x0054, 110 | DSS_CONFIG__MANUAL_EFFECTIVE_SPADS_SELECT_LO = 0x0055, 111 | DSS_CONFIG__MANUAL_BLOCK_SELECT = 0x0056, 112 | DSS_CONFIG__APERTURE_ATTENUATION = 0x0057, 113 | DSS_CONFIG__MAX_SPADS_LIMIT = 0x0058, 114 | DSS_CONFIG__MIN_SPADS_LIMIT = 0x0059, 115 | MM_CONFIG__TIMEOUT_MACROP_A = 0x005A, // added by Pololu for 16-bit accesses 116 | MM_CONFIG__TIMEOUT_MACROP_A_HI = 0x005A, 117 | MM_CONFIG__TIMEOUT_MACROP_A_LO = 0x005B, 118 | MM_CONFIG__TIMEOUT_MACROP_B = 0x005C, // added by Pololu for 16-bit accesses 119 | MM_CONFIG__TIMEOUT_MACROP_B_HI = 0x005C, 120 | MM_CONFIG__TIMEOUT_MACROP_B_LO = 0x005D, 121 | RANGE_CONFIG__TIMEOUT_MACROP_A = 0x005E, // added by Pololu for 16-bit accesses 122 | RANGE_CONFIG__TIMEOUT_MACROP_A_HI = 0x005E, 123 | RANGE_CONFIG__TIMEOUT_MACROP_A_LO = 0x005F, 124 | RANGE_CONFIG__VCSEL_PERIOD_A = 0x0060, 125 | RANGE_CONFIG__TIMEOUT_MACROP_B = 0x0061, // added by Pololu for 16-bit accesses 126 | RANGE_CONFIG__TIMEOUT_MACROP_B_HI = 0x0061, 127 | RANGE_CONFIG__TIMEOUT_MACROP_B_LO = 0x0062, 128 | RANGE_CONFIG__VCSEL_PERIOD_B = 0x0063, 129 | RANGE_CONFIG__SIGMA_THRESH = 0x0064, 130 | RANGE_CONFIG__SIGMA_THRESH_HI = 0x0064, 131 | RANGE_CONFIG__SIGMA_THRESH_LO = 0x0065, 132 | RANGE_CONFIG__MIN_COUNT_RATE_RTN_LIMIT_MCPS = 0x0066, 133 | RANGE_CONFIG__MIN_COUNT_RATE_RTN_LIMIT_MCPS_HI = 0x0066, 134 | RANGE_CONFIG__MIN_COUNT_RATE_RTN_LIMIT_MCPS_LO = 0x0067, 135 | RANGE_CONFIG__VALID_PHASE_LOW = 0x0068, 136 | RANGE_CONFIG__VALID_PHASE_HIGH = 0x0069, 137 | SYSTEM__INTERMEASUREMENT_PERIOD = 0x006C, 138 | SYSTEM__INTERMEASUREMENT_PERIOD_3 = 0x006C, 139 | SYSTEM__INTERMEASUREMENT_PERIOD_2 = 0x006D, 140 | SYSTEM__INTERMEASUREMENT_PERIOD_1 = 0x006E, 141 | SYSTEM__INTERMEASUREMENT_PERIOD_0 = 0x006F, 142 | SYSTEM__FRACTIONAL_ENABLE = 0x0070, 143 | SYSTEM__GROUPED_PARAMETER_HOLD_0 = 0x0071, 144 | SYSTEM__THRESH_HIGH = 0x0072, 145 | SYSTEM__THRESH_HIGH_HI = 0x0072, 146 | SYSTEM__THRESH_HIGH_LO = 0x0073, 147 | SYSTEM__THRESH_LOW = 0x0074, 148 | SYSTEM__THRESH_LOW_HI = 0x0074, 149 | SYSTEM__THRESH_LOW_LO = 0x0075, 150 | SYSTEM__ENABLE_XTALK_PER_QUADRANT = 0x0076, 151 | SYSTEM__SEED_CONFIG = 0x0077, 152 | SD_CONFIG__WOI_SD0 = 0x0078, 153 | SD_CONFIG__WOI_SD1 = 0x0079, 154 | SD_CONFIG__INITIAL_PHASE_SD0 = 0x007A, 155 | SD_CONFIG__INITIAL_PHASE_SD1 = 0x007B, 156 | SYSTEM__GROUPED_PARAMETER_HOLD_1 = 0x007C, 157 | SD_CONFIG__FIRST_ORDER_SELECT = 0x007D, 158 | SD_CONFIG__QUANTIFIER = 0x007E, 159 | ROI_CONFIG__USER_ROI_CENTRE_SPAD = 0x007F, 160 | ROI_CONFIG__USER_ROI_REQUESTED_GLOBAL_XY_SIZE = 0x0080, 161 | SYSTEM__SEQUENCE_CONFIG = 0x0081, 162 | SYSTEM__GROUPED_PARAMETER_HOLD = 0x0082, 163 | POWER_MANAGEMENT__GO1_POWER_FORCE = 0x0083, 164 | SYSTEM__STREAM_COUNT_CTRL = 0x0084, 165 | FIRMWARE__ENABLE = 0x0085, 166 | SYSTEM__INTERRUPT_CLEAR = 0x0086, 167 | SYSTEM__MODE_START = 0x0087, 168 | RESULT__INTERRUPT_STATUS = 0x0088, 169 | RESULT__RANGE_STATUS = 0x0089, 170 | RESULT__REPORT_STATUS = 0x008A, 171 | RESULT__STREAM_COUNT = 0x008B, 172 | RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0 = 0x008C, 173 | RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0_HI = 0x008C, 174 | RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0_LO = 0x008D, 175 | RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD0 = 0x008E, 176 | RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD0_HI = 0x008E, 177 | RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD0_LO = 0x008F, 178 | RESULT__AMBIENT_COUNT_RATE_MCPS_SD0 = 0x0090, 179 | RESULT__AMBIENT_COUNT_RATE_MCPS_SD0_HI = 0x0090, 180 | RESULT__AMBIENT_COUNT_RATE_MCPS_SD0_LO = 0x0091, 181 | RESULT__SIGMA_SD0 = 0x0092, 182 | RESULT__SIGMA_SD0_HI = 0x0092, 183 | RESULT__SIGMA_SD0_LO = 0x0093, 184 | RESULT__PHASE_SD0 = 0x0094, 185 | RESULT__PHASE_SD0_HI = 0x0094, 186 | RESULT__PHASE_SD0_LO = 0x0095, 187 | RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0 = 0x0096, 188 | RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0_HI = 0x0096, 189 | RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0_LO = 0x0097, 190 | RESULT__PEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0 = 0x0098, 191 | RESULT__PEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0_HI = 0x0098, 192 | RESULT__PEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0_LO = 0x0099, 193 | RESULT__MM_INNER_ACTUAL_EFFECTIVE_SPADS_SD0 = 0x009A, 194 | RESULT__MM_INNER_ACTUAL_EFFECTIVE_SPADS_SD0_HI = 0x009A, 195 | RESULT__MM_INNER_ACTUAL_EFFECTIVE_SPADS_SD0_LO = 0x009B, 196 | RESULT__MM_OUTER_ACTUAL_EFFECTIVE_SPADS_SD0 = 0x009C, 197 | RESULT__MM_OUTER_ACTUAL_EFFECTIVE_SPADS_SD0_HI = 0x009C, 198 | RESULT__MM_OUTER_ACTUAL_EFFECTIVE_SPADS_SD0_LO = 0x009D, 199 | RESULT__AVG_SIGNAL_COUNT_RATE_MCPS_SD0 = 0x009E, 200 | RESULT__AVG_SIGNAL_COUNT_RATE_MCPS_SD0_HI = 0x009E, 201 | RESULT__AVG_SIGNAL_COUNT_RATE_MCPS_SD0_LO = 0x009F, 202 | RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD1 = 0x00A0, 203 | RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD1_HI = 0x00A0, 204 | RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD1_LO = 0x00A1, 205 | RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD1 = 0x00A2, 206 | RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD1_HI = 0x00A2, 207 | RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD1_LO = 0x00A3, 208 | RESULT__AMBIENT_COUNT_RATE_MCPS_SD1 = 0x00A4, 209 | RESULT__AMBIENT_COUNT_RATE_MCPS_SD1_HI = 0x00A4, 210 | RESULT__AMBIENT_COUNT_RATE_MCPS_SD1_LO = 0x00A5, 211 | RESULT__SIGMA_SD1 = 0x00A6, 212 | RESULT__SIGMA_SD1_HI = 0x00A6, 213 | RESULT__SIGMA_SD1_LO = 0x00A7, 214 | RESULT__PHASE_SD1 = 0x00A8, 215 | RESULT__PHASE_SD1_HI = 0x00A8, 216 | RESULT__PHASE_SD1_LO = 0x00A9, 217 | RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD1 = 0x00AA, 218 | RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD1_HI = 0x00AA, 219 | RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD1_LO = 0x00AB, 220 | RESULT__SPARE_0_SD1 = 0x00AC, 221 | RESULT__SPARE_0_SD1_HI = 0x00AC, 222 | RESULT__SPARE_0_SD1_LO = 0x00AD, 223 | RESULT__SPARE_1_SD1 = 0x00AE, 224 | RESULT__SPARE_1_SD1_HI = 0x00AE, 225 | RESULT__SPARE_1_SD1_LO = 0x00AF, 226 | RESULT__SPARE_2_SD1 = 0x00B0, 227 | RESULT__SPARE_2_SD1_HI = 0x00B0, 228 | RESULT__SPARE_2_SD1_LO = 0x00B1, 229 | RESULT__SPARE_3_SD1 = 0x00B2, 230 | RESULT__THRESH_INFO = 0x00B3, 231 | RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0 = 0x00B4, 232 | RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0_3 = 0x00B4, 233 | RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0_2 = 0x00B5, 234 | RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0_1 = 0x00B6, 235 | RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0_0 = 0x00B7, 236 | RESULT_CORE__RANGING_TOTAL_EVENTS_SD0 = 0x00B8, 237 | RESULT_CORE__RANGING_TOTAL_EVENTS_SD0_3 = 0x00B8, 238 | RESULT_CORE__RANGING_TOTAL_EVENTS_SD0_2 = 0x00B9, 239 | RESULT_CORE__RANGING_TOTAL_EVENTS_SD0_1 = 0x00BA, 240 | RESULT_CORE__RANGING_TOTAL_EVENTS_SD0_0 = 0x00BB, 241 | RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0 = 0x00BC, 242 | RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0_3 = 0x00BC, 243 | RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0_2 = 0x00BD, 244 | RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0_1 = 0x00BE, 245 | RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0_0 = 0x00BF, 246 | RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0 = 0x00C0, 247 | RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0_3 = 0x00C0, 248 | RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0_2 = 0x00C1, 249 | RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0_1 = 0x00C2, 250 | RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0_0 = 0x00C3, 251 | RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1 = 0x00C4, 252 | RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1_3 = 0x00C4, 253 | RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1_2 = 0x00C5, 254 | RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1_1 = 0x00C6, 255 | RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1_0 = 0x00C7, 256 | RESULT_CORE__RANGING_TOTAL_EVENTS_SD1 = 0x00C8, 257 | RESULT_CORE__RANGING_TOTAL_EVENTS_SD1_3 = 0x00C8, 258 | RESULT_CORE__RANGING_TOTAL_EVENTS_SD1_2 = 0x00C9, 259 | RESULT_CORE__RANGING_TOTAL_EVENTS_SD1_1 = 0x00CA, 260 | RESULT_CORE__RANGING_TOTAL_EVENTS_SD1_0 = 0x00CB, 261 | RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1 = 0x00CC, 262 | RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1_3 = 0x00CC, 263 | RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1_2 = 0x00CD, 264 | RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1_1 = 0x00CE, 265 | RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1_0 = 0x00CF, 266 | RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1 = 0x00D0, 267 | RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1_3 = 0x00D0, 268 | RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1_2 = 0x00D1, 269 | RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1_1 = 0x00D2, 270 | RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1_0 = 0x00D3, 271 | RESULT_CORE__SPARE_0 = 0x00D4, 272 | PHASECAL_RESULT__REFERENCE_PHASE = 0x00D6, 273 | PHASECAL_RESULT__REFERENCE_PHASE_HI = 0x00D6, 274 | PHASECAL_RESULT__REFERENCE_PHASE_LO = 0x00D7, 275 | PHASECAL_RESULT__VCSEL_START = 0x00D8, 276 | REF_SPAD_CHAR_RESULT__NUM_ACTUAL_REF_SPADS = 0x00D9, 277 | REF_SPAD_CHAR_RESULT__REF_LOCATION = 0x00DA, 278 | VHV_RESULT__COLDBOOT_STATUS = 0x00DB, 279 | VHV_RESULT__SEARCH_RESULT = 0x00DC, 280 | VHV_RESULT__LATEST_SETTING = 0x00DD, 281 | RESULT__OSC_CALIBRATE_VAL = 0x00DE, 282 | RESULT__OSC_CALIBRATE_VAL_HI = 0x00DE, 283 | RESULT__OSC_CALIBRATE_VAL_LO = 0x00DF, 284 | ANA_CONFIG__POWERDOWN_GO1 = 0x00E0, 285 | ANA_CONFIG__REF_BG_CTRL = 0x00E1, 286 | ANA_CONFIG__REGDVDD1V2_CTRL = 0x00E2, 287 | ANA_CONFIG__OSC_SLOW_CTRL = 0x00E3, 288 | TEST_MODE__STATUS = 0x00E4, 289 | FIRMWARE__SYSTEM_STATUS = 0x00E5, 290 | FIRMWARE__MODE_STATUS = 0x00E6, 291 | FIRMWARE__SECONDARY_MODE_STATUS = 0x00E7, 292 | FIRMWARE__CAL_REPEAT_RATE_COUNTER = 0x00E8, 293 | FIRMWARE__CAL_REPEAT_RATE_COUNTER_HI = 0x00E8, 294 | FIRMWARE__CAL_REPEAT_RATE_COUNTER_LO = 0x00E9, 295 | FIRMWARE__HISTOGRAM_BIN = 0x00EA, 296 | GPH__SYSTEM__THRESH_HIGH = 0x00EC, 297 | GPH__SYSTEM__THRESH_HIGH_HI = 0x00EC, 298 | GPH__SYSTEM__THRESH_HIGH_LO = 0x00ED, 299 | GPH__SYSTEM__THRESH_LOW = 0x00EE, 300 | GPH__SYSTEM__THRESH_LOW_HI = 0x00EE, 301 | GPH__SYSTEM__THRESH_LOW_LO = 0x00EF, 302 | GPH__SYSTEM__ENABLE_XTALK_PER_QUADRANT = 0x00F0, 303 | GPH__SPARE_0 = 0x00F1, 304 | GPH__SD_CONFIG__WOI_SD0 = 0x00F2, 305 | GPH__SD_CONFIG__WOI_SD1 = 0x00F3, 306 | GPH__SD_CONFIG__INITIAL_PHASE_SD0 = 0x00F4, 307 | GPH__SD_CONFIG__INITIAL_PHASE_SD1 = 0x00F5, 308 | GPH__SD_CONFIG__FIRST_ORDER_SELECT = 0x00F6, 309 | GPH__SD_CONFIG__QUANTIFIER = 0x00F7, 310 | GPH__ROI_CONFIG__USER_ROI_CENTRE_SPAD = 0x00F8, 311 | GPH__ROI_CONFIG__USER_ROI_REQUESTED_GLOBAL_XY_SIZE = 0x00F9, 312 | GPH__SYSTEM__SEQUENCE_CONFIG = 0x00FA, 313 | GPH__GPH_ID = 0x00FB, 314 | SYSTEM__INTERRUPT_SET = 0x00FC, 315 | INTERRUPT_MANAGER__ENABLES = 0x00FD, 316 | INTERRUPT_MANAGER__CLEAR = 0x00FE, 317 | INTERRUPT_MANAGER__STATUS = 0x00FF, 318 | MCU_TO_HOST_BANK__WR_ACCESS_EN = 0x0100, 319 | POWER_MANAGEMENT__GO1_RESET_STATUS = 0x0101, 320 | PAD_STARTUP_MODE__VALUE_RO = 0x0102, 321 | PAD_STARTUP_MODE__VALUE_CTRL = 0x0103, 322 | PLL_PERIOD_US = 0x0104, 323 | PLL_PERIOD_US_3 = 0x0104, 324 | PLL_PERIOD_US_2 = 0x0105, 325 | PLL_PERIOD_US_1 = 0x0106, 326 | PLL_PERIOD_US_0 = 0x0107, 327 | INTERRUPT_SCHEDULER__DATA_OUT = 0x0108, 328 | INTERRUPT_SCHEDULER__DATA_OUT_3 = 0x0108, 329 | INTERRUPT_SCHEDULER__DATA_OUT_2 = 0x0109, 330 | INTERRUPT_SCHEDULER__DATA_OUT_1 = 0x010A, 331 | INTERRUPT_SCHEDULER__DATA_OUT_0 = 0x010B, 332 | NVM_BIST__COMPLETE = 0x010C, 333 | NVM_BIST__STATUS = 0x010D, 334 | IDENTIFICATION__MODEL_ID = 0x010F, 335 | IDENTIFICATION__MODULE_TYPE = 0x0110, 336 | IDENTIFICATION__REVISION_ID = 0x0111, 337 | IDENTIFICATION__MODULE_ID = 0x0112, 338 | IDENTIFICATION__MODULE_ID_HI = 0x0112, 339 | IDENTIFICATION__MODULE_ID_LO = 0x0113, 340 | ANA_CONFIG__FAST_OSC__TRIM_MAX = 0x0114, 341 | ANA_CONFIG__FAST_OSC__FREQ_SET = 0x0115, 342 | ANA_CONFIG__VCSEL_TRIM = 0x0116, 343 | ANA_CONFIG__VCSEL_SELION = 0x0117, 344 | ANA_CONFIG__VCSEL_SELION_MAX = 0x0118, 345 | PROTECTED_LASER_SAFETY__LOCK_BIT = 0x0119, 346 | LASER_SAFETY__KEY = 0x011A, 347 | LASER_SAFETY__KEY_RO = 0x011B, 348 | LASER_SAFETY__CLIP = 0x011C, 349 | LASER_SAFETY__MULT = 0x011D, 350 | GLOBAL_CONFIG__SPAD_ENABLES_RTN_0 = 0x011E, 351 | GLOBAL_CONFIG__SPAD_ENABLES_RTN_1 = 0x011F, 352 | GLOBAL_CONFIG__SPAD_ENABLES_RTN_2 = 0x0120, 353 | GLOBAL_CONFIG__SPAD_ENABLES_RTN_3 = 0x0121, 354 | GLOBAL_CONFIG__SPAD_ENABLES_RTN_4 = 0x0122, 355 | GLOBAL_CONFIG__SPAD_ENABLES_RTN_5 = 0x0123, 356 | GLOBAL_CONFIG__SPAD_ENABLES_RTN_6 = 0x0124, 357 | GLOBAL_CONFIG__SPAD_ENABLES_RTN_7 = 0x0125, 358 | GLOBAL_CONFIG__SPAD_ENABLES_RTN_8 = 0x0126, 359 | GLOBAL_CONFIG__SPAD_ENABLES_RTN_9 = 0x0127, 360 | GLOBAL_CONFIG__SPAD_ENABLES_RTN_10 = 0x0128, 361 | GLOBAL_CONFIG__SPAD_ENABLES_RTN_11 = 0x0129, 362 | GLOBAL_CONFIG__SPAD_ENABLES_RTN_12 = 0x012A, 363 | GLOBAL_CONFIG__SPAD_ENABLES_RTN_13 = 0x012B, 364 | GLOBAL_CONFIG__SPAD_ENABLES_RTN_14 = 0x012C, 365 | GLOBAL_CONFIG__SPAD_ENABLES_RTN_15 = 0x012D, 366 | GLOBAL_CONFIG__SPAD_ENABLES_RTN_16 = 0x012E, 367 | GLOBAL_CONFIG__SPAD_ENABLES_RTN_17 = 0x012F, 368 | GLOBAL_CONFIG__SPAD_ENABLES_RTN_18 = 0x0130, 369 | GLOBAL_CONFIG__SPAD_ENABLES_RTN_19 = 0x0131, 370 | GLOBAL_CONFIG__SPAD_ENABLES_RTN_20 = 0x0132, 371 | GLOBAL_CONFIG__SPAD_ENABLES_RTN_21 = 0x0133, 372 | GLOBAL_CONFIG__SPAD_ENABLES_RTN_22 = 0x0134, 373 | GLOBAL_CONFIG__SPAD_ENABLES_RTN_23 = 0x0135, 374 | GLOBAL_CONFIG__SPAD_ENABLES_RTN_24 = 0x0136, 375 | GLOBAL_CONFIG__SPAD_ENABLES_RTN_25 = 0x0137, 376 | GLOBAL_CONFIG__SPAD_ENABLES_RTN_26 = 0x0138, 377 | GLOBAL_CONFIG__SPAD_ENABLES_RTN_27 = 0x0139, 378 | GLOBAL_CONFIG__SPAD_ENABLES_RTN_28 = 0x013A, 379 | GLOBAL_CONFIG__SPAD_ENABLES_RTN_29 = 0x013B, 380 | GLOBAL_CONFIG__SPAD_ENABLES_RTN_30 = 0x013C, 381 | GLOBAL_CONFIG__SPAD_ENABLES_RTN_31 = 0x013D, 382 | ROI_CONFIG__MODE_ROI_CENTRE_SPAD = 0x013E, 383 | ROI_CONFIG__MODE_ROI_XY_SIZE = 0x013F, 384 | GO2_HOST_BANK_ACCESS__OVERRIDE = 0x0300, 385 | MCU_UTIL_MULTIPLIER__MULTIPLICAND = 0x0400, 386 | MCU_UTIL_MULTIPLIER__MULTIPLICAND_3 = 0x0400, 387 | MCU_UTIL_MULTIPLIER__MULTIPLICAND_2 = 0x0401, 388 | MCU_UTIL_MULTIPLIER__MULTIPLICAND_1 = 0x0402, 389 | MCU_UTIL_MULTIPLIER__MULTIPLICAND_0 = 0x0403, 390 | MCU_UTIL_MULTIPLIER__MULTIPLIER = 0x0404, 391 | MCU_UTIL_MULTIPLIER__MULTIPLIER_3 = 0x0404, 392 | MCU_UTIL_MULTIPLIER__MULTIPLIER_2 = 0x0405, 393 | MCU_UTIL_MULTIPLIER__MULTIPLIER_1 = 0x0406, 394 | MCU_UTIL_MULTIPLIER__MULTIPLIER_0 = 0x0407, 395 | MCU_UTIL_MULTIPLIER__PRODUCT_HI = 0x0408, 396 | MCU_UTIL_MULTIPLIER__PRODUCT_HI_3 = 0x0408, 397 | MCU_UTIL_MULTIPLIER__PRODUCT_HI_2 = 0x0409, 398 | MCU_UTIL_MULTIPLIER__PRODUCT_HI_1 = 0x040A, 399 | MCU_UTIL_MULTIPLIER__PRODUCT_HI_0 = 0x040B, 400 | MCU_UTIL_MULTIPLIER__PRODUCT_LO = 0x040C, 401 | MCU_UTIL_MULTIPLIER__PRODUCT_LO_3 = 0x040C, 402 | MCU_UTIL_MULTIPLIER__PRODUCT_LO_2 = 0x040D, 403 | MCU_UTIL_MULTIPLIER__PRODUCT_LO_1 = 0x040E, 404 | MCU_UTIL_MULTIPLIER__PRODUCT_LO_0 = 0x040F, 405 | MCU_UTIL_MULTIPLIER__START = 0x0410, 406 | MCU_UTIL_MULTIPLIER__STATUS = 0x0411, 407 | MCU_UTIL_DIVIDER__START = 0x0412, 408 | MCU_UTIL_DIVIDER__STATUS = 0x0413, 409 | MCU_UTIL_DIVIDER__DIVIDEND = 0x0414, 410 | MCU_UTIL_DIVIDER__DIVIDEND_3 = 0x0414, 411 | MCU_UTIL_DIVIDER__DIVIDEND_2 = 0x0415, 412 | MCU_UTIL_DIVIDER__DIVIDEND_1 = 0x0416, 413 | MCU_UTIL_DIVIDER__DIVIDEND_0 = 0x0417, 414 | MCU_UTIL_DIVIDER__DIVISOR = 0x0418, 415 | MCU_UTIL_DIVIDER__DIVISOR_3 = 0x0418, 416 | MCU_UTIL_DIVIDER__DIVISOR_2 = 0x0419, 417 | MCU_UTIL_DIVIDER__DIVISOR_1 = 0x041A, 418 | MCU_UTIL_DIVIDER__DIVISOR_0 = 0x041B, 419 | MCU_UTIL_DIVIDER__QUOTIENT = 0x041C, 420 | MCU_UTIL_DIVIDER__QUOTIENT_3 = 0x041C, 421 | MCU_UTIL_DIVIDER__QUOTIENT_2 = 0x041D, 422 | MCU_UTIL_DIVIDER__QUOTIENT_1 = 0x041E, 423 | MCU_UTIL_DIVIDER__QUOTIENT_0 = 0x041F, 424 | TIMER0__VALUE_IN = 0x0420, 425 | TIMER0__VALUE_IN_3 = 0x0420, 426 | TIMER0__VALUE_IN_2 = 0x0421, 427 | TIMER0__VALUE_IN_1 = 0x0422, 428 | TIMER0__VALUE_IN_0 = 0x0423, 429 | TIMER1__VALUE_IN = 0x0424, 430 | TIMER1__VALUE_IN_3 = 0x0424, 431 | TIMER1__VALUE_IN_2 = 0x0425, 432 | TIMER1__VALUE_IN_1 = 0x0426, 433 | TIMER1__VALUE_IN_0 = 0x0427, 434 | TIMER0__CTRL = 0x0428, 435 | TIMER1__CTRL = 0x0429, 436 | MCU_GENERAL_PURPOSE__GP_0 = 0x042C, 437 | MCU_GENERAL_PURPOSE__GP_1 = 0x042D, 438 | MCU_GENERAL_PURPOSE__GP_2 = 0x042E, 439 | MCU_GENERAL_PURPOSE__GP_3 = 0x042F, 440 | MCU_RANGE_CALC__CONFIG = 0x0430, 441 | MCU_RANGE_CALC__OFFSET_CORRECTED_RANGE = 0x0432, 442 | MCU_RANGE_CALC__OFFSET_CORRECTED_RANGE_HI = 0x0432, 443 | MCU_RANGE_CALC__OFFSET_CORRECTED_RANGE_LO = 0x0433, 444 | MCU_RANGE_CALC__SPARE_4 = 0x0434, 445 | MCU_RANGE_CALC__SPARE_4_3 = 0x0434, 446 | MCU_RANGE_CALC__SPARE_4_2 = 0x0435, 447 | MCU_RANGE_CALC__SPARE_4_1 = 0x0436, 448 | MCU_RANGE_CALC__SPARE_4_0 = 0x0437, 449 | MCU_RANGE_CALC__AMBIENT_DURATION_PRE_CALC = 0x0438, 450 | MCU_RANGE_CALC__AMBIENT_DURATION_PRE_CALC_HI = 0x0438, 451 | MCU_RANGE_CALC__AMBIENT_DURATION_PRE_CALC_LO = 0x0439, 452 | MCU_RANGE_CALC__ALGO_VCSEL_PERIOD = 0x043C, 453 | MCU_RANGE_CALC__SPARE_5 = 0x043D, 454 | MCU_RANGE_CALC__ALGO_TOTAL_PERIODS = 0x043E, 455 | MCU_RANGE_CALC__ALGO_TOTAL_PERIODS_HI = 0x043E, 456 | MCU_RANGE_CALC__ALGO_TOTAL_PERIODS_LO = 0x043F, 457 | MCU_RANGE_CALC__ALGO_ACCUM_PHASE = 0x0440, 458 | MCU_RANGE_CALC__ALGO_ACCUM_PHASE_3 = 0x0440, 459 | MCU_RANGE_CALC__ALGO_ACCUM_PHASE_2 = 0x0441, 460 | MCU_RANGE_CALC__ALGO_ACCUM_PHASE_1 = 0x0442, 461 | MCU_RANGE_CALC__ALGO_ACCUM_PHASE_0 = 0x0443, 462 | MCU_RANGE_CALC__ALGO_SIGNAL_EVENTS = 0x0444, 463 | MCU_RANGE_CALC__ALGO_SIGNAL_EVENTS_3 = 0x0444, 464 | MCU_RANGE_CALC__ALGO_SIGNAL_EVENTS_2 = 0x0445, 465 | MCU_RANGE_CALC__ALGO_SIGNAL_EVENTS_1 = 0x0446, 466 | MCU_RANGE_CALC__ALGO_SIGNAL_EVENTS_0 = 0x0447, 467 | MCU_RANGE_CALC__ALGO_AMBIENT_EVENTS = 0x0448, 468 | MCU_RANGE_CALC__ALGO_AMBIENT_EVENTS_3 = 0x0448, 469 | MCU_RANGE_CALC__ALGO_AMBIENT_EVENTS_2 = 0x0449, 470 | MCU_RANGE_CALC__ALGO_AMBIENT_EVENTS_1 = 0x044A, 471 | MCU_RANGE_CALC__ALGO_AMBIENT_EVENTS_0 = 0x044B, 472 | MCU_RANGE_CALC__SPARE_6 = 0x044C, 473 | MCU_RANGE_CALC__SPARE_6_HI = 0x044C, 474 | MCU_RANGE_CALC__SPARE_6_LO = 0x044D, 475 | MCU_RANGE_CALC__ALGO_ADJUST_VCSEL_PERIOD = 0x044E, 476 | MCU_RANGE_CALC__ALGO_ADJUST_VCSEL_PERIOD_HI = 0x044E, 477 | MCU_RANGE_CALC__ALGO_ADJUST_VCSEL_PERIOD_LO = 0x044F, 478 | MCU_RANGE_CALC__NUM_SPADS = 0x0450, 479 | MCU_RANGE_CALC__NUM_SPADS_HI = 0x0450, 480 | MCU_RANGE_CALC__NUM_SPADS_LO = 0x0451, 481 | MCU_RANGE_CALC__PHASE_OUTPUT = 0x0452, 482 | MCU_RANGE_CALC__PHASE_OUTPUT_HI = 0x0452, 483 | MCU_RANGE_CALC__PHASE_OUTPUT_LO = 0x0453, 484 | MCU_RANGE_CALC__RATE_PER_SPAD_MCPS = 0x0454, 485 | MCU_RANGE_CALC__RATE_PER_SPAD_MCPS_3 = 0x0454, 486 | MCU_RANGE_CALC__RATE_PER_SPAD_MCPS_2 = 0x0455, 487 | MCU_RANGE_CALC__RATE_PER_SPAD_MCPS_1 = 0x0456, 488 | MCU_RANGE_CALC__RATE_PER_SPAD_MCPS_0 = 0x0457, 489 | MCU_RANGE_CALC__SPARE_7 = 0x0458, 490 | MCU_RANGE_CALC__SPARE_8 = 0x0459, 491 | MCU_RANGE_CALC__PEAK_SIGNAL_RATE_MCPS = 0x045A, 492 | MCU_RANGE_CALC__PEAK_SIGNAL_RATE_MCPS_HI = 0x045A, 493 | MCU_RANGE_CALC__PEAK_SIGNAL_RATE_MCPS_LO = 0x045B, 494 | MCU_RANGE_CALC__AVG_SIGNAL_RATE_MCPS = 0x045C, 495 | MCU_RANGE_CALC__AVG_SIGNAL_RATE_MCPS_HI = 0x045C, 496 | MCU_RANGE_CALC__AVG_SIGNAL_RATE_MCPS_LO = 0x045D, 497 | MCU_RANGE_CALC__AMBIENT_RATE_MCPS = 0x045E, 498 | MCU_RANGE_CALC__AMBIENT_RATE_MCPS_HI = 0x045E, 499 | MCU_RANGE_CALC__AMBIENT_RATE_MCPS_LO = 0x045F, 500 | MCU_RANGE_CALC__XTALK = 0x0460, 501 | MCU_RANGE_CALC__XTALK_HI = 0x0460, 502 | MCU_RANGE_CALC__XTALK_LO = 0x0461, 503 | MCU_RANGE_CALC__CALC_STATUS = 0x0462, 504 | MCU_RANGE_CALC__DEBUG = 0x0463, 505 | MCU_RANGE_CALC__PEAK_SIGNAL_RATE_XTALK_CORR_MCPS = 0x0464, 506 | MCU_RANGE_CALC__PEAK_SIGNAL_RATE_XTALK_CORR_MCPS_HI = 0x0464, 507 | MCU_RANGE_CALC__PEAK_SIGNAL_RATE_XTALK_CORR_MCPS_LO = 0x0465, 508 | MCU_RANGE_CALC__SPARE_0 = 0x0468, 509 | MCU_RANGE_CALC__SPARE_1 = 0x0469, 510 | MCU_RANGE_CALC__SPARE_2 = 0x046A, 511 | MCU_RANGE_CALC__SPARE_3 = 0x046B, 512 | PATCH__CTRL = 0x0470, 513 | PATCH__JMP_ENABLES = 0x0472, 514 | PATCH__JMP_ENABLES_HI = 0x0472, 515 | PATCH__JMP_ENABLES_LO = 0x0473, 516 | PATCH__DATA_ENABLES = 0x0474, 517 | PATCH__DATA_ENABLES_HI = 0x0474, 518 | PATCH__DATA_ENABLES_LO = 0x0475, 519 | PATCH__OFFSET_0 = 0x0476, 520 | PATCH__OFFSET_0_HI = 0x0476, 521 | PATCH__OFFSET_0_LO = 0x0477, 522 | PATCH__OFFSET_1 = 0x0478, 523 | PATCH__OFFSET_1_HI = 0x0478, 524 | PATCH__OFFSET_1_LO = 0x0479, 525 | PATCH__OFFSET_2 = 0x047A, 526 | PATCH__OFFSET_2_HI = 0x047A, 527 | PATCH__OFFSET_2_LO = 0x047B, 528 | PATCH__OFFSET_3 = 0x047C, 529 | PATCH__OFFSET_3_HI = 0x047C, 530 | PATCH__OFFSET_3_LO = 0x047D, 531 | PATCH__OFFSET_4 = 0x047E, 532 | PATCH__OFFSET_4_HI = 0x047E, 533 | PATCH__OFFSET_4_LO = 0x047F, 534 | PATCH__OFFSET_5 = 0x0480, 535 | PATCH__OFFSET_5_HI = 0x0480, 536 | PATCH__OFFSET_5_LO = 0x0481, 537 | PATCH__OFFSET_6 = 0x0482, 538 | PATCH__OFFSET_6_HI = 0x0482, 539 | PATCH__OFFSET_6_LO = 0x0483, 540 | PATCH__OFFSET_7 = 0x0484, 541 | PATCH__OFFSET_7_HI = 0x0484, 542 | PATCH__OFFSET_7_LO = 0x0485, 543 | PATCH__OFFSET_8 = 0x0486, 544 | PATCH__OFFSET_8_HI = 0x0486, 545 | PATCH__OFFSET_8_LO = 0x0487, 546 | PATCH__OFFSET_9 = 0x0488, 547 | PATCH__OFFSET_9_HI = 0x0488, 548 | PATCH__OFFSET_9_LO = 0x0489, 549 | PATCH__OFFSET_10 = 0x048A, 550 | PATCH__OFFSET_10_HI = 0x048A, 551 | PATCH__OFFSET_10_LO = 0x048B, 552 | PATCH__OFFSET_11 = 0x048C, 553 | PATCH__OFFSET_11_HI = 0x048C, 554 | PATCH__OFFSET_11_LO = 0x048D, 555 | PATCH__OFFSET_12 = 0x048E, 556 | PATCH__OFFSET_12_HI = 0x048E, 557 | PATCH__OFFSET_12_LO = 0x048F, 558 | PATCH__OFFSET_13 = 0x0490, 559 | PATCH__OFFSET_13_HI = 0x0490, 560 | PATCH__OFFSET_13_LO = 0x0491, 561 | PATCH__OFFSET_14 = 0x0492, 562 | PATCH__OFFSET_14_HI = 0x0492, 563 | PATCH__OFFSET_14_LO = 0x0493, 564 | PATCH__OFFSET_15 = 0x0494, 565 | PATCH__OFFSET_15_HI = 0x0494, 566 | PATCH__OFFSET_15_LO = 0x0495, 567 | PATCH__ADDRESS_0 = 0x0496, 568 | PATCH__ADDRESS_0_HI = 0x0496, 569 | PATCH__ADDRESS_0_LO = 0x0497, 570 | PATCH__ADDRESS_1 = 0x0498, 571 | PATCH__ADDRESS_1_HI = 0x0498, 572 | PATCH__ADDRESS_1_LO = 0x0499, 573 | PATCH__ADDRESS_2 = 0x049A, 574 | PATCH__ADDRESS_2_HI = 0x049A, 575 | PATCH__ADDRESS_2_LO = 0x049B, 576 | PATCH__ADDRESS_3 = 0x049C, 577 | PATCH__ADDRESS_3_HI = 0x049C, 578 | PATCH__ADDRESS_3_LO = 0x049D, 579 | PATCH__ADDRESS_4 = 0x049E, 580 | PATCH__ADDRESS_4_HI = 0x049E, 581 | PATCH__ADDRESS_4_LO = 0x049F, 582 | PATCH__ADDRESS_5 = 0x04A0, 583 | PATCH__ADDRESS_5_HI = 0x04A0, 584 | PATCH__ADDRESS_5_LO = 0x04A1, 585 | PATCH__ADDRESS_6 = 0x04A2, 586 | PATCH__ADDRESS_6_HI = 0x04A2, 587 | PATCH__ADDRESS_6_LO = 0x04A3, 588 | PATCH__ADDRESS_7 = 0x04A4, 589 | PATCH__ADDRESS_7_HI = 0x04A4, 590 | PATCH__ADDRESS_7_LO = 0x04A5, 591 | PATCH__ADDRESS_8 = 0x04A6, 592 | PATCH__ADDRESS_8_HI = 0x04A6, 593 | PATCH__ADDRESS_8_LO = 0x04A7, 594 | PATCH__ADDRESS_9 = 0x04A8, 595 | PATCH__ADDRESS_9_HI = 0x04A8, 596 | PATCH__ADDRESS_9_LO = 0x04A9, 597 | PATCH__ADDRESS_10 = 0x04AA, 598 | PATCH__ADDRESS_10_HI = 0x04AA, 599 | PATCH__ADDRESS_10_LO = 0x04AB, 600 | PATCH__ADDRESS_11 = 0x04AC, 601 | PATCH__ADDRESS_11_HI = 0x04AC, 602 | PATCH__ADDRESS_11_LO = 0x04AD, 603 | PATCH__ADDRESS_12 = 0x04AE, 604 | PATCH__ADDRESS_12_HI = 0x04AE, 605 | PATCH__ADDRESS_12_LO = 0x04AF, 606 | PATCH__ADDRESS_13 = 0x04B0, 607 | PATCH__ADDRESS_13_HI = 0x04B0, 608 | PATCH__ADDRESS_13_LO = 0x04B1, 609 | PATCH__ADDRESS_14 = 0x04B2, 610 | PATCH__ADDRESS_14_HI = 0x04B2, 611 | PATCH__ADDRESS_14_LO = 0x04B3, 612 | PATCH__ADDRESS_15 = 0x04B4, 613 | PATCH__ADDRESS_15_HI = 0x04B4, 614 | PATCH__ADDRESS_15_LO = 0x04B5, 615 | SPI_ASYNC_MUX__CTRL = 0x04C0, 616 | CLK__CONFIG = 0x04C4, 617 | GPIO_LV_MUX__CTRL = 0x04CC, 618 | GPIO_LV_PAD__CTRL = 0x04CD, 619 | PAD_I2C_LV__CONFIG = 0x04D0, 620 | PAD_STARTUP_MODE__VALUE_RO_GO1 = 0x04D4, 621 | HOST_IF__STATUS_GO1 = 0x04D5, 622 | MCU_CLK_GATING__CTRL = 0x04D8, 623 | TEST__BIST_ROM_CTRL = 0x04E0, 624 | TEST__BIST_ROM_RESULT = 0x04E1, 625 | TEST__BIST_ROM_MCU_SIG = 0x04E2, 626 | TEST__BIST_ROM_MCU_SIG_HI = 0x04E2, 627 | TEST__BIST_ROM_MCU_SIG_LO = 0x04E3, 628 | TEST__BIST_RAM_CTRL = 0x04E4, 629 | TEST__BIST_RAM_RESULT = 0x04E5, 630 | TEST__TMC = 0x04E8, 631 | TEST__PLL_BIST_MIN_THRESHOLD = 0x04F0, 632 | TEST__PLL_BIST_MIN_THRESHOLD_HI = 0x04F0, 633 | TEST__PLL_BIST_MIN_THRESHOLD_LO = 0x04F1, 634 | TEST__PLL_BIST_MAX_THRESHOLD = 0x04F2, 635 | TEST__PLL_BIST_MAX_THRESHOLD_HI = 0x04F2, 636 | TEST__PLL_BIST_MAX_THRESHOLD_LO = 0x04F3, 637 | TEST__PLL_BIST_COUNT_OUT = 0x04F4, 638 | TEST__PLL_BIST_COUNT_OUT_HI = 0x04F4, 639 | TEST__PLL_BIST_COUNT_OUT_LO = 0x04F5, 640 | TEST__PLL_BIST_GONOGO = 0x04F6, 641 | TEST__PLL_BIST_CTRL = 0x04F7, 642 | RANGING_CORE__DEVICE_ID = 0x0680, 643 | RANGING_CORE__REVISION_ID = 0x0681, 644 | RANGING_CORE__CLK_CTRL1 = 0x0683, 645 | RANGING_CORE__CLK_CTRL2 = 0x0684, 646 | RANGING_CORE__WOI_1 = 0x0685, 647 | RANGING_CORE__WOI_REF_1 = 0x0686, 648 | RANGING_CORE__START_RANGING = 0x0687, 649 | RANGING_CORE__LOW_LIMIT_1 = 0x0690, 650 | RANGING_CORE__HIGH_LIMIT_1 = 0x0691, 651 | RANGING_CORE__LOW_LIMIT_REF_1 = 0x0692, 652 | RANGING_CORE__HIGH_LIMIT_REF_1 = 0x0693, 653 | RANGING_CORE__QUANTIFIER_1_MSB = 0x0694, 654 | RANGING_CORE__QUANTIFIER_1_LSB = 0x0695, 655 | RANGING_CORE__QUANTIFIER_REF_1_MSB = 0x0696, 656 | RANGING_CORE__QUANTIFIER_REF_1_LSB = 0x0697, 657 | RANGING_CORE__AMBIENT_OFFSET_1_MSB = 0x0698, 658 | RANGING_CORE__AMBIENT_OFFSET_1_LSB = 0x0699, 659 | RANGING_CORE__AMBIENT_OFFSET_REF_1_MSB = 0x069A, 660 | RANGING_CORE__AMBIENT_OFFSET_REF_1_LSB = 0x069B, 661 | RANGING_CORE__FILTER_STRENGTH_1 = 0x069C, 662 | RANGING_CORE__FILTER_STRENGTH_REF_1 = 0x069D, 663 | RANGING_CORE__SIGNAL_EVENT_LIMIT_1_MSB = 0x069E, 664 | RANGING_CORE__SIGNAL_EVENT_LIMIT_1_LSB = 0x069F, 665 | RANGING_CORE__SIGNAL_EVENT_LIMIT_REF_1_MSB = 0x06A0, 666 | RANGING_CORE__SIGNAL_EVENT_LIMIT_REF_1_LSB = 0x06A1, 667 | RANGING_CORE__TIMEOUT_OVERALL_PERIODS_MSB = 0x06A4, 668 | RANGING_CORE__TIMEOUT_OVERALL_PERIODS_LSB = 0x06A5, 669 | RANGING_CORE__INVERT_HW = 0x06A6, 670 | RANGING_CORE__FORCE_HW = 0x06A7, 671 | RANGING_CORE__STATIC_HW_VALUE = 0x06A8, 672 | RANGING_CORE__FORCE_CONTINUOUS_AMBIENT = 0x06A9, 673 | RANGING_CORE__TEST_PHASE_SELECT_TO_FILTER = 0x06AA, 674 | RANGING_CORE__TEST_PHASE_SELECT_TO_TIMING_GEN = 0x06AB, 675 | RANGING_CORE__INITIAL_PHASE_VALUE_1 = 0x06AC, 676 | RANGING_CORE__INITIAL_PHASE_VALUE_REF_1 = 0x06AD, 677 | RANGING_CORE__FORCE_UP_IN = 0x06AE, 678 | RANGING_CORE__FORCE_DN_IN = 0x06AF, 679 | RANGING_CORE__STATIC_UP_VALUE_1 = 0x06B0, 680 | RANGING_CORE__STATIC_UP_VALUE_REF_1 = 0x06B1, 681 | RANGING_CORE__STATIC_DN_VALUE_1 = 0x06B2, 682 | RANGING_CORE__STATIC_DN_VALUE_REF_1 = 0x06B3, 683 | RANGING_CORE__MONITOR_UP_DN = 0x06B4, 684 | RANGING_CORE__INVERT_UP_DN = 0x06B5, 685 | RANGING_CORE__CPUMP_1 = 0x06B6, 686 | RANGING_CORE__CPUMP_2 = 0x06B7, 687 | RANGING_CORE__CPUMP_3 = 0x06B8, 688 | RANGING_CORE__OSC_1 = 0x06B9, 689 | RANGING_CORE__PLL_1 = 0x06BB, 690 | RANGING_CORE__PLL_2 = 0x06BC, 691 | RANGING_CORE__REFERENCE_1 = 0x06BD, 692 | RANGING_CORE__REFERENCE_3 = 0x06BF, 693 | RANGING_CORE__REFERENCE_4 = 0x06C0, 694 | RANGING_CORE__REFERENCE_5 = 0x06C1, 695 | RANGING_CORE__REGAVDD1V2 = 0x06C3, 696 | RANGING_CORE__CALIB_1 = 0x06C4, 697 | RANGING_CORE__CALIB_2 = 0x06C5, 698 | RANGING_CORE__CALIB_3 = 0x06C6, 699 | RANGING_CORE__TST_MUX_SEL1 = 0x06C9, 700 | RANGING_CORE__TST_MUX_SEL2 = 0x06CA, 701 | RANGING_CORE__TST_MUX = 0x06CB, 702 | RANGING_CORE__GPIO_OUT_TESTMUX = 0x06CC, 703 | RANGING_CORE__CUSTOM_FE = 0x06CD, 704 | RANGING_CORE__CUSTOM_FE_2 = 0x06CE, 705 | RANGING_CORE__SPAD_READOUT = 0x06CF, 706 | RANGING_CORE__SPAD_READOUT_1 = 0x06D0, 707 | RANGING_CORE__SPAD_READOUT_2 = 0x06D1, 708 | RANGING_CORE__SPAD_PS = 0x06D2, 709 | RANGING_CORE__LASER_SAFETY_2 = 0x06D4, 710 | RANGING_CORE__NVM_CTRL__MODE = 0x0780, 711 | RANGING_CORE__NVM_CTRL__PDN = 0x0781, 712 | RANGING_CORE__NVM_CTRL__PROGN = 0x0782, 713 | RANGING_CORE__NVM_CTRL__READN = 0x0783, 714 | RANGING_CORE__NVM_CTRL__PULSE_WIDTH_MSB = 0x0784, 715 | RANGING_CORE__NVM_CTRL__PULSE_WIDTH_LSB = 0x0785, 716 | RANGING_CORE__NVM_CTRL__HV_RISE_MSB = 0x0786, 717 | RANGING_CORE__NVM_CTRL__HV_RISE_LSB = 0x0787, 718 | RANGING_CORE__NVM_CTRL__HV_FALL_MSB = 0x0788, 719 | RANGING_CORE__NVM_CTRL__HV_FALL_LSB = 0x0789, 720 | RANGING_CORE__NVM_CTRL__TST = 0x078A, 721 | RANGING_CORE__NVM_CTRL__TESTREAD = 0x078B, 722 | RANGING_CORE__NVM_CTRL__DATAIN_MMM = 0x078C, 723 | RANGING_CORE__NVM_CTRL__DATAIN_LMM = 0x078D, 724 | RANGING_CORE__NVM_CTRL__DATAIN_LLM = 0x078E, 725 | RANGING_CORE__NVM_CTRL__DATAIN_LLL = 0x078F, 726 | RANGING_CORE__NVM_CTRL__DATAOUT_MMM = 0x0790, 727 | RANGING_CORE__NVM_CTRL__DATAOUT_LMM = 0x0791, 728 | RANGING_CORE__NVM_CTRL__DATAOUT_LLM = 0x0792, 729 | RANGING_CORE__NVM_CTRL__DATAOUT_LLL = 0x0793, 730 | RANGING_CORE__NVM_CTRL__ADDR = 0x0794, 731 | RANGING_CORE__NVM_CTRL__DATAOUT_ECC = 0x0795, 732 | RANGING_CORE__RET_SPAD_EN_0 = 0x0796, 733 | RANGING_CORE__RET_SPAD_EN_1 = 0x0797, 734 | RANGING_CORE__RET_SPAD_EN_2 = 0x0798, 735 | RANGING_CORE__RET_SPAD_EN_3 = 0x0799, 736 | RANGING_CORE__RET_SPAD_EN_4 = 0x079A, 737 | RANGING_CORE__RET_SPAD_EN_5 = 0x079B, 738 | RANGING_CORE__RET_SPAD_EN_6 = 0x079C, 739 | RANGING_CORE__RET_SPAD_EN_7 = 0x079D, 740 | RANGING_CORE__RET_SPAD_EN_8 = 0x079E, 741 | RANGING_CORE__RET_SPAD_EN_9 = 0x079F, 742 | RANGING_CORE__RET_SPAD_EN_10 = 0x07A0, 743 | RANGING_CORE__RET_SPAD_EN_11 = 0x07A1, 744 | RANGING_CORE__RET_SPAD_EN_12 = 0x07A2, 745 | RANGING_CORE__RET_SPAD_EN_13 = 0x07A3, 746 | RANGING_CORE__RET_SPAD_EN_14 = 0x07A4, 747 | RANGING_CORE__RET_SPAD_EN_15 = 0x07A5, 748 | RANGING_CORE__RET_SPAD_EN_16 = 0x07A6, 749 | RANGING_CORE__RET_SPAD_EN_17 = 0x07A7, 750 | RANGING_CORE__SPAD_SHIFT_EN = 0x07BA, 751 | RANGING_CORE__SPAD_DISABLE_CTRL = 0x07BB, 752 | RANGING_CORE__SPAD_EN_SHIFT_OUT_DEBUG = 0x07BC, 753 | RANGING_CORE__SPI_MODE = 0x07BD, 754 | RANGING_CORE__GPIO_DIR = 0x07BE, 755 | RANGING_CORE__VCSEL_PERIOD = 0x0880, 756 | RANGING_CORE__VCSEL_START = 0x0881, 757 | RANGING_CORE__VCSEL_STOP = 0x0882, 758 | RANGING_CORE__VCSEL_1 = 0x0885, 759 | RANGING_CORE__VCSEL_STATUS = 0x088D, 760 | RANGING_CORE__STATUS = 0x0980, 761 | RANGING_CORE__LASER_CONTINUITY_STATE = 0x0981, 762 | RANGING_CORE__RANGE_1_MMM = 0x0982, 763 | RANGING_CORE__RANGE_1_LMM = 0x0983, 764 | RANGING_CORE__RANGE_1_LLM = 0x0984, 765 | RANGING_CORE__RANGE_1_LLL = 0x0985, 766 | RANGING_CORE__RANGE_REF_1_MMM = 0x0986, 767 | RANGING_CORE__RANGE_REF_1_LMM = 0x0987, 768 | RANGING_CORE__RANGE_REF_1_LLM = 0x0988, 769 | RANGING_CORE__RANGE_REF_1_LLL = 0x0989, 770 | RANGING_CORE__AMBIENT_WINDOW_EVENTS_1_MMM = 0x098A, 771 | RANGING_CORE__AMBIENT_WINDOW_EVENTS_1_LMM = 0x098B, 772 | RANGING_CORE__AMBIENT_WINDOW_EVENTS_1_LLM = 0x098C, 773 | RANGING_CORE__AMBIENT_WINDOW_EVENTS_1_LLL = 0x098D, 774 | RANGING_CORE__RANGING_TOTAL_EVENTS_1_MMM = 0x098E, 775 | RANGING_CORE__RANGING_TOTAL_EVENTS_1_LMM = 0x098F, 776 | RANGING_CORE__RANGING_TOTAL_EVENTS_1_LLM = 0x0990, 777 | RANGING_CORE__RANGING_TOTAL_EVENTS_1_LLL = 0x0991, 778 | RANGING_CORE__SIGNAL_TOTAL_EVENTS_1_MMM = 0x0992, 779 | RANGING_CORE__SIGNAL_TOTAL_EVENTS_1_LMM = 0x0993, 780 | RANGING_CORE__SIGNAL_TOTAL_EVENTS_1_LLM = 0x0994, 781 | RANGING_CORE__SIGNAL_TOTAL_EVENTS_1_LLL = 0x0995, 782 | RANGING_CORE__TOTAL_PERIODS_ELAPSED_1_MM = 0x0996, 783 | RANGING_CORE__TOTAL_PERIODS_ELAPSED_1_LM = 0x0997, 784 | RANGING_CORE__TOTAL_PERIODS_ELAPSED_1_LL = 0x0998, 785 | RANGING_CORE__AMBIENT_MISMATCH_MM = 0x0999, 786 | RANGING_CORE__AMBIENT_MISMATCH_LM = 0x099A, 787 | RANGING_CORE__AMBIENT_MISMATCH_LL = 0x099B, 788 | RANGING_CORE__AMBIENT_WINDOW_EVENTS_REF_1_MMM = 0x099C, 789 | RANGING_CORE__AMBIENT_WINDOW_EVENTS_REF_1_LMM = 0x099D, 790 | RANGING_CORE__AMBIENT_WINDOW_EVENTS_REF_1_LLM = 0x099E, 791 | RANGING_CORE__AMBIENT_WINDOW_EVENTS_REF_1_LLL = 0x099F, 792 | RANGING_CORE__RANGING_TOTAL_EVENTS_REF_1_MMM = 0x09A0, 793 | RANGING_CORE__RANGING_TOTAL_EVENTS_REF_1_LMM = 0x09A1, 794 | RANGING_CORE__RANGING_TOTAL_EVENTS_REF_1_LLM = 0x09A2, 795 | RANGING_CORE__RANGING_TOTAL_EVENTS_REF_1_LLL = 0x09A3, 796 | RANGING_CORE__SIGNAL_TOTAL_EVENTS_REF_1_MMM = 0x09A4, 797 | RANGING_CORE__SIGNAL_TOTAL_EVENTS_REF_1_LMM = 0x09A5, 798 | RANGING_CORE__SIGNAL_TOTAL_EVENTS_REF_1_LLM = 0x09A6, 799 | RANGING_CORE__SIGNAL_TOTAL_EVENTS_REF_1_LLL = 0x09A7, 800 | RANGING_CORE__TOTAL_PERIODS_ELAPSED_REF_1_MM = 0x09A8, 801 | RANGING_CORE__TOTAL_PERIODS_ELAPSED_REF_1_LM = 0x09A9, 802 | RANGING_CORE__TOTAL_PERIODS_ELAPSED_REF_1_LL = 0x09AA, 803 | RANGING_CORE__AMBIENT_MISMATCH_REF_MM = 0x09AB, 804 | RANGING_CORE__AMBIENT_MISMATCH_REF_LM = 0x09AC, 805 | RANGING_CORE__AMBIENT_MISMATCH_REF_LL = 0x09AD, 806 | RANGING_CORE__GPIO_CONFIG__A0 = 0x0A00, 807 | RANGING_CORE__RESET_CONTROL__A0 = 0x0A01, 808 | RANGING_CORE__INTR_MANAGER__A0 = 0x0A02, 809 | RANGING_CORE__POWER_FSM_TIME_OSC__A0 = 0x0A06, 810 | RANGING_CORE__VCSEL_ATEST__A0 = 0x0A07, 811 | RANGING_CORE__VCSEL_PERIOD_CLIPPED__A0 = 0x0A08, 812 | RANGING_CORE__VCSEL_STOP_CLIPPED__A0 = 0x0A09, 813 | RANGING_CORE__CALIB_2__A0 = 0x0A0A, 814 | RANGING_CORE__STOP_CONDITION__A0 = 0x0A0B, 815 | RANGING_CORE__STATUS_RESET__A0 = 0x0A0C, 816 | RANGING_CORE__READOUT_CFG__A0 = 0x0A0D, 817 | RANGING_CORE__WINDOW_SETTING__A0 = 0x0A0E, 818 | RANGING_CORE__VCSEL_DELAY__A0 = 0x0A1A, 819 | RANGING_CORE__REFERENCE_2__A0 = 0x0A1B, 820 | RANGING_CORE__REGAVDD1V2__A0 = 0x0A1D, 821 | RANGING_CORE__TST_MUX__A0 = 0x0A1F, 822 | RANGING_CORE__CUSTOM_FE_2__A0 = 0x0A20, 823 | RANGING_CORE__SPAD_READOUT__A0 = 0x0A21, 824 | RANGING_CORE__CPUMP_1__A0 = 0x0A22, 825 | RANGING_CORE__SPARE_REGISTER__A0 = 0x0A23, 826 | RANGING_CORE__VCSEL_CONT_STAGE5_BYPASS__A0 = 0x0A24, 827 | RANGING_CORE__RET_SPAD_EN_18 = 0x0A25, 828 | RANGING_CORE__RET_SPAD_EN_19 = 0x0A26, 829 | RANGING_CORE__RET_SPAD_EN_20 = 0x0A27, 830 | RANGING_CORE__RET_SPAD_EN_21 = 0x0A28, 831 | RANGING_CORE__RET_SPAD_EN_22 = 0x0A29, 832 | RANGING_CORE__RET_SPAD_EN_23 = 0x0A2A, 833 | RANGING_CORE__RET_SPAD_EN_24 = 0x0A2B, 834 | RANGING_CORE__RET_SPAD_EN_25 = 0x0A2C, 835 | RANGING_CORE__RET_SPAD_EN_26 = 0x0A2D, 836 | RANGING_CORE__RET_SPAD_EN_27 = 0x0A2E, 837 | RANGING_CORE__RET_SPAD_EN_28 = 0x0A2F, 838 | RANGING_CORE__RET_SPAD_EN_29 = 0x0A30, 839 | RANGING_CORE__RET_SPAD_EN_30 = 0x0A31, 840 | RANGING_CORE__RET_SPAD_EN_31 = 0x0A32, 841 | RANGING_CORE__REF_SPAD_EN_0__EWOK = 0x0A33, 842 | RANGING_CORE__REF_SPAD_EN_1__EWOK = 0x0A34, 843 | RANGING_CORE__REF_SPAD_EN_2__EWOK = 0x0A35, 844 | RANGING_CORE__REF_SPAD_EN_3__EWOK = 0x0A36, 845 | RANGING_CORE__REF_SPAD_EN_4__EWOK = 0x0A37, 846 | RANGING_CORE__REF_SPAD_EN_5__EWOK = 0x0A38, 847 | RANGING_CORE__REF_EN_START_SELECT = 0x0A39, 848 | RANGING_CORE__REGDVDD1V2_ATEST__EWOK = 0x0A41, 849 | SOFT_RESET_GO1 = 0x0B00, 850 | PRIVATE__PATCH_BASE_ADDR_RSLV = 0x0E00, 851 | PREV_SHADOW_RESULT__INTERRUPT_STATUS = 0x0ED0, 852 | PREV_SHADOW_RESULT__RANGE_STATUS = 0x0ED1, 853 | PREV_SHADOW_RESULT__REPORT_STATUS = 0x0ED2, 854 | PREV_SHADOW_RESULT__STREAM_COUNT = 0x0ED3, 855 | PREV_SHADOW_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0 = 0x0ED4, 856 | PREV_SHADOW_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0_HI = 0x0ED4, 857 | PREV_SHADOW_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0_LO = 0x0ED5, 858 | PREV_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD0 = 0x0ED6, 859 | PREV_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD0_HI = 0x0ED6, 860 | PREV_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD0_LO = 0x0ED7, 861 | PREV_SHADOW_RESULT__AMBIENT_COUNT_RATE_MCPS_SD0 = 0x0ED8, 862 | PREV_SHADOW_RESULT__AMBIENT_COUNT_RATE_MCPS_SD0_HI = 0x0ED8, 863 | PREV_SHADOW_RESULT__AMBIENT_COUNT_RATE_MCPS_SD0_LO = 0x0ED9, 864 | PREV_SHADOW_RESULT__SIGMA_SD0 = 0x0EDA, 865 | PREV_SHADOW_RESULT__SIGMA_SD0_HI = 0x0EDA, 866 | PREV_SHADOW_RESULT__SIGMA_SD0_LO = 0x0EDB, 867 | PREV_SHADOW_RESULT__PHASE_SD0 = 0x0EDC, 868 | PREV_SHADOW_RESULT__PHASE_SD0_HI = 0x0EDC, 869 | PREV_SHADOW_RESULT__PHASE_SD0_LO = 0x0EDD, 870 | PREV_SHADOW_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0 = 0x0EDE, 871 | PREV_SHADOW_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0_HI = 0x0EDE, 872 | PREV_SHADOW_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0_LO = 0x0EDF, 873 | PREV_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0 = 0x0EE0, 874 | PREV_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0_HI = 0x0EE0, 875 | PREV_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0_LO = 0x0EE1, 876 | PREV_SHADOW_RESULT__MM_INNER_ACTUAL_EFFECTIVE_SPADS_SD0 = 0x0EE2, 877 | PREV_SHADOW_RESULT__MM_INNER_ACTUAL_EFFECTIVE_SPADS_SD0_HI = 0x0EE2, 878 | PREV_SHADOW_RESULT__MM_INNER_ACTUAL_EFFECTIVE_SPADS_SD0_LO = 0x0EE3, 879 | PREV_SHADOW_RESULT__MM_OUTER_ACTUAL_EFFECTIVE_SPADS_SD0 = 0x0EE4, 880 | PREV_SHADOW_RESULT__MM_OUTER_ACTUAL_EFFECTIVE_SPADS_SD0_HI = 0x0EE4, 881 | PREV_SHADOW_RESULT__MM_OUTER_ACTUAL_EFFECTIVE_SPADS_SD0_LO = 0x0EE5, 882 | PREV_SHADOW_RESULT__AVG_SIGNAL_COUNT_RATE_MCPS_SD0 = 0x0EE6, 883 | PREV_SHADOW_RESULT__AVG_SIGNAL_COUNT_RATE_MCPS_SD0_HI = 0x0EE6, 884 | PREV_SHADOW_RESULT__AVG_SIGNAL_COUNT_RATE_MCPS_SD0_LO = 0x0EE7, 885 | PREV_SHADOW_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD1 = 0x0EE8, 886 | PREV_SHADOW_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD1_HI = 0x0EE8, 887 | PREV_SHADOW_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD1_LO = 0x0EE9, 888 | PREV_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD1 = 0x0EEA, 889 | PREV_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD1_HI = 0x0EEA, 890 | PREV_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD1_LO = 0x0EEB, 891 | PREV_SHADOW_RESULT__AMBIENT_COUNT_RATE_MCPS_SD1 = 0x0EEC, 892 | PREV_SHADOW_RESULT__AMBIENT_COUNT_RATE_MCPS_SD1_HI = 0x0EEC, 893 | PREV_SHADOW_RESULT__AMBIENT_COUNT_RATE_MCPS_SD1_LO = 0x0EED, 894 | PREV_SHADOW_RESULT__SIGMA_SD1 = 0x0EEE, 895 | PREV_SHADOW_RESULT__SIGMA_SD1_HI = 0x0EEE, 896 | PREV_SHADOW_RESULT__SIGMA_SD1_LO = 0x0EEF, 897 | PREV_SHADOW_RESULT__PHASE_SD1 = 0x0EF0, 898 | PREV_SHADOW_RESULT__PHASE_SD1_HI = 0x0EF0, 899 | PREV_SHADOW_RESULT__PHASE_SD1_LO = 0x0EF1, 900 | PREV_SHADOW_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD1 = 0x0EF2, 901 | PREV_SHADOW_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD1_HI = 0x0EF2, 902 | PREV_SHADOW_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD1_LO = 0x0EF3, 903 | PREV_SHADOW_RESULT__SPARE_0_SD1 = 0x0EF4, 904 | PREV_SHADOW_RESULT__SPARE_0_SD1_HI = 0x0EF4, 905 | PREV_SHADOW_RESULT__SPARE_0_SD1_LO = 0x0EF5, 906 | PREV_SHADOW_RESULT__SPARE_1_SD1 = 0x0EF6, 907 | PREV_SHADOW_RESULT__SPARE_1_SD1_HI = 0x0EF6, 908 | PREV_SHADOW_RESULT__SPARE_1_SD1_LO = 0x0EF7, 909 | PREV_SHADOW_RESULT__SPARE_2_SD1 = 0x0EF8, 910 | PREV_SHADOW_RESULT__SPARE_2_SD1_HI = 0x0EF8, 911 | PREV_SHADOW_RESULT__SPARE_2_SD1_LO = 0x0EF9, 912 | PREV_SHADOW_RESULT__SPARE_3_SD1 = 0x0EFA, 913 | PREV_SHADOW_RESULT__SPARE_3_SD1_HI = 0x0EFA, 914 | PREV_SHADOW_RESULT__SPARE_3_SD1_LO = 0x0EFB, 915 | PREV_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0 = 0x0EFC, 916 | PREV_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0_3 = 0x0EFC, 917 | PREV_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0_2 = 0x0EFD, 918 | PREV_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0_1 = 0x0EFE, 919 | PREV_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0_0 = 0x0EFF, 920 | PREV_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0 = 0x0F00, 921 | PREV_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0_3 = 0x0F00, 922 | PREV_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0_2 = 0x0F01, 923 | PREV_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0_1 = 0x0F02, 924 | PREV_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0_0 = 0x0F03, 925 | PREV_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0 = 0x0F04, 926 | PREV_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0_3 = 0x0F04, 927 | PREV_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0_2 = 0x0F05, 928 | PREV_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0_1 = 0x0F06, 929 | PREV_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0_0 = 0x0F07, 930 | PREV_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0 = 0x0F08, 931 | PREV_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0_3 = 0x0F08, 932 | PREV_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0_2 = 0x0F09, 933 | PREV_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0_1 = 0x0F0A, 934 | PREV_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0_0 = 0x0F0B, 935 | PREV_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1 = 0x0F0C, 936 | PREV_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1_3 = 0x0F0C, 937 | PREV_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1_2 = 0x0F0D, 938 | PREV_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1_1 = 0x0F0E, 939 | PREV_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1_0 = 0x0F0F, 940 | PREV_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1 = 0x0F10, 941 | PREV_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1_3 = 0x0F10, 942 | PREV_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1_2 = 0x0F11, 943 | PREV_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1_1 = 0x0F12, 944 | PREV_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1_0 = 0x0F13, 945 | PREV_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1 = 0x0F14, 946 | PREV_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1_3 = 0x0F14, 947 | PREV_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1_2 = 0x0F15, 948 | PREV_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1_1 = 0x0F16, 949 | PREV_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1_0 = 0x0F17, 950 | PREV_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1 = 0x0F18, 951 | PREV_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1_3 = 0x0F18, 952 | PREV_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1_2 = 0x0F19, 953 | PREV_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1_1 = 0x0F1A, 954 | PREV_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1_0 = 0x0F1B, 955 | PREV_SHADOW_RESULT_CORE__SPARE_0 = 0x0F1C, 956 | RESULT__DEBUG_STATUS = 0x0F20, 957 | RESULT__DEBUG_STAGE = 0x0F21, 958 | GPH__SYSTEM__THRESH_RATE_HIGH = 0x0F24, 959 | GPH__SYSTEM__THRESH_RATE_HIGH_HI = 0x0F24, 960 | GPH__SYSTEM__THRESH_RATE_HIGH_LO = 0x0F25, 961 | GPH__SYSTEM__THRESH_RATE_LOW = 0x0F26, 962 | GPH__SYSTEM__THRESH_RATE_LOW_HI = 0x0F26, 963 | GPH__SYSTEM__THRESH_RATE_LOW_LO = 0x0F27, 964 | GPH__SYSTEM__INTERRUPT_CONFIG_GPIO = 0x0F28, 965 | GPH__DSS_CONFIG__ROI_MODE_CONTROL = 0x0F2F, 966 | GPH__DSS_CONFIG__MANUAL_EFFECTIVE_SPADS_SELECT = 0x0F30, 967 | GPH__DSS_CONFIG__MANUAL_EFFECTIVE_SPADS_SELECT_HI = 0x0F30, 968 | GPH__DSS_CONFIG__MANUAL_EFFECTIVE_SPADS_SELECT_LO = 0x0F31, 969 | GPH__DSS_CONFIG__MANUAL_BLOCK_SELECT = 0x0F32, 970 | GPH__DSS_CONFIG__MAX_SPADS_LIMIT = 0x0F33, 971 | GPH__DSS_CONFIG__MIN_SPADS_LIMIT = 0x0F34, 972 | GPH__MM_CONFIG__TIMEOUT_MACROP_A_HI = 0x0F36, 973 | GPH__MM_CONFIG__TIMEOUT_MACROP_A_LO = 0x0F37, 974 | GPH__MM_CONFIG__TIMEOUT_MACROP_B_HI = 0x0F38, 975 | GPH__MM_CONFIG__TIMEOUT_MACROP_B_LO = 0x0F39, 976 | GPH__RANGE_CONFIG__TIMEOUT_MACROP_A_HI = 0x0F3A, 977 | GPH__RANGE_CONFIG__TIMEOUT_MACROP_A_LO = 0x0F3B, 978 | GPH__RANGE_CONFIG__VCSEL_PERIOD_A = 0x0F3C, 979 | GPH__RANGE_CONFIG__VCSEL_PERIOD_B = 0x0F3D, 980 | GPH__RANGE_CONFIG__TIMEOUT_MACROP_B_HI = 0x0F3E, 981 | GPH__RANGE_CONFIG__TIMEOUT_MACROP_B_LO = 0x0F3F, 982 | GPH__RANGE_CONFIG__SIGMA_THRESH = 0x0F40, 983 | GPH__RANGE_CONFIG__SIGMA_THRESH_HI = 0x0F40, 984 | GPH__RANGE_CONFIG__SIGMA_THRESH_LO = 0x0F41, 985 | GPH__RANGE_CONFIG__MIN_COUNT_RATE_RTN_LIMIT_MCPS = 0x0F42, 986 | GPH__RANGE_CONFIG__MIN_COUNT_RATE_RTN_LIMIT_MCPS_HI = 0x0F42, 987 | GPH__RANGE_CONFIG__MIN_COUNT_RATE_RTN_LIMIT_MCPS_LO = 0x0F43, 988 | GPH__RANGE_CONFIG__VALID_PHASE_LOW = 0x0F44, 989 | GPH__RANGE_CONFIG__VALID_PHASE_HIGH = 0x0F45, 990 | FIRMWARE__INTERNAL_STREAM_COUNT_DIV = 0x0F46, 991 | FIRMWARE__INTERNAL_STREAM_COUNTER_VAL = 0x0F47, 992 | DSS_CALC__ROI_CTRL = 0x0F54, 993 | DSS_CALC__SPARE_1 = 0x0F55, 994 | DSS_CALC__SPARE_2 = 0x0F56, 995 | DSS_CALC__SPARE_3 = 0x0F57, 996 | DSS_CALC__SPARE_4 = 0x0F58, 997 | DSS_CALC__SPARE_5 = 0x0F59, 998 | DSS_CALC__SPARE_6 = 0x0F5A, 999 | DSS_CALC__SPARE_7 = 0x0F5B, 1000 | DSS_CALC__USER_ROI_SPAD_EN_0 = 0x0F5C, 1001 | DSS_CALC__USER_ROI_SPAD_EN_1 = 0x0F5D, 1002 | DSS_CALC__USER_ROI_SPAD_EN_2 = 0x0F5E, 1003 | DSS_CALC__USER_ROI_SPAD_EN_3 = 0x0F5F, 1004 | DSS_CALC__USER_ROI_SPAD_EN_4 = 0x0F60, 1005 | DSS_CALC__USER_ROI_SPAD_EN_5 = 0x0F61, 1006 | DSS_CALC__USER_ROI_SPAD_EN_6 = 0x0F62, 1007 | DSS_CALC__USER_ROI_SPAD_EN_7 = 0x0F63, 1008 | DSS_CALC__USER_ROI_SPAD_EN_8 = 0x0F64, 1009 | DSS_CALC__USER_ROI_SPAD_EN_9 = 0x0F65, 1010 | DSS_CALC__USER_ROI_SPAD_EN_10 = 0x0F66, 1011 | DSS_CALC__USER_ROI_SPAD_EN_11 = 0x0F67, 1012 | DSS_CALC__USER_ROI_SPAD_EN_12 = 0x0F68, 1013 | DSS_CALC__USER_ROI_SPAD_EN_13 = 0x0F69, 1014 | DSS_CALC__USER_ROI_SPAD_EN_14 = 0x0F6A, 1015 | DSS_CALC__USER_ROI_SPAD_EN_15 = 0x0F6B, 1016 | DSS_CALC__USER_ROI_SPAD_EN_16 = 0x0F6C, 1017 | DSS_CALC__USER_ROI_SPAD_EN_17 = 0x0F6D, 1018 | DSS_CALC__USER_ROI_SPAD_EN_18 = 0x0F6E, 1019 | DSS_CALC__USER_ROI_SPAD_EN_19 = 0x0F6F, 1020 | DSS_CALC__USER_ROI_SPAD_EN_20 = 0x0F70, 1021 | DSS_CALC__USER_ROI_SPAD_EN_21 = 0x0F71, 1022 | DSS_CALC__USER_ROI_SPAD_EN_22 = 0x0F72, 1023 | DSS_CALC__USER_ROI_SPAD_EN_23 = 0x0F73, 1024 | DSS_CALC__USER_ROI_SPAD_EN_24 = 0x0F74, 1025 | DSS_CALC__USER_ROI_SPAD_EN_25 = 0x0F75, 1026 | DSS_CALC__USER_ROI_SPAD_EN_26 = 0x0F76, 1027 | DSS_CALC__USER_ROI_SPAD_EN_27 = 0x0F77, 1028 | DSS_CALC__USER_ROI_SPAD_EN_28 = 0x0F78, 1029 | DSS_CALC__USER_ROI_SPAD_EN_29 = 0x0F79, 1030 | DSS_CALC__USER_ROI_SPAD_EN_30 = 0x0F7A, 1031 | DSS_CALC__USER_ROI_SPAD_EN_31 = 0x0F7B, 1032 | DSS_CALC__USER_ROI_0 = 0x0F7C, 1033 | DSS_CALC__USER_ROI_1 = 0x0F7D, 1034 | DSS_CALC__MODE_ROI_0 = 0x0F7E, 1035 | DSS_CALC__MODE_ROI_1 = 0x0F7F, 1036 | SIGMA_ESTIMATOR_CALC__SPARE_0 = 0x0F80, 1037 | VHV_RESULT__PEAK_SIGNAL_RATE_MCPS = 0x0F82, 1038 | VHV_RESULT__PEAK_SIGNAL_RATE_MCPS_HI = 0x0F82, 1039 | VHV_RESULT__PEAK_SIGNAL_RATE_MCPS_LO = 0x0F83, 1040 | VHV_RESULT__SIGNAL_TOTAL_EVENTS_REF = 0x0F84, 1041 | VHV_RESULT__SIGNAL_TOTAL_EVENTS_REF_3 = 0x0F84, 1042 | VHV_RESULT__SIGNAL_TOTAL_EVENTS_REF_2 = 0x0F85, 1043 | VHV_RESULT__SIGNAL_TOTAL_EVENTS_REF_1 = 0x0F86, 1044 | VHV_RESULT__SIGNAL_TOTAL_EVENTS_REF_0 = 0x0F87, 1045 | PHASECAL_RESULT__PHASE_OUTPUT_REF = 0x0F88, 1046 | PHASECAL_RESULT__PHASE_OUTPUT_REF_HI = 0x0F88, 1047 | PHASECAL_RESULT__PHASE_OUTPUT_REF_LO = 0x0F89, 1048 | DSS_RESULT__TOTAL_RATE_PER_SPAD = 0x0F8A, 1049 | DSS_RESULT__TOTAL_RATE_PER_SPAD_HI = 0x0F8A, 1050 | DSS_RESULT__TOTAL_RATE_PER_SPAD_LO = 0x0F8B, 1051 | DSS_RESULT__ENABLED_BLOCKS = 0x0F8C, 1052 | DSS_RESULT__NUM_REQUESTED_SPADS = 0x0F8E, 1053 | DSS_RESULT__NUM_REQUESTED_SPADS_HI = 0x0F8E, 1054 | DSS_RESULT__NUM_REQUESTED_SPADS_LO = 0x0F8F, 1055 | MM_RESULT__INNER_INTERSECTION_RATE = 0x0F92, 1056 | MM_RESULT__INNER_INTERSECTION_RATE_HI = 0x0F92, 1057 | MM_RESULT__INNER_INTERSECTION_RATE_LO = 0x0F93, 1058 | MM_RESULT__OUTER_COMPLEMENT_RATE = 0x0F94, 1059 | MM_RESULT__OUTER_COMPLEMENT_RATE_HI = 0x0F94, 1060 | MM_RESULT__OUTER_COMPLEMENT_RATE_LO = 0x0F95, 1061 | MM_RESULT__TOTAL_OFFSET = 0x0F96, 1062 | MM_RESULT__TOTAL_OFFSET_HI = 0x0F96, 1063 | MM_RESULT__TOTAL_OFFSET_LO = 0x0F97, 1064 | XTALK_CALC__XTALK_FOR_ENABLED_SPADS = 0x0F98, 1065 | XTALK_CALC__XTALK_FOR_ENABLED_SPADS_3 = 0x0F98, 1066 | XTALK_CALC__XTALK_FOR_ENABLED_SPADS_2 = 0x0F99, 1067 | XTALK_CALC__XTALK_FOR_ENABLED_SPADS_1 = 0x0F9A, 1068 | XTALK_CALC__XTALK_FOR_ENABLED_SPADS_0 = 0x0F9B, 1069 | XTALK_RESULT__AVG_XTALK_USER_ROI_KCPS = 0x0F9C, 1070 | XTALK_RESULT__AVG_XTALK_USER_ROI_KCPS_3 = 0x0F9C, 1071 | XTALK_RESULT__AVG_XTALK_USER_ROI_KCPS_2 = 0x0F9D, 1072 | XTALK_RESULT__AVG_XTALK_USER_ROI_KCPS_1 = 0x0F9E, 1073 | XTALK_RESULT__AVG_XTALK_USER_ROI_KCPS_0 = 0x0F9F, 1074 | XTALK_RESULT__AVG_XTALK_MM_INNER_ROI_KCPS = 0x0FA0, 1075 | XTALK_RESULT__AVG_XTALK_MM_INNER_ROI_KCPS_3 = 0x0FA0, 1076 | XTALK_RESULT__AVG_XTALK_MM_INNER_ROI_KCPS_2 = 0x0FA1, 1077 | XTALK_RESULT__AVG_XTALK_MM_INNER_ROI_KCPS_1 = 0x0FA2, 1078 | XTALK_RESULT__AVG_XTALK_MM_INNER_ROI_KCPS_0 = 0x0FA3, 1079 | XTALK_RESULT__AVG_XTALK_MM_OUTER_ROI_KCPS = 0x0FA4, 1080 | XTALK_RESULT__AVG_XTALK_MM_OUTER_ROI_KCPS_3 = 0x0FA4, 1081 | XTALK_RESULT__AVG_XTALK_MM_OUTER_ROI_KCPS_2 = 0x0FA5, 1082 | XTALK_RESULT__AVG_XTALK_MM_OUTER_ROI_KCPS_1 = 0x0FA6, 1083 | XTALK_RESULT__AVG_XTALK_MM_OUTER_ROI_KCPS_0 = 0x0FA7, 1084 | RANGE_RESULT__ACCUM_PHASE = 0x0FA8, 1085 | RANGE_RESULT__ACCUM_PHASE_3 = 0x0FA8, 1086 | RANGE_RESULT__ACCUM_PHASE_2 = 0x0FA9, 1087 | RANGE_RESULT__ACCUM_PHASE_1 = 0x0FAA, 1088 | RANGE_RESULT__ACCUM_PHASE_0 = 0x0FAB, 1089 | RANGE_RESULT__OFFSET_CORRECTED_RANGE = 0x0FAC, 1090 | RANGE_RESULT__OFFSET_CORRECTED_RANGE_HI = 0x0FAC, 1091 | RANGE_RESULT__OFFSET_CORRECTED_RANGE_LO = 0x0FAD, 1092 | SHADOW_PHASECAL_RESULT__VCSEL_START = 0x0FAE, 1093 | SHADOW_RESULT__INTERRUPT_STATUS = 0x0FB0, 1094 | SHADOW_RESULT__RANGE_STATUS = 0x0FB1, 1095 | SHADOW_RESULT__REPORT_STATUS = 0x0FB2, 1096 | SHADOW_RESULT__STREAM_COUNT = 0x0FB3, 1097 | SHADOW_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0 = 0x0FB4, 1098 | SHADOW_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0_HI = 0x0FB4, 1099 | SHADOW_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0_LO = 0x0FB5, 1100 | SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD0 = 0x0FB6, 1101 | SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD0_HI = 0x0FB6, 1102 | SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD0_LO = 0x0FB7, 1103 | SHADOW_RESULT__AMBIENT_COUNT_RATE_MCPS_SD0 = 0x0FB8, 1104 | SHADOW_RESULT__AMBIENT_COUNT_RATE_MCPS_SD0_HI = 0x0FB8, 1105 | SHADOW_RESULT__AMBIENT_COUNT_RATE_MCPS_SD0_LO = 0x0FB9, 1106 | SHADOW_RESULT__SIGMA_SD0 = 0x0FBA, 1107 | SHADOW_RESULT__SIGMA_SD0_HI = 0x0FBA, 1108 | SHADOW_RESULT__SIGMA_SD0_LO = 0x0FBB, 1109 | SHADOW_RESULT__PHASE_SD0 = 0x0FBC, 1110 | SHADOW_RESULT__PHASE_SD0_HI = 0x0FBC, 1111 | SHADOW_RESULT__PHASE_SD0_LO = 0x0FBD, 1112 | SHADOW_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0 = 0x0FBE, 1113 | SHADOW_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0_HI = 0x0FBE, 1114 | SHADOW_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0_LO = 0x0FBF, 1115 | SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0 = 0x0FC0, 1116 | SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0_HI = 0x0FC0, 1117 | SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0_LO = 0x0FC1, 1118 | SHADOW_RESULT__MM_INNER_ACTUAL_EFFECTIVE_SPADS_SD0 = 0x0FC2, 1119 | SHADOW_RESULT__MM_INNER_ACTUAL_EFFECTIVE_SPADS_SD0_HI = 0x0FC2, 1120 | SHADOW_RESULT__MM_INNER_ACTUAL_EFFECTIVE_SPADS_SD0_LO = 0x0FC3, 1121 | SHADOW_RESULT__MM_OUTER_ACTUAL_EFFECTIVE_SPADS_SD0 = 0x0FC4, 1122 | SHADOW_RESULT__MM_OUTER_ACTUAL_EFFECTIVE_SPADS_SD0_HI = 0x0FC4, 1123 | SHADOW_RESULT__MM_OUTER_ACTUAL_EFFECTIVE_SPADS_SD0_LO = 0x0FC5, 1124 | SHADOW_RESULT__AVG_SIGNAL_COUNT_RATE_MCPS_SD0 = 0x0FC6, 1125 | SHADOW_RESULT__AVG_SIGNAL_COUNT_RATE_MCPS_SD0_HI = 0x0FC6, 1126 | SHADOW_RESULT__AVG_SIGNAL_COUNT_RATE_MCPS_SD0_LO = 0x0FC7, 1127 | SHADOW_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD1 = 0x0FC8, 1128 | SHADOW_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD1_HI = 0x0FC8, 1129 | SHADOW_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD1_LO = 0x0FC9, 1130 | SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD1 = 0x0FCA, 1131 | SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD1_HI = 0x0FCA, 1132 | SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD1_LO = 0x0FCB, 1133 | SHADOW_RESULT__AMBIENT_COUNT_RATE_MCPS_SD1 = 0x0FCC, 1134 | SHADOW_RESULT__AMBIENT_COUNT_RATE_MCPS_SD1_HI = 0x0FCC, 1135 | SHADOW_RESULT__AMBIENT_COUNT_RATE_MCPS_SD1_LO = 0x0FCD, 1136 | SHADOW_RESULT__SIGMA_SD1 = 0x0FCE, 1137 | SHADOW_RESULT__SIGMA_SD1_HI = 0x0FCE, 1138 | SHADOW_RESULT__SIGMA_SD1_LO = 0x0FCF, 1139 | SHADOW_RESULT__PHASE_SD1 = 0x0FD0, 1140 | SHADOW_RESULT__PHASE_SD1_HI = 0x0FD0, 1141 | SHADOW_RESULT__PHASE_SD1_LO = 0x0FD1, 1142 | SHADOW_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD1 = 0x0FD2, 1143 | SHADOW_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD1_HI = 0x0FD2, 1144 | SHADOW_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD1_LO = 0x0FD3, 1145 | SHADOW_RESULT__SPARE_0_SD1 = 0x0FD4, 1146 | SHADOW_RESULT__SPARE_0_SD1_HI = 0x0FD4, 1147 | SHADOW_RESULT__SPARE_0_SD1_LO = 0x0FD5, 1148 | SHADOW_RESULT__SPARE_1_SD1 = 0x0FD6, 1149 | SHADOW_RESULT__SPARE_1_SD1_HI = 0x0FD6, 1150 | SHADOW_RESULT__SPARE_1_SD1_LO = 0x0FD7, 1151 | SHADOW_RESULT__SPARE_2_SD1 = 0x0FD8, 1152 | SHADOW_RESULT__SPARE_2_SD1_HI = 0x0FD8, 1153 | SHADOW_RESULT__SPARE_2_SD1_LO = 0x0FD9, 1154 | SHADOW_RESULT__SPARE_3_SD1 = 0x0FDA, 1155 | SHADOW_RESULT__THRESH_INFO = 0x0FDB, 1156 | SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0 = 0x0FDC, 1157 | SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0_3 = 0x0FDC, 1158 | SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0_2 = 0x0FDD, 1159 | SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0_1 = 0x0FDE, 1160 | SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0_0 = 0x0FDF, 1161 | SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0 = 0x0FE0, 1162 | SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0_3 = 0x0FE0, 1163 | SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0_2 = 0x0FE1, 1164 | SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0_1 = 0x0FE2, 1165 | SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0_0 = 0x0FE3, 1166 | SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0 = 0x0FE4, 1167 | SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0_3 = 0x0FE4, 1168 | SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0_2 = 0x0FE5, 1169 | SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0_1 = 0x0FE6, 1170 | SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0_0 = 0x0FE7, 1171 | SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0 = 0x0FE8, 1172 | SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0_3 = 0x0FE8, 1173 | SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0_2 = 0x0FE9, 1174 | SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0_1 = 0x0FEA, 1175 | SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0_0 = 0x0FEB, 1176 | SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1 = 0x0FEC, 1177 | SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1_3 = 0x0FEC, 1178 | SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1_2 = 0x0FED, 1179 | SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1_1 = 0x0FEE, 1180 | SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1_0 = 0x0FEF, 1181 | SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1 = 0x0FF0, 1182 | SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1_3 = 0x0FF0, 1183 | SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1_2 = 0x0FF1, 1184 | SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1_1 = 0x0FF2, 1185 | SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1_0 = 0x0FF3, 1186 | SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1 = 0x0FF4, 1187 | SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1_3 = 0x0FF4, 1188 | SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1_2 = 0x0FF5, 1189 | SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1_1 = 0x0FF6, 1190 | SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1_0 = 0x0FF7, 1191 | SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1 = 0x0FF8, 1192 | SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1_3 = 0x0FF8, 1193 | SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1_2 = 0x0FF9, 1194 | SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1_1 = 0x0FFA, 1195 | SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1_0 = 0x0FFB, 1196 | SHADOW_RESULT_CORE__SPARE_0 = 0x0FFC, 1197 | SHADOW_PHASECAL_RESULT__REFERENCE_PHASE_HI = 0x0FFE, 1198 | SHADOW_PHASECAL_RESULT__REFERENCE_PHASE_LO = 0x0FFF, 1199 | }; 1200 | 1201 | enum DistanceMode { Short, Medium, Long, Unknown }; 1202 | 1203 | enum RangeStatus : uint8_t 1204 | { 1205 | RangeValid = 0, 1206 | 1207 | // "sigma estimator check is above the internal defined threshold" 1208 | // (sigma = standard deviation of measurement) 1209 | SigmaFail = 1, 1210 | 1211 | // "signal value is below the internal defined threshold" 1212 | SignalFail = 2, 1213 | 1214 | // "Target is below minimum detection threshold." 1215 | RangeValidMinRangeClipped = 3, 1216 | 1217 | // "phase is out of bounds" 1218 | // (nothing detected in range; try a longer distance mode if applicable) 1219 | OutOfBoundsFail = 4, 1220 | 1221 | // "HW or VCSEL failure" 1222 | HardwareFail = 5, 1223 | 1224 | // "The Range is valid but the wraparound check has not been done." 1225 | RangeValidNoWrapCheckFail = 6, 1226 | 1227 | // "Wrapped target, not matching phases" 1228 | // "no matching phase in other VCSEL period timing." 1229 | WrapTargetFail = 7, 1230 | 1231 | // "Internal algo underflow or overflow in lite ranging." 1232 | // ProcessingFail = 8: not used in API 1233 | 1234 | // "Specific to lite ranging." 1235 | // should never occur with this lib (which uses low power auto ranging, 1236 | // as the API does) 1237 | XtalkSignalFail = 9, 1238 | 1239 | // "1st interrupt when starting ranging in back to back mode. Ignore 1240 | // data." 1241 | // should never occur with this lib 1242 | SynchronizationInt = 10, // (the API spells this "syncronisation") 1243 | 1244 | // "All Range ok but object is result of multiple pulses merging together. 1245 | // Used by RQL for merged pulse detection" 1246 | // RangeValid MergedPulse = 11: not used in API 1247 | 1248 | // "Used by RQL as different to phase fail." 1249 | // TargetPresentLackOfSignal = 12: 1250 | 1251 | // "Target is below minimum detection threshold." 1252 | MinRangeFail = 13, 1253 | 1254 | // "The reported range is invalid" 1255 | // RangeInvalid = 14: can't actually be returned by API (range can never become negative, even after correction) 1256 | 1257 | // "No Update." 1258 | None = 255, 1259 | }; 1260 | 1261 | struct RangingData 1262 | { 1263 | uint16_t range_mm; 1264 | RangeStatus range_status; 1265 | float peak_signal_count_rate_MCPS; 1266 | float ambient_count_rate_MCPS; 1267 | }; 1268 | 1269 | RangingData ranging_data; 1270 | 1271 | uint8_t last_status; // status of last I2C transmission 1272 | 1273 | VL53L1X(); 1274 | 1275 | void setBus(TwoWire * bus) { this->bus = bus; } 1276 | TwoWire * getBus() { return bus; } 1277 | 1278 | void setAddress(uint8_t new_addr); 1279 | uint8_t getAddress() { return address; } 1280 | 1281 | bool init(bool io_2v8 = true); 1282 | 1283 | void writeReg(uint16_t reg, uint8_t value); 1284 | void writeReg16Bit(uint16_t reg, uint16_t value); 1285 | void writeReg32Bit(uint16_t reg, uint32_t value); 1286 | uint8_t readReg(regAddr reg); 1287 | uint16_t readReg16Bit(uint16_t reg); 1288 | uint32_t readReg32Bit(uint16_t reg); 1289 | 1290 | bool setDistanceMode(DistanceMode mode); 1291 | DistanceMode getDistanceMode() { return distance_mode; } 1292 | 1293 | bool setMeasurementTimingBudget(uint32_t budget_us); 1294 | uint32_t getMeasurementTimingBudget(); 1295 | 1296 | void setROISize(uint8_t width, uint8_t height); 1297 | void getROISize(uint8_t * width, uint8_t * height); 1298 | void setROICenter(uint8_t spadNum); 1299 | uint8_t getROICenter(); 1300 | 1301 | void startContinuous(uint32_t period_ms); 1302 | void stopContinuous(); 1303 | uint16_t read(bool blocking = true); 1304 | uint16_t readRangeContinuousMillimeters(bool blocking = true) { return read(blocking); } // alias of read() 1305 | uint16_t readSingle(bool blocking = true); 1306 | uint16_t readRangeSingleMillimeters(bool blocking = true) { return readSingle(blocking); } // alias of readSingle() 1307 | 1308 | // check if sensor has new reading available 1309 | // assumes interrupt is active low (GPIO_HV_MUX__CTRL bit 4 is 1) 1310 | bool dataReady() { return (readReg(GPIO__TIO_HV_STATUS) & 0x01) == 0; } 1311 | 1312 | static const char * rangeStatusToString(RangeStatus status); 1313 | 1314 | void setTimeout(uint16_t timeout) { io_timeout = timeout; } 1315 | uint16_t getTimeout() { return io_timeout; } 1316 | bool timeoutOccurred(); 1317 | 1318 | private: 1319 | 1320 | // The Arduino two-wire interface uses a 7-bit number for the address, 1321 | // and sets the last bit correctly based on reads and writes 1322 | static const uint8_t AddressDefault = 0b0101001; 1323 | 1324 | // value used in measurement timing budget calculations 1325 | // assumes PresetMode is LOWPOWER_AUTONOMOUS 1326 | // 1327 | // vhv = LOWPOWER_AUTO_VHV_LOOP_DURATION_US + LOWPOWERAUTO_VHV_LOOP_BOUND 1328 | // (tuning parm default) * LOWPOWER_AUTO_VHV_LOOP_DURATION_US 1329 | // = 245 + 3 * 245 = 980 1330 | // TimingGuard = LOWPOWER_AUTO_OVERHEAD_BEFORE_A_RANGING + 1331 | // LOWPOWER_AUTO_OVERHEAD_BETWEEN_A_B_RANGING + vhv 1332 | // = 1448 + 2100 + 980 = 4528 1333 | static const uint32_t TimingGuard = 4528; 1334 | 1335 | // value in DSS_CONFIG__TARGET_TOTAL_RATE_MCPS register, used in DSS 1336 | // calculations 1337 | static const uint16_t TargetRate = 0x0A00; 1338 | 1339 | // for storing values read from RESULT__RANGE_STATUS (0x0089) 1340 | // through RESULT__PEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0_LOW 1341 | // (0x0099) 1342 | struct ResultBuffer 1343 | { 1344 | uint8_t range_status; 1345 | // uint8_t report_status: not used 1346 | uint8_t stream_count; 1347 | uint16_t dss_actual_effective_spads_sd0; 1348 | // uint16_t peak_signal_count_rate_mcps_sd0: not used 1349 | uint16_t ambient_count_rate_mcps_sd0; 1350 | // uint16_t sigma_sd0: not used 1351 | // uint16_t phase_sd0: not used 1352 | uint16_t final_crosstalk_corrected_range_mm_sd0; 1353 | uint16_t peak_signal_count_rate_crosstalk_corrected_mcps_sd0; 1354 | }; 1355 | 1356 | // making this static would save RAM for multiple instances as long as there 1357 | // aren't multiple sensors being read at the same time (e.g. on separate 1358 | // I2C buses) 1359 | ResultBuffer results; 1360 | 1361 | TwoWire * bus; 1362 | 1363 | uint8_t address; 1364 | 1365 | uint16_t io_timeout; 1366 | bool did_timeout; 1367 | uint16_t timeout_start_ms; 1368 | 1369 | uint16_t fast_osc_frequency; 1370 | uint16_t osc_calibrate_val; 1371 | 1372 | bool calibrated; 1373 | uint8_t saved_vhv_init; 1374 | uint8_t saved_vhv_timeout; 1375 | 1376 | DistanceMode distance_mode; 1377 | 1378 | // Record the current time to check an upcoming timeout against 1379 | void startTimeout() { timeout_start_ms = millis(); } 1380 | 1381 | // Check if timeout is enabled (set to nonzero value) and has expired 1382 | bool checkTimeoutExpired() {return (io_timeout > 0) && ((uint16_t)(millis() - timeout_start_ms) > io_timeout); } 1383 | 1384 | void setupManualCalibration(); 1385 | void readResults(); 1386 | void updateDSS(); 1387 | void getRangingData(); 1388 | 1389 | static uint32_t decodeTimeout(uint16_t reg_val); 1390 | static uint16_t encodeTimeout(uint32_t timeout_mclks); 1391 | static uint32_t timeoutMclksToMicroseconds(uint32_t timeout_mclks, uint32_t macro_period_us); 1392 | static uint32_t timeoutMicrosecondsToMclks(uint32_t timeout_us, uint32_t macro_period_us); 1393 | uint32_t calcMacroPeriod(uint8_t vcsel_period); 1394 | 1395 | // Convert count rate from fixed point 9.7 format to float 1396 | float countRateFixedToFloat(uint16_t count_rate_fixed) { return (float)count_rate_fixed / (1 << 7); } 1397 | }; 1398 | -------------------------------------------------------------------------------- /examples/Continuous/Continuous.ino: -------------------------------------------------------------------------------- 1 | /* 2 | This example shows how to take simple range measurements with the VL53L1X. The 3 | range readings are in units of mm. 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | VL53L1X sensor; 10 | 11 | void setup() 12 | { 13 | while (!Serial) {} 14 | Serial.begin(115200); 15 | Wire.begin(); 16 | Wire.setClock(400000); // use 400 kHz I2C 17 | 18 | sensor.setTimeout(500); 19 | if (!sensor.init()) 20 | { 21 | Serial.println("Failed to detect and initialize sensor!"); 22 | while (1); 23 | } 24 | 25 | // Use long distance mode and allow up to 50000 us (50 ms) for a measurement. 26 | // You can change these settings to adjust the performance of the sensor, but 27 | // the minimum timing budget is 20 ms for short distance mode and 33 ms for 28 | // medium and long distance modes. See the VL53L1X datasheet for more 29 | // information on range and timing limits. 30 | sensor.setDistanceMode(VL53L1X::Long); 31 | sensor.setMeasurementTimingBudget(50000); 32 | 33 | // Start continuous readings at a rate of one measurement every 50 ms (the 34 | // inter-measurement period). This period should be at least as long as the 35 | // timing budget. 36 | sensor.startContinuous(50); 37 | } 38 | 39 | void loop() 40 | { 41 | Serial.print(sensor.read()); 42 | if (sensor.timeoutOccurred()) { Serial.print(" TIMEOUT"); } 43 | 44 | Serial.println(); 45 | } 46 | -------------------------------------------------------------------------------- /examples/ContinuousMultipleSensors/ContinuousMultipleSensors.ino: -------------------------------------------------------------------------------- 1 | /* 2 | This example shows how to set up and read multiple VL53L1X sensors connected to 3 | the same I2C bus. Each sensor needs to have its XSHUT pin connected to a 4 | different Arduino pin, and you should change sensorCount and the xshutPins array 5 | below to match your setup. 6 | 7 | For more information, see ST's application note AN4846 ("Using multiple VL53L0X 8 | in a single design"). The principles described there apply to the VL53L1X as 9 | well. 10 | */ 11 | 12 | #include 13 | #include 14 | 15 | // The number of sensors in your system. 16 | const uint8_t sensorCount = 3; 17 | 18 | // The Arduino pin connected to the XSHUT pin of each sensor. 19 | const uint8_t xshutPins[sensorCount] = { 4, 5, 6 }; 20 | 21 | VL53L1X sensors[sensorCount]; 22 | 23 | void setup() 24 | { 25 | while (!Serial) {} 26 | Serial.begin(115200); 27 | Wire.begin(); 28 | Wire.setClock(400000); // use 400 kHz I2C 29 | 30 | // Disable/reset all sensors by driving their XSHUT pins low. 31 | for (uint8_t i = 0; i < sensorCount; i++) 32 | { 33 | pinMode(xshutPins[i], OUTPUT); 34 | digitalWrite(xshutPins[i], LOW); 35 | } 36 | 37 | // Enable, initialize, and start each sensor, one by one. 38 | for (uint8_t i = 0; i < sensorCount; i++) 39 | { 40 | // Stop driving this sensor's XSHUT low. This should allow the carrier 41 | // board to pull it high. (We do NOT want to drive XSHUT high since it is 42 | // not level shifted.) Then wait a bit for the sensor to start up. 43 | pinMode(xshutPins[i], INPUT); 44 | delay(10); 45 | 46 | sensors[i].setTimeout(500); 47 | if (!sensors[i].init()) 48 | { 49 | Serial.print("Failed to detect and initialize sensor "); 50 | Serial.println(i); 51 | while (1); 52 | } 53 | 54 | // Each sensor must have its address changed to a unique value other than 55 | // the default of 0x29 (except for the last one, which could be left at 56 | // the default). To make it simple, we'll just count up from 0x2A. 57 | sensors[i].setAddress(0x2A + i); 58 | 59 | sensors[i].startContinuous(50); 60 | } 61 | } 62 | 63 | void loop() 64 | { 65 | for (uint8_t i = 0; i < sensorCount; i++) 66 | { 67 | Serial.print(sensors[i].read()); 68 | if (sensors[i].timeoutOccurred()) { Serial.print(" TIMEOUT"); } 69 | Serial.print('\t'); 70 | } 71 | Serial.println(); 72 | } 73 | -------------------------------------------------------------------------------- /examples/ContinuousWithDetails/ContinuousWithDetails.ino: -------------------------------------------------------------------------------- 1 | /* 2 | This example takes range measurements with the VL53L1X and displays additional 3 | details (status and signal/ambient rates) for each measurement, which can help 4 | you determine whether the sensor is operating normally and the reported range is 5 | valid. The range is in units of mm, and the rates are in units of MCPS (mega 6 | counts per second). 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | VL53L1X sensor; 13 | 14 | void setup() 15 | { 16 | while (!Serial) {} 17 | Serial.begin(115200); 18 | Wire.begin(); 19 | Wire.setClock(400000); // use 400 kHz I2C 20 | 21 | sensor.setTimeout(500); 22 | if (!sensor.init()) 23 | { 24 | Serial.println("Failed to detect and initialize sensor!"); 25 | while (1); 26 | } 27 | 28 | // Use long distance mode and allow up to 50000 us (50 ms) for a measurement. 29 | // You can change these settings to adjust the performance of the sensor, but 30 | // the minimum timing budget is 20 ms for short distance mode and 33 ms for 31 | // medium and long distance modes. See the VL53L1X datasheet for more 32 | // information on range and timing limits. 33 | sensor.setDistanceMode(VL53L1X::Long); 34 | sensor.setMeasurementTimingBudget(50000); 35 | 36 | // Start continuous readings at a rate of one measurement every 50 ms (the 37 | // inter-measurement period). This period should be at least as long as the 38 | // timing budget. 39 | sensor.startContinuous(50); 40 | } 41 | 42 | void loop() 43 | { 44 | sensor.read(); 45 | 46 | Serial.print("range: "); 47 | Serial.print(sensor.ranging_data.range_mm); 48 | Serial.print("\tstatus: "); 49 | Serial.print(VL53L1X::rangeStatusToString(sensor.ranging_data.range_status)); 50 | Serial.print("\tpeak signal: "); 51 | Serial.print(sensor.ranging_data.peak_signal_count_rate_MCPS); 52 | Serial.print("\tambient: "); 53 | Serial.print(sensor.ranging_data.ambient_count_rate_MCPS); 54 | 55 | Serial.println(); 56 | } -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | VL53L1X KEYWORD1 2 | 3 | setBus KEYWORD2 4 | getBus KEYWORD2 5 | setAddress KEYWORD2 6 | getAddress KEYWORD2 7 | init KEYWORD2 8 | writeReg KEYWORD2 9 | writeReg16Bit KEYWORD2 10 | writeReg32Bit KEYWORD2 11 | readReg KEYWORD2 12 | readReg16Bit KEYWORD2 13 | readReg32Bit KEYWORD2 14 | setDistanceMode KEYWORD2 15 | getDistanceMode KEYWORD2 16 | setMeasurementTimingBudget KEYWORD2 17 | getMeasurementTimingBudget KEYWORD2 18 | setROISize KEYWORD2 19 | getROISize KEYWORD2 20 | setROICenter KEYWORD2 21 | getROICenter KEYWORD2 22 | startContinuous KEYWORD2 23 | stopContinuous KEYWORD2 24 | read KEYWORD2 25 | readRangeContinuousMillimeters KEYWORD2 26 | rangeStatusToString KEYWORD2 27 | setTimeout KEYWORD2 28 | getTimeout KEYWORD2 29 | timeoutOccurred KEYWORD2 30 | 31 | Short LITERAL1 32 | Medium LITERAL1 33 | Long LITERAL1 34 | Unknown LITERAL1 35 | 36 | RangeValid LITERAL1 37 | SigmaFail LITERAL1 38 | SignalFail LITERAL1 39 | RangeValidMinRangeClipped LITERAL1 40 | OutOfBoundsFail LITERAL1 41 | HardwareFail LITERAL1 42 | RangeValidNoWrapCheckFail LITERAL1 43 | WrapTargetFail LITERAL1 44 | XtalkSignalFail LITERAL1 45 | SyncronisationInt LITERAL1 46 | MinRangeFail LITERAL1 47 | None LITERAL1 -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=VL53L1X 2 | version=1.3.1 3 | author=Pololu 4 | maintainer=Pololu 5 | sentence=VL53L1X distance sensor library 6 | paragraph=This is a library for the Arduino IDE that helps interface with ST's VL53L1X distance sensor. 7 | category=Sensors 8 | url=https://github.com/pololu/vl53l1x-arduino 9 | architectures=* 10 | --------------------------------------------------------------------------------