929f1009c7
Reference: https://man.openbsd.org/readline.3 Signed-off-by: chao an <anchao@xiaomi.com>
720 lines
18 KiB
C
720 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_stream(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;
|
|
}
|