Created
November 25, 2022 20:42
-
-
Save RobCranfill/a9929c4f7e13cfbaeaccc8e54dadbcf2 to your computer and use it in GitHub Desktop.
Display a scrolling message on an Adafruit 8x8 LED matrix. For the Adafruit RP2040 Feather board (or any CircuitPython board?).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Display a scrolling message on an Adafruit 8x8 LED matrix. | |
# For the Adafruit RP2040 Feather board (or any CircuitPython board?). | |
# | |
import board | |
from adafruit_ht16k33.matrix import Matrix8x8 | |
import time | |
import font # This is my data for a simple 8x8 font, found in this directory. | |
# For the given string, create the big list of bit values (columns), left to right. | |
# TODO: This might display faster if we didn't pack these bits, but just | |
# had an array of booleans. (That would take more memory but we have plenty I think.) | |
# | |
def makeVRasters(string): | |
bits = [] | |
if len(string) == 0: # is there a better way to handle this null-input case? | |
string = " " | |
else: | |
string += string[0] # duplicate the first char onto the end of the data for easier scrolling. TODO: needed? | |
for char in string: | |
# bl is the list of *horizontal* rasters for the char | |
bl = byteListForChar(char) | |
for bitIndex in range(7,-1,-1): | |
thisVR = 0 | |
for hRasterIndex in range(7,-1,-1): | |
bitVal = ((1 << bitIndex) & bl[hRasterIndex]) | |
if bitVal > 0: | |
thisVR += (1 << (7-hRasterIndex)) | |
bits.append(thisVR) | |
print(f"vraster (len {len(bits)}): {bits}\n") | |
for b in bits: | |
print(f" {b:08b}") | |
return bits | |
# Rotate the list of vertical rasters thru the display, forever. | |
# The input data already has the first char duplicated at the end, for ease of rotation. | |
# | |
def displayVRasters(display, vrs, delay): | |
# Paint the first char in its entirety. | |
for ri in range(0, 8): | |
vr = vrs[ri] | |
for k in range(8): | |
display[ri, 7-k] = vr & (1<<k) | |
time.sleep(delay) | |
# Now we can just scroll the display with hardware (?) | |
# and add the one new v-raster. | |
while True: | |
# display each vertical raster | |
for ri in range(7, len(vrs)): | |
display.shift_left() | |
vr = vrs[ri] | |
for k in range(8): | |
display[7, 7-k] = vr & (1<<k) | |
time.sleep(delay) | |
# Return a list of the bytes for the given character. | |
# TODO: catch missing chars? | |
# | |
def byteListForChar(char): | |
bits = font.FontData[char] | |
return bits | |
# main | |
i2c = board.I2C() | |
display = Matrix8x8(i2c) | |
display.fill(0) | |
time.sleep(1) | |
vrasters = makeVRasters("1234567890") | |
displayVRasters(display, vrasters, 0.0) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
''' | |
Font.py | |
Horizontal raster data for a simple 8x8 font. | |
''' | |
import time | |
# global oct2bin = ['000','001','010','011','100','101','110','111'] | |
global OCT2BIN | |
OCT2BIN = ['___','__*','_*_','_**','*__','*_*','**_','***'] | |
# from 8x8font.h | |
# | |
FontData = { | |
" ": [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], # space 0x20 | |
"!": [0x30,0x78,0x78,0x30,0x30,0x00,0x30,0x00], # ! | |
"\"": [0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00], # " | |
"#": [0x6C,0x6C,0xFE,0x6C,0xFE,0x6C,0x6C,0x00], # # | |
"$": [0x18,0x3E,0x60,0x3C,0x06,0x7C,0x18,0x00], # $ | |
"%": [0x00,0x63,0x66,0x0C,0x18,0x33,0x63,0x00], # % | |
"&": [0x1C,0x36,0x1C,0x3B,0x6E,0x66,0x3B,0x00], # & | |
"'": [0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00], # ' | |
"(": [0x0C,0x18,0x30,0x30,0x30,0x18,0x0C,0x00], # ( | |
")": [0x30,0x18,0x0C,0x0C,0x0C,0x18,0x30,0x00], # ) | |
"*": [0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00], # * | |
"+": [0x00,0x30,0x30,0xFC,0x30,0x30,0x00,0x00], # + | |
",": [0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30], # , | |
"-": [0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00], # - | |
".": [0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00], # . | |
"/": [0x03,0x06,0x0C,0x18,0x30,0x60,0x40,0x00], # / | |
"0": [0x3E,0x63,0x63,0x6B,0x63,0x63,0x3E,0x00], # 0 0x30 | |
"1": [0x18,0x38,0x58,0x18,0x18,0x18,0x7E,0x00], # 1 | |
"2": [0x3C,0x66,0x06,0x1C,0x30,0x66,0x7E,0x00], # 2 | |
"3": [0x3C,0x66,0x06,0x1C,0x06,0x66,0x3C,0x00], # 3 | |
"4": [0x0E,0x1E,0x36,0x66,0x7F,0x06,0x0F,0x00], # 4 | |
"5": [0x7E,0x60,0x7C,0x06,0x06,0x66,0x3C,0x00], # 5 | |
"6": [0x1C,0x30,0x60,0x7C,0x66,0x66,0x3C,0x00], # 6 | |
"7": [0x7E,0x66,0x06,0x0C,0x18,0x18,0x18,0x00], # 7 | |
"8": [0x3C,0x66,0x66,0x3C,0x66,0x66,0x3C,0x00], # 8 | |
"9": [0x3C,0x66,0x66,0x3E,0x06,0x0C,0x38,0x00], # 9 | |
":": [0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00], # : | |
";": [0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x30], # ; | |
"<": [0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00], # < | |
"=": [0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00], # = | |
">": [0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00], # > | |
"?": [0x3C,0x66,0x06,0x0C,0x18,0x00,0x18,0x00], # ? | |
"\@": [0x3E,0x63,0x6F,0x69,0x6F,0x60,0x3E,0x00], # @ 0x40 | |
"A": [0x18,0x3C,0x66,0x66,0x7E,0x66,0x66,0x00], # A | |
"B": [0x7E,0x33,0x33,0x3E,0x33,0x33,0x7E,0x00], # B | |
"C": [0x1E,0x33,0x60,0x60,0x60,0x33,0x1E,0x00], # C | |
"D": [0x7C,0x36,0x33,0x33,0x33,0x36,0x7C,0x00], # D | |
"E": [0x7F,0x31,0x34,0x3C,0x34,0x31,0x7F,0x00], # E | |
"F": [0x7F,0x31,0x34,0x3C,0x34,0x30,0x78,0x00], # F | |
"G": [0x1E,0x33,0x60,0x60,0x67,0x33,0x1F,0x00], # G | |
"H": [0x66,0x66,0x66,0x7E,0x66,0x66,0x66,0x00], # H | |
"I": [0x3C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00], # I | |
"J": [0x0F,0x06,0x06,0x06,0x66,0x66,0x3C,0x00], # J | |
"K": [0x73,0x33,0x36,0x3C,0x36,0x33,0x73,0x00], # K | |
"L": [0x78,0x30,0x30,0x30,0x31,0x33,0x7F,0x00], # L | |
"M": [0x63,0x77,0x7F,0x7F,0x6B,0x63,0x63,0x00], # M | |
"N": [0x63,0x73,0x7B,0x6F,0x67,0x63,0x63,0x00], # N | |
"O": [0x3E,0x63,0x63,0x63,0x63,0x63,0x3E,0x00], # O | |
"P": [0x7E,0x33,0x33,0x3E,0x30,0x30,0x78,0x00], # P 0x50 | |
"Q": [0x3C,0x66,0x66,0x66,0x6E,0x3C,0x0E,0x00], # Q | |
"R": [0x7E,0x33,0x33,0x3E,0x36,0x33,0x73,0x00], # R | |
"S": [0x3C,0x66,0x30,0x18,0x0C,0x66,0x3C,0x00], # S | |
"T": [0x7E,0x5A,0x18,0x18,0x18,0x18,0x3C,0x00], # T | |
"U": [0x66,0x66,0x66,0x66,0x66,0x66,0x7E,0x00], # U | |
"V": [0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00], # V | |
"W": [0x63,0x63,0x63,0x6B,0x7F,0x77,0x63,0x00], # W | |
"X": [0x63,0x63,0x36,0x1C,0x1C,0x36,0x63,0x00], # X | |
"Y": [0x66,0x66,0x66,0x3C,0x18,0x18,0x3C,0x00], # Y | |
"Z": [0x7F,0x63,0x46,0x0C,0x19,0x33,0x7F,0x00], # Z | |
"": [0x3C,0x30,0x30,0x30,0x30,0x30,0x3C,0x00], # [ | |
"\\": [0x60,0x30,0x18,0x0C,0x06,0x03,0x01,0x00], # \ (backslash) | |
"]": [0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00], # ] | |
"^": [0x08,0x1C,0x36,0x63,0x00,0x00,0x00,0x00], # ^ | |
"_": [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF], # _ | |
"`": [0x18,0x18,0x0C,0x00,0x00,0x00,0x00,0x00], # ` 0x60 | |
"a": [0x00,0x00,0x3C,0x06,0x3E,0x66,0x3B,0x00], # a | |
"b": [0x70,0x30,0x3E,0x33,0x33,0x33,0x6E,0x00], # b | |
"c": [0x00,0x00,0x3C,0x66,0x60,0x66,0x3C,0x00], # c | |
"d": [0x0E,0x06,0x3E,0x66,0x66,0x66,0x3B,0x00], # d | |
"e": [0x00,0x00,0x3C,0x66,0x7E,0x60,0x3C,0x00], # e | |
"f": [0x1C,0x36,0x30,0x78,0x30,0x30,0x78,0x00], # f | |
"g": [0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x7C], # g | |
"h": [0x70,0x30,0x36,0x3B,0x33,0x33,0x73,0x00], # h | |
"i": [0x18,0x00,0x38,0x18,0x18,0x18,0x3C,0x00], # i | |
"j": [0x06,0x00,0x06,0x06,0x06,0x66,0x66,0x3C], # j | |
"k": [0x70,0x30,0x33,0x36,0x3C,0x36,0x73,0x00], # k | |
"l": [0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00], # l | |
"m": [0x00,0x00,0x66,0x7F,0x7F,0x6B,0x63,0x00], # m | |
"n": [0x00,0x00,0x7C,0x66,0x66,0x66,0x66,0x00], # n | |
"o": [0x00,0x00,0x3C,0x66,0x66,0x66,0x3C,0x00], # o | |
"p": [0x00,0x00,0x6E,0x33,0x33,0x3E,0x30,0x78], # p 0x70 | |
"q": [0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x0F], # q | |
"r": [0x00,0x00,0x6E,0x3B,0x33,0x30,0x78,0x00], # r | |
"s": [0x00,0x00,0x3E,0x60,0x3C,0x06,0x7C,0x00], # s | |
"t": [0x08,0x18,0x3E,0x18,0x18,0x1A,0x0C,0x00], # t | |
"u": [0x00,0x00,0x66,0x66,0x66,0x66,0x3B,0x00], # u | |
"v": [0x00,0x00,0x66,0x66,0x66,0x3C,0x18,0x00], # v | |
"w": [0x00,0x00,0x63,0x6B,0x7F,0x7F,0x36,0x00], # w | |
"x": [0x00,0x00,0x63,0x36,0x1C,0x36,0x63,0x00], # x | |
"y": [0x00,0x00,0x66,0x66,0x66,0x3E,0x06,0x7C], # y | |
"z": [0x00,0x00,0x7E,0x4C,0x18,0x32,0x7E,0x00], # z | |
"{": [0x0E,0x18,0x18,0x70,0x18,0x18,0x0E,0x00], # { | |
"|": [0x0C,0x0C,0x0C,0x00,0x0C,0x0C,0x0C,0x00], # | | |
"}": [0x70,0x18,0x18,0x0E,0x18,0x18,0x70,0x00], # } | |
"~": [0x3B,0x6E,0x00,0x00,0x00,0x00,0x00,0x00] # ~ | |
} | |
def bin(x, digits=0): | |
global OCT2BIN | |
binstring = [OCT2BIN[int(n)] for n in oct(x)] | |
return ''.join(binstring).lstrip('0').zfill(digits) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Works just barely fast enough on an Adafruit RP2020 Feather. :-/