import badger2040 import machine import time import sys # Global Constants WIDTH = badger2040.WIDTH HEIGHT = badger2040.HEIGHT IMAGE_WIDTH = 110 COMPANY_HEIGHT = 30 DETAILS_HEIGHT = 20 NAME_HEIGHT = HEIGHT - COMPANY_HEIGHT - (DETAILS_HEIGHT * 2) - 2 TEXT_WIDTH = WIDTH - IMAGE_WIDTH - 1 COMPANY_TEXT_SIZE = 0.6 DETAILS_TEXT_SIZE = 0.5 LEFT_PADDING = 5 NAME_PADDING = 20 DETAIL_SPACING = 10 OVERLAY_BORDER = 40 OVERLAY_SPACING = 20 OVERLAY_TEXT_SIZE = 0.6 # ------------------------------ # Utility functions # ------------------------------ # Reduce the size of a string until it fits within a given width def truncatestring(text, text_size, width): while True: length = display.measure_text(text, text_size) if length > 0 and length > width: text = text[:-1] else: text += "" return text # ------------------------------ # Drawing functions # ------------------------------ # Draw an overlay box with a given message within it def draw_overlay(message, width, height, line_spacing, text_size): # Draw a light grey background display.pen(12) display.rectangle((WIDTH - width) // 2, (HEIGHT - height) // 2, width, height) # Take the provided message and split it up into # lines that fit within the specified width words = message.split(" ") lines = [] line = "" appended_line = "" for word in words: if len(word) > 0: appended_line += " " appended_line += word if display.measure_text(appended_line, text_size) >= width: lines.append(line) appended_line = word else: line = appended_line if len(line) != 0: lines.append(line) display.pen(0) display.thickness(2) # Display each line of text from the message, centre-aligned num_lines = len(lines) for i in range(num_lines): length = display.measure_text(lines[i], text_size) current_line = (i * line_spacing) - ((num_lines - 1) * line_spacing) // 2 display.text(lines[i], (WIDTH - length) // 2, (HEIGHT // 2) + current_line, text_size) # Draw the badge, including user text def draw_badge(): display.pen(0) display.clear() # Replace with drawing an image display.pen(15) display.rectangle(WIDTH - IMAGE_WIDTH, 0, IMAGE_WIDTH, HEIGHT) # Draw a border around the image display.pen(0) display.thickness(1) display.line(WIDTH - IMAGE_WIDTH, 0, WIDTH - 1, 0) display.line(WIDTH - IMAGE_WIDTH, 0, WIDTH - IMAGE_WIDTH, HEIGHT - 1) display.line(WIDTH - IMAGE_WIDTH, HEIGHT - 1, WIDTH - 1, HEIGHT - 1) display.line(WIDTH - 1, 0, WIDTH - 1, HEIGHT - 1) # Uncomment this if a white background is wanted behind the company # display.pen(15) # display.rectangle(1, 1, TEXT_WIDTH, COMPANY_HEIGHT - 1) # Draw the company display.pen(15) # Change this to 0 if a white background is used display.font("serif") display.thickness(3) display.text(company, LEFT_PADDING, (COMPANY_HEIGHT // 2) + 1, COMPANY_TEXT_SIZE) # Draw a white background behind the name display.pen(15) display.thickness(1) display.rectangle(1, COMPANY_HEIGHT + 1, TEXT_WIDTH, NAME_HEIGHT) # Draw the name, scaling it based on the available width display.pen(0) display.font("sans") display.thickness(4) name_size = 2.0 # A sensible starting scale while True: name_length = display.measure_text(name, name_size) if name_length >= (TEXT_WIDTH - NAME_PADDING) and name_size >= 0.1: name_size -= 0.01 else: display.text(name, (TEXT_WIDTH - name_length) // 2, (NAME_HEIGHT // 2) + COMPANY_HEIGHT + 1, name_size) break # Draw a white backgrounds behind the details display.pen(15) display.thickness(1) display.rectangle(1, HEIGHT - DETAILS_HEIGHT * 2, TEXT_WIDTH, DETAILS_HEIGHT - 1) display.rectangle(1, HEIGHT - DETAILS_HEIGHT, TEXT_WIDTH, DETAILS_HEIGHT - 1) # Draw the first detail's title and text display.pen(0) display.font("sans") display.thickness(3) name_length = display.measure_text(detail1_title, DETAILS_TEXT_SIZE) display.text(detail1_title, LEFT_PADDING, HEIGHT - ((DETAILS_HEIGHT * 3) // 2), DETAILS_TEXT_SIZE) display.thickness(2) display.text(detail1_text, 5 + name_length + DETAIL_SPACING, HEIGHT - ((DETAILS_HEIGHT * 3) // 2), DETAILS_TEXT_SIZE) # Draw the second detail's title and text display.thickness(3) name_length = display.measure_text(detail2_title, DETAILS_TEXT_SIZE) display.text(detail2_title, LEFT_PADDING, HEIGHT - (DETAILS_HEIGHT // 2), DETAILS_TEXT_SIZE) display.thickness(2) display.text(detail2_text, LEFT_PADDING + name_length + DETAIL_SPACING, HEIGHT - (DETAILS_HEIGHT // 2), DETAILS_TEXT_SIZE) # ------------------------------ # Program setup # ------------------------------ # Global variables show_overlay = False # Create a new Badger and set it to update NORMAL display = badger2040.Badger2040() display.update_speed(badger2040.UPDATE_NORMAL) try: open("badge.txt", "r") except OSError: display.pen(15) display.clear() draw_overlay("To run this Badge demo, make sure there is a badge.txt file on your MicroPython device.", WIDTH - OVERLAY_BORDER, HEIGHT - OVERLAY_BORDER, OVERLAY_SPACING, OVERLAY_TEXT_SIZE) display.update() sys.exit() # Open the badge file badge = open("badge.txt", "r") # Read in the next 6 lines company = badge.readline() # "mustelid inc" name = badge.readline() # "H. Badger" detail1_title = badge.readline() # "RP2040" detail1_text = badge.readline() # "2MB Flash" detail2_title = badge.readline() # "E ink" detail2_text = badge.readline() # "296x128px" # Truncate all of the text (except for the name as that is scaled) company = truncatestring(company, COMPANY_TEXT_SIZE, TEXT_WIDTH) detail1_title = truncatestring(detail1_title, DETAILS_TEXT_SIZE, TEXT_WIDTH) detail1_text = truncatestring(detail1_text, DETAILS_TEXT_SIZE, TEXT_WIDTH - DETAIL_SPACING - display.measure_text(detail1_title, DETAILS_TEXT_SIZE)) detail2_title = truncatestring(detail2_title, DETAILS_TEXT_SIZE, TEXT_WIDTH) detail2_text = truncatestring(detail2_text, DETAILS_TEXT_SIZE, TEXT_WIDTH - DETAIL_SPACING - display.measure_text(detail2_title, DETAILS_TEXT_SIZE)) # Set up the buttons button_a = machine.Pin(badger2040.BUTTON_A, machine.Pin.IN, machine.Pin.PULL_DOWN) button_b = machine.Pin(badger2040.BUTTON_B, machine.Pin.IN, machine.Pin.PULL_DOWN) button_c = machine.Pin(badger2040.BUTTON_C, machine.Pin.IN, machine.Pin.PULL_DOWN) button_up = machine.Pin(badger2040.BUTTON_UP, machine.Pin.IN, machine.Pin.PULL_DOWN) button_down = machine.Pin(badger2040.BUTTON_DOWN, machine.Pin.IN, machine.Pin.PULL_DOWN) # Button handling function def button(pin): global show_overlay if pin == button_a: show_overlay = True return if pin == button_b: show_overlay = True return if pin == button_c: show_overlay = True return if pin == button_up: show_overlay = True return if pin == button_down: show_overlay = True return # Register the button handling function with the buttons button_a.irq(trigger=machine.Pin.IRQ_RISING, handler=button) button_b.irq(trigger=machine.Pin.IRQ_RISING, handler=button) button_c.irq(trigger=machine.Pin.IRQ_RISING, handler=button) button_up.irq(trigger=machine.Pin.IRQ_RISING, handler=button) button_down.irq(trigger=machine.Pin.IRQ_RISING, handler=button) # ------------------------------ # Main program loop # ------------------------------ draw_badge() display.update() while True: if show_overlay: draw_overlay("To change the text, connect Badger2040 to a PC, load up Thonny, and modify badge.txt", WIDTH - OVERLAY_BORDER, HEIGHT - OVERLAY_BORDER, OVERLAY_SPACING, OVERLAY_TEXT_SIZE) display.update() time.sleep(4) draw_badge() display.update() show_overlay = False time.sleep(0.1)