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