Add support for pixelbuf

This commit is contained in:
George Waters 2020-05-08 22:45:05 -04:00
parent 694fdecb7e
commit 21310b27f8
7 changed files with 90 additions and 135 deletions

View file

@ -78,50 +78,6 @@ This example demonstrates the library with the single built-in DotStar on the
pixels = adafruit_dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1)
pixels[0] = (10, 0, 0)
This example demonstrates the library with the DotStar Feather Wing and bounces Blinka.
`Feather M4 Express <https://www.adafruit.com/product/3857>`_ and
`DotStar FeatherWing <https://www.adafruit.com/product/3449>`_.
.. code-block:: python
import board
import adafruit_dotstar
import time
import adafruit_dotstar
dotstar = adafruit_dotstar.DotStar(board.D13, board.D11, 72,
pixel_order=adafruit_dotstar.BGR,
brightness=0.3, auto_write=False)
blinka = (
(0, 0x0f0716, 0x504069, 0x482e63, 0, 0),
(0, 0x3d1446, 0x502b74, 0x622f8c, 0, 0),
(0, 0x2e021b, 0x2e021b, 0x2e021b, 0, 0),
(0, 0, 0x2e021b, 0x2e021b, 0, 0),
(0, 0x591755, 0x912892, 0x3f205c, 0x282828, 0x301844),
(0x65206b, 0x932281, 0x6e318f, 0x6d2b7e, 0x7e2686, 0x8c2c8f),
(0x7c2d8c, 0xa21c81, 0x6b308e, 0x74257b, 0x7b2482, 0x742f8d),
(0x23051a, 0x5c0f45, 0x81227b, 0x551a5b, 0x691b5d, 0x4d0c39),
)
offset = 0
direction = 1
while True:
dotstar.fill(0)
for y, row in enumerate(blinka):
for x, value in enumerate(row):
n = x * 12 + (y + offset)
dotstar[n] = row[x]
dotstar.show()
time.sleep(0.1)
offset += direction
if offset > 4 or offset < 0:
direction = -direction
offset += direction
Contributing
============

View file

