1969 lines
52 KiB
C
1969 lines
52 KiB
C
/**
|
|
******************************************************************************
|
|
* 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_api.h"
|
|
#include "vl53lx_register_settings.h"
|
|
#include "vl53lx_register_funcs.h"
|
|
#include "vl53lx_core.h"
|
|
#include "vl53lx_api_calibration.h"
|
|
#include "vl53lx_wait.h"
|
|
#include "vl53lx_preset_setup.h"
|
|
#include "vl53lx_api_debug.h"
|
|
#include "vl53lx_api_core.h"
|
|
#include "vl53lx_nvm.h"
|
|
|
|
|
|
#define ZONE_CHECK 5
|
|
|
|
#define LOG_FUNCTION_START(fmt, ...) \
|
|
_LOG_FUNCTION_START(VL53LX_TRACE_MODULE_API, fmt, ##__VA_ARGS__)
|
|
#define LOG_FUNCTION_END(status, ...) \
|
|
_LOG_FUNCTION_END(VL53LX_TRACE_MODULE_API, status, ##__VA_ARGS__)
|
|
#define LOG_FUNCTION_END_FMT(status, fmt, ...) \
|
|
_LOG_FUNCTION_END_FMT(VL53LX_TRACE_MODULE_API, status, \
|
|
fmt, ##__VA_ARGS__)
|
|
|
|
#ifdef VL53LX_LOG_ENABLE
|
|
#define trace_print(level, ...) trace_print_module_function(\
|
|
VL53LX_TRACE_MODULE_API, level, VL53LX_TRACE_FUNCTION_NONE, \
|
|
##__VA_ARGS__)
|
|
#endif
|
|
|
|
#ifndef MIN
|
|
#define MIN(v1, v2) ((v1) < (v2) ? (v1) : (v2))
|
|
#endif
|
|
#ifndef MAX
|
|
#define MAX(v1, v2) ((v1) < (v2) ? (v2) : (v1))
|
|
#endif
|
|
|
|
#define DMAX_REFLECTANCE_IDX 2
|
|
|
|
|
|
|
|
#define LOWPOWER_AUTO_VHV_LOOP_DURATION_US 245
|
|
#define LOWPOWER_AUTO_OVERHEAD_BEFORE_A_RANGING 1448
|
|
#define LOWPOWER_AUTO_OVERHEAD_BETWEEN_A_B_RANGING 2100
|
|
|
|
#define FDA_MAX_TIMING_BUDGET_US 550000
|
|
#define L4_FDA_MAX_TIMING_BUDGET_US 200000
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int32_t BDTable[VL53LX_TUNING_MAX_TUNABLE_KEY] = {
|
|
TUNING_VERSION,
|
|
TUNING_PROXY_MIN,
|
|
TUNING_SINGLE_TARGET_XTALK_TARGET_DISTANCE_MM,
|
|
TUNING_SINGLE_TARGET_XTALK_SAMPLE_NUMBER,
|
|
TUNING_MIN_AMBIENT_DMAX_VALID,
|
|
TUNING_MAX_SIMPLE_OFFSET_CALIBRATION_SAMPLE_NUMBER,
|
|
TUNING_XTALK_FULL_ROI_TARGET_DISTANCE_MM,
|
|
TUNING_SIMPLE_OFFSET_CALIBRATION_REPEAT,
|
|
TUNING_XTALK_FULL_ROI_BIN_SUM_MARGIN,
|
|
TUNING_XTALK_FULL_ROI_DEFAULT_OFFSET,
|
|
TUNING_ZERO_DISTANCE_OFFSET_NON_LINEAR_FACTOR_DEFAULT
|
|
};
|
|
|
|
static VL53LX_Error ComputeDevicePresetMode(
|
|
VL53LX_DistanceModes DistanceMode,
|
|
VL53LX_DevicePresetModes *pDevicePresetMode);
|
|
|
|
static VL53LX_Error SetPresetModeL3CX(VL53LX_DEV Dev,
|
|
VL53LX_DistanceModes DistanceMode,
|
|
uint32_t inter_measurement_period_ms);
|
|
|
|
static int IsL4(VL53LX_DEV Dev);
|
|
|
|
static VL53LX_Error CheckValidRectRoi(VL53LX_UserRoi_t ROI);
|
|
|
|
|
|
VL53LX_Error VL53LX_GetVersion(VL53LX_Version_t *pVersion)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
|
|
LOG_FUNCTION_START("");
|
|
|
|
pVersion->major = VL53LX_IMPLEMENTATION_VER_MAJOR;
|
|
pVersion->minor = VL53LX_IMPLEMENTATION_VER_MINOR;
|
|
pVersion->build = VL53LX_IMPLEMENTATION_VER_SUB;
|
|
|
|
pVersion->revision = VL53LX_IMPLEMENTATION_VER_REVISION;
|
|
|
|
LOG_FUNCTION_END(Status);
|
|
return Status;
|
|
}
|
|
|
|
VL53LX_Error VL53LX_GetProductRevision(VL53LX_DEV Dev,
|
|
uint8_t *pProductRevisionMajor, uint8_t *pProductRevisionMinor)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
uint8_t revision_id;
|
|
VL53LX_LLDriverData_t *pLLData;
|
|
|
|
LOG_FUNCTION_START("");
|
|
|
|
pLLData = VL53LXDevStructGetLLDriverHandle(Dev);
|
|
revision_id = pLLData->nvm_copy_data.identification__revision_id;
|
|
*pProductRevisionMajor = 1;
|
|
*pProductRevisionMinor = (revision_id & 0xF0) >> 4;
|
|
|
|
LOG_FUNCTION_END(Status);
|
|
return Status;
|
|
|
|
}
|
|
|
|
VL53LX_Error VL53LX_GetDeviceInfo(VL53LX_DEV Dev,
|
|
VL53LX_DeviceInfo_t *pVL53LX_DeviceInfo)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
uint8_t revision_id;
|
|
VL53LX_LLDriverData_t *pLLData;
|
|
|
|
LOG_FUNCTION_START("");
|
|
|
|
pLLData = VL53LXDevStructGetLLDriverHandle(Dev);
|
|
|
|
pVL53LX_DeviceInfo->ProductType =
|
|
pLLData->nvm_copy_data.identification__module_type;
|
|
|
|
revision_id = pLLData->nvm_copy_data.identification__revision_id;
|
|
pVL53LX_DeviceInfo->ProductRevisionMajor = 1;
|
|
pVL53LX_DeviceInfo->ProductRevisionMinor = (revision_id & 0xF0) >> 4;
|
|
|
|
LOG_FUNCTION_END(Status);
|
|
return Status;
|
|
}
|
|
|
|
VL53LX_Error VL53LX_GetUID(VL53LX_DEV Dev, uint64_t *pUid)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
uint8_t fmtdata[8];
|
|
|
|
LOG_FUNCTION_START("");
|
|
|
|
Status = VL53LX_read_nvm_raw_data(Dev,
|
|
(uint8_t)(0x1F8 >> 2),
|
|
(uint8_t)(8 >> 2),
|
|
fmtdata);
|
|
memcpy(pUid, fmtdata, sizeof(uint64_t));
|
|
|
|
LOG_FUNCTION_END(Status);
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
VL53LX_Error VL53LX_SetDeviceAddress(VL53LX_DEV Dev, uint8_t DeviceAddress)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev);
|
|
VL53LX_static_nvm_managed_t *pdata = &(pdev->stat_nvm);
|
|
|
|
LOG_FUNCTION_START("");
|
|
|
|
Status = VL53LX_WrByte(Dev, VL53LX_I2C_SLAVE__DEVICE_ADDRESS,
|
|
DeviceAddress / 2);
|
|
|
|
pdata->i2c_slave__device_address = (DeviceAddress / 2) & 0x7F;
|
|
|
|
LOG_FUNCTION_END(Status);
|
|
return Status;
|
|
}
|
|
|
|
|
|
VL53LX_Error VL53LX_DataInit(VL53LX_DEV Dev)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
VL53LX_LLDriverData_t *pdev;
|
|
uint8_t measurement_mode;
|
|
|
|
LOG_FUNCTION_START("");
|
|
|
|
|
|
#ifdef USE_I2C_2V8
|
|
Status = VL53LX_RdByte(Dev, VL53LX_PAD_I2C_HV__EXTSUP_CONFIG, &i);
|
|
if (Status == VL53LX_ERROR_NONE) {
|
|
i = (i & 0xfe) | 0x01;
|
|
Status = VL53LX_WrByte(Dev, VL53LX_PAD_I2C_HV__EXTSUP_CONFIG,
|
|
i);
|
|
}
|
|
#endif
|
|
|
|
if (Status == VL53LX_ERROR_NONE)
|
|
Status = VL53LX_data_init(Dev, 1);
|
|
|
|
if (Status == VL53LX_ERROR_NONE)
|
|
Status = SetPresetModeL3CX(Dev,
|
|
VL53LX_DISTANCEMODE_MEDIUM,
|
|
1000);
|
|
|
|
|
|
if (Status == VL53LX_ERROR_NONE)
|
|
Status = VL53LX_SetMeasurementTimingBudgetMicroSeconds(Dev,
|
|
33333);
|
|
|
|
if (Status == VL53LX_ERROR_NONE) {
|
|
pdev = VL53LXDevStructGetLLDriverHandle(Dev);
|
|
memset(&pdev->per_vcsel_cal_data, 0,
|
|
sizeof(pdev->per_vcsel_cal_data));
|
|
}
|
|
|
|
if (Status == VL53LX_ERROR_NONE) {
|
|
Status = VL53LX_set_dmax_mode(Dev,
|
|
VL53LX_DEVICEDMAXMODE__CUST_CAL_DATA);
|
|
}
|
|
|
|
|
|
if (Status == VL53LX_ERROR_NONE)
|
|
Status = VL53LX_SmudgeCorrectionEnable(Dev,
|
|
VL53LX_SMUDGE_CORRECTION_NONE);
|
|
|
|
measurement_mode = VL53LX_DEVICEMEASUREMENTMODE_BACKTOBACK;
|
|
VL53LXDevDataSet(Dev, LLData.measurement_mode, measurement_mode);
|
|
|
|
VL53LXDevDataSet(Dev, CurrentParameters.DistanceMode,
|
|
VL53LX_DISTANCEMODE_MEDIUM);
|
|
|
|
LOG_FUNCTION_END(Status);
|
|
return Status;
|
|
}
|
|
|
|
|
|
VL53LX_Error VL53LX_WaitDeviceBooted(VL53LX_DEV Dev)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
|
|
LOG_FUNCTION_START("");
|
|
|
|
Status = VL53LX_poll_for_boot_completion(Dev,
|
|
VL53LX_BOOT_COMPLETION_POLLING_TIMEOUT_MS);
|
|
|
|
LOG_FUNCTION_END(Status);
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
|
|
static VL53LX_Error ComputeDevicePresetMode(
|
|
VL53LX_DistanceModes DistanceMode,
|
|
VL53LX_DevicePresetModes *pDevicePresetMode)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
|
|
uint8_t DistIdx;
|
|
VL53LX_DevicePresetModes RangingModes[3] = {
|
|
VL53LX_DEVICEPRESETMODE_HISTOGRAM_SHORT_RANGE,
|
|
VL53LX_DEVICEPRESETMODE_HISTOGRAM_MEDIUM_RANGE,
|
|
VL53LX_DEVICEPRESETMODE_HISTOGRAM_LONG_RANGE};
|
|
|
|
switch (DistanceMode) {
|
|
case VL53LX_DISTANCEMODE_SHORT:
|
|
DistIdx = 0;
|
|
break;
|
|
case VL53LX_DISTANCEMODE_MEDIUM:
|
|
DistIdx = 1;
|
|
break;
|
|
default:
|
|
DistIdx = 2;
|
|
}
|
|
|
|
*pDevicePresetMode = RangingModes[DistIdx];
|
|
|
|
return Status;
|
|
}
|
|
|
|
static VL53LX_Error SetPresetModeL3CX(VL53LX_DEV Dev,
|
|
VL53LX_DistanceModes DistanceMode,
|
|
uint32_t inter_measurement_period_ms)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
VL53LX_DevicePresetModes device_preset_mode;
|
|
uint8_t measurement_mode;
|
|
uint16_t dss_config__target_total_rate_mcps = 0;
|
|
uint32_t phasecal_config_timeout_us = 0;
|
|
uint32_t mm_config_timeout_us = 0;
|
|
uint32_t lld_range_config_timeout_us = 0;
|
|
|
|
LOG_FUNCTION_START("");
|
|
|
|
measurement_mode = VL53LX_DEVICEMEASUREMENTMODE_BACKTOBACK;
|
|
|
|
Status = ComputeDevicePresetMode(DistanceMode,
|
|
&device_preset_mode);
|
|
|
|
if (Status == VL53LX_ERROR_NONE)
|
|
Status = VL53LX_get_preset_mode_timing_cfg(Dev,
|
|
device_preset_mode,
|
|
&dss_config__target_total_rate_mcps,
|
|
&phasecal_config_timeout_us,
|
|
&mm_config_timeout_us,
|
|
&lld_range_config_timeout_us);
|
|
|
|
if (Status == VL53LX_ERROR_NONE)
|
|
Status = VL53LX_set_preset_mode(
|
|
Dev,
|
|
device_preset_mode,
|
|
dss_config__target_total_rate_mcps,
|
|
phasecal_config_timeout_us,
|
|
mm_config_timeout_us,
|
|
lld_range_config_timeout_us,
|
|
inter_measurement_period_ms);
|
|
|
|
if (Status == VL53LX_ERROR_NONE)
|
|
VL53LXDevDataSet(Dev, LLData.measurement_mode,
|
|
measurement_mode);
|
|
|
|
LOG_FUNCTION_END(Status);
|
|
return Status;
|
|
}
|
|
|
|
static int IsL4(VL53LX_DEV Dev)
|
|
{
|
|
int devL4 = 0;
|
|
VL53LX_LLDriverData_t *pDev;
|
|
pDev = VL53LXDevStructGetLLDriverHandle(Dev);
|
|
|
|
if ((pDev->nvm_copy_data.identification__module_type == 0xAA) &&
|
|
(pDev->nvm_copy_data.identification__model_id == 0xEB))
|
|
devL4 = 1;
|
|
return devL4;
|
|
}
|
|
|
|
static VL53LX_Error CheckValidRectRoi(VL53LX_UserRoi_t ROI)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
|
|
LOG_FUNCTION_START("");
|
|
|
|
|
|
if ((ROI.TopLeftX > 15) || (ROI.TopLeftY > 15) ||
|
|
(ROI.BotRightX > 15) || (ROI.BotRightY > 15))
|
|
Status = VL53LX_ERROR_INVALID_PARAMS;
|
|
|
|
if ((ROI.TopLeftX > ROI.BotRightX) || (ROI.TopLeftY < ROI.BotRightY))
|
|
Status = VL53LX_ERROR_INVALID_PARAMS;
|
|
|
|
LOG_FUNCTION_END(Status);
|
|
return Status;
|
|
}
|
|
|
|
|
|
VL53LX_Error VL53LX_SetDistanceMode(VL53LX_DEV Dev,
|
|
VL53LX_DistanceModes DistanceMode)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
uint32_t inter_measurement_period_ms;
|
|
uint32_t TimingBudget = 0;
|
|
uint32_t MmTimeoutUs = 0;
|
|
uint32_t PhaseCalTimeoutUs = 0;
|
|
|
|
LOG_FUNCTION_START("%d", (int)DistanceMode);
|
|
|
|
|
|
|
|
if ((DistanceMode != VL53LX_DISTANCEMODE_SHORT) &&
|
|
(DistanceMode != VL53LX_DISTANCEMODE_MEDIUM) &&
|
|
(DistanceMode != VL53LX_DISTANCEMODE_LONG))
|
|
return VL53LX_ERROR_INVALID_PARAMS;
|
|
|
|
if (IsL4(Dev) && (DistanceMode == VL53LX_DISTANCEMODE_SHORT))
|
|
return VL53LX_ERROR_INVALID_PARAMS;
|
|
|
|
inter_measurement_period_ms = VL53LXDevDataGet(Dev,
|
|
LLData.inter_measurement_period_ms);
|
|
|
|
if (Status == VL53LX_ERROR_NONE)
|
|
Status = VL53LX_get_timeouts_us(Dev, &PhaseCalTimeoutUs,
|
|
&MmTimeoutUs, &TimingBudget);
|
|
|
|
if (Status == VL53LX_ERROR_NONE)
|
|
Status = SetPresetModeL3CX(Dev,
|
|
DistanceMode,
|
|
inter_measurement_period_ms);
|
|
|
|
if (Status == VL53LX_ERROR_NONE) {
|
|
VL53LXDevDataSet(Dev, CurrentParameters.DistanceMode,
|
|
DistanceMode);
|
|
}
|
|
|
|
if (Status == VL53LX_ERROR_NONE) {
|
|
Status = VL53LX_set_timeouts_us(Dev, PhaseCalTimeoutUs,
|
|
MmTimeoutUs, TimingBudget);
|
|
|
|
if (Status == VL53LX_ERROR_NONE)
|
|
VL53LXDevDataSet(Dev, LLData.range_config_timeout_us,
|
|
TimingBudget);
|
|
}
|
|
|
|
LOG_FUNCTION_END(Status);
|
|
return Status;
|
|
}
|
|
|
|
VL53LX_Error VL53LX_GetDistanceMode(VL53LX_DEV Dev,
|
|
VL53LX_DistanceModes *pDistanceMode)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
|
|
LOG_FUNCTION_START("");
|
|
|
|
*pDistanceMode = VL53LXDevDataGet(Dev, CurrentParameters.DistanceMode);
|
|
|
|
LOG_FUNCTION_END(Status);
|
|
return Status;
|
|
}
|
|
|
|
|
|
VL53LX_Error VL53LX_SetMeasurementTimingBudgetMicroSeconds(VL53LX_DEV Dev,
|
|
uint32_t MeasurementTimingBudgetMicroSeconds)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
uint32_t TimingGuard;
|
|
uint32_t divisor;
|
|
uint32_t TimingBudget = 0;
|
|
uint32_t MmTimeoutUs = 0;
|
|
uint32_t PhaseCalTimeoutUs = 0;
|
|
uint32_t FDAMaxTimingBudgetUs = FDA_MAX_TIMING_BUDGET_US;
|
|
|
|
LOG_FUNCTION_START("");
|
|
|
|
|
|
if (MeasurementTimingBudgetMicroSeconds > 10000000)
|
|
Status = VL53LX_ERROR_INVALID_PARAMS;
|
|
|
|
if (Status == VL53LX_ERROR_NONE)
|
|
Status = VL53LX_get_timeouts_us(Dev,
|
|
&PhaseCalTimeoutUs,
|
|
&MmTimeoutUs,
|
|
&TimingBudget);
|
|
|
|
TimingGuard = 1700;
|
|
divisor = 6;
|
|
|
|
if (IsL4(Dev))
|
|
FDAMaxTimingBudgetUs = L4_FDA_MAX_TIMING_BUDGET_US;
|
|
|
|
if (MeasurementTimingBudgetMicroSeconds <= TimingGuard)
|
|
Status = VL53LX_ERROR_INVALID_PARAMS;
|
|
else {
|
|
TimingBudget = (MeasurementTimingBudgetMicroSeconds
|
|
- TimingGuard);
|
|
}
|
|
|
|
if (Status == VL53LX_ERROR_NONE) {
|
|
if (TimingBudget > FDAMaxTimingBudgetUs)
|
|
Status = VL53LX_ERROR_INVALID_PARAMS;
|
|
else {
|
|
TimingBudget /= divisor;
|
|
Status = VL53LX_set_timeouts_us(
|
|
Dev,
|
|
PhaseCalTimeoutUs,
|
|
MmTimeoutUs,
|
|
TimingBudget);
|
|
}
|
|
|
|
if (Status == VL53LX_ERROR_NONE)
|
|
VL53LXDevDataSet(Dev,
|
|
LLData.range_config_timeout_us,
|
|
TimingBudget);
|
|
}
|
|
|
|
if (Status == VL53LX_ERROR_NONE) {
|
|
VL53LXDevDataSet(Dev,
|
|
CurrentParameters.MeasurementTimingBudgetMicroSeconds,
|
|
MeasurementTimingBudgetMicroSeconds);
|
|
}
|
|
|
|
LOG_FUNCTION_END(Status);
|
|
return Status;
|
|
}
|
|
|
|
|
|
VL53LX_Error VL53LX_GetMeasurementTimingBudgetMicroSeconds(VL53LX_DEV Dev,
|
|
uint32_t *pMeasurementTimingBudgetMicroSeconds)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
uint32_t MmTimeoutUs = 0;
|
|
uint32_t RangeTimeoutUs = 0;
|
|
uint32_t PhaseCalTimeoutUs = 0;
|
|
|
|
LOG_FUNCTION_START("");
|
|
|
|
*pMeasurementTimingBudgetMicroSeconds = 0;
|
|
|
|
if (Status == VL53LX_ERROR_NONE)
|
|
Status = VL53LX_get_timeouts_us(Dev,
|
|
&PhaseCalTimeoutUs,
|
|
&MmTimeoutUs,
|
|
&RangeTimeoutUs);
|
|
|
|
if (Status == VL53LX_ERROR_NONE)
|
|
*pMeasurementTimingBudgetMicroSeconds = (6 * RangeTimeoutUs) +
|
|
1700;
|
|
|
|
LOG_FUNCTION_END(Status);
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VL53LX_Error VL53LX_SetUserROI(VL53LX_DEV Dev,
|
|
VL53LX_UserRoi_t *pRoi)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
VL53LX_zone_config_t zone_cfg;
|
|
uint8_t x_centre, y_centre, width, height;
|
|
|
|
Status = CheckValidRectRoi(*pRoi);
|
|
if (Status != VL53LX_ERROR_NONE)
|
|
return VL53LX_ERROR_INVALID_PARAMS;
|
|
|
|
x_centre = (pRoi->BotRightX + pRoi->TopLeftX + 1) / 2;
|
|
y_centre = (pRoi->TopLeftY + pRoi->BotRightY + 1) / 2;
|
|
width = (pRoi->BotRightX - pRoi->TopLeftX);
|
|
height = (pRoi->TopLeftY - pRoi->BotRightY);
|
|
zone_cfg.max_zones = 1;
|
|
zone_cfg.active_zones = 0;
|
|
zone_cfg.user_zones[0].x_centre = x_centre;
|
|
zone_cfg.user_zones[0].y_centre = y_centre;
|
|
zone_cfg.user_zones[0].width = width;
|
|
zone_cfg.user_zones[0].height = height;
|
|
if ((width < 3) || (height < 3))
|
|
Status = VL53LX_ERROR_INVALID_PARAMS;
|
|
else
|
|
Status = VL53LX_set_zone_config(Dev, &zone_cfg);
|
|
|
|
LOG_FUNCTION_END(Status);
|
|
return Status;
|
|
}
|
|
|
|
VL53LX_Error VL53LX_GetUserROI(VL53LX_DEV Dev,
|
|
VL53LX_UserRoi_t *pRoi)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
VL53LX_zone_config_t zone_cfg;
|
|
uint8_t TopLeftX;
|
|
uint8_t TopLeftY;
|
|
uint8_t BotRightX;
|
|
uint8_t BotRightY;
|
|
|
|
LOG_FUNCTION_START("");
|
|
|
|
VL53LX_get_zone_config(Dev, &zone_cfg);
|
|
|
|
TopLeftX = (2 * zone_cfg.user_zones[0].x_centre -
|
|
zone_cfg.user_zones[0].width) >> 1;
|
|
TopLeftY = (2 * zone_cfg.user_zones[0].y_centre +
|
|
zone_cfg.user_zones[0].height) >> 1;
|
|
BotRightX = (2 * zone_cfg.user_zones[0].x_centre +
|
|
zone_cfg.user_zones[0].width) >> 1;
|
|
BotRightY = (2 * zone_cfg.user_zones[0].y_centre -
|
|
zone_cfg.user_zones[0].height) >> 1;
|
|
pRoi->TopLeftX = TopLeftX;
|
|
pRoi->TopLeftY = TopLeftY;
|
|
pRoi->BotRightX = BotRightX;
|
|
pRoi->BotRightY = BotRightY;
|
|
|
|
LOG_FUNCTION_END(Status);
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VL53LX_Error VL53LX_StartMeasurement(VL53LX_DEV Dev)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
uint8_t DeviceMeasurementMode;
|
|
uint8_t i;
|
|
VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev);
|
|
|
|
LOG_FUNCTION_START("");
|
|
|
|
VL53LX_load_patch(Dev);
|
|
for (i = 0; i < VL53LX_MAX_RANGE_RESULTS; i++) {
|
|
pdev->PreviousRangeMilliMeter[i] = 0;
|
|
pdev->PreviousRangeStatus[i] = 255;
|
|
pdev->PreviousExtendedRange[i] = 0;
|
|
}
|
|
pdev->PreviousStreamCount = 0;
|
|
pdev->PreviousRangeActiveResults = 0;
|
|
|
|
DeviceMeasurementMode = VL53LXDevDataGet(Dev, LLData.measurement_mode);
|
|
|
|
if (Status == VL53LX_ERROR_NONE)
|
|
Status = VL53LX_init_and_start_range(
|
|
Dev,
|
|
DeviceMeasurementMode,
|
|
VL53LX_DEVICECONFIGLEVEL_FULL);
|
|
|
|
LOG_FUNCTION_END(Status);
|
|
return Status;
|
|
}
|
|
|
|
VL53LX_Error VL53LX_StopMeasurement(VL53LX_DEV Dev)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
|
|
LOG_FUNCTION_START("");
|
|
|
|
Status = VL53LX_stop_range(Dev);
|
|
|
|
VL53LX_unload_patch(Dev);
|
|
|
|
LOG_FUNCTION_END(Status);
|
|
return Status;
|
|
}
|
|
|
|
|
|
VL53LX_Error VL53LX_ClearInterruptAndStartMeasurement(VL53LX_DEV Dev)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
uint8_t DeviceMeasurementMode;
|
|
|
|
LOG_FUNCTION_START("");
|
|
|
|
DeviceMeasurementMode = VL53LXDevDataGet(Dev, LLData.measurement_mode);
|
|
|
|
Status = VL53LX_clear_interrupt_and_enable_next_range(Dev,
|
|
DeviceMeasurementMode);
|
|
|
|
LOG_FUNCTION_END(Status);
|
|
return Status;
|
|
}
|
|
|
|
|
|
VL53LX_Error VL53LX_GetMeasurementDataReady(VL53LX_DEV Dev,
|
|
uint8_t *pMeasurementDataReady)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
|
|
LOG_FUNCTION_START("");
|
|
|
|
Status = VL53LX_is_new_data_ready(Dev, pMeasurementDataReady);
|
|
|
|
LOG_FUNCTION_END(Status);
|
|
return Status;
|
|
}
|
|
|
|
VL53LX_Error VL53LX_WaitMeasurementDataReady(VL53LX_DEV Dev)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
|
|
LOG_FUNCTION_START("");
|
|
|
|
|
|
|
|
Status = VL53LX_poll_for_range_completion(Dev,
|
|
VL53LX_RANGE_COMPLETION_POLLING_TIMEOUT_MS);
|
|
|
|
LOG_FUNCTION_END(Status);
|
|
return Status;
|
|
}
|
|
|
|
static uint8_t ConvertStatusHisto(uint8_t FilteredRangeStatus)
|
|
{
|
|
uint8_t RangeStatus;
|
|
|
|
switch (FilteredRangeStatus) {
|
|
case VL53LX_DEVICEERROR_RANGEPHASECHECK:
|
|
RangeStatus = VL53LX_RANGESTATUS_OUTOFBOUNDS_FAIL;
|
|
break;
|
|
case VL53LX_DEVICEERROR_SIGMATHRESHOLDCHECK:
|
|
RangeStatus = VL53LX_RANGESTATUS_SIGMA_FAIL;
|
|
break;
|
|
case VL53LX_DEVICEERROR_RANGECOMPLETE_NO_WRAP_CHECK:
|
|
RangeStatus =
|
|
VL53LX_RANGESTATUS_RANGE_VALID_NO_WRAP_CHECK_FAIL;
|
|
break;
|
|
case VL53LX_DEVICEERROR_PHASECONSISTENCY:
|
|
RangeStatus = VL53LX_RANGESTATUS_WRAP_TARGET_FAIL;
|
|
break;
|
|
case VL53LX_DEVICEERROR_PREV_RANGE_NO_TARGETS:
|
|
RangeStatus = VL53LX_RANGESTATUS_TARGET_PRESENT_LACK_OF_SIGNAL;
|
|
break;
|
|
case VL53LX_DEVICEERROR_EVENTCONSISTENCY:
|
|
RangeStatus = VL53LX_RANGESTATUS_WRAP_TARGET_FAIL;
|
|
break;
|
|
case VL53LX_DEVICEERROR_RANGECOMPLETE_MERGED_PULSE:
|
|
RangeStatus = VL53LX_RANGESTATUS_RANGE_VALID_MERGED_PULSE;
|
|
break;
|
|
case VL53LX_DEVICEERROR_RANGECOMPLETE:
|
|
RangeStatus = VL53LX_RANGESTATUS_RANGE_VALID;
|
|
break;
|
|
default:
|
|
RangeStatus = VL53LX_RANGESTATUS_NONE;
|
|
}
|
|
|
|
return RangeStatus;
|
|
}
|
|
|
|
static VL53LX_Error SetTargetData(VL53LX_DEV Dev,
|
|
uint8_t active_results, uint8_t streamcount, uint8_t iteration,
|
|
uint8_t device_status, VL53LX_range_data_t *presults_data,
|
|
VL53LX_TargetRangeData_t *pRangeData)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
VL53LX_LLDriverData_t *pdev =
|
|
VL53LXDevStructGetLLDriverHandle(Dev);
|
|
VL53LX_tuning_parm_storage_t *tp =
|
|
&(pdev->tuning_parms);
|
|
uint8_t sequency;
|
|
uint8_t FilteredRangeStatus;
|
|
FixPoint1616_t AmbientRate;
|
|
FixPoint1616_t SignalRate;
|
|
FixPoint1616_t TempFix1616;
|
|
int16_t Range, RangeDiff, RangeMillimeterInit;
|
|
int32_t ExtendedRangeEnabled = 0;
|
|
uint8_t uwr_status;
|
|
int16_t AddOffset;
|
|
uint8_t histo_merge_nb;
|
|
|
|
SUPPRESS_UNUSED_WARNING(Dev);
|
|
|
|
FilteredRangeStatus = presults_data->range_status & 0x1F;
|
|
|
|
SignalRate = VL53LX_FIXPOINT97TOFIXPOINT1616(
|
|
presults_data->peak_signal_count_rate_mcps);
|
|
pRangeData->SignalRateRtnMegaCps
|
|
= SignalRate;
|
|
|
|
AmbientRate = VL53LX_FIXPOINT97TOFIXPOINT1616(
|
|
presults_data->ambient_count_rate_mcps);
|
|
pRangeData->AmbientRateRtnMegaCps = AmbientRate;
|
|
|
|
TempFix1616 = VL53LX_FIXPOINT97TOFIXPOINT1616(
|
|
presults_data->VL53LX_p_002);
|
|
|
|
pRangeData->SigmaMilliMeter = TempFix1616;
|
|
|
|
pRangeData->RangeMilliMeter = presults_data->median_range_mm;
|
|
pRangeData->RangeMaxMilliMeter = presults_data->max_range_mm;
|
|
pRangeData->RangeMinMilliMeter = presults_data->min_range_mm;
|
|
|
|
|
|
switch (device_status) {
|
|
case VL53LX_DEVICEERROR_MULTCLIPFAIL:
|
|
case VL53LX_DEVICEERROR_VCSELWATCHDOGTESTFAILURE:
|
|
case VL53LX_DEVICEERROR_VCSELCONTINUITYTESTFAILURE:
|
|
case VL53LX_DEVICEERROR_NOVHVVALUEFOUND:
|
|
pRangeData->RangeStatus = VL53LX_RANGESTATUS_HARDWARE_FAIL;
|
|
break;
|
|
case VL53LX_DEVICEERROR_USERROICLIP:
|
|
pRangeData->RangeStatus = VL53LX_RANGESTATUS_MIN_RANGE_FAIL;
|
|
break;
|
|
default:
|
|
pRangeData->RangeStatus = VL53LX_RANGESTATUS_RANGE_VALID;
|
|
}
|
|
|
|
|
|
if ((pRangeData->RangeStatus == VL53LX_RANGESTATUS_RANGE_VALID) &&
|
|
(active_results == 0)) {
|
|
pRangeData->RangeStatus = VL53LX_RANGESTATUS_NONE;
|
|
pRangeData->SignalRateRtnMegaCps = 0;
|
|
pRangeData->SigmaMilliMeter = 0;
|
|
pRangeData->RangeMilliMeter = 8191;
|
|
pRangeData->RangeMaxMilliMeter = 8191;
|
|
pRangeData->RangeMinMilliMeter = 8191;
|
|
}
|
|
|
|
|
|
if (pRangeData->RangeStatus == VL53LX_RANGESTATUS_RANGE_VALID)
|
|
pRangeData->RangeStatus =
|
|
ConvertStatusHisto(FilteredRangeStatus);
|
|
|
|
|
|
|
|
VL53LX_get_tuning_parm(Dev, VL53LX_TUNINGPARM_UWR_ENABLE,
|
|
&ExtendedRangeEnabled);
|
|
|
|
sequency = streamcount % 2;
|
|
uwr_status = 0;
|
|
RangeMillimeterInit = pRangeData->RangeMilliMeter;
|
|
AddOffset = 0;
|
|
|
|
pRangeData->ExtendedRange = 0;
|
|
|
|
|
|
Status = VL53LX_compute_histo_merge_nb(Dev, &histo_merge_nb);
|
|
if ((active_results != 1) ||
|
|
(pdev->PreviousRangeActiveResults != 1)||(histo_merge_nb == 0))
|
|
ExtendedRangeEnabled = 0;
|
|
|
|
if (ExtendedRangeEnabled &&
|
|
(pRangeData->RangeStatus ==
|
|
VL53LX_RANGESTATUS_WRAP_TARGET_FAIL ||
|
|
pRangeData->RangeStatus ==
|
|
VL53LX_RANGESTATUS_OUTOFBOUNDS_FAIL)
|
|
&& (pdev->PreviousRangeStatus[iteration] ==
|
|
VL53LX_RANGESTATUS_WRAP_TARGET_FAIL ||
|
|
pdev->PreviousRangeStatus[iteration] ==
|
|
VL53LX_RANGESTATUS_OUTOFBOUNDS_FAIL ||
|
|
(pdev->PreviousRangeStatus[iteration] ==
|
|
VL53LX_RANGESTATUS_RANGE_VALID &&
|
|
pdev->PreviousExtendedRange[iteration] == 1)))
|
|
{
|
|
if (((pdev->PreviousStreamCount) ==
|
|
(pdev->hist_data.result__stream_count - 1 ))
|
|
|| ((pdev->PreviousStreamCount) ==
|
|
(pdev->hist_data.result__stream_count + 127)))
|
|
{
|
|
RangeDiff = pRangeData->RangeMilliMeter -
|
|
pdev->PreviousRangeMilliMeter[iteration];
|
|
|
|
uwr_status = 1;
|
|
switch (pdev->preset_mode) {
|
|
case VL53LX_DEVICEPRESETMODE_HISTOGRAM_SHORT_RANGE:
|
|
|
|
uwr_status = 0;
|
|
break;
|
|
|
|
case VL53LX_DEVICEPRESETMODE_HISTOGRAM_MEDIUM_RANGE:
|
|
if (RangeDiff > tp->tp_uwr_med_z_1_min &&
|
|
RangeDiff < tp->tp_uwr_med_z_1_max &&
|
|
sequency == 1) {
|
|
AddOffset =
|
|
tp->tp_uwr_med_corr_z_1_rangeb;
|
|
}
|
|
else
|
|
if (RangeDiff < -tp->tp_uwr_med_z_1_min &&
|
|
RangeDiff > -tp->tp_uwr_med_z_1_max &&
|
|
sequency == 0) {
|
|
AddOffset =
|
|
tp->tp_uwr_med_corr_z_1_rangea;
|
|
}
|
|
else
|
|
if (RangeDiff > tp->tp_uwr_med_z_2_min &&
|
|
RangeDiff < tp->tp_uwr_med_z_2_max &&
|
|
sequency == 0) {
|
|
AddOffset =
|
|
tp->tp_uwr_med_corr_z_2_rangea;
|
|
}
|
|
else
|
|
if (RangeDiff < -tp->tp_uwr_med_z_2_min &&
|
|
RangeDiff > -tp->tp_uwr_med_z_2_max &&
|
|
sequency == 1) {
|
|
AddOffset =
|
|
tp->tp_uwr_med_corr_z_2_rangeb;
|
|
}
|
|
else
|
|
if (RangeDiff > tp->tp_uwr_med_z_3_min &&
|
|
RangeDiff < tp->tp_uwr_med_z_3_max &&
|
|
sequency == 1) {
|
|
AddOffset =
|
|
tp->tp_uwr_med_corr_z_3_rangeb;
|
|
}
|
|
else
|
|
if (RangeDiff < -tp->tp_uwr_med_z_3_min &&
|
|
RangeDiff > -tp->tp_uwr_med_z_3_max &&
|
|
sequency == 0) {
|
|
AddOffset =
|
|
tp->tp_uwr_med_corr_z_3_rangea;
|
|
}
|
|
else
|
|
if (RangeDiff > tp->tp_uwr_med_z_4_min &&
|
|
RangeDiff < tp->tp_uwr_med_z_4_max &&
|
|
sequency == 0) {
|
|
AddOffset =
|
|
tp->tp_uwr_med_corr_z_4_rangea;
|
|
}
|
|
else
|
|
if (RangeDiff < -tp->tp_uwr_med_z_4_min &&
|
|
RangeDiff > -tp->tp_uwr_med_z_4_max &&
|
|
sequency == 1) {
|
|
AddOffset =
|
|
tp->tp_uwr_med_corr_z_4_rangeb;
|
|
}
|
|
else
|
|
if (RangeDiff < tp->tp_uwr_med_z_5_max &&
|
|
RangeDiff > tp->tp_uwr_med_z_5_min) {
|
|
AddOffset =
|
|
tp->tp_uwr_med_corr_z_5_rangea;
|
|
} else
|
|
uwr_status = 0;
|
|
break;
|
|
|
|
case VL53LX_DEVICEPRESETMODE_HISTOGRAM_LONG_RANGE:
|
|
if (RangeDiff > tp->tp_uwr_lng_z_1_min &&
|
|
RangeDiff < tp->tp_uwr_lng_z_1_max &&
|
|
sequency == 0) {
|
|
AddOffset =
|
|
tp->tp_uwr_lng_corr_z_1_rangea;
|
|
}
|
|
else
|
|
if (RangeDiff < -tp->tp_uwr_lng_z_1_min &&
|
|
RangeDiff > -tp->tp_uwr_lng_z_1_max &&
|
|
sequency == 1) {
|
|
AddOffset =
|
|
tp->tp_uwr_lng_corr_z_1_rangeb;
|
|
}
|
|
else
|
|
if (RangeDiff > tp->tp_uwr_lng_z_2_min &&
|
|
RangeDiff < tp->tp_uwr_lng_z_2_max &&
|
|
sequency == 1) {
|
|
AddOffset =
|
|
tp->tp_uwr_lng_corr_z_2_rangeb;
|
|
}
|
|
else
|
|
if (RangeDiff < -tp->tp_uwr_lng_z_2_min &&
|
|
RangeDiff > -tp->tp_uwr_lng_z_2_max &&
|
|
sequency == 0) {
|
|
AddOffset =
|
|
tp->tp_uwr_lng_corr_z_2_rangea;
|
|
}
|
|
else
|
|
if (RangeDiff < tp->tp_uwr_lng_z_3_max &&
|
|
RangeDiff > tp->tp_uwr_lng_z_3_min) {
|
|
AddOffset =
|
|
tp->tp_uwr_lng_corr_z_3_rangea;
|
|
}
|
|
else
|
|
uwr_status = 0;
|
|
break;
|
|
|
|
default:
|
|
uwr_status = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (uwr_status) {
|
|
pRangeData->RangeMilliMeter += AddOffset;
|
|
pRangeData->RangeMinMilliMeter += AddOffset;
|
|
pRangeData->RangeMaxMilliMeter += AddOffset;
|
|
pRangeData->ExtendedRange = 1;
|
|
pRangeData->RangeStatus = 0;
|
|
}
|
|
|
|
}
|
|
|
|
pdev->PreviousRangeMilliMeter[iteration] = RangeMillimeterInit;
|
|
pdev->PreviousRangeStatus[iteration] = pRangeData->RangeStatus;
|
|
pdev->PreviousExtendedRange[iteration] = pRangeData->ExtendedRange;
|
|
pdev->PreviousRangeActiveResults = active_results;
|
|
|
|
Range = pRangeData->RangeMilliMeter;
|
|
if ((pRangeData->RangeStatus == VL53LX_RANGESTATUS_RANGE_VALID) &&
|
|
(Range < 0)) {
|
|
if (Range < BDTable[VL53LX_TUNING_PROXY_MIN])
|
|
pRangeData->RangeStatus =
|
|
VL53LX_RANGESTATUS_RANGE_INVALID;
|
|
else
|
|
pRangeData->RangeMilliMeter = 0;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
static VL53LX_Error SetMeasurementData(VL53LX_DEV Dev,
|
|
VL53LX_range_results_t *presults,
|
|
VL53LX_MultiRangingData_t *pMultiRangingData)
|
|
{
|
|
VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev);
|
|
uint8_t i;
|
|
uint8_t iteration;
|
|
VL53LX_TargetRangeData_t *pRangeData;
|
|
VL53LX_range_data_t *presults_data;
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
uint8_t ActiveResults;
|
|
|
|
pMultiRangingData->NumberOfObjectsFound = presults->active_results;
|
|
pMultiRangingData->HasXtalkValueChanged =
|
|
presults->smudge_corrector_data.new_xtalk_applied_flag;
|
|
|
|
|
|
pMultiRangingData->TimeStamp = 0;
|
|
|
|
pMultiRangingData->StreamCount = presults->stream_count;
|
|
|
|
ActiveResults = presults->active_results;
|
|
if (ActiveResults < 1)
|
|
|
|
iteration = 1;
|
|
else
|
|
iteration = ActiveResults;
|
|
for (i = 0; i < iteration; i++) {
|
|
pRangeData = &(pMultiRangingData->RangeData[i]);
|
|
|
|
presults_data = &(presults->VL53LX_p_003[i]);
|
|
if (Status == VL53LX_ERROR_NONE)
|
|
Status = SetTargetData(Dev, ActiveResults,
|
|
pMultiRangingData->StreamCount,
|
|
i,
|
|
presults->device_status,
|
|
presults_data,
|
|
pRangeData);
|
|
|
|
pMultiRangingData->EffectiveSpadRtnCount =
|
|
presults_data->VL53LX_p_004;
|
|
|
|
}
|
|
pdev->PreviousStreamCount = pdev->hist_data.result__stream_count;
|
|
for (i = iteration; i < VL53LX_MAX_RANGE_RESULTS; i++) {
|
|
pdev->PreviousRangeMilliMeter[i] = 0;
|
|
pdev->PreviousRangeStatus[i] = 255;
|
|
pdev->PreviousExtendedRange[i] = 0;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
VL53LX_Error VL53LX_GetMultiRangingData(VL53LX_DEV Dev,
|
|
VL53LX_MultiRangingData_t *pMultiRangingData)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
VL53LX_LLDriverData_t *pdev =
|
|
VL53LXDevStructGetLLDriverHandle(Dev);
|
|
VL53LX_range_results_t *presults =
|
|
(VL53LX_range_results_t *) pdev->wArea1;
|
|
|
|
LOG_FUNCTION_START("");
|
|
|
|
|
|
memset(pMultiRangingData, 0xFF,
|
|
sizeof(VL53LX_MultiRangingData_t));
|
|
|
|
|
|
Status = VL53LX_get_device_results(
|
|
Dev,
|
|
VL53LX_DEVICERESULTSLEVEL_FULL,
|
|
presults);
|
|
|
|
Status = SetMeasurementData(Dev,
|
|
presults,
|
|
pMultiRangingData);
|
|
|
|
LOG_FUNCTION_END(Status);
|
|
return Status;
|
|
}
|
|
|
|
VL53LX_Error VL53LX_GetAdditionalData(VL53LX_DEV Dev,
|
|
VL53LX_AdditionalData_t *pAdditionalData)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
|
|
LOG_FUNCTION_START("");
|
|
|
|
Status = VL53LX_get_additional_data(Dev, pAdditionalData);
|
|
|
|
LOG_FUNCTION_END(Status);
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VL53LX_Error VL53LX_SetTuningParameter(VL53LX_DEV Dev,
|
|
uint16_t TuningParameterId, int32_t TuningParameterValue)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
|
|
LOG_FUNCTION_START("");
|
|
|
|
if (TuningParameterId ==
|
|
VL53LX_TUNINGPARM_DYNXTALK_NODETECT_XTALK_OFFSET_KCPS)
|
|
return VL53LX_ERROR_INVALID_PARAMS;
|
|
|
|
if (TuningParameterId >= 32768)
|
|
Status = VL53LX_set_tuning_parm(Dev,
|
|
TuningParameterId,
|
|
TuningParameterValue);
|
|
else {
|
|
if (TuningParameterId < VL53LX_TUNING_MAX_TUNABLE_KEY)
|
|
BDTable[TuningParameterId] = TuningParameterValue;
|
|
else
|
|
Status = VL53LX_ERROR_INVALID_PARAMS;
|
|
}
|
|
|
|
LOG_FUNCTION_END(Status);
|
|
return Status;
|
|
}
|
|
|
|
VL53LX_Error VL53LX_GetTuningParameter(VL53LX_DEV Dev,
|
|
uint16_t TuningParameterId, int32_t *pTuningParameterValue)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
|
|
LOG_FUNCTION_START("");
|
|
|
|
if (TuningParameterId >= 32768)
|
|
Status = VL53LX_get_tuning_parm(Dev,
|
|
TuningParameterId,
|
|
pTuningParameterValue);
|
|
else {
|
|
if (TuningParameterId < VL53LX_TUNING_MAX_TUNABLE_KEY)
|
|
*pTuningParameterValue = BDTable[TuningParameterId];
|
|
else
|
|
Status = VL53LX_ERROR_INVALID_PARAMS;
|
|
}
|
|
|
|
LOG_FUNCTION_END(Status);
|
|
return Status;
|
|
}
|
|
|
|
|
|
VL53LX_Error VL53LX_PerformRefSpadManagement(VL53LX_DEV Dev)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
VL53LX_Error RawStatus;
|
|
uint8_t dcrbuffer[24];
|
|
uint8_t *commbuf;
|
|
uint8_t numloc[2] = {5, 3};
|
|
VL53LX_LLDriverData_t *pdev;
|
|
VL53LX_customer_nvm_managed_t *pc;
|
|
VL53LX_DistanceModes DistanceMode;
|
|
|
|
LOG_FUNCTION_START("");
|
|
|
|
pdev = VL53LXDevStructGetLLDriverHandle(Dev);
|
|
pc = &pdev->customer;
|
|
|
|
DistanceMode = VL53LXDevDataGet(Dev,
|
|
CurrentParameters.DistanceMode);
|
|
|
|
if (Status == VL53LX_ERROR_NONE)
|
|
Status = VL53LX_run_ref_spad_char(Dev, &RawStatus);
|
|
|
|
if (Status == VL53LX_WARNING_REF_SPAD_CHAR_RATE_TOO_HIGH) {
|
|
|
|
Status = VL53LX_read_nvm_raw_data(Dev,
|
|
(uint8_t)(0xA0 >> 2),
|
|
(uint8_t)(24 >> 2),
|
|
dcrbuffer);
|
|
|
|
if (Status == VL53LX_ERROR_NONE)
|
|
Status = VL53LX_WriteMulti(Dev,
|
|
VL53LX_REF_SPAD_MAN__NUM_REQUESTED_REF_SPADS,
|
|
numloc, 2);
|
|
|
|
if (Status == VL53LX_ERROR_NONE) {
|
|
pc->ref_spad_man__num_requested_ref_spads = numloc[0];
|
|
pc->ref_spad_man__ref_location = numloc[1];
|
|
}
|
|
|
|
commbuf = &dcrbuffer[16];
|
|
|
|
|
|
|
|
if (Status == VL53LX_ERROR_NONE)
|
|
Status = VL53LX_WriteMulti(Dev,
|
|
VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_REF_0,
|
|
commbuf, 6);
|
|
|
|
if (Status == VL53LX_ERROR_NONE) {
|
|
pc->global_config__spad_enables_ref_0 = commbuf[0];
|
|
pc->global_config__spad_enables_ref_1 = commbuf[1];
|
|
pc->global_config__spad_enables_ref_2 = commbuf[2];
|
|
pc->global_config__spad_enables_ref_3 = commbuf[3];
|
|
pc->global_config__spad_enables_ref_4 = commbuf[4];
|
|
pc->global_config__spad_enables_ref_5 = commbuf[5];
|
|
}
|
|
|
|
}
|
|
|
|
|
|
VL53LX_SetDistanceMode(Dev, DistanceMode);
|
|
|
|
LOG_FUNCTION_END(Status);
|
|
return Status;
|
|
}
|
|
|
|
|
|
VL53LX_Error VL53LX_SmudgeCorrectionEnable(VL53LX_DEV Dev,
|
|
VL53LX_SmudgeCorrectionModes Mode)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
VL53LX_Error s1 = VL53LX_ERROR_NONE;
|
|
VL53LX_Error s2 = VL53LX_ERROR_NONE;
|
|
VL53LX_Error s3 = VL53LX_ERROR_NONE;
|
|
|
|
LOG_FUNCTION_START("");
|
|
|
|
switch (Mode) {
|
|
case VL53LX_SMUDGE_CORRECTION_NONE:
|
|
s1 = VL53LX_dynamic_xtalk_correction_disable(Dev);
|
|
s2 = VL53LX_dynamic_xtalk_correction_apply_disable(Dev);
|
|
s3 = VL53LX_dynamic_xtalk_correction_single_apply_disable(Dev);
|
|
break;
|
|
case VL53LX_SMUDGE_CORRECTION_CONTINUOUS:
|
|
s1 = VL53LX_dynamic_xtalk_correction_enable(Dev);
|
|
s2 = VL53LX_dynamic_xtalk_correction_apply_enable(Dev);
|
|
s3 = VL53LX_dynamic_xtalk_correction_single_apply_disable(Dev);
|
|
break;
|
|
case VL53LX_SMUDGE_CORRECTION_SINGLE:
|
|
s1 = VL53LX_dynamic_xtalk_correction_enable(Dev);
|
|
s2 = VL53LX_dynamic_xtalk_correction_apply_enable(Dev);
|
|
s3 = VL53LX_dynamic_xtalk_correction_single_apply_enable(Dev);
|
|
break;
|
|
case VL53LX_SMUDGE_CORRECTION_DEBUG:
|
|
s1 = VL53LX_dynamic_xtalk_correction_enable(Dev);
|
|
s2 = VL53LX_dynamic_xtalk_correction_apply_disable(Dev);
|
|
s3 = VL53LX_dynamic_xtalk_correction_single_apply_disable(Dev);
|
|
break;
|
|
default:
|
|
Status = VL53LX_ERROR_INVALID_PARAMS;
|
|
break;
|
|
}
|
|
|
|
if (Status == VL53LX_ERROR_NONE) {
|
|
Status = s1;
|
|
if (Status == VL53LX_ERROR_NONE)
|
|
Status = s2;
|
|
if (Status == VL53LX_ERROR_NONE)
|
|
Status = s3;
|
|
}
|
|
|
|
LOG_FUNCTION_END(Status);
|
|
return Status;
|
|
}
|
|
|
|
|
|
VL53LX_Error VL53LX_SetXTalkCompensationEnable(VL53LX_DEV Dev,
|
|
uint8_t XTalkCompensationEnable)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
|
|
LOG_FUNCTION_START("");
|
|
|
|
if (XTalkCompensationEnable == 0)
|
|
Status = VL53LX_disable_xtalk_compensation(Dev);
|
|
else
|
|
Status = VL53LX_enable_xtalk_compensation(Dev);
|
|
|
|
LOG_FUNCTION_END(Status);
|
|
return Status;
|
|
}
|
|
|
|
|
|
VL53LX_Error VL53LX_GetXTalkCompensationEnable(VL53LX_DEV Dev,
|
|
uint8_t *pXTalkCompensationEnable)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
|
|
LOG_FUNCTION_START("");
|
|
|
|
VL53LX_get_xtalk_compensation_enable(
|
|
Dev,
|
|
pXTalkCompensationEnable);
|
|
|
|
LOG_FUNCTION_END(Status);
|
|
return Status;
|
|
}
|
|
|
|
VL53LX_Error VL53LX_PerformXTalkCalibration(VL53LX_DEV Dev)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
VL53LX_Error UStatus;
|
|
int16_t CalDistanceMm;
|
|
VL53LX_xtalk_calibration_results_t xtalk;
|
|
|
|
VL53LX_CalibrationData_t caldata;
|
|
VL53LX_LLDriverData_t *pLLData;
|
|
int i;
|
|
uint32_t *pPlaneOffsetKcps;
|
|
uint32_t Margin =
|
|
BDTable[VL53LX_TUNING_XTALK_FULL_ROI_BIN_SUM_MARGIN];
|
|
uint32_t DefaultOffset =
|
|
BDTable[VL53LX_TUNING_XTALK_FULL_ROI_DEFAULT_OFFSET];
|
|
uint32_t *pLLDataPlaneOffsetKcps;
|
|
uint32_t sum = 0;
|
|
uint8_t binok = 0;
|
|
VL53LX_DistanceModes DistanceMode;
|
|
uint32_t TimingBudgetMicroSeconds;
|
|
|
|
LOG_FUNCTION_START("");
|
|
|
|
Status = VL53LX_GetDistanceMode(Dev, &DistanceMode);
|
|
Status = VL53LX_GetMeasurementTimingBudgetMicroSeconds(Dev, &TimingBudgetMicroSeconds);
|
|
|
|
pPlaneOffsetKcps =
|
|
&caldata.customer.algo__crosstalk_compensation_plane_offset_kcps;
|
|
pLLData = VL53LXDevStructGetLLDriverHandle(Dev);
|
|
pLLDataPlaneOffsetKcps =
|
|
&pLLData->xtalk_cal.algo__crosstalk_compensation_plane_offset_kcps;
|
|
|
|
CalDistanceMm = (int16_t)
|
|
BDTable[VL53LX_TUNING_XTALK_FULL_ROI_TARGET_DISTANCE_MM];
|
|
Status = VL53LX_run_hist_xtalk_extraction(Dev, CalDistanceMm,
|
|
&UStatus);
|
|
|
|
VL53LX_GetCalibrationData(Dev, &caldata);
|
|
for (i = 0; i < VL53LX_XTALK_HISTO_BINS; i++) {
|
|
sum += caldata.xtalkhisto.xtalk_shape.bin_data[i];
|
|
if (caldata.xtalkhisto.xtalk_shape.bin_data[i] > 0)
|
|
binok++;
|
|
}
|
|
if ((UStatus ==
|
|
VL53LX_ERROR_XTALK_EXTRACTION_SIGMA_LIMIT_FAIL) ||
|
|
(sum > (1024 + Margin)) || (sum < (1024 - Margin)) ||
|
|
(binok < 3)) {
|
|
*pPlaneOffsetKcps = DefaultOffset;
|
|
*pLLDataPlaneOffsetKcps = DefaultOffset;
|
|
caldata.xtalkhisto.xtalk_shape.bin_data[0] = 307;
|
|
caldata.xtalkhisto.xtalk_shape.bin_data[1] = 410;
|
|
caldata.xtalkhisto.xtalk_shape.bin_data[2] = 410;
|
|
caldata.xtalkhisto.xtalk_shape.bin_data[3] = 307;
|
|
for (i = 4; i < VL53LX_XTALK_HISTO_BINS; i++)
|
|
caldata.xtalkhisto.xtalk_shape.bin_data[i] = 0;
|
|
for (i = 0; i < VL53LX_BIN_REC_SIZE; i++)
|
|
caldata.algo__xtalk_cpo_HistoMerge_kcps[i] =
|
|
DefaultOffset + DefaultOffset * i;
|
|
VL53LX_SetCalibrationData(Dev, &caldata);
|
|
}
|
|
|
|
if (Status == VL53LX_ERROR_NONE) {
|
|
Status = VL53LX_get_current_xtalk_settings(Dev, &xtalk);
|
|
Status = VL53LX_set_tuning_parm(Dev,
|
|
VL53LX_TUNINGPARM_DYNXTALK_NODETECT_XTALK_OFFSET_KCPS,
|
|
xtalk.algo__crosstalk_compensation_plane_offset_kcps);
|
|
}
|
|
|
|
Status = VL53LX_SetDistanceMode(Dev, DistanceMode);
|
|
Status = VL53LX_SetMeasurementTimingBudgetMicroSeconds(Dev, TimingBudgetMicroSeconds);
|
|
|
|
LOG_FUNCTION_END(Status);
|
|
return Status;
|
|
}
|
|
|
|
|
|
VL53LX_Error VL53LX_SetOffsetCorrectionMode(VL53LX_DEV Dev,
|
|
VL53LX_OffsetCorrectionModes OffsetCorrectionMode)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
VL53LX_OffsetCorrectionMode offset_cor_mode;
|
|
|
|
LOG_FUNCTION_START("");
|
|
|
|
if (OffsetCorrectionMode ==
|
|
VL53LX_OFFSETCORRECTIONMODE_PERVCSEL)
|
|
offset_cor_mode =
|
|
VL53LX_OFFSETCORRECTIONMODE__PER_VCSEL_OFFSETS;
|
|
else {
|
|
offset_cor_mode =
|
|
VL53LX_OFFSETCORRECTIONMODE__MM1_MM2_OFFSETS;
|
|
if (OffsetCorrectionMode !=
|
|
VL53LX_OFFSETCORRECTIONMODE_STANDARD)
|
|
Status = VL53LX_ERROR_INVALID_PARAMS;
|
|
}
|
|
|
|
if (Status == VL53LX_ERROR_NONE)
|
|
Status = VL53LX_set_offset_correction_mode(Dev,
|
|
offset_cor_mode);
|
|
|
|
LOG_FUNCTION_END(Status);
|
|
return Status;
|
|
}
|
|
|
|
|
|
VL53LX_Error VL53LX_PerformOffsetSimpleCalibration(VL53LX_DEV Dev,
|
|
int32_t CalDistanceMilliMeter)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
int32_t sum_ranging;
|
|
uint8_t offset_meas;
|
|
int16_t Max, UnderMax, OverMax, Repeat;
|
|
int32_t total_count, inloopcount;
|
|
int32_t IncRounding;
|
|
int16_t meanDistance_mm;
|
|
int16_t offset;
|
|
VL53LX_MultiRangingData_t RangingMeasurementData;
|
|
VL53LX_LLDriverData_t *pdev;
|
|
uint8_t goodmeas;
|
|
VL53LX_Error SmudgeStatus = VL53LX_ERROR_NONE;
|
|
uint8_t smudge_corr_en;
|
|
VL53LX_TargetRangeData_t *pRange;
|
|
|
|
LOG_FUNCTION_START("");
|
|
|
|
pdev = VL53LXDevStructGetLLDriverHandle(Dev);
|
|
|
|
smudge_corr_en = pdev->smudge_correct_config.smudge_corr_enabled;
|
|
SmudgeStatus = VL53LX_dynamic_xtalk_correction_disable(Dev);
|
|
|
|
pdev->customer.algo__part_to_part_range_offset_mm = 0;
|
|
pdev->customer.mm_config__inner_offset_mm = 0;
|
|
pdev->customer.mm_config__outer_offset_mm = 0;
|
|
memset(&pdev->per_vcsel_cal_data, 0, sizeof(pdev->per_vcsel_cal_data));
|
|
Repeat = BDTable[VL53LX_TUNING_SIMPLE_OFFSET_CALIBRATION_REPEAT];
|
|
Max = BDTable[
|
|
VL53LX_TUNING_MAX_SIMPLE_OFFSET_CALIBRATION_SAMPLE_NUMBER];
|
|
UnderMax = 1 + (Max / 2);
|
|
OverMax = Max + (Max / 2);
|
|
sum_ranging = 0;
|
|
total_count = 0;
|
|
|
|
while ((Repeat > 0) && (Status == VL53LX_ERROR_NONE)) {
|
|
Status = VL53LX_StartMeasurement(Dev);
|
|
|
|
if (Status == VL53LX_ERROR_NONE) {
|
|
VL53LX_WaitMeasurementDataReady(Dev);
|
|
VL53LX_GetMultiRangingData(Dev,
|
|
&RangingMeasurementData);
|
|
VL53LX_ClearInterruptAndStartMeasurement(Dev);
|
|
}
|
|
|
|
inloopcount = 0;
|
|
offset_meas = 0;
|
|
while ((Status == VL53LX_ERROR_NONE) && (inloopcount < Max) &&
|
|
(offset_meas < OverMax)) {
|
|
Status = VL53LX_WaitMeasurementDataReady(Dev);
|
|
if (Status == VL53LX_ERROR_NONE)
|
|
Status = VL53LX_GetMultiRangingData(Dev,
|
|
&RangingMeasurementData);
|
|
pRange = &(RangingMeasurementData.RangeData[0]);
|
|
goodmeas = (pRange->RangeStatus ==
|
|
VL53LX_RANGESTATUS_RANGE_VALID);
|
|
if ((Status == VL53LX_ERROR_NONE) && goodmeas) {
|
|
sum_ranging += pRange->RangeMilliMeter;
|
|
inloopcount++;
|
|
}
|
|
Status = VL53LX_ClearInterruptAndStartMeasurement(Dev);
|
|
offset_meas++;
|
|
}
|
|
total_count += inloopcount;
|
|
|
|
|
|
if (inloopcount < UnderMax)
|
|
Status = VL53LX_ERROR_OFFSET_CAL_NO_SAMPLE_FAIL;
|
|
|
|
VL53LX_StopMeasurement(Dev);
|
|
|
|
Repeat--;
|
|
|
|
}
|
|
|
|
if ((SmudgeStatus == VL53LX_ERROR_NONE) && (smudge_corr_en == 1))
|
|
SmudgeStatus = VL53LX_dynamic_xtalk_correction_enable(Dev);
|
|
|
|
if ((sum_ranging < 0) ||
|
|
(sum_ranging > ((int32_t) total_count * 0xffff)))
|
|
Status = VL53LX_WARNING_OFFSET_CAL_SIGMA_TOO_HIGH;
|
|
|
|
if ((Status == VL53LX_ERROR_NONE) && (total_count > 0)) {
|
|
IncRounding = total_count / 2;
|
|
meanDistance_mm = (int16_t)((sum_ranging + IncRounding)
|
|
/ total_count);
|
|
offset = (int16_t)CalDistanceMilliMeter - meanDistance_mm;
|
|
pdev->customer.algo__part_to_part_range_offset_mm = 0;
|
|
pdev->customer.mm_config__inner_offset_mm = offset;
|
|
pdev->customer.mm_config__outer_offset_mm = offset;
|
|
|
|
Status = VL53LX_set_customer_nvm_managed(Dev,
|
|
&(pdev->customer));
|
|
}
|
|
|
|
LOG_FUNCTION_END(Status);
|
|
return Status;
|
|
}
|
|
|
|
VL53LX_Error VL53LX_PerformOffsetZeroDistanceCalibration(VL53LX_DEV Dev)
|
|
{
|
|
#define START_OFFSET 50
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
int32_t sum_ranging;
|
|
uint8_t offset_meas;
|
|
int16_t Max, UnderMax, OverMax, Repeat;
|
|
int32_t total_count, inloopcount;
|
|
int32_t IncRounding;
|
|
int16_t meanDistance_mm;
|
|
int16_t offset, ZeroDistanceOffset;
|
|
VL53LX_MultiRangingData_t RangingMeasurementData;
|
|
VL53LX_LLDriverData_t *pdev;
|
|
uint8_t goodmeas;
|
|
VL53LX_Error SmudgeStatus = VL53LX_ERROR_NONE;
|
|
uint8_t smudge_corr_en;
|
|
VL53LX_TargetRangeData_t *pRange;
|
|
|
|
LOG_FUNCTION_START("");
|
|
|
|
pdev = VL53LXDevStructGetLLDriverHandle(Dev);
|
|
smudge_corr_en = pdev->smudge_correct_config.smudge_corr_enabled;
|
|
SmudgeStatus = VL53LX_dynamic_xtalk_correction_disable(Dev);
|
|
pdev->customer.algo__part_to_part_range_offset_mm = 0;
|
|
pdev->customer.mm_config__inner_offset_mm = START_OFFSET;
|
|
pdev->customer.mm_config__outer_offset_mm = START_OFFSET;
|
|
memset(&pdev->per_vcsel_cal_data, 0, sizeof(pdev->per_vcsel_cal_data));
|
|
ZeroDistanceOffset = BDTable[
|
|
VL53LX_TUNING_ZERO_DISTANCE_OFFSET_NON_LINEAR_FACTOR];
|
|
Repeat = BDTable[VL53LX_TUNING_SIMPLE_OFFSET_CALIBRATION_REPEAT];
|
|
Max =
|
|
BDTable[VL53LX_TUNING_MAX_SIMPLE_OFFSET_CALIBRATION_SAMPLE_NUMBER];
|
|
UnderMax = 1 + (Max / 2);
|
|
OverMax = Max + (Max / 2);
|
|
sum_ranging = 0;
|
|
total_count = 0;
|
|
|
|
while ((Repeat > 0) && (Status == VL53LX_ERROR_NONE)) {
|
|
Status = VL53LX_StartMeasurement(Dev);
|
|
if (Status == VL53LX_ERROR_NONE) {
|
|
VL53LX_WaitMeasurementDataReady(Dev);
|
|
VL53LX_GetMultiRangingData(Dev,
|
|
&RangingMeasurementData);
|
|
VL53LX_ClearInterruptAndStartMeasurement(Dev);
|
|
}
|
|
inloopcount = 0;
|
|
offset_meas = 0;
|
|
while ((Status == VL53LX_ERROR_NONE) && (inloopcount < Max) &&
|
|
(offset_meas < OverMax)) {
|
|
Status = VL53LX_WaitMeasurementDataReady(Dev);
|
|
if (Status == VL53LX_ERROR_NONE)
|
|
Status = VL53LX_GetMultiRangingData(Dev,
|
|
&RangingMeasurementData);
|
|
pRange = &(RangingMeasurementData.RangeData[0]);
|
|
goodmeas = (pRange->RangeStatus ==
|
|
VL53LX_RANGESTATUS_RANGE_VALID);
|
|
if ((Status == VL53LX_ERROR_NONE) && goodmeas) {
|
|
sum_ranging = sum_ranging +
|
|
pRange->RangeMilliMeter;
|
|
inloopcount++;
|
|
}
|
|
Status = VL53LX_ClearInterruptAndStartMeasurement(Dev);
|
|
offset_meas++;
|
|
}
|
|
total_count += inloopcount;
|
|
if (inloopcount < UnderMax)
|
|
Status = VL53LX_ERROR_OFFSET_CAL_NO_SAMPLE_FAIL;
|
|
VL53LX_StopMeasurement(Dev);
|
|
Repeat--;
|
|
}
|
|
if ((SmudgeStatus == VL53LX_ERROR_NONE) && (smudge_corr_en == 1))
|
|
SmudgeStatus = VL53LX_dynamic_xtalk_correction_enable(Dev);
|
|
if ((sum_ranging < 0) ||
|
|
(sum_ranging > ((int32_t) total_count * 0xffff)))
|
|
Status = VL53LX_WARNING_OFFSET_CAL_SIGMA_TOO_HIGH;
|
|
|
|
if ((Status == VL53LX_ERROR_NONE) && (total_count > 0)) {
|
|
IncRounding = total_count / 2;
|
|
meanDistance_mm = (int16_t)
|
|
((sum_ranging + IncRounding) / total_count);
|
|
offset = START_OFFSET - meanDistance_mm + ZeroDistanceOffset;
|
|
pdev->customer.algo__part_to_part_range_offset_mm = 0;
|
|
pdev->customer.mm_config__inner_offset_mm = offset;
|
|
pdev->customer.mm_config__outer_offset_mm = offset;
|
|
Status = VL53LX_set_customer_nvm_managed(Dev,
|
|
&(pdev->customer));
|
|
}
|
|
|
|
LOG_FUNCTION_END(Status);
|
|
return Status;
|
|
}
|
|
|
|
VL53LX_Error VL53LX_SetCalibrationData(VL53LX_DEV Dev,
|
|
VL53LX_CalibrationData_t *pCalibrationData)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
VL53LX_CustomerNvmManaged_t *pC;
|
|
VL53LX_calibration_data_t cal_data;
|
|
uint32_t x;
|
|
VL53LX_xtalk_calibration_results_t xtalk;
|
|
|
|
LOG_FUNCTION_START("");
|
|
|
|
cal_data.struct_version = pCalibrationData->struct_version -
|
|
VL53LX_ADDITIONAL_CALIBRATION_DATA_STRUCT_VERSION;
|
|
|
|
|
|
memcpy(
|
|
&(cal_data.add_off_cal_data),
|
|
&(pCalibrationData->add_off_cal_data),
|
|
sizeof(VL53LX_additional_offset_cal_data_t));
|
|
|
|
|
|
memcpy(
|
|
&(cal_data.optical_centre),
|
|
&(pCalibrationData->optical_centre),
|
|
sizeof(VL53LX_optical_centre_t));
|
|
|
|
|
|
memcpy(
|
|
&(cal_data.xtalkhisto),
|
|
&(pCalibrationData->xtalkhisto),
|
|
sizeof(VL53LX_xtalk_histogram_data_t));
|
|
|
|
|
|
memcpy(
|
|
&(cal_data.gain_cal),
|
|
&(pCalibrationData->gain_cal),
|
|
sizeof(VL53LX_gain_calibration_data_t));
|
|
|
|
|
|
memcpy(
|
|
&(cal_data.cal_peak_rate_map),
|
|
&(pCalibrationData->cal_peak_rate_map),
|
|
sizeof(VL53LX_cal_peak_rate_map_t));
|
|
|
|
|
|
memcpy(
|
|
&(cal_data.per_vcsel_cal_data),
|
|
&(pCalibrationData->per_vcsel_cal_data),
|
|
sizeof(VL53LX_per_vcsel_period_offset_cal_data_t));
|
|
|
|
pC = &pCalibrationData->customer;
|
|
x = pC->algo__crosstalk_compensation_plane_offset_kcps;
|
|
cal_data.customer.algo__crosstalk_compensation_plane_offset_kcps =
|
|
(uint16_t)(x&0x0000FFFF);
|
|
|
|
cal_data.customer.global_config__spad_enables_ref_0 =
|
|
pC->global_config__spad_enables_ref_0;
|
|
cal_data.customer.global_config__spad_enables_ref_1 =
|
|
pC->global_config__spad_enables_ref_1;
|
|
cal_data.customer.global_config__spad_enables_ref_2 =
|
|
pC->global_config__spad_enables_ref_2;
|
|
cal_data.customer.global_config__spad_enables_ref_3 =
|
|
pC->global_config__spad_enables_ref_3;
|
|
cal_data.customer.global_config__spad_enables_ref_4 =
|
|
pC->global_config__spad_enables_ref_4;
|
|
cal_data.customer.global_config__spad_enables_ref_5 =
|
|
pC->global_config__spad_enables_ref_5;
|
|
cal_data.customer.global_config__ref_en_start_select =
|
|
pC->global_config__ref_en_start_select;
|
|
cal_data.customer.ref_spad_man__num_requested_ref_spads =
|
|
pC->ref_spad_man__num_requested_ref_spads;
|
|
cal_data.customer.ref_spad_man__ref_location =
|
|
pC->ref_spad_man__ref_location;
|
|
cal_data.customer.algo__crosstalk_compensation_x_plane_gradient_kcps =
|
|
pC->algo__crosstalk_compensation_x_plane_gradient_kcps;
|
|
cal_data.customer.algo__crosstalk_compensation_y_plane_gradient_kcps =
|
|
pC->algo__crosstalk_compensation_y_plane_gradient_kcps;
|
|
cal_data.customer.ref_spad_char__total_rate_target_mcps =
|
|
pC->ref_spad_char__total_rate_target_mcps;
|
|
cal_data.customer.algo__part_to_part_range_offset_mm =
|
|
pC->algo__part_to_part_range_offset_mm;
|
|
cal_data.customer.mm_config__inner_offset_mm =
|
|
pC->mm_config__inner_offset_mm;
|
|
cal_data.customer.mm_config__outer_offset_mm =
|
|
pC->mm_config__outer_offset_mm;
|
|
|
|
Status = VL53LX_set_part_to_part_data(Dev, &cal_data);
|
|
|
|
if (Status != VL53LX_ERROR_NONE)
|
|
goto ENDFUNC;
|
|
|
|
Status = VL53LX_get_current_xtalk_settings(Dev, &xtalk);
|
|
|
|
if (Status != VL53LX_ERROR_NONE)
|
|
goto ENDFUNC;
|
|
|
|
xtalk.algo__crosstalk_compensation_plane_offset_kcps = x;
|
|
|
|
Status = VL53LX_set_tuning_parm(Dev,
|
|
VL53LX_TUNINGPARM_DYNXTALK_NODETECT_XTALK_OFFSET_KCPS,
|
|
x);
|
|
|
|
|
|
memcpy(
|
|
&(xtalk.algo__xtalk_cpo_HistoMerge_kcps[0]),
|
|
&(pCalibrationData->algo__xtalk_cpo_HistoMerge_kcps[0]),
|
|
sizeof(pCalibrationData->algo__xtalk_cpo_HistoMerge_kcps));
|
|
|
|
Status = VL53LX_set_current_xtalk_settings(Dev, &xtalk);
|
|
|
|
ENDFUNC:
|
|
LOG_FUNCTION_END(Status);
|
|
return Status;
|
|
|
|
}
|
|
|
|
VL53LX_Error VL53LX_GetCalibrationData(VL53LX_DEV Dev,
|
|
VL53LX_CalibrationData_t *pCalibrationData)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
VL53LX_calibration_data_t cal_data;
|
|
VL53LX_CustomerNvmManaged_t *pC;
|
|
VL53LX_customer_nvm_managed_t *pC2;
|
|
VL53LX_xtalk_calibration_results_t xtalk;
|
|
uint32_t tmp;
|
|
|
|
LOG_FUNCTION_START("");
|
|
|
|
|
|
Status = VL53LX_get_part_to_part_data(Dev, &cal_data);
|
|
|
|
pCalibrationData->struct_version = cal_data.struct_version +
|
|
VL53LX_ADDITIONAL_CALIBRATION_DATA_STRUCT_VERSION;
|
|
|
|
|
|
memcpy(
|
|
&(pCalibrationData->add_off_cal_data),
|
|
&(cal_data.add_off_cal_data),
|
|
sizeof(VL53LX_additional_offset_cal_data_t));
|
|
|
|
|
|
memcpy(
|
|
&(pCalibrationData->optical_centre),
|
|
&(cal_data.optical_centre),
|
|
sizeof(VL53LX_optical_centre_t));
|
|
|
|
|
|
memcpy(
|
|
&(pCalibrationData->xtalkhisto),
|
|
&(cal_data.xtalkhisto),
|
|
sizeof(VL53LX_xtalk_histogram_data_t));
|
|
|
|
memcpy(
|
|
&(pCalibrationData->gain_cal),
|
|
&(cal_data.gain_cal),
|
|
sizeof(VL53LX_gain_calibration_data_t));
|
|
|
|
|
|
memcpy(
|
|
&(pCalibrationData->cal_peak_rate_map),
|
|
&(cal_data.cal_peak_rate_map),
|
|
sizeof(VL53LX_cal_peak_rate_map_t));
|
|
|
|
|
|
memcpy(
|
|
&(pCalibrationData->per_vcsel_cal_data),
|
|
&(cal_data.per_vcsel_cal_data),
|
|
sizeof(VL53LX_per_vcsel_period_offset_cal_data_t));
|
|
|
|
pC = &pCalibrationData->customer;
|
|
pC2 = &cal_data.customer;
|
|
pC->global_config__spad_enables_ref_0 =
|
|
pC2->global_config__spad_enables_ref_0;
|
|
pC->global_config__spad_enables_ref_1 =
|
|
pC2->global_config__spad_enables_ref_1;
|
|
pC->global_config__spad_enables_ref_2 =
|
|
pC2->global_config__spad_enables_ref_2;
|
|
pC->global_config__spad_enables_ref_3 =
|
|
pC2->global_config__spad_enables_ref_3;
|
|
pC->global_config__spad_enables_ref_4 =
|
|
pC2->global_config__spad_enables_ref_4;
|
|
pC->global_config__spad_enables_ref_5 =
|
|
pC2->global_config__spad_enables_ref_5;
|
|
pC->global_config__ref_en_start_select =
|
|
pC2->global_config__ref_en_start_select;
|
|
pC->ref_spad_man__num_requested_ref_spads =
|
|
pC2->ref_spad_man__num_requested_ref_spads;
|
|
pC->ref_spad_man__ref_location =
|
|
pC2->ref_spad_man__ref_location;
|
|
pC->algo__crosstalk_compensation_x_plane_gradient_kcps =
|
|
pC2->algo__crosstalk_compensation_x_plane_gradient_kcps;
|
|
pC->algo__crosstalk_compensation_y_plane_gradient_kcps =
|
|
pC2->algo__crosstalk_compensation_y_plane_gradient_kcps;
|
|
pC->ref_spad_char__total_rate_target_mcps =
|
|
pC2->ref_spad_char__total_rate_target_mcps;
|
|
pC->algo__part_to_part_range_offset_mm =
|
|
pC2->algo__part_to_part_range_offset_mm;
|
|
pC->mm_config__inner_offset_mm =
|
|
pC2->mm_config__inner_offset_mm;
|
|
pC->mm_config__outer_offset_mm =
|
|
pC2->mm_config__outer_offset_mm;
|
|
|
|
pC->algo__crosstalk_compensation_plane_offset_kcps =
|
|
(uint32_t)(
|
|
pC2->algo__crosstalk_compensation_plane_offset_kcps);
|
|
|
|
Status = VL53LX_get_current_xtalk_settings(Dev, &xtalk);
|
|
|
|
if (Status != VL53LX_ERROR_NONE)
|
|
goto ENDFUNC;
|
|
|
|
tmp = xtalk.algo__crosstalk_compensation_plane_offset_kcps;
|
|
pC->algo__crosstalk_compensation_plane_offset_kcps = tmp;
|
|
tmp = xtalk.algo__crosstalk_compensation_x_plane_gradient_kcps;
|
|
pC->algo__crosstalk_compensation_x_plane_gradient_kcps = tmp;
|
|
tmp = xtalk.algo__crosstalk_compensation_y_plane_gradient_kcps;
|
|
pC->algo__crosstalk_compensation_y_plane_gradient_kcps = tmp;
|
|
|
|
memcpy(&(pCalibrationData->algo__xtalk_cpo_HistoMerge_kcps[0]),
|
|
&(xtalk.algo__xtalk_cpo_HistoMerge_kcps[0]),
|
|
sizeof(pCalibrationData->algo__xtalk_cpo_HistoMerge_kcps));
|
|
ENDFUNC:
|
|
LOG_FUNCTION_END(Status);
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
VL53LX_Error VL53LX_PerformOffsetPerVcselCalibration(VL53LX_DEV Dev,
|
|
int32_t CalDistanceMilliMeter)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
int32_t sum_ranging_range_A, sum_ranging_range_B;
|
|
uint8_t offset_meas_range_A, offset_meas_range_B;
|
|
int16_t Max, UnderMax, OverMax, Repeat;
|
|
int32_t inloopcount;
|
|
int32_t IncRounding;
|
|
int16_t meanDistance_mm;
|
|
VL53LX_MultiRangingData_t RangingMeasurementData;
|
|
VL53LX_LLDriverData_t *pdev;
|
|
uint8_t goodmeas;
|
|
VL53LX_DistanceModes currentDist;
|
|
VL53LX_DistanceModes DistMode[3] = {VL53LX_DISTANCEMODE_SHORT,
|
|
VL53LX_DISTANCEMODE_MEDIUM, VL53LX_DISTANCEMODE_LONG};
|
|
int16_t offsetA[3] = {0, 0, 0};
|
|
int16_t offsetB[3] = {0, 0, 0};
|
|
|
|
VL53LX_Error SmudgeStatus = VL53LX_ERROR_NONE;
|
|
uint8_t smudge_corr_en, ics;
|
|
VL53LX_TargetRangeData_t *pRange;
|
|
|
|
LOG_FUNCTION_START("");
|
|
|
|
pdev = VL53LXDevStructGetLLDriverHandle(Dev);
|
|
|
|
smudge_corr_en = pdev->smudge_correct_config.smudge_corr_enabled;
|
|
SmudgeStatus = VL53LX_dynamic_xtalk_correction_disable(Dev);
|
|
|
|
pdev->customer.algo__part_to_part_range_offset_mm = 0;
|
|
pdev->customer.mm_config__inner_offset_mm = 0;
|
|
pdev->customer.mm_config__outer_offset_mm = 0;
|
|
pdev->customer.mm_config__outer_offset_mm = 0;
|
|
memset(&pdev->per_vcsel_cal_data, 0, sizeof(pdev->per_vcsel_cal_data));
|
|
|
|
Repeat = 0;
|
|
if (IsL4(Dev))
|
|
Repeat = 1;
|
|
Max = 2 * BDTable[
|
|
VL53LX_TUNING_MAX_SIMPLE_OFFSET_CALIBRATION_SAMPLE_NUMBER];
|
|
UnderMax = 1 + (Max / 2);
|
|
OverMax = Max + (Max / 2);
|
|
|
|
Status = VL53LX_GetDistanceMode(Dev, ¤tDist);
|
|
|
|
while ((Repeat < 3) && (Status == VL53LX_ERROR_NONE)) {
|
|
Status = VL53LX_SetDistanceMode(Dev, DistMode[Repeat]);
|
|
Status = VL53LX_StartMeasurement(Dev);
|
|
|
|
if (Status == VL53LX_ERROR_NONE) {
|
|
VL53LX_WaitMeasurementDataReady(Dev);
|
|
VL53LX_GetMultiRangingData(Dev,
|
|
&RangingMeasurementData);
|
|
VL53LX_ClearInterruptAndStartMeasurement(Dev);
|
|
}
|
|
|
|
inloopcount = 0;
|
|
offset_meas_range_A = 0;
|
|
sum_ranging_range_A = 0;
|
|
offset_meas_range_B = 0;
|
|
sum_ranging_range_B = 0;
|
|
while ((Status == VL53LX_ERROR_NONE) && (inloopcount < Max) &&
|
|
(inloopcount < OverMax)) {
|
|
Status = VL53LX_WaitMeasurementDataReady(Dev);
|
|
if (Status == VL53LX_ERROR_NONE)
|
|
Status = VL53LX_GetMultiRangingData(Dev,
|
|
&RangingMeasurementData);
|
|
pRange = &(RangingMeasurementData.RangeData[0]);
|
|
goodmeas = (pRange->RangeStatus ==
|
|
VL53LX_RANGESTATUS_RANGE_VALID);
|
|
ics = pdev->ll_state.cfg_internal_stream_count;
|
|
if ((Status == VL53LX_ERROR_NONE) && goodmeas) {
|
|
if (ics & 0x01) {
|
|
sum_ranging_range_A +=
|
|
pRange->RangeMilliMeter;
|
|
offset_meas_range_A++;
|
|
} else {
|
|
sum_ranging_range_B +=
|
|
pRange->RangeMilliMeter;
|
|
offset_meas_range_B++;
|
|
}
|
|
inloopcount = offset_meas_range_A +
|
|
offset_meas_range_B;
|
|
}
|
|
Status = VL53LX_ClearInterruptAndStartMeasurement(Dev);
|
|
}
|
|
|
|
|
|
if (inloopcount < UnderMax)
|
|
Status = VL53LX_ERROR_OFFSET_CAL_NO_SAMPLE_FAIL;
|
|
|
|
VL53LX_StopMeasurement(Dev);
|
|
|
|
|
|
if ((sum_ranging_range_A < 0) ||
|
|
(sum_ranging_range_B < 0) ||
|
|
(sum_ranging_range_A >
|
|
((int32_t) offset_meas_range_A * 0xffff)) ||
|
|
(sum_ranging_range_B >
|
|
((int32_t) offset_meas_range_B * 0xffff))) {
|
|
Status = VL53LX_WARNING_OFFSET_CAL_SIGMA_TOO_HIGH;
|
|
}
|
|
|
|
if ((Status == VL53LX_ERROR_NONE) &&
|
|
(offset_meas_range_A > 0)) {
|
|
IncRounding = offset_meas_range_A / 2;
|
|
meanDistance_mm = (int16_t)
|
|
((sum_ranging_range_A + IncRounding)
|
|
/ offset_meas_range_A);
|
|
offsetA[Repeat] = (int16_t)
|
|
CalDistanceMilliMeter - meanDistance_mm;
|
|
}
|
|
|
|
if ((Status == VL53LX_ERROR_NONE) &&
|
|
(offset_meas_range_B > 0)) {
|
|
IncRounding = offset_meas_range_B / 2;
|
|
meanDistance_mm = (int16_t)
|
|
((sum_ranging_range_B + IncRounding)
|
|
/ offset_meas_range_B);
|
|
offsetB[Repeat] = (int16_t)
|
|
CalDistanceMilliMeter - meanDistance_mm;
|
|
}
|
|
Repeat++;
|
|
}
|
|
|
|
if ((SmudgeStatus == VL53LX_ERROR_NONE) && (smudge_corr_en == 1))
|
|
SmudgeStatus = VL53LX_dynamic_xtalk_correction_enable(Dev);
|
|
|
|
if (Status == VL53LX_ERROR_NONE) {
|
|
pdev->per_vcsel_cal_data.short_a_offset_mm = offsetA[0];
|
|
pdev->per_vcsel_cal_data.short_b_offset_mm = offsetB[0];
|
|
pdev->per_vcsel_cal_data.medium_a_offset_mm = offsetA[1];
|
|
pdev->per_vcsel_cal_data.medium_b_offset_mm = offsetB[1];
|
|
pdev->per_vcsel_cal_data.long_a_offset_mm = offsetA[2];
|
|
pdev->per_vcsel_cal_data.long_b_offset_mm = offsetB[2];
|
|
}
|
|
|
|
VL53LX_SetDistanceMode(Dev, currentDist);
|
|
|
|
LOG_FUNCTION_END(Status);
|
|
return Status;
|
|
}
|
|
|
|
VL53LX_Error VL53LX_GetOpticalCenter(VL53LX_DEV Dev,
|
|
FixPoint1616_t *pOpticalCenterX,
|
|
FixPoint1616_t *pOpticalCenterY)
|
|
{
|
|
VL53LX_Error Status = VL53LX_ERROR_NONE;
|
|
VL53LX_calibration_data_t CalibrationData;
|
|
|
|
LOG_FUNCTION_START("");
|
|
|
|
*pOpticalCenterX = 0;
|
|
*pOpticalCenterY = 0;
|
|
Status = VL53LX_get_part_to_part_data(Dev, &CalibrationData);
|
|
if (Status == VL53LX_ERROR_NONE) {
|
|
*pOpticalCenterX = VL53LX_FIXPOINT44TOFIXPOINT1616(
|
|
CalibrationData.optical_centre.x_centre);
|
|
*pOpticalCenterY = VL53LX_FIXPOINT44TOFIXPOINT1616(
|
|
CalibrationData.optical_centre.y_centre);
|
|
}
|
|
|
|
LOG_FUNCTION_END(Status);
|
|
return Status;
|
|
}
|
|
|
|
|