/* * Copyright 2017, Digi International Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include #include #include #include #define DEFAULT_PWM_FREQUENCY 1000 #define DEFAULT_PWM_ALIAS "DEFAULT_PWM" #define ARG_PWM_CHIP 0 #define ARG_PWM_CHANNEL 1 static pwm_t *pwm_line; static int running = 1; /* * usage_and_exit() - Show usage information and exit with 'exitval' return * value * * @name: Application name. * @exitval: The exit code. */ static void usage_and_exit(char *name, int exitval) { fprintf(stdout, "Example application using libdigiapix PWM support\n" "\n" "Usage: %s\n" " %s is used as PWM alias\n" " %dHz is used as Frequency\n\n" "Usage: %s \n" " PWM alias\n" " Frequency to use (Hz)\n\n" "Usage: %s \n" " PWM chip number\n" " PWM channel number\n" " Frequency to use (Hz)\n" "\n" "Aliases for PWM can be configured in the library config file\n" "\n", name, DEFAULT_PWM_ALIAS, DEFAULT_PWM_FREQUENCY, name, name); exit(exitval); } /* * cleanup() - Frees all the allocated memory before exiting */ static void cleanup(void) { running = 0; if (pwm_line) { ldx_pwm_set_duty_cycle(pwm_line, 0); ldx_pwm_enable(pwm_line, PWM_DISABLED); ldx_pwm_free(pwm_line); } } /* * sigaction_handler() - Handler to execute after receiving a signal * * @signum: Received signal. */ static void sigaction_handler(int signum) { /* 'atexit' executes the cleanup function */ exit(EXIT_FAILURE); } /* * register_signals() - Registers program signals */ static void register_signals(void) { struct sigaction action; action.sa_handler = sigaction_handler; action.sa_flags = 0; sigemptyset(&action.sa_mask); sigaction(SIGHUP, &action, NULL); sigaction(SIGINT, &action, NULL); sigaction(SIGTERM, &action, NULL); } /* * parse_argument() - Parses the given string argument and returns the * corresponding integer value * * @argv: Argument to parse in string format. * @arg_type: Type of the argument to parse. * * Return: The parsed integer argument, -1 on error. */ static int parse_argument(char *argv, int arg_type) { char *endptr; long value; errno = 0; value = strtol(argv, &endptr, 10); if ((errno == ERANGE && (value == LONG_MAX || value == LONG_MIN)) || (errno != 0 && value == 0)) return -1; if (endptr == argv){ switch (arg_type) { case ARG_PWM_CHIP: return ldx_pwm_get_chip(endptr); case ARG_PWM_CHANNEL: return ldx_pwm_get_channel(endptr); default: return -1; } } return value; } int main(int argc, char **argv) { int ret, ascending = 1, pwm_chip, pwm_channel, pwm_freq = 0; char *name = basename(argv[0]); int duty_cycle[] = {0, 1, 3, 5, 10, 15, 20, 30, 50, 100}; int d = 0; int levels = sizeof(duty_cycle) / sizeof(duty_cycle[0]); /* Check if the PWM values are passed in the command line. */ if (argc == 1) { pwm_chip = ldx_pwm_get_chip(DEFAULT_PWM_ALIAS); pwm_channel = ldx_pwm_get_channel(DEFAULT_PWM_ALIAS); pwm_freq = DEFAULT_PWM_FREQUENCY; } else if (argc == 3) { pwm_chip = parse_argument(argv[1], ARG_PWM_CHIP); pwm_channel = parse_argument(argv[1], ARG_PWM_CHANNEL); pwm_freq = atoi(argv[2]); } else if (argc == 4) { pwm_chip = parse_argument(argv[1], ARG_PWM_CHIP); pwm_channel = parse_argument(argv[2], ARG_PWM_CHANNEL); pwm_freq = atoi(argv[3]); } else { usage_and_exit(name, EXIT_FAILURE); } if (pwm_chip < 0 || pwm_channel < 0 ) { printf("Unable to parse PWM chip or channel\n"); return EXIT_FAILURE; } if (pwm_freq <= 0) { printf("Frequency must be greater than 0\n"); return EXIT_FAILURE; } pwm_line = ldx_pwm_request(pwm_chip, pwm_channel, REQUEST_SHARED); /* Check PWM. */ if (!pwm_line) { printf("Failed to initialize PWM\n"); return EXIT_FAILURE; } /* Register signals and exit cleanup function */ atexit(cleanup); register_signals(); printf("Setting PWM frequency to %dHz...", pwm_freq); ret = ldx_pwm_set_freq(pwm_line, pwm_freq); if (ret != PWM_CONFIG_ERROR_NONE) { printf("Failed\n"); return EXIT_FAILURE; } /* Check the frequency. */ ret = ldx_pwm_get_freq(pwm_line); printf("%s\n", ret >= 0 ? "Done" : "Failed"); if (ret == -1) { return EXIT_FAILURE; } printf("Enabling PWM %d:%d...", pwm_line->chip, pwm_line->channel); ret = ldx_pwm_enable(pwm_line, PWM_ENABLED); if (ret != EXIT_SUCCESS) { printf("Failed\n"); return EXIT_FAILURE; } ret = ldx_pwm_is_enabled(pwm_line); printf("%s\n", ret == PWM_ENABLED ? "Done" : "Failed"); if (ret != PWM_ENABLED) { return EXIT_FAILURE; } /* Main application loop.*/ while (running) { /* Set the duty cycle. */ ret = ldx_pwm_set_duty_cycle_percentage(pwm_line, duty_cycle[d]); if (ret != PWM_CONFIG_ERROR_NONE) { printf("Failed to set the duty cycle\n"); return EXIT_FAILURE; } if (ascending) { if (++d == levels - 1) ascending = 0; } else { if (--d == 0) ascending = 1; } usleep(150000); } return EXIT_SUCCESS; }