From 5bba253d65e9e44e74fe0bdfb315e409df6f7482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?King=20K=C3=A9vin?= Date: Wed, 29 Jul 2015 10:50:57 +0200 Subject: [PATCH] add WS2812B LED controller library (from screenlight project) --- lib/ws2812b.c | 214 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/ws2812b.h | 38 +++++++++ 2 files changed, 252 insertions(+) create mode 100644 lib/ws2812b.c create mode 100644 lib/ws2812b.h diff --git a/lib/ws2812b.c b/lib/ws2812b.c new file mode 100644 index 0000000..34c3d18 --- /dev/null +++ b/lib/ws2812b.c @@ -0,0 +1,214 @@ +/* This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +/* This library allows to control WS2812B LEDs + * it uses timer 0 with interruts + */ + +#include // Standard Integer Types +#include // Standard IO facilities +#include // General utilities +#include // boolean type + +#include // AVR device-specific IO definitions +#include // Interrupts + +#include "ws2812b.h" // WS2812B header + +/* has the WS2812B been initialized correctly */ +bool initialized = false; +/* the green, red, and blue (8 bits each) bit values for each LEDs */ +uint8_t color_bits[3*8*WS2812B_NB_LEDS] = {0}; +/* how much to shift for which channel */ +uint8_t channel_shifts[WS2812B_NB_CHANNELS] = {0}; +/* have the 50 us reset code timeout passed */ +volatile bool reset_code = true; + +/* initialize */ +bool ws2812b_init() +{ + initialized = false; + /* verify we are running with 16 MHz */ + if (F_CPU != 16000000) { + return initialized; // the code has been designed for 16 MHz + } + /* verify there are LEDs to use */ + if (WS2812B_NB_LEDS==0) { + return initialized; // there in no data to send + } + /* generate the channel shift depending on mask*/ + uint8_t channel = 0; + for (uint8_t shift=0; shift<8; shift++) { + if ( (WS2812B_MASK>>shift)&0x01 ) { + channel_shifts[channel++] = shift; + } + } + /* verify the number of channels corresponds to the mask */ + if (WS2812B_NB_CHANNELS!=channel) { + return initialized; // the number of channels does not match the mask + } + + WS2812B_DDR |= WS2812B_MASK; // set pins as output + + /* user timer 0 to time the reset code of 50 us */ + TCCR0B |= (0<=WS2812B_NB_CHANNELS) { + return false; + } + if (led>=WS2812B_NB_LEDS) { + return false; + } + + /* set color values + * composition of 24bit data: G7..G0,R7..R0,B7..B0 + * high bit is sent first + * LEDs keep the first values and forward the next + */ + for (uint8_t i=0; i<8; i++) { + uint8_t color_bit = 1<<(7-i); + if (green&color_bit) { + color_bits[8*3*led+i] |= (1<. + * + */ +/* This library allows to control WS2812B LEDs + * it uses timer 0 with interruts + */ + +/* the port on which the WS2812B LEDs are attached */ +#define WS2812B_PORT PORTD +#define WS2812B_DDR DDRD +#define WS2812B_PIN PIND +/* the pin on the previous port on which the WS2812B LEDs are attached + * use as many strips in parallel on the available pins to save time and memory */ +#define WS2812B_MASK 0xfc +#define WS2812B_NB_CHANNELS 6 +/* the maximum number of chained WS2812B LEDs attached on a pin + * use as few in series and prefer putting them in parrallel to save time and memory */ +#define WS2812B_NB_LEDS 11 + +/* initialize port */ +bool ws2812b_init(void); +/* set the color of the LED on a channel LED chain, but do not show yet */ +bool ws2812b_set_led_color(uint8_t channel, uint8_t led, uint8_t red, uint8_t green, uint8_t blue); +/* switch off all LEDs, but do not show yet */ +void ws2812b_off(void); +/* send the RGB values to the LEDs */ +void ws2812b_show(void);