feat: add fork from https://github.com/oneearedrabbit/badger-system-ii
This commit is contained in:
58
README.md
58
README.md
@@ -1,3 +1,57 @@
|
|||||||
# personal-badger
|
# Badger2040 System II
|
||||||
|
|
||||||
Personal Badger 2040 (from Pimoroni)
|
Tired of boring badges that just blend in with the crowd? You want to show off your quirky personality and love of retro technology? You are looking for a fun project to bond with your engineering team? Look no further than the programmable e-ink badge!
|
||||||
|
|
||||||
|
https://kruzenshtern.org/the-e-ink-badge-the-coolest-badge-you-didnt-know-you-needed/
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Source code
|
||||||
|
|
||||||
|
Don't expect much, but it works (tm). See in /src.
|
||||||
|
|
||||||
|
## Components
|
||||||
|
|
||||||
|
1. Badger 2040: https://shop.pimoroni.com/products/badger-2040
|
||||||
|
2. Coin Cell Battery Holder: https://www.adafruit.com/product/783
|
||||||
|
3. 2x CR2032: https://www.amazon.com/gp/product/B078GC5K81/
|
||||||
|
4. 4x M2 8mm bolts: https://www.amazon.com/gp/product/B01BNIHG0E/
|
||||||
|
5. 3D-printed case: see /case folder. I was using Prusament PLA: https://www.prusa3d.com/product/prusament-pla-ms-pink-blend-970g/
|
||||||
|
|
||||||
|
## A quick glance at assembly steps
|
||||||
|
|
||||||
|
1. 3D print top and bottom panels.
|
||||||
|
2. Disassemble & attach a 2xCR2032 battery holder
|
||||||
|
3. Assemble the badge, use hot glue whenever applicable
|
||||||
|
4. Upload pimonori-badger2040-micropython bootloader
|
||||||
|
5. Upload Python scripts
|
||||||
|
|
||||||
|
## License & acknowledgements
|
||||||
|
|
||||||
|
Inspiration sources for the case:
|
||||||
|
|
||||||
|
- https://kaenner.de/badger2040 (CC4)
|
||||||
|
- https://www.thingiverse.com/thing:5320100/files (CC4)
|
||||||
|
|
||||||
|
I ended up using an OpenSCAD blueprint by usedbytes to get measurements of the device. Reconstructed/synthesized a new case in Fusion360. Noticeable changes:
|
||||||
|
- A different battery holder / back pannel to simplify the assembly to some extent
|
||||||
|
- Two coin cells vs three
|
||||||
|
- Added hidden buttons inspired by Känner's design
|
||||||
|
- Back panel is inspired by Känner's design too, I like that connectors are accessible
|
||||||
|
- Battery toggle button
|
||||||
|
- Any mistakes are exclusively mine
|
||||||
|
|
||||||
|
Source code:
|
||||||
|
- To a large extent based on pimoroni Badger2040 OS example: https://github.com/pimoroni/pimoroni-pico/tree/main/micropython/examples/badger2040 (MIT)
|
||||||
|
- Font & rendering: custom code, but it is not worth extracting it to a standalone app/library. Let's stick with MIT for simplicity too.
|
||||||
|
|
||||||
|
Assets:
|
||||||
|
- Font: 16bfZX https://www.pentacom.jp/pentacom/bitfontmaker2/gallery/?id=246 (Public domain)
|
||||||
|
- Clippy: hand-drawn, I think the character is trademarked by Microsoft though.
|
||||||
|
- Other assets: hand-drawn
|
||||||
|
|
||||||
|
What does it mean in terms of license? I guess, it is good for a hobby project. Hire a lawyer to check if it is good for commercial use.
|
||||||
|
|
||||||
|
## From
|
||||||
|
|
||||||
|
The folks at [Census](http://getcensus.com) originally put this together. Have data? We'll sync your data warehouse with your CRM and the customer success apps critical to your team.
|
||||||
|
|||||||
1
case/.gitkeep
Normal file
1
case/.gitkeep
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
28
case/README.md
Normal file
28
case/README.md
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# 3D printed case for Badger2040
|
||||||
|
|
||||||
|
A 3D-printed case has a slot for two CR2032 batteries. Badger 2040 runs
|
||||||
|
on RPi 2040. It is energy efficient, and batteries should last for a
|
||||||
|
long time. Also comes with a battery toggle switch to shut everything down.
|
||||||
|
|
||||||
|
The device is approximately 12mm thick, see below. I lost my digital
|
||||||
|
caliper, may replace the side shot later.
|
||||||
|
|
||||||
|
## Assembly
|
||||||
|
|
||||||
|
Steps:
|
||||||
|
- 3D print top and bottom panels. PLA plastic is good enough.
|
||||||
|
- Disassemble & attach a 2xCR2032 battery holder
|
||||||
|
https://www.adafruit.com/product/783.
|
||||||
|
- Assemble the badge, use hot glue whenever applicable
|
||||||
|
|
||||||
|
## Known bugs
|
||||||
|
|
||||||
|
- A 3D model has minor misalignments that I did not bother to fix,
|
||||||
|
e.g. a LED hole is 0.1-0.2mm off to the left.
|
||||||
|
|
||||||
|
## Photos
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
BIN
case/badger2040_bottom.stl
Normal file
BIN
case/badger2040_bottom.stl
Normal file
Binary file not shown.
BIN
case/badger2040_top_mirrored.stl
Normal file
BIN
case/badger2040_top_mirrored.stl
Normal file
Binary file not shown.
1
src/.gitkeep
Normal file
1
src/.gitkeep
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
46
src/README.md
Normal file
46
src/README.md
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
# Badger2040, Apple Macintosh 1984
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This is a custom UI for Badger 2040 that I built for the Census
|
||||||
|
engineering offsite in 2022. I aimed to recreate the iconic 1984
|
||||||
|
Macintosh UI in a compact design.
|
||||||
|
|
||||||
|
## Known bugs
|
||||||
|
|
||||||
|
I had to cut some corners, so that I could finish the assembly of a small batch
|
||||||
|
before the event. Here is a list of known bugs:
|
||||||
|
- If you open the same application twice (e.g. open QR app, open Badge
|
||||||
|
app, and open QR app again), the device will restart and show a
|
||||||
|
welcome screen. I shouldn't have tried to build a multi app
|
||||||
|
experience in the first place. IMO, it is too much to do to
|
||||||
|
implement this right in Python. I think if it was Lisp environment,
|
||||||
|
it would have been easier.
|
||||||
|
- I forgot to adjust the battery voltage to calculate the battery
|
||||||
|
level. The device may show that a battery is empty or it is not
|
||||||
|
plugged in.
|
||||||
|
|
||||||
|
## Upload steps
|
||||||
|
|
||||||
|
- Upload pimonori-badger2040-micropython bootloader
|
||||||
|
- Upload Python scripts
|
||||||
|
|
||||||
|
## Edit text
|
||||||
|
|
||||||
|
- Badge: badges/badge.txt
|
||||||
|
- QR: qrcodes/qrcode.txt
|
||||||
|
- Clippy: fortune/cookie.txt
|
||||||
|
|
||||||
|
## Edit images
|
||||||
|
|
||||||
|
1. Clone https://github.com/pimoroni/pimoroni-pico
|
||||||
|
2. `python3 examples/badger2040/image_converter/convert.py --binary image.png image.bin`
|
||||||
|
3. cp image.bin badges/badge.bin
|
||||||
|
|
||||||
|
## User Guide
|
||||||
|
|
||||||
|
- A button opens Badge app
|
||||||
|
- B button opens QR app
|
||||||
|
- C button opens Special app. Up/Down buttons randomly load a new
|
||||||
|
quote
|
||||||
|
- A + C buttons open Welcome screen
|
||||||
96
src/badge_app.py
Normal file
96
src/badge_app.py
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
import badger2040
|
||||||
|
import os
|
||||||
|
import badger_os
|
||||||
|
from widgets import draw_window, pprint, ptitle, plength, button, draw_ui
|
||||||
|
|
||||||
|
IMAGE_WIDTH = 96
|
||||||
|
IMAGE_HEIGHT = 96
|
||||||
|
DELTA = 0
|
||||||
|
|
||||||
|
# Check that the badges directory exists, if not, make it
|
||||||
|
try:
|
||||||
|
os.mkdir("badges")
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Load all available badge Code Files
|
||||||
|
try:
|
||||||
|
CODES = [f for f in os.listdir("/badges") if f.endswith(".txt")]
|
||||||
|
TOTAL_CODES = len(CODES)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
print(f'There are {TOTAL_CODES} badges available:')
|
||||||
|
for codename in CODES:
|
||||||
|
print(f'File: {codename}')
|
||||||
|
|
||||||
|
display = badger2040.Badger2040()
|
||||||
|
display.update_speed(badger2040.UPDATE_NORMAL)
|
||||||
|
|
||||||
|
state = {
|
||||||
|
"running": "badge_app",
|
||||||
|
}
|
||||||
|
|
||||||
|
def draw_badge(n):
|
||||||
|
draw_window(display, 6, 26, 182, 94, " Badge ")
|
||||||
|
|
||||||
|
file = CODES[n]
|
||||||
|
codetext = open("badges/{}".format(file), "r")
|
||||||
|
|
||||||
|
lines = codetext.read().strip().split("\n")
|
||||||
|
name_text = lines.pop(0)
|
||||||
|
title_text = lines.pop(0)
|
||||||
|
company_text = lines.pop(0)
|
||||||
|
github_text = lines.pop(0)
|
||||||
|
badge_path = lines.pop(0)
|
||||||
|
|
||||||
|
ptitle(display, name_text, 15, 44, 0)
|
||||||
|
|
||||||
|
if len(github_text.strip()) > 0:
|
||||||
|
# github icon
|
||||||
|
display.image(bytearray((0x3c,0x00,0xa5,0x81,0x81,0xc3,0x66,0x84)), 8, 8, 18, 86)
|
||||||
|
display.image(bytearray((0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xfe)), 8, 8, 18, 78)
|
||||||
|
display.image(bytearray((0x03,0x03,0x03,0x03,0x03,0x02,0x01,0x00)), 8, 8, 10, 86)
|
||||||
|
display.image(bytearray((0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x01)), 8, 8, 10, 78)
|
||||||
|
|
||||||
|
pprint(display, title_text, 15, 60, 0)
|
||||||
|
pprint(display, company_text, 15, 72, 0)
|
||||||
|
pprint(display, github_text, 30, 84, 0)
|
||||||
|
|
||||||
|
badge_dat = bytearray(int(IMAGE_WIDTH * IMAGE_HEIGHT / 8))
|
||||||
|
open(f"badges/{badge_path}", "rb").readinto(badge_dat)
|
||||||
|
|
||||||
|
display.image(badge_dat, IMAGE_WIDTH, IMAGE_HEIGHT, 194, 26)
|
||||||
|
|
||||||
|
|
||||||
|
def render():
|
||||||
|
display.pen(15)
|
||||||
|
display.clear()
|
||||||
|
|
||||||
|
draw_ui(display, "Badge")
|
||||||
|
|
||||||
|
draw_badge(0)
|
||||||
|
|
||||||
|
display.update()
|
||||||
|
|
||||||
|
changed = not badger2040.woken_by_button()
|
||||||
|
|
||||||
|
while True:
|
||||||
|
if display.pressed(badger2040.BUTTON_A):
|
||||||
|
changed = True
|
||||||
|
# button(display, badger2040.BUTTON_A)
|
||||||
|
if display.pressed(badger2040.BUTTON_B):
|
||||||
|
changed = True
|
||||||
|
button(display, badger2040.BUTTON_B)
|
||||||
|
if display.pressed(badger2040.BUTTON_C):
|
||||||
|
changed = True
|
||||||
|
button(display, badger2040.BUTTON_C)
|
||||||
|
|
||||||
|
if changed:
|
||||||
|
display.led(128)
|
||||||
|
render()
|
||||||
|
badger_os.state_save("badges", state)
|
||||||
|
display.led(0)
|
||||||
|
changed = False
|
||||||
|
|
||||||
|
display.halt()
|
||||||
183
src/badger_os.py
Normal file
183
src/badger_os.py
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
"""Keep track of app state in persistent flash storage."""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import gc
|
||||||
|
import time
|
||||||
|
import json
|
||||||
|
import machine
|
||||||
|
import badger2040
|
||||||
|
|
||||||
|
def get_battery_level():
|
||||||
|
# Battery measurement
|
||||||
|
vbat_adc = machine.ADC(badger2040.PIN_BATTERY)
|
||||||
|
vref_adc = machine.ADC(badger2040.PIN_1V2_REF)
|
||||||
|
vref_en = machine.Pin(badger2040.PIN_VREF_POWER)
|
||||||
|
vref_en.init(machine.Pin.OUT)
|
||||||
|
vref_en.value(0)
|
||||||
|
|
||||||
|
# Enable the onboard voltage reference
|
||||||
|
vref_en.value(1)
|
||||||
|
|
||||||
|
# Calculate the logic supply voltage, as will be lower that the usual 3.3V when running off low batteries
|
||||||
|
vdd = 1.24 * (65535 / vref_adc.read_u16())
|
||||||
|
vbat = (
|
||||||
|
(vbat_adc.read_u16() / 65535) * 3 * vdd
|
||||||
|
) # 3 in this is a gain, not rounding of 3.3V
|
||||||
|
|
||||||
|
# Disable the onboard voltage reference
|
||||||
|
vref_en.value(0)
|
||||||
|
|
||||||
|
# Convert the voltage to a level to display onscreen
|
||||||
|
return vbat
|
||||||
|
|
||||||
|
|
||||||
|
def get_disk_usage():
|
||||||
|
# f_bfree and f_bavail should be the same?
|
||||||
|
# f_files, f_ffree, f_favail and f_flag are unsupported.
|
||||||
|
f_bsize, f_frsize, f_blocks, f_bfree, _, _, _, _, _, f_namemax = os.statvfs("/")
|
||||||
|
|
||||||
|
f_total_size = f_frsize * f_blocks
|
||||||
|
f_total_free = f_bsize * f_bfree
|
||||||
|
f_total_used = f_total_size - f_total_free
|
||||||
|
|
||||||
|
f_used = 100 / f_total_size * f_total_used
|
||||||
|
f_free = 100 / f_total_size * f_total_free
|
||||||
|
|
||||||
|
return f_total_size, f_used, f_free
|
||||||
|
|
||||||
|
|
||||||
|
def state_running():
|
||||||
|
state = {"running": "launcher"}
|
||||||
|
state_load("launcher", state)
|
||||||
|
return state["running"]
|
||||||
|
|
||||||
|
|
||||||
|
def state_clear_running():
|
||||||
|
running = state_running()
|
||||||
|
state_modify("launcher", {"running": "launcher"})
|
||||||
|
return running != "launcher"
|
||||||
|
|
||||||
|
|
||||||
|
def state_set_running(app):
|
||||||
|
state_modify("launcher", {"running": app})
|
||||||
|
|
||||||
|
|
||||||
|
def state_launch():
|
||||||
|
app = state_running()
|
||||||
|
if app is not None and app != "launcher":
|
||||||
|
launch("_" + app)
|
||||||
|
|
||||||
|
|
||||||
|
def state_delete(app):
|
||||||
|
try:
|
||||||
|
os.remove("/state/{}.json".format(app))
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def state_save(app, data):
|
||||||
|
try:
|
||||||
|
with open("/state/{}.json".format(app), "w") as f:
|
||||||
|
f.write(json.dumps(data))
|
||||||
|
f.flush()
|
||||||
|
except OSError:
|
||||||
|
import os
|
||||||
|
try:
|
||||||
|
os.stat("/state")
|
||||||
|
except OSError:
|
||||||
|
os.mkdir("/state")
|
||||||
|
state_save(app, data)
|
||||||
|
|
||||||
|
|
||||||
|
def state_modify(app, data):
|
||||||
|
state = {}
|
||||||
|
state_load(app, state)
|
||||||
|
state.update(data)
|
||||||
|
state_save(app, state)
|
||||||
|
|
||||||
|
|
||||||
|
def state_load(app, defaults):
|
||||||
|
try:
|
||||||
|
data = json.loads(open("/state/{}.json".format(app), "r").read())
|
||||||
|
if type(data) is dict:
|
||||||
|
defaults.update(data)
|
||||||
|
return True
|
||||||
|
except (OSError, ValueError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
state_save(app, defaults)
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def launch(file):
|
||||||
|
state_set_running(file[1:])
|
||||||
|
|
||||||
|
gc.collect()
|
||||||
|
|
||||||
|
button_a = machine.Pin(badger2040.BUTTON_A, machine.Pin.IN, machine.Pin.PULL_DOWN)
|
||||||
|
button_c = machine.Pin(badger2040.BUTTON_C, machine.Pin.IN, machine.Pin.PULL_DOWN)
|
||||||
|
|
||||||
|
def quit_to_launcher(pin):
|
||||||
|
if button_a.value() and button_c.value():
|
||||||
|
machine.reset()
|
||||||
|
|
||||||
|
button_a.irq(trigger=machine.Pin.IRQ_RISING, handler=quit_to_launcher)
|
||||||
|
button_c.irq(trigger=machine.Pin.IRQ_RISING, handler=quit_to_launcher)
|
||||||
|
|
||||||
|
try:
|
||||||
|
try:
|
||||||
|
__import__(file[1:]) # Try to import _[file] (drop underscore prefix)
|
||||||
|
except ImportError:
|
||||||
|
__import__(file) # Failover to importing [_file]
|
||||||
|
|
||||||
|
except ImportError:
|
||||||
|
# If the app doesn't exist, notify the user
|
||||||
|
warning(None, "Could not launch: " + file[1:])
|
||||||
|
time.sleep(4.0)
|
||||||
|
except Exception as e:
|
||||||
|
# If the app throws an error, catch it and display!
|
||||||
|
print(e)
|
||||||
|
warning(None, str(e))
|
||||||
|
time.sleep(4.0)
|
||||||
|
|
||||||
|
# If the app exits or errors, do not relaunch!
|
||||||
|
print("System error, soft reset!")
|
||||||
|
state_clear_running()
|
||||||
|
machine.reset() # Exit back to launcher
|
||||||
|
|
||||||
|
|
||||||
|
# Draw an overlay box with a given message within it
|
||||||
|
def warning(display, message, width=badger2040.WIDTH - 40, height=badger2040.HEIGHT - 40, line_spacing=20, text_size=0.6):
|
||||||
|
if display is None:
|
||||||
|
display = badger2040.Badger2040()
|
||||||
|
display.led(128)
|
||||||
|
|
||||||
|
# Draw a light grey background
|
||||||
|
display.pen(12)
|
||||||
|
display.rectangle((badger2040.WIDTH - width) // 2, (badger2040.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 = []
|
||||||
|
current_line = ""
|
||||||
|
for word in words:
|
||||||
|
if display.measure_text(current_line + word + " ", text_size) < width:
|
||||||
|
current_line += word + " "
|
||||||
|
else:
|
||||||
|
lines.append(current_line.strip())
|
||||||
|
current_line = word + " "
|
||||||
|
lines.append(current_line.strip())
|
||||||
|
|
||||||
|
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], (badger2040.WIDTH - length) // 2, (badger2040.HEIGHT // 2) + current_line, text_size)
|
||||||
|
|
||||||
|
display.update()
|
||||||
BIN
src/badges/badge.bin
Normal file
BIN
src/badges/badge.bin
Normal file
Binary file not shown.
BIN
src/badges/badge.png
Normal file
BIN
src/badges/badge.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
5
src/badges/badge.txt
Normal file
5
src/badges/badge.txt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
Kirill Timofeev
|
||||||
|
Engineering Team
|
||||||
|
Census
|
||||||
|
oneearedrabbit
|
||||||
|
badge.bin
|
||||||
1308
src/fortune/cookie.txt
Normal file
1308
src/fortune/cookie.txt
Normal file
File diff suppressed because it is too large
Load Diff
121
src/fortune_app.py
Normal file
121
src/fortune_app.py
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
import badger2040
|
||||||
|
import os
|
||||||
|
import badger_os
|
||||||
|
from widgets import draw_window, pprint, ptitle, plength, ppara, button, draw_ui
|
||||||
|
from random import random
|
||||||
|
|
||||||
|
IMAGE_WIDTH = 96
|
||||||
|
IMAGE_HEIGHT = 96
|
||||||
|
DELTA = 0
|
||||||
|
|
||||||
|
# Check that the fortune directory exists, if not, make it
|
||||||
|
try:
|
||||||
|
os.mkdir("fortune")
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
display = badger2040.Badger2040()
|
||||||
|
display.update_speed(badger2040.UPDATE_FAST)
|
||||||
|
|
||||||
|
file = "cookie.txt"
|
||||||
|
cookies = open("fortune/cookie.txt", "r").read().split("%\n")
|
||||||
|
total_cookies = len(cookies)
|
||||||
|
|
||||||
|
state = {
|
||||||
|
"running": "badge_app",
|
||||||
|
}
|
||||||
|
|
||||||
|
IMAGE_WIDTH = 64
|
||||||
|
IMAGE_HEIGHT = 64
|
||||||
|
|
||||||
|
def render():
|
||||||
|
display.pen(15)
|
||||||
|
display.thickness(1)
|
||||||
|
display.rectangle(12, 42, 222, 84)
|
||||||
|
|
||||||
|
display.pen(0)
|
||||||
|
display.thickness(1)
|
||||||
|
n = int(random()*total_cookies)
|
||||||
|
print(f"Quote {n}")
|
||||||
|
text = cookies[n].strip().replace("\n", " ").replace("\t\t", " ").replace("\t", " ")
|
||||||
|
|
||||||
|
ppara(display, text, 12, 42, 222, 0)
|
||||||
|
display.update()
|
||||||
|
|
||||||
|
def draw_clippy():
|
||||||
|
x = 1
|
||||||
|
y = 21
|
||||||
|
width = 294
|
||||||
|
height = 106
|
||||||
|
draw_window(display, x, y, width, height, " Special ")
|
||||||
|
|
||||||
|
clippy_dat = bytearray(int(IMAGE_WIDTH * IMAGE_HEIGHT / 8))
|
||||||
|
open(f"images/clippy.bin", "rb").readinto(clippy_dat)
|
||||||
|
display.image(clippy_dat, IMAGE_WIDTH, IMAGE_HEIGHT, 212, 56)
|
||||||
|
|
||||||
|
# scrollbars
|
||||||
|
display.pen(0)
|
||||||
|
display.thickness(1)
|
||||||
|
scroll_size = 14
|
||||||
|
title_height = 11
|
||||||
|
display.rectangle(x + width - scroll_size - 1, y + title_height, scroll_size + 1, scroll_size)
|
||||||
|
display.rectangle(x + width - scroll_size - 1, y + height - scroll_size, scroll_size + 1, scroll_size)
|
||||||
|
display.rectangle(x + width - scroll_size - 1, y + title_height + scroll_size, scroll_size + 1, height - title_height)
|
||||||
|
|
||||||
|
display.pen(15)
|
||||||
|
display.rectangle(x + width - scroll_size, y + title_height + 1, scroll_size - 1, scroll_size - 2)
|
||||||
|
display.rectangle(x + width - scroll_size, y + height - scroll_size + 1, scroll_size - 1, scroll_size - 2)
|
||||||
|
display.pen(12)
|
||||||
|
display.rectangle(x + width - scroll_size, y + title_height + scroll_size, scroll_size - 1, height - 2 * scroll_size - title_height)
|
||||||
|
|
||||||
|
# arrows
|
||||||
|
display.pen(0)
|
||||||
|
# top
|
||||||
|
display.line(x + width - scroll_size // 2 - 1, y + title_height + 2, x + width - scroll_size // 2 - 7, y + title_height + 8)
|
||||||
|
display.line(x + width - scroll_size // 2 - 1, y + title_height + 3, x + width - scroll_size // 2 - 6, y + title_height + 8)
|
||||||
|
display.line(x + width - scroll_size // 2 - 1, y + title_height + 2, x + width - scroll_size // 2 + 5, y + title_height + 8)
|
||||||
|
display.line(x + width - scroll_size // 2 - 1, y + title_height + 3, x + width - scroll_size // 2 + 4, y + title_height + 8)
|
||||||
|
display.line(x + width - scroll_size // 2 - 4, y + title_height + 7, x + width - scroll_size // 2 - 4, y + title_height + 12)
|
||||||
|
display.line(x + width - scroll_size // 2 + 2, y + title_height + 7, x + width - scroll_size // 2 + 2, y + title_height + 12)
|
||||||
|
display.line(x + width - scroll_size // 2 - 4, y + title_height + 11, x + width - scroll_size // 2 + 3, y + title_height + 11)
|
||||||
|
|
||||||
|
# bottom
|
||||||
|
display.line(x + width - scroll_size // 2 - 1, y + height - 3, x + width - scroll_size // 2 - 7, y + height - 9)
|
||||||
|
display.line(x + width - scroll_size // 2 - 1, y + height - 4, x + width - scroll_size // 2 - 6, y + height - 9)
|
||||||
|
display.line(x + width - scroll_size // 2 - 1, y + height - 3, x + width - scroll_size // 2 + 5, y + height - 9)
|
||||||
|
display.line(x + width - scroll_size // 2 - 1, y + height - 4, x + width - scroll_size // 2 + 4, y + height - 9)
|
||||||
|
display.line(x + width - scroll_size // 2 - 4, y + height - 8, x + width - scroll_size // 2 - 4, y + height - 13)
|
||||||
|
display.line(x + width - scroll_size // 2 + 2, y + height - 8, x + width - scroll_size // 2 + 2, y + height - 13)
|
||||||
|
display.line(x + width - scroll_size // 2 - 4, y + height - 12, x + width - scroll_size // 2 + 3, y + height - 12)
|
||||||
|
|
||||||
|
def draw_elements():
|
||||||
|
display.pen(15)
|
||||||
|
display.clear()
|
||||||
|
|
||||||
|
draw_ui(display, "Special")
|
||||||
|
|
||||||
|
draw_clippy()
|
||||||
|
|
||||||
|
changed = not badger2040.woken_by_button()
|
||||||
|
|
||||||
|
draw_elements()
|
||||||
|
|
||||||
|
while True:
|
||||||
|
if display.pressed(badger2040.BUTTON_A):
|
||||||
|
changed = True
|
||||||
|
button(display, badger2040.BUTTON_A)
|
||||||
|
if display.pressed(badger2040.BUTTON_B):
|
||||||
|
changed = True
|
||||||
|
button(display, badger2040.BUTTON_B)
|
||||||
|
if display.pressed(badger2040.BUTTON_C) or display.pressed(badger2040.BUTTON_UP) or display.pressed(badger2040.BUTTON_DOWN):
|
||||||
|
changed = True
|
||||||
|
# button(display, badger2040.BUTTON_C)
|
||||||
|
|
||||||
|
if changed:
|
||||||
|
display.led(128)
|
||||||
|
render()
|
||||||
|
badger_os.state_save("fortune", state)
|
||||||
|
display.led(0)
|
||||||
|
changed = False
|
||||||
|
|
||||||
|
display.halt()
|
||||||
1
src/images/background.bin
Normal file
1
src/images/background.bin
Normal file
@@ -0,0 +1 @@
|
|||||||
|
33333333333333333333333333333333333333333333333333333333333333333333333333<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>33333333333333333333333333333333333333333333333333333333333333333333333333<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>33333333333333333333333333333333333333333333333333333333333333333333333333<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>33333333333333333333333333333333333333333333333333333333333333333333333333<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>33333333333333333333333333333333333333333333333333333333333333333333333333<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>33333333333333333333333333333333333333333333333333333333333333333333333333<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>33333333333333333333333333333333333333333333333333333333333333333333333333<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>33333333333333333333333333333333333333333333333333333333333333333333333333<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>33333333333333333333333333333333333333333333333333333333333333333333333333<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>33333333333333333333333333333333333333333333333333333333333333333333333333<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>33333333333333333333333333333333333333333333333333333333333333333333333333<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>33333333333333333333333333333333333333333333333333333333333333333333333333<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>33333333333333333333333333333333333333333333333333333333333333333333333333<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>33333333333333333333333333333333333333333333333333333333333333333333333333<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>33333333333333333333333333333333333333333333333333333333333333333333333333<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>33333333333333333333333333333333333333333333333333333333333333333333333333<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>33333333333333333333333333333333333333333333333333333333333333333333333333<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>33333333333333333333333333333333333333333333333333333333333333333333333333<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>33333333333333333333333333333333333333333333333333333333333333333333333333<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>33333333333333333333333333333333333333333333333333333333333333333333333333<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>33333333333333333333333333333333333333333333333333333333333333333333333333<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>33333333333333333333333333333333333333333333333333333333333333333333333333<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>33333333333333333333333333333333333333333333333333333333333333333333333333<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>33333333333333333333333333333333333333333333333333333333333333333333333333<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>33333333333333333333333333333333333333333333333333333333333333333333333333<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>33333333333333333333333333333333333333333333333333333333333333333333333333<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>33333333333333333333333333333333333333333333333333333333333333333333333333<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>33333333333333333333333333333333333333333333333333333333333333333333333333<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>33333333333333333333333333333333333333333333333333333333333333333333333333<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>33333333333333333333333333333333333333333333333333333333333333333333333333<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>33333333333333333333333333333333333333333333333333333333333333333333333333<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>33333333333333333333333333333333333333333333333333333333333333333333333333<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
BIN
src/images/background.png
Normal file
BIN
src/images/background.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 716 B |
BIN
src/images/census.bin
Normal file
BIN
src/images/census.bin
Normal file
Binary file not shown.
BIN
src/images/census.png
Normal file
BIN
src/images/census.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 192 B |
BIN
src/images/clippy.bin
Normal file
BIN
src/images/clippy.bin
Normal file
Binary file not shown.
BIN
src/images/clippy.png
Normal file
BIN
src/images/clippy.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 788 B |
86
src/launcher.py
Normal file
86
src/launcher.py
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
import badger2040
|
||||||
|
import badger_os
|
||||||
|
from widgets import draw_window, pprint, button, wait_for_user_to_release_buttons, draw_ui
|
||||||
|
|
||||||
|
# Reduce clock speed to 48MHz
|
||||||
|
badger2040.system_speed(badger2040.SYSTEM_NORMAL)
|
||||||
|
|
||||||
|
changed = False
|
||||||
|
exited_to_launcher = False
|
||||||
|
woken_by_button = badger2040.woken_by_button() # Must be done before we clear_pressed_to_wake
|
||||||
|
|
||||||
|
if badger2040.pressed_to_wake(badger2040.BUTTON_A) and badger2040.pressed_to_wake(badger2040.BUTTON_C):
|
||||||
|
# Pressing A and C together at start quits app
|
||||||
|
exited_to_launcher = badger_os.state_clear_running()
|
||||||
|
else:
|
||||||
|
# Otherwise restore previously running app
|
||||||
|
badger_os.state_launch()
|
||||||
|
|
||||||
|
display = badger2040.Badger2040()
|
||||||
|
display.led(128)
|
||||||
|
|
||||||
|
state = {
|
||||||
|
"running": "launcher",
|
||||||
|
}
|
||||||
|
|
||||||
|
badger_os.state_load("launcher", state)
|
||||||
|
|
||||||
|
def draw_about():
|
||||||
|
x = 78
|
||||||
|
y = 39
|
||||||
|
width = 144
|
||||||
|
height = 63
|
||||||
|
draw_window(display, x, y, width, height, " Welcome ")
|
||||||
|
|
||||||
|
# logo
|
||||||
|
image = bytearray(int(32 * 32 / 8))
|
||||||
|
open("images/{}".format("census.bin"), "r").readinto(image)
|
||||||
|
display.image(image, 32, 32, 86, 56)
|
||||||
|
|
||||||
|
pprint(display, "Engineering", 125, 56, 0)
|
||||||
|
pprint(display, "Offsite", 125, 66, 0)
|
||||||
|
pprint(display, "Brooklyn", 125, 76, 0)
|
||||||
|
pprint(display, "2022", 125, 86, 0)
|
||||||
|
|
||||||
|
def render():
|
||||||
|
display.pen(15)
|
||||||
|
display.clear()
|
||||||
|
|
||||||
|
draw_ui(display, "About")
|
||||||
|
|
||||||
|
draw_about()
|
||||||
|
|
||||||
|
display.update()
|
||||||
|
|
||||||
|
if exited_to_launcher or not woken_by_button:
|
||||||
|
wait_for_user_to_release_buttons(display)
|
||||||
|
display.update_speed(badger2040.UPDATE_NORMAL)
|
||||||
|
render()
|
||||||
|
display.led(0)
|
||||||
|
|
||||||
|
display.update_speed(badger2040.UPDATE_NORMAL)
|
||||||
|
|
||||||
|
# Save power, do NOT render screen every time
|
||||||
|
while True:
|
||||||
|
if display.pressed(badger2040.BUTTON_A):
|
||||||
|
changed = True
|
||||||
|
button(display, badger2040.BUTTON_A)
|
||||||
|
if display.pressed(badger2040.BUTTON_B):
|
||||||
|
changed = True
|
||||||
|
button(display, badger2040.BUTTON_B)
|
||||||
|
if display.pressed(badger2040.BUTTON_C):
|
||||||
|
changed = True
|
||||||
|
button(display, badger2040.BUTTON_C)
|
||||||
|
|
||||||
|
# if display.pressed(badger2040.BUTTON_UP):
|
||||||
|
# button(display, badger2040.BUTTON_UP)
|
||||||
|
# if display.pressed(badger2040.BUTTON_DOWN):
|
||||||
|
# button(display, badger2040.BUTTON_DOWN)
|
||||||
|
|
||||||
|
if changed:
|
||||||
|
badger_os.state_save("launcher", state)
|
||||||
|
changed = False
|
||||||
|
|
||||||
|
# Halt the Badger to save power, it will wake up if any of the front buttons are pressed
|
||||||
|
display.halt()
|
||||||
|
|
||||||
1
src/main.py
Normal file
1
src/main.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
import launcher
|
||||||
134
src/qr_app.py
Normal file
134
src/qr_app.py
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
import badger2040
|
||||||
|
import qrcode
|
||||||
|
import os
|
||||||
|
import badger_os
|
||||||
|
from widgets import draw_window, pprint, ptitle, plength, button, draw_ui
|
||||||
|
|
||||||
|
# Check that the qrcodes directory exists, if not, make it
|
||||||
|
try:
|
||||||
|
os.mkdir("qrcodes")
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Load all available QR Code Files
|
||||||
|
try:
|
||||||
|
CODES = [f for f in os.listdir("/qrcodes") if f.endswith(".txt")]
|
||||||
|
TOTAL_CODES = len(CODES)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
print(f'There are {TOTAL_CODES} QR Codes available:')
|
||||||
|
for codename in CODES:
|
||||||
|
print(f'File: {codename}')
|
||||||
|
|
||||||
|
display = badger2040.Badger2040()
|
||||||
|
|
||||||
|
code = qrcode.QRCode()
|
||||||
|
|
||||||
|
|
||||||
|
state = {
|
||||||
|
"running": "qr_app",
|
||||||
|
"current_qr": 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 draw_qr_file(n):
|
||||||
|
draw_window(display, 6, 26, 282, 94, " About us ")
|
||||||
|
|
||||||
|
file = CODES[n]
|
||||||
|
codetext = open("qrcodes/{}".format(file), "r")
|
||||||
|
|
||||||
|
lines = codetext.read().strip().split("\n")
|
||||||
|
code_text = lines.pop(0)
|
||||||
|
title_text = lines.pop(0)
|
||||||
|
detail_text = lines
|
||||||
|
|
||||||
|
display.pen(0)
|
||||||
|
|
||||||
|
code.set_text(code_text)
|
||||||
|
size, _ = measure_qr_code(128, code)
|
||||||
|
draw_qr_code(10, 41, 80, code)
|
||||||
|
|
||||||
|
left = 96
|
||||||
|
|
||||||
|
display.thickness(2)
|
||||||
|
ptitle(display, title_text, left, 40, 0)
|
||||||
|
display.thickness(1)
|
||||||
|
|
||||||
|
top = 56
|
||||||
|
for line in detail_text:
|
||||||
|
pprint(display, line, left, top, 0)
|
||||||
|
top += 10
|
||||||
|
|
||||||
|
if TOTAL_CODES > 1:
|
||||||
|
for i in range(TOTAL_CODES):
|
||||||
|
x = 286
|
||||||
|
y = int((128 / 2) - (TOTAL_CODES * 10 / 2) + (i * 10))
|
||||||
|
display.pen(0)
|
||||||
|
display.rectangle(x, y, 8, 8)
|
||||||
|
if state["current_qr"] != i:
|
||||||
|
display.pen(15)
|
||||||
|
display.rectangle(x + 1, y + 1, 6, 6)
|
||||||
|
|
||||||
|
def render():
|
||||||
|
display.pen(15)
|
||||||
|
display.clear()
|
||||||
|
|
||||||
|
draw_ui(display, "QR")
|
||||||
|
|
||||||
|
draw_qr_file(state["current_qr"])
|
||||||
|
|
||||||
|
display.update()
|
||||||
|
|
||||||
|
badger_os.state_load("qrcodes", state)
|
||||||
|
changed = not badger2040.woken_by_button()
|
||||||
|
|
||||||
|
while True:
|
||||||
|
if TOTAL_CODES > 1:
|
||||||
|
if display.pressed(badger2040.BUTTON_UP):
|
||||||
|
if state["current_qr"] > 0:
|
||||||
|
state["current_qr"] -= 1
|
||||||
|
changed = True
|
||||||
|
|
||||||
|
if display.pressed(badger2040.BUTTON_DOWN):
|
||||||
|
if state["current_qr"] < TOTAL_CODES - 1:
|
||||||
|
state["current_qr"] += 1
|
||||||
|
changed = True
|
||||||
|
|
||||||
|
if display.pressed(badger2040.BUTTON_A):
|
||||||
|
changed = True
|
||||||
|
button(display, badger2040.BUTTON_A)
|
||||||
|
if display.pressed(badger2040.BUTTON_B):
|
||||||
|
changed = True
|
||||||
|
# button(display, badger2040.BUTTON_B)
|
||||||
|
if display.pressed(badger2040.BUTTON_C):
|
||||||
|
changed = True
|
||||||
|
button(display, badger2040.BUTTON_C)
|
||||||
|
|
||||||
|
if changed:
|
||||||
|
display.led(128)
|
||||||
|
render()
|
||||||
|
badger_os.state_save("qrcodes", state)
|
||||||
|
display.led(0)
|
||||||
|
changed = False
|
||||||
|
|
||||||
|
# Halt the Badger to save power, it will wake up if any of the front buttons are pressed
|
||||||
|
display.halt()
|
||||||
8
src/qrcodes/qrcode.txt
Normal file
8
src/qrcodes/qrcode.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
https://getcensus.com/
|
||||||
|
Census
|
||||||
|
* the leading reverse ETL
|
||||||
|
* no more CSV files
|
||||||
|
* sync data in real-time
|
||||||
|
|
||||||
|
Scan this code to learn
|
||||||
|
more about Census.
|
||||||
321
src/widgets.py
Normal file
321
src/widgets.py
Normal file
@@ -0,0 +1,321 @@
|
|||||||
|
import badger_os
|
||||||
|
import badger2040
|
||||||
|
import time
|
||||||
|
import gc
|
||||||
|
from badger2040 import WIDTH
|
||||||
|
|
||||||
|
# for e.g. 2xAAA batteries, try max 3.4 min 3.0
|
||||||
|
MAX_BATTERY_VOLTAGE = 3.4
|
||||||
|
MIN_BATTERY_VOLTAGE = 3.0
|
||||||
|
|
||||||
|
font_table = {
|
||||||
|
' ': (0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ), # 0x20 32
|
||||||
|
'!': (0x00,0x00,0x03,0x03,0x03,0x03,0x00,0x03,0x00,0x00 ), # 0x21 33
|
||||||
|
'"': (0x00,0x00,0x1B,0x1B,0x12,0x00,0x00,0x00,0x00,0x00 ), # 0x22 34
|
||||||
|
'#': (0x00,0x00,0x36,0x7F,0x36,0x36,0x7F,0x36,0x00,0x00 ), # 0x23 35
|
||||||
|
'$': (0x00,0x0C,0x3E,0x0F,0x1E,0x3C,0x3F,0x1E,0x0C,0x00 ), # 0x24 36
|
||||||
|
'%': (0x00,0x00,0x63,0x33,0x18,0x0C,0x66,0x63,0x00,0x00 ), # 0x25 37
|
||||||
|
'&': (0x00,0x00,0x1E,0x33,0x1E,0x3F,0x1B,0x3E,0x00,0x00 ), # 0x26 38
|
||||||
|
"'": (0x00,0x00,0x03,0x03,0x02,0x00,0x00,0x00,0x00,0x00 ), # 0x27 39
|
||||||
|
'(': (0x00,0x06,0x03,0x03,0x03,0x03,0x03,0x03,0x06,0x00 ), # 0x28 40
|
||||||
|
')': (0x00,0x03,0x06,0x06,0x06,0x06,0x06,0x06,0x03,0x00 ), # 0x29 41
|
||||||
|
'*': (0x00,0x00,0x00,0x33,0x1E,0x1E,0x33,0x00,0x00,0x00 ), # 0x2A 42
|
||||||
|
'+': (0x00,0x00,0x0C,0x0C,0x3F,0x0C,0x0C,0x00,0x00,0x00 ), # 0x2B 43
|
||||||
|
',': (0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x02,0x00 ), # 0x2C 44
|
||||||
|
'-': (0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,0x00 ), # 0x2D 45
|
||||||
|
'.': (0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x00,0x00 ), # 0x2E 46
|
||||||
|
'/': (0x00,0x40,0x60,0x30,0x18,0x0C,0x06,0x03,0x01,0x00 ), # 0x2F 47
|
||||||
|
'0': (0x00,0x00,0x1E,0x33,0x33,0x33,0x33,0x1E,0x00,0x00 ), # 0x30 48
|
||||||
|
'1': (0x00,0x00,0x06,0x07,0x06,0x06,0x06,0x0F,0x00,0x00 ), # 0x31 49
|
||||||
|
'2': (0x00,0x00,0x1E,0x33,0x30,0x1E,0x03,0x3F,0x00,0x00 ), # 0x32 50
|
||||||
|
'3': (0x00,0x00,0x1E,0x33,0x18,0x30,0x33,0x1E,0x00,0x00 ), # 0x33 51
|
||||||
|
'4': (0x00,0x00,0x18,0x1C,0x1E,0x1B,0x3F,0x18,0x00,0x00 ), # 0x34 52
|
||||||
|
'5': (0x00,0x00,0x3F,0x03,0x1F,0x30,0x33,0x1E,0x00,0x00 ), # 0x35 53
|
||||||
|
'6': (0x00,0x00,0x1E,0x03,0x1F,0x33,0x33,0x1E,0x00,0x00 ), # 0x36 54
|
||||||
|
'7': (0x00,0x00,0x3F,0x30,0x18,0x0C,0x0C,0x0C,0x00,0x00 ), # 0x37 55
|
||||||
|
'8': (0x00,0x00,0x1E,0x33,0x1E,0x33,0x33,0x1E,0x00,0x00 ), # 0x38 56
|
||||||
|
'9': (0x00,0x00,0x1E,0x33,0x33,0x3E,0x30,0x1E,0x00,0x00 ), # 0x39 57
|
||||||
|
':': (0x00,0x00,0x00,0x03,0x03,0x00,0x03,0x03,0x00,0x00 ), # 0x3A 58
|
||||||
|
';': (0x00,0x00,0x00,0x03,0x03,0x00,0x03,0x03,0x02,0x00 ), # 0x3B 59
|
||||||
|
'<': (0x00,0x18,0x0C,0x06,0x03,0x06,0x0C,0x18,0x00,0x00 ), # 0x3C 60
|
||||||
|
'=': (0x00,0x00,0x00,0x3F,0x00,0x3F,0x00,0x00,0x00,0x00 ), # 0x3D 61
|
||||||
|
'>': (0x00,0x03,0x06,0x0C,0x18,0x0C,0x06,0x03,0x00,0x00 ), # 0x3E 62
|
||||||
|
'?': (0x00,0x00,0x1E,0x33,0x18,0x0C,0x00,0x0C,0x00,0x00 ), # 0x3F 63
|
||||||
|
'@': (0x7E,0xC3,0x3B,0xEF,0xEF,0xFB,0xC3,0x7E,0x00,0x00 ), # 0x40 64
|
||||||
|
'A': (0x00,0x00,0x1E,0x33,0x33,0x3F,0x33,0x33,0x00,0x00 ), # 0x41 65
|
||||||
|
'B': (0x00,0x00,0x1F,0x33,0x1F,0x33,0x33,0x1F,0x00,0x00 ), # 0x42 66
|
||||||
|
'C': (0x00,0x00,0x1E,0x33,0x03,0x03,0x33,0x1E,0x00,0x00 ), # 0x43 67
|
||||||
|
'D': (0x00,0x00,0x1F,0x33,0x33,0x33,0x33,0x1F,0x00,0x00 ), # 0x44 68
|
||||||
|
'E': (0x00,0x00,0x3F,0x03,0x0F,0x03,0x03,0x3F,0x00,0x00 ), # 0x45 69
|
||||||
|
'F': (0x00,0x00,0x3F,0x03,0x0F,0x03,0x03,0x03,0x00,0x00 ), # 0x46 70
|
||||||
|
'G': (0x00,0x00,0x1E,0x33,0x03,0x3B,0x33,0x1E,0x00,0x00 ), # 0x47 71
|
||||||
|
'H': (0x00,0x00,0x33,0x33,0x3F,0x33,0x33,0x33,0x00,0x00 ), # 0x48 72
|
||||||
|
'I': (0x00,0x00,0x0F,0x06,0x06,0x06,0x06,0x0F,0x00,0x00 ), # 0x49 73
|
||||||
|
'J': (0x00,0x00,0x30,0x30,0x30,0x30,0x33,0x1E,0x00,0x00 ), # 0x4A 74
|
||||||
|
'K': (0x00,0x00,0x33,0x1B,0x0F,0x0F,0x1B,0x33,0x00,0x00 ), # 0x4B 75
|
||||||
|
'L': (0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x3F,0x00,0x00 ), # 0x4C 76
|
||||||
|
'M': (0x00,0x00,0xC3,0xE7,0xFF,0xDB,0xC3,0xC3,0x00,0x00 ), # 0x4D 77
|
||||||
|
'N': (0x00,0x00,0x33,0x37,0x3F,0x3B,0x33,0x33,0x00,0x00 ), # 0x4E 78
|
||||||
|
'O': (0x00,0x00,0x1E,0x33,0x33,0x33,0x33,0x1E,0x00,0x00 ), # 0x4F 79
|
||||||
|
'P': (0x00,0x00,0x1F,0x33,0x33,0x1F,0x03,0x03,0x00,0x00 ), # 0x50 80
|
||||||
|
'Q': (0x00,0x00,0x1E,0x33,0x33,0x33,0x1B,0x36,0x00,0x00 ), # 0x51 81
|
||||||
|
'R': (0x00,0x00,0x1F,0x33,0x33,0x1F,0x1B,0x33,0x00,0x00 ), # 0x52 82
|
||||||
|
'S': (0x00,0x00,0x1E,0x03,0x1E,0x30,0x33,0x1E,0x00,0x00 ), # 0x53 83
|
||||||
|
'T': (0x00,0x00,0x3F,0x0C,0x0C,0x0C,0x0C,0x0C,0x00,0x00 ), # 0x54 84
|
||||||
|
'U': (0x00,0x00,0x33,0x33,0x33,0x33,0x33,0x1E,0x00,0x00 ), # 0x55 85
|
||||||
|
'V': (0x00,0x00,0x33,0x33,0x33,0x33,0x1E,0x0C,0x00,0x00 ), # 0x56 86
|
||||||
|
'W': (0x00,0x00,0xC3,0xDB,0xDB,0xDB,0xDB,0x7E,0x00,0x00 ), # 0x57 87
|
||||||
|
'X': (0x00,0x00,0x33,0x1E,0x0C,0x0C,0x1E,0x33,0x00,0x00 ), # 0x58 88
|
||||||
|
'Y': (0x00,0x00,0x33,0x33,0x33,0x1E,0x0C,0x0C,0x00,0x00 ), # 0x59 89
|
||||||
|
'Z': (0x00,0x00,0x3F,0x38,0x1C,0x0E,0x07,0x3F,0x00,0x00 ), # 0x5A 90
|
||||||
|
'[': (0x00,0x0F,0x03,0x03,0x03,0x03,0x03,0x03,0x0F,0x00 ), # 0x5B 91
|
||||||
|
'\\': (0x00,0x01,0x03,0x06,0x0C,0x18,0x30,0x60,0x40,0x00 ), # 0x5C 92
|
||||||
|
']': (0x00,0x0F,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0F,0x00 ), # 0x5D 93
|
||||||
|
'^': (0x00,0x00,0x0C,0x1E,0x33,0x00,0x00,0x00,0x00,0x00 ), # 0x5E 94
|
||||||
|
'_': (0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00 ), # 0x5F 95
|
||||||
|
'`': (0x00,0x00,0x03,0x03,0x02,0x00,0x00,0x00,0x00,0x00 ), # 0x60 96
|
||||||
|
'a': (0x00,0x00,0x00,0x1E,0x30,0x3E,0x33,0x3E,0x00,0x00 ), # 0x61 97
|
||||||
|
'b': (0x00,0x00,0x03,0x1F,0x33,0x33,0x33,0x1F,0x00,0x00 ), # 0x62 98
|
||||||
|
'c': (0x00,0x00,0x00,0x1E,0x33,0x03,0x33,0x1E,0x00,0x00 ), # 0x63 99
|
||||||
|
'd': (0x00,0x00,0x30,0x3E,0x33,0x33,0x33,0x3E,0x00,0x00 ), # 0x64 100
|
||||||
|
'e': (0x00,0x00,0x00,0x1E,0x33,0x1F,0x03,0x1E,0x00,0x00 ), # 0x65 101
|
||||||
|
'f': (0x00,0x00,0x0E,0x03,0x0F,0x03,0x03,0x03,0x00,0x00 ), # 0x66 102
|
||||||
|
'g': (0x00,0x00,0x00,0x3E,0x33,0x33,0x3E,0x30,0x1E,0x00 ), # 0x67 103
|
||||||
|
'h': (0x00,0x00,0x03,0x1F,0x33,0x33,0x33,0x33,0x00,0x00 ), # 0x68 104
|
||||||
|
'i': (0x00,0x00,0x03,0x00,0x03,0x03,0x03,0x03,0x00,0x00 ), # 0x69 105
|
||||||
|
'j': (0x00,0x00,0x06,0x00,0x06,0x06,0x06,0x06,0x03,0x00 ), # 0x6A 106
|
||||||
|
'k': (0x00,0x00,0x03,0x33,0x1B,0x0F,0x1B,0x33,0x00,0x00 ), # 0x6B 107
|
||||||
|
'l': (0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x06,0x00,0x00 ), # 0x6C 108
|
||||||
|
'm': (0x00,0x00,0x00,0x7F,0xDB,0xDB,0xDB,0xDB,0x00,0x00 ), # 0x6D 109
|
||||||
|
'n': (0x00,0x00,0x00,0x1F,0x33,0x33,0x33,0x33,0x00,0x00 ), # 0x6E 110
|
||||||
|
'o': (0x00,0x00,0x00,0x1E,0x33,0x33,0x33,0x1E,0x00,0x00 ), # 0x6F 111
|
||||||
|
'p': (0x00,0x00,0x00,0x1F,0x33,0x33,0x33,0x1F,0x03,0x00 ), # 0x70 112
|
||||||
|
'q': (0x00,0x00,0x00,0x3E,0x33,0x33,0x33,0x3E,0x30,0x00 ), # 0x71 113
|
||||||
|
'r': (0x00,0x00,0x00,0x0E,0x03,0x03,0x03,0x03,0x00,0x00 ), # 0x72 114
|
||||||
|
's': (0x00,0x00,0x00,0x1E,0x03,0x1E,0x30,0x1F,0x00,0x00 ), # 0x73 115
|
||||||
|
't': (0x00,0x00,0x06,0x0F,0x06,0x06,0x06,0x0C,0x00,0x00 ), # 0x74 116
|
||||||
|
'u': (0x00,0x00,0x00,0x33,0x33,0x33,0x33,0x1E,0x00,0x00 ), # 0x75 117
|
||||||
|
'v': (0x00,0x00,0x00,0x33,0x33,0x33,0x1E,0x0C,0x00,0x00 ), # 0x76 118
|
||||||
|
'w': (0x00,0x00,0x00,0xC3,0xDB,0xDB,0xDB,0x7E,0x00,0x00 ), # 0x77 119
|
||||||
|
'x': (0x00,0x00,0x00,0x33,0x1E,0x0C,0x1E,0x33,0x00,0x00 ), # 0x78 120
|
||||||
|
'y': (0x00,0x00,0x00,0x33,0x33,0x33,0x3E,0x30,0x1E,0x00 ), # 0x79 121
|
||||||
|
'z': (0x00,0x00,0x00,0x3F,0x18,0x0C,0x06,0x3F,0x00,0x00 ), # 0x7A 122
|
||||||
|
'(': (0x00,0x0C,0x06,0x06,0x03,0x03,0x06,0x06,0x0C,0x00 ), # 0x7B 123
|
||||||
|
'|': (0x00,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x00 ), # 0x7C 124
|
||||||
|
')': (0x00,0x03,0x06,0x06,0x0C,0x0C,0x06,0x06,0x03,0x00 ), # 0x7D 125
|
||||||
|
'~': (0x00,0x00,0x00,0x00,0x6E,0x3B,0x00,0x00,0x00,0x00 ) # 0x7E 126
|
||||||
|
}
|
||||||
|
|
||||||
|
def reverse_mask(x):
|
||||||
|
x = ((x & 0x55) << 1) | ((x & 0xAA) >> 1)
|
||||||
|
x = ((x & 0x33) << 2) | ((x & 0xCC) >> 2)
|
||||||
|
x = ((x & 0x0F) << 4) | ((x & 0xF0) >> 4)
|
||||||
|
return x
|
||||||
|
|
||||||
|
def get_char(c):
|
||||||
|
try:
|
||||||
|
char = font_table[c]
|
||||||
|
except KeyError:
|
||||||
|
print(f"Unrecognized char: {c}")
|
||||||
|
char = font_table[" "]
|
||||||
|
return char
|
||||||
|
|
||||||
|
def plength(para):
|
||||||
|
# This could be precalculated, but I am lazy
|
||||||
|
total = 0
|
||||||
|
for c in para:
|
||||||
|
char = get_char(c)
|
||||||
|
width = sum(1 for i in [sum(1 for i in [x & mask for x in char] if i > 0) for mask in [128, 64, 32, 16, 8, 4, 2, 1]] if i > 0)
|
||||||
|
total += 5 if width == 0 else width + 1
|
||||||
|
return total
|
||||||
|
|
||||||
|
def pprint(display, para, x, y, col):
|
||||||
|
offset = 0
|
||||||
|
display.thickness(1)
|
||||||
|
|
||||||
|
if col == 0:
|
||||||
|
display.pen(15)
|
||||||
|
else:
|
||||||
|
display.pen(0)
|
||||||
|
|
||||||
|
for c in para:
|
||||||
|
if col == 1:
|
||||||
|
char = [~x & 0xFF for x in get_char(c)]
|
||||||
|
else:
|
||||||
|
char = get_char(c)
|
||||||
|
|
||||||
|
display.image(bytearray([reverse_mask(x) for x in char]), 8, 10, x + offset, y)
|
||||||
|
display.rectangle(x + offset - 1, y, 1, 10)
|
||||||
|
|
||||||
|
offset += plength(c)
|
||||||
|
|
||||||
|
def ppara(display, para, x, y, width, col):
|
||||||
|
line = ""
|
||||||
|
base_x = x
|
||||||
|
length = 0
|
||||||
|
for c in para:
|
||||||
|
clength = plength(c)
|
||||||
|
if clength + length > width:
|
||||||
|
pprint(display, line, x, y, col)
|
||||||
|
y += 10
|
||||||
|
length = 0
|
||||||
|
x = base_x
|
||||||
|
line = ""
|
||||||
|
|
||||||
|
length += clength
|
||||||
|
line += c
|
||||||
|
|
||||||
|
pprint(display, line, x, y, col)
|
||||||
|
|
||||||
|
def ptitle(display, para, x, y, col):
|
||||||
|
pprint(display, para, x, y, 0)
|
||||||
|
|
||||||
|
display.thickness(2)
|
||||||
|
display.pen(0)
|
||||||
|
display.line(x, y + 10, x + plength(para), y + 10)
|
||||||
|
|
||||||
|
def draw_background(display):
|
||||||
|
display.pen(0)
|
||||||
|
display.thickness(1)
|
||||||
|
|
||||||
|
for y in range(11, 63):
|
||||||
|
for x in range(1, 147, 2):
|
||||||
|
display.rectangle(x * 2 + (2 if y % 2 == 0 else 0), y * 2, 2, 2)
|
||||||
|
|
||||||
|
# image = bytearray(int(296 * 128 / 8))
|
||||||
|
# open("images/{}".format("background.bin"), "r").readinto(image)
|
||||||
|
# display.image(image, 296, 128, 0, 0)
|
||||||
|
|
||||||
|
def draw_menu(display, selected):
|
||||||
|
menu = "Badge QR Special About"
|
||||||
|
|
||||||
|
# logo
|
||||||
|
display.pen(0)
|
||||||
|
display.thickness(1)
|
||||||
|
|
||||||
|
x = 12
|
||||||
|
y = 6
|
||||||
|
display.line(x + 2, y, x + 8, y)
|
||||||
|
display.line(x + 6, y + 1, x + 9, y + 1)
|
||||||
|
display.line(x + 1, y + 2, x + 10, y + 2)
|
||||||
|
display.line(x + 5, y + 3, x + 10, y + 3)
|
||||||
|
display.line(x, y + 4, x + 10, y + 4)
|
||||||
|
display.line(x + 5, y + 5, x + 10, y + 5)
|
||||||
|
display.line(x + 1, y + 6, x + 10, y + 6)
|
||||||
|
display.line(x + 6, y + 7, x + 9, y + 7)
|
||||||
|
display.line(x + 2, y + 8, x + 8, y + 8)
|
||||||
|
|
||||||
|
x = 40
|
||||||
|
pprint(display, menu, x, 6, 0)
|
||||||
|
|
||||||
|
# selected
|
||||||
|
display.pen(0)
|
||||||
|
offset = plength(menu.split(selected)[0])
|
||||||
|
display.rectangle(x + offset - 7, 3, plength(selected) + 13, 17)
|
||||||
|
pprint(display, selected, x + offset, 6, 1)
|
||||||
|
|
||||||
|
display.pen(0)
|
||||||
|
display.thickness(2)
|
||||||
|
display.line(1, 21, 295, 21)
|
||||||
|
|
||||||
|
def draw_border(display):
|
||||||
|
display.pen(0)
|
||||||
|
display.thickness(2)
|
||||||
|
|
||||||
|
display.line(1, 1, 295, 1)
|
||||||
|
display.line(1, 1, 1, 127)
|
||||||
|
display.line(1, 127, 295, 127)
|
||||||
|
display.line(295, 1, 295, 127)
|
||||||
|
display.image(bytearray((0xff, 0xff, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0xc0)), 8, 8, 0, 0)
|
||||||
|
display.image(bytearray((0xff, 0xff, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x03)), 8, 8, 288, 0)
|
||||||
|
display.image(bytearray((0x03, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0xff, 0xff)), 8, 8, 288, 120)
|
||||||
|
display.image(bytearray((0xc0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xff, 0xff)), 8, 8, 0, 120)
|
||||||
|
|
||||||
|
def map_value(input, in_min, in_max, out_min, out_max):
|
||||||
|
return (((input - in_min) * (out_max - out_min)) / (in_max - in_min)) + out_min
|
||||||
|
|
||||||
|
def draw_battery(display, x, y):
|
||||||
|
vbat = badger_os.get_battery_level()
|
||||||
|
level = int(map_value(vbat, MIN_BATTERY_VOLTAGE, MAX_BATTERY_VOLTAGE, 0, 4))
|
||||||
|
|
||||||
|
# Outline
|
||||||
|
display.thickness(1)
|
||||||
|
display.pen(15)
|
||||||
|
display.rectangle(x, y, 19, 10)
|
||||||
|
|
||||||
|
# Terminal
|
||||||
|
display.rectangle(x + 19, y + 3, 2, 4)
|
||||||
|
display.pen(0)
|
||||||
|
display.rectangle(x + 1, y + 1, 17, 8)
|
||||||
|
if level < 1:
|
||||||
|
display.pen(0)
|
||||||
|
display.line(x + 3, y, x + 3 + 10, y + 10)
|
||||||
|
display.line(x + 3 + 1, y, x + 3 + 11, y + 10)
|
||||||
|
display.pen(15)
|
||||||
|
display.line(x + 2 + 2, y - 1, x + 4 + 12, y + 11)
|
||||||
|
display.line(x + 2 + 3, y - 1, x + 4 + 13, y + 11)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Battery Bars
|
||||||
|
display.pen(15)
|
||||||
|
for i in range(4):
|
||||||
|
if level / 4 > (1.0 * i) / 4:
|
||||||
|
display.rectangle(i * 4 + x + 2, y + 2, 3, 6)
|
||||||
|
|
||||||
|
def draw_window(display, x, y, width, height, title):
|
||||||
|
display.thickness(1)
|
||||||
|
|
||||||
|
# borders
|
||||||
|
display.pen(15)
|
||||||
|
display.rectangle(x, y, width, height)
|
||||||
|
|
||||||
|
display.pen(0)
|
||||||
|
display.line(x, y, x + width - 1, y)
|
||||||
|
display.line(x, y, x, y + height - 1)
|
||||||
|
display.line(x, y + height - 1, x + width - 1, y + height - 1)
|
||||||
|
display.line(x + width - 1, y, x + width - 1, y + height - 1)
|
||||||
|
|
||||||
|
# shadow
|
||||||
|
display.line(x, y + height, x + width + 1, y + height)
|
||||||
|
display.line(x + width, y, x + width, y + height + 1)
|
||||||
|
display.line(x + 1, y + height + 1, x + width + 1, y + height + 1)
|
||||||
|
display.line(x + width + 1, y + 1, x + width + 1, y + height + 1)
|
||||||
|
|
||||||
|
# title
|
||||||
|
display.line(x + 4, y + 3, x + width - 4, y + 3)
|
||||||
|
display.line(x + 4, y + 5, x + width - 4, y + 5)
|
||||||
|
display.line(x + 4, y + 7, x + width - 4, y + 7)
|
||||||
|
|
||||||
|
display.line(x, y + 11, x + width, y + 11)
|
||||||
|
display.line(x, y + 11, x + width, y + 11)
|
||||||
|
|
||||||
|
pprint(display, title, (x + x + width - plength(title)) // 2, y + 1, 0)
|
||||||
|
|
||||||
|
def wait_for_user_to_release_buttons(display):
|
||||||
|
pr = display.pressed
|
||||||
|
while pr(badger2040.BUTTON_A) or pr(badger2040.BUTTON_B) or pr(badger2040.BUTTON_C) or pr(badger2040.BUTTON_UP) or pr(badger2040.BUTTON_DOWN):
|
||||||
|
time.sleep(0.01)
|
||||||
|
|
||||||
|
def launch_app(display, file):
|
||||||
|
wait_for_user_to_release_buttons(display)
|
||||||
|
|
||||||
|
for k in locals().keys():
|
||||||
|
if k not in ("gc", "file", "badger_os"):
|
||||||
|
del locals()[k]
|
||||||
|
gc.collect()
|
||||||
|
badger_os.launch(file)
|
||||||
|
|
||||||
|
def button(display, pin):
|
||||||
|
if not display.pressed(badger2040.BUTTON_USER): # User button is NOT held down
|
||||||
|
if pin == badger2040.BUTTON_A:
|
||||||
|
launch_app(display, "_badge_app")
|
||||||
|
if pin == badger2040.BUTTON_B:
|
||||||
|
launch_app(display, "_qr_app")
|
||||||
|
if pin == badger2040.BUTTON_C:
|
||||||
|
launch_app(display, "_fortune_app")
|
||||||
|
|
||||||
|
def draw_ui(display, selected):
|
||||||
|
draw_border(display)
|
||||||
|
draw_menu(display, selected)
|
||||||
|
draw_background(display)
|
||||||
|
draw_battery(display, WIDTH - 28, 6)
|
||||||
Reference in New Issue
Block a user