From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from xmbghk7.mail.qq.com (xmbghk7.mail.qq.com [43.163.128.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0C6D330C606; Sat, 7 Feb 2026 09:42:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=43.163.128.53 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770457376; cv=none; b=WNvIxvVOsYPPcVzFXojJDltrwogm5XRfR48bi2BTm1dcV9ksZ6YLMNLctPLwW+7iIqiXXV1e36ASyLMwZOa1Iq3Ke9NypDM6p1zLJE4OpZ3Q2xpP1OetWinHM4B7HHFtZwvkEtBrhac+CURVtM+UGrC1E0JVerAqAI8LzM9stu8= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770457376; c=relaxed/simple; bh=mivhbAEpIwXsg5JY5GypZxRuyny3HnzgW0/IhPeC65o=; h=Message-ID:From:To:Cc:Subject:Date:MIME-Version; b=f/Z+03xrRGuCEu4Pv3RgKdsqkz5qV02cssLH9584Tkez7P1BV0qNQ1bJl0LS8cs7OD21CCFa9bTam84/hbTvscLV92OfVydgg5FHACY4YPqb5CGRFYgmyG2FrBi47Xb6N2nLxjE6BENtqsBBjH5QXMLo1VvcE6seiFQ/JxaKomk= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=qq.com; spf=pass smtp.mailfrom=qq.com; dkim=pass (1024-bit key) header.d=qq.com header.i=@qq.com header.b=w6Atru6N; arc=none smtp.client-ip=43.163.128.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=qq.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=qq.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=qq.com header.i=@qq.com header.b="w6Atru6N" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qq.com; s=s201512; t=1770457365; bh=U28fsapFNpLzbN5G64boDdaXpuPju6izMWnvTRlD1+4=; h=From:To:Cc:Subject:Date; b=w6Atru6NK9W4Rp/oheI/hxQmCbkLExNp3vUPSyjptUS2oQ9OkOPvzZTyHbcUvNlMy aFXTaeqIEqMZiQzLfzWMXVHisxjjV8yKIirJFyI+QKUhqfma8jUN0lfaeQLfu9/xkv RVioqbUTIeHXsW2uAmZ2hHIuq5uFxbQY4dPvMlCs= Received: from localhost.localdomain ([58.34.102.26]) by newxmesmtplogicsvrszc50-0.qq.com (NewEsmtp) with SMTP id AA987696; Sat, 07 Feb 2026 17:42:41 +0800 X-QQ-mid: xmsmtpt1770457361t05o6f3mj Message-ID: X-QQ-XMAILINFO: MEx+xBdGVwfV+0PXCAnZ07J8RT9bwHwBgv5B5az7y46jpB/yiA8vD2G4jI0gCc EdpMGQrXjfdfHkXGSyTwGRDxZCrHBII+pBPnRAvC/8Teele8jPPewhVvc7hDo1UEnb6x93pm+Se6 XgP8yzmQ+PbkOwy5axiQNC5y5SovWNXTK2xTFHUMvx2SDK8F0tOOSWcilJb4xg6213j0XB6ZRTw5 MZ6+cF5jnRhbmB6o2zhF+47JUii67wpZnZOJE86CaoQ9c4ZUzzXCEuoL83aPhVcFavnSOgiELilH nLFWqSupBjMrAoyP4POQzPFrrWDXngeH7XSaZodRWjXcppFBnENNkRbnqGt++19UujmJFGpVR69p r28g4etZ9rzyXEvsWjEIyTK3DwRgYTs9IgIDOFy6Oa4j/YdzMQ41wCvVQ8sJ/rd4pDXDrsb1d/Cx JQhsj3EEbZQJwJHuKYa3kjaJIARvLX+2KrlKa1e3hBJ5Mxyjpc2eKxEz6E1f5/UxIHYBfN6DJYRV yi5AnRtAMuXbwD4J8zisVRO+cLjS6ooUW8G2tAR7Z8q0KH4+8ihW0wh4AHc0kLUFpTdDMB/YNhuX 8wUglZmgjpRlxqGWtp2KCfZkqAet2u5bprXFhlaX1hZW4t6tUntfM5XMeB4oRa2ucyS9vExfINJZ fD2j4/KmBE3JguFeQM0SezFc6FYPT8Ka7aifbiC60idmtV57Vo6hoeWm6BgulWQEYuz8Yyqrh4hV zkMjmKcbT+fdYNCEpQlH/6o0GAqkO5ZOBMvRtyfZUtxlZNvXh96GjXA06Wm2KNTxjt3SIJYw87w6 n2XJwJmZUrz32gROpFoay0ilx8V+P6AhrwiBt0biaTm4OGmwE5bRLntsOqWowMqZLxde77TlU4Vd SewEkvr7ozMDtno9i0fzfdX98L+YSpz4GT3492nhBBZCtv3JgVohcpQATJzISMc7CAd1eZ0TUhaD IKqrna5jriwdditq91pzWG9mFm04yg70Ch+DLR1rygrpvITUB1rA== X-QQ-XMRINFO: Nq+8W0+stu50tPAe92KXseR0ZZmBTk3gLg== From: 434779359@qq.com To: Jonathan Cameron Cc: David Lechner , =?UTF-8?q?Nuno=20S=C3=A1?= , Andy Shevchenko , Liam Girdwood , Mark Brown , Linus Walleij , Bartosz Golaszewski , liufulin , Waqar Hameed , linux-kernel@vger.kernel.org, linux-iio@vger.kernel.org, linux-gpio@vger.kernel.org Subject: [PATCH] tof: Add VL53L4CX TOF drivers Date: Sat, 7 Feb 2026 17:42:35 +0800 X-OQ-MSGID: <20260207094235.1780679-1-434779359@qq.com> X-Mailer: git-send-email 2.25.1 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: liufulin This patch adds support for the vl53l4cx tof ic ICs used in Qualcomm reference designs Signed-off-by: liufulin --- drivers/iio/proximity/Kconfig | 10 + drivers/iio/proximity/Makefile | 1 + drivers/iio/proximity/vl53l4cx-i2c.c | 18161 +++++++++++++++++++++++++ 3 files changed, 18172 insertions(+) create mode 100644 drivers/iio/proximity/vl53l4cx-i2c.c diff --git a/drivers/iio/proximity/Kconfig b/drivers/iio/proximity/Kconfig index 6070974c2c85..a2fcb39e444e 100644 --- a/drivers/iio/proximity/Kconfig +++ b/drivers/iio/proximity/Kconfig @@ -255,4 +255,14 @@ config AW96103 To compile this driver as a module, choose M here: the module will be called aw96103. +config VL53L4CX_I2C + tristate "STMicroelectronics VL53L0X ToF ranger sensor (I2C)" + depends on I2C + help + Say Y here to build a driver for STMicroelectronics VL53L0X + ToF ranger sensors with i2c interface. + This driver can be used to measure the distance of objects. + To compile this driver as a module, choose M here: the + module will be called vl53l0x-i2c. + endmenu diff --git a/drivers/iio/proximity/Makefile b/drivers/iio/proximity/Makefile index 152034d38c49..8a682bbed50b 100644 --- a/drivers/iio/proximity/Makefile +++ b/drivers/iio/proximity/Makefile @@ -24,4 +24,5 @@ obj-$(CONFIG_SX9500) += sx9500.o obj-$(CONFIG_VCNL3020) += vcnl3020.o obj-$(CONFIG_VL53L0X_I2C) += vl53l0x-i2c.o obj-$(CONFIG_AW96103) += aw96103.o +obj-$(CONFIG_VL53L4CX_I2C) += vl53l4cx-i2c.o diff --git a/drivers/iio/proximity/vl53l4cx-i2c.c b/drivers/iio/proximity/vl53l4cx-i2c.c new file mode 100644 index 000000000000..df9ae9786966 --- /dev/null +++ b/drivers/iio/proximity/vl53l4cx-i2c.c @@ -0,0 +1,18161 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Support for ST VL53L0X FlightSense ToF Ranging Sensor on a i2c bus. + * + * Copyright (C) 2016 STMicroelectronics Imaging Division. + * Copyright (C) 2018 Song Qiang + * Copyright (C) 2020 Ivan Drobyshevskyi + * + * Datasheet available at + * + * + * Default 7-bit i2c slave address 0x29. + * + * TODO: FIFO buffer, continuous mode, range selection, sensor ID check. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define STMVL53LX_DRV_NAME "stmvl53lx" +#define STMVL53LX_SLAVE_ADDR (0x52>>1) + +#define VL_REG_SYSRANGE_START 0x00 + +#define MODI2C_DEBUG 0 + +#if 0 +#define DEBUG 1 +#endif +#if 0 +#define FORCE_CONSOLE_DEBUG +#endif + +extern int stmvl53lx_enable_debug; + +#ifdef DEBUG +# ifdef FORCE_CONSOLE_DEBUG +#define vl53lx_dbgmsg(str, ...) do { \ + if (stmvl53lx_enable_debug) \ + pr_info("%s: " str, __func__, ##__VA_ARGS__); \ +} while (0) +# else +#define vl53lx_dbgmsg(str, ...) do { \ + if (stmvl53lx_enable_debug) \ + pr_debug("%s: " str, __func__, ##__VA_ARGS__); \ +} while (0) +# endif +#else +# define vl53lx_dbgmsg(...) ((void)0) +#endif + +#define WORK_DEBUG 0 +#if WORK_DEBUG +# define work_dbg(msg, ...)\ + printk("[D WK53L1] :" msg "\n", ##__VA_ARGS__) +#else +# define work_dbg(...) ((void)0) +#endif + +#define vl53lx_info(str, args...) \ + pr_info("%s: " str "\n", __func__, ##args) + +#define vl53lx_errmsg(str, args...) \ + pr_err("%s: " str, __func__, ##args) + +#define vl53lx_wanrmsg(str, args...) \ + pr_warn("%s: " str, __func__, ##args) + +#ifndef STMVL53LX_LOG_POLL_TIMING +# define STMVL53LX_LOG_POLL_TIMING 0 +#endif +#ifndef STMVL53LX_LOG_CCI_TIMING +# define STMVL53LX_LOG_CCI_TIMING 0 +#endif + +#define modi2c_warn(fmt, ...)\ + dev_WARN(&i2c_data->client->dev, fmt, ##__VA_ARGS__) + +#define modi2c_err(fmt, ...)\ + dev_err(&i2c_data->client->dev, fmt, ##__VA_ARGS__) + +#if MODI2C_DEBUG +#define modi2c_dbg(fmt, ...)\ + pr_devel("%s "fmt"\n", __func__, ##__VA_ARGS__) +#else +#define modi2c_dbg(...) ((void)0) +#endif + +#define VL_REG_SYSRANGE_MODE_MASK GENMASK(3, 0) +#define VL_REG_SYSRANGE_MODE_SINGLESHOT 0x00 +#define VL_REG_SYSRANGE_MODE_START_STOP BIT(0) +#define VL_REG_SYSRANGE_MODE_BACKTOBACK BIT(1) +#define VL_REG_SYSRANGE_MODE_TIMED BIT(2) +#define VL_REG_SYSRANGE_MODE_HISTOGRAM BIT(3) + +#define VL_REG_SYSTEM_INTERRUPT_CONFIG_GPIO 0x0A +#define VL_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY BIT(2) + +#define VL_REG_SYSTEM_INTERRUPT_CLEAR 0x0B + +#define VL_REG_RESULT_INT_STATUS 0x13 +#define VL_REG_RESULT_RANGE_STATUS 0x14 +#define VL_REG_RESULT_RANGE_STATUS_COMPLETE BIT(0) + +#define VL53LX_FIRMWARE_BOOT_TIME_US 1200 +#define VL53LX_I2C_SLAVE__DEVICE_ADDRESS 0x0001 + +#define VL53LX_NVM_PEAK_RATE_MAP_SAMPLES 25 + +#define VL53LX_MAX_USER_ZONES 5 + +#define VL53LX_MAX_RANGE_RESULTS 4 + +#define VL53LX_MAX_STRING_LENGTH 512 + +#define VL53LX_RTN_SPAD_BUFFER_SIZE 32 + +#define VL53LX_MAX_BIN_SEQUENCE_LENGTH 6 + +#define VL53LX_XTALK_HISTO_BINS 12 + +#define VL53LX_MAX_XTALK_RANGE_RESULTS 5 + +#define VL53LX_BIN_REC_SIZE 6 + +#define VL53LX_MAX_OFFSET_RANGE_RESULTS 3 + +#define VL53LX_TIMING_CONF_A_B_SIZE 2 + +#define VL53LX_HISTOGRAM_BUFFER_SIZE 24 + +#define VL53LX_FRAME_WAIT_EVENT 6 + +#define VL53LX_RANGE_STATUS__RANGE_STATUS_MASK 0x1F +#define VL53LX_RANGE_STATUS__MAX_THRESHOLD_HIT_MASK 0x20 +#define VL53LX_RANGE_STATUS__MIN_THRESHOLD_HIT_MASK 0x40 +#define VL53LX_RANGE_STATUS__GPH_ID_RANGE_STATUS_MASK 0x80 + +#define VL53LX_INTERRUPT_STATUS__INT_STATUS_MASK 0x07 +#define VL53LX_INTERRUPT_STATUS__INT_ERROR_STATUS_MASK 0x18 +#define VL53LX_INTERRUPT_STATUS__GPH_ID_INT_STATUS_MASK 0x20 + +#define VL53LX_MAX_BIN_SEQUENCE_LENGTH 6 +#define VL53LX_MAX_BIN_SEQUENCE_CODE 15 +#define VL53LX_HISTOGRAM_BUFFER_SIZE 24 +#define VL53LX_XTALK_HISTO_BINS 12 + +#define VL53LX_BOOT_COMPLETION_POLLING_TIMEOUT_MS 500 + +#define VL53LX_BOOT_COMPLETION_POLLING_TIMEOUT_MS 500 +#define VL53LX_RANGE_COMPLETION_POLLING_TIMEOUT_MS 2000 +#define VL53LX_TEST_COMPLETION_POLLING_TIMEOUT_MS 60000 + +#define VL53LX_POLLING_DELAY_MS 1 + +#define VL53LX_FIRMWARE__SYSTEM_STATUS 0x00E5 + +#define VL53LX_GROUPEDPARAMETERHOLD_ID_MASK 0x02 + +#define VL53LX_SYSTEM_CONTROL_I2C_SIZE_BYTES 5 + +#define STMVL53LX_MAX_CCI_XFER_SZ 256 + +#define FDA_MAX_TIMING_BUDGET_US 550000 +#define L4_FDA_MAX_TIMING_BUDGET_US 200000 + +#define WRITE_MULTIPLE_CHUNK_MAX 32 + +#define VL53LX_POWER_MANAGEMENT__GO1_POWER_FORCE 0x0083 + +#define VL53LX_DEVICEMEASUREMENTMODE_MODE_MASK 0xF0 +#define VL53LX_DEVICEMEASUREMENTMODE_STOP_MASK 0x0F + +#define VL53LX_MAX_AMBIENT_DMAX_VALUES 5 + +#define VL53LX_PATCH__CTRL 0x0470 + +#define VL53LX_FIRMWARE__ENABLE 0x0085 + +#define VL53LX_CUSTOMER_NVM_MANAGED_I2C_SIZE_BYTES 23 + +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_REF_0 0x000D + +#define IGNORE_DIVISION_BY_ZERO 0 + +#define IGNORE_XTALK_EXTRACTION_NO_SAMPLE_FAIL 0 +#define IGNORE_XTALK_EXTRACTION_SIGMA_LIMIT_FAIL 0 +#define IGNORE_XTALK_EXTRACTION_NO_SAMPLE_FOR_GRADIENT_WARN 0 +#define IGNORE_XTALK_EXTRACTION_SIGMA_LIMIT_FOR_GRADIENT_WARN 0 +#define IGNORE_XTALK_EXTRACTION_MISSING_SAMPLES_WARN 0 + +#define IGNORE_REF_SPAD_CHAR_NOT_ENOUGH_SPADS 0 +#define IGNORE_REF_SPAD_CHAR_RATE_TOO_HIGH 0 +#define IGNORE_REF_SPAD_CHAR_RATE_TOO_LOW 0 + +#define IGNORE_OFFSET_CAL_MISSING_SAMPLES 0 +#define IGNORE_OFFSET_CAL_SIGMA_TOO_HIGH 0 +#define IGNORE_OFFSET_CAL_RATE_TOO_HIGH 0 +#define IGNORE_OFFSET_CAL_SPAD_COUNT_TOO_LOW 0 + +#define IGNORE_ZONE_CAL_MISSING_SAMPLES 0 +#define IGNORE_ZONE_CAL_SIGMA_TOO_HIGH 0 +#define IGNORE_ZONE_CAL_RATE_TOO_HIGH 0 + +#ifndef SUPPRESS_UNUSED_WARNING +#define SUPPRESS_UNUSED_WARNING(x) ((void) (x)) +#endif + +#define VL53LX_TRACE_LEVEL_NONE 0x00000000 +#define VL53LX_TRACE_LEVEL_ERRORS 0x00000001 +#define VL53LX_TRACE_LEVEL_WARNING 0x00000002 +#define VL53LX_TRACE_LEVEL_INFO 0x00000004 +#define VL53LX_TRACE_LEVEL_DEBUG 0x00000008 +#define VL53LX_TRACE_LEVEL_ALL 0x00000010 +#define VL53LX_TRACE_LEVEL_IGNORE 0x00000020 +#define VL53LX_TRACE_FUNCTION_NONE 0x00000000 +#define VL53LX_TRACE_FUNCTION_I2C 0x00000001 +#define VL53LX_TRACE_FUNCTION_ALL 0x7fffffff +#define VL53LX_TRACE_MODULE_NONE 0x00000000 +#define VL53LX_TRACE_MODULE_API 0x00000001 +#define VL53LX_TRACE_MODULE_CORE 0x00000002 +#define VL53LX_TRACE_MODULE_PROTECTED 0x00000004 +#define VL53LX_TRACE_MODULE_HISTOGRAM 0x00000008 +#define VL53LX_TRACE_MODULE_REGISTERS 0x00000010 +#define VL53LX_TRACE_MODULE_PLATFORM 0x00000020 +#define VL53LX_TRACE_MODULE_NVM 0x00000040 +#define VL53LX_TRACE_MODULE_CALIBRATION_DATA 0x00000080 +#define VL53LX_TRACE_MODULE_NVM_DATA 0x00000100 +#define VL53LX_TRACE_MODULE_HISTOGRAM_DATA 0x00000200 +#define VL53LX_TRACE_MODULE_RANGE_RESULTS_DATA 0x00000400 +#define VL53LX_TRACE_MODULE_XTALK_DATA 0x00000800 +#define VL53LX_TRACE_MODULE_OFFSET_DATA 0x00001000 +#define VL53LX_TRACE_MODULE_DATA_INIT 0x00002000 +#define VL53LX_TRACE_MODULE_REF_SPAD_CHAR 0x00004000 +#define VL53LX_TRACE_MODULE_SPAD_RATE_MAP 0x00008000 +#define VL53LX_TRACE_MODULE_CUSTOMER_API 0x40000000 +#define VL53LX_TRACE_MODULE_ALL 0x7fffffff + +#define DISABLE_WARNINGS() +#define ENABLE_WARNINGS() + +#define IGNORE_STATUS(__FUNCTION_ID__, __ERROR_STATUS_CHECK__, __STATUS__) \ + do { \ + DISABLE_WARNINGS(); \ + if (__FUNCTION_ID__) { \ + if (__STATUS__ == __ERROR_STATUS_CHECK__) { \ + __STATUS__ = VL53LX_ERROR_NONE; \ + } \ + } \ + ENABLE_WARNINGS(); \ + } \ + while (0) + +#define VL53LX_COPYSTRING(str, ...) \ + (strncpy(str, ##__VA_ARGS__, VL53LX_MAX_STRING_LENGTH-1)) + +#define VL53LX_RANGESTATUS_NONE 255 + +#define VL53LX_MAX_I2C_XFER_SIZE 256 + +#define STMVL53LX_CFG_MAX_DEV 2 + +#define do_division_u(dividend, divisor) div64_u64(dividend, divisor) +#define do_division_s(dividend, divisor) div64_s64(dividend, divisor) + +#define VL53LX_SPEED_OF_LIGHT_IN_AIR 299704 + +#define VL53LX_SPEED_OF_LIGHT_IN_AIR_DIV_8 (299704 >> 3) + +#define VL53LX_STATIC_NVM_MANAGED_I2C_SIZE_BYTES 11 + +#define VL53LX_STATIC_NVM_MANAGED_I2C_INDEX \ + VL53LX_I2C_SLAVE__DEVICE_ADDRESS +#define VL53LX_CUSTOMER_NVM_MANAGED_I2C_INDEX \ + VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_REF_0 +#define VL53LX_STATIC_CONFIG_I2C_INDEX \ + VL53LX_DSS_CONFIG__TARGET_TOTAL_RATE_MCPS +#define VL53LX_GENERAL_CONFIG_I2C_INDEX \ + VL53LX_GPH_CONFIG__STREAM_COUNT_UPDATE_VALUE +#define VL53LX_TIMING_CONFIG_I2C_INDEX \ + VL53LX_MM_CONFIG__TIMEOUT_MACROP_A_HI +#define VL53LX_DYNAMIC_CONFIG_I2C_INDEX \ + VL53LX_SYSTEM__GROUPED_PARAMETER_HOLD_0 +#define VL53LX_SYSTEM_CONTROL_I2C_INDEX \ + VL53LX_POWER_MANAGEMENT__GO1_POWER_FORCE +#define VL53LX_SYSTEM_RESULTS_I2C_INDEX \ + VL53LX_RESULT__INTERRUPT_STATUS +#define VL53LX_CORE_RESULTS_I2C_INDEX \ + VL53LX_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0 +#define VL53LX_DEBUG_RESULTS_I2C_INDEX \ + VL53LX_PHASECAL_RESULT__REFERENCE_PHASE +#define VL53LX_NVM_COPY_DATA_I2C_INDEX \ + VL53LX_IDENTIFICATION__MODEL_ID +#define VL53LX_PREV_SHADOW_SYSTEM_RESULTS_I2C_INDEX \ + VL53LX_PREV_SHADOW_RESULT__INTERRUPT_STATUS +#define VL53LX_PREV_SHADOW_CORE_RESULTS_I2C_INDEX \ + VL53LX_PREV_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0 +#define VL53LX_PATCH_DEBUG_I2C_INDEX \ + VL53LX_RESULT__DEBUG_STATUS +#define VL53LX_GPH_GENERAL_CONFIG_I2C_INDEX \ + VL53LX_GPH__SYSTEM__THRESH_RATE_HIGH +#define VL53LX_GPH_STATIC_CONFIG_I2C_INDEX \ + VL53LX_GPH__DSS_CONFIG__ROI_MODE_CONTROL +#define VL53LX_GPH_TIMING_CONFIG_I2C_INDEX \ + VL53LX_GPH__MM_CONFIG__TIMEOUT_MACROP_A_HI +#define VL53LX_FW_INTERNAL_I2C_INDEX \ + VL53LX_FIRMWARE__INTERNAL_STREAM_COUNT_DIV +#define VL53LX_PATCH_RESULTS_I2C_INDEX \ + VL53LX_DSS_CALC__ROI_CTRL +#define VL53LX_SHADOW_SYSTEM_RESULTS_I2C_INDEX \ + VL53LX_SHADOW_PHASECAL_RESULT__VCSEL_START +#define VL53LX_SHADOW_CORE_RESULTS_I2C_INDEX \ + VL53LX_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0 + +#define CONT_CONTINUE 0 +#define CONT_NEXT_LOOP 1 +#define CONT_RESET 2 + +#define VL53LX_STATIC_NVM_MANAGED_I2C_SIZE_BYTES 11 +#define VL53LX_CUSTOMER_NVM_MANAGED_I2C_SIZE_BYTES 23 +#define VL53LX_STATIC_CONFIG_I2C_SIZE_BYTES 32 +#define VL53LX_GENERAL_CONFIG_I2C_SIZE_BYTES 22 +#define VL53LX_TIMING_CONFIG_I2C_SIZE_BYTES 23 +#define VL53LX_DYNAMIC_CONFIG_I2C_SIZE_BYTES 18 +#define VL53LX_SYSTEM_CONTROL_I2C_SIZE_BYTES 5 +#define VL53LX_SYSTEM_RESULTS_I2C_SIZE_BYTES 44 +#define VL53LX_CORE_RESULTS_I2C_SIZE_BYTES 33 +#define VL53LX_DEBUG_RESULTS_I2C_SIZE_BYTES 56 +#define VL53LX_NVM_COPY_DATA_I2C_SIZE_BYTES 49 +#define VL53LX_PREV_SHADOW_SYSTEM_RESULTS_I2C_SIZE_BYTES 44 +#define VL53LX_PREV_SHADOW_CORE_RESULTS_I2C_SIZE_BYTES 33 +#define VL53LX_PATCH_DEBUG_I2C_SIZE_BYTES 2 +#define VL53LX_GPH_GENERAL_CONFIG_I2C_SIZE_BYTES 5 +#define VL53LX_GPH_STATIC_CONFIG_I2C_SIZE_BYTES 6 +#define VL53LX_GPH_TIMING_CONFIG_I2C_SIZE_BYTES 16 +#define VL53LX_FW_INTERNAL_I2C_SIZE_BYTES 2 +#define VL53LX_PATCH_RESULTS_I2C_SIZE_BYTES 90 +#define VL53LX_SHADOW_SYSTEM_RESULTS_I2C_SIZE_BYTES 82 +#define VL53LX_SHADOW_CORE_RESULTS_I2C_SIZE_BYTES 33 + +#define VL53LX_ADDITIONAL_CALIBRATION_DATA_STRUCT_VERSION 0x20 + +#define VL53LX_LL_CALIBRATION_DATA_STRUCT_VERSION 0xECAB0102 + +#define VL53LX_CALIBRATION_DATA_STRUCT_VERSION \ + (VL53LX_LL_CALIBRATION_DATA_STRUCT_VERSION + \ + VL53LX_ADDITIONAL_CALIBRATION_DATA_STRUCT_VERSION) + +#define VL53LX_RANGESTATUS_RANGE_VALID 0 +#define VL53LX_RANGESTATUS_SIGMA_FAIL 1 +#define VL53LX_RANGESTATUS_SIGNAL_FAIL 2 +#define VL53LX_RANGESTATUS_RANGE_VALID_MIN_RANGE_CLIPPED 3 +#define VL53LX_RANGESTATUS_OUTOFBOUNDS_FAIL 4 +#define VL53LX_RANGESTATUS_HARDWARE_FAIL 5 +#define VL53LX_RANGESTATUS_RANGE_VALID_NO_WRAP_CHECK_FAIL 6 +#define VL53LX_RANGESTATUS_WRAP_TARGET_FAIL 7 +#define VL53LX_RANGESTATUS_PROCESSING_FAIL 8 +#define VL53LX_RANGESTATUS_XTALK_SIGNAL_FAIL 9 +#define VL53LX_RANGESTATUS_SYNCRONISATION_INT 10 +#define VL53LX_RANGESTATUS_RANGE_VALID_MERGED_PULSE 11 +#define VL53LX_RANGESTATUS_TARGET_PRESENT_LACK_OF_SIGNAL 12 +#define VL53LX_RANGESTATUS_MIN_RANGE_FAIL 13 +#define VL53LX_RANGESTATUS_RANGE_INVALID 14 +#define VL53LX_RANGESTATUS_NONE 255 + +#define VL53LX_Dev_t VL53LX_DevData_t +#define VL53LX_DEV VL53LX_DevData_t * + +#define VL53LXDevDataGet(Dev, field) (Dev->field) +#define VL53LXDevDataSet(Dev, field, data) ((Dev->field) = (data)) + +#define VL53LXDevStructGetLLDriverHandle(Dev) (&VL53LXDevDataGet(Dev, LLData)) +#define VL53LXDevStructGetLLResultsHandle(Dev) (&VL53LXDevDataGet(Dev,\ + llresults)) + +#define VL53LX_SETPARAMETERFIELD(Dev, field, value) \ + (VL53LXDevDataSet(Dev, CurrentParameters.field, value)) + +#define VL53LX_GETPARAMETERFIELD(Dev, field, variable) \ + (variable = VL53LXDevDataGet(Dev, CurrentParameters).field) + +#define VL53LX_SETARRAYPARAMETERFIELD(Dev, field, index, value) \ + (VL53LXDevDataSet(Dev, CurrentParameters.field[index], value)) + +#define VL53LX_GETARRAYPARAMETERFIELD(Dev, field, index, variable) \ + (variable = VL53LXDevDataGet(Dev, CurrentParameters).field[index]) + +#define VL53LX_SETDEVICESPECIFICPARAMETER(Dev, field, value) \ + (VL53LXDevDataSet(Dev, DeviceSpecificParameters.field, value)) + +#define VL53LX_GETDEVICESPECIFICPARAMETER(Dev, field) \ + (VL53LXDevDataGet(Dev, DeviceSpecificParameters).field) + +#define stvm531_get_max_meas_err(...) 3 +#define stvm531_get_max_stream_err(...) 6 + +#define VL53LX_D_001 8 +#define VL53LX_D_002 0xFFFF +#define VL53LX_D_008 0xFFFF +#define VL53LX_D_003 0xFFFFFF +#define VL53LX_D_007 0xFFFFFFFF +#define VL53LX_D_005 0x7FFFFFFFFF +#define VL53LX_D_009 0xFFFFFFFFFF +#define VL53LX_D_010 0xFFFFFFFFFFFF +#define VL53LX_D_004 0xFFFFFFFFFFFFFF +#define VL53LX_D_006 0x7FFFFFFFFFFFFFFF +#define VL53LX_D_011 0xFFFFFFFFFFFFFFFF + + +typedef uint32_t FixPoint1616_t; + +#define VL53LX_FIXPOINT1616TOFIXPOINT44(Value) ((uint16_t)((Value>>12)&0xFFFF)) +#define VL53LX_FIXPOINT44TOFIXPOINT1616(Value) ((FixPoint1616_t)((uint32_t)Value<<12)) + +#define VL53LX_FIXPOINT1616TOFIXPOINT72(Value) ((uint16_t)((Value>>14)&0xFFFF)) +#define VL53LX_FIXPOINT72TOFIXPOINT1616(Value) ((FixPoint1616_t)((uint32_t)Value<<14)) + +#define VL53LX_FIXPOINT1616TOFIXPOINT97(Value) ((uint16_t)((Value>>9)&0xFFFF)) +#define VL53LX_FIXPOINT97TOFIXPOINT1616(Value) ((FixPoint1616_t)((uint32_t)Value<<9)) + +#define VL53LX_FIXPOINT1616TOFIXPOINT88(Value) ((uint16_t)((Value>>8)&0xFFFF)) +#define VL53LX_FIXPOINT88TOFIXPOINT1616(Value) ((FixPoint1616_t)((uint32_t)Value<<8)) + +#define VL53LX_FIXPOINT1616TOFIXPOINT412(Value) ((uint16_t)((Value>>4)&0xFFFF)) +#define VL53LX_FIXPOINT412TOFIXPOINT1616(Value) ((FixPoint1616_t)((uint32_t)Value<<4)) + +#define VL53LX_FIXPOINT1616TOFIXPOINT313(Value) ((uint16_t)((Value>>3)&0xFFFF)) +#define VL53LX_FIXPOINT313TOFIXPOINT1616(Value) ((FixPoint1616_t)((uint32_t)Value<<3)) + +#define VL53LX_FIXPOINT1616TOFIXPOINT08(Value) ((uint8_t)((Value>>8)&0x00FF)) +#define VL53LX_FIXPOINT08TOFIXPOINT1616(Value) ((FixPoint1616_t)((uint32_t)Value<<8)) + +#define VL53LX_FIXPOINT1616TOFIXPOINT53(Value) ((uint8_t)((Value>>13)&0x00FF)) +#define VL53LX_FIXPOINT53TOFIXPOINT1616(Value) ((FixPoint1616_t)((uint32_t)Value<<13)) + +#define VL53LX_FIXPOINT1616TOFIXPOINT102(Value) ((uint16_t)((Value>>14)&0x0FFF)) +#define VL53LX_FIXPOINT102TOFIXPOINT1616(Value) ((FixPoint1616_t)((uint32_t)Value<<14)) + +#define VL53LX_FIXPOINT1616TOFIXPOINT142(Value) ((uint16_t)((Value>>14)&0xFFFF)) +#define VL53LX_FIXPOINT142TOFIXPOINT1616(Value) ((FixPoint1616_t)((uint32_t)Value<<14)) + +#define VL53LX_FIXPOINT1616TOFIXPOINT160(Value) ((uint16_t)((Value>>16)&0xFFFF)) +#define VL53LX_FIXPOINT160TOFIXPOINT1616(Value) ((FixPoint1616_t)((uint32_t)Value<<16)) + +#define VL53LX_MAKEUINT16(lsb, msb) ((uint16_t)((((uint16_t)msb)<<8) + (uint16_t)lsb)) + +#define ABNORMAL_STOP_1 1 +#define ABNORMAL_STOP_2 2 +#define ABNORMAL_STOP_3 3 + +#define VL53LX_MISC_DEV_NAME "stmvl53lx_ranging" + +enum __stmv53lx_parameter_name_e { + VL53LX_XTALKENABLE_PAR = 2, + VL53LX_POLLDELAY_PAR = 10, + VL53LX_TIMINGBUDGET_PAR = 11, + VL53LX_DISTANCEMODE_PAR = 12, + VL53LX_FORCEDEVICEONEN_PAR = 14, + VL53LX_LASTERROR_PAR = 15, + VL53LX_OFFSETCORRECTIONMODE_PAR = 16, + VL53LX_OPTICALCENTER_PAR = 17, + VL53LX_TUNING_PAR = 20, + VL53LX_SMUDGECORRECTIONMODE_PAR = 21, + VL53LX_ISXTALKVALUECHANGED_PAR = 22, +}; +#define stmv53lx_parameter_name_e enum __stmv53lx_parameter_name_e + +struct stmvl53lx_parameter { + uint32_t is_read; + stmv53lx_parameter_name_e name; + int32_t value; + int32_t value2; + int32_t status; +}; + +typedef struct { + uint8_t TopLeftX; + uint8_t TopLeftY; + uint8_t BotRightX; + uint8_t BotRightY; +} VL53LX_UserRoi_t; + +struct stmvl53lx_ioctl_roi_t { + int32_t is_read; + VL53LX_UserRoi_t Roi; +}; + +typedef uint8_t VL53LX_WaitMethod; + +#define VL53LX_WAIT_METHOD_BLOCKING ((VL53LX_WaitMethod) 0) +#define VL53LX_WAIT_METHOD_NON_BLOCKING ((VL53LX_WaitMethod) 1) + +#define VL53LX_RETURN_ARRAY_ONLY 0x01 +#define VL53LX_REFERENCE_ARRAY_ONLY 0x10 +#define VL53LX_BOTH_RETURN_AND_REFERENCE_ARRAYS 0x11 +#define VL53LX_NEITHER_RETURN_AND_REFERENCE_ARRAYS 0x00 +#define VL53LX_DEVICEINTERRUPTLEVEL_ACTIVE_HIGH 0x00 +#define VL53LX_DEVICEINTERRUPTLEVEL_ACTIV +#define VL53LX_DEVICEINTERRUPTLEVEL_ACTIVE_MASK 0x10 +#define VL53LX_POLLING_DELAY_US 1000 +#define VL53LX_SOFTWARE_RESET_DURATION_US 100 +#define VL53LX_FIRMWARE_BOOT_TIME_US 1200 +#define VL53LX_ENABLE_POWERFORCE_SETTLING_TIME_US 250 +#define VL53LX_SPAD_ARRAY_WIDTH 16 +#define VL53LX_SPAD_ARRAY_HEIGHT 16 +#define VL53LX_NVM_SIZE_IN_BYTES 512 +#define VL53LX_NO_OF_SPAD_ENABLES 256 +#define VL53LX_RTN_SPAD_BUFFER_SIZE 32 +#define VL53LX_REF_SPAD_BUFFER_SIZE 6 +#define VL53LX_AMBIENT_WINDOW_VCSEL_PERIODS 256 +#define VL53LX_RANGING_WINDOW_VCSEL_PERIODS 2048 +#define VL53LX_MACRO_PERIOD_VCSEL_PERIODS \ + (VL53LX_AMBIENT_WINDOW_VCSEL_PERIODS + \ + VL53LX_RANGING_WINDOW_VCSEL_PERIODS) +#define VL53LX_MAX_ALLOWED_PHASE 0xFFFF +#define VL53LX_RTN_SPAD_UNITY_TRANSMISSION 0x0100 +#define VL53LX_RTN_SPAD_APERTURE_TRANSMISSION 0x0038 +#define VL53LX_SPAD_TOTAL_COUNT_MAX ((0x01 << 29) - 1) +#define VL53LX_SPAD_TOTAL_COUNT_RES_THRES (0x01 << 24) +#define VL53LX_COUNT_RATE_INTERNAL_MAX ((0x01 << 24) - 1) +#define VL53LX_SPEED_OF_LIGHT_IN_AIR 299704 +#define VL53LX_SPEED_OF_LIGHT_IN_AIR_DIV_8 (299704 >> 3) + +typedef uint8_t VL53LX_DeviceError; + +#define VL53LX_DEVICEERROR_NOUPDATE \ + ((VL53LX_DeviceError) 0) +#define VL53LX_DEVICEERROR_VCSELCONTINUITYTESTFAILURE \ + ((VL53LX_DeviceError) 1) +#define VL53LX_DEVICEERROR_VCSELWATCHDOGTESTFAILURE \ + ((VL53LX_DeviceError) 2) +#define VL53LX_DEVICEERROR_NOVHVVALUEFOUND \ + ((VL53LX_DeviceError) 3) +#define VL53LX_DEVICEERROR_MSRCNOTARGET \ + ((VL53LX_DeviceError) 4) +#define VL53LX_DEVICEERROR_RANGEPHASECHECK \ + ((VL53LX_DeviceError) 5) +#define VL53LX_DEVICEERROR_SIGMATHRESHOLDCHECK \ + ((VL53LX_DeviceError) 6) +#define VL53LX_DEVICEERROR_PHASECONSISTENCY \ + ((VL53LX_DeviceError) 7) +#define VL53LX_DEVICEERROR_MINCLIP \ + ((VL53LX_DeviceError) 8) +#define VL53LX_DEVICEERROR_RANGECOMPLETE \ + ((VL53LX_DeviceError) 9) +#define VL53LX_DEVICEERROR_ALGOUNDERFLOW \ + ((VL53LX_DeviceError) 10) +#define VL53LX_DEVICEERROR_ALGOOVERFLOW \ + ((VL53LX_DeviceError) 11) +#define VL53LX_DEVICEERROR_RANGEIGNORETHRESHOLD \ + ((VL53LX_DeviceError) 12) +#define VL53LX_DEVICEERROR_USERROICLIP \ + ((VL53LX_DeviceError) 13) +#define VL53LX_DEVICEERROR_REFSPADCHARNOTENOUGHDPADS \ + ((VL53LX_DeviceError) 14) +#define VL53LX_DEVICEERROR_REFSPADCHARMORETHANTARGET \ + ((VL53LX_DeviceError) 15) +#define VL53LX_DEVICEERROR_REFSPADCHARLESSTHANTARGET \ + ((VL53LX_DeviceError) 16) +#define VL53LX_DEVICEERROR_MULTCLIPFAIL \ + ((VL53LX_DeviceError) 17) +#define VL53LX_DEVICEERROR_GPHSTREAMCOUNT0READY \ + ((VL53LX_DeviceError) 18) +#define VL53LX_DEVICEERROR_RANGECOMPLETE_NO_WRAP_CHECK \ + ((VL53LX_DeviceError) 19) +#define VL53LX_DEVICEERROR_EVENTCONSISTENCY \ + ((VL53LX_DeviceError) 20) +#define VL53LX_DEVICEERROR_MINSIGNALEVENTCHECK \ + ((VL53LX_DeviceError) 21) +#define VL53LX_DEVICEERROR_RANGECOMPLETE_MERGED_PULSE \ + ((VL53LX_DeviceError) 22) +#define VL53LX_DEVICEERROR_PREV_RANGE_NO_TARGETS \ + ((VL53LX_DeviceError) 23) + +#define STMVL53LX_CFG_POLL_DELAY_MS 5 + +#define STMVL53LX_CFG_TIMING_BUDGET_US 30000 + +#define STMVL53LX_CFG_DEFAULT_DISTANCE_MODE VL53LX_DISTANCEMODE_MEDIUM + +#define STMVL53LX_CFG_DEFAULT_CROSSTALK_ENABLE 0 + +#define STMVL53LX_CFG_DEFAULT_OFFSET_CORRECTION_MODE \ + VL53LX_OFFSETCORRECTIONMODE_STANDARD + +#define STMVL53LX_CFG_DEFAULT_DMAX_MODE VL53LX_DMAXMODE_CUSTCAL_DATA + +#define STMVL53LX_CFG_DEFAULT_SMUDGE_CORRECTION_MODE \ + VL53LX_SMUDGE_CORRECTION_NONE + +#define VL53LX_NVM_PEAK_RATE_MAP_SAMPLES 25 + +#define VL53LX_NVM_PEAK_RATE_MAP_WIDTH 5 + +#define VL53LX_NVM_PEAK_RATE_MAP_HEIGHT 5 + +#define VL53LX_DSS_CONTROL__ROI_SUBTRACT 0x20 +#define VL53LX_DSS_CONTROL__ROI_INTERSECT 0x10 + +#define VL53LX_DSS_CONTROL__MODE_DISABLED 0x00 +#define VL53LX_DSS_CONTROL__MODE_TARGET_RATE 0x01 +#define VL53LX_DSS_CONTROL__MODE_EFFSPADS 0x02 +#define VL53LX_DSS_CONTROL__MODE_BLOCKSELECT 0x03 + +#define VL53LX_LL_API_IMPLEMENTATION_VER_MAJOR 1 + +#define VL53LX_LL_API_IMPLEMENTATION_VER_MINOR 1 + +#define VL53LX_LL_API_IMPLEMENTATION_VER_SUB 1 + +#define VL53LX_LL_API_IMPLEMENTATION_VER_REVISION 0 + +#define VL53LX_LL_API_IMPLEMENTATION_VER_STRING "1.1.1" + +#define VL53LX_SOFT_RESET 0x0000 +#define VL53LX_I2C_SLAVE__DEVICE_ADDRESS 0x0001 +#define VL53LX_ANA_CONFIG__VHV_REF_SEL_VDDPIX 0x0002 +#define VL53LX_ANA_CONFIG__VHV_REF_SEL_VQUENCH 0x0003 +#define VL53LX_ANA_CONFIG__REG_AVDD1V2_SEL 0x0004 +#define VL53LX_ANA_CONFIG__FAST_OSC__TRIM 0x0005 +#define VL53LX_OSC_MEASURED__FAST_OSC__FREQUENCY 0x0006 +#define VL53LX_OSC_MEASURED__FAST_OSC__FREQUENCY_HI 0x0006 +#define VL53LX_OSC_MEASURED__FAST_OSC__FREQUENCY_LO 0x0007 +#define VL53LX_VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND 0x0008 +#define VL53LX_VHV_CONFIG__COUNT_THRESH 0x0009 +#define VL53LX_VHV_CONFIG__OFFSET 0x000A +#define VL53LX_VHV_CONFIG__INIT 0x000B +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_REF_0 0x000D +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_REF_1 0x000E +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_REF_2 0x000F +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_REF_3 0x0010 +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_REF_4 0x0011 +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_REF_5 0x0012 +#define VL53LX_GLOBAL_CONFIG__REF_EN_START_SELECT 0x0013 +#define VL53LX_REF_SPAD_MAN__NUM_REQUESTED_REF_SPADS 0x0014 +#define VL53LX_REF_SPAD_MAN__REF_LOCATION 0x0015 +#define VL53LX_ALGO__CROSSTALK_COMPENSATION_PLANE_OFFSET_KCPS 0x0016 +#define VL53LX_ALGO__CROSSTALK_COMPENSATION_PLANE_OFFSET_KCPS_HI 0x0016 +#define VL53LX_ALGO__CROSSTALK_COMPENSATION_PLANE_OFFSET_KCPS_LO 0x0017 +#define VL53LX_ALGO__CROSSTALK_COMPENSATION_X_PLANE_GRADIENT_KCPS 0x0018 +#define VL53LX_ALGO__CROSSTALK_COMPENSATION_X_PLANE_GRADIENT_KCPS_HI 0x0018 +#define VL53LX_ALGO__CROSSTALK_COMPENSATION_X_PLANE_GRADIENT_KCPS_LO 0x0019 +#define VL53LX_ALGO__CROSSTALK_COMPENSATION_Y_PLANE_GRADIENT_KCPS 0x001A +#define VL53LX_ALGO__CROSSTALK_COMPENSATION_Y_PLANE_GRADIENT_KCPS_HI 0x001A +#define VL53LX_ALGO__CROSSTALK_COMPENSATION_Y_PLANE_GRADIENT_KCPS_LO 0x001B +#define VL53LX_REF_SPAD_CHAR__TOTAL_RATE_TARGET_MCPS 0x001C +#define VL53LX_REF_SPAD_CHAR__TOTAL_RATE_TARGET_MCPS_HI 0x001C +#define VL53LX_REF_SPAD_CHAR__TOTAL_RATE_TARGET_MCPS_LO 0x001D +#define VL53LX_ALGO__PART_TO_PART_RANGE_OFFSET_MM 0x001E +#define VL53LX_ALGO__PART_TO_PART_RANGE_OFFSET_MM_HI 0x001E +#define VL53LX_ALGO__PART_TO_PART_RANGE_OFFSET_MM_LO 0x001F +#define VL53LX_MM_CONFIG__INNER_OFFSET_MM 0x0020 +#define VL53LX_MM_CONFIG__INNER_OFFSET_MM_HI 0x0020 +#define VL53LX_MM_CONFIG__INNER_OFFSET_MM_LO 0x0021 +#define VL53LX_MM_CONFIG__OUTER_OFFSET_MM 0x0022 +#define VL53LX_MM_CONFIG__OUTER_OFFSET_MM_HI 0x0022 +#define VL53LX_MM_CONFIG__OUTER_OFFSET_MM_LO 0x0023 +#define VL53LX_DSS_CONFIG__TARGET_TOTAL_RATE_MCPS 0x0024 +#define VL53LX_DSS_CONFIG__TARGET_TOTAL_RATE_MCPS_HI 0x0024 +#define VL53LX_DSS_CONFIG__TARGET_TOTAL_RATE_MCPS_LO 0x0025 +#define VL53LX_DEBUG__CTRL 0x0026 +#define VL53LX_TEST_MODE__CTRL 0x0027 +#define VL53LX_CLK_GATING__CTRL 0x0028 +#define VL53LX_NVM_BIST__CTRL 0x0029 +#define VL53LX_NVM_BIST__NUM_NVM_WORDS 0x002A +#define VL53LX_NVM_BIST__START_ADDRESS 0x002B +#define VL53LX_HOST_IF__STATUS 0x002C +#define VL53LX_PAD_I2C_HV__CONFIG 0x002D +#define VL53LX_PAD_I2C_HV__EXTSUP_CONFIG 0x002E +#define VL53LX_GPIO_HV_PAD__CTRL 0x002F +#define VL53LX_GPIO_HV_MUX__CTRL 0x0030 +#define VL53LX_GPIO__TIO_HV_STATUS 0x0031 +#define VL53LX_GPIO__FIO_HV_STATUS 0x0032 +#define VL53LX_ANA_CONFIG__SPAD_SEL_PSWIDTH 0x0033 +#define VL53LX_ANA_CONFIG__VCSEL_PULSE_WIDTH_OFFSET 0x0034 +#define VL53LX_ANA_CONFIG__FAST_OSC__CONFIG_CTRL 0x0035 +#define VL53LX_SIGMA_ESTIMATOR__EFFECTIVE_PULSE_WIDTH_NS 0x0036 +#define VL53LX_SIGMA_ESTIMATOR__EFFECTIVE_AMBIENT_WIDTH_NS 0x0037 +#define VL53LX_SIGMA_ESTIMATOR__SIGMA_REF_MM 0x0038 +#define VL53LX_ALGO__CROSSTALK_COMPENSATION_VALID_HEIGHT_MM 0x0039 +#define VL53LX_SPARE_HOST_CONFIG__STATIC_CONFIG_SPARE_0 0x003A +#define VL53LX_SPARE_HOST_CONFIG__STATIC_CONFIG_SPARE_1 0x003B +#define VL53LX_ALGO__RANGE_IGNORE_THRESHOLD_MCPS 0x003C +#define VL53LX_ALGO__RANGE_IGNORE_THRESHOLD_MCPS_HI 0x003C +#define VL53LX_ALGO__RANGE_IGNORE_THRESHOLD_MCPS_LO 0x003D +#define VL53LX_ALGO__RANGE_IGNORE_VALID_HEIGHT_MM 0x003E +#define VL53LX_ALGO__RANGE_MIN_CLIP 0x003F +#define VL53LX_ALGO__CONSISTENCY_CHECK__TOLERANCE 0x0040 +#define VL53LX_SPARE_HOST_CONFIG__STATIC_CONFIG_SPARE_2 0x0041 +#define VL53LX_SD_CONFIG__RESET_STAGES_MSB 0x0042 +#define VL53LX_SD_CONFIG__RESET_STAGES_LSB 0x0043 +#define VL53LX_GPH_CONFIG__STREAM_COUNT_UPDATE_VALUE 0x0044 +#define VL53LX_GLOBAL_CONFIG__STREAM_DIVIDER 0x0045 +#define VL53LX_SYSTEM__INTERRUPT_CONFIG_GPIO 0x0046 +#define VL53LX_CAL_CONFIG__VCSEL_START 0x0047 +#define VL53LX_CAL_CONFIG__REPEAT_RATE 0x0048 +#define VL53LX_CAL_CONFIG__REPEAT_RATE_HI 0x0048 +#define VL53LX_CAL_CONFIG__REPEAT_RATE_LO 0x0049 +#define VL53LX_GLOBAL_CONFIG__VCSEL_WIDTH 0x004A +#define VL53LX_PHASECAL_CONFIG__TIMEOUT_MACROP 0x004B +#define VL53LX_PHASECAL_CONFIG__TARGET 0x004C +#define VL53LX_PHASECAL_CONFIG__OVERRIDE 0x004D +#define VL53LX_DSS_CONFIG__ROI_MODE_CONTROL 0x004F +#define VL53LX_SYSTEM__THRESH_RATE_HIGH 0x0050 +#define VL53LX_SYSTEM__THRESH_RATE_HIGH_HI 0x0050 +#define VL53LX_SYSTEM__THRESH_RATE_HIGH_LO 0x0051 +#define VL53LX_SYSTEM__THRESH_RATE_LOW 0x0052 +#define VL53LX_SYSTEM__THRESH_RATE_LOW_HI 0x0052 +#define VL53LX_SYSTEM__THRESH_RATE_LOW_LO 0x0053 +#define VL53LX_DSS_CONFIG__MANUAL_EFFECTIVE_SPADS_SELECT 0x0054 +#define VL53LX_DSS_CONFIG__MANUAL_EFFECTIVE_SPADS_SELECT_HI 0x0054 +#define VL53LX_DSS_CONFIG__MANUAL_EFFECTIVE_SPADS_SELECT_LO 0x0055 +#define VL53LX_DSS_CONFIG__MANUAL_BLOCK_SELECT 0x0056 +#define VL53LX_DSS_CONFIG__APERTURE_ATTENUATION 0x0057 +#define VL53LX_DSS_CONFIG__MAX_SPADS_LIMIT 0x0058 +#define VL53LX_DSS_CONFIG__MIN_SPADS_LIMIT 0x0059 +#define VL53LX_MM_CONFIG__TIMEOUT_MACROP_A_HI 0x005A +#define VL53LX_MM_CONFIG__TIMEOUT_MACROP_A_LO 0x005B +#define VL53LX_MM_CONFIG__TIMEOUT_MACROP_B_HI 0x005C +#define VL53LX_MM_CONFIG__TIMEOUT_MACROP_B_LO 0x005D +#define VL53LX_RANGE_CONFIG__TIMEOUT_MACROP_A_HI 0x005E +#define VL53LX_RANGE_CONFIG__TIMEOUT_MACROP_A_LO 0x005F +#define VL53LX_RANGE_CONFIG__VCSEL_PERIOD_A 0x0060 +#define VL53LX_RANGE_CONFIG__TIMEOUT_MACROP_B_HI 0x0061 +#define VL53LX_RANGE_CONFIG__TIMEOUT_MACROP_B_LO 0x0062 +#define VL53LX_RANGE_CONFIG__VCSEL_PERIOD_B 0x0063 +#define VL53LX_RANGE_CONFIG__SIGMA_THRESH 0x0064 +#define VL53LX_RANGE_CONFIG__SIGMA_THRESH_HI 0x0064 +#define VL53LX_RANGE_CONFIG__SIGMA_THRESH_LO 0x0065 +#define VL53LX_RANGE_CONFIG__MIN_COUNT_RATE_RTN_LIMIT_MCPS 0x0066 +#define VL53LX_RANGE_CONFIG__MIN_COUNT_RATE_RTN_LIMIT_MCPS_HI 0x0066 +#define VL53LX_RANGE_CONFIG__MIN_COUNT_RATE_RTN_LIMIT_MCPS_LO 0x0067 +#define VL53LX_RANGE_CONFIG__VALID_PHASE_LOW 0x0068 +#define VL53LX_RANGE_CONFIG__VALID_PHASE_HIGH 0x0069 +#define VL53LX_SYSTEM__INTERMEASUREMENT_PERIOD 0x006C +#define VL53LX_SYSTEM__INTERMEASUREMENT_PERIOD_3 0x006C +#define VL53LX_SYSTEM__INTERMEASUREMENT_PERIOD_2 0x006D +#define VL53LX_SYSTEM__INTERMEASUREMENT_PERIOD_1 0x006E +#define VL53LX_SYSTEM__INTERMEASUREMENT_PERIOD_0 0x006F +#define VL53LX_SYSTEM__FRACTIONAL_ENABLE 0x0070 +#define VL53LX_SYSTEM__GROUPED_PARAMETER_HOLD_0 0x0071 +#define VL53LX_SYSTEM__THRESH_HIGH 0x0072 +#define VL53LX_SYSTEM__THRESH_HIGH_HI 0x0072 +#define VL53LX_SYSTEM__THRESH_HIGH_LO 0x0073 +#define VL53LX_SYSTEM__THRESH_LOW 0x0074 +#define VL53LX_SYSTEM__THRESH_LOW_HI 0x0074 +#define VL53LX_SYSTEM__THRESH_LOW_LO 0x0075 +#define VL53LX_SYSTEM__ENABLE_XTALK_PER_QUADRANT 0x0076 +#define VL53LX_SYSTEM__SEED_CONFIG 0x0077 +#define VL53LX_SD_CONFIG__WOI_SD0 0x0078 +#define VL53LX_SD_CONFIG__WOI_SD1 0x0079 +#define VL53LX_SD_CONFIG__INITIAL_PHASE_SD0 0x007A +#define VL53LX_SD_CONFIG__INITIAL_PHASE_SD1 0x007B +#define VL53LX_SYSTEM__GROUPED_PARAMETER_HOLD_1 0x007C +#define VL53LX_SD_CONFIG__FIRST_ORDER_SELECT 0x007D +#define VL53LX_SD_CONFIG__QUANTIFIER 0x007E +#define VL53LX_ROI_CONFIG__USER_ROI_CENTRE_SPAD 0x007F +#define VL53LX_ROI_CONFIG__USER_ROI_REQUESTED_GLOBAL_XY_SIZE 0x0080 +#define VL53LX_SYSTEM__SEQUENCE_CONFIG 0x0081 +#define VL53LX_SYSTEM__GROUPED_PARAMETER_HOLD 0x0082 +#define VL53LX_POWER_MANAGEMENT__GO1_POWER_FORCE 0x0083 +#define VL53LX_SYSTEM__STREAM_COUNT_CTRL 0x0084 +#define VL53LX_FIRMWARE__ENABLE 0x0085 +#define VL53LX_SYSTEM__INTERRUPT_CLEAR 0x0086 +#define VL53LX_SYSTEM__MODE_START 0x0087 +#define VL53LX_RESULT__INTERRUPT_STATUS 0x0088 +#define VL53LX_RESULT__RANGE_STATUS 0x0089 +#define VL53LX_RESULT__REPORT_STATUS 0x008A +#define VL53LX_RESULT__STREAM_COUNT 0x008B +#define VL53LX_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0 0x008C +#define VL53LX_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0_HI 0x008C +#define VL53LX_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0_LO 0x008D +#define VL53LX_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD0 0x008E +#define VL53LX_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD0_HI 0x008E +#define VL53LX_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD0_LO 0x008F +#define VL53LX_RESULT__AMBIENT_COUNT_RATE_MCPS_SD0 0x0090 +#define VL53LX_RESULT__AMBIENT_COUNT_RATE_MCPS_SD0_HI 0x0090 +#define VL53LX_RESULT__AMBIENT_COUNT_RATE_MCPS_SD0_LO 0x0091 +#define VL53LX_RESULT__SIGMA_SD0 0x0092 +#define VL53LX_RESULT__SIGMA_SD0_HI 0x0092 +#define VL53LX_RESULT__SIGMA_SD0_LO 0x0093 +#define VL53LX_RESULT__PHASE_SD0 0x0094 +#define VL53LX_RESULT__PHASE_SD0_HI 0x0094 +#define VL53LX_RESULT__PHASE_SD0_LO 0x0095 +#define VL53LX_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0 0x0096 +#define VL53LX_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0_HI 0x0096 +#define VL53LX_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0_LO 0x0097 +#define VL53LX_PEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0 0x0098 +#define VL53LX__PEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0_HI 0x0098 +#define VL53LX___PEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0_LO 0x0099 +#define VL53LX_RESULT__MM_INNER_ACTUAL_EFFECTIVE_SPADS_SD0 0x009A +#define VL53LX_RESULT__MM_INNER_ACTUAL_EFFECTIVE_SPADS_SD0_HI 0x009A +#define VL53LX_RESULT__MM_INNER_ACTUAL_EFFECTIVE_SPADS_SD0_LO 0x009B +#define VL53LX_RESULT__MM_OUTER_ACTUAL_EFFECTIVE_SPADS_SD0 0x009C +#define VL53LX_RESULT__MM_OUTER_ACTUAL_EFFECTIVE_SPADS_SD0_HI 0x009C +#define VL53LX_RESULT__MM_OUTER_ACTUAL_EFFECTIVE_SPADS_SD0_LO 0x009D +#define VL53LX_RESULT__AVG_SIGNAL_COUNT_RATE_MCPS_SD0 0x009E +#define VL53LX_RESULT__AVG_SIGNAL_COUNT_RATE_MCPS_SD0_HI 0x009E +#define VL53LX_RESULT__AVG_SIGNAL_COUNT_RATE_MCPS_SD0_LO 0x009F +#define VL53LX_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD1 0x00A0 +#define VL53LX_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD1_HI 0x00A0 +#define VL53LX_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD1_LO 0x00A1 +#define VL53LX_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD1 0x00A2 +#define VL53LX_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD1_HI 0x00A2 +#define VL53LX_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD1_LO 0x00A3 +#define VL53LX_RESULT__AMBIENT_COUNT_RATE_MCPS_SD1 0x00A4 +#define VL53LX_RESULT__AMBIENT_COUNT_RATE_MCPS_SD1_HI 0x00A4 +#define VL53LX_RESULT__AMBIENT_COUNT_RATE_MCPS_SD1_LO 0x00A5 +#define VL53LX_RESULT__SIGMA_SD1 0x00A6 +#define VL53LX_RESULT__SIGMA_SD1_HI 0x00A6 +#define VL53LX_RESULT__SIGMA_SD1_LO 0x00A7 +#define VL53LX_RESULT__PHASE_SD1 0x00A8 +#define VL53LX_RESULT__PHASE_SD1_HI 0x00A8 +#define VL53LX_RESULT__PHASE_SD1_LO 0x00A9 +#define VL53LX_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD1 0x00AA +#define VL53LX_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD1_HI 0x00AA +#define VL53LX_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD1_LO 0x00AB +#define VL53LX_RESULT__SPARE_0_SD1 0x00AC +#define VL53LX_RESULT__SPARE_0_SD1_HI 0x00AC +#define VL53LX_RESULT__SPARE_0_SD1_LO 0x00AD +#define VL53LX_RESULT__SPARE_1_SD1 0x00AE +#define VL53LX_RESULT__SPARE_1_SD1_HI 0x00AE +#define VL53LX_RESULT__SPARE_1_SD1_LO 0x00AF +#define VL53LX_RESULT__SPARE_2_SD1 0x00B0 +#define VL53LX_RESULT__SPARE_2_SD1_HI 0x00B0 +#define VL53LX_RESULT__SPARE_2_SD1_LO 0x00B1 +#define VL53LX_RESULT__SPARE_3_SD1 0x00B2 +#define VL53LX_RESULT__THRESH_INFO 0x00B3 +#define VL53LX_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0 0x00B4 +#define VL53LX_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0_3 0x00B4 +#define VL53LX_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0_2 0x00B5 +#define VL53LX_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0_1 0x00B6 +#define VL53LX_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0_0 0x00B7 +#define VL53LX_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0 0x00B8 +#define VL53LX_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0_3 0x00B8 +#define VL53LX_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0_2 0x00B9 +#define VL53LX_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0_1 0x00BA +#define VL53LX_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0_0 0x00BB +#define VL53LX_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0 0x00BC +#define VL53LX_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0_3 0x00BC +#define VL53LX_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0_2 0x00BD +#define VL53LX_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0_1 0x00BE +#define VL53LX_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0_0 0x00BF +#define VL53LX_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0 0x00C0 +#define VL53LX_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0_3 0x00C0 +#define VL53LX_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0_2 0x00C1 +#define VL53LX_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0_1 0x00C2 +#define VL53LX_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0_0 0x00C3 +#define VL53LX_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1 0x00C4 +#define VL53LX_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1_3 0x00C4 +#define VL53LX_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1_2 0x00C5 +#define VL53LX_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1_1 0x00C6 +#define VL53LX_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1_0 0x00C7 +#define VL53LX_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1 0x00C8 +#define VL53LX_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1_3 0x00C8 +#define VL53LX_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1_2 0x00C9 +#define VL53LX_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1_1 0x00CA +#define VL53LX_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1_0 0x00CB +#define VL53LX_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1 0x00CC +#define VL53LX_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1_3 0x00CC +#define VL53LX_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1_2 0x00CD +#define VL53LX_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1_1 0x00CE +#define VL53LX_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1_0 0x00CF +#define VL53LX_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1 0x00D0 +#define VL53LX_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1_3 0x00D0 +#define VL53LX_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1_2 0x00D1 +#define VL53LX_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1_1 0x00D2 +#define VL53LX_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1_0 0x00D3 +#define VL53LX_RESULT_CORE__SPARE_0 0x00D4 +#define VL53LX_PHASECAL_RESULT__REFERENCE_PHASE 0x00D6 +#define VL53LX_PHASECAL_RESULT__REFERENCE_PHASE_HI 0x00D6 +#define VL53LX_PHASECAL_RESULT__REFERENCE_PHASE_LO 0x00D7 +#define VL53LX_PHASECAL_RESULT__VCSEL_START 0x00D8 +#define VL53LX_REF_SPAD_CHAR_RESULT__NUM_ACTUAL_REF_SPADS 0x00D9 +#define VL53LX_REF_SPAD_CHAR_RESULT__REF_LOCATION 0x00DA +#define VL53LX_VHV_RESULT__COLDBOOT_STATUS 0x00DB +#define VL53LX_VHV_RESULT__SEARCH_RESULT 0x00DC +#define VL53LX_VHV_RESULT__LATEST_SETTING 0x00DD +#define VL53LX_RESULT__OSC_CALIBRATE_VAL 0x00DE +#define VL53LX_RESULT__OSC_CALIBRATE_VAL_HI 0x00DE +#define VL53LX_RESULT__OSC_CALIBRATE_VAL_LO 0x00DF +#define VL53LX_ANA_CONFIG__POWERDOWN_GO1 0x00E0 +#define VL53LX_ANA_CONFIG__REF_BG_CTRL 0x00E1 +#define VL53LX_ANA_CONFIG__REGDVDD1V2_CTRL 0x00E2 +#define VL53LX_ANA_CONFIG__OSC_SLOW_CTRL 0x00E3 +#define VL53LX_TEST_MODE__STATUS 0x00E4 +#define VL53LX_FIRMWARE__SYSTEM_STATUS 0x00E5 +#define VL53LX_FIRMWARE__MODE_STATUS 0x00E6 +#define VL53LX_FIRMWARE__SECONDARY_MODE_STATUS 0x00E7 +#define VL53LX_FIRMWARE__CAL_REPEAT_RATE_COUNTER 0x00E8 +#define VL53LX_FIRMWARE__CAL_REPEAT_RATE_COUNTER_HI 0x00E8 +#define VL53LX_FIRMWARE__CAL_REPEAT_RATE_COUNTER_LO 0x00E9 +#define VL53LX_FIRMWARE__HISTOGRAM_BIN 0x00EA +#define VL53LX_GPH__SYSTEM__THRESH_HIGH 0x00EC +#define VL53LX_GPH__SYSTEM__THRESH_HIGH_HI 0x00EC +#define VL53LX_GPH__SYSTEM__THRESH_HIGH_LO 0x00ED +#define VL53LX_GPH__SYSTEM__THRESH_LOW 0x00EE +#define VL53LX_GPH__SYSTEM__THRESH_LOW_HI 0x00EE +#define VL53LX_GPH__SYSTEM__THRESH_LOW_LO 0x00EF +#define VL53LX_GPH__SYSTEM__ENABLE_XTALK_PER_QUADRANT 0x00F0 +#define VL53LX_GPH__SPARE_0 0x00F1 +#define VL53LX_GPH__SD_CONFIG__WOI_SD0 0x00F2 +#define VL53LX_GPH__SD_CONFIG__WOI_SD1 0x00F3 +#define VL53LX_GPH__SD_CONFIG__INITIAL_PHASE_SD0 0x00F4 +#define VL53LX_GPH__SD_CONFIG__INITIAL_PHASE_SD1 0x00F5 +#define VL53LX_GPH__SD_CONFIG__FIRST_ORDER_SELECT 0x00F6 +#define VL53LX_GPH__SD_CONFIG__QUANTIFIER 0x00F7 +#define VL53LX_GPH__ROI_CONFIG__USER_ROI_CENTRE_SPAD 0x00F8 +#define VL53LX_GPH__ROI_CONFIG__USER_ROI_REQUESTED_GLOBAL_XY_SIZE 0x00F9 +#define VL53LX_GPH__SYSTEM__SEQUENCE_CONFIG 0x00FA +#define VL53LX_GPH__GPH_ID 0x00FB +#define VL53LX_SYSTEM__INTERRUPT_SET 0x00FC +#define VL53LX_INTERRUPT_MANAGER__ENABLES 0x00FD +#define VL53LX_INTERRUPT_MANAGER__CLEAR 0x00FE +#define VL53LX_INTERRUPT_MANAGER__STATUS 0x00FF +#define VL53LX_MCU_TO_HOST_BANK__WR_ACCESS_EN 0x0100 +#define VL53LX_POWER_MANAGEMENT__GO1_RESET_STATUS 0x0101 +#define VL53LX_PAD_STARTUP_MODE__VALUE_RO 0x0102 +#define VL53LX_PAD_STARTUP_MODE__VALUE_CTRL 0x0103 +#define VL53LX_PLL_PERIOD_US 0x0104 +#define VL53LX_PLL_PERIOD_US_3 0x0104 +#define VL53LX_PLL_PERIOD_US_2 0x0105 +#define VL53LX_PLL_PERIOD_US_1 0x0106 +#define VL53LX_PLL_PERIOD_US_0 0x0107 +#define VL53LX_INTERRUPT_SCHEDULER__DATA_OUT 0x0108 +#define VL53LX_INTERRUPT_SCHEDULER__DATA_OUT_3 0x0108 +#define VL53LX_INTERRUPT_SCHEDULER__DATA_OUT_2 0x0109 +#define VL53LX_INTERRUPT_SCHEDULER__DATA_OUT_1 0x010A +#define VL53LX_INTERRUPT_SCHEDULER__DATA_OUT_0 0x010B +#define VL53LX_NVM_BIST__COMPLETE 0x010C +#define VL53LX_NVM_BIST__STATUS 0x010D +#define VL53LX_IDENTIFICATION__MODEL_ID 0x010F +#define VL53LX_IDENTIFICATION__MODULE_TYPE 0x0110 +#define VL53LX_IDENTIFICATION__REVISION_ID 0x0111 +#define VL53LX_IDENTIFICATION__MODULE_ID 0x0112 +#define VL53LX_IDENTIFICATION__MODULE_ID_HI 0x0112 +#define VL53LX_IDENTIFICATION__MODULE_ID_LO 0x0113 +#define VL53LX_ANA_CONFIG__FAST_OSC__TRIM_MAX 0x0114 +#define VL53LX_ANA_CONFIG__FAST_OSC__FREQ_SET 0x0115 +#define VL53LX_ANA_CONFIG__VCSEL_TRIM 0x0116 +#define VL53LX_ANA_CONFIG__VCSEL_SELION 0x0117 +#define VL53LX_ANA_CONFIG__VCSEL_SELION_MAX 0x0118 +#define VL53LX_PROTECTED_LASER_SAFETY__LOCK_BIT 0x0119 +#define VL53LX_LASER_SAFETY__KEY 0x011A +#define VL53LX_LASER_SAFETY__KEY_RO 0x011B +#define VL53LX_LASER_SAFETY__CLIP 0x011C +#define VL53LX_LASER_SAFETY__MULT 0x011D +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_RTN_0 0x011E +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_RTN_1 0x011F +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_RTN_2 0x0120 +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_RTN_3 0x0121 +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_RTN_4 0x0122 +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_RTN_5 0x0123 +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_RTN_6 0x0124 +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_RTN_7 0x0125 +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_RTN_8 0x0126 +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_RTN_9 0x0127 +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_RTN_10 0x0128 +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_RTN_11 0x0129 +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_RTN_12 0x012A +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_RTN_13 0x012B +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_RTN_14 0x012C +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_RTN_15 0x012D +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_RTN_16 0x012E +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_RTN_17 0x012F +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_RTN_18 0x0130 +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_RTN_19 0x0131 +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_RTN_20 0x0132 +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_RTN_21 0x0133 +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_RTN_22 0x0134 +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_RTN_23 0x0135 +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_RTN_24 0x0136 +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_RTN_25 0x0137 +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_RTN_26 0x0138 +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_RTN_27 0x0139 +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_RTN_28 0x013A +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_RTN_29 0x013B +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_RTN_30 0x013C +#define VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_RTN_31 0x013D +#define VL53LX_ROI_CONFIG__MODE_ROI_CENTRE_SPAD 0x013E +#define VL53LX_ROI_CONFIG__MODE_ROI_XY_SIZE 0x013F +#define VL53LX_GO2_HOST_BANK_ACCESS__OVERRIDE 0x0300 +#define VL53LX_MCU_UTIL_MULTIPLIER__MULTIPLICAND 0x0400 +#define VL53LX_MCU_UTIL_MULTIPLIER__MULTIPLICAND_3 0x0400 +#define VL53LX_MCU_UTIL_MULTIPLIER__MULTIPLICAND_2 0x0401 +#define VL53LX_MCU_UTIL_MULTIPLIER__MULTIPLICAND_1 0x0402 +#define VL53LX_MCU_UTIL_MULTIPLIER__MULTIPLICAND_0 0x0403 +#define VL53LX_MCU_UTIL_MULTIPLIER__MULTIPLIER 0x0404 +#define VL53LX_MCU_UTIL_MULTIPLIER__MULTIPLIER_3 0x0404 +#define VL53LX_MCU_UTIL_MULTIPLIER__MULTIPLIER_2 0x0405 +#define VL53LX_MCU_UTIL_MULTIPLIER__MULTIPLIER_1 0x0406 +#define VL53LX_MCU_UTIL_MULTIPLIER__MULTIPLIER_0 0x0407 +#define VL53LX_MCU_UTIL_MULTIPLIER__PRODUCT_HI 0x0408 +#define VL53LX_MCU_UTIL_MULTIPLIER__PRODUCT_HI_3 0x0408 +#define VL53LX_MCU_UTIL_MULTIPLIER__PRODUCT_HI_2 0x0409 +#define VL53LX_MCU_UTIL_MULTIPLIER__PRODUCT_HI_1 0x040A +#define VL53LX_MCU_UTIL_MULTIPLIER__PRODUCT_HI_0 0x040B +#define VL53LX_MCU_UTIL_MULTIPLIER__PRODUCT_LO 0x040C +#define VL53LX_MCU_UTIL_MULTIPLIER__PRODUCT_LO_3 0x040C +#define VL53LX_MCU_UTIL_MULTIPLIER__PRODUCT_LO_2 0x040D +#define VL53LX_MCU_UTIL_MULTIPLIER__PRODUCT_LO_1 0x040E +#define VL53LX_MCU_UTIL_MULTIPLIER__PRODUCT_LO_0 0x040F +#define VL53LX_MCU_UTIL_MULTIPLIER__START 0x0410 +#define VL53LX_MCU_UTIL_MULTIPLIER__STATUS 0x0411 +#define VL53LX_MCU_UTIL_DIVIDER__START 0x0412 +#define VL53LX_MCU_UTIL_DIVIDER__STATUS 0x0413 +#define VL53LX_MCU_UTIL_DIVIDER__DIVIDEND 0x0414 +#define VL53LX_MCU_UTIL_DIVIDER__DIVIDEND_3 0x0414 +#define VL53LX_MCU_UTIL_DIVIDER__DIVIDEND_2 0x0415 +#define VL53LX_MCU_UTIL_DIVIDER__DIVIDEND_1 0x0416 +#define VL53LX_MCU_UTIL_DIVIDER__DIVIDEND_0 0x0417 +#define VL53LX_MCU_UTIL_DIVIDER__DIVISOR 0x0418 +#define VL53LX_MCU_UTIL_DIVIDER__DIVISOR_3 0x0418 +#define VL53LX_MCU_UTIL_DIVIDER__DIVISOR_2 0x0419 +#define VL53LX_MCU_UTIL_DIVIDER__DIVISOR_1 0x041A +#define VL53LX_MCU_UTIL_DIVIDER__DIVISOR_0 0x041B +#define VL53LX_MCU_UTIL_DIVIDER__QUOTIENT 0x041C +#define VL53LX_MCU_UTIL_DIVIDER__QUOTIENT_3 0x041C +#define VL53LX_MCU_UTIL_DIVIDER__QUOTIENT_2 0x041D +#define VL53LX_MCU_UTIL_DIVIDER__QUOTIENT_1 0x041E +#define VL53LX_MCU_UTIL_DIVIDER__QUOTIENT_0 0x041F +#define VL53LX_TIMER0__VALUE_IN 0x0420 +#define VL53LX_TIMER0__VALUE_IN_3 0x0420 +#define VL53LX_TIMER0__VALUE_IN_2 0x0421 +#define VL53LX_TIMER0__VALUE_IN_1 0x0422 +#define VL53LX_TIMER0__VALUE_IN_0 0x0423 +#define VL53LX_TIMER1__VALUE_IN 0x0424 +#define VL53LX_TIMER1__VALUE_IN_3 0x0424 +#define VL53LX_TIMER1__VALUE_IN_2 0x0425 +#define VL53LX_TIMER1__VALUE_IN_1 0x0426 +#define VL53LX_TIMER1__VALUE_IN_0 0x0427 +#define VL53LX_TIMER0__CTRL 0x0428 +#define VL53LX_TIMER1__CTRL 0x0429 +#define VL53LX_MCU_GENERAL_PURPOSE__GP_0 0x042C +#define VL53LX_MCU_GENERAL_PURPOSE__GP_1 0x042D +#define VL53LX_MCU_GENERAL_PURPOSE__GP_2 0x042E +#define VL53LX_MCU_GENERAL_PURPOSE__GP_3 0x042F +#define VL53LX_MCU_RANGE_CALC__CONFIG 0x0430 +#define VL53LX_MCU_RANGE_CALC__OFFSET_CORRECTED_RANGE 0x0432 +#define VL53LX_MCU_RANGE_CALC__OFFSET_CORRECTED_RANGE_HI 0x0432 +#define VL53LX_MCU_RANGE_CALC__OFFSET_CORRECTED_RANGE_LO 0x0433 +#define VL53LX_MCU_RANGE_CALC__SPARE_4 0x0434 +#define VL53LX_MCU_RANGE_CALC__SPARE_4_3 0x0434 +#define VL53LX_MCU_RANGE_CALC__SPARE_4_2 0x0435 +#define VL53LX_MCU_RANGE_CALC__SPARE_4_1 0x0436 +#define VL53LX_MCU_RANGE_CALC__SPARE_4_0 0x0437 +#define VL53LX_MCU_RANGE_CALC__AMBIENT_DURATION_PRE_CALC 0x0438 +#define VL53LX_MCU_RANGE_CALC__AMBIENT_DURATION_PRE_CALC_HI 0x0438 +#define VL53LX_MCU_RANGE_CALC__AMBIENT_DURATION_PRE_CALC_LO 0x0439 +#define VL53LX_MCU_RANGE_CALC__ALGO_VCSEL_PERIOD 0x043C +#define VL53LX_MCU_RANGE_CALC__SPARE_5 0x043D +#define VL53LX_MCU_RANGE_CALC__ALGO_TOTAL_PERIODS 0x043E +#define VL53LX_MCU_RANGE_CALC__ALGO_TOTAL_PERIODS_HI 0x043E +#define VL53LX_MCU_RANGE_CALC__ALGO_TOTAL_PERIODS_LO 0x043F +#define VL53LX_MCU_RANGE_CALC__ALGO_ACCUM_PHASE 0x0440 +#define VL53LX_MCU_RANGE_CALC__ALGO_ACCUM_PHASE_3 0x0440 +#define VL53LX_MCU_RANGE_CALC__ALGO_ACCUM_PHASE_2 0x0441 +#define VL53LX_MCU_RANGE_CALC__ALGO_ACCUM_PHASE_1 0x0442 +#define VL53LX_MCU_RANGE_CALC__ALGO_ACCUM_PHASE_0 0x0443 +#define VL53LX_MCU_RANGE_CALC__ALGO_SIGNAL_EVENTS 0x0444 +#define VL53LX_MCU_RANGE_CALC__ALGO_SIGNAL_EVENTS_3 0x0444 +#define VL53LX_MCU_RANGE_CALC__ALGO_SIGNAL_EVENTS_2 0x0445 +#define VL53LX_MCU_RANGE_CALC__ALGO_SIGNAL_EVENTS_1 0x0446 +#define VL53LX_MCU_RANGE_CALC__ALGO_SIGNAL_EVENTS_0 0x0447 +#define VL53LX_MCU_RANGE_CALC__ALGO_AMBIENT_EVENTS 0x0448 +#define VL53LX_MCU_RANGE_CALC__ALGO_AMBIENT_EVENTS_3 0x0448 +#define VL53LX_MCU_RANGE_CALC__ALGO_AMBIENT_EVENTS_2 0x0449 +#define VL53LX_MCU_RANGE_CALC__ALGO_AMBIENT_EVENTS_1 0x044A +#define VL53LX_MCU_RANGE_CALC__ALGO_AMBIENT_EVENTS_0 0x044B +#define VL53LX_MCU_RANGE_CALC__SPARE_6 0x044C +#define VL53LX_MCU_RANGE_CALC__SPARE_6_HI 0x044C +#define VL53LX_MCU_RANGE_CALC__SPARE_6_LO 0x044D +#define VL53LX_MCU_RANGE_CALC__ALGO_ADJUST_VCSEL_PERIOD 0x044E +#define VL53LX_MCU_RANGE_CALC__ALGO_ADJUST_VCSEL_PERIOD_HI 0x044E +#define VL53LX_MCU_RANGE_CALC__ALGO_ADJUST_VCSEL_PERIOD_LO 0x044F +#define VL53LX_MCU_RANGE_CALC__NUM_SPADS 0x0450 +#define VL53LX_MCU_RANGE_CALC__NUM_SPADS_HI 0x0450 +#define VL53LX_MCU_RANGE_CALC__NUM_SPADS_LO 0x0451 +#define VL53LX_MCU_RANGE_CALC__PHASE_OUTPUT 0x0452 +#define VL53LX_MCU_RANGE_CALC__PHASE_OUTPUT_HI 0x0452 +#define VL53LX_MCU_RANGE_CALC__PHASE_OUTPUT_LO 0x0453 +#define VL53LX_MCU_RANGE_CALC__RATE_PER_SPAD_MCPS 0x0454 +#define VL53LX_MCU_RANGE_CALC__RATE_PER_SPAD_MCPS_3 0x0454 +#define VL53LX_MCU_RANGE_CALC__RATE_PER_SPAD_MCPS_2 0x0455 +#define VL53LX_MCU_RANGE_CALC__RATE_PER_SPAD_MCPS_1 0x0456 +#define VL53LX_MCU_RANGE_CALC__RATE_PER_SPAD_MCPS_0 0x0457 +#define VL53LX_MCU_RANGE_CALC__SPARE_7 0x0458 +#define VL53LX_MCU_RANGE_CALC__SPARE_8 0x0459 +#define VL53LX_MCU_RANGE_CALC__PEAK_SIGNAL_RATE_MCPS 0x045A +#define VL53LX_MCU_RANGE_CALC__PEAK_SIGNAL_RATE_MCPS_HI 0x045A +#define VL53LX_MCU_RANGE_CALC__PEAK_SIGNAL_RATE_MCPS_LO 0x045B +#define VL53LX_MCU_RANGE_CALC__AVG_SIGNAL_RATE_MCPS 0x045C +#define VL53LX_MCU_RANGE_CALC__AVG_SIGNAL_RATE_MCPS_HI 0x045C +#define VL53LX_MCU_RANGE_CALC__AVG_SIGNAL_RATE_MCPS_LO 0x045D +#define VL53LX_MCU_RANGE_CALC__AMBIENT_RATE_MCPS 0x045E +#define VL53LX_MCU_RANGE_CALC__AMBIENT_RATE_MCPS_HI 0x045E +#define VL53LX_MCU_RANGE_CALC__AMBIENT_RATE_MCPS_LO 0x045F +#define VL53LX_MCU_RANGE_CALC__XTALK 0x0460 +#define VL53LX_MCU_RANGE_CALC__XTALK_HI 0x0460 +#define VL53LX_MCU_RANGE_CALC__XTALK_LO 0x0461 +#define VL53LX_MCU_RANGE_CALC__CALC_STATUS 0x0462 +#define VL53LX_MCU_RANGE_CALC__DEBUG 0x0463 +#define VL53LX_MCU_RANGE_CALC__PEAK_SIGNAL_RATE_XTALK_CORR_MCPS 0x0464 +#define VL53LX_MCU_RANGE_CALC__PEAK_SIGNAL_RATE_XTALK_CORR_MCPS_HI 0x0464 +#define VL53LX_MCU_RANGE_CALC__PEAK_SIGNAL_RATE_XTALK_CORR_MCPS_LO 0x0465 +#define VL53LX_MCU_RANGE_CALC__SPARE_0 0x0468 +#define VL53LX_MCU_RANGE_CALC__SPARE_1 0x0469 +#define VL53LX_MCU_RANGE_CALC__SPARE_2 0x046A +#define VL53LX_MCU_RANGE_CALC__SPARE_3 0x046B +#define VL53LX_PATCH__CTRL 0x0470 +#define VL53LX_PATCH__JMP_ENABLES 0x0472 +#define VL53LX_PATCH__JMP_ENABLES_HI 0x0472 +#define VL53LX_PATCH__JMP_ENABLES_LO 0x0473 +#define VL53LX_PATCH__DATA_ENABLES 0x0474 +#define VL53LX_PATCH__DATA_ENABLES_HI 0x0474 +#define VL53LX_PATCH__DATA_ENABLES_LO 0x0475 +#define VL53LX_PATCH__OFFSET_0 0x0476 +#define VL53LX_PATCH__OFFSET_0_HI 0x0476 +#define VL53LX_PATCH__OFFSET_0_LO 0x0477 +#define VL53LX_PATCH__OFFSET_1 0x0478 +#define VL53LX_PATCH__OFFSET_1_HI 0x0478 +#define VL53LX_PATCH__OFFSET_1_LO 0x0479 +#define VL53LX_PATCH__OFFSET_2 0x047A +#define VL53LX_PATCH__OFFSET_2_HI 0x047A +#define VL53LX_PATCH__OFFSET_2_LO 0x047B +#define VL53LX_PATCH__OFFSET_3 0x047C +#define VL53LX_PATCH__OFFSET_3_HI 0x047C +#define VL53LX_PATCH__OFFSET_3_LO 0x047D +#define VL53LX_PATCH__OFFSET_4 0x047E +#define VL53LX_PATCH__OFFSET_4_HI 0x047E +#define VL53LX_PATCH__OFFSET_4_LO 0x047F +#define VL53LX_PATCH__OFFSET_5 0x0480 +#define VL53LX_PATCH__OFFSET_5_HI 0x0480 +#define VL53LX_PATCH__OFFSET_5_LO 0x0481 +#define VL53LX_PATCH__OFFSET_6 0x0482 +#define VL53LX_PATCH__OFFSET_6_HI 0x0482 +#define VL53LX_PATCH__OFFSET_6_LO 0x0483 +#define VL53LX_PATCH__OFFSET_7 0x0484 +#define VL53LX_PATCH__OFFSET_7_HI 0x0484 +#define VL53LX_PATCH__OFFSET_7_LO 0x0485 +#define VL53LX_PATCH__OFFSET_8 0x0486 +#define VL53LX_PATCH__OFFSET_8_HI 0x0486 +#define VL53LX_PATCH__OFFSET_8_LO 0x0487 +#define VL53LX_PATCH__OFFSET_9 0x0488 +#define VL53LX_PATCH__OFFSET_9_HI 0x0488 +#define VL53LX_PATCH__OFFSET_9_LO 0x0489 +#define VL53LX_PATCH__OFFSET_10 0x048A +#define VL53LX_PATCH__OFFSET_10_HI 0x048A +#define VL53LX_PATCH__OFFSET_10_LO 0x048B +#define VL53LX_PATCH__OFFSET_11 0x048C +#define VL53LX_PATCH__OFFSET_11_HI 0x048C +#define VL53LX_PATCH__OFFSET_11_LO 0x048D +#define VL53LX_PATCH__OFFSET_12 0x048E +#define VL53LX_PATCH__OFFSET_12_HI 0x048E +#define VL53LX_PATCH__OFFSET_12_LO 0x048F +#define VL53LX_PATCH__OFFSET_13 0x0490 +#define VL53LX_PATCH__OFFSET_13_HI 0x0490 +#define VL53LX_PATCH__OFFSET_13_LO 0x0491 +#define VL53LX_PATCH__OFFSET_14 0x0492 +#define VL53LX_PATCH__OFFSET_14_HI 0x0492 +#define VL53LX_PATCH__OFFSET_14_LO 0x0493 +#define VL53LX_PATCH__OFFSET_15 0x0494 +#define VL53LX_PATCH__OFFSET_15_HI 0x0494 +#define VL53LX_PATCH__OFFSET_15_LO 0x0495 +#define VL53LX_PATCH__ADDRESS_0 0x0496 +#define VL53LX_PATCH__ADDRESS_0_HI 0x0496 +#define VL53LX_PATCH__ADDRESS_0_LO 0x0497 +#define VL53LX_PATCH__ADDRESS_1 0x0498 +#define VL53LX_PATCH__ADDRESS_1_HI 0x0498 +#define VL53LX_PATCH__ADDRESS_1_LO 0x0499 +#define VL53LX_PATCH__ADDRESS_2 0x049A +#define VL53LX_PATCH__ADDRESS_2_HI 0x049A +#define VL53LX_PATCH__ADDRESS_2_LO 0x049B +#define VL53LX_PATCH__ADDRESS_3 0x049C +#define VL53LX_PATCH__ADDRESS_3_HI 0x049C +#define VL53LX_PATCH__ADDRESS_3_LO 0x049D +#define VL53LX_PATCH__ADDRESS_4 0x049E +#define VL53LX_PATCH__ADDRESS_4_HI 0x049E +#define VL53LX_PATCH__ADDRESS_4_LO 0x049F +#define VL53LX_PATCH__ADDRESS_5 0x04A0 +#define VL53LX_PATCH__ADDRESS_5_HI 0x04A0 +#define VL53LX_PATCH__ADDRESS_5_LO 0x04A1 +#define VL53LX_PATCH__ADDRESS_6 0x04A2 +#define VL53LX_PATCH__ADDRESS_6_HI 0x04A2 +#define VL53LX_PATCH__ADDRESS_6_LO 0x04A3 +#define VL53LX_PATCH__ADDRESS_7 0x04A4 +#define VL53LX_PATCH__ADDRESS_7_HI 0x04A4 +#define VL53LX_PATCH__ADDRESS_7_LO 0x04A5 +#define VL53LX_PATCH__ADDRESS_8 0x04A6 +#define VL53LX_PATCH__ADDRESS_8_HI 0x04A6 +#define VL53LX_PATCH__ADDRESS_8_LO 0x04A7 +#define VL53LX_PATCH__ADDRESS_9 0x04A8 +#define VL53LX_PATCH__ADDRESS_9_HI 0x04A8 +#define VL53LX_PATCH__ADDRESS_9_LO 0x04A9 +#define VL53LX_PATCH__ADDRESS_10 0x04AA +#define VL53LX_PATCH__ADDRESS_10_HI 0x04AA +#define VL53LX_PATCH__ADDRESS_10_LO 0x04AB +#define VL53LX_PATCH__ADDRESS_11 0x04AC +#define VL53LX_PATCH__ADDRESS_11_HI 0x04AC +#define VL53LX_PATCH__ADDRESS_11_LO 0x04AD +#define VL53LX_PATCH__ADDRESS_12 0x04AE +#define VL53LX_PATCH__ADDRESS_12_HI 0x04AE +#define VL53LX_PATCH__ADDRESS_12_LO 0x04AF +#define VL53LX_PATCH__ADDRESS_13 0x04B0 +#define VL53LX_PATCH__ADDRESS_13_HI 0x04B0 +#define VL53LX_PATCH__ADDRESS_13_LO 0x04B1 +#define VL53LX_PATCH__ADDRESS_14 0x04B2 +#define VL53LX_PATCH__ADDRESS_14_HI 0x04B2 +#define VL53LX_PATCH__ADDRESS_14_LO 0x04B3 +#define VL53LX_PATCH__ADDRESS_15 0x04B4 +#define VL53LX_PATCH__ADDRESS_15_HI 0x04B4 +#define VL53LX_PATCH__ADDRESS_15_LO 0x04B5 +#define VL53LX_SPI_ASYNC_MUX__CTRL 0x04C0 +#define VL53LX_CLK__CONFIG 0x04C4 +#define VL53LX_GPIO_LV_MUX__CTRL 0x04CC +#define VL53LX_GPIO_LV_PAD__CTRL 0x04CD +#define VL53LX_PAD_I2C_LV__CONFIG 0x04D0 +#define VL53LX_PAD_STARTUP_MODE__VALUE_RO_GO1 0x04D4 +#define VL53LX_HOST_IF__STATUS_GO1 0x04D5 +#define VL53LX_MCU_CLK_GATING__CTRL 0x04D8 +#define VL53LX_TEST__BIST_ROM_CTRL 0x04E0 +#define VL53LX_TEST__BIST_ROM_RESULT 0x04E1 +#define VL53LX_TEST__BIST_ROM_MCU_SIG 0x04E2 +#define VL53LX_TEST__BIST_ROM_MCU_SIG_HI 0x04E2 +#define VL53LX_TEST__BIST_ROM_MCU_SIG_LO 0x04E3 +#define VL53LX_TEST__BIST_RAM_CTRL 0x04E4 +#define VL53LX_TEST__BIST_RAM_RESULT 0x04E5 +#define VL53LX_TEST__TMC 0x04E8 +#define VL53LX_TEST__PLL_BIST_MIN_THRESHOLD 0x04F0 +#define VL53LX_TEST__PLL_BIST_MIN_THRESHOLD_HI 0x04F0 +#define VL53LX_TEST__PLL_BIST_MIN_THRESHOLD_LO 0x04F1 +#define VL53LX_TEST__PLL_BIST_MAX_THRESHOLD 0x04F2 +#define VL53LX_TEST__PLL_BIST_MAX_THRESHOLD_HI 0x04F2 +#define VL53LX_TEST__PLL_BIST_MAX_THRESHOLD_LO 0x04F3 +#define VL53LX_TEST__PLL_BIST_COUNT_OUT 0x04F4 +#define VL53LX_TEST__PLL_BIST_COUNT_OUT_HI 0x04F4 +#define VL53LX_TEST__PLL_BIST_COUNT_OUT_LO 0x04F5 +#define VL53LX_TEST__PLL_BIST_GONOGO 0x04F6 +#define VL53LX_TEST__PLL_BIST_CTRL 0x04F7 +#define VL53LX_RANGING_CORE__DEVICE_ID 0x0680 +#define VL53LX_RANGING_CORE__REVISION_ID 0x0681 +#define VL53LX_RANGING_CORE__CLK_CTRL1 0x0683 +#define VL53LX_RANGING_CORE__CLK_CTRL2 0x0684 +#define VL53LX_RANGING_CORE__WOI_1 0x0685 +#define VL53LX_RANGING_CORE__WOI_REF_1 0x0686 +#define VL53LX_RANGING_CORE__START_RANGING 0x0687 +#define VL53LX_RANGING_CORE__LOW_LIMIT_1 0x0690 +#define VL53LX_RANGING_CORE__HIGH_LIMIT_1 0x0691 +#define VL53LX_RANGING_CORE__LOW_LIMIT_REF_1 0x0692 +#define VL53LX_RANGING_CORE__HIGH_LIMIT_REF_1 0x0693 +#define VL53LX_RANGING_CORE__QUANTIFIER_1_MSB 0x0694 +#define VL53LX_RANGING_CORE__QUANTIFIER_1_LSB 0x0695 +#define VL53LX_RANGING_CORE__QUANTIFIER_REF_1_MSB 0x0696 +#define VL53LX_RANGING_CORE__QUANTIFIER_REF_1_LSB 0x0697 +#define VL53LX_RANGING_CORE__AMBIENT_OFFSET_1_MSB 0x0698 +#define VL53LX_RANGING_CORE__AMBIENT_OFFSET_1_LSB 0x0699 +#define VL53LX_RANGING_CORE__AMBIENT_OFFSET_REF_1_MSB 0x069A +#define VL53LX_RANGING_CORE__AMBIENT_OFFSET_REF_1_LSB 0x069B +#define VL53LX_RANGING_CORE__FILTER_STRENGTH_1 0x069C +#define VL53LX_RANGING_CORE__FILTER_STRENGTH_REF_1 0x069D +#define VL53LX_RANGING_CORE__SIGNAL_EVENT_LIMIT_1_MSB 0x069E +#define VL53LX_RANGING_CORE__SIGNAL_EVENT_LIMIT_1_LSB 0x069F +#define VL53LX_RANGING_CORE__SIGNAL_EVENT_LIMIT_REF_1_MSB 0x06A0 +#define VL53LX_RANGING_CORE__SIGNAL_EVENT_LIMIT_REF_1_LSB 0x06A1 +#define VL53LX_RANGING_CORE__TIMEOUT_OVERALL_PERIODS_MSB 0x06A4 +#define VL53LX_RANGING_CORE__TIMEOUT_OVERALL_PERIODS_LSB 0x06A5 +#define VL53LX_RANGING_CORE__INVERT_HW 0x06A6 +#define VL53LX_RANGING_CORE__FORCE_HW 0x06A7 +#define VL53LX_RANGING_CORE__STATIC_HW_VALUE 0x06A8 +#define VL53LX_RANGING_CORE__FORCE_CONTINUOUS_AMBIENT 0x06A9 +#define VL53LX_RANGING_CORE__TEST_PHASE_SELECT_TO_FILTER 0x06AA +#define VL53LX_RANGING_CORE__TEST_PHASE_SELECT_TO_TIMING_GEN 0x06AB +#define VL53LX_RANGING_CORE__INITIAL_PHASE_VALUE_1 0x06AC +#define VL53LX_RANGING_CORE__INITIAL_PHASE_VALUE_REF_1 0x06AD +#define VL53LX_RANGING_CORE__FORCE_UP_IN 0x06AE +#define VL53LX_RANGING_CORE__FORCE_DN_IN 0x06AF +#define VL53LX_RANGING_CORE__STATIC_UP_VALUE_1 0x06B0 +#define VL53LX_RANGING_CORE__STATIC_UP_VALUE_REF_1 0x06B1 +#define VL53LX_RANGING_CORE__STATIC_DN_VALUE_1 0x06B2 +#define VL53LX_RANGING_CORE__STATIC_DN_VALUE_REF_1 0x06B3 +#define VL53LX_RANGING_CORE__MONITOR_UP_DN 0x06B4 +#define VL53LX_RANGING_CORE__INVERT_UP_DN 0x06B5 +#define VL53LX_RANGING_CORE__CPUMP_1 0x06B6 +#define VL53LX_RANGING_CORE__CPUMP_2 0x06B7 +#define VL53LX_RANGING_CORE__CPUMP_3 0x06B8 +#define VL53LX_RANGING_CORE__OSC_1 0x06B9 +#define VL53LX_RANGING_CORE__PLL_1 0x06BB +#define VL53LX_RANGING_CORE__PLL_2 0x06BC +#define VL53LX_RANGING_CORE__REFERENCE_1 0x06BD +#define VL53LX_RANGING_CORE__REFERENCE_3 0x06BF +#define VL53LX_RANGING_CORE__REFERENCE_4 0x06C0 +#define VL53LX_RANGING_CORE__REFERENCE_5 0x06C1 +#define VL53LX_RANGING_CORE__REGAVDD1V2 0x06C3 +#define VL53LX_RANGING_CORE__CALIB_1 0x06C4 +#define VL53LX_RANGING_CORE__CALIB_2 0x06C5 +#define VL53LX_RANGING_CORE__CALIB_3 0x06C6 +#define VL53LX_RANGING_CORE__TST_MUX_SEL1 0x06C9 +#define VL53LX_RANGING_CORE__TST_MUX_SEL2 0x06CA +#define VL53LX_RANGING_CORE__TST_MUX 0x06CB +#define VL53LX_RANGING_CORE__GPIO_OUT_TESTMUX 0x06CC +#define VL53LX_RANGING_CORE__CUSTOM_FE 0x06CD +#define VL53LX_RANGING_CORE__CUSTOM_FE_2 0x06CE +#define VL53LX_RANGING_CORE__SPAD_READOUT 0x06CF +#define VL53LX_RANGING_CORE__SPAD_READOUT_1 0x06D0 +#define VL53LX_RANGING_CORE__SPAD_READOUT_2 0x06D1 +#define VL53LX_RANGING_CORE__SPAD_PS 0x06D2 +#define VL53LX_RANGING_CORE__LASER_SAFETY_2 0x06D4 +#define VL53LX_RANGING_CORE__NVM_CTRL__MODE 0x0780 +#define VL53LX_RANGING_CORE__NVM_CTRL__PDN 0x0781 +#define VL53LX_RANGING_CORE__NVM_CTRL__PROGN 0x0782 +#define VL53LX_RANGING_CORE__NVM_CTRL__READN 0x0783 +#define VL53LX_RANGING_CORE__NVM_CTRL__PULSE_WIDTH_MSB 0x0784 +#define VL53LX_RANGING_CORE__NVM_CTRL__PULSE_WIDTH_LSB 0x0785 +#define VL53LX_RANGING_CORE__NVM_CTRL__HV_RISE_MSB 0x0786 +#define VL53LX_RANGING_CORE__NVM_CTRL__HV_RISE_LSB 0x0787 +#define VL53LX_RANGING_CORE__NVM_CTRL__HV_FALL_MSB 0x0788 +#define VL53LX_RANGING_CORE__NVM_CTRL__HV_FALL_LSB 0x0789 +#define VL53LX_RANGING_CORE__NVM_CTRL__TST 0x078A +#define VL53LX_RANGING_CORE__NVM_CTRL__TESTREAD 0x078B +#define VL53LX_RANGING_CORE__NVM_CTRL__DATAIN_MMM 0x078C +#define VL53LX_RANGING_CORE__NVM_CTRL__DATAIN_LMM 0x078D +#define VL53LX_RANGING_CORE__NVM_CTRL__DATAIN_LLM 0x078E +#define VL53LX_RANGING_CORE__NVM_CTRL__DATAIN_LLL 0x078F +#define VL53LX_RANGING_CORE__NVM_CTRL__DATAOUT_MMM 0x0790 +#define VL53LX_RANGING_CORE__NVM_CTRL__DATAOUT_LMM 0x0791 +#define VL53LX_RANGING_CORE__NVM_CTRL__DATAOUT_LLM 0x0792 +#define VL53LX_RANGING_CORE__NVM_CTRL__DATAOUT_LLL 0x0793 +#define VL53LX_RANGING_CORE__NVM_CTRL__ADDR 0x0794 +#define VL53LX_RANGING_CORE__NVM_CTRL__DATAOUT_ECC 0x0795 +#define VL53LX_RANGING_CORE__RET_SPAD_EN_0 0x0796 +#define VL53LX_RANGING_CORE__RET_SPAD_EN_1 0x0797 +#define VL53LX_RANGING_CORE__RET_SPAD_EN_2 0x0798 +#define VL53LX_RANGING_CORE__RET_SPAD_EN_3 0x0799 +#define VL53LX_RANGING_CORE__RET_SPAD_EN_4 0x079A +#define VL53LX_RANGING_CORE__RET_SPAD_EN_5 0x079B +#define VL53LX_RANGING_CORE__RET_SPAD_EN_6 0x079C +#define VL53LX_RANGING_CORE__RET_SPAD_EN_7 0x079D +#define VL53LX_RANGING_CORE__RET_SPAD_EN_8 0x079E +#define VL53LX_RANGING_CORE__RET_SPAD_EN_9 0x079F +#define VL53LX_RANGING_CORE__RET_SPAD_EN_10 0x07A0 +#define VL53LX_RANGING_CORE__RET_SPAD_EN_11 0x07A1 +#define VL53LX_RANGING_CORE__RET_SPAD_EN_12 0x07A2 +#define VL53LX_RANGING_CORE__RET_SPAD_EN_13 0x07A3 +#define VL53LX_RANGING_CORE__RET_SPAD_EN_14 0x07A4 +#define VL53LX_RANGING_CORE__RET_SPAD_EN_15 0x07A5 +#define VL53LX_RANGING_CORE__RET_SPAD_EN_16 0x07A6 +#define VL53LX_RANGING_CORE__RET_SPAD_EN_17 0x07A7 +#define VL53LX_RANGING_CORE__SPAD_SHIFT_EN 0x07BA +#define VL53LX_RANGING_CORE__SPAD_DISABLE_CTRL 0x07BB +#define VL53LX_RANGING_CORE__SPAD_EN_SHIFT_OUT_DEBUG 0x07BC +#define VL53LX_RANGING_CORE__SPI_MODE 0x07BD +#define VL53LX_RANGING_CORE__GPIO_DIR 0x07BE +#define VL53LX_RANGING_CORE__VCSEL_PERIOD 0x0880 +#define VL53LX_RANGING_CORE__VCSEL_START 0x0881 +#define VL53LX_RANGING_CORE__VCSEL_STOP 0x0882 +#define VL53LX_RANGING_CORE__VCSEL_1 0x0885 +#define VL53LX_RANGING_CORE__VCSEL_STATUS 0x088D +#define VL53LX_RANGING_CORE__STATUS 0x0980 +#define VL53LX_RANGING_CORE__LASER_CONTINUITY_STATE 0x0981 +#define VL53LX_RANGING_CORE__RANGE_1_MMM 0x0982 +#define VL53LX_RANGING_CORE__RANGE_1_LMM 0x0983 +#define VL53LX_RANGING_CORE__RANGE_1_LLM 0x0984 +#define VL53LX_RANGING_CORE__RANGE_1_LLL 0x0985 +#define VL53LX_RANGING_CORE__RANGE_REF_1_MMM 0x0986 +#define VL53LX_RANGING_CORE__RANGE_REF_1_LMM 0x0987 +#define VL53LX_RANGING_CORE__RANGE_REF_1_LLM 0x0988 +#define VL53LX_RANGING_CORE__RANGE_REF_1_LLL 0x0989 +#define VL53LX_RANGING_CORE__AMBIENT_WINDOW_EVENTS_1_MMM 0x098A +#define VL53LX_RANGING_CORE__AMBIENT_WINDOW_EVENTS_1_LMM 0x098B +#define VL53LX_RANGING_CORE__AMBIENT_WINDOW_EVENTS_1_LLM 0x098C +#define VL53LX_RANGING_CORE__AMBIENT_WINDOW_EVENTS_1_LLL 0x098D +#define VL53LX_RANGING_CORE__RANGING_TOTAL_EVENTS_1_MMM 0x098E +#define VL53LX_RANGING_CORE__RANGING_TOTAL_EVENTS_1_LMM 0x098F +#define VL53LX_RANGING_CORE__RANGING_TOTAL_EVENTS_1_LLM 0x0990 +#define VL53LX_RANGING_CORE__RANGING_TOTAL_EVENTS_1_LLL 0x0991 +#define VL53LX_RANGING_CORE__SIGNAL_TOTAL_EVENTS_1_MMM 0x0992 +#define VL53LX_RANGING_CORE__SIGNAL_TOTAL_EVENTS_1_LMM 0x0993 +#define VL53LX_RANGING_CORE__SIGNAL_TOTAL_EVENTS_1_LLM 0x0994 +#define VL53LX_RANGING_CORE__SIGNAL_TOTAL_EVENTS_1_LLL 0x0995 +#define VL53LX_RANGING_CORE__TOTAL_PERIODS_ELAPSED_1_MM 0x0996 +#define VL53LX_RANGING_CORE__TOTAL_PERIODS_ELAPSED_1_LM 0x0997 +#define VL53LX_RANGING_CORE__TOTAL_PERIODS_ELAPSED_1_LL 0x0998 +#define VL53LX_RANGING_CORE__AMBIENT_MISMATCH_MM 0x0999 +#define VL53LX_RANGING_CORE__AMBIENT_MISMATCH_LM 0x099A +#define VL53LX_RANGING_CORE__AMBIENT_MISMATCH_LL 0x099B +#define VL53LX_RANGING_CORE__AMBIENT_WINDOW_EVENTS_REF_1_MMM 0x099C +#define VL53LX_RANGING_CORE__AMBIENT_WINDOW_EVENTS_REF_1_LMM 0x099D +#define VL53LX_RANGING_CORE__AMBIENT_WINDOW_EVENTS_REF_1_LLM 0x099E +#define VL53LX_RANGING_CORE__AMBIENT_WINDOW_EVENTS_REF_1_LLL 0x099F +#define VL53LX_RANGING_CORE__RANGING_TOTAL_EVENTS_REF_1_MMM 0x09A0 +#define VL53LX_RANGING_CORE__RANGING_TOTAL_EVENTS_REF_1_LMM 0x09A1 +#define VL53LX_RANGING_CORE__RANGING_TOTAL_EVENTS_REF_1_LLM 0x09A2 +#define VL53LX_RANGING_CORE__RANGING_TOTAL_EVENTS_REF_1_LLL 0x09A3 +#define VL53LX_RANGING_CORE__SIGNAL_TOTAL_EVENTS_REF_1_MMM 0x09A4 +#define VL53LX_RANGING_CORE__SIGNAL_TOTAL_EVENTS_REF_1_LMM 0x09A5 +#define VL53LX_RANGING_CORE__SIGNAL_TOTAL_EVENTS_REF_1_LLM 0x09A6 +#define VL53LX_RANGING_CORE__SIGNAL_TOTAL_EVENTS_REF_1_LLL 0x09A7 +#define VL53LX_RANGING_CORE__TOTAL_PERIODS_ELAPSED_REF_1_MM 0x09A8 +#define VL53LX_RANGING_CORE__TOTAL_PERIODS_ELAPSED_REF_1_LM 0x09A9 +#define VL53LX_RANGING_CORE__TOTAL_PERIODS_ELAPSED_REF_1_LL 0x09AA +#define VL53LX_RANGING_CORE__AMBIENT_MISMATCH_REF_MM 0x09AB +#define VL53LX_RANGING_CORE__AMBIENT_MISMATCH_REF_LM 0x09AC +#define VL53LX_RANGING_CORE__AMBIENT_MISMATCH_REF_LL 0x09AD +#define VL53LX_RANGING_CORE__GPIO_CONFIG__A0 0x0A00 +#define VL53LX_RANGING_CORE__RESET_CONTROL__A0 0x0A01 +#define VL53LX_RANGING_CORE__INTR_MANAGER__A0 0x0A02 +#define VL53LX_RANGING_CORE__POWER_FSM_TIME_OSC__A0 0x0A06 +#define VL53LX_RANGING_CORE__VCSEL_ATEST__A0 0x0A07 +#define VL53LX_RANGING_CORE__VCSEL_PERIOD_CLIPPED__A0 0x0A08 +#define VL53LX_RANGING_CORE__VCSEL_STOP_CLIPPED__A0 0x0A09 +#define VL53LX_RANGING_CORE__CALIB_2__A0 0x0A0A +#define VL53LX_RANGING_CORE__STOP_CONDITION__A0 0x0A0B +#define VL53LX_RANGING_CORE__STATUS_RESET__A0 0x0A0C +#define VL53LX_RANGING_CORE__READOUT_CFG__A0 0x0A0D +#define VL53LX_RANGING_CORE__WINDOW_SETTING__A0 0x0A0E +#define VL53LX_RANGING_CORE__VCSEL_DELAY__A0 0x0A1A +#define VL53LX_RANGING_CORE__REFERENCE_2__A0 0x0A1B +#define VL53LX_RANGING_CORE__REGAVDD1V2__A0 0x0A1D +#define VL53LX_RANGING_CORE__TST_MUX__A0 0x0A1F +#define VL53LX_RANGING_CORE__CUSTOM_FE_2__A0 0x0A20 +#define VL53LX_RANGING_CORE__SPAD_READOUT__A0 0x0A21 +#define VL53LX_RANGING_CORE__CPUMP_1__A0 0x0A22 +#define VL53LX_RANGING_CORE__SPARE_REGISTER__A0 0x0A23 +#define VL53LX_RANGING_CORE__VCSEL_CONT_STAGE5_BYPASS__A0 0x0A24 +#define VL53LX_RANGING_CORE__RET_SPAD_EN_18 0x0A25 +#define VL53LX_RANGING_CORE__RET_SPAD_EN_19 0x0A26 +#define VL53LX_RANGING_CORE__RET_SPAD_EN_20 0x0A27 +#define VL53LX_RANGING_CORE__RET_SPAD_EN_21 0x0A28 +#define VL53LX_RANGING_CORE__RET_SPAD_EN_22 0x0A29 +#define VL53LX_RANGING_CORE__RET_SPAD_EN_23 0x0A2A +#define VL53LX_RANGING_CORE__RET_SPAD_EN_24 0x0A2B +#define VL53LX_RANGING_CORE__RET_SPAD_EN_25 0x0A2C +#define VL53LX_RANGING_CORE__RET_SPAD_EN_26 0x0A2D +#define VL53LX_RANGING_CORE__RET_SPAD_EN_27 0x0A2E +#define VL53LX_RANGING_CORE__RET_SPAD_EN_28 0x0A2F +#define VL53LX_RANGING_CORE__RET_SPAD_EN_29 0x0A30 +#define VL53LX_RANGING_CORE__RET_SPAD_EN_30 0x0A31 +#define VL53LX_RANGING_CORE__RET_SPAD_EN_31 0x0A32 +#define VL53LX_RANGING_CORE__REF_SPAD_EN_0__EWOK 0x0A33 +#define VL53LX_RANGING_CORE__REF_SPAD_EN_1__EWOK 0x0A34 +#define VL53LX_RANGING_CORE__REF_SPAD_EN_2__EWOK 0x0A35 +#define VL53LX_RANGING_CORE__REF_SPAD_EN_3__EWOK 0x0A36 +#define VL53LX_RANGING_CORE__REF_SPAD_EN_4__EWOK 0x0A37 +#define VL53LX_RANGING_CORE__REF_SPAD_EN_5__EWOK 0x0A38 +#define VL53LX_RANGING_CORE__REF_EN_START_SELECT 0x0A39 +#define VL53LX_RANGING_CORE__REGDVDD1V2_ATEST__EWOK 0x0A41 +#define VL53LX_PRIVATE__PATCH_BASE_ADDR_RSLV 0x0E00 +#define VL53LX_PREV_SHADOW_RESULT__INTERRUPT_STATUS 0x0ED0 +#define VL53LX_PREV_SHADOW_RESULT__RANGE_STATUS 0x0ED1 +#define VL53LX_PREV_SHADOW_RESULT__REPORT_STATUS 0x0ED2 +#define VL53LX_PREV_SHADOW_RESULT__STREAM_COUNT 0x0ED3 +#define VL53LX_PREV_SHADOW_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0 0x0ED4 +#define VL53LX_PREV_SHADOW_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0_HI 0x0ED4 +#define VL53LX_PREV_SHADOW_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0_LO 0x0ED5 +#define VL53LX_PREV_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD0 0x0ED6 +#define VL53LX_PREV_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD0_HI 0x0ED6 +#define VL53LX_PREV_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD0_LO 0x0ED7 +#define VL53LX_PREV_SHADOW_RESULT__AMBIENT_COUNT_RATE_MCPS_SD0 0x0ED8 +#define VL53LX_PREV_SHADOW_RESULT__AMBIENT_COUNT_RATE_MCPS_SD0_HI 0x0ED8 +#define VL53LX_PREV_SHADOW_RESULT__AMBIENT_COUNT_RATE_MCPS_SD0_LO 0x0ED9 +#define VL53LX_PREV_SHADOW_RESULT__SIGMA_SD0 0x0EDA +#define VL53LX_PREV_SHADOW_RESULT__SIGMA_SD0_HI 0x0EDA +#define VL53LX_PREV_SHADOW_RESULT__SIGMA_SD0_LO 0x0EDB +#define VL53LX_PREV_SHADOW_RESULT__PHASE_SD0 0x0EDC +#define VL53LX_PREV_SHADOW_RESULT__PHASE_SD0_HI 0x0EDC +#define VL53LX_PREV_SHADOW_RESULT__PHASE_SD0_LO 0x0EDD +#define VL53LX_PREV_SHADOW_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0 0x0EDE +#define VL53LX_PREV__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0_HI 0x0EDE +#define VL53LX_PREV__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0_LO 0x0EDF +#define VL53LX_PREV__PEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0 0x0EE0 +#define VL53LX_PPEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0_HI 0x0EE0 +#define VL53LX_PPEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0_LO 0x0EE1 +#define VL53LX_PREV_SHADOW_RESULT__MM_INNER_ACTUAL_EFFECTIVE_SPADS_SD0 0x0EE2 +#define VL53LX_PREV_SHADOW_RESULT__MM_INNER_ACTUAL_EFFECTIVE_SPADS_SD0_HI 0x0EE2 +#define VL53LX_PREV_SHADOW_RESULT__MM_INNER_ACTUAL_EFFECTIVE_SPADS_SD0_LO 0x0EE3 +#define VL53LX_PREV_SHADOW_RESULT__MM_OUTER_ACTUAL_EFFECTIVE_SPADS_SD0 0x0EE4 +#define VL53LX_PREV_SHADOW_RESULT__MM_OUTER_ACTUAL_EFFECTIVE_SPADS_SD0_HI 0x0EE4 +#define VL53LX_PREV_SHADOW_RESULT__MM_OUTER_ACTUAL_EFFECTIVE_SPADS_SD0_LO 0x0EE5 +#define VL53LX_PREV_SHADOW_RESULT__AVG_SIGNAL_COUNT_RATE_MCPS_SD0 0x0EE6 +#define VL53LX_PREV_SHADOW_RESULT__AVG_SIGNAL_COUNT_RATE_MCPS_SD0_HI 0x0EE6 +#define VL53LX_PREV_SHADOW_RESULT__AVG_SIGNAL_COUNT_RATE_MCPS_SD0_LO 0x0EE7 +#define VL53LX_PREV_SHADOW_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD1 0x0EE8 +#define VL53LX_PREV_SHADOW_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD1_HI 0x0EE8 +#define VL53LX_PREV_SHADOW_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD1_LO 0x0EE9 +#define VL53LX_PREV_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD1 0x0EEA +#define VL53LX_PREV_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD1_HI 0x0EEA +#define VL53LX_PREV_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD1_LO 0x0EEB +#define VL53LX_PREV_SHADOW_RESULT__AMBIENT_COUNT_RATE_MCPS_SD1 0x0EEC +#define VL53LX_PREV_SHADOW_RESULT__AMBIENT_COUNT_RATE_MCPS_SD1_HI 0x0EEC +#define VL53LX_PREV_SHADOW_RESULT__AMBIENT_COUNT_RATE_MCPS_SD1_LO 0x0EED +#define VL53LX_PREV_SHADOW_RESULT__SIGMA_SD1 0x0EEE +#define VL53LX_PREV_SHADOW_RESULT__SIGMA_SD1_HI 0x0EEE +#define VL53LX_PREV_SHADOW_RESULT__SIGMA_SD1_LO 0x0EEF +#define VL53LX_PREV_SHADOW_RESULT__PHASE_SD1 0x0EF0 +#define VL53LX_PREV_SHADOW_RESULT__PHASE_SD1_HI 0x0EF0 +#define VL53LX_PREV_SHADOW_RESULT__PHASE_SD1_LO 0x0EF1 +#define VL53LX_PREV_SHADOW_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD1 0x0EF2 +#define VL53LX_PFINAL_CROSSTALK_CORRECTED_RANGE_MM_SD1_HI 0x0EF2 +#define VL53LX_PFINAL_CROSSTALK_CORRECTED_RANGE_MM_SD1_LO 0x0EF3 +#define VL53LX_PREV_SHADOW_RESULT__SPARE_0_SD1 0x0EF4 +#define VL53LX_PREV_SHADOW_RESULT__SPARE_0_SD1_HI 0x0EF4 +#define VL53LX_PREV_SHADOW_RESULT__SPARE_0_SD1_LO 0x0EF5 +#define VL53LX_PREV_SHADOW_RESULT__SPARE_1_SD1 0x0EF6 +#define VL53LX_PREV_SHADOW_RESULT__SPARE_1_SD1_HI 0x0EF6 +#define VL53LX_PREV_SHADOW_RESULT__SPARE_1_SD1_LO 0x0EF7 +#define VL53LX_PREV_SHADOW_RESULT__SPARE_2_SD1 0x0EF8 +#define VL53LX_PREV_SHADOW_RESULT__SPARE_2_SD1_HI 0x0EF8 +#define VL53LX_PREV_SHADOW_RESULT__SPARE_2_SD1_LO 0x0EF9 +#define VL53LX_PREV_SHADOW_RESULT__SPARE_3_SD1 0x0EFA +#define VL53LX_PREV_SHADOW_RESULT__SPARE_3_SD1_HI 0x0EFA +#define VL53LX_PREV_SHADOW_RESULT__SPARE_3_SD1_LO 0x0EFB +#define VL53LX_PREV_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0 0x0EFC +#define VL53LX_PREV_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0_3 0x0EFC +#define VL53LX_PREV_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0_2 0x0EFD +#define VL53LX_PREV_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0_1 0x0EFE +#define VL53LX_PREV_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0_0 0x0EFF +#define VL53LX_PREV_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0 0x0F00 +#define VL53LX_PREV_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0_3 0x0F00 +#define VL53LX_PREV_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0_2 0x0F01 +#define VL53LX_PREV_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0_1 0x0F02 +#define VL53LX_PREV_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0_0 0x0F03 +#define VL53LX_PREV_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0 0x0F04 +#define VL53LX_PREV_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0_3 0x0F04 +#define VL53LX_PREV_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0_2 0x0F05 +#define VL53LX_PREV_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0_1 0x0F06 +#define VL53LX_PREV_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0_0 0x0F07 +#define VL53LX_PREV_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0 0x0F08 +#define VL53LX_PREV_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0_3 0x0F08 +#define VL53LX_PREV_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0_2 0x0F09 +#define VL53LX_PREV_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0_1 0x0F0A +#define VL53LX_PREV_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0_0 0x0F0B +#define VL53LX_PREV_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1 0x0F0C +#define VL53LX_PREV_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1_3 0x0F0C +#define VL53LX_PREV_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1_2 0x0F0D +#define VL53LX_PREV_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1_1 0x0F0E +#define VL53LX_PREV_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1_0 0x0F0F +#define VL53LX_PREV_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1 0x0F10 +#define VL53LX_PREV_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1_3 0x0F10 +#define VL53LX_PREV_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1_2 0x0F11 +#define VL53LX_PREV_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1_1 0x0F12 +#define VL53LX_PREV_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1_0 0x0F13 +#define VL53LX_PREV_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1 0x0F14 +#define VL53LX_PREV_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1_3 0x0F14 +#define VL53LX_PREV_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1_2 0x0F15 +#define VL53LX_PREV_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1_1 0x0F16 +#define VL53LX_PREV_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1_0 0x0F17 +#define VL53LX_PREV_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1 0x0F18 +#define VL53LX_PREV_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1_3 0x0F18 +#define VL53LX_PREV_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1_2 0x0F19 +#define VL53LX_PREV_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1_1 0x0F1A +#define VL53LX_PREV_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1_0 0x0F1B +#define VL53LX_PREV_SHADOW_RESULT_CORE__SPARE_0 0x0F1C +#define VL53LX_RESULT__DEBUG_STATUS 0x0F20 +#define VL53LX_RESULT__DEBUG_STAGE 0x0F21 +#define VL53LX_GPH__SYSTEM__THRESH_RATE_HIGH 0x0F24 +#define VL53LX_GPH__SYSTEM__THRESH_RATE_HIGH_HI 0x0F24 +#define VL53LX_GPH__SYSTEM__THRESH_RATE_HIGH_LO 0x0F25 +#define VL53LX_GPH__SYSTEM__THRESH_RATE_LOW 0x0F26 +#define VL53LX_GPH__SYSTEM__THRESH_RATE_LOW_HI 0x0F26 +#define VL53LX_GPH__SYSTEM__THRESH_RATE_LOW_LO 0x0F27 +#define VL53LX_GPH__SYSTEM__INTERRUPT_CONFIG_GPIO 0x0F28 +#define VL53LX_GPH__DSS_CONFIG__ROI_MODE_CONTROL 0x0F2F +#define VL53LX_GPH__DSS_CONFIG__MANUAL_EFFECTIVE_SPADS_SELECT 0x0F30 +#define VL53LX_GPH__DSS_CONFIG__MANUAL_EFFECTIVE_SPADS_SELECT_HI 0x0F30 +#define VL53LX_GPH__DSS_CONFIG__MANUAL_EFFECTIVE_SPADS_SELECT_LO 0x0F31 +#define VL53LX_GPH__DSS_CONFIG__MANUAL_BLOCK_SELECT 0x0F32 +#define VL53LX_GPH__DSS_CONFIG__MAX_SPADS_LIMIT 0x0F33 +#define VL53LX_GPH__DSS_CONFIG__MIN_SPADS_LIMIT 0x0F34 +#define VL53LX_GPH__MM_CONFIG__TIMEOUT_MACROP_A_HI 0x0F36 +#define VL53LX_GPH__MM_CONFIG__TIMEOUT_MACROP_A_LO 0x0F37 +#define VL53LX_GPH__MM_CONFIG__TIMEOUT_MACROP_B_HI 0x0F38 +#define VL53LX_GPH__MM_CONFIG__TIMEOUT_MACROP_B_LO 0x0F39 +#define VL53LX_GPH__RANGE_CONFIG__TIMEOUT_MACROP_A_HI 0x0F3A +#define VL53LX_GPH__RANGE_CONFIG__TIMEOUT_MACROP_A_LO 0x0F3B +#define VL53LX_GPH__RANGE_CONFIG__VCSEL_PERIOD_A 0x0F3C +#define VL53LX_GPH__RANGE_CONFIG__VCSEL_PERIOD_B 0x0F3D +#define VL53LX_GPH__RANGE_CONFIG__TIMEOUT_MACROP_B_HI 0x0F3E +#define VL53LX_GPH__RANGE_CONFIG__TIMEOUT_MACROP_B_LO 0x0F3F +#define VL53LX_GPH__RANGE_CONFIG__SIGMA_THRESH 0x0F40 +#define VL53LX_GPH__RANGE_CONFIG__SIGMA_THRESH_HI 0x0F40 +#define VL53LX_GPH__RANGE_CONFIG__SIGMA_THRESH_LO 0x0F41 +#define VL53LX_GPH__RANGE_CONFIG__MIN_COUNT_RATE_RTN_LIMIT_MCPS 0x0F42 +#define VL53LX_GPH__RANGE_CONFIG__MIN_COUNT_RATE_RTN_LIMIT_MCPS_HI 0x0F42 +#define VL53LX_GPH__RANGE_CONFIG__MIN_COUNT_RATE_RTN_LIMIT_MCPS_LO 0x0F43 +#define VL53LX_GPH__RANGE_CONFIG__VALID_PHASE_LOW 0x0F44 +#define VL53LX_GPH__RANGE_CONFIG__VALID_PHASE_HIGH 0x0F45 +#define VL53LX_FIRMWARE__INTERNAL_STREAM_COUNT_DIV 0x0F46 +#define VL53LX_FIRMWARE__INTERNAL_STREAM_COUNTER_VAL 0x0F47 +#define VL53LX_DSS_CALC__ROI_CTRL 0x0F54 +#define VL53LX_DSS_CALC__SPARE_1 0x0F55 +#define VL53LX_DSS_CALC__SPARE_2 0x0F56 +#define VL53LX_DSS_CALC__SPARE_3 0x0F57 +#define VL53LX_DSS_CALC__SPARE_4 0x0F58 +#define VL53LX_DSS_CALC__SPARE_5 0x0F59 +#define VL53LX_DSS_CALC__SPARE_6 0x0F5A +#define VL53LX_DSS_CALC__SPARE_7 0x0F5B +#define VL53LX_DSS_CALC__USER_ROI_SPAD_EN_0 0x0F5C +#define VL53LX_DSS_CALC__USER_ROI_SPAD_EN_1 0x0F5D +#define VL53LX_DSS_CALC__USER_ROI_SPAD_EN_2 0x0F5E +#define VL53LX_DSS_CALC__USER_ROI_SPAD_EN_3 0x0F5F +#define VL53LX_DSS_CALC__USER_ROI_SPAD_EN_4 0x0F60 +#define VL53LX_DSS_CALC__USER_ROI_SPAD_EN_5 0x0F61 +#define VL53LX_DSS_CALC__USER_ROI_SPAD_EN_6 0x0F62 +#define VL53LX_DSS_CALC__USER_ROI_SPAD_EN_7 0x0F63 +#define VL53LX_DSS_CALC__USER_ROI_SPAD_EN_8 0x0F64 +#define VL53LX_DSS_CALC__USER_ROI_SPAD_EN_9 0x0F65 +#define VL53LX_DSS_CALC__USER_ROI_SPAD_EN_10 0x0F66 +#define VL53LX_DSS_CALC__USER_ROI_SPAD_EN_11 0x0F67 +#define VL53LX_DSS_CALC__USER_ROI_SPAD_EN_12 0x0F68 +#define VL53LX_DSS_CALC__USER_ROI_SPAD_EN_13 0x0F69 +#define VL53LX_DSS_CALC__USER_ROI_SPAD_EN_14 0x0F6A +#define VL53LX_DSS_CALC__USER_ROI_SPAD_EN_15 0x0F6B +#define VL53LX_DSS_CALC__USER_ROI_SPAD_EN_16 0x0F6C +#define VL53LX_DSS_CALC__USER_ROI_SPAD_EN_17 0x0F6D +#define VL53LX_DSS_CALC__USER_ROI_SPAD_EN_18 0x0F6E +#define VL53LX_DSS_CALC__USER_ROI_SPAD_EN_19 0x0F6F +#define VL53LX_DSS_CALC__USER_ROI_SPAD_EN_20 0x0F70 +#define VL53LX_DSS_CALC__USER_ROI_SPAD_EN_21 0x0F71 +#define VL53LX_DSS_CALC__USER_ROI_SPAD_EN_22 0x0F72 +#define VL53LX_DSS_CALC__USER_ROI_SPAD_EN_23 0x0F73 +#define VL53LX_DSS_CALC__USER_ROI_SPAD_EN_24 0x0F74 +#define VL53LX_DSS_CALC__USER_ROI_SPAD_EN_25 0x0F75 +#define VL53LX_DSS_CALC__USER_ROI_SPAD_EN_26 0x0F76 +#define VL53LX_DSS_CALC__USER_ROI_SPAD_EN_27 0x0F77 +#define VL53LX_DSS_CALC__USER_ROI_SPAD_EN_28 0x0F78 +#define VL53LX_DSS_CALC__USER_ROI_SPAD_EN_29 0x0F79 +#define VL53LX_DSS_CALC__USER_ROI_SPAD_EN_30 0x0F7A +#define VL53LX_DSS_CALC__USER_ROI_SPAD_EN_31 0x0F7B +#define VL53LX_DSS_CALC__USER_ROI_0 0x0F7C +#define VL53LX_DSS_CALC__USER_ROI_1 0x0F7D +#define VL53LX_DSS_CALC__MODE_ROI_0 0x0F7E +#define VL53LX_DSS_CALC__MODE_ROI_1 0x0F7F +#define VL53LX_SIGMA_ESTIMATOR_CALC__SPARE_0 0x0F80 +#define VL53LX_VHV_RESULT__PEAK_SIGNAL_RATE_MCPS 0x0F82 +#define VL53LX_VHV_RESULT__PEAK_SIGNAL_RATE_MCPS_HI 0x0F82 +#define VL53LX_VHV_RESULT__PEAK_SIGNAL_RATE_MCPS_LO 0x0F83 +#define VL53LX_VHV_RESULT__SIGNAL_TOTAL_EVENTS_REF 0x0F84 +#define VL53LX_VHV_RESULT__SIGNAL_TOTAL_EVENTS_REF_3 0x0F84 +#define VL53LX_VHV_RESULT__SIGNAL_TOTAL_EVENTS_REF_2 0x0F85 +#define VL53LX_VHV_RESULT__SIGNAL_TOTAL_EVENTS_REF_1 0x0F86 +#define VL53LX_VHV_RESULT__SIGNAL_TOTAL_EVENTS_REF_0 0x0F87 +#define VL53LX_PHASECAL_RESULT__PHASE_OUTPUT_REF 0x0F88 +#define VL53LX_PHASECAL_RESULT__PHASE_OUTPUT_REF_HI 0x0F88 +#define VL53LX_PHASECAL_RESULT__PHASE_OUTPUT_REF_LO 0x0F89 +#define VL53LX_DSS_RESULT__TOTAL_RATE_PER_SPAD 0x0F8A +#define VL53LX_DSS_RESULT__TOTAL_RATE_PER_SPAD_HI 0x0F8A +#define VL53LX_DSS_RESULT__TOTAL_RATE_PER_SPAD_LO 0x0F8B +#define VL53LX_DSS_RESULT__ENABLED_BLOCKS 0x0F8C +#define VL53LX_DSS_RESULT__NUM_REQUESTED_SPADS 0x0F8E +#define VL53LX_DSS_RESULT__NUM_REQUESTED_SPADS_HI 0x0F8E +#define VL53LX_DSS_RESULT__NUM_REQUESTED_SPADS_LO 0x0F8F +#define VL53LX_MM_RESULT__INNER_INTERSECTION_RATE 0x0F92 +#define VL53LX_MM_RESULT__INNER_INTERSECTION_RATE_HI 0x0F92 +#define VL53LX_MM_RESULT__INNER_INTERSECTION_RATE_LO 0x0F93 +#define VL53LX_MM_RESULT__OUTER_COMPLEMENT_RATE 0x0F94 +#define VL53LX_MM_RESULT__OUTER_COMPLEMENT_RATE_HI 0x0F94 +#define VL53LX_MM_RESULT__OUTER_COMPLEMENT_RATE_LO 0x0F95 +#define VL53LX_MM_RESULT__TOTAL_OFFSET 0x0F96 +#define VL53LX_MM_RESULT__TOTAL_OFFSET_HI 0x0F96 +#define VL53LX_MM_RESULT__TOTAL_OFFSET_LO 0x0F97 +#define VL53LX_XTALK_CALC__XTALK_FOR_ENABLED_SPADS 0x0F98 +#define VL53LX_XTALK_CALC__XTALK_FOR_ENABLED_SPADS_3 0x0F98 +#define VL53LX_XTALK_CALC__XTALK_FOR_ENABLED_SPADS_2 0x0F99 +#define VL53LX_XTALK_CALC__XTALK_FOR_ENABLED_SPADS_1 0x0F9A +#define VL53LX_XTALK_CALC__XTALK_FOR_ENABLED_SPADS_0 0x0F9B +#define VL53LX_XTALK_RESULT__AVG_XTALK_USER_ROI_KCPS 0x0F9C +#define VL53LX_XTALK_RESULT__AVG_XTALK_USER_ROI_KCPS_3 0x0F9C +#define VL53LX_XTALK_RESULT__AVG_XTALK_USER_ROI_KCPS_2 0x0F9D +#define VL53LX_XTALK_RESULT__AVG_XTALK_USER_ROI_KCPS_1 0x0F9E +#define VL53LX_XTALK_RESULT__AVG_XTALK_USER_ROI_KCPS_0 0x0F9F +#define VL53LX_XTALK_RESULT__AVG_XTALK_MM_INNER_ROI_KCPS 0x0FA0 +#define VL53LX_XTALK_RESULT__AVG_XTALK_MM_INNER_ROI_KCPS_3 0x0FA0 +#define VL53LX_XTALK_RESULT__AVG_XTALK_MM_INNER_ROI_KCPS_2 0x0FA1 +#define VL53LX_XTALK_RESULT__AVG_XTALK_MM_INNER_ROI_KCPS_1 0x0FA2 +#define VL53LX_XTALK_RESULT__AVG_XTALK_MM_INNER_ROI_KCPS_0 0x0FA3 +#define VL53LX_XTALK_RESULT__AVG_XTALK_MM_OUTER_ROI_KCPS 0x0FA4 +#define VL53LX_XTALK_RESULT__AVG_XTALK_MM_OUTER_ROI_KCPS_3 0x0FA4 +#define VL53LX_XTALK_RESULT__AVG_XTALK_MM_OUTER_ROI_KCPS_2 0x0FA5 +#define VL53LX_XTALK_RESULT__AVG_XTALK_MM_OUTER_ROI_KCPS_1 0x0FA6 +#define VL53LX_XTALK_RESULT__AVG_XTALK_MM_OUTER_ROI_KCPS_0 0x0FA7 +#define VL53LX_RANGE_RESULT__ACCUM_PHASE 0x0FA8 +#define VL53LX_RANGE_RESULT__ACCUM_PHASE_3 0x0FA8 +#define VL53LX_RANGE_RESULT__ACCUM_PHASE_2 0x0FA9 +#define VL53LX_RANGE_RESULT__ACCUM_PHASE_1 0x0FAA +#define VL53LX_RANGE_RESULT__ACCUM_PHASE_0 0x0FAB +#define VL53LX_RANGE_RESULT__OFFSET_CORRECTED_RANGE 0x0FAC +#define VL53LX_RANGE_RESULT__OFFSET_CORRECTED_RANGE_HI 0x0FAC +#define VL53LX_RANGE_RESULT__OFFSET_CORRECTED_RANGE_LO 0x0FAD +#define VL53LX_SHADOW_PHASECAL_RESULT__VCSEL_START 0x0FAE +#define VL53LX_SHADOW_RESULT__INTERRUPT_STATUS 0x0FB0 +#define VL53LX_SHADOW_RESULT__RANGE_STATUS 0x0FB1 +#define VL53LX_SHADOW_RESULT__REPORT_STATUS 0x0FB2 +#define VL53LX_SHADOW_RESULT__STREAM_COUNT 0x0FB3 +#define VL53LX_SHADOW_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0 0x0FB4 +#define VL53LX_SHADOW_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0_HI 0x0FB4 +#define VL53LX_SHADOW_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0_LO 0x0FB5 +#define VL53LX_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD0 0x0FB6 +#define VL53LX_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD0_HI 0x0FB6 +#define VL53LX_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD0_LO 0x0FB7 +#define VL53LX_SHADOW_RESULT__AMBIENT_COUNT_RATE_MCPS_SD0 0x0FB8 +#define VL53LX_SHADOW_RESULT__AMBIENT_COUNT_RATE_MCPS_SD0_HI 0x0FB8 +#define VL53LX_SHADOW_RESULT__AMBIENT_COUNT_RATE_MCPS_SD0_LO 0x0FB9 +#define VL53LX_SHADOW_RESULT__SIGMA_SD0 0x0FBA +#define VL53LX_SHADOW_RESULT__SIGMA_SD0_HI 0x0FBA +#define VL53LX_SHADOW_RESULT__SIGMA_SD0_LO 0x0FBB +#define VL53LX_SHADOW_RESULT__PHASE_SD0 0x0FBC +#define VL53LX_SHADOW_RESULT__PHASE_SD0_HI 0x0FBC +#define VL53LX_SHADOW_RESULT__PHASE_SD0_LO 0x0FBD +#define VL53LX_SHADOW_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0 0x0FBE +#define VL53LX_SHADOW_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0_HI 0x0FBE +#define VL53LX_SHADOW_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0_LO 0x0FBF +#define VL53LX_SHPEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0 0x0FC0 +#define VL53LX_SHPEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0_HI 0x0FC0 +#define VL53LX_SHPEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0_LO 0x0FC1 +#define VL53LX_SHADOW_RESULT__MM_INNER_ACTUAL_EFFECTIVE_SPADS_SD0 0x0FC2 +#define VL53LX_SHADOW_RESULT__MM_INNER_ACTUAL_EFFECTIVE_SPADS_SD0_HI 0x0FC2 +#define VL53LX_SHADOW_RESULT__MM_INNER_ACTUAL_EFFECTIVE_SPADS_SD0_LO 0x0FC3 +#define VL53LX_SHADOW_RESULT__MM_OUTER_ACTUAL_EFFECTIVE_SPADS_SD0 0x0FC4 +#define VL53LX_SHADOW_RESULT__MM_OUTER_ACTUAL_EFFECTIVE_SPADS_SD0_HI 0x0FC4 +#define VL53LX_SHADOW_RESULT__MM_OUTER_ACTUAL_EFFECTIVE_SPADS_SD0_LO 0x0FC5 +#define VL53LX_SHADOW_RESULT__AVG_SIGNAL_COUNT_RATE_MCPS_SD0 0x0FC6 +#define VL53LX_SHADOW_RESULT__AVG_SIGNAL_COUNT_RATE_MCPS_SD0_HI 0x0FC6 +#define VL53LX_SHADOW_RESULT__AVG_SIGNAL_COUNT_RATE_MCPS_SD0_LO 0x0FC7 +#define VL53LX_SHADOW_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD1 0x0FC8 +#define VL53LX_SHADOW_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD1_HI 0x0FC8 +#define VL53LX_SHADOW_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD1_LO 0x0FC9 +#define VL53LX_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD1 0x0FCA +#define VL53LX_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD1_HI 0x0FCA +#define VL53LX_SHADOW_RESULT__PEAK_SIGNAL_COUNT_RATE_MCPS_SD1_LO 0x0FCB +#define VL53LX_SHADOW_RESULT__AMBIENT_COUNT_RATE_MCPS_SD1 0x0FCC +#define VL53LX_SHADOW_RESULT__AMBIENT_COUNT_RATE_MCPS_SD1_HI 0x0FCC +#define VL53LX_SHADOW_RESULT__AMBIENT_COUNT_RATE_MCPS_SD1_LO 0x0FCD +#define VL53LX_SHADOW_RESULT__SIGMA_SD1 0x0FCE +#define VL53LX_SHADOW_RESULT__SIGMA_SD1_HI 0x0FCE +#define VL53LX_SHADOW_RESULT__SIGMA_SD1_LO 0x0FCF +#define VL53LX_SHADOW_RESULT__PHASE_SD1 0x0FD0 +#define VL53LX_SHADOW_RESULT__PHASE_SD1_HI 0x0FD0 +#define VL53LX_SHADOW_RESULT__PHASE_SD1_LO 0x0FD1 +#define VL53LX_SHADOW_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD1 0x0FD2 +#define VL53LX_SHADOW_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD1_HI 0x0FD2 +#define VL53LX_SHADOW_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD1_LO 0x0FD3 +#define VL53LX_SHADOW_RESULT__SPARE_0_SD1 0x0FD4 +#define VL53LX_SHADOW_RESULT__SPARE_0_SD1_HI 0x0FD4 +#define VL53LX_SHADOW_RESULT__SPARE_0_SD1_LO 0x0FD5 +#define VL53LX_SHADOW_RESULT__SPARE_1_SD1 0x0FD6 +#define VL53LX_SHADOW_RESULT__SPARE_1_SD1_HI 0x0FD6 +#define VL53LX_SHADOW_RESULT__SPARE_1_SD1_LO 0x0FD7 +#define VL53LX_SHADOW_RESULT__SPARE_2_SD1 0x0FD8 +#define VL53LX_SHADOW_RESULT__SPARE_2_SD1_HI 0x0FD8 +#define VL53LX_SHADOW_RESULT__SPARE_2_SD1_LO 0x0FD9 +#define VL53LX_SHADOW_RESULT__SPARE_3_SD1 0x0FDA +#define VL53LX_SHADOW_RESULT__THRESH_INFO 0x0FDB +#define VL53LX_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0 0x0FDC +#define VL53LX_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0_3 0x0FDC +#define VL53LX_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0_2 0x0FDD +#define VL53LX_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0_1 0x0FDE +#define VL53LX_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD0_0 0x0FDF +#define VL53LX_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0 0x0FE0 +#define VL53LX_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0_3 0x0FE0 +#define VL53LX_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0_2 0x0FE1 +#define VL53LX_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0_1 0x0FE2 +#define VL53LX_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD0_0 0x0FE3 +#define VL53LX_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0 0x0FE4 +#define VL53LX_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0_3 0x0FE4 +#define VL53LX_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0_2 0x0FE5 +#define VL53LX_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0_1 0x0FE6 +#define VL53LX_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD0_0 0x0FE7 +#define VL53LX_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0 0x0FE8 +#define VL53LX_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0_3 0x0FE8 +#define VL53LX_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0_2 0x0FE9 +#define VL53LX_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0_1 0x0FEA +#define VL53LX_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD0_0 0x0FEB +#define VL53LX_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1 0x0FEC +#define VL53LX_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1_3 0x0FEC +#define VL53LX_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1_2 0x0FED +#define VL53LX_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1_1 0x0FEE +#define VL53LX_SHADOW_RESULT_CORE__AMBIENT_WINDOW_EVENTS_SD1_0 0x0FEF +#define VL53LX_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1 0x0FF0 +#define VL53LX_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1_3 0x0FF0 +#define VL53LX_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1_2 0x0FF1 +#define VL53LX_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1_1 0x0FF2 +#define VL53LX_SHADOW_RESULT_CORE__RANGING_TOTAL_EVENTS_SD1_0 0x0FF3 +#define VL53LX_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1 0x0FF4 +#define VL53LX_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1_3 0x0FF4 +#define VL53LX_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1_2 0x0FF5 +#define VL53LX_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1_1 0x0FF6 +#define VL53LX_SHADOW_RESULT_CORE__SIGNAL_TOTAL_EVENTS_SD1_0 0x0FF7 +#define VL53LX_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1 0x0FF8 +#define VL53LX_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1_3 0x0FF8 +#define VL53LX_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1_2 0x0FF9 +#define VL53LX_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1_1 0x0FFA +#define VL53LX_SHADOW_RESULT_CORE__TOTAL_PERIODS_ELAPSED_SD1_0 0x0FFB +#define VL53LX_SHADOW_RESULT_CORE__SPARE_0 0x0FFC +#define VL53LX_SHADOW_PHASECAL_RESULT__REFERENCE_PHASE_HI 0x0FFE +#define VL53LX_SHADOW_PHASECAL_RESULT__REFERENCE_PHASE_LO 0x0FFF + +#define VL53LX_HISTOGRAM_CONFIG__OPCODE_SEQUENCE_0 VL53LX_SIGMA_ESTIMATOR__EFFECTIVE_PULSE_WIDTH_NS +#define VL53LX_HISTOGRAM_CONFIG__OPCODE_SEQUENCE_1 VL53LX_SIGMA_ESTIMATOR__EFFECTIVE_AMBIENT_WIDTH_NS +#define VL53LX_HISTOGRAM_CONFIG__OPCODE_SEQUENCE_2 VL53LX_SIGMA_ESTIMATOR__SIGMA_REF_MM +#define VL53LX_HISTOGRAM_CONFIG__AMB_THRESH_HIGH VL53LX_ALGO__RANGE_IGNORE_THRESHOLD_MCPS + +#define VL53LX_RESULT__HISTOGRAM_BIN_0_2 0x008E +#define VL53LX_RESULT__HISTOGRAM_BIN_0_1 0x008F +#define VL53LX_RESULT__HISTOGRAM_BIN_0_0 0x0090 +#define VL53LX_RESULT__HISTOGRAM_BIN_23_2 0x00D3 +#define VL53LX_RESULT__HISTOGRAM_BIN_23_1 0x00D4 +#define VL53LX_RESULT__HISTOGRAM_BIN_23_0 0x00D5 +#define VL53LX_RESULT__HISTOGRAM_BIN_23_0_MSB 0x00D9 +#define VL53LX_RESULT__HISTOGRAM_BIN_23_0_LSB 0x00DA + +#define VL53LX_HISTOGRAM_BIN_DATA_I2C_INDEX VL53LX_RESULT__INTERRUPT_STATUS +#define VL53LX_HISTOGRAM_BIN_DATA_I2C_SIZE_BYTES (VL53LX_RESULT__HISTOGRAM_BIN_23_0_LSB - VL53LX_RESULT__INTERRUPT_STATUS + 1) + +#define VL53LX_TUNINGPARM_VERSION_DEFAULT \ +((uint16_t) 30) +#define VL53LX_TUNINGPARM_KEY_TABLE_VERSION_DEFAULT \ +((uint16_t) 14) +#define VL53LX_TUNINGPARM_LLD_VERSION_DEFAULT \ +((uint16_t) 12180) +#define VL53LX_TUNINGPARM_HIST_ALGO_SELECT_DEFAULT \ +((uint8_t) 4) +#define VL53LX_TUNINGPARM_HIST_TARGET_ORDER_DEFAULT \ +((uint8_t) 1) +#define VL53LX_TUNINGPARM_HIST_FILTER_WOI_0_DEFAULT \ +((uint8_t) 1) +#define VL53LX_TUNINGPARM_HIST_FILTER_WOI_1_DEFAULT \ +((uint8_t) 2) +#define VL53LX_TUNINGPARM_HIST_AMB_EST_METHOD_DEFAULT \ +((uint8_t) 1) +#define VL53LX_TUNINGPARM_HIST_AMB_THRESH_SIGMA_0_DEFAULT \ +((uint8_t) 80) +#define VL53LX_TUNINGPARM_HIST_AMB_THRESH_SIGMA_1_DEFAULT \ +((uint8_t) 100) +#define VL53LX_TUNINGPARM_HIST_MIN_AMB_THRESH_EVENTS_DEFAULT \ +((int32_t) 16) +#define VL53LX_TUNINGPARM_HIST_AMB_EVENTS_SCALER_DEFAULT \ +((uint16_t) 4157) +#define VL53LX_TUNINGPARM_HIST_NOISE_THRESHOLD_DEFAULT \ +((uint16_t) 50) +#define VL53LX_TUNINGPARM_HIST_SIGNAL_TOTAL_EVENTS_LIMIT_DEFAULT \ +((int32_t) 100) +#define VL53LX_TUNINGPARM_HIST_SIGMA_EST_REF_MM_DEFAULT \ +((uint8_t) 1) +#define VL53LX_TUNINGPARM_HIST_SIGMA_THRESH_MM_DEFAULT \ +((uint16_t) 180) +#define VL53LX_TUNINGPARM_HIST_GAIN_FACTOR_DEFAULT \ +((uint16_t) 2020) +#define VL53LX_TUNINGPARM_CONSISTENCY_HIST_PHASE_TOLERANCE_DEFAULT \ +((uint8_t) 8) +#define VL53LX_TUNINGPARM_CONSISTENCY_HIST_MIN_MAX_TOLERANCE_MM_DEFAULT \ +((uint16_t) 0) +#define VL53LX_TUNINGPARM_CONSISTENCY_HIST_EVENT_SIGMA_DEFAULT \ +((uint8_t) 0) +#define VL53LX_TUNINGPARM_CONSISTENCY_HIST_EVENT_SIGMA_MIN_SPAD_LIMIT_DEFAULT \ +((uint16_t) 2048) +#define VL53LX_TUNINGPARM_INITIAL_PHASE_RTN_HISTO_LONG_RANGE_DEFAULT \ +((uint8_t) 9) +#define VL53LX_TUNINGPARM_INITIAL_PHASE_RTN_HISTO_MED_RANGE_DEFAULT \ +((uint8_t) 5) +#define VL53LX_TUNINGPARM_INITIAL_PHASE_RTN_HISTO_SHORT_RANGE_DEFAULT \ +((uint8_t) 3) +#define VL53LX_TUNINGPARM_INITIAL_PHASE_REF_HISTO_LONG_RANGE_DEFAULT \ +((uint8_t) 6) +#define VL53LX_TUNINGPARM_INITIAL_PHASE_REF_HISTO_MED_RANGE_DEFAULT \ +((uint8_t) 6) +#define VL53LX_TUNINGPARM_INITIAL_PHASE_REF_HISTO_SHORT_RANGE_DEFAULT \ +((uint8_t) 6) +#define VL53LX_TUNINGPARM_XTALK_DETECT_MIN_VALID_RANGE_MM_DEFAULT \ +((int16_t) -50) +#define VL53LX_TUNINGPARM_XTALK_DETECT_MAX_VALID_RANGE_MM_DEFAULT \ +((int16_t) 50) +#define VL53LX_TUNINGPARM_XTALK_DETECT_MAX_SIGMA_MM_DEFAULT \ +((uint16_t) 140) +#define VL53LX_TUNINGPARM_XTALK_DETECT_MIN_MAX_TOLERANCE_DEFAULT \ +((uint16_t) 50) +#define VL53LX_TUNINGPARM_XTALK_DETECT_MAX_VALID_RATE_KCPS_DEFAULT \ +((uint16_t) 400) +#define VL53LX_TUNINGPARM_XTALK_DETECT_EVENT_SIGMA_DEFAULT \ +((uint8_t) 80) +#define VL53LX_TUNINGPARM_HIST_XTALK_MARGIN_KCPS_DEFAULT \ +((int16_t) 0) +#define VL53LX_TUNINGPARM_CONSISTENCY_LITE_PHASE_TOLERANCE_DEFAULT \ +((uint8_t) 2) +#define VL53LX_TUNINGPARM_PHASECAL_TARGET_DEFAULT \ +((uint8_t) 33) +#define VL53LX_TUNINGPARM_LITE_CAL_REPEAT_RATE_DEFAULT \ +((uint16_t) 0) +#define VL53LX_TUNINGPARM_LITE_RANGING_GAIN_FACTOR_DEFAULT \ +((uint16_t) 2011) +#define VL53LX_TUNINGPARM_LITE_MIN_CLIP_MM_DEFAULT \ +((uint8_t) 0) +#define VL53LX_TUNINGPARM_LITE_LONG_SIGMA_THRESH_MM_DEFAULT \ +((uint16_t) 60) +#define VL53LX_TUNINGPARM_LITE_MED_SIGMA_THRESH_MM_DEFAULT \ +((uint16_t) 60) +#define VL53LX_TUNINGPARM_LITE_SHORT_SIGMA_THRESH_MM_DEFAULT \ +((uint16_t) 60) +#define VL53LX_TUNINGPARM_LITE_LONG_MIN_COUNT_RATE_RTN_MCPS_DEFAULT \ +((uint16_t) 128) +#define VL53LX_TUNINGPARM_LITE_MED_MIN_COUNT_RATE_RTN_MCPS_DEFAULT \ +((uint16_t) 128) +#define VL53LX_TUNINGPARM_LITE_SHORT_MIN_COUNT_RATE_RTN_MCPS_DEFAULT \ +((uint16_t) 128) +#define VL53LX_TUNINGPARM_LITE_SIGMA_EST_PULSE_WIDTH_DEFAULT \ +((uint8_t) 8) +#define VL53LX_TUNINGPARM_LITE_SIGMA_EST_AMB_WIDTH_NS_DEFAULT \ +((uint8_t) 16) +#define VL53LX_TUNINGPARM_LITE_SIGMA_REF_MM_DEFAULT \ +((uint8_t) 1) +#define VL53LX_TUNINGPARM_LITE_RIT_MULT_DEFAULT \ +((uint8_t) 64) +#define VL53LX_TUNINGPARM_LITE_SEED_CONFIG_DEFAULT \ +((uint8_t) 2) +#define VL53LX_TUNINGPARM_LITE_QUANTIFIER_DEFAULT \ +((uint8_t) 2) +#define VL53LX_TUNINGPARM_LITE_FIRST_ORDER_SELECT_DEFAULT \ +((uint8_t) 0) +#define VL53LX_TUNINGPARM_LITE_XTALK_MARGIN_KCPS_DEFAULT \ +((int16_t) 0) +#define VL53LX_TUNINGPARM_INITIAL_PHASE_RTN_LITE_LONG_RANGE_DEFAULT \ +((uint8_t) 14) +#define VL53LX_TUNINGPARM_INITIAL_PHASE_RTN_LITE_MED_RANGE_DEFAULT \ +((uint8_t) 10) +#define VL53LX_TUNINGPARM_INITIAL_PHASE_RTN_LITE_SHORT_RANGE_DEFAULT \ +((uint8_t) 6) +#define VL53LX_TUNINGPARM_INITIAL_PHASE_REF_LITE_LONG_RANGE_DEFAULT \ +((uint8_t) 14) +#define VL53LX_TUNINGPARM_INITIAL_PHASE_REF_LITE_MED_RANGE_DEFAULT \ +((uint8_t) 10) +#define VL53LX_TUNINGPARM_INITIAL_PHASE_REF_LITE_SHORT_RANGE_DEFAULT \ +((uint8_t) 6) +#define VL53LX_TUNINGPARM_TIMED_SEED_CONFIG_DEFAULT \ +((uint8_t) 1) +#define VL53LX_TUNINGPARM_DMAX_CFG_SIGNAL_THRESH_SIGMA_DEFAULT \ +((uint8_t) 32) +#define VL53LX_TUNINGPARM_DMAX_CFG_REFLECTANCE_ARRAY_0_DEFAULT \ +((uint16_t) 15) +#define VL53LX_TUNINGPARM_DMAX_CFG_REFLECTANCE_ARRAY_1_DEFAULT \ +((uint16_t) 52) +#define VL53LX_TUNINGPARM_DMAX_CFG_REFLECTANCE_ARRAY_2_DEFAULT \ +((uint16_t) 200) +#define VL53LX_TUNINGPARM_DMAX_CFG_REFLECTANCE_ARRAY_3_DEFAULT \ +((uint16_t) 364) +#define VL53LX_TUNINGPARM_DMAX_CFG_REFLECTANCE_ARRAY_4_DEFAULT \ +((uint16_t) 400) +#define VL53LX_TUNINGPARM_VHV_LOOPBOUND_DEFAULT \ +((uint8_t) 129) +#define VL53LX_TUNINGPARM_REFSPADCHAR_DEVICE_TEST_MODE_DEFAULT \ +((uint8_t) 8) +#define VL53LX_TUNINGPARM_REFSPADCHAR_VCSEL_PERIOD_DEFAULT \ +((uint8_t) 11) +#define VL53LX_TUNINGPARM_REFSPADCHAR_PHASECAL_TIMEOUT_US_DEFAULT \ +((uint32_t) 1000) +#define VL53LX_TUNINGPARM_REFSPADCHAR_TARGET_COUNT_RATE_MCPS_DEFAULT \ +((uint16_t) 2560) +#define VL53LX_TUNINGPARM_REFSPADCHAR_MIN_COUNTRATE_LIMIT_MCPS_DEFAULT \ +((uint16_t) 1280) +#define VL53LX_TUNINGPARM_REFSPADCHAR_MAX_COUNTRATE_LIMIT_MCPS_DEFAULT \ +((uint16_t) 5120) +#define VL53LX_TUNINGPARM_XTALK_EXTRACT_NUM_OF_SAMPLES_DEFAULT \ +((uint8_t) 7) +#define VL53LX_TUNINGPARM_XTALK_EXTRACT_MIN_FILTER_THRESH_MM_DEFAULT \ +((int16_t) -70) +#define VL53LX_TUNINGPARM_XTALK_EXTRACT_MAX_FILTER_THRESH_MM_DEFAULT \ +((int16_t) 70) +#define VL53LX_TUNINGPARM_XTALK_EXTRACT_DSS_RATE_MCPS_DEFAULT \ +((uint16_t) 5120) +#define VL53LX_TUNINGPARM_XTALK_EXTRACT_PHASECAL_TIMEOUT_US_DEFAULT \ +((uint32_t) 15000) +#define VL53LX_TUNINGPARM_XTALK_EXTRACT_MAX_VALID_RATE_KCPS_DEFAULT \ +((uint16_t) 640) +#define VL53LX_TUNINGPARM_XTALK_EXTRACT_SIGMA_THRESHOLD_MM_DEFAULT \ +((uint16_t) 140) +#define VL53LX_TUNINGPARM_XTALK_EXTRACT_DSS_TIMEOUT_US_DEFAULT \ +((uint32_t) 2000) +#define VL53LX_TUNINGPARM_XTALK_EXTRACT_BIN_TIMEOUT_US_DEFAULT \ +((uint32_t) 10000) +#define VL53LX_TUNINGPARM_OFFSET_CAL_DSS_RATE_MCPS_DEFAULT \ +((uint16_t) 2560) +#define VL53LX_TUNINGPARM_OFFSET_CAL_PHASECAL_TIMEOUT_US_DEFAULT \ +((uint32_t) 15000) +#define VL53LX_TUNINGPARM_OFFSET_CAL_MM_TIMEOUT_US_DEFAULT \ +((uint32_t) 13000) +#define VL53LX_TUNINGPARM_OFFSET_CAL_RANGE_TIMEOUT_US_DEFAULT \ +((uint32_t) 13000) +#define VL53LX_TUNINGPARM_OFFSET_CAL_PRE_SAMPLES_DEFAULT \ +((uint8_t) 8) +#define VL53LX_TUNINGPARM_OFFSET_CAL_MM1_SAMPLES_DEFAULT \ +((uint8_t) 40) +#define VL53LX_TUNINGPARM_OFFSET_CAL_MM2_SAMPLES_DEFAULT \ +((uint8_t) 9) +#define VL53LX_TUNINGPARM_ZONE_CAL_DSS_RATE_MCPS_DEFAULT \ +((uint16_t) 5120) +#define VL53LX_TUNINGPARM_ZONE_CAL_PHASECAL_TIMEOUT_US_DEFAULT \ +((uint32_t) 15000) +#define VL53LX_TUNINGPARM_ZONE_CAL_DSS_TIMEOUT_US_DEFAULT \ +((uint32_t) 2000) +#define VL53LX_TUNINGPARM_ZONE_CAL_PHASECAL_NUM_SAMPLES_DEFAULT \ +((uint16_t) 16) +#define VL53LX_TUNINGPARM_ZONE_CAL_RANGE_TIMEOUT_US_DEFAULT \ +((uint32_t) 1000) +#define VL53LX_TUNINGPARM_ZONE_CAL_ZONE_NUM_SAMPLES_DEFAULT \ +((uint16_t) 8) +#define VL53LX_TUNINGPARM_SPADMAP_VCSEL_PERIOD_DEFAULT \ +((uint8_t) 18) +#define VL53LX_TUNINGPARM_SPADMAP_VCSEL_START_DEFAULT \ +((uint8_t) 15) +#define VL53LX_TUNINGPARM_SPADMAP_RATE_LIMIT_MCPS_DEFAULT \ +((uint16_t) 12) +#define VL53LX_TUNINGPARM_LITE_DSS_CONFIG_TARGET_TOTAL_RATE_MCPS_DEFAULT \ +((uint16_t) 2560) +#define VL53LX_TUNINGPARM_RANGING_DSS_CONFIG_TARGET_TOTAL_RATE_MCPS_DEFAULT \ +((uint16_t) 2560) +#define VL53LX_TUNINGPARM_MZ_DSS_CONFIG_TARGET_TOTAL_RATE_MCPS_DEFAULT \ +((uint16_t) 5120) +#define VL53LX_TUNINGPARM_TIMED_DSS_CONFIG_TARGET_TOTAL_RATE_MCPS_DEFAULT \ +((uint16_t) 2560) +#define VL53LX_TUNINGPARM_LITE_PHASECAL_CONFIG_TIMEOUT_US_DEFAULT \ +((uint32_t) 1000) +#define VL53LX_TUNINGPARM_RANGING_LONG_PHASECAL_CONFIG_TIMEOUT_US_DEFAULT \ +((uint32_t) 15000) +#define VL53LX_TUNINGPARM_RANGING_MED_PHASECAL_CONFIG_TIMEOUT_US_DEFAULT \ +((uint32_t) 15000) +#define VL53LX_TUNINGPARM_RANGING_SHORT_PHASECAL_CONFIG_TIMEOUT_US_DEFAULT \ +((uint32_t) 15000) +#define VL53LX_TUNINGPARM_MZ_LONG_PHASECAL_CONFIG_TIMEOUT_US_DEFAULT \ +((uint32_t) 15000) +#define VL53LX_TUNINGPARM_MZ_MED_PHASECAL_CONFIG_TIMEOUT_US_DEFAULT \ +((uint32_t) 9000) +#define VL53LX_TUNINGPARM_MZ_SHORT_PHASECAL_CONFIG_TIMEOUT_US_DEFAULT \ +((uint32_t) 6000) +#define VL53LX_TUNINGPARM_TIMED_PHASECAL_CONFIG_TIMEOUT_US_DEFAULT \ +((uint32_t) 1000) +#define VL53LX_TUNINGPARM_LITE_MM_CONFIG_TIMEOUT_US_DEFAULT \ +((uint32_t) 2000) +#define VL53LX_TUNINGPARM_RANGING_MM_CONFIG_TIMEOUT_US_DEFAULT \ +((uint32_t) 2000) +#define VL53LX_TUNINGPARM_MZ_MM_CONFIG_TIMEOUT_US_DEFAULT \ +((uint32_t) 2000) +#define VL53LX_TUNINGPARM_TIMED_MM_CONFIG_TIMEOUT_US_DEFAULT \ +((uint32_t) 2000) +#define VL53LX_TUNINGPARM_LITE_RANGE_CONFIG_TIMEOUT_US_DEFAULT \ +((uint32_t) 63000) +#define VL53LX_TUNINGPARM_RANGING_RANGE_CONFIG_TIMEOUT_US_DEFAULT \ +((uint32_t) 2500) +#define VL53LX_TUNINGPARM_MZ_RANGE_CONFIG_TIMEOUT_US_DEFAULT \ +((uint32_t) 2500) +#define VL53LX_TUNINGPARM_TIMED_RANGE_CONFIG_TIMEOUT_US_DEFAULT \ +((uint32_t) 13000) +#define VL53LX_TUNINGPARM_DYNXTALK_SMUDGE_MARGIN_DEFAULT \ +((uint16_t) 0) +#define VL53LX_TUNINGPARM_DYNXTALK_NOISE_MARGIN_DEFAULT \ +((uint32_t) 100) +#define VL53LX_TUNINGPARM_DYNXTALK_XTALK_OFFSET_LIMIT_DEFAULT \ +((uint32_t) 0) +#define VL53LX_TUNINGPARM_DYNXTALK_XTALK_OFFSET_LIMIT_HI_DEFAULT \ +((uint8_t) 0) +#define VL53LX_TUNINGPARM_DYNXTALK_SAMPLE_LIMIT_DEFAULT \ +((uint32_t) 200) +#define VL53LX_TUNINGPARM_DYNXTALK_SINGLE_XTALK_DELTA_DEFAULT \ +((uint32_t) 2048) +#define VL53LX_TUNINGPARM_DYNXTALK_AVERAGED_XTALK_DELTA_DEFAULT \ +((uint32_t) 308) +#define VL53LX_TUNINGPARM_DYNXTALK_CLIP_LIMIT_DEFAULT \ +((uint32_t) 10240) +#define VL53LX_TUNINGPARM_DYNXTALK_SCALER_CALC_METHOD_DEFAULT \ +((uint8_t) 0) +#define VL53LX_TUNINGPARM_DYNXTALK_XGRADIENT_SCALER_DEFAULT \ +((int16_t) 256) +#define VL53LX_TUNINGPARM_DYNXTALK_YGRADIENT_SCALER_DEFAULT \ +((int16_t) 256) +#define VL53LX_TUNINGPARM_DYNXTALK_USER_SCALER_SET_DEFAULT \ +((uint8_t) 0) +#define VL53LX_TUNINGPARM_DYNXTALK_SMUDGE_COR_SINGLE_APPLY_DEFAULT \ +((uint8_t) 0) +#define VL53LX_TUNINGPARM_DYNXTALK_XTALK_AMB_THRESHOLD_DEFAULT \ +((uint32_t) 128) +#define VL53LX_TUNINGPARM_DYNXTALK_NODETECT_AMB_THRESHOLD_KCPS_DEFAULT \ +((uint32_t) 57671680) +#define VL53LX_TUNINGPARM_DYNXTALK_NODETECT_SAMPLE_LIMIT_DEFAULT \ +((uint32_t) 40) +#define VL53LX_TUNINGPARM_DYNXTALK_NODETECT_XTALK_OFFSET_KCPS_DEFAULT \ +((uint32_t) 410) +#define VL53LX_TUNINGPARM_DYNXTALK_NODETECT_MIN_RANGE_MM_DEFAULT \ +((uint16_t) 900) +#define VL53LX_TUNINGPARM_LOWPOWERAUTO_VHV_LOOP_BOUND_DEFAULT \ +((uint8_t) 3) +#define VL53LX_TUNINGPARM_LOWPOWERAUTO_MM_CONFIG_TIMEOUT_US_DEFAULT \ +((uint32_t) 1) +#define VL53LX_TUNINGPARM_LOWPOWERAUTO_RANGE_CONFIG_TIMEOUT_US_DEFAULT \ +((uint32_t) 8000) +#define VL53LX_TUNINGPARM_VERY_SHORT_DSS_RATE_MCPS_DEFAULT \ +((uint16_t) 10240) +#define VL53LX_TUNINGPARM_PHASECAL_PATCH_POWER_DEFAULT \ +((uint32_t) 1) +#define VL53LX_TUNINGPARM_HIST_MERGE_DEFAULT \ +((uint8_t) 1) +#define VL53LX_TUNINGPARM_RESET_MERGE_THRESHOLD_DEFAULT \ +((uint32_t) 15000) +#define VL53LX_TUNINGPARM_HIST_MERGE_MAX_SIZE_DEFAULT \ +((uint8_t) 6) +#define VL53LX_TUNINGPARM_DYNXTALK_MAX_SMUDGE_FACTOR_DEFAULT \ +((uint32_t) 2000) +#define VL53LX_TUNINGPARM_UWR_ENABLE_DEFAULT \ +((uint8_t) 1) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_1_MIN_DEFAULT \ +((int16_t) 2000) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_1_MAX_DEFAULT \ +((int16_t) 2750) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_2_MIN_DEFAULT \ +((int16_t) 250) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_2_MAX_DEFAULT \ +((int16_t) 1000) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_3_MIN_DEFAULT \ +((int16_t) 1250) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_3_MAX_DEFAULT \ +((int16_t) 1750) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_4_MIN_DEFAULT \ +((int16_t) 1250) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_4_MAX_DEFAULT \ +((int16_t) 1750) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_5_MIN_DEFAULT \ +((int16_t) -200) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_5_MAX_DEFAULT \ +((int16_t) 200) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_1_RANGEA_DEFAULT \ +((int16_t) 2360) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_1_RANGEB_DEFAULT \ +((int16_t) 0) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_2_RANGEA_DEFAULT \ +((int16_t) 2375) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_2_RANGEB_DEFAULT \ +((int16_t) 3125) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_3_RANGEA_DEFAULT \ +((int16_t) 4720) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_3_RANGEB_DEFAULT \ +((int16_t) 3230) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_4_RANGEA_DEFAULT \ +((int16_t) 4750) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_4_RANGEB_DEFAULT \ +((int16_t) 6350) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_5_RANGEA_DEFAULT \ +((int16_t) 0) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_5_RANGEB_DEFAULT \ +((int16_t) 0) +#define VL53LX_TUNINGPARM_UWR_LONG_ZONE_1_MIN_DEFAULT \ +((int16_t) 250) +#define VL53LX_TUNINGPARM_UWR_LONG_ZONE_1_MAX_DEFAULT \ +((int16_t) 1250) +#define VL53LX_TUNINGPARM_UWR_LONG_ZONE_2_MIN_DEFAULT \ +((int16_t) 3250) +#define VL53LX_TUNINGPARM_UWR_LONG_ZONE_2_MAX_DEFAULT \ +((int16_t) 4500) +#define VL53LX_TUNINGPARM_UWR_LONG_ZONE_3_MIN_DEFAULT \ +((int16_t) -200) +#define VL53LX_TUNINGPARM_UWR_LONG_ZONE_3_MAX_DEFAULT \ +((int16_t) 200) +#define VL53LX_TUNINGPARM_UWR_LONG_ZONE_4_MIN_DEFAULT \ +((int16_t) 0) +#define VL53LX_TUNINGPARM_UWR_LONG_ZONE_4_MAX_DEFAULT \ +((int16_t) 0) +#define VL53LX_TUNINGPARM_UWR_LONG_ZONE_5_MIN_DEFAULT \ +((int16_t) 0) +#define VL53LX_TUNINGPARM_UWR_LONG_ZONE_5_MAX_DEFAULT \ +((int16_t) 0) +#define VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_1_RANGEA_DEFAULT \ +((int16_t) 3850) +#define VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_1_RANGEB_DEFAULT \ +((int16_t) 4600) +#define VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_2_RANGEA_DEFAULT \ +((int16_t) 3850) +#define VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_2_RANGEB_DEFAULT \ +((int16_t) 0) +#define VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_3_RANGEA_DEFAULT \ +((int16_t) 0) +#define VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_3_RANGEB_DEFAULT \ +((int16_t) 0) +#define VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_4_RANGEA_DEFAULT \ +((int16_t) 0) +#define VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_4_RANGEB_DEFAULT \ +((int16_t) 0) +#define VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_5_RANGEA_DEFAULT \ +((int16_t) 0) +#define VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_5_RANGEB_DEFAULT \ +((int16_t) 0) + +#define VL53LX_IOCTL_START _IO('p', 0x01) + +#define VL53LX_IOCTL_STOP _IO('p', 0x05) + +#define VL53LX_IOCTL_PARAMETER \ + _IOWR('p', 0x0d, struct stmvl53lx_parameter) + +#define VL53LX_IOCTL_ROI\ + _IOWR('p', 0x0e, struct stmvl53lx_ioctl_roi_t) + +#define VL53LX_IOCTL_MZ_DATA\ + _IOR('p', 0x0f, VL53LX_MultiRangingData_t) + +#define VL53LX_IOCTL_MZ_DATA_BLOCKING\ + _IOR('p', 0x11, VL53LX_MultiRangingData_t) + +#define VL53LX_IOCTL_CALIBRATION_DATA\ + _IOWR('p', 0x12, struct stmvl53lx_ioctl_calibration_data_t) + +#define VL53LX_IOCTL_PERFORM_CALIBRATION\ + _IOW('p', 0x13, struct stmvl53lx_ioctl_perform_calibration_t) + + + +struct stmvl53lx_register { + uint32_t is_read; + uint32_t index; + uint32_t cnt; + int32_t status; + union reg_data_t { + uint8_t b; + uint16_t w; + uint32_t dw; + uint8_t bytes[256]; + } data; +}; + +struct stmvl53lx_register_flexi { + uint32_t is_read; + uint32_t index; + uint32_t cnt; + int32_t status; + uint8_t data[]; +}; + +#define VL53LX_IOCTL_REGISTER _IOWR('p', 0x0c, struct stmvl53lx_register) + +#define VL53LX_IOCTL_MZ_DATA_ADDITIONAL\ + _IOR('p', 0x15, struct stmvl53lx_data_with_additional) + +#define VL53LX_IOCTL_MZ_DATA_ADDITIONAL_BLOCKING\ + _IOR('p', 0x16, struct stmvl53lx_data_with_additional) + +#define VL53LX_NVM_POWER_UP_DELAY_US 50 +#define VL53LX_NVM_READ_TRIGGER_DELAY_US 5 +#define VL53LX_NVM__IDENTIFICATION__MODEL_ID 0x0008 +#define VL53LX_NVM__IDENTIFICATION__MODULE_TYPE 0x000C +#define VL53LX_NVM__IDENTIFICATION__REVISION_ID 0x000D +#define VL53LX_NVM__IDENTIFICATION__MODULE_ID 0x000E +#define VL53LX_NVM__I2C_VALID 0x0010 +#define VL53LX_NVM__I2C_SLAVE__DEVICE_ADDRESS 0x0011 +#define VL53LX_NVM__EWS__OSC_MEASURED__FAST_OSC_FREQUENCY 0x0014 +#define VL53LX_NVM__EWS__FAST_OSC_TRIM_MAX 0x0016 +#define VL53LX_NVM__EWS__FAST_OSC_FREQ_SET 0x0017 +#define VL53LX_NVM__EWS__SLOW_OSC_CALIBRATION 0x0018 +#define VL53LX_NVM__FMT__OSC_MEASURED__FAST_OSC_FREQUENCY 0x001C +#define VL53LX_NVM__FMT__FAST_OSC_TRIM_MAX 0x001E +#define VL53LX_NVM__FMT__FAST_OSC_FREQ_SET 0x001F +#define VL53LX_NVM__FMT__SLOW_OSC_CALIBRATION 0x0020 +#define VL53LX_NVM__VHV_CONFIG_UNLOCK 0x0028 +#define VL53LX_NVM__REF_SELVDDPIX 0x0029 +#define VL53LX_NVM__REF_SELVQUENCH 0x002A +#define VL53LX_NVM__REGAVDD1V2_SEL_REGDVDD1V2_SEL 0x002B +#define VL53LX_NVM__VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND 0x002C +#define VL53LX_NVM__VHV_CONFIG__COUNT_THRESH 0x002D +#define VL53LX_NVM__VHV_CONFIG__OFFSET 0x002E +#define VL53LX_NVM__VHV_CONFIG__INIT 0x002F +#define VL53LX_NVM__LASER_SAFETY__VCSEL_TRIM_LL 0x0030 +#define VL53LX_NVM__LASER_SAFETY__VCSEL_SELION_LL 0x0031 +#define VL53LX_NVM__LASER_SAFETY__VCSEL_SELION_MAX_LL 0x0032 +#define VL53LX_NVM__LASER_SAFETY__MULT_LL 0x0034 +#define VL53LX_NVM__LASER_SAFETY__CLIP_LL 0x0035 +#define VL53LX_NVM__LASER_SAFETY__VCSEL_TRIM_LD 0x0038 +#define VL53LX_NVM__LASER_SAFETY__VCSEL_SELION_LD 0x0039 +#define VL53LX_NVM__LASER_SAFETY__VCSEL_SELION_MAX_LD 0x003A +#define VL53LX_NVM__LASER_SAFETY__MULT_LD 0x003C +#define VL53LX_NVM__LASER_SAFETY__CLIP_LD 0x003D +#define VL53LX_NVM__LASER_SAFETY_LOCK_BYTE 0x0040 +#define VL53LX_NVM__LASER_SAFETY_UNLOCK_BYTE 0x0044 +#define VL53LX_NVM__EWS__SPAD_ENABLES_RTN_0_ 0x0048 +#define VL53LX_NVM__EWS__SPAD_ENABLES_RTN_1_ 0x0049 +#define VL53LX_NVM__EWS__SPAD_ENABLES_RTN_2_ 0x004A +#define VL53LX_NVM__EWS__SPAD_ENABLES_RTN_3_ 0x004B +#define VL53LX_NVM__EWS__SPAD_ENABLES_RTN_4_ 0x004C +#define VL53LX_NVM__EWS__SPAD_ENABLES_RTN_5_ 0x004D +#define VL53LX_NVM__EWS__SPAD_ENABLES_RTN_6_ 0x004E +#define VL53LX_NVM__EWS__SPAD_ENABLES_RTN_7_ 0x004F +#define VL53LX_NVM__EWS__SPAD_ENABLES_RTN_8_ 0x0050 +#define VL53LX_NVM__EWS__SPAD_ENABLES_RTN_9_ 0x0051 +#define VL53LX_NVM__EWS__SPAD_ENABLES_RTN_10_ 0x0052 +#define VL53LX_NVM__EWS__SPAD_ENABLES_RTN_11_ 0x0053 +#define VL53LX_NVM__EWS__SPAD_ENABLES_RTN_12_ 0x0054 +#define VL53LX_NVM__EWS__SPAD_ENABLES_RTN_13_ 0x0055 +#define VL53LX_NVM__EWS__SPAD_ENABLES_RTN_14_ 0x0056 +#define VL53LX_NVM__EWS__SPAD_ENABLES_RTN_15_ 0x0057 +#define VL53LX_NVM__EWS__SPAD_ENABLES_RTN_16_ 0x0058 +#define VL53LX_NVM__EWS__SPAD_ENABLES_RTN_17_ 0x0059 +#define VL53LX_NVM__EWS__SPAD_ENABLES_RTN_18_ 0x005A +#define VL53LX_NVM__EWS__SPAD_ENABLES_RTN_19_ 0x005B +#define VL53LX_NVM__EWS__SPAD_ENABLES_RTN_20_ 0x005C +#define VL53LX_NVM__EWS__SPAD_ENABLES_RTN_21_ 0x005D +#define VL53LX_NVM__EWS__SPAD_ENABLES_RTN_22_ 0x005E +#define VL53LX_NVM__EWS__SPAD_ENABLES_RTN_23_ 0x005F +#define VL53LX_NVM__EWS__SPAD_ENABLES_RTN_24_ 0x0060 +#define VL53LX_NVM__EWS__SPAD_ENABLES_RTN_25_ 0x0061 +#define VL53LX_NVM__EWS__SPAD_ENABLES_RTN_26_ 0x0062 +#define VL53LX_NVM__EWS__SPAD_ENABLES_RTN_27_ 0x0063 +#define VL53LX_NVM__EWS__SPAD_ENABLES_RTN_28_ 0x0064 +#define VL53LX_NVM__EWS__SPAD_ENABLES_RTN_29_ 0x0065 +#define VL53LX_NVM__EWS__SPAD_ENABLES_RTN_30_ 0x0066 +#define VL53LX_NVM__EWS__SPAD_ENABLES_RTN_31_ 0x0067 +#define VL53LX_NVM__EWS__SPAD_ENABLES_REF__LOC1_0_ 0x0068 +#define VL53LX_NVM__EWS__SPAD_ENABLES_REF__LOC1_1_ 0x0069 +#define VL53LX_NVM__EWS__SPAD_ENABLES_REF__LOC1_2_ 0x006A +#define VL53LX_NVM__EWS__SPAD_ENABLES_REF__LOC1_3_ 0x006B +#define VL53LX_NVM__EWS__SPAD_ENABLES_REF__LOC1_4_ 0x006C +#define VL53LX_NVM__EWS__SPAD_ENABLES_REF__LOC1_5_ 0x006D +#define VL53LX_NVM__EWS__SPAD_ENABLES_REF__LOC2_0_ 0x0070 +#define VL53LX_NVM__EWS__SPAD_ENABLES_REF__LOC2_1_ 0x0071 +#define VL53LX_NVM__EWS__SPAD_ENABLES_REF__LOC2_2_ 0x0072 +#define VL53LX_NVM__EWS__SPAD_ENABLES_REF__LOC2_3_ 0x0073 +#define VL53LX_NVM__EWS__SPAD_ENABLES_REF__LOC2_4_ 0x0074 +#define VL53LX_NVM__EWS__SPAD_ENABLES_REF__LOC2_5_ 0x0075 +#define VL53LX_NVM__EWS__SPAD_ENABLES_REF__LOC3_0_ 0x0078 +#define VL53LX_NVM__EWS__SPAD_ENABLES_REF__LOC3_1_ 0x0079 +#define VL53LX_NVM__EWS__SPAD_ENABLES_REF__LOC3_2_ 0x007A +#define VL53LX_NVM__EWS__SPAD_ENABLES_REF__LOC3_3_ 0x007B +#define VL53LX_NVM__EWS__SPAD_ENABLES_REF__LOC3_4_ 0x007C +#define VL53LX_NVM__EWS__SPAD_ENABLES_REF__LOC3_5_ 0x007D +#define VL53LX_NVM__FMT__SPAD_ENABLES_RTN_0_ 0x0080 +#define VL53LX_NVM__FMT__SPAD_ENABLES_RTN_1_ 0x0081 +#define VL53LX_NVM__FMT__SPAD_ENABLES_RTN_2_ 0x0082 +#define VL53LX_NVM__FMT__SPAD_ENABLES_RTN_3_ 0x0083 +#define VL53LX_NVM__FMT__SPAD_ENABLES_RTN_4_ 0x0084 +#define VL53LX_NVM__FMT__SPAD_ENABLES_RTN_5_ 0x0085 +#define VL53LX_NVM__FMT__SPAD_ENABLES_RTN_6_ 0x0086 +#define VL53LX_NVM__FMT__SPAD_ENABLES_RTN_7_ 0x0087 +#define VL53LX_NVM__FMT__SPAD_ENABLES_RTN_8_ 0x0088 +#define VL53LX_NVM__FMT__SPAD_ENABLES_RTN_9_ 0x0089 +#define VL53LX_NVM__FMT__SPAD_ENABLES_RTN_10_ 0x008A +#define VL53LX_NVM__FMT__SPAD_ENABLES_RTN_11_ 0x008B +#define VL53LX_NVM__FMT__SPAD_ENABLES_RTN_12_ 0x008C +#define VL53LX_NVM__FMT__SPAD_ENABLES_RTN_13_ 0x008D +#define VL53LX_NVM__FMT__SPAD_ENABLES_RTN_14_ 0x008E +#define VL53LX_NVM__FMT__SPAD_ENABLES_RTN_15_ 0x008F +#define VL53LX_NVM__FMT__SPAD_ENABLES_RTN_16_ 0x0090 +#define VL53LX_NVM__FMT__SPAD_ENABLES_RTN_17_ 0x0091 +#define VL53LX_NVM__FMT__SPAD_ENABLES_RTN_18_ 0x0092 +#define VL53LX_NVM__FMT__SPAD_ENABLES_RTN_19_ 0x0093 +#define VL53LX_NVM__FMT__SPAD_ENABLES_RTN_20_ 0x0094 +#define VL53LX_NVM__FMT__SPAD_ENABLES_RTN_21_ 0x0095 +#define VL53LX_NVM__FMT__SPAD_ENABLES_RTN_22_ 0x0096 +#define VL53LX_NVM__FMT__SPAD_ENABLES_RTN_23_ 0x0097 +#define VL53LX_NVM__FMT__SPAD_ENABLES_RTN_24_ 0x0098 +#define VL53LX_NVM__FMT__SPAD_ENABLES_RTN_25_ 0x0099 +#define VL53LX_NVM__FMT__SPAD_ENABLES_RTN_26_ 0x009A +#define VL53LX_NVM__FMT__SPAD_ENABLES_RTN_27_ 0x009B +#define VL53LX_NVM__FMT__SPAD_ENABLES_RTN_28_ 0x009C +#define VL53LX_NVM__FMT__SPAD_ENABLES_RTN_29_ 0x009D +#define VL53LX_NVM__FMT__SPAD_ENABLES_RTN_30_ 0x009E +#define VL53LX_NVM__FMT__SPAD_ENABLES_RTN_31_ 0x009F +#define VL53LX_NVM__FMT__SPAD_ENABLES_REF__LOC1_0_ 0x00A0 +#define VL53LX_NVM__FMT__SPAD_ENABLES_REF__LOC1_1_ 0x00A1 +#define VL53LX_NVM__FMT__SPAD_ENABLES_REF__LOC1_2_ 0x00A2 +#define VL53LX_NVM__FMT__SPAD_ENABLES_REF__LOC1_3_ 0x00A3 +#define VL53LX_NVM__FMT__SPAD_ENABLES_REF__LOC1_4_ 0x00A4 +#define VL53LX_NVM__FMT__SPAD_ENABLES_REF__LOC1_5_ 0x00A5 +#define VL53LX_NVM__FMT__SPAD_ENABLES_REF__LOC2_0_ 0x00A8 +#define VL53LX_NVM__FMT__SPAD_ENABLES_REF__LOC2_1_ 0x00A9 +#define VL53LX_NVM__FMT__SPAD_ENABLES_REF__LOC2_2_ 0x00AA +#define VL53LX_NVM__FMT__SPAD_ENABLES_REF__LOC2_3_ 0x00AB +#define VL53LX_NVM__FMT__SPAD_ENABLES_REF__LOC2_4_ 0x00AC +#define VL53LX_NVM__FMT__SPAD_ENABLES_REF__LOC2_5_ 0x00AD +#define VL53LX_NVM__FMT__SPAD_ENABLES_REF__LOC3_0_ 0x00B0 +#define VL53LX_NVM__FMT__SPAD_ENABLES_REF__LOC3_1_ 0x00B1 +#define VL53LX_NVM__FMT__SPAD_ENABLES_REF__LOC3_2_ 0x00B2 +#define VL53LX_NVM__FMT__SPAD_ENABLES_REF__LOC3_3_ 0x00B3 +#define VL53LX_NVM__FMT__SPAD_ENABLES_REF__LOC3_4_ 0x00B4 +#define VL53LX_NVM__FMT__SPAD_ENABLES_REF__LOC3_5_ 0x00B5 +#define VL53LX_NVM__FMT__ROI_CONFIG__MODE_ROI_CENTRE_SPAD 0x00B8 +#define VL53LX_NVM__FMT__ROI_CONFIG__MODE_ROI_XY_SIZE 0x00B9 +#define VL53LX_NVM__FMT__REF_SPAD_APPLY__NUM_REQUESTED_REF_SPAD 0x00BC +#define VL53LX_NVM__FMT__REF_SPAD_MAN__REF_LOCATION 0x00BD +#define VL53LX_NVM__FMT__MM_CONFIG__INNER_OFFSET_MM 0x00C0 +#define VL53LX_NVM__FMT__MM_CONFIG__OUTER_OFFSET_MM 0x00C2 +#define VL53LX_NVM__FMT__ALGO__PART_TO_PART_RANGE_OFFSET_MM 0x00C4 +#define VL53LX_NVM__FMT__ALGO__CROSSTALK_COMPENSATION_PLANE_OFFSET_KCPS 0x00C8 +#define VL53LX_NVM__FMT__ALGO__CROSSTALK_COMPENSATION_X_PLANE_GRADIENT_KCPS 0x00CA +#define VL53LX_NVM__FMT__ALGO__CROSSTALK_COMPENSATION_Y_PLANE_GRADIENT_KCPS 0x00CC +#define VL53LX_NVM__FMT__SPARE_HOST_CONFIG__NVM_CONFIG_SPARE_0 0x00CE +#define VL53LX_NVM__FMT__SPARE_HOST_CONFIG__NVM_CONFIG_SPARE_1 0x00CF +#define VL53LX_NVM__CUSTOMER_NVM_SPACE_PROGRAMMED 0x00E0 +#define VL53LX_NVM__CUST__I2C_SLAVE__DEVICE_ADDRESS 0x00E4 +#define VL53LX_NVM__CUST__REF_SPAD_APPLY__NUM_REQUESTED_REF_SPAD 0x00E8 +#define VL53LX_NVM__CUST__REF_SPAD_MAN__REF_LOCATION 0x00E9 +#define VL53LX_NVM__CUST__MM_CONFIG__INNER_OFFSET_MM 0x00EC +#define VL53LX_NVM__CUST__MM_CONFIG__OUTER_OFFSET_MM 0x00EE +#define VL53LX_NVM__CUST__ALGO__PART_TO_PART_RANGE_OFFSET_MM 0x00F0 +#define VL53LX_NVM__CUST__ALGO__CROSSTALK_COMPENSATION_PLANE_OFFSET_KCPS 0x00F4 +#define VL53LX_NVM__CUST__ALGO__CROSSTALK_COMPENSATION_X_PLANE_GRADIENT_KCPS 0x00F6 +#define VL53LX_NVM__CUST__ALGO__CROSSTALK_COMPENSATION_Y_PLANE_GRADIENT_KCPS 0x00F8 +#define VL53LX_NVM__CUST__SPARE_HOST_CONFIG__NVM_CONFIG_SPARE_0 0x00FA +#define VL53LX_NVM__CUST__SPARE_HOST_CONFIG__NVM_CONFIG_SPARE_1 0x00FB +#define VL53LX_NVM__FMT__FGC__BYTE_0 0x01DC +#define VL53LX_NVM__FMT__FGC__BYTE_1 0x01DD +#define VL53LX_NVM__FMT__FGC__BYTE_2 0x01DE +#define VL53LX_NVM__FMT__FGC__BYTE_3 0x01DF +#define VL53LX_NVM__FMT__FGC__BYTE_4 0x01E0 +#define VL53LX_NVM__FMT__FGC__BYTE_5 0x01E1 +#define VL53LX_NVM__FMT__FGC__BYTE_6 0x01E2 +#define VL53LX_NVM__FMT__FGC__BYTE_7 0x01E3 +#define VL53LX_NVM__FMT__FGC__BYTE_8 0x01E4 +#define VL53LX_NVM__FMT__FGC__BYTE_9 0x01E5 +#define VL53LX_NVM__FMT__FGC__BYTE_10 0x01E6 +#define VL53LX_NVM__FMT__FGC__BYTE_11 0x01E7 +#define VL53LX_NVM__FMT__FGC__BYTE_12 0x01E8 +#define VL53LX_NVM__FMT__FGC__BYTE_13 0x01E9 +#define VL53LX_NVM__FMT__FGC__BYTE_14 0x01EA +#define VL53LX_NVM__FMT__FGC__BYTE_15 0x01EB +#define VL53LX_NVM__FMT__TEST_PROGRAM_MAJOR_MINOR 0x01EC +#define VL53LX_NVM__FMT__MAP_MAJOR_MINOR 0x01ED +#define VL53LX_NVM__FMT__YEAR_MONTH 0x01EE +#define VL53LX_NVM__FMT__DAY_MODULE_DATE_PHASE 0x01EF +#define VL53LX_NVM__FMT__TIME 0x01F0 +#define VL53LX_NVM__FMT__TESTER_ID 0x01F2 +#define VL53LX_NVM__FMT__SITE_ID 0x01F3 +#define VL53LX_NVM__EWS__TEST_PROGRAM_MAJOR_MINOR 0x01F4 +#define VL53LX_NVM__EWS__PROBE_CARD_MAJOR_MINOR 0x01F5 +#define VL53LX_NVM__EWS__TESTER_ID 0x01F6 +#define VL53LX_NVM__EWS__LOT__BYTE_0 0x01F8 +#define VL53LX_NVM__EWS__LOT__BYTE_1 0x01F9 +#define VL53LX_NVM__EWS__LOT__BYTE_2 0x01FA +#define VL53LX_NVM__EWS__LOT__BYTE_3 0x01FB +#define VL53LX_NVM__EWS__LOT__BYTE_4 0x01FC +#define VL53LX_NVM__EWS__LOT__BYTE_5 0x01FD +#define VL53LX_NVM__EWS__WAFER 0x01FD +#define VL53LX_NVM__EWS__XCOORD 0x01FE +#define VL53LX_NVM__EWS__YCOORD 0x01FF +#define VL53LX_NVM__FMT__OPTICAL_CENTRE_DATA_INDEX 0x00B8 +#define VL53LX_NVM__FMT__OPTICAL_CENTRE_DATA_SIZE 4 +#define VL53LX_NVM__FMT__CAL_PEAK_RATE_MAP_DATA_INDEX 0x015C +#define VL53LX_NVM__FMT__CAL_PEAK_RATE_MAP_DATA_SIZE 56 +#define VL53LX_NVM__FMT__ADDITIONAL_OFFSET_CAL_DATA_INDEX 0x0194 +#define VL53LX_NVM__FMT__ADDITIONAL_OFFSET_CAL_DATA_SIZE 8 +#define VL53LX_NVM__FMT__RANGE_RESULTS__140MM_MM_PRE_RANGE 0x019C +#define VL53LX_NVM__FMT__RANGE_RESULTS__140MM_DARK 0x01AC +#define VL53LX_NVM__FMT__RANGE_RESULTS__400MM_DARK 0x01BC +#define VL53LX_NVM__FMT__RANGE_RESULTS__400MM_AMBIENT 0x01CC +#define VL53LX_NVM__FMT__RANGE_RESULTS__SIZE_BYTES 16 + + +typedef uint8_t VL53LX_SmudgeCorrectionModes; +#define VL53LX_SMUDGE_CORRECTION_NONE ((VL53LX_SmudgeCorrectionModes) 0) +#define VL53LX_SMUDGE_CORRECTION_CONTINUOUS ((VL53LX_SmudgeCorrectionModes) 1) +#define VL53LX_SMUDGE_CORRECTION_SINGLE ((VL53LX_SmudgeCorrectionModes) 2) +#define VL53LX_SMUDGE_CORRECTION_DEBUG ((VL53LX_SmudgeCorrectionModes) 3) + +typedef uint8_t VL53LX_OffsetCorrectionModes; +#define VL53LX_OFFSETCORRECTIONMODE_STANDARD ((VL53LX_OffsetCorrectionModes) 1) +#define VL53LX_OFFSETCORRECTIONMODE_PERVCSEL ((VL53LX_OffsetCorrectionModes) 3) + +typedef int8_t VL53LX_Error; + +#define VL53LX_ERROR_NONE ((VL53LX_Error) 0) +#define VL53LX_ERROR_CALIBRATION_WARNING ((VL53LX_Error) - 1) +#define VL53LX_ERROR_MIN_CLIPPED ((VL53LX_Error) - 2) +#define VL53LX_ERROR_UNDEFINED ((VL53LX_Error) - 3) +#define VL53LX_ERROR_INVALID_PARAMS ((VL53LX_Error) - 4) +#define VL53LX_ERROR_NOT_SUPPORTED ((VL53LX_Error) - 5) +#define VL53LX_ERROR_RANGE_ERROR ((VL53LX_Error) - 6) +#define VL53LX_ERROR_TIME_OUT ((VL53LX_Error) - 7) +#define VL53LX_ERROR_MODE_NOT_SUPPORTED ((VL53LX_Error) - 8) +#define VL53LX_ERROR_BUFFER_TOO_SMALL ((VL53LX_Error) - 9) +#define VL53LX_ERROR_COMMS_BUFFER_TOO_SMALL ((VL53LX_Error) - 10) +#define VL53LX_ERROR_GPIO_NOT_EXISTING ((VL53LX_Error) - 11) +#define VL53LX_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED ((VL53LX_Error) - 12) +#define VL53LX_ERROR_CONTROL_INTERFACE ((VL53LX_Error) - 13) +#define VL53LX_ERROR_INVALID_COMMAND ((VL53LX_Error) - 14) +#define VL53LX_ERROR_DIVISION_BY_ZERO ((VL53LX_Error) - 15) +#define VL53LX_ERROR_REF_SPAD_INIT ((VL53LX_Error) - 16) +#define VL53LX_ERROR_GPH_SYNC_CHECK_FAIL ((VL53LX_Error) - 17) +#define VL53LX_ERROR_STREAM_COUNT_CHECK_FAIL ((VL53LX_Error) - 18) +#define VL53LX_ERROR_GPH_ID_CHECK_FAIL ((VL53LX_Error) - 19) +#define VL53LX_ERROR_ZONE_STREAM_COUNT_CHECK_FAIL ((VL53LX_Error) - 20) +#define VL53LX_ERROR_ZONE_GPH_ID_CHECK_FAIL ((VL53LX_Error) - 21) +#define VL53LX_ERROR_XTALK_EXTRACTION_NO_SAMPLE_FAIL ((VL53LX_Error) - 22) +#define VL53LX_ERROR_XTALK_EXTRACTION_SIGMA_LIMIT_FAIL ((VL53LX_Error) - 23) +#define VL53LX_ERROR_OFFSET_CAL_NO_SAMPLE_FAIL ((VL53LX_Error) - 24) +#define VL53LX_ERROR_OFFSET_CAL_NO_SPADS_ENABLED_FAIL ((VL53LX_Error) - 25) +#define VL53LX_ERROR_ZONE_CAL_NO_SAMPLE_FAIL ((VL53LX_Error) - 26) +#define VL53LX_ERROR_TUNING_PARM_KEY_MISMATCH ((VL53LX_Error) - 27) +#define VL53LX_WARNING_REF_SPAD_CHAR_NOT_ENOUGH_SPADS ((VL53LX_Error) - 28) +#define VL53LX_WARNING_REF_SPAD_CHAR_RATE_TOO_HIGH ((VL53LX_Error) - 29) +#define VL53LX_WARNING_REF_SPAD_CHAR_RATE_TOO_LOW ((VL53LX_Error) - 30) +#define VL53LX_WARNING_OFFSET_CAL_MISSING_SAMPLES ((VL53LX_Error) - 31) +#define VL53LX_WARNING_OFFSET_CAL_SIGMA_TOO_HIGH ((VL53LX_Error) - 32) +#define VL53LX_WARNING_OFFSET_CAL_RATE_TOO_HIGH ((VL53LX_Error) - 33) +#define VL53LX_WARNING_OFFSET_CAL_SPAD_COUNT_TOO_LOW ((VL53LX_Error) - 34) +#define VL53LX_WARNING_ZONE_CAL_MISSING_SAMPLES ((VL53LX_Error) - 35) +#define VL53LX_WARNING_ZONE_CAL_SIGMA_TOO_HIGH ((VL53LX_Error) - 36) +#define VL53LX_WARNING_ZONE_CAL_RATE_TOO_HIGH ((VL53LX_Error) - 37) +#define VL53LX_WARNING_XTALK_MISSING_SAMPLES ((VL53LX_Error) - 38) +#define VL53LX_WARNING_XTALK_NO_SAMPLES_FOR_GRADIENT ((VL53LX_Error) - 39) +#define VL53LX_WARNING_XTALK_SIGMA_LIMIT_FOR_GRADIENT ((VL53LX_Error) - 40) +#define VL53LX_ERROR_NOT_IMPLEMENTED ((VL53LX_Error) - 41) +#define VL53LX_ERROR_PLATFORM_SPECIFIC_START ((VL53LX_Error) - 60) + +#define VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS 0x8000 +#define VL53LX_TUNINGPARM_PRIVATE_PAGE_BASE_ADDRESS 0xC000 + +#define VL53LX_CALIBRATION_REF_SPAD 0 +#define VL53LX_CALIBRATION_CROSSTALK 1 +#define VL53LX_CALIBRATION_OFFSET 2 +#define VL53LX_CALIBRATION_OFFSET_SIMPLE 4 +#define VL53LX_CALIBRATION_OFFSET_PER_VCSEL 5 +#define VL53LX_CALIBRATION_OFFSET_ZERO_DISTANCE 6 + +typedef uint8_t VL53LX_DeviceZonePreset; + +typedef uint8_t VL53LX_DevicePresetModes; + +#define VL53LX_DEVICEPRESETMODE_NONE \ + ((VL53LX_DevicePresetModes) 0) +#define VL53LX_DEVICEPRESETMODE_HISTOGRAM_LONG_RANGE \ + ((VL53LX_DevicePresetModes) 27) +#define VL53LX_DEVICEPRESETMODE_HISTOGRAM_MEDIUM_RANGE \ + ((VL53LX_DevicePresetModes) 30) +#define VL53LX_DEVICEPRESETMODE_HISTOGRAM_SHORT_RANGE \ + ((VL53LX_DevicePresetModes) 33) + +typedef uint8_t VL53LX_DeviceMeasurementModes; + +#define VL53LX_DEVICEMEASUREMENTMODE_STOP \ + ((VL53LX_DeviceMeasurementModes) 0x00) +#define VL53LX_DEVICEMEASUREMENTMODE_SINGLESHOT \ + ((VL53LX_DeviceMeasurementModes) 0x10) +#define VL53LX_DEVICEMEASUREMENTMODE_BACKTOBACK \ + ((VL53LX_DeviceMeasurementModes) 0x20) +#define VL53LX_DEVICEMEASUREMENTMODE_TIMED \ + ((VL53LX_DeviceMeasurementModes) 0x40) +#define VL53LX_DEVICEMEASUREMENTMODE_ABORT \ + ((VL53LX_DeviceMeasurementModes) 0x80) + +typedef uint8_t VL53LX_OffsetCalibrationMode; + +#define VL53LX_OFFSETCALIBRATIONMODE__NONE \ + ((VL53LX_OffsetCalibrationMode) 0) +#define VL53LX_OFFSETCALIBRATIONMODE__MM1_MM2__STANDARD \ + ((VL53LX_OffsetCalibrationMode) 1) +#define VL53LX_OFFSETCALIBRATIONMODE__MM1_MM2__HISTOGRAM \ + ((VL53LX_OffsetCalibrationMode) 2) +#define VL53LX_OFFSETCALIBRATIONMODE__MM1_MM2__STANDARD_PRE_RANGE_ONLY \ + ((VL53LX_OffsetCalibrationMode) 3) +#define VL53LX_OFFSETCALIBRATIONMODE__MM1_MM2__HISTOGRAM_PRE_RANGE_ONLY \ + ((VL53LX_OffsetCalibrationMode) 4) + +typedef uint8_t VL53LX_OffsetCorrectionMode; + +#define VL53LX_OFFSETCORRECTIONMODE__NONE \ + ((VL53LX_OffsetCorrectionMode) 0) +#define VL53LX_OFFSETCORRECTIONMODE__MM1_MM2_OFFSETS \ + ((VL53LX_OffsetCorrectionMode) 1) +#define VL53LX_OFFSETCORRECTIONMODE__PER_VCSEL_OFFSETS \ + ((VL53LX_OffsetCorrectionMode) 3) + +typedef uint8_t VL53LX_DeviceDmaxMode; + +#define VL53LX_DEVICEDMAXMODE__NONE \ + ((VL53LX_DeviceDmaxMode) 0) +#define VL53LX_DEVICEDMAXMODE__FMT_CAL_DATA \ + ((VL53LX_DeviceDmaxMode) 1) +#define VL53LX_DEVICEDMAXMODE__CUST_CAL_DATA \ + ((VL53LX_DeviceDmaxMode) 2) + +typedef uint8_t VL53LX_DeviceState; + +#define VL53LX_DEVICESTATE_POWERDOWN ((VL53LX_DeviceState) 0) +#define VL53LX_DEVICESTATE_HW_STANDBY ((VL53LX_DeviceState) 1) +#define VL53LX_DEVICESTATE_FW_COLDBOOT ((VL53LX_DeviceState) 2) +#define VL53LX_DEVICESTATE_SW_STANDBY ((VL53LX_DeviceState) 3) +#define VL53LX_DEVICESTATE_RANGING_DSS_AUTO ((VL53LX_DeviceState) 4) +#define VL53LX_DEVICESTATE_RANGING_DSS_MANUAL ((VL53LX_DeviceState) 5) +#define VL53LX_DEVICESTATE_RANGING_WAIT_GPH_SYNC ((VL53LX_DeviceState) 6) +#define VL53LX_DEVICESTATE_RANGING_GATHER_DATA ((VL53LX_DeviceState) 7) +#define VL53LX_DEVICESTATE_RANGING_OUTPUT_DATA ((VL53LX_DeviceState) 8) + +#define VL53LX_DEVICESTATE_UNKNOWN ((VL53LX_DeviceState) 98) +#define VL53LX_DEVICESTATE_ERROR ((VL53LX_DeviceState) 99) + +typedef uint8_t VL53LX_GPIO_Interrupt_Mode; + +#define VL53LX_GPIOINTMODE_LEVEL_LOW \ + ((VL53LX_GPIO_Interrupt_Mode) 0) +#define VL53LX_GPIOINTMODE_LEVEL_HIGH \ + ((VL53LX_GPIO_Interrupt_Mode) 1) +#define VL53LX_GPIOINTMODE_OUT_OF_WINDOW \ + ((VL53LX_GPIO_Interrupt_Mode) 2) +#define VL53LX_GPIOINTMODE_IN_WINDOW \ + ((VL53LX_GPIO_Interrupt_Mode) 3) + +typedef uint8_t VL53LX_DeviceSscArray; + +#define VL53LX_DEVICESSCARRAY_RTN ((VL53LX_DeviceSscArray) 0x00) + +#define VL53LX_DEVICETESTMODE_REF ((VL53LX_DeviceSscArray) 0x01) + +typedef uint8_t VL53LX_HistAlgoSelect; + +#define VL53LX_HIST_ALGO_SELECT__PW_HIST_GEN1 \ + ((VL53LX_HistAlgoSelect) 1) +#define VL53LX_HIST_ALGO_SELECT__PW_HIST_GEN2 \ + ((VL53LX_HistAlgoSelect) 2) +#define VL53LX_HIST_ALGO_SELECT__PW_HIST_GEN3 \ + ((VL53LX_HistAlgoSelect) 3) +#define VL53LX_HIST_ALGO_SELECT__PW_HIST_GEN4 \ + ((VL53LX_HistAlgoSelect) 4) + + +typedef uint8_t VL53LX_HistTargetOrder; + +#define VL53LX_HIST_TARGET_ORDER__INCREASING_DISTANCE \ + ((VL53LX_HistTargetOrder) 1) +#define VL53LX_HIST_TARGET_ORDER__STRONGEST_FIRST \ + ((VL53LX_HistTargetOrder) 2) + +typedef uint8_t VL53LX_HistAmbEstMethod; + +#define VL53LX_HIST_AMB_EST_METHOD__AMBIENT_BINS \ + ((VL53LX_HistAmbEstMethod) 1) +#define VL53LX_HIST_AMB_EST_METHOD__THRESHOLDED_BINS \ + ((VL53LX_HistAmbEstMethod) 2) + +typedef uint16_t VL53LX_TuningParms; + +#define VL53LX_TUNINGPARMS_LLD_PUBLIC_MIN_ADDRESS \ + ((VL53LX_TuningParms) VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS) +#define VL53LX_TUNINGPARMS_LLD_PUBLIC_MAX_ADDRESS \ + ((VL53LX_TuningParms) VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_5_RANGEB) + +#define VL53LX_TUNINGPARMS_LLD_PRIVATE_MIN_ADDRESS \ + ((VL53LX_TuningParms) VL53LX_TUNINGPARM_PRIVATE_PAGE_BASE_ADDRESS) +#define VL53LX_TUNINGPARMS_LLD_PRIVATE_MAX_ADDRESS \ + ((VL53LX_TuningParms) VL53LX_TUNINGPARMS_LLD_PRIVATE_MIN_ADDRESS) + +typedef uint8_t VL53LX_DistanceModes; + +#define VL53LX_DISTANCEMODE_SHORT ((VL53LX_DistanceModes) 1) +#define VL53LX_DISTANCEMODE_MEDIUM ((VL53LX_DistanceModes) 2) +#define VL53LX_DISTANCEMODE_LONG ((VL53LX_DistanceModes) 3) + +typedef uint8_t VL53LX_DeviceInterruptPolarity; + +#define VL53LX_DEVICEINTERRUPTPOLARITY_ACTIVE_HIGH \ + ((VL53LX_DeviceInterruptPolarity) 0x00) +#define VL53LX_DEVICEINTERRUPTPOLARITY_ACTIVE_LOW \ + ((VL53LX_DeviceInterruptPolarity) 0x10) +#define VL53LX_DEVICEINTERRUPTPOLARITY_BIT_MASK \ + ((VL53LX_DeviceInterruptPolarity) 0x10) +#define VL53LX_DEVICEINTERRUPTPOLARITY_CLEAR_MASK \ + ((VL53LX_DeviceInterruptPolarity) 0xEF) + +typedef uint8_t VL53LX_ZoneConfig_BinConfig_select; + +#define VL53LX_ZONECONFIG_BINCONFIG__LOWAMB \ + ((VL53LX_ZoneConfig_BinConfig_select) 1) +#define VL53LX_ZONECONFIG_BINCONFIG__MIDAMB \ + ((VL53LX_ZoneConfig_BinConfig_select) 2) +#define VL53LX_ZONECONFIG_BINCONFIG__HIGHAMB \ + ((VL53LX_ZoneConfig_BinConfig_select) 3) + +typedef uint8_t VL53LX_DeviceConfigLevel; + +#define VL53LX_DEVICECONFIGLEVEL_SYSTEM_CONTROL \ + ((VL53LX_DeviceConfigLevel) 0) + +#define VL53LX_DEVICECONFIGLEVEL_DYNAMIC_ONWARDS \ + ((VL53LX_DeviceConfigLevel) 1) + +#define VL53LX_DEVICECONFIGLEVEL_TIMING_ONWARDS \ + ((VL53LX_DeviceConfigLevel) 2) + +#define VL53LX_DEVICECONFIGLEVEL_GENERAL_ONWARDS \ + ((VL53LX_DeviceConfigLevel) 3) + +#define VL53LX_DEVICECONFIGLEVEL_STATIC_ONWARDS \ + ((VL53LX_DeviceConfigLevel) 4) + +#define VL53LX_DEVICECONFIGLEVEL_CUSTOMER_ONWARDS \ + ((VL53LX_DeviceConfigLevel) 5) + +#define VL53LX_DEVICECONFIGLEVEL_FULL \ + ((VL53LX_DeviceConfigLevel) 6) + +typedef uint8_t VL53LX_DeviceResultsLevel; + +#define VL53LX_DEVICERESULTSLEVEL_SYSTEM_RESULTS \ + ((VL53LX_DeviceResultsLevel) 0) + +#define VL53LX_DEVICERESULTSLEVEL_UPTO_CORE \ + ((VL53LX_DeviceResultsLevel) 1) + +#define VL53LX_DEVICERESULTSLEVEL_FULL \ + ((VL53LX_DeviceResultsLevel) 2) + +typedef uint8_t VL53LX_DeviceReportStatus; + +#define VL53LX_DEVICEREPORTSTATUS_NOUPDATE \ + ((VL53LX_DeviceReportStatus) 0) + +#define VL53LX_DEVICEREPORTSTATUS_ROI_SETUP \ + ((VL53LX_DeviceReportStatus) 1) +#define VL53LX_DEVICEREPORTSTATUS_VHV \ + ((VL53LX_DeviceReportStatus) 2) +#define VL53LX_DEVICEREPORTSTATUS_PHASECAL \ + ((VL53LX_DeviceReportStatus) 3) +#define VL53LX_DEVICEREPORTSTATUS_REFERENCE_PHASE \ + ((VL53LX_DeviceReportStatus) 4) +#define VL53LX_DEVICEREPORTSTATUS_DSS1 \ + ((VL53LX_DeviceReportStatus) 5) +#define VL53LX_DEVICEREPORTSTATUS_DSS2 \ + ((VL53LX_DeviceReportStatus) 6) +#define VL53LX_DEVICEREPORTSTATUS_MM1 \ + ((VL53LX_DeviceReportStatus) 7) +#define VL53LX_DEVICEREPORTSTATUS_MM2 \ + ((VL53LX_DeviceReportStatus) 8) +#define VL53LX_DEVICEREPORTSTATUS_RANGE \ + ((VL53LX_DeviceReportStatus) 9) +#define VL53LX_DEVICEREPORTSTATUS_HISTOGRAM \ + ((VL53LX_DeviceReportStatus) 10) + +typedef uint8_t VL53LX_DeviceGpioMode; + +#define VL53LX_DEVICEGPIOMODE_OUTPUT_CONSTANT_ZERO \ + ((VL53LX_DeviceGpioMode) 0x00) +#define VL53LX_DEVICEGPIOMODE_OUTPUT_RANGE_AND_ERROR_INTERRUPTS \ + ((VL53LX_DeviceGpioMode) 0x01) +#define VL53LX_DEVICEGPIOMODE_OUTPUT_TIMIER_INTERRUPTS \ + ((VL53LX_DeviceGpioMode) 0x02) +#define VL53LX_DEVICEGPIOMODE_OUTPUT_RANGE_MODE_INTERRUPT_STATUS \ + ((VL53LX_DeviceGpioMode) 0x03) +#define VL53LX_DEVICEGPIOMODE_OUTPUT_SLOW_OSCILLATOR_CLOCK \ + ((VL53LX_DeviceGpioMode) 0x04) +#define VL53LX_DEVICEGPIOMODE_BIT_MASK \ + ((VL53LX_DeviceGpioMode) 0x0F) +#define VL53LX_DEVICEGPIOMODE_CLEAR_MASK \ + ((VL53LX_DeviceGpioMode) 0xF0) + +typedef uint8_t VL53LX_DeviceDssMode; + +#define VL53LX_DEVICEDSSMODE__DISABLED \ + ((VL53LX_DeviceDssMode) 0) +#define VL53LX_DEVICEDSSMODE__TARGET_RATE \ + ((VL53LX_DeviceDssMode) 1) +#define VL53LX_DEVICEDSSMODE__REQUESTED_EFFFECTIVE_SPADS \ + ((VL53LX_DeviceDssMode) 2) +#define VL53LX_DEVICEDSSMODE__BLOCK_SELECT \ + ((VL53LX_DeviceDssMode) 3) + +typedef uint8_t VL53LX_DeviceTestMode; + +#define VL53LX_DEVICETESTMODE_NONE \ + ((VL53LX_DeviceTestMode) 0x00) +#define VL53LX_DEVICETESTMODE_NVM_ZERO \ + ((VL53LX_DeviceTestMode) 0x01) +#define VL53LX_DEVICETESTMODE_NVM_COPY \ + ((VL53LX_DeviceTestMode) 0x02) +#define VL53LX_DEVICETESTMODE_PATCH \ + ((VL53LX_DeviceTestMode) 0x03) +#define VL53LX_DEVICETESTMODE_DCR \ + ((VL53LX_DeviceTestMode) 0x04) +#define VL53LX_DEVICETESTMODE_LCR_VCSEL_OFF \ + ((VL53LX_DeviceTestMode) 0x05) +#define VL53LX_DEVICETESTMODE_LCR_VCSEL_ON \ + ((VL53LX_DeviceTestMode) 0x06) +#define VL53LX_DEVICETESTMODE_SPOT_CENTRE_LOCATE \ + ((VL53LX_DeviceTestMode) 0x07) +#define VL53LX_DEVICETESTMODE_REF_SPAD_CHAR_WITH_PRE_VHV \ + ((VL53LX_DeviceTestMode) 0x08) +#define VL53LX_DEVICETESTMODE_REF_SPAD_CHAR_ONLY \ + ((VL53LX_DeviceTestMode) 0x09) + +#define VL53LX_SEQUENCE_VHV_EN 0x01 +#define VL53LX_SEQUENCE_PHASECAL_EN 0x02 +#define VL53LX_SEQUENCE_REFERENCE_PHASE_EN 0x04 +#define VL53LX_SEQUENCE_DSS1_EN 0x08 +#define VL53LX_SEQUENCE_DSS2_EN 0x10 +#define VL53LX_SEQUENCE_MM1_EN 0x20 +#define VL53LX_SEQUENCE_MM2_EN 0x40 +#define VL53LX_SEQUENCE_RANGE_EN 0x80 + +#define VL53LX_INTERRUPT_CONFIG_LEVEL_LOW 0x00 +#define VL53LX_INTERRUPT_CONFIG_LEVEL_HIGH 0x01 +#define VL53LX_INTERRUPT_CONFIG_OUT_OF_WINDOW 0x02 +#define VL53LX_INTERRUPT_CONFIG_IN_WINDOW 0x03 +#define VL53LX_INTERRUPT_CONFIG_NEW_SAMPLE_READY 0x20 + +#define VL53LX_CLEAR_RANGE_INT 0x01 +#define VL53LX_CLEAR_ERROR_INT 0x02 + +#define VL53LX_DEVICESCHEDULERMODE_PSEUDO_SOLO 0x00 +#define VL53LX_DEVICESCHEDULERMODE_STREAMING 0x01 +#define VL53LX_DEVICESCHEDULERMODE_HISTOGRAM 0x02 + +#define VL53LX_DEVICEREADOUTMODE_SINGLE_SD (0x00 << 2) +#define VL53LX_DEVICEREADOUTMODE_DUAL_SD (0x01 << 2) +#define VL53LX_DEVICEREADOUTMODE_SPLIT_READOUT (0x02 << 2) +#define VL53LX_DEVICEREADOUTMODE_SPLIT_MANUAL (0x03 << 2) + +#define VL53LX_TUNINGPARM_VERSION \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 0)) +#define VL53LX_TUNINGPARM_KEY_TABLE_VERSION \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 1)) +#define VL53LX_TUNINGPARM_LLD_VERSION \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 2)) +#define VL53LX_TUNINGPARM_HIST_ALGO_SELECT \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 3)) +#define VL53LX_TUNINGPARM_HIST_TARGET_ORDER \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 4)) +#define VL53LX_TUNINGPARM_HIST_FILTER_WOI_0 \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 5)) +#define VL53LX_TUNINGPARM_HIST_FILTER_WOI_1 \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 6)) +#define VL53LX_TUNINGPARM_HIST_AMB_EST_METHOD \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 7)) +#define VL53LX_TUNINGPARM_HIST_AMB_THRESH_SIGMA_0 \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 8)) +#define VL53LX_TUNINGPARM_HIST_AMB_THRESH_SIGMA_1 \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 9)) +#define VL53LX_TUNINGPARM_HIST_MIN_AMB_THRESH_EVENTS \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 10)) +#define VL53LX_TUNINGPARM_HIST_AMB_EVENTS_SCALER \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 11)) +#define VL53LX_TUNINGPARM_HIST_NOISE_THRESHOLD \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 12)) +#define VL53LX_TUNINGPARM_HIST_SIGNAL_TOTAL_EVENTS_LIMIT \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 13)) +#define VL53LX_TUNINGPARM_HIST_SIGMA_EST_REF_MM \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 14)) +#define VL53LX_TUNINGPARM_HIST_SIGMA_THRESH_MM \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 15)) +#define VL53LX_TUNINGPARM_HIST_GAIN_FACTOR \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 16)) +#define VL53LX_TUNINGPARM_CONSISTENCY_HIST_PHASE_TOLERANCE \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 17)) +#define VL53LX_TUNINGPARM_CONSISTENCY_HIST_MIN_MAX_TOLERANCE_MM \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 18)) +#define VL53LX_TUNINGPARM_CONSISTENCY_HIST_EVENT_SIGMA \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 19)) +#define VL53LX_TUNINGPARM_CONSISTENCY_HIST_EVENT_SIGMA_MIN_SPAD_LIMIT \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 20)) +#define VL53LX_TUNINGPARM_INITIAL_PHASE_RTN_HISTO_LONG_RANGE \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 21)) +#define VL53LX_TUNINGPARM_INITIAL_PHASE_RTN_HISTO_MED_RANGE \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 22)) +#define VL53LX_TUNINGPARM_INITIAL_PHASE_RTN_HISTO_SHORT_RANGE \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 23)) +#define VL53LX_TUNINGPARM_INITIAL_PHASE_REF_HISTO_LONG_RANGE \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 24)) +#define VL53LX_TUNINGPARM_INITIAL_PHASE_REF_HISTO_MED_RANGE \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 25)) +#define VL53LX_TUNINGPARM_INITIAL_PHASE_REF_HISTO_SHORT_RANGE \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 26)) +#define VL53LX_TUNINGPARM_XTALK_DETECT_MIN_VALID_RANGE_MM \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 27)) +#define VL53LX_TUNINGPARM_XTALK_DETECT_MAX_VALID_RANGE_MM \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 28)) +#define VL53LX_TUNINGPARM_XTALK_DETECT_MAX_SIGMA_MM \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 29)) +#define VL53LX_TUNINGPARM_XTALK_DETECT_MIN_MAX_TOLERANCE \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 30)) +#define VL53LX_TUNINGPARM_XTALK_DETECT_MAX_VALID_RATE_KCPS \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 31)) +#define VL53LX_TUNINGPARM_XTALK_DETECT_EVENT_SIGMA \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 32)) +#define VL53LX_TUNINGPARM_HIST_XTALK_MARGIN_KCPS \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 33)) +#define VL53LX_TUNINGPARM_CONSISTENCY_LITE_PHASE_TOLERANCE \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 34)) +#define VL53LX_TUNINGPARM_PHASECAL_TARGET \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 35)) +#define VL53LX_TUNINGPARM_LITE_CAL_REPEAT_RATE \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 36)) +#define VL53LX_TUNINGPARM_LITE_RANGING_GAIN_FACTOR \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 37)) +#define VL53LX_TUNINGPARM_LITE_MIN_CLIP_MM \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 38)) +#define VL53LX_TUNINGPARM_LITE_LONG_SIGMA_THRESH_MM \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 39)) +#define VL53LX_TUNINGPARM_LITE_MED_SIGMA_THRESH_MM \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 40)) +#define VL53LX_TUNINGPARM_LITE_SHORT_SIGMA_THRESH_MM \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 41)) +#define VL53LX_TUNINGPARM_LITE_LONG_MIN_COUNT_RATE_RTN_MCPS \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 42)) +#define VL53LX_TUNINGPARM_LITE_MED_MIN_COUNT_RATE_RTN_MCPS \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 43)) +#define VL53LX_TUNINGPARM_LITE_SHORT_MIN_COUNT_RATE_RTN_MCPS \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 44)) +#define VL53LX_TUNINGPARM_LITE_SIGMA_EST_PULSE_WIDTH \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 45)) +#define VL53LX_TUNINGPARM_LITE_SIGMA_EST_AMB_WIDTH_NS \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 46)) +#define VL53LX_TUNINGPARM_LITE_SIGMA_REF_MM \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 47)) +#define VL53LX_TUNINGPARM_LITE_RIT_MULT \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 48)) +#define VL53LX_TUNINGPARM_LITE_SEED_CONFIG \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 49)) +#define VL53LX_TUNINGPARM_LITE_QUANTIFIER \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 50)) +#define VL53LX_TUNINGPARM_LITE_FIRST_ORDER_SELECT \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 51)) +#define VL53LX_TUNINGPARM_LITE_XTALK_MARGIN_KCPS \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 52)) +#define VL53LX_TUNINGPARM_INITIAL_PHASE_RTN_LITE_LONG_RANGE \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 53)) +#define VL53LX_TUNINGPARM_INITIAL_PHASE_RTN_LITE_MED_RANGE \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 54)) +#define VL53LX_TUNINGPARM_INITIAL_PHASE_RTN_LITE_SHORT_RANGE \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 55)) +#define VL53LX_TUNINGPARM_INITIAL_PHASE_REF_LITE_LONG_RANGE \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 56)) +#define VL53LX_TUNINGPARM_INITIAL_PHASE_REF_LITE_MED_RANGE \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 57)) +#define VL53LX_TUNINGPARM_INITIAL_PHASE_REF_LITE_SHORT_RANGE \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 58)) +#define VL53LX_TUNINGPARM_TIMED_SEED_CONFIG \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 59)) +#define VL53LX_TUNINGPARM_DMAX_CFG_SIGNAL_THRESH_SIGMA \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 60)) +#define VL53LX_TUNINGPARM_DMAX_CFG_REFLECTANCE_ARRAY_0 \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 61)) +#define VL53LX_TUNINGPARM_DMAX_CFG_REFLECTANCE_ARRAY_1 \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 62)) +#define VL53LX_TUNINGPARM_DMAX_CFG_REFLECTANCE_ARRAY_2 \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 63)) +#define VL53LX_TUNINGPARM_DMAX_CFG_REFLECTANCE_ARRAY_3 \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 64)) +#define VL53LX_TUNINGPARM_DMAX_CFG_REFLECTANCE_ARRAY_4 \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 65)) +#define VL53LX_TUNINGPARM_VHV_LOOPBOUND \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 66)) +#define VL53LX_TUNINGPARM_REFSPADCHAR_DEVICE_TEST_MODE \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 67)) +#define VL53LX_TUNINGPARM_REFSPADCHAR_VCSEL_PERIOD \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 68)) +#define VL53LX_TUNINGPARM_REFSPADCHAR_PHASECAL_TIMEOUT_US \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 69)) +#define VL53LX_TUNINGPARM_REFSPADCHAR_TARGET_COUNT_RATE_MCPS \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 70)) +#define VL53LX_TUNINGPARM_REFSPADCHAR_MIN_COUNTRATE_LIMIT_MCPS \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 71)) +#define VL53LX_TUNINGPARM_REFSPADCHAR_MAX_COUNTRATE_LIMIT_MCPS \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 72)) +#define VL53LX_TUNINGPARM_XTALK_EXTRACT_NUM_OF_SAMPLES \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 73)) +#define VL53LX_TUNINGPARM_XTALK_EXTRACT_MIN_FILTER_THRESH_MM \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 74)) +#define VL53LX_TUNINGPARM_XTALK_EXTRACT_MAX_FILTER_THRESH_MM \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 75)) +#define VL53LX_TUNINGPARM_XTALK_EXTRACT_DSS_RATE_MCPS \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 76)) +#define VL53LX_TUNINGPARM_XTALK_EXTRACT_PHASECAL_TIMEOUT_US \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 77)) +#define VL53LX_TUNINGPARM_XTALK_EXTRACT_MAX_VALID_RATE_KCPS \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 78)) +#define VL53LX_TUNINGPARM_XTALK_EXTRACT_SIGMA_THRESHOLD_MM \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 79)) +#define VL53LX_TUNINGPARM_XTALK_EXTRACT_DSS_TIMEOUT_US \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 80)) +#define VL53LX_TUNINGPARM_XTALK_EXTRACT_BIN_TIMEOUT_US \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 81)) +#define VL53LX_TUNINGPARM_OFFSET_CAL_DSS_RATE_MCPS \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 82)) +#define VL53LX_TUNINGPARM_OFFSET_CAL_PHASECAL_TIMEOUT_US \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 83)) +#define VL53LX_TUNINGPARM_OFFSET_CAL_MM_TIMEOUT_US \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 84)) +#define VL53LX_TUNINGPARM_OFFSET_CAL_RANGE_TIMEOUT_US \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 85)) +#define VL53LX_TUNINGPARM_OFFSET_CAL_PRE_SAMPLES \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 86)) +#define VL53LX_TUNINGPARM_OFFSET_CAL_MM1_SAMPLES \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 87)) +#define VL53LX_TUNINGPARM_OFFSET_CAL_MM2_SAMPLES \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 88)) +#define VL53LX_TUNINGPARM_ZONE_CAL_DSS_RATE_MCPS \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 89)) +#define VL53LX_TUNINGPARM_ZONE_CAL_PHASECAL_TIMEOUT_US \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 90)) +#define VL53LX_TUNINGPARM_ZONE_CAL_DSS_TIMEOUT_US \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 91)) +#define VL53LX_TUNINGPARM_ZONE_CAL_PHASECAL_NUM_SAMPLES \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 92)) +#define VL53LX_TUNINGPARM_ZONE_CAL_RANGE_TIMEOUT_US \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 93)) +#define VL53LX_TUNINGPARM_ZONE_CAL_ZONE_NUM_SAMPLES \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 94)) +#define VL53LX_TUNINGPARM_SPADMAP_VCSEL_PERIOD \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 95)) +#define VL53LX_TUNINGPARM_SPADMAP_VCSEL_START \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 96)) +#define VL53LX_TUNINGPARM_SPADMAP_RATE_LIMIT_MCPS \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 97)) +#define VL53LX_TUNINGPARM_LITE_DSS_CONFIG_TARGET_TOTAL_RATE_MCPS \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 98)) +#define VL53LX_TUNINGPARM_RANGING_DSS_CONFIG_TARGET_TOTAL_RATE_MCPS \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 99)) +#define VL53LX_TUNINGPARM_MZ_DSS_CONFIG_TARGET_TOTAL_RATE_MCPS \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 100)) +#define VL53LX_TUNINGPARM_TIMED_DSS_CONFIG_TARGET_TOTAL_RATE_MCPS \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 101)) +#define VL53LX_TUNINGPARM_LITE_PHASECAL_CONFIG_TIMEOUT_US \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 102)) +#define VL53LX_TUNINGPARM_RANGING_LONG_PHASECAL_CONFIG_TIMEOUT_US \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 103)) +#define VL53LX_TUNINGPARM_RANGING_MED_PHASECAL_CONFIG_TIMEOUT_US \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 104)) +#define VL53LX_TUNINGPARM_RANGING_SHORT_PHASECAL_CONFIG_TIMEOUT_US \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 105)) +#define VL53LX_TUNINGPARM_MZ_LONG_PHASECAL_CONFIG_TIMEOUT_US \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 106)) +#define VL53LX_TUNINGPARM_MZ_MED_PHASECAL_CONFIG_TIMEOUT_US \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 107)) +#define VL53LX_TUNINGPARM_MZ_SHORT_PHASECAL_CONFIG_TIMEOUT_US \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 108)) +#define VL53LX_TUNINGPARM_TIMED_PHASECAL_CONFIG_TIMEOUT_US \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 109)) +#define VL53LX_TUNINGPARM_LITE_MM_CONFIG_TIMEOUT_US \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 110)) +#define VL53LX_TUNINGPARM_RANGING_MM_CONFIG_TIMEOUT_US \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 111)) +#define VL53LX_TUNINGPARM_MZ_MM_CONFIG_TIMEOUT_US \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 112)) +#define VL53LX_TUNINGPARM_TIMED_MM_CONFIG_TIMEOUT_US \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 113)) +#define VL53LX_TUNINGPARM_LITE_RANGE_CONFIG_TIMEOUT_US \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 114)) +#define VL53LX_TUNINGPARM_RANGING_RANGE_CONFIG_TIMEOUT_US \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 115)) +#define VL53LX_TUNINGPARM_MZ_RANGE_CONFIG_TIMEOUT_US \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 116)) +#define VL53LX_TUNINGPARM_TIMED_RANGE_CONFIG_TIMEOUT_US \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 117)) +#define VL53LX_TUNINGPARM_DYNXTALK_SMUDGE_MARGIN \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 118)) +#define VL53LX_TUNINGPARM_DYNXTALK_NOISE_MARGIN \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 119)) +#define VL53LX_TUNINGPARM_DYNXTALK_XTALK_OFFSET_LIMIT \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 120)) +#define VL53LX_TUNINGPARM_DYNXTALK_XTALK_OFFSET_LIMIT_HI \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 121)) +#define VL53LX_TUNINGPARM_DYNXTALK_SAMPLE_LIMIT \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 122)) +#define VL53LX_TUNINGPARM_DYNXTALK_SINGLE_XTALK_DELTA \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 123)) +#define VL53LX_TUNINGPARM_DYNXTALK_AVERAGED_XTALK_DELTA \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 124)) +#define VL53LX_TUNINGPARM_DYNXTALK_CLIP_LIMIT \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 125)) +#define VL53LX_TUNINGPARM_DYNXTALK_SCALER_CALC_METHOD \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 126)) +#define VL53LX_TUNINGPARM_DYNXTALK_XGRADIENT_SCALER \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 127)) +#define VL53LX_TUNINGPARM_DYNXTALK_YGRADIENT_SCALER \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 128)) +#define VL53LX_TUNINGPARM_DYNXTALK_USER_SCALER_SET \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 129)) +#define VL53LX_TUNINGPARM_DYNXTALK_SMUDGE_COR_SINGLE_APPLY \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 130)) +#define VL53LX_TUNINGPARM_DYNXTALK_XTALK_AMB_THRESHOLD \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 131)) +#define VL53LX_TUNINGPARM_DYNXTALK_NODETECT_AMB_THRESHOLD_KCPS \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 132)) +#define VL53LX_TUNINGPARM_DYNXTALK_NODETECT_SAMPLE_LIMIT \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 133)) +#define VL53LX_TUNINGPARM_DYNXTALK_NODETECT_XTALK_OFFSET_KCPS \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 134)) +#define VL53LX_TUNINGPARM_DYNXTALK_NODETECT_MIN_RANGE_MM \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 135)) +#define VL53LX_TUNINGPARM_LOWPOWERAUTO_VHV_LOOP_BOUND \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 136)) +#define VL53LX_TUNINGPARM_LOWPOWERAUTO_MM_CONFIG_TIMEOUT_US \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 137)) +#define VL53LX_TUNINGPARM_LOWPOWERAUTO_RANGE_CONFIG_TIMEOUT_US \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 138)) +#define VL53LX_TUNINGPARM_VERY_SHORT_DSS_RATE_MCPS \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 139)) +#define VL53LX_TUNINGPARM_PHASECAL_PATCH_POWER \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 140)) +#define VL53LX_TUNINGPARM_HIST_MERGE \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 141)) +#define VL53LX_TUNINGPARM_RESET_MERGE_THRESHOLD \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 142)) +#define VL53LX_TUNINGPARM_HIST_MERGE_MAX_SIZE \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 143)) +#define VL53LX_TUNINGPARM_DYNXTALK_MAX_SMUDGE_FACTOR \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 144)) +#define VL53LX_TUNINGPARM_UWR_ENABLE \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 145)) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_1_MIN \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 146)) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_1_MAX \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 147)) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_2_MIN \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 148)) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_2_MAX \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 149)) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_3_MIN \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 150)) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_3_MAX \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 151)) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_4_MIN \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 152)) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_4_MAX \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 153)) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_5_MIN \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 154)) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_5_MAX \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 155)) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_1_RANGEA \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 156)) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_1_RANGEB \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 157)) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_2_RANGEA \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 158)) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_2_RANGEB \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 159)) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_3_RANGEA \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 160)) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_3_RANGEB \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 161)) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_4_RANGEA \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 162)) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_4_RANGEB \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 163)) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_5_RANGEA \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 164)) +#define VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_5_RANGEB \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 165)) +#define VL53LX_TUNINGPARM_UWR_LONG_ZONE_1_MIN \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 166)) +#define VL53LX_TUNINGPARM_UWR_LONG_ZONE_1_MAX \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 167)) +#define VL53LX_TUNINGPARM_UWR_LONG_ZONE_2_MIN \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 168)) +#define VL53LX_TUNINGPARM_UWR_LONG_ZONE_2_MAX \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 169)) +#define VL53LX_TUNINGPARM_UWR_LONG_ZONE_3_MIN \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 170)) +#define VL53LX_TUNINGPARM_UWR_LONG_ZONE_3_MAX \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 171)) +#define VL53LX_TUNINGPARM_UWR_LONG_ZONE_4_MIN \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 172)) +#define VL53LX_TUNINGPARM_UWR_LONG_ZONE_4_MAX \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 173)) +#define VL53LX_TUNINGPARM_UWR_LONG_ZONE_5_MIN \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 174)) +#define VL53LX_TUNINGPARM_UWR_LONG_ZONE_5_MAX \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 175)) +#define VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_1_RANGEA \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 176)) +#define VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_1_RANGEB \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 177)) +#define VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_2_RANGEA \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 178)) +#define VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_2_RANGEB \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 179)) +#define VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_3_RANGEA \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 180)) +#define VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_3_RANGEB \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 181)) +#define VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_4_RANGEA \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 182)) +#define VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_4_RANGEB \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 183)) +#define VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_5_RANGEA \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 184)) +#define VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_5_RANGEB \ +((VL53LX_TuningParms) (VL53LX_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS + 185)) + +enum VL53LX_Tuning_t { + VL53LX_TUNING_VERSION = 0, + VL53LX_TUNING_PROXY_MIN, + VL53LX_TUNING_SINGLE_TARGET_XTALK_TARGET_DISTANCE_MM, + VL53LX_TUNING_SINGLE_TARGET_XTALK_SAMPLE_NUMBER, + VL53LX_TUNING_MIN_AMBIENT_DMAX_VALID, + VL53LX_TUNING_MAX_SIMPLE_OFFSET_CALIBRATION_SAMPLE_NUMBER, + VL53LX_TUNING_XTALK_FULL_ROI_TARGET_DISTANCE_MM, + VL53LX_TUNING_SIMPLE_OFFSET_CALIBRATION_REPEAT, + VL53LX_TUNING_XTALK_FULL_ROI_BIN_SUM_MARGIN, + VL53LX_TUNING_XTALK_FULL_ROI_DEFAULT_OFFSET, + VL53LX_TUNING_ZERO_DISTANCE_OFFSET_NON_LINEAR_FACTOR, + VL53LX_TUNING_MAX_TUNABLE_KEY +}; + +#define TUNING_VERSION 0x0007 +#define TUNING_PROXY_MIN -30 +#define TUNING_SINGLE_TARGET_XTALK_TARGET_DISTANCE_MM 600 +#define TUNING_SINGLE_TARGET_XTALK_SAMPLE_NUMBER 50 +#define TUNING_MIN_AMBIENT_DMAX_VALID 8 +#ifdef SMALL_FOOTPRINT +#define TUNING_MAX_SIMPLE_OFFSET_CALIBRATION_SAMPLE_NUMBER 50 +#else +#define TUNING_MAX_SIMPLE_OFFSET_CALIBRATION_SAMPLE_NUMBER 10 +#endif +#define TUNING_XTALK_FULL_ROI_TARGET_DISTANCE_MM 600 +#ifdef SMALL_FOOTPRINT +#define TUNING_SIMPLE_OFFSET_CALIBRATION_REPEAT 1 +#else +#define TUNING_SIMPLE_OFFSET_CALIBRATION_REPEAT 3 +#endif +#define TUNING_ZERO_DISTANCE_OFFSET_NON_LINEAR_FACTOR_DEFAULT 9 +#define TUNING_XTALK_FULL_ROI_BIN_SUM_MARGIN 24 +#define TUNING_XTALK_FULL_ROI_DEFAULT_OFFSET 50 + +#ifdef STMVL53LX_DEBUG_I2C +#define i2c_debug(fmt, ...) printk(fmt, ##__VA_ARGS__) +#else +#define i2c_debug(fmt, ...) ((void)0) +#endif + +#if STMVL53LX_LOG_POLL_TIMING +#define poll_timing_log(ptv) printk("poll in %d us\n", tv_elapsed_us(ptv)) +#else +#define poll_timing_log(...) ((void)0) +#endif + +#define IMPLEMENT_PARAMETER_INTEGER(sysfs_name, info_name)\ +static ssize_t stmvl53lx_show_##sysfs_name(struct device *dev, \ + struct device_attribute *attr, char *buf) \ +{ \ + struct stmvl53lx_data *data = dev_get_drvdata(dev); \ + int param; \ +\ + mutex_lock(&data->work_mutex); \ + param = data->sysfs_name; \ + mutex_unlock(&data->work_mutex);; \ +\ + return scnprintf(buf, PAGE_SIZE, "%d\n", param); \ +} \ +\ +static ssize_t stmvl53lx_store_##sysfs_name(struct device *dev, \ + struct device_attribute *attr, \ + const char *buf, size_t count) \ +{ \ + struct stmvl53lx_data *data = dev_get_drvdata(dev); \ + int rc = 0; \ + int param; \ +\ + mutex_lock(&data->work_mutex); \ +\ + if (kstrtoint(buf, 0, ¶m)) { \ + vl53lx_errmsg("invalid syntax in %s", buf); \ + rc = -EINVAL; \ + } else \ + rc = stmvl53lx_set_##sysfs_name(data, param); \ +\ + mutex_unlock(&data->work_mutex); \ +\ + return rc ? rc : count; \ +} \ +\ +static int ctrl_param_##sysfs_name(struct stmvl53lx_data *data, \ + struct stmvl53lx_parameter *param) \ +{ \ + int rc = 0; \ +\ + if (param->is_read) { \ + param->value = data->sysfs_name; \ + param->status = 0; \ + vl53lx_dbgmsg("get " info_name " %d", param->value); \ + rc = 0; \ + } else { \ + rc = stmvl53lx_set_##sysfs_name(data, param->value); \ + vl53lx_dbgmsg("rc %d req %d now %d", rc, \ + param->value, data->sysfs_name); \ + } \ +\ + return rc; \ +} + +typedef struct { + uint32_t VL53LX_p_016; + uint32_t VL53LX_p_017; + uint16_t VL53LX_p_011; + uint8_t range_status; +} VL53LX_object_data_t; + +typedef struct { + VL53LX_DeviceState cfg_device_state; + VL53LX_DeviceState rd_device_state; + uint8_t zone_id; + uint8_t stream_count; + uint8_t max_objects; + uint8_t active_objects; + VL53LX_object_data_t VL53LX_p_003[VL53LX_MAX_RANGE_RESULTS]; + VL53LX_object_data_t xmonitor; +} VL53LX_zone_objects_t; + +typedef struct { + uint32_t ll_revision; + uint8_t ll_major; + uint8_t ll_minor; + uint8_t ll_build; +} VL53LX_ll_version_t; + +typedef struct { + VL53LX_DeviceState cfg_device_state; + uint8_t cfg_stream_count; + uint8_t cfg_internal_stream_count; + uint8_t cfg_internal_stream_count_val; + uint8_t cfg_gph_id; + uint8_t cfg_timing_status; + uint8_t cfg_zone_id; + VL53LX_DeviceState rd_device_state; + uint8_t rd_stream_count; + uint8_t rd_internal_stream_count; + uint8_t rd_internal_stream_count_val; + uint8_t rd_gph_id; + uint8_t rd_timing_status; + uint8_t rd_zone_id; +} VL53LX_ll_driver_state_t; + +typedef struct { + VL53LX_GPIO_Interrupt_Mode intr_mode_distance; + VL53LX_GPIO_Interrupt_Mode intr_mode_rate; + uint8_t intr_new_measure_ready; + uint8_t intr_no_target; + uint8_t intr_combined_mode; + uint16_t threshold_distance_high; + uint16_t threshold_distance_low; + uint16_t threshold_rate_high; + uint16_t threshold_rate_low; +} VL53LX_GPIO_interrupt_config_t; + +typedef struct { + uint16_t tp_tuning_parm_version; + uint16_t tp_tuning_parm_key_table_version; + uint16_t tp_tuning_parm_lld_version; + uint8_t tp_init_phase_rtn_lite_long; + uint8_t tp_init_phase_rtn_lite_med; + uint8_t tp_init_phase_rtn_lite_short; + uint8_t tp_init_phase_ref_lite_long; + uint8_t tp_init_phase_ref_lite_med; + uint8_t tp_init_phase_ref_lite_short; + uint8_t tp_init_phase_rtn_hist_long; + uint8_t tp_init_phase_rtn_hist_med; + uint8_t tp_init_phase_rtn_hist_short; + uint8_t tp_init_phase_ref_hist_long; + uint8_t tp_init_phase_ref_hist_med; + uint8_t tp_init_phase_ref_hist_short; + uint8_t tp_consistency_lite_phase_tolerance; + uint8_t tp_phasecal_target; + uint16_t tp_cal_repeat_rate; + uint8_t tp_lite_min_clip; + uint16_t tp_lite_long_sigma_thresh_mm; + uint16_t tp_lite_med_sigma_thresh_mm; + uint16_t tp_lite_short_sigma_thresh_mm; + uint16_t tp_lite_long_min_count_rate_rtn_mcps; + uint16_t tp_lite_med_min_count_rate_rtn_mcps; + uint16_t tp_lite_short_min_count_rate_rtn_mcps; + uint8_t tp_lite_sigma_est_pulse_width_ns; + uint8_t tp_lite_sigma_est_amb_width_ns; + uint8_t tp_lite_sigma_ref_mm; + uint8_t tp_lite_seed_cfg; + uint8_t tp_timed_seed_cfg; + uint8_t tp_lite_quantifier; + uint8_t tp_lite_first_order_select; + uint16_t tp_dss_target_lite_mcps; + uint16_t tp_dss_target_histo_mcps; + uint16_t tp_dss_target_histo_mz_mcps; + uint16_t tp_dss_target_timed_mcps; + uint16_t tp_dss_target_very_short_mcps; + uint32_t tp_phasecal_timeout_lite_us; + uint32_t tp_phasecal_timeout_hist_long_us; + uint32_t tp_phasecal_timeout_hist_med_us; + uint32_t tp_phasecal_timeout_hist_short_us; + uint32_t tp_phasecal_timeout_mz_long_us; + uint32_t tp_phasecal_timeout_mz_med_us; + uint32_t tp_phasecal_timeout_mz_short_us; + uint32_t tp_phasecal_timeout_timed_us; + uint32_t tp_mm_timeout_lite_us; + uint32_t tp_mm_timeout_histo_us; + uint32_t tp_mm_timeout_mz_us; + uint32_t tp_mm_timeout_timed_us; + uint32_t tp_mm_timeout_lpa_us; + uint32_t tp_range_timeout_lite_us; + uint32_t tp_range_timeout_histo_us; + uint32_t tp_range_timeout_mz_us; + uint32_t tp_range_timeout_timed_us; + uint32_t tp_range_timeout_lpa_us; + uint32_t tp_phasecal_patch_power; + uint8_t tp_hist_merge; + uint32_t tp_reset_merge_threshold; + uint8_t tp_hist_merge_max_size; + uint8_t tp_uwr_enable; + int16_t tp_uwr_med_z_1_min; + int16_t tp_uwr_med_z_1_max; + int16_t tp_uwr_med_z_2_min; + int16_t tp_uwr_med_z_2_max; + int16_t tp_uwr_med_z_3_min; + int16_t tp_uwr_med_z_3_max; + int16_t tp_uwr_med_z_4_min; + int16_t tp_uwr_med_z_4_max; + int16_t tp_uwr_med_z_5_min; + int16_t tp_uwr_med_z_5_max; + int16_t tp_uwr_med_corr_z_1_rangea; + int16_t tp_uwr_med_corr_z_1_rangeb; + int16_t tp_uwr_med_corr_z_2_rangea; + int16_t tp_uwr_med_corr_z_2_rangeb; + int16_t tp_uwr_med_corr_z_3_rangea; + int16_t tp_uwr_med_corr_z_3_rangeb; + int16_t tp_uwr_med_corr_z_4_rangea; + int16_t tp_uwr_med_corr_z_4_rangeb; + int16_t tp_uwr_med_corr_z_5_rangea; + int16_t tp_uwr_med_corr_z_5_rangeb; + int16_t tp_uwr_lng_z_1_min; + int16_t tp_uwr_lng_z_1_max; + int16_t tp_uwr_lng_z_2_min; + int16_t tp_uwr_lng_z_2_max; + int16_t tp_uwr_lng_z_3_min; + int16_t tp_uwr_lng_z_3_max; + int16_t tp_uwr_lng_z_4_min; + int16_t tp_uwr_lng_z_4_max; + int16_t tp_uwr_lng_z_5_min; + int16_t tp_uwr_lng_z_5_max; + int16_t tp_uwr_lng_corr_z_1_rangea; + int16_t tp_uwr_lng_corr_z_1_rangeb; + int16_t tp_uwr_lng_corr_z_2_rangea; + int16_t tp_uwr_lng_corr_z_2_rangeb; + int16_t tp_uwr_lng_corr_z_3_rangea; + int16_t tp_uwr_lng_corr_z_3_rangeb; + int16_t tp_uwr_lng_corr_z_4_rangea; + int16_t tp_uwr_lng_corr_z_4_rangeb; + int16_t tp_uwr_lng_corr_z_5_rangea; + int16_t tp_uwr_lng_corr_z_5_rangeb; +} VL53LX_tuning_parm_storage_t; + +typedef struct { + uint8_t device_test_mode; + uint8_t VL53LX_p_005; + uint32_t timeout_us; + uint16_t target_count_rate_mcps; + uint16_t min_count_rate_limit_mcps; + uint16_t max_count_rate_limit_mcps; +} VL53LX_refspadchar_config_t; + +typedef struct { + VL53LX_DeviceSscArray array_select; + uint8_t VL53LX_p_005; + uint8_t vcsel_start; + uint8_t vcsel_width; + uint32_t timeout_us; + uint16_t rate_limit_mcps; +} VL53LX_ssc_config_t; + +typedef struct { + VL53LX_HistAlgoSelect hist_algo_select; + VL53LX_HistTargetOrder hist_target_order; + uint8_t filter_woi0; + uint8_t filter_woi1; + VL53LX_HistAmbEstMethod hist_amb_est_method; + uint8_t ambient_thresh_sigma0; + uint8_t ambient_thresh_sigma1; + uint16_t ambient_thresh_events_scaler; + int32_t min_ambient_thresh_events; + uint16_t noise_threshold; + int32_t signal_total_events_limit; + uint8_t sigma_estimator__sigma_ref_mm; + uint16_t sigma_thresh; + int16_t range_offset_mm; + uint16_t gain_factor; + uint8_t valid_phase_low; + uint8_t valid_phase_high; + uint8_t algo__consistency_check__phase_tolerance; + uint8_t algo__consistency_check__event_sigma; + uint16_t algo__consistency_check__event_min_spad_count; + uint16_t algo__consistency_check__min_max_tolerance; + uint8_t algo__crosstalk_compensation_enable; + uint32_t algo__crosstalk_compensation_plane_offset_kcps; + int16_t algo__crosstalk_compensation_x_plane_gradient_kcps; + int16_t algo__crosstalk_compensation_y_plane_gradient_kcps; + int16_t algo__crosstalk_detect_min_valid_range_mm; + int16_t algo__crosstalk_detect_max_valid_range_mm; + uint16_t algo__crosstalk_detect_max_valid_rate_kcps; + uint16_t algo__crosstalk_detect_max_sigma_mm; + uint8_t algo__crosstalk_detect_event_sigma; + uint16_t algo__crosstalk_detect_min_max_tolerance; +} VL53LX_hist_post_process_config_t; + +typedef struct { + uint8_t signal_thresh_sigma; + uint8_t ambient_thresh_sigma; + int32_t min_ambient_thresh_events; + int32_t signal_total_events_limit; + uint16_t target_reflectance_for_dmax_calc[VL53LX_MAX_AMBIENT_DMAX_VALUES]; + uint16_t max_effective_spads; + uint16_t dss_config__target_total_rate_mcps; + uint8_t dss_config__aperture_attenuation; +} VL53LX_hist_gen3_dmax_config_t; + +typedef struct { + uint16_t dss_config__target_total_rate_mcps; + uint32_t phasecal_config_timeout_us; + uint32_t mm_config_timeout_us; + uint32_t range_config_timeout_us; + uint8_t num_of_samples; + int16_t algo__crosstalk_extract_min_valid_range_mm; + int16_t algo__crosstalk_extract_max_valid_range_mm; + uint16_t algo__crosstalk_extract_max_valid_rate_kcps; + uint16_t algo__crosstalk_extract_max_sigma_mm; +} VL53LX_xtalkextract_config_t; + +typedef struct { + uint32_t algo__crosstalk_compensation_plane_offset_kcps; + int16_t algo__crosstalk_compensation_x_plane_gradient_kcps; + int16_t algo__crosstalk_compensation_y_plane_gradient_kcps; + uint32_t nvm_default__crosstalk_compensation_plane_offset_kcps; + int16_t nvm_default__crosstalk_compensation_x_plane_gradient_kcps; + int16_t nvm_default__crosstalk_compensation_y_plane_gradient_kcps; + uint8_t global_crosstalk_compensation_enable; + int16_t histogram_mode_crosstalk_margin_kcps; + int16_t lite_mode_crosstalk_margin_kcps; + uint8_t crosstalk_range_ignore_threshold_mult; + uint16_t crosstalk_range_ignore_threshold_rate_mcps; + int16_t algo__crosstalk_detect_min_valid_range_mm; + int16_t algo__crosstalk_detect_max_valid_range_mm; + uint16_t algo__crosstalk_detect_max_valid_rate_kcps; + uint16_t algo__crosstalk_detect_max_sigma_mm; +} VL53LX_xtalk_config_t; + +typedef struct { + uint16_t dss_config__target_total_rate_mcps; + uint32_t phasecal_config_timeout_us; + uint32_t range_config_timeout_us; + uint32_t mm_config_timeout_us; + uint8_t pre_num_of_samples; + uint8_t mm1_num_of_samples; + uint8_t mm2_num_of_samples; +} VL53LX_offsetcal_config_t; + +typedef struct { + uint16_t dss_config__target_total_rate_mcps; + uint32_t phasecal_config_timeout_us; + uint32_t mm_config_timeout_us; + uint32_t range_config_timeout_us; + uint16_t phasecal_num_of_samples; + uint16_t zone_num_of_samples; +} VL53LX_zonecal_config_t; + +typedef struct { + uint8_t global_config__spad_enables_ref_0; + uint8_t global_config__spad_enables_ref_1; + uint8_t global_config__spad_enables_ref_2; + uint8_t global_config__spad_enables_ref_3; + uint8_t global_config__spad_enables_ref_4; + uint8_t global_config__spad_enables_ref_5; + uint8_t global_config__ref_en_start_select; + uint8_t ref_spad_man__num_requested_ref_spads; + uint8_t ref_spad_man__ref_location; + uint16_t algo__crosstalk_compensation_plane_offset_kcps; + int16_t algo__crosstalk_compensation_x_plane_gradient_kcps; + int16_t algo__crosstalk_compensation_y_plane_gradient_kcps; + uint16_t ref_spad_char__total_rate_target_mcps; + int16_t algo__part_to_part_range_offset_mm; + int16_t mm_config__inner_offset_mm; + int16_t mm_config__outer_offset_mm; +} VL53LX_customer_nvm_managed_t; + +typedef struct { + int16_t cal_distance_mm; + uint16_t cal_reflectance_pc; + uint16_t max_samples; + uint16_t width; + uint16_t height; + uint16_t peak_rate_mcps[VL53LX_NVM_PEAK_RATE_MAP_SAMPLES]; +} VL53LX_cal_peak_rate_map_t; + +typedef struct { + uint16_t result__mm_inner_actual_effective_spads; + uint16_t result__mm_outer_actual_effective_spads; + uint16_t result__mm_inner_peak_signal_count_rtn_mcps; + uint16_t result__mm_outer_peak_signal_count_rtn_mcps; +} VL53LX_additional_offset_cal_data_t; + +typedef struct { + uint16_t ref__actual_effective_spads; + uint16_t ref__peak_signal_count_rate_mcps; + uint16_t ref__distance_mm; + uint16_t ref_reflectance_pc; + uint16_t coverglass_transmission; +} VL53LX_dmax_calibration_data_t; + +typedef struct { + uint16_t standard_ranging_gain_factor; + uint16_t histogram_ranging_gain_factor; +} VL53LX_gain_calibration_data_t; + +typedef struct { + uint8_t x_centre; + uint8_t y_centre; + uint8_t width; + uint8_t height; +} VL53LX_user_zone_t; + +typedef struct { + uint8_t x_centre; + uint8_t y_centre; +} VL53LX_optical_centre_t; + +typedef struct { + uint8_t histogram_config__spad_array_selection; + uint8_t histogram_config__low_amb_even_bin_0_1; + uint8_t histogram_config__low_amb_even_bin_2_3; + uint8_t histogram_config__low_amb_even_bin_4_5; + uint8_t histogram_config__low_amb_odd_bin_0_1; + uint8_t histogram_config__low_amb_odd_bin_2_3; + uint8_t histogram_config__low_amb_odd_bin_4_5; + uint8_t histogram_config__mid_amb_even_bin_0_1; + uint8_t histogram_config__mid_amb_even_bin_2_3; + uint8_t histogram_config__mid_amb_even_bin_4_5; + uint8_t histogram_config__mid_amb_odd_bin_0_1; + uint8_t histogram_config__mid_amb_odd_bin_2; + uint8_t histogram_config__mid_amb_odd_bin_3_4; + uint8_t histogram_config__mid_amb_odd_bin_5; + uint8_t histogram_config__user_bin_offset; + uint8_t histogram_config__high_amb_even_bin_0_1; + uint8_t histogram_config__high_amb_even_bin_2_3; + uint8_t histogram_config__high_amb_even_bin_4_5; + uint8_t histogram_config__high_amb_odd_bin_0_1; + uint8_t histogram_config__high_amb_odd_bin_2_3; + uint8_t histogram_config__high_amb_odd_bin_4_5; + uint16_t histogram_config__amb_thresh_low; + uint16_t histogram_config__amb_thresh_high; +} VL53LX_histogram_config_t; + +typedef struct { + uint8_t max_zones; + uint8_t active_zones; + VL53LX_histogram_config_t multizone_hist_cfg; + VL53LX_user_zone_t user_zones[VL53LX_MAX_USER_ZONES]; + uint8_t bin_config[VL53LX_MAX_USER_ZONES]; +} VL53LX_zone_config_t; + +typedef struct { + uint8_t i2c_slave__device_address; + uint8_t ana_config__vhv_ref_sel_vddpix; + uint8_t ana_config__vhv_ref_sel_vquench; + uint8_t ana_config__reg_avdd1v2_sel; + uint8_t ana_config__fast_osc__trim; + uint16_t osc_measured__fast_osc__frequency; + uint8_t vhv_config__timeout_macrop_loop_bound; + uint8_t vhv_config__count_thresh; + uint8_t vhv_config__offset; + uint8_t vhv_config__init; +} VL53LX_static_nvm_managed_t; + +typedef struct { + uint32_t VL53LX_p_037; + uint8_t VL53LX_p_063; + uint8_t VL53LX_p_064; + uint16_t VL53LX_p_065; + uint16_t VL53LX_p_066; + uint16_t VL53LX_p_067; + uint16_t VL53LX_p_038; + uint32_t VL53LX_p_009; + uint32_t VL53LX_p_033; + uint16_t VL53LX_p_034; + uint16_t VL53LX_p_004; + uint32_t VL53LX_p_028; + uint32_t VL53LX_p_035; + int16_t VL53LX_p_036; + int16_t VL53LX_p_022; +} VL53LX_hist_gen3_dmax_private_data_t; + +typedef struct { + uint16_t dss_config__target_total_rate_mcps; + uint8_t debug__ctrl; + uint8_t test_mode__ctrl; + uint8_t clk_gating__ctrl; + uint8_t nvm_bist__ctrl; + uint8_t nvm_bist__num_nvm_words; + uint8_t nvm_bist__start_address; + uint8_t host_if__status; + uint8_t pad_i2c_hv__config; + uint8_t pad_i2c_hv__extsup_config; + uint8_t gpio_hv_pad__ctrl; + uint8_t gpio_hv_mux__ctrl; + uint8_t gpio__tio_hv_status; + uint8_t gpio__fio_hv_status; + uint8_t ana_config__spad_sel_pswidth; + uint8_t ana_config__vcsel_pulse_width_offset; + uint8_t ana_config__fast_osc__config_ctrl; + uint8_t sigma_estimator__effective_pulse_width_ns; + uint8_t sigma_estimator__effective_ambient_width_ns; + uint8_t sigma_estimator__sigma_ref_mm; + uint8_t algo__crosstalk_compensation_valid_height_mm; + uint8_t spare_host_config__static_config_spare_0; + uint8_t spare_host_config__static_config_spare_1; + uint16_t algo__range_ignore_threshold_mcps; + uint8_t algo__range_ignore_valid_height_mm; + uint8_t algo__range_min_clip; + uint8_t algo__consistency_check__tolerance; + uint8_t spare_host_config__static_config_spare_2; + uint8_t sd_config__reset_stages_msb; + uint8_t sd_config__reset_stages_lsb; +} VL53LX_static_config_t; + +typedef struct { + uint8_t gph_config__stream_count_update_value; + uint8_t global_config__stream_divider; + uint8_t system__interrupt_config_gpio; + uint8_t cal_config__vcsel_start; + uint16_t cal_config__repeat_rate; + uint8_t global_config__vcsel_width; + uint8_t phasecal_config__timeout_macrop; + uint8_t phasecal_config__target; + uint8_t phasecal_config__override; + uint8_t dss_config__roi_mode_control; + uint16_t system__thresh_rate_high; + uint16_t system__thresh_rate_low; + uint16_t dss_config__manual_effective_spads_select; + uint8_t dss_config__manual_block_select; + uint8_t dss_config__aperture_attenuation; + uint8_t dss_config__max_spads_limit; + uint8_t dss_config__min_spads_limit; +} VL53LX_general_config_t; + +typedef struct { + uint8_t mm_config__timeout_macrop_a_hi; + uint8_t mm_config__timeout_macrop_a_lo; + uint8_t mm_config__timeout_macrop_b_hi; + uint8_t mm_config__timeout_macrop_b_lo; + uint8_t range_config__timeout_macrop_a_hi; + uint8_t range_config__timeout_macrop_a_lo; + uint8_t range_config__vcsel_period_a; + uint8_t range_config__timeout_macrop_b_hi; + uint8_t range_config__timeout_macrop_b_lo; + uint8_t range_config__vcsel_period_b; + uint16_t range_config__sigma_thresh; + uint16_t range_config__min_count_rate_rtn_limit_mcps; + uint8_t range_config__valid_phase_low; + uint8_t range_config__valid_phase_high; + uint32_t system__intermeasurement_period; + uint8_t system__fractional_enable; +} VL53LX_timing_config_t; + +typedef struct { + uint8_t system__grouped_parameter_hold_0; + uint16_t system__thresh_high; + uint16_t system__thresh_low; + uint8_t system__enable_xtalk_per_quadrant; + uint8_t system__seed_config; + uint8_t sd_config__woi_sd0; + uint8_t sd_config__woi_sd1; + uint8_t sd_config__initial_phase_sd0; + uint8_t sd_config__initial_phase_sd1; + uint8_t system__grouped_parameter_hold_1; + uint8_t sd_config__first_order_select; + uint8_t sd_config__quantifier; + uint8_t roi_config__user_roi_centre_spad; + uint8_t roi_config__user_roi_requested_global_xy_size; + uint8_t system__sequence_config; + uint8_t system__grouped_parameter_hold; +} VL53LX_dynamic_config_t; + +typedef struct { + uint8_t power_management__go1_power_force; + uint8_t system__stream_count_ctrl; + uint8_t firmware__enable; + uint8_t system__interrupt_clear; + uint8_t system__mode_start; +} VL53LX_system_control_t; + +typedef struct { + uint8_t result__interrupt_status; + uint8_t result__range_status; + uint8_t result__report_status; + uint8_t result__stream_count; + uint16_t result__dss_actual_effective_spads_sd0; + uint16_t result__peak_signal_count_rate_mcps_sd0; + uint16_t result__ambient_count_rate_mcps_sd0; + uint16_t result__sigma_sd0; + uint16_t result__phase_sd0; + uint16_t result__final_crosstalk_corrected_range_mm_sd0; + uint16_t result__peak_signal_count_rate_crosstalk_corrected_mcps_sd0; + uint16_t result__mm_inner_actual_effective_spads_sd0; + uint16_t result__mm_outer_actual_effective_spads_sd0; + uint16_t result__avg_signal_count_rate_mcps_sd0; + uint16_t result__dss_actual_effective_spads_sd1; + uint16_t result__peak_signal_count_rate_mcps_sd1; + uint16_t result__ambient_count_rate_mcps_sd1; + uint16_t result__sigma_sd1; + uint16_t result__phase_sd1; + uint16_t result__final_crosstalk_corrected_range_mm_sd1; + uint16_t result__spare_0_sd1; + uint16_t result__spare_1_sd1; + uint16_t result__spare_2_sd1; + uint8_t result__spare_3_sd1; + uint8_t result__thresh_info; +} VL53LX_system_results_t; + +typedef struct { + uint8_t identification__model_id; + uint8_t identification__module_type; + uint8_t identification__revision_id; + uint16_t identification__module_id; + uint8_t ana_config__fast_osc__trim_max; + uint8_t ana_config__fast_osc__freq_set; + uint8_t ana_config__vcsel_trim; + uint8_t ana_config__vcsel_selion; + uint8_t ana_config__vcsel_selion_max; + uint8_t protected_laser_safety__lock_bit; + uint8_t laser_safety__key; + uint8_t laser_safety__key_ro; + uint8_t laser_safety__clip; + uint8_t laser_safety__mult; + uint8_t global_config__spad_enables_rtn_0; + uint8_t global_config__spad_enables_rtn_1; + uint8_t global_config__spad_enables_rtn_2; + uint8_t global_config__spad_enables_rtn_3; + uint8_t global_config__spad_enables_rtn_4; + uint8_t global_config__spad_enables_rtn_5; + uint8_t global_config__spad_enables_rtn_6; + uint8_t global_config__spad_enables_rtn_7; + uint8_t global_config__spad_enables_rtn_8; + uint8_t global_config__spad_enables_rtn_9; + uint8_t global_config__spad_enables_rtn_10; + uint8_t global_config__spad_enables_rtn_11; + uint8_t global_config__spad_enables_rtn_12; + uint8_t global_config__spad_enables_rtn_13; + uint8_t global_config__spad_enables_rtn_14; + uint8_t global_config__spad_enables_rtn_15; + uint8_t global_config__spad_enables_rtn_16; + uint8_t global_config__spad_enables_rtn_17; + uint8_t global_config__spad_enables_rtn_18; + uint8_t global_config__spad_enables_rtn_19; + uint8_t global_config__spad_enables_rtn_20; + uint8_t global_config__spad_enables_rtn_21; + uint8_t global_config__spad_enables_rtn_22; + uint8_t global_config__spad_enables_rtn_23; + uint8_t global_config__spad_enables_rtn_24; + uint8_t global_config__spad_enables_rtn_25; + uint8_t global_config__spad_enables_rtn_26; + uint8_t global_config__spad_enables_rtn_27; + uint8_t global_config__spad_enables_rtn_28; + uint8_t global_config__spad_enables_rtn_29; + uint8_t global_config__spad_enables_rtn_30; + uint8_t global_config__spad_enables_rtn_31; + uint8_t roi_config__mode_roi_centre_spad; + uint8_t roi_config__mode_roi_xy_size; +} VL53LX_nvm_copy_data_t; + +typedef struct { + VL53LX_DeviceState cfg_device_state; + VL53LX_DeviceState rd_device_state; + uint8_t zone_id; + uint32_t time_stamp; + uint8_t VL53LX_p_019; + uint8_t VL53LX_p_020; + uint8_t VL53LX_p_021; + uint8_t number_of_ambient_bins; + uint8_t bin_seq[VL53LX_MAX_BIN_SEQUENCE_LENGTH]; + uint8_t bin_rep[VL53LX_MAX_BIN_SEQUENCE_LENGTH]; + int32_t bin_data[VL53LX_HISTOGRAM_BUFFER_SIZE]; + uint8_t result__interrupt_status; + uint8_t result__range_status; + uint8_t result__report_status; + uint8_t result__stream_count; + uint16_t result__dss_actual_effective_spads; + uint16_t phasecal_result__reference_phase; + uint8_t phasecal_result__vcsel_start; + uint8_t cal_config__vcsel_start; + uint16_t vcsel_width; + uint8_t VL53LX_p_005; + uint16_t VL53LX_p_015; + uint32_t total_periods_elapsed; + uint32_t peak_duration_us; + uint32_t woi_duration_us; + int32_t min_bin_value; + int32_t max_bin_value; + uint16_t zero_distance_phase; + uint8_t number_of_ambient_samples; + int32_t ambient_events_sum; + int32_t VL53LX_p_028; + uint8_t roi_config__user_roi_centre_spad; + uint8_t roi_config__user_roi_requested_global_xy_size; +} VL53LX_histogram_bin_data_t; + +typedef struct { + uint8_t zone_id; + uint32_t time_stamp; + uint8_t VL53LX_p_019; + uint8_t VL53LX_p_020; + uint8_t VL53LX_p_021; + uint32_t bin_data[VL53LX_XTALK_HISTO_BINS]; + uint16_t phasecal_result__reference_phase; + uint8_t phasecal_result__vcsel_start; + uint8_t cal_config__vcsel_start; + uint16_t vcsel_width; + uint16_t VL53LX_p_015; + uint16_t zero_distance_phase; +} VL53LX_xtalk_histogram_shape_t; + +typedef struct { + VL53LX_xtalk_histogram_shape_t xtalk_shape; + VL53LX_histogram_bin_data_t xtalk_hist_removed; +} VL53LX_xtalk_histogram_data_t; + +typedef struct { + uint8_t no_of_samples; + uint32_t rate_per_spad_kcps_sum; + uint32_t rate_per_spad_kcps_avg; + int32_t signal_total_events_sum; + int32_t signal_total_events_avg; + uint32_t sigma_mm_sum; + uint32_t sigma_mm_avg; + uint32_t median_phase_sum; + uint32_t median_phase_avg; +} VL53LX_xtalk_range_data_t; + +typedef struct { + VL53LX_Error cal_status; + uint8_t num_of_samples_status; + uint8_t zero_samples_status; + uint8_t max_sigma_status; + uint8_t max_results; + uint8_t active_results; + VL53LX_xtalk_range_data_t VL53LX_p_003[VL53LX_MAX_XTALK_RANGE_RESULTS]; + VL53LX_histogram_bin_data_t central_histogram_sum; + VL53LX_histogram_bin_data_t central_histogram_avg; + uint8_t central_histogram__window_start; + uint8_t central_histogram__window_end; + VL53LX_histogram_bin_data_t histogram_avg_1[VL53LX_MAX_XTALK_RANGE_RESULTS]; + VL53LX_histogram_bin_data_t histogram_avg_2[VL53LX_MAX_XTALK_RANGE_RESULTS]; + VL53LX_histogram_bin_data_t xtalk_avg[VL53LX_MAX_XTALK_RANGE_RESULTS]; +} VL53LX_xtalk_range_results_t; + +typedef struct { + uint32_t algo__crosstalk_compensation_plane_offset_kcps; + int16_t algo__crosstalk_compensation_x_plane_gradient_kcps; + int16_t algo__crosstalk_compensation_y_plane_gradient_kcps; + uint32_t algo__xtalk_cpo_HistoMerge_kcps[VL53LX_BIN_REC_SIZE]; +} VL53LX_xtalk_calibration_results_t; + +typedef struct { + uint32_t sample_count; + uint32_t pll_period_mm; + uint32_t peak_duration_us_sum; + uint32_t effective_spad_count_sum; + uint32_t zero_distance_phase_sum; + uint32_t zero_distance_phase_avg; + int32_t event_scaler_sum; + int32_t event_scaler_avg; + int32_t signal_events_sum; + uint32_t xtalk_rate_kcps_per_spad; + int32_t xtalk_start_phase; + int32_t xtalk_end_phase; + int32_t xtalk_width_phase; + int32_t target_start_phase; + int32_t target_end_phase; + int32_t target_width_phase; + int32_t effective_width; + int32_t event_scaler; + uint8_t VL53LX_p_012; + uint8_t VL53LX_p_013; + uint8_t target_start; + int32_t max_shape_value; + int32_t bin_data_sums[VL53LX_XTALK_HISTO_BINS]; +} VL53LX_hist_xtalk_extract_data_t; + +typedef struct { + uint8_t preset_mode; + uint8_t dss_config__roi_mode_control; + uint16_t dss_config__manual_effective_spads_select; + uint8_t no_of_samples; + uint32_t effective_spads; + uint32_t peak_rate_mcps; + uint32_t VL53LX_p_002; + int32_t median_range_mm; + int32_t range_mm_offset; +} VL53LX_offset_range_data_t; + +typedef struct { + int16_t cal_distance_mm; + uint16_t cal_reflectance_pc; + VL53LX_Error cal_status; + uint8_t cal_report; + uint8_t max_results; + uint8_t active_results; + VL53LX_offset_range_data_t VL53LX_p_003[VL53LX_MAX_OFFSET_RANGE_RESULTS]; +} VL53LX_offset_range_results_t; + +typedef struct { + uint32_t result_core__ambient_window_events_sd0; + uint32_t result_core__ranging_total_events_sd0; + int32_t result_core__signal_total_events_sd0; + uint32_t result_core__total_periods_elapsed_sd0; + uint32_t result_core__ambient_window_events_sd1; + uint32_t result_core__ranging_total_events_sd1; + int32_t result_core__signal_total_events_sd1; + uint32_t result_core__total_periods_elapsed_sd1; + uint8_t result_core__spare_0; +} VL53LX_core_results_t; + +typedef struct { + + uint16_t result__actual_effective_rtn_spads; + uint8_t ref_spad_array__num_requested_ref_spads; + uint8_t ref_spad_array__ref_location; + uint16_t result__peak_signal_count_rate_rtn_mcps; + uint16_t result__ambient_count_rate_rtn_mcps; + uint16_t result__peak_signal_count_rate_ref_mcps; + uint16_t result__ambient_count_rate_ref_mcps; + uint16_t measured_distance_mm; + uint16_t measured_distance_stdev_mm; +} VL53LX_decoded_nvm_fmt_range_data_t; + +typedef struct { + uint16_t phasecal_result__reference_phase; + uint8_t phasecal_result__vcsel_start; + uint8_t ref_spad_char_result__num_actual_ref_spads; + uint8_t ref_spad_char_result__ref_location; + uint8_t vhv_result__coldboot_status; + uint8_t vhv_result__search_result; + uint8_t vhv_result__latest_setting; + uint16_t result__osc_calibrate_val; + uint8_t ana_config__powerdown_go1; + uint8_t ana_config__ref_bg_ctrl; + uint8_t ana_config__regdvdd1v2_ctrl; + uint8_t ana_config__osc_slow_ctrl; + uint8_t test_mode__status; + uint8_t firmware__system_status; + uint8_t firmware__mode_status; + uint8_t firmware__secondary_mode_status; + uint16_t firmware__cal_repeat_rate_counter; + uint16_t gph__system__thresh_high; + uint16_t gph__system__thresh_low; + uint8_t gph__system__enable_xtalk_per_quadrant; + uint8_t gph__spare_0; + uint8_t gph__sd_config__woi_sd0; + uint8_t gph__sd_config__woi_sd1; + uint8_t gph__sd_config__initial_phase_sd0; + uint8_t gph__sd_config__initial_phase_sd1; + uint8_t gph__sd_config__first_order_select; + uint8_t gph__sd_config__quantifier; + uint8_t gph__roi_config__user_roi_centre_spad; + uint8_t gph__roi_config__user_roi_requested_global_xy_size; + uint8_t gph__system__sequence_config; + uint8_t gph__gph_id; + uint8_t system__interrupt_set; + uint8_t interrupt_manager__enables; + uint8_t interrupt_manager__clear; + uint8_t interrupt_manager__status; + uint8_t mcu_to_host_bank__wr_access_en; + uint8_t power_management__go1_reset_status; + uint8_t pad_startup_mode__value_ro; + uint8_t pad_startup_mode__value_ctrl; + uint32_t pll_period_us; + uint32_t interrupt_scheduler__data_out; + uint8_t nvm_bist__complete; + uint8_t nvm_bist__status; +} VL53LX_debug_results_t; + +typedef struct { + uint8_t smudge_corr_enabled; + uint8_t smudge_corr_apply_enabled; + uint8_t smudge_corr_single_apply; + uint16_t smudge_margin; + uint32_t noise_margin; + uint32_t user_xtalk_offset_limit; + uint8_t user_xtalk_offset_limit_hi; + uint32_t sample_limit; + uint32_t single_xtalk_delta; + uint32_t averaged_xtalk_delta; + uint32_t smudge_corr_clip_limit; + uint32_t smudge_corr_ambient_threshold; + uint8_t scaler_calc_method; + int16_t x_gradient_scaler; + int16_t y_gradient_scaler; + uint8_t user_scaler_set; + uint32_t nodetect_ambient_threshold; + uint32_t nodetect_sample_limit; + uint32_t nodetect_xtalk_offset; + uint16_t nodetect_min_range_mm; + uint32_t max_smudge_factor; +} VL53LX_smudge_corrector_config_t; + +typedef struct { + uint32_t current_samples; + uint32_t required_samples; + uint64_t accumulator; + uint32_t nodetect_counter; +} VL53LX_smudge_corrector_internals_t; + +typedef struct { + uint8_t vhv_loop_bound; + uint8_t is_low_power_auto_mode; + uint8_t low_power_auto_range_count; + uint8_t saved_interrupt_config; + uint8_t saved_vhv_init; + uint8_t saved_vhv_timeout; + uint8_t first_run_phasecal_result; + uint32_t dss__total_rate_per_spad_mcps; + uint16_t dss__required_spads; +} VL53LX_low_power_auto_data_t; + +typedef struct { + int16_t short_a_offset_mm; + int16_t short_b_offset_mm; + int16_t medium_a_offset_mm; + int16_t medium_b_offset_mm; + int16_t long_a_offset_mm; + int16_t long_b_offset_mm; +} VL53LX_per_vcsel_period_offset_cal_data_t; + +typedef struct { + uint8_t wait_method; + VL53LX_DevicePresetModes preset_mode; + VL53LX_DeviceZonePreset zone_preset; + VL53LX_DeviceMeasurementModes measurement_mode; + VL53LX_OffsetCalibrationMode offset_calibration_mode; + VL53LX_OffsetCorrectionMode offset_correction_mode; + VL53LX_DeviceDmaxMode dmax_mode; + uint32_t phasecal_config_timeout_us; + uint32_t mm_config_timeout_us; + uint32_t range_config_timeout_us; + uint32_t inter_measurement_period_ms; + uint16_t dss_config__target_total_rate_mcps; + uint32_t fw_ready_poll_duration_ms; + uint8_t fw_ready; + uint8_t debug_mode; + VL53LX_ll_version_t version; + VL53LX_ll_driver_state_t ll_state; + VL53LX_GPIO_interrupt_config_t gpio_interrupt_config; + VL53LX_customer_nvm_managed_t customer; + VL53LX_cal_peak_rate_map_t cal_peak_rate_map; + VL53LX_additional_offset_cal_data_t add_off_cal_data; + VL53LX_dmax_calibration_data_t fmt_dmax_cal; + VL53LX_dmax_calibration_data_t cust_dmax_cal; + VL53LX_gain_calibration_data_t gain_cal; + VL53LX_user_zone_t mm_roi; + VL53LX_optical_centre_t optical_centre; + VL53LX_zone_config_t zone_cfg; + VL53LX_tuning_parm_storage_t tuning_parms; + uint8_t rtn_good_spads[VL53LX_RTN_SPAD_BUFFER_SIZE]; + VL53LX_refspadchar_config_t refspadchar; + VL53LX_ssc_config_t ssc_cfg; + VL53LX_hist_post_process_config_t histpostprocess; + VL53LX_hist_gen3_dmax_config_t dmax_cfg; + VL53LX_xtalkextract_config_t xtalk_extract_cfg; + VL53LX_xtalk_config_t xtalk_cfg; + VL53LX_offsetcal_config_t offsetcal_cfg; + VL53LX_zonecal_config_t zonecal_cfg; + VL53LX_static_nvm_managed_t stat_nvm; + VL53LX_histogram_config_t hist_cfg; + VL53LX_static_config_t stat_cfg; + VL53LX_general_config_t gen_cfg; + VL53LX_timing_config_t tim_cfg; + VL53LX_dynamic_config_t dyn_cfg; + VL53LX_system_control_t sys_ctrl; + VL53LX_system_results_t sys_results; + VL53LX_nvm_copy_data_t nvm_copy_data; + VL53LX_histogram_bin_data_t hist_data; + VL53LX_histogram_bin_data_t hist_xtalk; + VL53LX_xtalk_histogram_data_t xtalk_shapes; + VL53LX_xtalk_range_results_t xtalk_results; + VL53LX_xtalk_calibration_results_t xtalk_cal; + VL53LX_hist_xtalk_extract_data_t xtalk_extract; + VL53LX_offset_range_results_t offset_results; + VL53LX_core_results_t core_results; + VL53LX_debug_results_t dbg_results; + VL53LX_smudge_corrector_config_t smudge_correct_config; + VL53LX_smudge_corrector_internals_t smudge_corrector_internals; + VL53LX_low_power_auto_data_t low_power_auto_data; + uint8_t wArea1[1536]; + uint8_t wArea2[512]; + VL53LX_per_vcsel_period_offset_cal_data_t per_vcsel_cal_data; + uint8_t bin_rec_pos; + uint8_t pos_before_next_recom; + int32_t multi_bins_rec[VL53LX_BIN_REC_SIZE][VL53LX_TIMING_CONF_A_B_SIZE][VL53LX_HISTOGRAM_BUFFER_SIZE]; + int16_t PreviousRangeMilliMeter[VL53LX_MAX_RANGE_RESULTS]; + uint8_t PreviousRangeStatus[VL53LX_MAX_RANGE_RESULTS]; + uint8_t PreviousExtendedRange[VL53LX_MAX_RANGE_RESULTS]; + uint8_t PreviousRangeActiveResults; + uint8_t PreviousStreamCount; +} VL53LX_LLDriverData_t; + +typedef struct { + uint8_t expected_stream_count; + uint8_t expected_gph_id; + uint8_t dss_mode; + uint16_t dss_requested_effective_spad_count; + uint8_t seed_cfg; + uint8_t initial_phase_seed; + uint8_t roi_config__user_roi_centre_spad; + uint8_t roi_config__user_roi_requested_global_xy_size; +} VL53LX_zone_private_dyn_cfg_t; + +typedef struct { + uint8_t max_zones; + uint8_t active_zones; + VL53LX_zone_private_dyn_cfg_t VL53LX_p_003[VL53LX_MAX_USER_ZONES]; +} VL53LX_zone_private_dyn_cfgs_t; + +typedef struct { + uint8_t range_id; + uint32_t time_stamp; + uint8_t VL53LX_p_012; + uint8_t VL53LX_p_019; + uint8_t VL53LX_p_023; + uint8_t VL53LX_p_024; + uint8_t VL53LX_p_013; + uint8_t VL53LX_p_025; + uint16_t width; + uint8_t VL53LX_p_029; + uint16_t fast_osc_frequency; + uint16_t zero_distance_phase; + uint16_t VL53LX_p_004; + uint32_t total_periods_elapsed; + uint32_t peak_duration_us; + uint32_t woi_duration_us; + uint32_t VL53LX_p_016; + uint32_t VL53LX_p_017; + int32_t VL53LX_p_010; + uint16_t peak_signal_count_rate_mcps; + uint16_t avg_signal_count_rate_mcps; + uint16_t ambient_count_rate_mcps; + uint16_t total_rate_per_spad_mcps; + uint32_t VL53LX_p_009; + uint16_t VL53LX_p_002; + uint16_t VL53LX_p_026; + uint16_t VL53LX_p_011; + uint16_t VL53LX_p_027; + int16_t min_range_mm; + int16_t median_range_mm; + int16_t max_range_mm; + uint8_t range_status; +} VL53LX_range_data_t; + +typedef struct { + uint8_t smudge_corr_valid; + uint8_t smudge_corr_clipped; + uint8_t single_xtalk_delta_flag; + uint8_t averaged_xtalk_delta_flag; + uint8_t sample_limit_exceeded_flag; + uint8_t gradient_zero_flag; + uint8_t new_xtalk_applied_flag; + uint32_t algo__crosstalk_compensation_plane_offset_kcps; + int16_t algo__crosstalk_compensation_x_plane_gradient_kcps; + int16_t algo__crosstalk_compensation_y_plane_gradient_kcps; +} VL53LX_smudge_corrector_data_t; + +typedef struct { + VL53LX_DeviceState cfg_device_state; + VL53LX_DeviceState rd_device_state; + uint8_t zone_id; + uint8_t stream_count; + int16_t VL53LX_p_022[VL53LX_MAX_AMBIENT_DMAX_VALUES]; + int16_t wrap_dmax_mm; + uint8_t device_status; + uint8_t max_results; + uint8_t active_results; + VL53LX_range_data_t VL53LX_p_003[VL53LX_MAX_RANGE_RESULTS]; + VL53LX_range_data_t xmonitor; + VL53LX_smudge_corrector_data_t smudge_corrector_data; +} VL53LX_range_results_t; + +typedef struct { + uint8_t max_zones; + uint8_t active_zones; + VL53LX_zone_objects_t VL53LX_p_003[VL53LX_MAX_USER_ZONES]; +} VL53LX_zone_results_t; + +typedef struct { + VL53LX_DeviceState rd_device_state; + uint8_t number_of_ambient_bins; + uint16_t result__dss_actual_effective_spads; + uint8_t VL53LX_p_005; + uint32_t total_periods_elapsed; + int32_t ambient_events_sum; +} VL53LX_zone_hist_info_t; + +typedef struct { + uint8_t max_zones; + uint8_t active_zones; + VL53LX_zone_hist_info_t VL53LX_p_003[VL53LX_MAX_USER_ZONES]; +} VL53LX_zone_histograms_t; + +typedef struct { + uint32_t no_of_samples; + uint32_t effective_spads; + uint32_t peak_rate_mcps; + uint32_t VL53LX_p_011; + uint32_t VL53LX_p_002; + int32_t median_range_mm; + int32_t range_mm_offset; +} VL53LX_zone_calibration_data_t; + +typedef struct { + uint32_t struct_version; + VL53LX_DevicePresetModes preset_mode; + VL53LX_DeviceZonePreset zone_preset; + int16_t cal_distance_mm; + uint16_t cal_reflectance_pc; + uint16_t phasecal_result__reference_phase; + uint16_t zero_distance_phase; + VL53LX_Error cal_status; + uint8_t max_zones; + uint8_t active_zones; + VL53LX_zone_calibration_data_t VL53LX_p_003[VL53LX_MAX_USER_ZONES]; +} VL53LX_zone_calibration_results_t; + +typedef struct { + VL53LX_range_results_t range_results; + VL53LX_zone_private_dyn_cfgs_t zone_dyn_cfgs; + VL53LX_zone_results_t zone_results; + VL53LX_zone_histograms_t zone_hists; + VL53LX_zone_calibration_results_t zone_cal; +} VL53LX_LLDriverResults_t; + +typedef struct { + VL53LX_DistanceModes DistanceMode; + uint32_t MeasurementTimingBudgetMicroSeconds; +} VL53LX_DeviceParameters_t; + +typedef struct { + VL53LX_LLDriverData_t LLData; + VL53LX_LLDriverResults_t llresults; + VL53LX_DeviceParameters_t CurrentParameters; +} VL53LX_DevData_t; + +typedef struct { + uint8_t global_config__spad_enables_ref_0; + uint8_t global_config__spad_enables_ref_1; + uint8_t global_config__spad_enables_ref_2; + uint8_t global_config__spad_enables_ref_3; + uint8_t global_config__spad_enables_ref_4; + uint8_t global_config__spad_enables_ref_5; + uint8_t global_config__ref_en_start_select; + uint8_t ref_spad_man__num_requested_ref_spads; + uint8_t ref_spad_man__ref_location; + uint32_t algo__crosstalk_compensation_plane_offset_kcps; + int16_t algo__crosstalk_compensation_x_plane_gradient_kcps; + int16_t algo__crosstalk_compensation_y_plane_gradient_kcps; + uint16_t ref_spad_char__total_rate_target_mcps; + int16_t algo__part_to_part_range_offset_mm; + int16_t mm_config__inner_offset_mm; + int16_t mm_config__outer_offset_mm; +} VL53LX_CustomerNvmManaged_t; + +typedef struct { + uint32_t struct_version; + VL53LX_CustomerNvmManaged_t customer; + VL53LX_additional_offset_cal_data_t add_off_cal_data; + VL53LX_optical_centre_t optical_centre; + VL53LX_xtalk_histogram_data_t xtalkhisto; + VL53LX_gain_calibration_data_t gain_cal; + VL53LX_cal_peak_rate_map_t cal_peak_rate_map; + VL53LX_per_vcsel_period_offset_cal_data_t per_vcsel_cal_data; + uint32_t algo__xtalk_cpo_HistoMerge_kcps[VL53LX_BIN_REC_SIZE]; +} VL53LX_CalibrationData_t; + +struct stmvl53lx_ioctl_calibration_data_t { + int32_t is_read; + VL53LX_CalibrationData_t data; +}; + +struct stmvl53lx_ioctl_perform_calibration_t { + uint32_t calibration_type; + uint32_t param1; + uint32_t param2; + uint32_t param3; +}; + +typedef struct { + uint8_t ProductType; + uint8_t ProductRevisionMajor; + uint8_t ProductRevisionMinor; +} VL53LX_DeviceInfo_t; + +typedef struct { + int16_t RangeMaxMilliMeter; + int16_t RangeMinMilliMeter; + FixPoint1616_t SignalRateRtnMegaCps; + FixPoint1616_t AmbientRateRtnMegaCps; + FixPoint1616_t SigmaMilliMeter; + int16_t RangeMilliMeter; + uint8_t RangeStatus; + uint8_t ExtendedRange; +} VL53LX_TargetRangeData_t; + +typedef struct { + uint32_t TimeStamp; + uint8_t StreamCount; + uint8_t NumberOfObjectsFound; + VL53LX_TargetRangeData_t RangeData[VL53LX_MAX_RANGE_RESULTS]; + uint8_t HasXtalkValueChanged; + uint16_t EffectiveSpadRtnCount; +} VL53LX_MultiRangingData_t; + +typedef struct { + VL53LX_DevicePresetModes preset_mode; + VL53LX_DeviceZonePreset zone_preset; + VL53LX_DeviceMeasurementModes measurement_mode; + VL53LX_OffsetCalibrationMode offset_calibration_mode; + VL53LX_OffsetCorrectionMode offset_correction_mode; + VL53LX_DeviceDmaxMode dmax_mode; + uint32_t phasecal_config_timeout_us; + uint32_t mm_config_timeout_us; + uint32_t range_config_timeout_us; + uint32_t inter_measurement_period_ms; + uint16_t dss_config__target_total_rate_mcps; + VL53LX_histogram_bin_data_t VL53LX_p_006; +} VL53LX_additional_data_t; + +typedef VL53LX_additional_data_t VL53LX_AdditionalData_t; + +struct stmvl53lx_data_with_additional { + VL53LX_MultiRangingData_t data; + VL53LX_AdditionalData_t additional_data; +}; + +typedef struct { + + uint32_t struct_version; + VL53LX_customer_nvm_managed_t customer; + VL53LX_dmax_calibration_data_t fmt_dmax_cal; + VL53LX_dmax_calibration_data_t cust_dmax_cal; + VL53LX_additional_offset_cal_data_t add_off_cal_data; + VL53LX_optical_centre_t optical_centre; + VL53LX_xtalk_histogram_data_t xtalkhisto; + VL53LX_gain_calibration_data_t gain_cal; + VL53LX_cal_peak_rate_map_t cal_peak_rate_map; + VL53LX_per_vcsel_period_offset_cal_data_t per_vcsel_cal_data; +} VL53LX_calibration_data_t; + +typedef struct { + uint8_t VL53LX_p_019; + uint8_t VL53LX_p_020; + uint8_t VL53LX_p_021; + uint8_t VL53LX_p_029; + int32_t VL53LX_p_016; + int32_t VL53LX_p_043[VL53LX_HISTOGRAM_BUFFER_SIZE]; + int32_t VL53LX_p_068[VL53LX_HISTOGRAM_BUFFER_SIZE]; + uint8_t VL53LX_p_040[VL53LX_HISTOGRAM_BUFFER_SIZE]; + int32_t VL53LX_p_018[VL53LX_HISTOGRAM_BUFFER_SIZE]; + uint16_t VL53LX_p_014[VL53LX_HISTOGRAM_BUFFER_SIZE]; + uint16_t VL53LX_p_008[VL53LX_HISTOGRAM_BUFFER_SIZE]; + +} VL53LX_hist_gen1_algo_private_data_t; + +typedef struct { + uint8_t VL53LX_p_019; + uint8_t VL53LX_p_020; + uint8_t VL53LX_p_021; + uint16_t VL53LX_p_015; + uint8_t VL53LX_p_005; + uint8_t VL53LX_p_029; + int32_t VL53LX_p_028; + int32_t VL53LX_p_016; + int32_t VL53LX_p_007[VL53LX_HISTOGRAM_BUFFER_SIZE]; + int32_t VL53LX_p_032[VL53LX_HISTOGRAM_BUFFER_SIZE]; + int32_t VL53LX_p_001[VL53LX_HISTOGRAM_BUFFER_SIZE]; + int32_t VL53LX_p_018[VL53LX_HISTOGRAM_BUFFER_SIZE]; + int32_t VL53LX_p_055[VL53LX_HISTOGRAM_BUFFER_SIZE]; + int32_t VL53LX_p_053[VL53LX_HISTOGRAM_BUFFER_SIZE]; + int32_t VL53LX_p_054[VL53LX_HISTOGRAM_BUFFER_SIZE]; +} VL53LX_hist_gen2_algo_filtered_data_t; + +typedef struct { + uint8_t VL53LX_p_019; + uint8_t VL53LX_p_020; + uint8_t VL53LX_p_021; + int32_t VL53LX_p_031; + uint8_t VL53LX_p_069[VL53LX_HISTOGRAM_BUFFER_SIZE]; + uint8_t VL53LX_p_070[VL53LX_HISTOGRAM_BUFFER_SIZE]; + uint32_t VL53LX_p_014[VL53LX_HISTOGRAM_BUFFER_SIZE]; + uint16_t VL53LX_p_008[VL53LX_HISTOGRAM_BUFFER_SIZE]; + uint8_t VL53LX_p_040[VL53LX_HISTOGRAM_BUFFER_SIZE]; +} VL53LX_hist_gen2_algo_detection_data_t; + +typedef struct { + uint8_t VL53LX_p_012; + uint8_t VL53LX_p_019; + uint8_t VL53LX_p_023; + uint8_t VL53LX_p_024; + uint8_t VL53LX_p_013; + uint8_t VL53LX_p_025; + uint8_t VL53LX_p_051; + int32_t VL53LX_p_016; + int32_t VL53LX_p_017; + int32_t VL53LX_p_010; + uint32_t VL53LX_p_026; + uint32_t VL53LX_p_011; + uint32_t VL53LX_p_027; + uint16_t VL53LX_p_002; +} VL53LX_hist_pulse_data_t; + +typedef struct { + uint8_t VL53LX_p_019; + uint8_t VL53LX_p_020; + uint8_t VL53LX_p_021; + uint8_t VL53LX_p_030; + uint8_t VL53LX_p_039; + int32_t VL53LX_p_028; + int32_t VL53LX_p_031; + uint8_t VL53LX_p_040[VL53LX_HISTOGRAM_BUFFER_SIZE]; + uint8_t VL53LX_p_041[VL53LX_HISTOGRAM_BUFFER_SIZE]; + uint8_t VL53LX_p_042[VL53LX_HISTOGRAM_BUFFER_SIZE]; + int32_t VL53LX_p_052[VL53LX_HISTOGRAM_BUFFER_SIZE]; + int32_t VL53LX_p_043[VL53LX_HISTOGRAM_BUFFER_SIZE]; + int32_t VL53LX_p_018[VL53LX_HISTOGRAM_BUFFER_SIZE]; + uint8_t VL53LX_p_044; + uint8_t VL53LX_p_045; + uint8_t VL53LX_p_046; + VL53LX_hist_pulse_data_t VL53LX_p_003[VL53LX_D_001]; + VL53LX_histogram_bin_data_t VL53LX_p_006; + VL53LX_histogram_bin_data_t VL53LX_p_047; + VL53LX_histogram_bin_data_t VL53LX_p_048; + VL53LX_histogram_bin_data_t VL53LX_p_049; + VL53LX_histogram_bin_data_t VL53LX_p_050; +} VL53LX_hist_gen3_algo_private_data_t; + +typedef struct { + uint8_t VL53LX_p_019; + uint8_t VL53LX_p_020; + uint8_t VL53LX_p_021; + int32_t VL53LX_p_007[VL53LX_HISTOGRAM_BUFFER_SIZE]; + int32_t VL53LX_p_032[VL53LX_HISTOGRAM_BUFFER_SIZE]; + int32_t VL53LX_p_001[VL53LX_HISTOGRAM_BUFFER_SIZE]; + int32_t VL53LX_p_053[VL53LX_HISTOGRAM_BUFFER_SIZE]; + int32_t VL53LX_p_054[VL53LX_HISTOGRAM_BUFFER_SIZE]; + uint8_t VL53LX_p_040[VL53LX_HISTOGRAM_BUFFER_SIZE]; +} VL53LX_hist_gen4_algo_filtered_data_t; + +struct st_timeval { + time64_t tv_sec; + long tv_usec; +}; + +struct stmvl53lx_data { + int id; + char name[64]; + VL53LX_DevData_t stdev; + void *client_object; + bool is_device_remove; + struct mutex work_mutex; + struct delayed_work dwork; + struct input_dev *input_dev_ps; + struct miscdevice miscdev; + int is_first_irq; + int is_first_start_done; + int poll_mode; + int poll_delay_ms; + int enable_sensor; + struct st_timeval start_tv; + int enable_debug; + bool allow_hidden_start_stop; + int32_t timing_budget; + int distance_mode; + int crosstalk_enable; + int output_mode; + bool force_device_on_en; + VL53LX_Error last_error; + int offset_correction_mode; + int smudge_correction_mode; + FixPoint1616_t optical_offset_x; + FixPoint1616_t optical_offset_y; + bool is_xtalk_value_changed; + bool is_calibrating; + struct range_t { + uint32_t cnt; + uint32_t intr; + int poll_cnt; + uint32_t err_cnt; + uint32_t err_tot; + struct st_timeval start_tv; + struct st_timeval comp_tv; + VL53LX_MultiRangingData_t multi_range_data; + VL53LX_MultiRangingData_t tmp_range_data; + VL53LX_AdditionalData_t additional_data; + } meas; + uint32_t flushCount; + int flush_todo_counter; + struct list_head simple_data_reader_list; + struct list_head mz_data_reader_list; + wait_queue_head_t waiter_for_data; + bool is_data_valid; + bool is_delay_allowed; + int reset_state; + VL53LX_UserRoi_t roi_cfg; +}; + +struct i2c_data { + struct i2c_client *client; + struct stmvl53lx_data *vl53lx_data; + struct kref ref; + struct regulator *vdd; + int pwren_gpio; + int xsdn_gpio; + int intr_gpio; + int boot_reg; + struct i2d_data_flags_t { + unsigned pwr_owned:1; + unsigned xsdn_owned:1; + unsigned intr_owned:1; + unsigned intr_started:1; + } io_flag; + int irq; + struct msgtctrl_t { + unsigned unhandled_irq_vec:1; + } msg_flag; +}; + +struct stmvl53lx_waiters { + struct list_head list; + pid_t pid; +}; + +struct stmvl53lx_data *stmvl53lx_dev_table[STMVL53LX_CFG_MAX_DEV]; + +struct stmvl53lx_module_fn_t { + int (*init)(void); + void (*deinit)(void *data); + int (*power_up)(void *data); + int (*power_down)(void *data); + int (*reset_release)(void *data); + int (*reset_hold)(void *data); + int (*start_intr)(void *object, int *poll_mode); + void (*clean_up)(void); + void *(*get)(void *object); + void (*put)(void *object); +}; + +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 struct i2c_client *stm_test_i2c_client; + +static const int tunings[][2] = { +}; + +int stmvl53lx_enable_debug = 1; + +static int force_device; +static int adapter_nb = -1; +static int xsdn_gpio_nb = -1; +static int pwren_gpio_nb = -1; +static int intr_gpio_nb = -1; +static int i2c_addr_nb = STMVL53LX_SLAVE_ADDR; + +static bool force_device_on_en_default = true; + +module_param(force_device_on_en_default, bool, 0444); +MODULE_PARM_DESC(force_device_on_en_default, "select whether force_device_on_en is true or false by default"); + +module_param(force_device, int, 0000); +MODULE_PARM_DESC(force_device, "force device insertion at module init"); + +module_param(adapter_nb, int, 0000); +MODULE_PARM_DESC(adapter_nb, "i2c adapter to use"); + +module_param(i2c_addr_nb, int, 0000); +MODULE_PARM_DESC(i2c_addr_nb, "desired i2c device address on adapter "); + +module_param(xsdn_gpio_nb, int, 0000); +MODULE_PARM_DESC(xsdn_gpio_nb, "select gpio numer to use for vl53lx reset"); + +module_param(pwren_gpio_nb, int, 0000); +MODULE_PARM_DESC(pwren_gpio_nb, "select gpio numer to use for vl53lx power"); + +module_param(intr_gpio_nb, int, 0000); +MODULE_PARM_DESC(intr_gpio_nb, "select gpio numer to use for vl53lx interrupt"); +static DEFINE_MUTEX(dev_addr_change_mutex); +static DEFINE_MUTEX(dev_table_mutex); + +static struct stmvl53lx_module_fn_t stmvl53lx_module_func_tbl; +static int _ctrl_stop(struct stmvl53lx_data *data); +static int reset_hold(struct stmvl53lx_data *data); +static void stmvl53lx_insert_flush_events_lock(struct stmvl53lx_data *data); +VL53LX_Error VL53LX_GetCalibrationData(VL53LX_DEV Dev, VL53LX_CalibrationData_t *pCalibrationData); +VL53LX_Error VL53LX_get_device_results(VL53LX_DEV Dev, VL53LX_DeviceResultsLevel device_results_level, VL53LX_range_results_t *prange_results); +VL53LX_Error VL53LX_poll_for_range_completion(VL53LX_DEV Dev, uint32_t timeout_ms); +VL53LX_Error VL53LX_preset_mode_histogram_short_range( + VL53LX_hist_post_process_config_t *phistpostprocess, + VL53LX_static_config_t *pstatic, + VL53LX_histogram_config_t *phistogram, + VL53LX_general_config_t *pgeneral, + VL53LX_timing_config_t *ptiming, + VL53LX_dynamic_config_t *pdynamic, + VL53LX_system_control_t *psystem, + VL53LX_tuning_parm_storage_t *ptuning_parms, + VL53LX_zone_config_t *pzone_cfg); +static VL53LX_Error SetMeasurementData(VL53LX_DEV Dev, VL53LX_range_results_t *presults, VL53LX_MultiRangingData_t *pMultiRangingData); +void stmvl53lx_put(void *object); +void st_gettimeofday(struct st_timeval *tv); +VL53LX_Error VL53LX_WaitUs(VL53LX_DEV pdev, int32_t wait_us); +VL53LX_Error VL53LX_WaitMs(VL53LX_DEV pdev, int32_t wait_ms); +VL53LX_Error VL53LX_WaitValueMaskEx(VL53LX_DEV pdev, uint32_t timeout_ms, uint16_t index, uint8_t value, uint8_t mask, uint32_t poll_delay_ms); +void VL53LX_init_ll_driver_state(VL53LX_DEV Dev, VL53LX_DeviceState device_state); +VL53LX_Error VL53LX_poll_for_boot_completion(VL53LX_DEV Dev, uint32_t timeout_ms); +VL53LX_Error VL53LX_WaitDeviceBooted(VL53LX_DEV Dev); +uint32_t VL53LX_calc_pll_period_us(uint16_t fast_osc_frequency); +uint8_t VL53LX_decode_vcsel_period(uint8_t vcsel_period_reg); +uint32_t VL53LX_calc_macro_period_us(uint16_t fast_osc_frequency, uint8_t VL53LX_p_005); +uint32_t VL53LX_calc_timeout_us(uint32_t timeout_mclks, uint32_t macro_period_us); +uint32_t VL53LX_decode_timeout(uint16_t encoded_timeout); +uint32_t VL53LX_calc_decoded_timeout_us( + uint16_t timeout_encoded, + uint32_t macro_period_us); +VL53LX_Error VL53LX_get_timeouts_us(VL53LX_DEV Dev, uint32_t *pphasecal_config_timeout_us, uint32_t *pmm_config_timeout_us, uint32_t *prange_config_timeout_us); +uint32_t VL53LX_calc_timeout_mclks(uint32_t timeout_us, uint32_t macro_period_us); +uint16_t VL53LX_encode_timeout(uint32_t timeout_mclks); +uint16_t VL53LX_calc_encoded_timeout(uint32_t timeout_us, uint32_t macro_period_us); +VL53LX_Error VL53LX_calc_timeout_register_values(uint32_t phasecal_config_timeout_us, uint32_t mm_config_timeout_us, uint32_t range_config_timeout_us, uint16_t fast_osc_frequency, VL53LX_general_config_t *pgeneral, VL53LX_timing_config_t *ptiming); +VL53LX_Error VL53LX_set_timeouts_us(VL53LX_DEV Dev, uint32_t phasecal_config_timeout_us, uint32_t mm_config_timeout_us, uint32_t range_config_timeout_us); +VL53LX_Error VL53LX_SetMeasurementTimingBudgetMicroSeconds(VL53LX_DEV Dev, uint32_t MeasurementTimingBudgetMicroSeconds); +VL53LX_Error VL53LX_i2c_encode_system_control(VL53LX_system_control_t *pdata, uint16_t buf_size, uint8_t *pbuffer); +VL53LX_Error VL53LX_WriteMulti(VL53LX_DEV pdev, uint16_t index, uint8_t *pdata, uint32_t count); +VL53LX_Error VL53LX_ReadMulti(VL53LX_DEV pdev, uint16_t index, uint8_t *pdata, uint32_t count); +VL53LX_Error VL53LX_RdByte(VL53LX_DEV pdev, uint16_t index, uint8_t *pdata); +VL53LX_Error VL53LX_WrByte(VL53LX_DEV pdev, uint16_t index, uint8_t data); +VL53LX_Error VL53LX_RdWord(VL53LX_DEV pdev, uint16_t index, uint16_t *pdata); +VL53LX_Error VL53LX_WrWord(VL53LX_DEV pdev, uint16_t index, uint16_t data); +VL53LX_Error VL53LX_WrDWord(VL53LX_DEV pdev, uint16_t index, uint32_t data); +VL53LX_Error VL53LX_RdDWord(VL53LX_DEV pdev, uint16_t index, uint32_t *pdata); +VL53LX_Error VL53LX_set_system_control(VL53LX_DEV Dev, VL53LX_system_control_t *pdata); +void V53L1_init_zone_results_structure(uint8_t active_zones, VL53LX_zone_results_t *pdata); +void V53L1_init_zone_dss_configs(VL53LX_DEV Dev); +VL53LX_Error VL53LX_low_power_auto_data_stop_range(VL53LX_DEV Dev); +VL53LX_Error VL53LX_stop_range(VL53LX_DEV Dev); +VL53LX_Error VL53LX_set_powerforce_register(VL53LX_DEV Dev, uint8_t value); +VL53LX_Error VL53LX_disable_powerforce(VL53LX_DEV Dev); +VL53LX_Error VL53LX_unload_patch(VL53LX_DEV Dev); +VL53LX_Error VL53LX_StopMeasurement(VL53LX_DEV Dev); +void VL53LX_i2c_encode_uint16_t(uint16_t ip_value, uint16_t count, uint8_t *pbuffer); +uint16_t VL53LX_i2c_decode_uint16_t(uint16_t count, uint8_t *pbuffer); +void VL53LX_i2c_encode_int16_t(int16_t ip_value, uint16_t count, uint8_t *pbuffer); +int16_t VL53LX_i2c_decode_int16_t(uint16_t count, uint8_t *pbuffer); +uint32_t VL53LX_i2c_decode_with_mask(uint16_t count, uint8_t *pbuffer, uint32_t bit_mask, uint32_t down_shift, uint32_t offset); +void VL53LX_i2c_encode_int32_t(int32_t ip_value, uint16_t count, uint8_t *pbuffer); +int32_t VL53LX_i2c_decode_int32_t(uint16_t count, uint8_t *pbuffer); +VL53LX_Error VL53LX_i2c_encode_customer_nvm_managed(VL53LX_customer_nvm_managed_t *pdata, uint16_t buf_size, uint8_t *pbuffer); +VL53LX_Error VL53LX_set_customer_nvm_managed(VL53LX_DEV Dev, VL53LX_customer_nvm_managed_t *pdata); +VL53LX_Error VL53LX_disable_xtalk_compensation(VL53LX_DEV Dev); +uint32_t VL53LX_calc_crosstalk_plane_offset_with_margin(uint32_t plane_offset_kcps, int16_t margin_offset_kcps); +uint16_t VL53LX_calc_range_ignore_threshold(uint32_t central_rate, int16_t x_gradient, int16_t y_gradient, uint8_t rate_mult); +VL53LX_Error VL53LX_enable_xtalk_compensation(VL53LX_DEV Dev); +VL53LX_Error VL53LX_SetXTalkCompensationEnable(VL53LX_DEV Dev, uint8_t XTalkCompensationEnable); +VL53LX_Error VL53LX_get_preset_mode_timing_cfg(VL53LX_DEV Dev, VL53LX_DevicePresetModes device_preset_mode, uint16_t *pdss_config__target_total_rate_mcps, uint32_t *pphasecal_config_timeout_us, uint32_t *pmm_config_timeout_us, uint32_t *prange_config_timeout_us); +VL53LX_Error VL53LX_preset_mode_standard_ranging( + VL53LX_static_config_t *pstatic, + VL53LX_histogram_config_t *phistogram, + VL53LX_general_config_t *pgeneral, + VL53LX_timing_config_t *ptiming, + VL53LX_dynamic_config_t *pdynamic, + VL53LX_system_control_t *psystem, + VL53LX_tuning_parm_storage_t *ptuning_parms, + VL53LX_zone_config_t *pzone_cfg); +void VL53LX_init_histogram_config_structure( + uint8_t even_bin0, + uint8_t even_bin1, + uint8_t even_bin2, + uint8_t even_bin3, + uint8_t even_bin4, + uint8_t even_bin5, + uint8_t odd_bin0, + uint8_t odd_bin1, + uint8_t odd_bin2, + uint8_t odd_bin3, + uint8_t odd_bin4, + uint8_t odd_bin5, + VL53LX_histogram_config_t *pdata); +void VL53LX_init_histogram_multizone_config_structure( + uint8_t even_bin0, + uint8_t even_bin1, + uint8_t even_bin2, + uint8_t even_bin3, + uint8_t even_bin4, + uint8_t even_bin5, + uint8_t odd_bin0, + uint8_t odd_bin1, + uint8_t odd_bin2, + uint8_t odd_bin3, + uint8_t odd_bin4, + uint8_t odd_bin5, + VL53LX_histogram_config_t *pdata); +void VL53LX_copy_hist_cfg_to_static_cfg( + VL53LX_histogram_config_t *phistogram, + VL53LX_static_config_t *pstatic, + VL53LX_general_config_t *pgeneral, + VL53LX_timing_config_t *ptiming, + VL53LX_dynamic_config_t *pdynamic); +VL53LX_Error VL53LX_preset_mode_histogram_ranging( + VL53LX_hist_post_process_config_t *phistpostprocess, + VL53LX_static_config_t *pstatic, + VL53LX_histogram_config_t *phistogram, + VL53LX_general_config_t *pgeneral, + VL53LX_timing_config_t *ptiming, + VL53LX_dynamic_config_t *pdynamic, + VL53LX_system_control_t *psystem, + VL53LX_tuning_parm_storage_t *ptuning_parms, + VL53LX_zone_config_t *pzone_cfg); +VL53LX_Error VL53LX_preset_mode_histogram_long_range( + VL53LX_hist_post_process_config_t *phistpostprocess, + VL53LX_static_config_t *pstatic, + VL53LX_histogram_config_t *phistogram, + VL53LX_general_config_t *pgeneral, + VL53LX_timing_config_t *ptiming, + VL53LX_dynamic_config_t *pdynamic, + VL53LX_system_control_t *psystem, + VL53LX_tuning_parm_storage_t *ptuning_parms, + VL53LX_zone_config_t *pzone_cfg); +VL53LX_Error VL53LX_set_inter_measurement_period_ms(VL53LX_DEV Dev, uint32_t inter_measurement_period_ms); +VL53LX_Error VL53LX_preset_mode_histogram_medium_range( + VL53LX_hist_post_process_config_t *phistpostprocess, + VL53LX_static_config_t *pstatic, + VL53LX_histogram_config_t *phistogram, + VL53LX_general_config_t *pgeneral, + VL53LX_timing_config_t *ptiming, + VL53LX_dynamic_config_t *pdynamic, + VL53LX_system_control_t *psystem, + VL53LX_tuning_parm_storage_t *ptuning_parms, + VL53LX_zone_config_t *pzone_cfg); +VL53LX_Error VL53LX_set_preset_mode(VL53LX_DEV Dev, VL53LX_DevicePresetModes device_preset_mode, uint16_t dss_config__target_total_rate_mcps, uint32_t phasecal_config_timeout_us, uint32_t mm_config_timeout_us, uint32_t range_config_timeout_us, uint32_t inter_measurement_period_ms); +VL53LX_Error VL53LX_SetDistanceMode(VL53LX_DEV Dev, VL53LX_DistanceModes DistanceMode); +VL53LX_Error VL53LX_set_offset_correction_mode(VL53LX_DEV Dev, VL53LX_OffsetCorrectionMode offset_cor_mode); +VL53LX_Error VL53LX_SetOffsetCorrectionMode(VL53LX_DEV Dev, VL53LX_OffsetCorrectionModes OffsetCorrectionMode); +VL53LX_Error VL53LX_dynamic_xtalk_correction_disable(VL53LX_DEV Dev); +VL53LX_Error VL53LX_dynamic_xtalk_correction_apply_disable(VL53LX_DEV Dev); +VL53LX_Error VL53LX_dynamic_xtalk_correction_single_apply_disable(VL53LX_DEV Dev); +VL53LX_Error VL53LX_dynamic_xtalk_correction_enable(VL53LX_DEV Dev); +VL53LX_Error VL53LX_dynamic_xtalk_correction_apply_enable(VL53LX_DEV Dev); +VL53LX_Error VL53LX_dynamic_xtalk_correction_single_apply_enable(VL53LX_DEV Dev); +VL53LX_Error VL53LX_SmudgeCorrectionEnable(VL53LX_DEV Dev, VL53LX_SmudgeCorrectionModes Mode); +VL53LX_Error VL53LX_init_zone_config_histogram_bins(VL53LX_zone_config_t *pdata); +VL53LX_Error VL53LX_set_zone_config(VL53LX_DEV Dev, VL53LX_zone_config_t *pzone_cfg); +VL53LX_Error VL53LX_SetUserROI(VL53LX_DEV Dev, VL53LX_UserRoi_t *pRoi); +VL53LX_Error VL53LX_enable_powerforce(VL53LX_DEV Dev); +VL53LX_Error VL53LX_get_tuning_parm(VL53LX_DEV Dev, VL53LX_TuningParms tuning_parm_key, int32_t *ptuning_parm_value); +VL53LX_Error VL53LX_load_patch(VL53LX_DEV Dev); +void VL53LX_encode_row_col(uint8_t row, uint8_t col, uint8_t *pspad_number); +void VL53LX_encode_zone_size(uint8_t width, uint8_t height, uint8_t *pencoded_xy_size); +VL53LX_Error VL53LX_set_user_zone(VL53LX_DEV Dev, VL53LX_user_zone_t *puser_zone); +VL53LX_Error VL53LX_set_zone_dss_config(VL53LX_DEV Dev, VL53LX_zone_private_dyn_cfg_t *pzone_dyn_cfg); +VL53LX_Error VL53LX_save_cfg_data(VL53LX_DEV Dev); +VL53LX_Error VL53LX_i2c_encode_static_nvm_managed(VL53LX_static_nvm_managed_t *pdata, uint16_t buf_size, uint8_t *pbuffer); +VL53LX_Error VL53LX_i2c_decode_static_nvm_managed(uint16_t buf_size, uint8_t *pbuffer, VL53LX_static_nvm_managed_t *pdata); +VL53LX_Error VL53LX_i2c_encode_static_config(VL53LX_static_config_t *pdata, uint16_t buf_size, uint8_t *pbuffer); +VL53LX_Error VL53LX_i2c_encode_general_config(VL53LX_general_config_t *pdata, uint16_t buf_size, uint8_t *pbuffer); +void VL53LX_i2c_encode_uint32_t(uint32_t ip_value, uint16_t count, uint8_t *pbuffer); +uint32_t VL53LX_i2c_decode_uint32_t(uint16_t count, uint8_t *pbuffer); +VL53LX_Error VL53LX_i2c_encode_timing_config(VL53LX_timing_config_t *pdata, uint16_t buf_size, uint8_t *pbuffer); +VL53LX_Error VL53LX_i2c_encode_dynamic_config(VL53LX_dynamic_config_t *pdata, uint16_t buf_size, uint8_t *pbuffer); +VL53LX_Error VL53LX_update_internal_stream_counters(VL53LX_DEV Dev, uint8_t external_stream_count, uint8_t *pinternal_stream_count, uint8_t *pinternal_stream_count_val); +VL53LX_Error VL53LX_update_ll_driver_rd_state(VL53LX_DEV Dev); +VL53LX_Error VL53LX_update_ll_driver_cfg_state(VL53LX_DEV Dev); +VL53LX_Error VL53LX_init_and_start_range(VL53LX_DEV Dev, uint8_t measurement_mode, VL53LX_DeviceConfigLevel device_config_level); +VL53LX_Error VL53LX_StartMeasurement(VL53LX_DEV Dev); +VL53LX_Error VL53LX_WaitMeasurementDataReady(VL53LX_DEV Dev); +VL53LX_Error VL53LX_is_new_data_ready(VL53LX_DEV Dev, uint8_t *pready); +VL53LX_Error VL53LX_GetMeasurementDataReady(VL53LX_DEV Dev, uint8_t *pMeasurementDataReady); +long stmvl53lx_tv_dif(struct st_timeval *pstart_tv, struct st_timeval *pstop_tv); +VL53LX_Error VL53LX_GetMultiRangingData(VL53LX_DEV Dev, VL53LX_MultiRangingData_t *pMultiRangingData); +VL53LX_Error VL53LX_get_histogram_debug_data(VL53LX_DEV Dev, VL53LX_histogram_bin_data_t *pdata); +VL53LX_Error VL53LX_get_additional_data(VL53LX_DEV Dev, VL53LX_additional_data_t *pdata); +VL53LX_Error VL53LX_GetAdditionalData(VL53LX_DEV Dev, VL53LX_AdditionalData_t *pAdditionalData); +VL53LX_Error VL53LX_clear_interrupt_and_enable_next_range(VL53LX_DEV Dev, uint8_t measurement_mode); +VL53LX_Error VL53LX_ClearInterruptAndStartMeasurement(VL53LX_DEV Dev); +int stmvl53lx_intr_handler(struct stmvl53lx_data *data); +VL53LX_Error VL53LX_set_tuning_parm(VL53LX_DEV Dev, VL53LX_TuningParms tuning_parm_key, int32_t tuning_parm_value); +VL53LX_Error VL53LX_SetTuningParameter(VL53LX_DEV Dev, uint16_t TuningParameterId, int32_t TuningParameterValue); +VL53LX_Error VL53LX_GetTuningParameter(VL53LX_DEV Dev, uint16_t TuningParameterId, int32_t *pTuningParameterValue); +VL53LX_Error VL53LX_set_part_to_part_data(VL53LX_DEV Dev, VL53LX_calibration_data_t *pcal_data); +VL53LX_Error VL53LX_get_current_xtalk_settings(VL53LX_DEV Dev, VL53LX_xtalk_calibration_results_t *pxtalk); +VL53LX_Error VL53LX_set_current_xtalk_settings(VL53LX_DEV Dev, VL53LX_xtalk_calibration_results_t *pxtalk); +VL53LX_Error VL53LX_SetCalibrationData(VL53LX_DEV Dev, VL53LX_CalibrationData_t *pCalibrationData); +VL53LX_Error VL53LX_get_part_to_part_data(VL53LX_DEV Dev, VL53LX_calibration_data_t *pcal_data); +void VL53LX_init_version(VL53LX_DEV Dev); +VL53LX_Error VL53LX_get_static_nvm_managed(VL53LX_DEV Dev, VL53LX_static_nvm_managed_t *pdata); +VL53LX_Error VL53LX_i2c_decode_customer_nvm_managed(uint16_t buf_size, uint8_t *pbuffer, VL53LX_customer_nvm_managed_t *pdata); +VL53LX_Error VL53LX_get_customer_nvm_managed(VL53LX_DEV Dev, VL53LX_customer_nvm_managed_t *pdata); +VL53LX_Error VL53LX_i2c_decode_nvm_copy_data(uint16_t buf_size, uint8_t *pbuffer, VL53LX_nvm_copy_data_t *pdata); +VL53LX_Error VL53LX_get_nvm_copy_data(VL53LX_DEV Dev, VL53LX_nvm_copy_data_t *pdata); +void VL53LX_copy_rtn_good_spads_to_buffer(VL53LX_nvm_copy_data_t *pdata, uint8_t *pbuffer); +VL53LX_Error VL53LX_set_firmware_enable_register(VL53LX_DEV Dev, uint8_t value); +VL53LX_Error VL53LX_disable_firmware(VL53LX_DEV Dev); +VL53LX_Error VL53LX_nvm_enable(VL53LX_DEV Dev, uint16_t nvm_ctrl_pulse_width, int32_t nvm_power_up_delay_us); +VL53LX_Error VL53LX_nvm_read(VL53LX_DEV Dev, uint8_t start_address, uint8_t count, uint8_t *pdata); +VL53LX_Error VL53LX_enable_firmware(VL53LX_DEV Dev); +VL53LX_Error VL53LX_nvm_disable(VL53LX_DEV Dev); +VL53LX_Error VL53LX_read_nvm_raw_data(VL53LX_DEV Dev, uint8_t start_address, uint8_t count, uint8_t *pnvm_raw_data); +VL53LX_Error VL53LX_nvm_decode_optical_centre(uint16_t buf_size, uint8_t *pbuffer, VL53LX_optical_centre_t *pdata); +VL53LX_Error VL53LX_read_nvm_optical_centre(VL53LX_DEV Dev, VL53LX_optical_centre_t *pcentre); +VL53LX_Error VL53LX_nvm_decode_cal_peak_rate_map(uint16_t buf_size, uint8_t *pbuffer, VL53LX_cal_peak_rate_map_t *pdata); +VL53LX_Error VL53LX_read_nvm_cal_peak_rate_map(VL53LX_DEV Dev, VL53LX_cal_peak_rate_map_t *pcal_data); +VL53LX_Error VL53LX_nvm_decode_additional_offset_cal_data(uint16_t buf_size, uint8_t *pbuffer, VL53LX_additional_offset_cal_data_t *pdata); +VL53LX_Error VL53LX_read_nvm_additional_offset_cal_data(VL53LX_DEV Dev, VL53LX_additional_offset_cal_data_t *pcal_data); +void VL53LX_spad_number_to_byte_bit_index(uint8_t spad_number, uint8_t *pbyte_index, uint8_t *pbit_index, uint8_t *pbit_mask); +uint8_t VL53LX_is_aperture_location(uint8_t row, uint8_t col); +void VL53LX_decode_row_col(uint8_t spad_number, uint8_t *prow, uint8_t *pcol); +void VL53LX_decode_zone_size(uint8_t encoded_xy_size, uint8_t *pwidth, uint8_t *pheight); +void VL53LX_decode_zone_limits(uint8_t encoded_xy_centre, uint8_t encoded_xy_size, int16_t *px_ll, int16_t *py_ll, int16_t *px_ur, int16_t *py_ur); +void VL53LX_calc_mm_effective_spads( + uint8_t encoded_mm_roi_centre, + uint8_t encoded_mm_roi_size, + uint8_t encoded_zone_centre, + uint8_t encoded_zone_size, + uint8_t *pgood_spads, + uint16_t aperture_attenuation, + uint16_t *pmm_inner_effective_spads, + uint16_t *pmm_outer_effective_spads); +VL53LX_Error VL53LX_nvm_decode_fmt_range_results_data(uint16_t buf_size, uint8_t *pbuffer, VL53LX_decoded_nvm_fmt_range_data_t *pdata); +VL53LX_Error VL53LX_read_nvm_fmt_range_results_data(VL53LX_DEV Dev, uint16_t range_results_select, VL53LX_decoded_nvm_fmt_range_data_t *prange_data); +VL53LX_Error VL53LX_get_mode_mitigation_roi(VL53LX_DEV Dev, VL53LX_user_zone_t *pmm_roi); +VL53LX_Error VL53LX_read_p2p_data(VL53LX_DEV Dev); +VL53LX_Error VL53LX_init_refspadchar_config_struct(VL53LX_refspadchar_config_t *pdata); +VL53LX_Error VL53LX_init_ssc_config_struct(VL53LX_ssc_config_t *pdata); +VL53LX_Error VL53LX_init_xtalk_config_struct(VL53LX_customer_nvm_managed_t *pnvm, VL53LX_xtalk_config_t *pdata); +VL53LX_Error VL53LX_init_xtalk_extract_config_struct(VL53LX_xtalkextract_config_t *pdata); +VL53LX_Error VL53LX_init_offset_cal_config_struct(VL53LX_offsetcal_config_t *pdata); +VL53LX_Error VL53LX_init_zone_cal_config_struct(VL53LX_zonecal_config_t *pdata); +VL53LX_Error VL53LX_init_hist_post_process_config_struct(uint8_t xtalk_compensation_enable, VL53LX_hist_post_process_config_t *pdata); +VL53LX_Error VL53LX_init_hist_gen3_dmax_config_struct(VL53LX_hist_gen3_dmax_config_t *pdata); +VL53LX_Error VL53LX_init_tuning_parm_storage_struct(VL53LX_tuning_parm_storage_t *pdata); +void VL53LX_init_histogram_bin_data_struct(int32_t bin_value, uint16_t VL53LX_p_021, VL53LX_histogram_bin_data_t *pdata); +void VL53LX_init_xtalk_bin_data_struct(uint32_t bin_value, uint16_t VL53LX_p_021, VL53LX_xtalk_histogram_shape_t *pdata); +VL53LX_Error VL53LX_xtalk_cal_data_init(VL53LX_DEV Dev); +VL53LX_Error VL53LX_dynamic_xtalk_correction_output_init(VL53LX_LLDriverResults_t *pres); +VL53LX_Error VL53LX_dynamic_xtalk_correction_data_init(VL53LX_DEV Dev); +VL53LX_Error VL53LX_low_power_auto_data_init(VL53LX_DEV Dev); +VL53LX_Error VL53LX_data_init(VL53LX_DEV Dev, uint8_t read_p2p_data); +VL53LX_Error VL53LX_set_dmax_mode(VL53LX_DEV Dev, VL53LX_DeviceDmaxMode dmax_mode); +VL53LX_Error VL53LX_DataInit(VL53LX_DEV Dev); +VL53LX_Error VL53LX_get_zone_config(VL53LX_DEV Dev, VL53LX_zone_config_t *pzone_cfg); +VL53LX_Error VL53LX_GetUserROI(VL53LX_DEV Dev, VL53LX_UserRoi_t *pRoi); +VL53LX_Error VL53LX_GetDeviceInfo(VL53LX_DEV Dev, VL53LX_DeviceInfo_t *pVL53LX_DeviceInfo); +VL53LX_Error VL53LX_GetOpticalCenter(VL53LX_DEV Dev, FixPoint1616_t *pOpticalCenterX, FixPoint1616_t *pOpticalCenterY); +void VL53LX_hist_get_bin_sequence_config(VL53LX_DEV Dev, VL53LX_histogram_bin_data_t *pdata); +uint32_t VL53LX_duration_maths(uint32_t pll_period_us, uint32_t vcsel_parm_pclks, uint32_t window_vclks, uint32_t elapsed_mclks); +void VL53LX_hist_calc_zero_distance_phase(VL53LX_histogram_bin_data_t *pdata); +void VL53LX_hist_estimate_ambient_from_ambient_bins(VL53LX_histogram_bin_data_t *pdata); +VL53LX_Error VL53LX_get_histogram_bin_data(VL53LX_DEV Dev, VL53LX_histogram_bin_data_t *pdata); +VL53LX_Error VL53LX_hist_copy_and_scale_ambient_info(VL53LX_zone_hist_info_t *pidata, VL53LX_histogram_bin_data_t *podata); +VL53LX_Error VL53LX_compute_histo_merge_nb(VL53LX_DEV Dev, uint8_t *histo_merge_nb); +void VL53LX_hist_combine_mm1_mm2_offsets( + int16_t mm1_offset_mm, + int16_t mm2_offset_mm, + uint8_t encoded_mm_roi_centre, + uint8_t encoded_mm_roi_size, + uint8_t encoded_zone_centre, + uint8_t encoded_zone_size, + VL53LX_additional_offset_cal_data_t *pcal_data, + uint8_t *pgood_spads, + uint16_t aperture_attenuation, + int16_t *prange_offset_mm); +void VL53LX_calc_max_effective_spads(uint8_t encoded_zone_centre, uint8_t encoded_zone_size, uint8_t *pgood_spads, uint16_t aperture_attenuation, uint16_t *pmax_effective_spads); +VL53LX_Error VL53LX_get_dmax_calibration_data(VL53LX_DEV Dev, VL53LX_DeviceDmaxMode dmax_mode, VL53LX_dmax_calibration_data_t *pdmax_cal); +VL53LX_Error VL53LX_f_031(VL53LX_histogram_bin_data_t *pidata, VL53LX_histogram_bin_data_t *podata); +VL53LX_Error VL53LX_f_032(uint32_t mean_offset, int16_t xgradient, int16_t ygradient, int8_t centre_offset_x, int8_t centre_offset_y, uint16_t roi_effective_spads, uint8_t roi_centre_spad, uint8_t roi_xy_size, uint32_t *xtalk_rate_kcps); +VL53LX_Error VL53LX_f_033(VL53LX_histogram_bin_data_t *phist_data, VL53LX_xtalk_histogram_shape_t *pxtalk_data, uint32_t xtalk_rate_kcps, VL53LX_histogram_bin_data_t *pxtalkcount_data); +void VL53LX_copy_xtalk_bin_data_to_histogram_data_struct(VL53LX_xtalk_histogram_shape_t *pxtalk, VL53LX_histogram_bin_data_t *phist); +void VL53LX_f_003(VL53LX_hist_gen3_algo_private_data_t *palgo); +void VL53LX_hist_find_min_max_bin_values(VL53LX_histogram_bin_data_t *pdata); +uint32_t VL53LX_isqrt(uint32_t num); +void VL53LX_hist_estimate_ambient_from_thresholded_bins(int32_t ambient_threshold_sigma, VL53LX_histogram_bin_data_t *pdata); +void VL53LX_hist_remove_ambient_bins(VL53LX_histogram_bin_data_t *pdata); +int8_t VL53LX_f_030(VL53LX_histogram_bin_data_t *pdata1, VL53LX_histogram_bin_data_t *pdata2); +void VL53LX_f_005(VL53LX_histogram_bin_data_t *pxtalk, VL53LX_histogram_bin_data_t *pbins, VL53LX_histogram_bin_data_t *pxtalk_realigned); +uint16_t VL53LX_rate_maths(int32_t VL53LX_p_018, uint32_t time_us); +uint32_t VL53LX_events_per_spad_maths(int32_t VL53LX_p_010, uint16_t num_spads, uint32_t duration); +uint32_t VL53LX_f_002(uint32_t events_threshold, uint32_t ref_signal_events, uint32_t ref_distance_mm, uint32_t signal_thresh_sigma); +VL53LX_Error VL53LX_f_001( + uint16_t target_reflectance, + VL53LX_dmax_calibration_data_t *pcal, + VL53LX_hist_gen3_dmax_config_t *pcfg, + VL53LX_histogram_bin_data_t *pbins, + VL53LX_hist_gen3_dmax_private_data_t *pdata, + int16_t *pambient_dmax_mm); +VL53LX_Error VL53LX_f_006( + uint16_t ambient_threshold_events_scaler, + int32_t ambient_threshold_sigma, + int32_t min_ambient_threshold_events, + uint8_t algo__crosstalk_compensation_enable, + VL53LX_histogram_bin_data_t *pbins, + VL53LX_histogram_bin_data_t *pxtalk, + VL53LX_hist_gen3_algo_private_data_t *palgo); +VL53LX_Error VL53LX_f_007(VL53LX_hist_gen3_algo_private_data_t *palgo); +VL53LX_Error VL53LX_f_008(VL53LX_hist_gen3_algo_private_data_t *palgo); +VL53LX_Error VL53LX_f_009(VL53LX_hist_gen3_algo_private_data_t *palgo); +VL53LX_Error VL53LX_f_010(uint8_t pulse_no, VL53LX_histogram_bin_data_t *pbins, VL53LX_hist_gen3_algo_private_data_t *palgo); +VL53LX_Error VL53LX_f_011( + uint8_t pulse_no, + VL53LX_histogram_bin_data_t *pbins, + VL53LX_hist_gen3_algo_private_data_t *palgo, + int32_t pad_value, + VL53LX_histogram_bin_data_t *ppulse); +VL53LX_Error VL53LX_f_014( + uint8_t bin, + uint8_t sigma_estimator__sigma_ref_mm, + uint8_t VL53LX_p_030, + uint8_t VL53LX_p_051, + uint8_t crosstalk_compensation_enable, + VL53LX_histogram_bin_data_t *phist_data_ap, + VL53LX_histogram_bin_data_t *phist_data_zp, + VL53LX_histogram_bin_data_t *pxtalk_hist, + uint16_t *psigma_est); +VL53LX_Error VL53LX_f_015(uint8_t pulse_no, uint8_t clip_events, VL53LX_histogram_bin_data_t *pbins, VL53LX_hist_gen3_algo_private_data_t *palgo); +VL53LX_Error VL53LX_f_016(VL53LX_HistTargetOrder target_order, VL53LX_hist_gen3_algo_private_data_t *palgo); +void VL53LX_f_017( + uint8_t range_id, + uint8_t valid_phase_low, + uint8_t valid_phase_high, + uint16_t sigma_thres, + VL53LX_histogram_bin_data_t *pbins, + VL53LX_hist_pulse_data_t *ppulse, + VL53LX_range_data_t *pdata); +VL53LX_Error VL53LX_f_018( + uint16_t vcsel_width, + uint16_t fast_osc_frequency, + uint32_t total_periods_elapsed, + uint16_t VL53LX_p_004, + VL53LX_range_data_t *pdata, + uint8_t histo_merge_nb); +void VL53LX_f_019(uint16_t gain_factor, int16_t range_offset_mm, VL53LX_range_data_t *pdata); +VL53LX_Error VL53LX_f_020(int16_t VL53LX_p_019, int16_t VL53LX_p_024, uint8_t VL53LX_p_030, uint8_t clip_events, VL53LX_histogram_bin_data_t *pbins, uint32_t *pphase); +void VL53LX_f_022(uint8_t VL53LX_p_032, uint8_t filter_woi, VL53LX_histogram_bin_data_t *pbins, int32_t *pa, int32_t *pb, int32_t *pc); +VL53LX_Error VL53LX_f_023( + uint8_t sigma_estimator__sigma_ref_mm, + uint32_t VL53LX_p_007, + uint32_t VL53LX_p_032, + uint32_t VL53LX_p_001, + uint32_t a_zp, + uint32_t c_zp, + uint32_t bx, + uint32_t ax_zp, + uint32_t cx_zp, + uint32_t VL53LX_p_028, + uint16_t fast_osc_frequency, + uint16_t *psigma_est); +VL53LX_Error VL53LX_f_025( + VL53LX_dmax_calibration_data_t *pdmax_cal, + VL53LX_hist_gen3_dmax_config_t *pdmax_cfg, + VL53LX_hist_post_process_config_t *ppost_cfg, + VL53LX_histogram_bin_data_t *pbins_input, + VL53LX_histogram_bin_data_t *pxtalk, + VL53LX_hist_gen3_algo_private_data_t *palgo3, + VL53LX_hist_gen4_algo_filtered_data_t *pfiltered, + VL53LX_hist_gen3_dmax_private_data_t *pdmax_algo, + VL53LX_range_results_t *presults, + uint8_t histo_merge_nb); +VL53LX_Error VL53LX_f_026( + uint8_t pulse_no, + VL53LX_histogram_bin_data_t *ppulse, + VL53LX_hist_gen3_algo_private_data_t *palgo3, + VL53LX_hist_gen4_algo_filtered_data_t *pfiltered); +VL53LX_Error VL53LX_f_027(uint8_t pulse_no, uint16_t noise_threshold, VL53LX_hist_gen4_algo_filtered_data_t *pfiltered, VL53LX_hist_gen3_algo_private_data_t *palgo3); +VL53LX_Error VL53LX_f_028( + uint8_t bin, + int32_t VL53LX_p_007, + int32_t VL53LX_p_032, + int32_t VL53LX_p_001, + int32_t ax, + int32_t bx, + int32_t cx, + int32_t VL53LX_p_028, + uint8_t VL53LX_p_030, + uint32_t *pmean_phase); +uint32_t VL53LX_calc_pll_period_mm(uint16_t fast_osc_frequency); +int32_t VL53LX_range_maths( + uint16_t fast_osc_frequency, + uint16_t VL53LX_p_014, + uint16_t zero_distance_phase, + uint8_t fractional_bits, + int32_t gain_factor, + int32_t range_offset_mm); +uint16_t VL53LX_rate_per_spad_maths(uint32_t frac_bits, uint32_t peak_count_rate, uint16_t num_spads, uint32_t max_output_value); +VL53LX_Error VL53LX_hist_process_data( + VL53LX_dmax_calibration_data_t *pdmax_cal, + VL53LX_hist_gen3_dmax_config_t *pdmax_cfg, + VL53LX_hist_post_process_config_t *ppost_cfg, + VL53LX_histogram_bin_data_t *pbins_input, + VL53LX_xtalk_histogram_data_t *pxtalk_shape, + uint8_t *pArea1, + uint8_t *pArea2, + VL53LX_range_results_t *presults, + uint8_t *HistMergeNumber); +VL53LX_Error VL53LX_hist_wrap_dmax(VL53LX_hist_post_process_config_t *phistpostprocess, VL53LX_histogram_bin_data_t *pcurrent, int16_t *pwrap_dmax_mm); +VL53LX_Error VL53LX_ipp_hist_process_data( + VL53LX_DEV Dev, + VL53LX_dmax_calibration_data_t *pdmax_cal, + VL53LX_hist_gen3_dmax_config_t *pdmax_cfg, + VL53LX_hist_post_process_config_t *ppost_cfg, + VL53LX_histogram_bin_data_t *pbins, + VL53LX_xtalk_histogram_data_t *pxtalk, + uint8_t *pArea1, + uint8_t *pArea2, + uint8_t *phisto_merge_nb, + VL53LX_range_results_t *presults); +VL53LX_Error VL53LX_hist_events_consistency_check( + uint8_t event_sigma, + uint16_t min_effective_spad_count, + VL53LX_zone_hist_info_t *phist_prev, + VL53LX_object_data_t *prange_prev, + VL53LX_range_data_t *prange_curr, + int32_t *pevents_tolerance, + int32_t *pevents_delta, + VL53LX_DeviceError *prange_status); +VL53LX_Error VL53LX_hist_phase_consistency_check(VL53LX_DEV Dev, VL53LX_zone_hist_info_t *phist_prev, VL53LX_zone_objects_t *prange_prev, VL53LX_range_results_t *prange_curr); +VL53LX_Error VL53LX_hist_merged_pulse_check(int16_t min_max_tolerance_mm, VL53LX_range_data_t *pdata, VL53LX_DeviceError *prange_status); +VL53LX_Error VL53LX_hist_xmonitor_consistency_check(VL53LX_DEV Dev, VL53LX_zone_hist_info_t *phist_prev, VL53LX_zone_objects_t *prange_prev, VL53LX_range_data_t *prange_curr); +void VL53LX_init_system_results(VL53LX_system_results_t *pdata); +void VL53LX_hist_copy_results_to_sys_and_core( + VL53LX_histogram_bin_data_t *pbins, + VL53LX_range_results_t *phist, + VL53LX_system_results_t *psys, + VL53LX_core_results_t *pcore); +VL53LX_Error VL53LX_dynamic_zone_update(VL53LX_DEV Dev, VL53LX_range_results_t *presults); +void VL53LX_copy_hist_bins_to_static_cfg(VL53LX_histogram_config_t *phistogram, VL53LX_static_config_t *pstatic, VL53LX_timing_config_t *ptiming); +VL53LX_Error VL53LX_multizone_hist_bins_update(VL53LX_DEV Dev); +VL53LX_Error VL53LX_dynamic_xtalk_correction_calc_required_samples(VL53LX_DEV Dev); +VL53LX_Error VL53LX_dynamic_xtalk_correction_calc_new_xtalk( + VL53LX_DEV Dev, + uint32_t xtalk_offset_out, + VL53LX_smudge_corrector_config_t *pconfig, + VL53LX_smudge_corrector_data_t *pout, + uint8_t add_smudge, + uint8_t soft_update + ); +VL53LX_Error VL53LX_dynamic_xtalk_correction_corrector(VL53LX_DEV Dev); +VL53LX_Error VL53LX_i2c_decode_debug_results(uint16_t buf_size, uint8_t *pbuffer, VL53LX_debug_results_t *pdata); +VL53LX_Error VL53LX_i2c_decode_core_results(uint16_t buf_size, uint8_t *pbuffer, VL53LX_core_results_t *pdata); +VL53LX_Error VL53LX_i2c_decode_system_results(uint16_t buf_size, uint8_t *pbuffer, VL53LX_system_results_t *pdata); +VL53LX_Error VL53LX_get_measurement_results(VL53LX_DEV Dev, VL53LX_DeviceResultsLevel device_results_level); +void VL53LX_copy_sys_and_core_results_to_range_results(int32_t gain_factor, VL53LX_system_results_t *psys, VL53LX_core_results_t *pcore, VL53LX_range_results_t *presults); +VL53LX_Error VL53LX_low_power_auto_setup_manual_calibration(VL53LX_DEV Dev); +VL53LX_Error VL53LX_low_power_auto_update_DSS(VL53LX_DEV Dev); +VL53LX_Error VL53LX_check_ll_driver_rd_state(VL53LX_DEV Dev); +VL53LX_Error VL53LX_set_ref_spad_char_config( + VL53LX_DEV Dev, + uint8_t vcsel_period_a, + uint32_t phasecal_timeout_us, + uint16_t total_rate_target_mcps, + uint16_t max_count_rate_rtn_limit_mcps, + uint16_t min_count_rate_rtn_limit_mcps, + uint16_t fast_osc_frequency); +VL53LX_Error VL53LX_start_test(VL53LX_DEV Dev, uint8_t test_mode__ctrl); +VL53LX_Error VL53LX_wait_for_test_completion(VL53LX_DEV Dev); +VL53LX_Error VL53LX_clear_interrupt(VL53LX_DEV Dev); +VL53LX_Error VL53LX_run_device_test(VL53LX_DEV Dev, VL53LX_DeviceTestMode device_test_mode); +VL53LX_Error VL53LX_run_ref_spad_char(VL53LX_DEV Dev, VL53LX_Error *pcal_status); +VL53LX_Error VL53LX_PerformRefSpadManagement(VL53LX_DEV Dev); +void VL53LX_hist_xtalk_extract_data_init(VL53LX_hist_xtalk_extract_data_t *pxtalk_data); +VL53LX_Error VL53LX_wait_for_range_completion(VL53LX_DEV Dev); +VL53LX_Error VL53LX_hist_xtalk_extract_calc_window( + int16_t target_distance_mm, + uint16_t target_width_oversize, + VL53LX_histogram_bin_data_t *phist_bins, + VL53LX_hist_xtalk_extract_data_t *pxtalk_data); +VL53LX_Error VL53LX_hist_xtalk_extract_calc_event_sums(VL53LX_histogram_bin_data_t *phist_bins, VL53LX_hist_xtalk_extract_data_t *pxtalk_data); +VL53LX_Error VL53LX_hist_xtalk_extract_update( + int16_t target_distance_mm, + uint16_t target_width_oversize, + VL53LX_histogram_bin_data_t *phist_bins, + VL53LX_hist_xtalk_extract_data_t *pxtalk_data); +VL53LX_Error VL53LX_hist_xtalk_extract_calc_rate_per_spad(VL53LX_hist_xtalk_extract_data_t *pxtalk_data); +VL53LX_Error VL53LX_hist_xtalk_extract_calc_shape(VL53LX_hist_xtalk_extract_data_t *pxtalk_data, VL53LX_xtalk_histogram_shape_t *pxtalk_shape); +VL53LX_Error VL53LX_hist_xtalk_extract_fini( + VL53LX_histogram_bin_data_t *phist_bins, + VL53LX_hist_xtalk_extract_data_t *pxtalk_data, + VL53LX_xtalk_calibration_results_t *pxtalk_cal, + VL53LX_xtalk_histogram_shape_t *pxtalk_shape); +VL53LX_Error VL53LX_run_hist_xtalk_extraction(VL53LX_DEV Dev, int16_t cal_distance_mm, VL53LX_Error *pcal_status); +VL53LX_Error VL53LX_PerformXTalkCalibration(VL53LX_DEV Dev); +VL53LX_Error VL53LX_PerformOffsetSimpleCalibration(VL53LX_DEV Dev, int32_t CalDistanceMilliMeter); +VL53LX_Error VL53LX_GetDistanceMode(VL53LX_DEV Dev, VL53LX_DistanceModes *pDistanceMode); +VL53LX_Error VL53LX_PerformOffsetPerVcselCalibration(VL53LX_DEV Dev, int32_t CalDistanceMilliMeter); +VL53LX_Error VL53LX_PerformOffsetZeroDistanceCalibration(VL53LX_DEV Dev); +int stmvl53lx_setup(struct stmvl53lx_data *data); +void stmvl53lx_cleanup(struct stmvl53lx_data *data); +void stmvl53lx_pm_suspend_stop(struct stmvl53lx_data *data); +int stmvl53lx_init_i2c(void); +void stmvl53lx_exit_i2c(void *i2c_object); +int stmvl53lx_power_up_i2c(void *object); +int stmvl53lx_power_down_i2c(void *i2c_object); +int stmvl53lx_reset_release_i2c(void *i2c_object); +int stmvl53lx_reset_hold_i2c(void *i2c_object); +void stmvl53lx_clean_up_i2c(void); +int stmvl53lx_start_intr(void *object, int *poll_mode); +void *stmvl53lx_get(void *object); + +void st_gettimeofday(struct st_timeval *tv) +{ + struct timespec64 now; + + ktime_get_real_ts64(&now); + tv->tv_sec = now.tv_sec; + tv->tv_usec = now.tv_nsec/1000; +} + +#if STMVL53LX_LOG_CCI_TIMING +static uint32_t tv_elapsed_us(struct st_timeval *tv) +{ + struct st_timeval now; + + st_gettimeofday(&now); + return (now.tv_sec - tv->tv_sec) * 1000000 + (now.tv_usec - tv->tv_usec); +} + +#define cci_access_var struct st_timeval cci_log_start_tv +#define cci_access_start() st_gettimeofday(&cci_log_start_tv) +#define cci_access_over(fmt, ...) printk("cci_timing %d us" fmt "\n", tv_elapsed_us(&cci_log_start_tv), ##__VA_ARGS__) +#else +#define cci_access_var +#define cci_access_start(...) ((void)0) +#define cci_access_over(...) ((void)0) +#endif + +static int get_xsdn(struct device *dev, struct i2c_data *i2c_data) +{ + int rc = 0; + + i2c_data->io_flag.xsdn_owned = 0; + if (i2c_data->xsdn_gpio == -1) { + vl53lx_errmsg("reset gpio is required"); + rc = -ENODEV; + goto no_gpio; + } + + vl53lx_dbgmsg("request xsdn_gpio %d", i2c_data->xsdn_gpio); + rc = gpio_request(i2c_data->xsdn_gpio, "vl53lx_xsdn"); + if (rc) { + vl53lx_errmsg("fail to acquire xsdn %d", rc); + goto request_failed; + } + + rc = gpio_direction_output(i2c_data->xsdn_gpio, 0); + if (rc) { + vl53lx_errmsg("fail to configure xsdn as output %d", rc); + goto direction_failed; + } + i2c_data->io_flag.xsdn_owned = 1; + + return rc; + +direction_failed: + gpio_free(i2c_data->xsdn_gpio); + +request_failed: +no_gpio: + return rc; +} + +static void put_xsdn(struct i2c_data *i2c_data) +{ + if (i2c_data->io_flag.xsdn_owned) { + vl53lx_dbgmsg("release xsdn_gpio %d", i2c_data->xsdn_gpio); + gpio_free(i2c_data->xsdn_gpio); + i2c_data->io_flag.xsdn_owned = 0; + } + i2c_data->xsdn_gpio = -1; +} + +static int get_pwren(struct device *dev, struct i2c_data *i2c_data) +{ + int rc = 0; + + i2c_data->io_flag.pwr_owned = 0; + if (i2c_data->pwren_gpio == -1) { + vl53lx_wanrmsg("pwren gpio disable"); + goto no_gpio; + } + + vl53lx_dbgmsg("request pwren_gpio %d", i2c_data->pwren_gpio); + rc = gpio_request(i2c_data->pwren_gpio, "vl53lx_pwren"); + if (rc) { + vl53lx_errmsg("fail to acquire pwren %d", rc); + goto request_failed; + } + + rc = gpio_direction_output(i2c_data->pwren_gpio, 0); + if (rc) { + vl53lx_errmsg("fail to configure pwren as output %d", rc); + goto direction_failed; + } + i2c_data->io_flag.pwr_owned = 1; + + return rc; + +direction_failed: + gpio_free(i2c_data->xsdn_gpio); + +request_failed: +no_gpio: + return rc; +} + +static void put_pwren(struct i2c_data *i2c_data) +{ + if (i2c_data->io_flag.pwr_owned) { + vl53lx_dbgmsg("release xsdn_gpio %d", i2c_data->xsdn_gpio); + gpio_free(i2c_data->pwren_gpio); + i2c_data->io_flag.pwr_owned = 0; + } + i2c_data->pwren_gpio = -1; +} + +static int get_intr(struct device *dev, struct i2c_data *i2c_data) +{ + int rc = 0; + + i2c_data->io_flag.intr_owned = 0; + if (i2c_data->intr_gpio == -1) { + vl53lx_wanrmsg("no interrupt gpio"); + goto no_gpio; + } + + vl53lx_dbgmsg("request intr_gpio %d", i2c_data->intr_gpio); + rc = gpio_request(i2c_data->intr_gpio, "vl53lx_intr"); + if (rc) { + vl53lx_errmsg("fail to acquire intr %d", rc); + goto request_failed; + } + + rc = gpio_direction_input(i2c_data->intr_gpio); + if (rc) { + vl53lx_errmsg("fail to configure intr as input %d", rc); + goto direction_failed; + } + + i2c_data->irq = gpio_to_irq(i2c_data->intr_gpio); + if (i2c_data->irq < 0) { + vl53lx_errmsg("fail to map GPIO: %d to interrupt:%d\n", i2c_data->intr_gpio, i2c_data->irq); + goto irq_failed; + } + i2c_data->io_flag.intr_owned = 1; + + return rc; + +irq_failed: +direction_failed: + gpio_free(i2c_data->intr_gpio); + +request_failed: +no_gpio: + return rc; +} + +static void put_intr(struct i2c_data *i2c_data) +{ + if (i2c_data->io_flag.intr_owned) { + if (i2c_data->io_flag.intr_started) { + free_irq(i2c_data->irq, i2c_data); + i2c_data->io_flag.intr_started = 0; + } + vl53lx_dbgmsg("release intr_gpio %d", i2c_data->intr_gpio); + gpio_free(i2c_data->intr_gpio); + i2c_data->io_flag.intr_owned = 0; + } + i2c_data->intr_gpio = -1; +} + +static int handle_i2c_address_device_change_lock(struct i2c_data *data) +{ + struct i2c_client *client = (struct i2c_client *) data->client; + uint8_t buffer[3]; + struct i2c_msg msg; + int rc = 0; + + vl53lx_dbgmsg("change device i2c address from 0x%02x to 0x%02x", data->boot_reg, client->addr); + + usleep_range(VL53LX_FIRMWARE_BOOT_TIME_US, VL53LX_FIRMWARE_BOOT_TIME_US + 1); + + buffer[0] = (VL53LX_I2C_SLAVE__DEVICE_ADDRESS >> 8) & 0xFF; + buffer[1] = (VL53LX_I2C_SLAVE__DEVICE_ADDRESS >> 0) & 0xFF; + buffer[2] = client->addr; + msg.addr = data->boot_reg; + msg.flags = client->flags; + msg.buf = buffer; + msg.len = 3; + if (i2c_transfer(client->adapter, &msg, 1) != 1) { + rc = -ENXIO; + vl53lx_errmsg("Fail to change i2c address to 0x%02x", client->addr); + } + + return rc; +} + +static int release_reset(struct i2c_data *data) +{ + struct i2c_client *client = (struct i2c_client *) data->client; + int rc = 0; + bool is_address_change = client->addr != data->boot_reg; + + if (is_address_change) + mutex_lock(&dev_addr_change_mutex); + + gpio_set_value(data->xsdn_gpio, 1); + if (is_address_change) { + rc = handle_i2c_address_device_change_lock(data); + if (rc) + gpio_set_value(data->xsdn_gpio, 0); + } + + if (is_address_change) + mutex_unlock(&dev_addr_change_mutex); + + return rc; +} + +VL53LX_Error VL53LX_WaitUs(VL53LX_DEV pdev, int32_t wait_us) +{ + struct stmvl53lx_data *data; + + data = (struct stmvl53lx_data *)container_of(pdev, struct stmvl53lx_data, stdev); + + if (!data->is_delay_allowed) + return VL53LX_ERROR_PLATFORM_SPECIFIC_START; + + if (wait_us < 10) + udelay(wait_us); + else if (wait_us < 20000) + usleep_range(wait_us, wait_us + 1); + else + msleep(wait_us / 1000); + + return VL53LX_ERROR_NONE; +} + +VL53LX_Error VL53LX_WaitMs(VL53LX_DEV pdev, int32_t wait_ms) +{ + return VL53LX_WaitUs(pdev, wait_ms * 1000); +} + +static int cci_write(struct stmvl53lx_data *dev, int index, uint8_t *data, uint16_t len) +{ + uint8_t buffer[STMVL53LX_MAX_CCI_XFER_SZ + 2]; + struct i2c_msg msg; + struct i2c_data *i2c_client_obj = (struct i2c_data *)dev->client_object; + struct i2c_client *client = (struct i2c_client *)i2c_client_obj->client; + int rc; + + cci_access_var; + if (len > STMVL53LX_MAX_CCI_XFER_SZ || len == 0) { + vl53lx_errmsg("invalid len %d\n", len); + return -1; + } + cci_access_start(); + buffer[0] = (index >> 8) & 0xFF; + buffer[1] = (index >> 0) & 0xFF; + memcpy(buffer + 2, data, len); + msg.addr = client->addr; + msg.flags = client->flags; + msg.buf = buffer; + msg.len = len + 2; + + rc = i2c_transfer(client->adapter, &msg, 1); + if (rc != 1) { + vl53lx_errmsg("wr i2c_transfer err:%d, index 0x%x len %d\n", rc, index, len); + } + cci_access_over("rd status %d long %d ", rc != 1, len); + return rc != 1; +} + +static int cci_read(struct stmvl53lx_data *dev, int index, uint8_t *data, uint16_t len) +{ + uint8_t buffer[2]; + struct i2c_msg msg[2]; + struct i2c_data *i2c_client_obj = (struct i2c_data *)dev->client_object; + struct i2c_client *client = (struct i2c_client *)i2c_client_obj->client; + int rc; + + cci_access_var; + if (len > STMVL53LX_MAX_CCI_XFER_SZ || len == 0) { + vl53lx_errmsg("invalid len %d\n", len); + return -1; + } + cci_access_start(); + + buffer[0] = (index >> 8) & 0xFF; + buffer[1] = (index >> 0) & 0xFF; + + msg[0].addr = client->addr; + msg[0].flags = client->flags; + msg[0].buf = buffer; + msg[0].len = 2; + + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD | client->flags; + msg[1].buf = data; + msg[1].len = len; + + rc = i2c_transfer(client->adapter, msg, 2); + if (rc != 2) { + pr_err("%s: i2c_transfer :%d, @%x index 0x%x len %d\n", __func__, rc, client->addr, index, len); + } + cci_access_over(" wr len %d status %d", rc != 2, len); + return rc != 2; +} + +static uint32_t tv_elapsed_ms(struct st_timeval *tv) +{ + struct st_timeval now; + + st_gettimeofday(&now); + return (now.tv_sec - tv->tv_sec) * 1000 + (now.tv_usec - tv->tv_usec) / 1000; +} + +static int is_time_over(struct st_timeval *tv, uint32_t msec) +{ + return tv_elapsed_ms(tv) >= msec; +} + +VL53LX_Error VL53LX_WaitValueMaskEx(VL53LX_DEV pdev, uint32_t timeout_ms, uint16_t index, uint8_t value, uint8_t mask, uint32_t poll_delay_ms) +{ + struct st_timeval start_tv; + struct stmvl53lx_data *dev; + int rc, time_over; + uint8_t rd_val; + + dev = (struct stmvl53lx_data *)container_of(pdev, struct stmvl53lx_data, stdev); + + st_gettimeofday(&start_tv); + do { + rc = cci_read(dev, index, &rd_val, 1); + if (rc) + return VL53LX_ERROR_CONTROL_INTERFACE; + if ((rd_val & mask) == value) { + poll_timing_log(&start_tv); + return VL53LX_ERROR_NONE; + } + vl53lx_dbgmsg("poll @%x %x & %d != %x", index, rd_val, mask, value); + time_over = is_time_over(&start_tv, timeout_ms); + if (!time_over) + msleep(poll_delay_ms); + } while (!time_over); + vl53lx_errmsg("time over %d ms", timeout_ms); + return VL53LX_ERROR_TIME_OUT; +} + +void VL53LX_init_ll_driver_state(VL53LX_DEV Dev, VL53LX_DeviceState device_state) +{ + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + VL53LX_ll_driver_state_t *pstate = &(pdev->ll_state); + + pstate->cfg_device_state = device_state; + pstate->cfg_stream_count = 0; + pstate->cfg_gph_id = VL53LX_GROUPEDPARAMETERHOLD_ID_MASK; + pstate->cfg_timing_status = 0; + pstate->cfg_zone_id = 0; + + pstate->rd_device_state = device_state; + pstate->rd_stream_count = 0; + pstate->rd_gph_id = VL53LX_GROUPEDPARAMETERHOLD_ID_MASK; + pstate->rd_timing_status = 0; + pstate->rd_zone_id = 0; +} + +VL53LX_Error VL53LX_poll_for_boot_completion(VL53LX_DEV Dev, uint32_t timeout_ms) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + status = VL53LX_WaitUs(Dev, VL53LX_FIRMWARE_BOOT_TIME_US); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_WaitValueMaskEx(Dev, timeout_ms, VL53LX_FIRMWARE__SYSTEM_STATUS, 0x01, 0x01, VL53LX_POLLING_DELAY_MS); + + if (status == VL53LX_ERROR_NONE) + VL53LX_init_ll_driver_state(Dev, VL53LX_DEVICESTATE_SW_STANDBY); + + return status; +} + +VL53LX_Error VL53LX_WaitDeviceBooted(VL53LX_DEV Dev) +{ + VL53LX_Error Status = VL53LX_ERROR_NONE; + + Status = VL53LX_poll_for_boot_completion(Dev, VL53LX_BOOT_COMPLETION_POLLING_TIMEOUT_MS); + + return Status; +} + +static int stmvl53lx_input_setup(struct stmvl53lx_data *data) +{ + int rc = 0; + struct input_dev *idev; + idev = input_allocate_device(); + if (idev == NULL) { + rc = -ENOMEM; + vl53lx_errmsg("%d error:%d\n", __LINE__, rc); + goto exit_err; + } + + set_bit(EV_ABS, idev->evbit); + + input_set_abs_params(idev, ABS_DISTANCE, 0, 0xff, 0, 0); + input_set_abs_params(idev, ABS_HAT0X, 0, 0xffffffff, 0, 0); + input_set_abs_params(idev, ABS_HAT0Y, 0, 0xffffffff, 0, 0); + input_set_abs_params(idev, ABS_HAT1X, 0, 0xffffffff, 0, 0); + input_set_abs_params(idev, ABS_HAT1Y, 0, 0xffffffff, 0, 0); + input_set_abs_params(idev, ABS_HAT2X, 0, 0xffffffff, 0, 0); + input_set_abs_params(idev, ABS_HAT2Y, 0, 0xffffffff, 0, 0); + input_set_abs_params(idev, ABS_HAT3X, 0, 0xffffffff, 0, 0); + input_set_abs_params(idev, ABS_HAT3Y, 0, 0xffffffff, 0, 0); + input_set_abs_params(idev, ABS_WHEEL, 0, 0xffffffff, 0, 0); + input_set_abs_params(idev, ABS_TILT_Y, 0, 0xffffffff, 0, 0); + input_set_abs_params(idev, ABS_BRAKE, 0, 0xffffffff, 0, 0); + input_set_abs_params(idev, ABS_TILT_X, 0, 0xffffffff, 0, 0); + input_set_abs_params(idev, ABS_TOOL_WIDTH, 0, 0xffffffff, 0, 0); + input_set_abs_params(idev, ABS_THROTTLE, 0, 0xffffffff, 0, 0); + input_set_abs_params(idev, ABS_RUDDER, 0, 0xffffffff, 0, 0); + input_set_abs_params(idev, ABS_MISC, 0, 0xffffffff, 0, 0); + input_set_abs_params(idev, ABS_VOLUME, 0, 0xffffffff, 0, 0); + input_set_abs_params(idev, ABS_GAS, 0, 0xffffffff, 0, 0); + + idev->name = "STM VL53LX proximity sensor"; + rc = input_register_device(idev); + if (rc) { + rc = -ENOMEM; + vl53lx_errmsg("%d error:%d\n", __LINE__, rc); + goto exit_free_dev_ps; + } + input_set_drvdata(idev, data); + data->input_dev_ps = idev; + return 0; + +exit_free_dev_ps: + input_free_device(data->input_dev_ps); +exit_err: + return rc; +} + +uint32_t VL53LX_calc_pll_period_us(uint16_t fast_osc_frequency) +{ + uint32_t pll_period_us = 0; + + if (fast_osc_frequency > 0) + pll_period_us = (0x01 << 30) / fast_osc_frequency; + return pll_period_us; +} + +uint8_t VL53LX_decode_vcsel_period(uint8_t vcsel_period_reg) +{ + uint8_t VL53LX_p_030 = 0; + + VL53LX_p_030 = (vcsel_period_reg + 1) << 1; + return VL53LX_p_030; +} + + +uint32_t VL53LX_calc_macro_period_us(uint16_t fast_osc_frequency, uint8_t VL53LX_p_005) +{ + uint32_t pll_period_us = 0; + uint8_t VL53LX_p_030 = 0; + uint32_t macro_period_us = 0; + + pll_period_us = VL53LX_calc_pll_period_us(fast_osc_frequency); + + VL53LX_p_030 = VL53LX_decode_vcsel_period(VL53LX_p_005); + + macro_period_us = (uint32_t)VL53LX_MACRO_PERIOD_VCSEL_PERIODS * pll_period_us; + macro_period_us = macro_period_us >> 6; + + macro_period_us = macro_period_us * (uint32_t)VL53LX_p_030; + macro_period_us = macro_period_us >> 6; + + return macro_period_us; +} + +uint32_t VL53LX_calc_timeout_us(uint32_t timeout_mclks, uint32_t macro_period_us) +{ + uint32_t timeout_us = 0; + uint64_t tmp = 0; + + + tmp = (uint64_t)timeout_mclks * (uint64_t)macro_period_us; + tmp += 0x00800; + tmp = tmp >> 12; + + timeout_us = (uint32_t)tmp; + + return timeout_us; +} + +uint32_t VL53LX_decode_timeout(uint16_t encoded_timeout) +{ + uint32_t timeout_macro_clks = 0; + + timeout_macro_clks = ((uint32_t) (encoded_timeout & 0x00FF) << (uint32_t) ((encoded_timeout & 0xFF00) >> 8)) + 1; + + return timeout_macro_clks; +} + +uint32_t VL53LX_calc_decoded_timeout_us( + uint16_t timeout_encoded, + uint32_t macro_period_us) +{ + uint32_t timeout_mclks = 0; + uint32_t timeout_us = 0; + + timeout_mclks = VL53LX_decode_timeout(timeout_encoded); + + timeout_us = VL53LX_calc_timeout_us(timeout_mclks, macro_period_us); + + return timeout_us; +} + +VL53LX_Error VL53LX_get_timeouts_us(VL53LX_DEV Dev, uint32_t *pphasecal_config_timeout_us, uint32_t *pmm_config_timeout_us, uint32_t *prange_config_timeout_us) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + uint32_t macro_period_us = 0; + uint16_t timeout_encoded = 0; + + if (pdev->stat_nvm.osc_measured__fast_osc__frequency == 0) + status = VL53LX_ERROR_DIVISION_BY_ZERO; + + if (status == VL53LX_ERROR_NONE) { + macro_period_us = VL53LX_calc_macro_period_us(pdev->stat_nvm.osc_measured__fast_osc__frequency, pdev->tim_cfg.range_config__vcsel_period_a); + + *pphasecal_config_timeout_us = VL53LX_calc_timeout_us((uint32_t)pdev->gen_cfg.phasecal_config__timeout_macrop, macro_period_us); + + timeout_encoded = (uint16_t)pdev->tim_cfg.mm_config__timeout_macrop_a_hi; + timeout_encoded = (timeout_encoded << 8) + (uint16_t)pdev->tim_cfg.mm_config__timeout_macrop_a_lo; + + *pmm_config_timeout_us = VL53LX_calc_decoded_timeout_us(timeout_encoded, macro_period_us); + + timeout_encoded = (uint16_t)pdev->tim_cfg.range_config__timeout_macrop_a_hi; + timeout_encoded = (timeout_encoded << 8) + (uint16_t)pdev->tim_cfg.range_config__timeout_macrop_a_lo; + + *prange_config_timeout_us = VL53LX_calc_decoded_timeout_us(timeout_encoded, macro_period_us); + + pdev->phasecal_config_timeout_us = *pphasecal_config_timeout_us; + pdev->mm_config_timeout_us = *pmm_config_timeout_us; + pdev->range_config_timeout_us = *prange_config_timeout_us; + + } + + return status; +} + +uint32_t VL53LX_calc_timeout_mclks(uint32_t timeout_us, uint32_t macro_period_us) +{ + uint32_t timeout_mclks = 0; + + if (macro_period_us == 0) + timeout_mclks = 0; + else + timeout_mclks = ((timeout_us << 12) + (macro_period_us>>1)) / macro_period_us; + + return timeout_mclks; +} + +uint16_t VL53LX_encode_timeout(uint32_t timeout_mclks) +{ + uint16_t encoded_timeout = 0; + uint32_t ls_byte = 0; + uint16_t ms_byte = 0; + + if (timeout_mclks > 0) { + ls_byte = timeout_mclks - 1; + while ((ls_byte & 0xFFFFFF00) > 0) { + ls_byte = ls_byte >> 1; + ms_byte++; + } + encoded_timeout = (ms_byte << 8) + (uint16_t) (ls_byte & 0x000000FF); + } + return encoded_timeout; +} + + +uint16_t VL53LX_calc_encoded_timeout(uint32_t timeout_us, uint32_t macro_period_us) +{ + uint32_t timeout_mclks = 0; + uint16_t timeout_encoded = 0; + + timeout_mclks = VL53LX_calc_timeout_mclks(timeout_us, macro_period_us); + + timeout_encoded = VL53LX_encode_timeout(timeout_mclks); + + return timeout_encoded; +} + +VL53LX_Error VL53LX_calc_timeout_register_values(uint32_t phasecal_config_timeout_us, uint32_t mm_config_timeout_us, uint32_t range_config_timeout_us, uint16_t fast_osc_frequency, VL53LX_general_config_t *pgeneral, VL53LX_timing_config_t *ptiming) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + uint32_t macro_period_us = 0; + uint32_t timeout_mclks = 0; + uint16_t timeout_encoded = 0; + + if (fast_osc_frequency == 0) { + status = VL53LX_ERROR_DIVISION_BY_ZERO; + } else { + macro_period_us = VL53LX_calc_macro_period_us(fast_osc_frequency, ptiming->range_config__vcsel_period_a); + + timeout_mclks = VL53LX_calc_timeout_mclks(phasecal_config_timeout_us, macro_period_us); + + if (timeout_mclks > 0xFF) + timeout_mclks = 0xFF; + + pgeneral->phasecal_config__timeout_macrop = (uint8_t)timeout_mclks; + + timeout_encoded = VL53LX_calc_encoded_timeout(mm_config_timeout_us, macro_period_us); + + ptiming->mm_config__timeout_macrop_a_hi = (uint8_t)((timeout_encoded & 0xFF00) >> 8); + ptiming->mm_config__timeout_macrop_a_lo = (uint8_t) (timeout_encoded & 0x00FF); + + timeout_encoded = VL53LX_calc_encoded_timeout(range_config_timeout_us, macro_period_us); + + ptiming->range_config__timeout_macrop_a_hi = (uint8_t)((timeout_encoded & 0xFF00) >> 8); + ptiming->range_config__timeout_macrop_a_lo = (uint8_t) (timeout_encoded & 0x00FF); + + macro_period_us = VL53LX_calc_macro_period_us(fast_osc_frequency, ptiming->range_config__vcsel_period_b); + + timeout_encoded = VL53LX_calc_encoded_timeout(mm_config_timeout_us, macro_period_us); + + ptiming->mm_config__timeout_macrop_b_hi = (uint8_t)((timeout_encoded & 0xFF00) >> 8); + ptiming->mm_config__timeout_macrop_b_lo = (uint8_t) (timeout_encoded & 0x00FF); + + timeout_encoded = VL53LX_calc_encoded_timeout(range_config_timeout_us, macro_period_us); + + ptiming->range_config__timeout_macrop_b_hi = (uint8_t)((timeout_encoded & 0xFF00) >> 8); + ptiming->range_config__timeout_macrop_b_lo = (uint8_t) (timeout_encoded & 0x00FF); + } + return status; +} + +VL53LX_Error VL53LX_set_timeouts_us(VL53LX_DEV Dev, uint32_t phasecal_config_timeout_us, uint32_t mm_config_timeout_us, uint32_t range_config_timeout_us) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + if (pdev->stat_nvm.osc_measured__fast_osc__frequency == 0) + status = VL53LX_ERROR_DIVISION_BY_ZERO; + + if (status == VL53LX_ERROR_NONE) { + pdev->phasecal_config_timeout_us = phasecal_config_timeout_us; + pdev->mm_config_timeout_us = mm_config_timeout_us; + pdev->range_config_timeout_us = range_config_timeout_us; + + status = VL53LX_calc_timeout_register_values(phasecal_config_timeout_us, mm_config_timeout_us, range_config_timeout_us, pdev->stat_nvm.osc_measured__fast_osc__frequency, &(pdev->gen_cfg), &(pdev->tim_cfg)); + } + 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; +} + +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; + + 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); + } + return Status; +} + +static int store_last_error(struct stmvl53lx_data *data, int rc) +{ + data->last_error = rc; + + return -EIO; +} + +VL53LX_Error VL53LX_i2c_encode_system_control(VL53LX_system_control_t *pdata, uint16_t buf_size, uint8_t *pbuffer) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + if (buf_size < VL53LX_SYSTEM_CONTROL_I2C_SIZE_BYTES) + return VL53LX_ERROR_COMMS_BUFFER_TOO_SMALL; + + *(pbuffer + 0) = pdata->power_management__go1_power_force & 0x1; + *(pbuffer + 1) = pdata->system__stream_count_ctrl & 0x1; + *(pbuffer + 2) = pdata->firmware__enable & 0x1; + *(pbuffer + 3) = pdata->system__interrupt_clear & 0x3; + *(pbuffer + 4) = pdata->system__mode_start; + + return status; +} + +VL53LX_Error VL53LX_WriteMulti(VL53LX_DEV pdev, uint16_t index, uint8_t *pdata, uint32_t count) +{ + uint32_t chunk_size = WRITE_MULTIPLE_CHUNK_MAX; + VL53LX_Error status; + uint32_t i; + uint16_t hostaddr = index; + struct stmvl53lx_data *dev; + + dev = (struct stmvl53lx_data *)container_of(pdev, struct stmvl53lx_data, stdev); + + for (i = 0; i < count; i += chunk_size) { + status = (cci_write(dev, hostaddr, &pdata[i], min(chunk_size, (count - i))) ? VL53LX_ERROR_CONTROL_INTERFACE : VL53LX_ERROR_NONE); + if (status != VL53LX_ERROR_NONE) + break; + hostaddr += chunk_size; + } + return status; +} + +VL53LX_Error VL53LX_ReadMulti(VL53LX_DEV pdev, uint16_t index, uint8_t *pdata, uint32_t count) +{ + struct stmvl53lx_data *dev; + + dev = (struct stmvl53lx_data *)container_of(pdev, struct stmvl53lx_data, stdev); + + return cci_read(dev, index, pdata, count) ? VL53LX_ERROR_CONTROL_INTERFACE : VL53LX_ERROR_NONE; +} + +VL53LX_Error VL53LX_RdByte(VL53LX_DEV pdev, uint16_t index, uint8_t *pdata) +{ + struct stmvl53lx_data *dev; + dev = (struct stmvl53lx_data *)container_of(pdev, struct stmvl53lx_data, stdev); + + return cci_read(dev, index, pdata, 1) ? VL53LX_ERROR_CONTROL_INTERFACE : VL53LX_ERROR_NONE; +} + +VL53LX_Error VL53LX_WrByte(VL53LX_DEV pdev, uint16_t index, uint8_t data) +{ + struct stmvl53lx_data *dev; + dev = (struct stmvl53lx_data *)container_of(pdev, struct stmvl53lx_data, stdev); + + return cci_write(dev, index, &data, 1); +} + +VL53LX_Error VL53LX_RdWord(VL53LX_DEV pdev, uint16_t index, uint16_t *pdata) +{ + VL53LX_Error status; + uint8_t buffer[2]; + + status = VL53LX_ReadMulti(pdev, index, buffer, 2); + + *pdata = ((uint16_t) buffer[0] << 8) + (uint16_t) buffer[1]; + + return status; +} + +VL53LX_Error VL53LX_WrWord(VL53LX_DEV pdev, uint16_t index, uint16_t data) +{ + VL53LX_Error status; + uint8_t buffer[2]; + + + buffer[0] = (uint8_t) (data >> 8); + buffer[1] = (uint8_t) (data & 0x00FF); + i2c_debug(" @%x d= %x => [ %x , %x ] ", index, data, buffer[0], buffer[1]); + status = VL53LX_WriteMulti(pdev, index, buffer, 2); + + return status; +} + +VL53LX_Error VL53LX_WrDWord(VL53LX_DEV pdev, uint16_t index, uint32_t data) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + uint8_t buffer[4]; + + buffer[0] = (uint8_t) (data >> 24); + buffer[1] = (uint8_t) ((data & 0x00FF0000) >> 16); + buffer[2] = (uint8_t) ((data & 0x0000FF00) >> 8); + buffer[3] = (uint8_t) (data & 0x000000FF); + + status = VL53LX_WriteMulti(pdev, index, buffer, 4); + + return status; +} + +VL53LX_Error VL53LX_RdDWord(VL53LX_DEV pdev, uint16_t index, uint32_t *pdata) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + uint8_t buffer[4]; + + status = VL53LX_ReadMulti(pdev, index, buffer, 4); + + *pdata = ((uint32_t) buffer[0] << 24) + ((uint32_t) buffer[1] << 16) + ((uint32_t) buffer[2] << 8) + (uint32_t) buffer[3]; + + return status; +} + +VL53LX_Error VL53LX_set_system_control(VL53LX_DEV Dev, VL53LX_system_control_t *pdata) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + uint8_t comms_buffer[VL53LX_SYSTEM_CONTROL_I2C_SIZE_BYTES]; + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_i2c_encode_system_control(pdata, VL53LX_SYSTEM_CONTROL_I2C_SIZE_BYTES, comms_buffer); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_WriteMulti(Dev, VL53LX_POWER_MANAGEMENT__GO1_POWER_FORCE, comms_buffer, VL53LX_SYSTEM_CONTROL_I2C_SIZE_BYTES); + + return status; +} + +void V53L1_init_zone_results_structure(uint8_t active_zones, VL53LX_zone_results_t *pdata) +{ + uint8_t z = 0; + VL53LX_zone_objects_t *pobjects; + + pdata->max_zones = VL53LX_MAX_USER_ZONES; + pdata->active_zones = active_zones; + + for (z = 0; z < pdata->max_zones; z++) { + pobjects = &(pdata->VL53LX_p_003[z]); + pobjects->cfg_device_state = VL53LX_DEVICESTATE_SW_STANDBY; + pobjects->rd_device_state = VL53LX_DEVICESTATE_SW_STANDBY; + pobjects->max_objects = VL53LX_MAX_RANGE_RESULTS; + pobjects->active_objects = 0; + } +} + +void V53L1_init_zone_dss_configs(VL53LX_DEV Dev) +{ + VL53LX_LLDriverResults_t *pres = VL53LXDevStructGetLLResultsHandle(Dev); + uint8_t z = 0; + uint8_t max_zones = VL53LX_MAX_USER_ZONES; + VL53LX_zone_private_dyn_cfgs_t *pdata = &(pres->zone_dyn_cfgs); + + for (z = 0; z < max_zones; z++) { + pdata->VL53LX_p_003[z].dss_mode = VL53LX_DSS_CONTROL__MODE_TARGET_RATE; + pdata->VL53LX_p_003[z].dss_requested_effective_spad_count = 0; + } +} + +VL53LX_Error VL53LX_low_power_auto_data_stop_range(VL53LX_DEV Dev) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + pdev->low_power_auto_data.low_power_auto_range_count = 0xFF; + + pdev->low_power_auto_data.first_run_phasecal_result = 0; + pdev->low_power_auto_data.dss__total_rate_per_spad_mcps = 0; + pdev->low_power_auto_data.dss__required_spads = 0; + + if (pdev->low_power_auto_data.saved_vhv_init != 0) + pdev->stat_nvm.vhv_config__init = pdev->low_power_auto_data.saved_vhv_init; + if (pdev->low_power_auto_data.saved_vhv_timeout != 0) + pdev->stat_nvm.vhv_config__timeout_macrop_loop_bound = pdev->low_power_auto_data.saved_vhv_timeout; + + pdev->gen_cfg.phasecal_config__override = 0x00; + + return status; +} + +VL53LX_Error VL53LX_stop_range(VL53LX_DEV Dev) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + VL53LX_LLDriverResults_t *pres = VL53LXDevStructGetLLResultsHandle(Dev); + + pdev->sys_ctrl.system__mode_start = (pdev->sys_ctrl.system__mode_start & VL53LX_DEVICEMEASUREMENTMODE_STOP_MASK) | VL53LX_DEVICEMEASUREMENTMODE_ABORT; + + status = VL53LX_set_system_control(Dev, &pdev->sys_ctrl); + + pdev->sys_ctrl.system__mode_start = (pdev->sys_ctrl.system__mode_start & VL53LX_DEVICEMEASUREMENTMODE_STOP_MASK); + + VL53LX_init_ll_driver_state(Dev, VL53LX_DEVICESTATE_SW_STANDBY); + + V53L1_init_zone_results_structure(pdev->zone_cfg.active_zones+1, &(pres->zone_results)); + + V53L1_init_zone_dss_configs(Dev); + + if (pdev->low_power_auto_data.is_low_power_auto_mode == 1) + VL53LX_low_power_auto_data_stop_range(Dev); + + return status; +} + +VL53LX_Error VL53LX_set_powerforce_register(VL53LX_DEV Dev, uint8_t value) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + pdev->sys_ctrl.power_management__go1_power_force = value; + + status = VL53LX_WrByte(Dev, VL53LX_POWER_MANAGEMENT__GO1_POWER_FORCE, pdev->sys_ctrl.power_management__go1_power_force); + + return status; +} + +VL53LX_Error VL53LX_disable_powerforce(VL53LX_DEV Dev) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + status = VL53LX_set_powerforce_register(Dev, 0x00); + + return status; +} + +VL53LX_Error VL53LX_unload_patch(VL53LX_DEV Dev) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_WrByte(Dev, VL53LX_FIRMWARE__ENABLE, 0x00); + + if (status == VL53LX_ERROR_NONE) + VL53LX_disable_powerforce(Dev); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_WrByte(Dev, VL53LX_PATCH__CTRL, 0x00); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_WrByte(Dev, VL53LX_FIRMWARE__ENABLE, 0x01); + + return status; +} + +VL53LX_Error VL53LX_StopMeasurement(VL53LX_DEV Dev) +{ + VL53LX_Error Status = VL53LX_ERROR_NONE; + + Status = VL53LX_stop_range(Dev); + + VL53LX_unload_patch(Dev); + + return Status; +} + +static void empty_and_free_list(struct list_head *head) +{ + struct stmvl53lx_waiters *waiter; + struct stmvl53lx_waiters *tmp; + + list_for_each_entry_safe(waiter, tmp, head, list) { + list_del(&waiter->list); + kfree(waiter); + } +} + +static void wake_up_data_waiters(struct stmvl53lx_data *data) +{ + empty_and_free_list(&data->simple_data_reader_list); + empty_and_free_list(&data->mz_data_reader_list); + wake_up(&data->waiter_for_data); +} + +static int stmvl53lx_stop(struct stmvl53lx_data *data) +{ + int rc = 0; + + rc = VL53LX_StopMeasurement(&data->stdev); + if (rc) { + vl53lx_errmsg("VL53LX_StopMeasurement @%d fail %d", __LINE__, rc); + rc = store_last_error(data, rc); + } + + reset_hold(data); + data->enable_sensor = 0; + if (data->poll_mode) { + cancel_delayed_work(&data->dwork); + } + + wake_up_data_waiters(data); + return rc; +} + +void VL53LX_i2c_encode_uint16_t(uint16_t ip_value, uint16_t count, uint8_t *pbuffer) +{ + uint16_t i = 0; + uint16_t VL53LX_p_003 = 0; + + VL53LX_p_003 = ip_value; + + for (i = 0; i < count; i++) { + pbuffer[count-i-1] = (uint8_t)(VL53LX_p_003 & 0x00FF); + VL53LX_p_003 = VL53LX_p_003 >> 8; + } +} + +uint16_t VL53LX_i2c_decode_uint16_t(uint16_t count, uint8_t *pbuffer) +{ + uint16_t value = 0x00; + + while (count-- > 0) + value = (value << 8) | (uint16_t)*pbuffer++; + + return value; +} + +void VL53LX_i2c_encode_int16_t(int16_t ip_value, uint16_t count, uint8_t *pbuffer) +{ + uint16_t i = 0; + int16_t VL53LX_p_003 = 0; + + VL53LX_p_003 = ip_value; + + for (i = 0; i < count; i++) { + pbuffer[count-i-1] = (uint8_t)(VL53LX_p_003 & 0x00FF); + VL53LX_p_003 = VL53LX_p_003 >> 8; + } +} + +int16_t VL53LX_i2c_decode_int16_t(uint16_t count, uint8_t *pbuffer) +{ + int16_t value = 0x00; + + if (*pbuffer >= 0x80) + value = 0xFFFF; + + while (count-- > 0) + value = (value << 8) | (int16_t)*pbuffer++; + + return value; +} + +uint32_t VL53LX_i2c_decode_with_mask(uint16_t count, uint8_t *pbuffer, uint32_t bit_mask, uint32_t down_shift, uint32_t offset) +{ + uint32_t value = 0x00; + + while (count-- > 0) + value = (value << 8) | (uint32_t)*pbuffer++; + + value = value & bit_mask; + if (down_shift > 0) + value = value >> down_shift; + + value = value + offset; + + return value; +} + + +void VL53LX_i2c_encode_int32_t(int32_t ip_value, uint16_t count, uint8_t *pbuffer) +{ + uint16_t i = 0; + int32_t VL53LX_p_003 = 0; + + VL53LX_p_003 = ip_value; + + for (i = 0; i < count; i++) { + pbuffer[count-i-1] = (uint8_t)(VL53LX_p_003 & 0x00FF); + VL53LX_p_003 = VL53LX_p_003 >> 8; + } +} + +int32_t VL53LX_i2c_decode_int32_t(uint16_t count, uint8_t *pbuffer) +{ + int32_t value = 0x00; + + if (*pbuffer >= 0x80) + value = 0xFFFFFFFF; + + while (count-- > 0) + value = (value << 8) | (int32_t)*pbuffer++; + + return value; +} + +VL53LX_Error VL53LX_i2c_encode_customer_nvm_managed(VL53LX_customer_nvm_managed_t *pdata, uint16_t buf_size, uint8_t *pbuffer) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + if (buf_size < VL53LX_CUSTOMER_NVM_MANAGED_I2C_SIZE_BYTES) + return VL53LX_ERROR_COMMS_BUFFER_TOO_SMALL; + + *(pbuffer + 0) = pdata->global_config__spad_enables_ref_0; + *(pbuffer + 1) = pdata->global_config__spad_enables_ref_1; + *(pbuffer + 2) = pdata->global_config__spad_enables_ref_2; + *(pbuffer + 3) = pdata->global_config__spad_enables_ref_3; + *(pbuffer + 4) = pdata->global_config__spad_enables_ref_4; + *(pbuffer + 5) = pdata->global_config__spad_enables_ref_5 & 0xF; + *(pbuffer + 6) = pdata->global_config__ref_en_start_select; + *(pbuffer + 7) = pdata->ref_spad_man__num_requested_ref_spads & 0x3F; + *(pbuffer + 8) = pdata->ref_spad_man__ref_location & 0x3; + VL53LX_i2c_encode_uint16_t(pdata->algo__crosstalk_compensation_plane_offset_kcps, 2, pbuffer + 9); + VL53LX_i2c_encode_int16_t(pdata->algo__crosstalk_compensation_x_plane_gradient_kcps, 2, pbuffer + 11); + VL53LX_i2c_encode_int16_t(pdata->algo__crosstalk_compensation_y_plane_gradient_kcps, 2, pbuffer + 13); + VL53LX_i2c_encode_uint16_t(pdata->ref_spad_char__total_rate_target_mcps, 2, pbuffer + 15); + VL53LX_i2c_encode_int16_t(pdata->algo__part_to_part_range_offset_mm & 0x1FFF, 2, pbuffer + 17); + VL53LX_i2c_encode_int16_t(pdata->mm_config__inner_offset_mm, 2, pbuffer + 19); + VL53LX_i2c_encode_int16_t(pdata->mm_config__outer_offset_mm, 2, pbuffer + 21); + + return status; +} + +VL53LX_Error VL53LX_set_customer_nvm_managed(VL53LX_DEV Dev, VL53LX_customer_nvm_managed_t *pdata) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + uint8_t comms_buffer[VL53LX_CUSTOMER_NVM_MANAGED_I2C_SIZE_BYTES]; + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_i2c_encode_customer_nvm_managed(pdata, VL53LX_CUSTOMER_NVM_MANAGED_I2C_SIZE_BYTES, comms_buffer); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_WriteMulti(Dev, VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_REF_0, comms_buffer, VL53LX_CUSTOMER_NVM_MANAGED_I2C_SIZE_BYTES); + + return status; +} + +VL53LX_Error VL53LX_disable_xtalk_compensation(VL53LX_DEV Dev) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + VL53LX_hist_post_process_config_t *pHP = &(pdev->histpostprocess); + VL53LX_customer_nvm_managed_t *pN = &(pdev->customer); + + pN->algo__crosstalk_compensation_plane_offset_kcps = 0x00; + pN->algo__crosstalk_compensation_x_plane_gradient_kcps = 0x00; + pN->algo__crosstalk_compensation_y_plane_gradient_kcps = 0x00; + pdev->xtalk_cfg.global_crosstalk_compensation_enable = 0x00; + pHP->algo__crosstalk_compensation_enable = pdev->xtalk_cfg.global_crosstalk_compensation_enable; + + if (status == VL53LX_ERROR_NONE) { + pdev->xtalk_cfg.crosstalk_range_ignore_threshold_rate_mcps = 0x0000; + } + if (status == VL53LX_ERROR_NONE) { + status = VL53LX_set_customer_nvm_managed(Dev, &(pdev->customer)); + } + return status; +} + +uint32_t VL53LX_calc_crosstalk_plane_offset_with_margin(uint32_t plane_offset_kcps, int16_t margin_offset_kcps) +{ + uint32_t plane_offset_with_margin = 0; + int32_t plane_offset_kcps_temp = 0; + + plane_offset_kcps_temp = (int32_t)plane_offset_kcps + (int32_t)margin_offset_kcps; + + if (plane_offset_kcps_temp < 0) + plane_offset_kcps_temp = 0; + else + if (plane_offset_kcps_temp > 0x3FFFF) + plane_offset_kcps_temp = 0x3FFFF; + + plane_offset_with_margin = (uint32_t) plane_offset_kcps_temp; + + return plane_offset_with_margin; +} + +uint16_t VL53LX_calc_range_ignore_threshold(uint32_t central_rate, int16_t x_gradient, int16_t y_gradient, uint8_t rate_mult) +{ + int32_t range_ignore_thresh_int = 0; + uint16_t range_ignore_thresh_kcps = 0; + int32_t central_rate_int = 0; + int16_t x_gradient_int = 0; + int16_t y_gradient_int = 0; + + central_rate_int = ((int32_t)central_rate * (1 << 4)) / (1000); + + if (x_gradient < 0) + x_gradient_int = x_gradient * -1; + + if (y_gradient < 0) + y_gradient_int = y_gradient * -1; + + + range_ignore_thresh_int = (8 * x_gradient_int * 4) + (8 * y_gradient_int * 4); + range_ignore_thresh_int = range_ignore_thresh_int / 1000; + range_ignore_thresh_int = range_ignore_thresh_int + central_rate_int; + range_ignore_thresh_int = (int32_t)rate_mult * range_ignore_thresh_int; + range_ignore_thresh_int = (range_ignore_thresh_int + (1<<4)) / (1<<5); + + if (range_ignore_thresh_int > 0xFFFF) + range_ignore_thresh_kcps = 0xFFFF; + else + range_ignore_thresh_kcps = (uint16_t)range_ignore_thresh_int; + + return range_ignore_thresh_kcps; +} + +VL53LX_Error VL53LX_enable_xtalk_compensation(VL53LX_DEV Dev) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + uint32_t tempu32; + + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + VL53LX_xtalk_config_t *pC = &(pdev->xtalk_cfg); + VL53LX_hist_post_process_config_t *pHP = &(pdev->histpostprocess); + VL53LX_customer_nvm_managed_t *pN = &(pdev->customer); + + tempu32 = VL53LX_calc_crosstalk_plane_offset_with_margin(pC->algo__crosstalk_compensation_plane_offset_kcps, pC->lite_mode_crosstalk_margin_kcps); + if (tempu32 > 0xFFFF) + tempu32 = 0xFFFF; + + pN->algo__crosstalk_compensation_plane_offset_kcps = (uint16_t)tempu32; + pN->algo__crosstalk_compensation_x_plane_gradient_kcps = pC->algo__crosstalk_compensation_x_plane_gradient_kcps; + pN->algo__crosstalk_compensation_y_plane_gradient_kcps = pC->algo__crosstalk_compensation_y_plane_gradient_kcps; + pHP->algo__crosstalk_compensation_plane_offset_kcps = VL53LX_calc_crosstalk_plane_offset_with_margin(pC->algo__crosstalk_compensation_plane_offset_kcps, pC->histogram_mode_crosstalk_margin_kcps); + pHP->algo__crosstalk_compensation_x_plane_gradient_kcps = pC->algo__crosstalk_compensation_x_plane_gradient_kcps; + pHP->algo__crosstalk_compensation_y_plane_gradient_kcps = pC->algo__crosstalk_compensation_y_plane_gradient_kcps; + pC->global_crosstalk_compensation_enable = 0x01; + pHP->algo__crosstalk_compensation_enable = pC->global_crosstalk_compensation_enable; + + if (status == VL53LX_ERROR_NONE) { + pC->crosstalk_range_ignore_threshold_rate_mcps = + VL53LX_calc_range_ignore_threshold(pC->algo__crosstalk_compensation_plane_offset_kcps, pC->algo__crosstalk_compensation_x_plane_gradient_kcps, pC->algo__crosstalk_compensation_y_plane_gradient_kcps, pC->crosstalk_range_ignore_threshold_mult); + } + if (status == VL53LX_ERROR_NONE) + status = VL53LX_set_customer_nvm_managed(Dev, &(pdev->customer)); + + return status; +} + +VL53LX_Error VL53LX_SetXTalkCompensationEnable(VL53LX_DEV Dev, uint8_t XTalkCompensationEnable) +{ + VL53LX_Error Status = VL53LX_ERROR_NONE; + + if (XTalkCompensationEnable == 0) + Status = VL53LX_disable_xtalk_compensation(Dev); + else + Status = VL53LX_enable_xtalk_compensation(Dev); + + 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; +} + +VL53LX_Error VL53LX_get_preset_mode_timing_cfg(VL53LX_DEV Dev, VL53LX_DevicePresetModes device_preset_mode, uint16_t *pdss_config__target_total_rate_mcps, uint32_t *pphasecal_config_timeout_us, uint32_t *pmm_config_timeout_us, uint32_t *prange_config_timeout_us) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + switch (device_preset_mode) { + case VL53LX_DEVICEPRESETMODE_HISTOGRAM_LONG_RANGE: + *pdss_config__target_total_rate_mcps = pdev->tuning_parms.tp_dss_target_histo_mcps; + *pphasecal_config_timeout_us = pdev->tuning_parms.tp_phasecal_timeout_hist_long_us; + *pmm_config_timeout_us = pdev->tuning_parms.tp_mm_timeout_histo_us; + *prange_config_timeout_us = pdev->tuning_parms.tp_range_timeout_histo_us; + break; + case VL53LX_DEVICEPRESETMODE_HISTOGRAM_MEDIUM_RANGE: + *pdss_config__target_total_rate_mcps = pdev->tuning_parms.tp_dss_target_histo_mcps; + *pphasecal_config_timeout_us = pdev->tuning_parms.tp_phasecal_timeout_hist_med_us; + *pmm_config_timeout_us = pdev->tuning_parms.tp_mm_timeout_histo_us; + *prange_config_timeout_us = pdev->tuning_parms.tp_range_timeout_histo_us; + break; + case VL53LX_DEVICEPRESETMODE_HISTOGRAM_SHORT_RANGE: + *pdss_config__target_total_rate_mcps = pdev->tuning_parms.tp_dss_target_histo_mcps; + *pphasecal_config_timeout_us = pdev->tuning_parms.tp_phasecal_timeout_hist_short_us; + *pmm_config_timeout_us = pdev->tuning_parms.tp_mm_timeout_histo_us; + *prange_config_timeout_us = pdev->tuning_parms.tp_range_timeout_histo_us; + break; + default: + status = VL53LX_ERROR_INVALID_PARAMS; + break; + } + + return status; +} + +VL53LX_Error VL53LX_preset_mode_standard_ranging( + VL53LX_static_config_t *pstatic, + VL53LX_histogram_config_t *phistogram, + VL53LX_general_config_t *pgeneral, + VL53LX_timing_config_t *ptiming, + VL53LX_dynamic_config_t *pdynamic, + VL53LX_system_control_t *psystem, + VL53LX_tuning_parm_storage_t *ptuning_parms, + VL53LX_zone_config_t *pzone_cfg) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + pstatic->dss_config__target_total_rate_mcps = 0x0A00; + pstatic->debug__ctrl = 0x00; + pstatic->test_mode__ctrl = 0x00; + pstatic->clk_gating__ctrl = 0x00; + pstatic->nvm_bist__ctrl = 0x00; + pstatic->nvm_bist__num_nvm_words = 0x00; + pstatic->nvm_bist__start_address = 0x00; + pstatic->host_if__status = 0x00; + pstatic->pad_i2c_hv__config = 0x00; + pstatic->pad_i2c_hv__extsup_config = 0x00; + pstatic->gpio_hv_pad__ctrl = 0x00; + pstatic->gpio_hv_mux__ctrl = VL53LX_DEVICEINTERRUPTPOLARITY_ACTIVE_LOW | VL53LX_DEVICEGPIOMODE_OUTPUT_RANGE_AND_ERROR_INTERRUPTS; + pstatic->gpio__tio_hv_status = 0x02; + pstatic->gpio__fio_hv_status = 0x00; + pstatic->ana_config__spad_sel_pswidth = 0x02; + pstatic->ana_config__vcsel_pulse_width_offset = 0x08; + pstatic->ana_config__fast_osc__config_ctrl = 0x00; + pstatic->sigma_estimator__effective_pulse_width_ns = ptuning_parms->tp_lite_sigma_est_pulse_width_ns; + pstatic->sigma_estimator__effective_ambient_width_ns = ptuning_parms->tp_lite_sigma_est_amb_width_ns; + pstatic->sigma_estimator__sigma_ref_mm = ptuning_parms->tp_lite_sigma_ref_mm; + pstatic->algo__crosstalk_compensation_valid_height_mm = 0x01; + pstatic->spare_host_config__static_config_spare_0 = 0x00; + pstatic->spare_host_config__static_config_spare_1 = 0x00; + pstatic->algo__range_ignore_threshold_mcps = 0x0000; + pstatic->algo__range_ignore_valid_height_mm = 0xff; + pstatic->algo__range_min_clip = ptuning_parms->tp_lite_min_clip; + pstatic->algo__consistency_check__tolerance = ptuning_parms->tp_consistency_lite_phase_tolerance; + pstatic->spare_host_config__static_config_spare_2 = 0x00; + pstatic->sd_config__reset_stages_msb = 0x00; + pstatic->sd_config__reset_stages_lsb = 0x00; + pgeneral->gph_config__stream_count_update_value = 0x00; + pgeneral->global_config__stream_divider = 0x00; + pgeneral->system__interrupt_config_gpio = VL53LX_INTERRUPT_CONFIG_NEW_SAMPLE_READY; + pgeneral->cal_config__vcsel_start = 0x0B; + pgeneral->cal_config__repeat_rate = ptuning_parms->tp_cal_repeat_rate; + pgeneral->global_config__vcsel_width = 0x02; + pgeneral->phasecal_config__timeout_macrop = 0x0D; + pgeneral->phasecal_config__target = ptuning_parms->tp_phasecal_target; + pgeneral->phasecal_config__override = 0x00; + pgeneral->dss_config__roi_mode_control = VL53LX_DEVICEDSSMODE__TARGET_RATE; + pgeneral->system__thresh_rate_high = 0x0000; + pgeneral->system__thresh_rate_low = 0x0000; + pgeneral->dss_config__manual_effective_spads_select = 0x8C00; + pgeneral->dss_config__manual_block_select = 0x00; + pgeneral->dss_config__aperture_attenuation = 0x38; + pgeneral->dss_config__max_spads_limit = 0xFF; + pgeneral->dss_config__min_spads_limit = 0x01; + ptiming->mm_config__timeout_macrop_a_hi = 0x00; + ptiming->mm_config__timeout_macrop_a_lo = 0x1a; + ptiming->mm_config__timeout_macrop_b_hi = 0x00; + ptiming->mm_config__timeout_macrop_b_lo = 0x20; + ptiming->range_config__timeout_macrop_a_hi = 0x01; + ptiming->range_config__timeout_macrop_a_lo = 0xCC; + ptiming->range_config__vcsel_period_a = 0x0B; + ptiming->range_config__timeout_macrop_b_hi = 0x01; + ptiming->range_config__timeout_macrop_b_lo = 0xF5; + ptiming->range_config__vcsel_period_b = 0x09; + ptiming->range_config__sigma_thresh = ptuning_parms->tp_lite_med_sigma_thresh_mm; + ptiming->range_config__min_count_rate_rtn_limit_mcps = ptuning_parms->tp_lite_med_min_count_rate_rtn_mcps; + ptiming->range_config__valid_phase_low = 0x08; + ptiming->range_config__valid_phase_high = 0x78; + ptiming->system__intermeasurement_period = 0x00000000; + ptiming->system__fractional_enable = 0x00; + phistogram->histogram_config__low_amb_even_bin_0_1 = 0x07; + phistogram->histogram_config__low_amb_even_bin_2_3 = 0x21; + phistogram->histogram_config__low_amb_even_bin_4_5 = 0x43; + phistogram->histogram_config__low_amb_odd_bin_0_1 = 0x10; + phistogram->histogram_config__low_amb_odd_bin_2_3 = 0x32; + phistogram->histogram_config__low_amb_odd_bin_4_5 = 0x54; + phistogram->histogram_config__mid_amb_even_bin_0_1 = 0x07; + phistogram->histogram_config__mid_amb_even_bin_2_3 = 0x21; + phistogram->histogram_config__mid_amb_even_bin_4_5 = 0x43; + phistogram->histogram_config__mid_amb_odd_bin_0_1 = 0x10; + phistogram->histogram_config__mid_amb_odd_bin_2 = 0x02; + phistogram->histogram_config__mid_amb_odd_bin_3_4 = 0x43; + phistogram->histogram_config__mid_amb_odd_bin_5 = 0x05; + phistogram->histogram_config__user_bin_offset = 0x00; + phistogram->histogram_config__high_amb_even_bin_0_1 = 0x07; + phistogram->histogram_config__high_amb_even_bin_2_3 = 0x21; + phistogram->histogram_config__high_amb_even_bin_4_5 = 0x43; + phistogram->histogram_config__high_amb_odd_bin_0_1 = 0x10; + phistogram->histogram_config__high_amb_odd_bin_2_3 = 0x32; + phistogram->histogram_config__high_amb_odd_bin_4_5 = 0x54; + phistogram->histogram_config__amb_thresh_low = 0xFFFF; + phistogram->histogram_config__amb_thresh_high = 0xFFFF; + phistogram->histogram_config__spad_array_selection = 0x00; + pzone_cfg->max_zones = VL53LX_MAX_USER_ZONES; + pzone_cfg->active_zones = 0x00; + pzone_cfg->user_zones[0].height = 0x0f; + pzone_cfg->user_zones[0].width = 0x0f; + pzone_cfg->user_zones[0].x_centre = 0x08; + pzone_cfg->user_zones[0].y_centre = 0x08; + pdynamic->system__grouped_parameter_hold_0 = 0x01; + pdynamic->system__thresh_high = 0x0000; + pdynamic->system__thresh_low = 0x0000; + pdynamic->system__enable_xtalk_per_quadrant = 0x00; + pdynamic->system__seed_config = ptuning_parms->tp_lite_seed_cfg; + pdynamic->sd_config__woi_sd0 = 0x0B; + pdynamic->sd_config__woi_sd1 = 0x09; + pdynamic->sd_config__initial_phase_sd0 = ptuning_parms->tp_init_phase_rtn_lite_med; + pdynamic->sd_config__initial_phase_sd1 = ptuning_parms->tp_init_phase_ref_lite_med; + pdynamic->system__grouped_parameter_hold_1 = 0x01; + pdynamic->sd_config__first_order_select = ptuning_parms->tp_lite_first_order_select; + pdynamic->sd_config__quantifier = ptuning_parms->tp_lite_quantifier; + pdynamic->roi_config__user_roi_centre_spad = 0xC7; + pdynamic->roi_config__user_roi_requested_global_xy_size = 0xFF; + pdynamic->system__sequence_config = VL53LX_SEQUENCE_VHV_EN | VL53LX_SEQUENCE_PHASECAL_EN | VL53LX_SEQUENCE_DSS1_EN | VL53LX_SEQUENCE_DSS2_EN | VL53LX_SEQUENCE_MM2_EN | VL53LX_SEQUENCE_RANGE_EN; + pdynamic->system__grouped_parameter_hold = 0x02; + psystem->system__stream_count_ctrl = 0x00; + psystem->firmware__enable = 0x01; + psystem->system__interrupt_clear = VL53LX_CLEAR_RANGE_INT; + psystem->system__mode_start = VL53LX_DEVICESCHEDULERMODE_STREAMING | VL53LX_DEVICEREADOUTMODE_SINGLE_SD | VL53LX_DEVICEMEASUREMENTMODE_BACKTOBACK; + + return status; +} + +void VL53LX_init_histogram_config_structure( + uint8_t even_bin0, + uint8_t even_bin1, + uint8_t even_bin2, + uint8_t even_bin3, + uint8_t even_bin4, + uint8_t even_bin5, + uint8_t odd_bin0, + uint8_t odd_bin1, + uint8_t odd_bin2, + uint8_t odd_bin3, + uint8_t odd_bin4, + uint8_t odd_bin5, + VL53LX_histogram_config_t *pdata) +{ + pdata->histogram_config__low_amb_even_bin_0_1 = (even_bin1 << 4) + even_bin0; + pdata->histogram_config__low_amb_even_bin_2_3 = (even_bin3 << 4) + even_bin2; + pdata->histogram_config__low_amb_even_bin_4_5 = (even_bin5 << 4) + even_bin4; + pdata->histogram_config__low_amb_odd_bin_0_1 = (odd_bin1 << 4) + odd_bin0; + pdata->histogram_config__low_amb_odd_bin_2_3 = (odd_bin3 << 4) + odd_bin2; + pdata->histogram_config__low_amb_odd_bin_4_5 = (odd_bin5 << 4) + odd_bin4; + pdata->histogram_config__mid_amb_even_bin_0_1 = pdata->histogram_config__low_amb_even_bin_0_1; + pdata->histogram_config__mid_amb_even_bin_2_3 = pdata->histogram_config__low_amb_even_bin_2_3; + pdata->histogram_config__mid_amb_even_bin_4_5 = pdata->histogram_config__low_amb_even_bin_4_5; + pdata->histogram_config__mid_amb_odd_bin_0_1 = pdata->histogram_config__low_amb_odd_bin_0_1; + pdata->histogram_config__mid_amb_odd_bin_2 = odd_bin2; + pdata->histogram_config__mid_amb_odd_bin_3_4 = (odd_bin4 << 4) + odd_bin3; + pdata->histogram_config__mid_amb_odd_bin_5 = odd_bin5; + pdata->histogram_config__user_bin_offset = 0x00; + pdata->histogram_config__high_amb_even_bin_0_1 = pdata->histogram_config__low_amb_even_bin_0_1; + pdata->histogram_config__high_amb_even_bin_2_3 = pdata->histogram_config__low_amb_even_bin_2_3; + pdata->histogram_config__high_amb_even_bin_4_5 = pdata->histogram_config__low_amb_even_bin_4_5; + pdata->histogram_config__high_amb_odd_bin_0_1 = pdata->histogram_config__low_amb_odd_bin_0_1; + pdata->histogram_config__high_amb_odd_bin_2_3 = pdata->histogram_config__low_amb_odd_bin_2_3; + pdata->histogram_config__high_amb_odd_bin_4_5 = pdata->histogram_config__low_amb_odd_bin_4_5; + pdata->histogram_config__amb_thresh_low = 0xFFFF; + pdata->histogram_config__amb_thresh_high = 0xFFFF; + pdata->histogram_config__spad_array_selection = 0x00; +} + +void VL53LX_init_histogram_multizone_config_structure( + uint8_t even_bin0, + uint8_t even_bin1, + uint8_t even_bin2, + uint8_t even_bin3, + uint8_t even_bin4, + uint8_t even_bin5, + uint8_t odd_bin0, + uint8_t odd_bin1, + uint8_t odd_bin2, + uint8_t odd_bin3, + uint8_t odd_bin4, + uint8_t odd_bin5, + VL53LX_histogram_config_t *pdata) +{ + pdata->histogram_config__low_amb_even_bin_0_1 = (even_bin1 << 4) + even_bin0; + pdata->histogram_config__low_amb_even_bin_2_3 = (even_bin3 << 4) + even_bin2; + pdata->histogram_config__low_amb_even_bin_4_5 = (even_bin5 << 4) + even_bin4; + pdata->histogram_config__low_amb_odd_bin_0_1 = pdata->histogram_config__low_amb_even_bin_0_1; + pdata->histogram_config__low_amb_odd_bin_2_3 = pdata->histogram_config__low_amb_even_bin_2_3; + pdata->histogram_config__low_amb_odd_bin_4_5 = pdata->histogram_config__low_amb_even_bin_4_5; + pdata->histogram_config__mid_amb_even_bin_0_1 = pdata->histogram_config__low_amb_even_bin_0_1; + pdata->histogram_config__mid_amb_even_bin_2_3 = pdata->histogram_config__low_amb_even_bin_2_3; + pdata->histogram_config__mid_amb_even_bin_4_5 = pdata->histogram_config__low_amb_even_bin_4_5; + pdata->histogram_config__mid_amb_odd_bin_0_1 = pdata->histogram_config__low_amb_odd_bin_0_1; + pdata->histogram_config__mid_amb_odd_bin_2 = odd_bin2; + pdata->histogram_config__mid_amb_odd_bin_3_4 = (odd_bin4 << 4) + odd_bin3; + pdata->histogram_config__mid_amb_odd_bin_5 = odd_bin5; + pdata->histogram_config__user_bin_offset = 0x00; + pdata->histogram_config__high_amb_even_bin_0_1 = (odd_bin1 << 4) + odd_bin0; + pdata->histogram_config__high_amb_even_bin_2_3 = (odd_bin3 << 4) + odd_bin2; + pdata->histogram_config__high_amb_even_bin_4_5 = (odd_bin5 << 4) + odd_bin4; + pdata->histogram_config__high_amb_odd_bin_0_1 = pdata->histogram_config__high_amb_even_bin_0_1; + pdata->histogram_config__high_amb_odd_bin_2_3 = pdata->histogram_config__high_amb_even_bin_2_3; + pdata->histogram_config__high_amb_odd_bin_4_5 = pdata->histogram_config__high_amb_even_bin_4_5; + pdata->histogram_config__amb_thresh_low = 0xFFFF; + pdata->histogram_config__amb_thresh_high = 0xFFFF; + pdata->histogram_config__spad_array_selection = 0x00; +} + +void VL53LX_copy_hist_cfg_to_static_cfg( + VL53LX_histogram_config_t *phistogram, + VL53LX_static_config_t *pstatic, + VL53LX_general_config_t *pgeneral, + VL53LX_timing_config_t *ptiming, + VL53LX_dynamic_config_t *pdynamic) +{ + SUPPRESS_UNUSED_WARNING(pgeneral); + + pstatic->sigma_estimator__effective_pulse_width_ns = phistogram->histogram_config__high_amb_even_bin_0_1; + pstatic->sigma_estimator__effective_ambient_width_ns = phistogram->histogram_config__high_amb_even_bin_2_3; + pstatic->sigma_estimator__sigma_ref_mm = phistogram->histogram_config__high_amb_even_bin_4_5; + pstatic->algo__crosstalk_compensation_valid_height_mm = phistogram->histogram_config__high_amb_odd_bin_0_1; + pstatic->spare_host_config__static_config_spare_0 = phistogram->histogram_config__high_amb_odd_bin_2_3; + pstatic->spare_host_config__static_config_spare_1 = phistogram->histogram_config__high_amb_odd_bin_4_5; + pstatic->algo__range_ignore_threshold_mcps = (((uint16_t)phistogram->histogram_config__mid_amb_even_bin_0_1) << 8) + (uint16_t)phistogram->histogram_config__mid_amb_even_bin_2_3; + pstatic->algo__range_ignore_valid_height_mm = phistogram->histogram_config__mid_amb_even_bin_4_5; + pstatic->algo__range_min_clip = phistogram->histogram_config__mid_amb_odd_bin_0_1; + pstatic->algo__consistency_check__tolerance = phistogram->histogram_config__mid_amb_odd_bin_2; + pstatic->spare_host_config__static_config_spare_2 = phistogram->histogram_config__mid_amb_odd_bin_3_4; + pstatic->sd_config__reset_stages_msb = phistogram->histogram_config__mid_amb_odd_bin_5; + pstatic->sd_config__reset_stages_lsb = phistogram->histogram_config__user_bin_offset; + ptiming->range_config__sigma_thresh = (((uint16_t)phistogram->histogram_config__low_amb_even_bin_0_1) << 8) + (uint16_t)phistogram->histogram_config__low_amb_even_bin_2_3; + ptiming->range_config__min_count_rate_rtn_limit_mcps = (((uint16_t)phistogram->histogram_config__low_amb_even_bin_4_5) << 8) + (uint16_t)phistogram->histogram_config__low_amb_odd_bin_0_1; + ptiming->range_config__valid_phase_low = phistogram->histogram_config__low_amb_odd_bin_2_3; + ptiming->range_config__valid_phase_high = phistogram->histogram_config__low_amb_odd_bin_4_5; + pdynamic->system__thresh_high = phistogram->histogram_config__amb_thresh_low; + pdynamic->system__thresh_low = phistogram->histogram_config__amb_thresh_high; + pdynamic->system__enable_xtalk_per_quadrant = phistogram->histogram_config__spad_array_selection; +} + +VL53LX_Error VL53LX_preset_mode_histogram_ranging( + VL53LX_hist_post_process_config_t *phistpostprocess, + VL53LX_static_config_t *pstatic, + VL53LX_histogram_config_t *phistogram, + VL53LX_general_config_t *pgeneral, + VL53LX_timing_config_t *ptiming, + VL53LX_dynamic_config_t *pdynamic, + VL53LX_system_control_t *psystem, + VL53LX_tuning_parm_storage_t *ptuning_parms, + VL53LX_zone_config_t *pzone_cfg) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + status = VL53LX_preset_mode_standard_ranging(pstatic, phistogram, pgeneral, ptiming, pdynamic, psystem, ptuning_parms, pzone_cfg); + if (status == VL53LX_ERROR_NONE) { + pstatic->dss_config__target_total_rate_mcps = 0x1400; + VL53LX_init_histogram_config_structure(7, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, phistogram); + VL53LX_init_histogram_multizone_config_structure(7, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, &(pzone_cfg->multizone_hist_cfg)); + ptiming->range_config__vcsel_period_a = 0x09; + ptiming->range_config__vcsel_period_b = 0x0B; + pdynamic->sd_config__woi_sd0 = 0x09; + pdynamic->sd_config__woi_sd1 = 0x0B; + ptiming->mm_config__timeout_macrop_a_hi = 0x00; + ptiming->mm_config__timeout_macrop_a_lo = 0x20; + ptiming->mm_config__timeout_macrop_b_hi = 0x00; + ptiming->mm_config__timeout_macrop_b_lo = 0x1A; + ptiming->range_config__timeout_macrop_a_hi = 0x00; + ptiming->range_config__timeout_macrop_a_lo = 0x28; + ptiming->range_config__timeout_macrop_b_hi = 0x00; + ptiming->range_config__timeout_macrop_b_lo = 0x21; + pgeneral->phasecal_config__timeout_macrop = 0xF5; + phistpostprocess->valid_phase_low = 0x08; + phistpostprocess->valid_phase_high = 0x88; + VL53LX_copy_hist_cfg_to_static_cfg(phistogram, pstatic, pgeneral, ptiming, pdynamic); + pdynamic->system__sequence_config = VL53LX_SEQUENCE_VHV_EN | VL53LX_SEQUENCE_PHASECAL_EN | VL53LX_SEQUENCE_DSS1_EN | VL53LX_SEQUENCE_DSS2_EN | VL53LX_SEQUENCE_RANGE_EN; + psystem->system__mode_start = VL53LX_DEVICESCHEDULERMODE_HISTOGRAM | VL53LX_DEVICEREADOUTMODE_DUAL_SD | VL53LX_DEVICEMEASUREMENTMODE_BACKTOBACK; + } + return status; +} + +VL53LX_Error VL53LX_preset_mode_histogram_long_range( + VL53LX_hist_post_process_config_t *phistpostprocess, + VL53LX_static_config_t *pstatic, + VL53LX_histogram_config_t *phistogram, + VL53LX_general_config_t *pgeneral, + VL53LX_timing_config_t *ptiming, + VL53LX_dynamic_config_t *pdynamic, + VL53LX_system_control_t *psystem, + VL53LX_tuning_parm_storage_t *ptuning_parms, + VL53LX_zone_config_t *pzone_cfg) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + status = VL53LX_preset_mode_histogram_ranging(phistpostprocess, pstatic, phistogram, pgeneral, ptiming, pdynamic, psystem, ptuning_parms, pzone_cfg); + if (status == VL53LX_ERROR_NONE) { + VL53LX_init_histogram_config_structure(7, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, phistogram); + VL53LX_init_histogram_multizone_config_structure(7, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, &(pzone_cfg->multizone_hist_cfg)); + VL53LX_copy_hist_cfg_to_static_cfg(phistogram, pstatic, pgeneral, ptiming, pdynamic); + ptiming->range_config__vcsel_period_a = 0x09; + ptiming->range_config__vcsel_period_b = 0x0b; + ptiming->mm_config__timeout_macrop_a_hi = 0x00; + ptiming->mm_config__timeout_macrop_a_lo = 0x21; + ptiming->mm_config__timeout_macrop_b_hi = 0x00; + ptiming->mm_config__timeout_macrop_b_lo = 0x1b; + ptiming->range_config__timeout_macrop_a_hi = 0x00; + ptiming->range_config__timeout_macrop_a_lo = 0x29; + ptiming->range_config__timeout_macrop_b_hi = 0x00; + ptiming->range_config__timeout_macrop_b_lo = 0x22; + pgeneral->cal_config__vcsel_start = 0x09; + pgeneral->phasecal_config__timeout_macrop = 0xF5; + pdynamic->sd_config__woi_sd0 = 0x09; + pdynamic->sd_config__woi_sd1 = 0x0B; + pdynamic->sd_config__initial_phase_sd0 = ptuning_parms->tp_init_phase_rtn_hist_long; + pdynamic->sd_config__initial_phase_sd1 = ptuning_parms->tp_init_phase_ref_hist_long; + phistpostprocess->valid_phase_low = 0x08; + phistpostprocess->valid_phase_high = 0x88; + pdynamic->system__sequence_config = VL53LX_SEQUENCE_VHV_EN | VL53LX_SEQUENCE_PHASECAL_EN | VL53LX_SEQUENCE_DSS1_EN | VL53LX_SEQUENCE_DSS2_EN | VL53LX_SEQUENCE_RANGE_EN; + psystem->system__mode_start = VL53LX_DEVICESCHEDULERMODE_HISTOGRAM | VL53LX_DEVICEREADOUTMODE_DUAL_SD | VL53LX_DEVICEMEASUREMENTMODE_BACKTOBACK; + } + return status; +} + +VL53LX_Error VL53LX_set_inter_measurement_period_ms(VL53LX_DEV Dev, uint32_t inter_measurement_period_ms) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + if (pdev->dbg_results.result__osc_calibrate_val == 0) + status = VL53LX_ERROR_DIVISION_BY_ZERO; + + if (status == VL53LX_ERROR_NONE) { + pdev->inter_measurement_period_ms = inter_measurement_period_ms; + pdev->tim_cfg.system__intermeasurement_period = inter_measurement_period_ms * (uint32_t)pdev->dbg_results.result__osc_calibrate_val; + } + return status; +} + +VL53LX_Error VL53LX_preset_mode_histogram_medium_range( + VL53LX_hist_post_process_config_t *phistpostprocess, + VL53LX_static_config_t *pstatic, + VL53LX_histogram_config_t *phistogram, + VL53LX_general_config_t *pgeneral, + VL53LX_timing_config_t *ptiming, + VL53LX_dynamic_config_t *pdynamic, + VL53LX_system_control_t *psystem, + VL53LX_tuning_parm_storage_t *ptuning_parms, + VL53LX_zone_config_t *pzone_cfg) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + status = VL53LX_preset_mode_histogram_ranging(phistpostprocess, pstatic, phistogram, pgeneral, ptiming, pdynamic, psystem, ptuning_parms, pzone_cfg); + + if (status == VL53LX_ERROR_NONE) { + VL53LX_init_histogram_config_structure(7, 0, 1, 1, 2, 2, 0, 1, 2, 1, 2, 3, phistogram); + VL53LX_init_histogram_multizone_config_structure(7, 0, 1, 1, 2, 2, 0, 1, 2, 1, 2, 3, &(pzone_cfg->multizone_hist_cfg)); + VL53LX_copy_hist_cfg_to_static_cfg(phistogram, pstatic, pgeneral, ptiming, pdynamic); + + ptiming->range_config__vcsel_period_a = 0x05; + ptiming->range_config__vcsel_period_b = 0x07; + + ptiming->mm_config__timeout_macrop_a_hi = 0x00; + ptiming->mm_config__timeout_macrop_a_lo = 0x36; + ptiming->mm_config__timeout_macrop_b_hi = 0x00; + ptiming->mm_config__timeout_macrop_b_lo = 0x28; + + ptiming->range_config__timeout_macrop_a_hi = 0x00; + ptiming->range_config__timeout_macrop_a_lo = 0x44; + ptiming->range_config__timeout_macrop_b_hi = 0x00; + ptiming->range_config__timeout_macrop_b_lo = 0x33; + + pgeneral->cal_config__vcsel_start = 0x05; + + pgeneral->phasecal_config__timeout_macrop = 0xF5; + + pdynamic->sd_config__woi_sd0 = 0x05; + pdynamic->sd_config__woi_sd1 = 0x07; + pdynamic->sd_config__initial_phase_sd0 = ptuning_parms->tp_init_phase_rtn_hist_med; + pdynamic->sd_config__initial_phase_sd1 = ptuning_parms->tp_init_phase_ref_hist_med; + + phistpostprocess->valid_phase_low = 0x08; + phistpostprocess->valid_phase_high = 0x48; + + pdynamic->system__sequence_config = VL53LX_SEQUENCE_VHV_EN | VL53LX_SEQUENCE_PHASECAL_EN | VL53LX_SEQUENCE_DSS1_EN | VL53LX_SEQUENCE_DSS2_EN | VL53LX_SEQUENCE_RANGE_EN; + + psystem->system__mode_start = VL53LX_DEVICESCHEDULERMODE_HISTOGRAM | VL53LX_DEVICEREADOUTMODE_DUAL_SD | VL53LX_DEVICEMEASUREMENTMODE_BACKTOBACK; + } + return status; +} + + +VL53LX_Error VL53LX_set_preset_mode(VL53LX_DEV Dev, VL53LX_DevicePresetModes device_preset_mode, uint16_t dss_config__target_total_rate_mcps, uint32_t phasecal_config_timeout_us, uint32_t mm_config_timeout_us, uint32_t range_config_timeout_us, uint32_t inter_measurement_period_ms) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + VL53LX_LLDriverResults_t *pres = VL53LXDevStructGetLLResultsHandle(Dev); + + VL53LX_hist_post_process_config_t *phistpostprocess = &(pdev->histpostprocess); + + VL53LX_static_config_t *pstatic = &(pdev->stat_cfg); + VL53LX_histogram_config_t *phistogram = &(pdev->hist_cfg); + VL53LX_general_config_t *pgeneral = &(pdev->gen_cfg); + VL53LX_timing_config_t *ptiming = &(pdev->tim_cfg); + VL53LX_dynamic_config_t *pdynamic = &(pdev->dyn_cfg); + VL53LX_system_control_t *psystem = &(pdev->sys_ctrl); + VL53LX_zone_config_t *pzone_cfg = &(pdev->zone_cfg); + VL53LX_tuning_parm_storage_t *ptuning_parms = &(pdev->tuning_parms); + + pdev->preset_mode = device_preset_mode; + pdev->mm_config_timeout_us = mm_config_timeout_us; + pdev->range_config_timeout_us = range_config_timeout_us; + pdev->inter_measurement_period_ms = inter_measurement_period_ms; + + VL53LX_init_ll_driver_state(Dev, VL53LX_DEVICESTATE_SW_STANDBY); + + switch (device_preset_mode) { + case VL53LX_DEVICEPRESETMODE_HISTOGRAM_LONG_RANGE: + status = VL53LX_preset_mode_histogram_long_range(phistpostprocess, pstatic, phistogram, pgeneral, ptiming, pdynamic, psystem, ptuning_parms, pzone_cfg); + break; + case VL53LX_DEVICEPRESETMODE_HISTOGRAM_MEDIUM_RANGE: + status = VL53LX_preset_mode_histogram_medium_range(phistpostprocess, pstatic, phistogram, pgeneral, ptiming, pdynamic, psystem, ptuning_parms, pzone_cfg); + break; + case VL53LX_DEVICEPRESETMODE_HISTOGRAM_SHORT_RANGE: + status = VL53LX_preset_mode_histogram_short_range(phistpostprocess, pstatic, phistogram, pgeneral, ptiming, pdynamic, psystem, ptuning_parms, pzone_cfg); + break; + default: + status = VL53LX_ERROR_INVALID_PARAMS; + break; + } + if (status == VL53LX_ERROR_NONE) { + pstatic->dss_config__target_total_rate_mcps = dss_config__target_total_rate_mcps; + pdev->dss_config__target_total_rate_mcps = dss_config__target_total_rate_mcps; + } + if (status == VL53LX_ERROR_NONE) + status = VL53LX_set_timeouts_us(Dev, phasecal_config_timeout_us, mm_config_timeout_us, range_config_timeout_us); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_set_inter_measurement_period_ms(Dev, inter_measurement_period_ms); + + V53L1_init_zone_results_structure(pdev->zone_cfg.active_zones+1, &(pres->zone_results)); + + 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; + + 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); + + 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; + + 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); + } + return Status; +} + +VL53LX_Error VL53LX_set_offset_correction_mode(VL53LX_DEV Dev, VL53LX_OffsetCorrectionMode offset_cor_mode) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + pdev->offset_correction_mode = offset_cor_mode; + + return status; +} + +VL53LX_Error VL53LX_SetOffsetCorrectionMode(VL53LX_DEV Dev, VL53LX_OffsetCorrectionModes OffsetCorrectionMode) +{ + VL53LX_Error Status = VL53LX_ERROR_NONE; + VL53LX_OffsetCorrectionMode offset_cor_mode; + + 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); + + return Status; +} + +VL53LX_Error VL53LX_dynamic_xtalk_correction_disable(VL53LX_DEV Dev) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + pdev->smudge_correct_config.smudge_corr_enabled = 0; + return status; +} + +VL53LX_Error VL53LX_dynamic_xtalk_correction_apply_disable(VL53LX_DEV Dev) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + pdev->smudge_correct_config.smudge_corr_apply_enabled = 0; + + return status; +} + +VL53LX_Error VL53LX_dynamic_xtalk_correction_single_apply_disable(VL53LX_DEV Dev) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + pdev->smudge_correct_config.smudge_corr_single_apply = 0; + + return status; +} + +VL53LX_Error VL53LX_dynamic_xtalk_correction_enable(VL53LX_DEV Dev) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + pdev->smudge_correct_config.smudge_corr_enabled = 1; + + return status; +} + +VL53LX_Error VL53LX_dynamic_xtalk_correction_apply_enable(VL53LX_DEV Dev) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + pdev->smudge_correct_config.smudge_corr_apply_enabled = 1; + + return status; +} + +VL53LX_Error VL53LX_dynamic_xtalk_correction_single_apply_enable(VL53LX_DEV Dev) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + pdev->smudge_correct_config.smudge_corr_single_apply = 1; + + 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; + + 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; + } + return Status; +} + +static VL53LX_Error CheckValidRectRoi(VL53LX_UserRoi_t ROI) +{ + VL53LX_Error Status = VL53LX_ERROR_NONE; + + 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; + + return Status; +} + +VL53LX_Error VL53LX_init_zone_config_histogram_bins(VL53LX_zone_config_t *pdata) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + uint8_t i; + + for (i = 0; i < pdata->max_zones; i++) + pdata->bin_config[i] = VL53LX_ZONECONFIG_BINCONFIG__LOWAMB; + + return status; +} + + +VL53LX_Error VL53LX_set_zone_config(VL53LX_DEV Dev, VL53LX_zone_config_t *pzone_cfg) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + memcpy(&(pdev->zone_cfg.user_zones), &(pzone_cfg->user_zones), sizeof(pdev->zone_cfg.user_zones)); + + pdev->zone_cfg.max_zones = pzone_cfg->max_zones; + pdev->zone_cfg.active_zones = pzone_cfg->active_zones; + + status = VL53LX_init_zone_config_histogram_bins(&pdev->zone_cfg); + + if (pzone_cfg->active_zones == 0) + pdev->gen_cfg.global_config__stream_divider = 0; + else if (pzone_cfg->active_zones < VL53LX_MAX_USER_ZONES) + pdev->gen_cfg.global_config__stream_divider = pzone_cfg->active_zones + 1; + else + pdev->gen_cfg.global_config__stream_divider = VL53LX_MAX_USER_ZONES + 1; + + 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); + + return Status; +} + +static int stmvl53lx_sendparams(struct stmvl53lx_data *data) +{ + int rc = 0; + + rc = VL53LX_SetXTalkCompensationEnable(&data->stdev, data->crosstalk_enable); + if (rc) { + vl53lx_errmsg("VL53LX_SetXTalkCompensationEnable %d fail %d", data->crosstalk_enable, rc); + rc = store_last_error(data, rc); + goto done; + } + vl53lx_dbgmsg("Xtalk enable @%d\n", data->crosstalk_enable); + + rc = VL53LX_SetDistanceMode(&data->stdev, data->distance_mode); + if (rc) { + vl53lx_errmsg("VL53LX_SetDistanceMode %d fail %d", data->distance_mode, rc); + rc = store_last_error(data, rc); + goto done; + } + vl53lx_dbgmsg("distance mode @%d\n", data->distance_mode); + + rc = VL53LX_SetMeasurementTimingBudgetMicroSeconds(&data->stdev, data->timing_budget); + if (rc) { + vl53lx_errmsg("SetTimingBudget %d fail %d", data->timing_budget, rc); + rc = store_last_error(data, rc); + goto done; + } + vl53lx_dbgmsg("timing budget @%d\n", data->timing_budget); + + rc = VL53LX_SetOffsetCorrectionMode(&data->stdev, data->offset_correction_mode); + if (rc) { + vl53lx_errmsg("offset correction mode %d fail %d", data->offset_correction_mode, rc); + rc = store_last_error(data, rc); + goto done; + } + vl53lx_dbgmsg("offset correction mode @%d\n", data->offset_correction_mode); + + rc = VL53LX_SmudgeCorrectionEnable(&data->stdev, data->smudge_correction_mode); + if (rc) { + vl53lx_errmsg("smudge correction mode %d fail %d", data->smudge_correction_mode, rc); + rc = store_last_error(data, rc); + goto done; + } + vl53lx_dbgmsg("smudge correction mode @%d\n", data->smudge_correction_mode); + + rc = VL53LX_SetUserROI(&data->stdev, &data->roi_cfg); + if (rc) { + vl53lx_errmsg("VL53LX_SetUserROI fail %d\n", rc); + rc = store_last_error(data, rc); + goto done; + } + vl53lx_dbgmsg("ROI set TopLeft(%d %d) BottomRight(%d %d)\n", data->roi_cfg.TopLeftX, data->roi_cfg.TopLeftY, data->roi_cfg.BotRightX, data->roi_cfg.BotRightY); + +done: + return rc; +} + +static void kill_mz_data(VL53LX_MultiRangingData_t *pdata) +{ + int i; + + memset(pdata, 0, sizeof(*pdata)); + for (i = 0; i < VL53LX_MAX_RANGE_RESULTS; i++) + pdata->RangeData[i].RangeStatus = VL53LX_RANGESTATUS_NONE; +} + +VL53LX_Error VL53LX_enable_powerforce(VL53LX_DEV Dev) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + status = VL53LX_set_powerforce_register(Dev, 0x01); + + return status; +} + +VL53LX_Error VL53LX_get_tuning_parm(VL53LX_DEV Dev, VL53LX_TuningParms tuning_parm_key, int32_t *ptuning_parm_value) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + VL53LX_hist_post_process_config_t *pHP = &(pdev->histpostprocess); + VL53LX_xtalkextract_config_t *pXC = &(pdev->xtalk_extract_cfg); + + switch (tuning_parm_key) { + case VL53LX_TUNINGPARM_VERSION: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_tuning_parm_version; + break; + case VL53LX_TUNINGPARM_KEY_TABLE_VERSION: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_tuning_parm_key_table_version; + break; + case VL53LX_TUNINGPARM_LLD_VERSION: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_tuning_parm_lld_version; + break; + case VL53LX_TUNINGPARM_HIST_ALGO_SELECT: + *ptuning_parm_value = (int32_t)pHP->hist_algo_select; + break; + case VL53LX_TUNINGPARM_HIST_TARGET_ORDER: + *ptuning_parm_value = (int32_t)pHP->hist_target_order; + break; + case VL53LX_TUNINGPARM_HIST_FILTER_WOI_0: + *ptuning_parm_value = (int32_t)pHP->filter_woi0; + break; + case VL53LX_TUNINGPARM_HIST_FILTER_WOI_1: + *ptuning_parm_value = (int32_t)pHP->filter_woi1; + break; + case VL53LX_TUNINGPARM_HIST_AMB_EST_METHOD: + *ptuning_parm_value = (int32_t)pHP->hist_amb_est_method; + break; + case VL53LX_TUNINGPARM_HIST_AMB_THRESH_SIGMA_0: + *ptuning_parm_value = (int32_t)pHP->ambient_thresh_sigma0; + break; + case VL53LX_TUNINGPARM_HIST_AMB_THRESH_SIGMA_1: + *ptuning_parm_value = (int32_t)pHP->ambient_thresh_sigma1; + break; + case VL53LX_TUNINGPARM_HIST_MIN_AMB_THRESH_EVENTS: + *ptuning_parm_value = (int32_t)pHP->min_ambient_thresh_events; + break; + case VL53LX_TUNINGPARM_HIST_AMB_EVENTS_SCALER: + *ptuning_parm_value = (int32_t)pHP->ambient_thresh_events_scaler; + break; + case VL53LX_TUNINGPARM_HIST_NOISE_THRESHOLD: + *ptuning_parm_value = (int32_t)pHP->noise_threshold; + break; + case VL53LX_TUNINGPARM_HIST_SIGNAL_TOTAL_EVENTS_LIMIT: + *ptuning_parm_value = (int32_t)pHP->signal_total_events_limit; + break; + case VL53LX_TUNINGPARM_HIST_SIGMA_EST_REF_MM: + *ptuning_parm_value = (int32_t)pHP->sigma_estimator__sigma_ref_mm; + break; + case VL53LX_TUNINGPARM_HIST_SIGMA_THRESH_MM: + *ptuning_parm_value = (int32_t)pHP->sigma_thresh; + break; + case VL53LX_TUNINGPARM_HIST_GAIN_FACTOR: + *ptuning_parm_value = (int32_t)pdev->gain_cal.histogram_ranging_gain_factor; + break; + case VL53LX_TUNINGPARM_CONSISTENCY_HIST_PHASE_TOLERANCE: + *ptuning_parm_value = (int32_t)pHP->algo__consistency_check__phase_tolerance; + break; + case VL53LX_TUNINGPARM_CONSISTENCY_HIST_MIN_MAX_TOLERANCE_MM: + *ptuning_parm_value = (int32_t)pHP->algo__consistency_check__min_max_tolerance; + break; + case VL53LX_TUNINGPARM_CONSISTENCY_HIST_EVENT_SIGMA: + *ptuning_parm_value = (int32_t)pHP->algo__consistency_check__event_sigma; + break; + case VL53LX_TUNINGPARM_CONSISTENCY_HIST_EVENT_SIGMA_MIN_SPAD_LIMIT: + *ptuning_parm_value = (int32_t)pHP->algo__consistency_check__event_min_spad_count; + break; + case VL53LX_TUNINGPARM_INITIAL_PHASE_RTN_HISTO_LONG_RANGE: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_init_phase_rtn_hist_long; + break; + case VL53LX_TUNINGPARM_INITIAL_PHASE_RTN_HISTO_MED_RANGE: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_init_phase_rtn_hist_med; + break; + case VL53LX_TUNINGPARM_INITIAL_PHASE_RTN_HISTO_SHORT_RANGE: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_init_phase_rtn_hist_short; + break; + case VL53LX_TUNINGPARM_INITIAL_PHASE_REF_HISTO_LONG_RANGE: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_init_phase_ref_hist_long; + break; + case VL53LX_TUNINGPARM_INITIAL_PHASE_REF_HISTO_MED_RANGE: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_init_phase_ref_hist_med; + break; + case VL53LX_TUNINGPARM_INITIAL_PHASE_REF_HISTO_SHORT_RANGE: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_init_phase_ref_hist_short; + break; + case VL53LX_TUNINGPARM_XTALK_DETECT_MIN_VALID_RANGE_MM: + *ptuning_parm_value = (int32_t)(pdev->xtalk_cfg.algo__crosstalk_detect_min_valid_range_mm); + break; + case VL53LX_TUNINGPARM_XTALK_DETECT_MAX_VALID_RANGE_MM: + *ptuning_parm_value = (int32_t)(pdev->xtalk_cfg.algo__crosstalk_detect_max_valid_range_mm); + break; + case VL53LX_TUNINGPARM_XTALK_DETECT_MAX_SIGMA_MM: + *ptuning_parm_value = (int32_t)pdev->xtalk_cfg.algo__crosstalk_detect_max_sigma_mm; + break; + case VL53LX_TUNINGPARM_XTALK_DETECT_MIN_MAX_TOLERANCE: + *ptuning_parm_value = (int32_t)pHP->algo__crosstalk_detect_min_max_tolerance; + break; + case VL53LX_TUNINGPARM_XTALK_DETECT_MAX_VALID_RATE_KCPS: + *ptuning_parm_value = (int32_t)(pdev->xtalk_cfg.algo__crosstalk_detect_max_valid_rate_kcps); + break; + case VL53LX_TUNINGPARM_XTALK_DETECT_EVENT_SIGMA: + *ptuning_parm_value = (int32_t)pHP->algo__crosstalk_detect_event_sigma; + break; + case VL53LX_TUNINGPARM_HIST_XTALK_MARGIN_KCPS: + *ptuning_parm_value = (int32_t)pdev->xtalk_cfg.histogram_mode_crosstalk_margin_kcps; + break; + case VL53LX_TUNINGPARM_CONSISTENCY_LITE_PHASE_TOLERANCE: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_consistency_lite_phase_tolerance; + break; + case VL53LX_TUNINGPARM_PHASECAL_TARGET: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_phasecal_target; + break; + case VL53LX_TUNINGPARM_LITE_CAL_REPEAT_RATE: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_cal_repeat_rate; + break; + case VL53LX_TUNINGPARM_LITE_RANGING_GAIN_FACTOR: + *ptuning_parm_value = (int32_t)pdev->gain_cal.standard_ranging_gain_factor; + break; + case VL53LX_TUNINGPARM_LITE_MIN_CLIP_MM: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_lite_min_clip; + break; + case VL53LX_TUNINGPARM_LITE_LONG_SIGMA_THRESH_MM: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_lite_long_sigma_thresh_mm; + break; + case VL53LX_TUNINGPARM_LITE_MED_SIGMA_THRESH_MM: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_lite_med_sigma_thresh_mm; + break; + case VL53LX_TUNINGPARM_LITE_SHORT_SIGMA_THRESH_MM: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_lite_short_sigma_thresh_mm; + break; + case VL53LX_TUNINGPARM_LITE_LONG_MIN_COUNT_RATE_RTN_MCPS: + *ptuning_parm_value = (int32_t)(pdev->tuning_parms.tp_lite_long_min_count_rate_rtn_mcps); + break; + case VL53LX_TUNINGPARM_LITE_MED_MIN_COUNT_RATE_RTN_MCPS: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_lite_med_min_count_rate_rtn_mcps; + break; + case VL53LX_TUNINGPARM_LITE_SHORT_MIN_COUNT_RATE_RTN_MCPS: + *ptuning_parm_value = (int32_t)(pdev->tuning_parms.tp_lite_short_min_count_rate_rtn_mcps); + break; + case VL53LX_TUNINGPARM_LITE_SIGMA_EST_PULSE_WIDTH: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_lite_sigma_est_pulse_width_ns; + break; + case VL53LX_TUNINGPARM_LITE_SIGMA_EST_AMB_WIDTH_NS: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_lite_sigma_est_amb_width_ns; + break; + case VL53LX_TUNINGPARM_LITE_SIGMA_REF_MM: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_lite_sigma_ref_mm; + break; + case VL53LX_TUNINGPARM_LITE_RIT_MULT: + *ptuning_parm_value = (int32_t)pdev->xtalk_cfg.crosstalk_range_ignore_threshold_mult; + break; + case VL53LX_TUNINGPARM_LITE_SEED_CONFIG: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_lite_seed_cfg; + break; + case VL53LX_TUNINGPARM_LITE_QUANTIFIER: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_lite_quantifier; + break; + case VL53LX_TUNINGPARM_LITE_FIRST_ORDER_SELECT: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_lite_first_order_select; + break; + case VL53LX_TUNINGPARM_LITE_XTALK_MARGIN_KCPS: + *ptuning_parm_value = (int32_t)pdev->xtalk_cfg.lite_mode_crosstalk_margin_kcps; + break; + case VL53LX_TUNINGPARM_INITIAL_PHASE_RTN_LITE_LONG_RANGE: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_init_phase_rtn_lite_long; + break; + case VL53LX_TUNINGPARM_INITIAL_PHASE_RTN_LITE_MED_RANGE: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_init_phase_rtn_lite_med; + break; + case VL53LX_TUNINGPARM_INITIAL_PHASE_RTN_LITE_SHORT_RANGE: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_init_phase_rtn_lite_short; + break; + case VL53LX_TUNINGPARM_INITIAL_PHASE_REF_LITE_LONG_RANGE: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_init_phase_ref_lite_long; + break; + case VL53LX_TUNINGPARM_INITIAL_PHASE_REF_LITE_MED_RANGE: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_init_phase_ref_lite_med; + break; + case VL53LX_TUNINGPARM_INITIAL_PHASE_REF_LITE_SHORT_RANGE: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_init_phase_ref_lite_short; + break; + case VL53LX_TUNINGPARM_TIMED_SEED_CONFIG: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_timed_seed_cfg; + break; + case VL53LX_TUNINGPARM_DMAX_CFG_SIGNAL_THRESH_SIGMA: + *ptuning_parm_value = (int32_t)pdev->dmax_cfg.signal_thresh_sigma; + break; + case VL53LX_TUNINGPARM_DMAX_CFG_REFLECTANCE_ARRAY_0: + *ptuning_parm_value = (int32_t)pdev->dmax_cfg.target_reflectance_for_dmax_calc[0]; + break; + case VL53LX_TUNINGPARM_DMAX_CFG_REFLECTANCE_ARRAY_1: + *ptuning_parm_value = (int32_t)pdev->dmax_cfg.target_reflectance_for_dmax_calc[1]; + break; + case VL53LX_TUNINGPARM_DMAX_CFG_REFLECTANCE_ARRAY_2: + *ptuning_parm_value = (int32_t)pdev->dmax_cfg.target_reflectance_for_dmax_calc[2]; + break; + case VL53LX_TUNINGPARM_DMAX_CFG_REFLECTANCE_ARRAY_3: + *ptuning_parm_value = (int32_t)pdev->dmax_cfg.target_reflectance_for_dmax_calc[3]; + break; + case VL53LX_TUNINGPARM_DMAX_CFG_REFLECTANCE_ARRAY_4: + *ptuning_parm_value = (int32_t)pdev->dmax_cfg.target_reflectance_for_dmax_calc[4]; + break; + case VL53LX_TUNINGPARM_VHV_LOOPBOUND: + *ptuning_parm_value = (int32_t)pdev->stat_nvm.vhv_config__timeout_macrop_loop_bound; + break; + case VL53LX_TUNINGPARM_REFSPADCHAR_DEVICE_TEST_MODE: + *ptuning_parm_value = (int32_t)pdev->refspadchar.device_test_mode; + break; + case VL53LX_TUNINGPARM_REFSPADCHAR_VCSEL_PERIOD: + *ptuning_parm_value = (int32_t)pdev->refspadchar.VL53LX_p_005; + break; + case VL53LX_TUNINGPARM_REFSPADCHAR_PHASECAL_TIMEOUT_US: + *ptuning_parm_value = (int32_t)pdev->refspadchar.timeout_us; + break; + case VL53LX_TUNINGPARM_REFSPADCHAR_TARGET_COUNT_RATE_MCPS: + *ptuning_parm_value = (int32_t)pdev->refspadchar.target_count_rate_mcps; + break; + case VL53LX_TUNINGPARM_REFSPADCHAR_MIN_COUNTRATE_LIMIT_MCPS: + *ptuning_parm_value = (int32_t)pdev->refspadchar.min_count_rate_limit_mcps; + break; + case VL53LX_TUNINGPARM_REFSPADCHAR_MAX_COUNTRATE_LIMIT_MCPS: + *ptuning_parm_value = (int32_t)pdev->refspadchar.max_count_rate_limit_mcps; + break; + case VL53LX_TUNINGPARM_XTALK_EXTRACT_NUM_OF_SAMPLES: + *ptuning_parm_value = (int32_t)pXC->num_of_samples; + break; + case VL53LX_TUNINGPARM_XTALK_EXTRACT_MIN_FILTER_THRESH_MM: + *ptuning_parm_value = (int32_t)pXC->algo__crosstalk_extract_min_valid_range_mm; + break; + case VL53LX_TUNINGPARM_XTALK_EXTRACT_MAX_FILTER_THRESH_MM: + *ptuning_parm_value = (int32_t)pXC->algo__crosstalk_extract_max_valid_range_mm; + break; + case VL53LX_TUNINGPARM_XTALK_EXTRACT_DSS_RATE_MCPS: + *ptuning_parm_value = (int32_t)pXC->dss_config__target_total_rate_mcps; + break; + case VL53LX_TUNINGPARM_XTALK_EXTRACT_PHASECAL_TIMEOUT_US: + *ptuning_parm_value = (int32_t)pXC->phasecal_config_timeout_us; + break; + case VL53LX_TUNINGPARM_XTALK_EXTRACT_MAX_VALID_RATE_KCPS: + *ptuning_parm_value = (int32_t)pXC->algo__crosstalk_extract_max_valid_rate_kcps; + break; + case VL53LX_TUNINGPARM_XTALK_EXTRACT_SIGMA_THRESHOLD_MM: + *ptuning_parm_value = (int32_t)pXC->algo__crosstalk_extract_max_sigma_mm; + break; + case VL53LX_TUNINGPARM_XTALK_EXTRACT_DSS_TIMEOUT_US: + *ptuning_parm_value = (int32_t)pXC->mm_config_timeout_us; + break; + case VL53LX_TUNINGPARM_XTALK_EXTRACT_BIN_TIMEOUT_US: + *ptuning_parm_value = (int32_t)pXC->range_config_timeout_us; + break; + case VL53LX_TUNINGPARM_OFFSET_CAL_DSS_RATE_MCPS: + *ptuning_parm_value = (int32_t)pdev->offsetcal_cfg.dss_config__target_total_rate_mcps; + break; + case VL53LX_TUNINGPARM_OFFSET_CAL_PHASECAL_TIMEOUT_US: + *ptuning_parm_value = (int32_t)pdev->offsetcal_cfg.phasecal_config_timeout_us; + break; + case VL53LX_TUNINGPARM_OFFSET_CAL_MM_TIMEOUT_US: + *ptuning_parm_value = (int32_t)pdev->offsetcal_cfg.mm_config_timeout_us; + break; + case VL53LX_TUNINGPARM_OFFSET_CAL_RANGE_TIMEOUT_US: + *ptuning_parm_value = (int32_t)pdev->offsetcal_cfg.range_config_timeout_us; + break; + case VL53LX_TUNINGPARM_OFFSET_CAL_PRE_SAMPLES: + *ptuning_parm_value = (int32_t)pdev->offsetcal_cfg.pre_num_of_samples; + break; + case VL53LX_TUNINGPARM_OFFSET_CAL_MM1_SAMPLES: + *ptuning_parm_value = (int32_t)pdev->offsetcal_cfg.mm1_num_of_samples; + break; + case VL53LX_TUNINGPARM_OFFSET_CAL_MM2_SAMPLES: + *ptuning_parm_value = (int32_t)pdev->offsetcal_cfg.mm2_num_of_samples; + break; + case VL53LX_TUNINGPARM_ZONE_CAL_DSS_RATE_MCPS: + *ptuning_parm_value = (int32_t)pdev->zonecal_cfg.dss_config__target_total_rate_mcps; + break; + case VL53LX_TUNINGPARM_ZONE_CAL_PHASECAL_TIMEOUT_US: + *ptuning_parm_value = (int32_t)pdev->zonecal_cfg.phasecal_config_timeout_us; + break; + case VL53LX_TUNINGPARM_ZONE_CAL_DSS_TIMEOUT_US: + *ptuning_parm_value = (int32_t)pdev->zonecal_cfg.mm_config_timeout_us; + break; + case VL53LX_TUNINGPARM_ZONE_CAL_PHASECAL_NUM_SAMPLES: + *ptuning_parm_value = (int32_t)pdev->zonecal_cfg.phasecal_num_of_samples; + break; + case VL53LX_TUNINGPARM_ZONE_CAL_RANGE_TIMEOUT_US: + *ptuning_parm_value = (int32_t)pdev->zonecal_cfg.range_config_timeout_us; + break; + case VL53LX_TUNINGPARM_ZONE_CAL_ZONE_NUM_SAMPLES: + *ptuning_parm_value = (int32_t)pdev->zonecal_cfg.zone_num_of_samples; + break; + case VL53LX_TUNINGPARM_SPADMAP_VCSEL_PERIOD: + *ptuning_parm_value = (int32_t)pdev->ssc_cfg.VL53LX_p_005; + break; + case VL53LX_TUNINGPARM_SPADMAP_VCSEL_START: + *ptuning_parm_value = (int32_t)pdev->ssc_cfg.vcsel_start; + break; + case VL53LX_TUNINGPARM_SPADMAP_RATE_LIMIT_MCPS: + *ptuning_parm_value = (int32_t)pdev->ssc_cfg.rate_limit_mcps; + break; + case VL53LX_TUNINGPARM_LITE_DSS_CONFIG_TARGET_TOTAL_RATE_MCPS: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_dss_target_lite_mcps; + break; + case VL53LX_TUNINGPARM_RANGING_DSS_CONFIG_TARGET_TOTAL_RATE_MCPS: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_dss_target_histo_mcps; + break; + case VL53LX_TUNINGPARM_MZ_DSS_CONFIG_TARGET_TOTAL_RATE_MCPS: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_dss_target_histo_mz_mcps; + break; + case VL53LX_TUNINGPARM_TIMED_DSS_CONFIG_TARGET_TOTAL_RATE_MCPS: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_dss_target_timed_mcps; + break; + case VL53LX_TUNINGPARM_LITE_PHASECAL_CONFIG_TIMEOUT_US: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_phasecal_timeout_lite_us; + break; + case VL53LX_TUNINGPARM_RANGING_LONG_PHASECAL_CONFIG_TIMEOUT_US: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_phasecal_timeout_hist_long_us; + break; + case VL53LX_TUNINGPARM_RANGING_MED_PHASECAL_CONFIG_TIMEOUT_US: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_phasecal_timeout_hist_med_us; + break; + case VL53LX_TUNINGPARM_RANGING_SHORT_PHASECAL_CONFIG_TIMEOUT_US: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_phasecal_timeout_hist_short_us; + break; + case VL53LX_TUNINGPARM_MZ_LONG_PHASECAL_CONFIG_TIMEOUT_US: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_phasecal_timeout_mz_long_us; + break; + case VL53LX_TUNINGPARM_MZ_MED_PHASECAL_CONFIG_TIMEOUT_US: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_phasecal_timeout_mz_med_us; + break; + case VL53LX_TUNINGPARM_MZ_SHORT_PHASECAL_CONFIG_TIMEOUT_US: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_phasecal_timeout_mz_short_us; + break; + case VL53LX_TUNINGPARM_TIMED_PHASECAL_CONFIG_TIMEOUT_US: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_phasecal_timeout_timed_us; + break; + case VL53LX_TUNINGPARM_LITE_MM_CONFIG_TIMEOUT_US: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_mm_timeout_lite_us; + break; + case VL53LX_TUNINGPARM_RANGING_MM_CONFIG_TIMEOUT_US: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_mm_timeout_histo_us; + break; + case VL53LX_TUNINGPARM_MZ_MM_CONFIG_TIMEOUT_US: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_mm_timeout_mz_us; + break; + case VL53LX_TUNINGPARM_TIMED_MM_CONFIG_TIMEOUT_US: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_mm_timeout_timed_us; + break; + case VL53LX_TUNINGPARM_LITE_RANGE_CONFIG_TIMEOUT_US: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_range_timeout_lite_us; + break; + case VL53LX_TUNINGPARM_RANGING_RANGE_CONFIG_TIMEOUT_US: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_range_timeout_histo_us; + break; + case VL53LX_TUNINGPARM_MZ_RANGE_CONFIG_TIMEOUT_US: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_range_timeout_mz_us; + break; + case VL53LX_TUNINGPARM_TIMED_RANGE_CONFIG_TIMEOUT_US: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_range_timeout_timed_us; + break; + case VL53LX_TUNINGPARM_DYNXTALK_SMUDGE_MARGIN: + *ptuning_parm_value = (int32_t)pdev->smudge_correct_config.smudge_margin; + break; + case VL53LX_TUNINGPARM_DYNXTALK_NOISE_MARGIN: + *ptuning_parm_value = (int32_t)pdev->smudge_correct_config.noise_margin; + break; + case VL53LX_TUNINGPARM_DYNXTALK_XTALK_OFFSET_LIMIT: + *ptuning_parm_value = (int32_t)pdev->smudge_correct_config.user_xtalk_offset_limit; + break; + case VL53LX_TUNINGPARM_DYNXTALK_XTALK_OFFSET_LIMIT_HI: + *ptuning_parm_value = (int32_t)pdev->smudge_correct_config.user_xtalk_offset_limit_hi; + break; + case VL53LX_TUNINGPARM_DYNXTALK_SAMPLE_LIMIT: + *ptuning_parm_value = (int32_t)pdev->smudge_correct_config.sample_limit; + break; + case VL53LX_TUNINGPARM_DYNXTALK_SINGLE_XTALK_DELTA: + *ptuning_parm_value = (int32_t)pdev->smudge_correct_config.single_xtalk_delta; + break; + case VL53LX_TUNINGPARM_DYNXTALK_AVERAGED_XTALK_DELTA: + *ptuning_parm_value = (int32_t)pdev->smudge_correct_config.averaged_xtalk_delta; + break; + case VL53LX_TUNINGPARM_DYNXTALK_CLIP_LIMIT: + *ptuning_parm_value = (int32_t)pdev->smudge_correct_config.smudge_corr_clip_limit; + break; + case VL53LX_TUNINGPARM_DYNXTALK_SCALER_CALC_METHOD: + *ptuning_parm_value = (int32_t)pdev->smudge_correct_config.scaler_calc_method; + break; + case VL53LX_TUNINGPARM_DYNXTALK_XGRADIENT_SCALER: + *ptuning_parm_value = (int32_t)pdev->smudge_correct_config.x_gradient_scaler; + break; + case VL53LX_TUNINGPARM_DYNXTALK_YGRADIENT_SCALER: + *ptuning_parm_value = (int32_t)pdev->smudge_correct_config.y_gradient_scaler; + break; + case VL53LX_TUNINGPARM_DYNXTALK_USER_SCALER_SET: + *ptuning_parm_value = (int32_t)pdev->smudge_correct_config.user_scaler_set; + break; + case VL53LX_TUNINGPARM_DYNXTALK_SMUDGE_COR_SINGLE_APPLY: + *ptuning_parm_value = (int32_t)pdev->smudge_correct_config.smudge_corr_single_apply; + break; + case VL53LX_TUNINGPARM_DYNXTALK_XTALK_AMB_THRESHOLD: + *ptuning_parm_value = (int32_t)(pdev->smudge_correct_config.smudge_corr_ambient_threshold); + break; + case VL53LX_TUNINGPARM_DYNXTALK_NODETECT_AMB_THRESHOLD_KCPS: + *ptuning_parm_value = (int32_t)pdev->smudge_correct_config.nodetect_ambient_threshold; + break; + case VL53LX_TUNINGPARM_DYNXTALK_NODETECT_SAMPLE_LIMIT: + *ptuning_parm_value = (int32_t)pdev->smudge_correct_config.nodetect_sample_limit; + break; + case VL53LX_TUNINGPARM_DYNXTALK_NODETECT_XTALK_OFFSET_KCPS: + *ptuning_parm_value = (int32_t)pdev->smudge_correct_config.nodetect_xtalk_offset; + break; + case VL53LX_TUNINGPARM_DYNXTALK_NODETECT_MIN_RANGE_MM: + *ptuning_parm_value = (int32_t)pdev->smudge_correct_config.nodetect_min_range_mm; + break; + case VL53LX_TUNINGPARM_LOWPOWERAUTO_VHV_LOOP_BOUND: + *ptuning_parm_value = (int32_t)pdev->low_power_auto_data.vhv_loop_bound; + break; + case VL53LX_TUNINGPARM_LOWPOWERAUTO_MM_CONFIG_TIMEOUT_US: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_mm_timeout_lpa_us; + break; + case VL53LX_TUNINGPARM_LOWPOWERAUTO_RANGE_CONFIG_TIMEOUT_US: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_range_timeout_lpa_us; + break; + case VL53LX_TUNINGPARM_VERY_SHORT_DSS_RATE_MCPS: + *ptuning_parm_value = (int32_t)pdev->tuning_parms.tp_dss_target_very_short_mcps; + break; + case VL53LX_TUNINGPARM_PHASECAL_PATCH_POWER: + *ptuning_parm_value = (int32_t) pdev->tuning_parms.tp_phasecal_patch_power; + break; + case VL53LX_TUNINGPARM_HIST_MERGE: + *ptuning_parm_value = (int32_t) pdev->tuning_parms.tp_hist_merge; + break; + case VL53LX_TUNINGPARM_RESET_MERGE_THRESHOLD: + *ptuning_parm_value = (int32_t) pdev->tuning_parms.tp_reset_merge_threshold; + break; + case VL53LX_TUNINGPARM_HIST_MERGE_MAX_SIZE: + *ptuning_parm_value = (int32_t) pdev->tuning_parms.tp_hist_merge_max_size; + break; + case VL53LX_TUNINGPARM_DYNXTALK_MAX_SMUDGE_FACTOR: + *ptuning_parm_value = pdev->smudge_correct_config.max_smudge_factor; + break; + case VL53LX_TUNINGPARM_UWR_ENABLE: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_enable; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_1_MIN: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_med_z_1_min; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_1_MAX: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_med_z_1_max; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_2_MIN: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_med_z_2_min; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_2_MAX: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_med_z_2_max; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_3_MIN: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_med_z_3_min; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_3_MAX: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_med_z_3_max; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_4_MIN: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_med_z_4_min; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_4_MAX: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_med_z_4_max; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_5_MIN: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_med_z_5_min; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_5_MAX: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_med_z_5_max; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_1_RANGEA: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_med_corr_z_1_rangea; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_1_RANGEB: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_med_corr_z_1_rangeb; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_2_RANGEA: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_med_corr_z_2_rangea; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_2_RANGEB: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_med_corr_z_2_rangeb; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_3_RANGEA: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_med_corr_z_3_rangea; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_3_RANGEB: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_med_corr_z_3_rangeb; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_4_RANGEA: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_med_corr_z_4_rangea; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_4_RANGEB: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_med_corr_z_4_rangeb; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_5_RANGEA: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_med_corr_z_5_rangea; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_5_RANGEB: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_med_corr_z_5_rangeb; + break; + case VL53LX_TUNINGPARM_UWR_LONG_ZONE_1_MIN: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_lng_z_1_min; + break; + case VL53LX_TUNINGPARM_UWR_LONG_ZONE_1_MAX: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_lng_z_1_max; + break; + case VL53LX_TUNINGPARM_UWR_LONG_ZONE_2_MIN: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_lng_z_2_min; + break; + case VL53LX_TUNINGPARM_UWR_LONG_ZONE_2_MAX: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_lng_z_2_max; + break; + case VL53LX_TUNINGPARM_UWR_LONG_ZONE_3_MIN: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_lng_z_3_min; + break; + case VL53LX_TUNINGPARM_UWR_LONG_ZONE_3_MAX: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_lng_z_3_max; + break; + case VL53LX_TUNINGPARM_UWR_LONG_ZONE_4_MIN: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_lng_z_4_min; + break; + case VL53LX_TUNINGPARM_UWR_LONG_ZONE_4_MAX: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_lng_z_4_max; + break; + case VL53LX_TUNINGPARM_UWR_LONG_ZONE_5_MIN: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_lng_z_5_min; + break; + case VL53LX_TUNINGPARM_UWR_LONG_ZONE_5_MAX: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_lng_z_5_max; + break; + case VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_1_RANGEA: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_lng_corr_z_1_rangea; + break; + case VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_1_RANGEB: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_lng_corr_z_1_rangeb; + break; + case VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_2_RANGEA: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_lng_corr_z_2_rangea; + break; + case VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_2_RANGEB: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_lng_corr_z_2_rangeb; + break; + case VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_3_RANGEA: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_lng_corr_z_3_rangea; + break; + case VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_3_RANGEB: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_lng_corr_z_3_rangeb; + break; + case VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_4_RANGEA: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_lng_corr_z_4_rangea; + break; + case VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_4_RANGEB: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_lng_corr_z_4_rangeb; + break; + case VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_5_RANGEA: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_lng_corr_z_5_rangea; + break; + case VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_5_RANGEB: + *ptuning_parm_value = pdev->tuning_parms.tp_uwr_lng_corr_z_5_rangeb; + break; + default: + *ptuning_parm_value = 0x7FFFFFFF; + status = VL53LX_ERROR_INVALID_PARAMS; + break; + + } + return status; +} + +VL53LX_Error VL53LX_load_patch(VL53LX_DEV Dev) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + int32_t patch_tuning = 0; + uint8_t comms_buffer[256]; + uint32_t patch_power; + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_WrByte(Dev, VL53LX_FIRMWARE__ENABLE, 0x00); + + if (status == VL53LX_ERROR_NONE) + VL53LX_enable_powerforce(Dev); + + VL53LX_get_tuning_parm(Dev, VL53LX_TUNINGPARM_PHASECAL_PATCH_POWER, &patch_tuning); + + switch (patch_tuning) { + case 0: + patch_power = 0x00; + break; + case 1: + patch_power = 0x10; + break; + case 2: + patch_power = 0x20; + break; + case 3: + patch_power = 0x40; + break; + default: + patch_power = 0x00; + } + + if (status == VL53LX_ERROR_NONE) { + comms_buffer[0] = 0x29; + comms_buffer[1] = 0xC9; + comms_buffer[2] = 0x0E; + comms_buffer[3] = 0x40; + comms_buffer[4] = 0x28; + comms_buffer[5] = patch_power; + status = VL53LX_WriteMulti(Dev, VL53LX_PATCH__OFFSET_0, comms_buffer, 6); + } + + if (status == VL53LX_ERROR_NONE) { + comms_buffer[0] = 0x03; + comms_buffer[1] = 0x6D; + comms_buffer[2] = 0x03; + comms_buffer[3] = 0x6F; + comms_buffer[4] = 0x07; + comms_buffer[5] = 0x29; + status = VL53LX_WriteMulti(Dev, VL53LX_PATCH__ADDRESS_0, comms_buffer, 6); + } + + if (status == VL53LX_ERROR_NONE) { + comms_buffer[0] = 0x00; + comms_buffer[1] = 0x07; + status = VL53LX_WriteMulti(Dev, VL53LX_PATCH__JMP_ENABLES, comms_buffer, 2); + } + + if (status == VL53LX_ERROR_NONE) { + comms_buffer[0] = 0x00; + comms_buffer[1] = 0x07; + status = VL53LX_WriteMulti(Dev, VL53LX_PATCH__DATA_ENABLES, comms_buffer, 2); + } + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_WrByte(Dev, VL53LX_PATCH__CTRL, 0x01); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_WrByte(Dev, VL53LX_FIRMWARE__ENABLE, 0x01); + + return status; +} + +void VL53LX_encode_row_col(uint8_t row, uint8_t col, uint8_t *pspad_number) +{ + if (row > 7) + *pspad_number = 128 + (col << 3) + (15-row); + else + *pspad_number = ((15-col) << 3) + row; +} + +void VL53LX_encode_zone_size(uint8_t width, uint8_t height, uint8_t *pencoded_xy_size) +{ + *pencoded_xy_size = (height << 4) + width; +} + +VL53LX_Error VL53LX_set_user_zone(VL53LX_DEV Dev, VL53LX_user_zone_t *puser_zone) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + VL53LX_encode_row_col(puser_zone->y_centre, puser_zone->x_centre, &(pdev->dyn_cfg.roi_config__user_roi_centre_spad)); + + VL53LX_encode_zone_size(puser_zone->width, puser_zone->height, &(pdev->dyn_cfg.roi_config__user_roi_requested_global_xy_size)); + + return status; +} + +VL53LX_Error VL53LX_set_zone_dss_config(VL53LX_DEV Dev, VL53LX_zone_private_dyn_cfg_t *pzone_dyn_cfg) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + VL53LX_ll_driver_state_t *pstate = &(pdev->ll_state); + + if (pstate->cfg_device_state == VL53LX_DEVICESTATE_RANGING_DSS_MANUAL) { + pdev->gen_cfg.dss_config__roi_mode_control = VL53LX_DSS_CONTROL__MODE_EFFSPADS; + pdev->gen_cfg.dss_config__manual_effective_spads_select = pzone_dyn_cfg->dss_requested_effective_spad_count; + } else { + pdev->gen_cfg.dss_config__roi_mode_control = VL53LX_DSS_CONTROL__MODE_TARGET_RATE; + } + + return status; +} + +VL53LX_Error VL53LX_save_cfg_data(VL53LX_DEV Dev) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + VL53LX_LLDriverResults_t *pres = VL53LXDevStructGetLLResultsHandle(Dev); + + VL53LX_zone_private_dyn_cfg_t *pzone_dyn_cfg; + VL53LX_dynamic_config_t *pdynamic = &(pdev->dyn_cfg); + + pzone_dyn_cfg = &(pres->zone_dyn_cfgs.VL53LX_p_003[pdev->ll_state.cfg_zone_id]); + pzone_dyn_cfg->expected_stream_count = pdev->ll_state.cfg_stream_count; + pzone_dyn_cfg->expected_gph_id = pdev->ll_state.cfg_gph_id; + pzone_dyn_cfg->roi_config__user_roi_centre_spad = pdynamic->roi_config__user_roi_centre_spad; + pzone_dyn_cfg->roi_config__user_roi_requested_global_xy_size = pdynamic->roi_config__user_roi_requested_global_xy_size; + + return status; +} + +VL53LX_Error VL53LX_i2c_encode_static_nvm_managed(VL53LX_static_nvm_managed_t *pdata, uint16_t buf_size, uint8_t *pbuffer) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + if (buf_size < VL53LX_STATIC_NVM_MANAGED_I2C_SIZE_BYTES) + return VL53LX_ERROR_COMMS_BUFFER_TOO_SMALL; + + *(pbuffer + 0) = pdata->i2c_slave__device_address & 0x7F; + *(pbuffer + 1) = pdata->ana_config__vhv_ref_sel_vddpix & 0xF; + *(pbuffer + 2) = pdata->ana_config__vhv_ref_sel_vquench & 0x7F; + *(pbuffer + 3) = pdata->ana_config__reg_avdd1v2_sel & 0x3; + *(pbuffer + 4) = pdata->ana_config__fast_osc__trim & 0x7F; + VL53LX_i2c_encode_uint16_t(pdata->osc_measured__fast_osc__frequency, 2, pbuffer + 5); + *(pbuffer + 7) = pdata->vhv_config__timeout_macrop_loop_bound; + *(pbuffer + 8) = pdata->vhv_config__count_thresh; + *(pbuffer + 9) = pdata->vhv_config__offset & 0x3F; + *(pbuffer + 10) = pdata->vhv_config__init; + + return status; +} + +VL53LX_Error VL53LX_i2c_decode_static_nvm_managed(uint16_t buf_size, uint8_t *pbuffer, VL53LX_static_nvm_managed_t *pdata) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + if (buf_size < VL53LX_STATIC_NVM_MANAGED_I2C_SIZE_BYTES) + return VL53LX_ERROR_COMMS_BUFFER_TOO_SMALL; + + pdata->i2c_slave__device_address = + (*(pbuffer + 0)) & 0x7F; + pdata->ana_config__vhv_ref_sel_vddpix = + (*(pbuffer + 1)) & 0xF; + pdata->ana_config__vhv_ref_sel_vquench = + (*(pbuffer + 2)) & 0x7F; + pdata->ana_config__reg_avdd1v2_sel = + (*(pbuffer + 3)) & 0x3; + pdata->ana_config__fast_osc__trim = + (*(pbuffer + 4)) & 0x7F; + pdata->osc_measured__fast_osc__frequency = + (VL53LX_i2c_decode_uint16_t(2, pbuffer + 5)); + pdata->vhv_config__timeout_macrop_loop_bound = + (*(pbuffer + 7)); + pdata->vhv_config__count_thresh = + (*(pbuffer + 8)); + pdata->vhv_config__offset = + (*(pbuffer + 9)) & 0x3F; + pdata->vhv_config__init = + (*(pbuffer + 10)); + + return status; +} + +VL53LX_Error VL53LX_i2c_encode_static_config(VL53LX_static_config_t *pdata, uint16_t buf_size, uint8_t *pbuffer) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + if (buf_size < VL53LX_STATIC_CONFIG_I2C_SIZE_BYTES) + return VL53LX_ERROR_COMMS_BUFFER_TOO_SMALL; + + VL53LX_i2c_encode_uint16_t(pdata->dss_config__target_total_rate_mcps, 2, pbuffer + 0); + *(pbuffer + 2) = pdata->debug__ctrl & 0x1; + *(pbuffer + 3) = pdata->test_mode__ctrl & 0xF; + *(pbuffer + 4) = pdata->clk_gating__ctrl & 0xF; + *(pbuffer + 5) = pdata->nvm_bist__ctrl & 0x1F; + *(pbuffer + 6) = pdata->nvm_bist__num_nvm_words & 0x7F; + *(pbuffer + 7) = pdata->nvm_bist__start_address & 0x7F; + *(pbuffer + 8) = pdata->host_if__status & 0x1; + *(pbuffer + 9) = pdata->pad_i2c_hv__config; + *(pbuffer + 10) = pdata->pad_i2c_hv__extsup_config & 0x1; + *(pbuffer + 11) = pdata->gpio_hv_pad__ctrl & 0x3; + *(pbuffer + 12) = pdata->gpio_hv_mux__ctrl & 0x1F; + *(pbuffer + 13) = pdata->gpio__tio_hv_status & 0x3; + *(pbuffer + 14) = pdata->gpio__fio_hv_status & 0x3; + *(pbuffer + 15) = pdata->ana_config__spad_sel_pswidth & 0x7; + *(pbuffer + 16) = pdata->ana_config__vcsel_pulse_width_offset & 0x1F; + *(pbuffer + 17) = pdata->ana_config__fast_osc__config_ctrl & 0x1; + *(pbuffer + 18) = pdata->sigma_estimator__effective_pulse_width_ns; + *(pbuffer + 19) = pdata->sigma_estimator__effective_ambient_width_ns; + *(pbuffer + 20) = pdata->sigma_estimator__sigma_ref_mm; + *(pbuffer + 21) = pdata->algo__crosstalk_compensation_valid_height_mm; + *(pbuffer + 22) = pdata->spare_host_config__static_config_spare_0; + *(pbuffer + 23) = pdata->spare_host_config__static_config_spare_1; + VL53LX_i2c_encode_uint16_t(pdata->algo__range_ignore_threshold_mcps, 2, pbuffer + 24); + *(pbuffer + 26) = pdata->algo__range_ignore_valid_height_mm; + *(pbuffer + 27) = pdata->algo__range_min_clip; + *(pbuffer + 28) = pdata->algo__consistency_check__tolerance & 0xF; + *(pbuffer + 29) = pdata->spare_host_config__static_config_spare_2; + *(pbuffer + 30) = pdata->sd_config__reset_stages_msb & 0xF; + *(pbuffer + 31) = pdata->sd_config__reset_stages_lsb; + + return status; +} + +VL53LX_Error VL53LX_i2c_encode_general_config(VL53LX_general_config_t *pdata, uint16_t buf_size, uint8_t *pbuffer) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + if (buf_size < VL53LX_GENERAL_CONFIG_I2C_SIZE_BYTES) + return VL53LX_ERROR_COMMS_BUFFER_TOO_SMALL; + + *(pbuffer + 0) = pdata->gph_config__stream_count_update_value; + *(pbuffer + 1) = pdata->global_config__stream_divider; + *(pbuffer + 2) = pdata->system__interrupt_config_gpio; + *(pbuffer + 3) = pdata->cal_config__vcsel_start & 0x7F; + VL53LX_i2c_encode_uint16_t(pdata->cal_config__repeat_rate & 0xFFF, 2, pbuffer + 4); + *(pbuffer + 6) = pdata->global_config__vcsel_width & 0x7F; + *(pbuffer + 7) = pdata->phasecal_config__timeout_macrop; + *(pbuffer + 8) = pdata->phasecal_config__target; + *(pbuffer + 9) = pdata->phasecal_config__override & 0x1; + *(pbuffer + 11) = pdata->dss_config__roi_mode_control & 0x7; + VL53LX_i2c_encode_uint16_t(pdata->system__thresh_rate_high, 2, pbuffer + 12); + VL53LX_i2c_encode_uint16_t(pdata->system__thresh_rate_low, 2, pbuffer + 14); + VL53LX_i2c_encode_uint16_t(pdata->dss_config__manual_effective_spads_select, 2, pbuffer + 16); + *(pbuffer + 18) = pdata->dss_config__manual_block_select; + *(pbuffer + 19) = pdata->dss_config__aperture_attenuation; + *(pbuffer + 20) = pdata->dss_config__max_spads_limit; + *(pbuffer + 21) = pdata->dss_config__min_spads_limit; + + return status; +} + +void VL53LX_i2c_encode_uint32_t(uint32_t ip_value, uint16_t count, uint8_t *pbuffer) +{ + uint16_t i = 0; + uint32_t VL53LX_p_003 = 0; + + VL53LX_p_003 = ip_value; + + for (i = 0; i < count; i++) { + pbuffer[count-i-1] = (uint8_t)(VL53LX_p_003 & 0x00FF); + VL53LX_p_003 = VL53LX_p_003 >> 8; + } +} + +uint32_t VL53LX_i2c_decode_uint32_t(uint16_t count, uint8_t *pbuffer) +{ + uint32_t value = 0x00; + + while (count-- > 0) + value = (value << 8) | (uint32_t)*pbuffer++; + + return value; +} + +VL53LX_Error VL53LX_i2c_encode_timing_config(VL53LX_timing_config_t *pdata, uint16_t buf_size, uint8_t *pbuffer) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + if (buf_size < VL53LX_TIMING_CONFIG_I2C_SIZE_BYTES) + return VL53LX_ERROR_COMMS_BUFFER_TOO_SMALL; + + *(pbuffer + 0) = pdata->mm_config__timeout_macrop_a_hi & 0xF; + *(pbuffer + 1) = pdata->mm_config__timeout_macrop_a_lo; + *(pbuffer + 2) = pdata->mm_config__timeout_macrop_b_hi & 0xF; + *(pbuffer + 3) = pdata->mm_config__timeout_macrop_b_lo; + *(pbuffer + 4) = pdata->range_config__timeout_macrop_a_hi & 0xF; + *(pbuffer + 5) = pdata->range_config__timeout_macrop_a_lo; + *(pbuffer + 6) = pdata->range_config__vcsel_period_a & 0x3F; + *(pbuffer + 7) = pdata->range_config__timeout_macrop_b_hi & 0xF; + *(pbuffer + 8) = pdata->range_config__timeout_macrop_b_lo; + *(pbuffer + 9) = pdata->range_config__vcsel_period_b & 0x3F; + VL53LX_i2c_encode_uint16_t(pdata->range_config__sigma_thresh, 2, pbuffer + 10); + VL53LX_i2c_encode_uint16_t(pdata->range_config__min_count_rate_rtn_limit_mcps, 2, pbuffer + 12); + *(pbuffer + 14) = pdata->range_config__valid_phase_low; + *(pbuffer + 15) = pdata->range_config__valid_phase_high; + VL53LX_i2c_encode_uint32_t(pdata->system__intermeasurement_period, 4, pbuffer + 18); + *(pbuffer + 22) = pdata->system__fractional_enable & 0x1; + + return status; +} + +VL53LX_Error VL53LX_i2c_encode_dynamic_config(VL53LX_dynamic_config_t *pdata, uint16_t buf_size, uint8_t *pbuffer) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + if (buf_size < VL53LX_DYNAMIC_CONFIG_I2C_SIZE_BYTES) + return VL53LX_ERROR_COMMS_BUFFER_TOO_SMALL; + + *(pbuffer + 0) = pdata->system__grouped_parameter_hold_0 & 0x3; + VL53LX_i2c_encode_uint16_t(pdata->system__thresh_high, 2, pbuffer + 1); + VL53LX_i2c_encode_uint16_t(pdata->system__thresh_low, 2, pbuffer + 3); + *(pbuffer + 5) = pdata->system__enable_xtalk_per_quadrant & 0x1; + *(pbuffer + 6) = pdata->system__seed_config & 0x7; + *(pbuffer + 7) = pdata->sd_config__woi_sd0; + *(pbuffer + 8) = pdata->sd_config__woi_sd1; + *(pbuffer + 9) = pdata->sd_config__initial_phase_sd0 & 0x7F; + *(pbuffer + 10) = pdata->sd_config__initial_phase_sd1 & 0x7F; + *(pbuffer + 11) = pdata->system__grouped_parameter_hold_1 & 0x3; + *(pbuffer + 12) = pdata->sd_config__first_order_select & 0x3; + *(pbuffer + 13) = pdata->sd_config__quantifier & 0xF; + *(pbuffer + 14) = pdata->roi_config__user_roi_centre_spad; + *(pbuffer + 15) = pdata->roi_config__user_roi_requested_global_xy_size; + *(pbuffer + 16) = pdata->system__sequence_config; + *(pbuffer + 17) = pdata->system__grouped_parameter_hold & 0x3; + + return status; +} + +VL53LX_Error VL53LX_update_internal_stream_counters(VL53LX_DEV Dev, uint8_t external_stream_count, uint8_t *pinternal_stream_count, uint8_t *pinternal_stream_count_val) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + uint8_t stream_divider; + + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + stream_divider = pdev->gen_cfg.global_config__stream_divider; + + if (stream_divider == 0) { + *pinternal_stream_count = external_stream_count; + } else if (*pinternal_stream_count_val == (stream_divider-1)) { + if (*pinternal_stream_count == 0xFF) + *pinternal_stream_count = 0x80; + else + *pinternal_stream_count = *pinternal_stream_count + 1; + *pinternal_stream_count_val = 0; + + } else { + *pinternal_stream_count_val = *pinternal_stream_count_val + 1; + } + return status; +} + +VL53LX_Error VL53LX_update_ll_driver_rd_state(VL53LX_DEV Dev) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + VL53LX_ll_driver_state_t *pstate = &(pdev->ll_state); + + if ((pdev->sys_ctrl.system__mode_start & VL53LX_DEVICEMEASUREMENTMODE_MODE_MASK) == 0x00) { + pstate->rd_device_state = VL53LX_DEVICESTATE_SW_STANDBY; + pstate->rd_stream_count = 0; + pstate->rd_internal_stream_count = 0; + pstate->rd_internal_stream_count_val = 0; + pstate->rd_gph_id = VL53LX_GROUPEDPARAMETERHOLD_ID_MASK; + pstate->rd_timing_status = 0; + pstate->rd_zone_id = 0; + + } else { + if (pstate->rd_stream_count == 0xFF) + pstate->rd_stream_count = 0x80; + else + pstate->rd_stream_count++; + + status = VL53LX_update_internal_stream_counters(Dev, pstate->rd_stream_count, &(pstate->rd_internal_stream_count), &(pstate->rd_internal_stream_count_val)); + pstate->rd_gph_id ^= VL53LX_GROUPEDPARAMETERHOLD_ID_MASK; + switch (pstate->rd_device_state) { + case VL53LX_DEVICESTATE_SW_STANDBY: + if ((pdev->dyn_cfg.system__grouped_parameter_hold & VL53LX_GROUPEDPARAMETERHOLD_ID_MASK) > 0) { + pstate->rd_device_state = + VL53LX_DEVICESTATE_RANGING_WAIT_GPH_SYNC; + } else { + if (pstate->rd_zone_id >= pdev->zone_cfg.active_zones) + pstate->rd_device_state = VL53LX_DEVICESTATE_RANGING_OUTPUT_DATA; + else + pstate->rd_device_state = VL53LX_DEVICESTATE_RANGING_GATHER_DATA; + } + pstate->rd_stream_count = 0; + pstate->rd_internal_stream_count = 0; + pstate->rd_internal_stream_count_val = 0; + pstate->rd_timing_status = 0; + pstate->rd_zone_id = 0; + break; + case VL53LX_DEVICESTATE_RANGING_WAIT_GPH_SYNC: + pstate->rd_stream_count = 0; + pstate->rd_internal_stream_count = 0; + pstate->rd_internal_stream_count_val = 0; + pstate->rd_zone_id = 0; + if (pstate->rd_zone_id >= pdev->zone_cfg.active_zones) + pstate->rd_device_state = VL53LX_DEVICESTATE_RANGING_OUTPUT_DATA; + else + pstate->rd_device_state = VL53LX_DEVICESTATE_RANGING_GATHER_DATA; + break; + case VL53LX_DEVICESTATE_RANGING_GATHER_DATA: + pstate->rd_zone_id++; + if (pstate->rd_zone_id >= pdev->zone_cfg.active_zones) + pstate->rd_device_state = VL53LX_DEVICESTATE_RANGING_OUTPUT_DATA; + else + pstate->rd_device_state = VL53LX_DEVICESTATE_RANGING_GATHER_DATA; + break; + case VL53LX_DEVICESTATE_RANGING_OUTPUT_DATA: + pstate->rd_zone_id = 0; + pstate->rd_timing_status ^= 0x01; + if (pstate->rd_zone_id >= pdev->zone_cfg.active_zones) + pstate->rd_device_state = VL53LX_DEVICESTATE_RANGING_OUTPUT_DATA; + else + pstate->rd_device_state = VL53LX_DEVICESTATE_RANGING_GATHER_DATA; + break; + default: + pstate->rd_device_state = VL53LX_DEVICESTATE_SW_STANDBY; + pstate->rd_stream_count = 0; + pstate->rd_internal_stream_count = 0; + pstate->rd_internal_stream_count_val = 0; + pstate->rd_gph_id = VL53LX_GROUPEDPARAMETERHOLD_ID_MASK; + pstate->rd_timing_status = 0; + pstate->rd_zone_id = 0; + break; + } + } + return status; +} + +VL53LX_Error VL53LX_update_ll_driver_cfg_state(VL53LX_DEV Dev) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + VL53LX_LLDriverResults_t *pres = VL53LXDevStructGetLLResultsHandle(Dev); + + VL53LX_ll_driver_state_t *pstate = &(pdev->ll_state); + VL53LX_zone_private_dyn_cfgs_t *pZ = &(pres->zone_dyn_cfgs); + + uint8_t prev_cfg_zone_id; + uint8_t prev_cfg_gph_id; + uint8_t prev_cfg_stream_count; + + if ((pdev->sys_ctrl.system__mode_start & VL53LX_DEVICEMEASUREMENTMODE_MODE_MASK) == 0x00) { + pstate->cfg_device_state = VL53LX_DEVICESTATE_SW_STANDBY; + pstate->cfg_stream_count = 0; + pstate->cfg_internal_stream_count = 0; + pstate->cfg_internal_stream_count_val = 0; + pstate->cfg_gph_id = VL53LX_GROUPEDPARAMETERHOLD_ID_MASK; + pstate->cfg_timing_status = 0; + pstate->cfg_zone_id = 0; + prev_cfg_zone_id = 0; + prev_cfg_gph_id = 0; + prev_cfg_stream_count = 0; + + } else { + prev_cfg_gph_id = pstate->cfg_gph_id; + prev_cfg_zone_id = pstate->cfg_zone_id; + prev_cfg_stream_count = pstate->cfg_stream_count; + + if (pstate->cfg_stream_count == 0xFF) + pstate->cfg_stream_count = 0x80; + else + pstate->cfg_stream_count++; + + status = VL53LX_update_internal_stream_counters(Dev, pstate->cfg_stream_count, &(pstate->cfg_internal_stream_count), &(pstate->cfg_internal_stream_count_val)); + + pstate->cfg_gph_id ^= VL53LX_GROUPEDPARAMETERHOLD_ID_MASK; + + switch (pstate->cfg_device_state) { + case VL53LX_DEVICESTATE_SW_STANDBY: + pstate->cfg_zone_id = 1; + if (pstate->cfg_zone_id > pdev->zone_cfg.active_zones) { + pstate->cfg_zone_id = 0; + pstate->cfg_timing_status ^= 0x01; + } + pstate->cfg_stream_count = 1; + + if (pdev->gen_cfg.global_config__stream_divider == 0) { + pstate->cfg_internal_stream_count = 1; + pstate->cfg_internal_stream_count_val = 0; + } else { + pstate->cfg_internal_stream_count = 0; + pstate->cfg_internal_stream_count_val = 1; + } + pstate->cfg_device_state = VL53LX_DEVICESTATE_RANGING_DSS_AUTO; + break; + case VL53LX_DEVICESTATE_RANGING_DSS_AUTO: + pstate->cfg_zone_id++; + if (pstate->cfg_zone_id > pdev->zone_cfg.active_zones) { + pstate->cfg_zone_id = 0; + pstate->cfg_timing_status ^= 0x01; + + if (pdev->zone_cfg.active_zones > 0) { + pstate->cfg_device_state = + VL53LX_DEVICESTATE_RANGING_DSS_MANUAL; + } + } + break; + case VL53LX_DEVICESTATE_RANGING_DSS_MANUAL: + pstate->cfg_zone_id++; + if (pstate->cfg_zone_id > pdev->zone_cfg.active_zones) { + pstate->cfg_zone_id = 0; + pstate->cfg_timing_status ^= 0x01; + } + break; + default: + pstate->cfg_device_state = VL53LX_DEVICESTATE_SW_STANDBY; + pstate->cfg_stream_count = 0; + pstate->cfg_internal_stream_count = 0; + pstate->cfg_internal_stream_count_val = 0; + pstate->cfg_gph_id = VL53LX_GROUPEDPARAMETERHOLD_ID_MASK; + pstate->cfg_timing_status = 0; + pstate->cfg_zone_id = 0; + break; + } + } + if (pdev->zone_cfg.active_zones == 0) { + pZ->VL53LX_p_003[prev_cfg_zone_id].expected_stream_count = prev_cfg_stream_count - 1; + pZ->VL53LX_p_003[pstate->rd_zone_id].expected_gph_id = prev_cfg_gph_id ^ VL53LX_GROUPEDPARAMETERHOLD_ID_MASK; + } else { + pZ->VL53LX_p_003[prev_cfg_zone_id].expected_stream_count = prev_cfg_stream_count; + pZ->VL53LX_p_003[prev_cfg_zone_id].expected_gph_id = prev_cfg_gph_id; + } + return status; +} + +VL53LX_Error VL53LX_init_and_start_range(VL53LX_DEV Dev, uint8_t measurement_mode, VL53LX_DeviceConfigLevel device_config_level) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + VL53LX_LLDriverResults_t *pres = VL53LXDevStructGetLLResultsHandle(Dev); + + uint8_t buffer[VL53LX_MAX_I2C_XFER_SIZE]; + + VL53LX_static_nvm_managed_t *pstatic_nvm = &(pdev->stat_nvm); + VL53LX_customer_nvm_managed_t *pcustomer_nvm = &(pdev->customer); + VL53LX_static_config_t *pstatic = &(pdev->stat_cfg); + VL53LX_general_config_t *pgeneral = &(pdev->gen_cfg); + VL53LX_timing_config_t *ptiming = &(pdev->tim_cfg); + VL53LX_dynamic_config_t *pdynamic = &(pdev->dyn_cfg); + VL53LX_system_control_t *psystem = &(pdev->sys_ctrl); + + VL53LX_ll_driver_state_t *pstate = &(pdev->ll_state); + VL53LX_customer_nvm_managed_t *pN = &(pdev->customer); + + uint8_t *pbuffer = &buffer[0]; + uint16_t i = 0; + uint16_t i2c_index = 0; + uint16_t i2c_buffer_offset_bytes = 0; + uint16_t i2c_buffer_size_bytes = 0; + + pdev->measurement_mode = measurement_mode; + + psystem->system__mode_start = (psystem->system__mode_start & VL53LX_DEVICEMEASUREMENTMODE_STOP_MASK) | measurement_mode; + + status = VL53LX_set_user_zone(Dev, &(pdev->zone_cfg.user_zones[pdev->ll_state.cfg_zone_id])); + if (pdev->zone_cfg.active_zones > 0) { + status = VL53LX_set_zone_dss_config(Dev, &(pres->zone_dyn_cfgs.VL53LX_p_003[pdev->ll_state.cfg_zone_id])); + } + + if (((pdev->sys_ctrl.system__mode_start & VL53LX_DEVICESCHEDULERMODE_HISTOGRAM) == 0x00) && (pdev->xtalk_cfg.global_crosstalk_compensation_enable == 0x01)) { + pdev->stat_cfg.algo__range_ignore_threshold_mcps = pdev->xtalk_cfg.crosstalk_range_ignore_threshold_rate_mcps; + } + + if (pdev->low_power_auto_data.low_power_auto_range_count == 0xFF) + pdev->low_power_auto_data.low_power_auto_range_count = 0x0; + + if ((pdev->low_power_auto_data.is_low_power_auto_mode == 1) && (pdev->low_power_auto_data.low_power_auto_range_count == 0)) { + pdev->low_power_auto_data.saved_interrupt_config = pdev->gen_cfg.system__interrupt_config_gpio; + pdev->gen_cfg.system__interrupt_config_gpio = 1 << 5; + if ((pdev->dyn_cfg.system__sequence_config & (VL53LX_SEQUENCE_MM1_EN | VL53LX_SEQUENCE_MM2_EN)) == 0x0) { + pN->algo__part_to_part_range_offset_mm = (pN->mm_config__outer_offset_mm << 2); + } else { + pN->algo__part_to_part_range_offset_mm = 0x0; + } + if (device_config_level < VL53LX_DEVICECONFIGLEVEL_CUSTOMER_ONWARDS) { + device_config_level = VL53LX_DEVICECONFIGLEVEL_CUSTOMER_ONWARDS; + } + } + + if ((pdev->low_power_auto_data.is_low_power_auto_mode == 1) && (pdev->low_power_auto_data.low_power_auto_range_count == 1)) { + pdev->gen_cfg.system__interrupt_config_gpio = pdev->low_power_auto_data.saved_interrupt_config; + device_config_level = VL53LX_DEVICECONFIGLEVEL_FULL; + } + if (status == VL53LX_ERROR_NONE) + status = VL53LX_save_cfg_data(Dev); + + switch (device_config_level) { + case VL53LX_DEVICECONFIGLEVEL_FULL: + i2c_index = VL53LX_STATIC_NVM_MANAGED_I2C_INDEX; + break; + case VL53LX_DEVICECONFIGLEVEL_CUSTOMER_ONWARDS: + i2c_index = VL53LX_CUSTOMER_NVM_MANAGED_I2C_INDEX; + break; + case VL53LX_DEVICECONFIGLEVEL_STATIC_ONWARDS: + i2c_index = VL53LX_STATIC_CONFIG_I2C_INDEX; + break; + case VL53LX_DEVICECONFIGLEVEL_GENERAL_ONWARDS: + i2c_index = VL53LX_GENERAL_CONFIG_I2C_INDEX; + break; + case VL53LX_DEVICECONFIGLEVEL_TIMING_ONWARDS: + i2c_index = VL53LX_TIMING_CONFIG_I2C_INDEX; + break; + case VL53LX_DEVICECONFIGLEVEL_DYNAMIC_ONWARDS: + i2c_index = VL53LX_DYNAMIC_CONFIG_I2C_INDEX; + break; + default: + i2c_index = VL53LX_SYSTEM_CONTROL_I2C_INDEX; + break; + } + i2c_buffer_size_bytes = (VL53LX_SYSTEM_CONTROL_I2C_INDEX + VL53LX_SYSTEM_CONTROL_I2C_SIZE_BYTES) - i2c_index; + + pbuffer = &buffer[0]; + for (i = 0; i < i2c_buffer_size_bytes; i++) + *pbuffer++ = 0; + + if (device_config_level >= VL53LX_DEVICECONFIGLEVEL_FULL && status == VL53LX_ERROR_NONE) { + i2c_buffer_offset_bytes = VL53LX_STATIC_NVM_MANAGED_I2C_INDEX - i2c_index; + status = VL53LX_i2c_encode_static_nvm_managed(pstatic_nvm, VL53LX_STATIC_NVM_MANAGED_I2C_SIZE_BYTES, &buffer[i2c_buffer_offset_bytes]); + } + if (device_config_level >= VL53LX_DEVICECONFIGLEVEL_CUSTOMER_ONWARDS && status == VL53LX_ERROR_NONE) { + i2c_buffer_offset_bytes = VL53LX_CUSTOMER_NVM_MANAGED_I2C_INDEX - i2c_index; + status = VL53LX_i2c_encode_customer_nvm_managed(pcustomer_nvm, VL53LX_CUSTOMER_NVM_MANAGED_I2C_SIZE_BYTES, &buffer[i2c_buffer_offset_bytes]); + } + if (device_config_level >= VL53LX_DEVICECONFIGLEVEL_STATIC_ONWARDS && status == VL53LX_ERROR_NONE) { + i2c_buffer_offset_bytes = VL53LX_STATIC_CONFIG_I2C_INDEX - i2c_index; + status = VL53LX_i2c_encode_static_config(pstatic, VL53LX_STATIC_CONFIG_I2C_SIZE_BYTES, &buffer[i2c_buffer_offset_bytes]); + } + if (device_config_level >= VL53LX_DEVICECONFIGLEVEL_GENERAL_ONWARDS && status == VL53LX_ERROR_NONE) { + i2c_buffer_offset_bytes = VL53LX_GENERAL_CONFIG_I2C_INDEX - i2c_index; + status = VL53LX_i2c_encode_general_config(pgeneral, VL53LX_GENERAL_CONFIG_I2C_SIZE_BYTES, &buffer[i2c_buffer_offset_bytes]); + } + if (device_config_level >= VL53LX_DEVICECONFIGLEVEL_TIMING_ONWARDS && status == VL53LX_ERROR_NONE) { + i2c_buffer_offset_bytes = VL53LX_TIMING_CONFIG_I2C_INDEX - i2c_index; + status = VL53LX_i2c_encode_timing_config(ptiming, VL53LX_TIMING_CONFIG_I2C_SIZE_BYTES, &buffer[i2c_buffer_offset_bytes]); + } + if (device_config_level >= VL53LX_DEVICECONFIGLEVEL_DYNAMIC_ONWARDS && status == VL53LX_ERROR_NONE) { + i2c_buffer_offset_bytes = VL53LX_DYNAMIC_CONFIG_I2C_INDEX - i2c_index; + if ((psystem->system__mode_start & VL53LX_DEVICEMEASUREMENTMODE_BACKTOBACK) == VL53LX_DEVICEMEASUREMENTMODE_BACKTOBACK) { + pdynamic->system__grouped_parameter_hold_0 = pstate->cfg_gph_id | 0x01; + pdynamic->system__grouped_parameter_hold_1 = pstate->cfg_gph_id | 0x01; + pdynamic->system__grouped_parameter_hold = pstate->cfg_gph_id; + } + status = VL53LX_i2c_encode_dynamic_config(pdynamic, VL53LX_DYNAMIC_CONFIG_I2C_SIZE_BYTES, &buffer[i2c_buffer_offset_bytes]); + } + if (status == VL53LX_ERROR_NONE) { + i2c_buffer_offset_bytes = VL53LX_SYSTEM_CONTROL_I2C_INDEX - i2c_index; + status = VL53LX_i2c_encode_system_control(psystem, VL53LX_SYSTEM_CONTROL_I2C_SIZE_BYTES, &buffer[i2c_buffer_offset_bytes]); + } + if (status == VL53LX_ERROR_NONE) { + status = VL53LX_WriteMulti(Dev, i2c_index, buffer, (uint32_t)i2c_buffer_size_bytes); + } + if (status == VL53LX_ERROR_NONE) + status = VL53LX_update_ll_driver_rd_state(Dev); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_update_ll_driver_cfg_state(Dev); + + 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); + + 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); + + return Status; +} + +VL53LX_Error VL53LX_WaitMeasurementDataReady(VL53LX_DEV Dev) +{ + VL53LX_Error Status = VL53LX_ERROR_NONE; + + Status = VL53LX_poll_for_range_completion(Dev, VL53LX_RANGE_COMPLETION_POLLING_TIMEOUT_MS); + + return Status; +} + +VL53LX_Error VL53LX_is_new_data_ready(VL53LX_DEV Dev, uint8_t *pready) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + uint8_t gpio__mux_active_high_hv = 0; + uint8_t gpio__tio_hv_status = 0; + uint8_t interrupt_ready = 0; + + gpio__mux_active_high_hv = pdev->stat_cfg.gpio_hv_mux__ctrl & VL53LX_DEVICEINTERRUPTLEVEL_ACTIVE_MASK; + + if (gpio__mux_active_high_hv == VL53LX_DEVICEINTERRUPTLEVEL_ACTIVE_HIGH) + interrupt_ready = 0x01; + else + interrupt_ready = 0x00; + + status = VL53LX_RdByte(Dev, VL53LX_GPIO__TIO_HV_STATUS, &gpio__tio_hv_status); + + if ((gpio__tio_hv_status & 0x01) == interrupt_ready) + *pready = 0x01; + else + *pready = 0x00; + + return status; +} + +VL53LX_Error VL53LX_GetMeasurementDataReady(VL53LX_DEV Dev, uint8_t *pMeasurementDataReady) +{ + VL53LX_Error Status = VL53LX_ERROR_NONE; + + Status = VL53LX_is_new_data_ready(Dev, pMeasurementDataReady); + + return Status; +} + +long stmvl53lx_tv_dif(struct st_timeval *pstart_tv, struct st_timeval *pstop_tv) +{ + long total_sec, total_usec; + + total_sec = pstop_tv->tv_sec - pstart_tv->tv_sec; + total_usec = (pstop_tv->tv_usec - pstart_tv->tv_usec); + + return total_sec*1000000+total_usec; +} + +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; + + memset(pMultiRangingData, 0xFF, sizeof(VL53LX_MultiRangingData_t)); + + Status = VL53LX_get_device_results(Dev, VL53LX_DEVICERESULTSLEVEL_FULL, presults); + Status = SetMeasurementData(Dev, presults, pMultiRangingData); + + return Status; +} + +VL53LX_Error VL53LX_get_histogram_debug_data(VL53LX_DEV Dev, VL53LX_histogram_bin_data_t *pdata) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + memcpy(pdata, &(pdev->hist_data), sizeof(VL53LX_histogram_bin_data_t)); + + return status; +} + +VL53LX_Error VL53LX_get_additional_data(VL53LX_DEV Dev, VL53LX_additional_data_t *pdata) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + pdata->preset_mode = pdev->preset_mode; + pdata->zone_preset = pdev->zone_preset; + pdata->measurement_mode = pdev->measurement_mode; + pdata->offset_calibration_mode = pdev->offset_calibration_mode; + pdata->offset_correction_mode = pdev->offset_correction_mode; + pdata->dmax_mode = pdev->dmax_mode; + + pdata->phasecal_config_timeout_us = pdev->phasecal_config_timeout_us; + pdata->mm_config_timeout_us = pdev->mm_config_timeout_us; + pdata->range_config_timeout_us = pdev->range_config_timeout_us; + pdata->inter_measurement_period_ms = pdev->inter_measurement_period_ms; + pdata->dss_config__target_total_rate_mcps = pdev->dss_config__target_total_rate_mcps; + + status = VL53LX_get_histogram_debug_data(Dev, &(pdata->VL53LX_p_006)); + + return status; +} + +VL53LX_Error VL53LX_GetAdditionalData(VL53LX_DEV Dev, VL53LX_AdditionalData_t *pAdditionalData) +{ + VL53LX_Error Status = VL53LX_ERROR_NONE; + + Status = VL53LX_get_additional_data(Dev, pAdditionalData); + + return Status; +} + +static void detect_xtalk_value_change(struct stmvl53lx_data *data, VL53LX_MultiRangingData_t *meas) +{ + data->is_xtalk_value_changed = meas->HasXtalkValueChanged ? true : data->is_xtalk_value_changed; +} + +static void stmvl53lx_input_push_data_multiobject(struct stmvl53lx_data *data) +{ + VL53LX_MultiRangingData_t *mmeas = &data->meas.multi_range_data; + int i; + int rc = 0; + VL53LX_TargetRangeData_t *meas_array[4]; + VL53LX_CalibrationData_t calibration_data; + struct st_timeval tv; + struct input_dev *input = data->input_dev_ps; + + st_gettimeofday(&tv); + + for (i = 0; i < 4; i++) + meas_array[i] = &mmeas->RangeData[i]; + + rc = VL53LX_GetCalibrationData(&data->stdev, &calibration_data); + if (rc) { + vl53lx_errmsg("%d error:%d\n", __LINE__, rc); + return; + } + + input_report_abs(input, ABS_HAT0X, tv.tv_sec); + vl53lx_dbgmsg("ABS_HAT0X : %ld, %zu\n", tv.tv_sec, sizeof(tv.tv_sec)); + + input_report_abs(input, ABS_HAT0Y, tv.tv_usec); + vl53lx_dbgmsg("ABS_HAT0Y : %ld\n", tv.tv_usec); + + input_report_abs(input, ABS_WHEEL, meas_array[0]->AmbientRateRtnMegaCps); + vl53lx_dbgmsg("ABS_WHEEL : AmbRate = %d\n", meas_array[0]->AmbientRateRtnMegaCps); + + input_report_abs(input, ABS_TILT_X, (mmeas->HasXtalkValueChanged << 16) | (mmeas->StreamCount << 8) | ((mmeas->NumberOfObjectsFound & 0x3) << 6)); + vl53lx_dbgmsg("ABS_TILT_X :(%d):(%d):(%d)\n\n", mmeas->HasXtalkValueChanged, mmeas->StreamCount, mmeas->NumberOfObjectsFound); + + input_report_abs(input, ABS_TILT_Y, 0); + input_report_abs(input, ABS_TOOL_WIDTH, calibration_data.customer.algo__crosstalk_compensation_plane_offset_kcps); + + vl53lx_dbgmsg("ABS_TOOL_WIDTH Xtalk = %d\n", calibration_data.customer.algo__crosstalk_compensation_plane_offset_kcps); + input_report_abs(input, ABS_BRAKE, mmeas->EffectiveSpadRtnCount << 16 | ((meas_array[1]->RangeStatus) << 8) | meas_array[0]->RangeStatus); + vl53lx_dbgmsg("ABS_BRAKE : (%d):(%d):(%d)\n", mmeas->EffectiveSpadRtnCount, meas_array[1]->RangeStatus, meas_array[0]->RangeStatus); + vl53lx_dbgmsg("ABS_BRAKE : 0x%X\n", (mmeas->EffectiveSpadRtnCount & 0xFFFF) << 16 | ((meas_array[1]->RangeStatus) << 8) | meas_array[0]->RangeStatus); + + if (mmeas->NumberOfObjectsFound == 0) { + input_sync(input); + return; + } + + input_report_abs(input, ABS_HAT1X, meas_array[0]->RangeMilliMeter << 16 | (meas_array[0]->SigmaMilliMeter/65536)); + vl53lx_dbgmsg("ABS_HAT1X : 0x%X(%d:%d)\n", + meas_array[0]->RangeMilliMeter << 16 + | (meas_array[0]->SigmaMilliMeter/65536), + meas_array[0]->RangeMilliMeter, + (meas_array[0]->SigmaMilliMeter/65536)); + + input_report_abs(input, ABS_HAT1Y, meas_array[0]->RangeMinMilliMeter << 16 | meas_array[0]->RangeMaxMilliMeter); + vl53lx_dbgmsg("ABS_HAT1Y : 0x%X(%d:%d)\n", + meas_array[0]->RangeMinMilliMeter << 16 + | meas_array[0]->RangeMaxMilliMeter, + meas_array[0]->RangeMinMilliMeter, + meas_array[0]->RangeMaxMilliMeter); + + if (mmeas->NumberOfObjectsFound > 1) { + input_report_abs(input, ABS_HAT2X, meas_array[1]->RangeMilliMeter << 16 | (meas_array[1]->SigmaMilliMeter/65536)); + vl53lx_dbgmsg("ABS_HAT2X : 0x%x(%d:%d)\n", + meas_array[1]->RangeMilliMeter << 16 + | (meas_array[1]->SigmaMilliMeter/65536), + meas_array[1]->RangeMilliMeter, + (meas_array[1]->SigmaMilliMeter/65536)); + + input_report_abs(input, ABS_HAT2Y, meas_array[1]->RangeMinMilliMeter << 16 | meas_array[1]->RangeMaxMilliMeter); + vl53lx_dbgmsg("ABS_HAT1Y : 0x%X(%d:%d)\n", + meas_array[1]->RangeMinMilliMeter << 16 + | meas_array[1]->RangeMaxMilliMeter, + meas_array[1]->RangeMinMilliMeter, + meas_array[1]->RangeMaxMilliMeter); + } + input_report_abs(input, ABS_HAT3X, meas_array[0]->SignalRateRtnMegaCps); + vl53lx_dbgmsg("ABS_HAT3X : SignalRateRtnMegaCps_0(%d)\n", meas_array[0]->SignalRateRtnMegaCps); + if (mmeas->NumberOfObjectsFound > 1) { + input_report_abs(input, ABS_HAT3Y, meas_array[1]->SignalRateRtnMegaCps); + vl53lx_dbgmsg("ABS_HAT3Y : SignalRateRtnMegaCps_1(%d)\n", meas_array[1]->SignalRateRtnMegaCps); + } + input_report_abs(input, ABS_MISC, 0); + input_sync(input); +} + +static void stmvl53lx_input_push_data(struct stmvl53lx_data *data) +{ + stmvl53lx_input_push_data_multiobject(data); +} + +static void stmvl53lx_on_newdata_event(struct stmvl53lx_data *data) +{ + int rc = 0; + VL53LX_MultiRangingData_t *pmrange; + VL53LX_MultiRangingData_t *tmprange; + VL53LX_TargetRangeData_t RangeData[VL53LX_MAX_RANGE_RESULTS]; + long ts_msec; + int i; + struct input_dev *input = data->input_dev_ps; + + st_gettimeofday(&data->meas.comp_tv); + ts_msec = stmvl53lx_tv_dif(&data->start_tv, &data->meas.comp_tv)/1000; + + pmrange = &data->meas.multi_range_data; + tmprange = &data->meas.tmp_range_data; + + for (i = 0; i < VL53LX_MAX_RANGE_RESULTS; i++) + memcpy(&RangeData[i], &pmrange->RangeData[i], sizeof(VL53LX_TargetRangeData_t)); + + data->meas.intr++; + + rc = VL53LX_GetMultiRangingData(&data->stdev, &data->meas.tmp_range_data); + + if (tmprange->NumberOfObjectsFound == 0) + tmprange->RangeData[0].RangeStatus = VL53LX_RANGESTATUS_NONE; + + memcpy(pmrange, tmprange, sizeof(VL53LX_MultiRangingData_t)); + + if (!rc) + rc = VL53LX_GetAdditionalData(&data->stdev, &data->meas.additional_data); + detect_xtalk_value_change(data, pmrange); + + if (data->enable_sensor == 0) { + vl53lx_dbgmsg("at meas #%d we got stopped\n", data->meas.cnt); + return; + } + if (rc) { + vl53lx_errmsg("VL53LX_GetRangingMeasurementData @%d %d", __LINE__, rc); + data->meas.err_cnt++; + data->meas.err_tot++; + if (data->meas.err_cnt > stvm531_get_max_meas_err(data) || + data->meas.err_tot > stvm531_get_max_stream_err(data)) { + vl53lx_errmsg("on #%d %d err %d tot stop", data->meas.cnt, data->meas.err_cnt, data->meas.err_tot); + _ctrl_stop(data); + input_report_abs(input, ABS_MISC, ABNORMAL_STOP_3); + input_sync(input); + } + return; + } + + pmrange->TimeStamp = ts_msec; + for (i = 1; i < pmrange->NumberOfObjectsFound; i++) + pmrange->TimeStamp = ts_msec; + + data->meas.cnt++; + vl53lx_dbgmsg("#%3d %2d poll ts %5d status=%d obj cnt=%d\n", + data->meas.cnt, + data->meas.poll_cnt, + pmrange->TimeStamp, + pmrange->RangeData[0].RangeStatus, + pmrange->NumberOfObjectsFound); + + data->is_data_valid = true; + + wake_up_data_waiters(data); + + stmvl53lx_input_push_data(data); + stmvl53lx_insert_flush_events_lock(data); + + data->meas.start_tv = data->meas.comp_tv; + data->meas.poll_cnt = 0; + data->meas.err_cnt = 0; +} + +VL53LX_Error VL53LX_clear_interrupt_and_enable_next_range(VL53LX_DEV Dev, uint8_t measurement_mode) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_init_and_start_range(Dev, measurement_mode, VL53LX_DEVICECONFIGLEVEL_GENERAL_ONWARDS); + + return status; +} + +VL53LX_Error VL53LX_ClearInterruptAndStartMeasurement(VL53LX_DEV Dev) +{ + VL53LX_Error Status = VL53LX_ERROR_NONE; + uint8_t DeviceMeasurementMode; + + DeviceMeasurementMode = VL53LXDevDataGet(Dev, LLData.measurement_mode); + + Status = VL53LX_clear_interrupt_and_enable_next_range(Dev, DeviceMeasurementMode); + return Status; +} + +static int stmvl53lx_intr_process(struct stmvl53lx_data *data) +{ + uint8_t data_rdy; + int rc = 0; + struct st_timeval tv_now; + struct input_dev *input = data->input_dev_ps; + + if (!data->enable_sensor) + goto done; + + data->meas.poll_cnt++; + rc = VL53LX_GetMeasurementDataReady(&data->stdev, &data_rdy); + if (rc) { + vl53lx_errmsg("GetMeasurementDataReady @%d %d, fail\n", __LINE__, rc); + goto stop_io; + } + + if (!data_rdy) { + long poll_us; + + st_gettimeofday(&tv_now); + poll_us = stmvl53lx_tv_dif(&data->meas.start_tv, &tv_now); + if (poll_us > data->timing_budget*4) { + vl53lx_errmsg("we're polling %ld ms too long\n", poll_us/1000); + goto stop_io; + } + work_dbg("intr with no data rdy"); + goto done; + } + + if (data->is_first_irq) + data->is_first_irq = false; + else + stmvl53lx_on_newdata_event(data); + + if (data->enable_sensor) { + work_dbg("intr clr"); + data->is_delay_allowed = data->allow_hidden_start_stop; + rc = VL53LX_ClearInterruptAndStartMeasurement(&data->stdev); + data->is_delay_allowed = 0; + if (rc) { + vl53lx_errmsg("Cltr intr restart fail %d\n", rc); + goto stop_io; + } + } +done: + return rc; +stop_io: + vl53lx_errmsg("GetDatardy fail stop\n"); + _ctrl_stop(data); + input_report_abs(input, ABS_MISC, ABNORMAL_STOP_1); + input_sync(input); + return rc; +} + +int stmvl53lx_intr_handler(struct stmvl53lx_data *data) +{ + int rc = 0; + + mutex_lock(&data->work_mutex); + if (data->enable_sensor) { + rc = stmvl53lx_intr_process(data); + } else { + vl53lx_dbgmsg("got intr but not on (dummy or calibration)\n"); + rc = 0; + } + + mutex_unlock(&data->work_mutex); + return rc; +} + +static irqreturn_t stmvl53lx_irq_handler_i2c(int vec, void *info) +{ + struct i2c_data *i2c_data = (struct i2c_data *)info; + + if (i2c_data->irq == vec) { + modi2c_dbg("irq"); + stmvl53lx_intr_handler(i2c_data->vl53lx_data); + modi2c_dbg("over"); + } else { + if (!i2c_data->msg_flag.unhandled_irq_vec) { + modi2c_warn("unmatching vec %d != %d\n", vec, i2c_data->irq); + i2c_data->msg_flag.unhandled_irq_vec = 1; + } + } + return IRQ_HANDLED; +} + +static void memory_release(struct kref *kref) +{ + struct i2c_data *data = container_of(kref, struct i2c_data, ref); + + vl53lx_dbgmsg("Enter\n"); + kfree(data->vl53lx_data); + kfree(data); + vl53lx_dbgmsg("End\n"); +} + +static int reset_release(struct stmvl53lx_data *data) +{ + int rc = 0; + + if (!data->reset_state) + return 0; + + rc = stmvl53lx_module_func_tbl.reset_release(data->client_object); + if (rc) + vl53lx_errmsg("reset release fail rc=%d\n", rc); + else + data->reset_state = 0; + + return rc; +} + +static int stmvl53lx_start(struct stmvl53lx_data *data) +{ + int rc = 0; + + data->is_first_irq = true; + data->is_data_valid = false; + data->is_xtalk_value_changed = false; + + rc = reset_release(data); + if (rc) + goto done; + + rc = stmvl53lx_sendparams(data); + if (rc) + goto done; + + st_gettimeofday(&data->start_tv); + data->meas.start_tv = data->start_tv; + kill_mz_data(&data->meas.multi_range_data); + + data->allow_hidden_start_stop = false; + + rc = VL53LX_StartMeasurement(&data->stdev); + if (rc) { + vl53lx_errmsg("VL53LX_StartMeasurement @%d fail %d", __LINE__, rc); + rc = store_last_error(data, rc); + goto done; + } + + data->meas.cnt = 0; + data->meas.err_cnt = 0; + data->meas.err_tot = 0; + data->meas.poll_cnt = 0; + data->meas.intr = 0; + data->enable_sensor = 1; + if (data->poll_mode) { + schedule_delayed_work(&data->dwork, msecs_to_jiffies(data->poll_delay_ms)); + } + +done: + data->is_first_start_done = true; + return rc; +} + +static int ctrl_start(struct stmvl53lx_data *data) +{ + int rc = 0; + + mutex_lock(&data->work_mutex); + + if (data->is_device_remove) { + rc = -ENODEV; + goto done; + } + + vl53lx_dbgmsg(" state = %d\n", data->enable_sensor); + if (data->enable_sensor == 0 && !data->is_calibrating) { + rc = stmvl53lx_start(data); + } else { + rc = -EBUSY; + } + vl53lx_dbgmsg(" final state = %d\n", data->enable_sensor); +done: + mutex_unlock(&data->work_mutex); + return rc; +} + +static void stmvl53lx_insert_flush_events_lock(struct stmvl53lx_data *data) +{ + while (data->flush_todo_counter) { + data->flushCount++; + input_report_abs(data->input_dev_ps, ABS_GAS, data->flushCount); + input_sync(data->input_dev_ps); + vl53lx_dbgmsg("Sensor HAL Flush Count = %u\n", data->flushCount); + data->flush_todo_counter--; + } +} + +static int _ctrl_stop(struct stmvl53lx_data *data) +{ + int rc = 0; + + vl53lx_dbgmsg("enter state = %d\n", data->enable_sensor); + data->is_data_valid = true; + if (data->enable_sensor == 1) { + rc = stmvl53lx_stop(data); + } else { + vl53lx_dbgmsg("already off did nothing\n"); + rc = 0; + } + stmvl53lx_insert_flush_events_lock(data); + vl53lx_dbgmsg(" final state = %d\n", data->enable_sensor); + + return rc; +} + +static int ctrl_stop(struct stmvl53lx_data *data) +{ + int rc = 0; + + mutex_lock(&data->work_mutex); + + if (data->is_device_remove) { + rc = -ENODEV; + goto done; + } + if (data->enable_sensor) + rc = _ctrl_stop(data); + else + rc = -EBUSY; +done: + mutex_unlock(&data->work_mutex); + return rc; +} + +static int ctrl_reg_access(struct stmvl53lx_data *data, void *p) +{ + struct stmvl53lx_register reg; + size_t total_byte; + int rc = 0; + + if (data->is_device_remove) + return -ENODEV; + + total_byte = offsetof(struct stmvl53lx_register, data.b); + if (copy_from_user(®, p, total_byte)) { + vl53lx_errmsg("%d, fail\n", __LINE__); + return -EFAULT; + } + + if (reg.cnt > STMVL53LX_MAX_CCI_XFER_SZ) { + vl53lx_errmsg("reg len %d > size limit\n", reg.cnt); + return -EINVAL; + } + + total_byte = offsetof(struct stmvl53lx_register, data.bytes[reg.cnt]); + if (!reg.is_read) { + if (copy_from_user(®, p, total_byte)) { + vl53lx_errmsg(" data cpy fail\n"); + return -EFAULT; + } + } + + if (!reg.is_read) { + rc = VL53LX_WriteMulti(&data->stdev, (uint16_t)reg.index, reg.data.bytes, reg.cnt); + reg.status = rc; + total_byte = offsetof(struct stmvl53lx_register, data.b); + vl53lx_dbgmsg("wr %x %d bytes statu %d\n", reg.index, reg.cnt, rc); + if (rc) + rc = store_last_error(data, rc); + } else { + rc = VL53LX_ReadMulti(&data->stdev, (uint16_t)reg.index, reg.data.bytes, reg.cnt); + reg.status = rc; + vl53lx_dbgmsg("rd %x %d bytes status %d\n", reg.index, reg.cnt, rc); + if (rc) { + total_byte = offsetof(struct stmvl53lx_register, data.b); + rc = store_last_error(data, rc); + } + } + + if (copy_to_user(p, ®, total_byte)) { + vl53lx_errmsg("%d, fail\n", __LINE__); + return -EFAULT; + } + return rc; +} + +static int reset_hold(struct stmvl53lx_data *data) +{ + int rc = 0; + + if (data->reset_state) + return 0; + + if (data->force_device_on_en) + return 0; + + rc = stmvl53lx_module_func_tbl.reset_hold(data->client_object); + if (!rc) + data->reset_state = 1; + + return rc; +} + +static ssize_t stmvl53lx_show_enable_ps_sensor(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct stmvl53lx_data *data = dev_get_drvdata(dev); + return snprintf(buf, 5, "%d\n", data->enable_sensor); +} + +static ssize_t stmvl53lx_store_enable_ps_sensor(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + int rc = 0; + unsigned long val; + struct stmvl53lx_data *data = dev_get_drvdata(dev); + + rc = kstrtoul(buf, 10, &val); + if (rc) { + vl53lx_errmsg("enable sensor syntax in %s\n", buf); + return -EINVAL; + } + if (val == 1) { + rc = ctrl_start(data); + } else if (val == 0) { + rc = ctrl_stop(data); + } else { + vl53lx_dbgmsg("Unclog Input sub-system\n"); + input_report_abs(data->input_dev_ps, ABS_HAT0X, -1); + input_report_abs(data->input_dev_ps, ABS_HAT0Y, -1); + input_report_abs(data->input_dev_ps, ABS_HAT1X, -1); + input_report_abs(data->input_dev_ps, ABS_HAT1Y, -1); + input_report_abs(data->input_dev_ps, ABS_HAT2X, -1); + input_report_abs(data->input_dev_ps, ABS_HAT2Y, -1); + input_report_abs(data->input_dev_ps, ABS_HAT3X, -1); + input_report_abs(data->input_dev_ps, ABS_HAT3Y, -1); + input_report_abs(data->input_dev_ps, ABS_WHEEL, -1); + input_report_abs(data->input_dev_ps, ABS_BRAKE, -1); + input_report_abs(data->input_dev_ps, ABS_GAS, -1); + input_report_abs(data->input_dev_ps, ABS_TILT_X, -1); + input_report_abs(data->input_dev_ps, ABS_TILT_Y, -1); + input_report_abs(data->input_dev_ps, ABS_TOOL_WIDTH, -1); + input_report_abs(data->input_dev_ps, ABS_DISTANCE, -1); + input_report_abs(data->input_dev_ps, ABS_THROTTLE, -1); + input_report_abs(data->input_dev_ps, ABS_RUDDER, -1); + input_report_abs(data->input_dev_ps, ABS_MISC, -1); + input_report_abs(data->input_dev_ps, ABS_VOLUME, -1); + input_sync(data->input_dev_ps); + vl53lx_dbgmsg("Unclog the input sub-system\n"); + rc = 0; + } + vl53lx_dbgmsg("End\n"); + return rc ? rc : count; +} + +static DEVICE_ATTR(enable_ps_sensor, 0664, stmvl53lx_show_enable_ps_sensor, stmvl53lx_store_enable_ps_sensor); + +static int stmvl53lx_set_poll_delay_ms(struct stmvl53lx_data *data, int delay) +{ + int rc = 0; + + if (delay <= 0) + rc = -EINVAL; + else + data->poll_delay_ms = delay; + + return rc; +} + +IMPLEMENT_PARAMETER_INTEGER(poll_delay_ms, "poll delay ms") + +static DEVICE_ATTR(set_delay_ms, 0660, stmvl53lx_show_poll_delay_ms, stmvl53lx_store_poll_delay_ms); + +static int stmvl53lx_set_timing_budget(struct stmvl53lx_data *data, int timing) +{ + int rc = 0; + + if (timing <= 0) { + vl53lx_errmsg("invalid timing valid %d\n", timing); + rc = -EINVAL; + } else if (data->enable_sensor) { + rc = VL53LX_SetMeasurementTimingBudgetMicroSeconds(&data->stdev, + timing); + if (rc) { + vl53lx_errmsg("SetTimingBudget %d fail %d", timing, rc); + rc = store_last_error(data, rc); + } else + data->timing_budget = timing; + } else + data->timing_budget = timing; + + return rc; +} + +IMPLEMENT_PARAMETER_INTEGER(timing_budget, "timing budget") + +static DEVICE_ATTR(timing_budget, 0660, stmvl53lx_show_timing_budget, stmvl53lx_store_timing_budget); + +static ssize_t stmvl53lx_show_roi(struct device *dev, struct device_attribute *attr, char *buf) +{ + int n; + struct stmvl53lx_data *data = dev_get_drvdata(dev); + + mutex_lock(&data->work_mutex); + n = scnprintf(buf, PAGE_SIZE, "%d %d %d %d\n", data->roi_cfg.TopLeftX, data->roi_cfg.TopLeftY, data->roi_cfg.BotRightX, data->roi_cfg.BotRightY); + mutex_unlock(&data->work_mutex); + return n; +} + +static ssize_t stmvl53lx_store_roi(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + int rc; + int n; + int tlx, tly, brx, bry; + struct stmvl53lx_data *data = dev_get_drvdata(dev); + + mutex_lock(&data->work_mutex); + if (data->enable_sensor) { + vl53lx_errmsg("ERROR can't set roi while ranging"); + rc = -EBUSY; + } else { + n = sscanf(buf, "%d %d %d %d", &tlx, &tly, &brx, &bry); + if (n == 4) { + data->roi_cfg.TopLeftX = tlx; + data->roi_cfg.TopLeftY = tly; + data->roi_cfg.BotRightX = brx; + data->roi_cfg.BotRightY = bry; + rc = count; + vl53lx_dbgmsg("ROI %2d %2d %2d %2d\n", (int)data->roi_cfg.TopLeftX, (int)data->roi_cfg.TopLeftY, (int)data->roi_cfg.BotRightX, (int)data->roi_cfg.BotRightY); + } else { + vl53lx_errmsg("wrong roi syntax %s ", buf); + rc = -EINVAL; + } + } + mutex_unlock(&data->work_mutex); + vl53lx_dbgmsg("ret %d count %d\n", rc, (int)count); + + return rc; +} + +static DEVICE_ATTR(roi, 0660, stmvl53lx_show_roi, stmvl53lx_store_roi); + +static int stmvl53lx_set_distance_mode(struct stmvl53lx_data *data, + int distance_mode) +{ + int rc = 0; + + if (data->enable_sensor) { + vl53lx_errmsg("can't change distance mode while ranging\n"); + rc = -EBUSY; + } else { + switch (distance_mode) { + case VL53LX_DISTANCEMODE_SHORT: + case VL53LX_DISTANCEMODE_MEDIUM: + case VL53LX_DISTANCEMODE_LONG: + data->distance_mode = distance_mode; + break; + default: + vl53lx_errmsg("invalid distance mode %d\n", + distance_mode); + rc = -EINVAL; + break; + } + } + + return rc; +} + +IMPLEMENT_PARAMETER_INTEGER(distance_mode, "distance mode") + +static DEVICE_ATTR(distance_mode, 0660, stmvl53lx_show_distance_mode, stmvl53lx_store_distance_mode); + +static int stmvl53lx_set_crosstalk_enable(struct stmvl53lx_data *data, + int crosstalk_enable) +{ + int rc = 0; + + if (data->enable_sensor) { + vl53lx_errmsg("can't change crosstalk enable while ranging\n"); + rc = -EBUSY; + } else if (crosstalk_enable == 0 || crosstalk_enable == 1) { + data->crosstalk_enable = crosstalk_enable; + } else { + vl53lx_errmsg("invalid crosstalk enable %d\n", + crosstalk_enable); + rc = -EINVAL; + } + + return rc; +} + +IMPLEMENT_PARAMETER_INTEGER(crosstalk_enable, "crosstalk enable") + +static DEVICE_ATTR(crosstalk_enable, 0660, stmvl53lx_show_crosstalk_enable, stmvl53lx_store_crosstalk_enable); + +static int stmvl53lx_set_force_device_on_en(struct stmvl53lx_data *data, + int force_device_on_en) +{ + int rc = 0; + + if (force_device_on_en != 0 && force_device_on_en != 1) { + vl53lx_errmsg("invalid force_device_on_en mode %d\n", + force_device_on_en); + return -EINVAL; + } + + data->force_device_on_en = force_device_on_en; + + /* don't update reset if sensor is enable */ + if (data->enable_sensor) + return 0; + + /* ok update reset according force_device_on_en value */ + if (force_device_on_en) + rc = reset_release(data); + else + rc = reset_hold(data); + + return rc; +} + +IMPLEMENT_PARAMETER_INTEGER(force_device_on_en, "force device on enable") + + +static DEVICE_ATTR(force_device_on_enable, 0660, stmvl53lx_show_force_device_on_en, stmvl53lx_store_force_device_on_en); + +static int stmvl53lx_set_offset_correction_mode(struct stmvl53lx_data *data, + int offset_correction_mode) +{ + int rc = 0; + + if (data->enable_sensor) { + vl53lx_errmsg( + "can't change offset correction mode while ranging\n"); + rc = -EBUSY; + } else { + switch (offset_correction_mode) { + case VL53LX_OFFSETCORRECTIONMODE_STANDARD: + case VL53LX_OFFSETCORRECTIONMODE_PERVCSEL: + data->offset_correction_mode = offset_correction_mode; + break; + default: + vl53lx_errmsg("invalid offset correction mode %d\n", + offset_correction_mode); + rc = -EINVAL; + break; + } + } + + return rc; +} + +IMPLEMENT_PARAMETER_INTEGER(offset_correction_mode, "offset correction mode") + +static DEVICE_ATTR(offset_correction_mode, 0660, stmvl53lx_show_offset_correction_mode, stmvl53lx_store_offset_correction_mode); + +static ssize_t stmvl53lx_do_flush(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct stmvl53lx_data *data = dev_get_drvdata(dev); + + mutex_lock(&data->work_mutex); + + data->flush_todo_counter++; + if (data->enable_sensor == 0) + stmvl53lx_insert_flush_events_lock(data); + + mutex_unlock(&data->work_mutex); + + return count; +} + +static DEVICE_ATTR(do_flush, 0660, NULL, stmvl53lx_do_flush); + +static ssize_t stmvl53lx_show_enable_debug(struct device *dev, struct device_attribute *attr, char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%d\n", stmvl53lx_enable_debug); +} + +static ssize_t stmvl53lx_store_enable_debug(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + int enable_debug; + int rc = 0; + + if (kstrtoint(buf, 0, &enable_debug)) { + vl53lx_errmsg("invalid syntax in %s", buf); + rc = -EINVAL; + } else + stmvl53lx_enable_debug = enable_debug; + + return rc ? rc : count; +} + +static DEVICE_ATTR(enable_debug, 0660, stmvl53lx_show_enable_debug, stmvl53lx_store_enable_debug); + +static ssize_t stmvl53lx_show_last_error_config(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct stmvl53lx_data *data = dev_get_drvdata(dev); + return scnprintf(buf, PAGE_SIZE, "%d\n", data->last_error); +} + +static DEVICE_ATTR(last_error, 0440, stmvl53lx_show_last_error_config, NULL); + +static ssize_t display_FixPoint1616(char *buf, size_t size, FixPoint1616_t fix) +{ + uint32_t msb = fix >> 16; + uint32_t lsb = fix & 0xffff; + + lsb = (lsb * 1000000ULL + 32768) / 65536; + + return scnprintf(buf, size, "%d.%06d", msb, (uint32_t) lsb); +} + +static ssize_t stmvl53lx_show_optical_center_config(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct stmvl53lx_data *data = dev_get_drvdata(dev); + ssize_t res = 0; + + res += display_FixPoint1616(&buf[res], PAGE_SIZE - res, data->optical_offset_x); + res += scnprintf(&buf[res], PAGE_SIZE - res, " "); + res += display_FixPoint1616(&buf[res], PAGE_SIZE - res, data->optical_offset_y); + res += scnprintf(&buf[res], PAGE_SIZE - res, "\n"); + return res; +} + +static DEVICE_ATTR(optical_center, 0440, stmvl53lx_show_optical_center_config, NULL); + +VL53LX_Error VL53LX_set_tuning_parm(VL53LX_DEV Dev, VL53LX_TuningParms tuning_parm_key, int32_t tuning_parm_value) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + VL53LX_hist_post_process_config_t *pHP = &(pdev->histpostprocess); + VL53LX_xtalkextract_config_t *pXC = &(pdev->xtalk_extract_cfg); + + switch (tuning_parm_key) { + case VL53LX_TUNINGPARM_VERSION: + pdev->tuning_parms.tp_tuning_parm_version = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_KEY_TABLE_VERSION: + pdev->tuning_parms.tp_tuning_parm_key_table_version = (uint16_t)tuning_parm_value; + if ((uint16_t)tuning_parm_value != VL53LX_TUNINGPARM_KEY_TABLE_VERSION_DEFAULT) + status = VL53LX_ERROR_TUNING_PARM_KEY_MISMATCH; + break; + case VL53LX_TUNINGPARM_LLD_VERSION: + pdev->tuning_parms.tp_tuning_parm_lld_version = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_HIST_ALGO_SELECT: + pHP->hist_algo_select = (VL53LX_HistAlgoSelect)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_HIST_TARGET_ORDER: + pHP->hist_target_order = (VL53LX_HistTargetOrder)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_HIST_FILTER_WOI_0: + pHP->filter_woi0 = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_HIST_FILTER_WOI_1: + pHP->filter_woi1 = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_HIST_AMB_EST_METHOD: + pHP->hist_amb_est_method = (VL53LX_HistAmbEstMethod)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_HIST_AMB_THRESH_SIGMA_0: + pHP->ambient_thresh_sigma0 = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_HIST_AMB_THRESH_SIGMA_1: + pHP->ambient_thresh_sigma1 = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_HIST_MIN_AMB_THRESH_EVENTS: + pHP->min_ambient_thresh_events = (int32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_HIST_AMB_EVENTS_SCALER: + pHP->ambient_thresh_events_scaler = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_HIST_NOISE_THRESHOLD: + pHP->noise_threshold = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_HIST_SIGNAL_TOTAL_EVENTS_LIMIT: + pHP->signal_total_events_limit = (int32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_HIST_SIGMA_EST_REF_MM: + pHP->sigma_estimator__sigma_ref_mm = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_HIST_SIGMA_THRESH_MM: + pHP->sigma_thresh = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_HIST_GAIN_FACTOR: + pdev->gain_cal.histogram_ranging_gain_factor = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_CONSISTENCY_HIST_PHASE_TOLERANCE: + pHP->algo__consistency_check__phase_tolerance = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_CONSISTENCY_HIST_MIN_MAX_TOLERANCE_MM: + pHP->algo__consistency_check__min_max_tolerance = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_CONSISTENCY_HIST_EVENT_SIGMA: + pHP->algo__consistency_check__event_sigma = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_CONSISTENCY_HIST_EVENT_SIGMA_MIN_SPAD_LIMIT: + pHP->algo__consistency_check__event_min_spad_count = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_INITIAL_PHASE_RTN_HISTO_LONG_RANGE: + pdev->tuning_parms.tp_init_phase_rtn_hist_long = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_INITIAL_PHASE_RTN_HISTO_MED_RANGE: + pdev->tuning_parms.tp_init_phase_rtn_hist_med = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_INITIAL_PHASE_RTN_HISTO_SHORT_RANGE: + pdev->tuning_parms.tp_init_phase_rtn_hist_short = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_INITIAL_PHASE_REF_HISTO_LONG_RANGE: + pdev->tuning_parms.tp_init_phase_ref_hist_long = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_INITIAL_PHASE_REF_HISTO_MED_RANGE: + pdev->tuning_parms.tp_init_phase_ref_hist_med = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_INITIAL_PHASE_REF_HISTO_SHORT_RANGE: + pdev->tuning_parms.tp_init_phase_ref_hist_short = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_XTALK_DETECT_MIN_VALID_RANGE_MM: + pdev->xtalk_cfg.algo__crosstalk_detect_min_valid_range_mm = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_XTALK_DETECT_MAX_VALID_RANGE_MM: + pdev->xtalk_cfg.algo__crosstalk_detect_max_valid_range_mm = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_XTALK_DETECT_MAX_SIGMA_MM: + pdev->xtalk_cfg.algo__crosstalk_detect_max_sigma_mm = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_XTALK_DETECT_MIN_MAX_TOLERANCE: + pHP->algo__crosstalk_detect_min_max_tolerance = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_XTALK_DETECT_MAX_VALID_RATE_KCPS: + pdev->xtalk_cfg.algo__crosstalk_detect_max_valid_rate_kcps = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_XTALK_DETECT_EVENT_SIGMA: + pHP->algo__crosstalk_detect_event_sigma = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_HIST_XTALK_MARGIN_KCPS: + pdev->xtalk_cfg.histogram_mode_crosstalk_margin_kcps = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_CONSISTENCY_LITE_PHASE_TOLERANCE: + pdev->tuning_parms.tp_consistency_lite_phase_tolerance = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_PHASECAL_TARGET: + pdev->tuning_parms.tp_phasecal_target = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_LITE_CAL_REPEAT_RATE: + pdev->tuning_parms.tp_cal_repeat_rate = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_LITE_RANGING_GAIN_FACTOR: + pdev->gain_cal.standard_ranging_gain_factor = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_LITE_MIN_CLIP_MM: + pdev->tuning_parms.tp_lite_min_clip = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_LITE_LONG_SIGMA_THRESH_MM: + pdev->tuning_parms.tp_lite_long_sigma_thresh_mm = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_LITE_MED_SIGMA_THRESH_MM: + pdev->tuning_parms.tp_lite_med_sigma_thresh_mm = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_LITE_SHORT_SIGMA_THRESH_MM: + pdev->tuning_parms.tp_lite_short_sigma_thresh_mm = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_LITE_LONG_MIN_COUNT_RATE_RTN_MCPS: + pdev->tuning_parms.tp_lite_long_min_count_rate_rtn_mcps = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_LITE_MED_MIN_COUNT_RATE_RTN_MCPS: + pdev->tuning_parms.tp_lite_med_min_count_rate_rtn_mcps = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_LITE_SHORT_MIN_COUNT_RATE_RTN_MCPS: + pdev->tuning_parms.tp_lite_short_min_count_rate_rtn_mcps = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_LITE_SIGMA_EST_PULSE_WIDTH: + pdev->tuning_parms.tp_lite_sigma_est_pulse_width_ns = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_LITE_SIGMA_EST_AMB_WIDTH_NS: + pdev->tuning_parms.tp_lite_sigma_est_amb_width_ns = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_LITE_SIGMA_REF_MM: + pdev->tuning_parms.tp_lite_sigma_ref_mm = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_LITE_RIT_MULT: + pdev->xtalk_cfg.crosstalk_range_ignore_threshold_mult = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_LITE_SEED_CONFIG: + pdev->tuning_parms.tp_lite_seed_cfg = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_LITE_QUANTIFIER: + pdev->tuning_parms.tp_lite_quantifier = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_LITE_FIRST_ORDER_SELECT: + pdev->tuning_parms.tp_lite_first_order_select = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_LITE_XTALK_MARGIN_KCPS: + pdev->xtalk_cfg.lite_mode_crosstalk_margin_kcps = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_INITIAL_PHASE_RTN_LITE_LONG_RANGE: + pdev->tuning_parms.tp_init_phase_rtn_lite_long = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_INITIAL_PHASE_RTN_LITE_MED_RANGE: + pdev->tuning_parms.tp_init_phase_rtn_lite_med = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_INITIAL_PHASE_RTN_LITE_SHORT_RANGE: + pdev->tuning_parms.tp_init_phase_rtn_lite_short = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_INITIAL_PHASE_REF_LITE_LONG_RANGE: + pdev->tuning_parms.tp_init_phase_ref_lite_long = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_INITIAL_PHASE_REF_LITE_MED_RANGE: + pdev->tuning_parms.tp_init_phase_ref_lite_med = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_INITIAL_PHASE_REF_LITE_SHORT_RANGE: + pdev->tuning_parms.tp_init_phase_ref_lite_short = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_TIMED_SEED_CONFIG: + pdev->tuning_parms.tp_timed_seed_cfg = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_DMAX_CFG_SIGNAL_THRESH_SIGMA: + pdev->dmax_cfg.signal_thresh_sigma = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_DMAX_CFG_REFLECTANCE_ARRAY_0: + pdev->dmax_cfg.target_reflectance_for_dmax_calc[0] = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_DMAX_CFG_REFLECTANCE_ARRAY_1: + pdev->dmax_cfg.target_reflectance_for_dmax_calc[1] = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_DMAX_CFG_REFLECTANCE_ARRAY_2: + pdev->dmax_cfg.target_reflectance_for_dmax_calc[2] = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_DMAX_CFG_REFLECTANCE_ARRAY_3: + pdev->dmax_cfg.target_reflectance_for_dmax_calc[3] = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_DMAX_CFG_REFLECTANCE_ARRAY_4: + pdev->dmax_cfg.target_reflectance_for_dmax_calc[4] = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_VHV_LOOPBOUND: + pdev->stat_nvm.vhv_config__timeout_macrop_loop_bound = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_REFSPADCHAR_DEVICE_TEST_MODE: + pdev->refspadchar.device_test_mode = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_REFSPADCHAR_VCSEL_PERIOD: + pdev->refspadchar.VL53LX_p_005 = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_REFSPADCHAR_PHASECAL_TIMEOUT_US: + pdev->refspadchar.timeout_us = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_REFSPADCHAR_TARGET_COUNT_RATE_MCPS: + pdev->refspadchar.target_count_rate_mcps = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_REFSPADCHAR_MIN_COUNTRATE_LIMIT_MCPS: + pdev->refspadchar.min_count_rate_limit_mcps = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_REFSPADCHAR_MAX_COUNTRATE_LIMIT_MCPS: + pdev->refspadchar.max_count_rate_limit_mcps = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_XTALK_EXTRACT_NUM_OF_SAMPLES: + pXC->num_of_samples = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_XTALK_EXTRACT_MIN_FILTER_THRESH_MM: + pXC->algo__crosstalk_extract_min_valid_range_mm = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_XTALK_EXTRACT_MAX_FILTER_THRESH_MM: + pXC->algo__crosstalk_extract_max_valid_range_mm = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_XTALK_EXTRACT_DSS_RATE_MCPS: + pXC->dss_config__target_total_rate_mcps = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_XTALK_EXTRACT_PHASECAL_TIMEOUT_US: + pXC->phasecal_config_timeout_us = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_XTALK_EXTRACT_MAX_VALID_RATE_KCPS: + pXC->algo__crosstalk_extract_max_valid_rate_kcps = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_XTALK_EXTRACT_SIGMA_THRESHOLD_MM: + pXC->algo__crosstalk_extract_max_sigma_mm = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_XTALK_EXTRACT_DSS_TIMEOUT_US: + pXC->mm_config_timeout_us = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_XTALK_EXTRACT_BIN_TIMEOUT_US: + pXC->range_config_timeout_us = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_OFFSET_CAL_DSS_RATE_MCPS: + pdev->offsetcal_cfg.dss_config__target_total_rate_mcps = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_OFFSET_CAL_PHASECAL_TIMEOUT_US: + pdev->offsetcal_cfg.phasecal_config_timeout_us = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_OFFSET_CAL_MM_TIMEOUT_US: + pdev->offsetcal_cfg.mm_config_timeout_us = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_OFFSET_CAL_RANGE_TIMEOUT_US: + pdev->offsetcal_cfg.range_config_timeout_us = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_OFFSET_CAL_PRE_SAMPLES: + pdev->offsetcal_cfg.pre_num_of_samples = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_OFFSET_CAL_MM1_SAMPLES: + pdev->offsetcal_cfg.mm1_num_of_samples = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_OFFSET_CAL_MM2_SAMPLES: + pdev->offsetcal_cfg.mm2_num_of_samples = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_ZONE_CAL_DSS_RATE_MCPS: + pdev->zonecal_cfg.dss_config__target_total_rate_mcps = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_ZONE_CAL_PHASECAL_TIMEOUT_US: + pdev->zonecal_cfg.phasecal_config_timeout_us = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_ZONE_CAL_DSS_TIMEOUT_US: + pdev->zonecal_cfg.mm_config_timeout_us = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_ZONE_CAL_PHASECAL_NUM_SAMPLES: + pdev->zonecal_cfg.phasecal_num_of_samples = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_ZONE_CAL_RANGE_TIMEOUT_US: + pdev->zonecal_cfg.range_config_timeout_us = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_ZONE_CAL_ZONE_NUM_SAMPLES: + pdev->zonecal_cfg.zone_num_of_samples = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_SPADMAP_VCSEL_PERIOD: + pdev->ssc_cfg.VL53LX_p_005 = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_SPADMAP_VCSEL_START: + pdev->ssc_cfg.vcsel_start = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_SPADMAP_RATE_LIMIT_MCPS: + pdev->ssc_cfg.rate_limit_mcps = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_LITE_DSS_CONFIG_TARGET_TOTAL_RATE_MCPS: + pdev->tuning_parms.tp_dss_target_lite_mcps = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_RANGING_DSS_CONFIG_TARGET_TOTAL_RATE_MCPS: + pdev->tuning_parms.tp_dss_target_histo_mcps = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_MZ_DSS_CONFIG_TARGET_TOTAL_RATE_MCPS: + pdev->tuning_parms.tp_dss_target_histo_mz_mcps = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_TIMED_DSS_CONFIG_TARGET_TOTAL_RATE_MCPS: + pdev->tuning_parms.tp_dss_target_timed_mcps = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_LITE_PHASECAL_CONFIG_TIMEOUT_US: + pdev->tuning_parms.tp_phasecal_timeout_lite_us = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_RANGING_LONG_PHASECAL_CONFIG_TIMEOUT_US: + pdev->tuning_parms.tp_phasecal_timeout_hist_long_us = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_RANGING_MED_PHASECAL_CONFIG_TIMEOUT_US: + pdev->tuning_parms.tp_phasecal_timeout_hist_med_us = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_RANGING_SHORT_PHASECAL_CONFIG_TIMEOUT_US: + pdev->tuning_parms.tp_phasecal_timeout_hist_short_us = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_MZ_LONG_PHASECAL_CONFIG_TIMEOUT_US: + pdev->tuning_parms.tp_phasecal_timeout_mz_long_us = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_MZ_MED_PHASECAL_CONFIG_TIMEOUT_US: + pdev->tuning_parms.tp_phasecal_timeout_mz_med_us = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_MZ_SHORT_PHASECAL_CONFIG_TIMEOUT_US: + pdev->tuning_parms.tp_phasecal_timeout_mz_short_us = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_TIMED_PHASECAL_CONFIG_TIMEOUT_US: + pdev->tuning_parms.tp_phasecal_timeout_timed_us = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_LITE_MM_CONFIG_TIMEOUT_US: + pdev->tuning_parms.tp_mm_timeout_lite_us = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_RANGING_MM_CONFIG_TIMEOUT_US: + pdev->tuning_parms.tp_mm_timeout_histo_us = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_MZ_MM_CONFIG_TIMEOUT_US: + pdev->tuning_parms.tp_mm_timeout_mz_us = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_TIMED_MM_CONFIG_TIMEOUT_US: + pdev->tuning_parms.tp_mm_timeout_timed_us = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_LITE_RANGE_CONFIG_TIMEOUT_US: + pdev->tuning_parms.tp_range_timeout_lite_us = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_RANGING_RANGE_CONFIG_TIMEOUT_US: + pdev->tuning_parms.tp_range_timeout_histo_us = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_MZ_RANGE_CONFIG_TIMEOUT_US: + pdev->tuning_parms.tp_range_timeout_mz_us = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_TIMED_RANGE_CONFIG_TIMEOUT_US: + pdev->tuning_parms.tp_range_timeout_timed_us = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_DYNXTALK_SMUDGE_MARGIN: + pdev->smudge_correct_config.smudge_margin = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_DYNXTALK_NOISE_MARGIN: + pdev->smudge_correct_config.noise_margin = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_DYNXTALK_XTALK_OFFSET_LIMIT: + pdev->smudge_correct_config.user_xtalk_offset_limit = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_DYNXTALK_XTALK_OFFSET_LIMIT_HI: + pdev->smudge_correct_config.user_xtalk_offset_limit_hi = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_DYNXTALK_SAMPLE_LIMIT: + pdev->smudge_correct_config.sample_limit = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_DYNXTALK_SINGLE_XTALK_DELTA: + pdev->smudge_correct_config.single_xtalk_delta = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_DYNXTALK_AVERAGED_XTALK_DELTA: + pdev->smudge_correct_config.averaged_xtalk_delta = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_DYNXTALK_CLIP_LIMIT: + pdev->smudge_correct_config.smudge_corr_clip_limit = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_DYNXTALK_SCALER_CALC_METHOD: + pdev->smudge_correct_config.scaler_calc_method = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_DYNXTALK_XGRADIENT_SCALER: + pdev->smudge_correct_config.x_gradient_scaler = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_DYNXTALK_YGRADIENT_SCALER: + pdev->smudge_correct_config.y_gradient_scaler = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_DYNXTALK_USER_SCALER_SET: + pdev->smudge_correct_config.user_scaler_set = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_DYNXTALK_SMUDGE_COR_SINGLE_APPLY: + pdev->smudge_correct_config.smudge_corr_single_apply = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_DYNXTALK_XTALK_AMB_THRESHOLD: + pdev->smudge_correct_config.smudge_corr_ambient_threshold = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_DYNXTALK_NODETECT_AMB_THRESHOLD_KCPS: + pdev->smudge_correct_config.nodetect_ambient_threshold = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_DYNXTALK_NODETECT_SAMPLE_LIMIT: + pdev->smudge_correct_config.nodetect_sample_limit = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_DYNXTALK_NODETECT_XTALK_OFFSET_KCPS: + pdev->smudge_correct_config.nodetect_xtalk_offset = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_DYNXTALK_NODETECT_MIN_RANGE_MM: + pdev->smudge_correct_config.nodetect_min_range_mm = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_LOWPOWERAUTO_VHV_LOOP_BOUND: + pdev->low_power_auto_data.vhv_loop_bound = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_LOWPOWERAUTO_MM_CONFIG_TIMEOUT_US: + pdev->tuning_parms.tp_mm_timeout_lpa_us = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_LOWPOWERAUTO_RANGE_CONFIG_TIMEOUT_US: + pdev->tuning_parms.tp_range_timeout_lpa_us = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_VERY_SHORT_DSS_RATE_MCPS: + pdev->tuning_parms.tp_dss_target_very_short_mcps = (uint16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_PHASECAL_PATCH_POWER: + pdev->tuning_parms.tp_phasecal_patch_power = (uint16_t) tuning_parm_value; + break; + case VL53LX_TUNINGPARM_HIST_MERGE: + pdev->tuning_parms.tp_hist_merge = (uint16_t) tuning_parm_value; + break; + case VL53LX_TUNINGPARM_RESET_MERGE_THRESHOLD: + pdev->tuning_parms.tp_reset_merge_threshold = (uint16_t) tuning_parm_value; + break; + case VL53LX_TUNINGPARM_HIST_MERGE_MAX_SIZE: + pdev->tuning_parms.tp_hist_merge_max_size = (uint16_t) tuning_parm_value; + break; + case VL53LX_TUNINGPARM_DYNXTALK_MAX_SMUDGE_FACTOR: + pdev->smudge_correct_config.max_smudge_factor = (uint32_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_ENABLE: + pdev->tuning_parms.tp_uwr_enable = (uint8_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_1_MIN: + pdev->tuning_parms.tp_uwr_med_z_1_min = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_1_MAX: + pdev->tuning_parms.tp_uwr_med_z_1_max = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_2_MIN: + pdev->tuning_parms.tp_uwr_med_z_2_min = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_2_MAX: + pdev->tuning_parms.tp_uwr_med_z_2_max = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_3_MIN: + pdev->tuning_parms.tp_uwr_med_z_3_min = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_3_MAX: + pdev->tuning_parms.tp_uwr_med_z_3_max = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_4_MIN: + pdev->tuning_parms.tp_uwr_med_z_4_min = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_4_MAX: + pdev->tuning_parms.tp_uwr_med_z_4_max = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_5_MIN: + pdev->tuning_parms.tp_uwr_med_z_5_min = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_5_MAX: + pdev->tuning_parms.tp_uwr_med_z_5_max = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_1_RANGEA: + pdev->tuning_parms.tp_uwr_med_corr_z_1_rangea = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_1_RANGEB: + pdev->tuning_parms.tp_uwr_med_corr_z_1_rangeb = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_2_RANGEA: + pdev->tuning_parms.tp_uwr_med_corr_z_2_rangea = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_2_RANGEB: + pdev->tuning_parms.tp_uwr_med_corr_z_2_rangeb = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_3_RANGEA: + pdev->tuning_parms.tp_uwr_med_corr_z_3_rangea = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_3_RANGEB: + pdev->tuning_parms.tp_uwr_med_corr_z_3_rangeb = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_4_RANGEA: + pdev->tuning_parms.tp_uwr_med_corr_z_4_rangea = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_4_RANGEB: + pdev->tuning_parms.tp_uwr_med_corr_z_4_rangeb = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_5_RANGEA: + pdev->tuning_parms.tp_uwr_med_corr_z_5_rangea = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_5_RANGEB: + pdev->tuning_parms.tp_uwr_med_corr_z_5_rangeb = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_LONG_ZONE_1_MIN: + pdev->tuning_parms.tp_uwr_lng_z_1_min = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_LONG_ZONE_1_MAX: + pdev->tuning_parms.tp_uwr_lng_z_1_max = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_LONG_ZONE_2_MIN: + pdev->tuning_parms.tp_uwr_lng_z_2_min = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_LONG_ZONE_2_MAX: + pdev->tuning_parms.tp_uwr_lng_z_2_max = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_LONG_ZONE_3_MIN: + pdev->tuning_parms.tp_uwr_lng_z_3_min = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_LONG_ZONE_3_MAX: + pdev->tuning_parms.tp_uwr_lng_z_3_max = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_LONG_ZONE_4_MIN: + pdev->tuning_parms.tp_uwr_lng_z_4_min = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_LONG_ZONE_4_MAX: + pdev->tuning_parms.tp_uwr_lng_z_4_max = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_LONG_ZONE_5_MIN: + pdev->tuning_parms.tp_uwr_lng_z_5_min = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_LONG_ZONE_5_MAX: + pdev->tuning_parms.tp_uwr_lng_z_5_max = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_1_RANGEA: + pdev->tuning_parms.tp_uwr_lng_corr_z_1_rangea = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_1_RANGEB: + pdev->tuning_parms.tp_uwr_lng_corr_z_1_rangeb = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_2_RANGEA: + pdev->tuning_parms.tp_uwr_lng_corr_z_2_rangea = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_2_RANGEB: + pdev->tuning_parms.tp_uwr_lng_corr_z_2_rangeb = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_3_RANGEA: + pdev->tuning_parms.tp_uwr_lng_corr_z_3_rangea = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_3_RANGEB: + pdev->tuning_parms.tp_uwr_lng_corr_z_3_rangeb = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_4_RANGEA: + pdev->tuning_parms.tp_uwr_lng_corr_z_4_rangea = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_4_RANGEB: + pdev->tuning_parms.tp_uwr_lng_corr_z_4_rangeb = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_5_RANGEA: + pdev->tuning_parms.tp_uwr_lng_corr_z_5_rangea = (int16_t)tuning_parm_value; + break; + case VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_5_RANGEB: + pdev->tuning_parms.tp_uwr_lng_corr_z_5_rangeb = (int16_t)tuning_parm_value; + break; + default: + status = VL53LX_ERROR_INVALID_PARAMS; + break; + } + return status; +} + +VL53LX_Error VL53LX_SetTuningParameter(VL53LX_DEV Dev, uint16_t TuningParameterId, int32_t TuningParameterValue) +{ + VL53LX_Error Status = VL53LX_ERROR_NONE; + + 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; + } + + return Status; +} + +static int stmvl53lx_set_tuning(struct stmvl53lx_data *data, int key, int value) +{ + int rc = 0; + + if (data->enable_sensor) { + vl53lx_errmsg("can't change tuning params while ranging\n"); + return -EBUSY; + } + + if (data->is_calibrating) { + vl53lx_errmsg("can't change tuning params while calibrating\n"); + return -EBUSY; + } + + if (key & ~0xffff) + return -EINVAL; + + vl53lx_dbgmsg("trying to set %d with key %d", value, key); + + rc = VL53LX_SetTuningParameter(&data->stdev, key, value); + if (rc) + rc = store_last_error(data, rc); + + return rc; +} + +static ssize_t stmvl53lx_store_tuning(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct stmvl53lx_data *data = dev_get_drvdata(dev); + int key; + int value; + int n; + int rc = 0; + + mutex_lock(&data->work_mutex); + + n = sscanf(buf, "%d %d", &key, &value); + if (n != 2) { + rc = -EINVAL; + goto error; + } + rc = stmvl53lx_set_tuning(data, key, value); + if (rc) + goto error; + + mutex_unlock(&data->work_mutex); + + return count; + +error: + mutex_unlock(&data->work_mutex); + return rc; +} + +static DEVICE_ATTR(tuning, 0220, NULL, stmvl53lx_store_tuning); + +VL53LX_Error VL53LX_GetTuningParameter(VL53LX_DEV Dev, uint16_t TuningParameterId, int32_t *pTuningParameterValue) +{ + VL53LX_Error Status = VL53LX_ERROR_NONE; + + 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; + } + + return Status; +} + +static int stmvl53lx_display_tuning_key(struct stmvl53lx_data *data, char *buf, int *pos, int key) +{ + int rc = 0; + int value = 0; + int sz; + + rc = VL53LX_GetTuningParameter(&data->stdev, key, &value); + if (rc) + return 0; + + sz = snprintf(&buf[*pos], PAGE_SIZE - *pos, "%d %d\n", key, value); + if (sz >= PAGE_SIZE - *pos) + return -ENOSPC; + + *pos += sz; + + return 0; +} + +static ssize_t stmvl53lx_show_tuning_status(struct device *dev, struct device_attribute *attr, char *buf) +{ + const int max_tuning_key = 65535; + struct stmvl53lx_data *data = dev_get_drvdata(dev); + int rc = 0; + int i; + int pos = 0; + + mutex_lock(&data->work_mutex); + + for (i = 0; i < max_tuning_key; ++i) { + rc = stmvl53lx_display_tuning_key(data, buf, &pos, i); + if (rc) + break; + } + + mutex_unlock(&data->work_mutex); + + return rc ? rc : pos; +} + +static DEVICE_ATTR(tuning_status, 0440, stmvl53lx_show_tuning_status, NULL); + +static int stmvl53lx_set_smudge_correction_mode(struct stmvl53lx_data *data, + int smudge_correction_mode) +{ + int rc = 0; + + if (data->enable_sensor) { + vl53lx_errmsg("can't change smudge corr mode while ranging\n"); + rc = -EBUSY; + } else { + switch (smudge_correction_mode) { + case VL53LX_SMUDGE_CORRECTION_NONE: + case VL53LX_SMUDGE_CORRECTION_CONTINUOUS: + case VL53LX_SMUDGE_CORRECTION_SINGLE: + case VL53LX_SMUDGE_CORRECTION_DEBUG: + data->smudge_correction_mode = smudge_correction_mode; + break; + default: + vl53lx_errmsg("invalid smudge correction mode %d\n", + smudge_correction_mode); + rc = -EINVAL; + break; + } + } + + return rc; +} + +IMPLEMENT_PARAMETER_INTEGER(smudge_correction_mode, "smudge correction mode") + +static DEVICE_ATTR(smudge_correction_mode, 0660, stmvl53lx_show_smudge_correction_mode, stmvl53lx_store_smudge_correction_mode); + +static ssize_t stmvl53lx_show_is_xtalk_value_changed_config(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct stmvl53lx_data *data = dev_get_drvdata(dev); + int param; + + mutex_lock(&data->work_mutex); + param = data->is_xtalk_value_changed; + mutex_unlock(&data->work_mutex); + + return scnprintf(buf, PAGE_SIZE, "%d\n", param); +} + +static DEVICE_ATTR(is_xtalk_value_changed, 0440, stmvl53lx_show_is_xtalk_value_changed_config, NULL); + +static struct attribute *stmvl53lx_attributes[] = { + &dev_attr_enable_ps_sensor.attr, + &dev_attr_set_delay_ms.attr, + &dev_attr_timing_budget.attr, + &dev_attr_roi.attr, + &dev_attr_do_flush.attr, + &dev_attr_distance_mode.attr, + &dev_attr_crosstalk_enable.attr, + &dev_attr_enable_debug.attr, + &dev_attr_force_device_on_enable.attr, + &dev_attr_last_error.attr, + &dev_attr_offset_correction_mode.attr, + &dev_attr_optical_center.attr, + &dev_attr_tuning.attr, + &dev_attr_tuning_status.attr, + &dev_attr_smudge_correction_mode.attr, + &dev_attr_is_xtalk_value_changed.attr, + NULL +}; + +static const struct attribute_group stmvl53lx_attr_group = { + .attrs = stmvl53lx_attributes, +}; + +static int ctrl_param_last_error(struct stmvl53lx_data *data, struct stmvl53lx_parameter *param) +{ + int rc = 0; + + if (param->is_read) { + param->value = data->last_error; + param->status = 0; + vl53lx_dbgmsg("get last error %d", param->value); + rc = 0; + } else { + rc = -EINVAL; + } + + return rc; +} + +static int ctrl_param_optical_center(struct stmvl53lx_data *data, struct stmvl53lx_parameter *param) +{ + if (!param->is_read) + return -EINVAL; + + param->value = data->optical_offset_x; + param->value2 = data->optical_offset_y; + + return 0; +} + +static int ctrl_param_tuning(struct stmvl53lx_data *data, struct stmvl53lx_parameter *param) +{ + if (param->is_read) + return -EINVAL; + + return stmvl53lx_set_tuning(data, param->value, param->value2); +} + +static int ctrl_param_is_xtalk_value_changed(struct stmvl53lx_data *data, struct stmvl53lx_parameter *param) +{ + if (!param->is_read) + return -EINVAL; + + param->value = data->is_xtalk_value_changed; + + return 0; +} + +static int ctrl_params(struct stmvl53lx_data *data, void __user *p) +{ + int rc, rc2; + struct stmvl53lx_parameter param; + + mutex_lock(&data->work_mutex); + + if (data->is_device_remove) { + rc = -ENODEV; + goto done; + } + rc = copy_from_user(¶m, p, sizeof(param)); + param.status = 0; + if (rc) { + rc = -EFAULT; + goto done; + } + switch (param.name) { + case VL53LX_POLLDELAY_PAR: + rc = ctrl_param_poll_delay_ms(data, ¶m); + break; + case VL53LX_TIMINGBUDGET_PAR: + rc = ctrl_param_timing_budget(data, ¶m); + break; + case VL53LX_DISTANCEMODE_PAR: + rc = ctrl_param_distance_mode(data, ¶m); + break; + case VL53LX_XTALKENABLE_PAR: + rc = ctrl_param_crosstalk_enable(data, ¶m); + break; + case VL53LX_FORCEDEVICEONEN_PAR: + rc = ctrl_param_force_device_on_en(data, ¶m); + break; + case VL53LX_LASTERROR_PAR: + rc = ctrl_param_last_error(data, ¶m); + break; + case VL53LX_OFFSETCORRECTIONMODE_PAR: + rc = ctrl_param_offset_correction_mode(data, ¶m); + break; + case VL53LX_OPTICALCENTER_PAR: + rc = ctrl_param_optical_center(data, ¶m); + break; + case VL53LX_TUNING_PAR: + rc = ctrl_param_tuning(data, ¶m); + break; + case VL53LX_SMUDGECORRECTIONMODE_PAR: + rc = ctrl_param_smudge_correction_mode(data, ¶m); + break; + case VL53LX_ISXTALKVALUECHANGED_PAR: + rc = ctrl_param_is_xtalk_value_changed(data, ¶m); + break; + default: + vl53lx_errmsg("unknown or unsupported %d\n", param.name); + rc = -EINVAL; + } + + if (param.is_read && rc == 0) { + rc2 = copy_to_user(p, ¶m, sizeof(param)); + if (rc2) { + rc = -EFAULT; + vl53lx_errmsg("copy to user fail %d\n", rc); + } + } +done: + mutex_unlock(&data->work_mutex); + return rc; +} + +VL53LX_Error VL53LX_set_part_to_part_data(VL53LX_DEV Dev, VL53LX_calibration_data_t *pcal_data) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + VL53LX_xtalk_config_t *pC = &(pdev->xtalk_cfg); + VL53LX_hist_post_process_config_t *pHP = &(pdev->histpostprocess); + VL53LX_customer_nvm_managed_t *pN = &(pdev->customer); + uint32_t tempu32; + + if (pcal_data->struct_version != VL53LX_LL_CALIBRATION_DATA_STRUCT_VERSION) { + status = VL53LX_ERROR_INVALID_PARAMS; + } + + if (status == VL53LX_ERROR_NONE) { + memcpy(&(pdev->customer), &(pcal_data->customer), sizeof(VL53LX_customer_nvm_managed_t)); + memcpy(&(pdev->add_off_cal_data), &(pcal_data->add_off_cal_data), sizeof(VL53LX_additional_offset_cal_data_t)); + memcpy(&(pdev->fmt_dmax_cal), &(pcal_data->fmt_dmax_cal), sizeof(VL53LX_dmax_calibration_data_t)); + memcpy(&(pdev->cust_dmax_cal), &(pcal_data->cust_dmax_cal), sizeof(VL53LX_dmax_calibration_data_t)); + memcpy(&(pdev->xtalk_shapes), &(pcal_data->xtalkhisto), sizeof(VL53LX_xtalk_histogram_data_t)); + memcpy(&(pdev->gain_cal), &(pcal_data->gain_cal), sizeof(VL53LX_gain_calibration_data_t)); + memcpy(&(pdev->cal_peak_rate_map), &(pcal_data->cal_peak_rate_map), sizeof(VL53LX_cal_peak_rate_map_t)); + memcpy(&(pdev->per_vcsel_cal_data), &(pcal_data->per_vcsel_cal_data), sizeof(VL53LX_per_vcsel_period_offset_cal_data_t)); + + pC->algo__crosstalk_compensation_plane_offset_kcps = pN->algo__crosstalk_compensation_plane_offset_kcps; + pC->algo__crosstalk_compensation_x_plane_gradient_kcps = pN->algo__crosstalk_compensation_x_plane_gradient_kcps; + pC->algo__crosstalk_compensation_y_plane_gradient_kcps = pN->algo__crosstalk_compensation_y_plane_gradient_kcps; + + pHP->algo__crosstalk_compensation_plane_offset_kcps = VL53LX_calc_crosstalk_plane_offset_with_margin(pC->algo__crosstalk_compensation_plane_offset_kcps, pC->histogram_mode_crosstalk_margin_kcps); + + pHP->algo__crosstalk_compensation_x_plane_gradient_kcps = pC->algo__crosstalk_compensation_x_plane_gradient_kcps; + pHP->algo__crosstalk_compensation_y_plane_gradient_kcps = pC->algo__crosstalk_compensation_y_plane_gradient_kcps; + + if (pC->global_crosstalk_compensation_enable == 0x00) { + pN->algo__crosstalk_compensation_plane_offset_kcps = 0x00; + pN->algo__crosstalk_compensation_x_plane_gradient_kcps = 0x00; + pN->algo__crosstalk_compensation_y_plane_gradient_kcps = 0x00; + } else { + tempu32 = VL53LX_calc_crosstalk_plane_offset_with_margin(pC->algo__crosstalk_compensation_plane_offset_kcps, pC->lite_mode_crosstalk_margin_kcps); + if (tempu32 > 0xFFFF) + tempu32 = 0xFFFF; + + pN->algo__crosstalk_compensation_plane_offset_kcps = (uint16_t)tempu32; + } + } + return status; +} + +VL53LX_Error VL53LX_get_current_xtalk_settings(VL53LX_DEV Dev, VL53LX_xtalk_calibration_results_t *pxtalk) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + uint8_t i; + + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + pxtalk->algo__crosstalk_compensation_plane_offset_kcps = pdev->xtalk_cfg.algo__crosstalk_compensation_plane_offset_kcps; + pxtalk->algo__crosstalk_compensation_x_plane_gradient_kcps = pdev->xtalk_cfg.algo__crosstalk_compensation_x_plane_gradient_kcps; + pxtalk->algo__crosstalk_compensation_y_plane_gradient_kcps = pdev->xtalk_cfg.algo__crosstalk_compensation_y_plane_gradient_kcps; + for (i = 0; i < VL53LX_BIN_REC_SIZE; i++) + pxtalk->algo__xtalk_cpo_HistoMerge_kcps[i] = pdev->xtalk_cal.algo__xtalk_cpo_HistoMerge_kcps[i]; + + return status; +} + +VL53LX_Error VL53LX_set_current_xtalk_settings(VL53LX_DEV Dev, VL53LX_xtalk_calibration_results_t *pxtalk) +{ + uint8_t i; + VL53LX_Error status = VL53LX_ERROR_NONE; + + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + pdev->xtalk_cfg.algo__crosstalk_compensation_plane_offset_kcps = pxtalk->algo__crosstalk_compensation_plane_offset_kcps; + pdev->xtalk_cfg.algo__crosstalk_compensation_x_plane_gradient_kcps = pxtalk->algo__crosstalk_compensation_x_plane_gradient_kcps; + pdev->xtalk_cfg.algo__crosstalk_compensation_y_plane_gradient_kcps = pxtalk->algo__crosstalk_compensation_y_plane_gradient_kcps; + for (i = 0; i < VL53LX_BIN_REC_SIZE; i++) + pdev->xtalk_cal.algo__xtalk_cpo_HistoMerge_kcps[i] = pxtalk->algo__xtalk_cpo_HistoMerge_kcps[i]; + + 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; + + 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: + return Status; + +} + +VL53LX_Error VL53LX_get_part_to_part_data(VL53LX_DEV Dev, VL53LX_calibration_data_t *pcal_data) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + VL53LX_xtalk_config_t *pC = &(pdev->xtalk_cfg); + VL53LX_customer_nvm_managed_t *pCN = &(pcal_data->customer); + + pcal_data->struct_version = VL53LX_LL_CALIBRATION_DATA_STRUCT_VERSION; + memcpy(&(pcal_data->customer), &(pdev->customer), sizeof(VL53LX_customer_nvm_managed_t)); + + if (pC->algo__crosstalk_compensation_plane_offset_kcps > 0xFFFF) { + pCN->algo__crosstalk_compensation_plane_offset_kcps = 0xFFFF; + } else { + pCN->algo__crosstalk_compensation_plane_offset_kcps = (uint16_t)pC->algo__crosstalk_compensation_plane_offset_kcps; + } + pCN->algo__crosstalk_compensation_x_plane_gradient_kcps = pC->algo__crosstalk_compensation_x_plane_gradient_kcps; + pCN->algo__crosstalk_compensation_y_plane_gradient_kcps = pC->algo__crosstalk_compensation_y_plane_gradient_kcps; + + memcpy(&(pcal_data->fmt_dmax_cal), &(pdev->fmt_dmax_cal), sizeof(VL53LX_dmax_calibration_data_t)); + memcpy(&(pcal_data->cust_dmax_cal), &(pdev->cust_dmax_cal), sizeof(VL53LX_dmax_calibration_data_t)); + memcpy(&(pcal_data->add_off_cal_data), &(pdev->add_off_cal_data), sizeof(VL53LX_additional_offset_cal_data_t)); + memcpy(&(pcal_data->optical_centre), &(pdev->optical_centre), sizeof(VL53LX_optical_centre_t)); + memcpy(&(pcal_data->xtalkhisto), &(pdev->xtalk_shapes), sizeof(VL53LX_xtalk_histogram_data_t)); + memcpy(&(pcal_data->gain_cal), &(pdev->gain_cal), sizeof(VL53LX_gain_calibration_data_t)); + memcpy(&(pcal_data->cal_peak_rate_map), &(pdev->cal_peak_rate_map), sizeof(VL53LX_cal_peak_rate_map_t)); + memcpy(&(pcal_data->per_vcsel_cal_data), &(pdev->per_vcsel_cal_data), sizeof(VL53LX_per_vcsel_period_offset_cal_data_t)); + + 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; + + 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: + return Status; +} + +static ssize_t stmvl53lx_calib_data_read(struct file *filp, struct kobject *kobj, const struct bin_attribute *attr, char *buf, loff_t off, size_t count) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct stmvl53lx_data *data = dev_get_drvdata(dev); + VL53LX_CalibrationData_t calib; + int rc = 0; + void *src = (void *) &calib; + + mutex_lock(&data->work_mutex); + + vl53lx_dbgmsg("off = %lld / count = %d", off, count); + + if (off < 0 || off > sizeof(VL53LX_CalibrationData_t)) + goto invalid; + + memset(&calib, 0, sizeof(calib)); + rc = VL53LX_GetCalibrationData(&data->stdev, &calib); + if (rc) { + vl53lx_errmsg("VL53LX_GetCalibrationData fail %d", rc); + rc = store_last_error(data, rc); + goto error; + } + + if (off + count > sizeof(VL53LX_CalibrationData_t)) + count = sizeof(VL53LX_CalibrationData_t) - off; + memcpy(buf, src + off, count); + + mutex_unlock(&data->work_mutex); + return count; + +invalid: + vl53lx_errmsg("invalid syntax"); + rc = -EINVAL; + goto error; + +error: + mutex_unlock(&data->work_mutex); + return rc; +} + +static ssize_t stmvl53lx_calib_data_write(struct file *filp, struct kobject *kobj, const struct bin_attribute *attr, char *buf, loff_t off, size_t count) +{ + int rc = 0; + struct device *dev = container_of(kobj, struct device, kobj); + struct stmvl53lx_data *data = dev_get_drvdata(dev); + + mutex_lock(&data->work_mutex); + + vl53lx_dbgmsg("off = %lld / count = %d", off, count); + + if (data->enable_sensor) { + rc = -EBUSY; + vl53lx_errmsg("can't set calib data while ranging\n"); + goto error; + } + + if (off != 0 || count != sizeof(VL53LX_CalibrationData_t)) + goto invalid; + + rc = VL53LX_SetCalibrationData(&data->stdev, (VL53LX_CalibrationData_t *) buf); + if (rc) { + vl53lx_errmsg("VL53LX_SetCalibrationData fail %d", rc); + rc = store_last_error(data, rc); + goto error; + } + + mutex_unlock(&data->work_mutex); + return count; + +invalid: + vl53lx_errmsg("invalid syntax"); + rc = -EINVAL; + goto error; + +error: + mutex_unlock(&data->work_mutex); + + return rc; +} + +static struct bin_attribute stmvl53lx_calib_data_attr = { + .attr = { + .name = "calibration_data", + .mode = 0660, + }, + .size = sizeof(VL53LX_CalibrationData_t), + .read = stmvl53lx_calib_data_read, + .write = stmvl53lx_calib_data_write, +}; + +void VL53LX_init_version(VL53LX_DEV Dev) +{ + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + pdev->version.ll_major = VL53LX_LL_API_IMPLEMENTATION_VER_MAJOR; + pdev->version.ll_minor = VL53LX_LL_API_IMPLEMENTATION_VER_MINOR; + pdev->version.ll_build = VL53LX_LL_API_IMPLEMENTATION_VER_SUB; + pdev->version.ll_revision = VL53LX_LL_API_IMPLEMENTATION_VER_REVISION; +} + +VL53LX_Error VL53LX_get_static_nvm_managed(VL53LX_DEV Dev, VL53LX_static_nvm_managed_t *pdata) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + uint8_t comms_buffer[VL53LX_STATIC_NVM_MANAGED_I2C_SIZE_BYTES]; + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_ReadMulti(Dev, VL53LX_I2C_SLAVE__DEVICE_ADDRESS, comms_buffer, VL53LX_STATIC_NVM_MANAGED_I2C_SIZE_BYTES); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_i2c_decode_static_nvm_managed(VL53LX_STATIC_NVM_MANAGED_I2C_SIZE_BYTES, comms_buffer, pdata); + + return status; +} + +VL53LX_Error VL53LX_i2c_decode_customer_nvm_managed(uint16_t buf_size, uint8_t *pbuffer, VL53LX_customer_nvm_managed_t *pdata) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + if (buf_size < VL53LX_CUSTOMER_NVM_MANAGED_I2C_SIZE_BYTES) + return VL53LX_ERROR_COMMS_BUFFER_TOO_SMALL; + + pdata->global_config__spad_enables_ref_0 = (*(pbuffer + 0)); + pdata->global_config__spad_enables_ref_1 = (*(pbuffer + 1)); + pdata->global_config__spad_enables_ref_2 = (*(pbuffer + 2)); + pdata->global_config__spad_enables_ref_3 = (*(pbuffer + 3)); + pdata->global_config__spad_enables_ref_4 = (*(pbuffer + 4)); + pdata->global_config__spad_enables_ref_5 = (*(pbuffer + 5)) & 0xF; + pdata->global_config__ref_en_start_select = (*(pbuffer + 6)); + pdata->ref_spad_man__num_requested_ref_spads = (*(pbuffer + 7)) & 0x3F; + pdata->ref_spad_man__ref_location = (*(pbuffer + 8)) & 0x3; + pdata->algo__crosstalk_compensation_plane_offset_kcps = (VL53LX_i2c_decode_uint16_t(2, pbuffer + 9)); + pdata->algo__crosstalk_compensation_x_plane_gradient_kcps = (VL53LX_i2c_decode_int16_t(2, pbuffer + 11)); + pdata->algo__crosstalk_compensation_y_plane_gradient_kcps = (VL53LX_i2c_decode_int16_t(2, pbuffer + 13)); + pdata->ref_spad_char__total_rate_target_mcps = (VL53LX_i2c_decode_uint16_t(2, pbuffer + 15)); + pdata->algo__part_to_part_range_offset_mm = (VL53LX_i2c_decode_int16_t(2, pbuffer + 17)) & 0x1FFF; + pdata->mm_config__inner_offset_mm = (VL53LX_i2c_decode_int16_t(2, pbuffer + 19)); + pdata->mm_config__outer_offset_mm = (VL53LX_i2c_decode_int16_t(2, pbuffer + 21)); + + return status; +} + +VL53LX_Error VL53LX_get_customer_nvm_managed(VL53LX_DEV Dev, VL53LX_customer_nvm_managed_t *pdata) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + uint8_t comms_buffer[VL53LX_CUSTOMER_NVM_MANAGED_I2C_SIZE_BYTES]; + int16_t offset; + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_ReadMulti(Dev, VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_REF_0, comms_buffer, VL53LX_CUSTOMER_NVM_MANAGED_I2C_SIZE_BYTES); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_i2c_decode_customer_nvm_managed(VL53LX_CUSTOMER_NVM_MANAGED_I2C_SIZE_BYTES, comms_buffer, pdata); + + if (status == VL53LX_ERROR_NONE) { + offset = pdata->algo__part_to_part_range_offset_mm; + offset = offset / 4; + if (offset >= 1024) + offset -= 2048; + pdata->algo__part_to_part_range_offset_mm = 0; + pdata->mm_config__inner_offset_mm = offset; + pdata->mm_config__outer_offset_mm = offset; + } + + return status; +} + +VL53LX_Error VL53LX_i2c_decode_nvm_copy_data(uint16_t buf_size, uint8_t *pbuffer, VL53LX_nvm_copy_data_t *pdata) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + if (buf_size < VL53LX_NVM_COPY_DATA_I2C_SIZE_BYTES) + return VL53LX_ERROR_COMMS_BUFFER_TOO_SMALL; + + pdata->identification__model_id = (*(pbuffer + 0)); + pdata->identification__module_type = (*(pbuffer + 1)); + pdata->identification__revision_id = (*(pbuffer + 2)); + pdata->identification__module_id = (VL53LX_i2c_decode_uint16_t(2, pbuffer + 3)); + pdata->ana_config__fast_osc__trim_max = (*(pbuffer + 5)) & 0x7F; + pdata->ana_config__fast_osc__freq_set = (*(pbuffer + 6)) & 0x7; + pdata->ana_config__vcsel_trim = (*(pbuffer + 7)) & 0x7; + pdata->ana_config__vcsel_selion = (*(pbuffer + 8)) & 0x3F; + pdata->ana_config__vcsel_selion_max = (*(pbuffer + 9)) & 0x3F; + pdata->protected_laser_safety__lock_bit = (*(pbuffer + 10)) & 0x1; + pdata->laser_safety__key = (*(pbuffer + 11)) & 0x7F; + pdata->laser_safety__key_ro = (*(pbuffer + 12)) & 0x1; + pdata->laser_safety__clip = (*(pbuffer + 13)) & 0x3F; + pdata->laser_safety__mult = (*(pbuffer + 14)) & 0x3F; + pdata->global_config__spad_enables_rtn_0 = (*(pbuffer + 15)); + pdata->global_config__spad_enables_rtn_1 = (*(pbuffer + 16)); + pdata->global_config__spad_enables_rtn_2 = (*(pbuffer + 17)); + pdata->global_config__spad_enables_rtn_3 = (*(pbuffer + 18)); + pdata->global_config__spad_enables_rtn_4 = (*(pbuffer + 19)); + pdata->global_config__spad_enables_rtn_5 = (*(pbuffer + 20)); + pdata->global_config__spad_enables_rtn_6 = (*(pbuffer + 21)); + pdata->global_config__spad_enables_rtn_7 = (*(pbuffer + 22)); + pdata->global_config__spad_enables_rtn_8 = (*(pbuffer + 23)); + pdata->global_config__spad_enables_rtn_9 = (*(pbuffer + 24)); + pdata->global_config__spad_enables_rtn_10 = (*(pbuffer + 25)); + pdata->global_config__spad_enables_rtn_11 = (*(pbuffer + 26)); + pdata->global_config__spad_enables_rtn_12 = (*(pbuffer + 27)); + pdata->global_config__spad_enables_rtn_13 = (*(pbuffer + 28)); + pdata->global_config__spad_enables_rtn_14 = (*(pbuffer + 29)); + pdata->global_config__spad_enables_rtn_15 = (*(pbuffer + 30)); + pdata->global_config__spad_enables_rtn_16 = (*(pbuffer + 31)); + pdata->global_config__spad_enables_rtn_17 = (*(pbuffer + 32)); + pdata->global_config__spad_enables_rtn_18 = (*(pbuffer + 33)); + pdata->global_config__spad_enables_rtn_19 = (*(pbuffer + 34)); + pdata->global_config__spad_enables_rtn_20 = (*(pbuffer + 35)); + pdata->global_config__spad_enables_rtn_21 = (*(pbuffer + 36)); + pdata->global_config__spad_enables_rtn_22 = (*(pbuffer + 37)); + pdata->global_config__spad_enables_rtn_23 = (*(pbuffer + 38)); + pdata->global_config__spad_enables_rtn_24 = (*(pbuffer + 39)); + pdata->global_config__spad_enables_rtn_25 = (*(pbuffer + 40)); + pdata->global_config__spad_enables_rtn_26 = (*(pbuffer + 41)); + pdata->global_config__spad_enables_rtn_27 = (*(pbuffer + 42)); + pdata->global_config__spad_enables_rtn_28 = (*(pbuffer + 43)); + pdata->global_config__spad_enables_rtn_29 = (*(pbuffer + 44)); + pdata->global_config__spad_enables_rtn_30 = (*(pbuffer + 45)); + pdata->global_config__spad_enables_rtn_31 = (*(pbuffer + 46)); + pdata->roi_config__mode_roi_centre_spad = (*(pbuffer + 47)); + pdata->roi_config__mode_roi_xy_size = (*(pbuffer + 48)); + + return status; +} + +VL53LX_Error VL53LX_get_nvm_copy_data(VL53LX_DEV Dev, VL53LX_nvm_copy_data_t *pdata) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + uint8_t comms_buffer[VL53LX_NVM_COPY_DATA_I2C_SIZE_BYTES]; + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_ReadMulti(Dev, VL53LX_IDENTIFICATION__MODEL_ID, comms_buffer, VL53LX_NVM_COPY_DATA_I2C_SIZE_BYTES); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_i2c_decode_nvm_copy_data(VL53LX_NVM_COPY_DATA_I2C_SIZE_BYTES, comms_buffer, pdata); + + return status; +} + +void VL53LX_copy_rtn_good_spads_to_buffer(VL53LX_nvm_copy_data_t *pdata, uint8_t *pbuffer) +{ + *(pbuffer + 0) = pdata->global_config__spad_enables_rtn_0; + *(pbuffer + 1) = pdata->global_config__spad_enables_rtn_1; + *(pbuffer + 2) = pdata->global_config__spad_enables_rtn_2; + *(pbuffer + 3) = pdata->global_config__spad_enables_rtn_3; + *(pbuffer + 4) = pdata->global_config__spad_enables_rtn_4; + *(pbuffer + 5) = pdata->global_config__spad_enables_rtn_5; + *(pbuffer + 6) = pdata->global_config__spad_enables_rtn_6; + *(pbuffer + 7) = pdata->global_config__spad_enables_rtn_7; + *(pbuffer + 8) = pdata->global_config__spad_enables_rtn_8; + *(pbuffer + 9) = pdata->global_config__spad_enables_rtn_9; + *(pbuffer + 10) = pdata->global_config__spad_enables_rtn_10; + *(pbuffer + 11) = pdata->global_config__spad_enables_rtn_11; + *(pbuffer + 12) = pdata->global_config__spad_enables_rtn_12; + *(pbuffer + 13) = pdata->global_config__spad_enables_rtn_13; + *(pbuffer + 14) = pdata->global_config__spad_enables_rtn_14; + *(pbuffer + 15) = pdata->global_config__spad_enables_rtn_15; + *(pbuffer + 16) = pdata->global_config__spad_enables_rtn_16; + *(pbuffer + 17) = pdata->global_config__spad_enables_rtn_17; + *(pbuffer + 18) = pdata->global_config__spad_enables_rtn_18; + *(pbuffer + 19) = pdata->global_config__spad_enables_rtn_19; + *(pbuffer + 20) = pdata->global_config__spad_enables_rtn_20; + *(pbuffer + 21) = pdata->global_config__spad_enables_rtn_21; + *(pbuffer + 22) = pdata->global_config__spad_enables_rtn_22; + *(pbuffer + 23) = pdata->global_config__spad_enables_rtn_23; + *(pbuffer + 24) = pdata->global_config__spad_enables_rtn_24; + *(pbuffer + 25) = pdata->global_config__spad_enables_rtn_25; + *(pbuffer + 26) = pdata->global_config__spad_enables_rtn_26; + *(pbuffer + 27) = pdata->global_config__spad_enables_rtn_27; + *(pbuffer + 28) = pdata->global_config__spad_enables_rtn_28; + *(pbuffer + 29) = pdata->global_config__spad_enables_rtn_29; + *(pbuffer + 30) = pdata->global_config__spad_enables_rtn_30; + *(pbuffer + 31) = pdata->global_config__spad_enables_rtn_31; +} + +VL53LX_Error VL53LX_set_firmware_enable_register(VL53LX_DEV Dev, uint8_t value) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + pdev->sys_ctrl.firmware__enable = value; + + status = VL53LX_WrByte(Dev, VL53LX_FIRMWARE__ENABLE, pdev->sys_ctrl.firmware__enable); + + return status; +} + +VL53LX_Error VL53LX_disable_firmware(VL53LX_DEV Dev) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + status = VL53LX_set_firmware_enable_register(Dev, 0x00); + + return status; +} + +VL53LX_Error VL53LX_nvm_enable(VL53LX_DEV Dev, uint16_t nvm_ctrl_pulse_width, int32_t nvm_power_up_delay_us) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_disable_firmware(Dev); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_enable_powerforce(Dev); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_WaitUs(Dev, VL53LX_ENABLE_POWERFORCE_SETTLING_TIME_US); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_WrByte(Dev, VL53LX_RANGING_CORE__NVM_CTRL__PDN, 0x01); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_WrByte(Dev, VL53LX_RANGING_CORE__CLK_CTRL1, 0x05); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_WaitUs(Dev, nvm_power_up_delay_us); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_WrByte(Dev, VL53LX_RANGING_CORE__NVM_CTRL__MODE, 0x01); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_WrWord(Dev, VL53LX_RANGING_CORE__NVM_CTRL__PULSE_WIDTH_MSB, nvm_ctrl_pulse_width); + + return status; +} + + +VL53LX_Error VL53LX_nvm_read(VL53LX_DEV Dev, uint8_t start_address, uint8_t count, uint8_t *pdata) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + uint8_t nvm_addr = 0; + + for (nvm_addr = start_address; + nvm_addr < (start_address+count) ; nvm_addr++) { + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_WrByte(Dev, VL53LX_RANGING_CORE__NVM_CTRL__ADDR, nvm_addr); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_WrByte(Dev, VL53LX_RANGING_CORE__NVM_CTRL__READN, 0x00); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_WaitUs(Dev, VL53LX_NVM_READ_TRIGGER_DELAY_US); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_WrByte(Dev, VL53LX_RANGING_CORE__NVM_CTRL__READN, 0x01); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_ReadMulti(Dev, VL53LX_RANGING_CORE__NVM_CTRL__DATAOUT_MMM, pdata, 4); + + pdata = pdata + 4; + } + return status; +} + +VL53LX_Error VL53LX_enable_firmware(VL53LX_DEV Dev) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + status = VL53LX_set_firmware_enable_register(Dev, 0x01); + + return status; +} + +VL53LX_Error VL53LX_nvm_disable(VL53LX_DEV Dev) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_WrByte(Dev, VL53LX_RANGING_CORE__NVM_CTRL__READN, 0x01); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_WrByte(Dev, VL53LX_RANGING_CORE__NVM_CTRL__PDN, 0x00); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_disable_powerforce(Dev); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_enable_firmware(Dev); + + return status; +} + +VL53LX_Error VL53LX_read_nvm_raw_data(VL53LX_DEV Dev, uint8_t start_address, uint8_t count, uint8_t *pnvm_raw_data) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_nvm_enable(Dev, 0x0004, VL53LX_NVM_POWER_UP_DELAY_US); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_nvm_read(Dev, start_address, count, pnvm_raw_data); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_nvm_disable(Dev); + + return status; +} + +VL53LX_Error VL53LX_nvm_decode_optical_centre(uint16_t buf_size, uint8_t *pbuffer, VL53LX_optical_centre_t *pdata) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + uint16_t tmp = 0; + + if (buf_size < VL53LX_NVM__FMT__OPTICAL_CENTRE_DATA_SIZE) + return VL53LX_ERROR_BUFFER_TOO_SMALL; + + tmp = 0x0100; + tmp -= (uint16_t)*(pbuffer + 2); + if (tmp > 0x0FF) + tmp = 0; + + pdata->x_centre = (uint8_t)tmp; + pdata->y_centre = *(pbuffer + 3); + + return status; +} + +VL53LX_Error VL53LX_read_nvm_optical_centre(VL53LX_DEV Dev, VL53LX_optical_centre_t *pcentre) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + uint8_t nvm_data[VL53LX_NVM__FMT__OPTICAL_CENTRE_DATA_SIZE]; + + status = VL53LX_read_nvm_raw_data(Dev, (uint8_t)(VL53LX_NVM__FMT__OPTICAL_CENTRE_DATA_INDEX >> 2), (uint8_t)(VL53LX_NVM__FMT__OPTICAL_CENTRE_DATA_SIZE >> 2), nvm_data); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_nvm_decode_optical_centre(VL53LX_NVM__FMT__OPTICAL_CENTRE_DATA_SIZE, nvm_data, pcentre); + + return status; +} + +VL53LX_Error VL53LX_nvm_decode_cal_peak_rate_map(uint16_t buf_size, uint8_t *pbuffer, VL53LX_cal_peak_rate_map_t *pdata) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + uint8_t *ptmp = NULL; + uint8_t i = 0; + + if (buf_size < VL53LX_NVM__FMT__CAL_PEAK_RATE_MAP_DATA_SIZE) + return VL53LX_ERROR_BUFFER_TOO_SMALL; + + pdata->cal_distance_mm = (uint16_t)VL53LX_i2c_decode_uint16_t(2, pbuffer); + + pdata->cal_reflectance_pc = (uint16_t)VL53LX_i2c_decode_uint16_t(2, pbuffer + 2); + pdata->cal_reflectance_pc = pdata->cal_reflectance_pc >> 6; + + pdata->max_samples = VL53LX_NVM_PEAK_RATE_MAP_SAMPLES; + pdata->width = VL53LX_NVM_PEAK_RATE_MAP_WIDTH; + pdata->height = VL53LX_NVM_PEAK_RATE_MAP_HEIGHT; + + ptmp = pbuffer + 4; + for (i = 0 ; i < VL53LX_NVM_PEAK_RATE_MAP_SAMPLES ; i++) { + pdata->peak_rate_mcps[i] = (uint16_t)VL53LX_i2c_decode_uint16_t(2, ptmp); + ptmp += 2; + } + + return status; +} + +VL53LX_Error VL53LX_read_nvm_cal_peak_rate_map(VL53LX_DEV Dev, VL53LX_cal_peak_rate_map_t *pcal_data) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + uint8_t nvm_data[VL53LX_NVM__FMT__CAL_PEAK_RATE_MAP_DATA_SIZE]; + + status = VL53LX_read_nvm_raw_data(Dev, (uint8_t)(VL53LX_NVM__FMT__CAL_PEAK_RATE_MAP_DATA_INDEX >> 2), (uint8_t)(VL53LX_NVM__FMT__CAL_PEAK_RATE_MAP_DATA_SIZE >> 2), nvm_data); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_nvm_decode_cal_peak_rate_map(VL53LX_NVM__FMT__CAL_PEAK_RATE_MAP_DATA_SIZE, nvm_data, pcal_data); + + return status; +} + +VL53LX_Error VL53LX_nvm_decode_additional_offset_cal_data(uint16_t buf_size, uint8_t *pbuffer, VL53LX_additional_offset_cal_data_t *pdata) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + if (buf_size < VL53LX_NVM__FMT__ADDITIONAL_OFFSET_CAL_DATA_SIZE) + return VL53LX_ERROR_BUFFER_TOO_SMALL; + + pdata->result__mm_inner_actual_effective_spads = (uint16_t)VL53LX_i2c_decode_uint16_t(2, pbuffer); + pdata->result__mm_outer_actual_effective_spads = (uint16_t)VL53LX_i2c_decode_uint16_t(2, pbuffer + 2); + pdata->result__mm_inner_peak_signal_count_rtn_mcps = (uint16_t)VL53LX_i2c_decode_uint16_t(2, pbuffer + 4); + pdata->result__mm_outer_peak_signal_count_rtn_mcps = (uint16_t)VL53LX_i2c_decode_uint16_t(2, pbuffer + 6); + + return status; +} + +VL53LX_Error VL53LX_read_nvm_additional_offset_cal_data(VL53LX_DEV Dev, VL53LX_additional_offset_cal_data_t *pcal_data) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + uint8_t nvm_data[VL53LX_NVM__FMT__ADDITIONAL_OFFSET_CAL_DATA_SIZE]; + + status = VL53LX_read_nvm_raw_data(Dev, (uint8_t)(VL53LX_NVM__FMT__ADDITIONAL_OFFSET_CAL_DATA_INDEX >> 2), (uint8_t)(VL53LX_NVM__FMT__ADDITIONAL_OFFSET_CAL_DATA_SIZE >> 2), nvm_data); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_nvm_decode_additional_offset_cal_data(VL53LX_NVM__FMT__ADDITIONAL_OFFSET_CAL_DATA_SIZE, nvm_data, pcal_data); + + return status; +} + +void VL53LX_spad_number_to_byte_bit_index(uint8_t spad_number, uint8_t *pbyte_index, uint8_t *pbit_index, uint8_t *pbit_mask) +{ + *pbyte_index = spad_number >> 3; + *pbit_index = spad_number & 0x07; + *pbit_mask = 0x01 << *pbit_index; +} + +uint8_t VL53LX_is_aperture_location(uint8_t row, uint8_t col) +{ + uint8_t is_aperture = 0; + uint8_t mod_row = row % 4; + uint8_t mod_col = col % 4; + + if (mod_row == 0 && mod_col == 2) + is_aperture = 1; + + if (mod_row == 2 && mod_col == 0) + is_aperture = 1; + + return is_aperture; +} + +void VL53LX_decode_row_col(uint8_t spad_number, uint8_t *prow, uint8_t *pcol) +{ + if (spad_number > 127) { + *prow = 8 + ((255-spad_number) & 0x07); + *pcol = (spad_number-128) >> 3; + } else { + *prow = spad_number & 0x07; + *pcol = (127-spad_number) >> 3; + } +} + +void VL53LX_decode_zone_size(uint8_t encoded_xy_size, uint8_t *pwidth, uint8_t *pheight) +{ + *pheight = encoded_xy_size >> 4; + *pwidth = encoded_xy_size & 0x0F; +} + +void VL53LX_decode_zone_limits(uint8_t encoded_xy_centre, uint8_t encoded_xy_size, int16_t *px_ll, int16_t *py_ll, int16_t *px_ur, int16_t *py_ur) +{ + uint8_t x_centre = 0; + uint8_t y_centre = 0; + uint8_t width = 0; + uint8_t height = 0; + + VL53LX_decode_row_col(encoded_xy_centre, &y_centre, &x_centre); + VL53LX_decode_zone_size(encoded_xy_size, &width, &height); + + *px_ll = (int16_t)x_centre - ((int16_t)width + 1) / 2; + if (*px_ll < 0) + *px_ll = 0; + + *px_ur = *px_ll + (int16_t)width; + if (*px_ur > (VL53LX_SPAD_ARRAY_WIDTH-1)) + *px_ur = VL53LX_SPAD_ARRAY_WIDTH-1; + + *py_ll = (int16_t)y_centre - ((int16_t)height + 1) / 2; + if (*py_ll < 0) + *py_ll = 0; + + *py_ur = *py_ll + (int16_t)height; + if (*py_ur > (VL53LX_SPAD_ARRAY_HEIGHT-1)) + *py_ur = VL53LX_SPAD_ARRAY_HEIGHT-1; +} + +void VL53LX_calc_mm_effective_spads( + uint8_t encoded_mm_roi_centre, + uint8_t encoded_mm_roi_size, + uint8_t encoded_zone_centre, + uint8_t encoded_zone_size, + uint8_t *pgood_spads, + uint16_t aperture_attenuation, + uint16_t *pmm_inner_effective_spads, + uint16_t *pmm_outer_effective_spads) +{ + int16_t x = 0; + int16_t y = 0; + int16_t mm_x_ll = 0; + int16_t mm_y_ll = 0; + int16_t mm_x_ur = 0; + int16_t mm_y_ur = 0; + int16_t zone_x_ll = 0; + int16_t zone_y_ll = 0; + int16_t zone_x_ur = 0; + int16_t zone_y_ur = 0; + uint8_t spad_number = 0; + uint8_t byte_index = 0; + uint8_t bit_index = 0; + uint8_t bit_mask = 0; + + uint8_t is_aperture = 0; + uint16_t spad_attenuation = 0; + + VL53LX_decode_zone_limits(encoded_mm_roi_centre, encoded_mm_roi_size, &mm_x_ll, &mm_y_ll, &mm_x_ur, &mm_y_ur); + VL53LX_decode_zone_limits(encoded_zone_centre, encoded_zone_size, &zone_x_ll, &zone_y_ll, &zone_x_ur, &zone_y_ur); + + *pmm_inner_effective_spads = 0; + *pmm_outer_effective_spads = 0; + + for (y = zone_y_ll; y <= zone_y_ur; y++) { + for (x = zone_x_ll; x <= zone_x_ur; x++) { + VL53LX_encode_row_col((uint8_t)y, (uint8_t)x, &spad_number); + VL53LX_spad_number_to_byte_bit_index(spad_number, &byte_index, &bit_index, &bit_mask); + if ((pgood_spads[byte_index] & bit_mask) > 0) { + is_aperture = VL53LX_is_aperture_location((uint8_t)y, (uint8_t)x); + if (is_aperture > 0) + spad_attenuation = aperture_attenuation; + else + spad_attenuation = 0x0100; + if (x >= mm_x_ll && x <= mm_x_ur && y >= mm_y_ll && y <= mm_y_ur) + *pmm_inner_effective_spads += spad_attenuation; + else + *pmm_outer_effective_spads += spad_attenuation; + } + } + } +} + +VL53LX_Error VL53LX_nvm_decode_fmt_range_results_data(uint16_t buf_size, uint8_t *pbuffer, VL53LX_decoded_nvm_fmt_range_data_t *pdata) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + if (buf_size < VL53LX_NVM__FMT__RANGE_RESULTS__SIZE_BYTES) + return VL53LX_ERROR_BUFFER_TOO_SMALL; + + pdata->result__actual_effective_rtn_spads = (uint16_t)VL53LX_i2c_decode_uint16_t(2, pbuffer); + pdata->ref_spad_array__num_requested_ref_spads = *(pbuffer+2); + pdata->ref_spad_array__ref_location = *(pbuffer+3); + pdata->result__peak_signal_count_rate_rtn_mcps = (uint16_t)VL53LX_i2c_decode_uint16_t(2, pbuffer + 4); + pdata->result__ambient_count_rate_rtn_mcps = (uint16_t)VL53LX_i2c_decode_uint16_t(2, pbuffer + 6); + pdata->result__peak_signal_count_rate_ref_mcps = (uint16_t)VL53LX_i2c_decode_uint16_t(2, pbuffer + 8); + pdata->result__ambient_count_rate_ref_mcps = (uint16_t)VL53LX_i2c_decode_uint16_t(2, pbuffer + 10); + pdata->measured_distance_mm = (uint16_t)VL53LX_i2c_decode_uint16_t(2, pbuffer + 12); + pdata->measured_distance_stdev_mm = (uint16_t)VL53LX_i2c_decode_uint16_t(2, pbuffer + 14); + + return status; +} + +VL53LX_Error VL53LX_read_nvm_fmt_range_results_data(VL53LX_DEV Dev, uint16_t range_results_select, VL53LX_decoded_nvm_fmt_range_data_t *prange_data) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + uint8_t nvm_data[VL53LX_NVM__FMT__RANGE_RESULTS__SIZE_BYTES]; + + status = VL53LX_read_nvm_raw_data(Dev, (uint8_t)(range_results_select >> 2), (uint8_t)(VL53LX_NVM__FMT__RANGE_RESULTS__SIZE_BYTES >> 2), +nvm_data); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_nvm_decode_fmt_range_results_data(VL53LX_NVM__FMT__RANGE_RESULTS__SIZE_BYTES, nvm_data, prange_data); + + return status; +} + +VL53LX_Error VL53LX_get_mode_mitigation_roi(VL53LX_DEV Dev, VL53LX_user_zone_t *pmm_roi) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + uint8_t x = 0; + uint8_t y = 0; + uint8_t xy_size = 0; + + VL53LX_decode_row_col(pdev->nvm_copy_data.roi_config__mode_roi_centre_spad, &y, &x); + + pmm_roi->x_centre = x; + pmm_roi->y_centre = y; + + xy_size = pdev->nvm_copy_data.roi_config__mode_roi_xy_size; + + pmm_roi->height = xy_size >> 4; + pmm_roi->width = xy_size & 0x0F; + + return status; +} + +VL53LX_Error VL53LX_read_p2p_data(VL53LX_DEV Dev) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + VL53LX_hist_post_process_config_t *pHP = &(pdev->histpostprocess); + VL53LX_customer_nvm_managed_t *pN = &(pdev->customer); + VL53LX_additional_offset_cal_data_t *pCD = &(pdev->add_off_cal_data); + VL53LX_decoded_nvm_fmt_range_data_t fmt_rrd; + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_get_static_nvm_managed(Dev, &(pdev->stat_nvm)); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_get_customer_nvm_managed(Dev, &(pdev->customer)); + + if (status == VL53LX_ERROR_NONE) { + status = VL53LX_get_nvm_copy_data(Dev, &(pdev->nvm_copy_data)); + + if (status == VL53LX_ERROR_NONE) + VL53LX_copy_rtn_good_spads_to_buffer(&(pdev->nvm_copy_data), &(pdev->rtn_good_spads[0])); + } + + if (status == VL53LX_ERROR_NONE) { + pHP->algo__crosstalk_compensation_plane_offset_kcps = + pN->algo__crosstalk_compensation_plane_offset_kcps; + pHP->algo__crosstalk_compensation_x_plane_gradient_kcps = + pN->algo__crosstalk_compensation_x_plane_gradient_kcps; + pHP->algo__crosstalk_compensation_y_plane_gradient_kcps = + pN->algo__crosstalk_compensation_y_plane_gradient_kcps; + } + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_read_nvm_optical_centre(Dev, &(pdev->optical_centre)); + + + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_read_nvm_cal_peak_rate_map(Dev, &(pdev->cal_peak_rate_map)); + + if (status == VL53LX_ERROR_NONE) { + status = VL53LX_read_nvm_additional_offset_cal_data(Dev, &(pdev->add_off_cal_data)); + + if (pCD->result__mm_inner_peak_signal_count_rtn_mcps == 0 && pCD->result__mm_outer_peak_signal_count_rtn_mcps == 0) { + pCD->result__mm_inner_peak_signal_count_rtn_mcps = 0x0080; + pCD->result__mm_outer_peak_signal_count_rtn_mcps = 0x0180; + + VL53LX_calc_mm_effective_spads(pdev->nvm_copy_data.roi_config__mode_roi_centre_spad, pdev->nvm_copy_data.roi_config__mode_roi_xy_size, 0xC7, 0xFF, &(pdev->rtn_good_spads[0]), VL53LX_RTN_SPAD_APERTURE_TRANSMISSION, &(pCD->result__mm_inner_actual_effective_spads), &(pCD->result__mm_outer_actual_effective_spads)); + } + } + + if (status == VL53LX_ERROR_NONE) { + + status = VL53LX_read_nvm_fmt_range_results_data(Dev, VL53LX_NVM__FMT__RANGE_RESULTS__140MM_DARK, &fmt_rrd); + if (status == VL53LX_ERROR_NONE) { + pdev->fmt_dmax_cal.ref__actual_effective_spads = fmt_rrd.result__actual_effective_rtn_spads; + pdev->fmt_dmax_cal.ref__peak_signal_count_rate_mcps = fmt_rrd.result__peak_signal_count_rate_rtn_mcps; + pdev->fmt_dmax_cal.ref__distance_mm = fmt_rrd.measured_distance_mm; + + if (pdev->cal_peak_rate_map.cal_reflectance_pc != 0) { + pdev->fmt_dmax_cal.ref_reflectance_pc = pdev->cal_peak_rate_map.cal_reflectance_pc; + } else { + pdev->fmt_dmax_cal.ref_reflectance_pc = 0x0014; + } + pdev->fmt_dmax_cal.coverglass_transmission = 0x0100; + } + } + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_RdWord(Dev, VL53LX_RESULT__OSC_CALIBRATE_VAL, &(pdev->dbg_results.result__osc_calibrate_val)); + + if (pdev->stat_nvm.osc_measured__fast_osc__frequency < 0x1000) { + pdev->stat_nvm.osc_measured__fast_osc__frequency = 0xBCCC; + } + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_get_mode_mitigation_roi(Dev, &(pdev->mm_roi)); + + if (pdev->optical_centre.x_centre == 0 && pdev->optical_centre.y_centre == 0) { + pdev->optical_centre.x_centre = pdev->mm_roi.x_centre << 4; + pdev->optical_centre.y_centre = pdev->mm_roi.y_centre << 4; + } + return status; +} + +VL53LX_Error VL53LX_init_refspadchar_config_struct(VL53LX_refspadchar_config_t *pdata) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + pdata->device_test_mode = VL53LX_TUNINGPARM_REFSPADCHAR_DEVICE_TEST_MODE_DEFAULT; + pdata->VL53LX_p_005 = VL53LX_TUNINGPARM_REFSPADCHAR_VCSEL_PERIOD_DEFAULT; + pdata->timeout_us = VL53LX_TUNINGPARM_REFSPADCHAR_PHASECAL_TIMEOUT_US_DEFAULT; + pdata->target_count_rate_mcps = VL53LX_TUNINGPARM_REFSPADCHAR_TARGET_COUNT_RATE_MCPS_DEFAULT; + pdata->min_count_rate_limit_mcps = VL53LX_TUNINGPARM_REFSPADCHAR_MIN_COUNTRATE_LIMIT_MCPS_DEFAULT; + pdata->max_count_rate_limit_mcps = VL53LX_TUNINGPARM_REFSPADCHAR_MAX_COUNTRATE_LIMIT_MCPS_DEFAULT; + + return status; +} + +VL53LX_Error VL53LX_init_ssc_config_struct(VL53LX_ssc_config_t *pdata) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + pdata->array_select = VL53LX_DEVICESSCARRAY_RTN; + pdata->VL53LX_p_005 = VL53LX_TUNINGPARM_SPADMAP_VCSEL_PERIOD_DEFAULT; + pdata->vcsel_start = VL53LX_TUNINGPARM_SPADMAP_VCSEL_START_DEFAULT; + pdata->vcsel_width = 0x02; + pdata->timeout_us = 36000; + pdata->rate_limit_mcps = VL53LX_TUNINGPARM_SPADMAP_RATE_LIMIT_MCPS_DEFAULT; + + return status; +} + +VL53LX_Error VL53LX_init_xtalk_config_struct(VL53LX_customer_nvm_managed_t *pnvm, VL53LX_xtalk_config_t *pdata) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + pdata->algo__crosstalk_compensation_plane_offset_kcps = pnvm->algo__crosstalk_compensation_plane_offset_kcps; + pdata->algo__crosstalk_compensation_x_plane_gradient_kcps = pnvm->algo__crosstalk_compensation_x_plane_gradient_kcps; + pdata->algo__crosstalk_compensation_y_plane_gradient_kcps = pnvm->algo__crosstalk_compensation_y_plane_gradient_kcps; + + pdata->nvm_default__crosstalk_compensation_plane_offset_kcps = (uint32_t)pnvm->algo__crosstalk_compensation_plane_offset_kcps; + pdata->nvm_default__crosstalk_compensation_x_plane_gradient_kcps = pnvm->algo__crosstalk_compensation_x_plane_gradient_kcps; + pdata->nvm_default__crosstalk_compensation_y_plane_gradient_kcps = pnvm->algo__crosstalk_compensation_y_plane_gradient_kcps; + + pdata->histogram_mode_crosstalk_margin_kcps = VL53LX_TUNINGPARM_HIST_XTALK_MARGIN_KCPS_DEFAULT; + pdata->lite_mode_crosstalk_margin_kcps = VL53LX_TUNINGPARM_LITE_XTALK_MARGIN_KCPS_DEFAULT; + + pdata->crosstalk_range_ignore_threshold_mult = VL53LX_TUNINGPARM_LITE_RIT_MULT_DEFAULT; + + if ((pdata->algo__crosstalk_compensation_plane_offset_kcps == 0x00) && (pdata->algo__crosstalk_compensation_x_plane_gradient_kcps == 0x00) && (pdata->algo__crosstalk_compensation_y_plane_gradient_kcps == 0x00)) + pdata->global_crosstalk_compensation_enable = 0x00; + else + pdata->global_crosstalk_compensation_enable = 0x01; + + if ((status == VL53LX_ERROR_NONE) && (pdata->global_crosstalk_compensation_enable == 0x01)) { + pdata->crosstalk_range_ignore_threshold_rate_mcps = VL53LX_calc_range_ignore_threshold(pdata->algo__crosstalk_compensation_plane_offset_kcps, pdata->algo__crosstalk_compensation_x_plane_gradient_kcps, pdata->algo__crosstalk_compensation_y_plane_gradient_kcps, pdata->crosstalk_range_ignore_threshold_mult); + } else { + pdata->crosstalk_range_ignore_threshold_rate_mcps = 0; + } + + pdata->algo__crosstalk_detect_min_valid_range_mm = VL53LX_TUNINGPARM_XTALK_DETECT_MIN_VALID_RANGE_MM_DEFAULT; + pdata->algo__crosstalk_detect_max_valid_range_mm = VL53LX_TUNINGPARM_XTALK_DETECT_MAX_VALID_RANGE_MM_DEFAULT; + pdata->algo__crosstalk_detect_max_valid_rate_kcps = VL53LX_TUNINGPARM_XTALK_DETECT_MAX_VALID_RATE_KCPS_DEFAULT; + pdata->algo__crosstalk_detect_max_sigma_mm = VL53LX_TUNINGPARM_XTALK_DETECT_MAX_SIGMA_MM_DEFAULT; + + return status; +} + +VL53LX_Error VL53LX_init_xtalk_extract_config_struct(VL53LX_xtalkextract_config_t *pdata) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + pdata->dss_config__target_total_rate_mcps = VL53LX_TUNINGPARM_XTALK_EXTRACT_DSS_RATE_MCPS_DEFAULT; + pdata->mm_config_timeout_us = VL53LX_TUNINGPARM_XTALK_EXTRACT_DSS_TIMEOUT_US_DEFAULT; + pdata->num_of_samples = VL53LX_TUNINGPARM_XTALK_EXTRACT_NUM_OF_SAMPLES_DEFAULT; + pdata->phasecal_config_timeout_us = VL53LX_TUNINGPARM_XTALK_EXTRACT_PHASECAL_TIMEOUT_US_DEFAULT; + pdata->range_config_timeout_us = VL53LX_TUNINGPARM_XTALK_EXTRACT_BIN_TIMEOUT_US_DEFAULT; + pdata->algo__crosstalk_extract_min_valid_range_mm = VL53LX_TUNINGPARM_XTALK_EXTRACT_MIN_FILTER_THRESH_MM_DEFAULT; + pdata->algo__crosstalk_extract_max_valid_range_mm = VL53LX_TUNINGPARM_XTALK_EXTRACT_MAX_FILTER_THRESH_MM_DEFAULT; + pdata->algo__crosstalk_extract_max_valid_rate_kcps = VL53LX_TUNINGPARM_XTALK_EXTRACT_MAX_VALID_RATE_KCPS_DEFAULT; + pdata->algo__crosstalk_extract_max_sigma_mm = VL53LX_TUNINGPARM_XTALK_EXTRACT_SIGMA_THRESHOLD_MM_DEFAULT; + + return status; +} + +VL53LX_Error VL53LX_init_offset_cal_config_struct(VL53LX_offsetcal_config_t *pdata) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + pdata->dss_config__target_total_rate_mcps = VL53LX_TUNINGPARM_OFFSET_CAL_DSS_RATE_MCPS_DEFAULT; + pdata->phasecal_config_timeout_us = VL53LX_TUNINGPARM_OFFSET_CAL_PHASECAL_TIMEOUT_US_DEFAULT; + pdata->range_config_timeout_us = VL53LX_TUNINGPARM_OFFSET_CAL_RANGE_TIMEOUT_US_DEFAULT; + pdata->mm_config_timeout_us = VL53LX_TUNINGPARM_OFFSET_CAL_MM_TIMEOUT_US_DEFAULT; + pdata->pre_num_of_samples = VL53LX_TUNINGPARM_OFFSET_CAL_PRE_SAMPLES_DEFAULT; + pdata->mm1_num_of_samples = VL53LX_TUNINGPARM_OFFSET_CAL_MM1_SAMPLES_DEFAULT; + pdata->mm2_num_of_samples = VL53LX_TUNINGPARM_OFFSET_CAL_MM2_SAMPLES_DEFAULT; + + return status; +} + +VL53LX_Error VL53LX_init_zone_cal_config_struct(VL53LX_zonecal_config_t *pdata) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + pdata->dss_config__target_total_rate_mcps = VL53LX_TUNINGPARM_ZONE_CAL_DSS_RATE_MCPS_DEFAULT; + pdata->phasecal_config_timeout_us = VL53LX_TUNINGPARM_ZONE_CAL_PHASECAL_TIMEOUT_US_DEFAULT; + pdata->range_config_timeout_us = VL53LX_TUNINGPARM_ZONE_CAL_RANGE_TIMEOUT_US_DEFAULT; + pdata->mm_config_timeout_us = VL53LX_TUNINGPARM_ZONE_CAL_DSS_TIMEOUT_US_DEFAULT; + pdata->phasecal_num_of_samples = VL53LX_TUNINGPARM_ZONE_CAL_PHASECAL_NUM_SAMPLES_DEFAULT; + pdata->zone_num_of_samples = VL53LX_TUNINGPARM_ZONE_CAL_ZONE_NUM_SAMPLES_DEFAULT; + + return status; +} + +VL53LX_Error VL53LX_init_hist_post_process_config_struct(uint8_t xtalk_compensation_enable, VL53LX_hist_post_process_config_t *pdata) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + pdata->hist_algo_select = VL53LX_TUNINGPARM_HIST_ALGO_SELECT_DEFAULT; + pdata->hist_target_order = VL53LX_TUNINGPARM_HIST_TARGET_ORDER_DEFAULT; + + pdata->filter_woi0 = VL53LX_TUNINGPARM_HIST_FILTER_WOI_0_DEFAULT; + pdata->filter_woi1 = VL53LX_TUNINGPARM_HIST_FILTER_WOI_1_DEFAULT; + + pdata->hist_amb_est_method = VL53LX_TUNINGPARM_HIST_AMB_EST_METHOD_DEFAULT; + + pdata->ambient_thresh_sigma0 = VL53LX_TUNINGPARM_HIST_AMB_THRESH_SIGMA_0_DEFAULT; + pdata->ambient_thresh_sigma1 = VL53LX_TUNINGPARM_HIST_AMB_THRESH_SIGMA_1_DEFAULT; + + pdata->ambient_thresh_events_scaler = VL53LX_TUNINGPARM_HIST_AMB_EVENTS_SCALER_DEFAULT; + + pdata->min_ambient_thresh_events = VL53LX_TUNINGPARM_HIST_MIN_AMB_THRESH_EVENTS_DEFAULT; + + pdata->noise_threshold = VL53LX_TUNINGPARM_HIST_NOISE_THRESHOLD_DEFAULT; + + pdata->signal_total_events_limit = VL53LX_TUNINGPARM_HIST_SIGNAL_TOTAL_EVENTS_LIMIT_DEFAULT; + pdata->sigma_estimator__sigma_ref_mm = VL53LX_TUNINGPARM_HIST_SIGMA_EST_REF_MM_DEFAULT; + + pdata->sigma_thresh = VL53LX_TUNINGPARM_HIST_SIGMA_THRESH_MM_DEFAULT; + pdata->range_offset_mm = 0; + pdata->gain_factor = VL53LX_TUNINGPARM_HIST_GAIN_FACTOR_DEFAULT; + + pdata->valid_phase_low = 0x08; + pdata->valid_phase_high = 0x88; + + pdata->algo__consistency_check__phase_tolerance = VL53LX_TUNINGPARM_CONSISTENCY_HIST_PHASE_TOLERANCE_DEFAULT; + pdata->algo__consistency_check__event_sigma = VL53LX_TUNINGPARM_CONSISTENCY_HIST_EVENT_SIGMA_DEFAULT; + pdata->algo__consistency_check__event_min_spad_count = VL53LX_TUNINGPARM_CONSISTENCY_HIST_EVENT_SIGMA_MIN_SPAD_LIMIT_DEFAULT; + pdata->algo__consistency_check__min_max_tolerance = VL53LX_TUNINGPARM_CONSISTENCY_HIST_MIN_MAX_TOLERANCE_MM_DEFAULT; + pdata->algo__crosstalk_compensation_enable = xtalk_compensation_enable; + pdata->algo__crosstalk_detect_min_valid_range_mm = VL53LX_TUNINGPARM_XTALK_DETECT_MIN_VALID_RANGE_MM_DEFAULT; + pdata->algo__crosstalk_detect_max_valid_range_mm = VL53LX_TUNINGPARM_XTALK_DETECT_MAX_VALID_RANGE_MM_DEFAULT; + pdata->algo__crosstalk_detect_max_valid_rate_kcps = VL53LX_TUNINGPARM_XTALK_DETECT_MAX_VALID_RATE_KCPS_DEFAULT; + pdata->algo__crosstalk_detect_max_sigma_mm = VL53LX_TUNINGPARM_XTALK_DETECT_MAX_SIGMA_MM_DEFAULT; + + pdata->algo__crosstalk_detect_event_sigma = VL53LX_TUNINGPARM_XTALK_DETECT_EVENT_SIGMA_DEFAULT; + + pdata->algo__crosstalk_detect_min_max_tolerance = VL53LX_TUNINGPARM_XTALK_DETECT_MIN_MAX_TOLERANCE_DEFAULT; + + return status; +} + +VL53LX_Error VL53LX_init_hist_gen3_dmax_config_struct(VL53LX_hist_gen3_dmax_config_t *pdata) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + pdata->dss_config__target_total_rate_mcps = 0x1400; + pdata->dss_config__aperture_attenuation = 0x38; + + pdata->signal_thresh_sigma = VL53LX_TUNINGPARM_DMAX_CFG_SIGNAL_THRESH_SIGMA_DEFAULT; + pdata->ambient_thresh_sigma = 0x70; + pdata->min_ambient_thresh_events = 16; + pdata->signal_total_events_limit = 100; + pdata->max_effective_spads = 0xFFFF; + + pdata->target_reflectance_for_dmax_calc[0] = VL53LX_TUNINGPARM_DMAX_CFG_REFLECTANCE_ARRAY_0_DEFAULT; + pdata->target_reflectance_for_dmax_calc[1] = VL53LX_TUNINGPARM_DMAX_CFG_REFLECTANCE_ARRAY_1_DEFAULT; + pdata->target_reflectance_for_dmax_calc[2] = VL53LX_TUNINGPARM_DMAX_CFG_REFLECTANCE_ARRAY_2_DEFAULT; + pdata->target_reflectance_for_dmax_calc[3] = VL53LX_TUNINGPARM_DMAX_CFG_REFLECTANCE_ARRAY_3_DEFAULT; + pdata->target_reflectance_for_dmax_calc[4] = VL53LX_TUNINGPARM_DMAX_CFG_REFLECTANCE_ARRAY_4_DEFAULT; + + return status; +} + +VL53LX_Error VL53LX_init_tuning_parm_storage_struct(VL53LX_tuning_parm_storage_t *pdata) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + pdata->tp_tuning_parm_version = VL53LX_TUNINGPARM_VERSION_DEFAULT; + pdata->tp_tuning_parm_key_table_version = VL53LX_TUNINGPARM_KEY_TABLE_VERSION_DEFAULT; + pdata->tp_tuning_parm_lld_version = VL53LX_TUNINGPARM_LLD_VERSION_DEFAULT; + pdata->tp_init_phase_rtn_lite_long = VL53LX_TUNINGPARM_INITIAL_PHASE_RTN_LITE_LONG_RANGE_DEFAULT; + pdata->tp_init_phase_rtn_lite_med = VL53LX_TUNINGPARM_INITIAL_PHASE_RTN_LITE_MED_RANGE_DEFAULT; + pdata->tp_init_phase_rtn_lite_short = VL53LX_TUNINGPARM_INITIAL_PHASE_RTN_LITE_SHORT_RANGE_DEFAULT; + pdata->tp_init_phase_ref_lite_long = VL53LX_TUNINGPARM_INITIAL_PHASE_REF_LITE_LONG_RANGE_DEFAULT; + pdata->tp_init_phase_ref_lite_med = VL53LX_TUNINGPARM_INITIAL_PHASE_REF_LITE_MED_RANGE_DEFAULT; + pdata->tp_init_phase_ref_lite_short = VL53LX_TUNINGPARM_INITIAL_PHASE_REF_LITE_SHORT_RANGE_DEFAULT; + pdata->tp_init_phase_rtn_hist_long = VL53LX_TUNINGPARM_INITIAL_PHASE_RTN_HISTO_LONG_RANGE_DEFAULT; + pdata->tp_init_phase_rtn_hist_med = VL53LX_TUNINGPARM_INITIAL_PHASE_RTN_HISTO_MED_RANGE_DEFAULT; + pdata->tp_init_phase_rtn_hist_short = VL53LX_TUNINGPARM_INITIAL_PHASE_RTN_HISTO_SHORT_RANGE_DEFAULT; + pdata->tp_init_phase_ref_hist_long = VL53LX_TUNINGPARM_INITIAL_PHASE_REF_HISTO_LONG_RANGE_DEFAULT; + pdata->tp_init_phase_ref_hist_med = VL53LX_TUNINGPARM_INITIAL_PHASE_REF_HISTO_MED_RANGE_DEFAULT; + pdata->tp_init_phase_ref_hist_short = VL53LX_TUNINGPARM_INITIAL_PHASE_REF_HISTO_SHORT_RANGE_DEFAULT; + pdata->tp_consistency_lite_phase_tolerance = VL53LX_TUNINGPARM_CONSISTENCY_LITE_PHASE_TOLERANCE_DEFAULT; + pdata->tp_phasecal_target = VL53LX_TUNINGPARM_PHASECAL_TARGET_DEFAULT; + pdata->tp_cal_repeat_rate = VL53LX_TUNINGPARM_LITE_CAL_REPEAT_RATE_DEFAULT; + pdata->tp_lite_min_clip = VL53LX_TUNINGPARM_LITE_MIN_CLIP_MM_DEFAULT; + pdata->tp_lite_long_sigma_thresh_mm = VL53LX_TUNINGPARM_LITE_LONG_SIGMA_THRESH_MM_DEFAULT; + pdata->tp_lite_med_sigma_thresh_mm = VL53LX_TUNINGPARM_LITE_MED_SIGMA_THRESH_MM_DEFAULT; + pdata->tp_lite_short_sigma_thresh_mm = VL53LX_TUNINGPARM_LITE_SHORT_SIGMA_THRESH_MM_DEFAULT; + pdata->tp_lite_long_min_count_rate_rtn_mcps = VL53LX_TUNINGPARM_LITE_LONG_MIN_COUNT_RATE_RTN_MCPS_DEFAULT; + pdata->tp_lite_med_min_count_rate_rtn_mcps = VL53LX_TUNINGPARM_LITE_MED_MIN_COUNT_RATE_RTN_MCPS_DEFAULT; + pdata->tp_lite_short_min_count_rate_rtn_mcps = VL53LX_TUNINGPARM_LITE_SHORT_MIN_COUNT_RATE_RTN_MCPS_DEFAULT; + pdata->tp_lite_sigma_est_pulse_width_ns = VL53LX_TUNINGPARM_LITE_SIGMA_EST_PULSE_WIDTH_DEFAULT; + pdata->tp_lite_sigma_est_amb_width_ns = VL53LX_TUNINGPARM_LITE_SIGMA_EST_AMB_WIDTH_NS_DEFAULT; + pdata->tp_lite_sigma_ref_mm = VL53LX_TUNINGPARM_LITE_SIGMA_REF_MM_DEFAULT; + pdata->tp_lite_seed_cfg = VL53LX_TUNINGPARM_LITE_SEED_CONFIG_DEFAULT; + pdata->tp_timed_seed_cfg = VL53LX_TUNINGPARM_TIMED_SEED_CONFIG_DEFAULT; + pdata->tp_lite_quantifier = VL53LX_TUNINGPARM_LITE_QUANTIFIER_DEFAULT; + pdata->tp_lite_first_order_select = VL53LX_TUNINGPARM_LITE_FIRST_ORDER_SELECT_DEFAULT; + pdata->tp_uwr_enable = VL53LX_TUNINGPARM_UWR_ENABLE_DEFAULT; + pdata->tp_uwr_med_z_1_min = VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_1_MIN_DEFAULT; + pdata->tp_uwr_med_z_1_max = VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_1_MAX_DEFAULT; + pdata->tp_uwr_med_z_2_min = VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_2_MIN_DEFAULT; + pdata->tp_uwr_med_z_2_max = VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_2_MAX_DEFAULT; + pdata->tp_uwr_med_z_3_min = VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_3_MIN_DEFAULT; + pdata->tp_uwr_med_z_3_max = VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_3_MAX_DEFAULT; + pdata->tp_uwr_med_z_4_min = VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_4_MIN_DEFAULT; + pdata->tp_uwr_med_z_4_max = VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_4_MAX_DEFAULT; + pdata->tp_uwr_med_z_5_min = VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_5_MIN_DEFAULT; + pdata->tp_uwr_med_z_5_max = VL53LX_TUNINGPARM_UWR_MEDIUM_ZONE_5_MAX_DEFAULT; + pdata->tp_uwr_med_corr_z_1_rangea = VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_1_RANGEA_DEFAULT; + pdata->tp_uwr_med_corr_z_1_rangeb = VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_1_RANGEB_DEFAULT; + pdata->tp_uwr_med_corr_z_2_rangea = VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_2_RANGEA_DEFAULT; + pdata->tp_uwr_med_corr_z_2_rangeb = VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_2_RANGEB_DEFAULT; + pdata->tp_uwr_med_corr_z_3_rangea = VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_3_RANGEA_DEFAULT; + pdata->tp_uwr_med_corr_z_3_rangeb = VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_3_RANGEB_DEFAULT; + pdata->tp_uwr_med_corr_z_4_rangea = VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_4_RANGEA_DEFAULT; + pdata->tp_uwr_med_corr_z_4_rangeb = VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_4_RANGEB_DEFAULT; + pdata->tp_uwr_med_corr_z_5_rangea = VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_5_RANGEA_DEFAULT; + pdata->tp_uwr_med_corr_z_5_rangeb = VL53LX_TUNINGPARM_UWR_MEDIUM_CORRECTION_ZONE_5_RANGEB_DEFAULT; + pdata->tp_uwr_lng_z_1_min = VL53LX_TUNINGPARM_UWR_LONG_ZONE_1_MIN_DEFAULT; + pdata->tp_uwr_lng_z_1_max = VL53LX_TUNINGPARM_UWR_LONG_ZONE_1_MAX_DEFAULT; + pdata->tp_uwr_lng_z_2_min = VL53LX_TUNINGPARM_UWR_LONG_ZONE_2_MIN_DEFAULT; + pdata->tp_uwr_lng_z_2_max = VL53LX_TUNINGPARM_UWR_LONG_ZONE_2_MAX_DEFAULT; + pdata->tp_uwr_lng_z_3_min = VL53LX_TUNINGPARM_UWR_LONG_ZONE_3_MIN_DEFAULT; + pdata->tp_uwr_lng_z_3_max = VL53LX_TUNINGPARM_UWR_LONG_ZONE_3_MAX_DEFAULT; + pdata->tp_uwr_lng_z_4_min = VL53LX_TUNINGPARM_UWR_LONG_ZONE_4_MIN_DEFAULT; + pdata->tp_uwr_lng_z_4_max = VL53LX_TUNINGPARM_UWR_LONG_ZONE_4_MAX_DEFAULT; + pdata->tp_uwr_lng_z_5_min = VL53LX_TUNINGPARM_UWR_LONG_ZONE_5_MIN_DEFAULT; + pdata->tp_uwr_lng_z_5_max = VL53LX_TUNINGPARM_UWR_LONG_ZONE_5_MAX_DEFAULT; + pdata->tp_uwr_lng_corr_z_1_rangea = VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_1_RANGEA_DEFAULT; + pdata->tp_uwr_lng_corr_z_1_rangeb = VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_1_RANGEB_DEFAULT; + pdata->tp_uwr_lng_corr_z_2_rangea = VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_2_RANGEA_DEFAULT; + pdata->tp_uwr_lng_corr_z_2_rangeb = VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_2_RANGEB_DEFAULT; + pdata->tp_uwr_lng_corr_z_3_rangea = VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_3_RANGEA_DEFAULT; + pdata->tp_uwr_lng_corr_z_3_rangeb = VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_3_RANGEB_DEFAULT; + pdata->tp_uwr_lng_corr_z_4_rangea = VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_4_RANGEA_DEFAULT; + pdata->tp_uwr_lng_corr_z_4_rangeb = VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_4_RANGEB_DEFAULT; + pdata->tp_uwr_lng_corr_z_5_rangea = VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_5_RANGEA_DEFAULT; + pdata->tp_uwr_lng_corr_z_5_rangeb = VL53LX_TUNINGPARM_UWR_LONG_CORRECTION_ZONE_5_RANGEB_DEFAULT; + + pdata->tp_dss_target_lite_mcps = VL53LX_TUNINGPARM_LITE_DSS_CONFIG_TARGET_TOTAL_RATE_MCPS_DEFAULT; + pdata->tp_dss_target_histo_mcps = VL53LX_TUNINGPARM_RANGING_DSS_CONFIG_TARGET_TOTAL_RATE_MCPS_DEFAULT; + pdata->tp_dss_target_histo_mz_mcps = VL53LX_TUNINGPARM_MZ_DSS_CONFIG_TARGET_TOTAL_RATE_MCPS_DEFAULT; + pdata->tp_dss_target_timed_mcps = VL53LX_TUNINGPARM_TIMED_DSS_CONFIG_TARGET_TOTAL_RATE_MCPS_DEFAULT; + pdata->tp_phasecal_timeout_lite_us = VL53LX_TUNINGPARM_LITE_PHASECAL_CONFIG_TIMEOUT_US_DEFAULT; + pdata->tp_phasecal_timeout_hist_long_us = VL53LX_TUNINGPARM_RANGING_LONG_PHASECAL_CONFIG_TIMEOUT_US_DEFAULT; + pdata->tp_phasecal_timeout_hist_med_us = VL53LX_TUNINGPARM_RANGING_MED_PHASECAL_CONFIG_TIMEOUT_US_DEFAULT; + pdata->tp_phasecal_timeout_hist_short_us = VL53LX_TUNINGPARM_RANGING_SHORT_PHASECAL_CONFIG_TIMEOUT_US_DEFAULT; + pdata->tp_phasecal_timeout_mz_long_us = VL53LX_TUNINGPARM_MZ_LONG_PHASECAL_CONFIG_TIMEOUT_US_DEFAULT; + pdata->tp_phasecal_timeout_mz_med_us = VL53LX_TUNINGPARM_MZ_MED_PHASECAL_CONFIG_TIMEOUT_US_DEFAULT; + pdata->tp_phasecal_timeout_mz_short_us = VL53LX_TUNINGPARM_MZ_SHORT_PHASECAL_CONFIG_TIMEOUT_US_DEFAULT; + pdata->tp_phasecal_timeout_timed_us = VL53LX_TUNINGPARM_TIMED_PHASECAL_CONFIG_TIMEOUT_US_DEFAULT; + pdata->tp_mm_timeout_lite_us = VL53LX_TUNINGPARM_LITE_MM_CONFIG_TIMEOUT_US_DEFAULT; + pdata->tp_mm_timeout_histo_us = VL53LX_TUNINGPARM_RANGING_MM_CONFIG_TIMEOUT_US_DEFAULT; + pdata->tp_mm_timeout_mz_us = VL53LX_TUNINGPARM_MZ_MM_CONFIG_TIMEOUT_US_DEFAULT; + pdata->tp_mm_timeout_timed_us = VL53LX_TUNINGPARM_TIMED_MM_CONFIG_TIMEOUT_US_DEFAULT; + pdata->tp_range_timeout_lite_us = VL53LX_TUNINGPARM_LITE_RANGE_CONFIG_TIMEOUT_US_DEFAULT; + pdata->tp_range_timeout_histo_us = VL53LX_TUNINGPARM_RANGING_RANGE_CONFIG_TIMEOUT_US_DEFAULT; + pdata->tp_range_timeout_mz_us = VL53LX_TUNINGPARM_MZ_RANGE_CONFIG_TIMEOUT_US_DEFAULT; + pdata->tp_range_timeout_timed_us = VL53LX_TUNINGPARM_TIMED_RANGE_CONFIG_TIMEOUT_US_DEFAULT; + + pdata->tp_mm_timeout_lpa_us = VL53LX_TUNINGPARM_LOWPOWERAUTO_MM_CONFIG_TIMEOUT_US_DEFAULT; + pdata->tp_range_timeout_lpa_us = VL53LX_TUNINGPARM_LOWPOWERAUTO_RANGE_CONFIG_TIMEOUT_US_DEFAULT; + + pdata->tp_dss_target_very_short_mcps = VL53LX_TUNINGPARM_VERY_SHORT_DSS_RATE_MCPS_DEFAULT; + + pdata->tp_phasecal_patch_power = VL53LX_TUNINGPARM_PHASECAL_PATCH_POWER_DEFAULT; + + pdata->tp_hist_merge = VL53LX_TUNINGPARM_HIST_MERGE_DEFAULT; + + pdata->tp_reset_merge_threshold = VL53LX_TUNINGPARM_RESET_MERGE_THRESHOLD_DEFAULT; + + pdata->tp_hist_merge_max_size = VL53LX_TUNINGPARM_HIST_MERGE_MAX_SIZE_DEFAULT; + + return status; +} + +VL53LX_Error VL53LX_preset_mode_histogram_short_range( + VL53LX_hist_post_process_config_t *phistpostprocess, + VL53LX_static_config_t *pstatic, + VL53LX_histogram_config_t *phistogram, + VL53LX_general_config_t *pgeneral, + VL53LX_timing_config_t *ptiming, + VL53LX_dynamic_config_t *pdynamic, + VL53LX_system_control_t *psystem, + VL53LX_tuning_parm_storage_t *ptuning_parms, + VL53LX_zone_config_t *pzone_cfg) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + status = VL53LX_preset_mode_histogram_ranging(phistpostprocess, pstatic, phistogram, pgeneral, ptiming, pdynamic, psystem, ptuning_parms, pzone_cfg); + if (status == VL53LX_ERROR_NONE) { + VL53LX_init_histogram_config_structure(7, 7, 0, 1, 1, 1, 0, 1, 1, 1, 2, 2, phistogram); + VL53LX_init_histogram_multizone_config_structure(7, 7, 0, 1, 1, 1, 0, 1, 1, 1, 2, 2, &(pzone_cfg->multizone_hist_cfg)); + VL53LX_copy_hist_cfg_to_static_cfg(phistogram, pstatic, pgeneral, ptiming, pdynamic); + + ptiming->range_config__vcsel_period_a = 0x03; + ptiming->range_config__vcsel_period_b = 0x05; + + ptiming->mm_config__timeout_macrop_a_hi = 0x00; + ptiming->mm_config__timeout_macrop_a_lo = 0x52; + ptiming->mm_config__timeout_macrop_b_hi = 0x00; + ptiming->mm_config__timeout_macrop_b_lo = 0x37; + + ptiming->range_config__timeout_macrop_a_hi = 0x00; + ptiming->range_config__timeout_macrop_a_lo = 0x66; + ptiming->range_config__timeout_macrop_b_hi = 0x00; + ptiming->range_config__timeout_macrop_b_lo = 0x44; + + pgeneral->cal_config__vcsel_start = 0x03; + + pgeneral->phasecal_config__timeout_macrop = 0xF5; + + pdynamic->sd_config__woi_sd0 = 0x03; + pdynamic->sd_config__woi_sd1 = 0x05; + pdynamic->sd_config__initial_phase_sd0 = ptuning_parms->tp_init_phase_rtn_hist_short; + pdynamic->sd_config__initial_phase_sd1 = ptuning_parms->tp_init_phase_ref_hist_short; + + phistpostprocess->valid_phase_low = 0x08; + phistpostprocess->valid_phase_high = 0x28; + + pdynamic->system__sequence_config = VL53LX_SEQUENCE_VHV_EN | VL53LX_SEQUENCE_PHASECAL_EN | VL53LX_SEQUENCE_DSS1_EN | VL53LX_SEQUENCE_DSS2_EN | VL53LX_SEQUENCE_MM1_EN | VL53LX_SEQUENCE_RANGE_EN; + + psystem->system__mode_start = VL53LX_DEVICESCHEDULERMODE_HISTOGRAM | VL53LX_DEVICEREADOUTMODE_DUAL_SD | VL53LX_DEVICEMEASUREMENTMODE_BACKTOBACK; + } + return status; +} + +void VL53LX_init_histogram_bin_data_struct(int32_t bin_value, uint16_t VL53LX_p_021, VL53LX_histogram_bin_data_t *pdata) +{ + uint16_t i = 0; + + pdata->cfg_device_state = VL53LX_DEVICESTATE_SW_STANDBY; + pdata->rd_device_state = VL53LX_DEVICESTATE_SW_STANDBY; + pdata->zone_id = 0; + pdata->time_stamp = 0; + pdata->VL53LX_p_019 = 0; + pdata->VL53LX_p_020 = VL53LX_HISTOGRAM_BUFFER_SIZE; + pdata->VL53LX_p_021 = (uint8_t)VL53LX_p_021; + pdata->number_of_ambient_bins = 0; + pdata->result__interrupt_status = 0; + pdata->result__range_status = 0; + pdata->result__report_status = 0; + pdata->result__stream_count = 0; + pdata->result__dss_actual_effective_spads = 0; + pdata->phasecal_result__reference_phase = 0; + pdata->phasecal_result__vcsel_start = 0; + pdata->cal_config__vcsel_start = 0; + pdata->vcsel_width = 0; + pdata->VL53LX_p_005 = 0; + pdata->VL53LX_p_015 = 0; + pdata->total_periods_elapsed = 0; + pdata->min_bin_value = 0; + pdata->max_bin_value = 0; + pdata->zero_distance_phase = 0; + pdata->number_of_ambient_samples = 0; + pdata->ambient_events_sum = 0; + pdata->VL53LX_p_028 = 0; + + for (i = 0; i < VL53LX_MAX_BIN_SEQUENCE_LENGTH; i++) + pdata->bin_seq[i] = (uint8_t)i; + + for (i = 0; i < VL53LX_MAX_BIN_SEQUENCE_LENGTH; i++) + pdata->bin_rep[i] = 1; + + for (i = 0; i < VL53LX_HISTOGRAM_BUFFER_SIZE; i++) + if (i < VL53LX_p_021) + pdata->bin_data[i] = bin_value; + else + pdata->bin_data[i] = 0; +} + +void VL53LX_init_xtalk_bin_data_struct(uint32_t bin_value, uint16_t VL53LX_p_021, VL53LX_xtalk_histogram_shape_t *pdata) +{ + uint16_t i = 0; + + pdata->zone_id = 0; + pdata->time_stamp = 0; + pdata->VL53LX_p_019 = 0; + pdata->VL53LX_p_020 = VL53LX_XTALK_HISTO_BINS; + pdata->VL53LX_p_021 = (uint8_t)VL53LX_p_021; + pdata->phasecal_result__reference_phase = 0; + pdata->phasecal_result__vcsel_start = 0; + pdata->cal_config__vcsel_start = 0; + pdata->vcsel_width = 0; + pdata->VL53LX_p_015 = 0; + pdata->zero_distance_phase = 0; + + for (i = 0; i < VL53LX_XTALK_HISTO_BINS; i++) { + if (i < VL53LX_p_021) + pdata->bin_data[i] = bin_value; + else + pdata->bin_data[i] = 0; + } +} + +VL53LX_Error VL53LX_xtalk_cal_data_init(VL53LX_DEV Dev) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + pdev->xtalk_cal.algo__crosstalk_compensation_plane_offset_kcps = 0; + pdev->xtalk_cal.algo__crosstalk_compensation_x_plane_gradient_kcps = 0; + pdev->xtalk_cal.algo__crosstalk_compensation_y_plane_gradient_kcps = 0; + memset(&pdev->xtalk_cal.algo__xtalk_cpo_HistoMerge_kcps[0], 0, sizeof(pdev->xtalk_cal.algo__xtalk_cpo_HistoMerge_kcps)); + + return status; +} + +VL53LX_Error VL53LX_dynamic_xtalk_correction_output_init(VL53LX_LLDriverResults_t *pres) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_smudge_corrector_data_t *pdata; + + pdata = &(pres->range_results.smudge_corrector_data); + + pdata->smudge_corr_valid = 0; + pdata->smudge_corr_clipped = 0; + pdata->single_xtalk_delta_flag = 0; + pdata->averaged_xtalk_delta_flag = 0; + pdata->sample_limit_exceeded_flag = 0; + pdata->gradient_zero_flag = 0; + pdata->new_xtalk_applied_flag = 0; + pdata->algo__crosstalk_compensation_plane_offset_kcps = 0; + pdata->algo__crosstalk_compensation_x_plane_gradient_kcps = 0; + pdata->algo__crosstalk_compensation_y_plane_gradient_kcps = 0; + + return status; +} + +VL53LX_Error VL53LX_dynamic_xtalk_correction_data_init(VL53LX_DEV Dev) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + VL53LX_LLDriverResults_t *pres = VL53LXDevStructGetLLResultsHandle(Dev); + + pdev->smudge_correct_config.smudge_corr_enabled = 1; + pdev->smudge_correct_config.smudge_corr_apply_enabled = 1; + pdev->smudge_correct_config.smudge_corr_single_apply = VL53LX_TUNINGPARM_DYNXTALK_SMUDGE_COR_SINGLE_APPLY_DEFAULT; + pdev->smudge_correct_config.smudge_margin = VL53LX_TUNINGPARM_DYNXTALK_SMUDGE_MARGIN_DEFAULT; + pdev->smudge_correct_config.noise_margin = VL53LX_TUNINGPARM_DYNXTALK_NOISE_MARGIN_DEFAULT; + pdev->smudge_correct_config.user_xtalk_offset_limit = VL53LX_TUNINGPARM_DYNXTALK_XTALK_OFFSET_LIMIT_DEFAULT; + pdev->smudge_correct_config.user_xtalk_offset_limit_hi = VL53LX_TUNINGPARM_DYNXTALK_XTALK_OFFSET_LIMIT_HI_DEFAULT; + pdev->smudge_correct_config.sample_limit = VL53LX_TUNINGPARM_DYNXTALK_SAMPLE_LIMIT_DEFAULT; + pdev->smudge_correct_config.single_xtalk_delta = VL53LX_TUNINGPARM_DYNXTALK_SINGLE_XTALK_DELTA_DEFAULT; + pdev->smudge_correct_config.averaged_xtalk_delta = VL53LX_TUNINGPARM_DYNXTALK_AVERAGED_XTALK_DELTA_DEFAULT; + pdev->smudge_correct_config.smudge_corr_clip_limit = VL53LX_TUNINGPARM_DYNXTALK_CLIP_LIMIT_DEFAULT; + pdev->smudge_correct_config.smudge_corr_ambient_threshold = VL53LX_TUNINGPARM_DYNXTALK_XTALK_AMB_THRESHOLD_DEFAULT; + pdev->smudge_correct_config.scaler_calc_method = 0; + pdev->smudge_correct_config.x_gradient_scaler = VL53LX_TUNINGPARM_DYNXTALK_XGRADIENT_SCALER_DEFAULT; + pdev->smudge_correct_config.y_gradient_scaler = VL53LX_TUNINGPARM_DYNXTALK_YGRADIENT_SCALER_DEFAULT; + pdev->smudge_correct_config.user_scaler_set = VL53LX_TUNINGPARM_DYNXTALK_USER_SCALER_SET_DEFAULT; + pdev->smudge_correct_config.nodetect_ambient_threshold = VL53LX_TUNINGPARM_DYNXTALK_NODETECT_AMB_THRESHOLD_KCPS_DEFAULT; + pdev->smudge_correct_config.nodetect_sample_limit = VL53LX_TUNINGPARM_DYNXTALK_NODETECT_SAMPLE_LIMIT_DEFAULT; + pdev->smudge_correct_config.nodetect_xtalk_offset = VL53LX_TUNINGPARM_DYNXTALK_NODETECT_XTALK_OFFSET_KCPS_DEFAULT; + pdev->smudge_correct_config.nodetect_min_range_mm = VL53LX_TUNINGPARM_DYNXTALK_NODETECT_MIN_RANGE_MM_DEFAULT; + pdev->smudge_correct_config.max_smudge_factor = VL53LX_TUNINGPARM_DYNXTALK_MAX_SMUDGE_FACTOR_DEFAULT; + pdev->smudge_corrector_internals.current_samples = 0; + pdev->smudge_corrector_internals.required_samples = 0; + pdev->smudge_corrector_internals.accumulator = 0; + pdev->smudge_corrector_internals.nodetect_counter = 0; + + VL53LX_dynamic_xtalk_correction_output_init(pres); + + return status; +} + +VL53LX_Error VL53LX_low_power_auto_data_init(VL53LX_DEV Dev) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + pdev->low_power_auto_data.vhv_loop_bound = VL53LX_TUNINGPARM_LOWPOWERAUTO_VHV_LOOP_BOUND_DEFAULT; + pdev->low_power_auto_data.is_low_power_auto_mode = 0; + pdev->low_power_auto_data.low_power_auto_range_count = 0; + pdev->low_power_auto_data.saved_interrupt_config = 0; + pdev->low_power_auto_data.saved_vhv_init = 0; + pdev->low_power_auto_data.saved_vhv_timeout = 0; + pdev->low_power_auto_data.first_run_phasecal_result = 0; + pdev->low_power_auto_data.dss__total_rate_per_spad_mcps = 0; + pdev->low_power_auto_data.dss__required_spads = 0; + + return status; +} + +VL53LX_Error VL53LX_data_init(VL53LX_DEV Dev, uint8_t read_p2p_data) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + VL53LX_LLDriverResults_t *pres = VL53LXDevStructGetLLResultsHandle(Dev); + VL53LX_zone_objects_t *pobjects; + uint8_t i = 0; + + VL53LX_init_ll_driver_state(Dev, VL53LX_DEVICESTATE_UNKNOWN); + + pres->range_results.max_results = VL53LX_MAX_RANGE_RESULTS; + pres->range_results.active_results = 0; + pres->zone_results.max_zones = VL53LX_MAX_USER_ZONES; + pres->zone_results.active_zones = 0; + + for (i = 0; i < VL53LX_MAX_USER_ZONES; i++) { + pobjects = &(pres->zone_results.VL53LX_p_003[i]); + pobjects->xmonitor.VL53LX_p_016 = 0; + pobjects->xmonitor.VL53LX_p_017 = 0; + pobjects->xmonitor.VL53LX_p_011 = 0; + pobjects->xmonitor.range_status = VL53LX_DEVICEERROR_NOUPDATE; + } + + pres->zone_hists.max_zones = VL53LX_MAX_USER_ZONES; + pres->zone_hists.active_zones = 0; + + pres->zone_cal.max_zones = VL53LX_MAX_USER_ZONES; + + pres->zone_cal.active_zones = 0; + for (i = 0; i < VL53LX_MAX_USER_ZONES; i++) { + pres->zone_cal.VL53LX_p_003[i].no_of_samples = 0; + pres->zone_cal.VL53LX_p_003[i].effective_spads = 0; + pres->zone_cal.VL53LX_p_003[i].peak_rate_mcps = 0; + pres->zone_cal.VL53LX_p_003[i].median_range_mm = 0; + pres->zone_cal.VL53LX_p_003[i].range_mm_offset = 0; + } + + pdev->wait_method = VL53LX_WAIT_METHOD_BLOCKING; + pdev->preset_mode = VL53LX_DEVICEPRESETMODE_HISTOGRAM_MEDIUM_RANGE; + pdev->zone_preset = 0; + pdev->measurement_mode = VL53LX_DEVICEMEASUREMENTMODE_STOP; + + pdev->offset_calibration_mode = VL53LX_OFFSETCALIBRATIONMODE__MM1_MM2__STANDARD; + pdev->offset_correction_mode = VL53LX_OFFSETCORRECTIONMODE__MM1_MM2_OFFSETS; + pdev->dmax_mode = VL53LX_DEVICEDMAXMODE__FMT_CAL_DATA; + + pdev->phasecal_config_timeout_us = 1000; + pdev->mm_config_timeout_us = 2000; + pdev->range_config_timeout_us = 13000; + pdev->inter_measurement_period_ms = 100; + pdev->dss_config__target_total_rate_mcps = 0x0A00; + pdev->debug_mode = 0x00; + + pdev->offset_results.max_results = VL53LX_MAX_OFFSET_RANGE_RESULTS; + pdev->offset_results.active_results = 0; + + pdev->gain_cal.standard_ranging_gain_factor = VL53LX_TUNINGPARM_LITE_RANGING_GAIN_FACTOR_DEFAULT; + pdev->gain_cal.histogram_ranging_gain_factor = VL53LX_TUNINGPARM_HIST_GAIN_FACTOR_DEFAULT; + + VL53LX_init_version(Dev); + + memset(pdev->multi_bins_rec, 0, sizeof(pdev->multi_bins_rec)); + pdev->bin_rec_pos = 0; + pdev->pos_before_next_recom = 0; + + if (read_p2p_data > 0 && status == VL53LX_ERROR_NONE) + status = VL53LX_read_p2p_data(Dev); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_init_refspadchar_config_struct(&(pdev->refspadchar)); + + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_init_ssc_config_struct(&(pdev->ssc_cfg)); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_init_xtalk_config_struct(&(pdev->customer), &(pdev->xtalk_cfg)); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_init_xtalk_extract_config_struct(&(pdev->xtalk_extract_cfg)); + + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_init_offset_cal_config_struct(&(pdev->offsetcal_cfg)); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_init_zone_cal_config_struct(&(pdev->zonecal_cfg)); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_init_hist_post_process_config_struct(pdev->xtalk_cfg.global_crosstalk_compensation_enable, &(pdev->histpostprocess)); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_init_hist_gen3_dmax_config_struct(&(pdev->dmax_cfg)); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_init_tuning_parm_storage_struct(&(pdev->tuning_parms)); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_set_preset_mode(Dev, pdev->preset_mode, pdev->dss_config__target_total_rate_mcps, pdev->phasecal_config_timeout_us, pdev->mm_config_timeout_us, pdev->range_config_timeout_us, pdev->inter_measurement_period_ms); + + VL53LX_init_histogram_bin_data_struct(0, VL53LX_HISTOGRAM_BUFFER_SIZE, &(pdev->hist_data)); + VL53LX_init_histogram_bin_data_struct(0, VL53LX_HISTOGRAM_BUFFER_SIZE, &(pdev->hist_xtalk)); + VL53LX_init_xtalk_bin_data_struct(0, VL53LX_XTALK_HISTO_BINS, &(pdev->xtalk_shapes.xtalk_shape)); + VL53LX_xtalk_cal_data_init(Dev); + VL53LX_dynamic_xtalk_correction_data_init(Dev); + VL53LX_low_power_auto_data_init(Dev); + + return status; +} + +VL53LX_Error VL53LX_set_dmax_mode(VL53LX_DEV Dev, VL53LX_DeviceDmaxMode dmax_mode) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + pdev->dmax_mode = dmax_mode; + + return status; +} + +VL53LX_Error VL53LX_DataInit(VL53LX_DEV Dev) +{ + VL53LX_Error Status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev; + uint8_t measurement_mode; + +#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); + + return Status; +} + +VL53LX_Error VL53LX_get_zone_config(VL53LX_DEV Dev, VL53LX_zone_config_t *pzone_cfg) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + memcpy(pzone_cfg, &(pdev->zone_cfg), sizeof(VL53LX_zone_config_t)); + + 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; + + 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; + + 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; + + 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; + + 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; + + *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); + } + return Status; +} + +static int setup_tunings(struct stmvl53lx_data *data) +{ + int rc = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(tunings); i++) { + rc = VL53LX_SetTuningParameter(&data->stdev, tunings[i][0], + tunings[i][1]); + if (rc) { + rc = store_last_error(data, rc); + break; + } + } + return rc; +} + +static int allocate_dev_id(void) +{ + int i; + + mutex_lock(&dev_table_mutex); + + for (i = 0; i < STMVL53LX_CFG_MAX_DEV; i++) + if (!stmvl53lx_dev_table[i]) + break; + i = i < STMVL53LX_CFG_MAX_DEV ? i : -1; + + mutex_unlock(&dev_table_mutex); + + return i; +} + +static void deallocate_dev_id(int id) +{ + mutex_lock(&dev_table_mutex); + + stmvl53lx_dev_table[id] = NULL; + + mutex_unlock(&dev_table_mutex); +} + +static void vl53lx_diff_histo_stddev(VL53LX_LLDriverData_t *pdev, + VL53LX_histogram_bin_data_t *pdata, uint8_t timing, uint8_t HighIndex, + uint8_t prev_pos, int32_t *pdiff_histo_stddev) +{ + uint16_t bin = 0; + int32_t total_rate_pre = 0; + int32_t total_rate_cur = 0; + int32_t PrevBin, CurrBin; + + total_rate_pre = 0; + total_rate_cur = 0; + + + for (bin = timing * 4; bin < HighIndex; bin++) { + total_rate_pre += pdev->multi_bins_rec[prev_pos][timing][bin]; + total_rate_cur += pdata->bin_data[bin]; + } + + if ((total_rate_pre != 0) && (total_rate_cur != 0)) + for (bin = timing * 4; bin < HighIndex; bin++) { + PrevBin = pdev->multi_bins_rec[prev_pos][timing][bin]; + PrevBin = (PrevBin * 1000) / total_rate_pre; + CurrBin = pdata->bin_data[bin] * 1000 / total_rate_cur; + *pdiff_histo_stddev += (PrevBin - CurrBin) * (PrevBin - CurrBin); + } +} + +static void vl53lx_histo_merge(VL53LX_DEV Dev, VL53LX_histogram_bin_data_t *pdata) +{ + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + uint16_t bin = 0; + uint8_t i = 0; + int32_t TuningBinRecSize = 0; + uint8_t recom_been_reset = 0; + uint8_t timing = 0; + int32_t rmt = 0; + int32_t diff_histo_stddev = 0; + uint8_t HighIndex, prev_pos; + uint8_t BuffSize = VL53LX_HISTOGRAM_BUFFER_SIZE; + uint8_t pos; + + VL53LX_get_tuning_parm(Dev, VL53LX_TUNINGPARM_HIST_MERGE_MAX_SIZE, &TuningBinRecSize); + VL53LX_get_tuning_parm(Dev, VL53LX_TUNINGPARM_RESET_MERGE_THRESHOLD, &rmt); + + if (pdev->pos_before_next_recom == 0) { + timing = 1 - pdata->result__stream_count % 2; + + diff_histo_stddev = 0; + HighIndex = BuffSize - timing * 4; + if (pdev->bin_rec_pos > 0) + prev_pos = pdev->bin_rec_pos - 1; + else + prev_pos = (TuningBinRecSize - 1); + + if (pdev->multi_bins_rec[prev_pos][timing][4] > 0) + vl53lx_diff_histo_stddev(pdev, pdata, timing, HighIndex, prev_pos, &diff_histo_stddev); + + if (diff_histo_stddev >= rmt) { + memset(pdev->multi_bins_rec, 0, sizeof(pdev->multi_bins_rec)); + pdev->bin_rec_pos = 0; + recom_been_reset = 1; + if (timing == 0) + pdev->pos_before_next_recom = VL53LX_FRAME_WAIT_EVENT; + else + pdev->pos_before_next_recom = VL53LX_FRAME_WAIT_EVENT + 1; + } else { + pos = pdev->bin_rec_pos; + for (i = 0; i < BuffSize; i++) + pdev->multi_bins_rec[pos][timing][i] = pdata->bin_data[i]; + } + if (pdev->bin_rec_pos == (TuningBinRecSize - 1) && timing == 1) + pdev->bin_rec_pos = 0; + else if (timing == 1) + pdev->bin_rec_pos++; + + if (!((recom_been_reset == 1) && (timing == 0)) && + (pdev->pos_before_next_recom == 0)) { + + for (bin = 0; bin < BuffSize; bin++) + pdata->bin_data[bin] = 0; + + for (bin = 0; bin < BuffSize; bin++) + for (i = 0; i < TuningBinRecSize; i++) + pdata->bin_data[bin] += (pdev->multi_bins_rec[i][timing][bin]); + } + } else { + + pdev->pos_before_next_recom--; + if (pdev->pos_before_next_recom == 255) + pdev->pos_before_next_recom = 0; + } +} + +void VL53LX_hist_get_bin_sequence_config(VL53LX_DEV Dev, VL53LX_histogram_bin_data_t *pdata) +{ + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + int32_t amb_thresh_low = 0; + int32_t amb_thresh_high = 0; + uint8_t i = 0; + + amb_thresh_low = 1024 * (int32_t)pdev->hist_cfg.histogram_config__amb_thresh_low; + amb_thresh_high = 1024 * (int32_t)pdev->hist_cfg.histogram_config__amb_thresh_high; + + if ((pdev->ll_state.rd_stream_count & 0x01) == 0) { + pdata->bin_seq[5] = pdev->hist_cfg.histogram_config__mid_amb_even_bin_4_5 >> 4; + pdata->bin_seq[4] = pdev->hist_cfg.histogram_config__mid_amb_even_bin_4_5 & 0x0F; + pdata->bin_seq[3] = pdev->hist_cfg.histogram_config__mid_amb_even_bin_2_3 >> 4; + pdata->bin_seq[2] = pdev->hist_cfg.histogram_config__mid_amb_even_bin_2_3 & 0x0F; + pdata->bin_seq[1] = pdev->hist_cfg.histogram_config__mid_amb_even_bin_0_1 >> 4; + pdata->bin_seq[0] = pdev->hist_cfg.histogram_config__mid_amb_even_bin_0_1 & 0x0F; + + if (pdata->ambient_events_sum > amb_thresh_high) { + pdata->bin_seq[5] = pdev->hist_cfg.histogram_config__high_amb_even_bin_4_5 >> 4; + pdata->bin_seq[4] = pdev->hist_cfg.histogram_config__high_amb_even_bin_4_5 & 0x0F; + pdata->bin_seq[3] = pdev->hist_cfg.histogram_config__high_amb_even_bin_2_3 >> 4; + pdata->bin_seq[2] = pdev->hist_cfg.histogram_config__high_amb_even_bin_2_3 & 0x0F; + pdata->bin_seq[1] = pdev->hist_cfg.histogram_config__high_amb_even_bin_0_1 >> 4; + pdata->bin_seq[0] = pdev->hist_cfg.histogram_config__high_amb_even_bin_0_1 & 0x0F; + } + if (pdata->ambient_events_sum < amb_thresh_low) { + pdata->bin_seq[5] = pdev->hist_cfg.histogram_config__low_amb_even_bin_4_5 >> 4; + pdata->bin_seq[4] = pdev->hist_cfg.histogram_config__low_amb_even_bin_4_5 & 0x0F; + pdata->bin_seq[3] = pdev->hist_cfg.histogram_config__low_amb_even_bin_2_3 >> 4; + pdata->bin_seq[2] = pdev->hist_cfg.histogram_config__low_amb_even_bin_2_3 & 0x0F; + pdata->bin_seq[1] = pdev->hist_cfg.histogram_config__low_amb_even_bin_0_1 >> 4; + pdata->bin_seq[0] = pdev->hist_cfg.histogram_config__low_amb_even_bin_0_1 & 0x0F; + } + + } else { + pdata->bin_seq[5] = pdev->hist_cfg.histogram_config__mid_amb_odd_bin_5 & 0x0F; + pdata->bin_seq[4] = pdev->hist_cfg.histogram_config__mid_amb_odd_bin_3_4 & 0x0F; + pdata->bin_seq[3] = pdev->hist_cfg.histogram_config__mid_amb_odd_bin_3_4 >> 4; + pdata->bin_seq[2] = pdev->hist_cfg.histogram_config__mid_amb_odd_bin_2 & 0x0F; + pdata->bin_seq[1] = pdev->hist_cfg.histogram_config__mid_amb_odd_bin_0_1 >> 4; + pdata->bin_seq[0] = pdev->hist_cfg.histogram_config__mid_amb_odd_bin_0_1 & 0x0F; + if (pdata->ambient_events_sum > amb_thresh_high) { + pdata->bin_seq[5] = pdev->hist_cfg.histogram_config__high_amb_odd_bin_4_5 >> 4; + pdata->bin_seq[4] = pdev->hist_cfg.histogram_config__high_amb_odd_bin_4_5 & 0x0F; + pdata->bin_seq[3] = pdev->hist_cfg.histogram_config__high_amb_odd_bin_2_3 >> 4; + pdata->bin_seq[2] = pdev->hist_cfg.histogram_config__high_amb_odd_bin_2_3 & 0x0F; + pdata->bin_seq[1] = pdev->hist_cfg.histogram_config__high_amb_odd_bin_0_1 >> 4; + pdata->bin_seq[0] = pdev->hist_cfg.histogram_config__high_amb_odd_bin_0_1 & 0x0F; + } + if (pdata->ambient_events_sum < amb_thresh_low) { + pdata->bin_seq[5] = pdev->hist_cfg.histogram_config__low_amb_odd_bin_4_5 >> 4; + pdata->bin_seq[4] = pdev->hist_cfg.histogram_config__low_amb_odd_bin_4_5 & 0x0F; + pdata->bin_seq[3] = pdev->hist_cfg.histogram_config__low_amb_odd_bin_2_3 >> 4; + pdata->bin_seq[2] = pdev->hist_cfg.histogram_config__low_amb_odd_bin_2_3 & 0x0F; + pdata->bin_seq[1] = pdev->hist_cfg.histogram_config__low_amb_odd_bin_0_1 >> 4; + pdata->bin_seq[0] = pdev->hist_cfg.histogram_config__low_amb_odd_bin_0_1 & 0x0F; + } + } + for (i = 0; i < VL53LX_MAX_BIN_SEQUENCE_LENGTH; i++) + pdata->bin_rep[i] = 1; +} + +uint32_t VL53LX_duration_maths(uint32_t pll_period_us, uint32_t vcsel_parm_pclks, uint32_t window_vclks, uint32_t elapsed_mclks) +{ + uint64_t tmp_long_int = 0; + uint32_t duration_us = 0; + + duration_us = window_vclks * pll_period_us; + duration_us = duration_us >> 12; + tmp_long_int = (uint64_t)duration_us; + duration_us = elapsed_mclks * vcsel_parm_pclks; + duration_us = duration_us >> 4; + tmp_long_int = tmp_long_int * (uint64_t)duration_us; + tmp_long_int = tmp_long_int >> 12; + if (tmp_long_int > 0xFFFFFFFF) + tmp_long_int = 0xFFFFFFFF; + + duration_us = (uint32_t)tmp_long_int; + return duration_us; +} + +void VL53LX_hist_calc_zero_distance_phase(VL53LX_histogram_bin_data_t *pdata) +{ + uint32_t period = 0; + uint32_t VL53LX_p_014 = 0; + + period = 2048 * (uint32_t)VL53LX_decode_vcsel_period(pdata->VL53LX_p_005); + + VL53LX_p_014 = period; + VL53LX_p_014 += (uint32_t)pdata->phasecal_result__reference_phase; + VL53LX_p_014 += (2048 * (uint32_t)pdata->phasecal_result__vcsel_start); + VL53LX_p_014 -= (2048 * (uint32_t)pdata->cal_config__vcsel_start); + + if (period != 0) + VL53LX_p_014 = VL53LX_p_014 % period; + else + VL53LX_p_014 = 0; + + pdata->zero_distance_phase = (uint16_t)VL53LX_p_014; +} + +void VL53LX_hist_estimate_ambient_from_ambient_bins(VL53LX_histogram_bin_data_t *pdata) +{ + uint8_t bin = 0; + + if (pdata->number_of_ambient_bins > 0) { + pdata->number_of_ambient_samples = pdata->number_of_ambient_bins; + pdata->ambient_events_sum = 0; + for (bin = 0; bin < pdata->number_of_ambient_bins; bin++) + pdata->ambient_events_sum += pdata->bin_data[bin]; + + pdata->VL53LX_p_028 = pdata->ambient_events_sum; + pdata->VL53LX_p_028 += ((int32_t)pdata->number_of_ambient_bins / 2); + pdata->VL53LX_p_028 /= (int32_t)pdata->number_of_ambient_bins; + } +} + +VL53LX_Error VL53LX_get_histogram_bin_data(VL53LX_DEV Dev, VL53LX_histogram_bin_data_t *pdata) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + VL53LX_LLDriverResults_t *pres = VL53LXDevStructGetLLResultsHandle(Dev); + VL53LX_zone_private_dyn_cfg_t *pzone_dyn_cfg; + VL53LX_static_nvm_managed_t *pstat_nvm = &(pdev->stat_nvm); + VL53LX_static_config_t *pstat_cfg = &(pdev->stat_cfg); + VL53LX_general_config_t *pgen_cfg = &(pdev->gen_cfg); + VL53LX_timing_config_t *ptim_cfg = &(pdev->tim_cfg); + VL53LX_range_results_t *presults = &(pres->range_results); + + uint8_t buffer[VL53LX_MAX_I2C_XFER_SIZE]; + uint8_t *pbuffer = &buffer[0]; + uint8_t bin_23_0 = 0x00; + uint16_t bin = 0; + uint16_t i2c_buffer_offset_bytes = 0; + uint16_t encoded_timeout = 0; + + uint32_t pll_period_us = 0; + uint32_t periods_elapsed_tmp = 0; + + uint8_t i = 0; + + int32_t hist_merge = 0; + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_ReadMulti(Dev, VL53LX_HISTOGRAM_BIN_DATA_I2C_INDEX, pbuffer, VL53LX_HISTOGRAM_BIN_DATA_I2C_SIZE_BYTES); + + pdata->result__interrupt_status = *(pbuffer + 0); + pdata->result__range_status = *(pbuffer + 1); + pdata->result__report_status = *(pbuffer + 2); + pdata->result__stream_count = *(pbuffer + 3); + pdata->result__dss_actual_effective_spads = VL53LX_i2c_decode_uint16_t(2, pbuffer + 4); + + i2c_buffer_offset_bytes = VL53LX_PHASECAL_RESULT__REFERENCE_PHASE - VL53LX_HISTOGRAM_BIN_DATA_I2C_INDEX; + + pbuffer = &buffer[i2c_buffer_offset_bytes]; + + pdata->phasecal_result__reference_phase = VL53LX_i2c_decode_uint16_t(2, pbuffer); + + i2c_buffer_offset_bytes = VL53LX_PHASECAL_RESULT__VCSEL_START - VL53LX_HISTOGRAM_BIN_DATA_I2C_INDEX; + + pdata->phasecal_result__vcsel_start = buffer[i2c_buffer_offset_bytes]; + + pdev->dbg_results.phasecal_result__reference_phase = pdata->phasecal_result__reference_phase; + pdev->dbg_results.phasecal_result__vcsel_start = pdata->phasecal_result__vcsel_start; + + i2c_buffer_offset_bytes = VL53LX_RESULT__HISTOGRAM_BIN_23_0_MSB - VL53LX_HISTOGRAM_BIN_DATA_I2C_INDEX; + + bin_23_0 = buffer[i2c_buffer_offset_bytes] << 2; + + i2c_buffer_offset_bytes = VL53LX_RESULT__HISTOGRAM_BIN_23_0_LSB - VL53LX_HISTOGRAM_BIN_DATA_I2C_INDEX; + + bin_23_0 += buffer[i2c_buffer_offset_bytes]; + + i2c_buffer_offset_bytes = VL53LX_RESULT__HISTOGRAM_BIN_23_0 - VL53LX_HISTOGRAM_BIN_DATA_I2C_INDEX; + + buffer[i2c_buffer_offset_bytes] = bin_23_0; + + i2c_buffer_offset_bytes = VL53LX_RESULT__HISTOGRAM_BIN_0_2 - VL53LX_HISTOGRAM_BIN_DATA_I2C_INDEX; + + pbuffer = &buffer[i2c_buffer_offset_bytes]; + for (bin = 0; bin < VL53LX_HISTOGRAM_BUFFER_SIZE; bin++) { + pdata->bin_data[bin] = (int32_t)VL53LX_i2c_decode_uint32_t(3, pbuffer); + pbuffer += 3; + } + + VL53LX_get_tuning_parm(Dev, VL53LX_TUNINGPARM_HIST_MERGE, &hist_merge); + if (pdata->result__stream_count == 0) { + + memset(pdev->multi_bins_rec, 0, sizeof(pdev->multi_bins_rec)); + pdev->bin_rec_pos = 0; + pdev->pos_before_next_recom = 0; + } + if (hist_merge == 1) + vl53lx_histo_merge(Dev, pdata); + + pdata->zone_id = pdev->ll_state.rd_zone_id; + pdata->VL53LX_p_019 = 0; + pdata->VL53LX_p_020 = VL53LX_HISTOGRAM_BUFFER_SIZE; + pdata->VL53LX_p_021 = VL53LX_HISTOGRAM_BUFFER_SIZE; + + pdata->cal_config__vcsel_start = pgen_cfg->cal_config__vcsel_start; + + + + pdata->vcsel_width = ((uint16_t)pgen_cfg->global_config__vcsel_width) << 4; + pdata->vcsel_width += (uint16_t)pstat_cfg->ana_config__vcsel_pulse_width_offset; + + pdata->VL53LX_p_015 = pstat_nvm->osc_measured__fast_osc__frequency; + + VL53LX_hist_get_bin_sequence_config(Dev, pdata); + + if (pdev->ll_state.rd_timing_status == 0) { + encoded_timeout = (ptim_cfg->range_config__timeout_macrop_a_hi << 8) + ptim_cfg->range_config__timeout_macrop_a_lo; + pdata->VL53LX_p_005 = ptim_cfg->range_config__vcsel_period_a; + } else { + encoded_timeout = (ptim_cfg->range_config__timeout_macrop_b_hi << 8) + ptim_cfg->range_config__timeout_macrop_b_lo; + pdata->VL53LX_p_005 = ptim_cfg->range_config__vcsel_period_b; + } + + pdata->number_of_ambient_bins = 0; + for (i = 0; i < 6; i++) { + if ((pdata->bin_seq[i] & 0x07) == 0x07) + pdata->number_of_ambient_bins = pdata->number_of_ambient_bins + 0x04; + } + pdata->total_periods_elapsed = VL53LX_decode_timeout(encoded_timeout); + + pll_period_us = VL53LX_calc_pll_period_us(pdata->VL53LX_p_015); + + periods_elapsed_tmp = pdata->total_periods_elapsed + 1; + + pdata->peak_duration_us = VL53LX_duration_maths(pll_period_us, (uint32_t)pdata->vcsel_width, VL53LX_RANGING_WINDOW_VCSEL_PERIODS, periods_elapsed_tmp); + + pdata->woi_duration_us = 0; + + VL53LX_hist_calc_zero_distance_phase(pdata); + VL53LX_hist_estimate_ambient_from_ambient_bins(pdata); + + pdata->cfg_device_state = pdev->ll_state.cfg_device_state; + pdata->rd_device_state = pdev->ll_state.rd_device_state; + + pzone_dyn_cfg = &(pres->zone_dyn_cfgs.VL53LX_p_003[pdata->zone_id]); + + pdata->roi_config__user_roi_centre_spad = pzone_dyn_cfg->roi_config__user_roi_centre_spad; + pdata->roi_config__user_roi_requested_global_xy_size = pzone_dyn_cfg->roi_config__user_roi_requested_global_xy_size; + + presults->device_status = VL53LX_DEVICEERROR_NOUPDATE; + + switch (pdata->result__range_status & VL53LX_RANGE_STATUS__RANGE_STATUS_MASK) { + case VL53LX_DEVICEERROR_VCSELCONTINUITYTESTFAILURE: + case VL53LX_DEVICEERROR_VCSELWATCHDOGTESTFAILURE: + case VL53LX_DEVICEERROR_NOVHVVALUEFOUND: + case VL53LX_DEVICEERROR_USERROICLIP: + case VL53LX_DEVICEERROR_MULTCLIPFAIL: + presults->device_status = (pdata->result__range_status & VL53LX_RANGE_STATUS__RANGE_STATUS_MASK); + status = VL53LX_ERROR_RANGE_ERROR; + break; + } + return status; +} + +VL53LX_Error VL53LX_hist_copy_and_scale_ambient_info(VL53LX_zone_hist_info_t *pidata, VL53LX_histogram_bin_data_t *podata) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + int64_t evts = 0; + int64_t tmpi = 0; + int64_t tmpo = 0; + + if (pidata->result__dss_actual_effective_spads == 0) { + status = VL53LX_ERROR_DIVISION_BY_ZERO; + } else { + if (pidata->number_of_ambient_bins > 0 && + podata->number_of_ambient_bins == 0) { + tmpo = 1 + (int64_t)podata->total_periods_elapsed; + tmpo *= (int64_t)podata->result__dss_actual_effective_spads; + tmpi = 1 + (int64_t)pidata->total_periods_elapsed; + tmpi *= (int64_t)pidata->result__dss_actual_effective_spads; + evts = tmpo * (int64_t)pidata->ambient_events_sum; + evts += (tmpi/2); + if (tmpi != 0) + evts = do_division_s(evts, tmpi); + + podata->ambient_events_sum = (int32_t)evts; + podata->VL53LX_p_028 = podata->ambient_events_sum; + podata->VL53LX_p_028 += ((int32_t)pidata->number_of_ambient_bins / 2); + podata->VL53LX_p_028 /= (int32_t)pidata->number_of_ambient_bins; + } + } + return status; +} + +VL53LX_Error VL53LX_compute_histo_merge_nb(VL53LX_DEV Dev, uint8_t *histo_merge_nb) +{ + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + VL53LX_Error status = VL53LX_ERROR_NONE; + uint8_t i, timing; + uint8_t sum = 0; + + timing = (pdev->hist_data.bin_seq[0] == 7 ? 1 : 0); + for (i = 0; i < VL53LX_BIN_REC_SIZE; i++) + if (pdev->multi_bins_rec[i][timing][7] > 0) + sum++; + *histo_merge_nb = sum; + return status; +} + +void VL53LX_hist_combine_mm1_mm2_offsets( + int16_t mm1_offset_mm, + int16_t mm2_offset_mm, + uint8_t encoded_mm_roi_centre, + uint8_t encoded_mm_roi_size, + uint8_t encoded_zone_centre, + uint8_t encoded_zone_size, + VL53LX_additional_offset_cal_data_t *pcal_data, + uint8_t *pgood_spads, + uint16_t aperture_attenuation, + int16_t *prange_offset_mm) +{ + uint16_t max_mm_inner_effective_spads = 0; + uint16_t max_mm_outer_effective_spads = 0; + uint16_t mm_inner_effective_spads = 0; + uint16_t mm_outer_effective_spads = 0; + uint32_t scaled_mm1_peak_rate_mcps = 0; + uint32_t scaled_mm2_peak_rate_mcps = 0; + int32_t tmp0 = 0; + int32_t tmp1 = 0; + + VL53LX_calc_mm_effective_spads( + encoded_mm_roi_centre, + encoded_mm_roi_size, + 0xC7, + 0xFF, + pgood_spads, + aperture_attenuation, + &max_mm_inner_effective_spads, + &max_mm_outer_effective_spads); + + if ((max_mm_inner_effective_spads == 0) || + (max_mm_outer_effective_spads == 0)) + goto FAIL; + + VL53LX_calc_mm_effective_spads( + encoded_mm_roi_centre, + encoded_mm_roi_size, + encoded_zone_centre, + encoded_zone_size, + pgood_spads, + aperture_attenuation, + &mm_inner_effective_spads, + &mm_outer_effective_spads); + + scaled_mm1_peak_rate_mcps = (uint32_t)pcal_data->result__mm_inner_peak_signal_count_rtn_mcps; + scaled_mm1_peak_rate_mcps *= (uint32_t)mm_inner_effective_spads; + scaled_mm1_peak_rate_mcps /= (uint32_t)max_mm_inner_effective_spads; + + scaled_mm2_peak_rate_mcps = (uint32_t)pcal_data->result__mm_outer_peak_signal_count_rtn_mcps; + scaled_mm2_peak_rate_mcps *= (uint32_t)mm_outer_effective_spads; + scaled_mm2_peak_rate_mcps /= (uint32_t)max_mm_outer_effective_spads; + + tmp0 = ((int32_t)mm1_offset_mm * (int32_t)scaled_mm1_peak_rate_mcps); + tmp0 += ((int32_t)mm2_offset_mm * (int32_t)scaled_mm2_peak_rate_mcps); + + tmp1 = (int32_t)scaled_mm1_peak_rate_mcps + (int32_t)scaled_mm2_peak_rate_mcps; + + if (tmp1 != 0) + tmp0 = (tmp0 * 4) / tmp1; +FAIL: + *prange_offset_mm = (int16_t)tmp0; + +} + +static VL53LX_Error select_offset_per_vcsel(VL53LX_LLDriverData_t *pdev, int16_t *poffset) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + int16_t tA, tB; + uint8_t isc; + + switch (pdev->preset_mode) { + case VL53LX_DEVICEPRESETMODE_HISTOGRAM_SHORT_RANGE: + tA = pdev->per_vcsel_cal_data.short_a_offset_mm; + tB = pdev->per_vcsel_cal_data.short_b_offset_mm; + break; + case VL53LX_DEVICEPRESETMODE_HISTOGRAM_MEDIUM_RANGE: + tA = pdev->per_vcsel_cal_data.medium_a_offset_mm; + tB = pdev->per_vcsel_cal_data.medium_b_offset_mm; + break; + case VL53LX_DEVICEPRESETMODE_HISTOGRAM_LONG_RANGE: + tA = pdev->per_vcsel_cal_data.long_a_offset_mm; + tB = pdev->per_vcsel_cal_data.long_b_offset_mm; + break; + default: + tA = pdev->per_vcsel_cal_data.long_a_offset_mm; + tB = pdev->per_vcsel_cal_data.long_b_offset_mm; + status = VL53LX_ERROR_INVALID_PARAMS; + *poffset = 0; + break; + } + + isc = pdev->ll_state.cfg_internal_stream_count; + if (status == VL53LX_ERROR_NONE) + *poffset = (isc & 0x01) ? tA : tB; + + return status; +} + +void VL53LX_calc_max_effective_spads(uint8_t encoded_zone_centre, uint8_t encoded_zone_size, uint8_t *pgood_spads, uint16_t aperture_attenuation, uint16_t *pmax_effective_spads) +{ + int16_t x = 0; + int16_t y = 0; + int16_t zone_x_ll = 0; + int16_t zone_y_ll = 0; + int16_t zone_x_ur = 0; + int16_t zone_y_ur = 0; + uint8_t spad_number = 0; + uint8_t byte_index = 0; + uint8_t bit_index = 0; + uint8_t bit_mask = 0; + uint8_t is_aperture = 0; + + VL53LX_decode_zone_limits(encoded_zone_centre, encoded_zone_size, &zone_x_ll, &zone_y_ll, &zone_x_ur, &zone_y_ur); + + *pmax_effective_spads = 0; + for (y = zone_y_ll; y <= zone_y_ur; y++) { + for (x = zone_x_ll; x <= zone_x_ur; x++) { + VL53LX_encode_row_col((uint8_t)y, (uint8_t)x, &spad_number); + VL53LX_spad_number_to_byte_bit_index(spad_number, &byte_index, &bit_index, &bit_mask); + if ((pgood_spads[byte_index] & bit_mask) > 0) { + is_aperture = VL53LX_is_aperture_location((uint8_t)y, (uint8_t)x); + if (is_aperture > 0) + *pmax_effective_spads += aperture_attenuation; + else + *pmax_effective_spads += 0x0100; + } + } + } +} + +VL53LX_Error VL53LX_get_dmax_calibration_data(VL53LX_DEV Dev, VL53LX_DeviceDmaxMode dmax_mode, VL53LX_dmax_calibration_data_t *pdmax_cal) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + switch (dmax_mode) { + case VL53LX_DEVICEDMAXMODE__CUST_CAL_DATA: + memcpy(pdmax_cal, &(pdev->cust_dmax_cal), sizeof(VL53LX_dmax_calibration_data_t)); + break; + case VL53LX_DEVICEDMAXMODE__FMT_CAL_DATA: + memcpy(pdmax_cal, &(pdev->fmt_dmax_cal), sizeof(VL53LX_dmax_calibration_data_t)); + break; + default: + status = VL53LX_ERROR_INVALID_PARAMS; + break; + } + return status; +} + +VL53LX_Error VL53LX_f_031(VL53LX_histogram_bin_data_t *pidata, VL53LX_histogram_bin_data_t *podata) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + uint8_t bin_initial_index[VL53LX_MAX_BIN_SEQUENCE_CODE+1]; + uint8_t bin_repeat_count[VL53LX_MAX_BIN_SEQUENCE_CODE+1]; + uint8_t bin_cfg = 0; + uint8_t bin_seq_length = 0; + int32_t repeat_count = 0; + uint8_t VL53LX_p_032 = 0; + uint8_t lc = 0; + uint8_t i = 0; + + memcpy(podata, pidata, sizeof(VL53LX_histogram_bin_data_t)); + + podata->VL53LX_p_021 = 0; + + for (lc = 0 ; lc < VL53LX_MAX_BIN_SEQUENCE_LENGTH ; lc++) + podata->bin_seq[lc] = VL53LX_MAX_BIN_SEQUENCE_CODE+1; + + for (lc = 0 ; lc < podata->VL53LX_p_020 ; lc++) + podata->bin_data[lc] = 0; + + for (lc = 0 ; lc <= VL53LX_MAX_BIN_SEQUENCE_CODE ; lc++) { + bin_initial_index[lc] = 0x00; + bin_repeat_count[lc] = 0x00; + } + + bin_seq_length = 0x00; + + for (lc = 0 ; lc < VL53LX_MAX_BIN_SEQUENCE_LENGTH ; lc++) { + bin_cfg = pidata->bin_seq[lc]; + + if (bin_repeat_count[bin_cfg] == 0) { + bin_initial_index[bin_cfg] = bin_seq_length * 4; + podata->bin_seq[bin_seq_length] = bin_cfg; + bin_seq_length++; + } + bin_repeat_count[bin_cfg]++; + + VL53LX_p_032 = bin_initial_index[bin_cfg]; + + for (i = 0 ; i < 4 ; i++) + podata->bin_data[VL53LX_p_032+i] += + pidata->bin_data[lc*4+i]; + + } + for (lc = 0 ; lc < VL53LX_MAX_BIN_SEQUENCE_LENGTH ; lc++) { + bin_cfg = podata->bin_seq[lc]; + + if (bin_cfg <= VL53LX_MAX_BIN_SEQUENCE_CODE) + podata->bin_rep[lc] = + bin_repeat_count[bin_cfg]; + else + podata->bin_rep[lc] = 0; + } + podata->VL53LX_p_021 = bin_seq_length * 4; + + for (lc = 0 ; lc <= VL53LX_MAX_BIN_SEQUENCE_CODE ; lc++) { + repeat_count = (int32_t)bin_repeat_count[lc]; + if (repeat_count > 0) { + VL53LX_p_032 = bin_initial_index[lc]; + for (i = 0 ; i < 4 ; i++) { + podata->bin_data[VL53LX_p_032+i] += (repeat_count/2); + podata->bin_data[VL53LX_p_032+i] /= repeat_count; + } + } + } + podata->number_of_ambient_bins = 0; + if ((bin_repeat_count[7] > 0) || (bin_repeat_count[15] > 0)) + podata->number_of_ambient_bins = 4; + + return status; +} + +VL53LX_Error VL53LX_f_032(uint32_t mean_offset, int16_t xgradient, int16_t ygradient, int8_t centre_offset_x, int8_t centre_offset_y, uint16_t roi_effective_spads, uint8_t roi_centre_spad, uint8_t roi_xy_size, uint32_t *xtalk_rate_kcps) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + uint8_t row = 0; + uint8_t col = 0; + int16_t bound_l_x = 0; + int16_t bound_r_x = 0; + int16_t bound_u_y = 0; + int16_t bound_d_y = 0; + int64_t xtalk_rate_ll = 0; + int64_t xtalk_rate_ur = 0; + int64_t xtalk_avg = 0; + + if (status == VL53LX_ERROR_NONE) { + VL53LX_decode_row_col(roi_centre_spad, &row, &col); + } + + if (status == VL53LX_ERROR_NONE) { + if ((((int16_t)roi_xy_size / 16) & 0x01) == 1) + bound_l_x = (int16_t) col - (((int16_t)roi_xy_size / 32) + 1); + else + bound_l_x = (int16_t) col - ((int16_t)roi_xy_size / 32); + + bound_r_x = (int16_t) col + ((int16_t)roi_xy_size / 32); + + if ((((int16_t)roi_xy_size) & 0x01) == 1) + bound_d_y = (int16_t) row - ((((int16_t)roi_xy_size & 0x0f) / 2) + 1); + else + bound_d_y = (int16_t) row - (((int16_t)roi_xy_size & 0x0f) / 2); + + bound_u_y = (int16_t) row + (((int16_t)roi_xy_size & 0xf) / 2); + } + + if (status == VL53LX_ERROR_NONE) { + bound_l_x = (2 * bound_l_x) - 15 + (2 * (int16_t)centre_offset_x); + bound_r_x = (2 * bound_r_x) - 15 + (2 * (int16_t)centre_offset_x); + bound_u_y = (2 * bound_u_y) - 15 + (2 * (int16_t)centre_offset_y); + bound_d_y = (2 * bound_d_y) - 15 + (2 * (int16_t)centre_offset_y); + } + + if (status == VL53LX_ERROR_NONE) { + xtalk_rate_ll = ((int64_t)bound_l_x * ((int64_t)xgradient)) + ((int64_t)bound_d_y * ((int64_t)ygradient)); + xtalk_rate_ll = do_division_s((xtalk_rate_ll + 1), 2); + xtalk_rate_ll += ((int64_t)mean_offset * 4); + + xtalk_rate_ur = ((int64_t)bound_r_x * ((int64_t)xgradient)) + ((int64_t)bound_u_y * ((int64_t)ygradient)); + xtalk_rate_ur = do_division_s((xtalk_rate_ur + 1), 2); + xtalk_rate_ur += ((int64_t)mean_offset * 4); + } + + if (status == VL53LX_ERROR_NONE) + xtalk_avg = do_division_s(((xtalk_rate_ll + xtalk_rate_ur) + 1), 2); + + if (status == VL53LX_ERROR_NONE) + if (xtalk_avg < 0) + xtalk_avg = 0; + + *xtalk_rate_kcps = (uint32_t) xtalk_avg; + return status; +} + +VL53LX_Error VL53LX_f_033(VL53LX_histogram_bin_data_t *phist_data, VL53LX_xtalk_histogram_shape_t *pxtalk_data, uint32_t xtalk_rate_kcps, VL53LX_histogram_bin_data_t *pxtalkcount_data) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + uint64_t xtalk_events_per_spad = 0; + uint64_t xtalk_total_events = 0; + uint64_t xtalk_temp_bin = 0; + uint8_t i = 0; + + xtalk_events_per_spad = do_division_u((((uint64_t)xtalk_rate_kcps * (uint64_t)phist_data->peak_duration_us) + 500), 1000); + + xtalk_total_events = xtalk_events_per_spad * (uint64_t)phist_data->result__dss_actual_effective_spads; + xtalk_total_events = do_division_u((xtalk_total_events), 256); + xtalk_total_events = do_division_u((xtalk_total_events + 1024), 2048); + + if (xtalk_total_events > 0xFFFFFFFF) + xtalk_total_events = 0xFFFFFFFF; + + for (i = 0; i < pxtalk_data->VL53LX_p_021; i++) { + xtalk_temp_bin = (uint64_t)pxtalk_data->bin_data[i] * (uint64_t)xtalk_total_events; + xtalk_temp_bin = do_division_u((xtalk_temp_bin + 512), 1024); + pxtalkcount_data->bin_data[i] = (uint32_t)xtalk_temp_bin; + } + return status; +} + +void VL53LX_copy_xtalk_bin_data_to_histogram_data_struct(VL53LX_xtalk_histogram_shape_t *pxtalk, VL53LX_histogram_bin_data_t *phist) +{ + phist->cal_config__vcsel_start = pxtalk->cal_config__vcsel_start; + phist->VL53LX_p_015 = pxtalk->VL53LX_p_015; + phist->VL53LX_p_019 = pxtalk->VL53LX_p_019; + + phist->phasecal_result__reference_phase = pxtalk->phasecal_result__reference_phase; + phist->phasecal_result__vcsel_start = pxtalk->phasecal_result__vcsel_start; + + phist->vcsel_width = pxtalk->vcsel_width; + phist->zero_distance_phase = pxtalk->zero_distance_phase; + + phist->zone_id = pxtalk->zone_id; + phist->VL53LX_p_020 = pxtalk->VL53LX_p_020; + phist->time_stamp = pxtalk->time_stamp; +} + +void VL53LX_f_003(VL53LX_hist_gen3_algo_private_data_t *palgo) +{ + uint8_t lb = 0; + palgo->VL53LX_p_020 = VL53LX_HISTOGRAM_BUFFER_SIZE; + palgo->VL53LX_p_019 = 0; + palgo->VL53LX_p_021 = 0; + palgo->VL53LX_p_039 = 0; + palgo->VL53LX_p_028 = 0; + palgo->VL53LX_p_031 = 0; + + for (lb = palgo->VL53LX_p_019; lb < palgo->VL53LX_p_020; lb++) { + palgo->VL53LX_p_040[lb] = 0; + palgo->VL53LX_p_041[lb] = 0; + palgo->VL53LX_p_042[lb] = 0; + palgo->VL53LX_p_043[lb] = 0; + palgo->VL53LX_p_018[lb] = 0; + } + palgo->VL53LX_p_044 = 0; + palgo->VL53LX_p_045 = VL53LX_D_001; + palgo->VL53LX_p_046 = 0; + + VL53LX_init_histogram_bin_data_struct(0, VL53LX_HISTOGRAM_BUFFER_SIZE, &(palgo->VL53LX_p_006)); + VL53LX_init_histogram_bin_data_struct(0, VL53LX_HISTOGRAM_BUFFER_SIZE, &(palgo->VL53LX_p_047)); + VL53LX_init_histogram_bin_data_struct(0, VL53LX_HISTOGRAM_BUFFER_SIZE, &(palgo->VL53LX_p_048)); + VL53LX_init_histogram_bin_data_struct(0, VL53LX_HISTOGRAM_BUFFER_SIZE, &(palgo->VL53LX_p_049)); + VL53LX_init_histogram_bin_data_struct(0, VL53LX_HISTOGRAM_BUFFER_SIZE, &(palgo->VL53LX_p_050)); +} + +void VL53LX_hist_find_min_max_bin_values(VL53LX_histogram_bin_data_t *pdata) +{ + uint8_t bin = 0; + + for (bin = 0; bin < pdata->VL53LX_p_021; bin++) { + if (bin == 0 || pdata->min_bin_value >= pdata->bin_data[bin]) + pdata->min_bin_value = pdata->bin_data[bin]; + + if (bin == 0 || pdata->max_bin_value <= pdata->bin_data[bin]) + pdata->max_bin_value = pdata->bin_data[bin]; + } +} + +uint32_t VL53LX_isqrt(uint32_t num) +{ + uint32_t res = 0; + uint32_t bit = 1 << 30; + + while (bit > num) + bit >>= 2; + + while (bit != 0) { + if (num >= res + bit) { + num -= res + bit; + res = (res >> 1) + bit; + } else { + res >>= 1; + } + bit >>= 2; + } + + return res; +} + + +void VL53LX_hist_estimate_ambient_from_thresholded_bins(int32_t ambient_threshold_sigma, VL53LX_histogram_bin_data_t *pdata) +{ + uint8_t bin = 0; + int32_t VL53LX_p_031 = 0; + + VL53LX_hist_find_min_max_bin_values(pdata); + + VL53LX_p_031 = (int32_t)VL53LX_isqrt((uint32_t)pdata->min_bin_value); + VL53LX_p_031 *= ambient_threshold_sigma; + VL53LX_p_031 += 0x07; + VL53LX_p_031 = VL53LX_p_031 >> 4; + VL53LX_p_031 += pdata->min_bin_value; + + pdata->number_of_ambient_samples = 0; + pdata->ambient_events_sum = 0; + + for (bin = 0; bin < pdata->VL53LX_p_021; bin++) { + if (pdata->bin_data[bin] < VL53LX_p_031) { + pdata->ambient_events_sum += pdata->bin_data[bin]; + pdata->number_of_ambient_samples++; + } + } + + if (pdata->number_of_ambient_samples > 0) { + pdata->VL53LX_p_028 = pdata->ambient_events_sum; + pdata->VL53LX_p_028 += ((int32_t)pdata->number_of_ambient_samples/2); + pdata->VL53LX_p_028 /= (int32_t)pdata->number_of_ambient_samples; + } +} + +void VL53LX_hist_remove_ambient_bins(VL53LX_histogram_bin_data_t *pdata) +{ + uint8_t bin = 0; + uint8_t lc = 0; + uint8_t i = 0; + + if ((pdata->bin_seq[0] & 0x07) == 0x07) { + i = 0; + for (lc = 0; lc < VL53LX_MAX_BIN_SEQUENCE_LENGTH; lc++) { + if ((pdata->bin_seq[lc] & 0x07) != 0x07) { + pdata->bin_seq[i] = pdata->bin_seq[lc]; + pdata->bin_rep[i] = pdata->bin_rep[lc]; + i++; + } + } + for (lc = i; lc < VL53LX_MAX_BIN_SEQUENCE_LENGTH; lc++) { + pdata->bin_seq[lc] = VL53LX_MAX_BIN_SEQUENCE_CODE + 1; + pdata->bin_rep[lc] = 0; + } + } + if (pdata->number_of_ambient_bins > 0) { + for (bin = pdata->number_of_ambient_bins; bin < pdata->VL53LX_p_020; bin++) { + pdata->bin_data[bin-pdata->number_of_ambient_bins] = pdata->bin_data[bin]; + } + pdata->VL53LX_p_021 = pdata->VL53LX_p_021 - pdata->number_of_ambient_bins; + pdata->number_of_ambient_bins = 0; + } +} + +int8_t VL53LX_f_030(VL53LX_histogram_bin_data_t *pdata1, VL53LX_histogram_bin_data_t *pdata2) +{ + int32_t phase_delta = 0; + int8_t bin_offset = 0; + uint32_t period = 0; + uint32_t remapped_phase = 0; + + period = 2048 * (uint32_t)VL53LX_decode_vcsel_period(pdata1->VL53LX_p_005); + + if (period != 0) + remapped_phase = (uint32_t)pdata2->zero_distance_phase % period; + + phase_delta = (int32_t)pdata1->zero_distance_phase - (int32_t)remapped_phase; + + if (phase_delta > 0) + bin_offset = (int8_t)((phase_delta + 1024) / 2048); + else + bin_offset = (int8_t)((phase_delta - 1024) / 2048); + + return bin_offset; +} + +void VL53LX_f_005(VL53LX_histogram_bin_data_t *pxtalk, VL53LX_histogram_bin_data_t *pbins, VL53LX_histogram_bin_data_t *pxtalk_realigned) +{ + uint8_t i = 0; + uint8_t min_bins = 0; + int8_t bin_offset = 0; + int8_t bin_access = 0; + + memcpy(pxtalk_realigned, pbins, sizeof(VL53LX_histogram_bin_data_t)); + + for (i = 0 ; i < pxtalk_realigned->VL53LX_p_020 ; i++) + pxtalk_realigned->bin_data[i] = 0; + + bin_offset = VL53LX_f_030(pbins, pxtalk); + + if (pxtalk->VL53LX_p_021 < pbins->VL53LX_p_021) + min_bins = pxtalk->VL53LX_p_021; + else + min_bins = pbins->VL53LX_p_021; + + for (i = 0 ; i < min_bins ; i++) { + if (bin_offset >= 0) + bin_access = ((int8_t)i + (int8_t)bin_offset) % (int8_t)pbins->VL53LX_p_021; + else + bin_access = ((int8_t)pbins->VL53LX_p_021 + ((int8_t)i + (int8_t)bin_offset)) % (int8_t)pbins->VL53LX_p_021; + + if (pbins->bin_data[(uint8_t)bin_access] > pxtalk->bin_data[i]) { + pbins->bin_data[(uint8_t)bin_access] = pbins->bin_data[(uint8_t)bin_access] - pxtalk->bin_data[i]; + } else { + pbins->bin_data[(uint8_t)bin_access] = 0; + } + pxtalk_realigned->bin_data[(uint8_t)bin_access] = pxtalk->bin_data[i]; + + + + } +} + +uint16_t VL53LX_rate_maths(int32_t VL53LX_p_018, uint32_t time_us) +{ + uint32_t tmp_int = 0; + uint32_t frac_bits = 7; + uint16_t rate_mcps = 0; + + if (VL53LX_p_018 > VL53LX_SPAD_TOTAL_COUNT_MAX) + tmp_int = VL53LX_SPAD_TOTAL_COUNT_MAX; + else if (VL53LX_p_018 > 0) + tmp_int = (uint32_t)VL53LX_p_018; + + if (VL53LX_p_018 > VL53LX_SPAD_TOTAL_COUNT_RES_THRES) + frac_bits = 3; + else + frac_bits = 7; + + if (time_us > 0) + tmp_int = ((tmp_int << frac_bits) + (time_us / 2)) / time_us; + + if (VL53LX_p_018 > VL53LX_SPAD_TOTAL_COUNT_RES_THRES) + tmp_int = tmp_int << 4; + + if (tmp_int > 0xFFFF) + tmp_int = 0xFFFF; + + rate_mcps = (uint16_t)tmp_int; + return rate_mcps; +} + +uint32_t VL53LX_events_per_spad_maths(int32_t VL53LX_p_010, uint16_t num_spads, uint32_t duration) +{ + uint64_t total_hist_counts = 0; + uint64_t xtalk_per_spad = 0; + uint32_t rate_per_spad_kcps = 0; + uint64_t dividend = ((uint64_t)VL53LX_p_010 * 1000 * 256); + + if (num_spads != 0) + total_hist_counts = do_division_u(dividend, (uint64_t)num_spads); + + if (duration > 0) { + uint64_t dividend = (((uint64_t)(total_hist_counts << 11)) + ((uint64_t)duration / 2)); + xtalk_per_spad = do_division_u(dividend, (uint64_t)duration); + } else { + xtalk_per_spad = (uint64_t)(total_hist_counts << 11); + } + rate_per_spad_kcps = (uint32_t)xtalk_per_spad; + return rate_per_spad_kcps; +} + +uint32_t VL53LX_f_002(uint32_t events_threshold, uint32_t ref_signal_events, uint32_t ref_distance_mm, uint32_t signal_thresh_sigma) +{ + uint32_t tmp32 = 0; + uint32_t range_mm = 0; + + tmp32 = 4 * events_threshold; + tmp32 += ((uint32_t)signal_thresh_sigma * (uint32_t)signal_thresh_sigma); + tmp32 = VL53LX_isqrt(tmp32); + tmp32 += (uint32_t)signal_thresh_sigma; + + range_mm = (uint32_t)VL53LX_isqrt(ref_signal_events << 4); + range_mm *= ref_distance_mm; + if (tmp32 != 0) { + range_mm += (tmp32); + range_mm /= (2*tmp32); + } + return range_mm; +} + +VL53LX_Error VL53LX_f_001( + uint16_t target_reflectance, + VL53LX_dmax_calibration_data_t *pcal, + VL53LX_hist_gen3_dmax_config_t *pcfg, + VL53LX_histogram_bin_data_t *pbins, + VL53LX_hist_gen3_dmax_private_data_t *pdata, + int16_t *pambient_dmax_mm) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + uint32_t pll_period_us = 0; + uint32_t periods_elapsed = 0; + uint32_t tmp32 = 0; + uint64_t tmp64 = 0; + uint32_t amb_thres_delta = 0; + + pdata->VL53LX_p_004 = 0x0000; + pdata->VL53LX_p_033 = 0x0000; + pdata->VL53LX_p_034 = 0x0000; + pdata->VL53LX_p_009 = 0x0000; + pdata->VL53LX_p_028 = 0x0000; + pdata->VL53LX_p_035 = 0x0000; + pdata->VL53LX_p_036 = 0; + pdata->VL53LX_p_022 = 0; + *pambient_dmax_mm = 0; + + if ((pbins->VL53LX_p_015 != 0) && (pbins->total_periods_elapsed != 0)) { + pll_period_us = VL53LX_calc_pll_period_us(pbins->VL53LX_p_015); + periods_elapsed = pbins->total_periods_elapsed + 1; + pdata->VL53LX_p_037 = VL53LX_duration_maths(pll_period_us, 1<<4, VL53LX_RANGING_WINDOW_VCSEL_PERIODS, periods_elapsed); + pdata->VL53LX_p_034 = VL53LX_rate_maths(pbins->VL53LX_p_028, pdata->VL53LX_p_037); + pdata->VL53LX_p_033 = VL53LX_events_per_spad_maths(pbins->VL53LX_p_028, pbins->result__dss_actual_effective_spads, pdata->VL53LX_p_037); + pdata->VL53LX_p_038 = pcfg->max_effective_spads; + pdata->VL53LX_p_004 = pcfg->max_effective_spads; + + if (pdata->VL53LX_p_033 > 0) { + tmp64 = (uint64_t)pcfg->dss_config__target_total_rate_mcps; + tmp64 *= 1000; + tmp64 <<= (11+1); + tmp32 = pdata->VL53LX_p_033/2; + tmp64 += (uint64_t)tmp32; + tmp64 = do_division_u(tmp64, (uint64_t)pdata->VL53LX_p_033); + if (tmp64 < (uint64_t)pcfg->max_effective_spads) + pdata->VL53LX_p_004 = (uint16_t)tmp64; + } + } + if ((pcal->ref__actual_effective_spads != 0) && (pbins->VL53LX_p_015 != 0) && (pcal->ref_reflectance_pc != 0) && (pbins->total_periods_elapsed != 0)) { + tmp64 = (uint64_t)pcal->ref__peak_signal_count_rate_mcps; + tmp64 *= (1000 * 256); + tmp32 = pcal->ref__actual_effective_spads/2; + tmp64 += (uint64_t)tmp32; + tmp64 = do_division_u(tmp64, (uint64_t)pcal->ref__actual_effective_spads); + + pdata->VL53LX_p_009 = (uint32_t)tmp64; + pdata->VL53LX_p_009 <<= 4; + + tmp64 = (uint64_t)pdata->VL53LX_p_037; + tmp64 *= (uint64_t)pdata->VL53LX_p_033; + tmp64 *= (uint64_t)pdata->VL53LX_p_004; + tmp64 += (1<<(11+7)); + tmp64 >>= (11+8); + tmp64 += 500; + tmp64 = do_division_u(tmp64, 1000); + + if (tmp64 > 0x00FFFFFF) + tmp64 = 0x00FFFFFF; + + pdata->VL53LX_p_028 = (uint32_t)tmp64; + tmp64 = (uint64_t)pdata->VL53LX_p_037; + tmp64 *= (uint64_t)pdata->VL53LX_p_009; + tmp64 *= (uint64_t)pdata->VL53LX_p_004; + tmp64 += (1<<(11+7)); + tmp64 >>= (11+8); + tmp64 *= ((uint64_t)target_reflectance * (uint64_t)pcal->coverglass_transmission); + tmp64 += ((uint64_t)pcal->ref_reflectance_pc * 128); + tmp64 = do_division_u(tmp64, ((uint64_t)pcal->ref_reflectance_pc * 256)); + tmp64 += 500; + tmp64 = do_division_u(tmp64, 1000); + if (tmp64 > 0x00FFFFFF) + tmp64 = 0x00FFFFFF; + pdata->VL53LX_p_035 = (uint32_t)tmp64; + tmp32 = VL53LX_isqrt(pdata->VL53LX_p_028 << 8); + tmp32 *= (uint32_t)pcfg->ambient_thresh_sigma; + if (pdata->VL53LX_p_028 < (uint32_t)pcfg->min_ambient_thresh_events) { + amb_thres_delta = pcfg->min_ambient_thresh_events - (uint32_t)pdata->VL53LX_p_028; + amb_thres_delta <<= 8; + if (tmp32 < amb_thres_delta) + tmp32 = amb_thres_delta; + } + pdata->VL53LX_p_022 = (int16_t)VL53LX_f_002(tmp32, pdata->VL53LX_p_035, (uint32_t)pcal->ref__distance_mm, (uint32_t)pcfg->signal_thresh_sigma); + + tmp32 = (uint32_t)pdata->VL53LX_p_035; + tmp32 *= (uint32_t)pbins->vcsel_width; + tmp32 += (1 << 3); + tmp32 /= (1 << 4); + + pdata->VL53LX_p_036 = (int16_t)VL53LX_f_002(256 * (uint32_t)pcfg->signal_total_events_limit, tmp32, (uint32_t)pcal->ref__distance_mm, (uint32_t)pcfg->signal_thresh_sigma); + + if (pdata->VL53LX_p_036 < pdata->VL53LX_p_022) + *pambient_dmax_mm = pdata->VL53LX_p_036; + else + *pambient_dmax_mm = pdata->VL53LX_p_022; + } + return status; +} + +VL53LX_Error VL53LX_f_006( + uint16_t ambient_threshold_events_scaler, + int32_t ambient_threshold_sigma, + int32_t min_ambient_threshold_events, + uint8_t algo__crosstalk_compensation_enable, + VL53LX_histogram_bin_data_t *pbins, + VL53LX_histogram_bin_data_t *pxtalk, + VL53LX_hist_gen3_algo_private_data_t *palgo) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + uint8_t lb = 0; + uint8_t VL53LX_p_001 = 0; + int64_t tmp = 0; + int32_t amb_events = 0; + int32_t VL53LX_p_018 = 0; + int32_t samples = 0; + + palgo->VL53LX_p_020 = pbins->VL53LX_p_020; + palgo->VL53LX_p_019 = pbins->VL53LX_p_019; + palgo->VL53LX_p_021 = pbins->VL53LX_p_021; + palgo->VL53LX_p_028 = pbins->VL53LX_p_028; + palgo->VL53LX_p_030 = VL53LX_decode_vcsel_period(pbins->VL53LX_p_005); + + tmp = (int64_t)pbins->VL53LX_p_028; + tmp *= (int64_t)ambient_threshold_events_scaler; + tmp += 2048; + tmp = do_division_s(tmp, 4096); + amb_events = (int32_t)tmp; + + for (lb = 0; lb < pbins->VL53LX_p_021; lb++) { + VL53LX_p_001 = lb >> 2; + samples = (int32_t)pbins->bin_rep[VL53LX_p_001]; + if (samples > 0) { + if (lb < pxtalk->VL53LX_p_021 && algo__crosstalk_compensation_enable > 0) + VL53LX_p_018 = samples * (amb_events + pxtalk->bin_data[lb]); + else + VL53LX_p_018 = samples * amb_events; + VL53LX_p_018 = VL53LX_isqrt(VL53LX_p_018); + VL53LX_p_018 += (samples/2); + VL53LX_p_018 /= samples; + VL53LX_p_018 *= ambient_threshold_sigma; + VL53LX_p_018 += 8; + VL53LX_p_018 /= 16; + VL53LX_p_018 += amb_events; + if (VL53LX_p_018 < min_ambient_threshold_events) + VL53LX_p_018 = min_ambient_threshold_events; + palgo->VL53LX_p_052[lb] = VL53LX_p_018; + palgo->VL53LX_p_031 = VL53LX_p_018; + } + } + palgo->VL53LX_p_039 = 0; + for (lb = pbins->VL53LX_p_019; lb < pbins->VL53LX_p_021; lb++) { + if (pbins->bin_data[lb] > palgo->VL53LX_p_052[lb]) { + palgo->VL53LX_p_040[lb] = 1; + palgo->VL53LX_p_041[lb] = 1; + palgo->VL53LX_p_039++; + } else { + palgo->VL53LX_p_040[lb] = 0; + palgo->VL53LX_p_041[lb] = 0; + } + } + return status; +} + +VL53LX_Error VL53LX_f_007(VL53LX_hist_gen3_algo_private_data_t *palgo) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + uint8_t i = 0; + uint8_t j = 0; + uint8_t found = 0; + + palgo->VL53LX_p_044 = 0; + for (i = 0; i < palgo->VL53LX_p_030; i++) { + j = (i + 1) % palgo->VL53LX_p_030; + if (i < palgo->VL53LX_p_021 && j < palgo->VL53LX_p_021) { + if (palgo->VL53LX_p_041[i] == 0 && palgo->VL53LX_p_041[j] == 1 && found == 0) { + palgo->VL53LX_p_044 = i; + found = 1; + } + } + } + return status; +} + +VL53LX_Error VL53LX_f_008(VL53LX_hist_gen3_algo_private_data_t *palgo) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + uint8_t i = 0; + uint8_t j = 0; + uint8_t lb = 0; + + for (lb = palgo->VL53LX_p_044; lb < (palgo->VL53LX_p_044 + palgo->VL53LX_p_030); lb++) { + i = lb % palgo->VL53LX_p_030; + j = (lb + 1) % palgo->VL53LX_p_030; + if (i < palgo->VL53LX_p_021 && j < palgo->VL53LX_p_021) { + if (palgo->VL53LX_p_041[i] == 0 && palgo->VL53LX_p_041[j] == 1) + palgo->VL53LX_p_046++; + if (palgo->VL53LX_p_046 > palgo->VL53LX_p_045) + palgo->VL53LX_p_046 = palgo->VL53LX_p_045; + if (palgo->VL53LX_p_041[i] > 0) + palgo->VL53LX_p_042[i] = palgo->VL53LX_p_046; + else + palgo->VL53LX_p_042[i] = 0; + } + } + return status; +} + +VL53LX_Error VL53LX_f_009(VL53LX_hist_gen3_algo_private_data_t *palgo) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + uint8_t i = 0; + uint8_t j = 0; + uint8_t blb = 0; + uint8_t pulse_no = 0; + uint8_t max_filter_half_width = 0; + VL53LX_hist_pulse_data_t *pdata; + + max_filter_half_width = palgo->VL53LX_p_030 - 1; + max_filter_half_width = max_filter_half_width >> 1; + + for (blb = palgo->VL53LX_p_044; blb < (palgo->VL53LX_p_044 + palgo->VL53LX_p_030); blb++) { + i = blb % palgo->VL53LX_p_030; + j = (blb + 1) % palgo->VL53LX_p_030; + + if (i < palgo->VL53LX_p_021 && j < palgo->VL53LX_p_021) { + if (palgo->VL53LX_p_042[i] == 0 && palgo->VL53LX_p_042[j] > 0) { + pulse_no = palgo->VL53LX_p_042[j] - 1; + if (pulse_no < palgo->VL53LX_p_045) { + pdata = &(palgo->VL53LX_p_003[pulse_no]); + pdata->VL53LX_p_012 = blb; + pdata->VL53LX_p_019 = blb + 1; + pdata->VL53LX_p_023 = 0xFF; + pdata->VL53LX_p_024 = 0; + pdata->VL53LX_p_013 = 0; + } + } + if (palgo->VL53LX_p_042[i] > 0 && palgo->VL53LX_p_042[j] == 0) { + pulse_no = palgo->VL53LX_p_042[i] - 1; + if (pulse_no < palgo->VL53LX_p_045) { + pdata = &(palgo->VL53LX_p_003[pulse_no]); + pdata->VL53LX_p_024 = blb; + pdata->VL53LX_p_013 = blb + 1; + pdata->VL53LX_p_025 = (pdata->VL53LX_p_024 + 1) - pdata->VL53LX_p_019; + pdata->VL53LX_p_051 = (pdata->VL53LX_p_013 + 1) - pdata->VL53LX_p_012; + if (pdata->VL53LX_p_051 > max_filter_half_width) + pdata->VL53LX_p_051 = max_filter_half_width; + } + } + } + } + return status; +} + +VL53LX_Error VL53LX_f_010(uint8_t pulse_no, VL53LX_histogram_bin_data_t *pbins, VL53LX_hist_gen3_algo_private_data_t *palgo) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + uint8_t i = 0; + uint8_t lb = 0; + + VL53LX_hist_pulse_data_t *pdata = &(palgo->VL53LX_p_003[pulse_no]); + pdata->VL53LX_p_017 = 0; + pdata->VL53LX_p_016 = 0; + + for (lb = pdata->VL53LX_p_012; lb <= pdata->VL53LX_p_013; lb++) { + i = lb % palgo->VL53LX_p_030; + pdata->VL53LX_p_017 += pbins->bin_data[i]; + pdata->VL53LX_p_016 += palgo->VL53LX_p_028; + } + pdata->VL53LX_p_010 = pdata->VL53LX_p_017 - pdata->VL53LX_p_016; + return status; +} + +VL53LX_Error VL53LX_f_011( + uint8_t pulse_no, + VL53LX_histogram_bin_data_t *pbins, + VL53LX_hist_gen3_algo_private_data_t *palgo, + int32_t pad_value, + VL53LX_histogram_bin_data_t *ppulse) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + uint8_t i = 0; + uint8_t lb = 0; + VL53LX_hist_pulse_data_t *pdata = &(palgo->VL53LX_p_003[pulse_no]); + + memcpy(ppulse, pbins, sizeof(VL53LX_histogram_bin_data_t)); + + for (lb = palgo->VL53LX_p_044; lb < (palgo->VL53LX_p_044 + palgo->VL53LX_p_030); lb++) { + if (lb < pdata->VL53LX_p_012 || lb > pdata->VL53LX_p_013) { + i = lb % palgo->VL53LX_p_030; + if (i < ppulse->VL53LX_p_021) + ppulse->bin_data[i] = pad_value; + } + } + return status; +} + +void VL53LX_f_022(uint8_t VL53LX_p_032, uint8_t filter_woi, VL53LX_histogram_bin_data_t *pbins, int32_t *pa, int32_t *pb, int32_t *pc) +{ + uint8_t w = 0; + uint8_t j = 0; + + *pa = 0; + *pb = pbins->bin_data[VL53LX_p_032]; + *pc = 0; + + for (w = 0 ; w < ((filter_woi << 1)+1) ; w++) { + j = ((VL53LX_p_032 + w + pbins->VL53LX_p_021) - filter_woi) % pbins->VL53LX_p_021; + if (w < filter_woi) + *pa += pbins->bin_data[j]; + else if (w > filter_woi) + *pc += pbins->bin_data[j]; + } +} + +VL53LX_Error VL53LX_f_026( + uint8_t pulse_no, + VL53LX_histogram_bin_data_t *ppulse, + VL53LX_hist_gen3_algo_private_data_t *palgo3, + VL53LX_hist_gen4_algo_filtered_data_t *pfiltered) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_hist_pulse_data_t *pdata = &(palgo3->VL53LX_p_003[pulse_no]); + + uint8_t lb = 0; + uint8_t i = 0; + int32_t suma = 0; + int32_t sumb = 0; + int32_t sumc = 0; + + pfiltered->VL53LX_p_020 = palgo3->VL53LX_p_020; + pfiltered->VL53LX_p_019 = palgo3->VL53LX_p_019; + pfiltered->VL53LX_p_021 = palgo3->VL53LX_p_021; + + for (lb = pdata->VL53LX_p_012; lb <= pdata->VL53LX_p_013; lb++) { + i = lb % palgo3->VL53LX_p_030; + VL53LX_f_022(i, pdata->VL53LX_p_051, ppulse, &suma, &sumb, &sumc); + + pfiltered->VL53LX_p_007[i] = suma; + pfiltered->VL53LX_p_032[i] = sumb; + pfiltered->VL53LX_p_001[i] = sumc; + pfiltered->VL53LX_p_053[i] = (suma + sumb) - (sumc + palgo3->VL53LX_p_028); + pfiltered->VL53LX_p_054[i] = (sumb + sumc) - (suma + palgo3->VL53LX_p_028); + } + return status; +} + +VL53LX_Error VL53LX_f_028( + uint8_t bin, + int32_t VL53LX_p_007, + int32_t VL53LX_p_032, + int32_t VL53LX_p_001, + int32_t ax, + int32_t bx, + int32_t cx, + int32_t VL53LX_p_028, + uint8_t VL53LX_p_030, + uint32_t *pmean_phase) +{ + VL53LX_Error status = VL53LX_ERROR_DIVISION_BY_ZERO; + + int64_t mean_phase = VL53LX_MAX_ALLOWED_PHASE; + int32_t mean_phase32; + int64_t VL53LX_p_055 = 0; + int64_t half_b_minus_amb = 0; + + VL53LX_p_055 = 4096 * ((int64_t)VL53LX_p_001 - (int64_t)cx - (int64_t)VL53LX_p_007 - (int64_t)ax); + half_b_minus_amb = 4096 * ((int64_t)VL53LX_p_032 - (int64_t)bx - (int64_t)VL53LX_p_028); + + if (half_b_minus_amb != 0) { + mean_phase = (4096 * VL53LX_p_055) + half_b_minus_amb; + mean_phase = do_division_s(mean_phase, (half_b_minus_amb * 2)); + mean_phase += 2048; + mean_phase += (4096 * (int64_t)bin); + mean_phase = do_division_s((mean_phase + 1), 2); + if (mean_phase < 0) + mean_phase = 0; + if (mean_phase > VL53LX_MAX_ALLOWED_PHASE) + mean_phase = VL53LX_MAX_ALLOWED_PHASE; + mean_phase32 = (int32_t)mean_phase; + mean_phase32 = mean_phase32 % ((int32_t)VL53LX_p_030 * 2048); + mean_phase = mean_phase32; + status = VL53LX_ERROR_NONE; + } + *pmean_phase = (uint32_t)mean_phase; + return status; +} + +VL53LX_Error VL53LX_f_027(uint8_t pulse_no, uint16_t noise_threshold, VL53LX_hist_gen4_algo_filtered_data_t *pfiltered, VL53LX_hist_gen3_algo_private_data_t *palgo3) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_Error func_status = VL53LX_ERROR_NONE; + VL53LX_hist_pulse_data_t *pdata = &(palgo3->VL53LX_p_003[pulse_no]); + + uint8_t lb = 0; + uint8_t i = 0; + uint8_t j = 0; + + for (lb = pdata->VL53LX_p_012; lb < pdata->VL53LX_p_013; lb++) { + i = lb % palgo3->VL53LX_p_030; + j = (lb+1) % palgo3->VL53LX_p_030; + if (i < palgo3->VL53LX_p_021 && j < palgo3->VL53LX_p_021) { + if (pfiltered->VL53LX_p_053[i] == 0 && pfiltered->VL53LX_p_054[i] == 0) + pfiltered->VL53LX_p_040[i] = 0; + else if (pfiltered->VL53LX_p_053[i] >= 0 && pfiltered->VL53LX_p_054[i] >= 0) + pfiltered->VL53LX_p_040[i] = 1; + else if (pfiltered->VL53LX_p_053[i] < 0 && pfiltered->VL53LX_p_054[i] >= 0 && pfiltered->VL53LX_p_053[j] >= 0 && pfiltered->VL53LX_p_054[j] < 0) + pfiltered->VL53LX_p_040[i] = 1; + else + pfiltered->VL53LX_p_040[i] = 0; + + if (pfiltered->VL53LX_p_040[i] > 0) { + pdata->VL53LX_p_023 = lb; + func_status = + VL53LX_f_028( + lb, + pfiltered->VL53LX_p_007[i], + pfiltered->VL53LX_p_032[i], + pfiltered->VL53LX_p_001[i], + 0, + 0, + 0, + palgo3->VL53LX_p_028, + palgo3->VL53LX_p_030, + &(pdata->VL53LX_p_011)); + + if (func_status == + VL53LX_ERROR_DIVISION_BY_ZERO) + pfiltered->VL53LX_p_040[i] = 0; + + } + } + } + return status; +} + +uint32_t VL53LX_calc_pll_period_mm(uint16_t fast_osc_frequency) +{ + uint32_t pll_period_us = 0; + uint32_t pll_period_mm = 0; + + pll_period_us = VL53LX_calc_pll_period_us(fast_osc_frequency); + pll_period_mm = VL53LX_SPEED_OF_LIGHT_IN_AIR_DIV_8 * (pll_period_us >> 2); + pll_period_mm = (pll_period_mm + (0x01<<15)) >> 16; + + return pll_period_mm; +} + +VL53LX_Error VL53LX_f_023( + uint8_t sigma_estimator__sigma_ref_mm, + uint32_t VL53LX_p_007, + uint32_t VL53LX_p_032, + uint32_t VL53LX_p_001, + uint32_t a_zp, + uint32_t c_zp, + uint32_t bx, + uint32_t ax_zp, + uint32_t cx_zp, + uint32_t VL53LX_p_028, + uint16_t fast_osc_frequency, + uint16_t *psigma_est) +{ + VL53LX_Error status = VL53LX_ERROR_DIVISION_BY_ZERO; + uint32_t sigma_int = VL53LX_D_002; + uint32_t pll_period_mm = 0; + uint64_t tmp0 = 0; + uint64_t tmp1 = 0; + uint64_t b_minus_amb = 0; + uint64_t VL53LX_p_055 = 0; + *psigma_est = VL53LX_D_002; + if (fast_osc_frequency != 0) { + pll_period_mm = VL53LX_calc_pll_period_mm(fast_osc_frequency); + + if (VL53LX_p_028 > VL53LX_p_032) + b_minus_amb = (uint64_t)VL53LX_p_028 - (uint64_t)VL53LX_p_032; + else + b_minus_amb = (uint64_t)VL53LX_p_032 - (uint64_t)VL53LX_p_028; + + if (VL53LX_p_007 > VL53LX_p_001) + VL53LX_p_055 = (uint64_t)VL53LX_p_007 - (uint64_t)VL53LX_p_001; + else + VL53LX_p_055 = (uint64_t)VL53LX_p_001 - (uint64_t)VL53LX_p_007; + + if (b_minus_amb != 0) { + tmp0 = (uint64_t)VL53LX_p_032 + (uint64_t)bx + (uint64_t)VL53LX_p_028; + if (tmp0 > VL53LX_D_003) + tmp0 = VL53LX_D_003; + + tmp1 = (uint64_t)VL53LX_p_055 * (uint64_t)VL53LX_p_055; + tmp1 = tmp1 << 8; + + if (tmp1 > VL53LX_D_004) + tmp1 = VL53LX_D_004; + + tmp1 = do_division_u(tmp1, b_minus_amb); + tmp1 = do_division_u(tmp1, b_minus_amb); + + if (tmp1 > (uint64_t)VL53LX_D_005) + tmp1 = (uint64_t)VL53LX_D_005; + + tmp0 = tmp1 * tmp0; + tmp1 = (uint64_t)c_zp + (uint64_t)cx_zp + (uint64_t)a_zp + (uint64_t)ax_zp; + + if (tmp1 > (uint64_t)VL53LX_D_003) + tmp1 = (uint64_t)VL53LX_D_003; + + tmp1 = tmp1 << 8; + + tmp0 = tmp1 + tmp0; + if (tmp0 > (uint64_t)VL53LX_D_006) + tmp0 = (uint64_t)VL53LX_D_006; + + if (tmp0 > (uint64_t)VL53LX_D_007) { + tmp0 = do_division_u(tmp0, b_minus_amb); + tmp0 = tmp0 * pll_period_mm; + } else { + tmp0 = tmp0 * pll_period_mm; + tmp0 = do_division_u(tmp0, b_minus_amb); + } + + if (tmp0 > (uint64_t)VL53LX_D_006) + tmp0 = (uint64_t)VL53LX_D_006; + + if (tmp0 > (uint64_t)VL53LX_D_007) { + tmp0 = do_division_u(tmp0, b_minus_amb); + tmp0 = do_division_u(tmp0, 4); + tmp0 = tmp0 * pll_period_mm; + } else { + tmp0 = tmp0 * pll_period_mm; + tmp0 = do_division_u(tmp0, b_minus_amb); + tmp0 = do_division_u(tmp0, 4); + } + + if (tmp0 > (uint64_t)VL53LX_D_006) + tmp0 = (uint64_t)VL53LX_D_006; + + tmp0 = tmp0 >> 2; + + if (tmp0 > (uint64_t)VL53LX_D_007) + tmp0 = (uint64_t)VL53LX_D_007; + + tmp1 = (uint64_t)sigma_estimator__sigma_ref_mm << 7; + tmp1 = tmp1 * tmp1; + tmp0 = tmp0 + tmp1; + + if (tmp0 > (uint64_t)VL53LX_D_007) + tmp0 = (uint64_t)VL53LX_D_007; + + sigma_int = VL53LX_isqrt((uint32_t)tmp0); + *psigma_est = (uint16_t)sigma_int; + status = VL53LX_ERROR_NONE; + } + } + return status; +} + +VL53LX_Error VL53LX_f_014( + uint8_t bin, + uint8_t sigma_estimator__sigma_ref_mm, + uint8_t VL53LX_p_030, + uint8_t VL53LX_p_051, + uint8_t crosstalk_compensation_enable, + VL53LX_histogram_bin_data_t *phist_data_ap, + VL53LX_histogram_bin_data_t *phist_data_zp, + VL53LX_histogram_bin_data_t *pxtalk_hist, + uint16_t *psigma_est) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_Error func_status = VL53LX_ERROR_NONE; + + uint8_t i = 0; + int32_t VL53LX_p_007 = 0; + int32_t VL53LX_p_032 = 0; + int32_t VL53LX_p_001 = 0; + int32_t a_zp = 0; + int32_t c_zp = 0; + int32_t ax = 0; + int32_t bx = 0; + int32_t cx = 0; + + if (VL53LX_p_030 == 0) { + *psigma_est = 0xFFFF; + return VL53LX_ERROR_DIVISION_BY_ZERO; + } + i = bin % VL53LX_p_030; + + VL53LX_f_022(i, VL53LX_p_051, phist_data_zp, &a_zp, &VL53LX_p_032, &c_zp); + VL53LX_f_022(i, VL53LX_p_051, phist_data_ap, &VL53LX_p_007, &VL53LX_p_032, &VL53LX_p_001); + + if (crosstalk_compensation_enable > 0) + VL53LX_f_022(i, VL53LX_p_051, pxtalk_hist, &ax, &bx, &cx); + + func_status = + VL53LX_f_023( + sigma_estimator__sigma_ref_mm, + (uint32_t)VL53LX_p_007, + (uint32_t)VL53LX_p_032, + (uint32_t)VL53LX_p_001, + (uint32_t)a_zp, + (uint32_t)c_zp, + (uint32_t)bx, + (uint32_t)ax, + (uint32_t)cx, + (uint32_t)phist_data_ap->VL53LX_p_028, + phist_data_ap->VL53LX_p_015, + psigma_est); + + if (func_status == VL53LX_ERROR_DIVISION_BY_ZERO) + *psigma_est = 0xFFFF; + + return status; +} + +VL53LX_Error VL53LX_f_020(int16_t VL53LX_p_019, int16_t VL53LX_p_024, uint8_t VL53LX_p_030, uint8_t clip_events, VL53LX_histogram_bin_data_t *pbins, uint32_t *pphase) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + int16_t i = 0; + int16_t lb = 0; + int64_t VL53LX_p_018 = 0; + int64_t event_sum = 0; + int64_t weighted_sum = 0; + + *pphase = VL53LX_MAX_ALLOWED_PHASE; + + if (VL53LX_p_030 != 0) { + for (lb = VL53LX_p_019; lb <= VL53LX_p_024; lb++) { + if (lb < 0) + i = lb + (int16_t)VL53LX_p_030; + else + i = lb % (int16_t)VL53LX_p_030; + + if ((i >= 0) && (i < VL53LX_HISTOGRAM_BUFFER_SIZE)) { + VL53LX_p_018 = (int64_t)pbins->bin_data[i] - (int64_t)pbins->VL53LX_p_028; + + if (clip_events > 0 && VL53LX_p_018 < 0) + VL53LX_p_018 = 0; + event_sum += VL53LX_p_018; + weighted_sum += (VL53LX_p_018 * (1024 + (2048*(int64_t)lb))); + } + + } + if (event_sum > 0) { + weighted_sum += do_division_s(event_sum, 2); + weighted_sum = do_division_s(weighted_sum, event_sum); + if (weighted_sum < 0) + weighted_sum = 0; + *pphase = (uint32_t)weighted_sum; + } + } + return status; +} + +VL53LX_Error VL53LX_f_015(uint8_t pulse_no, uint8_t clip_events, VL53LX_histogram_bin_data_t *pbins, VL53LX_hist_gen3_algo_private_data_t *palgo) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + uint8_t i = 0; + int16_t VL53LX_p_012 = 0; + int16_t VL53LX_p_013 = 0; + int16_t window_width = 0; + uint32_t tmp_phase = 0; + + VL53LX_hist_pulse_data_t *pdata = &(palgo->VL53LX_p_003[pulse_no]); + + if (pdata->VL53LX_p_023 == 0xFF) + pdata->VL53LX_p_023 = 1; + + i = pdata->VL53LX_p_023 % palgo->VL53LX_p_030; + + VL53LX_p_012 = (int16_t)i; + VL53LX_p_012 += (int16_t)pdata->VL53LX_p_012; + VL53LX_p_012 -= (int16_t)pdata->VL53LX_p_023; + + VL53LX_p_013 = (int16_t)i; + VL53LX_p_013 += (int16_t)pdata->VL53LX_p_013; + VL53LX_p_013 -= (int16_t)pdata->VL53LX_p_023; + + window_width = VL53LX_p_013 - VL53LX_p_012; + if (window_width > 3) + window_width = 3; + + status = VL53LX_f_020(VL53LX_p_012, VL53LX_p_012 + window_width, palgo->VL53LX_p_030, clip_events, pbins, &(pdata->VL53LX_p_026)); + + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_f_020(VL53LX_p_013 - window_width, VL53LX_p_013, palgo->VL53LX_p_030, clip_events, pbins, &(pdata->VL53LX_p_027)); + + if (pdata->VL53LX_p_026 > pdata->VL53LX_p_027) { + tmp_phase = pdata->VL53LX_p_026; + pdata->VL53LX_p_026 = pdata->VL53LX_p_027; + pdata->VL53LX_p_027 = tmp_phase; + } + + if (pdata->VL53LX_p_011 < pdata->VL53LX_p_026) + pdata->VL53LX_p_026 = pdata->VL53LX_p_011; + + if (pdata->VL53LX_p_011 > pdata->VL53LX_p_027) + pdata->VL53LX_p_027 = pdata->VL53LX_p_011; + + return status; +} + +VL53LX_Error VL53LX_f_016(VL53LX_HistTargetOrder target_order, VL53LX_hist_gen3_algo_private_data_t *palgo) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + VL53LX_hist_pulse_data_t tmp; + VL53LX_hist_pulse_data_t *ptmp = &tmp; + VL53LX_hist_pulse_data_t *p0; + VL53LX_hist_pulse_data_t *p1; + + uint8_t i = 0; + uint8_t swapped = 1; + + if (!(palgo->VL53LX_p_046 > 1)) + goto ENDFUNC; + + while (swapped > 0) { + swapped = 0; + for (i = 1; i < palgo->VL53LX_p_046; i++) { + p0 = &(palgo->VL53LX_p_003[i-1]); + p1 = &(palgo->VL53LX_p_003[i]); + + if (target_order == VL53LX_HIST_TARGET_ORDER__STRONGEST_FIRST) { + if (p0->VL53LX_p_010 < p1->VL53LX_p_010) { + memcpy(ptmp, p1, sizeof(VL53LX_hist_pulse_data_t)); + memcpy(p1, p0, sizeof(VL53LX_hist_pulse_data_t)); + memcpy(p0, ptmp, sizeof(VL53LX_hist_pulse_data_t)); + swapped = 1; + } + } else { + if (p0->VL53LX_p_011 > p1->VL53LX_p_011) { + memcpy(ptmp, p1, sizeof(VL53LX_hist_pulse_data_t)); + memcpy(p1, p0, sizeof(VL53LX_hist_pulse_data_t)); + memcpy(p0, ptmp, sizeof(VL53LX_hist_pulse_data_t)); + swapped = 1; + } + } + } + } +ENDFUNC: + return status; + +} + +void VL53LX_f_017( + uint8_t range_id, + uint8_t valid_phase_low, + uint8_t valid_phase_high, + uint16_t sigma_thres, + VL53LX_histogram_bin_data_t *pbins, + VL53LX_hist_pulse_data_t *ppulse, + VL53LX_range_data_t *pdata) +{ + uint16_t lower_phase_limit = 0; + uint16_t upper_phase_limit = 0; + + pdata->range_id = range_id; + pdata->time_stamp = 0; + pdata->VL53LX_p_012 = ppulse->VL53LX_p_012; + pdata->VL53LX_p_019 = ppulse->VL53LX_p_019; + pdata->VL53LX_p_023 = ppulse->VL53LX_p_023; + pdata->VL53LX_p_024 = ppulse->VL53LX_p_024; + pdata->VL53LX_p_013 = ppulse->VL53LX_p_013; + pdata->VL53LX_p_025 = ppulse->VL53LX_p_025; + pdata->VL53LX_p_029 = (ppulse->VL53LX_p_013 + 1) - ppulse->VL53LX_p_012; + + pdata->zero_distance_phase = pbins->zero_distance_phase; + pdata->VL53LX_p_002 = ppulse->VL53LX_p_002; + pdata->VL53LX_p_026 = (uint16_t)ppulse->VL53LX_p_026; + pdata->VL53LX_p_011 = (uint16_t)ppulse->VL53LX_p_011; + pdata->VL53LX_p_027 = (uint16_t)ppulse->VL53LX_p_027; + pdata->VL53LX_p_017 = (uint32_t)ppulse->VL53LX_p_017; + pdata->VL53LX_p_010 = ppulse->VL53LX_p_010; + pdata->VL53LX_p_016 = (uint32_t)ppulse->VL53LX_p_016; + pdata->total_periods_elapsed = pbins->total_periods_elapsed; + + pdata->range_status = VL53LX_DEVICEERROR_RANGECOMPLETE_NO_WRAP_CHECK; + + if (sigma_thres > 0 && (uint32_t)ppulse->VL53LX_p_002 > ((uint32_t)sigma_thres << 5)) + pdata->range_status = VL53LX_DEVICEERROR_SIGMATHRESHOLDCHECK; + + lower_phase_limit = (uint8_t)valid_phase_low << 8; + if (lower_phase_limit < pdata->zero_distance_phase) + lower_phase_limit = pdata->zero_distance_phase - lower_phase_limit; + else + lower_phase_limit = 0; + + upper_phase_limit = (uint8_t)valid_phase_high << 8; + upper_phase_limit += pbins->zero_distance_phase; + + if (pdata->VL53LX_p_011 < lower_phase_limit || + pdata->VL53LX_p_011 > upper_phase_limit) + pdata->range_status = VL53LX_DEVICEERROR_RANGEPHASECHECK; +} + +int32_t VL53LX_range_maths( + uint16_t fast_osc_frequency, + uint16_t VL53LX_p_014, + uint16_t zero_distance_phase, + uint8_t fractional_bits, + int32_t gain_factor, + int32_t range_offset_mm) +{ + uint32_t pll_period_us = 0; + int64_t tmp_long_int = 0; + int32_t range_mm = 0; + int32_t range_mm_10 = 0; + + pll_period_us = VL53LX_calc_pll_period_us(fast_osc_frequency); + + tmp_long_int = (int64_t)VL53LX_p_014 - (int64_t)zero_distance_phase; + tmp_long_int = tmp_long_int * (int64_t)pll_period_us; + tmp_long_int = tmp_long_int / (0x01 << 9); + tmp_long_int = tmp_long_int * VL53LX_SPEED_OF_LIGHT_IN_AIR_DIV_8; + tmp_long_int = tmp_long_int / (0x01 << 22); + + range_mm = (int32_t)tmp_long_int + range_offset_mm; + range_mm *= gain_factor; + range_mm += 0x0400; + range_mm /= 0x0800; + + if (fractional_bits == 0) { + range_mm_10 = range_mm * 10; + range_mm_10 = range_mm_10 / (0x01 << 2); + if ((range_mm_10 % 10) < 5) + range_mm = (int16_t)(range_mm_10 / 10); + else + range_mm = (int16_t)(range_mm_10 / 10 + 1); + } else if (fractional_bits == 1) + range_mm = range_mm / (0x01 << 1); + return range_mm; +} + +void VL53LX_f_019(uint16_t gain_factor, int16_t range_offset_mm, VL53LX_range_data_t *pdata) +{ + pdata->min_range_mm = + (int16_t)VL53LX_range_maths( + pdata->fast_osc_frequency, + pdata->VL53LX_p_026, + pdata->zero_distance_phase, + 0, + (int32_t)gain_factor, + (int32_t)range_offset_mm); + + pdata->median_range_mm = + (int16_t)VL53LX_range_maths( + pdata->fast_osc_frequency, + pdata->VL53LX_p_011, + pdata->zero_distance_phase, + 0, + (int32_t)gain_factor, + (int32_t)range_offset_mm); + + pdata->max_range_mm = + (int16_t)VL53LX_range_maths( + pdata->fast_osc_frequency, + pdata->VL53LX_p_027, + pdata->zero_distance_phase, + 0, + (int32_t)gain_factor, + (int32_t)range_offset_mm); +} + +uint16_t VL53LX_rate_per_spad_maths(uint32_t frac_bits, uint32_t peak_count_rate, uint16_t num_spads, uint32_t max_output_value) +{ + uint32_t tmp_int = 0; + uint16_t rate_per_spad = 0; + + if (num_spads > 0) { + tmp_int = (peak_count_rate << 8) << frac_bits; + tmp_int = (tmp_int + ((uint32_t)num_spads / 2)) / (uint32_t)num_spads; + } else { + tmp_int = ((peak_count_rate) << frac_bits); + } + + if (tmp_int > max_output_value) + tmp_int = max_output_value; + + rate_per_spad = (uint16_t)tmp_int; + + return rate_per_spad; +} + +VL53LX_Error VL53LX_f_018( + uint16_t vcsel_width, + uint16_t fast_osc_frequency, + uint32_t total_periods_elapsed, + uint16_t VL53LX_p_004, + VL53LX_range_data_t *pdata, + uint8_t histo_merge_nb) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + uint32_t pll_period_us = 0; + uint32_t periods_elapsed = 0; + uint32_t count_rate_total = 0; + + pdata->width = vcsel_width; + pdata->fast_osc_frequency = fast_osc_frequency; + pdata->total_periods_elapsed = total_periods_elapsed; + pdata->VL53LX_p_004 = VL53LX_p_004; + + if (pdata->fast_osc_frequency == 0) + status = VL53LX_ERROR_DIVISION_BY_ZERO; + + if (pdata->total_periods_elapsed == 0) + status = VL53LX_ERROR_DIVISION_BY_ZERO; + + if (status == VL53LX_ERROR_NONE) { + pll_period_us = VL53LX_calc_pll_period_us(pdata->fast_osc_frequency); + + periods_elapsed = pdata->total_periods_elapsed + 1; + + pdata->peak_duration_us = VL53LX_duration_maths(pll_period_us, (uint32_t)pdata->width, VL53LX_RANGING_WINDOW_VCSEL_PERIODS, periods_elapsed); + + pdata->woi_duration_us = VL53LX_duration_maths(pll_period_us, ((uint32_t)pdata->VL53LX_p_029) << 4, VL53LX_RANGING_WINDOW_VCSEL_PERIODS, periods_elapsed); + + pdata->peak_signal_count_rate_mcps = VL53LX_rate_maths((int32_t)pdata->VL53LX_p_010, pdata->peak_duration_us); + + pdata->avg_signal_count_rate_mcps = VL53LX_rate_maths((int32_t)pdata->VL53LX_p_010, pdata->woi_duration_us); + + pdata->ambient_count_rate_mcps = VL53LX_rate_maths((int32_t)pdata->VL53LX_p_016, pdata->woi_duration_us); + + count_rate_total = (uint32_t)pdata->peak_signal_count_rate_mcps + (uint32_t)pdata->ambient_count_rate_mcps; + + if (histo_merge_nb > 1) + count_rate_total /= histo_merge_nb; + + pdata->total_rate_per_spad_mcps = VL53LX_rate_per_spad_maths(0x06, count_rate_total, pdata->VL53LX_p_004, 0xFFFF); + + pdata->VL53LX_p_009 = VL53LX_events_per_spad_maths(pdata->VL53LX_p_010, pdata->VL53LX_p_004, pdata->peak_duration_us); + } + + return status; +} + +VL53LX_Error VL53LX_f_025( + VL53LX_dmax_calibration_data_t *pdmax_cal, + VL53LX_hist_gen3_dmax_config_t *pdmax_cfg, + VL53LX_hist_post_process_config_t *ppost_cfg, + VL53LX_histogram_bin_data_t *pbins_input, + VL53LX_histogram_bin_data_t *pxtalk, + VL53LX_hist_gen3_algo_private_data_t *palgo3, + VL53LX_hist_gen4_algo_filtered_data_t *pfiltered, + VL53LX_hist_gen3_dmax_private_data_t *pdmax_algo, + VL53LX_range_results_t *presults, + uint8_t histo_merge_nb) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + VL53LX_hist_pulse_data_t *ppulse_data; + VL53LX_range_data_t *prange_data; + uint8_t p = 0; + VL53LX_histogram_bin_data_t *pB = &(palgo3->VL53LX_p_006); + + VL53LX_f_003(palgo3); + + memcpy(&(palgo3->VL53LX_p_006), pbins_input, sizeof(VL53LX_histogram_bin_data_t)); + presults->cfg_device_state = pbins_input->cfg_device_state; + presults->rd_device_state = pbins_input->rd_device_state; + presults->zone_id = pbins_input->zone_id; + presults->stream_count = pbins_input->result__stream_count; + presults->wrap_dmax_mm = 0; + presults->max_results = VL53LX_MAX_RANGE_RESULTS; + presults->active_results = 0; + + for (p = 0; p < VL53LX_MAX_AMBIENT_DMAX_VALUES; p++) + presults->VL53LX_p_022[p] = 0; + + VL53LX_hist_calc_zero_distance_phase(&(palgo3->VL53LX_p_006)); + + VL53LX_hist_estimate_ambient_from_thresholded_bins((int32_t)ppost_cfg->ambient_thresh_sigma0, &(palgo3->VL53LX_p_006)); + + VL53LX_hist_estimate_ambient_from_ambient_bins(&(palgo3->VL53LX_p_006)); + + VL53LX_hist_remove_ambient_bins(&(palgo3->VL53LX_p_006)); + + if (ppost_cfg->algo__crosstalk_compensation_enable > 0) + VL53LX_f_005(pxtalk, &(palgo3->VL53LX_p_006), &(palgo3->VL53LX_p_047)); + + pdmax_cfg->ambient_thresh_sigma = ppost_cfg->ambient_thresh_sigma1; + + for (p = 0; p < VL53LX_MAX_AMBIENT_DMAX_VALUES; p++) { + if (status == VL53LX_ERROR_NONE) { + status = + VL53LX_f_001(pdmax_cfg->target_reflectance_for_dmax_calc[p], pdmax_cal, pdmax_cfg, &(palgo3->VL53LX_p_006), pdmax_algo, &(presults->VL53LX_p_022[p])); + } + } + if (status == VL53LX_ERROR_NONE) + status = + VL53LX_f_006( + ppost_cfg->ambient_thresh_events_scaler, + (int32_t)pdmax_cfg->ambient_thresh_sigma, + (int32_t)ppost_cfg->min_ambient_thresh_events, + ppost_cfg->algo__crosstalk_compensation_enable, + &(palgo3->VL53LX_p_006), + &(palgo3->VL53LX_p_047), + palgo3); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_f_007(palgo3); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_f_008(palgo3); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_f_009(palgo3); + + for (p = 0; p < palgo3->VL53LX_p_046; p++) { + ppulse_data = &(palgo3->VL53LX_p_003[p]); + if (status == VL53LX_ERROR_NONE) + status = VL53LX_f_010(p, &(palgo3->VL53LX_p_006), palgo3); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_f_011(p, &(palgo3->VL53LX_p_006), palgo3, pB->VL53LX_p_028, &(palgo3->VL53LX_p_048)); + + if (status == VL53LX_ERROR_NONE) { + status = VL53LX_f_011(p, &(palgo3->VL53LX_p_006), palgo3, 0, &(palgo3->VL53LX_p_049)); + } + + if (status == VL53LX_ERROR_NONE) { + status = VL53LX_f_011(p, &(palgo3->VL53LX_p_047), palgo3, 0, &(palgo3->VL53LX_p_050)); + } + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_f_026(p, &(palgo3->VL53LX_p_048), palgo3, pfiltered); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_f_027(p, ppost_cfg->noise_threshold, pfiltered, palgo3); + + if (status == VL53LX_ERROR_NONE) + status = + VL53LX_f_014( + ppulse_data->VL53LX_p_023, + ppost_cfg->sigma_estimator__sigma_ref_mm, + palgo3->VL53LX_p_030, + ppulse_data->VL53LX_p_051, + ppost_cfg->algo__crosstalk_compensation_enable, + &(palgo3->VL53LX_p_048), + &(palgo3->VL53LX_p_049), + &(palgo3->VL53LX_p_050), + &(ppulse_data->VL53LX_p_002)); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_f_015(p, 1, &(palgo3->VL53LX_p_006), palgo3); + } + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_f_016(ppost_cfg->hist_target_order, palgo3); + + for (p = 0; p < palgo3->VL53LX_p_046; p++) { + ppulse_data = &(palgo3->VL53LX_p_003[p]); + if (!(presults->active_results < presults->max_results)) + continue; + + if (ppulse_data->VL53LX_p_010 > ppost_cfg->signal_total_events_limit && ppulse_data->VL53LX_p_023 < 0xFF) { + prange_data = &(presults->VL53LX_p_003[presults->active_results]); + if (status == VL53LX_ERROR_NONE) + VL53LX_f_017( + presults->active_results, + ppost_cfg->valid_phase_low, + ppost_cfg->valid_phase_high, + ppost_cfg->sigma_thresh, + &(palgo3->VL53LX_p_006), + ppulse_data, + prange_data); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_f_018(pB->vcsel_width, pB->VL53LX_p_015, pB->total_periods_elapsed, pB->result__dss_actual_effective_spads, prange_data, histo_merge_nb); + + if (status == VL53LX_ERROR_NONE) + VL53LX_f_019(ppost_cfg->gain_factor, ppost_cfg->range_offset_mm, prange_data); + presults->active_results++; + } + } + return status; +} + +VL53LX_Error VL53LX_hist_process_data( + VL53LX_dmax_calibration_data_t *pdmax_cal, + VL53LX_hist_gen3_dmax_config_t *pdmax_cfg, + VL53LX_hist_post_process_config_t *ppost_cfg, + VL53LX_histogram_bin_data_t *pbins_input, + VL53LX_xtalk_histogram_data_t *pxtalk_shape, + uint8_t *pArea1, + uint8_t *pArea2, + VL53LX_range_results_t *presults, + uint8_t *HistMergeNumber) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + VL53LX_hist_gen3_algo_private_data_t *palgo_gen3 = (VL53LX_hist_gen3_algo_private_data_t *) pArea1; + VL53LX_hist_gen4_algo_filtered_data_t *pfiltered4 = (VL53LX_hist_gen4_algo_filtered_data_t *) pArea2; + VL53LX_hist_gen3_dmax_private_data_t dmax_algo_gen3; + VL53LX_hist_gen3_dmax_private_data_t *pdmax_algo_gen3 = &dmax_algo_gen3; + VL53LX_histogram_bin_data_t bins_averaged; + VL53LX_histogram_bin_data_t *pbins_averaged = &bins_averaged; + VL53LX_range_data_t *pdata; + uint32_t xtalk_rate_kcps = 0; + uint32_t max_xtalk_rate_per_spad_kcps = 0; + uint8_t xtalk_enable = 0; + uint8_t r = 0; + uint8_t t = 0; + uint32_t XtalkDetectMaxSigma = 0; + int16_t delta_mm = 0; + + VL53LX_f_031(pbins_input, pbins_averaged); + + VL53LX_init_histogram_bin_data_struct(0, pxtalk_shape->xtalk_shape.VL53LX_p_021, &(pxtalk_shape->xtalk_hist_removed)); + VL53LX_copy_xtalk_bin_data_to_histogram_data_struct(&(pxtalk_shape->xtalk_shape), &(pxtalk_shape->xtalk_hist_removed)); + + if ((status == VL53LX_ERROR_NONE) && (ppost_cfg->algo__crosstalk_compensation_enable > 0)) + status = + VL53LX_f_032( + ppost_cfg->algo__crosstalk_compensation_plane_offset_kcps, + ppost_cfg->algo__crosstalk_compensation_x_plane_gradient_kcps, + ppost_cfg->algo__crosstalk_compensation_y_plane_gradient_kcps, + 0, + 0, + pbins_input->result__dss_actual_effective_spads, + pbins_input->roi_config__user_roi_centre_spad, + pbins_input->roi_config__user_roi_requested_global_xy_size, + &(xtalk_rate_kcps)); + + if ((status == VL53LX_ERROR_NONE) && (ppost_cfg->algo__crosstalk_compensation_enable > 0)) + status = VL53LX_f_033(pbins_averaged, &(pxtalk_shape->xtalk_shape), xtalk_rate_kcps, &(pxtalk_shape->xtalk_hist_removed)); + + presults->xmonitor.total_periods_elapsed = pbins_averaged->total_periods_elapsed; + presults->xmonitor.VL53LX_p_004 = pbins_averaged->result__dss_actual_effective_spads; + + presults->xmonitor.peak_signal_count_rate_mcps = 0; + presults->xmonitor.VL53LX_p_009 = 0; + + presults->xmonitor.range_id = 0; + presults->xmonitor.range_status = VL53LX_DEVICEERROR_NOUPDATE; + + xtalk_enable = 0; + if (ppost_cfg->algo__crosstalk_compensation_enable > 0) + xtalk_enable = 1; + + for (r = 0 ; r <= xtalk_enable ; r++) { + ppost_cfg->algo__crosstalk_compensation_enable = r; + status = + VL53LX_f_025( + pdmax_cal, + pdmax_cfg, + ppost_cfg, + pbins_averaged, + &(pxtalk_shape->xtalk_hist_removed), + palgo_gen3, + pfiltered4, + pdmax_algo_gen3, + presults, + *HistMergeNumber); + + if (!(status == VL53LX_ERROR_NONE && r == 0)) + continue; + + if (presults->active_results == 0) { + pdata = &(presults->VL53LX_p_003[0]); + pdata->ambient_count_rate_mcps = pdmax_algo_gen3->VL53LX_p_034; + pdata->VL53LX_p_004 = pdmax_algo_gen3->VL53LX_p_004; + } + + max_xtalk_rate_per_spad_kcps = (uint32_t)(ppost_cfg->algo__crosstalk_detect_max_valid_rate_kcps); + max_xtalk_rate_per_spad_kcps *= (uint32_t)(*HistMergeNumber); + max_xtalk_rate_per_spad_kcps <<= 4; + + for (t = 0 ; t < presults->active_results ; t++) { + pdata = &(presults->VL53LX_p_003[t]); + if (pdata->max_range_mm > pdata->min_range_mm) + delta_mm = pdata->max_range_mm - pdata->min_range_mm; + else + delta_mm = pdata->min_range_mm - pdata->max_range_mm; + + XtalkDetectMaxSigma = ppost_cfg->algo__crosstalk_detect_max_sigma_mm; + XtalkDetectMaxSigma *= (uint32_t)(*HistMergeNumber); + XtalkDetectMaxSigma <<= 5; + if (pdata->median_range_mm > + ppost_cfg->algo__crosstalk_detect_min_valid_range_mm && + pdata->median_range_mm < + ppost_cfg->algo__crosstalk_detect_max_valid_range_mm && + pdata->VL53LX_p_009 < + max_xtalk_rate_per_spad_kcps && + pdata->VL53LX_p_002 < XtalkDetectMaxSigma && + delta_mm < + ppost_cfg->algo__crosstalk_detect_min_max_tolerance) { + memcpy(&(presults->xmonitor), pdata, sizeof(VL53LX_range_data_t)); + } + } + } + ppost_cfg->algo__crosstalk_compensation_enable = xtalk_enable; + return status; +} + +VL53LX_Error VL53LX_hist_wrap_dmax(VL53LX_hist_post_process_config_t *phistpostprocess, VL53LX_histogram_bin_data_t *pcurrent, int16_t *pwrap_dmax_mm) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + uint32_t pll_period_mm = 0; + uint32_t wrap_dmax_phase = 0; + uint32_t range_mm = 0; + + *pwrap_dmax_mm = 0; + + if (pcurrent->VL53LX_p_015 != 0) { + pll_period_mm = VL53LX_calc_pll_period_mm(pcurrent->VL53LX_p_015); + + wrap_dmax_phase = (uint32_t)phistpostprocess->valid_phase_high << 8; + + range_mm = wrap_dmax_phase * pll_period_mm; + range_mm = (range_mm + (1<<14)) >> 15; + + *pwrap_dmax_mm = (int16_t)range_mm; + } + return status; +} + +VL53LX_Error VL53LX_ipp_hist_process_data( + VL53LX_DEV Dev, + VL53LX_dmax_calibration_data_t *pdmax_cal, + VL53LX_hist_gen3_dmax_config_t *pdmax_cfg, + VL53LX_hist_post_process_config_t *ppost_cfg, + VL53LX_histogram_bin_data_t *pbins, + VL53LX_xtalk_histogram_data_t *pxtalk, + uint8_t *pArea1, + uint8_t *pArea2, + uint8_t *phisto_merge_nb, + VL53LX_range_results_t *presults) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + SUPPRESS_UNUSED_WARNING(Dev); + + status = VL53LX_hist_process_data(pdmax_cal, pdmax_cfg, ppost_cfg, pbins, pxtalk, pArea1, pArea2, presults, phisto_merge_nb); + return status; +} + +VL53LX_Error VL53LX_hist_events_consistency_check( + uint8_t event_sigma, + uint16_t min_effective_spad_count, + VL53LX_zone_hist_info_t *phist_prev, + VL53LX_object_data_t *prange_prev, + VL53LX_range_data_t *prange_curr, + int32_t *pevents_tolerance, + int32_t *pevents_delta, + VL53LX_DeviceError *prange_status) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + int64_t tmpp = 0; + int64_t tmpc = 0; + int64_t events_scaler = 0; + int64_t events_scaler_sq = 0; + int64_t c_signal_events = 0; + int64_t c_sig_noise_sq = 0; + int64_t c_amb_noise_sq = 0; + int64_t p_amb_noise_sq = 0; + int32_t p_signal_events = 0; + uint32_t noise_sq_sum = 0; + + if (event_sigma == 0) { + *prange_status = VL53LX_DEVICEERROR_RANGECOMPLETE; + return status; + } + + tmpp = 1 + (int64_t)phist_prev->total_periods_elapsed; + tmpp *= (int64_t)phist_prev->result__dss_actual_effective_spads; + + tmpc = 1 + (int64_t)prange_curr->total_periods_elapsed; + tmpc *= (int64_t)prange_curr->VL53LX_p_004; + + events_scaler = tmpp * 4096; + if (tmpc != 0) { + events_scaler += (tmpc/2); + events_scaler = do_division_s(events_scaler, tmpc); + } + + events_scaler_sq = events_scaler * events_scaler; + events_scaler_sq += 2048; + events_scaler_sq /= 4096; + + c_signal_events = (int64_t)prange_curr->VL53LX_p_017; + c_signal_events -= (int64_t)prange_curr->VL53LX_p_016; + c_signal_events *= (int64_t)events_scaler; + c_signal_events += 2048; + c_signal_events /= 4096; + + c_sig_noise_sq = (int64_t)events_scaler_sq; + c_sig_noise_sq *= (int64_t)prange_curr->VL53LX_p_017; + c_sig_noise_sq += 2048; + c_sig_noise_sq /= 4096; + + c_amb_noise_sq = (int64_t)events_scaler_sq; + c_amb_noise_sq *= (int64_t)prange_curr->VL53LX_p_016; + c_amb_noise_sq += 2048; + c_amb_noise_sq /= 4096; + + c_amb_noise_sq += 2; + c_amb_noise_sq /= 4; + + p_amb_noise_sq = (int64_t)prange_prev->VL53LX_p_016; + + p_amb_noise_sq += 2; + p_amb_noise_sq /= 4; + + noise_sq_sum = (uint32_t)prange_prev->VL53LX_p_017 + (uint32_t)c_sig_noise_sq + (uint32_t)p_amb_noise_sq + (uint32_t)c_amb_noise_sq; + + *pevents_tolerance = (int32_t)VL53LX_isqrt(noise_sq_sum * 16); + *pevents_tolerance *= (int32_t)event_sigma; + *pevents_tolerance += 32; + *pevents_tolerance /= 64; + + p_signal_events = (int32_t)prange_prev->VL53LX_p_017; + p_signal_events -= (int32_t)prange_prev->VL53LX_p_016; + + if ((int32_t)c_signal_events > p_signal_events) + *pevents_delta = (int32_t)c_signal_events - p_signal_events; + else + *pevents_delta = p_signal_events - (int32_t)c_signal_events; + + if (*pevents_delta > *pevents_tolerance && prange_curr->VL53LX_p_004 > min_effective_spad_count) + *prange_status = VL53LX_DEVICEERROR_EVENTCONSISTENCY; + else + *prange_status = VL53LX_DEVICEERROR_RANGECOMPLETE; + + return status; +} + +VL53LX_Error VL53LX_hist_merged_pulse_check(int16_t min_max_tolerance_mm, VL53LX_range_data_t *pdata, VL53LX_DeviceError *prange_status) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + int16_t delta_mm = 0; + + if (pdata->max_range_mm > pdata->min_range_mm) + delta_mm = pdata->max_range_mm - pdata->min_range_mm; + else + delta_mm = pdata->min_range_mm - pdata->max_range_mm; + + if (min_max_tolerance_mm > 0 && delta_mm > min_max_tolerance_mm) + *prange_status = VL53LX_DEVICEERROR_RANGECOMPLETE_MERGED_PULSE; + else + *prange_status = VL53LX_DEVICEERROR_RANGECOMPLETE; + + return status; +} + +VL53LX_Error VL53LX_hist_phase_consistency_check(VL53LX_DEV Dev, VL53LX_zone_hist_info_t *phist_prev, VL53LX_zone_objects_t *prange_prev, VL53LX_range_results_t *prange_curr) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + uint8_t lc = 0; + uint8_t p = 0; + uint16_t phase_delta = 0; + uint16_t phase_tolerance = 0; + int32_t events_delta = 0; + int32_t events_tolerance = 0; + uint8_t event_sigma; + uint16_t event_min_spad_count; + uint16_t min_max_tolerance; + uint8_t pht; + + VL53LX_DeviceError range_status = 0; + + event_sigma = pdev->histpostprocess.algo__consistency_check__event_sigma; + event_min_spad_count = pdev->histpostprocess.algo__consistency_check__event_min_spad_count; + min_max_tolerance = pdev->histpostprocess.algo__consistency_check__min_max_tolerance; + pht = pdev->histpostprocess.algo__consistency_check__phase_tolerance; + phase_tolerance = (uint16_t)pht; + phase_tolerance = phase_tolerance << 8; + + if (prange_prev->rd_device_state != VL53LX_DEVICESTATE_RANGING_GATHER_DATA && + prange_prev->rd_device_state != VL53LX_DEVICESTATE_RANGING_OUTPUT_DATA) + return status; + + if (phase_tolerance == 0) + return status; + + for (lc = 0; lc < prange_curr->active_results; lc++) { + if (!((prange_curr->VL53LX_p_003[lc].range_status == + VL53LX_DEVICEERROR_RANGECOMPLETE) || + (prange_curr->VL53LX_p_003[lc].range_status == + VL53LX_DEVICEERROR_RANGECOMPLETE_NO_WRAP_CHECK))) + continue; + + if (prange_prev->active_objects == 0) + prange_curr->VL53LX_p_003[lc].range_status = VL53LX_DEVICEERROR_PREV_RANGE_NO_TARGETS; + else + prange_curr->VL53LX_p_003[lc].range_status = VL53LX_DEVICEERROR_PHASECONSISTENCY; + + for (p = 0; p < prange_prev->active_objects; p++) { + if (prange_curr->VL53LX_p_003[lc].VL53LX_p_011 > prange_prev->VL53LX_p_003[p].VL53LX_p_011) { + phase_delta = prange_curr->VL53LX_p_003[lc].VL53LX_p_011 - prange_prev->VL53LX_p_003[p].VL53LX_p_011; + } else { + phase_delta = prange_prev->VL53LX_p_003[p].VL53LX_p_011 - prange_curr->VL53LX_p_003[lc].VL53LX_p_011; + } + + if (phase_delta < phase_tolerance) { + if (status == VL53LX_ERROR_NONE) + status = + VL53LX_hist_events_consistency_check( + event_sigma, + event_min_spad_count, + phist_prev, + &(prange_prev->VL53LX_p_003[p]), + &(prange_curr->VL53LX_p_003[lc]), + &events_tolerance, + &events_delta, + &range_status); + + if (status == VL53LX_ERROR_NONE && range_status == VL53LX_DEVICEERROR_RANGECOMPLETE) + status = VL53LX_hist_merged_pulse_check(min_max_tolerance, &(prange_curr->VL53LX_p_003[lc]), &range_status); + + prange_curr->VL53LX_p_003[lc].range_status = range_status; + } + } + } + return status; +} + +VL53LX_Error VL53LX_hist_xmonitor_consistency_check(VL53LX_DEV Dev, VL53LX_zone_hist_info_t *phist_prev, VL53LX_zone_objects_t *prange_prev, VL53LX_range_data_t *prange_curr) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + int32_t events_delta = 0; + int32_t events_tolerance = 0; + uint8_t event_sigma; + uint16_t min_spad_count; + + event_sigma = pdev->histpostprocess.algo__crosstalk_detect_event_sigma; + min_spad_count = pdev->histpostprocess.algo__consistency_check__event_min_spad_count; + + if (prange_curr->range_status == VL53LX_DEVICEERROR_RANGECOMPLETE || + prange_curr->range_status == VL53LX_DEVICEERROR_RANGECOMPLETE_NO_WRAP_CHECK || + prange_curr->range_status == VL53LX_DEVICEERROR_EVENTCONSISTENCY) { + + if (prange_prev->xmonitor.range_status == VL53LX_DEVICEERROR_RANGECOMPLETE || + prange_prev->xmonitor.range_status == VL53LX_DEVICEERROR_RANGECOMPLETE_NO_WRAP_CHECK || + prange_prev->xmonitor.range_status == VL53LX_DEVICEERROR_EVENTCONSISTENCY) { + prange_curr->range_status = VL53LX_DEVICEERROR_RANGECOMPLETE; + + status = + VL53LX_hist_events_consistency_check( + event_sigma, + min_spad_count, + phist_prev, + &(prange_prev->xmonitor), + prange_curr, + &events_tolerance, + &events_delta, + &(prange_curr->range_status)); + } + } + return status; +} + +void VL53LX_init_system_results(VL53LX_system_results_t *pdata) +{ + pdata->result__interrupt_status = 0xFF; + pdata->result__range_status = 0xFF; + pdata->result__report_status = 0xFF; + pdata->result__stream_count = 0xFF; + pdata->result__dss_actual_effective_spads_sd0 = 0xFFFF; + pdata->result__peak_signal_count_rate_mcps_sd0 = 0xFFFF; + pdata->result__ambient_count_rate_mcps_sd0 = 0xFFFF; + pdata->result__sigma_sd0 = 0xFFFF; + pdata->result__phase_sd0 = 0xFFFF; + pdata->result__final_crosstalk_corrected_range_mm_sd0 = 0xFFFF; + pdata->result__peak_signal_count_rate_crosstalk_corrected_mcps_sd0 = 0xFFFF; + pdata->result__mm_inner_actual_effective_spads_sd0 = 0xFFFF; + pdata->result__mm_outer_actual_effective_spads_sd0 = 0xFFFF; + pdata->result__avg_signal_count_rate_mcps_sd0 = 0xFFFF; + pdata->result__dss_actual_effective_spads_sd1 = 0xFFFF; + pdata->result__peak_signal_count_rate_mcps_sd1 = 0xFFFF; + pdata->result__ambient_count_rate_mcps_sd1 = 0xFFFF; + pdata->result__sigma_sd1 = 0xFFFF; + pdata->result__phase_sd1 = 0xFFFF; + pdata->result__final_crosstalk_corrected_range_mm_sd1 = 0xFFFF; + pdata->result__spare_0_sd1 = 0xFFFF; + pdata->result__spare_1_sd1 = 0xFFFF; + pdata->result__spare_2_sd1 = 0xFFFF; + pdata->result__spare_3_sd1 = 0xFF; +} + +void VL53LX_hist_copy_results_to_sys_and_core( + VL53LX_histogram_bin_data_t *pbins, + VL53LX_range_results_t *phist, + VL53LX_system_results_t *psys, + VL53LX_core_results_t *pcore) +{ + uint8_t i = 0; + VL53LX_range_data_t *pdata; + + VL53LX_init_system_results(psys); + + psys->result__interrupt_status = pbins->result__interrupt_status; + psys->result__range_status = phist->active_results; + psys->result__report_status = pbins->result__report_status; + psys->result__stream_count = pbins->result__stream_count; + + pdata = &(phist->VL53LX_p_003[0]); + + for (i = 0; i < phist->active_results; i++) { + switch (i) { + case 0: + psys->result__dss_actual_effective_spads_sd0 = pdata->VL53LX_p_004; + psys->result__peak_signal_count_rate_mcps_sd0 = pdata->peak_signal_count_rate_mcps; + psys->result__avg_signal_count_rate_mcps_sd0 = pdata->avg_signal_count_rate_mcps; + psys->result__ambient_count_rate_mcps_sd0 = pdata->ambient_count_rate_mcps; + psys->result__sigma_sd0 = pdata->VL53LX_p_002; + psys->result__phase_sd0 = pdata->VL53LX_p_011; + psys->result__final_crosstalk_corrected_range_mm_sd0 = (uint16_t)pdata->median_range_mm; + psys->result__phase_sd1 = pdata->zero_distance_phase; + pcore->result_core__ranging_total_events_sd0 = pdata->VL53LX_p_017; + pcore->result_core__signal_total_events_sd0 = pdata->VL53LX_p_010; + pcore->result_core__total_periods_elapsed_sd0 = pdata->total_periods_elapsed; + pcore->result_core__ambient_window_events_sd0 = pdata->VL53LX_p_016; + break; + case 1: + psys->result__dss_actual_effective_spads_sd1 = pdata->VL53LX_p_004; + psys->result__peak_signal_count_rate_mcps_sd1 = pdata->peak_signal_count_rate_mcps; + psys->result__ambient_count_rate_mcps_sd1 = pdata->ambient_count_rate_mcps; + psys->result__sigma_sd1 = pdata->VL53LX_p_002; + psys->result__phase_sd1 = pdata->VL53LX_p_011; + psys->result__final_crosstalk_corrected_range_mm_sd1 = (uint16_t)pdata->median_range_mm; + pcore->result_core__ranging_total_events_sd1 = pdata->VL53LX_p_017; + pcore->result_core__signal_total_events_sd1 = pdata->VL53LX_p_010; + pcore->result_core__total_periods_elapsed_sd1 = pdata->total_periods_elapsed; + pcore->result_core__ambient_window_events_sd1 = pdata->VL53LX_p_016; + break; + } + pdata++; + } +} + +VL53LX_Error VL53LX_dynamic_zone_update(VL53LX_DEV Dev, VL53LX_range_results_t *presults) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + VL53LX_LLDriverResults_t *pres = VL53LXDevStructGetLLResultsHandle(Dev); + VL53LX_zone_private_dyn_cfgs_t *pZ = &(pres->zone_dyn_cfgs); + + uint8_t zone_id = pdev->ll_state.rd_zone_id; + uint8_t i; + uint16_t max_total_rate_per_spads; + uint16_t target_rate = pdev->stat_cfg.dss_config__target_total_rate_mcps; + uint32_t temp = 0xFFFF; +#ifdef VL53LX_LOG_ENABLE + uint16_t eff_spad_cnt = + pZ->VL53LX_p_003[zone_id].dss_requested_effective_spad_count; +#endif + + pZ->VL53LX_p_003[zone_id].dss_requested_effective_spad_count = 0; + + max_total_rate_per_spads = presults->VL53LX_p_003[0].total_rate_per_spad_mcps; + + for (i = 1; i < presults->active_results; i++) { + if (presults->VL53LX_p_003[i].total_rate_per_spad_mcps > max_total_rate_per_spads) + max_total_rate_per_spads = presults->VL53LX_p_003[i].total_rate_per_spad_mcps; + } + + if (max_total_rate_per_spads == 0) { + temp = 0xFFFF; + } else { + temp = target_rate << 14; + temp = temp / max_total_rate_per_spads; + if (temp > 0xFFFF) + temp = 0xFFFF; + } + + pZ->VL53LX_p_003[zone_id].dss_requested_effective_spad_count = (uint16_t)temp; + + return status; +} + +void VL53LX_copy_hist_bins_to_static_cfg(VL53LX_histogram_config_t *phistogram, VL53LX_static_config_t *pstatic, VL53LX_timing_config_t *ptiming) +{ + pstatic->sigma_estimator__effective_pulse_width_ns = phistogram->histogram_config__high_amb_even_bin_0_1; + pstatic->sigma_estimator__effective_ambient_width_ns = phistogram->histogram_config__high_amb_even_bin_2_3; + pstatic->sigma_estimator__sigma_ref_mm = phistogram->histogram_config__high_amb_even_bin_4_5; + pstatic->algo__crosstalk_compensation_valid_height_mm = phistogram->histogram_config__high_amb_odd_bin_0_1; + pstatic->spare_host_config__static_config_spare_0 = phistogram->histogram_config__high_amb_odd_bin_2_3; + pstatic->spare_host_config__static_config_spare_1 = phistogram->histogram_config__high_amb_odd_bin_4_5; + pstatic->algo__range_ignore_threshold_mcps = + (((uint16_t)phistogram->histogram_config__mid_amb_even_bin_0_1) + << 8) + + (uint16_t)phistogram->histogram_config__mid_amb_even_bin_2_3; + pstatic->algo__range_ignore_valid_height_mm = phistogram->histogram_config__mid_amb_even_bin_4_5; + pstatic->algo__range_min_clip = phistogram->histogram_config__mid_amb_odd_bin_0_1; + pstatic->algo__consistency_check__tolerance = phistogram->histogram_config__mid_amb_odd_bin_2; + pstatic->spare_host_config__static_config_spare_2 = phistogram->histogram_config__mid_amb_odd_bin_3_4; + pstatic->sd_config__reset_stages_msb = phistogram->histogram_config__mid_amb_odd_bin_5; + ptiming->range_config__sigma_thresh = + (((uint16_t)phistogram->histogram_config__low_amb_even_bin_0_1) + << 8) + + (uint16_t)phistogram->histogram_config__low_amb_even_bin_2_3; + ptiming->range_config__min_count_rate_rtn_limit_mcps = + (((uint16_t)phistogram->histogram_config__low_amb_even_bin_4_5) + << 8) + + (uint16_t)phistogram->histogram_config__low_amb_odd_bin_0_1; + ptiming->range_config__valid_phase_low = + phistogram->histogram_config__low_amb_odd_bin_2_3; + ptiming->range_config__valid_phase_high = + phistogram->histogram_config__low_amb_odd_bin_4_5; +} + +VL53LX_Error VL53LX_multizone_hist_bins_update(VL53LX_DEV Dev) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + VL53LX_histogram_config_t *phist_cfg = &(pdev->hist_cfg); + + if (status == VL53LX_ERROR_NONE) { + VL53LX_copy_hist_bins_to_static_cfg(phist_cfg, &(pdev->stat_cfg), &(pdev->tim_cfg)); + } + return status; +} + +VL53LX_Error VL53LX_dynamic_xtalk_correction_calc_required_samples(VL53LX_DEV Dev) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + VL53LX_LLDriverResults_t *pres = VL53LXDevStructGetLLResultsHandle(Dev); + VL53LX_smudge_corrector_config_t *pconfig = &(pdev->smudge_correct_config); + VL53LX_smudge_corrector_internals_t *pint = &(pdev->smudge_corrector_internals); + VL53LX_range_results_t *presults = &(pres->range_results); + VL53LX_range_data_t *pxmonitor = &(presults->xmonitor); + + uint32_t peak_duration_us = pxmonitor->peak_duration_us; + uint64_t temp64a; + uint64_t temp64z; + + temp64a = pxmonitor->VL53LX_p_017 + pxmonitor->VL53LX_p_016; + if (peak_duration_us == 0) + peak_duration_us = 1000; + temp64a = do_division_u((temp64a * 1000), peak_duration_us); + temp64a = do_division_u((temp64a * 1000), peak_duration_us); + + temp64z = pconfig->noise_margin * pxmonitor->VL53LX_p_004; + if (temp64z == 0) + temp64z = 1; + temp64a = temp64a * 1000 * 256; + temp64a = do_division_u(temp64a, temp64z); + temp64a = temp64a * 1000 * 256; + temp64a = do_division_u(temp64a, temp64z); + + pint->required_samples = (uint32_t)temp64a; + + if (pint->required_samples < 2) + pint->required_samples = 2; + + return status; +} + +VL53LX_Error VL53LX_dynamic_xtalk_correction_calc_new_xtalk( + VL53LX_DEV Dev, + uint32_t xtalk_offset_out, + VL53LX_smudge_corrector_config_t *pconfig, + VL53LX_smudge_corrector_data_t *pout, + uint8_t add_smudge, + uint8_t soft_update + ) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + int16_t x_gradient_scaler; + int16_t y_gradient_scaler; + uint32_t orig_xtalk_offset; + int16_t orig_x_gradient; + int16_t orig_y_gradient; + uint8_t histo_merge_nb; + uint8_t i; + int32_t itemp32; + uint32_t SmudgeFactor; + VL53LX_xtalk_config_t *pX = &(pdev->xtalk_cfg); + VL53LX_xtalk_calibration_results_t *pC = &(pdev->xtalk_cal); + uint32_t *pcpo; + uint32_t max, nXtalk, cXtalk; + uint32_t incXtalk, cval; + + if (add_smudge == 1) { + pout->algo__crosstalk_compensation_plane_offset_kcps = (uint32_t)xtalk_offset_out + (uint32_t)pconfig->smudge_margin; + } else { + pout->algo__crosstalk_compensation_plane_offset_kcps = (uint32_t)xtalk_offset_out; + } + + orig_xtalk_offset = pX->nvm_default__crosstalk_compensation_plane_offset_kcps; + orig_x_gradient = pX->nvm_default__crosstalk_compensation_x_plane_gradient_kcps; + orig_y_gradient = pX->nvm_default__crosstalk_compensation_y_plane_gradient_kcps; + + if (((pconfig->user_scaler_set == 0) || (pconfig->scaler_calc_method == 1)) && (pC->algo__crosstalk_compensation_plane_offset_kcps != 0)) { + VL53LX_compute_histo_merge_nb(Dev, &histo_merge_nb); + + if (histo_merge_nb == 0) + histo_merge_nb = 1; + if (pdev->tuning_parms.tp_hist_merge != 1) + orig_xtalk_offset = pC->algo__crosstalk_compensation_plane_offset_kcps; + else + orig_xtalk_offset = pC->algo__xtalk_cpo_HistoMerge_kcps[histo_merge_nb-1]; + + orig_x_gradient = pC->algo__crosstalk_compensation_x_plane_gradient_kcps; + orig_y_gradient = pC->algo__crosstalk_compensation_y_plane_gradient_kcps; + } + + if ((pconfig->user_scaler_set == 0) && (orig_x_gradient == 0)) + pout->gradient_zero_flag |= 0x01; + + if ((pconfig->user_scaler_set == 0) && (orig_y_gradient == 0)) + pout->gradient_zero_flag |= 0x02; + + if (orig_xtalk_offset == 0) + orig_xtalk_offset = 1; + + if (pconfig->user_scaler_set == 1) { + x_gradient_scaler = pconfig->x_gradient_scaler; + y_gradient_scaler = pconfig->y_gradient_scaler; + } else { + x_gradient_scaler = (int16_t)do_division_s((((int32_t)orig_x_gradient) << 6), orig_xtalk_offset); + pconfig->x_gradient_scaler = x_gradient_scaler; + y_gradient_scaler = (int16_t)do_division_s((((int32_t)orig_y_gradient) << 6), orig_xtalk_offset); + pconfig->y_gradient_scaler = y_gradient_scaler; + } + + if (pconfig->scaler_calc_method == 0) { + itemp32 = (int32_t)(pout->algo__crosstalk_compensation_plane_offset_kcps * x_gradient_scaler); + itemp32 = itemp32 >> 6; + if (itemp32 > 0xFFFF) + itemp32 = 0xFFFF; + + pout->algo__crosstalk_compensation_x_plane_gradient_kcps = (int16_t)itemp32; + + itemp32 = (int32_t)(pout->algo__crosstalk_compensation_plane_offset_kcps * y_gradient_scaler); + itemp32 = itemp32 >> 6; + if (itemp32 > 0xFFFF) + itemp32 = 0xFFFF; + + pout->algo__crosstalk_compensation_y_plane_gradient_kcps = (int16_t)itemp32; + } else if (pconfig->scaler_calc_method == 1) { + itemp32 = (int32_t)(orig_xtalk_offset - pout->algo__crosstalk_compensation_plane_offset_kcps); + itemp32 = (int32_t)(do_division_s(itemp32, 16)); + itemp32 = itemp32 << 2; + itemp32 = itemp32 + (int32_t)(orig_x_gradient); + if (itemp32 > 0xFFFF) + itemp32 = 0xFFFF; + + pout->algo__crosstalk_compensation_x_plane_gradient_kcps = (int16_t)itemp32; + + itemp32 = (int32_t)(orig_xtalk_offset - pout->algo__crosstalk_compensation_plane_offset_kcps); + itemp32 = (int32_t)(do_division_s(itemp32, 80)); + itemp32 = itemp32 << 2; + itemp32 = itemp32 + (int32_t)(orig_y_gradient); + if (itemp32 > 0xFFFF) + itemp32 = 0xFFFF; + + pout->algo__crosstalk_compensation_y_plane_gradient_kcps = (int16_t)itemp32; + } + + if ((pconfig->smudge_corr_apply_enabled == 1) && (soft_update != 1)) { + pout->new_xtalk_applied_flag = 1; + nXtalk = pout->algo__crosstalk_compensation_plane_offset_kcps; + VL53LX_compute_histo_merge_nb(Dev, &histo_merge_nb); + max = pdev->tuning_parms.tp_hist_merge_max_size; + pcpo = &(pC->algo__xtalk_cpo_HistoMerge_kcps[0]); + if ((histo_merge_nb > 0) && (pdev->tuning_parms.tp_hist_merge == 1) && (nXtalk != 0)) { + cXtalk = pX->algo__crosstalk_compensation_plane_offset_kcps; + SmudgeFactor = cXtalk * 1000 / nXtalk; + if ((max == 0) || (SmudgeFactor >= pconfig->max_smudge_factor)) + pout->new_xtalk_applied_flag = 0; + else { + incXtalk = nXtalk / max; + cval = 0; + for (i = 0; i < max-1; i++) { + cval += incXtalk; + *pcpo = cval; + pcpo++; + } + *pcpo = nXtalk; + } + } + if (pout->new_xtalk_applied_flag) { + pX->algo__crosstalk_compensation_plane_offset_kcps = + pout->algo__crosstalk_compensation_plane_offset_kcps; + pX->algo__crosstalk_compensation_x_plane_gradient_kcps = + pout->algo__crosstalk_compensation_x_plane_gradient_kcps; + pX->algo__crosstalk_compensation_y_plane_gradient_kcps = + pout->algo__crosstalk_compensation_y_plane_gradient_kcps; + + if (pconfig->smudge_corr_single_apply == 1) { + pconfig->smudge_corr_apply_enabled = 0; + pconfig->smudge_corr_single_apply = 0; + } + } + } + + if (soft_update != 1) + pout->smudge_corr_valid = 1; + + return status; +} + +VL53LX_Error VL53LX_dynamic_xtalk_correction_corrector(VL53LX_DEV Dev) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + VL53LX_LLDriverResults_t *pres = VL53LXDevStructGetLLResultsHandle(Dev); + VL53LX_smudge_corrector_config_t *pconfig = &(pdev->smudge_correct_config); + VL53LX_smudge_corrector_internals_t *pint = &(pdev->smudge_corrector_internals); + VL53LX_smudge_corrector_data_t *pout = &(pres->range_results.smudge_corrector_data); + VL53LX_range_results_t *pR = &(pres->range_results); + VL53LX_xtalk_config_t *pX = &(pdev->xtalk_cfg); + + uint8_t run_smudge_detection = 0; + uint8_t merging_complete = 0; + uint8_t run_nodetect = 0; + uint8_t ambient_check = 0; + int32_t itemp32 = 0; + uint64_t utemp64 = 0; + uint8_t continue_processing = CONT_CONTINUE; + uint32_t xtalk_offset_out = 0; + uint32_t xtalk_offset_in = 0; + uint32_t current_xtalk = 0; + uint32_t smudge_margin_adjusted = 0; + uint8_t i = 0; + uint8_t nodetect_index = 0; + uint16_t amr; + uint32_t cco; + uint8_t histo_merge_nb; + + VL53LX_compute_histo_merge_nb(Dev, &histo_merge_nb); + if ((histo_merge_nb == 0) || (pdev->tuning_parms.tp_hist_merge != 1)) + histo_merge_nb = 1; + + VL53LX_dynamic_xtalk_correction_output_init(pres); + + ambient_check = (pconfig->smudge_corr_ambient_threshold == 0) || + ((pconfig->smudge_corr_ambient_threshold * histo_merge_nb) > + ((uint32_t)pR->xmonitor.ambient_count_rate_mcps)); + + merging_complete = ((pdev->tuning_parms.tp_hist_merge != 1) || (histo_merge_nb == pdev->tuning_parms.tp_hist_merge_max_size)); + run_smudge_detection = (pconfig->smudge_corr_enabled == 1) && ambient_check && (pR->xmonitor.range_status == VL53LX_DEVICEERROR_RANGECOMPLETE) && merging_complete; + + if ((pR->xmonitor.range_status != VL53LX_DEVICEERROR_RANGECOMPLETE) && (pconfig->smudge_corr_enabled == 1)) { + run_nodetect = 2; + for (i = 0; i < pR->active_results; i++) { + if (pR->VL53LX_p_003[i].range_status == VL53LX_DEVICEERROR_RANGECOMPLETE) { + if (pR->VL53LX_p_003[i].median_range_mm <= pconfig->nodetect_min_range_mm) { + run_nodetect = 0; + } else { + if (run_nodetect == 2) { + run_nodetect = 1; + nodetect_index = i; + } + } + } + } + + if (run_nodetect == 2) + run_nodetect = 0; + + amr = pR->VL53LX_p_003[nodetect_index].ambient_count_rate_mcps; + + if (run_nodetect == 1) { + utemp64 = 1000 * ((uint64_t)amr); + utemp64 = utemp64 << 9; + + if (utemp64 < pconfig->nodetect_ambient_threshold) + run_nodetect = 1; + else + run_nodetect = 0; + } + } + + if (run_smudge_detection) { + pint->nodetect_counter = 0; + VL53LX_dynamic_xtalk_correction_calc_required_samples(Dev); + + xtalk_offset_in = pR->xmonitor.VL53LX_p_009; + + cco = pX->algo__crosstalk_compensation_plane_offset_kcps; + current_xtalk = ((uint32_t)cco) << 2; + + smudge_margin_adjusted = ((uint32_t)(pconfig->smudge_margin)) << 2; + + itemp32 = xtalk_offset_in - current_xtalk + smudge_margin_adjusted; + + if (itemp32 < 0) + itemp32 = itemp32 * (-1); + + if (itemp32 > ((int32_t)pconfig->single_xtalk_delta)) { + if ((int32_t)xtalk_offset_in > ((int32_t)current_xtalk - (int32_t)smudge_margin_adjusted)) { + pout->single_xtalk_delta_flag = 1; + } else { + pout->single_xtalk_delta_flag = 2; + } + } + + pint->current_samples = pint->current_samples + 1; + + if (pint->current_samples > pconfig->sample_limit) { + pout->sample_limit_exceeded_flag = 1; + continue_processing = CONT_RESET; + } else { + pint->accumulator = pint->accumulator + xtalk_offset_in; + } + + if (pint->current_samples < pint->required_samples) + continue_processing = CONT_NEXT_LOOP; + + xtalk_offset_out = (uint32_t)(do_division_u(pint->accumulator, pint->current_samples)); + + itemp32 = xtalk_offset_out - current_xtalk + smudge_margin_adjusted; + + if (itemp32 < 0) + itemp32 = itemp32 * (-1); + + if (continue_processing == CONT_CONTINUE && (itemp32 >= ((int32_t)(pconfig->averaged_xtalk_delta)))) { + if ((int32_t)xtalk_offset_out > ((int32_t)current_xtalk - (int32_t)smudge_margin_adjusted)) + pout->averaged_xtalk_delta_flag = 1; + else + pout->averaged_xtalk_delta_flag = 2; + } + + if (continue_processing == CONT_CONTINUE && (itemp32 < ((int32_t)(pconfig->averaged_xtalk_delta)))) + continue_processing = CONT_RESET; + + pout->smudge_corr_clipped = 0; + if ((continue_processing == CONT_CONTINUE) && (pconfig->smudge_corr_clip_limit != 0)) { + if (xtalk_offset_out > (pconfig->smudge_corr_clip_limit * histo_merge_nb)) { + pout->smudge_corr_clipped = 1; + continue_processing = CONT_RESET; + } + } + + if (pconfig->user_xtalk_offset_limit_hi && (xtalk_offset_out > pconfig->user_xtalk_offset_limit)) + xtalk_offset_out = pconfig->user_xtalk_offset_limit; + + if ((pconfig->user_xtalk_offset_limit_hi == 0) && (xtalk_offset_out < pconfig->user_xtalk_offset_limit)) + xtalk_offset_out = pconfig->user_xtalk_offset_limit; + + xtalk_offset_out = xtalk_offset_out >> 2; + if (xtalk_offset_out > 0x3FFFF) + xtalk_offset_out = 0x3FFFF; + + if (continue_processing == CONT_CONTINUE) { + VL53LX_dynamic_xtalk_correction_calc_new_xtalk(Dev, xtalk_offset_out, pconfig, pout, 1, 0); + continue_processing = CONT_RESET; + } else { + VL53LX_dynamic_xtalk_correction_calc_new_xtalk(Dev, xtalk_offset_out, pconfig, pout, 1, 1); + } + + if (continue_processing == CONT_RESET) { + pint->accumulator = 0; + pint->current_samples = 0; + pint->nodetect_counter = 0; + } + } + + continue_processing = CONT_CONTINUE; + if (run_nodetect == 1) { + pint->nodetect_counter += 1; + if (pint->nodetect_counter < pconfig->nodetect_sample_limit) + continue_processing = CONT_NEXT_LOOP; + + xtalk_offset_out = (uint32_t)(pconfig->nodetect_xtalk_offset); + + if (continue_processing == CONT_CONTINUE) { + VL53LX_dynamic_xtalk_correction_calc_new_xtalk(Dev, xtalk_offset_out, pconfig, pout, 0, 0); + pout->smudge_corr_valid = 2; + continue_processing = CONT_RESET; + } else { + VL53LX_dynamic_xtalk_correction_calc_new_xtalk(Dev, xtalk_offset_out, pconfig, pout, 0, 1); + } + + if (continue_processing == CONT_RESET) { + pint->accumulator = 0; + pint->current_samples = 0; + pint->nodetect_counter = 0; + } + } + return status; +} + +VL53LX_Error VL53LX_i2c_decode_debug_results(uint16_t buf_size, uint8_t *pbuffer, VL53LX_debug_results_t *pdata) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + if (buf_size < VL53LX_DEBUG_RESULTS_I2C_SIZE_BYTES) + return VL53LX_ERROR_COMMS_BUFFER_TOO_SMALL; + + pdata->phasecal_result__reference_phase = (VL53LX_i2c_decode_uint16_t(2, pbuffer + 0)); + pdata->phasecal_result__vcsel_start = (*(pbuffer + 2)) & 0x7F; + pdata->ref_spad_char_result__num_actual_ref_spads = (*(pbuffer + 3)) & 0x3F; + pdata->ref_spad_char_result__ref_location = (*(pbuffer + 4)) & 0x3; + pdata->vhv_result__coldboot_status = (*(pbuffer + 5)) & 0x1; + pdata->vhv_result__search_result = (*(pbuffer + 6)) & 0x3F; + pdata->vhv_result__latest_setting = (*(pbuffer + 7)) & 0x3F; + pdata->result__osc_calibrate_val = (VL53LX_i2c_decode_uint16_t(2, pbuffer + 8)) & 0x3FF; + pdata->ana_config__powerdown_go1 = (*(pbuffer + 10)) & 0x3; + pdata->ana_config__ref_bg_ctrl = (*(pbuffer + 11)) & 0x3; + pdata->ana_config__regdvdd1v2_ctrl = (*(pbuffer + 12)) & 0xF; + pdata->ana_config__osc_slow_ctrl = (*(pbuffer + 13)) & 0x7; + pdata->test_mode__status = (*(pbuffer + 14)) & 0x1; + pdata->firmware__system_status = (*(pbuffer + 15)) & 0x3; + pdata->firmware__mode_status = (*(pbuffer + 16)); + pdata->firmware__secondary_mode_status = (*(pbuffer + 17)); + pdata->firmware__cal_repeat_rate_counter = (VL53LX_i2c_decode_uint16_t(2, pbuffer + 18)) & 0xFFF; + pdata->gph__system__thresh_high = (VL53LX_i2c_decode_uint16_t(2, pbuffer + 22)); + pdata->gph__system__thresh_low = (VL53LX_i2c_decode_uint16_t(2, pbuffer + 24)); + pdata->gph__system__enable_xtalk_per_quadrant = (*(pbuffer + 26)) & 0x1; + pdata->gph__spare_0 = (*(pbuffer + 27)) & 0x7; + pdata->gph__sd_config__woi_sd0 = (*(pbuffer + 28)); + pdata->gph__sd_config__woi_sd1 = (*(pbuffer + 29)); + pdata->gph__sd_config__initial_phase_sd0 = (*(pbuffer + 30)) & 0x7F; + pdata->gph__sd_config__initial_phase_sd1 = (*(pbuffer + 31)) & 0x7F; + pdata->gph__sd_config__first_order_select = (*(pbuffer + 32)) & 0x3; + pdata->gph__sd_config__quantifier = (*(pbuffer + 33)) & 0xF; + pdata->gph__roi_config__user_roi_centre_spad = (*(pbuffer + 34)); + pdata->gph__roi_config__user_roi_requested_global_xy_size = (*(pbuffer + 35)); + pdata->gph__system__sequence_config = (*(pbuffer + 36)); + pdata->gph__gph_id = (*(pbuffer + 37)) & 0x1; + pdata->system__interrupt_set = (*(pbuffer + 38)) & 0x3; + pdata->interrupt_manager__enables = (*(pbuffer + 39)) & 0x1F; + pdata->interrupt_manager__clear = (*(pbuffer + 40)) & 0x1F; + pdata->interrupt_manager__status = (*(pbuffer + 41)) & 0x1F; + pdata->mcu_to_host_bank__wr_access_en = (*(pbuffer + 42)) & 0x1; + pdata->power_management__go1_reset_status = (*(pbuffer + 43)) & 0x1; + pdata->pad_startup_mode__value_ro = (*(pbuffer + 44)) & 0x3; + pdata->pad_startup_mode__value_ctrl = (*(pbuffer + 45)) & 0x3F; + pdata->pll_period_us = (VL53LX_i2c_decode_uint32_t(4, pbuffer + 46)) & 0x3FFFF; + pdata->interrupt_scheduler__data_out = (VL53LX_i2c_decode_uint32_t(4, pbuffer + 50)); + pdata->nvm_bist__complete = (*(pbuffer + 54)) & 0x1; + pdata->nvm_bist__status = (*(pbuffer + 55)) & 0x1; + + return status; +} + +VL53LX_Error VL53LX_i2c_decode_core_results(uint16_t buf_size, uint8_t *pbuffer, VL53LX_core_results_t *pdata) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + if (buf_size < VL53LX_CORE_RESULTS_I2C_SIZE_BYTES) + return VL53LX_ERROR_COMMS_BUFFER_TOO_SMALL; + + pdata->result_core__ambient_window_events_sd0 = (VL53LX_i2c_decode_uint32_t(4, pbuffer + 0)); + pdata->result_core__ranging_total_events_sd0 = (VL53LX_i2c_decode_uint32_t(4, pbuffer + 4)); + pdata->result_core__signal_total_events_sd0 = (VL53LX_i2c_decode_int32_t(4, pbuffer + 8)); + pdata->result_core__total_periods_elapsed_sd0 = (VL53LX_i2c_decode_uint32_t(4, pbuffer + 12)); + pdata->result_core__ambient_window_events_sd1 = (VL53LX_i2c_decode_uint32_t(4, pbuffer + 16)); + pdata->result_core__ranging_total_events_sd1 = (VL53LX_i2c_decode_uint32_t(4, pbuffer + 20)); + pdata->result_core__signal_total_events_sd1 = (VL53LX_i2c_decode_int32_t(4, pbuffer + 24)); + pdata->result_core__total_periods_elapsed_sd1 = (VL53LX_i2c_decode_uint32_t(4, pbuffer + 28)); + pdata->result_core__spare_0 = (*(pbuffer + 32)); + + return status; +} + +VL53LX_Error VL53LX_i2c_decode_system_results(uint16_t buf_size, uint8_t *pbuffer, VL53LX_system_results_t *pdata) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + if (buf_size < VL53LX_SYSTEM_RESULTS_I2C_SIZE_BYTES) + return VL53LX_ERROR_COMMS_BUFFER_TOO_SMALL; + + pdata->result__interrupt_status = (*(pbuffer + 0)) & 0x3F; + pdata->result__range_status = (*(pbuffer + 1)); + pdata->result__report_status = (*(pbuffer + 2)) & 0xF; + pdata->result__stream_count = (*(pbuffer + 3)); + pdata->result__dss_actual_effective_spads_sd0 = (VL53LX_i2c_decode_uint16_t(2, pbuffer + 4)); + pdata->result__peak_signal_count_rate_mcps_sd0 = (VL53LX_i2c_decode_uint16_t(2, pbuffer + 6)); + pdata->result__ambient_count_rate_mcps_sd0 = (VL53LX_i2c_decode_uint16_t(2, pbuffer + 8)); + pdata->result__sigma_sd0 = (VL53LX_i2c_decode_uint16_t(2, pbuffer + 10)); + pdata->result__phase_sd0 = (VL53LX_i2c_decode_uint16_t(2, pbuffer + 12)); + pdata->result__final_crosstalk_corrected_range_mm_sd0 = (VL53LX_i2c_decode_uint16_t(2, pbuffer + 14)); + pdata->result__peak_signal_count_rate_crosstalk_corrected_mcps_sd0 = (VL53LX_i2c_decode_uint16_t(2, pbuffer + 16)); + pdata->result__mm_inner_actual_effective_spads_sd0 = (VL53LX_i2c_decode_uint16_t(2, pbuffer + 18)); + pdata->result__mm_outer_actual_effective_spads_sd0 = (VL53LX_i2c_decode_uint16_t(2, pbuffer + 20)); + pdata->result__avg_signal_count_rate_mcps_sd0 = (VL53LX_i2c_decode_uint16_t(2, pbuffer + 22)); + pdata->result__dss_actual_effective_spads_sd1 = (VL53LX_i2c_decode_uint16_t(2, pbuffer + 24)); + pdata->result__peak_signal_count_rate_mcps_sd1 = (VL53LX_i2c_decode_uint16_t(2, pbuffer + 26)); + pdata->result__ambient_count_rate_mcps_sd1 = (VL53LX_i2c_decode_uint16_t(2, pbuffer + 28)); + pdata->result__sigma_sd1 = (VL53LX_i2c_decode_uint16_t(2, pbuffer + 30)); + pdata->result__phase_sd1 = (VL53LX_i2c_decode_uint16_t(2, pbuffer + 32)); + pdata->result__final_crosstalk_corrected_range_mm_sd1 = (VL53LX_i2c_decode_uint16_t(2, pbuffer + 34)); + pdata->result__spare_0_sd1 = (VL53LX_i2c_decode_uint16_t(2, pbuffer + 36)); + pdata->result__spare_1_sd1 = (VL53LX_i2c_decode_uint16_t(2, pbuffer + 38)); + pdata->result__spare_2_sd1 = (VL53LX_i2c_decode_uint16_t(2, pbuffer + 40)); + pdata->result__spare_3_sd1 = (*(pbuffer + 42)); + pdata->result__thresh_info = (*(pbuffer + 43)); + + return status; +} + +VL53LX_Error VL53LX_get_measurement_results(VL53LX_DEV Dev, VL53LX_DeviceResultsLevel device_results_level) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + uint8_t buffer[VL53LX_MAX_I2C_XFER_SIZE]; + VL53LX_system_results_t *psystem_results = &(pdev->sys_results); + VL53LX_core_results_t *pcore_results = &(pdev->core_results); + VL53LX_debug_results_t *pdebug_results = &(pdev->dbg_results); + uint16_t i2c_index = VL53LX_SYSTEM_RESULTS_I2C_INDEX; + uint16_t i2c_buffer_offset_bytes = 0; + uint16_t i2c_buffer_size_bytes = 0; + + switch (device_results_level) { + case VL53LX_DEVICERESULTSLEVEL_FULL: + i2c_buffer_size_bytes = (VL53LX_DEBUG_RESULTS_I2C_INDEX + VL53LX_DEBUG_RESULTS_I2C_SIZE_BYTES) - i2c_index; + break; + case VL53LX_DEVICERESULTSLEVEL_UPTO_CORE: + i2c_buffer_size_bytes = (VL53LX_CORE_RESULTS_I2C_INDEX + VL53LX_CORE_RESULTS_I2C_SIZE_BYTES) - i2c_index; + break; + default: + i2c_buffer_size_bytes = VL53LX_SYSTEM_RESULTS_I2C_SIZE_BYTES; + break; + } + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_ReadMulti(Dev, i2c_index, buffer, (uint32_t)i2c_buffer_size_bytes); + + if (device_results_level >= VL53LX_DEVICERESULTSLEVEL_FULL && status == VL53LX_ERROR_NONE) { + i2c_buffer_offset_bytes = VL53LX_DEBUG_RESULTS_I2C_INDEX - i2c_index; + status = VL53LX_i2c_decode_debug_results(VL53LX_DEBUG_RESULTS_I2C_SIZE_BYTES, &buffer[i2c_buffer_offset_bytes], pdebug_results); + } + + if (device_results_level >= VL53LX_DEVICERESULTSLEVEL_UPTO_CORE && status == VL53LX_ERROR_NONE) { + i2c_buffer_offset_bytes = VL53LX_CORE_RESULTS_I2C_INDEX - i2c_index; + status = VL53LX_i2c_decode_core_results(VL53LX_CORE_RESULTS_I2C_SIZE_BYTES, &buffer[i2c_buffer_offset_bytes], pcore_results); + } + + if (status == VL53LX_ERROR_NONE) { + i2c_buffer_offset_bytes = 0; + status = VL53LX_i2c_decode_system_results(VL53LX_SYSTEM_RESULTS_I2C_SIZE_BYTES, &buffer[i2c_buffer_offset_bytes], psystem_results); + } + + return status; +} + +void VL53LX_copy_sys_and_core_results_to_range_results(int32_t gain_factor, VL53LX_system_results_t *psys, VL53LX_core_results_t *pcore, VL53LX_range_results_t *presults) +{ + uint8_t i = 0; + VL53LX_range_data_t *pdata; + int32_t range_mm = 0; + uint32_t tmpu32 = 0; + uint16_t rpscr_crosstalk_corrected_mcps_sd0; + uint16_t rmmo_effective_spads_sd0; + uint16_t rmmi_effective_spads_sd0; + + presults->zone_id = 0; + presults->stream_count = psys->result__stream_count; + presults->wrap_dmax_mm = 0; + presults->max_results = VL53LX_MAX_RANGE_RESULTS; + presults->active_results = 1; + rpscr_crosstalk_corrected_mcps_sd0 = psys->result__peak_signal_count_rate_crosstalk_corrected_mcps_sd0; + rmmo_effective_spads_sd0 = psys->result__mm_outer_actual_effective_spads_sd0; + rmmi_effective_spads_sd0 = psys->result__mm_inner_actual_effective_spads_sd0; + + for (i = 0; i < VL53LX_MAX_AMBIENT_DMAX_VALUES; i++) + presults->VL53LX_p_022[i] = 0; + + pdata = &(presults->VL53LX_p_003[0]); + + for (i = 0; i < 2; i++) { + pdata->range_id = i; + pdata->time_stamp = 0; + + if ((psys->result__stream_count == 0) && ((psys->result__range_status & VL53LX_RANGE_STATUS__RANGE_STATUS_MASK) == VL53LX_DEVICEERROR_RANGECOMPLETE)) { + pdata->range_status = VL53LX_DEVICEERROR_RANGECOMPLETE_NO_WRAP_CHECK; + } else { + pdata->range_status = psys->result__range_status & VL53LX_RANGE_STATUS__RANGE_STATUS_MASK; + } + + pdata->VL53LX_p_012 = 0; + pdata->VL53LX_p_019 = 0; + pdata->VL53LX_p_023 = 0; + pdata->VL53LX_p_024 = 0; + pdata->VL53LX_p_013 = 0; + pdata->VL53LX_p_025 = 0; + + switch (i) { + case 0: + if (psys->result__report_status == VL53LX_DEVICEREPORTSTATUS_MM1) + pdata->VL53LX_p_004 = rmmi_effective_spads_sd0; + else if (psys->result__report_status == VL53LX_DEVICEREPORTSTATUS_MM2) + pdata->VL53LX_p_004 = rmmo_effective_spads_sd0; + else + pdata->VL53LX_p_004 = psys->result__dss_actual_effective_spads_sd0; + + pdata->peak_signal_count_rate_mcps = rpscr_crosstalk_corrected_mcps_sd0; + pdata->avg_signal_count_rate_mcps = psys->result__avg_signal_count_rate_mcps_sd0; + pdata->ambient_count_rate_mcps = psys->result__ambient_count_rate_mcps_sd0; + + tmpu32 = ((uint32_t)psys->result__sigma_sd0 << 5); + if (tmpu32 > 0xFFFF) + tmpu32 = 0xFFFF; + pdata->VL53LX_p_002 = (uint16_t)tmpu32; + pdata->VL53LX_p_011 = psys->result__phase_sd0; + + range_mm = (int32_t)(psys->result__final_crosstalk_corrected_range_mm_sd0); + range_mm *= gain_factor; + range_mm += 0x0400; + range_mm /= 0x0800; + + pdata->median_range_mm = (int16_t)range_mm; + pdata->VL53LX_p_017 = pcore->result_core__ranging_total_events_sd0; + pdata->VL53LX_p_010 = pcore->result_core__signal_total_events_sd0; + pdata->total_periods_elapsed = pcore->result_core__total_periods_elapsed_sd0; + pdata->VL53LX_p_016 = pcore->result_core__ambient_window_events_sd0; + break; + case 1: + pdata->VL53LX_p_004 = psys->result__dss_actual_effective_spads_sd1; + pdata->peak_signal_count_rate_mcps = psys->result__peak_signal_count_rate_mcps_sd1; + pdata->avg_signal_count_rate_mcps = 0xFFFF; + pdata->ambient_count_rate_mcps = psys->result__ambient_count_rate_mcps_sd1; + + tmpu32 = ((uint32_t)psys->result__sigma_sd1 << 5); + if (tmpu32 > 0xFFFF) + tmpu32 = 0xFFFF; + pdata->VL53LX_p_002 = (uint16_t)tmpu32; + pdata->VL53LX_p_011 = psys->result__phase_sd1; + + range_mm = (int32_t)(psys->result__final_crosstalk_corrected_range_mm_sd1); + range_mm *= gain_factor; + range_mm += 0x0400; + range_mm /= 0x0800; + + pdata->median_range_mm = (int16_t)range_mm; + pdata->VL53LX_p_017 = pcore->result_core__ranging_total_events_sd1; + pdata->VL53LX_p_010 = pcore->result_core__signal_total_events_sd1; + pdata->total_periods_elapsed = pcore->result_core__total_periods_elapsed_sd1; + pdata->VL53LX_p_016 = pcore->result_core__ambient_window_events_sd1; + break; + } + + pdata->VL53LX_p_026 = pdata->VL53LX_p_011; + pdata->VL53LX_p_027 = pdata->VL53LX_p_011; + pdata->min_range_mm = pdata->median_range_mm; + pdata->max_range_mm = pdata->median_range_mm; + pdata++; + } + + presults->device_status = VL53LX_DEVICEERROR_NOUPDATE; + + switch (psys->result__range_status & VL53LX_RANGE_STATUS__RANGE_STATUS_MASK) { + case VL53LX_DEVICEERROR_VCSELCONTINUITYTESTFAILURE: + case VL53LX_DEVICEERROR_VCSELWATCHDOGTESTFAILURE: + case VL53LX_DEVICEERROR_NOVHVVALUEFOUND: + case VL53LX_DEVICEERROR_USERROICLIP: + case VL53LX_DEVICEERROR_MULTCLIPFAIL: + presults->device_status = (psys->result__range_status & VL53LX_RANGE_STATUS__RANGE_STATUS_MASK); + presults->VL53LX_p_003[0].range_status = VL53LX_DEVICEERROR_NOUPDATE; + break; + } +} + +VL53LX_Error VL53LX_low_power_auto_setup_manual_calibration(VL53LX_DEV Dev) +{ + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + VL53LX_Error status = VL53LX_ERROR_NONE; + + pdev->low_power_auto_data.saved_vhv_init = pdev->stat_nvm.vhv_config__init; + pdev->low_power_auto_data.saved_vhv_timeout = pdev->stat_nvm.vhv_config__timeout_macrop_loop_bound; + pdev->stat_nvm.vhv_config__init &= 0x7F; + pdev->stat_nvm.vhv_config__timeout_macrop_loop_bound = (pdev->stat_nvm.vhv_config__timeout_macrop_loop_bound & 0x03) + (pdev->low_power_auto_data.vhv_loop_bound << 2); + pdev->gen_cfg.phasecal_config__override = 0x01; + pdev->low_power_auto_data.first_run_phasecal_result = pdev->dbg_results.phasecal_result__vcsel_start; + pdev->gen_cfg.cal_config__vcsel_start = pdev->low_power_auto_data.first_run_phasecal_result; + + return status; +} + +VL53LX_Error VL53LX_low_power_auto_update_DSS(VL53LX_DEV Dev) +{ + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + VL53LX_system_results_t *pS = &(pdev->sys_results); + VL53LX_Error status = VL53LX_ERROR_NONE; + uint32_t utemp32a; + + utemp32a = pS->result__peak_signal_count_rate_crosstalk_corrected_mcps_sd0 + pS->result__ambient_count_rate_mcps_sd0; + + if (utemp32a > 0xFFFF) + utemp32a = 0xFFFF; + + utemp32a = utemp32a << 16; + + if (pdev->sys_results.result__dss_actual_effective_spads_sd0 == 0) + status = VL53LX_ERROR_DIVISION_BY_ZERO; + else { + utemp32a = utemp32a / + pdev->sys_results.result__dss_actual_effective_spads_sd0; + pdev->low_power_auto_data.dss__total_rate_per_spad_mcps = utemp32a; + utemp32a = pdev->stat_cfg.dss_config__target_total_rate_mcps << 16; + if (pdev->low_power_auto_data.dss__total_rate_per_spad_mcps == 0) + status = VL53LX_ERROR_DIVISION_BY_ZERO; + else { + utemp32a = utemp32a / pdev->low_power_auto_data.dss__total_rate_per_spad_mcps; + + if (utemp32a > 0xFFFF) + utemp32a = 0xFFFF; + + pdev->low_power_auto_data.dss__required_spads = (uint16_t)utemp32a; + pdev->gen_cfg.dss_config__manual_effective_spads_select = pdev->low_power_auto_data.dss__required_spads; + pdev->gen_cfg.dss_config__roi_mode_control = VL53LX_DEVICEDSSMODE__REQUESTED_EFFFECTIVE_SPADS; + } + } + + if (status == VL53LX_ERROR_DIVISION_BY_ZERO) { + pdev->low_power_auto_data.dss__required_spads = 0x8000; + pdev->gen_cfg.dss_config__manual_effective_spads_select = pdev->low_power_auto_data.dss__required_spads; + pdev->gen_cfg.dss_config__roi_mode_control = VL53LX_DEVICEDSSMODE__REQUESTED_EFFFECTIVE_SPADS; + status = VL53LX_ERROR_NONE; + } + + return status; +} + +VL53LX_Error VL53LX_check_ll_driver_rd_state(VL53LX_DEV Dev) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + VL53LX_LLDriverResults_t *pres = VL53LXDevStructGetLLResultsHandle(Dev); + VL53LX_ll_driver_state_t *pstate = &(pdev->ll_state); + VL53LX_system_results_t *psys_results = &(pdev->sys_results); + VL53LX_histogram_bin_data_t *phist_data = &(pdev->hist_data); + VL53LX_zone_private_dyn_cfgs_t *pZ = &(pres->zone_dyn_cfgs); + + uint8_t device_range_status = 0; + uint8_t device_stream_count = 0; + uint8_t device_gph_id = 0; + uint8_t histogram_mode = 0; + uint8_t expected_stream_count = 0; + uint8_t expected_gph_id = 0; + + device_range_status = psys_results->result__range_status & VL53LX_RANGE_STATUS__RANGE_STATUS_MASK; + device_stream_count = psys_results->result__stream_count; + + histogram_mode = (pdev->sys_ctrl.system__mode_start & VL53LX_DEVICESCHEDULERMODE_HISTOGRAM) == VL53LX_DEVICESCHEDULERMODE_HISTOGRAM; + + device_gph_id = (psys_results->result__interrupt_status & VL53LX_INTERRUPT_STATUS__GPH_ID_INT_STATUS_MASK) >> 4; + + if (histogram_mode) + device_gph_id = (phist_data->result__interrupt_status & VL53LX_INTERRUPT_STATUS__GPH_ID_INT_STATUS_MASK) >> 4; + + if (!((pdev->sys_ctrl.system__mode_start & VL53LX_DEVICEMEASUREMENTMODE_BACKTOBACK) == VL53LX_DEVICEMEASUREMENTMODE_BACKTOBACK)) + goto ENDFUNC; + + if (pstate->rd_device_state == VL53LX_DEVICESTATE_RANGING_WAIT_GPH_SYNC) { + if (histogram_mode == 0) { + if (device_range_status != VL53LX_DEVICEERROR_GPHSTREAMCOUNT0READY) + status = VL53LX_ERROR_GPH_SYNC_CHECK_FAIL; + } + } else { + if (pstate->rd_stream_count != device_stream_count) + status = VL53LX_ERROR_STREAM_COUNT_CHECK_FAIL; + + if (pstate->rd_gph_id != device_gph_id) + status = VL53LX_ERROR_GPH_ID_CHECK_FAIL; + + expected_stream_count = pZ->VL53LX_p_003[pstate->rd_zone_id].expected_stream_count; + expected_gph_id = pZ->VL53LX_p_003[pstate->rd_zone_id].expected_gph_id; + + if (expected_stream_count != device_stream_count) { + if (!((pdev->zone_cfg.active_zones == 0) && (device_stream_count == 255))) + status = VL53LX_ERROR_ZONE_STREAM_COUNT_CHECK_FAIL; + } + + if (expected_gph_id != device_gph_id) + status = VL53LX_ERROR_ZONE_GPH_ID_CHECK_FAIL; + } + +ENDFUNC: + return status; +} + +VL53LX_Error VL53LX_get_device_results(VL53LX_DEV Dev, VL53LX_DeviceResultsLevel device_results_level, VL53LX_range_results_t *prange_results) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + VL53LX_LLDriverResults_t *pres = VL53LXDevStructGetLLResultsHandle(Dev); + VL53LX_range_results_t *presults = &(pres->range_results); + VL53LX_zone_objects_t *pobjects = &(pres->zone_results.VL53LX_p_003[0]); + VL53LX_ll_driver_state_t *pstate = &(pdev->ll_state); + VL53LX_zone_config_t *pzone_cfg = &(pdev->zone_cfg); + VL53LX_zone_hist_info_t *phist_info = &(pres->zone_hists.VL53LX_p_003[0]); + VL53LX_dmax_calibration_data_t dmax_cal; + VL53LX_dmax_calibration_data_t *pdmax_cal = &dmax_cal; + VL53LX_hist_post_process_config_t *pHP = &(pdev->histpostprocess); + VL53LX_xtalk_config_t *pC = &(pdev->xtalk_cfg); + VL53LX_low_power_auto_data_t *pL = &(pdev->low_power_auto_data); + VL53LX_histogram_bin_data_t *pHD = &(pdev->hist_data); + VL53LX_customer_nvm_managed_t *pN = &(pdev->customer); + VL53LX_zone_histograms_t *pZH = &(pres->zone_hists); + VL53LX_xtalk_calibration_results_t *pXCR = &(pdev->xtalk_cal); + uint8_t tmp8; + uint8_t zid; + uint8_t i; + uint8_t histo_merge_nb, idx; + VL53LX_range_data_t *pdata; + + if ((pdev->sys_ctrl.system__mode_start & VL53LX_DEVICESCHEDULERMODE_HISTOGRAM) == VL53LX_DEVICESCHEDULERMODE_HISTOGRAM) { + status = VL53LX_get_histogram_bin_data(Dev, &(pdev->hist_data)); + if (status == VL53LX_ERROR_NONE && + pHD->number_of_ambient_bins == 0) { + zid = pdev->ll_state.rd_zone_id; + status = VL53LX_hist_copy_and_scale_ambient_info(&(pZH->VL53LX_p_003[zid]), &(pdev->hist_data)); + } + if (status != VL53LX_ERROR_NONE) + goto UPDATE_DYNAMIC_CONFIG; + + VL53LX_compute_histo_merge_nb(Dev, &histo_merge_nb); + if (histo_merge_nb == 0) + histo_merge_nb = 1; + idx = histo_merge_nb - 1; + if (pdev->tuning_parms.tp_hist_merge == 1) + pC->algo__crosstalk_compensation_plane_offset_kcps = pXCR->algo__xtalk_cpo_HistoMerge_kcps[idx]; + + pHP->gain_factor = pdev->gain_cal.histogram_ranging_gain_factor; + + pHP->algo__crosstalk_compensation_plane_offset_kcps = VL53LX_calc_crosstalk_plane_offset_with_margin(pC->algo__crosstalk_compensation_plane_offset_kcps, pC->histogram_mode_crosstalk_margin_kcps); + + pHP->algo__crosstalk_compensation_x_plane_gradient_kcps = pC->algo__crosstalk_compensation_x_plane_gradient_kcps; + pHP->algo__crosstalk_compensation_y_plane_gradient_kcps = pC->algo__crosstalk_compensation_y_plane_gradient_kcps; + + pdev->dmax_cfg.ambient_thresh_sigma = pHP->ambient_thresh_sigma1; + pdev->dmax_cfg.min_ambient_thresh_events = pHP->min_ambient_thresh_events; + pdev->dmax_cfg.signal_total_events_limit = pHP->signal_total_events_limit; + pdev->dmax_cfg.dss_config__target_total_rate_mcps = pdev->stat_cfg.dss_config__target_total_rate_mcps; + pdev->dmax_cfg.dss_config__aperture_attenuation = pdev->gen_cfg.dss_config__aperture_attenuation; + + pHP->algo__crosstalk_detect_max_valid_range_mm = pC->algo__crosstalk_detect_max_valid_range_mm; + pHP->algo__crosstalk_detect_min_valid_range_mm = pC->algo__crosstalk_detect_min_valid_range_mm; + pHP->algo__crosstalk_detect_max_valid_rate_kcps = pC->algo__crosstalk_detect_max_valid_rate_kcps; + pHP->algo__crosstalk_detect_max_sigma_mm = pC->algo__crosstalk_detect_max_sigma_mm; + + VL53LX_copy_rtn_good_spads_to_buffer(&(pdev->nvm_copy_data), &(pdev->rtn_good_spads[0])); + + switch (pdev->offset_correction_mode) { + case VL53LX_OFFSETCORRECTIONMODE__MM1_MM2_OFFSETS: + tmp8 = pdev->gen_cfg.dss_config__aperture_attenuation; + VL53LX_hist_combine_mm1_mm2_offsets( + pN->mm_config__inner_offset_mm, + pN->mm_config__outer_offset_mm, + pdev->nvm_copy_data.roi_config__mode_roi_centre_spad, + pdev->nvm_copy_data.roi_config__mode_roi_xy_size, + pHD->roi_config__user_roi_centre_spad, + pHD->roi_config__user_roi_requested_global_xy_size, + &(pdev->add_off_cal_data), + &(pdev->rtn_good_spads[0]), + (uint16_t)tmp8, + &(pHP->range_offset_mm)); + break; + case VL53LX_OFFSETCORRECTIONMODE__PER_VCSEL_OFFSETS: + select_offset_per_vcsel(pdev, &(pHP->range_offset_mm)); + pHP->range_offset_mm *= 4; + break; + default: + pHP->range_offset_mm = 0; + break; + } + + if (status != VL53LX_ERROR_NONE) + goto UPDATE_DYNAMIC_CONFIG; + + VL53LX_calc_max_effective_spads( + pHD->roi_config__user_roi_centre_spad, + pHD->roi_config__user_roi_requested_global_xy_size, + &(pdev->rtn_good_spads[0]), + (uint16_t)pdev->gen_cfg.dss_config__aperture_attenuation, + &(pdev->dmax_cfg.max_effective_spads)); + + status = VL53LX_get_dmax_calibration_data(Dev, pdev->dmax_mode, pdmax_cal); + + if (status != VL53LX_ERROR_NONE) + goto UPDATE_DYNAMIC_CONFIG; + + status = VL53LX_ipp_hist_process_data( + Dev, + pdmax_cal, + &(pdev->dmax_cfg), + &(pdev->histpostprocess), + &(pdev->hist_data), + &(pdev->xtalk_shapes), + pdev->wArea1, + pdev->wArea2, + &histo_merge_nb, + presults); + + if ((pdev->tuning_parms.tp_hist_merge == 1) && + (histo_merge_nb > 1)) + for (i = 0; i < VL53LX_MAX_RANGE_RESULTS; i++) { + pdata = &(presults->VL53LX_p_003[i]); + pdata->VL53LX_p_016 /= histo_merge_nb; + pdata->VL53LX_p_017 /= histo_merge_nb; + pdata->VL53LX_p_010 /= histo_merge_nb; + pdata->peak_signal_count_rate_mcps /= histo_merge_nb; + pdata->avg_signal_count_rate_mcps /= histo_merge_nb; + pdata->ambient_count_rate_mcps /= histo_merge_nb; + pdata->VL53LX_p_009 /= histo_merge_nb; + } + + if (status != VL53LX_ERROR_NONE) + goto UPDATE_DYNAMIC_CONFIG; + + status = VL53LX_hist_wrap_dmax(&(pdev->histpostprocess), &(pdev->hist_data), &(presults->wrap_dmax_mm)); + + if (status != VL53LX_ERROR_NONE) + goto UPDATE_DYNAMIC_CONFIG; + + zid = pdev->ll_state.rd_zone_id; + status = VL53LX_hist_phase_consistency_check(Dev, &(pZH->VL53LX_p_003[zid]), &(pres->zone_results.VL53LX_p_003[zid]), presults); + + if (status != VL53LX_ERROR_NONE) + goto UPDATE_DYNAMIC_CONFIG; + + zid = pdev->ll_state.rd_zone_id; + status = VL53LX_hist_xmonitor_consistency_check(Dev, &(pZH->VL53LX_p_003[zid]), &(pres->zone_results.VL53LX_p_003[zid]), &(presults->xmonitor)); + + if (status != VL53LX_ERROR_NONE) + goto UPDATE_DYNAMIC_CONFIG; + + zid = pdev->ll_state.rd_zone_id; + pZH->max_zones = VL53LX_MAX_USER_ZONES; + pZH->active_zones = pdev->zone_cfg.active_zones+1; + pHD->zone_id = zid; + + if (zid < pres->zone_results.max_zones) { + phist_info = &(pZH->VL53LX_p_003[zid]); + phist_info->rd_device_state = pHD->rd_device_state; + phist_info->number_of_ambient_bins = pHD->number_of_ambient_bins; + phist_info->result__dss_actual_effective_spads = pHD->result__dss_actual_effective_spads; + phist_info->VL53LX_p_005 = pHD->VL53LX_p_005; + phist_info->total_periods_elapsed = pHD->total_periods_elapsed; + phist_info->ambient_events_sum = pHD->ambient_events_sum; + } + + if (status != VL53LX_ERROR_NONE) + goto UPDATE_DYNAMIC_CONFIG; + VL53LX_hist_copy_results_to_sys_and_core(&(pdev->hist_data), presults, &(pdev->sys_results), &(pdev->core_results)); + +UPDATE_DYNAMIC_CONFIG: + if (pzone_cfg->active_zones > 0) { + if (pstate->rd_device_state != VL53LX_DEVICESTATE_RANGING_WAIT_GPH_SYNC) { + if (status == VL53LX_ERROR_NONE) { + status = VL53LX_dynamic_zone_update(Dev, presults); + } + } + + for (i = 0; i < VL53LX_MAX_USER_ZONES; i++) { + pzone_cfg->bin_config[i] = ((pdev->ll_state.cfg_internal_stream_count) & 0x01) ? VL53LX_ZONECONFIG_BINCONFIG__HIGHAMB : VL53LX_ZONECONFIG_BINCONFIG__LOWAMB; + } + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_multizone_hist_bins_update(Dev); + } + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_dynamic_xtalk_correction_corrector(Dev); + + if (pdev->tuning_parms.tp_hist_merge == 1) + pC->algo__crosstalk_compensation_plane_offset_kcps = pXCR->algo__xtalk_cpo_HistoMerge_kcps[0]; + } else { + if (status == VL53LX_ERROR_NONE) + status = VL53LX_get_measurement_results(Dev, device_results_level); + + if (status == VL53LX_ERROR_NONE) + VL53LX_copy_sys_and_core_results_to_range_results((int32_t)pdev->gain_cal.standard_ranging_gain_factor, &(pdev->sys_results), &(pdev->core_results), presults); + + if (pL->is_low_power_auto_mode == 1) { + if ((status == VL53LX_ERROR_NONE) && (pL->low_power_auto_range_count == 0)) { + status = VL53LX_low_power_auto_setup_manual_calibration(Dev); + pL->low_power_auto_range_count = 1; + } else if ((status == VL53LX_ERROR_NONE) && (pL->low_power_auto_range_count == 1)) { + pL->low_power_auto_range_count = 2; + } + + if ((pL->low_power_auto_range_count != 0xFF) && (status == VL53LX_ERROR_NONE)) { + status = VL53LX_low_power_auto_update_DSS(Dev); + } + } + } + + presults->cfg_device_state = pdev->ll_state.cfg_device_state; + presults->rd_device_state = pdev->ll_state.rd_device_state; + presults->zone_id = pdev->ll_state.rd_zone_id; + + if (status == VL53LX_ERROR_NONE) { + pres->zone_results.max_zones = VL53LX_MAX_USER_ZONES; + pres->zone_results.active_zones = pdev->zone_cfg.active_zones+1; + zid = pdev->ll_state.rd_zone_id; + + if (zid < pres->zone_results.max_zones) { + pobjects = &(pres->zone_results.VL53LX_p_003[zid]); + pobjects->cfg_device_state = presults->cfg_device_state; + pobjects->rd_device_state = presults->rd_device_state; + pobjects->zone_id = presults->zone_id; + pobjects->stream_count = presults->stream_count; + + pobjects->xmonitor.VL53LX_p_016 = presults->xmonitor.VL53LX_p_016; + pobjects->xmonitor.VL53LX_p_017 = presults->xmonitor.VL53LX_p_017; + pobjects->xmonitor.VL53LX_p_011 = presults->xmonitor.VL53LX_p_011; + pobjects->xmonitor.range_status = presults->xmonitor.range_status; + + pobjects->max_objects = presults->max_results; + pobjects->active_objects = presults->active_results; + + for (i = 0; i < presults->active_results; i++) { + pobjects->VL53LX_p_003[i].VL53LX_p_016 = presults->VL53LX_p_003[i].VL53LX_p_016; + pobjects->VL53LX_p_003[i].VL53LX_p_017 = presults->VL53LX_p_003[i].VL53LX_p_017; + pobjects->VL53LX_p_003[i].VL53LX_p_011 = presults->VL53LX_p_003[i].VL53LX_p_011; + pobjects->VL53LX_p_003[i].range_status = presults->VL53LX_p_003[i].range_status; + } + } + } + + memcpy(prange_results, presults, sizeof(VL53LX_range_results_t)); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_check_ll_driver_rd_state(Dev); + 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; + + 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; + + if ((active_results != 1) || (pdev->PreviousRangeActiveResults != 1)) + 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; +} + +static void stmvl53lx_work_handler(struct work_struct *work) +{ + struct stmvl53lx_data *data; + + data = container_of(work, struct stmvl53lx_data, dwork.work); + work_dbg("enter"); + mutex_lock(&data->work_mutex); + stmvl53lx_intr_process(data); + if (data->poll_mode && data->enable_sensor) { + schedule_delayed_work(&data->dwork, msecs_to_jiffies(data->poll_delay_ms)); + } + mutex_unlock(&data->work_mutex); +} + +static int ctrl_roi(struct stmvl53lx_data *data, void __user *p) +{ + int rc; + struct stmvl53lx_ioctl_roi_t roi; + + mutex_lock(&data->work_mutex); + + if (data->is_device_remove) { + rc = -ENODEV; + goto done; + } + rc = copy_from_user(&roi, p, sizeof(roi)); + if (rc) { + rc = -EFAULT; + goto done; + } + + if (roi.is_read) { + memcpy(&roi.Roi, &data->roi_cfg, sizeof(roi.Roi)); + rc = copy_to_user(p, &roi, sizeof(roi)); + if (rc) { + vl53lx_errmsg("fail to copy Roi to user %d", rc); + rc = -EFAULT; + goto done; + } + } else { + if (data->enable_sensor) { + rc = -EBUSY; + vl53lx_errmsg("can't set roi while ranging\n"); + goto done; + } + memcpy(&data->roi_cfg, &roi.Roi, sizeof(data->roi_cfg)); + vl53lx_dbgmsg("ROI modified TopLeft(%d %d) BottomRight(%d %d)\n", data->roi_cfg.TopLeftX, data->roi_cfg.TopLeftY, data->roi_cfg.BotRightX, data->roi_cfg.BotRightY); + } + +done: + mutex_unlock(&data->work_mutex); + return rc; +} + +static bool is_pid_in_list(pid_t pid, struct list_head *head) +{ + struct stmvl53lx_waiters *waiter; + + list_for_each_entry(waiter, head, list) + if (waiter->pid == pid) + return true; + + return false; +} + +static bool is_new_data_for_me(struct stmvl53lx_data *data, pid_t pid, struct list_head *head) +{ + return data->is_data_valid && !is_pid_in_list(pid, head); +} + +static bool sleep_for_data_condition(struct stmvl53lx_data *data, pid_t pid, struct list_head *head) +{ + bool res; + + mutex_lock(&data->work_mutex); + res = is_new_data_for_me(data, pid, head); + mutex_unlock(&data->work_mutex); + + return res; +} + +static int sleep_for_data(struct stmvl53lx_data *data, pid_t pid, struct list_head *head) +{ + int rc = 0; + + mutex_unlock(&data->work_mutex); + rc = wait_event_interruptible_timeout(data->waiter_for_data, sleep_for_data_condition(data, pid, head), usecs_to_jiffies(2 * data->timing_budget)); + if (rc == 0) + rc = -EAGAIN; + else + rc = 0; + mutex_lock(&data->work_mutex); + + return data->enable_sensor ? rc : -ENODEV; +} + +static int add_reader(pid_t pid, struct list_head *head) +{ + struct stmvl53lx_waiters *new_waiter; + + new_waiter = kmalloc(sizeof(struct stmvl53lx_waiters), GFP_KERNEL); + if (!new_waiter) + return -ENOMEM; + new_waiter->pid = pid; + list_add(&new_waiter->list, head); + + return 0; +} + +static int ctrl_mz_data_blocking_common(struct stmvl53lx_data *data, void __user *p, bool is_additional) +{ + int rc = 0; + int rc0; + struct stmvl53lx_data_with_additional __user *d = p; + pid_t pid = current->pid; + + mutex_lock(&data->work_mutex); + if (data->is_device_remove) { + rc = -ENODEV; + goto done; + } + if (!data->enable_sensor) { + rc = -ENODEV; + goto done; + } + if (!is_new_data_for_me(data, pid, &data->mz_data_reader_list)) + rc = sleep_for_data(data, pid, &data->mz_data_reader_list); + if (rc) { + kill_mz_data(&data->meas.multi_range_data); + rc0 = copy_to_user(&d->data, &data->meas.multi_range_data, sizeof(VL53LX_MultiRangingData_t)); + goto done; + } + + rc = copy_to_user(&d->data, &data->meas.multi_range_data, sizeof(VL53LX_MultiRangingData_t)); + if (rc) + goto done; + if (is_additional) { + rc = copy_to_user(&d->additional_data, &data->meas.additional_data, sizeof(VL53LX_AdditionalData_t)); + if (rc) + goto done; + } + rc = add_reader(pid, &data->mz_data_reader_list); + +done: + mutex_unlock(&data->work_mutex); + + return rc; +} + +static int ctrl_mz_data_common(struct stmvl53lx_data *data, void __user *p, bool is_additional) +{ + struct stmvl53lx_data_with_additional __user *d = p; + int rc = 0; + + mutex_lock(&data->work_mutex); + if (data->is_device_remove) { + rc = -ENODEV; + goto done; + } + rc = copy_to_user(&d->data, &data->meas.multi_range_data, sizeof(VL53LX_MultiRangingData_t)); + if (rc) { + vl53lx_dbgmsg("copy to user fail %d", rc); + rc = -EFAULT; + goto done; + } + if (is_additional) { + rc = copy_to_user(&d->additional_data, &data->meas.additional_data, sizeof(VL53LX_AdditionalData_t)); + if (rc) { + vl53lx_dbgmsg("copy to user fail %d", rc); + rc = -EFAULT; + goto done; + } + } + if (!data->enable_sensor) + rc = -ENODEV; + +done: + mutex_unlock(&data->work_mutex); + return rc; +} + +static int ctrl_mz_data(struct stmvl53lx_data *data, void __user *p) +{ + return ctrl_mz_data_common(data, p, false); +} + +static int ctrl_mz_data_blocking(struct stmvl53lx_data *data, void __user *p) +{ + return ctrl_mz_data_blocking_common(data, p, false); +} + +static int ctrl_calibration_data(struct stmvl53lx_data *data, void __user *p) +{ + int rc = 0; + struct stmvl53lx_ioctl_calibration_data_t calib; + int data_offset = offsetof(struct stmvl53lx_ioctl_calibration_data_t, data); + + mutex_lock(&data->work_mutex); + + if (data->is_device_remove) { + rc = -ENODEV; + goto done; + } + rc = copy_from_user(&calib, p, data_offset); + if (rc) { + vl53lx_errmsg("fail to detect read or write %d", rc); + rc = -EFAULT; + goto done; + } + + if (calib.is_read) { + memset(&calib.data, 0, sizeof(calib.data)); + rc = VL53LX_GetCalibrationData(&data->stdev, &calib.data); + if (rc) { + vl53lx_errmsg("VL53LX_GetCalibrationData fail %d", rc); + rc = store_last_error(data, rc); + goto done; + } + rc = copy_to_user(p + data_offset, &calib.data, + sizeof(calib.data)); + } else { + if (data->enable_sensor) { + rc = -EBUSY; + vl53lx_errmsg("can't set calib data while ranging\n"); + goto done; + } + rc = copy_from_user(&calib.data, p + data_offset, + sizeof(calib.data)); + if (rc) { + vl53lx_errmsg("fail to copy calib data"); + rc = -EFAULT; + goto done; + } + rc = VL53LX_SetCalibrationData(&data->stdev, &calib.data); + if (rc) { + vl53lx_errmsg("VL53LX_SetCalibrationData fail %d", rc); + rc = store_last_error(data, rc); + } + } + +done: + mutex_unlock(&data->work_mutex); + return rc; +} + +VL53LX_Error VL53LX_set_ref_spad_char_config( + VL53LX_DEV Dev, + uint8_t vcsel_period_a, + uint32_t phasecal_timeout_us, + uint16_t total_rate_target_mcps, + uint16_t max_count_rate_rtn_limit_mcps, + uint16_t min_count_rate_rtn_limit_mcps, + uint16_t fast_osc_frequency) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + uint8_t buffer[2]; + + uint32_t macro_period_us = 0; + uint32_t timeout_mclks = 0; + + macro_period_us = VL53LX_calc_macro_period_us(fast_osc_frequency, vcsel_period_a); + if (macro_period_us == 0) + macro_period_us = 1; + + timeout_mclks = phasecal_timeout_us << 12; + timeout_mclks = timeout_mclks + (macro_period_us>>1); + timeout_mclks = timeout_mclks / macro_period_us; + + if (timeout_mclks > 0xFF) + pdev->gen_cfg.phasecal_config__timeout_macrop = 0xFF; + else + pdev->gen_cfg.phasecal_config__timeout_macrop = (uint8_t)timeout_mclks; + + pdev->tim_cfg.range_config__vcsel_period_a = vcsel_period_a; + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_WrByte(Dev, VL53LX_PHASECAL_CONFIG__TIMEOUT_MACROP, pdev->gen_cfg.phasecal_config__timeout_macrop); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_WrByte(Dev, VL53LX_RANGE_CONFIG__VCSEL_PERIOD_A, pdev->tim_cfg.range_config__vcsel_period_a); + + buffer[0] = pdev->tim_cfg.range_config__vcsel_period_a; + buffer[1] = pdev->tim_cfg.range_config__vcsel_period_a; + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_WriteMulti(Dev, VL53LX_SD_CONFIG__WOI_SD0, buffer, 2); + + pdev->customer.ref_spad_char__total_rate_target_mcps = total_rate_target_mcps; + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_WrWord(Dev, VL53LX_REF_SPAD_CHAR__TOTAL_RATE_TARGET_MCPS, total_rate_target_mcps); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_WrWord(Dev, VL53LX_RANGE_CONFIG__SIGMA_THRESH, max_count_rate_rtn_limit_mcps); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_WrWord(Dev, VL53LX_RANGE_CONFIG__MIN_COUNT_RATE_RTN_LIMIT_MCPS, min_count_rate_rtn_limit_mcps); + + return status; +} + +VL53LX_Error VL53LX_start_test(VL53LX_DEV Dev, uint8_t test_mode__ctrl) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + if (status == VL53LX_ERROR_NONE) { + status = VL53LX_WrByte(Dev, VL53LX_TEST_MODE__CTRL, test_mode__ctrl); + } + return status; +} + +VL53LX_Error VL53LX_poll_for_range_completion(VL53LX_DEV Dev, uint32_t timeout_ms) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + uint8_t gpio__mux_active_high_hv = 0; + uint8_t interrupt_ready = 0; + + gpio__mux_active_high_hv = pdev->stat_cfg.gpio_hv_mux__ctrl & VL53LX_DEVICEINTERRUPTLEVEL_ACTIVE_MASK; + + if (gpio__mux_active_high_hv == VL53LX_DEVICEINTERRUPTLEVEL_ACTIVE_HIGH) + interrupt_ready = 0x01; + else + interrupt_ready = 0x00; + + status = VL53LX_WaitValueMaskEx(Dev, timeout_ms, VL53LX_GPIO__TIO_HV_STATUS, interrupt_ready, 0x01, VL53LX_POLLING_DELAY_MS); + return status; +} + +VL53LX_Error VL53LX_wait_for_test_completion(VL53LX_DEV Dev) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + uint8_t data_ready = 0; + + if (pdev->wait_method == VL53LX_WAIT_METHOD_BLOCKING) { + status = VL53LX_poll_for_range_completion(Dev, VL53LX_TEST_COMPLETION_POLLING_TIMEOUT_MS); + + } else { + data_ready = 0; + while (data_ready == 0x00 && status == VL53LX_ERROR_NONE) { + status = VL53LX_is_new_data_ready(Dev, &data_ready); + if (status == VL53LX_ERROR_NONE) { + status = VL53LX_WaitMs(Dev, VL53LX_POLLING_DELAY_MS); + } + } + } + return status; +} + +VL53LX_Error VL53LX_clear_interrupt(VL53LX_DEV Dev) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + pdev->sys_ctrl.system__interrupt_clear = VL53LX_CLEAR_RANGE_INT; + + status = VL53LX_WrByte(Dev, VL53LX_SYSTEM__INTERRUPT_CLEAR, pdev->sys_ctrl.system__interrupt_clear); + + return status; +} + +VL53LX_Error VL53LX_run_device_test(VL53LX_DEV Dev, VL53LX_DeviceTestMode device_test_mode) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + uint8_t comms_buffer[2]; + uint8_t gpio_hv_mux__ctrl = 0; + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_RdByte(Dev, VL53LX_GPIO_HV_MUX__CTRL, &gpio_hv_mux__ctrl); + + if (status == VL53LX_ERROR_NONE) + pdev->stat_cfg.gpio_hv_mux__ctrl = gpio_hv_mux__ctrl; + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_start_test(Dev, device_test_mode); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_wait_for_test_completion(Dev); + + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_ReadMulti(Dev, VL53LX_RESULT__RANGE_STATUS, comms_buffer, 2); + + if (status == VL53LX_ERROR_NONE) { + pdev->sys_results.result__range_status = comms_buffer[0]; + pdev->sys_results.result__report_status = comms_buffer[1]; + } + + pdev->sys_results.result__range_status &= VL53LX_RANGE_STATUS__RANGE_STATUS_MASK; + + if (status == VL53LX_ERROR_NONE) { + if (status == VL53LX_ERROR_NONE) + status = VL53LX_clear_interrupt(Dev); + } + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_start_test(Dev, 0x00); + + return status; +} + +VL53LX_Error VL53LX_run_ref_spad_char(VL53LX_DEV Dev, VL53LX_Error *pcal_status) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + + uint8_t comms_buffer[6]; + + VL53LX_refspadchar_config_t *prefspadchar = &(pdev->refspadchar); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_enable_powerforce(Dev); + + if (status == VL53LX_ERROR_NONE) + status = + VL53LX_set_ref_spad_char_config( + Dev, + prefspadchar->VL53LX_p_005, + prefspadchar->timeout_us, + prefspadchar->target_count_rate_mcps, + prefspadchar->max_count_rate_limit_mcps, + prefspadchar->min_count_rate_limit_mcps, + pdev->stat_nvm.osc_measured__fast_osc__frequency); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_run_device_test(Dev, prefspadchar->device_test_mode); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_ReadMulti(Dev, VL53LX_REF_SPAD_CHAR_RESULT__NUM_ACTUAL_REF_SPADS, comms_buffer, 2); + + if (status == VL53LX_ERROR_NONE) { + pdev->dbg_results.ref_spad_char_result__num_actual_ref_spads = comms_buffer[0]; + pdev->dbg_results.ref_spad_char_result__ref_location = comms_buffer[1]; + } + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_WriteMulti(Dev, VL53LX_REF_SPAD_MAN__NUM_REQUESTED_REF_SPADS, comms_buffer, 2); + + if (status == VL53LX_ERROR_NONE) { + pdev->customer.ref_spad_man__num_requested_ref_spads = comms_buffer[0]; + pdev->customer.ref_spad_man__ref_location = comms_buffer[1]; + } + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_ReadMulti(Dev, VL53LX_RESULT__SPARE_0_SD1, comms_buffer, 6); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_WriteMulti(Dev, VL53LX_GLOBAL_CONFIG__SPAD_ENABLES_REF_0, comms_buffer, 6); + + if (status == VL53LX_ERROR_NONE) { + pdev->customer.global_config__spad_enables_ref_0 = comms_buffer[0]; + pdev->customer.global_config__spad_enables_ref_1 = comms_buffer[1]; + pdev->customer.global_config__spad_enables_ref_2 = comms_buffer[2]; + pdev->customer.global_config__spad_enables_ref_3 = comms_buffer[3]; + pdev->customer.global_config__spad_enables_ref_4 = comms_buffer[4]; + pdev->customer.global_config__spad_enables_ref_5 = comms_buffer[5]; + } + + if (status == VL53LX_ERROR_NONE) { + switch (pdev->sys_results.result__range_status) { + case VL53LX_DEVICEERROR_REFSPADCHARNOTENOUGHDPADS: + status = VL53LX_WARNING_REF_SPAD_CHAR_NOT_ENOUGH_SPADS; + break; + case VL53LX_DEVICEERROR_REFSPADCHARMORETHANTARGET: + status = VL53LX_WARNING_REF_SPAD_CHAR_RATE_TOO_HIGH; + break; + case VL53LX_DEVICEERROR_REFSPADCHARLESSTHANTARGET: + status = VL53LX_WARNING_REF_SPAD_CHAR_RATE_TOO_LOW; + break; + } + } + *pcal_status = status; + IGNORE_STATUS(IGNORE_REF_SPAD_CHAR_NOT_ENOUGH_SPADS, VL53LX_WARNING_REF_SPAD_CHAR_NOT_ENOUGH_SPADS, status); + IGNORE_STATUS(IGNORE_REF_SPAD_CHAR_RATE_TOO_HIGH, VL53LX_WARNING_REF_SPAD_CHAR_RATE_TOO_HIGH, status); + IGNORE_STATUS(IGNORE_REF_SPAD_CHAR_RATE_TOO_LOW, VL53LX_WARNING_REF_SPAD_CHAR_RATE_TOO_LOW, status); + + 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; + + pdev = VL53LXDevStructGetLLDriverHandle(Dev); + pc = &pdev->customer; + + if (Status == VL53LX_ERROR_NONE) { + DistanceMode = VL53LXDevDataGet(Dev, CurrentParameters.DistanceMode); + Status = VL53LX_run_ref_spad_char(Dev, &RawStatus); + + if (Status == VL53LX_ERROR_NONE) + Status = VL53LX_SetDistanceMode(Dev, DistanceMode); + } + + 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]; + } + } + return Status; +} + +static int ctrl_perform_calibration_ref_spad_lock(struct stmvl53lx_data *data, struct stmvl53lx_ioctl_perform_calibration_t *calib) +{ + int rc = VL53LX_PerformRefSpadManagement(&data->stdev); + + if (rc) { + vl53lx_errmsg("VL53LX_PerformRefSpadManagement fail => %d", rc); + rc = store_last_error(data, rc); + } + return rc; +} + +void VL53LX_hist_xtalk_extract_data_init(VL53LX_hist_xtalk_extract_data_t *pxtalk_data) +{ int32_t lb = 0; + + pxtalk_data->sample_count = 0U; + pxtalk_data->pll_period_mm = 0U; + pxtalk_data->peak_duration_us_sum = 0U; + pxtalk_data->effective_spad_count_sum = 0U; + pxtalk_data->zero_distance_phase_sum = 0U; + pxtalk_data->zero_distance_phase_avg = 0U; + pxtalk_data->event_scaler_sum = 0U; + pxtalk_data->event_scaler_avg = 4096U; + pxtalk_data->signal_events_sum = 0; + pxtalk_data->xtalk_rate_kcps_per_spad = 0U; + pxtalk_data->VL53LX_p_012 = 0U; + pxtalk_data->VL53LX_p_013 = 0U; + pxtalk_data->target_start = 0U; + + for (lb = 0; lb < VL53LX_XTALK_HISTO_BINS; lb++) + pxtalk_data->bin_data_sums[lb] = 0; +} + +VL53LX_Error VL53LX_wait_for_range_completion(VL53LX_DEV Dev) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + uint8_t data_ready = 0; + + if (pdev->wait_method == VL53LX_WAIT_METHOD_BLOCKING) { + status = VL53LX_poll_for_range_completion(Dev, VL53LX_RANGE_COMPLETION_POLLING_TIMEOUT_MS); + } else { + data_ready = 0; + while (data_ready == 0x00 && status == VL53LX_ERROR_NONE) { + status = VL53LX_is_new_data_ready(Dev, &data_ready); + if (status == VL53LX_ERROR_NONE) { + status = VL53LX_WaitMs(Dev, VL53LX_POLLING_DELAY_MS); + } + } + } + return status; +} + +VL53LX_Error VL53LX_hist_xtalk_extract_calc_window( + int16_t target_distance_mm, + uint16_t target_width_oversize, + VL53LX_histogram_bin_data_t *phist_bins, + VL53LX_hist_xtalk_extract_data_t *pxtalk_data) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + pxtalk_data->pll_period_mm = VL53LX_calc_pll_period_mm(phist_bins->VL53LX_p_015); + if (pxtalk_data->pll_period_mm == 0) + pxtalk_data->pll_period_mm = 1; + + pxtalk_data->xtalk_width_phase = (int32_t)phist_bins->vcsel_width * 128; + pxtalk_data->target_width_phase = pxtalk_data->xtalk_width_phase + (int32_t)target_width_oversize * 128; + + pxtalk_data->xtalk_start_phase = (int32_t)phist_bins->zero_distance_phase - (pxtalk_data->xtalk_width_phase / 2); + pxtalk_data->xtalk_end_phase = (int32_t)pxtalk_data->xtalk_start_phase + pxtalk_data->xtalk_width_phase; + + if (pxtalk_data->xtalk_start_phase < 0) + pxtalk_data->xtalk_start_phase = 0; + + pxtalk_data->VL53LX_p_012 = (uint8_t)(pxtalk_data->xtalk_start_phase / 2048); + pxtalk_data->VL53LX_p_013 = (uint8_t)((pxtalk_data->xtalk_end_phase + 2047) / 2048); + + pxtalk_data->target_start_phase = (int32_t)target_distance_mm * 2048 * 16; + pxtalk_data->target_start_phase += ((int32_t)pxtalk_data->pll_period_mm / 2); + pxtalk_data->target_start_phase /= (int32_t)pxtalk_data->pll_period_mm; + pxtalk_data->target_start_phase += (int32_t)phist_bins->zero_distance_phase; + pxtalk_data->target_start_phase -= (pxtalk_data->target_width_phase / 2); + pxtalk_data->target_end_phase = (int32_t)pxtalk_data->target_start_phase + pxtalk_data->target_width_phase; + + if (pxtalk_data->target_start_phase < 0) + pxtalk_data->target_start_phase = 0; + + pxtalk_data->target_start = (uint8_t)(pxtalk_data->target_start_phase / 2048); + + if (pxtalk_data->VL53LX_p_013 > (pxtalk_data->target_start-1)) + pxtalk_data->VL53LX_p_013 = pxtalk_data->target_start-1; + + pxtalk_data->effective_width = (2048 * ((int32_t)pxtalk_data->VL53LX_p_013+1)); + pxtalk_data->effective_width -= pxtalk_data->xtalk_start_phase; + + if (pxtalk_data->effective_width > pxtalk_data->xtalk_width_phase) + pxtalk_data->effective_width = pxtalk_data->xtalk_width_phase; + + if (pxtalk_data->effective_width < 1) + pxtalk_data->effective_width = 1; + + pxtalk_data->event_scaler = pxtalk_data->xtalk_width_phase * 1000; + pxtalk_data->event_scaler += (pxtalk_data->effective_width / 2); + pxtalk_data->event_scaler /= pxtalk_data->effective_width; + + if (pxtalk_data->event_scaler < 1000) + pxtalk_data->event_scaler = 1000; + + if (pxtalk_data->event_scaler > 4000) + pxtalk_data->event_scaler = 4000; + + pxtalk_data->event_scaler_sum += pxtalk_data->event_scaler; + + pxtalk_data->peak_duration_us_sum += (uint32_t)phist_bins->peak_duration_us; + + pxtalk_data->effective_spad_count_sum += (uint32_t)phist_bins->result__dss_actual_effective_spads; + + pxtalk_data->zero_distance_phase_sum += (uint32_t)phist_bins->zero_distance_phase; + + return status; +} + +VL53LX_Error VL53LX_hist_xtalk_extract_calc_event_sums(VL53LX_histogram_bin_data_t *phist_bins, VL53LX_hist_xtalk_extract_data_t *pxtalk_data) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + uint8_t lb = 0; + uint8_t i = 0; + + for (lb = pxtalk_data->VL53LX_p_012; lb <= pxtalk_data->VL53LX_p_013; lb++) { + i = (lb + phist_bins->number_of_ambient_bins + phist_bins->VL53LX_p_021) % phist_bins->VL53LX_p_021; + + pxtalk_data->signal_events_sum += phist_bins->bin_data[i]; + pxtalk_data->signal_events_sum -= phist_bins->VL53LX_p_028; + } + + for (lb = 0; lb < VL53LX_XTALK_HISTO_BINS && lb < phist_bins->VL53LX_p_021; lb++) { + i = (lb + phist_bins->number_of_ambient_bins + phist_bins->VL53LX_p_021) % phist_bins->VL53LX_p_021; + + pxtalk_data->bin_data_sums[lb] += phist_bins->bin_data[i]; + pxtalk_data->bin_data_sums[lb] -= phist_bins->VL53LX_p_028; + } + + pxtalk_data->sample_count += 1; + return status; +} + +VL53LX_Error VL53LX_hist_xtalk_extract_update( + int16_t target_distance_mm, + uint16_t target_width_oversize, + VL53LX_histogram_bin_data_t *phist_bins, + VL53LX_hist_xtalk_extract_data_t *pxtalk_data) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + status = VL53LX_hist_xtalk_extract_calc_window(target_distance_mm, target_width_oversize, phist_bins, pxtalk_data); + + if (status == VL53LX_ERROR_NONE) { + status = VL53LX_hist_xtalk_extract_calc_event_sums(phist_bins, pxtalk_data); + } + return status; +} + +VL53LX_Error VL53LX_hist_xtalk_extract_calc_rate_per_spad(VL53LX_hist_xtalk_extract_data_t *pxtalk_data) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + uint64_t tmp64_0 = 0; + uint64_t tmp64_1 = 0; + uint64_t xtalk_per_spad = 0; + + tmp64_1 = (uint64_t)pxtalk_data->effective_spad_count_sum * (uint64_t)pxtalk_data->peak_duration_us_sum; + + if (pxtalk_data->signal_events_sum < 0) { + pxtalk_data->signal_events_sum = 0; + + tmp64_0 = ((uint64_t)pxtalk_data->sample_count * (uint64_t)pxtalk_data->event_scaler_avg * 256U) << 9U; + if (tmp64_0 > 0) { + pxtalk_data->signal_events_sum = (int32_t)do_division_u((50U * tmp64_1), tmp64_0); + } + } + tmp64_0 = ((uint64_t)pxtalk_data->signal_events_sum * (uint64_t)pxtalk_data->sample_count * (uint64_t)pxtalk_data->event_scaler_avg * 256U) << 9U; + if (tmp64_1 > 0U) { + tmp64_0 = tmp64_0 + (tmp64_1 >> 1U); + xtalk_per_spad = do_division_u(tmp64_0, tmp64_1); + } else { + xtalk_per_spad = (uint64_t)tmp64_0; + } + + pxtalk_data->xtalk_rate_kcps_per_spad = (uint32_t)xtalk_per_spad; + return status; +} + +VL53LX_Error VL53LX_hist_xtalk_extract_calc_shape(VL53LX_hist_xtalk_extract_data_t *pxtalk_data, VL53LX_xtalk_histogram_shape_t *pxtalk_shape) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + + int32_t lb = 0; + uint64_t total_events = 0U; + uint64_t tmp64_0 = 0U; + int32_t remaining_area = 1024; + + pxtalk_shape->VL53LX_p_019 = 0; + pxtalk_shape->VL53LX_p_020 = VL53LX_XTALK_HISTO_BINS; + pxtalk_shape->VL53LX_p_021 = VL53LX_XTALK_HISTO_BINS; + + pxtalk_shape->zero_distance_phase = (uint16_t)pxtalk_data->zero_distance_phase_avg; + pxtalk_shape->phasecal_result__reference_phase = (uint16_t)pxtalk_data->zero_distance_phase_avg + (3*2048); + + if (pxtalk_data->signal_events_sum > 0) + total_events = (uint64_t)pxtalk_data->signal_events_sum * (uint64_t)pxtalk_data->event_scaler_avg; + else + total_events = 1; + if (total_events == 0) + total_events = 1; + + remaining_area = 1024; + pxtalk_data->max_shape_value = 0; + + for (lb = 0; lb < VL53LX_XTALK_HISTO_BINS; lb++) { + if ((lb < (int32_t)pxtalk_data->VL53LX_p_012 || lb > (int32_t)pxtalk_data->VL53LX_p_013) || pxtalk_data->bin_data_sums[lb] < 0) { + if (remaining_area > 0 && remaining_area < 1024) { + if (remaining_area > pxtalk_data->max_shape_value) { + pxtalk_shape->bin_data[lb] = (uint32_t)pxtalk_data->max_shape_value; + remaining_area -= pxtalk_data->max_shape_value; + } else { + pxtalk_shape->bin_data[lb] = (uint32_t)remaining_area; + remaining_area = 0; + } + } else { + pxtalk_shape->bin_data[lb] = 0; + } + } else { + tmp64_0 = (uint64_t)pxtalk_data->bin_data_sums[lb] * 1024U * 1000U; + tmp64_0 += (total_events >> 1); + tmp64_0 = do_division_u(tmp64_0, total_events); + if (tmp64_0 > 0xFFFFU) + tmp64_0 = 0xFFFFU; + + pxtalk_shape->bin_data[lb] = (uint32_t)tmp64_0; + + if ((int32_t)pxtalk_shape->bin_data[lb] > pxtalk_data->max_shape_value) + pxtalk_data->max_shape_value = (int32_t)pxtalk_shape->bin_data[lb]; + + remaining_area -= (int32_t)pxtalk_shape->bin_data[lb]; + } + } + return status; +} + +VL53LX_Error VL53LX_hist_xtalk_extract_fini( + VL53LX_histogram_bin_data_t *phist_bins, + VL53LX_hist_xtalk_extract_data_t *pxtalk_data, + VL53LX_xtalk_calibration_results_t *pxtalk_cal, + VL53LX_xtalk_histogram_shape_t *pxtalk_shape) +{ + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_xtalk_calibration_results_t *pX = pxtalk_cal; + + if (pxtalk_data->sample_count > 0) { + pxtalk_data->event_scaler_avg = pxtalk_data->event_scaler_sum; + pxtalk_data->event_scaler_avg += (pxtalk_data->sample_count >> 1); + pxtalk_data->event_scaler_avg /= pxtalk_data->sample_count; + + status = VL53LX_hist_xtalk_extract_calc_rate_per_spad(pxtalk_data); + if (status == VL53LX_ERROR_NONE) { + pxtalk_data->zero_distance_phase_avg = pxtalk_data->zero_distance_phase_sum; + pxtalk_data->zero_distance_phase_avg += (pxtalk_data->sample_count >> 1); + pxtalk_data->zero_distance_phase_avg /= pxtalk_data->sample_count; + status = VL53LX_hist_xtalk_extract_calc_shape(pxtalk_data, pxtalk_shape); + + pxtalk_shape->phasecal_result__vcsel_start = phist_bins->phasecal_result__vcsel_start; + pxtalk_shape->cal_config__vcsel_start = phist_bins->cal_config__vcsel_start; + pxtalk_shape->vcsel_width = phist_bins->vcsel_width; + pxtalk_shape->VL53LX_p_015 = phist_bins->VL53LX_p_015; + } + + if (status == VL53LX_ERROR_NONE) { + pX->algo__crosstalk_compensation_plane_offset_kcps = pxtalk_data->xtalk_rate_kcps_per_spad; + pX->algo__crosstalk_compensation_x_plane_gradient_kcps = 0U; + pX->algo__crosstalk_compensation_y_plane_gradient_kcps = 0U; + } + } + return status; +} + +VL53LX_Error VL53LX_run_hist_xtalk_extraction(VL53LX_DEV Dev, int16_t cal_distance_mm, VL53LX_Error *pcal_status) +{ + #define OVERSIZE 4 + VL53LX_Error status = VL53LX_ERROR_NONE; + VL53LX_LLDriverData_t *pdev = VL53LXDevStructGetLLDriverHandle(Dev); + VL53LX_xtalkextract_config_t *pX = &(pdev->xtalk_extract_cfg); + VL53LX_xtalk_config_t *pC = &(pdev->xtalk_cfg); + VL53LX_xtalk_calibration_results_t *pXC = &(pdev->xtalk_cal); + + uint8_t smudge_corr_en = 0; + uint8_t i = 0; + int8_t k = 0; + uint8_t nbloops; + int32_t initMergeSize = 0; + int32_t MergeEnabled = 0; + uint32_t deltaXtalk; + uint32_t stepXtalk; + uint32_t XtalkMin; + uint32_t XtalkMax; + uint8_t measurement_mode = VL53LX_DEVICEMEASUREMENTMODE_BACKTOBACK; + int8_t MaxId; + uint8_t histo_merge_nb; + uint8_t wait_for_accumulation; + VL53LX_range_results_t *prange_results = (VL53LX_range_results_t *) pdev->wArea1; + uint8_t Very1stRange = 0; + + if (status == VL53LX_ERROR_NONE) + status = + VL53LX_set_preset_mode( + Dev, + VL53LX_DEVICEPRESETMODE_HISTOGRAM_LONG_RANGE, + pX->dss_config__target_total_rate_mcps, + pX->phasecal_config_timeout_us, + pX->mm_config_timeout_us, + pX->range_config_timeout_us, + 100); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_disable_xtalk_compensation(Dev); + + smudge_corr_en = pdev->smudge_correct_config.smudge_corr_enabled; + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_dynamic_xtalk_correction_disable(Dev); + + VL53LX_load_patch(Dev); + + VL53LX_get_tuning_parm(Dev, VL53LX_TUNINGPARM_HIST_MERGE_MAX_SIZE, &initMergeSize); + VL53LX_get_tuning_parm(Dev, VL53LX_TUNINGPARM_HIST_MERGE, &MergeEnabled); + memset(&pdev->xtalk_cal, 0, sizeof(pdev->xtalk_cal)); + + if (status == VL53LX_ERROR_NONE) + status = VL53LX_init_and_start_range(Dev, measurement_mode, VL53LX_DEVICECONFIGLEVEL_CUSTOMER_ONWARDS); + + MaxId = pdev->tuning_parms.tp_hist_merge_max_size - 1; + nbloops = (MergeEnabled == 0 ? 1 : 2); + for (k = 0; k < nbloops; k++) { + VL53LX_hist_xtalk_extract_data_init(&(pdev->xtalk_extract)); + VL53LX_set_tuning_parm(Dev, VL53LX_TUNINGPARM_HIST_MERGE_MAX_SIZE, k * MaxId + 1); + + for (i = 0; i <= pX->num_of_samples; i++) { + if (status == VL53LX_ERROR_NONE) + status = VL53LX_wait_for_range_completion(Dev); + if (status == VL53LX_ERROR_NONE) + status = VL53LX_get_device_results(Dev, VL53LX_DEVICERESULTSLEVEL_FULL, prange_results); + Very1stRange = (pdev->ll_state.rd_device_state == VL53LX_DEVICESTATE_RANGING_WAIT_GPH_SYNC); + + VL53LX_compute_histo_merge_nb(Dev, &histo_merge_nb); + wait_for_accumulation = ((k != 0) && (MergeEnabled) && (status == VL53LX_ERROR_NONE) && (histo_merge_nb < pdev->tuning_parms.tp_hist_merge_max_size)); + if (wait_for_accumulation) + i = 0; + else { + if ((status == VL53LX_ERROR_NONE) && (!Very1stRange)) { + status = VL53LX_hist_xtalk_extract_update(cal_distance_mm, OVERSIZE, &(pdev->hist_data), &(pdev->xtalk_extract)); + } + } + if (status == VL53LX_ERROR_NONE) + status = VL53LX_clear_interrupt_and_enable_next_range(Dev, measurement_mode); + } + if (status == VL53LX_ERROR_NONE) + status = VL53LX_hist_xtalk_extract_fini(&(pdev->hist_data), &(pdev->xtalk_extract), &(pdev->xtalk_cal), &(pdev->xtalk_shapes.xtalk_shape)); + + if (status == VL53LX_ERROR_NONE) { + pXC->algo__xtalk_cpo_HistoMerge_kcps[k * MaxId] = pXC->algo__crosstalk_compensation_plane_offset_kcps; + } + } + VL53LX_stop_range(Dev); + + VL53LX_set_tuning_parm(Dev, VL53LX_TUNINGPARM_HIST_MERGE_MAX_SIZE, initMergeSize); + VL53LX_unload_patch(Dev); + + if (status != VL53LX_ERROR_NONE) + status = VL53LX_ERROR_XTALK_EXTRACTION_SIGMA_LIMIT_FAIL; + else if ((MergeEnabled == 1) && (MaxId > 0)) { + XtalkMin = pdev->xtalk_cal.algo__xtalk_cpo_HistoMerge_kcps[0]; + XtalkMax = pdev->xtalk_cal.algo__xtalk_cpo_HistoMerge_kcps[MaxId]; + pdev->xtalk_cal.algo__crosstalk_compensation_plane_offset_kcps = XtalkMin; + if (XtalkMax > XtalkMin) { + deltaXtalk = XtalkMax - XtalkMin; + stepXtalk = deltaXtalk / MaxId; + for (k = 1; k < MaxId; k++) + pdev->xtalk_cal.algo__xtalk_cpo_HistoMerge_kcps[k] = XtalkMin + stepXtalk * k; + } else + status = VL53LX_ERROR_XTALK_EXTRACTION_SIGMA_LIMIT_FAIL; + } + if (status == VL53LX_ERROR_NONE) { + pC->algo__crosstalk_compensation_x_plane_gradient_kcps = pXC->algo__crosstalk_compensation_x_plane_gradient_kcps; + pC->algo__crosstalk_compensation_y_plane_gradient_kcps = pXC->algo__crosstalk_compensation_y_plane_gradient_kcps; + pC->algo__crosstalk_compensation_plane_offset_kcps = pXC->algo__crosstalk_compensation_plane_offset_kcps; + } + pdev->xtalk_results.cal_status = status; + *pcal_status = pdev->xtalk_results.cal_status; + + status = VL53LX_enable_xtalk_compensation(Dev); + if (smudge_corr_en == 1) + status = VL53LX_dynamic_xtalk_correction_enable(Dev); + + 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; + + 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); + } + + return Status; +} + +static int ctrl_perform_calibration_crosstalk_lock(struct stmvl53lx_data *data, struct stmvl53lx_ioctl_perform_calibration_t *calib) +{ + int rc = 0; + + rc = stmvl53lx_sendparams(data); + if (rc) + goto done; + + rc = VL53LX_PerformXTalkCalibration(&data->stdev); + if (rc) { + vl53lx_errmsg("VL53LX_PerformXTalkCalibration fail => %d", rc); + rc = store_last_error(data, rc); + } + + data->crosstalk_enable = 1; +done: + return rc; +} + +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; + + 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)); + } + return Status; +} + +static int ctrl_perform_simple_calibration_offset_lock(struct stmvl53lx_data *data, struct stmvl53lx_ioctl_perform_calibration_t *calib) +{ + int rc = 0; + + data->is_delay_allowed = 1; + rc = stmvl53lx_sendparams(data); + if (rc) + goto done; + + rc = VL53LX_PerformOffsetSimpleCalibration(&data->stdev, calib->param1); + data->is_delay_allowed = 0; + if (rc) { + vl53lx_errmsg( + "VL53LX_PerformOffsetSimpleCalibration fail => %d", rc); + rc = store_last_error(data, rc); + } + +done: + return rc; +} + +VL53LX_Error VL53LX_GetDistanceMode(VL53LX_DEV Dev, VL53LX_DistanceModes *pDistanceMode) +{ + VL53LX_Error Status = VL53LX_ERROR_NONE; + + *pDistanceMode = VL53LXDevDataGet(Dev, CurrentParameters.DistanceMode); + + 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; + + 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); + return Status; +} + +static int ctrl_perform_per_vcsel_calibration_offset_lock(struct stmvl53lx_data *data, struct stmvl53lx_ioctl_perform_calibration_t *calib) +{ + int rc = 0; + + data->is_delay_allowed = 1; + + rc = stmvl53lx_sendparams(data); + if (rc) + goto done; + + rc = VL53LX_PerformOffsetPerVcselCalibration(&data->stdev, calib->param1); + data->is_delay_allowed = 0; + if (rc) { + vl53lx_errmsg( + "VL53LX_PerformOffsetPerVcselCalibration fail => %d", rc); + rc = store_last_error(data, rc); + } + +done: + return rc; +} + +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; + + 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)); + } + + return Status; +} + +static int ctrl_perform_zero_distance_calibration_offset_lock(struct stmvl53lx_data *data, struct stmvl53lx_ioctl_perform_calibration_t *calib) +{ + int rc = 0; + + data->is_delay_allowed = 1; + + rc = stmvl53lx_sendparams(data); + if (rc) + goto done; + + rc = VL53LX_PerformOffsetZeroDistanceCalibration(&data->stdev); + data->is_delay_allowed = 0; + if (rc) { + vl53lx_errmsg( + "VL53LX_PerformOffsetZeroDistanceCalibration fail => %d", rc); + rc = store_last_error(data, rc); + } + +done: + return rc; +} + +static int ctrl_perform_calibration(struct stmvl53lx_data *data, void __user *p) +{ + int rc = 0; + struct stmvl53lx_ioctl_perform_calibration_t calib; + + mutex_lock(&data->work_mutex); + + if (data->is_device_remove) { + rc = -ENODEV; + goto done; + } + data->is_calibrating = true; + rc = copy_from_user(&calib, p, sizeof(calib)); + if (rc) { + rc = -EFAULT; + goto done; + } + if (data->enable_sensor) { + rc = -EBUSY; + vl53lx_errmsg("can't perform calibration while ranging\n"); + goto done; + } + + rc = reset_release(data); + if (rc) + goto done; + + switch (calib.calibration_type) { + case VL53LX_CALIBRATION_REF_SPAD: + rc = ctrl_perform_calibration_ref_spad_lock(data, &calib); + break; + case VL53LX_CALIBRATION_CROSSTALK: + rc = ctrl_perform_calibration_crosstalk_lock(data, &calib); + break; + case VL53LX_CALIBRATION_OFFSET: + rc = ctrl_perform_simple_calibration_offset_lock(data, &calib); + break; + case VL53LX_CALIBRATION_OFFSET_SIMPLE: + rc = ctrl_perform_simple_calibration_offset_lock(data, &calib); + break; + case VL53LX_CALIBRATION_OFFSET_PER_VCSEL: + rc = ctrl_perform_per_vcsel_calibration_offset_lock(data, &calib); + break; + case VL53LX_CALIBRATION_OFFSET_ZERO_DISTANCE: + rc = ctrl_perform_zero_distance_calibration_offset_lock(data, + &calib); + break; + default: + rc = -EINVAL; + break; + } + reset_hold(data); + +done: + data->is_calibrating = false; + data->is_first_start_done = true; + mutex_unlock(&data->work_mutex); + + return rc; +} + +static int ctrl_mz_data_additional(struct stmvl53lx_data *data, void __user *p) +{ + return ctrl_mz_data_common(data, p, true); +} + +static int ctrl_mz_data_blocking_additional(struct stmvl53lx_data *data, void __user *p) +{ + return ctrl_mz_data_blocking_common(data, p, true); +} + +static int stmvl53lx_ioctl_handler(struct stmvl53lx_data *data, unsigned int cmd, unsigned long arg, void __user *p) +{ + int rc = 0; + + if (!data) + return -EINVAL; + + switch (cmd) { + case VL53LX_IOCTL_START: + vl53lx_dbgmsg("VL53LX_IOCTL_START\n"); + rc = ctrl_start(data); + break; + case VL53LX_IOCTL_STOP: + vl53lx_dbgmsg("VL53LX_IOCTL_STOP\n"); + rc = ctrl_stop(data); + break; + case VL53LX_IOCTL_REGISTER: + vl53lx_dbgmsg("VL53LX_IOCTL_REGISTER\n"); + rc = ctrl_reg_access(data, p); + break; + case VL53LX_IOCTL_PARAMETER: + vl53lx_dbgmsg("VL53LX_IOCTL_PARAMETER\n"); + rc = ctrl_params(data, p); + break; + case VL53LX_IOCTL_ROI: + vl53lx_dbgmsg("VL53LX_IOCTL_ROI\n"); + rc = ctrl_roi(data, p); + break; + case VL53LX_IOCTL_MZ_DATA: + rc = ctrl_mz_data(data, p); + break; + case VL53LX_IOCTL_MZ_DATA_BLOCKING: + rc = ctrl_mz_data_blocking(data, p); + break; + case VL53LX_IOCTL_CALIBRATION_DATA: + vl53lx_dbgmsg("VL53LX_IOCTL_CALIBRATION_DATA\n"); + rc = ctrl_calibration_data(data, p); + break; + case VL53LX_IOCTL_PERFORM_CALIBRATION: + vl53lx_dbgmsg("VL53LX_IOCTL_PERFORM_CALIBRATION\n"); + rc = ctrl_perform_calibration(data, p); + break; + case VL53LX_IOCTL_MZ_DATA_ADDITIONAL: + rc = ctrl_mz_data_additional(data, p); + break; + case VL53LX_IOCTL_MZ_DATA_ADDITIONAL_BLOCKING: + rc = ctrl_mz_data_blocking_additional(data, p); + break; + default: + rc = -EINVAL; + break; + } + return rc; +} + +static long stmvl53lx_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + long ret; + struct stmvl53lx_data *data = container_of(file->private_data, struct stmvl53lx_data, miscdev); + ret = stmvl53lx_ioctl_handler(data, cmd, arg, (void __user *)arg); + return ret; +} + +static int stmvl53lx_open(struct inode *inode, struct file *file) +{ + struct stmvl53lx_data *data = container_of(file->private_data, struct stmvl53lx_data, miscdev); + + vl53lx_dbgmsg("Start\n"); + stmvl53lx_module_func_tbl.get(data->client_object); + vl53lx_dbgmsg("End\n"); + + return 0; +} + +static int stmvl53lx_release(struct inode *inode, struct file *file) +{ + struct stmvl53lx_data *data = container_of(file->private_data, struct stmvl53lx_data, miscdev); + + vl53lx_dbgmsg("Start\n"); + stmvl53lx_module_func_tbl.put(data->client_object); + vl53lx_dbgmsg("End\n"); + + return 0; +} + +static const struct file_operations stmvl53lx_ranging_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = stmvl53lx_ioctl, + .open = stmvl53lx_open, + .release = stmvl53lx_release, +}; + +int stmvl53lx_setup(struct stmvl53lx_data *data) +{ + int rc = 0; + VL53LX_DeviceInfo_t dev_info; + + vl53lx_dbgmsg("Enter\n"); + + data->id = allocate_dev_id(); + if (data->id < 0) { + vl53lx_errmsg("too many device already created"); + return -1; + } + vl53lx_dbgmsg("Dev id %d is @%p\n", data->id, data); + stmvl53lx_dev_table[data->id] = data; + + mutex_init(&data->work_mutex); + + INIT_DELAYED_WORK(&data->dwork, stmvl53lx_work_handler); + data->force_device_on_en = force_device_on_en_default; + data->reset_state = 1; + data->is_calibrating = false; + data->last_error = VL53LX_ERROR_NONE; + data->is_device_remove = false; + + rc = stmvl53lx_module_func_tbl.power_up(data->client_object); + if (rc) { + vl53lx_errmsg("%d,error rc %d\n", __LINE__, rc); + goto exit_func_end; + } + + rc = reset_release(data); + if (rc) + goto exit_func_end; + + rc = stmvl53lx_input_setup(data); + if (rc) + goto exit_func_end; + + INIT_LIST_HEAD(&data->simple_data_reader_list); + INIT_LIST_HEAD(&data->mz_data_reader_list); + init_waitqueue_head(&data->waiter_for_data); + data->is_data_valid = false; + + rc = sysfs_create_group(&data->input_dev_ps->dev.kobj, &stmvl53lx_attr_group); + if (rc) { + rc = -ENOMEM; + vl53lx_errmsg("%d error:%d\n", __LINE__, rc); + goto exit_unregister_dev_ps; + } + rc = sysfs_create_bin_file(&data->input_dev_ps->dev.kobj, + &stmvl53lx_calib_data_attr); + if (rc) { + rc = -ENOMEM; + vl53lx_errmsg("%d error:%d\n", __LINE__, rc); + goto exit_unregister_dev_ps; + } + data->enable_sensor = 0; + data->poll_delay_ms = STMVL53LX_CFG_POLL_DELAY_MS; + data->timing_budget = STMVL53LX_CFG_TIMING_BUDGET_US; + data->distance_mode = STMVL53LX_CFG_DEFAULT_DISTANCE_MODE; + data->crosstalk_enable = STMVL53LX_CFG_DEFAULT_CROSSTALK_ENABLE; + data->offset_correction_mode = STMVL53LX_CFG_DEFAULT_OFFSET_CORRECTION_MODE; + data->smudge_correction_mode = STMVL53LX_CFG_DEFAULT_SMUDGE_CORRECTION_MODE; + data->is_xtalk_value_changed = false; + data->is_delay_allowed = true; + + rc = VL53LX_DataInit(&data->stdev); + data->is_delay_allowed = false; + if (rc) { + vl53lx_errmsg("VL53LX_DataInit %d\n", rc); + goto exit_unregister_dev_ps; + } + + rc = VL53LX_GetUserROI(&data->stdev, &(data->roi_cfg)); + if (rc) { + vl53lx_errmsg("VL53LX_GetUserROI %d\n", rc); + goto exit_unregister_dev_ps; + } + + rc = VL53LX_GetDeviceInfo(&data->stdev, &dev_info); + if (rc) { + vl53lx_errmsg("VL53LX_GetDeviceInfo %d\n", rc); + goto exit_unregister_dev_ps; + } + vl53lx_errmsg("device type %x\n", dev_info.ProductType); + + rc = VL53LX_GetOpticalCenter(&data->stdev, &data->optical_offset_x, &data->optical_offset_y); + if (rc) { + vl53lx_errmsg("VL53LX_GetOpticalCenter %d\n", rc); + goto exit_unregister_dev_ps; + } + + rc = setup_tunings(data); + if (rc) { + vl53lx_errmsg("setup_tunings %d\n", rc); + goto exit_unregister_dev_ps; + } + + data->poll_mode = 0; + rc = stmvl53lx_module_func_tbl.start_intr(data->client_object, &data->poll_mode); + if (rc < 0) { + vl53lx_errmsg("can't start no intr\n"); + goto exit_unregister_dev_ps; + } + + data->is_first_irq = true; + data->is_first_start_done = false; + data->is_delay_allowed = false; + + data->miscdev.minor = MISC_DYNAMIC_MINOR; + if (data->id == 0) + strcpy(data->name, VL53LX_MISC_DEV_NAME); + else + sprintf(data->name, "%s%d", VL53LX_MISC_DEV_NAME, data->id); + + data->miscdev.name = data->name; + data->miscdev.fops = &stmvl53lx_ranging_fops; + vl53lx_errmsg("Misc device registration name:%s\n", data->miscdev.name); + rc = misc_register(&data->miscdev); + if (rc != 0) { + vl53lx_errmsg("misc dev reg fail\n"); + goto exit_unregister_dev_ps; + } + reset_hold(data); + return 0; + +exit_unregister_dev_ps: + sysfs_remove_bin_file(&data->input_dev_ps->dev.kobj, + &stmvl53lx_calib_data_attr); + sysfs_remove_group(&data->input_dev_ps->dev.kobj, + &stmvl53lx_attr_group); + input_unregister_device(data->input_dev_ps); + +exit_func_end: + return rc; +} + +static int stmvl53lx_parse_tree(struct device *dev, struct i2c_data *i2c_data) +{ + struct i2c_client *client = (struct i2c_client *) i2c_data->client; + int rc = 0; + u32 reg; + + i2c_data->vdd = NULL; + i2c_data->pwren_gpio = -1; + i2c_data->xsdn_gpio = -1; + i2c_data->intr_gpio = -1; + i2c_data->boot_reg = STMVL53LX_SLAVE_ADDR; + if (force_device) { + i2c_data->xsdn_gpio = xsdn_gpio_nb; + i2c_data->pwren_gpio = pwren_gpio_nb; + i2c_data->intr_gpio = intr_gpio_nb; + client->addr = i2c_addr_nb; + } else if (dev->of_node) { + i2c_data->vdd = devm_regulator_get_optional(dev, "vdd"); + if (IS_ERR(i2c_data->vdd) || i2c_data->vdd == NULL) { + i2c_data->vdd = NULL; + i2c_data->pwren_gpio = of_get_named_gpio(dev->of_node, "pwren-gpio", 0); + if (i2c_data->pwren_gpio < 0) { + i2c_data->pwren_gpio = -1; + vl53lx_wanrmsg("no regulator, nor power gpio => power ctrl disabled"); + } + } + + rc = of_property_read_u32_array(dev->of_node, "reg", ®, 1); + if (rc) { + vl53lx_wanrmsg("Unable to find reg %d 0x%x", rc, i2c_addr_nb); + reg = i2c_addr_nb; + } + client->addr = reg; + + i2c_data->xsdn_gpio = of_get_named_gpio(dev->of_node, "xsdn-gpio", 0); + if (i2c_data->xsdn_gpio < 0) { + vl53lx_wanrmsg("Unable to find xsdn-gpio %d %d", rc, i2c_data->xsdn_gpio); + i2c_data->xsdn_gpio = -1; + } + + i2c_data->intr_gpio = of_get_named_gpio(dev->of_node, "intr-gpio", 0); + if (i2c_data->intr_gpio < 0) { + vl53lx_wanrmsg("Unable to find intr-gpio %d %d", rc, i2c_data->intr_gpio); + i2c_data->intr_gpio = -1; + } + + rc = of_property_read_u32_array(dev->of_node, "boot-reg", &i2c_data->boot_reg, 1); + if (rc) { + vl53lx_wanrmsg("Unable to find boot-reg %d %d", rc, i2c_data->boot_reg); + i2c_data->boot_reg = STMVL53LX_SLAVE_ADDR; + } + } + + rc = get_xsdn(dev, i2c_data); + if (rc) + goto no_xsdn; + rc = get_pwren(dev, i2c_data); + if (rc) + goto no_pwren; + rc = get_intr(dev, i2c_data); + if (rc) + goto no_intr; + + return rc; + +no_intr: + put_intr(i2c_data); +no_pwren: + if (i2c_data->vdd) { + regulator_put(i2c_data->vdd); + i2c_data->vdd = NULL; + } + put_pwren(i2c_data); +no_xsdn: + put_xsdn(i2c_data); + return rc; +} + +static void stmvl53lx_release_gpios(struct i2c_data *i2c_data) +{ + put_xsdn(i2c_data); + if (i2c_data->vdd) { + regulator_put(i2c_data->vdd); + i2c_data->vdd = NULL; + } + put_pwren(i2c_data); + put_intr(i2c_data); +} + +void stmvl53lx_cleanup(struct stmvl53lx_data *data) +{ + int rc = 0; + + vl53lx_dbgmsg("enter\n"); + rc = _ctrl_stop(data); + if (rc < 0) + vl53lx_errmsg("stop failed %d aborting anyway\n", rc); + + if (data->input_dev_ps) { + vl53lx_dbgmsg("to remove sysfs group\n"); + sysfs_remove_group(&data->input_dev_ps->dev.kobj, + &stmvl53lx_attr_group); + sysfs_remove_bin_file(&data->input_dev_ps->dev.kobj, + &stmvl53lx_calib_data_attr); + + vl53lx_dbgmsg("to unregister input dev\n"); + input_unregister_device(data->input_dev_ps); + } + + if (!IS_ERR(data->miscdev.this_device) && + data->miscdev.this_device != NULL) { + vl53lx_dbgmsg("to unregister misc dev\n"); + misc_deregister(&data->miscdev); + } + + data->force_device_on_en = false; + reset_hold(data); + stmvl53lx_module_func_tbl.power_down(data->client_object); + vl53lx_dbgmsg("done\n"); + deallocate_dev_id(data->id); + data->is_device_remove = true; +} + +static int stmvl53lx_probe(struct i2c_client *client) +{ + int rc = 0; + struct stmvl53lx_data *vl53lx_data = NULL; + struct i2c_data *i2c_data = NULL; + + vl53lx_dbgmsg("Enter %s : 0x%02x\n", client->name, client->addr); + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE)) { + rc = -EIO; + return rc; + } + + vl53lx_data = kzalloc(sizeof(struct stmvl53lx_data), GFP_KERNEL); + if (!vl53lx_data) { + rc = -ENOMEM; + return rc; + } + if (vl53lx_data) { + vl53lx_data->client_object = kzalloc(sizeof(struct i2c_data), GFP_KERNEL); + if (!vl53lx_data) + goto done_freemem; + i2c_data = (struct i2c_data *)vl53lx_data->client_object; + } + + i2c_data->client = client; + i2c_data->vl53lx_data = vl53lx_data; + i2c_data->irq = -1; + + rc = stmvl53lx_parse_tree(&i2c_data->client->dev, i2c_data); + if (rc) + goto done_freemem; + + i2c_set_clientdata(client, vl53lx_data); + + rc = stmvl53lx_setup(vl53lx_data); + if (rc) + goto release_gpios; + vl53lx_dbgmsg("End\n"); + + kref_init(&i2c_data->ref); + + return rc; + +release_gpios: + stmvl53lx_release_gpios(i2c_data); + +done_freemem: + kfree(vl53lx_data); + kfree(i2c_data); + + return -1; +} + +static void stmvl53lx_remove(struct i2c_client *client) +{ + struct stmvl53lx_data *data = i2c_get_clientdata(client); + struct i2c_data *i2c_data = (struct i2c_data *)data->client_object; + + vl53lx_dbgmsg("Enter\n"); + mutex_lock(&data->work_mutex); + stmvl53lx_cleanup(data); + + stmvl53lx_release_gpios(i2c_data); + + mutex_unlock(&data->work_mutex); + + stmvl53lx_put(data->client_object); + + vl53lx_dbgmsg("End\n"); + + return; +} + +#ifdef CONFIG_PM_SLEEP + +void stmvl53lx_pm_suspend_stop(struct stmvl53lx_data *data) +{ + int rc = 0; + + vl53lx_dbgmsg("Enter\n"); + + rc = _ctrl_stop(data); + if (rc < 0) + vl53lx_errmsg("stop failed %d aborting anyway\n", rc); + + vl53lx_dbgmsg("done\n"); +} + +static int stmvl53lx_suspend(struct device *dev) +{ + struct stmvl53lx_data *data = i2c_get_clientdata(to_i2c_client(dev)); + + vl53lx_dbgmsg("Enter\n"); + mutex_lock(&data->work_mutex); + + stmvl53lx_pm_suspend_stop(data); + + mutex_unlock(&data->work_mutex); + + vl53lx_dbgmsg("End\n"); + + return 0; +} + +static int stmvl53lx_resume(struct device *dev) +{ +#if 0 + struct stmvl53lx_data *data = i2c_get_clientdata(to_i2c_client(dev)); + + vl53lx_dbgmsg("Enter\n"); + + mutex_lock(&data->work_mutex); + + /* do nothing user will restart measurements */ + + mutex_unlock(&data->work_mutex); + + vl53lx_dbgmsg("End\n"); +#else + vl53lx_dbgmsg("Enter\n"); + vl53lx_dbgmsg("End\n"); +#endif + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(stmvl53lx_pm_ops, stmvl53lx_suspend, stmvl53lx_resume); + +static const struct i2c_device_id stmvl53lx_id[] = { + { STMVL53LX_DRV_NAME, 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, stmvl53lx_id); + +static const struct of_device_id st_stmvl53lx_dt_match[] = { + { .compatible = "st,vl53l4cx", }, + { }, +}; + +static struct i2c_driver stmvl53lx_driver = { + .driver = { + .name = STMVL53LX_DRV_NAME, + .owner = THIS_MODULE, + .of_match_table = st_stmvl53lx_dt_match, + .pm = &stmvl53lx_pm_ops, + }, + .probe = stmvl53lx_probe, + .remove = stmvl53lx_remove, + .id_table = stmvl53lx_id, + +}; + +static int insert_device(void) +{ + int ret = 0; + struct i2c_adapter *adapter; + struct i2c_board_info info = { + .type = "stmvl53lx", + .addr = STMVL53LX_SLAVE_ADDR, + }; + + memset(&info, 0, sizeof(info)); + strcpy(info.type, "stmvl53lx"); + info.addr = STMVL53LX_SLAVE_ADDR; + adapter = i2c_get_adapter(adapter_nb); + if (!adapter) { + ret = -EINVAL; + goto done; + } + + stm_test_i2c_client = i2c_new_client_device(adapter, &info); + if (!stm_test_i2c_client) + ret = -EINVAL; + +done: + return ret; +} + +static int __init stmvl53lx_init(void) +{ + int rc = -1; + + vl53lx_dbgmsg("Enter\n"); + + rc = stmvl53lx_module_func_tbl.init(); + + vl53lx_dbgmsg("End %d\n", rc); + + return rc; +} + +static void __exit stmvl53lx_exit(void) +{ + vl53lx_dbgmsg("Enter\n"); + stmvl53lx_module_func_tbl.deinit(NULL); + if (stmvl53lx_module_func_tbl.clean_up != NULL) + stmvl53lx_module_func_tbl.clean_up(); + vl53lx_dbgmsg("End\n"); +} + +int stmvl53lx_init_i2c(void) +{ + int ret = 0; + + vl53lx_dbgmsg("Enter\n"); + + ret = i2c_add_driver(&stmvl53lx_driver); + if (ret) + vl53lx_errmsg("%d erro ret:%d\n", __LINE__, ret); + + if (!ret && force_device) + ret = insert_device(); + + if (ret) + i2c_del_driver(&stmvl53lx_driver); + + vl53lx_dbgmsg("End with rc:%d\n", ret); + + return ret; +} + +void stmvl53lx_exit_i2c(void *i2c_object) +{ + vl53lx_dbgmsg("Enter\n"); + i2c_del_driver(&stmvl53lx_driver); + vl53lx_dbgmsg("End\n"); +} + +int stmvl53lx_power_up_i2c(void *object) +{ + int rc = 0; + struct i2c_data *data = (struct i2c_data *) object; + + vl53lx_dbgmsg("Enter\n"); + + if (data->vdd) { + rc = regulator_enable(data->vdd); + if (rc) { + vl53lx_errmsg("fail to turn on regulator"); + return rc; + } + } else if (data->pwren_gpio != -1) { + gpio_set_value(data->pwren_gpio, 1); + vl53lx_info("slow power on"); + } else + vl53lx_wanrmsg("no power control"); + + return rc; +} + +int stmvl53lx_power_down_i2c(void *i2c_object) +{ + struct i2c_data *data = (struct i2c_data *) i2c_object; + int rc = 0; + + vl53lx_dbgmsg("Enter\n"); + + if (data->vdd) { + rc = regulator_disable(data->vdd); + if (rc) + vl53lx_errmsg("reg disable failed. rc=%d\n", + rc); + } else if (data->pwren_gpio != -1) { + gpio_set_value(data->pwren_gpio, 0); + } + vl53lx_dbgmsg("power off"); + + vl53lx_dbgmsg("End\n"); + + return rc; +} + +int stmvl53lx_reset_release_i2c(void *i2c_object) +{ + int rc; + struct i2c_data *data = (struct i2c_data *) i2c_object; + + vl53lx_dbgmsg("Enter\n"); + + rc = release_reset(data); + if (rc) + goto error; + + data->vl53lx_data->is_delay_allowed = true; + rc = VL53LX_WaitDeviceBooted(&data->vl53lx_data->stdev); + data->vl53lx_data->is_delay_allowed = false; + if (rc) { + gpio_set_value(data->xsdn_gpio, 0); + vl53lx_errmsg("boot fail with error %d", rc); + data->vl53lx_data->last_error = rc; + rc = -EIO; + } + +error: + vl53lx_dbgmsg("End\n"); + return rc; +} + +int stmvl53lx_reset_hold_i2c(void *i2c_object) +{ + struct i2c_data *data = (struct i2c_data *) i2c_object; + + vl53lx_dbgmsg("Enter\n"); + + gpio_set_value(data->xsdn_gpio, 0); + + vl53lx_dbgmsg("End\n"); + return 0; +} + +void stmvl53lx_clean_up_i2c(void) +{ + if (stm_test_i2c_client) { + vl53lx_dbgmsg("to unregister i2c client\n"); + i2c_unregister_device(stm_test_i2c_client); + } +} + +int stmvl53lx_start_intr(void *object, int *poll_mode) +{ + struct i2c_data *i2c_data; + int rc; + + i2c_data = (struct i2c_data *)object; + if (i2c_data->irq < 0) { + *poll_mode = -1; + return 0; + } + + i2c_data->msg_flag.unhandled_irq_vec = 0; + if (i2c_data->io_flag.intr_started) { + *poll_mode = 0; + return 0; + } + + vl53lx_dbgmsg("to register_irq:%d\n", i2c_data->irq); + rc = request_threaded_irq(i2c_data->irq, NULL, stmvl53lx_irq_handler_i2c, IRQF_TRIGGER_FALLING|IRQF_ONESHOT, "vl53lx_interrupt", (void *)i2c_data); + if (rc) { + vl53lx_errmsg("fail to req threaded irq rc=%d\n", rc); + *poll_mode = 0; + } else { + vl53lx_dbgmsg("irq %d now handled\n", i2c_data->irq); + i2c_data->io_flag.intr_started = 1; + *poll_mode = 0; + } + return rc; +} + +void *stmvl53lx_get(void *object) +{ + struct i2c_data *data = (struct i2c_data *) object; + + vl53lx_dbgmsg("Enter\n"); + kref_get(&data->ref); + vl53lx_dbgmsg("End\n"); + + return object; +} + +void stmvl53lx_put(void *object) +{ + struct i2c_data *data = (struct i2c_data *) object; + + vl53lx_dbgmsg("Enter\n"); + kref_put(&data->ref, memory_release); + vl53lx_dbgmsg("End\n"); +} + +static struct stmvl53lx_module_fn_t stmvl53lx_module_func_tbl = { + .init = stmvl53lx_init_i2c, + .deinit = stmvl53lx_exit_i2c, + .power_up = stmvl53lx_power_up_i2c, + .power_down = stmvl53lx_power_down_i2c, + .reset_release = stmvl53lx_reset_release_i2c, + .reset_hold = stmvl53lx_reset_hold_i2c, + .clean_up = stmvl53lx_clean_up_i2c, + .start_intr = stmvl53lx_start_intr, + .get = stmvl53lx_get, + .put = stmvl53lx_put, +}; + +module_init(stmvl53lx_init); +module_exit(stmvl53lx_exit); + +MODULE_AUTHOR("Song Qiang "); +MODULE_DESCRIPTION("ST vl53l4cx ToF ranging sensor driver"); +MODULE_LICENSE("GPL v2"); -- 2.25.1