hello

Committer:
shalutha
Date:
Tue Oct 01 14:08:33 2019 +0000
Revision:
0:69ce6d469c71
hello

Who changed what in which revision?

UserRevisionLine numberNew contents of line
shalutha 0:69ce6d469c71 1 // Most of the functionality of this library is based on the VL53L0X API
shalutha 0:69ce6d469c71 2 // provided by ST (STSW-IMG005), and some of the explanatory comments are quoted
shalutha 0:69ce6d469c71 3 // or paraphrased from the API source code, API user manual (UM2039), and the
shalutha 0:69ce6d469c71 4 // VL53L0X datasheet.
shalutha 0:69ce6d469c71 5
shalutha 0:69ce6d469c71 6 #include <memory>
shalutha 0:69ce6d469c71 7 #include <VL53L0X.h>
shalutha 0:69ce6d469c71 8
shalutha 0:69ce6d469c71 9 // Defines /////////////////////////////////////////////////////////////////////
shalutha 0:69ce6d469c71 10
shalutha 0:69ce6d469c71 11 // The Arduino two-wire interface uses a 7-bit number for the address,
shalutha 0:69ce6d469c71 12 // and sets the last bit correctly based on reads and writes
shalutha 0:69ce6d469c71 13 #define ADDRESS_DEFAULT (0b0101001 << 1)
shalutha 0:69ce6d469c71 14
shalutha 0:69ce6d469c71 15 // Record the current time to check an upcoming timeout against
shalutha 0:69ce6d469c71 16 #define startTimeout() (timeout_start_ms = millis())
shalutha 0:69ce6d469c71 17
shalutha 0:69ce6d469c71 18 // Check if timeout is enabled (set to nonzero value) and has expired
shalutha 0:69ce6d469c71 19 #define checkTimeoutExpired() (io_timeout > 0 && ((uint16_t)millis() - timeout_start_ms) > io_timeout)
shalutha 0:69ce6d469c71 20
shalutha 0:69ce6d469c71 21 // Decode VCSEL (vertical cavity surface emitting laser) pulse period in PCLKs
shalutha 0:69ce6d469c71 22 // from register value
shalutha 0:69ce6d469c71 23 // based on VL53L0X_decode_vcsel_period()
shalutha 0:69ce6d469c71 24 #define decodeVcselPeriod(reg_val) (((reg_val) + 1) << 1)
shalutha 0:69ce6d469c71 25
shalutha 0:69ce6d469c71 26 // Encode VCSEL pulse period register value from period in PCLKs
shalutha 0:69ce6d469c71 27 // based on VL53L0X_encode_vcsel_period()
shalutha 0:69ce6d469c71 28 #define encodeVcselPeriod(period_pclks) (((period_pclks) >> 1) - 1)
shalutha 0:69ce6d469c71 29
shalutha 0:69ce6d469c71 30 // Calculate macro period in *nanoseconds* from VCSEL period in PCLKs
shalutha 0:69ce6d469c71 31 // based on VL53L0X_calc_macro_period_ps()
shalutha 0:69ce6d469c71 32 // PLL_period_ps = 1655; macro_period_vclks = 2304
shalutha 0:69ce6d469c71 33 #define calcMacroPeriod(vcsel_period_pclks) ((((uint32_t)2304 * (vcsel_period_pclks) * 1655) + 500) / 1000)
shalutha 0:69ce6d469c71 34
shalutha 0:69ce6d469c71 35 // Transmission status (https://www.arduino.cc/en/Reference/WireEndTransmission)
shalutha 0:69ce6d469c71 36 #define ERR_OK 0
shalutha 0:69ce6d469c71 37 #define ERR_NACK_ADDR 2 // received NACK on transmit of address
shalutha 0:69ce6d469c71 38 #define ERR_NACK_DATA 3 // received NACK on transmit of data
shalutha 0:69ce6d469c71 39 #define ERR_OTHER 4
shalutha 0:69ce6d469c71 40
shalutha 0:69ce6d469c71 41 #define millis() timer->read_ms()
shalutha 0:69ce6d469c71 42
shalutha 0:69ce6d469c71 43 // Constructors ////////////////////////////////////////////////////////////////
shalutha 0:69ce6d469c71 44
shalutha 0:69ce6d469c71 45 VL53L0X::VL53L0X(I2C* i2c, Timer* timer)
shalutha 0:69ce6d469c71 46 : address(ADDRESS_DEFAULT)
shalutha 0:69ce6d469c71 47 , io_timeout(0) // no timeout
shalutha 0:69ce6d469c71 48 , did_timeout(false)
shalutha 0:69ce6d469c71 49 , i2c(i2c)
shalutha 0:69ce6d469c71 50 , timer(timer)
shalutha 0:69ce6d469c71 51 {
shalutha 0:69ce6d469c71 52 }
shalutha 0:69ce6d469c71 53
shalutha 0:69ce6d469c71 54 // Public Methods //////////////////////////////////////////////////////////////
shalutha 0:69ce6d469c71 55
shalutha 0:69ce6d469c71 56 void VL53L0X::setAddress(uint8_t new_addr)
shalutha 0:69ce6d469c71 57 {
shalutha 0:69ce6d469c71 58 writeReg(I2C_SLAVE_DEVICE_ADDRESS, new_addr & 0x7F);
shalutha 0:69ce6d469c71 59 address = new_addr << 1;
shalutha 0:69ce6d469c71 60 }
shalutha 0:69ce6d469c71 61
shalutha 0:69ce6d469c71 62 // Initialize sensor using sequence based on VL53L0X_DataInit(),
shalutha 0:69ce6d469c71 63 // VL53L0X_StaticInit(), and VL53L0X_PerformRefCalibration().
shalutha 0:69ce6d469c71 64 // This function does not perform reference SPAD calibration
shalutha 0:69ce6d469c71 65 // (VL53L0X_PerformRefSpadManagement()), since the API user manual says that it
shalutha 0:69ce6d469c71 66 // is performed by ST on the bare modules; it seems like that should work well
shalutha 0:69ce6d469c71 67 // enough unless a cover glass is added.
shalutha 0:69ce6d469c71 68 // If io_2v8 (optional) is true or not given, the sensor is configured for 2V8
shalutha 0:69ce6d469c71 69 // mode.
shalutha 0:69ce6d469c71 70 bool VL53L0X::init(bool io_2v8)
shalutha 0:69ce6d469c71 71 {
shalutha 0:69ce6d469c71 72 // VL53L0X_DataInit() begin
shalutha 0:69ce6d469c71 73
shalutha 0:69ce6d469c71 74 // sensor uses 1V8 mode for I/O by default; switch to 2V8 mode if necessary
shalutha 0:69ce6d469c71 75 if (io_2v8)
shalutha 0:69ce6d469c71 76 {
shalutha 0:69ce6d469c71 77 writeReg(VHV_CONFIG_PAD_SCL_SDA__EXTSUP_HV,
shalutha 0:69ce6d469c71 78 readReg(VHV_CONFIG_PAD_SCL_SDA__EXTSUP_HV) | 0x01); // set bit 0
shalutha 0:69ce6d469c71 79 }
shalutha 0:69ce6d469c71 80
shalutha 0:69ce6d469c71 81 // "Set I2C standard mode"
shalutha 0:69ce6d469c71 82 writeReg(0x88, 0x00);
shalutha 0:69ce6d469c71 83
shalutha 0:69ce6d469c71 84 writeReg(0x80, 0x01);
shalutha 0:69ce6d469c71 85 writeReg(0xFF, 0x01);
shalutha 0:69ce6d469c71 86 writeReg(0x00, 0x00);
shalutha 0:69ce6d469c71 87 stop_variable = readReg(0x91);
shalutha 0:69ce6d469c71 88 writeReg(0x00, 0x01);
shalutha 0:69ce6d469c71 89 writeReg(0xFF, 0x00);
shalutha 0:69ce6d469c71 90 writeReg(0x80, 0x00);
shalutha 0:69ce6d469c71 91
shalutha 0:69ce6d469c71 92 // disable SIGNAL_RATE_MSRC (bit 1) and SIGNAL_RATE_PRE_RANGE (bit 4) limit checks
shalutha 0:69ce6d469c71 93 writeReg(MSRC_CONFIG_CONTROL, readReg(MSRC_CONFIG_CONTROL) | 0x12);
shalutha 0:69ce6d469c71 94
shalutha 0:69ce6d469c71 95 // set final range signal rate limit to 0.25 MCPS (million counts per second)
shalutha 0:69ce6d469c71 96 setSignalRateLimit(0.25);
shalutha 0:69ce6d469c71 97
shalutha 0:69ce6d469c71 98 writeReg(SYSTEM_SEQUENCE_CONFIG, 0xFF);
shalutha 0:69ce6d469c71 99
shalutha 0:69ce6d469c71 100 // VL53L0X_DataInit() end
shalutha 0:69ce6d469c71 101
shalutha 0:69ce6d469c71 102 // VL53L0X_StaticInit() begin
shalutha 0:69ce6d469c71 103
shalutha 0:69ce6d469c71 104 uint8_t spad_count;
shalutha 0:69ce6d469c71 105 bool spad_type_is_aperture;
shalutha 0:69ce6d469c71 106 if (!getSpadInfo(&spad_count, &spad_type_is_aperture)) { return false; }
shalutha 0:69ce6d469c71 107
shalutha 0:69ce6d469c71 108 // The SPAD map (RefGoodSpadMap) is read by VL53L0X_get_info_from_device() in
shalutha 0:69ce6d469c71 109 // the API, but the same data seems to be more easily readable from
shalutha 0:69ce6d469c71 110 // GLOBAL_CONFIG_SPAD_ENABLES_REF_0 through _6, so read it from there
shalutha 0:69ce6d469c71 111 uint8_t ref_spad_map[6];
shalutha 0:69ce6d469c71 112 readMulti(GLOBAL_CONFIG_SPAD_ENABLES_REF_0, ref_spad_map, 6);
shalutha 0:69ce6d469c71 113
shalutha 0:69ce6d469c71 114 // -- VL53L0X_set_reference_spads() begin (assume NVM values are valid)
shalutha 0:69ce6d469c71 115
shalutha 0:69ce6d469c71 116 writeReg(0xFF, 0x01);
shalutha 0:69ce6d469c71 117 writeReg(DYNAMIC_SPAD_REF_EN_START_OFFSET, 0x00);
shalutha 0:69ce6d469c71 118 writeReg(DYNAMIC_SPAD_NUM_REQUESTED_REF_SPAD, 0x2C);
shalutha 0:69ce6d469c71 119 writeReg(0xFF, 0x00);
shalutha 0:69ce6d469c71 120 writeReg(GLOBAL_CONFIG_REF_EN_START_SELECT, 0xB4);
shalutha 0:69ce6d469c71 121
shalutha 0:69ce6d469c71 122 uint8_t first_spad_to_enable = spad_type_is_aperture ? 12 : 0; // 12 is the first aperture spad
shalutha 0:69ce6d469c71 123 uint8_t spads_enabled = 0;
shalutha 0:69ce6d469c71 124
shalutha 0:69ce6d469c71 125 for (uint8_t i = 0; i < 48; i++)
shalutha 0:69ce6d469c71 126 {
shalutha 0:69ce6d469c71 127 if (i < first_spad_to_enable || spads_enabled == spad_count)
shalutha 0:69ce6d469c71 128 {
shalutha 0:69ce6d469c71 129 // This bit is lower than the first one that should be enabled, or
shalutha 0:69ce6d469c71 130 // (reference_spad_count) bits have already been enabled, so zero this bit
shalutha 0:69ce6d469c71 131 ref_spad_map[i / 8] &= ~(1 << (i % 8));
shalutha 0:69ce6d469c71 132 }
shalutha 0:69ce6d469c71 133 else if ((ref_spad_map[i / 8] >> (i % 8)) & 0x1)
shalutha 0:69ce6d469c71 134 {
shalutha 0:69ce6d469c71 135 spads_enabled++;
shalutha 0:69ce6d469c71 136 }
shalutha 0:69ce6d469c71 137 }
shalutha 0:69ce6d469c71 138
shalutha 0:69ce6d469c71 139 writeMulti(GLOBAL_CONFIG_SPAD_ENABLES_REF_0, ref_spad_map, 6);
shalutha 0:69ce6d469c71 140
shalutha 0:69ce6d469c71 141 // -- VL53L0X_set_reference_spads() end
shalutha 0:69ce6d469c71 142
shalutha 0:69ce6d469c71 143 // -- VL53L0X_load_tuning_settings() begin
shalutha 0:69ce6d469c71 144 // DefaultTuningSettings from vl53l0x_tuning.h
shalutha 0:69ce6d469c71 145
shalutha 0:69ce6d469c71 146 writeReg(0xFF, 0x01);
shalutha 0:69ce6d469c71 147 writeReg(0x00, 0x00);
shalutha 0:69ce6d469c71 148
shalutha 0:69ce6d469c71 149 writeReg(0xFF, 0x00);
shalutha 0:69ce6d469c71 150 writeReg(0x09, 0x00);
shalutha 0:69ce6d469c71 151 writeReg(0x10, 0x00);
shalutha 0:69ce6d469c71 152 writeReg(0x11, 0x00);
shalutha 0:69ce6d469c71 153
shalutha 0:69ce6d469c71 154 writeReg(0x24, 0x01);
shalutha 0:69ce6d469c71 155 writeReg(0x25, 0xFF);
shalutha 0:69ce6d469c71 156 writeReg(0x75, 0x00);
shalutha 0:69ce6d469c71 157
shalutha 0:69ce6d469c71 158 writeReg(0xFF, 0x01);
shalutha 0:69ce6d469c71 159 writeReg(0x4E, 0x2C);
shalutha 0:69ce6d469c71 160 writeReg(0x48, 0x00);
shalutha 0:69ce6d469c71 161 writeReg(0x30, 0x20);
shalutha 0:69ce6d469c71 162
shalutha 0:69ce6d469c71 163 writeReg(0xFF, 0x00);
shalutha 0:69ce6d469c71 164 writeReg(0x30, 0x09);
shalutha 0:69ce6d469c71 165 writeReg(0x54, 0x00);
shalutha 0:69ce6d469c71 166 writeReg(0x31, 0x04);
shalutha 0:69ce6d469c71 167 writeReg(0x32, 0x03);
shalutha 0:69ce6d469c71 168 writeReg(0x40, 0x83);
shalutha 0:69ce6d469c71 169 writeReg(0x46, 0x25);
shalutha 0:69ce6d469c71 170 writeReg(0x60, 0x00);
shalutha 0:69ce6d469c71 171 writeReg(0x27, 0x00);
shalutha 0:69ce6d469c71 172 writeReg(0x50, 0x06);
shalutha 0:69ce6d469c71 173 writeReg(0x51, 0x00);
shalutha 0:69ce6d469c71 174 writeReg(0x52, 0x96);
shalutha 0:69ce6d469c71 175 writeReg(0x56, 0x08);
shalutha 0:69ce6d469c71 176 writeReg(0x57, 0x30);
shalutha 0:69ce6d469c71 177 writeReg(0x61, 0x00);
shalutha 0:69ce6d469c71 178 writeReg(0x62, 0x00);
shalutha 0:69ce6d469c71 179 writeReg(0x64, 0x00);
shalutha 0:69ce6d469c71 180 writeReg(0x65, 0x00);
shalutha 0:69ce6d469c71 181 writeReg(0x66, 0xA0);
shalutha 0:69ce6d469c71 182
shalutha 0:69ce6d469c71 183 writeReg(0xFF, 0x01);
shalutha 0:69ce6d469c71 184 writeReg(0x22, 0x32);
shalutha 0:69ce6d469c71 185 writeReg(0x47, 0x14);
shalutha 0:69ce6d469c71 186 writeReg(0x49, 0xFF);
shalutha 0:69ce6d469c71 187 writeReg(0x4A, 0x00);
shalutha 0:69ce6d469c71 188
shalutha 0:69ce6d469c71 189 writeReg(0xFF, 0x00);
shalutha 0:69ce6d469c71 190 writeReg(0x7A, 0x0A);
shalutha 0:69ce6d469c71 191 writeReg(0x7B, 0x00);
shalutha 0:69ce6d469c71 192 writeReg(0x78, 0x21);
shalutha 0:69ce6d469c71 193
shalutha 0:69ce6d469c71 194 writeReg(0xFF, 0x01);
shalutha 0:69ce6d469c71 195 writeReg(0x23, 0x34);
shalutha 0:69ce6d469c71 196 writeReg(0x42, 0x00);
shalutha 0:69ce6d469c71 197 writeReg(0x44, 0xFF);
shalutha 0:69ce6d469c71 198 writeReg(0x45, 0x26);
shalutha 0:69ce6d469c71 199 writeReg(0x46, 0x05);
shalutha 0:69ce6d469c71 200 writeReg(0x40, 0x40);
shalutha 0:69ce6d469c71 201 writeReg(0x0E, 0x06);
shalutha 0:69ce6d469c71 202 writeReg(0x20, 0x1A);
shalutha 0:69ce6d469c71 203 writeReg(0x43, 0x40);
shalutha 0:69ce6d469c71 204
shalutha 0:69ce6d469c71 205 writeReg(0xFF, 0x00);
shalutha 0:69ce6d469c71 206 writeReg(0x34, 0x03);
shalutha 0:69ce6d469c71 207 writeReg(0x35, 0x44);
shalutha 0:69ce6d469c71 208
shalutha 0:69ce6d469c71 209 writeReg(0xFF, 0x01);
shalutha 0:69ce6d469c71 210 writeReg(0x31, 0x04);
shalutha 0:69ce6d469c71 211 writeReg(0x4B, 0x09);
shalutha 0:69ce6d469c71 212 writeReg(0x4C, 0x05);
shalutha 0:69ce6d469c71 213 writeReg(0x4D, 0x04);
shalutha 0:69ce6d469c71 214
shalutha 0:69ce6d469c71 215 writeReg(0xFF, 0x00);
shalutha 0:69ce6d469c71 216 writeReg(0x44, 0x00);
shalutha 0:69ce6d469c71 217 writeReg(0x45, 0x20);
shalutha 0:69ce6d469c71 218 writeReg(0x47, 0x08);
shalutha 0:69ce6d469c71 219 writeReg(0x48, 0x28);
shalutha 0:69ce6d469c71 220 writeReg(0x67, 0x00);
shalutha 0:69ce6d469c71 221 writeReg(0x70, 0x04);
shalutha 0:69ce6d469c71 222 writeReg(0x71, 0x01);
shalutha 0:69ce6d469c71 223 writeReg(0x72, 0xFE);
shalutha 0:69ce6d469c71 224 writeReg(0x76, 0x00);
shalutha 0:69ce6d469c71 225 writeReg(0x77, 0x00);
shalutha 0:69ce6d469c71 226
shalutha 0:69ce6d469c71 227 writeReg(0xFF, 0x01);
shalutha 0:69ce6d469c71 228 writeReg(0x0D, 0x01);
shalutha 0:69ce6d469c71 229
shalutha 0:69ce6d469c71 230 writeReg(0xFF, 0x00);
shalutha 0:69ce6d469c71 231 writeReg(0x80, 0x01);
shalutha 0:69ce6d469c71 232 writeReg(0x01, 0xF8);
shalutha 0:69ce6d469c71 233
shalutha 0:69ce6d469c71 234 writeReg(0xFF, 0x01);
shalutha 0:69ce6d469c71 235 writeReg(0x8E, 0x01);
shalutha 0:69ce6d469c71 236 writeReg(0x00, 0x01);
shalutha 0:69ce6d469c71 237 writeReg(0xFF, 0x00);
shalutha 0:69ce6d469c71 238 writeReg(0x80, 0x00);
shalutha 0:69ce6d469c71 239
shalutha 0:69ce6d469c71 240 // -- VL53L0X_load_tuning_settings() end
shalutha 0:69ce6d469c71 241
shalutha 0:69ce6d469c71 242 // "Set interrupt config to new sample ready"
shalutha 0:69ce6d469c71 243 // -- VL53L0X_SetGpioConfig() begin
shalutha 0:69ce6d469c71 244
shalutha 0:69ce6d469c71 245 writeReg(SYSTEM_INTERRUPT_CONFIG_GPIO, 0x04);
shalutha 0:69ce6d469c71 246 writeReg(GPIO_HV_MUX_ACTIVE_HIGH, readReg(GPIO_HV_MUX_ACTIVE_HIGH) & ~0x10); // active low
shalutha 0:69ce6d469c71 247 writeReg(SYSTEM_INTERRUPT_CLEAR, 0x01);
shalutha 0:69ce6d469c71 248
shalutha 0:69ce6d469c71 249 // -- VL53L0X_SetGpioConfig() end
shalutha 0:69ce6d469c71 250
shalutha 0:69ce6d469c71 251 measurement_timing_budget_us = getMeasurementTimingBudget();
shalutha 0:69ce6d469c71 252
shalutha 0:69ce6d469c71 253 // "Disable MSRC and TCC by default"
shalutha 0:69ce6d469c71 254 // MSRC = Minimum Signal Rate Check
shalutha 0:69ce6d469c71 255 // TCC = Target CentreCheck
shalutha 0:69ce6d469c71 256 // -- VL53L0X_SetSequenceStepEnable() begin
shalutha 0:69ce6d469c71 257
shalutha 0:69ce6d469c71 258 writeReg(SYSTEM_SEQUENCE_CONFIG, 0xE8);
shalutha 0:69ce6d469c71 259
shalutha 0:69ce6d469c71 260 // -- VL53L0X_SetSequenceStepEnable() end
shalutha 0:69ce6d469c71 261
shalutha 0:69ce6d469c71 262 // "Recalculate timing budget"
shalutha 0:69ce6d469c71 263 setMeasurementTimingBudget(measurement_timing_budget_us);
shalutha 0:69ce6d469c71 264
shalutha 0:69ce6d469c71 265 // VL53L0X_StaticInit() end
shalutha 0:69ce6d469c71 266
shalutha 0:69ce6d469c71 267 // VL53L0X_PerformRefCalibration() begin (VL53L0X_perform_ref_calibration())
shalutha 0:69ce6d469c71 268
shalutha 0:69ce6d469c71 269 // -- VL53L0X_perform_vhv_calibration() begin
shalutha 0:69ce6d469c71 270
shalutha 0:69ce6d469c71 271 writeReg(SYSTEM_SEQUENCE_CONFIG, 0x01);
shalutha 0:69ce6d469c71 272 if (!performSingleRefCalibration(0x40)) { return false; }
shalutha 0:69ce6d469c71 273
shalutha 0:69ce6d469c71 274 // -- VL53L0X_perform_vhv_calibration() end
shalutha 0:69ce6d469c71 275
shalutha 0:69ce6d469c71 276 // -- VL53L0X_perform_phase_calibration() begin
shalutha 0:69ce6d469c71 277
shalutha 0:69ce6d469c71 278 writeReg(SYSTEM_SEQUENCE_CONFIG, 0x02);
shalutha 0:69ce6d469c71 279 if (!performSingleRefCalibration(0x00)) { return false; }
shalutha 0:69ce6d469c71 280
shalutha 0:69ce6d469c71 281 // -- VL53L0X_perform_phase_calibration() end
shalutha 0:69ce6d469c71 282
shalutha 0:69ce6d469c71 283 // "restore the previous Sequence Config"
shalutha 0:69ce6d469c71 284 writeReg(SYSTEM_SEQUENCE_CONFIG, 0xE8);
shalutha 0:69ce6d469c71 285
shalutha 0:69ce6d469c71 286 // VL53L0X_PerformRefCalibration() end
shalutha 0:69ce6d469c71 287
shalutha 0:69ce6d469c71 288 return true;
shalutha 0:69ce6d469c71 289 }
shalutha 0:69ce6d469c71 290
shalutha 0:69ce6d469c71 291 // Write an 8-bit register
shalutha 0:69ce6d469c71 292 void VL53L0X::writeReg(uint8_t reg, uint8_t value)
shalutha 0:69ce6d469c71 293 {
shalutha 0:69ce6d469c71 294 char data[] = {
shalutha 0:69ce6d469c71 295 reg,
shalutha 0:69ce6d469c71 296 value
shalutha 0:69ce6d469c71 297 };
shalutha 0:69ce6d469c71 298 if (i2c->write(address, data, 2)) {
shalutha 0:69ce6d469c71 299 last_status = ERR_OTHER;
shalutha 0:69ce6d469c71 300 } else {
shalutha 0:69ce6d469c71 301 last_status = ERR_OK;
shalutha 0:69ce6d469c71 302 }
shalutha 0:69ce6d469c71 303 }
shalutha 0:69ce6d469c71 304
shalutha 0:69ce6d469c71 305 // Write a 16-bit register
shalutha 0:69ce6d469c71 306 void VL53L0X::writeReg16Bit(uint8_t reg, uint16_t value)
shalutha 0:69ce6d469c71 307 {
shalutha 0:69ce6d469c71 308 char data[] = {
shalutha 0:69ce6d469c71 309 reg,
shalutha 0:69ce6d469c71 310 static_cast<char>((value >> 8) & 0xFF), // value high byte
shalutha 0:69ce6d469c71 311 static_cast<char>(value & 0xFF) // value low byte
shalutha 0:69ce6d469c71 312 };
shalutha 0:69ce6d469c71 313 if (i2c->write(address, data, 3)) {
shalutha 0:69ce6d469c71 314 last_status = ERR_OTHER;
shalutha 0:69ce6d469c71 315 } else {
shalutha 0:69ce6d469c71 316 last_status = ERR_OK;
shalutha 0:69ce6d469c71 317 }
shalutha 0:69ce6d469c71 318 }
shalutha 0:69ce6d469c71 319
shalutha 0:69ce6d469c71 320 // Write a 32-bit register
shalutha 0:69ce6d469c71 321 void VL53L0X::writeReg32Bit(uint8_t reg, uint32_t value)
shalutha 0:69ce6d469c71 322 {
shalutha 0:69ce6d469c71 323 char data[] = {
shalutha 0:69ce6d469c71 324 reg,
shalutha 0:69ce6d469c71 325 static_cast<char>((value >> 24) & 0xFF), // value highest byte
shalutha 0:69ce6d469c71 326 static_cast<char>((value >> 16) & 0xFF),
shalutha 0:69ce6d469c71 327 static_cast<char>((value >> 8) & 0xFF),
shalutha 0:69ce6d469c71 328 static_cast<char>(value & 0xFF) // value lowest byte
shalutha 0:69ce6d469c71 329 };
shalutha 0:69ce6d469c71 330 if (i2c->write(address, data, 5)) {
shalutha 0:69ce6d469c71 331 last_status = ERR_OTHER;
shalutha 0:69ce6d469c71 332 } else {
shalutha 0:69ce6d469c71 333 last_status = ERR_OK;
shalutha 0:69ce6d469c71 334 }
shalutha 0:69ce6d469c71 335 }
shalutha 0:69ce6d469c71 336
shalutha 0:69ce6d469c71 337 // Read an 8-bit register
shalutha 0:69ce6d469c71 338 uint8_t VL53L0X::readReg(uint8_t reg)
shalutha 0:69ce6d469c71 339 {
shalutha 0:69ce6d469c71 340 uint8_t value;
shalutha 0:69ce6d469c71 341
shalutha 0:69ce6d469c71 342 if (i2c->write(address, reinterpret_cast<char *>(&reg), 1)) {
shalutha 0:69ce6d469c71 343 last_status = ERR_NACK_ADDR;
shalutha 0:69ce6d469c71 344 return 0;
shalutha 0:69ce6d469c71 345 }
shalutha 0:69ce6d469c71 346 if (i2c->read(address, reinterpret_cast<char *>(&value), 1)) {
shalutha 0:69ce6d469c71 347 last_status = ERR_NACK_DATA;
shalutha 0:69ce6d469c71 348 return 0;
shalutha 0:69ce6d469c71 349 }
shalutha 0:69ce6d469c71 350 last_status = ERR_OK;
shalutha 0:69ce6d469c71 351
shalutha 0:69ce6d469c71 352 return value;
shalutha 0:69ce6d469c71 353 }
shalutha 0:69ce6d469c71 354
shalutha 0:69ce6d469c71 355 // Read a 16-bit register
shalutha 0:69ce6d469c71 356 uint16_t VL53L0X::readReg16Bit(uint8_t reg)
shalutha 0:69ce6d469c71 357 {
shalutha 0:69ce6d469c71 358 uint16_t value;
shalutha 0:69ce6d469c71 359 uint8_t data[2];
shalutha 0:69ce6d469c71 360
shalutha 0:69ce6d469c71 361 if (i2c->write(address, reinterpret_cast<char *>(&reg), 1)) {
shalutha 0:69ce6d469c71 362 last_status = ERR_NACK_ADDR;
shalutha 0:69ce6d469c71 363 return 0;
shalutha 0:69ce6d469c71 364 }
shalutha 0:69ce6d469c71 365 if (i2c->read(address, reinterpret_cast<char *>(data), 2)) {
shalutha 0:69ce6d469c71 366 last_status = ERR_NACK_DATA;
shalutha 0:69ce6d469c71 367 return 0;
shalutha 0:69ce6d469c71 368 }
shalutha 0:69ce6d469c71 369 last_status = ERR_OK;
shalutha 0:69ce6d469c71 370
shalutha 0:69ce6d469c71 371 value = static_cast<uint16_t>(data[0] << 8); // value high byte
shalutha 0:69ce6d469c71 372 value |= data[1]; // value low byte
shalutha 0:69ce6d469c71 373
shalutha 0:69ce6d469c71 374 return value;
shalutha 0:69ce6d469c71 375 }
shalutha 0:69ce6d469c71 376
shalutha 0:69ce6d469c71 377 // Read a 32-bit register
shalutha 0:69ce6d469c71 378 uint32_t VL53L0X::readReg32Bit(uint8_t reg)
shalutha 0:69ce6d469c71 379 {
shalutha 0:69ce6d469c71 380 uint32_t value;
shalutha 0:69ce6d469c71 381 uint8_t data[4];
shalutha 0:69ce6d469c71 382
shalutha 0:69ce6d469c71 383 if (i2c->write(address, reinterpret_cast<char *>(&reg), 1)) {
shalutha 0:69ce6d469c71 384 last_status = ERR_NACK_ADDR;
shalutha 0:69ce6d469c71 385 return 0;
shalutha 0:69ce6d469c71 386 }
shalutha 0:69ce6d469c71 387 if (i2c->read(address, reinterpret_cast<char *>(data), 4)) {
shalutha 0:69ce6d469c71 388 last_status = ERR_NACK_DATA;
shalutha 0:69ce6d469c71 389 return 0;
shalutha 0:69ce6d469c71 390 }
shalutha 0:69ce6d469c71 391 last_status = ERR_OK;
shalutha 0:69ce6d469c71 392
shalutha 0:69ce6d469c71 393 value = static_cast<uint32_t>(data[0] << 24); // value highest byte
shalutha 0:69ce6d469c71 394 value |= static_cast<uint32_t>(data[1] << 16);
shalutha 0:69ce6d469c71 395 value |= static_cast<uint32_t>(data[2] << 8);
shalutha 0:69ce6d469c71 396 value |= data[3]; // value lowest byte
shalutha 0:69ce6d469c71 397
shalutha 0:69ce6d469c71 398 return value;
shalutha 0:69ce6d469c71 399 }
shalutha 0:69ce6d469c71 400
shalutha 0:69ce6d469c71 401 // Write an arbitrary number of bytes from the given array to the sensor,
shalutha 0:69ce6d469c71 402 // starting at the given register
shalutha 0:69ce6d469c71 403 void VL53L0X::writeMulti(uint8_t reg, uint8_t const * src, uint8_t count)
shalutha 0:69ce6d469c71 404 {
shalutha 0:69ce6d469c71 405 if (i2c->write(address, reinterpret_cast<char *>(&reg), 1, true)) {
shalutha 0:69ce6d469c71 406 last_status = ERR_NACK_ADDR;
shalutha 0:69ce6d469c71 407 return;
shalutha 0:69ce6d469c71 408 }
shalutha 0:69ce6d469c71 409
shalutha 0:69ce6d469c71 410 if (i2c->write(address, const_cast<char *>(
shalutha 0:69ce6d469c71 411 reinterpret_cast<const char *>(src)), count)) {
shalutha 0:69ce6d469c71 412 last_status = ERR_NACK_DATA;
shalutha 0:69ce6d469c71 413 return;
shalutha 0:69ce6d469c71 414 }
shalutha 0:69ce6d469c71 415 last_status = ERR_OK;
shalutha 0:69ce6d469c71 416 }
shalutha 0:69ce6d469c71 417
shalutha 0:69ce6d469c71 418 // Read an arbitrary number of bytes from the sensor, starting at the given
shalutha 0:69ce6d469c71 419 // register, into the given array
shalutha 0:69ce6d469c71 420 void VL53L0X::readMulti(uint8_t reg, uint8_t * dst, uint8_t count)
shalutha 0:69ce6d469c71 421 {
shalutha 0:69ce6d469c71 422 if (i2c->write(address, reinterpret_cast<char *>(&reg), 1)) {
shalutha 0:69ce6d469c71 423 last_status = ERR_NACK_ADDR;
shalutha 0:69ce6d469c71 424 return;
shalutha 0:69ce6d469c71 425 }
shalutha 0:69ce6d469c71 426 if (i2c->read(address, reinterpret_cast<char *>(dst), count)) {
shalutha 0:69ce6d469c71 427 last_status = ERR_NACK_DATA;
shalutha 0:69ce6d469c71 428 return;
shalutha 0:69ce6d469c71 429 }
shalutha 0:69ce6d469c71 430 last_status = ERR_OK;
shalutha 0:69ce6d469c71 431 }
shalutha 0:69ce6d469c71 432
shalutha 0:69ce6d469c71 433 // Set the return signal rate limit check value in units of MCPS (mega counts
shalutha 0:69ce6d469c71 434 // per second). "This represents the amplitude of the signal reflected from the
shalutha 0:69ce6d469c71 435 // target and detected by the device"; setting this limit presumably determines
shalutha 0:69ce6d469c71 436 // the minimum measurement necessary for the sensor to report a valid reading.
shalutha 0:69ce6d469c71 437 // Setting a lower limit increases the potential range of the sensor but also
shalutha 0:69ce6d469c71 438 // seems to increase the likelihood of getting an inaccurate reading because of
shalutha 0:69ce6d469c71 439 // unwanted reflections from objects other than the intended target.
shalutha 0:69ce6d469c71 440 // Defaults to 0.25 MCPS as initialized by the ST API and this library.
shalutha 0:69ce6d469c71 441 bool VL53L0X::setSignalRateLimit(float limit_Mcps)
shalutha 0:69ce6d469c71 442 {
shalutha 0:69ce6d469c71 443 if (limit_Mcps < 0 || limit_Mcps > 511.99) { return false; }
shalutha 0:69ce6d469c71 444
shalutha 0:69ce6d469c71 445 // Q9.7 fixed point format (9 integer bits, 7 fractional bits)
shalutha 0:69ce6d469c71 446 writeReg16Bit(FINAL_RANGE_CONFIG_MIN_COUNT_RATE_RTN_LIMIT, limit_Mcps * (1 << 7));
shalutha 0:69ce6d469c71 447 return true;
shalutha 0:69ce6d469c71 448 }
shalutha 0:69ce6d469c71 449
shalutha 0:69ce6d469c71 450 // Get the return signal rate limit check value in MCPS
shalutha 0:69ce6d469c71 451 float VL53L0X::getSignalRateLimit(void)
shalutha 0:69ce6d469c71 452 {
shalutha 0:69ce6d469c71 453 return (float)readReg16Bit(FINAL_RANGE_CONFIG_MIN_COUNT_RATE_RTN_LIMIT) / (1 << 7);
shalutha 0:69ce6d469c71 454 }
shalutha 0:69ce6d469c71 455
shalutha 0:69ce6d469c71 456 // Set the measurement timing budget in microseconds, which is the time allowed
shalutha 0:69ce6d469c71 457 // for one measurement; the ST API and this library take care of splitting the
shalutha 0:69ce6d469c71 458 // timing budget among the sub-steps in the ranging sequence. A longer timing
shalutha 0:69ce6d469c71 459 // budget allows for more accurate measurements. Increasing the budget by a
shalutha 0:69ce6d469c71 460 // factor of N decreases the range measurement standard deviation by a factor of
shalutha 0:69ce6d469c71 461 // sqrt(N). Defaults to about 33 milliseconds; the minimum is 20 ms.
shalutha 0:69ce6d469c71 462 // based on VL53L0X_set_measurement_timing_budget_micro_seconds()
shalutha 0:69ce6d469c71 463 bool VL53L0X::setMeasurementTimingBudget(uint32_t budget_us)
shalutha 0:69ce6d469c71 464 {
shalutha 0:69ce6d469c71 465 SequenceStepEnables enables;
shalutha 0:69ce6d469c71 466 SequenceStepTimeouts timeouts;
shalutha 0:69ce6d469c71 467
shalutha 0:69ce6d469c71 468 uint16_t const StartOverhead = 1320; // note that this is different than the value in get_
shalutha 0:69ce6d469c71 469 uint16_t const EndOverhead = 960;
shalutha 0:69ce6d469c71 470 uint16_t const MsrcOverhead = 660;
shalutha 0:69ce6d469c71 471 uint16_t const TccOverhead = 590;
shalutha 0:69ce6d469c71 472 uint16_t const DssOverhead = 690;
shalutha 0:69ce6d469c71 473 uint16_t const PreRangeOverhead = 660;
shalutha 0:69ce6d469c71 474 uint16_t const FinalRangeOverhead = 550;
shalutha 0:69ce6d469c71 475
shalutha 0:69ce6d469c71 476 uint32_t const MinTimingBudget = 20000;
shalutha 0:69ce6d469c71 477
shalutha 0:69ce6d469c71 478 if (budget_us < MinTimingBudget) { return false; }
shalutha 0:69ce6d469c71 479
shalutha 0:69ce6d469c71 480 uint32_t used_budget_us = StartOverhead + EndOverhead;
shalutha 0:69ce6d469c71 481
shalutha 0:69ce6d469c71 482 getSequenceStepEnables(&enables);
shalutha 0:69ce6d469c71 483 getSequenceStepTimeouts(&enables, &timeouts);
shalutha 0:69ce6d469c71 484
shalutha 0:69ce6d469c71 485 if (enables.tcc)
shalutha 0:69ce6d469c71 486 {
shalutha 0:69ce6d469c71 487 used_budget_us += (timeouts.msrc_dss_tcc_us + TccOverhead);
shalutha 0:69ce6d469c71 488 }
shalutha 0:69ce6d469c71 489
shalutha 0:69ce6d469c71 490 if (enables.dss)
shalutha 0:69ce6d469c71 491 {
shalutha 0:69ce6d469c71 492 used_budget_us += 2 * (timeouts.msrc_dss_tcc_us + DssOverhead);
shalutha 0:69ce6d469c71 493 }
shalutha 0:69ce6d469c71 494 else if (enables.msrc)
shalutha 0:69ce6d469c71 495 {
shalutha 0:69ce6d469c71 496 used_budget_us += (timeouts.msrc_dss_tcc_us + MsrcOverhead);
shalutha 0:69ce6d469c71 497 }
shalutha 0:69ce6d469c71 498
shalutha 0:69ce6d469c71 499 if (enables.pre_range)
shalutha 0:69ce6d469c71 500 {
shalutha 0:69ce6d469c71 501 used_budget_us += (timeouts.pre_range_us + PreRangeOverhead);
shalutha 0:69ce6d469c71 502 }
shalutha 0:69ce6d469c71 503
shalutha 0:69ce6d469c71 504 if (enables.final_range)
shalutha 0:69ce6d469c71 505 {
shalutha 0:69ce6d469c71 506 used_budget_us += FinalRangeOverhead;
shalutha 0:69ce6d469c71 507
shalutha 0:69ce6d469c71 508 // "Note that the final range timeout is determined by the timing
shalutha 0:69ce6d469c71 509 // budget and the sum of all other timeouts within the sequence.
shalutha 0:69ce6d469c71 510 // If there is no room for the final range timeout, then an error
shalutha 0:69ce6d469c71 511 // will be set. Otherwise the remaining time will be applied to
shalutha 0:69ce6d469c71 512 // the final range."
shalutha 0:69ce6d469c71 513
shalutha 0:69ce6d469c71 514 if (used_budget_us > budget_us)
shalutha 0:69ce6d469c71 515 {
shalutha 0:69ce6d469c71 516 // "Requested timeout too big."
shalutha 0:69ce6d469c71 517 return false;
shalutha 0:69ce6d469c71 518 }
shalutha 0:69ce6d469c71 519
shalutha 0:69ce6d469c71 520 uint32_t final_range_timeout_us = budget_us - used_budget_us;
shalutha 0:69ce6d469c71 521
shalutha 0:69ce6d469c71 522 // set_sequence_step_timeout() begin
shalutha 0:69ce6d469c71 523 // (SequenceStepId == VL53L0X_SEQUENCESTEP_FINAL_RANGE)
shalutha 0:69ce6d469c71 524
shalutha 0:69ce6d469c71 525 // "For the final range timeout, the pre-range timeout
shalutha 0:69ce6d469c71 526 // must be added. To do this both final and pre-range
shalutha 0:69ce6d469c71 527 // timeouts must be expressed in macro periods MClks
shalutha 0:69ce6d469c71 528 // because they have different vcsel periods."
shalutha 0:69ce6d469c71 529
shalutha 0:69ce6d469c71 530 uint16_t final_range_timeout_mclks =
shalutha 0:69ce6d469c71 531 timeoutMicrosecondsToMclks(final_range_timeout_us,
shalutha 0:69ce6d469c71 532 timeouts.final_range_vcsel_period_pclks);
shalutha 0:69ce6d469c71 533
shalutha 0:69ce6d469c71 534 if (enables.pre_range)
shalutha 0:69ce6d469c71 535 {
shalutha 0:69ce6d469c71 536 final_range_timeout_mclks += timeouts.pre_range_mclks;
shalutha 0:69ce6d469c71 537 }
shalutha 0:69ce6d469c71 538
shalutha 0:69ce6d469c71 539 writeReg16Bit(FINAL_RANGE_CONFIG_TIMEOUT_MACROP_HI,
shalutha 0:69ce6d469c71 540 encodeTimeout(final_range_timeout_mclks));
shalutha 0:69ce6d469c71 541
shalutha 0:69ce6d469c71 542 // set_sequence_step_timeout() end
shalutha 0:69ce6d469c71 543
shalutha 0:69ce6d469c71 544 measurement_timing_budget_us = budget_us; // store for internal reuse
shalutha 0:69ce6d469c71 545 }
shalutha 0:69ce6d469c71 546 return true;
shalutha 0:69ce6d469c71 547 }
shalutha 0:69ce6d469c71 548
shalutha 0:69ce6d469c71 549 // Get the measurement timing budget in microseconds
shalutha 0:69ce6d469c71 550 // based on VL53L0X_get_measurement_timing_budget_micro_seconds()
shalutha 0:69ce6d469c71 551 // in us
shalutha 0:69ce6d469c71 552 uint32_t VL53L0X::getMeasurementTimingBudget(void)
shalutha 0:69ce6d469c71 553 {
shalutha 0:69ce6d469c71 554 SequenceStepEnables enables;
shalutha 0:69ce6d469c71 555 SequenceStepTimeouts timeouts;
shalutha 0:69ce6d469c71 556
shalutha 0:69ce6d469c71 557 uint16_t const StartOverhead = 1910; // note that this is different than the value in set_
shalutha 0:69ce6d469c71 558 uint16_t const EndOverhead = 960;
shalutha 0:69ce6d469c71 559 uint16_t const MsrcOverhead = 660;
shalutha 0:69ce6d469c71 560 uint16_t const TccOverhead = 590;
shalutha 0:69ce6d469c71 561 uint16_t const DssOverhead = 690;
shalutha 0:69ce6d469c71 562 uint16_t const PreRangeOverhead = 660;
shalutha 0:69ce6d469c71 563 uint16_t const FinalRangeOverhead = 550;
shalutha 0:69ce6d469c71 564
shalutha 0:69ce6d469c71 565 // "Start and end overhead times always present"
shalutha 0:69ce6d469c71 566 uint32_t budget_us = StartOverhead + EndOverhead;
shalutha 0:69ce6d469c71 567
shalutha 0:69ce6d469c71 568 getSequenceStepEnables(&enables);
shalutha 0:69ce6d469c71 569 getSequenceStepTimeouts(&enables, &timeouts);
shalutha 0:69ce6d469c71 570
shalutha 0:69ce6d469c71 571 if (enables.tcc)
shalutha 0:69ce6d469c71 572 {
shalutha 0:69ce6d469c71 573 budget_us += (timeouts.msrc_dss_tcc_us + TccOverhead);
shalutha 0:69ce6d469c71 574 }
shalutha 0:69ce6d469c71 575
shalutha 0:69ce6d469c71 576 if (enables.dss)
shalutha 0:69ce6d469c71 577 {
shalutha 0:69ce6d469c71 578 budget_us += 2 * (timeouts.msrc_dss_tcc_us + DssOverhead);
shalutha 0:69ce6d469c71 579 }
shalutha 0:69ce6d469c71 580 else if (enables.msrc)
shalutha 0:69ce6d469c71 581 {
shalutha 0:69ce6d469c71 582 budget_us += (timeouts.msrc_dss_tcc_us + MsrcOverhead);
shalutha 0:69ce6d469c71 583 }
shalutha 0:69ce6d469c71 584
shalutha 0:69ce6d469c71 585 if (enables.pre_range)
shalutha 0:69ce6d469c71 586 {
shalutha 0:69ce6d469c71 587 budget_us += (timeouts.pre_range_us + PreRangeOverhead);
shalutha 0:69ce6d469c71 588 }
shalutha 0:69ce6d469c71 589
shalutha 0:69ce6d469c71 590 if (enables.final_range)
shalutha 0:69ce6d469c71 591 {
shalutha 0:69ce6d469c71 592 budget_us += (timeouts.final_range_us + FinalRangeOverhead);
shalutha 0:69ce6d469c71 593 }
shalutha 0:69ce6d469c71 594
shalutha 0:69ce6d469c71 595 measurement_timing_budget_us = budget_us; // store for internal reuse
shalutha 0:69ce6d469c71 596 return budget_us;
shalutha 0:69ce6d469c71 597 }
shalutha 0:69ce6d469c71 598
shalutha 0:69ce6d469c71 599 // Set the VCSEL (vertical cavity surface emitting laser) pulse period for the
shalutha 0:69ce6d469c71 600 // given period type (pre-range or final range) to the given value in PCLKs.
shalutha 0:69ce6d469c71 601 // Longer periods seem to increase the potential range of the sensor.
shalutha 0:69ce6d469c71 602 // Valid values are (even numbers only):
shalutha 0:69ce6d469c71 603 // pre: 12 to 18 (initialized default: 14)
shalutha 0:69ce6d469c71 604 // final: 8 to 14 (initialized default: 10)
shalutha 0:69ce6d469c71 605 // based on VL53L0X_set_vcsel_pulse_period()
shalutha 0:69ce6d469c71 606 bool VL53L0X::setVcselPulsePeriod(vcselPeriodType type, uint8_t period_pclks)
shalutha 0:69ce6d469c71 607 {
shalutha 0:69ce6d469c71 608 uint8_t vcsel_period_reg = encodeVcselPeriod(period_pclks);
shalutha 0:69ce6d469c71 609
shalutha 0:69ce6d469c71 610 SequenceStepEnables enables;
shalutha 0:69ce6d469c71 611 SequenceStepTimeouts timeouts;
shalutha 0:69ce6d469c71 612
shalutha 0:69ce6d469c71 613 getSequenceStepEnables(&enables);
shalutha 0:69ce6d469c71 614 getSequenceStepTimeouts(&enables, &timeouts);
shalutha 0:69ce6d469c71 615
shalutha 0:69ce6d469c71 616 // "Apply specific settings for the requested clock period"
shalutha 0:69ce6d469c71 617 // "Re-calculate and apply timeouts, in macro periods"
shalutha 0:69ce6d469c71 618
shalutha 0:69ce6d469c71 619 // "When the VCSEL period for the pre or final range is changed,
shalutha 0:69ce6d469c71 620 // the corresponding timeout must be read from the device using
shalutha 0:69ce6d469c71 621 // the current VCSEL period, then the new VCSEL period can be
shalutha 0:69ce6d469c71 622 // applied. The timeout then must be written back to the device
shalutha 0:69ce6d469c71 623 // using the new VCSEL period.
shalutha 0:69ce6d469c71 624 //
shalutha 0:69ce6d469c71 625 // For the MSRC timeout, the same applies - this timeout being
shalutha 0:69ce6d469c71 626 // dependant on the pre-range vcsel period."
shalutha 0:69ce6d469c71 627
shalutha 0:69ce6d469c71 628
shalutha 0:69ce6d469c71 629 if (type == VcselPeriodPreRange)
shalutha 0:69ce6d469c71 630 {
shalutha 0:69ce6d469c71 631 // "Set phase check limits"
shalutha 0:69ce6d469c71 632 switch (period_pclks)
shalutha 0:69ce6d469c71 633 {
shalutha 0:69ce6d469c71 634 case 12:
shalutha 0:69ce6d469c71 635 writeReg(PRE_RANGE_CONFIG_VALID_PHASE_HIGH, 0x18);
shalutha 0:69ce6d469c71 636 break;
shalutha 0:69ce6d469c71 637
shalutha 0:69ce6d469c71 638 case 14:
shalutha 0:69ce6d469c71 639 writeReg(PRE_RANGE_CONFIG_VALID_PHASE_HIGH, 0x30);
shalutha 0:69ce6d469c71 640 break;
shalutha 0:69ce6d469c71 641
shalutha 0:69ce6d469c71 642 case 16:
shalutha 0:69ce6d469c71 643 writeReg(PRE_RANGE_CONFIG_VALID_PHASE_HIGH, 0x40);
shalutha 0:69ce6d469c71 644 break;
shalutha 0:69ce6d469c71 645
shalutha 0:69ce6d469c71 646 case 18:
shalutha 0:69ce6d469c71 647 writeReg(PRE_RANGE_CONFIG_VALID_PHASE_HIGH, 0x50);
shalutha 0:69ce6d469c71 648 break;
shalutha 0:69ce6d469c71 649
shalutha 0:69ce6d469c71 650 default:
shalutha 0:69ce6d469c71 651 // invalid period
shalutha 0:69ce6d469c71 652 return false;
shalutha 0:69ce6d469c71 653 }
shalutha 0:69ce6d469c71 654 writeReg(PRE_RANGE_CONFIG_VALID_PHASE_LOW, 0x08);
shalutha 0:69ce6d469c71 655
shalutha 0:69ce6d469c71 656 // apply new VCSEL period
shalutha 0:69ce6d469c71 657 writeReg(PRE_RANGE_CONFIG_VCSEL_PERIOD, vcsel_period_reg);
shalutha 0:69ce6d469c71 658
shalutha 0:69ce6d469c71 659 // update timeouts
shalutha 0:69ce6d469c71 660
shalutha 0:69ce6d469c71 661 // set_sequence_step_timeout() begin
shalutha 0:69ce6d469c71 662 // (SequenceStepId == VL53L0X_SEQUENCESTEP_PRE_RANGE)
shalutha 0:69ce6d469c71 663
shalutha 0:69ce6d469c71 664 uint16_t new_pre_range_timeout_mclks =
shalutha 0:69ce6d469c71 665 timeoutMicrosecondsToMclks(timeouts.pre_range_us, period_pclks);
shalutha 0:69ce6d469c71 666
shalutha 0:69ce6d469c71 667 writeReg16Bit(PRE_RANGE_CONFIG_TIMEOUT_MACROP_HI,
shalutha 0:69ce6d469c71 668 encodeTimeout(new_pre_range_timeout_mclks));
shalutha 0:69ce6d469c71 669
shalutha 0:69ce6d469c71 670 // set_sequence_step_timeout() end
shalutha 0:69ce6d469c71 671
shalutha 0:69ce6d469c71 672 // set_sequence_step_timeout() begin
shalutha 0:69ce6d469c71 673 // (SequenceStepId == VL53L0X_SEQUENCESTEP_MSRC)
shalutha 0:69ce6d469c71 674
shalutha 0:69ce6d469c71 675 uint16_t new_msrc_timeout_mclks =
shalutha 0:69ce6d469c71 676 timeoutMicrosecondsToMclks(timeouts.msrc_dss_tcc_us, period_pclks);
shalutha 0:69ce6d469c71 677
shalutha 0:69ce6d469c71 678 writeReg(MSRC_CONFIG_TIMEOUT_MACROP,
shalutha 0:69ce6d469c71 679 (new_msrc_timeout_mclks > 256) ? 255 : (new_msrc_timeout_mclks - 1));
shalutha 0:69ce6d469c71 680
shalutha 0:69ce6d469c71 681 // set_sequence_step_timeout() end
shalutha 0:69ce6d469c71 682 }
shalutha 0:69ce6d469c71 683 else if (type == VcselPeriodFinalRange)
shalutha 0:69ce6d469c71 684 {
shalutha 0:69ce6d469c71 685 switch (period_pclks)
shalutha 0:69ce6d469c71 686 {
shalutha 0:69ce6d469c71 687 case 8:
shalutha 0:69ce6d469c71 688 writeReg(FINAL_RANGE_CONFIG_VALID_PHASE_HIGH, 0x10);
shalutha 0:69ce6d469c71 689 writeReg(FINAL_RANGE_CONFIG_VALID_PHASE_LOW, 0x08);
shalutha 0:69ce6d469c71 690 writeReg(GLOBAL_CONFIG_VCSEL_WIDTH, 0x02);
shalutha 0:69ce6d469c71 691 writeReg(ALGO_PHASECAL_CONFIG_TIMEOUT, 0x0C);
shalutha 0:69ce6d469c71 692 writeReg(0xFF, 0x01);
shalutha 0:69ce6d469c71 693 writeReg(ALGO_PHASECAL_LIM, 0x30);
shalutha 0:69ce6d469c71 694 writeReg(0xFF, 0x00);
shalutha 0:69ce6d469c71 695 break;
shalutha 0:69ce6d469c71 696
shalutha 0:69ce6d469c71 697 case 10:
shalutha 0:69ce6d469c71 698 writeReg(FINAL_RANGE_CONFIG_VALID_PHASE_HIGH, 0x28);
shalutha 0:69ce6d469c71 699 writeReg(FINAL_RANGE_CONFIG_VALID_PHASE_LOW, 0x08);
shalutha 0:69ce6d469c71 700 writeReg(GLOBAL_CONFIG_VCSEL_WIDTH, 0x03);
shalutha 0:69ce6d469c71 701 writeReg(ALGO_PHASECAL_CONFIG_TIMEOUT, 0x09);
shalutha 0:69ce6d469c71 702 writeReg(0xFF, 0x01);
shalutha 0:69ce6d469c71 703 writeReg(ALGO_PHASECAL_LIM, 0x20);
shalutha 0:69ce6d469c71 704 writeReg(0xFF, 0x00);
shalutha 0:69ce6d469c71 705 break;
shalutha 0:69ce6d469c71 706
shalutha 0:69ce6d469c71 707 case 12:
shalutha 0:69ce6d469c71 708 writeReg(FINAL_RANGE_CONFIG_VALID_PHASE_HIGH, 0x38);
shalutha 0:69ce6d469c71 709 writeReg(FINAL_RANGE_CONFIG_VALID_PHASE_LOW, 0x08);
shalutha 0:69ce6d469c71 710 writeReg(GLOBAL_CONFIG_VCSEL_WIDTH, 0x03);
shalutha 0:69ce6d469c71 711 writeReg(ALGO_PHASECAL_CONFIG_TIMEOUT, 0x08);
shalutha 0:69ce6d469c71 712 writeReg(0xFF, 0x01);
shalutha 0:69ce6d469c71 713 writeReg(ALGO_PHASECAL_LIM, 0x20);
shalutha 0:69ce6d469c71 714 writeReg(0xFF, 0x00);
shalutha 0:69ce6d469c71 715 break;
shalutha 0:69ce6d469c71 716
shalutha 0:69ce6d469c71 717 case 14:
shalutha 0:69ce6d469c71 718 writeReg(FINAL_RANGE_CONFIG_VALID_PHASE_HIGH, 0x48);
shalutha 0:69ce6d469c71 719 writeReg(FINAL_RANGE_CONFIG_VALID_PHASE_LOW, 0x08);
shalutha 0:69ce6d469c71 720 writeReg(GLOBAL_CONFIG_VCSEL_WIDTH, 0x03);
shalutha 0:69ce6d469c71 721 writeReg(ALGO_PHASECAL_CONFIG_TIMEOUT, 0x07);
shalutha 0:69ce6d469c71 722 writeReg(0xFF, 0x01);
shalutha 0:69ce6d469c71 723 writeReg(ALGO_PHASECAL_LIM, 0x20);
shalutha 0:69ce6d469c71 724 writeReg(0xFF, 0x00);
shalutha 0:69ce6d469c71 725 break;
shalutha 0:69ce6d469c71 726
shalutha 0:69ce6d469c71 727 default:
shalutha 0:69ce6d469c71 728 // invalid period
shalutha 0:69ce6d469c71 729 return false;
shalutha 0:69ce6d469c71 730 }
shalutha 0:69ce6d469c71 731
shalutha 0:69ce6d469c71 732 // apply new VCSEL period
shalutha 0:69ce6d469c71 733 writeReg(FINAL_RANGE_CONFIG_VCSEL_PERIOD, vcsel_period_reg);
shalutha 0:69ce6d469c71 734
shalutha 0:69ce6d469c71 735 // update timeouts
shalutha 0:69ce6d469c71 736
shalutha 0:69ce6d469c71 737 // set_sequence_step_timeout() begin
shalutha 0:69ce6d469c71 738 // (SequenceStepId == VL53L0X_SEQUENCESTEP_FINAL_RANGE)
shalutha 0:69ce6d469c71 739
shalutha 0:69ce6d469c71 740 // "For the final range timeout, the pre-range timeout
shalutha 0:69ce6d469c71 741 // must be added. To do this both final and pre-range
shalutha 0:69ce6d469c71 742 // timeouts must be expressed in macro periods MClks
shalutha 0:69ce6d469c71 743 // because they have different vcsel periods."
shalutha 0:69ce6d469c71 744
shalutha 0:69ce6d469c71 745 uint16_t new_final_range_timeout_mclks =
shalutha 0:69ce6d469c71 746 timeoutMicrosecondsToMclks(timeouts.final_range_us, period_pclks);
shalutha 0:69ce6d469c71 747
shalutha 0:69ce6d469c71 748 if (enables.pre_range)
shalutha 0:69ce6d469c71 749 {
shalutha 0:69ce6d469c71 750 new_final_range_timeout_mclks += timeouts.pre_range_mclks;
shalutha 0:69ce6d469c71 751 }
shalutha 0:69ce6d469c71 752
shalutha 0:69ce6d469c71 753 writeReg16Bit(FINAL_RANGE_CONFIG_TIMEOUT_MACROP_HI,
shalutha 0:69ce6d469c71 754 encodeTimeout(new_final_range_timeout_mclks));
shalutha 0:69ce6d469c71 755
shalutha 0:69ce6d469c71 756 // set_sequence_step_timeout end
shalutha 0:69ce6d469c71 757 }
shalutha 0:69ce6d469c71 758 else
shalutha 0:69ce6d469c71 759 {
shalutha 0:69ce6d469c71 760 // invalid type
shalutha 0:69ce6d469c71 761 return false;
shalutha 0:69ce6d469c71 762 }
shalutha 0:69ce6d469c71 763
shalutha 0:69ce6d469c71 764 // "Finally, the timing budget must be re-applied"
shalutha 0:69ce6d469c71 765
shalutha 0:69ce6d469c71 766 setMeasurementTimingBudget(measurement_timing_budget_us);
shalutha 0:69ce6d469c71 767
shalutha 0:69ce6d469c71 768 // "Perform the phase calibration. This is needed after changing on vcsel period."
shalutha 0:69ce6d469c71 769 // VL53L0X_perform_phase_calibration() begin
shalutha 0:69ce6d469c71 770
shalutha 0:69ce6d469c71 771 uint8_t sequence_config = readReg(SYSTEM_SEQUENCE_CONFIG);
shalutha 0:69ce6d469c71 772 writeReg(SYSTEM_SEQUENCE_CONFIG, 0x02);
shalutha 0:69ce6d469c71 773 performSingleRefCalibration(0x0);
shalutha 0:69ce6d469c71 774 writeReg(SYSTEM_SEQUENCE_CONFIG, sequence_config);
shalutha 0:69ce6d469c71 775
shalutha 0:69ce6d469c71 776 // VL53L0X_perform_phase_calibration() end
shalutha 0:69ce6d469c71 777
shalutha 0:69ce6d469c71 778 return true;
shalutha 0:69ce6d469c71 779 }
shalutha 0:69ce6d469c71 780
shalutha 0:69ce6d469c71 781 // Get the VCSEL pulse period in PCLKs for the given period type.
shalutha 0:69ce6d469c71 782 // based on VL53L0X_get_vcsel_pulse_period()
shalutha 0:69ce6d469c71 783 uint8_t VL53L0X::getVcselPulsePeriod(vcselPeriodType type)
shalutha 0:69ce6d469c71 784 {
shalutha 0:69ce6d469c71 785 if (type == VcselPeriodPreRange)
shalutha 0:69ce6d469c71 786 {
shalutha 0:69ce6d469c71 787 return decodeVcselPeriod(readReg(PRE_RANGE_CONFIG_VCSEL_PERIOD));
shalutha 0:69ce6d469c71 788 }
shalutha 0:69ce6d469c71 789 else if (type == VcselPeriodFinalRange)
shalutha 0:69ce6d469c71 790 {
shalutha 0:69ce6d469c71 791 return decodeVcselPeriod(readReg(FINAL_RANGE_CONFIG_VCSEL_PERIOD));
shalutha 0:69ce6d469c71 792 }
shalutha 0:69ce6d469c71 793 else { return 255; }
shalutha 0:69ce6d469c71 794 }
shalutha 0:69ce6d469c71 795
shalutha 0:69ce6d469c71 796 // Start continuous ranging measurements. If period_ms (optional) is 0 or not
shalutha 0:69ce6d469c71 797 // given, continuous back-to-back mode is used (the sensor takes measurements as
shalutha 0:69ce6d469c71 798 // often as possible); otherwise, continuous timed mode is used, with the given
shalutha 0:69ce6d469c71 799 // inter-measurement period in milliseconds determining how often the sensor
shalutha 0:69ce6d469c71 800 // takes a measurement.
shalutha 0:69ce6d469c71 801 // based on VL53L0X_StartMeasurement()
shalutha 0:69ce6d469c71 802 void VL53L0X::startContinuous(uint32_t period_ms)
shalutha 0:69ce6d469c71 803 {
shalutha 0:69ce6d469c71 804 writeReg(0x80, 0x01);
shalutha 0:69ce6d469c71 805 writeReg(0xFF, 0x01);
shalutha 0:69ce6d469c71 806 writeReg(0x00, 0x00);
shalutha 0:69ce6d469c71 807 writeReg(0x91, stop_variable);
shalutha 0:69ce6d469c71 808 writeReg(0x00, 0x01);
shalutha 0:69ce6d469c71 809 writeReg(0xFF, 0x00);
shalutha 0:69ce6d469c71 810 writeReg(0x80, 0x00);
shalutha 0:69ce6d469c71 811
shalutha 0:69ce6d469c71 812 if (period_ms != 0)
shalutha 0:69ce6d469c71 813 {
shalutha 0:69ce6d469c71 814 // continuous timed mode
shalutha 0:69ce6d469c71 815
shalutha 0:69ce6d469c71 816 // VL53L0X_SetInterMeasurementPeriodMilliSeconds() begin
shalutha 0:69ce6d469c71 817
shalutha 0:69ce6d469c71 818 uint16_t osc_calibrate_val = readReg16Bit(OSC_CALIBRATE_VAL);
shalutha 0:69ce6d469c71 819
shalutha 0:69ce6d469c71 820 if (osc_calibrate_val != 0)
shalutha 0:69ce6d469c71 821 {
shalutha 0:69ce6d469c71 822 period_ms *= osc_calibrate_val;
shalutha 0:69ce6d469c71 823 }
shalutha 0:69ce6d469c71 824
shalutha 0:69ce6d469c71 825 writeReg32Bit(SYSTEM_INTERMEASUREMENT_PERIOD, period_ms);
shalutha 0:69ce6d469c71 826
shalutha 0:69ce6d469c71 827 // VL53L0X_SetInterMeasurementPeriodMilliSeconds() end
shalutha 0:69ce6d469c71 828
shalutha 0:69ce6d469c71 829 writeReg(SYSRANGE_START, 0x04); // VL53L0X_REG_SYSRANGE_MODE_TIMED
shalutha 0:69ce6d469c71 830 }
shalutha 0:69ce6d469c71 831 else
shalutha 0:69ce6d469c71 832 {
shalutha 0:69ce6d469c71 833 // continuous back-to-back mode
shalutha 0:69ce6d469c71 834 writeReg(SYSRANGE_START, 0x02); // VL53L0X_REG_SYSRANGE_MODE_BACKTOBACK
shalutha 0:69ce6d469c71 835 }
shalutha 0:69ce6d469c71 836 }
shalutha 0:69ce6d469c71 837
shalutha 0:69ce6d469c71 838 // Stop continuous measurements
shalutha 0:69ce6d469c71 839 // based on VL53L0X_StopMeasurement()
shalutha 0:69ce6d469c71 840 void VL53L0X::stopContinuous(void)
shalutha 0:69ce6d469c71 841 {
shalutha 0:69ce6d469c71 842 writeReg(SYSRANGE_START, 0x01); // VL53L0X_REG_SYSRANGE_MODE_SINGLESHOT
shalutha 0:69ce6d469c71 843
shalutha 0:69ce6d469c71 844 writeReg(0xFF, 0x01);
shalutha 0:69ce6d469c71 845 writeReg(0x00, 0x00);
shalutha 0:69ce6d469c71 846 writeReg(0x91, 0x00);
shalutha 0:69ce6d469c71 847 writeReg(0x00, 0x01);
shalutha 0:69ce6d469c71 848 writeReg(0xFF, 0x00);
shalutha 0:69ce6d469c71 849 }
shalutha 0:69ce6d469c71 850
shalutha 0:69ce6d469c71 851 // Returns a range reading in millimeters when continuous mode is active
shalutha 0:69ce6d469c71 852 // (readRangeSingleMillimeters() also calls this function after starting a
shalutha 0:69ce6d469c71 853 // single-shot range measurement)
shalutha 0:69ce6d469c71 854 uint16_t VL53L0X::readRangeContinuousMillimeters(void)
shalutha 0:69ce6d469c71 855 {
shalutha 0:69ce6d469c71 856 startTimeout();
shalutha 0:69ce6d469c71 857 while ((readReg(RESULT_INTERRUPT_STATUS) & 0x07) == 0)
shalutha 0:69ce6d469c71 858 {
shalutha 0:69ce6d469c71 859 if (checkTimeoutExpired())
shalutha 0:69ce6d469c71 860 {
shalutha 0:69ce6d469c71 861 did_timeout = true;
shalutha 0:69ce6d469c71 862 return 65535;
shalutha 0:69ce6d469c71 863 }
shalutha 0:69ce6d469c71 864 }
shalutha 0:69ce6d469c71 865
shalutha 0:69ce6d469c71 866 // assumptions: Linearity Corrective Gain is 1000 (default);
shalutha 0:69ce6d469c71 867 // fractional ranging is not enabled
shalutha 0:69ce6d469c71 868 uint16_t range = readReg16Bit(RESULT_RANGE_STATUS + 10);
shalutha 0:69ce6d469c71 869
shalutha 0:69ce6d469c71 870 writeReg(SYSTEM_INTERRUPT_CLEAR, 0x01);
shalutha 0:69ce6d469c71 871
shalutha 0:69ce6d469c71 872 return range;
shalutha 0:69ce6d469c71 873 }
shalutha 0:69ce6d469c71 874
shalutha 0:69ce6d469c71 875 // Performs a single-shot range measurement and returns the reading in
shalutha 0:69ce6d469c71 876 // millimeters
shalutha 0:69ce6d469c71 877 // based on VL53L0X_PerformSingleRangingMeasurement()
shalutha 0:69ce6d469c71 878 uint16_t VL53L0X::readRangeSingleMillimeters(void)
shalutha 0:69ce6d469c71 879 {
shalutha 0:69ce6d469c71 880 writeReg(0x80, 0x01);
shalutha 0:69ce6d469c71 881 writeReg(0xFF, 0x01);
shalutha 0:69ce6d469c71 882 writeReg(0x00, 0x00);
shalutha 0:69ce6d469c71 883 writeReg(0x91, stop_variable);
shalutha 0:69ce6d469c71 884 writeReg(0x00, 0x01);
shalutha 0:69ce6d469c71 885 writeReg(0xFF, 0x00);
shalutha 0:69ce6d469c71 886 writeReg(0x80, 0x00);
shalutha 0:69ce6d469c71 887
shalutha 0:69ce6d469c71 888 writeReg(SYSRANGE_START, 0x01);
shalutha 0:69ce6d469c71 889
shalutha 0:69ce6d469c71 890 // "Wait until start bit has been cleared"
shalutha 0:69ce6d469c71 891 startTimeout();
shalutha 0:69ce6d469c71 892 while (readReg(SYSRANGE_START) & 0x01)
shalutha 0:69ce6d469c71 893 {
shalutha 0:69ce6d469c71 894 if (checkTimeoutExpired())
shalutha 0:69ce6d469c71 895 {
shalutha 0:69ce6d469c71 896 did_timeout = true;
shalutha 0:69ce6d469c71 897 return 65535;
shalutha 0:69ce6d469c71 898 }
shalutha 0:69ce6d469c71 899 }
shalutha 0:69ce6d469c71 900
shalutha 0:69ce6d469c71 901 return readRangeContinuousMillimeters();
shalutha 0:69ce6d469c71 902 }
shalutha 0:69ce6d469c71 903
shalutha 0:69ce6d469c71 904 // Did a timeout occur in one of the read functions since the last call to
shalutha 0:69ce6d469c71 905 // timeoutOccurred()?
shalutha 0:69ce6d469c71 906 bool VL53L0X::timeoutOccurred()
shalutha 0:69ce6d469c71 907 {
shalutha 0:69ce6d469c71 908 bool tmp = did_timeout;
shalutha 0:69ce6d469c71 909 did_timeout = false;
shalutha 0:69ce6d469c71 910 return tmp;
shalutha 0:69ce6d469c71 911 }
shalutha 0:69ce6d469c71 912
shalutha 0:69ce6d469c71 913 // Private Methods /////////////////////////////////////////////////////////////
shalutha 0:69ce6d469c71 914
shalutha 0:69ce6d469c71 915 // Get reference SPAD (single photon avalanche diode) count and type
shalutha 0:69ce6d469c71 916 // based on VL53L0X_get_info_from_device(),
shalutha 0:69ce6d469c71 917 // but only gets reference SPAD count and type
shalutha 0:69ce6d469c71 918 bool VL53L0X::getSpadInfo(uint8_t * count, bool * type_is_aperture)
shalutha 0:69ce6d469c71 919 {
shalutha 0:69ce6d469c71 920 uint8_t tmp;
shalutha 0:69ce6d469c71 921
shalutha 0:69ce6d469c71 922 writeReg(0x80, 0x01);
shalutha 0:69ce6d469c71 923 writeReg(0xFF, 0x01);
shalutha 0:69ce6d469c71 924 writeReg(0x00, 0x00);
shalutha 0:69ce6d469c71 925
shalutha 0:69ce6d469c71 926 writeReg(0xFF, 0x06);
shalutha 0:69ce6d469c71 927 writeReg(0x83, readReg(0x83) | 0x04);
shalutha 0:69ce6d469c71 928 writeReg(0xFF, 0x07);
shalutha 0:69ce6d469c71 929 writeReg(0x81, 0x01);
shalutha 0:69ce6d469c71 930
shalutha 0:69ce6d469c71 931 writeReg(0x80, 0x01);
shalutha 0:69ce6d469c71 932
shalutha 0:69ce6d469c71 933 writeReg(0x94, 0x6b);
shalutha 0:69ce6d469c71 934 writeReg(0x83, 0x00);
shalutha 0:69ce6d469c71 935 startTimeout();
shalutha 0:69ce6d469c71 936 while (readReg(0x83) == 0x00)
shalutha 0:69ce6d469c71 937 {
shalutha 0:69ce6d469c71 938 if (checkTimeoutExpired()) { return false; }
shalutha 0:69ce6d469c71 939 }
shalutha 0:69ce6d469c71 940 writeReg(0x83, 0x01);
shalutha 0:69ce6d469c71 941 tmp = readReg(0x92);
shalutha 0:69ce6d469c71 942
shalutha 0:69ce6d469c71 943 *count = tmp & 0x7f;
shalutha 0:69ce6d469c71 944 *type_is_aperture = (tmp >> 7) & 0x01;
shalutha 0:69ce6d469c71 945
shalutha 0:69ce6d469c71 946 writeReg(0x81, 0x00);
shalutha 0:69ce6d469c71 947 writeReg(0xFF, 0x06);
shalutha 0:69ce6d469c71 948 writeReg(0x83, readReg( 0x83 & ~0x04));
shalutha 0:69ce6d469c71 949 writeReg(0xFF, 0x01);
shalutha 0:69ce6d469c71 950 writeReg(0x00, 0x01);
shalutha 0:69ce6d469c71 951
shalutha 0:69ce6d469c71 952 writeReg(0xFF, 0x00);
shalutha 0:69ce6d469c71 953 writeReg(0x80, 0x00);
shalutha 0:69ce6d469c71 954
shalutha 0:69ce6d469c71 955 return true;
shalutha 0:69ce6d469c71 956 }
shalutha 0:69ce6d469c71 957
shalutha 0:69ce6d469c71 958 // Get sequence step enables
shalutha 0:69ce6d469c71 959 // based on VL53L0X_GetSequenceStepEnables()
shalutha 0:69ce6d469c71 960 void VL53L0X::getSequenceStepEnables(SequenceStepEnables * enables)
shalutha 0:69ce6d469c71 961 {
shalutha 0:69ce6d469c71 962 uint8_t sequence_config = readReg(SYSTEM_SEQUENCE_CONFIG);
shalutha 0:69ce6d469c71 963
shalutha 0:69ce6d469c71 964 enables->tcc = (sequence_config >> 4) & 0x1;
shalutha 0:69ce6d469c71 965 enables->dss = (sequence_config >> 3) & 0x1;
shalutha 0:69ce6d469c71 966 enables->msrc = (sequence_config >> 2) & 0x1;
shalutha 0:69ce6d469c71 967 enables->pre_range = (sequence_config >> 6) & 0x1;
shalutha 0:69ce6d469c71 968 enables->final_range = (sequence_config >> 7) & 0x1;
shalutha 0:69ce6d469c71 969 }
shalutha 0:69ce6d469c71 970
shalutha 0:69ce6d469c71 971 // Get sequence step timeouts
shalutha 0:69ce6d469c71 972 // based on get_sequence_step_timeout(),
shalutha 0:69ce6d469c71 973 // but gets all timeouts instead of just the requested one, and also stores
shalutha 0:69ce6d469c71 974 // intermediate values
shalutha 0:69ce6d469c71 975 void VL53L0X::getSequenceStepTimeouts(SequenceStepEnables const * enables, SequenceStepTimeouts * timeouts)
shalutha 0:69ce6d469c71 976 {
shalutha 0:69ce6d469c71 977 timeouts->pre_range_vcsel_period_pclks = getVcselPulsePeriod(VcselPeriodPreRange);
shalutha 0:69ce6d469c71 978
shalutha 0:69ce6d469c71 979 timeouts->msrc_dss_tcc_mclks = readReg(MSRC_CONFIG_TIMEOUT_MACROP) + 1;
shalutha 0:69ce6d469c71 980 timeouts->msrc_dss_tcc_us =
shalutha 0:69ce6d469c71 981 timeoutMclksToMicroseconds(timeouts->msrc_dss_tcc_mclks,
shalutha 0:69ce6d469c71 982 timeouts->pre_range_vcsel_period_pclks);
shalutha 0:69ce6d469c71 983
shalutha 0:69ce6d469c71 984 timeouts->pre_range_mclks =
shalutha 0:69ce6d469c71 985 decodeTimeout(readReg16Bit(PRE_RANGE_CONFIG_TIMEOUT_MACROP_HI));
shalutha 0:69ce6d469c71 986 timeouts->pre_range_us =
shalutha 0:69ce6d469c71 987 timeoutMclksToMicroseconds(timeouts->pre_range_mclks,
shalutha 0:69ce6d469c71 988 timeouts->pre_range_vcsel_period_pclks);
shalutha 0:69ce6d469c71 989
shalutha 0:69ce6d469c71 990 timeouts->final_range_vcsel_period_pclks = getVcselPulsePeriod(VcselPeriodFinalRange);
shalutha 0:69ce6d469c71 991
shalutha 0:69ce6d469c71 992 timeouts->final_range_mclks =
shalutha 0:69ce6d469c71 993 decodeTimeout(readReg16Bit(FINAL_RANGE_CONFIG_TIMEOUT_MACROP_HI));
shalutha 0:69ce6d469c71 994
shalutha 0:69ce6d469c71 995 if (enables->pre_range)
shalutha 0:69ce6d469c71 996 {
shalutha 0:69ce6d469c71 997 timeouts->final_range_mclks -= timeouts->pre_range_mclks;
shalutha 0:69ce6d469c71 998 }
shalutha 0:69ce6d469c71 999
shalutha 0:69ce6d469c71 1000 timeouts->final_range_us =
shalutha 0:69ce6d469c71 1001 timeoutMclksToMicroseconds(timeouts->final_range_mclks,
shalutha 0:69ce6d469c71 1002 timeouts->final_range_vcsel_period_pclks);
shalutha 0:69ce6d469c71 1003 }
shalutha 0:69ce6d469c71 1004
shalutha 0:69ce6d469c71 1005 // Decode sequence step timeout in MCLKs from register value
shalutha 0:69ce6d469c71 1006 // based on VL53L0X_decode_timeout()
shalutha 0:69ce6d469c71 1007 // Note: the original function returned a uint32_t, but the return value is
shalutha 0:69ce6d469c71 1008 // always stored in a uint16_t.
shalutha 0:69ce6d469c71 1009 uint16_t VL53L0X::decodeTimeout(uint16_t reg_val)
shalutha 0:69ce6d469c71 1010 {
shalutha 0:69ce6d469c71 1011 // format: "(LSByte * 2^MSByte) + 1"
shalutha 0:69ce6d469c71 1012 return (uint16_t)((reg_val & 0x00FF) <<
shalutha 0:69ce6d469c71 1013 (uint16_t)((reg_val & 0xFF00) >> 8)) + 1;
shalutha 0:69ce6d469c71 1014 }
shalutha 0:69ce6d469c71 1015
shalutha 0:69ce6d469c71 1016 // Encode sequence step timeout register value from timeout in MCLKs
shalutha 0:69ce6d469c71 1017 // based on VL53L0X_encode_timeout()
shalutha 0:69ce6d469c71 1018 // Note: the original function took a uint16_t, but the argument passed to it
shalutha 0:69ce6d469c71 1019 // is always a uint16_t.
shalutha 0:69ce6d469c71 1020 uint16_t VL53L0X::encodeTimeout(uint16_t timeout_mclks)
shalutha 0:69ce6d469c71 1021 {
shalutha 0:69ce6d469c71 1022 // format: "(LSByte * 2^MSByte) + 1"
shalutha 0:69ce6d469c71 1023
shalutha 0:69ce6d469c71 1024 uint32_t ls_byte = 0;
shalutha 0:69ce6d469c71 1025 uint16_t ms_byte = 0;
shalutha 0:69ce6d469c71 1026
shalutha 0:69ce6d469c71 1027 if (timeout_mclks > 0)
shalutha 0:69ce6d469c71 1028 {
shalutha 0:69ce6d469c71 1029 ls_byte = timeout_mclks - 1;
shalutha 0:69ce6d469c71 1030
shalutha 0:69ce6d469c71 1031 while ((ls_byte & 0xFFFFFF00) > 0)
shalutha 0:69ce6d469c71 1032 {
shalutha 0:69ce6d469c71 1033 ls_byte >>= 1;
shalutha 0:69ce6d469c71 1034 ms_byte++;
shalutha 0:69ce6d469c71 1035 }
shalutha 0:69ce6d469c71 1036
shalutha 0:69ce6d469c71 1037 return (ms_byte << 8) | (ls_byte & 0xFF);
shalutha 0:69ce6d469c71 1038 }
shalutha 0:69ce6d469c71 1039 else { return 0; }
shalutha 0:69ce6d469c71 1040 }
shalutha 0:69ce6d469c71 1041
shalutha 0:69ce6d469c71 1042 // Convert sequence step timeout from MCLKs to microseconds with given VCSEL period in PCLKs
shalutha 0:69ce6d469c71 1043 // based on VL53L0X_calc_timeout_us()
shalutha 0:69ce6d469c71 1044 uint32_t VL53L0X::timeoutMclksToMicroseconds(uint16_t timeout_period_mclks, uint8_t vcsel_period_pclks)
shalutha 0:69ce6d469c71 1045 {
shalutha 0:69ce6d469c71 1046 uint32_t macro_period_ns = calcMacroPeriod(vcsel_period_pclks);
shalutha 0:69ce6d469c71 1047
shalutha 0:69ce6d469c71 1048 return ((timeout_period_mclks * macro_period_ns) + (macro_period_ns / 2)) / 1000;
shalutha 0:69ce6d469c71 1049 }
shalutha 0:69ce6d469c71 1050
shalutha 0:69ce6d469c71 1051 // Convert sequence step timeout from microseconds to MCLKs with given VCSEL period in PCLKs
shalutha 0:69ce6d469c71 1052 // based on VL53L0X_calc_timeout_mclks()
shalutha 0:69ce6d469c71 1053 uint32_t VL53L0X::timeoutMicrosecondsToMclks(uint32_t timeout_period_us, uint8_t vcsel_period_pclks)
shalutha 0:69ce6d469c71 1054 {
shalutha 0:69ce6d469c71 1055 uint32_t macro_period_ns = calcMacroPeriod(vcsel_period_pclks);
shalutha 0:69ce6d469c71 1056
shalutha 0:69ce6d469c71 1057 return (((timeout_period_us * 1000) + (macro_period_ns / 2)) / macro_period_ns);
shalutha 0:69ce6d469c71 1058 }
shalutha 0:69ce6d469c71 1059
shalutha 0:69ce6d469c71 1060
shalutha 0:69ce6d469c71 1061 // based on VL53L0X_perform_single_ref_calibration()
shalutha 0:69ce6d469c71 1062 bool VL53L0X::performSingleRefCalibration(uint8_t vhv_init_byte)
shalutha 0:69ce6d469c71 1063 {
shalutha 0:69ce6d469c71 1064 writeReg(SYSRANGE_START, 0x01 | vhv_init_byte); // VL53L0X_REG_SYSRANGE_MODE_START_STOP
shalutha 0:69ce6d469c71 1065
shalutha 0:69ce6d469c71 1066 startTimeout();
shalutha 0:69ce6d469c71 1067 while ((readReg(RESULT_INTERRUPT_STATUS) & 0x07) == 0)
shalutha 0:69ce6d469c71 1068 {
shalutha 0:69ce6d469c71 1069 if (checkTimeoutExpired()) { return false; }
shalutha 0:69ce6d469c71 1070 }
shalutha 0:69ce6d469c71 1071
shalutha 0:69ce6d469c71 1072 writeReg(SYSTEM_INTERRUPT_CLEAR, 0x01);
shalutha 0:69ce6d469c71 1073
shalutha 0:69ce6d469c71 1074 writeReg(SYSRANGE_START, 0x00);
shalutha 0:69ce6d469c71 1075
shalutha 0:69ce6d469c71 1076 return true;
shalutha 0:69ce6d469c71 1077 }