30
30
31
31
import math
32
32
33
- import digitalio
34
- from neopixel_write import neopixel_write
33
+ try :
34
+ # imports needed for main NeoPixel class
35
+ import digitalio
36
+ from neopixel_write import neopixel_write
37
+ except :
38
+ # silently accept this, can still use NeoPixel SPI class
39
+ pass
35
40
36
41
__version__ = "0.0.0-auto.0"
37
42
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_NeoPixel.git"
@@ -230,3 +235,82 @@ def show(self):
230
235
neopixel_write (self .pin , self .buf )
231
236
else :
232
237
neopixel_write (self .pin , bytearray ([int (i * self .brightness ) for i in self .buf ]))
238
+
239
+ class NeoPixel_SPI (NeoPixel ):
240
+ """
241
+ A sequence of neopixels.
242
+
243
+ :param ~busio.SPI spi: The SPI bus to output neopixel data on.
244
+ :param int n: The number of neopixels in the chain
245
+ :param int bpp: Bytes per pixel. 3 for RGB and 4 for RGBW pixels.
246
+ :param float brightness: Brightness of the pixels between 0.0 and 1.0 where 1.0 is full
247
+ brightness
248
+ :param bool auto_write: True if the neopixels should immediately change when set. If False,
249
+ `show` must be called explicitly.
250
+ :param tuple pixel_order: Set the pixel color channel order. GRBW is set by default.
251
+
252
+ Example:
253
+
254
+ .. code-block:: python
255
+
256
+ import board
257
+ import neopixel
258
+
259
+ pixels = neopixel.NeoPixel_SPI(board.SPI(), 10)
260
+ pixels.fill(0xff0000)
261
+ """
262
+ #pylint: disable=invalid-name
263
+
264
+ FREQ = 6400000 # 800kHz * 8, actual may be different
265
+ TRST = 80e-6 # Reset code low level time
266
+
267
+ def __init__ (self , spi , n , * , bpp = 3 , brightness = 1.0 , auto_write = True , pixel_order = None ):
268
+ from adafruit_bus_device .spi_device import SPIDevice
269
+ self ._spi = SPIDevice (spi , baudrate = self .FREQ )
270
+ with self ._spi as spi :
271
+ try :
272
+ # get actual SPI frequency
273
+ freq = spi .frequency
274
+ except AttributeError :
275
+ # use nominal
276
+ freq = self .FREQ
277
+ self .RESET = bytes ([0 ]* round (freq * self .TRST ))
278
+ self .n = n
279
+ if pixel_order is None :
280
+ self .order = GRBW
281
+ self .bpp = bpp
282
+ else :
283
+ self .order = pixel_order
284
+ self .bpp = len (self .order )
285
+ self .buf = bytearray (self .n * self .bpp )
286
+ # Set auto_write to False temporarily so brightness setter does _not_
287
+ # call show() while in __init__.
288
+ self .auto_write = False
289
+ self .brightness = brightness
290
+ self .auto_write = auto_write
291
+
292
+ def deinit (self ):
293
+ """Blank out the NeoPixels."""
294
+ for i in range (len (self .buf )):
295
+ self .buf [i ] = 0
296
+ self .show ()
297
+
298
+ def show (self ):
299
+ """Shows the new colors on the pixels themselves if they haven't already
300
+ been autowritten."""
301
+ with self ._spi as spi :
302
+ # write out special byte sequence surrounded by RESET
303
+ # leading RESET needed for cases where MOSI rests HI
304
+ spi .write (self .RESET + self ._transmogrify (self .buf ) + self .RESET )
305
+
306
+ def _transmogrify (self , buf ):
307
+ """Turn every BIT of buf into a special BYTE pattern."""
308
+ out_buf = bytearray ()
309
+ for byte in self .buf :
310
+ # MSB first
311
+ for i in range (7 , - 1 , - 1 ):
312
+ if byte >> i & 0x01 :
313
+ out_buf .append (0b11110000 ) # A NeoPixel 1 bit
314
+ else :
315
+ out_buf .append (0b11000000 ) # A NeoPixel 0 bit
316
+ return out_buf
0 commit comments