zephyr/drivers/sensor/vl53l1x/vl53l1_platform.c
Mark Watson 1f178ca935 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 <mwatson@prosaris.ca>
2023-03-03 10:01:55 -06:00

183 lines
4.3 KiB
C

/* 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 <zephyr/drivers/sensor.h>
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/init.h>
#include <zephyr/drivers/i2c.h>
#include <zephyr/logging/log.h>
#include <zephyr/sys/byteorder.h>
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 *)(&reg), 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(&current_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;
}