diff --git a/src/driver/drv_leds_shared.c b/src/driver/drv_leds_shared.c index c9ccbd1387..2342e2fc3c 100644 --- a/src/driver/drv_leds_shared.c +++ b/src/driver/drv_leds_shared.c @@ -13,14 +13,6 @@ static ledStrip_t led_backend; -enum ColorChannel { - COLOR_CHANNEL_RED, - COLOR_CHANNEL_GREEN, - COLOR_CHANNEL_BLUE, - COLOR_CHANNEL_COLD_WHITE, - COLOR_CHANNEL_WARM_WHITE -}; - #define DEFAULT_PIXEL_SIZE 3 const enum ColorChannel default_color_channel_order[3] = { COLOR_CHANNEL_RED, @@ -33,7 +25,16 @@ int pixel_size = DEFAULT_PIXEL_SIZE; // default is RGB -> 3 bytes per pixel // Number of pixels that can be addressed uint32_t pixel_count; -void SM16703P_GetPixel(uint32_t pixel, byte *dst) { +bool Strip_HasChannel(ColorChannel_t ch) { + for (int i = 0; i < pixel_size; i++) { + if (color_channel_order[i] == ch) { + return true; + } + } + return false; +} + +void Strip_GetPixel(uint32_t pixel, byte *dst) { int i; for (i = 0; i < pixel_size; i++) { @@ -42,19 +43,34 @@ void SM16703P_GetPixel(uint32_t pixel, byte *dst) { } bool Strip_VerifyPixel(uint32_t pixel, byte r, byte g, byte b) { - byte real[4]; - SM16703P_GetPixel(pixel, real); + byte real[5]; + Strip_GetPixel(pixel, real); + if (real[0] != r) + return false; + if (real[1] != g) + return false; + if (real[2] != b) + return false; + return true; +} +bool Strip_VerifyPixel5(uint32_t pixel, byte r, byte g, byte b, byte c, byte w) { + byte real[5]; + Strip_GetPixel(pixel, real); if (real[0] != r) return false; if (real[1] != g) return false; if (real[2] != b) return false; + if (real[3] != c) + return false; + if (real[4] != w) + return false; return true; } bool Strip_VerifyPixel4(uint32_t pixel, byte r, byte g, byte b, byte w) { - byte real[4]; - SM16703P_GetPixel(pixel, real); + byte real[5]; + Strip_GetPixel(pixel, real); if (real[0] != r) return false; if (real[1] != g) @@ -139,8 +155,8 @@ void Strip_scaleAllPixels(int scale) { byte *data, *input; for (pixel = 0; pixel < pixel_count; pixel++) { - for (ofs = 0; ofs < 3; ofs++) { - int byteIndex = pixel * 3 + ofs; + for (ofs = 0; ofs < pixel_size; ofs++) { + int byteIndex = pixel * pixel_size + ofs; byte b = led_backend.getByte(byteIndex); b = SCALE8_PIXEL(b, scale); led_backend.setByte(byteIndex, b); @@ -158,7 +174,7 @@ void Strip_setAllPixels(int r, int g, int b, int c, int w) { // SM16703P_SetRaw bUpdate byteOfs HexData // SM16703P_SetRaw 1 0 FF000000FF000000FF -commandResult_t SM16703P_CMD_setRaw(const void *context, const char *cmd, const char *args, int flags) { +commandResult_t Strip_CMD_setRaw(const void *context, const char *cmd, const char *args, int flags) { int ofs, bPush; Tokenizer_TokenizeString(args, 0); bPush = Tokenizer_GetArgInteger(0); @@ -176,7 +192,7 @@ commandResult_t SM16703P_CMD_setRaw(const void *context, const char *cmd, const } return CMD_RES_OK; } -commandResult_t SM16703P_CMD_setPixel(const void *context, const char *cmd, const char *args, int flags) { +commandResult_t Strip_CMD_setPixel(const void *context, const char *cmd, const char *args, int flags) { int i, r, g, b, c, w; int pixel = 0; const char *all = 0; @@ -199,13 +215,21 @@ commandResult_t SM16703P_CMD_setPixel(const void *context, const char *cmd, cons r = Tokenizer_GetArgIntegerRange(1, 0, 255); g = Tokenizer_GetArgIntegerRange(2, 0, 255); b = Tokenizer_GetArgIntegerRange(3, 0, 255); - c = 0; // cold white is optional for backward compatibility - if (Tokenizer_GetArgsCount() > 4) { - c = Tokenizer_GetArgIntegerRange(4, 0, 255); - } + c = 0; // cold white is optional for backward compatibility] w = 0; // warm white is optional for backward compatibility - if (Tokenizer_GetArgsCount() > 5) { - w = Tokenizer_GetArgIntegerRange(5, 0, 255); + int numArgs = Tokenizer_GetArgsCount(); + // this is a hack, so we can easily write commands for RGBW... + if (numArgs == 5 && Strip_HasChannel(COLOR_CHANNEL_WARM_WHITE)) { + // treat it as Warm (not Cool) + w = Tokenizer_GetArgIntegerRange(4, 0, 255); + } + else { + if (numArgs > 4) { + c = Tokenizer_GetArgIntegerRange(4, 0, 255); + } + if (numArgs > 5) { + w = Tokenizer_GetArgIntegerRange(5, 0, 255); + } } ADDLOG_INFO(LOG_FEATURE_CMD, "Set Pixel %i to R %i G %i B %i C %i W %i", pixel, r, g, b, c, w); @@ -223,7 +247,7 @@ commandResult_t SM16703P_CMD_setPixel(const void *context, const char *cmd, cons return CMD_RES_OK; } -commandResult_t SM16703P_InitForLEDCount(const void *context, const char *cmd, const char *args, int flags) { +commandResult_t Strip_CMD_InitForLEDCount(const void *context, const char *cmd, const char *args, int flags) { Tokenizer_TokenizeString(args, 0); @@ -292,7 +316,7 @@ bool Strip_IsActive() { void Strip_Apply() { led_backend.apply(); } -static commandResult_t SM16703P_StartTX(const void *context, const char *cmd, const char *args, int flags) { +static commandResult_t Strip_CMD_StartTX(const void *context, const char *cmd, const char *args, int flags) { Strip_Apply(); return CMD_RES_OK; } @@ -307,22 +331,26 @@ void LEDS_InitShared(ledStrip_t *api) { //cmddetail:"descr":"This will setup LED driver for a strip with given number of LEDs. Please note that it also works for WS2812B and similiar LEDs. You can optionally set the color order with can be any combination of R, G, B, C and W (e.g. RGBW or GRBWC, default is RGB). See [tutorial](https://www.elektroda.com/rtvforum/topic4036716.html).", //cmddetail:"fn":"SM16703P_InitForLEDCount","file":"driver/drv_leds_shared.c","requires":"", //cmddetail:"examples":""} - CMD_RegisterCommand("SM16703P_Init", SM16703P_InitForLEDCount, NULL); + CMD_RegisterCommand("SM16703P_Init", Strip_CMD_InitForLEDCount, NULL); + CMD_CreateAliasHelper("Strip_Init","SM16703P_Init"); //cmddetail:{"name":"SM16703P_Start","args":"", //cmddetail:"descr":"This will send the currently set data to the strip. Please note that it also works for WS2812B and similiar LEDs. See [tutorial](https://www.elektroda.com/rtvforum/topic4036716.html).", //cmddetail:"fn":"SM16703P_StartTX","file":"driver/drv_leds_shared.c","requires":"", //cmddetail:"examples":""} - CMD_RegisterCommand("SM16703P_Start", SM16703P_StartTX, NULL); + CMD_RegisterCommand("SM16703P_Start", Strip_CMD_StartTX, NULL); + CMD_CreateAliasHelper("Strip_Start", "SM16703P_Start"); //cmddetail:{"name":"SM16703P_SetPixel","args":"[index/all] [R] [G] [B]", //cmddetail:"descr":"Sets a pixel for LED strip. Index can be a number or 'all' keyword to set all. Then, 3 integer values for R, G and B. Please note that it also works for WS2812B and similiar LEDs. See [tutorial](https://www.elektroda.com/rtvforum/topic4036716.html).", //cmddetail:"fn":"SM16703P_CMD_setPixel","file":"driver/drv_leds_shared.c","requires":"", //cmddetail:"examples":""} - CMD_RegisterCommand("SM16703P_SetPixel", SM16703P_CMD_setPixel, NULL); + CMD_RegisterCommand("SM16703P_SetPixel", Strip_CMD_setPixel, NULL); + CMD_CreateAliasHelper("Strip_SetPixel", "SM16703P_SetPixel"); //cmddetail:{"name":"SM16703P_SetRaw","args":"[bUpdate] [byteOfs] [HexData]", //cmddetail:"descr":"Sets the raw data bytes for SPI DMA LED driver at the given offset. Hex data should be as a hex string, for example, FF00AA, etc. The bUpdate, if set to 1, will run SM16703P_Start automatically after setting data. Please note that it also works for WS2812B and similiar LEDs. See [tutorial](https://www.elektroda.com/rtvforum/topic4036716.html).", //cmddetail:"fn":"SM16703P_CMD_setRaw","file":"driver/drv_leds_shared.c","requires":"", //cmddetail:"examples":""} - CMD_RegisterCommand("SM16703P_SetRaw", SM16703P_CMD_setRaw, NULL); + CMD_RegisterCommand("SM16703P_SetRaw", Strip_CMD_setRaw, NULL); + CMD_CreateAliasHelper("Strip_SetRaw", "SM16703P_SetRaw"); //CMD_RegisterCommand("SM16703P_SendBytes", SM16703P_CMD_sendBytes, NULL); } diff --git a/src/driver/drv_leds_shared.h b/src/driver/drv_leds_shared.h index e0aad79941..1d28c7f92b 100644 --- a/src/driver/drv_leds_shared.h +++ b/src/driver/drv_leds_shared.h @@ -12,6 +12,13 @@ typedef struct ledStrip_s { void (*setLEDCount)(int pixel_count, int pixel_size); } ledStrip_t; +typedef enum ColorChannel { + COLOR_CHANNEL_RED, + COLOR_CHANNEL_GREEN, + COLOR_CHANNEL_BLUE, + COLOR_CHANNEL_COLD_WHITE, + COLOR_CHANNEL_WARM_WHITE +} ColorChannel_t; void LEDS_InitShared(ledStrip_t *api); void LEDS_ShutdownShared(); diff --git a/src/selftest/selftest_http.c b/src/selftest/selftest_http.c index 8fff6d2c76..412c394066 100644 --- a/src/selftest/selftest_http.c +++ b/src/selftest/selftest_http.c @@ -267,6 +267,10 @@ const char *Test_GetJSONValue_String(const char *keyword, const char *obj) { const char *Test_GetLastHTMLReply() { return replyAt; } +const char *Test_QueryHTMLReply(const char *url) { + Test_FakeHTTPClientPacket_GET(url); + return Test_GetLastHTMLReply(); +} void Test_Http_SingleRelayOnChannel1() { SIM_ClearOBK(0); diff --git a/src/selftest/selftest_led.c b/src/selftest/selftest_led.c index a7a0c1b79f..f821c1978e 100644 --- a/src/selftest/selftest_led.c +++ b/src/selftest/selftest_led.c @@ -557,7 +557,7 @@ void Test_LEDDriver_BP5758_RGBCW() { SIM_ClearOBK(0); Test_FakeHTTPClientPacket_GET("index"); - SELFTEST_ASSERT_HTML_REPLY_NOT_CONTAINS("LED RGB Color"); + SELFTEST_ASSERT_PAGE_NOT_CONTAINS("index","LED RGB Color"); SELFTEST_ASSERT_HTML_REPLY_NOT_CONTAINS("LED Temperature Slider"); CMD_ExecuteCommand("StartDriver BP5758D", 0); diff --git a/src/selftest/selftest_local.h b/src/selftest/selftest_local.h index f59cad2111..bd51176741 100644 --- a/src/selftest/selftest_local.h +++ b/src/selftest/selftest_local.h @@ -45,6 +45,13 @@ void SelfTest_Failed(const char *file, const char *function, int line, const cha #define SELFTEST_ASSERT_HTTP_HAS_BUTTON_LEDS_OFF(bHas) SELFTEST_ASSERT((bHas) == SIM_HasHTTP_LED_Toggler(false)); + + + + +#define SELFTEST_ASSERT_PAGE_NOT_CONTAINS(page,expected) SELFTEST_ASSERT(!(strstr(Test_QueryHTMLReply(page),expected))); +#define SELFTEST_ASSERT_PAGE_CONTAINS(page,expected) SELFTEST_ASSERT((strstr(Test_QueryHTMLReply(page),expected))); + #define SELFTEST_ASSERT_STRING(current,expected) SELFTEST_ASSERT((strcmp(expected,current) == 0)); #define SELFTEST_ASSERT_INTEGER(current,expected) SELFTEST_ASSERT((expected==current)); #define SELFTEST_ASSERT_HTML_REPLY(expected) SELFTEST_ASSERT((strcmp(Test_GetLastHTMLReply(),expected) == 0)); @@ -149,6 +156,7 @@ void Test_FakeHTTPClientPacket_POST(const char *tg, const char *data); void Test_FakeHTTPClientPacket_POST_withJSONReply(const char *tg, const char *data); void Test_FakeHTTPClientPacket_JSON(const char *tg); const char *Test_GetLastHTMLReply(); +const char *Test_QueryHTMLReply(const char *url); bool SIM_HasHTTPTemperature(); bool SIM_HasHTTPRGB(); diff --git a/src/selftest/selftest_ws2812b.c b/src/selftest/selftest_ws2812b.c index f126616a00..8eb406efbd 100644 --- a/src/selftest/selftest_ws2812b.c +++ b/src/selftest/selftest_ws2812b.c @@ -5,9 +5,12 @@ bool Strip_VerifyPixel(uint32_t pixel, byte r, byte g, byte b); bool Strip_VerifyPixel4(uint32_t pixel, byte r, byte g, byte b, byte a); +bool Strip_VerifyPixel5(uint32_t pixel, byte r, byte g, byte b, byte c, byte w); #define SELFTEST_ASSERT_PIXEL(index, r, g, b) SELFTEST_ASSERT(Strip_VerifyPixel(index, r, g, b)); #define SELFTEST_ASSERT_PIXEL4(index, r, g, b, w) SELFTEST_ASSERT(Strip_VerifyPixel4(index, r, g, b, w)); +#define SELFTEST_ASSERT_PIXEL5(index, r, g, b, c, w) SELFTEST_ASSERT(Strip_VerifyPixel5(index, r, g, b, c, w)); + void Strip_setMultiplePixel(uint32_t pixel, uint8_t *data, bool push); @@ -20,8 +23,15 @@ void Test_DMX_RGB() { SELFTEST_ASSERT_HAS_UART_EMPTY(); + SELFTEST_ASSERT_PAGE_NOT_CONTAINS("index", "LED RGB Color"); + SELFTEST_ASSERT_PAGE_NOT_CONTAINS("index", "LED Temperature Slider"); + CMD_ExecuteCommand("startDriver DMX", 0); - CMD_ExecuteCommand("SM16703P_Init 3", 0); + CMD_ExecuteCommand("Strip_Init 3", 0); + + SELFTEST_ASSERT_PAGE_CONTAINS("index", "LED RGB Color"); + SELFTEST_ASSERT_PAGE_NOT_CONTAINS("index", "LED Temperature Slider"); + CMD_ExecuteCommand("SM16703P_SetPixel all 255 0 128", 0); SELFTEST_ASSERT_PIXEL(0, 255, 0, 128); SELFTEST_ASSERT_PIXEL(1, 255, 0, 128); @@ -110,13 +120,13 @@ void Test_DMX_RGBC() { SELFTEST_ASSERT_HAS_UART_EMPTY(); CMD_ExecuteCommand("SM16703P_SetPixel 0 128 128 128 128", 0); - CMD_ExecuteCommand("SM16703P_SetPixel 1 255 255 255 255", 0); + CMD_ExecuteCommand("Strip_SetPixel 1 255 255 255 255", 0); CMD_ExecuteCommand("SM16703P_SetPixel 2 15 15 15 15", 0); SELFTEST_ASSERT_PIXEL4(0, 128, 128, 128, 128); SELFTEST_ASSERT_PIXEL4(1, 255, 255, 255, 255); SELFTEST_ASSERT_PIXEL4(2, 15, 15, 15, 15); SELFTEST_ASSERT_HAS_UART_EMPTY(); - CMD_ExecuteCommand("SM16703P_Start", 0); + CMD_ExecuteCommand("Strip_Start", 0); SELFTEST_ASSERT_HAS_SOME_DATA_IN_UART(); SELFTEST_ASSERT_HAS_SENT_UART_STRING("00 80808080 FFFFFFFF 0F0F0F0F"); // 512 channels, but checked already 12 @@ -129,37 +139,82 @@ void Test_DMX_RGBC() { } void Test_DMX_RGBW() { // reset whole device - //SIM_ClearOBK(0); + SIM_ClearOBK(0); - //SIM_UART_InitReceiveRingBuffer(4096); - //SIM_ClearUART(); + SIM_UART_InitReceiveRingBuffer(4096); + SIM_ClearUART(); - //SELFTEST_ASSERT_HAS_UART_EMPTY(); + SELFTEST_ASSERT_HAS_UART_EMPTY(); - //CMD_ExecuteCommand("startDriver DMX", 0); - //CMD_ExecuteCommand("SM16703P_Init 3 RGBW", 0); - //CMD_ExecuteCommand("SM16703P_SetPixel all 255 0 128 255", 0); - //SELFTEST_ASSERT_PIXEL4(0, 255, 0, 128, 255); - //SELFTEST_ASSERT_PIXEL4(1, 255, 0, 128, 255); - //SELFTEST_ASSERT_PIXEL4(2, 255, 0, 128, 255); + CMD_ExecuteCommand("startDriver DMX", 0); + CMD_ExecuteCommand("SM16703P_Init 3 RGBW", 0); + CMD_ExecuteCommand("SM16703P_SetPixel all 255 0 128 255", 0); + SELFTEST_ASSERT_PIXEL4(0, 255, 0, 128, 255); + SELFTEST_ASSERT_PIXEL4(1, 255, 0, 128, 255); + SELFTEST_ASSERT_PIXEL4(2, 255, 0, 128, 255); - //SELFTEST_ASSERT_HAS_UART_EMPTY(); + SELFTEST_ASSERT_HAS_UART_EMPTY(); + CMD_ExecuteCommand("SM16703P_Start", 0); + SELFTEST_ASSERT_HAS_SOME_DATA_IN_UART(); + SELFTEST_ASSERT_HAS_SENT_UART_STRING("00 FF0080FF FF0080FF FF0080FF"); + // 512 channels, but checked already 12 + for (int i = 0; i < 100; i++) { + SELFTEST_ASSERT_HAS_SENT_UART_STRING("00 00 00 00 00"); + } + SELFTEST_ASSERT_HAS_UART_EMPTY(); + + CMD_ExecuteCommand("SM16703P_SetPixel 0 128 128 128 128", 0); + CMD_ExecuteCommand("SM16703P_SetPixel 1 255 255 255 255", 0); + CMD_ExecuteCommand("SM16703P_SetPixel 2 15 15 15 15", 0); + SELFTEST_ASSERT_PIXEL4(0, 128, 128, 128, 128); + SELFTEST_ASSERT_PIXEL4(1, 255, 255, 255, 255); + SELFTEST_ASSERT_PIXEL4(2, 15, 15, 15, 15); + SELFTEST_ASSERT_HAS_UART_EMPTY(); //CMD_ExecuteCommand("SM16703P_Start", 0); //SELFTEST_ASSERT_HAS_SOME_DATA_IN_UART(); - //SELFTEST_ASSERT_HAS_SENT_UART_STRING("00 FF0080FF FF0080FF FF0080FF"); + //SELFTEST_ASSERT_HAS_SENT_UART_STRING("00 80808080 FFFFFFFF 0F0F0F0F"); //// 512 channels, but checked already 12 //for (int i = 0; i < 100; i++) { // SELFTEST_ASSERT_HAS_SENT_UART_STRING("00 00 00 00 00"); //} //SELFTEST_ASSERT_HAS_UART_EMPTY(); - //CMD_ExecuteCommand("SM16703P_SetPixel 0 128 128 128 128", 0); - //CMD_ExecuteCommand("SM16703P_SetPixel 1 255 255 255 255", 0); - //CMD_ExecuteCommand("SM16703P_SetPixel 2 15 15 15 15", 0); - //SELFTEST_ASSERT_PIXEL4(0, 128, 128, 128, 128); - //SELFTEST_ASSERT_PIXEL4(1, 255, 255, 255, 255); - //SELFTEST_ASSERT_PIXEL4(2, 15, 15, 15, 15); - //SELFTEST_ASSERT_HAS_UART_EMPTY(); + // nothing is sent by OBK at that point +} +void Test_DMX_RGBCW() { + // reset whole device + SIM_ClearOBK(0); + + SIM_UART_InitReceiveRingBuffer(4096); + SIM_ClearUART(); + + SELFTEST_ASSERT_HAS_UART_EMPTY(); + + CMD_ExecuteCommand("startDriver DMX", 0); + CMD_ExecuteCommand("SM16703P_Init 3 RGBCW", 0); + CMD_ExecuteCommand("SM16703P_SetPixel all 255 0 128 255 128", 0); + SELFTEST_ASSERT_PIXEL5(0, 255, 0, 128, 255, 128); + SELFTEST_ASSERT_PIXEL5(1, 255, 0, 128, 255, 128); + SELFTEST_ASSERT_PIXEL5(2, 255, 0, 128, 255, 128); + + SELFTEST_ASSERT_HAS_UART_EMPTY(); + CMD_ExecuteCommand("SM16703P_Start", 0); + SELFTEST_ASSERT_HAS_SOME_DATA_IN_UART(); + SELFTEST_ASSERT_HAS_SENT_UART_STRING("00 FF0080FF80 FF0080FF80 FF0080FF80"); + // 512 channels, but checked already 12+3 + SELFTEST_ASSERT_HAS_SENT_UART_STRING("00 00"); + for (int i = 0; i < 99; i++) { + SELFTEST_ASSERT_HAS_SENT_UART_STRING("00 00 00 00 00"); + } + SELFTEST_ASSERT_HAS_UART_EMPTY(); + + CMD_ExecuteCommand("SM16703P_SetPixel 0 128 128 128 128 11", 0); + CMD_ExecuteCommand("SM16703P_SetPixel 1 255 255 255 255 22", 0); + CMD_ExecuteCommand("SM16703P_SetPixel 2 15 15 15 15 33", 0); + SELFTEST_ASSERT_PIXEL5(0, 128, 128, 128, 128, 11); + SELFTEST_ASSERT_PIXEL5(1, 255, 255, 255, 255, 22); + SELFTEST_ASSERT_PIXEL5(2, 15, 15, 15, 15, 33); + SELFTEST_ASSERT_HAS_UART_EMPTY(); //CMD_ExecuteCommand("SM16703P_Start", 0); //SELFTEST_ASSERT_HAS_SOME_DATA_IN_UART(); //SELFTEST_ASSERT_HAS_SENT_UART_STRING("00 80808080 FFFFFFFF 0F0F0F0F"); @@ -453,6 +508,7 @@ void Test_LEDstrips() { Test_DMX_RGB(); Test_DMX_RGBC(); Test_DMX_RGBW(); + Test_DMX_RGBCW(); Test_WS2812B(); } diff --git a/src/sim/Controller_WS2812.cpp b/src/sim/Controller_WS2812.cpp index f904a51ded..b890f7d047 100644 --- a/src/sim/Controller_WS2812.cpp +++ b/src/sim/Controller_WS2812.cpp @@ -4,7 +4,7 @@ #include "Junction.h" extern "C" { - bool SM16703P_GetPixel(uint32_t pixel, byte *dst); + bool Strip_GetPixel(uint32_t pixel, byte *dst); } void CControllerWS2812::setShapesActive(bool b) { @@ -26,7 +26,7 @@ void CControllerWS2812::onDrawn() { if (b->getDepth() < idx) idx = b->getDepth(); //printf("%i - depth %i\n", this, idx); - SM16703P_GetPixel(idx, rgb); + Strip_GetPixel(idx, rgb); col_green.fromRGB(rgb); setShapesActive(true); setShapesFillColor(col_green);