Skip to content
Snippets Groups Projects
Commit 05be6cb9 authored by Cenk Gündoğan's avatar Cenk Gündoğan Committed by GitHub
Browse files

Merge pull request #5732 from haukepetersen/add_driver_lpd8808

drivers: add support for LPD8808 based LED stripes
parents bee57a4d 79087086
No related branches found
No related tags found
No related merge requests found
...@@ -94,6 +94,11 @@ ifneq (,$(filter lm75a,$(USEMODULE))) ...@@ -94,6 +94,11 @@ ifneq (,$(filter lm75a,$(USEMODULE)))
USEMODULE += xtimer USEMODULE += xtimer
endif endif
ifneq (,$(filter lpd8808,$(USEMODULE)))
USEMODULE += color
FEATURES_REQUIRED += periph_gpio
endif
ifneq (,$(filter ltc4150,$(USEMODULE))) ifneq (,$(filter ltc4150,$(USEMODULE)))
USEMODULE += xtimer USEMODULE += xtimer
endif endif
......
...@@ -67,3 +67,6 @@ endif ...@@ -67,3 +67,6 @@ endif
ifneq (,$(filter cc2420,$(USEMODULE))) ifneq (,$(filter cc2420,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/cc2420/include USEMODULE_INCLUDES += $(RIOTBASE)/drivers/cc2420/include
endif endif
ifneq (,$(filter lpd8808,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/lpd8808/include
endif
/*
* Copyright (C) 2016 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @defgroup drivers_lpd8808 LPD8808 based LED Strip
* @ingroup drivers
* @brief Driver for LPD8808 based LED strips
*
* LPD8808 based LED strips consist of a number of LEDs driven by LPD8808 chips.
* In these strips, each LED can be controlled individually. For this, every two
* LEDs are driven by a LPD8808 chip, which are chained and form a long shift
* register. To control a certain LED, the target color value needs to be
* shifted to the LEDs position on the strip.
*
* This driver implementation does not buffer the current values for each LED.
* It expects the application to take care of this.
*
* @{
* @file
* @brief Interface definition for the LPD8808 LED strip driver
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*/
#ifndef LPD8808_H
#define LPD8808_H
#include "color.h"
#include "periph/gpio.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Parameters needed for configuration
*/
typedef struct {
int led_cnt; /**< number of LEDs on the strip */
gpio_t pin_clk; /**< pin connected to the strip's clock signal */
gpio_t pin_dat; /**< pin connected to the strip's data signal */
} lpd8808_params_t;
/**
* @brief Device descriptor, same as the configuration parameters
*/
typedef lpd8808_params_t lpd8808_t;
/**
* @brief Initialize the given LPD8808 based LED strip
*
* @param[out] dev device to initialize
* @param[in] params parameters used for initialization
*
* @return 0 on success
* @return <0 on error
*/
int lpd8808_init(lpd8808_t *dev, const lpd8808_params_t *params);
/**
* @brief Set the color value of each LED on the strip
*
* This function sets the color value of each LED on the strip by shifting out
* the corresponding color values one after the other. The function expects an
* array of @p color_rgb_t values of the same length as LEDs on the strip.
*
* @param[in] dev device to load color values to
* @param[in] vals array of color values, MUST be of same length as LEDs on
* the strip
*/
void lpd8808_load_rgb(lpd8808_t *dev, color_rgb_t vals[]);
#ifdef __cplusplus
}
#endif
#endif /* LPD8808_H */
/** @} */
include $(RIOTBASE)/Makefile.base
/*
* Copyright (C) 2016 Hauke Petersen <devel@haukepetersen.de>
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup drivers_lpd8808
*
* @{
* @file
* @brief Default configuration for LPD8808 based LED strips
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*/
#ifndef LPD8808_PARAMS_H
#define LPD8808_PARAMS_H
#include "board.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Set default configuration parameters for the LPD8808 driver
* @{
*/
#ifndef LPD8808_PARAM_LED_CNT
#define LPD8808_PARAM_LED_CNT (64) /* most have 64 per meter... */
#endif
#ifndef LPD8808_PARAM_PIN_CLK
#define LPD8808_PARAM_PIN_CLK (GPIO_PIN(0, 0))
#endif
#ifndef LPD8808_PARAM_PIN_DAT
#define LPD8808_PARAM_PIN_DAT (GPIO_PIN(0, 1))
#endif
#define LPD8808_PARAMS_DEFAULT {.led_cnt = LPD8808_PARAM_LED_CNT, \
.pin_clk = LPD8808_PARAM_PIN_CLK, \
.pin_dat = LPD8808_PARAM_PIN_DAT }
/**@}*/
/**
* @brief LPD8808 parameter allocation
*/
static const lpd8808_params_t lpd8808_params[] =
{
#ifdef LPD8808_PARAMS_BOARD
LPD8808_PARAMS_BOARD,
#else
LPD8808_PARAMS_DEFAULT,
#endif
};
#ifdef __cplusplus
}
#endif
#endif /* LPD8808_PARAMS_H */
/** @} */
/*
* Copyright (C) 2016 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup lpd8808
* @{
*
* @file
* @brief LPD8808 based LED strip driver implementation
*
* @author Hauke Petersen <mail@haukepetersen.de>
*
* @}
*/
#include <string.h>
#include "lpd8808.h"
/**
* @brief Shift a single byte to the strip
*
* @param[in] dev device to use
* @param[in] d byte to shift out
*/
static void put_byte(lpd8808_t *dev, uint8_t d)
{
for (int i = 0; i < 8; i++) {
gpio_write(dev->pin_dat, d & 0x80);
gpio_set(dev->pin_clk);
gpio_clear(dev->pin_clk);
d <<= 1;
}
}
/**
* @brief Flush the previous input
*
* LPD8808 based strips need to be flushed after loading values for each LED.
* This is done by feeding the strip with one zero byte for every 32 LEDs on
* the strip.
*
* @param[in] dev device to flush
*/
static void flush(lpd8808_t *dev)
{
for (int i = 0; i < ((dev->led_cnt + 31) / 32); i++) {
put_byte(dev, 0);
}
}
int lpd8808_init(lpd8808_t *dev, const lpd8808_params_t *params)
{
memcpy(dev, params, sizeof(lpd8808_params_t));
/* initialize pins */
gpio_init(dev->pin_dat, GPIO_OUT);
gpio_init(dev->pin_clk, GPIO_OUT);
flush(dev);
return 0;
}
void lpd8808_load_rgb(lpd8808_t *dev, color_rgb_t vals[])
{
for (int i = 0; i < dev->led_cnt; i++) {
put_byte(dev, ((vals[i].g >> 1) | 0x80));
put_byte(dev, ((vals[i].r >> 1) | 0x80));
put_byte(dev, ((vals[i].b >> 1) | 0x80));
}
flush(dev);
}
APPLICATION = driver_lpd8808
include ../Makefile.tests_common
USEMODULE += lpd8808
USEMODULE += xtimer
include $(RIOTBASE)/Makefile.include
# About
This test application is made for verification of the LPD8808 LED strip driver.
# Usage
Connect a LPD8808 based LED strip to a board of your choice, build, and flash
this application. You should see a light running up and down your strip,
slowly changing it's color.
You might need to adjust the default parameters (number of LEDs on the strip and
pin configuration). You can do this simply by pre-setting the `CFLAGS`
environment variable, e.g.:
```
$ CFLAGS="-DLPD8808_PARAM_LED_CNT=78"" make all
```
/*
* Copyright (C) 2016 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup tests
* @{
*
* @file
* @brief Test application for the LPD8808 LED strip driver
*
* Refer to the accompanying README.md for more information.
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*
* @}
*/
#include <string.h>
#include <stdio.h>
#include "xtimer.h"
#include "lpd8808.h"
#include "lpd8808_params.h"
/**
* @brief Switch to the next LED every 10ms
*/
#define STEP (10 * 1000U)
/**
* @brief Allocate the device descriptor
*/
static lpd8808_t dev;
/**
* @brief Allocate a color_rgb_t struct for each LED on the strip
*/
static color_rgb_t leds[LPD8808_PARAM_LED_CNT];
int main(void)
{
uint32_t now = xtimer_now();
int pos = 0;
int step = 1;
color_hsv_t col = { 0.0, 1.0, 1.0 };
/* initialize all LED color values to black (off) */
memset(leds, 0, sizeof(color_rgb_t) * LPD8808_PARAM_LED_CNT);
/* initialize the driver */
lpd8808_init(&dev, &lpd8808_params[0]);
while (1) {
/* change the active color by running around the hue circle */
col.h += 1.0;
if (col.h > 360.0) {
col.h = 0;
}
/* set the active LED to the active color value */
memset(&leds[pos], 0, sizeof(color_rgb_t));
pos += step;
color_hsv2rgb(&col, &leds[pos]);
/* apply the values to the LED strip */
lpd8808_load_rgb(&dev, leds);
/* switch direction once reaching an end of the strip */
if ((pos == (LPD8808_PARAM_LED_CNT - 1)) || (pos == 0)) {
step *= -1;
}
xtimer_periodic_wakeup(&now, STEP);
}
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment