drivers/sensor: add support to IIS2DLPC accelerometer sensor
The IIS2DLPC is a 3D digital accelerometer ultra-low power sensor for industrial applications, which can be interfaced through either I2C or SPI bus. https://www.st.com/resource/en/datasheet/iis2dlpc.pdf This driver is based on stmemsc i/f v1.02 Signed-off-by: Armando Visconti <armando.visconti@st.com>
This commit is contained in:
parent
8da8b5c933
commit
e13205b256
14 changed files with 1320 additions and 0 deletions
|
@ -25,6 +25,7 @@ add_subdirectory_ifdef(CONFIG_TI_HDC ti_hdc)
|
|||
add_subdirectory_ifdef(CONFIG_HMC5883L hmc5883l)
|
||||
add_subdirectory_ifdef(CONFIG_HP206C hp206c)
|
||||
add_subdirectory_ifdef(CONFIG_HTS221 hts221)
|
||||
add_subdirectory_ifdef(CONFIG_IIS2DLPC iis2dlpc)
|
||||
add_subdirectory_ifdef(CONFIG_IIS3DHHC iis3dhhc)
|
||||
add_subdirectory_ifdef(CONFIG_ISL29035 isl29035)
|
||||
add_subdirectory_ifdef(CONFIG_LIS2DH lis2dh)
|
||||
|
|
|
@ -79,6 +79,8 @@ source "drivers/sensor/hp206c/Kconfig"
|
|||
|
||||
source "drivers/sensor/hts221/Kconfig"
|
||||
|
||||
source "drivers/sensor/iis2dlpc/Kconfig"
|
||||
|
||||
source "drivers/sensor/iis3dhhc/Kconfig"
|
||||
|
||||
source "drivers/sensor/isl29035/Kconfig"
|
||||
|
|
12
drivers/sensor/iis2dlpc/CMakeLists.txt
Normal file
12
drivers/sensor/iis2dlpc/CMakeLists.txt
Normal file
|
@ -0,0 +1,12 @@
|
|||
# ST Microelectronics IIS2DLPC 3-axis accelerometer driver
|
||||
#
|
||||
# Copyright (c) 2020 STMicroelectronics
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
zephyr_library()
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_IIS2DLPC iis2dlpc)
|
||||
zephyr_library_sources_ifdef(CONFIG_IIS2DLPC iis2dlpc_i2c.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_IIS2DLPC iis2dlpc_spi.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_IIS2DLPC_TRIGGER iis2dlpc_trigger.c)
|
227
drivers/sensor/iis2dlpc/Kconfig
Normal file
227
drivers/sensor/iis2dlpc/Kconfig
Normal file
|
@ -0,0 +1,227 @@
|
|||
# ST Microelectronics IIS2DLPC 3-axis accelerometer driver
|
||||
|
||||
# Copyright (c) 2020 STMicroelectronics
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
menuconfig IIS2DLPC
|
||||
bool "IIS2DLPC I2C/SPI accelerometer sensor driver"
|
||||
depends on (I2C && HAS_DTS_I2C) || SPI
|
||||
select HAS_STMEMSC
|
||||
select USE_STDC_IIS2DLPC
|
||||
help
|
||||
Enable driver for IIS2DLPC accelerometer sensor driver
|
||||
|
||||
if IIS2DLPC
|
||||
|
||||
choice IIS2DLPC_TRIGGER_MODE
|
||||
prompt "Trigger mode"
|
||||
help
|
||||
Specify the type of triggering to be used by the driver.
|
||||
|
||||
config IIS2DLPC_TRIGGER_NONE
|
||||
bool "No trigger"
|
||||
|
||||
config IIS2DLPC_TRIGGER_GLOBAL_THREAD
|
||||
bool "Use global thread"
|
||||
depends on GPIO
|
||||
select IIS2DLPC_TRIGGER
|
||||
|
||||
config IIS2DLPC_TRIGGER_OWN_THREAD
|
||||
bool "Use own thread"
|
||||
depends on GPIO
|
||||
select IIS2DLPC_TRIGGER
|
||||
|
||||
endchoice
|
||||
|
||||
config IIS2DLPC_TRIGGER
|
||||
bool
|
||||
|
||||
if IIS2DLPC_TRIGGER
|
||||
|
||||
config IIS2DLPC_THREAD_PRIORITY
|
||||
int "Thread priority"
|
||||
depends on IIS2DLPC_TRIGGER_OWN_THREAD
|
||||
default 10
|
||||
help
|
||||
Priority of thread used by the driver to handle interrupts.
|
||||
|
||||
config IIS2DLPC_THREAD_STACK_SIZE
|
||||
int "Thread stack size"
|
||||
depends on IIS2DLPC_TRIGGER_OWN_THREAD
|
||||
default 1024
|
||||
help
|
||||
Stack size of thread used by the driver to handle interrupts.
|
||||
|
||||
choice
|
||||
prompt "Sensor INT pin number"
|
||||
default IIS2DLPC_INT_PIN_1
|
||||
help
|
||||
The number of IIS2DLPC int pin used to generate interrupt to cpu.
|
||||
Supported values are int1 or int2
|
||||
|
||||
config IIS2DLPC_INT_PIN_1
|
||||
bool "int1"
|
||||
|
||||
config IIS2DLPC_INT_PIN_2
|
||||
bool "int2"
|
||||
endchoice
|
||||
|
||||
menuconfig IIS2DLPC_PULSE
|
||||
bool "Pulse detection"
|
||||
help
|
||||
Enable pulse (single/double tap) detection
|
||||
|
||||
if IIS2DLPC_PULSE
|
||||
|
||||
choice
|
||||
prompt "Pulse interrupt source"
|
||||
default IIS2DLPC_ONLY_SINGLE
|
||||
|
||||
config IIS2DLPC_ONLY_SINGLE
|
||||
bool "single"
|
||||
|
||||
config IIS2DLPC_SINGLE_DOUBLE
|
||||
bool "single/double"
|
||||
|
||||
endchoice
|
||||
|
||||
config IIS2DLPC_PULSE_THSX
|
||||
hex "Pulse X-axis threshold"
|
||||
range 0 0x1F
|
||||
default 0x0E
|
||||
help
|
||||
Threshold to start the pulse-event detection procedure on the X-axis.
|
||||
Threshold values for each axis are unsigned 5-bit corresponding
|
||||
to an 2g acceleration full-scale range.
|
||||
|
||||
config IIS2DLPC_PULSE_THSY
|
||||
hex "Pulse Y-axis threshold"
|
||||
range 0 0x1F
|
||||
default 0x0E
|
||||
help
|
||||
Threshold to start the pulse-event detection procedure on the Y-axis.
|
||||
Threshold values for each axis are unsigned 5-bit corresponding
|
||||
to an 2g acceleration full-scale range.
|
||||
|
||||
config IIS2DLPC_PULSE_THSZ
|
||||
hex "Pulse Z-axis threshold"
|
||||
range 0 0x1F
|
||||
default 0x0E
|
||||
help
|
||||
Threshold to start the pulse-event detection procedure on the Z-axis.
|
||||
Threshold values for each axis are unsigned 5-bit corresponding
|
||||
to an 2g acceleration full-scale range.
|
||||
|
||||
config IIS2DLPC_PULSE_X
|
||||
bool "Enable X axis for pulse"
|
||||
default y
|
||||
|
||||
config IIS2DLPC_PULSE_Y
|
||||
bool "Enable Y axis for pulse"
|
||||
default y
|
||||
|
||||
config IIS2DLPC_PULSE_Z
|
||||
bool "Enable Z axis for pulse"
|
||||
default y
|
||||
|
||||
config IIS2DLPC_PULSE_SHOCK
|
||||
hex "Shock value"
|
||||
range 0 0x03
|
||||
default 0x00
|
||||
help
|
||||
Maximum duration of over-threshold event: this register represents
|
||||
the maximum time of an over-threshold signal detection to be
|
||||
recognized as a tap event. Where 0 equals 4*1/ODR and 1LSB = 8*1/ODR.
|
||||
|
||||
config IIS2DLPC_PULSE_LTNCY
|
||||
hex "Latency value"
|
||||
range 0 0x0F
|
||||
default 0x05
|
||||
help
|
||||
When double-tap recognition is enabled, this register expresses
|
||||
the maximum time between two successive detected taps to
|
||||
determine a double-tap event. Where 0 equals 16*1/ODR and
|
||||
1LSB = 32*1/ODR.
|
||||
|
||||
config IIS2DLPC_PULSE_QUIET
|
||||
hex "Quiet value"
|
||||
range 0 0x03
|
||||
default 0x00
|
||||
help
|
||||
Expected quiet time after a tap detection: this register represents
|
||||
the time after the first detected tap in which there must not be
|
||||
any overthreshold event. Where 0 equals 2*1/ODR and 1LSB = 4*1/ODR.
|
||||
|
||||
endif # IIS2DLPC_PULSE
|
||||
|
||||
endif # IIS2DLPC_TRIGGER
|
||||
|
||||
choice
|
||||
prompt "Accelerometer Full-scale range setting"
|
||||
default IIS2DLPC_ACCEL_RANGE_RUNTIME
|
||||
|
||||
config IIS2DLPC_ACCEL_RANGE_RUNTIME
|
||||
bool "Set at runtime (Default 2G)"
|
||||
|
||||
config IIS2DLPC_ACCEL_RANGE_2G
|
||||
bool "2G"
|
||||
|
||||
config IIS2DLPC_ACCEL_RANGE_4G
|
||||
bool "4G"
|
||||
|
||||
config IIS2DLPC_ACCEL_RANGE_8G
|
||||
bool "8G"
|
||||
|
||||
config IIS2DLPC_ACCEL_RANGE_16G
|
||||
bool "16G"
|
||||
endchoice
|
||||
|
||||
choice
|
||||
prompt "Accelerometer sampling frequency (ODR)"
|
||||
default IIS2DLPC_ODR_RUNTIME
|
||||
|
||||
config IIS2DLPC_ODR_RUNTIME
|
||||
bool "Set at runtime (Default 100 Hz)"
|
||||
|
||||
config IIS2DLPC_ODR_1_6
|
||||
bool "1.6 Hz"
|
||||
|
||||
config IIS2DLPC_ODR_12_5
|
||||
bool "12.5 Hz"
|
||||
|
||||
config IIS2DLPC_ODR_25
|
||||
bool "25 Hz"
|
||||
|
||||
config IIS2DLPC_ODR_50
|
||||
bool "50 Hz"
|
||||
|
||||
config IIS2DLPC_ODR_100
|
||||
bool "100 Hz"
|
||||
|
||||
config IIS2DLPC_ODR_200
|
||||
bool "200 Hz"
|
||||
|
||||
config IIS2DLPC_ODR_400
|
||||
bool "400 Hz"
|
||||
|
||||
config IIS2DLPC_ODR_800
|
||||
bool "800 Hz"
|
||||
|
||||
config IIS2DLPC_ODR_1600
|
||||
bool "1600 Hz"
|
||||
|
||||
endchoice
|
||||
|
||||
config IIS2DLPC_POWER_MODE
|
||||
int "Sensor Power Modes"
|
||||
range 0 4
|
||||
default 0
|
||||
help
|
||||
Specify the sensor power mode
|
||||
0: Low Power M1
|
||||
1: Low Power M2
|
||||
2: Low Power M3
|
||||
3: Low Power M4
|
||||
4: High Performance
|
||||
|
||||
endif # IIS2DLPC
|
406
drivers/sensor/iis2dlpc/iis2dlpc.c
Normal file
406
drivers/sensor/iis2dlpc/iis2dlpc.c
Normal file
|
@ -0,0 +1,406 @@
|
|||
/* ST Microelectronics IIS2DLPC 3-axis accelerometer driver
|
||||
*
|
||||
* Copyright (c) 2020 STMicroelectronics
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Datasheet:
|
||||
* https://www.st.com/resource/en/datasheet/iis2dlpc.pdf
|
||||
*/
|
||||
|
||||
#include <init.h>
|
||||
#include <sys/__assert.h>
|
||||
#include <sys/byteorder.h>
|
||||
#include <logging/log.h>
|
||||
#include <drivers/sensor.h>
|
||||
|
||||
#if defined(DT_ST_IIS2DLPC_BUS_SPI)
|
||||
#include <drivers/spi.h>
|
||||
#elif defined(DT_ST_IIS2DLPC_BUS_I2C)
|
||||
#include <drivers/i2c.h>
|
||||
#endif
|
||||
|
||||
#include "iis2dlpc.h"
|
||||
|
||||
LOG_MODULE_REGISTER(IIS2DLPC, CONFIG_SENSOR_LOG_LEVEL);
|
||||
|
||||
/**
|
||||
* iis2dlpc_set_range - set full scale range for acc
|
||||
* @dev: Pointer to instance of struct device (I2C or SPI)
|
||||
* @range: Full scale range (2, 4, 8 and 16 G)
|
||||
*/
|
||||
static int iis2dlpc_set_range(struct device *dev, u16_t range)
|
||||
{
|
||||
int err;
|
||||
struct iis2dlpc_data *iis2dlpc = dev->driver_data;
|
||||
const struct iis2dlpc_device_config *cfg = dev->config->config_info;
|
||||
u8_t shift_gain = 0U;
|
||||
u8_t fs = IIS2DLPC_FS_TO_REG(range);
|
||||
|
||||
err = iis2dlpc_full_scale_set(iis2dlpc->ctx, fs);
|
||||
|
||||
if (cfg->pm == IIS2DLPC_CONT_LOW_PWR_12bit) {
|
||||
shift_gain = IIS2DLPC_SHFT_GAIN_NOLP1;
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
/* save internally gain for optimization */
|
||||
iis2dlpc->gain =
|
||||
IIS2DLPC_FS_TO_GAIN(IIS2DLPC_FS_TO_REG(range),
|
||||
shift_gain);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* iis2dlpc_set_odr - set new sampling frequency
|
||||
* @dev: Pointer to instance of struct device (I2C or SPI)
|
||||
* @odr: Output data rate
|
||||
*/
|
||||
static int iis2dlpc_set_odr(struct device *dev, u16_t odr)
|
||||
{
|
||||
struct iis2dlpc_data *iis2dlpc = dev->driver_data;
|
||||
u8_t val;
|
||||
|
||||
/* check if power off */
|
||||
if (odr == 0U) {
|
||||
return iis2dlpc_data_rate_set(iis2dlpc->ctx,
|
||||
IIS2DLPC_XL_ODR_OFF);
|
||||
}
|
||||
|
||||
val = IIS2DLPC_ODR_TO_REG(odr);
|
||||
if (val > IIS2DLPC_XL_ODR_1k6Hz) {
|
||||
LOG_ERR("ODR too high");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return iis2dlpc_data_rate_set(iis2dlpc->ctx, val);
|
||||
}
|
||||
|
||||
static inline void iis2dlpc_convert(struct sensor_value *val, int raw_val,
|
||||
float gain)
|
||||
{
|
||||
s64_t dval;
|
||||
|
||||
/* Gain is in ug/LSB */
|
||||
/* Convert to m/s^2 */
|
||||
dval = ((s64_t)raw_val * gain * SENSOR_G) / 1000000LL;
|
||||
val->val1 = dval / 1000000LL;
|
||||
val->val2 = dval % 1000000LL;
|
||||
}
|
||||
|
||||
static inline void iis2dlpc_channel_get_acc(struct device *dev,
|
||||
enum sensor_channel chan,
|
||||
struct sensor_value *val)
|
||||
{
|
||||
int i;
|
||||
u8_t ofs_start, ofs_stop;
|
||||
struct iis2dlpc_data *iis2dlpc = dev->driver_data;
|
||||
struct sensor_value *pval = val;
|
||||
|
||||
switch (chan) {
|
||||
case SENSOR_CHAN_ACCEL_X:
|
||||
ofs_start = ofs_stop = 0U;
|
||||
break;
|
||||
case SENSOR_CHAN_ACCEL_Y:
|
||||
ofs_start = ofs_stop = 1U;
|
||||
break;
|
||||
case SENSOR_CHAN_ACCEL_Z:
|
||||
ofs_start = ofs_stop = 2U;
|
||||
break;
|
||||
default:
|
||||
ofs_start = 0U; ofs_stop = 2U;
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = ofs_start; i <= ofs_stop ; i++) {
|
||||
iis2dlpc_convert(pval++, iis2dlpc->acc[i], iis2dlpc->gain);
|
||||
}
|
||||
}
|
||||
|
||||
static int iis2dlpc_channel_get(struct device *dev,
|
||||
enum sensor_channel chan,
|
||||
struct sensor_value *val)
|
||||
{
|
||||
switch (chan) {
|
||||
case SENSOR_CHAN_ACCEL_X:
|
||||
case SENSOR_CHAN_ACCEL_Y:
|
||||
case SENSOR_CHAN_ACCEL_Z:
|
||||
case SENSOR_CHAN_ACCEL_XYZ:
|
||||
iis2dlpc_channel_get_acc(dev, chan, val);
|
||||
return 0;
|
||||
default:
|
||||
LOG_DBG("Channel not supported");
|
||||
break;
|
||||
}
|
||||
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
static int iis2dlpc_config(struct device *dev, enum sensor_channel chan,
|
||||
enum sensor_attribute attr,
|
||||
const struct sensor_value *val)
|
||||
{
|
||||
switch (attr) {
|
||||
case SENSOR_ATTR_FULL_SCALE:
|
||||
return iis2dlpc_set_range(dev, sensor_ms2_to_g(val));
|
||||
case SENSOR_ATTR_SAMPLING_FREQUENCY:
|
||||
return iis2dlpc_set_odr(dev, val->val1);
|
||||
default:
|
||||
LOG_DBG("Acc attribute not supported");
|
||||
break;
|
||||
}
|
||||
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
static int iis2dlpc_attr_set(struct device *dev, enum sensor_channel chan,
|
||||
enum sensor_attribute attr,
|
||||
const struct sensor_value *val)
|
||||
{
|
||||
switch (chan) {
|
||||
case SENSOR_CHAN_ACCEL_X:
|
||||
case SENSOR_CHAN_ACCEL_Y:
|
||||
case SENSOR_CHAN_ACCEL_Z:
|
||||
case SENSOR_CHAN_ACCEL_XYZ:
|
||||
return iis2dlpc_config(dev, chan, attr, val);
|
||||
default:
|
||||
LOG_DBG("Attr not supported on %d channel", chan);
|
||||
break;
|
||||
}
|
||||
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
static int iis2dlpc_sample_fetch(struct device *dev, enum sensor_channel chan)
|
||||
{
|
||||
struct iis2dlpc_data *iis2dlpc = dev->driver_data;
|
||||
const struct iis2dlpc_device_config *cfg = dev->config->config_info;
|
||||
u8_t shift;
|
||||
union axis3bit16_t buf;
|
||||
|
||||
/* fetch raw data sample */
|
||||
if (iis2dlpc_acceleration_raw_get(iis2dlpc->ctx, buf.u8bit) < 0) {
|
||||
LOG_DBG("Failed to fetch raw data sample");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* adjust to resolution */
|
||||
if (cfg->pm == IIS2DLPC_CONT_LOW_PWR_12bit) {
|
||||
shift = IIS2DLPC_SHIFT_PM1;
|
||||
} else {
|
||||
shift = IIS2DLPC_SHIFT_PMOTHER;
|
||||
}
|
||||
|
||||
iis2dlpc->acc[0] = sys_le16_to_cpu(buf.i16bit[0]) >> shift;
|
||||
iis2dlpc->acc[1] = sys_le16_to_cpu(buf.i16bit[1]) >> shift;
|
||||
iis2dlpc->acc[2] = sys_le16_to_cpu(buf.i16bit[2]) >> shift;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct sensor_driver_api iis2dlpc_driver_api = {
|
||||
.attr_set = iis2dlpc_attr_set,
|
||||
#if CONFIG_IIS2DLPC_TRIGGER
|
||||
.trigger_set = iis2dlpc_trigger_set,
|
||||
#endif /* CONFIG_IIS2DLPC_TRIGGER */
|
||||
.sample_fetch = iis2dlpc_sample_fetch,
|
||||
.channel_get = iis2dlpc_channel_get,
|
||||
};
|
||||
|
||||
static int iis2dlpc_init_interface(struct device *dev)
|
||||
{
|
||||
struct iis2dlpc_data *iis2dlpc = dev->driver_data;
|
||||
const struct iis2dlpc_device_config *cfg = dev->config->config_info;
|
||||
|
||||
iis2dlpc->bus = device_get_binding(cfg->bus_name);
|
||||
if (!iis2dlpc->bus) {
|
||||
LOG_DBG("master bus not found: %s", cfg->bus_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#if defined(DT_ST_IIS2DLPC_BUS_SPI)
|
||||
iis2dlpc_spi_init(dev);
|
||||
#elif defined(DT_ST_IIS2DLPC_BUS_I2C)
|
||||
iis2dlpc_i2c_init(dev);
|
||||
#else
|
||||
#error "BUS MACRO NOT DEFINED IN DTS"
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iis2dlpc_set_power_mode(struct iis2dlpc_data *iis2dlpc,
|
||||
iis2dlpc_mode_t pm)
|
||||
{
|
||||
u8_t regval = IIS2DLPC_CONT_LOW_PWR_12bit;
|
||||
|
||||
switch (pm) {
|
||||
case IIS2DLPC_CONT_LOW_PWR_2:
|
||||
case IIS2DLPC_CONT_LOW_PWR_3:
|
||||
case IIS2DLPC_CONT_LOW_PWR_4:
|
||||
case IIS2DLPC_HIGH_PERFORMANCE:
|
||||
regval = pm;
|
||||
break;
|
||||
default:
|
||||
LOG_DBG("Apply default Power Mode");
|
||||
break;
|
||||
}
|
||||
|
||||
return iis2dlpc_write_reg(iis2dlpc->ctx, IIS2DLPC_CTRL1, ®val, 1);
|
||||
}
|
||||
|
||||
static int iis2dlpc_init(struct device *dev)
|
||||
{
|
||||
struct iis2dlpc_data *iis2dlpc = dev->driver_data;
|
||||
const struct iis2dlpc_device_config *cfg = dev->config->config_info;
|
||||
u8_t wai;
|
||||
|
||||
if (iis2dlpc_init_interface(dev)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* check chip ID */
|
||||
if (iis2dlpc_device_id_get(iis2dlpc->ctx, &wai) < 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (wai != IIS2DLPC_ID) {
|
||||
LOG_ERR("Invalid chip ID");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* reset device */
|
||||
if (iis2dlpc_reset_set(iis2dlpc->ctx, PROPERTY_ENABLE) < 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
k_busy_wait(100);
|
||||
|
||||
if (iis2dlpc_block_data_update_set(iis2dlpc->ctx,
|
||||
PROPERTY_ENABLE) < 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* set power mode */
|
||||
if (iis2dlpc_set_power_mode(iis2dlpc, CONFIG_IIS2DLPC_POWER_MODE)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* set default odr and full scale for acc */
|
||||
if (iis2dlpc_data_rate_set(iis2dlpc->ctx, IIS2DLPC_DEFAULT_ODR) < 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (iis2dlpc_full_scale_set(iis2dlpc->ctx, IIS2DLPC_ACC_FS) < 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
iis2dlpc->gain =
|
||||
IIS2DLPC_FS_TO_GAIN(IIS2DLPC_ACC_FS,
|
||||
cfg->pm == IIS2DLPC_CONT_LOW_PWR_12bit ?
|
||||
IIS2DLPC_SHFT_GAIN_NOLP1 : 0);
|
||||
|
||||
#ifdef CONFIG_IIS2DLPC_TRIGGER
|
||||
if (iis2dlpc_init_interrupt(dev) < 0) {
|
||||
LOG_ERR("Failed to initialize interrupts");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IIS2DLPC_PULSE
|
||||
if (iis2dlpc_tap_mode_set(iis2dlpc->ctx, cfg->pulse_trigger) < 0) {
|
||||
LOG_ERR("Failed to select pulse trigger mode");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (iis2dlpc_tap_threshold_x_set(iis2dlpc->ctx,
|
||||
cfg->pulse_ths[0]) < 0) {
|
||||
LOG_ERR("Failed to set tap X axis threshold");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (iis2dlpc_tap_threshold_y_set(iis2dlpc->ctx,
|
||||
cfg->pulse_ths[1]) < 0) {
|
||||
LOG_ERR("Failed to set tap Y axis threshold");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (iis2dlpc_tap_threshold_z_set(iis2dlpc->ctx,
|
||||
cfg->pulse_ths[2]) < 0) {
|
||||
LOG_ERR("Failed to set tap Z axis threshold");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (iis2dlpc_tap_detection_on_x_set(iis2dlpc->ctx,
|
||||
CONFIG_IIS2DLPC_PULSE_X) < 0) {
|
||||
LOG_ERR("Failed to set tap detection on X axis");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (iis2dlpc_tap_detection_on_y_set(iis2dlpc->ctx,
|
||||
CONFIG_IIS2DLPC_PULSE_Y) < 0) {
|
||||
LOG_ERR("Failed to set tap detection on Y axis");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (iis2dlpc_tap_detection_on_z_set(iis2dlpc->ctx,
|
||||
CONFIG_IIS2DLPC_PULSE_Z) < 0) {
|
||||
LOG_ERR("Failed to set tap detection on Z axis");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (iis2dlpc_tap_shock_set(iis2dlpc->ctx, cfg->pulse_shock) < 0) {
|
||||
LOG_ERR("Failed to set tap shock duration");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (iis2dlpc_tap_dur_set(iis2dlpc->ctx, cfg->pulse_ltncy) < 0) {
|
||||
LOG_ERR("Failed to set tap latency");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (iis2dlpc_tap_quiet_set(iis2dlpc->ctx, cfg->pulse_quiet) < 0) {
|
||||
LOG_ERR("Failed to set tap quiet time");
|
||||
return -EIO;
|
||||
}
|
||||
#endif /* CONFIG_IIS2DLPC_PULSE */
|
||||
#endif /* CONFIG_IIS2DLPC_TRIGGER */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct iis2dlpc_device_config iis2dlpc_cfg = {
|
||||
.bus_name = DT_INST_0_ST_IIS2DLPC_BUS_NAME,
|
||||
.pm = CONFIG_IIS2DLPC_POWER_MODE,
|
||||
#ifdef CONFIG_IIS2DLPC_TRIGGER
|
||||
.int_gpio_port = DT_INST_0_ST_IIS2DLPC_DRDY_GPIOS_CONTROLLER,
|
||||
.int_gpio_pin = DT_INST_0_ST_IIS2DLPC_DRDY_GPIOS_PIN,
|
||||
.int_gpio_flags = DT_INST_0_ST_IIS2DLPC_DRDY_GPIOS_FLAGS,
|
||||
#if defined(CONFIG_IIS2DLPC_INT_PIN_1)
|
||||
.int_pin = 1,
|
||||
#elif defined(CONFIG_IIS2DLPC_INT_PIN_2)
|
||||
.int_pin = 2,
|
||||
#endif /* CONFIG_IIS2DLPC_INT_PIN_* */
|
||||
|
||||
#ifdef CONFIG_IIS2DLPC_PULSE
|
||||
#if defined(CONFIG_IIS2DLPC_ONLY_SINGLE)
|
||||
.pulse_trigger = IIS2DLPC_ONLY_SINGLE,
|
||||
#elif defined(CONFIG_IIS2DLPC_SINGLE_DOUBLE)
|
||||
.pulse_trigger = IIS2DLPC_BOTH_SINGLE_DOUBLE,
|
||||
#endif
|
||||
.pulse_ths[0] = CONFIG_IIS2DLPC_PULSE_THSX,
|
||||
.pulse_ths[1] = CONFIG_IIS2DLPC_PULSE_THSY,
|
||||
.pulse_ths[2] = CONFIG_IIS2DLPC_PULSE_THSZ,
|
||||
.pulse_shock = CONFIG_IIS2DLPC_PULSE_SHOCK,
|
||||
.pulse_ltncy = CONFIG_IIS2DLPC_PULSE_LTNCY,
|
||||
.pulse_quiet = CONFIG_IIS2DLPC_PULSE_QUIET,
|
||||
#endif /* CONFIG_IIS2DLPC_PULSE */
|
||||
#endif /* CONFIG_IIS2DLPC_TRIGGER */
|
||||
};
|
||||
|
||||
struct iis2dlpc_data iis2dlpc_data;
|
||||
|
||||
DEVICE_AND_API_INIT(iis2dlpc, DT_INST_0_ST_IIS2DLPC_LABEL, iis2dlpc_init,
|
||||
&iis2dlpc_data, &iis2dlpc_cfg, POST_KERNEL,
|
||||
CONFIG_SENSOR_INIT_PRIORITY, &iis2dlpc_driver_api);
|
149
drivers/sensor/iis2dlpc/iis2dlpc.h
Normal file
149
drivers/sensor/iis2dlpc/iis2dlpc.h
Normal file
|
@ -0,0 +1,149 @@
|
|||
/* ST Microelectronics IIS2DLPC 3-axis accelerometer driver
|
||||
*
|
||||
* Copyright (c) 2020 STMicroelectronics
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Datasheet:
|
||||
* https://www.st.com/resource/en/datasheet/iis2dlpc.pdf
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_DRIVERS_SENSOR_IIS2DLPC_IIS2DLPC_H_
|
||||
#define ZEPHYR_DRIVERS_SENSOR_IIS2DLPC_IIS2DLPC_H_
|
||||
|
||||
#include <drivers/spi.h>
|
||||
#include <drivers/gpio.h>
|
||||
#include <sys/util.h>
|
||||
#include <drivers/sensor.h>
|
||||
#include "iis2dlpc_reg.h"
|
||||
|
||||
union axis3bit16_t {
|
||||
s16_t i16bit[3];
|
||||
u8_t u8bit[6];
|
||||
};
|
||||
|
||||
#if defined(CONFIG_IIS2DLPC_ODR_1_6)
|
||||
#define IIS2DLPC_DEFAULT_ODR IIS2DLPC_XL_ODR_1Hz6_LP_ONLY
|
||||
#elif defined(CONFIG_IIS2DLPC_ODR_12_5)
|
||||
#define IIS2DLPC_DEFAULT_ODR IIS2DLPC_XL_ODR_12Hz5
|
||||
#elif defined(CONFIG_IIS2DLPC_ODR_25)
|
||||
#define IIS2DLPC_DEFAULT_ODR IIS2DLPC_XL_ODR_25Hz
|
||||
#elif defined(CONFIG_IIS2DLPC_ODR_50)
|
||||
#define IIS2DLPC_DEFAULT_ODR IIS2DLPC_XL_ODR_50Hz
|
||||
#elif defined(CONFIG_IIS2DLPC_ODR_100) || \
|
||||
defined(CONFIG_IIS2DLPC_ODR_RUNTIME)
|
||||
#define IIS2DLPC_DEFAULT_ODR IIS2DLPC_XL_ODR_100Hz
|
||||
#elif defined(CONFIG_IIS2DLPC_ODR_200)
|
||||
#define IIS2DLPC_DEFAULT_ODR IIS2DLPC_XL_ODR_200Hz
|
||||
#elif defined(CONFIG_IIS2DLPC_ODR_400)
|
||||
#define IIS2DLPC_DEFAULT_ODR IIS2DLPC_XL_ODR_400Hz
|
||||
#elif defined(CONFIG_IIS2DLPC_ODR_800)
|
||||
#define IIS2DLPC_DEFAULT_ODR IIS2DLPC_XL_ODR_800Hz
|
||||
#elif defined(CONFIG_IIS2DLPC_ODR_1600)
|
||||
#define IIS2DLPC_DEFAULT_ODR IIS2DLPC_XL_ODR_1k6Hz
|
||||
#endif
|
||||
|
||||
/* Return ODR reg value based on data rate set */
|
||||
#define IIS2DLPC_ODR_TO_REG(_odr) \
|
||||
((_odr <= 1) ? IIS2DLPC_XL_ODR_1Hz6_LP_ONLY : \
|
||||
(_odr <= 12) ? IIS2DLPC_XL_ODR_12Hz5 : \
|
||||
((31 - __builtin_clz(_odr / 25))) + 3)
|
||||
|
||||
/* FS reg value from Full Scale */
|
||||
#define IIS2DLPC_FS_TO_REG(_fs) (30 - __builtin_clz(_fs))
|
||||
|
||||
#if defined(CONFIG_IIS2DLPC_ACCEL_RANGE_RUNTIME) || \
|
||||
defined(CONFIG_IIS2DLPC_ACCEL_RANGE_2G)
|
||||
#define IIS2DLPC_ACC_FS IIS2DLPC_2g
|
||||
#elif defined(CONFIG_IIS2DLPC_ACCEL_RANGE_4G)
|
||||
#define IIS2DLPC_ACC_FS IIS2DLPC_4g
|
||||
#elif defined(CONFIG_IIS2DLPC_ACCEL_RANGE_8G)
|
||||
#define IIS2DLPC_ACC_FS IIS2DLPC_8g
|
||||
#elif defined(CONFIG_IIS2DLPC_ACCEL_RANGE_16G)
|
||||
#define IIS2DLPC_ACC_FS IIS2DLPC_16g
|
||||
#endif
|
||||
|
||||
/* Acc Gain value in ug/LSB in High Perf mode */
|
||||
#define IIS2DLPC_FS_2G_GAIN 244
|
||||
#define IIS2DLPC_FS_4G_GAIN 488
|
||||
#define IIS2DLPC_FS_8G_GAIN 976
|
||||
#define IIS2DLPC_FS_16G_GAIN 1952
|
||||
|
||||
#define IIS2DLPC_SHFT_GAIN_NOLP1 2
|
||||
#define IIS2DLPC_ACCEL_GAIN_DEFAULT_VAL IIS2DLPC_FS_2G_GAIN
|
||||
#define IIS2DLPC_FS_TO_GAIN(_fs, _lp1) \
|
||||
(IIS2DLPC_FS_2G_GAIN << ((_fs) + (_lp1)))
|
||||
|
||||
/* shift value for power mode */
|
||||
#define IIS2DLPC_SHIFT_PM1 4
|
||||
#define IIS2DLPC_SHIFT_PMOTHER 2
|
||||
|
||||
/**
|
||||
* struct iis2dlpc_device_config - iis2dlpc hw configuration
|
||||
* @bus_name: Pointer to bus master identifier.
|
||||
* @pm: Power mode (lis2dh_powermode).
|
||||
* @int_gpio_port: Pointer to GPIO PORT identifier.
|
||||
* @int_gpio_pin: GPIO pin number connecter to sensor int pin.
|
||||
* @int_pin: Sensor int pin (int1/int2).
|
||||
*/
|
||||
struct iis2dlpc_device_config {
|
||||
const char *bus_name;
|
||||
iis2dlpc_mode_t pm;
|
||||
#ifdef CONFIG_IIS2DLPC_TRIGGER
|
||||
const char *int_gpio_port;
|
||||
u8_t int_gpio_pin;
|
||||
u8_t int_gpio_flags;
|
||||
u8_t int_pin;
|
||||
#ifdef CONFIG_IIS2DLPC_PULSE
|
||||
u8_t pulse_trigger;
|
||||
u8_t pulse_ths[3];
|
||||
u8_t pulse_shock;
|
||||
u8_t pulse_ltncy;
|
||||
u8_t pulse_quiet;
|
||||
#endif /* CONFIG_IIS2DLPC_PULSE */
|
||||
#endif /* CONFIG_IIS2DLPC_TRIGGER */
|
||||
};
|
||||
|
||||
/* sensor data */
|
||||
struct iis2dlpc_data {
|
||||
struct device *bus;
|
||||
s16_t acc[3];
|
||||
|
||||
/* save sensitivity */
|
||||
u16_t gain;
|
||||
|
||||
stmdev_ctx_t *ctx;
|
||||
#ifdef CONFIG_IIS2DLPC_TRIGGER
|
||||
struct device *gpio;
|
||||
u8_t gpio_pin;
|
||||
struct gpio_callback gpio_cb;
|
||||
sensor_trigger_handler_t drdy_handler;
|
||||
#ifdef CONFIG_IIS2DLPC_PULSE
|
||||
sensor_trigger_handler_t tap_handler;
|
||||
sensor_trigger_handler_t double_tap_handler;
|
||||
#endif /* CONFIG_IIS2DLPC_PULSE */
|
||||
#if defined(CONFIG_IIS2DLPC_TRIGGER_OWN_THREAD)
|
||||
K_THREAD_STACK_MEMBER(thread_stack, CONFIG_IIS2DLPC_THREAD_STACK_SIZE);
|
||||
struct k_thread thread;
|
||||
struct k_sem gpio_sem;
|
||||
#elif defined(CONFIG_IIS2DLPC_TRIGGER_GLOBAL_THREAD)
|
||||
struct k_work work;
|
||||
struct device *dev;
|
||||
#endif /* CONFIG_IIS2DLPC_TRIGGER_GLOBAL_THREAD */
|
||||
#endif /* CONFIG_IIS2DLPC_TRIGGER */
|
||||
#if defined(DT_INST_0_ST_IIS2DLPC_CS_GPIOS_CONTROLLER)
|
||||
struct spi_cs_control cs_ctrl;
|
||||
#endif
|
||||
};
|
||||
|
||||
int iis2dlpc_i2c_init(struct device *dev);
|
||||
int iis2dlpc_spi_init(struct device *dev);
|
||||
|
||||
#ifdef CONFIG_IIS2DLPC_TRIGGER
|
||||
int iis2dlpc_init_interrupt(struct device *dev);
|
||||
int iis2dlpc_trigger_set(struct device *dev,
|
||||
const struct sensor_trigger *trig,
|
||||
sensor_trigger_handler_t handler);
|
||||
#endif /* CONFIG_IIS2DLPC_TRIGGER */
|
||||
|
||||
#endif /* ZEPHYR_DRIVERS_SENSOR_IIS2DLPC_IIS2DLPC_H_ */
|
51
drivers/sensor/iis2dlpc/iis2dlpc_i2c.c
Normal file
51
drivers/sensor/iis2dlpc/iis2dlpc_i2c.c
Normal file
|
@ -0,0 +1,51 @@
|
|||
/* ST Microelectronics IIS2DLPC 3-axis accelerometer driver
|
||||
*
|
||||
* Copyright (c) 2020 STMicroelectronics
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Datasheet:
|
||||
* https://www.st.com/resource/en/datasheet/iis2dlpc.pdf
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <drivers/i2c.h>
|
||||
#include <logging/log.h>
|
||||
|
||||
#include "iis2dlpc.h"
|
||||
|
||||
#ifdef DT_ST_IIS2DLPC_BUS_I2C
|
||||
|
||||
static u16_t iis2dlpc_i2c_slave_addr = DT_INST_0_ST_IIS2DLPC_BASE_ADDRESS;
|
||||
|
||||
LOG_MODULE_DECLARE(IIS2DLPC, CONFIG_SENSOR_LOG_LEVEL);
|
||||
|
||||
static int iis2dlpc_i2c_read(struct iis2dlpc_data *data, u8_t reg_addr,
|
||||
u8_t *value, u16_t len)
|
||||
{
|
||||
return i2c_burst_read(data->bus, iis2dlpc_i2c_slave_addr,
|
||||
reg_addr, value, len);
|
||||
}
|
||||
|
||||
static int iis2dlpc_i2c_write(struct iis2dlpc_data *data, u8_t reg_addr,
|
||||
u8_t *value, u16_t len)
|
||||
{
|
||||
return i2c_burst_write(data->bus, iis2dlpc_i2c_slave_addr,
|
||||
reg_addr, value, len);
|
||||
}
|
||||
|
||||
stmdev_ctx_t iis2dlpc_i2c_ctx = {
|
||||
.read_reg = (stmdev_read_ptr) iis2dlpc_i2c_read,
|
||||
.write_reg = (stmdev_write_ptr) iis2dlpc_i2c_write,
|
||||
};
|
||||
|
||||
int iis2dlpc_i2c_init(struct device *dev)
|
||||
{
|
||||
struct iis2dlpc_data *data = dev->driver_data;
|
||||
|
||||
data->ctx = &iis2dlpc_i2c_ctx;
|
||||
data->ctx->handle = data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* DT_ST_IIS2DLPC_BUS_I2C */
|
126
drivers/sensor/iis2dlpc/iis2dlpc_spi.c
Normal file
126
drivers/sensor/iis2dlpc/iis2dlpc_spi.c
Normal file
|
@ -0,0 +1,126 @@
|
|||
/* ST Microelectronics IIS2DLPC 3-axis accelerometer driver
|
||||
*
|
||||
* Copyright (c) 2020 STMicroelectronics
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Datasheet:
|
||||
* https://www.st.com/resource/en/datasheet/iis2dlpc.pdf
|
||||
*/
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include "iis2dlpc.h"
|
||||
#include <logging/log.h>
|
||||
|
||||
#ifdef DT_ST_IIS2DLPC_BUS_SPI
|
||||
|
||||
#define IIS2DLPC_SPI_READ (1 << 7)
|
||||
|
||||
LOG_MODULE_DECLARE(IIS2DLPC, CONFIG_SENSOR_LOG_LEVEL);
|
||||
|
||||
static struct spi_config iis2dlpc_spi_conf = {
|
||||
.frequency = DT_INST_0_ST_IIS2DLPC_SPI_MAX_FREQUENCY,
|
||||
.operation = (SPI_OP_MODE_MASTER | SPI_MODE_CPOL |
|
||||
SPI_MODE_CPHA | SPI_WORD_SET(8) | SPI_LINES_SINGLE),
|
||||
.slave = DT_INST_0_ST_IIS2DLPC_BASE_ADDRESS,
|
||||
.cs = NULL,
|
||||
};
|
||||
|
||||
static int iis2dlpc_spi_read(struct iis2dlpc_data *ctx, u8_t reg,
|
||||
u8_t *data, u16_t len)
|
||||
{
|
||||
struct spi_config *spi_cfg = &iis2dlpc_spi_conf;
|
||||
u8_t buffer_tx[2] = { reg | IIS2DLPC_SPI_READ, 0 };
|
||||
const struct spi_buf tx_buf = {
|
||||
.buf = buffer_tx,
|
||||
.len = 2,
|
||||
};
|
||||
const struct spi_buf_set tx = {
|
||||
.buffers = &tx_buf,
|
||||
.count = 1
|
||||
};
|
||||
const struct spi_buf rx_buf[2] = {
|
||||
{
|
||||
.buf = NULL,
|
||||
.len = 1,
|
||||
},
|
||||
{
|
||||
.buf = data,
|
||||
.len = len,
|
||||
}
|
||||
};
|
||||
const struct spi_buf_set rx = {
|
||||
.buffers = rx_buf,
|
||||
.count = 2
|
||||
};
|
||||
|
||||
if (spi_transceive(ctx->bus, spi_cfg, &tx, &rx)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iis2dlpc_spi_write(struct iis2dlpc_data *ctx, u8_t reg,
|
||||
u8_t *data, u16_t len)
|
||||
{
|
||||
struct spi_config *spi_cfg = &iis2dlpc_spi_conf;
|
||||
u8_t buffer_tx[1] = { reg & ~IIS2DLPC_SPI_READ };
|
||||
const struct spi_buf tx_buf[2] = {
|
||||
{
|
||||
.buf = buffer_tx,
|
||||
.len = 1,
|
||||
},
|
||||
{
|
||||
.buf = data,
|
||||
.len = len,
|
||||
}
|
||||
};
|
||||
const struct spi_buf_set tx = {
|
||||
.buffers = tx_buf,
|
||||
.count = 2
|
||||
};
|
||||
|
||||
|
||||
if (spi_write(ctx->bus, spi_cfg, &tx)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
stmdev_ctx_t iis2dlpc_spi_ctx = {
|
||||
.read_reg = (stmdev_read_ptr) iis2dlpc_spi_read,
|
||||
.write_reg = (stmdev_write_ptr) iis2dlpc_spi_write,
|
||||
};
|
||||
|
||||
int iis2dlpc_spi_init(struct device *dev)
|
||||
{
|
||||
struct iis2dlpc_data *data = dev->driver_data;
|
||||
|
||||
data->ctx = &iis2dlpc_spi_ctx;
|
||||
data->ctx->handle = data;
|
||||
|
||||
#if defined(DT_INST_0_ST_IIS2DLPC_CS_GPIOS_CONTROLLER)
|
||||
/* handle SPI CS thru GPIO if it is the case */
|
||||
data->cs_ctrl.gpio_dev = device_get_binding(
|
||||
DT_INST_0_ST_IIS2DLPC_CS_GPIOS_CONTROLLER);
|
||||
if (!data->cs_ctrl.gpio_dev) {
|
||||
LOG_ERR("Unable to get GPIO SPI CS device");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
data->cs_ctrl.gpio_pin = DT_INST_0_ST_IIS2DLPC_CS_GPIOS_PIN;
|
||||
data->cs_ctrl.delay = 0U;
|
||||
|
||||
iis2dlpc_spi_conf.cs = &data->cs_ctrl;
|
||||
|
||||
LOG_DBG("SPI GPIO CS configured on %s:%u",
|
||||
DT_INST_0_ST_IIS2DLPC_CS_GPIOS_CONTROLLER,
|
||||
DT_INST_0_ST_IIS2DLPC_CS_GPIOS_PIN);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* DT_ST_IIS2DLPC_BUS_SPI */
|
284
drivers/sensor/iis2dlpc/iis2dlpc_trigger.c
Normal file
284
drivers/sensor/iis2dlpc/iis2dlpc_trigger.c
Normal file
|
@ -0,0 +1,284 @@
|
|||
/* ST Microelectronics IIS2DLPC 3-axis accelerometer driver
|
||||
*
|
||||
* Copyright (c) 2020 STMicroelectronics
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Datasheet:
|
||||
* https://www.st.com/resource/en/datasheet/iis2dlpc.pdf
|
||||
*/
|
||||
|
||||
#include <kernel.h>
|
||||
#include <drivers/sensor.h>
|
||||
#include <drivers/gpio.h>
|
||||
#include <logging/log.h>
|
||||
|
||||
#include "iis2dlpc.h"
|
||||
|
||||
LOG_MODULE_DECLARE(IIS2DLPC, CONFIG_SENSOR_LOG_LEVEL);
|
||||
|
||||
/**
|
||||
* iis2dlpc_enable_int - enable selected int pin to generate interrupt
|
||||
*/
|
||||
static int iis2dlpc_enable_int(struct device *dev,
|
||||
enum sensor_trigger_type type, int enable)
|
||||
{
|
||||
const struct iis2dlpc_device_config *cfg = dev->config->config_info;
|
||||
struct iis2dlpc_data *iis2dlpc = dev->driver_data;
|
||||
iis2dlpc_reg_t int_route;
|
||||
|
||||
if (cfg->int_pin == 1U) {
|
||||
/* set interrupt for pin INT1 */
|
||||
iis2dlpc_pin_int1_route_get(iis2dlpc->ctx,
|
||||
&int_route.ctrl4_int1_pad_ctrl);
|
||||
|
||||
switch (type) {
|
||||
case SENSOR_TRIG_DATA_READY:
|
||||
int_route.ctrl4_int1_pad_ctrl.int1_drdy = enable;
|
||||
break;
|
||||
#ifdef CONFIG_IIS2DLPC_PULSE
|
||||
case SENSOR_TRIG_TAP:
|
||||
int_route.ctrl4_int1_pad_ctrl.int1_single_tap = enable;
|
||||
break;
|
||||
case SENSOR_TRIG_DOUBLE_TAP:
|
||||
int_route.ctrl4_int1_pad_ctrl.int1_tap = enable;
|
||||
break;
|
||||
#endif /* CONFIG_IIS2DLPC_PULSE */
|
||||
default:
|
||||
LOG_ERR("Unsupported trigger interrupt route");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return iis2dlpc_pin_int1_route_set(iis2dlpc->ctx,
|
||||
&int_route.ctrl4_int1_pad_ctrl);
|
||||
} else {
|
||||
/* set interrupt for pin INT2 */
|
||||
iis2dlpc_pin_int2_route_get(iis2dlpc->ctx,
|
||||
&int_route.ctrl5_int2_pad_ctrl);
|
||||
|
||||
switch (type) {
|
||||
case SENSOR_TRIG_DATA_READY:
|
||||
int_route.ctrl5_int2_pad_ctrl.int2_drdy = enable;
|
||||
break;
|
||||
default:
|
||||
LOG_ERR("Unsupported trigger interrupt route");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return iis2dlpc_pin_int2_route_set(iis2dlpc->ctx,
|
||||
&int_route.ctrl5_int2_pad_ctrl);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* iis2dlpc_trigger_set - link external trigger to event data ready
|
||||
*/
|
||||
int iis2dlpc_trigger_set(struct device *dev,
|
||||
const struct sensor_trigger *trig,
|
||||
sensor_trigger_handler_t handler)
|
||||
{
|
||||
struct iis2dlpc_data *iis2dlpc = dev->driver_data;
|
||||
union axis3bit16_t raw;
|
||||
int state = (handler != NULL) ? PROPERTY_ENABLE : PROPERTY_DISABLE;
|
||||
|
||||
switch (trig->type) {
|
||||
case SENSOR_TRIG_DATA_READY:
|
||||
iis2dlpc->drdy_handler = handler;
|
||||
if (state) {
|
||||
/* dummy read: re-trigger interrupt */
|
||||
iis2dlpc_acceleration_raw_get(iis2dlpc->ctx, raw.u8bit);
|
||||
}
|
||||
return iis2dlpc_enable_int(dev, SENSOR_TRIG_DATA_READY, state);
|
||||
#ifdef CONFIG_IIS2DLPC_PULSE
|
||||
case SENSOR_TRIG_TAP:
|
||||
iis2dlpc->tap_handler = handler;
|
||||
return iis2dlpc_enable_int(dev, SENSOR_TRIG_TAP, state);
|
||||
case SENSOR_TRIG_DOUBLE_TAP:
|
||||
iis2dlpc->double_tap_handler = handler;
|
||||
return iis2dlpc_enable_int(dev, SENSOR_TRIG_DOUBLE_TAP, state);
|
||||
#endif /* CONFIG_IIS2DLPC_PULSE */
|
||||
default:
|
||||
LOG_ERR("Unsupported sensor trigger");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
}
|
||||
|
||||
static int iis2dlpc_handle_drdy_int(struct device *dev)
|
||||
{
|
||||
struct iis2dlpc_data *data = dev->driver_data;
|
||||
|
||||
struct sensor_trigger drdy_trig = {
|
||||
.type = SENSOR_TRIG_DATA_READY,
|
||||
.chan = SENSOR_CHAN_ALL,
|
||||
};
|
||||
|
||||
if (data->drdy_handler) {
|
||||
data->drdy_handler(dev, &drdy_trig);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IIS2DLPC_PULSE
|
||||
static int iis2dlpc_handle_single_tap_int(struct device *dev)
|
||||
{
|
||||
struct iis2dlpc_data *data = dev->driver_data;
|
||||
sensor_trigger_handler_t handler = data->tap_handler;
|
||||
|
||||
struct sensor_trigger pulse_trig = {
|
||||
.type = SENSOR_TRIG_TAP,
|
||||
.chan = SENSOR_CHAN_ALL,
|
||||
};
|
||||
|
||||
if (handler) {
|
||||
handler(dev, &pulse_trig);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iis2dlpc_handle_double_tap_int(struct device *dev)
|
||||
{
|
||||
struct iis2dlpc_data *data = dev->driver_data;
|
||||
sensor_trigger_handler_t handler = data->double_tap_handler;
|
||||
|
||||
struct sensor_trigger pulse_trig = {
|
||||
.type = SENSOR_TRIG_DOUBLE_TAP,
|
||||
.chan = SENSOR_CHAN_ALL,
|
||||
};
|
||||
|
||||
if (handler) {
|
||||
handler(dev, &pulse_trig);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_IIS2DLPC_PULSE */
|
||||
|
||||
/**
|
||||
* iis2dlpc_handle_interrupt - handle the drdy event
|
||||
* read data and call handler if registered any
|
||||
*/
|
||||
static void iis2dlpc_handle_interrupt(void *arg)
|
||||
{
|
||||
struct device *dev = (struct device *)arg;
|
||||
struct iis2dlpc_data *iis2dlpc = dev->driver_data;
|
||||
const struct iis2dlpc_device_config *cfg = dev->config->config_info;
|
||||
iis2dlpc_all_sources_t sources;
|
||||
|
||||
iis2dlpc_all_sources_get(iis2dlpc->ctx, &sources);
|
||||
|
||||
if (sources.status_dup.drdy) {
|
||||
iis2dlpc_handle_drdy_int(dev);
|
||||
}
|
||||
#ifdef CONFIG_IIS2DLPC_PULSE
|
||||
if (sources.status_dup.single_tap) {
|
||||
iis2dlpc_handle_single_tap_int(dev);
|
||||
}
|
||||
if (sources.status_dup.double_tap) {
|
||||
iis2dlpc_handle_double_tap_int(dev);
|
||||
}
|
||||
#endif /* CONFIG_IIS2DLPC_PULSE */
|
||||
|
||||
gpio_pin_interrupt_configure(iis2dlpc->gpio, cfg->int_gpio_pin,
|
||||
GPIO_INT_EDGE_TO_ACTIVE);
|
||||
}
|
||||
|
||||
static void iis2dlpc_gpio_callback(struct device *dev,
|
||||
struct gpio_callback *cb, u32_t pins)
|
||||
{
|
||||
struct iis2dlpc_data *iis2dlpc =
|
||||
CONTAINER_OF(cb, struct iis2dlpc_data, gpio_cb);
|
||||
|
||||
if ((pins & BIT(iis2dlpc->gpio_pin)) == 0U) {
|
||||
return;
|
||||
}
|
||||
|
||||
gpio_pin_interrupt_configure(dev, iis2dlpc->gpio_pin,
|
||||
GPIO_INT_DISABLE);
|
||||
|
||||
#if defined(CONFIG_IIS2DLPC_TRIGGER_OWN_THREAD)
|
||||
k_sem_give(&iis2dlpc->gpio_sem);
|
||||
#elif defined(CONFIG_IIS2DLPC_TRIGGER_GLOBAL_THREAD)
|
||||
k_work_submit(&iis2dlpc->work);
|
||||
#endif /* CONFIG_IIS2DLPC_TRIGGER_OWN_THREAD */
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IIS2DLPC_TRIGGER_OWN_THREAD
|
||||
static void iis2dlpc_thread(int dev_ptr, int unused)
|
||||
{
|
||||
struct device *dev = INT_TO_POINTER(dev_ptr);
|
||||
struct iis2dlpc_data *iis2dlpc = dev->driver_data;
|
||||
|
||||
ARG_UNUSED(unused);
|
||||
|
||||
while (1) {
|
||||
k_sem_take(&iis2dlpc->gpio_sem, K_FOREVER);
|
||||
iis2dlpc_handle_interrupt(dev);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_IIS2DLPC_TRIGGER_OWN_THREAD */
|
||||
|
||||
#ifdef CONFIG_IIS2DLPC_TRIGGER_GLOBAL_THREAD
|
||||
static void iis2dlpc_work_cb(struct k_work *work)
|
||||
{
|
||||
struct iis2dlpc_data *iis2dlpc =
|
||||
CONTAINER_OF(work, struct iis2dlpc_data, work);
|
||||
|
||||
iis2dlpc_handle_interrupt(iis2dlpc->dev);
|
||||
}
|
||||
#endif /* CONFIG_IIS2DLPC_TRIGGER_GLOBAL_THREAD */
|
||||
|
||||
int iis2dlpc_init_interrupt(struct device *dev)
|
||||
{
|
||||
struct iis2dlpc_data *iis2dlpc = dev->driver_data;
|
||||
const struct iis2dlpc_device_config *cfg = dev->config->config_info;
|
||||
int ret;
|
||||
|
||||
/* setup data ready gpio interrupt (INT1 or INT2) */
|
||||
iis2dlpc->gpio = device_get_binding(cfg->int_gpio_port);
|
||||
if (iis2dlpc->gpio == NULL) {
|
||||
LOG_DBG("Cannot get pointer to %s device",
|
||||
cfg->int_gpio_port);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_IIS2DLPC_TRIGGER_OWN_THREAD)
|
||||
k_sem_init(&iis2dlpc->gpio_sem, 0, UINT_MAX);
|
||||
|
||||
k_thread_create(&iis2dlpc->thread, iis2dlpc->thread_stack,
|
||||
CONFIG_IIS2DLPC_THREAD_STACK_SIZE,
|
||||
(k_thread_entry_t)iis2dlpc_thread, dev,
|
||||
0, NULL, K_PRIO_COOP(CONFIG_IIS2DLPC_THREAD_PRIORITY),
|
||||
0, K_NO_WAIT);
|
||||
#elif defined(CONFIG_IIS2DLPC_TRIGGER_GLOBAL_THREAD)
|
||||
iis2dlpc->work.handler = iis2dlpc_work_cb;
|
||||
iis2dlpc->dev = dev;
|
||||
#endif /* CONFIG_IIS2DLPC_TRIGGER_OWN_THREAD */
|
||||
|
||||
iis2dlpc->gpio_pin = cfg->int_gpio_pin;
|
||||
|
||||
ret = gpio_pin_configure(iis2dlpc->gpio, cfg->int_gpio_pin,
|
||||
GPIO_INPUT | cfg->int_gpio_flags);
|
||||
if (ret < 0) {
|
||||
LOG_DBG("Could not configure gpio");
|
||||
return ret;
|
||||
}
|
||||
|
||||
gpio_init_callback(&iis2dlpc->gpio_cb,
|
||||
iis2dlpc_gpio_callback,
|
||||
BIT(cfg->int_gpio_pin));
|
||||
|
||||
if (gpio_add_callback(iis2dlpc->gpio, &iis2dlpc->gpio_cb) < 0) {
|
||||
LOG_DBG("Could not set gpio callback");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* enable interrupt on int1/int2 in pulse mode */
|
||||
if (iis2dlpc_int_notification_set(iis2dlpc->ctx, IIS2DLPC_INT_PULSED)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return gpio_pin_interrupt_configure(iis2dlpc->gpio, cfg->int_gpio_pin,
|
||||
GPIO_INT_EDGE_TO_ACTIVE);
|
||||
}
|
19
dts/bindings/sensor/st,iis2dlpc-i2c.yaml
Normal file
19
dts/bindings/sensor/st,iis2dlpc-i2c.yaml
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Copyright (c) 2018 STMicroelectronics
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: |
|
||||
STMicroelectronics IIS2DLPC accelerometer accessed through I2C bus
|
||||
|
||||
compatible: "st,iis2dlpc"
|
||||
|
||||
include: i2c-device.yaml
|
||||
|
||||
properties:
|
||||
drdy-gpios:
|
||||
type: phandle-array
|
||||
required: false
|
||||
description: DRDY pin
|
||||
|
||||
This pin defaults to active high when produced by the sensor.
|
||||
The property value should ensure the flags properly describe
|
||||
the signal that is presented to the driver.
|
19
dts/bindings/sensor/st,iis2dlpc-spi.yaml
Normal file
19
dts/bindings/sensor/st,iis2dlpc-spi.yaml
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Copyright (c) 2019 STMicroelectronics
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: |
|
||||
STMicroelectronics IIS2DLPC accelerometer accessed through SPI bus
|
||||
|
||||
compatible: "st,iis2dlpc"
|
||||
|
||||
include: spi-device.yaml
|
||||
|
||||
properties:
|
||||
drdy-gpios:
|
||||
type: phandle-array
|
||||
required: false
|
||||
description: DRDY pin
|
||||
|
||||
This pin defaults to active high when produced by the sensor.
|
||||
The property value should ensure the flags properly describe
|
||||
the signal that is presented to the driver.
|
|
@ -119,6 +119,16 @@
|
|||
#define DT_INST_0_ST_HTS221_DRDY_GPIOS_CONTROLLER ""
|
||||
#endif
|
||||
|
||||
#ifndef DT_INST_0_ST_IIS2DLPC_LABEL
|
||||
#define DT_INST_0_ST_IIS2DLPC_LABEL ""
|
||||
#define DT_INST_0_ST_IIS2DLPC_BUS_NAME ""
|
||||
#define DT_INST_0_ST_IIS2DLPC_BASE_ADDRESS 0
|
||||
#define DT_INST_0_ST_IIS2DLPC_DRDY_GPIOS_FLAGS 0
|
||||
#define DT_INST_0_ST_IIS2DLPC_DRDY_GPIOS_PIN 0
|
||||
#define DT_INST_0_ST_IIS2DLPC_DRDY_GPIOS_CONTROLLER ""
|
||||
#define DT_ST_IIS2DLPC_BUS_I2C 1
|
||||
#endif
|
||||
|
||||
#ifndef DT_INST_0_ST_LIS3MDL_MAGN_LABEL
|
||||
#define DT_INST_0_ST_LIS3MDL_MAGN_LABEL ""
|
||||
#define DT_INST_0_ST_LIS3MDL_MAGN_BUS_NAME ""
|
||||
|
@ -485,6 +495,17 @@
|
|||
#define DT_INST_0_BOSCH_BMI160_SPI_MAX_FREQUENCY 6400000
|
||||
#endif
|
||||
|
||||
#ifndef DT_INST_0_ST_IIS2DLPC_LABEL
|
||||
#define DT_INST_0_ST_IIS2DLPC_LABEL ""
|
||||
#define DT_INST_0_ST_IIS2DLPC_BUS_NAME ""
|
||||
#define DT_INST_0_ST_IIS2DLPC_SPI_MAX_FREQUENCY 100000
|
||||
#define DT_INST_0_ST_IIS2DLPC_BASE_ADDRESS 1
|
||||
#define DT_INST_0_ST_IIS2DLPC_DRDY_GPIOS_CONTROLLER ""
|
||||
#define DT_INST_0_ST_IIS2DLPC_DRDY_GPIOS_FLAGS 0
|
||||
#define DT_INST_0_ST_IIS2DLPC_DRDY_GPIOS_PIN 0
|
||||
#define DT_ST_IIS2DLPC_BUS_SPI 1
|
||||
#endif
|
||||
|
||||
#ifndef DT_INST_0_ST_IIS3DHHC_LABEL
|
||||
#define DT_INST_0_ST_IIS3DHHC_LABEL ""
|
||||
#define DT_INST_0_ST_IIS3DHHC_BASE_ADDRESS 0
|
||||
|
|
|
@ -5,5 +5,6 @@ CONFIG_ADC=y
|
|||
CONFIG_GPIO=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_SENSOR=y
|
||||
CONFIG_IIS2DLPC=y
|
||||
CONFIG_LIS2DW12=y
|
||||
CONFIG_STTS751=y
|
||||
|
|
|
@ -5,6 +5,8 @@ CONFIG_ADC=y
|
|||
CONFIG_GPIO=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_SENSOR=y
|
||||
CONFIG_IIS2DLPC=y
|
||||
CONFIG_IIS2DLPC_TRIGGER_OWN_THREAD=y
|
||||
CONFIG_LIS2DW12=y
|
||||
CONFIG_LIS2DW12_TRIGGER_OWN_THREAD=y
|
||||
CONFIG_STTS751=y
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue