1 /*
2  * Copyright (c) 2024, Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/ztest.h>
8 #include <zephyr/device.h>
9 #include <zephyr/drivers/sensor.h>
10 
11 static const struct device *temp_dev = DEVICE_DT_GET(DT_NODELABEL(temp_sensor));
12 static enum sensor_channel chan_to_use; /* this is filled by before() */
13 
14 static volatile bool trigger_handler_called;
15 
ZTEST(temp_sensor,test_polling)16 ZTEST(temp_sensor, test_polling)
17 {
18 	int rc;
19 	int cnt;
20 	struct sensor_value val;
21 
22 	cnt = 0;
23 	while (1) {
24 		int32_t temp_val;
25 
26 		rc = sensor_sample_fetch_chan(temp_dev, chan_to_use);
27 		zassert_ok(rc, "Cannot fetch chan sample: %d.", rc);
28 
29 		rc = sensor_channel_get(temp_dev, chan_to_use, &val);
30 		zassert_ok(rc, "Cannot read from channel %d: %d.",
31 			   chan_to_use, rc);
32 
33 		temp_val = (val.val1 * 100) + (val.val2 / 10000);
34 		TC_PRINT("Temperature: %d.%02u\n",
35 			temp_val/100, abs(temp_val) % 100);
36 
37 		zassert_true(val.val1 > 10, "Too cold");
38 		zassert_true(val.val1 < 35, "Too hot");
39 
40 		++cnt;
41 		if (cnt >= 5) {
42 			break;
43 		}
44 
45 		k_sleep(K_MSEC(500));
46 	}
47 }
48 
trigger_handler(const struct device * temp_dev,const struct sensor_trigger * trig)49 static void trigger_handler(const struct device *temp_dev,
50 			    const struct sensor_trigger *trig)
51 {
52 	ARG_UNUSED(temp_dev);
53 	ARG_UNUSED(trig);
54 
55 	trigger_handler_called = true;
56 }
57 
ZTEST(temp_sensor,test_trigger)58 ZTEST(temp_sensor, test_trigger)
59 {
60 	int rc;
61 	struct sensor_value val;
62 	struct sensor_trigger trig = { .type = SENSOR_TRIG_THRESHOLD,
63 				       .chan = chan_to_use };
64 
65 	/* Check if the sensor allows setting a threshold trigger.
66 	 * If not, skip the test.
67 	 */
68 	rc = sensor_trigger_set(temp_dev, &trig, NULL);
69 	if (rc == -ENOSYS || rc == -ENOTSUP) {
70 		TC_PRINT("This sensor does not support threshold trigger.\n");
71 		ztest_test_skip();
72 	}
73 
74 	rc = sensor_channel_get(temp_dev, chan_to_use, &val);
75 	zassert_ok(rc, "Cannot read from channel %d: %d.",
76 			chan_to_use, rc);
77 
78 	/* Set the upper threshold somewhat below the temperature read above. */
79 	val.val1 -= 5;
80 	rc = sensor_attr_set(temp_dev, chan_to_use,
81 			     SENSOR_ATTR_UPPER_THRESH, &val);
82 	zassert_ok(rc, "Cannot set upper threshold: %d.", rc);
83 
84 	/* And the lower threshold below the upper one. */
85 	val.val1 -= 1;
86 	rc = sensor_attr_set(temp_dev, chan_to_use,
87 			     SENSOR_ATTR_LOWER_THRESH, &val);
88 	zassert_ok(rc, "Cannot set lower threshold: %d.", rc);
89 
90 	/* Set sampling frequency to 10 Hz, to expect a trigger after 100 ms. */
91 	val.val1 = 10;
92 	val.val2 = 0;
93 	rc = sensor_attr_set(temp_dev, chan_to_use,
94 			     SENSOR_ATTR_SAMPLING_FREQUENCY, &val);
95 	zassert_ok(rc, "Cannot set sampling frequency: %d.", rc);
96 
97 	trigger_handler_called = false;
98 
99 	rc = sensor_trigger_set(temp_dev, &trig, trigger_handler);
100 	zassert_ok(rc, "Cannot enable the trigger: %d.", rc);
101 
102 	k_sleep(K_MSEC(300));
103 	zassert_true(trigger_handler_called);
104 
105 	rc = sensor_trigger_set(temp_dev, &trig, NULL);
106 	zassert_ok(rc, "Cannot disable the trigger: %d.", rc);
107 
108 	trigger_handler_called = false;
109 
110 	k_sleep(K_MSEC(300));
111 	zassert_false(trigger_handler_called);
112 }
113 
before(void * fixture)114 static void before(void *fixture)
115 {
116 	ARG_UNUSED(fixture);
117 
118 	int rc;
119 	int cnt;
120 	struct sensor_value val;
121 
122 	zassert_true(device_is_ready(temp_dev),
123 		"Device %s is not ready.", temp_dev->name);
124 
125 	cnt = 0;
126 	/* Try to fetch a sample to check if the sensor is ready to work.
127 	 * Try several times if it appears to be needing a while for some
128 	 * initialization of communication etc.
129 	 */
130 	while (1) {
131 		rc = sensor_sample_fetch(temp_dev);
132 		if (rc != -EAGAIN && rc != -ENOTCONN) {
133 			break;
134 		}
135 
136 		++cnt;
137 		zassert_false(cnt >= 3, "Cannot fetch a sample: %d.", rc);
138 
139 		k_sleep(K_MSEC(1000));
140 	}
141 	zassert_ok(rc, "Cannot fetch a sample: %d.", rc);
142 
143 	/* Check if the sensor provides the die temperature.
144 	 * If not, switch to the ambient one.
145 	 */
146 	chan_to_use = SENSOR_CHAN_DIE_TEMP;
147 	rc = sensor_channel_get(temp_dev, chan_to_use, &val);
148 	if (rc == -ENOTSUP) {
149 		chan_to_use = SENSOR_CHAN_AMBIENT_TEMP;
150 	}
151 }
152 
153 ZTEST_SUITE(temp_sensor, NULL, NULL, before, NULL, NULL);
154