Extract our the 'old' WS2812 implementation

pull/18/head
Jesse Vincent 9 years ago
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_ */

115
cRGB.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…
Cancel
Save