Skip to content

Commit 5bba20c

Browse files
committed
feat(icm42670): add support for spi interface in icm42670
1 parent 061f8d6 commit 5bba20c

File tree

5 files changed

+145
-60
lines changed

5 files changed

+145
-60
lines changed

components/sensors/icm42670/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER_EQUAL "5.3")
2-
set(REQ esp_driver_i2c)
2+
set(REQ esp_driver_i2c esp_driver_spi)
33
else()
44
set(REQ driver)
55
endif()

components/sensors/icm42670/README.md

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
[![Component Registry](https://components.espressif.com/components/espressif/icm42670/badge.svg)](https://components.espressif.com/components/espressif/icm42670)
44
![maintenance-status](https://img.shields.io/badge/maintenance-passively--maintained-yellowgreen.svg)
55

6-
C driver for Invensense ICM42607/ICM42670 6-axis gyroscope and accelerometer based on I2C communication.
6+
C driver for Invensense ICM42607/ICM42670 6-axis gyroscope and accelerometer based on I2C/SPI communication.
77

88
## Features
99

@@ -12,10 +12,6 @@ C driver for Invensense ICM42607/ICM42670 6-axis gyroscope and accelerometer bas
1212
- Configure gyroscope and accelerometer sensitivity.
1313
- ICM42607/ICM42670 power down mode.
1414

15-
## Limitations
16-
17-
- Only I2C communication is supported.
18-
1915
## Get Started
2016

2117
This driver, along with many other components from this repository, can be used as a package from [Espressif's IDF Component Registry](https://components.espressif.com). To include this driver in your project, run the following idf.py from the project's root directory:

components/sensors/icm42670/icm42670.c

Lines changed: 107 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
#include "iot_sensor_hub.h"
1717
#include "icm42670.h"
1818

19-
#define I2C_CLK_SPEED 400000
19+
#define ICM42670_I2C_CLK_SPEED 400000
20+
#define ICM42670_SPI_CLK_SPEED 1000000
2021

2122
#define ALPHA 0.97f /*!< Weight of gyroscope */
2223
#define RAD_TO_DEG 57.27272727f /*!< Radians to degrees */
@@ -47,72 +48,100 @@
4748
#define ACCE_FS_2G_SENSITIVITY (16384)
4849

4950
/*******************************************************************************
50-
* Types definitions
51-
*******************************************************************************/
51+
* Types definitions
52+
*******************************************************************************/
5253

53-
typedef struct {
54+
typedef struct
55+
{
56+
bool using_spi;
57+
spi_device_handle_t spi_handle;
5458
i2c_master_dev_handle_t i2c_handle;
5559
bool initialized_filter;
5660
uint64_t previous_measurement_us;
5761
complimentary_angle_t previous_measurement;
5862
} icm42670_dev_t;
5963

6064
/*******************************************************************************
61-
* Function definitions
62-
*******************************************************************************/
65+
* Function definitions
66+
*******************************************************************************/
6367
static esp_err_t icm42670_write(icm42670_handle_t sensor, const uint8_t reg_start_addr, const uint8_t *data_buf,
6468
const uint8_t data_len);
6569
static esp_err_t icm42670_read(icm42670_handle_t sensor, const uint8_t reg_start_addr, uint8_t *data_buf,
6670
const uint8_t data_len);
6771

6872
static esp_err_t icm42670_get_raw_value(icm42670_handle_t sensor, uint8_t reg, icm42670_raw_value_t *value);
69-
73+
static esp_err_t check_device_present(icm42670_handle_t sensor);
7074
/*******************************************************************************
71-
* Local variables
72-
*******************************************************************************/
75+
* Local variables
76+
*******************************************************************************/
7377
static const char *TAG = "ICM42670";
7478

7579
/*******************************************************************************
76-
* Public API functions
77-
*******************************************************************************/
80+
* Public API functions
81+
*******************************************************************************/
7882

79-
esp_err_t icm42670_create(i2c_master_bus_handle_t i2c_bus, const uint8_t dev_addr, icm42670_handle_t *handle_ret)
83+
esp_err_t icm42670_create_i2c(i2c_master_bus_handle_t i2c_bus, const uint8_t dev_addr, icm42670_handle_t *handle_ret)
8084
{
8185
esp_err_t ret = ESP_OK;
8286

8387
// Allocate memory and init the driver object
84-
icm42670_dev_t *sensor = (icm42670_dev_t *) calloc(1, sizeof(icm42670_dev_t));
85-
ESP_RETURN_ON_FALSE(sensor != NULL, ESP_ERR_NO_MEM, TAG, "Not enough memory");
88+
icm42670_dev_t *sensor = (icm42670_dev_t *)calloc(1, sizeof(icm42670_dev_t));
89+
ESP_RETURN_ON_FALSE(sensor, ESP_ERR_NO_MEM, TAG, "Not enough memory");
8690

8791
// Add new I2C device
8892
const i2c_device_config_t i2c_dev_cfg = {
8993
.device_address = dev_addr,
90-
.scl_speed_hz = I2C_CLK_SPEED,
94+
.scl_speed_hz = ICM42670_I2C_CLK_SPEED,
9195
};
9296
ESP_GOTO_ON_ERROR(i2c_master_bus_add_device(i2c_bus, &i2c_dev_cfg, &sensor->i2c_handle), err, TAG,
9397
"Failed to add new I2C device");
9498
assert(sensor->i2c_handle);
9599

96100
// Check device presence
97-
uint8_t dev_id = 0;
98-
icm42670_get_deviceid(sensor, &dev_id);
99-
ESP_GOTO_ON_FALSE(dev_id == ICM42607_ID
100-
|| dev_id == ICM42670_ID, ESP_ERR_NOT_FOUND, err, TAG, "Incorrect Device ID (0x%02x).", dev_id);
101+
ESP_GOTO_ON_ERROR(check_device_present(sensor), err, TAG, "Incorrect device ID received");
101102

102-
ESP_LOGD(TAG, "Found device %s, ID: 0x%02x", (dev_id == ICM42607_ID ? "ICM42607" : "ICM42670"), dev_id);
103103
*handle_ret = sensor;
104+
return ESP_OK;
105+
106+
err:
107+
icm42670_delete(sensor);
104108
return ret;
109+
}
110+
111+
esp_err_t icm42670_create_spi(spi_host_device_t spi_bus, gpio_num_t cs_pin, icm42670_handle_t *handle_ret)
112+
{
113+
esp_err_t ret = ESP_OK;
114+
icm42670_dev_t *sensor = (icm42670_dev_t *)calloc(1, sizeof(icm42670_dev_t));
115+
ESP_RETURN_ON_FALSE(sensor, ESP_ERR_NO_MEM, TAG, "Not enough memory");
116+
sensor->using_spi = true;
117+
118+
spi_device_interface_config_t dev_cfg = {
119+
.clock_speed_hz = ICM42670_SPI_CLK_SPEED,
120+
.spics_io_num = cs_pin,
121+
.mode = 3,
122+
.queue_size = 1,
123+
};
124+
ESP_GOTO_ON_ERROR(spi_bus_add_device(spi_bus, &dev_cfg, &sensor->spi_handle), err, TAG, "Failed to add new SPI device");
125+
assert(sensor->spi_handle);
105126

127+
ESP_GOTO_ON_ERROR(check_device_present(sensor), err, TAG, "Incorrect device ID received");
128+
129+
*handle_ret = sensor;
130+
return ESP_OK;
106131
err:
107132
icm42670_delete(sensor);
108133
return ret;
109134
}
110135

111136
void icm42670_delete(icm42670_handle_t sensor)
112137
{
113-
icm42670_dev_t *sens = (icm42670_dev_t *) sensor;
114-
115-
if (sens->i2c_handle) {
138+
icm42670_dev_t *sens = (icm42670_dev_t *)sensor;
139+
if (sens->using_spi && sens->spi_handle)
140+
{
141+
spi_bus_remove_device(sens->spi_handle);
142+
}
143+
else if (sens->i2c_handle)
144+
{
116145
i2c_master_bus_rm_device(sens->i2c_handle);
117146
}
118147

@@ -333,9 +362,25 @@ esp_err_t icm42670_get_temp_value(icm42670_handle_t sensor, float *value)
333362
}
334363

335364
/*******************************************************************************
336-
* Private functions
337-
*******************************************************************************/
365+
* Private functions
366+
*******************************************************************************/
338367

368+
static esp_err_t check_device_present(icm42670_handle_t sensor)
369+
{
370+
uint8_t dev_id = 0;
371+
esp_err_t ret = icm42670_get_deviceid(sensor, &dev_id);
372+
if (ret != ESP_OK)
373+
{
374+
return ret;
375+
}
376+
if (dev_id != ICM42607_ID && dev_id != ICM42670_ID)
377+
{
378+
ESP_LOGD(TAG, "Incorrect Device ID (0x%02x).", dev_id);
379+
return ESP_ERR_NOT_FOUND;
380+
}
381+
ESP_LOGD(TAG, "Found device %s, ID: 0x%02x", (dev_id == ICM42607_ID ? "ICM42607" : "ICM42670"), dev_id);
382+
return ESP_OK;
383+
}
339384
static esp_err_t icm42670_get_raw_value(icm42670_handle_t sensor, uint8_t reg, icm42670_raw_value_t *value)
340385
{
341386
esp_err_t ret = ESP_FAIL;
@@ -366,18 +411,47 @@ static esp_err_t icm42670_write(icm42670_handle_t sensor, const uint8_t reg_star
366411
assert(data_len < 5);
367412
uint8_t write_buff[5] = {reg_start_addr};
368413
memcpy(&write_buff[1], data_buf, data_len);
369-
return i2c_master_transmit(sens->i2c_handle, write_buff, data_len + 1, -1);
414+
if (sens->using_spi)
415+
{
416+
spi_transaction_t trans = {
417+
.length = (data_len + 1) * 8, // Total length in bits
418+
.tx_buffer = write_buff,
419+
};
420+
return spi_device_transmit(sens->spi_handle, &trans);
421+
}
422+
else
423+
{
424+
return i2c_master_transmit(sens->i2c_handle, write_buff, data_len + 1, -1);
425+
}
370426
}
371-
372427
static esp_err_t icm42670_read(icm42670_handle_t sensor, const uint8_t reg_start_addr, uint8_t *data_buf,
373428
const uint8_t data_len)
374429
{
375-
uint8_t reg_buff[] = {reg_start_addr};
376-
icm42670_dev_t *sens = (icm42670_dev_t *) sensor;
377-
assert(sens);
378-
379-
/* Write register number and read data */
380-
return i2c_master_transmit_receive(sens->i2c_handle, reg_buff, sizeof(reg_buff), data_buf, data_len, -1);
430+
icm42670_dev_t *sens = (icm42670_dev_t *)sensor;
431+
assert(sens && data_buf && data_len <= 6);
432+
esp_err_t ret;
433+
if (sens->using_spi)
434+
{
435+
uint8_t tx_buf[7] = {reg_start_addr | 0x80}; // Set MSB for read operation
436+
uint8_t rx_buf[7] = {0}; // Buffer to receive data (including the register address)
437+
spi_transaction_t trans = {
438+
.length = (data_len + 1) * 8, // Total length in bits
439+
.tx_buffer = tx_buf,
440+
.rx_buffer = rx_buf,
441+
};
442+
ret = spi_device_transmit(sens->spi_handle, &trans);
443+
if (ret == ESP_OK)
444+
{
445+
memcpy(data_buf, &rx_buf[1], data_len); // Skip the first byte (register address)
446+
}
447+
}
448+
else
449+
{
450+
uint8_t reg_buff[] = {reg_start_addr};
451+
/* Write register number and read data */
452+
ret = i2c_master_transmit_receive(sens->i2c_handle, reg_buff, sizeof(reg_buff), data_buf, data_len, -1);
453+
}
454+
return ret;
381455
}
382456

383457
esp_err_t icm42670_complimentory_filter(icm42670_handle_t sensor, const icm42670_value_t *const acce_value,

components/sensors/icm42670/idf_component.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
version: 2.1.0
2-
description: I2C driver for ICM 42670 6-Axis MotionTracking
2+
description: I2C/SPI driver for ICM 42670 6-Axis MotionTracking
33
url: https://github.com/espressif/esp-bsp/tree/master/components/sensors/icm42670
44
dependencies:
55
idf: ">=5.2"

components/sensors/icm42670/include/icm42670.h

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ extern "C" {
1111
#endif
1212

1313
#include "driver/i2c_master.h"
14+
#include "driver/spi_master.h"
1415

1516
#define ICM42670_I2C_ADDRESS 0x68 /*!< I2C address with AD0 pin low */
1617
#define ICM42670_I2C_ADDRESS_1 0x69 /*!< I2C address with AD0 pin high */
@@ -48,14 +49,14 @@ typedef enum {
4849
ACCE_FS_8G = 1, /*!< Accelerometer full scale range is +/- 8g */
4950
ACCE_FS_4G = 2, /*!< Accelerometer full scale range is +/- 4g */
5051
ACCE_FS_2G = 3, /*!< Accelerometer full scale range is +/- 2g */
51-
} icm42670_acce_fs_t;
52+
} icm42670_acce_fs_t;
5253

5354
typedef enum {
5455
ACCE_PWR_OFF = 0, /*!< Accelerometer power off state */
5556
ACCE_PWR_ON = 1, /*!< Accelerometer power on state */
5657
ACCE_PWR_LOWPOWER = 2, /*!< Accelerometer low-power mode */
5758
ACCE_PWR_LOWNOISE = 3, /*!< Accelerometer low noise state */
58-
} icm42670_acce_pwr_t;
59+
} icm42670_acce_pwr_t;
5960

6061
typedef enum {
6162
ACCE_ODR_1600HZ = 5, /*!< Accelerometer ODR 1.6 kHz */
@@ -68,32 +69,32 @@ typedef enum {
6869
ACCE_ODR_12_5HZ = 12, /*!< Accelerometer ODR 12.5 Hz */
6970
ACCE_ODR_6_25HZ = 13, /*!< Accelerometer ODR 6.25 Hz */
7071
ACCE_ODR_3_125HZ = 14, /*!< Accelerometer ODR 3.125 Hz */
71-
ACCE_ODR_1_5625HZ = 15, /*!< Accelerometer ODR 1.5625 Hz */
72-
} icm42670_acce_odr_t;
72+
ACCE_ODR_1_5625HZ = 15, /*!< Accelerometer ODR 1.5625 Hz */
73+
} icm42670_acce_odr_t;
7374

7475
typedef enum {
7576
GYRO_FS_2000DPS = 0, /*!< Gyroscope full scale range is +/- 2000 degree per sencond */
7677
GYRO_FS_1000DPS = 1, /*!< Gyroscope full scale range is +/- 1000 degree per sencond */
7778
GYRO_FS_500DPS = 2, /*!< Gyroscope full scale range is +/- 500 degree per sencond */
7879
GYRO_FS_250DPS = 3, /*!< Gyroscope full scale range is +/- 250 degree per sencond */
79-
} icm42670_gyro_fs_t;
80+
} icm42670_gyro_fs_t;
8081

8182
typedef enum {
8283
GYRO_PWR_OFF = 0, /*!< Gyroscope power off state */
8384
GYRO_PWR_STANDBY = 1, /*!< Gyroscope power standby state */
8485
GYRO_PWR_LOWNOISE = 3, /*!< Gyroscope power low noise state */
85-
} icm42670_gyro_pwr_t;
86+
} icm42670_gyro_pwr_t;
8687

8788
typedef enum {
88-
GYRO_ODR_1600HZ = 5, /*!< Gyroscope ODR 1.6 kHz */
89+
GYRO_ODR_1600HZ = 5, /*!< Gyroscope ODR 1.6 kHz */
8990
GYRO_ODR_800HZ = 6, /*!< Gyroscope ODR 800 Hz */
9091
GYRO_ODR_400HZ = 7, /*!< Gyroscope ODR 400 Hz */
9192
GYRO_ODR_200HZ = 8, /*!< Gyroscope ODR 200 Hz */
9293
GYRO_ODR_100HZ = 9, /*!< Gyroscope ODR 100 Hz */
9394
GYRO_ODR_50HZ = 10, /*!< Gyroscope ODR 50 Hz */
9495
GYRO_ODR_25HZ = 11, /*!< Gyroscope ODR 25 Hz */
95-
GYRO_ODR_12_5HZ = 12, /*!< Gyroscope ODR 12.5 Hz */
96-
} icm42670_gyro_odr_t;
96+
GYRO_ODR_12_5HZ = 12, /*!< Gyroscope ODR 12.5 Hz */
97+
} icm42670_gyro_odr_t;
9798

9899
typedef struct {
99100
icm42670_acce_fs_t acce_fs; /*!< Accelerometer full scale range */
@@ -103,26 +104,26 @@ typedef struct {
103104
} icm42670_cfg_t;
104105

105106
typedef struct {
106-
int16_t x;
107-
int16_t y;
108-
int16_t z;
107+
int16_t x;
108+
int16_t y;
109+
int16_t z;
109110
} icm42670_raw_value_t;
110111

111112
typedef struct {
112-
float x;
113-
float y;
114-
float z;
113+
float x;
114+
float y;
115+
float z;
115116
} icm42670_value_t;
116117

117118
typedef struct {
118-
float roll;
119-
float pitch;
119+
float roll;
120+
float pitch;
120121
} complimentary_angle_t;
121122

122123
typedef void *icm42670_handle_t;
123124

124125
/**
125-
* @brief Create and init sensor object
126+
* @brief Create and init sensor object using I2C interface
126127
*
127128
* @param[in] i2c_bus I2C bus handle. Obtained from i2c_new_master_bus()
128129
* @param[in] dev_addr I2C device address of sensor. Can be ICM42670_I2C_ADDRESS or ICM42670_I2C_ADDRESS_1
@@ -134,8 +135,22 @@ typedef void *icm42670_handle_t;
134135
* - ESP_ERR_NOT_FOUND Sensor not found on the I2C bus
135136
* - Others Error from underlying I2C driver
136137
*/
137-
esp_err_t icm42670_create(i2c_master_bus_handle_t i2c_bus, const uint8_t dev_addr, icm42670_handle_t *handle_ret);
138+
esp_err_t icm42670_create_i2c(i2c_master_bus_handle_t i2c_bus, const uint8_t dev_addr, icm42670_handle_t *handle_ret);
138139

140+
/**
141+
* @brief Create and init sensor object using SPI interface
142+
*
143+
* @param[in] spi_bus SPI bus handle. Obtained from spi_new_master_bus()
144+
* @param[in] cs_pin SPI chip select pin of sensor. Can be ICM42670_SPI_CS_PIN or ICM42670_SPI_CS_PI_1
145+
* @param[out] handle_ret Handle to created ICM42670 driver object
146+
*
147+
* @return
148+
* - ESP_OK Success
149+
* - ESP_ERR_NO_MEM Not enough memory for the driver
150+
* - ESP_ERR_NOT_FOUND Sensor not found on the I2C bus
151+
* - Others Error from underlying I2C driver
152+
*/
153+
esp_err_t icm42670_create_spi(spi_host_device_t spi_bus, gpio_num_t cs_pin, icm42670_handle_t *handle_ret);
139154
/**
140155
* @brief Delete and release a sensor object
141156
*
@@ -357,7 +372,7 @@ esp_err_t icm42670_read_mreg_register(icm42670_handle_t sensor, uint8_t mreg, ui
357372
* - ESP_FAIL Fail
358373
*/
359374
esp_err_t icm42670_write_mreg_register(icm42670_handle_t sensor, uint8_t mreg, uint8_t reg,
360-
uint8_t val);
375+
uint8_t val);
361376

362377
#ifdef __cplusplus
363378
}

0 commit comments

Comments
 (0)