Skip to content

Commit 1d1dc09

Browse files
committed
leds: add arduino,modulino-smartleds
Add an led_strip driver for the modulino smartleds module. This is a pluggable I2C board with 8 addressable RGB LEDs The I2C protocol is implemented on an microcontroller on the modulino board itself, the firmware for that is open source and can be updated using an Arduino sketch: Link: https://github.com/arduino/node_modulino_firmware Link: https://github.com/arduino-libraries/Modulino Signed-off-by: Fabio Baltieri <[email protected]>
1 parent 8060a59 commit 1d1dc09

File tree

5 files changed

+144
-0
lines changed

5 files changed

+144
-0
lines changed

drivers/led_strip/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ zephyr_library_sources_ifdef(CONFIG_WS2812_STRIP_I2S ws2812_i2s.c)
1010
zephyr_library_sources_ifdef(CONFIG_WS2812_STRIP_RPI_PICO_PIO ws2812_rpi_pico_pio.c)
1111
zephyr_library_sources_ifdef(CONFIG_TLC5971_STRIP tlc5971.c)
1212
zephyr_library_sources_ifdef(CONFIG_TLC59731_STRIP tlc59731.c)
13+
zephyr_library_sources_ifdef(CONFIG_MODULINO_SMARTLEDS modulino_smartleds.c)

drivers/led_strip/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,6 @@ source "drivers/led_strip/Kconfig.tlc5971"
3737

3838
source "drivers/led_strip/Kconfig.tlc59731"
3939

40+
source "drivers/led_strip/Kconfig.modulino"
41+
4042
endif # LED_STRIP

drivers/led_strip/Kconfig.modulino

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Copyright (c) 2025 Google, LLC
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
config MODULINO_SMARTLEDS
5+
bool "Arduino Modulino smart LEDs"
6+
default y
7+
depends on DT_HAS_ARDUINO_MODULINO_SMARTLEDS_ENABLED
8+
select I2C
9+
help
10+
Enable driver Arduino Modulino smart LEDs.
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/*
2+
* Copyright 2025 Google LLC
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#define DT_DRV_COMPAT arduino_modulino_smartleds
8+
9+
#include <zephyr/device.h>
10+
#include <zephyr/drivers/i2c.h>
11+
#include <zephyr/drivers/led_strip.h>
12+
#include <zephyr/kernel.h>
13+
#include <zephyr/logging/log.h>
14+
#include <zephyr/sys/byteorder.h>
15+
16+
LOG_MODULE_REGISTER(modulino_smartleds, CONFIG_LED_STRIP_LOG_LEVEL);
17+
18+
#define MODULINO_SMARTLEDS_NUM_LEDS 8
19+
20+
/* This is a strip of LC8822 driven by the microcontroller on the Modulino
21+
* board, the start frame is sent automatically, the rest uses the LC8822
22+
* protocol:
23+
* - 4x "1" marker bits
24+
* - 5x brightness bits
25+
* - 3x bytes for B, G, R
26+
*/
27+
28+
#define MODULINO_SMARTLEDS_MARKER (0xe0 << 24)
29+
#define MODULINO_SMARTLEDS_FULL_BRIGHTNESS (0x1f << 24)
30+
31+
struct modulino_smartleds_config {
32+
struct i2c_dt_spec bus;
33+
};
34+
35+
struct modulino_smartleds_data {
36+
uint32_t buf[MODULINO_SMARTLEDS_NUM_LEDS];
37+
};
38+
39+
static int modulino_smartleds_update_rgb(const struct device *dev,
40+
struct led_rgb *pixels,
41+
size_t count)
42+
{
43+
const struct modulino_smartleds_config *cfg = dev->config;
44+
struct modulino_smartleds_data *data = dev->data;
45+
int ret;
46+
47+
if (count > MODULINO_SMARTLEDS_NUM_LEDS) {
48+
return -EINVAL;
49+
}
50+
51+
for (uint8_t i = 0; i < count; i++) {
52+
data->buf[i] = sys_cpu_to_be32(
53+
MODULINO_SMARTLEDS_MARKER |
54+
MODULINO_SMARTLEDS_FULL_BRIGHTNESS |
55+
(pixels[i].b << 16) |
56+
(pixels[i].g << 8) |
57+
pixels[i].r);
58+
}
59+
60+
ret = i2c_write_dt(&cfg->bus, (uint8_t *)data->buf, sizeof(data->buf));
61+
if (ret < 0) {
62+
LOG_ERR("i2c write error: %d", ret);
63+
return ret;
64+
}
65+
66+
return 0;
67+
}
68+
69+
static size_t modulino_smartleds_length(const struct device *dev)
70+
{
71+
return MODULINO_SMARTLEDS_NUM_LEDS;
72+
}
73+
74+
static int modulino_smartleds_init(const struct device *dev)
75+
{
76+
const struct modulino_smartleds_config *cfg = dev->config;
77+
struct modulino_smartleds_data *data = dev->data;
78+
int ret;
79+
80+
if (!i2c_is_ready_dt(&cfg->bus)) {
81+
LOG_ERR("Bus device is not ready");
82+
return -ENODEV;
83+
}
84+
85+
for (uint8_t i = 0; i < ARRAY_SIZE(data->buf); i++) {
86+
data->buf[i] = sys_cpu_to_be32(MODULINO_SMARTLEDS_MARKER);
87+
}
88+
89+
/* Reset to all LEDs off */
90+
ret = i2c_write_dt(&cfg->bus, (uint8_t *)data->buf, sizeof(data->buf));
91+
if (ret < 0) {
92+
LOG_ERR("i2c write error: %d", ret);
93+
return ret;
94+
}
95+
96+
return 0;
97+
}
98+
99+
static DEVICE_API(led_strip, modulino_smartleds_api) = {
100+
.update_rgb = modulino_smartleds_update_rgb,
101+
.length = modulino_smartleds_length,
102+
};
103+
104+
#define MODULINO_SMARTLEDS_INIT(inst) \
105+
static const struct modulino_smartleds_config \
106+
modulino_smartleds_cfg_##inst = { \
107+
.bus = I2C_DT_SPEC_INST_GET(inst), \
108+
}; \
109+
\
110+
static struct modulino_smartleds_data modulino_smartleds_data_##inst; \
111+
\
112+
DEVICE_DT_INST_DEFINE(inst, modulino_smartleds_init, NULL, \
113+
&modulino_smartleds_data_##inst, \
114+
&modulino_smartleds_cfg_##inst, \
115+
POST_KERNEL, CONFIG_LED_STRIP_INIT_PRIORITY, \
116+
&modulino_smartleds_api);
117+
118+
119+
DT_INST_FOREACH_STATUS_OKAY(MODULINO_SMARTLEDS_INIT)
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Copyright (c) 2025 Google, LLC
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
description: Arduino Modulino smart LEDs
5+
6+
compatible: "arduino,modulino-smartleds"
7+
8+
include: [led-strip.yaml, i2c-device.yaml]
9+
10+
properties:
11+
reg:
12+
required: true

0 commit comments

Comments
 (0)