Merge pull request #18 from mcscope/color_orders
Support Color Order setting
This commit is contained in:
commit
dfd0b4c868
1 changed files with 32 additions and 24 deletions
|
|
@ -36,6 +36,17 @@ import digitalio
|
|||
__version__ = "0.0.0-auto.0"
|
||||
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_DotStar.git"
|
||||
|
||||
START_HEADER_SIZE = 4
|
||||
|
||||
# Pixel color order constants
|
||||
RGB = (0, 1, 2)
|
||||
RBG = (0, 2, 1)
|
||||
GRB = (1, 0, 2)
|
||||
GBR = (1, 2, 0)
|
||||
BRG = (2, 0, 1)
|
||||
BGR = (2, 1, 0)
|
||||
|
||||
|
||||
class DotStar:
|
||||
"""
|
||||
A sequence of dotstars.
|
||||
|
|
@ -46,6 +57,9 @@ class DotStar:
|
|||
:param float brightness: Brightness of the pixels between 0.0 and 1.0
|
||||
:param bool auto_write: True if the dotstars should immediately change when
|
||||
set. If False, `show` must be called explicitly.
|
||||
:param tuple pixel_order: Set the pixel order on the strip - different
|
||||
strips implement this differently. If you send red, and it looks blue
|
||||
or green on the strip, modify this! It should be one of the values above
|
||||
|
||||
|
||||
Example for Gemma M0:
|
||||
|
|
@ -63,7 +77,7 @@ class DotStar:
|
|||
time.sleep(2)
|
||||
"""
|
||||
|
||||
def __init__(self, clock, data, n, *, brightness=1.0, auto_write=True):
|
||||
def __init__(self, clock, data, n, *, brightness=1.0, auto_write=True, pixel_order=BGR):
|
||||
self._spi = None
|
||||
try:
|
||||
self._spi = busio.SPI(clock, MOSI=data)
|
||||
|
|
@ -77,19 +91,18 @@ class DotStar:
|
|||
self.cpin.direction = digitalio.Direction.OUTPUT
|
||||
self.cpin.value = False
|
||||
self._n = n
|
||||
self.start_header_size = 4
|
||||
# Supply one extra clock cycle for each two pixels in the strip.
|
||||
self.end_header_size = n // 16
|
||||
if n % 16 != 0:
|
||||
self.end_header_size += 1
|
||||
self._buf = bytearray(n * 4 + self.start_header_size + self.end_header_size)
|
||||
self._buf = bytearray(n * 4 + START_HEADER_SIZE + self.end_header_size)
|
||||
self.end_header_index = len(self._buf) - self.end_header_size
|
||||
|
||||
self.pixel_order = pixel_order
|
||||
# Four empty bytes to start.
|
||||
for i in range(self.start_header_size):
|
||||
for i in range(START_HEADER_SIZE):
|
||||
self._buf[i] = 0x00
|
||||
# Mark the beginnings of each pixel.
|
||||
for i in range(self.start_header_size, self.end_header_index, 4):
|
||||
for i in range(START_HEADER_SIZE, self.end_header_index, 4):
|
||||
self._buf[i] = 0xff
|
||||
# 0xff bytes at the end.
|
||||
for i in range(self.end_header_index, len(self._buf)):
|
||||
|
|
@ -104,7 +117,7 @@ class DotStar:
|
|||
def deinit(self):
|
||||
"""Blank out the DotStars and release the resources."""
|
||||
self.auto_write = False
|
||||
for i in range(self.start_header_size, self.end_header_index):
|
||||
for i in range(START_HEADER_SIZE, self.end_header_index):
|
||||
if i % 4 != 0:
|
||||
self._buf[i] = 0
|
||||
self.show()
|
||||
|
|
@ -124,24 +137,19 @@ class DotStar:
|
|||
return "[" + ", ".join([str(x) for x in self]) + "]"
|
||||
|
||||
def _set_item(self, index, value):
|
||||
offset = index * 4 + self.start_header_size
|
||||
r = 0
|
||||
g = 0
|
||||
b = 0
|
||||
offset = index * 4 + START_HEADER_SIZE
|
||||
rgb = value
|
||||
if isinstance(value, int):
|
||||
r = value >> 16
|
||||
g = (value >> 8) & 0xff
|
||||
b = value & 0xff
|
||||
else:
|
||||
r, g, b = value
|
||||
rgb = (value >> 16, (value >> 8) & 0xff, value & 0xff)
|
||||
|
||||
# Each pixel starts with 0xFF, then red/green/blue. Although the data
|
||||
# sheet suggests using a global brightness in the first byte, we don't
|
||||
# do that because it causes further issues with persistence of vision
|
||||
# projects.
|
||||
self._buf[offset] = 0xff # redundant; should already be set
|
||||
self._buf[offset + 1] = b
|
||||
self._buf[offset + 2] = g
|
||||
self._buf[offset + 3] = r
|
||||
self._buf[offset + 1] = rgb[self.pixel_order[0]]
|
||||
self._buf[offset + 2] = rgb[self.pixel_order[1]]
|
||||
self._buf[offset + 3] = rgb[self.pixel_order[2]]
|
||||
|
||||
def __setitem__(self, index, val):
|
||||
if isinstance(index, slice):
|
||||
|
|
@ -164,14 +172,14 @@ class DotStar:
|
|||
out = []
|
||||
for in_i in range(*index.indices(self._n)):
|
||||
out.append(
|
||||
tuple(self._buf[in_i * 4 + (3 - i) + self.start_header_size] for i in range(3)))
|
||||
tuple(self._buf[in_i * 4 + (3 - i) + START_HEADER_SIZE] for i in range(3)))
|
||||
return out
|
||||
if index < 0:
|
||||
index += len(self)
|
||||
if index >= self._n or index < 0:
|
||||
raise IndexError
|
||||
offset = index * 4
|
||||
return tuple(self._buf[offset + (3 - i) + self.start_header_size]
|
||||
return tuple(self._buf[offset + (3 - i) + START_HEADER_SIZE]
|
||||
for i in range(3))
|
||||
|
||||
def __len__(self):
|
||||
|
|
@ -217,10 +225,10 @@ class DotStar:
|
|||
if self.brightness < 1.0:
|
||||
buf = bytearray(self._buf)
|
||||
# Four empty bytes to start.
|
||||
for i in range(self.start_header_size):
|
||||
for i in range(START_HEADER_SIZE):
|
||||
buf[i] = 0x00
|
||||
for i in range(self.start_header_size, self.end_header_index):
|
||||
buf[i] = self._buf[i] if i %4 == 0 else int(self._buf[i] * self._brightness)
|
||||
for i in range(START_HEADER_SIZE, self.end_header_index):
|
||||
buf[i] = self._buf[i] if i % 4 == 0 else int(self._buf[i] * self._brightness)
|
||||
# Four 0xff bytes at the end.
|
||||
for i in range(self.end_header_index, len(buf)):
|
||||
buf[i] = 0xff
|
||||
|
|
|
|||
Loading…
Reference in a new issue