Updates to follow mbed SDK coding style guidelines.
Dependencies: ST_INTERFACES X_NUCLEO_COMMON
Dependents: 53L0A1_Satellites_with_Interrupts_OS5 Display_53L0A1_OS5
Fork of X_NUCLEO_53L0A1 by
vl53l0x_class.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_class.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 loop_nb = loop_nb + 1; 00102 } while ( loop_nb < VL53L0X_DEFAULT_MAX_LOOP ); 00103 00104 if ( loop_nb >= VL53L0X_DEFAULT_MAX_LOOP ) 00105 status = VL53L0X_ERROR_TIME_OUT; 00106 00107 } 00108 00109 status |= vl53l0x_write_byte( dev, 0x83, 0x01 ); 00110 00111 LOG_FUNCTION_END( status ); 00112 return status; 00113 00114 } 00115 00116 VL53L0X_Error VL53L0X::vl53l0x_get_info_from_device( VL53L0X_DEV dev, uint8_t option ) 00117 { 00118 00119 VL53L0X_Error status = VL53L0X_ERROR_NONE; 00120 uint8_t byte; 00121 uint32_t tmp_dword; 00122 uint8_t module_id; 00123 uint8_t revision; 00124 uint8_t reference_spad_count = 0; 00125 uint8_t reference_spad_type = 0; 00126 uint32_t part_uid_upper = 0; 00127 uint32_t part_uid_lower = 0; 00128 uint32_t offset_fixed1104_mm = 0; 00129 int16_t offset_micro_meters = 0; 00130 uint32_t dist_meas_tgt_fixed1104_mm = 400 << 4; 00131 uint32_t dist_meas_fixed1104_400_mm = 0; 00132 uint32_t signal_rate_meas_fixed1104_400_mm = 0; 00133 char product_id[19]; 00134 char *product_id_tmp; 00135 uint8_t read_data_from_device_done; 00136 FixPoint1616_t signal_rate_meas_fixed400_mm_fix = 0; 00137 uint8_t nvm_ref_good_spad_map[VL53L0X_REF_SPAD_BUFFER_SIZE]; 00138 int i; 00139 00140 00141 LOG_FUNCTION_START( "" ); 00142 00143 read_data_from_device_done = VL53L0X_GETDEVICESPECIFICPARAMETER( dev, 00144 ReadDataFromDeviceDone ); 00145 00146 /* This access is done only once after that a GetDeviceInfo or 00147 * datainit is done*/ 00148 if ( read_data_from_device_done != 7 ) { 00149 00150 status |= vl53l0x_write_byte( dev, 0x80, 0x01 ); 00151 status |= vl53l0x_write_byte( dev, 0xFF, 0x01 ); 00152 status |= vl53l0x_write_byte( dev, 0x00, 0x00 ); 00153 00154 status |= vl53l0x_write_byte( dev, 0xFF, 0x06 ); 00155 status |= vl53l0x_read_byte( dev, 0x83, &byte ); 00156 status |= vl53l0x_write_byte( dev, 0x83, byte | 4 ); 00157 status |= vl53l0x_write_byte( dev, 0xFF, 0x07 ); 00158 status |= vl53l0x_write_byte( dev, 0x81, 0x01 ); 00159 00160 status |= vl53l0x_polling_delay( dev ); 00161 00162 status |= vl53l0x_write_byte( dev, 0x80, 0x01 ); 00163 00164 if ( ( ( option & 1 ) == 1 ) && 00165 ( ( read_data_from_device_done & 1 ) == 0 ) ) { 00166 status |= vl53l0x_write_byte( dev, 0x94, 0x6b ); 00167 status |= vl53l0x_device_read_strobe( dev ); 00168 status |= vl53l0x_read_dword( dev, 0x90, &tmp_dword ); 00169 00170 reference_spad_count = ( uint8_t )( ( tmp_dword >> 8 ) & 0x07f ); 00171 reference_spad_type = ( uint8_t )( ( tmp_dword >> 15 ) & 0x01 ); 00172 00173 status |= vl53l0x_write_byte( dev, 0x94, 0x24 ); 00174 status |= vl53l0x_device_read_strobe( dev ); 00175 status |= vl53l0x_read_dword( dev, 0x90, &tmp_dword ); 00176 00177 00178 nvm_ref_good_spad_map[0] = ( uint8_t )( ( tmp_dword >> 24 ) 00179 & 0xff ); 00180 nvm_ref_good_spad_map[1] = ( uint8_t )( ( tmp_dword >> 16 ) 00181 & 0xff ); 00182 nvm_ref_good_spad_map[2] = ( uint8_t )( ( tmp_dword >> 8 ) 00183 & 0xff ); 00184 nvm_ref_good_spad_map[3] = ( uint8_t )( tmp_dword & 0xff ); 00185 00186 status |= vl53l0x_write_byte( dev, 0x94, 0x25 ); 00187 status |= vl53l0x_device_read_strobe( dev ); 00188 status |= vl53l0x_read_dword( dev, 0x90, &tmp_dword ); 00189 00190 nvm_ref_good_spad_map[4] = ( uint8_t )( ( tmp_dword >> 24 ) 00191 & 0xff ); 00192 nvm_ref_good_spad_map[5] = ( uint8_t )( ( tmp_dword >> 16 ) 00193 & 0xff ); 00194 } 00195 00196 if ( ( ( option & 2 ) == 2 ) && 00197 ( ( read_data_from_device_done & 2 ) == 0 ) ) { 00198 00199 status |= vl53l0x_write_byte( dev, 0x94, 0x02 ); 00200 status |= vl53l0x_device_read_strobe( dev ); 00201 status |= vl53l0x_read_byte( dev, 0x90, &module_id ); 00202 00203 status |= vl53l0x_write_byte( dev, 0x94, 0x7B ); 00204 status |= vl53l0x_device_read_strobe( dev ); 00205 status |= vl53l0x_read_byte( dev, 0x90, &revision ); 00206 00207 status |= vl53l0x_write_byte( dev, 0x94, 0x77 ); 00208 status |= vl53l0x_device_read_strobe( dev ); 00209 status |= vl53l0x_read_dword( dev, 0x90, &tmp_dword ); 00210 00211 product_id[0] = ( char )( ( tmp_dword >> 25 ) & 0x07f ); 00212 product_id[1] = ( char )( ( tmp_dword >> 18 ) & 0x07f ); 00213 product_id[2] = ( char )( ( tmp_dword >> 11 ) & 0x07f ); 00214 product_id[3] = ( char )( ( tmp_dword >> 4 ) & 0x07f ); 00215 00216 byte = ( uint8_t )( ( tmp_dword & 0x00f ) << 3 ); 00217 00218 status |= vl53l0x_write_byte( dev, 0x94, 0x78 ); 00219 status |= vl53l0x_device_read_strobe( dev ); 00220 status |= vl53l0x_read_dword( dev, 0x90, &tmp_dword ); 00221 00222 product_id[4] = ( char )( byte + 00223 ( ( tmp_dword >> 29 ) & 0x07f ) ); 00224 product_id[5] = ( char )( ( tmp_dword >> 22 ) & 0x07f ); 00225 product_id[6] = ( char )( ( tmp_dword >> 15 ) & 0x07f ); 00226 product_id[7] = ( char )( ( tmp_dword >> 8 ) & 0x07f ); 00227 product_id[8] = ( char )( ( tmp_dword >> 1 ) & 0x07f ); 00228 00229 byte = ( uint8_t )( ( tmp_dword & 0x001 ) << 6 ); 00230 00231 status |= vl53l0x_write_byte( dev, 0x94, 0x79 ); 00232 00233 status |= vl53l0x_device_read_strobe( dev ); 00234 00235 status |= vl53l0x_read_dword( dev, 0x90, &tmp_dword ); 00236 00237 product_id[9] = ( char )( byte + 00238 ( ( tmp_dword >> 26 ) & 0x07f ) ); 00239 product_id[10] = ( char )( ( tmp_dword >> 19 ) & 0x07f ); 00240 product_id[11] = ( char )( ( tmp_dword >> 12 ) & 0x07f ); 00241 product_id[12] = ( char )( ( tmp_dword >> 5 ) & 0x07f ); 00242 00243 byte = ( uint8_t )( ( tmp_dword & 0x01f ) << 2 ); 00244 00245 status |= vl53l0x_write_byte( dev, 0x94, 0x7A ); 00246 00247 status |= vl53l0x_device_read_strobe( dev ); 00248 00249 status |= vl53l0x_read_dword( dev, 0x90, &tmp_dword ); 00250 00251 product_id[13] = ( char )( byte + 00252 ( ( tmp_dword >> 30 ) & 0x07f ) ); 00253 product_id[14] = ( char )( ( tmp_dword >> 23 ) & 0x07f ); 00254 product_id[15] = ( char )( ( tmp_dword >> 16 ) & 0x07f ); 00255 product_id[16] = ( char )( ( tmp_dword >> 9 ) & 0x07f ); 00256 product_id[17] = ( char )( ( tmp_dword >> 2 ) & 0x07f ); 00257 product_id[18] = '\0'; 00258 00259 } 00260 00261 if ( ( ( option & 4 ) == 4 ) && 00262 ( ( read_data_from_device_done & 4 ) == 0 ) ) { 00263 00264 status |= vl53l0x_write_byte( dev, 0x94, 0x7B ); 00265 status |= vl53l0x_device_read_strobe( dev ); 00266 status |= vl53l0x_read_dword( dev, 0x90, &part_uid_upper ); 00267 00268 status |= vl53l0x_write_byte( dev, 0x94, 0x7C ); 00269 status |= vl53l0x_device_read_strobe( dev ); 00270 status |= vl53l0x_read_dword( dev, 0x90, &part_uid_lower ); 00271 00272 status |= vl53l0x_write_byte( dev, 0x94, 0x73 ); 00273 status |= vl53l0x_device_read_strobe( dev ); 00274 status |= vl53l0x_read_dword( dev, 0x90, &tmp_dword ); 00275 00276 signal_rate_meas_fixed1104_400_mm = ( tmp_dword & 00277 0x0000000ff ) << 8; 00278 00279 status |= vl53l0x_write_byte( dev, 0x94, 0x74 ); 00280 status |= vl53l0x_device_read_strobe( dev ); 00281 status |= vl53l0x_read_dword( dev, 0x90, &tmp_dword ); 00282 00283 signal_rate_meas_fixed1104_400_mm |= ( ( tmp_dword & 00284 0xff000000 ) >> 24 ); 00285 00286 status |= vl53l0x_write_byte( dev, 0x94, 0x75 ); 00287 status |= vl53l0x_device_read_strobe( dev ); 00288 status |= vl53l0x_read_dword( dev, 0x90, &tmp_dword ); 00289 00290 dist_meas_fixed1104_400_mm = ( tmp_dword & 0x0000000ff ) 00291 << 8; 00292 00293 status |= vl53l0x_write_byte( dev, 0x94, 0x76 ); 00294 status |= vl53l0x_device_read_strobe( dev ); 00295 status |= vl53l0x_read_dword( dev, 0x90, &tmp_dword ); 00296 00297 dist_meas_fixed1104_400_mm |= ( ( tmp_dword & 0xff000000 ) 00298 >> 24 ); 00299 } 00300 00301 status |= vl53l0x_write_byte( dev, 0x81, 0x00 ); 00302 status |= vl53l0x_write_byte( dev, 0xFF, 0x06 ); 00303 status |= vl53l0x_read_byte( dev, 0x83, &byte ); 00304 status |= vl53l0x_write_byte( dev, 0x83, byte & 0xfb ); 00305 status |= vl53l0x_write_byte( dev, 0xFF, 0x01 ); 00306 status |= vl53l0x_write_byte( dev, 0x00, 0x01 ); 00307 00308 status |= vl53l0x_write_byte( dev, 0xFF, 0x00 ); 00309 status |= vl53l0x_write_byte( dev, 0x80, 0x00 ); 00310 } 00311 00312 if ( ( status == VL53L0X_ERROR_NONE ) && 00313 ( read_data_from_device_done != 7 ) ) { 00314 /* Assign to variable if status is ok */ 00315 if ( ( ( option & 1 ) == 1 ) && 00316 ( ( read_data_from_device_done & 1 ) == 0 ) ) { 00317 VL53L0X_SETDEVICESPECIFICPARAMETER( dev, 00318 ReferenceSpadCount, reference_spad_count ); 00319 00320 VL53L0X_SETDEVICESPECIFICPARAMETER( dev, 00321 ReferenceSpadType, reference_spad_type ); 00322 00323 for ( i = 0; i < VL53L0X_REF_SPAD_BUFFER_SIZE; i++ ) { 00324 dev->Data .SpadData .RefGoodSpadMap [i] = 00325 nvm_ref_good_spad_map[i]; 00326 } 00327 } 00328 00329 if ( ( ( option & 2 ) == 2 ) && 00330 ( ( read_data_from_device_done & 2 ) == 0 ) ) { 00331 VL53L0X_SETDEVICESPECIFICPARAMETER( dev, 00332 ModuleId, module_id ); 00333 00334 VL53L0X_SETDEVICESPECIFICPARAMETER( dev, 00335 Revision, revision ); 00336 00337 product_id_tmp = VL53L0X_GETDEVICESPECIFICPARAMETER( dev, 00338 ProductId ); 00339 VL53L0X_COPYSTRING( product_id_tmp, product_id ); 00340 00341 } 00342 00343 if ( ( ( option & 4 ) == 4 ) && 00344 ( ( read_data_from_device_done & 4 ) == 0 ) ) { 00345 VL53L0X_SETDEVICESPECIFICPARAMETER( dev, 00346 PartUIDUpper, part_uid_upper ); 00347 00348 VL53L0X_SETDEVICESPECIFICPARAMETER( dev, 00349 PartUIDLower, part_uid_lower ); 00350 00351 signal_rate_meas_fixed400_mm_fix = 00352 VL53L0X_FIXPOINT97TOFIXPOINT1616( 00353 signal_rate_meas_fixed1104_400_mm ); 00354 00355 VL53L0X_SETDEVICESPECIFICPARAMETER( dev, 00356 SignalRateMeasFixed400mm, 00357 signal_rate_meas_fixed400_mm_fix ); 00358 00359 offset_micro_meters = 0; 00360 if ( dist_meas_fixed1104_400_mm != 0 ) { 00361 offset_fixed1104_mm = 00362 dist_meas_fixed1104_400_mm - 00363 dist_meas_tgt_fixed1104_mm; 00364 offset_micro_meters = ( offset_fixed1104_mm 00365 * 1000 ) >> 4; 00366 offset_micro_meters *= -1; 00367 } 00368 00369 PALDevDataSet( dev, 00370 Part2PartOffsetAdjustmentNVMMicroMeter, 00371 offset_micro_meters ); 00372 } 00373 byte = ( uint8_t )( read_data_from_device_done | option ); 00374 VL53L0X_SETDEVICESPECIFICPARAMETER( dev, ReadDataFromDeviceDone, 00375 byte ); 00376 } 00377 00378 LOG_FUNCTION_END( status ); 00379 return status; 00380 } 00381 00382 VL53L0X_Error VL53L0X::wrapped_vl53l0x_get_offset_calibration_data_micro_meter( VL53L0X_DEV dev, 00383 int32_t *p_offset_calibration_data_micro_meter ) 00384 { 00385 VL53L0X_Error status = VL53L0X_ERROR_NONE; 00386 uint16_t range_offset_register; 00387 int16_t c_max_offset = 2047; 00388 int16_t c_offset_range = 4096; 00389 00390 /* Note that offset has 10.2 format */ 00391 00392 status = vl53l0x_read_word( dev, 00393 VL53L0X_REG_ALGO_PART_TO_PART_RANGE_OFFSET_MM, 00394 &range_offset_register ); 00395 00396 if ( status == VL53L0X_ERROR_NONE ) { 00397 range_offset_register = ( range_offset_register & 0x0fff ); 00398 00399 /* Apply 12 bit 2's compliment conversion */ 00400 if ( range_offset_register > c_max_offset ) 00401 *p_offset_calibration_data_micro_meter = 00402 ( int16_t )( range_offset_register - c_offset_range ) 00403 * 250; 00404 else 00405 *p_offset_calibration_data_micro_meter = 00406 ( int16_t )range_offset_register * 250; 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 if ( offset_calibration_data_micro_meter < c_min_offset_micro_meter ) 00440 offset_calibration_data_micro_meter = c_min_offset_micro_meter; 00441 00442 /* The offset register is 10.2 format and units are mm 00443 * therefore conversion is applied by a division of 00444 * 250. 00445 */ 00446 if ( offset_calibration_data_micro_meter >= 0 ) { 00447 encoded_offset_val = 00448 offset_calibration_data_micro_meter / 250; 00449 } else { 00450 encoded_offset_val = 00451 c_offset_range + 00452 offset_calibration_data_micro_meter / 250; 00453 } 00454 00455 status = vl53l0x_write_word( dev, 00456 VL53L0X_REG_ALGO_PART_TO_PART_RANGE_OFFSET_MM, 00457 encoded_offset_val ); 00458 00459 LOG_FUNCTION_END( status ); 00460 return status; 00461 } 00462 00463 VL53L0X_Error VL53L0X::vl53l0x_set_offset_calibration_data_micro_meter( VL53L0X_DEV dev, 00464 int32_t offset_calibration_data_micro_meter ) 00465 { 00466 VL53L0X_Error status = VL53L0X_ERROR_NONE; 00467 LOG_FUNCTION_START( "" ); 00468 00469 status = wrapped_vl53l0x_set_offset_calibration_data_micro_meter( dev, 00470 offset_calibration_data_micro_meter ); 00471 00472 LOG_FUNCTION_END( status ); 00473 return status; 00474 } 00475 00476 VL53L0X_Error VL53L0X::vl53l0x_apply_offset_adjustment( VL53L0X_DEV dev ) 00477 { 00478 VL53L0X_Error status = VL53L0X_ERROR_NONE; 00479 int32_t corrected_offset_micro_meters; 00480 int32_t current_offset_micro_meters; 00481 00482 /* if we run on this function we can read all the NVM info 00483 * used by the API */ 00484 status = vl53l0x_get_info_from_device( dev, 7 ); 00485 00486 /* Read back current device offset */ 00487 if ( status == VL53L0X_ERROR_NONE ) { 00488 status = vl53l0x_get_offset_calibration_data_micro_meter( dev, 00489 ¤t_offset_micro_meters ); 00490 } 00491 00492 /* Apply Offset Adjustment derived from 400mm measurements */ 00493 if ( status == VL53L0X_ERROR_NONE ) { 00494 00495 /* Store initial device offset */ 00496 PALDevDataSet( dev, Part2PartOffsetNVMMicroMeter, 00497 current_offset_micro_meters ); 00498 00499 corrected_offset_micro_meters = current_offset_micro_meters + 00500 ( int32_t )PALDevDataGet( dev, 00501 Part2PartOffsetAdjustmentNVMMicroMeter ); 00502 00503 status = vl53l0x_set_offset_calibration_data_micro_meter( dev, 00504 corrected_offset_micro_meters ); 00505 00506 /* store current, adjusted offset */ 00507 if ( status == VL53L0X_ERROR_NONE ) { 00508 VL53L0X_SETPARAMETERFIELD( dev, RangeOffsetMicroMeters, 00509 corrected_offset_micro_meters ); 00510 } 00511 } 00512 00513 return status; 00514 } 00515 00516 VL53L0X_Error VL53L0X::vl53l0x_get_device_mode( VL53L0X_DEV dev, 00517 VL53L0X_DeviceModes *p_device_mode ) 00518 { 00519 VL53L0X_Error status = VL53L0X_ERROR_NONE; 00520 LOG_FUNCTION_START( "" ); 00521 00522 VL53L0X_GETPARAMETERFIELD( dev, DeviceMode, *p_device_mode ); 00523 00524 LOG_FUNCTION_END( status ); 00525 return status; 00526 } 00527 00528 VL53L0X_Error VL53L0X::vl53l0x_get_inter_measurement_period_milli_seconds( VL53L0X_DEV dev, 00529 uint32_t *p_inter_measurement_period_milli_seconds ) 00530 { 00531 VL53L0X_Error status = VL53L0X_ERROR_NONE; 00532 uint16_t osc_calibrate_val; 00533 uint32_t im_period_milli_seconds; 00534 00535 LOG_FUNCTION_START( "" ); 00536 00537 status = vl53l0x_read_word( dev, VL53L0X_REG_OSC_CALIBRATE_VAL, 00538 &osc_calibrate_val ); 00539 00540 if ( status == VL53L0X_ERROR_NONE ) { 00541 status = vl53l0x_read_dword( dev, 00542 VL53L0X_REG_SYSTEM_INTERMEASUREMENT_PERIOD, 00543 &im_period_milli_seconds ); 00544 } 00545 00546 if ( status == VL53L0X_ERROR_NONE ) { 00547 if ( osc_calibrate_val != 0 ) { 00548 *p_inter_measurement_period_milli_seconds = 00549 im_period_milli_seconds / osc_calibrate_val; 00550 } 00551 VL53L0X_SETPARAMETERFIELD( dev, 00552 InterMeasurementPeriodMilliSeconds, 00553 *p_inter_measurement_period_milli_seconds ); 00554 } 00555 00556 LOG_FUNCTION_END( status ); 00557 return status; 00558 } 00559 00560 VL53L0X_Error VL53L0X::vl53l0x_get_x_talk_compensation_rate_mega_cps( VL53L0X_DEV dev, 00561 FixPoint1616_t *p_xtalk_compensation_rate_mega_cps ) 00562 { 00563 VL53L0X_Error status = VL53L0X_ERROR_NONE; 00564 uint16_t value; 00565 FixPoint1616_t temp_fix1616; 00566 00567 LOG_FUNCTION_START( "" ); 00568 00569 status = vl53l0x_read_word( dev, 00570 VL53L0X_REG_CROSSTALK_COMPENSATION_PEAK_RATE_MCPS, ( uint16_t * )&value ); 00571 if ( status == VL53L0X_ERROR_NONE ) { 00572 if ( value == 0 ) { 00573 /* the Xtalk is disabled return value from memory */ 00574 VL53L0X_GETPARAMETERFIELD( dev, 00575 XTalkCompensationRateMegaCps, temp_fix1616 ); 00576 *p_xtalk_compensation_rate_mega_cps = temp_fix1616; 00577 VL53L0X_SETPARAMETERFIELD( dev, XTalkCompensationEnable, 00578 0 ); 00579 } else { 00580 temp_fix1616 = VL53L0X_FIXPOINT313TOFIXPOINT1616( value ); 00581 *p_xtalk_compensation_rate_mega_cps = temp_fix1616; 00582 VL53L0X_SETPARAMETERFIELD( dev, 00583 XTalkCompensationRateMegaCps, temp_fix1616 ); 00584 VL53L0X_SETPARAMETERFIELD( dev, XTalkCompensationEnable, 00585 1 ); 00586 } 00587 } 00588 00589 LOG_FUNCTION_END( status ); 00590 return status; 00591 } 00592 00593 VL53L0X_Error VL53L0X::vl53l0x_get_limit_check_value( VL53L0X_DEV dev, uint16_t limit_check_id, 00594 FixPoint1616_t *p_limit_check_value ) 00595 { 00596 VL53L0X_Error status = VL53L0X_ERROR_NONE; 00597 uint8_t enable_zero_value = 0; 00598 uint16_t temp16; 00599 FixPoint1616_t temp_fix1616; 00600 00601 LOG_FUNCTION_START( "" ); 00602 00603 switch ( limit_check_id ) { 00604 00605 case VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE: 00606 /* internal computation: */ 00607 VL53L0X_GETARRAYPARAMETERFIELD( dev, LimitChecksValue, 00608 VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE, temp_fix1616 ); 00609 enable_zero_value = 0; 00610 break; 00611 00612 case VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE: 00613 status = vl53l0x_read_word( dev, 00614 VL53L0X_REG_FINAL_RANGE_CONFIG_MIN_COUNT_RATE_RTN_LIMIT, 00615 &temp16 ); 00616 if ( status == VL53L0X_ERROR_NONE ) 00617 temp_fix1616 = VL53L0X_FIXPOINT97TOFIXPOINT1616( temp16 ); 00618 00619 00620 enable_zero_value = 1; 00621 break; 00622 00623 case VL53L0X_CHECKENABLE_SIGNAL_REF_CLIP: 00624 /* internal computation: */ 00625 VL53L0X_GETARRAYPARAMETERFIELD( dev, LimitChecksValue, 00626 VL53L0X_CHECKENABLE_SIGNAL_REF_CLIP, temp_fix1616 ); 00627 enable_zero_value = 0; 00628 break; 00629 00630 case VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD: 00631 /* internal computation: */ 00632 VL53L0X_GETARRAYPARAMETERFIELD( dev, LimitChecksValue, 00633 VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD, temp_fix1616 ); 00634 enable_zero_value = 0; 00635 break; 00636 00637 case VL53L0X_CHECKENABLE_SIGNAL_RATE_MSRC: 00638 case VL53L0X_CHECKENABLE_SIGNAL_RATE_PRE_RANGE: 00639 status = vl53l0x_read_word( dev, 00640 VL53L0X_REG_PRE_RANGE_MIN_COUNT_RATE_RTN_LIMIT, 00641 &temp16 ); 00642 if ( status == VL53L0X_ERROR_NONE ) 00643 temp_fix1616 = VL53L0X_FIXPOINT97TOFIXPOINT1616( temp16 ); 00644 00645 00646 enable_zero_value = 0; 00647 break; 00648 00649 default: 00650 status = VL53L0X_ERROR_INVALID_PARAMS; 00651 00652 } 00653 00654 if ( status == VL53L0X_ERROR_NONE ) { 00655 00656 if ( enable_zero_value == 1 ) { 00657 00658 if ( temp_fix1616 == 0 ) { 00659 /* disabled: return value from memory */ 00660 VL53L0X_GETARRAYPARAMETERFIELD( dev, 00661 LimitChecksValue, limit_check_id, 00662 temp_fix1616 ); 00663 *p_limit_check_value = temp_fix1616; 00664 VL53L0X_SETARRAYPARAMETERFIELD( dev, 00665 LimitChecksEnable, limit_check_id, 0 ); 00666 } else { 00667 *p_limit_check_value = temp_fix1616; 00668 VL53L0X_SETARRAYPARAMETERFIELD( dev, 00669 LimitChecksValue, limit_check_id, 00670 temp_fix1616 ); 00671 VL53L0X_SETARRAYPARAMETERFIELD( dev, 00672 LimitChecksEnable, limit_check_id, 1 ); 00673 } 00674 } else { 00675 *p_limit_check_value = temp_fix1616; 00676 } 00677 } 00678 00679 LOG_FUNCTION_END( status ); 00680 return status; 00681 00682 } 00683 00684 VL53L0X_Error VL53L0X::vl53l0x_get_limit_check_enable( VL53L0X_DEV dev, uint16_t limit_check_id, 00685 uint8_t *p_limit_check_enable ) 00686 { 00687 VL53L0X_Error status = VL53L0X_ERROR_NONE; 00688 uint8_t temp8; 00689 00690 LOG_FUNCTION_START( "" ); 00691 00692 if ( limit_check_id >= VL53L0X_CHECKENABLE_NUMBER_OF_CHECKS ) { 00693 status = VL53L0X_ERROR_INVALID_PARAMS; 00694 *p_limit_check_enable = 0; 00695 } else { 00696 VL53L0X_GETARRAYPARAMETERFIELD( dev, LimitChecksEnable, 00697 limit_check_id, temp8 ); 00698 *p_limit_check_enable = temp8; 00699 } 00700 00701 LOG_FUNCTION_END( status ); 00702 return status; 00703 } 00704 00705 VL53L0X_Error VL53L0X::vl53l0x_get_wrap_around_check_enable( VL53L0X_DEV dev, 00706 uint8_t *p_wrap_around_check_enable ) 00707 { 00708 VL53L0X_Error status = VL53L0X_ERROR_NONE; 00709 uint8_t data; 00710 00711 LOG_FUNCTION_START( "" ); 00712 00713 status = vl53l0x_read_byte( dev, VL53L0X_REG_SYSTEM_SEQUENCE_CONFIG, &data ); 00714 if ( status == VL53L0X_ERROR_NONE ) { 00715 PALDevDataSet( dev, SequenceConfig, data ); 00716 if ( data & ( 0x01 << 7 ) ) 00717 *p_wrap_around_check_enable = 0x01; 00718 else 00719 *p_wrap_around_check_enable = 0x00; 00720 } 00721 if ( status == VL53L0X_ERROR_NONE ) { 00722 VL53L0X_SETPARAMETERFIELD( dev, WrapAroundCheckEnable, 00723 *p_wrap_around_check_enable ); 00724 } 00725 00726 LOG_FUNCTION_END( status ); 00727 return status; 00728 } 00729 00730 VL53L0X_Error VL53L0X::sequence_step_enabled( VL53L0X_DEV dev, 00731 VL53L0X_SequenceStepId sequence_step_id, uint8_t sequence_config, 00732 uint8_t *p_sequence_step_enabled ) 00733 { 00734 VL53L0X_Error Status = VL53L0X_ERROR_NONE; 00735 *p_sequence_step_enabled = 0; 00736 LOG_FUNCTION_START( "" ); 00737 00738 switch ( sequence_step_id ) { 00739 case VL53L0X_SEQUENCESTEP_TCC: 00740 *p_sequence_step_enabled = ( sequence_config & 0x10 ) >> 4; 00741 break; 00742 case VL53L0X_SEQUENCESTEP_DSS: 00743 *p_sequence_step_enabled = ( sequence_config & 0x08 ) >> 3; 00744 break; 00745 case VL53L0X_SEQUENCESTEP_MSRC: 00746 *p_sequence_step_enabled = ( sequence_config & 0x04 ) >> 2; 00747 break; 00748 case VL53L0X_SEQUENCESTEP_PRE_RANGE: 00749 *p_sequence_step_enabled = ( sequence_config & 0x40 ) >> 6; 00750 break; 00751 case VL53L0X_SEQUENCESTEP_FINAL_RANGE: 00752 *p_sequence_step_enabled = ( sequence_config & 0x80 ) >> 7; 00753 break; 00754 default: 00755 Status = VL53L0X_ERROR_INVALID_PARAMS; 00756 } 00757 00758 LOG_FUNCTION_END( status ); 00759 return Status; 00760 } 00761 00762 VL53L0X_Error VL53L0X::vl53l0x_get_sequence_step_enables( VL53L0X_DEV dev, 00763 VL53L0X_SchedulerSequenceSteps_t *p_scheduler_sequence_steps ) 00764 { 00765 VL53L0X_Error status = VL53L0X_ERROR_NONE; 00766 uint8_t sequence_config = 0; 00767 LOG_FUNCTION_START( "" ); 00768 00769 status = vl53l0x_read_byte( dev, VL53L0X_REG_SYSTEM_SEQUENCE_CONFIG, 00770 &sequence_config ); 00771 00772 if ( status == VL53L0X_ERROR_NONE ) { 00773 status = sequence_step_enabled( dev, 00774 VL53L0X_SEQUENCESTEP_TCC, sequence_config, 00775 &p_scheduler_sequence_steps->TccOn ); 00776 } 00777 if ( status == VL53L0X_ERROR_NONE ) { 00778 status = sequence_step_enabled( dev, 00779 VL53L0X_SEQUENCESTEP_DSS, sequence_config, 00780 &p_scheduler_sequence_steps->DssOn ); 00781 } 00782 if ( status == VL53L0X_ERROR_NONE ) { 00783 status = sequence_step_enabled( dev, 00784 VL53L0X_SEQUENCESTEP_MSRC, sequence_config, 00785 &p_scheduler_sequence_steps->MsrcOn ); 00786 } 00787 if ( status == VL53L0X_ERROR_NONE ) { 00788 status = sequence_step_enabled( dev, 00789 VL53L0X_SEQUENCESTEP_PRE_RANGE, sequence_config, 00790 &p_scheduler_sequence_steps->PreRangeOn ); 00791 } 00792 if ( status == VL53L0X_ERROR_NONE ) { 00793 status = sequence_step_enabled( dev, 00794 VL53L0X_SEQUENCESTEP_FINAL_RANGE, sequence_config, 00795 &p_scheduler_sequence_steps->FinalRangeOn ); 00796 } 00797 00798 LOG_FUNCTION_END( status ); 00799 return status; 00800 } 00801 00802 uint8_t VL53L0X::vl53l0x_decode_vcsel_period( uint8_t vcsel_period_reg ) 00803 { 00804 /*! 00805 * Converts the encoded VCSEL period register value into the real 00806 * period in PLL clocks 00807 */ 00808 00809 uint8_t vcsel_period_pclks = 0; 00810 00811 vcsel_period_pclks = ( vcsel_period_reg + 1 ) << 1; 00812 00813 return vcsel_period_pclks; 00814 } 00815 00816 uint8_t VL53L0X::lv53l0x_encode_vcsel_period( uint8_t vcsel_period_pclks ) 00817 { 00818 /*! 00819 * Converts the encoded VCSEL period register value into the real period 00820 * in PLL clocks 00821 */ 00822 00823 uint8_t vcsel_period_reg = 0; 00824 00825 vcsel_period_reg = ( vcsel_period_pclks >> 1 ) - 1; 00826 00827 return vcsel_period_reg; 00828 } 00829 00830 00831 VL53L0X_Error VL53L0X::wrapped_vl53l0x_set_vcsel_pulse_period( VL53L0X_DEV dev, 00832 VL53L0X_VcselPeriod vcsel_period_type, uint8_t vcsel_pulse_period_pclk ) 00833 { 00834 VL53L0X_Error status = VL53L0X_ERROR_NONE; 00835 uint8_t vcsel_period_reg; 00836 uint8_t min_pre_vcsel_period_pclk = 12; 00837 uint8_t max_pre_vcsel_period_pclk = 18; 00838 uint8_t min_final_vcsel_period_pclk = 8; 00839 uint8_t max_final_vcsel_period_pclk = 14; 00840 uint32_t measurement_timing_budget_micro_seconds; 00841 uint32_t final_range_timeout_micro_seconds; 00842 uint32_t pre_range_timeout_micro_seconds; 00843 uint32_t msrc_timeout_micro_seconds; 00844 uint8_t phase_cal_int = 0; 00845 00846 /* Check if valid clock period requested */ 00847 00848 if ( ( vcsel_pulse_period_pclk % 2 ) != 0 ) { 00849 /* Value must be an even number */ 00850 status = VL53L0X_ERROR_INVALID_PARAMS; 00851 } else if ( vcsel_period_type == VL53L0X_VCSEL_PERIOD_PRE_RANGE && 00852 ( vcsel_pulse_period_pclk < min_pre_vcsel_period_pclk || 00853 vcsel_pulse_period_pclk > max_pre_vcsel_period_pclk ) ) { 00854 status = VL53L0X_ERROR_INVALID_PARAMS; 00855 } else if ( vcsel_period_type == VL53L0X_VCSEL_PERIOD_FINAL_RANGE && 00856 ( vcsel_pulse_period_pclk < min_final_vcsel_period_pclk || 00857 vcsel_pulse_period_pclk > max_final_vcsel_period_pclk ) ) { 00858 00859 status = VL53L0X_ERROR_INVALID_PARAMS; 00860 } 00861 00862 /* Apply specific settings for the requested clock period */ 00863 00864 if ( status != VL53L0X_ERROR_NONE ) 00865 return status; 00866 00867 00868 if ( vcsel_period_type == VL53L0X_VCSEL_PERIOD_PRE_RANGE ) { 00869 00870 /* Set phase check limits */ 00871 if ( vcsel_pulse_period_pclk == 12 ) { 00872 00873 status = vl53l0x_write_byte( dev, 00874 VL53L0X_REG_PRE_RANGE_CONFIG_VALID_PHASE_HIGH, 00875 0x18 ); 00876 status = vl53l0x_write_byte( dev, 00877 VL53L0X_REG_PRE_RANGE_CONFIG_VALID_PHASE_LOW, 00878 0x08 ); 00879 } else if ( vcsel_pulse_period_pclk == 14 ) { 00880 00881 status = vl53l0x_write_byte( dev, 00882 VL53L0X_REG_PRE_RANGE_CONFIG_VALID_PHASE_HIGH, 00883 0x30 ); 00884 status = vl53l0x_write_byte( dev, 00885 VL53L0X_REG_PRE_RANGE_CONFIG_VALID_PHASE_LOW, 00886 0x08 ); 00887 } else if ( vcsel_pulse_period_pclk == 16 ) { 00888 00889 status = vl53l0x_write_byte( dev, 00890 VL53L0X_REG_PRE_RANGE_CONFIG_VALID_PHASE_HIGH, 00891 0x40 ); 00892 status = vl53l0x_write_byte( dev, 00893 VL53L0X_REG_PRE_RANGE_CONFIG_VALID_PHASE_LOW, 00894 0x08 ); 00895 } else if ( vcsel_pulse_period_pclk == 18 ) { 00896 00897 status = vl53l0x_write_byte( dev, 00898 VL53L0X_REG_PRE_RANGE_CONFIG_VALID_PHASE_HIGH, 00899 0x50 ); 00900 status = vl53l0x_write_byte( dev, 00901 VL53L0X_REG_PRE_RANGE_CONFIG_VALID_PHASE_LOW, 00902 0x08 ); 00903 } 00904 } else if ( vcsel_period_type == VL53L0X_VCSEL_PERIOD_FINAL_RANGE ) { 00905 00906 if ( vcsel_pulse_period_pclk == 8 ) { 00907 00908 status = vl53l0x_write_byte( dev, 00909 VL53L0X_REG_FINAL_RANGE_CONFIG_VALID_PHASE_HIGH, 00910 0x10 ); 00911 status = vl53l0x_write_byte( dev, 00912 VL53L0X_REG_FINAL_RANGE_CONFIG_VALID_PHASE_LOW, 00913 0x08 ); 00914 00915 status |= vl53l0x_write_byte( dev, 00916 VL53L0X_REG_GLOBAL_CONFIG_VCSEL_WIDTH, 0x02 ); 00917 status |= vl53l0x_write_byte( dev, 00918 VL53L0X_REG_ALGO_PHASECAL_CONFIG_TIMEOUT, 0x0C ); 00919 00920 status |= vl53l0x_write_byte( dev, 0xff, 0x01 ); 00921 status |= vl53l0x_write_byte( dev, 00922 VL53L0X_REG_ALGO_PHASECAL_LIM, 00923 0x30 ); 00924 status |= vl53l0x_write_byte( dev, 0xff, 0x00 ); 00925 } else if ( vcsel_pulse_period_pclk == 10 ) { 00926 00927 status = vl53l0x_write_byte( dev, 00928 VL53L0X_REG_FINAL_RANGE_CONFIG_VALID_PHASE_HIGH, 00929 0x28 ); 00930 status = vl53l0x_write_byte( dev, 00931 VL53L0X_REG_FINAL_RANGE_CONFIG_VALID_PHASE_LOW, 00932 0x08 ); 00933 00934 status |= vl53l0x_write_byte( dev, 00935 VL53L0X_REG_GLOBAL_CONFIG_VCSEL_WIDTH, 0x03 ); 00936 status |= vl53l0x_write_byte( dev, 00937 VL53L0X_REG_ALGO_PHASECAL_CONFIG_TIMEOUT, 0x09 ); 00938 00939 status |= vl53l0x_write_byte( dev, 0xff, 0x01 ); 00940 status |= vl53l0x_write_byte( dev, 00941 VL53L0X_REG_ALGO_PHASECAL_LIM, 00942 0x20 ); 00943 status |= vl53l0x_write_byte( dev, 0xff, 0x00 ); 00944 } else if ( vcsel_pulse_period_pclk == 12 ) { 00945 00946 status = vl53l0x_write_byte( dev, 00947 VL53L0X_REG_FINAL_RANGE_CONFIG_VALID_PHASE_HIGH, 00948 0x38 ); 00949 status = vl53l0x_write_byte( dev, 00950 VL53L0X_REG_FINAL_RANGE_CONFIG_VALID_PHASE_LOW, 00951 0x08 ); 00952 00953 status |= vl53l0x_write_byte( dev, 00954 VL53L0X_REG_GLOBAL_CONFIG_VCSEL_WIDTH, 0x03 ); 00955 status |= vl53l0x_write_byte( dev, 00956 VL53L0X_REG_ALGO_PHASECAL_CONFIG_TIMEOUT, 0x08 ); 00957 00958 status |= vl53l0x_write_byte( dev, 0xff, 0x01 ); 00959 status |= vl53l0x_write_byte( dev, 00960 VL53L0X_REG_ALGO_PHASECAL_LIM, 00961 0x20 ); 00962 status |= vl53l0x_write_byte( dev, 0xff, 0x00 ); 00963 } else if ( vcsel_pulse_period_pclk == 14 ) { 00964 00965 status = vl53l0x_write_byte( dev, 00966 VL53L0X_REG_FINAL_RANGE_CONFIG_VALID_PHASE_HIGH, 00967 0x048 ); 00968 status = vl53l0x_write_byte( dev, 00969 VL53L0X_REG_FINAL_RANGE_CONFIG_VALID_PHASE_LOW, 00970 0x08 ); 00971 00972 status |= vl53l0x_write_byte( dev, 00973 VL53L0X_REG_GLOBAL_CONFIG_VCSEL_WIDTH, 0x03 ); 00974 status |= vl53l0x_write_byte( dev, 00975 VL53L0X_REG_ALGO_PHASECAL_CONFIG_TIMEOUT, 0x07 ); 00976 00977 status |= vl53l0x_write_byte( dev, 0xff, 0x01 ); 00978 status |= vl53l0x_write_byte( dev, 00979 VL53L0X_REG_ALGO_PHASECAL_LIM, 00980 0x20 ); 00981 status |= vl53l0x_write_byte( dev, 0xff, 0x00 ); 00982 } 00983 } 00984 00985 00986 /* Re-calculate and apply timeouts, in macro periods */ 00987 00988 if ( status == VL53L0X_ERROR_NONE ) { 00989 vcsel_period_reg = lv53l0x_encode_vcsel_period( ( uint8_t ) 00990 vcsel_pulse_period_pclk ); 00991 00992 /* When the VCSEL period for the pre or final range is changed, 00993 * the corresponding timeout must be read from the device using 00994 * the current VCSEL period, then the new VCSEL period can be 00995 * applied. The timeout then must be written back to the device 00996 * using the new VCSEL period. 00997 * 00998 * For the MSRC timeout, the same applies - this timeout being 00999 * dependant on the pre-range vcsel period. 01000 */ 01001 switch ( vcsel_period_type ) { 01002 case VL53L0X_VCSEL_PERIOD_PRE_RANGE: 01003 status = get_sequence_step_timeout( dev, 01004 VL53L0X_SEQUENCESTEP_PRE_RANGE, 01005 &pre_range_timeout_micro_seconds ); 01006 01007 if ( status == VL53L0X_ERROR_NONE ) 01008 status = get_sequence_step_timeout( dev, 01009 VL53L0X_SEQUENCESTEP_MSRC, 01010 &msrc_timeout_micro_seconds ); 01011 01012 if ( status == VL53L0X_ERROR_NONE ) 01013 status = vl53l0x_write_byte( dev, 01014 VL53L0X_REG_PRE_RANGE_CONFIG_VCSEL_PERIOD, 01015 vcsel_period_reg ); 01016 01017 01018 if ( status == VL53L0X_ERROR_NONE ) 01019 status = set_sequence_step_timeout( dev, 01020 VL53L0X_SEQUENCESTEP_PRE_RANGE, 01021 pre_range_timeout_micro_seconds ); 01022 01023 01024 if ( status == VL53L0X_ERROR_NONE ) 01025 status = set_sequence_step_timeout( dev, 01026 VL53L0X_SEQUENCESTEP_MSRC, 01027 msrc_timeout_micro_seconds ); 01028 01029 VL53L0X_SETDEVICESPECIFICPARAMETER( 01030 dev, 01031 PreRangeVcselPulsePeriod, 01032 vcsel_pulse_period_pclk ); 01033 break; 01034 case VL53L0X_VCSEL_PERIOD_FINAL_RANGE: 01035 status = get_sequence_step_timeout( dev, 01036 VL53L0X_SEQUENCESTEP_FINAL_RANGE, 01037 &final_range_timeout_micro_seconds ); 01038 01039 if ( status == VL53L0X_ERROR_NONE ) 01040 status = vl53l0x_write_byte( dev, 01041 VL53L0X_REG_FINAL_RANGE_CONFIG_VCSEL_PERIOD, 01042 vcsel_period_reg ); 01043 01044 01045 if ( status == VL53L0X_ERROR_NONE ) 01046 status = set_sequence_step_timeout( dev, 01047 VL53L0X_SEQUENCESTEP_FINAL_RANGE, 01048 final_range_timeout_micro_seconds ); 01049 01050 VL53L0X_SETDEVICESPECIFICPARAMETER( 01051 dev, 01052 FinalRangeVcselPulsePeriod, 01053 vcsel_pulse_period_pclk ); 01054 break; 01055 default: 01056 status = VL53L0X_ERROR_INVALID_PARAMS; 01057 } 01058 } 01059 01060 /* Finally, the timing budget must be re-applied */ 01061 if ( status == VL53L0X_ERROR_NONE ) { 01062 VL53L0X_GETPARAMETERFIELD( dev, 01063 MeasurementTimingBudgetMicroSeconds, 01064 measurement_timing_budget_micro_seconds ); 01065 01066 status = vl53l0x_set_measurement_timing_budget_micro_seconds( dev, 01067 measurement_timing_budget_micro_seconds ); 01068 } 01069 01070 /* Perform the phase calibration. This is needed after changing on 01071 * vcsel period. 01072 * get_data_enable = 0, restore_config = 1 */ 01073 if ( status == VL53L0X_ERROR_NONE ) 01074 status = vl53l0x_perform_phase_calibration( 01075 dev, &phase_cal_int, 0, 1 ); 01076 01077 return status; 01078 } 01079 01080 VL53L0X_Error VL53L0X::vl53l0x_set_vcsel_pulse_period( VL53L0X_DEV dev, 01081 VL53L0X_VcselPeriod vcsel_period_type, uint8_t vcsel_pulse_period ) 01082 { 01083 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01084 LOG_FUNCTION_START( "" ); 01085 01086 status = wrapped_vl53l0x_set_vcsel_pulse_period( dev, vcsel_period_type, 01087 vcsel_pulse_period ); 01088 01089 LOG_FUNCTION_END( status ); 01090 return status; 01091 } 01092 01093 VL53L0X_Error VL53L0X::wrapped_vl53l0x_get_vcsel_pulse_period( VL53L0X_DEV dev, 01094 VL53L0X_VcselPeriod vcsel_period_type, uint8_t *p_vcsel_pulse_period_pclk ) 01095 { 01096 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01097 uint8_t vcsel_period_reg; 01098 01099 switch ( vcsel_period_type ) { 01100 case VL53L0X_VCSEL_PERIOD_PRE_RANGE: 01101 status = vl53l0x_read_byte( dev, 01102 VL53L0X_REG_PRE_RANGE_CONFIG_VCSEL_PERIOD, 01103 &vcsel_period_reg ); 01104 break; 01105 case VL53L0X_VCSEL_PERIOD_FINAL_RANGE: 01106 status = vl53l0x_read_byte( dev, 01107 VL53L0X_REG_FINAL_RANGE_CONFIG_VCSEL_PERIOD, 01108 &vcsel_period_reg ); 01109 break; 01110 default: 01111 status = VL53L0X_ERROR_INVALID_PARAMS; 01112 } 01113 01114 if ( status == VL53L0X_ERROR_NONE ) 01115 *p_vcsel_pulse_period_pclk = 01116 vl53l0x_decode_vcsel_period( vcsel_period_reg ); 01117 01118 return status; 01119 } 01120 01121 VL53L0X_Error VL53L0X::vl53l0x_get_vcsel_pulse_period( VL53L0X_DEV dev, 01122 VL53L0X_VcselPeriod vcsel_period_type, uint8_t *p_vcsel_pulse_period_pclk ) 01123 { 01124 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01125 LOG_FUNCTION_START( "" ); 01126 01127 status = wrapped_vl53l0x_get_vcsel_pulse_period( dev, vcsel_period_type, 01128 p_vcsel_pulse_period_pclk ); 01129 01130 LOG_FUNCTION_END( status ); 01131 return status; 01132 } 01133 01134 uint32_t VL53L0X::vl53l0x_decode_timeout( uint16_t encoded_timeout ) 01135 { 01136 /*! 01137 * Decode 16-bit timeout register value - format (LSByte * 2^MSByte) + 1 01138 */ 01139 01140 uint32_t timeout_macro_clks = 0; 01141 01142 timeout_macro_clks = ( ( uint32_t ) ( encoded_timeout & 0x00FF ) 01143 << ( uint32_t ) ( ( encoded_timeout & 0xFF00 ) >> 8 ) ) + 1; 01144 01145 return timeout_macro_clks; 01146 } 01147 01148 uint32_t VL53L0X::vl53l0x_calc_macro_period_ps( VL53L0X_DEV dev, uint8_t vcsel_period_pclks ) 01149 { 01150 uint64_t pll_period_ps; 01151 uint32_t macro_period_vclks; 01152 uint32_t macro_period_ps; 01153 01154 LOG_FUNCTION_START( "" ); 01155 01156 /* The above calculation will produce rounding errors, 01157 therefore set fixed value 01158 */ 01159 pll_period_ps = 1655; 01160 01161 macro_period_vclks = 2304; 01162 macro_period_ps = ( uint32_t )( macro_period_vclks 01163 * vcsel_period_pclks * pll_period_ps ); 01164 01165 LOG_FUNCTION_END( "" ); 01166 return macro_period_ps; 01167 } 01168 01169 /* To convert register value into us */ 01170 uint32_t VL53L0X::vl53l0x_calc_timeout_us( VL53L0X_DEV dev, 01171 uint16_t timeout_period_mclks, 01172 uint8_t vcsel_period_pclks ) 01173 { 01174 uint32_t macro_period_ps; 01175 uint32_t macro_period_ns; 01176 uint32_t actual_timeout_period_us = 0; 01177 01178 macro_period_ps = vl53l0x_calc_macro_period_ps( dev, vcsel_period_pclks ); 01179 macro_period_ns = ( macro_period_ps + 500 ) / 1000; 01180 01181 actual_timeout_period_us = 01182 ( ( timeout_period_mclks * macro_period_ns ) + 500 ) / 1000; 01183 01184 return actual_timeout_period_us; 01185 } 01186 01187 VL53L0X_Error VL53L0X::get_sequence_step_timeout( VL53L0X_DEV dev, 01188 VL53L0X_SequenceStepId sequence_step_id, 01189 uint32_t *p_time_out_micro_secs ) 01190 { 01191 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01192 uint8_t current_vcsel_pulse_period_p_clk; 01193 uint8_t encoded_time_out_byte = 0; 01194 uint32_t timeout_micro_seconds = 0; 01195 uint16_t pre_range_encoded_time_out = 0; 01196 uint16_t msrc_time_out_m_clks; 01197 uint16_t pre_range_time_out_m_clks; 01198 uint16_t final_range_time_out_m_clks = 0; 01199 uint16_t final_range_encoded_time_out; 01200 VL53L0X_SchedulerSequenceSteps_t scheduler_sequence_steps; 01201 01202 if ( ( sequence_step_id == VL53L0X_SEQUENCESTEP_TCC ) || 01203 ( sequence_step_id == VL53L0X_SEQUENCESTEP_DSS ) || 01204 ( sequence_step_id == VL53L0X_SEQUENCESTEP_MSRC ) ) { 01205 01206 status = vl53l0x_get_vcsel_pulse_period( dev, 01207 VL53L0X_VCSEL_PERIOD_PRE_RANGE, 01208 ¤t_vcsel_pulse_period_p_clk ); 01209 if ( status == VL53L0X_ERROR_NONE ) { 01210 status = vl53l0x_read_byte( dev, 01211 VL53L0X_REG_MSRC_CONFIG_TIMEOUT_MACROP, 01212 &encoded_time_out_byte ); 01213 } 01214 msrc_time_out_m_clks = vl53l0x_decode_timeout( encoded_time_out_byte ); 01215 01216 timeout_micro_seconds = vl53l0x_calc_timeout_us( dev, 01217 msrc_time_out_m_clks, 01218 current_vcsel_pulse_period_p_clk ); 01219 } else if ( sequence_step_id == VL53L0X_SEQUENCESTEP_PRE_RANGE ) { 01220 /* Retrieve PRE-RANGE VCSEL Period */ 01221 status = vl53l0x_get_vcsel_pulse_period( dev, 01222 VL53L0X_VCSEL_PERIOD_PRE_RANGE, 01223 ¤t_vcsel_pulse_period_p_clk ); 01224 01225 /* Retrieve PRE-RANGE Timeout in Macro periods (MCLKS) */ 01226 if ( status == VL53L0X_ERROR_NONE ) { 01227 01228 /* Retrieve PRE-RANGE VCSEL Period */ 01229 status = vl53l0x_get_vcsel_pulse_period( dev, 01230 VL53L0X_VCSEL_PERIOD_PRE_RANGE, 01231 ¤t_vcsel_pulse_period_p_clk ); 01232 01233 if ( status == VL53L0X_ERROR_NONE ) { 01234 status = vl53l0x_read_word( dev, 01235 VL53L0X_REG_PRE_RANGE_CONFIG_TIMEOUT_MACROP_HI, 01236 &pre_range_encoded_time_out ); 01237 } 01238 01239 pre_range_time_out_m_clks = vl53l0x_decode_timeout( 01240 pre_range_encoded_time_out ); 01241 01242 timeout_micro_seconds = vl53l0x_calc_timeout_us( dev, 01243 pre_range_time_out_m_clks, 01244 current_vcsel_pulse_period_p_clk ); 01245 } 01246 } else if ( sequence_step_id == VL53L0X_SEQUENCESTEP_FINAL_RANGE ) { 01247 01248 vl53l0x_get_sequence_step_enables( dev, &scheduler_sequence_steps ); 01249 pre_range_time_out_m_clks = 0; 01250 01251 if ( scheduler_sequence_steps.PreRangeOn ) { 01252 /* Retrieve PRE-RANGE VCSEL Period */ 01253 status = vl53l0x_get_vcsel_pulse_period( dev, 01254 VL53L0X_VCSEL_PERIOD_PRE_RANGE, 01255 ¤t_vcsel_pulse_period_p_clk ); 01256 01257 /* Retrieve PRE-RANGE Timeout in Macro periods 01258 * (MCLKS) */ 01259 if ( status == VL53L0X_ERROR_NONE ) { 01260 status = vl53l0x_read_word( dev, 01261 VL53L0X_REG_PRE_RANGE_CONFIG_TIMEOUT_MACROP_HI, 01262 &pre_range_encoded_time_out ); 01263 pre_range_time_out_m_clks = vl53l0x_decode_timeout( 01264 pre_range_encoded_time_out ); 01265 } 01266 } 01267 01268 if ( status == VL53L0X_ERROR_NONE ) { 01269 /* Retrieve FINAL-RANGE VCSEL Period */ 01270 status = vl53l0x_get_vcsel_pulse_period( dev, 01271 VL53L0X_VCSEL_PERIOD_FINAL_RANGE, 01272 ¤t_vcsel_pulse_period_p_clk ); 01273 } 01274 01275 /* Retrieve FINAL-RANGE Timeout in Macro periods (MCLKS) */ 01276 if ( status == VL53L0X_ERROR_NONE ) { 01277 status = vl53l0x_read_word( dev, 01278 VL53L0X_REG_FINAL_RANGE_CONFIG_TIMEOUT_MACROP_HI, 01279 &final_range_encoded_time_out ); 01280 final_range_time_out_m_clks = vl53l0x_decode_timeout( 01281 final_range_encoded_time_out ); 01282 } 01283 01284 final_range_time_out_m_clks -= pre_range_time_out_m_clks; 01285 timeout_micro_seconds = vl53l0x_calc_timeout_us( dev, 01286 final_range_time_out_m_clks, 01287 current_vcsel_pulse_period_p_clk ); 01288 } 01289 01290 *p_time_out_micro_secs = timeout_micro_seconds; 01291 01292 return status; 01293 } 01294 01295 VL53L0X_Error VL53L0X::wrapped_vl53l0x_get_measurement_timing_budget_micro_seconds( VL53L0X_DEV dev, 01296 uint32_t *p_measurement_timing_budget_micro_seconds ) 01297 { 01298 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01299 VL53L0X_SchedulerSequenceSteps_t scheduler_sequence_steps; 01300 uint32_t final_range_timeout_micro_seconds; 01301 uint32_t msrc_dcc_tcc_timeout_micro_seconds = 2000; 01302 uint32_t start_overhead_micro_seconds = 1910; 01303 uint32_t end_overhead_micro_seconds = 960; 01304 uint32_t msrc_overhead_micro_seconds = 660; 01305 uint32_t tcc_overhead_micro_seconds = 590; 01306 uint32_t dss_overhead_micro_seconds = 690; 01307 uint32_t pre_range_overhead_micro_seconds = 660; 01308 uint32_t final_range_overhead_micro_seconds = 550; 01309 uint32_t pre_range_timeout_micro_seconds = 0; 01310 01311 LOG_FUNCTION_START( "" ); 01312 01313 /* Start and end overhead times always present */ 01314 *p_measurement_timing_budget_micro_seconds 01315 = start_overhead_micro_seconds + end_overhead_micro_seconds; 01316 01317 status = vl53l0x_get_sequence_step_enables( dev, &scheduler_sequence_steps ); 01318 01319 if ( status != VL53L0X_ERROR_NONE ) { 01320 LOG_FUNCTION_END( status ); 01321 return status; 01322 } 01323 01324 01325 if ( scheduler_sequence_steps.TccOn || 01326 scheduler_sequence_steps.MsrcOn || 01327 scheduler_sequence_steps.DssOn ) { 01328 01329 status = get_sequence_step_timeout( dev, 01330 VL53L0X_SEQUENCESTEP_MSRC, 01331 &msrc_dcc_tcc_timeout_micro_seconds ); 01332 01333 if ( status == VL53L0X_ERROR_NONE ) { 01334 if ( scheduler_sequence_steps.TccOn ) { 01335 *p_measurement_timing_budget_micro_seconds += 01336 msrc_dcc_tcc_timeout_micro_seconds + 01337 tcc_overhead_micro_seconds; 01338 } 01339 01340 if ( scheduler_sequence_steps.DssOn ) { 01341 *p_measurement_timing_budget_micro_seconds += 01342 2 * ( msrc_dcc_tcc_timeout_micro_seconds + 01343 dss_overhead_micro_seconds ); 01344 } else if ( scheduler_sequence_steps.MsrcOn ) { 01345 *p_measurement_timing_budget_micro_seconds += 01346 msrc_dcc_tcc_timeout_micro_seconds + 01347 msrc_overhead_micro_seconds; 01348 } 01349 } 01350 } 01351 01352 if ( status == VL53L0X_ERROR_NONE ) { 01353 if ( scheduler_sequence_steps.PreRangeOn ) { 01354 status = get_sequence_step_timeout( dev, 01355 VL53L0X_SEQUENCESTEP_PRE_RANGE, 01356 &pre_range_timeout_micro_seconds ); 01357 *p_measurement_timing_budget_micro_seconds += 01358 pre_range_timeout_micro_seconds + 01359 pre_range_overhead_micro_seconds; 01360 } 01361 } 01362 01363 if ( status == VL53L0X_ERROR_NONE ) { 01364 if ( scheduler_sequence_steps.FinalRangeOn ) { 01365 status = get_sequence_step_timeout( dev, 01366 VL53L0X_SEQUENCESTEP_FINAL_RANGE, 01367 &final_range_timeout_micro_seconds ); 01368 *p_measurement_timing_budget_micro_seconds += 01369 ( final_range_timeout_micro_seconds + 01370 final_range_overhead_micro_seconds ); 01371 } 01372 } 01373 01374 if ( status == VL53L0X_ERROR_NONE ) { 01375 VL53L0X_SETPARAMETERFIELD( dev, 01376 MeasurementTimingBudgetMicroSeconds, 01377 *p_measurement_timing_budget_micro_seconds ); 01378 } 01379 01380 LOG_FUNCTION_END( status ); 01381 return status; 01382 } 01383 01384 VL53L0X_Error VL53L0X::vl53l0x_get_measurement_timing_budget_micro_seconds( VL53L0X_DEV dev, 01385 uint32_t *p_measurement_timing_budget_micro_seconds ) 01386 { 01387 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01388 LOG_FUNCTION_START( "" ); 01389 01390 status = wrapped_vl53l0x_get_measurement_timing_budget_micro_seconds( dev, 01391 p_measurement_timing_budget_micro_seconds ); 01392 01393 LOG_FUNCTION_END( status ); 01394 return status; 01395 } 01396 01397 VL53L0X_Error VL53L0X::vl53l0x_get_device_parameters( VL53L0X_DEV dev, 01398 VL53L0X_DeviceParameters_t *p_device_parameters ) 01399 { 01400 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01401 int i; 01402 01403 LOG_FUNCTION_START( "" ); 01404 01405 status = vl53l0x_get_device_mode( dev, &( p_device_parameters->DeviceMode ) ); 01406 01407 if ( status == VL53L0X_ERROR_NONE ) 01408 status = vl53l0x_get_inter_measurement_period_milli_seconds( dev, 01409 &( p_device_parameters->InterMeasurementPeriodMilliSeconds ) ); 01410 01411 01412 if ( status == VL53L0X_ERROR_NONE ) 01413 p_device_parameters->XTalkCompensationEnable = 0; 01414 01415 if ( status == VL53L0X_ERROR_NONE ) 01416 status = vl53l0x_get_x_talk_compensation_rate_mega_cps( dev, 01417 &( p_device_parameters->XTalkCompensationRateMegaCps ) ); 01418 01419 01420 if ( status == VL53L0X_ERROR_NONE ) 01421 status = vl53l0x_get_offset_calibration_data_micro_meter( dev, 01422 &( p_device_parameters->RangeOffsetMicroMeters ) ); 01423 01424 01425 if ( status == VL53L0X_ERROR_NONE ) { 01426 for ( i = 0; i < VL53L0X_CHECKENABLE_NUMBER_OF_CHECKS; i++ ) { 01427 /* get first the values, then the enables. 01428 * VL53L0X_GetLimitCheckValue will modify the enable 01429 * flags 01430 */ 01431 if ( status == VL53L0X_ERROR_NONE ) { 01432 status |= vl53l0x_get_limit_check_value( dev, i, 01433 &( p_device_parameters->LimitChecksValue [i] ) ); 01434 } else { 01435 break; 01436 } 01437 if ( status == VL53L0X_ERROR_NONE ) { 01438 status |= vl53l0x_get_limit_check_enable( dev, i, 01439 &( p_device_parameters->LimitChecksEnable [i] ) ); 01440 } else { 01441 break; 01442 } 01443 } 01444 } 01445 01446 if ( status == VL53L0X_ERROR_NONE ) { 01447 status = vl53l0x_get_wrap_around_check_enable( dev, 01448 &( p_device_parameters->WrapAroundCheckEnable ) ); 01449 } 01450 01451 /* Need to be done at the end as it uses VCSELPulsePeriod */ 01452 if ( status == VL53L0X_ERROR_NONE ) { 01453 status = vl53l0x_get_measurement_timing_budget_micro_seconds( dev, 01454 &( p_device_parameters->MeasurementTimingBudgetMicroSeconds ) ); 01455 } 01456 01457 LOG_FUNCTION_END( status ); 01458 return status; 01459 } 01460 01461 VL53L0X_Error VL53L0X::vl53l0x_set_limit_check_value( VL53L0X_DEV dev, uint16_t limit_check_id, 01462 FixPoint1616_t limit_check_value ) 01463 { 01464 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01465 uint8_t temp8; 01466 01467 LOG_FUNCTION_START( "" ); 01468 01469 VL53L0X_GETARRAYPARAMETERFIELD( dev, LimitChecksEnable, limit_check_id, 01470 temp8 ); 01471 01472 if ( temp8 == 0 ) { /* disabled write only internal value */ 01473 VL53L0X_SETARRAYPARAMETERFIELD( dev, LimitChecksValue, 01474 limit_check_id, limit_check_value ); 01475 } else { 01476 01477 switch ( limit_check_id ) { 01478 01479 case VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE: 01480 /* internal computation: */ 01481 VL53L0X_SETARRAYPARAMETERFIELD( dev, LimitChecksValue, 01482 VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE, 01483 limit_check_value ); 01484 break; 01485 01486 case VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE: 01487 01488 status = vl53l0x_write_word( dev, 01489 VL53L0X_REG_FINAL_RANGE_CONFIG_MIN_COUNT_RATE_RTN_LIMIT, 01490 VL53L0X_FIXPOINT1616TOFIXPOINT97( 01491 limit_check_value ) ); 01492 01493 break; 01494 01495 case VL53L0X_CHECKENABLE_SIGNAL_REF_CLIP: 01496 01497 /* internal computation: */ 01498 VL53L0X_SETARRAYPARAMETERFIELD( dev, LimitChecksValue, 01499 VL53L0X_CHECKENABLE_SIGNAL_REF_CLIP, 01500 limit_check_value ); 01501 01502 break; 01503 01504 case VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD: 01505 01506 /* internal computation: */ 01507 VL53L0X_SETARRAYPARAMETERFIELD( dev, LimitChecksValue, 01508 VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD, 01509 limit_check_value ); 01510 01511 break; 01512 01513 case VL53L0X_CHECKENABLE_SIGNAL_RATE_MSRC: 01514 case VL53L0X_CHECKENABLE_SIGNAL_RATE_PRE_RANGE: 01515 01516 status = vl53l0x_write_word( dev, 01517 VL53L0X_REG_PRE_RANGE_MIN_COUNT_RATE_RTN_LIMIT, 01518 VL53L0X_FIXPOINT1616TOFIXPOINT97( 01519 limit_check_value ) ); 01520 01521 break; 01522 01523 default: 01524 status = VL53L0X_ERROR_INVALID_PARAMS; 01525 01526 } 01527 01528 if ( status == VL53L0X_ERROR_NONE ) { 01529 VL53L0X_SETARRAYPARAMETERFIELD( dev, LimitChecksValue, 01530 limit_check_id, limit_check_value ); 01531 } 01532 } 01533 01534 LOG_FUNCTION_END( status ); 01535 return status; 01536 } 01537 01538 VL53L0X_Error VL53L0X::vl53l0x_data_init( VL53L0X_DEV dev ) 01539 { 01540 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01541 VL53L0X_DeviceParameters_t CurrentParameters; 01542 int i; 01543 uint8_t StopVariable; 01544 01545 LOG_FUNCTION_START( "" ); 01546 01547 /* by default the I2C is running at 1V8 if you want to change it you 01548 * need to include this define at compilation level. */ 01549 #ifdef USE_I2C_2V8 01550 Status = vl53l0x_update_word( Dev, 01551 VL53L0X_REG_VHV_CONFIG_PAD_SCL_SDA__EXTSUP_HV, 01552 0xFE, 01553 0x01 ); 01554 #endif 01555 01556 /* Set I2C standard mode */ 01557 if ( status == VL53L0X_ERROR_NONE ) 01558 status = vl53l0x_write_byte( dev, 0x88, 0x00 ); 01559 01560 VL53L0X_SETDEVICESPECIFICPARAMETER( dev, ReadDataFromDeviceDone, 0 ); 01561 01562 #ifdef USE_IQC_STATION 01563 if ( Status == VL53L0X_ERROR_NONE ) 01564 Status = VL53L0X_apply_offset_adjustment( Dev ); 01565 #endif 01566 01567 /* Default value is 1000 for Linearity Corrective Gain */ 01568 PALDevDataSet( dev, LinearityCorrectiveGain, 1000 ); 01569 01570 /* Dmax default Parameter */ 01571 PALDevDataSet( dev, DmaxCalRangeMilliMeter, 400 ); 01572 PALDevDataSet( dev, DmaxCalSignalRateRtnMegaCps, 01573 ( FixPoint1616_t )( ( 0x00016B85 ) ) ); /* 1.42 No Cover Glass*/ 01574 01575 /* Set Default static parameters 01576 *set first temporary values 9.44MHz * 65536 = 618660 */ 01577 VL53L0X_SETDEVICESPECIFICPARAMETER( dev, OscFrequencyMHz, 618660 ); 01578 01579 /* Set Default XTalkCompensationRateMegaCps to 0 */ 01580 VL53L0X_SETPARAMETERFIELD( dev, XTalkCompensationRateMegaCps, 0 ); 01581 01582 /* Get default parameters */ 01583 status = vl53l0x_get_device_parameters( dev, &CurrentParameters ); 01584 if ( status == VL53L0X_ERROR_NONE ) { 01585 /* initialize PAL values */ 01586 CurrentParameters.DeviceMode = VL53L0X_DEVICEMODE_SINGLE_RANGING; 01587 CurrentParameters.HistogramMode = VL53L0X_HISTOGRAMMODE_DISABLED; 01588 PALDevDataSet( dev, CurrentParameters, CurrentParameters ); 01589 } 01590 01591 /* Sigma estimator variable */ 01592 PALDevDataSet( dev, SigmaEstRefArray, 100 ); 01593 PALDevDataSet( dev, SigmaEstEffPulseWidth, 900 ); 01594 PALDevDataSet( dev, SigmaEstEffAmbWidth, 500 ); 01595 PALDevDataSet( dev, targetRefRate, 0x0A00 ); /* 20 MCPS in 9:7 format */ 01596 01597 /* Use internal default settings */ 01598 PALDevDataSet( dev, UseInternalTuningSettings, 1 ); 01599 01600 status |= vl53l0x_write_byte( dev, 0x80, 0x01 ); 01601 status |= vl53l0x_write_byte( dev, 0xFF, 0x01 ); 01602 status |= vl53l0x_write_byte( dev, 0x00, 0x00 ); 01603 status |= vl53l0x_read_byte( dev, 0x91, &StopVariable ); 01604 PALDevDataSet( dev, StopVariable, StopVariable ); 01605 status |= vl53l0x_write_byte( dev, 0x00, 0x01 ); 01606 status |= vl53l0x_write_byte( dev, 0xFF, 0x00 ); 01607 status |= vl53l0x_write_byte( dev, 0x80, 0x00 ); 01608 01609 /* Enable all check */ 01610 for ( i = 0; i < VL53L0X_CHECKENABLE_NUMBER_OF_CHECKS; i++ ) { 01611 if ( status == VL53L0X_ERROR_NONE ) 01612 status |= vl53l0x_set_limit_check_enable( dev, i, 1 ); 01613 else 01614 break; 01615 01616 } 01617 01618 /* Disable the following checks */ 01619 if ( status == VL53L0X_ERROR_NONE ) 01620 status = vl53l0x_set_limit_check_enable( dev, 01621 VL53L0X_CHECKENABLE_SIGNAL_REF_CLIP, 0 ); 01622 01623 if ( status == VL53L0X_ERROR_NONE ) 01624 status = vl53l0x_set_limit_check_enable( dev, 01625 VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD, 0 ); 01626 01627 if ( status == VL53L0X_ERROR_NONE ) 01628 status = vl53l0x_set_limit_check_enable( dev, 01629 VL53L0X_CHECKENABLE_SIGNAL_RATE_MSRC, 0 ); 01630 01631 if ( status == VL53L0X_ERROR_NONE ) 01632 status = vl53l0x_set_limit_check_enable( dev, 01633 VL53L0X_CHECKENABLE_SIGNAL_RATE_PRE_RANGE, 0 ); 01634 01635 /* Limit default values */ 01636 if ( status == VL53L0X_ERROR_NONE ) { 01637 status = vl53l0x_set_limit_check_value( dev, 01638 VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE, 01639 ( FixPoint1616_t )( 18 * 65536 ) ); 01640 } 01641 if ( status == VL53L0X_ERROR_NONE ) { 01642 status = vl53l0x_set_limit_check_value( dev, 01643 VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE, 01644 ( FixPoint1616_t )( 25 * 65536 / 100 ) ); 01645 /* 0.25 * 65536 */ 01646 } 01647 01648 if ( status == VL53L0X_ERROR_NONE ) { 01649 status = vl53l0x_set_limit_check_value( dev, 01650 VL53L0X_CHECKENABLE_SIGNAL_REF_CLIP, 01651 ( FixPoint1616_t )( 35 * 65536 ) ); 01652 } 01653 01654 if ( status == VL53L0X_ERROR_NONE ) { 01655 status = vl53l0x_set_limit_check_value( dev, 01656 VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD, 01657 ( FixPoint1616_t )( 0 * 65536 ) ); 01658 } 01659 01660 if ( status == VL53L0X_ERROR_NONE ) { 01661 01662 PALDevDataSet( dev, SequenceConfig, 0xFF ); 01663 status = vl53l0x_write_byte( dev, VL53L0X_REG_SYSTEM_SEQUENCE_CONFIG, 01664 0xFF ); 01665 01666 /* Set PAL state to tell that we are waiting for call to 01667 * VL53L0X_StaticInit */ 01668 PALDevDataSet( dev, PalState, VL53L0X_STATE_WAIT_STATICINIT ); 01669 } 01670 01671 if ( status == VL53L0X_ERROR_NONE ) 01672 VL53L0X_SETDEVICESPECIFICPARAMETER( dev, RefSpadsInitialised, 0 ); 01673 01674 01675 LOG_FUNCTION_END( status ); 01676 return status; 01677 } 01678 01679 VL53L0X_Error VL53L0X::vl53l0x_check_part_used( VL53L0X_DEV dev, 01680 uint8_t *revision, 01681 VL53L0X_DeviceInfo_t *p_vl53l0x_device_info ) 01682 { 01683 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01684 uint8_t module_id_int; 01685 char *product_id_tmp; 01686 01687 LOG_FUNCTION_START( "" ); 01688 01689 status = vl53l0x_get_info_from_device( dev, 2 ); 01690 01691 if ( status == VL53L0X_ERROR_NONE ) { 01692 module_id_int = VL53L0X_GETDEVICESPECIFICPARAMETER( dev, ModuleId ); 01693 01694 if ( module_id_int == 0 ) { 01695 *revision = 0; 01696 VL53L0X_COPYSTRING( p_vl53l0x_device_info->ProductId , "" ); 01697 } else { 01698 *revision = VL53L0X_GETDEVICESPECIFICPARAMETER( dev, Revision ); 01699 product_id_tmp = VL53L0X_GETDEVICESPECIFICPARAMETER( dev, 01700 ProductId ); 01701 VL53L0X_COPYSTRING( p_vl53l0x_device_info->ProductId , product_id_tmp ); 01702 } 01703 } 01704 01705 LOG_FUNCTION_END( status ); 01706 return status; 01707 } 01708 01709 VL53L0X_Error VL53L0X::wrapped_vl53l0x_get_device_info( VL53L0X_DEV dev, 01710 VL53L0X_DeviceInfo_t *p_vl53l0x_device_info ) 01711 { 01712 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01713 uint8_t revision_id; 01714 uint8_t revision; 01715 01716 status = vl53l0x_check_part_used( dev, &revision, p_vl53l0x_device_info ); 01717 01718 if ( status == VL53L0X_ERROR_NONE ) { 01719 if ( revision == 0 ) { 01720 VL53L0X_COPYSTRING( p_vl53l0x_device_info->Name , 01721 VL53L0X_STRING_DEVICE_INFO_NAME_TS0 ); 01722 } else if ( ( revision <= 34 ) && ( revision != 32 ) ) { 01723 VL53L0X_COPYSTRING( p_vl53l0x_device_info->Name , 01724 VL53L0X_STRING_DEVICE_INFO_NAME_TS1 ); 01725 } else if ( revision < 39 ) { 01726 VL53L0X_COPYSTRING( p_vl53l0x_device_info->Name , 01727 VL53L0X_STRING_DEVICE_INFO_NAME_TS2 ); 01728 } else { 01729 VL53L0X_COPYSTRING( p_vl53l0x_device_info->Name , 01730 VL53L0X_STRING_DEVICE_INFO_NAME_ES1 ); 01731 } 01732 01733 VL53L0X_COPYSTRING( p_vl53l0x_device_info->Type , 01734 VL53L0X_STRING_DEVICE_INFO_TYPE ); 01735 01736 } 01737 01738 if ( status == VL53L0X_ERROR_NONE ) { 01739 status = vl53l0x_read_byte( dev, VL53L0X_REG_IDENTIFICATION_MODEL_ID, 01740 &p_vl53l0x_device_info->ProductType ); 01741 } 01742 01743 if ( status == VL53L0X_ERROR_NONE ) { 01744 status = vl53l0x_read_byte( dev, 01745 VL53L0X_REG_IDENTIFICATION_REVISION_ID, 01746 &revision_id ); 01747 p_vl53l0x_device_info->ProductRevisionMajor = 1; 01748 p_vl53l0x_device_info->ProductRevisionMinor = 01749 ( revision_id & 0xF0 ) >> 4; 01750 } 01751 01752 return status; 01753 } 01754 01755 VL53L0X_Error VL53L0X::vl53l0x_get_device_info( VL53L0X_DEV dev, 01756 VL53L0X_DeviceInfo_t *p_vl53l0x_device_info ) 01757 { 01758 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01759 LOG_FUNCTION_START( "" ); 01760 01761 status = wrapped_vl53l0x_get_device_info( dev, p_vl53l0x_device_info ); 01762 01763 LOG_FUNCTION_END( status ); 01764 return status; 01765 } 01766 01767 VL53L0X_Error VL53L0X::vl53l0x_get_interrupt_mask_status( VL53L0X_DEV dev, 01768 uint32_t *p_interrupt_mask_status ) 01769 { 01770 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01771 uint8_t byte; 01772 LOG_FUNCTION_START( "" ); 01773 01774 status = vl53l0x_read_byte( dev, VL53L0X_REG_RESULT_INTERRUPT_STATUS, &byte ); 01775 *p_interrupt_mask_status = byte & 0x07; 01776 01777 if ( byte & 0x18 ) 01778 status = VL53L0X_ERROR_RANGE_ERROR; 01779 01780 LOG_FUNCTION_END( status ); 01781 return status; 01782 } 01783 01784 VL53L0X_Error VL53L0X::vl53l0x_get_measurement_data_ready( VL53L0X_DEV dev, 01785 uint8_t *p_measurement_data_ready ) 01786 { 01787 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01788 uint8_t sys_range_status_register; 01789 uint8_t interrupt_config; 01790 uint32_t interrupt_mask; 01791 LOG_FUNCTION_START( "" ); 01792 01793 interrupt_config = VL53L0X_GETDEVICESPECIFICPARAMETER( dev, 01794 Pin0GpioFunctionality ); 01795 01796 if ( interrupt_config == 01797 VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY ) { 01798 status = vl53l0x_get_interrupt_mask_status( dev, &interrupt_mask ); 01799 if ( interrupt_mask == 01800 VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY ) 01801 *p_measurement_data_ready = 1; 01802 else 01803 *p_measurement_data_ready = 0; 01804 } else { 01805 status = vl53l0x_read_byte( dev, VL53L0X_REG_RESULT_RANGE_STATUS, 01806 &sys_range_status_register ); 01807 if ( status == VL53L0X_ERROR_NONE ) { 01808 if ( sys_range_status_register & 0x01 ) 01809 *p_measurement_data_ready = 1; 01810 else 01811 *p_measurement_data_ready = 0; 01812 } 01813 } 01814 01815 LOG_FUNCTION_END( status ); 01816 return status; 01817 } 01818 01819 VL53L0X_Error VL53L0X::vl53l0x_polling_delay( VL53L0X_DEV dev ) 01820 { 01821 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01822 01823 // do nothing 01824 VL53L0X_OsDelay(); 01825 return status; 01826 } 01827 01828 VL53L0X_Error VL53L0X::vl53l0x_measurement_poll_for_completion( VL53L0X_DEV dev ) 01829 { 01830 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01831 uint8_t new_data_ready = 0; 01832 uint32_t loop_nb; 01833 01834 LOG_FUNCTION_START( "" ); 01835 01836 loop_nb = 0; 01837 01838 do { 01839 status = vl53l0x_get_measurement_data_ready( dev, &new_data_ready ); 01840 if ( status != 0 ) 01841 break; /* the error is set */ 01842 01843 if ( new_data_ready == 1 ) 01844 break; /* done note that status == 0 */ 01845 01846 loop_nb++; 01847 if ( loop_nb >= VL53L0X_DEFAULT_MAX_LOOP ) { 01848 status = VL53L0X_ERROR_TIME_OUT; 01849 break; 01850 } 01851 01852 vl53l0x_polling_delay( dev ); 01853 } while ( 1 ); 01854 01855 LOG_FUNCTION_END( status ); 01856 01857 return status; 01858 } 01859 01860 /* Group PAL Interrupt Functions */ 01861 VL53L0X_Error VL53L0X::vl53l0x_clear_interrupt_mask( VL53L0X_DEV dev, uint32_t interrupt_mask ) 01862 { 01863 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01864 uint8_t loop_count; 01865 uint8_t byte; 01866 LOG_FUNCTION_START( "" ); 01867 01868 /* clear bit 0 range interrupt, bit 1 error interrupt */ 01869 loop_count = 0; 01870 do { 01871 status = vl53l0x_write_byte( dev, 01872 VL53L0X_REG_SYSTEM_INTERRUPT_CLEAR, 0x01 ); 01873 status |= vl53l0x_write_byte( dev, 01874 VL53L0X_REG_SYSTEM_INTERRUPT_CLEAR, 0x00 ); 01875 status |= vl53l0x_read_byte( dev, 01876 VL53L0X_REG_RESULT_INTERRUPT_STATUS, &byte ); 01877 loop_count++; 01878 } while ( ( ( byte & 0x07 ) != 0x00 ) 01879 && ( loop_count < 3 ) 01880 && ( status == VL53L0X_ERROR_NONE ) ); 01881 01882 01883 if ( loop_count >= 3 ) 01884 status = VL53L0X_ERROR_INTERRUPT_NOT_CLEARED; 01885 01886 LOG_FUNCTION_END( status ); 01887 return status; 01888 } 01889 01890 VL53L0X_Error VL53L0X::vl53l0x_perform_single_ref_calibration( VL53L0X_DEV dev, 01891 uint8_t vhv_init_byte ) 01892 { 01893 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01894 01895 if ( status == VL53L0X_ERROR_NONE ) 01896 status = vl53l0x_write_byte( dev, VL53L0X_REG_SYSRANGE_START, 01897 VL53L0X_REG_SYSRANGE_MODE_START_STOP | 01898 vhv_init_byte ); 01899 01900 if ( status == VL53L0X_ERROR_NONE ) 01901 status = vl53l0x_measurement_poll_for_completion( dev ); 01902 01903 if ( status == VL53L0X_ERROR_NONE ) 01904 status = vl53l0x_clear_interrupt_mask( dev, 0 ); 01905 01906 if ( status == VL53L0X_ERROR_NONE ) 01907 status = vl53l0x_write_byte( dev, VL53L0X_REG_SYSRANGE_START, 0x00 ); 01908 01909 return status; 01910 } 01911 01912 VL53L0X_Error VL53L0X::vl53l0x_ref_calibration_io( VL53L0X_DEV dev, uint8_t read_not_write, 01913 uint8_t vhv_settings, uint8_t phase_cal, 01914 uint8_t *p_vhv_settings, uint8_t *p_phase_cal, 01915 const uint8_t vhv_enable, const uint8_t phase_enable ) 01916 { 01917 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01918 uint8_t phase_calint = 0; 01919 01920 /* Read VHV from device */ 01921 status |= vl53l0x_write_byte( dev, 0xFF, 0x01 ); 01922 status |= vl53l0x_write_byte( dev, 0x00, 0x00 ); 01923 status |= vl53l0x_write_byte( dev, 0xFF, 0x00 ); 01924 01925 if ( read_not_write ) { 01926 if ( vhv_enable ) 01927 status |= vl53l0x_read_byte( dev, 0xCB, p_vhv_settings ); 01928 if ( phase_enable ) 01929 status |= vl53l0x_read_byte( dev, 0xEE, &phase_calint ); 01930 } else { 01931 if ( vhv_enable ) 01932 status |= vl53l0x_write_byte( dev, 0xCB, vhv_settings ); 01933 if ( phase_enable ) 01934 status |= vl53l0x_update_byte( dev, 0xEE, 0x80, phase_cal ); 01935 } 01936 01937 status |= vl53l0x_write_byte( dev, 0xFF, 0x01 ); 01938 status |= vl53l0x_write_byte( dev, 0x00, 0x01 ); 01939 status |= vl53l0x_write_byte( dev, 0xFF, 0x00 ); 01940 01941 *p_phase_cal = ( uint8_t )( phase_calint & 0xEF ); 01942 01943 return status; 01944 } 01945 01946 VL53L0X_Error VL53L0X::vl53l0x_perform_vhv_calibration( VL53L0X_DEV dev, 01947 uint8_t *p_vhv_settings, const uint8_t get_data_enable, 01948 const uint8_t restore_config ) 01949 { 01950 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01951 uint8_t sequence_config = 0; 01952 uint8_t vhv_settings = 0; 01953 uint8_t phase_cal = 0; 01954 uint8_t phase_cal_int = 0; 01955 01956 /* store the value of the sequence config, 01957 * this will be reset before the end of the function 01958 */ 01959 01960 if ( restore_config ) 01961 sequence_config = PALDevDataGet( dev, SequenceConfig ); 01962 01963 /* Run VHV */ 01964 status = vl53l0x_write_byte( dev, VL53L0X_REG_SYSTEM_SEQUENCE_CONFIG, 0x01 ); 01965 01966 if ( status == VL53L0X_ERROR_NONE ) 01967 status = vl53l0x_perform_single_ref_calibration( dev, 0x40 ); 01968 01969 /* Read VHV from device */ 01970 if ( ( status == VL53L0X_ERROR_NONE ) && ( get_data_enable == 1 ) ) { 01971 status = vl53l0x_ref_calibration_io( dev, 1, 01972 vhv_settings, phase_cal, /* Not used here */ 01973 p_vhv_settings, &phase_cal_int, 01974 1, 0 ); 01975 } else 01976 *p_vhv_settings = 0; 01977 01978 01979 if ( ( status == VL53L0X_ERROR_NONE ) && restore_config ) { 01980 /* restore the previous Sequence Config */ 01981 status = vl53l0x_write_byte( dev, VL53L0X_REG_SYSTEM_SEQUENCE_CONFIG, 01982 sequence_config ); 01983 if ( status == VL53L0X_ERROR_NONE ) 01984 PALDevDataSet( dev, SequenceConfig, sequence_config ); 01985 01986 } 01987 01988 return status; 01989 } 01990 01991 VL53L0X_Error VL53L0X::vl53l0x_perform_phase_calibration( VL53L0X_DEV dev, 01992 uint8_t *p_phase_cal, const uint8_t get_data_enable, 01993 const uint8_t restore_config ) 01994 { 01995 VL53L0X_Error status = VL53L0X_ERROR_NONE; 01996 uint8_t sequence_config = 0; 01997 uint8_t vhv_settings = 0; 01998 uint8_t phase_cal = 0; 01999 uint8_t vhv_settingsint; 02000 02001 /* store the value of the sequence config, 02002 * this will be reset before the end of the function 02003 */ 02004 02005 if ( restore_config ) 02006 sequence_config = PALDevDataGet( dev, SequenceConfig ); 02007 02008 /* Run PhaseCal */ 02009 status = vl53l0x_write_byte( dev, VL53L0X_REG_SYSTEM_SEQUENCE_CONFIG, 0x02 ); 02010 02011 if ( status == VL53L0X_ERROR_NONE ) 02012 status = vl53l0x_perform_single_ref_calibration( dev, 0x0 ); 02013 02014 /* Read PhaseCal from device */ 02015 if ( ( status == VL53L0X_ERROR_NONE ) && ( get_data_enable == 1 ) ) { 02016 status = vl53l0x_ref_calibration_io( dev, 1, 02017 vhv_settings, phase_cal, /* Not used here */ 02018 &vhv_settingsint, p_phase_cal, 02019 0, 1 ); 02020 } else 02021 *p_phase_cal = 0; 02022 02023 02024 if ( ( status == VL53L0X_ERROR_NONE ) && restore_config ) { 02025 /* restore the previous Sequence Config */ 02026 status = vl53l0x_write_byte( dev, VL53L0X_REG_SYSTEM_SEQUENCE_CONFIG, 02027 sequence_config ); 02028 if ( status == VL53L0X_ERROR_NONE ) 02029 PALDevDataSet( dev, SequenceConfig, sequence_config ); 02030 02031 } 02032 02033 return status; 02034 } 02035 02036 VL53L0X_Error VL53L0X::vl53l0x_perform_ref_calibration( VL53L0X_DEV dev, 02037 uint8_t *p_vhv_settings, uint8_t *p_phase_cal, uint8_t get_data_enable ) 02038 { 02039 VL53L0X_Error status = VL53L0X_ERROR_NONE; 02040 uint8_t sequence_config = 0; 02041 02042 /* store the value of the sequence config, 02043 * this will be reset before the end of the function 02044 */ 02045 02046 sequence_config = PALDevDataGet( dev, SequenceConfig ); 02047 02048 /* In the following function we don't save the config to optimize 02049 * writes on device. Config is saved and restored only once. */ 02050 status = vl53l0x_perform_vhv_calibration( 02051 dev, p_vhv_settings, get_data_enable, 0 ); 02052 02053 02054 if ( status == VL53L0X_ERROR_NONE ) 02055 status = vl53l0x_perform_phase_calibration( 02056 dev, p_phase_cal, get_data_enable, 0 ); 02057 02058 02059 if ( status == VL53L0X_ERROR_NONE ) { 02060 /* restore the previous Sequence Config */ 02061 status = vl53l0x_write_byte( dev, VL53L0X_REG_SYSTEM_SEQUENCE_CONFIG, 02062 sequence_config ); 02063 if ( status == VL53L0X_ERROR_NONE ) 02064 PALDevDataSet( dev, SequenceConfig, sequence_config ); 02065 02066 } 02067 02068 return status; 02069 } 02070 02071 void VL53L0X::get_next_good_spad( uint8_t good_spad_array[], uint32_t size, 02072 uint32_t curr, int32_t *p_next ) 02073 { 02074 uint32_t start_index; 02075 uint32_t fine_offset; 02076 uint32_t c_spads_per_byte = 8; 02077 uint32_t coarse_index; 02078 uint32_t fine_index; 02079 uint8_t data_byte; 02080 uint8_t success = 0; 02081 02082 /* 02083 * Starting with the current good spad, loop through the array to find 02084 * the next. i.e. the next bit set in the sequence. 02085 * 02086 * The coarse index is the byte index of the array and the fine index is 02087 * the index of the bit within each byte. 02088 */ 02089 02090 *p_next = -1; 02091 02092 start_index = curr / c_spads_per_byte; 02093 fine_offset = curr % c_spads_per_byte; 02094 02095 for ( coarse_index = start_index; ( ( coarse_index < size ) && !success ); 02096 coarse_index++ ) { 02097 fine_index = 0; 02098 data_byte = good_spad_array[coarse_index]; 02099 02100 if ( coarse_index == start_index ) { 02101 /* locate the bit position of the provided current 02102 * spad bit before iterating */ 02103 data_byte >>= fine_offset; 02104 fine_index = fine_offset; 02105 } 02106 02107 while ( fine_index < c_spads_per_byte ) { 02108 if ( ( data_byte & 0x1 ) == 1 ) { 02109 success = 1; 02110 *p_next = coarse_index * c_spads_per_byte + fine_index; 02111 break; 02112 } 02113 data_byte >>= 1; 02114 fine_index++; 02115 } 02116 } 02117 } 02118 02119 uint8_t VL53L0X::is_aperture( uint32_t spad_index ) 02120 { 02121 /* 02122 * This function reports if a given spad index is an aperture SPAD by 02123 * deriving the quadrant. 02124 */ 02125 uint32_t quadrant; 02126 uint8_t is_aperture = 1; 02127 quadrant = spad_index >> 6; 02128 if ( refArrayQuadrants[quadrant] == REF_ARRAY_SPAD_0 ) 02129 is_aperture = 0; 02130 02131 return is_aperture; 02132 } 02133 02134 VL53L0X_Error VL53L0X::enable_spad_bit( uint8_t spad_array[], uint32_t size, 02135 uint32_t spad_index ) 02136 { 02137 VL53L0X_Error status = VL53L0X_ERROR_NONE; 02138 uint32_t c_spads_per_byte = 8; 02139 uint32_t coarse_index; 02140 uint32_t fine_index; 02141 02142 coarse_index = spad_index / c_spads_per_byte; 02143 fine_index = spad_index % c_spads_per_byte; 02144 if ( coarse_index >= size ) 02145 status = VL53L0X_ERROR_REF_SPAD_INIT; 02146 else 02147 spad_array[coarse_index] |= ( 1 << fine_index ); 02148 02149 return status; 02150 } 02151 02152 VL53L0X_Error VL53L0X::set_ref_spad_map( VL53L0X_DEV dev, uint8_t *p_ref_spad_array ) 02153 { 02154 VL53L0X_Error status = vl53l0x_write_multi( dev, 02155 VL53L0X_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_0, 02156 p_ref_spad_array, 6 ); 02157 02158 return status; 02159 } 02160 02161 VL53L0X_Error VL53L0X::get_ref_spad_map( VL53L0X_DEV dev, uint8_t *p_ref_spad_array ) 02162 { 02163 VL53L0X_Error status = vl53l0x_read_multi( dev, 02164 VL53L0X_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_0, 02165 p_ref_spad_array, 02166 6 ); 02167 // VL53L0X_Error status = VL53L0X_ERROR_NONE; 02168 // uint8_t count=0; 02169 02170 // for (count = 0; count < 6; count++) 02171 // status = vl53l0x_read_byte(Dev, (VL53L0X_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_0 + count), &refSpadArray[count]); 02172 return status; 02173 } 02174 02175 VL53L0X_Error VL53L0X::enable_ref_spads( VL53L0X_DEV dev, 02176 uint8_t aperture_spads, 02177 uint8_t good_spad_array[], 02178 uint8_t spad_array[], 02179 uint32_t size, 02180 uint32_t start, 02181 uint32_t offset, 02182 uint32_t spad_count, 02183 uint32_t *p_last_spad ) 02184 { 02185 VL53L0X_Error status = VL53L0X_ERROR_NONE; 02186 uint32_t index; 02187 uint32_t i; 02188 int32_t next_good_spad = offset; 02189 uint32_t current_spad; 02190 uint8_t check_spad_array[6]; 02191 02192 /* 02193 * This function takes in a spad array which may or may not have SPADS 02194 * already enabled and appends from a given offset a requested number 02195 * of new SPAD enables. The 'good spad map' is applied to 02196 * determine the next SPADs to enable. 02197 * 02198 * This function applies to only aperture or only non-aperture spads. 02199 * Checks are performed to ensure this. 02200 */ 02201 02202 current_spad = offset; 02203 for ( index = 0; index < spad_count; index++ ) { 02204 get_next_good_spad( good_spad_array, size, current_spad, 02205 &next_good_spad ); 02206 02207 if ( next_good_spad == -1 ) { 02208 status = VL53L0X_ERROR_REF_SPAD_INIT; 02209 break; 02210 } 02211 02212 /* Confirm that the next good SPAD is non-aperture */ 02213 if ( is_aperture( start + next_good_spad ) != aperture_spads ) { 02214 /* if we can't get the required number of good aperture 02215 * spads from the current quadrant then this is an error 02216 */ 02217 status = VL53L0X_ERROR_REF_SPAD_INIT; 02218 break; 02219 } 02220 current_spad = ( uint32_t )next_good_spad; 02221 enable_spad_bit( spad_array, size, current_spad ); 02222 current_spad++; 02223 } 02224 *p_last_spad = current_spad; 02225 02226 if ( status == VL53L0X_ERROR_NONE ) 02227 status = set_ref_spad_map( dev, spad_array ); 02228 02229 02230 if ( status == VL53L0X_ERROR_NONE ) { 02231 status = get_ref_spad_map( dev, check_spad_array ); 02232 02233 i = 0; 02234 02235 /* Compare spad maps. If not equal report error. */ 02236 while ( i < size ) { 02237 if ( spad_array[i] != check_spad_array[i] ) { 02238 status = VL53L0X_ERROR_REF_SPAD_INIT; 02239 break; 02240 } 02241 i++; 02242 } 02243 } 02244 return status; 02245 } 02246 02247 VL53L0X_Error VL53L0X::vl53l0x_set_device_mode( VL53L0X_DEV dev, VL53L0X_DeviceModes device_mode ) 02248 { 02249 VL53L0X_Error status = VL53L0X_ERROR_NONE; 02250 02251 LOG_FUNCTION_START( "%d", ( int )DeviceMode ); 02252 02253 switch ( device_mode ) { 02254 case VL53L0X_DEVICEMODE_SINGLE_RANGING: 02255 case VL53L0X_DEVICEMODE_CONTINUOUS_RANGING: 02256 case VL53L0X_DEVICEMODE_CONTINUOUS_TIMED_RANGING: 02257 case VL53L0X_DEVICEMODE_GPIO_DRIVE: 02258 case VL53L0X_DEVICEMODE_GPIO_OSC: 02259 /* Supported modes */ 02260 VL53L0X_SETPARAMETERFIELD( dev, DeviceMode, device_mode ); 02261 break; 02262 default: 02263 /* Unsupported mode */ 02264 status = VL53L0X_ERROR_MODE_NOT_SUPPORTED; 02265 } 02266 02267 LOG_FUNCTION_END( status ); 02268 return status; 02269 } 02270 02271 VL53L0X_Error VL53L0X::vl53l0x_set_interrupt_thresholds( VL53L0X_DEV dev, 02272 VL53L0X_DeviceModes device_mode, FixPoint1616_t threshold_low, 02273 FixPoint1616_t threshold_high ) 02274 { 02275 VL53L0X_Error status = VL53L0X_ERROR_NONE; 02276 uint16_t threshold16; 02277 LOG_FUNCTION_START( "" ); 02278 02279 /* no dependency on DeviceMode for Ewok */ 02280 /* Need to divide by 2 because the FW will apply a x2 */ 02281 threshold16 = ( uint16_t )( ( threshold_low >> 17 ) & 0x00fff ); 02282 status = vl53l0x_write_word( dev, VL53L0X_REG_SYSTEM_THRESH_LOW, threshold16 ); 02283 02284 if ( status == VL53L0X_ERROR_NONE ) { 02285 /* Need to divide by 2 because the FW will apply a x2 */ 02286 threshold16 = ( uint16_t )( ( threshold_high >> 17 ) & 0x00fff ); 02287 status = vl53l0x_write_word( dev, VL53L0X_REG_SYSTEM_THRESH_HIGH, 02288 threshold16 ); 02289 } 02290 02291 LOG_FUNCTION_END( status ); 02292 return status; 02293 } 02294 02295 VL53L0X_Error VL53L0X::vl53l0x_get_interrupt_thresholds( VL53L0X_DEV dev, 02296 VL53L0X_DeviceModes device_mode, FixPoint1616_t *p_threshold_low, 02297 FixPoint1616_t *p_threshold_high ) 02298 { 02299 VL53L0X_Error status = VL53L0X_ERROR_NONE; 02300 uint16_t threshold16; 02301 LOG_FUNCTION_START( "" ); 02302 02303 /* no dependency on DeviceMode for Ewok */ 02304 02305 status = vl53l0x_read_word( dev, VL53L0X_REG_SYSTEM_THRESH_LOW, &threshold16 ); 02306 /* Need to multiply by 2 because the FW will apply a x2 */ 02307 *p_threshold_low = ( FixPoint1616_t )( ( 0x00fff & threshold16 ) << 17 ); 02308 02309 if ( status == VL53L0X_ERROR_NONE ) { 02310 status = vl53l0x_read_word( dev, VL53L0X_REG_SYSTEM_THRESH_HIGH, 02311 &threshold16 ); 02312 /* Need to multiply by 2 because the FW will apply a x2 */ 02313 *p_threshold_high = 02314 ( FixPoint1616_t )( ( 0x00fff & threshold16 ) << 17 ); 02315 } 02316 02317 LOG_FUNCTION_END( status ); 02318 return status; 02319 } 02320 02321 VL53L0X_Error VL53L0X::vl53l0x_load_tuning_settings( VL53L0X_DEV dev, 02322 uint8_t *p_tuning_setting_buffer ) 02323 { 02324 VL53L0X_Error status = VL53L0X_ERROR_NONE; 02325 int i; 02326 int index; 02327 uint8_t msb; 02328 uint8_t lsb; 02329 uint8_t select_param; 02330 uint8_t number_of_writes; 02331 uint8_t address; 02332 uint8_t local_buffer[4]; /* max */ 02333 uint16_t temp16; 02334 02335 LOG_FUNCTION_START( "" ); 02336 02337 index = 0; 02338 02339 while ( ( *( p_tuning_setting_buffer + index ) != 0 ) && 02340 ( status == VL53L0X_ERROR_NONE ) ) { 02341 number_of_writes = *( p_tuning_setting_buffer + index ); 02342 index++; 02343 if ( number_of_writes == 0xFF ) { 02344 /* internal parameters */ 02345 select_param = *( p_tuning_setting_buffer + index ); 02346 index++; 02347 switch ( select_param ) { 02348 case 0: /* uint16_t SigmaEstRefArray -> 2 bytes */ 02349 msb = *( p_tuning_setting_buffer + index ); 02350 index++; 02351 lsb = *( p_tuning_setting_buffer + index ); 02352 index++; 02353 temp16 = VL53L0X_MAKEUINT16( lsb, msb ); 02354 PALDevDataSet( dev, SigmaEstRefArray, temp16 ); 02355 break; 02356 case 1: /* uint16_t SigmaEstEffPulseWidth -> 2 bytes */ 02357 msb = *( p_tuning_setting_buffer + index ); 02358 index++; 02359 lsb = *( p_tuning_setting_buffer + index ); 02360 index++; 02361 temp16 = VL53L0X_MAKEUINT16( lsb, msb ); 02362 PALDevDataSet( dev, SigmaEstEffPulseWidth, 02363 temp16 ); 02364 break; 02365 case 2: /* uint16_t SigmaEstEffAmbWidth -> 2 bytes */ 02366 msb = *( p_tuning_setting_buffer + index ); 02367 index++; 02368 lsb = *( p_tuning_setting_buffer + index ); 02369 index++; 02370 temp16 = VL53L0X_MAKEUINT16( lsb, msb ); 02371 PALDevDataSet( dev, SigmaEstEffAmbWidth, temp16 ); 02372 break; 02373 case 3: /* uint16_t targetRefRate -> 2 bytes */ 02374 msb = *( p_tuning_setting_buffer + index ); 02375 index++; 02376 lsb = *( p_tuning_setting_buffer + index ); 02377 index++; 02378 temp16 = VL53L0X_MAKEUINT16( lsb, msb ); 02379 PALDevDataSet( dev, targetRefRate, temp16 ); 02380 break; 02381 default: /* invalid parameter */ 02382 status = VL53L0X_ERROR_INVALID_PARAMS; 02383 } 02384 02385 } else if ( number_of_writes <= 4 ) { 02386 address = *( p_tuning_setting_buffer + index ); 02387 index++; 02388 02389 for ( i = 0; i < number_of_writes; i++ ) { 02390 local_buffer[i] = *( p_tuning_setting_buffer + 02391 index ); 02392 index++; 02393 } 02394 02395 status = vl53l0x_write_multi( dev, address, local_buffer, 02396 number_of_writes ); 02397 02398 } else { 02399 status = VL53L0X_ERROR_INVALID_PARAMS; 02400 } 02401 } 02402 02403 LOG_FUNCTION_END( status ); 02404 return status; 02405 } 02406 02407 VL53L0X_Error VL53L0X::vl53l0x_check_and_load_interrupt_settings( VL53L0X_DEV dev, 02408 uint8_t start_not_stopflag ) 02409 { 02410 uint8_t interrupt_config; 02411 FixPoint1616_t threshold_low; 02412 FixPoint1616_t threshold_high; 02413 VL53L0X_Error status = VL53L0X_ERROR_NONE; 02414 02415 interrupt_config = VL53L0X_GETDEVICESPECIFICPARAMETER( dev, 02416 Pin0GpioFunctionality ); 02417 02418 if ( ( interrupt_config == 02419 VL53L0X_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_LOW ) || 02420 ( interrupt_config == 02421 VL53L0X_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_HIGH ) || 02422 ( interrupt_config == 02423 VL53L0X_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_OUT ) ) { 02424 02425 status = vl53l0x_get_interrupt_thresholds( dev, 02426 VL53L0X_DEVICEMODE_CONTINUOUS_RANGING, 02427 &threshold_low, &threshold_high ); 02428 02429 if ( ( ( threshold_low > 255 * 65536 ) || 02430 ( threshold_high > 255 * 65536 ) ) && 02431 ( status == VL53L0X_ERROR_NONE ) ) { 02432 02433 if ( start_not_stopflag != 0 ) { 02434 status = vl53l0x_load_tuning_settings( dev, 02435 InterruptThresholdSettings ); 02436 } else { 02437 status |= vl53l0x_write_byte( dev, 0xFF, 0x04 ); 02438 status |= vl53l0x_write_byte( dev, 0x70, 0x00 ); 02439 status |= vl53l0x_write_byte( dev, 0xFF, 0x00 ); 02440 status |= vl53l0x_write_byte( dev, 0x80, 0x00 ); 02441 } 02442 02443 } 02444 02445 02446 } 02447 02448 return status; 02449 02450 } 02451 02452 VL53L0X_Error VL53L0X::vl53l0x_start_measurement( VL53L0X_DEV dev ) 02453 { 02454 VL53L0X_Error status = VL53L0X_ERROR_NONE; 02455 VL53L0X_DeviceModes device_mode; 02456 uint8_t byte; 02457 uint8_t start_stop_byte = VL53L0X_REG_SYSRANGE_MODE_START_STOP; 02458 uint32_t loop_nb; 02459 LOG_FUNCTION_START( "" ); 02460 02461 /* Get Current DeviceMode */ 02462 vl53l0x_get_device_mode( dev, &device_mode ); 02463 02464 status = vl53l0x_write_byte( dev, 0x80, 0x01 ); 02465 status = vl53l0x_write_byte( dev, 0xFF, 0x01 ); 02466 status = vl53l0x_write_byte( dev, 0x00, 0x00 ); 02467 status = vl53l0x_write_byte( dev, 0x91, PALDevDataGet( dev, StopVariable ) ); 02468 status = vl53l0x_write_byte( dev, 0x00, 0x01 ); 02469 status = vl53l0x_write_byte( dev, 0xFF, 0x00 ); 02470 status = vl53l0x_write_byte( dev, 0x80, 0x00 ); 02471 02472 switch ( device_mode ) { 02473 case VL53L0X_DEVICEMODE_SINGLE_RANGING: 02474 status = vl53l0x_write_byte( dev, VL53L0X_REG_SYSRANGE_START, 0x01 ); 02475 02476 byte = start_stop_byte; 02477 if ( status == VL53L0X_ERROR_NONE ) { 02478 /* Wait until start bit has been cleared */ 02479 loop_nb = 0; 02480 do { 02481 if ( loop_nb > 0 ) 02482 status = vl53l0x_read_byte( dev, 02483 VL53L0X_REG_SYSRANGE_START, &byte ); 02484 loop_nb = loop_nb + 1; 02485 } while ( ( ( byte & start_stop_byte ) == start_stop_byte ) 02486 && ( status == VL53L0X_ERROR_NONE ) 02487 && ( loop_nb < VL53L0X_DEFAULT_MAX_LOOP ) ); 02488 02489 if ( loop_nb >= VL53L0X_DEFAULT_MAX_LOOP ) 02490 status = VL53L0X_ERROR_TIME_OUT; 02491 02492 } 02493 02494 break; 02495 case VL53L0X_DEVICEMODE_CONTINUOUS_RANGING: 02496 /* Back-to-back mode */ 02497 02498 /* Check if need to apply interrupt settings */ 02499 if ( status == VL53L0X_ERROR_NONE ) 02500 status = vl53l0x_check_and_load_interrupt_settings( dev, 1 ); 02501 02502 status = vl53l0x_write_byte( dev, 02503 VL53L0X_REG_SYSRANGE_START, 02504 VL53L0X_REG_SYSRANGE_MODE_BACKTOBACK ); 02505 if ( status == VL53L0X_ERROR_NONE ) { 02506 /* Set PAL State to Running */ 02507 PALDevDataSet( dev, PalState, VL53L0X_STATE_RUNNING ); 02508 } 02509 break; 02510 case VL53L0X_DEVICEMODE_CONTINUOUS_TIMED_RANGING: 02511 /* Continuous mode */ 02512 /* Check if need to apply interrupt settings */ 02513 if ( status == VL53L0X_ERROR_NONE ) 02514 status = vl53l0x_check_and_load_interrupt_settings( dev, 1 ); 02515 02516 status = vl53l0x_write_byte( dev, 02517 VL53L0X_REG_SYSRANGE_START, 02518 VL53L0X_REG_SYSRANGE_MODE_TIMED ); 02519 02520 if ( status == VL53L0X_ERROR_NONE ) { 02521 /* Set PAL State to Running */ 02522 PALDevDataSet( dev, PalState, VL53L0X_STATE_RUNNING ); 02523 } 02524 break; 02525 default: 02526 /* Selected mode not supported */ 02527 status = VL53L0X_ERROR_MODE_NOT_SUPPORTED; 02528 } 02529 02530 02531 LOG_FUNCTION_END( status ); 02532 return status; 02533 } 02534 02535 /* Group PAL Measurement Functions */ 02536 VL53L0X_Error VL53L0X::vl53l0x_perform_single_measurement( VL53L0X_DEV dev ) 02537 { 02538 VL53L0X_Error status = VL53L0X_ERROR_NONE; 02539 VL53L0X_DeviceModes device_mode; 02540 02541 LOG_FUNCTION_START( "" ); 02542 02543 /* Get Current DeviceMode */ 02544 status = vl53l0x_get_device_mode( dev, &device_mode ); 02545 02546 /* Start immediately to run a single ranging measurement in case of 02547 * single ranging or single histogram */ 02548 if ( status == VL53L0X_ERROR_NONE 02549 && device_mode == VL53L0X_DEVICEMODE_SINGLE_RANGING ) 02550 status = vl53l0x_start_measurement( dev ); 02551 02552 02553 if ( status == VL53L0X_ERROR_NONE ) 02554 status = vl53l0x_measurement_poll_for_completion( dev ); 02555 02556 02557 /* Change PAL State in case of single ranging or single histogram */ 02558 if ( status == VL53L0X_ERROR_NONE 02559 && device_mode == VL53L0X_DEVICEMODE_SINGLE_RANGING ) 02560 PALDevDataSet( dev, PalState, VL53L0X_STATE_IDLE ); 02561 02562 02563 LOG_FUNCTION_END( status ); 02564 return status; 02565 } 02566 02567 VL53L0X_Error VL53L0X::vl53l0x_get_x_talk_compensation_enable( VL53L0X_DEV dev, 02568 uint8_t *p_x_talk_compensation_enable ) 02569 { 02570 VL53L0X_Error status = VL53L0X_ERROR_NONE; 02571 uint8_t temp8; 02572 LOG_FUNCTION_START( "" ); 02573 02574 VL53L0X_GETPARAMETERFIELD( dev, XTalkCompensationEnable, temp8 ); 02575 *p_x_talk_compensation_enable = temp8; 02576 02577 LOG_FUNCTION_END( status ); 02578 return status; 02579 } 02580 02581 VL53L0X_Error VL53L0X::vl53l0x_get_total_xtalk_rate( VL53L0X_DEV dev, 02582 VL53L0X_RangingMeasurementData_t *p_ranging_measurement_data, 02583 FixPoint1616_t *p_total_xtalk_rate_mcps ) 02584 { 02585 VL53L0X_Error status = VL53L0X_ERROR_NONE; 02586 02587 uint8_t xtalk_comp_enable; 02588 FixPoint1616_t total_xtalk_mega_cps; 02589 FixPoint1616_t xtalk_per_spad_mega_cps; 02590 02591 *p_total_xtalk_rate_mcps = 0; 02592 02593 status = vl53l0x_get_x_talk_compensation_enable( dev, &xtalk_comp_enable ); 02594 if ( status == VL53L0X_ERROR_NONE ) { 02595 02596 if ( xtalk_comp_enable ) { 02597 02598 VL53L0X_GETPARAMETERFIELD( 02599 dev, 02600 XTalkCompensationRateMegaCps, 02601 xtalk_per_spad_mega_cps ); 02602 02603 /* FixPoint1616 * FixPoint 8:8 = FixPoint0824 */ 02604 total_xtalk_mega_cps = 02605 p_ranging_measurement_data->EffectiveSpadRtnCount * 02606 xtalk_per_spad_mega_cps; 02607 02608 /* FixPoint0824 >> 8 = FixPoint1616 */ 02609 *p_total_xtalk_rate_mcps = 02610 ( total_xtalk_mega_cps + 0x80 ) >> 8; 02611 } 02612 } 02613 02614 return status; 02615 } 02616 02617 VL53L0X_Error VL53L0X::vl53l0x_get_total_signal_rate( VL53L0X_DEV dev, 02618 VL53L0X_RangingMeasurementData_t *p_ranging_measurement_data, 02619 FixPoint1616_t *p_total_signal_rate_mcps ) 02620 { 02621 VL53L0X_Error status = VL53L0X_ERROR_NONE; 02622 FixPoint1616_t total_xtalk_mega_cps; 02623 02624 LOG_FUNCTION_START( "" ); 02625 02626 *p_total_signal_rate_mcps = 02627 p_ranging_measurement_data->SignalRateRtnMegaCps; 02628 02629 status = vl53l0x_get_total_xtalk_rate( 02630 dev, p_ranging_measurement_data, &total_xtalk_mega_cps ); 02631 02632 if ( status == VL53L0X_ERROR_NONE ) 02633 *p_total_signal_rate_mcps += total_xtalk_mega_cps; 02634 02635 return status; 02636 } 02637 02638 /* To convert ms into register value */ 02639 uint32_t VL53L0X::vl53l0x_calc_timeout_mclks( VL53L0X_DEV dev, 02640 uint32_t timeout_period_us, 02641 uint8_t vcsel_period_pclks ) 02642 { 02643 uint32_t macro_period_ps; 02644 uint32_t macro_period_ns; 02645 uint32_t timeout_period_mclks = 0; 02646 02647 macro_period_ps = vl53l0x_calc_macro_period_ps( dev, vcsel_period_pclks ); 02648 macro_period_ns = ( macro_period_ps + 500 ) / 1000; 02649 02650 timeout_period_mclks = 02651 ( uint32_t ) ( ( ( timeout_period_us * 1000 ) 02652 + ( macro_period_ns / 2 ) ) / macro_period_ns ); 02653 02654 return timeout_period_mclks; 02655 } 02656 02657 uint32_t VL53L0X::vl53l0x_isqrt( uint32_t num ) 02658 { 02659 /* 02660 * Implements an integer square root 02661 * 02662 * From: http://en.wikipedia.org/wiki/Methods_of_computing_square_roots 02663 */ 02664 02665 uint32_t res = 0; 02666 uint32_t bit = 1 << 30; 02667 /* The second-to-top bit is set: 02668 * 1 << 14 for 16-bits, 1 << 30 for 32 bits */ 02669 02670 /* "bit" starts at the highest power of four <= the argument. */ 02671 while ( bit > num ) 02672 bit >>= 2; 02673 02674 02675 while ( bit != 0 ) { 02676 if ( num >= res + bit ) { 02677 num -= res + bit; 02678 res = ( res >> 1 ) + bit; 02679 } else 02680 res >>= 1; 02681 02682 bit >>= 2; 02683 } 02684 02685 return res; 02686 } 02687 02688 uint32_t VL53L0X::vl53l0x_quadrature_sum( uint32_t a, uint32_t b ) 02689 { 02690 /* 02691 * Implements a quadrature sum 02692 * 02693 * rea = sqrt(a^2 + b^2) 02694 * 02695 * Trap overflow case max input value is 65535 (16-bit value) 02696 * as internal calc are 32-bit wide 02697 * 02698 * If overflow then seta output to maximum 02699 */ 02700 uint32_t res = 0; 02701 02702 if ( a > 65535 || b > 65535 ) 02703 res = 65535; 02704 else 02705 res = vl53l0x_isqrt( a * a + b * b ); 02706 02707 return res; 02708 } 02709 02710 VL53L0X_Error VL53L0X::vl53l0x_calc_dmax( 02711 VL53L0X_DEV dev, 02712 FixPoint1616_t total_signal_rate_mcps, 02713 FixPoint1616_t total_corr_signal_rate_mcps, 02714 FixPoint1616_t pw_mult, 02715 uint32_t sigma_estimate_p1, 02716 FixPoint1616_t sigma_estimate_p2, 02717 uint32_t peak_vcsel_duration_us, 02718 uint32_t *pd_max_mm ) 02719 { 02720 const uint32_t c_sigma_limit = 18; 02721 const FixPoint1616_t c_signal_limit = 0x4000; /* 0.25 */ 02722 const FixPoint1616_t c_sigma_est_ref = 0x00000042; /* 0.001 */ 02723 const uint32_t c_amb_eff_width_sigma_est_ns = 6; 02724 const uint32_t c_amb_eff_width_d_max_ns = 7; 02725 uint32_t dmax_cal_range_mm; 02726 FixPoint1616_t dmax_cal_signal_rate_rtn_mcps; 02727 FixPoint1616_t min_signal_needed; 02728 FixPoint1616_t min_signal_needed_p1; 02729 FixPoint1616_t min_signal_needed_p2; 02730 FixPoint1616_t min_signal_needed_p3; 02731 FixPoint1616_t min_signal_needed_p4; 02732 FixPoint1616_t sigma_limit_tmp; 02733 FixPoint1616_t sigma_est_sq_tmp; 02734 FixPoint1616_t signal_limit_tmp; 02735 FixPoint1616_t signal_at0_mm; 02736 FixPoint1616_t dmax_dark; 02737 FixPoint1616_t dmax_ambient; 02738 FixPoint1616_t dmax_dark_tmp; 02739 FixPoint1616_t sigma_est_p2_tmp; 02740 uint32_t signal_rate_temp_mcps; 02741 02742 VL53L0X_Error status = VL53L0X_ERROR_NONE; 02743 02744 LOG_FUNCTION_START( "" ); 02745 02746 dmax_cal_range_mm = 02747 PALDevDataGet( dev, DmaxCalRangeMilliMeter ); 02748 02749 dmax_cal_signal_rate_rtn_mcps = 02750 PALDevDataGet( dev, DmaxCalSignalRateRtnMegaCps ); 02751 02752 /* uint32 * FixPoint1616 = FixPoint1616 */ 02753 signal_at0_mm = dmax_cal_range_mm * dmax_cal_signal_rate_rtn_mcps; 02754 02755 /* FixPoint1616 >> 8 = FixPoint2408 */ 02756 signal_at0_mm = ( signal_at0_mm + 0x80 ) >> 8; 02757 signal_at0_mm *= dmax_cal_range_mm; 02758 02759 min_signal_needed_p1 = 0; 02760 if ( total_corr_signal_rate_mcps > 0 ) { 02761 02762 /* Shift by 10 bits to increase resolution prior to the 02763 * division */ 02764 signal_rate_temp_mcps = total_signal_rate_mcps << 10; 02765 02766 /* Add rounding value prior to division */ 02767 min_signal_needed_p1 = signal_rate_temp_mcps + 02768 ( total_corr_signal_rate_mcps / 2 ); 02769 02770 /* FixPoint0626/FixPoint1616 = FixPoint2210 */ 02771 min_signal_needed_p1 /= total_corr_signal_rate_mcps; 02772 02773 /* Apply a factored version of the speed of light. 02774 Correction to be applied at the end */ 02775 min_signal_needed_p1 *= 3; 02776 02777 /* FixPoint2210 * FixPoint2210 = FixPoint1220 */ 02778 min_signal_needed_p1 *= min_signal_needed_p1; 02779 02780 /* FixPoint1220 >> 16 = FixPoint2804 */ 02781 min_signal_needed_p1 = ( min_signal_needed_p1 + 0x8000 ) >> 16; 02782 } 02783 02784 min_signal_needed_p2 = pw_mult * sigma_estimate_p1; 02785 02786 /* FixPoint1616 >> 16 = uint32 */ 02787 min_signal_needed_p2 = ( min_signal_needed_p2 + 0x8000 ) >> 16; 02788 02789 /* uint32 * uint32 = uint32 */ 02790 min_signal_needed_p2 *= min_signal_needed_p2; 02791 02792 /* Check sigmaEstimateP2 02793 * If this value is too high there is not enough signal rate 02794 * to calculate dmax value so set a suitable value to ensure 02795 * a very small dmax. 02796 */ 02797 sigma_est_p2_tmp = ( sigma_estimate_p2 + 0x8000 ) >> 16; 02798 sigma_est_p2_tmp = ( sigma_est_p2_tmp + c_amb_eff_width_sigma_est_ns / 2 ) / 02799 c_amb_eff_width_sigma_est_ns; 02800 sigma_est_p2_tmp *= c_amb_eff_width_d_max_ns; 02801 02802 if ( sigma_est_p2_tmp > 0xffff ) { 02803 min_signal_needed_p3 = 0xfff00000; 02804 } else { 02805 02806 /* DMAX uses a different ambient width from sigma, so apply 02807 * correction. 02808 * Perform division before multiplication to prevent overflow. 02809 */ 02810 sigma_estimate_p2 = ( sigma_estimate_p2 + c_amb_eff_width_sigma_est_ns / 2 ) / 02811 c_amb_eff_width_sigma_est_ns; 02812 sigma_estimate_p2 *= c_amb_eff_width_d_max_ns; 02813 02814 /* FixPoint1616 >> 16 = uint32 */ 02815 min_signal_needed_p3 = ( sigma_estimate_p2 + 0x8000 ) >> 16; 02816 02817 min_signal_needed_p3 *= min_signal_needed_p3; 02818 02819 } 02820 02821 /* FixPoint1814 / uint32 = FixPoint1814 */ 02822 sigma_limit_tmp = ( ( c_sigma_limit << 14 ) + 500 ) / 1000; 02823 02824 /* FixPoint1814 * FixPoint1814 = FixPoint3628 := FixPoint0428 */ 02825 sigma_limit_tmp *= sigma_limit_tmp; 02826 02827 /* FixPoint1616 * FixPoint1616 = FixPoint3232 */ 02828 sigma_est_sq_tmp = c_sigma_est_ref * c_sigma_est_ref; 02829 02830 /* FixPoint3232 >> 4 = FixPoint0428 */ 02831 sigma_est_sq_tmp = ( sigma_est_sq_tmp + 0x08 ) >> 4; 02832 02833 /* FixPoint0428 - FixPoint0428 = FixPoint0428 */ 02834 sigma_limit_tmp -= sigma_est_sq_tmp; 02835 02836 /* uint32_t * FixPoint0428 = FixPoint0428 */ 02837 min_signal_needed_p4 = 4 * 12 * sigma_limit_tmp; 02838 02839 /* FixPoint0428 >> 14 = FixPoint1814 */ 02840 min_signal_needed_p4 = ( min_signal_needed_p4 + 0x2000 ) >> 14; 02841 02842 /* uint32 + uint32 = uint32 */ 02843 min_signal_needed = ( min_signal_needed_p2 + min_signal_needed_p3 ); 02844 02845 /* uint32 / uint32 = uint32 */ 02846 min_signal_needed += ( peak_vcsel_duration_us / 2 ); 02847 min_signal_needed /= peak_vcsel_duration_us; 02848 02849 /* uint32 << 14 = FixPoint1814 */ 02850 min_signal_needed <<= 14; 02851 02852 /* FixPoint1814 / FixPoint1814 = uint32 */ 02853 min_signal_needed += ( min_signal_needed_p4 / 2 ); 02854 min_signal_needed /= min_signal_needed_p4; 02855 02856 /* FixPoint3200 * FixPoint2804 := FixPoint2804*/ 02857 min_signal_needed *= min_signal_needed_p1; 02858 02859 /* Apply correction by dividing by 1000000. 02860 * This assumes 10E16 on the numerator of the equation 02861 * and 10E-22 on the denominator. 02862 * We do this because 32bit fix point calculation can't 02863 * handle the larger and smaller elements of this equation, 02864 * i.e. speed of light and pulse widths. 02865 */ 02866 min_signal_needed = ( min_signal_needed + 500 ) / 1000; 02867 min_signal_needed <<= 4; 02868 02869 min_signal_needed = ( min_signal_needed + 500 ) / 1000; 02870 02871 /* FixPoint1616 >> 8 = FixPoint2408 */ 02872 signal_limit_tmp = ( c_signal_limit + 0x80 ) >> 8; 02873 02874 /* FixPoint2408/FixPoint2408 = uint32 */ 02875 if ( signal_limit_tmp != 0 ) 02876 dmax_dark_tmp = ( signal_at0_mm + ( signal_limit_tmp / 2 ) ) 02877 / signal_limit_tmp; 02878 else 02879 dmax_dark_tmp = 0; 02880 02881 dmax_dark = vl53l0x_isqrt( dmax_dark_tmp ); 02882 02883 /* FixPoint2408/FixPoint2408 = uint32 */ 02884 if ( min_signal_needed != 0 ) 02885 dmax_ambient = ( signal_at0_mm + min_signal_needed / 2 ) 02886 / min_signal_needed; 02887 else 02888 dmax_ambient = 0; 02889 02890 dmax_ambient = vl53l0x_isqrt( dmax_ambient ); 02891 02892 *pd_max_mm = dmax_dark; 02893 if ( dmax_dark > dmax_ambient ) 02894 *pd_max_mm = dmax_ambient; 02895 02896 LOG_FUNCTION_END( status ); 02897 02898 return status; 02899 } 02900 02901 VL53L0X_Error VL53L0X::vl53l0x_calc_sigma_estimate( VL53L0X_DEV dev, 02902 VL53L0X_RangingMeasurementData_t *p_ranging_measurement_data, 02903 FixPoint1616_t *p_sigma_estimate, 02904 uint32_t *p_dmax_mm ) 02905 { 02906 /* Expressed in 100ths of a ns, i.e. centi-ns */ 02907 const uint32_t c_pulse_effective_width_centi_ns = 800; 02908 /* Expressed in 100ths of a ns, i.e. centi-ns */ 02909 const uint32_t c_ambient_effective_width_centi_ns = 600; 02910 const FixPoint1616_t c_dflt_final_range_integration_time_milli_secs = 0x00190000; /* 25ms */ 02911 const uint32_t c_vcsel_pulse_width_ps = 4700; /* pico secs */ 02912 const FixPoint1616_t c_sigma_est_max = 0x028F87AE; 02913 const FixPoint1616_t c_sigma_est_rtn_max = 0xF000; 02914 const FixPoint1616_t c_amb_to_signal_ratio_max = 0xF0000000 / 02915 c_ambient_effective_width_centi_ns; 02916 /* Time Of Flight per mm (6.6 pico secs) */ 02917 const FixPoint1616_t c_tof_per_mm_ps = 0x0006999A; 02918 const uint32_t c_16bit_rounding_param = 0x00008000; 02919 const FixPoint1616_t c_max_x_talk_kcps = 0x00320000; 02920 const uint32_t c_pll_period_ps = 1655; 02921 02922 uint32_t vcsel_total_events_rtn; 02923 uint32_t final_range_timeout_micro_secs; 02924 uint32_t pre_range_timeout_micro_secs; 02925 uint32_t final_range_integration_time_milli_secs; 02926 FixPoint1616_t sigma_estimate_p1; 02927 FixPoint1616_t sigma_estimate_p2; 02928 FixPoint1616_t sigma_estimate_p3; 02929 FixPoint1616_t delta_t_ps; 02930 FixPoint1616_t pw_mult; 02931 FixPoint1616_t sigma_est_rtn; 02932 FixPoint1616_t sigma_estimate; 02933 FixPoint1616_t x_talk_correction; 02934 FixPoint1616_t ambient_rate_kcps; 02935 FixPoint1616_t peak_signal_rate_kcps; 02936 FixPoint1616_t x_talk_comp_rate_mcps; 02937 uint32_t x_talk_comp_rate_kcps; 02938 VL53L0X_Error status = VL53L0X_ERROR_NONE; 02939 FixPoint1616_t diff1_mcps; 02940 FixPoint1616_t diff2_mcps; 02941 FixPoint1616_t sqr1; 02942 FixPoint1616_t sqr2; 02943 FixPoint1616_t sqr_sum; 02944 FixPoint1616_t sqrt_result_centi_ns; 02945 FixPoint1616_t sqrt_result; 02946 FixPoint1616_t total_signal_rate_mcps; 02947 FixPoint1616_t corrected_signal_rate_mcps; 02948 FixPoint1616_t sigma_est_ref; 02949 uint32_t vcsel_width; 02950 uint32_t final_range_macro_pclks; 02951 uint32_t pre_range_macro_pclks; 02952 uint32_t peak_vcsel_duration_us; 02953 uint8_t final_range_vcsel_pclks; 02954 uint8_t pre_range_vcsel_pclks; 02955 /*! \addtogroup calc_sigma_estimate 02956 * @{ 02957 * 02958 * Estimates the range sigma 02959 */ 02960 02961 LOG_FUNCTION_START( "" ); 02962 02963 VL53L0X_GETPARAMETERFIELD( dev, XTalkCompensationRateMegaCps, 02964 x_talk_comp_rate_mcps ); 02965 02966 /* 02967 * We work in kcps rather than mcps as this helps keep within the 02968 * confines of the 32 Fix1616 type. 02969 */ 02970 02971 ambient_rate_kcps = 02972 ( p_ranging_measurement_data->AmbientRateRtnMegaCps * 1000 ) >> 16; 02973 02974 corrected_signal_rate_mcps = 02975 p_ranging_measurement_data->SignalRateRtnMegaCps; 02976 02977 02978 status = vl53l0x_get_total_signal_rate( 02979 dev, p_ranging_measurement_data, &total_signal_rate_mcps ); 02980 status = vl53l0x_get_total_xtalk_rate( 02981 dev, p_ranging_measurement_data, &x_talk_comp_rate_mcps ); 02982 02983 02984 /* Signal rate measurement provided by device is the 02985 * peak signal rate, not average. 02986 */ 02987 peak_signal_rate_kcps = ( total_signal_rate_mcps * 1000 ); 02988 peak_signal_rate_kcps = ( peak_signal_rate_kcps + 0x8000 ) >> 16; 02989 02990 x_talk_comp_rate_kcps = x_talk_comp_rate_mcps * 1000; 02991 02992 if ( x_talk_comp_rate_kcps > c_max_x_talk_kcps ) 02993 x_talk_comp_rate_kcps = c_max_x_talk_kcps; 02994 02995 if ( status == VL53L0X_ERROR_NONE ) { 02996 02997 /* Calculate final range macro periods */ 02998 final_range_timeout_micro_secs = VL53L0X_GETDEVICESPECIFICPARAMETER( 02999 dev, FinalRangeTimeoutMicroSecs ); 03000 03001 final_range_vcsel_pclks = VL53L0X_GETDEVICESPECIFICPARAMETER( 03002 dev, FinalRangeVcselPulsePeriod ); 03003 03004 final_range_macro_pclks = vl53l0x_calc_timeout_mclks( 03005 dev, final_range_timeout_micro_secs, final_range_vcsel_pclks ); 03006 03007 /* Calculate pre-range macro periods */ 03008 pre_range_timeout_micro_secs = VL53L0X_GETDEVICESPECIFICPARAMETER( 03009 dev, PreRangeTimeoutMicroSecs ); 03010 03011 pre_range_vcsel_pclks = VL53L0X_GETDEVICESPECIFICPARAMETER( 03012 dev, PreRangeVcselPulsePeriod ); 03013 03014 pre_range_macro_pclks = vl53l0x_calc_timeout_mclks( 03015 dev, pre_range_timeout_micro_secs, pre_range_vcsel_pclks ); 03016 03017 vcsel_width = 3; 03018 if ( final_range_vcsel_pclks == 8 ) 03019 vcsel_width = 2; 03020 03021 03022 peak_vcsel_duration_us = vcsel_width * 2048 * 03023 ( pre_range_macro_pclks + final_range_macro_pclks ); 03024 peak_vcsel_duration_us = ( peak_vcsel_duration_us + 500 ) / 1000; 03025 peak_vcsel_duration_us *= c_pll_period_ps; 03026 peak_vcsel_duration_us = ( peak_vcsel_duration_us + 500 ) / 1000; 03027 03028 /* Fix1616 >> 8 = Fix2408 */ 03029 total_signal_rate_mcps = ( total_signal_rate_mcps + 0x80 ) >> 8; 03030 03031 /* Fix2408 * uint32 = Fix2408 */ 03032 vcsel_total_events_rtn = total_signal_rate_mcps * 03033 peak_vcsel_duration_us; 03034 03035 /* Fix2408 >> 8 = uint32 */ 03036 vcsel_total_events_rtn = ( vcsel_total_events_rtn + 0x80 ) >> 8; 03037 03038 /* Fix2408 << 8 = Fix1616 = */ 03039 total_signal_rate_mcps <<= 8; 03040 } 03041 03042 if ( status != VL53L0X_ERROR_NONE ) { 03043 LOG_FUNCTION_END( status ); 03044 return status; 03045 } 03046 03047 if ( peak_signal_rate_kcps == 0 ) { 03048 *p_sigma_estimate = c_sigma_est_max; 03049 PALDevDataSet( dev, SigmaEstimate, c_sigma_est_max ); 03050 *p_dmax_mm = 0; 03051 } else { 03052 if ( vcsel_total_events_rtn < 1 ) 03053 vcsel_total_events_rtn = 1; 03054 03055 sigma_estimate_p1 = c_pulse_effective_width_centi_ns; 03056 03057 /* ((FixPoint1616 << 16)* uint32)/uint32 = FixPoint1616 */ 03058 sigma_estimate_p2 = ( ambient_rate_kcps << 16 ) / peak_signal_rate_kcps; 03059 if ( sigma_estimate_p2 > c_amb_to_signal_ratio_max ) { 03060 /* Clip to prevent overflow. Will ensure safe 03061 * max result. */ 03062 sigma_estimate_p2 = c_amb_to_signal_ratio_max; 03063 } 03064 sigma_estimate_p2 *= c_ambient_effective_width_centi_ns; 03065 03066 sigma_estimate_p3 = 2 * vl53l0x_isqrt( vcsel_total_events_rtn * 12 ); 03067 03068 /* uint32 * FixPoint1616 = FixPoint1616 */ 03069 delta_t_ps = p_ranging_measurement_data->RangeMilliMeter * 03070 c_tof_per_mm_ps; 03071 03072 /* 03073 * vcselRate - xtalkCompRate 03074 * (uint32 << 16) - FixPoint1616 = FixPoint1616. 03075 * Divide result by 1000 to convert to mcps. 03076 * 500 is added to ensure rounding when integer division 03077 * truncates. 03078 */ 03079 diff1_mcps = ( ( ( peak_signal_rate_kcps << 16 ) - 03080 2 * x_talk_comp_rate_kcps ) + 500 ) / 1000; 03081 03082 /* vcselRate + xtalkCompRate */ 03083 diff2_mcps = ( ( peak_signal_rate_kcps << 16 ) + 500 ) / 1000; 03084 03085 /* Shift by 8 bits to increase resolution prior to the 03086 * division */ 03087 diff1_mcps <<= 8; 03088 03089 /* FixPoint0824/FixPoint1616 = FixPoint2408 */ 03090 // xTalkCorrection = abs(diff1_mcps/diff2_mcps); 03091 // abs is causing compiler overloading isue in C++, but unsigned types. So, redundant call anyway! 03092 x_talk_correction = diff1_mcps / diff2_mcps; 03093 03094 /* FixPoint2408 << 8 = FixPoint1616 */ 03095 x_talk_correction <<= 8; 03096 03097 if( p_ranging_measurement_data->RangeStatus != 0 ) { 03098 pw_mult = 1 << 16; 03099 } else { 03100 /* FixPoint1616/uint32 = FixPoint1616 */ 03101 pw_mult = delta_t_ps / c_vcsel_pulse_width_ps; /* smaller than 1.0f */ 03102 03103 /* 03104 * FixPoint1616 * FixPoint1616 = FixPoint3232, however both 03105 * values are small enough such that32 bits will not be 03106 * exceeded. 03107 */ 03108 pw_mult *= ( ( 1 << 16 ) - x_talk_correction ); 03109 03110 /* (FixPoint3232 >> 16) = FixPoint1616 */ 03111 pw_mult = ( pw_mult + c_16bit_rounding_param ) >> 16; 03112 03113 /* FixPoint1616 + FixPoint1616 = FixPoint1616 */ 03114 pw_mult += ( 1 << 16 ); 03115 03116 /* 03117 * At this point the value will be 1.xx, therefore if we square 03118 * the value this will exceed 32 bits. To address this perform 03119 * a single shift to the right before the multiplication. 03120 */ 03121 pw_mult >>= 1; 03122 /* FixPoint1715 * FixPoint1715 = FixPoint3430 */ 03123 pw_mult = pw_mult * pw_mult; 03124 03125 /* (FixPoint3430 >> 14) = Fix1616 */ 03126 pw_mult >>= 14; 03127 } 03128 03129 /* FixPoint1616 * uint32 = FixPoint1616 */ 03130 sqr1 = pw_mult * sigma_estimate_p1; 03131 03132 /* (FixPoint1616 >> 16) = FixPoint3200 */ 03133 sqr1 = ( sqr1 + 0x8000 ) >> 16; 03134 03135 /* FixPoint3200 * FixPoint3200 = FixPoint6400 */ 03136 sqr1 *= sqr1; 03137 03138 sqr2 = sigma_estimate_p2; 03139 03140 /* (FixPoint1616 >> 16) = FixPoint3200 */ 03141 sqr2 = ( sqr2 + 0x8000 ) >> 16; 03142 03143 /* FixPoint3200 * FixPoint3200 = FixPoint6400 */ 03144 sqr2 *= sqr2; 03145 03146 /* FixPoint64000 + FixPoint6400 = FixPoint6400 */ 03147 sqr_sum = sqr1 + sqr2; 03148 03149 /* SQRT(FixPoin6400) = FixPoint3200 */ 03150 sqrt_result_centi_ns = vl53l0x_isqrt( sqr_sum ); 03151 03152 /* (FixPoint3200 << 16) = FixPoint1616 */ 03153 sqrt_result_centi_ns <<= 16; 03154 03155 /* 03156 * Note that the Speed Of Light is expressed in um per 1E-10 03157 * seconds (2997) Therefore to get mm/ns we have to divide by 03158 * 10000 03159 */ 03160 sigma_est_rtn = ( ( ( sqrt_result_centi_ns + 50 ) / 100 ) / 03161 sigma_estimate_p3 ); 03162 sigma_est_rtn *= VL53L0X_SPEED_OF_LIGHT_IN_AIR; 03163 03164 /* Add 5000 before dividing by 10000 to ensure rounding. */ 03165 sigma_est_rtn += 5000; 03166 sigma_est_rtn /= 10000; 03167 03168 if ( sigma_est_rtn > c_sigma_est_rtn_max ) { 03169 /* Clip to prevent overflow. Will ensure safe 03170 * max result. */ 03171 sigma_est_rtn = c_sigma_est_rtn_max; 03172 } 03173 final_range_integration_time_milli_secs = 03174 ( final_range_timeout_micro_secs + pre_range_timeout_micro_secs + 500 ) / 1000; 03175 03176 /* sigmaEstRef = 1mm * 25ms/final range integration time (inc pre-range) 03177 * sqrt(FixPoint1616/int) = FixPoint2408) 03178 */ 03179 sigma_est_ref = 03180 vl53l0x_isqrt( ( c_dflt_final_range_integration_time_milli_secs + 03181 final_range_integration_time_milli_secs / 2 ) / 03182 final_range_integration_time_milli_secs ); 03183 03184 /* FixPoint2408 << 8 = FixPoint1616 */ 03185 sigma_est_ref <<= 8; 03186 sigma_est_ref = ( sigma_est_ref + 500 ) / 1000; 03187 03188 /* FixPoint1616 * FixPoint1616 = FixPoint3232 */ 03189 sqr1 = sigma_est_rtn * sigma_est_rtn; 03190 /* FixPoint1616 * FixPoint1616 = FixPoint3232 */ 03191 sqr2 = sigma_est_ref * sigma_est_ref; 03192 03193 /* sqrt(FixPoint3232) = FixPoint1616 */ 03194 sqrt_result = vl53l0x_isqrt( ( sqr1 + sqr2 ) ); 03195 /* 03196 * Note that the Shift by 4 bits increases resolution prior to 03197 * the sqrt, therefore the result must be shifted by 2 bits to 03198 * the right to revert back to the FixPoint1616 format. 03199 */ 03200 03201 sigma_estimate = 1000 * sqrt_result; 03202 03203 if ( ( peak_signal_rate_kcps < 1 ) || ( vcsel_total_events_rtn < 1 ) || 03204 ( sigma_estimate > c_sigma_est_max ) ) { 03205 sigma_estimate = c_sigma_est_max; 03206 } 03207 03208 *p_sigma_estimate = ( uint32_t )( sigma_estimate ); 03209 PALDevDataSet( dev, SigmaEstimate, *p_sigma_estimate ); 03210 status = vl53l0x_calc_dmax( 03211 dev, 03212 total_signal_rate_mcps, 03213 corrected_signal_rate_mcps, 03214 pw_mult, 03215 sigma_estimate_p1, 03216 sigma_estimate_p2, 03217 peak_vcsel_duration_us, 03218 p_dmax_mm ); 03219 } 03220 03221 LOG_FUNCTION_END( status ); 03222 return status; 03223 } 03224 03225 VL53L0X_Error VL53L0X::vl53l0x_get_pal_range_status( VL53L0X_DEV dev, 03226 uint8_t device_range_status, 03227 FixPoint1616_t signal_rate, 03228 uint16_t effective_spad_rtn_count, 03229 VL53L0X_RangingMeasurementData_t *p_ranging_measurement_data, 03230 uint8_t *p_pal_range_status ) 03231 { 03232 VL53L0X_Error status = VL53L0X_ERROR_NONE; 03233 uint8_t none_flag; 03234 uint8_t sigma_limitflag = 0; 03235 uint8_t signal_ref_clipflag = 0; 03236 uint8_t range_ignore_thresholdflag = 0; 03237 uint8_t sigma_limit_check_enable = 0; 03238 uint8_t signal_rate_final_range_limit_check_enable = 0; 03239 uint8_t signal_ref_clip_limit_check_enable = 0; 03240 uint8_t range_ignore_threshold_limit_check_enable = 0; 03241 FixPoint1616_t sigma_estimate; 03242 FixPoint1616_t sigma_limit_value; 03243 FixPoint1616_t signal_ref_clip_value; 03244 FixPoint1616_t range_ignore_threshold_value; 03245 FixPoint1616_t signal_rate_per_spad; 03246 uint8_t device_range_status_internal = 0; 03247 uint16_t tmp_word = 0; 03248 uint8_t temp8; 03249 uint32_t dmax_mm = 0; 03250 FixPoint1616_t last_signal_ref_mcps; 03251 03252 LOG_FUNCTION_START( "" ); 03253 03254 03255 /* 03256 * VL53L0X has a good ranging when the value of the 03257 * DeviceRangeStatus = 11. This function will replace the value 0 with 03258 * the value 11 in the DeviceRangeStatus. 03259 * In addition, the SigmaEstimator is not included in the VL53L0X 03260 * DeviceRangeStatus, this will be added in the PalRangeStatus. 03261 */ 03262 03263 device_range_status_internal = ( ( device_range_status & 0x78 ) >> 3 ); 03264 03265 if ( device_range_status_internal == 0 || 03266 device_range_status_internal == 5 || 03267 device_range_status_internal == 7 || 03268 device_range_status_internal == 12 || 03269 device_range_status_internal == 13 || 03270 device_range_status_internal == 14 || 03271 device_range_status_internal == 15 03272 ) { 03273 none_flag = 1; 03274 } else { 03275 none_flag = 0; 03276 } 03277 03278 /* 03279 * Check if Sigma limit is enabled, if yes then do comparison with limit 03280 * value and put the result back into pPalRangeStatus. 03281 */ 03282 if ( status == VL53L0X_ERROR_NONE ) 03283 status = vl53l0x_get_limit_check_enable( dev, 03284 VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE, 03285 &sigma_limit_check_enable ); 03286 03287 if ( ( sigma_limit_check_enable != 0 ) && ( status == VL53L0X_ERROR_NONE ) ) { 03288 /* 03289 * compute the Sigma and check with limit 03290 */ 03291 status = vl53l0x_calc_sigma_estimate( 03292 dev, 03293 p_ranging_measurement_data, 03294 &sigma_estimate, 03295 &dmax_mm ); 03296 if ( status == VL53L0X_ERROR_NONE ) 03297 p_ranging_measurement_data->RangeDMaxMilliMeter = dmax_mm; 03298 03299 if ( status == VL53L0X_ERROR_NONE ) { 03300 status = vl53l0x_get_limit_check_value( dev, 03301 VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE, 03302 &sigma_limit_value ); 03303 03304 if ( ( sigma_limit_value > 0 ) && 03305 ( sigma_estimate > sigma_limit_value ) ) 03306 /* Limit Fail */ 03307 sigma_limitflag = 1; 03308 } 03309 } 03310 03311 /* 03312 * Check if Signal ref clip limit is enabled, if yes then do comparison 03313 * with limit value and put the result back into pPalRangeStatus. 03314 */ 03315 if ( status == VL53L0X_ERROR_NONE ) 03316 status = vl53l0x_get_limit_check_enable( dev, 03317 VL53L0X_CHECKENABLE_SIGNAL_REF_CLIP, 03318 &signal_ref_clip_limit_check_enable ); 03319 03320 if ( ( signal_ref_clip_limit_check_enable != 0 ) && 03321 ( status == VL53L0X_ERROR_NONE ) ) { 03322 03323 status = vl53l0x_get_limit_check_value( dev, 03324 VL53L0X_CHECKENABLE_SIGNAL_REF_CLIP, 03325 &signal_ref_clip_value ); 03326 03327 /* Read LastSignalRefMcps from device */ 03328 if ( status == VL53L0X_ERROR_NONE ) 03329 status = vl53l0x_write_byte( dev, 0xFF, 0x01 ); 03330 03331 if ( status == VL53L0X_ERROR_NONE ) 03332 status = vl53l0x_read_word( dev, 03333 VL53L0X_REG_RESULT_PEAK_SIGNAL_RATE_REF, 03334 &tmp_word ); 03335 03336 if ( status == VL53L0X_ERROR_NONE ) 03337 status = vl53l0x_write_byte( dev, 0xFF, 0x00 ); 03338 03339 last_signal_ref_mcps = VL53L0X_FIXPOINT97TOFIXPOINT1616( tmp_word ); 03340 PALDevDataSet( dev, LastSignalRefMcps, last_signal_ref_mcps ); 03341 03342 if ( ( signal_ref_clip_value > 0 ) && 03343 ( last_signal_ref_mcps > signal_ref_clip_value ) ) { 03344 /* Limit Fail */ 03345 signal_ref_clipflag = 1; 03346 } 03347 } 03348 03349 /* 03350 * Check if Signal ref clip limit is enabled, if yes then do comparison 03351 * with limit value and put the result back into pPalRangeStatus. 03352 * EffectiveSpadRtnCount has a format 8.8 03353 * If (Return signal rate < (1.5 x Xtalk x number of Spads)) : FAIL 03354 */ 03355 if ( status == VL53L0X_ERROR_NONE ) 03356 status = vl53l0x_get_limit_check_enable( dev, 03357 VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD, 03358 &range_ignore_threshold_limit_check_enable ); 03359 03360 if ( ( range_ignore_threshold_limit_check_enable != 0 ) && 03361 ( status == VL53L0X_ERROR_NONE ) ) { 03362 03363 /* Compute the signal rate per spad */ 03364 if ( effective_spad_rtn_count == 0 ) { 03365 signal_rate_per_spad = 0; 03366 } else { 03367 signal_rate_per_spad = ( FixPoint1616_t )( ( 256 * signal_rate ) 03368 / effective_spad_rtn_count ); 03369 } 03370 03371 status = vl53l0x_get_limit_check_value( dev, 03372 VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD, 03373 &range_ignore_threshold_value ); 03374 03375 if ( ( range_ignore_threshold_value > 0 ) && 03376 ( signal_rate_per_spad < range_ignore_threshold_value ) ) { 03377 /* Limit Fail add 2^6 to range status */ 03378 range_ignore_thresholdflag = 1; 03379 } 03380 } 03381 03382 if ( status == VL53L0X_ERROR_NONE ) { 03383 if ( none_flag == 1 ) { 03384 *p_pal_range_status = 255; /* NONE */ 03385 } else if ( device_range_status_internal == 1 || 03386 device_range_status_internal == 2 || 03387 device_range_status_internal == 3 ) { 03388 *p_pal_range_status = 5; /* HW fail */ 03389 } else if ( device_range_status_internal == 6 || 03390 device_range_status_internal == 9 ) { 03391 *p_pal_range_status = 4; /* Phase fail */ 03392 } else if ( device_range_status_internal == 8 || 03393 device_range_status_internal == 10 || 03394 signal_ref_clipflag == 1 ) { 03395 *p_pal_range_status = 3; /* Min range */ 03396 } else if ( device_range_status_internal == 4 || 03397 range_ignore_thresholdflag == 1 ) { 03398 *p_pal_range_status = 2; /* Signal Fail */ 03399 } else if ( sigma_limitflag == 1 ) { 03400 *p_pal_range_status = 1; /* Sigma Fail */ 03401 } else { 03402 *p_pal_range_status = 0; /* Range Valid */ 03403 } 03404 } 03405 03406 /* DMAX only relevant during range error */ 03407 if ( *p_pal_range_status == 0 ) 03408 p_ranging_measurement_data->RangeDMaxMilliMeter = 0; 03409 03410 /* fill the Limit Check Status */ 03411 03412 status = vl53l0x_get_limit_check_enable( dev, 03413 VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE, 03414 &signal_rate_final_range_limit_check_enable ); 03415 03416 if ( status == VL53L0X_ERROR_NONE ) { 03417 if ( ( sigma_limit_check_enable == 0 ) || ( sigma_limitflag == 1 ) ) 03418 temp8 = 1; 03419 else 03420 temp8 = 0; 03421 VL53L0X_SETARRAYPARAMETERFIELD( dev, LimitChecksStatus, 03422 VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE, temp8 ); 03423 03424 if ( ( device_range_status_internal == 4 ) || 03425 ( signal_rate_final_range_limit_check_enable == 0 ) ) 03426 temp8 = 1; 03427 else 03428 temp8 = 0; 03429 VL53L0X_SETARRAYPARAMETERFIELD( dev, LimitChecksStatus, 03430 VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE, 03431 temp8 ); 03432 03433 if ( ( signal_ref_clip_limit_check_enable == 0 ) || 03434 ( signal_ref_clipflag == 1 ) ) 03435 temp8 = 1; 03436 else 03437 temp8 = 0; 03438 03439 VL53L0X_SETARRAYPARAMETERFIELD( dev, LimitChecksStatus, 03440 VL53L0X_CHECKENABLE_SIGNAL_REF_CLIP, temp8 ); 03441 03442 if ( ( range_ignore_threshold_limit_check_enable == 0 ) || 03443 ( range_ignore_thresholdflag == 1 ) ) 03444 temp8 = 1; 03445 else 03446 temp8 = 0; 03447 03448 VL53L0X_SETARRAYPARAMETERFIELD( dev, LimitChecksStatus, 03449 VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD, 03450 temp8 ); 03451 } 03452 03453 LOG_FUNCTION_END( status ); 03454 return status; 03455 03456 } 03457 03458 VL53L0X_Error VL53L0X::vl53l0x_get_ranging_measurement_data( VL53L0X_DEV dev, 03459 VL53L0X_RangingMeasurementData_t *p_ranging_measurement_data ) 03460 { 03461 VL53L0X_Error status = VL53L0X_ERROR_NONE; 03462 uint8_t device_range_status; 03463 uint8_t range_fractional_enable; 03464 uint8_t pal_range_status; 03465 uint8_t x_talk_compensation_enable; 03466 uint16_t ambient_rate; 03467 FixPoint1616_t signal_rate; 03468 uint16_t x_talk_compensation_rate_mega_cps; 03469 uint16_t effective_spad_rtn_count; 03470 uint16_t tmpuint16; 03471 uint16_t xtalk_range_milli_meter; 03472 uint16_t linearity_corrective_gain; 03473 uint8_t localBuffer[12]; 03474 VL53L0X_RangingMeasurementData_t last_range_data_buffer; 03475 03476 LOG_FUNCTION_START( "" ); 03477 03478 /* 03479 * use multi read even if some registers are not useful, result will 03480 * be more efficient 03481 * start reading at 0x14 dec20 03482 * end reading at 0x21 dec33 total 14 bytes to read 03483 */ 03484 status = vl53l0x_read_multi( dev, 0x14, localBuffer, 12 ); 03485 03486 if ( status == VL53L0X_ERROR_NONE ) { 03487 03488 p_ranging_measurement_data->ZoneId = 0; /* Only one zone */ 03489 p_ranging_measurement_data->TimeStamp = 0; /* Not Implemented */ 03490 03491 tmpuint16 = VL53L0X_MAKEUINT16( localBuffer[11], localBuffer[10] ); 03492 /* cut1.1 if SYSTEM__RANGE_CONFIG if 1 range is 2bits fractional 03493 *(format 11.2) else no fractional 03494 */ 03495 03496 p_ranging_measurement_data->MeasurementTimeUsec = 0; 03497 03498 signal_rate = VL53L0X_FIXPOINT97TOFIXPOINT1616( 03499 VL53L0X_MAKEUINT16( localBuffer[7], localBuffer[6] ) ); 03500 /* peak_signal_count_rate_rtn_mcps */ 03501 p_ranging_measurement_data->SignalRateRtnMegaCps = signal_rate; 03502 03503 ambient_rate = VL53L0X_MAKEUINT16( localBuffer[9], localBuffer[8] ); 03504 p_ranging_measurement_data->AmbientRateRtnMegaCps = 03505 VL53L0X_FIXPOINT97TOFIXPOINT1616( ambient_rate ); 03506 03507 effective_spad_rtn_count = VL53L0X_MAKEUINT16( localBuffer[3], 03508 localBuffer[2] ); 03509 /* EffectiveSpadRtnCount is 8.8 format */ 03510 p_ranging_measurement_data->EffectiveSpadRtnCount = 03511 effective_spad_rtn_count; 03512 03513 device_range_status = localBuffer[0]; 03514 03515 /* Get Linearity Corrective Gain */ 03516 linearity_corrective_gain = PALDevDataGet( dev, 03517 LinearityCorrectiveGain ); 03518 03519 /* Get ranging configuration */ 03520 range_fractional_enable = PALDevDataGet( dev, 03521 RangeFractionalEnable ); 03522 03523 if ( linearity_corrective_gain != 1000 ) { 03524 03525 tmpuint16 = ( uint16_t )( ( linearity_corrective_gain 03526 * tmpuint16 + 500 ) / 1000 ); 03527 03528 /* Implement Xtalk */ 03529 VL53L0X_GETPARAMETERFIELD( dev, 03530 XTalkCompensationRateMegaCps, 03531 x_talk_compensation_rate_mega_cps ); 03532 VL53L0X_GETPARAMETERFIELD( dev, XTalkCompensationEnable, 03533 x_talk_compensation_enable ); 03534 03535 if ( x_talk_compensation_enable ) { 03536 03537 if ( ( signal_rate 03538 - ( ( x_talk_compensation_rate_mega_cps 03539 * effective_spad_rtn_count ) >> 8 ) ) 03540 <= 0 ) { 03541 if ( range_fractional_enable ) 03542 xtalk_range_milli_meter = 8888; 03543 else 03544 xtalk_range_milli_meter = 8888 03545 << 2; 03546 } else { 03547 xtalk_range_milli_meter = 03548 ( tmpuint16 * signal_rate ) 03549 / ( signal_rate 03550 - ( ( x_talk_compensation_rate_mega_cps 03551 * effective_spad_rtn_count ) 03552 >> 8 ) ); 03553 } 03554 03555 tmpuint16 = xtalk_range_milli_meter; 03556 } 03557 03558 } 03559 03560 if ( range_fractional_enable ) { 03561 p_ranging_measurement_data->RangeMilliMeter = 03562 ( uint16_t )( ( tmpuint16 ) >> 2 ); 03563 p_ranging_measurement_data->RangeFractionalPart = 03564 ( uint8_t )( ( tmpuint16 & 0x03 ) << 6 ); 03565 } else { 03566 p_ranging_measurement_data->RangeMilliMeter = tmpuint16; 03567 p_ranging_measurement_data->RangeFractionalPart = 0; 03568 } 03569 03570 /* 03571 * For a standard definition of RangeStatus, this should 03572 * return 0 in case of good result after a ranging 03573 * The range status depends on the device so call a device 03574 * specific function to obtain the right Status. 03575 */ 03576 status |= vl53l0x_get_pal_range_status( dev, device_range_status, 03577 signal_rate, effective_spad_rtn_count, 03578 p_ranging_measurement_data, &pal_range_status ); 03579 03580 if ( status == VL53L0X_ERROR_NONE ) 03581 p_ranging_measurement_data->RangeStatus = pal_range_status; 03582 03583 } 03584 03585 if ( status == VL53L0X_ERROR_NONE ) { 03586 /* Copy last read data into Dev buffer */ 03587 last_range_data_buffer = PALDevDataGet( dev, LastRangeMeasure ); 03588 03589 last_range_data_buffer.RangeMilliMeter = 03590 p_ranging_measurement_data->RangeMilliMeter; 03591 last_range_data_buffer.RangeFractionalPart = 03592 p_ranging_measurement_data->RangeFractionalPart; 03593 last_range_data_buffer.RangeDMaxMilliMeter = 03594 p_ranging_measurement_data->RangeDMaxMilliMeter; 03595 last_range_data_buffer.MeasurementTimeUsec = 03596 p_ranging_measurement_data->MeasurementTimeUsec; 03597 last_range_data_buffer.SignalRateRtnMegaCps = 03598 p_ranging_measurement_data->SignalRateRtnMegaCps; 03599 last_range_data_buffer.AmbientRateRtnMegaCps = 03600 p_ranging_measurement_data->AmbientRateRtnMegaCps; 03601 last_range_data_buffer.EffectiveSpadRtnCount = 03602 p_ranging_measurement_data->EffectiveSpadRtnCount; 03603 last_range_data_buffer.RangeStatus = 03604 p_ranging_measurement_data->RangeStatus; 03605 03606 PALDevDataSet( dev, LastRangeMeasure, last_range_data_buffer ); 03607 } 03608 03609 LOG_FUNCTION_END( status ); 03610 return status; 03611 } 03612 03613 VL53L0X_Error VL53L0X::vl53l0x_perform_single_ranging_measurement( VL53L0X_DEV dev, 03614 VL53L0X_RangingMeasurementData_t *p_ranging_measurement_data ) 03615 { 03616 VL53L0X_Error status = VL53L0X_ERROR_NONE; 03617 03618 LOG_FUNCTION_START( "" ); 03619 03620 /* This function will do a complete single ranging 03621 * Here we fix the mode! */ 03622 status = vl53l0x_set_device_mode( dev, VL53L0X_DEVICEMODE_SINGLE_RANGING ); 03623 03624 if ( status == VL53L0X_ERROR_NONE ) 03625 status = vl53l0x_perform_single_measurement( dev ); 03626 03627 03628 if ( status == VL53L0X_ERROR_NONE ) 03629 status = vl53l0x_get_ranging_measurement_data( dev, 03630 p_ranging_measurement_data ); 03631 03632 03633 if ( status == VL53L0X_ERROR_NONE ) 03634 status = vl53l0x_clear_interrupt_mask( dev, 0 ); 03635 03636 03637 LOG_FUNCTION_END( status ); 03638 return status; 03639 } 03640 03641 VL53L0X_Error VL53L0X::perform_ref_signal_measurement( VL53L0X_DEV dev, 03642 uint16_t *p_ref_signal_rate ) 03643 { 03644 VL53L0X_Error status = VL53L0X_ERROR_NONE; 03645 VL53L0X_RangingMeasurementData_t ranging_measurement_data; 03646 03647 uint8_t sequence_config = 0; 03648 03649 /* store the value of the sequence config, 03650 * this will be reset before the end of the function 03651 */ 03652 03653 sequence_config = PALDevDataGet( dev, SequenceConfig ); 03654 03655 /* 03656 * This function performs a reference signal rate measurement. 03657 */ 03658 if ( status == VL53L0X_ERROR_NONE ) 03659 status = vl53l0x_write_byte( dev, 03660 VL53L0X_REG_SYSTEM_SEQUENCE_CONFIG, 0xC0 ); 03661 03662 if ( status == VL53L0X_ERROR_NONE ) 03663 status = vl53l0x_perform_single_ranging_measurement( dev, 03664 &ranging_measurement_data ); 03665 03666 if ( status == VL53L0X_ERROR_NONE ) 03667 status = vl53l0x_write_byte( dev, 0xFF, 0x01 ); 03668 03669 if ( status == VL53L0X_ERROR_NONE ) 03670 status = vl53l0x_read_word( dev, 03671 VL53L0X_REG_RESULT_PEAK_SIGNAL_RATE_REF, 03672 p_ref_signal_rate ); 03673 03674 if ( status == VL53L0X_ERROR_NONE ) 03675 status = vl53l0x_write_byte( dev, 0xFF, 0x00 ); 03676 03677 if ( status == VL53L0X_ERROR_NONE ) { 03678 /* restore the previous Sequence Config */ 03679 status = vl53l0x_write_byte( dev, VL53L0X_REG_SYSTEM_SEQUENCE_CONFIG, 03680 sequence_config ); 03681 if ( status == VL53L0X_ERROR_NONE ) 03682 PALDevDataSet( dev, SequenceConfig, sequence_config ); 03683 } 03684 03685 return status; 03686 } 03687 03688 VL53L0X_Error VL53L0X::wrapped_vl53l0x_perform_ref_spad_management( VL53L0X_DEV dev, 03689 uint32_t *ref_spad_count, 03690 uint8_t *is_aperture_spads ) 03691 { 03692 VL53L0X_Error status = VL53L0X_ERROR_NONE; 03693 uint8_t last_spad_array[6]; 03694 uint8_t start_select = 0xB4; 03695 uint32_t minimum_spad_count = 3; 03696 uint32_t max_spad_count = 44; 03697 uint32_t current_spad_index = 0; 03698 uint32_t last_spad_index = 0; 03699 int32_t next_good_spad = 0; 03700 uint16_t target_ref_rate = 0x0A00; /* 20 MCPS in 9:7 format */ 03701 uint16_t peak_signal_rate_ref; 03702 uint32_t need_apt_spads = 0; 03703 uint32_t index = 0; 03704 uint32_t spad_array_size = 6; 03705 uint32_t signal_rate_diff = 0; 03706 uint32_t last_signal_rate_diff = 0; 03707 uint8_t complete = 0; 03708 uint8_t vhv_settings = 0; 03709 uint8_t phase_cal = 0; 03710 uint32_t ref_spad_count_int = 0; 03711 uint8_t is_aperture_spads_int = 0; 03712 03713 /* 03714 * The reference SPAD initialization procedure determines the minimum 03715 * amount of reference spads to be enables to achieve a target reference 03716 * signal rate and should be performed once during initialization. 03717 * 03718 * Either aperture or non-aperture spads are applied but never both. 03719 * Firstly non-aperture spads are set, begining with 5 spads, and 03720 * increased one spad at a time until the closest measurement to the 03721 * target rate is achieved. 03722 * 03723 * If the target rate is exceeded when 5 non-aperture spads are enabled, 03724 * initialization is performed instead with aperture spads. 03725 * 03726 * When setting spads, a 'Good Spad Map' is applied. 03727 * 03728 * This procedure operates within a SPAD window of interest of a maximum 03729 * 44 spads. 03730 * The start point is currently fixed to 180, which lies towards the end 03731 * of the non-aperture quadrant and runs in to the adjacent aperture 03732 * quadrant. 03733 */ 03734 03735 03736 target_ref_rate = PALDevDataGet( dev, targetRefRate ); 03737 03738 /* 03739 * Initialize Spad arrays. 03740 * Currently the good spad map is initialised to 'All good'. 03741 * This is a short term implementation. The good spad map will be 03742 * provided as an input. 03743 * Note that there are 6 bytes. Only the first 44 bits will be used to 03744 * represent spads. 03745 */ 03746 for ( index = 0; index < spad_array_size; index++ ) 03747 dev->Data .SpadData .RefSpadEnables [index] = 0; 03748 03749 03750 status = vl53l0x_write_byte( dev, 0xFF, 0x01 ); 03751 03752 if ( status == VL53L0X_ERROR_NONE ) 03753 status = vl53l0x_write_byte( dev, 03754 VL53L0X_REG_DYNAMIC_SPAD_REF_EN_START_OFFSET, 0x00 ); 03755 03756 if ( status == VL53L0X_ERROR_NONE ) 03757 status = vl53l0x_write_byte( dev, 03758 VL53L0X_REG_DYNAMIC_SPAD_NUM_REQUESTED_REF_SPAD, 0x2C ); 03759 03760 if ( status == VL53L0X_ERROR_NONE ) 03761 status = vl53l0x_write_byte( dev, 0xFF, 0x00 ); 03762 03763 if ( status == VL53L0X_ERROR_NONE ) 03764 status = vl53l0x_write_byte( dev, 03765 VL53L0X_REG_GLOBAL_CONFIG_REF_EN_START_SELECT, 03766 start_select ); 03767 03768 03769 if ( status == VL53L0X_ERROR_NONE ) 03770 status = vl53l0x_write_byte( dev, 03771 VL53L0X_REG_POWER_MANAGEMENT_GO1_POWER_FORCE, 0 ); 03772 03773 /* Perform ref calibration */ 03774 if ( status == VL53L0X_ERROR_NONE ) 03775 status = vl53l0x_perform_ref_calibration( dev, &vhv_settings, 03776 &phase_cal, 0 ); 03777 03778 if ( status == VL53L0X_ERROR_NONE ) { 03779 /* Enable Minimum NON-APERTURE Spads */ 03780 current_spad_index = 0; 03781 last_spad_index = current_spad_index; 03782 need_apt_spads = 0; 03783 status = enable_ref_spads( dev, 03784 need_apt_spads, 03785 dev->Data .SpadData .RefGoodSpadMap , 03786 dev->Data .SpadData .RefSpadEnables , 03787 spad_array_size, 03788 start_select, 03789 current_spad_index, 03790 minimum_spad_count, 03791 &last_spad_index ); 03792 } 03793 03794 if ( status == VL53L0X_ERROR_NONE ) { 03795 current_spad_index = last_spad_index; 03796 03797 status = perform_ref_signal_measurement( dev, 03798 &peak_signal_rate_ref ); 03799 if ( ( status == VL53L0X_ERROR_NONE ) && 03800 ( peak_signal_rate_ref > target_ref_rate ) ) { 03801 /* Signal rate measurement too high, 03802 * switch to APERTURE SPADs */ 03803 03804 for ( index = 0; index < spad_array_size; index++ ) 03805 dev->Data .SpadData .RefSpadEnables [index] = 0; 03806 03807 03808 /* Increment to the first APERTURE spad */ 03809 while ( ( is_aperture( start_select + current_spad_index ) 03810 == 0 ) && ( current_spad_index < max_spad_count ) ) { 03811 current_spad_index++; 03812 } 03813 03814 need_apt_spads = 1; 03815 03816 status = enable_ref_spads( dev, 03817 need_apt_spads, 03818 dev->Data .SpadData .RefGoodSpadMap , 03819 dev->Data .SpadData .RefSpadEnables , 03820 spad_array_size, 03821 start_select, 03822 current_spad_index, 03823 minimum_spad_count, 03824 &last_spad_index ); 03825 03826 if ( status == VL53L0X_ERROR_NONE ) { 03827 current_spad_index = last_spad_index; 03828 status = perform_ref_signal_measurement( dev, 03829 &peak_signal_rate_ref ); 03830 03831 if ( ( status == VL53L0X_ERROR_NONE ) && 03832 ( peak_signal_rate_ref > target_ref_rate ) ) { 03833 /* Signal rate still too high after 03834 * setting the minimum number of 03835 * APERTURE spads. Can do no more 03836 * therefore set the min number of 03837 * aperture spads as the result. 03838 */ 03839 is_aperture_spads_int = 1; 03840 ref_spad_count_int = minimum_spad_count; 03841 } 03842 } 03843 } else { 03844 need_apt_spads = 0; 03845 } 03846 } 03847 03848 if ( ( status == VL53L0X_ERROR_NONE ) && 03849 ( peak_signal_rate_ref < target_ref_rate ) ) { 03850 /* At this point, the minimum number of either aperture 03851 * or non-aperture spads have been set. Proceed to add 03852 * spads and perform measurements until the target 03853 * reference is reached. 03854 */ 03855 is_aperture_spads_int = need_apt_spads; 03856 ref_spad_count_int = minimum_spad_count; 03857 03858 memcpy( last_spad_array, dev->Data .SpadData .RefSpadEnables , 03859 spad_array_size ); 03860 last_signal_rate_diff = abs( peak_signal_rate_ref - 03861 target_ref_rate ); 03862 complete = 0; 03863 03864 while ( !complete ) { 03865 get_next_good_spad( 03866 dev->Data .SpadData .RefGoodSpadMap , 03867 spad_array_size, current_spad_index, 03868 &next_good_spad ); 03869 03870 if ( next_good_spad == -1 ) { 03871 status = VL53L0X_ERROR_REF_SPAD_INIT; 03872 break; 03873 } 03874 03875 /* Cannot combine Aperture and Non-Aperture spads, so 03876 * ensure the current spad is of the correct type. 03877 */ 03878 if ( is_aperture( ( uint32_t )start_select + next_good_spad ) != 03879 need_apt_spads ) { 03880 /* At this point we have enabled the maximum 03881 * number of Aperture spads. 03882 */ 03883 complete = 1; 03884 break; 03885 } 03886 03887 ( ref_spad_count_int )++; 03888 03889 current_spad_index = next_good_spad; 03890 status = enable_spad_bit( 03891 dev->Data .SpadData .RefSpadEnables , 03892 spad_array_size, current_spad_index ); 03893 03894 if ( status == VL53L0X_ERROR_NONE ) { 03895 current_spad_index++; 03896 /* Proceed to apply the additional spad and 03897 * perform measurement. */ 03898 status = set_ref_spad_map( dev, 03899 dev->Data .SpadData .RefSpadEnables ); 03900 } 03901 03902 if ( status != VL53L0X_ERROR_NONE ) 03903 break; 03904 03905 status = perform_ref_signal_measurement( dev, 03906 &peak_signal_rate_ref ); 03907 03908 if ( status != VL53L0X_ERROR_NONE ) 03909 break; 03910 03911 signal_rate_diff = abs( peak_signal_rate_ref - target_ref_rate ); 03912 03913 if ( peak_signal_rate_ref > target_ref_rate ) { 03914 /* Select the spad map that provides the 03915 * measurement closest to the target rate, 03916 * either above or below it. 03917 */ 03918 if ( signal_rate_diff > last_signal_rate_diff ) { 03919 /* Previous spad map produced a closer 03920 * measurement, so choose this. */ 03921 status = set_ref_spad_map( dev, 03922 last_spad_array ); 03923 memcpy( 03924 dev->Data .SpadData .RefSpadEnables , 03925 last_spad_array, spad_array_size ); 03926 03927 ( ref_spad_count_int )--; 03928 } 03929 complete = 1; 03930 } else { 03931 /* Continue to add spads */ 03932 last_signal_rate_diff = signal_rate_diff; 03933 memcpy( last_spad_array, 03934 dev->Data .SpadData .RefSpadEnables , 03935 spad_array_size ); 03936 } 03937 03938 } /* while */ 03939 } 03940 03941 if ( status == VL53L0X_ERROR_NONE ) { 03942 *ref_spad_count = ref_spad_count_int; 03943 *is_aperture_spads = is_aperture_spads_int; 03944 03945 VL53L0X_SETDEVICESPECIFICPARAMETER( dev, RefSpadsInitialised, 1 ); 03946 VL53L0X_SETDEVICESPECIFICPARAMETER( dev, 03947 ReferenceSpadCount, ( uint8_t )( *ref_spad_count ) ); 03948 VL53L0X_SETDEVICESPECIFICPARAMETER( dev, 03949 ReferenceSpadType, *is_aperture_spads ); 03950 } 03951 03952 return status; 03953 } 03954 03955 VL53L0X_Error VL53L0X::wrapped_vl53l0x_set_reference_spads( VL53L0X_DEV dev, 03956 uint32_t count, uint8_t is_aperture_spads ) 03957 { 03958 VL53L0X_Error status = VL53L0X_ERROR_NONE; 03959 uint32_t current_spad_index = 0; 03960 uint8_t start_select = 0xB4; 03961 uint32_t spad_array_size = 6; 03962 uint32_t max_spad_count = 44; 03963 uint32_t last_spad_index; 03964 uint32_t index; 03965 03966 /* 03967 * This function applies a requested number of reference spads, either 03968 * aperture or 03969 * non-aperture, as requested. 03970 * The good spad map will be applied. 03971 */ 03972 03973 status = vl53l0x_write_byte( dev, 0xFF, 0x01 ); 03974 03975 if ( status == VL53L0X_ERROR_NONE ) 03976 status = vl53l0x_write_byte( dev, 03977 VL53L0X_REG_DYNAMIC_SPAD_REF_EN_START_OFFSET, 0x00 ); 03978 03979 if ( status == VL53L0X_ERROR_NONE ) 03980 status = vl53l0x_write_byte( dev, 03981 VL53L0X_REG_DYNAMIC_SPAD_NUM_REQUESTED_REF_SPAD, 0x2C ); 03982 03983 if ( status == VL53L0X_ERROR_NONE ) 03984 status = vl53l0x_write_byte( dev, 0xFF, 0x00 ); 03985 03986 if ( status == VL53L0X_ERROR_NONE ) 03987 status = vl53l0x_write_byte( dev, 03988 VL53L0X_REG_GLOBAL_CONFIG_REF_EN_START_SELECT, 03989 start_select ); 03990 03991 for ( index = 0; index < spad_array_size; index++ ) 03992 dev->Data .SpadData .RefSpadEnables [index] = 0; 03993 03994 if ( is_aperture_spads ) { 03995 /* Increment to the first APERTURE spad */ 03996 while ( ( is_aperture( start_select + current_spad_index ) == 0 ) && 03997 ( current_spad_index < max_spad_count ) ) { 03998 current_spad_index++; 03999 } 04000 } 04001 status = enable_ref_spads( dev, 04002 is_aperture_spads, 04003 dev->Data .SpadData .RefGoodSpadMap , 04004 dev->Data .SpadData .RefSpadEnables , 04005 spad_array_size, 04006 start_select, 04007 current_spad_index, 04008 count, 04009 &last_spad_index ); 04010 04011 if ( status == VL53L0X_ERROR_NONE ) { 04012 VL53L0X_SETDEVICESPECIFICPARAMETER( dev, RefSpadsInitialised, 1 ); 04013 VL53L0X_SETDEVICESPECIFICPARAMETER( dev, 04014 ReferenceSpadCount, ( uint8_t )( count ) ); 04015 VL53L0X_SETDEVICESPECIFICPARAMETER( dev, 04016 ReferenceSpadType, is_aperture_spads ); 04017 } 04018 04019 return status; 04020 } 04021 04022 VL53L0X_Error VL53L0X::vl53l0x_wait_device_booted( VL53L0X_DEV dev ) 04023 { 04024 VL53L0X_Error status = VL53L0X_ERROR_NOT_IMPLEMENTED; 04025 LOG_FUNCTION_START( "" ); 04026 04027 /* not implemented on VL53L0X */ 04028 04029 LOG_FUNCTION_END( status ); 04030 return status; 04031 } 04032 04033 VL53L0X_Error VL53L0X::vl53l0x_perform_ref_calibration( VL53L0X_DEV dev, uint8_t *p_vhv_settings, 04034 uint8_t *p_phase_cal ) 04035 { 04036 VL53L0X_Error status = VL53L0X_ERROR_NONE; 04037 LOG_FUNCTION_START( "" ); 04038 04039 status = vl53l0x_perform_ref_calibration( dev, p_vhv_settings, 04040 p_phase_cal, 1 ); 04041 04042 LOG_FUNCTION_END( status ); 04043 return status; 04044 } 04045 04046 VL53L0X_Error VL53L0X::vl53l0x_perform_ref_spad_management( VL53L0X_DEV dev, 04047 uint32_t *ref_spad_count, uint8_t *is_aperture_spads ) 04048 { 04049 VL53L0X_Error status = VL53L0X_ERROR_NONE; 04050 LOG_FUNCTION_START( "" ); 04051 04052 status = wrapped_vl53l0x_perform_ref_spad_management( dev, ref_spad_count, 04053 is_aperture_spads ); 04054 04055 LOG_FUNCTION_END( status ); 04056 04057 return status; 04058 } 04059 04060 /* Group PAL Init Functions */ 04061 VL53L0X_Error VL53L0X::vl53l0x_set_device_address( VL53L0X_DEV dev, uint8_t device_address ) 04062 { 04063 VL53L0X_Error status = VL53L0X_ERROR_NONE; 04064 LOG_FUNCTION_START( "" ); 04065 04066 status = vl53l0x_write_byte( dev, VL53L0X_REG_I2C_SLAVE_DEVICE_ADDRESS, 04067 device_address / 2 ); 04068 04069 LOG_FUNCTION_END( status ); 04070 return status; 04071 } 04072 04073 VL53L0X_Error VL53L0X::vl53l0x_set_gpio_config( VL53L0X_DEV dev, uint8_t pin, 04074 VL53L0X_DeviceModes device_mode, VL53L0X_GpioFunctionality functionality, 04075 VL53L0X_InterruptPolarity polarity ) 04076 { 04077 VL53L0X_Error status = VL53L0X_ERROR_NONE; 04078 uint8_t data; 04079 04080 LOG_FUNCTION_START( "" ); 04081 04082 if ( pin != 0 ) { 04083 status = VL53L0X_ERROR_GPIO_NOT_EXISTING; 04084 } else if ( device_mode == VL53L0X_DEVICEMODE_GPIO_DRIVE ) { 04085 if ( polarity == VL53L0X_INTERRUPTPOLARITY_LOW ) 04086 data = 0x10; 04087 else 04088 data = 1; 04089 04090 status = vl53l0x_write_byte( dev, 04091 VL53L0X_REG_GPIO_HV_MUX_ACTIVE_HIGH, data ); 04092 04093 } else if ( device_mode == VL53L0X_DEVICEMODE_GPIO_OSC ) { 04094 04095 status |= vl53l0x_write_byte( dev, 0xff, 0x01 ); 04096 status |= vl53l0x_write_byte( dev, 0x00, 0x00 ); 04097 04098 status |= vl53l0x_write_byte( dev, 0xff, 0x00 ); 04099 status |= vl53l0x_write_byte( dev, 0x80, 0x01 ); 04100 status |= vl53l0x_write_byte( dev, 0x85, 0x02 ); 04101 04102 status |= vl53l0x_write_byte( dev, 0xff, 0x04 ); 04103 status |= vl53l0x_write_byte( dev, 0xcd, 0x00 ); 04104 status |= vl53l0x_write_byte( dev, 0xcc, 0x11 ); 04105 04106 status |= vl53l0x_write_byte( dev, 0xff, 0x07 ); 04107 status |= vl53l0x_write_byte( dev, 0xbe, 0x00 ); 04108 04109 status |= vl53l0x_write_byte( dev, 0xff, 0x06 ); 04110 status |= vl53l0x_write_byte( dev, 0xcc, 0x09 ); 04111 04112 status |= vl53l0x_write_byte( dev, 0xff, 0x00 ); 04113 status |= vl53l0x_write_byte( dev, 0xff, 0x01 ); 04114 status |= vl53l0x_write_byte( dev, 0x00, 0x00 ); 04115 04116 } else { 04117 04118 if ( status == VL53L0X_ERROR_NONE ) { 04119 switch ( functionality ) { 04120 case VL53L0X_GPIOFUNCTIONALITY_OFF: 04121 data = 0x00; 04122 break; 04123 case VL53L0X_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_LOW: 04124 data = 0x01; 04125 break; 04126 case VL53L0X_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_HIGH: 04127 data = 0x02; 04128 break; 04129 case VL53L0X_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_OUT: 04130 data = 0x03; 04131 break; 04132 case VL53L0X_GPIOFUNCTIONALITY_NEW_MEASURE_READY: 04133 data = 0x04; 04134 break; 04135 default: 04136 status = 04137 VL53L0X_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED; 04138 } 04139 } 04140 04141 if ( status == VL53L0X_ERROR_NONE ) 04142 status = vl53l0x_write_byte( dev, 04143 VL53L0X_REG_SYSTEM_INTERRUPT_CONFIG_GPIO, data ); 04144 04145 if ( status == VL53L0X_ERROR_NONE ) { 04146 if ( polarity == VL53L0X_INTERRUPTPOLARITY_LOW ) 04147 data = 0; 04148 else 04149 data = ( uint8_t )( 1 << 4 ); 04150 04151 status = vl53l0x_update_byte( dev, 04152 VL53L0X_REG_GPIO_HV_MUX_ACTIVE_HIGH, 0xEF, data ); 04153 } 04154 04155 if ( status == VL53L0X_ERROR_NONE ) 04156 VL53L0X_SETDEVICESPECIFICPARAMETER( dev, 04157 Pin0GpioFunctionality, functionality ); 04158 04159 if ( status == VL53L0X_ERROR_NONE ) 04160 status = vl53l0x_clear_interrupt_mask( dev, 0 ); 04161 04162 } 04163 LOG_FUNCTION_END( status ); 04164 return status; 04165 } 04166 04167 VL53L0X_Error VL53L0X::vl53l0x_get_fraction_enable( VL53L0X_DEV dev, uint8_t *p_enabled ) 04168 { 04169 VL53L0X_Error status = VL53L0X_ERROR_NONE; 04170 LOG_FUNCTION_START( "" ); 04171 04172 status = vl53l0x_read_byte( dev, VL53L0X_REG_SYSTEM_RANGE_CONFIG, p_enabled ); 04173 04174 if ( status == VL53L0X_ERROR_NONE ) 04175 *p_enabled = ( *p_enabled & 1 ); 04176 04177 LOG_FUNCTION_END( status ); 04178 return status; 04179 } 04180 04181 uint16_t VL53L0X::vl53l0x_encode_timeout( uint32_t timeout_macro_clks ) 04182 { 04183 /*! 04184 * Encode timeout in macro periods in (LSByte * 2^MSByte) + 1 format 04185 */ 04186 04187 uint16_t encoded_timeout = 0; 04188 uint32_t ls_byte = 0; 04189 uint16_t ms_byte = 0; 04190 04191 if ( timeout_macro_clks > 0 ) { 04192 ls_byte = timeout_macro_clks - 1; 04193 04194 while ( ( ls_byte & 0xFFFFFF00 ) > 0 ) { 04195 ls_byte = ls_byte >> 1; 04196 ms_byte++; 04197 } 04198 04199 encoded_timeout = ( ms_byte << 8 ) 04200 + ( uint16_t ) ( ls_byte & 0x000000FF ); 04201 } 04202 04203 return encoded_timeout; 04204 04205 } 04206 04207 VL53L0X_Error VL53L0X::set_sequence_step_timeout( VL53L0X_DEV dev, 04208 VL53L0X_SequenceStepId sequence_step_id, 04209 uint32_t timeout_micro_secs ) 04210 { 04211 VL53L0X_Error status = VL53L0X_ERROR_NONE; 04212 uint8_t current_vcsel_pulse_period_p_clk; 04213 uint8_t msrc_encoded_time_out; 04214 uint16_t pre_range_encoded_time_out; 04215 uint16_t pre_range_time_out_m_clks; 04216 uint16_t msrc_range_time_out_m_clks; 04217 uint32_t final_range_time_out_m_clks; 04218 uint16_t final_range_encoded_time_out; 04219 VL53L0X_SchedulerSequenceSteps_t scheduler_sequence_steps; 04220 04221 if ( ( sequence_step_id == VL53L0X_SEQUENCESTEP_TCC ) || 04222 ( sequence_step_id == VL53L0X_SEQUENCESTEP_DSS ) || 04223 ( sequence_step_id == VL53L0X_SEQUENCESTEP_MSRC ) ) { 04224 04225 status = vl53l0x_get_vcsel_pulse_period( dev, 04226 VL53L0X_VCSEL_PERIOD_PRE_RANGE, 04227 ¤t_vcsel_pulse_period_p_clk ); 04228 04229 if ( status == VL53L0X_ERROR_NONE ) { 04230 msrc_range_time_out_m_clks = vl53l0x_calc_timeout_mclks( dev, 04231 timeout_micro_secs, 04232 ( uint8_t )current_vcsel_pulse_period_p_clk ); 04233 04234 if ( msrc_range_time_out_m_clks > 256 ) 04235 msrc_encoded_time_out = 255; 04236 else 04237 msrc_encoded_time_out = 04238 ( uint8_t )msrc_range_time_out_m_clks - 1; 04239 04240 VL53L0X_SETDEVICESPECIFICPARAMETER( dev, 04241 LastEncodedTimeout, 04242 msrc_encoded_time_out ); 04243 } 04244 04245 if ( status == VL53L0X_ERROR_NONE ) { 04246 status = vl53l0x_write_byte( dev, 04247 VL53L0X_REG_MSRC_CONFIG_TIMEOUT_MACROP, 04248 msrc_encoded_time_out ); 04249 } 04250 } else { 04251 04252 if ( sequence_step_id == VL53L0X_SEQUENCESTEP_PRE_RANGE ) { 04253 04254 if ( status == VL53L0X_ERROR_NONE ) { 04255 status = vl53l0x_get_vcsel_pulse_period( dev, 04256 VL53L0X_VCSEL_PERIOD_PRE_RANGE, 04257 ¤t_vcsel_pulse_period_p_clk ); 04258 pre_range_time_out_m_clks = 04259 vl53l0x_calc_timeout_mclks( dev, 04260 timeout_micro_secs, 04261 ( uint8_t )current_vcsel_pulse_period_p_clk ); 04262 pre_range_encoded_time_out = vl53l0x_encode_timeout( 04263 pre_range_time_out_m_clks ); 04264 04265 VL53L0X_SETDEVICESPECIFICPARAMETER( dev, 04266 LastEncodedTimeout, 04267 pre_range_encoded_time_out ); 04268 } 04269 04270 if ( status == VL53L0X_ERROR_NONE ) { 04271 status = vl53l0x_write_word( dev, 04272 VL53L0X_REG_PRE_RANGE_CONFIG_TIMEOUT_MACROP_HI, 04273 pre_range_encoded_time_out ); 04274 } 04275 04276 if ( status == VL53L0X_ERROR_NONE ) { 04277 VL53L0X_SETDEVICESPECIFICPARAMETER( 04278 dev, 04279 PreRangeTimeoutMicroSecs, 04280 timeout_micro_secs ); 04281 } 04282 } else if ( sequence_step_id == VL53L0X_SEQUENCESTEP_FINAL_RANGE ) { 04283 04284 /* For the final range timeout, the pre-range timeout 04285 * must be added. To do this both final and pre-range 04286 * timeouts must be expressed in macro periods MClks 04287 * because they have different vcsel periods. 04288 */ 04289 04290 vl53l0x_get_sequence_step_enables( dev, 04291 &scheduler_sequence_steps ); 04292 pre_range_time_out_m_clks = 0; 04293 if ( scheduler_sequence_steps.PreRangeOn ) { 04294 04295 /* Retrieve PRE-RANGE VCSEL Period */ 04296 status = vl53l0x_get_vcsel_pulse_period( dev, 04297 VL53L0X_VCSEL_PERIOD_PRE_RANGE, 04298 ¤t_vcsel_pulse_period_p_clk ); 04299 04300 /* Retrieve PRE-RANGE Timeout in Macro periods 04301 * (MCLKS) */ 04302 if ( status == VL53L0X_ERROR_NONE ) { 04303 status = vl53l0x_read_word( dev, 0x51, 04304 &pre_range_encoded_time_out ); 04305 pre_range_time_out_m_clks = 04306 vl53l0x_decode_timeout( 04307 pre_range_encoded_time_out ); 04308 } 04309 } 04310 04311 /* Calculate FINAL RANGE Timeout in Macro Periods 04312 * (MCLKS) and add PRE-RANGE value 04313 */ 04314 if ( status == VL53L0X_ERROR_NONE ) { 04315 04316 status = vl53l0x_get_vcsel_pulse_period( dev, 04317 VL53L0X_VCSEL_PERIOD_FINAL_RANGE, 04318 ¤t_vcsel_pulse_period_p_clk ); 04319 } 04320 if ( status == VL53L0X_ERROR_NONE ) { 04321 04322 final_range_time_out_m_clks = 04323 vl53l0x_calc_timeout_mclks( dev, 04324 timeout_micro_secs, 04325 ( uint8_t ) current_vcsel_pulse_period_p_clk ); 04326 04327 final_range_time_out_m_clks += pre_range_time_out_m_clks; 04328 04329 final_range_encoded_time_out = 04330 vl53l0x_encode_timeout( final_range_time_out_m_clks ); 04331 04332 if ( status == VL53L0X_ERROR_NONE ) { 04333 status = vl53l0x_write_word( dev, 0x71, 04334 final_range_encoded_time_out ); 04335 } 04336 04337 if ( status == VL53L0X_ERROR_NONE ) { 04338 VL53L0X_SETDEVICESPECIFICPARAMETER( 04339 dev, 04340 FinalRangeTimeoutMicroSecs, 04341 timeout_micro_secs ); 04342 } 04343 } 04344 } else 04345 status = VL53L0X_ERROR_INVALID_PARAMS; 04346 04347 } 04348 return status; 04349 } 04350 04351 VL53L0X_Error VL53L0X::wrapped_vl53l0x_set_measurement_timing_budget_micro_seconds( VL53L0X_DEV dev, 04352 uint32_t measurement_timing_budget_micro_seconds ) 04353 { 04354 VL53L0X_Error status = VL53L0X_ERROR_NONE; 04355 uint32_t final_range_timing_budget_micro_seconds; 04356 VL53L0X_SchedulerSequenceSteps_t scheduler_sequence_steps; 04357 uint32_t msrc_dcc_tcc_timeout_micro_seconds = 2000; 04358 uint32_t start_overhead_micro_seconds = 1910; 04359 uint32_t end_overhead_micro_seconds = 960; 04360 uint32_t msrc_overhead_micro_seconds = 660; 04361 uint32_t tcc_overhead_micro_seconds = 590; 04362 uint32_t dss_overhead_micro_seconds = 690; 04363 uint32_t pre_range_overhead_micro_seconds = 660; 04364 uint32_t final_range_overhead_micro_seconds = 550; 04365 uint32_t pre_range_timeout_micro_seconds = 0; 04366 uint32_t c_min_timing_budget_micro_seconds = 20000; 04367 uint32_t sub_timeout = 0; 04368 04369 LOG_FUNCTION_START( "" ); 04370 04371 if ( measurement_timing_budget_micro_seconds 04372 < c_min_timing_budget_micro_seconds ) { 04373 status = VL53L0X_ERROR_INVALID_PARAMS; 04374 return status; 04375 } 04376 04377 final_range_timing_budget_micro_seconds = 04378 measurement_timing_budget_micro_seconds - 04379 ( start_overhead_micro_seconds + end_overhead_micro_seconds ); 04380 04381 status = vl53l0x_get_sequence_step_enables( dev, &scheduler_sequence_steps ); 04382 04383 if ( status == VL53L0X_ERROR_NONE && 04384 ( scheduler_sequence_steps.TccOn || 04385 scheduler_sequence_steps.MsrcOn || 04386 scheduler_sequence_steps.DssOn ) ) { 04387 04388 /* TCC, MSRC and DSS all share the same timeout */ 04389 status = get_sequence_step_timeout( dev, 04390 VL53L0X_SEQUENCESTEP_MSRC, 04391 &msrc_dcc_tcc_timeout_micro_seconds ); 04392 04393 /* Subtract the TCC, MSRC and DSS timeouts if they are 04394 * enabled. */ 04395 04396 if ( status != VL53L0X_ERROR_NONE ) 04397 return status; 04398 04399 /* TCC */ 04400 if ( scheduler_sequence_steps.TccOn ) { 04401 04402 sub_timeout = msrc_dcc_tcc_timeout_micro_seconds 04403 + tcc_overhead_micro_seconds; 04404 04405 if ( sub_timeout < 04406 final_range_timing_budget_micro_seconds ) { 04407 final_range_timing_budget_micro_seconds -= 04408 sub_timeout; 04409 } else { 04410 /* Requested timeout too big. */ 04411 status = VL53L0X_ERROR_INVALID_PARAMS; 04412 } 04413 } 04414 04415 if ( status != VL53L0X_ERROR_NONE ) { 04416 LOG_FUNCTION_END( status ); 04417 return status; 04418 } 04419 04420 /* DSS */ 04421 if ( scheduler_sequence_steps.DssOn ) { 04422 04423 sub_timeout = 2 * ( msrc_dcc_tcc_timeout_micro_seconds + 04424 dss_overhead_micro_seconds ); 04425 04426 if ( sub_timeout < final_range_timing_budget_micro_seconds ) { 04427 final_range_timing_budget_micro_seconds 04428 -= sub_timeout; 04429 } else { 04430 /* Requested timeout too big. */ 04431 status = VL53L0X_ERROR_INVALID_PARAMS; 04432 } 04433 } else if ( scheduler_sequence_steps.MsrcOn ) { 04434 /* MSRC */ 04435 sub_timeout = msrc_dcc_tcc_timeout_micro_seconds + 04436 msrc_overhead_micro_seconds; 04437 04438 if ( sub_timeout < final_range_timing_budget_micro_seconds ) { 04439 final_range_timing_budget_micro_seconds 04440 -= sub_timeout; 04441 } else { 04442 /* Requested timeout too big. */ 04443 status = VL53L0X_ERROR_INVALID_PARAMS; 04444 } 04445 } 04446 04447 } 04448 04449 if ( status != VL53L0X_ERROR_NONE ) { 04450 LOG_FUNCTION_END( status ); 04451 return status; 04452 } 04453 04454 if ( scheduler_sequence_steps.PreRangeOn ) { 04455 04456 /* Subtract the Pre-range timeout if enabled. */ 04457 04458 status = get_sequence_step_timeout( dev, 04459 VL53L0X_SEQUENCESTEP_PRE_RANGE, 04460 &pre_range_timeout_micro_seconds ); 04461 04462 sub_timeout = pre_range_timeout_micro_seconds + 04463 pre_range_overhead_micro_seconds; 04464 04465 if ( sub_timeout < final_range_timing_budget_micro_seconds ) { 04466 final_range_timing_budget_micro_seconds -= sub_timeout; 04467 } else { 04468 /* Requested timeout too big. */ 04469 status = VL53L0X_ERROR_INVALID_PARAMS; 04470 } 04471 } 04472 04473 04474 if ( status == VL53L0X_ERROR_NONE && 04475 scheduler_sequence_steps.FinalRangeOn ) { 04476 04477 final_range_timing_budget_micro_seconds -= 04478 final_range_overhead_micro_seconds; 04479 04480 /* Final Range Timeout 04481 * Note that the final range timeout is determined by the timing 04482 * budget and the sum of all other timeouts within the sequence. 04483 * If there is no room for the final range timeout, then an error 04484 * will be set. Otherwise the remaining time will be applied to 04485 * the final range. 04486 */ 04487 status = set_sequence_step_timeout( dev, 04488 VL53L0X_SEQUENCESTEP_FINAL_RANGE, 04489 final_range_timing_budget_micro_seconds ); 04490 04491 VL53L0X_SETPARAMETERFIELD( dev, 04492 MeasurementTimingBudgetMicroSeconds, 04493 measurement_timing_budget_micro_seconds ); 04494 } 04495 04496 LOG_FUNCTION_END( status ); 04497 04498 return status; 04499 } 04500 04501 VL53L0X_Error VL53L0X::vl53l0x_set_measurement_timing_budget_micro_seconds( VL53L0X_DEV dev, 04502 uint32_t measurement_timing_budget_micro_seconds ) 04503 { 04504 VL53L0X_Error status = VL53L0X_ERROR_NONE; 04505 LOG_FUNCTION_START( "" ); 04506 04507 status = wrapped_vl53l0x_set_measurement_timing_budget_micro_seconds( dev, 04508 measurement_timing_budget_micro_seconds ); 04509 04510 LOG_FUNCTION_END( status ); 04511 04512 return status; 04513 } 04514 04515 VL53L0X_Error VL53L0X::vl53l0x_set_sequence_step_enable( VL53L0X_DEV dev, 04516 VL53L0X_SequenceStepId sequence_step_id, uint8_t sequence_step_enabled ) 04517 { 04518 VL53L0X_Error status = VL53L0X_ERROR_NONE; 04519 uint8_t sequence_config = 0; 04520 uint8_t sequence_config_new = 0; 04521 uint32_t measurement_timing_budget_micro_seconds; 04522 LOG_FUNCTION_START( "" ); 04523 04524 status = vl53l0x_read_byte( dev, VL53L0X_REG_SYSTEM_SEQUENCE_CONFIG, 04525 &sequence_config ); 04526 04527 sequence_config_new = sequence_config; 04528 04529 if ( status == VL53L0X_ERROR_NONE ) { 04530 if ( sequence_step_enabled == 1 ) { 04531 04532 /* Enable requested sequence step 04533 */ 04534 switch ( sequence_step_id ) { 04535 case VL53L0X_SEQUENCESTEP_TCC: 04536 sequence_config_new |= 0x10; 04537 break; 04538 case VL53L0X_SEQUENCESTEP_DSS: 04539 sequence_config_new |= 0x28; 04540 break; 04541 case VL53L0X_SEQUENCESTEP_MSRC: 04542 sequence_config_new |= 0x04; 04543 break; 04544 case VL53L0X_SEQUENCESTEP_PRE_RANGE: 04545 sequence_config_new |= 0x40; 04546 break; 04547 case VL53L0X_SEQUENCESTEP_FINAL_RANGE: 04548 sequence_config_new |= 0x80; 04549 break; 04550 default: 04551 status = VL53L0X_ERROR_INVALID_PARAMS; 04552 } 04553 } else { 04554 /* Disable requested sequence step 04555 */ 04556 switch ( sequence_step_id ) { 04557 case VL53L0X_SEQUENCESTEP_TCC: 04558 sequence_config_new &= 0xef; 04559 break; 04560 case VL53L0X_SEQUENCESTEP_DSS: 04561 sequence_config_new &= 0xd7; 04562 break; 04563 case VL53L0X_SEQUENCESTEP_MSRC: 04564 sequence_config_new &= 0xfb; 04565 break; 04566 case VL53L0X_SEQUENCESTEP_PRE_RANGE: 04567 sequence_config_new &= 0xbf; 04568 break; 04569 case VL53L0X_SEQUENCESTEP_FINAL_RANGE: 04570 sequence_config_new &= 0x7f; 04571 break; 04572 default: 04573 status = VL53L0X_ERROR_INVALID_PARAMS; 04574 } 04575 } 04576 } 04577 04578 if ( sequence_config_new != sequence_config ) { 04579 /* Apply New Setting */ 04580 if ( status == VL53L0X_ERROR_NONE ) { 04581 status = vl53l0x_write_byte( dev, 04582 VL53L0X_REG_SYSTEM_SEQUENCE_CONFIG, sequence_config_new ); 04583 } 04584 if ( status == VL53L0X_ERROR_NONE ) 04585 PALDevDataSet( dev, SequenceConfig, sequence_config_new ); 04586 04587 04588 /* Recalculate timing budget */ 04589 if ( status == VL53L0X_ERROR_NONE ) { 04590 VL53L0X_GETPARAMETERFIELD( dev, 04591 MeasurementTimingBudgetMicroSeconds, 04592 measurement_timing_budget_micro_seconds ); 04593 04594 vl53l0x_set_measurement_timing_budget_micro_seconds( dev, 04595 measurement_timing_budget_micro_seconds ); 04596 } 04597 } 04598 04599 LOG_FUNCTION_END( status ); 04600 04601 return status; 04602 } 04603 04604 VL53L0X_Error VL53L0X::vl53l0x_set_limit_check_enable( VL53L0X_DEV dev, uint16_t limit_check_id, 04605 uint8_t limit_check_enable ) 04606 { 04607 VL53L0X_Error status = VL53L0X_ERROR_NONE; 04608 FixPoint1616_t temp_fix1616 = 0; 04609 uint8_t limit_check_enable_int = 0; 04610 uint8_t limit_check_disable = 0; 04611 uint8_t temp8; 04612 04613 LOG_FUNCTION_START( "" ); 04614 04615 if ( limit_check_id >= VL53L0X_CHECKENABLE_NUMBER_OF_CHECKS ) { 04616 status = VL53L0X_ERROR_INVALID_PARAMS; 04617 } else { 04618 if ( limit_check_enable == 0 ) { 04619 temp_fix1616 = 0; 04620 limit_check_enable_int = 0; 04621 limit_check_disable = 1; 04622 04623 } else { 04624 VL53L0X_GETARRAYPARAMETERFIELD( dev, LimitChecksValue, 04625 limit_check_id, temp_fix1616 ); 04626 limit_check_disable = 0; 04627 /* this to be sure to have either 0 or 1 */ 04628 limit_check_enable_int = 1; 04629 } 04630 04631 switch ( limit_check_id ) { 04632 04633 case VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE: 04634 /* internal computation: */ 04635 VL53L0X_SETARRAYPARAMETERFIELD( dev, LimitChecksEnable, 04636 VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE, 04637 limit_check_enable_int ); 04638 04639 break; 04640 04641 case VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE: 04642 04643 status = vl53l0x_write_word( dev, 04644 VL53L0X_REG_FINAL_RANGE_CONFIG_MIN_COUNT_RATE_RTN_LIMIT, 04645 VL53L0X_FIXPOINT1616TOFIXPOINT97( temp_fix1616 ) ); 04646 04647 break; 04648 04649 case VL53L0X_CHECKENABLE_SIGNAL_REF_CLIP: 04650 04651 /* internal computation: */ 04652 VL53L0X_SETARRAYPARAMETERFIELD( dev, LimitChecksEnable, 04653 VL53L0X_CHECKENABLE_SIGNAL_REF_CLIP, 04654 limit_check_enable_int ); 04655 04656 break; 04657 04658 case VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD: 04659 04660 /* internal computation: */ 04661 VL53L0X_SETARRAYPARAMETERFIELD( dev, LimitChecksEnable, 04662 VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD, 04663 limit_check_enable_int ); 04664 04665 break; 04666 04667 case VL53L0X_CHECKENABLE_SIGNAL_RATE_MSRC: 04668 04669 temp8 = ( uint8_t )( limit_check_disable << 1 ); 04670 status = vl53l0x_update_byte( dev, 04671 VL53L0X_REG_MSRC_CONFIG_CONTROL, 04672 0xFE, temp8 ); 04673 04674 break; 04675 04676 case VL53L0X_CHECKENABLE_SIGNAL_RATE_PRE_RANGE: 04677 04678 temp8 = ( uint8_t )( limit_check_disable << 4 ); 04679 status = vl53l0x_update_byte( dev, 04680 VL53L0X_REG_MSRC_CONFIG_CONTROL, 04681 0xEF, temp8 ); 04682 04683 break; 04684 04685 04686 default: 04687 status = VL53L0X_ERROR_INVALID_PARAMS; 04688 04689 } 04690 04691 } 04692 04693 if ( status == VL53L0X_ERROR_NONE ) { 04694 if ( limit_check_enable == 0 ) { 04695 VL53L0X_SETARRAYPARAMETERFIELD( dev, LimitChecksEnable, 04696 limit_check_id, 0 ); 04697 } else { 04698 VL53L0X_SETARRAYPARAMETERFIELD( dev, LimitChecksEnable, 04699 limit_check_id, 1 ); 04700 } 04701 } 04702 04703 LOG_FUNCTION_END( status ); 04704 return status; 04705 } 04706 04707 VL53L0X_Error VL53L0X::vl53l0x_static_init( VL53L0X_DEV dev ) 04708 { 04709 VL53L0X_Error status = VL53L0X_ERROR_NONE; 04710 VL53L0X_DeviceParameters_t current_parameters = {0}; 04711 uint8_t *p_tuning_setting_buffer; 04712 uint16_t tempword = 0; 04713 uint8_t tempbyte = 0; 04714 uint8_t use_internal_tuning_settings = 0; 04715 uint32_t count = 0; 04716 uint8_t is_aperture_spads = 0; 04717 uint32_t ref_spad_count = 0; 04718 uint8_t aperture_spads = 0; 04719 uint8_t vcsel_pulse_period_pclk; 04720 uint32_t seq_timeout_micro_secs; 04721 04722 LOG_FUNCTION_START( "" ); 04723 04724 status = vl53l0x_get_info_from_device( dev, 1 ); 04725 04726 /* set the ref spad from NVM */ 04727 count = ( uint32_t )VL53L0X_GETDEVICESPECIFICPARAMETER( dev, 04728 ReferenceSpadCount ); 04729 aperture_spads = VL53L0X_GETDEVICESPECIFICPARAMETER( dev, 04730 ReferenceSpadType ); 04731 04732 /* NVM value invalid */ 04733 if ( ( aperture_spads > 1 ) || 04734 ( ( aperture_spads == 1 ) && ( count > 32 ) ) || 04735 ( ( aperture_spads == 0 ) && ( count > 12 ) ) ) 04736 status = wrapped_vl53l0x_perform_ref_spad_management( dev, &ref_spad_count, 04737 &is_aperture_spads ); 04738 else 04739 status = wrapped_vl53l0x_set_reference_spads( dev, count, aperture_spads ); 04740 04741 04742 /* Initialize tuning settings buffer to prevent compiler warning. */ 04743 p_tuning_setting_buffer = DefaultTuningSettings; 04744 04745 if ( status == VL53L0X_ERROR_NONE ) { 04746 use_internal_tuning_settings = PALDevDataGet( dev, 04747 UseInternalTuningSettings ); 04748 04749 if ( use_internal_tuning_settings == 0 ) 04750 p_tuning_setting_buffer = PALDevDataGet( dev, 04751 pTuningSettingsPointer ); 04752 else 04753 p_tuning_setting_buffer = DefaultTuningSettings; 04754 04755 } 04756 04757 if ( status == VL53L0X_ERROR_NONE ) 04758 status = vl53l0x_load_tuning_settings( dev, p_tuning_setting_buffer ); 04759 04760 04761 /* Set interrupt config to new sample ready */ 04762 if ( status == VL53L0X_ERROR_NONE ) { 04763 status = vl53l0x_set_gpio_config( dev, 0, 0, 04764 VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY, 04765 VL53L0X_INTERRUPTPOLARITY_LOW ); 04766 } 04767 04768 if ( status == VL53L0X_ERROR_NONE ) { 04769 status = vl53l0x_write_byte( dev, 0xFF, 0x01 ); 04770 status |= vl53l0x_read_word( dev, 0x84, &tempword ); 04771 status |= vl53l0x_write_byte( dev, 0xFF, 0x00 ); 04772 } 04773 04774 if ( status == VL53L0X_ERROR_NONE ) { 04775 VL53L0X_SETDEVICESPECIFICPARAMETER( dev, OscFrequencyMHz, 04776 VL53L0X_FIXPOINT412TOFIXPOINT1616( tempword ) ); 04777 } 04778 04779 /* After static init, some device parameters may be changed, 04780 * so update them */ 04781 if ( status == VL53L0X_ERROR_NONE ) 04782 status = vl53l0x_get_device_parameters( dev, ¤t_parameters ); 04783 04784 04785 if ( status == VL53L0X_ERROR_NONE ) { 04786 status = vl53l0x_get_fraction_enable( dev, &tempbyte ); 04787 if ( status == VL53L0X_ERROR_NONE ) 04788 PALDevDataSet( dev, RangeFractionalEnable, tempbyte ); 04789 04790 } 04791 04792 if ( status == VL53L0X_ERROR_NONE ) 04793 PALDevDataSet( dev, CurrentParameters, current_parameters ); 04794 04795 04796 /* read the sequence config and save it */ 04797 if ( status == VL53L0X_ERROR_NONE ) { 04798 status = vl53l0x_read_byte( dev, 04799 VL53L0X_REG_SYSTEM_SEQUENCE_CONFIG, &tempbyte ); 04800 if ( status == VL53L0X_ERROR_NONE ) 04801 PALDevDataSet( dev, SequenceConfig, tempbyte ); 04802 04803 } 04804 04805 /* Disable MSRC and TCC by default */ 04806 if ( status == VL53L0X_ERROR_NONE ) 04807 status = vl53l0x_set_sequence_step_enable( dev, 04808 VL53L0X_SEQUENCESTEP_TCC, 0 ); 04809 04810 04811 if ( status == VL53L0X_ERROR_NONE ) 04812 status = vl53l0x_set_sequence_step_enable( dev, 04813 VL53L0X_SEQUENCESTEP_MSRC, 0 ); 04814 04815 04816 /* Set PAL State to standby */ 04817 if ( status == VL53L0X_ERROR_NONE ) 04818 PALDevDataSet( dev, PalState, VL53L0X_STATE_IDLE ); 04819 04820 04821 04822 /* Store pre-range vcsel period */ 04823 if ( status == VL53L0X_ERROR_NONE ) { 04824 status = vl53l0x_get_vcsel_pulse_period( 04825 dev, 04826 VL53L0X_VCSEL_PERIOD_PRE_RANGE, 04827 &vcsel_pulse_period_pclk ); 04828 } 04829 04830 if ( status == VL53L0X_ERROR_NONE ) { 04831 VL53L0X_SETDEVICESPECIFICPARAMETER( 04832 dev, 04833 PreRangeVcselPulsePeriod, 04834 vcsel_pulse_period_pclk ); 04835 } 04836 04837 /* Store final-range vcsel period */ 04838 if ( status == VL53L0X_ERROR_NONE ) { 04839 status = vl53l0x_get_vcsel_pulse_period( 04840 dev, 04841 VL53L0X_VCSEL_PERIOD_FINAL_RANGE, 04842 &vcsel_pulse_period_pclk ); 04843 } 04844 04845 if ( status == VL53L0X_ERROR_NONE ) { 04846 VL53L0X_SETDEVICESPECIFICPARAMETER( 04847 dev, 04848 FinalRangeVcselPulsePeriod, 04849 vcsel_pulse_period_pclk ); 04850 } 04851 04852 /* Store pre-range timeout */ 04853 if ( status == VL53L0X_ERROR_NONE ) { 04854 status = get_sequence_step_timeout( 04855 dev, 04856 VL53L0X_SEQUENCESTEP_PRE_RANGE, 04857 &seq_timeout_micro_secs ); 04858 } 04859 04860 if ( status == VL53L0X_ERROR_NONE ) { 04861 VL53L0X_SETDEVICESPECIFICPARAMETER( 04862 dev, 04863 PreRangeTimeoutMicroSecs, 04864 seq_timeout_micro_secs ); 04865 } 04866 04867 /* Store final-range timeout */ 04868 if ( status == VL53L0X_ERROR_NONE ) { 04869 status = get_sequence_step_timeout( 04870 dev, 04871 VL53L0X_SEQUENCESTEP_FINAL_RANGE, 04872 &seq_timeout_micro_secs ); 04873 } 04874 04875 if ( status == VL53L0X_ERROR_NONE ) { 04876 VL53L0X_SETDEVICESPECIFICPARAMETER( 04877 dev, 04878 FinalRangeTimeoutMicroSecs, 04879 seq_timeout_micro_secs ); 04880 } 04881 04882 LOG_FUNCTION_END( status ); 04883 return status; 04884 } 04885 04886 04887 VL53L0X_Error VL53L0X::vl53l0x_stop_measurement( VL53L0X_DEV dev ) 04888 { 04889 VL53L0X_Error status = VL53L0X_ERROR_NONE; 04890 LOG_FUNCTION_START( "" ); 04891 04892 status = vl53l0x_write_byte( dev, VL53L0X_REG_SYSRANGE_START, 04893 VL53L0X_REG_SYSRANGE_MODE_SINGLESHOT ); 04894 04895 status = vl53l0x_write_byte( dev, 0xFF, 0x01 ); 04896 status = vl53l0x_write_byte( dev, 0x00, 0x00 ); 04897 status = vl53l0x_write_byte( dev, 0x91, 0x00 ); 04898 status = vl53l0x_write_byte( dev, 0x00, 0x01 ); 04899 status = vl53l0x_write_byte( dev, 0xFF, 0x00 ); 04900 04901 if ( status == VL53L0X_ERROR_NONE ) { 04902 /* Set PAL State to Idle */ 04903 PALDevDataSet( dev, PalState, VL53L0X_STATE_IDLE ); 04904 } 04905 04906 /* Check if need to apply interrupt settings */ 04907 if ( status == VL53L0X_ERROR_NONE ) 04908 status = vl53l0x_check_and_load_interrupt_settings( dev, 0 ); 04909 04910 LOG_FUNCTION_END( status ); 04911 return status; 04912 } 04913 04914 VL53L0X_Error VL53L0X::vl53l0x_get_stop_completed_status( VL53L0X_DEV dev, 04915 uint32_t *p_stop_status ) 04916 { 04917 VL53L0X_Error status = VL53L0X_ERROR_NONE; 04918 uint8_t byte = 0; 04919 LOG_FUNCTION_START( "" ); 04920 04921 status = vl53l0x_write_byte( dev, 0xFF, 0x01 ); 04922 04923 if ( status == VL53L0X_ERROR_NONE ) 04924 status = vl53l0x_read_byte( dev, 0x04, &byte ); 04925 04926 if ( status == VL53L0X_ERROR_NONE ) 04927 status = vl53l0x_write_byte( dev, 0xFF, 0x0 ); 04928 04929 *p_stop_status = byte; 04930 04931 if ( byte == 0 ) { 04932 status = vl53l0x_write_byte( dev, 0x80, 0x01 ); 04933 status = vl53l0x_write_byte( dev, 0xFF, 0x01 ); 04934 status = vl53l0x_write_byte( dev, 0x00, 0x00 ); 04935 status = vl53l0x_write_byte( dev, 0x91, 04936 PALDevDataGet( dev, StopVariable ) ); 04937 status = vl53l0x_write_byte( dev, 0x00, 0x01 ); 04938 status = vl53l0x_write_byte( dev, 0xFF, 0x00 ); 04939 status = vl53l0x_write_byte( dev, 0x80, 0x00 ); 04940 } 04941 04942 LOG_FUNCTION_END( status ); 04943 return status; 04944 } 04945 04946 /****************** Write and read functions from I2C *************************/ 04947 04948 VL53L0X_Error VL53L0X::vl53l0x_write_multi( VL53L0X_DEV dev, uint8_t index, uint8_t *p_data, uint32_t count ) 04949 { 04950 int status; 04951 04952 status = vl53l0x_i2c_write( dev->I2cDevAddr , index, p_data, ( uint16_t )count ); 04953 return status; 04954 } 04955 04956 VL53L0X_Error VL53L0X::vl53l0x_read_multi( VL53L0X_DEV dev, uint8_t index, uint8_t *p_data, uint32_t count ) 04957 { 04958 int status; 04959 04960 if ( count >= VL53L0X_MAX_I2C_XFER_SIZE ) { 04961 status = VL53L0X_ERROR_INVALID_PARAMS; 04962 } 04963 04964 status = vl53l0x_i2c_read( dev->I2cDevAddr , index, p_data, ( uint16_t )count ); 04965 04966 return status; 04967 } 04968 04969 04970 VL53L0X_Error VL53L0X::vl53l0x_write_byte( VL53L0X_DEV Dev, uint8_t index, uint8_t data ) 04971 { 04972 int status; 04973 04974 status = vl53l0x_i2c_write( Dev->I2cDevAddr , index, &data, 1 ); 04975 return status; 04976 } 04977 04978 VL53L0X_Error VL53L0X::vl53l0x_write_word( VL53L0X_DEV dev, uint8_t index, uint16_t data ) 04979 { 04980 int status; 04981 uint8_t buffer[2]; 04982 04983 buffer[0] = data >> 8; 04984 buffer[1] = data & 0x00FF; 04985 status = vl53l0x_i2c_write( dev->I2cDevAddr , index, ( uint8_t * )buffer, 2 ); 04986 return status; 04987 } 04988 04989 VL53L0X_Error VL53L0X::vl53l0x_write_dword( VL53L0X_DEV Dev, uint8_t index, uint32_t data ) 04990 { 04991 int status; 04992 uint8_t buffer[4]; 04993 04994 buffer[0] = ( data >> 24 ) & 0xFF; 04995 buffer[1] = ( data >> 16 ) & 0xFF; 04996 buffer[2] = ( data >> 8 ) & 0xFF; 04997 buffer[3] = ( data >> 0 ) & 0xFF; 04998 status = vl53l0x_i2c_write( Dev->I2cDevAddr , index, ( uint8_t * )buffer, 4 ); 04999 return status; 05000 } 05001 05002 05003 VL53L0X_Error VL53L0X::vl53l0x_read_byte( VL53L0X_DEV Dev, uint8_t index, uint8_t *p_data ) 05004 { 05005 int status; 05006 05007 status = vl53l0x_i2c_read( Dev->I2cDevAddr , index, p_data, 1 ); 05008 05009 if( status ) 05010 return -1; 05011 05012 return 0; 05013 } 05014 05015 VL53L0X_Error VL53L0X::vl53l0x_read_word( VL53L0X_DEV Dev, uint8_t index, uint16_t *p_data ) 05016 { 05017 int status; 05018 uint8_t buffer[2] = {0, 0}; 05019 05020 status = vl53l0x_i2c_read( Dev->I2cDevAddr , index, buffer, 2 ); 05021 if ( !status ) { 05022 *p_data = ( buffer[0] << 8 ) + buffer[1]; 05023 } 05024 return status; 05025 05026 } 05027 05028 VL53L0X_Error VL53L0X::vl53l0x_read_dword( VL53L0X_DEV Dev, uint8_t index, uint32_t *p_data ) 05029 { 05030 int status; 05031 uint8_t buffer[4] = {0, 0, 0, 0}; 05032 05033 status = vl53l0x_i2c_read( Dev->I2cDevAddr , index, buffer, 4 ); 05034 if( !status ) { 05035 *p_data = ( buffer[0] << 24 ) + ( buffer[1] << 16 ) + ( buffer[2] << 8 ) + buffer[3]; 05036 } 05037 return status; 05038 05039 } 05040 05041 VL53L0X_Error VL53L0X::vl53l0x_update_byte( VL53L0X_DEV Dev, uint8_t index, uint8_t and_data, uint8_t or_data ) 05042 { 05043 int status; 05044 uint8_t buffer = 0; 05045 05046 /* read data direct onto buffer */ 05047 status = vl53l0x_i2c_read( Dev->I2cDevAddr , index, &buffer, 1 ); 05048 if ( !status ) { 05049 buffer = ( buffer & and_data ) | or_data; 05050 status = vl53l0x_i2c_write( Dev->I2cDevAddr , index, &buffer, ( uint8_t )1 ); 05051 } 05052 return status; 05053 } 05054 05055 VL53L0X_Error VL53L0X::vl53l0x_i2c_write( uint8_t DeviceAddr, uint8_t RegisterAddr, uint8_t *p_data, 05056 uint16_t NumByteToWrite ) 05057 { 05058 int ret; 05059 05060 ret = dev_i2c.i2c_write( p_data, DeviceAddr, RegisterAddr, NumByteToWrite ); 05061 05062 if( ret ) 05063 return -1; 05064 return 0; 05065 } 05066 05067 VL53L0X_Error VL53L0X::vl53l0x_i2c_read( uint8_t DeviceAddr, uint8_t RegisterAddr, uint8_t *p_data, 05068 uint16_t NumByteToRead ) 05069 { 05070 int ret; 05071 05072 ret = dev_i2c.i2c_read( p_data, DeviceAddr, RegisterAddr, NumByteToRead ); 05073 05074 if( ret ) 05075 return -1; 05076 return 0; 05077 } 05078 05079 int VL53L0X::read_id( uint8_t *id ) 05080 { 05081 int status = 0; 05082 uint16_t rl_id = 0; 05083 05084 status = vl53l0x_read_word( _device, VL53L0X_REG_IDENTIFICATION_MODEL_ID, &rl_id ); 05085 if ( rl_id == 0xEEAA ) 05086 return status; 05087 05088 return -1; 05089 } 05090 05091 05092 VL53L0X_Error VL53L0X::wait_measurement_data_ready( VL53L0X_DEV dev ) 05093 { 05094 VL53L0X_Error status = VL53L0X_ERROR_NONE; 05095 uint8_t new_dat_ready = 0; 05096 uint32_t loop_nb; 05097 05098 // Wait until it finished 05099 // use timeout to avoid deadlock 05100 if ( status == VL53L0X_ERROR_NONE ) { 05101 loop_nb = 0; 05102 do { 05103 status = vl53l0x_get_measurement_data_ready( dev, &new_dat_ready ); 05104 if ( ( new_dat_ready == 0x01 ) || status != VL53L0X_ERROR_NONE ) { 05105 break; 05106 } 05107 loop_nb = loop_nb + 1; 05108 vl53l0x_polling_delay( dev ); 05109 } while ( loop_nb < VL53L0X_DEFAULT_MAX_LOOP ); 05110 05111 if ( loop_nb >= VL53L0X_DEFAULT_MAX_LOOP ) { 05112 status = VL53L0X_ERROR_TIME_OUT; 05113 } 05114 } 05115 05116 return status; 05117 } 05118 05119 VL53L0X_Error VL53L0X::wait_stop_completed( VL53L0X_DEV dev ) 05120 { 05121 VL53L0X_Error status = VL53L0X_ERROR_NONE; 05122 uint32_t stop_completed = 0; 05123 uint32_t loop_nb; 05124 05125 // Wait until it finished 05126 // use timeout to avoid deadlock 05127 if ( status == VL53L0X_ERROR_NONE ) { 05128 loop_nb = 0; 05129 do { 05130 status = vl53l0x_get_stop_completed_status( dev, &stop_completed ); 05131 if ( ( stop_completed == 0x00 ) || status != VL53L0X_ERROR_NONE ) { 05132 break; 05133 } 05134 loop_nb = loop_nb + 1; 05135 vl53l0x_polling_delay( dev ); 05136 } while ( loop_nb < VL53L0X_DEFAULT_MAX_LOOP ); 05137 05138 if ( loop_nb >= VL53L0X_DEFAULT_MAX_LOOP ) { 05139 status = VL53L0X_ERROR_TIME_OUT; 05140 } 05141 05142 } 05143 05144 return status; 05145 } 05146 05147 05148 int VL53L0X::init_sensor( uint8_t new_addr ) 05149 { 05150 int status; 05151 05152 vl53l0x_off(); 05153 vl53l0x_on(); 05154 05155 // status=VL53L0X_WaitDeviceBooted(Device); 05156 // if(status) 05157 // printf("WaitDeviceBooted fail\n\r"); 05158 status = is_present(); 05159 if( !status ) { 05160 status = init( &_my_device ); 05161 if( status != VL53L0X_ERROR_NONE ) { 05162 printf( "Failed to init VL53L0X sensor!\n\r" ); 05163 return status; 05164 } 05165 05166 // deduce silicon version 05167 status = vl53l0x_get_device_info( &_my_device, &_device_info ); 05168 05169 05170 status = prepare(); 05171 if( status != VL53L0X_ERROR_NONE ) { 05172 printf( "Failed to prepare VL53L0X!\n\r" ); 05173 return status; 05174 } 05175 05176 if( new_addr != DEFAULT_DEVICE_ADDRESS ) { 05177 status = set_device_address( new_addr ); 05178 if( status ) { 05179 printf( "Failed to change I2C address!\n\r" ); 05180 return status; 05181 } 05182 } else { 05183 printf( "Invalid new address!\n\r" ); 05184 return VL53L0X_ERROR_INVALID_PARAMS; 05185 } 05186 } 05187 return status; 05188 } 05189 05190 int VL53L0X::range_meas_int_continuous_mode( void ( *fptr )( void ) ) 05191 { 05192 int status, clr_status; 05193 05194 status = vl53l0x_stop_measurement( _device ); // it is safer to do this while sensor is stopped 05195 05196 // status = VL53L0X_SetInterruptThresholds(Device, VL53L0X_DEVICEMODE_CONTINUOUS_RANGING, 0, 300); 05197 05198 status = vl53l0x_set_gpio_config( _device, 0, VL53L0X_DEVICEMODE_CONTINUOUS_RANGING, 05199 VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY, 05200 VL53L0X_INTERRUPTPOLARITY_HIGH ); 05201 05202 if ( !status ) { 05203 attach_interrupt_measure_detection_irq( fptr ); 05204 enable_interrupt_measure_detection_irq(); 05205 } 05206 05207 clr_status = clear_interrupt( VL53L0X_REG_RESULT_INTERRUPT_STATUS | VL53L0X_REG_RESULT_RANGE_STATUS ); 05208 if( clr_status ) 05209 VL53L0X_ErrLog( "VL53L0X_ClearErrorInterrupt fail\r\n" ); 05210 05211 if( !status ) { 05212 status = range_start_continuous_mode(); 05213 } 05214 return status; 05215 } 05216 05217 05218 int VL53L0X::start_measurement( OperatingMode operating_mode, void ( *fptr )( void ) ) 05219 { 05220 int Status = VL53L0X_ERROR_NONE; 05221 int ClrStatus; 05222 05223 uint8_t VhvSettings; 05224 uint8_t PhaseCal; 05225 // *** from mass market cube expansion v1.1, ranging with satellites. 05226 // default settings, for normal range. 05227 FixPoint1616_t signalLimit = ( FixPoint1616_t )( 0.25 * 65536 ); 05228 FixPoint1616_t sigmaLimit = ( FixPoint1616_t )( 18 * 65536 ); 05229 uint32_t timingBudget = 33000; 05230 uint8_t preRangeVcselPeriod = 14; 05231 uint8_t finalRangeVcselPeriod = 10; 05232 05233 if ( operating_mode == range_continuous_interrupt ) { 05234 if ( gpio1Int == NULL ) { 05235 printf ( "GPIO1 Error\r\n" ); 05236 return 1; 05237 } 05238 05239 Status = vl53l0x_stop_measurement( _device ); // it is safer to do this while sensor is stopped 05240 05241 // Status = VL53L0X_SetInterruptThresholds(Device, VL53L0X_DEVICEMODE_CONTINUOUS_RANGING, 0, 300); 05242 05243 Status = vl53l0x_set_gpio_config( _device, 0, VL53L0X_DEVICEMODE_CONTINUOUS_RANGING, 05244 VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY, 05245 VL53L0X_INTERRUPTPOLARITY_HIGH ); 05246 05247 if ( Status == VL53L0X_ERROR_NONE ) { 05248 attach_interrupt_measure_detection_irq( fptr ); 05249 enable_interrupt_measure_detection_irq(); 05250 } 05251 05252 ClrStatus = clear_interrupt( VL53L0X_REG_RESULT_INTERRUPT_STATUS | VL53L0X_REG_RESULT_RANGE_STATUS ); 05253 if( ClrStatus ) 05254 VL53L0X_ErrLog( "VL53L0X_ClearErrorInterrupt fail\r\n" ); 05255 05256 if( Status == VL53L0X_ERROR_NONE ) { 05257 Status = vl53l0x_set_device_mode( _device, VL53L0X_DEVICEMODE_CONTINUOUS_RANGING ); // Setup in continuous ranging mode 05258 } 05259 05260 if( Status == VL53L0X_ERROR_NONE ) { 05261 Status = vl53l0x_start_measurement( _device ); 05262 } 05263 } 05264 05265 if ( operating_mode == range_single_shot_polling ) { 05266 // singelshot, polled ranging 05267 if( Status == VL53L0X_ERROR_NONE ) { 05268 // no need to do this when we use VL53L0X_PerformSingleRangingMeasurement 05269 Status = vl53l0x_set_device_mode( _device, VL53L0X_DEVICEMODE_SINGLE_RANGING ); // Setup in single ranging mode 05270 } 05271 05272 // Enable/Disable Sigma and Signal check 05273 if ( Status == VL53L0X_ERROR_NONE ) { 05274 Status = vl53l0x_set_limit_check_enable( _device, 05275 VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE, 1 ); 05276 } 05277 if ( Status == VL53L0X_ERROR_NONE ) { 05278 Status = vl53l0x_set_limit_check_enable( _device, 05279 VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE, 1 ); 05280 } 05281 05282 // *** from mass market cube expansion v1.1, ranging with satellites. 05283 /* Ranging configuration */ 05284 //* 05285 // switch(rangingConfig) { 05286 // case LONG_RANGE: 05287 signalLimit = ( FixPoint1616_t )( 0.1 * 65536 ); 05288 sigmaLimit = ( FixPoint1616_t )( 60 * 65536 ); 05289 timingBudget = 33000; 05290 preRangeVcselPeriod = 18; 05291 finalRangeVcselPeriod = 14; 05292 /* break; 05293 case HIGH_ACCURACY: 05294 signalLimit = (FixPoint1616_t)(0.25*65536); 05295 sigmaLimit = (FixPoint1616_t)(18*65536); 05296 timingBudget = 200000; 05297 preRangeVcselPeriod = 14; 05298 finalRangeVcselPeriod = 10; 05299 break; 05300 case HIGH_SPEED: 05301 signalLimit = (FixPoint1616_t)(0.25*65536); 05302 sigmaLimit = (FixPoint1616_t)(32*65536); 05303 timingBudget = 20000; 05304 preRangeVcselPeriod = 14; 05305 finalRangeVcselPeriod = 10; 05306 break; 05307 default: 05308 debug_printf("Not Supported"); 05309 } 05310 */ 05311 05312 if ( Status == VL53L0X_ERROR_NONE ) { 05313 Status = vl53l0x_set_limit_check_value( _device, 05314 VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE, signalLimit ); 05315 } 05316 05317 if ( Status == VL53L0X_ERROR_NONE ) { 05318 Status = vl53l0x_set_limit_check_value( _device, 05319 VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE, sigmaLimit ); 05320 } 05321 05322 if ( Status == VL53L0X_ERROR_NONE ) { 05323 Status = vl53l0x_set_measurement_timing_budget_micro_seconds( _device, timingBudget ); 05324 } 05325 05326 if ( Status == VL53L0X_ERROR_NONE ) { 05327 Status = vl53l0x_set_vcsel_pulse_period( _device, 05328 VL53L0X_VCSEL_PERIOD_PRE_RANGE, preRangeVcselPeriod ); 05329 } 05330 05331 if ( Status == VL53L0X_ERROR_NONE ) { 05332 Status = vl53l0x_set_vcsel_pulse_period( _device, 05333 VL53L0X_VCSEL_PERIOD_FINAL_RANGE, finalRangeVcselPeriod ); 05334 } 05335 05336 if ( Status == VL53L0X_ERROR_NONE ) { 05337 Status = vl53l0x_perform_ref_calibration( _device, &VhvSettings, &PhaseCal ); 05338 } 05339 05340 } 05341 05342 if ( operating_mode == range_continuous_polling ) { 05343 if( Status == VL53L0X_ERROR_NONE ) { 05344 printf ( "Call of VL53L0X_SetDeviceMode\n" ); 05345 Status = vl53l0x_set_device_mode( _device, VL53L0X_DEVICEMODE_CONTINUOUS_RANGING ); // Setup in continuous ranging mode 05346 } 05347 05348 if( Status == VL53L0X_ERROR_NONE ) { 05349 printf ( "Call of VL53L0X_StartMeasurement\n" ); 05350 Status = vl53l0x_start_measurement( _device ); 05351 } 05352 } 05353 05354 return Status; 05355 } 05356 05357 05358 int VL53L0X::get_measurement( OperatingMode operating_mode, VL53L0X_RangingMeasurementData_t *p_data ) 05359 { 05360 int Status = VL53L0X_ERROR_NONE; 05361 05362 if ( operating_mode == range_single_shot_polling ) { 05363 Status = vl53l0x_perform_single_ranging_measurement( _device, p_data ); 05364 } 05365 05366 if ( operating_mode == range_continuous_polling ) { 05367 if ( Status == VL53L0X_ERROR_NONE ) 05368 Status = vl53l0x_measurement_poll_for_completion( _device ); 05369 05370 if( Status == VL53L0X_ERROR_NONE ) { 05371 Status = vl53l0x_get_ranging_measurement_data( _device, p_data ); 05372 05373 // Clear the interrupt 05374 vl53l0x_clear_interrupt_mask( _device, VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY ); 05375 vl53l0x_polling_delay( _device ); 05376 } 05377 } 05378 05379 if ( operating_mode == range_continuous_interrupt ) { 05380 Status = vl53l0x_get_ranging_measurement_data( _device, p_data ); 05381 vl53l0x_clear_interrupt_mask( _device, VL53L0X_REG_SYSTEM_INTERRUPT_CLEAR | VL53L0X_REG_RESULT_INTERRUPT_STATUS ); 05382 } 05383 05384 return Status; 05385 } 05386 05387 05388 int VL53L0X::stop_measurement( OperatingMode operating_mode ) 05389 { 05390 int status = VL53L0X_ERROR_NONE; 05391 05392 05393 // don't need to stop for a singleshot range! 05394 if ( operating_mode == range_single_shot_polling ) { 05395 } 05396 05397 if ( operating_mode == range_continuous_interrupt || operating_mode == range_continuous_polling ) { 05398 // continuous mode 05399 if( status == VL53L0X_ERROR_NONE ) { 05400 printf ( "Call of VL53L0X_StopMeasurement\n" ); 05401 status = vl53l0x_stop_measurement( _device ); 05402 } 05403 05404 if( status == VL53L0X_ERROR_NONE ) { 05405 printf ( "Wait Stop to be competed\n" ); 05406 status = wait_stop_completed( _device ); 05407 } 05408 05409 if( status == VL53L0X_ERROR_NONE ) 05410 status = vl53l0x_clear_interrupt_mask( _device, 05411 VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY ); 05412 } 05413 05414 return status; 05415 } 05416 05417 05418 int VL53L0X::handle_irq( OperatingMode operating_mode, VL53L0X_RangingMeasurementData_t *data ) 05419 { 05420 int status; 05421 status = get_measurement( operating_mode, data ); 05422 enable_interrupt_measure_detection_irq(); 05423 return status; 05424 } 05425 05426 int32_t VL53L0X::vl53l0x_cycle_power( void ) 05427 { 05428 int32_t status = STATUS_OK; 05429 #ifdef VL53L0X_LOG_ENABLE 05430 trace_i2c( "// cycle sensor power\n" ); 05431 #endif 05432 return status; 05433 } 05434 05435 uint8_t VL53L0X::vl53l0x_encode_vcsel_period( uint8_t vcsel_period_pclks ) 05436 { 05437 /*! 05438 * Converts the encoded VCSEL period register value into the real period 05439 * in PLL clocks 05440 */ 05441 05442 uint8_t vcsel_period_reg = 0; 05443 05444 vcsel_period_reg = ( vcsel_period_pclks >> 1 ) - 1; 05445 05446 return vcsel_period_reg; 05447 } 05448 05449 VL53L0X_Error VL53L0X::wrapped_vl53l0x_get_device_error_string( VL53L0X_DeviceError error_code, 05450 char *p_device_error_string ) 05451 { 05452 VL53L0X_Error status = VL53L0X_ERROR_NONE; 05453 05454 LOG_FUNCTION_START( "" ); 05455 05456 switch ( error_code ) { 05457 case VL53L0X_DEVICEERROR_NONE: 05458 VL53L0X_COPYSTRING( p_device_error_string, 05459 VL53L0X_STRING_DEVICEERROR_NONE ); 05460 break; 05461 case VL53L0X_DEVICEERROR_VCSELCONTINUITYTESTFAILURE: 05462 VL53L0X_COPYSTRING( p_device_error_string, 05463 VL53L0X_STRING_DEVICEERROR_VCSELCONTINUITYTESTFAILURE ); 05464 break; 05465 case VL53L0X_DEVICEERROR_VCSELWATCHDOGTESTFAILURE: 05466 VL53L0X_COPYSTRING( p_device_error_string, 05467 VL53L0X_STRING_DEVICEERROR_VCSELWATCHDOGTESTFAILURE ); 05468 break; 05469 case VL53L0X_DEVICEERROR_NOVHVVALUEFOUND: 05470 VL53L0X_COPYSTRING( p_device_error_string, 05471 VL53L0X_STRING_DEVICEERROR_NOVHVVALUEFOUND ); 05472 break; 05473 case VL53L0X_DEVICEERROR_MSRCNOTARGET: 05474 VL53L0X_COPYSTRING( p_device_error_string, 05475 VL53L0X_STRING_DEVICEERROR_MSRCNOTARGET ); 05476 break; 05477 case VL53L0X_DEVICEERROR_SNRCHECK: 05478 VL53L0X_COPYSTRING( p_device_error_string, 05479 VL53L0X_STRING_DEVICEERROR_SNRCHECK ); 05480 break; 05481 case VL53L0X_DEVICEERROR_RANGEPHASECHECK: 05482 VL53L0X_COPYSTRING( p_device_error_string, 05483 VL53L0X_STRING_DEVICEERROR_RANGEPHASECHECK ); 05484 break; 05485 case VL53L0X_DEVICEERROR_SIGMATHRESHOLDCHECK: 05486 VL53L0X_COPYSTRING( p_device_error_string, 05487 VL53L0X_STRING_DEVICEERROR_SIGMATHRESHOLDCHECK ); 05488 break; 05489 case VL53L0X_DEVICEERROR_TCC: 05490 VL53L0X_COPYSTRING( p_device_error_string, 05491 VL53L0X_STRING_DEVICEERROR_TCC ); 05492 break; 05493 case VL53L0X_DEVICEERROR_PHASECONSISTENCY: 05494 VL53L0X_COPYSTRING( p_device_error_string, 05495 VL53L0X_STRING_DEVICEERROR_PHASECONSISTENCY ); 05496 break; 05497 case VL53L0X_DEVICEERROR_MINCLIP: 05498 VL53L0X_COPYSTRING( p_device_error_string, 05499 VL53L0X_STRING_DEVICEERROR_MINCLIP ); 05500 break; 05501 case VL53L0X_DEVICEERROR_RANGECOMPLETE: 05502 VL53L0X_COPYSTRING( p_device_error_string, 05503 VL53L0X_STRING_DEVICEERROR_RANGECOMPLETE ); 05504 break; 05505 case VL53L0X_DEVICEERROR_ALGOUNDERFLOW: 05506 VL53L0X_COPYSTRING( p_device_error_string, 05507 VL53L0X_STRING_DEVICEERROR_ALGOUNDERFLOW ); 05508 break; 05509 case VL53L0X_DEVICEERROR_ALGOOVERFLOW: 05510 VL53L0X_COPYSTRING( p_device_error_string, 05511 VL53L0X_STRING_DEVICEERROR_ALGOOVERFLOW ); 05512 break; 05513 case VL53L0X_DEVICEERROR_RANGEIGNORETHRESHOLD: 05514 VL53L0X_COPYSTRING( p_device_error_string, 05515 VL53L0X_STRING_DEVICEERROR_RANGEIGNORETHRESHOLD ); 05516 break; 05517 05518 default: 05519 VL53L0X_COPYSTRING( p_device_error_string, 05520 VL53L0X_STRING_UNKNOW_ERROR_CODE ); 05521 05522 } 05523 05524 LOG_FUNCTION_END( status ); 05525 return status; 05526 } 05527 05528 05529 VL53L0X_Error VL53L0X::wrapped_vl53l0x_get_limit_check_info( VL53L0X_DEV dev, uint16_t limit_check_id, 05530 char *p_limit_check_string ) 05531 { 05532 05533 VL53L0X_Error status = VL53L0X_ERROR_NONE; 05534 05535 LOG_FUNCTION_START( "" ); 05536 05537 switch ( limit_check_id ) { 05538 case VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE: 05539 VL53L0X_COPYSTRING( p_limit_check_string, 05540 VL53L0X_STRING_CHECKENABLE_SIGMA_FINAL_RANGE ); 05541 break; 05542 case VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE: 05543 VL53L0X_COPYSTRING( p_limit_check_string, 05544 VL53L0X_STRING_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE ); 05545 break; 05546 case VL53L0X_CHECKENABLE_SIGNAL_REF_CLIP: 05547 VL53L0X_COPYSTRING( p_limit_check_string, 05548 VL53L0X_STRING_CHECKENABLE_SIGNAL_REF_CLIP ); 05549 break; 05550 case VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD: 05551 VL53L0X_COPYSTRING( p_limit_check_string, 05552 VL53L0X_STRING_CHECKENABLE_RANGE_IGNORE_THRESHOLD ); 05553 break; 05554 05555 case VL53L0X_CHECKENABLE_SIGNAL_RATE_MSRC: 05556 VL53L0X_COPYSTRING( p_limit_check_string, 05557 VL53L0X_STRING_CHECKENABLE_SIGNAL_RATE_MSRC ); 05558 break; 05559 05560 case VL53L0X_CHECKENABLE_SIGNAL_RATE_PRE_RANGE: 05561 VL53L0X_COPYSTRING( p_limit_check_string, 05562 VL53L0X_STRING_CHECKENABLE_SIGNAL_RATE_PRE_RANGE ); 05563 break; 05564 05565 default: 05566 VL53L0X_COPYSTRING( p_limit_check_string, 05567 VL53L0X_STRING_UNKNOW_ERROR_CODE ); 05568 05569 } 05570 05571 LOG_FUNCTION_END( status ); 05572 return status; 05573 } 05574 05575 VL53L0X_Error VL53L0X::wrapped_vl53l0x_get_pal_error_string( VL53L0X_Error pal_error_code, 05576 char *p_pal_error_string ) 05577 { 05578 VL53L0X_Error status = VL53L0X_ERROR_NONE; 05579 05580 LOG_FUNCTION_START( "" ); 05581 05582 switch ( pal_error_code ) { 05583 case VL53L0X_ERROR_NONE: 05584 VL53L0X_COPYSTRING( p_pal_error_string, 05585 VL53L0X_STRING_ERROR_NONE ); 05586 break; 05587 case VL53L0X_ERROR_CALIBRATION_WARNING: 05588 VL53L0X_COPYSTRING( p_pal_error_string, 05589 VL53L0X_STRING_ERROR_CALIBRATION_WARNING ); 05590 break; 05591 case VL53L0X_ERROR_MIN_CLIPPED: 05592 VL53L0X_COPYSTRING( p_pal_error_string, 05593 VL53L0X_STRING_ERROR_MIN_CLIPPED ); 05594 break; 05595 case VL53L0X_ERROR_UNDEFINED: 05596 VL53L0X_COPYSTRING( p_pal_error_string, 05597 VL53L0X_STRING_ERROR_UNDEFINED ); 05598 break; 05599 case VL53L0X_ERROR_INVALID_PARAMS: 05600 VL53L0X_COPYSTRING( p_pal_error_string, 05601 VL53L0X_STRING_ERROR_INVALID_PARAMS ); 05602 break; 05603 case VL53L0X_ERROR_NOT_SUPPORTED: 05604 VL53L0X_COPYSTRING( p_pal_error_string, 05605 VL53L0X_STRING_ERROR_NOT_SUPPORTED ); 05606 break; 05607 case VL53L0X_ERROR_INTERRUPT_NOT_CLEARED: 05608 VL53L0X_COPYSTRING( p_pal_error_string, 05609 VL53L0X_STRING_ERROR_INTERRUPT_NOT_CLEARED ); 05610 break; 05611 case VL53L0X_ERROR_RANGE_ERROR: 05612 VL53L0X_COPYSTRING( p_pal_error_string, 05613 VL53L0X_STRING_ERROR_RANGE_ERROR ); 05614 break; 05615 case VL53L0X_ERROR_TIME_OUT: 05616 VL53L0X_COPYSTRING( p_pal_error_string, 05617 VL53L0X_STRING_ERROR_TIME_OUT ); 05618 break; 05619 case VL53L0X_ERROR_MODE_NOT_SUPPORTED: 05620 VL53L0X_COPYSTRING( p_pal_error_string, 05621 VL53L0X_STRING_ERROR_MODE_NOT_SUPPORTED ); 05622 break; 05623 case VL53L0X_ERROR_BUFFER_TOO_SMALL: 05624 VL53L0X_COPYSTRING( p_pal_error_string, 05625 VL53L0X_STRING_ERROR_BUFFER_TOO_SMALL ); 05626 break; 05627 case VL53L0X_ERROR_GPIO_NOT_EXISTING: 05628 VL53L0X_COPYSTRING( p_pal_error_string, 05629 VL53L0X_STRING_ERROR_GPIO_NOT_EXISTING ); 05630 break; 05631 case VL53L0X_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED: 05632 VL53L0X_COPYSTRING( p_pal_error_string, 05633 VL53L0X_STRING_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED ); 05634 break; 05635 case VL53L0X_ERROR_CONTROL_INTERFACE: 05636 VL53L0X_COPYSTRING( p_pal_error_string, 05637 VL53L0X_STRING_ERROR_CONTROL_INTERFACE ); 05638 break; 05639 case VL53L0X_ERROR_INVALID_COMMAND: 05640 VL53L0X_COPYSTRING( p_pal_error_string, 05641 VL53L0X_STRING_ERROR_INVALID_COMMAND ); 05642 break; 05643 case VL53L0X_ERROR_DIVISION_BY_ZERO: 05644 VL53L0X_COPYSTRING( p_pal_error_string, 05645 VL53L0X_STRING_ERROR_DIVISION_BY_ZERO ); 05646 break; 05647 case VL53L0X_ERROR_REF_SPAD_INIT: 05648 VL53L0X_COPYSTRING( p_pal_error_string, 05649 VL53L0X_STRING_ERROR_REF_SPAD_INIT ); 05650 break; 05651 case VL53L0X_ERROR_NOT_IMPLEMENTED: 05652 VL53L0X_COPYSTRING( p_pal_error_string, 05653 VL53L0X_STRING_ERROR_NOT_IMPLEMENTED ); 05654 break; 05655 05656 default: 05657 VL53L0X_COPYSTRING( p_pal_error_string, 05658 VL53L0X_STRING_UNKNOW_ERROR_CODE ); 05659 } 05660 05661 LOG_FUNCTION_END( status ); 05662 return status; 05663 } 05664 05665 VL53L0X_Error VL53L0X::wrapped_vl53l0x_get_pal_state_string( VL53L0X_State pal_state_code, 05666 char *p_pal_state_string ) 05667 { 05668 VL53L0X_Error status = VL53L0X_ERROR_NONE; 05669 05670 LOG_FUNCTION_START( "" ); 05671 05672 switch ( pal_state_code ) { 05673 case VL53L0X_STATE_POWERDOWN: 05674 VL53L0X_COPYSTRING( p_pal_state_string, 05675 VL53L0X_STRING_STATE_POWERDOWN ); 05676 break; 05677 case VL53L0X_STATE_WAIT_STATICINIT: 05678 VL53L0X_COPYSTRING( p_pal_state_string, 05679 VL53L0X_STRING_STATE_WAIT_STATICINIT ); 05680 break; 05681 case VL53L0X_STATE_STANDBY: 05682 VL53L0X_COPYSTRING( p_pal_state_string, 05683 VL53L0X_STRING_STATE_STANDBY ); 05684 break; 05685 case VL53L0X_STATE_IDLE: 05686 VL53L0X_COPYSTRING( p_pal_state_string, 05687 VL53L0X_STRING_STATE_IDLE ); 05688 break; 05689 case VL53L0X_STATE_RUNNING: 05690 VL53L0X_COPYSTRING( p_pal_state_string, 05691 VL53L0X_STRING_STATE_RUNNING ); 05692 break; 05693 case VL53L0X_STATE_UNKNOWN: 05694 VL53L0X_COPYSTRING( p_pal_state_string, 05695 VL53L0X_STRING_STATE_UNKNOWN ); 05696 break; 05697 case VL53L0X_STATE_ERROR: 05698 VL53L0X_COPYSTRING( p_pal_state_string, 05699 VL53L0X_STRING_STATE_ERROR ); 05700 break; 05701 05702 default: 05703 VL53L0X_COPYSTRING( p_pal_state_string, 05704 VL53L0X_STRING_STATE_UNKNOWN ); 05705 } 05706 05707 LOG_FUNCTION_END( status ); 05708 return status; 05709 } 05710 05711 VL53L0X_Error VL53L0X::wrapped_vl53l0x_get_range_status_string( uint8_t range_status, 05712 char *p_range_status_string ) 05713 { 05714 VL53L0X_Error status = VL53L0X_ERROR_NONE; 05715 05716 LOG_FUNCTION_START( "" ); 05717 05718 switch ( range_status ) { 05719 case 0: 05720 VL53L0X_COPYSTRING( p_range_status_string, 05721 VL53L0X_STRING_RANGESTATUS_RANGEVALID ); 05722 break; 05723 case 1: 05724 VL53L0X_COPYSTRING( p_range_status_string, 05725 VL53L0X_STRING_RANGESTATUS_SIGMA ); 05726 break; 05727 case 2: 05728 VL53L0X_COPYSTRING( p_range_status_string, 05729 VL53L0X_STRING_RANGESTATUS_SIGNAL ); 05730 break; 05731 case 3: 05732 VL53L0X_COPYSTRING( p_range_status_string, 05733 VL53L0X_STRING_RANGESTATUS_MINRANGE ); 05734 break; 05735 case 4: 05736 VL53L0X_COPYSTRING( p_range_status_string, 05737 VL53L0X_STRING_RANGESTATUS_PHASE ); 05738 break; 05739 case 5: 05740 VL53L0X_COPYSTRING( p_range_status_string, 05741 VL53L0X_STRING_RANGESTATUS_HW ); 05742 break; 05743 05744 default: /**/ 05745 VL53L0X_COPYSTRING( p_range_status_string, 05746 VL53L0X_STRING_RANGESTATUS_NONE ); 05747 } 05748 05749 LOG_FUNCTION_END( status ); 05750 return status; 05751 } 05752 05753 05754 VL53L0X_Error VL53L0X::wrapped_vl53l0x_get_ref_calibration( VL53L0X_DEV dev, 05755 uint8_t *p_vhv_settings, uint8_t *p_phase_cal ) 05756 { 05757 VL53L0X_Error status = VL53L0X_ERROR_NONE; 05758 uint8_t vhv_settings = 0; 05759 uint8_t phase_cal = 0; 05760 05761 status = vl53l0x_ref_calibration_io( dev, 1, 05762 vhv_settings, phase_cal, 05763 p_vhv_settings, p_phase_cal, 05764 1, 1 ); 05765 05766 return status; 05767 } 05768 05769 VL53L0X_Error VL53L0X::count_enabled_spads( uint8_t spad_array[], 05770 uint32_t byte_count, uint32_t max_spads, 05771 uint32_t *p_total_spads_enabled, uint8_t *p_is_aperture ) 05772 { 05773 VL53L0X_Error status = VL53L0X_ERROR_NONE; 05774 uint32_t c_spads_per_byte = 8; 05775 uint32_t last_byte; 05776 uint32_t last_bit; 05777 uint32_t byte_index = 0; 05778 uint32_t bit_index = 0; 05779 uint8_t temp_byte; 05780 uint8_t spad_type_identified = 0; 05781 05782 /* The entire array will not be used for spads, therefore the last 05783 * byte and last bit is determined from the max spads value. 05784 */ 05785 05786 last_byte = max_spads / c_spads_per_byte; 05787 last_bit = max_spads % c_spads_per_byte; 05788 05789 /* Check that the max spads value does not exceed the array bounds. */ 05790 if ( last_byte >= byte_count ) 05791 status = VL53L0X_ERROR_REF_SPAD_INIT; 05792 05793 *p_total_spads_enabled = 0; 05794 05795 /* Count the bits enabled in the whole bytes */ 05796 for ( byte_index = 0; byte_index <= ( last_byte - 1 ); byte_index++ ) { 05797 temp_byte = spad_array[byte_index]; 05798 05799 for ( bit_index = 0; bit_index <= c_spads_per_byte; bit_index++ ) { 05800 if ( ( temp_byte & 0x01 ) == 1 ) { 05801 ( *p_total_spads_enabled )++; 05802 05803 if ( !spad_type_identified ) { 05804 *p_is_aperture = 1; 05805 if ( ( byte_index < 2 ) && ( bit_index < 4 ) ) 05806 *p_is_aperture = 0; 05807 spad_type_identified = 1; 05808 } 05809 } 05810 temp_byte >>= 1; 05811 } 05812 } 05813 05814 /* Count the number of bits enabled in the last byte accounting 05815 * for the fact that not all bits in the byte may be used. 05816 */ 05817 temp_byte = spad_array[last_byte]; 05818 05819 for ( bit_index = 0; bit_index <= last_bit; bit_index++ ) { 05820 if ( ( temp_byte & 0x01 ) == 1 ) 05821 ( *p_total_spads_enabled )++; 05822 } 05823 05824 return status; 05825 } 05826 05827 VL53L0X_Error VL53L0X::wrapped_vl53l0x_get_reference_spads( VL53L0X_DEV dev, 05828 uint32_t *p_spad_count, uint8_t *p_is_aperture_spads ) 05829 { 05830 VL53L0X_Error status = VL53L0X_ERROR_NONE; 05831 uint8_t ref_spads_initialised; 05832 uint8_t ref_spad_array[6]; 05833 uint32_t c_max_spad_count = 44; 05834 uint32_t c_spad_array_size = 6; 05835 uint32_t spads_enabled; 05836 uint8_t is_aperture_spads = 0; 05837 05838 ref_spads_initialised = VL53L0X_GETDEVICESPECIFICPARAMETER( dev, 05839 RefSpadsInitialised ); 05840 05841 if ( ref_spads_initialised == 1 ) { 05842 05843 *p_spad_count = ( uint32_t )VL53L0X_GETDEVICESPECIFICPARAMETER( dev, 05844 ReferenceSpadCount ); 05845 *p_is_aperture_spads = VL53L0X_GETDEVICESPECIFICPARAMETER( dev, 05846 ReferenceSpadType ); 05847 } else { 05848 05849 /* obtain spad info from device.*/ 05850 status = get_ref_spad_map( dev, ref_spad_array ); 05851 05852 if ( status == VL53L0X_ERROR_NONE ) { 05853 /* count enabled spads within spad map array and 05854 * determine if Aperture or Non-Aperture. 05855 */ 05856 status = count_enabled_spads( ref_spad_array, 05857 c_spad_array_size, 05858 c_max_spad_count, 05859 &spads_enabled, 05860 &is_aperture_spads ); 05861 05862 if ( status == VL53L0X_ERROR_NONE ) { 05863 05864 *p_spad_count = spads_enabled; 05865 *p_is_aperture_spads = is_aperture_spads; 05866 05867 VL53L0X_SETDEVICESPECIFICPARAMETER( dev, 05868 RefSpadsInitialised, 1 ); 05869 VL53L0X_SETDEVICESPECIFICPARAMETER( dev, 05870 ReferenceSpadCount, 05871 ( uint8_t )spads_enabled ); 05872 VL53L0X_SETDEVICESPECIFICPARAMETER( dev, 05873 ReferenceSpadType, is_aperture_spads ); 05874 } 05875 } 05876 } 05877 05878 return status; 05879 } 05880 05881 VL53L0X_Error VL53L0X::wrapped_vl53l0x_get_sequence_steps_info( 05882 VL53L0X_SequenceStepId sequence_step_id, 05883 char *p_sequence_steps_string ) 05884 { 05885 VL53L0X_Error status = VL53L0X_ERROR_NONE; 05886 LOG_FUNCTION_START( "" ); 05887 05888 switch ( sequence_step_id ) { 05889 case VL53L0X_SEQUENCESTEP_TCC: 05890 VL53L0X_COPYSTRING( p_sequence_steps_string, 05891 VL53L0X_STRING_SEQUENCESTEP_TCC ); 05892 break; 05893 case VL53L0X_SEQUENCESTEP_DSS: 05894 VL53L0X_COPYSTRING( p_sequence_steps_string, 05895 VL53L0X_STRING_SEQUENCESTEP_DSS ); 05896 break; 05897 case VL53L0X_SEQUENCESTEP_MSRC: 05898 VL53L0X_COPYSTRING( p_sequence_steps_string, 05899 VL53L0X_STRING_SEQUENCESTEP_MSRC ); 05900 break; 05901 case VL53L0X_SEQUENCESTEP_PRE_RANGE: 05902 VL53L0X_COPYSTRING( p_sequence_steps_string, 05903 VL53L0X_STRING_SEQUENCESTEP_PRE_RANGE ); 05904 break; 05905 case VL53L0X_SEQUENCESTEP_FINAL_RANGE: 05906 VL53L0X_COPYSTRING( p_sequence_steps_string, 05907 VL53L0X_STRING_SEQUENCESTEP_FINAL_RANGE ); 05908 break; 05909 05910 default: 05911 status = VL53L0X_ERROR_INVALID_PARAMS; 05912 } 05913 05914 LOG_FUNCTION_END( status ); 05915 05916 return status; 05917 } 05918 05919 VL53L0X_Error VL53L0X::vl53l0x_get_sequence_steps_info( VL53L0X_SequenceStepId sequence_step_id, 05920 char *p_sequence_steps_string ) 05921 { 05922 VL53L0X_Error status = VL53L0X_ERROR_NONE; 05923 LOG_FUNCTION_START( "" ); 05924 05925 status = wrapped_vl53l0x_get_sequence_steps_info( 05926 sequence_step_id, 05927 p_sequence_steps_string ); 05928 05929 LOG_FUNCTION_END( status ); 05930 05931 return status; 05932 } 05933 05934 int32_t VL53L0X::vl53l0x_get_timer_frequency( int32_t *p_timer_freq_hz ) 05935 { 05936 *p_timer_freq_hz = 0; 05937 return STATUS_FAIL; 05938 } 05939 05940 int32_t VL53L0X::vl53l0x_get_timer_value( int32_t *p_timer_count ) 05941 { 05942 *p_timer_count = 0; 05943 return STATUS_FAIL; 05944 } 05945 05946 VL53L0X_Error VL53L0X::vl53l0x_enable_interrupt_mask( VL53L0X_DEV dev, uint32_t interrupt_mask ) 05947 { 05948 VL53L0X_Error Status = VL53L0X_ERROR_NOT_IMPLEMENTED; 05949 LOG_FUNCTION_START( "" ); 05950 05951 /* not implemented for VL53L0X */ 05952 05953 LOG_FUNCTION_END( Status ); 05954 return Status; 05955 } 05956 05957 VL53L0X_Error VL53L0X::vl53l0x_get_device_error_status( VL53L0X_DEV dev, 05958 VL53L0X_DeviceError *p_device_error_status ) 05959 { 05960 VL53L0X_Error status = VL53L0X_ERROR_NONE; 05961 uint8_t range_status; 05962 05963 LOG_FUNCTION_START( "" ); 05964 05965 status = vl53l0x_read_byte( dev, VL53L0X_REG_RESULT_RANGE_STATUS, 05966 &range_status ); 05967 05968 *p_device_error_status = ( VL53L0X_DeviceError )( ( range_status & 0x78 ) >> 3 ); 05969 05970 LOG_FUNCTION_END( status ); 05971 return status; 05972 } 05973 05974 05975 VL53L0X_Error VL53L0X::vl53l0x_get_device_error_string( VL53L0X_DeviceError error_code, 05976 char *p_device_error_string ) 05977 { 05978 VL53L0X_Error status = VL53L0X_ERROR_NONE; 05979 05980 LOG_FUNCTION_START( "" ); 05981 05982 status = wrapped_vl53l0x_get_device_error_string( error_code, p_device_error_string ); 05983 05984 LOG_FUNCTION_END( status ); 05985 return status; 05986 } 05987 05988 VL53L0X_Error VL53L0X::vl53l0x_get_dmax_cal_parameters( VL53L0X_DEV dev, 05989 uint16_t *p_range_milli_meter, FixPoint1616_t *p_signal_rate_rtn_mega_cps ) 05990 { 05991 VL53L0X_Error status = VL53L0X_ERROR_NONE; 05992 05993 LOG_FUNCTION_START( "" ); 05994 05995 *p_range_milli_meter = PALDevDataGet( dev, DmaxCalRangeMilliMeter ); 05996 *p_signal_rate_rtn_mega_cps = PALDevDataGet( dev, 05997 DmaxCalSignalRateRtnMegaCps ); 05998 05999 LOG_FUNCTION_END( status ); 06000 return status; 06001 } 06002 06003 VL53L0X_Error VL53L0X::vl53l0x_get_dmax_cal_parameters( VL53L0X_DEV dev, 06004 uint16_t range_milli_meter, FixPoint1616_t signal_rate_rtn_mega_cps ) 06005 { 06006 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06007 FixPoint1616_t signal_rate_rtn_mega_cps_temp = 0; 06008 06009 LOG_FUNCTION_START( "" ); 06010 06011 /* Check if one of input parameter is zero, in that case the 06012 * value are get from NVM */ 06013 if ( ( range_milli_meter == 0 ) || ( signal_rate_rtn_mega_cps == 0 ) ) { 06014 /* NVM parameters */ 06015 /* Run VL53L0X_get_info_from_device wit option 4 to get 06016 * signal rate at 400 mm if the value have been already 06017 * get this function will return with no access to device */ 06018 vl53l0x_get_info_from_device( dev, 4 ); 06019 06020 signal_rate_rtn_mega_cps_temp = VL53L0X_GETDEVICESPECIFICPARAMETER( 06021 dev, SignalRateMeasFixed400mm ); 06022 06023 PALDevDataSet( dev, DmaxCalRangeMilliMeter, 400 ); 06024 PALDevDataSet( dev, DmaxCalSignalRateRtnMegaCps, 06025 signal_rate_rtn_mega_cps_temp ); 06026 } else { 06027 /* User parameters */ 06028 PALDevDataSet( dev, DmaxCalRangeMilliMeter, range_milli_meter ); 06029 PALDevDataSet( dev, DmaxCalSignalRateRtnMegaCps, 06030 signal_rate_rtn_mega_cps ); 06031 } 06032 06033 LOG_FUNCTION_END( status ); 06034 return status; 06035 } 06036 06037 VL53L0X_Error VL53L0X::vl53L0x_set_gpio_config( VL53L0X_DEV dev, uint8_t pin, 06038 VL53L0X_DeviceModes device_mode, VL53L0X_GpioFunctionality functionality, 06039 VL53L0X_InterruptPolarity polarity ) 06040 { 06041 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06042 uint8_t data; 06043 06044 LOG_FUNCTION_START( "" ); 06045 06046 if ( pin != 0 ) { 06047 status = VL53L0X_ERROR_GPIO_NOT_EXISTING; 06048 } else if ( device_mode == VL53L0X_DEVICEMODE_GPIO_DRIVE ) { 06049 if ( polarity == VL53L0X_INTERRUPTPOLARITY_LOW ) 06050 data = 0x10; 06051 else 06052 data = 1; 06053 06054 status = vl53l0x_write_byte( dev, 06055 VL53L0X_REG_GPIO_HV_MUX_ACTIVE_HIGH, data ); 06056 06057 } else if ( device_mode == VL53L0X_DEVICEMODE_GPIO_OSC ) { 06058 06059 status |= vl53l0x_write_byte( dev, 0xff, 0x01 ); 06060 status |= vl53l0x_write_byte( dev, 0x00, 0x00 ); 06061 06062 status |= vl53l0x_write_byte( dev, 0xff, 0x00 ); 06063 status |= vl53l0x_write_byte( dev, 0x80, 0x01 ); 06064 status |= vl53l0x_write_byte( dev, 0x85, 0x02 ); 06065 06066 status |= vl53l0x_write_byte( dev, 0xff, 0x04 ); 06067 status |= vl53l0x_write_byte( dev, 0xcd, 0x00 ); 06068 status |= vl53l0x_write_byte( dev, 0xcc, 0x11 ); 06069 06070 status |= vl53l0x_write_byte( dev, 0xff, 0x07 ); 06071 status |= vl53l0x_write_byte( dev, 0xbe, 0x00 ); 06072 06073 status |= vl53l0x_write_byte( dev, 0xff, 0x06 ); 06074 status |= vl53l0x_write_byte( dev, 0xcc, 0x09 ); 06075 06076 status |= vl53l0x_write_byte( dev, 0xff, 0x00 ); 06077 status |= vl53l0x_write_byte( dev, 0xff, 0x01 ); 06078 status |= vl53l0x_write_byte( dev, 0x00, 0x00 ); 06079 06080 } else { 06081 06082 if ( status == VL53L0X_ERROR_NONE ) { 06083 switch ( functionality ) { 06084 case VL53L0X_GPIOFUNCTIONALITY_OFF: 06085 data = 0x00; 06086 break; 06087 case VL53L0X_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_LOW: 06088 data = 0x01; 06089 break; 06090 case VL53L0X_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_HIGH: 06091 data = 0x02; 06092 break; 06093 case VL53L0X_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_OUT: 06094 data = 0x03; 06095 break; 06096 case VL53L0X_GPIOFUNCTIONALITY_NEW_MEASURE_READY: 06097 data = 0x04; 06098 break; 06099 default: 06100 status = 06101 VL53L0X_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED; 06102 } 06103 } 06104 06105 if ( status == VL53L0X_ERROR_NONE ) 06106 status = vl53l0x_write_byte( dev, 06107 VL53L0X_REG_SYSTEM_INTERRUPT_CONFIG_GPIO, data ); 06108 06109 if ( status == VL53L0X_ERROR_NONE ) { 06110 if ( polarity == VL53L0X_INTERRUPTPOLARITY_LOW ) 06111 data = 0; 06112 else 06113 data = ( uint8_t )( 1 << 4 ); 06114 06115 status = vl53l0x_update_byte( dev, 06116 VL53L0X_REG_GPIO_HV_MUX_ACTIVE_HIGH, 0xEF, data ); 06117 } 06118 06119 if ( status == VL53L0X_ERROR_NONE ) 06120 VL53L0X_SETDEVICESPECIFICPARAMETER( dev, 06121 Pin0GpioFunctionality, functionality ); 06122 06123 if ( status == VL53L0X_ERROR_NONE ) 06124 status = vl53l0x_clear_interrupt_mask( dev, 0 ); 06125 06126 } 06127 06128 LOG_FUNCTION_END( status ); 06129 return status; 06130 } 06131 06132 06133 VL53L0X_Error VL53L0X::vl53l0x_get_gpio_config( VL53L0X_DEV dev, uint8_t pin, 06134 VL53L0X_DeviceModes *p_device_mode, 06135 VL53L0X_GpioFunctionality *p_functionality, 06136 VL53L0X_InterruptPolarity *p_polarity ) 06137 { 06138 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06139 VL53L0X_GpioFunctionality gpio_functionality; 06140 uint8_t data; 06141 06142 LOG_FUNCTION_START( "" ); 06143 06144 /* pDeviceMode not managed by Ewok it return the current mode */ 06145 06146 status = vl53l0x_get_device_mode( dev, p_device_mode ); 06147 06148 if ( status == VL53L0X_ERROR_NONE ) { 06149 if ( pin != 0 ) { 06150 status = VL53L0X_ERROR_GPIO_NOT_EXISTING; 06151 } else { 06152 status = vl53l0x_read_byte( dev, 06153 VL53L0X_REG_SYSTEM_INTERRUPT_CONFIG_GPIO, &data ); 06154 } 06155 } 06156 06157 if ( status == VL53L0X_ERROR_NONE ) { 06158 switch ( data & 0x07 ) { 06159 case 0x00: 06160 gpio_functionality = VL53L0X_GPIOFUNCTIONALITY_OFF; 06161 break; 06162 case 0x01: 06163 gpio_functionality = 06164 VL53L0X_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_LOW; 06165 break; 06166 case 0x02: 06167 gpio_functionality = 06168 VL53L0X_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_HIGH; 06169 break; 06170 case 0x03: 06171 gpio_functionality = 06172 VL53L0X_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_OUT; 06173 break; 06174 case 0x04: 06175 gpio_functionality = 06176 VL53L0X_GPIOFUNCTIONALITY_NEW_MEASURE_READY; 06177 break; 06178 default: 06179 status = VL53L0X_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED; 06180 } 06181 } 06182 06183 if ( status == VL53L0X_ERROR_NONE ) 06184 status = vl53l0x_read_byte( dev, VL53L0X_REG_GPIO_HV_MUX_ACTIVE_HIGH, 06185 &data ); 06186 06187 if ( status == VL53L0X_ERROR_NONE ) { 06188 if ( ( data & ( uint8_t )( 1 << 4 ) ) == 0 ) 06189 *p_polarity = VL53L0X_INTERRUPTPOLARITY_LOW; 06190 else 06191 *p_polarity = VL53L0X_INTERRUPTPOLARITY_HIGH; 06192 } 06193 06194 if ( status == VL53L0X_ERROR_NONE ) { 06195 *p_functionality = gpio_functionality; 06196 VL53L0X_SETDEVICESPECIFICPARAMETER( dev, Pin0GpioFunctionality, 06197 gpio_functionality ); 06198 } 06199 06200 LOG_FUNCTION_END( status ); 06201 return status; 06202 } 06203 06204 VL53L0X_Error VL53L0X::vl53l0x_get_histogram_measurement_data( VL53L0X_DEV dev, 06205 VL53L0X_HistogramMeasurementData_t *p_histogram_measurement_data ) 06206 { 06207 VL53L0X_Error status = VL53L0X_ERROR_NOT_IMPLEMENTED; 06208 LOG_FUNCTION_START( "" ); 06209 06210 LOG_FUNCTION_END( status ); 06211 return status; 06212 } 06213 06214 VL53L0X_Error VL53L0X::vl53l0x_get_histogram_mode( VL53L0X_DEV dev, 06215 VL53L0X_HistogramModes *p_histogram_mode ) 06216 { 06217 VL53L0X_Error status = VL53L0X_ERROR_NOT_IMPLEMENTED; 06218 LOG_FUNCTION_START( "" ); 06219 06220 /* not implemented on VL53L0X */ 06221 06222 LOG_FUNCTION_END( status ); 06223 return status; 06224 } 06225 06226 VL53L0X_Error VL53L0X::vl53l0x_set_histogram_mode( VL53L0X_DEV dev, 06227 VL53L0X_HistogramModes histogram_mode ) 06228 { 06229 VL53L0X_Error status = VL53L0X_ERROR_NOT_IMPLEMENTED; 06230 LOG_FUNCTION_START( "" ); 06231 06232 /* not implemented on VL53L0X */ 06233 06234 LOG_FUNCTION_END( Status ); 06235 return status; 06236 } 06237 06238 VL53L0X_Error VL53L0X::vl53l0x_get_limit_check_current( VL53L0X_DEV dev, uint16_t limit_check_id, 06239 FixPoint1616_t *p_limit_check_current ) 06240 { 06241 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06242 VL53L0X_RangingMeasurementData_t last_range_data_buffer; 06243 06244 LOG_FUNCTION_START( "" ); 06245 06246 if ( limit_check_id >= VL53L0X_CHECKENABLE_NUMBER_OF_CHECKS ) { 06247 status = VL53L0X_ERROR_INVALID_PARAMS; 06248 } else { 06249 switch ( limit_check_id ) { 06250 case VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE: 06251 /* Need to run a ranging to have the latest values */ 06252 *p_limit_check_current = PALDevDataGet( dev, SigmaEstimate ); 06253 06254 break; 06255 06256 case VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE: 06257 /* Need to run a ranging to have the latest values */ 06258 last_range_data_buffer = PALDevDataGet( dev, 06259 LastRangeMeasure ); 06260 *p_limit_check_current = 06261 last_range_data_buffer.SignalRateRtnMegaCps; 06262 06263 break; 06264 06265 case VL53L0X_CHECKENABLE_SIGNAL_REF_CLIP: 06266 /* Need to run a ranging to have the latest values */ 06267 *p_limit_check_current = PALDevDataGet( dev, 06268 LastSignalRefMcps ); 06269 06270 break; 06271 06272 case VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD: 06273 /* Need to run a ranging to have the latest values */ 06274 last_range_data_buffer = PALDevDataGet( dev, 06275 LastRangeMeasure ); 06276 *p_limit_check_current = 06277 last_range_data_buffer.SignalRateRtnMegaCps; 06278 06279 break; 06280 06281 case VL53L0X_CHECKENABLE_SIGNAL_RATE_MSRC: 06282 /* Need to run a ranging to have the latest values */ 06283 last_range_data_buffer = PALDevDataGet( dev, 06284 LastRangeMeasure ); 06285 *p_limit_check_current = 06286 last_range_data_buffer.SignalRateRtnMegaCps; 06287 06288 break; 06289 06290 case VL53L0X_CHECKENABLE_SIGNAL_RATE_PRE_RANGE: 06291 /* Need to run a ranging to have the latest values */ 06292 last_range_data_buffer = PALDevDataGet( dev, 06293 LastRangeMeasure ); 06294 *p_limit_check_current = 06295 last_range_data_buffer.SignalRateRtnMegaCps; 06296 06297 break; 06298 06299 default: 06300 status = VL53L0X_ERROR_INVALID_PARAMS; 06301 } 06302 } 06303 06304 LOG_FUNCTION_END( status ); 06305 return status; 06306 06307 } 06308 06309 VL53L0X_Error VL53L0X::vl53l0x_get_limit_check_info( VL53L0X_DEV dev, uint16_t limit_check_id, 06310 char *p_limit_check_string ) 06311 { 06312 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06313 06314 LOG_FUNCTION_START( "" ); 06315 06316 status = wrapped_vl53l0x_get_limit_check_info( dev, limit_check_id, 06317 p_limit_check_string ); 06318 06319 LOG_FUNCTION_END( status ); 06320 return status; 06321 } 06322 06323 VL53L0X_Error VL53L0X::vl53l0x_get_limit_check_status( VL53L0X_DEV dev, uint16_t limit_check_id, 06324 uint8_t *p_limit_check_status ) 06325 { 06326 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06327 uint8_t temp8; 06328 06329 LOG_FUNCTION_START( "" ); 06330 06331 if ( limit_check_id >= VL53L0X_CHECKENABLE_NUMBER_OF_CHECKS ) { 06332 status = VL53L0X_ERROR_INVALID_PARAMS; 06333 } else { 06334 06335 VL53L0X_GETARRAYPARAMETERFIELD( dev, LimitChecksStatus, 06336 limit_check_id, temp8 ); 06337 06338 *p_limit_check_status = temp8; 06339 06340 } 06341 06342 LOG_FUNCTION_END( status ); 06343 return status; 06344 } 06345 06346 VL53L0X_Error VL53L0X::vl53l0x_set_linearity_corrective_gain( VL53L0X_DEV dev, 06347 int16_t linearity_corrective_gain ) 06348 { 06349 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06350 LOG_FUNCTION_START( "" ); 06351 06352 if ( ( linearity_corrective_gain < 0 ) || ( linearity_corrective_gain > 1000 ) ) 06353 status = VL53L0X_ERROR_INVALID_PARAMS; 06354 else { 06355 PALDevDataSet( dev, LinearityCorrectiveGain, 06356 linearity_corrective_gain ); 06357 06358 if ( linearity_corrective_gain != 1000 ) { 06359 /* Disable FW Xtalk */ 06360 status = vl53l0x_write_word( dev, 06361 VL53L0X_REG_CROSSTALK_COMPENSATION_PEAK_RATE_MCPS, 0 ); 06362 } 06363 } 06364 06365 LOG_FUNCTION_END( status ); 06366 return status; 06367 } 06368 06369 VL53L0X_Error VL53L0X::vl53l0x_get_linearity_corrective_gain( VL53L0X_DEV dev, 06370 uint16_t *p_linearity_corrective_gain ) 06371 { 06372 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06373 LOG_FUNCTION_START( "" ); 06374 06375 *p_linearity_corrective_gain = PALDevDataGet( dev, LinearityCorrectiveGain ); 06376 06377 LOG_FUNCTION_END( status ); 06378 return status; 06379 } 06380 06381 VL53L0X_Error VL53L0X::vl53l0x_get_max_number_of_roi_zones( VL53L0X_DEV dev, 06382 uint8_t *p_max_number_of_roi_zones ) 06383 { 06384 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06385 06386 LOG_FUNCTION_START( "" ); 06387 06388 *p_max_number_of_roi_zones = 1; 06389 06390 LOG_FUNCTION_END( status ); 06391 return status; 06392 } 06393 06394 VL53L0X_Error VL53L0X::vl53l0x_get_measurement_ref_signal( VL53L0X_DEV dev, 06395 FixPoint1616_t *p_measurement_ref_signal ) 06396 { 06397 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06398 uint8_t signal_ref_clip_limit_check_enable = 0; 06399 LOG_FUNCTION_START( "" ); 06400 06401 status = vl53l0x_get_limit_check_enable( dev, 06402 VL53L0X_CHECKENABLE_SIGNAL_REF_CLIP, 06403 &signal_ref_clip_limit_check_enable ); 06404 if ( signal_ref_clip_limit_check_enable != 0 ) { 06405 *p_measurement_ref_signal = PALDevDataGet( dev, LastSignalRefMcps ); 06406 } else { 06407 status = VL53L0X_ERROR_INVALID_COMMAND; 06408 } 06409 LOG_FUNCTION_END( status ); 06410 06411 return status; 06412 } 06413 06414 06415 VL53L0X_Error VL53L0X::vl53l0x_get_number_of_limit_check( uint16_t *p_number_of_limit_check ) 06416 { 06417 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06418 LOG_FUNCTION_START( "" ); 06419 06420 *p_number_of_limit_check = VL53L0X_CHECKENABLE_NUMBER_OF_CHECKS; 06421 06422 LOG_FUNCTION_END( status ); 06423 return status; 06424 } 06425 06426 VL53L0X_Error VL53L0X::vl53l0x_get_number_of_roi_zones( VL53L0X_DEV dev, 06427 uint8_t *p_number_of_roi_zones ) 06428 { 06429 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06430 06431 LOG_FUNCTION_START( "" ); 06432 06433 *p_number_of_roi_zones = 1; 06434 06435 LOG_FUNCTION_END( status ); 06436 return status; 06437 } 06438 06439 VL53L0X_Error VL53L0X::vl53l0x_set_number_of_roi_zones( VL53L0X_DEV dev, 06440 uint8_t number_of_roi_zones ) 06441 { 06442 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06443 06444 LOG_FUNCTION_START( "" ); 06445 06446 if ( number_of_roi_zones != 1 ) 06447 status = VL53L0X_ERROR_INVALID_PARAMS; 06448 06449 06450 LOG_FUNCTION_END( status ); 06451 return status; 06452 } 06453 06454 VL53L0X_Error VL53L0X::vl53l0x_get_number_of_sequence_steps( VL53L0X_DEV dev, 06455 uint8_t *p_number_of_sequence_steps ) 06456 { 06457 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06458 LOG_FUNCTION_START( "" ); 06459 06460 *p_number_of_sequence_steps = VL53L0X_SEQUENCESTEP_NUMBER_OF_CHECKS; 06461 06462 LOG_FUNCTION_END( status ); 06463 return status; 06464 } 06465 06466 VL53L0X_Error VL53L0X::vl53l0x_get_pal_error_string( VL53L0X_Error pal_error_code, 06467 char *p_pal_error_string ) 06468 { 06469 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06470 LOG_FUNCTION_START( "" ); 06471 06472 status = wrapped_vl53l0x_get_pal_error_string( pal_error_code, p_pal_error_string ); 06473 06474 LOG_FUNCTION_END( status ); 06475 return status; 06476 } 06477 06478 VL53L0X_Error VL53L0X::vl53l0x_get_pal_spec_version( VL53L0X_Version_t *p_pal_spec_version ) 06479 { 06480 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06481 06482 LOG_FUNCTION_START( "" ); 06483 06484 p_pal_spec_version->major = VL53L0X_SPECIFICATION_VER_MAJOR; 06485 p_pal_spec_version->minor = VL53L0X_SPECIFICATION_VER_MINOR; 06486 p_pal_spec_version->build = VL53L0X_SPECIFICATION_VER_SUB; 06487 06488 p_pal_spec_version->revision = VL53L0X_SPECIFICATION_VER_REVISION; 06489 06490 LOG_FUNCTION_END( status ); 06491 return status; 06492 } 06493 06494 VL53L0X_Error VL53L0X::vl53l0x_get_pal_state( VL53L0X_DEV dev, VL53L0X_State *p_pal_state ) 06495 { 06496 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06497 LOG_FUNCTION_START( "" ); 06498 06499 *p_pal_state = PALDevDataGet( dev, PalState ); 06500 06501 LOG_FUNCTION_END( status ); 06502 return status; 06503 } 06504 06505 VL53L0X_Error VL53L0X::vl53l0x_get_pal_state_string( VL53L0X_State pal_state_code, 06506 char *p_pal_state_string ) 06507 { 06508 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06509 LOG_FUNCTION_START( "" ); 06510 06511 status = wrapped_vl53l0x_get_pal_state_string( pal_state_code, p_pal_state_string ); 06512 06513 LOG_FUNCTION_END( status ); 06514 return status; 06515 } 06516 06517 VL53L0X_Error VL53L0X::vl53l0x_get_power_mode( VL53L0X_DEV dev, VL53L0X_PowerModes *p_power_mode ) 06518 { 06519 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06520 uint8_t byte; 06521 LOG_FUNCTION_START( "" ); 06522 06523 /* Only level1 of Power mode exists */ 06524 status = vl53l0x_read_byte( dev, 0x80, &byte ); 06525 06526 if ( status == VL53L0X_ERROR_NONE ) { 06527 if ( byte == 1 ) { 06528 PALDevDataSet( dev, PowerMode, 06529 VL53L0X_POWERMODE_IDLE_LEVEL1 ); 06530 } else { 06531 PALDevDataSet( dev, PowerMode, 06532 VL53L0X_POWERMODE_STANDBY_LEVEL1 ); 06533 } 06534 } 06535 06536 LOG_FUNCTION_END( status ); 06537 return status; 06538 } 06539 06540 VL53L0X_Error VL53L0X::vl53l0x_set_power_mode( VL53L0X_DEV dev, VL53L0X_PowerModes power_mode ) 06541 { 06542 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06543 LOG_FUNCTION_START( "" ); 06544 06545 /* Only level1 of Power mode exists */ 06546 if ( ( power_mode != VL53L0X_POWERMODE_STANDBY_LEVEL1 ) 06547 && ( power_mode != VL53L0X_POWERMODE_IDLE_LEVEL1 ) ) { 06548 status = VL53L0X_ERROR_MODE_NOT_SUPPORTED; 06549 } else if ( power_mode == VL53L0X_POWERMODE_STANDBY_LEVEL1 ) { 06550 /* set the standby level1 of power mode */ 06551 status = vl53l0x_write_byte( dev, 0x80, 0x00 ); 06552 if ( status == VL53L0X_ERROR_NONE ) { 06553 /* Set PAL State to standby */ 06554 PALDevDataSet( dev, PalState, VL53L0X_STATE_STANDBY ); 06555 PALDevDataSet( dev, PowerMode, 06556 VL53L0X_POWERMODE_STANDBY_LEVEL1 ); 06557 } 06558 06559 } else { 06560 /* VL53L0X_POWERMODE_IDLE_LEVEL1 */ 06561 status = vl53l0x_write_byte( dev, 0x80, 0x00 ); 06562 if ( status == VL53L0X_ERROR_NONE ) 06563 status = vl53l0x_static_init( dev ); 06564 06565 if ( status == VL53L0X_ERROR_NONE ) 06566 PALDevDataSet( dev, PowerMode, 06567 VL53L0X_POWERMODE_IDLE_LEVEL1 ); 06568 06569 } 06570 06571 LOG_FUNCTION_END( status ); 06572 return status; 06573 } 06574 06575 VL53L0X_Error VL53L0X::vl53l0x_get_product_revision( VL53L0X_DEV dev, 06576 uint8_t *p_product_revision_major, uint8_t *p_product_revision_minor ) 06577 { 06578 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06579 uint8_t revision_id; 06580 06581 LOG_FUNCTION_START( "" ); 06582 06583 status = vl53l0x_read_byte( dev, VL53L0X_REG_IDENTIFICATION_REVISION_ID, 06584 &revision_id ); 06585 *p_product_revision_major = 1; 06586 *p_product_revision_minor = ( revision_id & 0xF0 ) >> 4; 06587 06588 LOG_FUNCTION_END( status ); 06589 return status; 06590 06591 } 06592 06593 VL53L0X_Error VL53L0X::vl53l0x_get_range_status_string( uint8_t range_status, 06594 char *p_range_status_string ) 06595 { 06596 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06597 LOG_FUNCTION_START( "" ); 06598 06599 status = wrapped_vl53l0x_get_range_status_string( range_status, 06600 p_range_status_string ); 06601 06602 LOG_FUNCTION_END( status ); 06603 return status; 06604 } 06605 06606 VL53L0X_Error VL53L0X::vl53l0x_get_ref_calibration( VL53L0X_DEV dev, uint8_t *p_vhv_settings, 06607 uint8_t *p_phase_cal ) 06608 { 06609 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06610 LOG_FUNCTION_START( "" ); 06611 06612 status = wrapped_vl53l0x_get_ref_calibration( dev, p_vhv_settings, p_phase_cal ); 06613 06614 LOG_FUNCTION_END( status ); 06615 return status; 06616 } 06617 06618 VL53L0X_Error VL53L0X::vl53l0x_get_sequence_step_enable( VL53L0X_DEV dev, 06619 VL53L0X_SequenceStepId sequence_step_id, uint8_t *p_sequence_step_enabled ) 06620 { 06621 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06622 uint8_t SequenceConfig = 0; 06623 LOG_FUNCTION_START( "" ); 06624 06625 status = vl53l0x_read_byte( dev, VL53L0X_REG_SYSTEM_SEQUENCE_CONFIG, 06626 &SequenceConfig ); 06627 06628 if ( status == VL53L0X_ERROR_NONE ) { 06629 status = sequence_step_enabled( dev, sequence_step_id, 06630 SequenceConfig, p_sequence_step_enabled ); 06631 } 06632 06633 LOG_FUNCTION_END( status ); 06634 return status; 06635 } 06636 06637 VL53L0X_Error VL53L0X::vl53l0x_set_sequence_step_timeout( VL53L0X_DEV dev, 06638 VL53L0X_SequenceStepId sequence_step_id, FixPoint1616_t time_out_milli_secs ) 06639 { 06640 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06641 VL53L0X_Error status1 = VL53L0X_ERROR_NONE; 06642 uint32_t TimeoutMicroSeconds = ( ( time_out_milli_secs * 1000 ) + 0x8000 ) 06643 >> 16; 06644 uint32_t MeasurementTimingBudgetMicroSeconds; 06645 FixPoint1616_t OldTimeOutMicroSeconds; 06646 06647 LOG_FUNCTION_START( "" ); 06648 06649 /* Read back the current value in case we need to revert back to this. 06650 */ 06651 status = get_sequence_step_timeout( dev, sequence_step_id, 06652 &OldTimeOutMicroSeconds ); 06653 06654 if ( status == VL53L0X_ERROR_NONE ) { 06655 status = set_sequence_step_timeout( dev, sequence_step_id, 06656 TimeoutMicroSeconds ); 06657 } 06658 06659 if ( status == VL53L0X_ERROR_NONE ) { 06660 VL53L0X_GETPARAMETERFIELD( dev, 06661 MeasurementTimingBudgetMicroSeconds, 06662 MeasurementTimingBudgetMicroSeconds ); 06663 06664 /* At this point we don't know if the requested value is valid, 06665 therefore proceed to update the entire timing budget and 06666 if this fails, revert back to the previous value. 06667 */ 06668 status = vl53l0x_set_measurement_timing_budget_micro_seconds( dev, 06669 MeasurementTimingBudgetMicroSeconds ); 06670 06671 if ( status != VL53L0X_ERROR_NONE ) { 06672 status1 = set_sequence_step_timeout( dev, sequence_step_id, 06673 OldTimeOutMicroSeconds ); 06674 06675 if ( status1 == VL53L0X_ERROR_NONE ) { 06676 status1 = 06677 vl53l0x_set_measurement_timing_budget_micro_seconds( 06678 dev, 06679 MeasurementTimingBudgetMicroSeconds ); 06680 } 06681 06682 status = status1; 06683 } 06684 } 06685 06686 LOG_FUNCTION_END( status ); 06687 06688 return status; 06689 } 06690 06691 VL53L0X_Error VL53L0X::vl53l0x_get_sequence_step_timeout( VL53L0X_DEV dev, 06692 VL53L0X_SequenceStepId sequence_step_id, FixPoint1616_t *p_time_out_milli_secs ) 06693 { 06694 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06695 uint32_t timeout_micro_seconds; 06696 LOG_FUNCTION_START( "" ); 06697 06698 status = get_sequence_step_timeout( dev, sequence_step_id, 06699 &timeout_micro_seconds ); 06700 if ( status == VL53L0X_ERROR_NONE ) { 06701 timeout_micro_seconds <<= 8; 06702 *p_time_out_milli_secs = ( timeout_micro_seconds + 500 ) / 1000; 06703 *p_time_out_milli_secs <<= 8; 06704 } 06705 06706 LOG_FUNCTION_END( status ); 06707 return status; 06708 } 06709 06710 VL53L0X_Error VL53L0X::vl53l0x_set_spad_ambient_damper_factor( VL53L0X_DEV dev, 06711 uint16_t spad_ambient_damper_factor ) 06712 { 06713 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06714 uint8_t byte; 06715 LOG_FUNCTION_START( "" ); 06716 06717 byte = ( uint8_t )( spad_ambient_damper_factor & 0x00FF ); 06718 06719 status = vl53l0x_write_byte( dev, 0xFF, 0x01 ); 06720 status |= vl53l0x_write_byte( dev, 0x42, byte ); 06721 status |= vl53l0x_write_byte( dev, 0xFF, 0x00 ); 06722 06723 LOG_FUNCTION_END( status ); 06724 return status; 06725 } 06726 06727 06728 VL53L0X_Error VL53L0X::vl53l0x_get_spad_ambient_damper_factor( VL53L0X_DEV dev, 06729 uint16_t *p_spad_ambient_damper_factor ) 06730 { 06731 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06732 uint8_t Byte; 06733 LOG_FUNCTION_START( "" ); 06734 06735 status = vl53l0x_write_byte( dev, 0xFF, 0x01 ); 06736 status |= vl53l0x_read_byte( dev, 0x42, &Byte ); 06737 status |= vl53l0x_write_byte( dev, 0xFF, 0x00 ); 06738 *p_spad_ambient_damper_factor = ( uint16_t )Byte; 06739 06740 LOG_FUNCTION_END( status ); 06741 return status; 06742 } 06743 06744 VL53L0X_Error VL53L0X::vl53l0x_set_spad_ambient_damper_threshold( VL53L0X_DEV dev, 06745 uint16_t spad_ambient_damper_threshold ) 06746 { 06747 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06748 LOG_FUNCTION_START( "" ); 06749 06750 status = vl53l0x_write_byte( dev, 0xFF, 0x01 ); 06751 status |= vl53l0x_write_word( dev, 0x40, spad_ambient_damper_threshold ); 06752 status |= vl53l0x_write_byte( dev, 0xFF, 0x00 ); 06753 06754 LOG_FUNCTION_END( status ); 06755 return status; 06756 } 06757 06758 VL53L0X_Error VL53L0X::vl53l0x_get_spad_ambient_damper_threshold( VL53L0X_DEV dev, 06759 uint16_t *p_spad_ambient_damper_threshold ) 06760 { 06761 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06762 LOG_FUNCTION_START( "" ); 06763 06764 status = vl53l0x_write_byte( dev, 0xFF, 0x01 ); 06765 status |= vl53l0x_read_word( dev, 0x40, p_spad_ambient_damper_threshold ); 06766 status |= vl53l0x_write_byte( dev, 0xFF, 0x00 ); 06767 06768 LOG_FUNCTION_END( status ); 06769 return status; 06770 } 06771 06772 VL53L0X_Error VL53L0X::vl53l0x_get_upper_limit_milli_meter( VL53L0X_DEV dev, 06773 uint16_t *p_upper_limit_milli_meter ) 06774 { 06775 VL53L0X_Error status = VL53L0X_ERROR_NOT_IMPLEMENTED; 06776 LOG_FUNCTION_START( "" ); 06777 06778 /* not implemented on VL53L0X */ 06779 06780 LOG_FUNCTION_END( status ); 06781 return status; 06782 } 06783 06784 VL53L0X_Error VL53L0X::vl53l0x_set_tuning_setting_buffer( VL53L0X_DEV dev, 06785 uint8_t *p_tuning_setting_buffer, uint8_t use_internal_tuning_settings ) 06786 { 06787 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06788 06789 LOG_FUNCTION_START( "" ); 06790 06791 if ( use_internal_tuning_settings == 1 ) { 06792 /* Force use internal settings */ 06793 PALDevDataSet( dev, UseInternalTuningSettings, 1 ); 06794 } else { 06795 06796 /* check that the first byte is not 0 */ 06797 if ( *p_tuning_setting_buffer != 0 ) { 06798 PALDevDataSet( dev, pTuningSettingsPointer, 06799 p_tuning_setting_buffer ); 06800 PALDevDataSet( dev, UseInternalTuningSettings, 0 ); 06801 06802 } else { 06803 status = VL53L0X_ERROR_INVALID_PARAMS; 06804 } 06805 } 06806 06807 LOG_FUNCTION_END( status ); 06808 return status; 06809 } 06810 06811 VL53L0X_Error VL53L0X::vl53l0x_get_tuning_setting_buffer( VL53L0X_DEV dev, 06812 uint8_t **pp_tuning_setting_buffer, uint8_t *p_use_internal_tuning_settings ) 06813 { 06814 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06815 06816 LOG_FUNCTION_START( "" ); 06817 06818 *pp_tuning_setting_buffer = PALDevDataGet( dev, pTuningSettingsPointer ); 06819 *p_use_internal_tuning_settings = PALDevDataGet( dev, 06820 UseInternalTuningSettings ); 06821 06822 LOG_FUNCTION_END( status ); 06823 return status; 06824 } 06825 06826 VL53L0X_Error VL53L0X::vl53l0x_get_version( VL53L0X_Version_t *p_version ) 06827 { 06828 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06829 LOG_FUNCTION_START( "" ); 06830 06831 p_version->major = VL53L0X_IMPLEMENTATION_VER_MAJOR; 06832 p_version->minor = VL53L0X_IMPLEMENTATION_VER_MINOR; 06833 p_version->build = VL53L0X_IMPLEMENTATION_VER_SUB; 06834 06835 p_version->revision = VL53L0X_IMPLEMENTATION_VER_REVISION; 06836 06837 LOG_FUNCTION_END( status ); 06838 return status; 06839 } 06840 06841 VL53L0X_Error VL53L0X::vl53l0x_lock_sequence_access( VL53L0X_DEV dev ) 06842 { 06843 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06844 06845 return status; 06846 } 06847 06848 VL53L0X_Error VL53L0X::vl53l0x_unlock_sequence_access( VL53L0X_DEV dev ) 06849 { 06850 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06851 06852 return status; 06853 } 06854 06855 VL53L0X_Error VL53L0X::vl53l0x_perform_offset_calibration( VL53L0X_DEV dev, 06856 FixPoint1616_t cal_distance_milli_meter, 06857 int32_t *p_offset_micro_meter ) 06858 { 06859 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06860 uint16_t sum_ranging = 0; 06861 FixPoint1616_t total_count = 0; 06862 VL53L0X_RangingMeasurementData_t ranging_measurement_data; 06863 FixPoint1616_t stored_mean_range; 06864 uint32_t stored_mean_range_as_int; 06865 uint32_t cal_distance_as_int_mm; 06866 uint8_t sequence_step_enabled; 06867 int meas = 0; 06868 06869 if ( cal_distance_milli_meter <= 0 ) 06870 status = VL53L0X_ERROR_INVALID_PARAMS; 06871 06872 if ( status == VL53L0X_ERROR_NONE ) 06873 status = wrapped_vl53l0x_set_offset_calibration_data_micro_meter( dev, 0 ); 06874 06875 06876 /* Get the value of the TCC */ 06877 if ( status == VL53L0X_ERROR_NONE ) 06878 status = vl53l0x_get_sequence_step_enable( dev, 06879 VL53L0X_SEQUENCESTEP_TCC, &sequence_step_enabled ); 06880 06881 06882 /* Disable the TCC */ 06883 if ( status == VL53L0X_ERROR_NONE ) 06884 status = vl53l0x_set_sequence_step_enable( dev, 06885 VL53L0X_SEQUENCESTEP_TCC, 0 ); 06886 06887 06888 /* Disable the RIT */ 06889 if ( status == VL53L0X_ERROR_NONE ) 06890 status = vl53l0x_set_limit_check_enable( dev, 06891 VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD, 0 ); 06892 06893 /* Perform 50 measurements and compute the averages */ 06894 if ( status == VL53L0X_ERROR_NONE ) { 06895 sum_ranging = 0; 06896 total_count = 0; 06897 for ( meas = 0; meas < 50; meas++ ) { 06898 status = vl53l0x_perform_single_ranging_measurement( dev, 06899 &ranging_measurement_data ); 06900 06901 if ( status != VL53L0X_ERROR_NONE ) 06902 break; 06903 06904 /* The range is valid when RangeStatus = 0 */ 06905 if ( ranging_measurement_data.RangeStatus == 0 ) { 06906 sum_ranging = sum_ranging + 06907 ranging_measurement_data.RangeMilliMeter; 06908 total_count = total_count + 1; 06909 } 06910 } 06911 06912 /* no valid values found */ 06913 if ( total_count == 0 ) 06914 status = VL53L0X_ERROR_RANGE_ERROR; 06915 } 06916 06917 06918 if ( status == VL53L0X_ERROR_NONE ) { 06919 /* FixPoint1616_t / uint16_t = FixPoint1616_t */ 06920 stored_mean_range = ( FixPoint1616_t )( ( uint32_t )( sum_ranging << 16 ) 06921 / total_count ); 06922 06923 stored_mean_range_as_int = ( stored_mean_range + 0x8000 ) >> 16; 06924 06925 /* Round Cal Distance to Whole Number. 06926 * Note that the cal distance is in mm, therefore no resolution 06927 * is lost.*/ 06928 cal_distance_as_int_mm = ( cal_distance_milli_meter + 0x8000 ) >> 16; 06929 06930 *p_offset_micro_meter = ( cal_distance_as_int_mm - 06931 stored_mean_range_as_int ) * 1000; 06932 06933 /* Apply the calculated offset */ 06934 if ( status == VL53L0X_ERROR_NONE ) { 06935 VL53L0X_SETPARAMETERFIELD( dev, RangeOffsetMicroMeters, 06936 *p_offset_micro_meter ); 06937 status = vl53l0x_set_offset_calibration_data_micro_meter( dev, 06938 *p_offset_micro_meter ); 06939 } 06940 06941 } 06942 06943 /* Restore the TCC */ 06944 if ( status == VL53L0X_ERROR_NONE ) { 06945 if ( sequence_step_enabled != 0 ) 06946 status = vl53l0x_set_sequence_step_enable( dev, 06947 VL53L0X_SEQUENCESTEP_TCC, 1 ); 06948 } 06949 06950 return status; 06951 } 06952 06953 VL53L0X_Error VL53L0X::vl53l0x_set_x_talk_compensation_enable( VL53L0X_DEV dev, 06954 uint8_t x_talk_compensation_enable ) 06955 { 06956 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06957 FixPoint1616_t temp_fix1616; 06958 uint16_t linearity_corrective_gain; 06959 06960 LOG_FUNCTION_START( "" ); 06961 06962 linearity_corrective_gain = PALDevDataGet( dev, LinearityCorrectiveGain ); 06963 06964 if ( ( x_talk_compensation_enable == 0 ) 06965 || ( linearity_corrective_gain != 1000 ) ) { 06966 temp_fix1616 = 0; 06967 } else { 06968 VL53L0X_GETPARAMETERFIELD( dev, XTalkCompensationRateMegaCps, 06969 temp_fix1616 ); 06970 } 06971 06972 /* the following register has a format 3.13 */ 06973 status = vl53l0x_write_word( dev, 06974 VL53L0X_REG_CROSSTALK_COMPENSATION_PEAK_RATE_MCPS, 06975 VL53L0X_FIXPOINT1616TOFIXPOINT313( temp_fix1616 ) ); 06976 06977 if ( status == VL53L0X_ERROR_NONE ) { 06978 if ( x_talk_compensation_enable == 0 ) { 06979 VL53L0X_SETPARAMETERFIELD( dev, XTalkCompensationEnable, 06980 0 ); 06981 } else { 06982 VL53L0X_SETPARAMETERFIELD( dev, XTalkCompensationEnable, 06983 1 ); 06984 } 06985 } 06986 06987 LOG_FUNCTION_END( status ); 06988 return status; 06989 } 06990 06991 06992 VL53L0X_Error VL53L0X::vl53l0x_perform_xtalk_calibration( VL53L0X_DEV dev, 06993 FixPoint1616_t xtalk_cal_distance, 06994 FixPoint1616_t *p_xtalk_compensation_rate_mega_cps ) 06995 { 06996 VL53L0X_Error status = VL53L0X_ERROR_NONE; 06997 uint16_t sum_ranging = 0; 06998 uint16_t sum_spads = 0; 06999 FixPoint1616_t sum_signal_rate = 0; 07000 FixPoint1616_t total_count = 0; 07001 uint8_t xtalk_meas = 0; 07002 VL53L0X_RangingMeasurementData_t ranging_measurement_data; 07003 FixPoint1616_t x_talk_stored_mean_signal_rate; 07004 FixPoint1616_t x_talk_stored_mean_range; 07005 FixPoint1616_t x_talk_stored_mean_rtn_spads; 07006 uint32_t signal_x_talk_total_per_spad; 07007 uint32_t x_talk_stored_mean_rtn_spads_as_int; 07008 uint32_t x_talk_cal_distance_as_int; 07009 FixPoint1616_t x_talk_compensation_rate_mega_cps; 07010 07011 if ( xtalk_cal_distance <= 0 ) 07012 status = VL53L0X_ERROR_INVALID_PARAMS; 07013 07014 /* Disable the XTalk compensation */ 07015 if ( status == VL53L0X_ERROR_NONE ) 07016 status = vl53l0x_set_x_talk_compensation_enable( dev, 0 ); 07017 07018 /* Disable the RIT */ 07019 if ( status == VL53L0X_ERROR_NONE ) { 07020 status = vl53l0x_set_limit_check_enable( dev, 07021 VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD, 0 ); 07022 } 07023 07024 /* Perform 50 measurements and compute the averages */ 07025 if ( status == VL53L0X_ERROR_NONE ) { 07026 sum_ranging = 0; 07027 sum_spads = 0; 07028 sum_signal_rate = 0; 07029 total_count = 0; 07030 for ( xtalk_meas = 0; xtalk_meas < 50; xtalk_meas++ ) { 07031 status = vl53l0x_perform_single_ranging_measurement( dev, 07032 &ranging_measurement_data ); 07033 07034 if ( status != VL53L0X_ERROR_NONE ) 07035 break; 07036 07037 /* The range is valid when RangeStatus = 0 */ 07038 if ( ranging_measurement_data.RangeStatus == 0 ) { 07039 sum_ranging = sum_ranging + 07040 ranging_measurement_data.RangeMilliMeter; 07041 sum_signal_rate = sum_signal_rate + 07042 ranging_measurement_data.SignalRateRtnMegaCps; 07043 sum_spads = sum_spads + 07044 ranging_measurement_data.EffectiveSpadRtnCount 07045 / 256; 07046 total_count = total_count + 1; 07047 } 07048 } 07049 07050 /* no valid values found */ 07051 if ( total_count == 0 ) 07052 status = VL53L0X_ERROR_RANGE_ERROR; 07053 07054 } 07055 07056 07057 if ( status == VL53L0X_ERROR_NONE ) { 07058 /* FixPoint1616_t / uint16_t = FixPoint1616_t */ 07059 x_talk_stored_mean_signal_rate = sum_signal_rate / total_count; 07060 x_talk_stored_mean_range = ( FixPoint1616_t )( ( uint32_t )( 07061 sum_ranging << 16 ) / total_count ); 07062 x_talk_stored_mean_rtn_spads = ( FixPoint1616_t )( ( uint32_t )( 07063 sum_spads << 16 ) / total_count ); 07064 07065 /* Round Mean Spads to Whole Number. 07066 * Typically the calculated mean SPAD count is a whole number 07067 * or very close to a whole 07068 * number, therefore any truncation will not result in a 07069 * significant loss in accuracy. 07070 * Also, for a grey target at a typical distance of around 07071 * 400mm, around 220 SPADs will 07072 * be enabled, therefore, any truncation will result in a loss 07073 * of accuracy of less than 07074 * 0.5%. 07075 */ 07076 x_talk_stored_mean_rtn_spads_as_int = ( x_talk_stored_mean_rtn_spads + 07077 0x8000 ) >> 16; 07078 07079 /* Round Cal Distance to Whole Number. 07080 * Note that the cal distance is in mm, therefore no resolution 07081 * is lost.*/ 07082 x_talk_cal_distance_as_int = ( xtalk_cal_distance + 0x8000 ) >> 16; 07083 07084 if ( x_talk_stored_mean_rtn_spads_as_int == 0 || 07085 x_talk_cal_distance_as_int == 0 || 07086 x_talk_stored_mean_range >= xtalk_cal_distance ) { 07087 x_talk_compensation_rate_mega_cps = 0; 07088 } else { 07089 /* Round Cal Distance to Whole Number. 07090 Note that the cal distance is in mm, therefore no 07091 resolution is lost.*/ 07092 x_talk_cal_distance_as_int = ( xtalk_cal_distance + 07093 0x8000 ) >> 16; 07094 07095 /* Apply division by mean spad count early in the 07096 * calculation to keep the numbers small. 07097 * This ensures we can maintain a 32bit calculation. 07098 * Fixed1616 / int := Fixed1616 */ 07099 signal_x_talk_total_per_spad = ( x_talk_stored_mean_signal_rate ) / 07100 x_talk_stored_mean_rtn_spads_as_int; 07101 07102 /* Complete the calculation for total Signal XTalk per 07103 * SPAD 07104 * Fixed1616 * (Fixed1616 - Fixed1616/int) := 07105 * (2^16 * Fixed1616) 07106 */ 07107 signal_x_talk_total_per_spad *= ( ( 1 << 16 ) - 07108 ( x_talk_stored_mean_range / x_talk_cal_distance_as_int ) ); 07109 07110 /* Round from 2^16 * Fixed1616, to Fixed1616. */ 07111 x_talk_compensation_rate_mega_cps = ( signal_x_talk_total_per_spad 07112 + 0x8000 ) >> 16; 07113 } 07114 07115 *p_xtalk_compensation_rate_mega_cps = x_talk_compensation_rate_mega_cps; 07116 07117 /* Enable the XTalk compensation */ 07118 if ( status == VL53L0X_ERROR_NONE ) 07119 status = vl53l0x_set_x_talk_compensation_enable( dev, 1 ); 07120 07121 /* Enable the XTalk compensation */ 07122 if ( status == VL53L0X_ERROR_NONE ) 07123 status = vl53l0x_set_x_talk_compensation_rate_mega_cps( dev, 07124 x_talk_compensation_rate_mega_cps ); 07125 07126 } 07127 07128 return status; 07129 } 07130 07131 VL53L0X_Error VL53L0X::vl53l0x_set_x_talk_compensation_rate_mega_cps( VL53L0X_DEV dev, 07132 FixPoint1616_t x_talk_compensation_rate_mega_cps ) 07133 { 07134 VL53L0X_Error status = VL53L0X_ERROR_NONE; 07135 uint8_t temp8; 07136 uint16_t linearity_corrective_gain; 07137 uint16_t data; 07138 LOG_FUNCTION_START( "" ); 07139 07140 VL53L0X_GETPARAMETERFIELD( dev, XTalkCompensationEnable, temp8 ); 07141 linearity_corrective_gain = PALDevDataGet( dev, LinearityCorrectiveGain ); 07142 07143 if ( temp8 == 0 ) { /* disabled write only internal value */ 07144 VL53L0X_SETPARAMETERFIELD( dev, XTalkCompensationRateMegaCps, 07145 x_talk_compensation_rate_mega_cps ); 07146 } else { 07147 /* the following register has a format 3.13 */ 07148 if ( linearity_corrective_gain == 1000 ) { 07149 data = VL53L0X_FIXPOINT1616TOFIXPOINT313( 07150 x_talk_compensation_rate_mega_cps ); 07151 } else { 07152 data = 0; 07153 } 07154 07155 status = vl53l0x_write_word( dev, 07156 VL53L0X_REG_CROSSTALK_COMPENSATION_PEAK_RATE_MCPS, data ); 07157 07158 if ( status == VL53L0X_ERROR_NONE ) { 07159 VL53L0X_SETPARAMETERFIELD( dev, 07160 XTalkCompensationRateMegaCps, 07161 x_talk_compensation_rate_mega_cps ); 07162 } 07163 } 07164 07165 LOG_FUNCTION_END( status ); 07166 return status; 07167 } 07168 07169 VL53L0X_Error VL53L0X::vl53l0x_perform_xtalk_measurement( VL53L0X_DEV dev, 07170 uint32_t timeout_ms, FixPoint1616_t *p_xtalk_per_spad, 07171 uint8_t *p_ambient_too_high ) 07172 { 07173 VL53L0X_Error status = VL53L0X_ERROR_NOT_IMPLEMENTED; 07174 LOG_FUNCTION_START( "" ); 07175 07176 /* not implemented on VL53L0X */ 07177 07178 LOG_FUNCTION_END( status ); 07179 return status; 07180 } 07181 07182 VL53L0X_Error VL53L0X::vl53l0x_reset_device( VL53L0X_DEV dev ) 07183 { 07184 VL53L0X_Error status = VL53L0X_ERROR_NONE; 07185 uint8_t byte; 07186 LOG_FUNCTION_START( "" ); 07187 07188 /* Set reset bit */ 07189 status = vl53l0x_write_byte( dev, VL53L0X_REG_SOFT_RESET_GO2_SOFT_RESET_N, 07190 0x00 ); 07191 07192 /* Wait for some time */ 07193 if ( status == VL53L0X_ERROR_NONE ) { 07194 do { 07195 status = vl53l0x_read_byte( dev, 07196 VL53L0X_REG_IDENTIFICATION_MODEL_ID, &byte ); 07197 } while ( byte != 0x00 ); 07198 } 07199 07200 vl53l0x_polling_delay( dev ); 07201 07202 /* Release reset */ 07203 status = vl53l0x_write_byte( dev, VL53L0X_REG_SOFT_RESET_GO2_SOFT_RESET_N, 07204 0x01 ); 07205 07206 /* Wait until correct boot-up of the device */ 07207 if ( status == VL53L0X_ERROR_NONE ) { 07208 do { 07209 status = vl53l0x_read_byte( dev, 07210 VL53L0X_REG_IDENTIFICATION_MODEL_ID, &byte ); 07211 } while ( byte == 0x00 ); 07212 } 07213 07214 vl53l0x_polling_delay( dev ); 07215 07216 /* Set PAL State to VL53L0X_STATE_POWERDOWN */ 07217 if ( status == VL53L0X_ERROR_NONE ) 07218 PALDevDataSet( dev, PalState, VL53L0X_STATE_POWERDOWN ); 07219 07220 07221 LOG_FUNCTION_END( status ); 07222 return status; 07223 } 07224 07225 VL53L0X_Error VL53L0X::VL53L0X_reverse_bytes( uint8_t *data, uint32_t size ) 07226 { 07227 VL53L0X_Error status = VL53L0X_ERROR_NONE; 07228 uint8_t temp_data; 07229 uint32_t mirror_index; 07230 uint32_t middle = size / 2; 07231 uint32_t index; 07232 07233 for ( index = 0; index < middle; index++ ) { 07234 mirror_index = size - index - 1; 07235 temp_data = data[index]; 07236 data[index] = data[mirror_index]; 07237 data[mirror_index] = temp_data; 07238 } 07239 return status; 07240 } 07241 07242 VL53L0X_Error VL53L0X::vl53l0x_set_ref_calibration( VL53L0X_DEV dev, 07243 uint8_t vhv_settings, uint8_t phase_cal ) 07244 { 07245 VL53L0X_Error status = VL53L0X_ERROR_NONE; 07246 uint8_t p_vhv_settings; 07247 uint8_t p_phase_cal; 07248 07249 status = vl53l0x_ref_calibration_io( dev, 0, 07250 vhv_settings, phase_cal, 07251 &p_vhv_settings, &p_phase_cal, 07252 1, 1 ); 07253 07254 return status; 07255 } 07256 07257 VL53L0X_Error VL53L0X::VL53L0X_SetDeviceParameters( VL53L0X_DEV Dev, 07258 const VL53L0X_DeviceParameters_t *pDeviceParameters ) 07259 { 07260 VL53L0X_Error Status = VL53L0X_ERROR_NONE; 07261 int i; 07262 LOG_FUNCTION_START( "" ); 07263 Status = vl53l0x_set_device_mode( Dev, pDeviceParameters->DeviceMode ); 07264 07265 if ( Status == VL53L0X_ERROR_NONE ) 07266 Status = vl53l0x_set_inter_measurement_period_milli_seconds( Dev, 07267 pDeviceParameters->InterMeasurementPeriodMilliSeconds ); 07268 07269 07270 if ( Status == VL53L0X_ERROR_NONE ) 07271 Status = vl53l0x_set_x_talk_compensation_rate_mega_cps( Dev, 07272 pDeviceParameters->XTalkCompensationRateMegaCps ); 07273 07274 07275 if ( Status == VL53L0X_ERROR_NONE ) 07276 Status = vl53l0x_set_offset_calibration_data_micro_meter( Dev, 07277 pDeviceParameters->RangeOffsetMicroMeters ); 07278 07279 07280 for ( i = 0; i < VL53L0X_CHECKENABLE_NUMBER_OF_CHECKS; i++ ) { 07281 if ( Status == VL53L0X_ERROR_NONE ) 07282 Status |= vl53l0x_set_limit_check_enable( Dev, i, 07283 pDeviceParameters->LimitChecksEnable [i] ); 07284 else 07285 break; 07286 07287 if ( Status == VL53L0X_ERROR_NONE ) 07288 Status |= vl53l0x_set_limit_check_value( Dev, i, 07289 pDeviceParameters->LimitChecksValue [i] ); 07290 else 07291 break; 07292 07293 } 07294 07295 if ( Status == VL53L0X_ERROR_NONE ) 07296 Status = vl53l0x_set_wrap_around_check_enable( Dev, 07297 pDeviceParameters->WrapAroundCheckEnable ); 07298 07299 if ( Status == VL53L0X_ERROR_NONE ) 07300 Status = vl53l0x_set_measurement_timing_budget_micro_seconds( Dev, 07301 pDeviceParameters->MeasurementTimingBudgetMicroSeconds ); 07302 07303 07304 LOG_FUNCTION_END( Status ); 07305 return Status; 07306 } 07307 07308 VL53L0X_Error VL53L0X::vl53l0x_set_inter_measurement_period_milli_seconds( VL53L0X_DEV dev, 07309 uint32_t inter_measurement_period_milli_seconds ) 07310 { 07311 VL53L0X_Error status = VL53L0X_ERROR_NONE; 07312 uint16_t osc_calibrate_val; 07313 uint32_t im_period_milli_seconds; 07314 07315 LOG_FUNCTION_START( "" ); 07316 07317 status = vl53l0x_read_word( dev, VL53L0X_REG_OSC_CALIBRATE_VAL, 07318 &osc_calibrate_val ); 07319 07320 if ( status == VL53L0X_ERROR_NONE ) { 07321 if ( osc_calibrate_val != 0 ) { 07322 im_period_milli_seconds = 07323 inter_measurement_period_milli_seconds 07324 * osc_calibrate_val; 07325 } else { 07326 im_period_milli_seconds = 07327 inter_measurement_period_milli_seconds; 07328 } 07329 status = vl53l0x_write_dword( dev, 07330 VL53L0X_REG_SYSTEM_INTERMEASUREMENT_PERIOD, 07331 im_period_milli_seconds ); 07332 } 07333 07334 if ( status == VL53L0X_ERROR_NONE ) { 07335 VL53L0X_SETPARAMETERFIELD( dev, 07336 InterMeasurementPeriodMilliSeconds, 07337 inter_measurement_period_milli_seconds ); 07338 } 07339 07340 LOG_FUNCTION_END( status ); 07341 return status; 07342 } 07343 07344 VL53L0X_Error VL53L0X::vl53l0x_set_wrap_around_check_enable( VL53L0X_DEV dev, 07345 uint8_t wrap_around_check_enable ) 07346 { 07347 VL53L0X_Error status = VL53L0X_ERROR_NONE; 07348 uint8_t data; 07349 uint8_t wrap_around_check_enable_int; 07350 07351 LOG_FUNCTION_START( "" ); 07352 07353 status = vl53l0x_read_byte( dev, VL53L0X_REG_SYSTEM_SEQUENCE_CONFIG, &data ); 07354 if ( wrap_around_check_enable == 0 ) { 07355 /* Disable wraparound */ 07356 data = data & 0x7F; 07357 wrap_around_check_enable_int = 0; 07358 } else { 07359 /*Enable wraparound */ 07360 data = data | 0x80; 07361 wrap_around_check_enable_int = 1; 07362 } 07363 07364 status = vl53l0x_write_byte( dev, VL53L0X_REG_SYSTEM_SEQUENCE_CONFIG, data ); 07365 07366 if ( status == VL53L0X_ERROR_NONE ) { 07367 PALDevDataSet( dev, SequenceConfig, data ); 07368 VL53L0X_SETPARAMETERFIELD( dev, WrapAroundCheckEnable, 07369 wrap_around_check_enable_int ); 07370 } 07371 07372 LOG_FUNCTION_END( status ); 07373 return status; 07374 } 07375 07376 VL53L0X_Error VL53L0X::vl53l0x_set_group_param_hold( VL53L0X_DEV dev, uint8_t group_param_hold ) 07377 { 07378 VL53L0X_Error status = VL53L0X_ERROR_NOT_IMPLEMENTED; 07379 LOG_FUNCTION_START( "" ); 07380 07381 /* not implemented on VL53L0X */ 07382 07383 LOG_FUNCTION_END( status ); 07384 return status; 07385 } 07386 07387 VL53L0X_Error VL53L0X::vl53l0x_set_range_fraction_enable( VL53L0X_DEV dev, uint8_t enable ) 07388 { 07389 VL53L0X_Error status = VL53L0X_ERROR_NONE; 07390 07391 LOG_FUNCTION_START( "%d", ( int )Enable ); 07392 07393 status = vl53l0x_write_byte( dev, VL53L0X_REG_SYSTEM_RANGE_CONFIG, enable ); 07394 07395 if ( status == VL53L0X_ERROR_NONE ) 07396 PALDevDataSet( dev, RangeFractionalEnable, enable ); 07397 07398 LOG_FUNCTION_END( status ); 07399 return status; 07400 } 07401 07402 VL53L0X_Error VL53L0X::vl53l0x_set_reference_spads( VL53L0X_DEV dev, uint32_t count, 07403 uint8_t is_aperture_spads ) 07404 { 07405 VL53L0X_Error status = VL53L0X_ERROR_NONE; 07406 LOG_FUNCTION_START( "" ); 07407 07408 status = wrapped_vl53l0x_set_reference_spads( dev, count, is_aperture_spads ); 07409 07410 LOG_FUNCTION_END( status ); 07411 07412 return status; 07413 } 07414 07415 VL53L0X_Error VL53L0X::vl53l0x_get_reference_spads( VL53L0X_DEV dev, uint32_t *p_spad_count, 07416 uint8_t *p_is_aperture_spads ) 07417 { 07418 VL53L0X_Error status = VL53L0X_ERROR_NONE; 07419 LOG_FUNCTION_START( "" ); 07420 07421 status = wrapped_vl53l0x_get_reference_spads( dev, p_spad_count, p_is_aperture_spads ); 07422 07423 LOG_FUNCTION_END( status ); 07424 07425 return status; 07426 } 07427 07428 VL53L0X_Error VL53L0X::wrapped_vl53l0x_wait_device_booted( VL53L0X_DEV dev ) 07429 { 07430 VL53L0X_Error status = VL53L0X_ERROR_NOT_IMPLEMENTED; 07431 LOG_FUNCTION_START( "" ); 07432 07433 /* not implemented on VL53L0X */ 07434 07435 LOG_FUNCTION_END( status ); 07436 return status; 07437 } 07438 07439 VL53L0X_Error VL53L0X::vl53l0x_wait_device_ready_for_new_measurement( VL53L0X_DEV dev, 07440 uint32_t max_loop ) 07441 { 07442 VL53L0X_Error status = VL53L0X_ERROR_NOT_IMPLEMENTED; 07443 LOG_FUNCTION_START( "" ); 07444 07445 /* not implemented for VL53L0X */ 07446 07447 LOG_FUNCTION_END( satus ); 07448 return status; 07449 } 07450 /******************************************************************************/ 07451
Generated on Wed Jul 13 2022 19:35:41 by 1.7.2