led_strip: add a APA102 driver.
The APA102 is a RGB LED with integrated controller. LEDs can be daisy-chained and use SPI for communication. The SPI port is configured via Device Tree. Tested on the Adafruit Trinket M0. Signed-off-by: Michael Hope <mlhx@google.com>
This commit is contained in:
parent
d9538ec6b3
commit
8ee282e319
5 changed files with 137 additions and 0 deletions
|
@ -1,2 +1,3 @@
|
|||
zephyr_sources_ifdef(CONFIG_LPD880X_STRIP lpd880x.c)
|
||||
zephyr_sources_ifdef(CONFIG_WS2812_STRIP ws2812.c)
|
||||
zephyr_sources_ifdef(CONFIG_APA102_STRIP apa102.c)
|
||||
|
|
|
@ -46,4 +46,6 @@ source "drivers/led_strip/Kconfig.lpd880x"
|
|||
|
||||
source "drivers/led_strip/Kconfig.ws2812"
|
||||
|
||||
source "drivers/led_strip/Kconfig.apa102"
|
||||
|
||||
endif # LED_STRIP
|
||||
|
|
15
drivers/led_strip/Kconfig.apa102
Normal file
15
drivers/led_strip/Kconfig.apa102
Normal file
|
@ -0,0 +1,15 @@
|
|||
#
|
||||
# Copyright (c) 2018 Google LLC.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
menuconfig APA102_STRIP
|
||||
bool "APA102 SPI LED strip driver"
|
||||
depends on SPI
|
||||
depends on !SPI_LEGACY_API
|
||||
select LED_STRIP_RGB_SCRATCH
|
||||
default n
|
||||
help
|
||||
Enable the LED strip driver for a chain of APA102 RGB LEDs.
|
||||
These are sold as DotStar by Adafruit and Superled by others.
|
102
drivers/led_strip/apa102.c
Normal file
102
drivers/led_strip/apa102.c
Normal file
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Google LLC.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <led_strip.h>
|
||||
#include <spi.h>
|
||||
|
||||
struct apa102_data {
|
||||
struct spi_config cfg;
|
||||
};
|
||||
|
||||
static int apa102_update(struct device *dev, void *buf, size_t size)
|
||||
{
|
||||
struct apa102_data *data = dev->driver_data;
|
||||
static const u8_t zeros[] = {0, 0, 0, 0};
|
||||
static const u8_t ones[] = {0xFF, 0xFF, 0xFF, 0xFF};
|
||||
struct spi_buf tx[] = {
|
||||
{
|
||||
/* Start frame: at least 32 zeros */
|
||||
.buf = (u8_t *)zeros,
|
||||
.len = sizeof(zeros),
|
||||
},
|
||||
{
|
||||
/* LED data itself */
|
||||
.buf = buf,
|
||||
.len = size,
|
||||
},
|
||||
{
|
||||
/* End frame: at least 32 ones to clock the
|
||||
* remaining bits to the LEDs at the end of
|
||||
* the strip.
|
||||
*/
|
||||
.buf = (u8_t *)ones,
|
||||
.len = sizeof(ones),
|
||||
},
|
||||
};
|
||||
|
||||
return spi_write(&data->cfg, tx, ARRAY_SIZE(tx));
|
||||
}
|
||||
|
||||
static int apa102_update_rgb(struct device *dev, struct led_rgb *pixels,
|
||||
size_t count)
|
||||
{
|
||||
u8_t *p = (u8_t *)pixels;
|
||||
size_t i;
|
||||
/* SOF (3 bits) followed by the 0 to 31 global dimming level */
|
||||
u8_t prefix = 0xE0 | 31;
|
||||
|
||||
/* Rewrite to the on-wire format */
|
||||
for (i = 0; i < count; i++) {
|
||||
u8_t r = pixels[i].r;
|
||||
u8_t g = pixels[i].g;
|
||||
u8_t b = pixels[i].b;
|
||||
|
||||
*p++ = prefix;
|
||||
*p++ = b;
|
||||
*p++ = g;
|
||||
*p++ = r;
|
||||
}
|
||||
|
||||
BUILD_ASSERT(sizeof(struct led_rgb) == 4);
|
||||
return apa102_update(dev, pixels, sizeof(struct led_rgb) * count);
|
||||
}
|
||||
|
||||
static int apa102_update_channels(struct device *dev, u8_t *channels,
|
||||
size_t num_channels)
|
||||
{
|
||||
/* Not implemented */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int apa102_init(struct device *dev)
|
||||
{
|
||||
struct apa102_data *data = dev->driver_data;
|
||||
struct device *spi;
|
||||
|
||||
spi = device_get_binding(CONFIG_APA102_STRIP_BUS_NAME);
|
||||
if (!spi) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
data->cfg.dev = spi;
|
||||
data->cfg.frequency = CONFIG_APA102_STRIP_FREQUENCY;
|
||||
data->cfg.operation =
|
||||
SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | SPI_WORD_SET(8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct apa102_data apa102_data_0;
|
||||
|
||||
static const struct led_strip_driver_api apa102_api = {
|
||||
.update_rgb = apa102_update_rgb,
|
||||
.update_channels = apa102_update_channels,
|
||||
};
|
||||
|
||||
DEVICE_AND_API_INIT(apa102_0, CONFIG_APA102_STRIP_NAME, apa102_init,
|
||||
&apa102_data_0, NULL, POST_KERNEL,
|
||||
CONFIG_LED_STRIP_INIT_PRIORITY, &apa102_api);
|
17
dts/bindings/led_strip/apa,apa-102.yaml
Normal file
17
dts/bindings/led_strip/apa,apa-102.yaml
Normal file
|
@ -0,0 +1,17 @@
|
|||
---
|
||||
title: APA102 SPI LED strip
|
||||
id: apa,apa102
|
||||
version: 0.1
|
||||
|
||||
description: APA102 SPI LED strip binding
|
||||
|
||||
inherits:
|
||||
!include spi-device.yaml
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
type: string
|
||||
category: required
|
||||
description: compatible strings
|
||||
constraint: "apa,apa102"
|
||||
...
|
Loading…
Add table
Add a link
Reference in a new issue