From 72eac8048a09458395c4b9a4ae1af35cffc4694f Mon Sep 17 00:00:00 2001 From: Dominic Clifton Date: Fri, 19 Sep 2014 00:08:40 +0100 Subject: [PATCH] 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 --- src/main/common/color.h | 14 +++++--- src/main/io/ledstrip.c | 53 +++++++++++++++++++++++++++++- src/main/io/ledstrip.h | 5 ++- src/main/io/serial_cli.c | 38 +++++++++++++++++++++ src/test/unit/ledstrip_unittest.cc | 45 +++++++++++++++++++++++++ 5 files changed, 148 insertions(+), 7 deletions(-) diff --git a/src/main/common/color.h b/src/main/common/color.h index 42e83ad4e..76027754f 100644 --- a/src/main/common/color.h +++ b/src/main/common/color.h @@ -37,16 +37,20 @@ typedef union { uint8_t raw[RGB_COLOR_COMPONENT_COUNT]; } rgbColor24bpp_t; +#define HSV_HUE_MAX 359 +#define HSV_SATURATION_MAX 255 +#define HSV_VALUE_MAX 255 + typedef enum { - HSV_RED = 0, - HSV_GREEN, - HSV_BLUE + HSV_HUE = 0, + HSV_SATURATION, + HSV_VALUE } hsvColorComponent_e; -#define HSV_COLOR_COMPONENT_COUNT (HSV_BLUE + 1) +#define HSV_COLOR_COMPONENT_COUNT (HSV_VALUE + 1) typedef struct hsvColor_s { - uint16_t h; // 0 - 360 + uint16_t h; // 0 - 359 uint8_t s; // 0 - 255 uint8_t v; // 0 - 255 } hsvColor_t; diff --git a/src/main/io/ledstrip.c b/src/main/io/ledstrip.c index 509d2634b..696bfe8a5 100644 --- a/src/main/io/ledstrip.c +++ b/src/main/io/ledstrip.c @@ -54,7 +54,7 @@ static failsafe_t* failsafe; #error "Led strip length must match driver" #endif -static hsvColor_t *colors; +hsvColor_t *colors; //#define USE_LED_ANIMATION @@ -756,6 +756,57 @@ void updateLedStrip(void) 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) { memset(colors, 0, colorCount * sizeof(colors)); diff --git a/src/main/io/ledstrip.h b/src/main/io/ledstrip.h index a01aa3bf5..3f7365f0a 100644 --- a/src/main/io/ledstrip.h +++ b/src/main/io/ledstrip.h @@ -58,6 +58,9 @@ extern uint8_t ledCount; bool parseLedStripConfig(uint8_t ledIndex, const char *config); void updateLedStrip(void); -void applyDefaultColors(hsvColor_t *colors, uint8_t colorCount); + void applyDefaultLedStripConfig(ledConfig_t *ledConfig); 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); diff --git a/src/main/io/serial_cli.c b/src/main/io/serial_cli.c index b93f2099a..c0b774fe3 100644 --- a/src/main/io/serial_cli.c +++ b/src/main/io/serial_cli.c @@ -80,6 +80,7 @@ static void cliGpsPassthrough(char *cmdline); static void cliHelp(char *cmdline); static void cliMap(char *cmdline); static void cliLed(char *cmdline); +static void cliColor(char *cmdline); static void cliMixer(char *cmdline); static void cliMotor(char *cmdline); static void cliProfile(char *cmdline); @@ -137,6 +138,9 @@ typedef struct { const clicmd_t cmdTable[] = { { "aux", "feature_name auxflag or blank for list", cliAux }, { "cmix", "design custom mixer", cliCMix }, +#ifdef LED_STRIP + { "color", "configure colors", cliColor }, +#endif { "defaults", "reset to defaults and reboot", cliDefaults }, { "dump", "print configurable settings in a pastable form", cliDump }, { "exit", "", cliExit }, @@ -146,7 +150,9 @@ const clicmd_t cmdTable[] = { { "gpspassthrough", "passthrough gps to serial", cliGpsPassthrough }, #endif { "help", "", cliHelp }, +#ifdef LED_STRIP { "led", "configure leds", cliLed }, +#endif { "map", "mapping of rc channel order", cliMap }, { "mixer", "mixer name or list", cliMixer }, { "motor", "get/set motor output value", cliMotor }, @@ -530,6 +536,35 @@ static void cliLed(char *cmdline) #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) { uint32_t i; @@ -634,6 +669,9 @@ static void cliDump(char *cmdline) #ifdef LED_STRIP printf("\r\n\r\n# led\r\n"); cliLed(""); + + printf("\r\n\r\n# color\r\n"); + cliColor(""); #endif printSectionBreak(); dumpValues(MASTER_VALUE); diff --git a/src/test/unit/ledstrip_unittest.cc b/src/test/unit/ledstrip_unittest.cc index 90d6530c7..2415207d0 100644 --- a/src/test/unit/ledstrip_unittest.cc +++ b/src/test/unit/ledstrip_unittest.cc @@ -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; uint16_t flightModeFlags = 0; int16_t rcCommand[4];