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 #else
31 #error Unsupported board
32 #endif
33
34 #define ACMP_DAC_VALUE 128
35
36 struct acmp_attr {
37 int16_t attr;
38 int32_t val;
39 };
40
41 static const struct acmp_attr attrs[] = {
42 #if MCUX_ACMP_HAS_INPSEL
43 /* Positive input port set to MUX */
44 { .attr = SENSOR_ATTR_MCUX_ACMP_POSITIVE_PORT_INPUT, .val = 1 },
45 #endif
46 /* Positive input channel */
47 { .attr = SENSOR_ATTR_MCUX_ACMP_POSITIVE_MUX_INPUT,
48 .val = ACMP_POSITIVE },
49 #if MCUX_ACMP_HAS_INNSEL
50 /* Negative input port set to DAC */
51 { .attr = SENSOR_ATTR_MCUX_ACMP_NEGATIVE_PORT_INPUT, .val = 0 },
52 #endif
53 /* Negative input channel */
54 { .attr = SENSOR_ATTR_MCUX_ACMP_NEGATIVE_MUX_INPUT,
55 .val = ACMP_NEGATIVE },
56 /* DAC voltage reference */
57 { .attr = SENSOR_ATTR_MCUX_ACMP_DAC_VOLTAGE_REFERENCE,
58 .val = ACMP_DAC_VREF },
59 /* DAC value */
60 { .attr = SENSOR_ATTR_MCUX_ACMP_DAC_VALUE, .val = ACMP_DAC_VALUE },
61 #if MCUX_ACMP_HAS_HYSTCTR
62 /* Hysteresis level */
63 { .attr = SENSOR_ATTR_MCUX_ACMP_HYSTERESIS_LEVEL, .val = 3 },
64 #endif
65 #if MCUX_ACMP_HAS_DISCRETE_MODE
66 /* Discrete mode */
67 { .attr = SENSOR_ATTR_MCUX_ACMP_POSITIVE_DISCRETE_MODE, .val = 1 },
68 #endif
69 #if MCUX_ACMP_HAS_OFFSET
70 /* Offset level */
71 { .attr = SENSOR_ATTR_MCUX_ACMP_OFFSET_LEVEL, .val = 0 },
72 #endif
73 };
74
75 static const int16_t triggers[] = {
76 SENSOR_TRIG_MCUX_ACMP_OUTPUT_RISING,
77 SENSOR_TRIG_MCUX_ACMP_OUTPUT_FALLING,
78 };
79
acmp_input_handler(bool above_threshold)80 static void acmp_input_handler(bool above_threshold)
81 {
82 if (above_threshold) {
83 printf("ACMP input above threshold\n");
84 } else {
85 printf("ACMP input below threshold\n");
86 }
87 }
88
acmp_trigger_handler(const struct device * dev,const struct sensor_trigger * trigger)89 static void acmp_trigger_handler(const struct device *dev,
90 const struct sensor_trigger *trigger)
91 {
92 ARG_UNUSED(dev);
93
94 acmp_input_handler((int16_t)trigger->type ==
95 SENSOR_TRIG_MCUX_ACMP_OUTPUT_RISING);
96 }
97
main(void)98 int main(void)
99 {
100 struct sensor_trigger trigger;
101 const struct device *const acmp = DEVICE_DT_GET(ACMP_NODE);
102 struct sensor_value val;
103 int err;
104 int i;
105
106 if (!device_is_ready(acmp)) {
107 printf("ACMP device not ready");
108 return 0;
109 }
110
111 /* Set ACMP attributes */
112 val.val2 = 0;
113 for (i = 0; i < ARRAY_SIZE(attrs); i++) {
114 val.val1 = attrs[i].val;
115 err = sensor_attr_set(acmp, SENSOR_CHAN_MCUX_ACMP_OUTPUT,
116 attrs[i].attr, &val);
117 if (err) {
118 printf("failed to set attribute %d (err %d)", i, err);
119 return 0;
120 }
121 }
122
123 /* Delay for analog components (DAC, CMP, ...) to settle */
124 k_sleep(K_MSEC(1));
125
126 /* Set ACMP triggers */
127 trigger.chan = SENSOR_CHAN_MCUX_ACMP_OUTPUT;
128 for (i = 0; i < ARRAY_SIZE(triggers); i++) {
129 trigger.type = triggers[i];
130 err = sensor_trigger_set(acmp, &trigger, acmp_trigger_handler);
131 if (err) {
132 printf("failed to set trigger %d (err %d)", i, err);
133 return 0;
134 }
135 }
136
137 printf("Adjust ACMP input voltage by turning the potentiometer\n");
138
139 /* Read initial state */
140 err = sensor_sample_fetch(acmp);
141 if (err) {
142 printf("failed to fetch sample (err %d)", err);
143 return 0;
144 }
145
146 err = sensor_channel_get(acmp, SENSOR_CHAN_MCUX_ACMP_OUTPUT, &val);
147 if (err) {
148 printf("failed to get channel (err %d)", err);
149 return 0;
150 }
151
152 acmp_input_handler(val.val1 == 1);
153
154 /* Await trigger */
155 while (true) {
156 k_sleep(K_MSEC(1));
157 }
158 return 0;
159 }
160