| /* |
| * vl53l0x_api.c - Linux kernel modules for |
| * STM VL53L0 FlightSense TOF sensor |
| * |
| * Copyright (C) 2016 STMicroelectronics Imaging Division. |
| * Copyright (c) 2018, The Linux Foundation. All rights reserved. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| */ |
| |
| #include "vl53l0x_api.h" |
| #include "vl53l0x_tuning.h" |
| #include "vl53l0x_interrupt_threshold_settings.h" |
| #include "vl53l0x_api_core.h" |
| #include "vl53l0x_api_calibration.h" |
| #include "vl53l0x_api_strings.h" |
| |
| #ifndef __KERNEL__ |
| #include <stdlib.h> |
| #endif |
| #define LOG_FUNCTION_START(fmt, ...) \ |
| _LOG_FUNCTION_START(TRACE_MODULE_API, fmt, ##__VA_ARGS__) |
| #define LOG_FUNCTION_END(status, ...) \ |
| _LOG_FUNCTION_END(TRACE_MODULE_API, status, ##__VA_ARGS__) |
| #define LOG_FUNCTION_END_FMT(status, fmt, ...) \ |
| _LOG_FUNCTION_END_FMT(TRACE_MODULE_API, status, fmt, ##__VA_ARGS__) |
| |
| #ifdef VL_LOG_ENABLE |
| #define trace_print(level, ...) trace_print_module_function(TRACE_MODULE_API, \ |
| level, TRACE_FUNCTION_NONE, ##__VA_ARGS__) |
| #endif |
| |
| /* Group PAL General Functions */ |
| |
| int8_t VL_GetVersion(struct VL_Version_t *pVersion) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| pVersion->major = VL_IMPLEMENTATION_VER_MAJOR; |
| pVersion->minor = VL_IMPLEMENTATION_VER_MINOR; |
| pVersion->build = VL_IMPLEMENTATION_VER_SUB; |
| |
| pVersion->revision = VL_IMPLEMENTATION_VER_REVISION; |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetPalSpecVersion(struct VL_Version_t *pPalSpecVersion) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| pPalSpecVersion->major = VL_SPECIFICATION_VER_MAJOR; |
| pPalSpecVersion->minor = VL_SPECIFICATION_VER_MINOR; |
| pPalSpecVersion->build = VL_SPECIFICATION_VER_SUB; |
| |
| pPalSpecVersion->revision = VL_SPECIFICATION_VER_REVISION; |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetProductRevision(struct vl_data *Dev, |
| uint8_t *pProductRevisionMajor, uint8_t *pProductRevisionMinor) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| uint8_t revision_id; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_RdByte(Dev, VL_REG_IDENTIFICATION_REVISION_ID, |
| &revision_id); |
| *pProductRevisionMajor = 1; |
| *pProductRevisionMinor = (revision_id & 0xF0) >> 4; |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| |
| } |
| |
| int8_t VL_GetDeviceInfo(struct vl_data *Dev, |
| struct VL_DeviceInfo_t *pVL_DeviceInfo) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_get_device_info(Dev, pVL_DeviceInfo); |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetDeviceErrorStatus(struct vl_data *Dev, |
| uint8_t *pDeviceErrorStatus) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| uint8_t RangeStatus; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_RdByte(Dev, VL_REG_RESULT_RANGE_STATUS, |
| &RangeStatus); |
| |
| *pDeviceErrorStatus = (uint8_t)((RangeStatus & 0x78) >> 3); |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| |
| int8_t VL_GetDeviceErrorString(uint8_t ErrorCode, |
| char *pDeviceErrorString) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_get_device_error_string(ErrorCode, pDeviceErrorString); |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetRangeStatusString(uint8_t RangeStatus, |
| char *pRangeStatusString) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_get_range_status_string(RangeStatus, |
| pRangeStatusString); |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetPalErrorString(int8_t PalErrorCode, |
| char *pPalErrorString) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_get_pal_error_string(PalErrorCode, pPalErrorString); |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetPalStateString(uint8_t PalStateCode, |
| char *pPalStateString) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_get_pal_state_string(PalStateCode, pPalStateString); |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetPalState(struct vl_data *Dev, uint8_t *pPalState) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| *pPalState = PALDevDataGet(Dev, PalState); |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_SetPowerMode(struct vl_data *Dev, |
| uint8_t PowerMode) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| /* Only level1 of Power mode exists */ |
| if ((PowerMode != VL_POWERMODE_STANDBY_LEVEL1) |
| && (PowerMode != VL_POWERMODE_IDLE_LEVEL1)) { |
| Status = VL_ERROR_MODE_NOT_SUPPORTED; |
| } else if (PowerMode == VL_POWERMODE_STANDBY_LEVEL1) { |
| /* set the standby level1 of power mode */ |
| Status = VL_WrByte(Dev, 0x80, 0x00); |
| if (Status == VL_ERROR_NONE) { |
| /* Set PAL State to standby */ |
| PALDevDataSet(Dev, PalState, VL_STATE_STANDBY); |
| PALDevDataSet(Dev, PowerMode, |
| VL_POWERMODE_STANDBY_LEVEL1); |
| } |
| |
| } else { |
| /* VL_POWERMODE_IDLE_LEVEL1 */ |
| Status = VL_WrByte(Dev, 0x80, 0x00); |
| if (Status == VL_ERROR_NONE) |
| Status = VL_StaticInit(Dev); |
| |
| if (Status == VL_ERROR_NONE) |
| PALDevDataSet(Dev, PowerMode, |
| VL_POWERMODE_IDLE_LEVEL1); |
| |
| } |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetPowerMode(struct vl_data *Dev, |
| uint8_t *pPowerMode) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| uint8_t Byte; |
| |
| LOG_FUNCTION_START(""); |
| |
| /* Only level1 of Power mode exists */ |
| Status = VL_RdByte(Dev, 0x80, &Byte); |
| |
| if (Status == VL_ERROR_NONE) { |
| if (Byte == 1) { |
| PALDevDataSet(Dev, PowerMode, |
| VL_POWERMODE_IDLE_LEVEL1); |
| } else { |
| PALDevDataSet(Dev, PowerMode, |
| VL_POWERMODE_STANDBY_LEVEL1); |
| } |
| } |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_SetOffsetCalibrationDataMicroMeter(struct vl_data *Dev, |
| int32_t OffsetCalibrationDataMicroMeter) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_set_offset_calibration_data_micro_meter(Dev, |
| OffsetCalibrationDataMicroMeter); |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetOffsetCalibrationDataMicroMeter(struct vl_data *Dev, |
| int32_t *pOffsetCalibrationDataMicroMeter) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_get_offset_calibration_data_micro_meter(Dev, |
| pOffsetCalibrationDataMicroMeter); |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_SetLinearityCorrectiveGain(struct vl_data *Dev, |
| int16_t LinearityCorrectiveGain) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| if ((LinearityCorrectiveGain < 0) || (LinearityCorrectiveGain > 1000)) |
| Status = VL_ERROR_INVALID_PARAMS; |
| else { |
| PALDevDataSet(Dev, LinearityCorrectiveGain, |
| LinearityCorrectiveGain); |
| |
| if (LinearityCorrectiveGain != 1000) { |
| /* Disable FW Xtalk */ |
| Status = VL_WrWord(Dev, |
| VL_REG_CROSSTALK_COMPENSATION_PEAK_RATE_MCPS, 0); |
| } |
| } |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetLinearityCorrectiveGain(struct vl_data *Dev, |
| uint16_t *pLinearityCorrectiveGain) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| *pLinearityCorrectiveGain = PALDevDataGet(Dev, LinearityCorrectiveGain); |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_SetGroupParamHold(struct vl_data *Dev, uint8_t GroupParamHold) |
| { |
| int8_t Status = VL_ERROR_NOT_IMPLEMENTED; |
| |
| LOG_FUNCTION_START(""); |
| |
| /* not implemented on VL53L0X */ |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetUpperLimitMilliMeter(struct vl_data *Dev, |
| uint16_t *pUpperLimitMilliMeter) |
| { |
| int8_t Status = VL_ERROR_NOT_IMPLEMENTED; |
| |
| LOG_FUNCTION_START(""); |
| |
| /* not implemented on VL53L0X */ |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetTotalSignalRate(struct vl_data *Dev, |
| unsigned int *pTotalSignalRate) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| struct VL_RangingMeasurementData_t LastRangeDataBuffer; |
| |
| LOG_FUNCTION_START(""); |
| |
| LastRangeDataBuffer = PALDevDataGet(Dev, LastRangeMeasure); |
| |
| Status = VL_get_total_signal_rate( |
| Dev, &LastRangeDataBuffer, pTotalSignalRate); |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| /* End Group PAL General Functions */ |
| |
| /* Group PAL Init Functions */ |
| int8_t VL_SetDeviceAddress(struct vl_data *Dev, uint8_t DeviceAddress) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_WrByte(Dev, VL_REG_I2C_SLAVE_DEVICE_ADDRESS, |
| DeviceAddress / 2); |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_DataInit(struct vl_data *Dev) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| struct VL_DeviceParameters_t CurrentParameters; |
| int i; |
| uint8_t StopVariable; |
| |
| LOG_FUNCTION_START(""); |
| |
| /* by default the I2C is running at 1V8 if you want to change it you */ |
| /* need to include this define at compilation level. */ |
| #ifdef USE_I2C_2V8 |
| Status = VL_UpdateByte(Dev, |
| VL_REG_VHV_CONFIG_PAD_SCL_SDA__EXTSUP_HV, |
| 0xFE, |
| 0x01); |
| #endif |
| |
| /* Set I2C standard mode */ |
| if (Status == VL_ERROR_NONE) |
| Status = VL_WrByte(Dev, 0x88, 0x00); |
| |
| VL_SETDEVICESPECIFICPARAMETER(Dev, ReadDataFromDeviceDone, 0); |
| |
| #ifdef USE_IQC_STATION |
| if (Status == VL_ERROR_NONE) |
| Status = VL_apply_offset_adjustment(Dev); |
| #endif |
| |
| /* Default value is 1000 for Linearity Corrective Gain */ |
| PALDevDataSet(Dev, LinearityCorrectiveGain, 1000); |
| |
| /* Dmax default Parameter */ |
| PALDevDataSet(Dev, DmaxCalRangeMilliMeter, 400); |
| PALDevDataSet(Dev, DmaxCalSignalRateRtnMegaCps, |
| (unsigned int)((0x00016B85))); /* 1.42 No Cover Glass*/ |
| |
| /* Set Default static parameters */ |
| /* *set first temporary values 9.44MHz * 65536 = 618660 */ |
| VL_SETDEVICESPECIFICPARAMETER(Dev, OscFrequencyMHz, 618660); |
| |
| /* Set Default XTalkCompensationRateMegaCps to 0 */ |
| VL_SETPARAMETERFIELD(Dev, XTalkCompensationRateMegaCps, 0); |
| |
| /* Get default parameters */ |
| Status = VL_GetDeviceParameters(Dev, &CurrentParameters); |
| if (Status == VL_ERROR_NONE) { |
| /* initialize PAL values */ |
| CurrentParameters.DeviceMode = VL_DEVICEMODE_SINGLE_RANGING; |
| CurrentParameters.HistogramMode = VL_HISTOGRAMMODE_DISABLED; |
| PALDevDataSet(Dev, CurrentParameters, CurrentParameters); |
| } |
| |
| /* Sigma estimator variable */ |
| PALDevDataSet(Dev, SigmaEstRefArray, 100); |
| PALDevDataSet(Dev, SigmaEstEffPulseWidth, 900); |
| PALDevDataSet(Dev, SigmaEstEffAmbWidth, 500); |
| PALDevDataSet(Dev, targetRefRate, 0x0A00); /* 20 MCPS in 9:7 format */ |
| |
| /* Use internal default settings */ |
| PALDevDataSet(Dev, UseInternalTuningSettings, 1); |
| |
| Status |= VL_WrByte(Dev, 0x80, 0x01); |
| Status |= VL_WrByte(Dev, 0xFF, 0x01); |
| Status |= VL_WrByte(Dev, 0x00, 0x00); |
| Status |= VL_RdByte(Dev, 0x91, &StopVariable); |
| PALDevDataSet(Dev, StopVariable, StopVariable); |
| Status |= VL_WrByte(Dev, 0x00, 0x01); |
| Status |= VL_WrByte(Dev, 0xFF, 0x00); |
| Status |= VL_WrByte(Dev, 0x80, 0x00); |
| |
| /* Enable all check */ |
| for (i = 0; i < VL_CHECKENABLE_NUMBER_OF_CHECKS; i++) { |
| if (Status == VL_ERROR_NONE) |
| Status |= VL_SetLimitCheckEnable(Dev, i, 1); |
| else |
| break; |
| |
| } |
| |
| /* Disable the following checks */ |
| if (Status == VL_ERROR_NONE) |
| Status = VL_SetLimitCheckEnable(Dev, |
| VL_CHECKENABLE_SIGNAL_REF_CLIP, 0); |
| |
| if (Status == VL_ERROR_NONE) |
| Status = VL_SetLimitCheckEnable(Dev, |
| VL_CHECKENABLE_RANGE_IGNORE_THRESHOLD, 0); |
| |
| if (Status == VL_ERROR_NONE) |
| Status = VL_SetLimitCheckEnable(Dev, |
| VL_CHECKENABLE_SIGNAL_RATE_MSRC, 0); |
| |
| if (Status == VL_ERROR_NONE) |
| Status = VL_SetLimitCheckEnable(Dev, |
| VL_CHECKENABLE_SIGNAL_RATE_PRE_RANGE, 0); |
| |
| /* Limit default values */ |
| if (Status == VL_ERROR_NONE) { |
| Status = VL_SetLimitCheckValue(Dev, |
| VL_CHECKENABLE_SIGMA_FINAL_RANGE, |
| (unsigned int)(18 * 65536)); |
| } |
| if (Status == VL_ERROR_NONE) { |
| Status = VL_SetLimitCheckValue(Dev, |
| VL_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE, |
| (unsigned int)(25 * 65536 / 100)); |
| /* 0.25 * 65536 */ |
| } |
| |
| if (Status == VL_ERROR_NONE) { |
| Status = VL_SetLimitCheckValue(Dev, |
| VL_CHECKENABLE_SIGNAL_REF_CLIP, |
| (unsigned int)(35 * 65536)); |
| } |
| |
| if (Status == VL_ERROR_NONE) { |
| Status = VL_SetLimitCheckValue(Dev, |
| VL_CHECKENABLE_RANGE_IGNORE_THRESHOLD, |
| (unsigned int)(0 * 65536)); |
| } |
| |
| if (Status == VL_ERROR_NONE) { |
| |
| PALDevDataSet(Dev, SequenceConfig, 0xFF); |
| Status = VL_WrByte(Dev, VL_REG_SYSTEM_SEQUENCE_CONFIG, |
| 0xFF); |
| |
| /* Set PAL state to tell that we are waiting for call to */ |
| /* * VL_StaticInit */ |
| PALDevDataSet(Dev, PalState, VL_STATE_WAIT_STATICINIT); |
| } |
| |
| if (Status == VL_ERROR_NONE) |
| VL_SETDEVICESPECIFICPARAMETER(Dev, RefSpadsInitialised, 0); |
| |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_SetTuningSettingBuffer(struct vl_data *Dev, |
| uint8_t *pTuningSettingBuffer, uint8_t UseInternalTuningSettings) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| if (UseInternalTuningSettings == 1) { |
| /* Force use internal settings */ |
| PALDevDataSet(Dev, UseInternalTuningSettings, 1); |
| } else { |
| |
| /* check that the first byte is not 0 */ |
| if (*pTuningSettingBuffer != 0) { |
| PALDevDataSet(Dev, pTuningSettingsPointer, |
| pTuningSettingBuffer); |
| PALDevDataSet(Dev, UseInternalTuningSettings, 0); |
| |
| } else { |
| Status = VL_ERROR_INVALID_PARAMS; |
| } |
| } |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetTuningSettingBuffer(struct vl_data *Dev, |
| uint8_t **ppTuningSettingBuffer, uint8_t *pUseInternalTuningSettings) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| *ppTuningSettingBuffer = PALDevDataGet(Dev, pTuningSettingsPointer); |
| *pUseInternalTuningSettings = PALDevDataGet(Dev, |
| UseInternalTuningSettings); |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_StaticInit(struct vl_data *Dev) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| struct VL_DeviceParameters_t CurrentParameters = {0}; |
| uint8_t *pTuningSettingBuffer; |
| uint16_t tempword = 0; |
| uint8_t tempbyte = 0; |
| uint8_t UseInternalTuningSettings = 0; |
| uint32_t count = 0; |
| uint8_t isApertureSpads = 0; |
| uint32_t refSpadCount = 0; |
| uint8_t ApertureSpads = 0; |
| uint8_t vcselPulsePeriodPCLK; |
| uint32_t seqTimeoutMicroSecs; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_get_info_from_device(Dev, 1); |
| |
| /* set the ref spad from NVM */ |
| count = (uint32_t)VL_GETDEVICESPECIFICPARAMETER(Dev, |
| ReferenceSpadCount); |
| ApertureSpads = VL_GETDEVICESPECIFICPARAMETER(Dev, |
| ReferenceSpadType); |
| |
| /* NVM value invalid */ |
| if ((ApertureSpads > 1) || |
| ((ApertureSpads == 1) && (count > 32)) || |
| ((ApertureSpads == 0) && (count > 12))) |
| Status = VL_perform_ref_spad_management(Dev, &refSpadCount, |
| &isApertureSpads); |
| else |
| Status = VL_set_reference_spads(Dev, count, ApertureSpads); |
| |
| |
| /* Initialize tuning settings buffer to prevent compiler warning. */ |
| pTuningSettingBuffer = DefaultTuningSettings; |
| |
| if (Status == VL_ERROR_NONE) { |
| UseInternalTuningSettings = PALDevDataGet(Dev, |
| UseInternalTuningSettings); |
| |
| if (UseInternalTuningSettings == 0) |
| pTuningSettingBuffer = PALDevDataGet(Dev, |
| pTuningSettingsPointer); |
| else |
| pTuningSettingBuffer = DefaultTuningSettings; |
| |
| } |
| |
| if (Status == VL_ERROR_NONE) |
| Status = VL_load_tuning_settings(Dev, |
| pTuningSettingBuffer); |
| |
| |
| /* Set interrupt config to new sample ready */ |
| if (Status == VL_ERROR_NONE) { |
| Status = VL_SetGpioConfig(Dev, 0, 0, |
| VL_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY, |
| VL_INTERRUPTPOLARITY_LOW); |
| } |
| |
| if (Status == VL_ERROR_NONE) { |
| Status = VL_WrByte(Dev, 0xFF, 0x01); |
| Status |= VL_RdWord(Dev, 0x84, &tempword); |
| Status |= VL_WrByte(Dev, 0xFF, 0x00); |
| } |
| |
| if (Status == VL_ERROR_NONE) { |
| VL_SETDEVICESPECIFICPARAMETER(Dev, OscFrequencyMHz, |
| VL_FIXPOINT412TOFIXPOINT1616(tempword)); |
| } |
| |
| /* After static init, some device parameters may be changed, */ |
| /* * so update them */ |
| if (Status == VL_ERROR_NONE) |
| Status = VL_GetDeviceParameters(Dev, &CurrentParameters); |
| |
| |
| if (Status == VL_ERROR_NONE) { |
| Status = VL_GetFractionEnable(Dev, &tempbyte); |
| if (Status == VL_ERROR_NONE) |
| PALDevDataSet(Dev, RangeFractionalEnable, tempbyte); |
| |
| } |
| |
| if (Status == VL_ERROR_NONE) |
| PALDevDataSet(Dev, CurrentParameters, CurrentParameters); |
| |
| |
| /* read the sequence config and save it */ |
| if (Status == VL_ERROR_NONE) { |
| Status = VL_RdByte(Dev, |
| VL_REG_SYSTEM_SEQUENCE_CONFIG, &tempbyte); |
| if (Status == VL_ERROR_NONE) |
| PALDevDataSet(Dev, SequenceConfig, tempbyte); |
| |
| } |
| |
| /* Disable MSRC and TCC by default */ |
| if (Status == VL_ERROR_NONE) |
| Status = VL_SetSequenceStepEnable(Dev, |
| VL_SEQUENCESTEP_TCC, 0); |
| |
| |
| if (Status == VL_ERROR_NONE) |
| Status = VL_SetSequenceStepEnable(Dev, |
| VL_SEQUENCESTEP_MSRC, 0); |
| |
| |
| /* Set PAL State to standby */ |
| if (Status == VL_ERROR_NONE) |
| PALDevDataSet(Dev, PalState, VL_STATE_IDLE); |
| |
| |
| |
| /* Store pre-range vcsel period */ |
| if (Status == VL_ERROR_NONE) { |
| Status = VL_GetVcselPulsePeriod( |
| Dev, |
| VL_VCSEL_PERIOD_PRE_RANGE, |
| &vcselPulsePeriodPCLK); |
| } |
| |
| if (Status == VL_ERROR_NONE) { |
| VL_SETDEVICESPECIFICPARAMETER( |
| Dev, PreRangeVcselPulsePeriod, |
| vcselPulsePeriodPCLK); |
| } |
| |
| /* Store final-range vcsel period */ |
| if (Status == VL_ERROR_NONE) { |
| Status = VL_GetVcselPulsePeriod( |
| Dev, |
| VL_VCSEL_PERIOD_FINAL_RANGE, |
| &vcselPulsePeriodPCLK); |
| } |
| |
| if (Status == VL_ERROR_NONE) { |
| VL_SETDEVICESPECIFICPARAMETER( |
| Dev, FinalRangeVcselPulsePeriod, |
| vcselPulsePeriodPCLK); |
| } |
| |
| /* Store pre-range timeout */ |
| if (Status == VL_ERROR_NONE) { |
| Status = get_sequence_step_timeout( |
| Dev, |
| VL_SEQUENCESTEP_PRE_RANGE, |
| &seqTimeoutMicroSecs); |
| } |
| |
| if (Status == VL_ERROR_NONE) { |
| VL_SETDEVICESPECIFICPARAMETER( |
| Dev, |
| PreRangeTimeoutMicroSecs, |
| seqTimeoutMicroSecs); |
| } |
| |
| /* Store final-range timeout */ |
| if (Status == VL_ERROR_NONE) { |
| Status = get_sequence_step_timeout( |
| Dev, |
| VL_SEQUENCESTEP_FINAL_RANGE, |
| &seqTimeoutMicroSecs); |
| } |
| |
| if (Status == VL_ERROR_NONE) { |
| VL_SETDEVICESPECIFICPARAMETER( |
| Dev, |
| FinalRangeTimeoutMicroSecs, |
| seqTimeoutMicroSecs); |
| } |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_WaitDeviceBooted(struct vl_data *Dev) |
| { |
| int8_t Status = VL_ERROR_NOT_IMPLEMENTED; |
| |
| LOG_FUNCTION_START(""); |
| |
| /* not implemented on VL53L0X */ |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_ResetDevice(struct vl_data *Dev) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| uint8_t Byte; |
| |
| LOG_FUNCTION_START(""); |
| |
| /* Set reset bit */ |
| Status = VL_WrByte(Dev, VL_REG_SOFT_RESET_GO2_SOFT_RESET_N, |
| 0x00); |
| |
| /* Wait for some time */ |
| if (Status == VL_ERROR_NONE) { |
| do { |
| Status = VL_RdByte(Dev, |
| VL_REG_IDENTIFICATION_MODEL_ID, &Byte); |
| } while (Byte != 0x00); |
| } |
| |
| VL_PollingDelay(Dev); |
| |
| /* Release reset */ |
| Status = VL_WrByte(Dev, VL_REG_SOFT_RESET_GO2_SOFT_RESET_N, |
| 0x01); |
| |
| /* Wait until correct boot-up of the device */ |
| if (Status == VL_ERROR_NONE) { |
| do { |
| Status = VL_RdByte(Dev, |
| VL_REG_IDENTIFICATION_MODEL_ID, &Byte); |
| } while (Byte == 0x00); |
| } |
| |
| VL_PollingDelay(Dev); |
| |
| /* Set PAL State to VL_STATE_POWERDOWN */ |
| if (Status == VL_ERROR_NONE) |
| PALDevDataSet(Dev, PalState, VL_STATE_POWERDOWN); |
| |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| /* End Group PAL Init Functions */ |
| |
| /* Group PAL Parameters Functions */ |
| int8_t VL_SetDeviceParameters(struct vl_data *Dev, |
| const struct VL_DeviceParameters_t *pDeviceParameters) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| int i; |
| |
| LOG_FUNCTION_START(""); |
| Status = VL_SetDeviceMode(Dev, pDeviceParameters->DeviceMode); |
| |
| if (Status == VL_ERROR_NONE) |
| Status = VL_SetInterMeasurementPeriodMilliSeconds(Dev, |
| pDeviceParameters->InterMeasurementPeriodMilliSeconds); |
| |
| |
| if (Status == VL_ERROR_NONE) |
| Status = VL_SetXTalkCompensationRateMegaCps(Dev, |
| pDeviceParameters->XTalkCompensationRateMegaCps); |
| |
| |
| if (Status == VL_ERROR_NONE) |
| Status = VL_SetOffsetCalibrationDataMicroMeter(Dev, |
| pDeviceParameters->RangeOffsetMicroMeters); |
| |
| |
| for (i = 0; i < VL_CHECKENABLE_NUMBER_OF_CHECKS; i++) { |
| if (Status == VL_ERROR_NONE) |
| Status |= VL_SetLimitCheckEnable(Dev, i, |
| pDeviceParameters->LimitChecksEnable[i]); |
| else |
| break; |
| |
| if (Status == VL_ERROR_NONE) |
| Status |= VL_SetLimitCheckValue(Dev, i, |
| pDeviceParameters->LimitChecksValue[i]); |
| else |
| break; |
| |
| } |
| |
| if (Status == VL_ERROR_NONE) |
| Status = VL_SetWrapAroundCheckEnable(Dev, |
| pDeviceParameters->WrapAroundCheckEnable); |
| |
| if (Status == VL_ERROR_NONE) |
| Status = VL_SetMeasurementTimingBudgetMicroSeconds(Dev, |
| pDeviceParameters->MeasurementTimingBudgetMicroSeconds); |
| |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetDeviceParameters(struct vl_data *Dev, |
| struct VL_DeviceParameters_t *pDeviceParameters) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| int i; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_GetDeviceMode(Dev, &(pDeviceParameters->DeviceMode)); |
| |
| if (Status == VL_ERROR_NONE) |
| Status = VL_GetInterMeasurementPeriodMilliSeconds(Dev, |
| &(pDeviceParameters->InterMeasurementPeriodMilliSeconds)); |
| |
| |
| if (Status == VL_ERROR_NONE) |
| pDeviceParameters->XTalkCompensationEnable = 0; |
| |
| if (Status == VL_ERROR_NONE) |
| Status = VL_GetXTalkCompensationRateMegaCps(Dev, |
| &(pDeviceParameters->XTalkCompensationRateMegaCps)); |
| |
| |
| if (Status == VL_ERROR_NONE) |
| Status = VL_GetOffsetCalibrationDataMicroMeter(Dev, |
| &(pDeviceParameters->RangeOffsetMicroMeters)); |
| |
| |
| if (Status == VL_ERROR_NONE) { |
| for (i = 0; i < VL_CHECKENABLE_NUMBER_OF_CHECKS; i++) { |
| /* get first the values, then the enables. |
| * VL_GetLimitCheckValue will modify the enable |
| * flags |
| */ |
| if (Status == VL_ERROR_NONE) { |
| Status |= VL_GetLimitCheckValue(Dev, i, |
| &(pDeviceParameters->LimitChecksValue[i])); |
| } else { |
| break; |
| } |
| if (Status == VL_ERROR_NONE) { |
| Status |= VL_GetLimitCheckEnable(Dev, i, |
| &(pDeviceParameters->LimitChecksEnable[i])); |
| } else { |
| break; |
| } |
| } |
| } |
| |
| if (Status == VL_ERROR_NONE) { |
| Status = VL_GetWrapAroundCheckEnable(Dev, |
| &(pDeviceParameters->WrapAroundCheckEnable)); |
| } |
| |
| /* Need to be done at the end as it uses VCSELPulsePeriod */ |
| if (Status == VL_ERROR_NONE) { |
| Status = VL_GetMeasurementTimingBudgetMicroSeconds(Dev, |
| &(pDeviceParameters->MeasurementTimingBudgetMicroSeconds)); |
| } |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_SetDeviceMode(struct vl_data *Dev, |
| uint8_t DeviceMode) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START("%d", (int)DeviceMode); |
| |
| switch (DeviceMode) { |
| case VL_DEVICEMODE_SINGLE_RANGING: |
| case VL_DEVICEMODE_CONTINUOUS_RANGING: |
| case VL_DEVICEMODE_CONTINUOUS_TIMED_RANGING: |
| case VL_DEVICEMODE_GPIO_DRIVE: |
| case VL_DEVICEMODE_GPIO_OSC: |
| /* Supported modes */ |
| VL_SETPARAMETERFIELD(Dev, DeviceMode, DeviceMode); |
| break; |
| default: |
| /* Unsupported mode */ |
| Status = VL_ERROR_MODE_NOT_SUPPORTED; |
| } |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetDeviceMode(struct vl_data *Dev, |
| uint8_t *pDeviceMode) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| VL_GETPARAMETERFIELD(Dev, DeviceMode, *pDeviceMode); |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_SetRangeFractionEnable(struct vl_data *Dev, uint8_t Enable) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START("%d", (int)Enable); |
| |
| Status = VL_WrByte(Dev, VL_REG_SYSTEM_RANGE_CONFIG, Enable); |
| |
| if (Status == VL_ERROR_NONE) |
| PALDevDataSet(Dev, RangeFractionalEnable, Enable); |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetFractionEnable(struct vl_data *Dev, uint8_t *pEnabled) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_RdByte(Dev, VL_REG_SYSTEM_RANGE_CONFIG, pEnabled); |
| |
| if (Status == VL_ERROR_NONE) |
| *pEnabled = (*pEnabled & 1); |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_SetHistogramMode(struct vl_data *Dev, |
| uint8_t HistogramMode) |
| { |
| int8_t Status = VL_ERROR_NOT_IMPLEMENTED; |
| |
| LOG_FUNCTION_START(""); |
| |
| /* not implemented on VL53L0X */ |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetHistogramMode(struct vl_data *Dev, |
| uint8_t *pHistogramMode) |
| { |
| int8_t Status = VL_ERROR_NOT_IMPLEMENTED; |
| |
| LOG_FUNCTION_START(""); |
| |
| /* not implemented on VL53L0X */ |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_SetMeasurementTimingBudgetMicroSeconds(struct vl_data *Dev, |
| uint32_t MeasurementTimingBudgetMicroSeconds) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_set_measurement_timing_budget_micro_seconds(Dev, |
| MeasurementTimingBudgetMicroSeconds); |
| |
| LOG_FUNCTION_END(Status); |
| |
| return Status; |
| } |
| |
| int8_t VL_GetMeasurementTimingBudgetMicroSeconds(struct vl_data *Dev, |
| uint32_t *pMeasurementTimingBudgetMicroSeconds) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_get_measurement_timing_budget_micro_seconds(Dev, |
| pMeasurementTimingBudgetMicroSeconds); |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_SetVcselPulsePeriod(struct vl_data *Dev, |
| uint8_t VcselPeriodType, uint8_t VCSELPulsePeriodPCLK) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_set_vcsel_pulse_period(Dev, VcselPeriodType, |
| VCSELPulsePeriodPCLK); |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetVcselPulsePeriod(struct vl_data *Dev, |
| uint8_t VcselPeriodType, uint8_t *pVCSELPulsePeriodPCLK) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_get_vcsel_pulse_period(Dev, VcselPeriodType, |
| pVCSELPulsePeriodPCLK); |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_SetSequenceStepEnable(struct vl_data *Dev, |
| uint8_t SequenceStepId, uint8_t SequenceStepEnabled) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| uint8_t SequenceConfig = 0; |
| uint8_t SequenceConfigNew = 0; |
| uint32_t MeasurementTimingBudgetMicroSeconds; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_RdByte(Dev, VL_REG_SYSTEM_SEQUENCE_CONFIG, |
| &SequenceConfig); |
| |
| SequenceConfigNew = SequenceConfig; |
| |
| if (Status == VL_ERROR_NONE) { |
| if (SequenceStepEnabled == 1) { |
| |
| /* Enable requested sequence step |
| */ |
| switch (SequenceStepId) { |
| case VL_SEQUENCESTEP_TCC: |
| SequenceConfigNew |= 0x10; |
| break; |
| case VL_SEQUENCESTEP_DSS: |
| SequenceConfigNew |= 0x28; |
| break; |
| case VL_SEQUENCESTEP_MSRC: |
| SequenceConfigNew |= 0x04; |
| break; |
| case VL_SEQUENCESTEP_PRE_RANGE: |
| SequenceConfigNew |= 0x40; |
| break; |
| case VL_SEQUENCESTEP_FINAL_RANGE: |
| SequenceConfigNew |= 0x80; |
| break; |
| default: |
| Status = VL_ERROR_INVALID_PARAMS; |
| } |
| } else { |
| /* Disable requested sequence step |
| */ |
| switch (SequenceStepId) { |
| case VL_SEQUENCESTEP_TCC: |
| SequenceConfigNew &= 0xef; |
| break; |
| case VL_SEQUENCESTEP_DSS: |
| SequenceConfigNew &= 0xd7; |
| break; |
| case VL_SEQUENCESTEP_MSRC: |
| SequenceConfigNew &= 0xfb; |
| break; |
| case VL_SEQUENCESTEP_PRE_RANGE: |
| SequenceConfigNew &= 0xbf; |
| break; |
| case VL_SEQUENCESTEP_FINAL_RANGE: |
| SequenceConfigNew &= 0x7f; |
| break; |
| default: |
| Status = VL_ERROR_INVALID_PARAMS; |
| } |
| } |
| } |
| |
| if (SequenceConfigNew != SequenceConfig) { |
| /* Apply New Setting */ |
| if (Status == VL_ERROR_NONE) { |
| Status = VL_WrByte(Dev, |
| VL_REG_SYSTEM_SEQUENCE_CONFIG, SequenceConfigNew); |
| } |
| if (Status == VL_ERROR_NONE) |
| PALDevDataSet(Dev, SequenceConfig, SequenceConfigNew); |
| |
| |
| /* Recalculate timing budget */ |
| if (Status == VL_ERROR_NONE) { |
| VL_GETPARAMETERFIELD(Dev, |
| MeasurementTimingBudgetMicroSeconds, |
| MeasurementTimingBudgetMicroSeconds); |
| |
| VL_SetMeasurementTimingBudgetMicroSeconds(Dev, |
| MeasurementTimingBudgetMicroSeconds); |
| } |
| } |
| |
| LOG_FUNCTION_END(Status); |
| |
| return Status; |
| } |
| |
| int8_t sequence_step_enabled(struct vl_data *Dev, |
| uint8_t SequenceStepId, uint8_t SequenceConfig, |
| uint8_t *pSequenceStepEnabled) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| *pSequenceStepEnabled = 0; |
| |
| LOG_FUNCTION_START(""); |
| |
| switch (SequenceStepId) { |
| case VL_SEQUENCESTEP_TCC: |
| *pSequenceStepEnabled = (SequenceConfig & 0x10) >> 4; |
| break; |
| case VL_SEQUENCESTEP_DSS: |
| *pSequenceStepEnabled = (SequenceConfig & 0x08) >> 3; |
| break; |
| case VL_SEQUENCESTEP_MSRC: |
| *pSequenceStepEnabled = (SequenceConfig & 0x04) >> 2; |
| break; |
| case VL_SEQUENCESTEP_PRE_RANGE: |
| *pSequenceStepEnabled = (SequenceConfig & 0x40) >> 6; |
| break; |
| case VL_SEQUENCESTEP_FINAL_RANGE: |
| *pSequenceStepEnabled = (SequenceConfig & 0x80) >> 7; |
| break; |
| default: |
| Status = VL_ERROR_INVALID_PARAMS; |
| } |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetSequenceStepEnable(struct vl_data *Dev, |
| uint8_t SequenceStepId, uint8_t *pSequenceStepEnabled) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| uint8_t SequenceConfig = 0; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_RdByte(Dev, VL_REG_SYSTEM_SEQUENCE_CONFIG, |
| &SequenceConfig); |
| |
| if (Status == VL_ERROR_NONE) { |
| Status = sequence_step_enabled(Dev, SequenceStepId, |
| SequenceConfig, pSequenceStepEnabled); |
| } |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetSequenceStepEnables(struct vl_data *Dev, |
| struct VL_SchedulerSequenceSteps_t *pSchedulerSequenceSteps) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| uint8_t SequenceConfig = 0; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_RdByte(Dev, VL_REG_SYSTEM_SEQUENCE_CONFIG, |
| &SequenceConfig); |
| |
| if (Status == VL_ERROR_NONE) { |
| Status = sequence_step_enabled(Dev, |
| VL_SEQUENCESTEP_TCC, SequenceConfig, |
| &pSchedulerSequenceSteps->TccOn); |
| } |
| if (Status == VL_ERROR_NONE) { |
| Status = sequence_step_enabled(Dev, |
| VL_SEQUENCESTEP_DSS, SequenceConfig, |
| &pSchedulerSequenceSteps->DssOn); |
| } |
| if (Status == VL_ERROR_NONE) { |
| Status = sequence_step_enabled(Dev, |
| VL_SEQUENCESTEP_MSRC, SequenceConfig, |
| &pSchedulerSequenceSteps->MsrcOn); |
| } |
| if (Status == VL_ERROR_NONE) { |
| Status = sequence_step_enabled(Dev, |
| VL_SEQUENCESTEP_PRE_RANGE, SequenceConfig, |
| &pSchedulerSequenceSteps->PreRangeOn); |
| } |
| if (Status == VL_ERROR_NONE) { |
| Status = sequence_step_enabled(Dev, |
| VL_SEQUENCESTEP_FINAL_RANGE, SequenceConfig, |
| &pSchedulerSequenceSteps->FinalRangeOn); |
| } |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetNumberOfSequenceSteps(struct vl_data *Dev, |
| uint8_t *pNumberOfSequenceSteps) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| *pNumberOfSequenceSteps = VL_SEQUENCESTEP_NUMBER_OF_CHECKS; |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetSequenceStepsInfo( |
| uint8_t SequenceStepId, char *pSequenceStepsString) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_get_sequence_steps_info( |
| SequenceStepId, |
| pSequenceStepsString); |
| |
| LOG_FUNCTION_END(Status); |
| |
| return Status; |
| } |
| |
| int8_t VL_SetSequenceStepTimeout(struct vl_data *Dev, |
| uint8_t SequenceStepId, unsigned int TimeOutMilliSecs) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| int8_t Status1 = VL_ERROR_NONE; |
| uint32_t TimeoutMicroSeconds = ((TimeOutMilliSecs * 1000) + 0x8000) |
| >> 16; |
| uint32_t MeasurementTimingBudgetMicroSeconds; |
| unsigned int OldTimeOutMicroSeconds; |
| |
| LOG_FUNCTION_START(""); |
| |
| /* Read back the current value in case we need to revert back to this. |
| */ |
| Status = get_sequence_step_timeout(Dev, SequenceStepId, |
| &OldTimeOutMicroSeconds); |
| |
| if (Status == VL_ERROR_NONE) { |
| Status = set_sequence_step_timeout(Dev, SequenceStepId, |
| TimeoutMicroSeconds); |
| } |
| |
| if (Status == VL_ERROR_NONE) { |
| VL_GETPARAMETERFIELD(Dev, |
| MeasurementTimingBudgetMicroSeconds, |
| MeasurementTimingBudgetMicroSeconds); |
| |
| /* At this point we don't know if the requested */ |
| /* value is valid, */ |
| /* therefore proceed to update the entire timing budget and */ |
| /* if this fails, revert back to the previous value. */ |
| Status = VL_SetMeasurementTimingBudgetMicroSeconds(Dev, |
| MeasurementTimingBudgetMicroSeconds); |
| |
| if (Status != VL_ERROR_NONE) { |
| Status1 = set_sequence_step_timeout(Dev, SequenceStepId, |
| OldTimeOutMicroSeconds); |
| |
| if (Status1 == VL_ERROR_NONE) { |
| Status1 = |
| VL_SetMeasurementTimingBudgetMicroSeconds( |
| Dev, |
| MeasurementTimingBudgetMicroSeconds); |
| } |
| |
| Status = Status1; |
| } |
| } |
| |
| LOG_FUNCTION_END(Status); |
| |
| return Status; |
| } |
| |
| int8_t VL_GetSequenceStepTimeout(struct vl_data *Dev, |
| uint8_t SequenceStepId, |
| unsigned int *pTimeOutMilliSecs) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| uint32_t TimeoutMicroSeconds; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = get_sequence_step_timeout(Dev, SequenceStepId, |
| &TimeoutMicroSeconds); |
| if (Status == VL_ERROR_NONE) { |
| TimeoutMicroSeconds <<= 8; |
| *pTimeOutMilliSecs = (TimeoutMicroSeconds + 500)/1000; |
| *pTimeOutMilliSecs <<= 8; |
| } |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_SetInterMeasurementPeriodMilliSeconds(struct vl_data *Dev, |
| uint32_t InterMeasurementPeriodMilliSeconds) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| uint16_t osc_calibrate_val; |
| uint32_t IMPeriodMilliSeconds; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_RdWord(Dev, VL_REG_OSC_CALIBRATE_VAL, |
| &osc_calibrate_val); |
| |
| if (Status == VL_ERROR_NONE) { |
| if (osc_calibrate_val != 0) { |
| IMPeriodMilliSeconds = |
| InterMeasurementPeriodMilliSeconds |
| * osc_calibrate_val; |
| } else { |
| IMPeriodMilliSeconds = |
| InterMeasurementPeriodMilliSeconds; |
| } |
| Status = VL_WrDWord(Dev, |
| VL_REG_SYSTEM_INTERMEASUREMENT_PERIOD, |
| IMPeriodMilliSeconds); |
| } |
| |
| if (Status == VL_ERROR_NONE) { |
| VL_SETPARAMETERFIELD(Dev, |
| InterMeasurementPeriodMilliSeconds, |
| InterMeasurementPeriodMilliSeconds); |
| } |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetInterMeasurementPeriodMilliSeconds(struct vl_data *Dev, |
| uint32_t *pInterMeasurementPeriodMilliSeconds) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| uint16_t osc_calibrate_val; |
| uint32_t IMPeriodMilliSeconds; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_RdWord(Dev, VL_REG_OSC_CALIBRATE_VAL, |
| &osc_calibrate_val); |
| |
| if (Status == VL_ERROR_NONE) { |
| Status = VL_RdDWord(Dev, |
| VL_REG_SYSTEM_INTERMEASUREMENT_PERIOD, |
| &IMPeriodMilliSeconds); |
| } |
| |
| if (Status == VL_ERROR_NONE) { |
| if (osc_calibrate_val != 0) { |
| *pInterMeasurementPeriodMilliSeconds = |
| IMPeriodMilliSeconds / osc_calibrate_val; |
| } |
| VL_SETPARAMETERFIELD(Dev, |
| InterMeasurementPeriodMilliSeconds, |
| *pInterMeasurementPeriodMilliSeconds); |
| } |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_SetXTalkCompensationEnable(struct vl_data *Dev, |
| uint8_t XTalkCompensationEnable) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| unsigned int TempFix1616; |
| uint16_t LinearityCorrectiveGain; |
| |
| LOG_FUNCTION_START(""); |
| |
| LinearityCorrectiveGain = PALDevDataGet(Dev, LinearityCorrectiveGain); |
| |
| if ((XTalkCompensationEnable == 0) |
| || (LinearityCorrectiveGain != 1000)) { |
| TempFix1616 = 0; |
| } else { |
| VL_GETPARAMETERFIELD(Dev, XTalkCompensationRateMegaCps, |
| TempFix1616); |
| } |
| |
| /* the following register has a format 3.13 */ |
| Status = VL_WrWord(Dev, |
| VL_REG_CROSSTALK_COMPENSATION_PEAK_RATE_MCPS, |
| VL_FIXPOINT1616TOFIXPOINT313(TempFix1616)); |
| |
| if (Status == VL_ERROR_NONE) { |
| if (XTalkCompensationEnable == 0) { |
| VL_SETPARAMETERFIELD(Dev, XTalkCompensationEnable, |
| 0); |
| } else { |
| VL_SETPARAMETERFIELD(Dev, XTalkCompensationEnable, |
| 1); |
| } |
| } |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetXTalkCompensationEnable(struct vl_data *Dev, |
| uint8_t *pXTalkCompensationEnable) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| uint8_t Temp8; |
| |
| LOG_FUNCTION_START(""); |
| |
| VL_GETPARAMETERFIELD(Dev, XTalkCompensationEnable, Temp8); |
| *pXTalkCompensationEnable = Temp8; |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_SetXTalkCompensationRateMegaCps(struct vl_data *Dev, |
| unsigned int XTalkCompensationRateMegaCps) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| uint8_t Temp8; |
| uint16_t LinearityCorrectiveGain; |
| uint16_t data; |
| |
| LOG_FUNCTION_START(""); |
| |
| VL_GETPARAMETERFIELD(Dev, XTalkCompensationEnable, Temp8); |
| LinearityCorrectiveGain = PALDevDataGet(Dev, LinearityCorrectiveGain); |
| |
| if (Temp8 == 0) { /* disabled write only internal value */ |
| VL_SETPARAMETERFIELD(Dev, XTalkCompensationRateMegaCps, |
| XTalkCompensationRateMegaCps); |
| } else { |
| /* the following register has a format 3.13 */ |
| if (LinearityCorrectiveGain == 1000) { |
| data = VL_FIXPOINT1616TOFIXPOINT313( |
| XTalkCompensationRateMegaCps); |
| } else { |
| data = 0; |
| } |
| |
| Status = VL_WrWord(Dev, |
| VL_REG_CROSSTALK_COMPENSATION_PEAK_RATE_MCPS, data); |
| |
| if (Status == VL_ERROR_NONE) { |
| VL_SETPARAMETERFIELD(Dev, |
| XTalkCompensationRateMegaCps, |
| XTalkCompensationRateMegaCps); |
| } |
| } |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetXTalkCompensationRateMegaCps(struct vl_data *Dev, |
| unsigned int *pXTalkCompensationRateMegaCps) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| uint16_t Value; |
| unsigned int TempFix1616; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_RdWord(Dev, |
| VL_REG_CROSSTALK_COMPENSATION_PEAK_RATE_MCPS, (uint16_t *)&Value); |
| if (Status == VL_ERROR_NONE) { |
| if (Value == 0) { |
| /* the Xtalk is disabled return value from memory */ |
| VL_GETPARAMETERFIELD(Dev, |
| XTalkCompensationRateMegaCps, TempFix1616); |
| *pXTalkCompensationRateMegaCps = TempFix1616; |
| VL_SETPARAMETERFIELD(Dev, XTalkCompensationEnable, |
| 0); |
| } else { |
| TempFix1616 = VL_FIXPOINT313TOFIXPOINT1616(Value); |
| *pXTalkCompensationRateMegaCps = TempFix1616; |
| VL_SETPARAMETERFIELD(Dev, |
| XTalkCompensationRateMegaCps, TempFix1616); |
| VL_SETPARAMETERFIELD(Dev, XTalkCompensationEnable, |
| 1); |
| } |
| } |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_SetRefCalibration(struct vl_data *Dev, uint8_t VhvSettings, |
| uint8_t PhaseCal) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_set_ref_calibration(Dev, VhvSettings, PhaseCal); |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetRefCalibration(struct vl_data *Dev, uint8_t *pVhvSettings, |
| uint8_t *pPhaseCal) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_get_ref_calibration(Dev, pVhvSettings, pPhaseCal); |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| /* |
| * CHECK LIMIT FUNCTIONS |
| */ |
| |
| int8_t VL_GetNumberOfLimitCheck(uint16_t *pNumberOfLimitCheck) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| *pNumberOfLimitCheck = VL_CHECKENABLE_NUMBER_OF_CHECKS; |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetLimitCheckInfo(struct vl_data *Dev, uint16_t LimitCheckId, |
| char *pLimitCheckString) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_get_limit_check_info(Dev, LimitCheckId, |
| pLimitCheckString); |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetLimitCheckStatus(struct vl_data *Dev, |
| uint16_t LimitCheckId, uint8_t *pLimitCheckStatus) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| uint8_t Temp8; |
| |
| LOG_FUNCTION_START(""); |
| |
| if (LimitCheckId >= VL_CHECKENABLE_NUMBER_OF_CHECKS) { |
| Status = VL_ERROR_INVALID_PARAMS; |
| } else { |
| |
| VL_GETARRAYPARAMETERFIELD(Dev, LimitChecksStatus, |
| LimitCheckId, Temp8); |
| |
| *pLimitCheckStatus = Temp8; |
| |
| } |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_SetLimitCheckEnable(struct vl_data *Dev, |
| uint16_t LimitCheckId, uint8_t LimitCheckEnable) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| unsigned int TempFix1616 = 0; |
| uint8_t LimitCheckEnableInt = 0; |
| uint8_t LimitCheckDisable = 0; |
| uint8_t Temp8; |
| |
| LOG_FUNCTION_START(""); |
| |
| if (LimitCheckId >= VL_CHECKENABLE_NUMBER_OF_CHECKS) { |
| Status = VL_ERROR_INVALID_PARAMS; |
| } else { |
| if (LimitCheckEnable == 0) { |
| TempFix1616 = 0; |
| LimitCheckEnableInt = 0; |
| LimitCheckDisable = 1; |
| |
| } else { |
| VL_GETARRAYPARAMETERFIELD(Dev, LimitChecksValue, |
| LimitCheckId, TempFix1616); |
| LimitCheckDisable = 0; |
| /* this to be sure to have either 0 or 1 */ |
| LimitCheckEnableInt = 1; |
| } |
| |
| switch (LimitCheckId) { |
| |
| case VL_CHECKENABLE_SIGMA_FINAL_RANGE: |
| /* internal computation: */ |
| VL_SETARRAYPARAMETERFIELD(Dev, LimitChecksEnable, |
| VL_CHECKENABLE_SIGMA_FINAL_RANGE, |
| LimitCheckEnableInt); |
| |
| break; |
| |
| case VL_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE: |
| |
| Status = VL_WrWord(Dev, |
| VL_REG_FINAL_RANGE_CONFIG_MIN_COUNT_RATE_RTN_LIMIT, |
| VL_FIXPOINT1616TOFIXPOINT97(TempFix1616)); |
| |
| break; |
| |
| case VL_CHECKENABLE_SIGNAL_REF_CLIP: |
| |
| /* internal computation: */ |
| VL_SETARRAYPARAMETERFIELD(Dev, LimitChecksEnable, |
| VL_CHECKENABLE_SIGNAL_REF_CLIP, |
| LimitCheckEnableInt); |
| |
| break; |
| |
| case VL_CHECKENABLE_RANGE_IGNORE_THRESHOLD: |
| |
| /* internal computation: */ |
| VL_SETARRAYPARAMETERFIELD(Dev, LimitChecksEnable, |
| VL_CHECKENABLE_RANGE_IGNORE_THRESHOLD, |
| LimitCheckEnableInt); |
| |
| break; |
| |
| case VL_CHECKENABLE_SIGNAL_RATE_MSRC: |
| |
| Temp8 = (uint8_t)(LimitCheckDisable << 1); |
| Status = VL_UpdateByte(Dev, |
| VL_REG_MSRC_CONFIG_CONTROL, |
| 0xFE, Temp8); |
| |
| break; |
| |
| case VL_CHECKENABLE_SIGNAL_RATE_PRE_RANGE: |
| |
| Temp8 = (uint8_t)(LimitCheckDisable << 4); |
| Status = VL_UpdateByte(Dev, |
| VL_REG_MSRC_CONFIG_CONTROL, |
| 0xEF, Temp8); |
| |
| break; |
| |
| |
| default: |
| Status = VL_ERROR_INVALID_PARAMS; |
| |
| } |
| |
| } |
| |
| if (Status == VL_ERROR_NONE) { |
| if (LimitCheckEnable == 0) { |
| VL_SETARRAYPARAMETERFIELD(Dev, LimitChecksEnable, |
| LimitCheckId, 0); |
| } else { |
| VL_SETARRAYPARAMETERFIELD(Dev, LimitChecksEnable, |
| LimitCheckId, 1); |
| } |
| } |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetLimitCheckEnable(struct vl_data *Dev, |
| uint16_t LimitCheckId, uint8_t *pLimitCheckEnable) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| uint8_t Temp8; |
| |
| LOG_FUNCTION_START(""); |
| |
| if (LimitCheckId >= VL_CHECKENABLE_NUMBER_OF_CHECKS) { |
| Status = VL_ERROR_INVALID_PARAMS; |
| *pLimitCheckEnable = 0; |
| } else { |
| VL_GETARRAYPARAMETERFIELD(Dev, LimitChecksEnable, |
| LimitCheckId, Temp8); |
| *pLimitCheckEnable = Temp8; |
| } |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_SetLimitCheckValue(struct vl_data *Dev, uint16_t LimitCheckId, |
| unsigned int LimitCheckValue) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| uint8_t Temp8; |
| |
| LOG_FUNCTION_START(""); |
| |
| VL_GETARRAYPARAMETERFIELD(Dev, LimitChecksEnable, LimitCheckId, |
| Temp8); |
| |
| if (Temp8 == 0) { /* disabled write only internal value */ |
| VL_SETARRAYPARAMETERFIELD(Dev, LimitChecksValue, |
| LimitCheckId, LimitCheckValue); |
| } else { |
| |
| switch (LimitCheckId) { |
| |
| case VL_CHECKENABLE_SIGMA_FINAL_RANGE: |
| /* internal computation: */ |
| VL_SETARRAYPARAMETERFIELD(Dev, LimitChecksValue, |
| VL_CHECKENABLE_SIGMA_FINAL_RANGE, |
| LimitCheckValue); |
| break; |
| |
| case VL_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE: |
| |
| Status = VL_WrWord(Dev, |
| VL_REG_FINAL_RANGE_CONFIG_MIN_COUNT_RATE_RTN_LIMIT, |
| VL_FIXPOINT1616TOFIXPOINT97( |
| LimitCheckValue)); |
| |
| break; |
| |
| case VL_CHECKENABLE_SIGNAL_REF_CLIP: |
| |
| /* internal computation: */ |
| VL_SETARRAYPARAMETERFIELD(Dev, LimitChecksValue, |
| VL_CHECKENABLE_SIGNAL_REF_CLIP, |
| LimitCheckValue); |
| |
| break; |
| |
| case VL_CHECKENABLE_RANGE_IGNORE_THRESHOLD: |
| |
| /* internal computation: */ |
| VL_SETARRAYPARAMETERFIELD(Dev, LimitChecksValue, |
| VL_CHECKENABLE_RANGE_IGNORE_THRESHOLD, |
| LimitCheckValue); |
| |
| break; |
| |
| case VL_CHECKENABLE_SIGNAL_RATE_MSRC: |
| case VL_CHECKENABLE_SIGNAL_RATE_PRE_RANGE: |
| |
| Status = VL_WrWord(Dev, |
| VL_REG_PRE_RANGE_MIN_COUNT_RATE_RTN_LIMIT, |
| VL_FIXPOINT1616TOFIXPOINT97( |
| LimitCheckValue)); |
| |
| break; |
| |
| default: |
| Status = VL_ERROR_INVALID_PARAMS; |
| |
| } |
| |
| if (Status == VL_ERROR_NONE) { |
| VL_SETARRAYPARAMETERFIELD(Dev, LimitChecksValue, |
| LimitCheckId, LimitCheckValue); |
| } |
| } |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetLimitCheckValue(struct vl_data *Dev, uint16_t LimitCheckId, |
| unsigned int *pLimitCheckValue) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| uint8_t EnableZeroValue = 0; |
| uint16_t Temp16; |
| unsigned int TempFix1616; |
| |
| LOG_FUNCTION_START(""); |
| |
| switch (LimitCheckId) { |
| |
| case VL_CHECKENABLE_SIGMA_FINAL_RANGE: |
| /* internal computation: */ |
| VL_GETARRAYPARAMETERFIELD(Dev, LimitChecksValue, |
| VL_CHECKENABLE_SIGMA_FINAL_RANGE, TempFix1616); |
| EnableZeroValue = 0; |
| break; |
| |
| case VL_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE: |
| Status = VL_RdWord(Dev, |
| VL_REG_FINAL_RANGE_CONFIG_MIN_COUNT_RATE_RTN_LIMIT, |
| &Temp16); |
| if (Status == VL_ERROR_NONE) |
| TempFix1616 = VL_FIXPOINT97TOFIXPOINT1616(Temp16); |
| |
| |
| EnableZeroValue = 1; |
| break; |
| |
| case VL_CHECKENABLE_SIGNAL_REF_CLIP: |
| /* internal computation: */ |
| VL_GETARRAYPARAMETERFIELD(Dev, LimitChecksValue, |
| VL_CHECKENABLE_SIGNAL_REF_CLIP, TempFix1616); |
| EnableZeroValue = 0; |
| break; |
| |
| case VL_CHECKENABLE_RANGE_IGNORE_THRESHOLD: |
| /* internal computation: */ |
| VL_GETARRAYPARAMETERFIELD(Dev, LimitChecksValue, |
| VL_CHECKENABLE_RANGE_IGNORE_THRESHOLD, TempFix1616); |
| EnableZeroValue = 0; |
| break; |
| |
| case VL_CHECKENABLE_SIGNAL_RATE_MSRC: |
| case VL_CHECKENABLE_SIGNAL_RATE_PRE_RANGE: |
| Status = VL_RdWord(Dev, |
| VL_REG_PRE_RANGE_MIN_COUNT_RATE_RTN_LIMIT, |
| &Temp16); |
| if (Status == VL_ERROR_NONE) |
| TempFix1616 = VL_FIXPOINT97TOFIXPOINT1616(Temp16); |
| |
| |
| EnableZeroValue = 0; |
| break; |
| |
| default: |
| Status = VL_ERROR_INVALID_PARAMS; |
| |
| } |
| |
| if (Status == VL_ERROR_NONE) { |
| |
| if (EnableZeroValue == 1) { |
| |
| if (TempFix1616 == 0) { |
| /* disabled: return value from memory */ |
| VL_GETARRAYPARAMETERFIELD(Dev, |
| LimitChecksValue, LimitCheckId, |
| TempFix1616); |
| *pLimitCheckValue = TempFix1616; |
| VL_SETARRAYPARAMETERFIELD(Dev, |
| LimitChecksEnable, LimitCheckId, 0); |
| } else { |
| *pLimitCheckValue = TempFix1616; |
| VL_SETARRAYPARAMETERFIELD(Dev, |
| LimitChecksValue, LimitCheckId, |
| TempFix1616); |
| VL_SETARRAYPARAMETERFIELD(Dev, |
| LimitChecksEnable, LimitCheckId, 1); |
| } |
| } else { |
| *pLimitCheckValue = TempFix1616; |
| } |
| } |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| |
| } |
| |
| int8_t VL_GetLimitCheckCurrent(struct vl_data *Dev, |
| uint16_t LimitCheckId, unsigned int *pLimitCheckCurrent) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| struct VL_RangingMeasurementData_t LastRangeDataBuffer; |
| |
| LOG_FUNCTION_START(""); |
| |
| if (LimitCheckId >= VL_CHECKENABLE_NUMBER_OF_CHECKS) { |
| Status = VL_ERROR_INVALID_PARAMS; |
| } else { |
| switch (LimitCheckId) { |
| case VL_CHECKENABLE_SIGMA_FINAL_RANGE: |
| /* Need to run a ranging to have the latest values */ |
| *pLimitCheckCurrent = PALDevDataGet(Dev, SigmaEstimate); |
| |
| break; |
| |
| case VL_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE: |
| /* Need to run a ranging to have the latest values */ |
| LastRangeDataBuffer = PALDevDataGet(Dev, |
| LastRangeMeasure); |
| *pLimitCheckCurrent = |
| LastRangeDataBuffer.SignalRateRtnMegaCps; |
| |
| break; |
| |
| case VL_CHECKENABLE_SIGNAL_REF_CLIP: |
| /* Need to run a ranging to have the latest values */ |
| *pLimitCheckCurrent = PALDevDataGet(Dev, |
| LastSignalRefMcps); |
| |
| break; |
| |
| case VL_CHECKENABLE_RANGE_IGNORE_THRESHOLD: |
| /* Need to run a ranging to have the latest values */ |
| LastRangeDataBuffer = PALDevDataGet(Dev, |
| LastRangeMeasure); |
| *pLimitCheckCurrent = |
| LastRangeDataBuffer.SignalRateRtnMegaCps; |
| |
| break; |
| |
| case VL_CHECKENABLE_SIGNAL_RATE_MSRC: |
| /* Need to run a ranging to have the latest values */ |
| LastRangeDataBuffer = PALDevDataGet(Dev, |
| LastRangeMeasure); |
| *pLimitCheckCurrent = |
| LastRangeDataBuffer.SignalRateRtnMegaCps; |
| |
| break; |
| |
| case VL_CHECKENABLE_SIGNAL_RATE_PRE_RANGE: |
| /* Need to run a ranging to have the latest values */ |
| LastRangeDataBuffer = PALDevDataGet(Dev, |
| LastRangeMeasure); |
| *pLimitCheckCurrent = |
| LastRangeDataBuffer.SignalRateRtnMegaCps; |
| |
| break; |
| |
| default: |
| Status = VL_ERROR_INVALID_PARAMS; |
| } |
| } |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| |
| } |
| |
| /* |
| * WRAPAROUND Check |
| */ |
| int8_t VL_SetWrapAroundCheckEnable(struct vl_data *Dev, |
| uint8_t WrapAroundCheckEnable) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| uint8_t Byte; |
| uint8_t WrapAroundCheckEnableInt; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_RdByte(Dev, VL_REG_SYSTEM_SEQUENCE_CONFIG, &Byte); |
| if (WrapAroundCheckEnable == 0) { |
| /* Disable wraparound */ |
| Byte = Byte & 0x7F; |
| WrapAroundCheckEnableInt = 0; |
| } else { |
| /*Enable wraparound */ |
| Byte = Byte | 0x80; |
| WrapAroundCheckEnableInt = 1; |
| } |
| |
| Status = VL_WrByte(Dev, VL_REG_SYSTEM_SEQUENCE_CONFIG, Byte); |
| |
| if (Status == VL_ERROR_NONE) { |
| PALDevDataSet(Dev, SequenceConfig, Byte); |
| VL_SETPARAMETERFIELD(Dev, WrapAroundCheckEnable, |
| WrapAroundCheckEnableInt); |
| } |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetWrapAroundCheckEnable(struct vl_data *Dev, |
| uint8_t *pWrapAroundCheckEnable) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| uint8_t data; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_RdByte(Dev, VL_REG_SYSTEM_SEQUENCE_CONFIG, &data); |
| if (Status == VL_ERROR_NONE) { |
| PALDevDataSet(Dev, SequenceConfig, data); |
| if (data & (0x01 << 7)) |
| *pWrapAroundCheckEnable = 0x01; |
| else |
| *pWrapAroundCheckEnable = 0x00; |
| } |
| if (Status == VL_ERROR_NONE) { |
| VL_SETPARAMETERFIELD(Dev, WrapAroundCheckEnable, |
| *pWrapAroundCheckEnable); |
| } |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_SetDmaxCalParameters(struct vl_data *Dev, |
| uint16_t RangeMilliMeter, unsigned int SignalRateRtnMegaCps) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| unsigned int SignalRateRtnMegaCpsTemp = 0; |
| |
| LOG_FUNCTION_START(""); |
| |
| /* Check if one of input parameter is zero, in that case the */ |
| /* value are get from NVM */ |
| if ((RangeMilliMeter == 0) || (SignalRateRtnMegaCps == 0)) { |
| /* NVM parameters */ |
| /* Run VL_get_info_from_device wit option 4 to get */ |
| /* signal rate at 400 mm if the value have been already */ |
| /* get this function will return with no access to device */ |
| VL_get_info_from_device(Dev, 4); |
| |
| SignalRateRtnMegaCpsTemp = VL_GETDEVICESPECIFICPARAMETER( |
| Dev, SignalRateMeasFixed400mm); |
| |
| PALDevDataSet(Dev, DmaxCalRangeMilliMeter, 400); |
| PALDevDataSet(Dev, DmaxCalSignalRateRtnMegaCps, |
| SignalRateRtnMegaCpsTemp); |
| } else { |
| /* User parameters */ |
| PALDevDataSet(Dev, DmaxCalRangeMilliMeter, RangeMilliMeter); |
| PALDevDataSet(Dev, DmaxCalSignalRateRtnMegaCps, |
| SignalRateRtnMegaCps); |
| } |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetDmaxCalParameters(struct vl_data *Dev, |
| uint16_t *pRangeMilliMeter, unsigned int *pSignalRateRtnMegaCps) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| *pRangeMilliMeter = PALDevDataGet(Dev, DmaxCalRangeMilliMeter); |
| *pSignalRateRtnMegaCps = PALDevDataGet(Dev, |
| DmaxCalSignalRateRtnMegaCps); |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| /* End Group PAL Parameters Functions */ |
| |
| /* Group PAL Measurement Functions */ |
| int8_t VL_PerformSingleMeasurement(struct vl_data *Dev) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| uint8_t DeviceMode; |
| |
| LOG_FUNCTION_START(""); |
| |
| /* Get Current DeviceMode */ |
| Status = VL_GetDeviceMode(Dev, &DeviceMode); |
| |
| /* Start immediately to run a single ranging measurement in case of */ |
| /* single ranging or single histogram */ |
| if (Status == VL_ERROR_NONE |
| && DeviceMode == VL_DEVICEMODE_SINGLE_RANGING) |
| Status = VL_StartMeasurement(Dev); |
| |
| |
| if (Status == VL_ERROR_NONE) |
| Status = VL_measurement_poll_for_completion(Dev); |
| |
| |
| /* Change PAL State in case of single ranging or single histogram */ |
| if (Status == VL_ERROR_NONE |
| && DeviceMode == VL_DEVICEMODE_SINGLE_RANGING) |
| PALDevDataSet(Dev, PalState, VL_STATE_IDLE); |
| |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_PerformSingleHistogramMeasurement(struct vl_data *Dev, |
| struct VL_HistogramMeasurementData_t *pHistogramMeasurementData) |
| { |
| int8_t Status = VL_ERROR_NOT_IMPLEMENTED; |
| |
| LOG_FUNCTION_START(""); |
| |
| /* not implemented on VL53L0X */ |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_PerformRefCalibration(struct vl_data *Dev, |
| uint8_t *pVhvSettings, uint8_t *pPhaseCal) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_perform_ref_calibration(Dev, pVhvSettings, |
| pPhaseCal, 1); |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_PerformXTalkMeasurement(struct vl_data *Dev, |
| uint32_t TimeoutMs, unsigned int *pXtalkPerSpad, |
| uint8_t *pAmbientTooHigh) |
| { |
| int8_t Status = VL_ERROR_NOT_IMPLEMENTED; |
| |
| LOG_FUNCTION_START(""); |
| |
| /* not implemented on VL53L0X */ |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_PerformXTalkCalibration(struct vl_data *Dev, |
| unsigned int XTalkCalDistance, |
| unsigned int *pXTalkCompensationRateMegaCps) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_perform_xtalk_calibration(Dev, XTalkCalDistance, |
| pXTalkCompensationRateMegaCps); |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_PerformOffsetCalibration(struct vl_data *Dev, |
| unsigned int CalDistanceMilliMeter, int32_t *pOffsetMicroMeter) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_perform_offset_calibration(Dev, CalDistanceMilliMeter, |
| pOffsetMicroMeter); |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_CheckAndLoadInterruptSettings(struct vl_data *Dev, |
| uint8_t StartNotStopFlag) |
| { |
| uint8_t InterruptConfig; |
| unsigned int ThresholdLow; |
| unsigned int ThresholdHigh; |
| int8_t Status = VL_ERROR_NONE; |
| |
| InterruptConfig = VL_GETDEVICESPECIFICPARAMETER(Dev, |
| Pin0GpioFunctionality); |
| |
| if ((InterruptConfig == |
| VL_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_LOW) || |
| (InterruptConfig == |
| VL_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_HIGH) || |
| (InterruptConfig == |
| VL_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_OUT)) { |
| |
| Status = VL_GetInterruptThresholds(Dev, |
| VL_DEVICEMODE_CONTINUOUS_RANGING, |
| &ThresholdLow, &ThresholdHigh); |
| |
| if (((ThresholdLow > 255*65536) || |
| (ThresholdHigh > 255*65536)) && |
| (Status == VL_ERROR_NONE)) { |
| |
| if (StartNotStopFlag != 0) { |
| Status = VL_load_tuning_settings(Dev, |
| InterruptThresholdSettings); |
| } else { |
| Status |= VL_WrByte(Dev, 0xFF, 0x04); |
| Status |= VL_WrByte(Dev, 0x70, 0x00); |
| Status |= VL_WrByte(Dev, 0xFF, 0x00); |
| Status |= VL_WrByte(Dev, 0x80, 0x00); |
| } |
| |
| } |
| |
| |
| } |
| |
| return Status; |
| |
| } |
| |
| |
| int8_t VL_StartMeasurement(struct vl_data *Dev) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| uint8_t DeviceMode; |
| uint8_t Byte; |
| uint8_t StartStopByte = VL_REG_SYSRANGE_MODE_START_STOP; |
| uint32_t LoopNb; |
| |
| LOG_FUNCTION_START(""); |
| |
| /* Get Current DeviceMode */ |
| VL_GetDeviceMode(Dev, &DeviceMode); |
| |
| Status = VL_WrByte(Dev, 0x80, 0x01); |
| Status = VL_WrByte(Dev, 0xFF, 0x01); |
| Status = VL_WrByte(Dev, 0x00, 0x00); |
| Status = VL_WrByte(Dev, 0x91, PALDevDataGet(Dev, StopVariable)); |
| Status = VL_WrByte(Dev, 0x00, 0x01); |
| Status = VL_WrByte(Dev, 0xFF, 0x00); |
| Status = VL_WrByte(Dev, 0x80, 0x00); |
| |
| switch (DeviceMode) { |
| case VL_DEVICEMODE_SINGLE_RANGING: |
| Status = VL_WrByte(Dev, VL_REG_SYSRANGE_START, 0x01); |
| |
| Byte = StartStopByte; |
| if (Status == VL_ERROR_NONE) { |
| /* Wait until start bit has been cleared */ |
| LoopNb = 0; |
| do { |
| if (LoopNb > 0) |
| Status = VL_RdByte(Dev, |
| VL_REG_SYSRANGE_START, &Byte); |
| LoopNb = LoopNb + 1; |
| } while (((Byte & StartStopByte) == StartStopByte) |
| && (Status == VL_ERROR_NONE) |
| && (LoopNb < VL_DEFAULT_MAX_LOOP)); |
| |
| if (LoopNb >= VL_DEFAULT_MAX_LOOP) |
| Status = VL_ERROR_TIME_OUT; |
| |
| } |
| |
| break; |
| case VL_DEVICEMODE_CONTINUOUS_RANGING: |
| /* Back-to-back mode */ |
| |
| /* Check if need to apply interrupt settings */ |
| if (Status == VL_ERROR_NONE) |
| Status = VL_CheckAndLoadInterruptSettings(Dev, 1); |
| |
| Status = VL_WrByte(Dev, |
| VL_REG_SYSRANGE_START, |
| VL_REG_SYSRANGE_MODE_BACKTOBACK); |
| if (Status == VL_ERROR_NONE) { |
| /* Set PAL State to Running */ |
| PALDevDataSet(Dev, PalState, VL_STATE_RUNNING); |
| } |
| break; |
| case VL_DEVICEMODE_CONTINUOUS_TIMED_RANGING: |
| /* Continuous mode */ |
| /* Check if need to apply interrupt settings */ |
| if (Status == VL_ERROR_NONE) |
| Status = VL_CheckAndLoadInterruptSettings(Dev, 1); |
| |
| Status = VL_WrByte(Dev, |
| VL_REG_SYSRANGE_START, |
| VL_REG_SYSRANGE_MODE_TIMED); |
| |
| if (Status == VL_ERROR_NONE) { |
| /* Set PAL State to Running */ |
| PALDevDataSet(Dev, PalState, VL_STATE_RUNNING); |
| } |
| break; |
| default: |
| /* Selected mode not supported */ |
| Status = VL_ERROR_MODE_NOT_SUPPORTED; |
| } |
| |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_StopMeasurement(struct vl_data *Dev) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_WrByte(Dev, VL_REG_SYSRANGE_START, |
| VL_REG_SYSRANGE_MODE_SINGLESHOT); |
| |
| Status = VL_WrByte(Dev, 0xFF, 0x01); |
| Status = VL_WrByte(Dev, 0x00, 0x00); |
| Status = VL_WrByte(Dev, 0x91, 0x00); |
| Status = VL_WrByte(Dev, 0x00, 0x01); |
| Status = VL_WrByte(Dev, 0xFF, 0x00); |
| |
| if (Status == VL_ERROR_NONE) { |
| /* Set PAL State to Idle */ |
| PALDevDataSet(Dev, PalState, VL_STATE_IDLE); |
| } |
| |
| /* Check if need to apply interrupt settings */ |
| if (Status == VL_ERROR_NONE) |
| Status = VL_CheckAndLoadInterruptSettings(Dev, 0); |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetMeasurementDataReady(struct vl_data *Dev, |
| uint8_t *pMeasurementDataReady) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| uint8_t SysRangeStatusRegister; |
| uint8_t InterruptConfig; |
| uint32_t InterruptMask; |
| |
| LOG_FUNCTION_START(""); |
| |
| InterruptConfig = VL_GETDEVICESPECIFICPARAMETER(Dev, |
| Pin0GpioFunctionality); |
| |
| if (InterruptConfig == |
| VL_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY) { |
| Status = VL_GetInterruptMaskStatus(Dev, &InterruptMask); |
| if (InterruptMask == |
| VL_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY) |
| *pMeasurementDataReady = 1; |
| else |
| *pMeasurementDataReady = 0; |
| } else { |
| Status = VL_RdByte(Dev, VL_REG_RESULT_RANGE_STATUS, |
| &SysRangeStatusRegister); |
| if (Status == VL_ERROR_NONE) { |
| if (SysRangeStatusRegister & 0x01) |
| *pMeasurementDataReady = 1; |
| else |
| *pMeasurementDataReady = 0; |
| } |
| } |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_WaitDeviceReadyForNewMeasurement(struct vl_data *Dev, |
| uint32_t MaxLoop) |
| { |
| int8_t Status = VL_ERROR_NOT_IMPLEMENTED; |
| |
| LOG_FUNCTION_START(""); |
| |
| /* not implemented for VL53L0X */ |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| |
| int8_t VL_GetRangingMeasurementData(struct vl_data *Dev, |
| struct VL_RangingMeasurementData_t *pRangingMeasurementData) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| uint8_t DeviceRangeStatus; |
| uint8_t RangeFractionalEnable; |
| uint8_t PalRangeStatus; |
| uint8_t XTalkCompensationEnable; |
| uint16_t AmbientRate; |
| unsigned int SignalRate; |
| uint16_t XTalkCompensationRateMegaCps; |
| uint16_t EffectiveSpadRtnCount; |
| uint16_t tmpuint16; |
| uint16_t XtalkRangeMilliMeter; |
| uint16_t LinearityCorrectiveGain; |
| uint8_t localBuffer[12]; |
| struct VL_RangingMeasurementData_t LastRangeDataBuffer; |
| |
| LOG_FUNCTION_START(""); |
| |
| /* |
| * use multi read even if some registers are not useful, result will |
| * be more efficient |
| * start reading at 0x14 dec20 |
| * end reading at 0x21 dec33 total 14 bytes to read |
| */ |
| Status = VL_ReadMulti(Dev, 0x14, localBuffer, 12); |
| |
| if (Status == VL_ERROR_NONE) { |
| |
| pRangingMeasurementData->ZoneId = 0; /* Only one zone */ |
| pRangingMeasurementData->TimeStamp = 0; /* Not Implemented */ |
| |
| tmpuint16 = VL_MAKEUINT16(localBuffer[11], |
| localBuffer[10]); |
| /* cut1.1 if SYSTEM__RANGE_CONFIG if 1 range is 2bits fractional |
| *(format 11.2) else no fractional |
| */ |
| |
| pRangingMeasurementData->MeasurementTimeUsec = 0; |
| |
| SignalRate = VL_FIXPOINT97TOFIXPOINT1616( |
| VL_MAKEUINT16(localBuffer[7], localBuffer[6])); |
| /* peak_signal_count_rate_rtn_mcps */ |
| pRangingMeasurementData->SignalRateRtnMegaCps = SignalRate; |
| |
| AmbientRate = VL_MAKEUINT16(localBuffer[9], |
| localBuffer[8]); |
| pRangingMeasurementData->AmbientRateRtnMegaCps = |
| VL_FIXPOINT97TOFIXPOINT1616(AmbientRate); |
| |
| EffectiveSpadRtnCount = VL_MAKEUINT16(localBuffer[3], |
| localBuffer[2]); |
| /* EffectiveSpadRtnCount is 8.8 format */ |
| pRangingMeasurementData->EffectiveSpadRtnCount = |
| EffectiveSpadRtnCount; |
| |
| DeviceRangeStatus = localBuffer[0]; |
| |
| /* Get Linearity Corrective Gain */ |
| LinearityCorrectiveGain = PALDevDataGet(Dev, |
| LinearityCorrectiveGain); |
| |
| /* Get ranging configuration */ |
| RangeFractionalEnable = PALDevDataGet(Dev, |
| RangeFractionalEnable); |
| |
| if (LinearityCorrectiveGain != 1000) { |
| |
| tmpuint16 = (uint16_t)((LinearityCorrectiveGain |
| * tmpuint16 + 500) / 1000); |
| |
| /* Implement Xtalk */ |
| VL_GETPARAMETERFIELD(Dev, |
| XTalkCompensationRateMegaCps, |
| XTalkCompensationRateMegaCps); |
| VL_GETPARAMETERFIELD(Dev, XTalkCompensationEnable, |
| XTalkCompensationEnable); |
| |
| if (XTalkCompensationEnable) { |
| |
| if ((SignalRate |
| - ((XTalkCompensationRateMegaCps |
| * EffectiveSpadRtnCount) >> 8)) |
| <= 0) { |
| if (RangeFractionalEnable) |
| XtalkRangeMilliMeter = 8888; |
| else |
| XtalkRangeMilliMeter = 8888 |
| << 2; |
| } else { |
| XtalkRangeMilliMeter = |
| (tmpuint16 * SignalRate) |
| / (SignalRate |
| - ((XTalkCompensationRateMegaCps |
| * EffectiveSpadRtnCount) |
| >> 8)); |
| } |
| |
| tmpuint16 = XtalkRangeMilliMeter; |
| } |
| |
| } |
| |
| if (RangeFractionalEnable) { |
| pRangingMeasurementData->RangeMilliMeter = |
| (uint16_t)((tmpuint16) >> 2); |
| pRangingMeasurementData->RangeFractionalPart = |
| (uint8_t)((tmpuint16 & 0x03) << 6); |
| } else { |
| pRangingMeasurementData->RangeMilliMeter = tmpuint16; |
| pRangingMeasurementData->RangeFractionalPart = 0; |
| } |
| |
| /* |
| * For a standard definition of RangeStatus, this should |
| * return 0 in case of good result after a ranging |
| * The range status depends on the device so call a device |
| * specific function to obtain the right Status. |
| */ |
| Status |= VL_get_pal_range_status(Dev, DeviceRangeStatus, |
| SignalRate, EffectiveSpadRtnCount, |
| pRangingMeasurementData, &PalRangeStatus); |
| |
| if (Status == VL_ERROR_NONE) |
| pRangingMeasurementData->RangeStatus = PalRangeStatus; |
| |
| } |
| |
| if (Status == VL_ERROR_NONE) { |
| /* Copy last read data into Dev buffer */ |
| LastRangeDataBuffer = PALDevDataGet(Dev, LastRangeMeasure); |
| |
| LastRangeDataBuffer.RangeMilliMeter = |
| pRangingMeasurementData->RangeMilliMeter; |
| LastRangeDataBuffer.RangeFractionalPart = |
| pRangingMeasurementData->RangeFractionalPart; |
| LastRangeDataBuffer.RangeDMaxMilliMeter = |
| pRangingMeasurementData->RangeDMaxMilliMeter; |
| LastRangeDataBuffer.MeasurementTimeUsec = |
| pRangingMeasurementData->MeasurementTimeUsec; |
| LastRangeDataBuffer.SignalRateRtnMegaCps = |
| pRangingMeasurementData->SignalRateRtnMegaCps; |
| LastRangeDataBuffer.AmbientRateRtnMegaCps = |
| pRangingMeasurementData->AmbientRateRtnMegaCps; |
| LastRangeDataBuffer.EffectiveSpadRtnCount = |
| pRangingMeasurementData->EffectiveSpadRtnCount; |
| LastRangeDataBuffer.RangeStatus = |
| pRangingMeasurementData->RangeStatus; |
| |
| PALDevDataSet(Dev, LastRangeMeasure, LastRangeDataBuffer); |
| } |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetMeasurementRefSignal(struct vl_data *Dev, |
| unsigned int *pMeasurementRefSignal) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| uint8_t SignalRefClipLimitCheckEnable = 0; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_GetLimitCheckEnable(Dev, |
| VL_CHECKENABLE_SIGNAL_REF_CLIP, |
| &SignalRefClipLimitCheckEnable); |
| if (SignalRefClipLimitCheckEnable != 0) |
| *pMeasurementRefSignal = PALDevDataGet(Dev, LastSignalRefMcps); |
| else |
| Status = VL_ERROR_INVALID_COMMAND; |
| LOG_FUNCTION_END(Status); |
| |
| return Status; |
| } |
| |
| int8_t VL_GetHistogramMeasurementData(struct vl_data *Dev, |
| struct VL_HistogramMeasurementData_t *pHistogramMeasurementData) |
| { |
| int8_t Status = VL_ERROR_NOT_IMPLEMENTED; |
| |
| LOG_FUNCTION_START(""); |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_PerformSingleRangingMeasurement(struct vl_data *Dev, |
| struct VL_RangingMeasurementData_t *pRangingMeasurementData) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| /* This function will do a complete single ranging */ |
| /* Here we fix the mode! */ |
| Status = VL_SetDeviceMode(Dev, VL_DEVICEMODE_SINGLE_RANGING); |
| |
| if (Status == VL_ERROR_NONE) |
| Status = VL_PerformSingleMeasurement(Dev); |
| |
| |
| if (Status == VL_ERROR_NONE) |
| Status = VL_GetRangingMeasurementData(Dev, |
| pRangingMeasurementData); |
| |
| |
| if (Status == VL_ERROR_NONE) |
| Status = VL_ClearInterruptMask(Dev, 0); |
| |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_SetNumberOfROIZones(struct vl_data *Dev, |
| uint8_t NumberOfROIZones) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| if (NumberOfROIZones != 1) |
| Status = VL_ERROR_INVALID_PARAMS; |
| |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetNumberOfROIZones(struct vl_data *Dev, |
| uint8_t *pNumberOfROIZones) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| *pNumberOfROIZones = 1; |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetMaxNumberOfROIZones(struct vl_data *Dev, |
| uint8_t *pMaxNumberOfROIZones) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| *pMaxNumberOfROIZones = 1; |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| /* End Group PAL Measurement Functions */ |
| |
| int8_t VL_SetGpioConfig(struct vl_data *Dev, uint8_t Pin, |
| uint8_t DeviceMode, uint8_t Functionality, |
| uint8_t Polarity) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| uint8_t data; |
| |
| LOG_FUNCTION_START(""); |
| |
| if (Pin != 0) { |
| Status = VL_ERROR_GPIO_NOT_EXISTING; |
| } else if (DeviceMode == VL_DEVICEMODE_GPIO_DRIVE) { |
| if (Polarity == VL_INTERRUPTPOLARITY_LOW) |
| data = 0x10; |
| else |
| data = 1; |
| |
| Status = VL_WrByte(Dev, |
| VL_REG_GPIO_HV_MUX_ACTIVE_HIGH, data); |
| |
| } else if (DeviceMode == VL_DEVICEMODE_GPIO_OSC) { |
| |
| Status |= VL_WrByte(Dev, 0xff, 0x01); |
| Status |= VL_WrByte(Dev, 0x00, 0x00); |
| |
| Status |= VL_WrByte(Dev, 0xff, 0x00); |
| Status |= VL_WrByte(Dev, 0x80, 0x01); |
| Status |= VL_WrByte(Dev, 0x85, 0x02); |
| |
| Status |= VL_WrByte(Dev, 0xff, 0x04); |
| Status |= VL_WrByte(Dev, 0xcd, 0x00); |
| Status |= VL_WrByte(Dev, 0xcc, 0x11); |
| |
| Status |= VL_WrByte(Dev, 0xff, 0x07); |
| Status |= VL_WrByte(Dev, 0xbe, 0x00); |
| |
| Status |= VL_WrByte(Dev, 0xff, 0x06); |
| Status |= VL_WrByte(Dev, 0xcc, 0x09); |
| |
| Status |= VL_WrByte(Dev, 0xff, 0x00); |
| Status |= VL_WrByte(Dev, 0xff, 0x01); |
| Status |= VL_WrByte(Dev, 0x00, 0x00); |
| |
| } else { |
| |
| if (Status == VL_ERROR_NONE) { |
| switch (Functionality) { |
| case VL_GPIOFUNCTIONALITY_OFF: |
| data = 0x00; |
| break; |
| case VL_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_LOW: |
| data = 0x01; |
| break; |
| case VL_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_HIGH: |
| data = 0x02; |
| break; |
| case VL_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_OUT: |
| data = 0x03; |
| break; |
| case VL_GPIOFUNCTIONALITY_NEW_MEASURE_READY: |
| data = 0x04; |
| break; |
| default: |
| Status = |
| VL_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED; |
| } |
| } |
| |
| if (Status == VL_ERROR_NONE) |
| Status = VL_WrByte(Dev, |
| VL_REG_SYSTEM_INTERRUPT_CONFIG_GPIO, data); |
| |
| if (Status == VL_ERROR_NONE) { |
| if (Polarity == VL_INTERRUPTPOLARITY_LOW) |
| data = 0; |
| else |
| data = (uint8_t)(1 << 4); |
| |
| Status = VL_UpdateByte(Dev, |
| VL_REG_GPIO_HV_MUX_ACTIVE_HIGH, 0xEF, data); |
| } |
| |
| if (Status == VL_ERROR_NONE) |
| VL_SETDEVICESPECIFICPARAMETER(Dev, |
| Pin0GpioFunctionality, Functionality); |
| |
| if (Status == VL_ERROR_NONE) |
| Status = VL_ClearInterruptMask(Dev, 0); |
| |
| } |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetGpioConfig(struct vl_data *Dev, uint8_t Pin, |
| uint8_t *pDeviceMode, |
| uint8_t *pFunctionality, |
| uint8_t *pPolarity) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| uint8_t GpioFunctionality; |
| uint8_t data; |
| |
| LOG_FUNCTION_START(""); |
| |
| /* pDeviceMode not managed by Ewok it return the current mode */ |
| |
| Status = VL_GetDeviceMode(Dev, pDeviceMode); |
| |
| if (Status == VL_ERROR_NONE) { |
| if (Pin != 0) { |
| Status = VL_ERROR_GPIO_NOT_EXISTING; |
| } else { |
| Status = VL_RdByte(Dev, |
| VL_REG_SYSTEM_INTERRUPT_CONFIG_GPIO, &data); |
| } |
| } |
| |
| if (Status == VL_ERROR_NONE) { |
| switch (data & 0x07) { |
| case 0x00: |
| GpioFunctionality = VL_GPIOFUNCTIONALITY_OFF; |
| break; |
| case 0x01: |
| GpioFunctionality = |
| VL_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_LOW; |
| break; |
| case 0x02: |
| GpioFunctionality = |
| VL_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_HIGH; |
| break; |
| case 0x03: |
| GpioFunctionality = |
| VL_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_OUT; |
| break; |
| case 0x04: |
| GpioFunctionality = |
| VL_GPIOFUNCTIONALITY_NEW_MEASURE_READY; |
| break; |
| default: |
| Status = VL_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED; |
| } |
| } |
| |
| if (Status == VL_ERROR_NONE) |
| Status = VL_RdByte(Dev, |
| VL_REG_GPIO_HV_MUX_ACTIVE_HIGH, &data); |
| |
| if (Status == VL_ERROR_NONE) { |
| if ((data & (uint8_t)(1 << 4)) == 0) |
| *pPolarity = VL_INTERRUPTPOLARITY_LOW; |
| else |
| *pPolarity = VL_INTERRUPTPOLARITY_HIGH; |
| } |
| |
| if (Status == VL_ERROR_NONE) { |
| *pFunctionality = GpioFunctionality; |
| VL_SETDEVICESPECIFICPARAMETER(Dev, Pin0GpioFunctionality, |
| GpioFunctionality); |
| } |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_SetInterruptThresholds(struct vl_data *Dev, |
| uint8_t DeviceMode, unsigned int ThresholdLow, |
| unsigned int ThresholdHigh) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| uint16_t Threshold16; |
| |
| LOG_FUNCTION_START(""); |
| |
| /* no dependency on DeviceMode for Ewok */ |
| /* Need to divide by 2 because the FW will apply a x2 */ |
| Threshold16 = (uint16_t)((ThresholdLow >> 17) & 0x00fff); |
| Status = VL_WrWord(Dev, VL_REG_SYSTEM_THRESH_LOW, |
| Threshold16); |
| |
| if (Status == VL_ERROR_NONE) { |
| /* Need to divide by 2 because the FW will apply a x2 */ |
| Threshold16 = (uint16_t)((ThresholdHigh >> 17) & 0x00fff); |
| Status = VL_WrWord(Dev, VL_REG_SYSTEM_THRESH_HIGH, |
| Threshold16); |
| } |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetInterruptThresholds(struct vl_data *Dev, |
| uint8_t DeviceMode, unsigned int *pThresholdLow, |
| unsigned int *pThresholdHigh) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| uint16_t Threshold16; |
| |
| LOG_FUNCTION_START(""); |
| |
| /* no dependency on DeviceMode for Ewok */ |
| |
| Status = VL_RdWord(Dev, VL_REG_SYSTEM_THRESH_LOW, |
| &Threshold16); |
| /* Need to multiply by 2 because the FW will apply a x2 */ |
| *pThresholdLow = (unsigned int)((0x00fff & Threshold16) << 17); |
| |
| if (Status == VL_ERROR_NONE) { |
| Status = VL_RdWord(Dev, VL_REG_SYSTEM_THRESH_HIGH, |
| &Threshold16); |
| /* Need to multiply by 2 because the FW will apply a x2 */ |
| *pThresholdHigh = |
| (unsigned int)((0x00fff & Threshold16) << 17); |
| } |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetStopCompletedStatus(struct vl_data *Dev, |
| uint32_t *pStopStatus) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| uint8_t Byte = 0; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_WrByte(Dev, 0xFF, 0x01); |
| |
| if (Status == VL_ERROR_NONE) |
| Status = VL_RdByte(Dev, 0x04, &Byte); |
| |
| if (Status == VL_ERROR_NONE) |
| Status = VL_WrByte(Dev, 0xFF, 0x0); |
| |
| *pStopStatus = Byte; |
| |
| if (Byte == 0) { |
| Status = VL_WrByte(Dev, 0x80, 0x01); |
| Status = VL_WrByte(Dev, 0xFF, 0x01); |
| Status = VL_WrByte(Dev, 0x00, 0x00); |
| Status = VL_WrByte(Dev, 0x91, |
| PALDevDataGet(Dev, StopVariable)); |
| Status = VL_WrByte(Dev, 0x00, 0x01); |
| Status = VL_WrByte(Dev, 0xFF, 0x00); |
| Status = VL_WrByte(Dev, 0x80, 0x00); |
| } |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| /* Group PAL Interrupt Functions */ |
| int8_t VL_ClearInterruptMask(struct vl_data *Dev, |
| uint32_t InterruptMask) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| uint8_t LoopCount; |
| uint8_t Byte; |
| |
| LOG_FUNCTION_START(""); |
| |
| /* clear bit 0 range interrupt, bit 1 error interrupt */ |
| LoopCount = 0; |
| do { |
| Status = VL_WrByte(Dev, |
| VL_REG_SYSTEM_INTERRUPT_CLEAR, 0x01); |
| Status |= VL_WrByte(Dev, |
| VL_REG_SYSTEM_INTERRUPT_CLEAR, 0x00); |
| Status |= VL_RdByte(Dev, |
| VL_REG_RESULT_INTERRUPT_STATUS, &Byte); |
| LoopCount++; |
| } while (((Byte & 0x07) != 0x00) |
| && (LoopCount < 3) |
| && (Status == VL_ERROR_NONE)); |
| |
| |
| if (LoopCount >= 3) |
| Status = VL_ERROR_INTERRUPT_NOT_CLEARED; |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetInterruptMaskStatus(struct vl_data *Dev, |
| uint32_t *pInterruptMaskStatus) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| uint8_t Byte; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_RdByte(Dev, VL_REG_RESULT_INTERRUPT_STATUS, |
| &Byte); |
| *pInterruptMaskStatus = Byte & 0x07; |
| |
| if (Byte & 0x18) |
| Status = VL_ERROR_RANGE_ERROR; |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_EnableInterruptMask(struct vl_data *Dev, |
| uint32_t InterruptMask) |
| { |
| int8_t Status = VL_ERROR_NOT_IMPLEMENTED; |
| |
| LOG_FUNCTION_START(""); |
| |
| /* not implemented for VL53L0X */ |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| /* End Group PAL Interrupt Functions */ |
| |
| /* Group SPAD functions */ |
| |
| int8_t VL_SetSpadAmbientDamperThreshold(struct vl_data *Dev, |
| uint16_t SpadAmbientDamperThreshold) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_WrByte(Dev, 0xFF, 0x01); |
| Status |= VL_WrWord(Dev, 0x40, SpadAmbientDamperThreshold); |
| Status |= VL_WrByte(Dev, 0xFF, 0x00); |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetSpadAmbientDamperThreshold(struct vl_data *Dev, |
| uint16_t *pSpadAmbientDamperThreshold) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_WrByte(Dev, 0xFF, 0x01); |
| Status |= VL_RdWord(Dev, 0x40, pSpadAmbientDamperThreshold); |
| Status |= VL_WrByte(Dev, 0xFF, 0x00); |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_SetSpadAmbientDamperFactor(struct vl_data *Dev, |
| uint16_t SpadAmbientDamperFactor) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| uint8_t Byte; |
| |
| LOG_FUNCTION_START(""); |
| |
| Byte = (uint8_t)(SpadAmbientDamperFactor & 0x00FF); |
| |
| Status = VL_WrByte(Dev, 0xFF, 0x01); |
| Status |= VL_WrByte(Dev, 0x42, Byte); |
| Status |= VL_WrByte(Dev, 0xFF, 0x00); |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| int8_t VL_GetSpadAmbientDamperFactor(struct vl_data *Dev, |
| uint16_t *pSpadAmbientDamperFactor) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| uint8_t Byte; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_WrByte(Dev, 0xFF, 0x01); |
| Status |= VL_RdByte(Dev, 0x42, &Byte); |
| Status |= VL_WrByte(Dev, 0xFF, 0x00); |
| *pSpadAmbientDamperFactor = (uint16_t)Byte; |
| |
| LOG_FUNCTION_END(Status); |
| return Status; |
| } |
| |
| /* END Group SPAD functions */ |
| |
| /***************************************************************************** |
| * Internal functions |
| *****************************************************************************/ |
| |
| int8_t VL_SetReferenceSpads(struct vl_data *Dev, uint32_t count, |
| uint8_t isApertureSpads) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_set_reference_spads(Dev, count, isApertureSpads); |
| |
| LOG_FUNCTION_END(Status); |
| |
| return Status; |
| } |
| |
| int8_t VL_GetReferenceSpads(struct vl_data *Dev, uint32_t *pSpadCount, |
| uint8_t *pIsApertureSpads) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_get_reference_spads(Dev, pSpadCount, pIsApertureSpads); |
| |
| LOG_FUNCTION_END(Status); |
| |
| return Status; |
| } |
| |
| int8_t VL_PerformRefSpadManagement(struct vl_data *Dev, |
| uint32_t *refSpadCount, uint8_t *isApertureSpads) |
| { |
| int8_t Status = VL_ERROR_NONE; |
| |
| LOG_FUNCTION_START(""); |
| |
| Status = VL_perform_ref_spad_management(Dev, refSpadCount, |
| isApertureSpads); |
| |
| LOG_FUNCTION_END(Status); |
| |
| return Status; |
| } |