Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tdk invensense icm42x70 support 3axis #83498

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/releases/release-notes-4.1.rst
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,7 @@ New Drivers
* :dtcompatible:`adi,adxl366`
* :dtcompatible:`hc-sr04`
* :dtcompatible:`invensense,icm42670s`
* :dtcompatible:`invensense,icm42370`
* :dtcompatible:`maxim,ds3231-sensor`
* :dtcompatible:`melexis,mlx90394`
* :dtcompatible:`nordic,npm2100-vbat`
Expand Down
2 changes: 1 addition & 1 deletion drivers/sensor/tdk/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

# zephyr-keep-sorted-start
add_subdirectory_ifdef(CONFIG_ICM42605 icm42605)
add_subdirectory_ifdef(CONFIG_ICM42670 icm42670)
add_subdirectory_ifdef(CONFIG_ICM42688 icm42688)
add_subdirectory_ifdef(CONFIG_ICM42X70 icm42x70)
add_subdirectory_ifdef(CONFIG_ICP10125 icp10125)
add_subdirectory_ifdef(CONFIG_MPU6050 mpu6050)
add_subdirectory_ifdef(CONFIG_MPU9250 mpu9250)
Expand Down
2 changes: 1 addition & 1 deletion drivers/sensor/tdk/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

# zephyr-keep-sorted-start
source "drivers/sensor/tdk/icm42605/Kconfig"
source "drivers/sensor/tdk/icm42670/Kconfig"
source "drivers/sensor/tdk/icm42688/Kconfig"
source "drivers/sensor/tdk/icm42x70/Kconfig"
source "drivers/sensor/tdk/icp10125/Kconfig"
source "drivers/sensor/tdk/mpu6050/Kconfig"
source "drivers/sensor/tdk/mpu9250/Kconfig"
Expand Down
11 changes: 0 additions & 11 deletions drivers/sensor/tdk/icm42670/CMakeLists.txt

This file was deleted.

46 changes: 0 additions & 46 deletions drivers/sensor/tdk/icm42670/icm42670_trigger.h

This file was deleted.

13 changes: 13 additions & 0 deletions drivers/sensor/tdk/icm42x70/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# SPDX-License-Identifier: Apache-2.0

zephyr_library()

zephyr_library_sources(icm42x70.c)

zephyr_library_sources_ifdef(CONFIG_SPI icm42x70_spi.c)
zephyr_library_sources_ifdef(CONFIG_I2C icm42x70_i2c.c)

zephyr_library_sources_ifdef(CONFIG_USE_EMD_ICM42670 icm42670.c)

zephyr_library_sources_ifdef(CONFIG_ICM42X70_TRIGGER icm42x70_trigger.c)
zephyr_library_sources_ifdef(CONFIG_TDK_APEX icm42x70_apex.c)
Original file line number Diff line number Diff line change
Expand Up @@ -8,69 +8,81 @@
config TDK_APEX
bool

menuconfig ICM42670
bool "ICM42670-P/-S Six-Axis Motion Tracking Device"
menuconfig ICM42X70
bool "ICM42670-P/-S Six-Axis or ICM42370-P Three-Axis Motion Tracking Device"
default y
depends on DT_HAS_INVENSENSE_ICM42670P_ENABLED \
|| DT_HAS_INVENSENSE_ICM42670S_ENABLED
|| DT_HAS_INVENSENSE_ICM42670S_ENABLED \
|| DT_HAS_INVENSENSE_ICM42370P_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)
|| $(dt_compat_on_bus,$(DT_COMPAT_INVENSENSE_ICM42670S),spi) \
|| $(dt_compat_on_bus,$(DT_COMPAT_INVENSENSE_ICM42370P),spi)
select I2C if $(dt_compat_on_bus,$(DT_COMPAT_INVENSENSE_ICM42670P),i2c) \
|| $(dt_compat_on_bus,$(DT_COMPAT_INVENSENSE_ICM42670S),i2c)
|| $(dt_compat_on_bus,$(DT_COMPAT_INVENSENSE_ICM42670S),i2c) \
|| $(dt_compat_on_bus,$(DT_COMPAT_INVENSENSE_ICM42370P),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)
|| $(dt_node_str_prop_equals,$(dt_nodelabel_path,icm42670s),apex,wom) \
|| $(dt_node_str_prop_equals,$(dt_nodelabel_path,icm42370p),apex,pedometer) \
|| $(dt_node_str_prop_equals,$(dt_nodelabel_path,icm42370p),apex,tilt) \
|| $(dt_node_str_prop_equals,$(dt_nodelabel_path,icm42370p),apex,smd) \
|| $(dt_node_str_prop_equals,$(dt_nodelabel_path,icm42370p),apex,wom)
select USE_EMD_ICM42670 if DT_HAS_INVENSENSE_ICM42670P_ENABLED || DT_HAS_INVENSENSE_ICM42670S_ENABLED
select USE_EMD_ICM42370 if DT_HAS_INVENSENSE_ICM42370P_ENABLED
select SENSOR_ASYNC_API
help
Enable driver for ICM42670 SPI-based or I2C-based Six-Axis Motion Tracking device.
Enable driver for ICM42x70 SPI-based or I2C-based Six-Axis or Three-Axis Motion Tracking device.

