-
Notifications
You must be signed in to change notification settings - Fork 0
/
ws2812-code.ino
106 lines (80 loc) · 4.62 KB
/
ws2812-code.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// http://kevindarrah.com/download/arduino_code/WS1812_V4_FOR_VIDEO.ino
// https://www.youtube.com/watch?v=VAa4duqMrgs
//VARIABLES AND DEFINES HERE - NEEDED BY THE WS2812 DRIVER CODE
#define WS2812_pin 8 // only digital pin 8 works right now
#define numberOfLEDs 45// total number of RGB LEDs
byte RGB[135];//take your number of LEDs and multiply by 3
// FUNCTIONS HERE
void RGB_update(int LED, byte RED, byte GREEN, byte BLUE);//function to drive LEDs
void setup() {
pinMode(WS2812_pin, OUTPUT);
}//setup
void loop() {
RGB_update(0,0,0,0);//LED#, RED, GREEN, BLUE
delay(1000);
}//loop
//WS2812 Driver Function
void RGB_update(int LED, byte RED, byte GREEN, byte BLUE) {
// LED is the LED number starting with 0
// RED, GREEN, BLUE is the brightness 0..255 setpoint for that LED
byte ExistingPort, WS2812pinHIGH;//local variables here to speed up pinWrites
if(LED>=0){//map the REG GREEN BLUE Values into the RGB[] array
RGB[LED * 3] = GREEN;
RGB[LED * 3 + 1] = RED;
RGB[LED * 3 + 2] = BLUE;
}
noInterrupts();//kill the interrupts while we send the bit stream out...
ExistingPort = PORTB; // save the status of the entire PORT B - let's us write to the entire port without messing up the other pins on that port
WS2812pinHIGH = PORTB | 1; //this gives us a byte we can use to set the whole PORTB with the WS2812 pin HIGH
int bitStream = numberOfLEDs * 3;//total bytes in the LED string
//This for loop runs through all of the bits (8 at a time) to set the WS2812 pin ON/OFF times
for (int i = 0; i < bitStream; i++) {
PORTB = WS2812pinHIGH;//bit 7 first, set the pin HIGH - it always goes high regardless of a 0/1
//here's the tricky part, check if the bit in the byte is high/low then right that status to the pin
// (RGB[i] & B10000000) will strip away the other bits in RGB[i], so here we'll be left with B10000000 or B00000000
// then it's easy to check if the bit is high or low by AND'ing that with the bit mask ""&& B10000000)"" this gives 1 or 0
// if it's a 1, we'll OR that with the Existing port, thus keeping the pin HIGH, if 0 the pin is written LOW
PORTB = ((RGB[i] & B10000000) && B10000000) | ExistingPort;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");//these are NOPS - these let us delay clock cycles for more precise timing
PORTB = ExistingPort;//okay, here we know we have to be LOW regardless of the 0/1 bit state
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");//minimum LOW time for pin regardless of 0/1 bit state
// then do it again for the next bit and so on... see the last bit though for a slight change
PORTB = WS2812pinHIGH;//bit 6
PORTB = ((RGB[i] & B01000000) && B01000000) | ExistingPort;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
PORTB = ExistingPort;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
PORTB = WS2812pinHIGH;//bit 5
PORTB = ((RGB[i] & B00100000) && B00100000) | ExistingPort;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
PORTB = ExistingPort;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
PORTB = WS2812pinHIGH;//bit 4
PORTB = ((RGB[i] & B00010000) && B00010000) | ExistingPort;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
PORTB = ExistingPort;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
PORTB = WS2812pinHIGH;//bit 3
PORTB = ((RGB[i] & B00001000) && B00001000) | ExistingPort;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
PORTB = ExistingPort;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
PORTB = WS2812pinHIGH;//bit 2
PORTB = ((RGB[i] & B00000100) && B00000100) | ExistingPort;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
PORTB = ExistingPort;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
PORTB = WS2812pinHIGH;//bit 1
PORTB = ((RGB[i] & B00000010) && B00000010) | ExistingPort;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
PORTB = ExistingPort;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
PORTB = WS2812pinHIGH;//bit 0
__asm__("nop\n\t");//on this last bit, the check is much faster, so had to add a NOP here
PORTB = ((RGB[i] & B00000001) && B00000001) | ExistingPort;
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
PORTB = ExistingPort;//note there are no NOPs after writing the pin LOW, this is because the FOR Loop uses clock cycles that we can use instead of the NOPS
}//for loop
interrupts();//enable the interrupts
// all done!
}//void RGB_update