Skip to content

Commit 7c41bf7

Browse files
committed
Implement ICM45686 I2CM interface
1 parent b0ae68d commit 7c41bf7

File tree

3 files changed

+161
-4
lines changed

3 files changed

+161
-4
lines changed

src/sensor/imu/ICM45686.c

Lines changed: 149 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,148 @@ int icm45_ext_passthrough(bool passthrough)
418418
return 0;
419419
}
420420

421+
int icm45_ext_setup() {
422+
int err = 0;
423+
err |= ssi_reg_write_byte(SENSOR_INTERFACE_DEV_IMU, ICM45686_IOC_PAD_SCENARIO_AUX_OVRD, 0x17); // AUX1_MODE_OVRD, AUX1 in I2CM Master, AUX1_ENABLE_OVRD, AUX1 enabled
424+
sensor_interface_ext_configure(&sensor_ext_icm45686);
425+
return err;
426+
}
427+
428+
int icm45_bank_write(const uint8_t bank, const uint8_t reg, const uint8_t *buf, uint32_t num_bytes)
429+
{
430+
if (num_bytes == 0)
431+
{
432+
LOG_ERR("Invalid bank write size");
433+
return -1;
434+
}
435+
436+
int err = 0;
437+
uint8_t ireg_buf[3];
438+
ireg_buf[0] = bank;
439+
ireg_buf[1] = reg;
440+
ireg_buf[2] = buf[0];
441+
err |= ssi_burst_write(SENSOR_INTERFACE_DEV_IMU, ICM45686_IREG_ADDR_15_8, ireg_buf, 3);
442+
k_usleep(4);
443+
444+
for (uint32_t i = 1; i < num_bytes; i++)
445+
{
446+
err |= ssi_reg_write_byte(SENSOR_INTERFACE_DEV_IMU, ICM45686_IREG_DATA, buf[i]);
447+
k_usleep(4);
448+
}
449+
450+
return err;
451+
}
452+
453+
int icm45_bank_write_byte(const uint8_t bank, const uint8_t reg, const uint8_t value)
454+
{
455+
return icm45_bank_write(bank, reg, &value, 1);
456+
}
457+
458+
int icm45_bank_read(const uint8_t bank, const uint8_t reg, uint8_t *buf, uint32_t num_bytes)
459+
{
460+
if (num_bytes == 0)
461+
{
462+
LOG_ERR("Invalid bank read size");
463+
return -1;
464+
}
465+
466+
int err = 0;
467+
uint8_t ireg_buf[2];
468+
ireg_buf[0] = bank;
469+
ireg_buf[1] = reg;
470+
err |= ssi_burst_write(SENSOR_INTERFACE_DEV_IMU, ICM45686_IREG_ADDR_15_8, ireg_buf, 2);
471+
k_usleep(4);
472+
473+
for (uint32_t i = 0; i < num_bytes; i++)
474+
{
475+
err |= ssi_reg_read_byte(SENSOR_INTERFACE_DEV_IMU, ICM45686_IREG_DATA, &buf[i]);
476+
k_usleep(4);
477+
}
478+
return err;
479+
}
480+
481+
int icm45_bank_read_byte(const uint8_t bank, const uint8_t reg, uint8_t *value) {
482+
return icm45_bank_read(bank, reg, value, 1);
483+
}
484+
485+
int icm45_ext_write(const uint8_t addr, const uint8_t *buf, uint32_t num_bytes)
486+
{
487+
if (num_bytes > 6)
488+
{
489+
LOG_ERR("Unsupported write");
490+
return -1;
491+
}
492+
493+
int err = 0;
494+
495+
err |= icm45_bank_write(ICM45686_IPREG_TOP1, ICM45686_I2CM_WR_DATA_0, buf, num_bytes);
496+
err |= icm45_bank_write_byte(ICM45686_IPREG_TOP1, ICM45686_I2CM_COMMAND_0, 0x80 + num_bytes); // Last transaction, channel 0, write num_bytes bytes
497+
err |= icm45_bank_write_byte(ICM45686_IPREG_TOP1, ICM45686_I2CM_CONTROL, 0x01); // No restarts, fast mode, start transaction
498+
499+
uint8_t last_status = 0;
500+
err |= icm45_bank_read_byte(ICM45686_IPREG_TOP1, ICM45686_I2CM_STATUS, &last_status);
501+
while (last_status & 0x01) // I2CM busy
502+
{
503+
err |= icm45_bank_read_byte(ICM45686_IPREG_TOP1, ICM45686_I2CM_STATUS, &last_status);
504+
}
505+
506+
if (last_status != 0x02) // Not (just) "done"
507+
{
508+
LOG_ERR("I2CM error: %02x", last_status);
509+
return -1;
510+
}
511+
512+
uint8_t dev_status;
513+
err |= icm45_bank_read_byte(ICM45686_IPREG_TOP1, ICM45686_I2CM_EXT_DEV_STATUS, &dev_status);
514+
515+
if (dev_status & 0x01) {
516+
// Maybe log the nack?
517+
return -1;
518+
}
519+
520+
return err;
521+
}
522+
523+
int icm45_ext_write_read(const uint8_t addr, const void *write_buf, size_t num_write, void *read_buf, size_t num_read) {
524+
if (num_write != 1 || num_read < 1 || num_read > 15)
525+
{
526+
LOG_ERR("Unsupported write_read");
527+
return -1;
528+
}
529+
530+
int err = 0;
531+
532+
uint8_t dev_profile_data[2] = {((const uint8_t *)write_buf)[0], addr};
533+
err |= icm45_bank_write(ICM45686_IPREG_TOP1, ICM45686_DEV_PROFILE_0, dev_profile_data, 2);
534+
err |= icm45_bank_write_byte(ICM45686_IPREG_TOP1, ICM45686_I2CM_COMMAND_0, 0x90 + num_read); // Last transaction, channel 0, read num_read bytes with register specified
535+
err |= icm45_bank_write_byte(ICM45686_IPREG_TOP1, ICM45686_I2CM_CONTROL, 0x01); // No restarts, fast mode, start transaction
536+
537+
uint8_t last_status = 0;
538+
err |= icm45_bank_read_byte(ICM45686_IPREG_TOP1, ICM45686_I2CM_STATUS, &last_status);
539+
while (last_status & 0x01) // I2CM busy
540+
{
541+
err |= icm45_bank_read_byte(ICM45686_IPREG_TOP1, ICM45686_I2CM_STATUS, &last_status);
542+
}
543+
544+
if (last_status != 0x02) // Not (just) "done"
545+
{
546+
LOG_ERR("I2CM error: %02x", last_status);
547+
return -1;
548+
}
549+
550+
uint8_t dev_status;
551+
err |= icm45_bank_read_byte(ICM45686_IPREG_TOP1, ICM45686_I2CM_EXT_DEV_STATUS, &dev_status);
552+
553+
if (dev_status & 0x01) {
554+
// Maybe log the nack?
555+
return -1;
556+
}
557+
558+
err |= icm45_bank_read(ICM45686_IPREG_TOP1, ICM45686_I2CM_RD_DATA_0, read_buf, num_read);
559+
560+
return err;
561+
}
562+
421563
const sensor_imu_t sensor_imu_icm45686 = {
422564
*icm45_init,
423565
*icm45_shutdown,
@@ -433,6 +575,12 @@ const sensor_imu_t sensor_imu_icm45686 = {
433575

434576
*icm45_setup_WOM,
435577

436-
*imu_none_ext_setup,
578+
*icm45_ext_setup,
437579
*icm45_ext_passthrough
438580
};
581+
582+
const sensor_ext_ssi_t sensor_ext_icm45686 = {
583+
*icm45_ext_write,
584+
*icm45_ext_write_read,
585+
15
586+
};

src/sensor/imu/ICM45686.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,15 @@
5050
// User Bank IPREG_TOP1
5151
#define ICM45686_IPREG_TOP1 0xA2 // MSB
5252

53+
#define ICM45686_I2CM_COMMAND_0 0x06
54+
#define ICM45686_DEV_PROFILE_0 0x0e
55+
#define ICM45686_DEV_PROFILE_1 0x0f
56+
#define ICM45686_I2CM_CONTROL 0x16
57+
#define ICM45686_I2CM_STATUS 0x18
58+
#define ICM45686_I2CM_EXT_DEV_STATUS 0x1a
59+
#define ICM45686_I2CM_RD_DATA_0 0x1b
60+
#define ICM45686_I2CM_WR_DATA_0 0x33
61+
5362
#define ICM45686_SMC_CONTROL_0 0x58
5463

5564
#define ICM45686_SREG_CTRL 0x67

src/sensor/interface.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,9 @@ int ssi_write(enum sensor_interface_dev dev, const uint8_t *buf, uint32_t num_by
143143
#endif
144144
case SENSOR_INTERFACE_SPEC_I2C:
145145
return i2c_write_dt(sensor_interface_dev_i2c[dev], buf, num_bytes);
146+
case SENSOR_INTERFACE_SPEC_EXT:
147+
if (ext_ssi != NULL)
148+
return ext_ssi->ext_write(ext_addr, buf, num_bytes);
146149
default:
147150
return -1;
148151
}
@@ -179,9 +182,6 @@ int ssi_read(enum sensor_interface_dev dev, uint8_t *buf, uint32_t num_bytes)
179182
#endif
180183
case SENSOR_INTERFACE_SPEC_I2C:
181184
return i2c_read_dt(sensor_interface_dev_i2c[dev], buf, num_bytes);
182-
case SENSOR_INTERFACE_SPEC_EXT:
183-
if (ext_ssi != NULL)
184-
return ext_ssi->ext_write(ext_addr, buf, num_bytes);
185185
default:
186186
return -1;
187187
}

0 commit comments

Comments
 (0)