/**************************************************************************** * apps/testing/drivertest/drivertest_adc.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. The * ASF licenses this file to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. * ****************************************************************************/ /**************************************************************************** * Included Files ****************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ #define OPTARG_TO_VALUE(value, type, base) \ do { \ FAR char* ptr; \ value = (type)strtoul(optarg, &ptr, base); \ if (*ptr != '\0') { \ printf("Parameter error: -%c %s\n", ch, optarg); \ adc_help(argv[0]); \ } \ } while (0) /**************************************************************************** * Private Function Prototypes ****************************************************************************/ struct adc_state_s { char devpath[PATH_MAX]; /* device to adc device path */ int adc_diff; /* adc value difference */ int duration; /* duration of sampling adc in seconds */ bool soft_trigger; /* soft trigger : true or false */ }; /**************************************************************************** * Private Functions ****************************************************************************/ static void adc_help(FAR char *process_name) { printf("Usage: %s [OPTIONS]\n", process_name); printf(" -p adc device path , default : /dev/adc0\n"); printf(" -d sample adc changes over set-up value. default : 200\n"); printf(" -t duration of adc test [second] , default: 10s\n"); printf(" -m adc conversion method, 1 -- soft trigger, " "0 -- interrupt , default: 1\n"); exit(-1); } /**************************************************************************** * Name: parse_commandline ****************************************************************************/ static void parse_commandline(FAR struct adc_state_s *adc_state, int argc, FAR char **argv) { int ch; int converted; while ((ch = getopt(argc, argv, "p:d:m:t:h")) != ERROR) { switch (ch) { case 'p': strlcpy(adc_state->devpath, optarg, sizeof(adc_state->devpath)); adc_state->devpath[sizeof(adc_state->devpath) - 1] = '\0'; break; case 'd': OPTARG_TO_VALUE(converted, int, 10); if (converted < 0 || converted > 5000) { printf("sample adc value changes over: %d\n", converted); adc_help(argv[0]); } adc_state->adc_diff = (uint8_t)converted; break; case 't': OPTARG_TO_VALUE(converted, int, 10); if (converted < 1 || converted > INT_MAX) { printf("Duty out of range: %d\n", converted); adc_help(argv[0]); } adc_state->duration = (int)converted; break; case 'm': OPTARG_TO_VALUE(converted, uint8_t, 10); adc_state->soft_trigger = converted ? true : false; break; case '?': printf("Unsupported option: %s\n", optarg); case 'h': adc_help(argv[0]); break; } } } int32_t adc_read_one_sample(int fd, bool soft_trigger) { struct adc_msg_s sample; int ret; int nbytes; /* software trigger to start one ADC conversion */ if (soft_trigger) { ret = ioctl(fd, ANIOC_TRIGGER, 0); assert_return_code(ret, OK); } /* Read one samples */ nbytes = read(fd, &sample, sizeof(struct adc_msg_s)); /* Handle unexpected return values */ assert_true(nbytes == sizeof(struct adc_msg_s)); return sample.am_data; } /**************************************************************************** * Name: test_case_adc ****************************************************************************/ static void test_case_adc(FAR void** state) { int fd; bool succ = false; int32_t value1; int32_t value2; struct timeval tv1; struct timeval tv2; struct timeval res; FAR struct adc_state_s *adc_state; adc_state = (FAR struct adc_state_s *)*state; /* Open the ADC device for reading */ fd = open(adc_state->devpath, O_RDONLY); assert_true(fd > 0); value1 = adc_read_one_sample(fd, adc_state->soft_trigger); /* ADC sample value should be changed in duration [seconds] */ gettimeofday(&tv1, NULL); while (true) { value2 = adc_read_one_sample(fd, adc_state->soft_trigger); if (abs(value2 - value1) > adc_state->adc_diff) { succ = true; break; } gettimeofday(&tv2, NULL); timersub(&tv2, &tv1, &res); if (res.tv_sec >= adc_state->duration) { printf("adc test timed out\n"); break; } usleep(adc_state->soft_trigger ? 1000000 : 200000); } close(fd); assert_true(succ); } /**************************************************************************** * drivertest_adc_main ****************************************************************************/ int main(int argc, FAR char *argv[]) { /* Initialize the state data */ struct adc_state_s adc_state = { .devpath = "/dev/adc0", .adc_diff = 200, .duration = 10, .soft_trigger = true, }; parse_commandline(&adc_state, argc, argv); const struct CMUnitTest tests[] = { cmocka_unit_test_prestate(test_case_adc, &adc_state), }; return cmocka_run_group_tests(tests, NULL, NULL); }