Skip to content

Commit 9a15cfc

Browse files
committed
Add SK9822 support
1 parent fe9109e commit 9a15cfc

File tree

1 file changed

+21
-8
lines changed

1 file changed

+21
-8
lines changed

adafruit_dotstar.py

+21-8
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,10 @@ class DotStar:
5959
:param tuple pixel_order: Set the pixel order on the strip - different
6060
strips implement this differently. If you send red, and it looks blue
6161
or green on the strip, modify this! It should be one of the values above
62-
62+
:param bool SK9822: True if using SK9822 LEDs which have constant current brightness
63+
control. If set, global brightness will always use on-strip control instead
64+
of local scaling. Using the 4th tuple value brightness control will overwrite
65+
this on a per-pixel level
6366
6467
Example for Gemma M0:
6568
@@ -76,7 +79,8 @@ class DotStar:
7679
time.sleep(2)
7780
"""
7881

79-
def __init__(self, clock, data, n, *, brightness=1.0, auto_write=True, pixel_order=BGR):
82+
def __init__(self, clock, data, n, *, brightness=1.0,
83+
auto_write=True, pixel_order=BGR, SK9822=False):
8084
self._spi = None
8185
try:
8286
self._spi = busio.SPI(clock, MOSI=data)
@@ -91,7 +95,9 @@ def __init__(self, clock, data, n, *, brightness=1.0, auto_write=True, pixel_ord
9195
self.cpin.value = False
9296
self._n = n
9397
# Supply one extra clock cycle for each two pixels in the strip.
94-
self.end_header_size = n // 16
98+
# plus an extra 32 bits for SK9822 compatibility
99+
# uses unified APA102 / SK9822 protocol from https://cpldcpu.wordpress.com/2016/12/13/sk9822-a-clone-of-the-apa102/
100+
self.end_header_size = (n // 16) + 4
95101
if n % 16 != 0:
96102
self.end_header_size += 1
97103
self._buf = bytearray(n * 4 + START_HEADER_SIZE + self.end_header_size)
@@ -103,10 +109,11 @@ def __init__(self, clock, data, n, *, brightness=1.0, auto_write=True, pixel_ord
103109
# Mark the beginnings of each pixel.
104110
for i in range(START_HEADER_SIZE, self.end_header_index, 4):
105111
self._buf[i] = 0xff
106-
# 0xff bytes at the end.
112+
# 0x00 bytes at the end.
107113
for i in range(self.end_header_index, len(self._buf)):
108-
self._buf[i] = 0xff
114+
self._buf[i] = 0x00
109115
self._brightness = 1.0
116+
self._sk9822 = SK9822
110117
# Set auto_write to False temporarily so brightness setter does _not_
111118
# call show() while in __init__.
112119
self.auto_write = False
@@ -157,7 +164,7 @@ def _set_item(self, index, value):
157164
if isinstance(value, int):
158165
rgb = (value >> 16, (value >> 8) & 0xff, value & 0xff)
159166

160-
if len(value) == 4:
167+
if len(rgb) == 4:
161168
brightness = value[3]
162169
# Ignore value[3] below.
163170
else:
@@ -218,6 +225,11 @@ def brightness(self):
218225
@brightness.setter
219226
def brightness(self, brightness):
220227
self._brightness = min(max(brightness, 0.0), 1.0)
228+
if self._sk9822:
229+
brightness_byte = (32 - int(32 - brightness * 31) & 0b00011111) | LED_START
230+
for i in range(0, self._n * 4, 4):
231+
self._buf[i + START_HEADER_SIZE] = brightness_byte
232+
221233
if self.auto_write:
222234
self.show()
223235

@@ -247,7 +259,8 @@ def show(self):
247259
it may be done asynchronously."""
248260
# Create a second output buffer if we need to compute brightness
249261
buf = self._buf
250-
if self.brightness < 1.0:
262+
263+
if not self._sk9822 and self.brightness < 1.0:
251264
buf = bytearray(self._buf)
252265
# Four empty bytes to start.
253266
for i in range(START_HEADER_SIZE):
@@ -256,7 +269,7 @@ def show(self):
256269
buf[i] = self._buf[i] if i % 4 == 0 else int(self._buf[i] * self._brightness)
257270
# Four 0xff bytes at the end.
258271
for i in range(self.end_header_index, len(buf)):
259-
buf[i] = 0xff
272+
buf[i] = 0x00
260273

261274
if self._spi:
262275
self._spi.write(buf)

0 commit comments

Comments
 (0)