1 /*
2  * Copyright (c) 2023 Google LLC
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 #include <zephyr/devicetree.h>
7 #include <zephyr/drivers/emul.h>
8 #include <zephyr/drivers/sensor.h>
9 #include <zephyr/ztest.h>
10 
11 #include "akm09918c.h"
12 #include "akm09918c_emul.h"
13 #include "akm09918c_reg.h"
14 
15 struct akm09918c_fixture {
16 	const struct device *dev;
17 	const struct emul *target;
18 };
19 
akm09918c_setup(void)20 static void *akm09918c_setup(void)
21 {
22 	static struct akm09918c_fixture fixture = {
23 		.dev = DEVICE_DT_GET(DT_NODELABEL(akm09918c)),
24 		.target = EMUL_DT_GET(DT_NODELABEL(akm09918c)),
25 	};
26 
27 	zassert_not_null(fixture.dev);
28 	zassert_not_null(fixture.target);
29 	return &fixture;
30 }
31 
akm09918c_before(void * f)32 static void akm09918c_before(void *f)
33 {
34 	struct akm09918c_fixture *fixture = f;
35 
36 	akm09918c_emul_reset(fixture->target);
37 }
38 
39 ZTEST_SUITE(akm09918c, NULL, akm09918c_setup, akm09918c_before, NULL, NULL);
40 
ZTEST_F(akm09918c,test_fetch_fail_no_ready_data)41 ZTEST_F(akm09918c, test_fetch_fail_no_ready_data)
42 {
43 	uint8_t status = 0;
44 
45 	akm09918c_emul_set_reg(fixture->target, AKM09918C_REG_ST1, &status, 1);
46 	zassert_equal(-EBUSY, sensor_sample_fetch(fixture->dev));
47 }
48 
test_fetch_magnetic_field(const struct akm09918c_fixture * fixture,const int16_t magn_percent[3])49 static void test_fetch_magnetic_field(const struct akm09918c_fixture *fixture,
50 				      const int16_t magn_percent[3])
51 {
52 	struct sensor_value values[3];
53 	int64_t expect_ugauss;
54 	int64_t actual_ugauss;
55 	uint8_t register_buffer[6];
56 
57 	/* Set the ST1 register to show we have data */
58 	register_buffer[0] = AKM09918C_ST1_DRDY;
59 	akm09918c_emul_set_reg(fixture->target, AKM09918C_REG_ST1, register_buffer, 1);
60 
61 	/* Set the data magn_percent * range */
62 	for (int i = 0; i < 3; ++i) {
63 		register_buffer[i * 2 + 1] = (magn_percent[i] >> 8) & GENMASK(7, 0);
64 		register_buffer[i * 2] = magn_percent[i] & GENMASK(7, 0);
65 	}
66 	akm09918c_emul_set_reg(fixture->target, AKM09918C_REG_HXL, register_buffer, 6);
67 
68 	/* Fetch the data */
69 	zassert_ok(sensor_sample_fetch(fixture->dev));
70 	zassert_ok(sensor_channel_get(fixture->dev, SENSOR_CHAN_MAGN_XYZ, values));
71 
72 	/* Assert the data is within 0.000005 Gauss */
73 	actual_ugauss = values[0].val1 * INT64_C(1000000) + values[0].val2;
74 	expect_ugauss = magn_percent[0] * AKM09918C_MICRO_GAUSS_PER_BIT;
75 	zassert_within(expect_ugauss, actual_ugauss, INT64_C(5),
76 		       "(X) expected %" PRIi64 " micro-gauss, got %" PRIi64 " micro-gauss",
77 		       expect_ugauss, actual_ugauss);
78 
79 	actual_ugauss = values[1].val1 * INT64_C(1000000) + values[1].val2;
80 	expect_ugauss = magn_percent[1] * AKM09918C_MICRO_GAUSS_PER_BIT;
81 	zassert_within(expect_ugauss, actual_ugauss, INT64_C(5),
82 		       "(Y) expected %" PRIi64 " micro-gauss, got %" PRIi64 " micro-gauss",
83 		       expect_ugauss, actual_ugauss);
84 
85 	actual_ugauss = values[2].val1 * INT64_C(1000000) + values[2].val2;
86 	expect_ugauss = magn_percent[2] * AKM09918C_MICRO_GAUSS_PER_BIT;
87 	zassert_within(expect_ugauss, actual_ugauss, INT64_C(5),
88 		       "(Z) expected %" PRIi64 " micro-gauss, got %" PRIi64 " micro-gauss",
89 		       expect_ugauss, actual_ugauss);
90 }
91 
ZTEST_F(akm09918c,test_fetch_magn)92 ZTEST_F(akm09918c, test_fetch_magn)
93 {
94 	/* Use (0.25, -0.33..., 0.91) as the factors */
95 	const int16_t magn_percent[3] = {
96 		INT16_C(AKM09918C_MAGN_MAX_DATA_REG) / INT16_C(4),
97 		INT16_C(AKM09918C_MAGN_MIN_DATA_REG) / INT16_C(3),
98 		(int16_t)(INT16_C(AKM09918C_MAGN_MAX_DATA_REG) * INT32_C(91) / INT32_C(100)),
99 	};
100 
101 	test_fetch_magnetic_field(fixture, magn_percent);
102 }
103