/
leds.py
executable file
·146 lines (116 loc) · 3.74 KB
/
leds.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
"""
Classes for working with lights.
"""
import atexit
from spidev import SpiDev
START_OF_FRAME = 0xE0
MAX_BRIGHTNESS = 0x1F
class Pixel:
"""
An individual LED from a chain of APA102 LEDs
"""
def __init__(self, n, brightness=0x00):
"""
Constructor
:param n: LED number. Entirely informational, is not used anywhere.
:param brightness: initial global brightness, defaults to 0 (off). See set_brightness for additional info.
"""
self.brightness = brightness & ~START_OF_FRAME
self.n = n
self.buf = bytearray([START_OF_FRAME, 0, 0, 0])
def set(self, r, g, b, brightness=None):
"""
Set the colour values for the pixel. All values are in the range [0x00..0xFF].
:param r: Red value.
:param g: Green value.
:param b: Blue value.
:param brightness: Optional global brightness. If None (default) uses the existing global brightness.
"""
if brightness is not None:
self.brightness = brightness & ~START_OF_FRAME
self.buf[0] = START_OF_FRAME | self.brightness
self.buf[1] = b
self.buf[2] = g
self.buf[3] = r
def set_brightness(self, brightness):
"""
Sets the global brightness.
:param brightness: New global brightness. Valid range is [0x00..0x1F], anything else will be truncated.
"""
self.brightness = brightness & ~START_OF_FRAME
self.buf[0] = START_OF_FRAME | self.brightness
def get(self):
"""
Gets the current RGB value of the pixel.
:return: Tuple: (R, G, B)
"""
return self.buf[1], self.buf[2], self.buf[3]
def raw(self):
"""
Gets the raw bytes to send to the LED.
:return: 4 byte buffer.
"""
return self.buf
class Lights:
"""
A collection of APA102 LEDs.
"""
def __init__(self, led_indexes):
"""
Create the LED controller.
:param led_indexes: physical -> logical LED mapping: led_indexes[n] = LED number
"""
self.spi = SpiDev()
self.spi.open(0, 0)
self.spi.max_speed_hz = 1000000
self.pixels = [Pixel(n) for n in range(len(led_indexes))]
self.mapping = led_indexes
atexit.register(self._on_exit)
def set_pixel(self, index, r, g, b, brightness=None):
"""
Set pixel colour.
:param index: logical index of the LED
:param r: Red
:param g: Green
:param b: Blue
:param brightness: Optional brightness value
"""
pixel = self.get_pixel(index)
pixel.set(r, g, b, brightness)
def set_brightness(self, brightness, index=None):
"""
Set global brightness.
:param brightness: Global brightness value.
:param index: Optional LED to address. If None, sets brightness for the whole string.
"""
b = round(brightness)
if index is None:
for p in self.pixels:
p.set_brightness(b)
else:
self.get_pixel(index).set_brightness(b)
def get_pixel(self, index):
"""
Gets the pixel at a given index.
:param index: The index of the pixel.
:return: The pixel.
"""
return self.pixels[self.mapping[index]]
def clear(self):
"""
Blank all LEDs.
"""
for p in self.pixels:
p.set(0, 0, 0)
def show(self):
"""
Send the current pixel data to the LEDs
"""
buf = [0x00 for _ in range(8)]
for p in self.pixels:
buf += p.raw()
buf += [0xFF for _ in range(8)]
self.spi.xfer2(buf)
def _on_exit(self):
self.clear()
self.show()