Skip to content

Commit

Permalink
sensors: icm42688 async API
Browse files Browse the repository at this point in the history
Implementation of the async API for the icm42688

Signed-off-by: Al Semjonovs <[email protected]>
topic#icm42688_async
  • Loading branch information
asemjonovs authored and yperess committed Jun 5, 2023
1 parent 1f473d4 commit 8d9313f
Show file tree
Hide file tree
Showing 9 changed files with 521 additions and 63 deletions.
2 changes: 2 additions & 0 deletions drivers/sensor/icm42688/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ zephyr_library_sources(
icm42688_spi.c
)

zephyr_library_sources_ifdef(CONFIG_SENSOR_ASYNC_API icm42688_rtio.c)
zephyr_library_sources_ifdef(CONFIG_ICM42688_DECODER icm42688_decoder.c)
zephyr_library_sources_ifdef(CONFIG_ICM42688_TRIGGER icm42688_trigger.c)
zephyr_library_sources_ifdef(CONFIG_EMUL_ICM42688 icm42688_emul.c)
zephyr_include_directories_ifdef(CONFIG_EMUL_ICM42688 .)
8 changes: 8 additions & 0 deletions drivers/sensor/icm42688/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,18 @@ config EMUL_ICM42688
Enable the hardware emulator for the ICM42688. Doing so allows exercising
sensor APIs for this IMU in native_posix and qemu.

config ICM42688_DECODER
bool "ICM42688 decoder logic"
default y if ICM42688
help
Compile the ICM42688 decoder API which allows decoding raw data returned
from the sensor.

if ICM42688

choice
prompt "Trigger mode"
default ICM42688_TRIGGER_NONE if ICM42688_STREAM
default ICM42688_TRIGGER_GLOBAL_THREAD
help
Specify the type of triggering to be used by the driver
Expand Down
119 changes: 62 additions & 57 deletions drivers/sensor/icm42688/icm42688.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,15 @@
#include <zephyr/sys/byteorder.h>

#include "icm42688.h"
#include "icm42688_decoder.h"
#include "icm42688_reg.h"
#include "icm42688_rtio.h"
#include "icm42688_spi.h"
#include "icm42688_trigger.h"

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

struct icm42688_sensor_data {
struct icm42688_dev_data dev_data;

int16_t readings[7];
};

struct icm42688_sensor_config {
struct icm42688_dev_cfg dev_cfg;
};

