Skip to content

Commit 968a7be

Browse files
committed
simplify and clean up pixelmap, add ability to use pixel numbers without a list wrapping them
1 parent baa8095 commit 968a7be

File tree

3 files changed

+64
-101
lines changed

3 files changed

+64
-101
lines changed

adafruit_led_animation/animation/pulse.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,16 +74,11 @@ def reset(self):
7474
"""
7575
Resets the animation.
7676
"""
77-
white = len(self.pixel_object[0]) > 3 and isinstance(
78-
self.pixel_object[0][-1], int
79-
)
8077
dotstar = len(self.pixel_object[0]) == 4 and isinstance(
8178
self.pixel_object[0][-1], float
8279
)
8380
from adafruit_led_animation.helper import ( # pylint: disable=import-outside-toplevel
8481
pulse_generator,
8582
)
8683

87-
self._generator = pulse_generator(
88-
self._period, self, white, dotstar_pwm=dotstar
89-
)
84+
self._generator = pulse_generator(self._period, self, dotstar_pwm=dotstar)

adafruit_led_animation/animation/sparklepulse.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,11 @@ def __init__(
7474
self._max_intensity = max_intensity
7575
self._min_intensity = min_intensity
7676
self._period = period
77-
white = len(pixel_object) == 4 and isinstance(pixel_object[0][-1], int)
7877
dotstar = len(pixel_object) == 4 and isinstance(pixel_object[0][-1], float)
7978
super().__init__(
8079
pixel_object, speed=speed, color=color, num_sparkles=1, name=name
8180
)
82-
self._generator = pulse_generator(
83-
self._period, self, white, dotstar_pwm=dotstar
84-
)
81+
self._generator = pulse_generator(self._period, self, dotstar_pwm=dotstar)
8582

8683
def draw(self):
8784
self._sparkle_color = next(self._generator)

adafruit_led_animation/helper.py

Lines changed: 62 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import math
4646

4747
from . import NANOS_PER_SECOND, monotonic_ns
48+
from .color import calculate_intensity
4849

4950

5051
class PixelMap:
@@ -69,7 +70,7 @@ class PixelMap:
6970
pixel_wing_horizontal[0] = (255, 255, 0)
7071
pixel_wing_horizontal.show()
7172
72-
To use with individual pixels:
73+
To use with groups of individual pixels:
7374
7475
.. code-block:: python
7576
@@ -92,24 +93,59 @@ class PixelMap:
9293
pixel_wing_vertical[0] = (255, 255, 0)
9394
pixel_wing_vertical.show()
9495
96+
To use with individual pixels:
97+
98+
.. code-block:: python
99+
100+
import board
101+
import neopixel
102+
import time
103+
from adafruit_led_animation.helper import PixelMap
104+
105+
pixels = neopixel.NeoPixel(board.D6, 8, auto_write=False)
106+
107+
pixel_map = PixelMap(pixels, [
108+
0, 7, 1, 6, 2, 5, 3, 4
109+
], individual_pixels=True)
110+
111+
n = 0
112+
while True:
113+
pixel_map[n] = AMBER
114+
pixel_map.show()
115+
n = n + 1
116+
if n > 7:
117+
n = 0
118+
pixel_map.fill(0)
119+
time.sleep(0.25)
120+
121+
95122
"""
96123

97124
def __init__(self, strip, pixel_ranges, individual_pixels=False):
98125
self._pixels = strip
99126
self._ranges = pixel_ranges
127+
100128
self.n = len(self._ranges)
129+
if self.n == 0:
130+
raise (ValueError("A PixelMap must have at least one pixel defined"))
101131
self._individual_pixels = individual_pixels
132+
self._expand_ranges()
133+
134+
def _expand_ranges(self):
135+
if not self._individual_pixels:
136+
self._ranges = [
137+
[n for n in range(start, end)] for start, end in self._ranges
138+
]
139+
return
140+
if isinstance(self._ranges[0], int):
141+
self._ranges = [[n] for n in self._ranges]
102142

103143
def __repr__(self):
104-
return "[" + ", ".join([str(x) for x in self]) + "]"
144+
return "[" + ", ".join([str(self[x]) for x in range(self.n)]) + "]"
105145

106146
def _set_pixels(self, index, val):
107-
if self._individual_pixels:
108-
for pixel in self._ranges[index]:
109-
self._pixels[pixel] = val
110-
else:
111-
range_start, range_stop = self._ranges[index]
112-
self._pixels[range_start:range_stop] = [val] * (range_stop - range_start)
147+
for pixel in self._ranges[index]:
148+
self._pixels[pixel] = val
113149

114150
def __setitem__(self, index, val):
115151
if isinstance(index, slice):
@@ -124,7 +160,7 @@ def __setitem__(self, index, val):
124160
else:
125161
self._set_pixels(index, val)
126162

127-
if not self._pixels.auto_write:
163+
if self._pixels.auto_write:
128164
self.show()
129165

130166
def __getitem__(self, index):
@@ -160,13 +196,9 @@ def fill(self, color):
160196
161197
:param color: Color to fill all pixels referenced by this PixelMap definition with.
162198
"""
163-
if self._individual_pixels:
164-
for pixels in self._ranges:
165-
for pixel in pixels:
166-
self._pixels[pixel] = color
167-
else:
168-
for start, stop in self._ranges:
169-
self._pixels[start:stop] = [color] * (stop - start)
199+
for pixels in self._ranges:
200+
for pixel in pixels:
201+
self._pixels[pixel] = color
170202

171203
def show(self):
172204
"""
@@ -273,7 +305,7 @@ def mapper(x, y):
273305
return mapper
274306

275307

276-
class PixelSubset:
308+
class PixelSubset(PixelMap):
277309
"""
278310
PixelSubset lets you work with a subset of a pixel object.
279311
@@ -295,78 +327,18 @@ class PixelSubset:
295327
"""
296328

297329
def __init__(self, pixel_object, start, end):
298-
self._pixels = pixel_object
299-
self._start = start
300-
self._end = end
301-
self.n = self._end - self._start
302-
303-
def __repr__(self):
304-
return "[" + ", ".join([str(x) for x in self]) + "]"
305-
306-
def __setitem__(self, index, val):
307-
if isinstance(index, slice):
308-
start, stop, step = index.indices(self.n)
309-
self._pixels[start + self._start : stop + self._start : step] = val
310-
else:
311-
self._pixels[index + self._start] = val
312-
313-
if not self._pixels.auto_write:
314-
self.show()
315-
316-
def __getitem__(self, index):
317-
if isinstance(index, slice):
318-
start, stop, step = index.indices(self.n)
319-
return self._pixels[start + self._start : stop + self._start : step]
320-
if index < 0:
321-
index += len(self)
322-
if index >= self.n or index < 0:
323-
raise IndexError
324-
return self._pixels[index]
325-
326-
def __len__(self):
327-
return self.n
328-
329-
@property
330-
def brightness(self):
331-
"""
332-
brightness from the underlying strip.
333-
"""
334-
return self._pixels.brightness
335-
336-
@brightness.setter
337-
def brightness(self, brightness):
338-
self._pixels.brightness = min(max(brightness, 0.0), 1.0)
339-
340-
def fill(self, color):
341-
"""
342-
Fill the used pixel ranges with color.
343-
"""
344-
self._pixels[self._start : self._end] = [color] * (self.n)
345-
346-
def show(self):
347-
"""
348-
Shows the pixels on the underlying strip.
349-
"""
350-
self._pixels.show()
351-
352-
@property
353-
def auto_write(self):
354-
"""
355-
auto_write from the underlying strip.
356-
"""
357-
return self._pixels.auto_write
358-
359-
@auto_write.setter
360-
def auto_write(self, value):
361-
self._pixels.auto_write = value
330+
super().__init__(
331+
pixel_object,
332+
pixel_ranges=[[n] for n in range(start, end)],
333+
individual_pixels=True,
334+
)
362335

363336

364-
def pulse_generator(period: float, animation_object, white=False, dotstar_pwm=False):
337+
def pulse_generator(period: float, animation_object, dotstar_pwm=False):
365338
"""
366339
Generates a sequence of colors for a pulse, based on the time period specified.
367340
:param period: Pulse duration in seconds.
368341
:param animation_object: An animation object to interact with.
369-
:param white: Whether the pixel strip has a white pixel.
370342
:param dotstar_pwm: Whether to use the dostar per pixel PWM value for brightness control.
371343
"""
372344
period = int(period * NANOS_PER_SECOND)
@@ -376,7 +348,6 @@ def pulse_generator(period: float, animation_object, white=False, dotstar_pwm=Fa
376348
cycle_position = 0
377349
last_pos = 0
378350
while True:
379-
fill_color = list(animation_object.color)
380351
now = monotonic_ns()
381352
time_since_last_draw = now - last_update
382353
last_update = now
@@ -388,12 +359,12 @@ def pulse_generator(period: float, animation_object, white=False, dotstar_pwm=Fa
388359
pos = period - pos
389360
intensity = pos / half_period
390361
if dotstar_pwm:
391-
fill_color = (fill_color[0], fill_color[1], fill_color[2], intensity)
362+
fill_color = (
363+
animation_object.color[0],
364+
animation_object.color[1],
365+
animation_object.color[2],
366+
intensity,
367+
)
392368
yield fill_color
393369
continue
394-
if white and len(fill_color) == 4:
395-
fill_color[3] = int(fill_color[3] * intensity)
396-
fill_color[0] = int(fill_color[0] * intensity)
397-
fill_color[1] = int(fill_color[1] * intensity)
398-
fill_color[2] = int(fill_color[2] * intensity)
399-
yield fill_color
370+
yield calculate_intensity(animation_object.color, intensity)

0 commit comments

Comments
 (0)