Browse Source

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 <fabiobaltieri@google.com>
pull/87710/merge
Fabio Baltieri 3 months ago committed by Fabio Baltieri
parent
commit
1d1dc09ca3
  1. 1
      drivers/led_strip/CMakeLists.txt
  2. 2
      drivers/led_strip/Kconfig
  3. 10
      drivers/led_strip/Kconfig.modulino
  4. 119
      drivers/led_strip/modulino_smartleds.c
  5. 12
      dts/bindings/led_strip/arduino,modulino-smartleds.yaml

1
drivers/led_strip/CMakeLists.txt

@ -10,3 +10,4 @@ zephyr_library_sources_ifdef(CONFIG_WS2812_STRIP_I2S ws2812_i2s.c) @@ -10,3 +10,4 @@ zephyr_library_sources_ifdef(CONFIG_WS2812_STRIP_I2S ws2812_i2s.c)
zephyr_library_sources_ifdef(CONFIG_WS2812_STRIP_RPI_PICO_PIO ws2812_rpi_pico_pio.c)
zephyr_library_sources_ifdef(CONFIG_TLC5971_STRIP tlc5971.c)
zephyr_library_sources_ifdef(CONFIG_TLC59731_STRIP tlc59731.c)
zephyr_library_sources_ifdef(CONFIG_MODULINO_SMARTLEDS modulino_smartleds.c)

2
drivers/led_strip/Kconfig

@ -37,4 +37,6 @@ source "drivers/led_strip/Kconfig.tlc5971" @@ -37,4 +37,6 @@ source "drivers/led_strip/Kconfig.tlc5971"
source "drivers/led_strip/Kconfig.tlc59731"
source "drivers/led_strip/Kconfig.modulino"
endif # LED_STRIP

10
drivers/led_strip/Kconfig.modulino

@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
# Copyright (c) 2025 Google, LLC
# SPDX-License-Identifier: Apache-2.0
config MODULINO_SMARTLEDS
bool "Arduino Modulino smart LEDs"
default y
depends on DT_HAS_ARDUINO_MODULINO_SMARTLEDS_ENABLED
select I2C
help
Enable driver Arduino Modulino smart LEDs.

119
drivers/led_strip/modulino_smartleds.c

@ -0,0 +1,119 @@ @@ -0,0 +1,119 @@
/*
* Copyright 2025 Google LLC
*
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT arduino_modulino_smartleds
#include <zephyr/device.h>
#include <zephyr/drivers/i2c.h>
#include <zephyr/drivers/led_strip.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/sys/byteorder.h>
LOG_MODULE_REGISTER(modulino_smartleds, CONFIG_LED_STRIP_LOG_LEVEL);
#define MODULINO_SMARTLEDS_NUM_LEDS 8
/* This is a strip of LC8822 driven by the microcontroller on the Modulino
* board, the start frame is sent automatically, the rest uses the LC8822
* protocol:
* - 4x "1" marker bits
* - 5x brightness bits
* - 3x bytes for B, G, R
*/
#define MODULINO_SMARTLEDS_MARKER (0xe0 << 24)
#define MODULINO_SMARTLEDS_FULL_BRIGHTNESS (0x1f << 24)
struct modulino_smartleds_config {
struct i2c_dt_spec bus;
};
struct modulino_smartleds_data {
uint32_t buf[MODULINO_SMARTLEDS_NUM_LEDS];
};
static int modulino_smartleds_update_rgb(const struct device *dev,
struct led_rgb *pixels,
size_t count)
{
const struct modulino_smartleds_config *cfg = dev->config;
struct modulino_smartleds_data *data = dev->data;
int ret;
if (count > MODULINO_SMARTLEDS_NUM_LEDS) {
return -EINVAL;
}
for (uint8_t i = 0; i < count; i++) {
data->buf[i] = sys_cpu_to_be32(
MODULINO_SMARTLEDS_MARKER |
MODULINO_SMARTLEDS_FULL_BRIGHTNESS |
(pixels[i].b << 16) |
(pixels[i].g << 8) |
pixels[i].r);
}
ret = i2c_write_dt(&cfg->bus, (uint8_t *)data->buf, sizeof(data->buf));
if (ret < 0) {
LOG_ERR("i2c write error: %d", ret);
return ret;
}
return 0;
}
static size_t modulino_smartleds_length(const struct device *dev)
{
return MODULINO_SMARTLEDS_NUM_LEDS;
}
static int modulino_smartleds_init(const struct device *dev)
{
const struct modulino_smartleds_config *cfg = dev->config;
struct modulino_smartleds_data *data = dev->data;
int ret;
if (!i2c_is_ready_dt(&cfg->bus)) {
LOG_ERR("Bus device is not ready");
return -ENODEV;
}
for (uint8_t i = 0; i < ARRAY_SIZE(data->buf); i++) {
data->buf[i] = sys_cpu_to_be32(MODULINO_SMARTLEDS_MARKER);
}
/* Reset to all LEDs off */
ret = i2c_write_dt(&cfg->bus, (uint8_t *)data->buf, sizeof(data->buf));
if (ret < 0) {
LOG_ERR("i2c write error: %d", ret);
return ret;
}
return 0;
}
static DEVICE_API(led_strip, modulino_smartleds_api) = {
.update_rgb = modulino_smartleds_update_rgb,
.length = modulino_smartleds_length,
};
#define MODULINO_SMARTLEDS_INIT(inst) \
static const struct modulino_smartleds_config \
modulino_smartleds_cfg_##inst = { \
.bus = I2C_DT_SPEC_INST_GET(inst), \
}; \
\
static struct modulino_smartleds_data modulino_smartleds_data_##inst; \
\
DEVICE_DT_INST_DEFINE(inst, modulino_smartleds_init, NULL, \
&modulino_smartleds_data_##inst, \
&modulino_smartleds_cfg_##inst, \
POST_KERNEL, CONFIG_LED_STRIP_INIT_PRIORITY, \
&modulino_smartleds_api);
DT_INST_FOREACH_STATUS_OKAY(MODULINO_SMARTLEDS_INIT)

12
dts/bindings/led_strip/arduino,modulino-smartleds.yaml

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
# Copyright (c) 2025 Google, LLC
# SPDX-License-Identifier: Apache-2.0
description: Arduino Modulino smart LEDs
compatible: "arduino,modulino-smartleds"
include: [led-strip.yaml, i2c-device.yaml]
properties:
reg:
required: true
Loading…
Cancel
Save