diff --git a/Motorized_POV_Display/blinka.bmp b/Motorized_POV_Display/blinka.bmp new file mode 100755 index 000000000..34a0631f4 Binary files /dev/null and b/Motorized_POV_Display/blinka.bmp differ diff --git a/Motorized_POV_Display/code.py b/Motorized_POV_Display/code.py new file mode 100755 index 000000000..49e113b74 --- /dev/null +++ b/Motorized_POV_Display/code.py @@ -0,0 +1,130 @@ +# SPDX-FileCopyrightText: 2017 Limor Fried for Adafruit Industries +# +# SPDX-License-Identifier: MIT +# Dotstar POV Display! Can handle up to ~2300 pixel size image (e.g. 36 x 64) + +import gc +import time +from adafruit_motorkit import MotorKit +import board +import busio +import digitalio + +kit = MotorKit(i2c=board.I2C()) + +FILENAME = "nyan-xmas.bmp" +IMAGE_DELAY = 0.001 +REPEAT = True +BRIGHTNESS = 0.3 +PIXEL_DELAY = 0.003 + +dotstar = busio.SPI(board.SCK, board.MOSI) +while not dotstar.try_lock(): + pass +dotstar.configure(baudrate=44000000) + +# we'll resize this later +databuf = bytearray(0) + +led = digitalio.DigitalInOut(board.D13) +led.switch_to_output() + +def read_le(s): + # as of this writting, int.from_bytes does not have LE support, DIY! + result = 0 + shift = 0 + for byte in bytearray(s): + result += byte << shift + shift += 8 + return result + +class BMPError(Exception): + pass + +try: + with open("/" + FILENAME, "rb") as f: + print("File opened") + if f.read(2) != b'BM': # check signature + raise BMPError("Not BitMap file") + + bmpFileSize = read_le(f.read(4)) + f.read(4) # Read & ignore creator bytes + + bmpImageoffset = read_le(f.read(4)) # Start of image data + headerSize = read_le(f.read(4)) + bmpWidth = read_le(f.read(4)) + bmpHeight = read_le(f.read(4)) + flip = True + + print("Size: %d\nImage offset: %d\nHeader size: %d" % + (bmpFileSize, bmpImageoffset, headerSize)) + print("Width: %d\nHeight: %d" % (bmpWidth, bmpHeight)) + + if read_le(f.read(2)) != 1: + raise BMPError("Not singleplane") + bmpDepth = read_le(f.read(2)) # bits per pixel + print("Bit depth: %d" % (bmpDepth)) + if bmpDepth != 24: + raise BMPError("Not 24-bit") + if read_le(f.read(2)) != 0: + raise BMPError("Compressed file") + + print("Image OK!") + + rowSize = (bmpWidth * 3 + 3) & ~3 # 32-bit line boundary + + # its huge! but its also fast :) + databuf = bytearray(bmpWidth * bmpHeight * 4) + + for row in range(bmpHeight): # For each scanline... + if flip: # Bitmap is stored bottom-to-top order (normal BMP) + pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize + else: # Bitmap is stored top-to-bottom + pos = bmpImageoffset + row * rowSize + + # print ("seek to %d" % pos) + f.seek(pos) + for col in range(bmpWidth): + b, g, r = bytearray(f.read(3)) # BMP files store RGB in BGR + # front load brightness, gamma and reordering here! + order = [b, g, r] + idx = (col * bmpHeight + (bmpHeight - row - 1)) * 4 + databuf[idx] = 0xFF # first byte is 'brightness' + idx += 1 + for color in order: + databuf[idx] = int( + pow((color * BRIGHTNESS) / 255, 2.7) * 255 + 0.5) + idx += 1 + +except BMPError as e: + print("Failed to parse BMP: " + e.args[0]) + +gc.collect() +print(gc.mem_free()) +print("Ready to go!") + +kit.motor1.throttle = 1 + +while True: + print("Draw!") + index = 0 + + for col in range(bmpWidth): + row = databuf[index:index + bmpHeight * 4] + dotstar.write(bytearray([0x00, 0x00, 0x00, 0x00])) + dotstar.write(row) + dotstar.write(bytearray([0x00, 0x00, 0x00, 0x00])) + index += bmpHeight * 4 + time.sleep(PIXEL_DELAY) + + # clear it out + dotstar.write(bytearray([0x00, 0x00, 0x00, 0x00])) + for r in range(bmpHeight * 5): + dotstar.write(bytearray([0xFF, 0x00, 0x00, 0x00])) + dotstar.write(bytearray([0xff, 0xff, 0xff, 0xff])) + gc.collect() + + if not REPEAT: + break + + time.sleep(IMAGE_DELAY) diff --git a/Motorized_POV_Display/dreidel.bmp b/Motorized_POV_Display/dreidel.bmp new file mode 100644 index 000000000..674875808 Binary files /dev/null and b/Motorized_POV_Display/dreidel.bmp differ diff --git a/Motorized_POV_Display/nyan-xmas.bmp b/Motorized_POV_Display/nyan-xmas.bmp new file mode 100755 index 000000000..cb0a9422a Binary files /dev/null and b/Motorized_POV_Display/nyan-xmas.bmp differ diff --git a/Motorized_POV_Display/pipesky.bmp b/Motorized_POV_Display/pipesky.bmp new file mode 100755 index 000000000..de986ff9c Binary files /dev/null and b/Motorized_POV_Display/pipesky.bmp differ diff --git a/Motorized_POV_Display/xmas.bmp b/Motorized_POV_Display/xmas.bmp new file mode 100755 index 000000000..fdc22fc8f Binary files /dev/null and b/Motorized_POV_Display/xmas.bmp differ diff --git a/Motorized_POV_Display/xmastree.bmp b/Motorized_POV_Display/xmastree.bmp new file mode 100755 index 000000000..a10f439e2 Binary files /dev/null and b/Motorized_POV_Display/xmastree.bmp differ