# # Petcard System - v1.0 # Copyright (c) 2025 FreedTapestry21 # # Licensed under the MIT license # # Importing libraries import sys, time, machine, framebuf, ssd1306, _thread # Start Petcard frontend on core 1 with open("petcard.py") as app: _thread.start_new_thread(exec(app.read()), ()) # Initialize global variables CONFIG = json.loads(open("config.json", "r").read()) TEXT_HEIGHT = 8 PADDING = 4 # Initialize classes class Display: def __init__(self, disp, x, y) -> None: self.x = x self.y = y self.type = disp self.pages = y // 8 self.buffer = framebuf.FrameBuffer(bytearray(self.pages * x), x, y, framebuf.MONO_VLSB) def log(self, msg, IGN=False): # IGN => IGNore to report to console (Only log) if CONFIG["debug"] == 1: date = time.localtime() stamp = str(date[0]) + "-" + str(date[1]) + "-" + str(date[2]) + " " + str(date[3]) + ":" + str(date[4]) + ":" + str(date[5]) if IGN == False: text = "[" + stamp + "] " + msg print(text) else: if msg == "": text = msg else: text = "[" + stamp + "] " + msg if CONFIG["logging"] == 1: # Write log to log file with open(CONFIG["logfile"], "a") as file: file.write(text + '\n') file.close() def init(self): if self.type == "SSD1306": self.i2c = machine.I2C(0, sda=machine.Pin(4), scl=machine.Pin(5)) self.display = ssd1306.SSD1306_I2C(128, 64, self.i2c) def update(self): self.display.blit(self.buffer, 0, 0) self.display.show() class Controls: def __init__(self): pass def waitfor(self): while True: for x in CONFIG["controls"]: if machine.Pin(int(CONFIG["controls"][x]), machine.Pin.IN, machine.Pin.PULL_DOWN).value() == 1: for y in CONFIG["controls"]: if CONFIG["controls"][y] == x: return y else: pass class UI: def __init__(self): self.selection = -1 def menu(self, display, controls, entries): if self.selection == -1: self.selection = 0 while True: inp = controls.waitfor() if inp == "down": self.selection = self.selection + 1 if inp == "up": self.selection = self.selection - 1 if self.selection >= len(entries): self.selection = 0 if self.selection < 0: self.slection = len(entries) print(str(self.selection)) display.buffer.fill(0) display.buffer.fill_rect(0, int(self.selection*TEXT_HEIGHT) + int(self.selection*PADDING) + 2, display.x, 10, 1) i = PADDING q = 0 for x in entries: if i < display.y: if q == self.selection: display.buffer.text(x, 0, i, 0) else: display.buffer.text(x, 0, i, 1) i = i + TEXT_HEIGHT + PADDING q = q + 1 else: pass display.update() time.sleep(0.2) display.update() return display # Initialize functions def quit(msg=""): if msg == '': sys.exit() else: print("[" + NAME + "] " + msg)