@@ -103,6 +103,11 @@ class NeoPixel(_pixelbuf.PixelBuf):
103
103
time.sleep(2)
104
104
"""
105
105
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 ):
106
111
self .bpp = bpp
107
112
self .n = n
108
113
if not pixel_order :
@@ -122,9 +127,6 @@ def __init__(self, pin, n, *, bpp=3, brightness=1.0, auto_write=True, pixel_orde
122
127
byteorder = pixel_order ,
123
128
auto_write = auto_write )
124
129
125
- self .pin = digitalio .DigitalInOut (pin )
126
- self .pin .direction = digitalio .Direction .OUTPUT
127
-
128
130
def deinit (self ):
129
131
"""Blank out the NeoPixels and release the pin."""
130
132
self .fill (0 )
@@ -153,3 +155,69 @@ def show(self):
153
155
The colors may or may not be showing after this function returns because
154
156
it may be done asynchronously."""
155
157
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