Skip to content

Commit b8a9e4a

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 sample: 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]> for (int
1 parent d9f973d commit b8a9e4a

File tree

3 files changed

+194
-127
lines changed

3 files changed

+194
-127
lines changed

drivers/led/is31fl319x.c

Lines changed: 70 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -104,45 +104,36 @@ 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;
128+
int i;
114129

115-
if (info == NULL) {
116-
return -ENODEV;
117-
}
118-
119-
if (info->num_colors > config->channel_count) {
130+
if ((start_channel + num_channels) > config->channel_count) {
120131
return -ENOTSUP;
121132
}
122133

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);
134+
for (i = 0; i < num_channels; i++) {
135+
ret = i2c_reg_write_byte_dt(&config->bus, regs->led_channels[i + start_channel],
136+
buf[i]);
146137
if (ret != 0) {
147138
break;
148139
}
@@ -161,11 +152,32 @@ static int is31fl319x_set_color(const struct device *dev, uint32_t led, uint8_t
161152
return ret;
162153
}
163154

155+
static int is31fl319x_set_color(const struct device *dev, uint32_t led, uint8_t num_colors,
156+
const uint8_t *color)
157+
{
158+
const struct is31fl319x_config *config = dev->config;
159+
const struct led_info *info = is31fl319x_led_to_info(config, led);
160+
uint8_t channel_start;
161+
162+
if (info == NULL) {
163+
return -ENODEV;
164+
}
165+
166+
channel_start = is31fl319x_map_led_to_start_channel(config, led);
167+
168+
if (info->num_colors > config->channel_count) {
169+
return -ENOTSUP;
170+
}
171+
172+
return is31fl319x_write_channels(dev, channel_start, num_colors, color);
173+
}
174+
164175
static int is31fl319x_set_brightness(const struct device *dev, uint32_t led, uint8_t value)
165176
{
166177
const struct is31fl319x_config *config = dev->config;
167178
const struct led_info *info = is31fl319x_led_to_info(config, led);
168179
const struct is31f1319x_model *regs = config->regs;
180+
uint8_t channel_start;
169181

170182
int ret = 0;
171183

@@ -180,7 +192,9 @@ static int is31fl319x_set_brightness(const struct device *dev, uint32_t led, uin
180192
/* Rescale 0..100 to 0..255 */
181193
value = value * 255 / LED_BRIGHTNESS_MAX;
182194

183-
ret = i2c_reg_write_byte_dt(&config->bus, regs->led_channels[led], value);
195+
channel_start = is31fl319x_map_led_to_start_channel(config, led);
196+
197+
ret = i2c_reg_write_byte_dt(&config->bus, regs->led_channels[channel_start], value);
184198
if (ret == 0) {
185199
ret = i2c_reg_write_byte_dt(&config->bus,
186200
regs->update_reg,
@@ -194,81 +208,20 @@ static int is31fl319x_set_brightness(const struct device *dev, uint32_t led, uin
194208
return ret;
195209
}
196210

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-
226211
static int is31fl319x_check_config(const struct device *dev)
227212
{
228213
const struct is31fl319x_config *config = dev->config;
229214
const struct led_info *info;
230-
uint8_t rgb_counts[3] = { 0 };
215+
uint8_t rgb_count = 0;
231216
uint8_t i;
232217

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-
}
218+
/* verify that number of leds defined is not > number of channels */
219+
for (i = 0; i < config->num_leds; i++) {
220+
info = &config->led_infos[i];
221+
rgb_count += info->num_colors;
222+
}
263223

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);
224+
if (rgb_count > config->channel_count) {
272225
return -EINVAL;
273226
}
274227

@@ -280,9 +233,10 @@ static int is31fl319x_init(const struct device *dev)
280233
const struct is31fl319x_config *config = dev->config;
281234
const struct led_info *info = NULL;
282235
const struct is31f1319x_model *regs = config->regs;
283-
int i, ret;
284-
uint8_t prod_id, band;
236+
int i, j, ret;
237+
uint8_t prod_id, band, channel;
285238
uint8_t current_reg = 0;
239+
int i, j;
286240

287241
ret = is31fl319x_check_config(dev);
288242
if (ret != 0) {
@@ -307,27 +261,24 @@ static int is31fl319x_init(const struct device *dev)
307261
}
308262

309263
/* 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 */
264+
if (regs->current_reg != REG_NOT_DEFINED) {
265+
channel = 0;
319266
for (i = 0; i < config->num_leds; i++) {
267+
info = &config->led_infos[i];
320268
band = (config->current_limits[i] / 10) - 1;
321-
current_reg |= band << (2 * i);
269+
270+
for (j = 0; j < info->num_colors; j++) {
271+
current_reg |= band << (2 * channel);
272+
channel++;
273+
}
322274
}
323-
}
324275

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;
276+
ret = i2c_reg_write_byte_dt(&config->bus, regs->current_reg, current_reg);
277+
if (ret != 0) {
278+
LOG_ERR("%s: failed to set current limit", dev->name);
279+
return ret;
280+
}
329281
}
330-
331282
/* enable device */
332283
return i2c_reg_write_byte_dt(&config->bus, regs->conf_reg,
333284
regs->conf_enable);
@@ -337,6 +288,7 @@ static DEVICE_API(led, is31fl319x_led_api) = {
337288
.set_brightness = is31fl319x_set_brightness,
338289
.get_info = is31fl319x_get_info,
339290
.set_color = is31fl319x_set_color,
291+
.write_channels = is31fl319x_write_channels,
340292
};
341293

342294
#define COLOR_MAPPING(led_node_id) \
@@ -377,7 +329,6 @@ static DEVICE_API(led, is31fl319x_led_api) = {
377329
&is31fl319##id##_config_##n, POST_KERNEL, \
378330
CONFIG_LED_INIT_PRIORITY, &is31fl319x_led_api);
379331

380-
#undef DT_DRV_COMPAT
381332
#define DT_DRV_COMPAT issi_is31fl3194
382333
DT_INST_FOREACH_STATUS_OKAY_VARGS(IS31FL319X_DEVICE, 4, IS31FL3194_CHANNEL_COUNT,
383334
&is31f13194_model)

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)