0

I'm a beginner in python but wanted to create a simple hardware reminder to put correct bin out. And maybe learn a bit during the process. My setup is Raspberry Pico and Pico-Unicorn hat from Pimoroni. Goal was to have a scrolling reminder every Thursday. First I've made it with a single color, then I wanted to do a specific gradient

The gist of the code is I've used nested lists where [x][y] of the list corresponds to the x and y of the pico-unicorn led matrix. Value of the [x][y] will be either 0 (led off) or hex colour (led on with hex colour).

Short of learning assembler, what can I do with the code? Is my approach fundamentally flawed or is it just that pico is slow? It works, don't get me wrong, but if there's anything I can do to make it better/faster - I just want to learn best practices. Also, I've looked into using framebuf library but it's got a fixed font I don't like. Appreciate any tips.

import picounicorn as display
import utime
import math

utime.sleep(0.5)

display.init()
ledwidth= display.get_width()
ledheight = display.get_height()

def displayoff():
    return [[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0]]

def lettercolumn(letter):
    if letter == "H":
        return [[0,1,1,1,1,1,0],[0,0,0,1,0,0,0],[0,0,0,1,0,0,0],[0,0,0,1,0,0,0],[0,1,1,1,1,1,0]]
    elif letter == "A":
        return [[0,1,1,1,1,1,0],[0,1,0,1,0,0,0],[0,1,0,1,0,0,0],[0,1,0,1,0,0,0],[0,1,1,1,1,1,0]]
    elif letter == "B":
        return [[0,1,1,1,1,1,0],[0,1,0,1,0,1,0],[0,1,0,1,0,1,0],[0,1,0,1,0,1,0],[0,0,1,1,1,0,0]]
    elif letter == "C":
        return [[0,1,1,1,1,1,0],[0,1,0,0,0,1,0],[0,1,0,0,0,1,0],[0,1,0,0,0,1,0],[0,1,0,0,0,1,0]]
    elif letter == "D":
        return [[0,1,1,1,1,1,0],[0,1,0,0,0,1,0],[0,1,0,0,0,1,0],[0,1,0,0,0,1,0],[0,0,1,1,1,0,0]]
    elif letter == "E":
        return [[0,1,1,1,1,1,0],[0,1,0,1,0,1,0],[0,1,0,1,0,1,0],[0,1,0,1,0,1,0],[0,1,0,0,0,1,0]]
    elif letter == "F":
        return [[0,1,1,1,1,1,0],[0,1,0,1,0,0,0],[0,1,0,1,0,0,0],[0,1,0,1,0,0,0],[0,1,0,0,0,0,0]]
    elif letter == "G":
        return [[0,1,1,1,1,1,0],[0,1,0,0,0,1,0],[0,1,0,1,0,1,0],[0,1,0,1,0,1,0],[0,1,0,1,1,1,0]]
    elif letter == "I":
        return [[0,1,0,0,0,1,0],[0,1,0,0,0,1,0],[0,1,1,1,1,1,0],[0,1,0,0,0,1,0],[0,1,0,0,0,1,0]]
    elif letter == "J":
        return [[0,1,0,0,1,1,0],[0,1,0,0,0,1,0],[0,1,1,1,1,1,0],[0,1,0,0,0,0,0],[0,0,0,0,0,0,0]]
    elif letter == "K":
        return [[0,1,1,1,1,1,0],[0,0,0,1,0,0,0],[0,0,1,0,1,0,0],[0,1,0,0,0,1,0],[0,0,0,0,0,0,0]]
    elif letter == "L":
        return [[0,1,1,1,1,1,0],[0,0,0,0,0,1,0],[0,0,0,0,0,1,0],[0,0,0,0,0,1,0],[0,0,0,0,0,0,0]]
    elif letter == "M":
        return [[0,1,1,1,1,1,0],[0,0,1,0,0,0,0],[0,0,0,1,0,0,0],[0,0,1,0,0,0,0],[0,1,1,1,1,1,0]]
    elif letter == "N":
        return [[0,1,1,1,1,1,0],[0,0,1,0,0,0,0],[0,0,0,1,0,0,0],[0,0,0,0,1,0,0],[0,1,1,1,1,1,0]]
    elif letter == "O":
        return [[0,1,1,1,1,1,0],[0,1,0,0,0,1,0],[0,1,0,0,0,1,0],[0,1,0,0,0,1,0],[0,1,1,1,1,1,0]]
    elif letter == "P":
        return [[0,1,1,1,1,1,0],[0,1,0,1,0,0,0],[0,1,0,1,0,0,0],[0,1,0,1,0,0,0],[0,1,1,1,0,0,0]]
    elif letter == "Q":
        return [[0,1,1,1,1,1,0],[0,1,0,0,0,1,0],[0,1,0,0,0,1,0],[0,1,0,0,1,1,0],[0,1,1,1,1,1,0]]
    elif letter == "R":
        return [[0,1,1,1,1,1,0],[0,1,0,1,0,0,0],[0,1,0,1,0,0,0],[0,1,0,1,1,0,0],[0,1,1,1,0,1,0]]
    elif letter == "S":
        return [[0,1,1,1,0,1,0],[0,1,0,1,0,1,0],[0,1,0,1,0,1,0],[0,1,0,1,0,1,0],[0,1,0,1,1,1,0]]
    elif letter == "T":
        return [[0,1,0,0,0,0,0],[0,1,0,0,0,0,0],[0,1,1,1,1,1,0],[0,1,0,0,0,0,0],[0,1,0,0,0,0,0]]
    elif letter == "U":
        return [[0,1,1,1,1,1,0],[0,0,0,0,0,1,0],[0,0,0,0,0,1,0],[0,0,0,0,0,1,0],[0,1,1,1,1,1,0]]
    elif letter == "V":
        return [[0,1,1,0,0,0,0],[0,0,0,1,1,0,0],[0,0,0,0,0,1,0],[0,0,0,1,1,0,0],[0,1,1,0,0,0,0]]
    elif letter == "W":
        return [[0,1,1,1,1,1,0],[0,0,0,0,0,1,0],[0,0,0,0,1,0,0],[0,0,0,0,0,1,0],[0,1,1,1,1,1,0]]
    elif letter == "X":
        return [[0,1,0,0,0,1,0],[0,0,1,0,1,0,0],[0,0,0,1,0,0,0],[0,0,1,0,1,0,0],[0,1,0,0,0,1,0]]
    elif letter == "Y":
        return [[0,1,0,0,0,0,0],[0,0,1,0,0,0,0],[0,0,0,1,1,1,0],[0,0,1,0,0,0,0],[0,1,0,0,0,0,0]]
    elif letter == "Z":
        return [[0,1,0,0,0,1,0],[0,1,0,0,1,1,0],[0,1,0,1,0,1,0],[0,1,1,0,0,1,0],[0,1,0,0,0,1,0]]
    elif letter == "0":
        return [[0,0,1,1,1,0,0],[0,1,0,0,0,1,0],[0,1,0,0,0,1,0],[0,1,0,0,0,1,0],[0,0,1,1,1,0,0]]
    elif letter == "1":
        return [[0,0,0,0,0,0,0],[0,1,0,0,0,0,0],[0,1,1,1,1,1,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0]]
    elif letter == "2":
        return [[0,0,1,0,0,1,0],[0,1,0,0,1,1,0],[0,1,0,1,0,1,0],[0,0,1,0,0,1,0],[0,0,0,0,0,0,0]]
    elif letter == "3":
        return [[0,1,0,0,0,1,0],[0,1,0,1,0,1,0],[0,1,0,1,0,1,0],[0,1,1,1,1,1,0],[0,0,0,0,0,0,0]]
    elif letter == "4":
        return [[0,1,1,1,0,0,0],[0,0,0,1,0,0,0],[0,0,0,1,0,0,0],[0,1,1,1,1,1,0],[0,0,0,0,0,0,0]]
    elif letter == "5":
        return [[0,0,1,1,0,1,0],[0,1,0,1,0,1,0],[0,1,0,1,0,1,0],[0,1,0,1,1,1,0],[0,0,0,0,0,0,0]]
    elif letter == "6":
        return [[0,1,1,1,1,1,0],[0,1,0,1,0,1,0],[0,1,0,1,0,1,0],[0,1,0,1,1,1,0],[0,0,0,0,0,0,0]]
    elif letter == "7":
        return [[0,1,0,0,0,1,0],[0,1,0,0,1,0,0],[0,1,0,1,0,0,0],[0,1,1,0,0,0,0],[0,0,0,0,0,0,0]]
    elif letter == "8":
        return [[0,1,1,0,1,1,0],[0,1,0,1,0,1,0],[0,1,0,1,0,1,0],[0,1,1,0,1,1,0],[0,0,0,0,0,0,0]]
    elif letter == "9":
        return [[0,1,1,1,0,1,0],[0,1,0,1,0,1,0],[0,1,0,1,0,1,0],[0,1,1,1,1,1,0],[0,0,0,0,0,0,0]]
    elif letter == " ":
        return [[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0]]
    elif letter == "!":
        return [[0,0,1,1,0,0,0],[0,1,0,0,1,0,0],[0,0,1,0,0,1,0],[0,1,0,0,1,0,0],[0,0,1,1,0,0,0]]
    elif letter == "?":
        return [[0,0,1,1,0,0,0],[0,1,1,1,1,0,0],[0,0,1,1,1,1,0],[0,1,1,1,1,0,0],[0,0,1,1,0,0,0]]
    elif letter == "$":
        return [[0,1,1,1,1,1,1],[0,1,1,1,1,1,0],[0,1,1,1,1,1,0],[0,1,1,1,1,1,0],[0,1,1,1,1,1,0]]

hexcolorlist = ['#de1616','#de6f16','#dede16','#16de16','#16dede','#166fde','#1616de','#6f16de','#de16de','#de166f']

#de1616 - (222,   22, 22) - red
#dede16 - (222,  222, 22) - yellow
#16de16 - (22,   222, 22) - green
#16dede - (22,   222, 222) - cyan
#1616de - (22,    22, 222) - blue
#de16de - (222,   22, 222) - magenta)

def text2arraywithcolor(text):
    #create gradient color index list from red to magenta and repeat.
    #3 list items, [0] and [1] value is x and y (of the picounicord LED matrix),
    #while [2] value is color in hex
    colorindexarray = []
    for colorindex in range (0,math.ceil((len(text)*6+33)/4),1):
        for y in range (6,-1,-1):
            for x in range (0,4,1):
                colorindexarray += [[x+2*(6-y)+4*colorindex,y,hexcolorlist[colorindex%10]]]
    
    #create text array with [x][y] corresponding to picounicorn x,y led address
    #value of [x][y] field is either 1 or 0 indicating led on or off
    textarray = displayoff()
    for i in range(0,len(text)):
        textarray += [[0,0,0,0,0,0,0]]
        textarray += lettercolumn(text[i])
    textarray += displayoff()
    
    #mapping text array with gradient color array to have color effect on text
    for xxx in range (16,len(text)*6+16,1):
        for yyy in range (1,6,1):
            resultx = [search for search in colorindexarray if search[0] == xxx]
            resulttotal = [search2 for search2 in resultx if search2[1] == yyy]
            if resulttotal != [] and textarray[xxx][yyy] == 1:
                textarray[xxx][yyy] = resulttotal[0][2]

    return textarray

