Skip to content

Commit f160475

Browse files
[Silabs] Add Support for RGB led in Thread build (part 1) (project-chip#41926)
* Add Support for RGB led in Thread build * fix comments
1 parent 1dfcf6b commit f160475

File tree

9 files changed

+139
-115
lines changed

9 files changed

+139
-115
lines changed

examples/lighting-app/silabs/src/LightingManager.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -366,8 +366,8 @@ bool LightingManager::InitiateLightCtrlAction(int32_t aActor, Action_t aAction,
366366

367367
if (aAttributeId == ColorControl::Attributes::CurrentX::Id)
368368
{
369-
VerifyOrReturnValue(colorData.xy.y != *reinterpret_cast<uint16_t *>(value), action_initiated);
370-
colorData.xy.y = *reinterpret_cast<uint16_t *>(value);
369+
VerifyOrReturnValue(colorData.xy.x != *reinterpret_cast<uint16_t *>(value), action_initiated);
370+
colorData.xy.x = *reinterpret_cast<uint16_t *>(value);
371371
action_initiated = true;
372372
}
373373
else if (aAttributeId == ColorControl::Attributes::CurrentY::Id)
@@ -385,13 +385,15 @@ bool LightingManager::InitiateLightCtrlAction(int32_t aActor, Action_t aAction,
385385
{
386386
VerifyOrReturnValue(colorData.hsv.h != *value, action_initiated);
387387
colorData.hsv.h = *value;
388+
mCurrentHue = *value;
388389
action_initiated = true;
389390
}
390391
else if (aAttributeId == ColorControl::Attributes::CurrentSaturation::Id)
391392
{
392393
VerifyOrReturnValue(colorData.hsv.s != *value, action_initiated);
393-
colorData.hsv.s = *value;
394-
action_initiated = true;
394+
colorData.hsv.s = *value;
395+
mCurrentSaturation = *value;
396+
action_initiated = true;
395397
}
396398
break;
397399

examples/platform/silabs/LEDWidget.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ void LEDWidget::Init(const uint8_t led)
3838
mBlinkOffTimeMS = 0;
3939
mLed = led;
4040
mLedStatus = false;
41+
mLevel = 0;
4142
Set(false);
4243
}
4344

examples/platform/silabs/LEDWidget.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@ class LEDWidget
3737
uint8_t GetLevel();
3838

3939
private:
40-
uint8_t mLed;
41-
uint8_t mLevel;
42-
bool mLedStatus;
43-
uint64_t mLastChangeTimeMS;
44-
uint32_t mBlinkOnTimeMS;
45-
uint32_t mBlinkOffTimeMS;
40+
uint8_t mLed = 0;
41+
uint8_t mLevel = 0;
42+
bool mLedStatus = false;
43+
uint64_t mLastChangeTimeMS = 0;
44+
uint32_t mBlinkOnTimeMS = 0;
45+
uint32_t mBlinkOffTimeMS = 0;
4646
};

examples/platform/silabs/efr32/BUILD.gn

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,8 +185,8 @@ source_set("efr32-common") {
185185
}
186186

187187
if (sl_enable_rgb_led) {
188-
sources += [ "${silabs_common_plat_dir}/led/RGBLEDWidget.cpp" ]
189-
include_dirs = [ "${silabs_common_plat_dir}/rgb_led" ]
188+
sources += [ "${silabs_common_plat_dir}/rgb_led/RGBLEDWidget.cpp" ]
189+
include_dirs += [ "${silabs_common_plat_dir}/rgb_led" ]
190190
}
191191

192192
if (chip_build_libshell) {

examples/platform/silabs/rgb_led/RGBLEDWidget.cpp

Lines changed: 70 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ void RGBLEDWidget::SetColor(uint8_t red, uint8_t green, uint8_t blue)
3636
{
3737
if (GetPlatform().GetRGBLedState(GetLED()))
3838
{
39-
ChipLogProgress(Zcl, "SetColor : %u|%u|%u", red, green, blue);
39+
ChipLogProgress(Zcl, "SetColor : R:%u|G:%u|B:%u", red, green, blue);
4040
GetPlatform().SetLedColor(GetLED(), red, green, blue);
4141
}
4242
}
@@ -54,16 +54,77 @@ void RGBLEDWidget::GetColor(uint16_t & r, uint16_t & g, uint16_t & b)
5454

5555
ChipLogProgress(Zcl, "RGB Values: R=%u G=%u B=%u", r, g, b);
5656
}
57-
57+
/**
58+
* @brief Convert Data model hue and saturation to RGB and set the color
59+
* As per spec, hue range from 0 to 254 and saturation from 0 to 254
60+
* Since the equation expects hue in 0-360 and saturation in percentage, we scale them accordingly
61+
*
62+
* @param hue
63+
* @param saturation
64+
*/
5865
void RGBLEDWidget::SetColorFromHSV(uint8_t hue, uint8_t saturation)
5966
{
60-
RGBLEDWidget::HsvColor_t hsv;
61-
hsv.h = hue;
62-
hsv.s = saturation;
63-
hsv.v = GetLevel();
64-
ChipLogProgress(Zcl, "SetColorFromHSV : %u|%u", hsv.h, hsv.s);
65-
RGBLEDWidget::RgbColor_t rgb = RGBLEDWidget::HsvToRgb(hsv);
66-
SetColor(rgb.r, rgb.g, rgb.b);
67+
ChipLogDetail(Zcl, "SetColorFromHSV : H:%u|S:%u|V:%u", hue, saturation, GetLevel());
68+
// Per spec max value for each attribute is 254
69+
float h = (hue * 360.0f) / 254.0f, s = (saturation / 254.0f), v = (GetLevel() / 254.0f);
70+
float hh, p, q, t, ff, r, g, b;
71+
long i;
72+
73+
ChipLogDetail(Zcl, "HUE Values: H=%u S=%u V=%u", static_cast<uint8_t>(h), static_cast<uint8_t>(s * 100.0),
74+
static_cast<uint8_t>(v * 100.0));
75+
76+
if (s <= 0.0)
77+
{ // Achromatic (grey)
78+
SetColor(static_cast<uint8_t>(v * 255), static_cast<uint8_t>(v * 255), static_cast<uint8_t>(v * 255));
79+
return;
80+
}
81+
82+
hh = h;
83+
if (hh >= 360.0)
84+
hh = 0.0;
85+
hh /= 60.0;
86+
i = (long) hh;
87+
ff = hh - i;
88+
p = v * (1.0 - s);
89+
q = v * (1.0 - (s * ff));
90+
t = v * (1.0 - (s * (1.0 - ff)));
91+
92+
switch (i)
93+
{
94+
case 0:
95+
r = v;
96+
g = t;
97+
b = p;
98+
break;
99+
case 1:
100+
r = q;
101+
g = v;
102+
b = p;
103+
break;
104+
case 2:
105+
r = p;
106+
g = v;
107+
b = t;
108+
break;
109+
case 3:
110+
r = p;
111+
g = q;
112+
b = v;
113+
break;
114+
case 4:
115+
r = t;
116+
g = p;
117+
b = v;
118+
break;
119+
case 5:
120+
default:
121+
r = v;
122+
g = p;
123+
b = q;
124+
break;
125+
}
126+
127+
SetColor(static_cast<uint8_t>(r * 255), static_cast<uint8_t>(g * 255), static_cast<uint8_t>(b * 255));
67128
}
68129

69130
void RGBLEDWidget::SetColorFromXY(uint16_t currentX, uint16_t currentY)
@@ -214,55 +275,6 @@ RgbColor_t RGBLEDWidget::ConvertXYZToRGB(float X, float Y, float Z)
214275
return rgb;
215276
}
216277

217-
// Calculate the P value for HSV to RGB conversion
218-
uint8_t RGBLEDWidget::CalculateP(uint8_t v, uint8_t s)
219-
{
220-
// RGB value when the hue is at its minimum for the current region.
221-
return (v * (kMaxColorValue - s)) >> 8;
222-
}
223-
224-
// Calculate the Q value for HSV to RGB conversion
225-
uint8_t RGBLEDWidget::CalculateQ(uint8_t v, uint8_t s, uint32_t remainder)
226-
{
227-
// RGB value when the hue is transitioning from one primary color to another within the current region.
228-
return (v * (kMaxColorValue - ((s * remainder) >> 8))) >> 8;
229-
}
230-
231-
// Calculate the T value for HSV to RGB conversion
232-
uint8_t RGBLEDWidget::CalculateT(uint8_t v, uint8_t s, uint32_t remainder)
233-
{
234-
// RGB value when the hue is transitioning from one primary color to another within the current region, but in the opposite
235-
// direction of q.
236-
237-
return (v * (kMaxColorValue - ((s * (kMaxColorValue - remainder)) >> 8))) >> 8;
238-
}
239-
240-
// Set RGB values based on the region for HSV to RGB conversion
241-
void RGBLEDWidget::SetRgbByRegion(uint8_t region, uint8_t v, uint8_t p, uint8_t q, uint8_t t, RgbColor_t & rgb)
242-
{
243-
switch (region)
244-
{
245-
case 0:
246-
rgb.r = v, rgb.g = t, rgb.b = p;
247-
break;
248-
case 1:
249-
rgb.r = q, rgb.g = v, rgb.b = p;
250-
break;
251-
case 2:
252-
rgb.r = p, rgb.g = v, rgb.b = t;
253-
break;
254-
case 3:
255-
rgb.r = p, rgb.g = q, rgb.b = v;
256-
break;
257-
case 4:
258-
rgb.r = t, rgb.g = p, rgb.b = v;
259-
break;
260-
default:
261-
rgb.r = v, rgb.g = p, rgb.b = q;
262-
break;
263-
}
264-
}
265-
266278
// Convert color temperature to RGB color space
267279
RgbColor_t RGBLEDWidget::CTToRgb(uint16_t ctMireds)
268280
{
@@ -278,39 +290,6 @@ RgbColor_t RGBLEDWidget::CTToRgb(uint16_t ctMireds)
278290
return rgb;
279291
}
280292

