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/kernel.h>
9 #include <zephyr/device.h>
10 #include <zephyr/drivers/sensor.h>
11 #include <zephyr/drivers/gpio.h>
12 #include <zephyr/pm/device_runtime.h>
13
14 static K_SEM_DEFINE(sem, 0, 1);
15 static const struct gpio_dt_spec phase_a = GPIO_DT_SPEC_GET(DT_ALIAS(qenca), gpios);
16 static const struct gpio_dt_spec phase_b = GPIO_DT_SPEC_GET(DT_ALIAS(qencb), gpios);
17 static const struct device *const qdec_dev = DEVICE_DT_GET(DT_ALIAS(qdec0));
18 static const uint32_t qdec_config_step = DT_PROP(DT_ALIAS(qdec0), steps);
19 static struct sensor_trigger qdec_trigger = {.type = SENSOR_TRIG_DATA_READY,
20 .chan = SENSOR_CHAN_ROTATION};
21 static bool toggle_a = true;
22
qdec_trigger_handler(const struct device * dev,const struct sensor_trigger * trigger)23 static void qdec_trigger_handler(const struct device *dev, const struct sensor_trigger *trigger)
24 {
25 zassert_not_null(dev);
26 zassert_not_null(trigger);
27 zassert_equal_ptr(dev, qdec_dev);
28 /* trigger should be stored as a pointer in a driver
29 * thus this address should match
30 */
31 zassert_equal_ptr(trigger, &qdec_trigger);
32
33 k_sem_give(&sem);
34 }
35
qenc_emulate_work_handler(struct k_work * work)36 static void qenc_emulate_work_handler(struct k_work *work)
37 {
38 if (toggle_a) {
39 gpio_pin_toggle_dt(&phase_a);
40 } else {
41 gpio_pin_toggle_dt(&phase_b);
42 }
43 toggle_a = !toggle_a;
44 }
45
46 static K_WORK_DEFINE(qenc_emulate_work, qenc_emulate_work_handler);
47
qenc_emulate_timer_handler(struct k_timer * dummy)48 static void qenc_emulate_timer_handler(struct k_timer *dummy)
49 {
50 k_work_submit(&qenc_emulate_work);
51 }
52
53 static K_TIMER_DEFINE(qenc_emulate_timer, qenc_emulate_timer_handler, NULL);
54
qenc_emulate_reset_pin(const struct gpio_dt_spec * gpio_dt)55 static void qenc_emulate_reset_pin(const struct gpio_dt_spec *gpio_dt)
56 {
57 int rc;
58
59 rc = gpio_pin_set_dt(gpio_dt, 0);
60 zassert_ok(rc, "%s: pin set failed: %d", gpio_dt->port->name, rc);
61 }
62
qenc_emulate_setup_pin(const struct gpio_dt_spec * gpio_dt)63 static void qenc_emulate_setup_pin(const struct gpio_dt_spec *gpio_dt)
64 {
65 int rc;
66
67 rc = gpio_is_ready_dt(gpio_dt);
68 zassert_true(rc, "%s: device not ready: %d", gpio_dt->port->name, rc);
69
70 rc = gpio_pin_configure_dt(gpio_dt, GPIO_OUTPUT);
71 zassert_true(rc == 0, "%s: pin configure failed: %d", gpio_dt->port->name, rc);
72 }
73
qenc_emulate_start(k_timeout_t period,bool forward)74 static void qenc_emulate_start(k_timeout_t period, bool forward)
75 {
76 qenc_emulate_reset_pin(&phase_a);
77 qenc_emulate_reset_pin(&phase_b);
78
79 toggle_a = !forward;
80
81 k_timer_start(&qenc_emulate_timer, period, period);
82 }
83
qenc_emulate_stop(void)84 static void qenc_emulate_stop(void)
85 {
86 k_timer_stop(&qenc_emulate_timer);
87
88 qenc_emulate_reset_pin(&phase_a);
89 qenc_emulate_reset_pin(&phase_b);
90 }
91
qenc_emulate_verify_reading(int emulator_period_ms,int emulation_duration_ms,bool forward,bool overflow_expected)92 static void qenc_emulate_verify_reading(int emulator_period_ms, int emulation_duration_ms,
93 bool forward, bool overflow_expected)
94 {
95 int rc;
96 struct sensor_value val = {0};
97 int32_t expected_steps = emulation_duration_ms / emulator_period_ms;
98 int32_t expected_reading = 360 * expected_steps / qdec_config_step;
99 int32_t delta = expected_reading / 5;
100
101 if (!forward) {
102 expected_reading *= -1;
103 }
104
105 qenc_emulate_start(K_MSEC(emulator_period_ms), forward);
106
107 /* wait for some readings*/
108 k_msleep(emulation_duration_ms);
109
110 rc = sensor_sample_fetch(qdec_dev);
111
112 if (!overflow_expected) {
113 zassert_true(rc == 0, "Failed to fetch sample (%d)", rc);
114 } else {
115 zassert_true(rc == -EOVERFLOW, "Failed to detect overflow");
116 }
117
118 rc = sensor_channel_get(qdec_dev, SENSOR_CHAN_ROTATION, &val);
119 zassert_true(rc == 0, "Failed to get sample (%d)", rc);
120
121 if (!overflow_expected) {
122 zassert_within(val.val1, expected_reading, delta,
123 "Expected reading: %d, but got: %d", expected_reading, val.val1);
124 }
125
126 qenc_emulate_stop();
127
128 /* wait and get readings to clear state */
129 k_msleep(100);
130
131 rc = sensor_sample_fetch(qdec_dev);
132 zassert_true(rc == 0, "Failed to fetch sample (%d)", rc);
133
134 rc = sensor_channel_get(qdec_dev, SENSOR_CHAN_ROTATION, &val);
135 zassert_true(rc == 0, "Failed to get sample (%d)", rc);
136 }
137
138 /**
139 * @brief sensor_trigger_set test disable trigger
140 *
141 * Confirm trigger happens after set and stops after being disabled
142 *
143 */
ZTEST(qdec_sensor,test_sensor_trigger_set_and_disable)144 ZTEST(qdec_sensor, test_sensor_trigger_set_and_disable)
145 {
146 int rc;
147
148 if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) {
149 pm_device_runtime_get(qdec_dev);
150 }
151
152 qdec_trigger.type = SENSOR_TRIG_DATA_READY;
153 qdec_trigger.chan = SENSOR_CHAN_ALL;
154 rc = sensor_trigger_set(qdec_dev, &qdec_trigger, qdec_trigger_handler);
155 zassume_true(rc != -ENOSYS, "sensor_trigger_set not supported");
156
157 zassert_true(rc == 0, "sensor_trigger_set failed: %d", rc);
158
159 qenc_emulate_start(K_MSEC(10), true);
160
161 /* emulation working, handler should be called */
162 rc = k_sem_take(&sem, K_MSEC(200));
163 zassert_true(rc == 0, "qdec handler should be triggered (%d)", rc);
164
165 qenc_emulate_stop();
166
167 /* emulation not working, but there maybe old trigger, ignore */
168 rc = k_sem_take(&sem, K_MSEC(200));
169
170 if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) {
171 pm_device_runtime_put(qdec_dev);
172 }
173
174 /* there should be no triggers now*/
175 rc = k_sem_take(&sem, K_MSEC(200));
176 zassert_true(rc == -EAGAIN, "qdec handler should not be triggered (%d)", rc);
177
178 if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) {
179 pm_device_runtime_get(qdec_dev);
180 }
181
182 /* register empty trigger - disable trigger */
183 rc = sensor_trigger_set(qdec_dev, &qdec_trigger, NULL);
184 zassert_true(rc == 0, "sensor_trigger_set failed: %d", rc);
185
186 qenc_emulate_start(K_MSEC(10), true);
187
188 /* emulation working, but handler not set, thus should not be called */
189 rc = k_sem_take(&sem, K_MSEC(200));
190 zassert_true(rc == -EAGAIN, "qdec handler should not be triggered (%d)", rc);
191
192 if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) {
193 pm_device_runtime_put(qdec_dev);
194 }
195 }
196
197 /**
198 * @brief sensor_trigger_set test
199 *
200 * Confirm trigger happens after set
201 *
202 */
ZTEST(qdec_sensor,test_sensor_trigger_set)203 ZTEST(qdec_sensor, test_sensor_trigger_set)
204 {
205 int rc;
206 struct sensor_value val = {0};
207
208 if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) {
209 pm_device_runtime_get(qdec_dev);
210 }
211
212 qdec_trigger.type = SENSOR_TRIG_DATA_READY;
213 qdec_trigger.chan = SENSOR_CHAN_ROTATION;
214 rc = sensor_trigger_set(qdec_dev, &qdec_trigger, qdec_trigger_handler);
215 zassume_true(rc != -ENOSYS, "sensor_trigger_set not supported");
216
217 zassert_true(rc == 0, "sensor_trigger_set failed: %d", rc);
218
219 qenc_emulate_start(K_MSEC(10), true);
220
221 /* emulation working now */
222 rc = k_sem_take(&sem, K_MSEC(200));
223 zassert_true(rc == 0, "qdec handler should be triggered (%d)", rc);
224
225 rc = sensor_sample_fetch(qdec_dev);
226 zassert_true(rc == 0, "Failed to fetch sample (%d)", rc);
227
228 rc = sensor_channel_get(qdec_dev, SENSOR_CHAN_ROTATION, &val);
229 zassert_true(rc == 0, "Failed to fetch sample (%d)", rc);
230
231 TC_PRINT("QDEC reading: %d\n", val.val1);
232 zassert_true(val.val1 != 0, "No readings from QDEC");
233
234 if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) {
235 pm_device_runtime_put(qdec_dev);
236 }
237 }
238
239 /**
240 * @brief sensor_trigger_set test negative
241 *
242 * Confirm setting trigger with invalid data does not work
243 *
244 */
ZTEST(qdec_sensor,test_sensor_trigger_set_negative)245 ZTEST(qdec_sensor, test_sensor_trigger_set_negative)
246 {
247 int rc;
248
249 if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) {
250 pm_device_runtime_get(qdec_dev);
251 }
252
253 rc = sensor_trigger_set(qdec_dev, &qdec_trigger, qdec_trigger_handler);
254 zassume_true(rc != -ENOSYS, "sensor_trigger_set not supported");
255
256 qdec_trigger.type = SENSOR_TRIG_MAX;
257 qdec_trigger.chan = SENSOR_CHAN_ROTATION;
258
259 rc = sensor_trigger_set(qdec_dev, &qdec_trigger, qdec_trigger_handler);
260 zassume_true(rc < 0, "sensor_trigger_set should fail due to invalid trigger type");
261
262 qdec_trigger.type = SENSOR_TRIG_DATA_READY;
263 qdec_trigger.chan = SENSOR_CHAN_MAX;
264
265 rc = sensor_trigger_set(qdec_dev, &qdec_trigger, qdec_trigger_handler);
266 zassume_true(rc < 0, "sensor_trigger_set should fail due to invalid channel");
267
268 if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) {
269 pm_device_runtime_put(qdec_dev);
270 }
271 }
272
273 /**
274 * @brief QDEC readings tests
275 *
276 * Valid reading from QDEC base on simulated signal
277 *
278 */
ZTEST(qdec_sensor,test_qdec_readings)279 ZTEST(qdec_sensor, test_qdec_readings)
280 {
281 if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) {
282 pm_device_runtime_get(qdec_dev);
283 }
284
285 qenc_emulate_verify_reading(10, 100, true, false);
286 qenc_emulate_verify_reading(2, 500, true, false);
287 qenc_emulate_verify_reading(10, 200, false, false);
288 qenc_emulate_verify_reading(1, 1000, false, true);
289 qenc_emulate_verify_reading(1, 1000, true, true);
290
291 if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) {
292 pm_device_runtime_put(qdec_dev);
293 }
294 }
295
296 /**
297 * @brief sensor_channel_get test with no emulation
298 *
299 * Confirm getting empty reading from QDEC
300 *
301 */
ZTEST(qdec_sensor,test_sensor_channel_get_empty)302 ZTEST(qdec_sensor, test_sensor_channel_get_empty)
303 {
304 int rc;
305 struct sensor_value val = {0};
306
307 if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) {
308 pm_device_runtime_get(qdec_dev);
309 }
310
311 /* wait for potential new readings */
312 k_msleep(100);
313
314 rc = sensor_sample_fetch(qdec_dev);
315 zassert_true(rc == 0, "Failed to fetch sample (%d)", rc);
316
317 /* get readings but ignore them, as they may include reading from time
318 * when emulation was still working (i.e. during previous test)
319 */
320 rc = sensor_channel_get(qdec_dev, SENSOR_CHAN_ROTATION, &val);
321 zassert_true(rc == 0, "Failed to get sample (%d)", rc);
322
323 /* wait for potential new readings */
324 k_msleep(100);
325
326 rc = sensor_sample_fetch(qdec_dev);
327 zassert_true(rc == 0, "Failed to fetch sample (%d)", rc);
328
329 /* emulation was not working, expect no readings */
330 rc = sensor_channel_get(qdec_dev, SENSOR_CHAN_ROTATION, &val);
331 zassert_true(rc == 0, "Failed to get sample (%d)", rc);
332 zassert_true(val.val1 == 0, "Expected no readings but got: %d", val.val1);
333 zassert_true(val.val2 == 0, "Expected no readings but got: %d", val.val2);
334
335 if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) {
336 pm_device_runtime_put(qdec_dev);
337 }
338 }
339
340 /**
341 * @brief sensor_channel_get test with emulation
342 *
343 * Confirm getting readings from QDEC
344 *
345 */
ZTEST(qdec_sensor,test_sensor_channel_get)346 ZTEST(qdec_sensor, test_sensor_channel_get)
347 {
348 int rc;
349 struct sensor_value val_first = {0};
350 struct sensor_value val_second = {0};
351
352 if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) {
353 pm_device_runtime_get(qdec_dev);
354 }
355
356 qenc_emulate_start(K_MSEC(10), true);
357
358 /* wait for some readings*/
359 k_msleep(100);
360
361 rc = sensor_sample_fetch(qdec_dev);
362 zassert_true(rc == 0, "Failed to fetch sample (%d)", rc);
363
364 rc = sensor_channel_get(qdec_dev, SENSOR_CHAN_ROTATION, &val_first);
365 zassert_true(rc == 0, "Failed to get sample (%d)", rc);
366 zassert_true(val_first.val1 != 0, "No readings from QDEC");
367
368 /* wait for more readings*/
369 k_msleep(200);
370
371 rc = sensor_channel_get(qdec_dev, SENSOR_CHAN_ROTATION, &val_second);
372 zassert_true(rc == 0, "Failed to fetch sample (%d)", rc);
373 zassert_true(val_second.val1 != 0, "No readings from QDEC");
374
375 /* subsequent calls of sensor_channel_get without calling sensor_sample_fetch
376 * should yield the same value
377 */
378 zassert_true(val_first.val1 == val_second.val1,
379 "Expected the same readings: %d vs %d",
380 val_first.val1,
381 val_second.val1);
382
383 zassert_true(val_first.val2 == val_second.val2,
384 "Expected the same readings: %d vs %d",
385 val_first.val2,
386 val_second.val2);
387
388 if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) {
389 pm_device_runtime_put(qdec_dev);
390 }
391 }
392
393 /**
394 * @brief sensor_channel_get test negative
395 *
396 * Confirm getting readings from QDEC with invalid channel
397 *
398 */
ZTEST(qdec_sensor,test_sensor_channel_get_negative)399 ZTEST(qdec_sensor, test_sensor_channel_get_negative)
400 {
401 int rc;
402 struct sensor_value val = {0};
403
404 if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) {
405 pm_device_runtime_get(qdec_dev);
406 }
407
408 qenc_emulate_start(K_MSEC(10), true);
409
410 /* wait for some readings*/
411 k_msleep(100);
412
413 rc = sensor_sample_fetch(qdec_dev);
414 zassert_true(rc == 0, "Failed to fetch sample (%d)", rc);
415
416 rc = sensor_channel_get(qdec_dev, SENSOR_CHAN_MAX, &val);
417 zassert_true(rc < 0, "Should failed to get sample (%d)", rc);
418 zassert_true(val.val1 == 0, "Some readings from QDEC: %d", val.val1);
419 zassert_true(val.val2 == 0, "Some readings from QDEC: %d", val.val2);
420
421 if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) {
422 pm_device_runtime_put(qdec_dev);
423 }
424 }
425
426 /**
427 * @brief sensor_sample_fetch(_chan) test
428 *
429 * Confirm fetching work with QDEC specific channel - rotation
430 *
431 */
ZTEST(qdec_sensor,test_sensor_sample_fetch)432 ZTEST(qdec_sensor, test_sensor_sample_fetch)
433 {
434 int rc;
435
436 if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) {
437 pm_device_runtime_get(qdec_dev);
438 }
439
440 rc = sensor_sample_fetch(qdec_dev);
441 zassert_true(rc == 0, "Failed to fetch sample (%d)", rc);
442
443 rc = sensor_sample_fetch_chan(qdec_dev, SENSOR_CHAN_ROTATION);
444 zassert_true(rc == 0, "Failed to fetch sample (%d)", rc);
445
446 rc = sensor_sample_fetch_chan(qdec_dev, SENSOR_CHAN_MAX);
447 zassert_true(rc < 0, "Should fail to fetch sample from invalid channel (%d)", rc);
448
449 if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) {
450 pm_device_runtime_put(qdec_dev);
451 }
452 }
453
setup(void)454 static void *setup(void)
455 {
456 int rc;
457
458 rc = device_is_ready(qdec_dev);
459 zassert_true(rc, "QDEC device not ready: %d", rc);
460
461 qenc_emulate_setup_pin(&phase_a);
462 qenc_emulate_setup_pin(&phase_b);
463
464 return NULL;
465 }
466
before(void * fixture)467 static void before(void *fixture)
468 {
469 ARG_UNUSED(fixture);
470
471 qenc_emulate_stop();
472 }
473
after(void * fixture)474 static void after(void *fixture)
475 {
476 ARG_UNUSED(fixture);
477
478 qenc_emulate_stop();
479 }
480
481 ZTEST_SUITE(qdec_sensor, NULL, setup, before, after, NULL);
482