def lightupdisplay(ledmatrix,text):
    for xx in range (0,16,1):
        for yy in range (1,6,1):
            if ledmatrix[xx][yy] == 0:
                display.set_pixel(xx,yy,0,0,0)
            else:
                hexvalue = ledmatrix[xx][yy].lstrip('#')
                rgb = tuple(int(hexvalue[i:i+2], 16) for i in (0, 2, 4))
                display.set_pixel(xx,yy,rgb[0],rgb[1],rgb[2])

text = "BLUE BIN"

textarraywithcolor = text2arraywithcolor(text)

#while utime.localtime()[6] == 3:
while True:
    for i in range (0,len(text)*6+33-16,1):
        lightupdisplay(textarraywithcolor[i:i+16],text)
BDL
  • 21,052
  • 22
  • 49
  • 55
  • 1
    For one: the function `lettercolumn` would work better as a dictionary, because dictionaries have a lookup time `O(1)` whereas your function requires that potentially all of the if statements be tested, making it `O(n)`. However, you should actually time functions to determine what is slowing things down (my proposed change might do very little, it might do a lot). The `time` module is one way to do this. – Kraigolas May 21 '21 at 21:03
  • `set_pixel` is a horrible way to do graphics. Do you not have some kind of `bitblt` or block transfer, where you could prepare a bitmap and blast the bitmap in one fell swoop? – Tim Roberts May 21 '21 at 21:16
  • [https://github.com/pimoroni/pimoroni-pico/blob/main/micropython/examples/pico_unicorn/demo.py](https://github.com/pimoroni/pimoroni-pico/blob/main/micropython/examples/pico_unicorn/demo.py) is about there extend of current support for control of the led matrix. How would I go about a bitmap prep and upload to led matrix? – pavl0squiet0s May 21 '21 at 21:31
  • https://codereview.stackexchange.com/ might be better – Kenny Ostrom May 21 '21 at 22:10
  • 1
    Why do all of your sublists have a length of 7 in `displayoff`? The unicorn is 8x16. Using lists for a display is a very slow approach. You should simply use a `bytearray` and learn how to manipulate it. Maybe do some research on `@micropython.viper` and `ptr32` or `ptr8`. Filling lists up with nothing but `1` and `0` is extremely inefficient. For every sublist in your font it could just be 1 byte instead of 28 bytes. I still don't get this 7 thing. Everything you are using is 8-centiric ... just like the amount of bits in a byte. Where does 7 come in? – OneMadGypsy May 22 '21 at 02:02
  • Pico unicorn hat is actually 7x16 led matrix. So I'm working on a single column manipulation and that's where 7 comes from. Thanks for bytearray and other ideas. – pavl0squiet0s May 22 '21 at 06:06

0 Answers0