From 0010ff03d133bec2a8d976ae665e4fee76779cce Mon Sep 17 00:00:00 2001 From: Mark Watson Date: Wed, 11 Jan 2023 12:58:15 -0400 Subject: [PATCH] drivers: sensor: VL53L1X time-of-flight sensor. The driver utilizes ST Microelectronics library (which exists in modules\hal\st\sensor\vl53l1x. Platform specific headers and source files used by the library are included and adapted for Zephyr. The driver can be configured in proj.conf to use a interrupt/polling methods and the use of the XSHUT pin on the VL53L1X. All uses were tested successfully. Signed-off-by: Mark Watson --- drivers/sensor/CMakeLists.txt | 1 + drivers/sensor/Kconfig | 2 + drivers/sensor/vl53l1x/CMakeLists.txt | 8 + drivers/sensor/vl53l1x/Kconfig | 32 ++ drivers/sensor/vl53l1x/vl53l1.c | 479 ++++++++++++++++++ drivers/sensor/vl53l1x/vl53l1_platform.c | 182 +++++++ drivers/sensor/vl53l1x/vl53l1_platform.h | 149 ++++++ drivers/sensor/vl53l1x/vl53l1_platform_log.h | 200 ++++++++ .../vl53l1x/vl53l1_platform_user_config.h | 61 +++ .../vl53l1x/vl53l1_platform_user_data.h | 83 +++ .../vl53l1x/vl53l1_platform_user_defines.h | 73 +++ drivers/sensor/vl53l1x/vl53l1_types.h | 30 ++ dts/bindings/sensor/st,vl53l1x.yaml | 25 + tests/drivers/build_all/sensor/i2c.dtsi | 7 + 14 files changed, 1332 insertions(+) create mode 100644 drivers/sensor/vl53l1x/CMakeLists.txt create mode 100644 drivers/sensor/vl53l1x/Kconfig create mode 100644 drivers/sensor/vl53l1x/vl53l1.c create mode 100644 drivers/sensor/vl53l1x/vl53l1_platform.c create mode 100644 drivers/sensor/vl53l1x/vl53l1_platform.h create mode 100644 drivers/sensor/vl53l1x/vl53l1_platform_log.h create mode 100644 drivers/sensor/vl53l1x/vl53l1_platform_user_config.h create mode 100644 drivers/sensor/vl53l1x/vl53l1_platform_user_data.h create mode 100644 drivers/sensor/vl53l1x/vl53l1_platform_user_defines.h create mode 100644 drivers/sensor/vl53l1x/vl53l1_types.h create mode 100644 dts/bindings/sensor/st,vl53l1x.yaml diff --git a/drivers/sensor/CMakeLists.txt b/drivers/sensor/CMakeLists.txt index 087d33ce22455..5d000ac84dfbd 100644 --- a/drivers/sensor/CMakeLists.txt +++ b/drivers/sensor/CMakeLists.txt @@ -109,6 +109,7 @@ add_subdirectory_ifdef(CONFIG_TMP112 tmp112) add_subdirectory_ifdef(CONFIG_TMP116 tmp116) add_subdirectory_ifdef(CONFIG_VCNL4040 vcnl4040) add_subdirectory_ifdef(CONFIG_VL53L0X vl53l0x) +add_subdirectory_ifdef(CONFIG_VL53L1X vl53l1x) add_subdirectory_ifdef(CONFIG_TEMP_KINETIS nxp_kinetis_temp) add_subdirectory_ifdef(CONFIG_TACH_XEC mchp_tach_xec) add_subdirectory_ifdef(CONFIG_WSEN_HIDS wsen_hids) diff --git a/drivers/sensor/Kconfig b/drivers/sensor/Kconfig index 47c1ee1ee135d..11ae4f026563b 100644 --- a/drivers/sensor/Kconfig +++ b/drivers/sensor/Kconfig @@ -259,6 +259,8 @@ source "drivers/sensor/vcnl4040/Kconfig" source "drivers/sensor/vl53l0x/Kconfig" +source "drivers/sensor/vl53l1x/Kconfig" + source "drivers/sensor/nxp_kinetis_temp/Kconfig" source "drivers/sensor/wsen_hids/Kconfig" diff --git a/drivers/sensor/vl53l1x/CMakeLists.txt b/drivers/sensor/vl53l1x/CMakeLists.txt new file mode 100644 index 0000000000000..9df21487227b5 --- /dev/null +++ b/drivers/sensor/vl53l1x/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources( + vl53l1.c + vl53l1_platform.c +) diff --git a/drivers/sensor/vl53l1x/Kconfig b/drivers/sensor/vl53l1x/Kconfig new file mode 100644 index 0000000000000..0865ff795496c --- /dev/null +++ b/drivers/sensor/vl53l1x/Kconfig @@ -0,0 +1,32 @@ +# VL53L0X time of flight sensor configuration options + +# Copyright (c) 2023 Prosaris Solutions Inc. +# SPDX-License-Identifier: Apache-2.0 + +menuconfig VL53L1X + bool "VL53L1X time of flight sensor" + default y + depends on DT_HAS_ST_VL53L1X_ENABLED + select I2C + select HAS_STLIB + help + Enable driver for VL53L1X I2C-based time of flight sensor. + +if VL53L1X + +config VL53L1X_INTERRUPT_MODE + bool "Use interrupt mode for VL53L1X time of flight sensor" + default y + depends on GPIO + help + Enable interrupt mode for VL53L1X time of flight sensor. Otherwise, + the driver will use the polling method. + +config VL53L1X_XSHUT + bool "Use xshut pin on VL53L1X time of flight sensor" + depends on GPIO + help + Enable to use the xshut pin on the VL53L1X. If not, the pin should be + connected to VDD. + +endif # VL53L1X diff --git a/drivers/sensor/vl53l1x/vl53l1.c b/drivers/sensor/vl53l1x/vl53l1.c new file mode 100644 index 0000000000000..34ae02e6869b5 --- /dev/null +++ b/drivers/sensor/vl53l1x/vl53l1.c @@ -0,0 +1,479 @@ +/* vl53l1.c - Driver for ST VL53L1X time of flight sensor */ + +/* + * Copyright (c) 2023 Prosaris SOlutions Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT st_vl53l1x + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "vl53l1_api.h" +#include "vl53l1_platform.h" + +LOG_MODULE_REGISTER(VL53L1X, CONFIG_SENSOR_LOG_LEVEL); + +struct vl53l1x_config { + struct i2c_dt_spec i2c; +#ifdef CONFIG_VL53L1X_XSHUT + struct gpio_dt_spec xshut; +#endif +#ifdef CONFIG_VL53L1X_INTERRUPT_MODE + struct gpio_dt_spec gpio1; +#endif +}; + +struct vl53l1x_data { + VL53L1_Dev_t vl53l1x; + VL53L1_RangingMeasurementData_t data; + VL53L1_DistanceModes distance_mode; +#ifdef CONFIG_VL53L1X_INTERRUPT_MODE + struct gpio_callback gpio_cb; + struct k_work work; + const struct device *dev; +#endif +}; + +static VL53L1_Error vl53l1x_read_sensor(struct vl53l1x_data *drv_data) +{ + VL53L1_Error ret; + + ret = VL53L1_GetRangingMeasurementData(&drv_data->vl53l1x, &drv_data->data); + if (ret != VL53L1_ERROR_NONE) { + LOG_ERR("VL53L1_GetRangingMeasurementData return error (%d)", ret); + return ret; + } + + ret = VL53L1_ClearInterruptAndStartMeasurement(&drv_data->vl53l1x); + if (ret != VL53L1_ERROR_NONE) { + LOG_ERR("VL53L1_ClearInterruptAndStartMeasurement return error (%d)", ret); + return ret; + } + + return VL53L1_ERROR_NONE; +} + +static void vl53l1x_worker(struct k_work *work) +{ + if (IS_ENABLED(CONFIG_VL53L1X_INTERRUPT_MODE)) { + struct vl53l1x_data *drv_data = CONTAINER_OF(work, struct vl53l1x_data, work); + + vl53l1x_read_sensor(drv_data); + } +} + +static void vl53l1x_gpio_callback(const struct device *dev, + struct gpio_callback *cb, uint32_t pins) +{ + if (IS_ENABLED(CONFIG_VL53L1X_INTERRUPT_MODE)) { + struct vl53l1x_data *drv_data = CONTAINER_OF(cb, struct vl53l1x_data, gpio_cb); + + k_work_submit(&drv_data->work); + } +} + +static int vl53l1x_init_interrupt(const struct device *dev) +{ + if (IS_ENABLED(CONFIG_VL53L1X_INTERRUPT_MODE)) { + struct vl53l1x_data *drv_data = dev->data; + const struct vl53l1x_config *config = dev->config; + int ret; + + drv_data->dev = dev; + + if (!device_is_ready(config->gpio1.port)) { + LOG_ERR("%s: device %s is not ready", dev->name, config->gpio1.port->name); + return -ENODEV; + } + + ret = gpio_pin_configure_dt(&config->gpio1, GPIO_INPUT | GPIO_PULL_UP); + if (ret < 0) { + LOG_ERR("[%s] Unable to configure GPIO interrupt", dev->name); + return -EIO; + } + + gpio_init_callback(&drv_data->gpio_cb, + vl53l1x_gpio_callback, + BIT(config->gpio1.pin)); + + ret = gpio_add_callback(config->gpio1.port, &drv_data->gpio_cb); + if (ret < 0) { + LOG_ERR("Failed to set gpio callback!"); + return -EIO; + } + + drv_data->work.handler = vl53l1x_worker; + } + return 0; +} + +static int vl53l1x_initialize(const struct device *dev) +{ + struct vl53l1x_data *drv_data = dev->data; + VL53L1_Error ret; + VL53L1_DeviceInfo_t vl53l1x_dev_info; + + LOG_DBG("[%s] Initializing ", dev->name); + + /* Pull XSHUT high to start the sensor */ +#ifdef CONFIG_VL53L1X_XSHUT + const struct vl53l1x_config *const config = dev->config; + + if (config->xshut.port) { + int gpio_ret = gpio_pin_set_dt(&config->xshut, 1); + + if (gpio_ret < 0) { + LOG_ERR("[%s] Unable to set XSHUT gpio (error %d)", dev->name, gpio_ret); + return -EIO; + } + /* Boot duration is 1.2 ms max */ + k_sleep(K_MSEC(2)); + } +#endif + + /* ONE TIME device initialization. + * To be called ONLY ONCE after device is brought out of reset + */ + ret = VL53L1_DataInit(&drv_data->vl53l1x); + if (ret != VL53L1_ERROR_NONE) { + LOG_ERR("[%s] VL53L1X_DataInit return error (%d)", dev->name, ret); + return -ENOTSUP; + } + + /* Do basic device init */ + ret = VL53L1_StaticInit(&drv_data->vl53l1x); + if (ret != VL53L1_ERROR_NONE) { + LOG_ERR("[%s] VL53L1_StaticInit return error (%d)", dev->name, ret); + return -ENOTSUP; + } + + /* Get info from sensor */ + (void)memset(&vl53l1x_dev_info, 0, sizeof(VL53L1_DeviceInfo_t)); + + ret = VL53L1_GetDeviceInfo(&drv_data->vl53l1x, &vl53l1x_dev_info); + if (ret != VL53L1_ERROR_NONE) { + LOG_ERR("[%s] VL53L1_GetDeviceInfo return error (%d)", dev->name, ret); + return -ENODEV; + } + + LOG_DBG("[%s] VL53L1X_GetDeviceInfo returned %d", dev->name, ret); + LOG_DBG(" Device Name : %s", vl53l1x_dev_info.Name); + LOG_DBG(" Device Type : %s", vl53l1x_dev_info.Type); + LOG_DBG(" Device ID : %s", vl53l1x_dev_info.ProductId); + LOG_DBG(" ProductRevisionMajor : %d", vl53l1x_dev_info.ProductRevisionMajor); + LOG_DBG(" ProductRevisionMinor : %d", vl53l1x_dev_info.ProductRevisionMinor); + + /* Set default distance mode */ + drv_data->distance_mode = VL53L1_DISTANCEMODE_LONG; + ret = VL53L1_SetDistanceMode(&drv_data->vl53l1x, drv_data->distance_mode); + if (ret != VL53L1_ERROR_NONE) { + LOG_ERR("[%s] VL53L1_SetDistanceMode return error (%d)", dev->name, ret); + return -EINVAL; + } + + return 0; +} + +/* Mapping is 1:1 with the API. + * From VL531X datasheet: + * | Max distance | Max distance in + * Mode | in dark (cm) | strong ambient light (cm) + * ---------------------------------------------------- + * short | 136 | 135 + * medium | 290 | 76 + * long | 360 | 73 + */ +static int vl53l1x_set_mode(const struct device *dev, + const struct sensor_value *val) +{ + struct vl53l1x_data *drv_data = dev->data; + VL53L1_Error ret; + + switch (val->val1) { + /* short */ + case 1: + /* medium */ + case 2: + /* long */ + case 3: + drv_data->distance_mode = val->val1; + break; + default: + drv_data->distance_mode = VL53L1_DISTANCEMODE_LONG; + break; + } + + ret = VL53L1_SetDistanceMode(&drv_data->vl53l1x, drv_data->distance_mode); + if (ret != VL53L1_ERROR_NONE) { + LOG_ERR("[%s] VL53L1_SetDistanceMode return error (%d)", dev->name, ret); + return -EINVAL; + } + + return 0; +} + +/* + * The ROI is a 16x16 grid. + * The bottom left is (0,0), top right is (15, 15), for + * a total of 256 squares (numbered 0 through 255). + * The default ROI is val1 = 240, val2 = 15 (the full grid). + * See UM2356 User Manual (VL531X API doc). + */ +static int vl53l1x_set_roi(const struct device *dev, + const struct sensor_value *val) +{ + struct vl53l1x_data *drv_data = dev->data; + VL53L1_Error ret; + + if ((val->val1 < 0) || + (val->val2 < 0) || + (val->val1 > 255) || + (val->val2 > 255) || + (val->val2 >= val->val1)) { + return -EINVAL; + } + + /* Map val to pUserROi */ + VL53L1_UserRoi_t pUserROi = { + .TopLeftX = val->val1 % 16, + .TopLeftY = (uint8_t)(val->val1 / 16), + .BotRightX = val->val2 % 16, + .BotRightY = (uint8_t)(val->val2 / 16), + }; + + ret = VL53L1_SetUserROI(&drv_data->vl53l1x, &pUserROi); + if (ret != VL53L1_ERROR_NONE) { + LOG_ERR("[%s] VL53L1_SetUserROI return error (%d)", dev->name, ret); + return -EINVAL; + } + + return 0; +} + +static int vl53l1x_get_mode(const struct device *dev, + struct sensor_value *val) +{ + struct vl53l1x_data *drv_data = dev->data; + VL53L1_DistanceModes mode; + VL53L1_Error ret; + + ret = VL53L1_GetDistanceMode(&drv_data->vl53l1x, &mode); + if (ret != VL53L1_ERROR_NONE) { + LOG_ERR("[%s] VL53L1_GetDistanceMode return error (%d)", dev->name, ret); + return -ENODATA; + } + + /* Mapping is 1:1 with the API */ + val->val1 = (int32_t)mode; + val->val2 = 0; + return 0; +} + +static int vl53l1x_get_roi(const struct device *dev, + struct sensor_value *val) +{ + struct vl53l1x_data *drv_data = dev->data; + VL53L1_Error ret; + VL53L1_UserRoi_t pUserROi; + + ret = VL53L1_GetUserROI(&drv_data->vl53l1x, &pUserROi); + if (ret != VL53L1_ERROR_NONE) { + LOG_ERR("[%s] VL53L1_GetUserROI return error (%d)", dev->name, ret); + return -ENODATA; + } + + /* Map pUserROi to val */ + val->val1 = (int32_t)((16 * pUserROi.TopLeftY) + pUserROi.TopLeftX); + val->val2 = (int32_t)((16 * pUserROi.BotRightY) + pUserROi.BotRightX); + return 0; +} + +static int vl53l1x_sample_fetch(const struct device *dev, + enum sensor_channel chan) +{ + struct vl53l1x_data *drv_data = dev->data; + const struct vl53l1x_config *config = dev->config; + VL53L1_Error ret; + + __ASSERT_NO_MSG(chan == SENSOR_CHAN_DISTANCE); + + /* Will immediately stop current measurement */ + ret = VL53L1_StopMeasurement(&drv_data->vl53l1x); + if (ret != VL53L1_ERROR_NONE) { + LOG_ERR("VL53L1_StopMeasurement return error (%d)", ret); + return -EBUSY; + } + + if (IS_ENABLED(CONFIG_VL53L1X_INTERRUPT_MODE)) { + ret = gpio_pin_interrupt_configure_dt(&config->gpio1, GPIO_INT_EDGE_TO_INACTIVE); + if (ret < 0) { + LOG_ERR("[%s] Unable to config interrupt", dev->name); + return -EIO; + } + } + + ret = VL53L1_StartMeasurement(&drv_data->vl53l1x); + if (ret != VL53L1_ERROR_NONE) { + LOG_ERR("[%s] VL53L1_StartMeasurement return error (%d)", dev->name, ret); + return -EBUSY; + } + + return 0; +} + +static int vl53l1x_channel_get(const struct device *dev, + enum sensor_channel chan, + struct sensor_value *val) +{ + struct vl53l1x_data *drv_data = dev->data; + VL53L1_Error ret; + + __ASSERT_NO_MSG(chan == SENSOR_CHAN_DISTANCE); + + /* Calling VL53L1_WaitMeasurementDataReady regardless of using interrupt or + * polling method ensures user does not have to consider the time between + * calling fetch and get. + */ + ret = VL53L1_WaitMeasurementDataReady(&drv_data->vl53l1x); + if (ret != VL53L1_ERROR_NONE) { + LOG_ERR("[%s] VL53L1_WaitMeasurementDataReady return error (%d)", dev->name, ret); + return -EBUSY; + } + + if (IS_ENABLED(CONFIG_VL53L1X_INTERRUPT_MODE) == 0) { + /* Using driver poling mode */ + ret = vl53l1x_read_sensor(drv_data); + if (ret != VL53L1_ERROR_NONE) { + return -ENODATA; + } + } + + val->val1 = (int32_t)(drv_data->data.RangeMilliMeter); + /* RangeFractionalPart not implemented in API */ + val->val2 = 0; + + return 0; +} + +static int vl53l1x_attr_get(const struct device *dev, + enum sensor_channel chan, + enum sensor_attribute attr, + struct sensor_value *val) +{ + __ASSERT_NO_MSG(chan == SENSOR_CHAN_DISTANCE); + + if (attr == SENSOR_ATTR_CONFIGURATION) { + vl53l1x_get_mode(dev, val); + } else if (attr == SENSOR_ATTR_CALIB_TARGET) { + vl53l1x_get_roi(dev, val); + } else { + return -ENOTSUP; + } + + return 0; +} + +static int vl53l1x_attr_set(const struct device *dev, + enum sensor_channel chan, + enum sensor_attribute attr, + const struct sensor_value *val) +{ + __ASSERT_NO_MSG(chan == SENSOR_CHAN_DISTANCE); + + if (attr == SENSOR_ATTR_CONFIGURATION) { + vl53l1x_set_mode(dev, val); + } else if (attr == SENSOR_ATTR_CALIB_TARGET) { + vl53l1x_set_roi(dev, val); + } else { + return -ENOTSUP; + } + + return 0; +} + +static const struct sensor_driver_api vl53l1x_api_funcs = { + .sample_fetch = vl53l1x_sample_fetch, + .channel_get = vl53l1x_channel_get, + .attr_get = vl53l1x_attr_get, + .attr_set = vl53l1x_attr_set, +}; + +static int vl53l1x_init(const struct device *dev) +{ + int ret = 0; + struct vl53l1x_data *drv_data = dev->data; + const struct vl53l1x_config *config = dev->config; + + /* Initialize the HAL i2c peripheral */ + drv_data->vl53l1x.i2c = &config->i2c; + + if (!device_is_ready(config->i2c.bus)) { + LOG_ERR("I2C bus is not ready"); + return -ENODEV; + } + + /* Configure gpio connected to VL53L1X's XSHUT pin to + * allow deepest sleep mode + */ +#ifdef CONFIG_VL53L1X_XSHUT + if (config->xshut.port) { + ret = gpio_pin_configure_dt(&config->xshut, GPIO_OUTPUT); + if (ret < 0) { + LOG_ERR("[%s] Unable to configure GPIO as output", dev->name); + return -EIO; + } + } +#endif + +#ifdef CONFIG_VL53L1X_INTERRUPT_MODE + if (config->gpio1.port) { + ret = vl53l1x_init_interrupt(dev); + if (ret < 0) { + LOG_ERR("Failed to initialize interrupt!"); + return -EIO; + } + } +#endif + + ret = vl53l1x_initialize(dev); + if (ret) { + return ret; + } + + LOG_DBG("[%s] Initialized", dev->name); + return 0; +} + +#define VL53L1X_INIT(i) \ + static const struct vl53l1x_config vl53l1x_config_##i = { \ + .i2c = I2C_DT_SPEC_INST_GET(i), \ + IF_ENABLED(CONFIG_VL53L1X_XSHUT, ( \ + .xshut = GPIO_DT_SPEC_INST_GET_OR(i, xshut_gpios, { 0 }),)) \ + IF_ENABLED(CONFIG_VL53L1X_INTERRUPT_MODE, ( \ + .gpio1 = GPIO_DT_SPEC_INST_GET_OR(i, int_gpios, { 0 }),)) \ + }; \ + \ + static struct vl53l1x_data vl53l1x_data_##i; \ + \ + SENSOR_DEVICE_DT_INST_DEFINE(i, \ + vl53l1x_init, \ + NULL, \ + &vl53l1x_data_##i, \ + &vl53l1x_config_##i, \ + POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, \ + &vl53l1x_api_funcs); + +DT_INST_FOREACH_STATUS_OKAY(VL53L1X_INIT) diff --git a/drivers/sensor/vl53l1x/vl53l1_platform.c b/drivers/sensor/vl53l1x/vl53l1_platform.c new file mode 100644 index 0000000000000..a3e02b5466ade --- /dev/null +++ b/drivers/sensor/vl53l1x/vl53l1_platform.c @@ -0,0 +1,182 @@ +/* vl53l1_platform.c - Zephyr customization of ST vl53l1x library. + */ + +/* + * Copyright (c) 2023 Prosaris Solutions Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "vl53l1_platform.h" +#include "vl53l1_platform_log.h" + +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_DECLARE(VL53L1X, CONFIG_SENSOR_LOG_LEVEL); + +VL53L1_Error VL53L1_WriteMulti(VL53L1_Dev_t *pdev, uint16_t reg, + uint8_t *pdata, uint32_t count) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + int32_t status_int = 0; + uint8_t buffer[count + 2]; + + /* To be able to write to the 16-bit registers/addresses on the vl53l1x */ + buffer[1] = (uint8_t)(reg & 0x00ff); + buffer[0] = (uint8_t)((reg & 0xff00) >> 8); + + memcpy(&buffer[2], pdata, count); + + status_int = i2c_write_dt(pdev->i2c, buffer, count + 2); + + if (status_int < 0) { + status = VL53L1_ERROR_CONTROL_INTERFACE; + LOG_ERR("Failed to write"); + } + + return status; +} + +VL53L1_Error VL53L1_ReadMulti(VL53L1_Dev_t *pdev, uint16_t reg, + uint8_t *pdata, uint32_t count) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + int32_t status_int = 0; + + reg = sys_cpu_to_be16(reg); + + status_int = i2c_write_read_dt(pdev->i2c, (uint8_t *)(®), 2, pdata, count); + + if (status_int < 0) { + status = VL53L1_ERROR_CONTROL_INTERFACE; + LOG_ERR("Failed to read"); + return -EIO; + } + + return status; +} + +VL53L1_Error VL53L1_WrByte(VL53L1_Dev_t *pdev, uint16_t reg, uint8_t data) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + + status = VL53L1_WriteMulti(pdev, reg, &data, 1); + + return status; +} + +VL53L1_Error VL53L1_WrWord(VL53L1_Dev_t *pdev, uint16_t reg, uint16_t data) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + + data = sys_cpu_to_be16(data); + + status = VL53L1_WriteMulti(pdev, reg, (uint8_t *)(&data), VL53L1_BYTES_PER_WORD); + + return status; +} + +VL53L1_Error VL53L1_WrDWord(VL53L1_Dev_t *pdev, uint16_t reg, uint32_t data) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + + data = sys_cpu_to_be32(data); + + status = VL53L1_WriteMulti(pdev, reg, (uint8_t *)(&data), VL53L1_BYTES_PER_DWORD); + + return status; +} + +VL53L1_Error VL53L1_RdByte(VL53L1_Dev_t *pdev, uint16_t reg, uint8_t *pdata) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + + status = VL53L1_ReadMulti(pdev, reg, pdata, 1); + + return status; +} + +VL53L1_Error VL53L1_RdWord(VL53L1_Dev_t *pdev, uint16_t reg, uint16_t *pdata) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + + status = VL53L1_ReadMulti(pdev, reg, (uint8_t *)pdata, 2); + *pdata = sys_be16_to_cpu(*pdata); + + return status; +} + +VL53L1_Error VL53L1_RdDWord(VL53L1_Dev_t *pdev, uint16_t reg, uint32_t *pdata) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + + status = VL53L1_ReadMulti(pdev, reg, (uint8_t *)pdata, 4); + *pdata = sys_be32_to_cpu(*pdata); + + return status; +} + +VL53L1_Error VL53L1_WaitUs(VL53L1_Dev_t *pdev, int32_t wait_us) +{ + k_sleep(K_USEC(wait_us)); + return VL53L1_ERROR_NONE; +} + +VL53L1_Error VL53L1_WaitMs(VL53L1_Dev_t *pdev, int32_t wait_ms) +{ + return VL53L1_WaitUs(pdev, wait_ms * 1000); +} + +VL53L1_Error VL53L1_GetTickCount(uint32_t *ptick_count_ms) +{ + *ptick_count_ms = k_uptime_get_32(); + return VL53L1_ERROR_NONE; +} + +VL53L1_Error VL53L1_WaitValueMaskEx(VL53L1_Dev_t *dev, uint32_t timeout, uint16_t i, uint8_t val, + uint8_t mask, uint32_t delay) +{ + VL53L1_Error status = VL53L1_ERROR_NONE; + uint32_t start_time_ms = 0; + uint32_t current_time_ms = 0; + uint8_t byte_val = 0; + uint8_t found = 0; + + /* calculate time limit in absolute time */ + VL53L1_GetTickCount(&start_time_ms); + dev->new_data_ready_poll_duration_ms = 0; + + /* wait until val is found, timeout reached on error occurred */ + while ((status == VL53L1_ERROR_NONE) && + (dev->new_data_ready_poll_duration_ms < timeout) && + (found == 0)) { + status = VL53L1_RdByte(dev, i, &byte_val); + + if ((byte_val & mask) == val) { + found = 1; + } + + if ((status == VL53L1_ERROR_NONE) && (found == 0) && (delay > 0)) { + /* Allow for other threads to run */ + status = VL53L1_WaitMs(dev, delay); + } + + /* Update polling time (Compare difference rather than absolute to + * negate 32bit wrap around issue) + */ + VL53L1_GetTickCount(¤t_time_ms); + dev->new_data_ready_poll_duration_ms = current_time_ms - start_time_ms; + } + + if (found == 0 && status == VL53L1_ERROR_NONE) { + status = VL53L1_ERROR_TIME_OUT; + } + + return status; +} diff --git a/drivers/sensor/vl53l1x/vl53l1_platform.h b/drivers/sensor/vl53l1x/vl53l1_platform.h new file mode 100644 index 0000000000000..8b1b2a0f37f46 --- /dev/null +++ b/drivers/sensor/vl53l1x/vl53l1_platform.h @@ -0,0 +1,149 @@ +/* vl53l1_platform.h - Zephyr customization of ST vl53l1x library. */ + +/* + * Copyright (c) 2017 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_VL53L1X_VL53L1_PLATFORM_H_ +#define ZEPHYR_DRIVERS_SENSOR_VL53L1X_VL53L1_PLATFORM_H_ + +#include +#include "vl53l1_ll_def.h" +#include "vl53l1_platform_log.h" +#include "vl53l1_platform_user_data.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Writes the supplied byte buffer to the device + * @param pdev Pointer to device structure (device handle) + * @param index Register index value + * @param pdata Pointer to uint8_t (byte) buffer containing the data to be written + * @param count Number of bytes in the supplied byte buffer + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_WriteMulti(VL53L1_Dev_t *pdev, uint16_t index, + uint8_t *pdata, uint32_t count); + +/** + * Reads the requested number of bytes from the device + * @param pdev Pointer to device structure (device handle) + * @param index Register index value + * @param pdata Pointer to the uint8_t (byte) buffer to store read data + * @param count Number of bytes to read + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_ReadMulti(VL53L1_Dev_t *pdev, uint16_t index, + uint8_t *pdata, uint32_t count); + +/** + * Writes a single byte to the device + * @param pdev Pointer to device structure (device handle) + * @param index Register index value + * @param data Data value to write + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_WrByte(VL53L1_Dev_t *pdev, uint16_t index, uint8_t data); + +/** + * Writes a single word (16-bit unsigned) to the device + * @param pdev Pointer to device structure (device handle) + * @param index Register index value + * @param data Data value write + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_WrWord(VL53L1_Dev_t *pdev, uint16_t index, uint16_t data); + +/** + * Writes a single dword (32-bit unsigned) to the device + * @param pdev Pointer to device structure (device handle) + * @param index Register index value + * @param data Data value to write + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_WrDWord(VL53L1_Dev_t *pdev, uint16_t index, uint32_t data); + +/** + * Reads a single byte from the device + * @param pdev Pointer to device structure (device handle) + * @param index Register index + * @param pdata Pointer to uint8_t data value + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_RdByte(VL53L1_Dev_t *pdev, uint16_t index, uint8_t *pdata); + +/** + * Reads a single word (16-bit unsigned) from the device + * @param pdev Pointer to device structure (device handle) + * @param index Register index value + * @param pdata Pointer to uint16_t data value + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_RdWord(VL53L1_Dev_t *pdev, uint16_t index, uint16_t *pdata); + +/** + * Reads a single double word (32-bit unsigned) from the device + * @param pdev Pointer to device structure (device handle) + * @param index Register index value + * @param pdata Pointer to uint32_t data value + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_RdDWord(VL53L1_Dev_t *pdev, uint16_t index, uint32_t *pdata); + +/** + * Implements a programmable wait in us + * @param pdev Pointer to device structure (device handle) + * @param wait_us Integer wait in micro seconds + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_WaitUs(VL53L1_Dev_t *pdev, int32_t wait_us); + +/** + * Implements a programmable wait in ms + * @param pdev Pointer to device structure (device handle) + * @param wait_ms Integer wait in milliseconds + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_WaitMs(VL53L1_Dev_t *pdev, int32_t wait_ms); + +/** + * Gets current system tick count in [ms] + * @param Pointer to current time in [ms] + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_GetTickCount(uint32_t *ptime_ms); + +/** + * Register "wait for value" polling routine + * @param dev Pointer to device structure (device handle) + * @param timeout Timeout in [ms] + * @param i Register index value + * @param val Value to wait for + * @param mask Mask to be applied before comparison with value + * @param delay Polling delay between each read transaction in [ms] + * @return VL53L1_ERROR_NONE Success + * @return "Other error code" See ::VL53L1_Error + */ +VL53L1_Error VL53L1_WaitValueMaskEx(VL53L1_Dev_t *dev, uint32_t timeout, uint16_t i, uint8_t val, + uint8_t mask, uint32_t delay); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/drivers/sensor/vl53l1x/vl53l1_platform_log.h b/drivers/sensor/vl53l1x/vl53l1_platform_log.h new file mode 100644 index 0000000000000..57019e42ba02c --- /dev/null +++ b/drivers/sensor/vl53l1x/vl53l1_platform_log.h @@ -0,0 +1,200 @@ +/* vl53l1x_platform_log.h - Zephyr customization of ST vl53l1x library. */ + +/* + * Copyright (c) 2017 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +#ifndef _VL53L1_PLATFORM_LOG_H_ +#define _VL53L1_PLATFORM_LOG_H_ + + +#ifdef VL53L1_LOG_ENABLE + #include "vl53l1_platform_user_config.h" + + #ifdef _MSC_VER + # define EWOKPLUS_EXPORTS __declspec(dllexport) + #else + # define EWOKPLUS_EXPORTS + #endif + + #include "vl53l1_types.h" + + #ifdef __cplusplus + extern "C" { + #endif + + #include + + /** + * @brief Set the level, output and specific functions for module logging. + * + * + * @param filename - full path of output log file, NULL for print to stdout + * + * @param modules - Module or None or All to trace + * VL53L1_TRACE_MODULE_NONE + * VL53L1_TRACE_MODULE_API + * VL53L1_TRACE_MODULE_CORE + * VL53L1_TRACE_MODULE_TUNING + * VL53L1_TRACE_MODULE_CHARACTERISATION + * VL53L1_TRACE_MODULE_PLATFORM + * VL53L1_TRACE_MODULE_ALL + * + * @param level - trace level + * VL53L1_TRACE_LEVEL_NONE + * VL53L1_TRACE_LEVEL_ERRORS + * VL53L1_TRACE_LEVEL_WARNING + * VL53L1_TRACE_LEVEL_INFO + * VL53L1_TRACE_LEVEL_DEBUG + * VL53L1_TRACE_LEVEL_ALL + * VL53L1_TRACE_LEVEL_IGNORE + * + * @param functions - function level to trace; + * VL53L1_TRACE_FUNCTION_NONE + * VL53L1_TRACE_FUNCTION_I2C + * VL53L1_TRACE_FUNCTION_ALL + * + * @return status - always VL53L1_ERROR_NONE + * + */ + + #define VL53L1_TRACE_LEVEL_NONE 0x00000000 + #define VL53L1_TRACE_LEVEL_ERRORS 0x00000001 + #define VL53L1_TRACE_LEVEL_WARNING 0x00000002 + #define VL53L1_TRACE_LEVEL_INFO 0x00000004 + #define VL53L1_TRACE_LEVEL_DEBUG 0x00000008 + #define VL53L1_TRACE_LEVEL_ALL 0x00000010 + #define VL53L1_TRACE_LEVEL_IGNORE 0x00000020 + + #define VL53L1_TRACE_FUNCTION_NONE 0x00000000 + #define VL53L1_TRACE_FUNCTION_I2C 0x00000001 + #define VL53L1_TRACE_FUNCTION_ALL 0x7fffffff + + #define VL53L1_TRACE_MODULE_NONE 0x00000000 + #define VL53L1_TRACE_MODULE_API 0x00000001 + #define VL53L1_TRACE_MODULE_CORE 0x00000002 + #define VL53L1_TRACE_MODULE_PROTECTED 0x00000004 + #define VL53L1_TRACE_MODULE_HISTOGRAM 0x00000008 + #define VL53L1_TRACE_MODULE_REGISTERS 0x00000010 + #define VL53L1_TRACE_MODULE_PLATFORM 0x00000020 + #define VL53L1_TRACE_MODULE_NVM 0x00000040 + #define VL53L1_TRACE_MODULE_CALIBRATION_DATA 0x00000080 + #define VL53L1_TRACE_MODULE_NVM_DATA 0x00000100 + #define VL53L1_TRACE_MODULE_HISTOGRAM_DATA 0x00000200 + #define VL53L1_TRACE_MODULE_RANGE_RESULTS_DATA 0x00000400 + #define VL53L1_TRACE_MODULE_XTALK_DATA 0x00000800 + #define VL53L1_TRACE_MODULE_OFFSET_DATA 0x00001000 + #define VL53L1_TRACE_MODULE_DATA_INIT 0x00002000 + #define VL53L1_TRACE_MODULE_REF_SPAD_CHAR 0x00004000 + #define VL53L1_TRACE_MODULE_SPAD_RATE_MAP 0x00008000 +#ifdef PAL_EXTENDED + #define VL53L1_TRACE_MODULE_SPAD 0x01000000 + #define VL53L1_TRACE_MODULE_FMT 0x02000000 + #define VL53L1_TRACE_MODULE_UTILS 0x04000000 + #define VL53L1_TRACE_MODULE_BENCH_FUNCS 0x08000000 +#endif + #define VL53L1_TRACE_MODULE_CUSTOMER_API 0x40000000 + #define VL53L1_TRACE_MODULE_ALL 0x7fffffff + + + extern uint32_t _trace_level; + + /* + * NOTE: dynamically exported if we enable logging. + * this way, Python interfaces can access this function, but we don't + * need to include it in the .def files. + */ + EWOKPLUS_EXPORTS int8_t VL53L1_trace_config( + char *filename, + uint32_t modules, + uint32_t level, + uint32_t functions); + + /** + * @brief Print trace module function. + * + * @param module - ?? + * @param level - ?? + * @param function - ?? + * @param format - ?? + * + */ + + EWOKPLUS_EXPORTS void VL53L1_trace_print_module_function( + uint32_t module, + uint32_t level, + uint32_t function, + const char *format, ...); + + /** + * @brief Get global _trace_functions parameter + * + * @return _trace_functions + */ + + uint32_t VL53L1_get_trace_functions(void); + + /** + * @brief Set global _trace_functions parameter + * + * @param[in] function : new function code + */ + + void VL53L1_set_trace_functions(uint32_t function); + + + /* + * @brief Returns the current system tick count in [ms] + * + * @return time_ms : current time in [ms] + * + */ + + uint32_t VL53L1_clock(void); + + #define LOG_GET_TIME() \ + ((int)VL53L1_clock()) + + #define _LOG_TRACE_PRINT(module, level, function, ...) \ + VL53L1_trace_print_module_function(module, level, function, ##__VA_ARGS__); + + #define _LOG_FUNCTION_START(module, fmt, ...) \ + VL53L1_trace_print_module_function(module, _trace_level, VL53L1_TRACE_FUNCTION_ALL,\ + "%6ld %s "fmt"\n", LOG_GET_TIME(), __func__, ##__VA_ARGS__); + + #define _LOG_FUNCTION_END(module, status, ...)\ + VL53L1_trace_print_module_function(module, _trace_level, VL53L1_TRACE_FUNCTION_ALL,\ + "%6ld %s %d\n", LOG_GET_TIME(), __func__, (int)status, ##__VA_ARGS__) + + #define _LOG_FUNCTION_END_FMT(module, status, fmt, ...)\ + VL53L1_trace_print_module_function(module, _trace_level, VL53L1_TRACE_FUNCTION_ALL,\ + "%6ld %s %d "fmt"\n", LOG_GET_TIME(), __func__, (int)status, ##__VA_ARGS__) + + #define _LOG_GET_TRACE_FUNCTIONS()\ + VL53L1_get_trace_functions() + + #define _LOG_SET_TRACE_FUNCTIONS(functions)\ + VL53L1_set_trace_functions(functions) + + #define _LOG_STRING_BUFFER(x) char x[VL53L1_MAX_STRING_LENGTH] + + #ifdef __cplusplus + } + #endif + +#else /* VL53L1_LOG_ENABLE - no logging */ + + #define _LOG_TRACE_PRINT(module, level, function, ...) + #define _LOG_FUNCTION_START(module, fmt, ...) + #define _LOG_FUNCTION_END(module, status, ...) + #define _LOG_FUNCTION_END_FMT(module, status, fmt, ...) + #define _LOG_GET_TRACE_FUNCTIONS() 0 + #define _LOG_SET_TRACE_FUNCTIONS(functions) + #define _LOG_STRING_BUFFER(x) + +#endif /* VL53L1_LOG_ENABLE */ + +#endif /* _VL53L1_PLATFORM_LOG_H_ */ diff --git a/drivers/sensor/vl53l1x/vl53l1_platform_user_config.h b/drivers/sensor/vl53l1x/vl53l1_platform_user_config.h new file mode 100644 index 0000000000000..02b655437b47c --- /dev/null +++ b/drivers/sensor/vl53l1x/vl53l1_platform_user_config.h @@ -0,0 +1,61 @@ +/* vl53l1x_platform_user_config.h - Zephyr customization of ST vl53l1x library. */ + +/* + * Copyright (c) 2017 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _VL53L1_PLATFORM_USER_CONFIG_H_ +#define _VL53L1_PLATFORM_USER_CONFIG_H_ + +#define VL53L1_BYTES_PER_WORD 2 +#define VL53L1_BYTES_PER_DWORD 4 + +/* Define polling delays */ +#define VL53L1_BOOT_COMPLETION_POLLING_TIMEOUT_MS 500 +#define VL53L1_RANGE_COMPLETION_POLLING_TIMEOUT_MS 2000 +#define VL53L1_TEST_COMPLETION_POLLING_TIMEOUT_MS 60000 + +#define VL53L1_POLLING_DELAY_MS 1 + +/* Define LLD TuningParms Page Base Address + * - Part of Patch_AddedTuningParms_11761 + */ +#define VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS 0x8000 +#define VL53L1_TUNINGPARM_PRIVATE_PAGE_BASE_ADDRESS 0xC000 + +#define VL53L1_GAIN_FACTOR__STANDARD_DEFAULT 0x0800 + /*!< Default standard ranging gain correction factor + * 1.11 format. 1.0 = 0x0800, 0.980 = 0x07D7 + */ + +#define VL53L1_OFFSET_CAL_MIN_EFFECTIVE_SPADS 0x0500 + /*!< Lower Limit for the MM1 effective SPAD count during offset + * calibration Format 8.8 0x0500 -> 5.0 effective SPADs + */ + +#define VL53L1_OFFSET_CAL_MAX_PRE_PEAK_RATE_MCPS 0x1900 + /*!< Max Limit for the pre range peak rate during offset + * calibration Format 9.7 0x1900 -> 50.0 Mcps. + * If larger then in pile up + */ + +#define VL53L1_OFFSET_CAL_MAX_SIGMA_MM 0x0040 + /*!< Max sigma estimate limit during offset calibration + * Check applies to pre-range, mm1 and mm2 ranges + * Format 14.2 0x0040 -> 16.0mm. + */ + +#define VL53L1_MAX_USER_ZONES 1 + /*!< Max number of user Zones - maximal limitation from + * FW stream divide - value of 254 + */ + +#define VL53L1_MAX_RANGE_RESULTS 2 + /*!< Allocates storage for return and reference restults */ + + +#define VL53L1_MAX_STRING_LENGTH 512 + +#endif /* _VL53L1_PLATFORM_USER_CONFIG_H_ */ diff --git a/drivers/sensor/vl53l1x/vl53l1_platform_user_data.h b/drivers/sensor/vl53l1x/vl53l1_platform_user_data.h new file mode 100644 index 0000000000000..211265ca26c53 --- /dev/null +++ b/drivers/sensor/vl53l1x/vl53l1_platform_user_data.h @@ -0,0 +1,83 @@ +/* vl53l1_platform_user_data.h - Zephyr customization of ST vl53l1x library. */ + +/* + * Copyright (c) 2017 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_VL53L1X_VL53L1_PLATFORM_USER_DATA_H_ +#define ZEPHYR_DRIVERS_SENSOR_VL53L1X_VL53L1_PLATFORM_USER_DATA_H_ + +#include "vl53l1_def.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @struct VL53L1_Dev_t + * @brief Generic PAL device type that does link between API and platform + * abstraction layer + * + */ +typedef struct { + /*!< Low Level Driver data structure */ + VL53L1_DevData_t Data; + /*!< New data ready poll duration in ms - for debug */ + uint32_t new_data_ready_poll_duration_ms; + /*!< I2C device handle */ + const struct i2c_dt_spec *i2c; +} VL53L1_Dev_t; + + +/** + * @brief Declare the device Handle as a pointer of the structure @a VL53L1_Dev_t. + * + */ +typedef VL53L1_Dev_t *VL53L1_DEV; + +/** + * @def VL53L1PALDevDataGet + * @brief Get ST private structure @a VL53L1_DevData_t data access + * + * @param Dev Device Handle + * @param field ST structure field name + * It maybe used and as real data "ref" not just as "get" for sub-structure item + * like PALDevDataGet(FilterData.field)[i] or + * PALDevDataGet(FilterData.MeasurementIndex)++ + */ +#define VL53L1DevDataGet(Dev, field) (Dev->Data.field) + + +/** + * @def VL53L1PALDevDataSet(Dev, field, data) + * @brief Set ST private structure @a VL53L1_DevData_t data field + * @param Dev Device Handle + * @param field ST structure field name + * @param data Data to be set + */ +#define VL53L1DevDataSet(Dev, field, data) ((Dev->Data.field) = (data)) + + +/** + * @def VL53L1DevStructGetLLDriverHandle + * @brief Get LL Driver handle @a VL53L0_Dev_t data access + * + * @param Dev Device Handle + */ +#define VL53L1DevStructGetLLDriverHandle(Dev) (&Dev->Data.LLData) + +/** + * @def VL53L1DevStructGetLLResultsHandle + * @brief Get LL Results handle @a VL53L0_Dev_t data access + * + * @param Dev Device Handle + */ +#define VL53L1DevStructGetLLResultsHandle(Dev) (&Dev->Data.llresults) + +#ifdef __cplusplus +} +#endif + +#endif /*ZEPHYR_DRIVERS_SENSOR_VL53L1X_VL53L1_PLATFORM_USER_DATA_H_*/ diff --git a/drivers/sensor/vl53l1x/vl53l1_platform_user_defines.h b/drivers/sensor/vl53l1x/vl53l1_platform_user_defines.h new file mode 100644 index 0000000000000..c5caaac14a1b3 --- /dev/null +++ b/drivers/sensor/vl53l1x/vl53l1_platform_user_defines.h @@ -0,0 +1,73 @@ +/* vl53l1x_platform_user_defines.h - Zephyr customization of ST vl53l1x library. */ + +/* + * Copyright (c) 2017 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _VL53L1_PLATFORM_USER_DEFINES_H_ +#define _VL53L1_PLATFORM_USER_DEFINES_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * @file vl53l1_platform_user_defines.h + * + * @brief All end user OS/platform/application definitions + */ + + +/** + * @def do_division_u + * @brief customer supplied division operation - 64-bit unsigned + * + * @param dividend unsigned 64-bit numerator + * @param divisor unsigned 64-bit denominator + */ +#define do_division_u(dividend, divisor) (dividend / divisor) + + +/** + * @def do_division_s + * @brief customer supplied division operation - 64-bit signed + * + * @param dividend signed 64-bit numerator + * @param divisor signed 64-bit denominator + */ +#define do_division_s(dividend, divisor) (dividend / divisor) + + +/** + * @def WARN_OVERRIDE_STATUS + * @brief customer supplied macro to optionally output info when a specific + error has been overridden with success within the EwokPlus driver + * + * @param __X__ the macro which enabled the suppression + */ +#define WARN_OVERRIDE_STATUS(__X__)\ + trace_print(VL53L1_TRACE_LEVEL_WARNING, #__X__); + + +#ifdef _MSC_VER +#define DISABLE_WARNINGS() { \ + __pragma(warning(push)); \ + __pragma(warning(disable:4127)); \ + } +#define ENABLE_WARNINGS() { \ + __pragma(warning(pop)); \ + } +#else + #define DISABLE_WARNINGS() + #define ENABLE_WARNINGS() +#endif + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/drivers/sensor/vl53l1x/vl53l1_types.h b/drivers/sensor/vl53l1x/vl53l1_types.h new file mode 100644 index 0000000000000..bd8cd18606290 --- /dev/null +++ b/drivers/sensor/vl53l1x/vl53l1_types.h @@ -0,0 +1,30 @@ +/* vl53l1_types.h - Zephyr customization of ST vl53l1x library, basic type definition. */ + +/* + * Copyright (c) 2017 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_VL53L1X_VL53L1_TYPES_H_ +#define ZEPHYR_DRIVERS_SENSOR_VL53L1X_VL53L1_TYPES_H_ + + +/* Zephyr provides stdint.h and stddef.h, so this is enough to include it. + * If it was not the case, we would defined here all signed and unsigned + * basic types... + */ +#include +#include + +#ifndef NULL +#error "Error NULL definition should be done. Please add required include " +#endif + +/** use where fractional values are expected + * + * Given a floating point value f it's .16 bit point is (int)(f*(1<<16)) + */ +typedef uint32_t FixPoint1616_t; + +#endif /* ZEPHYR_DRIVERS_SENSOR_VL53L1X_VL53L1_TYPES_H_ */ diff --git a/dts/bindings/sensor/st,vl53l1x.yaml b/dts/bindings/sensor/st,vl53l1x.yaml new file mode 100644 index 0000000000000..d5df6706a84c6 --- /dev/null +++ b/dts/bindings/sensor/st,vl53l1x.yaml @@ -0,0 +1,25 @@ +# Copyright (c) 2023 Prosaris Solutions Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: STMicroelectronics VL53L1X Time of Flight sensor + +compatible: "st,vl53l1x" + +include: [sensor-device.yaml, i2c-device.yaml] + +properties: + xshut-gpios: + type: phandle-array + description: | + Driving the XSHUT pin low puts the VL53L1X into hardware + standby (if VDD is present) or complete power off (if + VDD is not present). Additionally, if XSHUT is connected + directly to VDD, the sensor will go into boot mode on a + transition from LOW to HIGH. + + int-gpios: + type: phandle-array + description: | + An interrupt is raised when a distance measurement is ready. + GPIO1 is the interrupt pin on the VL53L1X (active low). This + can be disabled if the user prefers to use polling instead. diff --git a/tests/drivers/build_all/sensor/i2c.dtsi b/tests/drivers/build_all/sensor/i2c.dtsi index 0bddfb4938f9f..5944d1b0faacf 100644 --- a/tests/drivers/build_all/sensor/i2c.dtsi +++ b/tests/drivers/build_all/sensor/i2c.dtsi @@ -664,3 +664,10 @@ test_i2c_wsen_tids: wsen_tids@67 { int-gpios = <&test_gpio 0 0>; odr = <25>; }; + +test_i2c_vl53l1x: vl53l1x@68 { + compatible = "st,vl53l1x"; + reg = <0x68>; + int-gpios = <&test_gpio 0 0>; + xshut-gpios = <&test_gpio 0 0>; +};