1 /*
2 * Copyright (c) 2020 Vestas Wind Systems A/S
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/device.h>
8 #include <zephyr/drivers/sensor.h>
9 #include <zephyr/drivers/sensor/mcux_acmp.h>
10 #include <zephyr/kernel.h>
11
12 #include <stdio.h>
13
14 #ifdef CONFIG_BOARD_TWR_KE18F
15 #define ACMP_NODE DT_NODELABEL(cmp2)
16 #define ACMP_POSITIVE 5
17 #define ACMP_NEGATIVE 5
18 #define ACMP_DAC_VREF 0
19 #elif (defined(CONFIG_BOARD_MIMXRT1170_EVK) || defined(CONFIG_BOARD_MIMXRT1180_EVK))
20 #define ACMP_NODE DT_NODELABEL(acmp1)
21 #define ACMP_POSITIVE 2
22 #define ACMP_NEGATIVE 7
23 /* Select Vin2. Vin1 is not used and tied to ground on this chip. Vin2 is from VDDA_1P8_IN. */
24 #define ACMP_DAC_VREF 1
25 #elif (defined(CONFIG_BOARD_FRDM_KE17Z) || defined(CONFIG_BOARD_FRDM_KE17Z512))
26 #define ACMP_NODE DT_NODELABEL(cmp0)
27 #define ACMP_POSITIVE 4
28 #define ACMP_NEGATIVE 4
29 #define ACMP_DAC_VREF 0
30 #elif (defined(CONFIG_BOARD_MIMXRT700_EVK))
31 #define ACMP_NODE DT_NODELABEL(acmp)
32 #define ACMP_POSITIVE 1
33 #define ACMP_NEGATIVE 7
34 #define ACMP_DAC_VREF 1
35 #else
36 #error Unsupported board
37 #endif
38
39 #define ACMP_DAC_VALUE 128
40
41 struct acmp_attr {
42 int16_t attr;
43 int32_t val;
44 };
45
46 static const struct acmp_attr attrs[] = {
47 #if MCUX_ACMP_HAS_INPSEL
48 /* Positive input port set to MUX */
49 { .attr = SENSOR_ATTR_MCUX_ACMP_POSITIVE_PORT_INPUT, .val = 1 },
50 #endif
51 /* Positive input channel */
52 { .attr = SENSOR_ATTR_MCUX_ACMP_POSITIVE_MUX_INPUT,
53 .val = ACMP_POSITIVE },
54 #if MCUX_ACMP_HAS_INNSEL
55 /* Negative input port set to DAC */
56 { .attr = SENSOR_ATTR_MCUX_ACMP_NEGATIVE_PORT_INPUT, .val = 0 },
57 #endif
58 /* Negative input channel */
59 { .attr = SENSOR_ATTR_MCUX_ACMP_NEGATIVE_MUX_INPUT,
60 .val = ACMP_NEGATIVE },
61 /* DAC voltage reference */
62 { .attr = SENSOR_ATTR_MCUX_ACMP_DAC_VOLTAGE_REFERENCE,
63 .val = ACMP_DAC_VREF },
64 /* DAC value */
65 { .attr = SENSOR_ATTR_MCUX_ACMP_DAC_VALUE, .val = ACMP_DAC_VALUE },
66 #if MCUX_ACMP_HAS_HYSTCTR
67 /* Hysteresis level */
68 { .attr = SENSOR_ATTR_MCUX_ACMP_HYSTERESIS_LEVEL, .val = 3 },
69 #endif
70 #if MCUX_ACMP_HAS_DISCRETE_MODE
71 /* Discrete mode */
72 { .attr = SENSOR_ATTR_MCUX_ACMP_POSITIVE_DISCRETE_MODE, .val = 1 },
73 #endif
74 #if MCUX_ACMP_HAS_OFFSET
75 /* Offset level */
76 { .attr = SENSOR_ATTR_MCUX_ACMP_OFFSET_LEVEL, .val = 0 },
77 #endif
78 };
79
80 static const int16_t triggers[] = {
81 SENSOR_TRIG_MCUX_ACMP_OUTPUT_RISING,
82 SENSOR_TRIG_MCUX_ACMP_OUTPUT_FALLING,
83 };
84
acmp_input_handler(bool above_threshold)85 static void acmp_input_handler(bool above_threshold)
86 {
87 if (above_threshold) {
88 printf("ACMP input above threshold\n");
89 } else {
90 printf("ACMP input below threshold\n");
91 }
92 }
93
acmp_trigger_handler(const struct device * dev,const struct sensor_trigger * trigger)94 static void acmp_trigger_handler(const struct device *dev,
95 const struct sensor_trigger *trigger)
96 {
97 ARG_UNUSED(dev);
98
99 acmp_input_handler((int16_t)trigger->type ==
100 SENSOR_TRIG_MCUX_ACMP_OUTPUT_RISING);
101 }
102
main(void)103 int main(void)
104 {
105 struct sensor_trigger trigger[ARRAY_SIZE(triggers)] = {
106 [0] = {
107 .chan = SENSOR_CHAN_MCUX_ACMP_OUTPUT,
108 .type = triggers[0],
109 },
110 [1] = {
111 .chan = SENSOR_CHAN_MCUX_ACMP_OUTPUT,
112 .type = triggers[1],
113 }};
114
115 const struct device *const acmp = DEVICE_DT_GET(ACMP_NODE);
116 struct sensor_value val;
117 int err;
118 int i;
119
120 if (!device_is_ready(acmp)) {
121 printf("ACMP device not ready");
122 return 0;
123 }
124
125 /* Set ACMP attributes */
126 val.val2 = 0;
127 for (i = 0; i < ARRAY_SIZE(attrs); i++) {
128 val.val1 = attrs[i].val;
129 err = sensor_attr_set(acmp, SENSOR_CHAN_MCUX_ACMP_OUTPUT,
130 attrs[i].attr, &val);
131 if (err) {
132 printf("failed to set attribute %d (err %d)", i, err);
133 return 0;
134 }
135 }
136
137 /* Delay for analog components (DAC, CMP, ...) to settle */
138 k_sleep(K_MSEC(1));
139
140 /* Set ACMP triggers */
141 for (i = 0; i < ARRAY_SIZE(triggers); i++) {
142 err = sensor_trigger_set(acmp, &trigger[i], acmp_trigger_handler);
143 if (err) {
144 printf("failed to set trigger %d (err %d)", i, err);
145 return 0;
146 }
147 }
148
149 printf("Adjust ACMP input voltage by turning the potentiometer\n");
150
151 /* Read initial state */
152 err = sensor_sample_fetch(acmp);
153 if (err) {
154 printf("failed to fetch sample (err %d)", err);
155 return 0;
156 }
157
158 err = sensor_channel_get(acmp, SENSOR_CHAN_MCUX_ACMP_OUTPUT, &val);
159 if (err) {
160 printf("failed to get channel (err %d)", err);
161 return 0;
162 }
163
164 acmp_input_handler(val.val1 == 1);
165
166 /* Await trigger */
167 while (true) {
168 k_sleep(K_MSEC(1));
169 }
170 return 0;
171 }
172