static void icm42688_convert_accel(struct sensor_value *val, int16_t raw_val,
struct icm42688_cfg *cfg)
{
Expand All @@ -47,42 +39,40 @@ static inline void icm42688_convert_temp(struct sensor_value *val, int16_t raw_v
icm42688_temp_c((int32_t)raw_val, &val->val1, &val->val2);
}

static int icm42688_channel_get(const struct device *dev, enum sensor_channel chan,
struct sensor_value *val)
int icm42688_channel_parse_readings(enum sensor_channel chan, int16_t readings[7],
struct icm42688_cfg *cfg, struct sensor_value *val)
{
struct icm42688_sensor_data *data = dev->data;

switch (chan) {
case SENSOR_CHAN_ACCEL_XYZ:
icm42688_convert_accel(&val[0], data->readings[1], &data->dev_data.cfg);
icm42688_convert_accel(&val[1], data->readings[2], &data->dev_data.cfg);
icm42688_convert_accel(&val[2], data->readings[3], &data->dev_data.cfg);
icm42688_convert_accel(&val[0], readings[1], cfg);
icm42688_convert_accel(&val[1], readings[2], cfg);
icm42688_convert_accel(&val[2], readings[3], cfg);
break;
case SENSOR_CHAN_ACCEL_X:
icm42688_convert_accel(val, data->readings[1], &data->dev_data.cfg);
icm42688_convert_accel(val, readings[1], cfg);
break;
case SENSOR_CHAN_ACCEL_Y:
icm42688_convert_accel(val, data->readings[2], &data->dev_data.cfg);
icm42688_convert_accel(val, readings[2], cfg);
break;
case SENSOR_CHAN_ACCEL_Z:
icm42688_convert_accel(val, data->readings[3], &data->dev_data.cfg);
icm42688_convert_accel(val, readings[3], cfg);
break;
case SENSOR_CHAN_GYRO_XYZ:
icm42688_convert_gyro(&val[0], data->readings[4], &data->dev_data.cfg);
icm42688_convert_gyro(&val[1], data->readings[5], &data->dev_data.cfg);
icm42688_convert_gyro(&val[2], data->readings[6], &data->dev_data.cfg);
icm42688_convert_gyro(&val[0], readings[4], cfg);
icm42688_convert_gyro(&val[1], readings[5], cfg);
icm42688_convert_gyro(&val[2], readings[6], cfg);
break;
case SENSOR_CHAN_GYRO_X:
icm42688_convert_gyro(val, data->readings[4], &data->dev_data.cfg);
icm42688_convert_gyro(val, readings[4], cfg);
break;
case SENSOR_CHAN_GYRO_Y:
icm42688_convert_gyro(val, data->readings[5], &data->dev_data.cfg);
icm42688_convert_gyro(val, readings[5], cfg);
break;
case SENSOR_CHAN_GYRO_Z:
icm42688_convert_gyro(val, data->readings[6], &data->dev_data.cfg);
icm42688_convert_gyro(val, readings[6], cfg);
break;
case SENSOR_CHAN_DIE_TEMP:
icm42688_convert_temp(val, data->readings[0]);
icm42688_convert_temp(val, readings[0]);
break;
default:
return -ENOTSUP;
Expand All @@ -91,13 +81,21 @@ static int icm42688_channel_get(const struct device *dev, enum sensor_channel ch
return 0;
}

static int icm42688_channel_get(const struct device *dev, enum sensor_channel chan,
struct sensor_value *val)
{
struct icm42688_dev_data *data = dev->data;

return icm42688_channel_parse_readings(chan, data->readings, &data->cfg, val);
}

static int icm42688_sample_fetch(const struct device *dev, enum sensor_channel chan)
{
uint8_t status;
struct icm42688_sensor_data *data = dev->data;
const struct icm42688_sensor_config *cfg = dev->config;
struct icm42688_dev_data *data = dev->data;
const struct icm42688_dev_cfg *cfg = dev->config;

int res = icm42688_spi_read(&cfg->dev_cfg.spi, REG_INT_STATUS, &status, 1);
int res = icm42688_spi_read(&cfg->spi, REG_INT_STATUS, &status, 1);

if (res) {
return res;
Expand Down Expand Up @@ -125,8 +123,8 @@ static int icm42688_sample_fetch(const struct device *dev, enum sensor_channel c
static int icm42688_attr_set(const struct device *dev, enum sensor_channel chan,
enum sensor_attribute attr, const struct sensor_value *val)
{
const struct icm42688_sensor_data *data = dev->data;
struct icm42688_cfg new_config = data->dev_data.cfg;
const struct icm42688_dev_data *data = dev->data;
struct icm42688_cfg new_config = data->cfg;
int res = 0;

__ASSERT_NO_MSG(val != NULL);
Expand Down Expand Up @@ -173,8 +171,8 @@ static int icm42688_attr_set(const struct device *dev, enum sensor_channel chan,
static int icm42688_attr_get(const struct device *dev, enum sensor_channel chan,
enum sensor_attribute attr, struct sensor_value *val)
{
const struct icm42688_sensor_data *data = dev->data;
const struct icm42688_cfg *cfg = &data->dev_data.cfg;
const struct icm42688_dev_data *data = dev->data;
const struct icm42688_cfg *cfg = &data->cfg;
int res = 0;

__ASSERT_NO_MSG(val != NULL);
Expand Down Expand Up @@ -223,15 +221,17 @@ static const struct sensor_driver_api icm42688_driver_api = {
#ifdef CONFIG_ICM42688_TRIGGER
.trigger_set = icm42688_trigger_set,
#endif
.get_decoder = icm42688_get_decoder,
.submit = icm42688_submit,
};

int icm42688_init(const struct device *dev)
{
struct icm42688_sensor_data *data = dev->data;
const struct icm42688_sensor_config *cfg = dev->config;
struct icm42688_dev_data *data = dev->data;
const struct icm42688_dev_cfg *cfg = dev->config;
int res;

if (!spi_is_ready_dt(&cfg->dev_cfg.spi)) {
if (!spi_is_ready_dt(&cfg->spi)) {
LOG_ERR("SPI bus is not ready");
return -ENODEV;
}
Expand All @@ -247,22 +247,18 @@ int icm42688_init(const struct device *dev)
LOG_ERR("Failed to initialize triggers");
return res;
}

res = icm42688_trigger_enable_interrupt(dev);
if (res != 0) {
LOG_ERR("Failed to enable triggers");
return res;
}
#endif

data->dev_data.cfg.accel_mode = ICM42688_ACCEL_LN;
data->dev_data.cfg.gyro_mode = ICM42688_GYRO_LN;
data->dev_data.cfg.accel_fs = ICM42688_ACCEL_FS_2G;
data->dev_data.cfg.gyro_fs = ICM42688_GYRO_FS_125;
data->dev_data.cfg.accel_odr = ICM42688_ACCEL_ODR_1000;
data->dev_data.cfg.gyro_odr = ICM42688_GYRO_ODR_1000;
memset(&data->cfg, 0, sizeof(struct icm42688_cfg));
data->cfg.accel_mode = ICM42688_ACCEL_LN;
data->cfg.gyro_mode = ICM42688_GYRO_LN;
data->cfg.accel_fs = ICM42688_ACCEL_FS_2G;
data->cfg.gyro_fs = ICM42688_GYRO_FS_125;
data->cfg.accel_odr = ICM42688_ACCEL_ODR_1000;
data->cfg.gyro_odr = ICM42688_GYRO_ODR_1000;
data->cfg.fifo_en = IS_ENABLED(CONFIG_ICM42688_STREAM);

res = icm42688_configure(dev, &data->dev_data.cfg);
res = icm42688_configure(dev, &data->cfg);
if (res != 0) {
LOG_ERR("Failed to configure");
return res;
Expand All @@ -286,16 +282,25 @@ void icm42688_unlock(const struct device *dev)
#define ICM42688_SPI_CFG \
SPI_OP_MODE_MASTER | SPI_MODE_CPOL | SPI_MODE_CPHA | SPI_WORD_SET(8) | SPI_TRANSFER_MSB

#define ICM42688_RTIO_DEFINE(inst) \
SPI_DT_IODEV_DEFINE(icm42688_spi_iodev_##inst, DT_DRV_INST(inst), ICM42688_SPI_CFG, 0U); \
RTIO_DEFINE(icm42688_rtio_##inst, 8, 4);

#define ICM42688_DEFINE_DATA(inst) \
IF_ENABLED(CONFIG_ICM42688_STREAM, (ICM42688_RTIO_DEFINE(inst))); \
static struct icm42688_dev_data icm42688_driver_##inst = { \
IF_ENABLED(CONFIG_ICM42688_STREAM, ( \
.r = &icm42688_rtio_##inst, \
.spi_iodev = &icm42688_spi_iodev_##inst, \
)) \
};

#define ICM42688_INIT(inst) \
static struct icm42688_sensor_data icm42688_driver_##inst = { 0 }; \
ICM42688_DEFINE_DATA(inst); \
\
static const struct icm42688_sensor_config icm42688_cfg_##inst = { \
.dev_cfg = \
{ \
.spi = SPI_DT_SPEC_INST_GET(inst, ICM42688_SPI_CFG, 0U), \
.gpio_int1 = GPIO_DT_SPEC_INST_GET_OR(inst, int_gpios, {0}), \
}, \
static const struct icm42688_dev_cfg icm42688_cfg_##inst = { \
.spi = SPI_DT_SPEC_INST_GET(inst, ICM42688_SPI_CFG, 0U), \
.gpio_int1 = GPIO_DT_SPEC_INST_GET_OR(inst, int_gpios, {0}), \
}; \
\
SENSOR_DEVICE_DT_INST_DEFINE(inst, icm42688_init, NULL, &icm42688_driver_##inst, \
Expand Down
12 changes: 7 additions & 5 deletions drivers/sensor/icm42688/icm42688.h
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,8 @@ struct icm42688_dev_data {
const struct sensor_trigger *data_ready_trigger;
struct k_mutex mutex;
#endif /* CONFIG_ICM42688_TRIGGER */

int16_t readings[7];
};

/**
Expand Down Expand Up @@ -515,7 +517,7 @@ static inline void icm42688_accel_g(struct icm42688_cfg *cfg, int32_t in, int32_
* @param out_dps whole deg/s output in int32_t
* @param out_udps micro (1/1000000) deg/s as uint32_t
*/
static inline void icm42688_gyro_dps(struct icm42688_cfg *cfg, int32_t in, int32_t *out_dps,
static inline void icm42688_gyro_dps(const struct icm42688_cfg *cfg, int32_t in, int32_t *out_dps,
uint32_t *out_udps)
{
int64_t sensitivity = 0; /* value equivalent for 10x gyro reading deg/s */
Expand Down Expand Up @@ -565,8 +567,8 @@ static inline void icm42688_gyro_dps(struct icm42688_cfg *cfg, int32_t in, int32
* @param out_ms meters/s^2 (whole) output in int32_t
* @param out_ums micrometers/s^2 output as uint32_t
*/
static inline void icm42688_accel_ms(struct icm42688_cfg *cfg, int32_t in, int32_t *out_ms,
uint32_t *out_ums)
static inline void icm42688_accel_ms(const struct icm42688_cfg *cfg, int32_t in, int32_t *out_ms,
int32_t *out_ums)
{
int64_t sensitivity = 0; /* value equivalent for 1g */

Expand Down Expand Up @@ -603,8 +605,8 @@ static inline void icm42688_accel_ms(struct icm42688_cfg *cfg, int32_t in, int32
* @param out_rads whole rad/s output in int32_t
* @param out_urads microrad/s as uint32_t
*/
static inline void icm42688_gyro_rads(struct icm42688_cfg *cfg, int32_t in, int32_t *out_rads,
uint32_t *out_urads)
static inline void icm42688_gyro_rads(const struct icm42688_cfg *cfg, int32_t in, int32_t *out_rads,
int32_t *out_urads)
{
int64_t sensitivity = 0; /* value equivalent for 10x gyro reading deg/s */

Expand Down
Loading

0 comments on commit 8d9313f

Please sign in to comment.