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-
3333import digitalio
3434from neopixel_write import neopixel_write
35+ try :
36+ import _pixelbuf
37+ except ImportError :
38+ import adafruit_pypixelbuf as _pixelbuf
39+
3540
3641__version__ = "0.0.0-auto.0"
3742__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_NeoPixel.git"
3843
44+
3945# Pixel color order constants
40- RGB = ( 0 , 1 , 2 )
46+ RGB = 'RGB'
4147"""Red Green Blue"""
42- GRB = ( 1 , 0 , 2 )
48+ GRB = 'GRB'
4349"""Green Red Blue"""
44- RGBW = ( 0 , 1 , 2 , 3 )
50+ RGBW = 'RGBW'
4551"""Red Green Blue White"""
46- GRBW = ( 1 , 0 , 2 , 3 )
52+ GRBW = 'GRBW'
4753"""Green Red Blue White"""
4854
49- class NeoPixel :
55+
56+ class NeoPixel (_pixelbuf .PixelBuf ):
5057 """
5158 A sequence of neopixels.
5259
@@ -57,7 +64,7 @@ class NeoPixel:
5764 brightness
5865 :param bool auto_write: True if the neopixels should immediately change when set. If False,
5966 `show` must be called explicitly.
60- :param tuple pixel_order : Set the pixel color channel order. GRBW is set by default.
67+ :param str : Set the pixel color channel order. GRBW is set by default.
6168
6269 Example for Circuit Playground Express:
6370
@@ -87,28 +94,37 @@ class NeoPixel:
8794 pixels[::2] = [RED] * (len(pixels) // 2)
8895 time.sleep(2)
8996 """
97+ bpp = None
98+ n = 0
99+
90100 def __init__ (self , pin , n , * , bpp = 3 , brightness = 1.0 , auto_write = True , pixel_order = None ):
91- self .pin = digitalio .DigitalInOut (pin )
92- self .pin .direction = digitalio .Direction .OUTPUT
101+ self .bpp = bpp
93102 self .n = n
94- if pixel_order is None :
95- self . order = GRBW
96- self . bpp = bpp
103+
104+ if not pixel_order :
105+ pixel_order = GRB if bpp == 3 else GRBW
97106 else :
98- self .order = pixel_order
99- self .bpp = len (self .order )
100- self .buf = bytearray (self .n * self .bpp )
101- # Set auto_write to False temporarily so brightness setter does _not_
102- # call show() while in __init__.
103- self .auto_write = False
104- self .brightness = brightness
105- self .auto_write = auto_write
107+ self .bpp = bpp = len (pixel_order )
108+ if isinstance (pixel_order , tuple ):
109+ order_chars = RGBW
110+ order = []
111+ for char_no , order in enumerate (pixel_order ):
112+ order [pixel_order ] = order_chars [char_no ]
113+ pixel_order = '' .join (order )
114+
115+ super ().__init__ (n , bytearray (self .n * bpp ),
116+ brightness = brightness ,
117+ rawbuf = bytearray (self .n * bpp ),
118+ byteorder = pixel_order ,
119+ auto_write = auto_write )
120+
121+ self .pin = digitalio .DigitalInOut (pin )
122+ self .pin .direction = digitalio .Direction .OUTPUT
106123
107124 def deinit (self ):
108125 """Blank out the NeoPixels and release the pin."""
109- for i in range (len (self .buf )):
110- self .buf [i ] = 0
111- neopixel_write (self .pin , self .buf )
126+ self .fill (0 )
127+ self .show ()
112128 self .pin .deinit ()
113129
114130 def __enter__ (self ):
@@ -120,100 +136,6 @@ def __exit__(self, exception_type, exception_value, traceback):
120136 def __repr__ (self ):
121137 return "[" + ", " .join ([str (x ) for x in self ]) + "]"
122138
123- def _set_item (self , index , value ):
124- if index < 0 :
125- index += len (self )
126- if index >= self .n or index < 0 :
127- raise IndexError
128- offset = index * self .bpp
129- r = 0
130- g = 0
131- b = 0
132- w = 0
133- if isinstance (value , int ):
134- if value >> 24 :
135- raise ValueError ("only bits 0->23 valid for integer input" )
136- r = value >> 16
137- g = (value >> 8 ) & 0xff
138- b = value & 0xff
139- w = 0
140- # If all components are the same and we have a white pixel then use it
141- # instead of the individual components.
142- if self .bpp == 4 and r == g and g == b :
143- w = r
144- r = 0
145- g = 0
146- b = 0
147- elif (len (value ) == self .bpp ) or ((len (value ) == 3 ) and (self .bpp == 4 )):
148- if len (value ) == 3 :
149- r , g , b = value
150- else :
151- r , g , b , w = value
152- else :
153- raise ValueError ("Color tuple size does not match pixel_order." )
154-
155- self .buf [offset + self .order [0 ]] = r
156- self .buf [offset + self .order [1 ]] = g
157- self .buf [offset + self .order [2 ]] = b
158- if self .bpp == 4 :
159- self .buf [offset + self .order [3 ]] = w
160-
161- def __setitem__ (self , index , val ):
162- if isinstance (index , slice ):
163- start , stop , step = index .indices (len (self .buf ) // self .bpp )
164- length = stop - start
165- if step != 0 :
166- length = math .ceil (length / step )
167- if len (val ) != length :
168- raise ValueError ("Slice and input sequence size do not match." )
169- for val_i , in_i in enumerate (range (start , stop , step )):
170- self ._set_item (in_i , val [val_i ])
171- else :
172- self ._set_item (index , val )
173-
174- if self .auto_write :
175- self .show ()
176-
177- def __getitem__ (self , index ):
178- if isinstance (index , slice ):
179- out = []
180- for in_i in range (* index .indices (len (self .buf ) // self .bpp )):
181- out .append (tuple (self .buf [in_i * self .bpp + self .order [i ]]
182- for i in range (self .bpp )))
183- return out
184- if index < 0 :
185- index += len (self )
186- if index >= self .n or index < 0 :
187- raise IndexError
188- offset = index * self .bpp
189- return tuple (self .buf [offset + self .order [i ]]
190- for i in range (self .bpp ))
191-
192- def __len__ (self ):
193- return len (self .buf ) // self .bpp
194-
195- @property
196- def brightness (self ):
197- """Overall brightness of the pixel"""
198- return self ._brightness
199-
200- @brightness .setter
201- def brightness (self , brightness ):
202- # pylint: disable=attribute-defined-outside-init
203- self ._brightness = min (max (brightness , 0.0 ), 1.0 )
204- if self .auto_write :
205- self .show ()
206-
207- def fill (self , color ):
208- """Colors all pixels the given ***color***."""
209- auto_write = self .auto_write
210- self .auto_write = False
211- for i , _ in enumerate (self ):
212- self [i ] = color
213- if auto_write :
214- self .show ()
215- self .auto_write = auto_write
216-
217139 def write (self ):
218140 """.. deprecated: 1.0.0
219141
@@ -226,7 +148,8 @@ def show(self):
226148
227149 The colors may or may not be showing after this function returns because
228150 it may be done asynchronously."""
229- if self .brightness > 0.99 :
230- neopixel_write (self .pin , self .buf )
231- else :
232- neopixel_write (self .pin , bytearray ([int (i * self .brightness ) for i in self .buf ]))
151+ neopixel_write (self .pin , self .buf )
152+
153+ def fill (self , color ):
154+ """Colors all pixels the given ***color***."""
155+ _pixelbuf .fill (self , color )
0 commit comments