Skip to content

Commit 37cbd64

Browse files
committed
drivers: led: is31fl319x - redo color to channel
Removed the driver knowing anything about what color each channel is. When you output to an LED with a buffer it simply writes the channels out with buffer. Also removed the assumptions that the leds are either a) RGB or b) 3 channels and instead use them the way they are defined. That is for example if we have 4 channels, we could define an LED with just one color in it and we could define another with three. The user can define 4 leds each with color yellow. For each LED it counts how many buffers were used by previous LEDs and starts there and outputs N channels. Decided it looked cleaner to use helper function write channels, so implemented it and added it to the call table. Updated example sketch: It manually computes which channel maps to red, green and blue and then uses those indexes to map the table of colors to the right channels. Signed-off-by: Kurt Eckhardt <[email protected]> sample changes
1 parent a0eee77 commit 37cbd64

File tree

3 files changed

+189
-124
lines changed

3 files changed

+189
-124
lines changed

drivers/led/is31fl319x.c

Lines changed: 66 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -104,45 +104,35 @@ static int is31fl319x_get_info(const struct device *dev,
104104
return 0;
105105
}
106106

107-
static int is31fl319x_set_color(const struct device *dev, uint32_t led, uint8_t num_colors,
108-
const uint8_t *color)
107+
static uint8_t is31fl319x_map_led_to_start_channel(const struct is31fl319x_config *config,
108+
uint32_t led)
109+
{
110+
/* It is assumed that led has been validated before calling this */
111+
const struct led_info *info = config->led_infos;
112+
uint8_t channel = 0;
113+
114+
while (led) {
115+
channel += info->num_colors;
116+
led--;
117+
info++;
118+
}
119+
return channel;
120+
}
121+
122+
static int is31fl319x_write_channels(const struct device *dev, uint32_t start_channel,
123+
uint32_t num_channels, const uint8_t *buf)
109124
{
110125
const struct is31fl319x_config *config = dev->config;
111-
const struct led_info *info = is31fl319x_led_to_info(config, led);
112126
const struct is31f1319x_model *regs = config->regs;
113127
int ret;
114128

115-
if (info == NULL) {
116-
return -ENODEV;
117-
}
118-
119-
if (info->num_colors > config->channel_count) {
129+
if ((start_channel + num_channels) > config->channel_count) {
120130
return -ENOTSUP;
121131
}
122132

123-
if (num_colors > config->channel_count) {
124-
return -ENOTSUP;
125-
}
126-
127-
for (int i = 0; i < num_colors; i++) {
128-
uint8_t value;
129-
130-
switch (info->color_mapping[i]) {
131-
case LED_COLOR_ID_RED:
132-
value = color[0];
133-
break;
134-
case LED_COLOR_ID_GREEN:
135-
value = color[1];
136-
break;
137-
case LED_COLOR_ID_BLUE:
138-
value = color[2];
139-
break;
140-
default:
141-
/* unreachable: mapping already tested in is31fl319x_check_config */
142-
return -EINVAL;
143-
}
144-
145-
ret = i2c_reg_write_byte_dt(&config->bus, regs->led_channels[i], value);
133+
for (int i = 0; i < num_channels; i++) {
134+
ret = i2c_reg_write_byte_dt(&config->bus, regs->led_channels[i + start_channel],
135+
buf[i]);
146136
if (ret != 0) {
147137
break;
148138
}
@@ -161,6 +151,25 @@ static int is31fl319x_set_color(const struct device *dev, uint32_t led, uint8_t
161151
return ret;
162152
}
163153

154+
static int is31fl319x_set_color(const struct device *dev, uint32_t led, uint8_t num_colors,
155+
const uint8_t *color)
156+
{
157+
const struct is31fl319x_config *config = dev->config;
158+
const struct led_info *info = is31fl319x_led_to_info(config, led);
159+
160+
if (info == NULL) {
161+
return -ENODEV;
162+
}
163+
164+
uint8_t channel_start = is31fl319x_map_led_to_start_channel(config, led);
165+
166+
if (info->num_colors > config->channel_count) {
167+
return -ENOTSUP;
168+
}
169+
170+
return is31fl319x_write_channels(dev, channel_start, num_colors, color);
171+
}
172+
164173
static int is31fl319x_set_brightness(const struct device *dev, uint32_t led, uint8_t value)
165174
{
166175
const struct is31fl319x_config *config = dev->config;
@@ -180,7 +189,9 @@ static int is31fl319x_set_brightness(const struct device *dev, uint32_t led, uin
180189
/* Rescale 0..100 to 0..255 */
181190
value = value * 255 / LED_BRIGHTNESS_MAX;
182191

183-
ret = i2c_reg_write_byte_dt(&config->bus, regs->led_channels[led], value);
192+
uint8_t channel_start = is31fl319x_map_led_to_start_channel(config, led);
193+
194+
ret = i2c_reg_write_byte_dt(&config->bus, regs->led_channels[channel_start], value);
184195
if (ret == 0) {
185196
ret = i2c_reg_write_byte_dt(&config->bus,
186197
regs->update_reg,
@@ -194,81 +205,20 @@ static int is31fl319x_set_brightness(const struct device *dev, uint32_t led, uin
194205
return ret;
195206
}
196207

197-
/*
198-
* Counts red, green, blue channels; returns true if color_id is valid
199-
* and no more than one channel maps to the same color
200-
*/
201-
static bool is31fl319x_count_colors(const struct device *dev,
202-
uint8_t color_id, uint8_t *rgb_counts)
203-
{
204-
bool ret = false;
205-
206-
switch (color_id) {
207-
case LED_COLOR_ID_RED:
208-
ret = (++rgb_counts[0] == 1);
209-
break;
210-
case LED_COLOR_ID_GREEN:
211-
ret = (++rgb_counts[1] == 1);
212-
break;
213-
case LED_COLOR_ID_BLUE:
214-
ret = (++rgb_counts[2] == 1);
215-
break;
216-
}
217-
218-
if (!ret) {
219-
LOG_ERR("%s: invalid color %d (duplicate or not RGB)",
220-
dev->name, color_id);
221-
}
222-
223-
return ret;
224-
}
225-
226208
static int is31fl319x_check_config(const struct device *dev)
227209
{
228210
const struct is31fl319x_config *config = dev->config;
229211
const struct led_info *info;
230-
uint8_t rgb_counts[3] = { 0 };
212+
uint8_t rgb_count = 0;
231213
uint8_t i;
232214

233-
switch (config->num_leds) {
234-
case 1:
235-
/* check that it is a three-channel LED */
236-
info = &config->led_infos[0];
237-
238-
if (info->num_colors != 3) {
239-
LOG_ERR("%s: invalid number of colors %d "
240-
"(must be 3 for RGB LED)",
241-
dev->name, info->num_colors);
242-
return -EINVAL;
243-
}
244-
245-
for (i = 0; i < 3; i++) {
246-
if (!is31fl319x_count_colors(dev, info->color_mapping[i], rgb_counts)) {
247-
return -EINVAL;
248-
}
249-
250-
}
251-
break;
252-
case 3:
253-
/* check that each LED is single-color */
254-
for (i = 0; i < 3; i++) {
255-
info = &config->led_infos[i];
256-
257-
if (info->num_colors != 1) {
258-
LOG_ERR("%s: invalid number of colors %d "
259-
"(must be 1 when defining multiple LEDs)",
260-
dev->name, info->num_colors);
261-
return -EINVAL;
262-
}
215+
/* verify that number of leds defined is not > number of channels */
216+
for (i = 0; i < config->num_leds; i++) {
217+
info = &config->led_infos[i];
218+
rgb_count += info->num_colors;
219+
}
263220

264-
if (!is31fl319x_count_colors(dev, info->color_mapping[0], rgb_counts)) {
265-
return -EINVAL;
266-
}
267-
}
268-
break;
269-
default:
270-
LOG_ERR("%s: invalid number of LEDs %d (must be 1 or 3)",
271-
dev->name, config->num_leds);
221+
if (rgb_count > config->channel_count) {
272222
return -EINVAL;
273223
}
274224

@@ -280,8 +230,8 @@ static int is31fl319x_init(const struct device *dev)
280230
const struct is31fl319x_config *config = dev->config;
281231
const struct led_info *info = NULL;
282232
const struct is31f1319x_model *regs = config->regs;
283-
int i, ret;
284-
uint8_t prod_id, band;
233+
int i, j, ret;
234+
uint8_t prod_id, band, channel;
285235
uint8_t current_reg = 0;
286236

287237
ret = is31fl319x_check_config(dev);
@@ -307,27 +257,24 @@ static int is31fl319x_init(const struct device *dev)
307257
}
308258

309259
/* calc current limit register value */
310-
info = &config->led_infos[0];
311-
if (info->num_colors == IS31FL3194_CHANNEL_COUNT) {
312-
/* one RGB LED: set all channels to the same current limit */
313-
band = (config->current_limits[0] / 10) - 1;
314-
for (i = 0; i < IS31FL3194_CHANNEL_COUNT; i++) {
315-
current_reg |= band << (2 * i);
316-
}
317-
} else {
318-
/* single-channel LEDs: independent limits */
260+
if (regs->current_reg != REG_NOT_DEFINED) {
261+
channel = 0;
319262
for (i = 0; i < config->num_leds; i++) {
263+
info = &config->led_infos[i];
320264
band = (config->current_limits[i] / 10) - 1;
321-
current_reg |= band << (2 * i);
265+
266+
for (j = 0; j < info->num_colors; j++) {
267+
current_reg |= band << (2 * channel);
268+
channel++;
269+
}
322270
}
323-
}
324271

325-
ret = i2c_reg_write_byte_dt(&config->bus, IS31FL3194_CURRENT_REG, current_reg);
326-
if (ret != 0) {
327-
LOG_ERR("%s: failed to set current limit", dev->name);
328-
return ret;
272+
ret = i2c_reg_write_byte_dt(&config->bus, regs->current_reg, current_reg);
273+
if (ret != 0) {
274+
LOG_ERR("%s: failed to set current limit", dev->name);
275+
return ret;
276+
}
329277
}
330-
331278
/* enable device */
332279
return i2c_reg_write_byte_dt(&config->bus, regs->conf_reg,
333280
regs->conf_enable);
@@ -337,6 +284,7 @@ static DEVICE_API(led, is31fl319x_led_api) = {
337284
.set_brightness = is31fl319x_set_brightness,
338285
.get_info = is31fl319x_get_info,
339286
.set_color = is31fl319x_set_color,
287+
.write_channels = is31fl319x_write_channels,
340288
};
341289

342290
#define COLOR_MAPPING(led_node_id) \

samples/drivers/led/is31fl319x/README.rst

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,23 @@
22
:name: IS31FL319x RGB LED
33
:relevant-api: led_interface
44

5-
Cycle colors on an RGB LED connected to the IS31FL3194 using the LED API.
5+
Cycle colors on an RGB LED connected to the IS31FL3194 or IS31FL3197
6+
using the LED API.
67

78
Overview
89
********
910

10-
This sample cycles several colors on an RGB LED forever using the LED API.
11+
This sample first looks through the color table to map which channels
12+
map to Red, Green and Blue.
13+
14+
It then shows the mapping, but setting one color on and fading it
15+
off. First Red, then Green and finally Blue.
16+
17+
It then forever cycles through several colors on an RGB LED. It uses a
18+
helper function, that maps the RGB colors into the correct order
19+
for the actual hardware LED, as some hardware LEDs will be defined in
20+
RGB order whereas others may be in another order such as BGR.
21+
Once mapped it calls off to the led library to display the color.
1122

1223
Building and Running
1324
********************
@@ -18,11 +29,18 @@ any board where the devicetree has an I2C device node with compatible
1829
controller node also being enabled.
1930

2031
.. zephyr-app-commands::
21-
:zephyr-app: samples/drivers/led/is31fl3194
32+
:zephyr-app: samples/drivers/led/is31fl319x
2233
:board: arduino_nicla_sense_me
2334
:goals: build flash
2435
:compact:
2536

37+
.. zephyr-app-commands::
38+
:zephyr-app: samples/drivers/led/is31fl319x
39+
:board: arduino_giga_r1//m7
40+
:shield: arduino_giga_display_shield
41+
:goals: build flash
42+
:compact:
43+
2644
After flashing, the LED starts to switch colors and messages with the current
2745
LED color are printed on the console. If a runtime error occurs, the sample
2846
exits without printing to the console.

0 commit comments

Comments
 (0)