Skip to content

Commit dd60236

Browse files
committed
Add NeoPixel_SPI from master
1 parent b0cb16e commit dd60236

File tree

1 file changed

+71
-3
lines changed

1 file changed

+71
-3
lines changed

neopixel.py

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,11 @@ class NeoPixel(_pixelbuf.PixelBuf):
103103
time.sleep(2)
104104
"""
105105
def __init__(self, pin, n, *, bpp=3, brightness=1.0, auto_write=True, pixel_order=None):
106+
self._configure(n, bpp, brightness, auto_write, pixel_order)
107+
self.pin = digitalio.DigitalInOut(pin)
108+
self.pin.direction = digitalio.Direction.OUTPUT
109+
110+
def _configure(self, n, bpp=3, brightness=1.0, auto_write=True, pixel_order=None):
106111
self.bpp = bpp
107112
self.n = n
108113
if not pixel_order:
@@ -122,9 +127,6 @@ def __init__(self, pin, n, *, bpp=3, brightness=1.0, auto_write=True, pixel_orde
122127
byteorder=pixel_order,
123128
auto_write=auto_write)
124129

125-
self.pin = digitalio.DigitalInOut(pin)
126-
self.pin.direction = digitalio.Direction.OUTPUT
127-
128130
def deinit(self):
129131
"""Blank out the NeoPixels and release the pin."""
130132
self.fill(0)
@@ -153,3 +155,69 @@ def show(self):
153155
The colors may or may not be showing after this function returns because
154156
it may be done asynchronously."""
155157
neopixel_write(self.pin, self.buf)
158+
159+
160+
class NeoPixel_SPI(NeoPixel):
161+
"""
162+
A sequence of neopixels.
163+
164+
:param ~busio.SPI spi: The SPI bus to output neopixel data on.
165+
:param int n: The number of neopixels in the chain
166+
:param int bpp: Bytes per pixel. 3 for RGB and 4 for RGBW pixels.
167+
:param float brightness: Brightness of the pixels between 0.0 and 1.0 where 1.0 is full
168+
brightness
169+
:param bool auto_write: True if the neopixels should immediately change when set. If False,
170+
`show` must be called explicitly.
171+
:param tuple pixel_order: Set the pixel color channel order. GRBW is set by default.
172+
173+
Example:
174+
175+
.. code-block:: python
176+
177+
import board
178+
import neopixel
179+
180+
pixels = neopixel.NeoPixel_SPI(board.SPI(), 10)
181+
pixels.fill(0xff0000)
182+
"""
183+
#pylint: disable=invalid-name, super-init-not-called
184+
185+
FREQ = 6400000 # 800kHz * 8, actual may be different
186+
TRST = 80e-6 # Reset code low level time
187+
188+
def __init__(self, spi, n, *, bpp=3, brightness=1.0, auto_write=True, pixel_order=None):
189+
self._configure(n, bpp, brightness, auto_write, pixel_order)
190+
191+
from adafruit_bus_device.spi_device import SPIDevice
192+
self._spi = SPIDevice(spi, baudrate=self.FREQ)
193+
with self._spi as spibus:
194+
try:
195+
# get actual SPI frequency
196+
freq = spibus.frequency
197+
except AttributeError:
198+
# use nominal
199+
freq = self.FREQ
200+
self.RESET = bytes([0]*round(freq*self.TRST))
201+
self.spibuf = bytearray(8*len(self.buf))
202+
203+
def show(self):
204+
"""Shows the new colors on the pixels themselves if they haven't already
205+
been autowritten."""
206+
self._transmogrify()
207+
with self._spi as spi:
208+
# write out special byte sequence surrounded by RESET
209+
# leading RESET needed for cases where MOSI rests HI
210+
spi.write(self.RESET + self.spibuf + self.RESET)
211+
212+
def _transmogrify(self):
213+
"""Turn every BIT of buf into a special BYTE pattern."""
214+
k = 0
215+
for byte in self.buf:
216+
byte = int(byte * self.brightness)
217+
# MSB first
218+
for i in range(7, -1, -1):
219+
if byte >> i & 0x01:
220+
self.spibuf[k] = 0b11110000 # A NeoPixel 1 bit
221+
else:
222+
self.spibuf[k] = 0b11000000 # A NeoPixel 0 bit
223+
k += 1

0 commit comments

Comments
 (0)