ST Expansion SW Team / VL53L3CX_mbed

Dependencies:   X_NUCLEO_COMMON ST_INTERFACES

Dependents:   VL53L3CX_NoShield_1Sensor_poll_Mb06x VL53L3_NoShield_1Sensor_polling_Mb63 X_NUCLEO_53L3A2 53L3A2_Ranging

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers vl53lx_api_calibration.c Source File

vl53lx_api_calibration.c

00001 
00002 // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
00003 /******************************************************************************
00004  * Copyright (c) 2020, STMicroelectronics - All Rights Reserved
00005 
00006  This file is part of VL53LX and is dual licensed,
00007  either GPL-2.0+
00008  or 'BSD 3-clause "New" or "Revised" License' , at your option.
00009  ******************************************************************************
00010  */
00011 
00012 
00013 
00014 
00015 
00016 #include "vl53lx_platform.h"
00017 #include "vl53lx_platform_ipp.h"
00018 #include "vl53lx_ll_def.h"
00019 #include "vl53lx_ll_device.h"
00020 #include "vl53lx_register_map.h"
00021 #include "vl53lx_register_funcs.h"
00022 #include "vl53lx_register_settings.h"
00023 #include "vl53lx_hist_map.h"
00024 #include "vl53lx_hist_structs.h"
00025 #include "vl53lx_core.h"
00026 #include "vl53lx_wait.h"
00027 #include "vl53lx_api_preset_modes.h"
00028 #include "vl53lx_silicon_core.h"
00029 #include "vl53lx_api_core.h"
00030 #include "vl53lx_api_calibration.h"
00031 
00032 #ifdef VL53LX_LOG_ENABLE
00033   #include "vl53lx_api_debug.h"
00034 #endif
00035 
00036 
00037 #define LOG_FUNCTION_START(fmt, ...) \
00038     _LOG_FUNCTION_START(VL53LX_TRACE_MODULE_CORE, fmt, ##__VA_ARGS__)
00039 #define LOG_FUNCTION_END(status, ...) \
00040     _LOG_FUNCTION_END(VL53LX_TRACE_MODULE_CORE, status, ##__VA_ARGS__)
00041 #define LOG_FUNCTION_END_FMT(status, fmt, ...) \
00042     _LOG_FUNCTION_END_FMT(VL53LX_TRACE_MODULE_CORE, status, \
00043         fmt, ##__VA_ARGS__)
00044 
00045 #define trace_print(level, ...) \
00046     _LOG_TRACE_PRINT(VL53LX_TRACE_MODULE_CORE, \
00047     level, VL53LX_TRACE_FUNCTION_NONE, ##__VA_ARGS__)
00048 
00049 
00050 VL53LX_Error VL53LX_run_ref_spad_char(
00051     VL53LX_DEV        Dev,
00052     VL53LX_Error     *pcal_status)
00053 {
00054 
00055 
00056     VL53LX_Error status = VL53LX_ERROR_NONE;
00057     VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev);
00058 
00059     uint8_t comms_buffer[6];
00060 
00061     VL53LX_refspadchar_config_t *prefspadchar  = &(pdev->refspadchar);
00062 
00063     LOG_FUNCTION_START("");
00064 
00065 
00066 
00067     if (status == VL53LX_ERROR_NONE)
00068         status = VL53LX_enable_powerforce(Dev);
00069 
00070 
00071 
00072     if (status == VL53LX_ERROR_NONE)
00073         status =
00074         VL53LX_set_ref_spad_char_config(
00075             Dev,
00076             prefspadchar->VL53LX_p_005,
00077             prefspadchar->timeout_us,
00078             prefspadchar->target_count_rate_mcps,
00079             prefspadchar->max_count_rate_limit_mcps,
00080             prefspadchar->min_count_rate_limit_mcps,
00081             pdev->stat_nvm.osc_measured__fast_osc__frequency);
00082 
00083 
00084 
00085     if (status == VL53LX_ERROR_NONE)
00086         status = VL53LX_run_device_test(
00087                     Dev,
00088                     prefspadchar->device_test_mode);
00089 
00090 
00091 
00092     if (status == VL53LX_ERROR_NONE)
00093         status =
00094         VL53LX_ReadMulti(
00095             Dev,
00096             VL53LX_REF_SPAD_CHAR_RESULT__NUM_ACTUAL_REF_SPADS,
00097             comms_buffer,
00098             2);
00099 
00100     if (status == VL53LX_ERROR_NONE) {
00101         pdev->dbg_results.ref_spad_char_result__num_actual_ref_spads =
00102                 comms_buffer[0];
00103         pdev->dbg_results.ref_spad_char_result__ref_location =
00104                 comms_buffer[1];
00105     }
00106 
00107 
00108 
00109     if (status == VL53LX_ERROR_NONE)
00110         status =
00111             VL53LX_WriteMulti(
00112                 Dev,
00113                 VL53LX_REF_SPAD_MAN__NUM_REQUESTED_REF_SPADS,
00114                 comms_buffer,
00115                 2);
00116 
00117     if (status == VL53LX_ERROR_NONE) {
00118         pdev->customer.ref_spad_man__num_requested_ref_spads =
00119                 comms_buffer[0];
00120         pdev->customer.ref_spad_man__ref_location =
00121                 comms_buffer[1];
00122     }
00123 
00124 
00125 
00126     if (status == VL53LX_ERROR_NONE)
00127         status =
00128             VL53LX_ReadMulti(
00129                 Dev,
00130                 VL53LX_RESULT__SPARE_0_SD1,
00131                 comms_buffer,
00132                 6);
00133 
00134 
00135 
00136     if (status == VL53LX_ERROR_NONE)
00137         status =
00138             VL53LX_WriteMulti(
00139                 Dev,
00140                 VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_REF_0,
00141                 comms_buffer,
00142                 6);
00143 
00144     if (status == VL53LX_ERROR_NONE) {
00145         pdev->customer.global_config__spad_enables_ref_0 =
00146                 comms_buffer[0];
00147         pdev->customer.global_config__spad_enables_ref_1 =
00148                 comms_buffer[1];
00149         pdev->customer.global_config__spad_enables_ref_2 =
00150                 comms_buffer[2];
00151         pdev->customer.global_config__spad_enables_ref_3 =
00152                 comms_buffer[3];
00153         pdev->customer.global_config__spad_enables_ref_4 =
00154                 comms_buffer[4];
00155         pdev->customer.global_config__spad_enables_ref_5 =
00156                 comms_buffer[5];
00157     }
00158 
00159 #ifdef VL53LX_LOG_ENABLE
00160 
00161     if (status == VL53LX_ERROR_NONE)
00162         VL53LX_print_customer_nvm_managed(
00163             &(pdev->customer),
00164             "run_ref_spad_char():pdev->lldata.customer.",
00165             VL53LX_TRACE_MODULE_REF_SPAD_CHAR);
00166 #endif
00167 
00168     if (status == VL53LX_ERROR_NONE) {
00169 
00170         switch (pdev->sys_results.result__range_status) {
00171 
00172         case VL53LX_DEVICEERROR_REFSPADCHARNOTENOUGHDPADS:
00173             status = VL53LX_WARNING_REF_SPAD_CHAR_NOT_ENOUGH_SPADS;
00174             break;
00175 
00176         case VL53LX_DEVICEERROR_REFSPADCHARMORETHANTARGET:
00177             status = VL53LX_WARNING_REF_SPAD_CHAR_RATE_TOO_HIGH;
00178             break;
00179 
00180         case VL53LX_DEVICEERROR_REFSPADCHARLESSTHANTARGET:
00181             status = VL53LX_WARNING_REF_SPAD_CHAR_RATE_TOO_LOW;
00182             break;
00183         }
00184     }
00185 
00186 
00187 
00188     *pcal_status = status;
00189 
00190 
00191 
00192     IGNORE_STATUS(
00193         IGNORE_REF_SPAD_CHAR_NOT_ENOUGH_SPADS,
00194         VL53LX_WARNING_REF_SPAD_CHAR_NOT_ENOUGH_SPADS,
00195         status);
00196 
00197     IGNORE_STATUS(
00198         IGNORE_REF_SPAD_CHAR_RATE_TOO_HIGH,
00199         VL53LX_WARNING_REF_SPAD_CHAR_RATE_TOO_HIGH,
00200         status);
00201 
00202     IGNORE_STATUS(
00203         IGNORE_REF_SPAD_CHAR_RATE_TOO_LOW,
00204         VL53LX_WARNING_REF_SPAD_CHAR_RATE_TOO_LOW,
00205         status);
00206 
00207 
00208     LOG_FUNCTION_END(status);
00209 
00210     return status;
00211 }
00212 
00213 
00214 VL53LX_Error VL53LX_get_and_avg_xtalk_samples(
00215         VL53LX_DEV                    Dev,
00216         uint8_t                       num_of_samples,
00217         uint8_t                       measurement_mode,
00218         int16_t                       xtalk_filter_thresh_max_mm,
00219         int16_t                       xtalk_filter_thresh_min_mm,
00220         uint16_t                      xtalk_max_valid_rate_kcps,
00221         uint8_t                       xtalk_result_id,
00222         uint8_t                       xtalk_histo_id,
00223         VL53LX_xtalk_range_results_t *pXR,
00224         VL53LX_histogram_bin_data_t  *psum_histo,
00225         VL53LX_histogram_bin_data_t  *pavg_histo)
00226 {
00227 
00228 
00229 
00230     VL53LX_Error status        = VL53LX_ERROR_NONE;
00231     VL53LX_LLDriverData_t *pdev =
00232         VL53LXDevStructGetLLDriverHandle(Dev);
00233 
00234 #ifdef VL53LX_LOG_ENABLE
00235     VL53LX_LLDriverResults_t *pres =
00236         VL53LXDevStructGetLLResultsHandle(Dev);
00237 #endif
00238 
00239     VL53LX_range_results_t      *prs =
00240             (VL53LX_range_results_t *) pdev->wArea1;
00241 
00242     VL53LX_range_data_t         *prange_data;
00243     VL53LX_xtalk_range_data_t   *pxtalk_range_data;
00244 
00245     uint8_t i                = 0;
00246     uint8_t j                = 0;
00247     uint8_t zone_id          = 0;
00248     uint8_t final_zone       = pdev->zone_cfg.active_zones+1;
00249     uint8_t valid_result;
00250 
00251     uint8_t smudge_corr_en   = 0;
00252 
00253 
00254 
00255 
00256     smudge_corr_en = pdev->smudge_correct_config.smudge_corr_enabled;
00257 
00258     status = VL53LX_dynamic_xtalk_correction_disable(Dev);
00259 
00260 
00261     VL53LX_load_patch(Dev);
00262 
00263 
00264 
00265     if (status == VL53LX_ERROR_NONE)
00266         status =
00267             VL53LX_init_and_start_range(
00268                 Dev,
00269                 measurement_mode,
00270                 VL53LX_DEVICECONFIGLEVEL_CUSTOMER_ONWARDS);
00271 
00272 
00273     for (i = 0; i <= (final_zone*num_of_samples); i++) {
00274 
00275 
00276 
00277         if (status == VL53LX_ERROR_NONE)
00278             status = VL53LX_wait_for_range_completion(Dev);
00279 
00280 
00281 
00282         if (status == VL53LX_ERROR_NONE)
00283             status =
00284                 VL53LX_get_device_results(
00285                     Dev,
00286                     VL53LX_DEVICERESULTSLEVEL_FULL,
00287                     prs);
00288 
00289 
00290 
00291         if (status == VL53LX_ERROR_NONE &&
00292             pdev->ll_state.rd_device_state !=
00293             VL53LX_DEVICESTATE_RANGING_WAIT_GPH_SYNC) {
00294 
00295             zone_id = pdev->ll_state.rd_zone_id + xtalk_result_id;
00296             prange_data       = &(prs->VL53LX_p_003[0]);
00297 
00298 
00299             if (prs->active_results > 1) {
00300                 for (j = 1;
00301                 j < prs->active_results; j++) {
00302                     if (prs->VL53LX_p_003[j].median_range_mm
00303                         <
00304                         prange_data->median_range_mm)
00305                         prange_data =
00306                         &(prs->VL53LX_p_003[j]);
00307 
00308                 }
00309             }
00310 
00311             pxtalk_range_data = &(pXR->VL53LX_p_003[zone_id]);
00312 
00313 
00314 
00315             if ((prs->active_results > 0) &&
00316                 (prange_data->median_range_mm <
00317                         xtalk_filter_thresh_max_mm) &&
00318                 (prange_data->median_range_mm >
00319                         xtalk_filter_thresh_min_mm) &&
00320                 (prange_data->VL53LX_p_009 <
00321                 (uint32_t)(xtalk_max_valid_rate_kcps * 16)))
00322                 valid_result = 1;
00323             else
00324                 valid_result = 0;
00325 
00326             if (valid_result == 1) {
00327 
00328                 pxtalk_range_data->no_of_samples++;
00329 
00330                 pxtalk_range_data->rate_per_spad_kcps_sum +=
00331                     prange_data->VL53LX_p_009;
00332 
00333                 pxtalk_range_data->signal_total_events_sum +=
00334                     prange_data->VL53LX_p_010;
00335 
00336                 pxtalk_range_data->sigma_mm_sum +=
00337                     (uint32_t)prange_data->VL53LX_p_002;
00338 
00339 
00340 
00341                 pxtalk_range_data->median_phase_sum +=
00342                     (uint32_t)prange_data->VL53LX_p_011;
00343 
00344 
00345 
00346 
00347             }
00348 
00349             if ((valid_result == 1) && (zone_id >= 4)) {
00350                 status = VL53LX_sum_histogram_data(
00351                         &(pdev->hist_data),
00352                         psum_histo);
00353 
00354 
00355 
00356                 if (prange_data->VL53LX_p_012 <
00357                     pXR->central_histogram__window_start)
00358                     pXR->central_histogram__window_start =
00359                     prange_data->VL53LX_p_012;
00360 
00361 
00362                 if (prange_data->VL53LX_p_013 >
00363                     pXR->central_histogram__window_end)
00364                     pXR->central_histogram__window_end =
00365                         prange_data->VL53LX_p_013;
00366 
00367             }
00368 
00369         }
00370 
00371 
00372 
00373 #ifdef VL53LX_LOG_ENABLE
00374         if (status == VL53LX_ERROR_NONE) {
00375             VL53LX_print_range_results(
00376                     &(pres->range_results),
00377                     "pres->range_results.",
00378                     VL53LX_TRACE_MODULE_CORE);
00379         }
00380 #endif
00381 
00382 
00383 
00384         if (status == VL53LX_ERROR_NONE)
00385             status = VL53LX_wait_for_firmware_ready(Dev);
00386 
00387 
00388 
00389         if (status == VL53LX_ERROR_NONE)
00390             status =
00391                 VL53LX_clear_interrupt_and_enable_next_range(
00392                     Dev,
00393                     measurement_mode);
00394 
00395 
00396     }
00397 
00398 
00399 
00400 
00401     if (status == VL53LX_ERROR_NONE)
00402         status = VL53LX_stop_range(Dev);
00403 
00404     VL53LX_unload_patch(Dev);
00405 
00406 
00407 
00408     for (i = 0; i < (pdev->zone_cfg.active_zones+1); i++) {
00409 
00410         pxtalk_range_data = &(pXR->VL53LX_p_003[i+xtalk_result_id]);
00411 
00412         if (pxtalk_range_data->no_of_samples > 0) {
00413             pxtalk_range_data->rate_per_spad_kcps_avg =
00414             pxtalk_range_data->rate_per_spad_kcps_sum /
00415             (uint32_t)pxtalk_range_data->no_of_samples;
00416 
00417             pxtalk_range_data->signal_total_events_avg =
00418             pxtalk_range_data->signal_total_events_sum /
00419             (int32_t)pxtalk_range_data->no_of_samples;
00420 
00421             pxtalk_range_data->sigma_mm_avg =
00422             pxtalk_range_data->sigma_mm_sum /
00423             (uint32_t)pxtalk_range_data->no_of_samples;
00424 
00425 
00426 
00427             pxtalk_range_data->median_phase_avg =
00428                 pxtalk_range_data->median_phase_sum /
00429                 (uint32_t)pxtalk_range_data->no_of_samples;
00430 
00431 
00432 
00433         } else {
00434             pxtalk_range_data->rate_per_spad_kcps_avg =
00435                 pxtalk_range_data->rate_per_spad_kcps_sum;
00436             pxtalk_range_data->signal_total_events_avg =
00437                 pxtalk_range_data->signal_total_events_sum;
00438             pxtalk_range_data->sigma_mm_avg =
00439                 pxtalk_range_data->sigma_mm_sum;
00440 
00441 
00442 
00443             pxtalk_range_data->median_phase_avg =
00444                     pxtalk_range_data->median_phase_sum;
00445 
00446 
00447         }
00448     }
00449 
00450 
00451 
00452     memcpy(pavg_histo, &(pdev->hist_data),
00453             sizeof(VL53LX_histogram_bin_data_t));
00454 
00455 
00456 
00457     if (status == VL53LX_ERROR_NONE) {
00458 
00459         pxtalk_range_data = &(pXR->VL53LX_p_003[xtalk_histo_id]);
00460 
00461         status = VL53LX_avg_histogram_data(
00462             pxtalk_range_data->no_of_samples,
00463             psum_histo,
00464             pavg_histo);
00465     }
00466 
00467 
00468 
00469 
00470     if (status == VL53LX_ERROR_NONE) {
00471         if (smudge_corr_en == 1)
00472             status = VL53LX_dynamic_xtalk_correction_enable(Dev);
00473     }
00474 
00475 
00476     LOG_FUNCTION_END(status);
00477 
00478     return status;
00479 
00480 }
00481 
00482 
00483 VL53LX_Error VL53LX_run_phasecal_average(
00484     VL53LX_DEV              Dev,
00485     uint8_t                 measurement_mode,
00486     uint8_t                 phasecal_result__vcsel_start,
00487     uint16_t                phasecal_num_of_samples,
00488     VL53LX_range_results_t *prange_results,
00489     uint16_t               *pphasecal_result__reference_phase,
00490     uint16_t               *pzero_distance_phase)
00491 {
00492 
00493 
00494     VL53LX_Error status        = VL53LX_ERROR_NONE;
00495     VL53LX_LLDriverData_t *pdev =
00496         VL53LXDevStructGetLLDriverHandle(Dev);
00497 
00498     uint16_t  i                                = 0;
00499     uint16_t  m                                = 0;
00500     uint32_t  samples                          = 0;
00501 
00502     uint32_t  period                           = 0;
00503     uint32_t  VL53LX_p_014                            = 0;
00504     uint32_t  phasecal_result__reference_phase = 0;
00505     uint32_t  zero_distance_phase              = 0;
00506 
00507 
00508     VL53LX_load_patch(Dev);
00509 
00510     for (m = 0; m < phasecal_num_of_samples; m++) {
00511 
00512 
00513 
00514         if (status == VL53LX_ERROR_NONE)
00515             status =
00516             VL53LX_init_and_start_range(
00517                 Dev,
00518                 measurement_mode,
00519                 VL53LX_DEVICECONFIGLEVEL_CUSTOMER_ONWARDS);
00520 
00521         for (i = 0; i <= 1; i++) {
00522 
00523 
00524 
00525             if (status == VL53LX_ERROR_NONE)
00526                 status =
00527                     VL53LX_wait_for_range_completion(Dev);
00528 
00529 
00530 
00531             if (status == VL53LX_ERROR_NONE)
00532                 status =
00533                     VL53LX_get_device_results(
00534                         Dev,
00535                         VL53LX_DEVICERESULTSLEVEL_FULL,
00536                         prange_results);
00537 
00538 
00539 
00540             if (status == VL53LX_ERROR_NONE)
00541                 status =
00542                     VL53LX_wait_for_firmware_ready(Dev);
00543 
00544 
00545 
00546             if (status == VL53LX_ERROR_NONE)
00547                 status =
00548                 VL53LX_clear_interrupt_and_enable_next_range(
00549                     Dev,
00550                     measurement_mode);
00551         }
00552 
00553 
00554 
00555         if (status == VL53LX_ERROR_NONE)
00556             status = VL53LX_stop_range(Dev);
00557 
00558 
00559 
00560         if (status == VL53LX_ERROR_NONE)
00561             status = VL53LX_WaitUs(Dev, 1000);
00562 
00563 
00564 
00565         if (status == VL53LX_ERROR_NONE) {
00566 
00567             samples++;
00568 
00569 
00570             period = 2048 *
00571                 (uint32_t)VL53LX_decode_vcsel_period(
00572                     pdev->hist_data.VL53LX_p_005);
00573 
00574             VL53LX_p_014  = period;
00575             VL53LX_p_014 += (uint32_t)(
00576             pdev->hist_data.phasecal_result__reference_phase);
00577             VL53LX_p_014 +=
00578                 (2048 *
00579                 (uint32_t)phasecal_result__vcsel_start);
00580             VL53LX_p_014 -= (2048 *
00581             (uint32_t)pdev->hist_data.cal_config__vcsel_start);
00582 
00583             VL53LX_p_014  = VL53LX_p_014 % period;
00584 
00585             phasecal_result__reference_phase += (uint32_t)(
00586             pdev->hist_data.phasecal_result__reference_phase);
00587 
00588             zero_distance_phase += (uint32_t)VL53LX_p_014;
00589         }
00590     }
00591     VL53LX_unload_patch(Dev);
00592 
00593 
00594 
00595     if (status == VL53LX_ERROR_NONE && samples > 0) {
00596 
00597         phasecal_result__reference_phase += (samples >> 1);
00598         phasecal_result__reference_phase /= samples;
00599 
00600         zero_distance_phase += (samples >> 1);
00601         zero_distance_phase /= samples;
00602 
00603         *pphasecal_result__reference_phase =
00604             (uint16_t)phasecal_result__reference_phase;
00605         *pzero_distance_phase =
00606             (uint16_t)zero_distance_phase;
00607     }
00608 
00609     return status;
00610 }
00611 
00612 
00613 VL53LX_Error VL53LX_run_device_test(
00614     VL53LX_DEV             Dev,
00615     VL53LX_DeviceTestMode  device_test_mode)
00616 {
00617 
00618 
00619     VL53LX_Error status = VL53LX_ERROR_NONE;
00620     VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev);
00621 
00622     uint8_t      comms_buffer[2];
00623     uint8_t      gpio_hv_mux__ctrl = 0;
00624 
00625     LOG_FUNCTION_START("");
00626 
00627 
00628 
00629     if (status == VL53LX_ERROR_NONE)
00630         status =
00631             VL53LX_RdByte(
00632                 Dev,
00633                 VL53LX_GPIO_HV_MUX__CTRL,
00634                 &gpio_hv_mux__ctrl);
00635 
00636     if (status == VL53LX_ERROR_NONE)
00637         pdev->stat_cfg.gpio_hv_mux__ctrl = gpio_hv_mux__ctrl;
00638 
00639 
00640     if (status == VL53LX_ERROR_NONE)
00641         status = VL53LX_start_test(
00642                     Dev,
00643                     device_test_mode);
00644 
00645 
00646     if (status == VL53LX_ERROR_NONE)
00647         status = VL53LX_wait_for_test_completion(Dev);
00648 
00649 
00650     if (status == VL53LX_ERROR_NONE)
00651         status =
00652             VL53LX_ReadMulti(
00653                 Dev,
00654                 VL53LX_RESULT__RANGE_STATUS,
00655                 comms_buffer,
00656                 2);
00657 
00658     if (status == VL53LX_ERROR_NONE) {
00659         pdev->sys_results.result__range_status  = comms_buffer[0];
00660         pdev->sys_results.result__report_status = comms_buffer[1];
00661     }
00662 
00663 
00664 
00665     pdev->sys_results.result__range_status &=
00666         VL53LX_RANGE_STATUS__RANGE_STATUS_MASK;
00667 
00668     if (status == VL53LX_ERROR_NONE) {
00669         trace_print(
00670         VL53LX_TRACE_LEVEL_INFO,
00671         "    Device Test Complete:\n\t%-32s = %3u\n\t%-32s = %3u\n",
00672         "result__range_status",
00673         pdev->sys_results.result__range_status,
00674         "result__report_status",
00675         pdev->sys_results.result__report_status);
00676 
00677 
00678         if (status == VL53LX_ERROR_NONE)
00679             status = VL53LX_clear_interrupt(Dev);
00680     }
00681 
00682 
00683 
00684     if (status == VL53LX_ERROR_NONE)
00685         status =
00686             VL53LX_start_test(
00687                 Dev,
00688                 0x00);
00689 
00690     LOG_FUNCTION_END(status);
00691 
00692     return status;
00693 }
00694 
00695 
00696 void VL53LX_hist_xtalk_extract_data_init(
00697     VL53LX_hist_xtalk_extract_data_t *pxtalk_data)
00698 {
00699 
00700 
00701     int32_t lb = 0;
00702 
00703     pxtalk_data->sample_count             = 0U;
00704     pxtalk_data->pll_period_mm            = 0U;
00705     pxtalk_data->peak_duration_us_sum     = 0U;
00706     pxtalk_data->effective_spad_count_sum = 0U;
00707     pxtalk_data->zero_distance_phase_sum  = 0U;
00708     pxtalk_data->zero_distance_phase_avg  = 0U;
00709     pxtalk_data->event_scaler_sum         = 0U;
00710     pxtalk_data->event_scaler_avg         = 4096U;
00711     pxtalk_data->signal_events_sum        = 0;
00712     pxtalk_data->xtalk_rate_kcps_per_spad = 0U;
00713     pxtalk_data->VL53LX_p_012             = 0U;
00714     pxtalk_data->VL53LX_p_013               = 0U;
00715     pxtalk_data->target_start             = 0U;
00716 
00717     for (lb = 0; lb < VL53LX_XTALK_HISTO_BINS; lb++)
00718         pxtalk_data->bin_data_sums[lb] = 0;
00719 
00720 }
00721 
00722 
00723 VL53LX_Error VL53LX_hist_xtalk_extract_update(
00724     int16_t                             target_distance_mm,
00725     uint16_t                            target_width_oversize,
00726     VL53LX_histogram_bin_data_t        *phist_bins,
00727     VL53LX_hist_xtalk_extract_data_t   *pxtalk_data)
00728 {
00729 
00730 
00731     VL53LX_Error  status = VL53LX_ERROR_NONE;
00732 
00733     LOG_FUNCTION_START("");
00734 
00735     status =
00736         VL53LX_hist_xtalk_extract_calc_window(
00737             target_distance_mm,
00738             target_width_oversize,
00739             phist_bins,
00740             pxtalk_data);
00741 
00742     if (status == VL53LX_ERROR_NONE) {
00743         status =
00744             VL53LX_hist_xtalk_extract_calc_event_sums(
00745                 phist_bins,
00746                 pxtalk_data);
00747     }
00748 
00749     LOG_FUNCTION_END(status);
00750 
00751     return status;
00752 }
00753 
00754 
00755 VL53LX_Error VL53LX_hist_xtalk_extract_fini(
00756     VL53LX_histogram_bin_data_t        *phist_bins,
00757     VL53LX_hist_xtalk_extract_data_t   *pxtalk_data,
00758     VL53LX_xtalk_calibration_results_t *pxtalk_cal,
00759     VL53LX_xtalk_histogram_shape_t     *pxtalk_shape)
00760 {
00761 
00762 
00763     VL53LX_Error  status = VL53LX_ERROR_NONE;
00764     VL53LX_xtalk_calibration_results_t *pX = pxtalk_cal;
00765 
00766     LOG_FUNCTION_START("");
00767 
00768     if (pxtalk_data->sample_count > 0) {
00769 
00770 
00771         pxtalk_data->event_scaler_avg  = pxtalk_data->event_scaler_sum;
00772         pxtalk_data->event_scaler_avg +=
00773                 (pxtalk_data->sample_count >> 1);
00774         pxtalk_data->event_scaler_avg /=  pxtalk_data->sample_count;
00775 
00776 
00777 
00778         status =
00779             VL53LX_hist_xtalk_extract_calc_rate_per_spad(
00780                 pxtalk_data);
00781 
00782 
00783 
00784         if (status == VL53LX_ERROR_NONE) {
00785 
00786 
00787             pxtalk_data->zero_distance_phase_avg =
00788                 pxtalk_data->zero_distance_phase_sum;
00789             pxtalk_data->zero_distance_phase_avg +=
00790                     (pxtalk_data->sample_count >> 1);
00791             pxtalk_data->zero_distance_phase_avg /=
00792                     pxtalk_data->sample_count;
00793 
00794 
00795             status =
00796                 VL53LX_hist_xtalk_extract_calc_shape(
00797                     pxtalk_data,
00798                     pxtalk_shape);
00799 
00800 
00801 
00802 
00803             pxtalk_shape->phasecal_result__vcsel_start =
00804                 phist_bins->phasecal_result__vcsel_start;
00805             pxtalk_shape->cal_config__vcsel_start =
00806                 phist_bins->cal_config__vcsel_start;
00807             pxtalk_shape->vcsel_width =
00808                 phist_bins->vcsel_width;
00809             pxtalk_shape->VL53LX_p_015 =
00810                 phist_bins->VL53LX_p_015;
00811         }
00812 
00813 
00814         if (status == VL53LX_ERROR_NONE) {
00815 
00816 
00817             pX->algo__crosstalk_compensation_plane_offset_kcps =
00818                 pxtalk_data->xtalk_rate_kcps_per_spad;
00819             pX->algo__crosstalk_compensation_x_plane_gradient_kcps
00820                 = 0U;
00821             pX->algo__crosstalk_compensation_y_plane_gradient_kcps
00822                 = 0U;
00823 
00824         }
00825     }
00826 
00827     LOG_FUNCTION_END(status);
00828 
00829     return status;
00830 }
00831 
00832 
00833 VL53LX_Error   VL53LX_run_hist_xtalk_extraction(
00834     VL53LX_DEV                          Dev,
00835     int16_t                             cal_distance_mm,
00836     VL53LX_Error                       *pcal_status)
00837 {
00838 
00839 
00840     #define OVERSIZE 4
00841     VL53LX_Error status = VL53LX_ERROR_NONE;
00842     VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev);
00843     VL53LX_xtalkextract_config_t *pX = &(pdev->xtalk_extract_cfg);
00844     VL53LX_xtalk_config_t *pC = &(pdev->xtalk_cfg);
00845     VL53LX_xtalk_calibration_results_t *pXC = &(pdev->xtalk_cal);
00846 
00847 
00848 
00849     uint8_t smudge_corr_en   = 0;
00850     uint8_t i                = 0;
00851     int8_t k = 0;
00852     uint8_t nbloops;
00853     int32_t initMergeSize = 0;
00854     int32_t MergeEnabled = 0;
00855     uint32_t deltaXtalk;
00856     uint32_t stepXtalk;
00857     uint32_t XtalkMin;
00858     uint32_t XtalkMax;
00859     uint8_t measurement_mode = VL53LX_DEVICEMEASUREMENTMODE_BACKTOBACK;
00860     int8_t MaxId;
00861     uint8_t histo_merge_nb;
00862     uint8_t wait_for_accumulation;
00863     VL53LX_range_results_t     *prange_results =
00864         (VL53LX_range_results_t *) pdev->wArea1;
00865     uint8_t Very1stRange = 0;
00866 
00867     LOG_FUNCTION_START("");
00868 
00869 
00870 
00871     if (status == VL53LX_ERROR_NONE)
00872         status =
00873             VL53LX_set_preset_mode(
00874                 Dev,
00875                 VL53LX_DEVICEPRESETMODE_HISTOGRAM_LONG_RANGE,
00876                 pX->dss_config__target_total_rate_mcps,
00877                 pX->phasecal_config_timeout_us,
00878                 pX->mm_config_timeout_us,
00879                 pX->range_config_timeout_us,
00880                 100);
00881 
00882 
00883 
00884     if (status == VL53LX_ERROR_NONE)
00885         status = VL53LX_disable_xtalk_compensation(Dev);
00886 
00887 
00888 
00889     smudge_corr_en = pdev->smudge_correct_config.smudge_corr_enabled;
00890 
00891     if (status == VL53LX_ERROR_NONE)
00892         status = VL53LX_dynamic_xtalk_correction_disable(Dev);
00893 
00894 
00895     VL53LX_load_patch(Dev);
00896 
00897     VL53LX_get_tuning_parm(Dev, VL53LX_TUNINGPARM_HIST_MERGE_MAX_SIZE,
00898             &initMergeSize);
00899     VL53LX_get_tuning_parm(Dev, VL53LX_TUNINGPARM_HIST_MERGE,
00900             &MergeEnabled);
00901     memset(&pdev->xtalk_cal, 0, sizeof(pdev->xtalk_cal));
00902 
00903     if (status == VL53LX_ERROR_NONE)
00904         status = VL53LX_init_and_start_range(
00905             Dev, measurement_mode,
00906             VL53LX_DEVICECONFIGLEVEL_CUSTOMER_ONWARDS);
00907 
00908     MaxId = pdev->tuning_parms.tp_hist_merge_max_size - 1;
00909     nbloops = (MergeEnabled == 0 ? 1 : 2);
00910     for (k = 0; k < nbloops; k++) {
00911 
00912         VL53LX_hist_xtalk_extract_data_init(
00913                 &(pdev->xtalk_extract));
00914         VL53LX_set_tuning_parm(Dev,
00915                 VL53LX_TUNINGPARM_HIST_MERGE_MAX_SIZE,
00916                 k * MaxId + 1);
00917 
00918         for (i = 0; i <= pX->num_of_samples; i++) {
00919             if (status == VL53LX_ERROR_NONE)
00920                 status = VL53LX_wait_for_range_completion(Dev);
00921             if (status == VL53LX_ERROR_NONE)
00922                 status = VL53LX_get_device_results(Dev,
00923                     VL53LX_DEVICERESULTSLEVEL_FULL,
00924                     prange_results);
00925             Very1stRange =
00926                 (pdev->ll_state.rd_device_state ==
00927                 VL53LX_DEVICESTATE_RANGING_WAIT_GPH_SYNC);
00928 
00929             VL53LX_compute_histo_merge_nb(Dev, &histo_merge_nb);
00930             wait_for_accumulation = ((k != 0) &&
00931                 (MergeEnabled) &&
00932                 (status == VL53LX_ERROR_NONE) &&
00933                 (histo_merge_nb <
00934                 pdev->tuning_parms.tp_hist_merge_max_size));
00935             if (wait_for_accumulation)
00936                 i = 0;
00937             else {
00938                 if ((status == VL53LX_ERROR_NONE) &&
00939                     (!Very1stRange)) {
00940                     status =
00941                     VL53LX_hist_xtalk_extract_update(
00942                         cal_distance_mm,
00943                         OVERSIZE,
00944                         &(pdev->hist_data),
00945                         &(pdev->xtalk_extract));
00946                 }
00947             }
00948 
00949             if (status == VL53LX_ERROR_NONE)
00950                 status = VL53LX_wait_for_firmware_ready(Dev);
00951             if (status == VL53LX_ERROR_NONE)
00952                 status =
00953                 VL53LX_clear_interrupt_and_enable_next_range(
00954                     Dev, measurement_mode);
00955 
00956 
00957             if (status == VL53LX_ERROR_NONE)
00958                 status =
00959                 VL53LX_hist_xtalk_extract_fini(
00960                     &(pdev->hist_data),
00961                     &(pdev->xtalk_extract),
00962                     &(pdev->xtalk_cal),
00963                     &(pdev->xtalk_shapes.xtalk_shape));
00964             if (status != VL53LX_ERROR_NONE)
00965                 goto LOOPOUT;
00966             pXC->algo__xtalk_cpo_HistoMerge_kcps[k * MaxId] =
00967             pXC->algo__crosstalk_compensation_plane_offset_kcps;
00968         }
00969     }
00970 
00971 LOOPOUT:
00972 
00973     VL53LX_stop_range(Dev);
00974 
00975     VL53LX_set_tuning_parm(Dev, VL53LX_TUNINGPARM_HIST_MERGE_MAX_SIZE,
00976             initMergeSize);
00977     VL53LX_unload_patch(Dev);
00978 
00979     if (status != VL53LX_ERROR_NONE)
00980         status = VL53LX_ERROR_XTALK_EXTRACTION_SIGMA_LIMIT_FAIL;
00981     else if ((MergeEnabled == 1) && (MaxId > 0)) {
00982         XtalkMin = pdev->xtalk_cal.algo__xtalk_cpo_HistoMerge_kcps[0];
00983         XtalkMax =
00984         pdev->xtalk_cal.algo__xtalk_cpo_HistoMerge_kcps[MaxId];
00985         pdev->xtalk_cal.
00986         algo__crosstalk_compensation_plane_offset_kcps = XtalkMin;
00987         if (XtalkMax > XtalkMin) {
00988             deltaXtalk =  XtalkMax - XtalkMin;
00989             stepXtalk = deltaXtalk / MaxId;
00990             for (k = 1; k < MaxId; k++)
00991             pdev->xtalk_cal.algo__xtalk_cpo_HistoMerge_kcps[k] =
00992                 XtalkMin + stepXtalk * k;
00993         } else
00994             status =
00995                 VL53LX_ERROR_XTALK_EXTRACTION_SIGMA_LIMIT_FAIL;
00996     }
00997 
00998     if (status == VL53LX_ERROR_NONE) {
00999         pC->algo__crosstalk_compensation_x_plane_gradient_kcps =
01000         pXC->algo__crosstalk_compensation_x_plane_gradient_kcps;
01001         pC->algo__crosstalk_compensation_y_plane_gradient_kcps =
01002         pXC->algo__crosstalk_compensation_y_plane_gradient_kcps;
01003         pC->algo__crosstalk_compensation_plane_offset_kcps =
01004         pXC->algo__crosstalk_compensation_plane_offset_kcps;
01005     }
01006 
01007 
01008     pdev->xtalk_results.cal_status = status;
01009     *pcal_status = pdev->xtalk_results.cal_status;
01010 
01011 
01012     status = VL53LX_enable_xtalk_compensation(Dev);
01013     if (smudge_corr_en == 1)
01014         status = VL53LX_dynamic_xtalk_correction_enable(Dev);
01015 
01016 #ifdef VL53LX_LOG_ENABLE
01017 
01018 
01019 
01020     VL53LX_print_customer_nvm_managed(
01021         &(pdev->customer),
01022         "run_xtalk_extraction():pdev->lldata.customer.",
01023         VL53LX_TRACE_MODULE_XTALK_DATA);
01024 
01025     VL53LX_print_xtalk_config(
01026         &(pdev->xtalk_cfg),
01027         "run_xtalk_extraction():pdev->lldata.xtalk_cfg.",
01028         VL53LX_TRACE_MODULE_XTALK_DATA);
01029 
01030     VL53LX_print_xtalk_histogram_data(
01031         &(pdev->xtalk_shapes),
01032         "pdev->lldata.xtalk_shapes.",
01033         VL53LX_TRACE_MODULE_XTALK_DATA);
01034 
01035 #endif
01036 
01037     LOG_FUNCTION_END(status);
01038 
01039     return status;
01040 }
01041