/** ****************************************************************************** * Copyright (c) 2020, STMicroelectronics - All Rights Reserved * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ #include "vl53lx_platform.h" #include "vl53lx_platform_ipp.h" #include "vl53lx_ll_def.h" #include "vl53lx_ll_device.h" #include "vl53lx_register_map.h" #include "vl53lx_register_funcs.h" #include "vl53lx_register_settings.h" #include "vl53lx_hist_map.h" #include "vl53lx_hist_structs.h" #include "vl53lx_core.h" #include "vl53lx_wait.h" #include "vl53lx_api_preset_modes.h" #include "vl53lx_silicon_core.h" #include "vl53lx_api_core.h" #include "vl53lx_api_calibration.h" #ifdef VL53LX_LOG_ENABLE #include "vl53lx_api_debug.h" #endif #define LOG_FUNCTION_START(fmt, ...) \ _LOG_FUNCTION_START(VL53LX_TRACE_MODULE_CORE, fmt, ##__VA_ARGS__) #define LOG_FUNCTION_END(status, ...) \ _LOG_FUNCTION_END(VL53LX_TRACE_MODULE_CORE, status, ##__VA_ARGS__) #define LOG_FUNCTION_END_FMT(status, fmt, ...) \ _LOG_FUNCTION_END_FMT(VL53LX_TRACE_MODULE_CORE, status, \ fmt, ##__VA_ARGS__) #define trace_print(level, ...) \ _LOG_TRACE_PRINT(VL53LX_TRACE_MODULE_CORE, \ level, VL53LX_TRACE_FUNCTION_NONE, ##__VA_ARGS__) VL53LX_Error VL53LX_run_ref_spad_char( VL53LX_DEV Dev, VL53LX_Error *pcal_status) { VL53LX_Error status = VL53LX_ERROR_NONE; VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); uint8_t comms_buffer[6]; VL53LX_refspadchar_config_t *prefspadchar = &(pdev->refspadchar); LOG_FUNCTION_START(""); if (status == VL53LX_ERROR_NONE) status = VL53LX_enable_powerforce(Dev); if (status == VL53LX_ERROR_NONE) status = VL53LX_set_ref_spad_char_config( Dev, prefspadchar->VL53LX_p_005, prefspadchar->timeout_us, prefspadchar->target_count_rate_mcps, prefspadchar->max_count_rate_limit_mcps, prefspadchar->min_count_rate_limit_mcps, pdev->stat_nvm.osc_measured__fast_osc__frequency); if (status == VL53LX_ERROR_NONE) status = VL53LX_run_device_test( Dev, prefspadchar->device_test_mode); if (status == VL53LX_ERROR_NONE) status = VL53LX_ReadMulti( Dev, VL53LX_REF_SPAD_CHAR_RESULT__NUM_ACTUAL_REF_SPADS, comms_buffer, 2); if (status == VL53LX_ERROR_NONE) { pdev->dbg_results.ref_spad_char_result__num_actual_ref_spads = comms_buffer[0]; pdev->dbg_results.ref_spad_char_result__ref_location = comms_buffer[1]; } if (status == VL53LX_ERROR_NONE) status = VL53LX_WriteMulti( Dev, VL53LX_REF_SPAD_MAN__NUM_REQUESTED_REF_SPADS, comms_buffer, 2); if (status == VL53LX_ERROR_NONE) { pdev->customer.ref_spad_man__num_requested_ref_spads = comms_buffer[0]; pdev->customer.ref_spad_man__ref_location = comms_buffer[1]; } if (status == VL53LX_ERROR_NONE) status = VL53LX_ReadMulti( Dev, VL53LX_RESULT__SPARE_0_SD1, comms_buffer, 6); if (status == VL53LX_ERROR_NONE) status = VL53LX_WriteMulti( Dev, VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_REF_0, comms_buffer, 6); if (status == VL53LX_ERROR_NONE) { pdev->customer.global_config__spad_enables_ref_0 = comms_buffer[0]; pdev->customer.global_config__spad_enables_ref_1 = comms_buffer[1]; pdev->customer.global_config__spad_enables_ref_2 = comms_buffer[2]; pdev->customer.global_config__spad_enables_ref_3 = comms_buffer[3]; pdev->customer.global_config__spad_enables_ref_4 = comms_buffer[4]; pdev->customer.global_config__spad_enables_ref_5 = comms_buffer[5]; } #ifdef VL53LX_LOG_ENABLE if (status == VL53LX_ERROR_NONE) VL53LX_print_customer_nvm_managed( &(pdev->customer), "run_ref_spad_char():pdev->lldata.customer.", VL53LX_TRACE_MODULE_REF_SPAD_CHAR); #endif if (status == VL53LX_ERROR_NONE) { switch (pdev->sys_results.result__range_status) { case VL53LX_DEVICEERROR_REFSPADCHARNOTENOUGHDPADS: status = VL53LX_WARNING_REF_SPAD_CHAR_NOT_ENOUGH_SPADS; break; case VL53LX_DEVICEERROR_REFSPADCHARMORETHANTARGET: status = VL53LX_WARNING_REF_SPAD_CHAR_RATE_TOO_HIGH; break; case VL53LX_DEVICEERROR_REFSPADCHARLESSTHANTARGET: status = VL53LX_WARNING_REF_SPAD_CHAR_RATE_TOO_LOW; break; } } *pcal_status = status; IGNORE_STATUS( IGNORE_REF_SPAD_CHAR_NOT_ENOUGH_SPADS, VL53LX_WARNING_REF_SPAD_CHAR_NOT_ENOUGH_SPADS, status); IGNORE_STATUS( IGNORE_REF_SPAD_CHAR_RATE_TOO_HIGH, VL53LX_WARNING_REF_SPAD_CHAR_RATE_TOO_HIGH, status); IGNORE_STATUS( IGNORE_REF_SPAD_CHAR_RATE_TOO_LOW, VL53LX_WARNING_REF_SPAD_CHAR_RATE_TOO_LOW, status); LOG_FUNCTION_END(status); return status; } VL53LX_Error VL53LX_get_and_avg_xtalk_samples( VL53LX_DEV Dev, uint8_t num_of_samples, uint8_t measurement_mode, int16_t xtalk_filter_thresh_max_mm, int16_t xtalk_filter_thresh_min_mm, uint16_t xtalk_max_valid_rate_kcps, uint8_t xtalk_result_id, uint8_t xtalk_histo_id, VL53LX_xtalk_range_results_t *pXR, VL53LX_histogram_bin_data_t *psum_histo, VL53LX_histogram_bin_data_t *pavg_histo) { VL53LX_Error status = VL53LX_ERROR_NONE; VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); #ifdef VL53LX_LOG_ENABLE VL53LX_LLDriverResults_t *pres = VL53LXDevStructGetLLResultsHandle(Dev); #endif VL53LX_range_results_t *prs = (VL53LX_range_results_t *) pdev->wArea1; VL53LX_range_data_t *prange_data; VL53LX_xtalk_range_data_t *pxtalk_range_data; uint8_t i = 0; uint8_t j = 0; uint8_t zone_id = 0; uint8_t final_zone = pdev->zone_cfg.active_zones+1; uint8_t valid_result; uint8_t smudge_corr_en = 0; smudge_corr_en = pdev->smudge_correct_config.smudge_corr_enabled; status = VL53LX_dynamic_xtalk_correction_disable(Dev); VL53LX_load_patch(Dev); if (status == VL53LX_ERROR_NONE) status = VL53LX_init_and_start_range( Dev, measurement_mode, VL53LX_DEVICECONFIGLEVEL_CUSTOMER_ONWARDS); for (i = 0; i <= (final_zone*num_of_samples); i++) { if (status == VL53LX_ERROR_NONE) status = VL53LX_wait_for_range_completion(Dev); if (status == VL53LX_ERROR_NONE) status = VL53LX_get_device_results( Dev, VL53LX_DEVICERESULTSLEVEL_FULL, prs); if (status == VL53LX_ERROR_NONE && pdev->ll_state.rd_device_state != VL53LX_DEVICESTATE_RANGING_WAIT_GPH_SYNC) { zone_id = pdev->ll_state.rd_zone_id + xtalk_result_id; prange_data = &(prs->VL53LX_p_003[0]); if (prs->active_results > 1) { for (j = 1; j < prs->active_results; j++) { if (prs->VL53LX_p_003[j].median_range_mm < prange_data->median_range_mm) prange_data = &(prs->VL53LX_p_003[j]); } } pxtalk_range_data = &(pXR->VL53LX_p_003[zone_id]); if ((prs->active_results > 0) && (prange_data->median_range_mm < xtalk_filter_thresh_max_mm) && (prange_data->median_range_mm > xtalk_filter_thresh_min_mm) && (prange_data->VL53LX_p_009 < (uint32_t)(xtalk_max_valid_rate_kcps * 16))) valid_result = 1; else valid_result = 0; if (valid_result == 1) { pxtalk_range_data->no_of_samples++; pxtalk_range_data->rate_per_spad_kcps_sum += prange_data->VL53LX_p_009; pxtalk_range_data->signal_total_events_sum += prange_data->VL53LX_p_010; pxtalk_range_data->sigma_mm_sum += (uint32_t)prange_data->VL53LX_p_002; pxtalk_range_data->median_phase_sum += (uint32_t)prange_data->VL53LX_p_011; } if ((valid_result == 1) && (zone_id >= 4)) { status = VL53LX_sum_histogram_data( &(pdev->hist_data), psum_histo); if (prange_data->VL53LX_p_012 < pXR->central_histogram__window_start) pXR->central_histogram__window_start = prange_data->VL53LX_p_012; if (prange_data->VL53LX_p_013 > pXR->central_histogram__window_end) pXR->central_histogram__window_end = prange_data->VL53LX_p_013; } } #ifdef VL53LX_LOG_ENABLE if (status == VL53LX_ERROR_NONE) { VL53LX_print_range_results( &(pres->range_results), "pres->range_results.", VL53LX_TRACE_MODULE_CORE); } #endif if (status == VL53LX_ERROR_NONE) status = VL53LX_clear_interrupt_and_enable_next_range( Dev, measurement_mode); } if (status == VL53LX_ERROR_NONE) status = VL53LX_stop_range(Dev); VL53LX_unload_patch(Dev); for (i = 0; i < (pdev->zone_cfg.active_zones+1); i++) { pxtalk_range_data = &(pXR->VL53LX_p_003[i+xtalk_result_id]); if (pxtalk_range_data->no_of_samples > 0) { pxtalk_range_data->rate_per_spad_kcps_avg = pxtalk_range_data->rate_per_spad_kcps_sum / (uint32_t)pxtalk_range_data->no_of_samples; pxtalk_range_data->signal_total_events_avg = pxtalk_range_data->signal_total_events_sum / (int32_t)pxtalk_range_data->no_of_samples; pxtalk_range_data->sigma_mm_avg = pxtalk_range_data->sigma_mm_sum / (uint32_t)pxtalk_range_data->no_of_samples; pxtalk_range_data->median_phase_avg = pxtalk_range_data->median_phase_sum / (uint32_t)pxtalk_range_data->no_of_samples; } else { pxtalk_range_data->rate_per_spad_kcps_avg = pxtalk_range_data->rate_per_spad_kcps_sum; pxtalk_range_data->signal_total_events_avg = pxtalk_range_data->signal_total_events_sum; pxtalk_range_data->sigma_mm_avg = pxtalk_range_data->sigma_mm_sum; pxtalk_range_data->median_phase_avg = pxtalk_range_data->median_phase_sum; } } memcpy(pavg_histo, &(pdev->hist_data), sizeof(VL53LX_histogram_bin_data_t)); if (status == VL53LX_ERROR_NONE) { pxtalk_range_data = &(pXR->VL53LX_p_003[xtalk_histo_id]); status = VL53LX_avg_histogram_data( pxtalk_range_data->no_of_samples, psum_histo, pavg_histo); } if (status == VL53LX_ERROR_NONE) { if (smudge_corr_en == 1) status = VL53LX_dynamic_xtalk_correction_enable(Dev); } LOG_FUNCTION_END(status); return status; } VL53LX_Error VL53LX_run_phasecal_average( VL53LX_DEV Dev, uint8_t measurement_mode, uint8_t phasecal_result__vcsel_start, uint16_t phasecal_num_of_samples, VL53LX_range_results_t *prange_results, uint16_t *pphasecal_result__reference_phase, uint16_t *pzero_distance_phase) { VL53LX_Error status = VL53LX_ERROR_NONE; VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); uint16_t i = 0; uint16_t m = 0; uint32_t samples = 0; uint32_t period = 0; uint32_t VL53LX_p_014 = 0; uint32_t phasecal_result__reference_phase = 0; uint32_t zero_distance_phase = 0; VL53LX_load_patch(Dev); for (m = 0; m < phasecal_num_of_samples; m++) { if (status == VL53LX_ERROR_NONE) status = VL53LX_init_and_start_range( Dev, measurement_mode, VL53LX_DEVICECONFIGLEVEL_CUSTOMER_ONWARDS); for (i = 0; i <= 1; i++) { if (status == VL53LX_ERROR_NONE) status = VL53LX_wait_for_range_completion(Dev); if (status == VL53LX_ERROR_NONE) status = VL53LX_get_device_results( Dev, VL53LX_DEVICERESULTSLEVEL_FULL, prange_results); if (status == VL53LX_ERROR_NONE) status = VL53LX_clear_interrupt_and_enable_next_range( Dev, measurement_mode); } if (status == VL53LX_ERROR_NONE) status = VL53LX_stop_range(Dev); if (status == VL53LX_ERROR_NONE) status = VL53LX_WaitUs(Dev, 1000); if (status == VL53LX_ERROR_NONE) { samples++; period = 2048 * (uint32_t)VL53LX_decode_vcsel_period( pdev->hist_data.VL53LX_p_005); VL53LX_p_014 = period; VL53LX_p_014 += (uint32_t)( pdev->hist_data.phasecal_result__reference_phase); VL53LX_p_014 += (2048 * (uint32_t)phasecal_result__vcsel_start); VL53LX_p_014 -= (2048 * (uint32_t)pdev->hist_data.cal_config__vcsel_start); if (period != 0) { VL53LX_p_014 = VL53LX_p_014 % period; } else { status = VL53LX_ERROR_DIVISION_BY_ZERO; VL53LX_p_014 = 0; } phasecal_result__reference_phase += (uint32_t)( pdev->hist_data.phasecal_result__reference_phase); zero_distance_phase += (uint32_t)VL53LX_p_014; } } VL53LX_unload_patch(Dev); if (status == VL53LX_ERROR_NONE && samples > 0) { phasecal_result__reference_phase += (samples >> 1); phasecal_result__reference_phase /= samples; zero_distance_phase += (samples >> 1); zero_distance_phase /= samples; *pphasecal_result__reference_phase = (uint16_t)phasecal_result__reference_phase; *pzero_distance_phase = (uint16_t)zero_distance_phase; } return status; } VL53LX_Error VL53LX_run_device_test( VL53LX_DEV Dev, VL53LX_DeviceTestMode device_test_mode) { VL53LX_Error status = VL53LX_ERROR_NONE; VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); uint8_t comms_buffer[2]; uint8_t gpio_hv_mux__ctrl = 0; LOG_FUNCTION_START(""); if (status == VL53LX_ERROR_NONE) status = VL53LX_RdByte( Dev, VL53LX_GPIO_HV_MUX__CTRL, &gpio_hv_mux__ctrl); if (status == VL53LX_ERROR_NONE) pdev->stat_cfg.gpio_hv_mux__ctrl = gpio_hv_mux__ctrl; if (status == VL53LX_ERROR_NONE) status = VL53LX_start_test( Dev, device_test_mode); if (status == VL53LX_ERROR_NONE) status = VL53LX_wait_for_test_completion(Dev); if (status == VL53LX_ERROR_NONE) status = VL53LX_ReadMulti( Dev, VL53LX_RESULT__RANGE_STATUS, comms_buffer, 2); if (status == VL53LX_ERROR_NONE) { pdev->sys_results.result__range_status = comms_buffer[0]; pdev->sys_results.result__report_status = comms_buffer[1]; } pdev->sys_results.result__range_status &= VL53LX_RANGE_STATUS__RANGE_STATUS_MASK; if (status == VL53LX_ERROR_NONE) { trace_print( VL53LX_TRACE_LEVEL_INFO, " Device Test Complete:\n\t%-32s = %3u\n\t%-32s = %3u\n", "result__range_status", pdev->sys_results.result__range_status, "result__report_status", pdev->sys_results.result__report_status); if (status == VL53LX_ERROR_NONE) status = VL53LX_clear_interrupt(Dev); } if (status == VL53LX_ERROR_NONE) status = VL53LX_start_test( Dev, 0x00); LOG_FUNCTION_END(status); return status; } void VL53LX_hist_xtalk_extract_data_init( VL53LX_hist_xtalk_extract_data_t *pxtalk_data) { int32_t lb = 0; pxtalk_data->sample_count = 0U; pxtalk_data->pll_period_mm = 0U; pxtalk_data->peak_duration_us_sum = 0U; pxtalk_data->effective_spad_count_sum = 0U; pxtalk_data->zero_distance_phase_sum = 0U; pxtalk_data->zero_distance_phase_avg = 0U; pxtalk_data->event_scaler_sum = 0U; pxtalk_data->event_scaler_avg = 4096U; pxtalk_data->signal_events_sum = 0; pxtalk_data->xtalk_rate_kcps_per_spad = 0U; pxtalk_data->VL53LX_p_012 = 0U; pxtalk_data->VL53LX_p_013 = 0U; pxtalk_data->target_start = 0U; for (lb = 0; lb < VL53LX_XTALK_HISTO_BINS; lb++) pxtalk_data->bin_data_sums[lb] = 0; } VL53LX_Error VL53LX_hist_xtalk_extract_update( int16_t target_distance_mm, uint16_t target_width_oversize, VL53LX_histogram_bin_data_t *phist_bins, VL53LX_hist_xtalk_extract_data_t *pxtalk_data) { VL53LX_Error status = VL53LX_ERROR_NONE; LOG_FUNCTION_START(""); status = VL53LX_hist_xtalk_extract_calc_window( target_distance_mm, target_width_oversize, phist_bins, pxtalk_data); if (status == VL53LX_ERROR_NONE) { status = VL53LX_hist_xtalk_extract_calc_event_sums( phist_bins, pxtalk_data); } LOG_FUNCTION_END(status); return status; } VL53LX_Error VL53LX_hist_xtalk_extract_fini( VL53LX_histogram_bin_data_t *phist_bins, VL53LX_hist_xtalk_extract_data_t *pxtalk_data, VL53LX_xtalk_calibration_results_t *pxtalk_cal, VL53LX_xtalk_histogram_shape_t *pxtalk_shape) { VL53LX_Error status = VL53LX_ERROR_NONE; VL53LX_xtalk_calibration_results_t *pX = pxtalk_cal; LOG_FUNCTION_START(""); if (pxtalk_data->sample_count > 0) { pxtalk_data->event_scaler_avg = pxtalk_data->event_scaler_sum; pxtalk_data->event_scaler_avg += (pxtalk_data->sample_count >> 1); pxtalk_data->event_scaler_avg /= pxtalk_data->sample_count; status = VL53LX_hist_xtalk_extract_calc_rate_per_spad( pxtalk_data); if (status == VL53LX_ERROR_NONE) { pxtalk_data->zero_distance_phase_avg = pxtalk_data->zero_distance_phase_sum; pxtalk_data->zero_distance_phase_avg += (pxtalk_data->sample_count >> 1); pxtalk_data->zero_distance_phase_avg /= pxtalk_data->sample_count; status = VL53LX_hist_xtalk_extract_calc_shape( pxtalk_data, pxtalk_shape); pxtalk_shape->phasecal_result__vcsel_start = phist_bins->phasecal_result__vcsel_start; pxtalk_shape->cal_config__vcsel_start = phist_bins->cal_config__vcsel_start; pxtalk_shape->vcsel_width = phist_bins->vcsel_width; pxtalk_shape->VL53LX_p_015 = phist_bins->VL53LX_p_015; } if (status == VL53LX_ERROR_NONE) { pX->algo__crosstalk_compensation_plane_offset_kcps = pxtalk_data->xtalk_rate_kcps_per_spad; pX->algo__crosstalk_compensation_x_plane_gradient_kcps = 0U; pX->algo__crosstalk_compensation_y_plane_gradient_kcps = 0U; } } LOG_FUNCTION_END(status); return status; } VL53LX_Error VL53LX_run_hist_xtalk_extraction( VL53LX_DEV Dev, int16_t cal_distance_mm, VL53LX_Error *pcal_status) { #define OVERSIZE 4 VL53LX_Error status = VL53LX_ERROR_NONE; VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); VL53LX_xtalkextract_config_t *pX = &(pdev->xtalk_extract_cfg); VL53LX_xtalk_config_t *pC = &(pdev->xtalk_cfg); VL53LX_xtalk_calibration_results_t *pXC = &(pdev->xtalk_cal); uint8_t smudge_corr_en = 0; uint8_t i = 0; int8_t k = 0; uint8_t nbloops; int32_t initMergeSize = 0; int32_t MergeEnabled = 0; uint32_t deltaXtalk; uint32_t stepXtalk; uint32_t XtalkMin; uint32_t XtalkMax; uint8_t measurement_mode = VL53LX_DEVICEMEASUREMENTMODE_BACKTOBACK; int8_t MaxId; uint8_t histo_merge_nb; uint8_t wait_for_accumulation; VL53LX_range_results_t *prange_results = (VL53LX_range_results_t *) pdev->wArea1; uint8_t Very1stRange = 0; VL53LX_DevicePresetModes current_device_preset_mode; uint32_t inter_measurement_period_ms; uint16_t dss_config__target_total_rate_mcps; uint32_t phasecal_config_timeout_us; uint32_t mm_config_timeout_us; uint32_t range_config_timeout_us; LOG_FUNCTION_START(""); current_device_preset_mode = pdev->preset_mode; inter_measurement_period_ms = pdev->inter_measurement_period_ms; if (status == VL53LX_ERROR_NONE) status = VL53LX_set_preset_mode( Dev, VL53LX_DEVICEPRESETMODE_HISTOGRAM_LONG_RANGE, pX->dss_config__target_total_rate_mcps, pX->phasecal_config_timeout_us, pX->mm_config_timeout_us, pX->range_config_timeout_us, 100); if (status == VL53LX_ERROR_NONE) status = VL53LX_disable_xtalk_compensation(Dev); smudge_corr_en = pdev->smudge_correct_config.smudge_corr_enabled; if (status == VL53LX_ERROR_NONE) status = VL53LX_dynamic_xtalk_correction_disable(Dev); VL53LX_load_patch(Dev); VL53LX_get_tuning_parm(Dev, VL53LX_TUNINGPARM_HIST_MERGE_MAX_SIZE, &initMergeSize); VL53LX_get_tuning_parm(Dev, VL53LX_TUNINGPARM_HIST_MERGE, &MergeEnabled); memset(&pdev->xtalk_cal, 0, sizeof(pdev->xtalk_cal)); if (status == VL53LX_ERROR_NONE) status = VL53LX_init_and_start_range( Dev, measurement_mode, VL53LX_DEVICECONFIGLEVEL_CUSTOMER_ONWARDS); MaxId = pdev->tuning_parms.tp_hist_merge_max_size - 1; nbloops = (MergeEnabled == 0 ? 1 : 2); for (k = 0; k < nbloops; k++) { VL53LX_hist_xtalk_extract_data_init( &(pdev->xtalk_extract)); VL53LX_set_tuning_parm(Dev, VL53LX_TUNINGPARM_HIST_MERGE_MAX_SIZE, k * MaxId + 1); for (i = 0; i <= pX->num_of_samples; i++) { if (status == VL53LX_ERROR_NONE) status = VL53LX_wait_for_range_completion(Dev); if (status == VL53LX_ERROR_NONE) status = VL53LX_get_device_results(Dev, VL53LX_DEVICERESULTSLEVEL_FULL, prange_results); Very1stRange = (pdev->ll_state.rd_device_state == VL53LX_DEVICESTATE_RANGING_WAIT_GPH_SYNC); VL53LX_compute_histo_merge_nb(Dev, &histo_merge_nb); wait_for_accumulation = ((k != 0) && (MergeEnabled) && (status == VL53LX_ERROR_NONE) && (histo_merge_nb < pdev->tuning_parms.tp_hist_merge_max_size)); if (wait_for_accumulation) i = 0; else { if ((status == VL53LX_ERROR_NONE) && (!Very1stRange)) { status = VL53LX_hist_xtalk_extract_update( cal_distance_mm, OVERSIZE, &(pdev->hist_data), &(pdev->xtalk_extract)); } } if (status == VL53LX_ERROR_NONE) status = VL53LX_clear_interrupt_and_enable_next_range( Dev, measurement_mode); } if (status == VL53LX_ERROR_NONE) status = VL53LX_hist_xtalk_extract_fini( &(pdev->hist_data), &(pdev->xtalk_extract), &(pdev->xtalk_cal), &(pdev->xtalk_shapes.xtalk_shape)); if (status == VL53LX_ERROR_NONE) { pXC->algo__xtalk_cpo_HistoMerge_kcps[k * MaxId] = pXC->algo__crosstalk_compensation_plane_offset_kcps; } } VL53LX_stop_range(Dev); VL53LX_set_tuning_parm(Dev, VL53LX_TUNINGPARM_HIST_MERGE_MAX_SIZE, initMergeSize); VL53LX_unload_patch(Dev); VL53LX_get_preset_mode_timing_cfg(Dev, current_device_preset_mode, &dss_config__target_total_rate_mcps, &phasecal_config_timeout_us, &mm_config_timeout_us, &range_config_timeout_us); VL53LX_set_preset_mode(Dev, current_device_preset_mode, dss_config__target_total_rate_mcps, phasecal_config_timeout_us, mm_config_timeout_us, range_config_timeout_us, inter_measurement_period_ms); if (status != VL53LX_ERROR_NONE) status = VL53LX_ERROR_XTALK_EXTRACTION_SIGMA_LIMIT_FAIL; else if ((MergeEnabled == 1) && (MaxId > 0)) { XtalkMin = pdev->xtalk_cal.algo__xtalk_cpo_HistoMerge_kcps[0]; XtalkMax = pdev->xtalk_cal.algo__xtalk_cpo_HistoMerge_kcps[MaxId]; pdev->xtalk_cal. algo__crosstalk_compensation_plane_offset_kcps = XtalkMin; if (XtalkMax > XtalkMin) { deltaXtalk = XtalkMax - XtalkMin; stepXtalk = deltaXtalk / MaxId; for (k = 1; k < MaxId; k++) pdev->xtalk_cal.algo__xtalk_cpo_HistoMerge_kcps[k] = XtalkMin + stepXtalk * k; } else status = VL53LX_ERROR_XTALK_EXTRACTION_SIGMA_LIMIT_FAIL; } if (status == VL53LX_ERROR_NONE) { pC->algo__crosstalk_compensation_x_plane_gradient_kcps = pXC->algo__crosstalk_compensation_x_plane_gradient_kcps; pC->algo__crosstalk_compensation_y_plane_gradient_kcps = pXC->algo__crosstalk_compensation_y_plane_gradient_kcps; pC->algo__crosstalk_compensation_plane_offset_kcps = pXC->algo__crosstalk_compensation_plane_offset_kcps; } pdev->xtalk_results.cal_status = status; *pcal_status = pdev->xtalk_results.cal_status; status = VL53LX_enable_xtalk_compensation(Dev); if (smudge_corr_en == 1) status = VL53LX_dynamic_xtalk_correction_enable(Dev); #ifdef VL53LX_LOG_ENABLE VL53LX_print_customer_nvm_managed( &(pdev->customer), "run_xtalk_extraction():pdev->lldata.customer.", VL53LX_TRACE_MODULE_XTALK_DATA); VL53LX_print_xtalk_config( &(pdev->xtalk_cfg), "run_xtalk_extraction():pdev->lldata.xtalk_cfg.", VL53LX_TRACE_MODULE_XTALK_DATA); VL53LX_print_xtalk_histogram_data( &(pdev->xtalk_shapes), "pdev->lldata.xtalk_shapes.", VL53LX_TRACE_MODULE_XTALK_DATA); #endif LOG_FUNCTION_END(status); return status; }