diff --git a/micropython/examples/badger2040w/badges/badge.jpg b/micropython/examples/badger2040w/badges/badge.jpg new file mode 100644 index 00000000..287a43ca Binary files /dev/null and b/micropython/examples/badger2040w/badges/badge.jpg differ diff --git a/micropython/examples/badger2040w/badges/badge.txt b/micropython/examples/badger2040w/badges/badge.txt new file mode 100644 index 00000000..0f75daef --- /dev/null +++ b/micropython/examples/badger2040w/badges/badge.txt @@ -0,0 +1,6 @@ +mustelid inc +H. Badger +RP2040 +2MB Flash +E ink +296x128px \ No newline at end of file diff --git a/micropython/examples/badger2040w/examples/badge.py b/micropython/examples/badger2040w/examples/badge.py index e69de29b..86ccc3ac 100644 --- a/micropython/examples/badger2040w/examples/badge.py +++ b/micropython/examples/badger2040w/examples/badge.py @@ -0,0 +1,171 @@ +import time +import badger2040w +import badger_os +import jpegdec + +# Global Constants +WIDTH = badger2040w.WIDTH +HEIGHT = badger2040w.HEIGHT + +IMAGE_WIDTH = 104 + +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 + +BADGE_PATH = "/badges/badge.txt" + +DEFAULT_TEXT = """mustelid inc +H. Badger +RP2040 +2MB Flash +E ink +296x128px +/badges/badge.jpg +""" + +# ------------------------------ +# 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 the badge, including user text +def draw_badge(): + display.set_pen(0) + display.clear() + + # Draw badge image + jpeg.open_file(badge_image) + jpeg.decode(WIDTH - IMAGE_WIDTH, 0) + + # Draw a border around the image + display.set_pen(0) + 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.set_pen(15) + # display.rectangle(1, 1, TEXT_WIDTH, COMPANY_HEIGHT - 1) + + # Draw the company + display.set_pen(15) # Change this to 0 if a white background is used + display.set_font("serif") + display.text(company, LEFT_PADDING, (COMPANY_HEIGHT // 2) + 1, WIDTH, COMPANY_TEXT_SIZE) + + # Draw a white background behind the name + display.set_pen(15) + display.rectangle(1, COMPANY_HEIGHT + 1, TEXT_WIDTH, NAME_HEIGHT) + + # Draw the name, scaling it based on the available width + display.set_pen(0) + display.set_font("sans") + 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, WIDTH, name_size) + break + + # Draw a white backgrounds behind the details + display.set_pen(15) + 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.set_pen(0) + display.set_font("sans") + name_length = display.measure_text(detail1_title, DETAILS_TEXT_SIZE) + display.text(detail1_title, LEFT_PADDING, HEIGHT - ((DETAILS_HEIGHT * 3) // 2), WIDTH, DETAILS_TEXT_SIZE) + display.text(detail1_text, 5 + name_length + DETAIL_SPACING, HEIGHT - ((DETAILS_HEIGHT * 3) // 2), WIDTH, DETAILS_TEXT_SIZE) + + # Draw the second detail's title and text + name_length = display.measure_text(detail2_title, DETAILS_TEXT_SIZE) + display.text(detail2_title, LEFT_PADDING, HEIGHT - (DETAILS_HEIGHT // 2), WIDTH, DETAILS_TEXT_SIZE) + display.text(detail2_text, LEFT_PADDING + name_length + DETAIL_SPACING, HEIGHT - (DETAILS_HEIGHT // 2), WIDTH, DETAILS_TEXT_SIZE) + + +# ------------------------------ +# Program setup +# ------------------------------ + +# Create a new Badger and set it to update NORMAL +display = badger2040w.Badger2040W() +display.led(128) +display.set_update_speed(badger2040w.UPDATE_NORMAL) + +jpeg = jpegdec.JPEG(display.display) + +# Open the badge file +try: + badge = open(BADGE_PATH, "r") +except OSError: + with open(BADGE_PATH, "w") as f: + f.write(DEFAULT_TEXT) + f.flush() + badge = open(BADGE_PATH, "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" +badge_image = badge.readline() # /badges/badge.jpg + +# 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)) + + +# ------------------------------ +# Main program +# ------------------------------ + +draw_badge() + +while True: + if display.pressed(badger2040w.BUTTON_A) or display.pressed(badger2040w.BUTTON_B) or display.pressed(badger2040w.BUTTON_C) or display.pressed(badger2040w.BUTTON_UP) or display.pressed(badger2040w.BUTTON_DOWN): + badger_os.warning(display, "To change the text, connect Badger2040 to a PC, load up Thonny, and modify badge.txt") + time.sleep(4) + + draw_badge() + + 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() diff --git a/micropython/examples/badger2040w/examples/icon-net-info.jpg b/micropython/examples/badger2040w/examples/icon-net-info.jpg new file mode 100644 index 00000000..73bcd3e3 Binary files /dev/null and b/micropython/examples/badger2040w/examples/icon-net-info.jpg differ diff --git a/micropython/examples/badger2040w/examples/icon-news.jpg b/micropython/examples/badger2040w/examples/icon-news.jpg new file mode 100644 index 00000000..7c1b73cb Binary files /dev/null and b/micropython/examples/badger2040w/examples/icon-news.jpg differ diff --git a/micropython/examples/badger2040w/examples/info.py b/micropython/examples/badger2040w/examples/info.py index 7cfff345..a878edda 100644 --- a/micropython/examples/badger2040w/examples/info.py +++ b/micropython/examples/badger2040w/examples/info.py @@ -1,8 +1,8 @@ import badger2040w from badger2040w import WIDTH -TEXT_SIZE = 0.45 -LINE_HEIGHT = 16 +TEXT_SIZE = 1 +LINE_HEIGHT = 15 display = badger2040w.Badger2040W() display.led(128) @@ -18,24 +18,23 @@ display.set_pen(15) display.text("badgerOS", 3, 4, WIDTH, 1) display.text("info", WIDTH - display.measure_text("help", 0.4) - 4, 4, WIDTH, 1) -display.set_font("sans") display.set_pen(0) y = 16 + int(LINE_HEIGHT / 2) -display.text("Made by Pimoroni, powered by MicroPython", 0, y, WIDTH, TEXT_SIZE) +display.text("Made by Pimoroni, powered by MicroPython", 5, y, WIDTH, TEXT_SIZE) y += LINE_HEIGHT -display.text("Dual-core RP2040, 133MHz, 264KB RAM", 0, y, WIDTH, TEXT_SIZE) +display.text("Dual-core RP2040, 133MHz, 264KB RAM", 5, y, WIDTH, TEXT_SIZE) y += LINE_HEIGHT -display.text("2MB Flash (1MB OS, 1MB Storage)", 0, y, WIDTH, TEXT_SIZE) +display.text("2MB Flash (1MB OS, 1MB Storage)", 5, y, WIDTH, TEXT_SIZE) y += LINE_HEIGHT -display.text("296x128 pixel Black/White e-Ink", 0, y, WIDTH, TEXT_SIZE) +display.text("296x128 pixel Black/White e-Ink", 5, y, WIDTH, TEXT_SIZE) y += LINE_HEIGHT y += LINE_HEIGHT -display.text("For more info:", 0, y, WIDTH, TEXT_SIZE) +display.text("For more info:", 5, y, WIDTH, TEXT_SIZE) y += LINE_HEIGHT -display.text("https://pimoroni.com/badger2040w", 0, y, WIDTH, TEXT_SIZE) +display.text("https://pimoroni.com/badger2040w", 5, y, WIDTH, TEXT_SIZE) display.update() diff --git a/micropython/examples/badger2040w/examples/network_info.py b/micropython/examples/badger2040w/examples/net_info.py similarity index 100% rename from micropython/examples/badger2040w/examples/network_info.py rename to micropython/examples/badger2040w/examples/net_info.py diff --git a/micropython/examples/badger2040w/launcher.py b/micropython/examples/badger2040w/launcher.py index da3d16f2..87947f35 100644 --- a/micropython/examples/badger2040w/launcher.py +++ b/micropython/examples/badger2040w/launcher.py @@ -20,10 +20,6 @@ else: # Otherwise restore previously running app badger_os.state_launch() -# for e.g. 2xAAA batteries, try max 3.4 min 3.0 -MAX_BATTERY_VOLTAGE = 4.0 -MIN_BATTERY_VOLTAGE = 3.2 - display = badger2040.Badger2040W() display.set_font("bitmap8") display.led(128) @@ -51,29 +47,6 @@ 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(level, x, y): - # Outline - display.set_pen(15) - display.rectangle(x, y, 19, 10) - # Terminal - display.rectangle(x + 19, y + 3, 2, 4) - display.set_pen(0) - display.rectangle(x + 1, y + 1, 17, 8) - if level < 1: - display.set_pen(0) - display.line(x + 3, y, x + 3 + 10, y + 10) - display.line(x + 3 + 1, y, x + 3 + 11, y + 10) - display.set_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.set_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_disk_usage(x): _, f_used, _ = badger_os.get_disk_usage() @@ -114,7 +87,8 @@ def render(): for i in range(max_icons): x = centers[i] label = examples[i + (state["page"] * 3)] - icon = f"{APP_DIR}/icon-{label}.jpg" + icon_label = label.replace("_", "-") + icon = f"{APP_DIR}/icon-{icon_label}.jpg" label = label.replace("_", " ") jpeg.open_file(icon) jpeg.decode(x - 32, 24) @@ -134,9 +108,6 @@ def render(): display.set_pen(0) display.rectangle(0, 0, WIDTH, 16) draw_disk_usage(90) - vbat = badger_os.get_battery_level() - bat = int(map_value(vbat, MIN_BATTERY_VOLTAGE, MAX_BATTERY_VOLTAGE, 0, 4)) - draw_battery(bat, WIDTH - 22 - 3, 3) display.set_pen(15) display.text("badgerOS", 4, 4, WIDTH, 1.0) diff --git a/micropython/examples/badger2040w/lib/badger2040w.py b/micropython/examples/badger2040w/lib/badger2040w.py index ca5475b4..11e975f8 100644 --- a/micropython/examples/badger2040w/lib/badger2040w.py +++ b/micropython/examples/badger2040w/lib/badger2040w.py @@ -28,6 +28,9 @@ UPDATE_MEDIUM = 1 UPDATE_FAST = 2 UPDATE_TURBO = 3 +LED = 22 +ENABLE_3V3 = 10 + WIDTH = 296 HEIGHT = 128 @@ -69,26 +72,39 @@ def system_speed(speed): class Badger2040W(): def __init__(self): self.display = PicoGraphics(DISPLAY_INKY_PACK) + self._led = machine.PWM(machine.Pin(LED)) + self._led.freq(1000) + self._led.duty_u16(0) def __getattr__(self, item): # Glue to redirect calls to PicoGraphics return getattr(self.display, item) def led(self, brightness): - pass + brightness = max(0, min(255, brightness)) + self._led.duty_u16(int(brightness * 256)) def invert(self, invert): - pass + raise RuntimeError("Display invert not supported in PicoGraphics.") def thickness(self, thickness): - print("Thickness!") + raise RuntimeError("Thickness not supported in PicoGraphics.") def halt(self): - pass + enable = machine.Pin(ENABLE_3V3, machine.Pin.OUT) + enable.off() + while not self.pressed_any(): + pass def pressed(self, button): return BUTTONS[button].value() == 1 + def pressed_any(self): + for button in BUTTONS.values(): + if button.value(): + return True + return False + @micropython.native def icon(self, data, index, data_w, icon_size, x, y): s_x = (index * icon_size) % data_w diff --git a/micropython/examples/badger2040w/uf2-manifest.txt b/micropython/examples/badger2040w/uf2-manifest.txt index 3e0c198b..6325b35e 100644 --- a/micropython/examples/badger2040w/uf2-manifest.txt +++ b/micropython/examples/badger2040w/uf2-manifest.txt @@ -3,4 +3,6 @@ lib/*.py examples/*.jpg examples/*.py images/*.jpg -images/*.txt \ No newline at end of file +images/*.txt +badges/*.txt +badges/*.jpg \ No newline at end of file