merge LED strip backend separation before DMX support

* stub

* clear

* clear upo

* one more test

* split

* fx

* Update drv_led_shared.c

* step

* split

* Update drv_leds_shared.c

* Update selftest_ws2812b.c

* port

* dmx

* DMX

* s

* with test

* fix

* fx

* ChType_Ph test and RGBW test

* ddp formats unfinished

* Update selftest_ws2812b.c

* Update selftest_hass_discovery_ext.c

* fxes
This commit is contained in:
openshwprojects
2025-08-28 21:52:59 +02:00
committed by GitHub
parent f9134dd3ac
commit 670798a83a
18 changed files with 678 additions and 336 deletions

View File

@@ -217,6 +217,7 @@
<ClCompile Include="src\driver\drv_debouncer.c" />
<ClCompile Include="src\driver\drv_dht.c" />
<ClCompile Include="src\driver\drv_dht_internal.c" />
<ClCompile Include="src\driver\drv_dmx512.c" />
<ClCompile Include="src\driver\drv_ds1820_full.c" />
<ClCompile Include="src\driver\drv_ds1820_common.c" />
<ClCompile Include="src\driver\drv_doorSensorWithDeepSleep.c" />
@@ -231,6 +232,7 @@
<ClCompile Include="src\driver\drv_ir.cpp" />
<ClCompile Include="src\driver\drv_kp18058.c" />
<ClCompile Include="src\driver\drv_kp18068.c" />
<ClCompile Include="src\driver\drv_leds_shared.c" />
<ClCompile Include="src\driver\drv_main.c" />
<ClCompile Include="src\driver\drv_max6675.c" />
<ClCompile Include="src\driver\drv_max72xx_clock.c" />

View File

@@ -408,6 +408,8 @@
<ClCompile Include="src\driver\drv_spi_flash.c" />
<ClCompile Include="src\hal\win32\hal_ota_win32.c" />
<ClCompile Include="src\driver\drv_tca9554.c" />
<ClCompile Include="src\driver\drv_leds_shared.c" />
<ClCompile Include="src\driver\drv_dmx512.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\base64\base64.h" />

View File

