drivers: sensor: icm42670: supports icm42670-P/-S

Prepare to use official TDK Invensense Inc. driver for icm42670-P/-S
sensor in tdk_hal module. Simplify I2C and SPI transport files.
Driver code moves in hal_tdk module.
Adds APEX features, such as Pedometer, Tilt detection, Wake on Motion
and Significant Motion Detector.

Signed-off-by: Aurelie Fontaine <aurelie.fontaine@tdk.com>
This commit is contained in:
Aurelie Fontaine 2024-12-05 10:55:18 +01:00 committed by Benjamin Cabé
parent 98dc480603
commit 8a0469dc4f
11 changed files with 1230 additions and 998 deletions

View file

@ -2,10 +2,10 @@
zephyr_library()
zephyr_library_sources(
icm42670.c
icm42670_spi.c
icm42670_i2c.c
)
zephyr_library_sources(icm42670.c)
zephyr_library_sources_ifdef(CONFIG_SPI icm42670_spi.c)
zephyr_library_sources_ifdef(CONFIG_I2C icm42670_i2c.c)
zephyr_library_sources_ifdef(CONFIG_ICM42670_TRIGGER icm42670_trigger.c)
zephyr_library_sources_ifdef(CONFIG_TDK_APEX icm42670_apex.c)

View file

@ -1,18 +1,33 @@
# ICM42670 Six-Axis Motion Tracking device configuration options
# ICM42670-P ICM42670-S Six-Axis Motion Tracking device configuration options
#
# Copyright (c) 2024 TDK Invensense
# Copyright (c) 2022 Esco Medical ApS
# Copyright (c) 2020 TDK Invensense
#
# SPDX-License-Identifier: Apache-2.0
config TDK_APEX
bool "TDK APEX features"
menuconfig ICM42670
bool "ICM42670 Six-Axis Motion Tracking Device"
bool "ICM42670-P/-S Six-Axis Motion Tracking Device"
default y
depends on DT_HAS_INVENSENSE_ICM42670_ENABLED
select SPI if $(dt_compat_on_bus,$(DT_COMPAT_INVENSENSE_ICM42670),spi)
select I2C if $(dt_compat_on_bus,$(DT_COMPAT_INVENSENSE_ICM42670),i2c)
depends on DT_HAS_INVENSENSE_ICM42670P_ENABLED \
|| DT_HAS_INVENSENSE_ICM42670S_ENABLED
depends on ZEPHYR_HAL_TDK_MODULE
select SPI if $(dt_compat_on_bus,$(DT_COMPAT_INVENSENSE_ICM42670P),spi) \
|| $(dt_compat_on_bus,$(DT_COMPAT_INVENSENSE_ICM42670S),spi)
select I2C if $(dt_compat_on_bus,$(DT_COMPAT_INVENSENSE_ICM42670P),i2c) \
|| $(dt_compat_on_bus,$(DT_COMPAT_INVENSENSE_ICM42670S),i2c)
select TDK_APEX if $(dt_node_str_prop_equals,$(dt_nodelabel_path,icm42670p),apex,pedometer) \
|| $(dt_node_str_prop_equals,$(dt_nodelabel_path,icm42670p),apex,tilt) \
|| $(dt_node_str_prop_equals,$(dt_nodelabel_path,icm42670p),apex,smd) \
|| $(dt_node_str_prop_equals,$(dt_nodelabel_path,icm42670p),apex,wom) \
|| $(dt_node_str_prop_equals,$(dt_nodelabel_path,icm42670s),apex,pedometer) \
|| $(dt_node_str_prop_equals,$(dt_nodelabel_path,icm42670s),apex,tilt) \
|| $(dt_node_str_prop_equals,$(dt_nodelabel_path,icm42670s),apex,smd) \
|| $(dt_node_str_prop_equals,$(dt_nodelabel_path,icm42670s),apex,wom)
help
Enable driver for ICM42670 SPI-based six-axis motion tracking device.
Enable driver for ICM42670 SPI-based or I2C-based Six-Axis Motion Tracking device.
if ICM42670
@ -28,13 +43,15 @@ config ICM42670_TRIGGER_NONE
config ICM42670_TRIGGER_GLOBAL_THREAD
bool "Use global thread"
depends on GPIO
depends on $(dt_compat_any_has_prop,$(DT_COMPAT_INVENSENSE_ICM42670),int-gpios)
depends on $(dt_compat_any_has_prop,$(DT_COMPAT_INVENSENSE_ICM42670P),int-gpios) \
|| $(dt_compat_any_has_prop,$(DT_COMPAT_INVENSENSE_ICM42670S),int-gpios)
select ICM42670_TRIGGER
config ICM42670_TRIGGER_OWN_THREAD
bool "Use own thread"
depends on GPIO
depends on $(dt_compat_any_has_prop,$(DT_COMPAT_INVENSENSE_ICM42670),int-gpios)
depends on $(dt_compat_any_has_prop,$(DT_COMPAT_INVENSENSE_ICM42670P),int-gpios) \
|| $(dt_compat_any_has_prop,$(DT_COMPAT_INVENSENSE_ICM42670S),int-gpios)
select ICM42670_TRIGGER
endchoice

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,5 @@
/*
* Copyright (c) 2024 TDK Invensense
* Copyright (c) 2022 Esco Medical ApS
* Copyright (c) 2020 TDK Invensense
*
@ -14,56 +15,66 @@
#include <zephyr/drivers/i2c.h>
#include <zephyr/kernel.h>
#define ICM42670_BUS_SPI DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(invensense_icm42670, spi)
#define ICM42670_BUS_I2C DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(invensense_icm42670, i2c)
#include "imu/inv_imu_driver.h"
#ifdef CONFIG_TDK_APEX
#include "imu/inv_imu_apex.h"
#endif
union icm42670_bus {
#if ICM42670_BUS_SPI
#if CONFIG_SPI
struct spi_dt_spec spi;
#endif
#if ICM42670_BUS_I2C
#if CONFIG_I2C
struct i2c_dt_spec i2c;
#endif
};
typedef int (*icm42670_bus_check_fn)(const union icm42670_bus *bus);
typedef int (*icm42670_reg_read_fn)(const union icm42670_bus *bus,
uint16_t reg, uint8_t *data, size_t size);
typedef int (*icm42670_reg_write_fn)(const union icm42670_bus *bus,
uint16_t reg, uint8_t data);
typedef int (*icm42670_reg_update_fn)(const union icm42670_bus *bus,
uint16_t reg, uint8_t mask, uint8_t data);
typedef int (*icm42670_reg_read_fn)(const union icm42670_bus *bus, uint8_t reg, uint8_t *buf,
uint32_t size);
typedef int (*icm42670_reg_write_fn)(const union icm42670_bus *bus, uint8_t reg, uint8_t *buf,
uint32_t size);
struct icm42670_bus_io {
icm42670_bus_check_fn check;
icm42670_reg_read_fn read;
icm42670_reg_write_fn write;
icm42670_reg_update_fn update;
};
#if ICM42670_BUS_SPI
#if CONFIG_SPI
extern const struct icm42670_bus_io icm42670_bus_io_spi;
#endif
#if ICM42670_BUS_I2C
#if CONFIG_I2C
extern const struct icm42670_bus_io icm42670_bus_io_i2c;
#endif
struct icm42670_data {
int16_t accel_x;
int16_t accel_y;
int16_t accel_z;
uint16_t accel_sensitivity_shift;
struct inv_imu_serif serif;
struct inv_imu_device driver;
uint8_t imu_whoami;
char *imu_name;
uint8_t chip_id;
int32_t accel_x;
int32_t accel_y;
int32_t accel_z;
uint16_t accel_hz;
uint16_t accel_fs;
int16_t gyro_x;
int16_t gyro_y;
int16_t gyro_z;
uint16_t gyro_sensitivity_x10;
uint8_t accel_fs;
uint8_t accel_pwr_mode;
int32_t gyro_x;
int32_t gyro_y;
int32_t gyro_z;
uint16_t gyro_hz;
uint16_t gyro_fs;
int16_t temp;
int32_t temp;
#ifdef CONFIG_TDK_APEX
uint8_t dmp_odr_hz;
uint64_t pedometer_cnt;
uint8_t pedometer_activity;
uint8_t pedometer_cadence;
uint8_t apex_status;
#endif
#ifdef CONFIG_ICM42670_TRIGGER
const struct device *dev;
struct gpio_callback gpio_cb;
@ -85,6 +96,33 @@ struct icm42670_config {
union icm42670_bus bus;
const struct icm42670_bus_io *bus_io;
struct gpio_dt_spec gpio_int;
uint8_t accel_fs;
uint16_t accel_hz;
uint16_t accel_avg;
uint16_t accel_filt_bw;
uint16_t gyro_fs;
uint16_t gyro_hz;
uint16_t gyro_filt_bw;
uint8_t accel_pwr_mode;
uint8_t apex;
};
#ifdef CONFIG_TDK_APEX
#define ICM42670_APEX_STATUS_MASK_TILT BIT(0)
#define ICM42670_APEX_STATUS_MASK_SMD BIT(1)
#define ICM42670_APEX_STATUS_MASK_WOM_X BIT(2)
#define ICM42670_APEX_STATUS_MASK_WOM_Y BIT(3)
#define ICM42670_APEX_STATUS_MASK_WOM_Z BIT(4)
int icm42670_apex_enable(inv_imu_device_t *s);
int icm42670_apex_fetch_from_dmp(const struct device *dev);
void icm42670_apex_pedometer_cadence_convert(struct sensor_value *val, uint8_t raw_val,
uint8_t dmp_odr_hz);
int icm42670_apex_enable_pedometer(const struct device *dev, inv_imu_device_t *s);
int icm42670_apex_enable_tilt(inv_imu_device_t *s);
int icm42670_apex_enable_smd(inv_imu_device_t *s);
int icm42670_apex_enable_wom(inv_imu_device_t *s);
#endif
#endif /* ZEPHYR_DRIVERS_SENSOR_ICM42670_H_ */

View file

@ -0,0 +1,177 @@
/*
* Copyright (c) 2024 TDK Invensense
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "icm42670.h"
#include "imu/inv_imu_apex.h"
int icm42670_apex_enable(inv_imu_device_t *s)
{
int err = 0;
inv_imu_apex_parameters_t apex_inputs;
inv_imu_interrupt_parameter_t config_int = {(inv_imu_interrupt_value)0};
/* Disabling FIFO to avoid extra power consumption due to ALP config */
err |= inv_imu_configure_fifo(s, INV_IMU_FIFO_DISABLED);
/* Enable Pedometer, Tilt and SMD interrupts */
config_int.INV_STEP_DET = INV_IMU_ENABLE;
config_int.INV_STEP_CNT_OVFL = INV_IMU_ENABLE;
config_int.INV_TILT_DET = INV_IMU_ENABLE;
config_int.INV_SMD = INV_IMU_ENABLE;
err |= inv_imu_set_config_int1(s, &config_int);
/* Enable accelerometer to feed the APEX Pedometer algorithm */
err |= inv_imu_set_accel_frequency(s, ACCEL_CONFIG0_ODR_50_HZ);
/* Set 2x averaging, in order to minimize power consumption (16x by default) */
err |= inv_imu_set_accel_lp_avg(s, ACCEL_CONFIG1_ACCEL_FILT_AVG_2);
err |= inv_imu_enable_accel_low_power_mode(s);
/* Get the default parameters for the APEX features */
err |= inv_imu_apex_init_parameters_struct(s, &apex_inputs);
/*
* Configure the power mode Normal mode.
* Avalaible mode : Low Power mode (WoM+Pedometer),
* configure the WoM to wake-up the DMP once it goes in power save mode
*/
apex_inputs.power_save = APEX_CONFIG0_DMP_POWER_SAVE_DIS;
err |= inv_imu_apex_configure_parameters(s, &apex_inputs);
/* Configure sampling frequency to 50Hz */
err |= inv_imu_apex_set_frequency(s, APEX_CONFIG1_DMP_ODR_50Hz);
return err;
}
int icm42670_apex_fetch_from_dmp(const struct device *dev)
{
struct icm42670_data *data = dev->data;
int rc = 0;
uint8_t int_status2, int_status3;
/* Read APEX interrupt status */
rc |= inv_imu_read_reg(&data->driver, INT_STATUS2, 1, &int_status2);
rc |= inv_imu_read_reg(&data->driver, INT_STATUS3, 1, &int_status3);
/* Test Pedometer interrupt */
if (int_status3 & (INT_STATUS3_STEP_DET_INT_MASK)) {
inv_imu_apex_step_activity_t apex_pedometer;
uint8_t step_cnt_ovflw = 0;
if (int_status3 & INT_STATUS3_STEP_CNT_OVF_INT_MASK) {
step_cnt_ovflw = 1;
}
rc |= inv_imu_apex_get_data_activity(&data->driver, &apex_pedometer);
if (data->pedometer_cnt !=
apex_pedometer.step_cnt + step_cnt_ovflw * (uint64_t)UINT16_MAX) {
data->pedometer_cnt =
apex_pedometer.step_cnt + step_cnt_ovflw * (uint64_t)UINT16_MAX;
data->pedometer_activity = apex_pedometer.activity_class;
data->pedometer_cadence = apex_pedometer.step_cadence;
} else {
/* Pedometer data processing */
rc = 1;
}
}
/* Test Tilt interrupt */
if (int_status3 & (INT_STATUS3_TILT_DET_INT_MASK)) {
data->apex_status = ICM42670_APEX_STATUS_MASK_TILT;
}
/* Test SMD interrupt */
if ((int_status2 & (INT_STATUS2_SMD_INT_MASK)) || (rc != 0)) {
data->apex_status = ICM42670_APEX_STATUS_MASK_SMD;
}
/* Test WOM interrupts */
if (int_status2 & (INT_STATUS2_WOM_X_INT_MASK | INT_STATUS2_WOM_Y_INT_MASK |
INT_STATUS2_WOM_Z_INT_MASK)) {
data->apex_status = 0;
if (int_status2 & INT_STATUS2_WOM_X_INT_MASK) {
data->apex_status |= ICM42670_APEX_STATUS_MASK_WOM_X;
}
if (int_status2 & INT_STATUS2_WOM_Y_INT_MASK) {
data->apex_status |= ICM42670_APEX_STATUS_MASK_WOM_Y;
}
if (int_status2 & INT_STATUS2_WOM_Z_INT_MASK) {
data->apex_status |= ICM42670_APEX_STATUS_MASK_WOM_Z;
}
}
return rc;
}
void icm42670_apex_pedometer_cadence_convert(struct sensor_value *val, uint8_t raw_val,
uint8_t dmp_odr_hz)
{
int64_t conv_val;
/* Converting u6.2 */
conv_val = (int64_t)(dmp_odr_hz << 2) * 1000000 / (raw_val + (raw_val & 0x03));
val->val1 = conv_val / 1000000;
val->val2 = conv_val % 1000000;
}
int icm42670_apex_enable_pedometer(const struct device *dev, inv_imu_device_t *s)
{
struct icm42670_data *data = dev->data;
data->dmp_odr_hz = 50;
/* Enable the pedometer */
return inv_imu_apex_enable_pedometer(s);
}
int icm42670_apex_enable_tilt(inv_imu_device_t *s)
{
/* Enable Tilt */
return inv_imu_apex_enable_tilt(s);
}
int icm42670_apex_enable_smd(inv_imu_device_t *s)
{
int rc = 0;
/* Enable SMD (and Pedometer as SMD uses it) */
rc |= inv_imu_apex_enable_pedometer(s);
rc |= inv_imu_apex_enable_smd(s);
return rc;
}
int icm42670_apex_enable_wom(inv_imu_device_t *s)
{
int rc = 0;
inv_imu_interrupt_parameter_t config_int = {(inv_imu_interrupt_value)0};
/*
* Optimize power consumption:
* - Disable FIFO usage.
* - Disable data ready interrupt and enable WOM interrupts.
* - Set 2X averaging.
* - Use Low-Power mode at low frequency.
*/
rc |= inv_imu_configure_fifo(s, INV_IMU_FIFO_DISABLED);
config_int.INV_WOM_X = INV_IMU_ENABLE;
config_int.INV_WOM_Y = INV_IMU_ENABLE;
config_int.INV_WOM_Z = INV_IMU_ENABLE;
rc |= inv_imu_set_config_int1(s, &config_int);
rc |= inv_imu_set_accel_lp_avg(s, ACCEL_CONFIG1_ACCEL_FILT_AVG_2);
rc |= inv_imu_set_accel_frequency(s, ACCEL_CONFIG0_ODR_12_5_HZ);
rc |= inv_imu_enable_accel_low_power_mode(s);
/*
* Configure WOM thresholds for each axis to 195 mg (Resolution 1g/256)
* WOM threshold = 50 * 1000 / 256 = 195 mg
* and enable WOM
*/
rc |= inv_imu_configure_wom(s, 50, 50, 50, WOM_CONFIG_WOM_INT_MODE_ORED,
WOM_CONFIG_WOM_INT_DUR_1_SMPL);
rc |= inv_imu_enable_wom(s);
return rc;
}

View file

@ -1,4 +1,5 @@
/*
* Copyright (c) 2024 TDK Invensense
* Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
@ -9,114 +10,28 @@
*/
#include "icm42670.h"
#include "icm42670_reg.h"
#if ICM42670_BUS_I2C
#if CONFIG_I2C
static int icm42670_bus_check_i2c(const union icm42670_bus *bus)
{
return i2c_is_ready_dt(&bus->i2c) ? 0 : -ENODEV;
return device_is_ready(bus->i2c.bus) ? 0 : -ENODEV;
}
static int i2c_read_mreg(const union icm42670_bus *bus, uint8_t reg, uint8_t bank,
uint8_t *buf, size_t len)
static int icm42670_reg_read_i2c(const union icm42670_bus *bus, uint8_t reg, uint8_t *buf,
uint32_t size)
{
int res = i2c_reg_write_byte_dt(&bus->i2c, REG_BLK_SEL_R, bank);
if (res) {
return res;
}
/* reads from MREG registers must be done byte-by-byte */
for (size_t i = 0; i < len; i++) {
uint8_t addr = reg + i;
res = i2c_reg_write_byte_dt(&bus->i2c, REG_MADDR_R, addr);
if (res) {
return res;
}
k_usleep(MREG_R_W_WAIT_US);
res = i2c_reg_read_byte_dt(&bus->i2c, REG_M_R, &buf[i]);
if (res) {
return res;
}
k_usleep(MREG_R_W_WAIT_US);
}
return 0;
return i2c_burst_read_dt(&bus->i2c, reg, buf, size);
}
static int icm42670_reg_read_i2c(const union icm42670_bus *bus, uint16_t reg, uint8_t *data,
size_t len)
static int icm42670_reg_write_i2c(const union icm42670_bus *bus, uint8_t reg, uint8_t *buf,
uint32_t size)
{
int res = 0;
uint8_t bank = FIELD_GET(REG_BANK_MASK, reg);
uint8_t address = FIELD_GET(REG_ADDRESS_MASK, reg);
if (bank) {
res = i2c_read_mreg(bus, address, bank, data, len);
} else {
res = i2c_burst_read_dt(&bus->i2c, address, data, len);
}
return res;
}
static int i2c_write_mreg(const union icm42670_bus *bus, uint16_t reg, uint8_t bank,
uint8_t buf)
{
int res = i2c_reg_write_byte_dt(&bus->i2c, REG_BLK_SEL_W, bank);
if (res) {
return res;
}
res = i2c_reg_write_byte_dt(&bus->i2c, REG_MADDR_W, reg);
if (res) {
return res;
}
res = i2c_reg_write_byte_dt(&bus->i2c, REG_M_W, buf);
if (res) {
return res;
}
k_usleep(MREG_R_W_WAIT_US);
return 0;
}
static int icm42670_reg_write_i2c(const union icm42670_bus *bus,
uint16_t reg, uint8_t data)
{
int res = 0;
uint8_t bank = FIELD_GET(REG_BANK_MASK, reg);
uint8_t address = FIELD_GET(REG_ADDRESS_MASK, reg);
if (bank) {
res = i2c_write_mreg(bus, address, bank, data);
} else {
res = i2c_reg_write_byte_dt(&bus->i2c, address, data);
}
return res;
}
static int icm42670_reg_update_i2c(const union icm42670_bus *bus, uint16_t reg, uint8_t mask,
uint8_t val)
{
return i2c_reg_update_byte_dt(&bus->i2c, reg, mask, val);
return i2c_burst_write_dt(&bus->i2c, reg, buf, size);
}
const struct icm42670_bus_io icm42670_bus_io_i2c = {
.check = icm42670_bus_check_i2c,
.read = icm42670_reg_read_i2c,
.write = icm42670_reg_write_i2c,
.update = icm42670_reg_update_i2c,
};
#endif /* ICM42670_BUS_I2C */
#endif /* CONFIG_I2C */

View file

@ -1,268 +0,0 @@
/*
* Copyright (c) 2022 Esco Medical ApS
* Copyright (c) 2020 TDK Invensense
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_DRIVERS_SENSOR_ICM42670_REG_H_
#define ZEPHYR_DRIVERS_SENSOR_ICM42670_REG_H_
#include <zephyr/sys/util.h>
/* Helper macros for addressing registers in MREG1-3, see datasheet section 13 */
#define REG_MADDR_BASE 0x0028
#define REG_MREG1_SHIFT 8
#define REG_MREG2_SHIFT 9
#define REG_MREG3_SHIFT 10
#define REG_BANK0_OFFSET 0x0000
#define REG_MREG1_OFFSET (REG_MADDR_BASE << REG_MREG1_SHIFT)
#define REG_MREG2_OFFSET (REG_MADDR_BASE << REG_MREG2_SHIFT)
#define REG_MREG3_OFFSET (REG_MADDR_BASE << REG_MREG3_SHIFT)
#define REG_ADDRESS_MASK GENMASK(7, 0)
#define REG_BANK_MASK GENMASK(15, 8)
#define REG_SPI_READ_BIT BIT(7)
#define MREG_R_W_WAIT_US 20 /* 10us, but use 20us to be on the safe side */
/* BANK 0 */
#define REG_MCLK_RDY (REG_BANK0_OFFSET | 0x00)
#define REG_DEVICE_CONFIG (REG_BANK0_OFFSET | 0x01)
#define REG_SIGNAL_PATH_RESET (REG_BANK0_OFFSET | 0x02)
#define REG_DRIVE_CONFIG1 (REG_BANK0_OFFSET | 0x03)
#define REG_DRIVE_CONFIG2 (REG_BANK0_OFFSET | 0x04)
#define REG_DRIVE_CONFIG3 (REG_BANK0_OFFSET | 0x05)
#define REG_INT_CONFIG (REG_BANK0_OFFSET | 0x06)
#define REG_TEMP_DATA1 (REG_BANK0_OFFSET | 0x09)
#define REG_TEMP_DATA0 (REG_BANK0_OFFSET | 0x0a)
#define REG_ACCEL_DATA_X1 (REG_BANK0_OFFSET | 0x0b)
#define REG_ACCEL_DATA_X0 (REG_BANK0_OFFSET | 0x0c)
#define REG_ACCEL_DATA_Y1 (REG_BANK0_OFFSET | 0x0d)
#define REG_ACCEL_DATA_Y0 (REG_BANK0_OFFSET | 0x0e)
#define REG_ACCEL_DATA_Z1 (REG_BANK0_OFFSET | 0x0f)
#define REG_ACCEL_DATA_Z0 (REG_BANK0_OFFSET | 0x10)
#define REG_GYRO_DATA_X1 (REG_BANK0_OFFSET | 0x11)
#define REG_GYRO_DATA_X0 (REG_BANK0_OFFSET | 0x12)
#define REG_GYRO_DATA_Y1 (REG_BANK0_OFFSET | 0x13)
#define REG_GYRO_DATA_Y0 (REG_BANK0_OFFSET | 0x14)
#define REG_GYRO_DATA_Z1 (REG_BANK0_OFFSET | 0x15)
#define REG_GYRO_DATA_Z0 (REG_BANK0_OFFSET | 0x16)
#define REG_TMST_FSYNCH (REG_BANK0_OFFSET | 0x17)
#define REG_TMST_FSYNCL (REG_BANK0_OFFSET | 0x18)
#define REG_APEX_DATA4 (REG_BANK0_OFFSET | 0x1d)
#define REG_APEX_DATA5 (REG_BANK0_OFFSET | 0x1e)
#define REG_PWR_MGMT0 (REG_BANK0_OFFSET | 0x1f)
#define REG_GYRO_CONFIG0 (REG_BANK0_OFFSET | 0x20)
#define REG_ACCEL_CONFIG0 (REG_BANK0_OFFSET | 0x21)
#define REG_TEMP_CONFIG0 (REG_BANK0_OFFSET | 0x22)
#define REG_GYRO_CONFIG1 (REG_BANK0_OFFSET | 0x23)
#define REG_ACCEL_CONFIG1 (REG_BANK0_OFFSET | 0x24)
#define REG_APEX_CONFIG0 (REG_BANK0_OFFSET | 0x25)
#define REG_APEX_CONFIG1 (REG_BANK0_OFFSET | 0x26)
#define REG_WOM_CONFIG (REG_BANK0_OFFSET | 0x27)
#define REG_FIFO_CONFIG1 (REG_BANK0_OFFSET | 0x28)
#define REG_FIFO_CONFIG2 (REG_BANK0_OFFSET | 0x29)
#define REG_FIFO_CONFIG3 (REG_BANK0_OFFSET | 0x2a)
#define REG_INT_SOURCE0 (REG_BANK0_OFFSET | 0x2b)
#define REG_INT_SOURCE1 (REG_BANK0_OFFSET | 0x2c)
#define REG_INT_SOURCE3 (REG_BANK0_OFFSET | 0x2d)
#define REG_INT_SOURCE4 (REG_BANK0_OFFSET | 0x2e)
#define REG_FIFO_LOST_PKT0 (REG_BANK0_OFFSET | 0x2f)
#define REG_FIFO_LOST_PKT1 (REG_BANK0_OFFSET | 0x30)
#define REG_APEX_DATA0 (REG_BANK0_OFFSET | 0x31)
#define REG_APEX_DATA1 (REG_BANK0_OFFSET | 0x32)
#define REG_APEX_DATA2 (REG_BANK0_OFFSET | 0x33)
#define REG_APEX_DATA3 (REG_BANK0_OFFSET | 0x34)
#define REG_INTF_CONFIG0 (REG_BANK0_OFFSET | 0x35)
#define REG_INTF_CONFIG1 (REG_BANK0_OFFSET | 0x36)
#define REG_INT_STATUS_DRDY (REG_BANK0_OFFSET | 0x39)
#define REG_INT_STATUS (REG_BANK0_OFFSET | 0x3a)
#define REG_INT_STATUS2 (REG_BANK0_OFFSET | 0x3b)
#define REG_INT_STATUS3 (REG_BANK0_OFFSET | 0x3c)
#define REG_FIFO_COUNTH (REG_BANK0_OFFSET | 0x3d)
#define REG_FIFO_COUNTL (REG_BANK0_OFFSET | 0x3e)
#define REG_FIFO_DATA (REG_BANK0_OFFSET | 0x3f)
#define REG_WHO_AM_I (REG_BANK0_OFFSET | 0x75)
#define REG_BLK_SEL_W (REG_BANK0_OFFSET | 0x79)
#define REG_MADDR_W (REG_BANK0_OFFSET | 0x7a)
#define REG_M_W (REG_BANK0_OFFSET | 0x7b)
#define REG_BLK_SEL_R (REG_BANK0_OFFSET | 0x7c)
#define REG_MADDR_R (REG_BANK0_OFFSET | 0x7d)
#define REG_M_R (REG_BANK0_OFFSET | 0x7e)
/* MREG1 */
#define REG_TMST_CONFIG1 (REG_MREG1_OFFSET | 0x00)
#define REG_FIFO_CONFIG5 (REG_MREG1_OFFSET | 0x01)
#define REG_FIFO_CONFIG6 (REG_MREG1_OFFSET | 0x02)
#define REG_FSYNC_CONFIG (REG_MREG1_OFFSET | 0x03)
#define REG_INT_CONFIG0 (REG_MREG1_OFFSET | 0x04)
#define REG_INT_CONFIG1 (REG_MREG1_OFFSET | 0x05)
#define REG_SENSOR_CONFIG3 (REG_MREG1_OFFSET | 0x06)
#define REG_ST_CONFIG (REG_MREG1_OFFSET | 0x13)
#define REG_SELFTEST (REG_MREG1_OFFSET | 0x14)
#define REG_INTF_CONFIG6 (REG_MREG1_OFFSET | 0x23)
#define REG_INTF_CONFIG10 (REG_MREG1_OFFSET | 0x25)
#define REG_INTF_CONFIG7 (REG_MREG1_OFFSET | 0x28)
#define REG_OTP_CONFIG (REG_MREG1_OFFSET | 0x2b)
#define REG_INT_SOURCE6 (REG_MREG1_OFFSET | 0x2f)
#define REG_INT_SOURCE7 (REG_MREG1_OFFSET | 0x30)
#define REG_INT_SOURCE8 (REG_MREG1_OFFSET | 0x31)
#define REG_INT_SOURCE9 (REG_MREG1_OFFSET | 0x32)
#define REG_INT_SOURCE10 (REG_MREG1_OFFSET | 0x33)
#define REG_APEX_CONFIG2 (REG_MREG1_OFFSET | 0x44)
#define REG_APEX_CONFIG3 (REG_MREG1_OFFSET | 0x45)
#define REG_APEX_CONFIG4 (REG_MREG1_OFFSET | 0x46)
#define REG_APEX_CONFIG5 (REG_MREG1_OFFSET | 0x47)
#define REG_APEX_CONFIG9 (REG_MREG1_OFFSET | 0x48)
#define REG_APEX_CONFIG10 (REG_MREG1_OFFSET | 0x49)
#define REG_APEX_CONFIG11 (REG_MREG1_OFFSET | 0x4a)
#define REG_ACCEL_WOM_X_THR (REG_MREG1_OFFSET | 0x4b)
#define REG_ACCEL_WOM_Y_THR (REG_MREG1_OFFSET | 0x4c)
#define REG_ACCEL_WOM_Z_THR (REG_MREG1_OFFSET | 0x4d)
#define REG_OFFSET_USER0 (REG_MREG1_OFFSET | 0x4e)
#define REG_OFFSET_USER1 (REG_MREG1_OFFSET | 0x4f)
#define REG_OFFSET_USER2 (REG_MREG1_OFFSET | 0x50)
#define REG_OFFSET_USER3 (REG_MREG1_OFFSET | 0x51)
#define REG_OFFSET_USER4 (REG_MREG1_OFFSET | 0x52)
#define REG_OFFSET_USER5 (REG_MREG1_OFFSET | 0x53)
#define REG_OFFSET_USER6 (REG_MREG1_OFFSET | 0x54)
#define REG_OFFSET_USER7 (REG_MREG1_OFFSET | 0x55)
#define REG_OFFSET_USER8 (REG_MREG1_OFFSET | 0x56)
#define REG_ST_STATUS1 (REG_MREG1_OFFSET | 0x63)
#define REG_ST_STATUS2 (REG_MREG1_OFFSET | 0x64)
#define REG_FDR_CONFIG (REG_MREG1_OFFSET | 0x66)
#define REG_APEX_CONFIG12 (REG_MREG1_OFFSET | 0x67)
/* MREG2 */
#define REG_OTP_CTRL7 (REG_MREG2_OFFSET | 0x06)
/* MREG3 */
#define REG_XA_ST_DATA3 (REG_MREG3_OFFSET | 0x00)
#define REG_YA_ST_DATA3 (REG_MREG3_OFFSET | 0x01)
#define REG_ZA_ST_DATA3 (REG_MREG3_OFFSET | 0x02)
#define REG_XG_ST_DATA3 (REG_MREG3_OFFSET | 0x03)
#define REG_YG_ST_DATA3 (REG_MREG3_OFFSET | 0x04)
#define REG_ZG_ST_DATA3 (REG_MREG3_OFFSET | 0x05)
/* Bank0 REG_MCLK_RDY */
#define BIT_MCLK_RDY BIT(3)
/* Bank0 REG_DEVICE_CONFIG */
#define BIT_SPI_AP_4WIRE BIT(2)
#define BIT_SPI_MODE BIT(0)
/* Bank0 REG_SIGNAL_PATH_RESET */
#define BIT_FIFO_FLUSH BIT(2)
#define BIT_SOFT_RESET BIT(4)
/* Bank0 REG_INST_STATUS */
#define BIT_STATUS_RESET_DONE_INT BIT(4)
/* Bank0 REG_INT_CONFIG */
#define BIT_INT1_POLARITY BIT(0)
#define BIT_INT1_DRIVE_CIRCUIT BIT(1)
#define BIT_INT1_MODE BIT(2)
#define BIT_INT2_POLARITY BIT(3)
#define BIT_INT2_DRIVE_CIRCUIT BIT(4)
#define BIT_INT2_MODE BIT(5)
/* Bank0 REG_PWR_MGMT_0 */
#define MASK_ACCEL_MODE GENMASK(1, 0)
#define BIT_ACCEL_MODE_OFF 0x00
#define BIT_ACCEL_MODE_LPM 0x02
#define BIT_ACCEL_MODE_LNM 0x03
#define MASK_GYRO_MODE GENMASK(3, 2)
#define BIT_GYRO_MODE_OFF 0x00
#define BIT_GYRO_MODE_STBY 0x01
#define BIT_GYRO_MODE_LNM 0x03
#define BIT_IDLE BIT(4)
#define BIT_ACCEL_LP_CLK_SEL BIT(7)
/* Bank0 REG_INT_SOURCE0 */
#define BIT_INT_AGC_RDY_INT1_EN BIT(0)
#define BIT_INT_FIFO_FULL_INT1_EN BIT(1)
#define BIT_INT_FIFO_THS_INT1_EN BIT(2)
#define BIT_INT_DRDY_INT1_EN BIT(3)
#define BIT_INT_RESET_DONE_INT1_EN BIT(4)
#define BIT_INT_PLL_RDY_INT1_EN BIT(5)
#define BIT_INT_FSYNC_INT1_EN BIT(6)
#define BIT_INT_ST_INT1_EN BIT(7)
/* Bank0 REG_INT_STATUS_DRDY */
#define BIT_INT_STATUS_DATA_DRDY BIT(0)
/* Bank9 REG_INTF_CONFIG1 */
#define BIT_I3C_SDR_EN BIT(3)
#define BIT_I3C_DDR_EN BIT(2)
#define MASK_CLKSEL GENMASK(1, 0)
#define BIT_CLKSEL_INT_RC 0x00
#define BIT_CLKSEL_PLL_OR_RC 0x01
#define BIT_CLKSEL_DISABLE 0x11
/* Bank0 REG_INT_STATUS */
#define BIT_INT_STATUS_AGC_RDY BIT(0)
#define BIT_INT_STATUS_FIFO_FULL BIT(1)
#define BIT_INT_STATUS_FIFO_THS BIT(2)
#define BIT_INT_STATUS_RESET_DONE BIT(4)
#define BIT_INT_STATUS_PLL_RDY BIT(5)
#define BIT_INT_STATUS_FSYNC BIT(6)
#define BIT_INT_STATUS_ST BIT(7)
/* Bank0 REG_INT_STATUS2 */
#define BIT_INT_STATUS_WOM_Z BIT(0)
#define BIT_INT_STATUS_WOM_Y BIT(1)
#define BIT_INT_STATUS_WOM_X BIT(2)
#define BIT_INT_STATUS_SMD BIT(3)
/* Bank0 REG_INT_STATUS3 */
#define BIT_INT_STATUS_LOWG_DET BIT(1)
#define BIT_INT_STATUS_FF_DET BIT(2)
#define BIT_INT_STATUS_TILT_DET BIT(3)
#define BIT_INT_STATUS_STEP_CNT_OVFL BIT(4)
#define BIT_INT_STATUS_STEP_DET BIT(5)
/* Bank0 REG_ACCEL_CONFIG0 */
#define MASK_ACCEL_UI_FS_SEL GENMASK(6, 5)
#define BIT_ACCEL_UI_FS_16 0x00
#define BIT_ACCEL_UI_FS_8 0x01
#define BIT_ACCEL_UI_FS_4 0x02
#define BIT_ACCEL_UI_FS_2 0x03
#define MASK_ACCEL_ODR GENMASK(3, 0)
#define BIT_ACCEL_ODR_1600 0x05
#define BIT_ACCEL_ODR_800 0x06
#define BIT_ACCEL_ODR_400 0x07
#define BIT_ACCEL_ODR_200 0x08
#define BIT_ACCEL_ODR_100 0x09
#define BIT_ACCEL_ODR_50 0x0A
#define BIT_ACCEL_ODR_25 0x0B
#define BIT_ACCEL_ODR_12 0x0C
#define BIT_ACCEL_ODR_6 0x0D
#define BIT_ACCEL_ODR_3 0x0E
#define BIT_ACCEL_ODR_1 0x0F
/* Bank0 REG_GYRO_CONFIG0 */
#define MASK_GYRO_UI_FS_SEL GENMASK(6, 5)
#define BIT_GYRO_UI_FS_2000 0x00
#define BIT_GYRO_UI_FS_1000 0x01
#define BIT_GYRO_UI_FS_500 0x02
#define BIT_GYRO_UI_FS_250 0x03
#define MASK_GYRO_ODR GENMASK(3, 0)
#define BIT_GYRO_ODR_1600 0x05
#define BIT_GYRO_ODR_800 0x06
#define BIT_GYRO_ODR_400 0x07
#define BIT_GYRO_ODR_200 0x08
#define BIT_GYRO_ODR_100 0x09
#define BIT_GYRO_ODR_50 0x0A
#define BIT_GYRO_ODR_25 0x0B
#define BIT_GYRO_ODR_12 0x0C
/* misc. defines */
#define WHO_AM_I_ICM42670 0x67
#define MIN_ACCEL_SENS_SHIFT 11
#define ACCEL_DATA_SIZE 6
#define GYRO_DATA_SIZE 6
#define TEMP_DATA_SIZE 2
#define MCLK_POLL_INTERVAL_US 250
#define MCLK_POLL_ATTEMPTS 100
#define SOFT_RESET_TIME_MS 2 /* 1ms + elbow room */
#endif /* ZEPHYR_DRIVERS_SENSOR_ICM42670_REG_H_ */

View file

@ -1,185 +1,72 @@
/*
* Copyright (c) 2024 TDK Invensense
* Copyright (c) 2022 Esco Medical ApS
* Copyright (c) 2020 TDK Invensense
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <zephyr/sys/util.h>
/*
* Bus-specific functionality for ICM42670 accessed via SPI.
*/
#include "icm42670.h"
#include "icm42670_reg.h"
#if ICM42670_BUS_SPI
static inline int spi_write_register(const union icm42670_bus *bus, uint8_t reg, uint8_t data)
{
const struct spi_buf buf[2] = {
{
.buf = &reg,
.len = 1,
},
{
.buf = &data,
.len = 1,
}
};
#if CONFIG_SPI
const struct spi_buf_set tx = {
.buffers = buf,
.count = 2,
};
return spi_write_dt(&bus->spi, &tx);
}
static inline int spi_read_register(const union icm42670_bus *bus, uint8_t reg, uint8_t *data,
size_t len)
{
uint8_t tx_buffer = REG_SPI_READ_BIT | reg;
const struct spi_buf tx_buf = {
.buf = &tx_buffer,
.len = 1,
};
const struct spi_buf_set tx = {
.buffers = &tx_buf,
.count = 1,
};
struct spi_buf rx_buf[2] = {
{
.buf = NULL,
.len = 1,
},
{
.buf = data,
.len = len,
}
};
const struct spi_buf_set rx = {
.buffers = rx_buf,
.count = 2,
};
return spi_transceive_dt(&bus->spi, &tx, &rx);
}
static inline int spi_read_mreg(const union icm42670_bus *bus, uint8_t reg, uint8_t bank,
uint8_t *buf, size_t len)
{
int res = spi_write_register(bus, REG_BLK_SEL_R, bank);
if (res) {
return res;
}
/* reads from MREG registers must be done byte-by-byte */
for (size_t i = 0; i < len; i++) {
uint8_t addr = reg + i;
res = spi_write_register(bus, REG_MADDR_R, addr);
if (res) {
return res;
}
k_usleep(MREG_R_W_WAIT_US);
res = spi_read_register(bus, REG_M_R, &buf[i], 1);
if (res) {
return res;
}
k_usleep(MREG_R_W_WAIT_US);
}
return 0;
}
static inline int spi_write_mreg(const union icm42670_bus *bus, uint8_t reg, uint8_t bank,
uint8_t buf)
{
int res = spi_write_register(bus, REG_BLK_SEL_W, bank);
if (res) {
return res;
}
res = spi_write_register(bus, REG_MADDR_W, reg);
if (res) {
return res;
}
res = spi_write_register(bus, REG_M_W, buf);
if (res) {
return res;
}
k_usleep(MREG_R_W_WAIT_US);
return 0;
}
int icm42670_spi_read(const union icm42670_bus *bus, uint16_t reg, uint8_t *data, size_t len)
{
int res = 0;
uint8_t bank = FIELD_GET(REG_BANK_MASK, reg);
uint8_t address = FIELD_GET(REG_ADDRESS_MASK, reg);
if (bank) {
res = spi_read_mreg(bus, address, bank, data, len);
} else {
res = spi_read_register(bus, address, data, len);
}
return res;
}
int icm42670_spi_single_write(const union icm42670_bus *bus, uint16_t reg, uint8_t data)
{
int res = 0;
uint8_t bank = FIELD_GET(REG_BANK_MASK, reg);
uint8_t address = FIELD_GET(REG_ADDRESS_MASK, reg);
if (bank) {
res = spi_write_mreg(bus, address, bank, data);
} else {
res = spi_write_register(bus, address, data);
}
return res;
}
int icm42670_spi_update_register(const union icm42670_bus *bus, uint16_t reg, uint8_t mask,
uint8_t data)
{
uint8_t temp = 0;
int res = icm42670_spi_read(bus, reg, &temp, 1);
if (res) {
return res;
}
temp &= ~mask;
temp |= FIELD_PREP(mask, data);
return icm42670_spi_single_write(bus, reg, temp);
}
#include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(ICM42670, CONFIG_SENSOR_LOG_LEVEL);
static int icm42670_bus_check_spi(const union icm42670_bus *bus)
{
return spi_is_ready_dt(&bus->spi) ? 0 : -ENODEV;
}
static int icm42670_reg_read_spi(const union icm42670_bus *bus, uint8_t start, uint8_t *buf,
uint32_t size)
{
uint8_t cmd[] = {(start | 0x80)};
const struct spi_buf tx_buf = {.buf = cmd, .len = sizeof(cmd)};
const struct spi_buf_set tx = {.buffers = &tx_buf, .count = 1};
struct spi_buf rx_buf[2];
const struct spi_buf_set rx = {.buffers = rx_buf, .count = ARRAY_SIZE(rx_buf)};
int ret;
rx_buf[0].buf = NULL;
rx_buf[0].len = 1;
rx_buf[1].len = size;
rx_buf[1].buf = buf;
ret = spi_transceive_dt(&bus->spi, &tx, &rx);
if (ret) {
LOG_ERR("spi_transceive FAIL %d\n", ret);
return ret;
}
return 0;
}
static int icm42670_reg_write_spi(const union icm42670_bus *bus, uint8_t reg, uint8_t *buf,
uint32_t size)
{
uint8_t cmd[] = {reg & 0x7F};
const struct spi_buf tx_buf[2] = {{.buf = cmd, .len = sizeof(cmd)},
{.buf = buf, .len = size}};
const struct spi_buf_set tx = {.buffers = tx_buf, .count = 2};
int ret = spi_write_dt(&bus->spi, &tx);
if (ret) {
LOG_ERR("spi_write FAIL %d\n", ret);
return ret;
}
return 0;
}
const struct icm42670_bus_io icm42670_bus_io_spi = {
.check = icm42670_bus_check_spi,
.read = icm42670_spi_read,
.write = icm42670_spi_single_write,
.update = icm42670_spi_update_register,
.read = icm42670_reg_read_spi,
.write = icm42670_reg_write_spi,
};
#endif /* ICM42670_BUS_SPI */
#endif /* CONFIG_SPI */

View file

@ -1,4 +1,5 @@
/*
* Copyright (c) 2024 TDK Invensense
* Copyright (c) 2022 Esco Medical ApS
* Copyright (c) 2016 TDK Invensense
*
@ -9,7 +10,6 @@
#include <zephyr/drivers/sensor.h>
#include <zephyr/sys/util.h>
#include "icm42670.h"
#include "icm42670_reg.h"
#include "icm42670_trigger.h"
#include <zephyr/logging/log.h>
@ -60,7 +60,6 @@ static void icm42670_thread(void *p1, void *p2, void *p3)
icm42670_thread_cb(data->dev);
}
}
#elif defined(CONFIG_ICM42670_TRIGGER_GLOBAL_THREAD)
static void icm42670_work_handler(struct k_work *work)
@ -75,7 +74,6 @@ static void icm42670_work_handler(struct k_work *work)
int icm42670_trigger_set(const struct device *dev, const struct sensor_trigger *trig,
sensor_trigger_handler_t handler)
{
int res = 0;
struct icm42670_data *data = dev->data;
const struct icm42670_config *cfg = dev->config;
@ -86,20 +84,22 @@ int icm42670_trigger_set(const struct device *dev, const struct sensor_trigger *
icm42670_lock(dev);
gpio_pin_interrupt_configure_dt(&cfg->gpio_int, GPIO_INT_DISABLE);
switch (trig->type) {
case SENSOR_TRIG_DATA_READY:
if (trig->type == SENSOR_TRIG_DATA_READY) {
data->data_ready_handler = handler;
data->data_ready_trigger = trig;
break;
default:
res = -ENOTSUP;
break;
#ifdef CONFIG_TDK_APEX
} else if (trig->type == SENSOR_TRIG_MOTION) {
data->data_ready_handler = handler;
data->data_ready_trigger = trig;
#endif
} else {
return -ENOTSUP;
}
icm42670_unlock(dev);
gpio_pin_interrupt_configure_dt(&cfg->gpio_int, GPIO_INT_EDGE_TO_ACTIVE);
return res;
return 0;
}
int icm42670_trigger_init(const struct device *dev)
@ -139,24 +139,26 @@ int icm42670_trigger_init(const struct device *dev)
data->work.handler = icm42670_work_handler;
#endif
return gpio_pin_interrupt_configure_dt(&cfg->gpio_int, GPIO_INT_EDGE_TO_ACTIVE);
return gpio_pin_interrupt_configure_dt(&cfg->gpio_int, GPIO_INT_EDGE_TO_INACTIVE);
}
int icm42670_trigger_enable_interrupt(const struct device *dev)
{
int res;
const struct icm42670_config *cfg = dev->config;
struct icm42670_data *data = dev->data;
int err = 0;
inv_imu_int1_pin_config_t int1_pin_config;
inv_imu_interrupt_parameter_t config_int = {(inv_imu_interrupt_value)0};
/* pulse-mode (auto clearing), push-pull and active-high */
res = cfg->bus_io->write(&cfg->bus, REG_INT_CONFIG,
BIT_INT1_DRIVE_CIRCUIT | BIT_INT1_POLARITY);
/* Set interrupt config */
int1_pin_config.int_polarity = INT_CONFIG_INT1_POLARITY_HIGH;
int1_pin_config.int_mode = INT_CONFIG_INT1_MODE_PULSED;
int1_pin_config.int_drive = INT_CONFIG_INT1_DRIVE_CIRCUIT_PP;
err |= inv_imu_set_pin_config_int1(&data->driver, &int1_pin_config);
if (res) {
return res;
}
config_int.INV_FIFO_THS = INV_IMU_ENABLE;
err |= inv_imu_set_config_int1(&data->driver, &config_int);
/* enable data ready interrupt on INT1 pin */
return cfg->bus_io->write(&cfg->bus, REG_INT_SOURCE0, BIT_INT_DRDY_INT1_EN);
return err;
}
void icm42670_lock(const struct device *dev)

View file

@ -0,0 +1,50 @@
/*
* Copyright (c) 2024 TDK Invensense
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_DRIVERS_SENSOR_ICM42670_H_
#define ZEPHYR_INCLUDE_DRIVERS_SENSOR_ICM42670_H_
#include <zephyr/drivers/sensor.h>
/**
* @file
* @brief Extended public API for ICM42670 6-axis MEMS sensor
*
* Some capabilities and operational requirements for this sensor
* cannot be expressed within the sensor driver abstraction.
*/
/** ICM42670 power mode */
#define ICM42670_LOW_NOISE_MODE (0)
#define ICM42670_LOW_POWER_MODE (1)
/**
* @brief Extended sensor attributes for ICM42670 6-axis MEMS sensor
*
* This exposes attributes for the ICM42670 which can be used for
* setting the signal path filtering parameters.
*
* The signal path starts with ADCs for the gyroscope and accelerometer.
* Low-Noise Mode and Low-Power Mode options are available for the
* accelerometer. Only Low-Noise Mode is available for gyroscope.
* In Low-Noise Mode, the ADC output is sent through an Anti-Alias Filter
* (AAF). The AAF is a filter with fixed coefficients (not user configurable),
* also the AAF cannot be bypassed. The AAF is followed by a 1st Order Low Pass
* Filter (LPF) with user selectable filter bandwidth options.
* In Low-Power Mode, the accelerometer ADC output is sent through an Average
* filter, with user configurable average filter setting.
* The output of 1st Order LPF in Low-Noise Mode, or Average filter in Low-Power
* Mode is subject to ODR selection, with user selectable ODR.
*/
enum sensor_attribute_icm42670 {
/** BW filtering */
/** Low-pass filter configuration */
SENSOR_ATTR_BW_FILTER_LPF = SENSOR_ATTR_PRIV_START,
/** Averaging configuration */
SENSOR_ATTR_AVERAGING,
};
#endif /* ZEPHYR_INCLUDE_DRIVERS_SENSOR_ICM42670_H_ */

