diff --git a/drivers/sensors/CMakeLists.txt b/drivers/sensors/CMakeLists.txt index 34010f349e6..a5e6c49b57a 100644 --- a/drivers/sensors/CMakeLists.txt +++ b/drivers/sensors/CMakeLists.txt @@ -113,7 +113,12 @@ if(CONFIG_SENSORS) endif() if(CONFIG_SENSORS_LSM9DS1) - list(APPEND SRCS lsm9ds1.c) + list(APPEND SRCS lsm9ds1_base.c) + if(CONFIG_SENSORS_LSM9DS1_UORB) + list(APPEND SRCS lsm9ds1_uorb.c) + else() + list(APPEND SRCS lsm9ds1.c) + endif() endif() if(CONFIG_SENSORS_MSA301) diff --git a/drivers/sensors/Kconfig b/drivers/sensors/Kconfig index 342daa2ff41..3a3a419f697 100644 --- a/drivers/sensors/Kconfig +++ b/drivers/sensors/Kconfig @@ -605,6 +605,36 @@ config SENSORS_LSM9DS1 ---help--- Enable driver support for the STMicro LSM9DS1. +config SENSORS_LSM9DS1_UORB + bool "LSM9DS1 UORB Interface" + default n + depends on SENSORS_LSM9DS1 + +if SENSORS_LSM9DS1_UORB + +config SENSORS_LSM9DS1_POLL + bool "Enables polling sensor data" + default n + ---help--- + Enables polling of sensor. + +config SENSORS_LSM9DS1_POLL_INTERVAL + int "Polling interval in microseconds, default 1 sec" + depends on SENSORS_LSM9DS1_POLL + default 1000000 + range 0 4294967295 + ---help--- + The interval until a new sensor measurement will be triggered. + +config SENSORS_LSM9DS1_THREAD_STACKSIZE + int "Worker thread stack size" + depends on SENSORS_LSM9DS1_POLL + default 1024 + ---help--- + The stack size for the worker thread. + +endif #SENSORS_LSM9DS1_UORB + config SENSORS_MSA301 bool "MSA301 support" default n @@ -616,7 +646,7 @@ config LSM9DS1_I2C_FREQUENCY int "LSM9DS1 I2C frequency" default 400000 range 1 400000 - depends on SENSORS_LSM9DS1 + depends on SENSORS_LSM9DS1 || SENSORS_LSM9DS1_UORB config SENSORS_LPS25H bool "STMicro LPS25H pressure sensor" diff --git a/drivers/sensors/Make.defs b/drivers/sensors/Make.defs index 8e513ab06e4..19ad604affb 100644 --- a/drivers/sensors/Make.defs +++ b/drivers/sensors/Make.defs @@ -121,7 +121,12 @@ ifeq ($(CONFIG_SENSORS_LSM6DSL),y) endif ifeq ($(CONFIG_SENSORS_LSM9DS1),y) - CSRCS += lsm9ds1.c + CSRCS += lsm9ds1_base.c + ifeq ($(CONFIG_SENSORS_LSM9DS1_UORB),y) + CSRCS += lsm9ds1_uorb.c + else + CSRCS += lsm9ds1.c + endif endif ifeq ($(CONFIG_SENSORS_MSA301),y) diff --git a/drivers/sensors/lsm9ds1.c b/drivers/sensors/lsm9ds1.c index 23e578d4d1a..ece7affa774 100644 --- a/drivers/sensors/lsm9ds1.c +++ b/drivers/sensors/lsm9ds1.c @@ -24,542 +24,14 @@ #include -#include -#include -#include -#include - -#include -#include -#include -#include -#include +#include "lsm9ds1_base.h" #if defined(CONFIG_I2C) && defined(CONFIG_SENSORS_LSM9DS1) -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -#ifndef CONFIG_LSM9DS1_I2C_FREQUENCY -# define CONFIG_LSM9DS1_I2C_FREQUENCY 400000 -#endif - -/* Register Addresses *******************************************************/ - -/* Accelerometer and gyroscope registers */ - -#define LSM9DS1_ACT_THS 0x04 /* Inactivity threshold */ -#define LSM9DS1_ACT_DUR 0x05 /* Inactivity duration */ -#define LSM9DS1_INT_GEN_CFG_XL 0x06 /* Accelerometer interrupt configuration */ -#define LSM9DS1_INT_GEN_THS_X_XL 0x07 /* Accelerometer X interrupt threshold */ -#define LSM9DS1_INT_GEN_THS_Y_XL 0x08 /* Accelerometer Y interrupt threshold */ -#define LSM9DS1_INT_GEN_THS_Z_XL 0x09 /* Accelerometer Z interrupt threshold */ -#define LSM9DS1_INT_GEN_DUR_XL 0x0a /* Accelerometer interrupt duration */ -#define LSM9DS1_REFERENCE_G 0x0b /* Gyroscope reference value for high-pass filter */ -#define LSM9DS1_INT1_CTRL 0x0c /* INT1_A/G pin control */ -#define LSM9DS1_INT2_CTRL 0x0d /* INT2_A/G pin control */ -#define LSM9DS1_WHO_AM_I 0x0f /* Accelerometer and gyroscope device identification */ -#define LSM9DS1_CTRL_REG1_G 0x10 /* Gyroscope control register 1 */ -#define LSM9DS1_CTRL_REG2_G 0x11 /* Gyroscope control register 2 */ -#define LSM9DS1_CTRL_REG3_G 0x12 /* Gyroscope control register 3 */ -#define LSM9DS1_ORIENT_CFG_G 0x13 /* Gyroscope sign and orientation */ -#define LSM9DS1_INT_GEN_SRC_G 0x14 /* Gyroscope interrupt source */ -#define LSM9DS1_OUT_TEMP_L 0x15 /* Temperature low byte */ -#define LSM9DS1_OUT_TEMP_H 0x16 /* Temperature high byte */ -#define LSM9DS1_STATUS_REG 0x17 /* Status register */ -#define LSM9DS1_OUT_X_L_G 0x18 /* Gyroscope pitch (X) low byte */ -#define LSM9DS1_OUT_X_H_G 0x19 /* Gyroscope pitch (X) high byte */ -#define LSM9DS1_OUT_Y_L_G 0x1a /* Gyroscope roll (Y) low byte */ -#define LSM9DS1_OUT_Y_H_G 0x1b /* Gyroscope roll (Y) high byte */ -#define LSM9DS1_OUT_Z_L_G 0x1c /* Gyroscope yaw (Z) low byte */ -#define LSM9DS1_OUT_Z_H_G 0x1d /* Gyroscope yaw (Z) high byte */ -#define LSM9DS1_CTRL_REG4 0x1e /* Control register 4 */ -#define LSM9DS1_CTRL_REG5_XL 0x1f /* Accelerometer control register 5 */ -#define LSM9DS1_CTRL_REG6_XL 0x20 /* Accelerometer control register 6 */ -#define LSM9DS1_CTRL_REG7_XL 0x21 /* Accelerometer control register 7 */ -#define LSM9DS1_CTRL_REG8 0x22 /* Control register 8 */ -#define LSM9DS1_CTRL_REG9 0x23 /* Control register 9 */ -#define LSM9DS1_CTRL_REG10 0x24 /* Control register 10 */ -#define LSM9DS1_INT_GEN_SRC_XL 0x26 /* Accelerometer interrupt source */ -#define LSM9DS1_STATUS_REG2 0x27 /* Status register 2 */ -#define LSM9DS1_OUT_X_L_XL 0x28 /* Accelerometer X low byte */ -#define LSM9DS1_OUT_X_H_XL 0x29 /* Accelerometer X high byte */ -#define LSM9DS1_OUT_Y_L_XL 0x2a /* Accelerometer Y low byte */ -#define LSM9DS1_OUT_Y_H_XL 0x2b /* Accelerometer Y high byte */ -#define LSM9DS1_OUT_Z_L_XL 0x2c /* Accelerometer Z low byte */ -#define LSM9DS1_OUT_Z_H_XL 0x2d /* Accelerometer Z high byte */ -#define LSM9DS1_FIFO_CTRL 0x2e /* FIFO control register */ -#define LSM9DS1_FIFO_SRC 0x2f /* FIFO status control register */ -#define LSM9DS1_INT_GEN_CFG_G 0x30 /* Gyroscope interrupt configuration */ -#define LSM9DS1_INT_GEN_THS_XH_G 0x31 /* Gyroscope pitch (X) interrupt threshold high byte */ -#define LSM9DS1_INT_GEN_THS_XL_G 0x32 /* Gyroscope pitch (X) interrupt threshold low byte */ -#define LSM9DS1_INT_GEN_THS_YH_G 0x33 /* Gyroscope roll (Y) interrupt threshold high byte */ -#define LSM9DS1_INT_GEN_THS_YL_G 0x34 /* Gyroscope roll (Y) interrupt threshold low byte */ -#define LSM9DS1_INT_GEN_THS_ZH_G 0x35 /* Gyroscope yaw (Z) interrupt threshold high byte */ -#define LSM9DS1_INT_GEN_THS_ZL_G 0x36 /* Gyroscope yaw (Z) interrupt threshold low byte */ -#define LSM9DS1_INT_GEN_DUR_G 0x37 /* Gyroscope interrupt duration */ - -/* Magnetometer registers */ - -#define LSM9DS1_OFFSET_X_REG_L_M 0x05 /* X low byte offset */ -#define LSM9DS1_OFFSET_X_REG_H_M 0x06 /* X high byte offset */ -#define LSM9DS1_OFFSET_Y_REG_L_M 0x07 /* Y low byte offset */ -#define LSM9DS1_OFFSET_Y_REG_H_M 0x08 /* Y high byte offset */ -#define LSM9DS1_OFFSET_Z_REG_L_M 0x09 /* Z low byte offset */ -#define LSM9DS1_OFFSET_Z_REG_H_M 0x0a /* Z high byte offset */ -#define LSM9DS1_WHO_AM_I_M 0x0f /* Device identification */ -#define LSM9DS1_CTRL_REG1_M 0x20 /* Control register 1 */ -#define LSM9DS1_CTRL_REG2_M 0x21 /* Control register 2 */ -#define LSM9DS1_CTRL_REG3_M 0x22 /* Control register 3 */ -#define LSM9DS1_CTRL_REG4_M 0x23 /* Control register 4 */ -#define LSM9DS1_CTRL_REG5_M 0x24 /* Control register 5 */ -#define LSM9DS1_STATUS_REG_M 0x27 /* Status register */ -#define LSM9DS1_OUT_X_L_M 0x28 /* X low byte */ -#define LSM9DS1_OUT_X_H_M 0x29 /* X high byte */ -#define LSM9DS1_OUT_Y_L_M 0x2a /* Y low byte */ -#define LSM9DS1_OUT_Y_H_M 0x2b /* Y high byte */ -#define LSM9DS1_OUT_Z_L_M 0x2c /* Z low byte */ -#define LSM9DS1_OUT_Z_H_M 0x2d /* Z high byte */ -#define LSM9DS1_INT_CFG_M 0x30 /* Interrupt configuration */ -#define LSM9DS1_INT_SRC_M 0x31 /* Interrupt source */ -#define LSM9DS1_INT_THS_L_M 0x32 /* Interrupt threshold low byte */ -#define LSM9DS1_INT_THS_H_M 0x33 /* Interrupt threshold high byte */ - -/* Register Bit Definitions *************************************************/ - -/* Inactivity threshold register */ - -#define LSM9DS1_ACT_THS_ACT_THS_SHIFT 0 /* Inactivity threshold */ -#define LSM9DS1_ACT_THS_ACT_THS_MASK (127 << LSM9DS1_ACT_THS_ACT_THS_SHIFT) -#define LSM9DS1_ACT_THS_SLEEP_ON_INACT_EN (1 << 7) /* Gyroscope operating mode during inactivity */ - -/* Accelerometer interrupt configuration register */ - -#define LSM9DS1_INT_GEN_CFG_XL_XLIE_XL (1 << 0) /* X-axis low byte interrupt enable */ -#define LSM9DS1_INT_GEN_CFG_XL_XHIE_XL (1 << 1) /* X-axis high byte interrupt enable */ -#define LSM9DS1_INT_GEN_CFG_XL_YLIE_XL (1 << 2) /* Y-axis low byte interrupt enable */ -#define LSM9DS1_INT_GEN_CFG_XL_YHIE_XL (1 << 3) /* Y-axis high byte interrupt enable */ -#define LSM9DS1_INT_GEN_CFG_XL_ZLIE_XL (1 << 4) /* Z-axis low byte interrupt enable */ -#define LSM9DS1_INT_GEN_CFG_XL_ZHIE_XL (1 << 5) /* Z-axis high byte interrupt enable */ -#define LSM9DS1_INT_GEN_CFG_XL_6D (1 << 6) /* 6-direction detection function for interrupt */ -#define LSM9DS1_INT_GEN_CFG_XL_AOI_XL (1 << 7) /* AND/OR combination of interrupt events */ - -/* Accelerometer interrupt duration register */ - -#define LSM9DS1_INT_GEN_DUR_XL_DUR_XL_SHIFT 0 /* Enter/exit interrupt duration */ -#define LSM9DS1_INT_GEN_DUR_XL_DUR_XL_MASK (127 << LSM9DS1_INT_GEN_DUR_XL_DUR_XL_SHIFT) -#define LSM9DS1_INT_GEN_DUR_XL_WAIT_XL (1 << 7) /* Wait function enabled on duration counter */ - -/* INT1_A/G pin control register */ - -#define LSM9DS1_INT1_CTRL_INT1_DRDY_XL (1 << 0) /* Accelerometer data ready */ -#define LSM9DS1_INT1_CTRL_INT1_DRDY_G (1 << 1) /* Gyroscope data ready */ -#define LSM9DS1_INT1_CTRL_INT1_BOOT (1 << 2) /* Boot status available */ -#define LSM9DS1_INT1_CTRL_INT1_FTH (1 << 3) /* FIFO threshold interrupt */ -#define LSM9DS1_INT1_CTRL_INT1_OVR (1 << 4) /* Overrun interrupt */ -#define LSM9DS1_INT1_CTRL_INT1_FSS5 (1 << 5) /* FSS5 interrupt */ -#define LSM9DS1_INT1_CTRL_INT1_IG_XL (1 << 6) /* Accelerometer interrupt enable */ -#define LSM9DS1_INT1_CTRL_INT1_IG_G (1 << 7) /* Gyroscope interrupt enable */ - -/* INT2_A/G pin control register */ - -#define LSM9DS1_INT2_CTRL_INT2_DRDY_XL (1 << 0) /* Accelerometer data ready */ -#define LSM9DS1_INT2_CTRL_INT2_DRDY_G (1 << 1) /* Gyroscope data ready */ -#define LSM9DS1_INT2_CTRL_INT2_DRDY_TEMP (1 << 2) /* Temperature data ready */ -#define LSM9DS1_INT2_CTRL_INT2_FTH (1 << 3) /* FIFO threshold interrupt */ -#define LSM9DS1_INT2_CTRL_INT2_OVR (1 << 4) /* Overrun interrupt */ -#define LSM9DS1_INT2_CTRL_INT2_FSS5 (1 << 5) /* FSS5 interrupt */ -#define LSM9DS1_INT2_CTRL_INT2_INACT (1 << 7) /* Inactivity interrupt output signal */ - -/* Device identification register */ - -#define LSM9DS1_WHO_AM_I_VALUE 0x68 - -/* Gyroscope control register 1 */ - -#define LSM9DS1_CTRL_REG1_G_BW_G_SHIFT 0 /* Gyroscope bandwidth selection */ -#define LSM9DS1_CTRL_REG1_G_BW_G_MASK (3 << LSM9DS1_CTRL_REG1_G_BW_G_SHIFT) -#define LSM9DS1_CTRL_REG1_G_FS_G_SHIFT 3 /* Gyroscope full-scale selection */ -#define LSM9DS1_CTRL_REG1_G_FS_G_MASK (3 << LSM9DS1_CTRL_REG1_G_FS_G_SHIFT) -# define LSM9DS1_CTRL_REG1_G_FS_G_245DPS (0 << LSM9DS1_CTRL_REG1_G_FS_G_SHIFT) /* 245 dps */ -# define LSM9DS1_CTRL_REG1_G_FS_G_500DPS (1 << LSM9DS1_CTRL_REG1_G_FS_G_SHIFT) /* 500 dps */ -# define LSM9DS1_CTRL_REG1_G_FS_G_2000DPS (3 << LSM9DS1_CTRL_REG1_G_FS_G_SHIFT) /* 2000 dps */ - -#define LSM9DS1_CTRL_REG1_G_ODR_G_SHIFT 5 /* Gyroscope bandwidth selection */ -#define LSM9DS1_CTRL_REG1_G_ODR_G_MASK (7 << LSM9DS1_CTRL_REG1_G_ODR_G_SHIFT) -# define LSM9DS1_CTRL_REG1_G_ODR_G_POWERDOWN (0 << LSM9DS1_CTRL_REG1_G_ODR_G_SHIFT) /* Power-down mode */ -# define LSM9DS1_CTRL_REG1_G_ODR_G_14p9HZ (1 << LSM9DS1_CTRL_REG1_G_ODR_G_SHIFT) /* 14.9 Hz */ -# define LSM9DS1_CTRL_REG1_G_ODR_G_59p5HZ (2 << LSM9DS1_CTRL_REG1_G_ODR_G_SHIFT) /* 59.5 Hz */ -# define LSM9DS1_CTRL_REG1_G_ODR_G_119HZ (3 << LSM9DS1_CTRL_REG1_G_ODR_G_SHIFT) /* 119 Hz */ -# define LSM9DS1_CTRL_REG1_G_ODR_G_238HZ (4 << LSM9DS1_CTRL_REG1_G_ODR_G_SHIFT) /* 238 Hz */ -# define LSM9DS1_CTRL_REG1_G_ODR_G_476HZ (5 << LSM9DS1_CTRL_REG1_G_ODR_G_SHIFT) /* 476 Hz */ -# define LSM9DS1_CTRL_REG1_G_ODR_G_952HZ (6 << LSM9DS1_CTRL_REG1_G_ODR_G_SHIFT) /* 952 Hz */ - -/* Gyroscope control register 2 */ - -#define LSM9DS1_CTRL_REG2_G_OUT_SEL_SHIFT 0 /* Out selection configuration */ -#define LSM9DS1_CTRL_REG2_G_OUT_SEL_MASK (3 << LSM9DS1_CTRL_REG2_G_OUT_SEL_SHIFT) -#define LSM9DS1_CTRL_REG2_G_INT_SEL_SHIFT 2 /* INT selection configuration */ -#define LSM9DS1_CTRL_REG2_G_INT_SEL_MASK (3 << LSM9DS1_CTRL_REG2_G_INT_SEL_SHIFT) - -/* Gyroscope control register 3 */ - -#define LSM9DS1_CTRL_REG3_G_HPCF_G_SHIFT 0 /* Gyroscope high-pass filter cutoff frequency selection */ -#define LSM9DS1_CTRL_REG3_G_HPCF_G_MASK (15 << LSM9DS1_CTRL_REG3_G_HPCF_G_SHIFT) -#define LSM9DS1_CTRL_REG3_G_HP_EN (1 << 6) /* High-pass filter enable */ -#define LSM9DS1_CTRL_REG3_G_LP_MODE (1 << 7) /* Low-power mode enable */ - -/* Gyroscope sign and orientation register */ - -#define LSM9DS1_ORIENT_CFG_G_ORIENT_SHIFT 0 /* Directional user orientation selection */ -#define LSM9DS1_ORIENT_CFG_G_ORIENT_MASK (3 << LSM9DS1_ORIENT_CFG_G_ORIENT_SHIFT) -#define LSM9DS1_ORIENT_CFG_G_SIGNZ_G (1 << 3) /* Yaw axis (Z) angular rate sign */ -#define LSM9DS1_ORIENT_CFG_G_SIGNY_G (1 << 4) /* Roll axis (Y) angular rate sign */ -#define LSM9DS1_ORIENT_CFG_G_SIGNX_G (1 << 5) /* Pitch axis (X) angular rate sign */ - -/* Gyroscope interrupt source register */ - -#define LSM9DS1_INT_GEN_SRC_G_XL_G (1 << 0) /* Pitch (X) low */ -#define LSM9DS1_INT_GEN_SRC_G_XH_G (1 << 1) /* Pitch (X) high */ -#define LSM9DS1_INT_GEN_SRC_G_YL_G (1 << 2) /* Roll (Y) low */ -#define LSM9DS1_INT_GEN_SRC_G_YH_G (1 << 3) /* Roll (Y) high */ -#define LSM9DS1_INT_GEN_SRC_G_ZL_G (1 << 4) /* Yaw (Z) low */ -#define LSM9DS1_INT_GEN_SRC_G_ZH_G (1 << 5) /* Yaw (Z) high */ -#define LSM9DS1_INT_GEN_SRC_G_IA_G (1 << 6) /* Interrupt active */ - -/* Status register */ - -#define LSM9DS1_STATUS_REG_XLDA (1 << 0) /* Accelerometer new data available */ -#define LSM9DS1_STATUS_REG_GDA (1 << 1) /* Gyroscope new data available */ -#define LSM9DS1_STATUS_REG_TDA (1 << 2) /* Temperature sensor new data available */ -#define LSM9DS1_STATUS_REG_BOOT_STATUS (1 << 3) /* Boot running flag signal */ -#define LSM9DS1_STATUS_REG_INACT (1 << 4) /* Inactivity interrupt output signal */ -#define LSM9DS1_STATUS_REG_IG_G (1 << 5) /* Gyroscope interrupt output signal */ -#define LSM9DS1_STATUS_REG_IG_XL (1 << 6) /* Accelerometer interrupt output signal */ - -/* Control register 4 */ - -#define LSM9DS1_CTRL_REG4_4D_XL1 (1 << 0) /* 4D option enabled on interrupt */ -#define LSM9DS1_CTRL_REG4_LIR_XL1 (1 << 1) /* Latched interrupt */ -#define LSM9DS1_CTRL_REG4_XEN_G (1 << 3) /* Gyroscope's pitch axis (X) output enable */ -#define LSM9DS1_CTRL_REG4_YEN_G (1 << 4) /* Gyroscope's roll axis (Y) output enable */ -#define LSM9DS1_CTRL_REG4_ZEN_G (1 << 5) /* Gyroscope's yaw axis (Z) output enable */ - -/* Accelerometer control register 5 */ - -#define LSM9DS1_CTRL_REG5_XL_XEN_XL (1 << 3) /* Accelerometer's X-axis output enable */ -#define LSM9DS1_CTRL_REG5_XL_YEN_XL (1 << 4) /* Accelerometer's Y-axis output enable */ -#define LSM9DS1_CTRL_REG5_XL_ZEN_XL (1 << 5) /* Accelerometer's Z-axis output enable */ - -#define LSM9DS1_CTRL_REG5_XL_DEC_SHIFT 6 /* Decimation of acceleration data on OUT REG and FIFO */ -#define LSM9DS1_CTRL_REG5_XL_DEC_MASK (3 << LSM9DS1_CTRL_REG5_XL_DEC_SHIFT) -# define LSM9DS1_CTRL_REG5_XL_DEC_NODEC (0 << LSM9DS1_CTRL_REG5_XL_DEC_SHIFT) /* No decimation */ -# define LSM9DS1_CTRL_REG5_XL_DEC_2SAMPLES (1 << LSM9DS1_CTRL_REG5_XL_DEC_SHIFT) /* Update every 2 samples */ -# define LSM9DS1_CTRL_REG5_XL_DEC_4SAMPLES (2 << LSM9DS1_CTRL_REG5_XL_DEC_SHIFT) /* Update every 4 samples */ -# define LSM9DS1_CTRL_REG5_XL_DEC_8SAMPLES (3 << LSM9DS1_CTRL_REG5_XL_DEC_SHIFT) /* Update every 8 samples */ - -/* Accelerometer control register 6 */ - -#define LSM9DS1_CTRL_REG6_XL_BW_XL_SHIFT 0 /* Anti-aliasing filter bandwidth selection */ -#define LSM9DS1_CTRL_REG6_XL_BW_XL_MASK (3 << LSM9DS1_CTRL_REG6_XL_BW_XL_SHIFT) -# define LSM9DS1_CTRL_REG6_XL_BW_XL_408HZ (0 << LSM9DS1_CTRL_REG6_XL_BW_XL_SHIFT) /* 408 Hz */ -# define LSM9DS1_CTRL_REG6_XL_BW_XL_211HZ (1 << LSM9DS1_CTRL_REG6_XL_BW_XL_SHIFT) /* 211 Hz */ -# define LSM9DS1_CTRL_REG6_XL_BW_XL_105HZ (2 << LSM9DS1_CTRL_REG6_XL_BW_XL_SHIFT) /* 105 Hz */ -# define LSM9DS1_CTRL_REG6_XL_BW_XL_50HZ (3 << LSM9DS1_CTRL_REG6_XL_BW_XL_SHIFT) /* 50 Hz */ - -#define LSM9DS1_CTRL_REG6_XL_BW_SCAL_ODR (1 << 2) /* Bandwidth selection */ - -#define LSM9DS1_CTRL_REG6_XL_FS_XL_SHIFT 3 /* Accelerometer full-scale selection */ -#define LSM9DS1_CTRL_REG6_XL_FS_XL_MASK (3 << LSM9DS1_CTRL_REG6_XL_FS_XL_SHIFT) -# define LSM9DS1_CTRL_REG6_XL_FS_XL_2G (0 << LSM9DS1_CTRL_REG6_XL_FS_XL_SHIFT) /* +/- 2 g */ -# define LSM9DS1_CTRL_REG6_XL_FS_XL_16G (1 << LSM9DS1_CTRL_REG6_XL_FS_XL_SHIFT) /* +/- 16 g */ -# define LSM9DS1_CTRL_REG6_XL_FS_XL_4G (2 << LSM9DS1_CTRL_REG6_XL_FS_XL_SHIFT) /* +/- 4 g */ -# define LSM9DS1_CTRL_REG6_XL_FS_XL_8G (3 << LSM9DS1_CTRL_REG6_XL_FS_XL_SHIFT) /* +/- 8 g */ - -#define LSM9DS1_CTRL_REG6_XL_ODR_XL_SHIFT 5 /* Output data rate and power mode selection */ -#define LSM9DS1_CTRL_REG6_XL_ODR_XL_MASK (7 << LSM9DS1_CTRL_REG6_XL_ODR_XL_SHIFT) -# define LSM9DS1_CTRL_REG6_XL_ODR_XL_POWERDOWN (0 << LSM9DS1_CTRL_REG6_XL_ODR_XL_SHIFT) /* Power-down mode */ -# define LSM9DS1_CTRL_REG6_XL_ODR_XL_10HZ (1 << LSM9DS1_CTRL_REG6_XL_ODR_XL_SHIFT) /* 10 Hz */ -# define LSM9DS1_CTRL_REG6_XL_ODR_XL_50HZ (2 << LSM9DS1_CTRL_REG6_XL_ODR_XL_SHIFT) /* 50 Hz */ -# define LSM9DS1_CTRL_REG6_XL_ODR_XL_119HZ (3 << LSM9DS1_CTRL_REG6_XL_ODR_XL_SHIFT) /* 119 Hz */ -# define LSM9DS1_CTRL_REG6_XL_ODR_XL_238HZ (4 << LSM9DS1_CTRL_REG6_XL_ODR_XL_SHIFT) /* 238 Hz */ -# define LSM9DS1_CTRL_REG6_XL_ODR_XL_476HZ (5 << LSM9DS1_CTRL_REG6_XL_ODR_XL_SHIFT) /* 476 Hz */ -# define LSM9DS1_CTRL_REG6_XL_ODR_XL_952HZ (6 << LSM9DS1_CTRL_REG6_XL_ODR_XL_SHIFT) /* 952 Hz */ - -/* Accelerometer control register 7 */ - -#define LSM9DS1_CTRL_REG7_XL_HPIS1 (1 << 0) /* High-pass filter enabled */ -#define LSM9DS1_CTRL_REG7_XL_FDS (1 << 2) /* Filtered data selection */ - -#define LSM9DS1_CTRL_REG7_XL_DCF_SHIFT 5 /* Accelerometer digital filter cutoff frequency selection */ -#define LSM9DS1_CTRL_REG7_XL_DCF_MASK (3 << LSM9DS1_CTRL_REG7_XL_DCF_SHIFT) -# define LSM9DS1_CTRL_REG7_XL_DCF_ODR_DIV50 (0 << LSM9DS1_CTRL_REG7_XL_DCF_SHIFT) -# define LSM9DS1_CTRL_REG7_XL_DCF_ODR_DIV100 (1 << LSM9DS1_CTRL_REG7_XL_DCF_SHIFT) -# define LSM9DS1_CTRL_REG7_XL_DCF_ODR_DIV9 (2 << LSM9DS1_CTRL_REG7_XL_DCF_SHIFT) -# define LSM9DS1_CTRL_REG7_XL_DCF_ODR_DIV400 (3 << LSM9DS1_CTRL_REG7_XL_DCF_SHIFT) -#define LSM9DS1_CTRL_REG7_XL_HR (1 << 7) /* High resolution mode enable */ - -/* Control register 8 */ - -#define LSM9DS1_CTRL_REG8_SW_RESET (1 << 0) /* Software reset */ -#define LSM9DS1_CTRL_REG8_BLE (1 << 1) /* Big/little endian data selection */ -#define LSM9DS1_CTRL_REG8_IF_ADD_INC (1 << 2) /* Register address automatically incremented during a multibyte access */ -#define LSM9DS1_CTRL_REG8_SIM (1 << 3) /* SPI serial interface mode selection */ -#define LSM9DS1_CTRL_REG8_PP_OD (1 << 4) /* Push-pull/open-drain selection on the INT1_A/G and INT2_A/G pins */ -#define LSM9DS1_CTRL_REG8_H_LACTIVE (1 << 5) /* Interrupt activation level */ -#define LSM9DS1_CTRL_REG8_BDU (1 << 6) /* Block data update */ -#define LSM9DS1_CTRL_REG8_BOOT (1 << 7) /* Reboot memory content */ - -/* Control register 9 */ - -#define LSM9DS1_CTRL_REG9_STOP_ON_FTH (1 << 0) /* Enable FIFO threshold level use */ -#define LSM9DS1_CTRL_REG9_FIFO_EN (1 << 1) /* FIFO memory enable */ -#define LSM9DS1_CTRL_REG9_I2C_DISABLE (1 << 2) /* Disable I2C interface */ -#define LSM9DS1_CTRL_REG9_DRDY_MASK_BIT (1 << 3) /* Data available enable bit */ -#define LSM9DS1_CTRL_REG9_FIFO_TEMP_EN (1 << 4) /* Temperature data storage in FIFO enable */ -#define LSM9DS1_CTRL_REG9_SLEEP_G (1 << 6) /* Gyroscope sleep mode enable */ - -/* Control register 10 */ - -#define LSM9DS1_CTRL_REG10_ST_XL (1 << 0) /* Linear acceleration sensor self-test enable */ -#define LSM9DS1_CTRL_REG10_ST_G (1 << 2) /* Angular rate sensor self-test enable */ - -/* Accelerometer interrupt source register */ - -#define LSM9DS1_INT_GEN_SRC_XL_XL_XL (1 << 0) /* Accelerometer's X low event */ -#define LSM9DS1_INT_GEN_SRC_XL_XH_XL (1 << 1) /* Accelerometer's X high event */ -#define LSM9DS1_INT_GEN_SRC_XL_YL_XL (1 << 2) /* Accelerometer's Y low event */ -#define LSM9DS1_INT_GEN_SRC_XL_YH_XL (1 << 3) /* Accelerometer's Y high event */ -#define LSM9DS1_INT_GEN_SRC_XL_ZL_XL (1 << 4) /* Accelerometer's Z low event */ -#define LSM9DS1_INT_GEN_SRC_XL_ZH_XL (1 << 5) /* Accelerometer's Z high event */ -#define LSM9DS1_INT_GEN_SRC_XL_IA_XL (1 << 6) /* Interrupt active */ - -/* Status register 2 */ - -#define LSM9DS1_STATUS_REG2_XLDA (1 << 0) /* Accelerometer new data available */ -#define LSM9DS1_STATUS_REG2_GDA (1 << 1) /* Gyroscope new data available */ -#define LSM9DS1_STATUS_REG2_TDA (1 << 2) /* Temperature sensor new data available */ -#define LSM9DS1_STATUS_REG2_BOOT_STATUS (1 << 3) /* Boot running flag signal */ -#define LSM9DS1_STATUS_REG2_INACT (1 << 4) /* Inactivity interrupt output signal */ -#define LSM9DS1_STATUS_REG2_IG_G (1 << 5) /* Gyroscope interrupt output signal */ -#define LSM9DS1_STATUS_REG2_IG_XL (1 << 6) /* Accelerometer interrupt output signal */ - -/* FIFO control register */ - -#define LSM9DS1_FIFO_CTRL_FTH_SHIFT 0 /* FIFO threshold level setting */ -#define LSM9DS1_FIFO_CTRL_FTH_MASK (31 << LSM9DS1_FIFO_CTRL_FTH_SHIFT) -#define LSM9DS1_FIFO_CTRL_FMODE_SHIFT 5 /* FIFO mode selection bits */ -#define LSM9DS1_FIFO_CTRL_FMODE_MASK (7 << LSM9DS1_FIFO_CTRL_FMODE_SHIFT) -# define LSM9DS1_FIFO_CTRL_FMODE_BYPASS (0 << LSM9DS1_FIFO_CTRL_FMODE_SHIFT) /* Bypass mode */ -# define LSM9DS1_FIFO_CTRL_FMODE_FIFO (1 << LSM9DS1_FIFO_CTRL_FMODE_SHIFT) /* FIFO mode */ -# define LSM9DS1_FIFO_CTRL_FMODE_CONT_FIFO (3 << LSM9DS1_FIFO_CTRL_FMODE_SHIFT) /* Continuous-to-FIFO mode */ -# define LSM9DS1_FIFO_CTRL_FMODE_BYPASS_CONT (4 << LSM9DS1_FIFO_CTRL_FMODE_SHIFT) /* Bypass-to-continuous mode */ -# define LSM9DS1_FIFO_CTRL_FMODE_CONT (5 << LSM9DS1_FIFO_CTRL_FMODE_SHIFT) /* Continuous mode */ - -/* FIFO status control register */ - -#define LSM9DS1_FIFO_SRC_FSS_SHIFT 0 /* Number of unread samples stored into FIFO */ -#define LSM9DS1_FIFO_SRC_FSS_MASK (63 << LSM9DS1_FIFO_SRC_FSS_SHIFT) -#define LSM9DS1_FIFO_SRC_OVRN (1 << 6) /* FIFO overrun status */ -#define LSM9DS1_FIFO_SRC_FTH (1 << 7) /* FIFO threshold status */ - -/* Gyroscope interrupt configuration register */ - -#define LSM9DS1_INT_GEN_CFG_G_XLIE_G (1 << 0) /* Pitch (X) axis low event interrupt enable */ -#define LSM9DS1_INT_GEN_CFG_G_XHIE_G (1 << 1) /* Pitch (X) axis high event interrupt enable */ -#define LSM9DS1_INT_GEN_CFG_G_YLIE_G (1 << 2) /* Roll (Y) axis low event interrupt enable */ -#define LSM9DS1_INT_GEN_CFG_G_YHIE_G (1 << 3) /* Roll (Y) axis high event interrupt enable */ -#define LSM9DS1_INT_GEN_CFG_G_ZLIE_G (1 << 4) /* Yaw (Z) axis low event interrupt enable */ -#define LSM9DS1_INT_GEN_CFG_G_ZHIE_G (1 << 5) /* Yaw (Z) axis high event interrupt enable */ -#define LSM9DS1_INT_GEN_CFG_G_LIR_G (1 << 6) /* Latch interrupt request */ -#define LSM9DS1_INT_GEN_CFG_G_AOI_G (1 << 7) /* AND/OR combination of interrupt events */ - -/* Gyroscope interrupt threshold registers */ - -#define LSM9DS1_INT_GEN_THS_XH_G_THS_XH_G_SHIFT 0 /* X interrupt threshold high byte */ -#define LSM9DS1_INT_GEN_THS_XH_G_THS_XH_G_MASK (127 << LSM9DS1_INT_GEN_THS_XH_G_THS_XH_G_SHIFT) -#define LSM9DS1_INT_GEN_THS_XH_G_DCRM_G (1 << 7) /* Decrement or reset counter mode selection */ - -/* Gyroscope interrupt duration register */ - -#define LSM9DS1_INT_GEN_DUR_G_DUR_G_SHIFT 0 /* Enter/exit interrupt duration */ -#define LSM9DS1_INT_GEN_DUR_G_DUR_G_MASK (127 << LSM9DS1_INT_GEN_DUR_G_DUR_G_SHIFT) -#define LSM9DS1_INT_GEN_DUR_G_WAIT_G (1 << 7) /* Exit from interrupt wait function enable */ - -/* Device identification register */ - -#define LSM9DS1_WHO_AM_I_M_VALUE 0x3d - -/* Magnetometer control register 1 */ - -#define LSM9DS1_CTRL_REG1_M_ST (1 << 0) /* Self-test enable */ -#define LSM9DS1_CTRL_REG1_M_FAST_ODR (1 << 1) /* Enable data rates higher than 80 Hz */ - -#define LSM9DS1_CTRL_REG1_M_DO_SHIFT 2 /* Output data rate selection */ -#define LSM9DS1_CTRL_REG1_M_DO_MASK (7 << LSM9DS1_CTRL_REG1_M_DO_SHIFT) -# define LSM9DS1_CTRL_REG1_M_DO_0p625HZ (0 << LSM9DS1_CTRL_REG1_M_DO_SHIFT) /* 0.625 Hz */ -# define LSM9DS1_CTRL_REG1_M_DO_1p25HZ (1 << LSM9DS1_CTRL_REG1_M_DO_SHIFT) /* 1.25 Hz */ -# define LSM9DS1_CTRL_REG1_M_DO_2p5HZ (2 << LSM9DS1_CTRL_REG1_M_DO_SHIFT) /* 2.5 Hz */ -# define LSM9DS1_CTRL_REG1_M_DO_5HZ (3 << LSM9DS1_CTRL_REG1_M_DO_SHIFT) /* 5 Hz */ -# define LSM9DS1_CTRL_REG1_M_DO_10HZ (4 << LSM9DS1_CTRL_REG1_M_DO_SHIFT) /* 10 Hz */ -# define LSM9DS1_CTRL_REG1_M_DO_20HZ (5 << LSM9DS1_CTRL_REG1_M_DO_SHIFT) /* 20 Hz */ -# define LSM9DS1_CTRL_REG1_M_DO_40HZ (6 << LSM9DS1_CTRL_REG1_M_DO_SHIFT) /* 40 Hz */ -# define LSM9DS1_CTRL_REG1_M_DO_80HZ (7 << LSM9DS1_CTRL_REG1_M_DO_SHIFT) /* 80 Hz */ - -#define LSM9DS1_CTRL_REG1_M_OM_SHIFT 5 /* X and Y axes operative mode selection */ -#define LSM9DS1_CTRL_REG1_M_OM_MASK (3 << LSM9DS1_CTRL_REG1_M_OM_SHIFT) -# define LSM9DS1_CTRL_REG1_M_OM_LOW (0 << LSM9DS1_CTRL_REG1_M_OM_SHIFT) /* Low-power mode */ -# define LSM9DS1_CTRL_REG1_M_OM_MEDIUM (1 << LSM9DS1_CTRL_REG1_M_OM_SHIFT) /* Medium-performance mode */ -# define LSM9DS1_CTRL_REG1_M_OM_HIGH (2 << LSM9DS1_CTRL_REG1_M_OM_SHIFT) /* High-performance mode */ -# define LSM9DS1_CTRL_REG1_M_OM_ULTRAHIGH (3 << LSM9DS1_CTRL_REG1_M_OM_SHIFT) /* Ultra-high performance mode */ - -#define LSM9DS1_CTRL_REG1_M_TEMP_COMP (1 << 7) /* Temperature compensation enable */ - -/* Magnetometer control register 2 */ - -#define LSM9DS1_CTRL_REG2_M_SOFT_RST (1 << 2) /* Configuration register and user register reset */ -#define LSM9DS1_CTRL_REG2_M_REBOOT (1 << 3) /* Reboot memory content */ - -#define LSM9DS1_CTRL_REG2_M_FS_SHIFT 5 /* Full-scale configuration */ -#define LSM9DS1_CTRL_REG2_M_FS_MASK (3 << LSM9DS1_CTRL_REG2_M_FS_SHIFT) -# define LSM9DS1_CTRL_REG2_M_FS_4GAUSS (0 << LSM9DS1_CTRL_REG2_M_FS_SHIFT) /* +/- 4 gauss */ -# define LSM9DS1_CTRL_REG2_M_FS_8GAUSS (1 << LSM9DS1_CTRL_REG2_M_FS_SHIFT) /* +/- 8 gauss */ -# define LSM9DS1_CTRL_REG2_M_FS_12GAUSS (2 << LSM9DS1_CTRL_REG2_M_FS_SHIFT) /* +/- 12 gauss */ -# define LSM9DS1_CTRL_REG2_M_FS_16GAUSS (3 << LSM9DS1_CTRL_REG2_M_FS_SHIFT) /* +/- 16 gauss */ - -/* Magnetometer control register 3 */ - -#define LSM9DS1_CTRL_REG3_M_MD_SHIFT 0 /* Operating mode selection */ -#define LSM9DS1_CTRL_REG3_M_MD_MASK (3 << LSM9DS1_CTRL_REG3_M_MD_SHIFT) -# define LSM9DS1_CTRL_REG3_M_MD_CONT (0 << LSM9DS1_CTRL_REG3_M_MD_SHIFT) /* Continuous-conversion mode */ -# define LSM9DS1_CTRL_REG3_M_MD_SINGLE (1 << LSM9DS1_CTRL_REG3_M_MD_SHIFT) /* Single-conversion mode */ -# define LSM9DS1_CTRL_REG3_M_MD_POWERDOWN (2 << LSM9DS1_CTRL_REG3_M_MD_SHIFT) /* Power-down mode */ -# define LSM9DS1_CTRL_REG3_M_MD_POWERDOWN2 (3 << LSM9DS1_CTRL_REG3_M_MD_SHIFT) /* Power-down mode */ - -#define LSM9DS1_CTRL_REG3_M_SIM (1 << 2) /* SPI serial interface mode selection */ -#define LSM9DS1_CTRL_REG3_M_LP (1 << 5) /* Low-power mode configuration */ -#define LSM9DS1_CTRL_REG3_M_I2C_DISABLE (1 << 7) /* Disable I2C interface */ - -/* Magnetometer control register 4 */ - -#define LSM9DS1_CTRL_REG4_M_BLE (1 << 1) /* Big/little endian data selection */ - -#define LSM9DS1_CTRL_REG4_M_OMZ_SHIFT 2 /* Z-axis operative mode selection */ -#define LSM9DS1_CTRL_REG4_M_OMZ_MASK (3 << LSM9DS1_CTRL_REG4_M_OMZ_SHIFT) -# define LSM9DS1_CTRL_REG4_M_OMZ_LOW (0 << LSM9DS1_CTRL_REG4_M_OMZ_SHIFT) /* Low-power mode */ -# define LSM9DS1_CTRL_REG4_M_OMZ_MEDIUM (1 << LSM9DS1_CTRL_REG4_M_OMZ_SHIFT) /* Medium-performance mode */ -# define LSM9DS1_CTRL_REG4_M_OMZ_HIGH (2 << LSM9DS1_CTRL_REG4_M_OMZ_SHIFT) /* High-performance mode */ -# define LSM9DS1_CTRL_REG4_M_OMZ_ULTRAHIGH (3 << LSM9DS1_CTRL_REG4_M_OMZ_SHIFT) /* Ultra-high performance mode */ - -/* Magnetometer control register 5 */ - -#define LSM9DS1_CTRL_REG5_M_BDU (1 << 6) /* Block data update */ -#define LSM9DS1_CTRL_REG5_M_FAST_READ (1 << 7) /* Fast read enable */ - -/* Magnetometer status register */ - -#define LSM9DS1_STATUS_REG_M_XDA (1 << 0) /* X-axis new data available */ -#define LSM9DS1_STATUS_REG_M_YDA (1 << 1) /* Y-axis new data available */ -#define LSM9DS1_STATUS_REG_M_ZDA (1 << 2) /* Z-axis new data available */ -#define LSM9DS1_STATUS_REG_M_ZYXDA (1 << 3) /* X, Y and Z-axis new data available */ -#define LSM9DS1_STATUS_REG_M_XOR (1 << 4) /* X-axis data overrun */ -#define LSM9DS1_STATUS_REG_M_YOR (1 << 5) /* Y-axis data overrun */ -#define LSM9DS1_STATUS_REG_M_ZOR (1 << 6) /* Z-axis data overrun */ -#define LSM9DS1_STATUS_REG_M_ZYXOR (1 << 7) /* X, Y and Z-axis data overrun */ - -/* Magnetometer interrupt configuration register */ - -#define LSM9DS1_INT_CFG_M_IEN (1 << 0) /* Interrupt enable on the INT_M pin */ -#define LSM9DS1_INT_CFG_M_IEL (1 << 1) /* Latch interrupt request */ -#define LSM9DS1_INT_CFG_M_IEA (1 << 2) /* Interrupt active configuration on INT_MAG */ -#define LSM9DS1_INT_CFG_M_ZIEN (1 << 5) /* Z-axis interrupt enable */ -#define LSM9DS1_INT_CFG_M_YIEN (1 << 6) /* Y-axis interrupt enable */ -#define LSM9DS1_INT_CFG_M_XIEN (1 << 7) /* X-axis interrupt enable */ - -/* Magnetometer interrupt source register */ - -#define LSM9DS1_INT_SRC_M_INT (1 << 0) /* Interrupt occurred */ -#define LSM9DS1_INT_SRC_M_MROI (1 << 1) /* Internal measurement range overflow */ -#define LSM9DS1_INT_SRC_M_NTH_Z (1 << 2) /* Value on Z-axis exceeds threshold on negative side */ -#define LSM9DS1_INT_SRC_M_NTH_Y (1 << 3) /* Value on Y-axis exceeds threshold on negative side */ -#define LSM9DS1_INT_SRC_M_NTH_X (1 << 4) /* Value on X-axis exceeds threshold on negative side */ -#define LSM9DS1_INT_SRC_M_PTH_Z (1 << 5) /* Value on Z-axis exceeds threshold on positive side */ -#define LSM9DS1_INT_SRC_M_PTH_Y (1 << 6) /* Value on Y-axis exceeds threshold on positive side */ -#define LSM9DS1_INT_SRC_M_PTH_X (1 << 7) /* Value on X-axis exceeds threshold on positive side */ - -/**************************************************************************** - * Private Types - ****************************************************************************/ - -struct lsm9ds1_dev_s; -struct lsm9ds1_ops_s -{ - CODE int (*config)(FAR struct lsm9ds1_dev_s *priv); - CODE int (*start)(FAR struct lsm9ds1_dev_s *priv); - CODE int (*stop)(FAR struct lsm9ds1_dev_s *priv); - CODE int (*setsamplerate)(FAR struct lsm9ds1_dev_s *priv, - uint32_t samplerate); - CODE int (*setfullscale)(FAR struct lsm9ds1_dev_s *priv, - uint32_t fullscale); -}; - -struct lsm9ds1_dev_s -{ - FAR struct i2c_master_s *i2c; /* I2C interface */ - uint8_t addr; /* I2C address */ - - FAR const struct lsm9ds1_ops_s *ops; - - uint32_t samplerate; /* Output data rate */ - uint8_t datareg; /* Output data register of X low byte */ -}; - /**************************************************************************** * Private Function Prototypes ****************************************************************************/ -/* I2C Helpers */ - -static int lsm9ds1_readreg8(FAR struct lsm9ds1_dev_s *priv, uint8_t regaddr, - FAR uint8_t *regval); -static int lsm9ds1_writereg8(FAR struct lsm9ds1_dev_s *priv, uint8_t regaddr, - uint8_t regval); -static int lsm9ds1_modifyreg8(FAR struct lsm9ds1_dev_s *priv, - uint8_t regaddr, uint8_t clearbits, - uint8_t setbits); - -/* Other Helpers */ - -static uint32_t lsm9ds1_midpoint(uint32_t a, uint32_t b); - -/* Accelerometer Operations */ - -static int lsm9ds1accelgyro_config(FAR struct lsm9ds1_dev_s *priv); -static int lsm9ds1accel_start(FAR struct lsm9ds1_dev_s *priv); -static int lsm9ds1accel_stop(FAR struct lsm9ds1_dev_s *priv); -static int lsm9ds1accelgyro_setsamplerate(FAR struct lsm9ds1_dev_s *priv, - uint32_t samplerate); -static int lsm9ds1accel_setfullscale(FAR struct lsm9ds1_dev_s *priv, - uint32_t fullscale); - -/* Gyroscope Operations */ - -static int lsm9ds1gyro_start(FAR struct lsm9ds1_dev_s *priv); -static int lsm9ds1gyro_stop(FAR struct lsm9ds1_dev_s *priv); -static int lsm9ds1gyro_setfullscale(FAR struct lsm9ds1_dev_s *priv, - uint32_t fullscale); - -/* Magnetometer Operations */ - -static int lsm9ds1mag_config(FAR struct lsm9ds1_dev_s *priv); -static int lsm9ds1mag_start(FAR struct lsm9ds1_dev_s *priv); -static int lsm9ds1mag_stop(FAR struct lsm9ds1_dev_s *priv); -static int lsm9ds1mag_setfullscale(FAR struct lsm9ds1_dev_s *priv, - uint32_t fullscale); -static int lsm9ds1mag_setsamplerate(FAR struct lsm9ds1_dev_s *priv, - uint32_t samplerate); - /* Character Driver Methods */ static ssize_t lsm9ds1_read(FAR struct file *filep, FAR char *buffer, @@ -590,605 +62,10 @@ static const struct file_operations g_fops = lsm9ds1_ioctl, /* ioctl */ }; -static const struct lsm9ds1_ops_s g_lsm9ds1accel_ops = -{ - lsm9ds1accelgyro_config, - lsm9ds1accel_start, - lsm9ds1accel_stop, - lsm9ds1accelgyro_setsamplerate, - lsm9ds1accel_setfullscale, -}; - -static const struct lsm9ds1_ops_s g_lsm9ds1gyro_ops = -{ - lsm9ds1accelgyro_config, - lsm9ds1gyro_start, - lsm9ds1gyro_stop, - lsm9ds1accelgyro_setsamplerate, - lsm9ds1gyro_setfullscale, -}; - -static const struct lsm9ds1_ops_s g_lsm9ds1mag_ops = -{ - lsm9ds1mag_config, - lsm9ds1mag_start, - lsm9ds1mag_stop, - lsm9ds1mag_setsamplerate, - lsm9ds1mag_setfullscale, -}; - /**************************************************************************** * Private Functions ****************************************************************************/ -/**************************************************************************** - * Name: lsm9ds1_readreg8 - * - * Description: - * Read from an 8-bit register. - * - ****************************************************************************/ - -static int lsm9ds1_readreg8(FAR struct lsm9ds1_dev_s *priv, uint8_t regaddr, - FAR uint8_t *regval) -{ - struct i2c_config_s config; - int ret; - - /* Sanity check */ - - DEBUGASSERT(priv != NULL); - DEBUGASSERT(regval != NULL); - - /* Set up the I2C configuration */ - - config.frequency = CONFIG_LSM9DS1_I2C_FREQUENCY; - config.address = priv->addr; - config.addrlen = 7; - - /* Write the register address */ - - ret = i2c_write(priv->i2c, &config, ®addr, sizeof(regaddr)); - if (ret < 0) - { - snerr("ERROR: i2c_write failed: %d\n", ret); - return ret; - } - - /* Restart and read 8 bits from the register */ - - ret = i2c_read(priv->i2c, &config, regval, sizeof(*regval)); - if (ret < 0) - { - snerr("ERROR: i2c_read failed: %d\n", ret); - return ret; - } - - sninfo("addr: %02x value: %02x\n", regaddr, *regval); - return OK; -} - -/**************************************************************************** - * Name: lsm9ds1_writereg8 - * - * Description: - * Write to an 8-bit register. - * - ****************************************************************************/ - -static int lsm9ds1_writereg8(FAR struct lsm9ds1_dev_s *priv, uint8_t regaddr, - uint8_t regval) -{ - struct i2c_config_s config; - uint8_t buffer[2]; - int ret; - - /* Sanity check */ - - DEBUGASSERT(priv != NULL); - - /* Set up a 2-byte message to send */ - - buffer[0] = regaddr; - buffer[1] = regval; - - /* Set up the I2C configuration */ - - config.frequency = CONFIG_LSM9DS1_I2C_FREQUENCY; - config.address = priv->addr; - config.addrlen = 7; - - /* Write the register address followed by the data (no RESTART) */ - - ret = i2c_write(priv->i2c, &config, buffer, sizeof(buffer)); - if (ret < 0) - { - snerr("ERROR: i2c_write failed: %d\n", ret); - return ret; - } - - sninfo("addr: %02x value: %02x\n", regaddr, regval); - return OK; -} - -/**************************************************************************** - * Name: lsm9ds1_modifyreg8 - * - * Description: - * Modify an 8-bit register. - * - ****************************************************************************/ - -static int lsm9ds1_modifyreg8(FAR struct lsm9ds1_dev_s *priv, - uint8_t regaddr, - uint8_t clearbits, - uint8_t setbits) -{ - int ret; - uint8_t regval; - - /* Sanity check */ - - DEBUGASSERT(priv != NULL); - - ret = lsm9ds1_readreg8(priv, regaddr, ®val); - if (ret < 0) - { - snerr("ERROR: lsm9ds1_readreg8 failed: %d\n", ret); - return ret; - } - - regval &= ~clearbits; - regval |= setbits; - - ret = lsm9ds1_writereg8(priv, regaddr, regval); - if (ret < 0) - { - snerr("ERROR: lsm9ds1_writereg8 failed: %d\n", ret); - return ret; - } - - return OK; -} - -/**************************************************************************** - * Name: lsm9ds1_midpoint - * - * Description: - * Find the midpoint between two numbers. - * - ****************************************************************************/ - -static uint32_t lsm9ds1_midpoint(uint32_t a, uint32_t b) -{ - return (uint32_t)(((uint64_t)a + - (uint64_t)b + (uint64_t)1) / (uint64_t)2); -} - -/**************************************************************************** - * Name: lsm9ds1accelgyro_config - * - * Description: - * Configure the accelerometer and gyroscope. - * - ****************************************************************************/ - -static int lsm9ds1accelgyro_config(FAR struct lsm9ds1_dev_s *priv) -{ - int ret; - uint8_t regval; - - /* Sanity check */ - - DEBUGASSERT(priv != NULL); - - /* Get the device identification */ - - ret = lsm9ds1_readreg8(priv, LSM9DS1_WHO_AM_I, ®val); - if (ret < 0) - { - snerr("ERROR: lsm9ds1_readreg8 failed: %d\n", ret); - return ret; - } - - if (regval != LSM9DS1_WHO_AM_I_VALUE) - { - snerr("ERROR: Invalid device identification %02x\n", regval); - return -ENODEV; - } - - return OK; -} - -/**************************************************************************** - * Name: lsm9ds1accel_start - * - * Description: - * Start the accelerometer. - * - ****************************************************************************/ - -static int lsm9ds1accel_start(FAR struct lsm9ds1_dev_s *priv) -{ - uint8_t setbits; - - /* Sanity check */ - - DEBUGASSERT(priv != NULL); - - if (priv->samplerate < lsm9ds1_midpoint(10, 50)) - { - setbits = LSM9DS1_CTRL_REG6_XL_ODR_XL_10HZ; - } - else if (priv->samplerate < lsm9ds1_midpoint(50, 119)) - { - setbits = LSM9DS1_CTRL_REG6_XL_ODR_XL_50HZ; - } - else if (priv->samplerate < lsm9ds1_midpoint(119, 238)) - { - setbits = LSM9DS1_CTRL_REG6_XL_ODR_XL_119HZ; - } - else if (priv->samplerate < lsm9ds1_midpoint(238, 476)) - { - setbits = LSM9DS1_CTRL_REG6_XL_ODR_XL_238HZ; - } - else if (priv->samplerate < lsm9ds1_midpoint(476, 952)) - { - setbits = LSM9DS1_CTRL_REG6_XL_ODR_XL_476HZ; - } - else - { - setbits = LSM9DS1_CTRL_REG6_XL_ODR_XL_952HZ; - } - - return lsm9ds1_modifyreg8(priv, LSM9DS1_CTRL_REG6_XL, - LSM9DS1_CTRL_REG6_XL_ODR_XL_MASK, setbits); -} - -/**************************************************************************** - * Name: lsm9ds1accel_stop - * - * Description: - * Stop the accelerometer. - * - ****************************************************************************/ - -static int lsm9ds1accel_stop(FAR struct lsm9ds1_dev_s *priv) -{ - /* Sanity check */ - - DEBUGASSERT(priv != NULL); - - return lsm9ds1_modifyreg8(priv, LSM9DS1_CTRL_REG6_XL, - LSM9DS1_CTRL_REG6_XL_ODR_XL_MASK, - LSM9DS1_CTRL_REG6_XL_ODR_XL_POWERDOWN); -} - -/**************************************************************************** - * Name: lsm9ds1accelgyro_setsamplerate - * - * Description: - * Set the accelerometer or gyroscope's sample rate. - * - ****************************************************************************/ - -static int lsm9ds1accelgyro_setsamplerate(FAR struct lsm9ds1_dev_s *priv, - uint32_t samplerate) -{ - /* Sanity check */ - - DEBUGASSERT(priv != NULL); - - priv->samplerate = samplerate; - return OK; -} - -/**************************************************************************** - * Name: lsm9ds1accel_setfullscale - * - * Description: - * Set the accelerometer's full-scale range. - * - ****************************************************************************/ - -static int lsm9ds1accel_setfullscale(FAR struct lsm9ds1_dev_s *priv, - uint32_t fullscale) -{ - uint8_t setbits; - - /* Sanity check */ - - DEBUGASSERT(priv != NULL); - - if (fullscale < lsm9ds1_midpoint(2, 4)) - { - setbits = LSM9DS1_CTRL_REG6_XL_FS_XL_2G; - } - else if (fullscale < lsm9ds1_midpoint(4, 8)) - { - setbits = LSM9DS1_CTRL_REG6_XL_FS_XL_4G; - } - else if (fullscale < lsm9ds1_midpoint(8, 16)) - { - setbits = LSM9DS1_CTRL_REG6_XL_FS_XL_8G; - } - else - { - setbits = LSM9DS1_CTRL_REG6_XL_FS_XL_16G; - } - - return lsm9ds1_modifyreg8(priv, LSM9DS1_CTRL_REG6_XL, - LSM9DS1_CTRL_REG6_XL_FS_XL_MASK, setbits); -} - -/**************************************************************************** - * Name: lsm9ds1gyro_start - * - * Description: - * Start the gyroscope. - * - ****************************************************************************/ - -static int lsm9ds1gyro_start(FAR struct lsm9ds1_dev_s *priv) -{ - uint8_t setbits; - - /* Sanity check */ - - DEBUGASSERT(priv != NULL); - - if (priv->samplerate < lsm9ds1_midpoint(14, 59)) - { - setbits = LSM9DS1_CTRL_REG1_G_ODR_G_14p9HZ; - } - else if (priv->samplerate < lsm9ds1_midpoint(59, 119)) - { - setbits = LSM9DS1_CTRL_REG1_G_ODR_G_59p5HZ; - } - else if (priv->samplerate < lsm9ds1_midpoint(119, 238)) - { - setbits = LSM9DS1_CTRL_REG1_G_ODR_G_119HZ; - } - else if (priv->samplerate < lsm9ds1_midpoint(238, 476)) - { - setbits = LSM9DS1_CTRL_REG1_G_ODR_G_238HZ; - } - else if (priv->samplerate < lsm9ds1_midpoint(476, 952)) - { - setbits = LSM9DS1_CTRL_REG1_G_ODR_G_476HZ; - } - else - { - setbits = LSM9DS1_CTRL_REG1_G_ODR_G_952HZ; - } - - return lsm9ds1_modifyreg8(priv, LSM9DS1_CTRL_REG1_G, - LSM9DS1_CTRL_REG1_G_ODR_G_MASK, setbits); -} - -/**************************************************************************** - * Name: lsm9ds1gyro_stop - * - * Description: - * Stop the gyroscope. - * - ****************************************************************************/ - -static int lsm9ds1gyro_stop(FAR struct lsm9ds1_dev_s *priv) -{ - /* Sanity check */ - - DEBUGASSERT(priv != NULL); - - return lsm9ds1_modifyreg8(priv, LSM9DS1_CTRL_REG1_G, - LSM9DS1_CTRL_REG1_G_ODR_G_MASK, - LSM9DS1_CTRL_REG1_G_ODR_G_POWERDOWN); -} - -/**************************************************************************** - * Name: lsm9ds1gyro_setfullscale - * - * Description: - * Set the gyroscope's full-scale range. - * - ****************************************************************************/ - -static int lsm9ds1gyro_setfullscale(FAR struct lsm9ds1_dev_s *priv, - uint32_t fullscale) -{ - uint8_t setbits; - - /* Sanity check */ - - DEBUGASSERT(priv != NULL); - - if (fullscale < lsm9ds1_midpoint(245, 500)) - { - setbits = LSM9DS1_CTRL_REG1_G_FS_G_245DPS; - } - else if (fullscale < lsm9ds1_midpoint(500, 2000)) - { - setbits = LSM9DS1_CTRL_REG1_G_FS_G_500DPS; - } - else - { - setbits = LSM9DS1_CTRL_REG1_G_FS_G_2000DPS; - } - - return lsm9ds1_modifyreg8(priv, LSM9DS1_CTRL_REG1_G, - LSM9DS1_CTRL_REG1_G_FS_G_MASK, setbits); -} - -/**************************************************************************** - * Name: lsm9ds1mag_config - * - * Description: - * Configure the magnetometer. - * - ****************************************************************************/ - -static int lsm9ds1mag_config(FAR struct lsm9ds1_dev_s *priv) -{ - int ret; - uint8_t regval; - - /* Sanity check */ - - DEBUGASSERT(priv != NULL); - - /* Get the device identification */ - - ret = lsm9ds1_readreg8(priv, LSM9DS1_WHO_AM_I_M, ®val); - if (ret < 0) - { - snerr("ERROR: lsm9ds1_readreg8 failed: %d\n", ret); - return ret; - } - - if (regval != LSM9DS1_WHO_AM_I_M_VALUE) - { - snerr("ERROR: Invalid device identification %02x\n", regval); - return -ENODEV; - } - - return OK; -} - -/**************************************************************************** - * Name: lsm9ds1mag_start - * - * Description: - * Start the magnetometer. - * - ****************************************************************************/ - -static int lsm9ds1mag_start(FAR struct lsm9ds1_dev_s *priv) -{ - /* Sanity check */ - - DEBUGASSERT(priv != NULL); - - return lsm9ds1_modifyreg8(priv, LSM9DS1_CTRL_REG3_M, - LSM9DS1_CTRL_REG3_M_MD_MASK, - LSM9DS1_CTRL_REG3_M_MD_CONT); -} - -/**************************************************************************** - * Name: lsm9ds1mag_stop - * - * Description: - * Stop the magnetometer. - * - ****************************************************************************/ - -static int lsm9ds1mag_stop(FAR struct lsm9ds1_dev_s *priv) -{ - /* Sanity check */ - - DEBUGASSERT(priv != NULL); - - return lsm9ds1_modifyreg8(priv, LSM9DS1_CTRL_REG3_M, - LSM9DS1_CTRL_REG3_M_MD_MASK, - LSM9DS1_CTRL_REG3_M_MD_POWERDOWN2); -} - -/**************************************************************************** - * Name: lsm9ds1mag_setfullscale - * - * Description: - * Set the magnetometer's full-scale range. - * - ****************************************************************************/ - -static int lsm9ds1mag_setfullscale(FAR struct lsm9ds1_dev_s *priv, - uint32_t fullscale) -{ - uint8_t setbits; - - /* Sanity check */ - - DEBUGASSERT(priv != NULL); - - if (fullscale < lsm9ds1_midpoint(4, 8)) - { - setbits = LSM9DS1_CTRL_REG2_M_FS_4GAUSS; - } - else if (fullscale < lsm9ds1_midpoint(8, 12)) - { - setbits = LSM9DS1_CTRL_REG2_M_FS_8GAUSS; - } - else if (fullscale < lsm9ds1_midpoint(12, 16)) - { - setbits = LSM9DS1_CTRL_REG2_M_FS_12GAUSS; - } - else - { - setbits = LSM9DS1_CTRL_REG2_M_FS_16GAUSS; - } - - return lsm9ds1_modifyreg8(priv, LSM9DS1_CTRL_REG2_M, - LSM9DS1_CTRL_REG2_M_FS_MASK, setbits); -} - -/**************************************************************************** - * Name: lsm9ds1mag_setsamplerate - * - * Description: - * Set the magnetometer's sample rate. - * - ****************************************************************************/ - -static int lsm9ds1mag_setsamplerate(FAR struct lsm9ds1_dev_s *priv, - uint32_t samplerate) -{ - uint8_t setbits; - - /* Sanity check */ - - DEBUGASSERT(priv != NULL); - - /* The magnetometer can change its sample rate without exiting - * power-down mode, so we don't need to save the value for later, - * unlike the accelerometer and gyroscope. - */ - - if (samplerate < lsm9ds1_midpoint(0, 1)) - { - setbits = LSM9DS1_CTRL_REG1_M_DO_0p625HZ; - } - else if (samplerate < lsm9ds1_midpoint(1, 2)) - { - setbits = LSM9DS1_CTRL_REG1_M_DO_1p25HZ; - } - else if (samplerate < lsm9ds1_midpoint(2, 5)) - { - setbits = LSM9DS1_CTRL_REG1_M_DO_2p5HZ; - } - else if (samplerate < lsm9ds1_midpoint(5, 10)) - { - setbits = LSM9DS1_CTRL_REG1_M_DO_5HZ; - } - else if (samplerate < lsm9ds1_midpoint(10, 20)) - { - setbits = LSM9DS1_CTRL_REG1_M_DO_10HZ; - } - else if (samplerate < lsm9ds1_midpoint(20, 40)) - { - setbits = LSM9DS1_CTRL_REG1_M_DO_20HZ; - } - else if (samplerate < lsm9ds1_midpoint(40, 80)) - { - setbits = LSM9DS1_CTRL_REG1_M_DO_40HZ; - } - else - { - setbits = LSM9DS1_CTRL_REG1_M_DO_80HZ; - } - - return lsm9ds1_modifyreg8(priv, LSM9DS1_CTRL_REG1_M, - LSM9DS1_CTRL_REG1_M_DO_MASK, setbits); -} - /**************************************************************************** * Name: lsm9ds1_read * diff --git a/drivers/sensors/lsm9ds1_base.c b/drivers/sensors/lsm9ds1_base.c new file mode 100644 index 00000000000..43ce757a96c --- /dev/null +++ b/drivers/sensors/lsm9ds1_base.c @@ -0,0 +1,717 @@ +/**************************************************************************** + * drivers/sensors/lsm9ds1_base.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "lsm9ds1_base.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Accelerometer Operations */ + +static int lsm9ds1accelgyro_config(FAR struct lsm9ds1_dev_s *priv); +static int lsm9ds1accel_start(FAR struct lsm9ds1_dev_s *priv); +static int lsm9ds1accel_stop(FAR struct lsm9ds1_dev_s *priv); +static int lsm9ds1accelgyro_setsamplerate(FAR struct lsm9ds1_dev_s *priv, + uint32_t samplerate); +static int lsm9ds1accel_setfullscale(FAR struct lsm9ds1_dev_s *priv, + uint32_t fullscale); + +/* Gyroscope Operations */ + +static int lsm9ds1gyro_start(FAR struct lsm9ds1_dev_s *priv); +static int lsm9ds1gyro_stop(FAR struct lsm9ds1_dev_s *priv); +static int lsm9ds1gyro_setfullscale(FAR struct lsm9ds1_dev_s *priv, + uint32_t fullscale); + +/* Magnetometer Operations */ + +static int lsm9ds1mag_config(FAR struct lsm9ds1_dev_s *priv); +static int lsm9ds1mag_start(FAR struct lsm9ds1_dev_s *priv); +static int lsm9ds1mag_stop(FAR struct lsm9ds1_dev_s *priv); +static int lsm9ds1mag_setfullscale(FAR struct lsm9ds1_dev_s *priv, + uint32_t fullscale); +static int lsm9ds1mag_setsamplerate(FAR struct lsm9ds1_dev_s *priv, + uint32_t samplerate); + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +const struct lsm9ds1_ops_s g_lsm9ds1accel_ops = +{ + lsm9ds1accelgyro_config, + lsm9ds1accel_start, + lsm9ds1accel_stop, + lsm9ds1accelgyro_setsamplerate, + lsm9ds1accel_setfullscale, +}; + +const struct lsm9ds1_ops_s g_lsm9ds1gyro_ops = +{ + lsm9ds1accelgyro_config, + lsm9ds1gyro_start, + lsm9ds1gyro_stop, + lsm9ds1accelgyro_setsamplerate, + lsm9ds1gyro_setfullscale, +}; + +const struct lsm9ds1_ops_s g_lsm9ds1mag_ops = +{ + lsm9ds1mag_config, + lsm9ds1mag_start, + lsm9ds1mag_stop, + lsm9ds1mag_setsamplerate, + lsm9ds1mag_setfullscale, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lsm9ds1accelgyro_config + * + * Description: + * Configure the accelerometer and gyroscope. + * + ****************************************************************************/ + +static int lsm9ds1accelgyro_config(FAR struct lsm9ds1_dev_s *priv) +{ + uint8_t regval; + int ret; + + /* Sanity check */ + + DEBUGASSERT(priv != NULL); + + /* Get the device identification */ + + ret = lsm9ds1_readreg8(priv, LSM9DS1_WHO_AM_I, ®val); + if (ret < 0) + { + snerr("ERROR: lsm9ds1_readreg8 failed: %d\n", ret); + return ret; + } + + if (regval != LSM9DS1_WHO_AM_I_VALUE) + { + snerr("ERROR: Invalid device identification %02x\n", regval); + return -ENODEV; + } + + return OK; +} + +/**************************************************************************** + * Name: lsm9ds1accel_start + * + * Description: + * Start the accelerometer. + * + ****************************************************************************/ + +static int lsm9ds1accel_start(FAR struct lsm9ds1_dev_s *priv) +{ + uint8_t setbits; + + /* Sanity check */ + + DEBUGASSERT(priv != NULL); + + if (priv->samplerate < lsm9ds1_midpoint(10, 50)) + { + setbits = LSM9DS1_CTRL_REG6_XL_ODR_XL_10HZ; + } + else if (priv->samplerate < lsm9ds1_midpoint(50, 119)) + { + setbits = LSM9DS1_CTRL_REG6_XL_ODR_XL_50HZ; + } + else if (priv->samplerate < lsm9ds1_midpoint(119, 238)) + { + setbits = LSM9DS1_CTRL_REG6_XL_ODR_XL_119HZ; + } + else if (priv->samplerate < lsm9ds1_midpoint(238, 476)) + { + setbits = LSM9DS1_CTRL_REG6_XL_ODR_XL_238HZ; + } + else if (priv->samplerate < lsm9ds1_midpoint(476, 952)) + { + setbits = LSM9DS1_CTRL_REG6_XL_ODR_XL_476HZ; + } + else + { + setbits = LSM9DS1_CTRL_REG6_XL_ODR_XL_952HZ; + } + + return lsm9ds1_modifyreg8(priv, LSM9DS1_CTRL_REG6_XL, + LSM9DS1_CTRL_REG6_XL_ODR_XL_MASK, setbits); +} + +/**************************************************************************** + * Name: lsm9ds1accel_stop + * + * Description: + * Stop the accelerometer. + * + ****************************************************************************/ + +static int lsm9ds1accel_stop(FAR struct lsm9ds1_dev_s *priv) +{ + /* Sanity check */ + + DEBUGASSERT(priv != NULL); + + return lsm9ds1_modifyreg8(priv, LSM9DS1_CTRL_REG6_XL, + LSM9DS1_CTRL_REG6_XL_ODR_XL_MASK, + LSM9DS1_CTRL_REG6_XL_ODR_XL_POWERDOWN); +} + +/**************************************************************************** + * Name: lsm9ds1accelgyro_setsamplerate + * + * Description: + * Set the accelerometer or gyroscope's sample rate. + * + ****************************************************************************/ + +static int lsm9ds1accelgyro_setsamplerate(FAR struct lsm9ds1_dev_s *priv, + uint32_t samplerate) +{ + /* Sanity check */ + + DEBUGASSERT(priv != NULL); + + priv->samplerate = samplerate; + return OK; +} + +/**************************************************************************** + * Name: lsm9ds1accel_setfullscale + * + * Description: + * Set the accelerometer's full-scale range. + * + ****************************************************************************/ + +static int lsm9ds1accel_setfullscale(FAR struct lsm9ds1_dev_s *priv, + uint32_t fullscale) +{ + uint8_t setbits; + + /* Sanity check */ + + DEBUGASSERT(priv != NULL); + + if (fullscale < lsm9ds1_midpoint(2, 4)) + { + setbits = LSM9DS1_CTRL_REG6_XL_FS_XL_2G; + } + else if (fullscale < lsm9ds1_midpoint(4, 8)) + { + setbits = LSM9DS1_CTRL_REG6_XL_FS_XL_4G; + } + else if (fullscale < lsm9ds1_midpoint(8, 16)) + { + setbits = LSM9DS1_CTRL_REG6_XL_FS_XL_8G; + } + else + { + setbits = LSM9DS1_CTRL_REG6_XL_FS_XL_16G; + } + + return lsm9ds1_modifyreg8(priv, LSM9DS1_CTRL_REG6_XL, + LSM9DS1_CTRL_REG6_XL_FS_XL_MASK, setbits); +} + +/**************************************************************************** + * Name: lsm9ds1gyro_start + * + * Description: + * Start the gyroscope. + * + ****************************************************************************/ + +static int lsm9ds1gyro_start(FAR struct lsm9ds1_dev_s *priv) +{ + uint8_t setbits; + + /* Sanity check */ + + DEBUGASSERT(priv != NULL); + + if (priv->samplerate < lsm9ds1_midpoint(14, 59)) + { + setbits = LSM9DS1_CTRL_REG1_G_ODR_G_14p9HZ; + } + else if (priv->samplerate < lsm9ds1_midpoint(59, 119)) + { + setbits = LSM9DS1_CTRL_REG1_G_ODR_G_59p5HZ; + } + else if (priv->samplerate < lsm9ds1_midpoint(119, 238)) + { + setbits = LSM9DS1_CTRL_REG1_G_ODR_G_119HZ; + } + else if (priv->samplerate < lsm9ds1_midpoint(238, 476)) + { + setbits = LSM9DS1_CTRL_REG1_G_ODR_G_238HZ; + } + else if (priv->samplerate < lsm9ds1_midpoint(476, 952)) + { + setbits = LSM9DS1_CTRL_REG1_G_ODR_G_476HZ; + } + else + { + setbits = LSM9DS1_CTRL_REG1_G_ODR_G_952HZ; + } + + return lsm9ds1_modifyreg8(priv, LSM9DS1_CTRL_REG1_G, + LSM9DS1_CTRL_REG1_G_ODR_G_MASK, setbits); +} + +/**************************************************************************** + * Name: lsm9ds1gyro_stop + * + * Description: + * Stop the gyroscope. + * + ****************************************************************************/ + +static int lsm9ds1gyro_stop(FAR struct lsm9ds1_dev_s *priv) +{ + /* Sanity check */ + + DEBUGASSERT(priv != NULL); + + return lsm9ds1_modifyreg8(priv, LSM9DS1_CTRL_REG1_G, + LSM9DS1_CTRL_REG1_G_ODR_G_MASK, + LSM9DS1_CTRL_REG1_G_ODR_G_POWERDOWN); +} + +/**************************************************************************** + * Name: lsm9ds1gyro_setfullscale + * + * Description: + * Set the gyroscope's full-scale range. + * + ****************************************************************************/ + +static int lsm9ds1gyro_setfullscale(FAR struct lsm9ds1_dev_s *priv, + uint32_t fullscale) +{ + uint8_t setbits; + + /* Sanity check */ + + DEBUGASSERT(priv != NULL); + + if (fullscale < lsm9ds1_midpoint(245, 500)) + { + setbits = LSM9DS1_CTRL_REG1_G_FS_G_245DPS; + } + else if (fullscale < lsm9ds1_midpoint(500, 2000)) + { + setbits = LSM9DS1_CTRL_REG1_G_FS_G_500DPS; + } + else + { + setbits = LSM9DS1_CTRL_REG1_G_FS_G_2000DPS; + } + + return lsm9ds1_modifyreg8(priv, LSM9DS1_CTRL_REG1_G, + LSM9DS1_CTRL_REG1_G_FS_G_MASK, setbits); +} + +/**************************************************************************** + * Name: lsm9ds1mag_config + * + * Description: + * Configure the magnetometer. + * + ****************************************************************************/ + +static int lsm9ds1mag_config(FAR struct lsm9ds1_dev_s *priv) +{ + uint8_t regval; + int ret; + + /* Sanity check */ + + DEBUGASSERT(priv != NULL); + + /* Get the device identification */ + + ret = lsm9ds1_readreg8(priv, LSM9DS1_WHO_AM_I_M, ®val); + if (ret < 0) + { + snerr("ERROR: lsm9ds1_readreg8 failed: %d\n", ret); + return ret; + } + + if (regval != LSM9DS1_WHO_AM_I_M_VALUE) + { + snerr("ERROR: Invalid device identification %02x\n", regval); + return -ENODEV; + } + + return OK; +} + +/**************************************************************************** + * Name: lsm9ds1mag_start + * + * Description: + * Start the magnetometer. + * + ****************************************************************************/ + +static int lsm9ds1mag_start(FAR struct lsm9ds1_dev_s *priv) +{ + /* Sanity check */ + + DEBUGASSERT(priv != NULL); + + return lsm9ds1_modifyreg8(priv, LSM9DS1_CTRL_REG3_M, + LSM9DS1_CTRL_REG3_M_MD_MASK, + LSM9DS1_CTRL_REG3_M_MD_CONT); +} + +/**************************************************************************** + * Name: lsm9ds1mag_stop + * + * Description: + * Stop the magnetometer. + * + ****************************************************************************/ + +static int lsm9ds1mag_stop(FAR struct lsm9ds1_dev_s *priv) +{ + /* Sanity check */ + + DEBUGASSERT(priv != NULL); + + return lsm9ds1_modifyreg8(priv, LSM9DS1_CTRL_REG3_M, + LSM9DS1_CTRL_REG3_M_MD_MASK, + LSM9DS1_CTRL_REG3_M_MD_POWERDOWN2); +} + +/**************************************************************************** + * Name: lsm9ds1mag_setfullscale + * + * Description: + * Set the magnetometer's full-scale range. + * + ****************************************************************************/ + +static int lsm9ds1mag_setfullscale(FAR struct lsm9ds1_dev_s *priv, + uint32_t fullscale) +{ + uint8_t setbits; + + /* Sanity check */ + + DEBUGASSERT(priv != NULL); + + if (fullscale < lsm9ds1_midpoint(4, 8)) + { + setbits = LSM9DS1_CTRL_REG2_M_FS_4GAUSS; + } + else if (fullscale < lsm9ds1_midpoint(8, 12)) + { + setbits = LSM9DS1_CTRL_REG2_M_FS_8GAUSS; + } + else if (fullscale < lsm9ds1_midpoint(12, 16)) + { + setbits = LSM9DS1_CTRL_REG2_M_FS_12GAUSS; + } + else + { + setbits = LSM9DS1_CTRL_REG2_M_FS_16GAUSS; + } + + return lsm9ds1_modifyreg8(priv, LSM9DS1_CTRL_REG2_M, + LSM9DS1_CTRL_REG2_M_FS_MASK, setbits); +} + +/**************************************************************************** + * Name: lsm9ds1mag_setsamplerate + * + * Description: + * Set the magnetometer's sample rate. + * + ****************************************************************************/ + +static int lsm9ds1mag_setsamplerate(FAR struct lsm9ds1_dev_s *priv, + uint32_t samplerate) +{ + uint8_t setbits; + + /* Sanity check */ + + DEBUGASSERT(priv != NULL); + + /* The magnetometer can change its sample rate without exiting + * power-down mode, so we don't need to save the value for later, + * unlike the accelerometer and gyroscope. + */ + + if (samplerate < lsm9ds1_midpoint(0, 1)) + { + setbits = LSM9DS1_CTRL_REG1_M_DO_0p625HZ; + } + else if (samplerate < lsm9ds1_midpoint(1, 2)) + { + setbits = LSM9DS1_CTRL_REG1_M_DO_1p25HZ; + } + else if (samplerate < lsm9ds1_midpoint(2, 5)) + { + setbits = LSM9DS1_CTRL_REG1_M_DO_2p5HZ; + } + else if (samplerate < lsm9ds1_midpoint(5, 10)) + { + setbits = LSM9DS1_CTRL_REG1_M_DO_5HZ; + } + else if (samplerate < lsm9ds1_midpoint(10, 20)) + { + setbits = LSM9DS1_CTRL_REG1_M_DO_10HZ; + } + else if (samplerate < lsm9ds1_midpoint(20, 40)) + { + setbits = LSM9DS1_CTRL_REG1_M_DO_20HZ; + } + else if (samplerate < lsm9ds1_midpoint(40, 80)) + { + setbits = LSM9DS1_CTRL_REG1_M_DO_40HZ; + } + else + { + setbits = LSM9DS1_CTRL_REG1_M_DO_80HZ; + } + + return lsm9ds1_modifyreg8(priv, LSM9DS1_CTRL_REG1_M, + LSM9DS1_CTRL_REG1_M_DO_MASK, setbits); +} + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lsm9ds1_readreg8 + * + * Description: + * Read from an 8-bit register. + * + ****************************************************************************/ + +int lsm9ds1_readreg8(FAR struct lsm9ds1_dev_s *priv, + uint8_t regaddr, FAR uint8_t *regval) +{ + struct i2c_config_s config; + int ret; + + /* Sanity check */ + + DEBUGASSERT(priv != NULL); + DEBUGASSERT(regval != NULL); + + /* Set up the I2C configuration */ + + config.frequency = CONFIG_LSM9DS1_I2C_FREQUENCY; + config.address = priv->addr; + config.addrlen = 7; + + /* Write the register address */ + + ret = i2c_write(priv->i2c, &config, ®addr, sizeof(regaddr)); + if (ret < 0) + { + snerr("ERROR: i2c_write failed: %d\n", ret); + return ret; + } + + /* Restart and read 8 bits from the register */ + + ret = i2c_read(priv->i2c, &config, regval, sizeof(*regval)); + if (ret < 0) + { + snerr("ERROR: i2c_read failed: %d\n", ret); + return ret; + } + + sninfo("addr: %02x value: %02x\n", regaddr, *regval); + return OK; +} + +/**************************************************************************** + * Name: lsm9ds1_readreg + * + * Description: + * Read bytes from registers + * + ****************************************************************************/ + +int lsm9ds1_readreg(FAR struct lsm9ds1_dev_s *priv, + uint8_t regaddr, FAR uint8_t *regval, uint8_t len) +{ + struct i2c_config_s config; + int ret; + + /* Sanity check */ + + DEBUGASSERT(priv != NULL); + DEBUGASSERT(regval != NULL); + + /* Set up the I2C configuration */ + + config.frequency = CONFIG_LSM9DS1_I2C_FREQUENCY; + config.address = priv->addr; + config.addrlen = 7; + + /* Write the register address */ + + ret = i2c_write(priv->i2c, &config, ®addr, sizeof(regaddr)); + if (ret < 0) + { + snerr("ERROR: i2c_write failed: %d\n", ret); + return ret; + } + + /* Restart and read 8 bits from the register */ + + ret = i2c_read(priv->i2c, &config, regval, sizeof(*regval) * len); + if (ret < 0) + { + snerr("ERROR: i2c_read failed: %d\n", ret); + return ret; + } + + return OK; +} + +/**************************************************************************** + * Name: lsm9ds1_writereg8 + * + * Description: + * Write to an 8-bit register. + * + ****************************************************************************/ + +int lsm9ds1_writereg8(FAR struct lsm9ds1_dev_s *priv, + uint8_t regaddr, uint8_t regval) +{ + struct i2c_config_s config; + uint8_t buffer[2]; + int ret; + + /* Sanity check */ + + DEBUGASSERT(priv != NULL); + + /* Set up a 2-byte message to send */ + + buffer[0] = regaddr; + buffer[1] = regval; + + /* Set up the I2C configuration */ + + config.frequency = CONFIG_LSM9DS1_I2C_FREQUENCY; + config.address = priv->addr; + config.addrlen = 7; + + /* Write the register address followed by the data (no RESTART) */ + + ret = i2c_write(priv->i2c, &config, buffer, sizeof(buffer)); + if (ret < 0) + { + snerr("ERROR: i2c_write failed: %d\n", ret); + return ret; + } + + sninfo("addr: %02x value: %02x\n", regaddr, regval); + return OK; +} + +/**************************************************************************** + * Name: lsm9ds1_modifyreg8 + * + * Description: + * Modify an 8-bit register. + * + ****************************************************************************/ + +int lsm9ds1_modifyreg8(FAR struct lsm9ds1_dev_s *priv, + uint8_t regaddr, uint8_t clearbits, + uint8_t setbits) +{ + uint8_t regval; + int ret; + + /* Sanity check */ + + DEBUGASSERT(priv != NULL); + + ret = lsm9ds1_readreg8(priv, regaddr, ®val); + if (ret < 0) + { + snerr("ERROR: lsm9ds1_readreg8 failed: %d\n", ret); + return ret; + } + + regval &= ~clearbits; + regval |= setbits; + + ret = lsm9ds1_writereg8(priv, regaddr, regval); + if (ret < 0) + { + snerr("ERROR: lsm9ds1_writereg8 failed: %d\n", ret); + return ret; + } + + return OK; +} + +/**************************************************************************** + * Name: lsm9ds1_midpoint + * + * Description: + * Find the midpoint between two numbers. + * + ****************************************************************************/ + +uint32_t lsm9ds1_midpoint(uint32_t a, uint32_t b) +{ + return (uint32_t)(((uint64_t)a + + (uint64_t)b + (uint64_t)1) / (uint64_t)2); +} + diff --git a/drivers/sensors/lsm9ds1_base.h b/drivers/sensors/lsm9ds1_base.h new file mode 100644 index 00000000000..e972d65670e --- /dev/null +++ b/drivers/sensors/lsm9ds1_base.h @@ -0,0 +1,537 @@ +/**************************************************************************** + * drivers/sensors/lsm9ds1_base.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_SENSORS_LSM9DS1_COMMOM_H +#define __INCLUDE_NUTTX_SENSORS_LSM9DS1_COMMOM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register Addresses *******************************************************/ + +/* Accelerometer and gyroscope registers */ + +#define LSM9DS1_ACT_THS 0x04 /* Inactivity threshold */ +#define LSM9DS1_ACT_DUR 0x05 /* Inactivity duration */ +#define LSM9DS1_INT_GEN_CFG_XL 0x06 /* Accelerometer interrupt configuration */ +#define LSM9DS1_INT_GEN_THS_X_XL 0x07 /* Accelerometer X interrupt threshold */ +#define LSM9DS1_INT_GEN_THS_Y_XL 0x08 /* Accelerometer Y interrupt threshold */ +#define LSM9DS1_INT_GEN_THS_Z_XL 0x09 /* Accelerometer Z interrupt threshold */ +#define LSM9DS1_INT_GEN_DUR_XL 0x0a /* Accelerometer interrupt duration */ +#define LSM9DS1_REFERENCE_G 0x0b /* Gyroscope reference value for high-pass filter */ +#define LSM9DS1_INT1_CTRL 0x0c /* INT1_A/G pin control */ +#define LSM9DS1_INT2_CTRL 0x0d /* INT2_A/G pin control */ +#define LSM9DS1_WHO_AM_I 0x0f /* Accelerometer and gyroscope device identification */ +#define LSM9DS1_CTRL_REG1_G 0x10 /* Gyroscope control register 1 */ +#define LSM9DS1_CTRL_REG2_G 0x11 /* Gyroscope control register 2 */ +#define LSM9DS1_CTRL_REG3_G 0x12 /* Gyroscope control register 3 */ +#define LSM9DS1_ORIENT_CFG_G 0x13 /* Gyroscope sign and orientation */ +#define LSM9DS1_INT_GEN_SRC_G 0x14 /* Gyroscope interrupt source */ +#define LSM9DS1_OUT_TEMP_L 0x15 /* Temperature low byte */ +#define LSM9DS1_OUT_TEMP_H 0x16 /* Temperature high byte */ +#define LSM9DS1_STATUS_REG 0x17 /* Status register */ +#define LSM9DS1_OUT_X_L_G 0x18 /* Gyroscope pitch (X) low byte */ +#define LSM9DS1_OUT_X_H_G 0x19 /* Gyroscope pitch (X) high byte */ +#define LSM9DS1_OUT_Y_L_G 0x1a /* Gyroscope roll (Y) low byte */ +#define LSM9DS1_OUT_Y_H_G 0x1b /* Gyroscope roll (Y) high byte */ +#define LSM9DS1_OUT_Z_L_G 0x1c /* Gyroscope yaw (Z) low byte */ +#define LSM9DS1_OUT_Z_H_G 0x1d /* Gyroscope yaw (Z) high byte */ +#define LSM9DS1_CTRL_REG4 0x1e /* Control register 4 */ +#define LSM9DS1_CTRL_REG5_XL 0x1f /* Accelerometer control register 5 */ +#define LSM9DS1_CTRL_REG6_XL 0x20 /* Accelerometer control register 6 */ +#define LSM9DS1_CTRL_REG7_XL 0x21 /* Accelerometer control register 7 */ +#define LSM9DS1_CTRL_REG8 0x22 /* Control register 8 */ +#define LSM9DS1_CTRL_REG9 0x23 /* Control register 9 */ +#define LSM9DS1_CTRL_REG10 0x24 /* Control register 10 */ +#define LSM9DS1_INT_GEN_SRC_XL 0x26 /* Accelerometer interrupt source */ +#define LSM9DS1_STATUS_REG2 0x27 /* Status register 2 */ +#define LSM9DS1_OUT_X_L_XL 0x28 /* Accelerometer X low byte */ +#define LSM9DS1_OUT_X_H_XL 0x29 /* Accelerometer X high byte */ +#define LSM9DS1_OUT_Y_L_XL 0x2a /* Accelerometer Y low byte */ +#define LSM9DS1_OUT_Y_H_XL 0x2b /* Accelerometer Y high byte */ +#define LSM9DS1_OUT_Z_L_XL 0x2c /* Accelerometer Z low byte */ +#define LSM9DS1_OUT_Z_H_XL 0x2d /* Accelerometer Z high byte */ +#define LSM9DS1_FIFO_CTRL 0x2e /* FIFO control register */ +#define LSM9DS1_FIFO_SRC 0x2f /* FIFO status control register */ +#define LSM9DS1_INT_GEN_CFG_G 0x30 /* Gyroscope interrupt configuration */ +#define LSM9DS1_INT_GEN_THS_XH_G 0x31 /* Gyroscope pitch (X) interrupt threshold high byte */ +#define LSM9DS1_INT_GEN_THS_XL_G 0x32 /* Gyroscope pitch (X) interrupt threshold low byte */ +#define LSM9DS1_INT_GEN_THS_YH_G 0x33 /* Gyroscope roll (Y) interrupt threshold high byte */ +#define LSM9DS1_INT_GEN_THS_YL_G 0x34 /* Gyroscope roll (Y) interrupt threshold low byte */ +#define LSM9DS1_INT_GEN_THS_ZH_G 0x35 /* Gyroscope yaw (Z) interrupt threshold high byte */ +#define LSM9DS1_INT_GEN_THS_ZL_G 0x36 /* Gyroscope yaw (Z) interrupt threshold low byte */ +#define LSM9DS1_INT_GEN_DUR_G 0x37 /* Gyroscope interrupt duration */ + +/* Magnetometer registers */ + +#define LSM9DS1_OFFSET_X_REG_L_M 0x05 /* X low byte offset */ +#define LSM9DS1_OFFSET_X_REG_H_M 0x06 /* X high byte offset */ +#define LSM9DS1_OFFSET_Y_REG_L_M 0x07 /* Y low byte offset */ +#define LSM9DS1_OFFSET_Y_REG_H_M 0x08 /* Y high byte offset */ +#define LSM9DS1_OFFSET_Z_REG_L_M 0x09 /* Z low byte offset */ +#define LSM9DS1_OFFSET_Z_REG_H_M 0x0a /* Z high byte offset */ +#define LSM9DS1_WHO_AM_I_M 0x0f /* Device identification */ +#define LSM9DS1_CTRL_REG1_M 0x20 /* Control register 1 */ +#define LSM9DS1_CTRL_REG2_M 0x21 /* Control register 2 */ +#define LSM9DS1_CTRL_REG3_M 0x22 /* Control register 3 */ +#define LSM9DS1_CTRL_REG4_M 0x23 /* Control register 4 */ +#define LSM9DS1_CTRL_REG5_M 0x24 /* Control register 5 */ +#define LSM9DS1_STATUS_REG_M 0x27 /* Status register */ +#define LSM9DS1_OUT_X_L_M 0x28 /* X low byte */ +#define LSM9DS1_OUT_X_H_M 0x29 /* X high byte */ +#define LSM9DS1_OUT_Y_L_M 0x2a /* Y low byte */ +#define LSM9DS1_OUT_Y_H_M 0x2b /* Y high byte */ +#define LSM9DS1_OUT_Z_L_M 0x2c /* Z low byte */ +#define LSM9DS1_OUT_Z_H_M 0x2d /* Z high byte */ +#define LSM9DS1_INT_CFG_M 0x30 /* Interrupt configuration */ +#define LSM9DS1_INT_SRC_M 0x31 /* Interrupt source */ +#define LSM9DS1_INT_THS_L_M 0x32 /* Interrupt threshold low byte */ +#define LSM9DS1_INT_THS_H_M 0x33 /* Interrupt threshold high byte */ + +/* Register Bit Definitions *************************************************/ + +/* Inactivity threshold register */ + +#define LSM9DS1_ACT_THS_ACT_THS_SHIFT 0 /* Inactivity threshold */ +#define LSM9DS1_ACT_THS_ACT_THS_MASK (127 << LSM9DS1_ACT_THS_ACT_THS_SHIFT) +#define LSM9DS1_ACT_THS_SLEEP_ON_INACT_EN (1 << 7) /* Gyroscope operating mode during inactivity */ + +/* Accelerometer interrupt configuration register */ + +#define LSM9DS1_INT_GEN_CFG_XL_XLIE_XL (1 << 0) /* X-axis low byte interrupt enable */ +#define LSM9DS1_INT_GEN_CFG_XL_XHIE_XL (1 << 1) /* X-axis high byte interrupt enable */ +#define LSM9DS1_INT_GEN_CFG_XL_YLIE_XL (1 << 2) /* Y-axis low byte interrupt enable */ +#define LSM9DS1_INT_GEN_CFG_XL_YHIE_XL (1 << 3) /* Y-axis high byte interrupt enable */ +#define LSM9DS1_INT_GEN_CFG_XL_ZLIE_XL (1 << 4) /* Z-axis low byte interrupt enable */ +#define LSM9DS1_INT_GEN_CFG_XL_ZHIE_XL (1 << 5) /* Z-axis high byte interrupt enable */ +#define LSM9DS1_INT_GEN_CFG_XL_6D (1 << 6) /* 6-direction detection function for interrupt */ +#define LSM9DS1_INT_GEN_CFG_XL_AOI_XL (1 << 7) /* AND/OR combination of interrupt events */ + +/* Accelerometer interrupt duration register */ + +#define LSM9DS1_INT_GEN_DUR_XL_DUR_XL_SHIFT 0 /* Enter/exit interrupt duration */ +#define LSM9DS1_INT_GEN_DUR_XL_DUR_XL_MASK (127 << LSM9DS1_INT_GEN_DUR_XL_DUR_XL_SHIFT) +#define LSM9DS1_INT_GEN_DUR_XL_WAIT_XL (1 << 7) /* Wait function enabled on duration counter */ + +/* INT1_A/G pin control register */ + +#define LSM9DS1_INT1_CTRL_INT1_DRDY_XL (1 << 0) /* Accelerometer data ready */ +#define LSM9DS1_INT1_CTRL_INT1_DRDY_G (1 << 1) /* Gyroscope data ready */ +#define LSM9DS1_INT1_CTRL_INT1_BOOT (1 << 2) /* Boot status available */ +#define LSM9DS1_INT1_CTRL_INT1_FTH (1 << 3) /* FIFO threshold interrupt */ +#define LSM9DS1_INT1_CTRL_INT1_OVR (1 << 4) /* Overrun interrupt */ +#define LSM9DS1_INT1_CTRL_INT1_FSS5 (1 << 5) /* FSS5 interrupt */ +#define LSM9DS1_INT1_CTRL_INT1_IG_XL (1 << 6) /* Accelerometer interrupt enable */ +#define LSM9DS1_INT1_CTRL_INT1_IG_G (1 << 7) /* Gyroscope interrupt enable */ + +/* INT2_A/G pin control register */ + +#define LSM9DS1_INT2_CTRL_INT2_DRDY_XL (1 << 0) /* Accelerometer data ready */ +#define LSM9DS1_INT2_CTRL_INT2_DRDY_G (1 << 1) /* Gyroscope data ready */ +#define LSM9DS1_INT2_CTRL_INT2_DRDY_TEMP (1 << 2) /* Temperature data ready */ +#define LSM9DS1_INT2_CTRL_INT2_FTH (1 << 3) /* FIFO threshold interrupt */ +#define LSM9DS1_INT2_CTRL_INT2_OVR (1 << 4) /* Overrun interrupt */ +#define LSM9DS1_INT2_CTRL_INT2_FSS5 (1 << 5) /* FSS5 interrupt */ +#define LSM9DS1_INT2_CTRL_INT2_INACT (1 << 7) /* Inactivity interrupt output signal */ + +/* Device identification register */ + +#define LSM9DS1_WHO_AM_I_VALUE 0x68 + +/* Gyroscope control register 1 */ + +#define LSM9DS1_CTRL_REG1_G_BW_G_SHIFT 0 /* Gyroscope bandwidth selection */ +#define LSM9DS1_CTRL_REG1_G_BW_G_MASK (3 << LSM9DS1_CTRL_REG1_G_BW_G_SHIFT) +#define LSM9DS1_CTRL_REG1_G_FS_G_SHIFT 3 /* Gyroscope full-scale selection */ +#define LSM9DS1_CTRL_REG1_G_FS_G_MASK (3 << LSM9DS1_CTRL_REG1_G_FS_G_SHIFT) +# define LSM9DS1_CTRL_REG1_G_FS_G_245DPS (0 << LSM9DS1_CTRL_REG1_G_FS_G_SHIFT) /* 245 dps */ +# define LSM9DS1_CTRL_REG1_G_FS_G_500DPS (1 << LSM9DS1_CTRL_REG1_G_FS_G_SHIFT) /* 500 dps */ +# define LSM9DS1_CTRL_REG1_G_FS_G_2000DPS (3 << LSM9DS1_CTRL_REG1_G_FS_G_SHIFT) /* 2000 dps */ + +#define LSM9DS1_CTRL_REG1_G_ODR_G_SHIFT 5 /* Gyroscope bandwidth selection */ +#define LSM9DS1_CTRL_REG1_G_ODR_G_MASK (7 << LSM9DS1_CTRL_REG1_G_ODR_G_SHIFT) +# define LSM9DS1_CTRL_REG1_G_ODR_G_POWERDOWN (0 << LSM9DS1_CTRL_REG1_G_ODR_G_SHIFT) /* Power-down mode */ +# define LSM9DS1_CTRL_REG1_G_ODR_G_14p9HZ (1 << LSM9DS1_CTRL_REG1_G_ODR_G_SHIFT) /* 14.9 Hz */ +# define LSM9DS1_CTRL_REG1_G_ODR_G_59p5HZ (2 << LSM9DS1_CTRL_REG1_G_ODR_G_SHIFT) /* 59.5 Hz */ +# define LSM9DS1_CTRL_REG1_G_ODR_G_119HZ (3 << LSM9DS1_CTRL_REG1_G_ODR_G_SHIFT) /* 119 Hz */ +# define LSM9DS1_CTRL_REG1_G_ODR_G_238HZ (4 << LSM9DS1_CTRL_REG1_G_ODR_G_SHIFT) /* 238 Hz */ +# define LSM9DS1_CTRL_REG1_G_ODR_G_476HZ (5 << LSM9DS1_CTRL_REG1_G_ODR_G_SHIFT) /* 476 Hz */ +# define LSM9DS1_CTRL_REG1_G_ODR_G_952HZ (6 << LSM9DS1_CTRL_REG1_G_ODR_G_SHIFT) /* 952 Hz */ + +/* Gyroscope control register 2 */ + +#define LSM9DS1_CTRL_REG2_G_OUT_SEL_SHIFT 0 /* Out selection configuration */ +#define LSM9DS1_CTRL_REG2_G_OUT_SEL_MASK (3 << LSM9DS1_CTRL_REG2_G_OUT_SEL_SHIFT) +#define LSM9DS1_CTRL_REG2_G_INT_SEL_SHIFT 2 /* INT selection configuration */ +#define LSM9DS1_CTRL_REG2_G_INT_SEL_MASK (3 << LSM9DS1_CTRL_REG2_G_INT_SEL_SHIFT) + +/* Gyroscope control register 3 */ + +#define LSM9DS1_CTRL_REG3_G_HPCF_G_SHIFT 0 /* Gyroscope high-pass filter cutoff frequency selection */ +#define LSM9DS1_CTRL_REG3_G_HPCF_G_MASK (15 << LSM9DS1_CTRL_REG3_G_HPCF_G_SHIFT) +#define LSM9DS1_CTRL_REG3_G_HP_EN (1 << 6) /* High-pass filter enable */ +#define LSM9DS1_CTRL_REG3_G_LP_MODE (1 << 7) /* Low-power mode enable */ + +/* Gyroscope sign and orientation register */ + +#define LSM9DS1_ORIENT_CFG_G_ORIENT_SHIFT 0 /* Directional user orientation selection */ +#define LSM9DS1_ORIENT_CFG_G_ORIENT_MASK (3 << LSM9DS1_ORIENT_CFG_G_ORIENT_SHIFT) +#define LSM9DS1_ORIENT_CFG_G_SIGNZ_G (1 << 3) /* Yaw axis (Z) angular rate sign */ +#define LSM9DS1_ORIENT_CFG_G_SIGNY_G (1 << 4) /* Roll axis (Y) angular rate sign */ +#define LSM9DS1_ORIENT_CFG_G_SIGNX_G (1 << 5) /* Pitch axis (X) angular rate sign */ + +/* Gyroscope interrupt source register */ + +#define LSM9DS1_INT_GEN_SRC_G_XL_G (1 << 0) /* Pitch (X) low */ +#define LSM9DS1_INT_GEN_SRC_G_XH_G (1 << 1) /* Pitch (X) high */ +#define LSM9DS1_INT_GEN_SRC_G_YL_G (1 << 2) /* Roll (Y) low */ +#define LSM9DS1_INT_GEN_SRC_G_YH_G (1 << 3) /* Roll (Y) high */ +#define LSM9DS1_INT_GEN_SRC_G_ZL_G (1 << 4) /* Yaw (Z) low */ +#define LSM9DS1_INT_GEN_SRC_G_ZH_G (1 << 5) /* Yaw (Z) high */ +#define LSM9DS1_INT_GEN_SRC_G_IA_G (1 << 6) /* Interrupt active */ + +/* Status register */ + +#define LSM9DS1_STATUS_REG_XLDA (1 << 0) /* Accelerometer new data available */ +#define LSM9DS1_STATUS_REG_GDA (1 << 1) /* Gyroscope new data available */ +#define LSM9DS1_STATUS_REG_TDA (1 << 2) /* Temperature sensor new data available */ +#define LSM9DS1_STATUS_REG_BOOT_STATUS (1 << 3) /* Boot running flag signal */ +#define LSM9DS1_STATUS_REG_INACT (1 << 4) /* Inactivity interrupt output signal */ +#define LSM9DS1_STATUS_REG_IG_G (1 << 5) /* Gyroscope interrupt output signal */ +#define LSM9DS1_STATUS_REG_IG_XL (1 << 6) /* Accelerometer interrupt output signal */ + +/* Control register 4 */ + +#define LSM9DS1_CTRL_REG4_4D_XL1 (1 << 0) /* 4D option enabled on interrupt */ +#define LSM9DS1_CTRL_REG4_LIR_XL1 (1 << 1) /* Latched interrupt */ +#define LSM9DS1_CTRL_REG4_XEN_G (1 << 3) /* Gyroscope's pitch axis (X) output enable */ +#define LSM9DS1_CTRL_REG4_YEN_G (1 << 4) /* Gyroscope's roll axis (Y) output enable */ +#define LSM9DS1_CTRL_REG4_ZEN_G (1 << 5) /* Gyroscope's yaw axis (Z) output enable */ + +/* Accelerometer control register 5 */ + +#define LSM9DS1_CTRL_REG5_XL_XEN_XL (1 << 3) /* Accelerometer's X-axis output enable */ +#define LSM9DS1_CTRL_REG5_XL_YEN_XL (1 << 4) /* Accelerometer's Y-axis output enable */ +#define LSM9DS1_CTRL_REG5_XL_ZEN_XL (1 << 5) /* Accelerometer's Z-axis output enable */ + +#define LSM9DS1_CTRL_REG5_XL_DEC_SHIFT 6 /* Decimation of acceleration data on OUT REG and FIFO */ +#define LSM9DS1_CTRL_REG5_XL_DEC_MASK (3 << LSM9DS1_CTRL_REG5_XL_DEC_SHIFT) +# define LSM9DS1_CTRL_REG5_XL_DEC_NODEC (0 << LSM9DS1_CTRL_REG5_XL_DEC_SHIFT) /* No decimation */ +# define LSM9DS1_CTRL_REG5_XL_DEC_2SAMPLES (1 << LSM9DS1_CTRL_REG5_XL_DEC_SHIFT) /* Update every 2 samples */ +# define LSM9DS1_CTRL_REG5_XL_DEC_4SAMPLES (2 << LSM9DS1_CTRL_REG5_XL_DEC_SHIFT) /* Update every 4 samples */ +# define LSM9DS1_CTRL_REG5_XL_DEC_8SAMPLES (3 << LSM9DS1_CTRL_REG5_XL_DEC_SHIFT) /* Update every 8 samples */ + +/* Accelerometer control register 6 */ + +#define LSM9DS1_CTRL_REG6_XL_BW_XL_SHIFT 0 /* Anti-aliasing filter bandwidth selection */ +#define LSM9DS1_CTRL_REG6_XL_BW_XL_MASK (3 << LSM9DS1_CTRL_REG6_XL_BW_XL_SHIFT) +# define LSM9DS1_CTRL_REG6_XL_BW_XL_408HZ (0 << LSM9DS1_CTRL_REG6_XL_BW_XL_SHIFT) /* 408 Hz */ +# define LSM9DS1_CTRL_REG6_XL_BW_XL_211HZ (1 << LSM9DS1_CTRL_REG6_XL_BW_XL_SHIFT) /* 211 Hz */ +# define LSM9DS1_CTRL_REG6_XL_BW_XL_105HZ (2 << LSM9DS1_CTRL_REG6_XL_BW_XL_SHIFT) /* 105 Hz */ +# define LSM9DS1_CTRL_REG6_XL_BW_XL_50HZ (3 << LSM9DS1_CTRL_REG6_XL_BW_XL_SHIFT) /* 50 Hz */ + +#define LSM9DS1_CTRL_REG6_XL_BW_SCAL_ODR (1 << 2) /* Bandwidth selection */ + +#define LSM9DS1_CTRL_REG6_XL_FS_XL_SHIFT 3 /* Accelerometer full-scale selection */ +#define LSM9DS1_CTRL_REG6_XL_FS_XL_MASK (3 << LSM9DS1_CTRL_REG6_XL_FS_XL_SHIFT) +# define LSM9DS1_CTRL_REG6_XL_FS_XL_2G (0 << LSM9DS1_CTRL_REG6_XL_FS_XL_SHIFT) /* +/- 2 g */ +# define LSM9DS1_CTRL_REG6_XL_FS_XL_16G (1 << LSM9DS1_CTRL_REG6_XL_FS_XL_SHIFT) /* +/- 16 g */ +# define LSM9DS1_CTRL_REG6_XL_FS_XL_4G (2 << LSM9DS1_CTRL_REG6_XL_FS_XL_SHIFT) /* +/- 4 g */ +# define LSM9DS1_CTRL_REG6_XL_FS_XL_8G (3 << LSM9DS1_CTRL_REG6_XL_FS_XL_SHIFT) /* +/- 8 g */ + +#define LSM9DS1_CTRL_REG6_XL_ODR_XL_SHIFT 5 /* Output data rate and power mode selection */ +#define LSM9DS1_CTRL_REG6_XL_ODR_XL_MASK (7 << LSM9DS1_CTRL_REG6_XL_ODR_XL_SHIFT) +# define LSM9DS1_CTRL_REG6_XL_ODR_XL_POWERDOWN (0 << LSM9DS1_CTRL_REG6_XL_ODR_XL_SHIFT) /* Power-down mode */ +# define LSM9DS1_CTRL_REG6_XL_ODR_XL_10HZ (1 << LSM9DS1_CTRL_REG6_XL_ODR_XL_SHIFT) /* 10 Hz */ +# define LSM9DS1_CTRL_REG6_XL_ODR_XL_50HZ (2 << LSM9DS1_CTRL_REG6_XL_ODR_XL_SHIFT) /* 50 Hz */ +# define LSM9DS1_CTRL_REG6_XL_ODR_XL_119HZ (3 << LSM9DS1_CTRL_REG6_XL_ODR_XL_SHIFT) /* 119 Hz */ +# define LSM9DS1_CTRL_REG6_XL_ODR_XL_238HZ (4 << LSM9DS1_CTRL_REG6_XL_ODR_XL_SHIFT) /* 238 Hz */ +# define LSM9DS1_CTRL_REG6_XL_ODR_XL_476HZ (5 << LSM9DS1_CTRL_REG6_XL_ODR_XL_SHIFT) /* 476 Hz */ +# define LSM9DS1_CTRL_REG6_XL_ODR_XL_952HZ (6 << LSM9DS1_CTRL_REG6_XL_ODR_XL_SHIFT) /* 952 Hz */ + +/* Accelerometer control register 7 */ + +#define LSM9DS1_CTRL_REG7_XL_HPIS1 (1 << 0) /* High-pass filter enabled */ +#define LSM9DS1_CTRL_REG7_XL_FDS (1 << 2) /* Filtered data selection */ + +#define LSM9DS1_CTRL_REG7_XL_DCF_SHIFT 5 /* Accelerometer digital filter cutoff frequency selection */ +#define LSM9DS1_CTRL_REG7_XL_DCF_MASK (3 << LSM9DS1_CTRL_REG7_XL_DCF_SHIFT) +# define LSM9DS1_CTRL_REG7_XL_DCF_ODR_DIV50 (0 << LSM9DS1_CTRL_REG7_XL_DCF_SHIFT) +# define LSM9DS1_CTRL_REG7_XL_DCF_ODR_DIV100 (1 << LSM9DS1_CTRL_REG7_XL_DCF_SHIFT) +# define LSM9DS1_CTRL_REG7_XL_DCF_ODR_DIV9 (2 << LSM9DS1_CTRL_REG7_XL_DCF_SHIFT) +# define LSM9DS1_CTRL_REG7_XL_DCF_ODR_DIV400 (3 << LSM9DS1_CTRL_REG7_XL_DCF_SHIFT) +#define LSM9DS1_CTRL_REG7_XL_HR (1 << 7) /* High resolution mode enable */ + +/* Control register 8 */ + +#define LSM9DS1_CTRL_REG8_SW_RESET (1 << 0) /* Software reset */ +#define LSM9DS1_CTRL_REG8_BLE (1 << 1) /* Big/little endian data selection */ +#define LSM9DS1_CTRL_REG8_IF_ADD_INC (1 << 2) /* Register address automatically incremented during a multibyte access */ +#define LSM9DS1_CTRL_REG8_SIM (1 << 3) /* SPI serial interface mode selection */ +#define LSM9DS1_CTRL_REG8_PP_OD (1 << 4) /* Push-pull/open-drain selection on the INT1_A/G and INT2_A/G pins */ +#define LSM9DS1_CTRL_REG8_H_LACTIVE (1 << 5) /* Interrupt activation level */ +#define LSM9DS1_CTRL_REG8_BDU (1 << 6) /* Block data update */ +#define LSM9DS1_CTRL_REG8_BOOT (1 << 7) /* Reboot memory content */ + +/* Control register 9 */ + +#define LSM9DS1_CTRL_REG9_STOP_ON_FTH (1 << 0) /* Enable FIFO threshold level use */ +#define LSM9DS1_CTRL_REG9_FIFO_EN (1 << 1) /* FIFO memory enable */ +#define LSM9DS1_CTRL_REG9_I2C_DISABLE (1 << 2) /* Disable I2C interface */ +#define LSM9DS1_CTRL_REG9_DRDY_MASK_BIT (1 << 3) /* Data available enable bit */ +#define LSM9DS1_CTRL_REG9_FIFO_TEMP_EN (1 << 4) /* Temperature data storage in FIFO enable */ +#define LSM9DS1_CTRL_REG9_SLEEP_G (1 << 6) /* Gyroscope sleep mode enable */ + +/* Control register 10 */ + +#define LSM9DS1_CTRL_REG10_ST_XL (1 << 0) /* Linear acceleration sensor self-test enable */ +#define LSM9DS1_CTRL_REG10_ST_G (1 << 2) /* Angular rate sensor self-test enable */ + +/* Accelerometer interrupt source register */ + +#define LSM9DS1_INT_GEN_SRC_XL_XL_XL (1 << 0) /* Accelerometer's X low event */ +#define LSM9DS1_INT_GEN_SRC_XL_XH_XL (1 << 1) /* Accelerometer's X high event */ +#define LSM9DS1_INT_GEN_SRC_XL_YL_XL (1 << 2) /* Accelerometer's Y low event */ +#define LSM9DS1_INT_GEN_SRC_XL_YH_XL (1 << 3) /* Accelerometer's Y high event */ +#define LSM9DS1_INT_GEN_SRC_XL_ZL_XL (1 << 4) /* Accelerometer's Z low event */ +#define LSM9DS1_INT_GEN_SRC_XL_ZH_XL (1 << 5) /* Accelerometer's Z high event */ +#define LSM9DS1_INT_GEN_SRC_XL_IA_XL (1 << 6) /* Interrupt active */ + +/* Status register 2 */ + +#define LSM9DS1_STATUS_REG2_XLDA (1 << 0) /* Accelerometer new data available */ +#define LSM9DS1_STATUS_REG2_GDA (1 << 1) /* Gyroscope new data available */ +#define LSM9DS1_STATUS_REG2_TDA (1 << 2) /* Temperature sensor new data available */ +#define LSM9DS1_STATUS_REG2_BOOT_STATUS (1 << 3) /* Boot running flag signal */ +#define LSM9DS1_STATUS_REG2_INACT (1 << 4) /* Inactivity interrupt output signal */ +#define LSM9DS1_STATUS_REG2_IG_G (1 << 5) /* Gyroscope interrupt output signal */ +#define LSM9DS1_STATUS_REG2_IG_XL (1 << 6) /* Accelerometer interrupt output signal */ + +/* FIFO control register */ + +#define LSM9DS1_FIFO_CTRL_FTH_SHIFT 0 /* FIFO threshold level setting */ +#define LSM9DS1_FIFO_CTRL_FTH_MASK (31 << LSM9DS1_FIFO_CTRL_FTH_SHIFT) +#define LSM9DS1_FIFO_CTRL_FMODE_SHIFT 5 /* FIFO mode selection bits */ +#define LSM9DS1_FIFO_CTRL_FMODE_MASK (7 << LSM9DS1_FIFO_CTRL_FMODE_SHIFT) +# define LSM9DS1_FIFO_CTRL_FMODE_BYPASS (0 << LSM9DS1_FIFO_CTRL_FMODE_SHIFT) /* Bypass mode */ +# define LSM9DS1_FIFO_CTRL_FMODE_FIFO (1 << LSM9DS1_FIFO_CTRL_FMODE_SHIFT) /* FIFO mode */ +# define LSM9DS1_FIFO_CTRL_FMODE_CONT_FIFO (3 << LSM9DS1_FIFO_CTRL_FMODE_SHIFT) /* Continuous-to-FIFO mode */ +# define LSM9DS1_FIFO_CTRL_FMODE_BYPASS_CONT (4 << LSM9DS1_FIFO_CTRL_FMODE_SHIFT) /* Bypass-to-continuous mode */ +# define LSM9DS1_FIFO_CTRL_FMODE_CONT (5 << LSM9DS1_FIFO_CTRL_FMODE_SHIFT) /* Continuous mode */ + +/* FIFO status control register */ + +#define LSM9DS1_FIFO_SRC_FSS_SHIFT 0 /* Number of unread samples stored into FIFO */ +#define LSM9DS1_FIFO_SRC_FSS_MASK (63 << LSM9DS1_FIFO_SRC_FSS_SHIFT) +#define LSM9DS1_FIFO_SRC_OVRN (1 << 6) /* FIFO overrun status */ +#define LSM9DS1_FIFO_SRC_FTH (1 << 7) /* FIFO threshold status */ + +/* Gyroscope interrupt configuration register */ + +#define LSM9DS1_INT_GEN_CFG_G_XLIE_G (1 << 0) /* Pitch (X) axis low event interrupt enable */ +#define LSM9DS1_INT_GEN_CFG_G_XHIE_G (1 << 1) /* Pitch (X) axis high event interrupt enable */ +#define LSM9DS1_INT_GEN_CFG_G_YLIE_G (1 << 2) /* Roll (Y) axis low event interrupt enable */ +#define LSM9DS1_INT_GEN_CFG_G_YHIE_G (1 << 3) /* Roll (Y) axis high event interrupt enable */ +#define LSM9DS1_INT_GEN_CFG_G_ZLIE_G (1 << 4) /* Yaw (Z) axis low event interrupt enable */ +#define LSM9DS1_INT_GEN_CFG_G_ZHIE_G (1 << 5) /* Yaw (Z) axis high event interrupt enable */ +#define LSM9DS1_INT_GEN_CFG_G_LIR_G (1 << 6) /* Latch interrupt request */ +#define LSM9DS1_INT_GEN_CFG_G_AOI_G (1 << 7) /* AND/OR combination of interrupt events */ + +/* Gyroscope interrupt threshold registers */ + +#define LSM9DS1_INT_GEN_THS_XH_G_THS_XH_G_SHIFT 0 /* X interrupt threshold high byte */ +#define LSM9DS1_INT_GEN_THS_XH_G_THS_XH_G_MASK (127 << LSM9DS1_INT_GEN_THS_XH_G_THS_XH_G_SHIFT) +#define LSM9DS1_INT_GEN_THS_XH_G_DCRM_G (1 << 7) /* Decrement or reset counter mode selection */ + +/* Gyroscope interrupt duration register */ + +#define LSM9DS1_INT_GEN_DUR_G_DUR_G_SHIFT 0 /* Enter/exit interrupt duration */ +#define LSM9DS1_INT_GEN_DUR_G_DUR_G_MASK (127 << LSM9DS1_INT_GEN_DUR_G_DUR_G_SHIFT) +#define LSM9DS1_INT_GEN_DUR_G_WAIT_G (1 << 7) /* Exit from interrupt wait function enable */ + +/* Device identification register */ + +#define LSM9DS1_WHO_AM_I_M_VALUE 0x3d + +/* Magnetometer control register 1 */ + +#define LSM9DS1_CTRL_REG1_M_ST (1 << 0) /* Self-test enable */ +#define LSM9DS1_CTRL_REG1_M_FAST_ODR (1 << 1) /* Enable data rates higher than 80 Hz */ + +#define LSM9DS1_CTRL_REG1_M_DO_SHIFT 2 /* Output data rate selection */ +#define LSM9DS1_CTRL_REG1_M_DO_MASK (7 << LSM9DS1_CTRL_REG1_M_DO_SHIFT) +# define LSM9DS1_CTRL_REG1_M_DO_0p625HZ (0 << LSM9DS1_CTRL_REG1_M_DO_SHIFT) /* 0.625 Hz */ +# define LSM9DS1_CTRL_REG1_M_DO_1p25HZ (1 << LSM9DS1_CTRL_REG1_M_DO_SHIFT) /* 1.25 Hz */ +# define LSM9DS1_CTRL_REG1_M_DO_2p5HZ (2 << LSM9DS1_CTRL_REG1_M_DO_SHIFT) /* 2.5 Hz */ +# define LSM9DS1_CTRL_REG1_M_DO_5HZ (3 << LSM9DS1_CTRL_REG1_M_DO_SHIFT) /* 5 Hz */ +# define LSM9DS1_CTRL_REG1_M_DO_10HZ (4 << LSM9DS1_CTRL_REG1_M_DO_SHIFT) /* 10 Hz */ +# define LSM9DS1_CTRL_REG1_M_DO_20HZ (5 << LSM9DS1_CTRL_REG1_M_DO_SHIFT) /* 20 Hz */ +# define LSM9DS1_CTRL_REG1_M_DO_40HZ (6 << LSM9DS1_CTRL_REG1_M_DO_SHIFT) /* 40 Hz */ +# define LSM9DS1_CTRL_REG1_M_DO_80HZ (7 << LSM9DS1_CTRL_REG1_M_DO_SHIFT) /* 80 Hz */ + +#define LSM9DS1_CTRL_REG1_M_OM_SHIFT 5 /* X and Y axes operative mode selection */ +#define LSM9DS1_CTRL_REG1_M_OM_MASK (3 << LSM9DS1_CTRL_REG1_M_OM_SHIFT) +# define LSM9DS1_CTRL_REG1_M_OM_LOW (0 << LSM9DS1_CTRL_REG1_M_OM_SHIFT) /* Low-power mode */ +# define LSM9DS1_CTRL_REG1_M_OM_MEDIUM (1 << LSM9DS1_CTRL_REG1_M_OM_SHIFT) /* Medium-performance mode */ +# define LSM9DS1_CTRL_REG1_M_OM_HIGH (2 << LSM9DS1_CTRL_REG1_M_OM_SHIFT) /* High-performance mode */ +# define LSM9DS1_CTRL_REG1_M_OM_ULTRAHIGH (3 << LSM9DS1_CTRL_REG1_M_OM_SHIFT) /* Ultra-high performance mode */ + +#define LSM9DS1_CTRL_REG1_M_TEMP_COMP (1 << 7) /* Temperature compensation enable */ + +/* Magnetometer control register 2 */ + +#define LSM9DS1_CTRL_REG2_M_SOFT_RST (1 << 2) /* Configuration register and user register reset */ +#define LSM9DS1_CTRL_REG2_M_REBOOT (1 << 3) /* Reboot memory content */ + +#define LSM9DS1_CTRL_REG2_M_FS_SHIFT 5 /* Full-scale configuration */ +#define LSM9DS1_CTRL_REG2_M_FS_MASK (3 << LSM9DS1_CTRL_REG2_M_FS_SHIFT) +# define LSM9DS1_CTRL_REG2_M_FS_4GAUSS (0 << LSM9DS1_CTRL_REG2_M_FS_SHIFT) /* +/- 4 gauss */ +# define LSM9DS1_CTRL_REG2_M_FS_8GAUSS (1 << LSM9DS1_CTRL_REG2_M_FS_SHIFT) /* +/- 8 gauss */ +# define LSM9DS1_CTRL_REG2_M_FS_12GAUSS (2 << LSM9DS1_CTRL_REG2_M_FS_SHIFT) /* +/- 12 gauss */ +# define LSM9DS1_CTRL_REG2_M_FS_16GAUSS (3 << LSM9DS1_CTRL_REG2_M_FS_SHIFT) /* +/- 16 gauss */ + +/* Magnetometer control register 3 */ + +#define LSM9DS1_CTRL_REG3_M_MD_SHIFT 0 /* Operating mode selection */ +#define LSM9DS1_CTRL_REG3_M_MD_MASK (3 << LSM9DS1_CTRL_REG3_M_MD_SHIFT) +# define LSM9DS1_CTRL_REG3_M_MD_CONT (0 << LSM9DS1_CTRL_REG3_M_MD_SHIFT) /* Continuous-conversion mode */ +# define LSM9DS1_CTRL_REG3_M_MD_SINGLE (1 << LSM9DS1_CTRL_REG3_M_MD_SHIFT) /* Single-conversion mode */ +# define LSM9DS1_CTRL_REG3_M_MD_POWERDOWN (2 << LSM9DS1_CTRL_REG3_M_MD_SHIFT) /* Power-down mode */ +# define LSM9DS1_CTRL_REG3_M_MD_POWERDOWN2 (3 << LSM9DS1_CTRL_REG3_M_MD_SHIFT) /* Power-down mode */ + +#define LSM9DS1_CTRL_REG3_M_SIM (1 << 2) /* SPI serial interface mode selection */ +#define LSM9DS1_CTRL_REG3_M_LP (1 << 5) /* Low-power mode configuration */ +#define LSM9DS1_CTRL_REG3_M_I2C_DISABLE (1 << 7) /* Disable I2C interface */ + +/* Magnetometer control register 4 */ + +#define LSM9DS1_CTRL_REG4_M_BLE (1 << 1) /* Big/little endian data selection */ + +#define LSM9DS1_CTRL_REG4_M_OMZ_SHIFT 2 /* Z-axis operative mode selection */ +#define LSM9DS1_CTRL_REG4_M_OMZ_MASK (3 << LSM9DS1_CTRL_REG4_M_OMZ_SHIFT) +# define LSM9DS1_CTRL_REG4_M_OMZ_LOW (0 << LSM9DS1_CTRL_REG4_M_OMZ_SHIFT) /* Low-power mode */ +# define LSM9DS1_CTRL_REG4_M_OMZ_MEDIUM (1 << LSM9DS1_CTRL_REG4_M_OMZ_SHIFT) /* Medium-performance mode */ +# define LSM9DS1_CTRL_REG4_M_OMZ_HIGH (2 << LSM9DS1_CTRL_REG4_M_OMZ_SHIFT) /* High-performance mode */ +# define LSM9DS1_CTRL_REG4_M_OMZ_ULTRAHIGH (3 << LSM9DS1_CTRL_REG4_M_OMZ_SHIFT) /* Ultra-high performance mode */ + +/* Magnetometer control register 5 */ + +#define LSM9DS1_CTRL_REG5_M_BDU (1 << 6) /* Block data update */ +#define LSM9DS1_CTRL_REG5_M_FAST_READ (1 << 7) /* Fast read enable */ + +/* Magnetometer status register */ + +#define LSM9DS1_STATUS_REG_M_XDA (1 << 0) /* X-axis new data available */ +#define LSM9DS1_STATUS_REG_M_YDA (1 << 1) /* Y-axis new data available */ +#define LSM9DS1_STATUS_REG_M_ZDA (1 << 2) /* Z-axis new data available */ +#define LSM9DS1_STATUS_REG_M_ZYXDA (1 << 3) /* X, Y and Z-axis new data available */ +#define LSM9DS1_STATUS_REG_M_XOR (1 << 4) /* X-axis data overrun */ +#define LSM9DS1_STATUS_REG_M_YOR (1 << 5) /* Y-axis data overrun */ +#define LSM9DS1_STATUS_REG_M_ZOR (1 << 6) /* Z-axis data overrun */ +#define LSM9DS1_STATUS_REG_M_ZYXOR (1 << 7) /* X, Y and Z-axis data overrun */ + +/* Magnetometer interrupt configuration register */ + +#define LSM9DS1_INT_CFG_M_IEN (1 << 0) /* Interrupt enable on the INT_M pin */ +#define LSM9DS1_INT_CFG_M_IEL (1 << 1) /* Latch interrupt request */ +#define LSM9DS1_INT_CFG_M_IEA (1 << 2) /* Interrupt active configuration on INT_MAG */ +#define LSM9DS1_INT_CFG_M_ZIEN (1 << 5) /* Z-axis interrupt enable */ +#define LSM9DS1_INT_CFG_M_YIEN (1 << 6) /* Y-axis interrupt enable */ +#define LSM9DS1_INT_CFG_M_XIEN (1 << 7) /* X-axis interrupt enable */ + +/* Magnetometer interrupt source register */ + +#define LSM9DS1_INT_SRC_M_INT (1 << 0) /* Interrupt occurred */ +#define LSM9DS1_INT_SRC_M_MROI (1 << 1) /* Internal measurement range overflow */ +#define LSM9DS1_INT_SRC_M_NTH_Z (1 << 2) /* Value on Z-axis exceeds threshold on negative side */ +#define LSM9DS1_INT_SRC_M_NTH_Y (1 << 3) /* Value on Y-axis exceeds threshold on negative side */ +#define LSM9DS1_INT_SRC_M_NTH_X (1 << 4) /* Value on X-axis exceeds threshold on negative side */ +#define LSM9DS1_INT_SRC_M_PTH_Z (1 << 5) /* Value on Z-axis exceeds threshold on positive side */ +#define LSM9DS1_INT_SRC_M_PTH_Y (1 << 6) /* Value on Y-axis exceeds threshold on positive side */ +#define LSM9DS1_INT_SRC_M_PTH_X (1 << 7) /* Value on X-axis exceeds threshold on positive side */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +struct lsm9ds1_dev_s; +struct lsm9ds1_ops_s +{ + CODE int (*config)(FAR struct lsm9ds1_dev_s *priv); + CODE int (*start)(FAR struct lsm9ds1_dev_s *priv); + CODE int (*stop)(FAR struct lsm9ds1_dev_s *priv); + CODE int (*setsamplerate)(FAR struct lsm9ds1_dev_s *priv, + uint32_t samplerate); + CODE int (*setfullscale)(FAR struct lsm9ds1_dev_s *priv, + uint32_t fullscale); +}; + +struct lsm9ds1_dev_s +{ + FAR struct i2c_master_s *i2c; /* I2C interface */ + FAR const struct lsm9ds1_ops_s *ops; /* Ops */ + uint8_t addr; /* I2C address */ + uint32_t samplerate; /* Output data rate */ + uint8_t datareg; /* Output data register of X low byte */ +}; + +/**************************************************************************** + * Public data + ****************************************************************************/ + +extern const struct lsm9ds1_ops_s g_lsm9ds1accel_ops; +extern const struct lsm9ds1_ops_s g_lsm9ds1gyro_ops; +extern const struct lsm9ds1_ops_s g_lsm9ds1mag_ops; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +int lsm9ds1_readreg8(FAR struct lsm9ds1_dev_s *priv, + uint8_t regaddr, FAR uint8_t *regval); +int lsm9ds1_readreg(FAR struct lsm9ds1_dev_s *priv, + uint8_t regaddr, FAR uint8_t *regval, uint8_t len); +int lsm9ds1_writereg8(FAR struct lsm9ds1_dev_s *priv, + uint8_t regaddr, uint8_t regval); +int lsm9ds1_modifyreg8(FAR struct lsm9ds1_dev_s *priv, + uint8_t regaddr, uint8_t clearbits, + uint8_t setbits); +uint32_t lsm9ds1_midpoint(uint32_t a, uint32_t b); + +#endif /* __INCLUDE_NUTTX_SENSORS_LSM9DS1_COMMOM_H */ diff --git a/drivers/sensors/lsm9ds1_uorb.c b/drivers/sensors/lsm9ds1_uorb.c new file mode 100644 index 00000000000..6875d5b5830 --- /dev/null +++ b/drivers/sensors/lsm9ds1_uorb.c @@ -0,0 +1,803 @@ +/**************************************************************************** + * drivers/sensors/lsm9ds1_uorb.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "lsm9ds1_base.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define CONSTANTS_ONE_G 9.8f + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +enum lsm9ds1_idx_e +{ + LSM9DS1_ACCEL_IDX = 0, + LSM9DS1_GYRO_IDX, + LSM9DS1_MAG_IDX, + LSM9DS1_MAX_IDX +}; + +struct lsm9ds1_sensor_s +{ + struct sensor_lowerhalf_s lower; + uint64_t last_update; + float scale; + FAR void *dev; +#ifdef CONFIG_SENSORS_LSM9DS1_POLL + bool enabled; + unsigned long interval; +#endif + struct lsm9ds1_dev_s base; +}; + +struct lsm9ds1_sensor_dev_s +{ + struct lsm9ds1_sensor_s priv[3]; + mutex_t lock; +#ifdef CONFIG_SENSORS_LSM9DS1_POLL + sem_t run; +#endif +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Sensor methods */ + +static int lsm9ds1_activate(FAR struct sensor_lowerhalf_s *lower, + FAR struct file *filep, + bool enable); +static int lsm9ds1_set_interval(FAR struct sensor_lowerhalf_s *lower, + FAR struct file *filep, + FAR unsigned long *period_us); +#ifndef CONFIG_SENSORS_LSM9DS1_POLL +static int lsm9ds1_fetch(FAR struct sensor_lowerhalf_s *lower, + FAR struct file *filep, + FAR char *buffer, size_t buflen); +#endif +static int lsm9ds1_control(FAR struct sensor_lowerhalf_s *lower, + FAR struct file *filep, + int cmd, unsigned long arg); + +/* Helpers */ + +static int lsm9ds1_mag_scale(FAR struct lsm9ds1_sensor_s *priv, + uint8_t scale); +static int lsm9ds1_accel_scale(FAR struct lsm9ds1_sensor_s *priv, + uint8_t scale); +static int lsm9ds1_gyro_scale(FAR struct lsm9ds1_sensor_s *priv, + uint8_t scale); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct sensor_ops_s g_sensor_ops = +{ + NULL, /* open */ + NULL, /* close */ + .activate = lsm9ds1_activate, + .set_interval = lsm9ds1_set_interval, + NULL, /* batch */ +#ifdef CONFIG_SENSORS_LSM9DS1_POLL + NULL, /* fetch */ +#else + .fetch = lsm9ds1_fetch, +#endif + NULL, /* selftest */ + NULL, /* set_calibvalue */ + NULL, /* calibrate */ + .control = lsm9ds1_control +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lsm9ds1_activate + ****************************************************************************/ + +static int lsm9ds1_activate(FAR struct sensor_lowerhalf_s *lower, + FAR struct file *filep, bool enable) +{ +#ifdef CONFIG_SENSORS_LSM9DS1_POLL + FAR struct lsm9ds1_sensor_s *priv = NULL; + FAR struct lsm9ds1_sensor_dev_s *dev = NULL; + bool start_thread = false; + int ret = OK; + + priv = container_of(lower, struct lsm9ds1_sensor_s, lower); + dev = priv->dev; + + if (enable) + { + if (!priv->enabled) + { + start_thread = true; + priv->last_update = sensor_get_timestamp(); + } + + ret = priv->base.ops->start(&priv->base); + } + else + { + ret = priv->base.ops->stop(&priv->base); + } + + priv->enabled = enable; + + if (start_thread) + { + /* Wake up the thread */ + + nxsem_post(&dev->run); + } + + return ret; +#else + return OK; +#endif +} + +/**************************************************************************** + * Name: lsm9ds1_set_interval + ****************************************************************************/ + +static int lsm9ds1_set_interval(FAR struct sensor_lowerhalf_s *lower, + FAR struct file *filep, + FAR unsigned long *interval) +{ +#ifdef CONFIG_SENSORS_LSM9DS1_POLL + FAR struct lsm9ds1_sensor_s *priv = NULL; + + priv = container_of(lower, struct lsm9ds1_sensor_s, lower); + + priv->interval = *interval; +#endif + + return OK; +} + +/**************************************************************************** + * Name: lsm9ds1_data + ****************************************************************************/ + +static int16_t lsm9ds1_data(int16_t data) +{ + /* The value is positive */ + + if (data < 0x8000) + { + data = data; + } + + /* The value is negative, so find its absolute value by taking the + * two's complement + */ + + else if (data > 0x8000) + { + data = -(~data + 1); + } + + /* The value is negative and can't be represented as a positive + * int16_t value + */ + + else + { + data = -32768; + } + + return data; +} + +#ifndef CONFIG_SENSORS_LSM9DS1_POLL +/**************************************************************************** + * Name: lsm9ds1_set_interval + ****************************************************************************/ + +static int lsm9ds1_fetch(FAR struct sensor_lowerhalf_s *lower, + FAR struct file *filep, FAR char *buffer, + size_t buflen) +{ + FAR struct lsm9ds1_sensor_s *priv = NULL; + int16_t data[3]; + int ret = OK; + + priv = container_of(lower, struct lsm9ds1_sensor_s, lower); + + switch (lower->type) + { + case SENSOR_TYPE_ACCELEROMETER: + { + struct sensor_accel accel; + + ret = lsm9ds1_readreg(&priv->base, LSM9DS1_OUT_X_L_XL, + (FAR uint8_t *)data, 6); + + accel.timestamp = sensor_get_timestamp(); + accel.x = (int16_t)lsm9ds1_data(data[0]) * priv->scale; + accel.y = (int16_t)lsm9ds1_data(data[1]) * priv->scale; + accel.z = (int16_t)lsm9ds1_data(data[2]) * priv->scale; + + memcpy(buffer, &accel, sizeof(accel)); + + break; + } + + case SENSOR_TYPE_GYROSCOPE: + { + struct sensor_gyro gyro; + + ret = lsm9ds1_readreg(&priv->base, LSM9DS1_OUT_X_L_G, + (FAR uint8_t *)data, 6); + + gyro.timestamp = sensor_get_timestamp(); + gyro.x = (int16_t)lsm9ds1_data(data[0]) * priv->scale; + gyro.y = (int16_t)lsm9ds1_data(data[1]) * priv->scale; + gyro.z = (int16_t)lsm9ds1_data(data[2]) * priv->scale; + + memcpy(buffer, &gyro, sizeof(gyro)); + + break; + } + + case SENSOR_TYPE_MAGNETIC_FIELD: + { + struct sensor_mag mag; + + ret = lsm9ds1_readreg(&priv->base, LSM9DS1_OUT_X_L_M, + (FAR uint8_t *)data, 6); + + mag.timestamp = sensor_get_timestamp(); + mag.x = (int16_t)lsm9ds1_data(data[0]) * priv->scale; + mag.y = (int16_t)lsm9ds1_data(data[1]) * priv->scale; + mag.z = (int16_t)lsm9ds1_data(data[2]) * priv->scale; + + memcpy(buffer, &mag, sizeof(mag)); + + break; + } + + default: + { + ret = -EINVAL; + break; + } + } + + return ret; +} +#endif + +/**************************************************************************** + * Name: lsm9ds1_cotrol + ****************************************************************************/ + +static int lsm9ds1_control(FAR struct sensor_lowerhalf_s *lower, + FAR struct file *filep, int cmd, + unsigned long arg) +{ + FAR struct lsm9ds1_sensor_s *priv = NULL; + int ret = OK; + + priv = container_of(lower, struct lsm9ds1_sensor_s, lower); + + switch (cmd) + { + /* Set full scale command */ + + case SNIOC_SET_SCALE_XL: + { + if (priv->lower.type == SENSOR_TYPE_GYROSCOPE) + { + ret = lsm9ds1_gyro_scale(priv, arg); + } + else if (priv->lower.type == SENSOR_TYPE_ACCELEROMETER) + { + ret = lsm9ds1_accel_scale(priv, arg); + } + else if (priv->lower.type == SENSOR_TYPE_MAGNETIC_FIELD) + { + ret = lsm9ds1_mag_scale(priv, arg); + } + + break; + } + + default: + { + snerr("ERROR: Unrecognized cmd: %d\n", cmd); + ret = -ENOTTY; + break; + } + } + + return ret; +} + +/**************************************************************************** + * Name: lsm9ds1_mag_scale + ****************************************************************************/ + +static int lsm9ds1_mag_scale(FAR struct lsm9ds1_sensor_s *priv, + uint8_t scale) +{ + int ret = OK; + + ret = priv->base.ops->setfullscale(&priv->base, scale); + if (ret < 0) + { + return ret; + } + + if (scale < lsm9ds1_midpoint(4, 8)) + { + priv->scale = 8.f / 65536.f; + } + else if (scale < lsm9ds1_midpoint(8, 12)) + { + priv->scale = 16.f / 65536.f; + } + else if (scale < lsm9ds1_midpoint(12, 16)) + { + priv->scale = 24.f / 65536.f; + } + else + { + priv->scale = 32.f / 65536.f; + } + + return ret; +} + +/**************************************************************************** + * Name: lsm9ds1_accel_scale + ****************************************************************************/ + +static int lsm9ds1_accel_scale(FAR struct lsm9ds1_sensor_s *priv, + uint8_t scale) +{ + int ret = OK; + + ret = priv->base.ops->setfullscale(&priv->base, scale); + if (ret < 0) + { + return ret; + } + + if (scale < lsm9ds1_midpoint(2, 4)) + { + priv->scale = CONSTANTS_ONE_G / 16384.f; + } + else if (scale < lsm9ds1_midpoint(4, 8)) + { + priv->scale = CONSTANTS_ONE_G / 8192.f; + } + else if (scale < lsm9ds1_midpoint(8, 16)) + { + priv->scale = CONSTANTS_ONE_G / 4096.f; + } + else + { + priv->scale = CONSTANTS_ONE_G / 2048.f; + } + + return ret; +} + +/**************************************************************************** + * Name: lsm9ds1_gyro_scale + ****************************************************************************/ + +static int lsm9ds1_gyro_scale(FAR struct lsm9ds1_sensor_s *priv, + uint8_t scale) +{ + int ret = OK; + + ret = priv->base.ops->setfullscale(&priv->base, scale); + if (ret < 0) + { + return ret; + } + + if (scale < lsm9ds1_midpoint(245, 500)) + { + priv->scale = (M_PI / 180.0f) * 245.f / 32768.f; + } + else if (scale < lsm9ds1_midpoint(500, 2000)) + { + priv->scale = (M_PI / 180.0f) * 500.f / 32768.f; + } + else + { + priv->scale = (M_PI / 180.0f) * 2000.f / 32768.f; + } + + return ret; +} + +#ifdef CONFIG_SENSORS_LSM9DS1_POLL +/**************************************************************************** + * Name: lsm9ds1_accel_data + * + * Description: get and push accel data from struct sensor_data_s + * + * Parameter: + * priv - Internal private lower half driver instance + * buf - Point to data + * + * Return: + * OK - on success + * + ****************************************************************************/ + +static void lsm9ds1_accel_data(FAR struct lsm9ds1_sensor_s *priv, + FAR int16_t *buf) +{ + FAR struct sensor_lowerhalf_s *lower = &priv->lower; + struct sensor_accel accel; + uint64_t now = sensor_get_timestamp(); + + if (!priv->enabled || now - priv->last_update < priv->interval) + { + return; + } + + priv->last_update = now; + + accel.timestamp = now; + accel.x = (int16_t)lsm9ds1_data(buf[0]) * priv->scale; + accel.y = (int16_t)lsm9ds1_data(buf[1]) * priv->scale; + accel.z = (int16_t)lsm9ds1_data(buf[2]) * priv->scale; + accel.temperature = 0; + + lower->push_event(lower->priv, &accel, sizeof(accel)); +} + +/**************************************************************************** + * Name: lsm9ds1_gyro_data + * + * Description: get and push gyro data from struct sensor_data_s + * + * Parameter: + * priv - Internal private lower half driver instance + * buf - Point to data + * + * Return: + * OK - on success + * + ****************************************************************************/ + +static void lsm9ds1_gyro_data(FAR struct lsm9ds1_sensor_s *priv, + FAR int16_t *buf) +{ + FAR struct sensor_lowerhalf_s *lower = &priv->lower; + struct sensor_gyro gyro; + uint64_t now = sensor_get_timestamp(); + + if (!priv->enabled || now - priv->last_update < priv->interval) + { + return; + } + + priv->last_update = now; + + gyro.timestamp = now; + gyro.x = (int16_t)lsm9ds1_data(buf[0]) * priv->scale; + gyro.y = (int16_t)lsm9ds1_data(buf[1]) * priv->scale; + gyro.z = (int16_t)lsm9ds1_data(buf[2]) * priv->scale; + gyro.temperature = 0; + + lower->push_event(lower->priv, &gyro, sizeof(gyro)); +} + +/**************************************************************************** + * Name: lsm9ds1_mag_data + * + * Description: get and push magnetometer data from struct sensor_data_s + * + * Parameter: + * priv - Internal private lower half driver instance + * buf - Point to data + * + * Return: + * OK - on success + * + ****************************************************************************/ + +static void lsm9ds1_mag_data(FAR struct lsm9ds1_sensor_s *priv, + FAR int16_t *buf) +{ + FAR struct sensor_lowerhalf_s *lower = &priv->lower; + struct sensor_mag mag; + uint64_t now = sensor_get_timestamp(); + + if (!priv->enabled || now - priv->last_update < priv->interval) + { + return; + } + + priv->last_update = now; + + mag.timestamp = now; + mag.x = (int16_t)lsm9ds1_data(buf[0]) * priv->scale; + mag.y = (int16_t)lsm9ds1_data(buf[1]) * priv->scale; + mag.z = (int16_t)lsm9ds1_data(buf[2]) * priv->scale; + mag.temperature = 0; + + lower->push_event(lower->priv, &mag, sizeof(mag)); +} + +/**************************************************************************** + * Name: lsm9ds1_thread + * + * Description: Thread for performing interval measurement cycle and data + * read. + * + * Parameter: + * argc - Number opf arguments + * argv - Pointer to argument list + * + ****************************************************************************/ + +static int lsm9ds1_thread(int argc, FAR char **argv) +{ + FAR struct lsm9ds1_sensor_dev_s *dev + = (FAR struct lsm9ds1_sensor_dev_s *)((uintptr_t)strtoul(argv[1], NULL, + 16)); + FAR struct lsm9ds1_sensor_s *accel = &dev->priv[LSM9DS1_ACCEL_IDX]; + FAR struct lsm9ds1_sensor_s *gyro = &dev->priv[LSM9DS1_GYRO_IDX]; + FAR struct lsm9ds1_sensor_s *mag = &dev->priv[LSM9DS1_MAG_IDX]; + unsigned long min_interval; + int16_t adata[3]; + int16_t gdata[3]; + int16_t mdata[3]; + int ret; + + while (true) + { + if ((!accel->enabled) && (!gyro->enabled) && (!mag->enabled)) + { + /* Waiting to be woken up */ + + ret = nxsem_wait(&dev->run); + if (ret < 0) + { + continue; + } + } + + /* Read accel */ + + if (accel->enabled) + { + ret = lsm9ds1_readreg(&accel->base, + LSM9DS1_OUT_X_L_XL, (uint8_t *)adata, 6); + lsm9ds1_accel_data(accel, adata); + } + + /* Read gyro */ + + if (gyro->enabled) + { + ret = lsm9ds1_readreg(&gyro->base, + LSM9DS1_OUT_X_L_G, (uint8_t *)gdata, 6); + lsm9ds1_gyro_data(gyro, gdata); + } + + /* Read mag */ + + if (mag->enabled) + { + ret = lsm9ds1_readreg(&mag->base, + LSM9DS1_OUT_X_L_M, (uint8_t *)mdata, 6); + lsm9ds1_mag_data(mag, mdata); + } + + /* Sleeping thread before fetching the next sensor data */ + + min_interval = MIN(accel->interval, gyro->interval); + min_interval = MIN(min_interval, mag->interval); + nxsig_usleep(min_interval); + } + + return OK; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lsm9ds1_register_uorb + * + * Description: + * Register the LSM9DS1 IMU as sensor device + * + * Input Parameters: + * devno - Instance number for driver + * config - configuratio + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int lsm9ds1_register_uorb(int devno, FAR struct lsm9ds1_config_s *config) +{ + FAR struct lsm9ds1_sensor_dev_s *dev = NULL; + FAR struct lsm9ds1_sensor_s *tmp = NULL; +#ifdef CONFIG_SENSORS_LSM9DS1_POLL + FAR char *argv[2]; + char arg1[32]; +#endif + int ret = OK; + + /* Initialize the device structure. */ + + dev = (FAR struct lsm9ds1_sensor_dev_s *)kmm_malloc(sizeof(*dev)); + if (dev == NULL) + { + snerr("ERROR: Failed to allocate instance\n"); + return -ENOMEM; + } + + memset(dev, 0, sizeof(*dev)); + nxmutex_init(&dev->lock); +#ifdef CONFIG_SENSORS_LSM9DS1_POLL + nxsem_init(&dev->run, 0, 0); +#endif + + /* Accelerometer register */ + + tmp = &dev->priv[LSM9DS1_ACCEL_IDX]; + tmp->dev = dev; + tmp->base.ops = &g_lsm9ds1accel_ops; + tmp->base.i2c = config->i2c; + tmp->base.addr = config->addr_acc; + tmp->lower.ops = &g_sensor_ops; + tmp->lower.type = SENSOR_TYPE_ACCELEROMETER; + tmp->lower.nbuffer = 1; +#ifdef CONFIG_SENSORS_LSM9DS1_POLL + tmp->enabled = false; + tmp->interval = CONFIG_SENSORS_LSM9DS1_POLL_INTERVAL; +#endif + + ret = sensor_register(&tmp->lower, devno); + if (ret < 0) + { + snerr("sensor_register failed: %d\n", ret); + goto gyro_err; + } + + lsm9ds1_accel_scale(tmp, 2); + + /* Gyroscope register */ + + tmp = &dev->priv[LSM9DS1_GYRO_IDX]; + tmp->dev = dev; + tmp->base.ops = &g_lsm9ds1gyro_ops; + tmp->base.i2c = config->i2c; + tmp->base.addr = config->addr_gyro; + tmp->lower.ops = &g_sensor_ops; + tmp->lower.type = SENSOR_TYPE_GYROSCOPE; + tmp->lower.nbuffer = 1; +#ifdef CONFIG_SENSORS_LSM9DS1_POLL + tmp->enabled = false; + tmp->interval = CONFIG_SENSORS_LSM9DS1_POLL_INTERVAL; +#endif + + ret = sensor_register(&tmp->lower, devno); + if (ret < 0) + { + snerr("sensor_register failed: %d\n", ret); + goto gyro_err; + } + + lsm9ds1_gyro_scale(tmp, 245); + + /* Magnetic register */ + + tmp = &dev->priv[LSM9DS1_MAG_IDX]; + tmp->dev = dev; + tmp->base.ops = &g_lsm9ds1mag_ops; + tmp->base.i2c = config->i2c; + tmp->base.addr = config->addr_mag; + tmp->lower.ops = &g_sensor_ops; + tmp->lower.type = SENSOR_TYPE_MAGNETIC_FIELD; + tmp->lower.nbuffer = 1; +#ifdef CONFIG_SENSORS_LSM9DS1_POLL + tmp->enabled = false; + tmp->interval = CONFIG_SENSORS_LSM9DS1_POLL_INTERVAL; +#endif + + ret = sensor_register(&tmp->lower, devno); + if (ret < 0) + { + snerr("sensor_register failed: %d\n", ret); + goto mag_err; + } + + lsm9ds1_mag_scale(tmp, 4); + +#ifdef CONFIG_SENSORS_LSM9DS1_POLL + /* Create thread for polling sensor data */ + + snprintf(arg1, 16, "%p", dev); + argv[0] = arg1; + argv[1] = NULL; + + ret = kthread_create("lsm9ds1_thread", SCHED_PRIORITY_DEFAULT, + CONFIG_SENSORS_LSM9DS1_THREAD_STACKSIZE, + lsm9ds1_thread, + argv); + if (ret < 0) + { + goto thr_err; + } +#endif + + return ret; + +#ifdef CONFIG_SENSORS_LSM9DS1_POLL +thr_err: +#endif + sensor_unregister(&dev->priv[LSM9DS1_MAG_IDX].lower, devno); +mag_err: + sensor_unregister(&dev->priv[LSM9DS1_GYRO_IDX].lower, devno); +gyro_err: + sensor_unregister(&dev->priv[LSM9DS1_ACCEL_IDX].lower, devno); + + kmm_free(dev); + + return ret; +} diff --git a/include/nuttx/sensors/lsm9ds1.h b/include/nuttx/sensors/lsm9ds1.h index a5cd2c6c35c..44ae703ca2c 100644 --- a/include/nuttx/sensors/lsm9ds1.h +++ b/include/nuttx/sensors/lsm9ds1.h @@ -57,6 +57,14 @@ struct i2c_master_s; +struct lsm9ds1_config_s +{ + FAR struct i2c_master_s *i2c; + int addr_acc; + int addr_gyro; + int addr_mag; +}; + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ @@ -66,6 +74,8 @@ extern "C" { #endif +#ifndef CONFIG_SENSORS_LSM9DS1_UORB + /**************************************************************************** * Name: lsm9ds1accel_register * @@ -126,6 +136,26 @@ int lsm9ds1mag_register(FAR const char *devpath, FAR struct i2c_master_s *i2c, uint8_t addr); +#else + +/**************************************************************************** + * Name: lsm9ds1_register_uorb + * + * Description: + * Register the LSM9DS1 IMU as sensor device + * + * Input Parameters: + * devno - Instance number for driver + * config - configuratio + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int lsm9ds1_register_uorb(int devno, FAR struct lsm9ds1_config_s *config); +#endif + #ifdef __cplusplus } #endif diff --git a/include/nuttx/sensors/sensor.h b/include/nuttx/sensors/sensor.h index 3aa577a94c5..4fd0f385e9f 100644 --- a/include/nuttx/sensors/sensor.h +++ b/include/nuttx/sensors/sensor.h @@ -966,7 +966,7 @@ struct sensor_ops_s FAR struct file *filep, unsigned long arg); -/**************************************************************************** + /************************************************************************** * Name: calibrate * * This operation can trigger the calibration operation, and if the