281-
// Convert HSV color space to RGB color space
282-
RgbColor_t RGBLEDWidget::HsvToRgb(HsvColor_t hsv)
283-
{
284-
RgbColor_t rgb;
285-
286-
uint8_t region, p, q, t;
287-
uint32_t remainder;
288-
289-
if (hsv.s == 0)
290-
{
291-
rgb.r = rgb.g = rgb.b = hsv.v;
292-
}
293-
else
294-
{
295-
// region variable is calculated by dividing the hue value by 43 (since the hue value ranges from 0 to 255, and there
296-
// are 6 regions, each region spans approximately 43 units)
297-
region = hsv.h / kHueRegionDivider;
298-
299-
// Calculates the position of h within the current region.Multiplying by 6 scales this position to a range of 0 to 255,
300-
// which is used to calculate intermediate RGB values.
301-
remainder = (hsv.h - (region * kHueRegionDivider)) * 6;
302-
303-
// p,q and t intermediate values used to calculate the final RGB values
304-
p = CalculateP(hsv.v, hsv.s);
305-
q = CalculateQ(hsv.v, hsv.s, remainder);
306-
t = CalculateT(hsv.v, hsv.s, remainder);
307-
308-
SetRgbByRegion(region, hsv.v, p, q, t, rgb);
309-
}
310-
311-
return rgb;
312-
}
313-
314293
// Convert XY color space to RGB color space
315294
RgbColor_t RGBLEDWidget::XYToRgb(uint8_t Level, uint16_t currentX, uint16_t currentY)
316295
{

examples/platform/silabs/rgb_led/RGBLEDWidget.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,4 @@ class RGBLEDWidget : public LEDWidget
7777
float CalculateRed(float ct);
7878
float CalculateGreen(float ct);
7979
float CalculateBlue(float ct);
80-
81-
uint8_t CalculateP(uint8_t v, uint8_t s);
82-
uint8_t CalculateQ(uint8_t v, uint8_t s, uint32_t remainder);
83-
uint8_t CalculateT(uint8_t v, uint8_t s, uint32_t remainder);
84-
void SetRgbByRegion(uint8_t region, uint8_t v, uint8_t p, uint8_t q, uint8_t t, RgbColor_t & rgb);
8580
};

