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
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
3335import digitalio
3436from 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 )
0 commit comments