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
+ # pylint: disable=ungrouped-imports
34
+ import sys
33
35
import digitalio
34
36
from neopixel_write import neopixel_write
35
37
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
+
36
47
__version__ = "0.0.0-auto.0"
37
48
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_NeoPixel.git"
38
49
50
+
39
51
# Pixel color order constants
40
- RGB = ( 0 , 1 , 2 )
52
+ RGB = "RGB"
41
53
"""Red Green Blue"""
42
- GRB = ( 1 , 0 , 2 )
54
+ GRB = "GRB"
43
55
"""Green Red Blue"""
44
- RGBW = ( 0 , 1 , 2 , 3 )
56
+ RGBW = "RGBW"
45
57
"""Red Green Blue White"""
46
- GRBW = ( 1 , 0 , 2 , 3 )
58
+ GRBW = "GRBW"
47
59
"""Green Red Blue White"""
48
60
49
61
50
- class NeoPixel :
62
+ class NeoPixel ( _pixelbuf . PixelBuf ) :
51
63
"""
52
64
A sequence of neopixels.
53
65
@@ -58,7 +70,7 @@ class NeoPixel:
58
70
brightness
59
71
:param bool auto_write: True if the neopixels should immediately change when set. If False,
60
72
`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.
62
74
63
75
Example for Circuit Playground Express:
64
76
@@ -87,32 +99,46 @@ class NeoPixel:
87
99
with neopixel.NeoPixel(NEOPIXEL, 10) as pixels:
88
100
pixels[::2] = [RED] * (len(pixels) // 2)
89
101
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
+
90
119
"""
91
120
92
121
def __init__ (
93
122
self , pin , n , * , bpp = 3 , brightness = 1.0 , auto_write = True , pixel_order = None
94
123
):
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
+
95
135
self .pin = digitalio .DigitalInOut (pin )
96
136
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
110
137
111
138
def deinit (self ):
112
139
"""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 ()
116
142
self .pin .deinit ()
117
143
118
144
def __enter__ (self ):
@@ -124,118 +150,18 @@ def __exit__(self, exception_type, exception_value, traceback):
124
150
def __repr__ (self ):
125
151
return "[" + ", " .join ([str (x ) for x in self ]) + "]"
126
152
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
-
202
153
@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 )
223
159
224
160
def write (self ):
225
161
""".. deprecated: 1.0.0
226
162
227
163
Use ``show`` instead. It matches Micro:Bit and Arduino APIs."""
228
164
self .show ()
229
165
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