-
Notifications
You must be signed in to change notification settings - Fork 7.7k
Add support for multi-color LEDs #92473
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
4a77680
2f25c1f
db55efa
051d638
ab647ef
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# Copyright (c) 2025 Seagate Technology LLC | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
config LEDS_GROUP_MULTICOLOR | ||
bool "LEDs group multi-color driver" | ||
default y | ||
depends on DT_HAS_LEDS_GROUP_MULTICOLOR_ENABLED | ||
help | ||
Enable this driver to supports multi-color LEDs built with several | ||
monochromatic LEDs. | ||
|
||
See the leds-group-multicolor DT binding for details. |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -4,6 +4,7 @@ | |||||
config LED_PWM | ||||||
bool "PWM LED driver" | ||||||
default y | ||||||
depends on PWM && DT_HAS_PWM_LEDS_ENABLED | ||||||
depends on DT_HAS_PWM_LEDS_ENABLED | ||||||
select PWM | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [nitpick] Using
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||
help | ||||||
Enable driver for PWM LEDs. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
/* | ||
* Copyright (c) 2025 Seagate Technology LLC | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#define DT_DRV_COMPAT leds_group_multicolor | ||
|
||
/** | ||
* @file | ||
* @brief Driver for multi-color LED built from monochromatic LEDs. | ||
*/ | ||
|
||
#include <zephyr/drivers/led.h> | ||
#include <zephyr/device.h> | ||
#include <zephyr/kernel.h> | ||
|
||
#include <zephyr/logging/log.h> | ||
LOG_MODULE_REGISTER(leds_group_multicolor, CONFIG_LED_LOG_LEVEL); | ||
|
||
struct leds_group_multicolor_config { | ||
uint8_t num_leds; | ||
const struct led_dt_spec *led; | ||
}; | ||
|
||
static int leds_group_multicolor_set_color(const struct device *dev, uint32_t led, | ||
uint8_t num_colors, const uint8_t *color) | ||
{ | ||
const struct leds_group_multicolor_config *config = dev->config; | ||
|
||
if (led != 0) { | ||
return -EINVAL; | ||
} | ||
if (num_colors != config->num_leds) { | ||
return -EINVAL; | ||
} | ||
|
||
for (uint8_t i = 0; i < num_colors; i++) { | ||
int err; | ||
|
||
err = led_set_brightness_dt(&config->led[i], color[i]); | ||
if (err) { | ||
return err; | ||
} | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
static int leds_group_multicolor_init(const struct device *dev) | ||
{ | ||
const struct leds_group_multicolor_config *config = dev->config; | ||
|
||
for (uint8_t i = 0; i < config->num_leds; i++) { | ||
const struct led_dt_spec *led = &config->led[i]; | ||
|
||
if (!led_is_ready_dt(led)) { | ||
LOG_ERR("%s: LED device %s is not ready", dev->name, led->dev->name); | ||
return -ENODEV; | ||
} | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
static DEVICE_API(led, leds_group_multicolor_api) = { | ||
.set_color = leds_group_multicolor_set_color, | ||
}; | ||
|
||
#define LED_DT_SPEC_GET_BY_PHANDLE_IDX(node_id, prop, idx) \ | ||
LED_DT_SPEC_GET(DT_PHANDLE_BY_IDX(node_id, prop, idx)) | ||
|
||
#define LEDS_GROUP_MULTICOLOR_DEVICE(inst) \ | ||
\ | ||
BUILD_ASSERT(DT_INST_PROP_LEN(inst, leds) > 0, \ | ||
"at least one LED phandle must be present"); \ | ||
\ | ||
static const struct led_dt_spec led_group_multicolor_##inst[] = { \ | ||
DT_INST_FOREACH_PROP_ELEM_SEP( \ | ||
inst, leds, LED_DT_SPEC_GET_BY_PHANDLE_IDX, (,)) \ | ||
}; \ | ||
\ | ||
static const struct leds_group_multicolor_config \ | ||
leds_group_multicolor_config_##inst = { \ | ||
.num_leds = ARRAY_SIZE(led_group_multicolor_##inst), \ | ||
.led = led_group_multicolor_##inst, \ | ||
}; \ | ||
\ | ||
DEVICE_DT_INST_DEFINE(inst, &leds_group_multicolor_init, NULL, \ | ||
NULL, &leds_group_multicolor_config_##inst, \ | ||
POST_KERNEL, CONFIG_LED_INIT_PRIORITY, \ | ||
&leds_group_multicolor_api); | ||
|
||
DT_INST_FOREACH_STATUS_OKAY(LEDS_GROUP_MULTICOLOR_DEVICE) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# Copyright (c) 2025 Seagate Technology LLC | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
# Common fields for LED nodes | ||
|
||
properties: | ||
label: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks redundant :-o There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You mean redundant with the node name ? There is a discussion here: LED.#92473 (comment). Feel free to join. |
||
type: string | ||
description: | | ||
Human readable string describing the LED. It can be used by an | ||
application to identify this LED or to retrieve its number/index | ||
(i.e. child node number) on the parent device. | ||
bjarki-andreasen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
color-mapping: | ||
type: array | ||
description: | | ||
Channel to color mapping of a multicolor LED. If a LED supports | ||
several colors, then the color-mapping property can be used to | ||
describe how the hardware channels and the colors are mapped. | ||
|
||
For example the channel to color mapping of RGB LEDs would be | ||
|
||
color-mapping = | ||
<LED_COLOR_ID_RED>, | ||
<LED_COLOR_ID_GREEN>, | ||
<LED_COLOR_ID_BLUE>; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
# Copyright (c) 2025 Seagate Technology LLC | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
title: Combines several monochromatic LEDs into one multi-color LED. | ||
|
||
description: | | ||
Here is an example that defines an RGB LED with a group of monochromatic | ||
PWM LEDs. Note that the pwms property definition handle depends on the PWM | ||
controller model. In this example, an STM32 PWM controller is assumed. | ||
|
||
simonguinot marked this conversation as resolved.
Show resolved
Hide resolved
|
||
#include <zephyr/dt-bindings/led/led.h> | ||
|
||
/ { | ||
monochromatic-leds { | ||
compatible = "pwm-leds"; | ||
|
||
red_pwm_led: led-0 { | ||
pwms = <&pwm1 1 PWM_MSEC(20) PWM_POLARITY_NORMAL>; | ||
}; | ||
|
||
green_pwm_led: led-1 { | ||
pwms = <&pwm2 1 PWM_MSEC(20) PWM_POLARITY_NORMAL>; | ||
}; | ||
|
||
blue_pwm_led: led-2 { | ||
pwms = <&pwm3 1 PWM_MSEC(20) PWM_POLARITY_NORMAL>; | ||
}; | ||
}; | ||
|
||
rgb-led { | ||
compatible = "leds-group-multicolor"; | ||
bjarki-andreasen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
leds = <&red_pwm_led>, <&green_pwm_led>, <&blue_pwm_led>; | ||
color-mapping = <LED_COLOR_ID_RED>, | ||
<LED_COLOR_ID_GREEN>, | ||
<LED_COLOR_ID_BLUE>; | ||
}; | ||
}; | ||
|
||
compatible: "leds-group-multicolor" | ||
|
||
include: led-node.yaml | ||
|
||
properties: | ||
leds: | ||
required: true | ||
type: phandles | ||
description: | | ||
References to monochromatic LED nodes. |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -10,6 +10,12 @@ compatible: "pwm-leds" | |||||
|
||||||
child-binding: | ||||||
description: PWM LED child node | ||||||
|
||||||
include: | ||||||
- name: led-node.yaml | ||||||
property-allowlist: | ||||||
- label | ||||||
|
||||||
properties: | ||||||
pwms: | ||||||
required: true | ||||||
|
@@ -22,10 +28,3 @@ child-binding: | |||||
brigtness granularity) and lesser than 50 milliseconds (average visual | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is a typo in
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||
persistence time of the human eye). Typical values for the PWM period | ||||||
are 10 or 20 milliseconds. | ||||||
|
||||||
label: | ||||||
type: string | ||||||
description: | | ||||||
Human readable string describing the LED. It can be used by an | ||||||
application to identify this LED or to retrieve its number/index | ||||||
(i.e. child node number) on the parent device. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,5 @@ | ||
CONFIG_LOG=y | ||
|
||
CONFIG_PWM=y | ||
|
||
CONFIG_LED=y | ||
|
||
CONFIG_LOG_MODE_IMMEDIATE=y |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,3 @@ | ||
CONFIG_TEST=y | ||
CONFIG_TEST_USERSPACE=y | ||
CONFIG_LED=y | ||
CONFIG_PWM=y |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The multi-color LED driver relies on the underlying PWM LED driver (LED_PWM). Add
depends on LED_PWM
to the Kconfig so that the necessary driver is enabled when multi-color support is selected.Copilot uses AI. Check for mistakes.