Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: Check_VL53L0X_simple_with_three_ToF Check_VL53L0X_simple_ToF_Sensor Check_VL53L0X_simple_with_three_ToF Check_VL53L0X_simple_ToF_Sensor ... more
Fork of VL53L0X by
VL53L0X.cpp
00001 /** 00002 ****************************************************************************** 00003 * @file VL53L0X_class.cpp 00004 * @author IMG 00005 * @version V0.0.1 00006 * @date 28-June-2016 00007 * @brief Implementation file for the VL53L0X driver class 00008 ****************************************************************************** 00009 * @attention 00010 * 00011 * <h2><center>© COPYRIGHT(c) 2016 STMicroelectronics</center></h2> 00012 * 00013 * Redistribution and use in source and binary forms, with or without modification, 00014 * are permitted provided that the following conditions are met: 00015 * 1. Redistributions of source code must retain the above copyright notice, 00016 * this list of conditions and the following disclaimer. 00017 * 2. Redistributions in binary form must reproduce the above copyright notice, 00018 * this list of conditions and the following disclaimer in the documentation 00019 * and/or other materials provided with the distribution. 00020 * 3. Neither the name of STMicroelectronics nor the names of its contributors 00021 * may be used to endorse or promote products derived from this software 00022 * without specific prior written permission. 00023 * 00024 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00025 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00026 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00027 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 00028 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00029 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00030 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00031 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00032 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00033 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00034 * 00035 ****************************************************************************** 00036 */ 00037 00038 /* Includes */ 00039 #include <stdlib.h> 00040 00041 #include "VL53L0X.h" 00042 00043 //#include "VL53L0X_api_core.h" 00044 //#include "VL53L0X_api_calibration.h" 00045 //#include "VL53L0X_api_strings.h" 00046 #include "VL53L0X_interrupt_threshold_settings.h" 00047 #include "VL53L0X_tuning.h" 00048 #include "VL53L0X_types.h" 00049 00050 00051 /****************** define for i2c configuration *******************************/ 00052 00053 #define TEMP_BUF_SIZE 64 00054 00055 /** Maximum buffer size to be used in i2c */ 00056 #define VL53L0X_MAX_I2C_XFER_SIZE 64 /* Maximum buffer size to be used in i2c */ 00057 #define VL53L0X_I2C_USER_VAR /* none but could be for a flag var to get/pass to mutex interruptible return flags and try again */ 00058 00059 00060 #define LOG_FUNCTION_START(fmt, ...) \ 00061 _LOG_FUNCTION_START(TRACE_MODULE_API, fmt, ##__VA_ARGS__) 00062 #define LOG_FUNCTION_END(status, ...) \ 00063 _LOG_FUNCTION_END(TRACE_MODULE_API, status, ##__VA_ARGS__) 00064 #define LOG_FUNCTION_END_FMT(status, fmt, ...) \ 00065 _LOG_FUNCTION_END_FMT(TRACE_MODULE_API, status, fmt, ##__VA_ARGS__) 00066 00067 #ifdef VL53L0X_LOG_ENABLE 00068 #define trace_print(level, ...) trace_print_module_function(TRACE_MODULE_API, \ 00069 level, TRACE_FUNCTION_NONE, ##__VA_ARGS__) 00070 #endif 00071 00072 #define REF_ARRAY_SPAD_0 0 00073 #define REF_ARRAY_SPAD_5 5 00074 #define REF_ARRAY_SPAD_10 10 00075 00076 uint32_t refArrayQuadrants[4] = {REF_ARRAY_SPAD_10, REF_ARRAY_SPAD_5, 00077 REF_ARRAY_SPAD_0, REF_ARRAY_SPAD_5 00078 }; 00079 00080 00081 00082 00083 VL53L0X_Error VL53L0X::VL53L0X_device_read_strobe(VL53L0X_DEV dev) 00084 { 00085 VL53L0X_Error status = VL53L0X_ERROR_NONE; 00086 uint8_t strobe; 00087 uint32_t loop_nb; 00088 LOG_FUNCTION_START(""); 00089 00090 status |= VL53L0X_write_byte(dev, 0x83, 0x00); 00091 00092 /* polling 00093 * use timeout to avoid deadlock*/ 00094 if (status == VL53L0X_ERROR_NONE) { 00095 loop_nb = 0; 00096 do { 00097 status = VL53L0X_read_byte(dev, 0x83, &strobe); 00098 if ((strobe != 0x00) || status != VL53L0X_ERROR_NONE) { 00099 break; 00100 } 00101 00102 loop_nb = loop_nb + 1; 00103 } while (loop_nb < VL53L0X_DEFAULT_MAX_LOOP); 00104 00105 if (loop_nb >= VL53L0X_DEFAULT_MAX_LOOP) { 00106 status = VL53L0X_ERROR_TIME_OUT; 00107 } 00108 } 00109 00110 status |= VL53L0X_write_byte(dev, 0x83, 0x01); 00111 00112 LOG_FUNCTION_END(status); 00113 return status; 00114 } 00115 00116 VL53L0X_Error VL53L0X::VL53L0X_get_info_from_device(VL53L0X_DEV dev, uint8_t option) 00117 { 00118 VL53L0X_Error status = VL53L0X_ERROR_NONE; 00119 uint8_t byte; 00120 uint32_t tmp_dword; 00121 uint8_t module_id; 00122 uint8_t revision; 00123 uint8_t reference_spad_count = 0; 00124 uint8_t reference_spad_type = 0; 00125 uint32_t part_uid_upper = 0; 00126 uint32_t part_uid_lower = 0; 00127 uint32_t offset_fixed1104_mm = 0; 00128 int16_t offset_micro_meters = 0; 00129 uint32_t dist_meas_tgt_fixed1104_mm = 400 << 4; 00130 uint32_t dist_meas_fixed1104_400_mm = 0; 00131 uint32_t signal_rate_meas_fixed1104_400_mm = 0; 00132 char product_id[19]; 00133 char *product_id_tmp; 00134 uint8_t read_data_from_device_done; 00135 FixPoint1616_t signal_rate_meas_fixed400_mm_fix = 0; 00136 uint8_t nvm_ref_good_spad_map[VL53L0X_REF_SPAD_BUFFER_SIZE]; 00137 int i; 00138 00139 00140 LOG_FUNCTION_START(""); 00141 00142 read_data_from_device_done = VL53L0X_GETDEVICESPECIFICPARAMETER(dev, 00143 ReadDataFromDeviceDone); 00144 00145 /* This access is done only once after that a GetDeviceInfo or 00146 * datainit is done*/ 00147 if (read_data_from_device_done != 7) { 00148 00149 status |= VL53L0X_write_byte(dev, 0x80, 0x01); 00150 status |= VL53L0X_write_byte(dev, 0xFF, 0x01); 00151 status |= VL53L0X_write_byte(dev, 0x00, 0x00); 00152 00153 status |= VL53L0X_write_byte(dev, 0xFF, 0x06); 00154 status |= VL53L0X_read_byte(dev, 0x83, &byte); 00155 status |= VL53L0X_write_byte(dev, 0x83, byte | 4); 00156 status |= VL53L0X_write_byte(dev, 0xFF, 0x07); 00157 status |= VL53L0X_write_byte(dev, 0x81, 0x01); 00158 00159 status |= VL53L0X_polling_delay(dev); 00160 00161 status |= VL53L0X_write_byte(dev, 0x80, 0x01); 00162 00163 if (((option & 1) == 1) && 00164 ((read_data_from_device_done & 1) == 0)) { 00165 status |= VL53L0X_write_byte(dev, 0x94, 0x6b); 00166 status |= VL53L0X_device_read_strobe(dev); 00167 status |= VL53L0X_read_dword(dev, 0x90, &tmp_dword); 00168 00169 reference_spad_count = (uint8_t)((tmp_dword >> 8) & 0x07f); 00170 reference_spad_type = (uint8_t)((tmp_dword >> 15) & 0x01); 00171 00172 status |= VL53L0X_write_byte(dev, 0x94, 0x24); 00173 status |= VL53L0X_device_read_strobe(dev); 00174 status |= VL53L0X_read_dword(dev, 0x90, &tmp_dword); 00175 00176 00177 nvm_ref_good_spad_map[0] = (uint8_t)((tmp_dword >> 24) 00178 & 0xff); 00179 nvm_ref_good_spad_map[1] = (uint8_t)((tmp_dword >> 16) 00180 & 0xff); 00181 nvm_ref_good_spad_map[2] = (uint8_t)((tmp_dword >> 8) 00182 & 0xff); 00183 nvm_ref_good_spad_map[3] = (uint8_t)(tmp_dword & 0xff); 00184 00185 status |= VL53L0X_write_byte(dev, 0x94, 0x25); 00186 status |= VL53L0X_device_read_strobe(dev); 00187 status |= VL53L0X_read_dword(dev, 0x90, &tmp_dword); 00188 00189 nvm_ref_good_spad_map[4] = (uint8_t)((tmp_dword >> 24) 00190 & 0xff); 00191 nvm_ref_good_spad_map[5] = (uint8_t)((tmp_dword >> 16) 00192 & 0xff); 00193 } 00194 00195 if (((option & 2) == 2) && 00196 ((read_data_from_device_done & 2) == 0)) { 00197 00198 status |= VL53L0X_write_byte(dev, 0x94, 0x02); 00199 status |= VL53L0X_device_read_strobe(dev); 00200 status |= VL53L0X_read_byte(dev, 0x90, &module_id); 00201 00202 status |= VL53L0X_write_byte(dev, 0x94, 0x7B); 00203 status |= VL53L0X_device_read_strobe(dev); 00204 status |= VL53L0X_read_byte(dev, 0x90, &revision); 00205 00206 status |= VL53L0X_write_byte(dev, 0x94, 0x77); 00207 status |= VL53L0X_device_read_strobe(dev); 00208 status |= VL53L0X_read_dword(dev, 0x90, &tmp_dword); 00209 00210 product_id[0] = (char)((tmp_dword >> 25) & 0x07f); 00211 product_id[1] = (char)((tmp_dword >> 18) & 0x07f); 00212 product_id[2] = (char)((tmp_dword >> 11) & 0x07f); 00213 product_id[3] = (char)((tmp_dword >> 4) & 0x07f); 00214 00215 byte = (uint8_t)((tmp_dword & 0x00f) << 3); 00216 00217 status |= VL53L0X_write_byte(dev, 0x94, 0x78); 00218 status |= VL53L0X_device_read_strobe(dev); 00219 status |= VL53L0X_read_dword(dev, 0x90, &tmp_dword); 00220 00221 product_id[4] = (char)(byte + 00222 ((tmp_dword >> 29) & 0x07f)); 00223 product_id[5] = (char)((tmp_dword >> 22) & 0x07f); 00224 product_id[6] = (char)((tmp_dword >> 15) & 0x07f); 00225 product_id[7] = (char)((tmp_dword >> 8) & 0x07f); 00226 product_id[8] = (char)((tmp_dword >> 1) & 0x07f); 00227 00228 byte = (uint8_t)((tmp_dword & 0x001) << 6); 00229 00230 status |= VL53L0X_write_byte(dev, 0x94, 0x79); 00231 00232 status |= VL53L0X_device_read_strobe(dev); 00233 00234 status |= VL53L0X_read_dword(dev, 0x90, &tmp_dword); 00235 00236 product_id[9] = (char)(byte + 00237 ((tmp_dword >> 26) & 0x07f)); 00238 product_id[10] = (char)((tmp_dword >> 19) & 0x07f); 00239 product_id[11] = (char)((tmp_dword >> 12) & 0x07f); 00240 product_id[12] = (char)((tmp_dword >> 5) & 0x07f); 00241 00242 byte = (uint8_t)((tmp_dword & 0x01f) << 2); 00243 00244 status |= VL53L0X_write_byte(dev, 0x94, 0x7A); 00245 00246 status |= VL53L0X_device_read_strobe(dev); 00247 00248 status |= VL53L0X_read_dword(dev, 0x90, &tmp_dword); 00249 00250 product_id[13] = (char)(byte + 00251 ((tmp_dword >> 30) & 0x07f)); 00252 product_id[14] = (char)((tmp_dword >> 23) & 0x07f); 00253 product_id[15] = (char)((tmp_dword >> 16) & 0x07f); 00254 product_id[16] = (char)((tmp_dword >> 9) & 0x07f); 00255 product_id[17] = (char)((tmp_dword >> 2) & 0x07f); 00256 product_id[18] = '\0'; 00257 00258 } 00259 00260 if (((option & 4) == 4) && 00261 ((read_data_from_device_done & 4) == 0)) { 00262 00263 status |= VL53L0X_write_byte(dev, 0x94, 0x7B); 00264 status |= VL53L0X_device_read_strobe(dev); 00265 status |= VL53L0X_read_dword(dev, 0x90, &part_uid_upper); 00266 00267 status |= VL53L0X_write_byte(dev, 0x94, 0x7C); 00268 status |= VL53L0X_device_read_strobe(dev); 00269 status |= VL53L0X_read_dword(dev, 0x90, &part_uid_lower); 00270 00271 status |= VL53L0X_write_byte(dev, 0x94, 0x73); 00272 status |= VL53L0X_device_read_strobe(dev); 00273 status |= VL53L0X_read_dword(dev, 0x90, &tmp_dword); 00274 00275 signal_rate_meas_fixed1104_400_mm = (tmp_dword & 00276 0x0000000ff) << 8; 00277 00278 status |= VL53L0X_write_byte(dev, 0x94, 0x74); 00279 status |= VL53L0X_device_read_strobe(dev); 00280 status |= VL53L0X_read_dword(dev, 0x90, &tmp_dword); 00281 00282 signal_rate_meas_fixed1104_400_mm |= ((tmp_dword & 00283 0xff000000) >> 24); 00284 00285 status |= VL53L0X_write_byte(dev, 0x94, 0x75); 00286 status |= VL53L0X_device_read_strobe(dev); 00287 status |= VL53L0X_read_dword(dev, 0x90, &tmp_dword); 00288 00289 dist_meas_fixed1104_400_mm = (tmp_dword & 0x0000000ff) 00290 << 8; 00291 00292 status |= VL53L0X_write_byte(dev, 0x94, 0x76); 00293 status |= VL53L0X_device_read_strobe(dev); 00294 status |= VL53L0X_read_dword(dev, 0x90, &tmp_dword); 00295 00296 dist_meas_fixed1104_400_mm |= ((tmp_dword & 0xff000000) 00297 >> 24); 00298 } 00299 00300 status |= VL53L0X_write_byte(dev, 0x81, 0x00); 00301 status |= VL53L0X_write_byte(dev, 0xFF, 0x06); 00302 status |= VL53L0X_read_byte(dev, 0x83, &byte); 00303 status |= VL53L0X_write_byte(dev, 0x83, byte & 0xfb); 00304 status |= VL53L0X_write_byte(dev, 0xFF, 0x01); 00305 status |= VL53L0X_write_byte(dev, 0x00, 0x01); 00306 00307 status |= VL53L0X_write_byte(dev, 0xFF, 0x00); 00308 status |= VL53L0X_write_byte(dev, 0x80, 0x00); 00309 } 00310 00311 if ((status == VL53L0X_ERROR_NONE) && 00312 (read_data_from_device_done != 7)) { 00313 /* Assign to variable if status is ok */ 00314 if (((option & 1) == 1) && 00315 ((read_data_from_device_done & 1) == 0)) { 00316 VL53L0X_SETDEVICESPECIFICPARAMETER(dev, 00317 ReferenceSpadCount, reference_spad_count); 00318 00319 VL53L0X_SETDEVICESPECIFICPARAMETER(dev, 00320 ReferenceSpadType, reference_spad_type); 00321 00322 for (i = 0; i < VL53L0X_REF_SPAD_BUFFER_SIZE; i++) { 00323 dev->Data .SpadData .RefGoodSpadMap [i] = 00324 nvm_ref_good_spad_map[i]; 00325 } 00326 } 00327 00328 if (((option & 2) == 2) && 00329 ((read_data_from_device_done & 2) == 0)) { 00330 VL53L0X_SETDEVICESPECIFICPARAMETER(dev, 00331 ModuleId, module_id); 00332 00333 VL53L0X_SETDEVICESPECIFICPARAMETER(dev, 00334 Revision, revision); 00335 00336 product_id_tmp = VL53L0X_GETDEVICESPECIFICPARAMETER(dev, 00337 ProductId); 00338 VL53L0X_COPYSTRING(product_id_tmp, product_id); 00339 00340 } 00341 00342 if (((option & 4) == 4) && 00343 ((read_data_from_device_done & 4) == 0)) { 00344 VL53L0X_SETDEVICESPECIFICPARAMETER(dev, 00345 PartUIDUpper, part_uid_upper); 00346 00347 VL53L0X_SETDEVICESPECIFICPARAMETER(dev, 00348 PartUIDLower, part_uid_lower); 00349 00350 signal_rate_meas_fixed400_mm_fix = 00351 VL53L0X_FIXPOINT97TOFIXPOINT1616( 00352 signal_rate_meas_fixed1104_400_mm); 00353 00354 VL53L0X_SETDEVICESPECIFICPARAMETER(dev, 00355 SignalRateMeasFixed400mm, 00356 signal_rate_meas_fixed400_mm_fix); 00357 00358 offset_micro_meters = 0; 00359 if (dist_meas_fixed1104_400_mm != 0) { 00360 offset_fixed1104_mm = 00361 dist_meas_fixed1104_400_mm - 00362 dist_meas_tgt_fixed1104_mm; 00363 offset_micro_meters = (offset_fixed1104_mm 00364 * 1000) >> 4; 00365 offset_micro_meters *= -1; 00366 } 00367 00368 PALDevDataSet(dev, 00369 Part2PartOffsetAdjustmentNVMMicroMeter, 00370 offset_micro_meters); 00371 } 00372 byte = (uint8_t)(read_data_from_device_done | option); 00373 VL53L0X_SETDEVICESPECIFICPARAMETER(dev, ReadDataFromDeviceDone, 00374 byte); 00375 } 00376 00377 LOG_FUNCTION_END(status); 00378 return status; 00379 } 00380 00381 VL53L0X_Error VL53L0X::wrapped_VL53L0X_get_offset_calibration_data_micro_meter(VL53L0X_DEV dev, 00382 int32_t *p_offset_calibration_data_micro_meter) 00383 { 00384 VL53L0X_Error status = VL53L0X_ERROR_NONE; 00385 uint16_t range_offset_register; 00386 int16_t c_max_offset = 2047; 00387 int16_t c_offset_range = 4096; 00388 00389 /* Note that offset has 10.2 format */ 00390 00391 status = VL53L0X_read_word(dev, 00392 VL53L0X_REG_ALGO_PART_TO_PART_RANGE_OFFSET_MM, 00393 &range_offset_register); 00394 00395 if (status == VL53L0X_ERROR_NONE) { 00396 range_offset_register = (range_offset_register & 0x0fff); 00397 00398 /* Apply 12 bit 2's compliment conversion */ 00399 if (range_offset_register > c_max_offset) { 00400 *p_offset_calibration_data_micro_meter = 00401 (int16_t)(range_offset_register - c_offset_range) 00402 * 250; 00403 } else { 00404 *p_offset_calibration_data_micro_meter = 00405 (int16_t)range_offset_register * 250; 00406 } 00407 00408 } 00409 00410 return status; 00411 } 00412 00413 VL53L0X_Error VL53L0X::VL53L0X_get_offset_calibration_data_micro_meter(VL53L0X_DEV dev, 00414 int32_t *p_offset_calibration_data_micro_meter) 00415 { 00416 VL53L0X_Error status = VL53L0X_ERROR_NONE; 00417 LOG_FUNCTION_START(""); 00418 00419 status = wrapped_VL53L0X_get_offset_calibration_data_micro_meter(dev, 00420 p_offset_calibration_data_micro_meter); 00421 00422 LOG_FUNCTION_END(status); 00423 return status; 00424 } 00425 00426 VL53L0X_Error VL53L0X::wrapped_VL53L0X_set_offset_calibration_data_micro_meter(VL53L0X_DEV dev, 00427 int32_t offset_calibration_data_micro_meter) 00428 { 00429 VL53L0X_Error status = VL53L0X_ERROR_NONE; 00430 int32_t c_max_offset_micro_meter = 511000; 00431 int32_t c_min_offset_micro_meter = -512000; 00432 int16_t c_offset_range = 4096; 00433 uint32_t encoded_offset_val; 00434 00435 LOG_FUNCTION_START(""); 00436 00437 if (offset_calibration_data_micro_meter > c_max_offset_micro_meter) { 00438 offset_calibration_data_micro_meter = c_max_offset_micro_meter; 00439 } else { 00440 if (offset_calibration_data_micro_meter < c_min_offset_micro_meter) { 00441 offset_calibration_data_micro_meter = c_min_offset_micro_meter; 00442 } 00443 } 00444 00445 /* The offset register is 10.2 format and units are mm 00446 * therefore conversion is applied by a division of 00447 * 250. 00448 */ 00449 if (offset_calibration_data_micro_meter >= 0) { 00450 encoded_offset_val = 00451 offset_calibration_data_micro_meter / 250; 00452 } else { 00453 encoded_offset_val = 00454 c_offset_range + 00455 offset_calibration_data_micro_meter / 250; 00456 } 00457 00458 status = VL53L0X_write_word(dev, 00459 VL53L0X_REG_ALGO_PART_TO_PART_RANGE_OFFSET_MM, 00460 encoded_offset_val); 00461 00462 LOG_FUNCTION_END(status); 00463 return status; 00464 } 00465 00466 VL53L0X_Error VL53L0X::VL53L0X_set_offset_calibration_data_micro_meter(VL53L0X_DEV dev, 00467 int32_t offset_calibration_data_micro_meter) 00468 { 00469 VL53L0X_Error status = VL53L0X_ERROR_NONE; 00470 LOG_FUNCTION_START(""); 00471 00472 status = wrapped_VL53L0X_set_offset_calibration_data_micro_meter(dev, 00473 offset_calibration_data_micro_meter); 00474 00475 LOG_FUNCTION_END(status); 00476 return status; 00477 } 00478 00479 VL53L0X_Error VL53L0X::VL53L0X_apply_offset_adjustment(VL53L0X_DEV dev) 00480 { 00481 VL53L0X_Error status = VL53L0X_ERROR_NONE; 00482 int32_t corrected_offset_micro_meters; 00483 int32_t current_offset_micro_meters; 00484 00485 /* if we run on this function we can read all the NVM info 00486 * used by the API */ 00487 status = VL53L0X_get_info_from_device(dev, 7); 00488 00489 /* Read back current device offset */ 00490 if (status == VL53L0X_ERROR_NONE) { 00491 status = VL53L0X_get_offset_calibration_data_micro_meter(dev, 00492 ¤t_offset_micro_meters); 00493 } 00494 00495 /* Apply Offset Adjustment derived from 400mm measurements */ 00496 if (status == VL53L0X_ERROR_NONE) { 00497 00498 /* Store initial device offset */ 00499 PALDevDataSet(dev, Part2PartOffsetNVMMicroMeter, 00500 current_offset_micro_meters); 00501 00502 corrected_offset_micro_meters = current_offset_micro_meters + 00503 (int32_t)PALDevDataGet(dev, 00504 Part2PartOffsetAdjustmentNVMMicroMeter); 00505 00506 status = VL53L0X_set_offset_calibration_data_micro_meter(dev, 00507 corrected_offset_micro_meters); 00508 00509 /* store current, adjusted offset */ 00510 if (status == VL53L0X_ERROR_NONE) { 00511 VL53L0X_SETPARAMETERFIELD(dev, RangeOffsetMicroMeters, 00512 corrected_offset_micro_meters); 00513 } 00514 } 00515 00516 return status; 00517 } 00518 00519 VL53L0X_Error VL53L0X::VL53L0X_get_device_mode(VL53L0X_DEV dev, 00520 VL53L0X_DeviceModes *p_device_mode) 00521 { 00522 VL53L0X_Error status = VL53L0X_ERROR_NONE; 00523 LOG_FUNCTION_START(""); 00524 00525 VL53L0X_GETPARAMETERFIELD(dev, DeviceMode, *p_device_mode); 00526 00527 LOG_FUNCTION_END(status); 00528 return status; 00529 } 00530 00531 VL53L0X_Error VL53L0X::VL53L0X_get_inter_measurement_period_milli_seconds(VL53L0X_DEV dev, 00532 uint32_t *p_inter_measurement_period_milli_seconds) 00533 { 00534 VL53L0X_Error status = VL53L0X_ERROR_NONE; 00535 uint16_t osc_calibrate_val; 00536 uint32_t im_period_milli_seconds; 00537 00538 LOG_FUNCTION_START(""); 00539 00540 status = VL53L0X_read_word(dev, VL53L0X_REG_OSC_CALIBRATE_VAL, 00541 &osc_calibrate_val); 00542 00543 if (status == VL53L0X_ERROR_NONE) { 00544 status = VL53L0X_read_dword(dev, 00545 VL53L0X_REG_SYSTEM_INTERMEASUREMENT_PERIOD, 00546 &im_period_milli_seconds); 00547 } 00548 00549 if (status == VL53L0X_ERROR_NONE) { 00550 if (osc_calibrate_val != 0) { 00551 *p_inter_measurement_period_milli_seconds = 00552 im_period_milli_seconds / osc_calibrate_val; 00553 } 00554 VL53L0X_SETPARAMETERFIELD(dev, 00555 InterMeasurementPeriodMilliSeconds, 00556 *p_inter_measurement_period_milli_seconds); 00557 } 00558 00559 LOG_FUNCTION_END(status); 00560 return status; 00561 } 00562 00563 VL53L0X_Error VL53L0X::VL53L0X_get_x_talk_compensation_rate_mega_cps(VL53L0X_DEV dev, 00564 FixPoint1616_t *p_xtalk_compensation_rate_mega_cps) 00565 { 00566 VL53L0X_Error status = VL53L0X_ERROR_NONE; 00567 uint16_t value; 00568 FixPoint1616_t temp_fix1616; 00569 00570 LOG_FUNCTION_START(""); 00571 00572 status = VL53L0X_read_word(dev, 00573 VL53L0X_REG_CROSSTALK_COMPENSATION_PEAK_RATE_MCPS, (uint16_t *)&value); 00574 if (status == VL53L0X_ERROR_NONE) { 00575 if (value == 0) { 00576 /* the Xtalk is disabled return value from memory */ 00577 VL53L0X_GETPARAMETERFIELD(dev, 00578 XTalkCompensationRateMegaCps, temp_fix1616); 00579 *p_xtalk_compensation_rate_mega_cps = temp_fix1616; 00580 VL53L0X_SETPARAMETERFIELD(dev, XTalkCompensationEnable, 00581 0); 00582 } else { 00583 temp_fix1616 = VL53L0X_FIXPOINT313TOFIXPOINT1616(value); 00584 *p_xtalk_compensation_rate_mega_cps = temp_fix1616; 00585 VL53L0X_SETPARAMETERFIELD(dev, 00586 XTalkCompensationRateMegaCps, temp_fix1616); 00587 VL53L0X_SETPARAMETERFIELD(dev, XTalkCompensationEnable, 00588 1); 00589 } 00590 } 00591 00592 LOG_FUNCTION_END(status); 00593 return status; 00594 } 00595 00596 VL53L0X_Error VL53L0X::VL53L0X_get_limit_check_value(VL53L0X_DEV dev, uint16_t limit_check_id, 00597 FixPoint1616_t *p_limit_check_value) 00598 { 00599 VL53L0X_Error status = VL53L0X_ERROR_NONE; 00600 uint8_t enable_zero_value = 0; 00601 uint16_t temp16; 00602 FixPoint1616_t temp_fix1616; 00603 00604 LOG_FUNCTION_START(""); 00605 00606 switch (limit_check_id) { 00607 00608 case VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE: 00609 /* internal computation: */ 00610 VL53L0X_GETARRAYPARAMETERFIELD(dev, LimitChecksValue, 00611 VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE, temp_fix1616); 00612 enable_zero_value = 0; 00613 break; 00614 00615 case VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE: 00616 status = VL53L0X_read_word(dev, 00617 VL53L0X_REG_FINAL_RANGE_CONFIG_MIN_COUNT_RATE_RTN_LIMIT, 00618 &temp16); 00619 if (status == VL53L0X_ERROR_NONE) { 00620 temp_fix1616 = VL53L0X_FIXPOINT97TOFIXPOINT1616(temp16); 00621 } 00622 00623 00624 enable_zero_value = 1; 00625 break; 00626 00627 case VL53L0X_CHECKENABLE_SIGNAL_REF_CLIP: 00628 /* internal computation: */ 00629 VL53L0X_GETARRAYPARAMETERFIELD(dev, LimitChecksValue, 00630 VL53L0X_CHECKENABLE_SIGNAL_REF_CLIP, temp_fix1616); 00631 enable_zero_value = 0; 00632 break; 00633 00634 case VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD: 00635 /* internal computation: */ 00636 VL53L0X_GETARRAYPARAMETERFIELD(dev, LimitChecksValue, 00637 VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD, temp_fix1616); 00638 enable_zero_value = 0; 00639 break; 00640 00641 case VL53L0X_CHECKENABLE_SIGNAL_RATE_MSRC: 00642 case VL53L0X_CHECKENABLE_SIGNAL_RATE_PRE_RANGE: 00643 status = VL53L0X_read_word(dev, 00644 VL53L0X_REG_PRE_RANGE_MIN_COUNT_RATE_RTN_LIMIT, 00645 &temp16); 00646 if (status == VL53L0X_ERROR_NONE) { 00647 temp_fix1616 = VL53L0X_FIXPOINT97TOFIXPOINT1616(temp16); 00648 } 00649 00650 00651 enable_zero_value = 0; 00652 break; 00653 00654 default: 00655 status = VL53L0X_ERROR_INVALID_PARAMS; 00656 00657 } 00658 00659 if (status == VL53L0X_ERROR_NONE) { 00660 00661 if (enable_zero_value == 1) { 00662 00663 if (temp_fix1616 == 0) { 00664 /* disabled: return value from memory */ 00665 VL53L0X_GETARRAYPARAMETERFIELD(dev, 00666 LimitChecksValue, limit_check_id, 00667 temp_fix1616); 00668 *p_limit_check_value = temp_fix1616; 00669 VL53L0X_SETARRAYPARAMETERFIELD(dev, 00670 LimitChecksEnable, limit_check_id, 0); 00671 } else { 00672 *p_limit_check_value = temp_fix1616; 00673 VL53L0X_SETARRAYPARAMETERFIELD(dev, 00674 LimitChecksValue, limit_check_id, 00675 temp_fix1616); 00676 VL53L0X_SETARRAYPARAMETERFIELD(dev, 00677 LimitChecksEnable, limit_check_id, 1); 00678 } 00679 } else { 00680 *p_limit_check_value = temp_fix1616; 00681 } 00682 } 00683 00684 LOG_FUNCTION_END(status); 00685 return status; 00686 00687 } 00688 00689 VL53L0X_Error VL53L0X::VL53L0X_get_limit_check_enable(VL53L0X_DEV dev, uint16_t limit_check_id, 00690 uint8_t *p_limit_check_enable) 00691 { 00692 VL53L0X_Error status = VL53L0X_ERROR_NONE; 00693 uint8_t temp8; 00694 00695 LOG_FUNCTION_START(""); 00696 00697 if (limit_check_id >= VL53L0X_CHECKENABLE_NUMBER_OF_CHECKS) { 00698 status = VL53L0X_ERROR_INVALID_PARAMS; 00699 *p_limit_check_enable = 0; 00700 } else { 00701 VL53L0X_GETARRAYPARAMETERFIELD(dev, LimitChecksEnable, 00702 limit_check_id, temp8); 00703 *p_limit_check_enable = temp8; 00704 } 00705 00706 LOG_FUNCTION_END(status); 00707 return status; 00708 } 00709 00710 VL53L0X_Error VL53L0X::VL53L0X_get_wrap_around_check_enable(VL53L0X_DEV dev, 00711 uint8_t *p_wrap_around_check_enable) 00712 { 00713 VL53L0X_Error status = VL53L0X_ERROR_NONE; 00714 uint8_t data; 00715 00716 LOG_FUNCTION_START(""); 00717 00718 status = VL53L0X_read_byte(dev, VL53L0X_REG_SYSTEM_SEQUENCE_CONFIG, &data); 00719 if (status == VL53L0X_ERROR_NONE) { 00720 PALDevDataSet(dev, SequenceConfig, data); 00721 if (data & (0x01 << 7)) { 00722 *p_wrap_around_check_enable = 0x01; 00723 } else { 00724 *p_wrap_around_check_enable = 0x00; 00725 } 00726 } 00727 if (status == VL53L0X_ERROR_NONE) { 00728 VL53L0X_SETPARAMETERFIELD(dev, WrapAroundCheckEnable, 00729 *p_wrap_around_check_enable); 00730 } 00731 00732 LOG_FUNCTION_END(status); 00733 return status; 00734 } 00735 00736 VL53L0X_Error VL53L0X::sequence_step_enabled(VL53L0X_DEV dev, 00737 VL53L0X_SequenceStepId sequence_step_id, uint8_t sequence_config, 00738 uint8_t *p_sequence_step_enabled) 00739 { 00740 VL53L0X_Error Status = VL53L0X_ERROR_NONE; 00741 *p_sequence_step_enabled = 0; 00742 LOG_FUNCTION_START(""); 00743 00744 switch (sequence_step_id) { 00745 case VL53L0X_SEQUENCESTEP_TCC: 00746 *p_sequence_step_enabled = (sequence_config & 0x10) >> 4; 00747 break; 00748 case VL53L0X_SEQUENCESTEP_DSS: 00749 *p_sequence_step_enabled = (sequence_config & 0x08) >> 3; 00750 break; 00751 case VL53L0X_SEQUENCESTEP_MSRC: 00752 *p_sequence_step_enabled = (sequence_config & 0x04) >> 2; 00753 break; 00754 case VL53L0X_SEQUENCESTEP_PRE_RANGE: 00755 *p_sequence_step_enabled = (sequence_config & 0x40) >> 6; 00756 break; 00757 case VL53L0X_SEQUENCESTEP_FINAL_RANGE: 00758 *p_sequence_step_enabled = (sequence_config & 0x80) >> 7; 00759 break; 00760 default: 00761 Status = VL53L0X_ERROR_INVALID_PARAMS; 00762 } 00763 00764 LOG_FUNCTION_END(status); 00765 return Status; 00766 } 00767 00768 VL53L0X_Error VL53L0X::VL53L0X_get_sequence_step_enables(VL53L0X_DEV dev, 00769 VL53L0X_SchedulerSequenceSteps_t *p_scheduler_sequence_steps) 00770 { 00771 VL53L0X_Error status = VL53L0X_ERROR_NONE; 00772 uint8_t sequence_config = 0; 00773 LOG_FUNCTION_START(""); 00774 00775 status = VL53L0X_read_byte(dev, VL53L0X_REG_SYSTEM_SEQUENCE_CONFIG, 00776 &sequence_config); 00777 00778 if (status == VL53L0X_ERROR_NONE) { 00779 status = sequence_step_enabled(dev, 00780 VL53L0X_SEQUENCESTEP_TCC, sequence_config, 00781 &p_scheduler_sequence_steps->TccOn); 00782 } 00783 if (status == VL53L0X_ERROR_NONE) { 00784 status = sequence_step_enabled(dev, 00785 VL53L0X_SEQUENCESTEP_DSS, sequence_config, 00786 &p_scheduler_sequence_steps->DssOn); 00787 } 00788 if (status == VL53L0X_ERROR_NONE) { 00789 status = sequence_step_enabled(dev, 00790 VL53L0X_SEQUENCESTEP_MSRC, sequence_config, 00791 &p_scheduler_sequence_steps->MsrcOn); 00792 } 00793 if (status == VL53L0X_ERROR_NONE) { 00794 status = sequence_step_enabled(dev, 00795 VL53L0X_SEQUENCESTEP_PRE_RANGE, sequence_config, 00796 &p_scheduler_sequence_steps->PreRangeOn); 00797 } 00798 if (status == VL53L0X_ERROR_NONE) { 00799 status = sequence_step_enabled(dev, 00800 VL53L0X_SEQUENCESTEP_FINAL_RANGE, sequence_config, 00801 &p_scheduler_sequence_steps->FinalRangeOn); 00802 } 00803 00804 LOG_FUNCTION_END(status); 00805 return status; 00806 } 00807 00808 uint8_t VL53L0X::VL53L0X_decode_vcsel_period(uint8_t vcsel_period_reg) 00809 { 00810 /*! 00811 * Converts the encoded VCSEL period register value into the real 00812 * period in PLL clocks 00813 */ 00814 00815 uint8_t vcsel_period_pclks = 0; 00816 00817 vcsel_period_pclks = (vcsel_period_reg + 1) << 1; 00818 00819 return vcsel_period_pclks; 00820 } 00821 00822 uint8_t VL53L0X::lv53l0x_encode_vcsel_period(uint8_t vcsel_period_pclks) 00823 { 00824 /*! 00825 * Converts the encoded VCSEL period register value into the real period 00826 * in PLL clocks 00827 */ 00828 00829 uint8_t vcsel_period_reg = 0; 00830 00831 vcsel_period_reg = (vcsel_period_pclks >> 1) - 1; 00832 00833 return vcsel_period_reg; 00834 } 00835 00836 00837 VL53L0X_Error VL53L0X::wrapped_VL53L0X_set_vcsel_pulse_period(VL53L0X_DEV dev, 00838 VL53L0X_VcselPeriod vcsel_period_type, uint8_t vcsel_pulse_period_pclk) 00839 { 00840 VL53L0X_Error status = VL53L0X_ERROR_NONE; 00841 uint8_t vcsel_period_reg; 00842 uint8_t min_pre_vcsel_period_pclk = 12; 00843 uint8_t max_pre_vcsel_period_pclk = 18; 00844 uint8_t min_final_vcsel_period_pclk = 8; 00845 uint8_t max_final_vcsel_period_pclk = 14; 00846 uint32_t measurement_timing_budget_micro_seconds; 00847 uint32_t final_range_timeout_micro_seconds; 00848 uint32_t pre_range_timeout_micro_seconds; 00849 uint32_t msrc_timeout_micro_seconds; 00850 uint8_t phase_cal_int = 0; 00851 00852 /* Check if valid clock period requested */ 00853 00854 if ((vcsel_pulse_period_pclk % 2) != 0) { 00855 /* Value must be an even number */ 00856 status = VL53L0X_ERROR_INVALID_PARAMS; 00857 } else if (vcsel_period_type == VL53L0X_VCSEL_PERIOD_PRE_RANGE && 00858 (vcsel_pulse_period_pclk < min_pre_vcsel_period_pclk || 00859 vcsel_pulse_period_pclk > max_pre_vcsel_period_pclk)) { 00860 status = VL53L0X_ERROR_INVALID_PARAMS; 00861 } else if (vcsel_period_type == VL53L0X_VCSEL_PERIOD_FINAL_RANGE && 00862 (vcsel_pulse_period_pclk < min_final_vcsel_period_pclk || 00863 vcsel_pulse_period_pclk > max_final_vcsel_period_pclk)) { 00864 00865 status = VL53L0X_ERROR_INVALID_PARAMS; 00866 } 00867 00868 /* Apply specific settings for the requested clock period */ 00869 00870 if (status != VL53L0X_ERROR_NONE) { 00871 return status; 00872 } 00873 00874 00875 if (vcsel_period_type == VL53L0X_VCSEL_PERIOD_PRE_RANGE) { 00876 00877 /* Set phase check limits */ 00878 if (vcsel_pulse_period_pclk == 12) { 00879 00880 status = VL53L0X_write_byte(dev, 00881 VL53L0X_REG_PRE_RANGE_CONFIG_VALID_PHASE_HIGH, 00882 0x18); 00883 status = VL53L0X_write_byte(dev, 00884 VL53L0X_REG_PRE_RANGE_CONFIG_VALID_PHASE_LOW, 00885 0x08); 00886 } else if (vcsel_pulse_period_pclk == 14) { 00887 00888 status = VL53L0X_write_byte(dev, 00889 VL53L0X_REG_PRE_RANGE_CONFIG_VALID_PHASE_HIGH, 00890 0x30); 00891 status = VL53L0X_write_byte(dev, 00892 VL53L0X_REG_PRE_RANGE_CONFIG_VALID_PHASE_LOW, 00893 0x08); 00894 } else if (vcsel_pulse_period_pclk == 16) { 00895 00896 status = VL53L0X_write_byte(dev, 00897 VL53L0X_REG_PRE_RANGE_CONFIG_VALID_PHASE_HIGH, 00898 0x40); 00899 status = VL53L0X_write_byte(dev, 00900 VL53L0X_REG_PRE_RANGE_CONFIG_VALID_PHASE_LOW, 00901 0x08); 00902 } else if (vcsel_pulse_period_pclk == 18) { 00903 00904 status = VL53L0X_write_byte(dev, 00905 VL53L0X_REG_PRE_RANGE_CONFIG_VALID_PHASE_HIGH, 00906 0x50); 00907 status = VL53L0X_write_byte(dev, 00908 VL53L0X_REG_PRE_RANGE_CONFIG_VALID_PHASE_LOW, 00909 0x08); 00910 } 00911 } else if (vcsel_period_type == VL53L0X_VCSEL_PERIOD_FINAL_RANGE) { 00912 00913 if (vcsel_pulse_period_pclk == 8) { 00914 00915 status = VL53L0X_write_byte(dev, 00916 VL53L0X_REG_FINAL_RANGE_CONFIG_VALID_PHASE_HIGH, 00917 0x10); 00918 status = VL53L0X_write_byte(dev, 00919 VL53L0X_REG_FINAL_RANGE_CONFIG_VALID_PHASE_LOW, 00920 0x08); 00921 00922 status |= VL53L0X_write_byte(dev, 00923 VL53L0X_REG_GLOBAL_CONFIG_VCSEL_WIDTH, 0x02); 00924 status |= VL53L0X_write_byte(dev, 00925 VL53L0X_REG_ALGO_PHASECAL_CONFIG_TIMEOUT, 0x0C); 00926 00927 status |= VL53L0X_write_byte(dev, 0xff, 0x01); 00928 status |= VL53L0X_write_byte(dev, 00929 VL53L0X_REG_ALGO_PHASECAL_LIM, 00930 0x30); 00931 status |= VL53L0X_write_byte(dev, 0xff, 0x00); 00932 } else if (vcsel_pulse_period_pclk == 10) { 00933 00934 status = VL53L0X_write_byte(dev, 00935 VL53L0X_REG_FINAL_RANGE_CONFIG_VALID_PHASE_HIGH, 00936 0x28); 00937 status = VL53L0X_write_byte(dev, 00938 VL53L0X_REG_FINAL_RANGE_CONFIG_VALID_PHASE_LOW, 00939 0x08); 00940 00941 status |= VL53L0X_write_byte(dev, 00942 VL53L0X_REG_GLOBAL_CONFIG_VCSEL_WIDTH, 0x03); 00943 status |= VL53L0X_write_byte(dev, 00944 VL53L0X_REG_ALGO_PHASECAL_CONFIG_TIMEOUT, 0x09); 00945 00946 status |= VL53L0X_write_byte(dev, 0xff, 0x01); 00947 status |= VL53L0X_write_byte(dev, 00948 VL53L0X_REG_ALGO_PHASECAL_LIM, 00949 0x20); 00950 status |= VL53L0X_write_byte(dev, 0xff, 0x00); 00951 } else if (vcsel_pulse_period_pclk == 12) { 00952 00953 status = VL53L0X_write_byte(dev, 00954 VL53L0X_REG_FINAL_RANGE_CONFIG_VALID_PHASE_HIGH, 00955 0x38); 00956 status = VL53L0X_write_byte(dev, 00957 VL53L0X_REG_FINAL_RANGE_CONFIG_VALID_PHASE_LOW, 00958 0x08); 00959 00960 status |= VL53L0X_write_byte(dev, 00961 VL53L0X_REG_GLOBAL_CONFIG_VCSEL_WIDTH, 0x03); 00962 status |= VL53L0X_write_byte(dev, 00963 VL53L0X_REG_ALGO_PHASECAL_CONFIG_TIMEOUT, 0x08); 00964 00965 status |= VL53L0X_write_byte(dev, 0xff, 0x01); 00966 status |= VL53L0X_write_byte(dev, 00967 VL53L0X_REG_ALGO_PHASECAL_LIM, 00968 0x20); 00969 status |= VL53L0X_write_byte(dev, 0xff, 0x00); 00970 } else if (vcsel_pulse_period_pclk == 14) { 00971 00972 status = VL53L0X_write_byte(dev, 00973 VL53L0X_REG_FINAL_RANGE_CONFIG_VALID_PHASE_HIGH, 00974 0x048); 00975 status = VL53L0X_write_byte(dev, 00976 VL53L0X_REG_FINAL_RANGE_CONFIG_VALID_PHASE_LOW, 00977 0x08); 00978 00979 status |= VL53L0X_write_byte(dev, 00980 VL53L0X_REG_GLOBAL_CONFIG_VCSEL_WIDTH, 0x03); 00981 status |= VL53L0X_write_byte(dev, 00982 VL53L0X_REG_ALGO_PHASECAL_CONFIG_TIMEOUT, 0x07); 00983 00984 status |= VL53L0X_write_byte(dev, 0xff, 0x01); 00985 status |= VL53L0X_write_byte(dev, 00986 VL53L0X_REG_ALGO_PHASECAL_LIM, 00987 0x20); 00988 status |= VL53L0X_write_byte(dev, 0xff, 0x00); 00989 } 00990 } 00991 00992 00993 /* Re-calculate and apply timeouts, in macro periods */ 00994 00995 if (status == VL53L0X_ERROR_NONE) { 00996 vcsel_period_reg = lv53l0x_encode_vcsel_period((uint8_t) 00997 vcsel_pulse_period_pclk); 00998 00999 /* When the VCSEL period for the pre or final range is changed, 01000 * the corresponding timeout must be read from the device using 01001 * the current VCSEL period, then the new VCSEL period can be 01002 * applied. The timeout then must be written back to the device 01003 * using the new VCSEL period. 01004 * 01005 * For the MSRC timeout, the same applies - this timeout being 01006 * dependant on the pre-range vcsel period. 01007 */ 01008 switch (vcsel_period_type) { 01009 case VL53L0X_VCSEL_PERIOD_PRE_RANGE: 01010 status = get_sequence_step_timeout(dev, 01011 VL53L0X_SEQUENCESTEP_PRE_RANGE, 01012 &pre_range_timeout_micro_seconds); 01013 01014 if (status == VL53L0X_ERROR_NONE) 01015 status = get_sequence_step_timeout(dev, 01016 VL53L0X_SEQUENCESTEP_MSRC, 01017 &msrc_timeout_micro_seconds); 01018 01019 if (status == VL53L0X_ERROR_NONE) 01020 status = VL53L0X_write_byte(dev, 01021 VL53L0X_REG_PRE_RANGE_CONFIG_VCSEL_PERIOD, 01022 vcsel_period_reg); 01023 01024 01025 if (status == VL53L0X_ERROR_NONE) 01026 status = set_sequence_step_timeout(dev, 01027 VL53L0X_SEQUENCESTEP_PRE_RANGE, 01028 pre_range_timeout_micro_seconds); 01029 01030 01031 if (status == VL53L0X_ERROR_NONE) 01032 status = set_sequence_step_timeout(dev, 01033 VL53L0X_SEQUENCESTEP_MSRC, 01034 msrc_timeout_micro_seconds); 01035 01036 VL53L0X_SETDEVICESPECIFICPARAMETER( 01037 dev, 01038 PreRangeVcselPulsePeriod, 01039 vcsel_pulse_period_pclk); 01040 break; 01041 case VL53L0X_VCSEL_PERIOD_FINAL_RANGE: 01042 status = get_sequence_step_timeout(dev, 01043 VL53L0X_SEQUENCESTEP_FINAL_RANGE, 01044 &final_range_timeout_micro_seconds); 01045 01046 if (status == VL53L0X_ERROR_NONE) 01047 status = VL53L0X_write_byte(dev, 01048 VL53L0X_REG_FINAL_RANGE_CONFIG_VCSEL_PERIOD, 01049 vcsel_period_reg); 01050 01051 01052 if (status == VL53L0X_ERROR_NONE) 01053 status = set_sequence_step_timeout(dev, 01054 VL53L0X_SEQUENCESTEP_FINAL_RANGE, 01055 final_range_timeout_micro_seconds); 01056 01057 VL53L0X_SETDEVICESPECIFICPARAMETER( 01058 dev, 01059 FinalRangeVcselPulsePeriod, 01060 vcsel_pulse_period_pclk); 01061 break; 01062 default: 01063 status = VL53L0X_ERROR_INVALID_PARAMS; 01064 } 01065 } 01066 01067 /* Finally, the timing budget must be re-applied */ 01068 if (status == VL53L0X_ERROR_NONE) { 01069 VL53L0X_GETPARAMETERFIELD(dev, 01070 MeasurementTimingBudgetMicroSeconds, 01071 measurement_timing_budget_micro_seconds); 01072 01073 status = VL53L0X_set_measurement_timing_budget_micro_seconds(dev, 01074 measurement_timing_budget_micro_seconds); 01075 } 01076 01077 /* Perform the phase calibration. This is needed after changing on 01078 * vcsel period. 01079 * get_data_enable = 0, restore_config = 1 */ 01080 if (status == VL53L0X_ERROR_NONE) 01081 status = VL53L0X_perform_phase_calibration( 01082 dev, &phase_cal_int, 0, 1); 01083 01084 return status; 01085 } 01086 01087 VL53L0X_Error VL53L0X::VL53L0X_set_vcsel_pulse_period(VL53L0X_DEV dev, 01088 VL53L0X_VcselPeriod vcsel_period_type, uint8_t vcsel_pulse_period) 01089 { 01090 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01091 LOG_FUNCTION_START(""); 01092 01093 status = wrapped_VL53L0X_set_vcsel_pulse_period(dev, vcsel_period_type, 01094 vcsel_pulse_period); 01095 01096 LOG_FUNCTION_END(status); 01097 return status; 01098 } 01099 01100 VL53L0X_Error VL53L0X::wrapped_VL53L0X_get_vcsel_pulse_period(VL53L0X_DEV dev, 01101 VL53L0X_VcselPeriod vcsel_period_type, uint8_t *p_vcsel_pulse_period_pclk) 01102 { 01103 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01104 uint8_t vcsel_period_reg; 01105 01106 switch (vcsel_period_type) { 01107 case VL53L0X_VCSEL_PERIOD_PRE_RANGE: 01108 status = VL53L0X_read_byte(dev, 01109 VL53L0X_REG_PRE_RANGE_CONFIG_VCSEL_PERIOD, 01110 &vcsel_period_reg); 01111 break; 01112 case VL53L0X_VCSEL_PERIOD_FINAL_RANGE: 01113 status = VL53L0X_read_byte(dev, 01114 VL53L0X_REG_FINAL_RANGE_CONFIG_VCSEL_PERIOD, 01115 &vcsel_period_reg); 01116 break; 01117 default: 01118 status = VL53L0X_ERROR_INVALID_PARAMS; 01119 } 01120 01121 if (status == VL53L0X_ERROR_NONE) 01122 *p_vcsel_pulse_period_pclk = 01123 VL53L0X_decode_vcsel_period(vcsel_period_reg); 01124 01125 return status; 01126 } 01127 01128 VL53L0X_Error VL53L0X::VL53L0X_get_vcsel_pulse_period(VL53L0X_DEV dev, 01129 VL53L0X_VcselPeriod vcsel_period_type, uint8_t *p_vcsel_pulse_period_pclk) 01130 { 01131 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01132 LOG_FUNCTION_START(""); 01133 01134 status = wrapped_VL53L0X_get_vcsel_pulse_period(dev, vcsel_period_type, 01135 p_vcsel_pulse_period_pclk); 01136 01137 LOG_FUNCTION_END(status); 01138 return status; 01139 } 01140 01141 uint32_t VL53L0X::VL53L0X_decode_timeout(uint16_t encoded_timeout) 01142 { 01143 /*! 01144 * Decode 16-bit timeout register value - format (LSByte * 2^MSByte) + 1 01145 */ 01146 01147 uint32_t timeout_macro_clks = 0; 01148 01149 timeout_macro_clks = ((uint32_t)(encoded_timeout & 0x00FF) 01150 << (uint32_t)((encoded_timeout & 0xFF00) >> 8)) + 1; 01151 01152 return timeout_macro_clks; 01153 } 01154 01155 uint32_t VL53L0X::VL53L0X_calc_macro_period_ps(VL53L0X_DEV dev, uint8_t vcsel_period_pclks) 01156 { 01157 uint64_t pll_period_ps; 01158 uint32_t macro_period_vclks; 01159 uint32_t macro_period_ps; 01160 01161 LOG_FUNCTION_START(""); 01162 01163 /* The above calculation will produce rounding errors, 01164 therefore set fixed value 01165 */ 01166 pll_period_ps = 1655; 01167 01168 macro_period_vclks = 2304; 01169 macro_period_ps = (uint32_t)(macro_period_vclks 01170 * vcsel_period_pclks * pll_period_ps); 01171 01172 LOG_FUNCTION_END(""); 01173 return macro_period_ps; 01174 } 01175 01176 /* To convert register value into us */ 01177 uint32_t VL53L0X::VL53L0X_calc_timeout_us(VL53L0X_DEV dev, 01178 uint16_t timeout_period_mclks, 01179 uint8_t vcsel_period_pclks) 01180 { 01181 uint32_t macro_period_ps; 01182 uint32_t macro_period_ns; 01183 uint32_t actual_timeout_period_us = 0; 01184 01185 macro_period_ps = VL53L0X_calc_macro_period_ps(dev, vcsel_period_pclks); 01186 macro_period_ns = (macro_period_ps + 500) / 1000; 01187 01188 actual_timeout_period_us = 01189 ((timeout_period_mclks * macro_period_ns) + 500) / 1000; 01190 01191 return actual_timeout_period_us; 01192 } 01193 01194 VL53L0X_Error VL53L0X::get_sequence_step_timeout(VL53L0X_DEV dev, 01195 VL53L0X_SequenceStepId sequence_step_id, 01196 uint32_t *p_time_out_micro_secs) 01197 { 01198 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01199 uint8_t current_vcsel_pulse_period_p_clk; 01200 uint8_t encoded_time_out_byte = 0; 01201 uint32_t timeout_micro_seconds = 0; 01202 uint16_t pre_range_encoded_time_out = 0; 01203 uint16_t msrc_time_out_m_clks; 01204 uint16_t pre_range_time_out_m_clks; 01205 uint16_t final_range_time_out_m_clks = 0; 01206 uint16_t final_range_encoded_time_out; 01207 VL53L0X_SchedulerSequenceSteps_t scheduler_sequence_steps; 01208 01209 if ((sequence_step_id == VL53L0X_SEQUENCESTEP_TCC) || 01210 (sequence_step_id == VL53L0X_SEQUENCESTEP_DSS) || 01211 (sequence_step_id == VL53L0X_SEQUENCESTEP_MSRC)) { 01212 01213 status = VL53L0X_get_vcsel_pulse_period(dev, 01214 VL53L0X_VCSEL_PERIOD_PRE_RANGE, 01215 ¤t_vcsel_pulse_period_p_clk); 01216 if (status == VL53L0X_ERROR_NONE) { 01217 status = VL53L0X_read_byte(dev, 01218 VL53L0X_REG_MSRC_CONFIG_TIMEOUT_MACROP, 01219 &encoded_time_out_byte); 01220 } 01221 msrc_time_out_m_clks = VL53L0X_decode_timeout(encoded_time_out_byte); 01222 01223 timeout_micro_seconds = VL53L0X_calc_timeout_us(dev, 01224 msrc_time_out_m_clks, 01225 current_vcsel_pulse_period_p_clk); 01226 } else if (sequence_step_id == VL53L0X_SEQUENCESTEP_PRE_RANGE) { 01227 /* Retrieve PRE-RANGE VCSEL Period */ 01228 status = VL53L0X_get_vcsel_pulse_period(dev, 01229 VL53L0X_VCSEL_PERIOD_PRE_RANGE, 01230 ¤t_vcsel_pulse_period_p_clk); 01231 01232 /* Retrieve PRE-RANGE Timeout in Macro periods (MCLKS) */ 01233 if (status == VL53L0X_ERROR_NONE) { 01234 01235 /* Retrieve PRE-RANGE VCSEL Period */ 01236 status = VL53L0X_get_vcsel_pulse_period(dev, 01237 VL53L0X_VCSEL_PERIOD_PRE_RANGE, 01238 ¤t_vcsel_pulse_period_p_clk); 01239 01240 if (status == VL53L0X_ERROR_NONE) { 01241 status = VL53L0X_read_word(dev, 01242 VL53L0X_REG_PRE_RANGE_CONFIG_TIMEOUT_MACROP_HI, 01243 &pre_range_encoded_time_out); 01244 } 01245 01246 pre_range_time_out_m_clks = VL53L0X_decode_timeout( 01247 pre_range_encoded_time_out); 01248 01249 timeout_micro_seconds = VL53L0X_calc_timeout_us(dev, 01250 pre_range_time_out_m_clks, 01251 current_vcsel_pulse_period_p_clk); 01252 } 01253 } else if (sequence_step_id == VL53L0X_SEQUENCESTEP_FINAL_RANGE) { 01254 01255 VL53L0X_get_sequence_step_enables(dev, &scheduler_sequence_steps); 01256 pre_range_time_out_m_clks = 0; 01257 01258 if (scheduler_sequence_steps.PreRangeOn) { 01259 /* Retrieve PRE-RANGE VCSEL Period */ 01260 status = VL53L0X_get_vcsel_pulse_period(dev, 01261 VL53L0X_VCSEL_PERIOD_PRE_RANGE, 01262 ¤t_vcsel_pulse_period_p_clk); 01263 01264 /* Retrieve PRE-RANGE Timeout in Macro periods 01265 * (MCLKS) */ 01266 if (status == VL53L0X_ERROR_NONE) { 01267 status = VL53L0X_read_word(dev, 01268 VL53L0X_REG_PRE_RANGE_CONFIG_TIMEOUT_MACROP_HI, 01269 &pre_range_encoded_time_out); 01270 pre_range_time_out_m_clks = VL53L0X_decode_timeout( 01271 pre_range_encoded_time_out); 01272 } 01273 } 01274 01275 if (status == VL53L0X_ERROR_NONE) { 01276 /* Retrieve FINAL-RANGE VCSEL Period */ 01277 status = VL53L0X_get_vcsel_pulse_period(dev, 01278 VL53L0X_VCSEL_PERIOD_FINAL_RANGE, 01279 ¤t_vcsel_pulse_period_p_clk); 01280 } 01281 01282 /* Retrieve FINAL-RANGE Timeout in Macro periods (MCLKS) */ 01283 if (status == VL53L0X_ERROR_NONE) { 01284 status = VL53L0X_read_word(dev, 01285 VL53L0X_REG_FINAL_RANGE_CONFIG_TIMEOUT_MACROP_HI, 01286 &final_range_encoded_time_out); 01287 final_range_time_out_m_clks = VL53L0X_decode_timeout( 01288 final_range_encoded_time_out); 01289 } 01290 01291 final_range_time_out_m_clks -= pre_range_time_out_m_clks; 01292 timeout_micro_seconds = VL53L0X_calc_timeout_us(dev, 01293 final_range_time_out_m_clks, 01294 current_vcsel_pulse_period_p_clk); 01295 } 01296 01297 *p_time_out_micro_secs = timeout_micro_seconds; 01298 01299 return status; 01300 } 01301 01302 VL53L0X_Error VL53L0X::wrapped_VL53L0X_get_measurement_timing_budget_micro_seconds(VL53L0X_DEV dev, 01303 uint32_t *p_measurement_timing_budget_micro_seconds) 01304 { 01305 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01306 VL53L0X_SchedulerSequenceSteps_t scheduler_sequence_steps; 01307 uint32_t final_range_timeout_micro_seconds; 01308 uint32_t msrc_dcc_tcc_timeout_micro_seconds = 2000; 01309 uint32_t start_overhead_micro_seconds = 1910; 01310 uint32_t end_overhead_micro_seconds = 960; 01311 uint32_t msrc_overhead_micro_seconds = 660; 01312 uint32_t tcc_overhead_micro_seconds = 590; 01313 uint32_t dss_overhead_micro_seconds = 690; 01314 uint32_t pre_range_overhead_micro_seconds = 660; 01315 uint32_t final_range_overhead_micro_seconds = 550; 01316 uint32_t pre_range_timeout_micro_seconds = 0; 01317 01318 LOG_FUNCTION_START(""); 01319 01320 /* Start and end overhead times always present */ 01321 *p_measurement_timing_budget_micro_seconds 01322 = start_overhead_micro_seconds + end_overhead_micro_seconds; 01323 01324 status = VL53L0X_get_sequence_step_enables(dev, &scheduler_sequence_steps); 01325 01326 if (status != VL53L0X_ERROR_NONE) { 01327 LOG_FUNCTION_END(status); 01328 return status; 01329 } 01330 01331 01332 if (scheduler_sequence_steps.TccOn || 01333 scheduler_sequence_steps.MsrcOn || 01334 scheduler_sequence_steps.DssOn) { 01335 01336 status = get_sequence_step_timeout(dev, 01337 VL53L0X_SEQUENCESTEP_MSRC, 01338 &msrc_dcc_tcc_timeout_micro_seconds); 01339 01340 if (status == VL53L0X_ERROR_NONE) { 01341 if (scheduler_sequence_steps.TccOn) { 01342 *p_measurement_timing_budget_micro_seconds += 01343 msrc_dcc_tcc_timeout_micro_seconds + 01344 tcc_overhead_micro_seconds; 01345 } 01346 01347 if (scheduler_sequence_steps.DssOn) { 01348 *p_measurement_timing_budget_micro_seconds += 01349 2 * (msrc_dcc_tcc_timeout_micro_seconds + 01350 dss_overhead_micro_seconds); 01351 } else if (scheduler_sequence_steps.MsrcOn) { 01352 *p_measurement_timing_budget_micro_seconds += 01353 msrc_dcc_tcc_timeout_micro_seconds + 01354 msrc_overhead_micro_seconds; 01355 } 01356 } 01357 } 01358 01359 if (status == VL53L0X_ERROR_NONE) { 01360 if (scheduler_sequence_steps.PreRangeOn) { 01361 status = get_sequence_step_timeout(dev, 01362 VL53L0X_SEQUENCESTEP_PRE_RANGE, 01363 &pre_range_timeout_micro_seconds); 01364 *p_measurement_timing_budget_micro_seconds += 01365 pre_range_timeout_micro_seconds + 01366 pre_range_overhead_micro_seconds; 01367 } 01368 } 01369 01370 if (status == VL53L0X_ERROR_NONE) { 01371 if (scheduler_sequence_steps.FinalRangeOn) { 01372 status = get_sequence_step_timeout(dev, 01373 VL53L0X_SEQUENCESTEP_FINAL_RANGE, 01374 &final_range_timeout_micro_seconds); 01375 *p_measurement_timing_budget_micro_seconds += 01376 (final_range_timeout_micro_seconds + 01377 final_range_overhead_micro_seconds); 01378 } 01379 } 01380 01381 if (status == VL53L0X_ERROR_NONE) { 01382 VL53L0X_SETPARAMETERFIELD(dev, 01383 MeasurementTimingBudgetMicroSeconds, 01384 *p_measurement_timing_budget_micro_seconds); 01385 } 01386 01387 LOG_FUNCTION_END(status); 01388 return status; 01389 } 01390 01391 VL53L0X_Error VL53L0X::VL53L0X_get_measurement_timing_budget_micro_seconds(VL53L0X_DEV dev, 01392 uint32_t *p_measurement_timing_budget_micro_seconds) 01393 { 01394 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01395 LOG_FUNCTION_START(""); 01396 01397 status = wrapped_VL53L0X_get_measurement_timing_budget_micro_seconds(dev, 01398 p_measurement_timing_budget_micro_seconds); 01399 01400 LOG_FUNCTION_END(status); 01401 return status; 01402 } 01403 01404 VL53L0X_Error VL53L0X::VL53L0X_get_device_parameters(VL53L0X_DEV dev, 01405 VL53L0X_DeviceParameters_t *p_device_parameters) 01406 { 01407 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01408 int i; 01409 01410 LOG_FUNCTION_START(""); 01411 01412 status = VL53L0X_get_device_mode(dev, &(p_device_parameters->DeviceMode )); 01413 01414 if (status == VL53L0X_ERROR_NONE) 01415 status = VL53L0X_get_inter_measurement_period_milli_seconds(dev, 01416 &(p_device_parameters->InterMeasurementPeriodMilliSeconds )); 01417 01418 01419 if (status == VL53L0X_ERROR_NONE) { 01420 p_device_parameters->XTalkCompensationEnable = 0; 01421 } 01422 01423 if (status == VL53L0X_ERROR_NONE) 01424 status = VL53L0X_get_x_talk_compensation_rate_mega_cps(dev, 01425 &(p_device_parameters->XTalkCompensationRateMegaCps )); 01426 01427 01428 if (status == VL53L0X_ERROR_NONE) 01429 status = VL53L0X_get_offset_calibration_data_micro_meter(dev, 01430 &(p_device_parameters->RangeOffsetMicroMeters )); 01431 01432 01433 if (status == VL53L0X_ERROR_NONE) { 01434 for (i = 0; i < VL53L0X_CHECKENABLE_NUMBER_OF_CHECKS; i++) { 01435 /* get first the values, then the enables. 01436 * VL53L0X_GetLimitCheckValue will modify the enable 01437 * flags 01438 */ 01439 if (status == VL53L0X_ERROR_NONE) { 01440 status |= VL53L0X_get_limit_check_value(dev, i, 01441 &(p_device_parameters->LimitChecksValue [i])); 01442 } else { 01443 break; 01444 } 01445 if (status == VL53L0X_ERROR_NONE) { 01446 status |= VL53L0X_get_limit_check_enable(dev, i, 01447 &(p_device_parameters->LimitChecksEnable [i])); 01448 } else { 01449 break; 01450 } 01451 } 01452 } 01453 01454 if (status == VL53L0X_ERROR_NONE) { 01455 status = VL53L0X_get_wrap_around_check_enable(dev, 01456 &(p_device_parameters->WrapAroundCheckEnable )); 01457 } 01458 01459 /* Need to be done at the end as it uses VCSELPulsePeriod */ 01460 if (status == VL53L0X_ERROR_NONE) { 01461 status = VL53L0X_get_measurement_timing_budget_micro_seconds(dev, 01462 &(p_device_parameters->MeasurementTimingBudgetMicroSeconds )); 01463 } 01464 01465 LOG_FUNCTION_END(status); 01466 return status; 01467 } 01468 01469 VL53L0X_Error VL53L0X::VL53L0X_set_limit_check_value(VL53L0X_DEV dev, uint16_t limit_check_id, 01470 FixPoint1616_t limit_check_value) 01471 { 01472 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01473 uint8_t temp8; 01474 01475 LOG_FUNCTION_START(""); 01476 01477 VL53L0X_GETARRAYPARAMETERFIELD(dev, LimitChecksEnable, limit_check_id, 01478 temp8); 01479 01480 if (temp8 == 0) { /* disabled write only internal value */ 01481 VL53L0X_SETARRAYPARAMETERFIELD(dev, LimitChecksValue, 01482 limit_check_id, limit_check_value); 01483 } else { 01484 01485 switch (limit_check_id) { 01486 01487 case VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE: 01488 /* internal computation: */ 01489 VL53L0X_SETARRAYPARAMETERFIELD(dev, LimitChecksValue, 01490 VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE, 01491 limit_check_value); 01492 break; 01493 01494 case VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE: 01495 01496 status = VL53L0X_write_word(dev, 01497 VL53L0X_REG_FINAL_RANGE_CONFIG_MIN_COUNT_RATE_RTN_LIMIT, 01498 VL53L0X_FIXPOINT1616TOFIXPOINT97( 01499 limit_check_value)); 01500 01501 break; 01502 01503 case VL53L0X_CHECKENABLE_SIGNAL_REF_CLIP: 01504 01505 /* internal computation: */ 01506 VL53L0X_SETARRAYPARAMETERFIELD(dev, LimitChecksValue, 01507 VL53L0X_CHECKENABLE_SIGNAL_REF_CLIP, 01508 limit_check_value); 01509 01510 break; 01511 01512 case VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD: 01513 01514 /* internal computation: */ 01515 VL53L0X_SETARRAYPARAMETERFIELD(dev, LimitChecksValue, 01516 VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD, 01517 limit_check_value); 01518 01519 break; 01520 01521 case VL53L0X_CHECKENABLE_SIGNAL_RATE_MSRC: 01522 case VL53L0X_CHECKENABLE_SIGNAL_RATE_PRE_RANGE: 01523 01524 status = VL53L0X_write_word(dev, 01525 VL53L0X_REG_PRE_RANGE_MIN_COUNT_RATE_RTN_LIMIT, 01526 VL53L0X_FIXPOINT1616TOFIXPOINT97( 01527 limit_check_value)); 01528 01529 break; 01530 01531 default: 01532 status = VL53L0X_ERROR_INVALID_PARAMS; 01533 01534 } 01535 01536 if (status == VL53L0X_ERROR_NONE) { 01537 VL53L0X_SETARRAYPARAMETERFIELD(dev, LimitChecksValue, 01538 limit_check_id, limit_check_value); 01539 } 01540 } 01541 01542 LOG_FUNCTION_END(status); 01543 return status; 01544 } 01545 01546 VL53L0X_Error VL53L0X::VL53L0X_data_init(VL53L0X_DEV dev) 01547 { 01548 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01549 VL53L0X_DeviceParameters_t CurrentParameters; 01550 int i; 01551 uint8_t StopVariable; 01552 01553 LOG_FUNCTION_START(""); 01554 01555 /* by default the I2C is running at 1V8 if you want to change it you 01556 * need to include this define at compilation level. */ 01557 #ifdef USE_I2C_2V8 01558 #if ORIGINAL 01559 Status = VL53L0X_UpdateByte(Dev, 01560 VL53L0X_REG_VHV_CONFIG_PAD_SCL_SDA__EXTSUP_HV, 01561 0xFE, 01562 0x01); 01563 #else 01564 status = VL53L0X_update_byte(dev, 01565 VL53L0X_REG_VHV_CONFIG_PAD_SCL_SDA__EXTSUP_HV, 01566 0xFE, 01567 0x01); 01568 #endif 01569 #endif 01570 01571 /* Set I2C standard mode */ 01572 if (status == VL53L0X_ERROR_NONE) { 01573 status = VL53L0X_write_byte(dev, 0x88, 0x00); 01574 } 01575 01576 VL53L0X_SETDEVICESPECIFICPARAMETER(dev, ReadDataFromDeviceDone, 0); 01577 01578 #ifdef USE_IQC_STATION 01579 if (Status == VL53L0X_ERROR_NONE) { 01580 Status = VL53L0X_apply_offset_adjustment(Dev); 01581 } 01582 #endif 01583 01584 /* Default value is 1000 for Linearity Corrective Gain */ 01585 PALDevDataSet(dev, LinearityCorrectiveGain, 1000); 01586 01587 /* Dmax default Parameter */ 01588 PALDevDataSet(dev, DmaxCalRangeMilliMeter, 400); 01589 PALDevDataSet(dev, DmaxCalSignalRateRtnMegaCps, 01590 (FixPoint1616_t)((0x00016B85))); /* 1.42 No Cover Glass*/ 01591 01592 /* Set Default static parameters 01593 *set first temporary values 9.44MHz * 65536 = 618660 */ 01594 VL53L0X_SETDEVICESPECIFICPARAMETER(dev, OscFrequencyMHz, 618660); 01595 01596 /* Set Default XTalkCompensationRateMegaCps to 0 */ 01597 VL53L0X_SETPARAMETERFIELD(dev, XTalkCompensationRateMegaCps, 0); 01598 01599 /* Get default parameters */ 01600 status = VL53L0X_get_device_parameters(dev, &CurrentParameters); 01601 if (status == VL53L0X_ERROR_NONE) { 01602 /* initialize PAL values */ 01603 CurrentParameters.DeviceMode = VL53L0X_DEVICEMODE_SINGLE_RANGING; 01604 CurrentParameters.HistogramMode = VL53L0X_HISTOGRAMMODE_DISABLED; 01605 PALDevDataSet(dev, CurrentParameters, CurrentParameters); 01606 } 01607 01608 /* Sigma estimator variable */ 01609 PALDevDataSet(dev, SigmaEstRefArray, 100); 01610 PALDevDataSet(dev, SigmaEstEffPulseWidth, 900); 01611 PALDevDataSet(dev, SigmaEstEffAmbWidth, 500); 01612 PALDevDataSet(dev, targetRefRate, 0x0A00); /* 20 MCPS in 9:7 format */ 01613 01614 /* Use internal default settings */ 01615 PALDevDataSet(dev, UseInternalTuningSettings, 1); 01616 01617 status |= VL53L0X_write_byte(dev, 0x80, 0x01); 01618 status |= VL53L0X_write_byte(dev, 0xFF, 0x01); 01619 status |= VL53L0X_write_byte(dev, 0x00, 0x00); 01620 status |= VL53L0X_read_byte(dev, 0x91, &StopVariable); 01621 PALDevDataSet(dev, StopVariable, StopVariable); 01622 status |= VL53L0X_write_byte(dev, 0x00, 0x01); 01623 status |= VL53L0X_write_byte(dev, 0xFF, 0x00); 01624 status |= VL53L0X_write_byte(dev, 0x80, 0x00); 01625 01626 /* Enable all check */ 01627 for (i = 0; i < VL53L0X_CHECKENABLE_NUMBER_OF_CHECKS; i++) { 01628 if (status == VL53L0X_ERROR_NONE) { 01629 status |= VL53L0X_set_limit_check_enable(dev, i, 1); 01630 } else { 01631 break; 01632 } 01633 01634 } 01635 01636 /* Disable the following checks */ 01637 if (status == VL53L0X_ERROR_NONE) 01638 status = VL53L0X_set_limit_check_enable(dev, 01639 VL53L0X_CHECKENABLE_SIGNAL_REF_CLIP, 0); 01640 01641 if (status == VL53L0X_ERROR_NONE) 01642 status = VL53L0X_set_limit_check_enable(dev, 01643 VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD, 0); 01644 01645 if (status == VL53L0X_ERROR_NONE) 01646 status = VL53L0X_set_limit_check_enable(dev, 01647 VL53L0X_CHECKENABLE_SIGNAL_RATE_MSRC, 0); 01648 01649 if (status == VL53L0X_ERROR_NONE) 01650 status = VL53L0X_set_limit_check_enable(dev, 01651 VL53L0X_CHECKENABLE_SIGNAL_RATE_PRE_RANGE, 0); 01652 01653 /* Limit default values */ 01654 if (status == VL53L0X_ERROR_NONE) { 01655 status = VL53L0X_set_limit_check_value(dev, 01656 VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE, 01657 (FixPoint1616_t)(18 * 65536)); 01658 } 01659 if (status == VL53L0X_ERROR_NONE) { 01660 status = VL53L0X_set_limit_check_value(dev, 01661 VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE, 01662 (FixPoint1616_t)(25 * 65536 / 100)); 01663 /* 0.25 * 65536 */ 01664 } 01665 01666 if (status == VL53L0X_ERROR_NONE) { 01667 status = VL53L0X_set_limit_check_value(dev, 01668 VL53L0X_CHECKENABLE_SIGNAL_REF_CLIP, 01669 (FixPoint1616_t)(35 * 65536)); 01670 } 01671 01672 if (status == VL53L0X_ERROR_NONE) { 01673 status = VL53L0X_set_limit_check_value(dev, 01674 VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD, 01675 (FixPoint1616_t)(0 * 65536)); 01676 } 01677 01678 if (status == VL53L0X_ERROR_NONE) { 01679 01680 PALDevDataSet(dev, SequenceConfig, 0xFF); 01681 status = VL53L0X_write_byte(dev, VL53L0X_REG_SYSTEM_SEQUENCE_CONFIG, 01682 0xFF); 01683 01684 /* Set PAL state to tell that we are waiting for call to 01685 * VL53L0X_StaticInit */ 01686 PALDevDataSet(dev, PalState, VL53L0X_STATE_WAIT_STATICINIT); 01687 } 01688 01689 if (status == VL53L0X_ERROR_NONE) { 01690 VL53L0X_SETDEVICESPECIFICPARAMETER(dev, RefSpadsInitialised, 0); 01691 } 01692 01693 01694 LOG_FUNCTION_END(status); 01695 return status; 01696 } 01697 01698 VL53L0X_Error VL53L0X::VL53L0X_check_part_used(VL53L0X_DEV dev, 01699 uint8_t *revision, 01700 VL53L0X_DeviceInfo_t *p_VL53L0X_device_info) 01701 { 01702 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01703 uint8_t module_id_int; 01704 char *product_id_tmp; 01705 01706 LOG_FUNCTION_START(""); 01707 01708 status = VL53L0X_get_info_from_device(dev, 2); 01709 01710 if (status == VL53L0X_ERROR_NONE) { 01711 module_id_int = VL53L0X_GETDEVICESPECIFICPARAMETER(dev, ModuleId); 01712 01713 if (module_id_int == 0) { 01714 *revision = 0; 01715 VL53L0X_COPYSTRING(p_VL53L0X_device_info->ProductId , ""); 01716 } else { 01717 *revision = VL53L0X_GETDEVICESPECIFICPARAMETER(dev, Revision); 01718 product_id_tmp = VL53L0X_GETDEVICESPECIFICPARAMETER(dev, 01719 ProductId); 01720 VL53L0X_COPYSTRING(p_VL53L0X_device_info->ProductId , product_id_tmp); 01721 } 01722 } 01723 01724 LOG_FUNCTION_END(status); 01725 return status; 01726 } 01727 01728 VL53L0X_Error VL53L0X::wrapped_VL53L0X_get_device_info(VL53L0X_DEV dev, 01729 VL53L0X_DeviceInfo_t *p_VL53L0X_device_info) 01730 { 01731 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01732 uint8_t revision_id; 01733 uint8_t revision; 01734 01735 status = VL53L0X_check_part_used(dev, &revision, p_VL53L0X_device_info); 01736 01737 if (status == VL53L0X_ERROR_NONE) { 01738 if (revision == 0) { 01739 VL53L0X_COPYSTRING(p_VL53L0X_device_info->Name , 01740 VL53L0X_STRING_DEVICE_INFO_NAME_TS0); 01741 } else if ((revision <= 34) && (revision != 32)) { 01742 VL53L0X_COPYSTRING(p_VL53L0X_device_info->Name , 01743 VL53L0X_STRING_DEVICE_INFO_NAME_TS1); 01744 } else if (revision < 39) { 01745 VL53L0X_COPYSTRING(p_VL53L0X_device_info->Name , 01746 VL53L0X_STRING_DEVICE_INFO_NAME_TS2); 01747 } else { 01748 VL53L0X_COPYSTRING(p_VL53L0X_device_info->Name , 01749 VL53L0X_STRING_DEVICE_INFO_NAME_ES1); 01750 } 01751 01752 VL53L0X_COPYSTRING(p_VL53L0X_device_info->Type , 01753 VL53L0X_STRING_DEVICE_INFO_TYPE); 01754 01755 } 01756 01757 if (status == VL53L0X_ERROR_NONE) { 01758 status = VL53L0X_read_byte(dev, VL53L0X_REG_IDENTIFICATION_MODEL_ID, 01759 &p_VL53L0X_device_info->ProductType ); 01760 } 01761 01762 if (status == VL53L0X_ERROR_NONE) { 01763 status = VL53L0X_read_byte(dev, 01764 VL53L0X_REG_IDENTIFICATION_REVISION_ID, 01765 &revision_id); 01766 p_VL53L0X_device_info->ProductRevisionMajor = 1; 01767 p_VL53L0X_device_info->ProductRevisionMinor = 01768 (revision_id & 0xF0) >> 4; 01769 } 01770 01771 return status; 01772 } 01773 01774 VL53L0X_Error VL53L0X::VL53L0X_get_device_info(VL53L0X_DEV dev, 01775 VL53L0X_DeviceInfo_t *p_VL53L0X_device_info) 01776 { 01777 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01778 LOG_FUNCTION_START(""); 01779 01780 status = wrapped_VL53L0X_get_device_info(dev, p_VL53L0X_device_info); 01781 01782 LOG_FUNCTION_END(status); 01783 return status; 01784 } 01785 01786 VL53L0X_Error VL53L0X::VL53L0X_get_interrupt_mask_status(VL53L0X_DEV dev, 01787 uint32_t *p_interrupt_mask_status) 01788 { 01789 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01790 uint8_t byte; 01791 LOG_FUNCTION_START(""); 01792 01793 status = VL53L0X_read_byte(dev, VL53L0X_REG_RESULT_INTERRUPT_STATUS, &byte); 01794 *p_interrupt_mask_status = byte & 0x07; 01795 01796 if (byte & 0x18) { 01797 status = VL53L0X_ERROR_RANGE_ERROR; 01798 } 01799 01800 LOG_FUNCTION_END(status); 01801 return status; 01802 } 01803 01804 VL53L0X_Error VL53L0X::VL53L0X_get_measurement_data_ready(VL53L0X_DEV dev, 01805 uint8_t *p_measurement_data_ready) 01806 { 01807 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01808 uint8_t sys_range_status_register; 01809 uint8_t interrupt_config; 01810 uint32_t interrupt_mask; 01811 LOG_FUNCTION_START(""); 01812 01813 interrupt_config = VL53L0X_GETDEVICESPECIFICPARAMETER(dev, 01814 Pin0GpioFunctionality); 01815 01816 if (interrupt_config == 01817 VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY) { 01818 status = VL53L0X_get_interrupt_mask_status(dev, &interrupt_mask); 01819 if (interrupt_mask == 01820 VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY) { 01821 *p_measurement_data_ready = 1; 01822 } else { 01823 *p_measurement_data_ready = 0; 01824 } 01825 } else { 01826 status = VL53L0X_read_byte(dev, VL53L0X_REG_RESULT_RANGE_STATUS, 01827 &sys_range_status_register); 01828 if (status == VL53L0X_ERROR_NONE) { 01829 if (sys_range_status_register & 0x01) { 01830 *p_measurement_data_ready = 1; 01831 } else { 01832 *p_measurement_data_ready = 0; 01833 } 01834 } 01835 } 01836 01837 LOG_FUNCTION_END(status); 01838 return status; 01839 } 01840 01841 VL53L0X_Error VL53L0X::VL53L0X_polling_delay(VL53L0X_DEV dev) 01842 { 01843 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01844 01845 // do nothing 01846 VL53L0X_OsDelay(); 01847 return status; 01848 } 01849 01850 VL53L0X_Error VL53L0X::VL53L0X_measurement_poll_for_completion(VL53L0X_DEV dev) 01851 { 01852 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01853 uint8_t new_data_ready = 0; 01854 uint32_t loop_nb; 01855 01856 LOG_FUNCTION_START(""); 01857 01858 loop_nb = 0; 01859 01860 do { 01861 status = VL53L0X_get_measurement_data_ready(dev, &new_data_ready); 01862 if (status != 0) { 01863 break; /* the error is set */ 01864 } 01865 01866 if (new_data_ready == 1) { 01867 break; /* done note that status == 0 */ 01868 } 01869 01870 loop_nb++; 01871 if (loop_nb >= VL53L0X_DEFAULT_MAX_LOOP) { 01872 status = VL53L0X_ERROR_TIME_OUT; 01873 break; 01874 } 01875 01876 VL53L0X_polling_delay(dev); 01877 } while (1); 01878 01879 LOG_FUNCTION_END(status); 01880 01881 return status; 01882 } 01883 01884 /* Group PAL Interrupt Functions */ 01885 VL53L0X_Error VL53L0X::VL53L0X_clear_interrupt_mask(VL53L0X_DEV dev, uint32_t interrupt_mask) 01886 { 01887 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01888 uint8_t loop_count; 01889 uint8_t byte; 01890 LOG_FUNCTION_START(""); 01891 01892 /* clear bit 0 range interrupt, bit 1 error interrupt */ 01893 loop_count = 0; 01894 do { 01895 status = VL53L0X_write_byte(dev, 01896 VL53L0X_REG_SYSTEM_INTERRUPT_CLEAR, 0x01); 01897 status |= VL53L0X_write_byte(dev, 01898 VL53L0X_REG_SYSTEM_INTERRUPT_CLEAR, 0x00); 01899 status |= VL53L0X_read_byte(dev, 01900 VL53L0X_REG_RESULT_INTERRUPT_STATUS, &byte); 01901 loop_count++; 01902 } while (((byte & 0x07) != 0x00) 01903 && (loop_count < 3) 01904 && (status == VL53L0X_ERROR_NONE)); 01905 01906 01907 if (loop_count >= 3) { 01908 status = VL53L0X_ERROR_INTERRUPT_NOT_CLEARED; 01909 } 01910 01911 LOG_FUNCTION_END(status); 01912 return status; 01913 } 01914 01915 VL53L0X_Error VL53L0X::VL53L0X_perform_single_ref_calibration(VL53L0X_DEV dev, 01916 uint8_t vhv_init_byte) 01917 { 01918 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01919 01920 if (status == VL53L0X_ERROR_NONE) { 01921 status = VL53L0X_write_byte(dev, VL53L0X_REG_SYSRANGE_START, 01922 VL53L0X_REG_SYSRANGE_MODE_START_STOP | 01923 vhv_init_byte); 01924 } 01925 01926 if (status == VL53L0X_ERROR_NONE) { 01927 status = VL53L0X_measurement_poll_for_completion(dev); 01928 } 01929 01930 if (status == VL53L0X_ERROR_NONE) { 01931 status = VL53L0X_clear_interrupt_mask(dev, 0); 01932 } 01933 01934 if (status == VL53L0X_ERROR_NONE) { 01935 status = VL53L0X_write_byte(dev, VL53L0X_REG_SYSRANGE_START, 0x00); 01936 } 01937 01938 return status; 01939 } 01940 01941 VL53L0X_Error VL53L0X::VL53L0X_ref_calibration_io(VL53L0X_DEV dev, uint8_t read_not_write, 01942 uint8_t vhv_settings, uint8_t phase_cal, 01943 uint8_t *p_vhv_settings, uint8_t *p_phase_cal, 01944 const uint8_t vhv_enable, const uint8_t phase_enable) 01945 { 01946 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01947 uint8_t phase_calint = 0; 01948 01949 /* Read VHV from device */ 01950 status |= VL53L0X_write_byte(dev, 0xFF, 0x01); 01951 status |= VL53L0X_write_byte(dev, 0x00, 0x00); 01952 status |= VL53L0X_write_byte(dev, 0xFF, 0x00); 01953 01954 if (read_not_write) { 01955 if (vhv_enable) { 01956 status |= VL53L0X_read_byte(dev, 0xCB, p_vhv_settings); 01957 } 01958 if (phase_enable) { 01959 status |= VL53L0X_read_byte(dev, 0xEE, &phase_calint); 01960 } 01961 } else { 01962 if (vhv_enable) { 01963 status |= VL53L0X_write_byte(dev, 0xCB, vhv_settings); 01964 } 01965 if (phase_enable) { 01966 status |= VL53L0X_update_byte(dev, 0xEE, 0x80, phase_cal); 01967 } 01968 } 01969 01970 status |= VL53L0X_write_byte(dev, 0xFF, 0x01); 01971 status |= VL53L0X_write_byte(dev, 0x00, 0x01); 01972 status |= VL53L0X_write_byte(dev, 0xFF, 0x00); 01973 01974 *p_phase_cal = (uint8_t)(phase_calint & 0xEF); 01975 01976 return status; 01977 } 01978 01979 VL53L0X_Error VL53L0X::VL53L0X_perform_vhv_calibration(VL53L0X_DEV dev, 01980 uint8_t *p_vhv_settings, const uint8_t get_data_enable, 01981 const uint8_t restore_config) 01982 { 01983 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01984 uint8_t sequence_config = 0; 01985 uint8_t vhv_settings = 0; 01986 uint8_t phase_cal = 0; 01987 uint8_t phase_cal_int = 0; 01988 01989 /* store the value of the sequence config, 01990 * this will be reset before the end of the function 01991 */ 01992 01993 if (restore_config) { 01994 sequence_config = PALDevDataGet(dev, SequenceConfig); 01995 } 01996 01997 /* Run VHV */ 01998 status = VL53L0X_write_byte(dev, VL53L0X_REG_SYSTEM_SEQUENCE_CONFIG, 0x01); 01999 02000 if (status == VL53L0X_ERROR_NONE) { 02001 status = VL53L0X_perform_single_ref_calibration(dev, 0x40); 02002 } 02003 02004 /* Read VHV from device */ 02005 if ((status == VL53L0X_ERROR_NONE) && (get_data_enable == 1)) { 02006 status = VL53L0X_ref_calibration_io(dev, 1, 02007 vhv_settings, phase_cal, /* Not used here */ 02008 p_vhv_settings, &phase_cal_int, 02009 1, 0); 02010 } else { 02011 *p_vhv_settings = 0; 02012 } 02013 02014 02015 if ((status == VL53L0X_ERROR_NONE) && restore_config) { 02016 /* restore the previous Sequence Config */ 02017 status = VL53L0X_write_byte(dev, VL53L0X_REG_SYSTEM_SEQUENCE_CONFIG, 02018 sequence_config); 02019 if (status == VL53L0X_ERROR_NONE) { 02020 PALDevDataSet(dev, SequenceConfig, sequence_config); 02021 } 02022 02023 } 02024 02025 return status; 02026 } 02027 02028 VL53L0X_Error VL53L0X::VL53L0X_perform_phase_calibration(VL53L0X_DEV dev, 02029 uint8_t *p_phase_cal, const uint8_t get_data_enable, 02030 const uint8_t restore_config) 02031 { 02032 VL53L0X_Error status = VL53L0X_ERROR_NONE; 02033 uint8_t sequence_config = 0; 02034 uint8_t vhv_settings = 0; 02035 uint8_t phase_cal = 0; 02036 uint8_t vhv_settingsint; 02037 02038 /* store the value of the sequence config, 02039 * this will be reset before the end of the function 02040 */ 02041 02042 if (restore_config) { 02043 sequence_config = PALDevDataGet(dev, SequenceConfig); 02044 } 02045 02046 /* Run PhaseCal */ 02047 status = VL53L0X_write_byte(dev, VL53L0X_REG_SYSTEM_SEQUENCE_CONFIG, 0x02); 02048 02049 if (status == VL53L0X_ERROR_NONE) { 02050 status = VL53L0X_perform_single_ref_calibration(dev, 0x0); 02051 } 02052 02053 /* Read PhaseCal from device */ 02054 if ((status == VL53L0X_ERROR_NONE) && (get_data_enable == 1)) { 02055 status = VL53L0X_ref_calibration_io(dev, 1, 02056 vhv_settings, phase_cal, /* Not used here */ 02057 &vhv_settingsint, p_phase_cal, 02058 0, 1); 02059 } else { 02060 *p_phase_cal = 0; 02061 } 02062 02063 02064 if ((status == VL53L0X_ERROR_NONE) && restore_config) { 02065 /* restore the previous Sequence Config */ 02066 status = VL53L0X_write_byte(dev, VL53L0X_REG_SYSTEM_SEQUENCE_CONFIG, 02067 sequence_config); 02068 if (status == VL53L0X_ERROR_NONE) { 02069 PALDevDataSet(dev, SequenceConfig, sequence_config); 02070 } 02071 02072 } 02073 02074 return status; 02075 } 02076 02077 VL53L0X_Error VL53L0X::VL53L0X_perform_ref_calibration(VL53L0X_DEV dev, 02078 uint8_t *p_vhv_settings, uint8_t *p_phase_cal, uint8_t get_data_enable) 02079 { 02080 VL53L0X_Error status = VL53L0X_ERROR_NONE; 02081 uint8_t sequence_config = 0; 02082 02083 /* store the value of the sequence config, 02084 * this will be reset before the end of the function 02085 */ 02086 02087 sequence_config = PALDevDataGet(dev, SequenceConfig); 02088 02089 /* In the following function we don't save the config to optimize 02090 * writes on device. Config is saved and restored only once. */ 02091 status = VL53L0X_perform_vhv_calibration( 02092 dev, p_vhv_settings, get_data_enable, 0); 02093 02094 if (status == VL53L0X_ERROR_NONE) { 02095 status = VL53L0X_perform_phase_calibration( 02096 dev, p_phase_cal, get_data_enable, 0); 02097 } 02098 02099 02100 if (status == VL53L0X_ERROR_NONE) { 02101 /* restore the previous Sequence Config */ 02102 status = VL53L0X_write_byte(dev, VL53L0X_REG_SYSTEM_SEQUENCE_CONFIG, 02103 sequence_config); 02104 if (status == VL53L0X_ERROR_NONE) { 02105 PALDevDataSet(dev, SequenceConfig, sequence_config); 02106 } 02107 02108 } 02109 02110 return status; 02111 } 02112 02113 void VL53L0X::get_next_good_spad(uint8_t good_spad_array[], uint32_t size, 02114 uint32_t curr, int32_t *p_next) 02115 { 02116 uint32_t start_index; 02117 uint32_t fine_offset; 02118 uint32_t c_spads_per_byte = 8; 02119 uint32_t coarse_index; 02120 uint32_t fine_index; 02121 uint8_t data_byte; 02122 uint8_t success = 0; 02123 02124 /* 02125 * Starting with the current good spad, loop through the array to find 02126 * the next. i.e. the next bit set in the sequence. 02127 * 02128 * The coarse index is the byte index of the array and the fine index is 02129 * the index of the bit within each byte. 02130 */ 02131 02132 *p_next = -1; 02133 02134 start_index = curr / c_spads_per_byte; 02135 fine_offset = curr % c_spads_per_byte; 02136 02137 for (coarse_index = start_index; ((coarse_index < size) && !success); 02138 coarse_index++) { 02139 fine_index = 0; 02140 data_byte = good_spad_array[coarse_index]; 02141 02142 if (coarse_index == start_index) { 02143 /* locate the bit position of the provided current 02144 * spad bit before iterating */ 02145 data_byte >>= fine_offset; 02146 fine_index = fine_offset; 02147 } 02148 02149 while (fine_index < c_spads_per_byte) { 02150 if ((data_byte & 0x1) == 1) { 02151 success = 1; 02152 *p_next = coarse_index * c_spads_per_byte + fine_index; 02153 break; 02154 } 02155 data_byte >>= 1; 02156 fine_index++; 02157 } 02158 } 02159 } 02160 02161 uint8_t VL53L0X::is_aperture(uint32_t spad_index) 02162 { 02163 /* 02164 * This function reports if a given spad index is an aperture SPAD by 02165 * deriving the quadrant. 02166 */ 02167 uint32_t quadrant; 02168 uint8_t is_aperture = 1; 02169 quadrant = spad_index >> 6; 02170 if (refArrayQuadrants[quadrant] == REF_ARRAY_SPAD_0) { 02171 is_aperture = 0; 02172 } 02173 02174 return is_aperture; 02175 } 02176 02177 VL53L0X_Error VL53L0X::enable_spad_bit(uint8_t spad_array[], uint32_t size, 02178 uint32_t spad_index) 02179 { 02180 VL53L0X_Error status = VL53L0X_ERROR_NONE; 02181 uint32_t c_spads_per_byte = 8; 02182 uint32_t coarse_index; 02183 uint32_t fine_index; 02184 02185 coarse_index = spad_index / c_spads_per_byte; 02186 fine_index = spad_index % c_spads_per_byte; 02187 if (coarse_index >= size) { 02188 status = VL53L0X_ERROR_REF_SPAD_INIT; 02189 } else { 02190 spad_array[coarse_index] |= (1 << fine_index); 02191 } 02192 02193 return status; 02194 } 02195 02196 VL53L0X_Error VL53L0X::set_ref_spad_map(VL53L0X_DEV dev, uint8_t *p_ref_spad_array) 02197 { 02198 VL53L0X_Error status = VL53L0X_write_multi(dev, 02199 VL53L0X_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_0, 02200 p_ref_spad_array, 6); 02201 02202 return status; 02203 } 02204 02205 VL53L0X_Error VL53L0X::get_ref_spad_map(VL53L0X_DEV dev, uint8_t *p_ref_spad_array) 02206 { 02207 VL53L0X_Error status = VL53L0X_read_multi(dev, 02208 VL53L0X_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_0, 02209 p_ref_spad_array, 02210 6); 02211 // VL53L0X_Error status = VL53L0X_ERROR_NONE; 02212 // uint8_t count=0; 02213 02214 // for (count = 0; count < 6; count++) 02215 // status = VL53L0X_RdByte(Dev, (VL53L0X_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_0 + count), &refSpadArray[count]); 02216 return status; 02217 } 02218 02219 VL53L0X_Error VL53L0X::enable_ref_spads(VL53L0X_DEV dev, 02220 uint8_t aperture_spads, 02221 uint8_t good_spad_array[], 02222 uint8_t spad_array[], 02223 uint32_t size, 02224 uint32_t start, 02225 uint32_t offset, 02226 uint32_t spad_count, 02227 uint32_t *p_last_spad) 02228 { 02229 VL53L0X_Error status = VL53L0X_ERROR_NONE; 02230 uint32_t index; 02231 uint32_t i; 02232 int32_t next_good_spad = offset; 02233 uint32_t current_spad; 02234 uint8_t check_spad_array[6]; 02235 02236 /* 02237 * This function takes in a spad array which may or may not have SPADS 02238 * already enabled and appends from a given offset a requested number 02239 * of new SPAD enables. The 'good spad map' is applied to 02240 * determine the next SPADs to enable. 02241 * 02242 * This function applies to only aperture or only non-aperture spads. 02243 * Checks are performed to ensure this. 02244 */ 02245 02246 current_spad = offset; 02247 for (index = 0; index < spad_count; index++) { 02248 get_next_good_spad(good_spad_array, size, current_spad, 02249 &next_good_spad); 02250 02251 if (next_good_spad == -1) { 02252 status = VL53L0X_ERROR_REF_SPAD_INIT; 02253 break; 02254 } 02255 02256 /* Confirm that the next good SPAD is non-aperture */ 02257 if (is_aperture(start + next_good_spad) != aperture_spads) { 02258 /* if we can't get the required number of good aperture 02259 * spads from the current quadrant then this is an error 02260 */ 02261 status = VL53L0X_ERROR_REF_SPAD_INIT; 02262 break; 02263 } 02264 current_spad = (uint32_t)next_good_spad; 02265 enable_spad_bit(spad_array, size, current_spad); 02266 current_spad++; 02267 } 02268 *p_last_spad = current_spad; 02269 02270 if (status == VL53L0X_ERROR_NONE) { 02271 status = set_ref_spad_map(dev, spad_array); 02272 } 02273 02274 02275 if (status == VL53L0X_ERROR_NONE) { 02276 status = get_ref_spad_map(dev, check_spad_array); 02277 02278 i = 0; 02279 02280 /* Compare spad maps. If not equal report error. */ 02281 while (i < size) { 02282 if (spad_array[i] != check_spad_array[i]) { 02283 status = VL53L0X_ERROR_REF_SPAD_INIT; 02284 break; 02285 } 02286 i++; 02287 } 02288 } 02289 return status; 02290 } 02291 02292 VL53L0X_Error VL53L0X::VL53L0X_set_device_mode(VL53L0X_DEV dev, VL53L0X_DeviceModes device_mode) 02293 { 02294 VL53L0X_Error status = VL53L0X_ERROR_NONE; 02295 02296 LOG_FUNCTION_START("%d", (int)DeviceMode); 02297 02298 switch (device_mode) { 02299 case VL53L0X_DEVICEMODE_SINGLE_RANGING: 02300 case VL53L0X_DEVICEMODE_CONTINUOUS_RANGING: 02301 case VL53L0X_DEVICEMODE_CONTINUOUS_TIMED_RANGING: 02302 case VL53L0X_DEVICEMODE_GPIO_DRIVE: 02303 case VL53L0X_DEVICEMODE_GPIO_OSC: 02304 /* Supported modes */ 02305 VL53L0X_SETPARAMETERFIELD(dev, DeviceMode, device_mode); 02306 break; 02307 default: 02308 /* Unsupported mode */ 02309 status = VL53L0X_ERROR_MODE_NOT_SUPPORTED; 02310 } 02311 02312 LOG_FUNCTION_END(status); 02313 return status; 02314 } 02315 02316 VL53L0X_Error VL53L0X::VL53L0X_set_interrupt_thresholds(VL53L0X_DEV dev, 02317 VL53L0X_DeviceModes device_mode, FixPoint1616_t threshold_low, 02318 FixPoint1616_t threshold_high) 02319 { 02320 VL53L0X_Error status = VL53L0X_ERROR_NONE; 02321 uint16_t threshold16; 02322 LOG_FUNCTION_START(""); 02323 02324 /* no dependency on DeviceMode for Ewok */ 02325 /* Need to divide by 2 because the FW will apply a x2 */ 02326 threshold16 = (uint16_t)((threshold_low >> 17) & 0x00fff); 02327 status = VL53L0X_write_word(dev, VL53L0X_REG_SYSTEM_THRESH_LOW, threshold16); 02328 02329 if (status == VL53L0X_ERROR_NONE) { 02330 /* Need to divide by 2 because the FW will apply a x2 */ 02331 threshold16 = (uint16_t)((threshold_high >> 17) & 0x00fff); 02332 status = VL53L0X_write_word(dev, VL53L0X_REG_SYSTEM_THRESH_HIGH, 02333 threshold16); 02334 } 02335 02336 LOG_FUNCTION_END(status); 02337 return status; 02338 } 02339 02340 VL53L0X_Error VL53L0X::VL53L0X_get_interrupt_thresholds(VL53L0X_DEV dev, 02341 VL53L0X_DeviceModes device_mode, FixPoint1616_t *p_threshold_low, 02342 FixPoint1616_t *p_threshold_high) 02343 { 02344 VL53L0X_Error status = VL53L0X_ERROR_NONE; 02345 uint16_t threshold16; 02346 LOG_FUNCTION_START(""); 02347 02348 /* no dependency on DeviceMode for Ewok */ 02349 02350 status = VL53L0X_read_word(dev, VL53L0X_REG_SYSTEM_THRESH_LOW, &threshold16); 02351 /* Need to multiply by 2 because the FW will apply a x2 */ 02352 *p_threshold_low = (FixPoint1616_t)((0x00fff & threshold16) << 17); 02353 02354 if (status == VL53L0X_ERROR_NONE) { 02355 status = VL53L0X_read_word(dev, VL53L0X_REG_SYSTEM_THRESH_HIGH, 02356 &threshold16); 02357 /* Need to multiply by 2 because the FW will apply a x2 */ 02358 *p_threshold_high = 02359 (FixPoint1616_t)((0x00fff & threshold16) << 17); 02360 } 02361 02362 LOG_FUNCTION_END(status); 02363 return status; 02364 } 02365 02366 VL53L0X_Error VL53L0X::VL53L0X_load_tuning_settings(VL53L0X_DEV dev, 02367 uint8_t *p_tuning_setting_buffer) 02368 { 02369 VL53L0X_Error status = VL53L0X_ERROR_NONE; 02370 int i; 02371 int index; 02372 uint8_t msb; 02373 uint8_t lsb; 02374 uint8_t select_param; 02375 uint8_t number_of_writes; 02376 uint8_t address; 02377 uint8_t local_buffer[4]; /* max */ 02378 uint16_t temp16; 02379 02380 LOG_FUNCTION_START(""); 02381 02382 index = 0; 02383 02384 while ((*(p_tuning_setting_buffer + index) != 0) && 02385 (status == VL53L0X_ERROR_NONE)) { 02386 number_of_writes = *(p_tuning_setting_buffer + index); 02387 index++; 02388 if (number_of_writes == 0xFF) { 02389 /* internal parameters */ 02390 select_param = *(p_tuning_setting_buffer + index); 02391 index++; 02392 switch (select_param) { 02393 case 0: /* uint16_t SigmaEstRefArray -> 2 bytes */ 02394 msb = *(p_tuning_setting_buffer + index); 02395 index++; 02396 lsb = *(p_tuning_setting_buffer + index); 02397 index++; 02398 temp16 = VL53L0X_MAKEUINT16(lsb, msb); 02399 PALDevDataSet(dev, SigmaEstRefArray, temp16); 02400 break; 02401 case 1: /* uint16_t SigmaEstEffPulseWidth -> 2 bytes */ 02402 msb = *(p_tuning_setting_buffer + index); 02403 index++; 02404 lsb = *(p_tuning_setting_buffer + index); 02405 index++; 02406 temp16 = VL53L0X_MAKEUINT16(lsb, msb); 02407 PALDevDataSet(dev, SigmaEstEffPulseWidth, 02408 temp16); 02409 break; 02410 case 2: /* uint16_t SigmaEstEffAmbWidth -> 2 bytes */ 02411 msb = *(p_tuning_setting_buffer + index); 02412 index++; 02413 lsb = *(p_tuning_setting_buffer + index); 02414 index++; 02415 temp16 = VL53L0X_MAKEUINT16(lsb, msb); 02416 PALDevDataSet(dev, SigmaEstEffAmbWidth, temp16); 02417 break; 02418 case 3: /* uint16_t targetRefRate -> 2 bytes */ 02419 msb = *(p_tuning_setting_buffer + index); 02420 index++; 02421 lsb = *(p_tuning_setting_buffer + index); 02422 index++; 02423 temp16 = VL53L0X_MAKEUINT16(lsb, msb); 02424 PALDevDataSet(dev, targetRefRate, temp16); 02425 break; 02426 default: /* invalid parameter */ 02427 status = VL53L0X_ERROR_INVALID_PARAMS; 02428 } 02429 02430 } else if (number_of_writes <= 4) { 02431 address = *(p_tuning_setting_buffer + index); 02432 index++; 02433 02434 for (i = 0; i < number_of_writes; i++) { 02435 local_buffer[i] = *(p_tuning_setting_buffer + 02436 index); 02437 index++; 02438 } 02439 02440 status = VL53L0X_write_multi(dev, address, local_buffer, 02441 number_of_writes); 02442 02443 } else { 02444 status = VL53L0X_ERROR_INVALID_PARAMS; 02445 } 02446 } 02447 02448 LOG_FUNCTION_END(status); 02449 return status; 02450 } 02451 02452 VL53L0X_Error VL53L0X::VL53L0X_check_and_load_interrupt_settings(VL53L0X_DEV dev, 02453 uint8_t start_not_stopflag) 02454 { 02455 uint8_t interrupt_config; 02456 FixPoint1616_t threshold_low; 02457 FixPoint1616_t threshold_high; 02458 VL53L0X_Error status = VL53L0X_ERROR_NONE; 02459 02460 interrupt_config = VL53L0X_GETDEVICESPECIFICPARAMETER(dev, 02461 Pin0GpioFunctionality); 02462 02463 if ((interrupt_config == 02464 VL53L0X_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_LOW) || 02465 (interrupt_config == 02466 VL53L0X_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_HIGH) || 02467 (interrupt_config == 02468 VL53L0X_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_OUT)) { 02469 02470 status = VL53L0X_get_interrupt_thresholds(dev, 02471 VL53L0X_DEVICEMODE_CONTINUOUS_RANGING, 02472 &threshold_low, &threshold_high); 02473 02474 if (((threshold_low > 255 * 65536) || 02475 (threshold_high > 255 * 65536)) && 02476 (status == VL53L0X_ERROR_NONE)) { 02477 02478 if (start_not_stopflag != 0) { 02479 status = VL53L0X_load_tuning_settings(dev, 02480 InterruptThresholdSettings); 02481 } else { 02482 status |= VL53L0X_write_byte(dev, 0xFF, 0x04); 02483 status |= VL53L0X_write_byte(dev, 0x70, 0x00); 02484 status |= VL53L0X_write_byte(dev, 0xFF, 0x00); 02485 status |= VL53L0X_write_byte(dev, 0x80, 0x00); 02486 } 02487 02488 } 02489 02490 02491 } 02492 02493 return status; 02494 02495 } 02496 02497 VL53L0X_Error VL53L0X::VL53L0X_start_measurement(VL53L0X_DEV dev) 02498 { 02499 VL53L0X_Error status = VL53L0X_ERROR_NONE; 02500 VL53L0X_DeviceModes device_mode; 02501 uint8_t byte; 02502 uint8_t start_stop_byte = VL53L0X_REG_SYSRANGE_MODE_START_STOP; 02503 uint32_t loop_nb; 02504 LOG_FUNCTION_START(""); 02505 02506 /* Get Current DeviceMode */ 02507 VL53L0X_get_device_mode(dev, &device_mode); 02508 02509 status = VL53L0X_write_byte(dev, 0x80, 0x01); 02510 status = VL53L0X_write_byte(dev, 0xFF, 0x01); 02511 status = VL53L0X_write_byte(dev, 0x00, 0x00); 02512 status = VL53L0X_write_byte(dev, 0x91, PALDevDataGet(dev, StopVariable)); 02513 status = VL53L0X_write_byte(dev, 0x00, 0x01); 02514 status = VL53L0X_write_byte(dev, 0xFF, 0x00); 02515 status = VL53L0X_write_byte(dev, 0x80, 0x00); 02516 02517 switch (device_mode) { 02518 case VL53L0X_DEVICEMODE_SINGLE_RANGING: 02519 status = VL53L0X_write_byte(dev, VL53L0X_REG_SYSRANGE_START, 0x01); 02520 02521 byte = start_stop_byte; 02522 if (status == VL53L0X_ERROR_NONE) { 02523 /* Wait until start bit has been cleared */ 02524 loop_nb = 0; 02525 do { 02526 if (loop_nb > 0) 02527 status = VL53L0X_read_byte(dev, 02528 VL53L0X_REG_SYSRANGE_START, &byte); 02529 loop_nb = loop_nb + 1; 02530 } while (((byte & start_stop_byte) == start_stop_byte) 02531 && (status == VL53L0X_ERROR_NONE) 02532 && (loop_nb < VL53L0X_DEFAULT_MAX_LOOP)); 02533 02534 if (loop_nb >= VL53L0X_DEFAULT_MAX_LOOP) { 02535 status = VL53L0X_ERROR_TIME_OUT; 02536 } 02537 02538 } 02539 02540 break; 02541 case VL53L0X_DEVICEMODE_CONTINUOUS_RANGING: 02542 /* Back-to-back mode */ 02543 02544 /* Check if need to apply interrupt settings */ 02545 if (status == VL53L0X_ERROR_NONE) { 02546 status = VL53L0X_check_and_load_interrupt_settings(dev, 1); 02547 } 02548 02549 status = VL53L0X_write_byte(dev, 02550 VL53L0X_REG_SYSRANGE_START, 02551 VL53L0X_REG_SYSRANGE_MODE_BACKTOBACK); 02552 if (status == VL53L0X_ERROR_NONE) { 02553 /* Set PAL State to Running */ 02554 PALDevDataSet(dev, PalState, VL53L0X_STATE_RUNNING); 02555 } 02556 break; 02557 case VL53L0X_DEVICEMODE_CONTINUOUS_TIMED_RANGING: 02558 /* Continuous mode */ 02559 /* Check if need to apply interrupt settings */ 02560 if (status == VL53L0X_ERROR_NONE) { 02561 status = VL53L0X_check_and_load_interrupt_settings(dev, 1); 02562 } 02563 02564 status = VL53L0X_write_byte(dev, 02565 VL53L0X_REG_SYSRANGE_START, 02566 VL53L0X_REG_SYSRANGE_MODE_TIMED); 02567 02568 if (status == VL53L0X_ERROR_NONE) { 02569 /* Set PAL State to Running */ 02570 PALDevDataSet(dev, PalState, VL53L0X_STATE_RUNNING); 02571 } 02572 break; 02573 default: 02574 /* Selected mode not supported */ 02575 status = VL53L0X_ERROR_MODE_NOT_SUPPORTED; 02576 } 02577 02578 02579 LOG_FUNCTION_END(status); 02580 return status; 02581 } 02582 02583 /* Group PAL Measurement Functions */ 02584 VL53L0X_Error VL53L0X::VL53L0X_perform_single_measurement(VL53L0X_DEV dev) 02585 { 02586 VL53L0X_Error status = VL53L0X_ERROR_NONE; 02587 VL53L0X_DeviceModes device_mode; 02588 02589 LOG_FUNCTION_START(""); 02590 02591 /* Get Current DeviceMode */ 02592 status = VL53L0X_get_device_mode(dev, &device_mode); 02593 02594 /* Start immediately to run a single ranging measurement in case of 02595 * single ranging or single histogram */ 02596 if (status == VL53L0X_ERROR_NONE 02597 && device_mode == VL53L0X_DEVICEMODE_SINGLE_RANGING) { 02598 status = VL53L0X_start_measurement(dev); 02599 } 02600 02601 02602 if (status == VL53L0X_ERROR_NONE) { 02603 status = VL53L0X_measurement_poll_for_completion(dev); 02604 } 02605 02606 02607 /* Change PAL State in case of single ranging or single histogram */ 02608 if (status == VL53L0X_ERROR_NONE 02609 && device_mode == VL53L0X_DEVICEMODE_SINGLE_RANGING) { 02610 PALDevDataSet(dev, PalState, VL53L0X_STATE_IDLE); 02611 } 02612 02613 02614 LOG_FUNCTION_END(status); 02615 return status; 02616 } 02617 02618 VL53L0X_Error VL53L0X::VL53L0X_get_x_talk_compensation_enable(VL53L0X_DEV dev, 02619 uint8_t *p_x_talk_compensation_enable) 02620 { 02621 VL53L0X_Error status = VL53L0X_ERROR_NONE; 02622 uint8_t temp8; 02623 LOG_FUNCTION_START(""); 02624 02625 VL53L0X_GETPARAMETERFIELD(dev, XTalkCompensationEnable, temp8); 02626 *p_x_talk_compensation_enable = temp8; 02627 02628 LOG_FUNCTION_END(status); 02629 return status; 02630 } 02631 02632 VL53L0X_Error VL53L0X::VL53L0X_get_total_xtalk_rate(VL53L0X_DEV dev, 02633 VL53L0X_RangingMeasurementData_t *p_ranging_measurement_data, 02634 FixPoint1616_t *p_total_xtalk_rate_mcps) 02635 { 02636 VL53L0X_Error status = VL53L0X_ERROR_NONE; 02637 02638 uint8_t xtalk_comp_enable; 02639 FixPoint1616_t total_xtalk_mega_cps; 02640 FixPoint1616_t xtalk_per_spad_mega_cps; 02641 02642 *p_total_xtalk_rate_mcps = 0; 02643 02644 status = VL53L0X_get_x_talk_compensation_enable(dev, &xtalk_comp_enable); 02645 if (status == VL53L0X_ERROR_NONE) { 02646 02647 if (xtalk_comp_enable) { 02648 02649 VL53L0X_GETPARAMETERFIELD( 02650 dev, 02651 XTalkCompensationRateMegaCps, 02652 xtalk_per_spad_mega_cps); 02653 02654 /* FixPoint1616 * FixPoint 8:8 = FixPoint0824 */ 02655 total_xtalk_mega_cps = 02656 p_ranging_measurement_data->EffectiveSpadRtnCount * 02657 xtalk_per_spad_mega_cps; 02658 02659 /* FixPoint0824 >> 8 = FixPoint1616 */ 02660 *p_total_xtalk_rate_mcps = 02661 (total_xtalk_mega_cps + 0x80) >> 8; 02662 } 02663 } 02664 02665 return status; 02666 } 02667 02668 VL53L0X_Error VL53L0X::VL53L0X_get_total_signal_rate(VL53L0X_DEV dev, 02669 VL53L0X_RangingMeasurementData_t *p_ranging_measurement_data, 02670 FixPoint1616_t *p_total_signal_rate_mcps) 02671 { 02672 VL53L0X_Error status = VL53L0X_ERROR_NONE; 02673 FixPoint1616_t total_xtalk_mega_cps; 02674 02675 LOG_FUNCTION_START(""); 02676 02677 *p_total_signal_rate_mcps = 02678 p_ranging_measurement_data->SignalRateRtnMegaCps; 02679 02680 status = VL53L0X_get_total_xtalk_rate( 02681 dev, p_ranging_measurement_data, &total_xtalk_mega_cps); 02682 02683 if (status == VL53L0X_ERROR_NONE) { 02684 *p_total_signal_rate_mcps += total_xtalk_mega_cps; 02685 } 02686 02687 return status; 02688 } 02689 02690 /* To convert ms into register value */ 02691 uint32_t VL53L0X::VL53L0X_calc_timeout_mclks(VL53L0X_DEV dev, 02692 uint32_t timeout_period_us, 02693 uint8_t vcsel_period_pclks) 02694 { 02695 uint32_t macro_period_ps; 02696 uint32_t macro_period_ns; 02697 uint32_t timeout_period_mclks = 0; 02698 02699 macro_period_ps = VL53L0X_calc_macro_period_ps(dev, vcsel_period_pclks); 02700 macro_period_ns = (macro_period_ps + 500) / 1000; 02701 02702 timeout_period_mclks = 02703 (uint32_t)(((timeout_period_us * 1000) 02704 + (macro_period_ns / 2)) / macro_period_ns); 02705 02706 return timeout_period_mclks; 02707 } 02708 02709 uint32_t VL53L0X::VL53L0X_isqrt(uint32_t num) 02710 { 02711 /* 02712 * Implements an integer square root 02713 * 02714 * From: http://en.wikipedia.org/wiki/Methods_of_computing_square_roots 02715 */ 02716 02717 uint32_t res = 0; 02718 uint32_t bit = 1 << 30; 02719 /* The second-to-top bit is set: 02720 * 1 << 14 for 16-bits, 1 << 30 for 32 bits */ 02721 02722 /* "bit" starts at the highest power of four <= the argument. */ 02723 while (bit > num) { 02724 bit >>= 2; 02725 } 02726 02727 02728 while (bit != 0) { 02729 if (num >= res + bit) { 02730 num -= res + bit; 02731 res = (res >> 1) + bit; 02732 } else { 02733 res >>= 1; 02734 } 02735 02736 bit >>= 2; 02737 } 02738 02739 return res; 02740 } 02741 02742 VL53L0X_Error VL53L0X::VL53L0X_calc_dmax( 02743 VL53L0X_DEV dev, 02744 FixPoint1616_t total_signal_rate_mcps, 02745 FixPoint1616_t total_corr_signal_rate_mcps, 02746 FixPoint1616_t pw_mult, 02747 uint32_t sigma_estimate_p1, 02748 FixPoint1616_t sigma_estimate_p2, 02749 uint32_t peak_vcsel_duration_us, 02750 uint32_t *pd_max_mm) 02751 { 02752 const uint32_t c_sigma_limit = 18; 02753 const FixPoint1616_t c_signal_limit = 0x4000; /* 0.25 */ 02754 const FixPoint1616_t c_sigma_est_ref = 0x00000042; /* 0.001 */ 02755 const uint32_t c_amb_eff_width_sigma_est_ns = 6; 02756 const uint32_t c_amb_eff_width_d_max_ns = 7; 02757 uint32_t dmax_cal_range_mm; 02758 FixPoint1616_t dmax_cal_signal_rate_rtn_mcps; 02759 FixPoint1616_t min_signal_needed; 02760 FixPoint1616_t min_signal_needed_p1; 02761 FixPoint1616_t min_signal_needed_p2; 02762 FixPoint1616_t min_signal_needed_p3; 02763 FixPoint1616_t min_signal_needed_p4; 02764 FixPoint1616_t sigma_limit_tmp; 02765 FixPoint1616_t sigma_est_sq_tmp; 02766 FixPoint1616_t signal_limit_tmp; 02767 FixPoint1616_t signal_at0_mm; 02768 FixPoint1616_t dmax_dark; 02769 FixPoint1616_t dmax_ambient; 02770 FixPoint1616_t dmax_dark_tmp; 02771 FixPoint1616_t sigma_est_p2_tmp; 02772 uint32_t signal_rate_temp_mcps; 02773 02774 VL53L0X_Error status = VL53L0X_ERROR_NONE; 02775 02776 LOG_FUNCTION_START(""); 02777 02778 dmax_cal_range_mm = 02779 PALDevDataGet(dev, DmaxCalRangeMilliMeter); 02780 02781 dmax_cal_signal_rate_rtn_mcps = 02782 PALDevDataGet(dev, DmaxCalSignalRateRtnMegaCps); 02783 02784 /* uint32 * FixPoint1616 = FixPoint1616 */ 02785 signal_at0_mm = dmax_cal_range_mm * dmax_cal_signal_rate_rtn_mcps; 02786 02787 /* FixPoint1616 >> 8 = FixPoint2408 */ 02788 signal_at0_mm = (signal_at0_mm + 0x80) >> 8; 02789 signal_at0_mm *= dmax_cal_range_mm; 02790 02791 min_signal_needed_p1 = 0; 02792 if (total_corr_signal_rate_mcps > 0) { 02793 02794 /* Shift by 10 bits to increase resolution prior to the 02795 * division */ 02796 signal_rate_temp_mcps = total_signal_rate_mcps << 10; 02797 02798 /* Add rounding value prior to division */ 02799 min_signal_needed_p1 = signal_rate_temp_mcps + 02800 (total_corr_signal_rate_mcps / 2); 02801 02802 /* FixPoint0626/FixPoint1616 = FixPoint2210 */ 02803 min_signal_needed_p1 /= total_corr_signal_rate_mcps; 02804 02805 /* Apply a factored version of the speed of light. 02806 Correction to be applied at the end */ 02807 min_signal_needed_p1 *= 3; 02808 02809 /* FixPoint2210 * FixPoint2210 = FixPoint1220 */ 02810 min_signal_needed_p1 *= min_signal_needed_p1; 02811 02812 /* FixPoint1220 >> 16 = FixPoint2804 */ 02813 min_signal_needed_p1 = (min_signal_needed_p1 + 0x8000) >> 16; 02814 } 02815 02816 min_signal_needed_p2 = pw_mult * sigma_estimate_p1; 02817 02818 /* FixPoint1616 >> 16 = uint32 */ 02819 min_signal_needed_p2 = (min_signal_needed_p2 + 0x8000) >> 16; 02820 02821 /* uint32 * uint32 = uint32 */ 02822 min_signal_needed_p2 *= min_signal_needed_p2; 02823 02824 /* Check sigmaEstimateP2 02825 * If this value is too high there is not enough signal rate 02826 * to calculate dmax value so set a suitable value to ensure 02827 * a very small dmax. 02828 */ 02829 sigma_est_p2_tmp = (sigma_estimate_p2 + 0x8000) >> 16; 02830 sigma_est_p2_tmp = (sigma_est_p2_tmp + c_amb_eff_width_sigma_est_ns / 2) / 02831 c_amb_eff_width_sigma_est_ns; 02832 sigma_est_p2_tmp *= c_amb_eff_width_d_max_ns; 02833 02834 if (sigma_est_p2_tmp > 0xffff) { 02835 min_signal_needed_p3 = 0xfff00000; 02836 } else { 02837 02838 /* DMAX uses a different ambient width from sigma, so apply 02839 * correction. 02840 * Perform division before multiplication to prevent overflow. 02841 */ 02842 sigma_estimate_p2 = (sigma_estimate_p2 + c_amb_eff_width_sigma_est_ns / 2) / 02843 c_amb_eff_width_sigma_est_ns; 02844 sigma_estimate_p2 *= c_amb_eff_width_d_max_ns; 02845 02846 /* FixPoint1616 >> 16 = uint32 */ 02847 min_signal_needed_p3 = (sigma_estimate_p2 + 0x8000) >> 16; 02848 02849 min_signal_needed_p3 *= min_signal_needed_p3; 02850 02851 } 02852 02853 /* FixPoint1814 / uint32 = FixPoint1814 */ 02854 sigma_limit_tmp = ((c_sigma_limit << 14) + 500) / 1000; 02855 02856 /* FixPoint1814 * FixPoint1814 = FixPoint3628 := FixPoint0428 */ 02857 sigma_limit_tmp *= sigma_limit_tmp; 02858 02859 /* FixPoint1616 * FixPoint1616 = FixPoint3232 */ 02860 sigma_est_sq_tmp = c_sigma_est_ref * c_sigma_est_ref; 02861 02862 /* FixPoint3232 >> 4 = FixPoint0428 */ 02863 sigma_est_sq_tmp = (sigma_est_sq_tmp + 0x08) >> 4; 02864 02865 /* FixPoint0428 - FixPoint0428 = FixPoint0428 */ 02866 sigma_limit_tmp -= sigma_est_sq_tmp; 02867 02868 /* uint32_t * FixPoint0428 = FixPoint0428 */ 02869 min_signal_needed_p4 = 4 * 12 * sigma_limit_tmp; 02870 02871 /* FixPoint0428 >> 14 = FixPoint1814 */ 02872 min_signal_needed_p4 = (min_signal_needed_p4 + 0x2000) >> 14; 02873 02874 /* uint32 + uint32 = uint32 */ 02875 min_signal_needed = (min_signal_needed_p2 + min_signal_needed_p3); 02876 02877 /* uint32 / uint32 = uint32 */ 02878 min_signal_needed += (peak_vcsel_duration_us / 2); 02879 min_signal_needed /= peak_vcsel_duration_us; 02880 02881 /* uint32 << 14 = FixPoint1814 */ 02882 min_signal_needed <<= 14; 02883 02884 /* FixPoint1814 / FixPoint1814 = uint32 */ 02885 min_signal_needed += (min_signal_needed_p4 / 2); 02886 min_signal_needed /= min_signal_needed_p4; 02887 02888 /* FixPoint3200 * FixPoint2804 := FixPoint2804*/ 02889 min_signal_needed *= min_signal_needed_p1; 02890 02891 /* Apply correction by dividing by 1000000. 02892 * This assumes 10E16 on the numerator of the equation 02893 * and 10E-22 on the denominator. 02894 * We do this because 32bit fix point calculation can't 02895 * handle the larger and smaller elements of this equation, 02896 * i.e. speed of light and pulse widths. 02897 */ 02898 min_signal_needed = (min_signal_needed + 500) / 1000; 02899 min_signal_needed <<= 4; 02900 02901 min_signal_needed = (min_signal_needed + 500) / 1000; 02902 02903 /* FixPoint1616 >> 8 = FixPoint2408 */ 02904 signal_limit_tmp = (c_signal_limit + 0x80) >> 8; 02905 02906 /* FixPoint2408/FixPoint2408 = uint32 */ 02907 if (signal_limit_tmp != 0) { 02908 dmax_dark_tmp = (signal_at0_mm + (signal_limit_tmp / 2)) 02909 / signal_limit_tmp; 02910 } else { 02911 dmax_dark_tmp = 0; 02912 } 02913 02914 dmax_dark = VL53L0X_isqrt(dmax_dark_tmp); 02915 02916 /* FixPoint2408/FixPoint2408 = uint32 */ 02917 if (min_signal_needed != 0) { 02918 dmax_ambient = (signal_at0_mm + min_signal_needed / 2) 02919 / min_signal_needed; 02920 } else { 02921 dmax_ambient = 0; 02922 } 02923 02924 dmax_ambient = VL53L0X_isqrt(dmax_ambient); 02925 02926 *pd_max_mm = dmax_dark; 02927 if (dmax_dark > dmax_ambient) { 02928 *pd_max_mm = dmax_ambient; 02929 } 02930 02931 LOG_FUNCTION_END(status); 02932 02933 return status; 02934 } 02935 02936 VL53L0X_Error VL53L0X::VL53L0X_calc_sigma_estimate(VL53L0X_DEV dev, 02937 VL53L0X_RangingMeasurementData_t *p_ranging_measurement_data, 02938 FixPoint1616_t *p_sigma_estimate, 02939 uint32_t *p_dmax_mm) 02940 { 02941 /* Expressed in 100ths of a ns, i.e. centi-ns */ 02942 const uint32_t c_pulse_effective_width_centi_ns = 800; 02943 /* Expressed in 100ths of a ns, i.e. centi-ns */ 02944 const uint32_t c_ambient_effective_width_centi_ns = 600; 02945 const FixPoint1616_t c_dflt_final_range_integration_time_milli_secs = 0x00190000; /* 25ms */ 02946 const uint32_t c_vcsel_pulse_width_ps = 4700; /* pico secs */ 02947 const FixPoint1616_t c_sigma_est_max = 0x028F87AE; 02948 const FixPoint1616_t c_sigma_est_rtn_max = 0xF000; 02949 const FixPoint1616_t c_amb_to_signal_ratio_max = 0xF0000000 / 02950 c_ambient_effective_width_centi_ns; 02951 /* Time Of Flight per mm (6.6 pico secs) */ 02952 const FixPoint1616_t c_tof_per_mm_ps = 0x0006999A; 02953 const uint32_t c_16bit_rounding_param = 0x00008000; 02954 const FixPoint1616_t c_max_x_talk_kcps = 0x00320000; 02955 const uint32_t c_pll_period_ps = 1655; 02956 02957 uint32_t vcsel_total_events_rtn; 02958 uint32_t final_range_timeout_micro_secs; 02959 uint32_t pre_range_timeout_micro_secs; 02960 uint32_t final_range_integration_time_milli_secs; 02961 FixPoint1616_t sigma_estimate_p1; 02962 FixPoint1616_t sigma_estimate_p2; 02963 FixPoint1616_t sigma_estimate_p3; 02964 FixPoint1616_t delta_t_ps; 02965 FixPoint1616_t pw_mult; 02966 FixPoint1616_t sigma_est_rtn; 02967 FixPoint1616_t sigma_estimate; 02968 FixPoint1616_t x_talk_correction; 02969 FixPoint1616_t ambient_rate_kcps; 02970 FixPoint1616_t peak_signal_rate_kcps; 02971 FixPoint1616_t x_talk_comp_rate_mcps; 02972 uint32_t x_talk_comp_rate_kcps; 02973 VL53L0X_Error status = VL53L0X_ERROR_NONE; 02974 FixPoint1616_t diff1_mcps; 02975 FixPoint1616_t diff2_mcps; 02976 FixPoint1616_t sqr1; 02977 FixPoint1616_t sqr2; 02978 FixPoint1616_t sqr_sum; 02979 FixPoint1616_t sqrt_result_centi_ns; 02980 FixPoint1616_t sqrt_result; 02981 FixPoint1616_t total_signal_rate_mcps; 02982 FixPoint1616_t corrected_signal_rate_mcps; 02983 FixPoint1616_t sigma_est_ref; 02984 uint32_t vcsel_width; 02985 uint32_t final_range_macro_pclks; 02986 uint32_t pre_range_macro_pclks; 02987 uint32_t peak_vcsel_duration_us; 02988 uint8_t final_range_vcsel_pclks; 02989 uint8_t pre_range_vcsel_pclks; 02990 /*! \addtogroup calc_sigma_estimate 02991 * @{ 02992 * 02993 * Estimates the range sigma 02994 */ 02995 02996 LOG_FUNCTION_START(""); 02997 02998 VL53L0X_GETPARAMETERFIELD(dev, XTalkCompensationRateMegaCps, 02999 x_talk_comp_rate_mcps); 03000 03001 /* 03002 * We work in kcps rather than mcps as this helps keep within the 03003 * confines of the 32 Fix1616 type. 03004 */ 03005 03006 ambient_rate_kcps = 03007 (p_ranging_measurement_data->AmbientRateRtnMegaCps * 1000) >> 16; 03008 03009 corrected_signal_rate_mcps = 03010 p_ranging_measurement_data->SignalRateRtnMegaCps; 03011 03012 03013 status = VL53L0X_get_total_signal_rate( 03014 dev, p_ranging_measurement_data, &total_signal_rate_mcps); 03015 status = VL53L0X_get_total_xtalk_rate( 03016 dev, p_ranging_measurement_data, &x_talk_comp_rate_mcps); 03017 03018 03019 /* Signal rate measurement provided by device is the 03020 * peak signal rate, not average. 03021 */ 03022 peak_signal_rate_kcps = (total_signal_rate_mcps * 1000); 03023 peak_signal_rate_kcps = (peak_signal_rate_kcps + 0x8000) >> 16; 03024 03025 x_talk_comp_rate_kcps = x_talk_comp_rate_mcps * 1000; 03026 03027 if (x_talk_comp_rate_kcps > c_max_x_talk_kcps) { 03028 x_talk_comp_rate_kcps = c_max_x_talk_kcps; 03029 } 03030 03031 if (status == VL53L0X_ERROR_NONE) { 03032 03033 /* Calculate final range macro periods */ 03034 final_range_timeout_micro_secs = VL53L0X_GETDEVICESPECIFICPARAMETER( 03035 dev, FinalRangeTimeoutMicroSecs); 03036 03037 final_range_vcsel_pclks = VL53L0X_GETDEVICESPECIFICPARAMETER( 03038 dev, FinalRangeVcselPulsePeriod); 03039 03040 final_range_macro_pclks = VL53L0X_calc_timeout_mclks( 03041 dev, final_range_timeout_micro_secs, final_range_vcsel_pclks); 03042 03043 /* Calculate pre-range macro periods */ 03044 pre_range_timeout_micro_secs = VL53L0X_GETDEVICESPECIFICPARAMETER( 03045 dev, PreRangeTimeoutMicroSecs); 03046 03047 pre_range_vcsel_pclks = VL53L0X_GETDEVICESPECIFICPARAMETER( 03048 dev, PreRangeVcselPulsePeriod); 03049 03050 pre_range_macro_pclks = VL53L0X_calc_timeout_mclks( 03051 dev, pre_range_timeout_micro_secs, pre_range_vcsel_pclks); 03052 03053 vcsel_width = 3; 03054 if (final_range_vcsel_pclks == 8) { 03055 vcsel_width = 2; 03056 } 03057 03058 03059 peak_vcsel_duration_us = vcsel_width * 2048 * 03060 (pre_range_macro_pclks + final_range_macro_pclks); 03061 peak_vcsel_duration_us = (peak_vcsel_duration_us + 500) / 1000; 03062 peak_vcsel_duration_us *= c_pll_period_ps; 03063 peak_vcsel_duration_us = (peak_vcsel_duration_us + 500) / 1000; 03064 03065 /* Fix1616 >> 8 = Fix2408 */ 03066 total_signal_rate_mcps = (total_signal_rate_mcps + 0x80) >> 8; 03067 03068 /* Fix2408 * uint32 = Fix2408 */ 03069 vcsel_total_events_rtn = total_signal_rate_mcps * 03070 peak_vcsel_duration_us; 03071 03072 /* Fix2408 >> 8 = uint32 */ 03073 vcsel_total_events_rtn = (vcsel_total_events_rtn + 0x80) >> 8; 03074 03075 /* Fix2408 << 8 = Fix1616 = */ 03076 total_signal_rate_mcps <<= 8; 03077 } 03078 03079 if (status != VL53L0X_ERROR_NONE) { 03080 LOG_FUNCTION_END(status); 03081 return status; 03082 } 03083 03084 if (peak_signal_rate_kcps == 0) { 03085 *p_sigma_estimate = c_sigma_est_max; 03086 PALDevDataSet(dev, SigmaEstimate, c_sigma_est_max); 03087 *p_dmax_mm = 0; 03088 } else { 03089 if (vcsel_total_events_rtn < 1) { 03090 vcsel_total_events_rtn = 1; 03091 } 03092 03093 sigma_estimate_p1 = c_pulse_effective_width_centi_ns; 03094 03095 /* ((FixPoint1616 << 16)* uint32)/uint32 = FixPoint1616 */ 03096 sigma_estimate_p2 = (ambient_rate_kcps << 16) / peak_signal_rate_kcps; 03097 if (sigma_estimate_p2 > c_amb_to_signal_ratio_max) { 03098 /* Clip to prevent overflow. Will ensure safe 03099 * max result. */ 03100 sigma_estimate_p2 = c_amb_to_signal_ratio_max; 03101 } 03102 sigma_estimate_p2 *= c_ambient_effective_width_centi_ns; 03103 03104 sigma_estimate_p3 = 2 * VL53L0X_isqrt(vcsel_total_events_rtn * 12); 03105 03106 /* uint32 * FixPoint1616 = FixPoint1616 */ 03107 delta_t_ps = p_ranging_measurement_data->RangeMilliMeter * 03108 c_tof_per_mm_ps; 03109 03110 /* 03111 * vcselRate - xtalkCompRate 03112 * (uint32 << 16) - FixPoint1616 = FixPoint1616. 03113 * Divide result by 1000 to convert to mcps. 03114 * 500 is added to ensure rounding when integer division 03115 * truncates. 03116 */ 03117 diff1_mcps = (((peak_signal_rate_kcps << 16) - 03118 2 * x_talk_comp_rate_kcps) + 500) / 1000; 03119 03120 /* vcselRate + xtalkCompRate */ 03121 diff2_mcps = ((peak_signal_rate_kcps << 16) + 500) / 1000; 03122 03123 /* Shift by 8 bits to increase resolution prior to the 03124 * division */ 03125 diff1_mcps <<= 8; 03126 03127 /* FixPoint0824/FixPoint1616 = FixPoint2408 */ 03128 // xTalkCorrection = abs(diff1_mcps/diff2_mcps); 03129 // abs is causing compiler overloading isue in C++, but unsigned types. So, redundant call anyway! 03130 x_talk_correction = diff1_mcps / diff2_mcps; 03131 03132 /* FixPoint2408 << 8 = FixPoint1616 */ 03133 x_talk_correction <<= 8; 03134 03135 if (p_ranging_measurement_data->RangeStatus != 0) { 03136 pw_mult = 1 << 16; 03137 } else { 03138 /* FixPoint1616/uint32 = FixPoint1616 */ 03139 pw_mult = delta_t_ps / c_vcsel_pulse_width_ps; /* smaller than 1.0f */ 03140 03141 /* 03142 * FixPoint1616 * FixPoint1616 = FixPoint3232, however both 03143 * values are small enough such that32 bits will not be 03144 * exceeded. 03145 */ 03146 pw_mult *= ((1 << 16) - x_talk_correction); 03147 03148 /* (FixPoint3232 >> 16) = FixPoint1616 */ 03149 pw_mult = (pw_mult + c_16bit_rounding_param) >> 16; 03150 03151 /* FixPoint1616 + FixPoint1616 = FixPoint1616 */ 03152 pw_mult += (1 << 16); 03153 03154 /* 03155 * At this point the value will be 1.xx, therefore if we square 03156 * the value this will exceed 32 bits. To address this perform 03157 * a single shift to the right before the multiplication. 03158 */ 03159 pw_mult >>= 1; 03160 /* FixPoint1715 * FixPoint1715 = FixPoint3430 */ 03161 pw_mult = pw_mult * pw_mult; 03162 03163 /* (FixPoint3430 >> 14) = Fix1616 */ 03164 pw_mult >>= 14; 03165 } 03166 03167 /* FixPoint1616 * uint32 = FixPoint1616 */ 03168 sqr1 = pw_mult * sigma_estimate_p1; 03169 03170 /* (FixPoint1616 >> 16) = FixPoint3200 */ 03171 sqr1 = (sqr1 + 0x8000) >> 16; 03172 03173 /* FixPoint3200 * FixPoint3200 = FixPoint6400 */ 03174 sqr1 *= sqr1; 03175 03176 sqr2 = sigma_estimate_p2; 03177 03178 /* (FixPoint1616 >> 16) = FixPoint3200 */ 03179 sqr2 = (sqr2 + 0x8000) >> 16; 03180 03181 /* FixPoint3200 * FixPoint3200 = FixPoint6400 */ 03182 sqr2 *= sqr2; 03183 03184 /* FixPoint64000 + FixPoint6400 = FixPoint6400 */ 03185 sqr_sum = sqr1 + sqr2; 03186 03187 /* SQRT(FixPoin6400) = FixPoint3200 */ 03188 sqrt_result_centi_ns = VL53L0X_isqrt(sqr_sum); 03189 03190 /* (FixPoint3200 << 16) = FixPoint1616 */ 03191 sqrt_result_centi_ns <<= 16; 03192 03193 /* 03194 * Note that the Speed Of Light is expressed in um per 1E-10 03195 * seconds (2997) Therefore to get mm/ns we have to divide by 03196 * 10000 03197 */ 03198 sigma_est_rtn = (((sqrt_result_centi_ns + 50) / 100) / 03199 sigma_estimate_p3); 03200 sigma_est_rtn *= VL53L0X_SPEED_OF_LIGHT_IN_AIR; 03201 03202 /* Add 5000 before dividing by 10000 to ensure rounding. */ 03203 sigma_est_rtn += 5000; 03204 sigma_est_rtn /= 10000; 03205 03206 if (sigma_est_rtn > c_sigma_est_rtn_max) { 03207 /* Clip to prevent overflow. Will ensure safe 03208 * max result. */ 03209 sigma_est_rtn = c_sigma_est_rtn_max; 03210 } 03211 final_range_integration_time_milli_secs = 03212 (final_range_timeout_micro_secs + pre_range_timeout_micro_secs + 500) / 1000; 03213 03214 /* sigmaEstRef = 1mm * 25ms/final range integration time (inc pre-range) 03215 * sqrt(FixPoint1616/int) = FixPoint2408) 03216 */ 03217 sigma_est_ref = 03218 VL53L0X_isqrt((c_dflt_final_range_integration_time_milli_secs + 03219 final_range_integration_time_milli_secs / 2) / 03220 final_range_integration_time_milli_secs); 03221 03222 /* FixPoint2408 << 8 = FixPoint1616 */ 03223 sigma_est_ref <<= 8; 03224 sigma_est_ref = (sigma_est_ref + 500) / 1000; 03225 03226 /* FixPoint1616 * FixPoint1616 = FixPoint3232 */ 03227 sqr1 = sigma_est_rtn * sigma_est_rtn; 03228 /* FixPoint1616 * FixPoint1616 = FixPoint3232 */ 03229 sqr2 = sigma_est_ref * sigma_est_ref; 03230 03231 /* sqrt(FixPoint3232) = FixPoint1616 */ 03232 sqrt_result = VL53L0X_isqrt((sqr1 + sqr2)); 03233 /* 03234 * Note that the Shift by 4 bits increases resolution prior to 03235 * the sqrt, therefore the result must be shifted by 2 bits to 03236 * the right to revert back to the FixPoint1616 format. 03237 */ 03238 03239 sigma_estimate = 1000 * sqrt_result; 03240 03241 if ((peak_signal_rate_kcps < 1) || (vcsel_total_events_rtn < 1) || 03242 (sigma_estimate > c_sigma_est_max)) { 03243 sigma_estimate = c_sigma_est_max; 03244 } 03245 03246 *p_sigma_estimate = (uint32_t)(sigma_estimate); 03247 PALDevDataSet(dev, SigmaEstimate, *p_sigma_estimate); 03248 status = VL53L0X_calc_dmax( 03249 dev, 03250 total_signal_rate_mcps, 03251 corrected_signal_rate_mcps, 03252 pw_mult, 03253 sigma_estimate_p1, 03254 sigma_estimate_p2, 03255 peak_vcsel_duration_us, 03256 p_dmax_mm); 03257 } 03258 03259 LOG_FUNCTION_END(status); 03260 return status; 03261 } 03262 03263 VL53L0X_Error VL53L0X::VL53L0X_get_pal_range_status(VL53L0X_DEV dev, 03264 uint8_t device_range_status, 03265 FixPoint1616_t signal_rate, 03266 uint16_t effective_spad_rtn_count, 03267 VL53L0X_RangingMeasurementData_t *p_ranging_measurement_data, 03268 uint8_t *p_pal_range_status) 03269 { 03270 VL53L0X_Error status = VL53L0X_ERROR_NONE; 03271 uint8_t none_flag; 03272 uint8_t sigma_limitflag = 0; 03273 uint8_t signal_ref_clipflag = 0; 03274 uint8_t range_ignore_thresholdflag = 0; 03275 uint8_t sigma_limit_check_enable = 0; 03276 uint8_t signal_rate_final_range_limit_check_enable = 0; 03277 uint8_t signal_ref_clip_limit_check_enable = 0; 03278 uint8_t range_ignore_threshold_limit_check_enable = 0; 03279 FixPoint1616_t sigma_estimate; 03280 FixPoint1616_t sigma_limit_value; 03281 FixPoint1616_t signal_ref_clip_value; 03282 FixPoint1616_t range_ignore_threshold_value; 03283 FixPoint1616_t signal_rate_per_spad; 03284 uint8_t device_range_status_internal = 0; 03285 uint16_t tmp_word = 0; 03286 uint8_t temp8; 03287 uint32_t dmax_mm = 0; 03288 FixPoint1616_t last_signal_ref_mcps; 03289 03290 LOG_FUNCTION_START(""); 03291 03292 03293 /* 03294 * VL53L0X has a good ranging when the value of the 03295 * DeviceRangeStatus = 11. This function will replace the value 0 with 03296 * the value 11 in the DeviceRangeStatus. 03297 * In addition, the SigmaEstimator is not included in the VL53L0X 03298 * DeviceRangeStatus, this will be added in the PalRangeStatus. 03299 */ 03300 03301 device_range_status_internal = ((device_range_status & 0x78) >> 3); 03302 03303 if (device_range_status_internal == 0 || 03304 device_range_status_internal == 5 || 03305 device_range_status_internal == 7 || 03306 device_range_status_internal == 12 || 03307 device_range_status_internal == 13 || 03308 device_range_status_internal == 14 || 03309 device_range_status_internal == 15 03310 ) { 03311 none_flag = 1; 03312 } else { 03313 none_flag = 0; 03314 } 03315 03316 /* 03317 * Check if Sigma limit is enabled, if yes then do comparison with limit 03318 * value and put the result back into pPalRangeStatus. 03319 */ 03320 if (status == VL53L0X_ERROR_NONE) { 03321 status = VL53L0X_get_limit_check_enable(dev, 03322 VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE, 03323 &sigma_limit_check_enable); 03324 } 03325 03326 if ((sigma_limit_check_enable != 0) && (status == VL53L0X_ERROR_NONE)) { 03327 /* 03328 * compute the Sigma and check with limit 03329 */ 03330 status = VL53L0X_calc_sigma_estimate( 03331 dev, 03332 p_ranging_measurement_data, 03333 &sigma_estimate, 03334 &dmax_mm); 03335 if (status == VL53L0X_ERROR_NONE) { 03336 p_ranging_measurement_data->RangeDMaxMilliMeter = dmax_mm; 03337 } 03338 03339 if (status == VL53L0X_ERROR_NONE) { 03340 status = VL53L0X_get_limit_check_value(dev, 03341 VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE, 03342 &sigma_limit_value); 03343 03344 if ((sigma_limit_value > 0) && 03345 (sigma_estimate > sigma_limit_value)) { 03346 /* Limit Fail */ 03347 sigma_limitflag = 1; 03348 } 03349 } 03350 } 03351 03352 /* 03353 * Check if Signal ref clip limit is enabled, if yes then do comparison 03354 * with limit value and put the result back into pPalRangeStatus. 03355 */ 03356 if (status == VL53L0X_ERROR_NONE) { 03357 status = VL53L0X_get_limit_check_enable(dev, 03358 VL53L0X_CHECKENABLE_SIGNAL_REF_CLIP, 03359 &signal_ref_clip_limit_check_enable); 03360 } 03361 03362 if ((signal_ref_clip_limit_check_enable != 0) && 03363 (status == VL53L0X_ERROR_NONE)) { 03364 03365 status = VL53L0X_get_limit_check_value(dev, 03366 VL53L0X_CHECKENABLE_SIGNAL_REF_CLIP, 03367 &signal_ref_clip_value); 03368 03369 /* Read LastSignalRefMcps from device */ 03370 if (status == VL53L0X_ERROR_NONE) { 03371 status = VL53L0X_write_byte(dev, 0xFF, 0x01); 03372 } 03373 03374 if (status == VL53L0X_ERROR_NONE) { 03375 status = VL53L0X_read_word(dev, 03376 VL53L0X_REG_RESULT_PEAK_SIGNAL_RATE_REF, 03377 &tmp_word); 03378 } 03379 03380 if (status == VL53L0X_ERROR_NONE) { 03381 status = VL53L0X_write_byte(dev, 0xFF, 0x00); 03382 } 03383 03384 last_signal_ref_mcps = VL53L0X_FIXPOINT97TOFIXPOINT1616(tmp_word); 03385 PALDevDataSet(dev, LastSignalRefMcps, last_signal_ref_mcps); 03386 03387 if ((signal_ref_clip_value > 0) && 03388 (last_signal_ref_mcps > signal_ref_clip_value)) { 03389 /* Limit Fail */ 03390 signal_ref_clipflag = 1; 03391 } 03392 } 03393 03394 /* 03395 * Check if Signal ref clip limit is enabled, if yes then do comparison 03396 * with limit value and put the result back into pPalRangeStatus. 03397 * EffectiveSpadRtnCount has a format 8.8 03398 * If (Return signal rate < (1.5 x Xtalk x number of Spads)) : FAIL 03399 */ 03400 if (status == VL53L0X_ERROR_NONE) { 03401 status = VL53L0X_get_limit_check_enable(dev, 03402 VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD, 03403 &range_ignore_threshold_limit_check_enable); 03404 } 03405 03406 if ((range_ignore_threshold_limit_check_enable != 0) && 03407 (status == VL53L0X_ERROR_NONE)) { 03408 03409 /* Compute the signal rate per spad */ 03410 if (effective_spad_rtn_count == 0) { 03411 signal_rate_per_spad = 0; 03412 } else { 03413 signal_rate_per_spad = (FixPoint1616_t)((256 * signal_rate) 03414 / effective_spad_rtn_count); 03415 } 03416 03417 status = VL53L0X_get_limit_check_value(dev, 03418 VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD, 03419 &range_ignore_threshold_value); 03420 03421 if ((range_ignore_threshold_value > 0) && 03422 (signal_rate_per_spad < range_ignore_threshold_value)) { 03423 /* Limit Fail add 2^6 to range status */ 03424 range_ignore_thresholdflag = 1; 03425 } 03426 } 03427 03428 if (status == VL53L0X_ERROR_NONE) { 03429 if (none_flag == 1) { 03430 *p_pal_range_status = 255; /* NONE */ 03431 } else if (device_range_status_internal == 1 || 03432 device_range_status_internal == 2 || 03433 device_range_status_internal == 3) { 03434 *p_pal_range_status = 5; /* HW fail */ 03435 } else if (device_range_status_internal == 6 || 03436 device_range_status_internal == 9) { 03437 *p_pal_range_status = 4; /* Phase fail */ 03438 } else if (device_range_status_internal == 8 || 03439 device_range_status_internal == 10 || 03440 signal_ref_clipflag == 1) { 03441 *p_pal_range_status = 3; /* Min range */ 03442 } else if (device_range_status_internal == 4 || 03443 range_ignore_thresholdflag == 1) { 03444 *p_pal_range_status = 2; /* Signal Fail */ 03445 } else if (sigma_limitflag == 1) { 03446 *p_pal_range_status = 1; /* Sigma Fail */ 03447 } else { 03448 *p_pal_range_status = 0; /* Range Valid */ 03449 } 03450 } 03451 03452 /* DMAX only relevant during range error */ 03453 if (*p_pal_range_status == 0) { 03454 p_ranging_measurement_data->RangeDMaxMilliMeter = 0; 03455 } 03456 03457 /* fill the Limit Check Status */ 03458 03459 status = VL53L0X_get_limit_check_enable(dev, 03460 VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE, 03461 &signal_rate_final_range_limit_check_enable); 03462 03463 if (status == VL53L0X_ERROR_NONE) { 03464 if ((sigma_limit_check_enable == 0) || (sigma_limitflag == 1)) { 03465 temp8 = 1; 03466 } else { 03467 temp8 = 0; 03468 } 03469 VL53L0X_SETARRAYPARAMETERFIELD(dev, LimitChecksStatus, 03470 VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE, temp8); 03471 03472 if ((device_range_status_internal == 4) || 03473 (signal_rate_final_range_limit_check_enable == 0)) { 03474 temp8 = 1; 03475 } else { 03476 temp8 = 0; 03477 } 03478 VL53L0X_SETARRAYPARAMETERFIELD(dev, LimitChecksStatus, 03479 VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE, 03480 temp8); 03481 03482 if ((signal_ref_clip_limit_check_enable == 0) || 03483 (signal_ref_clipflag == 1)) { 03484 temp8 = 1; 03485 } else { 03486 temp8 = 0; 03487 } 03488 03489 VL53L0X_SETARRAYPARAMETERFIELD(dev, LimitChecksStatus, 03490 VL53L0X_CHECKENABLE_SIGNAL_REF_CLIP, temp8); 03491 03492 if ((range_ignore_threshold_limit_check_enable == 0) || 03493 (range_ignore_thresholdflag == 1)) { 03494 temp8 = 1; 03495 } else { 03496 temp8 = 0; 03497 } 03498 03499 VL53L0X_SETARRAYPARAMETERFIELD(dev, LimitChecksStatus, 03500 VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD, 03501 temp8); 03502 } 03503 03504 LOG_FUNCTION_END(status); 03505 return status; 03506 03507 } 03508 03509 VL53L0X_Error VL53L0X::VL53L0X_get_ranging_measurement_data(VL53L0X_DEV dev, 03510 VL53L0X_RangingMeasurementData_t *p_ranging_measurement_data) 03511 { 03512 VL53L0X_Error status = VL53L0X_ERROR_NONE; 03513 uint8_t device_range_status; 03514 uint8_t range_fractional_enable; 03515 uint8_t pal_range_status; 03516 uint8_t x_talk_compensation_enable; 03517 uint16_t ambient_rate; 03518 FixPoint1616_t signal_rate; 03519 uint16_t x_talk_compensation_rate_mega_cps; 03520 uint16_t effective_spad_rtn_count; 03521 uint16_t tmpuint16; 03522 uint16_t xtalk_range_milli_meter; 03523 uint16_t linearity_corrective_gain; 03524 uint8_t localBuffer[12]; 03525 VL53L0X_RangingMeasurementData_t last_range_data_buffer; 03526 03527 LOG_FUNCTION_START(""); 03528 03529 /* 03530 * use multi read even if some registers are not useful, result will 03531 * be more efficient 03532 * start reading at 0x14 dec20 03533 * end reading at 0x21 dec33 total 14 bytes to read 03534 */ 03535 status = VL53L0X_read_multi(dev, 0x14, localBuffer, 12); 03536 03537 if (status == VL53L0X_ERROR_NONE) { 03538 03539 p_ranging_measurement_data->ZoneId = 0; /* Only one zone */ 03540 p_ranging_measurement_data->TimeStamp = 0; /* Not Implemented */ 03541 03542 tmpuint16 = VL53L0X_MAKEUINT16(localBuffer[11], localBuffer[10]); 03543 /* cut1.1 if SYSTEM__RANGE_CONFIG if 1 range is 2bits fractional 03544 *(format 11.2) else no fractional 03545 */ 03546 03547 p_ranging_measurement_data->MeasurementTimeUsec = 0; 03548 03549 signal_rate = VL53L0X_FIXPOINT97TOFIXPOINT1616( 03550 VL53L0X_MAKEUINT16(localBuffer[7], localBuffer[6])); 03551 /* peak_signal_count_rate_rtn_mcps */ 03552 p_ranging_measurement_data->SignalRateRtnMegaCps = signal_rate; 03553 03554 ambient_rate = VL53L0X_MAKEUINT16(localBuffer[9], localBuffer[8]); 03555 p_ranging_measurement_data->AmbientRateRtnMegaCps = 03556 VL53L0X_FIXPOINT97TOFIXPOINT1616(ambient_rate); 03557 03558 effective_spad_rtn_count = VL53L0X_MAKEUINT16(localBuffer[3], 03559 localBuffer[2]); 03560 /* EffectiveSpadRtnCount is 8.8 format */ 03561 p_ranging_measurement_data->EffectiveSpadRtnCount = 03562 effective_spad_rtn_count; 03563 03564 device_range_status = localBuffer[0]; 03565 03566 /* Get Linearity Corrective Gain */ 03567 linearity_corrective_gain = PALDevDataGet(dev, 03568 LinearityCorrectiveGain); 03569 03570 /* Get ranging configuration */ 03571 range_fractional_enable = PALDevDataGet(dev, 03572 RangeFractionalEnable); 03573 03574 if (linearity_corrective_gain != 1000) { 03575 03576 tmpuint16 = (uint16_t)((linearity_corrective_gain 03577 * tmpuint16 + 500) / 1000); 03578 03579 /* Implement Xtalk */ 03580 VL53L0X_GETPARAMETERFIELD(dev, 03581 XTalkCompensationRateMegaCps, 03582 x_talk_compensation_rate_mega_cps); 03583 VL53L0X_GETPARAMETERFIELD(dev, XTalkCompensationEnable, 03584 x_talk_compensation_enable); 03585 03586 if (x_talk_compensation_enable) { 03587 03588 if ((signal_rate 03589 - ((x_talk_compensation_rate_mega_cps 03590 * effective_spad_rtn_count) >> 8)) 03591 <= 0) { 03592 if (range_fractional_enable) { 03593 xtalk_range_milli_meter = 8888; 03594 } else { 03595 xtalk_range_milli_meter = 8888 << 2; 03596 } 03597 } else { 03598 xtalk_range_milli_meter = 03599 (tmpuint16 * signal_rate) 03600 / (signal_rate 03601 - ((x_talk_compensation_rate_mega_cps 03602 * effective_spad_rtn_count) 03603 >> 8)); 03604 } 03605 03606 tmpuint16 = xtalk_range_milli_meter; 03607 } 03608 03609 } 03610 03611 if (range_fractional_enable) { 03612 p_ranging_measurement_data->RangeMilliMeter = 03613 (uint16_t)((tmpuint16) >> 2); 03614 p_ranging_measurement_data->RangeFractionalPart = 03615 (uint8_t)((tmpuint16 & 0x03) << 6); 03616 } else { 03617 p_ranging_measurement_data->RangeMilliMeter = tmpuint16; 03618 p_ranging_measurement_data->RangeFractionalPart = 0; 03619 } 03620 03621 /* 03622 * For a standard definition of RangeStatus, this should 03623 * return 0 in case of good result after a ranging 03624 * The range status depends on the device so call a device 03625 * specific function to obtain the right Status. 03626 */ 03627 status |= VL53L0X_get_pal_range_status(dev, device_range_status, 03628 signal_rate, effective_spad_rtn_count, 03629 p_ranging_measurement_data, &pal_range_status); 03630 03631 if (status == VL53L0X_ERROR_NONE) { 03632 p_ranging_measurement_data->RangeStatus = pal_range_status; 03633 } 03634 03635 } 03636 03637 if (status == VL53L0X_ERROR_NONE) { 03638 /* Copy last read data into Dev buffer */ 03639 last_range_data_buffer = PALDevDataGet(dev, LastRangeMeasure); 03640 03641 last_range_data_buffer.RangeMilliMeter = 03642 p_ranging_measurement_data->RangeMilliMeter; 03643 last_range_data_buffer.RangeFractionalPart = 03644 p_ranging_measurement_data->RangeFractionalPart; 03645 last_range_data_buffer.RangeDMaxMilliMeter = 03646 p_ranging_measurement_data->RangeDMaxMilliMeter; 03647 last_range_data_buffer.MeasurementTimeUsec = 03648 p_ranging_measurement_data->MeasurementTimeUsec; 03649 last_range_data_buffer.SignalRateRtnMegaCps = 03650 p_ranging_measurement_data->SignalRateRtnMegaCps; 03651 last_range_data_buffer.AmbientRateRtnMegaCps = 03652 p_ranging_measurement_data->AmbientRateRtnMegaCps; 03653 last_range_data_buffer.EffectiveSpadRtnCount = 03654 p_ranging_measurement_data->EffectiveSpadRtnCount; 03655 last_range_data_buffer.RangeStatus = 03656 p_ranging_measurement_data->RangeStatus; 03657 03658 PALDevDataSet(dev, LastRangeMeasure, last_range_data_buffer); 03659 } 03660 03661 LOG_FUNCTION_END(status); 03662 return status; 03663 } 03664 03665 VL53L0X_Error VL53L0X::VL53L0X_perform_single_ranging_measurement(VL53L0X_DEV dev, 03666 VL53L0X_RangingMeasurementData_t *p_ranging_measurement_data) 03667 { 03668 VL53L0X_Error status = VL53L0X_ERROR_NONE; 03669 03670 LOG_FUNCTION_START(""); 03671 03672 /* This function will do a complete single ranging 03673 * Here we fix the mode! */ 03674 status = VL53L0X_set_device_mode(dev, VL53L0X_DEVICEMODE_SINGLE_RANGING); 03675 03676 if (status == VL53L0X_ERROR_NONE) { 03677 status = VL53L0X_perform_single_measurement(dev); 03678 } 03679 03680 if (status == VL53L0X_ERROR_NONE) { 03681 status = VL53L0X_get_ranging_measurement_data(dev, 03682 p_ranging_measurement_data); 03683 } 03684 03685 if (status == VL53L0X_ERROR_NONE) { 03686 status = VL53L0X_clear_interrupt_mask(dev, 0); 03687 } 03688 03689 LOG_FUNCTION_END(status); 03690 return status; 03691 } 03692 03693 VL53L0X_Error VL53L0X::perform_ref_signal_measurement(VL53L0X_DEV dev, 03694 uint16_t *p_ref_signal_rate) 03695 { 03696 VL53L0X_Error status = VL53L0X_ERROR_NONE; 03697 VL53L0X_RangingMeasurementData_t ranging_measurement_data; 03698 03699 uint8_t sequence_config = 0; 03700 03701 /* store the value of the sequence config, 03702 * this will be reset before the end of the function 03703 */ 03704 03705 sequence_config = PALDevDataGet(dev, SequenceConfig); 03706 03707 /* 03708 * This function performs a reference signal rate measurement. 03709 */ 03710 if (status == VL53L0X_ERROR_NONE) { 03711 status = VL53L0X_write_byte(dev, 03712 VL53L0X_REG_SYSTEM_SEQUENCE_CONFIG, 0xC0); 03713 } 03714 03715 if (status == VL53L0X_ERROR_NONE) { 03716 status = VL53L0X_perform_single_ranging_measurement(dev, 03717 &ranging_measurement_data); 03718 } 03719 03720 if (status == VL53L0X_ERROR_NONE) { 03721 status = VL53L0X_write_byte(dev, 0xFF, 0x01); 03722 } 03723 03724 if (status == VL53L0X_ERROR_NONE) { 03725 status = VL53L0X_read_word(dev, 03726 VL53L0X_REG_RESULT_PEAK_SIGNAL_RATE_REF, 03727 p_ref_signal_rate); 03728 } 03729 03730 if (status == VL53L0X_ERROR_NONE) { 03731 status = VL53L0X_write_byte(dev, 0xFF, 0x00); 03732 } 03733 03734 if (status == VL53L0X_ERROR_NONE) { 03735 /* restore the previous Sequence Config */ 03736 status = VL53L0X_write_byte(dev, VL53L0X_REG_SYSTEM_SEQUENCE_CONFIG, 03737 sequence_config); 03738 if (status == VL53L0X_ERROR_NONE) { 03739 PALDevDataSet(dev, SequenceConfig, sequence_config); 03740 } 03741 } 03742 03743 return status; 03744 } 03745 03746 VL53L0X_Error VL53L0X::wrapped_VL53L0X_perform_ref_spad_management(VL53L0X_DEV dev, 03747 uint32_t *ref_spad_count, 03748 uint8_t *is_aperture_spads) 03749 { 03750 VL53L0X_Error status = VL53L0X_ERROR_NONE; 03751 uint8_t last_spad_array[6]; 03752 uint8_t start_select = 0xB4; 03753 uint32_t minimum_spad_count = 3; 03754 uint32_t max_spad_count = 44; 03755 uint32_t current_spad_index = 0; 03756 uint32_t last_spad_index = 0; 03757 int32_t next_good_spad = 0; 03758 uint16_t target_ref_rate = 0x0A00; /* 20 MCPS in 9:7 format */ 03759 uint16_t peak_signal_rate_ref; 03760 uint32_t need_apt_spads = 0; 03761 uint32_t index = 0; 03762 uint32_t spad_array_size = 6; 03763 uint32_t signal_rate_diff = 0; 03764 uint32_t last_signal_rate_diff = 0; 03765 uint8_t complete = 0; 03766 uint8_t vhv_settings = 0; 03767 uint8_t phase_cal = 0; 03768 uint32_t ref_spad_count_int = 0; 03769 uint8_t is_aperture_spads_int = 0; 03770 03771 /* 03772 * The reference SPAD initialization procedure determines the minimum 03773 * amount of reference spads to be enables to achieve a target reference 03774 * signal rate and should be performed once during initialization. 03775 * 03776 * Either aperture or non-aperture spads are applied but never both. 03777 * Firstly non-aperture spads are set, begining with 5 spads, and 03778 * increased one spad at a time until the closest measurement to the 03779 * target rate is achieved. 03780 * 03781 * If the target rate is exceeded when 5 non-aperture spads are enabled, 03782 * initialization is performed instead with aperture spads. 03783 * 03784 * When setting spads, a 'Good Spad Map' is applied. 03785 * 03786 * This procedure operates within a SPAD window of interest of a maximum 03787 * 44 spads. 03788 * The start point is currently fixed to 180, which lies towards the end 03789 * of the non-aperture quadrant and runs in to the adjacent aperture 03790 * quadrant. 03791 */ 03792 target_ref_rate = PALDevDataGet(dev, targetRefRate); 03793 03794 /* 03795 * Initialize Spad arrays. 03796 * Currently the good spad map is initialised to 'All good'. 03797 * This is a short term implementation. The good spad map will be 03798 * provided as an input. 03799 * Note that there are 6 bytes. Only the first 44 bits will be used to 03800 * represent spads. 03801 */ 03802 for (index = 0; index < spad_array_size; index++) { 03803 dev->Data .SpadData .RefSpadEnables [index] = 0; 03804 } 03805 03806 03807 status = VL53L0X_write_byte(dev, 0xFF, 0x01); 03808 03809 if (status == VL53L0X_ERROR_NONE) { 03810 status = VL53L0X_write_byte(dev, 03811 VL53L0X_REG_DYNAMIC_SPAD_REF_EN_START_OFFSET, 0x00); 03812 } 03813 03814 if (status == VL53L0X_ERROR_NONE) { 03815 status = VL53L0X_write_byte(dev, 03816 VL53L0X_REG_DYNAMIC_SPAD_NUM_REQUESTED_REF_SPAD, 0x2C); 03817 } 03818 03819 if (status == VL53L0X_ERROR_NONE) { 03820 status = VL53L0X_write_byte(dev, 0xFF, 0x00); 03821 } 03822 03823 if (status == VL53L0X_ERROR_NONE) { 03824 status = VL53L0X_write_byte(dev, 03825 VL53L0X_REG_GLOBAL_CONFIG_REF_EN_START_SELECT, 03826 start_select); 03827 } 03828 03829 if (status == VL53L0X_ERROR_NONE) { 03830 status = VL53L0X_write_byte(dev, 03831 VL53L0X_REG_POWER_MANAGEMENT_GO1_POWER_FORCE, 0); 03832 } 03833 03834 /* Perform ref calibration */ 03835 if (status == VL53L0X_ERROR_NONE) { 03836 status = VL53L0X_perform_ref_calibration(dev, &vhv_settings, 03837 &phase_cal, 0); 03838 } 03839 03840 if (status == VL53L0X_ERROR_NONE) { 03841 /* Enable Minimum NON-APERTURE Spads */ 03842 current_spad_index = 0; 03843 last_spad_index = current_spad_index; 03844 need_apt_spads = 0; 03845 status = enable_ref_spads(dev, 03846 need_apt_spads, 03847 dev->Data .SpadData .RefGoodSpadMap , 03848 dev->Data .SpadData .RefSpadEnables , 03849 spad_array_size, 03850 start_select, 03851 current_spad_index, 03852 minimum_spad_count, 03853 &last_spad_index); 03854 } 03855 03856 if (status == VL53L0X_ERROR_NONE) { 03857 current_spad_index = last_spad_index; 03858 03859 status = perform_ref_signal_measurement(dev, 03860 &peak_signal_rate_ref); 03861 if ((status == VL53L0X_ERROR_NONE) && 03862 (peak_signal_rate_ref > target_ref_rate)) { 03863 /* Signal rate measurement too high, 03864 * switch to APERTURE SPADs */ 03865 03866 for (index = 0; index < spad_array_size; index++) { 03867 dev->Data .SpadData .RefSpadEnables [index] = 0; 03868 } 03869 03870 03871 /* Increment to the first APERTURE spad */ 03872 while ((is_aperture(start_select + current_spad_index) 03873 == 0) && (current_spad_index < max_spad_count)) { 03874 current_spad_index++; 03875 } 03876 03877 need_apt_spads = 1; 03878 03879 status = enable_ref_spads(dev, 03880 need_apt_spads, 03881 dev->Data .SpadData .RefGoodSpadMap , 03882 dev->Data .SpadData .RefSpadEnables , 03883 spad_array_size, 03884 start_select, 03885 current_spad_index, 03886 minimum_spad_count, 03887 &last_spad_index); 03888 03889 if (status == VL53L0X_ERROR_NONE) { 03890 current_spad_index = last_spad_index; 03891 status = perform_ref_signal_measurement(dev, 03892 &peak_signal_rate_ref); 03893 03894 if ((status == VL53L0X_ERROR_NONE) && 03895 (peak_signal_rate_ref > target_ref_rate)) { 03896 /* Signal rate still too high after 03897 * setting the minimum number of 03898 * APERTURE spads. Can do no more 03899 * therefore set the min number of 03900 * aperture spads as the result. 03901 */ 03902 is_aperture_spads_int = 1; 03903 ref_spad_count_int = minimum_spad_count; 03904 } 03905 } 03906 } else { 03907 need_apt_spads = 0; 03908 } 03909 } 03910 03911 if ((status == VL53L0X_ERROR_NONE) && 03912 (peak_signal_rate_ref < target_ref_rate)) { 03913 /* At this point, the minimum number of either aperture 03914 * or non-aperture spads have been set. Proceed to add 03915 * spads and perform measurements until the target 03916 * reference is reached. 03917 */ 03918 is_aperture_spads_int = need_apt_spads; 03919 ref_spad_count_int = minimum_spad_count; 03920 03921 memcpy(last_spad_array, dev->Data .SpadData .RefSpadEnables , 03922 spad_array_size); 03923 last_signal_rate_diff = abs(peak_signal_rate_ref - 03924 target_ref_rate); 03925 complete = 0; 03926 03927 while (!complete) { 03928 get_next_good_spad( 03929 dev->Data .SpadData .RefGoodSpadMap , 03930 spad_array_size, current_spad_index, 03931 &next_good_spad); 03932 03933 if (next_good_spad == -1) { 03934 status = VL53L0X_ERROR_REF_SPAD_INIT; 03935 break; 03936 } 03937 03938 /* Cannot combine Aperture and Non-Aperture spads, so 03939 * ensure the current spad is of the correct type. 03940 */ 03941 if (is_aperture((uint32_t)start_select + next_good_spad) != 03942 need_apt_spads) { 03943 /* At this point we have enabled the maximum 03944 * number of Aperture spads. 03945 */ 03946 complete = 1; 03947 break; 03948 } 03949 03950 (ref_spad_count_int)++; 03951 03952 current_spad_index = next_good_spad; 03953 status = enable_spad_bit( 03954 dev->Data .SpadData .RefSpadEnables , 03955 spad_array_size, current_spad_index); 03956 03957 if (status == VL53L0X_ERROR_NONE) { 03958 current_spad_index++; 03959 /* Proceed to apply the additional spad and 03960 * perform measurement. */ 03961 status = set_ref_spad_map(dev, 03962 dev->Data .SpadData .RefSpadEnables ); 03963 } 03964 03965 if (status != VL53L0X_ERROR_NONE) { 03966 break; 03967 } 03968 03969 status = perform_ref_signal_measurement(dev, 03970 &peak_signal_rate_ref); 03971 03972 if (status != VL53L0X_ERROR_NONE) { 03973 break; 03974 } 03975 03976 signal_rate_diff = abs(peak_signal_rate_ref - target_ref_rate); 03977 03978 if (peak_signal_rate_ref > target_ref_rate) { 03979 /* Select the spad map that provides the 03980 * measurement closest to the target rate, 03981 * either above or below it. 03982 */ 03983 if (signal_rate_diff > last_signal_rate_diff) { 03984 /* Previous spad map produced a closer 03985 * measurement, so choose this. */ 03986 status = set_ref_spad_map(dev, 03987 last_spad_array); 03988 memcpy( 03989 dev->Data .SpadData .RefSpadEnables , 03990 last_spad_array, spad_array_size); 03991 03992 (ref_spad_count_int)--; 03993 } 03994 complete = 1; 03995 } else { 03996 /* Continue to add spads */ 03997 last_signal_rate_diff = signal_rate_diff; 03998 memcpy(last_spad_array, 03999 dev->Data .SpadData .RefSpadEnables , 04000 spad_array_size); 04001 } 04002 04003 } /* while */ 04004 } 04005 04006 if (status == VL53L0X_ERROR_NONE) { 04007 *ref_spad_count = ref_spad_count_int; 04008 *is_aperture_spads = is_aperture_spads_int; 04009 04010 VL53L0X_SETDEVICESPECIFICPARAMETER(dev, RefSpadsInitialised, 1); 04011 VL53L0X_SETDEVICESPECIFICPARAMETER(dev, 04012 ReferenceSpadCount, (uint8_t)(*ref_spad_count)); 04013 VL53L0X_SETDEVICESPECIFICPARAMETER(dev, 04014 ReferenceSpadType, *is_aperture_spads); 04015 } 04016 04017 return status; 04018 } 04019 04020 VL53L0X_Error VL53L0X::VL53L0X_set_reference_spads(VL53L0X_DEV dev, 04021 uint32_t count, uint8_t is_aperture_spads) 04022 { 04023 VL53L0X_Error status = VL53L0X_ERROR_NONE; 04024 uint32_t current_spad_index = 0; 04025 uint8_t start_select = 0xB4; 04026 uint32_t spad_array_size = 6; 04027 uint32_t max_spad_count = 44; 04028 uint32_t last_spad_index; 04029 uint32_t index; 04030 04031 /* 04032 * This function applies a requested number of reference spads, either 04033 * aperture or 04034 * non-aperture, as requested. 04035 * The good spad map will be applied. 04036 */ 04037 04038 status = VL53L0X_write_byte(dev, 0xFF, 0x01); 04039 04040 if (status == VL53L0X_ERROR_NONE) { 04041 status = VL53L0X_write_byte(dev, 04042 VL53L0X_REG_DYNAMIC_SPAD_REF_EN_START_OFFSET, 0x00); 04043 } 04044 04045 if (status == VL53L0X_ERROR_NONE) { 04046 status = VL53L0X_write_byte(dev, 04047 VL53L0X_REG_DYNAMIC_SPAD_NUM_REQUESTED_REF_SPAD, 0x2C); 04048 } 04049 04050 if (status == VL53L0X_ERROR_NONE) { 04051 status = VL53L0X_write_byte(dev, 0xFF, 0x00); 04052 } 04053 04054 if (status == VL53L0X_ERROR_NONE) { 04055 status = VL53L0X_write_byte(dev, 04056 VL53L0X_REG_GLOBAL_CONFIG_REF_EN_START_SELECT, 04057 start_select); 04058 } 04059 04060 for (index = 0; index < spad_array_size; index++) { 04061 dev->Data .SpadData .RefSpadEnables [index] = 0; 04062 } 04063 04064 if (is_aperture_spads) { 04065 /* Increment to the first APERTURE spad */ 04066 while ((is_aperture(start_select + current_spad_index) == 0) && 04067 (current_spad_index < max_spad_count)) { 04068 current_spad_index++; 04069 } 04070 } 04071 status = enable_ref_spads(dev, 04072 is_aperture_spads, 04073 dev->Data .SpadData .RefGoodSpadMap , 04074 dev->Data .SpadData .RefSpadEnables , 04075 spad_array_size, 04076 start_select, 04077 current_spad_index, 04078 count, 04079 &last_spad_index); 04080 04081 if (status == VL53L0X_ERROR_NONE) { 04082 VL53L0X_SETDEVICESPECIFICPARAMETER(dev, RefSpadsInitialised, 1); 04083 VL53L0X_SETDEVICESPECIFICPARAMETER(dev, 04084 ReferenceSpadCount, (uint8_t)(count)); 04085 VL53L0X_SETDEVICESPECIFICPARAMETER(dev, 04086 ReferenceSpadType, is_aperture_spads); 04087 } 04088 04089 return status; 04090 } 04091 04092 VL53L0X_Error VL53L0X::VL53L0X_wait_device_booted(VL53L0X_DEV dev) 04093 { 04094 VL53L0X_Error status = VL53L0X_ERROR_NOT_IMPLEMENTED; 04095 LOG_FUNCTION_START(""); 04096 04097 /* not implemented on VL53L0X */ 04098 04099 LOG_FUNCTION_END(status); 04100 return status; 04101 } 04102 04103 VL53L0X_Error VL53L0X::VL53L0X_perform_ref_calibration(VL53L0X_DEV dev, uint8_t *p_vhv_settings, 04104 uint8_t *p_phase_cal) 04105 { 04106 VL53L0X_Error status = VL53L0X_ERROR_NONE; 04107 LOG_FUNCTION_START(""); 04108 04109 status = VL53L0X_perform_ref_calibration(dev, p_vhv_settings, 04110 p_phase_cal, 1); 04111 04112 LOG_FUNCTION_END(status); 04113 return status; 04114 } 04115 04116 VL53L0X_Error VL53L0X::VL53L0X_perform_ref_spad_management(VL53L0X_DEV dev, 04117 uint32_t *ref_spad_count, uint8_t *is_aperture_spads) 04118 { 04119 VL53L0X_Error status = VL53L0X_ERROR_NONE; 04120 LOG_FUNCTION_START(""); 04121 04122 status = wrapped_VL53L0X_perform_ref_spad_management(dev, ref_spad_count, 04123 is_aperture_spads); 04124 04125 LOG_FUNCTION_END(status); 04126 04127 return status; 04128 } 04129 04130 /* Group PAL Init Functions */ 04131 VL53L0X_Error VL53L0X::VL53L0X_set_device_address(VL53L0X_DEV dev, uint8_t device_address) 04132 { 04133 VL53L0X_Error status = VL53L0X_ERROR_NONE; 04134 LOG_FUNCTION_START(""); 04135 04136 status = VL53L0X_write_byte(dev, VL53L0X_REG_I2C_SLAVE_DEVICE_ADDRESS, 04137 device_address / 2); 04138 04139 LOG_FUNCTION_END(status); 04140 return status; 04141 } 04142 04143 VL53L0X_Error VL53L0X::VL53L0X_set_gpio_config(VL53L0X_DEV dev, uint8_t pin, 04144 VL53L0X_DeviceModes device_mode, VL53L0X_GpioFunctionality functionality, 04145 VL53L0X_InterruptPolarity polarity) 04146 { 04147 VL53L0X_Error status = VL53L0X_ERROR_NONE; 04148 uint8_t data; 04149 04150 LOG_FUNCTION_START(""); 04151 04152 if (pin != 0) { 04153 status = VL53L0X_ERROR_GPIO_NOT_EXISTING; 04154 } else if (device_mode == VL53L0X_DEVICEMODE_GPIO_DRIVE) { 04155 if (polarity == VL53L0X_INTERRUPTPOLARITY_LOW) { 04156 data = 0x10; 04157 } else { 04158 data = 1; 04159 } 04160 04161 status = VL53L0X_write_byte(dev, 04162 VL53L0X_REG_GPIO_HV_MUX_ACTIVE_HIGH, data); 04163 04164 } else { 04165 if (device_mode == VL53L0X_DEVICEMODE_GPIO_OSC) { 04166 04167 status |= VL53L0X_write_byte(dev, 0xff, 0x01); 04168 status |= VL53L0X_write_byte(dev, 0x00, 0x00); 04169 04170 status |= VL53L0X_write_byte(dev, 0xff, 0x00); 04171 status |= VL53L0X_write_byte(dev, 0x80, 0x01); 04172 status |= VL53L0X_write_byte(dev, 0x85, 0x02); 04173 04174 status |= VL53L0X_write_byte(dev, 0xff, 0x04); 04175 status |= VL53L0X_write_byte(dev, 0xcd, 0x00); 04176 status |= VL53L0X_write_byte(dev, 0xcc, 0x11); 04177 04178 status |= VL53L0X_write_byte(dev, 0xff, 0x07); 04179 status |= VL53L0X_write_byte(dev, 0xbe, 0x00); 04180 04181 status |= VL53L0X_write_byte(dev, 0xff, 0x06); 04182 status |= VL53L0X_write_byte(dev, 0xcc, 0x09); 04183 04184 status |= VL53L0X_write_byte(dev, 0xff, 0x00); 04185 status |= VL53L0X_write_byte(dev, 0xff, 0x01); 04186 status |= VL53L0X_write_byte(dev, 0x00, 0x00); 04187 04188 } else { 04189 04190 if (status == VL53L0X_ERROR_NONE) { 04191 switch (functionality) { 04192 case VL53L0X_GPIOFUNCTIONALITY_OFF: 04193 data = 0x00; 04194 break; 04195 case VL53L0X_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_LOW: 04196 data = 0x01; 04197 break; 04198 case VL53L0X_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_HIGH: 04199 data = 0x02; 04200 break; 04201 case VL53L0X_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_OUT: 04202 data = 0x03; 04203 break; 04204 case VL53L0X_GPIOFUNCTIONALITY_NEW_MEASURE_READY: 04205 data = 0x04; 04206 break; 04207 default: 04208 status = 04209 VL53L0X_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED; 04210 } 04211 } 04212 04213 if (status == VL53L0X_ERROR_NONE) { 04214 status = VL53L0X_write_byte(dev, 04215 VL53L0X_REG_SYSTEM_INTERRUPT_CONFIG_GPIO, data); 04216 } 04217 04218 if (status == VL53L0X_ERROR_NONE) { 04219 if (polarity == VL53L0X_INTERRUPTPOLARITY_LOW) { 04220 data = 0; 04221 } else { 04222 data = (uint8_t)(1 << 4); 04223 } 04224 status = VL53L0X_update_byte(dev, 04225 VL53L0X_REG_GPIO_HV_MUX_ACTIVE_HIGH, 0xEF, data); 04226 } 04227 04228 if (status == VL53L0X_ERROR_NONE) { 04229 VL53L0X_SETDEVICESPECIFICPARAMETER(dev, 04230 Pin0GpioFunctionality, functionality); 04231 } 04232 04233 if (status == VL53L0X_ERROR_NONE) { 04234 status = VL53L0X_clear_interrupt_mask(dev, 0); 04235 } 04236 } 04237 } 04238 LOG_FUNCTION_END(status); 04239 return status; 04240 } 04241 04242 VL53L0X_Error VL53L0X::VL53L0X_get_fraction_enable(VL53L0X_DEV dev, uint8_t *p_enabled) 04243 { 04244 VL53L0X_Error status = VL53L0X_ERROR_NONE; 04245 LOG_FUNCTION_START(""); 04246 04247 status = VL53L0X_read_byte(dev, VL53L0X_REG_SYSTEM_RANGE_CONFIG, p_enabled); 04248 04249 if (status == VL53L0X_ERROR_NONE) { 04250 *p_enabled = (*p_enabled & 1); 04251 } 04252 04253 LOG_FUNCTION_END(status); 04254 return status; 04255 } 04256 04257 uint16_t VL53L0X::VL53L0X_encode_timeout (uint32_t timeout_macro_clks) 04258 { 04259 /*! 04260 * Encode timeout in macro periods in (LSByte * 2^MSByte) + 1 format 04261 */ 04262 04263 uint16_t encoded_timeout = 0; 04264 uint32_t ls_byte = 0; 04265 uint16_t ms_byte = 0; 04266 04267 if (timeout_macro_clks > 0) { 04268 ls_byte = timeout_macro_clks - 1; 04269 04270 while ((ls_byte & 0xFFFFFF00) > 0) { 04271 ls_byte = ls_byte >> 1; 04272 ms_byte++; 04273 } 04274 04275 encoded_timeout = (ms_byte << 8) 04276 + (uint16_t)(ls_byte & 0x000000FF); 04277 } 04278 04279 return encoded_timeout; 04280 04281 } 04282 04283 VL53L0X_Error VL53L0X::set_sequence_step_timeout(VL53L0X_DEV dev, 04284 VL53L0X_SequenceStepId sequence_step_id, 04285 uint32_t timeout_micro_secs) 04286 { 04287 VL53L0X_Error status = VL53L0X_ERROR_NONE; 04288 uint8_t current_vcsel_pulse_period_p_clk; 04289 uint8_t msrc_encoded_time_out; 04290 uint16_t pre_range_encoded_time_out; 04291 uint16_t pre_range_time_out_m_clks; 04292 uint16_t msrc_range_time_out_m_clks; 04293 uint32_t final_range_time_out_m_clks; 04294 uint16_t final_range_encoded_time_out; 04295 VL53L0X_SchedulerSequenceSteps_t scheduler_sequence_steps; 04296 04297 if ((sequence_step_id == VL53L0X_SEQUENCESTEP_TCC) || 04298 (sequence_step_id == VL53L0X_SEQUENCESTEP_DSS) || 04299 (sequence_step_id == VL53L0X_SEQUENCESTEP_MSRC)) { 04300 04301 status = VL53L0X_get_vcsel_pulse_period(dev, 04302 VL53L0X_VCSEL_PERIOD_PRE_RANGE, 04303 ¤t_vcsel_pulse_period_p_clk); 04304 04305 if (status == VL53L0X_ERROR_NONE) { 04306 msrc_range_time_out_m_clks = VL53L0X_calc_timeout_mclks(dev, 04307 timeout_micro_secs, 04308 (uint8_t)current_vcsel_pulse_period_p_clk); 04309 04310 if (msrc_range_time_out_m_clks > 256) { 04311 msrc_encoded_time_out = 255; 04312 } else { 04313 msrc_encoded_time_out = 04314 (uint8_t)msrc_range_time_out_m_clks - 1; 04315 } 04316 04317 VL53L0X_SETDEVICESPECIFICPARAMETER(dev, 04318 LastEncodedTimeout, 04319 msrc_encoded_time_out); 04320 } 04321 04322 if (status == VL53L0X_ERROR_NONE) { 04323 status = VL53L0X_write_byte(dev, 04324 VL53L0X_REG_MSRC_CONFIG_TIMEOUT_MACROP, 04325 msrc_encoded_time_out); 04326 } 04327 } else { 04328 04329 if (sequence_step_id == VL53L0X_SEQUENCESTEP_PRE_RANGE) { 04330 04331 if (status == VL53L0X_ERROR_NONE) { 04332 status = VL53L0X_get_vcsel_pulse_period(dev, 04333 VL53L0X_VCSEL_PERIOD_PRE_RANGE, 04334 ¤t_vcsel_pulse_period_p_clk); 04335 pre_range_time_out_m_clks = 04336 VL53L0X_calc_timeout_mclks(dev, 04337 timeout_micro_secs, 04338 (uint8_t)current_vcsel_pulse_period_p_clk); 04339 pre_range_encoded_time_out = VL53L0X_encode_timeout ( 04340 pre_range_time_out_m_clks); 04341 04342 VL53L0X_SETDEVICESPECIFICPARAMETER(dev, 04343 LastEncodedTimeout, 04344 pre_range_encoded_time_out); 04345 } 04346 04347 if (status == VL53L0X_ERROR_NONE) { 04348 status = VL53L0X_write_word(dev, 04349 VL53L0X_REG_PRE_RANGE_CONFIG_TIMEOUT_MACROP_HI, 04350 pre_range_encoded_time_out); 04351 } 04352 04353 if (status == VL53L0X_ERROR_NONE) { 04354 VL53L0X_SETDEVICESPECIFICPARAMETER( 04355 dev, 04356 PreRangeTimeoutMicroSecs, 04357 timeout_micro_secs); 04358 } 04359 } else if (sequence_step_id == VL53L0X_SEQUENCESTEP_FINAL_RANGE) { 04360 04361 /* For the final range timeout, the pre-range timeout 04362 * must be added. To do this both final and pre-range 04363 * timeouts must be expressed in macro periods MClks 04364 * because they have different vcsel periods. 04365 */ 04366 04367 VL53L0X_get_sequence_step_enables(dev, 04368 &scheduler_sequence_steps); 04369 pre_range_time_out_m_clks = 0; 04370 if (scheduler_sequence_steps.PreRangeOn) { 04371 04372 /* Retrieve PRE-RANGE VCSEL Period */ 04373 status = VL53L0X_get_vcsel_pulse_period(dev, 04374 VL53L0X_VCSEL_PERIOD_PRE_RANGE, 04375 ¤t_vcsel_pulse_period_p_clk); 04376 04377 /* Retrieve PRE-RANGE Timeout in Macro periods 04378 * (MCLKS) */ 04379 if (status == VL53L0X_ERROR_NONE) { 04380 status = VL53L0X_read_word(dev, 0x51, 04381 &pre_range_encoded_time_out); 04382 pre_range_time_out_m_clks = 04383 VL53L0X_decode_timeout( 04384 pre_range_encoded_time_out); 04385 } 04386 } 04387 04388 /* Calculate FINAL RANGE Timeout in Macro Periods 04389 * (MCLKS) and add PRE-RANGE value 04390 */ 04391 if (status == VL53L0X_ERROR_NONE) { 04392 status = VL53L0X_get_vcsel_pulse_period(dev, 04393 VL53L0X_VCSEL_PERIOD_FINAL_RANGE, 04394 ¤t_vcsel_pulse_period_p_clk); 04395 } 04396 if (status == VL53L0X_ERROR_NONE) { 04397 final_range_time_out_m_clks = 04398 VL53L0X_calc_timeout_mclks(dev, 04399 timeout_micro_secs, 04400 (uint8_t) current_vcsel_pulse_period_p_clk); 04401 04402 final_range_time_out_m_clks += pre_range_time_out_m_clks; 04403 04404 final_range_encoded_time_out = 04405 VL53L0X_encode_timeout (final_range_time_out_m_clks); 04406 04407 if (status == VL53L0X_ERROR_NONE) { 04408 status = VL53L0X_write_word(dev, 0x71, 04409 final_range_encoded_time_out); 04410 } 04411 04412 if (status == VL53L0X_ERROR_NONE) { 04413 VL53L0X_SETDEVICESPECIFICPARAMETER( 04414 dev, 04415 FinalRangeTimeoutMicroSecs, 04416 timeout_micro_secs); 04417 } 04418 } 04419 } else { 04420 status = VL53L0X_ERROR_INVALID_PARAMS; 04421 } 04422 04423 } 04424 return status; 04425 } 04426 04427 VL53L0X_Error VL53L0X::wrapped_VL53L0X_set_measurement_timing_budget_micro_seconds(VL53L0X_DEV dev, 04428 uint32_t measurement_timing_budget_micro_seconds) 04429 { 04430 VL53L0X_Error status = VL53L0X_ERROR_NONE; 04431 uint32_t final_range_timing_budget_micro_seconds; 04432 VL53L0X_SchedulerSequenceSteps_t scheduler_sequence_steps; 04433 uint32_t msrc_dcc_tcc_timeout_micro_seconds = 2000; 04434 uint32_t start_overhead_micro_seconds = 1910; 04435 uint32_t end_overhead_micro_seconds = 960; 04436 uint32_t msrc_overhead_micro_seconds = 660; 04437 uint32_t tcc_overhead_micro_seconds = 590; 04438 uint32_t dss_overhead_micro_seconds = 690; 04439 uint32_t pre_range_overhead_micro_seconds = 660; 04440 uint32_t final_range_overhead_micro_seconds = 550; 04441 uint32_t pre_range_timeout_micro_seconds = 0; 04442 uint32_t c_min_timing_budget_micro_seconds = 20000; 04443 uint32_t sub_timeout = 0; 04444 04445 LOG_FUNCTION_START(""); 04446 04447 if (measurement_timing_budget_micro_seconds 04448 < c_min_timing_budget_micro_seconds) { 04449 status = VL53L0X_ERROR_INVALID_PARAMS; 04450 return status; 04451 } 04452 04453 final_range_timing_budget_micro_seconds = 04454 measurement_timing_budget_micro_seconds - 04455 (start_overhead_micro_seconds + end_overhead_micro_seconds); 04456 04457 status = VL53L0X_get_sequence_step_enables(dev, &scheduler_sequence_steps); 04458 04459 if (status == VL53L0X_ERROR_NONE && 04460 (scheduler_sequence_steps.TccOn || 04461 scheduler_sequence_steps.MsrcOn || 04462 scheduler_sequence_steps.DssOn)) { 04463 04464 /* TCC, MSRC and DSS all share the same timeout */ 04465 status = get_sequence_step_timeout(dev, 04466 VL53L0X_SEQUENCESTEP_MSRC, 04467 &msrc_dcc_tcc_timeout_micro_seconds); 04468 04469 /* Subtract the TCC, MSRC and DSS timeouts if they are 04470 * enabled. */ 04471 04472 if (status != VL53L0X_ERROR_NONE) { 04473 return status; 04474 } 04475 04476 /* TCC */ 04477 if (scheduler_sequence_steps.TccOn) { 04478 04479 sub_timeout = msrc_dcc_tcc_timeout_micro_seconds 04480 + tcc_overhead_micro_seconds; 04481 04482 if (sub_timeout < 04483 final_range_timing_budget_micro_seconds) { 04484 final_range_timing_budget_micro_seconds -= 04485 sub_timeout; 04486 } else { 04487 /* Requested timeout too big. */ 04488 status = VL53L0X_ERROR_INVALID_PARAMS; 04489 } 04490 } 04491 04492 if (status != VL53L0X_ERROR_NONE) { 04493 LOG_FUNCTION_END(status); 04494 return status; 04495 } 04496 04497 /* DSS */ 04498 if (scheduler_sequence_steps.DssOn) { 04499 04500 sub_timeout = 2 * (msrc_dcc_tcc_timeout_micro_seconds + 04501 dss_overhead_micro_seconds); 04502 04503 if (sub_timeout < final_range_timing_budget_micro_seconds) { 04504 final_range_timing_budget_micro_seconds 04505 -= sub_timeout; 04506 } else { 04507 /* Requested timeout too big. */ 04508 status = VL53L0X_ERROR_INVALID_PARAMS; 04509 } 04510 } else if (scheduler_sequence_steps.MsrcOn) { 04511 /* MSRC */ 04512 sub_timeout = msrc_dcc_tcc_timeout_micro_seconds + 04513 msrc_overhead_micro_seconds; 04514 04515 if (sub_timeout < final_range_timing_budget_micro_seconds) { 04516 final_range_timing_budget_micro_seconds 04517 -= sub_timeout; 04518 } else { 04519 /* Requested timeout too big. */ 04520 status = VL53L0X_ERROR_INVALID_PARAMS; 04521 } 04522 } 04523 04524 } 04525 04526 if (status != VL53L0X_ERROR_NONE) { 04527 LOG_FUNCTION_END(status); 04528 return status; 04529 } 04530 04531 if (scheduler_sequence_steps.PreRangeOn) { 04532 04533 /* Subtract the Pre-range timeout if enabled. */ 04534 04535 status = get_sequence_step_timeout(dev, 04536 VL53L0X_SEQUENCESTEP_PRE_RANGE, 04537 &pre_range_timeout_micro_seconds); 04538 04539 sub_timeout = pre_range_timeout_micro_seconds + 04540 pre_range_overhead_micro_seconds; 04541 04542 if (sub_timeout < final_range_timing_budget_micro_seconds) { 04543 final_range_timing_budget_micro_seconds -= sub_timeout; 04544 } else { 04545 /* Requested timeout too big. */ 04546 status = VL53L0X_ERROR_INVALID_PARAMS; 04547 } 04548 } 04549 04550 04551 if (status == VL53L0X_ERROR_NONE && 04552 scheduler_sequence_steps.FinalRangeOn) { 04553 04554 final_range_timing_budget_micro_seconds -= 04555 final_range_overhead_micro_seconds; 04556 04557 /* Final Range Timeout 04558 * Note that the final range timeout is determined by the timing 04559 * budget and the sum of all other timeouts within the sequence. 04560 * If there is no room for the final range timeout, then an error 04561 * will be set. Otherwise the remaining time will be applied to 04562 * the final range. 04563 */ 04564 status = set_sequence_step_timeout(dev, 04565 VL53L0X_SEQUENCESTEP_FINAL_RANGE, 04566 final_range_timing_budget_micro_seconds); 04567 04568 VL53L0X_SETPARAMETERFIELD(dev, 04569 MeasurementTimingBudgetMicroSeconds, 04570 measurement_timing_budget_micro_seconds); 04571 } 04572 04573 LOG_FUNCTION_END(status); 04574 04575 return status; 04576 } 04577 04578 VL53L0X_Error VL53L0X::VL53L0X_set_measurement_timing_budget_micro_seconds(VL53L0X_DEV dev, 04579 uint32_t measurement_timing_budget_micro_seconds) 04580 { 04581 VL53L0X_Error status = VL53L0X_ERROR_NONE; 04582 LOG_FUNCTION_START(""); 04583 04584 status = wrapped_VL53L0X_set_measurement_timing_budget_micro_seconds(dev, 04585 measurement_timing_budget_micro_seconds); 04586 04587 LOG_FUNCTION_END(status); 04588 04589 return status; 04590 } 04591 04592 VL53L0X_Error VL53L0X::VL53L0X_set_sequence_step_enable(VL53L0X_DEV dev, 04593 VL53L0X_SequenceStepId sequence_step_id, uint8_t sequence_step_enabled) 04594 { 04595 VL53L0X_Error status = VL53L0X_ERROR_NONE; 04596 uint8_t sequence_config = 0; 04597 uint8_t sequence_config_new = 0; 04598 uint32_t measurement_timing_budget_micro_seconds; 04599 LOG_FUNCTION_START(""); 04600 04601 status = VL53L0X_read_byte(dev, VL53L0X_REG_SYSTEM_SEQUENCE_CONFIG, 04602 &sequence_config); 04603 04604 sequence_config_new = sequence_config; 04605 04606 if (status == VL53L0X_ERROR_NONE) { 04607 if (sequence_step_enabled == 1) { 04608 04609 /* Enable requested sequence step 04610 */ 04611 switch (sequence_step_id) { 04612 case VL53L0X_SEQUENCESTEP_TCC: 04613 sequence_config_new |= 0x10; 04614 break; 04615 case VL53L0X_SEQUENCESTEP_DSS: 04616 sequence_config_new |= 0x28; 04617 break; 04618 case VL53L0X_SEQUENCESTEP_MSRC: 04619 sequence_config_new |= 0x04; 04620 break; 04621 case VL53L0X_SEQUENCESTEP_PRE_RANGE: 04622 sequence_config_new |= 0x40; 04623 break; 04624 case VL53L0X_SEQUENCESTEP_FINAL_RANGE: 04625 sequence_config_new |= 0x80; 04626 break; 04627 default: 04628 status = VL53L0X_ERROR_INVALID_PARAMS; 04629 } 04630 } else { 04631 /* Disable requested sequence step 04632 */ 04633 switch (sequence_step_id) { 04634 case VL53L0X_SEQUENCESTEP_TCC: 04635 sequence_config_new &= 0xef; 04636 break; 04637 case VL53L0X_SEQUENCESTEP_DSS: 04638 sequence_config_new &= 0xd7; 04639 break; 04640 case VL53L0X_SEQUENCESTEP_MSRC: 04641 sequence_config_new &= 0xfb; 04642 break; 04643 case VL53L0X_SEQUENCESTEP_PRE_RANGE: 04644 sequence_config_new &= 0xbf; 04645 break; 04646 case VL53L0X_SEQUENCESTEP_FINAL_RANGE: 04647 sequence_config_new &= 0x7f; 04648 break; 04649 default: 04650 status = VL53L0X_ERROR_INVALID_PARAMS; 04651 } 04652 } 04653 } 04654 04655 if (sequence_config_new != sequence_config) { 04656 /* Apply New Setting */ 04657 if (status == VL53L0X_ERROR_NONE) { 04658 status = VL53L0X_write_byte(dev, 04659 VL53L0X_REG_SYSTEM_SEQUENCE_CONFIG, sequence_config_new); 04660 } 04661 if (status == VL53L0X_ERROR_NONE) { 04662 PALDevDataSet(dev, SequenceConfig, sequence_config_new); 04663 } 04664 04665 04666 /* Recalculate timing budget */ 04667 if (status == VL53L0X_ERROR_NONE) { 04668 VL53L0X_GETPARAMETERFIELD(dev, 04669 MeasurementTimingBudgetMicroSeconds, 04670 measurement_timing_budget_micro_seconds); 04671 04672 VL53L0X_set_measurement_timing_budget_micro_seconds(dev, 04673 measurement_timing_budget_micro_seconds); 04674 } 04675 } 04676 04677 LOG_FUNCTION_END(status); 04678 04679 return status; 04680 } 04681 04682 VL53L0X_Error VL53L0X::VL53L0X_set_limit_check_enable(VL53L0X_DEV dev, uint16_t limit_check_id, 04683 uint8_t limit_check_enable) 04684 { 04685 VL53L0X_Error status = VL53L0X_ERROR_NONE; 04686 FixPoint1616_t temp_fix1616 = 0; 04687 uint8_t limit_check_enable_int = 0; 04688 uint8_t limit_check_disable = 0; 04689 uint8_t temp8; 04690 04691 LOG_FUNCTION_START(""); 04692 04693 if (limit_check_id >= VL53L0X_CHECKENABLE_NUMBER_OF_CHECKS) { 04694 status = VL53L0X_ERROR_INVALID_PARAMS; 04695 } else { 04696 if (limit_check_enable == 0) { 04697 temp_fix1616 = 0; 04698 limit_check_enable_int = 0; 04699 limit_check_disable = 1; 04700 04701 } else { 04702 VL53L0X_GETARRAYPARAMETERFIELD(dev, LimitChecksValue, 04703 limit_check_id, temp_fix1616); 04704 limit_check_disable = 0; 04705 /* this to be sure to have either 0 or 1 */ 04706 limit_check_enable_int = 1; 04707 } 04708 04709 switch (limit_check_id) { 04710 04711 case VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE: 04712 /* internal computation: */ 04713 VL53L0X_SETARRAYPARAMETERFIELD(dev, LimitChecksEnable, 04714 VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE, 04715 limit_check_enable_int); 04716 04717 break; 04718 04719 case VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE: 04720 04721 status = VL53L0X_write_word(dev, 04722 VL53L0X_REG_FINAL_RANGE_CONFIG_MIN_COUNT_RATE_RTN_LIMIT, 04723 VL53L0X_FIXPOINT1616TOFIXPOINT97(temp_fix1616)); 04724 04725 break; 04726 04727 case VL53L0X_CHECKENABLE_SIGNAL_REF_CLIP: 04728 04729 /* internal computation: */ 04730 VL53L0X_SETARRAYPARAMETERFIELD(dev, LimitChecksEnable, 04731 VL53L0X_CHECKENABLE_SIGNAL_REF_CLIP, 04732 limit_check_enable_int); 04733 04734 break; 04735 04736 case VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD: 04737 04738 /* internal computation: */ 04739 VL53L0X_SETARRAYPARAMETERFIELD(dev, LimitChecksEnable, 04740 VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD, 04741 limit_check_enable_int); 04742 04743 break; 04744 04745 case VL53L0X_CHECKENABLE_SIGNAL_RATE_MSRC: 04746 04747 temp8 = (uint8_t)(limit_check_disable << 1); 04748 status = VL53L0X_update_byte(dev, 04749 VL53L0X_REG_MSRC_CONFIG_CONTROL, 04750 0xFE, temp8); 04751 04752 break; 04753 04754 case VL53L0X_CHECKENABLE_SIGNAL_RATE_PRE_RANGE: 04755 04756 temp8 = (uint8_t)(limit_check_disable << 4); 04757 status = VL53L0X_update_byte(dev, 04758 VL53L0X_REG_MSRC_CONFIG_CONTROL, 04759 0xEF, temp8); 04760 04761 break; 04762 04763 04764 default: 04765 status = VL53L0X_ERROR_INVALID_PARAMS; 04766 04767 } 04768 04769 } 04770 04771 if (status == VL53L0X_ERROR_NONE) { 04772 if (limit_check_enable == 0) { 04773 VL53L0X_SETARRAYPARAMETERFIELD(dev, LimitChecksEnable, 04774 limit_check_id, 0); 04775 } else { 04776 VL53L0X_SETARRAYPARAMETERFIELD(dev, LimitChecksEnable, 04777 limit_check_id, 1); 04778 } 04779 } 04780 04781 LOG_FUNCTION_END(status); 04782 return status; 04783 } 04784 04785 VL53L0X_Error VL53L0X::VL53L0X_static_init(VL53L0X_DEV dev) 04786 { 04787 VL53L0X_Error status = VL53L0X_ERROR_NONE; 04788 VL53L0X_DeviceParameters_t current_parameters = {0}; 04789 uint8_t *p_tuning_setting_buffer; 04790 uint16_t tempword = 0; 04791 uint8_t tempbyte = 0; 04792 uint8_t use_internal_tuning_settings = 0; 04793 uint32_t count = 0; 04794 uint8_t is_aperture_spads = 0; 04795 uint32_t ref_spad_count = 0; 04796 uint8_t aperture_spads = 0; 04797 uint8_t vcsel_pulse_period_pclk; 04798 uint32_t seq_timeout_micro_secs; 04799 04800 LOG_FUNCTION_START(""); 04801 04802 status = VL53L0X_get_info_from_device(dev, 1); 04803 04804 /* set the ref spad from NVM */ 04805 count = (uint32_t)VL53L0X_GETDEVICESPECIFICPARAMETER(dev, 04806 ReferenceSpadCount); 04807 aperture_spads = VL53L0X_GETDEVICESPECIFICPARAMETER(dev, 04808 ReferenceSpadType); 04809 04810 /* NVM value invalid */ 04811 if ((aperture_spads > 1) || 04812 ((aperture_spads == 1) && (count > 32)) || 04813 ((aperture_spads == 0) && (count > 12))) { 04814 status = wrapped_VL53L0X_perform_ref_spad_management(dev, &ref_spad_count, 04815 &is_aperture_spads); 04816 } else { 04817 status = VL53L0X_set_reference_spads(dev, count, aperture_spads); 04818 } 04819 04820 04821 /* Initialize tuning settings buffer to prevent compiler warning. */ 04822 p_tuning_setting_buffer = DefaultTuningSettings; 04823 04824 if (status == VL53L0X_ERROR_NONE) { 04825 use_internal_tuning_settings = PALDevDataGet(dev, 04826 UseInternalTuningSettings); 04827 04828 if (use_internal_tuning_settings == 0) { 04829 p_tuning_setting_buffer = PALDevDataGet(dev, 04830 pTuningSettingsPointer); 04831 } else { 04832 p_tuning_setting_buffer = DefaultTuningSettings; 04833 } 04834 04835 } 04836 04837 if (status == VL53L0X_ERROR_NONE) { 04838 status = VL53L0X_load_tuning_settings(dev, p_tuning_setting_buffer); 04839 } 04840 04841 04842 /* Set interrupt config to new sample ready */ 04843 if (status == VL53L0X_ERROR_NONE) { 04844 status = VL53L0X_set_gpio_config(dev, 0, 0, 04845 VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY, 04846 VL53L0X_INTERRUPTPOLARITY_LOW); 04847 } 04848 04849 if (status == VL53L0X_ERROR_NONE) { 04850 status = VL53L0X_write_byte(dev, 0xFF, 0x01); 04851 status |= VL53L0X_read_word(dev, 0x84, &tempword); 04852 status |= VL53L0X_write_byte(dev, 0xFF, 0x00); 04853 } 04854 04855 if (status == VL53L0X_ERROR_NONE) { 04856 VL53L0X_SETDEVICESPECIFICPARAMETER(dev, OscFrequencyMHz, 04857 VL53L0X_FIXPOINT412TOFIXPOINT1616(tempword)); 04858 } 04859 04860 /* After static init, some device parameters may be changed, 04861 * so update them */ 04862 if (status == VL53L0X_ERROR_NONE) { 04863 status = VL53L0X_get_device_parameters(dev, ¤t_parameters); 04864 } 04865 04866 04867 if (status == VL53L0X_ERROR_NONE) { 04868 status = VL53L0X_get_fraction_enable(dev, &tempbyte); 04869 if (status == VL53L0X_ERROR_NONE) { 04870 PALDevDataSet(dev, RangeFractionalEnable, tempbyte); 04871 } 04872 04873 } 04874 04875 if (status == VL53L0X_ERROR_NONE) { 04876 PALDevDataSet(dev, CurrentParameters, current_parameters); 04877 } 04878 04879 04880 /* read the sequence config and save it */ 04881 if (status == VL53L0X_ERROR_NONE) { 04882 status = VL53L0X_read_byte(dev, 04883 VL53L0X_REG_SYSTEM_SEQUENCE_CONFIG, &tempbyte); 04884 if (status == VL53L0X_ERROR_NONE) { 04885 PALDevDataSet(dev, SequenceConfig, tempbyte); 04886 } 04887 } 04888 04889 /* Disable MSRC and TCC by default */ 04890 if (status == VL53L0X_ERROR_NONE) { 04891 status = VL53L0X_set_sequence_step_enable(dev, 04892 VL53L0X_SEQUENCESTEP_TCC, 0); 04893 } 04894 04895 if (status == VL53L0X_ERROR_NONE) { 04896 status = VL53L0X_set_sequence_step_enable(dev, 04897 VL53L0X_SEQUENCESTEP_MSRC, 0); 04898 } 04899 04900 /* Set PAL State to standby */ 04901 if (status == VL53L0X_ERROR_NONE) { 04902 PALDevDataSet(dev, PalState, VL53L0X_STATE_IDLE); 04903 } 04904 04905 /* Store pre-range vcsel period */ 04906 if (status == VL53L0X_ERROR_NONE) { 04907 status = VL53L0X_get_vcsel_pulse_period( 04908 dev, 04909 VL53L0X_VCSEL_PERIOD_PRE_RANGE, 04910 &vcsel_pulse_period_pclk); 04911 } 04912 04913 if (status == VL53L0X_ERROR_NONE) { 04914 VL53L0X_SETDEVICESPECIFICPARAMETER( 04915 dev, 04916 PreRangeVcselPulsePeriod, 04917 vcsel_pulse_period_pclk); 04918 } 04919 04920 /* Store final-range vcsel period */ 04921 if (status == VL53L0X_ERROR_NONE) { 04922 status = VL53L0X_get_vcsel_pulse_period( 04923 dev, 04924 VL53L0X_VCSEL_PERIOD_FINAL_RANGE, 04925 &vcsel_pulse_period_pclk); 04926 } 04927 04928 if (status == VL53L0X_ERROR_NONE) { 04929 VL53L0X_SETDEVICESPECIFICPARAMETER( 04930 dev, 04931 FinalRangeVcselPulsePeriod, 04932 vcsel_pulse_period_pclk); 04933 } 04934 04935 /* Store pre-range timeout */ 04936 if (status == VL53L0X_ERROR_NONE) { 04937 status = get_sequence_step_timeout( 04938 dev, 04939 VL53L0X_SEQUENCESTEP_PRE_RANGE, 04940 &seq_timeout_micro_secs); 04941 } 04942 04943 if (status == VL53L0X_ERROR_NONE) { 04944 VL53L0X_SETDEVICESPECIFICPARAMETER( 04945 dev, 04946 PreRangeTimeoutMicroSecs, 04947 seq_timeout_micro_secs); 04948 } 04949 04950 /* Store final-range timeout */ 04951 if (status == VL53L0X_ERROR_NONE) { 04952 status = get_sequence_step_timeout( 04953 dev, 04954 VL53L0X_SEQUENCESTEP_FINAL_RANGE, 04955 &seq_timeout_micro_secs); 04956 } 04957 04958 if (status == VL53L0X_ERROR_NONE) { 04959 VL53L0X_SETDEVICESPECIFICPARAMETER( 04960 dev, 04961 FinalRangeTimeoutMicroSecs, 04962 seq_timeout_micro_secs); 04963 } 04964 04965 LOG_FUNCTION_END(status); 04966 return status; 04967 } 04968 04969 04970 VL53L0X_Error VL53L0X::VL53L0X_stop_measurement(VL53L0X_DEV dev) 04971 { 04972 VL53L0X_Error status = VL53L0X_ERROR_NONE; 04973 LOG_FUNCTION_START(""); 04974 04975 status = VL53L0X_write_byte(dev, VL53L0X_REG_SYSRANGE_START, 04976 VL53L0X_REG_SYSRANGE_MODE_SINGLESHOT); 04977 04978 status = VL53L0X_write_byte(dev, 0xFF, 0x01); 04979 status = VL53L0X_write_byte(dev, 0x00, 0x00); 04980 status = VL53L0X_write_byte(dev, 0x91, 0x00); 04981 status = VL53L0X_write_byte(dev, 0x00, 0x01); 04982 status = VL53L0X_write_byte(dev, 0xFF, 0x00); 04983 04984 if (status == VL53L0X_ERROR_NONE) { 04985 /* Set PAL State to Idle */ 04986 PALDevDataSet(dev, PalState, VL53L0X_STATE_IDLE); 04987 } 04988 04989 /* Check if need to apply interrupt settings */ 04990 if (status == VL53L0X_ERROR_NONE) { 04991 status = VL53L0X_check_and_load_interrupt_settings(dev, 0); 04992 } 04993 04994 LOG_FUNCTION_END(status); 04995 return status; 04996 } 04997 04998 VL53L0X_Error VL53L0X::VL53L0X_get_stop_completed_status(VL53L0X_DEV dev, 04999 uint32_t *p_stop_status) 05000 { 05001 VL53L0X_Error status = VL53L0X_ERROR_NONE; 05002 uint8_t byte = 0; 05003 LOG_FUNCTION_START(""); 05004 05005 status = VL53L0X_write_byte(dev, 0xFF, 0x01); 05006 05007 if (status == VL53L0X_ERROR_NONE) { 05008 status = VL53L0X_read_byte(dev, 0x04, &byte); 05009 } 05010 05011 if (status == VL53L0X_ERROR_NONE) { 05012 status = VL53L0X_write_byte(dev, 0xFF, 0x0); 05013 } 05014 05015 *p_stop_status = byte; 05016 05017 if (byte == 0) { 05018 status = VL53L0X_write_byte(dev, 0x80, 0x01); 05019 status = VL53L0X_write_byte(dev, 0xFF, 0x01); 05020 status = VL53L0X_write_byte(dev, 0x00, 0x00); 05021 status = VL53L0X_write_byte(dev, 0x91, 05022 PALDevDataGet(dev, StopVariable)); 05023 status = VL53L0X_write_byte(dev, 0x00, 0x01); 05024 status = VL53L0X_write_byte(dev, 0xFF, 0x00); 05025 status = VL53L0X_write_byte(dev, 0x80, 0x00); 05026 } 05027 05028 LOG_FUNCTION_END(status); 05029 return status; 05030 } 05031 05032 /****************** Write and read functions from I2C *************************/ 05033 05034 VL53L0X_Error VL53L0X::VL53L0X_write_multi(VL53L0X_DEV dev, uint8_t index, uint8_t *p_data, uint32_t count) 05035 { 05036 int status; 05037 05038 status = VL53L0X_i2c_write(dev->I2cDevAddr , index, p_data, (uint16_t)count); 05039 return status; 05040 } 05041 05042 VL53L0X_Error VL53L0X::VL53L0X_read_multi(VL53L0X_DEV dev, uint8_t index, uint8_t *p_data, uint32_t count) 05043 { 05044 int status; 05045 05046 if (count >= VL53L0X_MAX_I2C_XFER_SIZE) { 05047 status = VL53L0X_ERROR_INVALID_PARAMS; 05048 } 05049 05050 status = VL53L0X_i2c_read(dev->I2cDevAddr , index, p_data, (uint16_t)count); 05051 05052 return status; 05053 } 05054 05055 05056 VL53L0X_Error VL53L0X::VL53L0X_write_byte(VL53L0X_DEV Dev, uint8_t index, uint8_t data) 05057 { 05058 int status; 05059 05060 status = VL53L0X_i2c_write(Dev->I2cDevAddr , index, &data, 1); 05061 return status; 05062 } 05063 05064 VL53L0X_Error VL53L0X::VL53L0X_write_word(VL53L0X_DEV dev, uint8_t index, uint16_t data) 05065 { 05066 int status; 05067 uint8_t buffer[2]; 05068 05069 buffer[0] = data >> 8; 05070 buffer[1] = data & 0x00FF; 05071 status = VL53L0X_i2c_write(dev->I2cDevAddr , index, (uint8_t *)buffer, 2); 05072 return status; 05073 } 05074 05075 VL53L0X_Error VL53L0X::VL53L0X_write_dword(VL53L0X_DEV Dev, uint8_t index, uint32_t data) 05076 { 05077 int status; 05078 uint8_t buffer[4]; 05079 05080 buffer[0] = (data >> 24) & 0xFF; 05081 buffer[1] = (data >> 16) & 0xFF; 05082 buffer[2] = (data >> 8) & 0xFF; 05083 buffer[3] = (data >> 0) & 0xFF; 05084 status = VL53L0X_i2c_write(Dev->I2cDevAddr , index, (uint8_t *)buffer, 4); 05085 return status; 05086 } 05087 05088 05089 VL53L0X_Error VL53L0X::VL53L0X_read_byte(VL53L0X_DEV Dev, uint8_t index, uint8_t *p_data) 05090 { 05091 int status; 05092 05093 status = VL53L0X_i2c_read(Dev->I2cDevAddr , index, p_data, 1); 05094 05095 if (status) { 05096 return -1; 05097 } 05098 05099 return 0; 05100 } 05101 05102 VL53L0X_Error VL53L0X::VL53L0X_read_word(VL53L0X_DEV Dev, uint8_t index, uint16_t *p_data) 05103 { 05104 int status; 05105 uint8_t buffer[2] = {0, 0}; 05106 05107 status = VL53L0X_i2c_read(Dev->I2cDevAddr , index, buffer, 2); 05108 if (!status) { 05109 *p_data = (buffer[0] << 8) + buffer[1]; 05110 } 05111 return status; 05112 05113 } 05114 05115 VL53L0X_Error VL53L0X::VL53L0X_read_dword(VL53L0X_DEV Dev, uint8_t index, uint32_t *p_data) 05116 { 05117 int status; 05118 uint8_t buffer[4] = {0, 0, 0, 0}; 05119 05120 status = VL53L0X_i2c_read(Dev->I2cDevAddr , index, buffer, 4); 05121 if (!status) { 05122 *p_data = (buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + buffer[3]; 05123 } 05124 return status; 05125 05126 } 05127 05128 VL53L0X_Error VL53L0X::VL53L0X_update_byte(VL53L0X_DEV Dev, uint8_t index, uint8_t and_data, uint8_t or_data) 05129 { 05130 int status; 05131 uint8_t buffer = 0; 05132 05133 /* read data direct onto buffer */ 05134 status = VL53L0X_i2c_read(Dev->I2cDevAddr , index, &buffer, 1); 05135 if (!status) { 05136 buffer = (buffer & and_data) | or_data; 05137 status = VL53L0X_i2c_write(Dev->I2cDevAddr , index, &buffer, (uint8_t)1); 05138 } 05139 return status; 05140 } 05141 05142 VL53L0X_Error VL53L0X::VL53L0X_i2c_write(uint8_t DeviceAddr, uint8_t RegisterAddr, uint8_t *p_data, 05143 uint16_t NumByteToWrite) 05144 { 05145 int ret; 05146 #if ORIGINAL 05147 ret = _dev_i2c->i2c_write(p_data, DeviceAddr, RegisterAddr, NumByteToWrite); 05148 #else 05149 ret = i2c_write(p_data, DeviceAddr, RegisterAddr, NumByteToWrite); 05150 #endif 05151 05152 if (ret) { 05153 return -1; 05154 } 05155 return 0; 05156 } 05157 05158 VL53L0X_Error VL53L0X::VL53L0X_i2c_read(uint8_t DeviceAddr, uint8_t RegisterAddr, uint8_t *p_data, 05159 uint16_t NumByteToRead) 05160 { 05161 int ret; 05162 05163 #if ORIGINAL 05164 ret = _dev_i2c->i2c_read(p_data, DeviceAddr, RegisterAddr, NumByteToRead); 05165 #else 05166 ret = i2c_read(p_data, DeviceAddr, RegisterAddr, NumByteToRead); 05167 #endif 05168 05169 if (ret) { 05170 return -1; 05171 } 05172 return 0; 05173 } 05174 05175 int VL53L0X::read_id(uint8_t *id) 05176 { 05177 int status = 0; 05178 uint16_t rl_id = 0; 05179 05180 status = VL53L0X_read_word(_device, VL53L0X_REG_IDENTIFICATION_MODEL_ID, &rl_id); 05181 if (rl_id == 0xEEAA) { 05182 return status; 05183 } 05184 05185 return -1; 05186 } 05187 05188 05189 VL53L0X_Error VL53L0X::wait_measurement_data_ready(VL53L0X_DEV dev) 05190 { 05191 VL53L0X_Error status = VL53L0X_ERROR_NONE; 05192 uint8_t new_dat_ready = 0; 05193 uint32_t loop_nb; 05194 05195 // Wait until it finished 05196 // use timeout to avoid deadlock 05197 if (status == VL53L0X_ERROR_NONE) { 05198 loop_nb = 0; 05199 do { 05200 status = VL53L0X_get_measurement_data_ready(dev, &new_dat_ready); 05201 if ((new_dat_ready == 0x01) || status != VL53L0X_ERROR_NONE) { 05202 break; 05203 } 05204 loop_nb = loop_nb + 1; 05205 VL53L0X_polling_delay(dev); 05206 } while (loop_nb < VL53L0X_DEFAULT_MAX_LOOP); 05207 05208 if (loop_nb >= VL53L0X_DEFAULT_MAX_LOOP) { 05209 status = VL53L0X_ERROR_TIME_OUT; 05210 } 05211 } 05212 05213 return status; 05214 } 05215 05216 VL53L0X_Error VL53L0X::wait_stop_completed(VL53L0X_DEV dev) 05217 { 05218 VL53L0X_Error status = VL53L0X_ERROR_NONE; 05219 uint32_t stop_completed = 0; 05220 uint32_t loop_nb; 05221 05222 // Wait until it finished 05223 // use timeout to avoid deadlock 05224 if (status == VL53L0X_ERROR_NONE) { 05225 loop_nb = 0; 05226 do { 05227 status = VL53L0X_get_stop_completed_status(dev, &stop_completed); 05228 if ((stop_completed == 0x00) || status != VL53L0X_ERROR_NONE) { 05229 break; 05230 } 05231 loop_nb = loop_nb + 1; 05232 VL53L0X_polling_delay(dev); 05233 } while (loop_nb < VL53L0X_DEFAULT_MAX_LOOP); 05234 05235 if (loop_nb >= VL53L0X_DEFAULT_MAX_LOOP) { 05236 status = VL53L0X_ERROR_TIME_OUT; 05237 } 05238 05239 } 05240 05241 return status; 05242 } 05243 05244 05245 int VL53L0X::init_sensor(uint8_t new_addr) 05246 { 05247 int status; 05248 05249 VL53L0X_off(); 05250 VL53L0X_on(); 05251 05252 // status=VL53L0X_WaitDeviceBooted(Device); 05253 // if(status) 05254 // printf("WaitDeviceBooted fail\n\r"); 05255 status = is_present(); 05256 if (!status) { 05257 status = init(&_my_device); 05258 if (status != VL53L0X_ERROR_NONE) { 05259 printf("Failed to init VL53L0X sensor!\n\r"); 05260 return status; 05261 } 05262 05263 // deduce silicon version 05264 status = VL53L0X_get_device_info(&_my_device, &_device_info); 05265 05266 status = prepare(); 05267 if (status != VL53L0X_ERROR_NONE) { 05268 printf("Failed to prepare VL53L0X!\n\r"); 05269 return status; 05270 } 05271 05272 if (new_addr != VL53L0X_DEFAULT_ADDRESS) { 05273 status = set_device_address(new_addr); 05274 if (status) { 05275 printf("Failed to change I2C address!\n\r"); 05276 return status; 05277 } 05278 } else { 05279 #if ORIGINAL 05280 printf("Invalid new address!\n\r"); 05281 #endif 05282 return VL53L0X_ERROR_INVALID_PARAMS; 05283 } 05284 } 05285 return status; 05286 } 05287 05288 int VL53L0X::range_meas_int_continuous_mode(void (*fptr)(void)) 05289 { 05290 int status, clr_status; 05291 05292 status = VL53L0X_stop_measurement(_device); // it is safer to do this while sensor is stopped 05293 05294 // status = VL53L0X_SetInterruptThresholds(Device, VL53L0X_DEVICEMODE_CONTINUOUS_RANGING, 0, 300); 05295 05296 status = VL53L0X_set_gpio_config(_device, 0, VL53L0X_DEVICEMODE_CONTINUOUS_RANGING, 05297 VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY, 05298 VL53L0X_INTERRUPTPOLARITY_HIGH); 05299 05300 if (!status) { 05301 attach_interrupt_measure_detection_irq(fptr); 05302 enable_interrupt_measure_detection_irq(); 05303 } 05304 05305 clr_status = clear_interrupt(VL53L0X_REG_RESULT_INTERRUPT_STATUS | VL53L0X_REG_RESULT_RANGE_STATUS); 05306 if (clr_status) { 05307 VL53L0X_ErrLog("VL53L0X_ClearErrorInterrupt fail\r\n"); 05308 } 05309 05310 if (!status) { 05311 status = range_start_continuous_mode(); 05312 } 05313 return status; 05314 } 05315 05316 05317 int VL53L0X::start_measurement(OperatingMode operating_mode, void (*fptr)(void)) 05318 { 05319 int Status = VL53L0X_ERROR_NONE; 05320 int ClrStatus; 05321 05322 uint8_t VhvSettings; 05323 uint8_t PhaseCal; 05324 // *** from mass market cube expansion v1.1, ranging with satellites. 05325 // default settings, for normal range. 05326 FixPoint1616_t signalLimit = (FixPoint1616_t)(0.25 * 65536); 05327 FixPoint1616_t sigmaLimit = (FixPoint1616_t)(18 * 65536); 05328 uint32_t timingBudget = 33000; 05329 uint8_t preRangeVcselPeriod = 14; 05330 uint8_t finalRangeVcselPeriod = 10; 05331 05332 if (operating_mode == range_continuous_interrupt) { 05333 if (_gpio1Int == NULL) { 05334 printf("GPIO1 Error\r\n"); 05335 return 1; 05336 } 05337 05338 Status = VL53L0X_stop_measurement(_device); // it is safer to do this while sensor is stopped 05339 05340 // Status = VL53L0X_SetInterruptThresholds(Device, VL53L0X_DEVICEMODE_CONTINUOUS_RANGING, 0, 300); 05341 05342 Status = VL53L0X_set_gpio_config(_device, 0, VL53L0X_DEVICEMODE_CONTINUOUS_RANGING, 05343 VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY, 05344 VL53L0X_INTERRUPTPOLARITY_HIGH); 05345 05346 if (Status == VL53L0X_ERROR_NONE) { 05347 attach_interrupt_measure_detection_irq(fptr); 05348 enable_interrupt_measure_detection_irq(); 05349 } 05350 05351 ClrStatus = clear_interrupt(VL53L0X_REG_RESULT_INTERRUPT_STATUS | VL53L0X_REG_RESULT_RANGE_STATUS); 05352 if (ClrStatus) { 05353 VL53L0X_ErrLog("VL53L0X_ClearErrorInterrupt fail\r\n"); 05354 } 05355 05356 if (Status == VL53L0X_ERROR_NONE) { 05357 Status = VL53L0X_set_device_mode(_device, VL53L0X_DEVICEMODE_CONTINUOUS_RANGING); // Setup in continuous ranging mode 05358 } 05359 05360 if (Status == VL53L0X_ERROR_NONE) { 05361 Status = VL53L0X_start_measurement(_device); 05362 } 05363 } 05364 05365 if (operating_mode == range_single_shot_polling) { 05366 // singelshot, polled ranging 05367 if (Status == VL53L0X_ERROR_NONE) { 05368 // no need to do this when we use VL53L0X_PerformSingleRangingMeasurement 05369 Status = VL53L0X_set_device_mode(_device, VL53L0X_DEVICEMODE_SINGLE_RANGING); // Setup in single ranging mode 05370 } 05371 05372 // Enable/Disable Sigma and Signal check 05373 if (Status == VL53L0X_ERROR_NONE) { 05374 Status = VL53L0X_set_limit_check_enable(_device, 05375 VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE, 1); 05376 } 05377 if (Status == VL53L0X_ERROR_NONE) { 05378 Status = VL53L0X_set_limit_check_enable(_device, 05379 VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE, 1); 05380 } 05381 05382 // *** from mass market cube expansion v1.1, ranging with satellites. 05383 #if ORIGINAL 05384 /* Ranging configuration */ 05385 //* 05386 // switch(rangingConfig) { 05387 // case LONG_RANGE: 05388 signalLimit = (FixPoint1616_t)(0.1 * 65536); 05389 sigmaLimit = (FixPoint1616_t)(60 * 65536); 05390 timingBudget = 33000; 05391 preRangeVcselPeriod = 18; 05392 finalRangeVcselPeriod = 14; 05393 /* break; 05394 case HIGH_ACCURACY: 05395 signalLimit = (FixPoint1616_t)(0.25*65536); 05396 sigmaLimit = (FixPoint1616_t)(18*65536); 05397 timingBudget = 200000; 05398 preRangeVcselPeriod = 14; 05399 finalRangeVcselPeriod = 10; 05400 break; 05401 case HIGH_SPEED: 05402 signalLimit = (FixPoint1616_t)(0.25*65536); 05403 sigmaLimit = (FixPoint1616_t)(32*65536); 05404 timingBudget = 20000; 05405 preRangeVcselPeriod = 14; 05406 finalRangeVcselPeriod = 10; 05407 break; 05408 default: 05409 debug_printf("Not Supported"); 05410 } 05411 */ 05412 #else 05413 /* Ranging configuration */ 05414 switch(_range_mode) { 05415 case range_hi_accurate_200ms_120cm: 05416 signalLimit = (FixPoint1616_t)(0.25*65536); 05417 sigmaLimit = (FixPoint1616_t)(18*65536); 05418 timingBudget = 200000; 05419 preRangeVcselPeriod = 14; 05420 finalRangeVcselPeriod = 10; 05421 break; 05422 case range_hi_speed_20ms_120cm: 05423 signalLimit = (FixPoint1616_t)(0.25*65536); 05424 sigmaLimit = (FixPoint1616_t)(32*65536); 05425 timingBudget = 20000; 05426 preRangeVcselPeriod = 14; 05427 finalRangeVcselPeriod = 10; 05428 break; 05429 case range_long_distance_33ms_200cm: 05430 default: 05431 signalLimit = (FixPoint1616_t)(0.1 * 65536); 05432 sigmaLimit = (FixPoint1616_t)(60 * 65536); 05433 timingBudget = 33000; 05434 preRangeVcselPeriod = 18; 05435 finalRangeVcselPeriod = 14; 05436 } 05437 #endif 05438 if (Status == VL53L0X_ERROR_NONE) { 05439 Status = VL53L0X_set_limit_check_value(_device, 05440 VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE, signalLimit); 05441 } 05442 05443 if (Status == VL53L0X_ERROR_NONE) { 05444 Status = VL53L0X_set_limit_check_value(_device, 05445 VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE, sigmaLimit); 05446 } 05447 05448 if (Status == VL53L0X_ERROR_NONE) { 05449 Status = VL53L0X_set_measurement_timing_budget_micro_seconds(_device, timingBudget); 05450 } 05451 05452 if (Status == VL53L0X_ERROR_NONE) { 05453 Status = VL53L0X_set_vcsel_pulse_period(_device, 05454 VL53L0X_VCSEL_PERIOD_PRE_RANGE, preRangeVcselPeriod); 05455 } 05456 05457 if (Status == VL53L0X_ERROR_NONE) { 05458 Status = VL53L0X_set_vcsel_pulse_period(_device, 05459 VL53L0X_VCSEL_PERIOD_FINAL_RANGE, finalRangeVcselPeriod); 05460 } 05461 05462 if (Status == VL53L0X_ERROR_NONE) { 05463 Status = VL53L0X_perform_ref_calibration(_device, &VhvSettings, &PhaseCal); 05464 } 05465 05466 } 05467 05468 if (operating_mode == range_continuous_polling) { 05469 if (Status == VL53L0X_ERROR_NONE) { 05470 //printf("Call of VL53L0X_SetDeviceMode\n"); 05471 Status = VL53L0X_set_device_mode(_device, VL53L0X_DEVICEMODE_CONTINUOUS_RANGING); // Setup in continuous ranging mode 05472 } 05473 05474 if (Status == VL53L0X_ERROR_NONE) { 05475 //printf("Call of VL53L0X_StartMeasurement\n"); 05476 Status = VL53L0X_start_measurement(_device); 05477 } 05478 } 05479 05480 return Status; 05481 } 05482 05483 05484 int VL53L0X::get_measurement(OperatingMode operating_mode, VL53L0X_RangingMeasurementData_t *p_data) 05485 { 05486 int Status = VL53L0X_ERROR_NONE; 05487 05488 if (operating_mode == range_single_shot_polling) { 05489 Status = VL53L0X_perform_single_ranging_measurement(_device, p_data); 05490 } 05491 05492 if (operating_mode == range_continuous_polling) { 05493 if (Status == VL53L0X_ERROR_NONE) { 05494 Status = VL53L0X_measurement_poll_for_completion(_device); 05495 } 05496 05497 if (Status == VL53L0X_ERROR_NONE) { 05498 Status = VL53L0X_get_ranging_measurement_data(_device, p_data); 05499 05500 // Clear the interrupt 05501 VL53L0X_clear_interrupt_mask(_device, VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY); 05502 VL53L0X_polling_delay(_device); 05503 } 05504 } 05505 05506 if (operating_mode == range_continuous_interrupt) { 05507 Status = VL53L0X_get_ranging_measurement_data(_device, p_data); 05508 VL53L0X_clear_interrupt_mask(_device, VL53L0X_REG_SYSTEM_INTERRUPT_CLEAR | VL53L0X_REG_RESULT_INTERRUPT_STATUS); 05509 } 05510 05511 return Status; 05512 } 05513 05514 05515 int VL53L0X::stop_measurement(OperatingMode operating_mode) 05516 { 05517 int status = VL53L0X_ERROR_NONE; 05518 05519 05520 // don't need to stop for a singleshot range! 05521 if (operating_mode == range_single_shot_polling) { 05522 } 05523 05524 if (operating_mode == range_continuous_interrupt || operating_mode == range_continuous_polling) { 05525 // continuous mode 05526 if (status == VL53L0X_ERROR_NONE) { 05527 //printf("Call of VL53L0X_StopMeasurement\n"); 05528 status = VL53L0X_stop_measurement(_device); 05529 } 05530 05531 if (status == VL53L0X_ERROR_NONE) { 05532 //printf("Wait Stop to be competed\n"); 05533 status = wait_stop_completed(_device); 05534 } 05535 05536 if (status == VL53L0X_ERROR_NONE) 05537 status = VL53L0X_clear_interrupt_mask(_device, 05538 VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY); 05539 } 05540 05541 return status; 05542 } 05543 05544 05545 int VL53L0X::handle_irq(OperatingMode operating_mode, VL53L0X_RangingMeasurementData_t *data) 05546 { 05547 int status; 05548 status = get_measurement(operating_mode, data); 05549 enable_interrupt_measure_detection_irq(); 05550 return status; 05551 } 05552 05553 05554 /******************************************************************************/
Generated on Wed Jul 13 2022 18:43:14 by
1.7.2
