Created
May 14, 2022 09:53
-
-
Save ideasasylum/f78f0e27a637029981c1e68558673dce to your computer and use it in GitHub Desktop.
This is a script to present "slides" (text files) on a [Badger 2040](https://shop.pimoroni.com/products/badger-2040?variant=39752959852627)
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
image | |
images/podia-logo.bin |
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
qr | |
https://twitter.com/ideasasylum | |
@ideasasylum |
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
text | |
# Jamie Lawrence | |
CTO, Podia | |
[email protected] |
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
import time | |
import qrcode | |
import badger2040 | |
import badger_os | |
# Global Constants | |
WIDTH = badger2040.WIDTH | |
HEIGHT = badger2040.HEIGHT | |
IMAGE_WIDTH = 104 | |
HEADING_HEIGHT = 30 | |
TEXT_HEIGHT = 20 | |
#NAME_HEIGHT = HEIGHT - COMPANY_HEIGHT - (DETAILS_HEIGHT * 2) - 2 | |
TEXT_WIDTH = WIDTH | |
QR_TITLE_WIDTH = WIDTH - 140 | |
HEADING_SIZE = 0.7 | |
TEXT_SIZE = 0.5 | |
LEFT_PADDING = 5 | |
NAME_PADDING = 20 | |
DETAIL_SPACING = 10 | |
# ------------------------------ | |
# 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 | |
# ------------------------------ | |
def blank_canvas(): | |
display.pen(0) | |
display.clear() | |
display.pen(15) | |
display.rectangle(0, 0, WIDTH, HEIGHT) | |
def render_slide(): | |
# Open the badge file | |
slide = open(str(slide_number())+".txt", "r") | |
slide_template = slide.readline()[:-1] # "image" or "text" (removing \n) | |
if slide_template == "image": | |
render_image(slide) | |
elif slide_template == "text": | |
render_text(slide) | |
elif slide_template == "qr": | |
render_qr(slide) | |
else: | |
error_and_reset("No slide template for" + slide_template) | |
def error_and_reset(message): | |
badger_os.warning(display, message) | |
time.sleep(4) | |
update_slide_number(1) | |
render_slide() | |
def measure_qr_code(size, code): | |
w, h = code.get_size() | |
module_size = int(size / w) | |
return module_size * w, module_size | |
def draw_qr_code(ox, oy, size, code): | |
size, module_size = measure_qr_code(size, code) | |
display.pen(15) | |
display.rectangle(ox, oy, size, size) | |
display.pen(0) | |
for x in range(size): | |
for y in range(size): | |
if code.get_module(x, y): | |
display.rectangle(ox + x * module_size, oy + y * module_size, module_size, module_size) | |
def render_qr(slide): | |
url = slide.readline() | |
code = qrcode.QRCode() | |
blank_canvas() | |
display.pen(0) | |
code.set_text(url) | |
size, _ = measure_qr_code(128, code) | |
left = top = int((badger2040.HEIGHT / 2) - (size / 2)) | |
draw_qr_code(WIDTH-128, 0, 128, code) | |
title = slide.readline() | |
display.pen(0) | |
display.rectangle(0, 0, QR_TITLE_WIDTH, HEADING_HEIGHT) | |
display.pen(15) # Change this to 0 if a white background is used | |
display.font("sans") | |
display.thickness(3) | |
line = truncatestring(title, TEXT_SIZE, QR_TITLE_WIDTH) | |
display.text(line, LEFT_PADDING, (HEADING_HEIGHT // 2) + 1, HEADING_SIZE) | |
detail = slide.readline() | |
display.pen(0) | |
display.font("sans") | |
display.thickness(2) | |
line = truncatestring(detail, TEXT_SIZE, QR_TITLE_WIDTH) | |
display.text(line, LEFT_PADDING, HEADING_HEIGHT + (HEADING_HEIGHT // 2) + 1, HEADING_SIZE) | |
def render_image(slide): | |
image_filename = slide.readline() | |
buffer = bytearray(int(WIDTH * HEIGHT / 8)) | |
open(image_filename, "rb").readinto(buffer) | |
blank_canvas() | |
display.image(buffer, WIDTH, HEIGHT, 0, 0) | |
def render_text(slide): | |
blank_canvas() | |
line_number = 0 | |
line = slide.readline() | |
while len(line) > 1: | |
line_number += 1 | |
if line[0:2] == "# ": | |
mode = "heading" | |
line = line[2:] | |
elif line[0:2] == "- ": | |
mode = "list" | |
line = line[2:] | |
else: | |
mode = "text" | |
LINE_Y = HEADING_HEIGHT * (line_number - 1) | |
if mode == "heading": | |
# Uncomment this if a white background is wanted behind the company | |
display.pen(0) | |
display.rectangle(0, LINE_Y, TEXT_WIDTH, HEADING_HEIGHT) | |
display.pen(15) # Change this to 0 if a white background is used | |
display.font("sans") | |
display.thickness(3) | |
elif mode == "text": | |
display.pen(15) | |
display.rectangle(0, LINE_Y, TEXT_WIDTH, HEADING_HEIGHT) | |
display.pen(0) # Change this to 0 if a white background is used | |
display.font("sans") | |
display.thickness(2) | |
line = truncatestring(line, TEXT_SIZE, WIDTH) | |
display.text(line, LEFT_PADDING, LINE_Y + (HEADING_HEIGHT // 2) + 1, HEADING_SIZE) | |
line = slide.readline() | |
# ------------------------------ | |
# Program setup | |
# ------------------------------ | |
# Create a new Badger and set it to update NORMAL | |
display = badger2040.Badger2040() | |
display.led(128) | |
display.update_speed(badger2040.UPDATE_MEDIUM) | |
state = {"slide_number": 1} | |
badger_os.state_load("jamie", state) | |
def update_slide_number(num): | |
state["slide_number"] = num | |
badger_os.state_modify("jamie", state) | |
def slide_number(): | |
return state["slide_number"] | |
# ------------------------------ | |
# Main program | |
# ------------------------------ | |
while True: | |
if display.pressed(badger2040.BUTTON_A): | |
# Reset to the start | |
update_slide_number(1) | |
if display.pressed(badger2040.BUTTON_B): | |
update_slide_number(1) | |
if display.pressed(badger2040.BUTTON_C): | |
update_slide_number(1) | |
if display.pressed(badger2040.BUTTON_UP): | |
# Scroll up | |
update_slide_number(slide_number()-1) | |
if display.pressed(badger2040.BUTTON_DOWN): | |
# Scroll down | |
update_slide_number(slide_number()+1) | |
try: | |
render_slide() | |
display.update() | |
except OSError: | |
message = "No file found for slide number "+str(slide_number) | |
badger_os.warning(display, message) | |
time.sleep(4) | |
update_slide_number(1) | |
render_slide() | |
display.update() | |
# If on battery, halt the Badger to save power, it will wake up if any of the front buttons are pressed | |
display.halt() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment