dey-examples/apix-pwm-example/main.c

198 lines
5.1 KiB
C

/*
* Copyright (c) 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 <libgen.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pwm.h>
/*------------------------------------------------------------------------------
D E F I N I T I O N S
------------------------------------------------------------------------------*/
#define DEFAULT_PWM_CHANNEL 0
#define DEFAULT_FREQUENCY 1000 /* In Hz */
#define DEFAULT_PWM_ALIAS "DEFAULT_PWM"
#define BUFF_SIZE 256
#define USAGE \
"Usage:\n" \
"%s [pwm-chip pwm-freq]\n\n" \
"Where:\n" \
" 'pwm-chip' is an optional PWM chip number\n" \
" 'pwm-freq' is an optional frequency to use (Hz)\n\n" \
/*------------------------------------------------------------------------------
F U N C T I O N D E C L A R A T I O N S
------------------------------------------------------------------------------*/
static void cleanup();
static void add_sigkill_signal(void);
static void graceful_shutdown(void);
static void sigint_handler(int signum);
static void usage(char const * const name);
/**
* sigint_handler() - Manage signal received.
*
* @signum: Received signal.
*/
static void sigint_handler(int signum)
{
exit(EXIT_SUCCESS);
}
/**
* usage() - Print usage information
*
* @name: Name of the application.
*/
static void usage(char const * const name)
{
printf(USAGE, name);
}
/*------------------------------------------------------------------------------
G L O B A L V A R I A B L E S
------------------------------------------------------------------------------*/
static pwm_t *pwm_line;
static int running = 1;
int main(int argc, char **argv)
{
unsigned int pwm_freq = DEFAULT_FREQUENCY;
int ret, duty_cycle = 10, ascending = 1;
char *name = basename(argv[0]);
/* Check if the PWM values are passed in the command line. */
if (argc == 3) {
unsigned int pwm_chip = atoi(argv[1]);
pwm_freq = atoi(argv[2]);
pwm_line = pwm_request(pwm_chip, DEFAULT_PWM_CHANNEL, REQUEST_SHARED);
} else if (argc == 1) {
/* Initialize the PWM. */
pwm_line = pwm_request_by_alias(DEFAULT_PWM_ALIAS, REQUEST_SHARED);
} else if (argc <= 2 || argc > 3) {
usage(name);
return EXIT_FAILURE;
}
/* Check PWM. */
if (!pwm_line) {
printf("Failed to initialize PWM\n");
return EXIT_FAILURE;
}
add_sigkill_signal();
printf("Setting PWM frequency to %dHz...", pwm_freq);
/* Set a duty cycle of 0 to avoid errors configuring the frequency */
pwm_set_duty_cycle(pwm_line, 0);
ret = pwm_set_freq(pwm_line, pwm_freq);
if (ret != PWM_CONFIG_ERROR_NONE) {
printf("Failed\n");
return EXIT_FAILURE;
}
/* Check the frequency. */
ret = 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 = pwm_enable(pwm_line, PWM_ENABLED);
if (ret != EXIT_SUCCESS) {
printf("Failed\n");
return EXIT_FAILURE;
}
ret = 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 = pwm_set_duty_cycle_percentage(pwm_line, duty_cycle);
if (ret != PWM_CONFIG_ERROR_NONE) {
printf("Failed to set the duty cycle\n");
return EXIT_FAILURE;
}
if (ascending) {
duty_cycle += 10;
if (duty_cycle == 100) {
duty_cycle = 80;
ascending = 0;
}
} else {
duty_cycle -= 10;
if (duty_cycle == 0) {
duty_cycle = 20;
ascending = 1;
}
}
sleep(1);
}
return EXIT_SUCCESS;
}
/**
* cleanup() - Frees and leaves PWM into a known state before exit
*/
static void cleanup()
{
if (pwm_line) {
pwm_enable(pwm_line, PWM_DISABLED);
pwm_free(pwm_line);
}
}
/**
* add_sigkill_signal() - Add the kill signal to the process
*/
static void add_sigkill_signal(void)
{
struct sigaction new_action;
struct sigaction old_action;
/* Setup signal hander. */
atexit(graceful_shutdown);
new_action.sa_handler = sigint_handler;
sigemptyset(&new_action.sa_mask);
new_action.sa_flags = 0;
sigaction(SIGINT, NULL, &old_action);
if (old_action.sa_handler != SIG_IGN)
sigaction(SIGINT, &new_action, NULL);
}
/**
* graceful_shutdown() - Stop main loop
*/
void graceful_shutdown(void)
{
running = 0;
cleanup();
}