@ -29,8 +29,15 @@
* Author(s): Damien P. George, Limor Fried, Scott Shawcroft & Roy Hooper
"""
# pylint: disable=ungrouped-imports
import sys
import busio
import digitalio
if sys.implementation.version[0] < 5:
import adafruit_pypixelbuf as _pixelbuf
else:
try:
import _pixelbuf
except ImportError:
@ -41,13 +48,13 @@ __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_DotStar.git"
START_HEADER_SIZE = 4
RBG = 'PRBG'
RGB = 'PRGB'
GRB = 'PGRB'
GBR = 'PGBR'
BRG = 'PBRG'
BGR = 'PBGR'
BGR = 'PBGR'
RBG = "PRBG"
RGB = "PRGB"
GRB = "PGRB"
GBR = "PGBR"
BRG = "PBRG"
BGR = "PBGR"
BGR = "PBGR"
class DotStar(_pixelbuf.PixelBuf):
@ -81,6 +88,22 @@ class DotStar(_pixelbuf.PixelBuf):
with adafruit_dotstar.DotStar(APA102_SCK, APA102_MOSI, 1) as pixels:
pixels[0] = RED
time.sleep(2)
.. py:method:: DotStar.show()
Shows the new colors on the dotstars themselves if they haven't already
been autowritten.
The colors may or may not be showing after this function returns because
it may be done asynchronously.
.. py:method:: DotStar.fill(color)
Colors all dotstars the given ***color***.
.. py:attribute:: brightness
Overall brightness of the dotstar (0 to 1.0)
"""
def __init__(
@ -107,56 +130,25 @@ class DotStar(_pixelbuf.PixelBuf):
self.dpin.direction = digitalio.Direction.OUTPUT
self.cpin.direction = digitalio.Direction.OUTPUT
self.cpin.value = False
self.n = n
# Supply one extra clock cycle for each two pixels in the strip.
end_header_size = n // 16
trailer_size = n // 16
if n % 16 != 0:
end_header_size += 1
bufsize = 4 * n + START_HEADER_SIZE + end_header_size
end_header_index = bufsize - end_header_size
self.pixel_order = pixel_order
trailer_size += 1
self._buf = bytearray(bufsize)
self._rawbuf = bytearray(bufsize)
# Four empty bytes for the header.
header = bytearray(START_HEADER_SIZE)
# 0xff bytes for the trailer.
trailer = bytearray(b"\xff") * trailer_size
# Four empty bytes to start.
for i in range(START_HEADER_SIZE):
self._rawbuf[i] = 0x00
# 0xff bytes at the end.
for i in range(end_header_index, bufsize):
self._rawbuf[i] = 0xff
# Mark the beginnings of each pixel.
for i in range(START_HEADER_SIZE, end_header_index, 4):
self._rawbuf[i] = 0xff
self._buf[:] = self._rawbuf[:]
super(DotStar, self).__init__(n, self._buf, byteorder=pixel_order,
rawbuf=self._rawbuf, offset=START_HEADER_SIZE,
brightness=brightness, auto_write=auto_write)
def show(self):
"""Shows the new colors on the pixels themselves if they haven't already
been autowritten.
The colors may or may not be showing after this method returns because
it may be done asynchronously.
This method is called automatically if auto_write is set to True.
"""
if self._spi:
self._spi.write(self._buf)
else:
self.ds_writebytes()
def _ds_writebytes(self):
for b in self.buf:
for _ in range(8):
self.dpin.value = (b & 0x80)
self.cpin.value = True
self.cpin.value = False
b = b << 1
self.cpin.value = False
super().__init__(
n,
byteorder=pixel_order,
brightness=brightness,
auto_write=auto_write,
header=header,
trailer=trailer,
)
def deinit(self):
"""Blank out the DotStars and release the resources."""
@ -177,6 +169,24 @@ class DotStar(_pixelbuf.PixelBuf):
def __repr__(self):
return "[" + ", ".join([str(x) for x in self]) + "]"
def fill(self, color):
"""Colors all pixels the given ***color***."""
_pixelbuf.fill(self, color)
@property
def n(self):
"""
The number of dotstars in the chain (read-only)
"""
return len(self)
def _transmit(self, buffer):
if self._spi:
self._spi.write(buffer)
else:
self._ds_writebytes(buffer)
def _ds_writebytes(self, buffer):
for b in buffer:
for _ in range(8):
self.dpin.value = b & 0x80
self.cpin.value = True
self.cpin.value = False
b = b << 1
self.cpin.value = False

View file

@ -16,7 +16,7 @@ extensions = [
"sphinx.ext.viewcode",
]
autodoc_mock_imports = ["pypixelbuf"]
# autodoc_mock_imports = ["digitalio", "busio"]
intersphinx_mapping = {
"python": ("https://docs.python.org/3.4", None),

View file

@ -25,7 +25,7 @@ DOTS = dotstar.DotStar(
board.MOSI,
NUMPIXELS,
auto_write=False,
brightness=0.25,
brightness=1.0,
pixel_order=ORDER,
)
@ -42,41 +42,29 @@ if HEIGHT > NUMPIXELS:
# Calculate gamma correction table, makes mid-range colors look 'right':
GAMMA = bytearray(256)
brightness = 0.25
for i in range(256):
# Notice we access DOTS.brightness directly here...the gamma table will
# handle any brightness-scaling, so we can set the object brightness back
# to max and it won't need to perform brightness scaling on every write.
GAMMA[i] = int(pow(float(i) / 255.0, 2.7) * DOTS.brightness * 255.0 + 0.5)
DOTS.brightness = 1.0
GAMMA[i] = int(pow(float(i) / 255.0, 2.7) * brightness * 255.0 + 0.5)
# Allocate list of bytearrays, one for each column of image.
# Each pixel REQUIRES 4 bytes (0xFF, B, G, R).
# Allocate list of lists, one for each column of image.
print("Allocating...")
COLUMN = [0 for x in range(WIDTH)]
for x in range(WIDTH):
COLUMN[x] = bytearray(HEIGHT * 4)
COLUMN[x] = [[0, 0, 0, 0] for _ in range(HEIGHT)]
# Convert entire RGB image into column-wise bytearray list.
# The dotstar_image_paint.py example uses the library's 'setter' operation
# for each pixel to do any R/G/B reordering. Because we're preparing data
# directly for the strip, there's a reference to 'ORDER' here to rearrange
# the color bytes as needed.
# Convert entire RGB image into columnxrow 2D list.
print("Converting...")
for x in range(WIDTH): # For each column of image
for y in range(HEIGHT): # For each pixel in column
value = PIXELS[x, y] # Read RGB pixel in image
y4 = y * 4 # Position in raw buffer
COLUMN[x][y4] = 0xFF # Pixel start marker
y4 += 1 # Pixel color data start
COLUMN[x][y4 + ORDER[0]] = GAMMA[value[0]] # Gamma-corrected R
COLUMN[x][y4 + ORDER[1]] = GAMMA[value[1]] # Gamma-corrected G
COLUMN[x][y4 + ORDER[2]] = GAMMA[value[2]] # Gamma-corrected B
COLUMN[x][y][0] = GAMMA[value[0]] # Gamma-corrected R
COLUMN[x][y][1] = GAMMA[value[1]] # Gamma-corrected G
COLUMN[x][y][2] = GAMMA[value[2]] # Gamma-corrected B
COLUMN[x][y][3] = 1.0 # Brightness
print("Displaying...")
while True: # Loop forever
# pylint: disable=protected-access
# (Really shouldn't access _buf directly, but needed for fastest POV)
for x in range(WIDTH): # For each column of image...
DOTS._buf[4 : 4 + HEIGHT * 4] = COLUMN[x] # Copy column to DotStar buffer
DOTS[0 : DOTS.n] = COLUMN[x] # Copy column to DotStar buffer
DOTS.show() # Send data to strip

View file

@ -14,7 +14,7 @@ dots = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2)
# HELPERS
# a random color 0 -> 224
# a random color 0 -> 192
def random_color():
return random.randrange(0, 7) * 32

View file

@ -1,3 +1,3 @@
Adafruit-Blinka
adafruit-circuitpython-busdevice
adafruit-circuitpython-pypixelbuf
adafruit-circuitpython-pypixelbuf>=2.0.0

View file

@ -28,12 +28,13 @@ setup(
# The project's main homepage.
url="https://github.com/adafruit/Adafruit_CircuitPython_DotStar",
# Author details
author='Adafruit Industries',
author_email='circuitpython@adafruit.com',
install_requires=['Adafruit-Blinka', 'adafruit-circuitpython-busdevice',
'adafruit-circuitpython-pypixelbuf'],
author="Adafruit Industries",
author_email="circuitpython@adafruit.com",
install_requires=[
"Adafruit-Blinka",
"adafruit-circuitpython-busdevice",
"adafruit-circuitpython-pypixelbuf>=2.0.0",
],
# Choose your license
license="MIT",
# See https://pypi.python.org/pypi?%3Aaction=list_classifiers