Skip to content

Commit

Permalink
bugfix for edge case with CW LED driver channels, along with a self test
Browse files Browse the repository at this point in the history
  • Loading branch information
openshwprojects committed Dec 11, 2023
1 parent d3bc90c commit b7e359e
Show file tree
Hide file tree
Showing 2 changed files with 156 additions and 56 deletions.
43 changes: 27 additions & 16 deletions src/cmnds/cmd_newLEDDriver.c
Original file line number Diff line number Diff line change
Expand Up @@ -310,14 +310,8 @@ void LED_RunQuickColorLerp(int deltaMS) {

deltaSeconds = deltaMS * 0.001f;

// The color order is RGBCW.
// some people set RED to channel 0, and some of them set RED to channel 1
// Let's detect if there is a PWM on channel 0
if(CHANNEL_HasChannelPinWithRoleOrRole(0, IOR_PWM, IOR_PWM_n)) {
firstChannelIndex = 0;
} else {
firstChannelIndex = 1;
}
firstChannelIndex = LED_GetFirstChannelIndex();

if (CFG_HasFlag(OBK_FLAG_LED_EMULATE_COOL_WITH_RGB)) {
emulatedCool = firstChannelIndex + 3;
}
Expand Down Expand Up @@ -423,6 +417,29 @@ float led_gamma_correction (int color, float iVal) { // apply LED gamma and RGB
void LED_SaveStateToFlashVarsNow() {
HAL_FlashVars_SaveLED(g_lightMode, g_brightness0to100, led_temperature_current, baseColors[0], baseColors[1], baseColors[2], g_lightEnableAll);
}
// The color order is RGBCW.
// some people set RED to channel 0, and some of them set RED to channel 1
// Let's detect if there is a PWM on channel 0
int LED_GetFirstChannelIndex() {
#if 0
int firstChannelIndex;
if (CHANNEL_HasChannelPinWithRoleOrRole(0, IOR_PWM, IOR_PWM_n)) {
firstChannelIndex = 0;
}
else {
firstChannelIndex = 1;
}
return firstChannelIndex;
#else
int i;
for (i = 0; i < 5; i++) {
if (CHANNEL_HasChannelPinWithRoleOrRole(i, IOR_PWM, IOR_PWM_n)) {
return i;
}
}
return 0;
#endif
}
void apply_smart_light() {
int i;
int firstChannelIndex;
Expand All @@ -434,14 +451,8 @@ void apply_smart_light() {
int value_brightness = 0;
int value_cold_or_warm = 0;

// The color order is RGBCW.
// some people set RED to channel 0, and some of them set RED to channel 1
// Let's detect if there is a PWM on channel 0
if(CHANNEL_HasChannelPinWithRoleOrRole(0, IOR_PWM, IOR_PWM_n)) {
firstChannelIndex = 0;
} else {
firstChannelIndex = 1;
}

firstChannelIndex = LED_GetFirstChannelIndex();

if (CFG_HasFlag(OBK_FLAG_LED_EMULATE_COOL_WITH_RGB)) {
emulatedCool = firstChannelIndex + 3;
Expand Down
169 changes: 129 additions & 40 deletions src/selftest/selftest_led.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,92 @@ void Test_LEDDriver_CW() {
}
}

void Test_LEDDriver_CW_OtherChannels() {
int i;
// reset whole device
SIM_ClearOBK(0);

// CW bulb requires two PWMs - first on channel 1, second on channel 2
// NOTE: we also support case where first PWM is on channel 0, and second on 1
PIN_SetPinRoleForPinIndex(24, IOR_PWM);
PIN_SetPinChannelForPinIndex(24, 3);

PIN_SetPinRoleForPinIndex(26, IOR_PWM);
PIN_SetPinChannelForPinIndex(26, 4);

CMD_ExecuteCommand("led_enableAll 1", 0);


// check expressions (not really LED related but ok)
SELFTEST_ASSERT_EXPRESSION("$led_enableAll", 1.0f);
// Set 100% Warm
CMD_ExecuteCommand("led_temperature 500", 0);

printf("Channel C is %i, channel W is %i\n", CHANNEL_Get(3), CHANNEL_Get(4));
SELFTEST_ASSERT_CHANNEL(3, 0);
SELFTEST_ASSERT_CHANNEL(4, 100);

// check read access
SELFTEST_ASSERT_EXPRESSION("$led_temperature", 500.0f);

// check expressions (not really LED related but ok)
SELFTEST_ASSERT_EXPRESSION("$led_temperature*2", 1000.0f);
SELFTEST_ASSERT_EXPRESSION("2*$led_temperature", 1000.0f);

// Set 100% Cold
CMD_ExecuteCommand("led_temperature 154", 0);
// check read access
SELFTEST_ASSERT_EXPRESSION("$led_temperature", 154.0f);
SELFTEST_ASSERT_EXPRESSION("$led_enableAll", 1.0f);
SELFTEST_ASSERT_CHANNEL(3, 100);
SELFTEST_ASSERT_CHANNEL(4, 0);

// Tasmota style command should disable LED
Test_FakeHTTPClientPacket_GET("cm?cmnd=POWER%200");
SELFTEST_ASSERT_EXPRESSION("$led_enableAll", 0.0f);
SELFTEST_ASSERT_CHANNEL(3, 0);
SELFTEST_ASSERT_CHANNEL(4, 0);
// Tasmota style command should enable LED
Test_FakeHTTPClientPacket_GET("cm?cmnd=POWER%201");
SELFTEST_ASSERT_EXPRESSION("$led_enableAll", 1.0f);
SELFTEST_ASSERT_CHANNEL(3, 100);
SELFTEST_ASSERT_CHANNEL(4, 0);


SIM_SendFakeMQTTAndRunSimFrame_CMND("POWER", "ON");
SELFTEST_ASSERT_EXPRESSION("$led_enableAll", 1.0f);
SELFTEST_ASSERT_CHANNEL(3, 100);
SELFTEST_ASSERT_CHANNEL(4, 0);
SIM_SendFakeMQTTAndRunSimFrame_CMND("POWER", "OFF");
SELFTEST_ASSERT_EXPRESSION("$led_enableAll", 0.0f);
SELFTEST_ASSERT_CHANNEL(3, 0);
SELFTEST_ASSERT_CHANNEL(4, 0);
SIM_SendFakeMQTTAndRunSimFrame_CMND("POWER", "ON");
SELFTEST_ASSERT_EXPRESSION("$led_enableAll", 1.0f);
SELFTEST_ASSERT_CHANNEL(3, 100);
SELFTEST_ASSERT_CHANNEL(4, 0);

for (i = 0; i <= 100; i++) {
char buffer[64];
sprintf(buffer, "Dimmer %i", i);
CMD_ExecuteCommand(buffer, 0);
//printf("Dimmer loop test: %i\n",i);
SELFTEST_ASSERT_EXPRESSION("$led_dimmer", i);
}
for (i = 154; i <= 500; i++) {
char buffer[64];
sprintf(buffer, "CT %i", i);
CMD_ExecuteCommand(buffer, 0);
//printf("Dimmer loop test: %i\n",i);
SELFTEST_ASSERT_EXPRESSION("$led_temperature", i);
}
CMD_ExecuteCommand("Dimmer 0", 0);
for (i = 0; i < 100; i++) {
SELFTEST_ASSERT_EXPRESSION("$led_dimmer", i);
CMD_ExecuteCommand("add_dimmer 1", 0);
SELFTEST_ASSERT_EXPRESSION("$led_dimmer", i + 1);
}
}
void Test_LEDDriver_CW_Alternate() {
int i;
// reset whole device
Expand Down Expand Up @@ -271,20 +357,20 @@ void Test_LEDDriver_RGBCW() {
//CMD_ExecuteCommand("{\"color\":{\"b\":255,\"c\":0,\"g\":255,\"r\":255},\"state\":\"1\"}", "");

}
void Test_LEDDriver_RGB() {
void Test_LEDDriver_RGB(int firstChannel) {
// reset whole device
SIM_ClearOBK(0);

// RGB bulb requires three PWMs - first on channel 1, second on channel 2, third on channel 3
// NOTE: we also support case where first PWM is on channel 0, and second on 1
PIN_SetPinRoleForPinIndex(24, IOR_PWM);
PIN_SetPinChannelForPinIndex(24, 1);
PIN_SetPinChannelForPinIndex(24, firstChannel);

PIN_SetPinRoleForPinIndex(26, IOR_PWM);
PIN_SetPinChannelForPinIndex(26, 2);
PIN_SetPinChannelForPinIndex(26, firstChannel+1);

PIN_SetPinRoleForPinIndex(9, IOR_PWM);
PIN_SetPinChannelForPinIndex(9, 3);
PIN_SetPinChannelForPinIndex(9, firstChannel + 2);

CMD_ExecuteCommand("led_enableAll 1", 0);
// check expressions (not really LED related but ok)
Expand All @@ -304,74 +390,77 @@ void Test_LEDDriver_RGB() {
SELFTEST_ASSERT_EXPRESSION("$led_dimmer+$led_dimmer", 200.0f);
SELFTEST_ASSERT_EXPRESSION("$led_dimmer+$led_dimmer+$led_dimmer", 300.0f);

printf("Channel R is %i, channel G is %i, channel B is %i\n", CHANNEL_Get(1), CHANNEL_Get(2), CHANNEL_Get(3));
SELFTEST_ASSERT_CHANNEL(1, 100);
SELFTEST_ASSERT_CHANNEL(2, 0);
SELFTEST_ASSERT_CHANNEL(3, 0);
printf("Channel R is %i, channel G is %i, channel B is %i\n", CHANNEL_Get(firstChannel), CHANNEL_Get(firstChannel+1), CHANNEL_Get(firstChannel+2));
SELFTEST_ASSERT_CHANNEL(firstChannel, 100);
SELFTEST_ASSERT_CHANNEL(firstChannel+1, 0);
SELFTEST_ASSERT_CHANNEL(firstChannel+2, 0);

// Set green
CMD_ExecuteCommand("led_baseColor_rgb 00FF00", 0);
printf("Channel R is %i, channel G is %i, channel B is %i\n", CHANNEL_Get(1), CHANNEL_Get(2), CHANNEL_Get(3));
SELFTEST_ASSERT_CHANNEL(1, 0);
SELFTEST_ASSERT_CHANNEL(2, 100);
SELFTEST_ASSERT_CHANNEL(3, 0);
printf("Channel R is %i, channel G is %i, channel B is %i\n", CHANNEL_Get(firstChannel), CHANNEL_Get(firstChannel+1), CHANNEL_Get(firstChannel+2));
SELFTEST_ASSERT_CHANNEL(firstChannel, 0);
SELFTEST_ASSERT_CHANNEL(firstChannel+1, 100);
SELFTEST_ASSERT_CHANNEL(firstChannel+2, 0);

// Set blue - also support #
CMD_ExecuteCommand("led_baseColor_rgb #0000FF", 0);
printf("Channel R is %i, channel G is %i, channel B is %i\n", CHANNEL_Get(1), CHANNEL_Get(2), CHANNEL_Get(3));
SELFTEST_ASSERT_CHANNEL(1, 0);
SELFTEST_ASSERT_CHANNEL(2, 0);
SELFTEST_ASSERT_CHANNEL(3, 100);
printf("Channel R is %i, channel G is %i, channel B is %i\n", CHANNEL_Get(firstChannel), CHANNEL_Get(firstChannel+1), CHANNEL_Get(firstChannel+2));
SELFTEST_ASSERT_CHANNEL(firstChannel, 0);
SELFTEST_ASSERT_CHANNEL(firstChannel+1, 0);
SELFTEST_ASSERT_CHANNEL(firstChannel+2, 100);

// set 50% brightness
CMD_ExecuteCommand("led_dimmer 50", 0);
// check expressions (not really LED related but ok)
SELFTEST_ASSERT_EXPRESSION("$led_dimmer", 50.0f);
printf("Channel R is %i, channel G is %i, channel B is %i\n", CHANNEL_Get(1), CHANNEL_Get(2), CHANNEL_Get(3));
SELFTEST_ASSERT_CHANNEL(1, 0);
SELFTEST_ASSERT_CHANNEL(2, 0);
SELFTEST_ASSERT_CHANNEL(3, 21);
printf("Channel R is %i, channel G is %i, channel B is %i\n", CHANNEL_Get(firstChannel), CHANNEL_Get(firstChannel+1), CHANNEL_Get(firstChannel+2));
SELFTEST_ASSERT_CHANNEL(firstChannel, 0);
SELFTEST_ASSERT_CHANNEL(firstChannel+1, 0);
SELFTEST_ASSERT_CHANNEL(firstChannel+2, 21);

// set 90% brightness
CMD_ExecuteCommand("led_dimmer 90", 0);
// check expressions (not really LED related but ok)
SELFTEST_ASSERT_EXPRESSION("$led_dimmer", 90.0f);
printf("Channel R is %i, channel G is %i, channel B is %i\n", CHANNEL_Get(1), CHANNEL_Get(2), CHANNEL_Get(3));
SELFTEST_ASSERT_CHANNEL(1, 0);
SELFTEST_ASSERT_CHANNEL(2, 0);
SELFTEST_ASSERT_CHANNEL(3, 79);
printf("Channel R is %i, channel G is %i, channel B is %i\n", CHANNEL_Get(firstChannel), CHANNEL_Get(firstChannel+1), CHANNEL_Get(firstChannel+2));
SELFTEST_ASSERT_CHANNEL(firstChannel, 0);
SELFTEST_ASSERT_CHANNEL(firstChannel+1, 0);
SELFTEST_ASSERT_CHANNEL(firstChannel+2, 79);
// disable
CMD_ExecuteCommand("led_enableAll 0", 0);
printf("Channel R is %i, channel G is %i, channel B is %i\n", CHANNEL_Get(1), CHANNEL_Get(2), CHANNEL_Get(3));
SELFTEST_ASSERT_CHANNEL(1, 0);
SELFTEST_ASSERT_CHANNEL(2, 0);
SELFTEST_ASSERT_CHANNEL(3, 0);
printf("Channel R is %i, channel G is %i, channel B is %i\n", CHANNEL_Get(firstChannel), CHANNEL_Get(firstChannel+1), CHANNEL_Get(firstChannel+2));
SELFTEST_ASSERT_CHANNEL(firstChannel, 0);
SELFTEST_ASSERT_CHANNEL(firstChannel+1, 0);
SELFTEST_ASSERT_CHANNEL(firstChannel+2, 0);
// reenable, it should remember last state
CMD_ExecuteCommand("led_enableAll 1", 0);
printf("Channel R is %i, channel G is %i, channel B is %i\n", CHANNEL_Get(1), CHANNEL_Get(2), CHANNEL_Get(3));
SELFTEST_ASSERT_CHANNEL(1, 0);
SELFTEST_ASSERT_CHANNEL(2, 0);
SELFTEST_ASSERT_CHANNEL(3, 79);
printf("Channel R is %i, channel G is %i, channel B is %i\n", CHANNEL_Get(firstChannel), CHANNEL_Get(firstChannel+1), CHANNEL_Get(firstChannel+2));
SELFTEST_ASSERT_CHANNEL(firstChannel, 0);
SELFTEST_ASSERT_CHANNEL(firstChannel+1, 0);
SELFTEST_ASSERT_CHANNEL(firstChannel+2, 79);

// Tasmota style command should disable LED
Test_FakeHTTPClientPacket_GET("cm?cmnd=POWER%200");
SELFTEST_ASSERT_CHANNEL(1, 0);
SELFTEST_ASSERT_CHANNEL(2, 0);
SELFTEST_ASSERT_CHANNEL(3, 0);
SELFTEST_ASSERT_CHANNEL(firstChannel, 0);
SELFTEST_ASSERT_CHANNEL(firstChannel+1, 0);
SELFTEST_ASSERT_CHANNEL(firstChannel+2, 0);
// Tasmota style command should enable LED
Test_FakeHTTPClientPacket_GET("cm?cmnd=POWER%201");
SELFTEST_ASSERT_CHANNEL(1, 0);
SELFTEST_ASSERT_CHANNEL(2, 0);
SELFTEST_ASSERT_CHANNEL(3, 79);
SELFTEST_ASSERT_CHANNEL(firstChannel, 0);
SELFTEST_ASSERT_CHANNEL(firstChannel+1, 0);
SELFTEST_ASSERT_CHANNEL(firstChannel+2, 79);

// make error
//SELFTEST_ASSERT_CHANNEL(3, 666);
//SELFTEST_ASSERT_CHANNEL(firstChannel+2, 666);
}
void Test_LEDDriver() {

Test_LEDDriver_CW_Alternate();
Test_LEDDriver_CW();
Test_LEDDriver_RGB();
Test_LEDDriver_CW_OtherChannels();
// support both indexing from 0 and 1
Test_LEDDriver_RGB(0);
Test_LEDDriver_RGB(1);
Test_LEDDriver_RGBCW();
}

Expand Down

0 comments on commit b7e359e

Please sign in to comment.