-
Notifications
You must be signed in to change notification settings - Fork 0
/
LedStrips.py
152 lines (123 loc) · 3.71 KB
/
LedStrips.py
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
import serial
import time
import optparse
import array
class LedStrips:
frame_count = 0
format_time_total = 0
def __init__(self, image_width, offset):
"""
Initialize an med strip
@param offset X position of the image to get LED image data from
"""
self.image_width = image_width
self.offset = offset
def connect(self, port):
self.ser = serial.Serial(port, 115200, timeout=0)
def RgbRowToStrips(self, data):
"""
Convert a row of eight RGB pixels into LED strip data.
@param data 24-byte array of 8bit RGB data for one row of pixels:
0 1 2 3 4 5 6 7
RGBRGBRGBRGBRGBRGBRGBRGB
@return 24-byte stream to write to the USB port.
"""
if len(data) != 24:
raise Exception('Expected 24 bytes of data, got %i'%(len(data)))
output = ''
data = array.array('B', data)
# Green byte
output += '\xFF'
for bit_index in range(7, 0, -1):
c = 0x00
for pixel_index in range(0, 8):
c += (data[1+3*pixel_index] >> bit_index & 1) << pixel_index
output += chr(c)
# Red byte
output += '\xFF'
for bit_index in range(7, 0, -1):
c = 0x00
for pixel_index in range(0, 8):
c |= (data[3*pixel_index] >> bit_index & 1) << pixel_index
output += chr(c)
# Blue byte
output += '\xFF'
for bit_index in range(7, 0, -1):
c = 0x00
for pixel_index in range(0, 8):
c |= (data[2+3*pixel_index] >> bit_index & 1) << pixel_index
output += chr(c)
return output
def draw(self, data):
"""
Draw a portion of an image frame to LED strips.
@param data Image data, as a 1D, 8bit RGB array.
"""
self.load_data(data)
self.flip()
def load_data(self, data):
"""
Load the next frame into the strips, but don't actually clock it out.
@param data Image data, as a 1D, 8bit RGB array.
"""
s = ''
format_time = 0
# for each 'row' in the data, assemble a byte stream for it.
for row in range(0,len(data)/3/self.image_width):
start_index = (self.image_width*row + self.offset)*3
format_start_time = time.time()
s += self.RgbRowToStrips(data[start_index:start_index+24])
format_time += time.time() - format_start_time
# Send the data out in 64-byte chunks
output_start_time = time.time()
for x in range(0, len(s)/64):
t = s[64 * x : (64 * x) + 64]
self.ser.write(t)
output_time = time.time() - output_start_time
self.format_time_total += format_time
self.frame_count += 1
if self.frame_count > 30:
average_time = self.format_time_total/self.frame_count
self.frame_count = 0
self.format_time_total = 0
print average_time
def flip(self):
# TODO: Why does 20 work? it make a'no sense.
# 1 does not work with the listener.
for i in range(0,64):
self.ser.write('\x00')
if __name__ == "__main__":
parser = optparse.OptionParser()
parser.add_option("-p", "--serialport", dest="serial_port",
help="serial port (ex: /dev/ttyUSB0)", default="/dev/tty.usbmodel12341")
parser.add_option("-l", "--length", dest="strip_length",
help="length of the strip", default=160, type=int)
(options, args) = parser.parse_args()
image_width = 8 # width of the picture
strip = LedStrips(image_width, 0)
strip.connect(options.serial_port)
i = 0
j = 0
while True:
data = ''
for row in range (0, options.strip_length):
for col in range (0, image_width):
if ((row+j)%3 == 0):
data += chr(0xFF) # B
data += chr(0) # B
data += chr(0) # B
if ((row+j)%3 == 1):
data += chr(0) # B
data += chr(0xFF) # B
data += chr(0) # B
if ((row+j)%3 == 2):
data += chr(0) # B
data += chr(0) # B
data += chr(0xFF) # B
# data += chr(0xFF) # B
# data += chr(0xFF) # B
# data += chr(0xFF) # B
i = (i+1)%20
if i == 0:
j = (j+1)%255
strip.draw(data)