diff options
Diffstat (limited to 'zephyr/test/drivers/default/src/bmi160.c')
-rw-r--r-- | zephyr/test/drivers/default/src/bmi160.c | 2188 |
1 files changed, 2188 insertions, 0 deletions
diff --git a/zephyr/test/drivers/default/src/bmi160.c b/zephyr/test/drivers/default/src/bmi160.c new file mode 100644 index 0000000000..3f06e7f0fd --- /dev/null +++ b/zephyr/test/drivers/default/src/bmi160.c @@ -0,0 +1,2188 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include <zephyr/kernel.h> +#include <zephyr/ztest.h> + +#include "common.h" +#include "i2c.h" +#include "emul/emul_bmi.h" +#include "emul/emul_common_i2c.h" +#include "test/drivers/test_mocks.h" + +#include "motion_sense_fifo.h" +#include "driver/accelgyro_bmi160.h" +#include "driver/accelgyro_bmi_common.h" +#include "test/drivers/test_state.h" + +#define BMI_NODE DT_NODELABEL(accel_bmi160) +#define BMI_ACC_SENSOR_ID SENSOR_ID(DT_NODELABEL(ms_bmi160_accel)) +#define BMI_GYR_SENSOR_ID SENSOR_ID(DT_NODELABEL(ms_bmi160_gyro)) +#define BMI_INT_EVENT \ + TASK_EVENT_MOTION_SENSOR_INTERRUPT(SENSOR_ID(DT_ALIAS(bmi160_int))) + +/** How accurate comparision of vectors should be */ +#define V_EPS 8 + +/** Convert from one type of vector to another */ +#define convert_int3v_int16(v, r) \ + do { \ + r[0] = v[0]; \ + r[1] = v[1]; \ + r[2] = v[2]; \ + } while (0) + +/** Rotation used in some tests */ +static const mat33_fp_t test_rotation = { { 0, FLOAT_TO_FP(1), 0 }, + { FLOAT_TO_FP(-1), 0, 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; +/** Rotate given vector by test rotation */ +static void rotate_int3v_by_test_rotation(intv3_t v) +{ + int16_t t; + + t = v[0]; + v[0] = -v[1]; + v[1] = t; + v[2] = -v[2]; +} + +/** Set emulator accelerometer offset values to intv3_t vector */ +static void set_emul_acc_offset(const struct emul *emul, intv3_t offset) +{ + bmi_emul_set_off(emul, BMI_EMUL_ACC_X, offset[0]); + bmi_emul_set_off(emul, BMI_EMUL_ACC_Y, offset[1]); + bmi_emul_set_off(emul, BMI_EMUL_ACC_Z, offset[2]); +} + +/** Save emulator accelerometer offset values to intv3_t vector */ +static void get_emul_acc_offset(const struct emul *emul, intv3_t offset) +{ + offset[0] = bmi_emul_get_off(emul, BMI_EMUL_ACC_X); + offset[1] = bmi_emul_get_off(emul, BMI_EMUL_ACC_Y); + offset[2] = bmi_emul_get_off(emul, BMI_EMUL_ACC_Z); +} + +/** Set emulator accelerometer values to intv3_t vector */ +static void set_emul_acc(const struct emul *emul, intv3_t acc) +{ + bmi_emul_set_value(emul, BMI_EMUL_ACC_X, acc[0]); + bmi_emul_set_value(emul, BMI_EMUL_ACC_Y, acc[1]); + bmi_emul_set_value(emul, BMI_EMUL_ACC_Z, acc[2]); +} + +/** Set emulator gyroscope offset values to intv3_t vector */ +static void set_emul_gyr_offset(const struct emul *emul, intv3_t offset) +{ + bmi_emul_set_off(emul, BMI_EMUL_GYR_X, offset[0]); + bmi_emul_set_off(emul, BMI_EMUL_GYR_Y, offset[1]); + bmi_emul_set_off(emul, BMI_EMUL_GYR_Z, offset[2]); +} + +/** Save emulator gyroscope offset values to intv3_t vector */ +static void get_emul_gyr_offset(const struct emul *emul, intv3_t offset) +{ + offset[0] = bmi_emul_get_off(emul, BMI_EMUL_GYR_X); + offset[1] = bmi_emul_get_off(emul, BMI_EMUL_GYR_Y); + offset[2] = bmi_emul_get_off(emul, BMI_EMUL_GYR_Z); +} + +/** Set emulator gyroscope values to vector of three int16_t */ +static void set_emul_gyr(const struct emul *emul, intv3_t gyr) +{ + bmi_emul_set_value(emul, BMI_EMUL_GYR_X, gyr[0]); + bmi_emul_set_value(emul, BMI_EMUL_GYR_Y, gyr[1]); + bmi_emul_set_value(emul, BMI_EMUL_GYR_Z, gyr[2]); +} + +/** Convert accelerometer read to units used by emulator */ +static void drv_acc_to_emul(intv3_t drv, int range, intv3_t out) +{ + const int scale = MOTION_SCALING_FACTOR / BMI_EMUL_1G; + + out[0] = drv[0] * range / scale; + out[1] = drv[1] * range / scale; + out[2] = drv[2] * range / scale; +} + +/** Convert gyroscope read to units used by emulator */ +static void drv_gyr_to_emul(intv3_t drv, int range, intv3_t out) +{ + const int scale = MOTION_SCALING_FACTOR / BMI_EMUL_125_DEG_S; + + range /= 125; + out[0] = drv[0] * range / scale; + out[1] = drv[1] * range / scale; + out[2] = drv[2] * range / scale; +} + +/** Compare two vectors of intv3_t type */ +static void compare_int3v_f(intv3_t exp_v, intv3_t v, int eps, int line) +{ + int i; + + for (i = 0; i < 3; i++) { + zassert_within( + exp_v[i], v[i], eps, + "Expected [%d; %d; %d], got [%d; %d; %d]; line: %d", + exp_v[0], exp_v[1], exp_v[2], v[0], v[1], v[2], line); + } +} +#define compare_int3v_eps(exp_v, v, e) compare_int3v_f(exp_v, v, e, __LINE__) +#define compare_int3v(exp_v, v) compare_int3v_eps(exp_v, v, V_EPS) + +/** Test get accelerometer offset with and without rotation */ +ZTEST_USER(bmi160, test_bmi_acc_get_offset) +{ + struct motion_sensor_t *ms; + const struct emul *emul = EMUL_DT_GET(BMI_NODE); + struct i2c_common_emul_data *common_data = + emul_bmi_get_i2c_common_data(emul); + int16_t ret[3]; + intv3_t ret_v; + intv3_t exp_v; + int16_t temp; + + ms = &motion_sensors[BMI_ACC_SENSOR_ID]; + + /* Set emulator offset */ + exp_v[0] = BMI_EMUL_1G / 10; + exp_v[1] = BMI_EMUL_1G / 20; + exp_v[2] = -(int)BMI_EMUL_1G / 30; + set_emul_acc_offset(emul, exp_v); + /* BMI driver returns value in mg units */ + exp_v[0] = 1000 / 10; + exp_v[1] = 1000 / 20; + exp_v[2] = -1000 / 30; + + /* Test fail on offset read */ + i2c_common_emul_set_read_fail_reg(common_data, BMI160_OFFSET_ACC70); + zassert_equal(EC_ERROR_INVAL, ms->drv->get_offset(ms, ret, &temp), + NULL); + i2c_common_emul_set_read_fail_reg(common_data, BMI160_OFFSET_ACC70 + 1); + zassert_equal(EC_ERROR_INVAL, ms->drv->get_offset(ms, ret, &temp), + NULL); + i2c_common_emul_set_read_fail_reg(common_data, BMI160_OFFSET_ACC70 + 2); + zassert_equal(EC_ERROR_INVAL, ms->drv->get_offset(ms, ret, &temp), + NULL); + i2c_common_emul_set_read_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + + /* Disable rotation */ + ms->rot_standard_ref = NULL; + + /* Test get offset without rotation */ + zassert_equal(EC_SUCCESS, ms->drv->get_offset(ms, ret, &temp), NULL); + zassert_equal(temp, (int16_t)EC_MOTION_SENSE_INVALID_CALIB_TEMP, NULL); + convert_int3v_int16(ret, ret_v); + compare_int3v(exp_v, ret_v); + + /* Setup rotation and rotate expected offset */ + ms->rot_standard_ref = &test_rotation; + rotate_int3v_by_test_rotation(exp_v); + + /* Test get offset with rotation */ + zassert_equal(EC_SUCCESS, ms->drv->get_offset(ms, ret, &temp), NULL); + zassert_equal(temp, (int16_t)EC_MOTION_SENSE_INVALID_CALIB_TEMP, NULL); + convert_int3v_int16(ret, ret_v); + compare_int3v(exp_v, ret_v); +} + +/** Test get gyroscope offset with and without rotation */ +ZTEST_USER(bmi160, test_bmi_gyr_get_offset) +{ + struct motion_sensor_t *ms; + const struct emul *emul = EMUL_DT_GET(BMI_NODE); + struct i2c_common_emul_data *common_data = + emul_bmi_get_i2c_common_data(emul); + int16_t ret[3]; + intv3_t ret_v; + intv3_t exp_v; + int16_t temp; + + ms = &motion_sensors[BMI_GYR_SENSOR_ID]; + + /* Do not fail on read */ + i2c_common_emul_set_read_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + + /* Set emulator offset */ + exp_v[0] = BMI_EMUL_125_DEG_S / 100; + exp_v[1] = BMI_EMUL_125_DEG_S / 200; + exp_v[2] = -(int)BMI_EMUL_125_DEG_S / 300; + set_emul_gyr_offset(emul, exp_v); + /* BMI driver returns value in mdeg/s units */ + exp_v[0] = 125000 / 100; + exp_v[1] = 125000 / 200; + exp_v[2] = -125000 / 300; + + /* Test fail on offset read */ + i2c_common_emul_set_read_fail_reg(common_data, BMI160_OFFSET_GYR70); + zassert_equal(EC_ERROR_INVAL, ms->drv->get_offset(ms, ret, &temp), + NULL); + i2c_common_emul_set_read_fail_reg(common_data, BMI160_OFFSET_GYR70 + 1); + zassert_equal(EC_ERROR_INVAL, ms->drv->get_offset(ms, ret, &temp), + NULL); + i2c_common_emul_set_read_fail_reg(common_data, BMI160_OFFSET_GYR70 + 2); + zassert_equal(EC_ERROR_INVAL, ms->drv->get_offset(ms, ret, &temp), + NULL); + i2c_common_emul_set_read_fail_reg(common_data, BMI160_OFFSET_EN_GYR98); + zassert_equal(EC_ERROR_INVAL, ms->drv->get_offset(ms, ret, &temp), + NULL); + i2c_common_emul_set_read_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + + /* Disable rotation */ + ms->rot_standard_ref = NULL; + + /* Test get offset without rotation */ + zassert_equal(EC_SUCCESS, ms->drv->get_offset(ms, ret, &temp), NULL); + zassert_equal(temp, (int16_t)EC_MOTION_SENSE_INVALID_CALIB_TEMP, NULL); + convert_int3v_int16(ret, ret_v); + compare_int3v_eps(exp_v, ret_v, 64); + + /* Setup rotation and rotate expected offset */ + ms->rot_standard_ref = &test_rotation; + rotate_int3v_by_test_rotation(exp_v); + + /* Test get offset with rotation */ + zassert_equal(EC_SUCCESS, ms->drv->get_offset(ms, ret, &temp), NULL); + zassert_equal(temp, (int16_t)EC_MOTION_SENSE_INVALID_CALIB_TEMP, NULL); + convert_int3v_int16(ret, ret_v); + compare_int3v_eps(exp_v, ret_v, 64); +} + +/** + * Test set accelerometer offset with and without rotation. Also test behaviour + * on I2C error. + */ +ZTEST_USER(bmi160, test_bmi_acc_set_offset) +{ + struct motion_sensor_t *ms; + const struct emul *emul = EMUL_DT_GET(BMI_NODE); + struct i2c_common_emul_data *common_data = + emul_bmi_get_i2c_common_data(emul); + int16_t input_v[3]; + int16_t temp = 0; + intv3_t ret_v; + intv3_t exp_v; + + ms = &motion_sensors[BMI_ACC_SENSOR_ID]; + + /* Test fail on OFFSET EN GYR98 register read and write */ + i2c_common_emul_set_read_fail_reg(common_data, BMI160_OFFSET_EN_GYR98); + zassert_equal(EC_ERROR_INVAL, ms->drv->set_offset(ms, input_v, temp), + NULL); + i2c_common_emul_set_read_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + i2c_common_emul_set_write_fail_reg(common_data, BMI160_OFFSET_EN_GYR98); + zassert_equal(EC_ERROR_INVAL, ms->drv->set_offset(ms, input_v, temp), + NULL); + i2c_common_emul_set_write_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + + /* Test fail on offset write */ + i2c_common_emul_set_write_fail_reg(common_data, BMI160_OFFSET_ACC70); + zassert_equal(EC_ERROR_INVAL, ms->drv->set_offset(ms, input_v, temp), + NULL); + i2c_common_emul_set_write_fail_reg(common_data, + BMI160_OFFSET_ACC70 + 1); + zassert_equal(EC_ERROR_INVAL, ms->drv->set_offset(ms, input_v, temp), + NULL); + i2c_common_emul_set_write_fail_reg(common_data, + BMI160_OFFSET_ACC70 + 2); + zassert_equal(EC_ERROR_INVAL, ms->drv->set_offset(ms, input_v, temp), + NULL); + i2c_common_emul_set_write_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + + /* Set input offset */ + exp_v[0] = BMI_EMUL_1G / 10; + exp_v[1] = BMI_EMUL_1G / 20; + exp_v[2] = -(int)BMI_EMUL_1G / 30; + /* BMI driver accept value in mg units */ + input_v[0] = 1000 / 10; + input_v[1] = 1000 / 20; + input_v[2] = -1000 / 30; + /* Disable rotation */ + ms->rot_standard_ref = NULL; + + /* Test set offset without rotation */ + zassert_equal(EC_SUCCESS, ms->drv->set_offset(ms, input_v, temp), NULL); + get_emul_acc_offset(emul, ret_v); + /* + * Depending on used range, accelerometer values may be up to 6 bits + * more accurate then offset value resolution. + */ + compare_int3v_eps(exp_v, ret_v, 64); + /* Accelerometer offset should be enabled */ + zassert_true(bmi_emul_get_reg(emul, BMI160_OFFSET_EN_GYR98) & + BMI160_OFFSET_ACC_EN, + NULL); + + /* Setup rotation and rotate input for set_offset function */ + ms->rot_standard_ref = &test_rotation; + convert_int3v_int16(input_v, ret_v); + rotate_int3v_by_test_rotation(ret_v); + convert_int3v_int16(ret_v, input_v); + + /* Test set offset with rotation */ + zassert_equal(EC_SUCCESS, ms->drv->set_offset(ms, input_v, temp), NULL); + get_emul_acc_offset(emul, ret_v); + compare_int3v_eps(exp_v, ret_v, 64); + /* Accelerometer offset should be enabled */ + zassert_true(bmi_emul_get_reg(emul, BMI160_OFFSET_EN_GYR98) & + BMI160_OFFSET_ACC_EN, + NULL); +} + +/** + * Test set gyroscope offset with and without rotation. Also test behaviour + * on I2C error. + */ +ZTEST_USER(bmi160, test_bmi_gyr_set_offset) +{ + struct motion_sensor_t *ms; + const struct emul *emul = EMUL_DT_GET(BMI_NODE); + struct i2c_common_emul_data *common_data = + emul_bmi_get_i2c_common_data(emul); + int16_t input_v[3]; + int16_t temp = 0; + intv3_t ret_v; + intv3_t exp_v; + + ms = &motion_sensors[BMI_GYR_SENSOR_ID]; + + /* Test fail on OFFSET EN GYR98 register read and write */ + i2c_common_emul_set_read_fail_reg(common_data, BMI160_OFFSET_EN_GYR98); + zassert_equal(EC_ERROR_INVAL, ms->drv->set_offset(ms, input_v, temp), + NULL); + i2c_common_emul_set_read_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + i2c_common_emul_set_write_fail_reg(common_data, BMI160_OFFSET_EN_GYR98); + zassert_equal(EC_ERROR_INVAL, ms->drv->set_offset(ms, input_v, temp), + NULL); + i2c_common_emul_set_write_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + + /* Test fail on offset write */ + i2c_common_emul_set_write_fail_reg(common_data, BMI160_OFFSET_GYR70); + zassert_equal(EC_ERROR_INVAL, ms->drv->set_offset(ms, input_v, temp), + NULL); + i2c_common_emul_set_write_fail_reg(common_data, + BMI160_OFFSET_GYR70 + 1); + zassert_equal(EC_ERROR_INVAL, ms->drv->set_offset(ms, input_v, temp), + NULL); + i2c_common_emul_set_write_fail_reg(common_data, + BMI160_OFFSET_GYR70 + 2); + zassert_equal(EC_ERROR_INVAL, ms->drv->set_offset(ms, input_v, temp), + NULL); + i2c_common_emul_set_write_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + + /* Set input offset */ + exp_v[0] = BMI_EMUL_125_DEG_S / 100; + exp_v[1] = BMI_EMUL_125_DEG_S / 200; + exp_v[2] = -(int)BMI_EMUL_125_DEG_S / 300; + /* BMI driver accept value in mdeg/s units */ + input_v[0] = 125000 / 100; + input_v[1] = 125000 / 200; + input_v[2] = -125000 / 300; + /* Disable rotation */ + ms->rot_standard_ref = NULL; + + /* Test set offset without rotation */ + zassert_equal(EC_SUCCESS, ms->drv->set_offset(ms, input_v, temp), NULL); + get_emul_gyr_offset(emul, ret_v); + compare_int3v(exp_v, ret_v); + /* Gyroscope offset should be enabled */ + zassert_true(bmi_emul_get_reg(emul, BMI160_OFFSET_EN_GYR98) & + BMI160_OFFSET_GYRO_EN, + NULL); + + /* Setup rotation and rotate input for set_offset function */ + ms->rot_standard_ref = &test_rotation; + convert_int3v_int16(input_v, ret_v); + rotate_int3v_by_test_rotation(ret_v); + convert_int3v_int16(ret_v, input_v); + + /* Test set offset with rotation */ + zassert_equal(EC_SUCCESS, ms->drv->set_offset(ms, input_v, temp), NULL); + get_emul_gyr_offset(emul, ret_v); + compare_int3v(exp_v, ret_v); + zassert_true(bmi_emul_get_reg(emul, BMI160_OFFSET_EN_GYR98) & + BMI160_OFFSET_GYRO_EN, + NULL); +} + +/** + * Try to set accelerometer range and check if expected range was set + * in driver and in emulator. + */ +static void check_set_acc_range_f(const struct emul *emul, + struct motion_sensor_t *ms, int range, + int rnd, int exp_range, int line) +{ + uint8_t exp_range_reg; + uint8_t range_reg; + + zassert_equal(EC_SUCCESS, ms->drv->set_range(ms, range, rnd), + "set_range failed; line: %d", line); + zassert_equal(exp_range, ms->current_range, + "Expected range %d, got %d; line %d", exp_range, + ms->current_range, line); + range_reg = bmi_emul_get_reg(emul, BMI160_ACC_RANGE); + + switch (exp_range) { + case 2: + exp_range_reg = BMI160_GSEL_2G; + break; + case 4: + exp_range_reg = BMI160_GSEL_4G; + break; + case 8: + exp_range_reg = BMI160_GSEL_8G; + break; + case 16: + exp_range_reg = BMI160_GSEL_16G; + break; + default: + /* Unknown expected range */ + zassert_unreachable( + "Expected range %d not supported by device; line %d", + exp_range, line); + return; + } + + zassert_equal(exp_range_reg, range_reg, + "Expected range reg 0x%x, got 0x%x; line %d", + exp_range_reg, range_reg, line); +} +#define check_set_acc_range(emul, ms, range, rnd, exp_range) \ + check_set_acc_range_f(emul, ms, range, rnd, exp_range, __LINE__) + +/** Test set accelerometer range with and without I2C errors */ +ZTEST_USER(bmi160, test_bmi_acc_set_range) +{ + struct motion_sensor_t *ms; + const struct emul *emul = EMUL_DT_GET(BMI_NODE); + struct i2c_common_emul_data *common_data = + emul_bmi_get_i2c_common_data(emul); + int start_range; + + ms = &motion_sensors[BMI_ACC_SENSOR_ID]; + + /* Setup starting range, shouldn't be changed on error */ + start_range = 2; + ms->current_range = start_range; + bmi_emul_set_reg(emul, BMI160_ACC_RANGE, BMI160_GSEL_2G); + /* Setup emulator fail on write */ + i2c_common_emul_set_write_fail_reg(common_data, BMI160_ACC_RANGE); + + /* Test fail on write */ + zassert_equal(EC_ERROR_INVAL, ms->drv->set_range(ms, 12, 0), NULL); + zassert_equal(start_range, ms->current_range, NULL); + zassert_equal(BMI160_GSEL_2G, bmi_emul_get_reg(emul, BMI160_ACC_RANGE), + NULL); + zassert_equal(EC_ERROR_INVAL, ms->drv->set_range(ms, 12, 1), NULL); + zassert_equal(start_range, ms->current_range, NULL); + zassert_equal(BMI160_GSEL_2G, bmi_emul_get_reg(emul, BMI160_ACC_RANGE), + NULL); + + /* Do not fail on write */ + i2c_common_emul_set_write_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + + /* Test setting range with rounding down */ + check_set_acc_range(emul, ms, 1, 0, 2); + check_set_acc_range(emul, ms, 2, 0, 2); + check_set_acc_range(emul, ms, 3, 0, 2); + check_set_acc_range(emul, ms, 4, 0, 4); + check_set_acc_range(emul, ms, 5, 0, 4); + check_set_acc_range(emul, ms, 6, 0, 4); + check_set_acc_range(emul, ms, 7, 0, 4); + check_set_acc_range(emul, ms, 8, 0, 8); + check_set_acc_range(emul, ms, 9, 0, 8); + check_set_acc_range(emul, ms, 15, 0, 8); + check_set_acc_range(emul, ms, 16, 0, 16); + check_set_acc_range(emul, ms, 17, 0, 16); + + /* Test setting range with rounding up */ + check_set_acc_range(emul, ms, 1, 1, 2); + check_set_acc_range(emul, ms, 2, 1, 2); + check_set_acc_range(emul, ms, 3, 1, 4); + check_set_acc_range(emul, ms, 4, 1, 4); + check_set_acc_range(emul, ms, 5, 1, 8); + check_set_acc_range(emul, ms, 6, 1, 8); + check_set_acc_range(emul, ms, 7, 1, 8); + check_set_acc_range(emul, ms, 8, 1, 8); + check_set_acc_range(emul, ms, 9, 1, 16); + check_set_acc_range(emul, ms, 15, 1, 16); + check_set_acc_range(emul, ms, 16, 1, 16); + check_set_acc_range(emul, ms, 17, 1, 16); +} + +/** + * Try to set gyroscope range and check if expected range was set in driver and + * in emulator. + */ +static void check_set_gyr_range_f(const struct emul *emul, + struct motion_sensor_t *ms, int range, + int rnd, int exp_range, int line) +{ + uint8_t exp_range_reg; + uint8_t range_reg; + + zassert_equal(EC_SUCCESS, ms->drv->set_range(ms, range, rnd), + "set_range failed; line: %d", line); + zassert_equal(exp_range, ms->current_range, + "Expected range %d, got %d; line %d", exp_range, + ms->current_range, line); + range_reg = bmi_emul_get_reg(emul, BMI160_GYR_RANGE); + + switch (exp_range) { + case 125: + exp_range_reg = BMI160_DPS_SEL_125; + break; + case 250: + exp_range_reg = BMI160_DPS_SEL_250; + break; + case 500: + exp_range_reg = BMI160_DPS_SEL_500; + break; + case 1000: + exp_range_reg = BMI160_DPS_SEL_1000; + break; + case 2000: + exp_range_reg = BMI160_DPS_SEL_2000; + break; + default: + /* Unknown expected range */ + zassert_unreachable( + "Expected range %d not supported by device; line %d", + exp_range, line); + return; + } + + zassert_equal(exp_range_reg, range_reg, + "Expected range reg 0x%x, got 0x%x; line %d", + exp_range_reg, range_reg, line); +} +#define check_set_gyr_range(emul, ms, range, rnd, exp_range) \ + check_set_gyr_range_f(emul, ms, range, rnd, exp_range, __LINE__) + +/** Test set gyroscope range with and without I2C errors */ +ZTEST_USER(bmi160, test_bmi_gyr_set_range) +{ + struct motion_sensor_t *ms; + const struct emul *emul = EMUL_DT_GET(BMI_NODE); + struct i2c_common_emul_data *common_data = + emul_bmi_get_i2c_common_data(emul); + int start_range; + + ms = &motion_sensors[BMI_GYR_SENSOR_ID]; + + /* Setup starting range, shouldn't be changed on error */ + start_range = 250; + ms->current_range = start_range; + bmi_emul_set_reg(emul, BMI160_GYR_RANGE, BMI160_DPS_SEL_250); + /* Setup emulator fail on write */ + i2c_common_emul_set_write_fail_reg(common_data, BMI160_GYR_RANGE); + + /* Test fail on write */ + zassert_equal(EC_ERROR_INVAL, ms->drv->set_range(ms, 125, 0), NULL); + zassert_equal(start_range, ms->current_range, NULL); + zassert_equal(BMI160_DPS_SEL_250, + bmi_emul_get_reg(emul, BMI160_GYR_RANGE), NULL); + zassert_equal(EC_ERROR_INVAL, ms->drv->set_range(ms, 125, 1), NULL); + zassert_equal(start_range, ms->current_range, NULL); + zassert_equal(BMI160_DPS_SEL_250, + bmi_emul_get_reg(emul, BMI160_GYR_RANGE), NULL); + + /* Do not fail on write */ + i2c_common_emul_set_write_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + + /* Test setting range with rounding down */ + check_set_gyr_range(emul, ms, 1, 0, 125); + check_set_gyr_range(emul, ms, 124, 0, 125); + check_set_gyr_range(emul, ms, 125, 0, 125); + check_set_gyr_range(emul, ms, 126, 0, 125); + check_set_gyr_range(emul, ms, 249, 0, 125); + check_set_gyr_range(emul, ms, 250, 0, 250); + check_set_gyr_range(emul, ms, 251, 0, 250); + check_set_gyr_range(emul, ms, 499, 0, 250); + check_set_gyr_range(emul, ms, 500, 0, 500); + check_set_gyr_range(emul, ms, 501, 0, 500); + check_set_gyr_range(emul, ms, 999, 0, 500); + check_set_gyr_range(emul, ms, 1000, 0, 1000); + check_set_gyr_range(emul, ms, 1001, 0, 1000); + check_set_gyr_range(emul, ms, 1999, 0, 1000); + check_set_gyr_range(emul, ms, 2000, 0, 2000); + check_set_gyr_range(emul, ms, 2001, 0, 2000); + + /* Test setting range with rounding up */ + check_set_gyr_range(emul, ms, 1, 1, 125); + check_set_gyr_range(emul, ms, 124, 1, 125); + check_set_gyr_range(emul, ms, 125, 1, 125); + check_set_gyr_range(emul, ms, 126, 1, 250); + check_set_gyr_range(emul, ms, 249, 1, 250); + check_set_gyr_range(emul, ms, 250, 1, 250); + check_set_gyr_range(emul, ms, 251, 1, 500); + check_set_gyr_range(emul, ms, 499, 1, 500); + check_set_gyr_range(emul, ms, 500, 1, 500); + check_set_gyr_range(emul, ms, 501, 1, 1000); + check_set_gyr_range(emul, ms, 999, 1, 1000); + check_set_gyr_range(emul, ms, 1000, 1, 1000); + check_set_gyr_range(emul, ms, 1001, 1, 2000); + check_set_gyr_range(emul, ms, 1999, 1, 2000); + check_set_gyr_range(emul, ms, 2000, 1, 2000); + check_set_gyr_range(emul, ms, 2001, 1, 2000); +} + +/** Test get resolution of acclerometer and gyroscope sensor */ +ZTEST_USER(bmi160, test_bmi_get_resolution) +{ + struct motion_sensor_t *ms; + + /* Test accelerometer */ + ms = &motion_sensors[BMI_ACC_SENSOR_ID]; + + /* Resolution should be always 16 bits */ + zassert_equal(16, ms->drv->get_resolution(ms), NULL); + + /* Test gyroscope */ + ms = &motion_sensors[BMI_GYR_SENSOR_ID]; + + /* Resolution should be always 16 bits */ + zassert_equal(16, ms->drv->get_resolution(ms), NULL); +} + +/** + * Try to set accelerometer data rate and check if expected rate was set + * in driver and in emulator. + */ +static void check_set_acc_rate_f(const struct emul *emul, + struct motion_sensor_t *ms, int rate, int rnd, + int exp_rate, int line) +{ + uint8_t exp_rate_reg; + uint8_t rate_reg; + int drv_rate; + + zassert_equal(EC_SUCCESS, ms->drv->set_data_rate(ms, rate, rnd), + "set_data_rate failed; line: %d", line); + drv_rate = ms->drv->get_data_rate(ms); + zassert_equal(exp_rate, drv_rate, "Expected rate %d, got %d; line %d", + exp_rate, drv_rate, line); + rate_reg = bmi_emul_get_reg(emul, BMI160_ACC_CONF); + rate_reg &= BMI_ODR_MASK; + + switch (exp_rate) { + case 12500: + exp_rate_reg = 0x5; + break; + case 25000: + exp_rate_reg = 0x6; + break; + case 50000: + exp_rate_reg = 0x7; + break; + case 100000: + exp_rate_reg = 0x8; + break; + case 200000: + exp_rate_reg = 0x9; + break; + case 400000: + exp_rate_reg = 0xa; + break; + case 800000: + exp_rate_reg = 0xb; + break; + case 1600000: + exp_rate_reg = 0xc; + break; + default: + /* Unknown expected rate */ + zassert_unreachable( + "Expected rate %d not supported by device; line %d", + exp_rate, line); + return; + } + + zassert_equal(exp_rate_reg, rate_reg, + "Expected rate reg 0x%x, got 0x%x; line %d", exp_rate_reg, + rate_reg, line); +} +#define check_set_acc_rate(emul, ms, rate, rnd, exp_rate) \ + check_set_acc_rate_f(emul, ms, rate, rnd, exp_rate, __LINE__) + +/** Test set and get accelerometer rate with and without I2C errors */ +ZTEST_USER(bmi160, test_bmi_acc_rate) +{ + struct motion_sensor_t *ms; + const struct emul *emul = EMUL_DT_GET(BMI_NODE); + struct i2c_common_emul_data *common_data = + emul_bmi_get_i2c_common_data(emul); + uint8_t reg_rate; + int pmu_status; + int drv_rate; + + ms = &motion_sensors[BMI_ACC_SENSOR_ID]; + + /* Test setting rate with rounding down */ + check_set_acc_rate(emul, ms, 12500, 0, 12500); + check_set_acc_rate(emul, ms, 12501, 0, 12500); + check_set_acc_rate(emul, ms, 24999, 0, 12500); + check_set_acc_rate(emul, ms, 25000, 0, 25000); + check_set_acc_rate(emul, ms, 25001, 0, 25000); + check_set_acc_rate(emul, ms, 49999, 0, 25000); + check_set_acc_rate(emul, ms, 50000, 0, 50000); + check_set_acc_rate(emul, ms, 50001, 0, 50000); + check_set_acc_rate(emul, ms, 99999, 0, 50000); + check_set_acc_rate(emul, ms, 100000, 0, 100000); + check_set_acc_rate(emul, ms, 100001, 0, 100000); + check_set_acc_rate(emul, ms, 199999, 0, 100000); + check_set_acc_rate(emul, ms, 200000, 0, 200000); + check_set_acc_rate(emul, ms, 200001, 0, 200000); + check_set_acc_rate(emul, ms, 399999, 0, 200000); + /* + * We cannot test frequencies from 400000 to 1600000 because + * CONFIG_EC_MAX_SENSOR_FREQ_MILLIHZ is set to 250000 + */ + + /* Test setting rate with rounding up */ + check_set_acc_rate(emul, ms, 6251, 1, 12500); + check_set_acc_rate(emul, ms, 12499, 1, 12500); + check_set_acc_rate(emul, ms, 12500, 1, 12500); + check_set_acc_rate(emul, ms, 12501, 1, 25000); + check_set_acc_rate(emul, ms, 24999, 1, 25000); + check_set_acc_rate(emul, ms, 25000, 1, 25000); + check_set_acc_rate(emul, ms, 25001, 1, 50000); + check_set_acc_rate(emul, ms, 49999, 1, 50000); + check_set_acc_rate(emul, ms, 50000, 1, 50000); + check_set_acc_rate(emul, ms, 50001, 1, 100000); + check_set_acc_rate(emul, ms, 99999, 1, 100000); + check_set_acc_rate(emul, ms, 100000, 1, 100000); + check_set_acc_rate(emul, ms, 100001, 1, 200000); + check_set_acc_rate(emul, ms, 199999, 1, 200000); + check_set_acc_rate(emul, ms, 200000, 1, 200000); + + /* Test out of range rate with rounding down */ + zassert_equal(EC_RES_INVALID_PARAM, ms->drv->set_data_rate(ms, 1, 0), + NULL); + zassert_equal(EC_RES_INVALID_PARAM, + ms->drv->set_data_rate(ms, 12499, 0), NULL); + zassert_equal(EC_RES_INVALID_PARAM, + ms->drv->set_data_rate(ms, 400000, 0), NULL); + zassert_equal(EC_RES_INVALID_PARAM, + ms->drv->set_data_rate(ms, 2000000, 0), NULL); + + /* Test out of range rate with rounding up */ + zassert_equal(EC_RES_INVALID_PARAM, ms->drv->set_data_rate(ms, 1, 1), + NULL); + zassert_equal(EC_RES_INVALID_PARAM, ms->drv->set_data_rate(ms, 6250, 1), + NULL); + zassert_equal(EC_RES_INVALID_PARAM, + ms->drv->set_data_rate(ms, 200001, 1), NULL); + zassert_equal(EC_RES_INVALID_PARAM, + ms->drv->set_data_rate(ms, 400000, 1), NULL); + zassert_equal(EC_RES_INVALID_PARAM, + ms->drv->set_data_rate(ms, 2000000, 1), NULL); + + /* Current rate shouldn't be changed on error */ + drv_rate = ms->drv->get_data_rate(ms); + reg_rate = bmi_emul_get_reg(emul, BMI160_ACC_CONF); + + /* Setup emulator fail on read */ + i2c_common_emul_set_read_fail_reg(common_data, BMI160_ACC_CONF); + + /* Test fail on read */ + zassert_equal(EC_ERROR_INVAL, ms->drv->set_data_rate(ms, 50000, 0), + NULL); + zassert_equal(drv_rate, ms->drv->get_data_rate(ms), NULL); + zassert_equal(reg_rate, bmi_emul_get_reg(emul, BMI160_ACC_CONF), NULL); + zassert_equal(EC_ERROR_INVAL, ms->drv->set_data_rate(ms, 50000, 1), + NULL); + zassert_equal(drv_rate, ms->drv->get_data_rate(ms), NULL); + zassert_equal(reg_rate, bmi_emul_get_reg(emul, BMI160_ACC_CONF), NULL); + + /* Do not fail on read */ + i2c_common_emul_set_read_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + + /* Setup emulator fail on write */ + i2c_common_emul_set_write_fail_reg(common_data, BMI160_ACC_CONF); + + /* Test fail on write */ + zassert_equal(EC_ERROR_INVAL, ms->drv->set_data_rate(ms, 50000, 0), + NULL); + zassert_equal(drv_rate, ms->drv->get_data_rate(ms), NULL); + zassert_equal(reg_rate, bmi_emul_get_reg(emul, BMI160_ACC_CONF), NULL); + zassert_equal(EC_ERROR_INVAL, ms->drv->set_data_rate(ms, 50000, 1), + NULL); + zassert_equal(drv_rate, ms->drv->get_data_rate(ms), NULL); + zassert_equal(reg_rate, bmi_emul_get_reg(emul, BMI160_ACC_CONF), NULL); + + /* Do not fail on write */ + i2c_common_emul_set_write_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + + /* Test disabling sensor */ + pmu_status = BMI160_PMU_NORMAL << BMI160_PMU_ACC_OFFSET; + pmu_status |= BMI160_PMU_NORMAL << BMI160_PMU_GYR_OFFSET; + bmi_emul_set_reg(emul, BMI160_PMU_STATUS, pmu_status); + zassert_equal(EC_SUCCESS, ms->drv->set_data_rate(ms, 0, 0), NULL); + + bmi_read8(ms->port, ms->i2c_spi_addr_flags, BMI160_PMU_STATUS, + &pmu_status); + zassert_equal(BMI160_PMU_NORMAL << BMI160_PMU_GYR_OFFSET, pmu_status, + "Gyroscope should be still enabled"); + + /* Test enabling sensor */ + bmi_emul_set_reg(emul, BMI160_PMU_STATUS, 0); + zassert_equal(EC_SUCCESS, ms->drv->set_data_rate(ms, 50000, 0), NULL); + + bmi_read8(ms->port, ms->i2c_spi_addr_flags, BMI160_PMU_STATUS, + &pmu_status); + zassert_equal(BMI160_PMU_NORMAL << BMI160_PMU_ACC_OFFSET, pmu_status, + "Accelerometer should be enabled"); +} + +/** + * Try to set gyroscope data rate and check if expected rate was set + * in driver and in emulator. + */ +static void check_set_gyr_rate_f(const struct emul *emul, + struct motion_sensor_t *ms, int rate, int rnd, + int exp_rate, int line) +{ + uint8_t exp_rate_reg; + uint8_t rate_reg; + int drv_rate; + + zassert_equal(EC_SUCCESS, ms->drv->set_data_rate(ms, rate, rnd), + "set_data_rate failed; line: %d", line); + drv_rate = ms->drv->get_data_rate(ms); + zassert_equal(exp_rate, drv_rate, "Expected rate %d, got %d; line %d", + exp_rate, drv_rate, line); + rate_reg = bmi_emul_get_reg(emul, BMI160_GYR_CONF); + rate_reg &= BMI_ODR_MASK; + + switch (exp_rate) { + case 25000: + exp_rate_reg = 0x6; + break; + case 50000: + exp_rate_reg = 0x7; + break; + case 100000: + exp_rate_reg = 0x8; + break; + case 200000: + exp_rate_reg = 0x9; + break; + case 400000: + exp_rate_reg = 0xa; + break; + case 800000: + exp_rate_reg = 0xb; + break; + case 1600000: + exp_rate_reg = 0xc; + break; + case 3200000: + exp_rate_reg = 0xc; + break; + default: + /* Unknown expected rate */ + zassert_unreachable( + "Expected rate %d not supported by device; line %d", + exp_rate, line); + return; + } + + zassert_equal(exp_rate_reg, rate_reg, + "Expected rate reg 0x%x, got 0x%x; line %d", exp_rate_reg, + rate_reg, line); +} +#define check_set_gyr_rate(emul, ms, rate, rnd, exp_rate) \ + check_set_gyr_rate_f(emul, ms, rate, rnd, exp_rate, __LINE__) + +/** Test set and get gyroscope rate with and without I2C errors */ +ZTEST_USER(bmi160, test_bmi_gyr_rate) +{ + struct motion_sensor_t *ms; + const struct emul *emul = EMUL_DT_GET(BMI_NODE); + struct i2c_common_emul_data *common_data = + emul_bmi_get_i2c_common_data(emul); + uint8_t reg_rate; + int pmu_status; + int drv_rate; + + ms = &motion_sensors[BMI_GYR_SENSOR_ID]; + + /* Test setting rate with rounding down */ + check_set_gyr_rate(emul, ms, 25000, 0, 25000); + check_set_gyr_rate(emul, ms, 25001, 0, 25000); + check_set_gyr_rate(emul, ms, 49999, 0, 25000); + check_set_gyr_rate(emul, ms, 50000, 0, 50000); + check_set_gyr_rate(emul, ms, 50001, 0, 50000); + check_set_gyr_rate(emul, ms, 99999, 0, 50000); + check_set_gyr_rate(emul, ms, 100000, 0, 100000); + check_set_gyr_rate(emul, ms, 100001, 0, 100000); + check_set_gyr_rate(emul, ms, 199999, 0, 100000); + check_set_gyr_rate(emul, ms, 200000, 0, 200000); + check_set_gyr_rate(emul, ms, 200001, 0, 200000); + check_set_gyr_rate(emul, ms, 399999, 0, 200000); + /* + * We cannot test frequencies from 400000 to 3200000 because + * CONFIG_EC_MAX_SENSOR_FREQ_MILLIHZ is set to 250000 + */ + + /* Test setting rate with rounding up */ + check_set_gyr_rate(emul, ms, 12501, 1, 25000); + check_set_gyr_rate(emul, ms, 24999, 1, 25000); + check_set_gyr_rate(emul, ms, 25000, 1, 25000); + check_set_gyr_rate(emul, ms, 25001, 1, 50000); + check_set_gyr_rate(emul, ms, 49999, 1, 50000); + check_set_gyr_rate(emul, ms, 50000, 1, 50000); + check_set_gyr_rate(emul, ms, 50001, 1, 100000); + check_set_gyr_rate(emul, ms, 99999, 1, 100000); + check_set_gyr_rate(emul, ms, 100000, 1, 100000); + check_set_gyr_rate(emul, ms, 100001, 1, 200000); + check_set_gyr_rate(emul, ms, 199999, 1, 200000); + check_set_gyr_rate(emul, ms, 200000, 1, 200000); + + /* Test out of range rate with rounding down */ + zassert_equal(EC_RES_INVALID_PARAM, ms->drv->set_data_rate(ms, 1, 0), + NULL); + zassert_equal(EC_RES_INVALID_PARAM, + ms->drv->set_data_rate(ms, 24999, 0), NULL); + zassert_equal(EC_RES_INVALID_PARAM, + ms->drv->set_data_rate(ms, 400000, 0), NULL); + zassert_equal(EC_RES_INVALID_PARAM, + ms->drv->set_data_rate(ms, 4000000, 0), NULL); + + /* Test out of range rate with rounding up */ + zassert_equal(EC_RES_INVALID_PARAM, ms->drv->set_data_rate(ms, 1, 1), + NULL); + zassert_equal(EC_RES_INVALID_PARAM, + ms->drv->set_data_rate(ms, 12499, 1), NULL); + zassert_equal(EC_RES_INVALID_PARAM, + ms->drv->set_data_rate(ms, 200001, 1), NULL); + zassert_equal(EC_RES_INVALID_PARAM, + ms->drv->set_data_rate(ms, 400000, 1), NULL); + zassert_equal(EC_RES_INVALID_PARAM, + ms->drv->set_data_rate(ms, 4000000, 1), NULL); + + /* Current rate shouldn't be changed on error */ + drv_rate = ms->drv->get_data_rate(ms); + reg_rate = bmi_emul_get_reg(emul, BMI160_GYR_CONF); + + /* Setup emulator fail on read */ + i2c_common_emul_set_read_fail_reg(common_data, BMI160_GYR_CONF); + + /* Test fail on read */ + zassert_equal(EC_ERROR_INVAL, ms->drv->set_data_rate(ms, 50000, 0), + NULL); + zassert_equal(drv_rate, ms->drv->get_data_rate(ms), NULL); + zassert_equal(reg_rate, bmi_emul_get_reg(emul, BMI160_GYR_CONF), NULL); + zassert_equal(EC_ERROR_INVAL, ms->drv->set_data_rate(ms, 50000, 1), + NULL); + zassert_equal(drv_rate, ms->drv->get_data_rate(ms), NULL); + zassert_equal(reg_rate, bmi_emul_get_reg(emul, BMI160_GYR_CONF), NULL); + + /* Do not fail on read */ + i2c_common_emul_set_read_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + + /* Setup emulator fail on write */ + i2c_common_emul_set_write_fail_reg(common_data, BMI160_GYR_CONF); + + /* Test fail on write */ + zassert_equal(EC_ERROR_INVAL, ms->drv->set_data_rate(ms, 50000, 0), + NULL); + zassert_equal(drv_rate, ms->drv->get_data_rate(ms), NULL); + zassert_equal(reg_rate, bmi_emul_get_reg(emul, BMI160_GYR_CONF), NULL); + zassert_equal(EC_ERROR_INVAL, ms->drv->set_data_rate(ms, 50000, 1), + NULL); + zassert_equal(drv_rate, ms->drv->get_data_rate(ms), NULL); + zassert_equal(reg_rate, bmi_emul_get_reg(emul, BMI160_GYR_CONF), NULL); + + /* Do not fail on write */ + i2c_common_emul_set_write_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + + /* Test disabling sensor */ + pmu_status = BMI160_PMU_NORMAL << BMI160_PMU_ACC_OFFSET; + pmu_status |= BMI160_PMU_NORMAL << BMI160_PMU_GYR_OFFSET; + bmi_emul_set_reg(emul, BMI160_PMU_STATUS, pmu_status); + zassert_equal(EC_SUCCESS, ms->drv->set_data_rate(ms, 0, 0), NULL); + + bmi_read8(ms->port, ms->i2c_spi_addr_flags, BMI160_PMU_STATUS, + &pmu_status); + zassert_equal(BMI160_PMU_NORMAL << BMI160_PMU_ACC_OFFSET, pmu_status, + "Accelerometer should be still enabled"); + + /* Test enabling sensor */ + bmi_emul_set_reg(emul, BMI160_PMU_STATUS, 0); + zassert_equal(EC_SUCCESS, ms->drv->set_data_rate(ms, 50000, 0), NULL); + + bmi_read8(ms->port, ms->i2c_spi_addr_flags, BMI160_PMU_STATUS, + &pmu_status); + zassert_equal(BMI160_PMU_NORMAL << BMI160_PMU_GYR_OFFSET, pmu_status, + "Gyroscope should be enabled"); +} + +/** + * Test setting and getting scale in accelerometer and gyroscope sensors. + * Correct appling scale to results is checked in "read" test. + */ +ZTEST_USER(bmi160, test_bmi_scale) +{ + struct motion_sensor_t *ms; + int16_t ret_scale[3]; + int16_t exp_scale[3] = { 100, 231, 421 }; + int16_t t; + + /* Test accelerometer */ + ms = &motion_sensors[BMI_ACC_SENSOR_ID]; + + zassert_equal(EC_SUCCESS, ms->drv->set_scale(ms, exp_scale, 0), NULL); + zassert_equal(EC_SUCCESS, ms->drv->get_scale(ms, ret_scale, &t), NULL); + + zassert_equal(t, (int16_t)EC_MOTION_SENSE_INVALID_CALIB_TEMP, NULL); + zassert_equal(exp_scale[0], ret_scale[0], NULL); + zassert_equal(exp_scale[1], ret_scale[1], NULL); + zassert_equal(exp_scale[2], ret_scale[2], NULL); + + /* Test gyroscope */ + ms = &motion_sensors[BMI_GYR_SENSOR_ID]; + + zassert_equal(EC_SUCCESS, ms->drv->set_scale(ms, exp_scale, 0), NULL); + zassert_equal(EC_SUCCESS, ms->drv->get_scale(ms, ret_scale, &t), NULL); + + zassert_equal(t, (int16_t)EC_MOTION_SENSE_INVALID_CALIB_TEMP, NULL); + zassert_equal(exp_scale[0], ret_scale[0], NULL); + zassert_equal(exp_scale[1], ret_scale[1], NULL); + zassert_equal(exp_scale[2], ret_scale[2], NULL); +} + +/** Test reading temperature using accelerometer and gyroscope sensors */ +ZTEST_USER(bmi160, test_bmi_read_temp) +{ + struct motion_sensor_t *ms_acc, *ms_gyr; + const struct emul *emul = EMUL_DT_GET(BMI_NODE); + struct i2c_common_emul_data *common_data = + emul_bmi_get_i2c_common_data(emul); + int ret_temp; + int exp_temp; + + ms_acc = &motion_sensors[BMI_ACC_SENSOR_ID]; + ms_gyr = &motion_sensors[BMI_GYR_SENSOR_ID]; + + /* Setup emulator fail on read */ + i2c_common_emul_set_read_fail_reg(common_data, BMI160_TEMPERATURE_0); + zassert_equal(EC_ERROR_NOT_POWERED, + ms_acc->drv->read_temp(ms_acc, &ret_temp), NULL); + zassert_equal(EC_ERROR_NOT_POWERED, + ms_gyr->drv->read_temp(ms_gyr, &ret_temp), NULL); + i2c_common_emul_set_read_fail_reg(common_data, BMI160_TEMPERATURE_1); + zassert_equal(EC_ERROR_NOT_POWERED, + ms_acc->drv->read_temp(ms_acc, &ret_temp), NULL); + zassert_equal(EC_ERROR_NOT_POWERED, + ms_gyr->drv->read_temp(ms_gyr, &ret_temp), NULL); + /* Do not fail on read */ + i2c_common_emul_set_read_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + + /* Fail on invalid temperature */ + bmi_emul_set_reg(emul, BMI160_TEMPERATURE_0, 0x00); + bmi_emul_set_reg(emul, BMI160_TEMPERATURE_1, 0x80); + zassert_equal(EC_ERROR_NOT_POWERED, + ms_acc->drv->read_temp(ms_acc, &ret_temp), NULL); + zassert_equal(EC_ERROR_NOT_POWERED, + ms_gyr->drv->read_temp(ms_gyr, &ret_temp), NULL); + + /* + * Test correct values. Both motion sensors should return the same + * temperature. + */ + exp_temp = C_TO_K(23); + bmi_emul_set_reg(emul, BMI160_TEMPERATURE_0, 0x00); + bmi_emul_set_reg(emul, BMI160_TEMPERATURE_1, 0x00); + zassert_equal(EC_SUCCESS, ms_acc->drv->read_temp(ms_acc, &ret_temp), + NULL); + zassert_equal(exp_temp, ret_temp, NULL); + zassert_equal(EC_SUCCESS, ms_gyr->drv->read_temp(ms_gyr, &ret_temp), + NULL); + zassert_equal(exp_temp, ret_temp, NULL); + + exp_temp = C_TO_K(87); + bmi_emul_set_reg(emul, BMI160_TEMPERATURE_0, 0xff); + bmi_emul_set_reg(emul, BMI160_TEMPERATURE_1, 0x7f); + zassert_equal(EC_SUCCESS, ms_acc->drv->read_temp(ms_acc, &ret_temp), + NULL); + zassert_equal(exp_temp, ret_temp, NULL); + zassert_equal(EC_SUCCESS, ms_gyr->drv->read_temp(ms_gyr, &ret_temp), + NULL); + zassert_equal(exp_temp, ret_temp, NULL); + + exp_temp = C_TO_K(-41); + bmi_emul_set_reg(emul, BMI160_TEMPERATURE_0, 0x01); + bmi_emul_set_reg(emul, BMI160_TEMPERATURE_1, 0x80); + zassert_equal(EC_SUCCESS, ms_acc->drv->read_temp(ms_acc, &ret_temp), + NULL); + zassert_equal(exp_temp, ret_temp, NULL); + zassert_equal(EC_SUCCESS, ms_gyr->drv->read_temp(ms_gyr, &ret_temp), + NULL); + zassert_equal(exp_temp, ret_temp, NULL); + + exp_temp = C_TO_K(47); + bmi_emul_set_reg(emul, BMI160_TEMPERATURE_0, 0x00); + bmi_emul_set_reg(emul, BMI160_TEMPERATURE_1, 0x30); + zassert_equal(EC_SUCCESS, ms_acc->drv->read_temp(ms_acc, &ret_temp), + NULL); + zassert_equal(exp_temp, ret_temp, NULL); + zassert_equal(EC_SUCCESS, ms_gyr->drv->read_temp(ms_gyr, &ret_temp), + NULL); + zassert_equal(exp_temp, ret_temp, NULL); +} + +/** Test reading accelerometer sensor data */ +ZTEST_USER(bmi160, test_bmi_acc_read) +{ + struct motion_sensor_t *ms; + const struct emul *emul = EMUL_DT_GET(BMI_NODE); + struct i2c_common_emul_data *common_data = + emul_bmi_get_i2c_common_data(emul); + intv3_t ret_v; + intv3_t exp_v; + int16_t scale[3] = { MOTION_SENSE_DEFAULT_SCALE, + MOTION_SENSE_DEFAULT_SCALE, + MOTION_SENSE_DEFAULT_SCALE }; + + ms = &motion_sensors[BMI_ACC_SENSOR_ID]; + + /* Set offset 0 to simplify test */ + bmi_emul_set_off(emul, BMI_EMUL_ACC_X, 0); + bmi_emul_set_off(emul, BMI_EMUL_ACC_Y, 0); + bmi_emul_set_off(emul, BMI_EMUL_ACC_Z, 0); + + /* Fail on read status */ + i2c_common_emul_set_read_fail_reg(common_data, BMI160_STATUS); + zassert_equal(EC_ERROR_INVAL, ms->drv->read(ms, ret_v), NULL); + + i2c_common_emul_set_read_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + + /* When not ready, driver should return saved raw value */ + exp_v[0] = 100; + exp_v[1] = 200; + exp_v[2] = 300; + ms->raw_xyz[0] = exp_v[0]; + ms->raw_xyz[1] = exp_v[1]; + ms->raw_xyz[2] = exp_v[2]; + + /* Status not ready */ + bmi_emul_set_reg(emul, BMI160_STATUS, 0); + zassert_equal(EC_SUCCESS, ms->drv->read(ms, ret_v), NULL); + compare_int3v(exp_v, ret_v); + + /* Status only GYR ready */ + bmi_emul_set_reg(emul, BMI160_STATUS, BMI160_DRDY_GYR); + zassert_equal(EC_SUCCESS, ms->drv->read(ms, ret_v), NULL); + compare_int3v(exp_v, ret_v); + + /* Status ACC ready */ + bmi_emul_set_reg(emul, BMI160_STATUS, BMI160_DRDY_ACC); + + /* Set input accelerometer values */ + exp_v[0] = BMI_EMUL_1G / 10; + exp_v[1] = BMI_EMUL_1G / 20; + exp_v[2] = -(int)BMI_EMUL_1G / 30; + set_emul_acc(emul, exp_v); + /* Disable rotation */ + ms->rot_standard_ref = NULL; + /* Set scale */ + zassert_equal(EC_SUCCESS, ms->drv->set_scale(ms, scale, 0), NULL); + /* Set range to 2G */ + zassert_equal(EC_SUCCESS, ms->drv->set_range(ms, 2, 0), NULL); + + /* Test read without rotation */ + zassert_equal(EC_SUCCESS, ms->drv->read(ms, ret_v), NULL); + drv_acc_to_emul(ret_v, 2, ret_v); + compare_int3v(exp_v, ret_v); + + /* Set range to 4G */ + zassert_equal(EC_SUCCESS, ms->drv->set_range(ms, 4, 0), NULL); + + /* Test read without rotation */ + zassert_equal(EC_SUCCESS, ms->drv->read(ms, ret_v), NULL); + drv_acc_to_emul(ret_v, 4, ret_v); + compare_int3v(exp_v, ret_v); + + /* Setup rotation and rotate expected vector */ + ms->rot_standard_ref = &test_rotation; + rotate_int3v_by_test_rotation(exp_v); + /* Set range to 2G */ + zassert_equal(EC_SUCCESS, ms->drv->set_range(ms, 2, 0), NULL); + + /* Test read with rotation */ + zassert_equal(EC_SUCCESS, ms->drv->read(ms, ret_v), NULL); + drv_acc_to_emul(ret_v, 2, ret_v); + compare_int3v(exp_v, ret_v); + + /* Set range to 4G */ + zassert_equal(EC_SUCCESS, ms->drv->set_range(ms, 4, 0), NULL); + + /* Test read with rotation */ + zassert_equal(EC_SUCCESS, ms->drv->read(ms, ret_v), NULL); + drv_acc_to_emul(ret_v, 4, ret_v); + compare_int3v(exp_v, ret_v); + + /* Fail on read of data registers */ + i2c_common_emul_set_read_fail_reg(common_data, BMI160_ACC_X_L_G); + zassert_equal(EC_ERROR_INVAL, ms->drv->read(ms, ret_v), NULL); + i2c_common_emul_set_read_fail_reg(common_data, BMI160_ACC_X_H_G); + zassert_equal(EC_ERROR_INVAL, ms->drv->read(ms, ret_v), NULL); + i2c_common_emul_set_read_fail_reg(common_data, BMI160_ACC_Y_L_G); + zassert_equal(EC_ERROR_INVAL, ms->drv->read(ms, ret_v), NULL); + i2c_common_emul_set_read_fail_reg(common_data, BMI160_ACC_Y_H_G); + zassert_equal(EC_ERROR_INVAL, ms->drv->read(ms, ret_v), NULL); + i2c_common_emul_set_read_fail_reg(common_data, BMI160_ACC_Z_L_G); + zassert_equal(EC_ERROR_INVAL, ms->drv->read(ms, ret_v), NULL); + i2c_common_emul_set_read_fail_reg(common_data, BMI160_ACC_Z_H_G); + zassert_equal(EC_ERROR_INVAL, ms->drv->read(ms, ret_v), NULL); + + i2c_common_emul_set_read_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + ms->rot_standard_ref = NULL; +} + +/** Test reading gyroscope sensor data */ +ZTEST_USER(bmi160, test_bmi_gyr_read) +{ + struct motion_sensor_t *ms; + const struct emul *emul = EMUL_DT_GET(BMI_NODE); + struct i2c_common_emul_data *common_data = + emul_bmi_get_i2c_common_data(emul); + intv3_t ret_v; + intv3_t exp_v; + int16_t scale[3] = { MOTION_SENSE_DEFAULT_SCALE, + MOTION_SENSE_DEFAULT_SCALE, + MOTION_SENSE_DEFAULT_SCALE }; + + ms = &motion_sensors[BMI_GYR_SENSOR_ID]; + + /* Set offset 0 to simplify test */ + bmi_emul_set_off(emul, BMI_EMUL_GYR_X, 0); + bmi_emul_set_off(emul, BMI_EMUL_GYR_Y, 0); + bmi_emul_set_off(emul, BMI_EMUL_GYR_Z, 0); + + /* Fail on read status */ + i2c_common_emul_set_read_fail_reg(common_data, BMI160_STATUS); + zassert_equal(EC_ERROR_INVAL, ms->drv->read(ms, ret_v), NULL); + + i2c_common_emul_set_read_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + + /* When not ready, driver should return saved raw value */ + exp_v[0] = 100; + exp_v[1] = 200; + exp_v[2] = 300; + ms->raw_xyz[0] = exp_v[0]; + ms->raw_xyz[1] = exp_v[1]; + ms->raw_xyz[2] = exp_v[2]; + + /* Status not ready */ + bmi_emul_set_reg(emul, BMI160_STATUS, 0); + zassert_equal(EC_SUCCESS, ms->drv->read(ms, ret_v), NULL); + compare_int3v(exp_v, ret_v); + + /* Status only ACC ready */ + bmi_emul_set_reg(emul, BMI160_STATUS, BMI160_DRDY_ACC); + zassert_equal(EC_SUCCESS, ms->drv->read(ms, ret_v), NULL); + compare_int3v(exp_v, ret_v); + + /* Status GYR ready */ + bmi_emul_set_reg(emul, BMI160_STATUS, BMI160_DRDY_GYR); + + /* Set input accelerometer values */ + exp_v[0] = BMI_EMUL_125_DEG_S / 10; + exp_v[1] = BMI_EMUL_125_DEG_S / 20; + exp_v[2] = -(int)BMI_EMUL_125_DEG_S / 30; + set_emul_gyr(emul, exp_v); + /* Disable rotation */ + ms->rot_standard_ref = NULL; + /* Set scale */ + zassert_equal(EC_SUCCESS, ms->drv->set_scale(ms, scale, 0), NULL); + /* Set range to 125°/s */ + zassert_equal(EC_SUCCESS, ms->drv->set_range(ms, 125, 0), NULL); + + /* Test read without rotation */ + zassert_equal(EC_SUCCESS, ms->drv->read(ms, ret_v), NULL); + drv_gyr_to_emul(ret_v, 125, ret_v); + compare_int3v(exp_v, ret_v); + + /* Set range to 1000°/s */ + zassert_equal(EC_SUCCESS, ms->drv->set_range(ms, 1000, 0), NULL); + + /* Test read without rotation */ + zassert_equal(EC_SUCCESS, ms->drv->read(ms, ret_v), NULL); + drv_gyr_to_emul(ret_v, 1000, ret_v); + compare_int3v(exp_v, ret_v); + + /* Setup rotation and rotate expected vector */ + ms->rot_standard_ref = &test_rotation; + rotate_int3v_by_test_rotation(exp_v); + /* Set range to 125°/s */ + zassert_equal(EC_SUCCESS, ms->drv->set_range(ms, 125, 0), NULL); + + /* Test read with rotation */ + zassert_equal(EC_SUCCESS, ms->drv->read(ms, ret_v), NULL); + drv_gyr_to_emul(ret_v, 125, ret_v); + compare_int3v(exp_v, ret_v); + + /* Set range to 1000°/s */ + zassert_equal(EC_SUCCESS, ms->drv->set_range(ms, 1000, 0), NULL); + + /* Test read with rotation */ + zassert_equal(EC_SUCCESS, ms->drv->read(ms, ret_v), NULL); + drv_gyr_to_emul(ret_v, 1000, ret_v); + compare_int3v(exp_v, ret_v); + + /* Fail on read of data registers */ + i2c_common_emul_set_read_fail_reg(common_data, BMI160_GYR_X_L_G); + zassert_equal(EC_ERROR_INVAL, ms->drv->read(ms, ret_v), NULL); + i2c_common_emul_set_read_fail_reg(common_data, BMI160_GYR_X_H_G); + zassert_equal(EC_ERROR_INVAL, ms->drv->read(ms, ret_v), NULL); + i2c_common_emul_set_read_fail_reg(common_data, BMI160_GYR_Y_L_G); + zassert_equal(EC_ERROR_INVAL, ms->drv->read(ms, ret_v), NULL); + i2c_common_emul_set_read_fail_reg(common_data, BMI160_GYR_Y_H_G); + zassert_equal(EC_ERROR_INVAL, ms->drv->read(ms, ret_v), NULL); + i2c_common_emul_set_read_fail_reg(common_data, BMI160_GYR_Z_L_G); + zassert_equal(EC_ERROR_INVAL, ms->drv->read(ms, ret_v), NULL); + i2c_common_emul_set_read_fail_reg(common_data, BMI160_GYR_Z_H_G); + zassert_equal(EC_ERROR_INVAL, ms->drv->read(ms, ret_v), NULL); + + i2c_common_emul_set_read_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + ms->rot_standard_ref = NULL; +} + +/** + * Custom emulatro read function which always return not ready STATUS register. + * Used in calibration test. + */ +static int emul_nrdy(const struct emul *emul, int reg, uint8_t *val, int byte, + void *data) +{ + if (reg == BMI160_STATUS) { + bmi_emul_set_reg(emul, BMI160_STATUS, 0); + *val = 0; + + return 0; + } + + return 1; +} + +/** Test acceleromtere calibration */ +ZTEST_USER(bmi160, test_bmi_acc_perform_calib) +{ + struct motion_sensor_t *ms; + const struct emul *emul = EMUL_DT_GET(BMI_NODE); + struct i2c_common_emul_data *common_data = + emul_bmi_get_i2c_common_data(emul); + uint8_t pmu_status; + intv3_t start_off; + intv3_t exp_off; + intv3_t ret_off; + int range; + int rate; + mat33_fp_t rot = { { FLOAT_TO_FP(1), 0, 0 }, + { 0, FLOAT_TO_FP(1), 0 }, + { 0, 0, FLOAT_TO_FP(-1) } }; + + ms = &motion_sensors[BMI_ACC_SENSOR_ID]; + + /* Enable sensors */ + pmu_status = BMI160_PMU_NORMAL << BMI160_PMU_ACC_OFFSET; + pmu_status |= BMI160_PMU_NORMAL << BMI160_PMU_GYR_OFFSET; + bmi_emul_set_reg(emul, BMI160_PMU_STATUS, pmu_status); + + /* Range and rate cannot change after calibration */ + range = 4; + rate = 50000; + zassert_equal(EC_SUCCESS, ms->drv->set_range(ms, range, 0), NULL); + zassert_equal(EC_SUCCESS, ms->drv->set_data_rate(ms, rate, 0), NULL); + + /* Set offset 0 */ + start_off[0] = 0; + start_off[1] = 0; + start_off[2] = 0; + set_emul_acc_offset(emul, start_off); + + /* Set input accelerometer values */ + exp_off[0] = BMI_EMUL_1G / 10; + exp_off[1] = BMI_EMUL_1G / 20; + exp_off[2] = BMI_EMUL_1G - (int)BMI_EMUL_1G / 30; + set_emul_acc(emul, exp_off); + + /* + * Expected offset is [-X, -Y, 1G - Z] for no rotation or positive + * rotation on Z axis + */ + exp_off[0] = -exp_off[0]; + exp_off[1] = -exp_off[1]; + exp_off[2] = BMI_EMUL_1G - exp_off[2]; + + /* Test fail on rate set */ + i2c_common_emul_set_read_fail_reg(common_data, BMI160_ACC_CONF); + zassert_equal(EC_ERROR_INVAL, ms->drv->perform_calib(ms, 1), NULL); + zassert_equal(range, ms->current_range, NULL); + zassert_equal(rate, ms->drv->get_data_rate(ms), NULL); + + /* Test fail on status read */ + i2c_common_emul_set_read_fail_reg(common_data, BMI160_STATUS); + zassert_equal(EC_ERROR_INVAL, ms->drv->perform_calib(ms, 1), NULL); + zassert_equal(range, ms->current_range, NULL); + zassert_equal(rate, ms->drv->get_data_rate(ms), NULL); + /* Stop fast offset compensation before next test */ + bmi_emul_set_reg(emul, BMI160_CMD_REG, BMI160_CMD_NOOP); + + /* Test fail on data not ready */ + i2c_common_emul_set_read_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + i2c_common_emul_set_read_func(common_data, emul_nrdy, NULL); + zassert_equal(EC_RES_TIMEOUT, ms->drv->perform_calib(ms, 1), NULL); + zassert_equal(range, ms->current_range, NULL); + zassert_equal(rate, ms->drv->get_data_rate(ms), NULL); + /* Remove custom emulator read function */ + i2c_common_emul_set_read_func(common_data, NULL, NULL); + /* Stop fast offset compensation before next test */ + bmi_emul_set_reg(emul, BMI160_CMD_REG, BMI160_CMD_NOOP); + + /* Disable rotation */ + ms->rot_standard_ref = NULL; + /* Test successful offset compenastion without rotation */ + zassert_equal(EC_SUCCESS, ms->drv->perform_calib(ms, 1), NULL); + zassert_equal(range, ms->current_range, NULL); + zassert_equal(rate, ms->drv->get_data_rate(ms), NULL); + get_emul_acc_offset(emul, ret_off); + /* + * Depending on used range, accelerometer values may be up to 6 bits + * more accurate then offset value resolution. + */ + compare_int3v_eps(exp_off, ret_off, 64); + /* Acelerometer offset should be enabled */ + zassert_true(bmi_emul_get_reg(emul, BMI160_OFFSET_EN_GYR98) & + BMI160_OFFSET_ACC_EN, + NULL); + + /* Enable rotation with negative value on Z axis */ + ms->rot_standard_ref = &rot; + /* Expected offset -1G - accelerometer[Z] */ + bmi_emul_set_value(emul, BMI_EMUL_ACC_Z, -(int)BMI_EMUL_1G - 1234); + exp_off[2] = 1234; + + /* Test successful offset compenastion with negative Z rotation */ + zassert_equal(EC_SUCCESS, ms->drv->perform_calib(ms, 1), NULL); + zassert_equal(range, ms->current_range, NULL); + zassert_equal(rate, ms->drv->get_data_rate(ms), NULL); + get_emul_acc_offset(emul, ret_off); + compare_int3v_eps(exp_off, ret_off, 64); + /* Acelerometer offset should be enabled */ + zassert_true(bmi_emul_get_reg(emul, BMI160_OFFSET_EN_GYR98) & + BMI160_OFFSET_ACC_EN, + NULL); + + /* Set positive rotation on Z axis */ + rot[2][2] = FLOAT_TO_FP(1); + /* Expected offset 1G - accelerometer[Z] */ + bmi_emul_set_value(emul, BMI_EMUL_ACC_Z, BMI_EMUL_1G - 1234); + exp_off[2] = 1234; + + /* Test successful offset compenastion with positive Z rotation */ + zassert_equal(EC_SUCCESS, ms->drv->perform_calib(ms, 1), NULL); + zassert_equal(range, ms->current_range, NULL); + zassert_equal(rate, ms->drv->get_data_rate(ms), NULL); + get_emul_acc_offset(emul, ret_off); + compare_int3v_eps(exp_off, ret_off, 64); + /* Acelerometer offset should be enabled */ + zassert_true(bmi_emul_get_reg(emul, BMI160_OFFSET_EN_GYR98) & + BMI160_OFFSET_ACC_EN, + NULL); + /* Disable rotation */ + ms->rot_standard_ref = NULL; +} + +/** Test gyroscope calibration */ +ZTEST_USER(bmi160, test_bmi_gyr_perform_calib) +{ + struct motion_sensor_t *ms; + const struct emul *emul = EMUL_DT_GET(BMI_NODE); + struct i2c_common_emul_data *common_data = + emul_bmi_get_i2c_common_data(emul); + uint8_t pmu_status; + intv3_t start_off; + intv3_t exp_off; + intv3_t ret_off; + int range; + int rate; + + ms = &motion_sensors[BMI_GYR_SENSOR_ID]; + + /* Enable sensors */ + pmu_status = BMI160_PMU_NORMAL << BMI160_PMU_ACC_OFFSET; + pmu_status |= BMI160_PMU_NORMAL << BMI160_PMU_GYR_OFFSET; + bmi_emul_set_reg(emul, BMI160_PMU_STATUS, pmu_status); + + /* Range and rate cannot change after calibration */ + range = 250; + rate = 50000; + zassert_equal(EC_SUCCESS, ms->drv->set_range(ms, range, 0), NULL); + zassert_equal(EC_SUCCESS, ms->drv->set_data_rate(ms, rate, 0), NULL); + + /* Set offset 0 */ + start_off[0] = 0; + start_off[1] = 0; + start_off[2] = 0; + set_emul_gyr_offset(emul, start_off); + + /* Set input accelerometer values */ + exp_off[0] = BMI_EMUL_125_DEG_S / 100; + exp_off[1] = BMI_EMUL_125_DEG_S / 200; + exp_off[2] = -(int)BMI_EMUL_125_DEG_S / 300; + set_emul_gyr(emul, exp_off); + + /* Expected offset is [-X, -Y, -Z] */ + exp_off[0] = -exp_off[0]; + exp_off[1] = -exp_off[1]; + exp_off[2] = -exp_off[2]; + + /* Test success on disabling calibration */ + zassert_equal(EC_SUCCESS, ms->drv->perform_calib(ms, 0), NULL); + zassert_equal(range, ms->current_range, NULL); + zassert_equal(rate, ms->drv->get_data_rate(ms), NULL); + + /* Test fail on rate set */ + i2c_common_emul_set_read_fail_reg(common_data, BMI160_GYR_CONF); + zassert_equal(EC_ERROR_INVAL, ms->drv->perform_calib(ms, 1), NULL); + zassert_equal(range, ms->current_range, NULL); + zassert_equal(rate, ms->drv->get_data_rate(ms), NULL); + + /* Test fail on status read */ + i2c_common_emul_set_read_fail_reg(common_data, BMI160_STATUS); + zassert_equal(EC_ERROR_INVAL, ms->drv->perform_calib(ms, 1), NULL); + zassert_equal(range, ms->current_range, NULL); + zassert_equal(rate, ms->drv->get_data_rate(ms), NULL); + /* Stop fast offset compensation before next test */ + bmi_emul_set_reg(emul, BMI160_CMD_REG, BMI160_CMD_NOOP); + + /* Test fail on data not ready */ + i2c_common_emul_set_read_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + i2c_common_emul_set_read_func(common_data, emul_nrdy, NULL); + zassert_equal(EC_RES_TIMEOUT, ms->drv->perform_calib(ms, 1), NULL); + zassert_equal(range, ms->current_range, NULL); + zassert_equal(rate, ms->drv->get_data_rate(ms), NULL); + /* Remove custom emulator read function */ + i2c_common_emul_set_read_func(common_data, NULL, NULL); + /* Stop fast offset compensation before next test */ + bmi_emul_set_reg(emul, BMI160_CMD_REG, BMI160_CMD_NOOP); + + /* Test successful offset compenastion */ + zassert_equal(EC_SUCCESS, ms->drv->perform_calib(ms, 1), NULL); + zassert_equal(range, ms->current_range, NULL); + zassert_equal(rate, ms->drv->get_data_rate(ms), NULL); + get_emul_gyr_offset(emul, ret_off); + /* + * Depending on used range, gyroscope values may be up to 4 bits + * more accurate then offset value resolution. + */ + compare_int3v_eps(exp_off, ret_off, 32); + /* Gyroscope offset should be enabled */ + zassert_true(bmi_emul_get_reg(emul, BMI160_OFFSET_EN_GYR98) & + BMI160_OFFSET_GYRO_EN, + NULL); +} + +/** Test init function of BMI160 accelerometer and gyroscope sensors */ +ZTEST_USER(bmi160, test_bmi_init) +{ + struct motion_sensor_t *ms_acc, *ms_gyr; + + ms_acc = &motion_sensors[BMI_ACC_SENSOR_ID]; + ms_gyr = &motion_sensors[BMI_GYR_SENSOR_ID]; + + /* Test successful init */ + zassert_equal(EC_RES_SUCCESS, ms_acc->drv->init(ms_acc), NULL); + + zassert_equal(EC_RES_SUCCESS, ms_gyr->drv->init(ms_gyr), NULL); +} + +/** Data for custom emulator read function used in FIFO test */ +struct fifo_func_data { + uint16_t interrupts; +}; + +/** + * Custom emulator read function used in FIFO test. It sets interrupt registers + * to value passed as additional data. It sets interrupt registers to 0 after + * access. + */ +static int emul_fifo_func(const struct emul *emul, int reg, uint8_t *val, + int byte, void *data) +{ + struct fifo_func_data *d = data; + + if (reg + byte == BMI160_INT_STATUS_0) { + bmi_emul_set_reg(emul, BMI160_INT_STATUS_0, + d->interrupts & 0xff); + d->interrupts &= 0xff00; + } else if (reg + byte == BMI160_INT_STATUS_1) { + bmi_emul_set_reg(emul, BMI160_INT_STATUS_1, + (d->interrupts >> 8) & 0xff); + d->interrupts &= 0xff; + } + + return 1; +} + +/** + * Run irq handler on accelerometer sensor and check if committed data in FIFO + * match what was set in FIFO frames in emulator. + */ +static void check_fifo_f(struct motion_sensor_t *ms_acc, + struct motion_sensor_t *ms_gyr, + struct bmi_emul_frame *frame, int acc_range, + int gyr_range, int line) +{ + struct ec_response_motion_sensor_data vector; + struct bmi_emul_frame *f_acc, *f_gyr; + uint32_t event = BMI_INT_EVENT; + uint16_t size; + intv3_t exp_v; + intv3_t ret_v; + + /* Find first frame of acc and gyr type */ + f_acc = frame; + while (f_acc != NULL && !(f_acc->type & BMI_EMUL_FRAME_ACC)) { + f_acc = f_acc->next; + } + + f_gyr = frame; + while (f_gyr != NULL && !(f_gyr->type & BMI_EMUL_FRAME_GYR)) { + f_gyr = f_gyr->next; + } + + /* Read FIFO in driver */ + zassert_equal(EC_SUCCESS, ms_acc->drv->irq_handler(ms_acc, &event), + "Failed to read FIFO in irq handler, line %d", line); + + /* Read all data committed to FIFO */ + while (motion_sense_fifo_read(sizeof(vector), 1, &vector, &size)) { + /* Ignore timestamp frames */ + if (vector.flags == MOTIONSENSE_SENSOR_FLAG_TIMESTAMP) { + continue; + } + + /* Check acclerometer frames */ + if (ms_acc - motion_sensors == vector.sensor_num) { + if (f_acc == NULL) { + zassert_unreachable( + "Not expected acclerometer data in FIFO, line %d", + line); + } + + convert_int3v_int16(vector.data, ret_v); + drv_acc_to_emul(ret_v, acc_range, ret_v); + exp_v[0] = f_acc->acc_x; + exp_v[1] = f_acc->acc_y; + exp_v[2] = f_acc->acc_z; + compare_int3v_f(exp_v, ret_v, V_EPS, line); + f_acc = f_acc->next; + } + + /* Check gyroscope frames */ + if (ms_gyr - motion_sensors == vector.sensor_num) { + if (f_gyr == NULL) { + zassert_unreachable( + "Not expected gyroscope data in FIFO, line %d", + line); + } + + convert_int3v_int16(vector.data, ret_v); + drv_gyr_to_emul(ret_v, gyr_range, ret_v); + exp_v[0] = f_gyr->gyr_x; + exp_v[1] = f_gyr->gyr_y; + exp_v[2] = f_gyr->gyr_z; + compare_int3v_f(exp_v, ret_v, V_EPS, line); + f_gyr = f_gyr->next; + } + } + + /* Skip frames of different type at the end */ + while (f_acc != NULL && !(f_acc->type & BMI_EMUL_FRAME_ACC)) { + f_acc = f_acc->next; + } + + while (f_gyr != NULL && !(f_gyr->type & BMI_EMUL_FRAME_GYR)) { + f_gyr = f_gyr->next; + } + + /* All frames are readed */ + zassert_is_null(f_acc, "Not all accelerometer frames are read, line %d", + line); + zassert_is_null(f_gyr, "Not all gyroscope frames are read, line %d", + line); +} +#define check_fifo(ms_acc, ms_gyr, frame, acc_range, gyr_range) \ + check_fifo_f(ms_acc, ms_gyr, frame, acc_range, gyr_range, __LINE__) + +/** Test irq handler of accelerometer sensor */ +ZTEST_USER(bmi160, test_bmi_acc_fifo) +{ + struct motion_sensor_t *ms, *ms_gyr; + struct fifo_func_data func_data; + struct bmi_emul_frame f[3]; + const struct emul *emul = EMUL_DT_GET(BMI_NODE); + struct i2c_common_emul_data *common_data = + emul_bmi_get_i2c_common_data(emul); + int gyr_range = 125; + int acc_range = 2; + int event; + + ms = &motion_sensors[BMI_ACC_SENSOR_ID]; + ms_gyr = &motion_sensors[BMI_GYR_SENSOR_ID]; + + /* init bmi before test */ + zassert_equal(EC_RES_SUCCESS, ms->drv->init(ms), NULL); + zassert_equal(EC_RES_SUCCESS, ms_gyr->drv->init(ms_gyr), NULL); + + /* Need to be set to collect all data in FIFO */ + ms->oversampling_ratio = 1; + ms_gyr->oversampling_ratio = 1; + /* Only BMI event should be handled */ + event = 0x1234 & ~BMI_INT_EVENT; + zassert_equal(EC_ERROR_NOT_HANDLED, ms->drv->irq_handler(ms, &event), + NULL); + + event = BMI_INT_EVENT; + + /* Test fail to read interrupt status registers */ + i2c_common_emul_set_read_fail_reg(common_data, BMI160_INT_STATUS_0); + zassert_equal(EC_ERROR_INVAL, ms->drv->irq_handler(ms, &event), NULL); + i2c_common_emul_set_read_fail_reg(common_data, BMI160_INT_STATUS_1); + zassert_equal(EC_ERROR_INVAL, ms->drv->irq_handler(ms, &event), NULL); + i2c_common_emul_set_read_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + + /* Test no interrupt */ + bmi_emul_set_reg(emul, BMI160_INT_STATUS_0, 0); + bmi_emul_set_reg(emul, BMI160_INT_STATUS_1, 0); + + /* Enable sensor FIFO */ + zassert_equal(EC_SUCCESS, ms->drv->set_data_rate(ms, 50000, 0), NULL); + + /* Trigger irq handler and check results */ + check_fifo(ms, ms_gyr, NULL, acc_range, gyr_range); + + /* Set custom function for FIFO test */ + i2c_common_emul_set_read_func(common_data, emul_fifo_func, &func_data); + /* Set range */ + zassert_equal(EC_SUCCESS, ms->drv->set_range(ms, acc_range, 0), NULL); + zassert_equal(EC_SUCCESS, ms_gyr->drv->set_range(ms_gyr, gyr_range, 0), + NULL); + /* Setup single accelerometer frame */ + f[0].type = BMI_EMUL_FRAME_ACC; + f[0].acc_x = BMI_EMUL_1G / 10; + f[0].acc_y = BMI_EMUL_1G / 20; + f[0].acc_z = -(int)BMI_EMUL_1G / 30; + f[0].next = NULL; + bmi_emul_append_frame(emul, f); + /* Setup interrupts register */ + func_data.interrupts = BMI160_FWM_INT; + + /* Trigger irq handler and check results */ + check_fifo(ms, ms_gyr, f, acc_range, gyr_range); + + /* Setup second accelerometer frame */ + f[1].type = BMI_EMUL_FRAME_ACC; + f[1].acc_x = -(int)BMI_EMUL_1G / 40; + f[1].acc_y = BMI_EMUL_1G / 50; + f[1].acc_z = BMI_EMUL_1G / 60; + f[0].next = &(f[1]); + f[1].next = NULL; + bmi_emul_append_frame(emul, f); + /* Setup interrupts register */ + func_data.interrupts = BMI160_FWM_INT; + + /* Trigger irq handler and check results */ + check_fifo(ms, ms_gyr, f, acc_range, gyr_range); + + /* Enable sensor FIFO */ + zassert_equal(EC_SUCCESS, ms_gyr->drv->set_data_rate(ms_gyr, 50000, 0), + NULL); + + /* Setup first gyroscope frame (after two accelerometer frames) */ + f[2].type = BMI_EMUL_FRAME_GYR; + f[2].gyr_x = -(int)BMI_EMUL_125_DEG_S / 100; + f[2].gyr_y = BMI_EMUL_125_DEG_S / 200; + f[2].gyr_z = BMI_EMUL_125_DEG_S / 300; + f[1].next = &(f[2]); + f[2].next = NULL; + bmi_emul_append_frame(emul, f); + /* Setup interrupts register */ + func_data.interrupts = BMI160_FWM_INT; + + /* Trigger irq handler and check results */ + check_fifo(ms, ms_gyr, f, acc_range, gyr_range); + + /* Setup second accelerometer frame to by gyroscope frame too */ + f[1].type |= BMI_EMUL_FRAME_GYR; + f[1].gyr_x = -(int)BMI_EMUL_125_DEG_S / 300; + f[1].gyr_y = BMI_EMUL_125_DEG_S / 400; + f[1].gyr_z = BMI_EMUL_125_DEG_S / 500; + bmi_emul_append_frame(emul, f); + /* Setup interrupts register */ + func_data.interrupts = BMI160_FWM_INT; + + /* Trigger irq handler and check results */ + check_fifo(ms, ms_gyr, f, acc_range, gyr_range); + + /* Skip frame should be ignored by driver */ + bmi_emul_set_skipped_frames(emul, 8); + bmi_emul_append_frame(emul, f); + /* Setup interrupts register */ + func_data.interrupts = BMI160_FWM_INT; + + /* Trigger irq handler and check results */ + check_fifo(ms, ms_gyr, f, acc_range, gyr_range); + + /* Setup second frame as an config frame */ + f[1].type = BMI_EMUL_FRAME_CONFIG; + /* Indicate that accelerometer range changed */ + f[1].config = 0x1; + bmi_emul_append_frame(emul, f); + /* Setup interrupts register */ + func_data.interrupts = BMI160_FWM_INT; + + /* Trigger irq handler and check results */ + check_fifo(ms, ms_gyr, f, acc_range, gyr_range); + + /* Remove custom emulator read function */ + i2c_common_emul_set_read_func(common_data, NULL, NULL); +} + +/** Test irq handler of gyroscope sensor */ +ZTEST_USER(bmi160, test_bmi_gyr_fifo) +{ + struct motion_sensor_t *ms; + uint32_t event; + + ms = &motion_sensors[BMI_GYR_SENSOR_ID]; + + /* Interrupt shuldn't be triggered for gyroscope motion sense */ + event = BMI_INT_EVENT; + zassert_equal(EC_ERROR_NOT_HANDLED, ms->drv->irq_handler(ms, &event), + NULL); +} + +/** Test reading from compass via `bmi160_sec_raw_read8()` */ +ZTEST_USER(bmi160, test_bmi_sec_raw_read8) +{ + struct motion_sensor_t *ms = &motion_sensors[BMI_ACC_SENSOR_ID]; + const struct emul *emul = EMUL_DT_GET(BMI_NODE); + uint8_t expected_read_value = 0xAA; + uint8_t requested_reg_addr = 0x55; + uint8_t actual_reg_addr; + int actual_read_value; + int ret; + + bmi_emul_set_reg(emul, BMI160_MAG_I2C_READ_DATA, expected_read_value); + + ret = bmi160_sec_raw_read8(ms->port, ms->i2c_spi_addr_flags, + requested_reg_addr, &actual_read_value); + + /* Verify return value */ + zassert_equal(ret, EC_RES_SUCCESS, "Expected return code %d but got %d", + EC_RES_SUCCESS, ret); + + /* Verify the correct value was read */ + zassert_equal(expected_read_value, actual_read_value, + "Read value $%02x but expected to read $%02x", + actual_read_value, expected_read_value); + + /* Verify the intended register address was read */ + actual_reg_addr = bmi_emul_get_reg(emul, BMI160_MAG_I2C_READ_ADDR); + zassert_equal(requested_reg_addr, actual_reg_addr, + "Read reg $%02x but expected to read $%02x", + actual_reg_addr, requested_reg_addr); +} + +/** Test writing to compass via `bmi160_sec_raw_write8()` */ +ZTEST_USER(bmi160, test_bmi_sec_raw_write8) +{ + struct motion_sensor_t *ms = &motion_sensors[BMI_ACC_SENSOR_ID]; + const struct emul *emul = EMUL_DT_GET(BMI_NODE); + uint8_t expected_write_value = 0xAB; + uint8_t requested_reg_addr = 0x56; + uint8_t actual_reg_addr; + int actual_written_value; + int ret; + + ret = bmi160_sec_raw_write8(ms->port, ms->i2c_spi_addr_flags, + requested_reg_addr, expected_write_value); + + /* Verify return value */ + zassert_equal(ret, EC_RES_SUCCESS, "Expected return code %d but got %d", + EC_RES_SUCCESS, ret); + + /* Verify the correct value was written */ + actual_written_value = + bmi_emul_get_reg(emul, BMI160_MAG_I2C_WRITE_DATA); + zassert_equal(expected_write_value, actual_written_value, + "Wrote value $%02x but expected to write $%02x", + actual_written_value, expected_write_value); + + /* Verify the intended register address was used */ + actual_reg_addr = bmi_emul_get_reg(emul, BMI160_MAG_I2C_WRITE_ADDR); + zassert_equal(requested_reg_addr, actual_reg_addr, + "Wrote reg $%02x but expected to write $%02x", + actual_reg_addr, requested_reg_addr); +} + +/** Test setting an offset on an invalid sensor type */ +ZTEST_USER(bmi160, test_bmi_set_offset_invalid_type) +{ + struct motion_sensor_t ms_fake; + int ret; + int16_t unused_offset = 0; + int16_t temp = 0; + + /* make a copy of the accel motion sensor so we modify its type */ + memcpy(&ms_fake, &motion_sensors[BMI_ACC_SENSOR_ID], sizeof(ms_fake)); + ms_fake.type = MOTIONSENSE_TYPE_MAX; + + ret = ms_fake.drv->set_offset(&ms_fake, &unused_offset, temp); + + zassert_equal(ret, EC_RES_INVALID_PARAM, + "Expected return code of %d but got %d", + EC_RES_INVALID_PARAM, ret); +} + +/** Test performing a calibration on a magnetometer, which is not supported */ +ZTEST_USER(bmi160, test_bmi_perform_calib_invalid_type) +{ + struct motion_sensor_t ms_fake; + int ret; + + /* make a copy of the accel motion sensor so we modify its type */ + memcpy(&ms_fake, &motion_sensors[BMI_ACC_SENSOR_ID], sizeof(ms_fake)); + ms_fake.type = MOTIONSENSE_TYPE_MAG; + + ret = ms_fake.drv->perform_calib(&ms_fake, 1); + + zassert_equal(ret, EC_RES_INVALID_PARAM, + "Expected return code of %d but got %d", + EC_RES_INVALID_PARAM, ret); +} + +/** Test reading the onboard temperature sensor */ +ZTEST_USER(bmi160, test_bmi_temp_sensor) +{ + const struct emul *emul = EMUL_DT_GET(BMI_NODE); + int ret; + + /* Part 1: + * Set up the register so we read 300 Kelvin. 0x0000 is 23 deg C, and + * each LSB is 0.5^9 deg C. See BMI160 datasheet for more details. + */ + int actual_read_temp_k, expected_temp_k = 300; + uint16_t temp_reg_value = (K_TO_C(expected_temp_k) - 23) << 9; + + bmi_emul_set_reg(emul, BMI160_TEMPERATURE_0, temp_reg_value & 0xFF); + bmi_emul_set_reg(emul, BMI160_TEMPERATURE_1, temp_reg_value >> 8); + + /* The output will be in Kelvin */ + ret = bmi160_get_sensor_temp(BMI_ACC_SENSOR_ID, &actual_read_temp_k); + + zassert_equal(ret, EC_RES_SUCCESS, "Expected %d but got %d", + EC_RES_SUCCESS, ret); + zassert_equal(expected_temp_k, actual_read_temp_k, + "Expected %dK but got %dK", expected_temp_k, + actual_read_temp_k); + + /* Part 2: + * Have the chip return an invalid reading. + */ + temp_reg_value = BMI_INVALID_TEMP; + bmi_emul_set_reg(emul, BMI160_TEMPERATURE_0, temp_reg_value & 0xFF); + bmi_emul_set_reg(emul, BMI160_TEMPERATURE_1, temp_reg_value >> 8); + + ret = bmi160_get_sensor_temp(BMI_ACC_SENSOR_ID, &actual_read_temp_k); + + zassert_equal(ret, EC_ERROR_NOT_POWERED, "Expected %d but got %d", + EC_ERROR_NOT_POWERED, ret); +} + +ZTEST_USER(bmi160, test_bmi_interrupt_handler) +{ + /* The accelerometer interrupt handler simply sets an event flag for the + * motion sensing task. Make sure that flag starts cleared, fire the + * interrupt, and ensure the flag is set. + */ + + atomic_t *mask; + + mask = task_get_event_bitmap(TASK_ID_MOTIONSENSE); + zassert_true(mask != NULL, + "Got a null pointer when getting event bitmap."); + zassert_true((*mask & CONFIG_ACCELGYRO_BMI160_INT_EVENT) == 0, + "Event flag is set before firing interrupt"); + + bmi160_interrupt(0); + + mask = task_get_event_bitmap(TASK_ID_MOTIONSENSE); + zassert_true(mask != NULL, + "Got a null pointer when getting event bitmap."); + zassert_true(*mask & CONFIG_ACCELGYRO_BMI160_INT_EVENT, + "Event flag is not set after firing interrupt"); +} + +/* Make an I2C emulator mock wrapped in FFF for use with test_bmi_init_chip_id() + */ +FAKE_VALUE_FUNC(int, bmi_init_chip_id_mock_write_fn, const struct emul *, int, + uint8_t, int, void *); + +/** Test handling of invalid or unreadable chip IDs in init() */ +ZTEST_USER(bmi160, test_bmi_init_chip_id) +{ + struct motion_sensor_t *ms = &motion_sensors[BMI_ACC_SENSOR_ID]; + const struct emul *emul = EMUL_DT_GET(BMI_NODE); + struct i2c_common_emul_data *common_data = + emul_bmi_get_i2c_common_data(emul); + int ret; + + /* Part 1: Cannot read the Chip ID register */ + i2c_common_emul_set_read_fail_reg(common_data, BMI160_CHIP_ID); + ret = ms->drv->init(ms); + + zassert_equal(ret, EC_ERROR_UNKNOWN, "Expected %d but got %d", + EC_ERROR_UNKNOWN, ret); + + i2c_common_emul_set_read_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + + /* Part 2: Incorrect chip ID - this triggers a series of writes in an + * attempt to 'unlock' the chip. + */ + + /* Have the mocked write function return 1 so everything is passed + * through. We only care about using FFF to capture the argument + * history. + */ + + RESET_FAKE(bmi_init_chip_id_mock_write_fn); + bmi_init_chip_id_mock_write_fn_fake.return_val = 1; + i2c_common_emul_set_write_func(common_data, + bmi_init_chip_id_mock_write_fn, NULL); + + /* Return a phony chip ID */ + bmi_emul_set_reg(emul, BMI160_CHIP_ID, 0xFF); + + ret = ms->drv->init(ms); + + /* Verify return value */ + zassert_equal(ret, EC_ERROR_ACCESS_DENIED, "Expected %d but got %d", + EC_ERROR_ACCESS_DENIED, ret); + + /* Verify that all expected I2C writes were completed, in order */ + MOCK_ASSERT_I2C_WRITE(bmi_init_chip_id_mock_write_fn, 0, BMI160_CMD_REG, + BMI160_CMD_EXT_MODE_EN_B0); + MOCK_ASSERT_I2C_WRITE(bmi_init_chip_id_mock_write_fn, 1, BMI160_CMD_REG, + BMI160_CMD_EXT_MODE_EN_B1); + MOCK_ASSERT_I2C_WRITE(bmi_init_chip_id_mock_write_fn, 2, BMI160_CMD_REG, + BMI160_CMD_EXT_MODE_EN_B2); + MOCK_ASSERT_I2C_WRITE(bmi_init_chip_id_mock_write_fn, 3, + BMI160_CMD_EXT_MODE_ADDR, BMI160_CMD_PAGING_EN); + MOCK_ASSERT_I2C_WRITE(bmi_init_chip_id_mock_write_fn, 4, + BMI160_CMD_EXT_MODE_ADDR, 0); + + i2c_common_emul_set_write_func(common_data, NULL, NULL); +} + +static void bmi160_before(void *fixture) +{ + ARG_UNUSED(fixture); + const struct emul *emul = EMUL_DT_GET(BMI_NODE); + struct i2c_common_emul_data *common_data = + emul_bmi_get_i2c_common_data(emul); + struct motion_sensor_t *acc_ms; + struct motion_sensor_t *gyr_ms; + + acc_ms = &motion_sensors[BMI_ACC_SENSOR_ID]; + gyr_ms = &motion_sensors[BMI_GYR_SENSOR_ID]; + + i2c_common_emul_set_read_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + bmi_emul_set_reg(emul, BMI160_CHIP_ID, 0xd1); + + /* Disable rotation */ + gyr_ms->rot_standard_ref = NULL; + acc_ms->rot_standard_ref = NULL; + + zassume_equal(EC_SUCCESS, acc_ms->drv->set_data_rate(acc_ms, 50000, 0), + NULL); + zassume_equal(EC_SUCCESS, gyr_ms->drv->set_data_rate(gyr_ms, 50000, 0), + NULL); +} + +static void bmi160_after(void *state) +{ + ARG_UNUSED(state); + struct motion_sensor_t *acc_ms, *gyr_ms; + + acc_ms = &motion_sensors[BMI_ACC_SENSOR_ID]; + gyr_ms = &motion_sensors[BMI_GYR_SENSOR_ID]; + + acc_ms->drv->set_data_rate(acc_ms, 0, 0); + gyr_ms->drv->set_data_rate(gyr_ms, 0, 0); +} + +ZTEST_SUITE(bmi160, drivers_predicate_pre_main, NULL, bmi160_before, + bmi160_after, NULL); + +/** Cause an interrupt and verify the motion_sense task handled it. */ +ZTEST_USER(bmi160_tasks, test_irq_handling) +{ + struct bmi_emul_frame f[3]; + const struct emul *emul = EMUL_DT_GET(BMI_NODE); + + f[0].type = BMI_EMUL_FRAME_ACC; + f[0].acc_x = BMI_EMUL_1G / 10; + f[0].acc_y = BMI_EMUL_1G / 20; + f[0].acc_z = -(int)BMI_EMUL_1G / 30; + f[0].next = NULL; + bmi_emul_append_frame(emul, f); + bmi_emul_set_reg(emul, BMI160_INT_STATUS_0, BMI160_FWM_INT & 0xff); + bmi_emul_set_reg(emul, BMI160_INT_STATUS_1, + (BMI160_FWM_INT >> 8) & 0xff); + + bmi160_interrupt(0); + k_sleep(K_SECONDS(10)); + + /* Verify that the motion_sense_task read it. */ + zassert_equal(bmi_emul_get_reg(emul, BMI160_INT_STATUS_0), 0, NULL); + zassert_equal(bmi_emul_get_reg(emul, BMI160_INT_STATUS_1), 0, NULL); +} + +ZTEST_SUITE(bmi160_tasks, drivers_predicate_post_main, NULL, bmi160_before, + bmi160_after, NULL); |