parent
ee835142b2
commit
828834ad7a
@ -1,114 +0,0 @@
|
|||||||
/*
|
|
||||||
* light weight WS2812 lib V2.1 - Arduino support
|
|
||||||
*
|
|
||||||
* Controls WS2811/WS2812/WS2812B RGB-LEDs
|
|
||||||
* Author: Matthias Riegler
|
|
||||||
*
|
|
||||||
* Mar 07 2014: Added Arduino and C++ Library
|
|
||||||
*
|
|
||||||
* September 6, 2014: Added option to switch between most popular color orders
|
|
||||||
* (RGB, GRB, and BRG) -- Windell H. Oskay
|
|
||||||
*
|
|
||||||
* License: GNU GPL v2 (see License.txt)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "WS2812.h"
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
WS2812::WS2812(uint16_t num_leds) {
|
|
||||||
count_led = num_leds;
|
|
||||||
|
|
||||||
pixels = (uint8_t*)malloc(count_led*3);
|
|
||||||
#ifdef RGB_ORDER_ON_RUNTIME
|
|
||||||
offsetGreen = 0;
|
|
||||||
offsetRed = 1;
|
|
||||||
offsetBlue = 2;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
cRGB WS2812::get_crgb_at(uint16_t index) {
|
|
||||||
|
|
||||||
cRGB px_value;
|
|
||||||
|
|
||||||
if(index < count_led) {
|
|
||||||
|
|
||||||
uint16_t tmp;
|
|
||||||
tmp = index * 3;
|
|
||||||
|
|
||||||
px_value.r = pixels[OFFSET_R(tmp)];
|
|
||||||
px_value.g = pixels[OFFSET_G(tmp)];
|
|
||||||
px_value.b = pixels[OFFSET_B(tmp)];
|
|
||||||
}
|
|
||||||
|
|
||||||
return px_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t WS2812::set_crgb_at(uint16_t index, cRGB px_value) {
|
|
||||||
|
|
||||||
if(index < count_led) {
|
|
||||||
|
|
||||||
uint16_t tmp;
|
|
||||||
tmp = index * 3;
|
|
||||||
|
|
||||||
pixels[OFFSET_R(tmp)] = px_value.r;
|
|
||||||
pixels[OFFSET_G(tmp)] = px_value.g;
|
|
||||||
pixels[OFFSET_B(tmp)] = px_value.b;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t WS2812::set_subpixel_at(uint16_t index, uint8_t offset, uint8_t px_value) {
|
|
||||||
if (index < count_led) {
|
|
||||||
uint16_t tmp;
|
|
||||||
tmp = index * 3;
|
|
||||||
|
|
||||||
pixels[tmp + offset] = px_value;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WS2812::sync() {
|
|
||||||
*ws2812_port_reg |= pinMask; // Enable DDR
|
|
||||||
ws2812_sendarray_mask(pixels,3*count_led,pinMask,(uint8_t*) ws2812_port,(uint8_t*) ws2812_port_reg );
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef RGB_ORDER_ON_RUNTIME
|
|
||||||
void WS2812::setColorOrderGRB() { // Default color order
|
|
||||||
offsetGreen = 0;
|
|
||||||
offsetRed = 1;
|
|
||||||
offsetBlue = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WS2812::setColorOrderRGB() {
|
|
||||||
offsetRed = 0;
|
|
||||||
offsetGreen = 1;
|
|
||||||
offsetBlue = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WS2812::setColorOrderBRG() {
|
|
||||||
offsetBlue = 0;
|
|
||||||
offsetRed = 1;
|
|
||||||
offsetGreen = 2;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
WS2812::~WS2812() {
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef ARDUINO
|
|
||||||
void WS2812::setOutput(const volatile uint8_t* port, volatile uint8_t* reg, uint8_t pin) {
|
|
||||||
pinMask = (1<<pin);
|
|
||||||
ws2812_port = port;
|
|
||||||
ws2812_port_reg = reg;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
void WS2812::setOutput(uint8_t pin) {
|
|
||||||
pinMask = digitalPinToBitMask(pin);
|
|
||||||
ws2812_port = portOutputRegister(digitalPinToPort(pin));
|
|
||||||
ws2812_port_reg = portModeRegister(digitalPinToPort(pin));
|
|
||||||
}
|
|
||||||
#endif
|
|
@ -1,99 +0,0 @@
|
|||||||
/*
|
|
||||||
* light weight WS2812 lib V2.1 - Arduino support
|
|
||||||
*
|
|
||||||
* Controls WS2811/WS2812/WS2812B RGB-LEDs
|
|
||||||
* Author: Matthias Riegler
|
|
||||||
*
|
|
||||||
* Mar 07 2014: Added Arduino and C++ Library
|
|
||||||
*
|
|
||||||
* September 6, 2014 Added option to switch between most popular color orders
|
|
||||||
* (RGB, GRB, and BRG) -- Windell H. Oskay
|
|
||||||
*
|
|
||||||
* January 24, 2015 Added option to make color orders static again
|
|
||||||
* Moved cRGB to a header so it is easier to replace / expand
|
|
||||||
* (added SetHSV based on code from kasperkamperman.com)
|
|
||||||
* -- Freezy
|
|
||||||
*
|
|
||||||
* License: GNU GPL v2 (see License.txt)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef WS2812_H_
|
|
||||||
#define WS2812_H_
|
|
||||||
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
#include <avr/io.h>
|
|
||||||
#ifndef F_CPU
|
|
||||||
#define F_CPU 16000000UL
|
|
||||||
#endif
|
|
||||||
#include <util/delay.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#ifdef ARDUINO
|
|
||||||
#if (ARDUINO >= 100)
|
|
||||||
#include <Arduino.h>
|
|
||||||
#else
|
|
||||||
#include <WProgram.h>
|
|
||||||
#include <pins_arduino.h>
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//Easier to change cRGB into any other rgb struct
|
|
||||||
#include "cRGB.h"
|
|
||||||
|
|
||||||
// If you want to use the setColorOrder functions, enable this line
|
|
||||||
#define RGB_ORDER_ON_RUNTIME
|
|
||||||
|
|
||||||
#ifdef RGB_ORDER_ON_RUNTIME
|
|
||||||
#define OFFSET_R(r) r+offsetRed
|
|
||||||
#define OFFSET_G(g) g+offsetGreen
|
|
||||||
#define OFFSET_B(b) b+offsetBlue
|
|
||||||
#else
|
|
||||||
// CHANGE YOUR STATIC RGB ORDER HERE
|
|
||||||
#define OFFSET_R(r) r+1
|
|
||||||
#define OFFSET_G(g) g
|
|
||||||
#define OFFSET_B(b) b+2
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class WS2812 {
|
|
||||||
public:
|
|
||||||
WS2812(uint16_t num_led);
|
|
||||||
~WS2812();
|
|
||||||
|
|
||||||
#ifndef ARDUINO
|
|
||||||
void setOutput(const volatile uint8_t* port, volatile uint8_t* reg, uint8_t pin);
|
|
||||||
#else
|
|
||||||
void setOutput(uint8_t pin);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
cRGB get_crgb_at(uint16_t index);
|
|
||||||
uint8_t set_crgb_at(uint16_t index, cRGB px_value);
|
|
||||||
uint8_t set_subpixel_at(uint16_t index, uint8_t offset, uint8_t px_value);
|
|
||||||
|
|
||||||
void sync();
|
|
||||||
|
|
||||||
#ifdef RGB_ORDER_ON_RUNTIME
|
|
||||||
void setColorOrderRGB();
|
|
||||||
void setColorOrderGRB();
|
|
||||||
void setColorOrderBRG();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
private:
|
|
||||||
uint16_t count_led;
|
|
||||||
uint8_t *pixels;
|
|
||||||
|
|
||||||
#ifdef RGB_ORDER_ON_RUNTIME
|
|
||||||
uint8_t offsetRed;
|
|
||||||
uint8_t offsetGreen;
|
|
||||||
uint8_t offsetBlue;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void ws2812_sendarray_mask(uint8_t *array,uint16_t length, uint8_t pinmask,uint8_t *port, uint8_t *portreg);
|
|
||||||
|
|
||||||
const volatile uint8_t *ws2812_port;
|
|
||||||
volatile uint8_t *ws2812_port_reg;
|
|
||||||
uint8_t pinMask;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* WS2812_H_ */
|
|
@ -1,115 +0,0 @@
|
|||||||
#ifndef CRGB_H
|
|
||||||
#define CRGB_H
|
|
||||||
|
|
||||||
/*
|
|
||||||
Control a RGB led with Hue, Saturation and Brightness (HSB / HSV )
|
|
||||||
|
|
||||||
Hue is change by an analog input.
|
|
||||||
Brightness is changed by a fading function.
|
|
||||||
Saturation stays constant at 255
|
|
||||||
|
|
||||||
getRGB() function based on <http://www.codeproject.com/miscctrl/CPicker.asp>
|
|
||||||
dim_curve idea by Jims
|
|
||||||
|
|
||||||
created 05-01-2010 by kasperkamperman.com
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
dim_curve 'lookup table' to compensate for the nonlinearity of human vision.
|
|
||||||
Used in the getRGB function on saturation and brightness to make 'dimming' look more natural.
|
|
||||||
Exponential function used to create values below :
|
|
||||||
x from 0 - 255 : y = round(pow( 2.0, x+64/40.0) - 1)
|
|
||||||
*/
|
|
||||||
|
|
||||||
// uncomment this line if you use HSV is many projects
|
|
||||||
#define USE_HSV
|
|
||||||
|
|
||||||
#ifdef USE_HSV
|
|
||||||
const byte dim_curve[] = {
|
|
||||||
0, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3,
|
|
||||||
3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
|
||||||
4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6,
|
|
||||||
6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8,
|
|
||||||
8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11,
|
|
||||||
11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15,
|
|
||||||
15, 15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 20,
|
|
||||||
20, 20, 21, 21, 22, 22, 22, 23, 23, 24, 24, 25, 25, 25, 26, 26,
|
|
||||||
27, 27, 28, 28, 29, 29, 30, 30, 31, 32, 32, 33, 33, 34, 35, 35,
|
|
||||||
36, 36, 37, 38, 38, 39, 40, 40, 41, 42, 43, 43, 44, 45, 46, 47,
|
|
||||||
48, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
|
|
||||||
63, 64, 65, 66, 68, 69, 70, 71, 73, 74, 75, 76, 78, 79, 81, 82,
|
|
||||||
83, 85, 86, 88, 90, 91, 93, 94, 96, 98, 99, 101, 103, 105, 107, 109,
|
|
||||||
110, 112, 114, 116, 118, 121, 123, 125, 127, 129, 132, 134, 136, 139, 141, 144,
|
|
||||||
146, 149, 151, 154, 157, 159, 162, 165, 168, 171, 174, 177, 180, 183, 186, 190,
|
|
||||||
193, 196, 200, 203, 207, 211, 214, 218, 222, 226, 230, 234, 238, 242, 248, 255,
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct cRGB {
|
|
||||||
uint8_t g;
|
|
||||||
uint8_t r;
|
|
||||||
uint8_t b;
|
|
||||||
|
|
||||||
#ifdef USE_HSV
|
|
||||||
void SetHSV(int hue, byte sat, byte val) {
|
|
||||||
/* convert hue, saturation and brightness ( HSB/HSV ) to RGB
|
|
||||||
The dim_curve is used only on brightness/value and on saturation (inverted).
|
|
||||||
This looks the most natural.
|
|
||||||
*/
|
|
||||||
|
|
||||||
val = dim_curve[val];
|
|
||||||
sat = 255 - dim_curve[255 - sat];
|
|
||||||
|
|
||||||
int base;
|
|
||||||
|
|
||||||
if (sat == 0) { // Acromatic color (gray). Hue doesn't mind.
|
|
||||||
r = val;
|
|
||||||
g = val;
|
|
||||||
b = val;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
base = ((255 - sat) * val) >> 8;
|
|
||||||
|
|
||||||
switch (hue / 60) {
|
|
||||||
case 0:
|
|
||||||
r = val;
|
|
||||||
g = (((val - base)*hue) / 60) + base;
|
|
||||||
b = base;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
r = (((val - base)*(60 - (hue % 60))) / 60) + base;
|
|
||||||
g = val;
|
|
||||||
b = base;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
r = base;
|
|
||||||
g = val;
|
|
||||||
b = (((val - base)*(hue % 60)) / 60) + base;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
r = base;
|
|
||||||
g = (((val - base)*(60 - (hue % 60))) / 60) + base;
|
|
||||||
b = val;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
r = (((val - base)*(hue % 60)) / 60) + base;
|
|
||||||
g = base;
|
|
||||||
b = val;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 5:
|
|
||||||
r = val;
|
|
||||||
g = base;
|
|
||||||
b = (((val - base)*(60 - (hue % 60))) / 60) + base;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,156 +0,0 @@
|
|||||||
/*
|
|
||||||
* light weight WS2812 lib V2.1 - Arduino support
|
|
||||||
*
|
|
||||||
* Controls WS2811/WS2812/WS2812B RGB-LEDs
|
|
||||||
* Author: Tim (cpldcpu@gmail.com)
|
|
||||||
*
|
|
||||||
* Jan 18th, 2014 v2.0b Initial Version
|
|
||||||
* March 7th, 2014 v2.1 Added option to retarget the port register during runtime
|
|
||||||
* Removes inlining to allow compiling with c++
|
|
||||||
*
|
|
||||||
* License: GNU GPL v2 (see License.txt)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "WS2812.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
This routine writes an array of bytes with RGB values to the Dataout pin
|
|
||||||
using the fast 800kHz clockless WS2811/2812 protocol.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Timing in ns
|
|
||||||
#define w_zeropulse 350
|
|
||||||
#define w_onepulse 900
|
|
||||||
#define w_totalperiod 1250
|
|
||||||
|
|
||||||
// Fixed cycles used by the inner loop
|
|
||||||
#define w_fixedlow 3
|
|
||||||
#define w_fixedhigh 6
|
|
||||||
#define w_fixedtotal 10
|
|
||||||
|
|
||||||
// Insert NOPs to match the timing, if possible
|
|
||||||
#define w_zerocycles (((F_CPU/1000)*w_zeropulse )/1000000)
|
|
||||||
#define w_onecycles (((F_CPU/1000)*w_onepulse +500000)/1000000)
|
|
||||||
#define w_totalcycles (((F_CPU/1000)*w_totalperiod +500000)/1000000)
|
|
||||||
|
|
||||||
// w1 - nops between rising edge and falling edge - low
|
|
||||||
#define w1 (w_zerocycles-w_fixedlow)
|
|
||||||
// w2 nops between fe low and fe high
|
|
||||||
#define w2 (w_onecycles-w_fixedhigh-w1)
|
|
||||||
// w3 nops to complete loop
|
|
||||||
#define w3 (w_totalcycles-w_fixedtotal-w1-w2)
|
|
||||||
|
|
||||||
#if w1>0
|
|
||||||
#define w1_nops w1
|
|
||||||
#else
|
|
||||||
#define w1_nops 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// The only critical timing parameter is the minimum pulse length of the "0"
|
|
||||||
// Warn or throw error if this timing can not be met with current F_CPU settings.
|
|
||||||
#define w_lowtime ((w1_nops+w_fixedlow)*1000000)/(F_CPU/1000)
|
|
||||||
#if w_lowtime>550
|
|
||||||
#error "Light_ws2812: Sorry, the clock speed is too low. Did you set F_CPU correctly?"
|
|
||||||
#elif w_lowtime>450
|
|
||||||
#warning "Light_ws2812: The timing is critical and may only work on WS2812B, not on WS2812(S)."
|
|
||||||
#warning "Please consider a higher clockspeed, if possible"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if w2>0
|
|
||||||
#define w2_nops w2
|
|
||||||
#else
|
|
||||||
#define w2_nops 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if w3>0
|
|
||||||
#define w3_nops w3
|
|
||||||
#else
|
|
||||||
#define w3_nops 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define w_nop1 "nop \n\t"
|
|
||||||
#define w_nop2 "rjmp .+0 \n\t"
|
|
||||||
#define w_nop4 w_nop2 w_nop2
|
|
||||||
#define w_nop8 w_nop4 w_nop4
|
|
||||||
#define w_nop16 w_nop8 w_nop8
|
|
||||||
|
|
||||||
void WS2812::ws2812_sendarray_mask(uint8_t *data,uint16_t datlen,uint8_t maskhi,uint8_t *port, uint8_t *portreg)
|
|
||||||
{
|
|
||||||
uint8_t curbyte,ctr,masklo;
|
|
||||||
uint8_t sreg_prev;
|
|
||||||
|
|
||||||
masklo = ~maskhi & *port;
|
|
||||||
maskhi |= *port;
|
|
||||||
sreg_prev=SREG;
|
|
||||||
cli();
|
|
||||||
|
|
||||||
while (datlen--) {
|
|
||||||
curbyte=*data++;
|
|
||||||
|
|
||||||
asm volatile(
|
|
||||||
" ldi %0,8 \n\t"
|
|
||||||
"loop%=: \n\t"
|
|
||||||
" st X,%3 \n\t" // '1' [02] '0' [02] - re
|
|
||||||
#if (w1_nops&1)
|
|
||||||
w_nop1
|
|
||||||
#endif
|
|
||||||
#if (w1_nops&2)
|
|
||||||
w_nop2
|
|
||||||
#endif
|
|
||||||
#if (w1_nops&4)
|
|
||||||
w_nop4
|
|
||||||
#endif
|
|
||||||
#if (w1_nops&8)
|
|
||||||
w_nop8
|
|
||||||
#endif
|
|
||||||
#if (w1_nops&16)
|
|
||||||
w_nop16
|
|
||||||
#endif
|
|
||||||
" sbrs %1,7 \n\t" // '1' [04] '0' [03]
|
|
||||||
" st X,%4 \n\t" // '1' [--] '0' [05] - fe-low
|
|
||||||
" lsl %1 \n\t" // '1' [05] '0' [06]
|
|
||||||
#if (w2_nops&1)
|
|
||||||
w_nop1
|
|
||||||
#endif
|
|
||||||
#if (w2_nops&2)
|
|
||||||
w_nop2
|
|
||||||
#endif
|
|
||||||
#if (w2_nops&4)
|
|
||||||
w_nop4
|
|
||||||
#endif
|
|
||||||
#if (w2_nops&8)
|
|
||||||
w_nop8
|
|
||||||
#endif
|
|
||||||
#if (w2_nops&16)
|
|
||||||
w_nop16
|
|
||||||
#endif
|
|
||||||
" brcc skipone%= \n\t" // '1' [+1] '0' [+2] -
|
|
||||||
" st X,%4 \n\t" // '1' [+3] '0' [--] - fe-high
|
|
||||||
"skipone%=: " // '1' [+3] '0' [+2] -
|
|
||||||
|
|
||||||
#if (w3_nops&1)
|
|
||||||
w_nop1
|
|
||||||
#endif
|
|
||||||
#if (w3_nops&2)
|
|
||||||
w_nop2
|
|
||||||
#endif
|
|
||||||
#if (w3_nops&4)
|
|
||||||
w_nop4
|
|
||||||
#endif
|
|
||||||
#if (w3_nops&8)
|
|
||||||
w_nop8
|
|
||||||
#endif
|
|
||||||
#if (w3_nops&16)
|
|
||||||
w_nop16
|
|
||||||
#endif
|
|
||||||
|
|
||||||
" dec %0 \n\t" // '1' [+4] '0' [+3]
|
|
||||||
" brne loop%=\n\t" // '1' [+5] '0' [+4]
|
|
||||||
: "=&d" (ctr)
|
|
||||||
// : "r" (curbyte), "I" (_SFR_IO_ADDR(ws2812_PORTREG)), "r" (maskhi), "r" (masklo)
|
|
||||||
: "r" (curbyte), "x" (port), "r" (maskhi), "r" (masklo)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
SREG=sreg_prev;
|
|
||||||
}
|
|
Loading…
Reference in new issue