@@ -114,6 +114,7 @@ set(OBKM_SRC
${OBK_SRCS}driver/drv_soft_spi.c
${OBK_SRCS}driver/drv_sm15155e.c
${OBK_SRCS}driver/drv_sm16703P.c
${OBK_SRCS}driver/drv_leds_shared.c
${OBK_SRCS}driver/drv_spi.c
${OBK_SRCS}driver/drv_spiLED.c
${OBK_SRCS}driver/drv_spi_flash.c

View File

@@ -128,6 +128,7 @@ OBKM_SRC += $(OBK_SRCS)driver/drv_shiftRegister.c
OBKM_SRC += $(OBK_SRCS)driver/drv_sht3x.c
OBKM_SRC += $(OBK_SRCS)driver/drv_sm15155e.c
OBKM_SRC += $(OBK_SRCS)driver/drv_sm16703P.c
OBKM_SRC += $(OBK_SRCS)driver/drv_leds_shared.c
OBKM_SRC += $(OBK_SRCS)driver/drv_sm2135.c
OBKM_SRC += $(OBK_SRCS)driver/drv_sm2235.c
OBKM_SRC += $(OBK_SRCS)driver/drv_soft_i2c.c

View File

@@ -124,19 +124,23 @@ void DDP_Parse(byte *data, int len) {
if(len > 12) {
byte r, g, b;
r = data[10];
g = data[11];
b = data[12];
// This is done by WLED, but not checked in Tasmota
// data type 0x1B (formerly 0x1A) is RGBW (type 3, 8 bit/channel)
byte bytesPerPixel = ((data[2] & 0b00111000) >> 3 == 0b011) ? 4 : 3;
#if ENABLE_DRIVER_SM16703P
if (spiLED.ready) {
// Note that this is limited by DDP msgbuf size
uint32_t pixel = (len - 10) / 3;
uint32_t numPixels = (len - 10) / 3;
// This immediately activates the pixels, maybe we should read the PUSH flag
SM16703P_setMultiplePixel(pixel, &data[10], true);
SM16703P_setMultiplePixel(numPixels, &data[10], true);
} else
#endif
{
r = data[10];
g = data[11];
b = data[12];
#if ENABLE_LED_BASIC
LED_SetDimmerIfChanged(100);
if (data[9] == 4) {

86
src/driver/drv_dmx512.c Normal file
View File

@@ -0,0 +1,86 @@
#include "../new_cfg.h"
#include "../new_common.h"
#include "../new_pins.h"
// Commands register, execution API and cmd tokenizer
#include "../cmnds/cmd_public.h"
#include "../hal/hal_pins.h"
#include "../httpserver/new_http.h"
#include "../logging/logging.h"
#include "../mqtt/new_mqtt.h"
#if ENABLE_DRIVER_DMX
#include "drv_leds_shared.h"
#include "drv_local.h"
#define DMX_CHANNELS_SIZE 512
#define DMX_BUFFER_SIZE (DMX_CHANNELS_SIZE+1)
static byte *g_dmxBuffer;
static int dmx_pixelCount = 0;
static int dmx_pixelSize = 3;
int dmx_pin = 0;
void DMX_Show() {
// BREAK: pull TX low manually
HAL_PIN_Setup_Output(dmx_pin);
HAL_PIN_SetOutputValue(dmx_pin, 0);
HAL_Delay_us(120); // ≥88µs
HAL_PIN_SetOutputValue(dmx_pin, 1);
HAL_Delay_us(12); // MAB ≥8µs
// restore UART and send DMX data
HAL_UART_Init(250000, 2, true);
for (int i = 0; i < DMX_BUFFER_SIZE; i++) {
HAL_UART_SendByte(g_dmxBuffer[i]);
}
//Serial485.begin(250000, SERIAL_8N2, RS485_RX_PIN, RS485_TX_PIN);
////Serial485.write(dmxBuffer, sizeof(dmxBuffer));
//Serial485.flush();
}
byte DMX_GetByte(uint32_t idx) {
if (idx >= DMX_CHANNELS_SIZE)
return 0;
return g_dmxBuffer[1 + idx];
}
void DMX_setByte(int idx, byte color) {
if (idx >= DMX_CHANNELS_SIZE)
return 0;
g_dmxBuffer[1 + idx] = color;
}
void DMX_SetLEDCount(int pixel_count, int pixel_size) {
dmx_pixelCount = pixel_count;
dmx_pixelSize = pixel_size;
}
void DMX_Init() {
g_dmxBuffer = (byte*)malloc(DMX_BUFFER_SIZE);
memset(g_dmxBuffer, 0, DMX_BUFFER_SIZE);
ledStrip_t ws_export;
ws_export.apply = DMX_Show;
ws_export.getByte = DMX_GetByte;
ws_export.setByte = DMX_setByte;
ws_export.setLEDCount = DMX_SetLEDCount;
LEDS_InitShared(&ws_export);
}
void DMX_OnEverySecond() {
}
void DMX_Shutdown() {
if (g_dmxBuffer) {
free(g_dmxBuffer);
g_dmxBuffer = 0;
}
LEDS_ShutdownShared();
}
#endif

View File

@@ -0,0 +1,325 @@
#include "../new_cfg.h"
#include "../new_common.h"
#include "../new_pins.h"
// Commands register, execution API and cmd tokenizer
#include "../cmnds/cmd_public.h"
#include "../hal/hal_pins.h"
#include "../httpserver/new_http.h"
#include "../logging/logging.h"
#include "../mqtt/new_mqtt.h"
#include "drv_local.h"
#include "drv_leds_shared.h"
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,
COLOR_CHANNEL_GREEN,
COLOR_CHANNEL_BLUE
};
enum ColorChannel *color_channel_order = default_color_channel_order;
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) {
int i;
for (i = 0; i < pixel_size; i++) {
dst[i] = led_backend.getByte(pixel * pixel_size + i);
}
}
bool SM16703P_VerifyPixel(uint32_t pixel, byte r, byte g, byte b) {
byte real[4];
SM16703P_GetPixel(pixel, real);
if (real[0] != r)
return false;
if (real[1] != g)
return false;
if (real[2] != b)
return false;
return true;
}
bool SM16703P_VerifyPixel4(uint32_t pixel, byte r, byte g, byte b, byte w) {
byte real[4];
SM16703P_GetPixel(pixel, real);
if (real[0] != r)
return false;
if (real[1] != g)
return false;
if (real[2] != b)
return false;
if (real[3] != w)
return false;
return true;
}
void SM16703P_setPixel(int pixel, int r, int g, int b, int c, int w) {
if (pixel < 0 || pixel >= pixel_count) {
return; // out of range - would crash
}
int i;
for (i = 0; i < pixel_size; i++)
{
byte pcolor;
switch (color_channel_order[i])
{
case COLOR_CHANNEL_RED:
pcolor = r;
break;
case COLOR_CHANNEL_GREEN:
pcolor = g;
break;
case COLOR_CHANNEL_BLUE:
pcolor = b;
break;
case COLOR_CHANNEL_COLD_WHITE:
pcolor = c;
break;
case COLOR_CHANNEL_WARM_WHITE:
pcolor = w;
break;
default:
ADDLOG_ERROR(LOG_FEATURE_CMD, "Unknown color channel %d at index %d", color_channel_order[i], i);
return;
}
led_backend.setByte(i + (pixel * pixel_size), pcolor);
}
}
void SM16703P_setMultiplePixel(uint32_t pixel, uint8_t *data, bool push) {
// Check max pixel
if (pixel > pixel_count)
pixel = pixel_count;
// Iterate over pixel
for (uint32_t i = 0; i < pixel; i++) {
uint8_t r, g, b;
r = *data++;
g = *data++;
b = *data++;
// TODO: Not sure how this works. Should we add Cold and Warm white here as well?
SM16703P_setPixel((int)i, (int)r, (int)g, (int)b, 0, 0);
}
if (push) {
SM16703P_Show();
}
}
extern float g_brightness0to100;//TODO
void SM16703P_setPixelWithBrig(int pixel, int r, int g, int b, int c, int w) {
// scale brightness
#if ENABLE_LED_BASIC
r = (int)(r * g_brightness0to100*0.01f);
g = (int)(g * g_brightness0to100*0.01f);
b = (int)(b * g_brightness0to100*0.01f);
c = (int)(c * g_brightness0to100*0.01f);
w = (int)(w * g_brightness0to100*0.01f);
#endif
SM16703P_setPixel(pixel, r, g, b, c, w);
}
#define SCALE8_PIXEL(x, scale) (uint8_t)(((uint32_t)x * (uint32_t)scale) / 256)
void SM16703P_scaleAllPixels(int scale) {
int pixel;
byte b;
int ofs;
byte *data, *input;
for (pixel = 0; pixel < pixel_count; pixel++) {
for (ofs = 0; ofs < 3; ofs++) {
int byteIndex = pixel * 3 + ofs;
byte b = led_backend.getByte(byteIndex);
b = SCALE8_PIXEL(b, scale);
led_backend.setByte(byteIndex, b);
}
}
}
void SM16703P_setAllPixels(int r, int g, int b, int c, int w) {
int pixel;
for (pixel = 0; pixel < pixel_count; pixel++) {
SM16703P_setPixel(pixel, r, g, b, c, 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) {
int ofs, bPush;
Tokenizer_TokenizeString(args, 0);
bPush = Tokenizer_GetArgInteger(0);
ofs = Tokenizer_GetArgInteger(1);
const char *s = Tokenizer_GetArg(2);
int i = 0;
// parse hex string like FFAABB0011 byte by byte
while (s[0] && s[1]) {
led_backend.setByte(i, hexbyte(s));
i++;
s += 2;
}
if (bPush) {
led_backend.apply();
}
return CMD_RES_OK;
}
commandResult_t SM16703P_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;
Tokenizer_TokenizeString(args, 0);
if (Tokenizer_GetArgsCount() < 4) {
// We need at least 4 arguments: pixel, red, green, blue - cold and warm white are optional
ADDLOG_INFO(LOG_FEATURE_CMD, "Not Enough Arguments for init SM16703P: Amount of LEDs missing");
return CMD_RES_NOT_ENOUGH_ARGUMENTS;
}
all = Tokenizer_GetArg(0);
if (*all == 'a') {
}
else {
pixel = Tokenizer_GetArgInteger(0);
all = 0;
}
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);
}
w = 0; // warm white is optional for backward compatibility
if (Tokenizer_GetArgsCount() > 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);
if (all) {
for (i = 0; i < pixel_count; i++) {
SM16703P_setPixel(i, r, g, b, c, w);
}
}
else {
SM16703P_setPixel(pixel, r, g, b, c, w);
}
return CMD_RES_OK;
}
commandResult_t SM16703P_InitForLEDCount(const void *context, const char *cmd, const char *args, int flags) {
Tokenizer_TokenizeString(args, 0);
if (Tokenizer_GetArgsCount() == 0) {
ADDLOG_INFO(LOG_FEATURE_CMD, "Not Enough Arguments for init SM16703P: Amount of LEDs missing");
return CMD_RES_NOT_ENOUGH_ARGUMENTS;
}
SM16703P_Shutdown();
// First arg: number of pixel to address
pixel_count = Tokenizer_GetArgIntegerRange(0, 0, 255);
// Second arg (optional, default "RGB"): pixel format of "RGB" or "GRB"
if (Tokenizer_GetArgsCount() > 1) {
const char *format = Tokenizer_GetArg(1);
size_t format_length = strlen(format);
enum ColorChannel *new_channel_order = os_malloc(sizeof(enum ColorChannel) * (format_length + 1));
if (!new_channel_order) {
ADDLOG_ERROR(LOG_FEATURE_CMD, "Failed to allocate memory for color channel order");
return CMD_RES_ERROR;
}
int i = 0;
for (const char *p = format; *p; p++) {
switch (*p) {
case 'R':
new_channel_order[i++] = COLOR_CHANNEL_RED;
break;
case 'G':
new_channel_order[i++] = COLOR_CHANNEL_GREEN;
break;
case 'B':
new_channel_order[i++] = COLOR_CHANNEL_BLUE;
break;
case 'C':
new_channel_order[i++] = COLOR_CHANNEL_COLD_WHITE;
break;
case 'W':
new_channel_order[i++] = COLOR_CHANNEL_WARM_WHITE;
break;
default:
ADDLOG_ERROR(LOG_FEATURE_CMD, "Invalid color '%c' in format '%s', should be combination of R,G,B,C,W", *p, format);
os_free(new_channel_order);
return CMD_RES_ERROR;
}
}
pixel_size = i; // number of color channels
color_channel_order = new_channel_order;
}
led_backend.setLEDCount(pixel_count, pixel_size);
ADDLOG_INFO(LOG_FEATURE_CMD, "Register driver with %i LEDs", pixel_count);
return CMD_RES_OK;
}
static commandResult_t SM16703P_StartTX(const void *context, const char *cmd, const char *args, int flags) {
led_backend.apply();
return CMD_RES_OK;
}
// startDriver SM16703P
// backlog startDriver SM16703P; SM16703P_Test
void LEDS_InitShared(ledStrip_t *api) {
led_backend = *api;
//cmddetail:{"name":"SM16703P_Init","args":"[NumberOfLEDs][ColorOrder]",
//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":"NULL);","file":"driver/drv_sm16703P.c","requires":"",
//cmddetail:"examples":""}
CMD_RegisterCommand("SM16703P_Init", SM16703P_InitForLEDCount, NULL);
//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":"NULL);","file":"driver/drv_sm16703P.c","requires":"",
//cmddetail:"examples":""}
CMD_RegisterCommand("SM16703P_Start", SM16703P_StartTX, NULL);
//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":"NULL);","file":"driver/drv_sm16703P.c","requires":"",
//cmddetail:"examples":""}
CMD_RegisterCommand("SM16703P_SetPixel", SM16703P_CMD_setPixel, NULL);
//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":"NULL);","file":"driver/drv_sm16703P.c","requires":"",
//cmddetail:"examples":""}
CMD_RegisterCommand("SM16703P_SetRaw", SM16703P_CMD_setRaw, NULL);
//CMD_RegisterCommand("SM16703P_SendBytes", SM16703P_CMD_sendBytes, NULL);
}
void LEDS_ShutdownShared() {
if (color_channel_order != default_color_channel_order) {
os_free(color_channel_order);
color_channel_order = default_color_channel_order;
}
pixel_size = DEFAULT_PIXEL_SIZE;
}

View File

@@ -0,0 +1,19 @@
#ifndef __DRV_LED_SHARED_H__
#define __DRV_LED_SHARED_H__
#include "../new_cfg.h"
#include "../new_common.h"
#include "../new_pins.h"
typedef struct ledStrip_s {
byte (*getByte)(uint32_t pixel);
void (*setByte)(uint32_t idx, byte val);
void (*apply)();
void (*setLEDCount)(int pixel_count, int pixel_size);
} ledStrip_t;
void LEDS_InitShared(ledStrip_t *api);
void LEDS_ShutdownShared();
#endif

View File

@@ -190,6 +190,10 @@ void TCA9554_Init();
void TCA9554_OnEverySecond();
void TCA9554_OnChannelChanged(int ch, int value);
void DMX_Init();
void DMX_OnEverySecond();
void DMX_Shutdown();
void PWMG_Init();
void Freeze_Init();

View File

@@ -53,6 +53,13 @@ static driver_t g_drivers[] = {
//drvdetail:"requires":""}
{ "TCA9554", TCA9554_Init, TCA9554_OnEverySecond, NULL, NULL, NULL, TCA9554_OnChannelChanged , NULL, false },
#endif
#if ENABLE_DRIVER_DMX
//drvdetail:{"name":"DMX",
//drvdetail:"title":"TODO",
//drvdetail:"descr":"DMX.",
//drvdetail:"requires":""}
{ "DMX", DMX_Init, DMX_OnEverySecond, NULL, NULL, DMX_Shutdown, NULL , NULL, false },
#endif
#if ENABLE_DRIVER_FREEZE
//drvdetail:{"name":"FREEZE",
//drvdetail:"title":"TODO",

View File

@@ -10,272 +10,35 @@
#if ENABLE_DRIVER_SM16703P
#include "drv_leds_shared.h"
#include "drv_local.h"
#include "drv_spiLED.h"
// Number of pixels that can be addressed
uint32_t pixel_count;
void SM16703P_GetPixel(uint32_t pixel, byte *dst) {
int i;
uint8_t *input;
void SM16703P_Show() {
if (spiLED.ready == 0)
return;
SPIDMA_StartTX(spiLED.msg);
}
byte SM16703P_GetByte(uint32_t idx) {
if (spiLED.msg == 0)
return 0;
if (spiLED.ready == 0)
return 0;
byte *input = spiLED.buf + spiLED.ofs + idx * 4;
byte ret = reverse_translate_byte(input);
return ret;
}
void SM16703P_setByte(int index, byte color) {
if (spiLED.buf == 0)
return;
input = spiLED.buf + spiLED.ofs + (pixel * 3 * 4);
for (i = 0; i < 3; i++) {
*dst++ = reverse_translate_byte(input + i * 4);
}
}
enum ColorChannel {
COLOR_CHANNEL_RED,
COLOR_CHANNEL_GREEN,
COLOR_CHANNEL_BLUE,
COLOR_CHANNEL_COLD_WHITE,
COLOR_CHANNEL_WARM_WHITE
};
const enum ColorChannel default_color_channel_order[3] = {
COLOR_CHANNEL_RED,
COLOR_CHANNEL_GREEN,
COLOR_CHANNEL_BLUE
};
enum ColorChannel *color_channel_order = default_color_channel_order;
int pixel_size = 3; // default is RGB -> 3 bytes per pixel
bool SM16703P_VerifyPixel(uint32_t pixel, byte r, byte g, byte b) {
byte real[3];
SM16703P_GetPixel(pixel, real);
if (real[0] != r)
return false;
if (real[1] != g)
return false;
if (real[2] != b)
return false;
return true;
}
void SM16703P_setPixel(int pixel, int r, int g, int b, int c, int w) {
if (!spiLED.ready)
if (spiLED.ready == 0)
return;
if(pixel < 0 || pixel >= pixel_count) {
return; // out of range - would crash
}
int i;
for(i = 0; i < pixel_size; i++)
{
int pcolor;
switch (color_channel_order[i])
{
case COLOR_CHANNEL_RED:
pcolor = r;
break;
case COLOR_CHANNEL_GREEN:
pcolor = g;
break;
case COLOR_CHANNEL_BLUE:
pcolor = b;
break;
case COLOR_CHANNEL_COLD_WHITE:
pcolor = c;
break;
case COLOR_CHANNEL_WARM_WHITE:
pcolor = w;
break;
default:
ADDLOG_ERROR(LOG_FEATURE_CMD, "Unknown color channel %d at index %d", color_channel_order[i], i);
return;
}
translate_byte(pcolor, spiLED.buf + (spiLED.ofs + i * 4 + (pixel * pixel_size * 4)));
}
}
void SM16703P_setMultiplePixel(uint32_t pixel, uint8_t *data, bool push) {
// Return if driver is not loaded
if (!spiLED.ready)
return;
// Check max pixel
if (pixel > pixel_count)
pixel = pixel_count;
// Iterate over pixel
uint8_t *dst = spiLED.buf + spiLED.ofs;
for (uint32_t i = 0; i < pixel; i++) {
uint8_t r, g, b;
r = *data++;
g = *data++;
b = *data++;
// TODO: Not sure how this works. Should we add Cold and Warm white here as well?
SM16703P_setPixel((int)i, (int)r, (int)g, (int)b, 0, 0);
}
if (push) {
SPIDMA_StartTX(spiLED.msg);
}
}
extern float g_brightness0to100;//TODO
void SM16703P_setPixelWithBrig(int pixel, int r, int g, int b, int c, int w) {
// scale brightness
#if ENABLE_LED_BASIC
r = (int)(r * g_brightness0to100*0.01f);
g = (int)(g * g_brightness0to100*0.01f);
b = (int)(b * g_brightness0to100*0.01f);
c = (int)(c * g_brightness0to100*0.01f);
w = (int)(w * g_brightness0to100*0.01f);
#endif
SM16703P_setPixel(pixel,r, g, b, c, w);
}
#define SCALE8_PIXEL(x, scale) (uint8_t)(((uint32_t)x * (uint32_t)scale) / 256)
void SM16703P_scaleAllPixels(int scale) {
int pixel;
byte b;
int ofs;
byte *data, *input;
for (pixel = 0; pixel < pixel_count; pixel++) {
for (ofs = 0; ofs < 3; ofs++) {
data = spiLED.buf + (spiLED.ofs + ofs * 4 + (pixel * 3 * 4));
b = reverse_translate_byte(data);
b = SCALE8_PIXEL(b, scale);
translate_byte(b, data);
}
}
}
void SM16703P_setAllPixels(int r, int g, int b, int c, int w) {
int pixel;
if (!spiLED.ready)
return;
for (pixel = 0; pixel < pixel_count; pixel++) {
SM16703P_setPixel(pixel, r, g, b, c, w);
}
translate_byte(color, spiLED.buf + (spiLED.ofs + index * 4));
}
// 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) {
int ofs, bPush;
Tokenizer_TokenizeString(args, 0);
bPush = Tokenizer_GetArgInteger(0);
ofs = Tokenizer_GetArgInteger(1);
SPILED_SetRawHexString(ofs, Tokenizer_GetArg(2), bPush);
return CMD_RES_OK;
}
commandResult_t SM16703P_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;
Tokenizer_TokenizeString(args, 0);
if (Tokenizer_GetArgsCount() < 4) {
// We need at least 4 arguments: pixel, red, green, blue - cold and warm white are optional
ADDLOG_INFO(LOG_FEATURE_CMD, "Not Enough Arguments for init SM16703P: Amount of LEDs missing");
return CMD_RES_NOT_ENOUGH_ARGUMENTS;
}
all = Tokenizer_GetArg(0);
if (*all == 'a') {
}
else {
pixel = Tokenizer_GetArgInteger(0);
all = 0;
}
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);
}
w = 0; // warm white is optional for backward compatibility
if (Tokenizer_GetArgsCount() > 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);
if (all) {
for (i = 0; i < pixel_count; i++) {
SM16703P_setPixel(i, r, g, b, c, w);
}
}
else {
SM16703P_setPixel(pixel, r, g, b, c, w);
ADDLOG_INFO(LOG_FEATURE_CMD, "Raw Data 0x%02x 0x%02x 0x%02x 0x%02x - 0x%02x 0x%02x 0x%02x 0x%02x - 0x%02x 0x%02x 0x%02x 0x%02x",
spiLED.buf[spiLED.ofs + 0 + (pixel * 3 * 4)],
spiLED.buf[spiLED.ofs + 1 + (pixel * 3 * 4)],
spiLED.buf[spiLED.ofs + 2 + (pixel * 3 * 4)],
spiLED.buf[spiLED.ofs + 3 + (pixel * 3 * 4)],
spiLED.buf[spiLED.ofs + 4 + (pixel * 3 * 4)],
spiLED.buf[spiLED.ofs + 5 + (pixel * 3 * 4)],
spiLED.buf[spiLED.ofs + 6 + (pixel * 3 * 4)],
spiLED.buf[spiLED.ofs + 7 + (pixel * 3 * 4)],
spiLED.buf[spiLED.ofs + 8 + (pixel * 3 * 4)],
spiLED.buf[spiLED.ofs + 9 + (pixel * 3 * 4)],
spiLED.buf[spiLED.ofs + 10 + (pixel * 3 * 4)],
spiLED.buf[spiLED.ofs + 11 + (pixel * 3 * 4)]);
}
return CMD_RES_OK;
}
commandResult_t SM16703P_InitForLEDCount(const void *context, const char *cmd, const char *args, int flags) {
Tokenizer_TokenizeString(args, 0);
if (Tokenizer_GetArgsCount() == 0) {
ADDLOG_INFO(LOG_FEATURE_CMD, "Not Enough Arguments for init SM16703P: Amount of LEDs missing");
return CMD_RES_NOT_ENOUGH_ARGUMENTS;
}
SM16703P_Shutdown();
// First arg: number of pixel to address
pixel_count = Tokenizer_GetArgIntegerRange(0, 0, 255);
// Second arg (optional, default "RGB"): pixel format of "RGB" or "GRB"
if (Tokenizer_GetArgsCount() > 1) {
const char *format = Tokenizer_GetArg(1);
size_t format_length = strlen(format);
enum ColorChannel *new_channel_order = os_malloc(sizeof(enum ColorChannel) * (format_length + 1));
if (!new_channel_order) {
ADDLOG_ERROR(LOG_FEATURE_CMD, "Failed to allocate memory for color channel order");
return CMD_RES_ERROR;
}
int i = 0;
for (const char *p = format; *p; p++) {
switch (*p) {
case 'R':
new_channel_order[i++] = COLOR_CHANNEL_RED;
break;
case 'G':
new_channel_order[i++] = COLOR_CHANNEL_GREEN;
break;
case 'B':
new_channel_order[i++] = COLOR_CHANNEL_BLUE;
break;
case 'C':
new_channel_order[i++] = COLOR_CHANNEL_COLD_WHITE;
break;
case 'W':
new_channel_order[i++] = COLOR_CHANNEL_WARM_WHITE;
break;
default:
ADDLOG_ERROR(LOG_FEATURE_CMD, "Invalid color '%c' in format '%s', should be combination of R,G,B,C,W", *p, format);
os_free(new_channel_order);
return CMD_RES_ERROR;
}
}
pixel_size = i; // number of color channels
color_channel_order = new_channel_order;
}
void SM16703P_SetLEDCount(int pixel_count, int pixel_size) {
// Third arg (optional, default "0"): spiLED.ofs to prepend to each transmission
if (Tokenizer_GetArgsCount() > 2) {
spiLED.ofs = Tokenizer_GetArgIntegerRange(2, 0, 255);
@@ -285,41 +48,10 @@ commandResult_t SM16703P_InitForLEDCount(const void *context, const char *cmd, c
//if (Tokenizer_GetArgsCount() > 3) {
// spiLED.padding = Tokenizer_GetArgIntegerRange(3, 0, 255);
//}
ADDLOG_INFO(LOG_FEATURE_CMD, "Register driver with %i LEDs", pixel_count);
// each pixel is RGB, so 3 bytes per pixel
SPILED_InitDMA(pixel_count * pixel_size);
return CMD_RES_OK;
}
void SM16703P_Show() {
SPIDMA_StartTX(spiLED.msg);
}
static commandResult_t SM16703P_StartTX(const void *context, const char *cmd, const char *args, int flags) {
if (!spiLED.ready)
return CMD_RES_ERROR;
SM16703P_Show();
return CMD_RES_OK;
}
//static commandResult_t SM16703P_CMD_sendBytes(const void *context, const char *cmd, const char *args, int flags) {
// if (!spiLED.ready)
// return CMD_RES_ERROR;
// const char *s = args;
// int i = spiLED.ofs;
// while (*s && s[1]) {
// *(spiLED.buf + (i)) = hexbyte(s);
// s += 2;
// i++;
// }
// while (i < spiLED.msg->send_len) {
// *(spiLED.buf + (i)) = 0;
// }
// SPIDMA_StartTX(spiLED.msg);
// return CMD_RES_OK;
//}
// startDriver SM16703P
// backlog startDriver SM16703P; SM16703P_Test
void SM16703P_Init() {
@@ -327,34 +59,16 @@ void SM16703P_Init() {
int pin = PIN_FindPinIndexForRole(IOR_SM16703P_DIN, -1);
SPILED_Init(pin);
//cmddetail:{"name":"SM16703P_Init","args":"[NumberOfLEDs][ColorOrder]",
//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":"NULL);","file":"driver/drv_sm16703P.c","requires":"",
//cmddetail:"examples":""}
CMD_RegisterCommand("SM16703P_Init", SM16703P_InitForLEDCount, NULL);
//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":"NULL);","file":"driver/drv_sm16703P.c","requires":"",
//cmddetail:"examples":""}
CMD_RegisterCommand("SM16703P_Start", SM16703P_StartTX, NULL);
//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":"NULL);","file":"driver/drv_sm16703P.c","requires":"",
//cmddetail:"examples":""}
CMD_RegisterCommand("SM16703P_SetPixel", SM16703P_CMD_setPixel, NULL);
//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":"NULL);","file":"driver/drv_sm16703P.c","requires":"",
//cmddetail:"examples":""}
CMD_RegisterCommand("SM16703P_SetRaw", SM16703P_CMD_setRaw, NULL);
ledStrip_t ws_export;
ws_export.apply = SM16703P_Show;
ws_export.getByte = SM16703P_GetByte;
ws_export.setByte = SM16703P_setByte;
ws_export.setLEDCount = SM16703P_SetLEDCount;
//CMD_RegisterCommand("SM16703P_SendBytes", SM16703P_CMD_sendBytes, NULL);
LEDS_InitShared(&ws_export);
}
void SM16703P_Shutdown() {
if (color_channel_order != default_color_channel_order) {
os_free(color_channel_order);
color_channel_order = default_color_channel_order;
}
LEDS_ShutdownShared();
}
#endif

View File

@@ -130,24 +130,7 @@ void SPILED_InitDMA(int numBytes) {
void SPILED_SetRawHexString(int start_offset, const char *s, int push) {
// start offset is in bytes, and we do 2 bits per dst byte, so *4
uint8_t *dst = spiLED.buf + spiLED.ofs + start_offset * 4;
// parse hex string like FFAABB0011 byte by byte
while (s[0] && s[1]) {
byte b;
b = hexbyte(s);
*dst++ = translate_2bit((b >> 6));
*dst++ = translate_2bit((b >> 4));
*dst++ = translate_2bit((b >> 2));
*dst++ = translate_2bit(b);
s += 2;
}
if (push) {
SPIDMA_StartTX(spiLED.msg);
}
}
void SPILED_SetRawBytes(int start_offset, byte *bytes, int numBytes, int push) {
// start offset is in bytes, and we do 2 bits per dst byte, so *4
uint8_t *dst = spiLED.buf + spiLED.ofs + start_offset * 4;

View File

@@ -179,6 +179,7 @@
#define ENABLE_OBK_SCRIPTING 1
#define ENABLE_OBK_BERRY 1
#define ENABLE_DRIVER_DS1820_FULL 1
#define ENABLE_DRIVER_DMX 1
#elif PLATFORM_BL602

View File

@@ -437,6 +437,35 @@ void Test_HassDiscovery_Channel_Smoke() {
SELFTEST_ASSERT_JSON_VALUE_STRING(0, "name", "Smoke");
}
void Test_HassDiscovery_Channel_Ph() {
const char *shortName = "WinCustom";
const char *fullName = "Windows Fake Custom";
const char *mqttName = "testCustom";
SIM_ClearOBK(shortName);
SIM_ClearAndPrepareForMQTTTesting(mqttName, "bekens");
CFG_SetShortDeviceName(shortName);
CFG_SetDeviceName(fullName);
CHANNEL_SetType(4, ChType_Ph);
SIM_ClearMQTTHistory();
CMD_ExecuteCommand("scheduleHADiscovery 1", 0);
Sim_RunSeconds(5, false);
// OBK device should publish JSON on MQTT topic "homeassistant"
SELFTEST_ASSERT_HAS_MQTT_JSON_SENT("homeassistant", true);
SELFTEST_ASSERT_JSON_VALUE_STRING("dev", "name", shortName);
SELFTEST_ASSERT_JSON_VALUE_STRING("dev", "sw", USER_SW_VER);
SELFTEST_ASSERT_JSON_VALUE_STRING("dev", "mf", MANUFACTURER);
SELFTEST_ASSERT_JSON_VALUE_STRING("dev", "mdl", PLATFORM_MCU_NAME);
SELFTEST_ASSERT_JSON_VALUE_STRING(0, "stat_t", "~/4/get");
// user says it should not be set
SELFTEST_ASSERT_JSON_VALUE_STRING_NOT_PRESENT(0, "unit_of_meas");
SELFTEST_ASSERT_JSON_VALUE_STRING(0, "dev_cla", "ph");
}
void Test_HassDiscovery_Channel_Custom() {
const char *shortName = "WinCustom";
const char *fullName = "Windows Fake Custom";
@@ -674,6 +703,7 @@ void Test_HassDiscovery_Ext() {
Test_HassDiscovery_Channel_Custom();
Test_HassDiscovery_Channel_BatteryLevelPercent();
Test_HassDiscovery_Channel_Smoke();
Test_HassDiscovery_Channel_Ph();
}

View File

@@ -59,6 +59,7 @@ void SelfTest_Failed(const char *file, const char *function, int line, const cha
#define SELFTEST_ASSERT_HAS_MQTT_JSON_SENT_ANY_4KEY(topic, bPrefixMode, object1, object2, key, value, key2, value2, key3, value3, key4, value4) SELFTEST_ASSERT(SIM_HasMQTTHistoryStringWithJSONPayload(topic, bPrefixMode, object1, object2, key, value, key2, value2, key3, value3, key4, value4));
#define SELFTEST_ASSERT_HAS_SENT_UART_STRING(str) SELFTEST_ASSERT(SIM_UART_ExpectAndConsumeHexStr(str));
#define SELFTEST_ASSERT_HAS_UART_EMPTY() SELFTEST_ASSERT(SIM_UART_GetDataSize()==0);
#define SELFTEST_ASSERT_HAS_SOME_DATA_IN_UART() SELFTEST_ASSERT(SIM_UART_GetDataSize()!=0);
//#define FLOAT_EQUALS (a,b) (fabs(a-b)<0.001f)
float myFabs(float f);
@@ -129,6 +130,8 @@ void Test_MQTT_Get_Relay();
void Test_TuyaMCU_BatteryPowered();
void Test_ChargeLimitDriver();
void Test_WS2812B();
void Test_LEDstrips();
void Test_DMX();
void Test_DoorSensor();
void Test_Enums();
void Test_Expressions_RunTests_Basic();

View File

@@ -4,11 +4,103 @@
bool SM16703P_VerifyPixel(uint32_t pixel, byte r, byte g, byte b);
bool SM16703P_VerifyPixel4(uint32_t pixel, byte r, byte g, byte b, byte a);
#define SELFTEST_ASSERT_PIXEL(index, r, g, b) SELFTEST_ASSERT(SM16703P_VerifyPixel(index, r, g, b));
#define SELFTEST_ASSERT_PIXEL4(index, r, g, b, w) SELFTEST_ASSERT(SM16703P_VerifyPixel4(index, r, g, b, w));
void SM16703P_setMultiplePixel(uint32_t pixel, uint8_t *data, bool push);
void Test_DMX_RGB() {
// 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", 0);
CMD_ExecuteCommand("SM16703P_SetPixel all 255 0 128", 0);
SELFTEST_ASSERT_PIXEL(0, 255, 0, 128);
SELFTEST_ASSERT_PIXEL(1, 255, 0, 128);
SELFTEST_ASSERT_PIXEL(2, 255, 0, 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 FF0080 FF0080 FF0080");
// 512 channels, but checked already 10
for (int i = 0; i < 100; i++) {
SELFTEST_ASSERT_HAS_SENT_UART_STRING("00 00 00 00 00");
}
SELFTEST_ASSERT_HAS_SENT_UART_STRING("00 00 00");
SELFTEST_ASSERT_HAS_UART_EMPTY();
CMD_ExecuteCommand("SM16703P_SetPixel 0 128 128 128", 0);
CMD_ExecuteCommand("SM16703P_SetPixel 1 255 255 255", 0);
CMD_ExecuteCommand("SM16703P_SetPixel 2 15 15 15", 0);
SELFTEST_ASSERT_PIXEL(0, 128, 128, 128);
SELFTEST_ASSERT_PIXEL(1, 255, 255, 255);
SELFTEST_ASSERT_PIXEL(2, 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 808080 FFFFFF 0F0F0F");
// 512 channels, but checked already 10
for (int i = 0; i < 100; i++) {
SELFTEST_ASSERT_HAS_SENT_UART_STRING("00 00 00 00 00");
}
SELFTEST_ASSERT_HAS_SENT_UART_STRING("00 00 00");
SELFTEST_ASSERT_HAS_UART_EMPTY();
// nothing is sent by OBK at that point
}
void Test_DMX_RGBW() {
// 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 RGBC", 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();
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 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();
// nothing is sent by OBK at that point
}
void Test_WS2812B() {
// reset whole device
SIM_ClearOBK(0);
@@ -27,6 +119,9 @@ void Test_WS2812B() {
SELFTEST_ASSERT_PIXEL(1, 0, 0, 255);
SELFTEST_ASSERT_PIXEL(2, 0, 0, 255);
// cannot crash
CMD_ExecuteCommand("SM16703P_SetPixel 1234 255 0 0", 0);
CMD_ExecuteCommand("SM16703P_SetPixel -123 255 0 0", 0);
// fake 3 pixels data
{ // RGB
@@ -135,6 +230,35 @@ void Test_WS2812B() {
SELFTEST_ASSERT_PIXEL(1, 0xFF, 0, 0);
SELFTEST_ASSERT_PIXEL(2, 0xFF, 0, 0xFF);
}
// fake DDP RGBW packet
{
byte ddpPacket[128];
ddpPacket[2] = 0x1A;
// data starts at offset 10
// pixel 0
ddpPacket[10] = 0xFF;
ddpPacket[11] = 0xFF;
ddpPacket[12] = 0xFF;
ddpPacket[13] = 0xFF;
// pixel 1
ddpPacket[14] = 0xFF;
ddpPacket[15] = 0x0;
ddpPacket[16] = 0x0;
ddpPacket[17] = 0xFF;
// pixel 2
ddpPacket[18] = 0xFF;
ddpPacket[19] = 0x0;
ddpPacket[20] = 0xFF;
ddpPacket[21] = 0xFF;
DDP_Parse(ddpPacket, sizeof(ddpPacket));
SELFTEST_ASSERT_PIXEL(0, 0xFF, 0xFF, 0xFF);
///SELFTEST_ASSERT_PIXEL(1, 0xFF, 0, 0);
//SELFTEST_ASSERT_PIXEL(2, 0xFF, 0, 0xFF);
}
CMD_ExecuteCommand("SM16703P_Init 6 RGB", 0);
CMD_ExecuteCommand("SM16703P_SetPixel 0 255 0 0", 0);
@@ -150,8 +274,38 @@ void Test_WS2812B() {
SELFTEST_ASSERT_PIXEL(4, 0, 255, 0);
SELFTEST_ASSERT_PIXEL(5, 0, 0, 255);
CMD_ExecuteCommand("SM16703P_SetPixel all 123 231 132", 0);
for (int i = 0; i < 6; i++) {
SELFTEST_ASSERT_PIXEL(i, 123, 231, 132);
}
CMD_ExecuteCommand("SM16703P_SetPixel all 128 128 128", 0);
for (int i = 0; i < 6; i++) {
SELFTEST_ASSERT_PIXEL(i, 128, 128, 128);
}
SM16703P_scaleAllPixels(128);
for (int i = 0; i < 6; i++) {
SELFTEST_ASSERT_PIXEL(i, 64, 64, 64);
}
SM16703P_scaleAllPixels(128);
for (int i = 0; i < 6; i++) {
SELFTEST_ASSERT_PIXEL(i, 32, 32, 32);
}
SM16703P_scaleAllPixels(64);
for (int i = 0; i < 6; i++) {
SELFTEST_ASSERT_PIXEL(i, 8, 8, 8);
}
CMD_ExecuteCommand("SM16703P_SetRaw 1 0 FF000000FF000000FF", 0);
SELFTEST_ASSERT_PIXEL(0, 0xff, 0x00, 0x00);
SELFTEST_ASSERT_PIXEL(1, 0x00, 0xff, 0x00);
SELFTEST_ASSERT_PIXEL(2, 0x00, 0x00, 0xff);
CMD_ExecuteCommand("SM16703P_SetRaw 1 0 AABBCC00BA00000023", 0);
SELFTEST_ASSERT_PIXEL(0, 0xAA, 0xBB, 0xCC);
SELFTEST_ASSERT_PIXEL(1, 0x00, 0xBA, 0x00);
SELFTEST_ASSERT_PIXEL(2, 0x00, 0x00, 0x23);
#if ENABLE_LED_BASIC
CMD_ExecuteCommand("startDriver PixelAnim", 0);
CMD_ExecuteCommand("led_enableAll 1", 0);
@@ -192,5 +346,10 @@ void Test_WS2812B() {
#endif
}
void Test_LEDstrips() {
Test_DMX_RGB();
Test_DMX_RGBW();
Test_WS2812B();
}
#endif

View File

@@ -22,9 +22,10 @@ void SIM_ClearUART() {
int SIM_UART_GetDataSize()
{
return (g_recvBufIn >= g_recvBufOut
int ret = (g_recvBufIn >= g_recvBufOut
? g_recvBufIn - g_recvBufOut
: g_recvBufIn + (g_recvBufSize - g_recvBufOut) + 1);
return ret;
}
byte SIM_UART_GetByte(int idx) {

View File

@@ -183,7 +183,7 @@ void Win_DoUnitTests() {
//Test_Enums();
Test_Backlog();
Test_DoorSensor();
Test_WS2812B();
Test_LEDstrips();
Test_Command_If_Else();
Test_MQTT();
Test_ChargeLimitDriver();