mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-19 14:25:20 +03:00
Allow colors to be configurable via the cli.
color x h,s,v x = 0-15 h = 0-359 s = 0-255 v = 0-255
This commit is contained in:
parent
4b06592ce7
commit
72eac8048a
5 changed files with 148 additions and 7 deletions
|
@ -37,16 +37,20 @@ typedef union {
|
||||||
uint8_t raw[RGB_COLOR_COMPONENT_COUNT];
|
uint8_t raw[RGB_COLOR_COMPONENT_COUNT];
|
||||||
} rgbColor24bpp_t;
|
} rgbColor24bpp_t;
|
||||||
|
|
||||||
|
#define HSV_HUE_MAX 359
|
||||||
|
#define HSV_SATURATION_MAX 255
|
||||||
|
#define HSV_VALUE_MAX 255
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
HSV_RED = 0,
|
HSV_HUE = 0,
|
||||||
HSV_GREEN,
|
HSV_SATURATION,
|
||||||
HSV_BLUE
|
HSV_VALUE
|
||||||
} hsvColorComponent_e;
|
} hsvColorComponent_e;
|
||||||
|
|
||||||
#define HSV_COLOR_COMPONENT_COUNT (HSV_BLUE + 1)
|
#define HSV_COLOR_COMPONENT_COUNT (HSV_VALUE + 1)
|
||||||
|
|
||||||
typedef struct hsvColor_s {
|
typedef struct hsvColor_s {
|
||||||
uint16_t h; // 0 - 360
|
uint16_t h; // 0 - 359
|
||||||
uint8_t s; // 0 - 255
|
uint8_t s; // 0 - 255
|
||||||
uint8_t v; // 0 - 255
|
uint8_t v; // 0 - 255
|
||||||
} hsvColor_t;
|
} hsvColor_t;
|
||||||
|
|
|
@ -54,7 +54,7 @@ static failsafe_t* failsafe;
|
||||||
#error "Led strip length must match driver"
|
#error "Led strip length must match driver"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static hsvColor_t *colors;
|
hsvColor_t *colors;
|
||||||
|
|
||||||
//#define USE_LED_ANIMATION
|
//#define USE_LED_ANIMATION
|
||||||
|
|
||||||
|
@ -756,6 +756,57 @@ void updateLedStrip(void)
|
||||||
ws2811UpdateStrip();
|
ws2811UpdateStrip();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool parseColor(uint8_t index, char *colorConfig)
|
||||||
|
{
|
||||||
|
char *remainingCharacters = colorConfig;
|
||||||
|
|
||||||
|
hsvColor_t *color = &colors[index];
|
||||||
|
|
||||||
|
bool ok = true;
|
||||||
|
|
||||||
|
uint8_t componentIndex;
|
||||||
|
for (componentIndex = 0; ok && componentIndex < HSV_COLOR_COMPONENT_COUNT; componentIndex++) {
|
||||||
|
uint16_t val = atoi(remainingCharacters);
|
||||||
|
switch (componentIndex) {
|
||||||
|
case HSV_HUE:
|
||||||
|
if (val > HSV_HUE_MAX) {
|
||||||
|
ok = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
colors[index].h = val;
|
||||||
|
break;
|
||||||
|
case HSV_SATURATION:
|
||||||
|
if (val > HSV_SATURATION_MAX) {
|
||||||
|
ok = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
colors[index].s = (uint8_t)val;
|
||||||
|
break;
|
||||||
|
case HSV_VALUE:
|
||||||
|
if (val > HSV_VALUE_MAX) {
|
||||||
|
ok = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
colors[index].v = (uint8_t)val;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
remainingCharacters = strstr(remainingCharacters, ",");
|
||||||
|
if (remainingCharacters) {
|
||||||
|
remainingCharacters++;
|
||||||
|
} else {
|
||||||
|
if (componentIndex < 2) {
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ok) {
|
||||||
|
memset(color, 0, sizeof(hsvColor_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
void applyDefaultColors(hsvColor_t *colors, uint8_t colorCount)
|
void applyDefaultColors(hsvColor_t *colors, uint8_t colorCount)
|
||||||
{
|
{
|
||||||
memset(colors, 0, colorCount * sizeof(colors));
|
memset(colors, 0, colorCount * sizeof(colors));
|
||||||
|
|
|
@ -58,6 +58,9 @@ extern uint8_t ledCount;
|
||||||
|
|
||||||
bool parseLedStripConfig(uint8_t ledIndex, const char *config);
|
bool parseLedStripConfig(uint8_t ledIndex, const char *config);
|
||||||
void updateLedStrip(void);
|
void updateLedStrip(void);
|
||||||
void applyDefaultColors(hsvColor_t *colors, uint8_t colorCount);
|
|
||||||
void applyDefaultLedStripConfig(ledConfig_t *ledConfig);
|
void applyDefaultLedStripConfig(ledConfig_t *ledConfig);
|
||||||
void generateLedConfig(uint8_t ledIndex, char *ledConfigBuffer, size_t bufferSize);
|
void generateLedConfig(uint8_t ledIndex, char *ledConfigBuffer, size_t bufferSize);
|
||||||
|
|
||||||
|
bool parseColor(uint8_t index, char *colorConfig);
|
||||||
|
void applyDefaultColors(hsvColor_t *colors, uint8_t colorCount);
|
||||||
|
|
|
@ -80,6 +80,7 @@ static void cliGpsPassthrough(char *cmdline);
|
||||||
static void cliHelp(char *cmdline);
|
static void cliHelp(char *cmdline);
|
||||||
static void cliMap(char *cmdline);
|
static void cliMap(char *cmdline);
|
||||||
static void cliLed(char *cmdline);
|
static void cliLed(char *cmdline);
|
||||||
|
static void cliColor(char *cmdline);
|
||||||
static void cliMixer(char *cmdline);
|
static void cliMixer(char *cmdline);
|
||||||
static void cliMotor(char *cmdline);
|
static void cliMotor(char *cmdline);
|
||||||
static void cliProfile(char *cmdline);
|
static void cliProfile(char *cmdline);
|
||||||
|
@ -137,6 +138,9 @@ typedef struct {
|
||||||
const clicmd_t cmdTable[] = {
|
const clicmd_t cmdTable[] = {
|
||||||
{ "aux", "feature_name auxflag or blank for list", cliAux },
|
{ "aux", "feature_name auxflag or blank for list", cliAux },
|
||||||
{ "cmix", "design custom mixer", cliCMix },
|
{ "cmix", "design custom mixer", cliCMix },
|
||||||
|
#ifdef LED_STRIP
|
||||||
|
{ "color", "configure colors", cliColor },
|
||||||
|
#endif
|
||||||
{ "defaults", "reset to defaults and reboot", cliDefaults },
|
{ "defaults", "reset to defaults and reboot", cliDefaults },
|
||||||
{ "dump", "print configurable settings in a pastable form", cliDump },
|
{ "dump", "print configurable settings in a pastable form", cliDump },
|
||||||
{ "exit", "", cliExit },
|
{ "exit", "", cliExit },
|
||||||
|
@ -146,7 +150,9 @@ const clicmd_t cmdTable[] = {
|
||||||
{ "gpspassthrough", "passthrough gps to serial", cliGpsPassthrough },
|
{ "gpspassthrough", "passthrough gps to serial", cliGpsPassthrough },
|
||||||
#endif
|
#endif
|
||||||
{ "help", "", cliHelp },
|
{ "help", "", cliHelp },
|
||||||
|
#ifdef LED_STRIP
|
||||||
{ "led", "configure leds", cliLed },
|
{ "led", "configure leds", cliLed },
|
||||||
|
#endif
|
||||||
{ "map", "mapping of rc channel order", cliMap },
|
{ "map", "mapping of rc channel order", cliMap },
|
||||||
{ "mixer", "mixer name or list", cliMixer },
|
{ "mixer", "mixer name or list", cliMixer },
|
||||||
{ "motor", "get/set motor output value", cliMotor },
|
{ "motor", "get/set motor output value", cliMotor },
|
||||||
|
@ -530,6 +536,35 @@ static void cliLed(char *cmdline)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cliColor(char *cmdline)
|
||||||
|
{
|
||||||
|
#ifndef LED_STRIP
|
||||||
|
UNUSED(cmdline);
|
||||||
|
#else
|
||||||
|
int i;
|
||||||
|
uint8_t len;
|
||||||
|
char *ptr;
|
||||||
|
|
||||||
|
len = strlen(cmdline);
|
||||||
|
if (len == 0) {
|
||||||
|
for (i = 0; i < CONFIGURABLE_COLOR_COUNT; i++) {
|
||||||
|
printf("color %u %d,%u,%u\r\n", i, masterConfig.colors[i].h, masterConfig.colors[i].s, masterConfig.colors[i].v);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ptr = cmdline;
|
||||||
|
i = atoi(ptr);
|
||||||
|
if (i < CONFIGURABLE_COLOR_COUNT) {
|
||||||
|
ptr = strchr(cmdline, ' ');
|
||||||
|
if (!parseColor(i, ++ptr)) {
|
||||||
|
printf("Parse error\r\n", CONFIGURABLE_COLOR_COUNT);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf("Invalid color index: must be < %u\r\n", CONFIGURABLE_COLOR_COUNT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void dumpValues(uint8_t mask)
|
static void dumpValues(uint8_t mask)
|
||||||
{
|
{
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
@ -634,6 +669,9 @@ static void cliDump(char *cmdline)
|
||||||
#ifdef LED_STRIP
|
#ifdef LED_STRIP
|
||||||
printf("\r\n\r\n# led\r\n");
|
printf("\r\n\r\n# led\r\n");
|
||||||
cliLed("");
|
cliLed("");
|
||||||
|
|
||||||
|
printf("\r\n\r\n# color\r\n");
|
||||||
|
cliColor("");
|
||||||
#endif
|
#endif
|
||||||
printSectionBreak();
|
printSectionBreak();
|
||||||
dumpValues(MASTER_VALUE);
|
dumpValues(MASTER_VALUE);
|
||||||
|
|
|
@ -286,6 +286,51 @@ TEST(LedStripTest, smallestGrid)
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
hsvColor_t testColors[CONFIGURABLE_COLOR_COUNT];
|
||||||
|
|
||||||
|
extern hsvColor_t *colors;
|
||||||
|
|
||||||
|
#define TEST_COLOR_COUNT 4
|
||||||
|
|
||||||
|
TEST(ColorTest, parseColor)
|
||||||
|
{
|
||||||
|
// given
|
||||||
|
colors = testColors;
|
||||||
|
memset(colors, 0, sizeof(colors) * CONFIGURABLE_COLOR_COUNT);
|
||||||
|
|
||||||
|
// and
|
||||||
|
const hsvColor_t expectedColors[TEST_COLOR_COUNT] = {
|
||||||
|
// H S V
|
||||||
|
{ 0, 0, 0 },
|
||||||
|
{ 1, 1, 1 },
|
||||||
|
{ 360, 255, 255 },
|
||||||
|
{ 333, 22, 1 }
|
||||||
|
};
|
||||||
|
|
||||||
|
char *testColors[TEST_COLOR_COUNT] = {
|
||||||
|
"0,0,0",
|
||||||
|
"1,1,1",
|
||||||
|
"360,255,255",
|
||||||
|
"333,22,1"
|
||||||
|
};
|
||||||
|
|
||||||
|
// when
|
||||||
|
for (uint8_t index = 0; index < TEST_COLOR_COUNT; index++) {
|
||||||
|
printf("parse iteration: %d\n", index);
|
||||||
|
parseColor(index, testColors[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// then
|
||||||
|
|
||||||
|
for (uint8_t index = 0; index < TEST_COLOR_COUNT; index++) {
|
||||||
|
printf("iteration: %d\n", index);
|
||||||
|
|
||||||
|
EXPECT_EQ(expectedColors[index].h, colors[index].h);
|
||||||
|
EXPECT_EQ(expectedColors[index].s, colors[index].s);
|
||||||
|
EXPECT_EQ(expectedColors[index].v, colors[index].v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t armingFlags = 0;
|
uint8_t armingFlags = 0;
|
||||||
uint16_t flightModeFlags = 0;
|
uint16_t flightModeFlags = 0;
|
||||||
int16_t rcCommand[4];
|
int16_t rcCommand[4];
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue