## CONFIGURATION WIDTH=1920 HEIGHT=1080 TRAY_WIDTH=128 TRAY_HEIGHT=24 COLOUR_1=(255,255,255) COLOUR_0=(0,0,0) XOFFSET=WIDTH-TRAY_WIDTH YOFFSET=0 TEXT_XOFF=8 TEXT_YOFF=4 BAT_PATH="/sys/class/power_supply/BAT0/" BAT_RECHECK_DELAY=32 REDRAW_DELAY=0.2 ## CREATE DRAWING SURFACE surface=[[0 for y in" "*TRAY_WIDTH]for x in" "*TRAY_HEIGHT] ## IMPORT TIME from time import ctime,sleep ## LOOK THROUGH LIST BY KEY def keyindex(list, index, key):return [key(x) for x in list].index(index) ## LOAD FONT (BDF FORMAT) font=[] inbit=0 with open("./font.bdf", "r") as f: for x in f.readlines(): if "STARTCHAR" in x: # BEGIN LOADING CHARACTER font.append([]) elif x.startswith("ENCODING"): # READ CHARACTER INDEX font[-1].append(int(x.replace("ENCODING","").strip())) elif "BBX" in x: # READ CHARACTER DIMENSIONS font[-1].append([int(y) for y in x.split(" ")[1:3]]) elif "BITMAP" in x: # BEGIN READING CHARACTER GLYPH DATA inbit=1 font[-1].append([]) elif "ENDCHAR" in x: # END READING CHARACTER inbit=0 elif inbit: # LOAD GLYPH DATA AS 2D LIST line=[] for y in x.strip(): line.extend({ # CONVERT HEX TO BINARY LIST. BAD IMPLEMENTATION, BUT ONLY RUN ONCE "0":[0,0,0,0], "1":[0,0,0,1], "2":[0,0,1,0], "3":[0,0,1,1], "4":[0,1,0,0], "5":[0,1,0,1], "6":[0,1,1,0], "7":[0,1,1,1], "8":[1,0,0,0], "9":[1,0,0,1], "a":[1,0,1,0], "b":[1,0,1,1], "c":[1,1,0,0], "d":[1,1,0,1], "e":[1,1,1,0], "f":[1,1,1,1] }[y.lower()]) font[-1][-1].append(line[:font[-1][1][0]]) ## DRAW status=-1 time=-1 recheck=0 while 1: if not recheck: # UPDATE BATTERY STATUS AND CLOCK ON A SLOWER LOOP with open (BAT_PATH+"/status", "r") as f: # READ AND STORE BATTERY VARIABLES old=status status = {"Discharging":0,"Charging":1,"Full":2, "Unknown":3}[f.read().strip()] if old!=status:redraw=1 # REDRAW SURFACE IF BATTERY STATUS CHANGED with open (BAT_PATH+"/charge_now", "r") as f: charge = int(f.read()) with open (BAT_PATH+"/charge_full", "r") as f: filled = int(f.read()) percentage = int(charge/filled*100) # CALCULATE BATTERY PERCENTAGE if time!=ctime():time=ctime();redraw=1 # REDRAW SURFACE IF TIME CHANGES recheck = (recheck + 1) % BAT_RECHECK_DELAY if redraw: time_text = time.split()[-2][:-3].split(":") # GENERATE TIME STRING time_text[0] = str((int(time_text[0])+11)%12+1) #12H TIME if len(time_text[0])==1:time_text[0]=" "+time_text[0] # PADDING text = ["DSCH","CHRG","FULL","????"][status] + " "+" "*(3-len(str(percentage)))+str(percentage)+"% "+":".join(time_text) # CONCAT ALL TEXT text_surface = [] for x in text: # SELECT CHARACTER FROM FONT text_surface.append(font[keyindex(font, ord(x), lambda x:x[0])][-1]) text_scanlines=[[] for i in " "*max([len(x) for x in text_surface])] # RENDER TEXT TO SEPARATE TEXT SURFACE for char in text_surface: for i in range(len(char)): text_scanlines[i].extend(char[i]) for y in range(TRAY_HEIGHT): # DRAW BORDER for x in range(TRAY_WIDTH): if x in (0,TRAY_WIDTH-1) or y in (0,TRAY_HEIGHT-1):surface[y][x]=1 else: surface[y][x]=0 for y in range(len(text_scanlines)): # RENDER TEXT TO MAIN SURFACE for x in range(len(text_scanlines[y])): if text_scanlines[y][x]: surface[y+TEXT_YOFF][x+TEXT_XOFF]=1 redraw = 0 with open ("/dev/fb0", "wb") as fb: # OPEN FRAMEBUFFER for y in range(TRAY_HEIGHT): # LOOP THROUGH SURFACE fb.seek(WIDTH*4*(y+YOFFSET) + XOFFSET*4) for x in range(TRAY_WIDTH): if surface[y][x]: # RENDER SURFACE TO FRAMEBUFFER r,g,b=COLOUR_1 else: r,g,b=COLOUR_0 fb.write((b).to_bytes(1, byteorder="little")) fb.write((g).to_bytes(1, byteorder="little")) fb.write((r).to_bytes(1, byteorder="little")) fb.write((0).to_bytes(1, byteorder="little")) sleep(REDRAW_DELAY) # DELAY BEFORE REDRAW