if ICM42670
if ICM42X70

choice ICM42670_TRIGGER_MODE
choice ICM42X70_TRIGGER_MODE
prompt "Trigger mode"
default ICM42670_TRIGGER_NONE
default ICM42X70_TRIGGER_NONE
help
Specify the type of triggering to be used by the driver.

config ICM42670_TRIGGER_NONE
config ICM42X70_TRIGGER_NONE
bool "No trigger"

config ICM42670_TRIGGER_GLOBAL_THREAD
config ICM42X70_TRIGGER_GLOBAL_THREAD
bool "Use global thread"
depends on GPIO
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
|| $(dt_compat_any_has_prop,$(DT_COMPAT_INVENSENSE_ICM42670S),int-gpios) \
|| $(dt_compat_any_has_prop,$(DT_COMPAT_INVENSENSE_ICM42370P),int-gpios)
select ICM42X70_TRIGGER

config ICM42670_TRIGGER_OWN_THREAD
config ICM42X70_TRIGGER_OWN_THREAD
bool "Use own thread"
depends on GPIO
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
|| $(dt_compat_any_has_prop,$(DT_COMPAT_INVENSENSE_ICM42670S),int-gpios) \
|| $(dt_compat_any_has_prop,$(DT_COMPAT_INVENSENSE_ICM42370P),int-gpios)
select ICM42X70_TRIGGER

endchoice

config ICM42670_TRIGGER
config ICM42X70_TRIGGER
bool

config ICM42670_THREAD_PRIORITY
config ICM42X70_THREAD_PRIORITY
int "Thread priority"
depends on ICM42670_TRIGGER_OWN_THREAD
depends on ICM42X70_TRIGGER_OWN_THREAD
default 10
help
Priority of thread used by the driver to handle interrupts.

config ICM42670_THREAD_STACK_SIZE
config ICM42X70_THREAD_STACK_SIZE
int "Thread stack size"
depends on ICM42670_TRIGGER_OWN_THREAD
depends on ICM42X70_TRIGGER_OWN_THREAD
default 1024
help
Stack size of thread used by the driver to handle interrupts.

endif # ICM42670
endif # ICM42X70
137 changes: 137 additions & 0 deletions drivers/sensor/tdk/icm42x70/icm42670.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/*
* Copyright (c) 2025 TDK Invensense
*
* SPDX-License-Identifier: Apache-2.0
*/

#include "icm42670.h"

#include <zephyr/drivers/sensor/icm42x70.h>
#include <zephyr/sys/byteorder.h>

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(ICM42670, CONFIG_SENSOR_LOG_LEVEL);

static uint32_t convert_gyr_fs_to_bitfield(uint32_t val, uint16_t *fs)
{
uint32_t bitfield = 0;

if (val < 500 && val >= 250) {
bitfield = GYRO_CONFIG0_FS_SEL_250dps;
*fs = 250;
} else if (val < 1000 && val >= 500) {
bitfield = GYRO_CONFIG0_FS_SEL_500dps;
*fs = 500;
} else if (val < 2000 && val >= 1000) {
bitfield = GYRO_CONFIG0_FS_SEL_1000dps;
*fs = 1000;
} else if (val == 2000) {
bitfield = GYRO_CONFIG0_FS_SEL_2000dps;
*fs = 2000;
}
return bitfield;
}

