zephyr/drivers/sensor/tdk/icm42688/icm42688_decoder.c
Tom Burdick 058253b4b6 icm42688: Follow st's devicetree bindings
Fix the devicetree bindings to actually be used as the default
configuration, following the example set by various ST sensor devices.

This requires sadly dropping enums and using #defines for various
options as well as repeating many numbers, but presumably is the way to
do it given the precedent set by ST with sensors like the lsm6dso.

Signed-off-by: Tom Burdick <thomas.burdick@intel.com>
2024-06-26 14:13:21 -04:00

702 lines
19 KiB
C

/*
* Copyright (c) 2023 Google LLC
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "icm42688_decoder.h"
#include "icm42688_reg.h"
#include "icm42688.h"
#include <errno.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(ICM42688_DECODER, CONFIG_SENSOR_LOG_LEVEL);
#define DT_DRV_COMPAT invensense_icm42688
static int icm42688_get_shift(enum sensor_channel channel, int accel_fs, int gyro_fs, int8_t *shift)
{
switch (channel) {
case SENSOR_CHAN_ACCEL_XYZ:
case SENSOR_CHAN_ACCEL_X:
case SENSOR_CHAN_ACCEL_Y:
case SENSOR_CHAN_ACCEL_Z:
switch (accel_fs) {
case ICM42688_DT_ACCEL_FS_2:
*shift = 5;
return 0;
case ICM42688_DT_ACCEL_FS_4:
*shift = 6;
return 0;
case ICM42688_DT_ACCEL_FS_8:
*shift = 7;
return 0;
case ICM42688_DT_ACCEL_FS_16:
*shift = 8;
return 0;
default:
return -EINVAL;
}
case SENSOR_CHAN_GYRO_XYZ:
case SENSOR_CHAN_GYRO_X:
case SENSOR_CHAN_GYRO_Y:
case SENSOR_CHAN_GYRO_Z:
switch (gyro_fs) {
case ICM42688_DT_GYRO_FS_15_625:
*shift = -1;
return 0;
case ICM42688_DT_GYRO_FS_31_25:
*shift = 0;
return 0;
case ICM42688_DT_GYRO_FS_62_5:
*shift = 1;
return 0;
case ICM42688_DT_GYRO_FS_125:
*shift = 2;
return 0;
case ICM42688_DT_GYRO_FS_250:
*shift = 3;
return 0;
case ICM42688_DT_GYRO_FS_500:
*shift = 4;
return 0;
case ICM42688_DT_GYRO_FS_1000:
*shift = 5;
return 0;
case ICM42688_DT_GYRO_FS_2000:
*shift = 6;
return 0;
default:
return -EINVAL;
}
case SENSOR_CHAN_DIE_TEMP:
*shift = 9;
return 0;
default:
return -EINVAL;
}
}
int icm42688_convert_raw_to_q31(struct icm42688_cfg *cfg, enum sensor_channel chan, int32_t reading,
q31_t *out)
{
int32_t whole;
int32_t fraction;
int64_t intermediate;
int8_t shift;
int rc;
rc = icm42688_get_shift(chan, cfg->accel_fs, cfg->gyro_fs, &shift);
if (rc != 0) {
return rc;
}
switch (chan) {
case SENSOR_CHAN_ACCEL_XYZ:
case SENSOR_CHAN_ACCEL_X:
case SENSOR_CHAN_ACCEL_Y:
case SENSOR_CHAN_ACCEL_Z:
icm42688_accel_ms(cfg, reading, &whole, &fraction);
break;
case SENSOR_CHAN_GYRO_XYZ:
case SENSOR_CHAN_GYRO_X:
case SENSOR_CHAN_GYRO_Y:
case SENSOR_CHAN_GYRO_Z:
icm42688_gyro_rads(cfg, reading, &whole, &fraction);
break;
case SENSOR_CHAN_DIE_TEMP:
icm42688_temp_c(reading, &whole, &fraction);
break;
default:
return -ENOTSUP;
}
intermediate = ((int64_t)whole * INT64_C(1000000) + fraction);
if (shift < 0) {
intermediate =
intermediate * ((int64_t)INT32_MAX + 1) * (1 << -shift) / INT64_C(1000000);
} else if (shift > 0) {
intermediate =
intermediate * ((int64_t)INT32_MAX + 1) / ((1 << shift) * INT64_C(1000000));
}
*out = CLAMP(intermediate, INT32_MIN, INT32_MAX);
return 0;
}
static int icm42688_get_channel_position(enum sensor_channel chan)
{
switch (chan) {
case SENSOR_CHAN_DIE_TEMP:
return 0;
case SENSOR_CHAN_ACCEL_XYZ:
case SENSOR_CHAN_ACCEL_X:
return 1;
case SENSOR_CHAN_ACCEL_Y:
return 2;
case SENSOR_CHAN_ACCEL_Z:
return 3;
case SENSOR_CHAN_GYRO_XYZ:
case SENSOR_CHAN_GYRO_X:
return 4;
case SENSOR_CHAN_GYRO_Y:
return 5;
case SENSOR_CHAN_GYRO_Z:
return 6;
default:
return 0;
}
}
static uint8_t icm42688_encode_channel(enum sensor_channel chan)
{
uint8_t encode_bmask = 0;
switch (chan) {
case SENSOR_CHAN_DIE_TEMP:
case SENSOR_CHAN_ACCEL_X:
case SENSOR_CHAN_ACCEL_Y:
case SENSOR_CHAN_ACCEL_Z:
case SENSOR_CHAN_GYRO_X:
case SENSOR_CHAN_GYRO_Y:
case SENSOR_CHAN_GYRO_Z:
encode_bmask = BIT(icm42688_get_channel_position(chan));
break;
case SENSOR_CHAN_ACCEL_XYZ:
encode_bmask = BIT(icm42688_get_channel_position(SENSOR_CHAN_ACCEL_X)) |
BIT(icm42688_get_channel_position(SENSOR_CHAN_ACCEL_Y)) |
BIT(icm42688_get_channel_position(SENSOR_CHAN_ACCEL_Z));
break;
case SENSOR_CHAN_GYRO_XYZ:
encode_bmask = BIT(icm42688_get_channel_position(SENSOR_CHAN_GYRO_X)) |
BIT(icm42688_get_channel_position(SENSOR_CHAN_GYRO_Y)) |
BIT(icm42688_get_channel_position(SENSOR_CHAN_GYRO_Z));
break;
default:
break;
}
return encode_bmask;
}
int icm42688_encode(const struct device *dev, const struct sensor_chan_spec *const channels,
const size_t num_channels, uint8_t *buf)
{
struct icm42688_dev_data *data = dev->data;
struct icm42688_encoded_data *edata = (struct icm42688_encoded_data *)buf;
edata->channels = 0;
for (int i = 0; i < num_channels; i++) {
edata->channels |= icm42688_encode_channel(channels[i].chan_type);
}
edata->header.is_fifo = false;
edata->header.accel_fs = data->cfg.accel_fs;
edata->header.gyro_fs = data->cfg.gyro_fs;
edata->header.timestamp = k_ticks_to_ns_floor64(k_uptime_ticks());
return 0;
}
#define IS_ACCEL(chan) ((chan) >= SENSOR_CHAN_ACCEL_X && (chan) <= SENSOR_CHAN_ACCEL_XYZ)
#define IS_GYRO(chan) ((chan) >= SENSOR_CHAN_GYRO_X && (chan) <= SENSOR_CHAN_GYRO_XYZ)
static inline q31_t icm42688_read_temperature_from_packet(const uint8_t *pkt)
{
int32_t temperature;
int32_t whole;
int32_t fraction;
/* Temperature always assumes a shift of 9 for a range of (-273,273) C */
if (FIELD_GET(FIFO_HEADER_20, pkt[0]) == 1) {
temperature = (pkt[0xd] << 8) | pkt[0xe];
icm42688_temp_c(temperature, &whole, &fraction);
} else {
if (FIELD_GET(FIFO_HEADER_ACCEL, pkt[0]) == 1 &&
FIELD_GET(FIFO_HEADER_GYRO, pkt[0]) == 1) {
temperature = pkt[0xd];
} else {
temperature = pkt[0x7];
}
int64_t sensitivity = 207;
int64_t temperature100 = (temperature * 100) + (25 * sensitivity);
whole = temperature100 / sensitivity;
fraction =
((temperature100 - whole * sensitivity) * INT64_C(1000000)) / sensitivity;
}
__ASSERT_NO_MSG(whole >= -512 && whole <= 511);
return FIELD_PREP(GENMASK(31, 22), whole) | (fraction * GENMASK64(21, 0) / 1000000);
}
static int icm42688_read_imu_from_packet(const uint8_t *pkt, bool is_accel, int fs,
uint8_t axis_offset, q31_t *out)
{
int32_t value;
int64_t scale = 0;
int32_t max = BIT(15);
int offset = 1 + (axis_offset * 2);
if (is_accel) {
switch (fs) {
case ICM42688_DT_ACCEL_FS_2:
scale = INT64_C(2) * BIT(31 - 5) * 9.80665;
break;
case ICM42688_DT_ACCEL_FS_4:
scale = INT64_C(4) * BIT(31 - 6) * 9.80665;
break;
case ICM42688_DT_ACCEL_FS_8:
scale = INT64_C(8) * BIT(31 - 7) * 9.80665;
break;
case ICM42688_DT_ACCEL_FS_16:
scale = INT64_C(16) * BIT(31 - 8) * 9.80665;
break;
}
} else {
switch (fs) {
case ICM42688_DT_GYRO_FS_2000:
scale = 164;
break;
case ICM42688_DT_GYRO_FS_1000:
scale = 328;
break;
case ICM42688_DT_GYRO_FS_500:
scale = 655;
break;
case ICM42688_DT_GYRO_FS_250:
scale = 1310;
break;
case ICM42688_DT_GYRO_FS_125:
scale = 2620;
break;
case ICM42688_DT_GYRO_FS_62_5:
scale = 5243;
break;
case ICM42688_DT_GYRO_FS_31_25:
scale = 10486;
break;
case ICM42688_DT_GYRO_FS_15_625:
scale = 20972;
break;
}
}
if (!is_accel && FIELD_GET(FIFO_HEADER_ACCEL, pkt[0]) == 1) {
offset += 7;
}
value = (int16_t)sys_le16_to_cpu((pkt[offset] << 8) | pkt[offset + 1]);
if (FIELD_GET(FIFO_HEADER_20, pkt[0]) == 1) {
uint32_t mask = is_accel ? GENMASK(7, 4) : GENMASK(3, 0);
offset = 0x11 + axis_offset;
value = (value << 4) | FIELD_GET(mask, pkt[offset]);
/* In 20 bit mode, FS can only be +/-16g and +/-2000dps */
scale = is_accel ? (INT64_C(16) * BIT(8) * 9.80665) : 131;
max = is_accel ? BIT(18) : BIT(19);
if (value == -524288) {
/* Invalid 20 bit value */
return -ENODATA;
}
} else {
if (value <= -32767) {
/* Invalid 16 bit value */
return -ENODATA;
}
}
*out = (q31_t)(value * scale / max);
return 0;
}
static uint32_t accel_period_ns[] = {
[ICM42688_DT_ACCEL_ODR_1_5625] = UINT32_C(10000000000000) / 15625,
[ICM42688_DT_ACCEL_ODR_3_125] = UINT32_C(10000000000000) / 31250,
[ICM42688_DT_ACCEL_ODR_6_25] = UINT32_C(10000000000000) / 62500,
[ICM42688_DT_ACCEL_ODR_12_5] = UINT32_C(10000000000000) / 12500,
[ICM42688_DT_ACCEL_ODR_25] = UINT32_C(1000000000) / 25,
[ICM42688_DT_ACCEL_ODR_50] = UINT32_C(1000000000) / 50,
[ICM42688_DT_ACCEL_ODR_100] = UINT32_C(1000000000) / 100,
[ICM42688_DT_ACCEL_ODR_200] = UINT32_C(1000000000) / 200,
[ICM42688_DT_ACCEL_ODR_500] = UINT32_C(1000000000) / 500,
[ICM42688_DT_ACCEL_ODR_1000] = UINT32_C(1000000),
[ICM42688_DT_ACCEL_ODR_2000] = UINT32_C(1000000) / 2,
[ICM42688_DT_ACCEL_ODR_4000] = UINT32_C(1000000) / 4,
[ICM42688_DT_ACCEL_ODR_8000] = UINT32_C(1000000) / 8,
[ICM42688_DT_ACCEL_ODR_16000] = UINT32_C(1000000) / 16,
[ICM42688_DT_ACCEL_ODR_32000] = UINT32_C(1000000) / 32,
};
static uint32_t gyro_period_ns[] = {
[ICM42688_DT_GYRO_ODR_12_5] = UINT32_C(10000000000000) / 12500,
[ICM42688_DT_GYRO_ODR_25] = UINT32_C(1000000000) / 25,
[ICM42688_DT_GYRO_ODR_50] = UINT32_C(1000000000) / 50,
[ICM42688_DT_GYRO_ODR_100] = UINT32_C(1000000000) / 100,
[ICM42688_DT_GYRO_ODR_200] = UINT32_C(1000000000) / 200,
[ICM42688_DT_GYRO_ODR_500] = UINT32_C(1000000000) / 500,
[ICM42688_DT_GYRO_ODR_1000] = UINT32_C(1000000),
[ICM42688_DT_GYRO_ODR_2000] = UINT32_C(1000000) / 2,
[ICM42688_DT_GYRO_ODR_4000] = UINT32_C(1000000) / 4,
[ICM42688_DT_GYRO_ODR_8000] = UINT32_C(1000000) / 8,
[ICM42688_DT_GYRO_ODR_16000] = UINT32_C(1000000) / 16,
[ICM42688_DT_GYRO_ODR_32000] = UINT32_C(1000000) / 32,
};
static int icm42688_fifo_decode(const uint8_t *buffer, struct sensor_chan_spec chan_spec,
uint32_t *fit, uint16_t max_count, void *data_out)
{
const struct icm42688_fifo_data *edata = (const struct icm42688_fifo_data *)buffer;
const uint8_t *buffer_end = buffer + sizeof(struct icm42688_fifo_data) + edata->fifo_count;
int accel_frame_count = 0;
int gyro_frame_count = 0;
int count = 0;
int rc;
if ((uintptr_t)buffer_end <= *fit || chan_spec.chan_idx != 0) {
return 0;
}
((struct sensor_data_header *)data_out)->base_timestamp_ns = edata->header.timestamp;
buffer += sizeof(struct icm42688_fifo_data);
while (count < max_count && buffer < buffer_end) {
const bool is_20b = FIELD_GET(FIFO_HEADER_20, buffer[0]) == 1;
const bool has_accel = FIELD_GET(FIFO_HEADER_ACCEL, buffer[0]) == 1;
const bool has_gyro = FIELD_GET(FIFO_HEADER_GYRO, buffer[0]) == 1;
const uint8_t *frame_end = buffer;
if (is_20b) {
frame_end += 20;
} else if (has_accel && has_gyro) {
frame_end += 16;
} else {
frame_end += 8;
}
if (has_accel) {
accel_frame_count++;
}
if (has_gyro) {
gyro_frame_count++;
}
if ((uintptr_t)buffer < *fit) {
/* This frame was already decoded, move on to the next frame */
buffer = frame_end;
continue;
}
if (chan_spec.chan_type == SENSOR_CHAN_DIE_TEMP) {
struct sensor_q31_data *data = (struct sensor_q31_data *)data_out;
data->shift = 9;
if (has_accel) {
data->readings[count].timestamp_delta =
accel_period_ns[edata->accel_odr] * (accel_frame_count - 1);
} else {
data->readings[count].timestamp_delta =
gyro_period_ns[edata->gyro_odr] * (gyro_frame_count - 1);
}
data->readings[count].temperature =
icm42688_read_temperature_from_packet(buffer);
} else if (IS_ACCEL(chan_spec.chan_type) && has_accel) {
/* Decode accel */
struct sensor_three_axis_data *data =
(struct sensor_three_axis_data *)data_out;
uint64_t period_ns = accel_period_ns[edata->accel_odr];
icm42688_get_shift(SENSOR_CHAN_ACCEL_XYZ, edata->header.accel_fs,
edata->header.gyro_fs, &data->shift);
data->readings[count].timestamp_delta = (accel_frame_count - 1) * period_ns;
rc = icm42688_read_imu_from_packet(buffer, true, edata->header.accel_fs, 0,
&data->readings[count].x);
rc |= icm42688_read_imu_from_packet(buffer, true, edata->header.accel_fs, 1,
&data->readings[count].y);
rc |= icm42688_read_imu_from_packet(buffer, true, edata->header.accel_fs, 2,
&data->readings[count].z);
if (rc != 0) {
accel_frame_count--;
buffer = frame_end;
continue;
}
} else if (IS_GYRO(chan_spec.chan_type) && has_gyro) {
/* Decode gyro */
struct sensor_three_axis_data *data =
(struct sensor_three_axis_data *)data_out;
uint64_t period_ns = accel_period_ns[edata->gyro_odr];
icm42688_get_shift(SENSOR_CHAN_GYRO_XYZ, edata->header.accel_fs,
edata->header.gyro_fs, &data->shift);
data->readings[count].timestamp_delta = (gyro_frame_count - 1) * period_ns;
rc = icm42688_read_imu_from_packet(buffer, false, edata->header.gyro_fs, 0,
&data->readings[count].x);
rc |= icm42688_read_imu_from_packet(buffer, false, edata->header.gyro_fs, 1,
&data->readings[count].y);
rc |= icm42688_read_imu_from_packet(buffer, false, edata->header.gyro_fs, 2,
&data->readings[count].z);
if (rc != 0) {
gyro_frame_count--;
buffer = frame_end;
continue;
}
}
buffer = frame_end;
*fit = (uintptr_t)frame_end;
count++;
}
return count;
}
static int icm42688_one_shot_decode(const uint8_t *buffer, struct sensor_chan_spec chan_spec,
uint32_t *fit, uint16_t max_count, void *data_out)
{
const struct icm42688_encoded_data *edata = (const struct icm42688_encoded_data *)buffer;
const struct icm42688_decoder_header *header = &edata->header;
struct icm42688_cfg cfg = {
.accel_fs = edata->header.accel_fs,
.gyro_fs = edata->header.gyro_fs,
};
uint8_t channel_request;
int rc;
if (*fit != 0) {
return 0;
}
if (max_count == 0 || chan_spec.chan_idx != 0) {
return -EINVAL;
}
switch (chan_spec.chan_type) {
case SENSOR_CHAN_ACCEL_X:
case SENSOR_CHAN_ACCEL_Y:
case SENSOR_CHAN_ACCEL_Z:
case SENSOR_CHAN_ACCEL_XYZ: {
channel_request = icm42688_encode_channel(SENSOR_CHAN_ACCEL_XYZ);
if ((channel_request & edata->channels) != channel_request) {
return -ENODATA;
}
struct sensor_three_axis_data *out = data_out;
out->header.base_timestamp_ns = edata->header.timestamp;
out->header.reading_count = 1;
rc = icm42688_get_shift(SENSOR_CHAN_ACCEL_XYZ, header->accel_fs, header->gyro_fs,
&out->shift);
if (rc != 0) {
return -EINVAL;
}
icm42688_convert_raw_to_q31(
&cfg, SENSOR_CHAN_ACCEL_X,
edata->readings[icm42688_get_channel_position(SENSOR_CHAN_ACCEL_X)],
&out->readings[0].x);
icm42688_convert_raw_to_q31(
&cfg, SENSOR_CHAN_ACCEL_Y,
edata->readings[icm42688_get_channel_position(SENSOR_CHAN_ACCEL_Y)],
&out->readings[0].y);
icm42688_convert_raw_to_q31(
&cfg, SENSOR_CHAN_ACCEL_Z,
edata->readings[icm42688_get_channel_position(SENSOR_CHAN_ACCEL_Z)],
&out->readings[0].z);
*fit = 1;
return 1;
}
case SENSOR_CHAN_GYRO_X:
case SENSOR_CHAN_GYRO_Y:
case SENSOR_CHAN_GYRO_Z:
case SENSOR_CHAN_GYRO_XYZ: {
channel_request = icm42688_encode_channel(SENSOR_CHAN_GYRO_XYZ);
if ((channel_request & edata->channels) != channel_request) {
return -ENODATA;
}
struct sensor_three_axis_data *out = data_out;
out->header.base_timestamp_ns = edata->header.timestamp;
out->header.reading_count = 1;
rc = icm42688_get_shift(SENSOR_CHAN_GYRO_XYZ, header->accel_fs, header->gyro_fs,
&out->shift);
if (rc != 0) {
return -EINVAL;
}
out->readings[0].timestamp_delta = 0;
icm42688_convert_raw_to_q31(
&cfg, SENSOR_CHAN_GYRO_X,
edata->readings[icm42688_get_channel_position(SENSOR_CHAN_GYRO_X)],
&out->readings[0].x);
icm42688_convert_raw_to_q31(
&cfg, SENSOR_CHAN_GYRO_Y,
edata->readings[icm42688_get_channel_position(SENSOR_CHAN_GYRO_Y)],
&out->readings[0].y);
icm42688_convert_raw_to_q31(
&cfg, SENSOR_CHAN_GYRO_Z,
edata->readings[icm42688_get_channel_position(SENSOR_CHAN_GYRO_Z)],
&out->readings[0].z);
*fit = 1;
return 1;
}
case SENSOR_CHAN_DIE_TEMP: {
channel_request = icm42688_encode_channel(SENSOR_CHAN_DIE_TEMP);
if ((channel_request & edata->channels) != channel_request) {
return -ENODATA;
}
struct sensor_q31_data *out = data_out;
out->header.base_timestamp_ns = edata->header.timestamp;
out->header.reading_count = 1;
rc = icm42688_get_shift(SENSOR_CHAN_DIE_TEMP, header->accel_fs, header->gyro_fs,
&out->shift);
if (rc != 0) {
return -EINVAL;
}
out->readings[0].timestamp_delta = 0;
icm42688_convert_raw_to_q31(
&cfg, SENSOR_CHAN_DIE_TEMP,
edata->readings[icm42688_get_channel_position(SENSOR_CHAN_DIE_TEMP)],
&out->readings[0].temperature);
*fit = 1;
return 1;
}
default:
return -EINVAL;
}
}
static int icm42688_decoder_decode(const uint8_t *buffer, struct sensor_chan_spec chan_spec,
uint32_t *fit, uint16_t max_count, void *data_out)
{
const struct icm42688_decoder_header *header =
(const struct icm42688_decoder_header *)buffer;
if (header->is_fifo) {
return icm42688_fifo_decode(buffer, chan_spec, fit, max_count, data_out);
}
return icm42688_one_shot_decode(buffer, chan_spec, fit, max_count, data_out);
}
static int icm42688_decoder_get_frame_count(const uint8_t *buffer,
struct sensor_chan_spec chan_spec,
uint16_t *frame_count)
{
const struct icm42688_fifo_data *data = (const struct icm42688_fifo_data *)buffer;
const struct icm42688_decoder_header *header = &data->header;
if (chan_spec.chan_idx != 0) {
return -ENOTSUP;
}
if (!header->is_fifo) {
switch (chan_spec.chan_type) {
case SENSOR_CHAN_ACCEL_X:
case SENSOR_CHAN_ACCEL_Y:
case SENSOR_CHAN_ACCEL_Z:
case SENSOR_CHAN_ACCEL_XYZ:
case SENSOR_CHAN_GYRO_X:
case SENSOR_CHAN_GYRO_Y:
case SENSOR_CHAN_GYRO_Z:
case SENSOR_CHAN_GYRO_XYZ:
case SENSOR_CHAN_DIE_TEMP:
*frame_count = 1;
return 0;
default:
return -ENOTSUP;
}
return 0;
}
/* Skip the header */
buffer += sizeof(struct icm42688_fifo_data);
uint16_t count = 0;
const uint8_t *end = buffer + data->fifo_count;
while (buffer < end) {
bool is_20b = FIELD_GET(FIFO_HEADER_20, buffer[0]);
int size = is_20b ? 3 : 2;
if (FIELD_GET(FIFO_HEADER_ACCEL, buffer[0])) {
size += 6;
}
if (FIELD_GET(FIFO_HEADER_GYRO, buffer[0])) {
size += 6;
}
if (FIELD_GET(FIFO_HEADER_TIMESTAMP_FSYNC, buffer[0])) {
size += 2;
}
if (is_20b) {
size += 3;
}
buffer += size;
++count;
}
*frame_count = count;
return 0;
}
static int icm42688_decoder_get_size_info(struct sensor_chan_spec chan_spec, size_t *base_size,
size_t *frame_size)
{
switch (chan_spec.chan_type) {
case SENSOR_CHAN_ACCEL_X:
case SENSOR_CHAN_ACCEL_Y:
case SENSOR_CHAN_ACCEL_Z:
case SENSOR_CHAN_ACCEL_XYZ:
case SENSOR_CHAN_GYRO_X:
case SENSOR_CHAN_GYRO_Y:
case SENSOR_CHAN_GYRO_Z:
case SENSOR_CHAN_GYRO_XYZ:
*base_size = sizeof(struct sensor_three_axis_data);
*frame_size = sizeof(struct sensor_three_axis_sample_data);
return 0;
case SENSOR_CHAN_DIE_TEMP:
*base_size = sizeof(struct sensor_q31_data);
*frame_size = sizeof(struct sensor_q31_sample_data);
return 0;
default:
return -ENOTSUP;
}
}
static bool icm24688_decoder_has_trigger(const uint8_t *buffer, enum sensor_trigger_type trigger)
{
const struct icm42688_fifo_data *edata = (const struct icm42688_fifo_data *)buffer;
if (!edata->header.is_fifo) {
return false;
}
switch (trigger) {
case SENSOR_TRIG_DATA_READY:
return FIELD_GET(BIT_INT_STATUS_DATA_RDY, edata->int_status);
case SENSOR_TRIG_FIFO_WATERMARK:
return FIELD_GET(BIT_INT_STATUS_FIFO_THS, edata->int_status);
case SENSOR_TRIG_FIFO_FULL:
return FIELD_GET(BIT_INT_STATUS_FIFO_FULL, edata->int_status);
default:
return false;
}
}
SENSOR_DECODER_API_DT_DEFINE() = {
.get_frame_count = icm42688_decoder_get_frame_count,
.get_size_info = icm42688_decoder_get_size_info,
.decode = icm42688_decoder_decode,
.has_trigger = icm24688_decoder_has_trigger,
};
int icm42688_get_decoder(const struct device *dev, const struct sensor_decoder_api **decoder)
{
ARG_UNUSED(dev);
*decoder = &SENSOR_DECODER_NAME();
return 0;
}