forked from adafruit/LPD8806
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCompileTimeLEDs.h
More file actions
111 lines (92 loc) · 4.35 KB
/
CompileTimeLEDs.h
File metadata and controls
111 lines (92 loc) · 4.35 KB
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
107
108
109
110
111
// Hack for speeding up LPD8806 LED strip without using SPI.
// Code written by Michael Noland, "Speeding up LPD8806 show() without hardware SPI"
// http://michaelnoland.com/speeding-up-lpd8806-show-without-hardware-spi/
// To use, replace strip.show() with strip.showCompileTime<ClockPin, DataPin>(ClockPort, DataPort);
// ClockPin/DataPin are NOT the Arduino board pin number, it's the actual pin offset within the port.
// You can find these numbers with some Googling (eg "Arduino Leonardo pin mapping").
// ClockPort and DataPort are the data registers that contain the pins; on my Flora these are both `PORTD`.
// For my Flora with LEDs on data pin 6 and clock pin 12,
// this is how I show my LEDs: strip.showCompileTime<6, 7>(PORTD, PORTD);
#ifndef _COMPILE_TIME_LEDS_
#define _COMPILE_TIME_LEDS_
#endif
template<unsigned int ClockPin>
void PulseClockLine(volatile uint8_t& ClockRegister) {
const byte LED_CLOCK_MASK = 1 << ClockPin;
ClockRegister |= LED_CLOCK_MASK;
ClockRegister &= ~LED_CLOCK_MASK;
}
template<unsigned int ClockPin, unsigned int DataPin>
void TransmitBit(byte& CurrentByte, volatile uint8_t& ClockRegister, volatile uint8_t& DataRegister) {
// Set the data bit
const byte LED_DATA_MASK = 1 << DataPin;
if (CurrentByte & 0x80) {
DataRegister |= LED_DATA_MASK;
} else {
DataRegister &= ~LED_DATA_MASK;
}
// Pulse the clock line
PulseClockLine<ClockPin>(ClockRegister);
// Advance to the next bit to transmit
CurrentByte = CurrentByte << 1;
}
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
#define MAP_ARDUINO_PIN_TO_PORT_PIN(ArduinoPin) \
( ArduinoPin & 7 )
#define MAP_ARDUINO_PIN_TO_PORT_REG(ArduinoPin) \
( (ArduinoPin >= 16) ? PORTC : (((ArduinoPin) >= 8) ? PORTB : PORTD) )
// Specify Arduino pin numbers
template<unsigned int ClockPin, unsigned int DataPin>
void showCompileTime() {
showCompileTime<MAP_ARDUINO_PIN_TO_PORT_PIN(ClockPin), MAP_ARDUINO_PIN_TO_PORT_PIN(DataPin)>(
MAP_ARDUINO_PIN_TO_PORT_REG(ClockPin),
MAP_ARDUINO_PIN_TO_PORT_REG(DataPin));
}
#undef MAP_ARDUINO_PIN_TO_PORT_PIN
#undef MAP_ARDUINO_PIN_TO_PORT_REG
#else
// Sorry: Didn't write an equivalent for other boards; use the other
// overload and explicitly specify ports and offsets within those ports
#endif
// Note: Pin template params need to be relative to their port (0..7), not Arduino pinout numbers
template<unsigned int ClockPin, unsigned int DataPin>
void showCompileTime(volatile uint8_t& ClockRegister, volatile uint8_t& DataRegister) {
int pause = 0;
// Clock out the color for each LED
byte* DataPtr = pixels;
byte* EndDataPtr = pixels + (numLEDs * 3);
do {
byte CurrentByte = *DataPtr++;
TransmitBit<ClockPin, DataPin>(CurrentByte, ClockRegister, DataRegister);
TransmitBit<ClockPin, DataPin>(CurrentByte, ClockRegister, DataRegister);
TransmitBit<ClockPin, DataPin>(CurrentByte, ClockRegister, DataRegister);
TransmitBit<ClockPin, DataPin>(CurrentByte, ClockRegister, DataRegister);
TransmitBit<ClockPin, DataPin>(CurrentByte, ClockRegister, DataRegister);
TransmitBit<ClockPin, DataPin>(CurrentByte, ClockRegister, DataRegister);
TransmitBit<ClockPin, DataPin>(CurrentByte, ClockRegister, DataRegister);
TransmitBit<ClockPin, DataPin>(CurrentByte, ClockRegister, DataRegister);
}
while (DataPtr != EndDataPtr);
// Clear the data line while we clock out the latching pattern
const byte LED_DATA_MASK = 1 << DataPin;
DataRegister &= ~LED_DATA_MASK;
// All of the original data had the high bit set in each byte. To latch
// the color in, we need to clock out another LED worth of 0's for every
// 64 LEDs in the strip apparently.
byte RemainingLatchBytes = ((numLEDs + 63) / 64) * 3;
do {
PulseClockLine<ClockPin>(ClockRegister);
PulseClockLine<ClockPin>(ClockRegister);
PulseClockLine<ClockPin>(ClockRegister);
PulseClockLine<ClockPin>(ClockRegister);
PulseClockLine<ClockPin>(ClockRegister);
PulseClockLine<ClockPin>(ClockRegister);
PulseClockLine<ClockPin>(ClockRegister);
PulseClockLine<ClockPin>(ClockRegister);
} while (--RemainingLatchBytes);
// Need a bit of a delay before clocking again, but ideally this
// is set to 0 and meaningful work is done instead
if (pause) {
delay(pause);
}
}