Compare commits

9 Commits

18 changed files with 193 additions and 1348 deletions

View File

@@ -1,5 +1,7 @@
# Badger2040 System II # Badger2040 System II
> Forked from https://github.com/oneearedrabbit/badger-system-ii
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! 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/ https://kruzenshtern.org/the-e-ink-badge-the-coolest-badge-you-didnt-know-you-needed/

3
scripts/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
*.bin
*.png
*.jpeg

136
scripts/convert.py Normal file
View File

@@ -0,0 +1,136 @@
#!/usr/bin/env python3
"""
Converts images into a format suitable for display on Badger 2040.
Optionally resizes images to 296x128 to fit the display.
Crunches images down to dithered, 1bit colour depth.
Outputs either in raw binary format or as a .py file for embedding into MicroPython.
Output to py functionality is borrwed from data_to_py.py, Copyright (c) 2016 Peter Hinch
"""
import io
import argparse
from PIL import Image, ImageEnhance
from pathlib import Path
PY_HEADER = """# Code generated by convert.py.
"""
PY_FOOTER = """_mvdata = memoryview(_data)
def data():
return _mvdata
"""
parser = argparse.ArgumentParser(description='Converts images into the format used by Badger2040.')
parser.add_argument('file', nargs="+", help='input files to convert')
parser.add_argument('--out_dir', type=Path, default=None, help='output directory')
parser.add_argument('--binary', action="store_true", help='output binary file for MicroPython')
parser.add_argument('--py', action="store_true", help='output .py file for MicroPython embedding')
parser.add_argument('--resize', action="store_true", help='force images to 296x128 pixels')
options = parser.parse_args()
class ByteWriter(object):
bytes_per_line = 16
def __init__(self, stream, varname):
self.stream = stream
self.stream.write('{} =\\\n'.format(varname))
self.bytecount = 0 # For line breaks
def _eol(self):
self.stream.write("'\\\n")
def _eot(self):
self.stream.write("'\n")
def _bol(self):
self.stream.write("b'")
# Output a single byte
def obyte(self, data):
if not self.bytecount:
self._bol()
self.stream.write('\\x{:02x}'.format(data))
self.bytecount += 1
self.bytecount %= self.bytes_per_line
if not self.bytecount:
self._eol()
# Output from a sequence
def odata(self, bytelist):
for byt in bytelist:
self.obyte(byt)
# ensure a correct final line
def eot(self): # User force EOL if one hasn't occurred
if self.bytecount:
self._eot()
self.stream.write('\n')
def convert_image(img):
if options.resize:
img = img.resize((296, 128)) # resize
try:
enhancer = ImageEnhance.Contrast(img)
img = enhancer.enhance(2.0)
except ValueError:
pass
img = img.convert("1") # convert to black and white
return img
def write_stream(header, footer, ip_stream, op_stream):
op_stream.write(header)
op_stream.write('\n')
data = ip_stream.read()
bw_data = ByteWriter(op_stream, '_data')
bw_data.odata(data)
bw_data.eot()
op_stream.write(footer)
# create map of images based on input filenames
for input_filename in options.file:
with Image.open(input_filename) as img:
img = convert_image(img)
image_name = Path(input_filename).stem
w, h = img.size
output_data = [~b & 0xff for b in list(img.tobytes())]
if options.binary:
if options.out_dir is not None:
output_filename = (options.out_dir / image_name).with_suffix(".bin")
else:
output_filename = Path(input_filename).with_suffix(".bin")
print(f"Saving to {output_filename}, {w}x{h}")
with open(output_filename, "wb") as out:
out.write(bytearray(output_data))
elif options.py:
if options.out_dir is not None:
output_filename = (options.out_dir / image_name).with_suffix(".py")
else:
output_filename = Path(input_filename).with_suffix(".py")
print(f"Saving to {output_filename}, {w}x{h}")
with open(output_filename, "w") as out:
write_stream(PY_HEADER, PY_FOOTER, io.BytesIO(bytes(output_data)), out)
else:
image_code = '''\
static const uint8_t {image_name}[{count}] = {{
{byte_data}
}};
'''.format(image_name=image_name, count=len(output_data), byte_data=", ".join(str(b) for b in output_data))
print(image_code)

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -1,5 +1,5 @@
Kirill Timofeev Mariano Sciacco
Engineering Team IoT & Cloud Engineer
Census Vimar S.p.A.
oneearedrabbit git.marianosciacco.it
badge.bin badgem.bin

BIN
src/badges/badgem.bin Normal file

Binary file not shown.

BIN
src/badges/badgem.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -4,9 +4,9 @@ import badger_os
from widgets import draw_window, pprint, ptitle, plength, ppara, button, draw_ui from widgets import draw_window, pprint, ptitle, plength, ppara, button, draw_ui
from random import random from random import random
IMAGE_WIDTH = 96 # IMAGE_WIDTH = 96
IMAGE_HEIGHT = 96 # IMAGE_HEIGHT = 96
DELTA = 0 # DELTA = 0
# Check that the fortune directory exists, if not, make it # Check that the fortune directory exists, if not, make it
try: try:
@@ -25,8 +25,8 @@ state = {
"running": "badge_app", "running": "badge_app",
} }
IMAGE_WIDTH = 64 IMAGE_WIDTH = 29
IMAGE_HEIGHT = 64 IMAGE_HEIGHT = 32
def render(): def render():
display.pen(15) display.pen(15)
@@ -47,11 +47,11 @@ def draw_clippy():
y = 21 y = 21
width = 294 width = 294
height = 106 height = 106
draw_window(display, x, y, width, height, " Special ") draw_window(display, x, y, width, height, " Information ")
clippy_dat = bytearray(int(IMAGE_WIDTH * IMAGE_HEIGHT / 8)) # clippy_dat = bytearray(int(IMAGE_WIDTH * IMAGE_HEIGHT / 8))
open(f"images/clippy.bin", "rb").readinto(clippy_dat) # open(f"images/logo.bin", "rb").readinto(clippy_dat)
display.image(clippy_dat, IMAGE_WIDTH, IMAGE_HEIGHT, 212, 56) # display.image(clippy_dat, IMAGE_WIDTH, IMAGE_HEIGHT, 212, 56)
# scrollbars # scrollbars
display.pen(0) display.pen(0)
@@ -92,7 +92,7 @@ def draw_elements():
display.pen(15) display.pen(15)
display.clear() display.clear()
draw_ui(display, "Special") draw_ui(display, "About")
draw_clippy() draw_clippy()

BIN
src/images/loghetto.bin Normal file

Binary file not shown.

BIN
src/images/loghetto.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

BIN
src/images/logo.bin Normal file

Binary file not shown.

BIN
src/images/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 767 B

View File

@@ -34,19 +34,19 @@ def draw_about():
# logo # logo
image = bytearray(int(32 * 32 / 8)) image = bytearray(int(32 * 32 / 8))
open("images/{}".format("census.bin"), "r").readinto(image) open("images/{}".format("logo.bin"), "r").readinto(image)
display.image(image, 32, 32, 86, 56) display.image(image, 32, 32, 86, 56)
pprint(display, "Engineering", 125, 56, 0) pprint(display, "AWS Summit", 125, 56, 0)
pprint(display, "Offsite", 125, 66, 0) # pprint(display, "---", 125, 66, 0)
pprint(display, "Brooklyn", 125, 76, 0) pprint(display, "Milan (Italy)", 125, 66, 0)
pprint(display, "2022", 125, 86, 0) pprint(display, "2024", 125, 76, 0)
def render(): def render():
display.pen(15) display.pen(15)
display.clear() display.clear()
draw_ui(display, "About") draw_ui(display, "Event")
draw_about() draw_about()

View File

@@ -51,7 +51,7 @@ def draw_qr_code(ox, oy, size, code):
def draw_qr_file(n): def draw_qr_file(n):
draw_window(display, 6, 26, 282, 94, " About us ") draw_window(display, 6, 26, 282, 94, " About me ")
file = CODES[n] file = CODES[n]
codetext = open("qrcodes/{}".format(file), "r") codetext = open("qrcodes/{}".format(file), "r")

View File

@@ -1,8 +1,8 @@
https://getcensus.com/ https://marianosciacco.it/publications/qrfuzz-paper/
Census Mariano Sciacco
* the leading reverse ETL * IoT & Cloud Engineer
* no more CSV files * Vimar S.p.A.
* sync data in real-time * (AWS Summit 2024)
Scan this code to learn If You Are Scanning This,
more about Census. It Is Too Late!

View File

@@ -187,23 +187,28 @@ def draw_background(display):
# display.image(image, 296, 128, 0, 0) # display.image(image, 296, 128, 0, 0)
def draw_menu(display, selected): def draw_menu(display, selected):
menu = "Badge QR Special About" menu = "Badge QR About Event"
# logo # logo
display.pen(0) display.pen(0)
display.thickness(1) display.thickness(1)
x = 12 loghetto = bytearray(int(16 * 18 / 8))
y = 6 open("images/{}".format("loghetto.bin"), "r").readinto(loghetto)
display.line(x + 2, y, x + 8, y) display.image(loghetto, 16, 18, 10, 2)
display.line(x + 6, y + 1, x + 9, y + 1)
display.line(x + 1, y + 2, x + 10, y + 2) # old logo
display.line(x + 5, y + 3, x + 10, y + 3) # x = 12
display.line(x, y + 4, x + 10, y + 4) # y = 6
display.line(x + 5, y + 5, x + 10, y + 5) # display.line(x + 2, y, x + 8, y)
display.line(x + 1, y + 6, x + 10, y + 6) # display.line(x + 6, y + 1, x + 9, y + 1)
display.line(x + 6, y + 7, x + 9, y + 7) # display.line(x + 1, y + 2, x + 10, y + 2)
display.line(x + 2, y + 8, x + 8, y + 8) # 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 x = 40
pprint(display, menu, x, 6, 0) pprint(display, menu, x, 6, 0)
@@ -226,6 +231,7 @@ def draw_border(display):
display.line(1, 1, 1, 127) display.line(1, 1, 1, 127)
display.line(1, 127, 295, 127) display.line(1, 127, 295, 127)
display.line(295, 1, 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, 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((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((0x03, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0xff, 0xff)), 8, 8, 288, 120)