Add example app for LP503x LED driver

Update examples/lp503x/lp503x_main.c

Move struct lp503x_cmd_s to private types section

Update examples/lp503x/lp503x_main.c

Update examples/lp503x/lp503x_main.c

Update examples/lp503x/lp503x_main.c

Update examples/lp503x/lp503x_main.c

Update examples/lp503x/lp503x_main.c

Update examples/lp503x/lp503x_main.c

Update examples/lp503x/lp503x_main.c

Update examples/lp503x/lp503x_main.c

Update examples/lp503x/lp503x_main.c

Update examples/lp503x/lp503x_main.c

Update examples/lp503x/lp503x_main.c

Update examples/lp503x/lp503x_main.c

Update examples/lp503x/lp503x_main.c

Update examples/lp503x/lp503x_main.c

Update examples/lp503x/lp503x_main.c

Update examples/lp503x/lp503x_main.c

Update examples/lp503x/lp503x_main.c

Update examples/lp503x/lp503x_main.c

Co-Authored-By: Petro Karashchenko <petro.karashchenko@gmail.com>
This commit is contained in:
TimJTi 2022-12-21 16:10:57 +00:00 committed by Xiang Xiao
parent 2ad05e3062
commit 9d1a70af86
4 changed files with 806 additions and 0 deletions

33
examples/lp503x/Kconfig Executable file
View File

@ -0,0 +1,33 @@
#
# For a description of the syntax of this configuration file,
# see the file kconfig-language.txt in the NuttX tools repository.
#
config EXAMPLES_LP503X
tristate "LP503X PWM LED example"
default n
---help---
Enable the LP503X example
if EXAMPLES_LP503X
config EXAMPLES_LP503X_PROGNAME
string "Program name"
default "lp503x"
---help---
This is the name of the program that will be used when the NSH ELF
program is installed.
config EXAMPLES_LP503X_DEVPATH
string "LP503X device path"
default "/dev/leddrv0"
config EXAMPLES_LP503X_PRIORITY
int "lp503x task priority"
default 100
config EXAMPLES_LP503X_STACKSIZE
int "lp503x stack size"
default DEFAULT_TASK_STACKSIZE
endif

23
examples/lp503x/Make.defs Executable file
View File

@ -0,0 +1,23 @@
############################################################################
# apps/examples/lp503x/Make.defs
#
# 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.
#
############################################################################
ifneq ($(CONFIG_EXAMPLES_LP503X),)
CONFIGURED_APPS += $(APPDIR)/examples/lp503x
endif

34
examples/lp503x/Makefile Executable file
View File

@ -0,0 +1,34 @@
############################################################################
# apps/examples/lp5036/Makefile
#
# 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.
#
############################################################################
include $(APPDIR)/Make.defs
# LP503x built-in application info
PROGNAME = $(CONFIG_EXAMPLES_LP503X_PROGNAME)
PRIORITY = $(CONFIG_EXAMPLES_LP503X_PRIORITY)
STACKSIZE = $(CONFIG_EXAMPLES_LP503X_STACKSIZE)
MODULE = $(CONFIG_EXAMPLES_LP503X)
# LP503x Test
MAINSRC = lp503x_main.c
include $(APPDIR)/Application.mk

716
examples/lp503x/lp503x_main.c Executable file
View File

@ -0,0 +1,716 @@
/****************************************************************************
* 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 "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;
}