|
16 | 16 | #include "iot_sensor_hub.h" |
17 | 17 | #include "icm42670.h" |
18 | 18 |
|
19 | | -#define I2C_CLK_SPEED 400000 |
| 19 | +#define ICM42670_I2C_CLK_SPEED 400000 |
| 20 | +#define ICM42670_SPI_CLK_SPEED 1000000 |
20 | 21 |
|
21 | 22 | #define ALPHA 0.97f /*!< Weight of gyroscope */ |
22 | 23 | #define RAD_TO_DEG 57.27272727f /*!< Radians to degrees */ |
|
47 | 48 | #define ACCE_FS_2G_SENSITIVITY (16384) |
48 | 49 |
|
49 | 50 | /******************************************************************************* |
50 | | -* Types definitions |
51 | | -*******************************************************************************/ |
| 51 | + * Types definitions |
| 52 | + *******************************************************************************/ |
52 | 53 |
|
53 | | -typedef struct { |
| 54 | +typedef struct |
| 55 | +{ |
| 56 | + bool using_spi; |
| 57 | + spi_device_handle_t spi_handle; |
54 | 58 | i2c_master_dev_handle_t i2c_handle; |
55 | 59 | bool initialized_filter; |
56 | 60 | uint64_t previous_measurement_us; |
57 | 61 | complimentary_angle_t previous_measurement; |
58 | 62 | } icm42670_dev_t; |
59 | 63 |
|
60 | 64 | /******************************************************************************* |
61 | | -* Function definitions |
62 | | -*******************************************************************************/ |
| 65 | + * Function definitions |
| 66 | + *******************************************************************************/ |
63 | 67 | static esp_err_t icm42670_write(icm42670_handle_t sensor, const uint8_t reg_start_addr, const uint8_t *data_buf, |
64 | 68 | const uint8_t data_len); |
65 | 69 | static esp_err_t icm42670_read(icm42670_handle_t sensor, const uint8_t reg_start_addr, uint8_t *data_buf, |
66 | 70 | const uint8_t data_len); |
67 | 71 |
|
68 | 72 | 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); |
70 | 74 | /******************************************************************************* |
71 | | -* Local variables |
72 | | -*******************************************************************************/ |
| 75 | + * Local variables |
| 76 | + *******************************************************************************/ |
73 | 77 | static const char *TAG = "ICM42670"; |
74 | 78 |
|
75 | 79 | /******************************************************************************* |
76 | | -* Public API functions |
77 | | -*******************************************************************************/ |
| 80 | + * Public API functions |
| 81 | + *******************************************************************************/ |
78 | 82 |
|
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) |
80 | 84 | { |
81 | 85 | esp_err_t ret = ESP_OK; |
82 | 86 |
|
83 | 87 | // 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"); |
86 | 90 |
|
87 | 91 | // Add new I2C device |
88 | 92 | const i2c_device_config_t i2c_dev_cfg = { |
89 | 93 | .device_address = dev_addr, |
90 | | - .scl_speed_hz = I2C_CLK_SPEED, |
| 94 | + .scl_speed_hz = ICM42670_I2C_CLK_SPEED, |
91 | 95 | }; |
92 | 96 | ESP_GOTO_ON_ERROR(i2c_master_bus_add_device(i2c_bus, &i2c_dev_cfg, &sensor->i2c_handle), err, TAG, |
93 | 97 | "Failed to add new I2C device"); |
94 | 98 | assert(sensor->i2c_handle); |
95 | 99 |
|
96 | 100 | // 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"); |
101 | 102 |
|
102 | | - ESP_LOGD(TAG, "Found device %s, ID: 0x%02x", (dev_id == ICM42607_ID ? "ICM42607" : "ICM42670"), dev_id); |
103 | 103 | *handle_ret = sensor; |
| 104 | + return ESP_OK; |
| 105 | + |
| 106 | +err: |
| 107 | + icm42670_delete(sensor); |
104 | 108 | 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); |
105 | 126 |
|
| 127 | + ESP_GOTO_ON_ERROR(check_device_present(sensor), err, TAG, "Incorrect device ID received"); |
| 128 | + |
| 129 | + *handle_ret = sensor; |
| 130 | + return ESP_OK; |
106 | 131 | err: |
107 | 132 | icm42670_delete(sensor); |
108 | 133 | return ret; |
109 | 134 | } |
110 | 135 |
|
111 | 136 | void icm42670_delete(icm42670_handle_t sensor) |
112 | 137 | { |
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 | + { |
116 | 145 | i2c_master_bus_rm_device(sens->i2c_handle); |
117 | 146 | } |
118 | 147 |
|
@@ -333,9 +362,25 @@ esp_err_t icm42670_get_temp_value(icm42670_handle_t sensor, float *value) |
333 | 362 | } |
334 | 363 |
|
335 | 364 | /******************************************************************************* |
336 | | -* Private functions |
337 | | -*******************************************************************************/ |
| 365 | + * Private functions |
| 366 | + *******************************************************************************/ |
338 | 367 |
|
| 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 | +} |
339 | 384 | static esp_err_t icm42670_get_raw_value(icm42670_handle_t sensor, uint8_t reg, icm42670_raw_value_t *value) |
340 | 385 | { |
341 | 386 | 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 |
366 | 411 | assert(data_len < 5); |
367 | 412 | uint8_t write_buff[5] = {reg_start_addr}; |
368 | 413 | 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 | + } |
370 | 426 | } |
371 | | - |
372 | 427 | static esp_err_t icm42670_read(icm42670_handle_t sensor, const uint8_t reg_start_addr, uint8_t *data_buf, |
373 | 428 | const uint8_t data_len) |
374 | 429 | { |
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; |
381 | 455 | } |
382 | 456 |
|
383 | 457 | esp_err_t icm42670_complimentory_filter(icm42670_handle_t sensor, const icm42670_value_t *const acce_value, |
|
0 commit comments