src/platform/silabs/platformAbstraction/GsdkSpam.cpp

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,27 @@
3535

3636
#ifdef ENABLE_WSTK_LEDS
3737
extern "C" {
38+
#if (defined(SL_MATTER_RGB_LED_ENABLED) && SL_MATTER_RGB_LED_ENABLED == 1)
39+
#include "sl_simple_rgb_pwm_led.h"
40+
#include "sl_simple_rgb_pwm_led_instances.h"
41+
#define SL_SIMPLE_LED_INSTANCE(x) (&sl_simple_rgb_pwm_led_rgb_led0)
42+
#define SL_SIMPLE_LED_COUNT 1
43+
#define SL_LED_INIT_INTANCES() sl_simple_rgb_pwm_led_init_instances();
44+
#define SL_LED_GET_STATE(x) (x->led_common.context->state)
45+
#define SL_LED_TURN_ON(x) sl_led_turn_on(&(x->led_common))
46+
#define SL_LED_TURN_OFF(x) sl_led_turn_off(&(x->led_common))
47+
#define SL_LED_TOGGLE(x) sl_led_toggle(&(x->led_common))
48+
#else
3849
#include "sl_simple_led_instances.h"
50+
#define SL_LED_INIT_INTANCES() sl_simple_led_init_instances();
51+
#define SL_LED_GET_STATE(x) sl_simple_led_get_state(const_cast<sl_led_t *>(x))
52+
#define SL_LED_TURN_ON(x) sl_simple_led_turn_on(const_cast<sl_led_t *>(x))
53+
#define SL_LED_TURN_OFF(x) sl_simple_led_turn_off(const_cast<sl_led_t *>(x))
54+
#define SL_LED_TOGGLE(x) sl_simple_led_toggle(const_cast<sl_led_t *>(x))
55+
56+
#endif // (defined(SL_MATTER_RGB_LED_ENABLED) && SL_MATTER_RGB_LED_ENABLED == 1)
3957
}
58+
4059
#endif
4160

4261
#ifdef SL_CATALOG_SIMPLE_BUTTON_PRESENT
@@ -193,7 +212,7 @@ CHIP_ERROR SilabsPlatform::FlashWritePage(uint32_t addr, const uint8_t * data, s
193212
#ifdef ENABLE_WSTK_LEDS
194213
void SilabsPlatform::InitLed(void)
195214
{
196-
sl_simple_led_init_instances();
215+
SL_LED_INIT_INTANCES();
197216
}
198217

199218
CHIP_ERROR SilabsPlatform::SetLed(bool state, uint8_t led)
@@ -203,7 +222,7 @@ CHIP_ERROR SilabsPlatform::SetLed(bool state, uint8_t led)
203222
return CHIP_ERROR_INVALID_ARGUMENT;
204223
}
205224

206-
(state) ? sl_led_turn_on(SL_SIMPLE_LED_INSTANCE(led)) : sl_led_turn_off(SL_SIMPLE_LED_INSTANCE(led));
225+
(state) ? SL_LED_TURN_ON(SL_SIMPLE_LED_INSTANCE(led)) : SL_LED_TURN_OFF(SL_SIMPLE_LED_INSTANCE(led));
207226
return CHIP_NO_ERROR;
208227
}
209228

@@ -213,8 +232,7 @@ bool SilabsPlatform::GetLedState(uint8_t led)
213232
{
214233
return false;
215234
}
216-
217-
return sl_led_get_state(SL_SIMPLE_LED_INSTANCE(led));
235+
return SL_LED_GET_STATE(SL_SIMPLE_LED_INSTANCE(led));
218236
}
219237

