1 /*
2  * Copyright (c) 2020 Vestas Wind Systems A/S
3  * Copyright NXP 2024
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <zephyr/device.h>
9 #include <zephyr/drivers/sensor.h>
10 #include <zephyr/drivers/sensor/mcux_lpcmp.h>
11 #include <zephyr/kernel.h>
12 #include <stdio.h>
13 
14 struct lpcmp_attr {
15 	int16_t attr;
16 	int32_t val;
17 };
18 
19 static const struct lpcmp_attr attrs[] = {
20 	{.attr = SENSOR_ATTR_MCUX_LPCMP_POSITIVE_MUX_INPUT, .val = 0},
21 	{.attr = SENSOR_ATTR_MCUX_LPCMP_NEGATIVE_MUX_INPUT, .val = 7},
22 
23 	{.attr = SENSOR_ATTR_MCUX_LPCMP_DAC_ENABLE, .val = 1},
24 	{.attr = SENSOR_ATTR_MCUX_LPCMP_DAC_HIGH_POWER_MODE_ENABLE, .val = 0},
25 	{.attr = SENSOR_ATTR_MCUX_LPCMP_DAC_REFERENCE_VOLTAGE_SOURCE, .val = 0},
26 	{.attr = SENSOR_ATTR_MCUX_LPCMP_DAC_OUTPUT_VOLTAGE, .val = (0xFF >> 1)},
27 
28 	{.attr = SENSOR_ATTR_MCUX_LPCMP_SAMPLE_ENABLE, .val = 0},
29 	{.attr = SENSOR_ATTR_MCUX_LPCMP_FILTER_COUNT, .val = 7},
30 	{.attr = SENSOR_ATTR_MCUX_LPCMP_FILTER_PERIOD, .val = (0xFF >> 1)},
31 
32 	{.attr = SENSOR_ATTR_MCUX_LPCMP_COUTA_WINDOW_ENABLE, .val = 0},
33 	{.attr = SENSOR_ATTR_MCUX_LPCMP_COUTA_WINDOW_SIGNAL_INVERT_ENABLE, .val = 0},
34 	{.attr = SENSOR_ATTR_MCUX_LPCMP_COUTA_SIGNAL, .val = 0},
35 	{.attr = SENSOR_ATTR_MCUX_LPCMP_COUT_EVENT_TO_CLOSE_WINDOW, .val = 0},
36 };
37 
38 #ifdef CONFIG_MCUX_LPCMP_TRIGGER
39 static const int16_t triggers[] = {
40 	SENSOR_TRIG_MCUX_LPCMP_OUTPUT_RISING,
41 	SENSOR_TRIG_MCUX_LPCMP_OUTPUT_FALLING,
42 };
43 #endif /* CONFIG_MCUX_LPCMP_TRIGGER */
44 
lpcmp_input_handler(bool above_threshold)45 static void lpcmp_input_handler(bool above_threshold)
46 {
47 	if (above_threshold) {
48 		printf("LPCMP input above threshold\n");
49 	} else {
50 		printf("LPCMP input below threshold\n");
51 	}
52 }
53 
54 #ifdef CONFIG_MCUX_LPCMP_TRIGGER
lpcmp_trigger_handler(const struct device * dev,const struct sensor_trigger * trigger)55 static void lpcmp_trigger_handler(const struct device *dev, const struct sensor_trigger *trigger)
56 {
57 	ARG_UNUSED(dev);
58 
59 	lpcmp_input_handler((int16_t)trigger->type == SENSOR_TRIG_MCUX_LPCMP_OUTPUT_RISING);
60 }
61 #endif /* CONFIG_MCUX_LPCMP_TRIGGER */
62 
main(void)63 int main(void)
64 {
65 #ifdef CONFIG_MCUX_LPCMP_TRIGGER
66 	struct sensor_trigger trigger[ARRAY_SIZE(triggers)] = {
67 		[0] = {
68 				.chan = SENSOR_CHAN_MCUX_LPCMP_OUTPUT,
69 				.type = triggers[0],
70 			},
71 		[1] = {
72 				.chan = SENSOR_CHAN_MCUX_LPCMP_OUTPUT,
73 				.type = triggers[1],
74 			}
75 		};
76 #endif /* CONFIG_MCUX_LPCMP_TRIGGER */
77 	const struct device *const lpcmp = DEVICE_DT_GET(DT_NODELABEL(lpcmp0));
78 	struct sensor_value val;
79 	int err;
80 
81 	if (!device_is_ready(lpcmp)) {
82 		printf("LPCMP device not ready\n");
83 		return 0;
84 	}
85 
86 	/* Set LPCMP attributes */
87 	val.val2 = 0;
88 	for (uint8_t i = 0; i < ARRAY_SIZE(attrs); i++) {
89 		val.val1 = attrs[i].val;
90 		err = sensor_attr_set(lpcmp, SENSOR_CHAN_MCUX_LPCMP_OUTPUT, attrs[i].attr, &val);
91 		if (err) {
92 			printf("failed to set attribute %d (err %d)\n", i, err);
93 			return 0;
94 		}
95 	}
96 
97 	/* Delay for analog components (DAC, CMP, ...) to settle */
98 	k_sleep(K_MSEC(1));
99 
100 #ifdef CONFIG_MCUX_LPCMP_TRIGGER
101 	/* Set LPCMP triggers */
102 	for (uint8_t i = 0; i < ARRAY_SIZE(triggers); i++) {
103 		err = sensor_trigger_set(lpcmp, &trigger[i], lpcmp_trigger_handler);
104 		if (err) {
105 			printf("failed to set trigger %d (err %d)\n", i, err);
106 			return 0;
107 		}
108 	}
109 
110 	/* Await trigger */
111 	while (true) {
112 		k_sleep(K_MSEC(1));
113 	}
114 #else  /* !CONFIG_MCUX_LPCMP_TRIGGER */
115 	err = sensor_sample_fetch(lpcmp);
116 	if (err) {
117 		printf("failed to fetch sample (err %d)\n", err);
118 		return 0;
119 	}
120 
121 	err = sensor_channel_get(lpcmp, SENSOR_CHAN_MCUX_LPCMP_OUTPUT, &val);
122 	if (err) {
123 		printf("failed to get channel (err %d)\n", err);
124 		return 0;
125 	}
126 
127 	lpcmp_input_handler(val.val1 == 1);
128 #endif /* CONFIG_MCUX_LPCMP_TRIGGER */
129 
130 	return 0;
131 }
132