Skip to content

Commit 326fed4

Browse files
authored
Merge pull request #82 from dunkmann00/pixelbuf
Pixelbuf Support #2
2 parents e2ffd40 + ef6edc4 commit 326fed4

File tree

2 files changed

+59
-132
lines changed

2 files changed

+59
-132
lines changed

neopixel.py

Lines changed: 58 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
#
33
# Copyright (c) 2016 Damien P. George
44
# Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
5+
# Copyright (c) 2019 Carter Nelson
6+
# Copyright (c) 2019 Roy Hooper
57
#
68
# Permission is hereby granted, free of charge, to any person obtaining a copy
79
# of this software and associated documentation files (the "Software"), to deal
@@ -25,29 +27,39 @@
2527
`neopixel` - NeoPixel strip driver
2628
====================================================
2729
28-
* Author(s): Damien P. George & Scott Shawcroft
30+
* Author(s): Damien P. George, Scott Shawcroft, Carter Nelson, Roy Hooper
2931
"""
3032

31-
import math
32-
33+
# pylint: disable=ungrouped-imports
34+
import sys
3335
import digitalio
3436
from neopixel_write import neopixel_write
3537

38+
if sys.implementation.version[0] < 5:
39+
import adafruit_pypixelbuf as _pixelbuf
40+
else:
41+
try:
42+
import _pixelbuf
43+
except ImportError:
44+
import adafruit_pypixelbuf as _pixelbuf
45+
46+
3647
__version__ = "0.0.0-auto.0"
3748
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_NeoPixel.git"
3849

50+
3951
# Pixel color order constants
40-
RGB = (0, 1, 2)
52+
RGB = "RGB"
4153
"""Red Green Blue"""
42-
GRB = (1, 0, 2)
54+
GRB = "GRB"
4355
"""Green Red Blue"""
44-
RGBW = (0, 1, 2, 3)
56+
RGBW = "RGBW"
4557
"""Red Green Blue White"""
46-
GRBW = (1, 0, 2, 3)
58+
GRBW = "GRBW"
4759
"""Green Red Blue White"""
4860

4961

50-
class NeoPixel:
62+
class NeoPixel(_pixelbuf.PixelBuf):
5163
"""
5264
A sequence of neopixels.
5365
@@ -58,7 +70,7 @@ class NeoPixel:
5870
brightness
5971
:param bool auto_write: True if the neopixels should immediately change when set. If False,
6072
`show` must be called explicitly.
61-
:param tuple pixel_order: Set the pixel color channel order. GRBW is set by default.
73+
:param str: Set the pixel color channel order. GRBW is set by default.
6274
6375
Example for Circuit Playground Express:
6476
@@ -87,32 +99,46 @@ class NeoPixel:
8799
with neopixel.NeoPixel(NEOPIXEL, 10) as pixels:
88100
pixels[::2] = [RED] * (len(pixels) // 2)
89101
time.sleep(2)
102+
103+
.. py:method:: NeoPixel.show()
104+
105+
Shows the new colors on the pixels themselves if they haven't already
106+
been autowritten.
107+
108+
The colors may or may not be showing after this function returns because
109+
it may be done asynchronously.
110+
111+
.. py:method:: NeoPixel.fill(color)
112+
113+
Colors all pixels the given ***color***.
114+
115+
.. py:attribute:: brightness
116+
117+
Overall brightness of the pixel (0 to 1.0)
118+
90119
"""
91120

92121
def __init__(
93122
self, pin, n, *, bpp=3, brightness=1.0, auto_write=True, pixel_order=None
94123
):
124+
if not pixel_order:
125+
pixel_order = GRB if bpp == 3 else GRBW
126+
else:
127+
if isinstance(pixel_order, tuple):
128+
order_list = [RGBW[order] for order in pixel_order]
129+
pixel_order = "".join(order_list)
130+
131+
super().__init__(
132+
n, brightness=brightness, byteorder=pixel_order, auto_write=auto_write
133+
)
134+
95135
self.pin = digitalio.DigitalInOut(pin)
96136
self.pin.direction = digitalio.Direction.OUTPUT
97-
self.n = n
98-
if pixel_order is None:
99-
self.order = GRBW
100-
self.bpp = bpp
101-
else:
102-
self.order = pixel_order
103-
self.bpp = len(self.order)
104-
self.buf = bytearray(self.n * self.bpp)
105-
# Set auto_write to False temporarily so brightness setter does _not_
106-
# call show() while in __init__.
107-
self.auto_write = False
108-
self.brightness = brightness
109-
self.auto_write = auto_write
110137

111138
def deinit(self):
112139
"""Blank out the NeoPixels and release the pin."""
113-
for i in range(len(self.buf)):
114-
self.buf[i] = 0
115-
neopixel_write(self.pin, self.buf)
140+
self.fill(0)
141+
self.show()
116142
self.pin.deinit()
117143

118144
def __enter__(self):
@@ -124,118 +150,18 @@ def __exit__(self, exception_type, exception_value, traceback):
124150
def __repr__(self):
125151
return "[" + ", ".join([str(x) for x in self]) + "]"
126152

127-
def _set_item(self, index, value):
128-
if index < 0:
129-
index += len(self)
130-
if index >= self.n or index < 0:
131-
raise IndexError
132-
offset = index * self.bpp
133-
r = 0
134-
g = 0
135-
b = 0
136-
w = 0
137-
if isinstance(value, int):
138-
if value >> 24:
139-
raise ValueError("only bits 0->23 valid for integer input")
140-
r = value >> 16
141-
g = (value >> 8) & 0xFF
142-
b = value & 0xFF
143-
w = 0
144-
# If all components are the same and we have a white pixel then use it
145-
# instead of the individual components.
146-
if self.bpp == 4 and r == g and g == b:
147-
w = r
148-
r = 0
149-
g = 0
150-
b = 0
151-
elif (len(value) == self.bpp) or ((len(value) == 3) and (self.bpp == 4)):
152-
if len(value) == 3:
153-
r, g, b = value
154-
else:
155-
r, g, b, w = value
156-
else:
157-
raise ValueError("Color tuple size does not match pixel_order.")
158-
159-
self.buf[offset + self.order[0]] = r
160-
self.buf[offset + self.order[1]] = g
161-
self.buf[offset + self.order[2]] = b
162-
if self.bpp == 4:
163-
self.buf[offset + self.order[3]] = w
164-
165-
def __setitem__(self, index, val):
166-
if isinstance(index, slice):
167-
start, stop, step = index.indices(len(self.buf) // self.bpp)
168-
length = stop - start
169-
if step != 0:
170-
length = math.ceil(length / step)
171-
if len(val) != length:
172-
raise ValueError("Slice and input sequence size do not match.")
173-
for val_i, in_i in enumerate(range(start, stop, step)):
174-
self._set_item(in_i, val[val_i])
175-
else:
176-
self._set_item(index, val)
177-
178-
if self.auto_write:
179-
self.show()
180-
181-
def __getitem__(self, index):
182-
if isinstance(index, slice):
183-
out = []
184-
for in_i in range(*index.indices(len(self.buf) // self.bpp)):
185-
out.append(
186-
tuple(
187-
self.buf[in_i * self.bpp + self.order[i]]
188-
for i in range(self.bpp)
189-
)
190-
)
191-
return out
192-
if index < 0:
193-
index += len(self)
194-
if index >= self.n or index < 0:
195-
raise IndexError
196-
offset = index * self.bpp
197-
return tuple(self.buf[offset + self.order[i]] for i in range(self.bpp))
198-
199-
def __len__(self):
200-
return len(self.buf) // self.bpp
201-
202153
@property
203-
def brightness(self):
204-
"""Overall brightness of the pixel"""
205-
return self._brightness
206-
207-
@brightness.setter
208-
def brightness(self, brightness):
209-
# pylint: disable=attribute-defined-outside-init
210-
self._brightness = min(max(brightness, 0.0), 1.0)
211-
if self.auto_write:
212-
self.show()
213-
214-
def fill(self, color):
215-
"""Colors all pixels the given ***color***."""
216-
auto_write = self.auto_write
217-
self.auto_write = False
218-
for i, _ in enumerate(self):
219-
self[i] = color
220-
if auto_write:
221-
self.show()
222-
self.auto_write = auto_write
154+
def n(self):
155+
"""
156+
The number of neopixels in the chain (read-only)
157+
"""
158+
return len(self)
223159

224160
def write(self):
225161
""".. deprecated: 1.0.0
226162
227163
Use ``show`` instead. It matches Micro:Bit and Arduino APIs."""
228164
self.show()
229165

230-
def show(self):
231-
"""Shows the new colors on the pixels themselves if they haven't already
232-
been autowritten.
233-
234-
The colors may or may not be showing after this function returns because
235-
it may be done asynchronously."""
236-
if self.brightness > 0.99:
237-
neopixel_write(self.pin, self.buf)
238-
else:
239-
neopixel_write(
240-
self.pin, bytearray([int(i * self.brightness) for i in self.buf])
241-
)
166+
def _transmit(self, buffer):
167+
neopixel_write(self.pin, buffer)

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
Adafruit-Blinka
2+
adafruit-circuitpython-pypixelbuf

0 commit comments

Comments
 (0)