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/drivers/comparator/nrf_comp.h>
9 #include <zephyr/drivers/gpio.h>
10 #include <zephyr/kernel.h>
11 
12 static const struct device *test_dev = DEVICE_DT_GET(DT_ALIAS(test_comp));
13 static const struct gpio_dt_spec test_pin_1 = GPIO_DT_SPEC_GET(DT_PATH(zephyr_user), first_gpios);
14 static const struct gpio_dt_spec test_pin_2 = GPIO_DT_SPEC_GET(DT_PATH(zephyr_user), second_gpios);
15 
16 #define TEST_COMP_SE_PSEL_AIN _CONCAT(COMP_NRF_COMP_PSEL_AIN, \
17 				      CONFIG_TEST_COMP_SE_PSEL_AIN_INDEX)
18 #define TEST_COMP_SE_EXTREFSEL_AIN _CONCAT(COMP_NRF_COMP_EXTREFSEL_AIN, \
19 					   CONFIG_TEST_COMP_SE_EXTREFSEL_AIN_INDEX)
20 #define TEST_COMP_DIFF_PSEL_AIN _CONCAT(COMP_NRF_COMP_PSEL_AIN, \
21 					CONFIG_TEST_COMP_DIFF_PSEL_AIN_INDEX)
22 #define TEST_COMP_DIFF_EXTREFSEL_AIN _CONCAT(COMP_NRF_COMP_EXTREFSEL_AIN, \
23 					     CONFIG_TEST_COMP_DIFF_EXTREFSEL_AIN_INDEX)
24 
25 struct comp_nrf_comp_se_config comp_se_config = {
26 	.psel = TEST_COMP_SE_PSEL_AIN,
27 	.sp_mode = COMP_NRF_COMP_SP_MODE_HIGH,
28 	.isource = COMP_NRF_COMP_ISOURCE_DISABLED,
29 	.refsel = COMP_NRF_COMP_REFSEL_AREF,
30 	.extrefsel = TEST_COMP_SE_EXTREFSEL_AIN,
31 	.th_up = 32,
32 	.th_down = 32,
33 };
34 
35 struct comp_nrf_comp_diff_config comp_diff_config = {
36 	.psel = TEST_COMP_DIFF_PSEL_AIN,
37 	.sp_mode = COMP_NRF_COMP_SP_MODE_LOW,
38 	.isource = COMP_NRF_COMP_ISOURCE_DISABLED,
39 	.extrefsel = TEST_COMP_DIFF_EXTREFSEL_AIN,
40 	.enable_hyst = true,
41 };
42 
43 atomic_t counter;
44 
test_callback(const struct device * dev,void * user_data)45 static void test_callback(const struct device *dev, void *user_data)
46 {
47 	counter++;
48 }
49 
50 /**
51  * @brief Configure comparator in single-ended mode with
52  * external voltage reference.
53  * Check if events were detected.
54  */
55 
ZTEST(comparator_runtime_configure,test_comp_config_se_aref)56 ZTEST(comparator_runtime_configure, test_comp_config_se_aref)
57 {
58 	int rc;
59 
60 	rc = comp_nrf_comp_configure_se(test_dev, &comp_se_config);
61 	zassert_equal(rc, 0, "Cannot configure comparator.");
62 
63 	rc = comparator_set_trigger_callback(test_dev, test_callback, NULL);
64 	zassert_equal(rc, 0, "Cannot set callback for comparator.");
65 
66 	rc = comparator_set_trigger(test_dev, COMPARATOR_TRIGGER_BOTH_EDGES);
67 	zassert_equal(rc, 0, "Cannot set trigger for comparator.");
68 
69 	k_msleep(10);
70 
71 	atomic_clear(&counter);
72 	gpio_pin_set_dt(&test_pin_2, 1);
73 	k_msleep(10);
74 	zassert_equal(atomic_get(&counter), 1, "COMP was not triggered for first threshold cross");
75 	gpio_pin_set_dt(&test_pin_2, 0);
76 	k_msleep(10);
77 	zassert_equal(atomic_get(&counter), 2, "COMP was not triggered for second threshold cross");
78 
79 }
80 
81 /**
82  * @brief Configure comparator in single-ended mode with
83  * internal voltage reference.
84  * Check if events were detected.
85  */
86 
87 
ZTEST(comparator_runtime_configure,test_comp_config_se_vdd)88 ZTEST(comparator_runtime_configure, test_comp_config_se_vdd)
89 {
90 	int rc;
91 
92 	struct comp_nrf_comp_se_config conf = comp_se_config;
93 
94 #ifdef COMP_REFSEL_REFSEL_AVDDAO1V8
95 	conf.refsel = COMP_NRF_COMP_REFSEL_AVDDAO1V8;
96 #elif defined(COMP_REFSEL_REFSEL_VDD)
97 	conf.refsel = COMP_NRF_COMP_REFSEL_VDD;
98 #else
99 	/* Use internal 1.2 V derived from VDD */
100 	conf.refsel = COMP_NRF_COMP_REFSEL_INT_1V2;
101 #endif
102 	rc = comp_nrf_comp_configure_se(test_dev, &conf);
103 	zassert_equal(rc, 0, "Cannot configure comparator.");
104 
105 	rc = comparator_set_trigger_callback(test_dev, test_callback, NULL);
106 	zassert_equal(rc, 0, "Cannot set callback for comparator.");
107 
108 	rc = comparator_set_trigger(test_dev, COMPARATOR_TRIGGER_BOTH_EDGES);
109 	zassert_equal(rc, 0, "Cannot set trigger for comparator.");
110 
111 	k_msleep(10);
112 
113 	atomic_clear(&counter);
114 	gpio_pin_set_dt(&test_pin_2, 1);
115 	k_msleep(10);
116 	zassert_equal(atomic_get(&counter), 1, "COMP was not triggered for first threshold cross");
117 	gpio_pin_set_dt(&test_pin_2, 0);
118 	k_msleep(10);
119 	zassert_equal(atomic_get(&counter), 2, "COMP was not triggered for second threshold cross");
120 
121 }
122 
123 /**
124  * @brief Configure comparator in differential mode
125  * Check if events were detected.
126  */
127 
ZTEST(comparator_runtime_configure,test_comp_config_diff_both)128 ZTEST(comparator_runtime_configure, test_comp_config_diff_both)
129 {
130 	int rc;
131 
132 	gpio_pin_set_dt(&test_pin_1, 1);
133 	gpio_pin_set_dt(&test_pin_2, 0);
134 	comparator_trigger_is_pending(test_dev);
135 
136 	atomic_clear(&counter);
137 	struct comp_nrf_comp_diff_config config = comp_diff_config;
138 
139 	config.isource = COMP_NRF_COMP_ISOURCE_2UA5;
140 	rc = comp_nrf_comp_configure_diff(test_dev, &config);
141 	zassert_equal(rc, 0, "Cannot configure comparator.");
142 
143 	rc = comparator_set_trigger_callback(test_dev, test_callback, NULL);
144 	zassert_equal(rc, 0, "Cannot set callback for comparator.");
145 
146 	rc = comparator_set_trigger(test_dev, COMPARATOR_TRIGGER_BOTH_EDGES);
147 	zassert_equal(rc, 0, "Cannot set trigger for comparator.");
148 	k_msleep(10);
149 
150 	atomic_clear(&counter);
151 	gpio_pin_set_dt(&test_pin_1, 0);
152 	gpio_pin_set_dt(&test_pin_2, 1);
153 	k_msleep(10);
154 	zassert_equal(atomic_get(&counter), 1, "COMP was not triggered for first threshold cross");
155 
156 	gpio_pin_set_dt(&test_pin_2, 0);
157 	gpio_pin_set_dt(&test_pin_1, 1);
158 	k_msleep(10);
159 
160 	zassert_equal(atomic_get(&counter), 2, "COMP was not triggered for second threshold cross");
161 }
162 
163 /**
164  * @brief Configure comparator in differential mode
165  * trigger both edges, event should be detected for falling one
166  */
167 
ZTEST(comparator_runtime_configure,test_comp_config_diff_falling)168 ZTEST(comparator_runtime_configure, test_comp_config_diff_falling)
169 {
170 	int rc;
171 
172 	gpio_pin_set_dt(&test_pin_1, 0);
173 	gpio_pin_set_dt(&test_pin_2, 1);
174 	comparator_trigger_is_pending(test_dev);
175 
176 	atomic_clear(&counter);
177 	struct comp_nrf_comp_diff_config config = comp_diff_config;
178 
179 	config.isource = COMP_NRF_COMP_ISOURCE_5UA;
180 	rc = comp_nrf_comp_configure_diff(test_dev, &config);
181 
182 	zassert_equal(rc,  0, "Cannot configure comparator.");
183 
184 	rc = comparator_set_trigger_callback(test_dev, test_callback, NULL);
185 	zassert_equal(rc, 0, "Cannot set callback for comparator.");
186 
187 	rc = comparator_set_trigger(test_dev, COMPARATOR_TRIGGER_FALLING_EDGE);
188 	zassert_equal(rc, 0, "Cannot set trigger for comparator.");
189 
190 	atomic_clear(&counter);
191 	gpio_pin_set_dt(&test_pin_1, 1);
192 	gpio_pin_set_dt(&test_pin_2, 0);
193 	k_msleep(10);
194 
195 	zassert_equal(counter, 0, "COMP was triggered for rising threshold cross");
196 
197 	gpio_pin_set_dt(&test_pin_1, 0);
198 	gpio_pin_set_dt(&test_pin_2, 1);
199 	k_msleep(10);
200 
201 	zassert_equal(atomic_get(&counter), 1, "COMP wasn't triggered for falling threshold cross");
202 }
203 
204 /**
205  * @brief Configure comparator in differential mode
206  * trigger both edges, event should be detected for rising one
207  */
208 
ZTEST(comparator_runtime_configure,test_comp_config_diff_rising)209 ZTEST(comparator_runtime_configure, test_comp_config_diff_rising)
210 {
211 	int rc;
212 
213 	gpio_pin_set_dt(&test_pin_1, 1);
214 	gpio_pin_set_dt(&test_pin_2, 0);
215 	comparator_trigger_is_pending(test_dev);
216 
217 	atomic_clear(&counter);
218 	struct comp_nrf_comp_diff_config config = comp_diff_config;
219 
220 	config.isource = COMP_NRF_COMP_ISOURCE_10UA;
221 	rc = comp_nrf_comp_configure_diff(test_dev, &config);
222 	zassert_equal(rc, 0, "Cannot configure comparator.");
223 
224 	rc = comparator_set_trigger_callback(test_dev, test_callback, NULL);
225 	zassert_equal(rc, 0, "Cannot set callback for comparator.");
226 
227 	rc = comparator_set_trigger(test_dev, COMPARATOR_TRIGGER_RISING_EDGE);
228 	zassert_equal(rc, 0, "Cannot set trigger for comparator.");
229 
230 	atomic_clear(&counter);
231 	gpio_pin_set_dt(&test_pin_1, 0);
232 	gpio_pin_set_dt(&test_pin_2, 1);
233 	k_msleep(10);
234 
235 	zassert_equal(atomic_get(&counter), 0, "COMP was triggered for falling threshold cross");
236 
237 	gpio_pin_set_dt(&test_pin_1, 1);
238 	gpio_pin_set_dt(&test_pin_2, 0);
239 	k_msleep(10);
240 
241 	zassert_equal(atomic_get(&counter), 1, "COMP was not triggered for rising threshold cross");
242 }
243 
244 /**
245  * @brief Configure comparator in differential mode
246  * trigger both edges, event should not be detected.
247  */
248 
ZTEST(comparator_runtime_configure,test_comp_config_diff_none)249 ZTEST(comparator_runtime_configure, test_comp_config_diff_none)
250 {
251 	int rc;
252 
253 	gpio_pin_set_dt(&test_pin_1, 1);
254 	gpio_pin_set_dt(&test_pin_2, 0);
255 	comparator_trigger_is_pending(test_dev);
256 
257 	atomic_clear(&counter);
258 	struct comp_nrf_comp_diff_config config = comp_diff_config;
259 
260 	config.isource = COMP_NRF_COMP_ISOURCE_10UA;
261 	rc = comp_nrf_comp_configure_diff(test_dev, &config);
262 	zassert_equal(rc, 0, "Cannot configure comparator.");
263 
264 	rc = comparator_set_trigger_callback(test_dev, test_callback, NULL);
265 	zassert_equal(rc, 0, "Cannot set callback for comparator.");
266 
267 	rc = comparator_set_trigger(test_dev, COMPARATOR_TRIGGER_NONE);
268 	zassert_equal(rc, 0, "Cannot set trigger for comparator.");
269 
270 	atomic_clear(&counter);
271 	gpio_pin_set_dt(&test_pin_1, 0);
272 	gpio_pin_set_dt(&test_pin_2, 1);
273 	k_msleep(10);
274 
275 	zassert_equal(atomic_get(&counter), 0, "COMP was triggered for falling threshold cross");
276 
277 	gpio_pin_set_dt(&test_pin_1, 1);
278 	gpio_pin_set_dt(&test_pin_2, 0);
279 	k_msleep(10);
280 
281 	zassert_equal(atomic_get(&counter), 0, "COMP was not triggered for rising threshold cross");
282 }
283 
suite_setup(void)284 static void *suite_setup(void)
285 {
286 	TC_PRINT("Test executed on %s\n", CONFIG_BOARD_TARGET);
287 	TC_PRINT("===================================================================\n");
288 
289 	return NULL;
290 }
291 
test_before(void * f)292 static void test_before(void *f)
293 {
294 	ARG_UNUSED(f);
295 	gpio_pin_configure_dt(&test_pin_1, GPIO_OUTPUT_INACTIVE);
296 	gpio_pin_configure_dt(&test_pin_2, GPIO_OUTPUT_INACTIVE);
297 
298 }
299 
300 ZTEST_SUITE(comparator_runtime_configure, NULL, suite_setup, test_before, NULL, NULL);
301