220238
CHIP_ERROR SilabsPlatform::ToggleLed(uint8_t led)
@@ -223,7 +241,7 @@ CHIP_ERROR SilabsPlatform::ToggleLed(uint8_t led)
223241
{
224242
return CHIP_ERROR_INVALID_ARGUMENT;
225243
}
226-
sl_led_toggle(SL_SIMPLE_LED_INSTANCE(led));
244+
SL_LED_TOGGLE(SL_SIMPLE_LED_INSTANCE(led));
227245
return CHIP_NO_ERROR;
228246
}
229247
#endif // ENABLE_WSTK_LEDS
@@ -236,6 +254,23 @@ void SilabsPlatform::StartScheduler()
236254
}
237255
#endif
238256

257+
#if (defined(SL_MATTER_RGB_LED_ENABLED) && SL_MATTER_RGB_LED_ENABLED == 1)
258+
bool SilabsPlatform::GetRGBLedState(uint8_t led)
259+
{
260+
return SL_LED_GET_STATE(SL_SIMPLE_LED_INSTANCE(led));
261+
}
262+
CHIP_ERROR SilabsPlatform::SetLedColor(uint8_t led, uint8_t red, uint8_t green, uint8_t blue)
263+
{
264+
sl_led_set_rgb_color(SL_SIMPLE_LED_INSTANCE(led), red, green, blue);
265+
return CHIP_NO_ERROR;
266+
}
267+
CHIP_ERROR SilabsPlatform::GetLedColor(uint8_t led, uint16_t & r, uint16_t & g, uint16_t & b)
268+
{
269+
sl_led_get_rgb_color(SL_SIMPLE_LED_INSTANCE(led), &r, &g, &b);
270+
return CHIP_NO_ERROR;
271+
}
272+
#endif // (defined(SL_MATTER_RGB_LED_ENABLED) && SL_MATTER_RGB_LED_ENABLED == 1)
273+
239274
#ifdef SL_CATALOG_SIMPLE_BUTTON_PRESENT
240275
extern "C" void sl_button_on_change(const sl_button_t * handle)
241276
{

third_party/silabs/efr32_sdk.gni

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,10 @@ template("efr32_sdk") {
417417
defines += [ "ENABLE_WSTK_LEDS" ]
418418
}
419419

420+
if (sl_enable_rgb_led) {
421+
defines += [ "SL_MATTER_RGB_LED_ENABLED=1" ]
422+
}
423+
420424
if (use_wstk_buttons) {
421425
_include_dirs += [ "${efr32_sdk_root}/platform/driver/button/inc" ]
422426
}
@@ -906,9 +910,15 @@ template("efr32_sdk") {
906910
"${efr32_sdk_root}/platform/driver/leddrv/src/sl_led.c",
907911
"${efr32_sdk_root}/platform/driver/leddrv/src/sl_pwm_led.c",
908912
"${efr32_sdk_root}/platform/driver/leddrv/src/sl_simple_led.c",
909-
"${efr32_sdk_root}/platform/driver/leddrv/src/sl_simple_rgb_pwm_led.c",
910-
"${silabs_gen_folder}/autogen/sl_simple_led_instances.c",
911913
]
914+
if (sl_enable_rgb_led) {
915+
sources += [
916+
"${efr32_sdk_root}/platform/driver/leddrv/src/sl_simple_rgb_pwm_led.c",
917+
"${silabs_gen_folder}/autogen/sl_simple_rgb_pwm_led_instances.c",
918+
]
919+
} else {
920+
sources += [ "${silabs_gen_folder}/autogen/sl_simple_led_instances.c" ]
921+
}
912922
}
913923

914924
# SPI is only used for Wifi

third_party/silabs/silabs_board.gni

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ if (is_si917_board) {
154154
silabs_family = "efr32mg24"
155155
silabs_mcu = "EFR32MG24B310F1536IM48"
156156

157+
# TODO enable me once submodule is updated
158+
# sl_enable_rgb_led = true
157159
# ThunderBoards don't have a LCD,
158160
show_qr_code = false
159161
disable_lcd = true

0 commit comments

Comments
 (0)