nuttx-apps/examples/powerled/powerled_main.c

802 lines
21 KiB
C

/****************************************************************************
* examples/adc/powerled_main.c
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Author: Mateusz Szafoni <raiden00@railab.me>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdbool.h>
#include <errno.h>
#include <debug.h>
#include <sys/ioctl.h>
#include <nuttx/fs/fs.h>
#include <nuttx/power/powerled.h>
#if defined(CONFIG_EXAMPLES_POWERLED)
#ifndef CONFIG_DRIVERS_POWERLED
# error "Powerled example requires powerled support"
#endif
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifndef CONFIG_EXAMPLES_POWERLED_CURRENT_LIMIT
# error "LED current limit must be set!"
#endif
#ifndef CONFIG_LIBC_FLOATINGPOINT
# error "CONFIG_LIBC_FLOATINGPOINT must be set!"
#endif
#define DEMO_CONT_BRIGHTNESS_MAX 100.0
#define DEMO_CONT_BRIGHTNESS_MIN 0.0
#define DEMO_CONT_BRIGHTNESS_STEP 10.0
#define DEMO_FLASH_FREQUENCY_STEP 0.5
#define DEMO_FLASH_FREQUENCY_MIN 1.0
#define DEMO_FLASH_FREQUENCY_MAX 5.0
#define DEMO_FLASH_DUTY_SET 50.0
#define DEMO_FLASH_BRIGHTNESS_SET 100.0
/****************************************************************************
* Private Type Definition
****************************************************************************/
/* Example modes */
enum powerled_main_mode_e
{
POWERLED_MAIN_DEMO = 0,
POWERLED_MAIN_CONT,
POWERLED_MAIN_FLASH
};
/* Application arguments */
struct args_s
{
uint8_t mode;
int time;
float duty;
float brightness;
float frequency;
};
/****************************************************************************
* Private Function Protototypes
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
struct args_s g_args;
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: powerled_help
****************************************************************************/
#ifdef CONFIG_NSH_BUILTIN_APPS
static void powerled_help(FAR struct args_s *args)
{
printf("Usage: powerled [OPTIONS]\n\n");
printf(" [-m mode] select mode\n");
printf(" 0 - demo mode [deafult]\n");
printf(" 1 - continuous mode\n");
printf(" 2 - flash mode\n");
printf(" [-d duty] selects duty cycle for flash mode in %%\n");
printf(" valid values from 0.0 to 100.0\n");
printf(" [-b brightness] selects LED brightness in %%\n");
printf(" valid values from 0.0 to 100.0\n");
printf(" [-f frequency] selects frequency for flash mode in Hz\n");
printf(" valid values greater than 0.0\n");
printf(" [-t time] selects time for continuous and flash mode in s\n");
printf(" valid values greater than 0 and\n");
printf(" -1 for infinity [default]\n");
printf("\n");
}
#endif
/****************************************************************************
* Name: arg_string
****************************************************************************/
#ifdef CONFIG_NSH_BUILTIN_APPS
static int arg_string(FAR char **arg, FAR char **value)
{
FAR char *ptr = *arg;
if (ptr[2] == '\0')
{
*value = arg[1];
return 2;
}
else
{
*value = &ptr[2];
return 1;
}
}
#endif
/****************************************************************************
* Name: arg_decimal
****************************************************************************/
#ifdef CONFIG_NSH_BUILTIN_APPS
static int arg_decimal(FAR char **arg, FAR int *value)
{
FAR char *string;
int ret;
ret = arg_string(arg, &string);
*value = atoi(string);
return ret;
}
#endif
/****************************************************************************
* Name: arg_float
****************************************************************************/
#ifdef CONFIG_NSH_BUILTIN_APPS
static int arg_float(FAR char **arg, FAR float *value)
{
FAR char *string;
int ret;
ret = arg_string(arg, &string);
*value = atof(string);
return ret;
}
#endif
/****************************************************************************
* Name: parse_args
****************************************************************************/
#ifdef CONFIG_NSH_BUILTIN_APPS
static void parse_args(FAR struct args_s *args, int argc, FAR char **argv)
{
FAR char *ptr;
int index;
int nargs;
int i_value;
float f_value;
for (index = 1; index < argc;)
{
ptr = argv[index];
if (ptr[0] != '-')
{
printf("Invalid options format: %s\n", ptr);
exit(0);
}
switch (ptr[1])
{
/* Get operation mode */
case 'm':
{
nargs = arg_decimal(&argv[index], &i_value);
index += nargs;
if ((i_value != POWERLED_MAIN_DEMO) &&
(i_value != POWERLED_MAIN_CONT) &&
(i_value != POWERLED_MAIN_FLASH))
{
printf("Unsupported mode %d\n", i_value);
exit(1);
}
args->mode = i_value;
break;
}
/* Get duty cycle */
case 'd':
{
nargs = arg_float(&argv[index], &f_value);
index += nargs;
if (f_value <= 0.0 || f_value > 100.0)
{
printf("Invalid duty value %.2f%%\n", f_value);
exit(1);
}
args->duty = f_value;
break;
}
/* Get LED brightness */
case 'b':
{
nargs = arg_float(&argv[index], &f_value);
index += nargs;
if (f_value <= 0.0 || f_value > 100.0)
{
printf("Invalid brightness value %.2f%%\n", f_value);
exit(1);
}
args->brightness = f_value;
break;
}
/* Get flashing frequency */
case 'f':
{
nargs = arg_float(&argv[index], &f_value);
index += nargs;
if (f_value <= 0.0)
{
printf("Invalid frequency value %.2f Hz\n", f_value);
exit(1);
}
args->frequency = f_value;
break;
}
/* Get work time */
case 't':
{
nargs = arg_decimal(&argv[index], &i_value);
index += nargs;
if (i_value <= 0)
{
printf("Invalid time value %d s\n", i_value);
exit(1);
}
args->time = i_value;
break;
}
/* Print help message */
case 'h':
{
powerled_help(args);
exit(0);
}
default:
{
printf("Unsupported option: %s\n", ptr);
powerled_help(args);
exit(1);
}
}
}
}
#endif
/****************************************************************************
* Name: validate_args
****************************************************************************/
#ifdef CONFIG_NSH_BUILTIN_APPS
static int validate_args(FAR struct args_s *args)
{
int ret = OK;
/* Validate parameters for demo mode */
if (args->mode == POWERLED_MAIN_DEMO)
{
printf("Powerled demo selected!\n");
/* Demo mode does not use time parameter */
args->time = -1;
}
/* Validate parameters for continuous mode */
if (args->mode == POWERLED_MAIN_CONT)
{
printf("Powerled continuous mode selected!\n");
printf(" brightnes: %.2f\n", args->brightness);
printf(" time: %d\n", args->time);
/* Needs brightness */
if (args->brightness <= 0.0)
{
printf("Continuous mode needs brightness parameter!\n");
ret = -EINVAL;
goto errout;
}
}
/* Validate parameters for flash mode */
if (args->mode == POWERLED_MAIN_FLASH)
{
printf("Powerled flash mode selected!\n");
printf(" brightness: %.2f\n", args->brightness);
printf(" frequency: %.2f\n", args->frequency);
printf(" duty: %.2f\n", args->duty);
printf(" time: %d\n", args->time);
/* Needs brightness */
if (args->brightness <= 0.0)
{
printf("Flash mode needs brightness parameter!\n");
ret = -EINVAL;
goto errout;
}
/* Needs frequency */
if (args->frequency <= 0.0)
{
printf("Flash mode needs frequency parameter!\n");
ret = -EINVAL;
goto errout;
}
/* Needs duty */
if (args->duty <= 0.0)
{
printf("Flash mode needs duty parameter!\n");
ret = -EINVAL;
goto errout;
}
}
errout:
return ret;
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: powerled_main
****************************************************************************/
int powerled_main(int argc, char *argv[])
{
struct powerled_limits_s powerled_limits;
struct powerled_params_s powerled_params;
struct powerled_state_s powerled_state;
struct args_s *args = &g_args;
uint8_t powerled_mode;
uint8_t demo;
bool terminate;
bool config;
int ret;
int fd = -1;
/* Initialize variables */
g_args.mode = POWERLED_MAIN_DEMO;
g_args.time = -1;
g_args.duty = 0.0;
g_args.brightness = 0.0;
g_args.frequency = 0.0;
demo = POWERLED_OPMODE_CONTINUOUS;
terminate = false;
config = true;
/* Initialize powerled stuctures */
memset(&powerled_limits, 0, sizeof(struct powerled_limits_s));
memset(&powerled_params, 0, sizeof(struct powerled_params_s));
/* Parse the command line */
#ifdef CONFIG_NSH_BUILTIN_APPS
parse_args(args, argc, argv);
#endif
/* Validate arguments */
#ifdef CONFIG_NSH_BUILTIN_APPS
ret = validate_args(args);
if (ret != OK)
{
printf("powerled_main: validate arguments failed!\n");
goto errout;
}
#endif
#ifndef CONFIG_NSH_BUILTIN_APPS
/* Perform architecture-specific initialization (if configured) */
(void)boardctl(BOARDIOC_INIT, 0);
#ifdef CONFIG_BOARDCTL_FINALINIT
/* Perform architecture-specific final-initialization (if configured) */
(void)boardctl(BOARDIOC_FINALINIT, 0);
#endif
#endif
/* Set LED current limit */
powerled_limits.current = (((float)CONFIG_EXAMPLES_POWERLED_CURRENT_LIMIT)/1000.0);
printf("\nStart powerled_main application!\n");
/* Open the Powerled driver */
fd = open(CONFIG_EXAMPLES_POWERLED_DEVPATH, 0);
if (fd <= 0)
{
printf("powerled_main: open %s failed %d\n", CONFIG_EXAMPLES_POWERLED_DEVPATH, errno);
goto errout;
}
/* Set LED current limit */
printf("Set max current: %.3f A\n", powerled_limits.current);
ret = ioctl(fd, PWRIOC_SET_LIMITS, (unsigned long)&powerled_limits);
if (ret < 0)
{
printf("failed to set limits %d. Force exit!\n", ret);
goto errout;
}
/* Main loop */
while (terminate != true)
{
switch (args->mode)
{
case POWERLED_MAIN_DEMO:
{
/* Continuous mode demo */
if (demo == POWERLED_OPMODE_CONTINUOUS)
{
if (config == true)
{
printf("\nConfigure continuous mode demo\n");
powerled_mode = POWERLED_OPMODE_CONTINUOUS;
/* Set Powerled continuous mode */
ret = ioctl(fd, PWRIOC_SET_MODE, (unsigned long)powerled_mode);
if (ret < 0)
{
printf("failed to set powerled mode %d \n", ret);
}
config = false;
}
printf("Brightness is %.2f\n", powerled_params.brightness);
/* Set Powerled parameters */
ret = ioctl(fd, PWRIOC_SET_PARAMS, (unsigned long)&powerled_params);
if (ret < 0)
{
printf("failed to set params %d \n", ret);
}
/* Start Powerled */
ret = ioctl(fd, PWRIOC_START, (unsigned long)0);
if (ret != OK)
{
printf("IOCTL PWRIOC_START failed %d!\n", ret);
}
/* Increase brightness */
powerled_params.brightness += DEMO_CONT_BRIGHTNESS_STEP;
/* Change mode if max brightness */
if (powerled_params.brightness > DEMO_CONT_BRIGHTNESS_MAX)
{
demo = POWERLED_OPMODE_FLASH;
config = true;
}
/* Next step after 1 second */
sleep(1);
}
if (demo == POWERLED_OPMODE_FLASH)
{
/* Flash mode demo */
if (config == true)
{
printf("\nConfigure flash mode demo\n");
powerled_params.brightness = DEMO_FLASH_BRIGHTNESS_SET;
powerled_params.duty = DEMO_FLASH_DUTY_SET;
powerled_params.frequency = DEMO_FLASH_FREQUENCY_MIN;
powerled_mode = POWERLED_OPMODE_FLASH;
/* Set Powerled flash mode */
ret = ioctl(fd, PWRIOC_SET_MODE, (unsigned long)powerled_mode);
if (ret < 0)
{
printf("failed to set powerled mode %d \n", ret);
}
printf("Brightness is %.2f\n", powerled_params.brightness);
printf("Duty is %.2f\n", powerled_params.duty);
config = false;
}
printf("Frequency is %.2f\n", powerled_params.frequency);
/* Set Powerled parameters */
ret = ioctl(fd, PWRIOC_SET_PARAMS, (unsigned long)&powerled_params);
if (ret < 0)
{
printf("failed to set params %d \n", ret);
}
/* Start Powerled */
ret = ioctl(fd, PWRIOC_START, (unsigned long)0);
if (ret != OK)
{
printf("IOCTL PWRIOC_START failed %d!\n", ret);
}
/* Increase flash frequency */
powerled_params.frequency += DEMO_FLASH_FREQUENCY_STEP;
/* Terinate demo if max frequency */
if (powerled_params.frequency > DEMO_FLASH_FREQUENCY_MAX)
{
terminate = true;
config = false;
}
/* Next step after 1 second */
sleep(2);
}
break;
}
case POWERLED_MAIN_CONT:
{
/* Configure only once */
if (config == true)
{
printf("\nStart Continuous mode!\n");
powerled_mode = POWERLED_OPMODE_CONTINUOUS;
/* Set Powerled continuous mode */
ret = ioctl(fd, PWRIOC_SET_MODE, (unsigned long)powerled_mode);
if (ret < 0)
{
printf("failed to set powerled mode %d \n", ret);
}
powerled_params.brightness = args->brightness;
powerled_params.duty = 0;
powerled_params.frequency = 0;
/* Set Powerled parameters */
ret = ioctl(fd, PWRIOC_SET_PARAMS, (unsigned long)&powerled_params);
if (ret < 0)
{
printf("failed to set params %d \n", ret);
}
/* Start Powerled */
ret = ioctl(fd, PWRIOC_START, (unsigned long)0);
if (ret != OK)
{
printf("IOCTL PWRIOC_START failed %d!\n", ret);
}
config = false;
}
break;
}
case POWERLED_MAIN_FLASH:
{
/* Configure only once */
if (config == true)
{
printf("\nStart Flash mode!\n");
powerled_mode = POWERLED_OPMODE_FLASH;
/* Set Powerled flash mode */
ret = ioctl(fd, PWRIOC_SET_MODE, (unsigned long)powerled_mode);
if (ret < 0)
{
printf("failed to set powerled mode %d \n", ret);
}
powerled_params.brightness = args->brightness;
powerled_params.duty = args->duty;
powerled_params.frequency = args->frequency;
/* Set Powerled parameters */
ret = ioctl(fd, PWRIOC_SET_PARAMS, (unsigned long)&powerled_params);
if (ret < 0)
{
printf("failed to set params %d \n", ret);
}
/* Start Powerled */
ret = ioctl(fd, PWRIOC_START, (unsigned long)0);
if (ret < 0)
{
printf("IOCTL PWRIOC_START failed %d!\n", ret);
}
config = false;
}
break;
}
default:
{
printf("Unsupported powerled mode %d!\n", args->mode);
goto errout;
}
}
/* Get driver state */
ret = ioctl(fd, PWRIOC_GET_STATE, (unsigned long)&powerled_state);
if (ret < 0)
{
printf("Failed to get state %d \n", ret);
}
/* Terminate if fault state */
if (powerled_state.state > POWERLED_STATE_RUN)
{
printf("Powerled state = %d, fault = %d\n", powerled_state.state,
powerled_state.fault);
terminate = true;
}
if (args->time != -1 && terminate != true)
{
printf("wait %d s ...\n", args->time);
/* Wait */
sleep(args->time);
/* Exit loop */
terminate = true;
}
}
errout:
fflush(stdout);
fflush(stderr);
if (fd > 0)
{
printf("Stop powerled driver\n");
/* Stop powerled driver */
ret = ioctl(fd, PWRIOC_STOP, (unsigned long)0);
if (ret != OK)
{
printf("IOCTL PWRIOC_STOP failed %d!\n", ret);
}
/* Close file */
close(fd);
}
return 0;
}
#endif /* CONFIG_EXAMPLE_POWERLED */