Skip to content

Commit 27220d0

Browse files
committed
led: seesaw_neopixel: new driver
Add new LED driver for the Adafruit Seesaw neopixel controller. Because the seesaw module holds the color buffer, it is possible to control individual leds, instead of refreshing the entire strip everytime Signed-off-by: Titouan Christophe <[email protected]>
1 parent 59a4137 commit 27220d0

File tree

5 files changed

+136
-0
lines changed

5 files changed

+136
-0
lines changed

drivers/led/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ zephyr_library_sources_ifdef(CONFIG_LP5562 lp5562.c)
2121
zephyr_library_sources_ifdef(CONFIG_LP5569 lp5569.c)
2222
zephyr_library_sources_ifdef(CONFIG_NCP5623 ncp5623.c)
2323
zephyr_library_sources_ifdef(CONFIG_PCA9633 pca9633.c)
24+
zephyr_library_sources_ifdef(CONFIG_SEESAW_NEOPIXEL seesaw_neopixel.c)
2425
zephyr_library_sources_ifdef(CONFIG_TLC59108 tlc59108.c)
2526
# zephyr-keep-sorted-stop
2627

drivers/led/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ source "drivers/led/Kconfig.ncp5623"
4242
source "drivers/led/Kconfig.npm1300"
4343
source "drivers/led/Kconfig.pca9633"
4444
source "drivers/led/Kconfig.pwm"
45+
source "drivers/led/Kconfig.seesaw_neopixel"
4546
source "drivers/led/Kconfig.tlc59108"
4647
source "drivers/led/Kconfig.xec"
4748
# zephyr-keep-sorted-stop
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Copyright 2025 Titouan Chrisotphe
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
config SEESAW_NEOPIXEL
5+
bool "Adafruit Seesaw neopixel leds over I2C"
6+
default y
7+
depends on MFD_SEESAW
8+
depends on DT_HAS_ADAFRUIT_SEESAW_NEOPIXEL_ENABLED
9+
help
10+
Enable support for Adafruit Seesaw neopixel leds

drivers/led/seesaw_neopixel.c

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/*
2+
* Copyright (c) 2025 Titouan Christophe
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#define DT_DRV_COMPAT adafruit_seesaw_neopixel
8+
9+
#include <zephyr/drivers/led.h>
10+
#include <zephyr/drivers/mfd/mfd_seesaw.h>
11+
#include <zephyr/dt-bindings/led/led.h>
12+
13+
enum seesaw_mod_neopixel {
14+
NEOPIXEL_PIN = 0x01,
15+
NEOPIXEL_SPEED = 0x02,
16+
NEOPIXEL_BUF_LENGTH = 0x03,
17+
NEOPIXEL_BUF = 0x04,
18+
NEOPIXEL_SHOW = 0x05,
19+
};
20+
21+
struct seesaw_neopixel_config {
22+
const struct device *seesaw;
23+
size_t length;
24+
const uint8_t *color_mapping;
25+
uint8_t num_colors;
26+
uint8_t output_pin;
27+
};
28+
29+
static int seesaw_neopixel_set_color(const struct device *dev, uint32_t led, uint8_t num_colors,
30+
const uint8_t *color)
31+
{
32+
int ret;
33+
const struct seesaw_neopixel_config *config = dev->config;
34+
uint16_t offset = config->num_colors * led;
35+
uint8_t buf[6] = {offset >> 8, offset & 0xff};
36+
37+
if (led >= config->length || num_colors != config->num_colors) {
38+
return -EINVAL;
39+
}
40+
41+
memcpy(buf + 2, color, num_colors);
42+
43+
ret = seesaw_write(config->seesaw, SEESAW_MOD_NEOPIXEL, NEOPIXEL_BUF, buf, 2 + num_colors);
44+
if (ret) {
45+
return ret;
46+
}
47+
48+
return seesaw_cmd(config->seesaw, SEESAW_MOD_NEOPIXEL, NEOPIXEL_SHOW);
49+
}
50+
51+
static int seesaw_neopixel_set_brightness(const struct device *dev, uint32_t led, uint8_t value)
52+
{
53+
const struct seesaw_neopixel_config *config = dev->config;
54+
uint8_t b = 255 * value / 100;
55+
uint8_t color[] = {b, b, b, b};
56+
57+
if (value > 100) {
58+
return -EINVAL;
59+
}
60+
61+
return seesaw_neopixel_set_color(dev, led, config->num_colors, color);
62+
}
63+
64+
static int seesaw_neopixel_on(const struct device *dev, uint32_t led)
65+
{
66+
return seesaw_neopixel_set_brightness(dev, led, 100);
67+
}
68+
69+
static int seesaw_neopixel_off(const struct device *dev, uint32_t led)
70+
{
71+
return seesaw_neopixel_set_brightness(dev, led, 0);
72+
}
73+
74+
static int seesaw_neopixel_init(const struct device *dev)
75+
{
76+
const struct seesaw_neopixel_config *config = dev->config;
77+
int ret = seesaw_claim_module(config->seesaw, SEESAW_MOD_NEOPIXEL, dev);
78+
79+
if (ret) {
80+
return ret;
81+
}
82+
83+
seesaw_write(config->seesaw, SEESAW_MOD_NEOPIXEL, NEOPIXEL_PIN, &config->output_pin, 1);
84+
seesaw_write_uint16(config->seesaw, SEESAW_MOD_NEOPIXEL,
85+
NEOPIXEL_BUF_LENGTH, 3 * config->length);
86+
87+
return 0;
88+
}
89+
90+
static DEVICE_API(led, seesaw_neopixel_api) = {
91+
.on = seesaw_neopixel_on,
92+
.off = seesaw_neopixel_off,
93+
.set_brightness = seesaw_neopixel_set_brightness,
94+
.set_color = seesaw_neopixel_set_color,
95+
};
96+
97+
#define SEESAW_NEOPIXEL_INIT(inst) \
98+
static const uint8_t cmap_##idx[] = DT_INST_PROP(inst, color_mapping); \
99+
static const struct seesaw_neopixel_config config_##inst = { \
100+
.seesaw = DEVICE_DT_GET(DT_INST_PARENT(inst)), \
101+
.length = DT_INST_PROP(inst, chain_length), \
102+
.color_mapping = cmap_##idx, \
103+
.num_colors = sizeof(cmap_##idx), \
104+
.output_pin = DT_INST_PROP(inst, output_pin), \
105+
}; \
106+
DEVICE_DT_INST_DEFINE(inst, seesaw_neopixel_init, NULL, NULL, &config_##inst, POST_KERNEL, \
107+
CONFIG_LED_INIT_PRIORITY, &seesaw_neopixel_api);
108+
109+
DT_INST_FOREACH_STATUS_OKAY(SEESAW_NEOPIXEL_INIT)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Copyright (c) 2025 Titouan Christophe
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
description: Adafruit Seesaw neopixel output
5+
6+
compatible: "adafruit,seesaw-neopixel"
7+
8+
include: [led-strip.yaml]
9+
10+
properties:
11+
output-pin:
12+
required: true
13+
type: int
14+
description: |
15+
Neopixel output pin number

0 commit comments

Comments
 (0)