View file

@ -0,0 +1,47 @@
/*
* Copyright (c) 2024 TDK Invensense
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_DRIVERS_SENSOR_TDK_APEX_H_
#define ZEPHYR_INCLUDE_DRIVERS_SENSOR_TDK_APEX_H_
#include <zephyr/drivers/sensor.h>
/**
* @file
* @brief Extended public API for TDK MEMS sensor
*
* Some capabilities and operational requirements for this sensor
* cannot be expressed within the sensor driver abstraction.
*/
/** TDK APEX features */
#define TDK_APEX_PEDOMETER (1)
#define TDK_APEX_TILT (2)
#define TDK_APEX_SMD (3)
#define TDK_APEX_WOM (4)
/**
* @brief Extended sensor channel for TDK MEMS supportintg APEX features
*
* This exposes sensor channel for the TDK MEMS which can be used for
* getting the APEX features data.
*
* The APEX (Advanced Pedometer and Event Detection neXt gen) features of
* TDK MEMS consist of:
* ** Pedometer: Tracks step count.
* ** Tilt Detection: Detect the Tilt angle exceeds 35 degrees.
* ** Wake on Motion (WoM): Detects motion when accelerometer samples exceed
* a programmable threshold. This motion event can be used to enable device
* operation from sleep mode.
* ** Significant Motion Detector (SMD): Detects significant motion based on
* accelerometer data.
*/
enum sensor_channel_tdk_apex {
/** APEX features */
SENSOR_CHAN_APEX_MOTION = SENSOR_CHAN_PRIV_START,
};
#endif /* ZEPHYR_INCLUDE_DRIVERS_SENSOR_TDK_APEX_H_ */