1 /*
2  * Copyright (c) 2022 Valerio Setti <valerio.setti@gmail.com>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/device.h>
9 #include <zephyr/drivers/sensor.h>
10 #include <zephyr/sys/printk.h>
11 
12 #define QUAD_ENC_EMUL_ENABLED \
13 	DT_NODE_EXISTS(DT_ALIAS(qenca)) && DT_NODE_EXISTS(DT_ALIAS(qencb))
14 
15 #if QUAD_ENC_EMUL_ENABLED
16 
17 #include <zephyr/drivers/gpio.h>
18 
19 #define QUAD_ENC_EMUL_PERIOD 100
20 
21 static const struct gpio_dt_spec phase_a =
22 			GPIO_DT_SPEC_GET(DT_ALIAS(qenca), gpios);
23 static const struct gpio_dt_spec phase_b =
24 			GPIO_DT_SPEC_GET(DT_ALIAS(qencb), gpios);
25 static bool toggle_a;
26 
qenc_emulate_work_handler(struct k_work * work)27 void qenc_emulate_work_handler(struct k_work *work)
28 {
29 	toggle_a = !toggle_a;
30 	if (toggle_a) {
31 		gpio_pin_toggle_dt(&phase_a);
32 	} else {
33 		gpio_pin_toggle_dt(&phase_b);
34 	}
35 }
36 
37 static K_WORK_DEFINE(qenc_emulate_work, qenc_emulate_work_handler);
38 
qenc_emulate_timer_handler(struct k_timer * dummy)39 static void qenc_emulate_timer_handler(struct k_timer *dummy)
40 {
41 	k_work_submit(&qenc_emulate_work);
42 }
43 
44 static K_TIMER_DEFINE(qenc_emulate_timer, qenc_emulate_timer_handler, NULL);
45 
qenc_emulate_init(void)46 static void qenc_emulate_init(void)
47 {
48 	printk("Quadrature encoder emulator enabled with %u ms period\n",
49 		QUAD_ENC_EMUL_PERIOD);
50 
51 	if (!gpio_is_ready_dt(&phase_a)) {
52 		printk("%s: device not ready.", phase_a.port->name);
53 		return;
54 	}
55 	gpio_pin_configure_dt(&phase_a, GPIO_OUTPUT);
56 
57 	if (!gpio_is_ready_dt(&phase_b)) {
58 		printk("%s: device not ready.", phase_b.port->name);
59 		return;
60 	}
61 	gpio_pin_configure_dt(&phase_b, GPIO_OUTPUT);
62 
63 	k_timer_start(&qenc_emulate_timer, K_MSEC(QUAD_ENC_EMUL_PERIOD / 2),
64 			K_MSEC(QUAD_ENC_EMUL_PERIOD / 2));
65 }
66 
67 #else
68 
qenc_emulate_init(void)69 static void qenc_emulate_init(void) { };
70 
71 #endif /* QUAD_ENC_EMUL_ENABLED */
72 
main(void)73 int main(void)
74 {
75 	struct sensor_value val;
76 	int rc;
77 	const struct device *const dev = DEVICE_DT_GET(DT_ALIAS(qdec0));
78 
79 	if (!device_is_ready(dev)) {
80 		printk("Qdec device is not ready\n");
81 		return 0;
82 	}
83 
84 	printk("Quadrature decoder sensor test\n");
85 
86 	qenc_emulate_init();
87 
88 #ifndef CONFIG_COVERAGE
89 	while (true) {
90 #else
91 	for (int i = 0; i < 3; i++) {
92 #endif
93 		/* sleep first to gather position from first period */
94 		k_msleep(1000);
95 
96 		rc = sensor_sample_fetch(dev);
97 		if (rc != 0) {
98 			printk("Failed to fetch sample (%d)\n", rc);
99 			return 0;
100 		}
101 
102 		rc = sensor_channel_get(dev, SENSOR_CHAN_ROTATION, &val);
103 		if (rc != 0) {
104 			printk("Failed to get data (%d)\n", rc);
105 			return 0;
106 		}
107 
108 		printk("Position = %d degrees\n", val.val1);
109 	}
110 	return 0;
111 }
112