|
| 1 | +/* |
| 2 | + * Copyright 2025 CogniPilot Foundation |
| 3 | + * SPDX-License-Identifier: Apache-2.0 |
| 4 | + */ |
| 5 | + |
| 6 | +#include <stdio.h> |
| 7 | +#include <math.h> |
| 8 | +#include <zephyr/device.h> |
| 9 | +#include <zephyr/kernel.h> |
| 10 | +#include <zephyr/ztest.h> |
| 11 | +#include <zephyr/rtio/rtio.h> |
| 12 | +#include <zephyr/drivers/sensor.h> |
| 13 | +#include <zephyr/logging/log.h> |
| 14 | + |
| 15 | +#define BATCH_DURATION 50 |
| 16 | + |
| 17 | +double q31_to_double(int32_t q31_value, int8_t shift) |
| 18 | +{ |
| 19 | + return ((double)q31_value) / (double)(1 << (31 - shift)); |
| 20 | +} |
| 21 | + |
| 22 | +static struct rtio_sqe *streaming_handle; |
| 23 | + |
| 24 | +static struct sensor_stream_trigger stream_trigger = { |
| 25 | + .opt = SENSOR_STREAM_DATA_INCLUDE, |
| 26 | + .trigger = SENSOR_TRIG_FIFO_WATERMARK, |
| 27 | +}; |
| 28 | + |
| 29 | +static struct sensor_read_config stream_config = { |
| 30 | + .sensor = DEVICE_DT_GET(DT_NODELABEL(icm42688_1)), |
| 31 | + .is_streaming = true, |
| 32 | + .triggers = &stream_trigger, |
| 33 | + .count = 0, |
| 34 | + .max = 1, |
| 35 | +}; |
| 36 | + |
| 37 | +static RTIO_IODEV_DEFINE(iodev_stream, &__sensor_iodev_api, &stream_config); |
| 38 | +RTIO_DEFINE_WITH_MEMPOOL(rtio, 4, 4, 32, 64, 4); |
| 39 | + |
| 40 | +static void callback(int result, uint8_t *buf, uint32_t buf_len, void *userdata) |
| 41 | +{ |
| 42 | + static uint8_t decoded_buffer[127]; |
| 43 | + |
| 44 | + zassert_not_null(stream_config.sensor->api); |
| 45 | + const struct sensor_decoder_api *decoder; |
| 46 | + |
| 47 | + zassert_ok(sensor_get_decoder(stream_config.sensor, &decoder)); |
| 48 | + int channels[] = { |
| 49 | + SENSOR_CHAN_GYRO_XYZ, |
| 50 | + SENSOR_CHAN_ACCEL_XYZ, |
| 51 | + }; |
| 52 | + |
| 53 | + for (int i = 0; i < ARRAY_SIZE(channels); i++) { |
| 54 | + int chan = channels[i]; |
| 55 | + struct sensor_chan_spec ch = { |
| 56 | + .chan_idx = 0, |
| 57 | + .chan_type = chan, |
| 58 | + }; |
| 59 | + |
| 60 | + uint32_t fit = 0; |
| 61 | + int count = 0; |
| 62 | + |
| 63 | + while (decoder->decode(buf, ch, &fit, 1, decoded_buffer) > 0) { |
| 64 | + zassert(count++ < 127, "fifo overflow"); |
| 65 | + if (ch.chan_type == SENSOR_CHAN_ACCEL_XYZ) { |
| 66 | + struct sensor_three_axis_data *data = |
| 67 | + (struct sensor_three_axis_data *)decoded_buffer; |
| 68 | + double x = q31_to_double(data->readings[0].values[0], data->shift); |
| 69 | + double y = q31_to_double(data->readings[0].values[1], data->shift); |
| 70 | + double z = q31_to_double(data->readings[0].values[2], data->shift); |
| 71 | + |
| 72 | + zassert(fabs(x) < 1.0, "fail", "accel x out of range: %10.4f", x); |
| 73 | + zassert(fabs(y) < 1.0, "fail", "accel y out of range: %10.4f", y); |
| 74 | + zassert(fabs(z - 9.8) < 1.0, "fail", |
| 75 | + "accel z out of range: %10.4f", z); |
| 76 | + } else if (ch.chan_type == SENSOR_CHAN_GYRO_XYZ) { |
| 77 | + struct sensor_three_axis_data *data = |
| 78 | + (struct sensor_three_axis_data *)decoded_buffer; |
| 79 | + double x = q31_to_double(data->readings[0].values[0], data->shift); |
| 80 | + double y = q31_to_double(data->readings[0].values[1], data->shift); |
| 81 | + double z = q31_to_double(data->readings[0].values[2], data->shift); |
| 82 | + |
| 83 | + zassert(fabs(x) < 0.1, "fail", "gyro x out of range: %10.4f", x); |
| 84 | + zassert(fabs(y) < 0.1, "fail", "gyro y out of range: %10.4f", y); |
| 85 | + zassert(fabs(z) < 0.1, "fail", "gyro z out of range: %10.4f", z); |
| 86 | + } |
| 87 | + } |
| 88 | + } |
| 89 | +} |
| 90 | + |
| 91 | +ZTEST(icm42688_stream, test_icm42688_stream) |
| 92 | +{ |
| 93 | + stream_config.count = 1; |
| 94 | + struct sensor_value val_in = { BATCH_DURATION, 0 }; |
| 95 | + |
| 96 | + zassert_ok(sensor_attr_set( |
| 97 | + stream_config.sensor, |
| 98 | + SENSOR_CHAN_ALL, |
| 99 | + SENSOR_ATTR_BATCH_DURATION, &val_in)); |
| 100 | + struct sensor_value val_out; |
| 101 | + |
| 102 | + zassert_ok(sensor_attr_get( |
| 103 | + stream_config.sensor, |
| 104 | + SENSOR_CHAN_ALL, |
| 105 | + SENSOR_ATTR_BATCH_DURATION, &val_out)); |
| 106 | + zassert_equal(val_in.val1, val_out.val1); |
| 107 | + zassert_ok(sensor_stream(&iodev_stream, &rtio, NULL, |
| 108 | + &streaming_handle)); |
| 109 | + sensor_processing_with_callback(&rtio, callback); |
| 110 | + zassert_ok(rtio_sqe_cancel(streaming_handle)); |
| 111 | +} |
| 112 | + |
| 113 | +static void *icm42688_stream_setup(void) |
| 114 | +{ |
| 115 | + return NULL; |
| 116 | +} |
| 117 | + |
| 118 | + |
| 119 | +ZTEST_SUITE(icm42688_stream, NULL, icm42688_stream_setup, NULL, NULL, NULL); |
0 commit comments