Phil B even more fixes re: linting errors

This commit is contained in:
John Edgar Park 2018-08-24 15:11:49 -07:00
parent 2921f46fbf
commit 2f830df5e8
2 changed files with 142 additions and 152 deletions

View file

@ -1,5 +1,6 @@
# Simple NeoPixel light painter for CPX. Single image filename and speed are set
# in code, there's no interface for selecting items/speed/triggering etc.
"""Circuit Playground Express Light Paintbrush"""
# Single images only. Filename and speed are set in code,
# images should be 30px high, up to 100px wide, 24-bit .bmp files
import gc
import time
@ -10,42 +11,40 @@ from neopixel_write import neopixel_write
# uncomment one line only here to select bitmap
FILENAME = "bats.bmp" # BMP file to load from flash filesystem
# FILENAME = "digikey.bmp"
# FILENAME = "burger.bmp"
# FILENAME = "afbanner.bmp"
# FILENAME = "blinka.bmp"
# FILENAME = "ghost04.bmp"
# FILENAME = "ghost07.bmp"
# FILENAME = "ghost02.bmp"
# FILENAME = "helix-32x30.bmp"
# FILENAME = "wales2-107x30.bmp"
# FILENAME = "pumpkin.bmp"
# FILENAME = "rainbow.bmp"
# FILENAME = "rainbowRoad.bmp"
# FILENAME = "rainbowZig.bmp"
# FILENAME = "skull.bmp"
# FILENAME = "adabot.bmp"
# FILENAME = "green_stripes.bmp"
# FILENAME = "red_blue.bmp"
# FILENAME = "minerva.bmp"
#FILENAME = "jpw01.bmp"
#FILENAME = "digikey.bmp"
#FILENAME = "burger.bmp"
#FILENAME = "afbanner.bmp"
#FILENAME = "blinka.bmp"
#FILENAME = "ghost.bmp"
#FILENAME = "helix-32x30.bmp"
#FILENAME = "wales2-107x30.bmp"
#FILENAME = "pumpkin.bmp"
#FILENAME = "rainbow.bmp"
#FILENAME = "rainbowRoad.bmp"
#FILENAME = "rainbowZig.bmp"
#FILENAME = "skull.bmp"
#FILENAME = "adabot.bmp"
#FILENAME = "green_stripes.bmp"
#FILENAME = "red_blue.bmp"
#FILENAME = "minerva.bmp"
TOUCH = touchio.TouchIn(board.A5) # Rightmost capacitive touch pad
BRIGHTNESS = 1.0 # NeoPixel brightness 0.0 (min) to 1.0 (max)
TOUCH = touchio.TouchIn(board.A5) # capacitive touch pad
SPEED = 50000
BRIGHTNESS = 1.0 # Set brightness here, NOT in NeoPixel constructor
GAMMA = 2.7 # Adjusts perceived brighthess linearity
NUM_PIXELS = 30 # NeoPixel strip length (in pixels)
SPEED = 20000 # adjust this to change the playback speed e.g. 50000 is slow
LOOP = False # set to True for looping
# Switch off onboard NeoPixel...
NEOPIXEL_PIN = digitalio.DigitalInOut(board.NEOPIXEL)
NEOPIXEL_PIN.direction = digitalio.Direction.OUTPUT
neopixel_write(NEOPIXEL_PIN, bytearray(3))
# ...then assign NEOPIXEL_PIN to the external NeoPixel connector:
NEOPIXEL_PIN = digitalio.DigitalInOut(board.A1)
NEOPIXEL_PIN = board.A1 # Pin where NeoPixels are connected
DELAY_TIME = 0.01 # Timer delay before it starts
LOOP = False # Set to True for looping
# Enable NeoPixel pin as output and clear the strip
NEOPIXEL_PIN = digitalio.DigitalInOut(NEOPIXEL_PIN)
NEOPIXEL_PIN.direction = digitalio.Direction.OUTPUT
neopixel_write(NEOPIXEL_PIN, bytearray(NUM_PIXELS * 3))
# Interpret multi-byte value from file as little-endian value
def read_le(value):
"""Interpret multi-byte value from file as little-endian value"""
result = 0
shift = 0
for byte in value:
@ -54,72 +53,69 @@ def read_le(value):
return result
class BMPError(Exception):
"""Error handler for BMP-loading function"""
pass
def load_bmp(filename):
"""Load BMP file, return as list of column buffers"""
# pylint: disable=too-many-locals, too-many-branches
try:
print("Loading", filename)
with open("/" + filename, "rb") as f:
with open("/" + filename, "rb") as bmp:
print("File opened")
if f.read(2) != b'BM': # check signature
if bmp.read(2) != b'BM': # check signature
raise BMPError("Not BitMap file")
f.read(4) # Read & ignore file size
f.read(4) # Read & ignore creator bytes
bmp.read(8) # Read & ignore file size and creator bytes
bmpImageoffset = read_le(f.read(4)) # Start of image data
f.read(4) # Read & ignore header size
bmpWidth = read_le(f.read(4))
bmpHeight = read_le(f.read(4))
bmp_image_offset = read_le(bmp.read(4)) # Start of image data
bmp.read(4) # Read & ignore header size
bmp_width = read_le(bmp.read(4))
bmp_height = read_le(bmp.read(4))
# BMPs are traditionally stored bottom-to-top.
# If bmpHeight is negative, image is in top-down order.
# If bmp_height is negative, image is in top-down order.
# This is not BMP canon but has been observed in the wild!
flip = True
if bmpHeight < 0:
bmpHeight = -bmpHeight
if bmp_height < 0:
bmp_height = -bmp_height
flip = False
print("WxH: (%d,%d)" % (bmpWidth, bmpHeight))
print("WxH: (%d,%d)" % (bmp_width, bmp_height))
if read_le(f.read(2)) != 1:
if read_le(bmp.read(2)) != 1:
raise BMPError("Not single-plane")
bmpDepth = read_le(f.read(2)) # bits per pixel
# print("Bit depth: %d" % (bmpDepth))
if bmpDepth != 24:
if read_le(bmp.read(2)) != 24: # bits per pixel
raise BMPError("Not 24-bit")
if read_le(f.read(2)) != 0:
if read_le(bmp.read(2)) != 0:
raise BMPError("Compressed file")
print("Image format OK, reading data...")
rowSize = (bmpWidth * 3 + 3) & ~3 # 32-bit line boundary
row_size = (bmp_width * 3 + 3) & ~3 # 32-bit line boundary
# Constrain rows loaded to pixel strip length
clippedHeight = bmpHeight
if clippedHeight > NUM_PIXELS:
clippedHeight = NUM_PIXELS
clipped_height = min(bmp_height, NUM_PIXELS)
# Allocate per-column pixel buffers, sized for NeoPixel strip:
columns = [bytearray(NUM_PIXELS * 3) for i in range(bmpWidth)]
columns = [bytearray(NUM_PIXELS * 3) for _ in range(bmp_width)]
# Image is displayed at END (not start) of NeoPixel strip,
# this index works incrementally backward in column buffers...
idx = (NUM_PIXELS - 1) * 3
for row in range(clippedHeight): # For each scanline...
for row in range(clipped_height): # For each scanline...
if flip: # Bitmap is stored bottom-to-top order (normal BMP)
pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize
pos = bmp_image_offset + (bmp_height - 1 - row) * row_size
else: # Bitmap is stored top-to-bottom
pos = bmpImageoffset + row * rowSize
f.seek(pos) # Start of scanline
for c in columns: # For each pixel of scanline...
pos = bmp_image_offset + row * row_size
bmp.seek(pos) # Start of scanline
for column in columns: # For each pixel of scanline...
# BMP files use BGR color order
# blue, green, red = bytearray(f.read(3))
blue, green, red = f.read(3)
blue, green, red = bmp.read(3)
# Rearrange into NeoPixel strip's color order,
# while handling brightness & gamma correction:
c[idx ] = int(pow(green / 255, GAMMA) * BRIGHTNESS * 255 + 0.5)
c[idx+1] = int(pow(red / 255, GAMMA) * BRIGHTNESS * 255 + 0.5)
c[idx+2] = int(pow(blue / 255, GAMMA) * BRIGHTNESS * 255 + 0.5)
column[idx] = int(pow(green / 255, GAMMA) * BRIGHTNESS * 255 + 0.5)
column[idx+1] = int(pow(red / 255, GAMMA) * BRIGHTNESS * 255 + 0.5)
column[idx+2] = int(pow(blue / 255, GAMMA) * BRIGHTNESS * 255 + 0.5)
idx -= 3 # Advance (back) one pixel
# Add one more column with no color data loaded. This is used
@ -131,40 +127,39 @@ def load_bmp(filename):
gc.collect() # Garbage-collect now so playback is smoother
return columns
except OSError as e:
if e.args[0] == 28:
except OSError as err:
if err.args[0] == 28:
raise OSError("OS Error 28 0.25")
else:
raise OSError("OS Error 0.5")
except BMPError as e:
print("Failed to parse BMP: " + e.args[0])
except BMPError as err:
print("Failed to parse BMP: " + err.args[0])
# Load BMP image, return 'columns' array:
columns = load_bmp(FILENAME)
COLUMNS = load_bmp(FILENAME)
print("Mem free:", gc.mem_free())
# Orig code: 10320 bytes free
# New code: 13216 bytes free
column_delay = SPEED / 65535.0 / 10.0 # 0.0 to 0.1 seconds
COLUMN_DELAY = SPEED / 65535.0 / 10.0 # 0.0 to 0.1 seconds
# print(COLUMN_DELAY)
while LOOP:
for c in columns:
neopixel_write(NEOPIXEL_PIN, c)
time.sleep(column_delay) # Column-to-column delay
for COLUMN in COLUMNS:
neopixel_write(NEOPIXEL_PIN, COLUMN)
time.sleep(COLUMN_DELAY)
while True:
# Wait for touch pad input:
while not TOUCH.value:
continue
column_delay = SPEED / 65535.0 / 10.0 # 0.0 to 0.1 seconds
# print(column_delay)
time.sleep(DELAY_TIME)
# Play back color data loaded into each column:
for c in columns:
neopixel_write(NEOPIXEL_PIN, c)
time.sleep(column_delay) # Column-to-column delay
# Play back color data loaded into each column:
for COLUMN in COLUMNS:
neopixel_write(NEOPIXEL_PIN, COLUMN)
time.sleep(COLUMN_DELAY)
# Last column is all 0's, no need to explicitly clear strip
# Wait for touch pad release, just in case:

View file

@ -1,6 +1,6 @@
# HalloWing Light Paintbrush
# Single images only. Filename is set
# in code, potentiometer is used to tune playback SPEED
"""HalloWing Light Paintbrush"""
# Single images only. Filename is set in code,
# potentiometer is used to tune playback SPEED
# images should be 30px high, up to 100px wide, 24-bit .bmp files
import gc
@ -13,31 +13,31 @@ from neopixel_write import neopixel_write
# uncomment one line only here to select bitmap
FILENAME = "bats.bmp" # BMP file to load from flash filesystem
# FILENAME = "digikey.bmp"
# FILENAME = "burger.bmp"
# FILENAME = "afbanner.bmp"
# FILENAME = "blinka.bmp"
# FILENAME = "ghost04.bmp"
# FILENAME = "ghost07.bmp"
# FILENAME = "ghost02.bmp"
# FILENAME = "helix-32x30.bmp"
# FILENAME = "wales2-107x30.bmp"
# FILENAME = "pumpkin.bmp"
# FILENAME = "rainbow.bmp"
# FILENAME = "rainbowRoad.bmp"
# FILENAME = "rainbowZig.bmp"
# FILENAME = "skull.bmp"
# FILENAME = "adabot.bmp"
# FILENAME = "green_stripes.bmp"
# FILENAME = "red_blue.bmp"
# FILENAME = "minerva.bmp"
#FILENAME = "digikey.bmp"
#FILENAME = "burger.bmp"
#FILENAME = "afbanner.bmp"
#FILENAME = "blinka.bmp"
#FILENAME = "ghost04.bmp"
#FILENAME = "ghost07.bmp"
#FILENAME = "ghost02.bmp"
#FILENAME = "helix-32x30.bmp"
#FILENAME = "wales2-107x30.bmp"
#FILENAME = "pumpkin.bmp"
#FILENAME = "rainbow.bmp"
#FILENAME = "rainbowRoad.bmp"
#FILENAME = "rainbowZig.bmp"
#FILENAME = "skull.bmp"
#FILENAME = "adabot.bmp"
#FILENAME = "green_stripes.bmp"
#FILENAME = "red_blue.bmp"
#FILENAME = "minerva.bmp"
TOUCH = touchio.TouchIn(board.A2) # Rightmost capacitive touch pad
ANALOG = AnalogIn(board.SENSE) # Potentiometer on SENSE pin
BRIGHTNESS = 1.0 # NeoPixel brightness 0.0 (min) to 1.0 (max)
GAMMA = 2.7 # Adjusts perceived brighthess linearity
NUM_PIXELS = 30 # NeoPixel strip length (in pixels)
LOOP = False # set to True for looping
LOOP = False #set to True for looping
# Switch off onboard NeoPixel...
NEOPIXEL_PIN = digitalio.DigitalInOut(board.NEOPIXEL)
NEOPIXEL_PIN.direction = digitalio.Direction.OUTPUT
@ -47,8 +47,8 @@ NEOPIXEL_PIN = digitalio.DigitalInOut(board.EXTERNAL_NEOPIXEL)
NEOPIXEL_PIN.direction = digitalio.Direction.OUTPUT
neopixel_write(NEOPIXEL_PIN, bytearray(NUM_PIXELS * 3))
# Interpret multi-byte value from file as little-endian value
def read_le(value):
"""Interpret multi-byte value from file as little-endian value"""
result = 0
shift = 0
for byte in value:
@ -57,72 +57,69 @@ def read_le(value):
return result
class BMPError(Exception):
"""Error handler for BMP-loading function"""
pass
def load_bmp(filename):
"""Load BMP file, return as list of column buffers"""
# pylint: disable=too-many-locals, too-many-branches
try:
print("Loading", filename)
with open("/" + filename, "rb") as f:
with open("/" + filename, "rb") as bmp:
print("File opened")
if f.read(2) != b'BM': # check signature
if bmp.read(2) != b'BM': # check signature
raise BMPError("Not BitMap file")
f.read(4) # Read & ignore file size
f.read(4) # Read & ignore creator bytes
bmp.read(8) # Read & ignore file size and creator bytes
bmpImageoffset = read_le(f.read(4)) # Start of image data
f.read(4) # Read & ignore header size
bmpWidth = read_le(f.read(4))
bmpHeight = read_le(f.read(4))
bmp_image_offset = read_le(bmp.read(4)) # Start of image data
bmp.read(4) # Read & ignore header size
bmp_width = read_le(bmp.read(4))
bmp_height = read_le(bmp.read(4))
# BMPs are traditionally stored bottom-to-top.
# If bmpHeight is negative, image is in top-down order.
# If bmp_height is negative, image is in top-down order.
# This is not BMP canon but has been observed in the wild!
flip = True
if bmpHeight < 0:
bmpHeight = -bmpHeight
if bmp_height < 0:
bmp_height = -bmp_height
flip = False
print("WxH: (%d,%d)" % (bmpWidth, bmpHeight))
print("WxH: (%d,%d)" % (bmp_width, bmp_height))
if read_le(f.read(2)) != 1:
if read_le(bmp.read(2)) != 1:
raise BMPError("Not single-plane")
bmpDepth = read_le(f.read(2)) # bits per pixel
# print("Bit depth: %d" % (bmpDepth))
if bmpDepth != 24:
if read_le(bmp.read(2)) != 24: # bits per pixel
raise BMPError("Not 24-bit")
if read_le(f.read(2)) != 0:
if read_le(bmp.read(2)) != 0:
raise BMPError("Compressed file")
print("Image format OK, reading data...")
rowSize = (bmpWidth * 3 + 3) & ~3 # 32-bit line boundary
row_size = (bmp_width * 3 + 3) & ~3 # 32-bit line boundary
# Constrain rows loaded to pixel strip length
clippedHeight = bmpHeight
if clippedHeight > NUM_PIXELS:
clippedHeight = NUM_PIXELS
clipped_height = min(bmp_height, NUM_PIXELS)
# Allocate per-column pixel buffers, sized for NeoPixel strip:
columns = [bytearray(NUM_PIXELS * 3) for i in range(bmpWidth)]
columns = [bytearray(NUM_PIXELS * 3) for _ in range(bmp_width)]
# Image is displayed at END (not start) of NeoPixel strip,
# this index works incrementally backward in column buffers...
idx = (NUM_PIXELS - 1) * 3
for row in range(clippedHeight): # For each scanline...
for row in range(clipped_height): # For each scanline...
if flip: # Bitmap is stored bottom-to-top order (normal BMP)
pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize
pos = bmp_image_offset + (bmp_height - 1 - row) * row_size
else: # Bitmap is stored top-to-bottom
pos = bmpImageoffset + row * rowSize
f.seek(pos) # Start of scanline
for c in columns: # For each pixel of scanline...
pos = bmp_image_offset + row * row_size
bmp.seek(pos) # Start of scanline
for column in columns: # For each pixel of scanline...
# BMP files use BGR color order
# blue, green, red = bytearray(f.read(3))
blue, green, red = f.read(3)
blue, green, red = bmp.read(3)
# Rearrange into NeoPixel strip's color order,
# while handling brightness & gamma correction:
c[idx ] = int(pow(green / 255, GAMMA) * BRIGHTNESS * 255 + 0.5)
c[idx+1] = int(pow(red / 255, GAMMA) * BRIGHTNESS * 255 + 0.5)
c[idx+2] = int(pow(blue / 255, GAMMA) * BRIGHTNESS * 255 + 0.5)
column[idx] = int(pow(green / 255, GAMMA) * BRIGHTNESS * 255 + 0.5)
column[idx+1] = int(pow(red / 255, GAMMA) * BRIGHTNESS * 255 + 0.5)
column[idx+2] = int(pow(blue / 255, GAMMA) * BRIGHTNESS * 255 + 0.5)
idx -= 3 # Advance (back) one pixel
# Add one more column with no color data loaded. This is used
@ -134,40 +131,38 @@ def load_bmp(filename):
gc.collect() # Garbage-collect now so playback is smoother
return columns
except OSError as e:
if e.args[0] == 28:
except OSError as err:
if err.args[0] == 28:
raise OSError("OS Error 28 0.25")
else:
raise OSError("OS Error 0.5")
except BMPError as e:
print("Failed to parse BMP: " + e.args[0])
except BMPError as err:
print("Failed to parse BMP: " + err.args[0])
# Load BMP image, return 'columns' array:
columns = load_bmp(FILENAME)
# Load BMP image, return 'COLUMNS' array:
COLUMNS = load_bmp(FILENAME)
print("Mem free:", gc.mem_free())
# Orig code: 10320 bytes free
# New code: 13216 bytes free
column_delay = ANALOG.value / 65535.0 / 10.0 # 0.0 to 0.1 seconds
COLUMN_DELAY = ANALOG.value / 65535.0 / 10.0 # 0.0 to 0.1 seconds
while LOOP:
for c in columns:
neopixel_write(NEOPIXEL_PIN, c)
time.sleep(column_delay) # Column-to-column delay
for COLUMN in COLUMNS:
neopixel_write(NEOPIXEL_PIN, COLUMN)
time.sleep(COLUMN_DELAY)
while True:
# Wait for touch pad input:
while not TOUCH.value:
continue
column_delay = ANALOG.value / 65535.0 / 10.0 # 0.0 to 0.1 seconds
# print(column_delay)
COLUMN_DELAY = ANALOG.value / 65535.0 / 10.0 # 0.0 to 0.1 seconds
# print(COLUMN_DELAY)
# Play back color data loaded into each column:
for c in columns:
neopixel_write(NEOPIXEL_PIN, c)
time.sleep(column_delay) # Column-to-column delay
for COLUMN in COLUMNS:
neopixel_write(NEOPIXEL_PIN, COLUMN)
time.sleep(COLUMN_DELAY)
# Last column is all 0's, no need to explicitly clear strip
# Wait for touch pad release, just in case: