2
2
#
3
3
# Copyright (c) 2016 Damien P. George
4
4
# Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
5
+ # Copyright (c) 2019 Carter Nelson
6
+ # Copyright (c) 2019 Roy Hooper
5
7
#
6
8
# Permission is hereby granted, free of charge, to any person obtaining a copy
7
9
# of this software and associated documentation files (the "Software"), to deal
25
27
`neopixel` - NeoPixel strip driver
26
28
====================================================
27
29
28
- * Author(s): Damien P. George & Scott Shawcroft
30
+ * Author(s): Damien P. George, Scott Shawcroft, Carter Nelson, Roy Hooper
29
31
"""
30
32
31
- import math
32
-
33
33
import digitalio
34
34
from neopixel_write import neopixel_write
35
+ try :
36
+ import _pixelbuf
37
+ except ImportError :
38
+ import adafruit_pypixelbuf as _pixelbuf
39
+
35
40
36
41
__version__ = "0.0.0-auto.0"
37
42
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_NeoPixel.git"
38
43
44
+
39
45
# Pixel color order constants
40
- RGB = ( 0 , 1 , 2 )
46
+ RGB = 'RGB'
41
47
"""Red Green Blue"""
42
- GRB = ( 1 , 0 , 2 )
48
+ GRB = 'GRB'
43
49
"""Green Red Blue"""
44
- RGBW = ( 0 , 1 , 2 , 3 )
50
+ RGBW = 'RGBW'
45
51
"""Red Green Blue White"""
46
- GRBW = ( 1 , 0 , 2 , 3 )
52
+ GRBW = 'GRBW'
47
53
"""Green Red Blue White"""
48
54
49
- class NeoPixel :
55
+
56
+ class NeoPixel (_pixelbuf .PixelBuf ):
50
57
"""
51
58
A sequence of neopixels.
52
59
@@ -57,7 +64,7 @@ class NeoPixel:
57
64
brightness
58
65
:param bool auto_write: True if the neopixels should immediately change when set. If False,
59
66
`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.
61
68
62
69
Example for Circuit Playground Express:
63
70
@@ -87,28 +94,37 @@ class NeoPixel:
87
94
pixels[::2] = [RED] * (len(pixels) // 2)
88
95
time.sleep(2)
89
96
"""
97
+ bpp = None
98
+ n = 0
99
+
90
100
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
93
102
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
97
106
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
106
123
107
124
def deinit (self ):
108
125
"""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 ()
112
128
self .pin .deinit ()
113
129
114
130
def __enter__ (self ):
@@ -120,100 +136,6 @@ def __exit__(self, exception_type, exception_value, traceback):
120
136
def __repr__ (self ):
121
137
return "[" + ", " .join ([str (x ) for x in self ]) + "]"
122
138
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
-
217
139
def write (self ):
218
140
""".. deprecated: 1.0.0
219
141
@@ -226,7 +148,8 @@ def show(self):
226
148
227
149
The colors may or may not be showing after this function returns because
228
150
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