mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 10:31:46 +09:00
iio: proximity: add nds03 tof sensor
Change-Id: I263bc2a7cc302ded8c940a10f73e050abdefa1de Signed-off-by: Jianwei Fan <jianwei.fan@rock-chips.com>
This commit is contained in:
@@ -32,6 +32,8 @@ config CROS_EC_MKBP_PROXIMITY
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called cros_ec_mkbp_proximity.
|
||||
|
||||
source "drivers/iio/proximity/nds03/Kconfig"
|
||||
|
||||
config ISL29501
|
||||
tristate "Intersil ISL29501 Time Of Flight sensor"
|
||||
depends on I2C
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
# When adding new entries keep the list in alphabetical order
|
||||
obj-$(CONFIG_AS3935) += as3935.o
|
||||
obj-$(CONFIG_CROS_EC_MKBP_PROXIMITY) += cros_ec_mkbp_proximity.o
|
||||
obj-$(CONFIG_DTOF_NDS03) += nds03/
|
||||
obj-$(CONFIG_ISL29501) += isl29501.o
|
||||
obj-$(CONFIG_LIDAR_LITE_V2) += pulsedlight-lidar-lite-v2.o
|
||||
obj-$(CONFIG_MB1232) += mb1232.o
|
||||
|
||||
7
drivers/iio/proximity/nds03/Kconfig
Normal file
7
drivers/iio/proximity/nds03/Kconfig
Normal file
@@ -0,0 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
config DTOF_NDS03
|
||||
tristate "NDS03 I2C DEVICE"
|
||||
depends on I2C && SYSFS
|
||||
help
|
||||
Using I2C
|
||||
9
drivers/iio/proximity/nds03/Makefile
Normal file
9
drivers/iio/proximity/nds03/Makefile
Normal file
@@ -0,0 +1,9 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#
|
||||
# Makefile for the nds03 drivers.
|
||||
#
|
||||
|
||||
obj-$(CONFIG_DTOF_NDS03) += nds03.o
|
||||
nds03-y += nds03_module.o nds03_platform.o nds03_module_i2c.o nds03_iio.o \
|
||||
nds03_dev.o nds03_data.o \
|
||||
nds03_comm.o nds03_calib.o
|
||||
104
drivers/iio/proximity/nds03/nds03.h
Normal file
104
drivers/iio/proximity/nds03/nds03.h
Normal file
@@ -0,0 +1,104 @@
|
||||
/*!
|
||||
@file nds03.h
|
||||
@brief
|
||||
@author lull
|
||||
@date 2025-06
|
||||
@copyright Copyright (c) 2025 Shenzhen Nephotonics Semiconductor Technology Co., Ltd.
|
||||
@license BSD 3-Clause License
|
||||
This file is part of the Nephotonics sensor SDK.
|
||||
It is licensed under the BSD 3-Clause License.
|
||||
A copy of the license can be found in the project root directory, in the file named LICENSE.
|
||||
*/
|
||||
#ifndef __NDS03_H
|
||||
#define __NDS03_H
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
/* nds03 sdk */
|
||||
#include "nds03_comm.h"
|
||||
#include "nds03_dev.h"
|
||||
#include "nds03_data.h"
|
||||
#include "nds03_calib.h"
|
||||
#include "nds03_def.h"
|
||||
|
||||
#define TOF_NDS03_DRV_NAME "tof_nds03"
|
||||
#define DRIVER_VERSION "1.0.4"
|
||||
#define TOF_NDS03_MAJOR 255
|
||||
#define MAX_POS_BITS 32
|
||||
|
||||
/*! use debug */
|
||||
extern int nds03_enable_debug;
|
||||
|
||||
#define nds03_dbgmsg(str, ...) \
|
||||
do { \
|
||||
if (nds03_enable_debug > 0) \
|
||||
printk("%s: " str, __FUNCTION__, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define nds03_info(str, ...) \
|
||||
pr_info("%s: " str , __FUNCTION__, ##__VA_ARGS__)
|
||||
|
||||
#define nds03_errmsg(str, ...) \
|
||||
pr_err("%s: " str, __FUNCTION__, ##__VA_ARGS__)
|
||||
|
||||
#define nds03_warnmsg(str, ...) \
|
||||
pr_warn("%s: " str,__FUNCTION__, ##__VA_ARGS__)
|
||||
|
||||
struct nds03_context {
|
||||
|
||||
/*!< multiple device id 0 based*/
|
||||
int id;
|
||||
|
||||
/*!< misc device name */
|
||||
char name[64];
|
||||
|
||||
struct i2c_client * client;
|
||||
|
||||
/*!< nds03 device info */
|
||||
NDS03_Dev_t g_nds03_device;
|
||||
|
||||
/*!< main dev mutex/lock */
|
||||
struct mutex work_mutex;
|
||||
|
||||
// /*!< work for pseudo irq polling check */
|
||||
struct delayed_work dwork;
|
||||
struct work_struct irq_work;
|
||||
// /*!< input device used for sending event */
|
||||
struct input_dev *idev;
|
||||
|
||||
/*!< intr gpio number */
|
||||
int irq;
|
||||
|
||||
bool remove_flag;
|
||||
/// /* user control configuration parameter */
|
||||
/*!< measure mode irq or poll*/
|
||||
atomic_t meas_mode;
|
||||
/*!< rescheduled time use in poll mode */
|
||||
atomic_t poll_delay_ms;
|
||||
/*!< use ctrl measure state */
|
||||
atomic_t is_meas;
|
||||
/*!< calibtion result of the deivce */
|
||||
int calib_result;
|
||||
/*!< open input file descriptor count*/
|
||||
int fd_open_count;
|
||||
struct iio_dev *indio_dev;
|
||||
struct nds03_iio_dev *iio;
|
||||
};
|
||||
|
||||
int nds03_common_probe(struct nds03_context * ctx);
|
||||
int nds03_common_remove(struct nds03_context * ctx);
|
||||
int nds03_interrupt_config(NDS03_Dev_t *pNxDevice, uint8_t is_open);
|
||||
int nds03_sensor_init(struct nds03_context *ctx);
|
||||
|
||||
#endif
|
||||
275
drivers/iio/proximity/nds03/nds03_calib.c
Normal file
275
drivers/iio/proximity/nds03/nds03_calib.c
Normal file
@@ -0,0 +1,275 @@
|
||||
/**
|
||||
* @file nds03_calib.c
|
||||
* @author tongsheng.tang
|
||||
* @brief NDS03 Calibration functions
|
||||
* @version 2.x.x
|
||||
* @date 2025-06
|
||||
*
|
||||
* @copyright Copyright (c) 2025, Nephotonics Information Technology (Hefei) Co., Ltd.
|
||||
*
|
||||
* @license BSD 3-Clause License
|
||||
* This file is part of the NDS03 SDK and is licensed under the BSD 3-Clause License.
|
||||
* You may obtain a copy of the license in the project root directory,
|
||||
* in the file named LICENSE.
|
||||
*/
|
||||
|
||||
#include "nds03_comm.h"
|
||||
#include "nds03_dev.h"
|
||||
#include "nds03_data.h"
|
||||
#include "nds03_calib.h"
|
||||
|
||||
/**
|
||||
* @brief NDS03 Get Offset Calib Depth MM
|
||||
* 获取offset标定距离
|
||||
* @param pNxDevice
|
||||
* @param calib_depth_mm
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_GetOffsetCalibDepthMM(NDS03_Dev_t *pNxDevice, uint16_t *calib_depth_mm)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
CHECK_RET(NDS03_ReadHalfWord(pNxDevice, NDS03_REG_OFFSET_MM, calib_depth_mm));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Set Offset Calib Depth MM
|
||||
* 设置offset标定距离
|
||||
* @param pNxDevice
|
||||
* @param calib_depth_mm
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_SetOffsetCalibDepthMM(NDS03_Dev_t *pNxDevice, uint16_t calib_depth_mm)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
if (calib_depth_mm == 0)
|
||||
CHECK_RET(NDS03_ReadHalfWord(pNxDevice, NDS03_REG_OFFSET_MM, &calib_depth_mm));
|
||||
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_CFG_ENA, NDS03_CMD_ENA_ENABLE));
|
||||
CHECK_RET(NDS03_WriteHalfWord(pNxDevice, NDS03_REG_OFFSET_MM, calib_depth_mm));
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_CFG_ENA, NDS03_CMD_ENA_DISABLE));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Offset Calibration Check
|
||||
* Offset 标定检查
|
||||
* @param pNxDevice
|
||||
* @param calib_depth_mm
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
static NDS03_Error NDS03_OffsetCalibrationCheck(NDS03_Dev_t *pNxDevice)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
uint16_t ref_histo_max, depth[2];
|
||||
uint8_t depth_flag;
|
||||
|
||||
CHECK_RET(NDS03_GetSingleRangingData(pNxDevice));
|
||||
CHECK_RET(NDS03_ReadHalfWord(pNxDevice, NDS03_REG_REF_HISTO_MAX, &ref_histo_max));
|
||||
if (ret == NDS03_ERROR_NONE && ref_histo_max < NDS03_OFFSET_REF_MAX_COUNT_TH) {
|
||||
ret = NDS03_ERROR_VCSEL_ERROR;
|
||||
NX_PRINTF("ref_histo_max:%d\r\n", ref_histo_max);
|
||||
return ret;
|
||||
}
|
||||
CHECK_RET(NDS03_ReadByte(pNxDevice, NDS03_REG_DEPTH_FLAG, &depth_flag));
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_CFG_ENA, NDS03_CMD_ENA_ENABLE));
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_DEPTH_FLAG, 1));
|
||||
CHECK_RET(NDS03_GetSingleRangingData(pNxDevice));
|
||||
depth[0] = pNxDevice->ranging_data[0].depth;
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_DEPTH_FLAG, 2));
|
||||
CHECK_RET(NDS03_GetSingleRangingData(pNxDevice));
|
||||
depth[1] = pNxDevice->ranging_data[0].depth;
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_DEPTH_FLAG, depth_flag));
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_CFG_ENA, NDS03_CMD_ENA_DISABLE));
|
||||
if (ret == NDS03_ERROR_NONE && ((depth[0] + NDS03_OFFSET_DEPTH_ERROR_TH < depth[1]) ||
|
||||
(depth[0] > depth[1] + NDS03_OFFSET_DEPTH_ERROR_TH) ||
|
||||
depth[0] == NDS03_DEPTH_INVALID_VALUE || depth[1] == NDS03_DEPTH_INVALID_VALUE)) {
|
||||
ret = NDS03_ERROR_OFFSET_ERROR;
|
||||
NX_PRINTF("depth[0]:%d depth[1]:%d\r\n", depth[0], depth[1]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief ToF Offset 标定
|
||||
* @details 不可以指定标定距离,使用默认距离,如果没有修改,那值默认是500mm
|
||||
*
|
||||
* @param pNxDevice 设备模组
|
||||
* @return int8_t
|
||||
* @retval 0: 成功
|
||||
* @retval !0: Offset标定失败
|
||||
*/
|
||||
NDS03_Error NDS03_OffsetCalibration(NDS03_Dev_t *pNxDevice)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
uint16_t ambient_bg;
|
||||
|
||||
NX_PRINTF("%s Start!\r\n", __func__);
|
||||
CHECK_RET(NDS03_GetSingleRangingData(pNxDevice));
|
||||
CHECK_RET(NDS03_ReadHalfWord(pNxDevice, NDS03_REG_AMBIENT, &ambient_bg));
|
||||
if (ambient_bg > NDS03_AMBIENT_TH) {
|
||||
ret = NDS03_ERROR_AMBIENT_HIGH;
|
||||
NX_PRINTF("ambient_bg:%d\r\n", ambient_bg);
|
||||
return ret;
|
||||
}
|
||||
// 打开使能
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_CMD_ENA, NDS03_CMD_ENA_ENABLE));
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_CMD_REQ, NDS03_CMD_OFFSET_CALIB));
|
||||
CHECK_RET(NDS03_WaitforCmdVal(pNxDevice, NDS03_CMD_OFFSET_CALIB, 10000));
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_CMD_VAL, NDS03_CMD_ENA_DISABLE));
|
||||
CHECK_RET(NDS03_ReadByte(pNxDevice, NDS03_REG_CALIB_STATE, (uint8_t*)&ret));
|
||||
CHECK_RET(NDS03_OffsetCalibrationCheck(pNxDevice));
|
||||
|
||||
NX_PRINTF("%s End!\r\n", __func__);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief ToF Offset 标定
|
||||
* @details 可以指定标定距离
|
||||
*
|
||||
* @param pNxDevice 设备模组
|
||||
* @param calib_depth_mm 标定距离
|
||||
* @return int8_t
|
||||
* @retval 0: 成功
|
||||
* @retval !0: Offset标定失败
|
||||
*/
|
||||
NDS03_Error NDS03_OffsetCalibrationAtDepth(NDS03_Dev_t *pNxDevice, uint16_t calib_depth_mm)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
uint16_t ambient_bg;
|
||||
|
||||
NX_PRINTF("%s Start!\r\n", __func__);
|
||||
|
||||
CHECK_RET(NDS03_GetSingleRangingData(pNxDevice));
|
||||
CHECK_RET(NDS03_ReadHalfWord(pNxDevice, NDS03_REG_AMBIENT, &ambient_bg));
|
||||
if (ambient_bg > NDS03_AMBIENT_TH){
|
||||
ret = NDS03_ERROR_AMBIENT_HIGH;
|
||||
NX_PRINTF("ambient:%d \r\n", ambient_bg);
|
||||
return ret;
|
||||
}
|
||||
CHECK_RET(NDS03_SetOffsetCalibDepthMM(pNxDevice, calib_depth_mm));
|
||||
// 打开使能
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_CMD_ENA, NDS03_CMD_ENA_ENABLE));
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_CMD_REQ, NDS03_CMD_OFFSET_CALIB));
|
||||
CHECK_RET(NDS03_WaitforCmdVal(pNxDevice, NDS03_CMD_OFFSET_CALIB, 10000));
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_CMD_VAL, NDS03_CMD_ENA_DISABLE));
|
||||
CHECK_RET(NDS03_ReadByte(pNxDevice, NDS03_REG_CALIB_STATE, (uint8_t*)&ret));
|
||||
CHECK_RET(NDS03_OffsetCalibrationCheck(pNxDevice));
|
||||
|
||||
NX_PRINTF("%s End!\r\n", __func__);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Read Xtalk Data
|
||||
* 读取NDS03串扰数据
|
||||
* @param pNxDevice 模组设备
|
||||
* @param rbuf 数据指针
|
||||
* @param size 数据大小
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
static NDS03_Error NDS03_ReadXtalkData(NDS03_Dev_t *pNxDevice)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
uint32_t rsize, _size;
|
||||
uint8_t one_size;
|
||||
uint16_t addr;
|
||||
uint16_t rbuf[240];
|
||||
uint8_t *rbuf_ptr = (uint8_t *)rbuf;
|
||||
uint32_t size = 240 * 2;
|
||||
|
||||
CHECK_RET(NDS03_ReadByte(pNxDevice, NDS03_REG_CACHE_SIZE, &one_size));
|
||||
CHECK_RET(NDS03_ReadHalfWord(pNxDevice, 0xEC, &addr));
|
||||
_size = (uint32_t)one_size;
|
||||
rsize = 0;
|
||||
while ((rsize < size) && (ret == NDS03_ERROR_NONE)) {
|
||||
CHECK_RET(NDS03_WriteHalfWord(pNxDevice, NDS03_REG_CACHE_ADDR, addr));
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_CMD_ENA, 0x05));
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_DAT_REQ, 0xC0));
|
||||
CHECK_RET(NDS03_WaitforDataVal(pNxDevice, 0xC0, 200));
|
||||
CHECK_RET(NDS03_ReadNBytes(pNxDevice, NDS03_REG_CACHE_DATA, rbuf_ptr,
|
||||
((size-rsize)>_size) ? _size:(size-rsize)));
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_DAT_VAL, NDS03_DATA_VAL_IDLE));
|
||||
rbuf_ptr += _size;
|
||||
addr += _size;
|
||||
rsize += _size;
|
||||
}
|
||||
for (int i = 80; i < 240; i++) {
|
||||
if (rbuf[i] > 10000)
|
||||
return -14;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Xtalk Calibration
|
||||
* NDS03串扰/盖板标定
|
||||
* @param pNxDevice 设备模组
|
||||
* @return int8_t
|
||||
* @retval 0: 成功
|
||||
* @retval !0: xtalk标定失败
|
||||
*/
|
||||
NDS03_Error NDS03_XtalkCalibration(NDS03_Dev_t *pNxDevice)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE, calib_state = NDS03_ERROR_NONE;
|
||||
uint16_t ambient_bg,ref_histo_max;
|
||||
uint8_t cnt = 2;
|
||||
int8_t check_xtalk_state = 0;
|
||||
|
||||
NX_PRINTF("%s Start!\r\n", __func__);
|
||||
do {
|
||||
CHECK_RET(NDS03_GetSingleRangingData(pNxDevice));
|
||||
CHECK_RET(NDS03_ReadHalfWord(pNxDevice, NDS03_REG_AMBIENT, &ambient_bg));
|
||||
CHECK_RET(NDS03_ReadHalfWord(pNxDevice, NDS03_REG_REF_HISTO_MAX, &ref_histo_max));
|
||||
if (ambient_bg > NDS03_AMBIENT_TH) {
|
||||
ret = NDS03_ERROR_AMBIENT_HIGH;
|
||||
NX_PRINTF("ambient:%d\r\n", ambient_bg);
|
||||
return ret;
|
||||
}
|
||||
if (ret == NDS03_ERROR_NONE && ref_histo_max < NDS03_OFFSET_REF_MAX_COUNT_TH) {
|
||||
ret = NDS03_ERROR_VCSEL_ERROR;
|
||||
NX_PRINTF("ref_histo_max:%d\r\n", ref_histo_max);
|
||||
return ret;
|
||||
}
|
||||
// 打开使能
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_CMD_ENA, NDS03_CMD_ENA_ENABLE));
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_CMD_REQ, NDS03_CMD_XTALK_CALIB));
|
||||
CHECK_RET(NDS03_WaitforCmdVal(pNxDevice, NDS03_CMD_XTALK_CALIB, 5000));
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_CMD_VAL, NDS03_CMD_ENA_DISABLE));
|
||||
CHECK_RET(NDS03_GetFirmwareVersion(pNxDevice));
|
||||
if (pNxDevice->chip_info.fw_version == 0x10203) {
|
||||
CHECK_RET(NDS03_GetSingleRangingData(pNxDevice));
|
||||
check_xtalk_state = NDS03_ReadXtalkData(pNxDevice);
|
||||
}
|
||||
|
||||
} while (cnt-- && check_xtalk_state != 0);
|
||||
CHECK_RET(NDS03_ReadByte(pNxDevice, NDS03_REG_CALIB_STATE, (uint8_t*)&calib_state));
|
||||
ret = check_xtalk_state ? check_xtalk_state : (ret | calib_state) &
|
||||
(NDS03_CALIB_ERROR_XTALK_OVERFLOW | NDS03_CALIB_ERROR_XTALK_EXCESSIVE);
|
||||
NX_PRINTF("%s End!\r\n", __func__);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Get Xtalk Value
|
||||
* 获取标定串扰值
|
||||
* @param pNxDevice
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_GetXTalkValue(NDS03_Dev_t *pNxDevice, uint16_t* xtalk_value)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
CHECK_RET(NDS03_ReadHalfWord(pNxDevice, NDS03_REG_XTALK, xtalk_value));
|
||||
|
||||
return ret;
|
||||
}
|
||||
42
drivers/iio/proximity/nds03/nds03_calib.h
Normal file
42
drivers/iio/proximity/nds03/nds03_calib.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* @file nds03_calib.h
|
||||
* @author tongsheng.tang
|
||||
* @brief NDS03 Calibration functions
|
||||
* @version 2.x.x
|
||||
* @date 2025-06
|
||||
*
|
||||
* @copyright Copyright (c) 2025, Nephotonics Information Technology (Hefei) Co., Ltd.
|
||||
*
|
||||
* @license BSD 3-Clause License
|
||||
* This file is part of the NDS03 SDK and is licensed under the BSD 3-Clause License.
|
||||
* You may obtain a copy of the license in the project root directory, in the file named LICENSE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __NDS03_CALIB_H__
|
||||
#define __NDS03_CALIB_H__
|
||||
|
||||
#include "nds03_def.h"
|
||||
|
||||
/** @defgroup NDS03_Calibration_Group NDS03 Calibration Functions
|
||||
* @brief NDS03 Calibration Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** 获取offset标定距离 */
|
||||
NDS03_Error NDS03_GetOffsetCalibDepthMM(NDS03_Dev_t *pNxDevice, uint16_t *calib_depth_mm);
|
||||
/** 设置offset标定距离 */
|
||||
NDS03_Error NDS03_SetOffsetCalibDepthMM(NDS03_Dev_t *pNxDevice, uint16_t calib_depth_mm);
|
||||
/** Offset标定函数(无标定距离设置) */
|
||||
NDS03_Error NDS03_OffsetCalibration(NDS03_Dev_t *pNxDevice);
|
||||
/** Offset标定函数(有标定距离设置) */
|
||||
NDS03_Error NDS03_OffsetCalibrationAtDepth(NDS03_Dev_t *pNxDevice, uint16_t calib_depth_mm);
|
||||
/** XTalk标定 */
|
||||
NDS03_Error NDS03_XtalkCalibration(NDS03_Dev_t *pNxDevice);
|
||||
/** 获取标定串扰值 */
|
||||
NDS03_Error NDS03_GetXTalkValue(NDS03_Dev_t *pNxDevice, uint16_t* xtalk_value);
|
||||
|
||||
/** @} NDS03_Calibration_Group */
|
||||
|
||||
#endif
|
||||
|
||||
385
drivers/iio/proximity/nds03/nds03_comm.c
Normal file
385
drivers/iio/proximity/nds03/nds03_comm.c
Normal file
@@ -0,0 +1,385 @@
|
||||
/**
|
||||
* @file nds03_comm.c
|
||||
* @author tongsheng.tang
|
||||
* @brief NDS03 communication functions
|
||||
* @version 2.x.x
|
||||
* @date 2025-06
|
||||
*
|
||||
* @copyright Copyright (c) 2025, Nephotonics Information Technology (Hefei) Co., Ltd.
|
||||
*
|
||||
* @license BSD 3-Clause License
|
||||
* This file is part of the NDS03 SDK and is licensed under the BSD 3-Clause License.
|
||||
* You may obtain a copy of the license in the project root directory,
|
||||
* in the file named LICENSE.
|
||||
*/
|
||||
|
||||
#include "nds03_stdint.h"
|
||||
#if NDS03_PLATFORM != PLATFORM_LINUX_DRIVER
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#else
|
||||
#include <linux/types.h>
|
||||
#endif
|
||||
#include "nds03_dev.h"
|
||||
#include "nds03_comm.h"
|
||||
#include "nds03_def.h"
|
||||
#include "nds03_platform.h"
|
||||
|
||||
/**
|
||||
* @brief NDS03 Delay 1ms
|
||||
* @param ms 延时时间
|
||||
* @return void
|
||||
*/
|
||||
NDS03_Error NDS03_Delay1ms(NDS03_Dev_t *pNxDevice, uint32_t ms)
|
||||
{
|
||||
return nds03_delay_1ms(&pNxDevice->platform, ms);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Delay 10us
|
||||
* @param us 延时时间
|
||||
* @return void
|
||||
*/
|
||||
NDS03_Error NDS03_Delay10us(NDS03_Dev_t *pNxDevice, uint32_t us)
|
||||
{
|
||||
return nds03_delay_10us(&pNxDevice->platform, us);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Get System Clk Ms
|
||||
* @param pNxDevice 模组设备
|
||||
* @param time_ms 获取时间(ms)
|
||||
* @return void
|
||||
*/
|
||||
NDS03_Error NDS03_GetSystemClkMs(NDS03_Dev_t *pNxDevice,int32_t *time_ms)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
ret = nds03_get_system_clk_ms(&pNxDevice->platform, time_ms);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Set XShut Pin Level
|
||||
* 设置xshut引脚的电平
|
||||
* @param pNxDevice 模组设备
|
||||
* @param level xshut引脚电平,0为低电平,1为高电平
|
||||
* @return void
|
||||
*/
|
||||
NDS03_Error NDS03_SetXShutPinLevel(NDS03_Dev_t *pNxDevice, int8_t level)
|
||||
{
|
||||
return nds03_set_xshut_pin_level(&pNxDevice->platform, level);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取当前i2c时钟频率
|
||||
*
|
||||
* @param pNxDevice 模组设备
|
||||
* @param freq 获取的频率
|
||||
* @return
|
||||
*/
|
||||
NDS03_Error NDS03_GetI2cFreq(NDS03_Dev_t *pNxDevice, uint32_t *freq)
|
||||
{
|
||||
return nds03_i2c_get_clock_frequency(&pNxDevice->platform, freq);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置当前i2c时钟频率
|
||||
*
|
||||
* @param pNxDevice 模组设备
|
||||
* @param freq 设置的频率
|
||||
* @return
|
||||
*/
|
||||
NDS03_Error NDS03_SetI2cFreq(NDS03_Dev_t *pNxDevice, uint32_t freq)
|
||||
{
|
||||
return nds03_i2c_set_clock_frequency(&pNxDevice->platform, freq);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 半字,即2个字节,调换数据格式
|
||||
* 小端无影响,大端会调换数据格式
|
||||
* @param buf 数据缓冲区
|
||||
* @param buf_num 数据个数
|
||||
*/
|
||||
static void NDS03_HalfWordDataFmtChange(uint16_t *buf, uint16_t buf_num)
|
||||
{
|
||||
uint16_t tmp;
|
||||
uint8_t *pu8buf = (uint8_t*)buf;
|
||||
uint16_t i;
|
||||
|
||||
for (i = 0; i < buf_num; i++) {
|
||||
tmp = buf[i];
|
||||
*pu8buf++ = (tmp >> 0);
|
||||
*pu8buf++ = (tmp >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 1字,即4个字节,调换数据格式
|
||||
* 小端无影响,大端会调换数据格式
|
||||
* @param buf 数据缓冲区
|
||||
* @param buf_num 数据个数
|
||||
*/
|
||||
static void NDS03_WordDataFmtChange(uint32_t *buf, uint16_t buf_num)
|
||||
{
|
||||
uint32_t tmp;
|
||||
uint8_t *pu8buf = (uint8_t*)buf;
|
||||
uint16_t i;
|
||||
|
||||
for (i = 0; i < buf_num; i++) {
|
||||
tmp = buf[i];
|
||||
*pu8buf++ = (tmp >> 0);
|
||||
*pu8buf++ = (tmp >> 8);
|
||||
*pu8buf++ = (tmp >> 16);
|
||||
*pu8buf++ = (tmp >> 24);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write n Words to NDS03
|
||||
* 对NDS03的寄存器写N个字
|
||||
* @param pNxDevice: NDS03模组设备信息结构体指针
|
||||
* @param addr: 寄存器地址
|
||||
* @param wdata: 存放寄存器值的指针
|
||||
* @param len: 写数据的长度,按字个数计算
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_WriteNBytes(NDS03_Dev_t *pNxDevice, uint8_t addr, void *wdata, uint16_t size)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
ret = nds03_i2c_write_nbytes(&pNxDevice->platform, addr, (uint8_t*)wdata, size);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read n Words from NDS03
|
||||
* 对NDS03的寄存器读N个字
|
||||
* @param pNxDevice: NDS03模组设备信息结构体指针
|
||||
* @param addr: 寄存器地址
|
||||
* @param rdata: 存放寄存器值的指针
|
||||
* @param len: 读数据的长度,按字个数计算
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_ReadNBytes(NDS03_Dev_t *pNxDevice, uint8_t addr, void *rdata, uint16_t size)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
ret = nds03_i2c_read_nbytes(&pNxDevice->platform, addr, (uint8_t*)rdata, size);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write 1 Byte to NDS03
|
||||
* 对NDS03的寄存器写1个字节
|
||||
* @param pNxDevice: NDS03模组设备信息结构体指针
|
||||
* @param addr: 寄存器地址
|
||||
* @param wdata: 寄存器的值
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_WriteByte(NDS03_Dev_t *pNxDevice, uint8_t addr, uint8_t wdata)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
ret = nds03_i2c_write_nbytes(&pNxDevice->platform, addr, &wdata, 1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read 1 Byte from NDS03
|
||||
* 对NDS03的寄存器读1个字节
|
||||
* @param pNxDevice: NDS03模组设备信息结构体指针
|
||||
* @param addr: 寄存器地址
|
||||
* @param rdata: 寄存器的值
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_ReadByte(NDS03_Dev_t *pNxDevice, uint8_t addr, uint8_t *rdata)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
ret = nds03_i2c_read_nbytes(&pNxDevice->platform, addr, rdata, 1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write N bytes By Half-Word to NDS03
|
||||
* 对NDS03的寄存器写N个字节,使用半字写的方式
|
||||
* @param pNxDevice: NDS03模组设备信息结构体指针
|
||||
* @param addr: 寄存器地址
|
||||
* @param wdata: 寄存器的值
|
||||
* @param size: 写数据的长度,按字节个数计算
|
||||
* 注意:size必须是2的倍数
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_WriteNBytesByHalfWord(NDS03_Dev_t *pNxDevice,
|
||||
uint8_t addr, uint16_t *wdata, uint16_t size)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
if ((size & 0x01) == 0) {
|
||||
NDS03_HalfWordDataFmtChange(wdata, size / 2);
|
||||
ret = nds03_i2c_write_nbytes(&pNxDevice->platform, addr, (uint8_t*)wdata, size);
|
||||
NDS03_HalfWordDataFmtChange(wdata, size / 2);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read N Bytes By Half-World from NDS03
|
||||
* 对NDS03的寄存器读N个字节,使用半字读的方式
|
||||
* @param pNxDevice: NDS03模组设备信息结构体指针
|
||||
* @param addr: 寄存器地址
|
||||
* @param rdata: 寄存器的值
|
||||
* @param size: 读数据的长度,按字节个数计算
|
||||
* 注意:size必须是2的倍数
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_ReadNBytesByHalfWord(NDS03_Dev_t *pNxDevice, uint8_t addr, uint16_t *rdata, uint16_t size)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
if ((size & 0x01) == 0 && rdata != NULL) {
|
||||
ret = nds03_i2c_read_nbytes(&pNxDevice->platform, addr, (uint8_t*)rdata, size);
|
||||
NDS03_HalfWordDataFmtChange(rdata, size / 2);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write 2 Byte to NDS03
|
||||
* 对NDS03的寄存器写2个字节
|
||||
* @param pNxDevice: NDS03模组设备信息结构体指针
|
||||
* @param addr: 寄存器地址
|
||||
* @param wdata: 寄存器的值
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_WriteHalfWord(NDS03_Dev_t *pNxDevice, uint8_t addr, uint16_t wdata)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
uint8_t tmp[2];
|
||||
|
||||
tmp[0] = (wdata >> 0) & 0xFF;
|
||||
tmp[1] = (wdata >> 8) & 0xFF;
|
||||
ret = nds03_i2c_write_nbytes(&pNxDevice->platform, addr, tmp, sizeof(tmp));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read 2 Byte from NDS03
|
||||
* 对NDS03的寄存器读2个字节
|
||||
* @param pNxDevice: NDS03模组设备信息结构体指针
|
||||
* @param addr: 寄存器地址
|
||||
* @param rdata: 寄存器的值
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_ReadHalfWord(NDS03_Dev_t *pNxDevice, uint8_t addr, uint16_t *rdata)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
uint8_t tmp[2];
|
||||
|
||||
if (rdata != NULL) {
|
||||
ret = nds03_i2c_read_nbytes(&pNxDevice->platform, addr, tmp, sizeof(tmp));
|
||||
*rdata = (uint16_t)tmp[0] | ((uint16_t)tmp[1] << 8);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write N Bytes By Word to NDS03
|
||||
* 对NDS03的寄存器写N个字节,使用字方式
|
||||
* @param pNxDevice: NDS03模组设备信息结构体指针
|
||||
* @param addr: 寄存器地址
|
||||
* @param wdata: 寄存器的值
|
||||
* @param size: 写数据的长度,按字节个数计算
|
||||
* 注意:size必须是4的倍数
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_WriteNBytesByWord(NDS03_Dev_t *pNxDevice, uint8_t addr,
|
||||
uint32_t *wdata, uint16_t size)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
if ((size & 0x03) == 0) {
|
||||
NDS03_WordDataFmtChange(wdata, size / 4);
|
||||
ret = nds03_i2c_write_nbytes(&pNxDevice->platform, addr, (uint8_t*)wdata, size);
|
||||
NDS03_WordDataFmtChange(wdata, size / 4);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read N Bytes By Word from NDS03
|
||||
* 对NDS03的寄存器读N个字节,使用字方式
|
||||
* @param pNxDevice: NDS03模组设备信息结构体指针
|
||||
* @param addr: 寄存器地址
|
||||
* @param rdata: 寄存器的值
|
||||
* @param size: 读数据的长度,按字节个数计算
|
||||
* 注意:size必须是4的倍数
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_ReadNBytesByWord(NDS03_Dev_t *pNxDevice, uint8_t addr, uint32_t *rdata, uint16_t size)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
if ((size & 0x03) == 0 && rdata != NULL) {
|
||||
ret = nds03_i2c_read_nbytes(&pNxDevice->platform, addr, (uint8_t*)rdata, size);
|
||||
NDS03_WordDataFmtChange(rdata, size / 4);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write 4 Byte to NDS03
|
||||
* 对NDS03的寄存器写2个字节
|
||||
* @param pNxDevice: NDS03模组设备信息结构体指针
|
||||
* @param addr: 寄存器地址
|
||||
* @param wdata: 寄存器的值
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_WriteWord(NDS03_Dev_t *pNxDevice, uint8_t addr, uint32_t wdata)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
uint8_t tmp[4];
|
||||
|
||||
tmp[0] = (wdata >> 0) & 0xFF;
|
||||
tmp[1] = (wdata >> 8) & 0xFF;
|
||||
tmp[2] = (wdata >> 16) & 0xFF;
|
||||
tmp[3] = (wdata >> 24) & 0xFF;
|
||||
ret = nds03_i2c_write_nbytes(&pNxDevice->platform, addr, tmp, sizeof(tmp));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read 4 Byte from NDS03
|
||||
* 对NDS03的寄存器读2个字节
|
||||
* @param pNxDevice: NDS03模组设备信息结构体指针
|
||||
* @param addr: 寄存器地址
|
||||
* @param rdata: 寄存器的值
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_ReadWord(NDS03_Dev_t *pNxDevice, uint8_t addr, uint32_t *rdata)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
uint8_t tmp[4];
|
||||
|
||||
if (rdata != NULL) {
|
||||
ret = nds03_i2c_read_nbytes(&pNxDevice->platform, addr, tmp, sizeof(tmp));
|
||||
*rdata = (uint32_t)tmp[0] | ((uint32_t)tmp[1] << 8) |
|
||||
((uint32_t)tmp[2] << 16) | ((uint32_t)tmp[3] << 24);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
71
drivers/iio/proximity/nds03/nds03_comm.h
Normal file
71
drivers/iio/proximity/nds03/nds03_comm.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* @file nds03_comm.h
|
||||
* @author tongsheng.tang
|
||||
* @brief NDS03 communication functions
|
||||
* @version 2.x.x
|
||||
* @date 2025-06
|
||||
*
|
||||
* @copyright Copyright (c) 2025, Nephotonics Information Technology (Hefei) Co., Ltd.
|
||||
*
|
||||
* @license BSD 3-Clause License
|
||||
* This file is part of the NDS03 SDK and is licensed under the BSD 3-Clause License.
|
||||
* You may obtain a copy of the license in the project root directory,
|
||||
* in the file named LICENSE.
|
||||
*/
|
||||
#ifndef __NDS03_COMM_H__
|
||||
#define __NDS03_COMM_H__
|
||||
|
||||
#include "nds03_def.h"
|
||||
|
||||
/** @defgroup NDS03_Communication_Group NDS03 Communication Functions
|
||||
* @brief NDS03 Communication Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** 延时时间(ms) */
|
||||
NDS03_Error NDS03_Delay1ms(NDS03_Dev_t *pNxDevice, uint32_t ms);
|
||||
|
||||
/** 延时时间(10us) */
|
||||
NDS03_Error NDS03_Delay10us(NDS03_Dev_t *pNxDevice, uint32_t us);
|
||||
|
||||
/** 设置xshut引脚的电平 */
|
||||
NDS03_Error NDS03_SetXShutPinLevel(NDS03_Dev_t *pNxDevice, int8_t level);
|
||||
|
||||
/** NDS03设置i2c频率 */
|
||||
NDS03_Error NDS03_SetI2cFreq(NDS03_Dev_t *pNxDevice, uint32_t freq);
|
||||
/** NDS03获取i2c频率 */
|
||||
NDS03_Error NDS03_GetI2cFreq(NDS03_Dev_t *pNxDevice, uint32_t *freq);
|
||||
/** 对NDS03寄存器写N个字节 */
|
||||
NDS03_Error NDS03_WriteNBytes(NDS03_Dev_t *pNxDevice, uint8_t addr, void *wdata, uint16_t size);
|
||||
/** 对NDS03寄存器读N个字节 */
|
||||
NDS03_Error NDS03_ReadNBytes(NDS03_Dev_t *pNxDevice, uint8_t addr, void *rdata, uint16_t size);
|
||||
/** 对NDS03寄存器写1个字节 */
|
||||
NDS03_Error NDS03_WriteByte(NDS03_Dev_t *pNxDevice, uint8_t addr, uint8_t wdata);
|
||||
/** 对NDS03寄存器写1个字节 */
|
||||
NDS03_Error NDS03_ReadByte(NDS03_Dev_t *pNxDevice, uint8_t addr, uint8_t *rdata);
|
||||
/** 对NDS03寄存器写N个字节,使用半字方式 */
|
||||
NDS03_Error NDS03_WriteNBytesByHalfWord(NDS03_Dev_t *pNxDevice,
|
||||
uint8_t addr, uint16_t *wdata, uint16_t size);
|
||||
/** 对NDS03寄存器读N个字节,使用半字方式 */
|
||||
NDS03_Error NDS03_ReadNBytesByHalfWord(NDS03_Dev_t *pNxDevice,
|
||||
uint8_t addr, uint16_t *rdata, uint16_t size);
|
||||
/** 对NDS03寄存器写1个字 */
|
||||
NDS03_Error NDS03_WriteHalfWord(NDS03_Dev_t *pNxDevice, uint8_t addr, uint16_t wdata);
|
||||
/** 对NDS03寄存器读1个字 */
|
||||
NDS03_Error NDS03_ReadHalfWord(NDS03_Dev_t *pNxDevice, uint8_t addr, uint16_t *rdata);
|
||||
/** 对NDS03寄存器写N个字节,使用字方式 */
|
||||
NDS03_Error NDS03_WriteNBytesByWord(NDS03_Dev_t *pNxDevice,
|
||||
uint8_t addr, uint32_t *wdata, uint16_t size);
|
||||
/** 对NDS03寄存器读N个字节,使用字方式 */
|
||||
NDS03_Error NDS03_ReadNBytesByWord(NDS03_Dev_t *pNxDevice,
|
||||
uint8_t addr, uint32_t *rdata, uint16_t size);
|
||||
/** 对NDS03寄存器写1个字 */
|
||||
NDS03_Error NDS03_WriteWord(NDS03_Dev_t *pNxDevice, uint8_t addr, uint32_t wdata);
|
||||
/** 对NDS03寄存器读1个字 */
|
||||
NDS03_Error NDS03_ReadWord(NDS03_Dev_t *pNxDevice, uint8_t addr, uint32_t *rdata);
|
||||
/** 获取系统时钟时间(ms) */
|
||||
NDS03_Error NDS03_GetSystemClkMs(NDS03_Dev_t *pNxDevice,int32_t *time_ms);
|
||||
|
||||
/** @} NDS03_Communication_Group */
|
||||
|
||||
#endif
|
||||
238
drivers/iio/proximity/nds03/nds03_data.c
Normal file
238
drivers/iio/proximity/nds03/nds03_data.c
Normal file
@@ -0,0 +1,238 @@
|
||||
|
||||
/**
|
||||
* @file nds03_data.c
|
||||
* @author tongsheng.tang
|
||||
* @brief NDS03 get depth data functions
|
||||
* @version 2.x.x
|
||||
* @date 2025-06
|
||||
*
|
||||
* @copyright Copyright (c) 2025, Nephotonics Information Technology (Hefei) Co., Ltd.
|
||||
*
|
||||
* @license BSD 3-Clause License
|
||||
* This file is part of the NDS03 SDK and is licensed under the BSD 3-Clause License.
|
||||
* You may obtain a copy of the license in the project root directory,
|
||||
* in the file named LICENSE.
|
||||
*/
|
||||
|
||||
#include "nds03_def.h"
|
||||
#include "nds03_comm.h"
|
||||
#include "nds03_dev.h"
|
||||
#include "nds03_data.h"
|
||||
|
||||
/**
|
||||
* @brief NDS03 Get Ranging Data Ready
|
||||
* 检测NDS03测距是否完成
|
||||
* @param pNxDevice 模组设备
|
||||
* @return int8_t
|
||||
* @retval 函数执行结果
|
||||
* - 0:未完成
|
||||
* 1: 完成
|
||||
* - ::NDS03_ERROR_I2C:IIC通讯错误/数据异常
|
||||
*/
|
||||
NDS03_Error NDS03_GetRangingDataReady(NDS03_Dev_t *pNxDevice)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
uint8_t buf_valid_flag = 0x00;
|
||||
|
||||
CHECK_RET(NDS03_ReadByte(pNxDevice, NDS03_REG_DAT_VAL, &buf_valid_flag));
|
||||
|
||||
if (buf_valid_flag == NDS03_DEPTH_DATA_FLAG)
|
||||
return 1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Start Single Measurement
|
||||
* 发送开始单次测量信号
|
||||
* @param pNxDevice 模组设备
|
||||
* @return int8_t
|
||||
*/
|
||||
NDS03_Error NDS03_StartSingleMeasurement(NDS03_Dev_t *pNxDevice)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
/* 清除标志位 */
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_DAT_VAL, NDS03_DATA_VAL_IDLE));
|
||||
/* 发送触发信号 */
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_DAT_REQ, NDS03_DEPTH_DATA_FLAG));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Start Continuous Measurement
|
||||
* 发送开始连续测量信号
|
||||
* @param pNxDevice 模组设备
|
||||
* @return int8_t
|
||||
*/
|
||||
NDS03_Error NDS03_StartContinuousMeasurement(NDS03_Dev_t *pNxDevice)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
if (pNxDevice->config.continuous_flag == 0) {
|
||||
/* 清除标志位 */
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_DAT_VAL, NDS03_DATA_VAL_IDLE));
|
||||
/* 发送触发信号 */
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice,
|
||||
NDS03_REG_DAT_REQ, NDS03_DEPTH_CONTINUOUS_FLAG));
|
||||
pNxDevice->config.continuous_flag = 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Stop Continuous Measurement
|
||||
* 发送结束连续测量信号,用于连续模式
|
||||
* @param pNxDevice 模组设备
|
||||
* @return int8_t
|
||||
*/
|
||||
NDS03_Error NDS03_StopContinuousMeasurement(NDS03_Dev_t *pNxDevice)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
if (pNxDevice->config.continuous_flag != 0) {
|
||||
/* 清除标志位 */
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_DAT_REQ, NDS03_DATA_REQ_IDLE));
|
||||
/* 等待测量完成 */
|
||||
CHECK_RET(NDS03_WaitforDataVal(pNxDevice, NDS03_DEPTH_CONTINUOUS_FLAG, 200));
|
||||
/* 清除标志位 */
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_DAT_VAL, NDS03_DATA_VAL_IDLE));
|
||||
pNxDevice->config.continuous_flag = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Clear Data Valid Flag
|
||||
* 清除NDS03测量数据的有效位,取完一次数
|
||||
* 据做的操作,通知NDS03数据已读取
|
||||
* @param pNxDevice 模组设备
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_ClearDataValidFlag(NDS03_Dev_t *pNxDevice)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_DAT_VAL, NDS03_DATA_VAL_IDLE));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Read Ranging Data
|
||||
* 读取NDS03寄存器获取测量数据,数据更新于一次测距完成后
|
||||
* @param pNxDevice 模组设备
|
||||
* @return int32_t
|
||||
*/
|
||||
NDS03_Error NDS03_ReadRangingData(NDS03_Dev_t *pNxDevice)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
#if NDS03_TARGET_MAX_NUM == 1
|
||||
CHECK_RET(NDS03_ReadNBytesByHalfWord(pNxDevice,
|
||||
NDS03_REG_DEPTH, (uint16_t*)&pNxDevice->ranging_data[0],
|
||||
sizeof(pNxDevice->ranging_data[0])));
|
||||
#endif
|
||||
|
||||
#if NDS03_TARGET_MAX_NUM == 2
|
||||
CHECK_RET(NDS03_ReadNBytesByHalfWord(pNxDevice,
|
||||
NDS03_REG_DEPTH, (uint16_t*)&pNxDevice->ranging_data[0],
|
||||
2 * sizeof(pNxDevice->ranging_data[0])));
|
||||
#endif
|
||||
|
||||
#if NDS03_TARGET_MAX_NUM == 3
|
||||
CHECK_RET(NDS03_ReadNBytesByHalfWord(pNxDevice,
|
||||
NDS03_REG_DEPTH, (uint16_t*)&pNxDevice->ranging_data[0],
|
||||
3 * sizeof(pNxDevice->ranging_data[0])));
|
||||
#endif
|
||||
|
||||
#if NDS03_TARGET_MAX_NUM >= 4
|
||||
CHECK_RET(NDS03_ReadNBytesByHalfWord(pNxDevice,
|
||||
NDS03_REG_DEPTH, (uint16_t*)&pNxDevice->ranging_data[0],
|
||||
4 * sizeof(pNxDevice->ranging_data[0])));
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Get Continuous Ranging Data
|
||||
* 连续模式下,从NDS03中获取一次深度数据,
|
||||
* 需要与NDS03_StartContinuousMeasurement函数搭配
|
||||
* @param pNxDevice 模组设备
|
||||
* @param pData 获取到的深度和幅度数据
|
||||
* @return int32_t
|
||||
*/
|
||||
NDS03_Error NDS03_GetContinuousRangingData(NDS03_Dev_t *pNxDevice)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
uint8_t data_cnt;
|
||||
uint32_t retry_cnt = 20000;
|
||||
|
||||
/* 等待测量完成 */
|
||||
do {
|
||||
CHECK_RET(NDS03_ReadByte(pNxDevice, NDS03_REG_DATA_CNT, &data_cnt));
|
||||
CHECK_RET(NDS03_Delay10us(pNxDevice, 10));
|
||||
} while (data_cnt == pNxDevice->data_cnt && --retry_cnt);
|
||||
pNxDevice->data_cnt = data_cnt;
|
||||
if (retry_cnt != 0) {
|
||||
/* 读取测量数据 */
|
||||
CHECK_RET(NDS03_ReadRangingData(pNxDevice));
|
||||
/* 清除数据有效标志位 */
|
||||
CHECK_RET(NDS03_ClearDataValidFlag(pNxDevice));
|
||||
} else {
|
||||
ret = NDS03_ERROR_TIMEOUT;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Get Single Ranging Data
|
||||
* NDS03中获取一次深度数据
|
||||
*
|
||||
* @param pNxDevice 模组设备
|
||||
* @return int32_t
|
||||
*/
|
||||
NDS03_Error NDS03_GetSingleRangingData(NDS03_Dev_t *pNxDevice)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
int32_t timeout_ms = pNxDevice->config.range_frame_time_us / 1000;
|
||||
|
||||
/* 清除标志位 */
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_DAT_VAL, NDS03_DATA_VAL_IDLE));
|
||||
/* 发送触发信号 */
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_DAT_REQ, NDS03_DEPTH_DATA_FLAG));
|
||||
/* 等待测量完成 */
|
||||
timeout_ms = (timeout_ms < 200) ? 200 : timeout_ms;
|
||||
CHECK_RET(NDS03_WaitforDataVal(pNxDevice, NDS03_DEPTH_DATA_FLAG, timeout_ms));
|
||||
/* 读取测量数据 */
|
||||
CHECK_RET(NDS03_ReadRangingData(pNxDevice));
|
||||
/* 清除数据有效标志位 */
|
||||
CHECK_RET(NDS03_ClearDataValidFlag(pNxDevice));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Get Interrupt Ranging Data
|
||||
* NDS03中获取一次中断深度数据
|
||||
*
|
||||
* @param pNxDevice 模组设备
|
||||
* @return int32_t
|
||||
*/
|
||||
NDS03_Error NDS03_GetInterruptRangingData(NDS03_Dev_t *pNxDevice)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
/* 读取测量数据 */
|
||||
CHECK_RET(NDS03_ReadRangingData(pNxDevice));
|
||||
/* 清除数据有效标志位 */
|
||||
CHECK_RET(NDS03_ClearDataValidFlag(pNxDevice));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
46
drivers/iio/proximity/nds03/nds03_data.h
Normal file
46
drivers/iio/proximity/nds03/nds03_data.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* @file nds03_data.h
|
||||
* @author tongsheng.tang
|
||||
* @brief NDS03 communication and data handling functions
|
||||
* @version 2.x.x
|
||||
* @date 2025-06
|
||||
*
|
||||
* @copyright Copyright (c) 2025, Nephotonics Information Technology (Hefei) Co., Ltd.
|
||||
*
|
||||
* @license BSD 3-Clause License
|
||||
* This file is part of the NDS03 SDK and is licensed under the BSD 3-Clause License.
|
||||
* You may obtain a copy of the license in the project root directory,
|
||||
* in the file named LICENSE.
|
||||
*
|
||||
*/
|
||||
#ifndef __NDS03_DATA_H__
|
||||
#define __NDS03_DATA_H__
|
||||
|
||||
#include "nds03_def.h"
|
||||
/** @defgroup NDS03_Data_Group NDS03 Data Functions
|
||||
* @brief NDS03 Data Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** 检测NDS03测距是否完成 */
|
||||
NDS03_Error NDS03_GetRangingDataReady(NDS03_Dev_t *pNxDevice);
|
||||
/** 发送开始单次测量信号 */
|
||||
NDS03_Error NDS03_StartSingleMeasurement(NDS03_Dev_t *pNxDevice);
|
||||
/** 发送开始连续测量信号 */
|
||||
NDS03_Error NDS03_StartContinuousMeasurement(NDS03_Dev_t *pNxDevice);
|
||||
/** 发送结束连续测量信号 */
|
||||
NDS03_Error NDS03_StopContinuousMeasurement(NDS03_Dev_t *pNxDevice);
|
||||
/** 清除数据有效位 */
|
||||
NDS03_Error NDS03_ClearDataValidFlag(NDS03_Dev_t *pNxDevice);
|
||||
/** 读取深度和幅度值 */
|
||||
NDS03_Error NDS03_ReadRangingData(NDS03_Dev_t *pNxDevice);
|
||||
/** 获取连续测量深度和幅度值 */
|
||||
NDS03_Error NDS03_GetContinuousRangingData(NDS03_Dev_t *pNxDevice);
|
||||
/** 获取一次测量深度和幅度值 */
|
||||
NDS03_Error NDS03_GetSingleRangingData(NDS03_Dev_t *pNxDevice);
|
||||
/** 获取一次中断数据 */
|
||||
NDS03_Error NDS03_GetInterruptRangingData(NDS03_Dev_t *pNxDevice);
|
||||
|
||||
/** @} NDS03_Data_Group */
|
||||
|
||||
#endif // __NDS03_DATA_H__
|
||||
308
drivers/iio/proximity/nds03/nds03_def.h
Normal file
308
drivers/iio/proximity/nds03/nds03_def.h
Normal file
@@ -0,0 +1,308 @@
|
||||
/**
|
||||
* @file nds03_def.h
|
||||
* @author tongsheng.tang
|
||||
* @brief NDS03's Macro definition and data structure
|
||||
* @version 2.x.x
|
||||
* @date 2025-06
|
||||
*
|
||||
* @copyright Copyright (c) 2025, Nephotonics Information Technology (Hefei) Co., Ltd.
|
||||
*
|
||||
* @license BSD 3-Clause License
|
||||
* This file is part of the NDS03 SDK and is licensed under the BSD 3-Clause License.
|
||||
* You may obtain a copy of the license in the project root directory,
|
||||
* in the file named LICENSE.
|
||||
*
|
||||
*/
|
||||
#ifndef __NDS03_DEF_H__
|
||||
#define __NDS03_DEF_H__
|
||||
|
||||
#include "nds03_stdint.h"
|
||||
#if NDS03_PLATFORM == PLATFORM_LINUX_DRIVER
|
||||
#include <linux/kernel.h>
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#include "nds03_platform.h"
|
||||
|
||||
#ifndef DEBUG_INFO
|
||||
#define DEBUG_INFO 0 /** 调试信息打印开关 */
|
||||
#endif
|
||||
|
||||
#if NDS03_PLATFORM == PLATFORM_NOT_C51
|
||||
#include <stdio.h>
|
||||
#define NX_PRINTF(fmt, ...) do { if (DEBUG_INFO) printf(fmt, ##__VA_ARGS__); } while(0)
|
||||
|
||||
#elif NDS03_PLATFORM == PLATFORM_LINUX_DRIVER
|
||||
#include <linux/kernel.h>
|
||||
#define NX_PRINTF(fmt, args...) do { if (DEBUG_INFO) printk(fmt, ##args); } while(0)
|
||||
|
||||
#elif NDS03_PLATFORM == PLATFORM_C51
|
||||
#define NX_PRINTF(fmt, ...)
|
||||
|
||||
#else
|
||||
#define NX_PRINTF(fmt, ...)
|
||||
#endif
|
||||
|
||||
/** @defgroup NDS03_Global_Define_Group NDS03 Defines
|
||||
* @brief NDS03 Defines
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup NDS03_Reg_Group NDS03 Register Defines
|
||||
* @brief NDS03 Register Defines
|
||||
* @{
|
||||
*/
|
||||
#define NDS03_REG_DEV_ADDR (0x1E) /** 模组的设备地址 */
|
||||
|
||||
#define NDS03_REG_STATE (0x20) /** 模组运行状态寄存器 */
|
||||
#define NDS03_REG_DATA_CNT (0x21) /** 模组测距次数计数值 */
|
||||
#define NDS03_REG_FW_VER (0x24) /** 模组固件版本号寄存器 */
|
||||
|
||||
#define NDS03_REG_RANGE_STATE (0x28) /** 测距状态码 */
|
||||
#define NDS03_REG_CALIB_STATE (0x29) /** 标定状态码 */
|
||||
#define NDS03_REG_THERM (0x2A) /** 温度值 */
|
||||
#define NDS03_REG_AMBIENT (0x2C) /** 环境光值 */
|
||||
|
||||
#define NDS03_REG_DEPTH (0x30) /** 深度值 */
|
||||
#define NDS03_REG_CONFI (0x32) /** 置信度 */
|
||||
#define NDS03_REG_COUNT (0x34) /** 计数值 */
|
||||
#define NDS03_REG_CRATE (0x36) /** 计数率 */
|
||||
#define NDS03_REG_DEPTH2 (0x38) /** 深度值 */
|
||||
#define NDS03_REG_CONFI2 (0x3A) /** 置信度 */
|
||||
#define NDS03_REG_COUNT2 (0x3C) /** 计数值 */
|
||||
#define NDS03_REG_CRATE2 (0x3E) /** 计数率 */
|
||||
#define NDS03_REG_DEPTH3 (0x40) /** 深度值 */
|
||||
#define NDS03_REG_CONFI3 (0x42) /** 置信度 */
|
||||
#define NDS03_REG_COUNT3 (0x44) /** 计数值 */
|
||||
#define NDS03_REG_CRATE3 (0x46) /** 计数率 */
|
||||
#define NDS03_REG_DEPTH4 (0x48) /** 深度值 */
|
||||
#define NDS03_REG_CONFI4 (0x4A) /** 置信度 */
|
||||
#define NDS03_REG_COUNT4 (0x4C) /** 计数值 */
|
||||
#define NDS03_REG_CRATE4 (0x4E) /** 计数率 */
|
||||
|
||||
#define NDS03_REG_DAT_REQ (0x50) /** 获取深度请求寄存器 */
|
||||
#define NDS03_REG_DAT_VAL (0x51) /** 获取数据命令有效寄存器 */
|
||||
#define NDS03_REG_CMD_REQ (0x52) /** 命令请求寄存器 */
|
||||
#define NDS03_REG_CMD_VAL (0x53) /** 命令完成寄存器 */
|
||||
#define NDS03_REG_CMD_ENA (0x54) /** 命令使能寄存器 */
|
||||
#define NDS03_REG_CFG_ENA (0x55) /** 配置使能,该值为0xA5才能访问其他寄存器 */
|
||||
#define NDS03_REG_REF_HISTO_MAX (0x56) /** 参考直方图最大值 */
|
||||
|
||||
#define NDS03_REG_DEPTH_FLAG (0x64) /** 测距结果标志位 */
|
||||
#define NDS03_REG_SLEEP_TIME (0x66) /** 睡眠时间(ms) */
|
||||
#define NDS03_REG_PULSE_NUM (0x6C) /** 发光次数 */
|
||||
|
||||
#define NDS03_REG_DEPTH_TH_L (0x70) /** 深度低阈值 */
|
||||
#define NDS03_REG_DEPTH_TH_H (0x72) /** 深度高阈值 */
|
||||
#define NDS03_REG_GPIO1_FUNC (0x74) /** 中断功能/方式 */
|
||||
#define NDS03_REG_SLEEP_MODE (0x75) /** 睡眠方式 */
|
||||
#define NDS03_REG_CONFI_TH (0x76) /** 置信度阈值 */
|
||||
#define NDS03_REG_TARGET_NUM (0x77) /** 目标个数 */
|
||||
#define NDS03_REG_INV_TIME (0x7C) /** 测量间隔时间 */
|
||||
#define NDS03_REG_OFFSET_MM (0x90) /** offset 标定位置 */
|
||||
|
||||
#define NDS03_REG_XTALK_TH (0xB0) /** 串扰阈值 */
|
||||
#define NDS03_REG_XTALK (0xB2) /** 串扰值 */
|
||||
|
||||
#define NDS03_REG_DATA_SIZE (0x5C) /** 数据大小 */
|
||||
#define NDS03_REG_CACHE_SIZE (0x5D) /** 缓存大小 */
|
||||
#define NDS03_REG_CACHE_ADDR (0x5E) /** 缓存地址 */
|
||||
#define NDS03_REG_CACHE_DATA (0xC0) /** 缓存数据 */
|
||||
|
||||
/** @} NDS03_Reg_Group */
|
||||
|
||||
/** @defgroup NDS03_State_Group NDS03 Data Request Index
|
||||
* @brief NDS03 State (NDS03_REG_STATE)
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define NDS03_STATE_IDLE 0x00 /** 空闲状态 */
|
||||
#define NDS03_STATE_SOFT_READY 0xA5 /** 软件就绪状态 */
|
||||
#define NDS03_STATE_GOT_DEPTH 0xA6 /** 已获取深度状态 */
|
||||
|
||||
/** @} NDS03_State_Group */
|
||||
|
||||
/** @defgroup NDS03_Data_Val_Req_Idx_Group NDS03 Data Request Index
|
||||
* @brief NDS03 Data Request Mask (NDS03_REG_DAT_VAL_REQ)
|
||||
* @{
|
||||
*/
|
||||
/** DATA REQ */
|
||||
#define NDS03_DATA_REQ_IDLE 0x00 /** 无效数据命令标志位 */
|
||||
#define NDS03_DEPTH_DATA_FLAG 0x10 /** 获取深度数据标志 */
|
||||
#define NDS03_DEPTH_CONTINUOUS_FLAG 0x13 /** 连续获取深度数据标志 */
|
||||
#define NDS03_USER_DATA_FLAG 0x50 /** 读用户数据标志位 */
|
||||
#define NDS03_GET_MODEL_FLAG 0x51 /** 获取模组型号标志位 */
|
||||
#define NDS03_CMD_READ_HGM_DATA 0xC0 /** 读直方图数据标志位 */
|
||||
#define NDS03_CMD_READ_HGM_DATA_ENA 0x05 /** 读直方图数据使能标志位 */
|
||||
|
||||
/** DATA VAL */
|
||||
#define NDS03_DATA_VAL_IDLE 0x00 /** 无效数据标志位 */
|
||||
|
||||
/** CMD REQ */
|
||||
#define NDS03_CMD_OFFSET_CALIB 0x20 /** offset标定命令 */
|
||||
#define NDS03_CMD_XTALK_CALIB 0x24 /** xtalk标定 */
|
||||
#define NDS03_CMD_WRITE_USER_DATA 0x50 /** 写用户数据区域标志位 */
|
||||
|
||||
|
||||
/** CMD VAL */
|
||||
#define NDS03_CMD_VAL_IDLE 0x00 /** 无效命令标志位 */
|
||||
|
||||
/** CMD ENA */
|
||||
#define NDS03_CMD_WRITE_USER_DATA_ENA 0xAA /** 用户数据使能标志位 */
|
||||
#define NDS03_CMD_ENA_ENABLE 0xA5 /** 配置开启标志位 */
|
||||
#define NDS03_CMD_ENA_DISABLE 0x00 /** 配置关闭标志位 */
|
||||
|
||||
/** @} NDS03_Data_Val_Req_Idx_Group */
|
||||
|
||||
/** @defgroup NDS03_Sleep_Group NDS03 Sleep Group
|
||||
* @brief NDS03 Sleep (NDS03_REG_SLEEP_MODE)
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define NDS03_MANUAL_SLEEP_TIME_OUT_WEAK_UP 0xA5 /* 手动进入软件睡眠标志位,超时唤醒 */
|
||||
#define NDS03_MANUAL_SLEEP_MANUAL_WEAK_UP 0xA4 /* 手动进入软件睡眠标志位,手动唤醒 */
|
||||
// #define NDS03_AUTO_SLEEP_MANUAL_WEAK_UP 0xA3 /* 测量结束自动进入软件睡眠标志位,手动唤醒 */
|
||||
// #define NDS03_AUTO_SLEEP_TIME_OUT_WEAK_UP 0xA2 /* 测量结束自动进入软件睡眠标志位,超时唤醒 */
|
||||
|
||||
/** @} NDS03_Sleep_Group */
|
||||
|
||||
/** @enum NDS03_Status_e
|
||||
* @brief 定义NDS03状态宏
|
||||
*/
|
||||
typedef int8_t NDS03_Error;
|
||||
|
||||
/** @defgroup NDS03_Error_Group NDS03 Error Group
|
||||
* @brief NDS03 Error Group (NDS03_REG_ERROR_FLAG)
|
||||
* @{
|
||||
*/
|
||||
#define NDS03_ERROR_NONE 0 /** 成功 */
|
||||
#define NDS03_ERROR_API -1 /** api接口注册失败 */
|
||||
#define NDS03_ERROR_TIMEOUT -2 /** 超时错误 */
|
||||
#define NDS03_ERROR_I2C -3 /** IIC通讯错误 */
|
||||
#define NDS03_ERROR_BOOT -4 /** 模组启动错误 */
|
||||
#define NDS03_ERROR_CALIB -5 /** 标定失败错误 */
|
||||
#define NDS03_ERROR_INIT -6 /** 初始化失败 */
|
||||
#define NDS03_ERROR_RANGING -7 /** 测距出错 */
|
||||
#define NDS03_ERROR_UPGRADE_VER -8 /** 升级版本不对 */
|
||||
#define NDS03_ERROR_UPGRADE -9 /** 升级失败 */
|
||||
#define NDS03_ERROR_AMBIENT_HIGH -10 /** 标定时环境光强过大 */
|
||||
#define NDS03_ERROR_NO_NDS03 -11 /** 不是NDS03模组 */
|
||||
#define NDS03_ERROR_VCSEL_ERROR -12 /** VCSEL不亮 */
|
||||
#define NDS03_ERROR_OFFSET_ERROR -13 /** OFFSET 标定失败 */
|
||||
|
||||
/** @} NDS03_Error_Group */
|
||||
|
||||
/** @defgroup NDS03_Calib_State_Group NDS03 Calib State Group
|
||||
* @brief NDS03 Calib State Group (NDS03_REG_CALIB_STATE)
|
||||
* @{
|
||||
*/
|
||||
#define NDS03_CALIB_ERROR_NONE 0x00 /** 成功 */
|
||||
#define NDS03_CALIB_ERROR_XTALK_OVERFLOW 0x02 /** 串扰溢出 */
|
||||
#define NDS03_CALIB_ERROR_XTALK_EXCESSIVE 0x10 /** 串扰过大 */
|
||||
#define NDS03_CALIB_ERROR_OFFSET 0x20 /** offset标定后测距误差过大 */
|
||||
/** @} NDS03_Calib_State_Group */
|
||||
|
||||
/** @defgroup NDS03_GPIO1_Func_Group NDS03 GPIO1 Functions Define
|
||||
* @brief NDS03 GPIO1 Functions Define Group (NDS03_REG_GPIO1_FUNC)
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** REG_GPIO1_SETTING Mask */
|
||||
#define NDS03_GPIO1_FUNCTIONALITY_MASK 0x07 /** GPIO1功能配置掩码 */
|
||||
#define NDS03_GPIO1_POLARITY_MASK 0x08 /** 极性配置掩码 */
|
||||
|
||||
/** GPIO1 Functionality */
|
||||
typedef uint8_t NDS03_Gpio1Func_t;
|
||||
#define NDS03_GPIO1_FUNCTIONALITY_OFF ((NDS03_Gpio1Func_t)0x00) /** 无触发中断 */
|
||||
#define NDS03_GPIO1_THRESHOLD_LOW ((NDS03_Gpio1Func_t)0x01) /** 低深度触发中断 (value < NDS03_REG_DEPTH_TH_L) */
|
||||
#define NDS03_GPIO1_THRESHOLD_HIGH ((NDS03_Gpio1Func_t)0x02) /** 高深度触发中断 (value > NDS03_REG_DEPTH_TH_H) */
|
||||
#define NDS03_GPIO1_THRESHOLD_DOMAIN_OUT ((NDS03_Gpio1Func_t)0x03) /** 低深度或高深度触发中断 (value < NDS03_REG_DEPTH_TH_L 或 value > NDS03_REG_DEPTH_TH_H) */
|
||||
#define NDS03_GPIO1_NEW_MEASURE_READY ((NDS03_Gpio1Func_t)0x04) /** 新深度数据就绪中断 */
|
||||
|
||||
/** GPIO1 polarity */
|
||||
typedef uint8_t NDS03_Gpio1Polar_t;
|
||||
#define NDS03_GPIO1_POLARITY_LOW ((NDS03_Gpio1Polar_t)0x00) /** 负极性, 低电平有效 */
|
||||
#define NDS03_GPIO1_POLARITY_HIGH ((NDS03_Gpio1Polar_t)0x01) /** 正极性, 高电平有效 */
|
||||
|
||||
/** @} NDS03_GPIO1_Func_Group */
|
||||
|
||||
#define NDS03_TARGET_MAX_NUM 4
|
||||
#define NDS03_AMBIENT_TH 1000 /** 标定时环境光强阈值 */
|
||||
#define NDS03_OFFSET_DEPTH_ERROR_TH 10 /** OFFSET 标定深度误差阈值 */
|
||||
#define NDS03_OFFSET_REF_MAX_COUNT_TH 500 /** OFFSET 标定深度误差阈值 */
|
||||
#define NDS03_DEPTH_INVALID_VALUE 65300 /** 深度无效值 */
|
||||
|
||||
/** @enum NDS03_Status_e
|
||||
* @brief 定义NDS03状态宏
|
||||
*/
|
||||
typedef enum{
|
||||
NDS03_DISABLE = 0, ///< 关闭状态
|
||||
NDS03_ENABLE = 1 ///< 使能状态
|
||||
} NDS03_Status_e;
|
||||
|
||||
/**
|
||||
* @struct NDS03_RangingData_t
|
||||
*
|
||||
* @brief NDS03测量结果结构体 \n
|
||||
* 定义存储NDS03的深度、置信度信息
|
||||
*/
|
||||
typedef struct{
|
||||
uint16_t depth; ///< 测量距离
|
||||
uint16_t confi; ///< 测量置信度
|
||||
uint16_t count; ///< 计数值
|
||||
uint16_t crate; ///< 计数率
|
||||
} NDS03_RangingData_t;
|
||||
|
||||
|
||||
/**
|
||||
* @struct NDS03_ChipInfo_t
|
||||
*
|
||||
* @brief NDS03模组生产信息\n
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t fw_version; ///< NDS03固件版本
|
||||
} NDS03_ChipInfo_t;
|
||||
|
||||
/**
|
||||
* @struct NDS03_DevConfig_t
|
||||
*
|
||||
* @brief NDS03模组配置数据\n
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t range_frame_time_us; //< 模组取图帧间隔时间配置
|
||||
uint8_t continuous_flag; ///< 连续模式标志位
|
||||
uint8_t target_num; ///< 目标个数
|
||||
} NDS03_DevConfig_t;
|
||||
|
||||
/**
|
||||
* @struct NDS03_Dev_t
|
||||
*
|
||||
* @brief 设备类型结构体\n
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t dev_pwr_state; ///< 设备的当前状态, 就绪模式或者休眠模式
|
||||
NDS03_DevConfig_t config; ///< 模组配置信息
|
||||
NDS03_ChipInfo_t chip_info; ///< 模组设备信息
|
||||
uint8_t data_cnt; ///< 数据获取次数
|
||||
NDS03_RangingData_t ranging_data[NDS03_TARGET_MAX_NUM]; ///< 测距数据结果
|
||||
NDS03_Platform_t platform;
|
||||
} NDS03_Dev_t;
|
||||
|
||||
#define NDS03_DEFAULT_SLAVE_ADDR 0x5C
|
||||
|
||||
#if NDS03_PLATFORM == PLATFORM_C51
|
||||
#define CHECK_RET(func) \
|
||||
ret = func; \
|
||||
if(ret != NDS03_ERROR_NONE) \
|
||||
return ret;
|
||||
#else
|
||||
#define CHECK_RET(func) do { \
|
||||
ret = func; \
|
||||
if(ret != NDS03_ERROR_NONE) { \
|
||||
NX_PRINTF("%s I2c Error, ret: %d\r\n", #func, ret); \
|
||||
return ret; \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
743
drivers/iio/proximity/nds03/nds03_dev.c
Normal file
743
drivers/iio/proximity/nds03/nds03_dev.c
Normal file
@@ -0,0 +1,743 @@
|
||||
/**
|
||||
* @file nds03_dev.c
|
||||
* @author tongsheng.tang
|
||||
* @brief NDS03 device setting functions
|
||||
* @version 2.x.x
|
||||
* @date 2025-06
|
||||
*
|
||||
* @copyright Copyright (c) 2025, Nephotonics Information Technology (Hefei) Co., Ltd.
|
||||
*
|
||||
* @license BSD 3-Clause License
|
||||
* This file is part of the NDS03 SDK and is licensed under the BSD 3-Clause License.
|
||||
* You may obtain a copy of the license in the project root directory,
|
||||
* in the file named LICENSE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "nds03_dev.h"
|
||||
#include "nds03_def.h"
|
||||
#include "nds03_comm.h"
|
||||
|
||||
/** SDK主版本 */
|
||||
static uint8_t sdk_version_major = 2;
|
||||
/** SDK次版本 */
|
||||
static uint8_t sdk_version_minor = 0;
|
||||
/** SDK小版本 */
|
||||
static uint8_t sdk_version_patch = 3;
|
||||
|
||||
/**
|
||||
* @brief NDS03 Get SDK Version
|
||||
* 获取当前SDK的软件版本号
|
||||
* @return uint32_t
|
||||
* @retval 软件版本号
|
||||
*/
|
||||
uint32_t NDS03_GetSdkVersion(void)
|
||||
{
|
||||
return ((uint32_t)sdk_version_major << 16) +
|
||||
((uint32_t)sdk_version_minor << 8) + (uint32_t)sdk_version_patch;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Get Firmware Version
|
||||
* 获取NDS03模组固件版本号
|
||||
* @param pNxDevice
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_GetFirmwareVersion(NDS03_Dev_t *pNxDevice)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
CHECK_RET(NDS03_ReadWord(pNxDevice, NDS03_REG_FW_VER, &pNxDevice->chip_info.fw_version));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Get Therm
|
||||
* 获取NDS03的温度
|
||||
* @param pNxDevice
|
||||
* @param therm 温度,单位为0.1度
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_GetTherm(NDS03_Dev_t *pNxDevice, int16_t* therm)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
CHECK_RET(NDS03_ReadHalfWord(pNxDevice, NDS03_REG_THERM, (uint16_t*)therm));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Set Pulse Num
|
||||
* 设置发光次数
|
||||
* @param pNxDevice
|
||||
* @param pulse_num 发光次数
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_SetPulseNum(NDS03_Dev_t *pNxDevice, uint32_t pulse_num)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_CFG_ENA, NDS03_CMD_ENA_ENABLE));
|
||||
CHECK_RET(NDS03_WriteWord(pNxDevice, NDS03_REG_PULSE_NUM, pulse_num));
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_CFG_ENA, NDS03_CMD_ENA_DISABLE));
|
||||
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
* @brief NDS03 Get Pulse Num
|
||||
* 获取发光次数
|
||||
* @param pNxDevice
|
||||
* @param pulse_num 发光次数
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_GetPulseNum(NDS03_Dev_t *pNxDevice, uint32_t *pulse_num)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
CHECK_RET(NDS03_ReadWord(pNxDevice, NDS03_REG_PULSE_NUM, pulse_num));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Set Frame Time
|
||||
* 设置测量帧间隔时间(us)
|
||||
* @param pNxDevice
|
||||
* @param inv_time 测量帧间隔时间
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_SetFrameTime(NDS03_Dev_t *pNxDevice, uint32_t frame_time_us)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_CFG_ENA, NDS03_CMD_ENA_ENABLE));
|
||||
CHECK_RET(NDS03_WriteWord(pNxDevice, NDS03_REG_INV_TIME, frame_time_us));
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_CFG_ENA, NDS03_CMD_ENA_DISABLE));
|
||||
CHECK_RET(NDS03_ReadWord(pNxDevice, NDS03_REG_INV_TIME,
|
||||
&pNxDevice->config.range_frame_time_us));
|
||||
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
* @brief NDS03 Get Frame Time
|
||||
* 获取帧测量间隔时间(us)
|
||||
* @param pNxDevice
|
||||
* @param inv_time 测量间隔时间
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_GetFrameTime(NDS03_Dev_t *pNxDevice, uint32_t *frame_time_us)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
CHECK_RET(NDS03_ReadWord(pNxDevice, NDS03_REG_INV_TIME,
|
||||
&pNxDevice->config.range_frame_time_us));
|
||||
*frame_time_us = pNxDevice->config.range_frame_time_us;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Set Confidence threshold
|
||||
* 配置置信度阈值
|
||||
* @param pNxDevice
|
||||
* @param confi_th
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_SetConfiTh(NDS03_Dev_t *pNxDevice, uint8_t confi_th)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_CFG_ENA, NDS03_CMD_ENA_ENABLE));
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_CONFI_TH, confi_th));
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_CFG_ENA, NDS03_CMD_ENA_DISABLE));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Get Confidence threshold
|
||||
* 获取置信度阈值
|
||||
* @param pNxDevice
|
||||
* @param confi_th 置信度阈值
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_GetConfiTh(NDS03_Dev_t *pNxDevice, uint8_t *confi_th)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
CHECK_RET(NDS03_ReadByte(pNxDevice, NDS03_REG_CONFI_TH, confi_th));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Set Target Num
|
||||
* 配置目标个数
|
||||
* @param pNxDevice
|
||||
* @param num
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_SetTargetNum(NDS03_Dev_t *pNxDevice, uint8_t num)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
num = (num > NDS03_TARGET_MAX_NUM) ? NDS03_TARGET_MAX_NUM : num;
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_CFG_ENA, NDS03_CMD_ENA_ENABLE));
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_TARGET_NUM, num));
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_CFG_ENA, NDS03_CMD_ENA_DISABLE));
|
||||
pNxDevice->config.target_num = num;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Get Target Num
|
||||
* 获取目标个数
|
||||
* @param pNxDevice
|
||||
* @param num
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_GetTargetNum(NDS03_Dev_t *pNxDevice, uint8_t *num)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
CHECK_RET(NDS03_ReadByte(pNxDevice, NDS03_REG_TARGET_NUM, num));
|
||||
pNxDevice->config.target_num = *num;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Set Gpio1 Configuration
|
||||
* 设置中断引脚的功能配置
|
||||
* @param pNxDevice: NDS03模组设备信息结构体
|
||||
* @param functionality: 中断功能设置
|
||||
* NDS03_GPIO1_FUNCTIONALITY_OFF: 无功能(默认)
|
||||
* NDS03_GPIO1_THRESHOLD_LOW:比较功能,当深度小于低阈值时,GPIO输出有效电平
|
||||
* NDS03_GPIO1_THRESHOLD_HIGH:比较功能,当深度大于高阈值时,GPIO输出有效电平
|
||||
* NDS03_GPIO1_THRESHOLD_DOMAIN_OUT:比较功能,当深度小于低阈值或者大于高阈值时,GPIO输出有效电平
|
||||
* NDS03_GPIO1_NEW_MEASURE_READY:深度数据有效功能,当深度数据有效时,GPIO输出有效电平
|
||||
* @param polarity: INT引脚有效电平
|
||||
* NDS03_GPIO1_POLARITY_LOW:低电平有效
|
||||
* NDS03_GPIO1_POLARITY_HIGH:高电平有效
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_SetGpio1Config(NDS03_Dev_t *pNxDevice,
|
||||
NDS03_Gpio1Func_t functionality, NDS03_Gpio1Polar_t polarity)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
uint8_t rbuf;
|
||||
|
||||
CHECK_RET(NDS03_ReadByte(pNxDevice, NDS03_REG_GPIO1_FUNC, &rbuf));
|
||||
/** 设置中断功能 */
|
||||
rbuf = rbuf & (~NDS03_GPIO1_FUNCTIONALITY_MASK);
|
||||
rbuf = rbuf | (functionality & NDS03_GPIO1_FUNCTIONALITY_MASK);
|
||||
/** 设置中断引脚极性 */
|
||||
if (polarity == NDS03_GPIO1_POLARITY_HIGH)
|
||||
rbuf = rbuf | NDS03_GPIO1_POLARITY_MASK;
|
||||
else
|
||||
rbuf = rbuf & (~NDS03_GPIO1_POLARITY_MASK);
|
||||
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_CFG_ENA, NDS03_CMD_ENA_ENABLE));
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_GPIO1_FUNC, rbuf));
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_CFG_ENA, NDS03_CMD_ENA_DISABLE));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Get Gpio1 Config
|
||||
* 获取中断引脚的功能配置
|
||||
* @param pNxDevice: NDS03模组设备信息结构体指针
|
||||
* @param functionality: 获取到的中断功能变量指针
|
||||
* @param polarity: 获取到的中断引脚极性变量指针
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_GetGpio1Config(NDS03_Dev_t *pNxDevice,
|
||||
NDS03_Gpio1Func_t *functionality, NDS03_Gpio1Polar_t *polarity)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
uint8_t rbuf;
|
||||
|
||||
CHECK_RET(NDS03_ReadByte(pNxDevice, NDS03_REG_GPIO1_FUNC, &rbuf));
|
||||
// Polarity
|
||||
*polarity = ((rbuf & NDS03_GPIO1_POLARITY_MASK) == NDS03_GPIO1_POLARITY_MASK) ?
|
||||
NDS03_GPIO1_POLARITY_HIGH : NDS03_GPIO1_POLARITY_LOW;
|
||||
// Functionality
|
||||
*functionality = rbuf & NDS03_GPIO1_FUNCTIONALITY_MASK;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Set Depth Threshold
|
||||
* 设置深度阈值
|
||||
* 该功能仅用于GPIO功能为
|
||||
* NDS03_GPIO1_THRESHOLD_LOW
|
||||
* 或NDS03_GPIO1_THRESHOLD_HIGH
|
||||
* 或NDS03_GPIO1_THRESHOLD_DOMAIN_OUT
|
||||
* @param pNxDevice: NDS03模组设备信息结构体
|
||||
* @param depth_low: 低深度阈值 / mm
|
||||
* @param depth_high: 高深度阈值 / mm
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_SetDepthThreshold(NDS03_Dev_t *pNxDevice,
|
||||
uint16_t depth_low, uint16_t depth_high)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_CFG_ENA, NDS03_CMD_ENA_ENABLE));
|
||||
CHECK_RET(NDS03_WriteHalfWord(pNxDevice, NDS03_REG_DEPTH_TH_L, depth_low));
|
||||
CHECK_RET(NDS03_WriteHalfWord(pNxDevice, NDS03_REG_DEPTH_TH_H, depth_high));
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_CFG_ENA, NDS03_CMD_ENA_DISABLE));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Get Depth Threshold
|
||||
* 获取深度阈值
|
||||
* @param pNxDevice: NDS03模组设备信息结构体
|
||||
* @param depth_low: 低深度阈值 / mm
|
||||
* @param depth_high: 高深度阈值 / mm
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_GetDepthThreshold(NDS03_Dev_t *pNxDevice,
|
||||
uint16_t *depth_low, uint16_t *depth_high)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
CHECK_RET(NDS03_ReadHalfWord(pNxDevice, NDS03_REG_DEPTH_TH_L, depth_low));
|
||||
CHECK_RET(NDS03_ReadHalfWord(pNxDevice, NDS03_REG_DEPTH_TH_H, depth_high));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Waitfor Data Val
|
||||
* 等待数据完成
|
||||
* @param pNxDevice 模组设备
|
||||
* @param flag 读命令标志位
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_WaitforDataVal(NDS03_Dev_t *pNxDevice, uint8_t flag, int32_t timeout_ms)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
uint8_t dat_valid_flag = 0x00;
|
||||
int32_t retry_cnt;
|
||||
|
||||
retry_cnt = timeout_ms * 2;
|
||||
do {
|
||||
CHECK_RET(NDS03_ReadByte(pNxDevice, NDS03_REG_DAT_VAL, &dat_valid_flag));
|
||||
if (dat_valid_flag == flag)
|
||||
break;
|
||||
NDS03_Delay10us(pNxDevice, 50);
|
||||
} while (--retry_cnt);
|
||||
|
||||
if (retry_cnt == 0) {
|
||||
NX_PRINTF("data_valid_flag: %d\r\n", dat_valid_flag);
|
||||
ret = NDS03_ERROR_TIMEOUT;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Waitfor Cmd Val
|
||||
* 等待命令完成
|
||||
* @param pNxDevice 模组设备
|
||||
* @param cmd 命令
|
||||
* @param timeout_ms 超时时间
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_WaitforCmdVal(NDS03_Dev_t *pNxDevice, uint8_t cmd, int32_t timeout_ms)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
int32_t retry_cnt;
|
||||
uint8_t val;
|
||||
|
||||
retry_cnt = timeout_ms * 2;
|
||||
do {
|
||||
CHECK_RET(NDS03_ReadByte(pNxDevice, NDS03_REG_CMD_VAL, &val));
|
||||
if (val == cmd)
|
||||
break;
|
||||
|
||||
NDS03_Delay10us(pNxDevice, 50);
|
||||
} while (--retry_cnt);
|
||||
|
||||
if (retry_cnt == 0) {
|
||||
NX_PRINTF("Timeout!!, val: 0x%02x\r\n", val);
|
||||
ret = NDS03_ERROR_TIMEOUT;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Read Hgm Data
|
||||
* 读取NDS03直方图数据
|
||||
* @param pNxDevice 模组设备
|
||||
* @param rbuf 数据指针
|
||||
* @param size 数据大小
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_ReadHgmData(NDS03_Dev_t *pNxDevice, uint8_t *rbuf, uint32_t size)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
uint32_t rsize, _size;
|
||||
uint8_t one_size;
|
||||
uint16_t addr = 0xe000;
|
||||
|
||||
CHECK_RET(NDS03_ReadByte(pNxDevice, NDS03_REG_CACHE_SIZE, &one_size));
|
||||
_size = (uint32_t)one_size;
|
||||
rsize = 0;
|
||||
while ((rsize < size) && (ret == NDS03_ERROR_NONE)) {
|
||||
CHECK_RET(NDS03_WriteHalfWord(pNxDevice, NDS03_REG_CACHE_ADDR, addr));
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_CMD_ENA, 0x05));
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_DAT_REQ, 0xC0));
|
||||
CHECK_RET(NDS03_WaitforDataVal(pNxDevice, 0xC0, 200));
|
||||
CHECK_RET(NDS03_ReadNBytes(pNxDevice,
|
||||
NDS03_REG_CACHE_DATA, rbuf,
|
||||
((size - rsize) > _size) ? _size : (size - rsize)));
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_DAT_VAL, NDS03_DATA_VAL_IDLE));
|
||||
rbuf += _size;
|
||||
addr += _size;
|
||||
rsize += _size;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Read User Data
|
||||
* 读取NDS03中用户数据区域,支持任意地址循环读取,比如从0xFFF0开始读取32个字节,
|
||||
* 则前16个字节数据是0xFFF0~0xFFFF的数据,后16个字节是0x0000~0x000F的数据
|
||||
* @param pNxDevice 模组设备
|
||||
* @param addr 数据地址,0x0000~0xFFFF
|
||||
* @param rbuf 数据指针
|
||||
* @param size 数据大小
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_ReadUserData(NDS03_Dev_t *pNxDevice,
|
||||
uint16_t addr, uint8_t *rbuf, uint32_t size)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
uint32_t rsize, _size;
|
||||
uint8_t one_size;
|
||||
|
||||
CHECK_RET(NDS03_ReadByte(pNxDevice, NDS03_REG_CACHE_SIZE, &one_size));
|
||||
_size = (uint32_t)one_size;
|
||||
rsize = 0;
|
||||
while ((rsize < size) && (ret == NDS03_ERROR_NONE)) {
|
||||
CHECK_RET(NDS03_WriteHalfWord(pNxDevice, NDS03_REG_CACHE_ADDR, addr));
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_DAT_REQ, NDS03_USER_DATA_FLAG));
|
||||
CHECK_RET(NDS03_WaitforDataVal(pNxDevice, NDS03_USER_DATA_FLAG, 200));
|
||||
CHECK_RET(NDS03_ReadNBytes(pNxDevice, NDS03_REG_CACHE_DATA,
|
||||
rbuf, ((size - rsize) > _size) ? _size : (size - rsize)));
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_DAT_VAL, NDS03_DATA_VAL_IDLE));
|
||||
rbuf += _size;
|
||||
addr += _size;
|
||||
rsize += _size;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Read User Data
|
||||
* 写入NDS03中用户数据区域, 支持任意地址循环写入,比如从0xFFF0开始写入32个字节,
|
||||
* 则前16个字节数据是0xFFF0~0xFFFF的数据,后16个字节是0x0000~0x000F的数据
|
||||
* @param pNxDevice 模组设备
|
||||
* @param addr 数据地址,0x0000~0xFFFF
|
||||
* @param wbuf 数据指针
|
||||
* @param size 数据大小
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_WriteUserData(NDS03_Dev_t *pNxDevice,
|
||||
uint16_t addr, uint8_t *wbuf, uint32_t size)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
uint32_t rsize, _size;
|
||||
uint8_t one_size;
|
||||
|
||||
// NX_PRINTF("%s Start\r\n", __func__);
|
||||
CHECK_RET(NDS03_ReadByte(pNxDevice, NDS03_REG_CACHE_SIZE, &one_size));
|
||||
_size = (uint32_t)one_size;
|
||||
rsize = 0;
|
||||
while ((rsize < size) && (ret == NDS03_ERROR_NONE)) {
|
||||
CHECK_RET(NDS03_WriteNBytes(pNxDevice, NDS03_REG_CACHE_DATA,
|
||||
wbuf, ((size - rsize) > _size) ? _size : (size - rsize)));
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_DATA_SIZE,
|
||||
((size - rsize) > _size) ? _size : (size - rsize)));
|
||||
CHECK_RET(NDS03_WriteHalfWord(pNxDevice, NDS03_REG_CACHE_ADDR, addr));
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_CMD_ENA,
|
||||
NDS03_CMD_WRITE_USER_DATA_ENA));
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_CMD_REQ,
|
||||
NDS03_CMD_WRITE_USER_DATA));
|
||||
CHECK_RET(NDS03_WaitforCmdVal(pNxDevice, NDS03_CMD_WRITE_USER_DATA, 500));
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_CMD_VAL, NDS03_CMD_VAL_IDLE));
|
||||
wbuf += _size;
|
||||
addr += _size;
|
||||
rsize += _size;
|
||||
}
|
||||
// NX_PRINTF("%s End\r\n", __func__);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03软件休眠,定时自动唤醒
|
||||
*
|
||||
* @param pNxDevice 模组设备
|
||||
* @param sleep_time_ms 软件睡眠时间,达到时间后自动唤醒
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_SoftSleepWithAutoWakeup(NDS03_Dev_t *pNxDevice, uint16_t sleep_time_ms)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_CFG_ENA, NDS03_CMD_ENA_ENABLE));
|
||||
CHECK_RET(NDS03_WriteHalfWord(pNxDevice, NDS03_REG_SLEEP_TIME, sleep_time_ms));
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_SLEEP_MODE,
|
||||
NDS03_MANUAL_SLEEP_TIME_OUT_WEAK_UP));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03软件休眠,需要手动唤醒
|
||||
*
|
||||
* @param pNxDevice 模组设备
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_SoftSleepWithManualWakeup(NDS03_Dev_t *pNxDevice)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_CFG_ENA, NDS03_CMD_ENA_ENABLE));
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice,
|
||||
NDS03_REG_SLEEP_MODE, NDS03_MANUAL_SLEEP_MANUAL_WEAK_UP));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Sleep
|
||||
* NDS03进入休眠
|
||||
* @param pNxDevice 模组设备
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_Sleep(NDS03_Dev_t *pNxDevice)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
CHECK_RET(NDS03_SetXShutPinLevel(pNxDevice, 0));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Wakeup
|
||||
* NDS03从软件睡眠中唤醒
|
||||
* @param pNxDevice 模组设备
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_SoftWakeup(NDS03_Dev_t *pNxDevice)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
uint32_t freq;
|
||||
|
||||
CHECK_RET(NDS03_GetI2cFreq(pNxDevice,&freq));
|
||||
CHECK_RET(NDS03_SetI2cFreq(pNxDevice,1000));
|
||||
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_CFG_ENA, NDS03_CMD_ENA_ENABLE));
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_SLEEP_MODE, 0));
|
||||
|
||||
CHECK_RET(NDS03_SetI2cFreq(pNxDevice,freq));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Software Sleep
|
||||
* 软件睡眠
|
||||
* @param pNxDevice 模组设备
|
||||
* @param sleep_time_ms 软件睡眠时间,达到时间后自动唤醒
|
||||
* @return NDS03_Error
|
||||
* @deprecated 在以后的版本会弃用,请使用NDS03_SoftSleepWithAutoWakeup()
|
||||
*/
|
||||
static __maybe_unused NDS03_Error NDS03_SoftSleep(NDS03_Dev_t *pNxDevice, uint16_t sleep_time_ms)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
ret |= NDS03_WriteByte(pNxDevice, NDS03_REG_CFG_ENA, NDS03_CMD_ENA_ENABLE);
|
||||
ret |= NDS03_WriteHalfWord(pNxDevice, NDS03_REG_SLEEP_TIME, sleep_time_ms);
|
||||
ret |= NDS03_WriteByte(pNxDevice, NDS03_REG_SLEEP_MODE,
|
||||
NDS03_MANUAL_SLEEP_TIME_OUT_WEAK_UP);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Wakeup
|
||||
* NDS03从睡眠中唤醒
|
||||
* @param pNxDevice 模组设备
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_Wakeup(NDS03_Dev_t *pNxDevice)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
CHECK_RET(NDS03_SetXShutPinLevel(pNxDevice, 1));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 判断是否为NDS03
|
||||
*
|
||||
* @param pNxDevice
|
||||
* @return NDS03_Error
|
||||
* @arg 0: 是NDS03
|
||||
* @arg NDS03_ERROR_NO_NDS03: 不是NDS03
|
||||
* @arg others: 不确定是否为该模组,需要进一步排查,可能是I2C通信异常。
|
||||
* 如果排除I2C通信异常,则认为不是NDS03,可能是其他设备。
|
||||
*/
|
||||
NDS03_Error NDS03_IsNDS03(NDS03_Dev_t *pNxDevice)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
uint8_t buf[4] = {0};
|
||||
|
||||
NDS03_SetXShutPinLevel(pNxDevice, 1);
|
||||
CHECK_RET(NDS03_Delay1ms(pNxDevice, 10));
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_DAT_REQ, NDS03_GET_MODEL_FLAG));
|
||||
CHECK_RET(NDS03_WaitforDataVal(pNxDevice, NDS03_GET_MODEL_FLAG, 200));
|
||||
CHECK_RET(NDS03_ReadNBytes(pNxDevice, NDS03_REG_CACHE_DATA, buf, sizeof(buf)));
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_DAT_VAL, NDS03_DATA_VAL_IDLE));
|
||||
if ((buf[0] != 0x31) || (buf[1] != 0x53) || (buf[2] != 0x30) || (buf[3] != 0x33))
|
||||
ret = NDS03_ERROR_NO_NDS03;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Set Device Address
|
||||
* 设置模组设备地址
|
||||
* @param pNxDevice 模组设备
|
||||
* @param dev_addr
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_SetDevAddr(NDS03_Dev_t *pNxDevice, uint8_t dev_addr)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
CHECK_RET(NDS03_WriteByte(pNxDevice, NDS03_REG_DEV_ADDR, dev_addr));
|
||||
pNxDevice->platform.i2c_dev_addr = dev_addr;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 InitDevice
|
||||
* 初始化设备
|
||||
* @param pNxDevice 模组设备
|
||||
* @return NDS03_Error
|
||||
*/
|
||||
NDS03_Error NDS03_InitDevice(NDS03_Dev_t *pNxDevice)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
|
||||
// NX_PRINTF("%s Start!\r\n", __func__);
|
||||
|
||||
CHECK_RET(NDS03_GetFirmwareVersion(pNxDevice));
|
||||
CHECK_RET(NDS03_ReadByte(pNxDevice, NDS03_REG_DATA_CNT, &pNxDevice->data_cnt));
|
||||
CHECK_RET(NDS03_GetFrameTime(pNxDevice, &pNxDevice->config.range_frame_time_us));
|
||||
pNxDevice->config.continuous_flag = 0;
|
||||
|
||||
// NX_PRINTF("%s End!\r\n", __func__);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Wait for Device Boot Up
|
||||
* 等待NDS03模组启动
|
||||
* @param pNxDevice 模组设备
|
||||
* @return NDS03_ERROR_NONE:成功
|
||||
* NDS03_ERROR_BOOT:启动失败--请检测模组是否焊接好,还有i2c地址与读写函数是否错误。
|
||||
* NDS03_ERROR_FW:固件不兼容--请与FAE联系,是否模组的固件与SDK不兼容。
|
||||
*/
|
||||
NDS03_Error NDS03_WaitDeviceBootUp(NDS03_Dev_t *pNxDevice)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
int32_t try_times = 200;
|
||||
uint8_t slave_addr = pNxDevice->platform.i2c_dev_addr;
|
||||
|
||||
NDS03_SetXShutPinLevel(pNxDevice, 0);
|
||||
CHECK_RET(NDS03_Delay10us(pNxDevice, 20));
|
||||
NDS03_SetXShutPinLevel(pNxDevice, 1);
|
||||
CHECK_RET(NDS03_Delay1ms(pNxDevice, 2));
|
||||
ret = NDS03_SetXShutPinLevel(pNxDevice, 1);
|
||||
pNxDevice->platform.i2c_dev_addr = (ret == NDS03_ERROR_NONE) ?
|
||||
NDS03_DEFAULT_SLAVE_ADDR : pNxDevice->platform.i2c_dev_addr;
|
||||
|
||||
pNxDevice->data_cnt = 0;
|
||||
pNxDevice->config.continuous_flag = 0;
|
||||
|
||||
do {
|
||||
CHECK_RET(NDS03_Delay10us(pNxDevice, 10));
|
||||
CHECK_RET(NDS03_ReadByte(pNxDevice, NDS03_REG_STATE, &pNxDevice->dev_pwr_state));
|
||||
} while ((pNxDevice->dev_pwr_state != NDS03_STATE_SOFT_READY) &&
|
||||
(pNxDevice->dev_pwr_state != NDS03_STATE_GOT_DEPTH) && --try_times);
|
||||
|
||||
if (0 == try_times) {
|
||||
NX_PRINTF("state: 0x%02x\r\n", pNxDevice->dev_pwr_state);
|
||||
NX_PRINTF("NDS03 boot error\r\n");
|
||||
return NDS03_ERROR_BOOT;
|
||||
}
|
||||
|
||||
if (slave_addr != pNxDevice->platform.i2c_dev_addr)
|
||||
CHECK_RET(NDS03_SetDevAddr(pNxDevice, slave_addr));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NDS03 Dirty Warning
|
||||
* 脏污预警
|
||||
* @param pNxDevice 模组设备
|
||||
* @param flag 脏污预警标志位 1:脏污预警,0:正常
|
||||
* @param time_th 近距离时间阈值,单位ms
|
||||
* @return NDS03_ERROR_NONE:成功
|
||||
*/
|
||||
NDS03_Error NDS03_DirtyWarning(NDS03_Dev_t *pNxDevice,uint8_t *flag,uint32_t time_th)
|
||||
{
|
||||
NDS03_Error ret = NDS03_ERROR_NONE;
|
||||
uint16_t depth_low_th = 30;
|
||||
static int32_t depth_low_count = 0, depth_low_time_sta = 0, depth_low_time_end = 0;
|
||||
|
||||
if (time_th == 0)
|
||||
time_th = 10 * 1000;
|
||||
|
||||
if (pNxDevice->ranging_data[0].depth < depth_low_th) {
|
||||
depth_low_count ++;
|
||||
if (depth_low_count == 1)
|
||||
NDS03_GetSystemClkMs(pNxDevice, &depth_low_time_sta);
|
||||
|
||||
NDS03_GetSystemClkMs(pNxDevice, &depth_low_time_end);
|
||||
if (depth_low_time_end < depth_low_time_sta) {
|
||||
depth_low_time_sta = 0;
|
||||
depth_low_time_end = 0;
|
||||
}
|
||||
} else {
|
||||
depth_low_count = 0;
|
||||
depth_low_time_sta = 0;
|
||||
depth_low_time_end = 0;
|
||||
}
|
||||
|
||||
if (depth_low_count > 10 && pNxDevice->ranging_data[1].depth != NDS03_DEPTH_INVALID_VALUE)
|
||||
*flag = 1;
|
||||
|
||||
if ((depth_low_time_end - depth_low_time_sta) > time_th)
|
||||
*flag = 1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
94
drivers/iio/proximity/nds03/nds03_dev.h
Normal file
94
drivers/iio/proximity/nds03/nds03_dev.h
Normal file
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* @file nds03_dev.h
|
||||
* @author tongsheng.tang
|
||||
* @brief NDS03 device setting functions
|
||||
* @version 2.x.x
|
||||
* @date 2025-06
|
||||
*
|
||||
* @copyright Copyright (c) 2025, Nephotonics Information Technology (Hefei) Co., Ltd.
|
||||
*
|
||||
* @license BSD 3-Clause License
|
||||
* This file is part of the NDS03 SDK and is licensed under the BSD 3-Clause License.
|
||||
* You may obtain a copy of the license in the project root directory, in the file named LICENSE.
|
||||
*
|
||||
*/
|
||||
#ifndef __NDS03_DEV_H__
|
||||
#define __NDS03_DEV_H__
|
||||
|
||||
#include "nds03_def.h"
|
||||
|
||||
/** @defgroup NDS03_Dev_Group NDS03 Device Functions
|
||||
* @brief NDS03 Device Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** 获取SDK版本号 */
|
||||
uint32_t NDS03_GetSdkVersion(void);
|
||||
/** 获取NDS03模组固件版本号 */
|
||||
NDS03_Error NDS03_GetFirmwareVersion(NDS03_Dev_t *pNxDevice);
|
||||
/** 获取温度 */
|
||||
NDS03_Error NDS03_GetTherm(NDS03_Dev_t *pNxDevice, int16_t* therm);
|
||||
/** 设置发光次数 */
|
||||
NDS03_Error NDS03_SetPulseNum(NDS03_Dev_t *pNxDevice, uint32_t pulse_num);
|
||||
/** 获取发光次数 */
|
||||
NDS03_Error NDS03_GetPulseNum(NDS03_Dev_t *pNxDevice, uint32_t *pulse_num);
|
||||
/** 设置测量间隔时间 */
|
||||
NDS03_Error NDS03_SetFrameTime(NDS03_Dev_t *pNxDevice, uint32_t frame_time_us);
|
||||
/** 获取测量间隔时间 */
|
||||
NDS03_Error NDS03_GetFrameTime(NDS03_Dev_t *pNxDevice, uint32_t *frame_time_us);
|
||||
/** 设置置信度阈值 */
|
||||
NDS03_Error NDS03_SetConfiTh(NDS03_Dev_t *pNxDevice, uint8_t confi_th);
|
||||
/** 获取置信度阈值 */
|
||||
NDS03_Error NDS03_GetConfiTh(NDS03_Dev_t *pNxDevice, uint8_t *confi_th);
|
||||
/** 设置目标个数 */
|
||||
NDS03_Error NDS03_SetTargetNum(NDS03_Dev_t *pNxDevice, uint8_t num);
|
||||
/** 获取目标个数 */
|
||||
NDS03_Error NDS03_GetTargetNum(NDS03_Dev_t *pNxDevice, uint8_t *num);
|
||||
/** 设置中断引脚功能 */
|
||||
NDS03_Error NDS03_SetGpio1Config(NDS03_Dev_t *pNxDevice,
|
||||
NDS03_Gpio1Func_t functionality, NDS03_Gpio1Polar_t polarity);
|
||||
/** 获取中断引脚功能 */
|
||||
NDS03_Error NDS03_GetGpio1Config(NDS03_Dev_t *pNxDevice,
|
||||
NDS03_Gpio1Func_t *functionality, NDS03_Gpio1Polar_t *polarity);
|
||||
/** 设置深度阈值 */
|
||||
NDS03_Error NDS03_SetDepthThreshold(NDS03_Dev_t *pNxDevice,
|
||||
uint16_t depth_low, uint16_t depth_high);
|
||||
/** 获取深度阈值 */
|
||||
NDS03_Error NDS03_GetDepthThreshold(NDS03_Dev_t *pNxDevice,
|
||||
uint16_t *depth_low, uint16_t *depth_high);
|
||||
/** 等待获取数据结束 */
|
||||
NDS03_Error NDS03_WaitforDataVal(NDS03_Dev_t *pNxDevice, uint8_t flag, int32_t timeout_ms);
|
||||
/** 等待命令结束 */
|
||||
NDS03_Error NDS03_WaitforCmdVal(NDS03_Dev_t *pNxDevice, uint8_t cmd, int32_t timeout_ms);
|
||||
/** 从NDS03中读取直方图数据 */
|
||||
NDS03_Error NDS03_ReadHgmData(NDS03_Dev_t *pNxDevice,uint8_t *rbuf, uint32_t size);
|
||||
/** 从NDS03中读取用户数据 */
|
||||
NDS03_Error NDS03_ReadUserData(NDS03_Dev_t *pNxDevice, uint16_t addr, uint8_t *rbuf, uint32_t size);
|
||||
/** 从NDS03中写入用户数据 */
|
||||
NDS03_Error NDS03_WriteUserData(NDS03_Dev_t *pNxDevice,
|
||||
uint16_t addr, uint8_t *wbuf, uint32_t size);
|
||||
/** NDS03进入软件睡眠,手动唤醒 */
|
||||
NDS03_Error NDS03_SoftSleepWithManualWakeup(NDS03_Dev_t *pNxDevice);
|
||||
/** NDS03进入软件睡眠,自动唤醒 */
|
||||
NDS03_Error NDS03_SoftSleepWithAutoWakeup(NDS03_Dev_t *pNxDevice, uint16_t sleep_time_ms);
|
||||
/** NDS03从软件睡眠中唤醒 */
|
||||
NDS03_Error NDS03_SoftWakeup(NDS03_Dev_t *pNxDevice);
|
||||
/** NDS03进入睡眠 */
|
||||
NDS03_Error NDS03_Sleep(NDS03_Dev_t *pNxDevice);
|
||||
/** NDS03从睡眠中唤醒 */
|
||||
NDS03_Error NDS03_Wakeup(NDS03_Dev_t *pNxDevice);
|
||||
/** 判断是否为NDS03设备,返回值为0表示是NDS03设备 */
|
||||
NDS03_Error NDS03_IsNDS03(NDS03_Dev_t *pNxDevice);
|
||||
/** 设置模组设备地址 */
|
||||
NDS03_Error NDS03_SetDevAddr(NDS03_Dev_t *pNxDevice, uint8_t dev_addr);
|
||||
/** 初始化设备 */
|
||||
NDS03_Error NDS03_InitDevice(NDS03_Dev_t *pNxDevice);
|
||||
/** 等待设备启动 */
|
||||
NDS03_Error NDS03_WaitDeviceBootUp(NDS03_Dev_t *pNxDevice);
|
||||
/** 脏污预警 */
|
||||
NDS03_Error NDS03_DirtyWarning(NDS03_Dev_t *pNxDevice,uint8_t *flag,uint32_t time_th);
|
||||
|
||||
/** @} NDS03_Dev_Group */
|
||||
|
||||
#endif
|
||||
|
||||
235
drivers/iio/proximity/nds03/nds03_iio.c
Normal file
235
drivers/iio/proximity/nds03/nds03_iio.c
Normal file
@@ -0,0 +1,235 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/module.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/buffer.h>
|
||||
#include <linux/iio/kfifo_buf.h>
|
||||
#include <linux/ktime.h>
|
||||
#include "nds03_iio.h"
|
||||
#include "nds03.h"
|
||||
|
||||
#define NDS03_DISTANCE_CHANNEL { \
|
||||
.type = IIO_DISTANCE, \
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
|
||||
BIT(IIO_CHAN_INFO_SCALE) | \
|
||||
BIT(IIO_CHAN_INFO_ENABLE), \
|
||||
.info_mask_separate_available = BIT(IIO_CHAN_INFO_SCALE),\
|
||||
.scan_index = NDS03_IIO_CHAN_DISTANCE, \
|
||||
.scan_type = { \
|
||||
.sign = 'u', \
|
||||
.realbits = 16, \
|
||||
.storagebits = 16, \
|
||||
.endianness = IIO_LE, \
|
||||
}, \
|
||||
}
|
||||
|
||||
static const int nds03_scales[] = { 1 };
|
||||
|
||||
static const struct iio_chan_spec nds03_channels[] = {
|
||||
NDS03_DISTANCE_CHANNEL,
|
||||
IIO_CHAN_SOFT_TIMESTAMP(NDS03_IIO_CHAN_TIMESTAMP),
|
||||
};
|
||||
|
||||
static int nds03_read_avail(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
const int **vals, int *type, int *length,
|
||||
long mask)
|
||||
{
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
*type = IIO_VAL_INT;
|
||||
*vals = nds03_scales;
|
||||
*length = ARRAY_SIZE(nds03_scales);
|
||||
return IIO_AVAIL_LIST;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* === read_raw === */
|
||||
static int nds03_read_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int *val, int *val2, long mask)
|
||||
{
|
||||
struct nds03_iio_dev *iio = iio_device_get_drvdata(indio_dev);
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
if (chan->scan_index == NDS03_IIO_CHAN_DISTANCE) {
|
||||
*val = iio->ctx->g_nds03_device.ranging_data[0].depth;
|
||||
return IIO_VAL_INT;
|
||||
}
|
||||
break;
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
*val = nds03_scales[0];
|
||||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_ENABLE:
|
||||
*val = iio->enabled;
|
||||
return IIO_VAL_INT;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int nds03_write_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int val, int val2, long mask)
|
||||
{
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
return -EINVAL;
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
/* NOTE: Default to 1 */
|
||||
return 0;
|
||||
case IIO_CHAN_INFO_ENABLE:
|
||||
return -EINVAL;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct iio_info nds03_iio_info = {
|
||||
.read_raw = nds03_read_raw,
|
||||
.write_raw = nds03_write_raw,
|
||||
.read_avail= nds03_read_avail,
|
||||
};
|
||||
|
||||
/* === buffer setup === */
|
||||
static void nds03_enable_work(struct work_struct *work)
|
||||
{
|
||||
struct nds03_iio_dev *iio = container_of(work, struct nds03_iio_dev, enable_work);
|
||||
struct nds03_context *ctx = iio->ctx;
|
||||
NDS03_Dev_t *dev = &ctx->g_nds03_device;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ctx->work_mutex);
|
||||
if (iio->enabled)
|
||||
goto out;
|
||||
|
||||
schedule_delayed_work(&ctx->dwork,
|
||||
msecs_to_jiffies(atomic_read(&ctx->poll_delay_ms)));
|
||||
atomic_set(&ctx->is_meas, 1);
|
||||
ret = nds03_sensor_init(ctx);
|
||||
if(ret != 0) {
|
||||
dev_err(&ctx->client->dev, "nds03 sensor init failed %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
ret = NDS03_StartContinuousMeasurement(dev);
|
||||
if (ret) {
|
||||
dev_err(&ctx->client->dev, "StartContinuous fail %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
iio->enabled = true;
|
||||
dev_info(&ctx->client->dev, "NDS03 sensor started\n");
|
||||
goto out;
|
||||
|
||||
out:
|
||||
mutex_unlock(&ctx->work_mutex);
|
||||
}
|
||||
|
||||
static void nds03_disable_work(struct work_struct *work)
|
||||
{
|
||||
struct nds03_iio_dev *iio = container_of(work, struct nds03_iio_dev, disable_work);
|
||||
struct nds03_context *ctx = iio->ctx;
|
||||
NDS03_Dev_t *dev = &ctx->g_nds03_device;
|
||||
|
||||
mutex_lock(&ctx->work_mutex);
|
||||
if (!iio->enabled)
|
||||
goto out;
|
||||
|
||||
atomic_set(&ctx->is_meas, 0);
|
||||
NDS03_StopContinuousMeasurement(dev);
|
||||
iio->enabled = false;
|
||||
dev_info(&ctx->client->dev, "NDS03 sensor stopped\n");
|
||||
out:
|
||||
mutex_unlock(&ctx->work_mutex);
|
||||
}
|
||||
|
||||
static int nds03_buffer_preenable(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct nds03_iio_dev *iio = iio_device_get_drvdata(indio_dev);
|
||||
|
||||
schedule_work(&iio->enable_work);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nds03_buffer_predisable(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct nds03_iio_dev *iio = iio_device_get_drvdata(indio_dev);
|
||||
|
||||
schedule_work(&iio->disable_work);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct iio_buffer_setup_ops nds03_buffer_setup_ops = {
|
||||
.preenable = nds03_buffer_preenable,
|
||||
.predisable = nds03_buffer_predisable,
|
||||
};
|
||||
|
||||
int nds03_iio_init(struct nds03_context *ctx)
|
||||
{
|
||||
struct device *dev = &ctx->client->dev;
|
||||
struct nds03_iio_dev *iio;
|
||||
int ret;
|
||||
|
||||
iio = devm_kzalloc(dev, sizeof(*iio), GFP_KERNEL);
|
||||
if (!iio) {
|
||||
nds03_errmsg("devm_kzalloc error\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
iio->indio_dev = devm_iio_device_alloc(dev, 0);
|
||||
if (!iio->indio_dev) {
|
||||
nds03_errmsg("devm_iio_device_alloc error\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
iio->ctx = ctx;
|
||||
iio->enabled = false;
|
||||
INIT_WORK(&iio->enable_work, nds03_enable_work);
|
||||
INIT_WORK(&iio->disable_work, nds03_disable_work);
|
||||
|
||||
iio->indio_dev->name = "nds03";
|
||||
iio->indio_dev->channels = nds03_channels;
|
||||
iio->indio_dev->num_channels = ARRAY_SIZE(nds03_channels);
|
||||
iio->indio_dev->info = &nds03_iio_info;
|
||||
iio->indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;
|
||||
iio_device_set_drvdata(iio->indio_dev, iio);
|
||||
|
||||
/* kfifo buffer + setup_ops */
|
||||
ret = devm_iio_kfifo_buffer_setup(dev, iio->indio_dev, &nds03_buffer_setup_ops);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_iio_device_register(dev, iio->indio_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ctx->iio = iio;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nds03_iio_init);
|
||||
|
||||
void nds03_iio_remove(struct nds03_context *ctx)
|
||||
{
|
||||
return;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nds03_iio_remove);
|
||||
|
||||
void nds03_iio_push_data(struct nds03_context *ctx, uint16_t distance_mm)
|
||||
{
|
||||
struct nds03_iio_dev *iio = ctx->iio;
|
||||
struct nds03_scan scan;
|
||||
|
||||
if (!iio || !iio->enabled)
|
||||
return;
|
||||
|
||||
scan.distance = distance_mm;
|
||||
if (iio_buffer_enabled(iio->indio_dev))
|
||||
iio_push_to_buffers_with_timestamp(iio->indio_dev, &scan,
|
||||
ktime_get_boottime_ns());
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nds03_iio_push_data);
|
||||
31
drivers/iio/proximity/nds03/nds03_iio.h
Normal file
31
drivers/iio/proximity/nds03/nds03_iio.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __NDS03_IIO_H
|
||||
#define __NDS03_IIO_H
|
||||
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/buffer.h>
|
||||
#include <linux/iio/kfifo_buf.h>
|
||||
|
||||
struct nds03_iio_dev {
|
||||
struct iio_dev *indio_dev;
|
||||
struct nds03_context *ctx;
|
||||
bool enabled;
|
||||
struct work_struct enable_work;
|
||||
struct work_struct disable_work;
|
||||
};
|
||||
|
||||
enum nds03_iio_chan {
|
||||
NDS03_IIO_CHAN_DISTANCE,
|
||||
NDS03_IIO_CHAN_TIMESTAMP,
|
||||
};
|
||||
|
||||
struct nds03_scan {
|
||||
__le16 distance;
|
||||
s64 ts;
|
||||
};
|
||||
|
||||
int nds03_iio_init(struct nds03_context *ctx);
|
||||
void nds03_iio_remove(struct nds03_context *ctx);
|
||||
void nds03_iio_push_data(struct nds03_context *ctx, uint16_t distance_mm);
|
||||
|
||||
#endif
|
||||
674
drivers/iio/proximity/nds03/nds03_module.c
Normal file
674
drivers/iio/proximity/nds03/nds03_module.c
Normal file
@@ -0,0 +1,674 @@
|
||||
|
||||
/*!
|
||||
@file nds03_module.c
|
||||
@brief
|
||||
@author lull
|
||||
@date 2025-06
|
||||
@copyright Copyright (c) 2025 Shenzhen Nephotonics Semiconductor Technology Co., Ltd.
|
||||
@license BSD 3-Clause License
|
||||
This file is part of the Nephotonics sensor SDK.
|
||||
It is licensed under the BSD 3-Clause License.
|
||||
A copy of the license can be found in the project root directory, in the file named LICENSE.
|
||||
*/
|
||||
#include "nds03.h"
|
||||
#include "nds03_iio.h"
|
||||
|
||||
/* Set default value to 1 to allow to see module insertion debug messages */
|
||||
int nds03_enable_debug = 0;
|
||||
|
||||
static inline NDS03_Platform_t *to_nds03_platform(struct nds03_context *ctx)
|
||||
{
|
||||
return &ctx->g_nds03_device.platform;
|
||||
}
|
||||
static inline NDS03_Dev_t * to_nds03_dev(struct nds03_context *ctx)
|
||||
{
|
||||
return &ctx->g_nds03_device;
|
||||
}
|
||||
|
||||
int nds03_interrupt_config(NDS03_Dev_t *pNxDevice, uint8_t is_open)
|
||||
{
|
||||
int8_t retval = 0;
|
||||
|
||||
if (is_open) {
|
||||
retval |= NDS03_SetGpio1Config(pNxDevice,
|
||||
NDS03_GPIO1_NEW_MEASURE_READY, NDS03_GPIO1_POLARITY_LOW);
|
||||
/* 连续模式开启测量 */
|
||||
retval |= NDS03_StartContinuousMeasurement(pNxDevice);
|
||||
} else {
|
||||
/* 连续模式关闭测量 */
|
||||
retval |= NDS03_StopContinuousMeasurement(pNxDevice);
|
||||
/* 关闭测距中断 */
|
||||
retval |= NDS03_SetGpio1Config(pNxDevice,
|
||||
NDS03_GPIO1_FUNCTIONALITY_OFF, NDS03_GPIO1_POLARITY_LOW);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nds03_interrupt_config);
|
||||
|
||||
int nds03_sensor_init(struct nds03_context *ctx)
|
||||
{
|
||||
NDS03_Dev_t *pNxDevice = to_nds03_dev(ctx);
|
||||
|
||||
NDS03_Platform_t *pdev = to_nds03_platform(ctx);
|
||||
/* 函数指针结构体 */
|
||||
|
||||
if (NDS03_ERROR_NONE != nds03_platform_init(pdev, ctx->client)) {
|
||||
nds03_errmsg("nds03_platform init error\n");
|
||||
return -1;
|
||||
}
|
||||
/* 循环等待设备启动, 若模组或者IIC读写函数有问题则会报错 */
|
||||
if (NDS03_ERROR_NONE != NDS03_WaitDeviceBootUp(pNxDevice)) {
|
||||
nds03_errmsg("NDS03_WaitDeviceBootUp error\r\n");
|
||||
return -1;
|
||||
}
|
||||
/** 判断是否为NDS03设备 */
|
||||
if (NDS03_ERROR_NONE != NDS03_IsNDS03(pNxDevice)) {
|
||||
nds03_errmsg("The device is not NDS03, please change the device!\n");
|
||||
return -2;
|
||||
}
|
||||
/* 初始化模组设备 */
|
||||
if (NDS03_ERROR_NONE != NDS03_InitDevice(pNxDevice)) {
|
||||
nds03_errmsg("NDS03_InitDevice error!!\r\n");
|
||||
return -3;
|
||||
}
|
||||
if (atomic_read(&ctx->meas_mode) == 0)
|
||||
nds03_interrupt_config(pNxDevice, 1);
|
||||
else
|
||||
nds03_interrupt_config(pNxDevice, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nds03_sensor_init);
|
||||
|
||||
static void printf_ranging_data(NDS03_Dev_t *pNxDevice)
|
||||
{
|
||||
nds03_info("ranging data start:\r\n");
|
||||
|
||||
nds03_info("dist start:\r\n");
|
||||
nds03_info(
|
||||
"%d %d %d %d\r\n",
|
||||
pNxDevice->ranging_data[0].depth, pNxDevice->ranging_data[1].depth,
|
||||
pNxDevice->ranging_data[2].depth, pNxDevice->ranging_data[3].depth);
|
||||
nds03_info("dist end\r\n");
|
||||
|
||||
nds03_info("confi start:\r\n");
|
||||
nds03_info(
|
||||
"%d %d %d %d\r\n",
|
||||
pNxDevice->ranging_data[0].confi, pNxDevice->ranging_data[1].confi,
|
||||
pNxDevice->ranging_data[2].confi, pNxDevice->ranging_data[3].confi);
|
||||
nds03_info("confi end\r\n");
|
||||
|
||||
nds03_info("count start:\r\n");
|
||||
nds03_info(
|
||||
"%d %d %d %d\r\n",
|
||||
pNxDevice->ranging_data[0].count, pNxDevice->ranging_data[1].count,
|
||||
pNxDevice->ranging_data[2].count, pNxDevice->ranging_data[3].count);
|
||||
nds03_info("count end\r\n");
|
||||
|
||||
nds03_info("crate start:\r\n");
|
||||
nds03_info(
|
||||
"%d %d %d %d\r\n",
|
||||
pNxDevice->ranging_data[0].crate, pNxDevice->ranging_data[1].crate,
|
||||
pNxDevice->ranging_data[2].crate, pNxDevice->ranging_data[3].crate);
|
||||
nds03_info("crate end\r\n");
|
||||
|
||||
nds03_info("ranging data end\r\n");
|
||||
}
|
||||
|
||||
static int32_t nds03_make_measure(struct nds03_context *ctx)
|
||||
{
|
||||
int32_t ret = 0;
|
||||
NDS03_Dev_t *pNxDevice = &ctx->g_nds03_device;
|
||||
|
||||
mutex_lock(&ctx->work_mutex);
|
||||
/* 获取测量数据 */
|
||||
if (atomic_read(&ctx->meas_mode))
|
||||
ret = NDS03_GetSingleRangingData(pNxDevice);
|
||||
else
|
||||
ret = NDS03_GetInterruptRangingData(pNxDevice);
|
||||
|
||||
if (ret >= 0 && nds03_enable_debug)
|
||||
printf_ranging_data(pNxDevice);
|
||||
|
||||
mutex_unlock(&ctx->work_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __ctrl_tof_start(struct nds03_context * ctx)
|
||||
{
|
||||
schedule_delayed_work(&ctx->dwork,
|
||||
msecs_to_jiffies(atomic_read(&ctx->poll_delay_ms)));
|
||||
atomic_set(&ctx->is_meas, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __ctrl_tof_stop(struct nds03_context * ctx)
|
||||
{
|
||||
atomic_set(&ctx->is_meas, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __ctrl_tof_reset(struct nds03_context * ctx)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
__ctrl_tof_stop(ctx);
|
||||
mutex_lock(&ctx->work_mutex);
|
||||
ret = nds03_sensor_init(ctx);
|
||||
if (ret != 0)
|
||||
nds03_errmsg("nds03 sensor init failed\n");
|
||||
|
||||
mutex_unlock(&ctx->work_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int32_t tof_offset_calib(struct nds03_context *ctx, uint16_t calib_dist)
|
||||
{
|
||||
int32_t i, cnt = 20;
|
||||
int32_t depth_sum, depth_aver;
|
||||
NDS03_Dev_t *pNxDevice = to_nds03_dev(ctx);
|
||||
/* 将设备处于500mm处 */
|
||||
NDS03_StopContinuousMeasurement(pNxDevice);
|
||||
msleep(100);
|
||||
/* 串扰标定 */
|
||||
ctx->calib_result = NDS03_XtalkCalibration(pNxDevice);
|
||||
if (NDS03_ERROR_NONE != ctx->calib_result) {
|
||||
nds03_info("Xtalk calib error: %d\n", ctx->calib_result);
|
||||
return -1;
|
||||
}
|
||||
/* Offset标定 */
|
||||
ctx->calib_result = NDS03_OffsetCalibrationAtDepth(pNxDevice, calib_dist);
|
||||
if(NDS03_ERROR_NONE != ctx->calib_result) {
|
||||
nds03_info("Offset calib error: %d\n", ctx->calib_result);
|
||||
return -1;
|
||||
}
|
||||
/* 获取平均值 */
|
||||
NDS03_GetSingleRangingData(pNxDevice);
|
||||
NDS03_GetSingleRangingData(pNxDevice);
|
||||
depth_sum = 0;
|
||||
for (i = 0; i < cnt; i++) {
|
||||
if (NDS03_ERROR_NONE != NDS03_GetSingleRangingData(pNxDevice)) {
|
||||
nds03_info("NDS03_GetSingleRangingData error!!\r\n");
|
||||
return -1;
|
||||
}
|
||||
depth_sum = depth_sum + (int32_t)(uint32_t)pNxDevice->ranging_data[0].depth;
|
||||
}
|
||||
depth_aver = depth_sum / cnt;
|
||||
if (depth_aver < (calib_dist - 20) || depth_aver > (calib_dist + 20)) {
|
||||
ctx->calib_result = NDS03_ERROR_RANGING;
|
||||
nds03_info("NDS03 calibration fail!!\r\n");
|
||||
return -1;
|
||||
}
|
||||
nds03_info("NDS03 calibration success\r\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void report_meas_event(struct nds03_context * ctx)
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
retval = nds03_make_measure(ctx);
|
||||
if (retval < 0)
|
||||
return;
|
||||
|
||||
uint16_t distance = ctx->g_nds03_device.ranging_data[0].depth;
|
||||
nds03_iio_push_data(ctx, distance);
|
||||
}
|
||||
|
||||
static irqreturn_t tof_irq_handler_i2c(int vec, void *info)
|
||||
{
|
||||
struct nds03_context *ctx = (struct nds03_context *)info;
|
||||
bool is_meas = atomic_read(&ctx->is_meas);
|
||||
|
||||
if (ctx->irq == vec && is_meas)
|
||||
schedule_work(&ctx->irq_work);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void nds03_work_handler(struct work_struct *work)
|
||||
{
|
||||
struct nds03_context *ctx = container_of(work, struct nds03_context, dwork.work);
|
||||
|
||||
if (atomic_read(&ctx->meas_mode) && atomic_read(&ctx->is_meas)) {
|
||||
nds03_make_measure(ctx);
|
||||
schedule_delayed_work(&ctx->dwork,
|
||||
msecs_to_jiffies(atomic_read(&ctx->poll_delay_ms)));
|
||||
report_meas_event(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
static void nds03_measure_irq_work(struct work_struct *work)
|
||||
{
|
||||
struct nds03_context *ctx = container_of(work, struct nds03_context, irq_work);
|
||||
|
||||
report_meas_event(ctx);
|
||||
}
|
||||
|
||||
static ssize_t nds03_show_is_meas(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct nds03_context *ctx = dev_get_drvdata(dev);
|
||||
return snprintf(buf, 10, "%d\n", atomic_read(&ctx->is_meas));
|
||||
}
|
||||
|
||||
static ssize_t nds03_store_is_meas(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf,size_t count)
|
||||
{
|
||||
struct nds03_context *ctx = dev_get_drvdata(dev);
|
||||
int ret = count;
|
||||
|
||||
switch (buf[0]) {
|
||||
case '0':
|
||||
__ctrl_tof_stop(ctx);
|
||||
break;
|
||||
case '1':
|
||||
__ctrl_tof_start(ctx);
|
||||
break;
|
||||
default:
|
||||
nds03_warnmsg("Invalid value\n");
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
return ret ;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(is_meas, 0660, nds03_show_is_meas, nds03_store_is_meas);
|
||||
|
||||
static ssize_t nds03_show_poll_delay_ms(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
uint32_t poll_ms;
|
||||
struct nds03_context *ctx = dev_get_drvdata(dev);
|
||||
|
||||
poll_ms = atomic_read(&ctx->poll_delay_ms);
|
||||
return snprintf(buf, 10, "%d\n", poll_ms);
|
||||
}
|
||||
|
||||
static ssize_t nds03_store_poll_delay_ms(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf,size_t count)
|
||||
{
|
||||
struct nds03_context *ctx = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
unsigned long delay_ms;
|
||||
|
||||
ret = kstrtoul(buf, 10, &delay_ms);
|
||||
if(ret < 0) {
|
||||
nds03_warnmsg("Invalid input ctx\n");
|
||||
goto store_err;
|
||||
}
|
||||
atomic_set(&ctx->poll_delay_ms, delay_ms);
|
||||
nds03_dbgmsg("Poll delay %lu ms\n", delay_ms);
|
||||
store_err:
|
||||
return ret < 0 ? -EINVAL : count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(meas_delay_ms, 0660, nds03_show_poll_delay_ms, nds03_store_poll_delay_ms);
|
||||
|
||||
static ssize_t nds03_show_meas_mode(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct nds03_context *ctx = dev_get_drvdata(dev);
|
||||
|
||||
return snprintf(buf, 10, "%d\n",atomic_read(&ctx->meas_mode));
|
||||
}
|
||||
|
||||
static ssize_t nds03_store_meas_mode(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf,size_t count)
|
||||
{
|
||||
struct nds03_context *ctx = dev_get_drvdata(dev);
|
||||
NDS03_Dev_t *pNxDevice = to_nds03_dev(ctx);
|
||||
int ret = count;
|
||||
|
||||
mutex_lock(&ctx->work_mutex);
|
||||
switch (buf[0]) {
|
||||
case '0':
|
||||
if(ctx->irq < 0){
|
||||
nds03_warnmsg("No support Interrupt\n");
|
||||
ret = -EINVAL;
|
||||
} else {
|
||||
atomic_set(&ctx->meas_mode, 0);
|
||||
nds03_interrupt_config(pNxDevice, 1);
|
||||
nds03_dbgmsg("Enter Interrupt Mode\n");
|
||||
}
|
||||
break;
|
||||
case '1':
|
||||
atomic_set(&ctx->meas_mode, 1);
|
||||
nds03_interrupt_config(pNxDevice, 0);
|
||||
nds03_dbgmsg("Enter Poll Mode\n");
|
||||
break;
|
||||
default:
|
||||
nds03_warnmsg("Invalid value\n");
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&ctx->work_mutex);
|
||||
return ret ;
|
||||
}
|
||||
static DEVICE_ATTR(meas_mode, 0660, nds03_show_meas_mode, nds03_store_meas_mode);
|
||||
|
||||
static ssize_t nds03_store_tof_reset(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf,size_t count)
|
||||
{
|
||||
struct nds03_context *ctx = dev_get_drvdata(dev);
|
||||
int ret = 0;
|
||||
|
||||
if(buf[0] == '1')
|
||||
ret = __ctrl_tof_reset(ctx);
|
||||
|
||||
return ret < 0 ? ret : count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(tof_reset, 0660, NULL, nds03_store_tof_reset);
|
||||
|
||||
static ssize_t nds03_show_tof_calib(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct nds03_context *ctx = dev_get_drvdata(dev);
|
||||
|
||||
return snprintf(buf, 10, "%d\n",ctx->calib_result);
|
||||
}
|
||||
|
||||
static ssize_t nds03_store_tof_calib(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf,size_t count)
|
||||
{
|
||||
struct nds03_context *ctx = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
unsigned long calib_dis;
|
||||
|
||||
mutex_lock(&ctx->work_mutex);
|
||||
ret = kstrtoul(buf, 10, &calib_dis);
|
||||
if(ret < 0) {
|
||||
nds03_warnmsg("Invalid input ctx\n");
|
||||
ret = -EPERM;
|
||||
goto store_err;
|
||||
}
|
||||
nds03_info("offset calib distance: %ld mm\n", calib_dis);
|
||||
ret = tof_offset_calib(ctx, calib_dis);
|
||||
if (nds03_sensor_init(ctx) != 0)
|
||||
nds03_errmsg("nds03 sensor init failed\n");
|
||||
|
||||
store_err:
|
||||
mutex_unlock(&ctx->work_mutex);
|
||||
return ret < 0 ? ret : count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(tof_calib, 0660, nds03_show_tof_calib, nds03_store_tof_calib);
|
||||
|
||||
static ssize_t nds03_show_enable_debug(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, 10, "%d\n", nds03_enable_debug);
|
||||
}
|
||||
|
||||
static ssize_t nds03_store_enable_debug(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf,size_t count)
|
||||
{
|
||||
struct nds03_context *ctx = dev_get_drvdata(dev);
|
||||
int32_t ret = 0;
|
||||
|
||||
mutex_lock(&ctx->work_mutex);
|
||||
switch (buf[0]) {
|
||||
case '0':
|
||||
nds03_enable_debug = 0;
|
||||
nds03_info("close nds03 debug\n");
|
||||
break;
|
||||
case '1':
|
||||
nds03_enable_debug = 1;
|
||||
nds03_info("open nds03 debug\n");
|
||||
break;
|
||||
default:
|
||||
nds03_warnmsg("Invalid value\n");
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&ctx->work_mutex);
|
||||
return ret < 0 ? ret : count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(enable_debug, 0660, nds03_show_enable_debug, nds03_store_enable_debug);
|
||||
|
||||
static ssize_t nds03_store_tof_pulsenum(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf,size_t count)
|
||||
{
|
||||
int ret;
|
||||
unsigned long pulsenum;
|
||||
struct nds03_context *ctx = dev_get_drvdata(dev);
|
||||
NDS03_Dev_t *pdev = to_nds03_dev(ctx);
|
||||
|
||||
ret = kstrtoul(buf, 10, &pulsenum);
|
||||
if (ret < 0) {
|
||||
nds03_errmsg("Invalid input ctx\n");
|
||||
return -EPERM;
|
||||
}
|
||||
mutex_lock(&ctx->work_mutex);
|
||||
ret = NDS03_SetPulseNum(pdev, pulsenum);
|
||||
mutex_unlock(&ctx->work_mutex);
|
||||
nds03_info("set tof pulsenum: %ld, ret: %d\n", pulsenum, ret);
|
||||
return ret < 0 ? ret : count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(tof_pulsenum, 0660, NULL, nds03_store_tof_pulsenum);
|
||||
|
||||
static ssize_t nds03_show_tof_xtalk(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int ret, count;
|
||||
uint16_t xtalk_value;
|
||||
struct nds03_context *ctx = dev_get_drvdata(dev);
|
||||
NDS03_Dev_t *pdev = to_nds03_dev(ctx);
|
||||
|
||||
mutex_lock(&ctx->work_mutex);
|
||||
ret = NDS03_GetXTalkValue(pdev, &xtalk_value);
|
||||
if (ret < 0)
|
||||
nds03_errmsg("get tof xtalk_value error\n");
|
||||
mutex_unlock(&ctx->work_mutex);
|
||||
count = snprintf(buf, 10, "%d\n",xtalk_value);
|
||||
return ret < 0 ? ret : count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(tof_xtalk, 0660, nds03_show_tof_xtalk, NULL);
|
||||
|
||||
static ssize_t nds03_store_xtalk_calibration(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf,size_t count)
|
||||
{
|
||||
int32_t ret = 0;
|
||||
struct nds03_context *ctx = dev_get_drvdata(dev);
|
||||
NDS03_Dev_t *pdev = to_nds03_dev(ctx);
|
||||
|
||||
if (sysfs_streq(buf, "1") || sysfs_streq(buf, "on") ||
|
||||
sysfs_streq(buf, "start")) {
|
||||
mutex_lock(&ctx->work_mutex);
|
||||
NDS03_StopContinuousMeasurement(pdev);
|
||||
ret = NDS03_XtalkCalibration(pdev);
|
||||
if (nds03_sensor_init(ctx) != 0)
|
||||
nds03_errmsg("nds03 sensor init failed\n");
|
||||
|
||||
mutex_unlock(&ctx->work_mutex);
|
||||
if(ret < 0) {
|
||||
nds03_errmsg("NDS03_XtalkCalibration error, ret = %d\n", ret);
|
||||
return -EIO;
|
||||
}
|
||||
return count;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(xtalk_calibration, 0660, NULL, nds03_store_xtalk_calibration);
|
||||
|
||||
static ssize_t nds03_store_offset_calibration(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf,size_t count)
|
||||
{
|
||||
int ret;
|
||||
struct nds03_context *ctx = dev_get_drvdata(dev);
|
||||
NDS03_Dev_t *pdev = to_nds03_dev(ctx);
|
||||
int32_t calib_depth_mm_tmp = 0;
|
||||
|
||||
ret = kstrtoint(buf, 10, &calib_depth_mm_tmp);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&ctx->work_mutex);
|
||||
NDS03_StopContinuousMeasurement(pdev);
|
||||
ret = NDS03_OffsetCalibrationAtDepth(pdev, calib_depth_mm_tmp);
|
||||
if (nds03_sensor_init(ctx) != 0)
|
||||
nds03_errmsg("nds03 sensor init failed\n");
|
||||
|
||||
mutex_unlock(&ctx->work_mutex);
|
||||
if (ret < 0) {
|
||||
nds03_errmsg("NDS03_OffsetCalibrationAtDepth error, ret = %d\n", ret);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(offset_calibration, 0660, NULL, nds03_store_offset_calibration);
|
||||
|
||||
static struct attribute *nds03_attributes[] = {
|
||||
&dev_attr_is_meas.attr,
|
||||
&dev_attr_meas_delay_ms.attr,
|
||||
&dev_attr_meas_mode.attr,
|
||||
&dev_attr_enable_debug.attr,
|
||||
&dev_attr_tof_reset.attr,
|
||||
&dev_attr_tof_calib.attr,
|
||||
&dev_attr_tof_pulsenum.attr,
|
||||
&dev_attr_tof_xtalk.attr,
|
||||
&dev_attr_xtalk_calibration.attr,
|
||||
&dev_attr_offset_calibration.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group nds03_sysfs_groups = {
|
||||
.attrs = nds03_attributes,
|
||||
};
|
||||
|
||||
static void nds03_parse_device_tree(struct nds03_context *ctx)
|
||||
{
|
||||
int32_t ret;
|
||||
NDS03_Platform_t *pdev = to_nds03_platform(ctx);
|
||||
|
||||
/* Initialize xshut gpio */
|
||||
pdev->xshut_gpio = devm_gpiod_get_optional(&ctx->client->dev, "xshut", GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(pdev->xshut_gpio)) {
|
||||
ret = PTR_ERR(pdev->xshut_gpio);
|
||||
nds03_warnmsg( "no xshut pin available, error = %d\n", ret);
|
||||
return;
|
||||
} else {
|
||||
nds03_dbgmsg("get xshut pin success\n");
|
||||
}
|
||||
|
||||
/* Initialize irq gpio*/
|
||||
atomic_set(&ctx->meas_mode, 1); //Default to polling mode
|
||||
ctx->irq = -1;
|
||||
pdev->intr_gpio = devm_gpiod_get_optional(&ctx->client->dev, "intr", GPIOD_IN);
|
||||
if (IS_ERR(pdev->intr_gpio)) {
|
||||
ret = PTR_ERR(pdev->intr_gpio);
|
||||
nds03_warnmsg( "no intr pin available, error = %d\n", ret);
|
||||
return;
|
||||
}
|
||||
nds03_dbgmsg("get intr pin success\n");
|
||||
ctx->irq = ctx->client->irq;
|
||||
if (ctx->irq) {
|
||||
unsigned long default_trigger = irqd_get_trigger_type(irq_get_irq_data(ctx->irq));
|
||||
ret = devm_request_threaded_irq(&ctx->client->dev,
|
||||
ctx->irq, NULL,
|
||||
tof_irq_handler_i2c,
|
||||
default_trigger|IRQF_ONESHOT,
|
||||
"nds03_interrupt",
|
||||
(void *)ctx);
|
||||
if (ret) {
|
||||
nds03_errmsg("fail to req threaded irq rc=%d\n", ret);
|
||||
} else {
|
||||
nds03_info(
|
||||
"request irq success, irq mode use, irq num: %d, type: %lu",
|
||||
ctx->irq, default_trigger);
|
||||
atomic_set(&ctx->meas_mode, 0); //Configure in interrupt mode
|
||||
}
|
||||
} else {
|
||||
void *poll_interval_dt = NULL;
|
||||
uint32_t delay_ms;
|
||||
nds03_info("no irq number specified, polling mode is used\n");
|
||||
poll_interval_dt = (void *)of_get_property(ctx->client->dev.of_node,
|
||||
"nds03_poll_interval",
|
||||
NULL);
|
||||
delay_ms = poll_interval_dt ? be32_to_cpup(poll_interval_dt) : 0;
|
||||
|
||||
nds03_dbgmsg("poll delay ms:%d\n", delay_ms);
|
||||
|
||||
atomic_set(&ctx->poll_delay_ms, delay_ms);
|
||||
}
|
||||
}
|
||||
|
||||
int nds03_common_probe(struct nds03_context * ctx)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 i2c_freq = 0;
|
||||
// struct input_dev *input;
|
||||
|
||||
/* Initialize mutex */
|
||||
mutex_init(&ctx->work_mutex);
|
||||
|
||||
/* init work handler */
|
||||
INIT_DELAYED_WORK(&ctx->dwork, nds03_work_handler);
|
||||
|
||||
INIT_WORK(&ctx->irq_work, nds03_measure_irq_work);
|
||||
|
||||
atomic_set(&ctx->is_meas, 0);
|
||||
|
||||
/* Parse the device tree for NDS03 sensor configuration. */
|
||||
nds03_parse_device_tree(ctx);
|
||||
of_property_read_u32(ctx->client->adapter->dev.of_node, "clock-frequency", &i2c_freq);
|
||||
pr_info("I2C bus number is %d, bus speed: %u Hz\n", ctx->client->adapter->nr, i2c_freq);
|
||||
|
||||
ret = nds03_iio_init(ctx);
|
||||
if (ret) {
|
||||
nds03_errmsg("IIO init failed: %d\n", ret);
|
||||
goto err_iio;
|
||||
}
|
||||
ctx->fd_open_count = 0;
|
||||
|
||||
nds03_dbgmsg("create sysfs group successfully\n");
|
||||
|
||||
/* Initialize nds03 sensor */
|
||||
ret = nds03_sensor_init(ctx);
|
||||
if (ret != 0 ) {
|
||||
nds03_errmsg("Failed to init nds03 sensor error:%d\n", ret);
|
||||
goto err_iio;
|
||||
}
|
||||
nds03_dbgmsg("init nds03 sensor successfully\n");
|
||||
|
||||
ret = sysfs_create_group(&ctx->client->dev.kobj, &nds03_sysfs_groups);
|
||||
if (ret) {
|
||||
nds03_errmsg("Failed to create sysfs group error:%d\n", ret);
|
||||
goto exit_err;
|
||||
}
|
||||
ctx->remove_flag = false;
|
||||
nds03_dbgmsg("register chardev successfully\n");
|
||||
|
||||
nds03_info("nds03 module registered successfully\n");
|
||||
nds03_info( "NDS03 Driver version: %s \n", DRIVER_VERSION);
|
||||
return 0;
|
||||
|
||||
err_iio:
|
||||
nds03_iio_remove(ctx);
|
||||
|
||||
exit_err:
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nds03_common_probe);
|
||||
|
||||
int nds03_common_remove(struct nds03_context * ctx)
|
||||
{
|
||||
nds03_dbgmsg("Enter %s \n", __FUNCTION__);
|
||||
cancel_delayed_work(&ctx->dwork);
|
||||
ctx->remove_flag = true;
|
||||
sysfs_remove_group(&ctx->client->dev.kobj, &nds03_sysfs_groups);
|
||||
nds03_iio_remove(ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nds03_common_remove);
|
||||
99
drivers/iio/proximity/nds03/nds03_module_i2c.c
Normal file
99
drivers/iio/proximity/nds03/nds03_module_i2c.c
Normal file
@@ -0,0 +1,99 @@
|
||||
/*!
|
||||
@file nds03_module_i2c.c
|
||||
@brief
|
||||
@author lull
|
||||
@date 2025-06
|
||||
@copyright Copyright (c) 2025 Shenzhen Nephotonics Semiconductor Technology Co., Ltd.
|
||||
@license BSD 3-Clause License
|
||||
This file is part of the Nephotonics sensor SDK.
|
||||
It is licensed under the BSD 3-Clause License.
|
||||
A copy of the license can be found in the project root directory, in the file named LICENSE.
|
||||
*/
|
||||
#include "nds03.h"
|
||||
#include "nds03_platform.h"
|
||||
|
||||
struct nds03_context *nds03_context_obj = NULL;
|
||||
|
||||
// int nds03_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
static int nds03_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
{
|
||||
int ret = 0;
|
||||
struct device *dev = &client->dev;
|
||||
struct nds03_context * ctx = NULL;
|
||||
|
||||
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
|
||||
if(IS_ERR(ctx)) {
|
||||
nds03_errmsg("nds03_data memory allocation failed\n");
|
||||
ret = -ENOMEM;
|
||||
goto module_reg_err;
|
||||
}
|
||||
|
||||
nds03_context_obj = ctx;
|
||||
ctx->client = client;
|
||||
|
||||
ret = nds03_common_probe(ctx);
|
||||
if(ret != 0) {
|
||||
nds03_errmsg("Failed to register nds03 module: %d\n", ret);
|
||||
goto module_reg_err;
|
||||
}
|
||||
i2c_set_clientdata(client, ctx);
|
||||
return 0;
|
||||
|
||||
module_reg_err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void nds03_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
struct nds03_context * ctx = i2c_get_clientdata(client);
|
||||
nds03_common_remove(ctx);
|
||||
// return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id tof_nds03_id[] = {
|
||||
{TOF_NDS03_DRV_NAME, 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, tof_nds03_id);
|
||||
|
||||
static const struct of_device_id tof_nds03_dt_match[] = {
|
||||
{ .compatible = "nx,"TOF_NDS03_DRV_NAME, },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tof_nds03_dt_match);
|
||||
|
||||
static struct i2c_driver tof_nds03_driver = {
|
||||
.driver = {
|
||||
.name = TOF_NDS03_DRV_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = tof_nds03_dt_match,
|
||||
},
|
||||
.probe = nds03_i2c_probe,
|
||||
.remove = nds03_i2c_remove,
|
||||
.id_table = tof_nds03_id,
|
||||
|
||||
};
|
||||
|
||||
static int __init tof_nds03_init_i2c(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
nds03_dbgmsg("Enter\n");
|
||||
ret = i2c_add_driver(&tof_nds03_driver);
|
||||
if (ret)
|
||||
nds03_errmsg("%d erro ret:%d\n", __LINE__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit tof_nds03_exit_i2c(void )
|
||||
{
|
||||
nds03_dbgmsg("Exit\n");
|
||||
i2c_del_driver(&tof_nds03_driver);
|
||||
}
|
||||
|
||||
module_init(tof_nds03_init_i2c);
|
||||
module_exit(tof_nds03_exit_i2c);
|
||||
|
||||
MODULE_DESCRIPTION("Time-of-Flight sensor driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(DRIVER_VERSION);
|
||||
117
drivers/iio/proximity/nds03/nds03_platform.c
Normal file
117
drivers/iio/proximity/nds03/nds03_platform.c
Normal file
@@ -0,0 +1,117 @@
|
||||
/*!
|
||||
@file nds03_platform.c
|
||||
@brief
|
||||
@author lull
|
||||
@date 2025-06
|
||||
@copyright Copyright (c) 2025 Shenzhen Nephotonics Semiconductor Technology Co., Ltd.
|
||||
@license BSD 3-Clause License
|
||||
This file is part of the Nephotonics sensor SDK.
|
||||
It is licensed under the BSD 3-Clause License.
|
||||
A copy of the license can be found in the project root directory, in the file named LICENSE.
|
||||
*/
|
||||
#include "nds03_platform.h"
|
||||
|
||||
int8_t nds03_platform_init(NDS03_Platform_t *pdev, void * client)
|
||||
{
|
||||
pdev->client = (struct i2c_client *)client;
|
||||
pdev->i2c_dev_addr = 0X5C;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t nds03_platform_uninit(NDS03_Platform_t *pdev, void * param)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t nds03_i2c_read_nbytes(NDS03_Platform_t *pDev, uint8_t i2c_raddr, uint8_t *i2c_rdata, uint16_t len)
|
||||
{
|
||||
int8_t ret;
|
||||
struct i2c_msg i2c_message[2];
|
||||
uint8_t i2c_buf[256];
|
||||
|
||||
i2c_buf[0] = i2c_raddr;
|
||||
i2c_message[0].addr = pDev->i2c_dev_addr;
|
||||
i2c_message[0].buf = i2c_buf;
|
||||
i2c_message[0].len = 1;
|
||||
i2c_message[0].flags = 0 ; //| I2C_M_STOP;//I2C_M_STOP;
|
||||
|
||||
i2c_message[1].addr = pDev->i2c_dev_addr;
|
||||
i2c_message[1].buf = i2c_rdata;
|
||||
i2c_message[1].len = len;
|
||||
i2c_message[1].flags = I2C_M_RD;
|
||||
ret = i2c_transfer(pDev->client->adapter, i2c_message, 2);
|
||||
if (ret != 2) {
|
||||
pr_err("NDS03: i2c read error, i2c_raddr: 0x%x, reg: 0x%x, ret: %d", pDev->i2c_dev_addr, i2c_raddr, ret);
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int8_t nds03_i2c_write_nbytes(NDS03_Platform_t *pDev, uint8_t i2c_waddr, uint8_t *i2c_wdata, uint16_t len)
|
||||
{
|
||||
int32_t ret;
|
||||
struct i2c_msg i2c_message;
|
||||
//For user implement
|
||||
uint8_t i2c_buf[256];
|
||||
|
||||
memcpy(&i2c_buf[1], i2c_wdata, len);
|
||||
i2c_buf[0] = i2c_waddr;
|
||||
|
||||
i2c_message.addr = pDev->i2c_dev_addr;
|
||||
i2c_message.buf = i2c_buf;
|
||||
i2c_message.len = len + 1;
|
||||
i2c_message.flags = 0;
|
||||
ret = i2c_transfer(pDev->client->adapter, &i2c_message, 1);
|
||||
if (ret != 1) {
|
||||
pr_err("NDS03: i2c write error, i2c_waddr: 0x%x, reg: 0x%x, ret: %d", pDev->i2c_dev_addr, i2c_waddr, ret);
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int8_t nds03_delay_10us(NDS03_Platform_t *pDev, uint32_t wait_10us)
|
||||
{
|
||||
wait_10us *= 10;
|
||||
if (wait_10us < 10)
|
||||
udelay(wait_10us);
|
||||
else if (wait_10us < 20000)
|
||||
usleep_range(wait_10us, wait_10us + 1);
|
||||
else
|
||||
msleep(wait_10us / 1000);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t nds03_delay_1ms(NDS03_Platform_t *pDev, uint32_t wait_ms)
|
||||
{
|
||||
nds03_delay_10us(pDev, wait_ms * 100);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t nds03_set_xshut_pin_level(NDS03_Platform_t *pDev, int8_t level)
|
||||
{
|
||||
if (pDev->xshut_gpio == NULL) {
|
||||
pr_err("xshut_gpiod is not init , not setting xshut\n");
|
||||
return -1;
|
||||
}
|
||||
gpiod_set_value(pDev->xshut_gpio, level);
|
||||
// pr_info("xshut set to %d\n", level);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t nds03_i2c_get_clock_frequency(NDS03_Platform_t *pDev, uint32_t *clock_frequency)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t nds03_i2c_set_clock_frequency(NDS03_Platform_t *pDev, uint32_t clock_frequency)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t nds03_get_system_clk_ms(NDS03_Platform_t *pDev, int32_t *time_ms)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
137
drivers/iio/proximity/nds03/nds03_platform.h
Normal file
137
drivers/iio/proximity/nds03/nds03_platform.h
Normal file
@@ -0,0 +1,137 @@
|
||||
/*!
|
||||
@file nds03_platform.h
|
||||
@brief
|
||||
@author lull
|
||||
@date 2025-06
|
||||
@copyright Copyright (c) 2025 Shenzhen Nephotonics Semiconductor Technology Co., Ltd.
|
||||
@license BSD 3-Clause License
|
||||
This file is part of the Nephotonics sensor SDK.
|
||||
It is licensed under the BSD 3-Clause License.
|
||||
A copy of the license can be found in the project root directory, in the file named LICENSE.
|
||||
*/
|
||||
#ifndef __NDS03_PLATFORM__H__
|
||||
#define __NDS03_PLATFORM__H__
|
||||
|
||||
#include "nds03_stdint.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio.h>
|
||||
/**
|
||||
* @struct NDS03_Platform_t
|
||||
*
|
||||
* @brief NDS03平台相关定义 \n
|
||||
* 定义i2c地址等,注意必须定义i2c地址
|
||||
*/
|
||||
typedef struct{
|
||||
//文件描述符
|
||||
int fd;
|
||||
/** 用户不可更改以下变量 @{ */
|
||||
uint8_t i2c_dev_addr; // i2c设备地址
|
||||
/** @} */
|
||||
/** 用户可根据需要添加变量 */
|
||||
struct i2c_client *client;
|
||||
////// /* nds03 device io */
|
||||
struct gpio_desc *intr_gpio;
|
||||
/*!< xsdn reset (low active) gpio number to device */
|
||||
struct gpio_desc *xshut_gpio;
|
||||
|
||||
} NDS03_Platform_t;
|
||||
|
||||
/**
|
||||
* @brief NDS03平台初始化
|
||||
*
|
||||
* @param pDev 平台设备指针
|
||||
* @param void* 拓展指针
|
||||
* @return int8_t
|
||||
* @retval 0:成功, 其他:失败
|
||||
*/
|
||||
int8_t nds03_platform_init(NDS03_Platform_t *pdev, void *);
|
||||
|
||||
/**
|
||||
* @brief NDS03平台释放
|
||||
*
|
||||
* @param pDev 平台设备指针
|
||||
* @param void* 拓展指针
|
||||
* @return int8_t
|
||||
* @retval 0:成功, 其他:失败
|
||||
*/
|
||||
int8_t nds03_platform_uninit(NDS03_Platform_t *pdev, void *);
|
||||
|
||||
/**
|
||||
* @brief I2C读一个字节
|
||||
*
|
||||
* @param pDev 平台设备指针
|
||||
* @param i2c_raddr 读寄存器地址
|
||||
* @param i2c_rdata 读数据
|
||||
* @return int8_t
|
||||
* @retval 0:成功, 其他:失败
|
||||
*/
|
||||
int8_t nds03_i2c_read_nbytes(NDS03_Platform_t *pDev, uint8_t i2c_raddr, uint8_t *i2c_rdata, uint16_t len);
|
||||
|
||||
/**
|
||||
* @brief I2C写一个字节
|
||||
*
|
||||
* @param pDev 平台设备指针
|
||||
* @param i2c_waddr 写寄存器地址
|
||||
* @param i2c_wdata 写数据
|
||||
* @return int8_t
|
||||
* @retval 0:成功, 其他:失败
|
||||
*/
|
||||
int8_t nds03_i2c_write_nbytes(NDS03_Platform_t *pDev, uint8_t i2c_waddr, uint8_t *i2c_wdata, uint16_t len);
|
||||
|
||||
/**
|
||||
* @brief 延时wait_ms毫秒
|
||||
*
|
||||
* @param pDev 平台设备指针
|
||||
* @param wait_ms 输入需要延时时长
|
||||
* @return int8_t
|
||||
* @retval 0:成功, 其他:失败
|
||||
*/
|
||||
int8_t nds03_delay_1ms(NDS03_Platform_t *pDev, uint32_t wait_ms);
|
||||
|
||||
/**
|
||||
* @brief 延时10*wait_10us微秒
|
||||
*
|
||||
* @param pDev 平台设备指针
|
||||
* @param wait_10us 输入需要延时时长
|
||||
* @return int8_t
|
||||
* @retval 0:成功, 其他:失败
|
||||
*/
|
||||
int8_t nds03_delay_10us(NDS03_Platform_t *pDev, uint32_t wait_10us);
|
||||
|
||||
/**
|
||||
* @brief 设置nds03 xshut引脚电平
|
||||
*
|
||||
* @param pDev 平台设备指针
|
||||
* @param level 引脚电平,0为低电平,1为高电平
|
||||
* @return int8_t
|
||||
* @retval 0:成功, 其他:失败
|
||||
*/
|
||||
int8_t nds03_set_xshut_pin_level(NDS03_Platform_t *pDev, int8_t level);
|
||||
|
||||
/*!
|
||||
@brief NDS03获取当前i2c时钟频率
|
||||
@param pDev 平台设备指针
|
||||
@param clock_frequency 时钟频率指针
|
||||
@return int8_t
|
||||
*/
|
||||
int8_t nds03_i2c_get_clock_frequency(NDS03_Platform_t *pDev, uint32_t *clock_frequency);
|
||||
|
||||
/*!
|
||||
@brief NDS03设置当前i2c时钟频率
|
||||
@param pDev 平台设备指针
|
||||
@param clock_frequency 时钟频率指针
|
||||
@return int8_t
|
||||
*/
|
||||
int8_t nds03_i2c_set_clock_frequency(NDS03_Platform_t *pDev, uint32_t clock_frequency);
|
||||
/*!
|
||||
@brief 获取当前系统时间,单位ms
|
||||
@param pDev
|
||||
@param time_ms
|
||||
@return int8_t
|
||||
*/
|
||||
int8_t nds03_get_system_clk_ms(NDS03_Platform_t *pDev, int32_t *time_ms);
|
||||
|
||||
#endif
|
||||
|
||||
95
drivers/iio/proximity/nds03/nds03_stdint.h
Normal file
95
drivers/iio/proximity/nds03/nds03_stdint.h
Normal file
@@ -0,0 +1,95 @@
|
||||
|
||||
/**
|
||||
* @file nds03_stdint.h
|
||||
* @author tongsheng.tang
|
||||
* @brief NDS03 platform-specific integer type definitions
|
||||
* @version 2.x.x
|
||||
* @date 2025-06
|
||||
*
|
||||
* @copyright Copyright (c) 2025, Nephotonics Information Technology (Hefei) Co., Ltd.
|
||||
*
|
||||
* @license BSD 3-Clause License
|
||||
* This file is part of the NDS03 SDK and is licensed under the BSD 3-Clause License.
|
||||
* You may obtain a copy of the license in the project root directory, in the file named LICENSE.
|
||||
*
|
||||
*/
|
||||
#ifndef __NDS03_STDINT_H__
|
||||
#define __NDS03_STDINT_H__
|
||||
|
||||
#define PLATFORM_C51 0
|
||||
#define PLATFORM_NOT_C51 1
|
||||
#define PLATFORM_LINUX_DRIVER 2
|
||||
#ifndef NDS03_PLATFORM
|
||||
#define NDS03_PLATFORM PLATFORM_LINUX_DRIVER
|
||||
#endif
|
||||
|
||||
#if NDS03_PLATFORM == PLATFORM_NOT_C51
|
||||
#include <stdint.h>
|
||||
|
||||
#elif NDS03_PLATFORM == PLATFORM_C51
|
||||
/* exact-width signed integer types */
|
||||
typedef signed char int8_t;
|
||||
typedef signed int int16_t;
|
||||
typedef signed long int32_t;
|
||||
|
||||
/* exact-width unsigned integer types */
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned int uint16_t;
|
||||
typedef unsigned long uint32_t;
|
||||
|
||||
#define __func__ __FILE__
|
||||
|
||||
/* minimum values of exact-width signed integer types */
|
||||
#define INT32_MIN (~0x7fffffff) /* -2147483648 is unsigned */
|
||||
|
||||
/* maximum values of exact-width signed integer types */
|
||||
#define INT32_MAX 2147483647
|
||||
|
||||
/* maximum values of exact-width unsigned integer types */
|
||||
#define UINT32_MAX 4294967295u
|
||||
|
||||
/* 7.18.2.2 */
|
||||
|
||||
/* minimum values of minimum-width signed integer types */
|
||||
#define INT_LEAST32_MIN (~0x7fffffff)
|
||||
|
||||
/* maximum values of minimum-width signed integer types */
|
||||
#define INT_LEAST32_MAX 2147483647
|
||||
|
||||
/* maximum values of minimum-width unsigned integer types */
|
||||
#define UINT_LEAST32_MAX 4294967295u
|
||||
|
||||
/* 7.18.2.3 */
|
||||
|
||||
/* minimum values of fastest minimum-width signed integer types */
|
||||
#define INT_FAST32_MIN (~0x7fffffff)
|
||||
|
||||
/* maximum values of fastest minimum-width signed integer types */
|
||||
#define INT_FAST32_MAX 2147483647
|
||||
|
||||
/* maximum values of fastest minimum-width unsigned integer types */
|
||||
#define UINT_FAST32_MAX 4294967295u
|
||||
#elif NDS03_PLATFORM == PLATFORM_LINUX_DRIVER
|
||||
/* exact-width signed integer types */
|
||||
typedef signed char int8_t;
|
||||
typedef signed short int16_t;
|
||||
typedef signed int int32_t;
|
||||
|
||||
/* exact-width unsigned integer types */
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
|
||||
#define __func__ __FILE__
|
||||
|
||||
/* minimum values of exact-width signed integer types */
|
||||
#define INT32_MIN (~0x7fffffff) /* -2147483648 is unsigned */
|
||||
/* maximum values of exact-width signed integer types */
|
||||
#define INT32_MAX 2147483647
|
||||
|
||||
/* maximum values of exact-width unsigned integer types */
|
||||
#define UINT32_MAX 4294967295u
|
||||
#endif
|
||||
|
||||
#endif /** __NDS03_STDINT_H__ */
|
||||
|
||||
Reference in New Issue
Block a user