/* 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<