1 /*
2 * Copyright 2021 Google LLC
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/drivers/adc.h>
8 #include <zephyr/drivers/adc/adc_emul.h>
9 #include <zephyr/kernel.h>
10 #include <zephyr/ztest.h>
11
12 #define ADC_DEVICE_NODE DT_INST(0, zephyr_adc_emul)
13 #define ADC_REF_INTERNAL_MV DT_PROP(DT_INST(0, zephyr_adc_emul), ref_internal_mv)
14 #define ADC_REF_EXTERNAL1_MV DT_PROP(DT_INST(0, zephyr_adc_emul), ref_external1_mv)
15 #define ADC_RESOLUTION 14
16 #define ADC_ACQUISITION_TIME ADC_ACQ_TIME_DEFAULT
17 #define ADC_1ST_CHANNEL_ID 0
18 #define ADC_2ND_CHANNEL_ID 1
19
20 #define INVALID_ADC_VALUE SHRT_MIN
21 /* Raw to millivolt conversion doesn't handle rounding */
22 #define MV_OUTPUT_EPS 2
23 #define SEQUENCE_STEP 100
24
25 #define BUFFER_SIZE 6
26 static ZTEST_BMEM int16_t m_sample_buffer[BUFFER_SIZE];
27
28 /**
29 * @brief Get ADC emulated device
30 *
31 * @return pointer to ADC device
32 */
get_adc_device(void)33 const struct device *get_adc_device(void)
34 {
35 const struct device *const adc_dev = DEVICE_DT_GET(ADC_DEVICE_NODE);
36
37 zassert_true(device_is_ready(adc_dev), "ADC device is not ready");
38
39 return adc_dev;
40 }
41
42 /**
43 * @brief Setup channel with specific reference and gain
44 *
45 * @param adc_dev Pointer to ADC device
46 * @param ref ADC reference voltage source
47 * @param gain Gain applied to ADC @p channel
48 * @param channel ADC channel which is being setup
49 *
50 * @return none
51 */
channel_setup(const struct device * adc_dev,enum adc_reference ref,enum adc_gain gain,int channel)52 static void channel_setup(const struct device *adc_dev, enum adc_reference ref,
53 enum adc_gain gain, int channel)
54 {
55 int ret;
56 struct adc_channel_cfg channel_cfg = {
57 .gain = gain,
58 .reference = ref,
59 .acquisition_time = ADC_ACQUISITION_TIME,
60 .channel_id = channel,
61 };
62
63 ret = adc_channel_setup(adc_dev, &channel_cfg);
64 zassert_ok(ret, "Setting up of the %d channel failed with code %d",
65 channel, ret);
66 }
67
68 /**
69 * @brief Check if samples for specific channel are correct. It can check
70 * samples with arithmetic sequence with common difference.
71 *
72 * @param expected_count Number of samples that are expected to be set
73 * @param start_mv_value Voltage in mV that was set on input at the beginning
74 * of sampling
75 * @param step Common difference in arithmetic sequence which describes how
76 * samples were generated
77 * @param num_channels Number of channels that were sampled
78 * @param channel_id ADC channel from which samples are checked
79 * @param ref_mv Reference voltage in mV
80 * @param gain Gain applied to ADC @p channel_id
81 *
82 * @return none
83 */
check_samples(int expected_count,int32_t start_mv_value,int step,int num_channels,int channel_id,int32_t ref_mv,enum adc_gain gain)84 static void check_samples(int expected_count, int32_t start_mv_value, int step,
85 int num_channels, int channel_id, int32_t ref_mv,
86 enum adc_gain gain)
87 {
88 int32_t output, expected;
89 int i, ret;
90
91 for (i = channel_id; i < expected_count; i += num_channels) {
92 expected = start_mv_value + i / num_channels * step;
93 output = m_sample_buffer[i];
94 ret = adc_raw_to_millivolts(ref_mv, gain, ADC_RESOLUTION,
95 &output);
96 zassert_ok(ret, "adc_raw_to_millivolts() failed with code %d",
97 ret);
98 zassert_within(expected, output, MV_OUTPUT_EPS,
99 "%u != %u [%u] should has set value",
100 expected, output, i);
101 }
102
103 }
104
105 /**
106 * @brief Check if any values in buffer were set after expected samples.
107 *
108 * @param expected_count Number of samples that are expected to be set
109 *
110 * @return none
111 */
check_empty_samples(int expected_count)112 static void check_empty_samples(int expected_count)
113 {
114 int i;
115
116 for (i = expected_count; i < BUFFER_SIZE; i++) {
117 zassert_equal(INVALID_ADC_VALUE, m_sample_buffer[i],
118 "[%u] should be empty", i);
119 }
120 }
121
122 /**
123 * @brief Run adc_read for given channels and collect specified number of
124 * samples.
125 *
126 * @param adc_dev Pointer to ADC device
127 * @param channel_mask Mask of channels that will be sampled
128 * @param samples Number of requested samples for each channel
129 *
130 * @return none
131 */
start_adc_read(const struct device * adc_dev,uint32_t channel_mask,int samples)132 static void start_adc_read(const struct device *adc_dev, uint32_t channel_mask,
133 int samples)
134 {
135 int ret;
136 const struct adc_sequence_options *options_ptr;
137
138 const struct adc_sequence_options options = {
139 .extra_samplings = samples - 1,
140 };
141
142 if (samples > 1) {
143 options_ptr = &options;
144 } else {
145 options_ptr = NULL;
146 }
147
148 const struct adc_sequence sequence = {
149 .options = options_ptr,
150 .channels = channel_mask,
151 .buffer = m_sample_buffer,
152 .buffer_size = sizeof(m_sample_buffer),
153 .resolution = ADC_RESOLUTION,
154 };
155
156 ret = adc_read(adc_dev, &sequence);
157 zassert_ok(ret, "adc_read() failed with code %d", ret);
158 }
159
160 /** @brief Data for handle_seq function */
161 struct handle_seq_params {
162 /** Current input value in mV */
163 unsigned int value;
164 };
165
166 /**
167 * @brief Simple custom function to set as value input function for emulated
168 * ADC channel. It returns arithmetic sequence with SEQUENCE_STEP
169 * as common difference, starting from param value.
170 *
171 * @param dev Pointer to ADC device
172 * @param channel ADC channel for which input value is requested
173 * @param data Pointer to function parameters. It has to be
174 * struct handle_seq_params type
175 * @param result Pointer where input value should be stored
176 *
177 * @return 0 on success
178 * @return -EINVAL when current input value equals 0
179 */
handle_seq(const struct device * dev,unsigned int channel,void * data,uint32_t * result)180 static int handle_seq(const struct device *dev, unsigned int channel,
181 void *data, uint32_t *result)
182 {
183 struct handle_seq_params *param = data;
184
185 if (param->value == 0) {
186 return -EINVAL;
187 }
188
189 *result = param->value;
190 param->value += SEQUENCE_STEP;
191
192 return 0;
193 }
194
195 /** @brief Test setting one channel with constant output. */
ZTEST_USER(adc_emul,test_adc_emul_single_value)196 ZTEST_USER(adc_emul, test_adc_emul_single_value)
197 {
198 const uint16_t input_mv = 1500;
199 const int samples = 4;
200 int ret, i;
201
202 for (i = 0; i < BUFFER_SIZE; ++i) {
203 m_sample_buffer[i] = INVALID_ADC_VALUE;
204 }
205
206 /* Generic ADC setup */
207 const struct device *adc_dev = get_adc_device();
208
209 channel_setup(adc_dev, ADC_REF_INTERNAL, ADC_GAIN_1,
210 ADC_1ST_CHANNEL_ID);
211
212 /* ADC emulator-specific setup */
213 ret = adc_emul_const_value_set(adc_dev, ADC_1ST_CHANNEL_ID, input_mv);
214 zassert_ok(ret, "adc_emul_const_value_set() failed with code %d", ret);
215
216 /* Test sampling */
217 start_adc_read(adc_dev, BIT(ADC_1ST_CHANNEL_ID), samples);
218
219 /* Check samples */
220 check_samples(samples, input_mv, 0 /* step */, 1 /* channels */, 0 /* first channel data */,
221 ADC_REF_INTERNAL_MV, ADC_GAIN_1);
222
223 check_empty_samples(samples);
224 }
225
226 /** @brief Test setting one channel with constant raw output. */
ZTEST_USER(adc_emul,test_adc_emul_single_raw_value_half_reference)227 ZTEST_USER(adc_emul, test_adc_emul_single_raw_value_half_reference)
228 {
229 const uint16_t input_raw_value = (1 << ADC_RESOLUTION) / 2;
230 const uint16_t input_mv = ADC_REF_INTERNAL_MV / 2;
231 const int samples = 4;
232 int ret, i;
233
234 for (i = 0; i < BUFFER_SIZE; ++i) {
235 m_sample_buffer[i] = INVALID_ADC_VALUE;
236 }
237
238 /* Generic ADC setup */
239 const struct device *adc_dev = get_adc_device();
240
241 channel_setup(adc_dev, ADC_REF_INTERNAL, ADC_GAIN_1, ADC_1ST_CHANNEL_ID);
242
243 /* ADC emulator-specific setup */
244 ret = adc_emul_const_raw_value_set(adc_dev, ADC_1ST_CHANNEL_ID, input_raw_value);
245 zassert_ok(ret, "adc_emul_const_value_set() failed with code %d", ret);
246
247 /* Test sampling */
248 start_adc_read(adc_dev, BIT(ADC_1ST_CHANNEL_ID), samples);
249
250 /* Check samples */
251 check_samples(samples, input_mv, 0 /* step */, 1 /* channels */, 0 /* first channel data */,
252 ADC_REF_INTERNAL_MV, ADC_GAIN_1);
253
254 check_empty_samples(samples);
255 }
256
257 /** @brief Test setting one channel with constant raw output. */
ZTEST_USER(adc_emul,test_adc_emul_single_raw_value_quarter_reference)258 ZTEST_USER(adc_emul, test_adc_emul_single_raw_value_quarter_reference)
259 {
260 const uint16_t input_raw_value = (1 << ADC_RESOLUTION) / 4;
261 const uint16_t input_mv = ADC_REF_INTERNAL_MV / 4;
262 const int samples = 4;
263 int ret, i;
264
265 for (i = 0; i < BUFFER_SIZE; ++i) {
266 m_sample_buffer[i] = INVALID_ADC_VALUE;
267 }
268
269 /* Generic ADC setup */
270 const struct device *adc_dev = get_adc_device();
271
272 channel_setup(adc_dev, ADC_REF_INTERNAL, ADC_GAIN_1, ADC_1ST_CHANNEL_ID);
273
274 /* ADC emulator-specific setup */
275 ret = adc_emul_const_raw_value_set(adc_dev, ADC_1ST_CHANNEL_ID, input_raw_value);
276 zassert_ok(ret, "adc_emul_const_value_set() failed with code %d", ret);
277
278 /* Test sampling */
279 start_adc_read(adc_dev, BIT(ADC_1ST_CHANNEL_ID), samples);
280
281 /* Check samples */
282 check_samples(samples, input_mv, 0 /* step */, 1 /* channels */,
283 0 /* first channel data */, ADC_REF_INTERNAL_MV,
284 ADC_GAIN_1);
285
286 check_empty_samples(samples);
287 }
288
289 /** @brief Test setting two channels with different constant output */
ZTEST_USER(adc_emul,test_adc_emul_single_value_2ch)290 ZTEST_USER(adc_emul, test_adc_emul_single_value_2ch)
291 {
292 const uint16_t input1_mv = 3000;
293 const uint16_t input2_mv = 2000;
294 const int samples = 3;
295 int ret, i;
296
297 for (i = 0; i < BUFFER_SIZE; ++i) {
298 m_sample_buffer[i] = INVALID_ADC_VALUE;
299 }
300
301 /* Generic ADC setup */
302 const struct device *adc_dev = get_adc_device();
303
304 channel_setup(adc_dev, ADC_REF_INTERNAL, ADC_GAIN_1,
305 ADC_1ST_CHANNEL_ID);
306 channel_setup(adc_dev, ADC_REF_INTERNAL, ADC_GAIN_1,
307 ADC_2ND_CHANNEL_ID);
308
309 /* ADC emulator-specific setup */
310 ret = adc_emul_const_value_set(adc_dev, ADC_1ST_CHANNEL_ID, input1_mv);
311 zassert_ok(ret, "adc_emul_const_value_set() failed with code %d", ret);
312
313 ret = adc_emul_const_value_set(adc_dev, ADC_2ND_CHANNEL_ID, input2_mv);
314 zassert_ok(ret, "adc_emul_const_value_set() failed with code %d", ret);
315
316 /* Test sampling */
317 start_adc_read(adc_dev, BIT(ADC_1ST_CHANNEL_ID) |
318 BIT(ADC_2ND_CHANNEL_ID), samples);
319
320 /* Check samples */
321 check_samples(samples * 2, input1_mv, 0 /* step */, 2 /* channels */,
322 0 /* first channel data */, ADC_REF_INTERNAL_MV,
323 ADC_GAIN_1);
324 check_samples(samples * 2, input2_mv, 0 /* step */, 2 /* channels */,
325 1 /* first channel data */, ADC_REF_INTERNAL_MV,
326 ADC_GAIN_1);
327
328 check_empty_samples(samples * 2);
329 }
330
331 /** @brief Test setting one channel with custom function. */
ZTEST_USER(adc_emul,test_adc_emul_custom_function)332 ZTEST_USER(adc_emul, test_adc_emul_custom_function)
333 {
334 struct handle_seq_params channel1_param;
335 const uint16_t input_mv = 1500;
336 const int samples = 4;
337 int ret, i;
338
339 for (i = 0; i < BUFFER_SIZE; ++i) {
340 m_sample_buffer[i] = INVALID_ADC_VALUE;
341 }
342
343 /* Generic ADC setup */
344 const struct device *adc_dev = get_adc_device();
345
346 channel_setup(adc_dev, ADC_REF_INTERNAL, ADC_GAIN_1,
347 ADC_1ST_CHANNEL_ID);
348
349 /* ADC emulator-specific setup */
350 channel1_param.value = input_mv;
351
352 ret = adc_emul_value_func_set(adc_dev, ADC_1ST_CHANNEL_ID,
353 handle_seq, &channel1_param);
354 zassert_ok(ret, "adc_emul_value_func_set() failed with code %d", ret);
355
356 /* Test sampling */
357 start_adc_read(adc_dev, BIT(ADC_1ST_CHANNEL_ID), samples);
358
359 /* Check samples */
360 check_samples(samples, input_mv, SEQUENCE_STEP, 1 /* channels */,
361 0 /* first channel data */, ADC_REF_INTERNAL_MV,
362 ADC_GAIN_1);
363
364 check_empty_samples(samples);
365 }
366
367 /** @brief Test setting one channel with custom function raw value. */
ZTEST_USER(adc_emul,test_adc_emul_custom_function_raw_value)368 ZTEST_USER(adc_emul, test_adc_emul_custom_function_raw_value)
369 {
370 struct handle_seq_params channel1_param;
371 const uint16_t raw_value = 1000;
372 const uint16_t input_mV = (raw_value * ADC_REF_INTERNAL_MV / BIT(ADC_RESOLUTION));
373 const int samples = 4;
374 int ret, i;
375
376 for (i = 0; i < BUFFER_SIZE; ++i) {
377 m_sample_buffer[i] = INVALID_ADC_VALUE;
378 }
379
380 /* Generic ADC setup */
381 const struct device *adc_dev = get_adc_device();
382
383 channel_setup(adc_dev, ADC_REF_INTERNAL, ADC_GAIN_1, ADC_1ST_CHANNEL_ID);
384
385 /* ADC emulator-specific setup */
386 channel1_param.value = raw_value;
387
388 ret = adc_emul_raw_value_func_set(adc_dev, ADC_1ST_CHANNEL_ID, handle_seq, &channel1_param);
389 zassert_ok(ret, "adc_emul_value_func_set() failed with code %d", ret);
390
391 /* Test sampling */
392 start_adc_read(adc_dev, BIT(ADC_1ST_CHANNEL_ID), samples);
393
394 /* Check samples */
395 check_samples(samples, input_mV,
396 (SEQUENCE_STEP * ADC_REF_INTERNAL_MV / BIT(ADC_RESOLUTION)), 1 /* channels */,
397 0 /* first channel data */, ADC_REF_INTERNAL_MV, ADC_GAIN_1);
398
399 check_empty_samples(samples);
400 }
401
402 /**
403 * @brief Test setting two channels with custom function and different
404 * params.
405 */
ZTEST_USER(adc_emul,test_adc_emul_custom_function_2ch)406 ZTEST_USER(adc_emul, test_adc_emul_custom_function_2ch)
407 {
408 struct handle_seq_params channel1_param;
409 struct handle_seq_params channel2_param;
410 const uint16_t input1_mv = 1500;
411 const uint16_t input2_mv = 1000;
412 const int samples = 3;
413 int ret, i;
414
415 for (i = 0; i < BUFFER_SIZE; ++i) {
416 m_sample_buffer[i] = INVALID_ADC_VALUE;
417 }
418
419 /* Generic ADC setup */
420 const struct device *adc_dev = get_adc_device();
421
422 channel_setup(adc_dev, ADC_REF_INTERNAL, ADC_GAIN_1,
423 ADC_1ST_CHANNEL_ID);
424 channel_setup(adc_dev, ADC_REF_INTERNAL, ADC_GAIN_1,
425 ADC_2ND_CHANNEL_ID);
426
427 /* ADC emulator-specific setup */
428 channel1_param.value = input1_mv;
429 channel2_param.value = input2_mv;
430
431 ret = adc_emul_value_func_set(adc_dev, ADC_1ST_CHANNEL_ID,
432 handle_seq, &channel1_param);
433 zassert_ok(ret, "adc_emul_value_func_set() failed with code %d", ret);
434
435 ret = adc_emul_value_func_set(adc_dev, ADC_2ND_CHANNEL_ID,
436 handle_seq, &channel2_param);
437 zassert_ok(ret, "adc_emul_value_func_set() failed with code %d", ret);
438
439 /* Test sampling */
440 start_adc_read(adc_dev, BIT(ADC_1ST_CHANNEL_ID) |
441 BIT(ADC_2ND_CHANNEL_ID), samples);
442
443 /* Check samples */
444 check_samples(samples * 2, input1_mv, SEQUENCE_STEP,
445 2 /* channels */, 0 /* first channel data */,
446 ADC_REF_INTERNAL_MV, ADC_GAIN_1);
447 check_samples(samples * 2, input2_mv, SEQUENCE_STEP,
448 2 /* channels */, 1 /* first channel data */,
449 ADC_REF_INTERNAL_MV, ADC_GAIN_1);
450
451 check_empty_samples(samples * 2);
452 }
453
454 /**
455 * @brief Test setting two channels, one with custom function and
456 * one with constant value.
457 */
ZTEST_USER(adc_emul,test_adc_emul_custom_function_and_value)458 ZTEST_USER(adc_emul, test_adc_emul_custom_function_and_value)
459 {
460 struct handle_seq_params channel1_param;
461 const uint16_t input1_mv = 1500;
462 const uint16_t input2_mv = 1000;
463 const int samples = 3;
464 int ret, i;
465
466 for (i = 0; i < BUFFER_SIZE; ++i) {
467 m_sample_buffer[i] = INVALID_ADC_VALUE;
468 }
469
470 /* Generic ADC setup */
471 const struct device *adc_dev = get_adc_device();
472
473 channel_setup(adc_dev, ADC_REF_INTERNAL, ADC_GAIN_1,
474 ADC_1ST_CHANNEL_ID);
475 channel_setup(adc_dev, ADC_REF_INTERNAL, ADC_GAIN_1,
476 ADC_2ND_CHANNEL_ID);
477
478 /* ADC emulator-specific setup */
479 channel1_param.value = input1_mv;
480
481 ret = adc_emul_value_func_set(adc_dev, ADC_1ST_CHANNEL_ID,
482 handle_seq, &channel1_param);
483 zassert_ok(ret, "adc_emul_value_func_set() failed with code %d", ret);
484
485 ret = adc_emul_const_value_set(adc_dev, ADC_2ND_CHANNEL_ID, input2_mv);
486 zassert_ok(ret, "adc_emul_const_value_set() failed with code %d", ret);
487
488 /* Test sampling */
489 start_adc_read(adc_dev, BIT(ADC_1ST_CHANNEL_ID) |
490 BIT(ADC_2ND_CHANNEL_ID), samples);
491
492 /* Check samples */
493 check_samples(samples * 2, input1_mv, SEQUENCE_STEP,
494 2 /* channels */, 0 /* first channel data */,
495 ADC_REF_INTERNAL_MV, ADC_GAIN_1);
496 check_samples(samples * 2, input2_mv, 0 /* step */, 2 /* channels */,
497 1 /* first channel data */, ADC_REF_INTERNAL_MV,
498 ADC_GAIN_1);
499
500 check_empty_samples(samples * 2);
501 }
502
503 /** @brief Test few different settings of gain argument. */
ZTEST_USER(adc_emul,test_adc_emul_gain)504 ZTEST_USER(adc_emul, test_adc_emul_gain)
505 {
506 const uint16_t input_mv = 1000;
507 uint32_t channel_mask;
508 const int samples = 3;
509 int ret, i;
510
511 for (i = 0; i < BUFFER_SIZE; ++i) {
512 m_sample_buffer[i] = INVALID_ADC_VALUE;
513 }
514
515 /* Generic ADC setup */
516 const struct device *adc_dev = get_adc_device();
517
518 channel_setup(adc_dev, ADC_REF_INTERNAL, ADC_GAIN_1_6,
519 ADC_1ST_CHANNEL_ID);
520 channel_setup(adc_dev, ADC_REF_INTERNAL, ADC_GAIN_3,
521 ADC_2ND_CHANNEL_ID);
522
523 /* ADC emulator-specific setup */
524 channel_mask = BIT(ADC_1ST_CHANNEL_ID) | BIT(ADC_2ND_CHANNEL_ID);
525
526 ret = adc_emul_const_value_set(adc_dev, ADC_1ST_CHANNEL_ID, input_mv);
527 zassert_ok(ret, "adc_emul_const_value_set() failed with code %d", ret);
528
529 ret = adc_emul_const_value_set(adc_dev, ADC_2ND_CHANNEL_ID, input_mv);
530 zassert_ok(ret, "adc_emul_const_value_set() failed with code %d", ret);
531
532 /* Test sampling */
533 start_adc_read(adc_dev, channel_mask, samples);
534
535 /* Check samples */
536 check_samples(samples * 2, input_mv, 0 /* step */, 2 /* channels */,
537 0 /* first channel data */, ADC_REF_INTERNAL_MV,
538 ADC_GAIN_1_6);
539 check_samples(samples * 2, input_mv, 0 /* step */, 2 /* channels */,
540 1 /* first channel data */, ADC_REF_INTERNAL_MV,
541 ADC_GAIN_3);
542
543 check_empty_samples(samples * 2);
544
545 /* Change gain and re-run test */
546 channel_setup(adc_dev, ADC_REF_INTERNAL, ADC_GAIN_1_4,
547 ADC_1ST_CHANNEL_ID);
548 channel_setup(adc_dev, ADC_REF_INTERNAL, ADC_GAIN_2_3,
549 ADC_2ND_CHANNEL_ID);
550
551 /* Test sampling */
552 start_adc_read(adc_dev, channel_mask, samples);
553
554 /* Check samples */
555 check_samples(samples * 2, input_mv, 0 /* step */, 2 /* channels */,
556 0 /* first channel data */, ADC_REF_INTERNAL_MV,
557 ADC_GAIN_1_4);
558 check_samples(samples * 2, input_mv, 0 /* step */, 2 /* channels */,
559 1 /* first channel data */, ADC_REF_INTERNAL_MV,
560 ADC_GAIN_2_3);
561
562 check_empty_samples(samples * 2);
563 }
564
565 /**
566 * @brief Test behaviour on input higher than reference. Return value should be
567 * cropped to reference value and cannot exceed resolution requested in
568 * adc_read().
569 */
ZTEST_USER(adc_emul,test_adc_emul_input_higher_than_ref)570 ZTEST_USER(adc_emul, test_adc_emul_input_higher_than_ref)
571 {
572 const uint16_t input_mv = ADC_REF_INTERNAL_MV + 100;
573 const int samples = 4;
574 int ret, i;
575
576 for (i = 0; i < BUFFER_SIZE; ++i) {
577 m_sample_buffer[i] = INVALID_ADC_VALUE;
578 }
579
580 /* Generic ADC setup */
581 const struct device *adc_dev = get_adc_device();
582
583 channel_setup(adc_dev, ADC_REF_INTERNAL, ADC_GAIN_1,
584 ADC_1ST_CHANNEL_ID);
585
586 /* ADC emulator-specific setup */
587 ret = adc_emul_const_value_set(adc_dev, ADC_1ST_CHANNEL_ID, input_mv);
588 zassert_ok(ret, "adc_emul_const_value_set() failed with code %d", ret);
589
590 /* Test sampling */
591 start_adc_read(adc_dev, BIT(ADC_1ST_CHANNEL_ID), samples);
592
593 /*
594 * Check samples - returned value should max out on reference value.
595 * Raw value shouldn't exceed resolution.
596 */
597 check_samples(samples, ADC_REF_INTERNAL_MV, 0 /* step */,
598 1 /* channels */, 0 /* first channel data */,
599 ADC_REF_INTERNAL_MV, ADC_GAIN_1);
600
601 check_empty_samples(samples);
602
603 for (i = 0; i < samples; i++) {
604 zassert_equal(BIT_MASK(ADC_RESOLUTION), m_sample_buffer[i],
605 "[%u] raw value isn't max value", i);
606 }
607 }
608
609 /**
610 * @brief Test different reference sources and if error is reported when
611 * unconfigured reference source is requested.
612 */
ZTEST_USER(adc_emul,test_adc_emul_reference)613 ZTEST_USER(adc_emul, test_adc_emul_reference)
614 {
615 const uint16_t input1_mv = 4000;
616 const uint16_t input2_mv = 2000;
617 const int samples = 3;
618 int ret, i;
619
620 for (i = 0; i < BUFFER_SIZE; ++i) {
621 m_sample_buffer[i] = INVALID_ADC_VALUE;
622 }
623
624 /* Generic ADC setup */
625 const struct device *adc_dev = get_adc_device();
626
627 channel_setup(adc_dev, ADC_REF_EXTERNAL1, ADC_GAIN_1,
628 ADC_1ST_CHANNEL_ID);
629
630 struct adc_channel_cfg channel_cfg = {
631 .gain = ADC_GAIN_1,
632 /* Reference value not setup in DTS */
633 .reference = ADC_REF_EXTERNAL0,
634 .acquisition_time = ADC_ACQUISITION_TIME,
635 .channel_id = ADC_2ND_CHANNEL_ID,
636 };
637
638 ret = adc_channel_setup(adc_dev, &channel_cfg);
639 zassert_not_equal(ret, 0,
640 "Setting up of the %d channel shouldn't succeeded",
641 ADC_2ND_CHANNEL_ID);
642
643 channel_setup(adc_dev, ADC_REF_INTERNAL, ADC_GAIN_1,
644 ADC_2ND_CHANNEL_ID);
645
646 /* ADC emulator-specific setup */
647 ret = adc_emul_const_value_set(adc_dev, ADC_1ST_CHANNEL_ID, input1_mv);
648 zassert_ok(ret, "adc_emul_const_value_set() failed with code %d", ret);
649
650 ret = adc_emul_const_value_set(adc_dev, ADC_2ND_CHANNEL_ID, input2_mv);
651 zassert_ok(ret, "adc_emul_const_value_set() failed with code %d", ret);
652
653 /* Test sampling */
654 start_adc_read(adc_dev, BIT(ADC_1ST_CHANNEL_ID) |
655 BIT(ADC_2ND_CHANNEL_ID), samples);
656
657 /* Check samples */
658 check_samples(samples * 2, input1_mv, 0 /* step */, 2 /* channels */,
659 0 /* first channel data */, ADC_REF_EXTERNAL1_MV,
660 ADC_GAIN_1);
661 check_samples(samples * 2, input2_mv, 0 /* step */, 2 /* channels */,
662 1 /* first channel data */, ADC_REF_INTERNAL_MV,
663 ADC_GAIN_1);
664
665 check_empty_samples(samples * 2);
666 }
667
668 /** @brief Test setting reference value. */
ZTEST_USER(adc_emul,test_adc_emul_ref_voltage_set)669 ZTEST_USER(adc_emul, test_adc_emul_ref_voltage_set)
670 {
671 const uint16_t input1_mv = 4000;
672 const uint16_t input2_mv = 2000;
673 const uint16_t ref1_mv = 6000;
674 const uint16_t ref2_mv = 9000;
675 const int samples = 3;
676 int ret, i;
677
678 for (i = 0; i < BUFFER_SIZE; ++i) {
679 m_sample_buffer[i] = INVALID_ADC_VALUE;
680 }
681
682 /* Generic ADC setup */
683 const struct device *adc_dev = get_adc_device();
684
685 channel_setup(adc_dev, ADC_REF_EXTERNAL1, ADC_GAIN_1,
686 ADC_1ST_CHANNEL_ID);
687 channel_setup(adc_dev, ADC_REF_INTERNAL, ADC_GAIN_1,
688 ADC_2ND_CHANNEL_ID);
689
690 /* ADC emulator-specific setup */
691 ret = adc_emul_const_value_set(adc_dev, ADC_1ST_CHANNEL_ID, input1_mv);
692 zassert_ok(ret, "adc_emul_const_value_set() failed with code %d", ret);
693
694 ret = adc_emul_const_value_set(adc_dev, ADC_2ND_CHANNEL_ID, input2_mv);
695 zassert_ok(ret, "adc_emul_const_value_set() failed with code %d", ret);
696
697 /* Change reference voltage */
698 ret = adc_emul_ref_voltage_set(adc_dev, ADC_REF_EXTERNAL1, ref1_mv);
699 zassert_ok(ret, "adc_emul_ref_voltage_set() failed with code %d", ret);
700
701 ret = adc_emul_ref_voltage_set(adc_dev, ADC_REF_INTERNAL, ref2_mv);
702 zassert_ok(ret, "adc_emul_ref_voltage_set() failed with code %d", ret);
703
704 /* Test sampling */
705 start_adc_read(adc_dev, BIT(ADC_1ST_CHANNEL_ID) |
706 BIT(ADC_2ND_CHANNEL_ID), samples);
707
708 /* Check samples */
709 check_samples(samples * 2, input1_mv, 0 /* step */, 2 /* channels */,
710 0 /* first channel data */, ref1_mv, ADC_GAIN_1);
711 check_samples(samples * 2, input2_mv, 0 /* step */, 2 /* channels */,
712 1 /* first channel data */, ref2_mv, ADC_GAIN_1);
713
714 check_empty_samples(samples * 2);
715
716 /* Set previous reference voltage value */
717 ret = adc_emul_ref_voltage_set(adc_dev, ADC_REF_EXTERNAL1,
718 ADC_REF_EXTERNAL1_MV);
719 zassert_ok(ret, "adc_emul_ref_voltage_set() failed with code %d", ret);
720
721 ret = adc_emul_ref_voltage_set(adc_dev, ADC_REF_INTERNAL,
722 ADC_REF_INTERNAL_MV);
723 zassert_ok(ret, "adc_emul_ref_voltage_set() failed with code %d", ret);
724
725 /* Test sampling */
726 start_adc_read(adc_dev, BIT(ADC_1ST_CHANNEL_ID) |
727 BIT(ADC_2ND_CHANNEL_ID), samples);
728
729 /* Check samples */
730 check_samples(samples * 2, input1_mv, 0 /* step */, 2 /* channels */,
731 0 /* first channel data */, ADC_REF_EXTERNAL1_MV,
732 ADC_GAIN_1);
733 check_samples(samples * 2, input2_mv, 0 /* step */, 2 /* channels */,
734 1 /* first channel data */, ADC_REF_INTERNAL_MV,
735 ADC_GAIN_1);
736
737 check_empty_samples(samples * 2);
738 }
739
adc_emul_setup(void)740 void *adc_emul_setup(void)
741 {
742 k_object_access_grant(get_adc_device(), k_current_get());
743
744 return NULL;
745 }
746
747 ZTEST_SUITE(adc_emul, NULL, adc_emul_setup, NULL, NULL, NULL);
748