4
4
import gc
5
5
import time
6
6
import board
7
- import neopixel
8
7
import touchio
9
- from analogio import AnalogIn
8
+ import digitalio
9
+ from neopixel_write import neopixel_write
10
10
11
11
# uncomment one line only here to select bitmap
12
12
FILENAME = "bats.bmp" # BMP file to load from flash filesystem
13
- #FILENAME = "jpw01.bmp"
14
- #FILENAME = "digikey.bmp"
15
- #FILENAME = "burger.bmp"
16
- #FILENAME = "afbanner.bmp"
17
- #FILENAME = "blinka.bmp"
18
- #FILENAME = "ghost.bmp"
19
- #FILENAME = "helix-32x30.bmp"
20
- #FILENAME = "wales2-107x30.bmp"
21
- #FILENAME = "pumpkin.bmp"
22
- #FILENAME = "rainbow.bmp"
23
- #FILENAME = "rainbowRoad.bmp"
24
- #FILENAME = "rainbowZig.bmp"
25
- #FILENAME = "skull.bmp"
26
- #FILENAME = "adabot.bmp"
27
- #FILENAME = "green_stripes.bmp"
28
- #FILENAME = "red_blue.bmp"
29
- #FILENAME = "minerva.bmp"
30
-
31
- TOUCH = touchio .TouchIn (board .A5 ) # capacitive touch pad
32
- SPEED = 50000
33
- BRIGHTNESS = 1.0 # Set brightness here, NOT in NeoPixel constructor
34
- GAMMA = 2.7 # Adjusts perceived brighthess linearity
35
- NUM_PIXELS = 30 # NeoPixel strip length (in pixels)
36
- NEOPIXEL_PIN = board .A1 # Pin where NeoPixels are connected
37
- STRIP = neopixel .NeoPixel (NEOPIXEL_PIN , NUM_PIXELS , brightness = 1 , auto_write = False )
38
- DELAY_TIME = 0.01 # Timer delay before it starts
13
+ # FILENAME = "digikey.bmp"
14
+ # FILENAME = "burger.bmp"
15
+ # FILENAME = "afbanner.bmp"
16
+ # FILENAME = "blinka.bmp"
17
+ # FILENAME = "ghost04.bmp"
18
+ # FILENAME = "ghost07.bmp"
19
+ # FILENAME = "ghost02.bmp"
20
+ # FILENAME = "helix-32x30.bmp"
21
+ # FILENAME = "wales2-107x30.bmp"
22
+ # FILENAME = "pumpkin.bmp"
23
+ # FILENAME = "rainbow.bmp"
24
+ # FILENAME = "rainbowRoad.bmp"
25
+ # FILENAME = "rainbowZig.bmp"
26
+ # FILENAME = "skull.bmp"
27
+ # FILENAME = "adabot.bmp"
28
+ # FILENAME = "green_stripes.bmp"
29
+ # FILENAME = "red_blue.bmp"
30
+ # FILENAME = "minerva.bmp"
31
+
32
+ TOUCH = touchio .TouchIn (board .A5 ) # Rightmost capacitive touch pad
33
+ BRIGHTNESS = 1.0 # NeoPixel brightness 0.0 (min) to 1.0 (max)
34
+ GAMMA = 2.7 # Adjusts perceived brighthess linearity
35
+ NUM_PIXELS = 30 # NeoPixel strip length (in pixels)
36
+ SPEED = 20000 # adjust this to change the playback speed e.g. 50000 is slow
37
+ LOOP = False # set to True for looping
38
+ # Switch off onboard NeoPixel...
39
+ NEOPIXEL_PIN = digitalio .DigitalInOut (board .NEOPIXEL )
40
+ NEOPIXEL_PIN .direction = digitalio .Direction .OUTPUT
41
+ neopixel_write (NEOPIXEL_PIN , bytearray (3 ))
42
+ # ...then assign NEOPIXEL_PIN to the external NeoPixel connector:
43
+ NEOPIXEL_PIN = digitalio .DigitalInOut (board .A1 )
44
+ NEOPIXEL_PIN .direction = digitalio .Direction .OUTPUT
45
+ neopixel_write (NEOPIXEL_PIN , bytearray (NUM_PIXELS * 3 ))
39
46
40
47
# Interpret multi-byte value from file as little-endian value
41
48
def read_le (value ):
@@ -57,11 +64,11 @@ def load_bmp(filename):
57
64
if f .read (2 ) != b'BM' : # check signature
58
65
raise BMPError ("Not BitMap file" )
59
66
60
- bmpFileSize = read_le ( f .read (4 ))
67
+ f .read (4 ) # Read & ignore file size
61
68
f .read (4 ) # Read & ignore creator bytes
62
69
63
70
bmpImageoffset = read_le (f .read (4 )) # Start of image data
64
- headerSize = read_le ( f .read (4 ))
71
+ f .read (4 ) # Read & ignore header size
65
72
bmpWidth = read_le (f .read (4 ))
66
73
bmpHeight = read_le (f .read (4 ))
67
74
# BMPs are traditionally stored bottom-to-top.
@@ -72,8 +79,6 @@ def load_bmp(filename):
72
79
bmpHeight = - bmpHeight
73
80
flip = False
74
81
75
- # print("Size: %d\nImage offset: %d\nHeader size: %d" %
76
- # (bmpFileSize, bmpImageoffset, headerSize))
77
82
print ("WxH: (%d,%d)" % (bmpWidth , bmpHeight ))
78
83
79
84
if read_le (f .read (2 )) != 1 :
@@ -95,7 +100,7 @@ def load_bmp(filename):
95
100
clippedHeight = NUM_PIXELS
96
101
97
102
# Allocate per-column pixel buffers, sized for NeoPixel strip:
98
- columns = [bytearray (NUM_PIXELS * STRIP . bpp ) for i in range (bmpWidth )]
103
+ columns = [bytearray (NUM_PIXELS * 3 ) for i in range (bmpWidth )]
99
104
100
105
# Image is displayed at END (not start) of NeoPixel strip,
101
106
# this index works incrementally backward in column buffers...
@@ -105,22 +110,22 @@ def load_bmp(filename):
105
110
pos = bmpImageoffset + (bmpHeight - 1 - row ) * rowSize
106
111
else : # Bitmap is stored top-to-bottom
107
112
pos = bmpImageoffset + row * rowSize
108
- f .seek (pos ) # Start of scanline
113
+ f .seek (pos ) # Start of scanline
109
114
for c in columns : # For each pixel of scanline...
110
115
# BMP files use BGR color order
111
116
# blue, green, red = bytearray(f.read(3))
112
117
blue , green , red = f .read (3 )
113
118
# Rearrange into NeoPixel strip's color order,
114
119
# while handling brightness & gamma correction:
115
- c [idx + STRIP . order [ 0 ]] = int (pow (red / 255 , GAMMA ) * BRIGHTNESS * 255 + 0.5 )
116
- c [idx + STRIP . order [ 1 ]] = int (pow (green / 255 , GAMMA ) * BRIGHTNESS * 255 + 0.5 )
117
- c [idx + STRIP . order [ 2 ] ] = int (pow (blue / 255 , GAMMA ) * BRIGHTNESS * 255 + 0.5 )
120
+ c [idx ] = int (pow (green / 255 , GAMMA ) * BRIGHTNESS * 255 + 0.5 )
121
+ c [idx + 1 ] = int (pow (red / 255 , GAMMA ) * BRIGHTNESS * 255 + 0.5 )
122
+ c [idx + 2 ] = int (pow (blue / 255 , GAMMA ) * BRIGHTNESS * 255 + 0.5 )
118
123
idx -= 3 # Advance (back) one pixel
119
124
120
- # Add one more column, using the NeoPixel strip's normal buffer,
121
- # which is never assigned any color data. This is used to turn
122
- # the strip off at the end of the painting operation.
123
- columns .append (STRIP . buf )
125
+ # Add one more column with no color data loaded. This is used
126
+ # to turn the strip off at the end of the painting operation.
127
+ if not LOOP :
128
+ columns .append (bytearray ( NUM_PIXELS * 3 ) )
124
129
125
130
print ("Loaded OK!" )
126
131
gc .collect () # Garbage-collect now so playback is smoother
@@ -139,28 +144,26 @@ def load_bmp(filename):
139
144
columns = load_bmp (FILENAME )
140
145
141
146
print ("Mem free:" , gc .mem_free ())
147
+ # Orig code: 10320 bytes free
148
+ # New code: 13216 bytes free
142
149
143
- # Switch off onboard NeoPixel
144
- neo = neopixel .NeoPixel (board .NEOPIXEL , 1 , brightness = 0 , auto_write = True )
145
- neo .fill (0 )
150
+ column_delay = SPEED / 65535.0 / 10.0 # 0.0 to 0.1 seconds
151
+ while LOOP :
152
+ for c in columns :
153
+ neopixel_write (NEOPIXEL_PIN , c )
154
+ time .sleep (column_delay ) # Column-to-column delay
146
155
147
156
while True :
148
-
149
157
# Wait for touch pad input:
150
158
while not TOUCH .value :
151
159
continue
152
160
153
- time .sleep (DELAY_TIME )
154
161
column_delay = SPEED / 65535.0 / 10.0 # 0.0 to 0.1 seconds
155
162
# print(column_delay)
156
163
157
164
# Play back color data loaded into each column:
158
165
for c in columns :
159
- # Rather than replace the data in the NeoPixel strip's buffer
160
- # pixel-by-pixel, which would be very slow, we just override
161
- # STRIP's buffer object with each column of precomputed data:
162
- STRIP .buf = c # Substitute our data
163
- STRIP .show () # Push to strip
166
+ neopixel_write (NEOPIXEL_PIN , c )
164
167
time .sleep (column_delay ) # Column-to-column delay
165
168
# Last column is all 0's, no need to explicitly clear strip
166
169
0 commit comments