Skip to content

Commit 76a1b5d

Browse files
authored
Merge pull request #4 from adafruit/enhancements
Support any number of strands from 1 to 8; make demo more like arduino demo
2 parents ade06ed + 674782f commit 76a1b5d

File tree

2 files changed

+66
-32
lines changed

2 files changed

+66
-32
lines changed

adafruit_neopxl8.py

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
bitloop:
3333
pull ifempty [1] ; don't start outputting HIGH unless data is available (always-low part)
3434
mov pins, ~ null [3] ; always-high part
35-
out pins, 8 [4] ; variable part
35+
{} ; variable part
3636
mov pins, null ; always-low part (last cycle is the 'pull ifempty' after wrap)
3737
3838
jmp y--, bitloop ; always-low part
@@ -46,7 +46,6 @@
4646
jmp top
4747
"""
4848

49-
_ASSEMBLED = adafruit_pioasm.assemble(_PROGRAM)
5049

5150
# Pixel color order constants
5251
RGB = "RGB"
@@ -110,7 +109,7 @@ def __init__(
110109
brightness=1.0,
111110
auto_write=True,
112111
pixel_order=None,
113-
):
112+
): # pylint: disable=too-many-locals
114113
if n % num_strands:
115114
raise ValueError("Length must be a multiple of num_strands")
116115
if not pixel_order:
@@ -124,25 +123,48 @@ def __init__(
124123
n, brightness=brightness, byteorder=pixel_order, auto_write=auto_write
125124
)
126125

127-
data_len = bpp * n * 8 // num_strands
126+
if num_strands == 1:
127+
data_len = bpp * n
128+
pack = ">L"
129+
osr = False
130+
loop_count = 8 * data_len
131+
else:
132+
data_len = bpp * n * 8 // num_strands
133+
pack = "<L"
134+
osr = True
135+
loop_count = data_len
128136
padding_count = -data_len % 4
129137

138+
self._num_strands = num_strands
130139
self._data = bytearray(8 + data_len + padding_count)
131140
self._data32 = memoryview(self._data).cast("L")
132-
self._transposed = memoryview(self._data)[4 : 4 + data_len]
133-
self._data[:4] = struct.pack("<L", data_len - 1)
134-
self._data[-4:] = struct.pack("<L", 3840 * 2)
141+
self._pixels = memoryview(self._data)[4 : 4 + data_len]
142+
self._data[:4] = struct.pack(pack, loop_count - 1)
143+
self._data[-4:] = struct.pack(pack, 3840)
135144

136145
self._num_strands = num_strands
137146

147+
if num_strands == 8:
148+
variable_part = "out pins, 8 [4] ; variable part"
149+
elif num_strands == 1:
150+
variable_part = "out pins, 1 [4] ; variable part"
151+
else:
152+
variable_part = f"""
153+
out pins, {num_strands} [3] ; variable part
154+
out x, {8-num_strands} ; variable part
155+
"""
156+
157+
program = _PROGRAM.format(variable_part)
158+
assembled = adafruit_pioasm.assemble(program)
159+
138160
self._sm = rp2pio.StateMachine(
139-
_ASSEMBLED,
161+
assembled,
140162
frequency=800_000 * 16,
141163
first_out_pin=data0,
142-
out_pin_count=8,
164+
out_pin_count=num_strands,
143165
first_set_pin=data0,
144166
auto_pull=False,
145-
out_shift_right=True,
167+
out_shift_right=osr,
146168
)
147169

148170
def deinit(self):
@@ -177,5 +199,9 @@ def num_strands(self):
177199
def _transmit(self, buffer):
178200
while self._sm.pending:
179201
pass
180-
bitops.bit_transpose(buffer, self._transposed, self._num_strands)
181-
self._sm.background_write(self._data32)
202+
if self.num_strands == 1:
203+
self._pixels[:] = buffer
204+
self._sm.background_write(self._data32, swap=True)
205+
else:
206+
bitops.bit_transpose(buffer, self._pixels, self._num_strands)
207+
self._sm.background_write(self._data32)

examples/neopxl8_animations.py

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,12 @@
22
#
33
# SPDX-License-Identifier: Unlicense
44

5-
# Set up a separate animation on each of 8 strips with NeoPxl8
6-
75
import board
8-
from adafruit_led_animation.animation.rainbow import Rainbow
6+
import rainbowio
7+
import adafruit_ticks
98
from adafruit_led_animation.animation.comet import Comet
10-
from adafruit_led_animation.animation.rainbowcomet import RainbowComet
11-
from adafruit_led_animation.animation.rainbowchase import RainbowChase
12-
from adafruit_led_animation.animation.chase import Chase
139
from adafruit_led_animation.group import AnimationGroup
1410
from adafruit_led_animation.helper import PixelMap
15-
from adafruit_led_animation import color
1611
from adafruit_neopxl8 import NeoPxl8
1712

1813
# Customize for your strands here
@@ -28,30 +23,43 @@
2823
num_pixels,
2924
num_strands=num_strands,
3025
auto_write=False,
31-
brightness=0.07,
26+
brightness=0.50,
3227
)
3328

3429

35-
def strand(i):
30+
def strand(n):
3631
return PixelMap(
3732
pixels,
38-
range(i * strand_length, (i + 1) * strand_length),
33+
range(n * strand_length, (n + 1) * strand_length),
3934
individual_pixels=True,
4035
)
4136

4237

38+
# Create the 8 virtual strands
4339
strands = [strand(i) for i in range(num_strands)]
4440

45-
animations = AnimationGroup(
46-
Comet(strands[0], 0.5, color.CYAN),
47-
Comet(strands[1], 0.4, color.AMBER),
48-
RainbowComet(strands[2], 0.3),
49-
RainbowComet(strands[3], 0.7),
50-
Chase(strands[4], 0.05, size=2, spacing=3, color=color.PURPLE),
51-
RainbowChase(strands[5], 0.05, size=2, spacing=3),
52-
Rainbow(strands[6], 0.6),
53-
Rainbow(strands[7], 0.23, step=21),
54-
)
41+
# For each strand, create a comet animation of a different color
42+
animations = [
43+
Comet(strand, 0.02, rainbowio.colorwheel(3 * 32 * i), ring=True)
44+
for i, strand in enumerate(strands)
45+
]
46+
47+
# Advance the animations by varying amounts so that they become staggered
48+
for i, animation in enumerate(animations):
49+
animation._tail_start = 30 * 5 * i // 8 # pylint: disable=protected-access
50+
51+
# Group them so we can run them all at once
52+
animations = AnimationGroup(*animations)
5553

54+
# Run the animations and report on the speed in frame per secodn
55+
t0 = adafruit_ticks.ticks_ms()
56+
frame_count = 0
5657
while True:
5758
animations.animate()
59+
frame_count += 1
60+
t1 = adafruit_ticks.ticks_ms()
61+
dt = adafruit_ticks.ticks_diff(t1, t0)
62+
if dt > 1000:
63+
print(f"{frame_count * 1000/dt:.1f}fps")
64+
t0 = t1
65+
frame_count = 0

0 commit comments

Comments
 (0)