static int icm42670_set_gyro_odr(struct icm42x70_data *drv_data, const struct sensor_value *val)
{
if (val->val1 <= 1600 && val->val1 > 12) {
if (drv_data->gyro_hz == 0) {
inv_imu_set_gyro_frequency(
&drv_data->driver,
convert_freq_to_bitfield(val->val1, &drv_data->gyro_hz));
inv_imu_enable_gyro_low_noise_mode(&drv_data->driver);
} else {
inv_imu_set_gyro_frequency(
&drv_data->driver,
convert_freq_to_bitfield(val->val1, &drv_data->gyro_hz));
}
} else if (val->val1 == 0) {
inv_imu_disable_gyro(&drv_data->driver);
drv_data->gyro_hz = val->val1;
} else {
LOG_ERR("Incorrect sampling value");
return -EINVAL;
}
return 0;
}

static int icm42670_set_gyro_fs(struct icm42x70_data *drv_data, const struct sensor_value *val)
{
if (val->val1 > 2000 || val->val1 < 250) {
LOG_ERR("Incorrect fullscale value");
return -EINVAL;
}
inv_imu_set_gyro_fsr(&drv_data->driver,
convert_gyr_fs_to_bitfield(val->val1, &drv_data->gyro_fs));
LOG_DBG("Set gyro fullscale to: %d dps", drv_data->gyro_fs);
return 0;
}

int icm42670_gyro_config(struct icm42x70_data *drv_data, enum sensor_attribute attr,
const struct sensor_value *val)
{
if (attr == SENSOR_ATTR_SAMPLING_FREQUENCY) {
icm42670_set_gyro_odr(drv_data, val);

} else if (attr == SENSOR_ATTR_FULL_SCALE) {
icm42670_set_gyro_fs(drv_data, val);

} else if ((enum sensor_attribute_icm42x70)attr == SENSOR_ATTR_BW_FILTER_LPF) {
if (val->val1 > 180) {
LOG_ERR("Incorrect low pass filter bandwidth value");
return -EINVAL;
}
inv_imu_set_gyro_ln_bw(&drv_data->driver, convert_ln_bw_to_bitfield(val->val1));

} else {
LOG_ERR("Unsupported attribute");
return -EINVAL;
}
return 0;
}

void icm42670_convert_gyro(struct sensor_value *val, int16_t raw_val, uint16_t fs)
{
int64_t conv_val;

/* 16 bit gyroscope. 2^15 bits represent the range in degrees/s */
/* see datasheet section 3.1 for details */
conv_val = ((int64_t)raw_val * fs * SENSOR_PI) / (INT16_MAX * 180U);

val->val1 = conv_val / 1000000;
val->val2 = conv_val % 1000000;
}

int icm42670_sample_fetch_gyro(const struct device *dev)
{
struct icm42x70_data *data = dev->data;
uint8_t buffer[GYRO_DATA_SIZE];

int res = inv_imu_read_reg(&data->driver, GYRO_DATA_X1, GYRO_DATA_SIZE, buffer);

if (res) {
return res;
}

data->gyro_x = (int16_t)sys_get_be16(&buffer[0]);
data->gyro_y = (int16_t)sys_get_be16(&buffer[2]);
data->gyro_z = (int16_t)sys_get_be16(&buffer[4]);

return 0;
}

uint16_t convert_bitfield_to_gyr_fs(uint8_t bitfield)
{
uint16_t gyr_fs = 0;

if (bitfield == GYRO_CONFIG0_FS_SEL_250dps) {
gyr_fs = 250;
} else if (bitfield == GYRO_CONFIG0_FS_SEL_500dps) {
gyr_fs = 500;
} else if (bitfield == GYRO_CONFIG0_FS_SEL_1000dps) {
gyr_fs = 1000;
} else if (bitfield == GYRO_CONFIG0_FS_SEL_2000dps) {
gyr_fs = 2000;
}
return gyr_fs;
}
22 changes: 22 additions & 0 deletions drivers/sensor/tdk/icm42x70/icm42670.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright (c) 2025 TDK Invensense
*
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef ZEPHYR_DRIVERS_SENSOR_ICM42670_H_
#define ZEPHYR_DRIVERS_SENSOR_ICM42670_H_

#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/kernel.h>

#include "icm42x70.h"

int icm42670_gyro_config(struct icm42x70_data *drv_data, enum sensor_attribute attr,
const struct sensor_value *val);
void icm42670_convert_gyro(struct sensor_value *val, int16_t raw_val, uint16_t fs);
int icm42670_sample_fetch_gyro(const struct device *dev);
uint16_t convert_bitfield_to_gyr_fs(uint8_t bitfield);

#endif /* ZEPHYR_DRIVERS_SENSOR_ICM42670_H_ */
Loading
Loading