nuttx-apps/examples/lp503x/lp503x_main.c
Xiang Xiao a29d9ea9da fsutils/examples: Include unistd.h explicitly
to get the prototypes or macros are defined in it

Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
2023-02-05 08:46:59 +02:00

719 lines
18 KiB
C

/****************************************************************************
* apps/examples/lp503x/lp503x_main.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 <nuttx/config.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include "system/readline.h"
#include <nuttx/leds/lp503x.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define LP503X_HELP_TEXT(x) x
/****************************************************************************
* Private Types
****************************************************************************/
typedef CODE int (*lp503x_func)(FAR char *pargs);
struct lp503x_cmd_s
{
FAR const char *cmd; /* The command text */
FAR const char *arghelp; /* Text describing the args */
lp503x_func pfunc; /* Pointer to command handler */
FAR const char *help; /* The help text */
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static int lp503x_cmd_quit(FAR char *parg);
static int lp503x_cmd_help(FAR char *parg);
static int lp503x_cmd_set_rgbled(FAR char *parg);
static int lp503x_cmd_setled(FAR char *parg);
static int lp503x_cmd_setcolour(FAR char *parg);
static int lp503x_cmd_pattern(FAR char *parg);
static int lp503x_cmd_brightness(FAR char *parg);
static int lp503x_cmd_mode(FAR char *parg);
static int lp503x_cmd_disable(FAR char *parg);
static int lp503x_cmd_set_bank_mode(FAR char *parg);
static int lp503x_cmd_set_banka_colour(FAR char *parg);
static int lp503x_cmd_set_bankb_colour(FAR char *parg);
static int lp503x_cmd_set_bankc_colour(FAR char *parg);
static int lp503x_cmd_set_bank_brightness(FAR char *parg);
static int lp503x_cmd_set_individual_mode(FAR char *parg);
/****************************************************************************
* Private Data
****************************************************************************/
int fd;
static struct lp503x_cmd_s g_lp503x_cmds[] =
{
{
"q",
"",
lp503x_cmd_quit,
LP503X_HELP_TEXT("Exit lp503x")
},
{
"h",
"",
lp503x_cmd_help,
LP503X_HELP_TEXT("Display help for commands")
},
{
"?",
"",
lp503x_cmd_help,
LP503X_HELP_TEXT("Display help for commands")
},
{
"help",
"",
lp503x_cmd_help,
LP503X_HELP_TEXT("Display help for commands")
},
{
"m",
"",
lp503x_cmd_mode,
LP503X_HELP_TEXT("send default mode to the device")
},
{
"c",
"hex",
lp503x_cmd_setcolour,
LP503X_HELP_TEXT("Hex RGB colour required")
},
{
"l",
"led, 0..11",
lp503x_cmd_set_rgbled,
LP503X_HELP_TEXT("set RGB LED selected to current colour")
},
{
"n",
"led, 0..35",
lp503x_cmd_setled,
LP503X_HELP_TEXT("set individual LED to current brightness X")
},
{
"p",
"num of leds in pattern (1..12)",
lp503x_cmd_pattern,
LP503X_HELP_TEXT("play LED pattern")
},
{
"b",
"brightness, 0-255",
lp503x_cmd_brightness,
LP503X_HELP_TEXT("set brightness of all leds")
},
{
"d",
"disable=1",
lp503x_cmd_disable,
LP503X_HELP_TEXT("globally disable ALL leds")
},
{
"k",
"led num",
lp503x_cmd_set_bank_mode,
LP503X_HELP_TEXT("enable bank mode for LED ")
},
{
"i",
"led num 0..11",
lp503x_cmd_set_individual_mode,
LP503X_HELP_TEXT("enable individual mode for LED ")
},
{
"A",
"",
lp503x_cmd_set_banka_colour,
LP503X_HELP_TEXT("set bankA colour")
},
{
"B",
"",
lp503x_cmd_set_bankb_colour,
LP503X_HELP_TEXT("set bankB colour")
},
{
"C",
"",
lp503x_cmd_set_bankc_colour,
LP503X_HELP_TEXT("set bankC colour")
},
{
"X",
"0..255",
lp503x_cmd_set_bank_brightness,
LP503X_HELP_TEXT("Bank or individual LED brightness required")
},
};
static const int g_lp503x_cmd_count = sizeof(g_lp503x_cmds) /
sizeof(struct lp503x_cmd_s);
FAR static struct lp503x_config_s *lp503x_config;
FAR static struct ioctl_arg_s *lp503x_ioctl_args;
int current_colour;
int current_led_brightness;
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name:lp503x_cmd_mode
*
* send default (Kconfig) mode/config to the device
****************************************************************************/
static int lp503x_cmd_mode(FAR char *parg)
{
return ioctl(fd, PWMIOC_CONFIG, lp503x_config);
}
/****************************************************************************
* Name:lp503x_cmd_quit
*
* lp503x_cmd_quit() terminates the application
****************************************************************************/
static int lp503x_cmd_quit(FAR char *parg)
{
return OK;
}
/****************************************************************************
* Name:lp503x_cmd_disable
*
* Globally disable all LEDS
****************************************************************************/
static int lp503x_cmd_disable(FAR char *parg)
{
return ioctl(fd, PWMIOC_ENABLE, atoi(parg)) ;
}
/****************************************************************************
* Name:lp503x_setled
*
* sets the chosen led (0..35) to the current brightness (0..255) (T)
****************************************************************************/
static int lp503x_cmd_setled(FAR char *parg)
{
int ret;
int lednum;
lednum = atoi(parg);
if (lednum > MAX_LEDS)
{
printf("ERROR: led number must be in range 0..35\n");
ret = -EINVAL;
}
else
{
lp503x_ioctl_args->lednum = lednum;
lp503x_ioctl_args->param = current_led_brightness;
ret = ioctl(fd, PWMIOC_SET_LED_COLOUR, lp503x_ioctl_args);
}
return ret;
}
/****************************************************************************
* Name:lp503x_setRGBled
*
* sets the chosen RGB led (0..11) to the current RGB colour
****************************************************************************/
static int lp503x_cmd_set_rgbled(FAR char *parg)
{
int ret;
int lednum;
lednum = atoi(parg);
if (lednum > MAX_RGB_LEDS)
{
printf("ERROR: RGB led must be in range 0..11\n");
ret = -EINVAL;
}
else
{
lp503x_ioctl_args->lednum = lednum;
lp503x_ioctl_args->param = current_colour;
ret = ioctl(fd, PWMIOC_SET_RGB_COLOUR, lp503x_ioctl_args);
}
return ret;
}
/****************************************************************************
* Name:lp503x_cmd_set_bank_mode
*
* sets requested led to use "bank" mode
****************************************************************************/
static int lp503x_cmd_set_bank_mode(FAR char *parg)
{
int ret;
int lednum;
lednum = atoi(parg);
if (lednum > MAX_RGB_LEDS)
{
printf("ERROR: RGB led must be in range 0..11\n");
ret = -EINVAL;
}
else
{
lp503x_ioctl_args->param = LP503X_LED_BANK_MODE_ENABLED;
lp503x_ioctl_args->lednum = lednum;
ret = ioctl(fd, PWMIOC_ENABLE_LED_BANK_MODE, lp503x_ioctl_args);
}
return ret;
}
/****************************************************************************
* Name:lp503x_cmd_set_individual_mode
*
* sets requested led to use "individual" mode (default)
****************************************************************************/
static int lp503x_cmd_set_individual_mode(FAR char *parg)
{
int ret;
int lednum;
lednum = atoi(parg);
if (lednum > MAX_RGB_LEDS)
{
printf("ERROR: RGB led must be in range 0..11\n");
ret = -EINVAL;
}
else
{
lp503x_ioctl_args->param = LP503X_LED_BANK_MODE_DISABLED;
lp503x_ioctl_args->lednum = lednum;
ret = ioctl(fd, PWMIOC_ENABLE_LED_BANK_MODE, lp503x_ioctl_args);
}
return ret;
}
/****************************************************************************
* Name:lp503x_cmd_set_bank?_colour
*
* sets bank A/B/C to the current brightness (T)
****************************************************************************/
static int lp503x_cmd_set_banka_colour(FAR char *parg)
{
uint8_t requested_colour;
requested_colour = atoi(parg);
if ((requested_colour > MAX_BRIGHTNESS) || (requested_colour < 0))
{
printf("ERR: Bank Colour (mix percent) must be in range 0..255\n");
return -EINVAL;
}
else
{
lp503x_ioctl_args->param = requested_colour;
lp503x_ioctl_args->lednum = 'A';
return ioctl(fd, PWMIOC_SET_BANK_MIX_COLOUR, lp503x_ioctl_args);
}
}
static int lp503x_cmd_set_bankb_colour(FAR char *parg)
{
uint8_t requested_colour;
requested_colour = atoi(parg);
if ((requested_colour > MAX_BRIGHTNESS) || (requested_colour < 0))
{
printf("ERR: Bank Colour (mix percent) must be in range 0..255\n");
return -EINVAL;
}
else
{
lp503x_ioctl_args->param = requested_colour;
lp503x_ioctl_args->lednum = 'B';
return ioctl(fd, PWMIOC_SET_BANK_MIX_COLOUR, lp503x_ioctl_args);
}
}
static int lp503x_cmd_set_bankc_colour(FAR char *parg)
{
uint8_t requested_colour;
requested_colour = atoi(parg);
if ((requested_colour > MAX_BRIGHTNESS) || (requested_colour < 0))
{
printf("ERR: Bank Colour (mix percent) must be in range 0..255\n");
return -EINVAL;
}
else
{
lp503x_ioctl_args->param = requested_colour;
lp503x_ioctl_args->lednum = 'C';
return ioctl(fd, PWMIOC_SET_BANK_MIX_COLOUR, lp503x_ioctl_args);
}
}
/****************************************************************************
* Name:lp503x_cmd_brightness
*
* sets all RGB led to the requested brightness
****************************************************************************/
static int lp503x_cmd_brightness(FAR char *parg)
{
int ret;
int lednum;
int requested_brightness;
requested_brightness = ((int)strtol(parg, NULL, 0)) & 0xff;
if ((requested_brightness > 255) || (requested_brightness < 0))
{
printf("ERROR: brightness must be in range 0..255\n");
ret = -EINVAL;
}
else
{
lp503x_ioctl_args->param = requested_brightness;
for (lednum = 0; lednum < 12; lednum++)
{
lp503x_ioctl_args->lednum = lednum;
ret = ioctl(fd, PWMIOC_SET_RGB_BRIGHTNESS, lp503x_ioctl_args);
}
}
return ret;
}
/****************************************************************************
* Name:lp503x_cmd_pattern
*
* run a pattern for "arg[0]" leds.
* Repeats 5 times at different brightness levels
****************************************************************************/
static int lp503x_cmd_pattern(FAR char *parg)
{
int ret;
int numleds;
int i;
int j;
uint8_t k;
int colour_lookup[12] =
{
0x0000ff, 0x00ff00, 0xff0000,
0x00ffff, 0xff00ff, 0xffff33,
0xffffff, 0xffa500, 0xff00a5,
0x8080ff, 0x80ff80, 0xff8080
};
int pattern_brightness[5] =
{
50, 100, 150, 200, 255
};
int curcolour;
numleds = atoi(parg);
if ((numleds > 12) || (numleds < 1))
{
printf("Error: number of leds should be between 1 and 12\n");
return -EINVAL;
}
curcolour = 0;
for (i = 0; i < 5; i++)
{
for (j = 0; j < numleds; j++)
{
lp503x_ioctl_args->lednum = j;
lp503x_ioctl_args->param = pattern_brightness[i];
ret = ioctl(fd, PWMIOC_SET_RGB_BRIGHTNESS, lp503x_ioctl_args);
curcolour++;
if (curcolour >= numleds)
{
curcolour = 0;
}
lp503x_ioctl_args->param = colour_lookup[curcolour];
ret = ioctl(fd, PWMIOC_SET_RGB_COLOUR, lp503x_ioctl_args);
}
usleep(500000);
curcolour++;
}
lp503x_ioctl_args->param = 0;
for (k = 0; k < numleds; k++)
{
lp503x_ioctl_args->lednum = k;
ret = ioctl(fd, PWMIOC_SET_RGB_COLOUR, lp503x_ioctl_args);
}
return ret;
}
/****************************************************************************
* Name:lp503x_cmd_set_bank_brightness
*
* sets the bank brightness to be used
****************************************************************************/
static int lp503x_cmd_set_bank_brightness(FAR char *parg)
{
int bank_brightness;
if (parg != NULL || *parg != '\0')
{
bank_brightness = atoi(parg);
if ((bank_brightness > MAX_BRIGHTNESS) || (bank_brightness < 0))
{
printf("bank brightness range is 0..255\n");
bank_brightness = 0;
return -EINVAL;
}
else
{
lp503x_ioctl_args->param = bank_brightness;
current_led_brightness = bank_brightness;
return ioctl(fd, PWMIOC_SET_BANK_BRIGHTNESS, lp503x_ioctl_args);
}
}
return OK;
}
/****************************************************************************
* Name:lp503x_setcolour
*
* sets the current RGB colour to be used
****************************************************************************/
static int lp503x_cmd_setcolour(FAR char *parg)
{
int colour;
if (parg == NULL || *parg != '\0')
{
printf("current colour is: 0x%06x\n", current_colour);
}
else
{
colour = (int)strtol(parg, NULL, 16);
if (colour > MAX_RGB_COLOUR)
{
printf("colour range is 0...0xFFFFFF\n");
current_colour = 0;
return -EINVAL;
}
else
{
current_colour = colour;
printf("colour set to: 0x%06x\n", current_colour);
}
}
return OK;
}
/****************************************************************************
* Name: lp503x_cmd_help
*
* lp503x_cmd_help() displays the application's help information on
* supported commands and command syntax.
****************************************************************************/
static int lp503x_cmd_help(FAR char *parg)
{
int len;
int maxlen = 0;
int x;
int c;
/* Calculate length of longest cmd + arghelp */
for (x = 0; x < g_lp503x_cmd_count; x++)
{
len = strlen(g_lp503x_cmds[x].cmd) +
strlen(g_lp503x_cmds[x].arghelp);
if (len > maxlen)
{
maxlen = len;
}
}
printf("lp503x commands\n================\n");
for (x = 0; x < g_lp503x_cmd_count; x++)
{
/* Print the command and it's arguments */
printf(" %s %s", g_lp503x_cmds[x].cmd,
g_lp503x_cmds[x].arghelp);
/* Calculate number of spaces to print before the help text */
len = maxlen - (strlen(g_lp503x_cmds[x].cmd) +
strlen(g_lp503x_cmds[x].arghelp));
for (c = 0; c < len; c++)
{
printf(" ");
}
printf(" : %s\n", g_lp503x_cmds[x].help);
}
return OK;
}
/****************************************************************************
* lp503x_main
****************************************************************************/
int main(int argc, FAR char *argv[])
{
bool running;
char buffer[CONFIG_NSH_LINELEN];
int len;
int x;
char *cmd;
char *arg;
fd = open(CONFIG_EXAMPLES_LP503X_DEVPATH, O_CREAT);
if (fd < 0)
{
fprintf(stderr, "ERROR: Failed to open %s: %d\n",
CONFIG_EXAMPLES_LP503X_DEVPATH, errno);
close(fd);
return ENODEV;
}
running = true;
while (running)
{
printf("lp503x> ");
fflush(stdout);
/* read a line from the terminal */
len = readline(buffer, sizeof(buffer), stdin, stdout);
buffer[len] = '\0';
if (len > 0)
{
if (strncmp(buffer, "!", 1) != 0)
{
/* a command */
if (buffer[len - 1] == '\n')
{
buffer[len - 1] = '\0';
}
/* Parse the command from the argument */
cmd = strtok_r(buffer, " \n", &arg);
if (cmd == NULL)
{
continue;
}
/* Remove leading spaces from arg */
while (*arg == ' ')
{
arg++;
}
/* Find the command in our cmd array */
for (x = 0; x < g_lp503x_cmd_count; x++)
{
if (strcmp(cmd, g_lp503x_cmds[x].cmd) == 0)
{
/* Command found. Call it's handler if not NULL */
if (g_lp503x_cmds[x].pfunc != NULL)
{
g_lp503x_cmds[x].pfunc(arg);
}
/* Test if it is a quit command */
if (g_lp503x_cmds[x].pfunc == lp503x_cmd_quit)
{
running = FALSE;
}
break;
}
}
}
else
{
#ifdef CONFIG_SYSTEM_SYSTEM
/* Transfer nuttx shell */
system(buffer + 1);
#else
printf("%s: unknown lp503x command\n", buffer);
#endif
}
}
}
close(fd);
return 0;
}