mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-25 22:43:50 +01:00
Merge pull request #5732 from haukepetersen/add_driver_lpd8808
drivers: add support for LPD8808 based LED stripes
This commit is contained in:
commit
05be6cb9e0
@ -94,6 +94,11 @@ ifneq (,$(filter lm75a,$(USEMODULE)))
|
||||
USEMODULE += xtimer
|
||||
endif
|
||||
|
||||
ifneq (,$(filter lpd8808,$(USEMODULE)))
|
||||
USEMODULE += color
|
||||
FEATURES_REQUIRED += periph_gpio
|
||||
endif
|
||||
|
||||
ifneq (,$(filter ltc4150,$(USEMODULE)))
|
||||
USEMODULE += xtimer
|
||||
endif
|
||||
|
||||
@ -67,3 +67,6 @@ endif
|
||||
ifneq (,$(filter cc2420,$(USEMODULE)))
|
||||
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/cc2420/include
|
||||
endif
|
||||
ifneq (,$(filter lpd8808,$(USEMODULE)))
|
||||
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/lpd8808/include
|
||||
endif
|
||||
|
||||
83
drivers/include/lpd8808.h
Normal file
83
drivers/include/lpd8808.h
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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 */
|
||||
/** @} */
|
||||
1
drivers/lpd8808/Makefile
Normal file
1
drivers/lpd8808/Makefile
Normal file
@ -0,0 +1 @@
|
||||
include $(RIOTBASE)/Makefile.base
|
||||
64
drivers/lpd8808/include/lpd8808_params.h
Normal file
64
drivers/lpd8808/include/lpd8808_params.h
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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 */
|
||||
/** @} */
|
||||
77
drivers/lpd8808/lpd8808.c
Normal file
77
drivers/lpd8808/lpd8808.c
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
7
tests/driver_lpd8808/Makefile
Normal file
7
tests/driver_lpd8808/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
APPLICATION = driver_lpd8808
|
||||
include ../Makefile.tests_common
|
||||
|
||||
USEMODULE += lpd8808
|
||||
USEMODULE += xtimer
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
||||
14
tests/driver_lpd8808/README.md
Normal file
14
tests/driver_lpd8808/README.md
Normal file
@ -0,0 +1,14 @@
|
||||
# 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
|
||||
```
|
||||
85
tests/driver_lpd8808/main.c
Normal file
85
tests/driver_lpd8808/main.c
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user