# SPDX-FileCopyrightText: 2020 Jeff Epler for Adafruit Industries # SPDX-FileCopyrightText: 2020 Limor Fried for Adafruit Industries # # SPDX-License-Identifier: MIT """ RGB Matrix Ocean Scroller Adafruit invests time and resources providing this open source code. Please support Adafruit and open source hardware by purchasing products from Adafruit! Written by Jeff Epler & Limor Fried for Adafruit Industries Copyright (c) 2019-2020 Adafruit Industries Licensed under the MIT license. All text above must be included in any redistribution. """ import math import time import random import adafruit_imageload.bmp import board import displayio import framebufferio import rgbmatrix import ulab displayio.release_displays() class Reshader: '''reshader fades the image to mimic brightness control''' def __init__(self, palette): self.palette = palette ulab_palette = ulab.numpy.zeros((len(palette), 3)) for i in range(len(palette)): rgb = int(palette[i]) ulab_palette[i, 2] = rgb & 0xff ulab_palette[i, 1] = (rgb >> 8) & 0xff ulab_palette[i, 0] = rgb >> 16 self.ulab_palette = ulab_palette def reshade(self, brightness): '''reshader''' palette = self.palette shaded = ulab.numpy.array(self.ulab_palette * brightness, dtype=ulab.numpy.uint8) for i in range(len(palette)): palette[i] = tuple(shaded[i]) def do_crawl_down(image_file, *, speed=12, weave=4, pulse=.5, weave_speed=1/6, pulse_speed=1/7): # pylint:disable=too-many-locals '''function to scroll the image''' the_bitmap, the_palette = adafruit_imageload.load( image_file, bitmap=displayio.Bitmap, palette=displayio.Palette) shader = Reshader(the_palette) group = displayio.Group() tile_grid = displayio.TileGrid(bitmap=the_bitmap, pixel_shader=the_palette) group.append(tile_grid) display.show(group) start_time = time.monotonic_ns() start_y = display.height # High enough to be "off the top" end_y = -the_bitmap.height # Low enough to be "off the bottom" # Mix up how the bobs and brightness change on each run r1 = random.random() * math.pi r2 = random.random() * math.pi y = start_y while y > end_y: now = time.monotonic_ns() y = start_y - speed * ((now - start_time) / 1e9) group.y = round(y) # wave from side to side group.x = round(weave * math.cos(y * weave_speed + r1)) # Change the brightness if pulse > 0: shader.reshade((1 - pulse) + pulse * math.sin(y * pulse_speed + r2)) display.refresh(minimum_frames_per_second=0, target_frames_per_second=60) def do_pulse(image_file, *, duration=4, pulse_speed=1/8, pulse=.5): '''pulse animation''' the_bitmap, the_palette = adafruit_imageload.load( image_file, bitmap=displayio.Bitmap, palette=displayio.Palette) shader = Reshader(the_palette) group = displayio.Group() tile_grid = displayio.TileGrid(bitmap=the_bitmap, pixel_shader=the_palette) group.append(tile_grid) group.x = (display.width - the_bitmap.width) // 2 group.y = (display.height - the_bitmap.height) // 2 display.show(group) start_time = time.monotonic_ns() end_time = start_time + int(duration * 1e9) now_ns = time.monotonic_ns() while now_ns < end_time: now_ns = time.monotonic_ns() current_time = (now_ns - start_time) / 1e9 shader.reshade((1 - pulse) - pulse * math.cos(2*math.pi*current_time*pulse_speed)**2) display.refresh(minimum_frames_per_second=0, target_frames_per_second=60) matrix = rgbmatrix.RGBMatrix( width=64, height=32, bit_depth=5, rgb_pins=[board.D6, board.D5, board.D9, board.D11, board.D10, board.D12], addr_pins=[board.A5, board.A4, board.A3, board.A2], clock_pin=board.D13, latch_pin=board.D0, output_enable_pin=board.D1) display = framebufferio.FramebufferDisplay(matrix, auto_refresh=False) # Image playlist - set to run randomly. Set pulse from 0 to .5 while True: show_next = random.randint(1, 5) #change to reflect how many images you add if show_next == 1: do_crawl_down("/ray.bmp") elif show_next == 2: do_crawl_down("/waves1.bmp", speed=7, weave=0, pulse=.35) elif show_next == 3: do_crawl_down("/waves2.bmp", speed=9, weave=0, pulse=.35) elif show_next == 4: do_pulse("/heart.bmp", duration=4, pulse=.45) elif show_next == 5: do_crawl_down("/dark.bmp")