Skip to content

Commit dfd0b4c

Browse files
authored
Merge pull request #18 from mcscope/color_orders
Support Color Order setting
2 parents 144bb07 + 1b877e1 commit dfd0b4c

File tree

1 file changed

+32
-24
lines changed

1 file changed

+32
-24
lines changed

adafruit_dotstar.py

+32-24
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,17 @@
3636
__version__ = "0.0.0-auto.0"
3737
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_DotStar.git"
3838

39+
START_HEADER_SIZE = 4
40+
41+
# Pixel color order constants
42+
RGB = (0, 1, 2)
43+
RBG = (0, 2, 1)
44+
GRB = (1, 0, 2)
45+
GBR = (1, 2, 0)
46+
BRG = (2, 0, 1)
47+
BGR = (2, 1, 0)
48+
49+
3950
class DotStar:
4051
"""
4152
A sequence of dotstars.
@@ -46,6 +57,9 @@ class DotStar:
4657
:param float brightness: Brightness of the pixels between 0.0 and 1.0
4758
:param bool auto_write: True if the dotstars should immediately change when
4859
set. If False, `show` must be called explicitly.
60+
:param tuple pixel_order: Set the pixel order on the strip - different
61+
strips implement this differently. If you send red, and it looks blue
62+
or green on the strip, modify this! It should be one of the values above
4963
5064
5165
Example for Gemma M0:
@@ -63,7 +77,7 @@ class DotStar:
6377
time.sleep(2)
6478
"""
6579

66-
def __init__(self, clock, data, n, *, brightness=1.0, auto_write=True):
80+
def __init__(self, clock, data, n, *, brightness=1.0, auto_write=True, pixel_order=BGR):
6781
self._spi = None
6882
try:
6983
self._spi = busio.SPI(clock, MOSI=data)
@@ -77,19 +91,18 @@ def __init__(self, clock, data, n, *, brightness=1.0, auto_write=True):
7791
self.cpin.direction = digitalio.Direction.OUTPUT
7892
self.cpin.value = False
7993
self._n = n
80-
self.start_header_size = 4
8194
# Supply one extra clock cycle for each two pixels in the strip.
8295
self.end_header_size = n // 16
8396
if n % 16 != 0:
8497
self.end_header_size += 1
85-
self._buf = bytearray(n * 4 + self.start_header_size + self.end_header_size)
98+
self._buf = bytearray(n * 4 + START_HEADER_SIZE + self.end_header_size)
8699
self.end_header_index = len(self._buf) - self.end_header_size
87-
100+
self.pixel_order = pixel_order
88101
# Four empty bytes to start.
89-
for i in range(self.start_header_size):
102+
for i in range(START_HEADER_SIZE):
90103
self._buf[i] = 0x00
91104
# Mark the beginnings of each pixel.
92-
for i in range(self.start_header_size, self.end_header_index, 4):
105+
for i in range(START_HEADER_SIZE, self.end_header_index, 4):
93106
self._buf[i] = 0xff
94107
# 0xff bytes at the end.
95108
for i in range(self.end_header_index, len(self._buf)):
@@ -104,7 +117,7 @@ def __init__(self, clock, data, n, *, brightness=1.0, auto_write=True):
104117
def deinit(self):
105118
"""Blank out the DotStars and release the resources."""
106119
self.auto_write = False
107-
for i in range(self.start_header_size, self.end_header_index):
120+
for i in range(START_HEADER_SIZE, self.end_header_index):
108121
if i % 4 != 0:
109122
self._buf[i] = 0
110123
self.show()
@@ -124,24 +137,19 @@ def __repr__(self):
124137
return "[" + ", ".join([str(x) for x in self]) + "]"
125138

126139
def _set_item(self, index, value):
127-
offset = index * 4 + self.start_header_size
128-
r = 0
129-
g = 0
130-
b = 0
140+
offset = index * 4 + START_HEADER_SIZE
141+
rgb = value
131142
if isinstance(value, int):
132-
r = value >> 16
133-
g = (value >> 8) & 0xff
134-
b = value & 0xff
135-
else:
136-
r, g, b = value
143+
rgb = (value >> 16, (value >> 8) & 0xff, value & 0xff)
144+
137145
# Each pixel starts with 0xFF, then red/green/blue. Although the data
138146
# sheet suggests using a global brightness in the first byte, we don't
139147
# do that because it causes further issues with persistence of vision
140148
# projects.
141149
self._buf[offset] = 0xff # redundant; should already be set
142-
self._buf[offset + 1] = b
143-
self._buf[offset + 2] = g
144-
self._buf[offset + 3] = r
150+
self._buf[offset + 1] = rgb[self.pixel_order[0]]
151+
self._buf[offset + 2] = rgb[self.pixel_order[1]]
152+
self._buf[offset + 3] = rgb[self.pixel_order[2]]
145153

146154
def __setitem__(self, index, val):
147155
if isinstance(index, slice):
@@ -164,14 +172,14 @@ def __getitem__(self, index):
164172
out = []
165173
for in_i in range(*index.indices(self._n)):
166174
out.append(
167-
tuple(self._buf[in_i * 4 + (3 - i) + self.start_header_size] for i in range(3)))
175+
tuple(self._buf[in_i * 4 + (3 - i) + START_HEADER_SIZE] for i in range(3)))
168176
return out
169177
if index < 0:
170178
index += len(self)
171179
if index >= self._n or index < 0:
172180
raise IndexError
173181
offset = index * 4
174-
return tuple(self._buf[offset + (3 - i) + self.start_header_size]
182+
return tuple(self._buf[offset + (3 - i) + START_HEADER_SIZE]
175183
for i in range(3))
176184

177185
def __len__(self):
@@ -217,10 +225,10 @@ def show(self):
217225
if self.brightness < 1.0:
218226
buf = bytearray(self._buf)
219227
# Four empty bytes to start.
220-
for i in range(self.start_header_size):
228+
for i in range(START_HEADER_SIZE):
221229
buf[i] = 0x00
222-
for i in range(self.start_header_size, self.end_header_index):
223-
buf[i] = self._buf[i] if i %4 == 0 else int(self._buf[i] * self._brightness)
230+
for i in range(START_HEADER_SIZE, self.end_header_index):
231+
buf[i] = self._buf[i] if i % 4 == 0 else int(self._buf[i] * self._brightness)
224232
# Four 0xff bytes at the end.
225233
for i in range(self.end_header_index, len(buf)):
226234
buf[i] = 0xff

0 commit comments

Comments
 (0)